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 simulation
59 # use a FSM-based div core
64 if self
== DivPipeKind
.DivPipeCore
:
65 return DivPipeKindConfig(
66 core_config
=DivPipeCoreConfig(
70 supported
=[DP
.UDivRem
]
72 core_input_data_class
=DivPipeCoreInputData
,
73 core_interstage_data_class
=DivPipeCoreInterstageData
,
74 core_output_data_class
=DivPipeCoreOutputData
,
75 core_setup_stage_class
=DivPipeCoreSetupStage
,
76 core_calculate_stage_class
=DivPipeCoreCalculateStage
,
77 core_final_stage_class
=DivPipeCoreFinalStage
)
78 elif self
== DivPipeKind
.SimOnly
:
79 # import here to avoid import loop
80 from soc
.fu
.div
.sim_only_core
import (
81 SimOnlyCoreConfig
, SimOnlyCoreInputData
,
82 SimOnlyCoreInterstageData
, SimOnlyCoreOutputData
,
83 SimOnlyCoreSetupStage
, SimOnlyCoreCalculateStage
,
84 SimOnlyCoreFinalStage
)
85 return DivPipeKindConfig(
86 core_config
=SimOnlyCoreConfig(),
87 core_input_data_class
=SimOnlyCoreInputData
,
88 core_interstage_data_class
=SimOnlyCoreInterstageData
,
89 core_output_data_class
=SimOnlyCoreOutputData
,
90 core_setup_stage_class
=SimOnlyCoreSetupStage
,
91 core_calculate_stage_class
=SimOnlyCoreCalculateStage
,
92 core_final_stage_class
=SimOnlyCoreFinalStage
)
94 # ensure we didn't forget any cases
95 # -- I wish Python had a switch/match statement
96 assert self
== DivPipeKind
.FSMCore
97 # TODO(programmerjake): implement
98 raise NotImplementedError()
101 class DivPipeSpec(CommonPipeSpec
):
102 def __init__(self
, id_wid
, div_pipe_kind
):
103 super().__init
__(id_wid
=id_wid
)
104 self
.div_pipe_kind
= div_pipe_kind
105 self
.core_config
= div_pipe_kind
.config
.core_config
107 regspec
= (DivInputData
.regspec
, DivMulOutputData
.regspec
)
108 opsubsetkls
= CompLogicalOpSubset
111 class CoreBaseData(DivInputData
):
112 def __init__(self
, pspec
, core_data_class
):
113 super().__init
__(pspec
)
114 self
.core
= core_data_class(pspec
.core_config
)
115 self
.divisor_neg
= Signal(reset_less
=True)
116 self
.dividend_neg
= Signal(reset_less
=True)
117 self
.div_by_zero
= Signal(reset_less
=True)
119 # set if an overflow for divide extended instructions is detected
120 # because `abs_dividend >= abs_divisor` for the appropriate bit width;
121 # 0 if the instruction is not a divide extended instruction
122 self
.dive_abs_ov32
= Signal(reset_less
=True)
123 self
.dive_abs_ov64
= Signal(reset_less
=True)
126 yield from super().__iter
__()
127 yield from self
.core
.__iter
__(self
)
128 yield self
.divisor_neg
129 yield self
.dividend_neg
132 return self
.eq_without_core(rhs
) + self
.core
.eq(rhs
.core
)
134 def eq_without_core(self
, rhs
):
135 return super().eq(rhs
) + \
136 [self
.divisor_neg
.eq(rhs
.divisor_neg
),
137 self
.dividend_neg
.eq(rhs
.dividend_neg
),
138 self
.dive_abs_ov32
.eq(rhs
.dive_abs_ov32
),
139 self
.dive_abs_ov64
.eq(rhs
.dive_abs_ov64
),
140 self
.div_by_zero
.eq(rhs
.div_by_zero
)]
143 class CoreInputData(CoreBaseData
):
144 def __init__(self
, pspec
):
145 super().__init
__(pspec
, pspec
.div_pipe_kind
.config
.core_input_data_class
)
148 class CoreInterstageData(CoreBaseData
):
149 def __init__(self
, pspec
):
150 super().__init
__(pspec
, pspec
.div_pipe_kind
.config
.core_interstage_data_class
)
153 class CoreOutputData(CoreBaseData
):
154 def __init__(self
, pspec
):
155 super().__init
__(pspec
, pspec
.div_pipe_kind
.config
.core_output_data_class
)