from nmigen.compat.sim import run_simulation
from nmigen.cli import verilog, rtlil
from nmigen import Module, Signal, Cat, Array, Const, Elaboratable
-from nmutil.latch import SRLatch
from nmigen.lib.coding import Decoder
-from shadow_fn import ShadowFn
+from nmutil.latch import SRLatch, latchregister
+
+from .shadow_fn import ShadowFn
class FnUnit(Elaboratable):
self.src2_i = Signal(max=wid, reset_less=True) # oper2 R# in (top)
self.issue_i = Signal(reset_less=True) # Issue in (top)
- self.go_write_i = Signal(reset_less=True) # Go Write in (left)
- self.go_read_i = Signal(reset_less=True) # Go Read in (left)
+ self.go_wr_i = Signal(reset_less=True) # Go Write in (left)
+ self.go_rd_i = Signal(reset_less=True) # Go Read in (left)
self.req_rel_i = Signal(reset_less=True) # request release (left)
self.g_xx_pend_i = Array(Signal(wid, reset_less=True, name="g_pend_i") \
for i in range(n_dests)) # writable out (right)
self.busy_o = Signal(reset_less=True) # busy out (left)
+ self.src1_pend_o = Signal(wid, reset_less=True) # src1 pending
+ self.src2_pend_o = Signal(wid, reset_less=True) # src1 pending
self.rd_pend_o = Signal(wid, reset_less=True) # rd pending (right)
self.xx_pend_o = Array(Signal(wid, reset_less=True, name="pend_o") \
for i in range(n_dests))# wr pending (right)
for i in range(self.n_dests):
m.d.comb += self.xx_pend_o[i].eq(0) # initialise all array
m.d.comb += self.writable_o[i].eq(0) # to zero
+ m.d.comb += self.readable_o[i].eq(0) # to zero
- # go_write latch: reset on go_write HI, set on issue
+ # go_wr latch: reset on go_wr HI, set on issue
m.d.comb += wr_l.s.eq(self.issue_i)
- m.d.comb += wr_l.r.eq(self.go_write_i | recover)
+ m.d.comb += wr_l.r.eq(self.go_wr_i | recover)
- # src1 latch: reset on go_read HI, set on issue
+ # src1 latch: reset on go_rd HI, set on issue
m.d.comb += rd_l.s.eq(self.issue_i)
- m.d.comb += rd_l.r.eq(self.go_read_i | recover)
-
- # dest decoder: write-pending out
- m.d.comb += dest_d.i.eq(self.dest_i)
+ m.d.comb += rd_l.r.eq(self.go_rd_i | recover)
+
+ # latch/registers for dest / src1 / src2
+ dest_r = Signal(max=self.reg_width, reset_less=True)
+ src1_r = Signal(max=self.reg_width, reset_less=True)
+ src2_r = Signal(max=self.reg_width, reset_less=True)
+ # XXX latch based on *issue* rather than !latch (as in book)
+ latchregister(m, self.dest_i, dest_r, self.issue_i) #wr_l.qn)
+ latchregister(m, self.src1_i, src1_r, self.issue_i) #wr_l.qn)
+ latchregister(m, self.src2_i, src2_r, self.issue_i) #wr_l.qn)
+
+ # dest decoder (use dest reg as input): write-pending out
+ m.d.comb += dest_d.i.eq(dest_r)
m.d.comb += dest_d.n.eq(wr_l.qn) # decode is inverted
m.d.comb += self.busy_o.eq(wr_l.q) # busy if set
m.d.comb += xx_pend_o.eq(dest_d.o)
- # src1/src2 decoder: read-pending out
- m.d.comb += src1_d.i.eq(self.src1_i)
+ # src1/src2 decoder (use src1/2 regs as input): read-pending out
+ m.d.comb += src1_d.i.eq(src1_r)
m.d.comb += src1_d.n.eq(rd_l.qn) # decode is inverted
- m.d.comb += src2_d.i.eq(self.src2_i)
+ m.d.comb += src2_d.i.eq(src2_r)
m.d.comb += src2_d.n.eq(rd_l.qn) # decode is inverted
+ m.d.comb += self.src1_pend_o.eq(src1_d.o)
+ m.d.comb += self.src2_pend_o.eq(src2_d.o)
m.d.comb += self.rd_pend_o.eq(src1_d.o | src2_d.o)
# readable output signal
g_rd = Signal(self.reg_width, reset_less=True)
+ ro = Signal(reset_less=True)
m.d.comb += g_rd.eq(self.g_wr_pend_i & self.rd_pend_o)
- m.d.comb += self.readable_o.eq(g_rd.bool())
+ m.d.comb += ro.eq(~g_rd.bool())
+ m.d.comb += self.readable_o.eq(ro & rd_l.q)
# writable output signal
g_wr_v = Signal(self.reg_width, reset_less=True)
wo = Signal(reset_less=True)
m.d.comb += g_wr_v.eq(g_pend_i & xx_pend_o)
m.d.comb += g_wr.eq(~g_wr_v.bool())
- m.d.comb += wo.eq(g_wr & rd_l.q & self.req_rel_i & shadown)
+ m.d.comb += wo.eq(g_wr & rd_l.qn & self.req_rel_i & shadown)
m.d.comb += writable_o.eq(wo)
return m
yield self.src1_i
yield self.src2_i
yield self.issue_i
- yield self.go_write_i
- yield self.go_read_i
+ yield self.go_wr_i
+ yield self.go_rd_i
yield self.req_rel_i
yield from self.g_xx_pend_i
yield self.g_wr_pend_i
yield
yield dut.issue_i.eq(0)
yield
- yield dut.go_read_i.eq(1)
+ yield dut.go_rd_i.eq(1)
yield
- yield dut.go_read_i.eq(0)
+ yield dut.go_rd_i.eq(0)
yield
- yield dut.go_write_i.eq(1)
+ yield dut.go_wr_i.eq(1)
yield
- yield dut.go_write_i.eq(0)
+ yield dut.go_wr_i.eq(0)
yield
def test_int_fn_unit():