Skip to content

Commit

Permalink
[sim] Add emission for plusargs for UPF simulations
Browse files Browse the repository at this point in the history
For UPF simulations, we want to disable plusargs but drive the output
wires with 0 instead of z.  We want this to be able to enable this mode
of operation while also enabling assertions, so we add another macro
UPF_SIM to control this behaviour.
  • Loading branch information
youngar committed Feb 28, 2025
1 parent 3a4eb3a commit fa875f7
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 23 deletions.
63 changes: 51 additions & 12 deletions lib/Conversion/SimToSV/SimToSV.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ namespace {
struct SimConversionState {
hw::HWModuleOp module;
bool usedSynthesisMacro = false;
bool usedUPFSimMacro = false;
SetVector<StringAttr> dpiCallees;
};

Expand Down Expand Up @@ -99,6 +100,7 @@ class PlusArgsValueLowering : public SimConversionPattern<PlusArgsValueOp> {
rewriter.getStringAttr("_pargs_f"));

state.usedSynthesisMacro = true;
state.usedUPFSimMacro = true;
rewriter.create<sv::IfDefOp>(
loc, "SYNTHESIS",
[&]() {
Expand All @@ -115,18 +117,38 @@ class PlusArgsValueLowering : public SimConversionPattern<PlusArgsValueOp> {
rewriter.create<sv::AssignOp>(loc, regf, cstFalse);
},
[&]() {
rewriter.create<sv::InitialOp>(loc, [&] {
auto zero32 = rewriter.create<hw::ConstantOp>(loc, APInt(32, 0));
auto tmpResultType = rewriter.getIntegerType(32);
auto str =
rewriter.create<sv::ConstantStrOp>(loc, op.getFormatString());
auto call = rewriter.create<sv::SystemFunctionOp>(
loc, tmpResultType, "value$plusargs",
ArrayRef<Value>{str, regv});
auto test = rewriter.create<comb::ICmpOp>(
loc, comb::ICmpPredicate::ne, call, zero32, true);
rewriter.create<sv::BPAssignOp>(loc, regf, test);
});
rewriter.create<sv::IfDefOp>(
loc, "UPF_SIMULATION",
[&]() {
auto zero = rewriter.create<hw::ConstantOp>(
loc, APInt(type.getIntOrFloatBitWidth(), 0));
auto assign = rewriter.create<sv::AssignOp>(loc, regv, zero);
circt::sv::setSVAttributes(
assign,
sv::SVAttributeAttr::get(
rewriter.getContext(),
"This dummy assignment exists to avoid undriven lint "
"warnings (e.g., Verilator UNDRIVEN).",
/*emitAsComment=*/true));
auto cstFalse =
rewriter.create<hw::ConstantOp>(loc, APInt(1, 0));
rewriter.create<sv::AssignOp>(loc, regf, cstFalse);
},
[&]() {
rewriter.create<sv::InitialOp>(loc, [&] {
auto zero32 =
rewriter.create<hw::ConstantOp>(loc, APInt(32, 0));
auto tmpResultType = rewriter.getIntegerType(32);
auto str = rewriter.create<sv::ConstantStrOp>(
loc, op.getFormatString());
auto call = rewriter.create<sv::SystemFunctionOp>(
loc, tmpResultType, "value$plusargs",
ArrayRef<Value>{str, regv});
auto test = rewriter.create<comb::ICmpOp>(
loc, comb::ICmpPredicate::ne, call, zero32, true);
rewriter.create<sv::BPAssignOp>(loc, regf, test);
});
});
});

auto readf = rewriter.create<sv::ReadInOutOp>(loc, regf);
Expand Down Expand Up @@ -316,6 +338,7 @@ struct SimToSVPass : public circt::impl::LowerSimToSVBase<SimToSVPass> {
lowerDPIFunc.lower(func);

std::atomic<bool> usedSynthesisMacro = false;
std::atomic<bool> usedUPFSimMacro = false;
auto lowerModule = [&](hw::HWModuleOp module) {
SimConversionState state;
ConversionTarget target(*context);
Expand Down Expand Up @@ -343,6 +366,8 @@ struct SimToSVPass : public circt::impl::LowerSimToSVBase<SimToSVPass> {

if (state.usedSynthesisMacro)
usedSynthesisMacro = true;
if (state.usedUPFSimMacro)
usedUPFSimMacro = true;
return result;
};

Expand All @@ -363,6 +388,20 @@ struct SimToSVPass : public circt::impl::LowerSimToSVBase<SimToSVPass> {
builder.create<sv::MacroDeclOp>("SYNTHESIS");
}
}

if (usedUPFSimMacro) {
Operation *op = circuit.lookupSymbol("UPF_SIMULATION");
if (op) {
if (!isa<sv::MacroDeclOp>(op)) {
op->emitOpError("should be a macro declaration");
return signalPassFailure();
}
} else {
auto builder = ImplicitLocOpBuilder::atBlockBegin(
UnknownLoc::get(context), circuit.getBody());
builder.create<sv::MacroDeclOp>("UPF_SIMULATION");
}
}
}
};
} // anonymous namespace
Expand Down
21 changes: 15 additions & 6 deletions test/Conversion/SimToSV/plusargs.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,21 @@ hw.module @plusargs_value(out test: i1, out value: i5) {
// CHECK-SAME: emitAsComment
// CHECK-NEXT: sv.assign [[BAR_FOUND_DECL]], %false
// CHECK-NEXT: } else {
// CHECK-NEXT: sv.initial {
// CHECK-NEXT: %c0_i32 = hw.constant 0 : i32
// CHECK-NEXT: [[BAR_STR:%.*]] = sv.constantStr "bar"
// CHECK-NEXT: [[TMP:%.*]] = sv.system "value$plusargs"([[BAR_STR]], [[BAR_VALUE_DECL]])
// CHECK-NEXT: [[TMP2:%.*]] = comb.icmp bin ne [[TMP]], %c0_i32
// CHECK-NEXT: sv.bpassign [[BAR_FOUND_DECL]], [[TMP2]]
// CHECK-NEXT: sv.ifdef @UPF_SIMULATION {
// CHECK-NEXT: %c0_i5 = hw.constant 0 : i5
// CHECK-NEXT: sv.assign [[BAR_VALUE_DECL]], %c0_i5 {sv.attributes = [
// CHECK-SAME: #sv.attribute<"This dummy assignment exists to avoid undriven lint warnings
// CHECK-SAME: emitAsComment
// CHECK-NEXT: %false = hw.constant false
// CHECK-NEXT: sv.assign [[BAR_FOUND_DECL]], %false
// CHECK-NEXT: } else {
// CHECK-NEXT: sv.initial {
// CHECK-NEXT: %c0_i32 = hw.constant 0 : i32
// CHECK-NEXT: [[BAR_STR:%.*]] = sv.constantStr "bar"
// CHECK-NEXT: [[TMP:%.*]] = sv.system "value$plusargs"([[BAR_STR]], [[BAR_VALUE_DECL]])
// CHECK-NEXT: [[TMP2:%.*]] = comb.icmp bin ne [[TMP]], %c0_i32
// CHECK-NEXT: sv.bpassign [[BAR_FOUND_DECL]], [[TMP2]]
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: [[BAR_FOUND:%.*]] = sv.read_inout [[BAR_FOUND_DECL]]
Expand Down
15 changes: 10 additions & 5 deletions test/firtool/plusargs.fir
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,16 @@ circuit PlusArgTest:
; CHECK-NEXT: sv.assign [[RESULT_BAR_REG]], %z_i32 {sv.attributes = [#sv.attribute<"This dummy assignment exists to avoid undriven lint warnings (e.g., Verilator UNDRIVEN).", emitAsComment>]} : i32
; CHECK-NEXT: sv.assign [[FOUND_BAR_REG]], %false : i1
; CHECK-NEXT: } else {
; CHECK-NEXT: sv.initial {
; CHECK-NEXT: [[FORMAT_BAR:%.+]] = sv.constantStr "foo=%d"
; CHECK-NEXT: [[TMP_BAR:%.+]] = sv.system "value$plusargs"([[FORMAT_BAR]], [[RESULT_BAR_REG]]) : (!hw.string, !hw.inout<i32>) -> i32
; CHECK-NEXT: [[FOUND_BAR_VAL:%.+]] = comb.icmp bin ne [[TMP_BAR]], %c0_i32 : i32
; CHECK-NEXT: sv.bpassign [[FOUND_BAR_REG]], [[FOUND_BAR_VAL]] : i1
; CHECK-NEXT: sv.ifdef @UPF_SIMULATION {
; CHECK-NEXT: sv.assign [[RESULT_BAR_REG]], %c0_i32 {sv.attributes = [#sv.attribute<"This dummy assignment exists to avoid undriven lint warnings (e.g., Verilator UNDRIVEN).", emitAsComment>]} : i32
; CHECK-NEXT: sv.assign [[FOUND_BAR_REG]], %false : i1
; CHECK-NEXT: } else {
; CHECK-NEXT: sv.initial {
; CHECK-NEXT: [[FORMAT_BAR:%.+]] = sv.constantStr "foo=%d"
; CHECK-NEXT: [[TMP_BAR:%.+]] = sv.system "value$plusargs"([[FORMAT_BAR]], [[RESULT_BAR_REG]]) : (!hw.string, !hw.inout<i32>) -> i32
; CHECK-NEXT: [[FOUND_BAR_VAL:%.+]] = comb.icmp bin ne [[TMP_BAR]], %c0_i32 : i32
; CHECK-NEXT: sv.bpassign [[FOUND_BAR_REG]], [[FOUND_BAR_VAL]] : i1
; CHECK-NEXT: }
; CHECK-NEXT: }
; CHECK-NEXT: }
; CHECK-NEXT: [[FOUND_BAR:%.+]] = sv.read_inout [[FOUND_BAR_REG]] : !hw.inout<i1>
Expand Down

0 comments on commit fa875f7

Please sign in to comment.