bc60a55a9ce4db149b050635d180e6d9faac1702
[ieee754fpu.git] / src / ieee754 / fpcommon / getop.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.lib.coding import PriorityEncoder
7 from nmigen.cli import main, verilog
8 from math import log
9
10 from ieee754.fpcommon.fpbase import FPOpIn, FPBase, FPNumBase
11 from nmutil.singlepipe import PrevControl
12
13 from nmutil import nmoperator
14
15
16 class FPGetOpMod(Elaboratable):
17 def __init__(self, width):
18 self.in_op = FPOpIn(width)
19 self.in_op.data_i = Signal(width)
20 self.out_op = Signal(width)
21 self.out_decode = Signal(reset_less=True)
22
23 def elaborate(self, platform):
24 m = Module()
25 m.d.comb += self.out_decode.eq((self.in_op.ready_o) & \
26 (self.in_op.valid_i_test))
27 m.submodules.get_op_in = self.in_op
28 with m.If(self.out_decode):
29 m.d.comb += [
30 self.out_op.eq(self.in_op.v),
31 ]
32 return m
33
34
35 class FPNumBase2Ops:
36
37 def __init__(self, width, id_wid, m_extra=True):
38 self.a = FPNumBase(width, m_extra)
39 self.b = FPNumBase(width, m_extra)
40 self.muxid = Signal(id_wid, reset_less=True)
41
42 def eq(self, i):
43 return [self.a.eq(i.a), self.b.eq(i.b), self.muxid.eq(i.muxid)]
44
45 def ports(self):
46 return [self.a, self.b, self.muxid]
47
48
49 class FPPipeContext:
50
51 def __init__(self, pspec):
52 """ creates a pipeline context. currently: operator (op) and muxid
53
54 opkls (within pspec) - the class to create that will be the
55 "operator". instance must have an "eq"
56 function.
57 """
58 self.id_wid = pspec.id_wid
59 self.op_wid = pspec.op_wid
60 self.muxid = Signal(self.id_wid, reset_less=True) # RS multiplex ID
61 opkls = pspec.opkls
62 if opkls is None:
63 self.op = Signal(self.op_wid, reset_less=True)
64 else:
65 self.op = opkls(pspec)
66
67 def eq(self, i):
68 ret = [self.muxid.eq(i.muxid)]
69 ret.append(self.op.eq(i.op))
70 return ret
71
72 def __iter__(self):
73 yield self.muxid
74 yield self.op
75
76 def ports(self):
77 return list(self)
78
79
80 class FPADDBaseData:
81
82 def __init__(self, pspec, n_ops=2):
83 width = pspec.width
84 self.ctx = FPPipeContext(pspec)
85 ops = []
86 for i in range(n_ops):
87 name = chr(ord("a")+i)
88 operand = Signal(width, name=name)
89 setattr(self, name, operand)
90 ops.append(operand)
91 self.muxid = self.ctx.muxid # make muxid available here: complicated
92 self.ops = ops
93
94 def eq(self, i):
95 ret = []
96 for op1, op2 in zip(self.ops, i.ops):
97 ret.append(op1.eq(op2))
98 ret.append(self.ctx.eq(i.ctx))
99 return ret
100
101 def __iter__(self):
102 if self.ops:
103 yield from self.ops
104 yield from self.ctx
105
106 def ports(self):
107 return list(self)
108
109
110 class FPGet2OpMod(PrevControl):
111 def __init__(self, width, id_wid, op_wid=None):
112 PrevControl.__init__(self)
113 self.width = width
114 self.id_wid = id_wid
115 self.data_i = self.ispec()
116 self.i = self.data_i
117 self.o = self.ospec()
118
119 def ispec(self):
120 return FPADDBaseData(self.width, self.id_wid, self.op_wid)
121
122 def ospec(self):
123 return FPADDBaseData(self.width, self.id_wid, self.op_wid)
124
125 def process(self, i):
126 return self.o
127
128 def elaborate(self, platform):
129 m = PrevControl.elaborate(self, platform)
130 with m.If(self.trigger):
131 m.d.comb += [
132 self.o.eq(self.data_i),
133 ]
134 return m
135
136