Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions include/circt/Dialect/FIRRTL/FIRRTLIntrinsics.td
Original file line number Diff line number Diff line change
Expand Up @@ -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
//===----------------------------------------------------------------------===//
Expand Down
6 changes: 3 additions & 3 deletions include/circt/Dialect/FIRRTL/FIRRTLStatements.td
Original file line number Diff line number Diff line change
Expand Up @@ -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<FIRRTLBaseType>:$substitutions, StrAttr:$name);
let results = (outs);

let assemblyFormat = [{
$clock `,` $cond `,` $formatString `` custom<PrintfAttrs>(attr-dict) ` `
(`(` $substitutions^ `)`)? `:` type($clock) `,` type($cond) (`,` qualified(type($substitutions))^)?
$clock `,` $cond `,` $fd `,` $formatString `` custom<PrintfAttrs>(attr-dict) ` `
(`(` $substitutions^ `)`)? `:` type($clock) `,` type($cond) `,` type($fd) (`,` qualified(type($substitutions))^)?
}];
}

Expand Down
7 changes: 7 additions & 0 deletions include/circt/Dialect/FIRRTL/FIRRTLTypes.td
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,11 @@ def UnsizedUIntType :
"type_cast<UIntType>($_self).getWidth() == std::nullopt">,
"uint with uninferred width", "::circt::firrtl::UIntType">;

class SizedSIntType<int width> : FIRRTLDialectType<
CPred<"type_isa<SIntType>($_self) && "
"type_cast<SIntType>($_self).getWidth() == " # width>,
width # "-bit uint", "::circt::firrtl::SIntType">;

class SizedUIntType<int width> : FIRRTLDialectType<
CPred<"type_isa<UIntType>($_self) && "
"type_cast<UIntType>($_self).getWidth() == " # width>,
Expand All @@ -139,6 +144,8 @@ class NonConstSizedUIntType<int width> :
BuildableType<
"::circt::firrtl::UIntType::get($_builder.getContext(), " # width # ")">;

def SInt32Type : SizedSIntType<32>;

def UInt1Type : SizedUIntType<1>;
def UInt2Type : SizedUIntType<2>;
def UInt32Type : SizedUIntType<32>;
Expand Down
4 changes: 3 additions & 1 deletion include/circt/Dialect/FIRRTL/FIRRTLVisitors.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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);
Expand Down
29 changes: 25 additions & 4 deletions lib/Conversion/FIRRTLToHW/LowerToHW.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1633,6 +1633,8 @@ struct FIRRTLLowering : public FIRRTLVisitor<FIRRTLLowering, LogicalResult> {
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);
Expand Down Expand Up @@ -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<Value, 4> operands;
Expand All @@ -4358,9 +4361,7 @@ LogicalResult FIRRTLLowering::visitStmt(PrintFOp op) {
ifCond = builder.createOrFold<comb::AndOp>(ifCond, cond, true);

addIfProceduralBlock(ifCond, [&]() {
// Emit the sv.fwrite, writing to stderr by default.
Value fdStderr = builder.create<hw::ConstantOp>(APInt(32, 0x80000002));
builder.create<sv::FWriteOp>(fdStderr, op.getFormatString(), operands);
builder.create<sv::FWriteOp>(fd, op.getFormatString(), operands);
});
});
});
Expand Down Expand Up @@ -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<sv::ConstantStrOp>(op.getFilename());
auto mode = builder.create<sv::ConstantStrOp>(op.getMode());

return setLoweringTo<sv::SystemFunctionOp>(
op, resultTy, builder.getStringAttr("fopen"), ValueRange{filename, mode});
Comment on lines +4681 to +4682
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$fopen is task so you cannot put this into non-procedural region. Please put this to initial block and assign return value to a register.

}

LogicalResult FIRRTLLowering::visitExpr(FCloseIntrinsicOp op) {
auto fd = getLoweredValue(op.getFd());
auto result = builder.create<sv::SystemFunctionOp>(
NoneType::get(builder.getContext()), builder.getStringAttr("fclose"),
ValueRange{fd});
return success();
Comment on lines +4687 to +4690
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This also needs to be in a procedural region. I noticed currently there is no support for final statement. That seems reasonable addition to SV dialect.

}

LogicalResult FIRRTLLowering::visitStmt(AttachOp op) {
// Don't emit anything for a zero or one operand attach.
if (op.getAttached().size() < 2)
Expand Down
2 changes: 2 additions & 0 deletions lib/Dialect/FIRRTL/Export/FIREmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
35 changes: 35 additions & 0 deletions lib/Dialect/FIRRTL/FIRRTLIntrinsics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<SIntType>(32);
}

void convert(GenericIntrinsic gi, GenericIntrinsicOpAdaptor adaptor,
PatternRewriter &rewriter) override {
rewriter.replaceOpWithNewOp<FOpenIntrinsicOp>(
gi.op, gi.op.getResultTypes(), gi.getParamValue<StringAttr>("filename"),
gi.getParamValue<StringAttr>("mode"));
}
};

class CirctFCloseConverter : public IntrinsicConverter {
public:
using IntrinsicConverter::IntrinsicConverter;

bool check(GenericIntrinsic gi) override {
return gi.hasNParam(0) || gi.hasNInputs(1) ||
gi.sizedInput<SIntType>(0, 32);
}

void convert(GenericIntrinsic gi, GenericIntrinsicOpAdaptor adaptor,
PatternRewriter &rewriter) override {
rewriter.replaceOpWithNewOp<FCloseIntrinsicOp>(gi.op,
adaptor.getOperands()[0]);
}
};

} // namespace

//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -704,4 +737,6 @@ void FIRRTLIntrinsicLoweringDialectInterface::populateIntrinsicLowerings(
lowering.add<CirctCoverConverter>("circt.chisel_cover", "circt_chisel_cover");
lowering.add<CirctUnclockedAssumeConverter>("circt.unclocked_assume",
"circt_unclocked_assume");
lowering.add<CirctFOpenConverter>("circt.fopen", "circt_fopen");
lowering.add<CirctFCloseConverter>("circt.fclose", "circt_fclose");
}
7 changes: 4 additions & 3 deletions lib/Dialect/FIRRTL/Import/FIRParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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") ||
Copy link
Copy Markdown
Member

@uenoku uenoku Jun 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It 's necessary to accept old syntal. Please add a condition for FIRRTL-spec version.

parseGetSpelling(formatString) ||
parseToken(FIRToken::string, "expected format string in printf"))
return failure();
Expand All @@ -2853,7 +2854,7 @@ ParseResult FIRStmtParser::parsePrintf() {
locationProcessor.setLoc(startTok.getLoc());

auto formatStrUnescaped = FIRToken::getStringValue(formatString);
builder.create<PrintFOp>(clock, condition,
builder.create<PrintFOp>(clock, condition, fd,
builder.getStringAttr(formatStrUnescaped), operands,
name);
return success();
Expand Down
9 changes: 9 additions & 0 deletions test/Conversion/FIRRTLToHW/intrinsics.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,15 @@ firrtl.circuit "Intrinsics" {
%6 = firrtl.int.isX %c : !firrtl.bundle<a: uint<3>, 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
Expand Down
16 changes: 9 additions & 7 deletions test/Conversion/FIRRTLToHW/lower-to-hw-module.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -51,33 +51,35 @@ 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
firrtl.connect %xyz#1, %u2 : !firrtl.uint<2>, !firrtl.uint<2>

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.

// CHECK: %myext.out = hw.instance "myext" @MyParameterizedExtModule<DEFAULT: i64 = 0, DEPTH: f64 = 3.242000e+01, FORMAT: none = "xyz_timeout=%d\0A", WIDTH: i8 = 32>(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) {
Expand Down
29 changes: 19 additions & 10 deletions test/Conversion/FIRRTLToHW/lower-to-hw.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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

Expand Down
Loading