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
.logical
.pipe_data
import LogicalInputData
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
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()
22 self
.abs_divisor
= Signal(64)
23 self
.abs_dividend
= Signal(64)
26 return LogicalInputData(self
.pspec
)
29 return CoreInputData(self
.pspec
)
31 def elaborate(self
, platform
):
34 op
, a
, b
= self
.i
.ctx
.op
, self
.i
.a
, self
.i
.b
35 core_input_data
= self
.o
.core
36 dividend_neg
= self
.o
.dividend_neg
37 divisor_neg
= self
.o
.divisor_neg
38 dividend_in
= core_input_data
.dividend
39 divisor_in
= core_input_data
.divisor_radicand
41 comb
+= core_input_data
.operation
.eq(
42 int(DivPipeCoreOperation
.UDivRem
))
44 comb
+= dividend_neg
.eq(Mux(op
.is_32bit
, a
[31], a
[63]) & op
.is_signed
)
45 comb
+= divisor_neg
.eq(Mux(op
.is_32bit
, b
[31], b
[63]) & op
.is_signed
)
47 # negation of a 64-bit value produces the same lower 32-bit
48 # result as negation of just the lower 32-bits, so we don't
49 # need to do anything special before negating
50 comb
+= self
.abs_divisor
.eq(Mux(divisor_neg
, -b
, b
))
51 comb
+= self
.abs_dividend
.eq(Mux(dividend_neg
, -a
, a
))
53 comb
+= self
.o
.dive_abs_overflow_64
.eq(
54 (self
.abs_dividend
>= self
.abs_divisor
)
55 & (op
.insn_type
== InternalOp
.OP_DIVE
))
57 comb
+= self
.o
.dive_abs_overflow_32
.eq(
58 (self
.abs_dividend
[0:32] >= self
.abs_divisor
[0:32])
59 & (op
.insn_type
== InternalOp
.OP_DIVE
))
61 with m
.If(op
.is_32bit
):
62 comb
+= divisor_in
.eq(self
.abs_divisor
[0:32])
64 comb
+= divisor_in
.eq(self
.abs_divisor
[0:64])
66 comb
+= self
.o
.div_by_zero
.eq(self
.divisor_in
== 0)
68 ##########################
71 with m
.Switch(op
.insn_type
):
72 with m
.Case(InternalOp
.OP_DIV
, InternalOp
.OP_MOD
):
73 with m
.If(op
.is_32bit
):
74 comb
+= dividend_in
.eq(self
.abs_dividend
[0:32])
76 comb
+= dividend_in
.eq(self
.abs_dividend
[0:64])
77 with m
.Case(InternalOp
.OP_DIVE
):
78 with m
.If(op
.is_32bit
):
79 comb
+= dividend_in
.eq(self
.abs_dividend
[0:32] << 32)
81 comb
+= dividend_in
.eq(self
.abs_dividend
[0:64] << 64)
83 ###### sticky overflow and context, both pass-through #####
85 comb
+= self
.o
.xer_so
.data
.eq(self
.i
.xer_so
)
86 comb
+= self
.o
.ctx
.eq(self
.i
.ctx
)
90 comb
+= self
.o
.op
.eq(op
)