@@ -41,6 +41,7 @@ namespace {
41
41
struct SimConversionState {
42
42
hw::HWModuleOp module;
43
43
bool usedSynthesisMacro = false ;
44
+ bool usedUPFSimMacro = false ;
44
45
SetVector<StringAttr> dpiCallees;
45
46
};
46
47
@@ -99,6 +100,7 @@ class PlusArgsValueLowering : public SimConversionPattern<PlusArgsValueOp> {
99
100
rewriter.getStringAttr (" _pargs_f" ));
100
101
101
102
state.usedSynthesisMacro = true ;
103
+ state.usedUPFSimMacro = true ;
102
104
rewriter.create <sv::IfDefOp>(
103
105
loc, " SYNTHESIS" ,
104
106
[&]() {
@@ -115,18 +117,38 @@ class PlusArgsValueLowering : public SimConversionPattern<PlusArgsValueOp> {
115
117
rewriter.create <sv::AssignOp>(loc, regf, cstFalse);
116
118
},
117
119
[&]() {
118
- rewriter.create <sv::InitialOp>(loc, [&] {
119
- auto zero32 = rewriter.create <hw::ConstantOp>(loc, APInt (32 , 0 ));
120
- auto tmpResultType = rewriter.getIntegerType (32 );
121
- auto str =
122
- rewriter.create <sv::ConstantStrOp>(loc, op.getFormatString ());
123
- auto call = rewriter.create <sv::SystemFunctionOp>(
124
- loc, tmpResultType, " value$plusargs" ,
125
- ArrayRef<Value>{str, regv});
126
- auto test = rewriter.create <comb::ICmpOp>(
127
- loc, comb::ICmpPredicate::ne, call, zero32, true );
128
- rewriter.create <sv::BPAssignOp>(loc, regf, test);
129
- });
120
+ rewriter.create <sv::IfDefOp>(
121
+ loc, " UPF_SIMULATION" ,
122
+ [&]() {
123
+ auto zero = rewriter.create <hw::ConstantOp>(
124
+ loc, APInt (type.getIntOrFloatBitWidth (), 0 ));
125
+ auto assign = rewriter.create <sv::AssignOp>(loc, regv, zero);
126
+ circt::sv::setSVAttributes (
127
+ assign,
128
+ sv::SVAttributeAttr::get (
129
+ rewriter.getContext (),
130
+ " This dummy assignment exists to avoid undriven lint "
131
+ " warnings (e.g., Verilator UNDRIVEN)." ,
132
+ /* emitAsComment=*/ true ));
133
+ auto cstFalse =
134
+ rewriter.create <hw::ConstantOp>(loc, APInt (1 , 0 ));
135
+ rewriter.create <sv::AssignOp>(loc, regf, cstFalse);
136
+ },
137
+ [&]() {
138
+ rewriter.create <sv::InitialOp>(loc, [&] {
139
+ auto zero32 =
140
+ rewriter.create <hw::ConstantOp>(loc, APInt (32 , 0 ));
141
+ auto tmpResultType = rewriter.getIntegerType (32 );
142
+ auto str = rewriter.create <sv::ConstantStrOp>(
143
+ loc, op.getFormatString ());
144
+ auto call = rewriter.create <sv::SystemFunctionOp>(
145
+ loc, tmpResultType, " value$plusargs" ,
146
+ ArrayRef<Value>{str, regv});
147
+ auto test = rewriter.create <comb::ICmpOp>(
148
+ loc, comb::ICmpPredicate::ne, call, zero32, true );
149
+ rewriter.create <sv::BPAssignOp>(loc, regf, test);
150
+ });
151
+ });
130
152
});
131
153
132
154
auto readf = rewriter.create <sv::ReadInOutOp>(loc, regf);
@@ -316,6 +338,7 @@ struct SimToSVPass : public circt::impl::LowerSimToSVBase<SimToSVPass> {
316
338
lowerDPIFunc.lower (func);
317
339
318
340
std::atomic<bool > usedSynthesisMacro = false ;
341
+ std::atomic<bool > usedUPFSimMacro = false ;
319
342
auto lowerModule = [&](hw::HWModuleOp module) {
320
343
SimConversionState state;
321
344
ConversionTarget target (*context);
@@ -343,6 +366,8 @@ struct SimToSVPass : public circt::impl::LowerSimToSVBase<SimToSVPass> {
343
366
344
367
if (state.usedSynthesisMacro )
345
368
usedSynthesisMacro = true ;
369
+ if (state.usedUPFSimMacro )
370
+ usedUPFSimMacro = true ;
346
371
return result;
347
372
};
348
373
@@ -363,6 +388,20 @@ struct SimToSVPass : public circt::impl::LowerSimToSVBase<SimToSVPass> {
363
388
builder.create <sv::MacroDeclOp>(" SYNTHESIS" );
364
389
}
365
390
}
391
+
392
+ if (usedUPFSimMacro) {
393
+ Operation *op = circuit.lookupSymbol (" UPF_SIMULATION" );
394
+ if (op) {
395
+ if (!isa<sv::MacroDeclOp>(op)) {
396
+ op->emitOpError (" should be a macro declaration" );
397
+ return signalPassFailure ();
398
+ }
399
+ } else {
400
+ auto builder = ImplicitLocOpBuilder::atBlockBegin (
401
+ UnknownLoc::get (context), circuit.getBody ());
402
+ builder.create <sv::MacroDeclOp>(" UPF_SIMULATION" );
403
+ }
404
+ }
366
405
}
367
406
};
368
407
} // anonymous namespace
0 commit comments