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 DivPipeKindConfig
:
39 core_input_data_class
,
40 core_interstage_data_class
,
41 core_output_data_class
,
42 core_setup_stage_class
,
43 core_calculate_stage_class
,
44 core_final_stage_class
):
45 self
.core_config
= core_config
46 self
.core_input_data_class
= core_input_data_class
47 self
.core_interstage_data_class
= core_interstage_data_class
48 self
.core_output_data_class
= core_output_data_class
49 self
.core_setup_stage_class
= core_setup_stage_class
50 self
.core_calculate_stage_class
= core_calculate_stage_class
51 self
.core_final_stage_class
= core_final_stage_class
54 class DivPipeKind(enum
.Enum
):
55 # use ieee754.div_rem_sqrt_rsqrt.core.DivPipeCore*
56 DivPipeCore
= enum
.auto()
57 # use nmigen's built-in div and rem operators -- only suitable for
60 # use a FSM-based div core
65 if self
== DivPipeKind
.DivPipeCore
:
66 return DivPipeKindConfig(
67 core_config
=DivPipeCoreConfig(
71 supported
=[DP
.UDivRem
]
73 core_input_data_class
=DivPipeCoreInputData
,
74 core_interstage_data_class
=DivPipeCoreInterstageData
,
75 core_output_data_class
=DivPipeCoreOutputData
,
76 core_setup_stage_class
=DivPipeCoreSetupStage
,
77 core_calculate_stage_class
=DivPipeCoreCalculateStage
,
78 core_final_stage_class
=DivPipeCoreFinalStage
)
79 elif self
== DivPipeKind
.SimOnly
:
80 # import here to avoid import loop
81 from soc
.fu
.div
.sim_only_core
import (
82 SimOnlyCoreConfig
, SimOnlyCoreInputData
,
83 SimOnlyCoreInterstageData
, SimOnlyCoreOutputData
,
84 SimOnlyCoreSetupStage
, SimOnlyCoreCalculateStage
,
85 SimOnlyCoreFinalStage
)
86 return DivPipeKindConfig(
87 core_config
=SimOnlyCoreConfig(),
88 core_input_data_class
=SimOnlyCoreInputData
,
89 core_interstage_data_class
=SimOnlyCoreInterstageData
,
90 core_output_data_class
=SimOnlyCoreOutputData
,
91 core_setup_stage_class
=SimOnlyCoreSetupStage
,
92 core_calculate_stage_class
=SimOnlyCoreCalculateStage
,
93 core_final_stage_class
=SimOnlyCoreFinalStage
)
95 # ensure we didn't forget any cases
96 # -- I wish Python had a switch/match statement
97 assert self
== DivPipeKind
.FSMCore
98 # TODO(programmerjake): implement
99 raise NotImplementedError()
102 class DivPipeSpec(CommonPipeSpec
):
103 def __init__(self
, id_wid
, div_pipe_kind
):
104 super().__init
__(id_wid
=id_wid
)
105 self
.div_pipe_kind
= div_pipe_kind
106 self
.core_config
= div_pipe_kind
.config
.core_config
108 regspec
= (DivInputData
.regspec
, DivMulOutputData
.regspec
)
109 opsubsetkls
= CompLogicalOpSubset
112 class CoreBaseData(DivInputData
):
113 def __init__(self
, pspec
, core_data_class
):
114 super().__init
__(pspec
)
115 self
.core
= core_data_class(pspec
.core_config
)
116 self
.divisor_neg
= Signal(reset_less
=True)
117 self
.dividend_neg
= Signal(reset_less
=True)
118 self
.div_by_zero
= Signal(reset_less
=True)
120 # set if an overflow for divide extended instructions is detected
121 # because `abs_dividend >= abs_divisor` for the appropriate bit width;
122 # 0 if the instruction is not a divide extended instruction
123 self
.dive_abs_ov32
= Signal(reset_less
=True)
124 self
.dive_abs_ov64
= Signal(reset_less
=True)
127 yield from super().__iter
__()
128 yield from self
.core
.__iter
__(self
)
129 yield self
.divisor_neg
130 yield self
.dividend_neg
133 return self
.eq_without_core(rhs
) + self
.core
.eq(rhs
.core
)
135 def eq_without_core(self
, rhs
):
136 return super().eq(rhs
) + \
137 [self
.divisor_neg
.eq(rhs
.divisor_neg
),
138 self
.dividend_neg
.eq(rhs
.dividend_neg
),
139 self
.dive_abs_ov32
.eq(rhs
.dive_abs_ov32
),
140 self
.dive_abs_ov64
.eq(rhs
.dive_abs_ov64
),
141 self
.div_by_zero
.eq(rhs
.div_by_zero
)]
144 class CoreInputData(CoreBaseData
):
145 def __init__(self
, pspec
):
146 super().__init
__(pspec
,
147 pspec
.div_pipe_kind
.config
.core_input_data_class
)
150 class CoreInterstageData(CoreBaseData
):
151 def __init__(self
, pspec
):
152 super().__init
__(pspec
,
153 pspec
.div_pipe_kind
.config
.core_interstage_data_class
)
156 class CoreOutputData(CoreBaseData
):
157 def __init__(self
, pspec
):
158 super().__init
__(pspec
,
159 pspec
.div_pipe_kind
.config
.core_output_data_class
)