From 2ad0fedb66c136f10a6a3540b01c28ca1d0baf9f Mon Sep 17 00:00:00 2001 From: Hideto Ueno Date: Thu, 26 Dec 2024 21:19:22 -0800 Subject: [PATCH 1/4] [CombToAIG] Use string substitution in a test, NFC --- test/Conversion/CombToAIG/comb-to-aig-arith.mlir | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/Conversion/CombToAIG/comb-to-aig-arith.mlir b/test/Conversion/CombToAIG/comb-to-aig-arith.mlir index 59d956e953a0..00514f0a3d06 100644 --- a/test/Conversion/CombToAIG/comb-to-aig-arith.mlir +++ b/test/Conversion/CombToAIG/comb-to-aig-arith.mlir @@ -34,11 +34,11 @@ hw.module @sub(in %lhs: i4, in %rhs: i4, out out: i4) { // ALLOW_ADD-NEXT: %[[EXT_0:.+]] = comb.extract %lhs from 0 : (i2) -> i1 // ALLOW_ADD-NEXT: %[[EXT_1:.+]] = comb.extract %lhs from 1 : (i2) -> i1 // ALLOW_ADD-NEXT: %c0_i2 = hw.constant 0 : i2 -// ALLOW_ADD-NEXT: %[[MUX_0:.+]] = comb.mux %0, %rhs, %c0_i2 : i2 -// ALLOW_ADD-NEXT: %[[MUX_1:.+]] = comb.mux %1, %rhs, %c0_i2 : i2 -// ALLOW_ADD-NEXT: %[[EXT_MUX_1:.+]] = comb.extract %3 from 0 : (i2) -> i1 +// ALLOW_ADD-NEXT: %[[MUX_0:.+]] = comb.mux %[[EXT_0]], %rhs, %c0_i2 : i2 +// ALLOW_ADD-NEXT: %[[MUX_1:.+]] = comb.mux %[[EXT_1]], %rhs, %c0_i2 : i2 +// ALLOW_ADD-NEXT: %[[EXT_MUX_1:.+]] = comb.extract %[[MUX_1]] from 0 : (i2) -> i1 // ALLOW_ADD-NEXT: %false = hw.constant false -// ALLOW_ADD-NEXT: %[[SHIFT:.+]] = comb.concat %4, %false : i1, i1 +// ALLOW_ADD-NEXT: %[[SHIFT:.+]] = comb.concat %[[EXT_MUX_1]], %false : i1, i1 // ALLOW_ADD-NEXT: %[[ADD:.+]] = comb.add bin %[[MUX_0]], %[[SHIFT]] : i2 // ALLOW_ADD-NEXT: hw.output %[[ADD]] : i2 // ALLOW_ADD-NEXT: } From e9f915cfe68ba6c8361a5af7418a40e692a8c4e0 Mon Sep 17 00:00:00 2001 From: Hideto Ueno Date: Sun, 29 Dec 2024 16:17:33 -0800 Subject: [PATCH 2/4] [CombToAIG] Lower comb.parity comb.parity can be lowered into comb.xor. LEC is verified. --- .../circt-synth/comb-lowering-lec.mlir | 7 +++++++ lib/Conversion/CombToAIG/CombToAIG.cpp | 15 ++++++++++++++- test/Conversion/CombToAIG/comb-to-aig-arith.mlir | 12 ++++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/integration_test/circt-synth/comb-lowering-lec.mlir b/integration_test/circt-synth/comb-lowering-lec.mlir index 9db9667c7be9..1b3f0944aac8 100644 --- a/integration_test/circt-synth/comb-lowering-lec.mlir +++ b/integration_test/circt-synth/comb-lowering-lec.mlir @@ -14,6 +14,13 @@ hw.module @bit_logical(in %arg0: i32, in %arg1: i32, in %arg2: i32, in %arg3: i3 hw.output %0, %1, %2, %3 : i32, i32, i32, i32 } +// RUN: circt-lec %t.mlir %s -c1=parity -c2=parity --shared-libs=%libz3 | FileCheck %s --check-prefix=COMB_PARITY +// COMB_PARITY: c1 == c2 +hw.module @parity(in %arg0: i4, out out: i1) { + %0 = comb.parity %arg0 : i4 + hw.output %0 : i1 +} + // RUN: circt-lec %t.mlir %s -c1=add -c2=add --shared-libs=%libz3 | FileCheck %s --check-prefix=COMB_ADD // COMB_ADD: c1 == c2 hw.module @add(in %arg0: i4, in %arg1: i4, in %arg2: i4, out add: i4) { diff --git a/lib/Conversion/CombToAIG/CombToAIG.cpp b/lib/Conversion/CombToAIG/CombToAIG.cpp index f7613baa5aac..986d56ad5018 100644 --- a/lib/Conversion/CombToAIG/CombToAIG.cpp +++ b/lib/Conversion/CombToAIG/CombToAIG.cpp @@ -328,6 +328,19 @@ struct CombMulOpConversion : OpConversionPattern { } }; +struct CombParityOpConversion : OpConversionPattern { + using OpConversionPattern::OpConversionPattern; + + LogicalResult + matchAndRewrite(ParityOp op, OpAdaptor adaptor, + ConversionPatternRewriter &rewriter) const override { + // Parity is the XOR of all bits. + rewriter.replaceOpWithNewOp( + op, extractBits(rewriter, adaptor.getInput()), true); + return success(); + } +}; + } // namespace //===----------------------------------------------------------------------===// @@ -347,7 +360,7 @@ static void populateCombToAIGConversionPatterns(RewritePatternSet &patterns) { patterns.add< // Bitwise Logical Ops CombAndOpConversion, CombOrOpConversion, CombXorOpConversion, - CombMuxOpConversion, + CombMuxOpConversion, CombParityOpConversion, // Arithmetic Ops CombAddOpConversion, CombSubOpConversion, CombMulOpConversion, // Variadic ops that must be lowered to binary operations diff --git a/test/Conversion/CombToAIG/comb-to-aig-arith.mlir b/test/Conversion/CombToAIG/comb-to-aig-arith.mlir index 00514f0a3d06..faa1a13db6b0 100644 --- a/test/Conversion/CombToAIG/comb-to-aig-arith.mlir +++ b/test/Conversion/CombToAIG/comb-to-aig-arith.mlir @@ -2,6 +2,18 @@ // RUN: circt-opt %s --pass-pipeline="builtin.module(hw.module(convert-comb-to-aig{additional-legal-ops=comb.xor,comb.or,comb.and,comb.mux,comb.add}))" | FileCheck %s --check-prefix=ALLOW_ADD +// CHECK-LABEL: @parity +hw.module @parity(in %arg0: i4, out out: i1) { + // CHECK-NEXT: %[[ext0:.+]] = comb.extract %arg0 from 0 : (i4) -> i1 + // CHECK-NEXT: %[[ext1:.+]] = comb.extract %arg0 from 1 : (i4) -> i1 + // CHECK-NEXT: %[[ext2:.+]] = comb.extract %arg0 from 2 : (i4) -> i1 + // CHECK-NEXT: %[[ext3:.+]] = comb.extract %arg0 from 3 : (i4) -> i1 + // CHECK-NEXT: %[[xor:.+]] = comb.xor bin %[[ext0]], %[[ext1]], %[[ext2]], %[[ext3]] : i1 + // CHECK-NEXT: hw.output %[[xor]] : i1 + %0 = comb.parity %arg0 : i4 + hw.output %0 : i1 +} + // CHECK-LABEL: @add hw.module @add(in %lhs: i2, in %rhs: i2, out out: i2) { // CHECK: %[[lhs0:.*]] = comb.extract %lhs from 0 : (i2) -> i1 From bae447c8f12a1df7f0ccbaaeddd4954e769d2d2b Mon Sep 17 00:00:00 2001 From: Martin Erhart Date: Tue, 31 Dec 2024 10:15:21 +0100 Subject: [PATCH 3/4] [Arc][ArcToLLVM] Support seq.clock_inv --- lib/Conversion/ArcToLLVM/LowerArcToLLVM.cpp | 14 ++++++++++++++ test/Conversion/ArcToLLVM/lower-arc-to-llvm.mlir | 7 +++++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/lib/Conversion/ArcToLLVM/LowerArcToLLVM.cpp b/lib/Conversion/ArcToLLVM/LowerArcToLLVM.cpp index cf1c758e1ad1..66a1592361be 100644 --- a/lib/Conversion/ArcToLLVM/LowerArcToLLVM.cpp +++ b/lib/Conversion/ArcToLLVM/LowerArcToLLVM.cpp @@ -265,6 +265,19 @@ struct ClockGateOpLowering : public OpConversionPattern { } }; +/// Lower 'seq.clock_inv x' to 'llvm.xor x true' +struct ClockInvOpLowering : public OpConversionPattern { + using OpConversionPattern::OpConversionPattern; + LogicalResult + matchAndRewrite(seq::ClockInverterOp op, OpAdaptor adaptor, + ConversionPatternRewriter &rewriter) const final { + auto constTrue = rewriter.create(op->getLoc(), + rewriter.getI1Type(), 1); + rewriter.replaceOpWithNewOp(op, adaptor.getInput(), constTrue); + return success(); + } +}; + struct ZeroCountOpLowering : public OpConversionPattern { using OpConversionPattern::OpConversionPattern; LogicalResult @@ -646,6 +659,7 @@ void LowerArcToLLVMPass::runOnOperation() { AllocStateLikeOpLowering, AllocStorageOpLowering, ClockGateOpLowering, + ClockInvOpLowering, MemoryReadOpLowering, MemoryWriteOpLowering, ModelOpLowering, diff --git a/test/Conversion/ArcToLLVM/lower-arc-to-llvm.mlir b/test/Conversion/ArcToLLVM/lower-arc-to-llvm.mlir index cacdf64a6238..faa372e64411 100644 --- a/test/Conversion/ArcToLLVM/lower-arc-to-llvm.mlir +++ b/test/Conversion/ArcToLLVM/lower-arc-to-llvm.mlir @@ -179,12 +179,15 @@ func.func @seqClocks(%clk1: !seq.clock, %clk2: !seq.clock) -> !seq.clock { %1 = seq.from_clock %clk2 %2 = arith.xori %0, %1 : i1 %3 = seq.to_clock %2 - return %3 : !seq.clock + %4 = seq.clock_inv %3 + return %4 : !seq.clock } // CHECK-LABEL: llvm.func @seqClocks // CHECK-SAME: ([[CLK1:%.+]]: i1, [[CLK2:%.+]]: i1) // CHECK: [[RES:%.+]] = llvm.xor [[CLK1]], [[CLK2]] -// CHECK: llvm.return [[RES]] : i1 +// CHECK: [[TRUE:%.+]] = llvm.mlir.constant(true) : i1 +// CHECK: [[RES1:%.+]] = llvm.xor [[RES]], [[TRUE]] : i1 +// CHECK: llvm.return [[RES1]] : i1 // CHECK-LABEL: llvm.func @ReadAggregates( // CHECK-SAME: %arg0: !llvm.ptr From afa566aabda8a7bcb2d30c971a2b2ebd3dff069f Mon Sep 17 00:00:00 2001 From: Martin Erhart Date: Tue, 31 Dec 2024 10:25:30 +0100 Subject: [PATCH 4/4] [Arc][ArcToLLVM] Fix seq.clock_gate lowering This op did not properly lower because it created comb ops for which no lowering pattern was registered. Instead, lower to LLVM directly, but also register the CombToArith patterns to support comb as intermediate operations. This is also consistent with registering HWToLLVM and CombToLLVM in this pass directly. Also, add a missing test for the clock gate lowering. --- lib/Conversion/ArcToLLVM/CMakeLists.txt | 1 + lib/Conversion/ArcToLLVM/LowerArcToLLVM.cpp | 6 ++++-- test/Conversion/ArcToLLVM/lower-arc-to-llvm.mlir | 6 ++++-- tools/arcilator/arcilator.cpp | 1 - 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/lib/Conversion/ArcToLLVM/CMakeLists.txt b/lib/Conversion/ArcToLLVM/CMakeLists.txt index 213b31f38883..4544210ea80e 100644 --- a/lib/Conversion/ArcToLLVM/CMakeLists.txt +++ b/lib/Conversion/ArcToLLVM/CMakeLists.txt @@ -11,6 +11,7 @@ add_circt_conversion_library(CIRCTArcToLLVM CIRCTArc CIRCTComb CIRCTSeq + CIRCTCombToArith CIRCTCombToLLVM CIRCTHWToLLVM MLIRArithToLLVM diff --git a/lib/Conversion/ArcToLLVM/LowerArcToLLVM.cpp b/lib/Conversion/ArcToLLVM/LowerArcToLLVM.cpp index 66a1592361be..8d8f80c17941 100644 --- a/lib/Conversion/ArcToLLVM/LowerArcToLLVM.cpp +++ b/lib/Conversion/ArcToLLVM/LowerArcToLLVM.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "circt/Conversion/ArcToLLVM.h" +#include "circt/Conversion/CombToArith.h" #include "circt/Conversion/CombToLLVM.h" #include "circt/Conversion/HWToLLVM.h" #include "circt/Dialect/Arc/ArcOps.h" @@ -259,8 +260,8 @@ struct ClockGateOpLowering : public OpConversionPattern { LogicalResult matchAndRewrite(seq::ClockGateOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const final { - rewriter.replaceOpWithNewOp(op, adaptor.getInput(), - adaptor.getEnable(), true); + rewriter.replaceOpWithNewOp(op, adaptor.getInput(), + adaptor.getEnable()); return success(); } }; @@ -648,6 +649,7 @@ void LowerArcToLLVMPass::runOnOperation() { populateHWToLLVMConversionPatterns(converter, patterns, globals, constAggregateGlobalsMap); populateHWToLLVMTypeConversions(converter); + populateCombToArithConversionPatterns(converter, patterns); populateCombToLLVMConversionPatterns(converter, patterns); // Arc patterns. diff --git a/test/Conversion/ArcToLLVM/lower-arc-to-llvm.mlir b/test/Conversion/ArcToLLVM/lower-arc-to-llvm.mlir index faa372e64411..7ad14ed5e0d8 100644 --- a/test/Conversion/ArcToLLVM/lower-arc-to-llvm.mlir +++ b/test/Conversion/ArcToLLVM/lower-arc-to-llvm.mlir @@ -180,14 +180,16 @@ func.func @seqClocks(%clk1: !seq.clock, %clk2: !seq.clock) -> !seq.clock { %2 = arith.xori %0, %1 : i1 %3 = seq.to_clock %2 %4 = seq.clock_inv %3 - return %4 : !seq.clock + %5 = seq.clock_gate %4, %0 + return %5 : !seq.clock } // CHECK-LABEL: llvm.func @seqClocks // CHECK-SAME: ([[CLK1:%.+]]: i1, [[CLK2:%.+]]: i1) // CHECK: [[RES:%.+]] = llvm.xor [[CLK1]], [[CLK2]] // CHECK: [[TRUE:%.+]] = llvm.mlir.constant(true) : i1 // CHECK: [[RES1:%.+]] = llvm.xor [[RES]], [[TRUE]] : i1 -// CHECK: llvm.return [[RES1]] : i1 +// CHECK: [[RES2:%.+]] = llvm.and [[RES1]], [[CLK1]] : i1 +// CHECK: llvm.return [[RES2]] : i1 // CHECK-LABEL: llvm.func @ReadAggregates( // CHECK-SAME: %arg0: !llvm.ptr diff --git a/tools/arcilator/arcilator.cpp b/tools/arcilator/arcilator.cpp index 9f092e800a86..47b1918bb0fe 100644 --- a/tools/arcilator/arcilator.cpp +++ b/tools/arcilator/arcilator.cpp @@ -355,7 +355,6 @@ static void populateArcToLLVMPipeline(PassManager &pm) { // Lower the arcs and update functions to LLVM. if (untilReached(UntilLLVMLowering)) return; - pm.addPass(createConvertCombToArithPass()); pm.addPass(createLowerArcToLLVMPass()); pm.addPass(createCSEPass()); pm.addPass(arc::createArcCanonicalizerPass());