diff --git a/include/circt/Dialect/SV/SVExpressions.td b/include/circt/Dialect/SV/SVExpressions.td index aa3b791bab..fe071f411e 100644 --- a/include/circt/Dialect/SV/SVExpressions.td +++ b/include/circt/Dialect/SV/SVExpressions.td @@ -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)"; +} diff --git a/include/circt/Dialect/SV/SVVisitors.h b/include/circt/Dialect/SV/SVVisitors.h index 6e80792b9b..fedad56f5c 100644 --- a/include/circt/Dialect/SV/SVVisitors.h +++ b/include/circt/Dialect/SV/SVVisitors.h @@ -28,7 +28,8 @@ public: return TypeSwitch(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); diff --git a/lib/Dialect/SV/SVOps.cpp b/lib/Dialect/SV/SVOps.cpp index 8aba69c061..32a7678115 100644 --- a/lib/Dialect/SV/SVOps.cpp +++ b/lib/Dialect/SV/SVOps.cpp @@ -24,7 +24,8 @@ using namespace sv; /// Return true if the specified operation is an expression. bool sv::isExpression(Operation *op) { return isa(op) || isa(op) || - isa(op); + isa(op) || isa(op) || + isa(op); } //===----------------------------------------------------------------------===// diff --git a/lib/Translation/ExportVerilog/ExportVerilog.cpp b/lib/Translation/ExportVerilog/ExportVerilog.cpp index 134c40319b..3616c9b42d 100644 --- a/lib/Translation/ExportVerilog/ExportVerilog.cpp +++ b/lib/Translation/ExportVerilog/ExportVerilog.cpp @@ -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(); diff --git a/test/Dialect/SV/basic.mlir b/test/Dialect/SV/basic.mlir index e44c65b23d..3ec65c8fb6 100644 --- a/test/Dialect/SV/basic.mlir +++ b/test/Dialect/SV/basic.mlir @@ -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: } diff --git a/test/ExportVerilog/sv-dialect.mlir b/test/ExportVerilog/sv-dialect.mlir index 3c4ac019f5..2423b05685 100644 --- a/test/ExportVerilog/sv-dialect.mlir +++ b/test/ExportVerilog/sv-dialect.mlir @@ -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" }