sort-of (maybe) implemented a virtual port on top of RegFileArray.
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Tue, 26 May 2020 15:54:33 +0000 (16:54 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Tue, 26 May 2020 15:54:33 +0000 (16:54 +0100)
needs checking

src/soc/regfile/virtual_port.py

index 159ff04d40ab95fcdbd4594a1fa1cdc2f9da5498..4f025887328699279e0faf96b5138deab1ef5568 100644 (file)
@@ -21,15 +21,19 @@ class VirtualRegPort(RegFileArray):
     def __init__(self, bitwidth, n_regs):
         self.bitwidth = bitwidth
         self.nregs = n_regs
-        self.regwidth = bitwidth // n_regs
+        self.regwidth = regwidth = bitwidth // n_regs
         super().__init__(self.regwidth, n_regs)
 
         # create suite of 8 write and 8 read ports for external use
-        self.wr_ports = self.write_reg_port(f"extw")
-        self.rd_ports = self.read_reg_port(f"extr")
-        # now for internal use
-        self._wr_regs = self.write_reg_port(f"intw")
-        self._rd_regs = self.read_reg_port(f"intr")
+        self.wr_ports = []
+        self.rd_ports = []
+        for i in range(n_regs):
+            self.wr_ports.append(RecordObject([("wen", n_regs),
+                                              ("data_i", regwidth)],
+                                             name="w%d" % i))
+            self.rd_ports.append(RecordObject([("ren", n_regs),
+                                              ("data_o", regwidth)],
+                                             name="r%d" % i))
         # and append the "full" depth variant to the "external" ports
         self.wr_ports.append(RecordObject([("wen", n_regs),
                                           ("data_i", bitwidth)], # *full* wid
@@ -37,6 +41,9 @@ class VirtualRegPort(RegFileArray):
         self.rd_ports.append(RecordObject([("ren", n_regs),
                                           ("data_o", bitwidth)], # *full* wid
                                          name="full_rd"))
+        # now for internal use
+        self._wr_regs = self.write_reg_port(f"intw")
+        self._rd_regs = self.read_reg_port(f"intr")
 
     def elaborate(self, platform):
         m = super().elaborate(platform)
@@ -45,20 +52,23 @@ class VirtualRegPort(RegFileArray):
         # connect up: detect if read is requested on large (full) port
         # nothing fancy needed because reads are same-cycle
         rlast = self.rd_ports[-1]
+        ren_sig = Signal(reset_less=True)
+        comb += ren_sig.eq(rlast.ren.bool())
         print (rlast)
-        with m.If(self._get_en_sig([rlast], "ren") != 0):
-            # wire up the enable signals and accumulate the data
-            l = []
-            print (self._rdports)
-            for i, port in enumerate(self._rdports[:-1]):
-                print (port)
-                comb += port.ren.eq(1<<i) # port indices are *unary*-indexed
-                l.append(port.data_o)
+        with m.If(ren_sig):
+            # wire up the enable signals and chain-accumulate the data
+            print (self._rd_regs)
+            l = map(lambda port: port.data_o, self._rd_regs) # get port data(s)
+            le = map(lambda port: port.ren, self._rd_regs) # get port ren(s)
             comb += rlast.data_o.eq(Cat(*l)) # we like Cat on lists
+            comb += Cat(*le).eq(rlast.ren)
         with m.Else():
             # allow request through the corresponding lower indexed ports
-            for i, port in enumerate(self._rdports[:-1]):
-                comb += port.eq(self.rd_ports[i])
+            # TODO: make data_o and ren fields "directional" then simply
+            # use record "connect"
+            for i, port in enumerate(self._rd_regs):
+                comb += port.ren.eq(self.rd_ports[i].ren)
+                comb += self.rd_ports[i].data_o.eq(port.data_o)
 
         # connect up: detect if write is requested on large (full) port
         # however due to the delay (1 clock) on write, we also need to
@@ -67,27 +77,27 @@ class VirtualRegPort(RegFileArray):
         data_sig = Signal(reset_less=True) # sync (one clock delay)
 
         wlast = self.wr_ports[-1]
-        comb += en_sig.eq(self._get_en_sig([wlast], "wen") != 0)
+        comb += en_sig.eq(wlast.wen.bool())
         sync += data_sig.eq(en_sig)
 
         with m.If(en_sig):
-            # wire up the enable signals
-            for i, port in enumerate(self._wrports[:-1]):
-                comb += port.wen.eq(1<<i) # port indices are *unary*-indexed
+            # wire up the enable signals from the large (full) port
+            le = map(lambda port: port.wen, self._wr_regs) # get port wen(s)
+            comb += Cat(*le).eq(wlast.wen)
         with m.Else():
             # allow request through the corresponding lower indexed ports
-            for i, port in enumerate(self._wrports[:-1]):
-                comb += port.wen.eq(self.wn_ports[i].wen)
+            for i, port in enumerate(self._wr_regs):
+                comb += port.wen.eq(self.wr_ports[i].wen)
 
         # and (sigh) data is on one clock-delay, connect that too
         with m.If(data_sig):
-            # get list of all data_i and assign to them via Cat
-            l = map(lambda port: port.data_i, self._wrports[:-1])
+            # get list of all data_i (and wens) and assign to them via Cat
+            l = map(lambda port: port.data_i, self._wr_regs)
             comb += Cat(*l).eq(wlast.data_i)
         with m.Else():
             # allow data through the corresponding lower indexed ports
-            for i, port in enumerate(self._wrports[:-1]):
-                comb += self.wr_ports[i].data_i.eq(port.data_i)
+            for i, port in enumerate(self._wr_regs):
+                comb += port.data_i.eq(self.wr_ports[i].data_i)
 
         return m
 
@@ -100,7 +110,7 @@ class VirtualRegPort(RegFileArray):
 
 
 def test_regfile():
-    dut = VirtualRegPort(32, 4)
+    dut = VirtualRegPort(32, 8)
     ports=dut.ports()
     print ("ports", ports)
     vl = rtlil.convert(dut, ports=ports)