diff --git a/include/circt/Dialect/SV/SVExpressions.td b/include/circt/Dialect/SV/SVExpressions.td index c4c8e912e4..4b4b06890d 100644 --- a/include/circt/Dialect/SV/SVExpressions.td +++ b/include/circt/Dialect/SV/SVExpressions.td @@ -90,8 +90,14 @@ def ConstantXOp : SVOp<"constantX", [NoSideEffect, HasCustomSSAName]> { }]; let arguments = (ins); - let results = (outs HWIntegerType:$result); + let results = (outs HWValueType:$result); let assemblyFormat = " attr-dict `:` type($result)"; + let verifier = "return ::verify$cppClass(*this);"; + let extraClassDeclaration = [{ + int64_t getWidth() { + return hw::getBitWidth(getType()); + } + }]; } def ConstantZOp : SVOp<"constantZ", [NoSideEffect, HasCustomSSAName]> { @@ -102,8 +108,14 @@ def ConstantZOp : SVOp<"constantZ", [NoSideEffect, HasCustomSSAName]> { }]; let arguments = (ins); - let results = (outs HWIntegerType:$result); + let results = (outs HWValueType:$result); let assemblyFormat = " attr-dict `:` type($result)"; + let verifier = "return ::verify$cppClass(*this);"; + let extraClassDeclaration = [{ + int64_t getWidth() { + return hw::getBitWidth(getType()); + } + }]; } def LocalParamOp : SVOp<"localparam", diff --git a/lib/Conversion/ExportVerilog/ExportVerilog.cpp b/lib/Conversion/ExportVerilog/ExportVerilog.cpp index 4b7b96e0d3..f21fed1c5f 100644 --- a/lib/Conversion/ExportVerilog/ExportVerilog.cpp +++ b/lib/Conversion/ExportVerilog/ExportVerilog.cpp @@ -1884,12 +1884,12 @@ SubExprInfo ExprEmitter::visitVerbatimExprOp(Operation *op, ArrayAttr symbols) { } SubExprInfo ExprEmitter::visitSV(ConstantXOp op) { - os << op.getType().getWidth() << "'bx"; + os << op.getWidth() << "'bx"; return {Unary, IsUnsigned}; } SubExprInfo ExprEmitter::visitSV(ConstantZOp op) { - os << op.getType().getWidth() << "'bz"; + os << op.getWidth() << "'bz"; return {Unary, IsUnsigned}; } diff --git a/lib/Dialect/SV/SVOps.cpp b/lib/Dialect/SV/SVOps.cpp index 607c1e829c..aabcde65c3 100644 --- a/lib/Dialect/SV/SVOps.cpp +++ b/lib/Dialect/SV/SVOps.cpp @@ -170,18 +170,32 @@ void ConstantXOp::getAsmResultNames( function_ref setNameFn) { SmallVector specialNameBuffer; llvm::raw_svector_ostream specialName(specialNameBuffer); - specialName << "x_" << getType(); + specialName << "x_i" << getWidth(); setNameFn(getResult(), specialName.str()); } +static LogicalResult verifyConstantXOp(ConstantXOp op) { + // We don't allow zero width constant or unknown width. + if (op.getWidth() <= 0) + return op.emitError("unsupported type"); + return success(); +} + void ConstantZOp::getAsmResultNames( function_ref setNameFn) { SmallVector specialNameBuffer; llvm::raw_svector_ostream specialName(specialNameBuffer); - specialName << "z_" << getType(); + specialName << "z_i" << getWidth(); setNameFn(getResult(), specialName.str()); } +static LogicalResult verifyConstantZOp(ConstantZOp op) { + // We don't allow zero width constant or unknown type. + if (op.getWidth() <= 0) + return op.emitError("unsupported type"); + return success(); +} + //===----------------------------------------------------------------------===// // LocalParamOp //===----------------------------------------------------------------------===// diff --git a/test/Conversion/ExportVerilog/sv-dialect.mlir b/test/Conversion/ExportVerilog/sv-dialect.mlir index 2d4bfd3823..b064d1d2d0 100644 --- a/test/Conversion/ExportVerilog/sv-dialect.mlir +++ b/test/Conversion/ExportVerilog/sv-dialect.mlir @@ -445,6 +445,16 @@ hw.module @struct_field_inout2(%a: !hw.inout>>) { sv.assign %1, %true : i1 } +// CHECK-LABEL: module AggregateConstantXZ( +hw.module @AggregateConstantXZ() -> (res1: !hw.struct>, + res2: !hw.struct>) { + %0 = sv.constantX : !hw.struct> + %1 = sv.constantZ : !hw.struct> + // CHECK: assign res1 = 14'bx + // CHECK: assign res2 = 14'bz + hw.output %0, %1 : !hw.struct>, !hw.struct> +} + // CHECK-LABEL: issue508 // https://github.com/llvm/circt/issues/508 hw.module @issue508(%in1: i1, %in2: i1) { diff --git a/test/Dialect/SV/errors.mlir b/test/Dialect/SV/errors.mlir index 6a88a5f418..0028fd9c0e 100644 --- a/test/Dialect/SV/errors.mlir +++ b/test/Dialect/SV/errors.mlir @@ -199,3 +199,17 @@ hw.module @part_select1() { // expected-error @+1 {{slice width should not be greater than input width}} %c = sv.indexed_part_select %r1[%c2 : 20] : i10,i3 } + +// ----- + +hw.module @ZeroWidthConstantX() { + // expected-error @+1 {{unsupported type}} + %0 = sv.constantX : !hw.struct<> +} + +// ----- + +hw.module @ZeroWidthConstantZ() { + // expected-error @+1 {{unsupported type}} + %0 = sv.constantZ : !hw.struct<> +}