add issue unit
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Mon, 6 May 2019 14:06:39 +0000 (15:06 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Mon, 6 May 2019 14:06:54 +0000 (15:06 +0100)
src/scoreboard/issue_unit.py [new file with mode: 0644]

diff --git a/src/scoreboard/issue_unit.py b/src/scoreboard/issue_unit.py
new file mode 100644 (file)
index 0000000..3506b9e
--- /dev/null
@@ -0,0 +1,110 @@
+from nmigen.compat.sim import run_simulation
+from nmigen.cli import verilog, rtlil
+from nmigen import Module, Signal, Cat, Array, Const, Record, Elaboratable
+from nmutil.latch import SRLatch
+from nmigen.lib.coding import Decoder
+
+from shadow_fn import ShadowFn
+
+
+class IssueUnit(Elaboratable):
+    """ implements 11.4.14 issue unit, p50
+
+        Inputs
+
+        * :wid:         register file width
+    """
+    def __init__(self, wid, n_insns):
+        self.reg_width = wid
+        self.n_insns = n_insns
+
+        # inputs
+        self.store_i = Signal(reset_less=True) # instruction is a store
+        self.dest_i = Signal(max=wid, reset_less=True) # Dest R# in 
+        self.src1_i = Signal(max=wid, reset_less=True) # oper1 R# in
+        self.src2_i = Signal(max=wid, reset_less=True) # oper2 R# in
+
+        self.g_wr_pend_i = Signal(wid, reset_less=True) # write pending vector
+
+        self.insn_i = Array(Signal(reset_less=True, name="insn_i") \
+                               for i in range(n_insns))
+        self.busy_i = Array(Signal(reset_less=True, name="busy_i") \
+                               for i in range(n_insns))
+
+        # outputs
+        self.fn_issue_o = Array(Signal(reset_less=True, name="fn_issue_o") \
+                               for i in range(n_insns))
+        self.g_issue_o = Signal(reset_less=True)
+
+    def elaborate(self, platform):
+        m = Module()
+        m.submodules.dest_d = dest_d = Decoder(self.reg_width)
+
+        # temporaries
+        waw_stall = Signal(reset_less=True)
+        fu_stall = Signal(reset_less=True)
+        pend = Signal(self.reg_width, reset_less=True)
+
+        # dest decoder: write-pending
+        m.d.comb += dest_d.i.eq(self.dest_i)
+        m.d.comb += dest_d.n.eq(~self.store_i) # decode is inverted
+        m.d.comb += pend.eq(dest_d.o & self.g_wr_pend_i)
+        m.d.comb += waw_stall.eq(pend.bool())
+
+        ib_l = []
+        for i in range(self.n_insns):
+            ib_l.append(self.insn_i[i] & self.busy_i[i])
+        m.d.comb += fu_stall.eq(Cat(*ib_l).bool())
+        m.d.comb += self.g_issue_o.eq(~(waw_stall | fu_stall))
+        for i in range(self.n_insns):
+            m.d.comb += self.fn_issue_o[i].eq(self.g_issue_o & self.insn_i[i])
+
+        return m
+
+    def __iter__(self):
+        yield self.store_i
+        yield self.dest_i
+        yield self.src1_i
+        yield self.src2_i
+        yield self.g_wr_pend_i
+        yield from self.insn_i
+        yield from self.busy_i
+        yield from self.fn_issue_o
+        yield self.g_issue_o
+
+    def ports(self):
+        return list(self)
+
+
+def issue_unit_sim(dut):
+    yield dut.dest_i.eq(1)
+    yield dut.issue_i.eq(1)
+    yield
+    yield dut.issue_i.eq(0)
+    yield
+    yield dut.src1_i.eq(1)
+    yield dut.issue_i.eq(1)
+    yield
+    yield
+    yield
+    yield dut.issue_i.eq(0)
+    yield
+    yield dut.go_read_i.eq(1)
+    yield
+    yield dut.go_read_i.eq(0)
+    yield
+    yield dut.go_write_i.eq(1)
+    yield
+    yield dut.go_write_i.eq(0)
+    yield
+
+def test_issue_unit():
+    dut = IssueUnit(32, 3)
+    vl = rtlil.convert(dut, ports=dut.ports())
+    with open("test_issue_unit.il", "w") as f:
+        f.write(vl)
+
+    run_simulation(dut, issue_unit_sim(dut), vcd_name='test_issue_unit.vcd')
+
+if __name__ == '__main__':
+    test_issue_unit()