1 # This stage is the setup stage that converts the inputs
2 # into the values expected by DivPipeCore
4 from nmigen
import (Module
, Signal
, Cat
, Repl
, Mux
, Const
, Array
)
5 from nmutil
.pipemodbase
import PipeModBase
6 from soc
.fu
.div
.pipe_data
import DIVInputData
7 from soc
.fu
.alu
.pipe_data
import ALUOutputData
8 from ieee754
.part
.partsig
import PartitionedSignal
9 from soc
.decoder
.power_enums
import InternalOp
11 from soc
.decoder
.power_fields
import DecodeFields
12 from soc
.decoder
.power_fieldsn
import SignalBitRange
13 from soc
.fu
.div
.pipe_data
import CoreInputData
14 from ieee754
.div_rem_sqrt_rsqrt
.core
import DivPipeCoreOperation
16 def eq32(is_32bit
, dest
, src
):
17 return [dest
[0:32].eq(src
[0:32]),
18 dest
[32:64].eq(Mux(is_32bit
, 0, src
[32:64]))]
21 class DivSetupStage(PipeModBase
):
22 def __init__(self
, pspec
):
23 super().__init
__(pspec
, "setup_stage")
24 self
.fields
= DecodeFields(SignalBitRange
, [self
.i
.ctx
.op
.insn
])
25 self
.fields
.create_specs()
28 return DIVInputData(self
.pspec
)
31 return CoreInputData(self
.pspec
)
33 def elaborate(self
, platform
):
36 # convenience variables
37 op
, a
, b
= self
.i
.ctx
.op
, self
.i
.a
, self
.i
.b
39 dividend_neg_o
= self
.o
.dividend_neg
40 divisor_neg_o
= self
.o
.divisor_neg
41 dividend_o
= core_o
.dividend
42 divisor_o
= core_o
.divisor_radicand
44 # set operation to unsigned div/remainder
45 comb
+= core_o
.operation
.eq(int(DivPipeCoreOperation
.UDivRem
))
47 # work out if a/b are negative (check 32-bit / signed)
48 comb
+= dividend_neg_o
.eq(Mux(op
.is_32bit
, a
[31], a
[63]) & op
.is_signed
)
49 comb
+= divisor_neg_o
.eq(Mux(op
.is_32bit
, b
[31], b
[63]) & op
.is_signed
)
51 # negation of a 64-bit value produces the same lower 32-bit
52 # result as negation of just the lower 32-bits, so we don't
53 # need to do anything special before negating
54 abs_dor
= Signal(64, reset_less
=True) # absolute of divisor
55 abs_dend
= Signal(64, reset_less
=True) # absolute of dividend
56 comb
+= abs_dor
.eq(Mux(divisor_neg_o
, -b
, b
))
57 comb
+= abs_dend
.eq(Mux(dividend_neg_o
, -a
, a
))
59 # check for absolute overflow condition (32/64)
60 comb
+= self
.o
.dive_abs_ov64
.eq((abs_dend
>= abs_dor
)
61 & (op
.insn_type
== InternalOp
.OP_DIVE
))
63 comb
+= self
.o
.dive_abs_ov32
.eq((abs_dend
[0:32] >= abs_dor
[0:32])
64 & (op
.insn_type
== InternalOp
.OP_DIVE
))
66 # set divisor based on 32/64 bit mode (must be absolute)
67 comb
+= eq32(op
.is_32bit
, divisor_o
, abs_dor
)
69 # divide by zero error detection
70 comb
+= self
.o
.div_by_zero
.eq(divisor_o
== 0)
72 ##########################
75 with m
.Switch(op
.insn_type
):
76 # div/mod takes straight (absolute) dividend
77 with m
.Case(InternalOp
.OP_DIV
, InternalOp
.OP_MOD
):
78 comb
+= eq32(op
.is_32bit
, dividend_o
, abs_dend
)
79 # extended div shifts dividend up
80 with m
.Case(InternalOp
.OP_DIVE
):
81 with m
.If(op
.is_32bit
):
82 comb
+= dividend_o
.eq(abs_dend
[0:32] << 32)
84 comb
+= dividend_o
.eq(abs_dend
[0:64] << 64)
86 ###### sticky overflow and context, both pass-through #####
88 comb
+= self
.o
.xer_so
.eq(self
.i
.xer_so
)
89 comb
+= self
.o
.ctx
.eq(self
.i
.ctx
)