convert SPRs and others to Data.data/ok
[soc.git] / src / regfile / regfile.py
index 3cb5ef4507711a02ae2ebf3f22657c904e5255bd..b1d6f1c6717351f7b38be806bb25462e51f3bbf0 100644 (file)
@@ -10,8 +10,9 @@ import operator
 
 
 class Register(Elaboratable):
-    def __init__(self, width):
+    def __init__(self, width, writethru=True):
         self.width = width
+        self.writethru = writethru
         self._rdports = []
         self._wrports = []
 
@@ -31,18 +32,21 @@ class Register(Elaboratable):
 
     def elaborate(self, platform):
         m = Module()
-        reg = Signal(self.width, name="reg")
+        self.reg = reg = Signal(self.width, name="reg")
 
         # read ports. has write-through detection (returns data written)
         for rp in self._rdports:
-            wr_detect = Signal(reset_less=False)
             with m.If(rp.ren):
-                m.d.comb += wr_detect.eq(0)
-                for wp in self._wrports:
-                    with m.If(wp.wen):
-                        m.d.comb += rp.data_o.eq(wp.data_i)
-                        m.d.comb += wr_detect.eq(1)
-                with m.If(~wr_detect):
+                if self.writethru:
+                    wr_detect = Signal(reset_less=False)
+                    m.d.comb += wr_detect.eq(0)
+                    for wp in self._wrports:
+                        with m.If(wp.wen):
+                            m.d.comb += rp.data_o.eq(wp.data_i)
+                            m.d.comb += wr_detect.eq(1)
+                    with m.If(~wr_detect):
+                        m.d.comb += rp.data_o.eq(reg)
+                else:
                     m.d.comb += rp.data_o.eq(reg)
 
         # write ports, don't allow write to address 0 (ignore it)
@@ -61,16 +65,16 @@ class Register(Elaboratable):
     def ports(self):
         res = list(self)
 
-def treereduce(tree):
+def treereduce(tree, attr="data_o"):
     #print ("treereduce", tree)
     if not isinstance(tree, list):
         return tree
     if len(tree) == 1:
-        return tree[0].data_o
+        return getattr(tree[0], attr)
     if len(tree) == 2:
-        return tree[0].data_o | tree[1].data_o
-    splitpoint = len(tree) // 2
-    return treereduce(tree[:splitpoint]) | treereduce(tree[splitpoint:])
+        return getattr(tree[0], attr) | getattr(tree[1], attr)
+    split = len(tree) // 2
+    return treereduce(tree[:split], attr) | treereduce(tree[split:], attr)
 
 
 class RegFileArray(Elaboratable):
@@ -229,6 +233,36 @@ def regfile_sim(dut, rp, wp):
     data = yield rp.data_o
     print (data)
 
+def regfile_array_sim(dut, rp1, rp2, wp):
+    yield wp.data_i.eq(2)
+    yield wp.wen.eq(1<<1)
+    yield
+    yield wp.wen.eq(0)
+    yield rp1.ren.eq(1<<1)
+    yield
+    data = yield rp1.data_o
+    print (data)
+    assert data == 2
+
+    yield rp1.ren.eq(1<<5)
+    yield rp2.ren.eq(1<<1)
+    yield wp.wen.eq(1<<5)
+    yield wp.data_i.eq(6)
+    data = yield rp1.data_o
+    print (data)
+    yield
+    yield wp.wen.eq(0)
+    yield rp1.ren.eq(0)
+    yield rp2.ren.eq(0)
+    data1 = yield rp1.data_o
+    print (data1)
+    data2 = yield rp2.data_o
+    print (data2)
+    assert data1 == 6
+    yield
+    data = yield rp1.data_o
+    print (data)
+
 def test_regfile():
     dut = RegFile(32, 8)
     rp = dut.read_port()
@@ -240,7 +274,8 @@ def test_regfile():
     run_simulation(dut, regfile_sim(dut, rp, wp), vcd_name='test_regfile.vcd')
 
     dut = RegFileArray(32, 8)
-    rp = dut.read_port("read")
+    rp1 = dut.read_port("read1")
+    rp2 = dut.read_port("read2")
     wp = dut.write_port("write")
     ports=dut.ports()
     print ("ports", ports)
@@ -248,7 +283,8 @@ def test_regfile():
     with open("test_regfile_array.il", "w") as f:
         f.write(vl)
 
-    #run_simulation(dut, regfile_sim(dut, rp, wp), vcd_name='test_regfile.vcd')
+    run_simulation(dut, regfile_array_sim(dut, rp1, rp2, wp),
+                   vcd_name='test_regfile_array.vcd')
 
 if __name__ == '__main__':
     test_regfile()