add algebraic ld tests lwax, lwaux
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sun, 23 Aug 2020 20:39:25 +0000 (21:39 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sun, 23 Aug 2020 20:57:18 +0000 (21:57 +0100)
src/soc/experiment/compldst_multi.py
src/soc/fu/ldst/test/test_pipe_caller.py
src/soc/litex/florent/sim.py

index 5109ad253e3a6d1f6fa75c66699bde286b223069..41739ed4551fb6c43124bfea7ae6bbcabbf5aa8c 100644 (file)
@@ -85,6 +85,7 @@ from nmigen.hdl.rec import Record, Layout
 
 from nmutil.latch import SRLatch, latchregister
 from nmutil.byterev import byte_reverse
+from nmutil.extend import exts
 
 from soc.experiment.compalu_multi import go_record, CompUnitRecord
 from soc.experiment.l0_cache import PortInterface
@@ -301,6 +302,17 @@ class LDSTCompUnit(RegSpecAPI, Elaboratable):
         p_st_go = Signal(reset_less=True)
         sync += p_st_go.eq(self.st.go_i)
 
+        # decode bits of operand (latched)
+        oper_r = CompLDSTOpSubset(name="oper_r")  # Dest register
+        comb += op_is_st.eq(oper_r.insn_type == MicrOp.OP_STORE)  # ST
+        comb += op_is_ld.eq(oper_r.insn_type == MicrOp.OP_LOAD)  # LD
+        op_is_update = oper_r.ldst_mode == LDSTMode.update           # UPDATE
+        op_is_cix = oper_r.ldst_mode == LDSTMode.cix           # cache-inhibit
+        comb += self.load_mem_o.eq(op_is_ld & self.go_ad_i)
+        comb += self.stwd_mem_o.eq(op_is_st & self.go_st_i)
+        comb += self.ld_o.eq(op_is_ld)
+        comb += self.st_o.eq(op_is_st)
+
         ##########################
         # FSM implemented through sequence of latches.  approximately this:
         # - opc_l       : opcode
@@ -340,7 +352,9 @@ class LDSTCompUnit(RegSpecAPI, Elaboratable):
 
         # dest operand latch
         comb += wri_l.s.eq(issue_i)
-        sync += wri_l.r.eq(reset_w | Repl(self.done_o, self.n_dst))
+        sync += wri_l.r.eq(reset_w | Repl(self.done_o |
+                                          (self.pi.busy_o & op_is_update),
+                                          self.n_dst))
 
         # update-mode operand latch (EA written to reg 2)
         sync += upd_l.s.eq(reset_i)
@@ -359,7 +373,6 @@ class LDSTCompUnit(RegSpecAPI, Elaboratable):
         comb += rst_l.r.eq(issue_i)
 
         # create a latch/register for the operand
-        oper_r = CompLDSTOpSubset(name="oper_r")  # Dest register
         with m.If(self.issue_i):
             sync += oper_r.eq(self.oper_i)
         with m.If(self.done_o):
@@ -398,16 +411,6 @@ class LDSTCompUnit(RegSpecAPI, Elaboratable):
         comb += alu_o.eq(src1_or_z + src2_or_imm)  # actual EA
         m.d.sync += alu_ok.eq(alu_valid)             # keep ack in sync with EA
 
-        # decode bits of operand (latched)
-        comb += op_is_st.eq(oper_r.insn_type == MicrOp.OP_STORE)  # ST
-        comb += op_is_ld.eq(oper_r.insn_type == MicrOp.OP_LOAD)  # LD
-        op_is_update = oper_r.ldst_mode == LDSTMode.update           # UPDATE
-        op_is_cix = oper_r.ldst_mode == LDSTMode.cix           # cache-inhibit
-        comb += self.load_mem_o.eq(op_is_ld & self.go_ad_i)
-        comb += self.stwd_mem_o.eq(op_is_st & self.go_st_i)
-        comb += self.ld_o.eq(op_is_ld)
-        comb += self.st_o.eq(op_is_st)
-
         ############################
         # Control Signal calculation
 
@@ -490,13 +493,21 @@ class LDSTCompUnit(RegSpecAPI, Elaboratable):
         comb += addr_ok.eq(self.pi.addr_ok_o)  # no exc, address fine
 
         # byte-reverse on LD
+        revnorev = Signal(64, reset_less=True)
         with m.If(oper_r.byte_reverse):
             # byte-reverse the data based on ld/st width (turn it to LE)
             data_len = oper_r.data_len
             lddata_r = byte_reverse(m, 'lddata_r', pi.ld.data, data_len)
-            comb += ldd_o.eq(lddata_r)  # put reversed- data out
+            comb += revnorev.eq(lddata_r)  # put reversed- data out
         with m.Else():
-            comb += ldd_o.eq(pi.ld.data)  # put data out, straight (as BE)
+            comb += revnorev.eq(pi.ld.data)  # put data out, straight (as BE)
+
+        # then check sign-extend
+        with m.If(oper_r.sign_extend):
+            comb += ldd_o.eq(exts(revnorev, 32, 64))  # sign-extend
+        with m.Else():
+            comb += ldd_o.eq(revnorev)
+
         # ld - ld gets latched in via lod_l
         comb += ld_ok.eq(pi.ld.ok)  # ld.ok *closes* (freezes) ld data
 
index 31ddfc52c8e8669537ae366ac2c71834dfb65ea8..dc32e9d69cff43567223980b7165500b2a8639aa 100644 (file)
@@ -167,3 +167,42 @@ class LDSTTestCase(TestAccumulatorBase):
         self.add_case(Program(lst, bigendian), initial_regs,
                              initial_mem=initial_mem)
 
+    def case_9_load_algebraic_1(self):
+        lst = ["lwax 3, 4, 2"]
+        initial_regs = [0] * 32
+        initial_regs[1] = 0x5678
+        initial_regs[2] = 0x001c
+        initial_regs[4] = 0x0008
+        initial_mem = {0x0000: (0x5432123412345678, 8),
+                       0x0008: (0xabcdef0187654321, 8),
+                       0x0020: (0xf000000f0000ffff, 8),
+                        }
+        self.add_case(Program(lst, bigendian), initial_regs,
+                             initial_mem=initial_mem)
+
+    def case_9_load_algebraic_2(self):
+        lst = ["lwax 3, 4, 2"]
+        initial_regs = [0] * 32
+        initial_regs[1] = 0x5678
+        initial_regs[2] = 0x001c
+        initial_regs[4] = 0x0008
+        initial_mem = {0x0000: (0x5432123412345678, 8),
+                       0x0008: (0xabcdef0187654321, 8),
+                       0x0020: (0x7000000f0000ffff, 8),
+                        }
+        self.add_case(Program(lst, bigendian), initial_regs,
+                             initial_mem=initial_mem)
+
+    def case_9_load_algebraic_3(self):
+        lst = ["lwaux 3, 4, 2"]
+        initial_regs = [0] * 32
+        initial_regs[1] = 0x5678
+        initial_regs[2] = 0x001c
+        initial_regs[4] = 0x0008
+        initial_mem = {0x0000: (0x5432123412345678, 8),
+                       0x0008: (0xabcdef0187654321, 8),
+                       0x0020: (0xf000000f0000ffff, 8),
+                        }
+        self.add_case(Program(lst, bigendian), initial_regs,
+                             initial_mem=initial_mem)
+
index e62f064937d2ca8984f2d3d9a704eb9a1cbf6154..e4a1fbbf2446ea4c62694cdcdcc573dd69e1a137 100755 (executable)
@@ -50,7 +50,7 @@ class LibreSoCSim(SoCSDRAM):
         #            "hello_world/hello_world.bin"
         ram_fname = "/home/lkcl/src/libresoc/microwatt/" \
                     "tests/1.bin"
-        ram_fname = None
+        #ram_fname = None
 
         ram_init = []
         if ram_fname:
@@ -221,7 +221,7 @@ class LibreSoCSim(SoCSDRAM):
              ),
             # also check if this is a "stat"
             If(dbg_addr == 1, # requested a STAT
-                Display("    stat: %x", dbg_dout),
+                #Display("    stat: %x", dbg_dout),
                 If(dbg_dout & 2, # bit 2 of STAT is "stopped" mode
                      dmirunning.eq(1), # continue running
                      dmi_monitor.eq(0), # and stop monitor mode