Commit Graph

70 Commits (7e544c1fb8c2ad742f6c71b13f80d9eab97c3fff)

Author SHA1 Message Date
Paul Mackerras 3268ef717c FPU: Make opsel_a a function of just the state
This adds some extra states and transitions so that opsel_a becomes
a function only of the current state.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
4 weeks ago
Paul Mackerras 73505b1626 FPU: Provide a separate path for transferring A/B/C to R
The timing path from r.a.class to result showed up as a critical path
on the Artix-7, apparently because of transfers of A, B or C to R in
special cases (e.g. NaN inputs) and the fsel instruction.  To
alleviate this, we provide a path via the miscellaneous value
multiplexer from A, B and C to R, selected via opsel_R = RES_MISC and
misc_sel = 111.  A new selector opsel_sel selects which of A, B or C
to transfer, using the same encoding as opsel_a.  This new selector is
now also used for the result class when rcls_op = RCLS_SEL and for the
result sign when rsgn_op = RSGN_SEL.  This reduces the number of
things that opsel_a depends on and eases timing in the main adder
path.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
4 weeks ago
Paul Mackerras b63773f6e9 FPU: Move computation of main adder inputs out of the state machine
Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
4 weeks ago
Paul Mackerras b4aae8511d FPU: Move special case handling to a separate process
This creates a new fpu_specialcases process that handles most of the
logic that was previously in the DO_NAN_INF and DO_ZERO_DEN states.
What remains of those states, i.e. the handling of denormalized
inputs, is in a new DO_SPECIAL state.  The state machine goes into
DO_SPECIAL state after IDLE for any arithmetic operation where an
input is a NaN, infinity, zero or denormalized value.  Doing this
means that the rest of the state machine won't try to start any
computation which would need to be overridden by the logic to produce
the result value selected by the fpu_specialcases process.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
4 weeks ago
Paul Mackerras b1bd2aa865 FPU: Make set_r independent of multiply_to_f.valid
Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
4 weeks ago
Paul Mackerras fcfdbc449c FPU: Move condition register calculations to an explicit data path
Instead of calculating v.cr_result in the state machine, we now have
the state machine set a 'cr_op' variable which then controls what
computation the CR data path does to set v.cr_result.  The CR data
path also handles updating the XERC result bits for integer operations
(division and modulus).

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
4 weeks ago
Paul Mackerras bbc485f336 FPU: Rework inputs to the main adder
With this, the A input no longer has R as an option but now takes the
rounding constants and the low-order bits of P (used as an adjustment
in the square root algorithm).  The B input has either R or zero.
Both inputs can be optionally inverted for subtraction.  The select
inputs to the multiplexers now have 3 bits in opsel_a and 1 bit in
opsel_b.

The states which need R to be set now explicitly have set_r := 1 even
though that is the default, essentially for documentation reasons.
Similarly some states set opsel_b <= BIN_R even though that is the
default.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
4 weeks ago
Paul Mackerras 0e7c11a0e4 FPU: Move result_class logic outside of state machine
The various states choose one of four operations (including no-op) to
be done on result_class.  Some operations have side-effects on
arith_done or FPSCR.  The DO_NAN_INF and DO_ZERO_DEN states still set
result_class directly since their logic is expected to move out to a
separate process later.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
4 weeks ago
Paul Mackerras 5f0b2d433d FPU: Simplify calculation of result_class
For the various arithmetic operators, we only get to the DO_* states
when the inputs are finite (not zero, infinity or NaN), so we can
replace setting of v.result_class to r.a.class or r.b.class with a
overall setting of it to FINITE in cycle 1 of all those operations.

Also, integer division doesn't need to set the result class since the
result is integer.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
4 weeks ago
Paul Mackerras 70819c4c39 FPU: Do renormalization from DO_ZERO_DEN state
Instead of having the various DO_* states (DO_FMUL, DO_FDIV, etc.)
handle checking for denormalized inputs, we now have DO_ZERO_DEN state
check for denormalized inputs and branch to RENORM_{A,B,C} to handle
them.

This also meant some changes were needed in how fsqrt and frsqrte
handled inputs with odd exponent.  The DO_FSQRT and DO_FRSQRTE states
were very similar and have been combined into one.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
4 weeks ago
Paul Mackerras 8648ddb64f FPU: Eliminate EXC_RESULT state
This lets us remove r.opsel_a and is a step towards moving the
handling of exceptional cases out to a separate process.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
4 weeks ago
Paul Mackerras 850b87c83f FPU: Get rid of r.madd_cmp and r.exp_cmp
This saves a few LUTs and simplifies the code a little.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
4 weeks ago
Paul Mackerras ba2add029a FPU: Remove need to set opsel_a one cycle ahead
Most states set opsel_a directly to select the operand for the A input
of the main adder.  The exception is the EXC_RESULT state, which uses
r.opsel_a set by the previous cycle to indicate which input operand to
use as the result.

In order to make timing, ensure that the controls that select the
inputs to the main adder (opsel_*, etc.) don't depend on any
complicated functions of the data (such as px_nz, pcmpb_eq, pcmpb_lt,
etc.), but are as far as possible constant for each state.  There is
now a control called set_r for whether the result is written to r.r,
which enables us to avoid setting opsel_b or opsel_r conditionally in
some cases.

Also, to avoid a data-dependent setting of msel_2 in IDIV_DODIV state,
the IDIV_NR1 and IDIV_NR2 states have been reworked so that completion
of the required number of iterations is checked in IDIV_NR1 state, and
at that point, if the inverse estimate is < 0.5, we go to IDIV_USE0_5
state in order to use 0.5 as the estimate.  This means that in the
normal case, the inverse estimate is already in Y when we get to
IDIV_DODIV state.  IDIV_USE0_5 has been reworked to put R (which will
contain 0.5) into Y as the inverse estimate.  That means that
IDIV_DODIV state doesn't have any data-dependent logic to put either P
or R into Y.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
4 weeks ago
Paul Mackerras 2731384a4b FPU: Reduce misc_sel to 3 bits
Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
4 weeks ago
Paul Mackerras cf866ce910 FPU: Simplify logic for setting r.x
Since r.x is mostly set from the value in r.r and only once from
anything else (r.b.mantissa), move the check to before the input
multiplexer for the main adder, so it works on r.r rather than
whatever is selected by r.opsel_a.

For the case in DO_FRSP where we have B selected by r.opsel_a, we add
a new state so that we now get B into R and then check the low bits of
R.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
4 weeks ago
Paul Mackerras 4e5f856c55 FPU: Factor out some of the common elements of the DO_* states
Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
4 weeks ago
Paul Mackerras 2422585e14 FPU: Reduce use of r.insn inside the state machine
Instead use things derived from the instruction in the first cycle,
such as r.is_multiply, r.is_addition, etc.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
4 weeks ago
Paul Mackerras 7812a55b6c FPU: Reorganize NaN and infinity handling and improve arch compliance
The architecture specifies that an invalid operation exception for
signalling NaN (VXSNAN) can occur in the same instructions as an
invalid operation exception for infinity times zero (VXIMZ) in the
case of a multiply-add instruction where B is a signalling NaN, and
one of A and C is infinity and the other is zero.  This moves the
invalid operation tests around so as to handle this case correctly.
It also restructures the infinity and NaN cases to simplify the logic
a little.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
4 weeks ago
Paul Mackerras a3613d863b FPU: Simplify sign calculation in FP multiply-add instructions
By starting out with result_sign = +/- sign of B, we avoid the need to
flip the result sign in a few places.

This also simplifies DO_FMADD state a bit by having DO_ZERO_DEN go to
DO_FMUL state for floating multiply-add where B is zero.  (The
RENORM_A2 and RENORM_C2 states already do this.)

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
4 weeks ago
Paul Mackerras 707dd619a0 FPU: Move NaN/infinity and zero/denorm handling out to separate states
This should simplify the DO_* states and hopefully be simpler overall.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
4 weeks ago
Paul Mackerras 27b3e42353 FPU: Move result_sign computations from state machine to a data path
Instead of operating on result_sign directly, the state machine now
sets a control variable "rsgn_op" that then directs a tiny ALU to do
what's required.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
4 weeks ago
Paul Mackerras 71b7df679b FPU: Calculate quieten_nan in first cycle
Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
4 weeks ago
Paul Mackerras 955fa561fb FPU: Move most result_sign computation out of state machine
This moves the computation of r.result_sign out of the various
states for most instructions.  Now the sign is mostly computed in the
first cycle (when e_in.valid is true).

The set of operations done on r.result_sign in the state machine are
now restricted to 5 (other than no change): invert, xor with
r.is_subtract, or set to the sign of A, B or C.

Similarly r.is_subtract and r.negate are computed in the first cycle
now.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
4 weeks ago
Paul Mackerras f4d28d1521 FPU: Fix ftdiv and ftsqrt instructions
With ftdiv, we weren't setting result_exp to B.exponent before
testing result_exp in state FTDIV_1; the fix is to transfer B.exponent
to result_exp in state DO_FTDIV.

With ftsqrt, we were setting bit 1 of the destination CR field to 0
always, due to a typo.

Also move a couple of statements around to try to get slightly simpler
logic.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
1 year ago
Paul Mackerras 95595af08d FPU: Fix typo in expression for exp_huge
Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
1 year ago
Paul Mackerras 18911455c6
FPU: Fix fsel instruction to not alter FPSCR (#426)
The fsel instruction is not supposed to alter FPSCR, but it was
clearing FR and FI.  Fix this.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
1 year ago
Paul Mackerras 51954671f3 FPU: Fix behaviour of fdiv with denormalized divisor
Renormalization of the divisor for fdiv[s] was adjusting the result
exponent in the wrong direction, making the result smaller in
magnitude than it should be by a power of 2.  Fix this by negating
r.shift in the RENORM_B2 state and then subtracting it in the LOOKUP
cycle.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
1 year ago
Paul Mackerras eecf1ca399 FPU: Fix setting of FPRF
The sign recorded in FPRF was sometimes wrong because we weren't doing
the modifications that were done in pack_dp when setting FPRF (FPSCR
field).  These modifications are: set sign for zero result of
subtraction based on rounding mode; negate result for fnmadd/sub;
but don't modify sign of NaNs.

Instead we now do these modifications in the main state machine code
and put the result in an 'rsign' variable that is used to set
v.res_sign, then r.res_sign is used in the next cycle both for setting
FPRF and in the pack_dp functions.  That simplifies pack_dp and lets
us get rid of r.res_negate, r.res_subtract and r.res_rmode.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
1 year ago
Paul Mackerras e02d8060ed Change the multiplier interface to support signed multipliers
This adds an 'is_signed' signal to MultiplyInputType to indicate
whether the data1 and data2 fields are to be interpreted as signed or
unsigned numbers.

The 'not_result' field is replaced by a 'subtract' field which
provides a more intuitive interface for requesting that the product be
subtracted from the addend rather than added, i.e. subtract = 1 gives
C - A * B, vs. subtract = 0 giving C + A * B.  (Previously the users
of the multipliers got the same effect by complementing the addend and
setting not_result = 1.)

The is_32bit field is removed because it is no longer used now that we
have a separate 32-bit multiplier.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
3 years ago
Paul Mackerras 09965b9102 FPU: Set sign of 0 result of subtraction in pack_dp
When a floating-point subtraction results in a zero result, the sign
of the result is required to be positive in all rounding modes except
the round to minus infinity mode, when it is negative.  Consolidate
the logic for doing this in one place, in the pack_dp function,
instead of having it at each place where a zero result is generated.

Since fnmadd[s] and fnmsub[s] negate the result after this rule has
been applied, we use the r.negate signal to indicate a negation which
is now done in pack_dp.  Thus the EXC_RESULT state no longer uses
r.negate, and in fact doesn't set v.result_sign at all; that is now
done in the states that lead into EXC_RESULT.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
3 years 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
them.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
3 years ago
Paul Mackerras 8da05e5331 FPU: Make an explicit exponent data path
With this, the large case statement sets values for a set of control
signals, which then control multiplexers and adders that generate
values for v.result_exp and v.shift.  The plan is for the case
statement to turn into a microcode ROM eventually.

The value of v.result_exp is the sum of two values, either of which
can be negated (but not both).  The first value can be chosen from the
result exponent, A exponent, B exponent arithmetically shifted right
one bit, or 0.  The second value can be chosen from new_exp (which is
r.result_exp - r.shift), B exponent, C exponent or a constant.  The
choices for the constant are 0, 56, the maximum exponent (max_exp) or
the exponent bias for trap-enabled overflow conditions (bias_exp).
These choices are controlled by the signals re_sel1, re_neg1, re_sel2
and re_neg2, and the sum is written into v.result_exp if re_set_result
is 1.

For v.shift we also compute the sum of two values, either of which
can be negated (but not both).  The first value can be chosen from
new_exp, B exponent, r.shift, or 0.  The second value can be chosen
from the A exponent or a constant.  The possible constants are 0, 1,
4, 8, 32, 52, 56, 63, 64, or the minimum exponent (min_exp).  These
choices are controlled by the signals rs_sel1, rs_neg1, rs_sel2 and
rs_neg2.  After the adder there is a multiplexer which selects either
the sum or a shift count for normalization (derived from a count
leading zeroes operation on R) to be written into v.shift.  The
count-leading-zeroes result does not go through the adder for timing
reasons.

In order to simplify the logic and help improve timing, settings of
the control signals have been made unconditional in a state in many
places, even if those settings are only required when some condition
is met.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
3 years ago
Paul Mackerras 03ca9b5dd5 FPU: Minor fix and simplifications
In preparation for an explicit exponent data path.  The fix is that
fre[s] needs to negate the exponent after renomalization rather than
before, otherwise the exponent adjustment done by the renormalization
is in the wrong direction.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
3 years ago
Joel Stanley 60c54fb959 fpu: Fix -Whide warnings
fpu.vhdl:513:18⚠️ declaration of "result" hides signal "result" [-Whide]
         variable result : std_ulogic_vector(63 downto 0);

Signed-off-by: Joel Stanley <joel@jms.id.au>
3 years ago
Michael Neuling 43dadca052 Metavalue cleanup for fpu.vhdl
Signed-off-by: Michael Neuling <mikey@neuling.org>
3 years 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
more.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
3 years 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 <paulus@ozlabs.org>
3 years ago
Paul Mackerras 34330552e8 FPU: Add logic for 32-bit integer division
Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
3 years ago
Paul Mackerras a95f8aab38 FPU: Add integer division logic to FPU
This adds logic to the FPU to accomplish 64-bit integer divisions.
No instruction actually uses this yet.

The algorithm used is to obtain an estimate of the reciprocal of the
divisor using the lookup table and refine it by one to three
iterations of the Newton-Raphson algorithm (the number of iterations
depends on the number of significant bits in the dividend).  Then the
reciprocal is multiplied by the dividend to get the quotient estimate.
The remainder is calculated as dividend - quotient * divisor.  If the
remainder is greater than or equal to the divisor, the quotient is
incremented, or if a modulo operation is being done, the divisor is
subtracted from the remainder.  The inverse estimate after refinement
is good enough that the quotient estimate is always equal to or one
less than the true quotient.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
3 years ago
Paul Mackerras 23d5c4edc5 FPU: Convert internal R, A, B, and C registers to 8.56 format
This changes the representation of the R, A, B and C registers in the
FPU from 10.54 format (10 bits to the left of the binary point and 54
bits to the right) to 8.56 format, to match the representation used in
the P and Y registers and the multiplier operands.  This eliminates
the need for shifting when R, A, B or C is an input to the multiplier
and will make it easier to implement integer division in the FPU.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
3 years ago
Paul Mackerras 9a8a8e50f8 FPU: Add stage-2 stall ability to FPU
This makes the FPU able to stall other units at execute stage 2 and be
stalled by other units (specifically the LSU).

This means that the completion and writeback for an instruction can
now end up being deferred until the second cycle of a following
instruction, i.e. the cycle when the state machine has gone through
IDLE state into one of the DO_* states, which means we need to latch
the destination FPR number, CR mask, etc. from the previous
instruction so that we present the correct information to writeback.

The advantage of this is that we can get rid of the in_progress signal
from the LSU.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
3 years ago
Anton Blanchard 9d35340bb1 fpu: Reduce uninitialised signals
Reduce uninitialised signals coming out of the FPU.

Signed-off-by: Anton Blanchard <anton@linux.ibm.com>
3 years ago
Anton Blanchard 64d2def0c6 fpu: Fix capitalisation of Execute1ToFPUType
While this is not an issue in VHDL, I noticed this when running
a script over the source and we may as well fix it.

Signed-off-by: Anton Blanchard <anton@linux.ibm.com>
3 years ago
Anton Blanchard 50b4cb9423 fpu: Make inverse_table a constant
GHDL synthesis is complaining that inverse_table is never stored to.
Change it to a constant.

Signed-off-by: Anton Blanchard <anton@linux.ibm.com>
3 years ago
Paul Mackerras acb3d2d745 core: Send FPU interrupts to writeback rather than execute1
Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
4 years ago
Paul Mackerras c0b45e153b core: Track GPR hazards using tags that propagate through the pipelines
This changes the way GPR hazards are detected and tracked.  Instead of
having a model of the pipeline in gpr_hazard.vhdl, which has to mirror
the behaviour of the real pipeline exactly, we now assign a 2-bit tag
to each instruction and record which GSPR the instruction writes.
Subsequent instructions that need to use the GSPR get the tag number
and stall until the value with that tag is being written back to the
register file.

For now, the forwarding paths are disabled.  That gives about a 8%
reduction in coremark performance.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
4 years ago
Paul Mackerras 5535257c71 FPU: Don't use mask generator for rounding
Instead of using the mask generator in the rounding process, this uses
simpler logic to add in a 1 at the appropriate position (bit 2 or bit
31, depending on precision) and mask off the low-order bits.  Since
there are only two positions at which the masking and incrementing
need to be done, we don't need the full generality of the mask
generator.  This reduces the amount of logic and improves timing.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
4 years ago
Paul Mackerras 45c5236700 FPU: Relax timing around multiplier output
At present there is a state transition in the handling of the fmadd
instructions where the next state depends on the sign bit of the
multiplier result.  This creates a critical path which doesn't make
timing on the A7-100.  To fix this, we make the state transition
independent of the sign of the multiplier result, which improves
timing, but means we take one more cycle to do a fmadd-family
instruction in some cases.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
4 years ago
Paul Mackerras 73f819301b FPU: Do masking after adder rather than on A input
The masking enabled by opsel_amask is only used when rounding, to trim
the rounded result to the required precision.  We now do the masking
after the adder rather than before (on the A input).  This gives the
same result and helps timing.  The path from r.shift through the mask
generator and adder to v.r was showing up as a critical path.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
5 years ago
Paul Mackerras e1ca023bad FPU: Decide on mask length a cycle earlier
This moves longmask into the reg_type record, meaning that it now
needs to be decided a cycle earlier, in order to help timing.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
5 years ago