1 # IEEE Floating Point Adder (Single Precision)
2 # Copyright (C) Jonathan P Dawson 2013
8 from nmigen
import Module
, Signal
, Cat
, Const
, Mux
, Elaboratable
9 from nmigen
.cli
import main
, verilog
11 from nmutil
.singlepipe
import ControlBase
12 from nmutil
.concurrentunit
import ReservationStations
, num_bits
14 from ieee754
.fpcommon
.fpbase
import Overflow
15 from ieee754
.fpcommon
.getop
import FPADDBaseData
16 from ieee754
.fpcommon
.pack
import FPPackData
17 from ieee754
.fpcommon
.normtopack
import FPNormToPack
18 from ieee754
.fpcommon
.postcalc
import FPAddStage1Data
19 from ieee754
.fpcommon
.msbhigh
import FPMSBHigh
20 from ieee754
.fpcommon
.exphigh
import FPEXPHigh
23 from nmigen
import Module
, Signal
, Elaboratable
26 from ieee754
.fpcommon
.fpbase
import FPNumIn
, FPNumOut
, FPNumBaseRecord
27 from ieee754
.fpcommon
.fpbase
import FPState
, FPNumBase
28 from ieee754
.fpcommon
.getop
import FPPipeContext
30 from ieee754
.fpcommon
.fpbase
import FPNumDecode
, FPNumBaseRecord
31 from nmutil
.singlepipe
import SimpleHandshake
, StageChain
33 from ieee754
.fpcommon
.fpbase
import FPState
34 from ieee754
.pipeline
import PipelineSpec
37 class FPCVTFloatToIntMod(Elaboratable
):
38 """ integer to FP conversion: copes with 16/32/64 fp to 16/32/64 int/uint
40 self.ctx.i.op & 0x1 == 0x1 : SIGNED int
41 self.ctx.i.op & 0x1 == 0x0 : UNSIGNED int
43 Note: this is a single-stage conversion that goes direct to FPPackData
45 def __init__(self
, in_pspec
, out_pspec
):
46 self
.in_pspec
= in_pspec
47 self
.out_pspec
= out_pspec
52 return FPADDBaseData(self
.in_pspec
)
55 return FPPackData(self
.out_pspec
)
57 def setup(self
, m
, i
):
58 """ links module to inputs and outputs
60 m
.submodules
.upconvert
= self
61 m
.d
.comb
+= self
.i
.eq(i
)
66 def elaborate(self
, platform
):
70 # set up FP Num decoder
71 print("in_width out", self
.in_pspec
.width
,
73 a1
= FPNumBaseRecord(self
.in_pspec
.width
, False)
74 print("a1", a1
.width
, a1
.rmw
, a1
.e_width
, a1
.e_start
, a1
.e_end
)
75 m
.submodules
.sc_decode_a
= a1
= FPNumDecode(None, a1
)
76 comb
+= a1
.v
.eq(self
.i
.a
)
83 print("ms-me", ms
, me
)
85 espec
= (a1
.e_width
, True)
87 signed
= Signal(reset_less
=True)
88 comb
+= signed
.eq(self
.i
.ctx
.op
[0])
93 comb
+= self
.o
.z
.eq((1<<(mz
-1))-1) # signed NaN overflow
95 comb
+= self
.o
.z
.eq((1<<mz
)-1) # NaN overflow
97 # zero exponent: definitely out of range of INT. zero...
98 with m
.Elif(a1
.exp_n127
):
99 comb
+= self
.o
.z
.eq(0)
101 # unsigned, -ve, return 0
102 with m
.Elif((~signed
) & a1
.s
):
103 comb
+= self
.o
.z
.eq(0)
105 # signed, exp too big
106 with m
.Elif(signed
& (a1
.e
>= Const(mz
-1, espec
))):
107 with m
.If(a1
.s
): # negative FP, so negative overrun
108 comb
+= self
.o
.z
.eq(-(1<<(mz
-1)))
109 with m
.Else(): # positive FP, so positive overrun
110 comb
+= self
.o
.z
.eq((1<<(mz
-1))-1)
112 # unsigned, exp too big
113 with m
.Elif((~signed
) & (a1
.e
>= Const(mz
, espec
))):
114 with m
.If(a1
.s
): # negative FP, so negative overrun (zero)
115 comb
+= self
.o
.z
.eq(0)
116 with m
.Else(): # positive FP, so positive overrun (max INT)
117 comb
+= self
.o
.z
.eq((1<<(mz
))-1)
119 # ok exp should be in range: shift and round it
121 mlen
= max(a1
.m_width
, mz
) + 5
122 mantissa
= Signal(mlen
, reset_less
=True)
123 l
= [0] * 2 + [a1
.m
[:-1]] + [1]
124 comb
+= mantissa
[-a1
.m_width
-3:].eq(Cat(*l
))
125 comb
+= self
.o
.z
.eq(mantissa
)
128 msr
= FPEXPHigh(mlen
, espec
[0])
129 m
.submodules
.norm_exp
= msr
130 comb
+= [msr
.m_in
.eq(mantissa
),
132 msr
.ediff
.eq(Mux(signed
, mz
, mz
)-a1
.e
)
136 comb
+= of
.guard
.eq(msr
.m_out
[2])
137 comb
+= of
.round_bit
.eq(msr
.m_out
[1])
138 comb
+= of
.sticky
.eq(msr
.m_out
[0])
139 comb
+= of
.m0
.eq(msr
.m_out
[3])
141 # XXX TODO: check if this overflows the mantissa
142 mround
= Signal(mlen
, reset_less
=True)
143 with m
.If(of
.roundz
):
144 comb
+= mround
.eq(msr
.m_out
[3:]+1)
146 comb
+= mround
.eq(msr
.m_out
[3:])
149 with m
.If(signed
& a1
.s
):
150 comb
+= self
.o
.z
.eq(-mround
) # inverted
152 comb
+= self
.o
.z
.eq(mround
)
154 # copy the context (muxid, operator)
155 #comb += self.o.oz.eq(self.o.z.v)
156 comb
+= self
.o
.ctx
.eq(self
.i
.ctx
)