From: Luke Kenneth Casson Leighton Date: Sun, 5 May 2019 14:43:03 +0000 (+0100) Subject: add shadow capability to function unit X-Git-Tag: ls180-24jan2020~1028 X-Git-Url: https://git.libre-soc.org/?p=ieee754fpu.git;a=commitdiff_plain;h=9c11e3753905c8539cc256b55f008af810641625 add shadow capability to function unit --- diff --git a/src/scoreboard/int_fn_unit.py b/src/scoreboard/int_fn_unit.py index ca8bc1a2..898373aa 100644 --- a/src/scoreboard/int_fn_unit.py +++ b/src/scoreboard/int_fn_unit.py @@ -1,20 +1,28 @@ from nmigen.compat.sim import run_simulation from nmigen.cli import verilog, rtlil -from nmigen import Module, Signal, Elaboratable +from nmigen import Module, Signal, Cat, Elaboratable from nmutil.latch import SRLatch from nmigen.lib.coding import Decoder class IntFnUnit(Elaboratable): """ implements 11.4.8 integer function unit, p31 + also implements optional shadowing 11.5.1, p55 + + shadowing can be used for branches as well as exceptions (interrupts), + and vector-element predication (once the predicate is known, which it + may not be at instruction issue) notes: * req_rel_i (request release) is the direct equivalent of pipeline "output valid" + * recover is a local python variable (actually go_die_o) + * when shadow_wid = 0, recover and shadown are Consts """ - def __init__(self, wid): + def __init__(self, wid, shadow_wid=0): self.reg_width = wid + self.shadow_wid = shadow_wid # inputs self.dest_i = Signal(wid, reset_less=True) # Dest in (top) @@ -29,9 +37,16 @@ class IntFnUnit(Elaboratable): self.g_rd_pend_i = Signal(wid, reset_less=True) # global rd (right) self.g_wr_pend_i = Signal(wid, reset_less=True) # global wr (right) + if shadow_wid: + self.shadow_i = Signal(shadow_wid, reset_less=True) + self.s_fail_i = Signal(shadow_wid, reset_less=True) + self.s_good_i = Signal(shadow_wid, reset_less=True) + self.go_die_o = Signal(reset_less=True) + # outputs self.readable_o = Signal(reset_less=True) # Readable out (right) self.writable_o = Signal(reset_less=True) # Writable out (right) + self.busy_o = Signal(reset_less=True) # busy out (left) self.rd_pend_o = Signal(wid, reset_less=True) # rd pending (right) self.wr_pend_o = Signal(wid, reset_less=True) # wr pending (right) @@ -43,25 +58,52 @@ class IntFnUnit(Elaboratable): m.submodules.dest_d = dest_d = Decoder(self.reg_width) m.submodules.src1_d = src1_d = Decoder(self.reg_width) m.submodules.src2_d = src2_d = Decoder(self.reg_width) + s_latches = [] + for i in range(self.shadow_wid): + sl = SRLatch(sync=False) + setattr(m.submodules, "shadow%d" % i, sl) + s_latches.append(sl) + + # shadow / recover (optional: shadow_wid > 0) + if self.shadow_wid: + recover = self.go_die_o + si = Signal(self.shadow_wid, reset_less=True) + sq = Signal(self.shadow_wid, reset_less=True) + shadown = Signal(reset_less=True) + recfail = Signal(self.shadow_wid, reset_less=True) + l = self.shadow_i & Cat(*([self.issue_i] * self.shadow_wid)) + q_l = [] + for i, s in enumerate(l): + m.d.comb += s_latches[i].s.eq(s) # issue_i & shadow_i[i] + m.d.comb += s_latches[i].r.eq(self.s_good_i[i]) + q_l.append(s_latches[i].q) + m.d.comb += sq.eq(Cat(*q_l)) + m.d.comb += shadown.eq(~sq.bool()) + m.d.comb += recfail.eq(sq & self.s_fail_i) + m.d.comb += recover.eq(recfail.bool()) + else: + shadown = Const(1) + recover = Const(0) # go_write latch: reset on go_write 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) + m.d.comb += wr_l.r.eq(self.go_write_i | recover) # src1 latch: reset on go_read 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) + 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 += dest_d.n.eq(wr_l.q) # FIXME this is sync-delayed! + 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 += self.wr_pend_o.eq(dest_d.o) # src1/src2 decoder: read-pending out m.d.comb += src1_d.i.eq(self.src1_i) - m.d.comb += src1_d.n.eq(rd_l.q) # FIXME this is sync-delayed! + 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.n.eq(rd_l.q) # FIXME this is sync-delayed! + m.d.comb += src2_d.n.eq(rd_l.qn) # decode is inverted m.d.comb += self.rd_pend_o.eq(src1_d.o | src2_d.o) # readable output signal @@ -74,7 +116,7 @@ class IntFnUnit(Elaboratable): g_rw = Signal(reset_less=True) m.d.comb += int_g_rw.eq(self.g_rd_pend_i & self.wr_pend_o) m.d.comb += g_rw.eq(~int_g_rw.bool()) - m.d.comb += self.writable_o.eq(g_rw & rd_l.q & self.req_rel_i) + m.d.comb += self.writable_o.eq(g_rw & rd_l.q & self.req_rel_i & shadown) return m @@ -120,7 +162,7 @@ def int_fn_unit_sim(dut): yield def test_int_fn_unit(): - dut = IntFnUnit(32) + dut = IntFnUnit(32, 2) vl = rtlil.convert(dut, ports=dut.ports()) with open("test_int_fn_unit.il", "w") as f: f.write(vl)