Skip to content

Commit 44ea9a8

Browse files
authored
[Seq] Fix FIFO lowering to correct depth and pointer increments (#8003)
Fixes two bugs: - Incorrect depth constant led to FIFO never reaching capacity. - Increment pointers only worked for depth which were powers of two. Updates integration test to test for these two conditions.
1 parent e508c74 commit 44ea9a8

File tree

6 files changed

+89
-109
lines changed

6 files changed

+89
-109
lines changed

include/circt/Dialect/Seq/SeqPasses.td

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,11 @@ include "mlir/Pass/PassBase.td"
1818
def LowerSeqFIFO : Pass<"lower-seq-fifo", "hw::HWModuleOp"> {
1919
let summary = "Lower seq.fifo ops";
2020
let constructor = "circt::seq::createLowerSeqFIFOPass()";
21-
let dependentDialects = ["circt::hw::HWDialect", "circt::comb::CombDialect"];
21+
let dependentDialects = [
22+
"circt::hw::HWDialect",
23+
"circt::comb::CombDialect",
24+
"circt::verif::VerifDialect"
25+
];
2226
}
2327

2428
def LowerSeqHLMem: Pass<"lower-seq-hlmem", "hw::HWModuleOp"> {
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
// REQUIRES: iverilog,cocotb
22

3-
// RUN: circt-opt %s --lower-seq-fifo --lower-seq-hlmem --lower-seq-to-sv --sv-trace-iverilog --export-verilog -o %t.mlir > %t.sv
3+
// RUN: circt-opt %s --lower-seq-fifo --lower-seq-hlmem --lower-seq-to-sv --lower-verif-to-sv --sv-trace-iverilog --export-verilog -o %t.mlir > %t.sv
44
// RUN: circt-cocotb-driver.py --objdir=%T --topLevel=fifo \
55
// RUN: --pythonModule=fifo --pythonFolder="%S,%S/.." %t.sv 2>&1
66

77
// CHECK: ** TEST
88
// CHECK: ** TESTS=[[N:.*]] PASS=[[N]] FAIL=0 SKIP=0
99

1010
hw.module @fifo(in %clk : !seq.clock, in %rst : i1, in %inp : i32, in %rdEn : i1, in %wrEn : i1, out out: i32, out empty: i1, out full: i1, out almost_empty : i1, out almost_full : i1) {
11-
%out, %full, %empty, %almostFull, %almostEmpty = seq.fifo depth 4 almost_full 2 almost_empty 1 in %inp rdEn %rdEn wrEn %wrEn clk %clk rst %rst : i32
11+
%out, %full, %empty, %almostFull, %almostEmpty = seq.fifo depth 6 almost_full 2 almost_empty 1 in %inp rdEn %rdEn wrEn %wrEn clk %clk rst %rst : i32
1212
hw.output %out, %empty, %full, %almostEmpty, %almostFull : i32, i1, i1, i1, i1
1313
}

integration_test/Dialect/Seq/fifo/fifo.py

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ async def initDut(dut):
2020

2121
async def write(dut, value):
2222
dut.inp.value = value
23+
assert dut.full.value == 0
2324
dut.wrEn.value = 1
2425
await clock(dut)
2526
dut.wrEn.value = 0
@@ -52,14 +53,21 @@ async def readWrite(dut, value):
5253
return data
5354

5455

55-
FIFO_DEPTH = 4
56+
FIFO_DEPTH = 6
5657
FIFO_ALMOST_FULL = 2
5758
FIFO_ALMOST_EMPTY = 1
5859

5960

61+
@cocotb.test()
6062
async def test_separate_read_write(dut):
61-
# Run a test where we incrementally write and read values from 1 to FIFO_DEPTH values
62-
for i in range(1, FIFO_DEPTH):
63+
"""Run a test where we incrementally write and read values from 1 to
64+
FIFO_DEPTH values."""
65+
66+
dut.inp.value = 0
67+
dut.rdEn.value = 0
68+
dut.wrEn.value = 0
69+
await initDut(dut)
70+
for i in range(1, FIFO_DEPTH + 1):
6371
for j in range(i):
6472
await write(dut, 42 + j)
6573

@@ -78,29 +86,25 @@ async def test_separate_read_write(dut):
7886
assert dut.empty.value == 1
7987

8088

89+
@cocotb.test()
8190
async def test_concurrent_read_write(dut):
82-
# Fill up the FIFO halfway and concurrently read and write. Should be able
83-
# to do this continuously.
91+
"""Fill up the FIFO halfway and concurrently read and write. Should be able
92+
to do this continuously."""
93+
94+
dut.inp.value = 0
95+
dut.rdEn.value = 0
96+
dut.wrEn.value = 0
97+
await initDut(dut)
98+
8499
counter = 0
85100
for i in range(FIFO_DEPTH // 2):
86101
await write(dut, counter)
87102
counter += 1
88103

89104
for i in range(FIFO_DEPTH * 2):
90105
expected_value = counter - FIFO_DEPTH // 2
91-
print("expected_value: ", expected_value)
106+
print(f"expected_value: {expected_value}")
92107
assert await readWrite(dut, counter) == expected_value
93108
assert dut.full.value == 0
94109
assert dut.empty.value == 0
95110
counter += 1
96-
97-
98-
@cocotb.test()
99-
async def test1(dut):
100-
dut.inp.value = 0
101-
dut.rdEn.value = 0
102-
dut.wrEn.value = 0
103-
await initDut(dut)
104-
105-
await test_separate_read_write(dut)
106-
await test_concurrent_read_write(dut)

lib/Dialect/Seq/Transforms/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ add_circt_dialect_library(CIRCTSeqTransforms
1515
CIRCTSeq
1616
CIRCTSupport
1717
CIRCTSV
18+
CIRCTVerif
1819
MLIRIR
1920
MLIRPass
2021
MLIRTransformUtils

lib/Dialect/Seq/Transforms/LowerSeqFIFO.cpp

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "circt/Dialect/SV/SVOps.h"
1111
#include "circt/Dialect/Seq/SeqOps.h"
1212
#include "circt/Dialect/Seq/SeqPasses.h"
13+
#include "circt/Dialect/Verif/VerifOps.h"
1314
#include "circt/Support/BackedgeBuilder.h"
1415
#include "mlir/Pass/Pass.h"
1516
#include "mlir/Transforms/DialectConversion.h"
@@ -34,10 +35,10 @@ struct FIFOLowering : public OpConversionPattern<seq::FIFOOp> {
3435
LogicalResult
3536
matchAndRewrite(seq::FIFOOp mem, OpAdaptor adaptor,
3637
ConversionPatternRewriter &rewriter) const final {
38+
Location loc = mem.getLoc();
3739
Type eltType = adaptor.getInput().getType();
3840
Value clk = adaptor.getClk();
3941
Value rst = adaptor.getRst();
40-
Location loc = mem.getLoc();
4142
BackedgeBuilder bb(rewriter, loc);
4243
size_t depth = mem.getDepth();
4344
Type countType = rewriter.getIntegerType(llvm::Log2_64_Ceil(depth + 1));
@@ -47,11 +48,12 @@ struct FIFOLowering : public OpConversionPattern<seq::FIFOOp> {
4748
Backedge nextCount = bb.get(countType);
4849

4950
// ====== Some constants ======
50-
Value countTcFull =
51-
rewriter.create<hw::ConstantOp>(loc, countType, depth - 1);
51+
Value countTcFull = rewriter.create<hw::ConstantOp>(loc, countType, depth);
5252
Value countTc1 = rewriter.create<hw::ConstantOp>(loc, countType, 1);
5353
Value countTc0 = rewriter.create<hw::ConstantOp>(loc, countType, 0);
54+
Value ptrTc0 = rewriter.create<hw::ConstantOp>(loc, ptrType, 0);
5455
Value ptrTc1 = rewriter.create<hw::ConstantOp>(loc, ptrType, 1);
56+
Value ptrTcFull = rewriter.create<hw::ConstantOp>(loc, ptrType, depth);
5557

5658
// ====== Hardware units ======
5759
Value count = rewriter.create<seq::CompRegOp>(
@@ -123,8 +125,13 @@ struct FIFOLowering : public OpConversionPattern<seq::FIFOOp> {
123125
Value wrAndNotFull = rewriter.create<comb::AndOp>(
124126
loc, adaptor.getWrEn(), comb::createOrFoldNot(loc, fifoFull, rewriter));
125127
auto addWrAddrPtrTc1 = rewriter.create<comb::AddOp>(loc, wrAddr, ptrTc1);
126-
wrAddrNext.setValue(rewriter.create<comb::MuxOp>(loc, wrAndNotFull,
127-
addWrAddrPtrTc1, wrAddr));
128+
129+
auto wrAddrNextNoRollover = rewriter.create<comb::MuxOp>(
130+
loc, wrAndNotFull, addWrAddrPtrTc1, wrAddr);
131+
auto isMaxAddrWr = rewriter.create<comb::ICmpOp>(
132+
loc, comb::ICmpPredicate::eq, wrAddrNextNoRollover, ptrTcFull);
133+
wrAddrNext.setValue(rewriter.create<comb::MuxOp>(loc, isMaxAddrWr, ptrTc0,
134+
wrAddrNextNoRollover));
128135
static_cast<Value>(wrAddrNext)
129136
.getDefiningOp()
130137
->setAttr("sv.namehint", rewriter.getStringAttr("fifo_wr_addr_next"));
@@ -133,8 +140,12 @@ struct FIFOLowering : public OpConversionPattern<seq::FIFOOp> {
133140
Value rdAndNotEmpty =
134141
rewriter.create<comb::AndOp>(loc, adaptor.getRdEn(), notFifoEmpty);
135142
auto addRdAddrPtrTc1 = rewriter.create<comb::AddOp>(loc, rdAddr, ptrTc1);
136-
rdAddrNext.setValue(rewriter.create<comb::MuxOp>(loc, rdAndNotEmpty,
137-
addRdAddrPtrTc1, rdAddr));
143+
auto rdAddrNextNoRollover = rewriter.create<comb::MuxOp>(
144+
loc, rdAndNotEmpty, addRdAddrPtrTc1, rdAddr);
145+
auto isMaxAddrRd = rewriter.create<comb::ICmpOp>(
146+
loc, comb::ICmpPredicate::eq, rdAddrNextNoRollover, ptrTcFull);
147+
rdAddrNext.setValue(rewriter.create<comb::MuxOp>(loc, isMaxAddrRd, ptrTc0,
148+
rdAddrNextNoRollover));
138149
static_cast<Value>(rdAddrNext)
139150
.getDefiningOp()
140151
->setAttr("sv.namehint", rewriter.getStringAttr("fifo_rd_addr_next"));
@@ -168,6 +179,22 @@ struct FIFOLowering : public OpConversionPattern<seq::FIFOOp> {
168179
->setAttr("sv.namehint", rewriter.getStringAttr("fifo_almost_empty"));
169180
}
170181

182+
// ====== Protocol checks =====
183+
Value clkI1 = rewriter.create<seq::FromClockOp>(loc, clk);
184+
Value notEmptyAndRden = comb::createOrFoldNot(
185+
loc, rewriter.create<comb::AndOp>(loc, adaptor.getRdEn(), fifoEmpty),
186+
rewriter);
187+
rewriter.create<verif::ClockedAssertOp>(
188+
loc, notEmptyAndRden, verif::ClockEdge::Pos, clkI1, /*enable=*/Value(),
189+
rewriter.getStringAttr("FIFO empty when read enabled"));
190+
Value notFullAndWren = comb::createOrFoldNot(
191+
loc, rewriter.create<comb::AndOp>(loc, adaptor.getWrEn(), fifoFull),
192+
rewriter);
193+
rewriter.create<verif::ClockedAssertOp>(
194+
loc, notFullAndWren, verif::ClockEdge::Pos, clkI1,
195+
/*enable=*/Value(),
196+
rewriter.getStringAttr("FIFO full when write enabled"));
197+
171198
rewriter.replaceOp(mem, results);
172199
return success();
173200
}
@@ -186,7 +213,8 @@ void LowerSeqFIFOPass::runOnOperation() {
186213

187214
// Lowering patterns must lower away all HLMem-related operations.
188215
target.addIllegalOp<seq::FIFOOp>();
189-
target.addLegalDialect<seq::SeqDialect, hw::HWDialect, comb::CombDialect>();
216+
target.addLegalDialect<seq::SeqDialect, hw::HWDialect, comb::CombDialect,
217+
verif::VerifDialect>();
190218
RewritePatternSet patterns(&ctxt);
191219
patterns.add<FIFOLowering>(&ctxt);
192220

test/Dialect/Seq/lower-fifo.mlir

Lines changed: 24 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -4,94 +4,37 @@
44
// RUN: circt-opt --lower-seq-fifo --canonicalize %s | FileCheck %s --implicit-check-not=seq.fifo
55

66

7-
// CHECK: hw.module @fifo1(in %[[CLOCK:.*]] : !seq.clock, in %[[VAL_1:.*]] : i1, in %[[VAL_2:.*]] : i32, in %[[VAL_3:.*]] : i1, in %[[VAL_4:.*]] : i1, out out : i32) {
8-
// CHECK: %[[VAL_6:.*]] = hw.constant -1 : i2
9-
// CHECK: %[[VAL_5:.*]] = hw.constant true
10-
// CHECK: %[[VAL_7:.*]] = hw.constant -2 : i2
11-
// CHECK: %[[VAL_8:.*]] = hw.constant 1 : i2
12-
// CHECK: %[[VAL_9:.*]] = hw.constant 0 : i2
13-
// CHECK: %[[VAL_10:.*]] = seq.compreg sym @fifo_count %[[VAL_11:.*]], %[[CLOCK]] reset %[[VAL_1]], %[[VAL_9]] : i2
14-
// CHECK: %[[VAL_12:.*]] = seq.hlmem @fifo_mem %[[CLOCK]], %[[VAL_1]] : <3xi32>
15-
// CHECK: %[[VAL_13:.*]] = seq.compreg sym @fifo_rd_addr %[[VAL_14:.*]], %[[CLOCK]] reset %[[VAL_1]], %[[VAL_9]] : i2
16-
// CHECK: %[[VAL_15:.*]] = seq.compreg sym @fifo_wr_addr %[[VAL_16:.*]], %[[CLOCK]] reset %[[VAL_1]], %[[VAL_9]] : i2
17-
// CHECK: %[[VAL_17:.*]] = seq.read %[[VAL_12]]{{\[}}%[[VAL_13]]] rden %[[VAL_3]] {latency = 0 : i64} : !seq.hlmem<3xi32>
18-
// CHECK: seq.write %[[VAL_12]]{{\[}}%[[VAL_15]]] %[[VAL_2]] wren %[[VAL_4]] {latency = 1 : i64} : !seq.hlmem<3xi32>
19-
// CHECK: %[[VAL_18:.*]] = comb.xor %[[VAL_3]], %[[VAL_5]] : i1
20-
// CHECK: %[[VAL_19:.*]] = comb.xor %[[VAL_4]], %[[VAL_5]] : i1
21-
// CHECK: %[[VAL_20:.*]] = comb.and %[[VAL_3]], %[[VAL_19]] : i1
22-
// CHECK: %[[VAL_21:.*]] = comb.and %[[VAL_4]], %[[VAL_18]] : i1
23-
// CHECK: %[[VAL_22:.*]] = comb.icmp eq %[[VAL_10]], %[[VAL_7]] : i2
24-
// CHECK: %[[VAL_23:.*]] = comb.add %[[VAL_10]], %[[VAL_8]] : i2
25-
// CHECK: %[[VAL_24:.*]] = comb.mux %[[VAL_22]], %[[VAL_10]], %[[VAL_23]] : i2
26-
// CHECK: %[[VAL_25:.*]] = comb.icmp eq %[[VAL_10]], %[[VAL_9]] : i2
27-
// CHECK: %[[VAL_26:.*]] = comb.add %[[VAL_10]], %[[VAL_6]] : i2
28-
// CHECK: %[[VAL_27:.*]] = comb.xor %[[VAL_20]], %[[VAL_5]] : i1
29-
// CHECK: %[[VAL_28:.*]] = comb.or %[[VAL_27]], %[[VAL_25]] : i1
30-
// CHECK: %[[VAL_29:.*]] = comb.mux %[[VAL_28]], %[[VAL_10]], %[[VAL_26]] : i2
31-
// CHECK: %[[VAL_30:.*]] = comb.mux %[[VAL_21]], %[[VAL_24]], %[[VAL_29]] : i2
32-
// CHECK: %[[VAL_31:.*]] = comb.or %[[VAL_3]], %[[VAL_4]] : i1
33-
// CHECK: %[[VAL_11]] = comb.mux %[[VAL_31]], %[[VAL_30]], %[[VAL_10]] {sv.namehint = "fifo_count_next"} : i2
34-
// CHECK: %[[VAL_32:.*]] = comb.icmp ne %[[VAL_10]], %[[VAL_7]] : i2
35-
// CHECK: %[[VAL_33:.*]] = comb.and %[[VAL_4]], %[[VAL_32]] : i1
36-
// CHECK: %[[VAL_34:.*]] = comb.add %[[VAL_15]], %[[VAL_8]] : i2
37-
// CHECK: %[[VAL_16]] = comb.mux %[[VAL_33]], %[[VAL_34]], %[[VAL_15]] {sv.namehint = "fifo_wr_addr_next"} : i2
38-
// CHECK: %[[VAL_35:.*]] = comb.icmp ne %[[VAL_10]], %[[VAL_9]] : i2
39-
// CHECK: %[[VAL_36:.*]] = comb.and %[[VAL_3]], %[[VAL_35]] : i1
40-
// CHECK: %[[VAL_37:.*]] = comb.add %[[VAL_13]], %[[VAL_8]] : i2
41-
// CHECK: %[[VAL_14]] = comb.mux %[[VAL_36]], %[[VAL_37]], %[[VAL_13]] {sv.namehint = "fifo_rd_addr_next"} : i2
42-
// CHECK: hw.output %[[VAL_17]] : i32
43-
// CHECK: }
7+
// CHECK: hw.module @fifo1(in %[[CLOCK:.*]] : !seq.clock, in %[[VAL_1:.*]] : i1, in %[[VAL_2:.*]] : i32, in %[[VAL_3:.*]] : i1, in %[[VAL_4:.*]] : i1, out out : i32) {
8+
// CHECK: %fifo_count = seq.compreg sym @fifo_count %{{.+}}, %clk reset %rst, %c0_i2 : i2
9+
// CHECK: %fifo_mem = seq.hlmem @fifo_mem %clk, %rst : <3xi32>
10+
// CHECK: %fifo_rd_addr = seq.compreg sym @fifo_rd_addr %{{.+}}, %clk reset %rst, %c0_i2 : i2
11+
// CHECK: %fifo_wr_addr = seq.compreg sym @fifo_wr_addr %{{.+}}, %clk reset %rst, %c0_i2 : i2
12+
// CHECK: %fifo_mem_rdata = seq.read %fifo_mem[%fifo_rd_addr] rden %rdEn {latency = 0 : i64} : !seq.hlmem<3xi32>
13+
// CHECK: seq.write %fifo_mem[%fifo_wr_addr] %in wren %wrEn {latency = 1 : i64} : !seq.hlmem<3xi32>
14+
// All of the comb logic which would be here is pretty much impossible
15+
// to verify visually. As a rule, if it's difficult to verify
16+
// visually, that's a candidate for a new op: #8002. Since I haven't
17+
// verified it visually, I'm not including it here. There are
18+
// integration tests for it.
19+
// CHECK: verif.clocked_assert %{{.+}}, posedge %{{.+}} label "FIFO empty when read enabled" : i1
20+
// CHECK: verif.clocked_assert %{{.+}}, posedge %{{.+}} label "FIFO full when write enabled" : i1
21+
// CHECK: hw.output %fifo_mem_rdata : i32
4422
hw.module @fifo1(in %clk : !seq.clock, in %rst : i1, in %in : i32, in %rdEn : i1, in %wrEn : i1, out out : i32) {
4523
%out, %full, %empty = seq.fifo depth 3 in %in rdEn %rdEn wrEn %wrEn clk %clk rst %rst : i32
4624
hw.output %out : i32
4725
}
4826

4927

5028
// CHECK: hw.module @fifo2(in %[[CLOCK:.*]] : !seq.clock, in %[[VAL_1:.*]] : i1, in %[[VAL_2:.*]] : [[TY:.+]], in %[[VAL_3:.*]] : i1, in %[[VAL_4:.*]] : i1, out out : [[TY]], out empty : i1, out full : i1, out almost_empty : i1, out almost_full : i1) {
51-
// CHECK: %[[VAL_5:.*]] = hw.constant 2 : i3
52-
// CHECK: %[[VAL_8:.*]] = hw.constant -1 : i3
53-
// CHECK: %[[VAL_7:.*]] = hw.constant true
54-
// CHECK: %[[VAL_6:.*]] = hw.constant 0 : i2
55-
// CHECK: %[[VAL_9:.*]] = hw.constant 3 : i3
56-
// CHECK: %[[VAL_10:.*]] = hw.constant 1 : i3
57-
// CHECK: %[[VAL_11:.*]] = hw.constant 0 : i3
58-
// CHECK: %[[VAL_12:.*]] = hw.constant 1 : i2
59-
// CHECK: %[[VAL_13:.*]] = seq.compreg sym @fifo_count %[[VAL_14:.*]], %[[CLOCK]] reset %[[VAL_1]], %[[VAL_11]] : i3
60-
// CHECK: %[[VAL_15:.*]] = seq.hlmem @fifo_mem %[[CLOCK]], %[[VAL_1]] : <4x[[TY]]>
61-
// CHECK: %[[VAL_16:.*]] = seq.compreg sym @fifo_rd_addr %[[VAL_17:.*]], %[[CLOCK]] reset %[[VAL_1]], %[[VAL_6]] : i2
62-
// CHECK: %[[VAL_18:.*]] = seq.compreg sym @fifo_wr_addr %[[VAL_19:.*]], %[[CLOCK]] reset %[[VAL_1]], %[[VAL_6]] : i2
63-
// CHECK: %[[VAL_20:.*]] = seq.read %[[VAL_15]]{{\[}}%[[VAL_16]]] rden %[[VAL_3]] {latency = 1 : i64} : !seq.hlmem<4x[[TY]]>
64-
// CHECK: seq.write %[[VAL_15]]{{\[}}%[[VAL_18]]] %[[VAL_2]] wren %[[VAL_4]] {latency = 1 : i64} : !seq.hlmem<4x[[TY]]>
65-
// CHECK: %[[VAL_21:.*]] = comb.icmp eq %[[VAL_13]], %[[VAL_9]] {sv.namehint = "fifo_full"} : i3
66-
// CHECK: %[[VAL_22:.*]] = comb.icmp eq %[[VAL_13]], %[[VAL_11]] {sv.namehint = "fifo_empty"} : i3
67-
// CHECK: %[[VAL_23:.*]] = comb.xor %[[VAL_3]], %[[VAL_7]] : i1
68-
// CHECK: %[[VAL_24:.*]] = comb.xor %[[VAL_4]], %[[VAL_7]] : i1
69-
// CHECK: %[[VAL_25:.*]] = comb.and %[[VAL_3]], %[[VAL_24]] : i1
70-
// CHECK: %[[VAL_26:.*]] = comb.and %[[VAL_4]], %[[VAL_23]] : i1
71-
// CHECK: %[[VAL_27:.*]] = comb.icmp eq %[[VAL_13]], %[[VAL_9]] : i3
72-
// CHECK: %[[VAL_28:.*]] = comb.add %[[VAL_13]], %[[VAL_10]] : i3
73-
// CHECK: %[[VAL_29:.*]] = comb.mux %[[VAL_27]], %[[VAL_13]], %[[VAL_28]] : i3
74-
// CHECK: %[[VAL_30:.*]] = comb.icmp eq %[[VAL_13]], %[[VAL_11]] : i3
75-
// CHECK: %[[VAL_31:.*]] = comb.add %[[VAL_13]], %[[VAL_8]] : i3
76-
// CHECK: %[[VAL_32:.*]] = comb.xor %[[VAL_25]], %[[VAL_7]] : i1
77-
// CHECK: %[[VAL_33:.*]] = comb.or %[[VAL_32]], %[[VAL_30]] : i1
78-
// CHECK: %[[VAL_34:.*]] = comb.mux %[[VAL_33]], %[[VAL_13]], %[[VAL_31]] : i3
79-
// CHECK: %[[VAL_35:.*]] = comb.mux %[[VAL_26]], %[[VAL_29]], %[[VAL_34]] : i3
80-
// CHECK: %[[VAL_36:.*]] = comb.or %[[VAL_3]], %[[VAL_4]] : i1
81-
// CHECK: %[[VAL_14]] = comb.mux %[[VAL_36]], %[[VAL_35]], %[[VAL_13]] {sv.namehint = "fifo_count_next"} : i3
82-
// CHECK: %[[VAL_37:.*]] = comb.xor %[[VAL_21]], %[[VAL_7]] : i1
83-
// CHECK: %[[VAL_38:.*]] = comb.and %[[VAL_4]], %[[VAL_37]] : i1
84-
// CHECK: %[[VAL_39:.*]] = comb.add %[[VAL_18]], %[[VAL_12]] : i2
85-
// CHECK: %[[VAL_19]] = comb.mux %[[VAL_38]], %[[VAL_39]], %[[VAL_18]] {sv.namehint = "fifo_wr_addr_next"} : i2
86-
// CHECK: %[[VAL_40:.*]] = comb.xor %[[VAL_22]], %[[VAL_7]] : i1
87-
// CHECK: %[[VAL_41:.*]] = comb.and %[[VAL_3]], %[[VAL_40]] : i1
88-
// CHECK: %[[VAL_42:.*]] = comb.add %[[VAL_16]], %[[VAL_12]] : i2
89-
// CHECK: %[[VAL_17]] = comb.mux %[[VAL_41]], %[[VAL_42]], %[[VAL_16]] {sv.namehint = "fifo_rd_addr_next"} : i2
90-
// CHECK: %[[VAL_43:.*]] = comb.extract %[[VAL_13]] from 1 : (i3) -> i2
91-
// CHECK: %[[VAL_44:.*]] = comb.icmp ne %[[VAL_43]], %[[VAL_6]] {sv.namehint = "fifo_almost_full"} : i2
92-
// CHECK: %[[VAL_45:.*]] = comb.icmp ult %[[VAL_13]], %[[VAL_5]] {sv.namehint = "fifo_almost_empty"} : i3
93-
// CHECK: hw.output %[[VAL_20]], %[[VAL_22]], %[[VAL_21]], %[[VAL_45]], %[[VAL_44]] : [[TY]], i1, i1, i1, i1
94-
// CHECK: }
29+
// CHECK: %fifo_count = seq.compreg sym @fifo_count %16, %clk reset %rst, %c0_i3 : i3
30+
// CHECK: %fifo_mem = seq.hlmem @fifo_mem %clk, %rst : <4x!hw.array<2xi32>>
31+
// CHECK: %fifo_rd_addr = seq.compreg sym @fifo_rd_addr %28, %clk reset %rst, %c0_i2 : i2
32+
// CHECK: %fifo_wr_addr = seq.compreg sym @fifo_wr_addr %22, %clk reset %rst, %c0_i2 : i2
33+
// CHECK: %fifo_mem_rdata = seq.read %fifo_mem[%fifo_rd_addr] rden %rdEn {latency = 1 : i64} : !seq.hlmem<4x!hw.array<2xi32>>
34+
// CHECK: seq.write %fifo_mem[%fifo_wr_addr] %in wren %wrEn {latency = 1 : i64} : !seq.hlmem<4x!hw.array<2xi32>>
35+
// See comment above.
36+
// CHECK: verif.clocked_assert %{{.+}}, posedge %{{.+}} label "FIFO empty when read enabled" : i1
37+
// CHECK: verif.clocked_assert %{{.+}}, posedge %{{.+}} label "FIFO full when write enabled" : i1
9538
!testType = !hw.array<2xi32>
9639
hw.module @fifo2(in %clk : !seq.clock, in %rst : i1, in %in : !testType, in %rdEn : i1, in %wrEn : i1, out out: !testType, out empty: i1, out full: i1, out almost_empty : i1, out almost_full : i1) {
9740
%out, %full, %empty, %almostFull, %almostEmpty = seq.fifo depth 4 rd_latency 1 almost_full 2 almost_empty 1 in %in rdEn %rdEn wrEn %wrEn clk %clk rst %rst : !testType

0 commit comments

Comments
 (0)