Avoid a combinatorial loop on valid_o
authorCesar Strauss <cestrauss@gmail.com>
Tue, 9 Jun 2020 11:57:31 +0000 (08:57 -0300)
committerCesar Strauss <cestrauss@gmail.com>
Tue, 9 Jun 2020 12:15:50 +0000 (09:15 -0300)
The path was:

all_rd (1) -> all_rd_pulse (1) -> alui_l.s (1) ->
-> alu.p.valid_i (1) -> ALU (zero-delay) -> alu.n.valid_o (1) ->
-> rok_l.r (1) -> all_rd (0)

Decided to break the loop on the reset of the read-done, write proceed
latch (rok_l.r), with no ill effects on performance.

Added a test case for this, using the zero-delay ALU (OP_NOP).

src/soc/experiment/compalu_multi.py
src/soc/experiment/test/test_compalu_multi.py

index 63a6d6845b828fd7bdb3d9dec2ebe2eff49c20ca..a73d305ba6758bc51c6a4e51df128cf37ad43e03 100644 (file)
@@ -223,7 +223,7 @@ class MultiCompUnit(RegSpecALUAPI, Elaboratable):
 
         # read-done,wr-proceed latch
         m.d.comb += rok_l.s.eq(self.issue_i)  # set up when issue starts
-        m.d.comb += rok_l.r.eq(self.alu.n.valid_o & self.busy_o) # ALU done
+        m.d.sync += rok_l.r.eq(self.alu.n.valid_o & self.busy_o) # ALU done
 
         # wr-done, back-to-start latch
         m.d.comb += rst_l.s.eq(all_rd)     # set when read-phase is fully done
index 9399908d6d32e65d2440584f6ee2676e3597cb52..7b79be9aca21cdc8adeecc3bc4415265c053a4d8 100644 (file)
@@ -102,6 +102,12 @@ def scoreboard_sim(dut):
     result = yield from op_sim(dut, 5, 2, InternalOp.OP_ADD, zero_a=1)
     assert result == 2
 
+    # test combinatorial zero-delay operation
+    # In the test ALU, any operation other than ADD, MUL or SHR
+    # is zero-delay, and do a subtraction.
+    result = yield from op_sim(dut, 5, 2, InternalOp.OP_NOP)
+    assert result == 3
+
 
 def test_compunit():
 
@@ -147,7 +153,7 @@ class CompUnitParallelTest:
 
     def driver(self):
         print("Begin parallel test.")
-        yield from self.operation(5, 2, InternalOp.OP_ADD, inv_a=0,
+        yield from self.operation(5, 2, InternalOp.OP_NOP, inv_a=0,
                                   imm=8, imm_ok=0, rdmaskn=(1, 0))
 
     def operation(self, a, b, op, inv_a=0, imm=0, imm_ok=0, zero_a=0,