add srcstep and correct PC-advancing during Sub-PC looping in ISACaller
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Fri, 12 Feb 2021 14:41:48 +0000 (14:41 +0000)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Fri, 12 Feb 2021 14:41:48 +0000 (14:41 +0000)
src/soc/decoder/isa/caller.py
src/soc/decoder/isa/test_caller.py
src/soc/decoder/isa/test_caller_svp64.py

index 7ade13afd13381ab3df36fde8343973e39d0fbc3..4a38a1ede376a61c3402c20b46715dabfe4b92ce 100644 (file)
@@ -211,14 +211,17 @@ class GPR(dict):
 class PC:
     def __init__(self, pc_init=0):
         self.CIA = SelectableInt(pc_init, 64)
 class PC:
     def __init__(self, pc_init=0):
         self.CIA = SelectableInt(pc_init, 64)
-        self.NIA = self.CIA + SelectableInt(4, 64)
+        self.NIA = self.CIA + SelectableInt(4, 64) # only true for v3.0B!
+
+    def update_nia(self, is_svp64):
+        increment = 8 if is_svp64 else 4
+        self.NIA = self.CIA + SelectableInt(increment, 64)
 
     def update(self, namespace, is_svp64):
         """updates the program counter (PC) by 4 if v3.0B mode or 8 if SVP64
         """
 
     def update(self, namespace, is_svp64):
         """updates the program counter (PC) by 4 if v3.0B mode or 8 if SVP64
         """
-        increment = 8 if is_svp64 else 4
         self.CIA = namespace['NIA'].narrow(64)
         self.CIA = namespace['NIA'].narrow(64)
-        self.NIA = self.CIA + SelectableInt(increment, 64)
+        self.update_nia(is_svp64)
         namespace['CIA'] = self.CIA
         namespace['NIA'] = self.NIA
 
         namespace['CIA'] = self.CIA
         namespace['NIA'] = self.NIA
 
@@ -695,6 +698,7 @@ class ISACaller:
         self.is_svp64_mode = ((major == 0b000001) and
                               pfx.insn[7].value == 0b1 and
                               pfx.insn[9].value == 0b1)
         self.is_svp64_mode = ((major == 0b000001) and
                               pfx.insn[7].value == 0b1 and
                               pfx.insn[9].value == 0b1)
+        self.pc.update_nia(self.is_svp64_mode)
         if not self.is_svp64_mode:
             return
 
         if not self.is_svp64_mode:
             return
 
@@ -863,6 +867,9 @@ class ISACaller:
             dest_cr, src_cr, src_byname, dest_byname = False, False, {}, {}
         print ("sv rm", sv_rm, dest_cr, src_cr, src_byname, dest_byname)
 
             dest_cr, src_cr, src_byname, dest_byname = False, False, {}, {}
         print ("sv rm", sv_rm, dest_cr, src_cr, src_byname, dest_byname)
 
+        # get SVSTATE srcstep.  TODO: dststep (twin predication)
+        srcstep = self.svstate.srcstep.asint(msb0=True)
+
         # main input registers (RT, RA ...)
         inputs = []
         for name in input_names:
         # main input registers (RT, RA ...)
         inputs = []
         for name in input_names:
@@ -873,6 +880,10 @@ class ISACaller:
                 # doing this is not part of svp64, it's because output
                 # registers, to be modified, need to be in the namespace.
                 regnum, is_vec = yield from get_pdecode_idx_out(self.dec2, name)
                 # doing this is not part of svp64, it's because output
                 # registers, to be modified, need to be in the namespace.
                 regnum, is_vec = yield from get_pdecode_idx_out(self.dec2, name)
+            # here's where we go "vector".  TODO: zero-testing (RA_IS_ZERO)
+            if is_vec:
+                regnum += srcstep # TODO, elwidth overrides
+
             # in case getting the register number is needed, _RA, _RB
             regname = "_" + name
             self.namespace[regname] = regnum
             # in case getting the register number is needed, _RA, _RB
             regname = "_" + name
             self.namespace[regname] = regnum
@@ -943,6 +954,9 @@ class ISACaller:
         if rc_en:
             self.handle_comparison(results)
 
         if rc_en:
             self.handle_comparison(results)
 
+        # svp64 loop can end early if the dest is scalar
+        svp64_dest_vector = False
+
         # any modified return results?
         if info.write_regs:
             for name, output in zip(output_names, results):
         # any modified return results?
         if info.write_regs:
             for name, output in zip(output_names, results):
@@ -971,13 +985,15 @@ class ISACaller:
                         # temporary hack for not having 2nd output
                         regnum = yield getattr(self.decoder, name)
                         is_vec = False
                         # temporary hack for not having 2nd output
                         regnum = yield getattr(self.decoder, name)
                         is_vec = False
+                    # here's where we go "vector".
+                    if is_vec:
+                        regnum += srcstep # TODO, elwidth overrides
+                        svp64_dest_vector = True
                     print('writing reg %d %s' % (regnum, str(output)), is_vec)
                     if output.bits > 64:
                         output = SelectableInt(output.value, 64)
                     self.gpr[regnum] = output
 
                     print('writing reg %d %s' % (regnum, str(output)), is_vec)
                     if output.bits > 64:
                         output = SelectableInt(output.value, 64)
                     self.gpr[regnum] = output
 
-        print("end of call", self.namespace['CIA'], self.namespace['NIA'])
-
         # check if it is the SVSTATE.src/dest step that needs incrementing
         # this is our Sub-Program-Counter loop from 0 to VL-1
         if self.is_svp64_mode:
         # check if it is the SVSTATE.src/dest step that needs incrementing
         # this is our Sub-Program-Counter loop from 0 to VL-1
         if self.is_svp64_mode:
@@ -988,16 +1004,23 @@ class ISACaller:
             print ("    svstate.vl", vl)
             print ("    svstate.mvl", mvl)
             print ("    svstate.srcstep", srcstep)
             print ("    svstate.vl", vl)
             print ("    svstate.mvl", mvl)
             print ("    svstate.srcstep", srcstep)
-            # check if srcstep needs incrementing by one
-            if srcstep != vl-1:
+            # check if srcstep needs incrementing by one, stop PC advancing
+            if svp64_dest_vector and srcstep != vl-1:
                 self.svstate.srcstep += SelectableInt(1, 7)
                 self.svstate.srcstep += SelectableInt(1, 7)
+                self.pc.NIA.value = self.pc.CIA.value
+                self.namespace['NIA'] = self.pc.NIA
+                print("end of sub-pc call", self.namespace['CIA'],
+                                     self.namespace['NIA'])
                 return # DO NOT allow PC to update whilst Sub-PC loop running
             # reset to zero
             self.svstate.srcstep[0:7] = 0
             print ("    svstate.srcstep loop end (PC to update)")
                 return # DO NOT allow PC to update whilst Sub-PC loop running
             # reset to zero
             self.svstate.srcstep[0:7] = 0
             print ("    svstate.srcstep loop end (PC to update)")
+            self.pc.update_nia(self.is_svp64_mode)
+            self.namespace['NIA'] = self.pc.NIA
 
         # UPDATE program counter
         self.pc.update(self.namespace, self.is_svp64_mode)
 
         # UPDATE program counter
         self.pc.update(self.namespace, self.is_svp64_mode)
+        print("end of call", self.namespace['CIA'], self.namespace['NIA'])
 
 
 def inject():
 
 
 def inject():
index 8f190ca0625bf3b5e2bb06d1d58a83b43aed5ca6..691d9a71357b2fd2211e946fa0f4d731f2b70775 100644 (file)
@@ -53,7 +53,7 @@ def run_tst(generator, initial_regs, initial_sprs=None, svstate=0):
             yield Settle()
 
             ins, code = instructions[index]
             yield Settle()
 
             ins, code = instructions[index]
-            print("0x{:X}".format(ins & 0xffffffff))
+            print("    0x{:X}".format(ins & 0xffffffff))
             opname = code.split(' ')[0]
             print(code, opname)
 
             opname = code.split(' ')[0]
             print(code, opname)
 
index 90f2d40996cec8a2a20a3dac569e80ab9557982a..c164b91c1e985c79702d24cd6ff7349bbf441d2f 100644 (file)
@@ -17,7 +17,10 @@ from soc.sv.trans.svp64 import SVP64Asm
 class DecoderTestCase(FHDLTestCase):
 
     def test_sv_add(self):
 class DecoderTestCase(FHDLTestCase):
 
     def test_sv_add(self):
-        isa = SVP64Asm(['sv.add 1, 5, 9'
+        # adds:
+        #       1 = 5 + 9   => 0x5555 = 0x4321+0x1234
+        #       2 = 6 + 10  => 0x3334 = 0x2223+0x1111
+        isa = SVP64Asm(['sv.add 1.v, 5.v, 9.v'
                        ])
 
         lst = list(isa)
                        ])
 
         lst = list(isa)
@@ -34,6 +37,53 @@ class DecoderTestCase(FHDLTestCase):
         with Program(lst, bigendian=False) as program:
             sim = self.run_tst_program(program, initial_regs, svstate)
             self.assertEqual(sim.gpr(1), SelectableInt(0x5555, 64))
         with Program(lst, bigendian=False) as program:
             sim = self.run_tst_program(program, initial_regs, svstate)
             self.assertEqual(sim.gpr(1), SelectableInt(0x5555, 64))
+            self.assertEqual(sim.gpr(2), SelectableInt(0x3334, 64))
+
+    def test_sv_add_2(self):
+        # adds:
+        #       1 = 5 + 9   => 0x5555 = 0x4321+0x1234
+        #       r1 is scalar so ENDS EARLY
+        isa = SVP64Asm(['sv.add 1, 5.v, 9.v'
+                       ])
+
+        lst = list(isa)
+        print ("listing", lst)
+        initial_regs = [0] * 32
+        initial_regs[9] = 0x1234
+        initial_regs[10] = 0x1111
+        initial_regs[5] = 0x4321
+        initial_regs[6] = 0x2223
+        svstate = SVP64State()
+        svstate.vl[0:7] = 2 # VL
+        svstate.maxvl[0:7] = 2 # MAXVL
+        print ("SVSTATE", bin(svstate.spr.asint()))
+        with Program(lst, bigendian=False) as program:
+            sim = self.run_tst_program(program, initial_regs, svstate)
+            self.assertEqual(sim.gpr(1), SelectableInt(0x5555, 64))
+            self.assertEqual(sim.gpr(2), SelectableInt(0, 64))
+
+    def test_sv_add_3(self):
+        # adds:
+        #       1 = 5 + 9   => 0x5555 = 0x4321+0x1234
+        #       2 = 5 + 10  => 0x5432 = 0x4321+0x1111
+        isa = SVP64Asm(['sv.add 1.v, 5, 9.v'
+                       ])
+
+        lst = list(isa)
+        print ("listing", lst)
+        initial_regs = [0] * 32
+        initial_regs[9] = 0x1234
+        initial_regs[10] = 0x1111
+        initial_regs[5] = 0x4321
+        initial_regs[6] = 0x2223
+        svstate = SVP64State()
+        svstate.vl[0:7] = 2 # VL
+        svstate.maxvl[0:7] = 2 # MAXVL
+        print ("SVSTATE", bin(svstate.spr.asint()))
+        with Program(lst, bigendian=False) as program:
+            sim = self.run_tst_program(program, initial_regs, svstate)
+            self.assertEqual(sim.gpr(1), SelectableInt(0x5555, 64))
+            self.assertEqual(sim.gpr(2), SelectableInt(0x5432, 64))
 
     def run_tst_program(self, prog, initial_regs=[0] * 32,
                               svstate=None):
 
     def run_tst_program(self, prog, initial_regs=[0] * 32,
                               svstate=None):