if nmigen.sim.pysim import fails use nmigen.back.pysim
[soc.git] / src / soc / fu / div / fsm.py
1 import enum
2 from nmigen import Elaboratable, Module, Signal, Shape, unsigned, Cat, Mux
3 from soc.fu.div.pipe_data import CoreInputData, CoreOutputData, DivPipeSpec
4 from nmutil.iocontrol import PrevControl, NextControl
5 from ieee754.div_rem_sqrt_rsqrt.core import DivPipeCoreOperation
6
7
8 class FSMDivCoreConfig:
9 n_stages = 1
10 bit_width = 64
11 fract_width = 64
12
13
14 class FSMDivCoreInputData:
15 def __init__(self, core_config, reset_less=True):
16 self.core_config = core_config
17 self.dividend = Signal(128, reset_less=reset_less)
18 self.divisor_radicand = Signal(64, reset_less=reset_less)
19 self.operation = DivPipeCoreOperation.create_signal(
20 reset_less=reset_less)
21
22 def __iter__(self):
23 """ Get member signals. """
24 yield self.dividend
25 yield self.divisor_radicand
26 yield self.operation
27
28 def eq(self, rhs):
29 """ Assign member signals. """
30 return [self.dividend.eq(rhs.dividend),
31 self.divisor_radicand.eq(rhs.divisor_radicand),
32 self.operation.eq(rhs.operation),
33 ]
34
35
36 class FSMDivCoreOutputData:
37 def __init__(self, core_config, reset_less=True):
38 self.core_config = core_config
39 self.quotient_root = Signal(64, reset_less=reset_less)
40 self.remainder = Signal(3 * 64, reset_less=reset_less)
41
42 def __iter__(self):
43 """ Get member signals. """
44 yield self.quotient_root
45 yield self.remainder
46 return
47
48 def eq(self, rhs):
49 """ Assign member signals. """
50 return [self.quotient_root.eq(rhs.quotient_root),
51 self.remainder.eq(rhs.remainder)]
52
53
54 class FSMDivCorePrevControl(PrevControl):
55 data_i: CoreInputData
56
57 def __init__(self, pspec):
58 super().__init__(stage_ctl=True, maskwid=pspec.id_wid)
59 self.pspec = pspec
60 self.data_i = CoreInputData(pspec)
61
62
63 class FSMDivCoreNextControl(NextControl):
64 data_o: CoreOutputData
65
66 def __init__(self, pspec):
67 super().__init__(stage_ctl=True, maskwid=pspec.id_wid)
68 self.pspec = pspec
69 self.data_o = CoreOutputData(pspec)
70
71
72 class DivStateNext(Elaboratable):
73 def __init__(self, quotient_width):
74 self.quotient_width = quotient_width
75 self.i = DivState(quotient_width=quotient_width, name="i")
76 self.divisor = Signal(quotient_width)
77 self.o = DivState(quotient_width=quotient_width, name="o")
78
79 def elaborate(self, platform):
80 m = Module()
81 difference = Signal(self.i.quotient_width * 2)
82 m.d.comb += difference.eq(self.i.dividend_quotient
83 - (self.divisor
84 << (self.quotient_width - 1)))
85 next_quotient_bit = Signal()
86 m.d.comb += next_quotient_bit.eq(
87 ~difference[self.quotient_width * 2 - 1])
88 value = Signal(self.i.quotient_width * 2)
89 with m.If(next_quotient_bit):
90 m.d.comb += value.eq(difference)
91 with m.Else():
92 m.d.comb += value.eq(self.i.dividend_quotient)
93
94 with m.If(self.i.done):
95 m.d.comb += self.o.eq(self.i)
96 with m.Else():
97 m.d.comb += [
98 self.o.q_bits_known.eq(self.i.q_bits_known + 1),
99 self.o.dividend_quotient.eq(Cat(next_quotient_bit, value))]
100 return m
101
102
103 class DivStateInit(Elaboratable):
104 def __init__(self, quotient_width):
105 self.quotient_width = quotient_width
106 self.dividend = Signal(quotient_width * 2)
107 self.o = DivState(quotient_width=quotient_width, name="o")
108
109 def elaborate(self, platform):
110 m = Module()
111 m.d.comb += self.o.q_bits_known.eq(0)
112 m.d.comb += self.o.dividend_quotient.eq(self.dividend)
113 return m
114
115
116 class DivState:
117 def __init__(self, quotient_width, name):
118 self.quotient_width = quotient_width
119 self.q_bits_known = Signal(range(1 + quotient_width),
120 name=name + "_q_bits_known")
121 self.dividend_quotient = Signal(unsigned(2 * quotient_width),
122 name=name + "_dividend_quotient")
123
124 @property
125 def done(self):
126 return self.q_bits_known == self.quotient_width
127
128 @property
129 def quotient(self):
130 """ get the quotient -- requires self.done is True """
131 return self.dividend_quotient[0:self.quotient_width]
132
133 @property
134 def remainder(self):
135 """ get the remainder -- requires self.done is True """
136 return self.dividend_quotient[self.quotient_width:self.quotient_width*2]
137
138 def eq(self, rhs):
139 return [self.q_bits_known.eq(rhs.q_bits_known),
140 self.dividend_quotient.eq(rhs.dividend_quotient)]
141
142
143 class FSMDivCoreStage(Elaboratable):
144 def __init__(self, pspec: DivPipeSpec):
145 self.pspec = pspec
146 self.p = FSMDivCorePrevControl(pspec)
147 self.n = FSMDivCoreNextControl(pspec)
148 self.saved_input_data = CoreInputData(pspec)
149 self.canceled = Signal()
150 self.empty = Signal(reset=1)
151 self.saved_state = DivState(64)
152
153 def elaborate(self, platform):
154 m = Module()
155 m.submodules.p = self.p
156 m.submodules.n = self.n
157 data_i = self.p.data_i
158 data_o = self.p.data_o
159
160 # TODO: calculate self.canceled from self.p.data_i.ctx
161 m.d.comb += self.canceled.eq(False)
162
163 # TODO: adapt to refactored DivState interface
164 fsm_state_in = DivState(64)
165 divisor = Signal(unsigned(64))
166 fsm_state_out = fsm_state_in.make_next_state(m, divisor)
167
168 with m.If(self.canceled):
169 with m.If(self.p.valid_i):
170 ...
171 with m.Else():
172 ...
173 with m.Else():
174 with m.If(self.p.valid_i):
175 ...
176 with m.Else():
177 ...
178
179 return m
180
181 def __iter__(self):
182 yield from self.p
183 yield from self.n
184
185 def ports(self):
186 return list(self)