use a virtual regfile port for the hazard bitvectors
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Tue, 16 Nov 2021 18:54:21 +0000 (18:54 +0000)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Tue, 16 Nov 2021 18:54:26 +0000 (18:54 +0000)
this allows a full width of enables and full width of bits
(one per reg being written to)

src/soc/regfile/regfiles.py
src/soc/regfile/virtual_port.py
src/soc/simple/core.py

index 7bd726fd285e7534e03b9f578cf7a9dc413648e9..fc87bee924fff5cb75af431e9033a988ccef2259 100644 (file)
@@ -285,9 +285,9 @@ class RegFiles:
 
     def make_hazard_vec(self, rf, name):
         if isinstance(rf, VirtualRegPort):
-            vec = RegFileArray(1, rf.nregs)
+            vec = VirtualRegPort(rf.nregs, rf.nregs, wr2=True)
         else:
-            vec = RegFileArray(1, rf.depth)
+            vec = VirtualRegPort(rf.depth, rf.depth, wr2=True)
         # get read/write port specs and create bitvector ports with same names
         wr_spec, rd_spec = rf.get_port_specs()
         # ok, this is complicated/fun.
@@ -297,12 +297,8 @@ class RegFiles:
         # bitvector *ALSO* needs to be wrtten (a 0).  therefore we need to
         # MERGE the wr_spec and rd_spec with some appropriate name prefixes
         # to make sure they do not clash
-        rd_bvspec = {'issue': 'issue'}
-        wr_bvspec = {'set': 'set', 'clr': 'clr'}
-        #for k, port in wr_spec.items():
-        #    wr_bvspec["wr_%s" % k] = "wr_%s" % port
-        #for k, port in rd_spec.items():
-        #    wr_bvspec["rd_%s" % k] = "rd_%s" % port
+        rd_bvspec = {'issue': 'full_rd'}
+        wr_bvspec = {'set': 'full_wr', 'clr': 'full_wr2'}
         create_ports(vec, wr_bvspec, rd_bvspec)
         return vec
 
index 9bb67028d77fc76ed95f66a6095c4a5dc584b4f7..dc5c57d6ad3f8d2f5d68384a4c005efd848b8da8 100644 (file)
@@ -18,10 +18,11 @@ from soc.regfile.regfile import RegFileArray
 
 
 class VirtualRegPort(RegFileArray):
-    def __init__(self, bitwidth, n_regs, rd2=False):
+    def __init__(self, bitwidth, n_regs, rd2=False, wr2=False):
         self.bitwidth = bitwidth
         self.nregs = n_regs
         self.rd2 = rd2 # eurgh hack
+        self.wr2 = wr2 # eurgh hack
         self.regwidth = regwidth = bitwidth // n_regs
         super().__init__(self.regwidth, n_regs)
 
@@ -32,12 +33,27 @@ class VirtualRegPort(RegFileArray):
         self.full_rd = RecordObject([("ren", n_regs),
                                      ("o_data", bitwidth)],  # *full* wid
                                     name="full_rd")
-        if not rd2:
-            return
-        self.full_rd2 = RecordObject([("ren", n_regs),
+        if wr2:
+            self.full_wr2 = RecordObject([("wen", n_regs),
+                                     ("i_data", bitwidth)],  # *full* wid
+                                    name="full_wr2")
+        if rd2:
+            self.full_rd2 = RecordObject([("ren", n_regs),
                                      ("o_data", bitwidth)],  # *full* wid
                                     name="full_rd2")
 
+    def connect_full_wr(self, m, wfull, name):
+        comb = m.d.comb
+        wr_regs = self.write_reg_port(name)
+
+        # wire up the enable signals from the large (full) port
+        l = map(lambda port: port.i_data, wr_regs)
+        le = map(lambda port: port.wen, wr_regs)  # get port wen(s)
+
+        # get list of all i_data (and wens) and assign to them via Cat
+        comb += Cat(*l).eq(wfull.i_data)
+        comb += Cat(*le).eq(wfull.wen)
+
     def connect_full_rd(self, m, rfull, name):
         comb = m.d.comb
         rd_regs = self.read_reg_port(name)
@@ -53,25 +69,16 @@ class VirtualRegPort(RegFileArray):
         m = super().elaborate(platform)
         comb = m.d.comb
 
-        # for internal use only.
-        wr_regs = self.write_reg_port(f"w")
+        # connect up full write port
+        self.connect_full_wr(m, self.full_wr, "w")
+        if self.wr2:
+            self.connect_full_wr(m, self.full_wr2, "w2")
 
         # connect up full read port
         self.connect_full_rd(m, self.full_rd, "r")
         if self.rd2: # hack!
             self.connect_full_rd(m, self.full_rd2, "r2")
 
-        # connect up full write port
-        wfull = self.full_wr
-
-        # wire up the enable signals from the large (full) port
-        l = map(lambda port: port.i_data, wr_regs)
-        le = map(lambda port: port.wen, wr_regs)  # get port wen(s)
-
-        # get list of all i_data (and wens) and assign to them via Cat
-        comb += Cat(*l).eq(wfull.i_data)
-        comb += Cat(*le).eq(wfull.wen)
-
         return m
 
     def __iter__(self):
index 3b541541de3e6c2568f9c5e3f0b1fb790143411e..4e7ade872f982f807b2cdc38df4c0d2999268cc4 100644 (file)
@@ -540,7 +540,10 @@ class NonProductionCore(ControlBase):
         for i, fspec in enumerate(fspecs):
             # connect up the FU req/go signals and the reg-read to the FU
             # these are arbitrated by Data.ok signals
-            (rf, wf, read, write, wid, fuspec) = fspec
+            (rf, wf, read, _write, wid, fuspec) = fspec
+            wrname = "write_%s_%s_%d" % (regfile, regname, i)
+            write = Signal.like(_write, name=wrname)
+            comb += write.eq(_write)
             for pi, (funame, fu, idx) in enumerate(fuspec):
                 pi += ppoffs[i]
 
@@ -592,7 +595,6 @@ class NonProductionCore(ControlBase):
                         comb += wvaddr_en.eq(1<<addr_en)
                 wvclren.append(wvaddr_en)
 
-                continue
                 # now connect up the bitvector write hazard.  unlike the
                 # regfile writeports, a ONE must be written to the corresponding
                 # bit of the hazard bitvector (to indicate the existence of
@@ -607,10 +609,11 @@ class NonProductionCore(ControlBase):
                 comb += issue_active.eq(fu.issue_i & fu_active & wrflags[i])
                 with m.If(issue_active):
                     if rfile.unary:
-                        comb += wvaddr_en.eq(addr_en)
+                        comb += wvaddr_en.eq(write)
                     else:
-                        comb += wvaddr_en.eq(1<<addr_en)
-                    wvsetens.append(wvaddr_en)
+                        comb += wvaddr_en.eq(1<<write)
+                    wvseten.append(wvaddr_en)
+                    wvsets.append(wvaddr_en)
 
         # here is where we create the Write Broadcast Bus. simple, eh?
         comb += wport.i_data.eq(ortreereduce_sig(wsigs))
@@ -623,9 +626,9 @@ class NonProductionCore(ControlBase):
             comb += wport.wen.eq(ortreereduce_sig(wens))
 
         # for write-vectors
-        comb += wvclr.wen.eq(ortreereduce_sig(wvclren))
-        #comb += wvset.wen.eq(ortreereduce_sig(wvens))
-        #comb += wvset.i_data.eq(ortreereduce_sig(wvsets))
+        comb += wvclr.wen.eq(ortreereduce_sig(wvclren)) # clear (regfile write)
+        comb += wvset.wen.eq(ortreereduce_sig(wvseten)) # set (issue time)
+        comb += wvset.i_data.eq(ortreereduce_sig(wvsets))
 
     def connect_wrports(self, m, fu_bitdict):
         """connect write ports