mirror of https://github.com/llvm/circt.git
[LLHD] Let WaitOp observe plain values instead of signals (#7528)
This is necessary to lower the moore dialect's always_comb and always_latch without introducing helper signals. It also allows for more mem2reg at the LLHD level.
This commit is contained in:
parent
246636cee1
commit
9efc2e7572
|
@ -130,14 +130,14 @@ def WaitOp : LLHDOp<"wait", [
|
|||
```
|
||||
}];
|
||||
|
||||
let arguments = (ins Variadic<InOutType>:$obs,
|
||||
let arguments = (ins Variadic<HWValueType>:$observed,
|
||||
Optional<LLHDTimeType>:$time,
|
||||
Variadic<AnyType>:$destOps);
|
||||
|
||||
let successors = (successor AnySuccessor:$dest);
|
||||
|
||||
let assemblyFormat = [{
|
||||
(`for` $time^ `,`)? (`(`$obs^ `:` qualified(type($obs))`)` `,`)?
|
||||
(`for` $time^ `,`)? (`(`$observed^ `:` qualified(type($observed))`)` `,`)?
|
||||
$dest (`(` $destOps^ `:` qualified(type($destOps)) `)`)? attr-dict
|
||||
}];
|
||||
}
|
||||
|
|
|
@ -322,6 +322,19 @@ struct WaitEventOpConversion : public OpConversionPattern<WaitEventOp> {
|
|||
rewriter.eraseOp(detectOp);
|
||||
}
|
||||
|
||||
auto setInsertionPointAfterDef = [&](Value value) {
|
||||
if (auto *op = value.getDefiningOp())
|
||||
rewriter.setInsertionPointAfter(op);
|
||||
if (auto arg = dyn_cast<BlockArgument>(value))
|
||||
rewriter.setInsertionPointToStart(value.getParentBlock());
|
||||
};
|
||||
|
||||
auto probeIfSignal = [&](Value value) -> Value {
|
||||
if (!isa<hw::InOutType>(value.getType()))
|
||||
return value;
|
||||
return rewriter.create<llhd::PrbOp>(loc, value);
|
||||
};
|
||||
|
||||
// Determine the values used during event detection that are defined outside
|
||||
// the `wait_event`'s body region. We want to wait for a change on these
|
||||
// signals before we check if any interesting event happened.
|
||||
|
@ -334,12 +347,16 @@ struct WaitEventOpConversion : public OpConversionPattern<WaitEventOp> {
|
|||
if (!alreadyObserved.insert(value).second)
|
||||
continue;
|
||||
if (auto remapped = rewriter.getRemappedValue(value)) {
|
||||
observeValues.push_back(remapped);
|
||||
OpBuilder::InsertionGuard g(rewriter);
|
||||
setInsertionPointAfterDef(remapped);
|
||||
observeValues.push_back(probeIfSignal(remapped));
|
||||
} else {
|
||||
OpBuilder::InsertionGuard g(rewriter);
|
||||
setInsertionPointAfterDef(value);
|
||||
auto type = typeConverter->convertType(value.getType());
|
||||
auto converted = typeConverter->materializeTargetConversion(
|
||||
rewriter, loc, type, value);
|
||||
observeValues.push_back(converted);
|
||||
observeValues.push_back(probeIfSignal(converted));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -34,40 +34,6 @@ struct ProcessLoweringPass
|
|||
void runOnOperation() override;
|
||||
};
|
||||
|
||||
/// Backtrack a signal value and make sure that every part of it is in the
|
||||
/// observer list at some point. Assumes that there is no operation that adds
|
||||
/// parts to a signal that it does not take as input (e.g. something like
|
||||
/// llhd.sig.zext %sig : !hw.inout<i32> -> !hw.inout<i64>).
|
||||
static LogicalResult checkSignalsAreObserved(OperandRange obs, Value value) {
|
||||
// If the value in the observer list, we don't need to backtrack further.
|
||||
if (llvm::is_contained(obs, value))
|
||||
return success();
|
||||
|
||||
if (Operation *op = value.getDefiningOp()) {
|
||||
// If no input is a signal, this operation creates one and thus this is the
|
||||
// last point where it could have been observed. As we've already checked
|
||||
// that, we can fail here. This includes for example llhd.sig
|
||||
if (llvm::none_of(op->getOperands(), [](Value arg) {
|
||||
return isa<hw::InOutType>(arg.getType());
|
||||
}))
|
||||
return failure();
|
||||
|
||||
// Only recusively backtrack signal values. Other values cannot be changed
|
||||
// from outside or with a delay. If they come from probes at some point,
|
||||
// they are covered by that probe. As soon as we find a signal that is not
|
||||
// observed no matter how far we backtrack, we fail.
|
||||
return success(llvm::all_of(op->getOperands(), [&](Value arg) {
|
||||
return !isa<hw::InOutType>(arg.getType()) ||
|
||||
succeeded(checkSignalsAreObserved(obs, arg));
|
||||
}));
|
||||
}
|
||||
|
||||
// If the value is a module argument (no block arguments except for the entry
|
||||
// block are allowed here) and was not observed, we cannot backtrack further
|
||||
// and thus fail.
|
||||
return failure();
|
||||
}
|
||||
|
||||
static LogicalResult isProcValidToLower(llhd::ProcessOp op) {
|
||||
size_t numBlocks = op.getBody().getBlocks().size();
|
||||
|
||||
|
@ -98,13 +64,24 @@ static LogicalResult isProcValidToLower(llhd::ProcessOp op) {
|
|||
"during process-lowering: llhd.wait terminators with optional time "
|
||||
"argument cannot be lowered to structural LLHD");
|
||||
|
||||
SmallVector<Value> observedSignals;
|
||||
for (Value obs : wait.getObserved())
|
||||
if (auto prb = obs.getDefiningOp<llhd::PrbOp>())
|
||||
if (!op.getBody().isAncestor(prb->getParentRegion()))
|
||||
observedSignals.push_back(prb.getSignal());
|
||||
|
||||
// Every probed signal has to occur in the observed signals list in
|
||||
// the wait instruction
|
||||
WalkResult result = op.walk([&wait](llhd::PrbOp prbOp) -> WalkResult {
|
||||
if (failed(checkSignalsAreObserved(wait.getObs(), prbOp.getSignal())))
|
||||
return wait.emitOpError(
|
||||
"during process-lowering: the wait terminator is required to "
|
||||
"have all probed signals as arguments");
|
||||
WalkResult result = op.walk([&](Operation *operation) -> WalkResult {
|
||||
// TODO: value does not need to be observed if all values this value is
|
||||
// a combinatorial result of are observed.
|
||||
for (Value operand : operation->getOperands())
|
||||
if (!op.getBody().isAncestor(operand.getParentRegion()) &&
|
||||
!llvm::is_contained(wait.getObserved(), operand) &&
|
||||
!llvm::is_contained(observedSignals, operand))
|
||||
return wait.emitOpError(
|
||||
"during process-lowering: the wait terminator is required to "
|
||||
"have values used in the process as arguments");
|
||||
|
||||
return WalkResult::advance();
|
||||
});
|
||||
|
|
|
@ -536,8 +536,19 @@ func.func private @dummyC() -> ()
|
|||
// CHECK-LABEL: hw.module @WaitEvent
|
||||
moore.module @WaitEvent() {
|
||||
// CHECK: %a = llhd.sig
|
||||
// CHECK: [[PRB_A6:%.+]] = llhd.prb %a
|
||||
// CHECK: [[PRB_A5:%.+]] = llhd.prb %a
|
||||
// CHECK: [[PRB_A4:%.+]] = llhd.prb %a
|
||||
// CHECK: [[PRB_A3:%.+]] = llhd.prb %a
|
||||
// CHECK: [[PRB_A2:%.+]] = llhd.prb %a
|
||||
// CHECK: [[PRB_A1:%.+]] = llhd.prb %a
|
||||
// CHECK: [[PRB_A0:%.+]] = llhd.prb %a
|
||||
// CHECK: %b = llhd.sig
|
||||
// CHECK: [[PRB_B2:%.+]] = llhd.prb %b
|
||||
// CHECK: [[PRB_B1:%.+]] = llhd.prb %b
|
||||
// CHECK: [[PRB_B0:%.+]] = llhd.prb %b
|
||||
// CHECK: %c = llhd.sig
|
||||
// CHECK: [[PRB_C:%.+]] = llhd.prb %c
|
||||
%a = moore.variable : <i1>
|
||||
%b = moore.variable : <i1>
|
||||
%c = moore.variable : <i1>
|
||||
|
@ -569,7 +580,7 @@ moore.module @WaitEvent() {
|
|||
// CHECK: llhd.process {
|
||||
moore.procedure initial {
|
||||
// CHECK: [[BEFORE:%.+]] = llhd.prb %a
|
||||
// CHECK: llhd.wait (%a : {{.+}}), ^[[CHECK:.+]]
|
||||
// CHECK: llhd.wait ([[PRB_A0]] : {{.+}}), ^[[CHECK:.+]]
|
||||
// CHECK: ^[[CHECK]]:
|
||||
// CHECK: [[AFTER:%.+]] = llhd.prb %a
|
||||
// CHECK: [[TMP:%.+]] = comb.icmp bin ne [[BEFORE]], [[AFTER]]
|
||||
|
@ -585,7 +596,7 @@ moore.module @WaitEvent() {
|
|||
moore.procedure initial {
|
||||
// CHECK: [[BEFORE_A:%.+]] = llhd.prb %a
|
||||
// CHECK: [[BEFORE_B:%.+]] = llhd.prb %b
|
||||
// CHECK: llhd.wait (%a, %b : {{.+}}), ^[[CHECK:.+]]
|
||||
// CHECK: llhd.wait ([[PRB_A1]], [[PRB_B0]] : {{.+}}), ^[[CHECK:.+]]
|
||||
// CHECK: ^[[CHECK]]:
|
||||
// CHECK: [[AFTER_A:%.+]] = llhd.prb %a
|
||||
// CHECK: [[AFTER_B:%.+]] = llhd.prb %b
|
||||
|
@ -605,7 +616,7 @@ moore.module @WaitEvent() {
|
|||
// CHECK: [[BEFORE_A:%.+]] = llhd.prb %a
|
||||
// CHECK: [[BEFORE_B:%.+]] = llhd.prb %b
|
||||
// CHECK: [[BEFORE_C:%.+]] = llhd.prb %c
|
||||
// CHECK: llhd.wait (%a, %b, %c : {{.+}}), ^[[CHECK:.+]]
|
||||
// CHECK: llhd.wait ([[PRB_A2]], [[PRB_B1]], [[PRB_C]] : {{.+}}), ^[[CHECK:.+]]
|
||||
// CHECK: ^[[CHECK]]:
|
||||
// CHECK: [[AFTER_A:%.+]] = llhd.prb %a
|
||||
// CHECK: [[AFTER_B:%.+]] = llhd.prb %b
|
||||
|
@ -629,7 +640,7 @@ moore.module @WaitEvent() {
|
|||
// CHECK: llhd.process {
|
||||
moore.procedure initial {
|
||||
// CHECK: [[BEFORE:%.+]] = llhd.prb %a
|
||||
// CHECK: llhd.wait (%a : {{.+}}), ^[[CHECK:.+]]
|
||||
// CHECK: llhd.wait ([[PRB_A3]] : {{.+}}), ^[[CHECK:.+]]
|
||||
// CHECK: ^[[CHECK]]:
|
||||
// CHECK: [[AFTER:%.+]] = llhd.prb %a
|
||||
// CHECK: [[TRUE:%.+]] = hw.constant true
|
||||
|
@ -646,7 +657,7 @@ moore.module @WaitEvent() {
|
|||
// CHECK: llhd.process {
|
||||
moore.procedure initial {
|
||||
// CHECK: [[BEFORE:%.+]] = llhd.prb %a
|
||||
// CHECK: llhd.wait (%a : {{.+}}), ^[[CHECK:.+]]
|
||||
// CHECK: llhd.wait ([[PRB_A4]] : {{.+}}), ^[[CHECK:.+]]
|
||||
// CHECK: ^[[CHECK]]:
|
||||
// CHECK: [[AFTER:%.+]] = llhd.prb %a
|
||||
// CHECK: [[TRUE:%.+]] = hw.constant true
|
||||
|
@ -663,7 +674,7 @@ moore.module @WaitEvent() {
|
|||
// CHECK: llhd.process {
|
||||
moore.procedure initial {
|
||||
// CHECK: [[BEFORE:%.+]] = llhd.prb %a
|
||||
// CHECK: llhd.wait (%a : {{.+}}), ^[[CHECK:.+]]
|
||||
// CHECK: llhd.wait ([[PRB_A5]] : {{.+}}), ^[[CHECK:.+]]
|
||||
// CHECK: ^[[CHECK]]:
|
||||
// CHECK: [[AFTER:%.+]] = llhd.prb %a
|
||||
// CHECK: [[TRUE:%.+]] = hw.constant true
|
||||
|
@ -682,7 +693,7 @@ moore.module @WaitEvent() {
|
|||
|
||||
// CHECK: llhd.process {
|
||||
moore.procedure initial {
|
||||
// CHECK: llhd.wait (%a, %b :
|
||||
// CHECK: llhd.wait ([[PRB_A6]], [[PRB_B2]] :
|
||||
moore.wait_event {
|
||||
%0 = moore.constant 0 : i1
|
||||
%1 = moore.conditional %0 : i1 -> i1 {
|
||||
|
|
|
@ -18,7 +18,8 @@ hw.module @checkPrbDceAndCseIn(inout %arg0 : i32, inout %arg1 : i32, inout %arg2
|
|||
|
||||
// CHECK-LABEL: @checkPrbDceButNotCse
|
||||
hw.module @checkPrbDceButNotCse(inout %arg0 : i32, inout %arg1 : i32, inout %arg2 : i32) {
|
||||
// CHECK-NEXT: llhd.process
|
||||
%prb = llhd.prb %arg0 : !hw.inout<i32>
|
||||
// CHECK: llhd.process
|
||||
llhd.process {
|
||||
// CHECK-NEXT: llhd.constant_time
|
||||
%time = llhd.constant_time <0ns, 1d, 0e>
|
||||
|
@ -26,7 +27,7 @@ hw.module @checkPrbDceButNotCse(inout %arg0 : i32, inout %arg1 : i32, inout %arg
|
|||
// CHECK-NEXT: [[P1:%.*]] = llhd.prb
|
||||
%1 = llhd.prb %arg0 : !hw.inout<i32>
|
||||
// CHECK-NEXT: llhd.wait
|
||||
llhd.wait (%arg0: !hw.inout<i32>), ^bb1
|
||||
llhd.wait (%prb: i32), ^bb1
|
||||
// CHECK-NEXT: ^bb1:
|
||||
^bb1:
|
||||
// CHECK-NEXT: [[P2:%.*]] = llhd.prb
|
||||
|
|
|
@ -176,10 +176,14 @@ hw.module @check_wait_1 () {
|
|||
|
||||
// CHECK: @check_wait_2(inout %[[ARG0:.*]] : i64, inout %[[ARG1:.*]] : i1) {
|
||||
hw.module @check_wait_2 (inout %arg0 : i64, inout %arg1 : i1) {
|
||||
// CHECK: [[PRB0:%.+]] = llhd.prb %arg0
|
||||
%prb0 = llhd.prb %arg0 : !hw.inout<i64>
|
||||
// CHECK: [[PRB1:%.+]] = llhd.prb %arg1
|
||||
%prb1 = llhd.prb %arg1 : !hw.inout<i1>
|
||||
// CHECK-NEXT: llhd.process
|
||||
llhd.process {
|
||||
// CHECK-NEXT: llhd.wait (%[[ARG0]], %[[ARG1]] : !hw.inout<i64>, !hw.inout<i1>), ^[[BB:.*]](%[[ARG1]] : !hw.inout<i1>)
|
||||
llhd.wait (%arg0, %arg1 : !hw.inout<i64>, !hw.inout<i1>), ^bb1(%arg1 : !hw.inout<i1>)
|
||||
// CHECK-NEXT: llhd.wait ([[PRB0]], [[PRB1]] : i64, i1), ^[[BB:.*]](%[[ARG1]] : !hw.inout<i1>)
|
||||
llhd.wait (%prb0, %prb1 : i64, i1), ^bb1(%arg1 : !hw.inout<i1>)
|
||||
// CHECK: ^[[BB]](%[[A:.*]]: !hw.inout<i1>):
|
||||
^bb1(%a: !hw.inout<i1>):
|
||||
llhd.halt
|
||||
|
@ -188,12 +192,16 @@ hw.module @check_wait_2 (inout %arg0 : i64, inout %arg1 : i1) {
|
|||
|
||||
// CHECK: hw.module @check_wait_3(inout %[[ARG0:.*]] : i64, inout %[[ARG1:.*]] : i1) {
|
||||
hw.module @check_wait_3 (inout %arg0 : i64, inout %arg1 : i1) {
|
||||
// CHECK: [[PRB0:%.+]] = llhd.prb %arg0
|
||||
%prb0 = llhd.prb %arg0 : !hw.inout<i64>
|
||||
// CHECK: [[PRB1:%.+]] = llhd.prb %arg1
|
||||
%prb1 = llhd.prb %arg1 : !hw.inout<i1>
|
||||
// CHECK-NEXT: llhd.process
|
||||
llhd.process {
|
||||
// CHECK-NEXT: %[[TIME:.*]] = llhd.constant_time
|
||||
%time = llhd.constant_time #llhd.time<0ns, 0d, 0e>
|
||||
// CHECK-NEXT: llhd.wait for %[[TIME]], (%[[ARG0]], %[[ARG1]] : !hw.inout<i64>, !hw.inout<i1>), ^[[BB:.*]](%[[ARG1]], %[[ARG0]] : !hw.inout<i1>, !hw.inout<i64>)
|
||||
llhd.wait for %time, (%arg0, %arg1 : !hw.inout<i64>, !hw.inout<i1>), ^bb1(%arg1, %arg0 : !hw.inout<i1>, !hw.inout<i64>)
|
||||
// CHECK-NEXT: llhd.wait for %[[TIME]], ([[PRB0]], [[PRB1]] : i64, i1), ^[[BB:.*]](%[[ARG1]], %[[ARG0]] : !hw.inout<i1>, !hw.inout<i64>)
|
||||
llhd.wait for %time, (%prb0, %prb1 : i64, i1), ^bb1(%arg1, %arg0 : !hw.inout<i1>, !hw.inout<i64>)
|
||||
// CHECK: ^[[BB]](%[[A:.*]]: !hw.inout<i1>, %[[B:.*]]: !hw.inout<i64>):
|
||||
^bb1(%a: !hw.inout<i1>, %b: !hw.inout<i64>):
|
||||
llhd.halt
|
||||
|
|
|
@ -123,6 +123,7 @@ hw.module @check_blockarg(inout %sig : i32) {
|
|||
|
||||
// CHECK-LABEL: @loop
|
||||
// CHECK-SAME: (inout %[[VAL_0:.*]] : i2)
|
||||
// CHECK: [[PRB:%.+]] = llhd.prb %in_i
|
||||
// CHECK: llhd.process
|
||||
// CHECK: %[[VAL_1:.*]] = hw.constant 0 : i32
|
||||
// CHECK: %[[VAL_2:.*]] = hw.constant 2 : i32
|
||||
|
@ -138,7 +139,7 @@ hw.module @check_blockarg(inout %sig : i32) {
|
|||
// CHECK: %[[VAL_8:.*]] = llhd.prb %[[VAL_0]] : !hw.inout<i2>
|
||||
// CHECK: cf.cond_br %[[VAL_7]], ^[[BB4:.+]], ^[[BB3:.+]]
|
||||
// CHECK: ^[[BB3]]:
|
||||
// CHECK: llhd.wait (%[[VAL_0]] : !hw.inout<i2>), ^[[BB1]]
|
||||
// CHECK: llhd.wait ([[PRB]] : i2), ^[[BB1]]
|
||||
// CHECK: ^[[BB4]]:
|
||||
// CHECK: %[[VAL_9:.*]] = llhd.load %[[VAL_5]] : !llhd.ptr<i32>
|
||||
// CHECK: %[[VAL_10:.*]] = comb.add %[[VAL_9]], %[[VAL_4]] : i32
|
||||
|
@ -146,6 +147,7 @@ hw.module @check_blockarg(inout %sig : i32) {
|
|||
// CHECK: cf.br ^[[BB2]]
|
||||
// CHECK: }
|
||||
hw.module @loop(inout %in_i : i2) {
|
||||
%prb0 = llhd.prb %in_i : !hw.inout<i2>
|
||||
llhd.process {
|
||||
// TR: -1
|
||||
cf.br ^body
|
||||
|
@ -162,7 +164,7 @@ hw.module @loop(inout %in_i : i2) {
|
|||
cf.cond_br %2, ^loop_continue, ^check
|
||||
^check:
|
||||
// TR: 1
|
||||
llhd.wait (%in_i : !hw.inout<i2>), ^body
|
||||
llhd.wait (%prb0 : i2), ^body
|
||||
^loop_continue:
|
||||
// TR: 1
|
||||
%3 = hw.constant 0 : i2
|
||||
|
@ -177,6 +179,8 @@ hw.module @loop(inout %in_i : i2) {
|
|||
|
||||
// CHECK-LABEL: @complicated
|
||||
// CHECK-SAME: (inout %[[VAL_0:.*]] : i1, inout %[[VAL_1:.*]] : i1, inout %[[VAL_2:.*]] : i1, inout %[[VAL_3:.*]] : i1, inout %[[VAL_4:.*]] : i1)
|
||||
// CHECK: [[PRB_CLK:%.+]] = llhd.prb %[[VAL_1]]
|
||||
// CHECK: [[PRB_RST:%.+]] = llhd.prb %[[VAL_0]]
|
||||
// CHECK: llhd.process
|
||||
// CHECK: %[[ALLSET:.*]] = hw.constant true
|
||||
// CHECK: %[[VAL_5:.*]] = hw.constant false
|
||||
|
@ -191,7 +195,7 @@ hw.module @loop(inout %in_i : i2) {
|
|||
// CHECK: %[[VAL_10:.*]] = llhd.prb %[[VAL_0]] : !hw.inout<i1>
|
||||
// CHECK: %[[VAL_11:.*]] = comb.icmp eq %[[VAL_9]], %[[VAL_5]] : i1
|
||||
// CHECK: %[[VAL_12:.*]] = comb.icmp ne %[[VAL_10]], %[[VAL_5]] : i1
|
||||
// CHECK: llhd.wait (%[[VAL_1]], %[[VAL_0]] : !hw.inout<i1>, !hw.inout<i1>), ^[[BB3:.+]]
|
||||
// CHECK: llhd.wait ([[PRB_CLK]], [[PRB_RST]] : i1, i1), ^[[BB3:.+]]
|
||||
// CHECK: ^[[BB3]]:
|
||||
// CHECK: %[[VAL_13:.*]] = llhd.prb %[[VAL_3]] : !hw.inout<i1>
|
||||
// CHECK: llhd.store %[[VAL_8]], %[[VAL_13]] : !llhd.ptr<i1>
|
||||
|
@ -221,6 +225,8 @@ hw.module @loop(inout %in_i : i2) {
|
|||
// CHECK: cf.br ^[[BB1]]
|
||||
// CHECK: }
|
||||
hw.module @complicated(inout %rst_ni: i1, inout %clk_i: i1, inout %async_ack_i: i1, inout %ack_src_q: i1, inout %ack_q: i1) {
|
||||
%prb_clk = llhd.prb %clk_i : !hw.inout<i1>
|
||||
%prb_rst = llhd.prb %rst_ni : !hw.inout<i1>
|
||||
llhd.process {
|
||||
%allset = hw.constant 1 : i1
|
||||
// TR: -1
|
||||
|
@ -234,7 +240,7 @@ hw.module @complicated(inout %rst_ni: i1, inout %clk_i: i1, inout %async_ack_i:
|
|||
// TR: 2
|
||||
%clk_i_prb = llhd.prb %clk_i : !hw.inout<i1>
|
||||
%rst_ni_prb = llhd.prb %rst_ni : !hw.inout<i1>
|
||||
llhd.wait (%clk_i, %rst_ni : !hw.inout<i1>, !hw.inout<i1>), ^check
|
||||
llhd.wait (%prb_clk, %prb_rst : i1, i1), ^check
|
||||
^check:
|
||||
// TR: 0
|
||||
%2 = llhd.prb %ack_src_q : !hw.inout<i1>
|
||||
|
|
|
@ -262,6 +262,7 @@ hw.module @multiple_store_one_block() {
|
|||
|
||||
// CHECK-LABEL: @loop
|
||||
// CHECK-SAME: (inout %[[VAL_0:.*]] : i2)
|
||||
// CHECK: [[PRB:%.+]] = llhd.prb %[[VAL_0]]
|
||||
// CHECK: cf.br ^bb1
|
||||
// CHECK: ^bb1:
|
||||
// CHECK: %[[VAL_1:.*]] = hw.constant 0 : i32
|
||||
|
@ -271,7 +272,7 @@ hw.module @multiple_store_one_block() {
|
|||
// CHECK: %[[VAL_4:.*]] = comb.icmp ult %[[VAL_2]], %[[VAL_3]] : i32
|
||||
// CHECK: cf.cond_br %[[VAL_4]], ^bb4, ^bb3
|
||||
// CHECK: ^bb3:
|
||||
// CHECK: llhd.wait (%[[VAL_0]] : !hw.inout<i2>), ^bb1
|
||||
// CHECK: llhd.wait ([[PRB]] : i2), ^bb1
|
||||
// CHECK: ^bb4:
|
||||
// CHECK: %[[VAL_5:.*]] = hw.constant 0 : i2
|
||||
// CHECK: %[[VAL_6:.*]] = hw.constant 1 : i32
|
||||
|
@ -279,6 +280,7 @@ hw.module @multiple_store_one_block() {
|
|||
// CHECK: cf.br ^bb2(%[[VAL_7]] : i32)
|
||||
// CHECK: }
|
||||
hw.module @loop(inout %in_i : i2) {
|
||||
%prb = llhd.prb %in_i : !hw.inout<i2>
|
||||
llhd.process {
|
||||
cf.br ^body
|
||||
^body:
|
||||
|
@ -291,7 +293,7 @@ hw.module @loop(inout %in_i : i2) {
|
|||
%2 = comb.icmp ult %i_ld, %1 : i32
|
||||
cf.cond_br %2, ^loop_continue, ^check
|
||||
^check:
|
||||
llhd.wait (%in_i : !hw.inout<i2>), ^body
|
||||
llhd.wait (%prb : i2), ^body
|
||||
^loop_continue:
|
||||
%3 = hw.constant 0 : i2
|
||||
%5 = hw.constant 1 : i32
|
||||
|
|
|
@ -23,31 +23,41 @@ hw.module @simpleWait() {
|
|||
// Check wait with observing probed signals
|
||||
// CHECK-LABEL: hw.module @prbAndWait
|
||||
hw.module @prbAndWait(inout %arg0 : i64) {
|
||||
// CHECK-NEXT: %{{.*}} = llhd.prb
|
||||
%1 = llhd.prb %arg0 : !hw.inout<i64>
|
||||
llhd.process {
|
||||
// CHECK-NEXT: %{{.*}} = llhd.prb
|
||||
// CHECK-NEXT: hw.output
|
||||
cf.br ^bb1
|
||||
^bb1:
|
||||
%0 = llhd.prb %arg0 : !hw.inout<i64>
|
||||
llhd.wait (%arg0 : !hw.inout<i64>), ^bb1
|
||||
llhd.wait (%1 : i64), ^bb1
|
||||
}
|
||||
}
|
||||
|
||||
// Check wait with observing probed signals
|
||||
// CHECK-LABEL: hw.module @prbAndWaitMoreObserved
|
||||
hw.module @prbAndWaitMoreObserved(inout %arg0 : i64, inout %arg1 : i64) {
|
||||
// CHECK-NEXT: %{{.*}} = llhd.prb
|
||||
%1 = llhd.prb %arg0 : !hw.inout<i64>
|
||||
// CHECK-NEXT: %{{.*}} = llhd.prb
|
||||
%2 = llhd.prb %arg1 : !hw.inout<i64>
|
||||
llhd.process {
|
||||
// CHECK-NEXT: %{{.*}} = llhd.prb
|
||||
// CHECK-NEXT: hw.output
|
||||
cf.br ^bb1
|
||||
^bb1:
|
||||
%0 = llhd.prb %arg0 : !hw.inout<i64>
|
||||
llhd.wait (%arg0, %arg1 : !hw.inout<i64>, !hw.inout<i64>), ^bb1
|
||||
llhd.wait (%1, %2 : i64, i64), ^bb1
|
||||
}
|
||||
}
|
||||
|
||||
// CHECK-LABEL: hw.module @muxedSignal
|
||||
hw.module @muxedSignal(inout %arg0 : i64, inout %arg1 : i64) {
|
||||
// CHECK-NEXT: %{{.*}} = llhd.prb
|
||||
%1 = llhd.prb %arg0 : !hw.inout<i64>
|
||||
// CHECK-NEXT: %{{.*}} = llhd.prb
|
||||
%2 = llhd.prb %arg1 : !hw.inout<i64>
|
||||
llhd.process {
|
||||
cf.br ^bb1
|
||||
^bb1:
|
||||
|
@ -58,28 +68,32 @@ hw.module @muxedSignal(inout %arg0 : i64, inout %arg1 : i64) {
|
|||
%cond = hw.constant true
|
||||
%sig = comb.mux %cond, %arg0, %arg1 : !hw.inout<i64>
|
||||
%0 = llhd.prb %sig : !hw.inout<i64>
|
||||
llhd.wait (%arg0, %arg1 : !hw.inout<i64>, !hw.inout<i64>), ^bb1
|
||||
llhd.wait (%1, %2 : i64, i64), ^bb1
|
||||
}
|
||||
}
|
||||
|
||||
// CHECK-LABEL: hw.module @muxedSignal2
|
||||
hw.module @muxedSignal2(inout %arg0 : i64, inout %arg1 : i64) {
|
||||
// CHECK-NEXT: %{{.*}} = hw.constant
|
||||
// CHECK-NEXT: %{{.*}} = comb.mux
|
||||
// CHECK-NEXT: %{{.*}} = llhd.prb
|
||||
%cond = hw.constant true
|
||||
%sig = comb.mux %cond, %arg0, %arg1 : !hw.inout<i64>
|
||||
%0 = llhd.prb %sig : !hw.inout<i64>
|
||||
llhd.process {
|
||||
cf.br ^bb1
|
||||
^bb1:
|
||||
// CHECK-NEXT: %{{.*}} = hw.constant
|
||||
// CHECK-NEXT: %{{.*}} = comb.mux
|
||||
// CHECK-NEXT: %{{.*}} = llhd.prb
|
||||
// CHECK-NEXT: comb.and
|
||||
%1 = comb.and %0, %0 : i64
|
||||
// CHECK-NEXT: hw.output
|
||||
%cond = hw.constant true
|
||||
%sig = comb.mux %cond, %arg0, %arg1 : !hw.inout<i64>
|
||||
%0 = llhd.prb %sig : !hw.inout<i64>
|
||||
llhd.wait (%sig : !hw.inout<i64>), ^bb1
|
||||
llhd.wait (%0 : i64), ^bb1
|
||||
}
|
||||
}
|
||||
|
||||
// CHECK-LABEL: hw.module @partialSignal
|
||||
hw.module @partialSignal(inout %arg0 : i64) {
|
||||
// CHECK-NEXT: %{{.*}} = llhd.prb
|
||||
%1 = llhd.prb %arg0 : !hw.inout<i64>
|
||||
llhd.process {
|
||||
cf.br ^bb1
|
||||
^bb1:
|
||||
|
@ -90,6 +104,6 @@ hw.module @partialSignal(inout %arg0 : i64) {
|
|||
%c = hw.constant 16 : i6
|
||||
%sig = llhd.sig.extract %arg0 from %c : (!hw.inout<i64>) -> !hw.inout<i32>
|
||||
%0 = llhd.prb %sig : !hw.inout<i32>
|
||||
llhd.wait (%arg0 : !hw.inout<i64>), ^bb1
|
||||
llhd.wait (%1 : i64), ^bb1
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ hw.module @prbAndWaitNotObserved(inout %arg0 : i64) {
|
|||
cf.br ^bb1
|
||||
^bb1:
|
||||
%0 = llhd.prb %arg0 : !hw.inout<i64>
|
||||
// expected-error @+1 {{during process-lowering: the wait terminator is required to have all probed signals as arguments}}
|
||||
// expected-error @+1 {{during process-lowering: the wait terminator is required to have values used in the process as arguments}}
|
||||
llhd.wait ^bb1
|
||||
}
|
||||
}
|
||||
|
@ -17,9 +17,10 @@ hw.module @prbAndWaitNotObserved(inout %arg0 : i64) {
|
|||
hw.module @blockArgumentsNotAllowed(inout %arg0 : i64) {
|
||||
// expected-error @+1 {{during process-lowering: the second block (containing the llhd.wait) is not allowed to have arguments}}
|
||||
llhd.process {
|
||||
cf.br ^bb1(%arg0 : !hw.inout<i64>)
|
||||
^bb1(%a : !hw.inout<i64>):
|
||||
llhd.wait ^bb1(%a : !hw.inout<i64>)
|
||||
%prb = llhd.prb %arg0 : !hw.inout<i64>
|
||||
cf.br ^bb1(%prb : i64)
|
||||
^bb1(%a : i64):
|
||||
llhd.wait ^bb1(%a: i64)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -83,7 +84,7 @@ hw.module @muxedSignal(inout %arg0 : i64, inout %arg1 : i64, inout %arg2 : i1) {
|
|||
%cond = llhd.prb %arg2 : !hw.inout<i1>
|
||||
%sig = comb.mux %cond, %arg0, %arg1 : !hw.inout<i64>
|
||||
%0 = llhd.prb %sig : !hw.inout<i64>
|
||||
// expected-error @+1 {{during process-lowering: the wait terminator is required to have all probed signals as arguments}}
|
||||
llhd.wait (%arg0, %arg2 : !hw.inout<i64>, !hw.inout<i1>), ^bb1
|
||||
// expected-error @+1 {{during process-lowering: the wait terminator is required to have values used in the process as arguments}}
|
||||
llhd.wait (%cond : i1), ^bb1
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,6 +32,14 @@ hw.module @basic(in %cond: i1) {
|
|||
%n = llhd.sig %c0_i5 : i5
|
||||
%o = llhd.sig %c0_i5 : i5
|
||||
|
||||
%prb_k = llhd.prb %k : !hw.inout<i5>
|
||||
%prb_c = llhd.prb %c : !hw.inout<i1>
|
||||
%prb_e = llhd.prb %e : !hw.inout<i1>
|
||||
%prb_h = llhd.prb %h : !hw.inout<i4>
|
||||
%prb_d = llhd.prb %d : !hw.inout<i1>
|
||||
%prb_f = llhd.prb %f : !hw.inout<i1>
|
||||
%prb_g = llhd.prb %g : !hw.inout<i4>
|
||||
|
||||
// COM: Check that an auxillary block is created and all drives are moved to
|
||||
// COM: the exit block with the correct enable condition
|
||||
// CHECK: llhd.process
|
||||
|
@ -41,7 +49,7 @@ hw.module @basic(in %cond: i1) {
|
|||
// CHECK: ^[[BB1]]:
|
||||
^bb1:
|
||||
// CHECK: llhd.wait ({{.*}}), ^[[BB2:.+]]
|
||||
llhd.wait (%k, %c, %e, %h, %d, %f, %g : !hw.inout<i5>, !hw.inout<i1>, !hw.inout<i1>, !hw.inout<i4>, !hw.inout<i1>, !hw.inout<i1>, !hw.inout<i4>), ^bb2
|
||||
llhd.wait (%prb_k, %prb_c, %prb_e, %prb_h, %prb_d, %prb_f, %prb_g : i5, i1, i1, i4, i1, i1, i4), ^bb2
|
||||
// CHECK: ^[[BB2]]:
|
||||
^bb2:
|
||||
// CHECK: [[V14:%.+]] = llhd.prb %k
|
||||
|
|
Loading…
Reference in New Issue