Begin adding proof for decoder stage 1
authorMichael Nolan <mtnolan2640@gmail.com>
Mon, 16 Mar 2020 19:15:49 +0000 (15:15 -0400)
committerMichael Nolan <mtnolan2640@gmail.com>
Wed, 18 Mar 2020 13:00:31 +0000 (09:00 -0400)
src/soc/decoder/formal/proof_decoder.py [new file with mode: 0644]

diff --git a/src/soc/decoder/formal/proof_decoder.py b/src/soc/decoder/formal/proof_decoder.py
new file mode 100644 (file)
index 0000000..94e0c91
--- /dev/null
@@ -0,0 +1,119 @@
+from nmigen import Module, Signal, Elaboratable, Cat
+from nmigen.asserts import Assert, AnyConst, Assume
+from nmigen.test.utils import FHDLTestCase
+
+from soc.decoder.power_decoder import create_pdecode, PowerOp
+from soc.decoder.power_enums import (In1Sel, In2Sel, In3Sel,
+                                     OutSel, RC, Form, Function,
+                                     LdstLen, CryIn,
+                                     InternalOp, SPR, get_csv)
+from soc.decoder.power_decoder2 import (PowerDecode2,
+                                        Decode2ToExecute1Type)
+import unittest
+import pdb
+
+class Driver(Elaboratable):
+    def __init__(self):
+        self.instruction = Signal(32, reset_less=True)
+        self.m = None
+        self.comb = None
+
+    def elaborate(self, platform):
+        self.m = Module()
+        self.comb = self.m.d.comb
+        self.instruction = Signal(32)
+
+        self.comb += self.instruction.eq(AnyConst(32))
+
+        pdecode = create_pdecode()
+
+        self.m.submodules.pdecode2 = pdecode2 = PowerDecode2(pdecode)
+        dec1 = pdecode2.dec
+        self.comb += pdecode2.dec.opcode_in.eq(self.instruction)
+
+        # ignore special decoding of nop
+        self.comb += Assume(self.instruction != 0x60000000)
+
+        #self.assert_dec1_decode(dec1, dec1.dec)
+
+        self.assert_form(dec1, pdecode2)
+        return self.m
+
+    def assert_dec1_decode(self, dec1, decoders):
+        if not isinstance(decoders, list):
+            decoders = [decoders]
+        for d in decoders:
+            print(d.pattern)
+            opcode_switch = Signal(d.bitsel[1] - d.bitsel[0])
+            self.comb += opcode_switch.eq(
+                self.instruction[d.bitsel[0]:d.bitsel[1]])
+            with self.m.Switch(opcode_switch):
+                self.handle_subdecoders(dec1, d)
+                for row in d.opcodes:
+                    opcode = row['opcode']
+                    if d.opint and '-' not in opcode:
+                        opcode = int(opcode, 0)
+                    if not row['unit']:
+                        continue
+                    with self.m.Case(opcode):
+                        self.comb += self.assert_dec1_signals(dec1, row)
+
+    def handle_subdecoders(self, dec1, decoders):
+        for dec in decoders.subdecoders:
+            if isinstance(dec, list):
+                pattern = dec[0].pattern
+            else:
+                pattern = dec.pattern
+            with self.m.Case(pattern):
+                self.assert_dec1_decode(dec1, dec)
+
+    def assert_dec1_signals(self, dec, row):
+        op = dec.op
+        return [Assert(op.function_unit == Function[row['unit']]),
+                Assert(op.internal_op == InternalOp[row['internal op']]),
+                Assert(op.in1_sel == In1Sel[row['in1']]),
+                Assert(op.in2_sel == In2Sel[row['in2']]),
+                Assert(op.in3_sel == In3Sel[row['in3']]),
+                Assert(op.out_sel == OutSel[row['out']]),
+                Assert(op.ldst_len == LdstLen[row['ldst len']]),
+                Assert(op.rc_sel == RC[row['rc']]),
+                Assert(op.cry_in == CryIn[row['cry in']]),
+                Assert(op.form == Form[row['form']]),
+                ]
+
+    def assert_form(self, dec, dec2):
+        with self.m.Switch(dec.op.form):
+            with self.m.Case(Form.A):
+                self.comb += Assert(dec2.e.write_reg.data ==
+                                    self.instr_bits(6, 10))
+                self.comb += Assert(dec2.e.read_reg1.data ==
+                                    self.instr_bits(11, 15))
+                self.comb += Assert(dec2.e.read_reg2.data ==
+                                    self.instr_bits(16, 20))
+                # The table has fields for XO and Rc, but idk what they correspond to
+            with self.m.Case(Form.B):
+                pass
+            with self.m.Case(Form.D):
+                self.comb += Assert(dec.op.in1_sel.matches(
+                    In1Sel.NONE, In1Sel.RA, In1Sel.RA_OR_ZERO))
+                self.comb += Assert(dec.op.in2_sel.matches(
+                    In2Sel.CONST_UI, In2Sel.CONST_SI, In2Sel.CONST_UI_HI,
+                    In2Sel.CONST_SI_HI))
+                self.comb += Assert(dec.op.out_sel.matches(
+                    OutSel.NONE, OutSel.RT, OutSel.RA))
+                        
+                
+                
+        
+    def instr_bits(self, start, end=None):
+        if not end:
+            end = start
+        return self.instruction[::-1][start:end+1]
+
+class DecoderTestCase(FHDLTestCase):
+    def test_decoder(self):
+        module = Driver()
+        self.assertFormal(module, mode="bmc", depth=4)
+
+if __name__ == '__main__':
+    unittest.main()