Skip to content

Commit

Permalink
[MooreToCore] Add multibit DetectEventOp support (#7943)
Browse files Browse the repository at this point in the history
  • Loading branch information
AndreyVV-100 authored Dec 5, 2024
1 parent ca2d9c7 commit e9150ac
Show file tree
Hide file tree
Showing 2 changed files with 118 additions and 17 deletions.
30 changes: 22 additions & 8 deletions lib/Conversion/MooreToCore/MooreToCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -393,10 +393,26 @@ struct WaitEventOpConversion : public OpConversionPattern<WaitEventOp> {
// Helper function to detect if a certain change occurred between a value
// before the `llhd.wait` and after.
auto computeTrigger = [&](Value before, Value after, Edge edge) -> Value {
before = typeConverter->materializeTargetConversion(
rewriter, loc, rewriter.getI1Type(), before);
after = typeConverter->materializeTargetConversion(
rewriter, loc, rewriter.getI1Type(), after);
assert(before.getType() == after.getType() &&
"mismatched types after clone op");
auto beforeType = cast<IntType>(before.getType());

// 9.4.2 IEEE 1800-2017: An edge event shall be detected only on the LSB
// of the expression
if (beforeType.getWidth() != 1 && edge != Edge::AnyChange) {
constexpr int LSB = 0;
beforeType =
IntType::get(rewriter.getContext(), 1, beforeType.getDomain());
before =
rewriter.create<moore::ExtractOp>(loc, beforeType, before, LSB);
after = rewriter.create<moore::ExtractOp>(loc, beforeType, after, LSB);
}

auto intType = rewriter.getIntegerType(beforeType.getWidth());
before = typeConverter->materializeTargetConversion(rewriter, loc,
intType, before);
after = typeConverter->materializeTargetConversion(rewriter, loc, intType,
after);

if (edge == Edge::AnyChange)
return rewriter.create<comb::ICmpOp>(loc, ICmpPredicate::ne, before,
Expand Down Expand Up @@ -430,10 +446,8 @@ struct WaitEventOpConversion : public OpConversionPattern<WaitEventOp> {
// value corresponds to the detect op's input.
SmallVector<Value> triggers;
for (auto [detectOp, before] : llvm::zip(detectOps, valuesBefore)) {
// TODO: Support multi-bit values. Edge detection occurs per-bit.
if (auto intType = dyn_cast<IntType>(before.getType());
!intType || intType.getWidth() != 1)
return detectOp->emitError() << "requires single bit operand";
if (!isa<IntType>(before.getType()))
return detectOp->emitError() << "requires int operand";

rewriter.setInsertionPoint(detectOp);
auto trigger =
Expand Down
105 changes: 96 additions & 9 deletions test/Conversion/MooreToCore/basic.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -598,9 +598,16 @@ moore.module @WaitEvent() {
// CHECK: [[PRB_B0:%.+]] = llhd.prb %b
// CHECK: %c = llhd.sig
// CHECK: [[PRB_C:%.+]] = llhd.prb %c
// CHECK: %d = llhd.sig
// CHECK: [[PRB_D4:%.+]] = llhd.prb %d
// CHECK: [[PRB_D3:%.+]] = llhd.prb %d
// CHECK: [[PRB_D2:%.+]] = llhd.prb %d
// CHECK: [[PRB_D1:%.+]] = llhd.prb %d
// CHECK: [[PRB_D0:%.+]] = llhd.prb %d
%a = moore.variable : <i1>
%b = moore.variable : <i1>
%c = moore.variable : <i1>
%d = moore.variable : <i4>

// CHECK: llhd.process {
// CHECK: func.call @dummyA()
Expand Down Expand Up @@ -641,6 +648,21 @@ moore.module @WaitEvent() {
moore.return
}

// CHECK: llhd.process {
moore.procedure initial {
// CHECK: [[BEFORE:%.+]] = llhd.prb %d
// CHECK: llhd.wait ([[PRB_D0]] : {{.+}}), ^[[CHECK:.+]]
// CHECK: ^[[CHECK]]:
// CHECK: [[AFTER:%.+]] = llhd.prb %d
// CHECK: [[TMP:%.+]] = comb.icmp bin ne [[BEFORE]], [[AFTER]]
// CHECK: cf.cond_br [[TMP]]
moore.wait_event {
%0 = moore.read %d : <i4>
moore.detect_event any %0 : i4
}
moore.return
}

// CHECK: llhd.process {
moore.procedure initial {
// CHECK: [[BEFORE_A:%.+]] = llhd.prb %a
Expand All @@ -665,23 +687,28 @@ moore.module @WaitEvent() {
// CHECK: [[BEFORE_A:%.+]] = llhd.prb %a
// CHECK: [[BEFORE_B:%.+]] = llhd.prb %b
// CHECK: [[BEFORE_C:%.+]] = llhd.prb %c
// CHECK: llhd.wait ([[PRB_A2]], [[PRB_B1]], [[PRB_C]] : {{.+}}), ^[[CHECK:.+]]
// CHECK: [[BEFORE_D:%.+]] = llhd.prb %d
// CHECK: llhd.wait ([[PRB_A2]], [[PRB_B1]], [[PRB_C]], [[PRB_D1]] : {{.+}}), ^[[CHECK:.+]]
// CHECK: ^[[CHECK]]:
// CHECK: [[AFTER_A:%.+]] = llhd.prb %a
// CHECK: [[AFTER_B:%.+]] = llhd.prb %b
// CHECK: [[AFTER_C:%.+]] = llhd.prb %c
// CHECK: [[AFTER_D:%.+]] = llhd.prb %d
// CHECK: [[TMP1:%.+]] = comb.icmp bin ne [[BEFORE_A]], [[AFTER_A]]
// CHECK: [[TMP2:%.+]] = comb.icmp bin ne [[BEFORE_B]], [[AFTER_B]]
// CHECK: [[TMP3:%.+]] = comb.icmp bin ne [[BEFORE_C]], [[AFTER_C]]
// CHECK: [[TMP4:%.+]] = comb.or bin [[TMP1]], [[TMP2]], [[TMP3]]
// CHECK: cf.cond_br [[TMP4]]
// CHECK: [[TMP4:%.+]] = comb.icmp bin ne [[BEFORE_D]], [[AFTER_D]]
// CHECK: [[TMP5:%.+]] = comb.or bin [[TMP1]], [[TMP2]], [[TMP3]], [[TMP4]]
// CHECK: cf.cond_br [[TMP5]]
moore.wait_event {
%0 = moore.read %a : <i1>
%1 = moore.read %b : <i1>
%2 = moore.read %c : <i1>
%3 = moore.read %d : <i4>
moore.detect_event any %0 : i1
moore.detect_event any %1 : i1
moore.detect_event any %2 : i1
moore.detect_event any %3 : i4
}
moore.return
}
Expand Down Expand Up @@ -740,6 +767,66 @@ moore.module @WaitEvent() {
moore.return
}

// CHECK: llhd.process {
moore.procedure initial {
// CHECK: [[BEFORE:%.+]] = llhd.prb %d
// CHECK: llhd.wait ([[PRB_D2]] : {{.+}}), ^[[CHECK:.+]]
// CHECK: ^[[CHECK]]:
// CHECK: [[AFTER:%.+]] = llhd.prb %d
// CHECK: [[TMP1:%.+]] = comb.extract [[BEFORE]] from 0 : (i4) -> i1
// CHECK: [[TMP2:%.+]] = comb.extract [[AFTER]] from 0 : (i4) -> i1
// CHECK: [[TRUE:%.+]] = hw.constant true
// CHECK: [[TMP3:%.+]] = comb.xor bin [[TMP1]], [[TRUE]]
// CHECK: [[TMP4:%.+]] = comb.and bin [[TMP3]], [[TMP2]]
// CHECK: cf.cond_br [[TMP4]]
moore.wait_event {
%0 = moore.read %d : <i4>
moore.detect_event posedge %0 : i4
}
moore.return
}

// CHECK: llhd.process {
moore.procedure initial {
// CHECK: [[BEFORE:%.+]] = llhd.prb %d
// CHECK: llhd.wait ([[PRB_D3]] : {{.+}}), ^[[CHECK:.+]]
// CHECK: ^[[CHECK]]:
// CHECK: [[AFTER:%.+]] = llhd.prb %d
// CHECK: [[TMP1:%.+]] = comb.extract [[BEFORE]] from 0 : (i4) -> i1
// CHECK: [[TMP2:%.+]] = comb.extract [[AFTER]] from 0 : (i4) -> i1
// CHECK: [[TRUE:%.+]] = hw.constant true
// CHECK: [[TMP3:%.+]] = comb.xor bin [[TMP2]], [[TRUE]]
// CHECK: [[TMP4:%.+]] = comb.and bin [[TMP1]], [[TMP3]]
// CHECK: cf.cond_br [[TMP4]]
moore.wait_event {
%0 = moore.read %d : <i4>
moore.detect_event negedge %0 : i4
}
moore.return
}

// CHECK: llhd.process {
moore.procedure initial {
// CHECK: [[BEFORE:%.+]] = llhd.prb %d
// CHECK: llhd.wait ([[PRB_D4]] : {{.+}}), ^[[CHECK:.+]]
// CHECK: ^[[CHECK]]:
// CHECK: [[AFTER:%.+]] = llhd.prb %d
// CHECK: [[TMP1:%.+]] = comb.extract [[BEFORE]] from 0 : (i4) -> i1
// CHECK: [[TMP2:%.+]] = comb.extract [[AFTER]] from 0 : (i4) -> i1
// CHECK: [[TRUE:%.+]] = hw.constant true
// CHECK: [[TMP3:%.+]] = comb.xor bin [[TMP1]], [[TRUE]]
// CHECK: [[TMP4:%.+]] = comb.and bin [[TMP3]], [[TMP2]]
// CHECK: [[TMP5:%.+]] = comb.xor bin [[TMP2]], [[TRUE]]
// CHECK: [[TMP6:%.+]] = comb.and bin [[TMP1]], [[TMP5]]
// CHECK: [[TMP7:%.+]] = comb.or bin [[TMP4]], [[TMP6]]
// CHECK: cf.cond_br [[TMP7]]
moore.wait_event {
%0 = moore.read %d : <i4>
moore.detect_event edge %0 : i4
}
moore.return
}

// CHECK: [[PRB_A:%.+]] = llhd.prb %a
// CHECK: [[PRB_B:%.+]] = llhd.prb %b
// CHECK: llhd.process {
Expand All @@ -762,21 +849,21 @@ moore.module @WaitEvent() {
moore.return
}

// CHECK: [[PRB_D:%.+]] = llhd.prb %d
// CHECK: [[PRB_E:%.+]] = llhd.prb %e
// CHECK: llhd.process {
// CHECK: cf.br ^[[BB1:.+]]
// CHECK: ^[[BB1]]:
// CHECK: llhd.prb %d
// CHECK: llhd.prb %e
// CHECK: cf.br ^[[BB2:.+]]
// CHECK: ^[[BB2]]:
// CHECK: llhd.wait ([[PRB_D]] : {{.*}}), ^[[BB1]]
// CHECK: llhd.wait ([[PRB_E]] : {{.*}}), ^[[BB1]]
moore.procedure always_latch {
%3 = moore.read %d : <i1>
%3 = moore.read %e : <i1>
moore.return
}

// CHECK: %d = llhd.sig %false
%d = moore.variable : <i1>
// CHECK: %e = llhd.sig %false
%e = moore.variable : <i1>

// CHECK: llhd.process {
moore.procedure initial {
Expand Down

0 comments on commit e9150ac

Please sign in to comment.