split out RegSpecs into separate module
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sat, 23 May 2020 18:05:31 +0000 (19:05 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sat, 23 May 2020 18:05:31 +0000 (19:05 +0100)
src/soc/experiment/compalu_multi.py
src/soc/fu/regspec.py [new file with mode: 0644]

index fe42f07d72236f5cc273dd542d8d3591a9e9f483..88ad54868c084f5c9554c47ed32af012c51b8c32 100644 (file)
@@ -8,6 +8,7 @@ from nmutil.iocontrol import RecordObject
 
 from soc.decoder.power_decoder2 import Data
 from soc.decoder.power_enums import InternalOp
+from soc.fu.regspec import RegSpec, RegSpecALUAPI
 
 
 """ Computation Unit (aka "ALU Manager").
@@ -68,22 +69,8 @@ def go_record(n, name):
     return r
 
 # see https://libre-soc.org/3d_gpu/architecture/regfile/ section on regspecs
-def get_regspec_bitwidth(regspec, srcdest, idx):
-    bitspec = regspec[srcdest][idx]
-    wid = 0
-    print (bitspec)
-    for ranges in bitspec[2].split(","):
-        ranges = ranges.split(":")
-        print (ranges)
-        if len(ranges) == 1: # only one bit
-            wid += 1
-        else:
-            start, end = map(int, ranges)
-            wid += (end-start)+1
-    return wid
-
-
-class CompUnitRecord(RecordObject):
+
+class CompUnitRecord(RegSpec, RecordObject):
     """CompUnitRecord
 
     base class for Computation Units, to provide a uniform API
@@ -100,14 +87,8 @@ class CompUnitRecord(RecordObject):
     see https://libre-soc.org/3d_gpu/architecture/regfile/ section on regspecs
     """
     def __init__(self, subkls, rwid, n_src=None, n_dst=None, name=None):
+        RegSpec.__init__(self, rwid, n_src, n_dst)
         RecordObject.__init__(self, name)
-        self._rwid = rwid
-        if isinstance(rwid, int):
-            # rwid: integer (covers all registers)
-            self._n_src, self._n_dst = n_src, n_dst
-        else:
-            # rwid: a regspec.
-            self._n_src, self._n_dst = len(rwid[0]), len(rwid[1])
         self._subkls = subkls
 
         src = []
@@ -143,44 +124,6 @@ class CompUnitRecord(RecordObject):
         self.busy_o = Signal(reset_less=True) # fn busy out
         self.done_o = Signal(reset_less=True)
 
-    def _get_dstwid(self, i):
-        if isinstance(self._rwid, int):
-            return self._rwid
-        return get_regspec_bitwidth(self._rwid, 1, i)
-
-    def _get_srcwid(self, i):
-        if isinstance(self._rwid, int):
-            return self._rwid
-        return get_regspec_bitwidth(self._rwid, 0, i)
-
-
-class RegSpecALUAPI:
-    def __init__(self, rwid, alu):
-        """RegSpecAPI
-
-        * :rwid:       regspec
-        * :alu:        ALU covered by this regspec
-        """
-        self.rwid = rwid
-        self.alu = alu # actual ALU - set as a "submodule" of the CU
-
-    def get_out(self, i):
-        if isinstance(self.rwid, int): # old - testing - API (rwid is int)
-            return self.alu.out[i]
-        # regspec-based API: look up variable through regspec according to row number
-        return getattr(self.alu.n.data_o, self.rwid[1][i][1])
-
-    def get_in(self, i):
-        if isinstance(self.rwid, int): # old - testing - API (rwid is int)
-            return self.alu.i[i]
-        # regspec-based API: look up variable through regspec according to row number
-        return getattr(self.alu.p.data_i, self.rwid[0][i][1])
-
-    def get_op(self):
-        if isinstance(self.rwid, int): # old - testing - API (rwid is int)
-            return self.alu.op
-        return self.alu.p.data_i.ctx.op
-
 
 class MultiCompUnit(RegSpecALUAPI, Elaboratable):
     def __init__(self, rwid, alu, opsubsetkls, n_src=2, n_dst=1):
diff --git a/src/soc/fu/regspec.py b/src/soc/fu/regspec.py
new file mode 100644 (file)
index 0000000..31931f5
--- /dev/null
@@ -0,0 +1,64 @@
+# see https://libre-soc.org/3d_gpu/architecture/regfile/ section on regspecs
+
+def get_regspec_bitwidth(regspec, srcdest, idx):
+    bitspec = regspec[srcdest][idx]
+    wid = 0
+    print (bitspec)
+    for ranges in bitspec[2].split(","):
+        ranges = ranges.split(":")
+        print (ranges)
+        if len(ranges) == 1: # only one bit
+            wid += 1
+        else:
+            start, end = map(int, ranges)
+            wid += (end-start)+1
+    return wid
+
+
+class RegSpec:
+    def __init__(self, rwid, n_src=None, n_dst=None, name=None):
+        self._rwid = rwid
+        if isinstance(rwid, int):
+            # rwid: integer (covers all registers)
+            self._n_src, self._n_dst = n_src, n_dst
+        else:
+            # rwid: a regspec.
+            self._n_src, self._n_dst = len(rwid[0]), len(rwid[1])
+
+    def _get_dstwid(self, i):
+        if isinstance(self._rwid, int):
+            return self._rwid
+        return get_regspec_bitwidth(self._rwid, 1, i)
+
+    def _get_srcwid(self, i):
+        if isinstance(self._rwid, int):
+            return self._rwid
+        return get_regspec_bitwidth(self._rwid, 0, i)
+
+
+class RegSpecALUAPI:
+    def __init__(self, rwid, alu):
+        """RegSpecAPI
+
+        * :rwid:       regspec
+        * :alu:        ALU covered by this regspec
+        """
+        self.rwid = rwid
+        self.alu = alu # actual ALU - set as a "submodule" of the CU
+
+    def get_out(self, i):
+        if isinstance(self.rwid, int): # old - testing - API (rwid is int)
+            return self.alu.out[i]
+        # regspec-based API: look up variable through regspec according to row number
+        return getattr(self.alu.n.data_o, self.rwid[1][i][1])
+
+    def get_in(self, i):
+        if isinstance(self.rwid, int): # old - testing - API (rwid is int)
+            return self.alu.i[i]
+        # regspec-based API: look up variable through regspec according to row number
+        return getattr(self.alu.p.data_i, self.rwid[0][i][1])
+
+    def get_op(self):
+        if isinstance(self.rwid, int): # old - testing - API (rwid is int)
+            return self.alu.op
+        return self.alu.p.data_i.ctx.op