2 from nmigen
import Signal
, Const
3 from soc
.fu
.pipe_data
import FUBaseData
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(FUBaseData
):
13 def __init__(self
, pspec
):
14 super().__init
__(pspec
, False)
16 self
.a
, self
.b
= self
.ra
, self
.rb
20 return [('INT', 'ra', self
.intrange
), # RA
21 ('INT', 'rb', self
.intrange
), # RB/immediate
22 ('XER', 'xer_so', '32'), ] # XER bit 32: SO
25 # output stage shared between div and mul: like ALUOutputData but no CA/32
26 class DivMulOutputData(FUBaseData
):
28 def __init__(self
, pspec
):
29 super().__init
__(pspec
, True)
35 return [('INT', 'o', self
.intrange
),
36 ('CR', 'cr_a', '0:3'),
37 ('XER', 'xer_ov', '33,44'), # bit0: ov, bit1: ov32
38 ('XER', 'xer_so', '32')]
41 class DivPipeKindConfigBase
:
44 core_input_data_class
,
45 core_interstage_data_class
,
46 core_output_data_class
):
47 self
.core_config
= core_config
48 self
.core_input_data_class
= core_input_data_class
49 self
.core_interstage_data_class
= core_interstage_data_class
50 self
.core_output_data_class
= core_output_data_class
53 class DivPipeKindConfigCombPipe(DivPipeKindConfigBase
):
56 core_input_data_class
,
57 core_interstage_data_class
,
58 core_output_data_class
,
59 core_setup_stage_class
,
60 core_calculate_stage_class
,
61 core_final_stage_class
):
62 super().__init
__(core_config
, core_input_data_class
,
63 core_interstage_data_class
, core_output_data_class
)
64 self
.core_setup_stage_class
= core_setup_stage_class
65 self
.core_calculate_stage_class
= core_calculate_stage_class
66 self
.core_final_stage_class
= core_final_stage_class
69 class DivPipeKindConfigFSM(DivPipeKindConfigBase
):
72 core_input_data_class
,
73 core_output_data_class
,
75 core_interstage_data_class
= None
76 super().__init
__(core_config
, core_input_data_class
,
77 core_interstage_data_class
, core_output_data_class
)
78 self
.core_stage_class
= core_stage_class
81 class DivPipeKind(enum
.Enum
):
82 # use ieee754.div_rem_sqrt_rsqrt.core.DivPipeCore*
83 DivPipeCore
= enum
.auto()
84 # use nmigen's built-in div and rem operators -- only suitable for
87 # use a FSM-based div core
88 FSMDivCore
= enum
.auto()
92 if self
== DivPipeKind
.DivPipeCore
:
93 return DivPipeKindConfigCombPipe(
94 core_config
=DivPipeCoreConfig(
98 supported
=[DP
.UDivRem
]
100 core_input_data_class
=DivPipeCoreInputData
,
101 core_interstage_data_class
=DivPipeCoreInterstageData
,
102 core_output_data_class
=DivPipeCoreOutputData
,
103 core_setup_stage_class
=DivPipeCoreSetupStage
,
104 core_calculate_stage_class
=DivPipeCoreCalculateStage
,
105 core_final_stage_class
=DivPipeCoreFinalStage
)
106 if self
== DivPipeKind
.SimOnly
:
107 # import here to avoid import loop
108 from soc
.fu
.div
.sim_only_core
import (
109 SimOnlyCoreConfig
, SimOnlyCoreInputData
,
110 SimOnlyCoreInterstageData
, SimOnlyCoreOutputData
,
111 SimOnlyCoreSetupStage
, SimOnlyCoreCalculateStage
,
112 SimOnlyCoreFinalStage
)
113 return DivPipeKindConfigCombPipe(
114 core_config
=SimOnlyCoreConfig(),
115 core_input_data_class
=SimOnlyCoreInputData
,
116 core_interstage_data_class
=SimOnlyCoreInterstageData
,
117 core_output_data_class
=SimOnlyCoreOutputData
,
118 core_setup_stage_class
=SimOnlyCoreSetupStage
,
119 core_calculate_stage_class
=SimOnlyCoreCalculateStage
,
120 core_final_stage_class
=SimOnlyCoreFinalStage
)
121 # ensure we didn't forget any cases
122 # -- I wish Python had a switch/match statement
123 assert self
== DivPipeKind
.FSMDivCore
125 # import here to avoid import loop
126 from soc
.fu
.div
.fsm
import (
127 FSMDivCoreConfig
, FSMDivCoreInputData
,
128 FSMDivCoreOutputData
, FSMDivCoreStage
)
129 return DivPipeKindConfigFSM(
130 core_config
=FSMDivCoreConfig(),
131 core_input_data_class
=FSMDivCoreInputData
,
132 core_output_data_class
=FSMDivCoreOutputData
,
133 core_stage_class
=FSMDivCoreStage
)
136 class DivPipeSpec(CommonPipeSpec
):
137 def __init__(self
, id_wid
, parent_pspec
, div_pipe_kind
):
138 super().__init
__(id_wid
=id_wid
, parent_pspec
=parent_pspec
)
139 self
.div_pipe_kind
= div_pipe_kind
140 self
.core_config
= div_pipe_kind
.config
.core_config
142 regspecklses
= (DivInputData
, DivMulOutputData
)
143 opsubsetkls
= CompLogicalOpSubset
146 class DivPipeSpecDivPipeCore(DivPipeSpec
):
147 def __init__(self
, id_wid
, parent_pspec
):
148 super().__init
__(id_wid
=id_wid
,
149 parent_pspec
=parent_pspec
,
150 div_pipe_kind
=DivPipeKind
.DivPipeCore
)
153 class DivPipeSpecFSMDivCore(DivPipeSpec
):
154 def __init__(self
, id_wid
, parent_pspec
):
155 super().__init
__(id_wid
=id_wid
,
156 parent_pspec
=parent_pspec
,
157 div_pipe_kind
=DivPipeKind
.FSMDivCore
)
160 class DivPipeSpecSimOnly(DivPipeSpec
):
161 def __init__(self
, id_wid
, parent_pspec
):
162 super().__init
__(id_wid
=id_wid
,
163 parent_pspec
=parent_pspec
,
164 div_pipe_kind
=DivPipeKind
.SimOnly
)
167 class CoreBaseData(DivInputData
):
168 def __init__(self
, pspec
, core_data_class
):
169 super().__init
__(pspec
)
170 self
.core
= core_data_class(pspec
.core_config
)
171 self
.divisor_neg
= Signal(reset_less
=True)
172 self
.dividend_neg
= Signal(reset_less
=True)
173 self
.div_by_zero
= Signal(reset_less
=True)
175 # set if an overflow for divide extended instructions is detected
176 # because `abs_dividend >= abs_divisor` for the appropriate bit width;
177 # 0 if the instruction is not a divide extended instruction
178 self
.dive_abs_ov32
= Signal(reset_less
=True)
179 self
.dive_abs_ov64
= Signal(reset_less
=True)
182 yield from super().__iter
__()
183 yield from self
.core
.__iter
__(self
)
184 yield self
.divisor_neg
185 yield self
.dividend_neg
188 return self
.eq_without_core(rhs
) + self
.core
.eq(rhs
.core
)
190 def eq_without_core(self
, rhs
):
191 return super().eq(rhs
) + \
192 [self
.divisor_neg
.eq(rhs
.divisor_neg
),
193 self
.dividend_neg
.eq(rhs
.dividend_neg
),
194 self
.dive_abs_ov32
.eq(rhs
.dive_abs_ov32
),
195 self
.dive_abs_ov64
.eq(rhs
.dive_abs_ov64
),
196 self
.div_by_zero
.eq(rhs
.div_by_zero
)]
199 class CoreInputData(CoreBaseData
):
200 def __init__(self
, pspec
):
201 super().__init
__(pspec
,
202 pspec
.div_pipe_kind
.config
.core_input_data_class
)
205 class CoreInterstageData(CoreBaseData
):
206 def __init__(self
, pspec
):
207 data_class
= pspec
.div_pipe_kind
.config
.core_interstage_data_class
208 if data_class
is None:
210 f
"CoreInterstageData not supported for {pspec.div_pipe_kind}")
211 super().__init
__(pspec
, data_class
)
214 class CoreOutputData(CoreBaseData
):
215 def __init__(self
, pspec
):
216 super().__init
__(pspec
,
217 pspec
.div_pipe_kind
.config
.core_output_data_class
)