From 902a09ea80b5d0e7a0062dcbae1f7ed4e13578be Mon Sep 17 00:00:00 2001 From: woshiren Date: Wed, 13 May 2026 23:16:25 +0800 Subject: [PATCH 1/4] [LowerToHW] Add support for lower-to-core in firrtl.fprintf --- lib/Conversion/FIRRTLToHW/LowerToHW.cpp | 26 +++++++++++++++++-- .../FIRRTLToHW/lower-to-core-errors.mlir | 14 ---------- test/Conversion/FIRRTLToHW/lower-to-core.mlir | 21 +++++++++++++++ test/firtool/lower-to-core.fir | 17 +++++++++++- 4 files changed, 61 insertions(+), 17 deletions(-) diff --git a/lib/Conversion/FIRRTLToHW/LowerToHW.cpp b/lib/Conversion/FIRRTLToHW/LowerToHW.cpp index 024c7d0175c2..efc2c270cc6d 100644 --- a/lib/Conversion/FIRRTLToHW/LowerToHW.cpp +++ b/lib/Conversion/FIRRTLToHW/LowerToHW.cpp @@ -5462,8 +5462,30 @@ LogicalResult FIRRTLLowering::visitStmt(PrintFOp op) { } LogicalResult FIRRTLLowering::visitStmt(FPrintFOp op) { - if (circuitState.lowerToCore) - return op.emitOpError("lower-to-core does not support firrtl.fprintf yet"); + if (circuitState.lowerToCore) { + auto clock = getLoweredValue(op.getClock()); + auto cond = getLoweredValue(op.getCond()); + if (!clock || !cond) + return failure(); + + auto fileFormatString = lowerSimFormatString( + op.getOutputFileAttr(), op.getOutputFileSubstitutions()); + if (failed(fileFormatString)) + return failure(); + + auto formatString = + lowerSimFormatString(op.getFormatString(), op.getSubstitutions()); + if (failed(formatString)) + return failure(); + + OpBuilder::InsertionGuard guard(builder); + auto triggeredOp = sim::TriggeredOp::create(builder, clock, cond); + builder.setInsertionPointToStart(triggeredOp.getBodyBlock()); + auto fileOp = sim::GetFileOp::create(builder, *fileFormatString); + sim::PrintFormattedProcOp::create(builder, *formatString, + fileOp->getResult(0)); + return success(); + } StringAttr outputFileAttr; if (failed(resolveFormatString(op.getLoc(), op.getOutputFileAttr(), diff --git a/test/Conversion/FIRRTLToHW/lower-to-core-errors.mlir b/test/Conversion/FIRRTLToHW/lower-to-core-errors.mlir index f575989079f0..f323ac6b0f54 100644 --- a/test/Conversion/FIRRTLToHW/lower-to-core-errors.mlir +++ b/test/Conversion/FIRRTLToHW/lower-to-core-errors.mlir @@ -15,20 +15,6 @@ firrtl.circuit "time_printf" { // ----- -firrtl.circuit "fprintf_unsupported" { - firrtl.module @fprintf_unsupported( - in %clock: !firrtl.clock, - in %enable: !firrtl.uint<1>) { - // expected-error @+2 {{'firrtl.fprintf' op lower-to-core does not support firrtl.fprintf yet}} - // expected-error @below {{'firrtl.fprintf' op LowerToHW couldn't handle this operation}} - firrtl.fprintf %clock, %enable, "out.txt"(), "msg\0A"() - : !firrtl.clock, !firrtl.uint<1> - firrtl.skip - } -} - -// ----- - firrtl.circuit "fflush_unsupported" { firrtl.module @fflush_unsupported( in %clock: !firrtl.clock, diff --git a/test/Conversion/FIRRTLToHW/lower-to-core.mlir b/test/Conversion/FIRRTLToHW/lower-to-core.mlir index e9862b5e862c..224c27141bdc 100644 --- a/test/Conversion/FIRRTLToHW/lower-to-core.mlir +++ b/test/Conversion/FIRRTLToHW/lower-to-core.mlir @@ -30,6 +30,27 @@ firrtl.circuit "LowerToCore" { firrtl.printf %clock, %enable, "value=%d @ {{}}\0A"(%x, %hier) : !firrtl.clock, !firrtl.uint<1>, !firrtl.sint<4>, !firrtl.fstring + // CHECK: [[FMTFILE1:%.+]] = sim.fmt.literal "out.txt" + // CHECK: [[MSG:%.+]] = sim.fmt.concat + // CHECK: sim.triggered %clock if %enable { + // CHECK-NEXT: [[FILE1:%.+]] = sim.get_file [[FMTFILE1]] + // CHECK-NEXT: sim.proc.print [[MSG]] to [[FILE1]] + // CHECK-NEXT: } + firrtl.fprintf %clock, %enable, "out.txt"(), "value=%d @ {{}}\0A"(%x, %hier) + : !firrtl.clock, !firrtl.uint<1>, !firrtl.sint<4>, !firrtl.fstring + + // CHECK: [[LIT2:%.+]] = sim.fmt.literal "out" + // CHECK: [[FILEVAL:%.+]] = sim.fmt.dec %x signed : i4 + // CHECK: [[LIT3:%.+]] = sim.fmt.literal ".txt" + // CHECK: [[FMTFILE2:%.+]] = sim.fmt.concat ([[LIT2]], [[FILEVAL]], [[LIT3]]) + // CHECK: [[MSG:%.+]] = sim.fmt.concat + // CHECK: sim.triggered %clock if %enable { + // CHECK-NEXT: [[FILE2:%.+]] = sim.get_file [[FMTFILE2]] + // CHECK-NEXT: sim.proc.print [[MSG]] to [[FILE2]] + // CHECK-NEXT: } + firrtl.fprintf %clock, %enable, "out%d.txt"(%x), "value=%d @ {{}}\0A"(%x, %hier) + : !firrtl.clock, !firrtl.uint<1>, !firrtl.sint<4>, !firrtl.sint<4>, !firrtl.fstring + firrtl.skip } diff --git a/test/firtool/lower-to-core.fir b/test/firtool/lower-to-core.fir index e91407a89306..4a641d6e12e4 100644 --- a/test/firtool/lower-to-core.fir +++ b/test/firtool/lower-to-core.fir @@ -1,5 +1,5 @@ ; RUN: firtool --ir-hw --lower-to-core %s | FileCheck %s -FIRRTL version 4.0.0 +FIRRTL version 6.0.0 circuit LowerToCore: public module LowerToCore: @@ -10,8 +10,13 @@ circuit LowerToCore: assert(clock, pred, enable, "assert failed") printf(clock, enable, "value=%d\n", x) + fprintf(clock, enable, "out.txt", "value=%d\n", x) + fprintf(clock, enable, "out%d.txt", x, "value=%d\n", x) ; CHECK-LABEL: hw.module @LowerToCore +; CHECK-DAG: [[LITFILE1:%.+]] = sim.fmt.literal "out" +; CHECK-DAG: [[LITFILE2:%.+]] = sim.fmt.literal ".txt" +; CHECK-DAG: [[FMTFILE1:%.+]] = sim.fmt.literal "out.txt" ; CHECK-DAG: [[NL:%.+]] = sim.fmt.literal "\0A" ; CHECK-DAG: [[LIT:%.+]] = sim.fmt.literal "value=" ; CHECK-DAG: [[CLK:%.+]] = seq.from_clock %clock @@ -21,5 +26,15 @@ circuit LowerToCore: ; CHECK: sim.triggered %clock if %enable { ; CHECK-NEXT: sim.proc.print [[MSG]] ; CHECK-NEXT: } +; CHECK: sim.print [[MSG]] on %clock if %enable +; CHECK: sim.triggered %clock if %enable { +; CHECK-NEXT: [[FILE1:%.+]] = sim.get_file [[FMTFILE1]] +; CHECK-NEXT: sim.proc.print [[MSG]] to [[FILE1]] +; CHECK-NEXT: } +; CHECK: [[FMTFILE2:%.+]] = sim.fmt.concat ([[LITFILE1]], [[FMT]], [[LITFILE2]]) +; CHECK: sim.triggered %clock if %enable { +; CHECK-NEXT: [[FILE2:%.+]] = sim.get_file [[FMTFILE2]] +; CHECK-NEXT: sim.proc.print [[MSG]] to [[FILE2]] +; CHECK-NEXT: } ; CHECK-NOT: sv.assert ; CHECK-NOT: sv.fwrite From d81065f940cb873b5931dba2bd75142a5ecf9ae2 Mon Sep 17 00:00:00 2001 From: woshiren Date: Fri, 15 May 2026 16:34:40 +0800 Subject: [PATCH 2/4] fix tests --- test/firtool/lower-to-core.fir | 1 - 1 file changed, 1 deletion(-) diff --git a/test/firtool/lower-to-core.fir b/test/firtool/lower-to-core.fir index 4a641d6e12e4..2dabbd31559b 100644 --- a/test/firtool/lower-to-core.fir +++ b/test/firtool/lower-to-core.fir @@ -26,7 +26,6 @@ circuit LowerToCore: ; CHECK: sim.triggered %clock if %enable { ; CHECK-NEXT: sim.proc.print [[MSG]] ; CHECK-NEXT: } -; CHECK: sim.print [[MSG]] on %clock if %enable ; CHECK: sim.triggered %clock if %enable { ; CHECK-NEXT: [[FILE1:%.+]] = sim.get_file [[FMTFILE1]] ; CHECK-NEXT: sim.proc.print [[MSG]] to [[FILE1]] From 2f644dadb9b83fdaad69d61a1c5fd4ef1aa0f33c Mon Sep 17 00:00:00 2001 From: woshiren Date: Fri, 15 May 2026 17:19:18 +0800 Subject: [PATCH 3/4] use new builder --- lib/Conversion/FIRRTLToHW/LowerToHW.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/Conversion/FIRRTLToHW/LowerToHW.cpp b/lib/Conversion/FIRRTLToHW/LowerToHW.cpp index efc2c270cc6d..8810eb453149 100644 --- a/lib/Conversion/FIRRTLToHW/LowerToHW.cpp +++ b/lib/Conversion/FIRRTLToHW/LowerToHW.cpp @@ -5478,12 +5478,11 @@ LogicalResult FIRRTLLowering::visitStmt(FPrintFOp op) { if (failed(formatString)) return failure(); - OpBuilder::InsertionGuard guard(builder); - auto triggeredOp = sim::TriggeredOp::create(builder, clock, cond); - builder.setInsertionPointToStart(triggeredOp.getBodyBlock()); - auto fileOp = sim::GetFileOp::create(builder, *fileFormatString); - sim::PrintFormattedProcOp::create(builder, *formatString, - fileOp->getResult(0)); + sim::TriggeredOp::create(builder, clock, cond, [&] { + auto fileOp = sim::GetFileOp::create(builder, *fileFormatString); + sim::PrintFormattedProcOp::create(builder, *formatString, + fileOp->getResult(0)); + }); return success(); } From 2a25f87114b04b97d7ad396fcbff8b6014d4f34b Mon Sep 17 00:00:00 2001 From: woshiren Date: Mon, 25 May 2026 13:19:37 +0800 Subject: [PATCH 4/4] fix nit --- lib/Conversion/FIRRTLToHW/LowerToHW.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/Conversion/FIRRTLToHW/LowerToHW.cpp b/lib/Conversion/FIRRTLToHW/LowerToHW.cpp index 8810eb453149..af0e5f7c4805 100644 --- a/lib/Conversion/FIRRTLToHW/LowerToHW.cpp +++ b/lib/Conversion/FIRRTLToHW/LowerToHW.cpp @@ -5480,8 +5480,7 @@ LogicalResult FIRRTLLowering::visitStmt(FPrintFOp op) { sim::TriggeredOp::create(builder, clock, cond, [&] { auto fileOp = sim::GetFileOp::create(builder, *fileFormatString); - sim::PrintFormattedProcOp::create(builder, *formatString, - fileOp->getResult(0)); + sim::PrintFormattedProcOp::create(builder, *formatString, fileOp); }); return success(); }