1 # IEEE Floating Point Adder (Single Precision)
2 # Copyright (C) Jonathan P Dawson 2013
5 from nmigen
import Module
, Signal
, Cat
, Const
, Elaboratable
6 from nmigen
.cli
import main
, verilog
8 from nmutil
.singlepipe
import ControlBase
9 from nmutil
.concurrentunit
import ReservationStations
, num_bits
11 from ieee754
.fpcommon
.getop
import FPADDBaseData
12 from ieee754
.fpcommon
.pack
import FPPackData
13 from ieee754
.fpcommon
.normtopack
import FPNormToPack
14 from ieee754
.fpcommon
.postcalc
import FPAddStage1Data
15 from ieee754
.fpcommon
.msbhigh
import FPMSBHigh
16 from ieee754
.fpcommon
.fpbase
import MultiShiftRMerge
19 from nmigen
import Module
, Signal
, Elaboratable
22 from ieee754
.fpcommon
.fpbase
import FPNumIn
, FPNumOut
, FPNumBaseRecord
23 from ieee754
.fpcommon
.fpbase
import FPState
, FPNumBase
24 from ieee754
.fpcommon
.getop
import FPPipeContext
26 from ieee754
.fpcommon
.fpbase
import FPNumDecode
, FPNumBaseRecord
27 from nmutil
.singlepipe
import SimpleHandshake
, StageChain
29 from ieee754
.fpcommon
.fpbase
import FPState
30 from ieee754
.pipeline
import PipelineSpec
35 self
.signed
= Signal(reset_less
=True)
38 return [self
.signed
.eq(i
)]
41 class FPCVTFloatToIntMod(Elaboratable
):
42 """ integer to FP conversion: copes with 16/32/64 fp to 16/32/64 int/uint
44 self.ctx.i.op & 0x1 == 0x1 : SIGNED int
45 self.ctx.i.op & 0x1 == 0x0 : UNSIGNED int
47 Note: this is a single-stage conversion that goes direct to FPPackData
49 def __init__(self
, in_pspec
, out_pspec
):
50 self
.in_pspec
= in_pspec
51 self
.out_pspec
= out_pspec
56 return FPADDBaseData(self
.in_pspec
)
59 return FPPackData(self
.out_pspec
)
61 def setup(self
, m
, i
):
62 """ links module to inputs and outputs
64 m
.submodules
.upconvert
= self
65 m
.d
.comb
+= self
.i
.eq(i
)
70 def elaborate(self
, platform
):
73 #m.submodules.sc_out_z = self.o.z
75 # decode: XXX really should move to separate stage
76 print("in_width out", self
.in_pspec
.width
,
78 a1
= FPNumBaseRecord(self
.in_pspec
.width
, False)
79 print("a1", a1
.width
, a1
.rmw
, a1
.e_width
, a1
.e_start
, a1
.e_end
)
80 m
.submodules
.sc_decode_a
= a1
= FPNumDecode(None, a1
)
81 m
.d
.comb
+= a1
.v
.eq(self
.i
.a
)
88 print("ms-me", ms
, me
)
90 espec
= (len(a1
.e_width
), True)
91 ediff_intwid
= Signal(espec
, reset_less
=True)
93 # conversion can mostly be done manually...
94 m
.d
.comb
+= self
.o
.z
.s
.eq(a1
.s
)
95 m
.d
.comb
+= self
.o
.z
.e
.eq(a1
.e
)
96 m
.d
.comb
+= self
.o
.z
.m
[ms
:].eq(a1
.m
)
97 m
.d
.comb
+= self
.o
.z
.create(a1
.s
, a1
.e
, self
.o
.z
.m
) # ... here
99 signed
= Signal(reset_less
=True)
100 m
.d
.comb
+= signed
.eq(self
.i
.ctx
.op
[0])
103 with m
.If(a1
.exp_n127
):
104 m
.d
.comb
+= self
.o
.z
.eq(0)
106 # signed, exp too big
107 with m
.Elif(signed
& (a1
.e
> Const(mz
-1, espec
))):
108 with m
.If(a1
.s
): # negative FP, so negative overrun
109 m
.d
.comb
+= self
.o
.z
.eq(-(1<<(mz
-1)))
110 with m
.Else(): # positive FP, so positive overrun
111 m
.d
.comb
+= self
.o
.z
.eq((1<<(mz
-1)-1))
113 # unsigned, exp too big
114 with m
.Elif((~signed
) & (a1
.e
> Const(mz
, espec
))):
115 with m
.If(a1
.s
): # negative FP, so negative overrun (zero)
116 m
.d
.comb
+= self
.o
.z
.eq(0)
117 with m
.Else(): # positive FP, so positive overrun (max INT)
118 m
.d
.comb
+= self
.o
.z
.eq((1<<(mz
)-1))
120 # ok exp should be in range: shift it...
122 mantissa
= Signal(z1
, reset_less
=True)
123 l
= [0] * ms
+ [1] + a1
.m
124 m
.d
.comb
+= mantissa
.eq(Cat(*l
) >> a1
.e
)
125 m
.d
.comb
+= self
.o
.z
.eq(mantissa
)
127 # copy the context (muxid, operator)
128 m
.d
.comb
+= self
.o
.oz
.eq(self
.o
.z
.v
)
129 m
.d
.comb
+= self
.o
.ctx
.eq(self
.i
.ctx
)
134 class FPCVTIntToFloatMod(Elaboratable
):
135 """ FP integer conversion: copes with 16/32/64 int to 16/32/64 fp.
137 self.ctx.i.op & 0x1 == 0x1 : SIGNED int
138 self.ctx.i.op & 0x1 == 0x0 : UNSIGNED int
140 def __init__(self
, in_pspec
, out_pspec
):
141 self
.in_pspec
= in_pspec
142 self
.out_pspec
= out_pspec
143 self
.i
= self
.ispec()
144 self
.o
= self
.ospec()
147 return FPADDBaseData(self
.in_pspec
)
150 return FPAddStage1Data(self
.out_pspec
, e_extra
=True)
152 def setup(self
, m
, i
):
153 """ links module to inputs and outputs
155 m
.submodules
.intconvert
= self
156 m
.d
.comb
+= self
.i
.eq(i
)
158 def process(self
, i
):
161 def elaborate(self
, platform
):
164 #m.submodules.sc_out_z = self.o.z
166 # decode: XXX really should move to separate stage
167 print("in_width out", self
.in_pspec
.width
,
168 self
.out_pspec
.width
)
169 print("a1", self
.in_pspec
.width
)
171 print("z1", z1
.width
, z1
.rmw
, z1
.e_width
, z1
.e_start
, z1
.e_end
)
173 me
= self
.in_pspec
.width
176 print("ms-me", ms
, me
, mz
)
178 # 3 extra bits for guard/round/sticky
179 msb
= FPMSBHigh(me
+3, z1
.e_width
)
180 m
.submodules
.norm_msb
= msb
182 # signed or unsigned, use operator context
183 signed
= Signal(reset_less
=True)
184 m
.d
.comb
+= signed
.eq(self
.i
.ctx
.op
[0])
186 # copy of mantissa (one less bit if signed)
187 mantissa
= Signal(me
, reset_less
=True)
189 # detect signed/unsigned. key case: -ve numbers need inversion
190 # to +ve because the FP sign says if it's -ve or not.
192 m
.d
.comb
+= z1
.s
.eq(self
.i
.a
[-1]) # sign in top bit of a
194 m
.d
.comb
+= mantissa
.eq(-self
.i
.a
) # invert input if sign -ve
196 m
.d
.comb
+= mantissa
.eq(self
.i
.a
) # leave as-is
198 m
.d
.comb
+= mantissa
.eq(self
.i
.a
) # unsigned, use full a
199 m
.d
.comb
+= z1
.s
.eq(0)
201 # set input from full INT
202 m
.d
.comb
+= msb
.m_in
.eq(Cat(0, 0, 0, mantissa
)) # g/r/s + input
203 m
.d
.comb
+= msb
.e_in
.eq(me
) # exp = int width
205 # to do with FP16... not yet resolved why
209 m
.d
.comb
+= z1
.e
.eq(msb
.e_out
-1)
210 mmsb
= msb
.m_out
[-mz
-1:]
212 # larger int to smaller FP (uint32/64 -> fp16 most likely)
213 m
.d
.comb
+= z1
.m
[ms
-1:].eq(mmsb
)
214 else: # 32? XXX weirdness...
215 m
.d
.comb
+= z1
.m
.eq(mmsb
)
217 # smaller int to larger FP
218 m
.d
.comb
+= z1
.e
.eq(msb
.e_out
)
219 m
.d
.comb
+= z1
.m
[ms
:].eq(msb
.m_out
[3:])
220 m
.d
.comb
+= z1
.create(z1
.s
, z1
.e
, z1
.m
) # ... here
222 # note: post-normalisation actually appears to be capable of
223 # detecting overflow to infinity (FPPackMod). so it's ok to
224 # drop the bits into the mantissa (with a fixed exponent),
225 # do some rounding (which might result in exceeding the
226 # range of the target FP by re-increasing the exponent),
227 # and basically *not* have to do any kind of range-checking
228 # here: just set up guard/round/sticky, drop the INT into the
229 # mantissa, and away we go. XXX TODO: see if FPNormaliseMod
230 # is even necessary. it probably isn't
232 # initialise rounding (but only activate if needed)
234 # larger int to smaller FP (uint32/64 -> fp16 most likely)
235 m
.d
.comb
+= self
.o
.of
.guard
.eq(msb
.m_out
[-mz
-2])
236 m
.d
.comb
+= self
.o
.of
.round_bit
.eq(msb
.m_out
[-mz
-3])
237 m
.d
.comb
+= self
.o
.of
.sticky
.eq(msb
.m_out
[:-mz
-3].bool())
238 m
.d
.comb
+= self
.o
.of
.m0
.eq(msb
.m_out
[-mz
-1])
240 # smaller int to larger FP
241 m
.d
.comb
+= self
.o
.of
.guard
.eq(msb
.m_out
[2])
242 m
.d
.comb
+= self
.o
.of
.round_bit
.eq(msb
.m_out
[1])
243 m
.d
.comb
+= self
.o
.of
.sticky
.eq(msb
.m_out
[:1].bool())
244 m
.d
.comb
+= self
.o
.of
.m0
.eq(msb
.m_out
[3])
246 # special cases active by default
247 m
.d
.comb
+= self
.o
.out_do_z
.eq(1)
250 with m
.If(~self
.i
.a
.bool()):
251 m
.d
.comb
+= self
.o
.z
.zero(0)
253 m
.d
.comb
+= self
.o
.out_do_z
.eq(0) # activate normalisation
255 # copy the context (muxid, operator)
256 m
.d
.comb
+= self
.o
.oz
.eq(self
.o
.z
.v
)
257 m
.d
.comb
+= self
.o
.ctx
.eq(self
.i
.ctx
)
262 class FPCVTUpConvertMod(Elaboratable
):
263 """ FP up-conversion (lower to higher bitwidth)
265 def __init__(self
, in_pspec
, out_pspec
):
266 self
.in_pspec
= in_pspec
267 self
.out_pspec
= out_pspec
268 self
.i
= self
.ispec()
269 self
.o
= self
.ospec()
272 return FPADDBaseData(self
.in_pspec
)
275 return FPAddStage1Data(self
.out_pspec
, e_extra
=False)
277 def setup(self
, m
, i
):
278 """ links module to inputs and outputs
280 m
.submodules
.upconvert
= self
281 m
.d
.comb
+= self
.i
.eq(i
)
283 def process(self
, i
):
286 def elaborate(self
, platform
):
289 #m.submodules.sc_out_z = self.o.z
291 # decode: XXX really should move to separate stage
292 print("in_width out", self
.in_pspec
.width
,
293 self
.out_pspec
.width
)
294 a1
= FPNumBaseRecord(self
.in_pspec
.width
, False)
295 print("a1", a1
.width
, a1
.rmw
, a1
.e_width
, a1
.e_start
, a1
.e_end
)
296 m
.submodules
.sc_decode_a
= a1
= FPNumDecode(None, a1
)
297 m
.d
.comb
+= a1
.v
.eq(self
.i
.a
)
299 print("z1", z1
.width
, z1
.rmw
, z1
.e_width
, z1
.e_start
, z1
.e_end
)
302 ms
= self
.o
.z
.rmw
- a1
.rmw
303 print("ms-me", ms
, me
, self
.o
.z
.rmw
, a1
.rmw
)
305 # conversion can mostly be done manually...
306 m
.d
.comb
+= self
.o
.z
.s
.eq(a1
.s
)
307 m
.d
.comb
+= self
.o
.z
.e
.eq(a1
.e
)
308 m
.d
.comb
+= self
.o
.z
.m
[ms
:].eq(a1
.m
)
309 m
.d
.comb
+= self
.o
.z
.create(a1
.s
, a1
.e
, self
.o
.z
.m
) # ... here
311 # initialise rounding to all zeros (deactivate)
312 m
.d
.comb
+= self
.o
.of
.guard
.eq(0)
313 m
.d
.comb
+= self
.o
.of
.round_bit
.eq(0)
314 m
.d
.comb
+= self
.o
.of
.sticky
.eq(0)
315 m
.d
.comb
+= self
.o
.of
.m0
.eq(a1
.m
[0])
317 # most special cases active (except tiny-number normalisation, below)
318 m
.d
.comb
+= self
.o
.out_do_z
.eq(1)
320 # detect NaN/Inf first
321 with m
.If(a1
.exp_128
):
322 with m
.If(~a1
.m_zero
):
323 m
.d
.comb
+= self
.o
.z
.nan(0) # RISC-V wants normalised NaN
325 m
.d
.comb
+= self
.o
.z
.inf(a1
.s
) # RISC-V wants signed INF
327 with m
.If(a1
.exp_n127
):
328 with m
.If(~a1
.m_zero
):
329 m
.d
.comb
+= self
.o
.z
.m
[ms
:].eq(Cat(0, a1
.m
))
330 m
.d
.comb
+= self
.o
.out_do_z
.eq(0) # activate normalisation
332 # RISC-V zero needs actual zero
333 m
.d
.comb
+= self
.o
.z
.zero(a1
.s
)
335 # copy the context (muxid, operator)
336 m
.d
.comb
+= self
.o
.oz
.eq(self
.o
.z
.v
)
337 m
.d
.comb
+= self
.o
.ctx
.eq(self
.i
.ctx
)
342 class FPCVTDownConvertMod(Elaboratable
):
343 """ FP down-conversion (higher to lower bitwidth)
345 def __init__(self
, in_pspec
, out_pspec
):
346 self
.in_pspec
= in_pspec
347 self
.out_pspec
= out_pspec
348 self
.i
= self
.ispec()
349 self
.o
= self
.ospec()
352 return FPADDBaseData(self
.in_pspec
)
355 return FPAddStage1Data(self
.out_pspec
, e_extra
=True)
357 def setup(self
, m
, i
):
358 """ links module to inputs and outputs
360 m
.submodules
.downconvert
= self
361 m
.d
.comb
+= self
.i
.eq(i
)
363 def process(self
, i
):
366 def elaborate(self
, platform
):
369 #m.submodules.sc_out_z = self.o.z
371 # decode: XXX really should move to separate stage
372 print("in_width out", self
.in_pspec
.width
,
373 self
.out_pspec
.width
)
374 a1
= FPNumBaseRecord(self
.in_pspec
.width
, False)
375 print("a1", a1
.width
, a1
.rmw
, a1
.e_width
, a1
.e_start
, a1
.e_end
)
376 m
.submodules
.sc_decode_a
= a1
= FPNumDecode(None, a1
)
377 m
.d
.comb
+= a1
.v
.eq(self
.i
.a
)
379 print("z1", z1
.width
, z1
.rmw
, z1
.e_width
, z1
.e_start
, z1
.e_end
)
382 ms
= a1
.rmw
- self
.o
.z
.rmw
383 print("ms-me", ms
, me
)
386 exp_sub_n126
= Signal((a1
.e_width
, True), reset_less
=True)
387 exp_gt127
= Signal(reset_less
=True)
388 # constants from z1, at the bit-width of a1.
389 N126
= Const(z1
.fp
.N126
.value
, (a1
.e_width
, True))
390 P127
= Const(z1
.fp
.P127
.value
, (a1
.e_width
, True))
391 m
.d
.comb
+= exp_sub_n126
.eq(a1
.e
- N126
)
392 m
.d
.comb
+= exp_gt127
.eq(a1
.e
> P127
)
394 # if a zero, return zero (signed)
395 with m
.If(a1
.exp_n127
):
396 m
.d
.comb
+= self
.o
.z
.zero(a1
.s
)
397 m
.d
.comb
+= self
.o
.out_do_z
.eq(1)
399 # if a range outside z's min range (-126)
400 with m
.Elif(exp_sub_n126
< 0):
401 m
.d
.comb
+= self
.o
.of
.guard
.eq(a1
.m
[ms
-1])
402 m
.d
.comb
+= self
.o
.of
.round_bit
.eq(a1
.m
[ms
-2])
403 m
.d
.comb
+= self
.o
.of
.sticky
.eq(a1
.m
[:ms
-2].bool())
404 m
.d
.comb
+= self
.o
.of
.m0
.eq(a1
.m
[ms
]) # bit of a1
406 m
.d
.comb
+= self
.o
.z
.s
.eq(a1
.s
)
407 m
.d
.comb
+= self
.o
.z
.e
.eq(a1
.e
)
408 m
.d
.comb
+= self
.o
.z
.m
.eq(a1
.m
[-self
.o
.z
.rmw
-1:])
409 m
.d
.comb
+= self
.o
.z
.m
[-1].eq(1)
411 # if a is inf return inf
412 with m
.Elif(a1
.is_inf
):
413 m
.d
.comb
+= self
.o
.z
.inf(a1
.s
)
414 m
.d
.comb
+= self
.o
.out_do_z
.eq(1)
416 # if a is NaN return NaN
417 with m
.Elif(a1
.is_nan
):
418 m
.d
.comb
+= self
.o
.z
.nan(0)
419 m
.d
.comb
+= self
.o
.out_do_z
.eq(1)
421 # if a mantissa greater than 127, return inf
422 with m
.Elif(exp_gt127
):
423 print("inf", self
.o
.z
.inf(a1
.s
))
424 m
.d
.comb
+= self
.o
.z
.inf(a1
.s
)
425 m
.d
.comb
+= self
.o
.out_do_z
.eq(1)
427 # ok after all that, anything else should fit fine (whew)
429 m
.d
.comb
+= self
.o
.of
.guard
.eq(a1
.m
[ms
-1])
430 m
.d
.comb
+= self
.o
.of
.round_bit
.eq(a1
.m
[ms
-2])
431 m
.d
.comb
+= self
.o
.of
.sticky
.eq(a1
.m
[:ms
-2].bool())
432 m
.d
.comb
+= self
.o
.of
.m0
.eq(a1
.m
[ms
]) # bit of a1
434 # XXX TODO: this is basically duplicating FPRoundMod. hmmm...
435 print("alen", a1
.e_start
, z1
.fp
.N126
, N126
)
436 print("m1", self
.o
.z
.rmw
, a1
.m
[-self
.o
.z
.rmw
-1:])
437 mo
= Signal(self
.o
.z
.m_width
-1)
438 m
.d
.comb
+= mo
.eq(a1
.m
[ms
:me
])
439 with m
.If(self
.o
.of
.roundz
):
440 with m
.If((~mo
== 0)): # all 1s
441 m
.d
.comb
+= self
.o
.z
.create(a1
.s
, a1
.e
+1, mo
+1)
443 m
.d
.comb
+= self
.o
.z
.create(a1
.s
, a1
.e
, mo
+1)
445 m
.d
.comb
+= self
.o
.z
.create(a1
.s
, a1
.e
, a1
.m
[-self
.o
.z
.rmw
-1:])
446 m
.d
.comb
+= self
.o
.out_do_z
.eq(1)
448 # copy the context (muxid, operator)
449 m
.d
.comb
+= self
.o
.oz
.eq(self
.o
.z
.v
)
450 m
.d
.comb
+= self
.o
.ctx
.eq(self
.i
.ctx
)
455 class FPCVTIntToFloat(FPState
):
459 def __init__(self
, in_width
, out_width
, id_wid
):
460 FPState
.__init
__(self
, "inttofloat")
461 self
.mod
= FPCVTIntToFloatMod(in_width
, out_width
)
462 self
.out_z
= self
.mod
.ospec()
463 self
.out_do_z
= Signal(reset_less
=True)
465 def setup(self
, m
, i
):
466 """ links module to inputs and outputs
468 self
.mod
.setup(m
, i
, self
.out_do_z
)
469 m
.d
.sync
+= self
.out_z
.v
.eq(self
.mod
.out_z
.v
) # only take the output
470 m
.d
.sync
+= self
.out_z
.ctx
.eq(self
.mod
.o
.ctx
) # (and context)
474 with m
.If(self
.out_do_z
):
477 m
.next
= "denormalise"
480 class FPCVTUpConvert(FPState
):
484 def __init__(self
, in_width
, out_width
, id_wid
):
485 FPState
.__init
__(self
, "upconvert")
486 self
.mod
= FPCVTUpConvertMod(in_width
, out_width
)
487 self
.out_z
= self
.mod
.ospec()
488 self
.out_do_z
= Signal(reset_less
=True)
490 def setup(self
, m
, i
):
491 """ links module to inputs and outputs
493 self
.mod
.setup(m
, i
, self
.out_do_z
)
494 m
.d
.sync
+= self
.out_z
.v
.eq(self
.mod
.out_z
.v
) # only take the output
495 m
.d
.sync
+= self
.out_z
.ctx
.eq(self
.mod
.o
.ctx
) # (and context)
499 with m
.If(self
.out_do_z
):
502 m
.next
= "denormalise"
505 class FPCVTDownConvert(FPState
):
506 """ special cases: NaNs, infs, zeros, denormalised
509 def __init__(self
, in_width
, out_width
, id_wid
):
510 FPState
.__init
__(self
, "special_cases")
511 self
.mod
= FPCVTDownConvertMod(in_width
, out_width
)
512 self
.out_z
= self
.mod
.ospec()
513 self
.out_do_z
= Signal(reset_less
=True)
515 def setup(self
, m
, i
):
516 """ links module to inputs and outputs
518 self
.mod
.setup(m
, i
, self
.out_do_z
)
519 m
.d
.sync
+= self
.out_z
.v
.eq(self
.mod
.out_z
.v
) # only take the output
520 m
.d
.sync
+= self
.out_z
.ctx
.eq(self
.mod
.o
.ctx
) # (and context)
524 with m
.If(self
.out_do_z
):
527 m
.next
= "denormalise"
530 class FPCVTIntToFloatDeNorm(FPState
, SimpleHandshake
):
534 def __init__(self
, in_pspec
, out_pspec
):
535 FPState
.__init
__(self
, "inttofloat")
536 sc
= FPCVTIntToFloatMod(in_pspec
, out_pspec
)
537 SimpleHandshake
.__init
__(self
, sc
)
538 self
.out
= self
.ospec(None)
541 class FPCVTUpConvertDeNorm(FPState
, SimpleHandshake
):
545 def __init__(self
, in_pspec
, out_pspec
):
546 FPState
.__init
__(self
, "upconvert")
547 sc
= FPCVTUpConvertMod(in_pspec
, out_pspec
)
548 SimpleHandshake
.__init
__(self
, sc
)
549 self
.out
= self
.ospec(None)
552 class FPCVTDownConvertDeNorm(FPState
, SimpleHandshake
):
556 def __init__(self
, in_pspec
, out_pspec
):
557 FPState
.__init
__(self
, "downconvert")
558 sc
= FPCVTDownConvertMod(in_pspec
, out_pspec
)
559 SimpleHandshake
.__init
__(self
, sc
)
560 self
.out
= self
.ospec(None)
563 class FPCVTIntBasePipe(ControlBase
):
564 def __init__(self
, in_pspec
, out_pspec
):
565 ControlBase
.__init
__(self
)
566 self
.pipe1
= FPCVTIntToFloatDeNorm(in_pspec
, out_pspec
)
567 self
.pipe2
= FPNormToPack(out_pspec
, e_extra
=True)
569 self
._eqs
= self
.connect([self
.pipe1
, self
.pipe2
])
571 def elaborate(self
, platform
):
572 m
= ControlBase
.elaborate(self
, platform
)
573 m
.submodules
.toint
= self
.pipe1
574 m
.submodules
.normpack
= self
.pipe2
575 m
.d
.comb
+= self
._eqs
579 class FPCVTUpBasePipe(ControlBase
):
580 def __init__(self
, in_pspec
, out_pspec
):
581 ControlBase
.__init
__(self
)
582 self
.pipe1
= FPCVTUpConvertDeNorm(in_pspec
, out_pspec
)
583 self
.pipe2
= FPNormToPack(out_pspec
, e_extra
=False)
585 self
._eqs
= self
.connect([self
.pipe1
, self
.pipe2
])
587 def elaborate(self
, platform
):
588 m
= ControlBase
.elaborate(self
, platform
)
589 m
.submodules
.up
= self
.pipe1
590 m
.submodules
.normpack
= self
.pipe2
591 m
.d
.comb
+= self
._eqs
595 class FPCVTDownBasePipe(ControlBase
):
596 def __init__(self
, in_pspec
, out_pspec
):
597 ControlBase
.__init
__(self
)
598 self
.pipe1
= FPCVTDownConvertDeNorm(in_pspec
, out_pspec
)
599 self
.pipe2
= FPNormToPack(out_pspec
, e_extra
=True)
601 self
._eqs
= self
.connect([self
.pipe1
, self
.pipe2
])
603 def elaborate(self
, platform
):
604 m
= ControlBase
.elaborate(self
, platform
)
605 m
.submodules
.down
= self
.pipe1
606 m
.submodules
.normpack
= self
.pipe2
607 m
.d
.comb
+= self
._eqs
611 class FPCVTIntMuxInOut(ReservationStations
):
612 """ Reservation-Station version of FPCVT int-to-float pipeline.
614 * fan-in on inputs (an array of FPADDBaseData: a,b,mid)
615 * 2-stage multiplier pipeline
616 * fan-out on outputs (an array of FPPackData: z,mid)
618 Fan-in and Fan-out are combinatorial.
621 def __init__(self
, in_width
, out_width
, num_rows
, op_wid
=0):
623 self
.id_wid
= num_bits(in_width
)
624 self
.out_id_wid
= num_bits(out_width
)
626 self
.in_pspec
= PipelineSpec(in_width
, self
.id_wid
, self
.op_wid
)
627 self
.out_pspec
= PipelineSpec(out_width
, self
.out_id_wid
, op_wid
)
629 self
.alu
= FPCVTIntBasePipe(self
.in_pspec
, self
.out_pspec
)
630 ReservationStations
.__init
__(self
, num_rows
)
633 return FPADDBaseData(self
.in_pspec
)
636 return FPPackData(self
.out_pspec
)
639 class FPCVTUpMuxInOut(ReservationStations
):
640 """ Reservation-Station version of FPCVT up pipeline.
642 * fan-in on inputs (an array of FPADDBaseData: a,b,mid)
643 * 2-stage multiplier pipeline
644 * fan-out on outputs (an array of FPPackData: z,mid)
646 Fan-in and Fan-out are combinatorial.
649 def __init__(self
, in_width
, out_width
, num_rows
, op_wid
=0):
651 self
.id_wid
= num_bits(in_width
)
652 self
.out_id_wid
= num_bits(out_width
)
654 self
.in_pspec
= PipelineSpec(in_width
, self
.id_wid
, self
.op_wid
)
655 self
.out_pspec
= PipelineSpec(out_width
, self
.out_id_wid
, op_wid
)
657 self
.alu
= FPCVTUpBasePipe(self
.in_pspec
, self
.out_pspec
)
658 ReservationStations
.__init
__(self
, num_rows
)
661 return FPADDBaseData(self
.in_pspec
)
664 return FPPackData(self
.out_pspec
)
667 class FPCVTDownMuxInOut(ReservationStations
):
668 """ Reservation-Station version of FPCVT pipeline.
670 * fan-in on inputs (an array of FPADDBaseData: a,b,mid)
671 * 2-stage multiplier pipeline
672 * fan-out on outputs (an array of FPPackData: z,mid)
674 Fan-in and Fan-out are combinatorial.
677 def __init__(self
, in_width
, out_width
, num_rows
, op_wid
=0):
679 self
.id_wid
= num_bits(in_width
)
680 self
.out_id_wid
= num_bits(out_width
)
682 self
.in_pspec
= PipelineSpec(in_width
, self
.id_wid
, self
.op_wid
)
683 self
.out_pspec
= PipelineSpec(out_width
, self
.out_id_wid
, op_wid
)
685 self
.alu
= FPCVTDownBasePipe(self
.in_pspec
, self
.out_pspec
)
686 ReservationStations
.__init
__(self
, num_rows
)
689 return FPADDBaseData(self
.in_pspec
)
692 return FPPackData(self
.out_pspec
)