Implement 1<<r3 predicate mode
[soc.git] / src / soc / simple / issuer.py
index 075655f13e3af950dea0fc46da2e5bafcdff0be0..b2711cbb0ccced9ecce3b770511ee1f98fc99b01 100644 (file)
@@ -56,22 +56,23 @@ def get_insn(f_instr_o, pc):
         return f_instr_o.word_select(pc[2], 32)
 
 # gets state input or reads from state regfile
-def state_get(m, state_i, name, regfile, regnum):
+def state_get(m, core_rst, state_i, name, regfile, regnum):
     comb = m.d.comb
     sync = m.d.sync
     # read the PC
     res = Signal(64, reset_less=True, name=name)
     res_ok_delay = Signal(name="%s_ok_delay" % name)
-    sync += res_ok_delay.eq(~state_i.ok)
-    with m.If(state_i.ok):
-        # incoming override (start from pc_i)
-        comb += res.eq(state_i.data)
-    with m.Else():
-        # otherwise read StateRegs regfile for PC...
-        comb += regfile.ren.eq(1<<regnum)
-    # ... but on a 1-clock delay
-    with m.If(res_ok_delay):
-        comb += res.eq(regfile.data_o)
+    with m.If(~core_rst):
+        sync += res_ok_delay.eq(~state_i.ok)
+        with m.If(state_i.ok):
+            # incoming override (start from pc_i)
+            comb += res.eq(state_i.data)
+        with m.Else():
+            # otherwise read StateRegs regfile for PC...
+            comb += regfile.ren.eq(1<<regnum)
+        # ... but on a 1-clock delay
+        with m.If(res_ok_delay):
+            comb += res.eq(regfile.data_o)
     return res
 
 def get_predint(m, mask, name):
@@ -408,6 +409,10 @@ class TestIssuerInternal(Elaboratable):
         predmode = rm_dec.predmode
         srcpred, dstpred = rm_dec.srcpred, rm_dec.dstpred
         cr_pred, int_pred = self.cr_pred, self.int_pred   # read regfiles
+        # get src/dst step, so we can skip already used mask bits
+        cur_state = self.cur_state
+        srcstep = cur_state.svstate.srcstep
+        dststep = cur_state.svstate.dststep
 
         # elif predmode == CR:
         #    CR-src sidx, sinvert = get_predcr(m, srcpred)
@@ -461,7 +466,17 @@ class TestIssuerInternal(Elaboratable):
             with m.State("INT_DST_READ"):
                 # store destination mask
                 inv = Repl(dinvert, 64)
-                sync += self.dstmask.eq(self.int_pred.data_o ^ inv)
+                new_dstmask = Signal(64)
+                with m.If(dunary):
+                    # set selected mask bit for 1<<r3 mode
+                    dst_shift = Signal(range(64))
+                    comb += dst_shift.eq(self.int_pred.data_o & 0b111111)
+                    comb += new_dstmask.bit_select(dst_shift, 1).eq(1)
+                with m.Else():
+                    # invert mask if requested
+                    comb += new_dstmask.eq(self.int_pred.data_o ^ inv)
+                # shift-out already used mask bits
+                sync += self.dstmask.eq(new_dstmask >> dststep)
                 # skip fetching source mask register, when zero
                 with m.If(sall1s):
                     sync += self.srcmask.eq(-1)
@@ -475,7 +490,17 @@ class TestIssuerInternal(Elaboratable):
             with m.State("INT_SRC_READ"):
                 # store source mask
                 inv = Repl(sinvert, 64)
-                sync += self.srcmask.eq(self.int_pred.data_o ^ inv)
+                new_srcmask = Signal(64)
+                with m.If(sunary):
+                    # set selected mask bit for 1<<r3 mode
+                    src_shift = Signal(range(64))
+                    comb += src_shift.eq(self.int_pred.data_o & 0b111111)
+                    comb += new_srcmask.bit_select(src_shift, 1).eq(1)
+                with m.Else():
+                    # invert mask if requested
+                    comb += new_srcmask.eq(self.int_pred.data_o ^ inv)
+                # shift-out already used mask bits
+                sync += self.srcmask.eq(new_srcmask >> srcstep)
                 m.next = "FETCH_PRED_DONE"
 
             with m.State("FETCH_PRED_DONE"):
@@ -600,12 +625,15 @@ class TestIssuerInternal(Elaboratable):
                             # append guard bit, in case the mask is all zeros
                             pri_enc_src = PriorityEncoder(65)
                             m.submodules.pri_enc_src = pri_enc_src
-                            comb += pri_enc_src.i.eq(Cat(self.srcmask, 1))
+                            comb += pri_enc_src.i.eq(Cat(self.srcmask,
+                                                         Const(1, 1)))
                             comb += src_delta.eq(pri_enc_src.o)
                         # apply delta to srcstep
                         comb += skip_srcstep.eq(cur_srcstep + src_delta)
                         # shift-out all leading zeros from the mask
                         # plus the leading "one" bit
+                        # TODO count leading zeros and shift-out the zero
+                        #      bits, in the same step, in hardware
                         sync += self.srcmask.eq(self.srcmask >> (src_delta+1))
 
                         # same as above, but for dststep
@@ -614,7 +642,8 @@ class TestIssuerInternal(Elaboratable):
                         with m.If(~pred_dst_zero):
                             pri_enc_dst = PriorityEncoder(65)
                             m.submodules.pri_enc_dst = pri_enc_dst
-                            comb += pri_enc_dst.i.eq(Cat(self.dstmask, 1))
+                            comb += pri_enc_dst.i.eq(Cat(self.dstmask,
+                                                         Const(1, 1)))
                             comb += dst_delta.eq(pri_enc_dst.o)
                         comb += skip_dststep.eq(cur_dststep + dst_delta)
                         sync += self.dstmask.eq(self.dstmask >> (dst_delta+1))
@@ -863,6 +892,10 @@ class TestIssuerInternal(Elaboratable):
         # set up peripherals and core
         core_rst = self.setup_peripherals(m)
 
+        # reset current state if core reset requested
+        with m.If(core_rst):
+            m.d.sync += self.cur_state.eq(0)
+
         # PC and instruction from I-Memory
         comb += self.pc_o.eq(cur_state.pc)
         pc_changed = Signal() # note write to PC
@@ -870,9 +903,11 @@ class TestIssuerInternal(Elaboratable):
 
         # read state either from incoming override or from regfile
         # TODO: really should be doing MSR in the same way
-        pc = state_get(m, self.pc_i, "pc",                  # read PC
+        pc = state_get(m, core_rst, self.pc_i,
+                            "pc",                  # read PC
                             self.state_r_pc, StateRegs.PC)
-        svstate = state_get(m, self.svstate_i, "svstate",   # read SVSTATE
+        svstate = state_get(m, core_rst, self.svstate_i,
+                            "svstate",   # read SVSTATE
                             self.state_r_sv, StateRegs.SVSTATE)
 
         # don't write pc every cycle
@@ -884,7 +919,7 @@ class TestIssuerInternal(Elaboratable):
 
         # address of the next instruction, in the absence of a branch
         # depends on the instruction size
-        nia = Signal(64, reset_less=True)
+        nia = Signal(64)
 
         # connect up debug signals
         # TODO comb += core.icache_rst_i.eq(dbg.icache_rst_o)
@@ -955,6 +990,10 @@ class TestIssuerInternal(Elaboratable):
                          exec_insn_valid_i, exec_insn_ready_o,
                          exec_pc_valid_o, exec_pc_ready_i)
 
+        # whatever was done above, over-ride it if core reset is held
+        with m.If(core_rst):
+            sync += nia.eq(0)
+
         # this bit doesn't have to be in the FSM: connect up to read
         # regfiles on demand from DMI
         self.do_dmi(m, dbg)