-
Notifications
You must be signed in to change notification settings - Fork 299
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Pipeline] Add preliminary stall lowering
This commit adds preliminary stall lowering. Given the presence of a stall signal, every stage registers' clock enable value is now &'ed with the (pipeline) global stall signal.
- Loading branch information
Showing
5 changed files
with
261 additions
and
40 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
// REQUIRES: iverilog,cocotb | ||
|
||
// Test 1: default lowering (input muxing) | ||
|
||
// RUN: circt-opt %s -pass-pipeline='builtin.module(hw.module(pipeline.scheduled(pipeline-explicit-regs), lower-pipeline-to-hw{outline-stages}), lower-seq-to-sv, sv-trace-iverilog, export-verilog)' \ | ||
// RUN: -o %t.mlir > %t.sv | ||
|
||
// RUN: circt-cocotb-driver.py --objdir=%T --topLevel=stallTest \ | ||
// RUN: --pythonModule=stallTest --pythonFolder="%S,%S/.." %t.sv 2>&1 | FileCheck %s | ||
|
||
// Test 2: Clock-gate implementation | ||
|
||
// RUN: circt-opt %s -pass-pipeline='builtin.module(hw.module(pipeline.scheduled(pipeline-explicit-regs), lower-pipeline-to-hw{outline-stages clock-gate-regs}), lower-seq-to-sv, sv-trace-iverilog, export-verilog)' \ | ||
// RUN: -o %t_clockgated.mlir > %t.sv | ||
|
||
// RUN: circt-cocotb-driver.py --objdir=%T --topLevel=stallTest \ | ||
// RUN: --pythonModule=stallTest --pythonFolder="%S,%S/.." %t.sv 2>&1 | FileCheck %s | ||
|
||
|
||
// CHECK: ** TEST | ||
// CHECK: ** TESTS=[[N:.*]] PASS=[[N]] FAIL=0 SKIP=0 | ||
|
||
hw.module @stallTest(%arg0 : i32, %arg1 : i32, %go : i1, %stall : i1, %clock : i1, %reset : i1) -> (out: i32, done : i1) { | ||
%out, %done = pipeline.scheduled(%arg0, %arg1) stall %stall clock %clock reset %reset go %go : (i32, i32) -> (i32) { | ||
^bb0(%a0 : i32, %a1: i32, %s0_valid : i1): | ||
%add0 = comb.add %a0, %a1 : i32 | ||
pipeline.stage ^bb1 | ||
|
||
^bb1(%s1_valid : i1): | ||
%add1 = comb.add %add0, %a0 : i32 | ||
pipeline.stage ^bb2 | ||
|
||
^bb2(%s2_valid : i1): | ||
%add2 = comb.add %add1, %add0 : i32 | ||
pipeline.return %add2 : i32 | ||
} | ||
hw.output %out, %done : i32, i1 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
import cocotb | ||
from cocotb.triggers import Timer | ||
import cocotb.clock | ||
|
||
|
||
async def clock(dut): | ||
dut.clock.value = 0 | ||
await Timer(1, units='ns') | ||
dut.clock.value = 1 | ||
await Timer(1, units='ns') | ||
|
||
|
||
async def initDut(dut): | ||
""" | ||
Initializes a dut by adding a clock, setting initial valid and ready flags, | ||
and performing a reset. | ||
""" | ||
# Reset | ||
dut.reset.value = 1 | ||
await clock(dut) | ||
dut.reset.value = 0 | ||
await clock(dut) | ||
|
||
|
||
def ref(v1, v2): | ||
x1 = v1 + v2 | ||
x2 = x1 + v1 | ||
return x1 + x2 | ||
|
||
|
||
@cocotb.test() | ||
async def test1(dut): | ||
dut.go.value = 0 | ||
dut.stall.value = 0 | ||
await initDut(dut) | ||
|
||
v1 = 42 | ||
v2 = 24 | ||
resref = ref(v1, v2) | ||
|
||
# Get values into the first stage | ||
dut.arg0.value = v1 | ||
dut.arg1.value = v2 | ||
dut.go.value = 1 | ||
await clock(dut) | ||
|
||
# Stall for 2 cycles. Done should not be asserted nor the output correct. | ||
dut.go.value = 0 | ||
dut.arg0.value = 0 | ||
dut.arg1.value = 0 | ||
dut.stall.value = 1 | ||
for i in range(2): | ||
await clock(dut) | ||
assert dut.done != 1, "DUT should not be done when stalling" | ||
|
||
# Unstall and wait for 1 clock cycles - this should propagate the values through | ||
# the remaining stage. | ||
dut.stall.value = 0 | ||
await clock(dut) | ||
assert dut.done == 1, "DUT should be done after unstalling" | ||
assert dut.out == resref, f"Expected {resref}, got {dut.out}" | ||
|
||
# Clock once more, done should be deasserted. | ||
await clock(dut) | ||
assert dut.done == 0, "DUT should not be done after pipeline has finished" |
Oops, something went wrong.