From e9150ac3de7a0876c26b6f6267624d598cee7942 Mon Sep 17 00:00:00 2001 From: Andrey Vyazovtsev <70313689+AndreyVV-100@users.noreply.github.com> Date: Thu, 5 Dec 2024 19:54:14 +0300 Subject: [PATCH] [MooreToCore] Add multibit DetectEventOp support (#7943) --- lib/Conversion/MooreToCore/MooreToCore.cpp | 30 ++++-- test/Conversion/MooreToCore/basic.mlir | 105 +++++++++++++++++++-- 2 files changed, 118 insertions(+), 17 deletions(-) diff --git a/lib/Conversion/MooreToCore/MooreToCore.cpp b/lib/Conversion/MooreToCore/MooreToCore.cpp index 7853e71c0630..486d362bbf86 100644 --- a/lib/Conversion/MooreToCore/MooreToCore.cpp +++ b/lib/Conversion/MooreToCore/MooreToCore.cpp @@ -393,10 +393,26 @@ struct WaitEventOpConversion : public OpConversionPattern { // 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(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(loc, beforeType, before, LSB); + after = rewriter.create(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(loc, ICmpPredicate::ne, before, @@ -430,10 +446,8 @@ struct WaitEventOpConversion : public OpConversionPattern { // value corresponds to the detect op's input. SmallVector triggers; for (auto [detectOp, before] : llvm::zip(detectOps, valuesBefore)) { - // TODO: Support multi-bit values. Edge detection occurs per-bit. - if (auto intType = dyn_cast(before.getType()); - !intType || intType.getWidth() != 1) - return detectOp->emitError() << "requires single bit operand"; + if (!isa(before.getType())) + return detectOp->emitError() << "requires int operand"; rewriter.setInsertionPoint(detectOp); auto trigger = diff --git a/test/Conversion/MooreToCore/basic.mlir b/test/Conversion/MooreToCore/basic.mlir index ea1baf413d2c..7b7b70eabb18 100644 --- a/test/Conversion/MooreToCore/basic.mlir +++ b/test/Conversion/MooreToCore/basic.mlir @@ -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 : %b = moore.variable : %c = moore.variable : + %d = moore.variable : // CHECK: llhd.process { // CHECK: func.call @dummyA() @@ -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 : + moore.detect_event any %0 : i4 + } + moore.return + } + // CHECK: llhd.process { moore.procedure initial { // CHECK: [[BEFORE_A:%.+]] = llhd.prb %a @@ -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 : %1 = moore.read %b : %2 = moore.read %c : + %3 = moore.read %d : 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 } @@ -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 : + 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 : + 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 : + moore.detect_event edge %0 : i4 + } + moore.return + } + // CHECK: [[PRB_A:%.+]] = llhd.prb %a // CHECK: [[PRB_B:%.+]] = llhd.prb %b // CHECK: llhd.process { @@ -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 : + %3 = moore.read %e : moore.return } - // CHECK: %d = llhd.sig %false - %d = moore.variable : + // CHECK: %e = llhd.sig %false + %e = moore.variable : // CHECK: llhd.process { moore.procedure initial {