[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:
Martin Erhart 2024-08-19 17:36:10 +01:00 committed by GitHub
parent 246636cee1
commit 9efc2e7572
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 125 additions and 80 deletions

View File

@ -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
}];
}

View File

@ -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));
}
}
});

View File

@ -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();
});

View File

@ -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 {

View File

@ -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

View File

@ -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

View File

@ -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>

View File

@ -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

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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