Skip to content

Commit

Permalink
[Seq] FIFO: permit any type and add read latency (#7810)
Browse files Browse the repository at this point in the history
- Makes $input and $output allow any type rather than just a bit vector.
- Adds read latency attribute to specify the number of cycles after
which rdEn is asserted that data appears in the output.
  • Loading branch information
teqdruid authored Nov 14, 2024
1 parent e666347 commit 9351303
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 12 deletions.
11 changes: 8 additions & 3 deletions include/circt/Dialect/Seq/SeqOps.td
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,9 @@ def FIFOOp : SeqOp<"fifo", [
operations.
The fifo operation is configurable with the following parameters:
1. Depth (cycles)
2. Almost full/empty thresholds (optional). If not provided, these will
2. Read latency (cycles) is the number of cycles it takes for a read to
return data after the read enable signal is asserted.
3. Almost full/empty thresholds (optional). If not provided, these will
be asserted when the FIFO is full/empty.

Like `seq.hlmem` there are no guarantees that all possible fifo configuration
Expand All @@ -286,18 +288,21 @@ def FIFOOp : SeqOp<"fifo", [
}];

let arguments = (ins
HWIntegerType:$input, I1:$rdEn, I1:$wrEn, ClockType:$clk, I1:$rst,
AnyType:$input, I1:$rdEn, I1:$wrEn, ClockType:$clk, I1:$rst,
ConfinedAttr<I64Attr, [IntMinValue<1>]>:$depth,
DefaultValuedOptionalAttr<ConfinedAttr<I64Attr, [IntMinValue<0>]>, "0">
:$rdLatency,
OptionalAttr<ConfinedAttr<I64Attr, [IntMinValue<0>]>>:$almostFullThreshold,
OptionalAttr<ConfinedAttr<I64Attr, [IntMinValue<0>]>>:$almostEmptyThreshold
);

let results = (outs
HWIntegerType:$output, I1:$full, I1:$empty, Optional<I1>:$almostFull,
AnyType:$output, I1:$full, I1:$empty, Optional<I1>:$almostFull,
Optional<I1>:$almostEmpty);

let assemblyFormat = [{
`depth` $depth
(`rd_latency` $rdLatency^)?
custom<FIFOAFThreshold>($almostFullThreshold, type($almostFull))
custom<FIFOAEThreshold>($almostEmptyThreshold, type($almostEmpty))
`in` $input `rdEn` $rdEn `wrEn` $wrEn `clk` $clk `rst` $rst attr-dict `:` type($input)
Expand Down
2 changes: 1 addition & 1 deletion lib/Dialect/Seq/Transforms/LowerSeqFIFO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ struct FIFOLowering : public OpConversionPattern<seq::FIFOOp> {

Value readData = rewriter.create<seq::ReadPortOp>(
loc, hlmem, llvm::SmallVector<Value>{rdAddr}, adaptor.getRdEn(),
/*latency*/ 0);
mem.getRdLatency());
rewriter.create<seq::WritePortOp>(loc, hlmem,
llvm::SmallVector<Value>{wrAddr},
adaptor.getInput(), adaptor.getWrEn(),
Expand Down
17 changes: 9 additions & 8 deletions test/Dialect/Seq/lower-fifo.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ hw.module @fifo1(in %clk : !seq.clock, in %rst : i1, in %in : i32, in %rdEn : i1
}


// CHECK: hw.module @fifo2(in %[[CLOCK:.*]] : !seq.clock, in %[[VAL_1:.*]] : i1, in %[[VAL_2:.*]] : i32, in %[[VAL_3:.*]] : i1, in %[[VAL_4:.*]] : i1, out out : i32, out empty : i1, out full : i1, out almost_empty : i1, out almost_full : i1) {
// 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) {
// CHECK: %[[VAL_5:.*]] = hw.constant 2 : i3
// CHECK: %[[VAL_8:.*]] = hw.constant -1 : i3
// CHECK: %[[VAL_7:.*]] = hw.constant true
Expand All @@ -57,11 +57,11 @@ hw.module @fifo1(in %clk : !seq.clock, in %rst : i1, in %in : i32, in %rdEn : i1
// CHECK: %[[VAL_11:.*]] = hw.constant 0 : i3
// CHECK: %[[VAL_12:.*]] = hw.constant 1 : i2
// CHECK: %[[VAL_13:.*]] = seq.compreg sym @fifo_count %[[VAL_14:.*]], %[[CLOCK]] reset %[[VAL_1]], %[[VAL_11]] : i3
// CHECK: %[[VAL_15:.*]] = seq.hlmem @fifo_mem %[[CLOCK]], %[[VAL_1]] : <4xi32>
// CHECK: %[[VAL_15:.*]] = seq.hlmem @fifo_mem %[[CLOCK]], %[[VAL_1]] : <4x[[TY]]>
// CHECK: %[[VAL_16:.*]] = seq.compreg sym @fifo_rd_addr %[[VAL_17:.*]], %[[CLOCK]] reset %[[VAL_1]], %[[VAL_6]] : i2
// CHECK: %[[VAL_18:.*]] = seq.compreg sym @fifo_wr_addr %[[VAL_19:.*]], %[[CLOCK]] reset %[[VAL_1]], %[[VAL_6]] : i2
// CHECK: %[[VAL_20:.*]] = seq.read %[[VAL_15]]{{\[}}%[[VAL_16]]] rden %[[VAL_3]] {latency = 0 : i64} : !seq.hlmem<4xi32>
// CHECK: seq.write %[[VAL_15]]{{\[}}%[[VAL_18]]] %[[VAL_2]] wren %[[VAL_4]] {latency = 1 : i64} : !seq.hlmem<4xi32>
// CHECK: %[[VAL_20:.*]] = seq.read %[[VAL_15]]{{\[}}%[[VAL_16]]] rden %[[VAL_3]] {latency = 1 : i64} : !seq.hlmem<4x[[TY]]>
// CHECK: seq.write %[[VAL_15]]{{\[}}%[[VAL_18]]] %[[VAL_2]] wren %[[VAL_4]] {latency = 1 : i64} : !seq.hlmem<4x[[TY]]>
// CHECK: %[[VAL_21:.*]] = comb.icmp eq %[[VAL_13]], %[[VAL_9]] {sv.namehint = "fifo_full"} : i3
// CHECK: %[[VAL_22:.*]] = comb.icmp eq %[[VAL_13]], %[[VAL_11]] {sv.namehint = "fifo_empty"} : i3
// CHECK: %[[VAL_23:.*]] = comb.xor %[[VAL_3]], %[[VAL_7]] : i1
Expand Down Expand Up @@ -90,9 +90,10 @@ hw.module @fifo1(in %clk : !seq.clock, in %rst : i1, in %in : i32, in %rdEn : i1
// CHECK: %[[VAL_43:.*]] = comb.extract %[[VAL_13]] from 1 : (i3) -> i2
// CHECK: %[[VAL_44:.*]] = comb.icmp ne %[[VAL_43]], %[[VAL_6]] {sv.namehint = "fifo_almost_full"} : i2
// CHECK: %[[VAL_45:.*]] = comb.icmp ult %[[VAL_13]], %[[VAL_5]] {sv.namehint = "fifo_almost_empty"} : i3
// CHECK: hw.output %[[VAL_20]], %[[VAL_22]], %[[VAL_21]], %[[VAL_45]], %[[VAL_44]] : i32, i1, i1, i1, i1
// CHECK: hw.output %[[VAL_20]], %[[VAL_22]], %[[VAL_21]], %[[VAL_45]], %[[VAL_44]] : [[TY]], i1, i1, i1, i1
// CHECK: }
hw.module @fifo2(in %clk : !seq.clock, in %rst : i1, in %in : i32, in %rdEn : i1, in %wrEn : i1, out out: i32, out empty: i1, out full: i1, out almost_empty : i1, out almost_full : i1) {
%out, %full, %empty, %almostFull, %almostEmpty = seq.fifo depth 4 almost_full 2 almost_empty 1 in %in rdEn %rdEn wrEn %wrEn clk %clk rst %rst : i32
hw.output %out, %empty, %full, %almostEmpty, %almostFull : i32, i1, i1, i1, i1
!testType = !hw.array<2xi32>
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) {
%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
hw.output %out, %empty, %full, %almostEmpty, %almostFull : !testType, i1, i1, i1, i1
}

0 comments on commit 9351303

Please sign in to comment.