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 ieee754
.part
.partsig
import SimdSignal
8 from openpower
.decoder
.power_enums
import MicrOp
10 from openpower
.decoder
.power_fields
import DecodeFields
11 from openpower
.decoder
.power_fieldsn
import SignalBitRange
12 from soc
.fu
.div
.pipe_data
import CoreInputData
13 from ieee754
.div_rem_sqrt_rsqrt
.core
import DivPipeCoreOperation
14 from nmutil
.util
import eq32
17 class DivSetupStage(PipeModBase
):
18 def __init__(self
, pspec
):
19 super().__init
__(pspec
, "setup_stage")
20 self
.fields
= DecodeFields(SignalBitRange
, [self
.i
.ctx
.op
.insn
])
21 self
.fields
.create_specs()
24 return DivInputData(self
.pspec
)
27 return CoreInputData(self
.pspec
)
29 def elaborate(self
, platform
):
30 XLEN
= self
.pspec
.XLEN
33 # convenience variables
34 op
, a
, b
= self
.i
.ctx
.op
, self
.i
.a
, self
.i
.b
36 dividend_neg_o
= self
.o
.dividend_neg
37 divisor_neg_o
= self
.o
.divisor_neg
38 dividend_o
= core_o
.dividend
39 divisor_o
= core_o
.divisor_radicand
41 # set operation to unsigned div/remainder
42 comb
+= core_o
.operation
.eq(int(DivPipeCoreOperation
.UDivRem
))
44 # work out if a/b are negative (check 32-bit / signed)
45 comb
+= dividend_neg_o
.eq(Mux(op
.is_32bit
,
46 a
[31], a
[XLEN
-1]) & op
.is_signed
)
47 comb
+= divisor_neg_o
.eq(Mux(op
.is_32bit
,
48 b
[31], b
[XLEN
-1]) & op
.is_signed
)
50 # negation of a 64-bit value produces the same lower 32-bit
51 # result as negation of just the lower 32-bits, so we don't
52 # need to do anything special before negating
53 abs_dor
= Signal(XLEN
, reset_less
=True) # absolute of divisor
54 abs_dend
= Signal(XLEN
, reset_less
=True) # absolute of dividend
55 comb
+= abs_dor
.eq(Mux(divisor_neg_o
, -b
, b
))
56 comb
+= abs_dend
.eq(Mux(dividend_neg_o
, -a
, a
))
58 # check for absolute overflow condition (32/64)
59 comb
+= self
.o
.dive_abs_ov64
.eq((abs_dend
>= abs_dor
)
60 & (op
.insn_type
== MicrOp
.OP_DIVE
))
62 comb
+= self
.o
.dive_abs_ov32
.eq((abs_dend
[0:32] >= abs_dor
[0:32])
63 & (op
.insn_type
== MicrOp
.OP_DIVE
))
65 # set divisor based on 32/64 bit mode (must be absolute)
66 comb
+= eq32(op
.is_32bit
, divisor_o
, abs_dor
)
68 # divide by zero error detection
69 comb
+= self
.o
.div_by_zero
.eq(divisor_o
== 0)
71 ##########################
74 with m
.Switch(op
.insn_type
):
75 # div/mod takes straight (absolute) dividend
76 with m
.Case(MicrOp
.OP_DIV
, MicrOp
.OP_MOD
):
77 comb
+= eq32(op
.is_32bit
, dividend_o
, abs_dend
)
78 # extended div shifts dividend up
79 with m
.Case(MicrOp
.OP_DIVE
):
80 with m
.If(op
.is_32bit
):
81 comb
+= dividend_o
.eq(abs_dend
[0:32] << 32)
83 comb
+= dividend_o
.eq(abs_dend
[0:XLEN
] << XLEN
)
85 ###### sticky overflow and context, both pass-through #####
87 comb
+= self
.o
.xer_so
.eq(self
.i
.xer_so
)
88 comb
+= self
.o
.ctx
.eq(self
.i
.ctx
)