Merge WAIT_RESET into INSN_FETCH on the Issue FSM
authorCesar Strauss <cestrauss@gmail.com>
Sun, 7 Mar 2021 11:49:55 +0000 (08:49 -0300)
committerCesar Strauss <cestrauss@gmail.com>
Sun, 7 Mar 2021 12:39:05 +0000 (09:39 -0300)
In a VL==0 loop, while we are skipping vector instructions, there needs to
be a way to stop the core. Unfortunately, this means duplicating the
corresponding code at instruction end, since there is no state in common
on either loop (the VL==0 instruction skip loop and the VL>1 vector loop).

This does makes it a little non-deterministic.

Normally, we would stop the core at instruction end, but could instead end
up stopping at instruction start. For this to happen, you need to stop the
core at the right moment, just after the instruction ended and before
the next instruction begins.

A way to avoid this, if necessary, would be to create a duplicate of the
INSN_FETCH state, that doesn't wait on "core stop" release.

Since we are now waiting on "core stop" release at instruction start
anyway, there is no need for the special WAIT_RESET state anymore.

src/soc/simple/issuer.py

index f13f5672de12722ebaf2abc324b4914543a07d7d..ca561f8b0e1a609bafc468639a8395ef8f1442d9 100644 (file)
@@ -269,10 +269,16 @@ class TestIssuerInternal(Elaboratable):
 
         with m.FSM(name="issue_fsm"):
 
-            # Wait on "core stop" release, at reset
-            with m.State("WAIT_RESET"):
+            # go fetch the instruction at the current PC
+            # at this point, there is no instruction running, that
+            # could inadvertently update the PC.
+            with m.State("INSN_FETCH"):
+                # wait on "core stop" release, before next fetch
+                # need to do this here, in case we are in a VL==0 loop
                 with m.If(~dbg.core_stop_o & ~core_rst):
-                    m.next = "INSN_FETCH"
+                    comb += fetch_pc_valid_i.eq(1)
+                    with m.If(fetch_pc_ready_o):
+                        m.next = "INSN_WAIT"
                 with m.Else():
                     comb += core.core_stopped_i.eq(1)
                     comb += dbg.core_stopped_i.eq(1)
@@ -286,15 +292,6 @@ class TestIssuerInternal(Elaboratable):
                         comb += update_svstate.eq(1)
                         sync += sv_changed.eq(1)
 
-            # go fetch the instruction at the current PC
-            # at this point, there is no instruction running, that
-            # could inadvertently update the PC.
-            with m.State("INSN_FETCH"):
-                # TODO: update PC here, before fetch
-                comb += fetch_pc_valid_i.eq(1)
-                with m.If(fetch_pc_ready_o):
-                    m.next = "INSN_WAIT"
-
             # decode the instruction when it arrives
             with m.State("INSN_WAIT"):
                 comb += fetch_insn_ready_i.eq(1)
@@ -325,6 +322,7 @@ class TestIssuerInternal(Elaboratable):
 
             with m.State("EXECUTE_WAIT"):
                 # wait on "core stop" release, at instruction end
+                # need to do this here, in case we are in a VL>1 loop
                 with m.If(~dbg.core_stop_o & ~core_rst):
                     comb += exec_pc_ready_i.eq(1)
                     with m.If(exec_pc_valid_o):