diff --git a/include/circt/Dialect/FIRRTL/FIRRTLIntrinsics.td b/include/circt/Dialect/FIRRTL/FIRRTLIntrinsics.td index 92dfd5313e59..02fe91b8bfd9 100644 --- a/include/circt/Dialect/FIRRTL/FIRRTLIntrinsics.td +++ b/include/circt/Dialect/FIRRTL/FIRRTLIntrinsics.td @@ -168,6 +168,38 @@ def UnclockedAssumeIntrinsicOp : FIRRTLOp<"int.unclocked_assume", []> { let hasCanonicalizer = 1; } +//===----------------------------------------------------------------------===// +// File IO intrinsics +//===----------------------------------------------------------------------===// + +def FOpenIntrinsicOp : FIRRTLOp<"int.fopen", []> { + let summary = "Open a file and return a file descriptor"; + let description = [{ + The `firrtl.int.fopen` intrinsic opens a file and returns a file descriptor. + It will be lowered into a SV `fopen` system task. + }]; + + let arguments = (ins StrAttr:$filename, StrAttr:$mode); + let results = (outs SInt32Type:$fd); + + let assemblyFormat = [{ + $filename `,` $mode attr-dict `:` qualified(type($fd)) + }]; +} + +def FCloseIntrinsicOp : FIRRTLOp<"int.fclose", []> { + let summary = "Close a file descriptor"; + let description = [{ + The `firrtl.int.fclose` intrinsic closes a file descriptor. + It will be lowered into a SV `fclose` system task. + }]; + + let arguments = (ins SInt32Type:$fd); + let results = (outs); + + let assemblyFormat = "$fd attr-dict `:` qualified(type($fd))"; +} + //===----------------------------------------------------------------------===// // Other intrinsics //===----------------------------------------------------------------------===// diff --git a/include/circt/Dialect/FIRRTL/FIRRTLStatements.td b/include/circt/Dialect/FIRRTL/FIRRTLStatements.td index 10dd7941410d..9c79a665c2d4 100644 --- a/include/circt/Dialect/FIRRTL/FIRRTLStatements.td +++ b/include/circt/Dialect/FIRRTL/FIRRTLStatements.td @@ -110,13 +110,13 @@ def RefDefineOp : FIRRTLOp<"ref.define", [SameTypeOperands, FConnectLike]> { def PrintFOp : FIRRTLOp<"printf"> { let summary = "Formatted Print Statement"; - let arguments = (ins ClockType:$clock, UInt1Type:$cond, StrAttr:$formatString, + let arguments = (ins ClockType:$clock, UInt1Type:$cond, SInt32Type:$fd, StrAttr:$formatString, Variadic:$substitutions, StrAttr:$name); let results = (outs); let assemblyFormat = [{ - $clock `,` $cond `,` $formatString `` custom(attr-dict) ` ` - (`(` $substitutions^ `)`)? `:` type($clock) `,` type($cond) (`,` qualified(type($substitutions))^)? + $clock `,` $cond `,` $fd `,` $formatString `` custom(attr-dict) ` ` + (`(` $substitutions^ `)`)? `:` type($clock) `,` type($cond) `,` type($fd) (`,` qualified(type($substitutions))^)? }]; } diff --git a/include/circt/Dialect/FIRRTL/FIRRTLTypes.td b/include/circt/Dialect/FIRRTL/FIRRTLTypes.td index 97317a0232e8..b02ed281eca4 100644 --- a/include/circt/Dialect/FIRRTL/FIRRTLTypes.td +++ b/include/circt/Dialect/FIRRTL/FIRRTLTypes.td @@ -123,6 +123,11 @@ def UnsizedUIntType : "type_cast($_self).getWidth() == std::nullopt">, "uint with uninferred width", "::circt::firrtl::UIntType">; +class SizedSIntType : FIRRTLDialectType< + CPred<"type_isa($_self) && " + "type_cast($_self).getWidth() == " # width>, + width # "-bit uint", "::circt::firrtl::SIntType">; + class SizedUIntType : FIRRTLDialectType< CPred<"type_isa($_self) && " "type_cast($_self).getWidth() == " # width>, @@ -139,6 +144,8 @@ class NonConstSizedUIntType : BuildableType< "::circt::firrtl::UIntType::get($_builder.getContext(), " # width # ")">; +def SInt32Type : SizedSIntType<32>; + def UInt1Type : SizedUIntType<1>; def UInt2Type : SizedUIntType<2>; def UInt32Type : SizedUIntType<32>; diff --git a/include/circt/Dialect/FIRRTL/FIRRTLVisitors.h b/include/circt/Dialect/FIRRTL/FIRRTLVisitors.h index 45ce850b949b..b54d07a7e679 100644 --- a/include/circt/Dialect/FIRRTL/FIRRTLVisitors.h +++ b/include/circt/Dialect/FIRRTL/FIRRTLVisitors.h @@ -56,7 +56,7 @@ class ExprVisitor { LTLImplicationIntrinsicOp, LTLUntilIntrinsicOp, LTLEventuallyIntrinsicOp, LTLClockIntrinsicOp, LTLDisableIntrinsicOp, Mux2CellIntrinsicOp, Mux4CellIntrinsicOp, - HasBeenResetIntrinsicOp, + HasBeenResetIntrinsicOp, FOpenIntrinsicOp, FCloseIntrinsicOp, // Miscellaneous. BitsPrimOp, HeadPrimOp, MuxPrimOp, PadPrimOp, ShlPrimOp, ShrPrimOp, TailPrimOp, VerbatimExprOp, HWStructCastOp, BitCastOp, RefSendOp, @@ -187,6 +187,8 @@ class ExprVisitor { HANDLE(Mux4CellIntrinsicOp, Unhandled); HANDLE(Mux2CellIntrinsicOp, Unhandled); HANDLE(HasBeenResetIntrinsicOp, Unhandled); + HANDLE(FOpenIntrinsicOp, Unhandled); + HANDLE(FCloseIntrinsicOp, Unhandled); // Miscellaneous. HANDLE(BitsPrimOp, Unhandled); diff --git a/lib/Conversion/FIRRTLToHW/LowerToHW.cpp b/lib/Conversion/FIRRTLToHW/LowerToHW.cpp index fa4c0a318b0a..b7919ddb3495 100644 --- a/lib/Conversion/FIRRTLToHW/LowerToHW.cpp +++ b/lib/Conversion/FIRRTLToHW/LowerToHW.cpp @@ -1633,6 +1633,8 @@ struct FIRRTLLowering : public FIRRTLVisitor { LogicalResult visitStmt(VerifCoverIntrinsicOp op); LogicalResult visitExpr(HasBeenResetIntrinsicOp op); LogicalResult visitStmt(UnclockedAssumeIntrinsicOp op); + LogicalResult visitExpr(FOpenIntrinsicOp op); + LogicalResult visitExpr(FCloseIntrinsicOp op); // Other Operations LogicalResult visitExpr(BitsPrimOp op); @@ -4333,7 +4335,8 @@ LogicalResult FIRRTLLowering::visitStmt(RefReleaseInitialOp op) { LogicalResult FIRRTLLowering::visitStmt(PrintFOp op) { auto clock = getLoweredNonClockValue(op.getClock()); auto cond = getLoweredValue(op.getCond()); - if (!clock || !cond) + auto fd = getLoweredValue(op.getFd()); + if (!clock || !cond || !fd) return failure(); SmallVector operands; @@ -4358,9 +4361,7 @@ LogicalResult FIRRTLLowering::visitStmt(PrintFOp op) { ifCond = builder.createOrFold(ifCond, cond, true); addIfProceduralBlock(ifCond, [&]() { - // Emit the sv.fwrite, writing to stderr by default. - Value fdStderr = builder.create(APInt(32, 0x80000002)); - builder.create(fdStderr, op.getFormatString(), operands); + builder.create(fd, op.getFormatString(), operands); }); }); }); @@ -4669,6 +4670,26 @@ LogicalResult FIRRTLLowering::visitStmt(UnclockedAssumeIntrinsicOp op) { }); } +LogicalResult FIRRTLLowering::visitExpr(FOpenIntrinsicOp op) { + auto resultTy = lowerType(op.getType()); + if (!resultTy) + return failure(); + + auto filename = builder.create(op.getFilename()); + auto mode = builder.create(op.getMode()); + + return setLoweringTo( + op, resultTy, builder.getStringAttr("fopen"), ValueRange{filename, mode}); +} + +LogicalResult FIRRTLLowering::visitExpr(FCloseIntrinsicOp op) { + auto fd = getLoweredValue(op.getFd()); + auto result = builder.create( + NoneType::get(builder.getContext()), builder.getStringAttr("fclose"), + ValueRange{fd}); + return success(); +} + LogicalResult FIRRTLLowering::visitStmt(AttachOp op) { // Don't emit anything for a zero or one operand attach. if (op.getAttached().size() < 2) diff --git a/lib/Dialect/FIRRTL/Export/FIREmitter.cpp b/lib/Dialect/FIRRTL/Export/FIREmitter.cpp index 519766afe797..9dc17fc4cec3 100644 --- a/lib/Dialect/FIRRTL/Export/FIREmitter.cpp +++ b/lib/Dialect/FIRRTL/Export/FIREmitter.cpp @@ -781,6 +781,8 @@ void Emitter::emitStatement(PrintFOp op) { ps << "," << PP::space; emitExpression(op.getCond()); ps << "," << PP::space; + emitExpression(op.getFd()); + ps << "," << PP::space; ps.writeQuotedEscaped(op.getFormatString()); for (auto operand : op.getSubstitutions()) { ps << "," << PP::space; diff --git a/lib/Dialect/FIRRTL/FIRRTLIntrinsics.cpp b/lib/Dialect/FIRRTL/FIRRTLIntrinsics.cpp index c65cd88c3dde..d197fe2c80ee 100644 --- a/lib/Dialect/FIRRTL/FIRRTLIntrinsics.cpp +++ b/lib/Dialect/FIRRTL/FIRRTLIntrinsics.cpp @@ -638,6 +638,39 @@ class CirctUnclockedAssumeConverter : public IntrinsicConverter { } }; +class CirctFOpenConverter : public IntrinsicConverter { +public: + using IntrinsicConverter::IntrinsicConverter; + + bool check(GenericIntrinsic gi) override { + return gi.namedParam("filename") || gi.namedParam("mode") || + gi.hasNParam(2) || gi.sizedOutput(32); + } + + void convert(GenericIntrinsic gi, GenericIntrinsicOpAdaptor adaptor, + PatternRewriter &rewriter) override { + rewriter.replaceOpWithNewOp( + gi.op, gi.op.getResultTypes(), gi.getParamValue("filename"), + gi.getParamValue("mode")); + } +}; + +class CirctFCloseConverter : public IntrinsicConverter { +public: + using IntrinsicConverter::IntrinsicConverter; + + bool check(GenericIntrinsic gi) override { + return gi.hasNParam(0) || gi.hasNInputs(1) || + gi.sizedInput(0, 32); + } + + void convert(GenericIntrinsic gi, GenericIntrinsicOpAdaptor adaptor, + PatternRewriter &rewriter) override { + rewriter.replaceOpWithNewOp(gi.op, + adaptor.getOperands()[0]); + } +}; + } // namespace //===----------------------------------------------------------------------===// @@ -704,4 +737,6 @@ void FIRRTLIntrinsicLoweringDialectInterface::populateIntrinsicLowerings( lowering.add("circt.chisel_cover", "circt_chisel_cover"); lowering.add("circt.unclocked_assume", "circt_unclocked_assume"); + lowering.add("circt.fopen", "circt_fopen"); + lowering.add("circt.fclose", "circt_fclose"); } diff --git a/lib/Dialect/FIRRTL/Import/FIRParser.cpp b/lib/Dialect/FIRRTL/Import/FIRParser.cpp index 5268fdcfab33..832f431c11e2 100644 --- a/lib/Dialect/FIRRTL/Import/FIRParser.cpp +++ b/lib/Dialect/FIRRTL/Import/FIRParser.cpp @@ -2824,14 +2824,15 @@ ParseResult FIRStmtParser::parseMemPort(MemDirAttr direction) { return moduleContext.addSymbolEntry(id, memoryData, startLoc, true); } -/// printf ::= 'printf(' exp exp StringLit exp* ')' name? info? +/// printf ::= 'printf(' exp exp exp StringLit exp* ')' name? info? ParseResult FIRStmtParser::parsePrintf() { auto startTok = consumeToken(FIRToken::lp_printf); - Value clock, condition; + Value clock, condition, fd; StringRef formatString; if (parseExp(clock, "expected clock expression in printf") || parseExp(condition, "expected condition in printf") || + parseExp(fd, "expected fd expression in printf") || parseGetSpelling(formatString) || parseToken(FIRToken::string, "expected format string in printf")) return failure(); @@ -2853,7 +2854,7 @@ ParseResult FIRStmtParser::parsePrintf() { locationProcessor.setLoc(startTok.getLoc()); auto formatStrUnescaped = FIRToken::getStringValue(formatString); - builder.create(clock, condition, + builder.create(clock, condition, fd, builder.getStringAttr(formatStrUnescaped), operands, name); return success(); diff --git a/test/Conversion/FIRRTLToHW/intrinsics.mlir b/test/Conversion/FIRRTLToHW/intrinsics.mlir index 568ad3ea7a48..fe3330163794 100644 --- a/test/Conversion/FIRRTLToHW/intrinsics.mlir +++ b/test/Conversion/FIRRTLToHW/intrinsics.mlir @@ -40,6 +40,15 @@ firrtl.circuit "Intrinsics" { %6 = firrtl.int.isX %c : !firrtl.bundle, b: uint<3>> %x6 = firrtl.node interesting_name %6 : !firrtl.uint<1> + // CHECK-NEXT: [[filename:%.+]] = sv.constantStr "file.txt" + // CHECK-NEXT: [[mode:%.+]] = sv.constantStr "w" + // CHECK-NEXT: [[fd:%.+]] = sv.system "fopen"([[filename]], [[mode]]) : (!hw.string, !hw.string) -> i32 + // CHECK-NEXT: %x7 = hw.wire [[fd]] + %7 = firrtl.int.fopen "file.txt", "w" : !firrtl.sint<32> + %x7 = firrtl.node interesting_name %7 : !firrtl.sint<32> + + // CHECK-NEXT: sv.system "fclose"(%x7) : (i32) -> none + firrtl.int.fclose %x7 : !firrtl.sint<32> } // CHECK-LABEL: hw.module @ClockGate diff --git a/test/Conversion/FIRRTLToHW/lower-to-hw-module.mlir b/test/Conversion/FIRRTLToHW/lower-to-hw-module.mlir index 2e996313813a..d28e4007701c 100644 --- a/test/Conversion/FIRRTLToHW/lower-to-hw-module.mlir +++ b/test/Conversion/FIRRTLToHW/lower-to-hw-module.mlir @@ -51,11 +51,12 @@ firrtl.circuit "Simple" { in %clock: !firrtl.clock, in %reset: !firrtl.uint<1>) { // CHECK-NEXT: [[CLK:%.+]] = seq.from_clock %clock - // CHECK-NEXT: %c0_i2 = hw.constant + // CHECK-NEXT: [[fd:%.+]] = hw.constant -2147483646 : i32 + // CHECK-NEXT: [[c0_i2:%.+]] = hw.constant 0 : i2 // CHECK-NEXT: %xyz.out4 = hw.instance "xyz" @Simple(in1: [[ARG1:%.+]]: i4, in2: %u2: i2, in3: %s8: i8) -> (out4: i4) %xyz:4 = firrtl.instance xyz @Simple(in in1: !firrtl.uint<4>, in in2: !firrtl.uint<2>, in in3: !firrtl.sint<8>, out out4: !firrtl.uint<4>) - // CHECK: [[ARG1]] = comb.concat %c0_i2, %u2 : i2, i2 + // CHECK: [[ARG1]] = comb.concat [[c0_i2]], %u2 : i2, i2 firrtl.connect %xyz#0, %u2 : !firrtl.uint<4>, !firrtl.uint<2> // CHECK-NOT: hw.connect @@ -63,7 +64,9 @@ firrtl.circuit "Simple" { firrtl.connect %xyz#2, %s8 : !firrtl.sint<8>, !firrtl.sint<8> - firrtl.printf %clock, %reset, "%x"(%xyz#3) : !firrtl.clock, !firrtl.uint<1>, !firrtl.uint<4> + %fd = firrtl.constant 0x80000002 : !firrtl.sint<32> + + firrtl.printf %clock, %reset, %fd, "%x"(%xyz#3) : !firrtl.clock, !firrtl.uint<1>, !firrtl.sint<32>, !firrtl.uint<4> // Parameterized module reference. // hw.instance carries the parameters, unlike at the FIRRTL layer. @@ -71,13 +74,12 @@ firrtl.circuit "Simple" { // CHECK: %myext.out = hw.instance "myext" @MyParameterizedExtModule(in: %reset: i1) -> (out: i8) %myext:2 = firrtl.instance myext @MyParameterizedExtModule(in in: !firrtl.uint<1>, out out: !firrtl.uint<8>) - // CHECK: [[FD:%.*]] = hw.constant -2147483646 : i32 - // CHECK: sv.fwrite [[FD]], "%x"(%xyz.out4) : i4 - // CHECK: sv.fwrite [[FD]], "Something interesting! %x"(%myext.out) : i8 + // CHECK: sv.fwrite %c-2147483646_i32, "%x"(%xyz.out4) : i4 + // CHECK: sv.fwrite %c-2147483646_i32, "Something interesting! %x"(%myext.out) : i8 firrtl.connect %myext#0, %reset : !firrtl.uint<1>, !firrtl.uint<1> - firrtl.printf %clock, %reset, "Something interesting! %x"(%myext#1) : !firrtl.clock, !firrtl.uint<1>, !firrtl.uint<8> + firrtl.printf %clock, %reset, %fd, "Something interesting! %x"(%myext#1) : !firrtl.clock, !firrtl.uint<1>, !firrtl.sint<32>, !firrtl.uint<8> } // CHECK-LABEL: hw.module private @OutputFirst(out out4 : i4, in %in1 : i1, in %in4 : i4) { diff --git a/test/Conversion/FIRRTLToHW/lower-to-hw.mlir b/test/Conversion/FIRRTLToHW/lower-to-hw.mlir index 27b108d15421..85b0fc9d296b 100644 --- a/test/Conversion/FIRRTLToHW/lower-to-hw.mlir +++ b/test/Conversion/FIRRTLToHW/lower-to-hw.mlir @@ -331,8 +331,11 @@ firrtl.circuit "Simple" attributes {annotations = [{class = in %a: !firrtl.uint<4>, in %b: !firrtl.uint<4>, in %c: !firrtl.sint<4>, in %d: !firrtl.sint<4>) { // CHECK: [[CLOCK:%.+]] = seq.from_clock %clock + // CHECK: [[STDERR:%.+]] = hw.constant -2147483646 : i32 + // CHECK: [[FILENAME:%.+]] = sv.constantStr "file.txt" + // CHECK: [[MODE:%.+]] = sv.constantStr "a" + // CHECK: [[FILE:%.+]] = sv.system "fopen"([[FILENAME]], [[MODE]]) : (!hw.string, !hw.string) -> i32 // CHECK: [[ADD:%.+]] = comb.add - // CHECK: [[ADDSIGNED:%.+]] = comb.add // CHECK: [[SUMSIGNED:%.+]] = sv.system "signed"([[ADDSIGNED]]) // CHECK: [[DSIGNED:%.+]] = sv.system "signed"(%d) @@ -343,32 +346,38 @@ firrtl.circuit "Simple" attributes {annotations = [{class = // CHECK-NEXT: %PRINTF_COND_ = sv.macro.ref @PRINTF_COND_() : () -> i1 // CHECK-NEXT: [[AND:%.+]] = comb.and bin %PRINTF_COND_, %reset // CHECK-NEXT: sv.if [[AND]] { - // CHECK-NEXT: [[FD:%.+]] = hw.constant -2147483646 : i32 - // CHECK-NEXT: sv.fwrite [[FD]], "No operands!\0A" + // CHECK-NEXT: sv.fwrite [[STDERR]], "No operands!\0A" // CHECK-NEXT: } // CHECK-NEXT: %PRINTF_COND__0 = sv.macro.ref @PRINTF_COND_() : () -> i1 // CHECK-NEXT: [[AND:%.+]] = comb.and bin %PRINTF_COND__0, %reset : i1 // CHECK-NEXT: sv.if [[AND]] { - // CHECK-NEXT: [[FD:%.+]] = hw.constant -2147483646 : i32 - // CHECK-NEXT: sv.fwrite [[FD]], "Hi %x %x\0A"([[ADD]], %b) : i5, i4 + // CHECK-NEXT: sv.fwrite [[FILE]], "(File) No operands!\0A" // CHECK-NEXT: } // CHECK-NEXT: %PRINTF_COND__1 = sv.macro.ref @PRINTF_COND_() : () -> i1 // CHECK-NEXT: [[AND:%.+]] = comb.and bin %PRINTF_COND__1, %reset : i1 // CHECK-NEXT: sv.if [[AND]] { - // CHECK-NEXT: [[FD:%.+]] = hw.constant -2147483646 : i32 - // CHECK-NEXT: sv.fwrite [[FD]], "Hi signed %d %d\0A"([[SUMSIGNED]], [[DSIGNED]]) : i5, i4 + // CHECK-NEXT: sv.fwrite [[STDERR]], "Hi %x %x\0A"([[ADD]], %b) : i5, i4 + // CHECK-NEXT: } + // CHECK-NEXT: %PRINTF_COND__2 = sv.macro.ref @PRINTF_COND_() : () -> i1 + // CHECK-NEXT: [[AND:%.+]] = comb.and bin %PRINTF_COND__2, %reset : i1 + // CHECK-NEXT: sv.if [[AND]] { + // CHECK-NEXT: sv.fwrite [[STDERR]], "Hi signed %d %d\0A"([[SUMSIGNED]], [[DSIGNED]]) : i5, i4 // CHECK-NEXT: } // CHECK-NEXT: } // CHECK-NEXT: } - firrtl.printf %clock, %reset, "No operands!\0A" : !firrtl.clock, !firrtl.uint<1> + %stderr = firrtl.constant 0x80000002 : !firrtl.sint<32> + %file = firrtl.int.fopen "file.txt", "a" : !firrtl.sint<32> + + firrtl.printf %clock, %reset, %stderr, "No operands!\0A" : !firrtl.clock, !firrtl.uint<1>, !firrtl.sint<32> + firrtl.printf %clock, %reset, %file, "(File) No operands!\0A" : !firrtl.clock, !firrtl.uint<1>, !firrtl.sint<32> %0 = firrtl.add %a, %a : (!firrtl.uint<4>, !firrtl.uint<4>) -> !firrtl.uint<5> - firrtl.printf %clock, %reset, "Hi %x %x\0A"(%0, %b) : !firrtl.clock, !firrtl.uint<1>, !firrtl.uint<5>, !firrtl.uint<4> + firrtl.printf %clock, %reset, %stderr, "Hi %x %x\0A"(%0, %b) : !firrtl.clock, !firrtl.uint<1>, !firrtl.sint<32>, !firrtl.uint<5>, !firrtl.uint<4> %1 = firrtl.add %c, %c : (!firrtl.sint<4>, !firrtl.sint<4>) -> !firrtl.sint<5> - firrtl.printf %clock, %reset, "Hi signed %d %d\0A"(%1, %d) : !firrtl.clock, !firrtl.uint<1>, !firrtl.sint<5>, !firrtl.sint<4> + firrtl.printf %clock, %reset, %stderr, "Hi signed %d %d\0A"(%1, %d) : !firrtl.clock, !firrtl.uint<1>, !firrtl.sint<32>, !firrtl.sint<5>, !firrtl.sint<4> firrtl.skip diff --git a/test/Dialect/FIRRTL/SFCTests/complex-asserts.fir b/test/Dialect/FIRRTL/SFCTests/complex-asserts.fir index b7308ad88b82..c860838813d9 100644 --- a/test/Dialect/FIRRTL/SFCTests/complex-asserts.fir +++ b/test/Dialect/FIRRTL/SFCTests/complex-asserts.fir @@ -23,56 +23,57 @@ circuit Foo: input other : UInt<1> input sum : UInt<42> + node fd = SInt<32>(-2147483646) ; assert with predicate only ; expected-note @+2 {{example printf here, this is now just a printf and nothing more}} when not(or(predicate1, asUInt(reset))) : - printf(clock, enable, "foo [verif-library-assert]{\"predicateModifier\":{\"type\":\"noMod\"},\"format\":{\"type\":\"ifElseFatal\"},\"baseMsg\":\"Assertion failed (verification library): \"} bar") + printf(clock, enable, fd, "foo [verif-library-assert]{\"predicateModifier\":{\"type\":\"noMod\"},\"format\":{\"type\":\"ifElseFatal\"},\"baseMsg\":\"Assertion failed (verification library): \"} bar") stop(clock, enable, 1) ; assert with message when not(or(predicate2, asUInt(reset))) : - printf(clock, enable, "foo [verif-library-assert]{\"predicateModifier\":{\"type\":\"noMod\"},\"format\":{\"type\":\"ifElseFatal\"},\"baseMsg\":\"Assertion failed (verification library): sum =/= 1.U\"} bar") + printf(clock, enable, fd, "foo [verif-library-assert]{\"predicateModifier\":{\"type\":\"noMod\"},\"format\":{\"type\":\"ifElseFatal\"},\"baseMsg\":\"Assertion failed (verification library): sum =/= 1.U\"} bar") stop(clock, enable, 1) ; assert with when when other : when not(or(predicate3, asUInt(reset))) : - printf(clock, enable, "foo [verif-library-assert]{\"predicateModifier\":{\"type\":\"noMod\"},\"format\":{\"type\":\"ifElseFatal\"},\"baseMsg\":\"Assertion failed (verification library): Assert with when\"} bar") + printf(clock, enable, fd, "foo [verif-library-assert]{\"predicateModifier\":{\"type\":\"noMod\"},\"format\":{\"type\":\"ifElseFatal\"},\"baseMsg\":\"Assertion failed (verification library): Assert with when\"} bar") stop(clock, enable, 1) ; assert with message with arguments when not(or(predicate4, asUInt(reset))) : - printf(clock, enable, "foo [verif-library-assert]{\"predicateModifier\":{\"type\":\"noMod\"},\"format\":{\"type\":\"ifElseFatal\"},\"baseMsg\":\"Assertion failed (verification library): expected sum === 2.U but got %d\"} bar", sum) + printf(clock, enable, fd, "foo [verif-library-assert]{\"predicateModifier\":{\"type\":\"noMod\"},\"format\":{\"type\":\"ifElseFatal\"},\"baseMsg\":\"Assertion failed (verification library): expected sum === 2.U but got %d\"} bar", sum) stop(clock, enable, 1) ; assert emitted as SVA when not(or(predicate5, asUInt(reset))) : - printf(clock, enable, "foo [verif-library-assert]{\"predicateModifier\":{\"type\":\"noMod\"},\"format\":{\"type\":\"sva\"},\"baseMsg\":\"Assertion failed (verification library): SVA assert example, sum was %d\"} bar", sum) + printf(clock, enable, fd, "foo [verif-library-assert]{\"predicateModifier\":{\"type\":\"noMod\"},\"format\":{\"type\":\"sva\"},\"baseMsg\":\"Assertion failed (verification library): SVA assert example, sum was %d\"} bar", sum) stop(clock, enable, 1) ; assert with custom label when not(or(predicate6, asUInt(reset))) : - printf(clock, enable, "foo [verif-library-assert]{\"predicateModifier\":{\"type\":\"noMod\"},\"format\":{\"type\":\"sva\"},\"labelExts\":[\"hello\",\"world\"],\"baseMsg\":\"Assertion failed (verification library): Custom label example\"} bar") + printf(clock, enable, fd, "foo [verif-library-assert]{\"predicateModifier\":{\"type\":\"noMod\"},\"format\":{\"type\":\"sva\"},\"labelExts\":[\"hello\",\"world\"],\"baseMsg\":\"Assertion failed (verification library): Custom label example\"} bar") stop(clock, enable, 1) ; assert with predicate option for X-passing when not(predicate7) : - printf(clock, enable, "foo [verif-library-assert]{\"predicateModifier\":{\"type\":\"trueOrIsX\"},\"format\":{\"type\":\"sva\"},\"baseMsg\":\"Assertion failed (verification library): X-passing assert example\"} bar") + printf(clock, enable, fd, "foo [verif-library-assert]{\"predicateModifier\":{\"type\":\"trueOrIsX\"},\"format\":{\"type\":\"sva\"},\"baseMsg\":\"Assertion failed (verification library): X-passing assert example\"} bar") stop(clock, enable, 1) ; assert with toggle option e.g. UNROnly when not(or(predicate8, asUInt(reset))) : - printf(clock, enable, "foo [verif-library-assert]{\"predicateModifier\":{\"type\":\"noMod\"},\"conditionalCompileToggles\":[{\"type\":\"unrOnly\"}],\"format\":{\"type\":\"sva\"},\"baseMsg\":\"Assertion failed (verification library): Conditional compilation example for UNR-only assert\"} bar") + printf(clock, enable, fd, "foo [verif-library-assert]{\"predicateModifier\":{\"type\":\"noMod\"},\"conditionalCompileToggles\":[{\"type\":\"unrOnly\"}],\"format\":{\"type\":\"sva\"},\"baseMsg\":\"Assertion failed (verification library): Conditional compilation example for UNR-only assert\"} bar") stop(clock, enable, 1) ; if-else-fatal style assert with conditional compilation toggles when not(or(predicate9, asUInt(reset))) : - printf(clock, enable, "foo [verif-library-assert]{\"predicateModifier\":{\"type\":\"noMod\"},\"conditionalCompileToggles\":[{\"type\":\"unrOnly\"}],\"format\":{\"type\":\"ifElseFatal\"},\"baseMsg\":\"Assertion failed (verification library): Conditional compilation example with if-else-fatal style assert\"} bar") + printf(clock, enable, fd, "foo [verif-library-assert]{\"predicateModifier\":{\"type\":\"noMod\"},\"conditionalCompileToggles\":[{\"type\":\"unrOnly\"}],\"format\":{\"type\":\"ifElseFatal\"},\"baseMsg\":\"Assertion failed (verification library): Conditional compilation example with if-else-fatal style assert\"} bar") stop(clock, enable, 1) ; assert with multiple toggle options when not(or(predicate10, asUInt(reset))) : - printf(clock, enable, "foo [verif-library-assert]{\"predicateModifier\":{\"type\":\"noMod\"},\"conditionalCompileToggles\":[{\"type\":\"formalOnly\"},{\"type\":\"unrOnly\"}],\"format\":{\"type\":\"sva\"},\"baseMsg\":\"Assertion failed (verification library): Conditional compilation example for UNR-only and formal-only assert\"} bar") + printf(clock, enable, fd, "foo [verif-library-assert]{\"predicateModifier\":{\"type\":\"noMod\"},\"conditionalCompileToggles\":[{\"type\":\"formalOnly\"},{\"type\":\"unrOnly\"}],\"format\":{\"type\":\"sva\"},\"baseMsg\":\"Assertion failed (verification library): Conditional compilation example for UNR-only and formal-only assert\"} bar") stop(clock, enable, 1) diff --git a/test/Dialect/FIRRTL/SFCTests/complex-assumes.fir b/test/Dialect/FIRRTL/SFCTests/complex-assumes.fir index b639933c90d9..fb03f029e078 100644 --- a/test/Dialect/FIRRTL/SFCTests/complex-assumes.fir +++ b/test/Dialect/FIRRTL/SFCTests/complex-assumes.fir @@ -20,44 +20,46 @@ circuit Foo: input other : UInt<1> input sum : UInt<42> + node fd = SInt<32>(-2147483646) + ; assume with predicate only ; expected-note @+2 {{example printf here, this is now just a printf and nothing more}} when not(or(predicate1, asUInt(reset))) : - printf(clock, enable, "foo [verif-library-assume]{\"predicateModifier\":{\"type\":\"noMod\"},\"baseMsg\":\"Assumption does not hold (verification library): \"} bar") + printf(clock, enable, fd, "foo [verif-library-assume]{\"predicateModifier\":{\"type\":\"noMod\"},\"baseMsg\":\"Assumption does not hold (verification library): \"} bar") stop(clock, enable, 1) ; assume with message when not(or(predicate2, asUInt(reset))) : - printf(clock, enable, "foo [verif-library-assume]{\"predicateModifier\":{\"type\":\"noMod\"},\"baseMsg\":\"Assumption does not hold (verification library): sum =/= 1.U\"} bar") + printf(clock, enable, fd, "foo [verif-library-assume]{\"predicateModifier\":{\"type\":\"noMod\"},\"baseMsg\":\"Assumption does not hold (verification library): sum =/= 1.U\"} bar") stop(clock, enable, 1) ; assume with when when other : when not(or(predicate3, asUInt(reset))) : - printf(clock, enable, "foo [verif-library-assume]{\"predicateModifier\":{\"type\":\"noMod\"},\"baseMsg\":\"Assumption does not hold (verification library): assume with when\"} bar") + printf(clock, enable, fd, "foo [verif-library-assume]{\"predicateModifier\":{\"type\":\"noMod\"},\"baseMsg\":\"Assumption does not hold (verification library): assume with when\"} bar") stop(clock, enable, 1) ; assume with message with arguments when not(or(predicate4, asUInt(reset))) : - printf(clock, enable, "foo [verif-library-assume]{\"predicateModifier\":{\"type\":\"noMod\"},\"baseMsg\":\"Assumption does not hold (verification library): expected sum === 2.U but got %d\"} bar", sum) + printf(clock, enable, fd, "foo [verif-library-assume]{\"predicateModifier\":{\"type\":\"noMod\"},\"baseMsg\":\"Assumption does not hold (verification library): expected sum === 2.U but got %d\"} bar", sum) stop(clock, enable, 1) ; assume with custom label when not(or(predicate5, asUInt(reset))) : - printf(clock, enable, "foo [verif-library-assume]{\"predicateModifier\":{\"type\":\"noMod\"},\"labelExts\":[\"hello\",\"world\"],\"baseMsg\":\"Assumption does not hold (verification library): Custom label example\"} bar") + printf(clock, enable, fd, "foo [verif-library-assume]{\"predicateModifier\":{\"type\":\"noMod\"},\"labelExts\":[\"hello\",\"world\"],\"baseMsg\":\"Assumption does not hold (verification library): Custom label example\"} bar") stop(clock, enable, 1) ; assume with predicate option for X-passing when not(predicate6) : - printf(clock, enable, "foo [verif-library-assume]{\"predicateModifier\":{\"type\":\"trueOrIsX\"},\"baseMsg\":\"Assumption does not hold (verification library): X-passing assume example\"} bar") + printf(clock, enable, fd, "foo [verif-library-assume]{\"predicateModifier\":{\"type\":\"trueOrIsX\"},\"baseMsg\":\"Assumption does not hold (verification library): X-passing assume example\"} bar") stop(clock, enable, 1) ; assume with toggle option e.g. UNROnly when not(or(predicate7, asUInt(reset))) : - printf(clock, enable, "foo [verif-library-assume]{\"predicateModifier\":{\"type\":\"noMod\"},\"conditionalCompileToggles\":[{\"type\":\"unrOnly\"}],\"baseMsg\":\"Assumption does not hold (verification library): Conditional compilation example for UNR-only assume\"} bar") + printf(clock, enable, fd, "foo [verif-library-assume]{\"predicateModifier\":{\"type\":\"noMod\"},\"conditionalCompileToggles\":[{\"type\":\"unrOnly\"}],\"baseMsg\":\"Assumption does not hold (verification library): Conditional compilation example for UNR-only assume\"} bar") stop(clock, enable, 1) ; assume with multiple toggle options when not(or(predicate8, asUInt(reset))) : - printf(clock, enable, "foo [verif-library-assume]{\"predicateModifier\":{\"type\":\"noMod\"},\"conditionalCompileToggles\":[{\"type\":\"formalOnly\"},{\"type\":\"unrOnly\"}],\"baseMsg\":\"Assumption does not hold (verification library): Conditional compilation example for UNR-only and formal-only assume\"} bar") + printf(clock, enable, fd, "foo [verif-library-assume]{\"predicateModifier\":{\"type\":\"noMod\"},\"conditionalCompileToggles\":[{\"type\":\"formalOnly\"},{\"type\":\"unrOnly\"}],\"baseMsg\":\"Assumption does not hold (verification library): Conditional compilation example for UNR-only and formal-only assume\"} bar") stop(clock, enable, 1) diff --git a/test/Dialect/FIRRTL/canonicalization.mlir b/test/Dialect/FIRRTL/canonicalization.mlir index 448705a1211e..46819278dbcb 100644 --- a/test/Dialect/FIRRTL/canonicalization.mlir +++ b/test/Dialect/FIRRTL/canonicalization.mlir @@ -3562,6 +3562,8 @@ firrtl.module @Whens(in %clock: !firrtl.clock, in %a: !firrtl.uint<1>, in %reset %true = firrtl.constant 1: !firrtl.uint<1> %false = firrtl.constant 0: !firrtl.uint<1> + %fd = firrtl.constant -2 : !firrtl.sint<32> + // Erase empty whens. // CHECK-NOT: when %a firrtl.when %a : !firrtl.uint<1> { @@ -3570,24 +3572,25 @@ firrtl.module @Whens(in %clock: !firrtl.clock, in %a: !firrtl.uint<1>, in %reset } else { } // Erase an empty else block. - // CHECK: firrtl.when %reset : !firrtl.uint<1> { - // CHECK-NEXT: firrtl.printf %clock, %reset, "foo!" : !firrtl.clock, !firrtl.uint<1> + // CHECK: [[fd:%.+]] = firrtl.constant -2 : !firrtl.sint<32> + // CHECK-NEXT: firrtl.when %reset : !firrtl.uint<1> { + // CHECK-NEXT: firrtl.printf %clock, %reset, [[fd]], "foo!" : !firrtl.clock, !firrtl.uint<1>, !firrtl.sint<32> // CHECK-NEXT: } firrtl.when %reset : !firrtl.uint<1> { - firrtl.printf %clock, %reset, "foo!" : !firrtl.clock, !firrtl.uint<1> + firrtl.printf %clock, %reset, %fd, "foo!" : !firrtl.clock, !firrtl.uint<1>, !firrtl.sint<32> } else { } - // CHECK-NEXT: firrtl.printf %clock, %reset, "bar!" : !firrtl.clock, !firrtl.uint<1> + // CHECK-NEXT: firrtl.printf %clock, %reset, [[fd]], "bar!" : !firrtl.clock, !firrtl.uint<1>, !firrtl.sint<32> firrtl.when %false : !firrtl.uint<1> { } else { - firrtl.printf %clock, %reset, "bar!" : !firrtl.clock, !firrtl.uint<1> + firrtl.printf %clock, %reset, %fd, "bar!" : !firrtl.clock, !firrtl.uint<1>, !firrtl.sint<32> } // CHECK-NOT: firrtl.when firrtl.when %true : !firrtl.uint<1> { } else { - firrtl.printf %clock, %reset, "baz!" : !firrtl.clock, !firrtl.uint<1> + firrtl.printf %clock, %reset, %fd, "baz!" : !firrtl.clock, !firrtl.uint<1>, !firrtl.sint<32> } } diff --git a/test/Dialect/FIRRTL/emit-basic.mlir b/test/Dialect/FIRRTL/emit-basic.mlir index 78dd384b8d33..58ce98f0a5e0 100644 --- a/test/Dialect/FIRRTL/emit-basic.mlir +++ b/test/Dialect/FIRRTL/emit-basic.mlir @@ -114,8 +114,10 @@ firrtl.circuit "Foo" { firrtl.stop %someClock, %ui1, 42 {name = "foo"} : !firrtl.clock, !firrtl.uint<1> // CHECK: skip firrtl.skip - // CHECK: printf(someClock, ui1, "some\n magic\"stuff\"", ui1, someReset) : foo - firrtl.printf %someClock, %ui1, "some\n magic\"stuff\"" {name = "foo"} (%ui1, %someReset) : !firrtl.clock, !firrtl.uint<1>, !firrtl.uint<1>, !firrtl.reset + %fd = firrtl.constant 0x80000002 : !firrtl.sint<32> + // CHECK: printf(someClock, ui1, SInt<32>(-2147483646), "some\n magic\"stuff\"", ui1, + // CHECK: someReset) : foo + firrtl.printf %someClock, %ui1, %fd, "some\n magic\"stuff\"" {name = "foo"} (%ui1, %someReset) : !firrtl.clock, !firrtl.uint<1>, !firrtl.sint<32>, !firrtl.uint<1>, !firrtl.reset // CHECK: assert(someClock, ui1, ui1, "msg") : foo // CHECK: assume(someClock, ui1, ui1, "msg") : foo // CHECK: cover(someClock, ui1, ui1, "msg") : foo diff --git a/test/Dialect/FIRRTL/expand-whens.mlir b/test/Dialect/FIRRTL/expand-whens.mlir index 8d90c1e8a7e9..11512715dd13 100644 --- a/test/Dialect/FIRRTL/expand-whens.mlir +++ b/test/Dialect/FIRRTL/expand-whens.mlir @@ -36,15 +36,16 @@ firrtl.module @shadow_when(in %p : !firrtl.uint<1>) { // Test all simulation constructs firrtl.module @simulation(in %clock : !firrtl.clock, in %p : !firrtl.uint<1>, in %enable : !firrtl.uint<1>, in %reset : !firrtl.uint<1>) { + %fd = firrtl.constant -2 : !firrtl.sint<32> firrtl.when %p : !firrtl.uint<1> { - firrtl.printf %clock, %enable, "CIRCT Rocks!" : !firrtl.clock, !firrtl.uint<1> + firrtl.printf %clock, %enable, %fd, "CIRCT Rocks!" : !firrtl.clock, !firrtl.uint<1>, !firrtl.sint<32> firrtl.stop %clock, %enable, 0 : !firrtl.clock, !firrtl.uint<1> firrtl.assert %clock, %p, %enable, "" : !firrtl.clock, !firrtl.uint<1>, !firrtl.uint<1> firrtl.assume %clock, %p, %enable, "" : !firrtl.clock, !firrtl.uint<1>, !firrtl.uint<1> firrtl.cover %clock, %p, %enable, "" : !firrtl.clock, !firrtl.uint<1>, !firrtl.uint<1> firrtl.int.unclocked_assume %p, %enable, "" : !firrtl.uint<1>, !firrtl.uint<1> } else { - firrtl.printf %clock, %reset, "CIRCT Rocks!" : !firrtl.clock, !firrtl.uint<1> + firrtl.printf %clock, %reset, %fd, "CIRCT Rocks!" : !firrtl.clock, !firrtl.uint<1>, !firrtl.sint<32> firrtl.stop %clock, %enable, 1 : !firrtl.clock, !firrtl.uint<1> firrtl.assert %clock, %p, %enable, "" : !firrtl.clock, !firrtl.uint<1>, !firrtl.uint<1> firrtl.assume %clock, %p, %enable, "" : !firrtl.clock, !firrtl.uint<1>, !firrtl.uint<1> @@ -53,8 +54,9 @@ firrtl.module @simulation(in %clock : !firrtl.clock, in %p : !firrtl.uint<1>, in } } // CHECK-LABEL: firrtl.module @simulation(in %clock: !firrtl.clock, in %p: !firrtl.uint<1>, in %enable: !firrtl.uint<1>, in %reset: !firrtl.uint<1>) { +// CHECK-NEXT: [[fd:%.+]] = firrtl.constant -2 : !firrtl.sint<32> // CHECK-NEXT: %0 = firrtl.and %p, %enable : (!firrtl.uint<1>, !firrtl.uint<1>) -> !firrtl.uint<1> -// CHECK-NEXT: firrtl.printf %clock, %0, "CIRCT Rocks!" : !firrtl.clock, !firrtl.uint<1> +// CHECK-NEXT: firrtl.printf %clock, %0, [[fd]], "CIRCT Rocks!" : !firrtl.clock, !firrtl.uint<1>, !firrtl.sint<32> // CHECK-NEXT: %1 = firrtl.and %p, %enable : (!firrtl.uint<1>, !firrtl.uint<1>) -> !firrtl.uint<1> // CHECK-NEXT: firrtl.stop %clock, %1, 0 : !firrtl.clock, !firrtl.uint<1> // CHECK-NEXT: %2 = firrtl.and %p, %enable : (!firrtl.uint<1>, !firrtl.uint<1>) -> !firrtl.uint<1> @@ -67,7 +69,7 @@ firrtl.module @simulation(in %clock : !firrtl.clock, in %p : !firrtl.uint<1>, in // CHECK-NEXT: firrtl.int.unclocked_assume %p, %5, "" : !firrtl.uint<1>, !firrtl.uint<1> // CHECK-NEXT: %6 = firrtl.not %p : (!firrtl.uint<1>) -> !firrtl.uint<1> // CHECK-NEXT: %7 = firrtl.and %6, %reset : (!firrtl.uint<1>, !firrtl.uint<1>) -> !firrtl.uint<1> -// CHECK-NEXT: firrtl.printf %clock, %7, "CIRCT Rocks!" : !firrtl.clock, !firrtl.uint<1> +// CHECK-NEXT: firrtl.printf %clock, %7, [[fd]], "CIRCT Rocks!" : !firrtl.clock, !firrtl.uint<1>, !firrtl.sint<32> // CHECK-NEXT: %8 = firrtl.and %6, %enable : (!firrtl.uint<1>, !firrtl.uint<1>) -> !firrtl.uint<1> // CHECK-NEXT: firrtl.stop %clock, %8, 1 : !firrtl.clock, !firrtl.uint<1> // CHECK-NEXT: %9 = firrtl.and %6, %enable : (!firrtl.uint<1>, !firrtl.uint<1>) -> !firrtl.uint<1> @@ -85,14 +87,16 @@ firrtl.module @simulation(in %clock : !firrtl.clock, in %p : !firrtl.uint<1>, in firrtl.module @nested_whens(in %clock : !firrtl.clock, in %p0 : !firrtl.uint<1>, in %p1 : !firrtl.uint<1>, in %enable : !firrtl.uint<1>, in %reset : !firrtl.uint<1>) { firrtl.when %p0 : !firrtl.uint<1> { firrtl.when %p1 : !firrtl.uint<1> { - firrtl.printf %clock, %enable, "CIRCT Rocks!" : !firrtl.clock, !firrtl.uint<1> + %fd = firrtl.constant -2 : !firrtl.sint<32> + firrtl.printf %clock, %enable, %fd, "CIRCT Rocks!" : !firrtl.clock, !firrtl.uint<1>, !firrtl.sint<32> } } } // CHECK-LABEL: firrtl.module @nested_whens(in %clock: !firrtl.clock, in %p0: !firrtl.uint<1>, in %p1: !firrtl.uint<1>, in %enable: !firrtl.uint<1>, in %reset: !firrtl.uint<1>) { // CHECK-NEXT: %0 = firrtl.and %p0, %p1 : (!firrtl.uint<1>, !firrtl.uint<1>) -> !firrtl.uint<1> +// CHECK-NEXT: [[fd:%.+]] = firrtl.constant -2 : !firrtl.sint<32> // CHECK-NEXT: %1 = firrtl.and %0, %enable : (!firrtl.uint<1>, !firrtl.uint<1>) -> !firrtl.uint<1> -// CHECK-NEXT: firrtl.printf %clock, %1, "CIRCT Rocks!" : !firrtl.clock, !firrtl.uint<1> +// CHECK-NEXT: firrtl.printf %clock, %1, [[fd]], "CIRCT Rocks!" : !firrtl.clock, !firrtl.uint<1>, !firrtl.sint<32> // CHECK-NEXT: } diff --git a/test/Dialect/FIRRTL/imdce.mlir b/test/Dialect/FIRRTL/imdce.mlir index 5759b6075cf9..5339350c715b 100644 --- a/test/Dialect/FIRRTL/imdce.mlir +++ b/test/Dialect/FIRRTL/imdce.mlir @@ -323,7 +323,8 @@ firrtl.circuit "DeleteInstance" { %invalid_ui289 = firrtl.invalidvalue : !firrtl.uint<289> } firrtl.module private @SideEffect1(in %a: !firrtl.uint<1>, in %clock: !firrtl.clock) { - firrtl.printf %clock, %a, "foo" : !firrtl.clock, !firrtl.uint<1> + %fd = firrtl.constant -2 : !firrtl.sint<32> + firrtl.printf %clock, %a, %fd, "foo" : !firrtl.clock, !firrtl.uint<1>, !firrtl.sint<32> } firrtl.module private @SideEffect2(in %a: !firrtl.uint<1>, in %clock: !firrtl.clock) { %s1_a, %s1_clock = firrtl.instance s1 @SideEffect1(in a: !firrtl.uint<1>, in clock: !firrtl.clock) diff --git a/test/Dialect/FIRRTL/infer-widths.mlir b/test/Dialect/FIRRTL/infer-widths.mlir index addc24852f00..e8d49803eecc 100644 --- a/test/Dialect/FIRRTL/infer-widths.mlir +++ b/test/Dialect/FIRRTL/infer-widths.mlir @@ -456,7 +456,8 @@ firrtl.circuit "Foo" { // CHECK: %ui = firrtl.wire : !firrtl.uint<5> %ui = firrtl.wire : !firrtl.uint - firrtl.printf %clk, %false, "foo" : !firrtl.clock, !firrtl.uint<1> + %fd = firrtl.constant -2 : !firrtl.sint<32> + firrtl.printf %clk, %false, %fd, "foo" : !firrtl.clock, !firrtl.uint<1>, !firrtl.sint<32> firrtl.skip firrtl.stop %clk, %false, 0 : !firrtl.clock, !firrtl.uint<1> firrtl.when %a : !firrtl.uint<1> { diff --git a/test/Dialect/FIRRTL/lower-intrinsics.mlir b/test/Dialect/FIRRTL/lower-intrinsics.mlir index 301dd739cc25..6cbd6240781b 100644 --- a/test/Dialect/FIRRTL/lower-intrinsics.mlir +++ b/test/Dialect/FIRRTL/lower-intrinsics.mlir @@ -156,4 +156,10 @@ firrtl.circuit "Foo" { // CHECK-NEXT: firrtl.int.fpga_probe %clock, %data : !firrtl.uint<32> firrtl.int.generic "circt_fpga_probe" %data, %clock : (!firrtl.uint<32>, !firrtl.clock) -> () } + + // CHECK-LABEL: firrtl.module private @FOpenIntrinsicTest + firrtl.module private @FOpenIntrinsicTest() { + // CHECK-NEXT: firrtl.int.fopen "file.txt", "w" : !firrtl.sint<32> + %fd = firrtl.int.generic "circt_fopen" : () -> !firrtl.sint<32> + } } diff --git a/test/Dialect/FIRRTL/parse-basic.fir b/test/Dialect/FIRRTL/parse-basic.fir index e11929b8b8b1..3ec7a1ec0cd3 100644 --- a/test/Dialect/FIRRTL/parse-basic.fir +++ b/test/Dialect/FIRRTL/parse-basic.fir @@ -292,11 +292,13 @@ circuit MyModule : ; CHECK: firrtl.circuit "MyModule" { else : _t <= _t_2 - ; CHECK: firrtl.printf %clock, %reset, "Something interesting!\0A %x %x" (%_t, %_t_2) : !firrtl.clock, !firrtl.uint<1>, !firrtl.vector, 12>, !firrtl.vector, 12> - printf(clock, reset, "Something interesting!\n %x %x", _t, _t_2) + node fd = SInt<32>(-2147483646) - ; CHECK: firrtl.printf %clock, %reset, "Something interesting!\0A %x %x" {name = "printf_0"} (%_t, %_t_2) : !firrtl.clock, !firrtl.uint<1>, !firrtl.vector, 12>, !firrtl.vector, 12> - printf(clock, reset, "Something interesting!\n %x %x", _t, _t_2) : printf_0 + ; CHECK: firrtl.printf %clock, %reset, %fd, "Something interesting!\0A %x %x" (%_t, %_t_2) : !firrtl.clock, !firrtl.uint<1>, !firrtl.const.sint<32>, !firrtl.vector, 12>, !firrtl.vector, 12> + printf(clock, reset, fd, "Something interesting!\n %x %x", _t, _t_2) + + ; CHECK: firrtl.printf %clock, %reset, %fd, "Something interesting!\0A %x %x" {name = "printf_0"} (%_t, %_t_2) : !firrtl.clock, !firrtl.uint<1>, !firrtl.const.sint<32>, !firrtl.vector, 12>, !firrtl.vector, 12> + printf(clock, reset, fd, "Something interesting!\n %x %x", _t, _t_2) : printf_0 ; CHECK: firrtl.stop %clock, %reset, 42 : !firrtl.clock, !firrtl.uint<1> stop(clock, reset, 42) @@ -357,7 +359,7 @@ circuit MyModule : ; CHECK: firrtl.circuit "MyModule" { ; CHECK: %myext_in, %myext_out = firrtl.instance myext interesting_name @MyExtModule(in in: !firrtl.uint, out out: !firrtl.uint<8>) inst myext of MyExtModule myext.in <= i8 - printf(clock, reset, "Something interesting! %x", myext.out) + printf(clock, reset, fd, "Something interesting! %x", myext.out) ; CHECK: firrtl.when %reset : !firrtl.uint<1> { when reset : diff --git a/test/Dialect/FIRRTL/when-encoded-verif.fir b/test/Dialect/FIRRTL/when-encoded-verif.fir index 9faefb61f1cb..caa276833b3b 100644 --- a/test/Dialect/FIRRTL/when-encoded-verif.fir +++ b/test/Dialect/FIRRTL/when-encoded-verif.fir @@ -9,92 +9,94 @@ circuit WhenEncodedVerification: input not_reset: UInt<1> input value: UInt<42> + node fd = SInt<32>(-2147483646) + ; expected-note @+3 {{example printf here, this is now just a printf and nothing more}} ; rocket-chip properties when cond: - printf(clock, enable, "assert:foo 0", value) + printf(clock, enable, fd, "assert:foo 0", value) when cond: - printf(clock, enable, "assume:foo 1", value) + printf(clock, enable, fd, "assume:foo 1", value) when cond: - printf(clock, enable, "cover:foo 2", value) + printf(clock, enable, fd, "cover:foo 2", value) when cond: - printf(clock, enable, "assert:foo_0:", value) + printf(clock, enable, fd, "assert:foo_0:", value) when cond: - printf(clock, enable, "assume:foo_1:", value) + printf(clock, enable, fd, "assume:foo_1:", value) when cond: - printf(clock, enable, "cover:foo_2:", value) + printf(clock, enable, fd, "cover:foo_2:", value) when cond: - printf(clock, enable, "assert:custom label 0:foo 3", value) + printf(clock, enable, fd, "assert:custom label 0:foo 3", value) when cond: - printf(clock, enable, "assume:custom label 1:foo 4", value) + printf(clock, enable, fd, "assume:custom label 1:foo 4", value) when cond: - printf(clock, enable, "cover:custom label 2:foo 5", value) + printf(clock, enable, fd, "cover:custom label 2:foo 5", value) ; Optional `stop` with same clock and condition should be removed. when cond: - printf(clock, enable, "assert:without_stop") + printf(clock, enable, fd, "assert:without_stop") stop(clock, enable, 1) when cond: - printf(clock, enable, "assert:foo 6, %d", value, value) + printf(clock, enable, fd, "assert:foo 6, %d", value, value) ; AssertNotX -- usually `cond` only checks for not-in-reset, and `enable` is ; just set to 1; the actual check `^value !== 'x` is implicit. when cond: - printf(clock, enable, "assertNotX:%d:value must not be X!", value) + printf(clock, enable, fd, "assertNotX:%d:value must not be X!", value) ; Chisel built-in assertions when cond: - printf(clock, enable, "Assertion failed with value %d", value) + printf(clock, enable, fd, "Assertion failed with value %d", value) stop(clock, enable, 1) when cond: - printf(clock, enable, "Assertion failed: some message with value %d", value) + printf(clock, enable, fd, "Assertion failed: some message with value %d", value) stop(clock, enable, 1) ; Verification Library Assertions ; Predicate modifier `noMod` when cond: - printf(clock, enable, "Assertion failed: [verif-library-assert]{\"predicateModifier\":{\"type\":\"noMod\"},\"conditionalCompileToggles\":[{\"type\":\"unrOnly\"},{\"type\":\"formalOnly\"}],\"labelExts\":[\"label\",\"magic\"],\"format\":{\"type\":\"sva\"},\"baseMsg\":\"Hello Assert\"}", value) + printf(clock, enable, fd, "Assertion failed: [verif-library-assert]{\"predicateModifier\":{\"type\":\"noMod\"},\"conditionalCompileToggles\":[{\"type\":\"unrOnly\"},{\"type\":\"formalOnly\"}],\"labelExts\":[\"label\",\"magic\"],\"format\":{\"type\":\"sva\"},\"baseMsg\":\"Hello Assert\"}", value) stop(clock, enable, 1) ; Predicate modifier `trueOrIsX` when cond: - printf(clock, enable, "Assertion failed: [verif-library-assert]{\"predicateModifier\":{\"type\":\"trueOrIsX\"},\"conditionalCompileToggles\":[{\"type\":\"unrOnly\"},{\"type\":\"formalOnly\"}],\"labelExts\":[\"label\",\"magic\"],\"format\":{\"type\":\"sva\"},\"baseMsg\":\"Hello Assert\"}", value) + printf(clock, enable, fd, "Assertion failed: [verif-library-assert]{\"predicateModifier\":{\"type\":\"trueOrIsX\"},\"conditionalCompileToggles\":[{\"type\":\"unrOnly\"},{\"type\":\"formalOnly\"}],\"labelExts\":[\"label\",\"magic\"],\"format\":{\"type\":\"sva\"},\"baseMsg\":\"Hello Assert\"}", value) stop(clock, enable, 1) ; Verification Library Assumptions ; Predicate modifier `noMod` when cond: - printf(clock, enable, "Assumption failed: [verif-library-assume]{\"predicateModifier\":{\"type\":\"noMod\"},\"conditionalCompileToggles\":[{\"type\":\"unrOnly\"},{\"type\":\"formalOnly\"}],\"labelExts\":[\"label\",\"voodoo\"],\"baseMsg\":\"Hello Assume\"}", value) + printf(clock, enable, fd, "Assumption failed: [verif-library-assume]{\"predicateModifier\":{\"type\":\"noMod\"},\"conditionalCompileToggles\":[{\"type\":\"unrOnly\"},{\"type\":\"formalOnly\"}],\"labelExts\":[\"label\",\"voodoo\"],\"baseMsg\":\"Hello Assume\"}", value) stop(clock, enable, 1) ; Predicate modifier `trueOrIsX` when cond: - printf(clock, enable, "Assumption failed: [verif-library-assume]{\"predicateModifier\":{\"type\":\"trueOrIsX\"},\"conditionalCompileToggles\":[{\"type\":\"unrOnly\"},{\"type\":\"formalOnly\"}],\"labelExts\":[\"label\",\"voodoo\"],\"baseMsg\":\"Hello Assume\"}", value) + printf(clock, enable, fd, "Assumption failed: [verif-library-assume]{\"predicateModifier\":{\"type\":\"trueOrIsX\"},\"conditionalCompileToggles\":[{\"type\":\"unrOnly\"},{\"type\":\"formalOnly\"}],\"labelExts\":[\"label\",\"voodoo\"],\"baseMsg\":\"Hello Assume\"}", value) stop(clock, enable, 1) ; New flavor of when-encoded verification that also includes an assert assert(clock, cond, enable, "hello") node not_cond = eq(cond, UInt<1>(0)) when not_cond: - printf(clock, enable, "Assertion failed: hello") + printf(clock, enable, fd, "Assertion failed: hello") when not_reset: assert(clock, cond, enable, "hello outside reset") node not_cond2 = eq(cond, UInt<1>(0)) when not_cond2: - printf(clock, enable, "Assertion failed: hello outside reset") + printf(clock, enable, fd, "Assertion failed: hello outside reset") ; Check that the above doesn't error if the assert is a double user of the ; condition. @@ -102,14 +104,14 @@ circuit WhenEncodedVerification: assert(clock, UInt<1>(1), UInt<1>(1), "double user assert") node not_cond3 = eq(UInt<1>(1), UInt<1>(0)) when not_cond3: - printf(clock, UInt<1>(1), "Assertion failed: double user assert") + printf(clock, UInt<1>(1), fd, "Assertion failed: double user assert") when cond : - printf(clock, not(enable), "assert: bar") + printf(clock, not(enable), fd, "assert: bar") ; Verification Library Covers ; Predicate modifier `noMod` when not(cond): - printf(clock, enable, "Assertion failed: [verif-library-cover]{\"predicateModifier\":{\"type\":\"noMod\"},\"conditionalCompileToggles\":[{\"type\":\"unrOnly\"},{\"type\":\"formalOnly\"}],\"labelExts\":[\"cover\",\"label\"],\"format\":{\"type\":\"sva\"},\"baseMsg\":\"cover hello world\"}", value) + printf(clock, enable, fd, "Assertion failed: [verif-library-cover]{\"predicateModifier\":{\"type\":\"noMod\"},\"conditionalCompileToggles\":[{\"type\":\"unrOnly\"},{\"type\":\"formalOnly\"}],\"labelExts\":[\"cover\",\"label\"],\"format\":{\"type\":\"sva\"},\"baseMsg\":\"cover hello world\"}", value) assert(clock, cond, enable, "") diff --git a/test/firtool/fopen-fclose.fir b/test/firtool/fopen-fclose.fir new file mode 100644 index 000000000000..200db89f640f --- /dev/null +++ b/test/firtool/fopen-fclose.fir @@ -0,0 +1,27 @@ +; RUN: firtool %s --format=fir --ir-sv | FileCheck %s + +FIRRTL version 4.0.0 +circuit FOpenFCloseTest: + ; CHECK-LABEL: @FOpenFCloseTest + public module FOpenFCloseTest : + input clock : Clock + input cond : UInt<1> + input var : UInt<32> + node fd = intrinsic(circt_fopen : SInt<32>) + printf(clock, cond, fd, "test %d\n", var) + intrinsic(circt_fclose, fd) + + ; CHECK: [[filename:%.+]] = sv.constantStr "file.txt" + ; CHECK-NEXT: [[mode:%.+]] = sv.constantStr "a" + ; CHECK-NEXT: [[fd:%.+]] = sv.system "fopen"([[filename]], [[mode]]) {sv.namehint = "fd"} : (!hw.string, !hw.string) -> i32 + ; CHECK-NEXT: sv.ifdef @SYNTHESIS { + ; CHECK-NEXT: } else { + ; CHECK-NEXT: sv.always posedge %clock { + ; CHECK-NEXT: [[PRINTF_COND:%.+]] = sv.macro.ref @PRINTF_COND_() : () -> i1 + ; CHECK-NEXT: [[COND:%.+]] = comb.and bin [[PRINTF_COND]], %cond : i1 + ; CHECK-NEXT: sv.if [[COND]] { + ; CHECK-NEXT: sv.fwrite [[fd]], "test %d\0A"(%var) : i32 + ; CHECK-NEXT: } + ; CHECK-NEXT: } + ; CHECK-NEXT: } + ; CHECK-NEXT: sv.system "fclose"([[fd]]) : (i32) -> none \ No newline at end of file diff --git a/test/firtool/import-ref.fir b/test/firtool/import-ref.fir index f9ea6e0d2156..b0be00b26a01 100644 --- a/test/firtool/import-ref.fir +++ b/test/firtool/import-ref.fir @@ -17,7 +17,7 @@ circuit TestHarness: ; CHECK: fwrite ; CHECK-SAME: "%x", TestHarness.dut.`ref_DUT_read) - printf(clock, UInt<1>(1) "%x", read(dut.read)) + printf(clock, UInt<1>(1), SInt<32>(-2147483646) "%x", read(dut.read)) ; CHECK: initial ; CHECK: force TestHarness.dut.`ref_DUT_write = 32'hDEADBEEF; force_initial(dut.write, UInt<32>("hdeadbeef")) diff --git a/test/firtool/lower-layers2.fir b/test/firtool/lower-layers2.fir index f34cbc9b7a3a..83104648cb61 100644 --- a/test/firtool/lower-layers2.fir +++ b/test/firtool/lower-layers2.fir @@ -89,7 +89,7 @@ circuit TestHarness: connect b, dut.b layerblock Verification: - printf(clock, reset, "The last PC was: %x", read(dut.trace)) + printf(clock, reset, SInt<32>(-0h7FFFFFFE), "The last PC was: %x", read(dut.trace)) ; CHECK: // ----- 8< ----- FILE "layers_TestHarness_Verification.sv" ----- 8< ----- ; CHECK: `ifndef layers_TestHarness_Verification diff --git a/test/firtool/print.fir b/test/firtool/print.fir index 25a9d34a9580..145acd0fbd24 100644 --- a/test/firtool/print.fir +++ b/test/firtool/print.fir @@ -6,7 +6,7 @@ circuit PrintTest: input clock : Clock input cond : UInt<1> input var : UInt<32> - printf(clock, cond, "test %d\n", var) + printf(clock, cond, SInt<32>(-2147483646), "test %d\n", var) ; CHECK: sv.ifdef @SYNTHESIS { ; CHECK-NEXT: } else { diff --git a/test/firtool/stop.fir b/test/firtool/stop.fir index 17c3a1b2ea4c..63adbbaa2923 100644 --- a/test/firtool/stop.fir +++ b/test/firtool/stop.fir @@ -26,6 +26,6 @@ circuit StopAndFinishTest: ; CHECK: } ; CHECK: } - printf(clock, cond, "Stop message") + printf(clock, cond, SInt<32>(-2147483646), "Stop message") stop(clock, cond, 0) stop(clock, cond, 1)