from nmigen.compat.sim import run_simulation
from nmigen.cli import verilog, rtlil
-from nmigen import Module, Signal, Elaboratable, Array, Cat
+from nmigen import Module, Signal, Elaboratable, Array, Cat, Repl
from nmutil.latch import SRLatch
asynchronous) would be reset at the exact moment that GO was requested,
and the RSEL would be garbage.
"""
- def __init__(self):
+ def __init__(self, llen):
+ self.llen = llen
# inputs
- self.reg_i = Signal(reset_less=True) # reg bit in (top)
+ self.reg_i = Signal(llen, reset_less=True) # reg bit in (top)
self.issue_i = Signal(reset_less=True) # Issue in (top)
- self.hazard_i = Signal(reset_less=True) # to check hazard
+ self.hazard_i = Signal(llen, reset_less=True) # to check hazard
self.go_i = Signal(reset_less=True) # Go read/write in (left)
self.die_i = Signal(reset_less=True) # Die in (left)
- self.q_o = Signal(reset_less=True) # Latch out (register active)
+ self.q_o = Signal(llen, reset_less=True) # Latch out (reg active)
# for Register File Select Lines (vertical)
- self.rsel_o = Signal(reset_less=True) # reg sel (bottom)
+ self.rsel_o = Signal(llen, reset_less=True) # reg sel (bottom)
# for Function Unit "forward progress" (horizontal)
- self.fwd_o = Signal(reset_less=True) # FU forard progress (right)
+ self.fwd_o = Signal(llen, reset_less=True) # FU forard progress (right)
def elaborate(self, platform):
m = Module()
- m.submodules.l = l = SRLatch(sync=False) # async latch
+ m.submodules.l = l = SRLatch(sync=False, llen=self.llen) # async latch
# reset on go HI, set on dest and issue
- m.d.comb += l.s.eq(self.issue_i & self.reg_i)
- m.d.comb += l.r.eq(self.go_i | self.die_i)
+ m.d.comb += l.s.eq(Repl(self.issue_i, self.llen) & self.reg_i)
+ m.d.comb += l.r.eq(Repl(self.go_i | self.die_i, self.llen))
# Function Unit "Forward Progress".
m.d.comb += self.fwd_o.eq((l.q) & self.hazard_i) # & ~self.issue_i)
# Register Select. Activated on go read/write and *current* latch set
m.d.comb += self.q_o.eq(l.qlq)
- m.d.comb += self.rsel_o.eq(l.qlq & self.go_i)
+ m.d.comb += self.rsel_o.eq(l.qlq & Repl(self.go_i, self.llen))
return m
return list(self)
-class DependenceCell(Elaboratable):
+class DependencyRow(Elaboratable):
""" implements 11.4.7 mitch alsup dependence cell, p27
"""
- def __init__(self):
+ def __init__(self, n_reg):
+ self.n_reg = n_reg
# inputs
- self.dest_i = Signal(reset_less=True) # Dest in (top)
- self.src1_i = Signal(reset_less=True) # oper1 in (top)
- self.src2_i = Signal(reset_less=True) # oper2 in (top)
+ self.dest_i = Signal(n_reg, reset_less=True) # Dest in (top)
+ self.src1_i = Signal(n_reg, reset_less=True) # oper1 in (top)
+ self.src2_i = Signal(n_reg, reset_less=True) # oper2 in (top)
self.issue_i = Signal(reset_less=True) # Issue in (top)
- self.rd_pend_i = Signal(reset_less=True) # Read pending in (top)
- self.wr_pend_i = Signal(reset_less=True) # Write pending in (top)
- self.rd_rsel_o = Signal(reset_less=True) # Read pending out (bottom)
- self.wr_rsel_o = Signal(reset_less=True) # Write pending out (bottom)
+ self.rd_pend_i = Signal(n_reg, reset_less=True) # Read pend in (top)
+ self.wr_pend_i = Signal(n_reg, reset_less=True) # Write pend in (top)
+ self.rd_rsel_o = Signal(n_reg, reset_less=True) # Read pend out (bot)
+ self.wr_rsel_o = Signal(n_reg, reset_less=True) # Write pend out (bot)
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.go_die_i = Signal(reset_less=True) # Go Die in (left)
# for Register File Select Lines (vertical)
- self.dest_rsel_o = Signal(reset_less=True) # dest reg sel (bottom)
- self.src1_rsel_o = Signal(reset_less=True) # src1 reg sel (bottom)
- self.src2_rsel_o = Signal(reset_less=True) # src2 reg sel (bottom)
+ self.dest_rsel_o = Signal(n_reg, reset_less=True) # dest reg sel (bot)
+ self.src1_rsel_o = Signal(n_reg, reset_less=True) # src1 reg sel (bot)
+ self.src2_rsel_o = Signal(n_reg, reset_less=True) # src2 reg sel (bot)
# for Function Unit "forward progress" (horizontal)
- self.dest_fwd_o = Signal(reset_less=True) # dest FU fw (right)
- self.src1_fwd_o = Signal(reset_less=True) # src1 FU fw (right)
- self.src2_fwd_o = Signal(reset_less=True) # src2 FU fw (right)
+ self.dest_fwd_o = Signal(n_reg, reset_less=True) # dest FU fw (right)
+ self.src1_fwd_o = Signal(n_reg, reset_less=True) # src1 FU fw (right)
+ self.src2_fwd_o = Signal(n_reg, reset_less=True) # src2 FU fw (right)
def elaborate(self, platform):
m = Module()
- m.submodules.dest_c = dest_c = DepCell()
- m.submodules.src1_c = src1_c = DepCell()
- m.submodules.src2_c = src2_c = DepCell()
+ m.submodules.dest_c = dest_c = DepCell(self.n_reg)
+ m.submodules.src1_c = src1_c = DepCell(self.n_reg)
+ m.submodules.src2_c = src2_c = DepCell(self.n_reg)
# connect issue and die
for c in [dest_c, src1_c, src2_c]:
# wark-wark: yes, writing to the same reg you are reading is *NOT*
# a write-after-read hazard.
- selfhazard = Signal(reset_less=False)
+ selfhazard = Signal(self.n_reg, reset_less=False)
m.d.comb += selfhazard.eq((self.dest_i & self.src1_i) |
(self.dest_i & self.src2_i))
return list(self)
-class DependencyRow(Elaboratable):
- def __init__(self, n_reg_col):
- self.n_reg_col = n_reg_col
-
- # ----
- # fields all match DependencyCell precisely
-
- self.dest_i = Signal(n_reg_col, reset_less=True)
- self.src1_i = Signal(n_reg_col, reset_less=True)
- self.src2_i = Signal(n_reg_col, reset_less=True)
-
- self.rd_pend_i = Signal(n_reg_col, reset_less=True)
- self.wr_pend_i = Signal(n_reg_col, reset_less=True)
-
- self.rd_rsel_o = Signal(n_reg_col, reset_less=True)
- self.wr_rsel_o = Signal(n_reg_col, reset_less=True)
-
- self.issue_i = Signal(reset_less=True)
- self.go_wr_i = Signal(reset_less=True)
- self.go_rd_i = Signal(reset_less=True)
- self.go_die_i = Signal(reset_less=True)
-
- self.dest_rsel_o = Signal(n_reg_col, reset_less=True)
- self.src1_rsel_o = Signal(n_reg_col, reset_less=True)
- self.src2_rsel_o = Signal(n_reg_col, reset_less=True)
-
- self.dest_fwd_o = Signal(n_reg_col, reset_less=True)
- self.src1_fwd_o = Signal(n_reg_col, reset_less=True)
- self.src2_fwd_o = Signal(n_reg_col, reset_less=True)
-
- def elaborate(self, platform):
- m = Module()
- rcell = Array(DependenceCell() for f in range(self.n_reg_col))
- for rn in range(self.n_reg_col):
- setattr(m.submodules, "dm_r%d" % rn, rcell[rn])
-
- # ---
- # connect Dep dest/src to module dest/src
- # ---
- rd_pend_i = []
- wr_pend_i = []
- rd_rsel_o = []
- wr_rsel_o = []
- dest_i = []
- src1_i = []
- src2_i = []
- for rn in range(self.n_reg_col):
- dc = rcell[rn]
- # accumulate cell inputs dest/src1/src2
- rd_pend_i.append(dc.rd_pend_i)
- wr_pend_i.append(dc.wr_pend_i)
- rd_rsel_o.append(dc.rd_rsel_o)
- wr_rsel_o.append(dc.wr_rsel_o)
- dest_i.append(dc.dest_i)
- src1_i.append(dc.src1_i)
- src2_i.append(dc.src2_i)
- # wire up inputs from module to row cell inputs (Cat is gooood)
- m.d.comb += [Cat(*dest_i).eq(self.dest_i),
- Cat(*src1_i).eq(self.src1_i),
- Cat(*src2_i).eq(self.src2_i),
- Cat(*rd_pend_i).eq(self.rd_pend_i),
- Cat(*wr_pend_i).eq(self.wr_pend_i),
- self.rd_rsel_o.eq(Cat(*rd_rsel_o)),
- self.wr_rsel_o.eq(Cat(*wr_rsel_o)),
- ]
-
- # ---
- # connect Dep die/issue_i/go_rd_i/go_wr_i to module issue_i/go_rd/go_wr
- # ---
- for rn in range(self.n_reg_col):
- dc = rcell[rn]
- m.d.comb += [dc.go_rd_i.eq(self.go_rd_i),
- dc.go_wr_i.eq(self.go_wr_i),
- dc.issue_i.eq(self.issue_i),
- dc.go_die_i.eq(self.go_die_i),
- ]
-
- # ---
- # connect Function Unit vector
- # ---
- dest_fwd_o = []
- src1_fwd_o = []
- src2_fwd_o = []
- for rn in range(self.n_reg_col):
- dc = rcell[rn]
- # accumulate cell fwd outputs for dest/src1/src2
- dest_fwd_o.append(dc.dest_fwd_o)
- src1_fwd_o.append(dc.src1_fwd_o)
- src2_fwd_o.append(dc.src2_fwd_o)
- # connect cell fwd outputs to FU Vector Out [Cat is gooood]
- m.d.comb += [self.dest_fwd_o.eq(Cat(*dest_fwd_o)),
- self.src1_fwd_o.eq(Cat(*src1_fwd_o)),
- self.src2_fwd_o.eq(Cat(*src2_fwd_o))
- ]
-
- # ---
- # connect Reg Selection vector
- # ---
- dest_rsel_o = []
- src1_rsel_o = []
- src2_rsel_o = []
- for rn in range(self.n_reg_col):
- dc = rcell[rn]
- # accumulate cell reg-select outputs dest/src1/src2
- dest_rsel_o.append(dc.dest_rsel_o)
- src1_rsel_o.append(dc.src1_rsel_o)
- src2_rsel_o.append(dc.src2_rsel_o)
- # connect cell reg-select outputs to Reg Vector Out
- m.d.comb += self.dest_rsel_o.eq(Cat(*dest_rsel_o))
- m.d.comb += self.src1_rsel_o.eq(Cat(*src1_rsel_o))
- m.d.comb += self.src2_rsel_o.eq(Cat(*src2_rsel_o))
-
- return m
-
- def __iter__(self):
- yield self.dest_i
- yield self.src1_i
- yield self.src2_i
- yield self.issue_i
- yield self.go_wr_i
- yield self.go_rd_i
- yield self.go_die_i
- yield self.dest_rsel_o
- yield self.src1_rsel_o
- yield self.src2_rsel_o
- yield self.dest_fwd_o
- yield self.src1_fwd_o
- yield self.src2_fwd_o
-
- def ports(self):
- return list(self)
-
-
def dcell_sim(dut):
yield dut.dest_i.eq(1)
yield dut.issue_i.eq(1)
with open("test_drow.il", "w") as f:
f.write(vl)
- dut = DependenceCell()
- vl = rtlil.convert(dut, ports=dut.ports())
- with open("test_dcell.il", "w") as f:
- f.write(vl)
-
run_simulation(dut, dcell_sim(dut), vcd_name='test_dcell.vcd')
if __name__ == '__main__':