50c07835421ea63e2b93243525095ad128af0f80
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 nmutil
.singlepipe
import ControlBase
6 from ieee754
.div_rem_sqrt_rsqrt
.core
import DivPipeCoreOperation
9 class FSMDivCoreConfig
:
15 class FSMDivCoreInputData
:
16 def __init__(self
, core_config
, reset_less
=True):
17 self
.core_config
= core_config
18 self
.dividend
= Signal(128, reset_less
=reset_less
)
19 self
.divisor_radicand
= Signal(64, reset_less
=reset_less
)
20 self
.operation
= DivPipeCoreOperation
.create_signal(
21 reset_less
=reset_less
)
24 """ Get member signals. """
26 yield self
.divisor_radicand
30 """ Assign member signals. """
31 return [self
.dividend
.eq(rhs
.dividend
),
32 self
.divisor_radicand
.eq(rhs
.divisor_radicand
),
33 self
.operation
.eq(rhs
.operation
),
37 class FSMDivCoreOutputData
:
38 def __init__(self
, core_config
, reset_less
=True):
39 self
.core_config
= core_config
40 self
.quotient_root
= Signal(64, reset_less
=reset_less
)
41 self
.remainder
= Signal(3 * 64, reset_less
=reset_less
)
44 """ Get member signals. """
45 yield self
.quotient_root
50 """ Assign member signals. """
51 return [self
.quotient_root
.eq(rhs
.quotient_root
),
52 self
.remainder
.eq(rhs
.remainder
)]
55 class FSMDivCorePrevControl(PrevControl
):
56 def __init__(self
, pspec
):
59 self
.data_i
= CoreInputData(pspec
)
62 class FSMDivCoreNextControl(NextControl
):
63 def __init__(self
, pspec
):
66 self
.data_o
= CoreOutputData(pspec
)
69 class DivStateNext(Elaboratable
):
70 def __init__(self
, quotient_width
):
71 self
.quotient_width
= quotient_width
72 self
.i
= DivState(quotient_width
=quotient_width
, name
="i")
73 self
.divisor
= Signal(quotient_width
)
74 self
.o
= DivState(quotient_width
=quotient_width
, name
="o")
76 def elaborate(self
, platform
):
78 difference
= Signal(self
.i
.quotient_width
* 2)
79 m
.d
.comb
+= difference
.eq(self
.i
.dividend_quotient
81 << (self
.quotient_width
- 1)))
82 next_quotient_bit
= Signal()
83 m
.d
.comb
+= next_quotient_bit
.eq(
84 ~difference
[self
.quotient_width
* 2 - 1])
85 value
= Signal(self
.i
.quotient_width
* 2)
86 with m
.If(next_quotient_bit
):
87 m
.d
.comb
+= value
.eq(difference
)
89 m
.d
.comb
+= value
.eq(self
.i
.dividend_quotient
)
91 with m
.If(self
.i
.done
):
92 m
.d
.comb
+= self
.o
.eq(self
.i
)
95 self
.o
.q_bits_known
.eq(self
.i
.q_bits_known
+ 1),
96 self
.o
.dividend_quotient
.eq(Cat(next_quotient_bit
, value
))]
100 class DivStateInit(Elaboratable
):
101 def __init__(self
, quotient_width
):
102 self
.quotient_width
= quotient_width
103 self
.dividend
= Signal(quotient_width
* 2)
104 self
.o
= DivState(quotient_width
=quotient_width
, name
="o")
106 def elaborate(self
, platform
):
108 m
.d
.comb
+= self
.o
.q_bits_known
.eq(0)
109 m
.d
.comb
+= self
.o
.dividend_quotient
.eq(self
.dividend
)
114 def __init__(self
, quotient_width
, name
):
115 self
.quotient_width
= quotient_width
116 self
.q_bits_known
= Signal(range(1 + quotient_width
),
117 name
=name
+ "_q_bits_known")
118 self
.dividend_quotient
= Signal(unsigned(2 * quotient_width
),
119 name
=name
+ "_dividend_quotient")
123 return self
.q_bits_known
== self
.quotient_width
127 """ get the quotient -- requires self.done is True """
128 return self
.dividend_quotient
[0:self
.quotient_width
]
132 """ get the remainder -- requires self.done is True """
133 return self
.dividend_quotient
[self
.quotient_width
:self
.quotient_width
*2]
136 return [self
.q_bits_known
.eq(rhs
.q_bits_known
),
137 self
.dividend_quotient
.eq(rhs
.dividend_quotient
)]
140 class FSMDivCoreStage(ControlBase
):
141 def __init__(self
, pspec
):
145 self
.p
= FSMDivCorePrevControl(pspec
)
146 self
.n
= FSMDivCoreNextControl(pspec
)
147 self
.saved_input_data
= CoreInputData(pspec
)
148 self
.empty
= Signal(reset
=1)
149 self
.saved_state
= DivState(64, name
="saved_state")
150 self
.div_state_next
= DivStateNext(64)
151 self
.div_state_init
= DivStateInit(64)
152 self
.divisor
= Signal(unsigned(64))
154 def elaborate(self
, platform
):
155 m
= super().elaborate(platform
)
156 m
.submodules
.div_state_next
= self
.div_state_next
157 m
.submodules
.div_state_init
= self
.div_state_init
158 data_i
= self
.p
.data_i
159 data_o
= self
.n
.data_o
160 core_saved_i
= self
.saved_input_data
.core
162 # TODO: handle cancellation
164 m
.d
.comb
+= self
.div_state_init
.dividend
.eq(core_i
.dividend
)
166 m
.d
.comb
+= data_o
.eq_without_core(self
.saved_input_data
)
167 m
.d
.comb
+= core_o
.quotient_root
.eq(self
.div_state_next
.o
.quotient
)
168 # fract width of `DivPipeCoreOutputData.remainder`
169 remainder_fract_width
= 64 * 3
170 # fract width of `DivPipeCoreInputData.dividend`
171 dividend_fract_width
= 64 * 2
172 rem_start
= remainder_fract_width
- dividend_fract_width
173 m
.d
.comb
+= core_o
.remainder
.eq(self
.div_state_next
.o
.remainder
175 m
.d
.comb
+= self
.n
.valid_o
.eq(~self
.empty
& self
.div_state_next
.o
.done
)
176 m
.d
.comb
+= self
.p
.ready_o
.eq(self
.empty
)
177 m
.d
.sync
+= self
.saved_state
.eq(self
.div_state_next
.o
)
179 with m
.If(self
.empty
):
180 m
.d
.comb
+= self
.div_state_next
.i
.eq(self
.div_state_init
.o
)
181 m
.d
.comb
+= self
.div_state_next
.divisor
.eq(core_i
.divisor_radicand
)
182 with m
.If(self
.p
.valid_i
):
183 m
.d
.sync
+= self
.empty
.eq(0)
184 m
.d
.sync
+= self
.saved_input_data
.eq(data_i
)
187 self
.div_state_next
.i
.eq(self
.saved_state
),
188 self
.div_state_next
.divisor
.eq(core_saved_i
.divisor_radicand
)]
189 with m
.If(self
.n
.ready_i
& self
.n
.valid_o
):
190 m
.d
.sync
+= self
.empty
.eq(1)