fix up Logical pipeline to produce HDL with XLEN=32
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sun, 27 Feb 2022 19:16:35 +0000 (19:16 +0000)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sun, 27 Feb 2022 19:16:35 +0000 (19:16 +0000)
fix Logical test_pipe_caller.py to use new regspeckls style

src/soc/fu/logical/bpermd.py
src/soc/fu/logical/main_stage.py
src/soc/fu/logical/pipe_data.py
src/soc/fu/logical/popcount.py
src/soc/fu/logical/test/test_pipe_caller.py

index dc086faefb70a5f217a6ee3cb894c4553a18371f..83eaf989ca08df99b4f23eba8dc026215a3dbab7 100644 (file)
@@ -58,15 +58,16 @@ class Bpermd(Elaboratable):
     def elaborate(self, platform):
         m = Module()
         perm = Signal(self.width, reset_less=True)
-        rb64 = [Signal(1, reset_less=True, name=f"rb64_{i}") for i in range(64)]
-        for i in range(64):
-            m.d.comb += rb64[i].eq(self.rb[63-i])
+        rb64 = [Signal(1, reset_less=True, name=f"rb64_{i}")
+                for i in range(self.width)]
+        for i in range(self.width):
+            m.d.comb += rb64[i].eq(self.rb[self.width-1-i])
         rb64 = Array(rb64)
-        for i in range(8):
+        for i in range(self.width//8):
             index = self.rs[8*i:8*i+8]
             idx = Signal(8, name=f"idx_{i}", reset_less=True)
             m.d.comb += idx.eq(index)
-            with m.If(idx < 64):
+            with m.If(idx < self.width):
                 m.d.comb += perm[i].eq(rb64[idx])
         m.d.comb += self.ra[0:8].eq(perm)
         return m
index 253664032fc16a1401665416a70e33688c6caa65..6a90395783e798165bd55576c769c9bf73144952 100644 (file)
@@ -6,6 +6,8 @@
 # to the output stage
 
 # Copyright (C) 2020 Michael Nolan <mtnolan2640@gmail.com>
+# Copyright (C) 2020, 2021 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
+
 from nmigen import (Module, Signal, Cat, Repl, Mux, Const, Array)
 from nmutil.pipemodbase import PipeModBase
 from nmutil.clz import CLZ
@@ -33,14 +35,15 @@ class LogicalMainStage(PipeModBase):
         return LogicalOutputData(self.pspec)
 
     def elaborate(self, platform):
+        XLEN = self.pspec.XLEN
         m = Module()
         comb = m.d.comb
         op, a, b, o = self.i.ctx.op, self.i.a, self.i.b, self.o.o
 
         comb += o.ok.eq(1) # overridden if no op activates
 
-        m.submodules.bpermd = bpermd = Bpermd(64)
-        m.submodules.popcount = popcount = Popcount()
+        m.submodules.bpermd = bpermd = Bpermd(XLEN)
+        m.submodules.popcount = popcount = Popcount(XLEN)
 
         ##########################
         # main switch for logic ops AND, OR and XOR, cmpb, parity, and popcount
@@ -84,12 +87,14 @@ class LogicalMainStage(PipeModBase):
                 par0 = Signal(reset_less=True)
                 par1 = Signal(reset_less=True)
                 comb += par0.eq(Cat(a[0], a[8], a[16], a[24]).xor())
-                comb += par1.eq(Cat(a[32], a[40], a[48], a[56]).xor())
+                if XLEN == 64:
+                    comb += par1.eq(Cat(a[32], a[40], a[48], a[56]).xor())
                 with m.If(op.data_len[3] == 1):
                     comb += o.data.eq(par0 ^ par1)
                 with m.Else():
                     comb += o[0].eq(par0)
-                    comb += o[32].eq(par1)
+                    if XLEN == 64:
+                        comb += o[32].eq(par1)
 
             ###################
             ###### cntlz v3.0B p99
@@ -99,7 +104,7 @@ class LogicalMainStage(PipeModBase):
                 count_right = Signal(reset_less=True)
                 comb += count_right.eq(XO[-1])
 
-                cntz_i = Signal(64, reset_less=True)
+                cntz_i = Signal(XLEN, reset_less=True)
                 a32 = Signal(32, reset_less=True)
                 comb += a32.eq(a[0:32])
 
@@ -108,7 +113,7 @@ class LogicalMainStage(PipeModBase):
                 with m.Else():
                     comb += cntz_i.eq(Mux(count_right, a[::-1], a))
 
-                m.submodules.clz = clz = CLZ(64)
+                m.submodules.clz = clz = CLZ(XLEN)
                 comb += clz.sig_in.eq(cntz_i)
                 comb += o.data.eq(Mux(op.is_32bit, clz.lz-32, clz.lz))
 
index 40a18bc214a6ac6a6a652238ae9c24570a856c07..359a2a595689ed66b5b15f2789e92b7a90b90998 100644 (file)
@@ -5,38 +5,45 @@ from soc.fu.logical.logical_input_record import CompLogicalOpSubset
 
 # input (and output) for logical initial stage (common input)
 class LogicalInputData(FUBaseData):
-    regspec = [('INT', 'ra', '0:63'), # RA
-               ('INT', 'rb', '0:63'), # RB/immediate
-               ('XER', 'xer_so', '32'),    # bit0: so
-               ]
     def __init__(self, pspec):
         super().__init__(pspec, False)
         # convenience
         self.a, self.b = self.ra, self.rb
 
+    @property
+    def regspec(self):
+        return [('INT', 'ra', self.intrange),  # RA
+               ('INT', 'rb', self.intrange),  # RB/immediate
+               ('XER', 'xer_so', '32'),    # bit0: so
+               ]
 
 # input to logical final stage (common output)
 class LogicalOutputData(FUBaseData):
-    regspec = [('INT', 'o', '0:63'),        # RT
-               ('CR', 'cr_a', '0:3'),
-               ('XER', 'xer_so', '32'),    # bit0: so
-               ]
     def __init__(self, pspec):
         super().__init__(pspec, True)
         # convenience
         self.cr0 = self.cr_a
 
+    @property
+    def regspec(self):
+        return [('INT', 'o', self.intrange),
+               ('CR', 'cr_a', '0:3'),
+               ('XER', 'xer_so', '32'),    # bit0: so
+               ]
+
 
 # output from logical final stage (common output) - note that XER.so
 # is *not* included (the only reason it's in the input is because of CR0)
 class LogicalOutputDataFinal(FUBaseData):
-    regspec = [('INT', 'o', '0:63'),        # RT
-               ('CR', 'cr_a', '0:3'),
-               ]
     def __init__(self, pspec):
         super().__init__(pspec, True)
         # convenience
         self.cr0 = self.cr_a
+    @property
+    def regspec(self):
+        return [('INT', 'o', self.intrange),
+               ('CR', 'cr_a', '0:3'),
+               ]
 
 
 class LogicalPipeSpec(CommonPipeSpec):
index ca90112d495c326996e16b1b11d93ef2649dfb12..5975149db345bdb28822d7ee683a47148e80c61a 100644 (file)
@@ -23,11 +23,13 @@ def array_of(count, bitwidth):
 
 
 class Popcount(Elaboratable):
-    def __init__(self):
-        self.a = Signal(64, reset_less=True)
-        self.b = Signal(64, reset_less=True)
+    def __init__(self, width=64):
+        self.width = width
+        self.a = Signal(width, reset_less=True)
+        self.b = Signal(width, reset_less=True)
         self.data_len = Signal(4, reset_less=True) # data len up to... err.. 8?
-        self.o = Signal(64, reset_less=True)
+        self.o = Signal(width, reset_less=True)
+        assert width in [32, 64], "only 32 or 64 bit supported for now"
 
     def elaborate(self, platform):
         m = Module()
@@ -38,11 +40,13 @@ class Popcount(Elaboratable):
         # creating arrays big enough to store the sum, each time
         pc = [a]
         # QTY32 2-bit (to take 2x 1-bit sums) etc.
-        work = [(32, 2), (16, 3), (8, 4), (4, 5), (2, 6), (1, 7)]
+        work = [(16, 3), (8, 4), (4, 5), (2, 6), (1, 7)]
+        if self.width == 64:
+            work = [(32, 2)] + work
         for l, bw in work: # l=number of add-reductions, bw=bitwidth
             pc.append(array_of(l, bw))
-        pc8 = pc[3]     # array of 8 8-bit counts (popcntb)
-        pc32 = pc[5]    # array of 2 32-bit counts (popcntw)
+        pc8 = pc[-4]     # array of 8 8-bit counts (popcntb)
+        pc32 = pc[-2]    # array of 2 32-bit counts (popcntw)
         popcnt = pc[-1]  # array of 1 64-bit count (popcntd)
         # cascade-tree of adds
         for idx, (l, bw) in enumerate(work):
@@ -54,12 +58,15 @@ class Popcount(Elaboratable):
         # decode operation length (1-hot)
         with m.If(data_len == 1):
             # popcntb - pack 8x 4-bit answers into 8x 8-bit output fields
-            for i in range(8):
+            for i in range(self.width//8):
                 comb += o[i*8:(i+1)*8].eq(pc8[i])
         with m.Elif(data_len == 4):
-            # popcntw - pack 2x 5-bit answers into 2x 32-bit output fields
-            for i in range(2):
-                comb += o[i*32:(i+1)*32].eq(pc32[i])
+            if self.width == 64:
+                # popcntw - pack 2x 5-bit answers into 2x 32-bit output fields
+                for i in range(2):
+                    comb += o[i*32:(i+1)*32].eq(pc32[i])
+            else:
+                comb += o.eq(popcnt[0])
         with m.Else():
             # popcntd - put 1x 6-bit answer into 64-bit output
             comb += o.eq(popcnt[0])
index 5ecbe2303bd1ca8b35d81801ad36ab63de99f4c3..5df6effc09109b45c399ad7e6c759bc824810e4e 100644 (file)
@@ -51,17 +51,17 @@ def set_alu_inputs(alu, dec2, sim):
 class LogicalIlangCase(TestAccumulatorBase):
 
     def case_ilang(self):
-        pspec = LogicalPipeSpec(id_wid=2, parent_pspec=None)
+        class PPspec:
+            XLEN = 64
+        pps = PPspec()
+        pspec = LogicalPipeSpec(id_wid=2, parent_pspec=pps)
         alu = LogicalBasePipe(pspec)
         vl = rtlil.convert(alu, ports=alu.ports())
         with open("logical_pipeline.il", "w") as f:
             f.write(vl)
 
 
-class TestRunner(FHDLTestCase):
-    def __init__(self, test_data):
-        super().__init__("run_all")
-        self.test_data = test_data
+class TestRunner(unittest.TestCase):
 
     def execute(self, alu, instruction, pdecode2, test):
         print(test.name)
@@ -107,7 +107,9 @@ class TestRunner(FHDLTestCase):
                                               simulator, code)
             yield Settle()
 
-    def run_all(self):
+    def test_it(self):
+        test_data = LogicalIlangCase().test_data + \
+                    LogicalTestCase().test_data
         m = Module()
         comb = m.d.comb
         instruction = Signal(32)
@@ -116,7 +118,10 @@ class TestRunner(FHDLTestCase):
 
         m.submodules.pdecode2 = pdecode2 = PowerDecode2(pdecode)
 
-        pspec = LogicalPipeSpec(id_wid=2, parent_pspec=None)
+        class PPspec:
+            XLEN = 64
+        pps = PPspec()
+        pspec = LogicalPipeSpec(id_wid=2, parent_pspec=pps)
         m.submodules.alu = alu = LogicalBasePipe(pspec)
 
         comb += alu.p.i_data.ctx.op.eq_from_execute1(pdecode2.do)
@@ -127,7 +132,7 @@ class TestRunner(FHDLTestCase):
         sim.add_clock(1e-6)
 
         def process():
-            for test in self.test_data:
+            for test in test_data:
                 print(test.name)
                 program = test.program
                 with self.subTest(test.name):
@@ -163,10 +168,4 @@ class TestRunner(FHDLTestCase):
 
 
 if __name__ == "__main__":
-    unittest.main(exit=False)
-    suite = unittest.TestSuite()
-    suite.addTest(TestRunner(LogicalIlangCase().test_data))
-    suite.addTest(TestRunner(LogicalTestCase().test_data))
-
-    runner = unittest.TextTestRunner()
-    runner.run(suite)
+    unittest.main()