diff --git a/lib/Conversion/FIRRTLToHW/LowerToHW.cpp b/lib/Conversion/FIRRTLToHW/LowerToHW.cpp index 024c7d0175c2..af0e5f7c4805 100644 --- a/lib/Conversion/FIRRTLToHW/LowerToHW.cpp +++ b/lib/Conversion/FIRRTLToHW/LowerToHW.cpp @@ -5462,8 +5462,28 @@ 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(); + + sim::TriggeredOp::create(builder, clock, cond, [&] { + auto fileOp = sim::GetFileOp::create(builder, *fileFormatString); + sim::PrintFormattedProcOp::create(builder, *formatString, fileOp); + }); + 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..2dabbd31559b 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,14 @@ circuit LowerToCore: ; CHECK: sim.triggered %clock if %enable { ; CHECK-NEXT: sim.proc.print [[MSG]] ; CHECK-NEXT: } +; 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