2 from nmigen
import Signal
, Const
3 from soc
.fu
.pipe_data
import IntegerData
4 from soc
.fu
.alu
.pipe_data
import CommonPipeSpec
5 from soc
.fu
.logical
.logical_input_record
import CompLogicalOpSubset
6 from ieee754
.div_rem_sqrt_rsqrt
.core
import (
7 DivPipeCoreConfig
, DivPipeCoreInputData
, DP
,
8 DivPipeCoreInterstageData
, DivPipeCoreOutputData
,
9 DivPipeCoreSetupStage
, DivPipeCoreCalculateStage
, DivPipeCoreFinalStage
)
12 class DivInputData(IntegerData
):
13 regspec
= [('INT', 'ra', '0:63'), # RA
14 ('INT', 'rb', '0:63'), # RB/immediate
15 ('XER', 'xer_so', '32'), ] # XER bit 32: SO
17 def __init__(self
, pspec
):
18 super().__init
__(pspec
, False)
20 self
.a
, self
.b
= self
.ra
, self
.rb
23 # output stage shared between div and mul: like ALUOutputData but no CA/32
24 class DivMulOutputData(IntegerData
):
25 regspec
= [('INT', 'o', '0:63'),
26 ('CR', 'cr_a', '0:3'),
27 ('XER', 'xer_ov', '33,44'), # bit0: ov, bit1: ov32
28 ('XER', 'xer_so', '32')]
30 def __init__(self
, pspec
):
31 super().__init
__(pspec
, True)
36 class DivPipeKindConfigBase
:
39 core_input_data_class
,
40 core_interstage_data_class
,
41 core_output_data_class
):
42 self
.core_config
= core_config
43 self
.core_input_data_class
= core_input_data_class
44 self
.core_interstage_data_class
= core_interstage_data_class
45 self
.core_output_data_class
= core_output_data_class
48 class DivPipeKindConfigCombPipe(DivPipeKindConfigBase
):
51 core_input_data_class
,
52 core_interstage_data_class
,
53 core_output_data_class
,
54 core_setup_stage_class
,
55 core_calculate_stage_class
,
56 core_final_stage_class
):
57 super().__init
__(core_config
, core_input_data_class
,
58 core_interstage_data_class
, core_output_data_class
)
59 self
.core_setup_stage_class
= core_setup_stage_class
60 self
.core_calculate_stage_class
= core_calculate_stage_class
61 self
.core_final_stage_class
= core_final_stage_class
64 class DivPipeKindConfigFSM(DivPipeKindConfigBase
):
67 core_input_data_class
,
68 core_output_data_class
,
70 core_interstage_data_class
= None
71 super().__init
__(core_config
, core_input_data_class
,
72 core_interstage_data_class
, core_output_data_class
)
73 self
.core_stage_class
= core_stage_class
76 class DivPipeKind(enum
.Enum
):
77 # use ieee754.div_rem_sqrt_rsqrt.core.DivPipeCore*
78 DivPipeCore
= enum
.auto()
79 # use nmigen's built-in div and rem operators -- only suitable for
82 # use a FSM-based div core
83 FSMDivCore
= enum
.auto()
87 if self
== DivPipeKind
.DivPipeCore
:
88 return DivPipeKindConfigCombPipe(
89 core_config
=DivPipeCoreConfig(
93 supported
=[DP
.UDivRem
]
95 core_input_data_class
=DivPipeCoreInputData
,
96 core_interstage_data_class
=DivPipeCoreInterstageData
,
97 core_output_data_class
=DivPipeCoreOutputData
,
98 core_setup_stage_class
=DivPipeCoreSetupStage
,
99 core_calculate_stage_class
=DivPipeCoreCalculateStage
,
100 core_final_stage_class
=DivPipeCoreFinalStage
)
101 if self
== DivPipeKind
.SimOnly
:
102 # import here to avoid import loop
103 from soc
.fu
.div
.sim_only_core
import (
104 SimOnlyCoreConfig
, SimOnlyCoreInputData
,
105 SimOnlyCoreInterstageData
, SimOnlyCoreOutputData
,
106 SimOnlyCoreSetupStage
, SimOnlyCoreCalculateStage
,
107 SimOnlyCoreFinalStage
)
108 return DivPipeKindConfigCombPipe(
109 core_config
=SimOnlyCoreConfig(),
110 core_input_data_class
=SimOnlyCoreInputData
,
111 core_interstage_data_class
=SimOnlyCoreInterstageData
,
112 core_output_data_class
=SimOnlyCoreOutputData
,
113 core_setup_stage_class
=SimOnlyCoreSetupStage
,
114 core_calculate_stage_class
=SimOnlyCoreCalculateStage
,
115 core_final_stage_class
=SimOnlyCoreFinalStage
)
116 # ensure we didn't forget any cases
117 # -- I wish Python had a switch/match statement
118 assert self
== DivPipeKind
.FSMDivCore
120 # import here to avoid import loop
121 from soc
.fu
.div
.fsm
import (
122 FSMDivCoreConfig
, FSMDivCoreInputData
,
123 FSMDivCoreOutputData
, FSMDivCoreStage
)
124 return DivPipeKindConfigFSM(
125 core_config
=FSMDivCoreConfig(),
126 core_input_data_class
=FSMDivCoreInputData
,
127 core_output_data_class
=FSMDivCoreOutputData
,
128 core_stage_class
=FSMDivCoreStage
)
131 class DivPipeSpec(CommonPipeSpec
):
132 def __init__(self
, id_wid
, div_pipe_kind
):
133 super().__init
__(id_wid
=id_wid
)
134 self
.div_pipe_kind
= div_pipe_kind
135 self
.core_config
= div_pipe_kind
.config
.core_config
137 regspec
= (DivInputData
.regspec
, DivMulOutputData
.regspec
)
138 opsubsetkls
= CompLogicalOpSubset
141 class DivPipeSpecDivPipeCore(DivPipeSpec
):
142 def __init__(self
, id_wid
):
143 super().__init
__(id_wid
=id_wid
, div_pipe_kind
=DivPipeKind
.DivPipeCore
)
146 class DivPipeSpecFSMDivCore(DivPipeSpec
):
147 def __init__(self
, id_wid
):
148 super().__init
__(id_wid
=id_wid
, div_pipe_kind
=DivPipeKind
.FSMDivCore
)
151 class DivPipeSpecSimOnly(DivPipeSpec
):
152 def __init__(self
, id_wid
):
153 super().__init
__(id_wid
=id_wid
, div_pipe_kind
=DivPipeKind
.SimOnly
)
156 class CoreBaseData(DivInputData
):
157 def __init__(self
, pspec
, core_data_class
):
158 super().__init
__(pspec
)
159 self
.core
= core_data_class(pspec
.core_config
)
160 self
.divisor_neg
= Signal(reset_less
=True)
161 self
.dividend_neg
= Signal(reset_less
=True)
162 self
.div_by_zero
= Signal(reset_less
=True)
164 # set if an overflow for divide extended instructions is detected
165 # because `abs_dividend >= abs_divisor` for the appropriate bit width;
166 # 0 if the instruction is not a divide extended instruction
167 self
.dive_abs_ov32
= Signal(reset_less
=True)
168 self
.dive_abs_ov64
= Signal(reset_less
=True)
171 yield from super().__iter
__()
172 yield from self
.core
.__iter
__(self
)
173 yield self
.divisor_neg
174 yield self
.dividend_neg
177 return self
.eq_without_core(rhs
) + self
.core
.eq(rhs
.core
)
179 def eq_without_core(self
, rhs
):
180 return super().eq(rhs
) + \
181 [self
.divisor_neg
.eq(rhs
.divisor_neg
),
182 self
.dividend_neg
.eq(rhs
.dividend_neg
),
183 self
.dive_abs_ov32
.eq(rhs
.dive_abs_ov32
),
184 self
.dive_abs_ov64
.eq(rhs
.dive_abs_ov64
),
185 self
.div_by_zero
.eq(rhs
.div_by_zero
)]
188 class CoreInputData(CoreBaseData
):
189 def __init__(self
, pspec
):
190 super().__init
__(pspec
,
191 pspec
.div_pipe_kind
.config
.core_input_data_class
)
194 class CoreInterstageData(CoreBaseData
):
195 def __init__(self
, pspec
):
196 data_class
= pspec
.div_pipe_kind
.config
.core_interstage_data_class
197 if data_class
is None:
199 f
"CoreInterstageData not supported for {pspec.div_pipe_kind}")
200 super().__init
__(pspec
, data_class
)
203 class CoreOutputData(CoreBaseData
):
204 def __init__(self
, pspec
):
205 super().__init
__(pspec
,
206 pspec
.div_pipe_kind
.config
.core_output_data_class
)