mirror of https://github.com/llvm/circt.git
[SV] Add sim ctrl and severity message system tasks (#1989)
Extend the SV dialect to cover all simulation control system tasks (`$stop`, `$finish`, and `$exit`), and all severity message tasks (`$fatal`, `$error`, `$warning`, `$info`). This change includes added support for diagnostic verbosity in stop, finish, and fatal, as well as optional messages and interpolation operands for fatal, error, warning, and info. A subsequent PR will make use of these to lower from the FIRRTL dialect.
This commit is contained in:
parent
8c3cc01766
commit
e4878fdef7
|
@ -432,30 +432,6 @@ def FWriteOp : SVOp<"fwrite", [ProceduralOp]> {
|
|||
"$string attr-dict (`(` $operands^ `)` `:` type($operands))?";
|
||||
}
|
||||
|
||||
def FinishOp : SVOp<"finish", [ProceduralOp]> {
|
||||
let summary = "'$finish' statement";
|
||||
let description = [{
|
||||
Finishes a simulation and exits the simulation process.
|
||||
}];
|
||||
|
||||
let arguments = (ins);
|
||||
let results = (outs);
|
||||
|
||||
let assemblyFormat = "attr-dict";
|
||||
}
|
||||
|
||||
def FatalOp : SVOp<"fatal", [ProceduralOp]> {
|
||||
let summary = "'$fatal' statement";
|
||||
let description = [{
|
||||
Run-time fatal assertion error.
|
||||
}];
|
||||
|
||||
let arguments = (ins);
|
||||
let results = (outs);
|
||||
|
||||
let assemblyFormat = "attr-dict";
|
||||
}
|
||||
|
||||
def VerbatimOp : SVOp<"verbatim"> {
|
||||
let summary = "Verbatim opaque text emitted inline.";
|
||||
let description = [{
|
||||
|
@ -523,5 +499,136 @@ def BindInterfaceOp : SVOp<"bind.interface", []> {
|
|||
sv::InterfaceInstanceOp
|
||||
getReferencedInstance(const hw::SymbolCache *cache = nullptr);
|
||||
}];
|
||||
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Simulation Control Tasks
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// A number passed to `$stop` and `$finish` that indicates the level of
|
||||
/// verbosity of the diagnostic message to be printed (see section 20.2 of IEEE
|
||||
/// 1800-2017):
|
||||
///
|
||||
/// - `0`: Prints nothing
|
||||
/// - `1`: Prints simulation time and location (default)
|
||||
/// - `2`: Prints simulation time, location, and statistics about the memory and
|
||||
/// CPU time used in simulation
|
||||
def VerbosityIntAttr : DefaultValuedAttr<Confined<I8Attr,
|
||||
[IntMinValue<0>, IntMaxValue<2>]>, "1">;
|
||||
|
||||
/// Commonalities between `StopOp` and `FinishOp`.
|
||||
class FinishOrStopOp<string mnemonic, list<OpTrait> traits = []> :
|
||||
SVOp<mnemonic, [ProceduralOp] # traits> {
|
||||
let arguments = (ins VerbosityIntAttr:$verbosity);
|
||||
let assemblyFormat = "$verbosity attr-dict";
|
||||
|
||||
// First line intentionally left blank.
|
||||
string verbosityDescription = [{
|
||||
The optional `verbosity` parameter controls how much diagnostic information
|
||||
is printed when the system task is executed (see section 20.2 of IEEE
|
||||
1800-2017):
|
||||
|
||||
- `0`: Prints nothing
|
||||
- `1`: Prints simulation time and location (default)
|
||||
- `2`: Prints simulation time, location, and statistics about the memory and
|
||||
CPU time used in simulation
|
||||
}];
|
||||
}
|
||||
|
||||
def StopOp : FinishOrStopOp<"stop"> {
|
||||
let summary = "`$stop` system task";
|
||||
let description = [{
|
||||
Causes the simulation to be suspended. Does not terminate the simulator.
|
||||
}] # verbosityDescription;
|
||||
}
|
||||
|
||||
def FinishOp : FinishOrStopOp<"finish"> {
|
||||
let summary = "`$finish` system task";
|
||||
let description = [{
|
||||
Stops the simulation and exits/terminates the simulator process. In practice
|
||||
most GUI-based simulators will show a prompt to the user offering them an
|
||||
opportunity to not close the simulator altogether.
|
||||
|
||||
Other tasks such as `$exit` or `$fatal` implicitly call this system task.
|
||||
}] # verbosityDescription;
|
||||
}
|
||||
|
||||
def ExitOp : SVOp<"exit", [ProceduralOp]> {
|
||||
let summary = "`$exit` system task";
|
||||
let description = [{
|
||||
Waits for all `program` blocks to complete and then makes an implicit call
|
||||
to `$finish` with default verbosity (level 1) to conclude the simulation.
|
||||
}];
|
||||
let assemblyFormat = "attr-dict";
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Severity Message Tasks
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
def FatalOp : SVOp<"fatal", [ProceduralOp]> {
|
||||
let summary = "`$fatal` severity message task";
|
||||
let description = [{
|
||||
Generates a run-time fatal error which terminates the simulation with an
|
||||
error code. Makes an implicit call to `$finish`, forwarding the `verbosity`
|
||||
operand. If present, the optional message is printed with any additional
|
||||
operands interpolated into the message string.
|
||||
}];
|
||||
let arguments = (ins
|
||||
VerbosityIntAttr:$verbosity,
|
||||
OptionalAttr<StrAttr>:$message, Variadic<AnyType>:$operands);
|
||||
let assemblyFormat = [{
|
||||
$verbosity
|
||||
(`,` $message^ (`(` $operands^ `)` `:` type($operands))?)?
|
||||
attr-dict
|
||||
}];
|
||||
let builders = [
|
||||
OpBuilder<(ins CArg<VerbosityIntAttr.returnType,"1">:$verbosity),
|
||||
"build(odsBuilder, odsState, verbosity, StringAttr{}, ValueRange{});">,
|
||||
OpBuilder<(ins VerbosityIntAttr.returnType:$verbosity,
|
||||
"mlir::StringAttr":$message),
|
||||
"build(odsBuilder, odsState, verbosity, message, ValueRange{});">,
|
||||
];
|
||||
}
|
||||
|
||||
/// Commonalities between `ErrorOp`, `WarningOp`, and `InfoOp`.
|
||||
class NonfatalMessageOp<string mnemonic, list<OpTrait> traits = []> :
|
||||
SVOp<mnemonic, [ProceduralOp] # traits> {
|
||||
string messageDescription = [{
|
||||
If present, the optional message is printed with any additional operands
|
||||
interpolated into the message string.
|
||||
}];
|
||||
let arguments = (ins
|
||||
OptionalAttr<StrAttr>:$message, Variadic<AnyType>:$operands);
|
||||
let assemblyFormat = [{
|
||||
($message^ (`(` $operands^ `)` `:` type($operands))?)?
|
||||
attr-dict
|
||||
}];
|
||||
let builders = [
|
||||
OpBuilder<(ins),
|
||||
"build(odsBuilder, odsState, StringAttr{}, ValueRange{});">,
|
||||
OpBuilder<(ins "mlir::StringAttr":$message),
|
||||
"build(odsBuilder, odsState, message, ValueRange{});">,
|
||||
];
|
||||
}
|
||||
|
||||
def ErrorOp : NonfatalMessageOp<"error"> {
|
||||
let summary = "`$error` severity message task";
|
||||
let description = [{
|
||||
This system task indicates a run-time error.
|
||||
}] # messageDescription;
|
||||
}
|
||||
|
||||
def WarningOp : NonfatalMessageOp<"warning"> {
|
||||
let summary = "`$warning` severity message task";
|
||||
let description = [{
|
||||
This system task indicates a run-time warning.
|
||||
}] # messageDescription;
|
||||
}
|
||||
|
||||
def InfoOp : NonfatalMessageOp<"info"> {
|
||||
let summary = "`$info` severity message task";
|
||||
let description = [{
|
||||
This system task indicates a message with no specific severity.
|
||||
}] # messageDescription;
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ public:
|
|||
AlwaysFFOp, InitialOp, CaseZOp,
|
||||
// Other Statements.
|
||||
AssignOp, BPAssignOp, PAssignOp, ForceOp, ReleaseOp, AliasOp,
|
||||
FWriteOp, FatalOp, FinishOp, VerbatimOp,
|
||||
FWriteOp, VerbatimOp,
|
||||
// Type declarations.
|
||||
InterfaceOp, InterfaceSignalOp, InterfaceModportOp,
|
||||
InterfaceInstanceOp, GetModportOp, AssignInterfaceSignalOp,
|
||||
|
@ -46,7 +46,11 @@ public:
|
|||
AssertOp, AssumeOp, CoverOp, AssertConcurrentOp, AssumeConcurrentOp,
|
||||
CoverConcurrentOp,
|
||||
// Bind Statements
|
||||
BindOp>([&](auto expr) -> ResultType {
|
||||
BindOp,
|
||||
// Simulator control tasks
|
||||
StopOp, FinishOp, ExitOp,
|
||||
// Severity message tasks
|
||||
FatalOp, ErrorOp, WarningOp, InfoOp>([&](auto expr) -> ResultType {
|
||||
return thisCast->visitSV(expr, args...);
|
||||
})
|
||||
.Default([&](auto expr) -> ResultType {
|
||||
|
@ -103,8 +107,6 @@ public:
|
|||
HANDLE(ReleaseOp, Unhandled);
|
||||
HANDLE(AliasOp, Unhandled);
|
||||
HANDLE(FWriteOp, Unhandled);
|
||||
HANDLE(FatalOp, Unhandled);
|
||||
HANDLE(FinishOp, Unhandled);
|
||||
HANDLE(VerbatimOp, Unhandled);
|
||||
|
||||
// Type declarations.
|
||||
|
@ -126,6 +128,17 @@ public:
|
|||
|
||||
// Bind statements.
|
||||
HANDLE(BindOp, Unhandled);
|
||||
|
||||
// Simulator control tasks
|
||||
HANDLE(StopOp, Unhandled);
|
||||
HANDLE(FinishOp, Unhandled);
|
||||
HANDLE(ExitOp, Unhandled);
|
||||
|
||||
// Severity message tasks
|
||||
HANDLE(FatalOp, Unhandled);
|
||||
HANDLE(ErrorOp, Unhandled);
|
||||
HANDLE(WarningOp, Unhandled);
|
||||
HANDLE(InfoOp, Unhandled);
|
||||
#undef HANDLE
|
||||
};
|
||||
|
||||
|
|
|
@ -2075,10 +2075,23 @@ private:
|
|||
LogicalResult visitSV(InitialOp op);
|
||||
LogicalResult visitSV(CaseZOp op);
|
||||
LogicalResult visitSV(FWriteOp op);
|
||||
LogicalResult visitSV(FatalOp op);
|
||||
LogicalResult visitSV(FinishOp op);
|
||||
LogicalResult visitSV(VerbatimOp op);
|
||||
|
||||
LogicalResult emitSimulationControlTask(Operation *op, StringRef taskName,
|
||||
Optional<unsigned> verbosity);
|
||||
LogicalResult visitSV(StopOp op);
|
||||
LogicalResult visitSV(FinishOp op);
|
||||
LogicalResult visitSV(ExitOp op);
|
||||
|
||||
LogicalResult emitSeverityMessageTask(Operation *op, StringRef taskName,
|
||||
Optional<unsigned> verbosity,
|
||||
StringAttr message,
|
||||
ValueRange operands);
|
||||
LogicalResult visitSV(FatalOp op);
|
||||
LogicalResult visitSV(ErrorOp op);
|
||||
LogicalResult visitSV(WarningOp op);
|
||||
LogicalResult visitSV(InfoOp op);
|
||||
|
||||
void emitAssertionLabel(Operation *op, StringRef opName);
|
||||
void emitAssertionMessage(StringAttr message, ValueRange args,
|
||||
SmallPtrSet<Operation *, 8> &ops);
|
||||
|
@ -2367,14 +2380,6 @@ LogicalResult StmtEmitter::visitSV(FWriteOp op) {
|
|||
return success();
|
||||
}
|
||||
|
||||
LogicalResult StmtEmitter::visitSV(FatalOp op) {
|
||||
SmallPtrSet<Operation *, 8> ops;
|
||||
ops.insert(op);
|
||||
indent() << "$fatal;";
|
||||
emitLocationInfoAndNewLine(ops);
|
||||
return success();
|
||||
}
|
||||
|
||||
LogicalResult StmtEmitter::visitSV(VerbatimOp op) {
|
||||
SmallPtrSet<Operation *, 8> ops;
|
||||
ops.insert(op);
|
||||
|
@ -2416,14 +2421,95 @@ LogicalResult StmtEmitter::visitSV(VerbatimOp op) {
|
|||
return success();
|
||||
}
|
||||
|
||||
LogicalResult StmtEmitter::visitSV(FinishOp op) {
|
||||
/// Emit one of the simulation control tasks `$stop`, `$finish`, or `$exit`.
|
||||
LogicalResult
|
||||
StmtEmitter::emitSimulationControlTask(Operation *op, StringRef taskName,
|
||||
Optional<unsigned> verbosity) {
|
||||
SmallPtrSet<Operation *, 8> ops;
|
||||
ops.insert(op);
|
||||
indent() << "$finish;";
|
||||
indent() << taskName;
|
||||
if (verbosity && *verbosity != 1)
|
||||
os << "(" << *verbosity << ")";
|
||||
os << ";";
|
||||
emitLocationInfoAndNewLine(ops);
|
||||
return success();
|
||||
}
|
||||
|
||||
LogicalResult StmtEmitter::visitSV(StopOp op) {
|
||||
return emitSimulationControlTask(op, "$stop", op.verbosity());
|
||||
}
|
||||
|
||||
LogicalResult StmtEmitter::visitSV(FinishOp op) {
|
||||
return emitSimulationControlTask(op, "$finish", op.verbosity());
|
||||
}
|
||||
|
||||
LogicalResult StmtEmitter::visitSV(ExitOp op) {
|
||||
return emitSimulationControlTask(op, "$exit", {});
|
||||
}
|
||||
|
||||
/// Emit one of the severity message tasks `$fatal`, `$error`, `$warning`, or
|
||||
/// `$info`.
|
||||
LogicalResult StmtEmitter::emitSeverityMessageTask(Operation *op,
|
||||
StringRef taskName,
|
||||
Optional<unsigned> verbosity,
|
||||
StringAttr message,
|
||||
ValueRange operands) {
|
||||
SmallPtrSet<Operation *, 8> ops;
|
||||
ops.insert(op);
|
||||
indent() << taskName;
|
||||
|
||||
// In case we have a message to print, or the operation has an optional
|
||||
// verbosity and that verbosity is present, print the parenthesized parameter
|
||||
// list.
|
||||
if ((verbosity && *verbosity != 1) || message) {
|
||||
os << "(";
|
||||
|
||||
// If the operation takes a verbosity, print it if it is set, or print the
|
||||
// default "1".
|
||||
if (verbosity)
|
||||
os << *verbosity;
|
||||
|
||||
// Print the message and interpolation operands if present.
|
||||
if (message) {
|
||||
if (verbosity)
|
||||
os << ", ";
|
||||
os << "\"";
|
||||
os.write_escaped(message.getValue());
|
||||
os << "\"";
|
||||
for (auto operand : operands) {
|
||||
os << ", ";
|
||||
emitExpression(operand, ops);
|
||||
}
|
||||
}
|
||||
|
||||
os << ")";
|
||||
}
|
||||
|
||||
os << ";";
|
||||
emitLocationInfoAndNewLine(ops);
|
||||
return success();
|
||||
}
|
||||
|
||||
LogicalResult StmtEmitter::visitSV(FatalOp op) {
|
||||
return emitSeverityMessageTask(op, "$fatal", op.verbosity(), op.messageAttr(),
|
||||
op.operands());
|
||||
}
|
||||
|
||||
LogicalResult StmtEmitter::visitSV(ErrorOp op) {
|
||||
return emitSeverityMessageTask(op, "$error", {}, op.messageAttr(),
|
||||
op.operands());
|
||||
}
|
||||
|
||||
LogicalResult StmtEmitter::visitSV(WarningOp op) {
|
||||
return emitSeverityMessageTask(op, "$warning", {}, op.messageAttr(),
|
||||
op.operands());
|
||||
}
|
||||
|
||||
LogicalResult StmtEmitter::visitSV(InfoOp op) {
|
||||
return emitSeverityMessageTask(op, "$info", {}, op.messageAttr(),
|
||||
op.operands());
|
||||
}
|
||||
|
||||
/// Emit the `<label>:` portion of an immediate or concurrent verification
|
||||
/// operation. If a label has been stored for the operation through
|
||||
/// `addLegalName` in the pre-pass, that label is used. Otherwise, if the
|
||||
|
|
|
@ -173,6 +173,48 @@ hw.module @test1(%arg0: i1, %arg1: i1, %arg8: i8) {
|
|||
%reg24 = sv.reg sym @regSym1 : !hw.inout<i23>
|
||||
%wire25 = sv.wire sym @wireSym1 : !hw.inout<i23>
|
||||
|
||||
// Simulation Control Tasks
|
||||
// CHECK-NEXT: sv.initial {
|
||||
// CHECK-NEXT: sv.stop 1
|
||||
// CHECK-NEXT: sv.finish 1
|
||||
// CHECK-NEXT: sv.exit
|
||||
// CHECK-NEXT: }
|
||||
sv.initial {
|
||||
sv.stop 1
|
||||
sv.finish 1
|
||||
sv.exit
|
||||
}
|
||||
|
||||
// Severity Message Tasks
|
||||
// CHECK-NEXT: sv.initial {
|
||||
// CHECK-NEXT: sv.fatal 1
|
||||
// CHECK-NEXT: sv.fatal 1, "hello"
|
||||
// CHECK-NEXT: sv.fatal 1, "hello %d"(%arg0) : i1
|
||||
// CHECK-NEXT: sv.error
|
||||
// CHECK-NEXT: sv.error "hello"
|
||||
// CHECK-NEXT: sv.error "hello %d"(%arg0) : i1
|
||||
// CHECK-NEXT: sv.warning
|
||||
// CHECK-NEXT: sv.warning "hello"
|
||||
// CHECK-NEXT: sv.warning "hello %d"(%arg0) : i1
|
||||
// CHECK-NEXT: sv.info
|
||||
// CHECK-NEXT: sv.info "hello"
|
||||
// CHECK-NEXT: sv.info "hello %d"(%arg0) : i1
|
||||
// CHECK-NEXT: }
|
||||
sv.initial {
|
||||
sv.fatal 1
|
||||
sv.fatal 1, "hello"
|
||||
sv.fatal 1, "hello %d"(%arg0) : i1
|
||||
sv.error
|
||||
sv.error "hello"
|
||||
sv.error "hello %d"(%arg0) : i1
|
||||
sv.warning
|
||||
sv.warning "hello"
|
||||
sv.warning "hello %d"(%arg0) : i1
|
||||
sv.info
|
||||
sv.info "hello"
|
||||
sv.info "hello %d"(%arg0) : i1
|
||||
}
|
||||
|
||||
// CHECK-NEXT: hw.output
|
||||
hw.output
|
||||
}
|
||||
|
|
|
@ -77,13 +77,13 @@ hw.module @IfOp(%arg0: i1) {
|
|||
// -----
|
||||
hw.module @Fatal() {
|
||||
// expected-error @+1 {{sv.fatal should be in a procedural region}}
|
||||
sv.fatal
|
||||
sv.fatal 1
|
||||
}
|
||||
|
||||
// -----
|
||||
hw.module @Fatal() {
|
||||
hw.module @Finish() {
|
||||
// expected-error @+1 {{sv.finish should be in a procedural region}}
|
||||
sv.finish
|
||||
sv.finish 1
|
||||
}
|
||||
|
||||
// -----
|
||||
|
|
|
@ -78,7 +78,7 @@ hw.module @array_create_get_default(%arg0: i8, %arg1: i8, %arg2: i8, %arg3: i8,
|
|||
// CHECK: sv.if %1 {
|
||||
%cond = comb.icmp eq %2, %arg2 : i8
|
||||
sv.if %cond {
|
||||
sv.fatal
|
||||
sv.fatal 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ hw.module @unary_ops(%arg0: i8, %arg1: i8, %arg2: i8, %arg3: i1)
|
|||
// CHECK: [[XOR3:%.+]] = comb.xor %arg3, [[TRUE2]]
|
||||
// CHECK: sv.if [[XOR3]]
|
||||
sv.if %c {
|
||||
sv.fatal
|
||||
sv.fatal 1
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -124,17 +124,17 @@ hw.module @sink_expression(%clock: i1, %a: i1, %a2: i1, %a3: i1, %a4: i1) {
|
|||
// CHECK: [[OR:%.*]] = comb.or %a2, %a3 : i1
|
||||
// CHECK: sv.if [[OR]]
|
||||
sv.if %0 {
|
||||
sv.fatal
|
||||
sv.fatal 1
|
||||
}
|
||||
// CHECK: sv.if [[XOR]]
|
||||
sv.if %2 {
|
||||
sv.fatal
|
||||
sv.fatal 1
|
||||
}
|
||||
}
|
||||
|
||||
// CHECK: sv.if [[XOR]]
|
||||
sv.if %2 {
|
||||
sv.fatal
|
||||
sv.fatal 1
|
||||
}
|
||||
}
|
||||
hw.output
|
||||
|
@ -152,12 +152,12 @@ hw.module @dont_sink_se_expression(%clock: i1, %a: i1, %a2: i1, %a3: i1, %a4: i1
|
|||
// CHECK: [[SINK:%.*]] = sv.verbatim.expr "SINK_ME"
|
||||
// CHECK: sv.if [[SINK]]
|
||||
sv.if %0 {
|
||||
sv.fatal
|
||||
sv.fatal 1
|
||||
}
|
||||
|
||||
// CHECK: sv.if [[DONT_TOUCH]]
|
||||
sv.if %1 {
|
||||
sv.fatal
|
||||
sv.fatal 1
|
||||
}
|
||||
}
|
||||
hw.output
|
||||
|
|
|
@ -21,7 +21,7 @@ hw.module @side_effect_expr(%clock: i1) -> (a: i1, a2: i1) {
|
|||
// CHECK: if (INLINE_OK)
|
||||
// DISALLOW: if ([[COND]])
|
||||
sv.if %0 {
|
||||
sv.fatal
|
||||
sv.fatal 1
|
||||
}
|
||||
|
||||
// This should go through a reg when in "disallow" mode.
|
||||
|
@ -30,7 +30,7 @@ hw.module @side_effect_expr(%clock: i1) -> (a: i1, a2: i1) {
|
|||
// DISALLOW: if ([[SE_REG]])
|
||||
%1 = sv.verbatim.expr.se "SIDE_EFFECT" : () -> i1
|
||||
sv.if %1 {
|
||||
sv.fatal
|
||||
sv.fatal 1
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -66,7 +66,7 @@ hw.module @hoist_expressions(%clock: i1, %x: i8, %y: i8, %z: i8) {
|
|||
// DISALLOW: $fwrite(32'h80000002, "Hi %x\n", [[MUL]]);
|
||||
%2 = comb.mul %0, %z : i8
|
||||
sv.fwrite "Hi %x\0A"(%2) : i8
|
||||
sv.fatal
|
||||
sv.fatal 1
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -87,7 +87,7 @@ hw.module @hoist_expressions(%clock: i1, %x: i8, %y: i8, %z: i8) {
|
|||
// CHECK: if (x + myWire == z)
|
||||
// DISALLOW: if ([[COND]])
|
||||
sv.if %4 {
|
||||
sv.fatal
|
||||
sv.fatal 1
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -174,10 +174,49 @@ hw.module @M1<param1: i42>(%clock : i1, %cond : i1, %val : i8) {
|
|||
// CHECK-NEXT: cover_0: cover(cond);
|
||||
sv.cover %cond, immediate label "cover_0"
|
||||
|
||||
// CHECK-NEXT: $fatal
|
||||
sv.fatal
|
||||
// CHECK-NEXT: $finish
|
||||
sv.finish
|
||||
// Simulator Control Tasks
|
||||
// CHECK-NEXT: $stop;
|
||||
// CHECK-NEXT: $stop(0);
|
||||
sv.stop 1
|
||||
sv.stop 0
|
||||
// CHECK-NEXT: $finish;
|
||||
// CHECK-NEXT: $finish(0);
|
||||
sv.finish 1
|
||||
sv.finish 0
|
||||
// CHECK-NEXT: $exit;
|
||||
sv.exit
|
||||
|
||||
// Severity Message Tasks
|
||||
// CHECK-NEXT: $fatal;
|
||||
// CHECK-NEXT: $fatal(1, "foo");
|
||||
// CHECK-NEXT: $fatal(1, "foo", val);
|
||||
// CHECK-NEXT: $fatal(0);
|
||||
// CHECK-NEXT: $fatal(0, "foo");
|
||||
// CHECK-NEXT: $fatal(0, "foo", val);
|
||||
sv.fatal 1
|
||||
sv.fatal 1, "foo"
|
||||
sv.fatal 1, "foo"(%val) : i8
|
||||
sv.fatal 0
|
||||
sv.fatal 0, "foo"
|
||||
sv.fatal 0, "foo"(%val) : i8
|
||||
// CHECK-NEXT: $error;
|
||||
// CHECK-NEXT: $error("foo");
|
||||
// CHECK-NEXT: $error("foo", val);
|
||||
sv.error
|
||||
sv.error "foo"
|
||||
sv.error "foo"(%val) : i8
|
||||
// CHECK-NEXT: $warning;
|
||||
// CHECK-NEXT: $warning("foo");
|
||||
// CHECK-NEXT: $warning("foo", val);
|
||||
sv.warning
|
||||
sv.warning "foo"
|
||||
sv.warning "foo"(%val) : i8
|
||||
// CHECK-NEXT: $info;
|
||||
// CHECK-NEXT: $info("foo");
|
||||
// CHECK-NEXT: $info("foo", val);
|
||||
sv.info
|
||||
sv.info "foo"
|
||||
sv.info "foo"(%val) : i8
|
||||
|
||||
// CHECK-NEXT: Emit some stuff in verilog
|
||||
// CHECK-NEXT: Great power and responsibility!
|
||||
|
@ -221,7 +260,7 @@ hw.module @M1<param1: i42>(%clock : i1, %cond : i1, %val : i8) {
|
|||
// CHECK-NOT: begin
|
||||
sv.initial {
|
||||
// CHECK-NEXT: $fatal
|
||||
sv.fatal
|
||||
sv.fatal 1
|
||||
}
|
||||
|
||||
// CHECK-NEXT: initial begin
|
||||
|
@ -505,7 +544,7 @@ hw.module @issue720(%clock: i1, %arg1: i1, %arg2: i1, %arg3: i1) {
|
|||
// CHECK: if (arg1)
|
||||
// CHECK: $fatal;
|
||||
sv.if %arg1 {
|
||||
sv.fatal
|
||||
sv.fatal 1
|
||||
}
|
||||
|
||||
// CHECK: if (_T)
|
||||
|
@ -515,13 +554,13 @@ hw.module @issue720(%clock: i1, %arg1: i1, %arg2: i1, %arg3: i1) {
|
|||
%610 = comb.and %arg1, %arg2 : i1
|
||||
%611 = comb.and %arg3, %610 : i1
|
||||
sv.if %610 {
|
||||
sv.fatal
|
||||
sv.fatal 1
|
||||
}
|
||||
|
||||
// CHECK: if (arg3 & _T)
|
||||
// CHECK: $fatal;
|
||||
sv.if %611 {
|
||||
sv.fatal
|
||||
sv.fatal 1
|
||||
}
|
||||
} // CHECK: end // always @(posedge)
|
||||
|
||||
|
@ -539,7 +578,7 @@ hw.module @issue720ifdef(%clock: i1, %arg1: i1, %arg2: i1, %arg3: i1) {
|
|||
// CHECK: if (arg1)
|
||||
// CHECK: $fatal;
|
||||
sv.if %arg1 {
|
||||
sv.fatal
|
||||
sv.fatal 1
|
||||
}
|
||||
|
||||
// CHECK: `ifdef FUN_AND_GAMES
|
||||
|
@ -550,13 +589,13 @@ hw.module @issue720ifdef(%clock: i1, %arg1: i1, %arg2: i1, %arg3: i1) {
|
|||
// CHECK: $fatal;
|
||||
%610 = comb.and %arg1, %arg2 : i1
|
||||
sv.if %610 {
|
||||
sv.fatal
|
||||
sv.fatal 1
|
||||
}
|
||||
// CHECK: if (arg3 & _T)
|
||||
// CHECK: $fatal;
|
||||
%611 = comb.and %arg3, %610 : i1
|
||||
sv.if %611 {
|
||||
sv.fatal
|
||||
sv.fatal 1
|
||||
}
|
||||
// CHECK: `endif
|
||||
// CHECK: end // always @(posedge)
|
||||
|
|
|
@ -348,7 +348,7 @@ hw.module @Stop(%clock: i1, %reset: i1) {
|
|||
%0 = sv.verbatim.expr "`STOP_COND_" : () -> i1
|
||||
%1 = comb.and %0, %reset : i1
|
||||
sv.if %1 {
|
||||
sv.fatal
|
||||
sv.fatal 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue