add operand down pipeline chain
[ieee754fpu.git] / src / ieee754 / fpcommon / roundz.py
1 # IEEE Floating Point Adder (Single Precision)
2 # Copyright (C) Jonathan P Dawson 2013
3 # 2013-12-12
4
5 from nmigen import Module, Signal, Elaboratable
6 from nmigen.cli import main, verilog
7
8 from ieee754.fpcommon.fpbase import FPNumBase, FPNumBaseRecord
9 from ieee754.fpcommon.fpbase import FPState
10 from .postnormalise import FPNorm1Data
11
12
13 class FPRoundData:
14
15 def __init__(self, width, id_wid, op_wid=None):
16 self.z = FPNumBaseRecord(width, False)
17 self.mid = Signal(id_wid, reset_less=True) # multiplex ID
18 # pipeline bypass [data comes from specialcases]
19 self.out_do_z = Signal(reset_less=True)
20 self.oz = Signal(width, reset_less=True)
21 self.op_wid = op_wid
22 if op_wid:
23 self.op = Signal(op_wid, reset_less=True)
24
25 def eq(self, i):
26 ret = [self.z.eq(i.z), self.out_do_z.eq(i.out_do_z), self.oz.eq(i.oz),
27 self.mid.eq(i.mid)]
28 if self.op_wid:
29 ret.append(self.op.eq(i.op))
30 return ret
31
32
33
34 class FPRoundMod(Elaboratable):
35
36 def __init__(self, width, id_wid, op_wid=None):
37 self.width = width
38 self.id_wid = id_wid
39 self.op_wid = op_wid
40 self.i = self.ispec()
41 self.out_z = self.ospec()
42
43 def ispec(self):
44 return FPNorm1Data(self.width, self.id_wid, self.op_wid)
45
46 def ospec(self):
47 return FPRoundData(self.width, self.id_wid, self.op_wid)
48
49 def process(self, i):
50 return self.out_z
51
52 def setup(self, m, i):
53 m.submodules.roundz = self
54 m.d.comb += self.i.eq(i)
55
56 def elaborate(self, platform):
57 m = Module()
58 m.d.comb += self.out_z.eq(self.i) # copies mid, z, out_do_z
59 with m.If(~self.i.out_do_z): # bypass wasn't enabled
60 with m.If(self.i.roundz):
61 m.d.comb += self.out_z.z.m.eq(self.i.z.m + 1) # mantissa up
62 with m.If(self.i.z.m == self.i.z.m1s): # all 1s
63 m.d.comb += self.out_z.z.e.eq(self.i.z.e + 1) # exponent up
64
65 return m
66
67
68 class FPRound(FPState):
69
70 def __init__(self, width, id_wid):
71 FPState.__init__(self, "round")
72 self.mod = FPRoundMod(width)
73 self.out_z = self.ospec()
74
75 def ispec(self):
76 return self.mod.ispec()
77
78 def ospec(self):
79 return self.mod.ospec()
80
81 def setup(self, m, i):
82 """ links module to inputs and outputs
83 """
84 self.mod.setup(m, i)
85
86 self.idsync(m)
87 m.d.sync += self.out_z.eq(self.mod.out_z)
88 m.d.sync += self.out_z.mid.eq(self.mod.o.mid)
89
90 def action(self, m):
91 m.next = "corrections"