Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Arc] Hoist reset value in CompReg when lowering for simulation #6972

Merged
merged 4 commits into from
May 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 31 additions & 1 deletion lib/Dialect/Arc/Transforms/ArcCanonicalizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "circt/Dialect/Arc/ArcPasses.h"
#include "circt/Dialect/Comb/CombOps.h"
#include "circt/Dialect/HW/HWOps.h"
#include "circt/Dialect/Seq/SeqOps.h"
#include "circt/Support/Namespace.h"
#include "circt/Support/SymCache.h"
#include "mlir/IR/Matchers.h"
Expand Down Expand Up @@ -240,6 +241,12 @@ struct ICMPCanonicalizer : public OpRewritePattern<comb::ICmpOp> {
PatternRewriter &rewriter) const final;
};

struct CompRegCanonicalizer : public OpRewritePattern<seq::CompRegOp> {
using OpRewritePattern::OpRewritePattern;
LogicalResult matchAndRewrite(seq::CompRegOp op,
PatternRewriter &rewriter) const final;
};

struct RemoveUnusedArcArgumentsPattern : public SymOpRewritePattern<DefineOp> {
using SymOpRewritePattern::SymOpRewritePattern;
LogicalResult matchAndRewrite(DefineOp op,
Expand Down Expand Up @@ -547,6 +554,29 @@ SinkArcInputsPattern::matchAndRewrite(DefineOp op,
return success(toDelete.any());
}

LogicalResult
CompRegCanonicalizer::matchAndRewrite(seq::CompRegOp op,
PatternRewriter &rewriter) const {
if (!op.getReset())
return failure();

// Because Arcilator supports constant zero reset values, skip them.
APInt constant;
if (mlir::matchPattern(op.getResetValue(), mlir::m_ConstantInt(&constant)))
if (constant.isZero())
return failure();

Value newInput = rewriter.create<comb::MuxOp>(
op->getLoc(), op.getReset(), op.getResetValue(), op.getInput());
rewriter.modifyOpInPlace(op, [&]() {
op.getInputMutable().set(newInput);
op.getResetMutable().clear();
op.getResetValueMutable().clear();
});

return success();
}

//===----------------------------------------------------------------------===//
// ArcCanonicalizerPass implementation
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -594,7 +624,7 @@ void ArcCanonicalizerPass::runOnOperation() {
dialect->getCanonicalizationPatterns(patterns);
for (mlir::RegisteredOperationName op : ctxt.getRegisteredOperations())
op.getCanonicalizationPatterns(patterns, &ctxt);
patterns.add<ICMPCanonicalizer>(&getContext());
patterns.add<ICMPCanonicalizer, CompRegCanonicalizer>(&getContext());

// Don't test for convergence since it is often not reached.
(void)mlir::applyPatternsAndFoldGreedily(getOperation(), std::move(patterns),
Expand Down
28 changes: 28 additions & 0 deletions test/Dialect/Arc/arc-canonicalizer.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,34 @@ hw.module @icmpNeCanonicalizer(in %arg0: i1, in %arg1: i1, in %arg2: i1, in %arg
hw.output %1, %3, %5, %7 : i1, i1, i1, i1
}

//===----------------------------------------------------------------------===//
// CompRegCanonicalizer
//===----------------------------------------------------------------------===//

// CHECK-LABEL: hw.module @HoistCompRegReset
// CHECK-SAME: in %[[CLOCK:[^ ]*]] : !seq.clock, in %[[INPUT:[^ ]*]] : i32, in %[[RESET:[^ ]*]] : i1, in %[[RESET_VALUE:[^ ]*]] : i32
hw.module @HoistCompRegReset(in %clock: !seq.clock, in %input: i32, in %reset: i1, in %resetValue: i32, out out: i32) {
// CHECK: %[[NEW_INPUT:.*]] = comb.mux %[[RESET]], %[[RESET_VALUE]], %[[INPUT]] : i32
// CHECK: %[[REG:.*]] = seq.compreg %[[NEW_INPUT]], %[[CLOCK]] : i32
%reg = seq.compreg %input, %clock reset %reset, %resetValue : i32

// CHECK: hw.output %[[REG]] : i32
hw.output %reg : i32
}

// CHECK-LABEL: hw.module @NoHoistCompRegZeroResetValue
// CHECK-SAME: in %[[CLOCK:[^ ]*]] : !seq.clock, in %[[INPUT:[^ ]*]] : i32, in %[[RESET:[^ ]*]] : i1
hw.module @NoHoistCompRegZeroResetValue(in %clock: !seq.clock, in %input: i32, in %reset: i1, out out: i32) {
// CHECK: %[[ZERO:.*]] = hw.constant 0 : i32
%zero = hw.constant 0 : i32

// CHECK: %[[REG:.*]] = seq.compreg %[[INPUT]], %[[CLOCK]] reset %[[RESET]], %[[ZERO]] : i32
%reg = seq.compreg %input, %clock reset %reset, %zero : i32

// CHECK: hw.output %[[REG]] : i32
hw.output %reg : i32
}

//===----------------------------------------------------------------------===//
// RemoveUnusedArcArguments
//===----------------------------------------------------------------------===//
Expand Down
9 changes: 9 additions & 0 deletions test/arcilator/compreg.mlir
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// RUN: arcilator %s

// This test ensures that the pipeline completes, without checking the result.
// This is to make sure compatibility for some constructs does not regress.

hw.module @arbitrary_reset_value(in %value: i32, in %clock: !seq.clock, in %reset: i1, in %resetValue: i32, out out: i32) {
%reg = seq.compreg %value, %clock reset %reset, %resetValue : i32
hw.output %reg : i32
}
Loading