convert branch pipeline to use msr/cia as immediates
[soc.git] / src / soc / fu / div / pipe_data.py
1 import enum
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)
10
11
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
16
17 def __init__(self, pspec):
18 super().__init__(pspec, False)
19 # convenience
20 self.a, self.b = self.ra, self.rb
21
22
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')]
29
30 def __init__(self, pspec):
31 super().__init__(pspec, True)
32 # convenience
33 self.cr0 = self.cr_a
34
35
36 class DivPipeKindConfigBase:
37 def __init__(self,
38 core_config,
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
46
47
48 class DivPipeKindConfigCombPipe(DivPipeKindConfigBase):
49 def __init__(self,
50 core_config,
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
62
63
64 class DivPipeKindConfigFSM(DivPipeKindConfigBase):
65 def __init__(self,
66 core_config,
67 core_input_data_class,
68 core_output_data_class,
69 core_stage_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
74
75
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
80 # simulation
81 SimOnly = enum.auto()
82 # use a FSM-based div core
83 FSMDivCore = enum.auto()
84
85 @property
86 def config(self):
87 if self == DivPipeKind.DivPipeCore:
88 return DivPipeKindConfigCombPipe(
89 core_config=DivPipeCoreConfig(
90 bit_width=64,
91 fract_width=64,
92 log2_radix=1,
93 supported=[DP.UDivRem]
94 ),
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
119
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)
129
130
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
138
139 regspec = (DivInputData.regspec, DivMulOutputData.regspec)
140 opsubsetkls = CompLogicalOpSubset
141
142
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)
150
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)
156
157 def __iter__(self):
158 yield from super().__iter__()
159 yield from self.core.__iter__(self)
160 yield self.divisor_neg
161 yield self.dividend_neg
162
163 def eq(self, rhs):
164 return self.eq_without_core(rhs) + self.core.eq(rhs.core)
165
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)]
173
174
175 class CoreInputData(CoreBaseData):
176 def __init__(self, pspec):
177 super().__init__(pspec,
178 pspec.div_pipe_kind.config.core_input_data_class)
179
180
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:
185 raise ValueError(
186 f"CoreInterstageData not supported for {pspec.div_pipe_kind}")
187 super().__init__(pspec, data_class)
188
189
190 class CoreOutputData(CoreBaseData):
191 def __init__(self, pspec):
192 super().__init__(pspec,
193 pspec.div_pipe_kind.config.core_output_data_class)