From: Cesar Strauss Date: Tue, 9 Jun 2020 11:57:31 +0000 (-0300) Subject: Avoid a combinatorial loop on valid_o X-Git-Tag: div_pipeline~450 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=c8c13adf3da9a6ca8b7765edc597ec7fdf19e8d8;p=soc.git Avoid a combinatorial loop on valid_o 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). --- diff --git a/src/soc/experiment/compalu_multi.py b/src/soc/experiment/compalu_multi.py index 63a6d684..a73d305b 100644 --- a/src/soc/experiment/compalu_multi.py +++ b/src/soc/experiment/compalu_multi.py @@ -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 diff --git a/src/soc/experiment/test/test_compalu_multi.py b/src/soc/experiment/test/test_compalu_multi.py index 9399908d..7b79be9a 100644 --- a/src/soc/experiment/test/test_compalu_multi.py +++ b/src/soc/experiment/test/test_compalu_multi.py @@ -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,