diff --git a/core/src/main/scala/chisel3/properties/Property.scala b/core/src/main/scala/chisel3/properties/Property.scala index a80a08552f..1287e9ec68 100644 --- a/core/src/main/scala/chisel3/properties/Property.scala +++ b/core/src/main/scala/chisel3/properties/Property.scala @@ -147,7 +147,7 @@ private[chisel3] object PropertyType extends LowPriorityPropertyTypeInstances { } implicit val stringPropertyTypeInstance: SimplePropertyType[String] = - makeSimple[String](fir.StringPropertyType, fir.StringPropertyLiteral(_)) + makeSimple[String](fir.StringPropertyType, s => fir.StringPropertyLiteral(fir.StringLit(s))) implicit val boolPropertyTypeInstance: SimplePropertyType[Boolean] = makeSimple[Boolean](fir.BooleanPropertyType, fir.BooleanPropertyLiteral(_)) diff --git a/firrtl/src/main/scala/firrtl/ir/IR.scala b/firrtl/src/main/scala/firrtl/ir/IR.scala index 5d3e4f1ca4..b512814efb 100644 --- a/firrtl/src/main/scala/firrtl/ir/IR.scala +++ b/firrtl/src/main/scala/firrtl/ir/IR.scala @@ -241,7 +241,7 @@ case class DoublePropertyLiteral(value: Double) extends Expression with UseSeria val width = UnknownWidth } -case class StringPropertyLiteral(value: String) extends Expression with UseSerializer { +case class StringPropertyLiteral(value: StringLit) extends Expression with UseSerializer { def tpe = StringPropertyType val width = UnknownWidth } diff --git a/firrtl/src/main/scala/firrtl/ir/Serializer.scala b/firrtl/src/main/scala/firrtl/ir/Serializer.scala index cc9e3b359f..a1da49da0f 100644 --- a/firrtl/src/main/scala/firrtl/ir/Serializer.scala +++ b/firrtl/src/main/scala/firrtl/ir/Serializer.scala @@ -113,7 +113,7 @@ object Serializer { case DoublePropertyLiteral(value) => b ++= "Double("; b ++= value.toString(); b ++= ")" case StringPropertyLiteral(value) => - b ++= "String(\""; b ++= value; b ++= "\")" + b ++= "String("; b ++= value.escape; b ++= ")" case BooleanPropertyLiteral(value) => b ++= s"Bool(${value})" case PathPropertyLiteral(value) => diff --git a/panamaconverter/src/PanamaCIRCTConverter.scala b/panamaconverter/src/PanamaCIRCTConverter.scala index a9ccb91502..5da12f316c 100644 --- a/panamaconverter/src/PanamaCIRCTConverter.scala +++ b/panamaconverter/src/PanamaCIRCTConverter.scala @@ -576,7 +576,7 @@ class PanamaCIRCTConverter(val circt: PanamaCIRCT, fos: Option[FirtoolOptions], case fir.DoublePropertyLiteral(value) => val attrs = Seq(("value", circt.mlirFloatAttrDoubleGet(circt.mlirF64TypeGet(), value))) ("double", attrs, Seq.empty) - case fir.StringPropertyLiteral(value) => + case fir.StringPropertyLiteral(fir.StringLit(value)) => val attrs = Seq(("value", circt.mlirStringAttrGet(value))) ("string", attrs, Seq.empty) case fir.BooleanPropertyLiteral(value) => diff --git a/src/test/scala/chiselTests/properties/PropertySpec.scala b/src/test/scala/chiselTests/properties/PropertySpec.scala index 00cefa881f..0fb5676eb3 100644 --- a/src/test/scala/chiselTests/properties/PropertySpec.scala +++ b/src/test/scala/chiselTests/properties/PropertySpec.scala @@ -132,6 +132,31 @@ class PropertySpec extends ChiselFlatSpec with MatchesAndOmits { )() } + it should "escape special characters in Property String literals" in { + val input = "foo\"\n\t\\bar" + val expected = """foo\"\n\t\\bar""" + val chirrtl = ChiselStage.emitCHIRRTL(new RawModule { + val propOut = IO(Output(Property[String]())) + propOut := Property(input) + }) + + matchesAndOmits(chirrtl)( + s"""propassign propOut, String("$expected")""" + )() + } + + it should "not escape characters that do not need escaping in Property String literals" in { + val input = "foo!@#$%^&*()_+bar" + val chirrtl = ChiselStage.emitCHIRRTL(new RawModule { + val propOut = IO(Output(Property[String]())) + propOut := Property(input) + }) + + matchesAndOmits(chirrtl)( + s"""propassign propOut, String("$input")""" + )() + } + it should "support Boolean as a Property type" in { val chirrtl = ChiselStage.emitCHIRRTL(new RawModule { val boolProp = IO(Input(Property[Boolean]()))