# Copyright (C) Jonathan P Dawson 2013
# 2013-12-12
-from nmigen import Module, Signal, Cat, Mux, Array
+from nmigen import Module, Signal, Cat, Mux, Array, Const
from nmigen.lib.coding import PriorityEncoder
from nmigen.cli import main, verilog
+from math import log
from fpbase import FPNumIn, FPNumOut, FPOp, Overflow, FPBase, FPNumBase
from fpbase import MultiShiftRMerge, Trigger
#from fpbase import FPNumShiftMultiRight
+
class FPState(FPBase):
def __init__(self, state_from):
self.state_from = state_from
setattr(self, k, v)
+class FPGetSyncOpsMod:
+ def __init__(self, width, num_ops=2):
+ self.width = width
+ self.num_ops = num_ops
+ inops = []
+ outops = []
+ for i in range(num_ops):
+ inops.append(Signal(width, reset_less=True))
+ outops.append(Signal(width, reset_less=True))
+ self.in_op = inops
+ self.out_op = outops
+ self.stb = Signal(num_ops)
+ self.ack = Signal()
+ self.ready = Signal(reset_less=True)
+ self.out_decode = Signal(reset_less=True)
+
+ def elaborate(self, platform):
+ m = Module()
+ m.d.comb += self.ready.eq(self.stb == Const(-1, (self.num_ops, False)))
+ m.d.comb += self.out_decode.eq(self.ack & self.ready)
+ with m.If(self.out_decode):
+ for i in range(self.num_ops):
+ m.d.comb += [
+ self.out_op[i].eq(self.in_op[i]),
+ ]
+ return m
+
+ def ports(self):
+ return self.in_op + self.out_op + [self.stb, self.ack]
+
+
+class FPOps(Trigger):
+ def __init__(self, width, num_ops):
+ Trigger.__init__(self)
+ self.width = width
+ self.num_ops = num_ops
+
+ res = []
+ for i in range(num_ops):
+ res.append(Signal(width))
+ self.v = Array(res)
+
+ def ports(self):
+ res = []
+ for i in range(self.num_ops):
+ res.append(self.v[i])
+ res.append(self.ack)
+ res.append(self.stb)
+ return res
+
+
+class InputGroup:
+ def __init__(self, width, num_ops=2, num_rows=4):
+ self.width = width
+ self.num_ops = num_ops
+ self.num_rows = num_rows
+ self.mmax = int(log(self.num_rows) / log(2))
+ self.rs = []
+ self.mid = Signal(self.mmax, reset_less=True) # multiplex id
+ for i in range(num_rows):
+ self.rs.append(FPGetSyncOpsMod(width, num_ops))
+ self.rs = Array(self.rs)
+
+ self.out_op = FPOps(width, num_ops)
+
+ def elaborate(self, platform):
+ m = Module()
+
+ pe = PriorityEncoder(self.num_rows)
+ m.submodules.selector = pe
+ m.submodules.out_op = self.out_op
+ m.submodules += self.rs
+
+ # connect priority encoder
+ in_ready = []
+ for i in range(self.num_rows):
+ in_ready.append(self.rs[i].ready)
+ m.d.comb += pe.i.eq(Cat(*in_ready))
+ m.d.comb += self.out_op.stb.eq(pe.n) # strobe-out when encoder active
+
+ with m.If(pe.n):
+ m.d.sync += self.mid.eq(pe.o)
+ for j in range(self.num_ops):
+ m.d.sync += self.out_op.v[j].eq(self.rs[pe.o].out_op[j])
+ return m
+
+ def ports(self):
+ res = []
+ for i in range(self.num_rows):
+ inop = self.rs[i]
+ res += inop.in_op + [inop.stb]
+ return self.out_op.ports() + res #+ [self.ack + self.stb]
+
+
class FPGetOpMod:
def __init__(self, width):
self.in_op = FPOp(width)
class FPPutZ(FPState):
- def __init__(self, state, in_z, out_z, in_mid, out_mid):
+ def __init__(self, state, in_z, out_z, in_mid, out_mid, to_state=None):
FPState.__init__(self, state)
+ if to_state is None:
+ to_state = "get_ops"
+ self.to_state = to_state
self.in_z = in_z
self.out_z = out_z
self.in_mid = in_mid
]
with m.If(self.out_z.stb & self.out_z.ack):
m.d.sync += self.out_z.stb.eq(0)
- m.next = "get_ops"
+ m.next = self.to_state
with m.Else():
m.d.sync += self.out_z.stb.eq(1)
+class FPPutZIdx(FPState):
+
+ def __init__(self, state, in_z, out_zs, in_mid, to_state=None):
+ FPState.__init__(self, state)
+ if to_state is None:
+ to_state = "get_ops"
+ self.to_state = to_state
+ self.in_z = in_z
+ self.out_zs = out_zs
+ self.in_mid = in_mid
+
+ def action(self, m):
+ outz_stb = Signal(reset_less=True)
+ outz_ack = Signal(reset_less=True)
+ m.d.comb += [outz_stb.eq(self.out_zs[self.in_mid].stb),
+ outz_ack.eq(self.out_zs[self.in_mid].ack),
+ ]
+ m.d.sync += [
+ self.out_zs[self.in_mid].v.eq(self.in_z.v)
+ ]
+ with m.If(outz_stb & outz_ack):
+ m.d.sync += self.out_zs[self.in_mid].stb.eq(0)
+ m.next = self.to_state
+ with m.Else():
+ m.d.sync += self.out_zs[self.in_mid].stb.eq(1)
+
+
class FPADDBaseMod(FPID):
def __init__(self, width, id_wid=None, single_cycle=False, compact=True):
m.d.sync += self.add_stb.eq(add_stb)
m.d.sync += self.add_ack.eq(0) # sets to zero when not in active state
+ m.d.sync += self.out_z.ack.eq(0) # likewise
#m.d.sync += self.in_t.stb.eq(0)
m.submodules.fpadd = self.mod
with m.Else():
m.d.sync += [self.add_ack.eq(0),
self.in_t.stb.eq(0),
+ self.out_z.ack.eq(1),
]
with m.Else():
# done: acknowledge, and write out id and value
m.d.sync += [self.add_ack.eq(1),
self.in_t.stb.eq(0)
]
- m.next = "get_a"
+ m.next = "put_z"
return
with m.Else():
m.d.sync += self.out_z.stb.eq(1)
+class ResArray:
+ def __init__(self, width, id_wid):
+ self.width = width
+ self.id_wid = id_wid
+ res = []
+ for i in range(rs_sz):
+ out_z = FPOp(width)
+ out_z.name = "out_z_%d" % i
+ res.append(out_z)
+ self.res = Array(res)
+ self.in_z = FPOp(width)
+ self.in_mid = Signal(self.id_wid, reset_less=True)
+
+ def setup(self, m, in_z, in_mid):
+ m.d.comb += [self.in_z.copy(in_z),
+ self.in_mid.eq(in_mid)]
+
+ def get_fragment(self, platform=None):
+ """ creates the HDL code-fragment for FPAdd
+ """
+ m = Module()
+ m.submodules.res_in_z = self.in_z
+ m.submodules += self.res
+
+ return m
+
+ def ports(self):
+ res = []
+ for z in self.res:
+ res += z.ports()
+ return res
+
class FPADD(FPID):
""" FPADD: stages as follows:
needs to be the thing that raises the incoming stb.
"""
- def __init__(self, width, id_wid=None, single_cycle=False, rs_sz=1):
+ def __init__(self, width, id_wid=None, single_cycle=False, rs_sz=2):
""" IEEE754 FP Add
* width: bit-width of IEEE754. supported: 16, 32, 64
for i in range(rs_sz):
in_a = FPOp(width)
in_b = FPOp(width)
- out_z = FPOp(width)
in_a.name = "in_a_%d" % i
in_b.name = "in_b_%d" % i
- out_z.name = "out_z_%d" % i
- rs.append((in_a, in_b, out_z))
+ rs.append((in_a, in_b))
self.rs = Array(rs)
+ res = []
+ for i in range(rs_sz):
+ out_z = FPOp(width)
+ out_z.name = "out_z_%d" % i
+ res.append(out_z)
+ self.res = Array(res)
+
self.states = []
def add_state(self, state):
in_a = self.rs[0][0]
in_b = self.rs[0][1]
- out_z = self.rs[0][2]
+
+ out_z = FPOp(self.width)
+ out_mid = Signal(self.id_wid, reset_less=True)
+ m.submodules.out_z = out_z
+
geta = self.add_state(FPGetOp("get_a", "get_b",
in_a, self.width))
geta.setup(m, in_a)
ab = FPADDBase(self.width, self.id_wid, self.single_cycle)
ab = self.add_state(ab)
ab.setup(m, a, b, getb.out_decode, self.ids.in_mid,
- out_z, self.ids.out_mid)
+ out_z, out_mid)
- #pz = self.add_state(FPPutZ("put_z", ab.out_z, self.out_z,
- # ab.out_mid, self.out_mid))
+ pz = self.add_state(FPPutZIdx("put_z", ab.out_z, self.res,
+ out_mid, "get_a"))
with m.FSM() as fsm:
if __name__ == "__main__":
if True:
alu = FPADD(width=32, id_wid=5, single_cycle=True)
- main(alu, ports=alu.in_a.ports() + \
- alu.in_b.ports() + \
- alu.out_z.ports() + \
- [alu.in_mid, alu.out_mid])
+ main(alu, ports=alu.rs[0][0].ports() + \
+ alu.rs[0][1].ports() + \
+ alu.res[0].ports() + \
+ [alu.ids.in_mid, alu.ids.out_mid])
else:
alu = FPADDBase(width=32, id_wid=5, single_cycle=True)
main(alu, ports=[alu.in_a, alu.in_b] + \