mirror of https://github.com/llvm/circt.git
parent
b26a9afcbd
commit
ca0a68f45d
|
@ -25,3 +25,27 @@ def TextualValueOp : SVOp<"textual_value", [NoSideEffect]> {
|
|||
let results = (outs AnySignlessInteger:$result);
|
||||
let assemblyFormat = "$string attr-dict `:` type($result)";
|
||||
}
|
||||
|
||||
def ConstantXOp : SVOp<"constantX", [NoSideEffect]> {
|
||||
let summary = "A constant of value 'x'";
|
||||
let description = [{
|
||||
This operation produces a constant value of 'x'. This 'x' follows the
|
||||
System Verilog rules for 'x' propagation.
|
||||
}];
|
||||
|
||||
let arguments = (ins);
|
||||
let results = (outs RTLIntegerType:$result);
|
||||
let assemblyFormat = " attr-dict `:` type($result)";
|
||||
}
|
||||
|
||||
def ConstantZOp : SVOp<"constantZ", [NoSideEffect]> {
|
||||
let summary = "A constant of value 'z'";
|
||||
let description = [{
|
||||
This operation produces a constant value of 'z'. This 'z' follows the
|
||||
System Verilog rules for 'z' propagation.
|
||||
}];
|
||||
|
||||
let arguments = (ins);
|
||||
let results = (outs RTLIntegerType:$result);
|
||||
let assemblyFormat = " attr-dict `:` type($result)";
|
||||
}
|
||||
|
|
|
@ -28,7 +28,8 @@ public:
|
|||
return TypeSwitch<Operation *, ResultType>(op)
|
||||
.template Case<
|
||||
// Expressions
|
||||
ReadInOutOp, ArrayIndexInOutOp, TextualValueOp,
|
||||
ReadInOutOp, ArrayIndexInOutOp, TextualValueOp, ConstantXOp,
|
||||
ConstantZOp,
|
||||
// Declarations.
|
||||
RegOp, WireOp,
|
||||
// Control flow.
|
||||
|
@ -74,9 +75,11 @@ public:
|
|||
HANDLE(WireOp, Unhandled);
|
||||
|
||||
// Expressions
|
||||
HANDLE(TextualValueOp, Unhandled)
|
||||
HANDLE(ReadInOutOp, Unhandled);
|
||||
HANDLE(ArrayIndexInOutOp, Unhandled);
|
||||
HANDLE(TextualValueOp, Unhandled);
|
||||
HANDLE(ConstantXOp, Unhandled);
|
||||
HANDLE(ConstantZOp, Unhandled);
|
||||
|
||||
// Control flow.
|
||||
HANDLE(IfDefOp, Unhandled);
|
||||
|
|
|
@ -24,7 +24,8 @@ using namespace sv;
|
|||
/// Return true if the specified operation is an expression.
|
||||
bool sv::isExpression(Operation *op) {
|
||||
return isa<sv::TextualValueOp>(op) || isa<sv::GetModportOp>(op) ||
|
||||
isa<sv::ReadInterfaceSignalOp>(op);
|
||||
isa<sv::ReadInterfaceSignalOp>(op) || isa<sv::ConstantXOp>(op) ||
|
||||
isa<sv::ConstantZOp>(op);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -722,6 +722,8 @@ private:
|
|||
SubExprInfo visitSV(GetModportOp op);
|
||||
SubExprInfo visitSV(ReadInterfaceSignalOp op);
|
||||
SubExprInfo visitSV(TextualValueOp op);
|
||||
SubExprInfo visitSV(ConstantXOp op);
|
||||
SubExprInfo visitSV(ConstantZOp op);
|
||||
|
||||
// Noop cast operators.
|
||||
SubExprInfo visitSV(ReadInOutOp op) {
|
||||
|
@ -1104,6 +1106,16 @@ SubExprInfo ExprEmitter::visitSV(TextualValueOp op) {
|
|||
return {Unary, IsUnsigned};
|
||||
}
|
||||
|
||||
SubExprInfo ExprEmitter::visitSV(ConstantXOp op) {
|
||||
os << op.getType().getWidth() << "'bx";
|
||||
return {Unary, IsUnsigned};
|
||||
}
|
||||
|
||||
SubExprInfo ExprEmitter::visitSV(ConstantZOp op) {
|
||||
os << op.getType().getWidth() << "'bz";
|
||||
return {Unary, IsUnsigned};
|
||||
}
|
||||
|
||||
SubExprInfo ExprEmitter::visitTypeOp(ConstantOp op) {
|
||||
bool isNegated = false;
|
||||
const APInt &value = op.getValue();
|
||||
|
|
|
@ -15,7 +15,9 @@ rtl.module @test1(%arg0: i1, %arg1: i1, %arg8: i8) {
|
|||
sv.ifdef "SYNTHESIS" {
|
||||
} else {
|
||||
%tmp = sv.textual_value "PRINTF_COND_" : i1
|
||||
%tmp2 = comb.and %tmp, %arg1 : i1
|
||||
%tmpx = sv.constantX : i1
|
||||
%tmpz = sv.constantZ : i1
|
||||
%tmp2 = comb.and %tmp, %tmpx, %tmpz, %arg1 : i1
|
||||
sv.if %tmp2 {
|
||||
sv.fwrite "Hi\n"
|
||||
}
|
||||
|
@ -32,12 +34,14 @@ rtl.module @test1(%arg0: i1, %arg1: i1, %arg8: i8) {
|
|||
// CHECK-NEXT: sv.ifdef "SYNTHESIS" {
|
||||
// CHECK-NEXT: } else {
|
||||
// CHECK-NEXT: %0 = sv.textual_value "PRINTF_COND_" : i1
|
||||
// CHECK-NEXT: %1 = comb.and %0, %arg1 : i1
|
||||
// CHECK-NEXT: sv.if %1 {
|
||||
// CHECK-NEXT: %1 = sv.constantX : i1
|
||||
// CHECK-NEXT: %2 = sv.constantZ : i1
|
||||
// CHECK-NEXT: %3 = comb.and %0, %1, %2, %arg1 : i1
|
||||
// CHECK-NEXT: sv.if %3 {
|
||||
// CHECK-NEXT: sv.fwrite "Hi\0A"
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: sv.if %1 {
|
||||
// CHECK-NEXT: sv.fwrite "%x"(%1) : i1
|
||||
// CHECK-NEXT: sv.if %3 {
|
||||
// CHECK-NEXT: sv.fwrite "%x"(%3) : i1
|
||||
// CHECK-NEXT: } else {
|
||||
// CHECK-NEXT: sv.fwrite "There\0A"
|
||||
// CHECK-NEXT: }
|
||||
|
|
|
@ -9,18 +9,20 @@ rtl.module @M1(%clock : i1, %cond : i1, %val : i8) {
|
|||
sv.always posedge %clock {
|
||||
sv.ifdef "SYNTHESIS" {
|
||||
} else {
|
||||
// CHECK-NEXT: if (PRINTF_COND_ & cond)
|
||||
// CHECK-NEXT: if (PRINTF_COND_ & 1'bx & 1'bz & cond)
|
||||
%tmp = sv.textual_value "PRINTF_COND_" : i1
|
||||
%tmp2 = comb.and %tmp, %cond : i1
|
||||
sv.if %tmp2 {
|
||||
%tmp1 = sv.constantX : i1
|
||||
%tmp2 = sv.constantZ : i1
|
||||
%tmp3 = comb.and %tmp, %tmp1, %tmp2, %cond : i1
|
||||
sv.if %tmp3 {
|
||||
// CHECK-NEXT: $fwrite(32'h80000002, "Hi\n");
|
||||
sv.fwrite "Hi\n"
|
||||
}
|
||||
|
||||
// CHECK-NEXT: if (!(clock | cond))
|
||||
// CHECK-NEXT: $fwrite(32'h80000002, "Bye\n");
|
||||
%tmp3 = comb.or %clock, %cond : i1
|
||||
sv.if %tmp3 {
|
||||
%tmp4 = comb.or %clock, %cond : i1
|
||||
sv.if %tmp4 {
|
||||
} else {
|
||||
sv.fwrite "Bye\n"
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue