14 #include "../PassDetail.h"
21 #include "mlir/IR/Builders.h"
22 #include "mlir/IR/DialectImplementation.h"
23 #include "mlir/IR/ImplicitLocOpBuilder.h"
24 #include "mlir/IR/Threading.h"
25 #include "mlir/Pass/Pass.h"
26 #include "mlir/Transforms/DialectConversion.h"
28 #define DEBUG_TYPE "lower-sim-to-sv"
30 using namespace circt;
35 struct SimConversionState {
36 std::atomic<bool> usedSynthesisMacro =
false;
41 explicit SimConversionPattern(MLIRContext *context, SimConversionState &state)
44 SimConversionState &state;
53 using SimConversionPattern<PlusArgsTestOp>::SimConversionPattern;
57 ConversionPatternRewriter &rewriter)
const final {
58 auto loc = op.getLoc();
59 auto resultType = rewriter.getIntegerType(1);
60 auto str = rewriter.create<sv::ConstantStrOp>(loc, op.getFormatString());
62 rewriter.getStringAttr(
"_pargs"));
63 rewriter.create<sv::InitialOp>(loc, [&] {
64 auto call = rewriter.create<sv::SystemFunctionOp>(
65 loc, resultType,
"test$plusargs", ArrayRef<Value>{str});
66 rewriter.create<sv::BPAssignOp>(loc,
reg, call);
78 using SimConversionPattern<PlusArgsValueOp>::SimConversionPattern;
82 ConversionPatternRewriter &rewriter)
const final {
83 auto loc = op.getLoc();
85 auto i1ty = rewriter.getIntegerType(1);
86 auto type = op.getResult().getType();
88 auto regv = rewriter.create<
sv::RegOp>(loc, type,
89 rewriter.getStringAttr(
"_pargs_v_"));
90 auto regf = rewriter.create<
sv::RegOp>(loc, i1ty,
91 rewriter.getStringAttr(
"_pargs_f"));
93 state.usedSynthesisMacro =
true;
98 auto cstZ = rewriter.
create<sv::ConstantZOp>(loc, type);
99 auto assignZ = rewriter.create<
sv::AssignOp>(loc, regv, cstZ);
103 rewriter.getContext(),
104 "This dummy assignment exists to avoid undriven lint "
105 "warnings (e.g., Verilator UNDRIVEN).",
110 rewriter.
create<sv::InitialOp>(loc, [&] {
112 auto tmpResultType = rewriter.getIntegerType(32);
114 rewriter.
create<sv::ConstantStrOp>(loc, op.getFormatString());
115 auto call = rewriter.create<sv::SystemFunctionOp>(
116 loc, tmpResultType,
"value$plusargs",
117 ArrayRef<Value>{str, regv});
118 auto test = rewriter.create<comb::ICmpOp>(
119 loc, comb::ICmpPredicate::ne, call, zero32,
true);
120 rewriter.create<sv::BPAssignOp>(loc, regf, test);
126 rewriter.replaceOp(op, {readf, readv});
131 template <
typename FromOp,
typename ToOp>
134 using SimConversionPattern<FromOp>::SimConversionPattern;
138 ConversionPatternRewriter &rewriter)
const final {
139 auto loc = op.getLoc();
141 Value clockCast = rewriter.create<seq::FromClockOp>(loc, adaptor.getClk());
143 this->state.usedSynthesisMacro =
true;
145 loc,
"SYNTHESIS", [&] {},
147 rewriter.create<sv::AlwaysOp>(
148 loc, sv::EventControl::AtPosEdge, clockCast, [&] {
149 rewriter.create<sv::IfOp>(loc, adaptor.getCond(),
150 [&] { rewriter.create<ToOp>(loc); });
154 rewriter.eraseOp(op);
161 struct SimToSVPass :
public LowerSimToSVBase<SimToSVPass> {
162 void runOnOperation()
override {
163 auto circuit = getOperation();
164 MLIRContext *context = &getContext();
166 SimConversionState state;
168 ConversionTarget target(*context);
169 target.addIllegalDialect<SimDialect>();
170 target.addLegalDialect<sv::SVDialect>();
171 target.addLegalDialect<hw::HWDialect>();
172 target.addLegalDialect<seq::SeqDialect>();
173 target.addLegalDialect<comb::CombDialect>();
175 RewritePatternSet
patterns(context);
182 return applyPartialConversion(module, target, std::move(
patterns));
185 if (failed(mlir::failableParallelForEach(
187 return signalPassFailure();
189 if (state.usedSynthesisMacro) {
190 Operation *op = circuit.lookupSymbol(
"SYNTHESIS");
192 if (!isa<sv::MacroDeclOp>(op)) {
193 op->emitOpError(
"should be a macro declaration");
194 return signalPassFailure();
197 auto builder = ImplicitLocOpBuilder::atBlockBegin(
199 builder.create<sv::MacroDeclOp>(
"SYNTHESIS");
207 return std::make_unique<SimToSVPass>();
LogicalResult matchAndRewrite(PlusArgsTestOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const final
LogicalResult matchAndRewrite(PlusArgsValueOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const final
LogicalResult matchAndRewrite(FromOp op, typename FromOp::Adaptor adaptor, ConversionPatternRewriter &rewriter) const final
def create(data_type, value)
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
void setSVAttributes(mlir::Operation *op, mlir::ArrayAttr attrs)
Set the SV attributes of an operation.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
std::unique_ptr< mlir::Pass > createLowerSimToSVPass()
def reg(value, clock, reset=None, reset_value=None, name=None, sym_name=None)