Skip to content
Draft
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
17 changes: 17 additions & 0 deletions include/circt/Dialect/Moore/MooreOps.td
Original file line number Diff line number Diff line change
Expand Up @@ -3039,6 +3039,23 @@ def DisplayBIOp : Builtin<"display"> {
let assemblyFormat = "$message attr-dict";
}

def StrobeBIOp : Builtin<"strobe"> {
let summary = "Display formatted values at end of simulation timestep";
let description = [{
Schedules a display of the formatted message in the Postponed region of the
current simulation time, after all Active and NBA updates have settled.
The format string is evaluated at the time the body execute,
not at the time `$strobe` is called.
Corresponds to `$strobe[boh]` system task.
Message formatting is handled by `moore.fmt.*` ops.

See IEEE 1800-2017 § 21.2.2 "Strobed monitoring".
}];
let arguments = (ins FormatStringType:$message);
let results = (outs);
let assemblyFormat = "$message attr-dict";
}

def SeverityInfo : I32EnumAttrCase<"Info", 0, "info">;
def SeverityWarning : I32EnumAttrCase<"Warning", 1, "warning">;
def SeverityError : I32EnumAttrCase<"Error", 2, "error">;
Expand Down
11 changes: 11 additions & 0 deletions include/circt/Dialect/SV/SVStatements.td
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,17 @@ def WriteOp : SVOp<"write", [ProceduralOp]> {
}];
}

def StrobeOp : SVOp<"strobe", [ProceduralOp]> {
let summary = "'$strobe' statement";
let arguments = (ins StrAttr:$format_string,
Variadic<AnyType>:$substitutions);
let results = (outs);
let assemblyFormat = [{
$format_string attr-dict (`(` $substitutions^ `)` `:`
qualified(type($substitutions)))?
}];
}

def FWriteOp : SVOp<"fwrite", [ProceduralOp]> {
let summary = "'$fwrite' statement";

Expand Down
3 changes: 2 additions & 1 deletion include/circt/Dialect/SV/SVVisitors.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class Visitor {
AlwaysCombOp, AlwaysFFOp, InitialOp, CaseOp,
// Other Statements.
AssignOp, BPAssignOp, PAssignOp, ForceOp, ReleaseOp, AliasOp,
WriteOp, FWriteOp, FFlushOp, SystemFunctionOp, VerbatimOp,
WriteOp, StrobeOp, FWriteOp, FFlushOp, SystemFunctionOp, VerbatimOp,
MacroRefOp, FuncCallOp, FuncCallProceduralOp, ReturnOp, IncludeOp,
MacroErrorOp,
// Type declarations.
Expand Down Expand Up @@ -137,6 +137,7 @@ class Visitor {
HANDLE(ReleaseOp, Unhandled);
HANDLE(AliasOp, Unhandled);
HANDLE(WriteOp, Unhandled);
HANDLE(StrobeOp, Unhandled);
HANDLE(FWriteOp, Unhandled);
HANDLE(FFlushOp, Unhandled);
HANDLE(SystemFunctionOp, Unhandled);
Expand Down
14 changes: 14 additions & 0 deletions include/circt/Dialect/Sim/SimOps.td
Original file line number Diff line number Diff line change
Expand Up @@ -1212,6 +1212,20 @@ def TriggeredOp : SimOp<"triggered", [
];
}

def DeferOp : SimOp<"defer", [
SingleBlock, NoTerminator, ProceduralOp, ProceduralRegion]> {
let summary = "Execute a region at the end of the current simulation time";
let description = [{
Schedules its body for execution in the Postponed region of the current
simulation time.
}];
let regions = (region SizedRegion<1>:$body);
let assemblyFormat = "$body attr-dict";
let extraClassDeclaration = [{
Block *getBodyBlock() { return &getBody().front(); }
}];
}

//===----------------------------------------------------------------------===//
// File I/O
//===----------------------------------------------------------------------===//
Expand Down
7 changes: 7 additions & 0 deletions lib/Conversion/ExportVerilog/ExportVerilog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4113,6 +4113,7 @@ class StmtEmitter : public EmitterBase,
emitFormattedWriteLikeOp(OpTy op, StringRef callee, StringRef formatString,
ValueRange substitutions, EmitPrefixFn emitPrefix);
LogicalResult visitSV(WriteOp op);
LogicalResult visitSV(StrobeOp op);
LogicalResult visitSV(FWriteOp op);
LogicalResult visitSV(FFlushOp op);
LogicalResult visitSV(VerbatimOp op);
Expand Down Expand Up @@ -4682,6 +4683,12 @@ LogicalResult StmtEmitter::visitSV(WriteOp op) {
[&](SmallPtrSetImpl<Operation *> &) {});
}

LogicalResult StmtEmitter::visitSV(StrobeOp op) {
return emitFormattedWriteLikeOp(op, "$strobe(", op.getFormatString(),
op.getSubstitutions(),
[&](SmallPtrSetImpl<Operation *> &) {});
}

LogicalResult StmtEmitter::visitSV(FWriteOp op) {
return emitFormattedWriteLikeOp(op, "$fwrite(", op.getFormatString(),
op.getSubstitutions(),
Expand Down
33 changes: 32 additions & 1 deletion lib/Conversion/ImportVerilog/Statements.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1006,11 +1006,12 @@ struct StmtVisitor {
}

// Display and Write Tasks (`$display[boh]?` or `$write[boh]?` or
// `$fdisplay[boh]?` or `$fwrite[boh]?`)
// `$fdisplay[boh]?` or `$fwrite[boh]? or `$strobe[boh]?`)

using moore::IntFormat;
bool isDisplay = false;
bool isFDisplay = false;
bool isStrobe = false;
bool appendNewline = false;
IntFormat defaultFormat = IntFormat::Decimal;
switch (nameId) {
Expand Down Expand Up @@ -1082,6 +1083,25 @@ struct StmtVisitor {
isFDisplay = true;
defaultFormat = IntFormat::HexLower;
break;
case ksn::Strobe:
isStrobe = true;
appendNewline = true;
break;
case ksn::StrobeB:
isStrobe = true;
appendNewline = true;
defaultFormat = IntFormat::Binary;
break;
case ksn::StrobeO:
isStrobe = true;
appendNewline = true;
defaultFormat = IntFormat::Octal;
break;
case ksn::StrobeH:
isStrobe = true;
appendNewline = true;
defaultFormat = IntFormat::HexLower;
break;
default:
break;
}
Expand Down Expand Up @@ -1116,6 +1136,17 @@ struct StmtVisitor {
return true;
}

if (isStrobe) {
auto message =
context.convertFormatString(args, loc, defaultFormat, appendNewline);
if (failed(message))
return failure();
if (*message == Value{})
return true;
moore::StrobeBIOp::create(builder, loc, *message);
return true;
}

// Severity Tasks
using moore::Severity;
std::optional<Severity> severity;
Expand Down
16 changes: 16 additions & 0 deletions lib/Conversion/MooreToCore/MooreToCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2966,6 +2966,21 @@ struct FDisplayBIOpConversion : public OpConversionPattern<FDisplayBIOp> {
}
};

struct StrobeBIOpConversion : public OpConversionPattern<StrobeBIOp> {
using OpConversionPattern::OpConversionPattern;

LogicalResult
matchAndRewrite(StrobeBIOp op, OpAdaptor adaptor,
ConversionPatternRewriter &rewriter) const override {
auto loc = op.getLoc();
auto deferOp = sim::DeferOp::create(rewriter, loc);
rewriter.createBlock(&deferOp.getBody());
sim::PrintFormattedProcOp::create(rewriter, loc, adaptor.getMessage());
rewriter.eraseOp(op);
return success();
}
};

struct FOpenBIOpConversion : public OpConversionPattern<FOpenBIOp> {
using OpConversionPattern::OpConversionPattern;
LogicalResult
Expand Down Expand Up @@ -3575,6 +3590,7 @@ static void populateOpConversion(ConversionPatternSet &patterns,
FormatRealOpConversion,
DisplayBIOpConversion,
FDisplayBIOpConversion,
StrobeBIOpConversion,

// File I/O operations
FOpenBIOpConversion,
Expand Down
15 changes: 14 additions & 1 deletion lib/Conversion/SimToSV/SimToSV.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -815,6 +815,7 @@ LogicalResult lowerPrintFormattedProcToSV(hw::HWModuleOp module,
SmallVector<GetFileOp> getFileOps;
SmallVector<PrintFormattedProcOp> printOps;
SmallVector<Operation *, 8> cleanupSeeds;
llvm::SetVector<sim::DeferOp> deferOpsToInline;
module.walk([&](Operation *op) {
if (auto getFileOp = dyn_cast<GetFileOp>(op))
getFileOps.push_back(getFileOp);
Expand Down Expand Up @@ -848,8 +849,12 @@ LogicalResult lowerPrintFormattedProcToSV(hw::HWModuleOp module,
<< "while lowering format string";
return failure();
}
bool isDeferred = isa<sim::DeferOp>(printOp->getParentOp());
auto stream = printOp.getStream();
if (!stream) {
if (isDeferred) {
sv::StrobeOp::create(builder, printOp.getLoc(), formatString, args);
deferOpsToInline.insert(cast<sim::DeferOp>(printOp->getParentOp()));
} else if (!stream) {
// no stream is specified, emit sv.write.
sv::WriteOp::create(builder, printOp.getLoc(), formatString, args);
} else {
Expand All @@ -865,6 +870,14 @@ LogicalResult lowerPrintFormattedProcToSV(hw::HWModuleOp module,

cleanupDeadSimFmtOps(cleanupSeeds);

for (auto deferOp : deferOpsToInline) {
auto *body = deferOp.getBodyBlock();
auto *parentBlock = deferOp->getBlock();
parentBlock->getOperations().splice(Block::iterator(deferOp),
body->getOperations());
deferOp.erase();
}

return success();
}

Expand Down
17 changes: 17 additions & 0 deletions test/Conversion/ExportVerilog/sv-dialect.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -1998,6 +1998,23 @@ hw.module @write_task_test(in %clock : i1) {
}
}

// CHECK-LABEL: module strobe_task_test(
// CHECK: always_ff @(posedge clock) begin
// CHECK-NEXT: $strobe("stdout");
// CHECK-NEXT: $strobe("%d", 32'h2A);
// CHECK-NEXT: $strobe("%d %d", 32'h80000001, 32'h80000002);
// CHECK-NEXT: end
hw.module @strobe_task_test(in %clock : i1) {
sv.alwaysff(posedge %clock) {
%c0 = hw.constant 42 : i32
%c1 = hw.constant 0x80000001 : i32
%c2 = hw.constant 0x80000002 : i32
sv.strobe "stdout"
sv.strobe "%d"(%c0) : i32
sv.strobe "%d %d"(%c1, %c2) : i32, i32
}
}

// CHECK-LABEL: module fwrite_task_test(
// CHECK: always_ff @(posedge clock) begin
// CHECK-NEXT: $fwrite(32'h80000001, "stdout");
Expand Down
39 changes: 39 additions & 0 deletions test/Conversion/ImportVerilog/builtins.sv
Original file line number Diff line number Diff line change
Expand Up @@ -846,3 +846,42 @@ function void FileDisplayBuiltins(int fd, int x);
$fdisplayh(fd, x);

endfunction

// IEEE 1800-2017 § 21.2.2 "Strobed monitoring"
// CHECK-LABEL: func.func private @StrobeBuiltins(
// CHECK-SAME: [[X:%.+]]: !moore.i32
function void StrobeBuiltins(int x);
// CHECK: [[TMP:%.+]] = moore.fmt.literal "\0A"
// CHECK: moore.builtin.strobe [[TMP]]
$strobe;

// CHECK: [[TMP1:%.+]] = moore.fmt.literal "hello"
// CHECK: [[TMP2:%.+]] = moore.fmt.literal "\0A"
// CHECK: [[TMP3:%.+]] = moore.fmt.concat ([[TMP1]], [[TMP2]])
// CHECK: moore.builtin.strobe [[TMP3]]
$strobe("hello");

// CHECK: [[TMP1:%.+]] = moore.fmt.int decimal [[X]], align right, pad space signed : i32
// CHECK: [[TMP2:%.+]] = moore.fmt.literal "\0A"
// CHECK: [[TMP3:%.+]] = moore.fmt.concat ([[TMP1]], [[TMP2]])
// CHECK: moore.builtin.strobe [[TMP3]]
$strobe(x);

// CHECK: [[TMP1:%.+]] = moore.fmt.int binary [[X]], align right, pad zero : i32
// CHECK: [[TMP2:%.+]] = moore.fmt.literal "\0A"
// CHECK: [[TMP3:%.+]] = moore.fmt.concat ([[TMP1]], [[TMP2]])
// CHECK: moore.builtin.strobe [[TMP3]]
$strobeb(x);

// CHECK: [[TMP1:%.+]] = moore.fmt.int octal [[X]], align right, pad zero : i32
// CHECK: [[TMP2:%.+]] = moore.fmt.literal "\0A"
// CHECK: [[TMP3:%.+]] = moore.fmt.concat ([[TMP1]], [[TMP2]])
// CHECK: moore.builtin.strobe [[TMP3]]
$strobeo(x);

// CHECK: [[TMP1:%.+]] = moore.fmt.int hex_lower [[X]], align right, pad zero : i32
// CHECK: [[TMP2:%.+]] = moore.fmt.literal "\0A"
// CHECK: [[TMP3:%.+]] = moore.fmt.concat ([[TMP1]], [[TMP2]])
// CHECK: moore.builtin.strobe [[TMP3]]
$strobeh(x);
endfunction
12 changes: 12 additions & 0 deletions test/Conversion/MooreToCore/basic.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,18 @@ func.func @FormatStrings(%arg0: !moore.i42, %arg1: !moore.f32, %arg2: !moore.f64
return
}

// CHECK-LABEL: func @StrobeToPrint
func.func @StrobeToPrint() {
// CHECK: [[TMP:%.+]] = sim.fmt.literal "hello\0A"
%0 = moore.fmt.literal "hello\0A"

// CHECK-NEXT: sim.defer {
// CHECK-NEXT: sim.proc.print [[TMP]]
// CHECK-NEXT: }
moore.builtin.strobe %0
return
}

// CHECK-LABEL: hw.module @InstanceNull() {
moore.module @InstanceNull() {

Expand Down
18 changes: 18 additions & 0 deletions test/Conversion/SimToSV/lower-print-formatted-proc-to-sv.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -192,3 +192,21 @@ hw.module @print_to_file_under_condition(in %clk : i1, in %idx : i8, in %en : i1
}
}
}

// CHECK-LABEL: hw.module @deferred_print
hw.module @deferred_print(in %clk : i1, in %arg : i8) {
hw.triggered posedge %clk (%arg) : i8 {
^bb0(%arg_in : i8):
%l0 = sim.fmt.literal "val="
%f0 = sim.fmt.dec %arg_in specifierWidth 3 : i8
%msg = sim.fmt.concat (%l0, %f0)

// CHECK: ^bb0(%[[ARG:.+]]: i8):
// CHECK-NEXT: %[[UNSIGNED:.+]] = sv.system "unsigned"(%[[ARG]]) : (i8) -> i8
// CHECK-NEXT: sv.strobe "val=%3d"(%[[UNSIGNED]]) : i8
// CHECK-NOT: sim.defer
sim.defer {
sim.proc.print %msg
}
}
}
Loading