convert SPRs and others to Data.data/ok
[soc.git] / src / experiment / score6600.py
index 281fed9bc962fa964b366b16c4efd53eb973f200..209bc99c28e8dae05a8e4003c697aac9fbb385a1 100644 (file)
@@ -1,5 +1,6 @@
 from nmigen.compat.sim import run_simulation
 from nmigen.cli import verilog, rtlil
+from nmigen.hdl.ast import unsigned
 from nmigen import Module, Const, Signal, Array, Cat, Elaboratable, Memory
 
 from regfile.regfile import RegFileArray, treereduce
@@ -28,23 +29,12 @@ class TestMemory(Elaboratable):
     def __init__(self, regwid, addrw):
         self.ddepth = 1 # regwid //8
         depth = (1<<addrw) // self.ddepth
-        self.adr   = Signal(addrw)
-        self.dat_r = Signal(regwid)
-        self.dat_w = Signal(regwid)
-        self.we    = Signal()
         self.mem   = Memory(width=regwid, depth=depth, init=range(0, depth))
 
     def elaborate(self, platform):
         m = Module()
-        m.submodules.rdport = rdport = self.mem.read_port()
-        m.submodules.wrport = wrport = self.mem.write_port()
-        m.d.comb += [
-            rdport.addr.eq(self.adr[self.ddepth:]), # ignore low bits
-            self.dat_r.eq(rdport.data),
-            wrport.addr.eq(self.adr),
-            wrport.data.eq(self.dat_w),
-            wrport.en.eq(self.we),
-        ]
+        m.submodules.rdport = self.rdport = self.mem.read_port()
+        m.submodules.wrport = self.wrport = self.mem.write_port()
         return m
 
 
@@ -121,11 +111,14 @@ class CompUnitsBase(Elaboratable):
         self.rd_rel_o = Signal(n_units, reset_less=True)
         self.req_rel_o = Signal(n_units, reset_less=True)
         if ldstmode:
+            self.ld_o = Signal(n_units, reset_less=True) # op is LD
+            self.st_o = Signal(n_units, reset_less=True) # op is ST
             self.adr_rel_o = Signal(n_units, reset_less=True)
             self.sto_rel_o = Signal(n_units, reset_less=True)
             self.req_rel_o = Signal(n_units, reset_less=True)
             self.load_mem_o = Signal(n_units, reset_less=True)
             self.stwd_mem_o = Signal(n_units, reset_less=True)
+            self.addr_o = Signal(rwid, reset_less=True)
 
         # in/out register data (note: not register#, actual data)
         self.data_o = Signal(rwid, reset_less=True)
@@ -169,10 +162,12 @@ class CompUnitsBase(Elaboratable):
         # connect data register input/output
 
         # merge (OR) all integer FU / ALU outputs to a single value
-        # bit of a hack: treereduce needs a list with an item named "data_o"
         if self.units:
-            data_o = treereduce(self.units)
+            data_o = treereduce(self.units, "data_o")
             comb += self.data_o.eq(data_o)
+            if self.ldstmode:
+                addr_o = treereduce(self.units, "addr_o")
+                comb += self.addr_o.eq(addr_o)
 
         for i, alu in enumerate(self.units):
             comb += alu.src1_i.eq(self.src1_i)
@@ -185,15 +180,21 @@ class CompUnitsBase(Elaboratable):
         stmem_l = []
         go_ad_l = []
         go_st_l = []
+        ld_l = []
+        st_l = []
         adr_rel_l = []
         sto_rel_l = []
         for alu in self.units:
+            ld_l.append(alu.ld_o)
+            st_l.append(alu.st_o)
             adr_rel_l.append(alu.adr_rel_o)
             sto_rel_l.append(alu.sto_rel_o)
             ldmem_l.append(alu.load_mem_o)
             stmem_l.append(alu.stwd_mem_o)
             go_ad_l.append(alu.go_ad_i)
             go_st_l.append(alu.go_st_i)
+        comb += self.ld_o.eq(Cat(*ld_l))
+        comb += self.st_o.eq(Cat(*st_l))
         comb += self.adr_rel_o.eq(Cat(*adr_rel_l))
         comb += self.sto_rel_o.eq(Cat(*sto_rel_l))
         comb += self.load_mem_o.eq(Cat(*ldmem_l))
@@ -405,6 +406,9 @@ class Scoreboard(Elaboratable):
         self.intregs = RegFileArray(rwid, n_regs)
         self.fpregs = RegFileArray(rwid, n_regs)
 
+        # Memory (test for now)
+        self.mem = TestMemory(self.rwid, 8) # not too big, takes too long
+
         # issue q needs to get at these
         self.aluissue = IssueUnitGroup(2)
         self.lsissue = IssueUnitGroup(2)
@@ -418,9 +422,9 @@ class Scoreboard(Elaboratable):
         self.ls_imm_i = Signal(rwid, reset_less=True)
 
         # inputs
-        self.int_dest_i = Signal(max=n_regs, reset_less=True) # Dest R# in
-        self.int_src1_i = Signal(max=n_regs, reset_less=True) # oper1 R# in
-        self.int_src2_i = Signal(max=n_regs, reset_less=True) # oper2 R# in
+        self.int_dest_i = Signal(range(n_regs), reset_less=True) # Dest R# in
+        self.int_src1_i = Signal(range(n_regs), reset_less=True) # oper1 R# in
+        self.int_src2_i = Signal(range(n_regs), reset_less=True) # oper2 R# in
         self.reg_enable_i = Signal(reset_less=True) # enable reg decode
 
         # outputs
@@ -442,6 +446,7 @@ class Scoreboard(Elaboratable):
 
         m.submodules.intregs = self.intregs
         m.submodules.fpregs = self.fpregs
+        m.submodules.mem = mem = self.mem
 
         # register ports
         int_dest = self.intregs.write_port("dest")
@@ -472,6 +477,10 @@ class Scoreboard(Elaboratable):
         # Memory FUs
         m.submodules.memfus = memfus = MemFunctionUnits(n_ldsts, 5)
 
+        # Memory Priority Picker 1: one gateway per memory port
+        mempick1 = GroupPicker(n_ldsts) # picks 1 reader and 1 writer to intreg
+        m.submodules.mempick1 = mempick1
+
         # Count of number of FUs
         n_intfus = n_int_alus
         n_fp_fus = 0 # for now
@@ -542,25 +551,41 @@ class Scoreboard(Elaboratable):
         #---------
         reset_b = Signal(cul.n_units, reset_less=True)
         sync += reset_b.eq(cul.go_st_i | cul.go_wr_i | cul.go_die_i)
+
         comb += memfus.fn_issue_i.eq(cul.issue_i) # Comp Unit Issue -> Mem FUs
         comb += memfus.addr_en_i.eq(cul.adr_rel_o) # Match enable on adr rel
         comb += memfus.addr_rs_i.eq(reset_b) # reset same as LDSTCompUnit
+
+        # LD/STs have to accumulate prior LD/STs (TODO: multi-issue as well,
+        # in a transitive fashion).  This cycle activates based on LDSTCompUnit
+        # issue_i.  multi-issue gets a bit more complex but not a lot.
+        prior_ldsts = Signal(cul.n_units, reset_less=True)
+        sync += prior_ldsts.eq(memfus.g_int_ld_pend_o | memfus.g_int_st_pend_o)
         with m.If(self.ls_oper_i[2]): # LD bit of operand
-            comb += memfus.ld_i.eq(cul.issue_i)
+            comb += memfus.ld_i.eq(cul.issue_i | prior_ldsts)
         with m.If(self.ls_oper_i[3]): # ST bit of operand
-            comb += memfus.st_i.eq(cul.issue_i)
+            comb += memfus.st_i.eq(cul.issue_i | prior_ldsts)
+
+        # TODO: adr_rel_o needs to go into L1 Cache.  for now,
+        # just immediately activate go_adr
+        comb += cul.go_ad_i.eq(cul.adr_rel_o)
 
         # connect up address data
-        comb += memfus.addrs_i[0].eq(cul.units[0].data_o)
-        comb += memfus.addrs_i[1].eq(cul.units[1].data_o)
+        comb += memfus.addrs_i[0].eq(cul.units[0].addr_o)
+        comb += memfus.addrs_i[1].eq(cul.units[1].addr_o)
 
         # connect loadable / storable to go_ld/go_st.
         # XXX should only be done when the memory ld/st has actually happened!
-
-        comb += memfus.go_ld_i.eq(memfus.loadable_o & memfus.addr_nomatch_o)
-        comb += memfus.go_st_i.eq(memfus.storable_o & memfus.addr_nomatch_o)
-        #comb += cul.go_wr_i.eq(memfus.loadable_o & memfus.addr_nomatch_o)
-        comb += cul.go_st_i.eq(memfus.storable_o & memfus.addr_nomatch_o)
+        go_st_i = Signal(cul.n_units, reset_less=True)
+        go_ld_i = Signal(cul.n_units, reset_less=True)
+        comb += go_ld_i.eq(memfus.loadable_o & memfus.addr_nomatch_o &\
+                                  cul.req_rel_o & cul.ld_o)
+        comb += go_st_i.eq(memfus.storable_o & memfus.addr_nomatch_o &\
+                                  cul.sto_rel_o & cul.st_o)
+        comb += memfus.go_ld_i.eq(go_ld_i)
+        comb += memfus.go_st_i.eq(go_st_i)
+        #comb += cul.go_wr_i.eq(go_ld_i)
+        comb += cul.go_st_i.eq(go_st_i)
 
         #comb += cu.go_rd_i[0:n_intfus].eq(go_rd_o[0:n_intfus])
         #comb += cu.go_wr_i[0:n_intfus].eq(go_wr_o[0:n_intfus])
@@ -718,7 +743,7 @@ class IssueToScoreboard(Elaboratable):
         self.opw = opwid
         self.n_regs = n_regs
 
-        mqbits = (int(log(qlen) / log(2))+2, False)
+        mqbits = unsigned(int(log(qlen) / log(2))+2)
         self.p_add_i = Signal(mqbits) # instructions to add (from data_i)
         self.p_ready_o = Signal() # instructions were added
         self.data_i = Instruction.nq(n_in, "data_i", rwid, opwid)
@@ -733,10 +758,8 @@ class IssueToScoreboard(Elaboratable):
 
         iq = InstructionQ(self.rwid, self.opw, self.qlen, self.n_in, self.n_out)
         sc = Scoreboard(self.rwid, self.n_regs)
-        mem = TestMemory(self.rwid, 8) # not too big, takes too long
         m.submodules.iq = iq
         m.submodules.sc = sc
-        m.submodules.mem = mem
 
         # get at the regfile for testing
         self.intregs = sc.intregs
@@ -1125,19 +1148,19 @@ def scoreboard_sim(dut, alusim):
         if False:
             instrs = create_random_ops(dut, 15, True, 4)
 
-        if True: # LD/ST test (with immediate)
-            instrs.append( (1, 2, 2, 0x10, 1, 1, (0, 0)) )
-            #instrs.append( (1, 2, 7, 0x10, 1, 1, (0, 0)) )
+        if False: # LD/ST test (with immediate)
+            instrs.append( (1, 2, 0, 0x10, 1, 1, (0, 0)) )
+            #instrs.append( (1, 2, 0, 0x10, 1, 1, (0, 0)) )
 
-        if False:
+        if True:
             instrs.append( (1, 2, 2, 1, 1, 20, (0, 0)) )
 
-        if False:
-            instrs.append( (7, 3, 2, 4, (0, 0)) )
-            instrs.append( (7, 6, 6, 2, (0, 0)) )
-            instrs.append( (1, 7, 2, 2, (0, 0)) )
+        if True:
+            instrs.append( (7, 3, 2, 4, 0, 0, (0, 0)) )
+            instrs.append( (7, 6, 6, 2, 0, 0, (0, 0)) )
+            instrs.append( (1, 7, 2, 2, 0, 0, (0, 0)) )
 
-        if False:
+        if True:
             instrs.append((2, 3, 3, 0, 0, 0, (0, 0)))
             instrs.append((5, 3, 3, 1, 0, 0, (0, 0)))
             instrs.append((3, 5, 5, 2, 0, 0, (0, 0)))