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
=None):
133 if div_pipe_kind
is None:
134 div_pipe_kind
= DivPipeKind
.DivPipeCore
135 super().__init
__(id_wid
=id_wid
)
136 self
.div_pipe_kind
= div_pipe_kind
137 self
.core_config
= div_pipe_kind
.config
.core_config
139 regspec
= (DivInputData
.regspec
, DivMulOutputData
.regspec
)
140 opsubsetkls
= CompLogicalOpSubset
143 class CoreBaseData(DivInputData
):
144 def __init__(self
, pspec
, core_data_class
):
145 super().__init
__(pspec
)
146 self
.core
= core_data_class(pspec
.core_config
)
147 self
.divisor_neg
= Signal(reset_less
=True)
148 self
.dividend_neg
= Signal(reset_less
=True)
149 self
.div_by_zero
= Signal(reset_less
=True)
151 # set if an overflow for divide extended instructions is detected
152 # because `abs_dividend >= abs_divisor` for the appropriate bit width;
153 # 0 if the instruction is not a divide extended instruction
154 self
.dive_abs_ov32
= Signal(reset_less
=True)
155 self
.dive_abs_ov64
= Signal(reset_less
=True)
158 yield from super().__iter
__()
159 yield from self
.core
.__iter
__(self
)
160 yield self
.divisor_neg
161 yield self
.dividend_neg
164 return self
.eq_without_core(rhs
) + self
.core
.eq(rhs
.core
)
166 def eq_without_core(self
, rhs
):
167 return super().eq(rhs
) + \
168 [self
.divisor_neg
.eq(rhs
.divisor_neg
),
169 self
.dividend_neg
.eq(rhs
.dividend_neg
),
170 self
.dive_abs_ov32
.eq(rhs
.dive_abs_ov32
),
171 self
.dive_abs_ov64
.eq(rhs
.dive_abs_ov64
),
172 self
.div_by_zero
.eq(rhs
.div_by_zero
)]
175 class CoreInputData(CoreBaseData
):
176 def __init__(self
, pspec
):
177 super().__init
__(pspec
,
178 pspec
.div_pipe_kind
.config
.core_input_data_class
)
181 class CoreInterstageData(CoreBaseData
):
182 def __init__(self
, pspec
):
183 data_class
= pspec
.div_pipe_kind
.config
.core_interstage_data_class
184 if data_class
is None:
186 f
"CoreInterstageData not supported for {pspec.div_pipe_kind}")
187 super().__init
__(pspec
, data_class
)
190 class CoreOutputData(CoreBaseData
):
191 def __init__(self
, pspec
):
192 super().__init
__(pspec
,
193 pspec
.div_pipe_kind
.config
.core_output_data_class
)