Commit Graph

157 Commits (83dcfeabf8d37e7ea1adfafcd782f1298a3ddbef)

Author SHA1 Message Date
Paul Mackerras 21ab36a0c0 Pre-decode instructions when writing them to icache
This splits out the decoding done in the decode0 step into a separate
predecoder, used when writing instructions into the icache.  The
icache now holds 36 bits per instruction rather than 32.  For valid
instructions, those 36 bits comprise the bottom 26 bits of the
instruction word, a 9-bit insn_code value (which uniquely identifies
the instruction), and a zero in the MSB.  For illegal instructions,
the MSB is one and the full instruction word is in the bottom 32 bits.
Having the full instruction word available for illegal instructions
means that it can be printed in the log when simulating, or in future
could be placed in the HEIR register.

If we don't have an FPU, then the floating-point instructions are
regarded as illegal.  In that case, the insn_code values would fit
into 8 bits, which could be used in future to reduce the size of
decode_rom from 512 to 256 entries.

Signed-off-by: Paul Mackerras <>
1 year ago
Paul Mackerras 26dc1e879c Eliminate use of primary opcode outside of decode1
This changes code that previously looked at the primary opcode (bits
26 to 31) of the instruction to use other methods, in places other
than in stage0 of decode1.

* Extend rc_t to have a new value, RCOE, indicating that the
  instruction has both Rc and OE bits.

* Decode2 now tells execute1 whether the instruction has a third
  operand, used for distinguishing between multiply and multiply-add

* The invert_a field of the decode ROM is overloaded for load/store
  instructions to indicate cache-inhibited loads and stores.

Signed-off-by: Paul Mackerras <>
1 year ago
Paul Mackerras c9aea45ffe decode1: Divide insn_code values into ranges to indicate register usage
This lets us compute r_out.reg_*_addr and r_out.read_2_enable values
without needing access to the primary opcode value.  We also have that
non-FP instructions are < 256.

Signed-off-by: Paul Mackerras <>
1 year ago
Paul Mackerras c3ee10f013 decode1: Split instruction decoding into two steps
This reduces the block RAM requirements for instruction decoding by
splitting it into two steps.  The first, in a new pipeline stage
called decode0 (implemented by code in decode1.vhdl) maps the
instruction to a 9-bit instruction code using major and row decode
ROMs.  The second maps the 9-bit code to the final decode_rom_t (about
44 bits wide).  Branch prediction done in decode is now done in
decode0 rather than decode1.

Signed-off-by: Paul Mackerras <>
1 year ago
Paul Mackerras 5380d80039 decode1: Use block RAMs in decode
This combines the various decode arrays in decode1 into two, one
indexed by the major opcode (bits 31--26 of the instruction) together
with bits 4--0 of the instruction, and the other indexed mostly by the
minor opcode (bits 10--1), with some swizzles to accommodate the
relevant parts of the minor opcode space for opcodes 19, 31, 59 and 63
within a 2k entry ROM (11 address bits).  These are called the "major"
and the "row" decode ROMs respectively.  (Bits 10--6 of the
instruction are called the "row index", and bits 5--1, or 5--0 for
some opcodes, are called the "column index", because of the way the
opcode maps in the ISA are laid out.)

Both ROMs are looked up each cycle and the result from one or other,
or from an override in ri.override_decode, are selected after a clock

This uses quite a lot of BRAM resources.  In future a predecode step
will reduce the BRAM usage substantially.

Signed-off-by: Paul Mackerras <>
1 year ago
Paul Mackerras 47895f8aff decode2: Decode unit and single-pipe attributes for mfspr/mtspr in decode2
Instead of doing that in decode1.  That lets us get rid of the
force_single and override_unit fields of reg_internal_t in decode1,
which will simplify following changes to decode1.

Signed-off-by: Paul Mackerras <>
1 year ago
Paul Mackerras 932da4c114 FPU: Simplify IDLE state code
Do more decoding of the instruction ahead of the IDLE state
processing so that the IDLE state code becomes much simpler.
To make the decoding easier, we now use four insn_type_t codes for
floating-point operations rather than two.  This also rearranges the
insn_type_t values a little to get the 4 FP opcode values to differ
only in the bottom 2 bits, and put OP_DIV, OP_DIVE and OP_MOD next to

Signed-off-by: Paul Mackerras <>
1 year ago
Paul Mackerras 7a60c118ed loadstore1: Simplify address generation in OP_FETCH_FAILED case
Instead of having a multiplexer in loadstore1 in order to be able to
put the instruction address into v.addr, we now set decode.input_reg_a
to CIA in the decode table entry for OP_FETCH_FAILED.  That means that
the operand selection machinery in decode2 will supply the instruction
address to loadstore1 on the lv.addr1 input and no special case is
needed in loadstore1.  This saves a few LUTs (~40 on the Artix-7).

Signed-off-by: Paul Mackerras <>
1 year ago
Michael Neuling 602ba25c70 Metavalue cleanup for decoder1.vhdl
Signed-off-by: Michael Neuling <>
1 year ago
Michael Neuling caf458be37 Metavalue cleanup for common.vhdl
This affects other files which have been included here.

Signed-off-by: Michael Neuling <>
1 year ago
Paul Mackerras d6121cd636 Use register addresses from decode1 for dependency tracking
This improves timing a little because the register addresses now come
directly from a latch instead of being calculated by
decode_input_reg_*.  The asserts that check that the two are the same
are now in decode2 rather than register_file.

Signed-off-by: Paul Mackerras <>
1 year ago
Paul Mackerras 1d7de2f1da register_file: Make read access to register file synchronous
With this, the register RAM is read synchronously using the addresses
supplied by decode1.  That means the register RAM can now be block RAM
rather than LUT RAM.

Debug accesses are done via the B port on cycles when decode1
indicates that there is no valid instruction or the instruction
doesn't use a [F]RB operand.

We latch the addresses being read in each cycle and use the same
address next cycle if stalled.  Data that is being written is latched
and a multiplexer on each read port then supplies the latched write
data if the read address for that port equals the write address.

Signed-off-by: Paul Mackerras <>
1 year ago
Paul Mackerras 06c13d4988 decode1: Work out register addresses in decode1
This adds some relatively simple logic to decode1 to compute the
GPR/FPR addresses that an instruction will access.  It always computes
three addresses regardless of whether the instruction will actually
use all of them.  The main things it computes are whether the
instruction uses the RS field or the RC field for the 3rd operand, and
whether the operands are FPRs or GPRs (it is possible for RS to be an
FPR but RA and RB to be GPRs, as for example with stfdx).

At the moment all we do with these computed register addresses is to
assert that they are identical to the ones coming from decode2 one
cycle later.

Signed-off-by: Paul Mackerras <>
1 year ago
Paul Mackerras 047be5c0c3 loadstore1: Do SPR reading in stage 2 rather than stage 3
This eliminates one leg of the output value multiplexer, and seems
to improve timing slightly on the A7-100.

Since SPR values are written in stage 3 and read in stage 2, an mfspr
immediately following an mtspr to the same SPR won't give the correct
value.  To avoid this, we make mtspr to the load/store SPRs single
issue in decode1.

Signed-off-by: Paul Mackerras <>
1 year ago
Paul Mackerras fdb3ef6874 Finish off taking SPRs out of register file
With this, the register file now contains 64 entries, for 32 GPRs and
32 FPRs, rather than the 128 it had previously.  Several things get
simplified - decode1 no longer has to work out the ispr{1,2,o} values,
decode_input_reg_{a,b,c} no longer have the t = SPR case, etc.

Signed-off-by: Paul Mackerras <>
1 year ago
Paul Mackerras 337b104250 Move LR, CTR and TAR out of the register file
By putting CTR on the odd side and LR and TAR on the even side, we can
read and write CTR for bdnz-style instructions in parallel with
reading LR or TAR for indirect branches and writing LR for branches
with LK=1.  Thus we don't need to double up any of these instructions,
giving a simplification in decode2.

We now have logic for printing LR and CTR at the end of a simulation
in execute1, in addition to the similar logic in register_file and

Signed-off-by: Paul Mackerras <>
1 year ago
Paul Mackerras bc4d02cb0d Start removing SPRs from register file
This starts the process of removing SPRs from the register file by
moving SRR0/1, SPRG0-3, HSRR0/1 and HSPRG0/1 out of the register file
and putting them into execute1.  They are stored in a pair of small
RAM arrays, referred to as "even" and "odd".  The reason for having
two arrays is so that two values can be read and written in each
cycle.  For example, SRR0 and SRR1 can be written in parallel by an
interrupt and read in parallel by the rfid instruction.

The addresses in the RAM which will be accessed are determined in the
decode2 stage.  We have one write address for both sides, but two read
addresses, since in future we will want to be able to read CTR at the
same time as either LR or TAR.

We now have a connection from writeback to execute1 which carries the
partial SRR1 value for an interrupt.  SRR0 comes from the execute
pipeline; we no longer need to carry instruction addresses along the
LSU and FPU pipelines.  Since SRR0 and SRR1 can be written in the same
cycle now, we don't need the little state machine in writeback any

Signed-off-by: Paul Mackerras <>
1 year ago
Paul Mackerras 73cc5167ec Use FPU for division instructions if we have an FPU
- Arrange for XER to be written for OE=1 forms
- Arrange for condition codes to be set for RC=1 forms
  (including correct handling for 32-bit mode)
- Don't instantiate the divider if we have an FPU.

Signed-off-by: Paul Mackerras <>
1 year ago
Paul Mackerras 2da08bcf2e decode1: Remove stash buffer
Now that the timing of the busy signal from decode2 doesn't depend on
register numbers or downstream instruction completion, we no longer
need the stash buffer on the output of decode1.

Signed-off-by: Paul Mackerras <>
1 year ago
Paul Mackerras c9e838b656 Remove support for lq, stq, lqarx and stqcx.
They are optional in SFFS (scalar fixed-point and floating-point
subset), are not needed for running Linux, and add complexity, so
remove them.

Signed-off-by: Paul Mackerras <>
1 year ago
Paul Mackerras ebe1caab85 decode1: Reduce number of single-issue instructions
This reduces the set of instructions marked as single-issue to just
attn and mtspr to "slow" SPRs (those that are not stored in the
register file).

The instructions that were previously single-issue are: isync, dcbf,
dcbst, dcbt, dcbtst, eieio, icbi, mfmsr, mtmsr, mtmsrd, mfspr to slow
SPRS, sync, tlbsync and wait.  The synchronization instructions are
mostly no-ops anyway due to the in-order nature of the core, and the
cache-management instructions are unimplemented (except for icbi).
The MSR ops don't need to be single-issue due to the in-order core and
the fact that MSR updates are effective on the following instruction.

Signed-off-by: Paul Mackerras <>
1 year ago
Paul Mackerras 813e2317bf execute1: Restructure to separate out execution of side effects
We now have a record that represents the actions taken in executing an
instruction, and a process that computes that for the incoming
instruction.  We no longer have 'current' or 'r.cur_instr', instead
things like the destination register are put into r.e in the first
cycle of an instruction and not reinitialized in subsequent busy

For mfspr and mtspr, we now decode "slow" SPR numbers (those SPRs that
are not stored in the register file) to a new "spr_selector" record
in decode1 (excluding those in the loadstore unit).  With this, the
result for mfspr is determined in the data path.

Signed-off-by: Paul Mackerras <>
1 year ago
Paul Mackerras 83dea94793 decode1: Conditional trap instructions don't need to be single-issue
They can generate interrupts, but that doesn't mean they have to

Signed-off-by: Paul Mackerras <>
2 years ago
Michael Neuling 2224b28c2c
Merge pull request #324 from paulusmack/master
Performance and timing improvements
2 years ago
Paul Mackerras 54b0e8b8c8 core: Predict not-taken conditional branches using BTC
This adds a bit to the BTC to store whether the corresponding branch
instruction was taken last time it was encountered.  That lets us pass
a not-taken prediction down to decode1, which for backwards direct
branches inhibits it from redirecting fetch to the target of the
branch.  This increases coremark by about 2%.

Signed-off-by: Paul Mackerras <>
2 years ago
Paul Mackerras d4cfdb1bfe decode1: Fix form of isel marked as single-issue
The row in the decode table for isel with BC=0 was inadvertently left
marked as single-issue by commit 813f834012 ("Add CR hazard
detection", 2019-10-15).  Fix it.

Signed-off-by: Paul Mackerras <>
2 years ago
Paul Mackerras 06e07c69a8 decode1: Fix maddld and maddhdu to not set CR0
Signed-off-by: Paul Mackerras <>
2 years ago
Paul Mackerras a68921edca core: Fix mcrxrx, addpcis and bpermd
- mcrxrx put the bits in the wrong order

- addpcis was setting CR0 if the instruction bit 0 = 1, which it

- bpermd was producing 0 always and additionally had the wrong bit

Signed-off-by: Paul Mackerras <>
2 years ago
Paul Mackerras 18120f153d MMU: Implement a vestigial partition table
This implements a 1-entry partition table, so that instead of getting
the process table base address from the PRTBL SPR, the MMU now reads
the doubleword pointed to by the PTCR register plus 8 to get the
process table base address.  The partition table entry is cached.

Having the PTCR and the vestigial partition table reduces the amount
of software change required in Linux for Microwatt support.

Signed-off-by: Paul Mackerras <>
3 years ago
Paul Mackerras ae2afeca5c core: Track CR hazards and bypasses using tags
Signed-off-by: Paul Mackerras <>
3 years ago
Paul Mackerras a1d7b54f76 core: Crack branches that update both CTR and LR
This uses the instruction doubling machinery to convert conditional
branch instructions that update both CTR and LR (e.g., bdnzl, bdnzlrl)
into two instructions, of which the first updates CTR and determines
whether the branch is taken, and the second updates LR and does the
redirect if necessary.

Signed-off-by: Paul Mackerras <>
3 years ago
Paul Mackerras 4c61a71a62 core: Crack update-form loads into two internal ops
This uses the instruction-doubling machinery to send load with update
instructions down to loadstore1 as two separate ops, rather than
one op with two destinations.  This will help to simplify the value
tracking mechanisms.

Signed-off-by: Paul Mackerras <>
3 years ago
Paul Mackerras 0fb207be60 fetch1: Implement a simple branch target cache
This implements a cache in fetch1, where each entry stores the address
of a simple branch instruction (b or bc) and the target of the branch.
When fetching sequentially, if the address being fetched matches the
cache entry, then fetching will be redirected to the branch target.
The cache has 1024 entries and is direct-mapped, i.e. indexed by bits
11..2 of the NIA.

The bus from execute1 now carries information about taken and
not-taken simple branches, which fetch1 uses to update the cache.
The cache entry is updated for both taken and not-taken branches, with
the valid bit being set if the branch was taken and cleared if the
branch was not taken.

If fetching is redirected to the branch target then that goes down the
pipe as a predicted-taken branch, and decode1 does not do any static
branch prediction.  If fetching is not redirected, then the next
instruction goes down the pipe as normal and decode1 does its static
branch prediction.

In order to make timing, the lookup of the cache is pipelined, so on
each cycle the cache entry for the current NIA + 8 is read.  This
means that after a redirect (from decode1 or execute1), only the third
and subsequent sequentially-fetched instructions will be able to be

This improves the coremark value on the Arty A7-100 from about 180 to
about 190 (more than 5%).

The BTC is optional.  Builds for the Artix 7 35-T part have it off by
default because the extra ~1420 LUTs it takes mean that the design
doesn't fit on the Arty A7-35 board.

Signed-off-by: Paul Mackerras <>
3 years ago
Paul Mackerras cb1e3f6d70 decode1: Take an extra cycle for predicted branch redirects
This does the addition of NIA plus the branch offset from the
instruction after a clock edge, in order to ease timing, as the path
from the icache RAM through the adder in decode1 to the NIA register
in fetch1 was showing up as a critical path.

This adds one extra cycle of latency when redirecting fetch because of
a predicted-taken branch.

Signed-off-by: Paul Mackerras <>
3 years ago
Paul Mackerras c0f282b691 decode1: Implement tlbsync as a no-op
Signed-off-by: Paul Mackerras <>
3 years ago
Paul Mackerras d6134babc0 decode1: Implement obsolete dst, dstst, dss instructions as no-ops
Signed-off-by: Paul Mackerras <>
3 years ago
Paul Mackerras 89a67a18d0 decode: Add a facility field to the instruction decode tables
This makes it simpler to work out when to deliver a FPU unavailable
interrupt.  This also means we can get rid of the OP_FPLOAD and
OP_FPSTORE insn_type values.

Signed-off-by: Paul Mackerras <>
3 years ago
Paul Mackerras 4b2c23703c core: Implement quadword loads and stores
This implements the lq, stq, lqarx and stqcx. instructions.

These instructions all access two consecutive GPRs; for example the
"lq %r6,0(%r3)" instruction will load the doubleword at the address
in R3 into R7 and the doubleword at address R3 + 8 into R6.  To cope
with having two GPR sources or destinations, the instruction gets
repeated at the decode2 stage, that is, for each lq/stq/lqarx/stqcx.
coming in from decode1, two instructions get sent out to execute1.

For these instructions, the RS or RT register gets modified on one
of the iterations by setting the LSB of the register number.  In LE
mode, the first iteration uses RS|1 or RT|1 and the second iteration
uses RS or RT.  In BE mode, this is done the other way around.  In
order for decode2 to know what endianness is currently in use, we
pass the big_endian flag down from icache through decode1 to decode2.
This is always in sync with what execute1 is using because only rfid
or an interrupt can change MSR[LE], and those operations all cause
a flush and redirect.

There is now an extra column in the decode tables in decode1 to
indicate whether the instruction needs to be repeated.  Decode1 also
enforces the rule that lq with RT = RT and lqarx with RA = RT or
RB = RT are illegal.

Decode2 now passes a 'repeat' flag and a 'second' flag to execute1,
and execute1 passes them on to loadstore1.  The 'repeat' flag is set
for both iterations of a repeated instruction, and 'second' is set
on the second iteration.  Execute1 does not take asynchronous or
trace interrupts on the second iteration of a repeated instruction.

Loadstore1 uses 'next_addr' for the second iteration of a repeated
load/store so that we access the second doubleword of the memory
operand.  Thus loadstore1 accesses the doublewords in increasing
memory order.  For 16-byte loads this means that the first iteration
writes GPR RT|1.  It is possible that RA = RT|1 (this is a legal
but non-preferred form), meaning that if the memory operand was
misaligned, the first iteration would overwrite RA but then the
second iteration might take a page fault, leading to corrupted state.
To avoid that possibility, 16-byte loads in LE mode take an
alignment interrupt if the operand is not 16-byte aligned.  (This
is the case anyway for lqarx, and we enforce it for lq as well.)

Signed-off-by: Paul Mackerras <>
3 years ago
Paul Mackerras 55f7d99376 decode1: Fix decoding of recommended NOP instruction
We were decoding nop with the wrong major opcode.  Fix it.

Signed-off-by: Paul Mackerras <>
3 years ago
Paul Mackerras 1037c6aa2e core: Implement mtmsr instruction
This is like mtmsrd except it only alters the lower 32 bits of the MSR.

Signed-off-by: Paul Mackerras <>
3 years ago
Paul Mackerras dc1544db69 FPU: Implement floating multiply-add instructions
This implements fmadd, fmsub, fnmadd, fnmsub and their
single-precision counterparts.  The single-precision versions operate
the same as the double-precision versions until the final rounding and
overflow/underflow steps.

This adds an S register to store the low bits of the product.  S
shifts into R on left shifts, and can be negated, but doesn't do any
other arithmetic.

This adds a test for the double-precision versions of these

Signed-off-by: Paul Mackerras <>
3 years ago
Paul Mackerras c083b9507d FPU: Implement ftdiv and ftsqrt
Signed-off-by: Paul Mackerras <>
3 years ago
Paul Mackerras c350bc1f25 FPU: Implement fsqrt[s] and add a test for fsqrt
This implements the floating square-root calculation using a table
lookup of the inverse square root approximation, followed by three
iterations of Goldschmidt's algorithm, which gives estimates of both
sqrt(FRB) and 1/sqrt(FRB).  Then the residual is calculated as
FRB - R * R and that is multiplied by the 1/sqrt(FRB) estimate to get
an adjustment to R.  The residual and the adjustment can be negative,
and since we have an unsigned multiplier, the upper bits can be wrong.
In practice the adjustment fits into an 8-bit signed value, and the
bottom 8 bits of the adjustment product are correct, so we sign-extend
them, divide by 4 (because R is in 10.54 format) and add them to R.

Finally the residual is calculated again and compared to 2*R+1 to see
if a final increment is needed.  Then the result is rounded and
written back.

This implements fsqrts as fsqrt, but with rounding to single precision
and underflow/overflow calculation using the single-precision exponent
range.  This could be optimized later.

Signed-off-by: Paul Mackerras <>
3 years ago
Paul Mackerras 394f993e75 FPU: Implement frsqrte[s] and a test for frsqrte
This implements frsqrte by table lookup.  We first normalize the input
if necessary and adjust so that the exponent is even, giving us a
mantissa value in the range [1.0, 4.0), which is then used to look up
an entry in a 768-entry table.  The 768 entries are appended to the
table for reciprocal estimates, giving a table of 1024 entries in
total.  frsqrtes is implemented identically to frsqrte.

The estimate supplied is accurate to 1 part in 1024 or better.

Signed-off-by: Paul Mackerras <>
3 years ago
Paul Mackerras 49f3d1e77a FPU: Implement fcmpu and fcmpo
Signed-off-by: Paul Mackerras <>
3 years ago
Paul Mackerras 4cd9301da6 FPU: Implement fsel
Signed-off-by: Paul Mackerras <>
3 years ago
Paul Mackerras 4ad5ab9203 FPU: Implement fre[s]
This just returns the value from the inverse lookup table.  The result
is accurate to better than one part in 512 (the architecture requires

This also adds a simple test, which relies on the particular values in
the inverse lookup table, so it is not a general test.

Signed-off-by: Paul Mackerras <>
3 years ago
Paul Mackerras 9cce936251 FPU: Implement fdiv[s]
This implements floating-point division A/B by a process that starts
with normalizing both inputs if necessary.  Then an estimate of 1/B
from a lookup table is refined by 3 Newton-Raphson iterations and then
multiplied by A to get a quotient.  The remainder is calculated as
A - R * B (where R is the result, i.e. the quotient) and the remainder
is compared to 0 and to B to see whether the quotient needs to be
incremented by 1.  The calculations of 1 / B are done with 56 fraction
bits and intermediate results are truncated rather than rounded,
meaning that the final estimate of 1 / B is always correct or a little
bit low, never too high, and thus the calculated quotient is correct
or 1 unit too low.  Doing the estimate of 1 / B with sufficient
precision that the quotient is always correct to the last bit without
needing any adjustment would require many more bits of precision.

This implements fdivs by computing a double-precision quotient and
then rounding it to single precision.  It would be possible to
optimize this by e.g. doing only 2 iterations of Newton-Raphson and
then doing the remainder calculation and adjustment at single
precision rather than double precision.

Signed-off-by: Paul Mackerras <>
3 years ago
Paul Mackerras e6a5f237bc FPU: Implement fmul[s]
This implements the fmul and fmuls instructions.

For fmul[s] with denormalized operands we normalize the inputs
before doing the multiplication, to eliminate the need for doing
count-leading-zeroes on P.  This adds 3 or 5 cycles to the
execution time when one or both operands are denormalized.

Signed-off-by: Paul Mackerras <>
3 years ago
Paul Mackerras 86b826cd7e FPU: Implement fadd[s] and fsub[s] and add tests for them
Signed-off-by: Paul Mackerras <>
3 years ago