add logical compunit test
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sun, 31 May 2020 23:07:42 +0000 (00:07 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sun, 31 May 2020 23:07:42 +0000 (00:07 +0100)
src/soc/fu/compunits/compunits.py
src/soc/fu/compunits/test/test_alu_compunit.py
src/soc/fu/compunits/test/test_compunit.py
src/soc/fu/compunits/test/test_logical_compunit.py [new file with mode: 0644]
src/soc/fu/logical/logical_input_record.py
src/soc/fu/logical/pipe_data.py

index bfaa693a7629f1e0fc05f5454ad7a204aab8bc26..d40549d5324dc50ef38e6ba88e1bca9a42dd6451 100644 (file)
@@ -48,6 +48,9 @@ from soc.experiment.compalu_multi import MultiCompUnit
 from soc.fu.alu.pipeline import ALUBasePipe
 from soc.fu.alu.pipe_data import ALUPipeSpec
 
+from soc.fu.logical.pipeline import LogicalBasePipe
+from soc.fu.logical.pipe_data import LogicalPipeSpec
+
 from soc.fu.cr.pipeline import CRBasePipe
 from soc.fu.cr.pipe_data import CRPipeSpec
 
@@ -97,6 +100,9 @@ class FunctionUnitBaseMulti:
 class ALUFunctionUnit(FunctionUnitBaseSingle):
     def __init__(self): super().__init__(ALUPipeSpec, ALUBasePipe)
 
+class LogicalFunctionUnit(FunctionUnitBaseSingle):
+    def __init__(self): super().__init__(LogicalPipeSpec, LogicalBasePipe)
+
 class CRFunctionUnit(FunctionUnitBaseSingle):
     def __init__(self): super().__init__(CRPipeSpec, CRBasePipe)
 
index da867e77ba2a1f7e61e37c23c3b7a803312fc5ef..840bda32b59dabc8f5c151fd871bf5c54277ec42 100644 (file)
@@ -1,5 +1,5 @@
 import unittest
-from soc.decoder.power_enums import (XER_bits,)
+from soc.decoder.power_enums import (XER_bits, Function)
 
 # XXX bad practice: use of global variables
 from soc.fu.alu.test.test_pipe_caller import ALUTestCase # creates the tests
@@ -11,7 +11,8 @@ from soc.fu.compunits.test.test_compunit import TestRunner
 
 class ALUTestRunner(TestRunner):
     def __init__(self, test_data):
-        super().__init__(test_data, ALUFunctionUnit, self)
+        super().__init__(test_data, ALUFunctionUnit, self,
+                         Function.ALU)
 
     def get_cu_inputs(self, dec2, sim):
         """naming (res) must conform to ALUFunctionUnit input regspec
index 06aef9fe4d88e91c891d115758008520fcb0be79..62d2f2aaa9e4329c4ae1a75857038e5f4525c72e 100644 (file)
@@ -104,11 +104,12 @@ def get_cu_rd_mask(n_src, inp):
 
 
 class TestRunner(FHDLTestCase):
-    def __init__(self, test_data, fukls, iodef):
+    def __init__(self, test_data, fukls, iodef, funit):
         super().__init__("run_all")
         self.test_data = test_data
         self.fukls = fukls
-        self.iodef = iodef 
+        self.iodef = iodef
+        self.funit = funit
 
     def run_all(self):
         m = Module()
@@ -149,7 +150,7 @@ class TestRunner(FHDLTestCase):
                     yield instruction.eq(ins)          # raw binary instr.
                     yield Settle()
                     fn_unit = yield pdecode2.e.fn_unit
-                    self.assertEqual(fn_unit, Function.ALU.value)
+                    self.assertEqual(fn_unit, self.funit.value)
 
                     # set operand and get inputs
                     yield from set_operand(cu, pdecode2, sim)
diff --git a/src/soc/fu/compunits/test/test_logical_compunit.py b/src/soc/fu/compunits/test/test_logical_compunit.py
new file mode 100644 (file)
index 0000000..1c9258b
--- /dev/null
@@ -0,0 +1,90 @@
+import unittest
+from soc.decoder.power_enums import (XER_bits, Function)
+
+# XXX bad practice: use of global variables
+from soc.fu.logical.test.test_pipe_caller import LogicalTestCase
+from soc.fu.logical.test.test_pipe_caller import test_data
+
+from soc.fu.compunits.compunits import LogicalFunctionUnit
+from soc.fu.compunits.test.test_compunit import TestRunner
+
+
+class LogicalTestRunner(TestRunner):
+    def __init__(self, test_data):
+        super().__init__(test_data, LogicalFunctionUnit, self,
+                         Function.LOGICAL)
+
+    def get_cu_inputs(self, dec2, sim):
+        """naming (res) must conform to LogicalFunctionUnit input regspec
+        """
+        res = {}
+
+        # RA (or RC)
+        reg3_ok = yield dec2.e.read_reg3.ok
+        reg1_ok = yield dec2.e.read_reg1.ok
+        assert reg3_ok != reg1_ok
+        if reg3_ok:
+            data1 = yield dec2.e.read_reg3.data
+            res['a'] = sim.gpr(data1).value
+        elif reg1_ok:
+            data1 = yield dec2.e.read_reg1.data
+            res['a'] = sim.gpr(data1).value
+
+        # RB (or immediate)
+        reg2_ok = yield dec2.e.read_reg2.ok
+        if reg2_ok:
+            data2 = yield dec2.e.read_reg2.data
+            res['b'] = sim.gpr(data2).value
+
+        return res
+
+    def check_cu_outputs(self, res, dec2, sim, code):
+        """naming (res) must conform to LogicalFunctionUnit output regspec
+        """
+
+        # RT
+        out_reg_valid = yield dec2.e.write_reg.ok
+        if out_reg_valid:
+            write_reg_idx = yield dec2.e.write_reg.data
+            expected = sim.gpr(write_reg_idx).value
+            cu_out = res['o']
+            print(f"expected {expected:x}, actual: {cu_out:x}")
+            self.assertEqual(expected, cu_out, code)
+
+        rc = yield dec2.e.rc.data
+        op = yield dec2.e.insn_type
+        cridx_ok = yield dec2.e.write_cr.ok
+        cridx = yield dec2.e.write_cr.data
+
+        print ("check extra output", repr(code), cridx_ok, cridx)
+
+        if rc:
+            self.assertEqual(cridx_ok, 1, code)
+            self.assertEqual(cridx, 0, code)
+
+        # CR (CR0-7)
+        if cridx_ok:
+            cr_expected = sim.crl[cridx].get_range().value
+            cr_actual = res['cr0']
+            print ("CR", cridx, cr_expected, cr_actual)
+            self.assertEqual(cr_expected, cr_actual, "CR%d %s" % (cridx, code))
+
+        # XER.ca
+        cry_out = yield dec2.e.output_carry
+        if cry_out:
+            expected_carry = 1 if sim.spr['XER'][XER_bits['CA']] else 0
+            xer_ca = res['xer_ca']
+            real_carry = xer_ca & 0b1 # XXX CO not CO32
+            self.assertEqual(expected_carry, real_carry, code)
+            expected_carry32 = 1 if sim.spr['XER'][XER_bits['CA32']] else 0
+            real_carry32 = bool(xer_ca & 0b10) # XXX CO32
+            self.assertEqual(expected_carry32, real_carry32, code)
+
+
+if __name__ == "__main__":
+    unittest.main(exit=False)
+    suite = unittest.TestSuite()
+    suite.addTest(LogicalTestRunner(test_data))
+
+    runner = unittest.TextTestRunner()
+    runner.run(suite)
index c6641a0145f2ec29d61bce923aa24e82b1a9d17a..34d1dd917bc26749fb7c3112ae367b0057d38558 100644 (file)
@@ -21,6 +21,7 @@ class CompLogicalOpSubset(Record):
                   ('zero_a', 1),
                   ('input_carry', CryIn),
                   ('invert_out', 1),
+                  ('write_cr', Layout((("data", 3), ("ok", 1)))), # Data
                   ('output_carry', 1),
                   ('is_32bit', 1),
                   ('is_signed', 1),
index ccb6d95e7c4e660e08d68113bf16a9ddd03509d9..86e036226a091794d7001a8898918194d5cb73d5 100644 (file)
@@ -8,7 +8,7 @@ from soc.fu.logical.logical_input_record import CompLogicalOpSubset
 
 class LogicalInputData(IntegerData):
     regspec = [('INT', 'a', '0:63'),
-               ('INT', 'rb', '0:63'),
+               ('INT', 'b', '0:63'),
                ]
     def __init__(self, pspec):
         super().__init__(pspec)