From 69c6cd7c1444bb98ba811a0ac41ee1d00b7567a2 Mon Sep 17 00:00:00 2001 From: John Wright Date: Wed, 6 May 2020 17:35:09 -0700 Subject: [PATCH 1/5] Add support for emitting string-valued and plusargs with no default --- src/main/scala/util/PlusArg.scala | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/src/main/scala/util/PlusArg.scala b/src/main/scala/util/PlusArg.scala index 5f8939ffcdf..a0cee115be4 100644 --- a/src/main/scala/util/PlusArg.scala +++ b/src/main/scala/util/PlusArg.scala @@ -6,7 +6,14 @@ import chisel3._ import chisel3.experimental._ import chisel3.util.HasBlackBoxResource -case class PlusArgInfo(default: BigInt, docstring: String) +abstract class PlusArgInfo[T] { + val docstring: String + val default: Option[T] + def doctype: String +} + +case class BigIntPlusArgInfo(default: Option[BigInt], docstring: String) extends PlusArgInfo[BigInt] { def doctype = "INT" } +case class StringPlusArgInfo(default: Option[String], docstring: String) extends PlusArgInfo[String] { def doctype = "STRING" } class plusarg_reader(val format: String, val default: BigInt, val docstring: String, val width: Int) extends BlackBox(Map( "FORMAT" -> StringParam(format), @@ -55,18 +62,27 @@ object PlusArg } object PlusArgArtefacts { - private var artefacts: Map[String, PlusArgInfo] = Map.empty + private var artefacts: Map[String, PlusArgInfo[_]] = Map.empty /* Add a new PlusArg */ + def append(name: String, default: Option[BigInt], docstring: String): Unit = + artefacts = artefacts ++ Map(name -> BigIntPlusArgInfo(default, docstring)) + def append(name: String, default: BigInt, docstring: String): Unit = - artefacts = artefacts ++ Map(name -> PlusArgInfo(default, docstring)) + append(name, Some(default), docstring) + + def appendString(name: String, default: Option[String], docstring: String): Unit = + artefacts = artefacts ++ Map(name -> StringPlusArgInfo(default, docstring)) + + def appendString(name: String, default: String, docstring: String): Unit = + appendString(name, Some(default), docstring) /* From plus args, generate help text */ private def serializeHelp_cHeader(tab: String = ""): String = artefacts - .map{ case(arg, PlusArgInfo(default, docstring)) => - s"""|$tab+$arg=INT\\n\\ - |$tab${" "*20}$docstring\\n\\ - |$tab${" "*22}(default=$default)""".stripMargin }.toSeq + .map{ case(arg, info) => + s"""|$tab+$arg=${info.doctype}\\n\\ + |$tab${" "*20}${info.docstring}\\n\\ + |$tab${" "*22}(default=${info.default.getOrElse("NONE")})""".stripMargin }.toSeq .mkString("\\n\\\n") ++ "\"" /* From plus args, generate a char array of their names */ From 7c7dcfac36601ffeabb2c7ae6f5add409f48149d Mon Sep 17 00:00:00 2001 From: John Wright Date: Fri, 8 May 2020 13:51:28 -0700 Subject: [PATCH 2/5] CR feedback --- src/main/scala/util/PlusArg.scala | 56 ++++++++++++++++++------------- 1 file changed, 33 insertions(+), 23 deletions(-) diff --git a/src/main/scala/util/PlusArg.scala b/src/main/scala/util/PlusArg.scala index a0cee115be4..bb00793c3dc 100644 --- a/src/main/scala/util/PlusArg.scala +++ b/src/main/scala/util/PlusArg.scala @@ -6,14 +6,17 @@ import chisel3._ import chisel3.experimental._ import chisel3.util.HasBlackBoxResource -abstract class PlusArgInfo[T] { - val docstring: String - val default: Option[T] - def doctype: String -} - -case class BigIntPlusArgInfo(default: Option[BigInt], docstring: String) extends PlusArgInfo[BigInt] { def doctype = "INT" } -case class StringPlusArgInfo(default: Option[String], docstring: String) extends PlusArgInfo[String] { def doctype = "STRING" } +@deprecated("This will be removed in Rocket Chip 2020.08", "Rocket Chip 2020.05") +case class PlusArgInfo(default: BigInt, docstring: String) + +/** Case class for PlusArg information + * + * @tparam A scala type of the PlusArg value + * @param default optional default value + * @param docstring text to include in the help + * @param doctype description of the Verilog type of the PlusArg value (e.g. STRING, INT) + */ +private case class PlusArgContainer[A](default: Option[A], docstring: String, doctype: String) class plusarg_reader(val format: String, val default: BigInt, val docstring: String, val width: Int) extends BlackBox(Map( "FORMAT" -> StringParam(format), @@ -47,7 +50,7 @@ object PlusArg * pass. */ def apply(name: String, default: BigInt = 0, docstring: String = "", width: Int = 32): UInt = { - PlusArgArtefacts.append(name, default, docstring) + PlusArgArtefacts.append(name, Some(default), docstring, "INT") Module(new plusarg_reader(name + "=%d", default, docstring, width)).io.out } @@ -56,34 +59,41 @@ object PlusArg * Default 0 will never assert. */ def timeout(name: String, default: BigInt = 0, docstring: String = "", width: Int = 32)(count: UInt) { - PlusArgArtefacts.append(name, default, docstring) + PlusArgArtefacts.append(name, Some(default), docstring, "INT") Module(new PlusArgTimeout(name + "=%d", default, docstring, width)).io.count := count } } object PlusArgArtefacts { - private var artefacts: Map[String, PlusArgInfo[_]] = Map.empty + private var artefacts: Map[String, PlusArgContainer[_]] = Map.empty /* Add a new PlusArg */ - def append(name: String, default: Option[BigInt], docstring: String): Unit = - artefacts = artefacts ++ Map(name -> BigIntPlusArgInfo(default, docstring)) - + @deprecated( + "Use `Some(BigInt)` to specify a `default` value. This will be removed in Rocket Chip 2020.08", + "Rocket Chip 2020.05" + ) def append(name: String, default: BigInt, docstring: String): Unit = - append(name, Some(default), docstring) - - def appendString(name: String, default: Option[String], docstring: String): Unit = - artefacts = artefacts ++ Map(name -> StringPlusArgInfo(default, docstring)) - - def appendString(name: String, default: String, docstring: String): Unit = - appendString(name, Some(default), docstring) + append(name, Some(default), docstring, "INT") + + /** Add a new PlusArg + * + * @tparam A scala type of the PlusArg value + * @param name name for the PlusArg + * @param default optional default value + * @param docstring text to include in the help + * @param doctype description of the Verilog type of the PlusArg value (e.g. STRING, INT) + */ + def append[A](name: String, default: Option[A], docstring: String, doctype: String): Unit = + artefacts = artefacts ++ Map(name -> PlusArgContainer[A](default, docstring, doctype)) /* From plus args, generate help text */ private def serializeHelp_cHeader(tab: String = ""): String = artefacts .map{ case(arg, info) => s"""|$tab+$arg=${info.doctype}\\n\\ |$tab${" "*20}${info.docstring}\\n\\ - |$tab${" "*22}(default=${info.default.getOrElse("NONE")})""".stripMargin }.toSeq - .mkString("\\n\\\n") ++ "\"" + |""".stripMargin ++ info.default.map{ case default => + s"$tab${" "*22}(default=${default})\\n\\\n"}.getOrElse("") + }.toSeq.mkString("\\n\\\n") ++ "\"" /* From plus args, generate a char array of their names */ private def serializeArray_cHeader(tab: String = ""): String = { From fc6ec5f823c2b4cd06f53cbfebcf88157ffada24 Mon Sep 17 00:00:00 2001 From: John Wright Date: Fri, 8 May 2020 14:18:33 -0700 Subject: [PATCH 3/5] make doctype have a default of INT --- src/main/scala/util/PlusArg.scala | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/scala/util/PlusArg.scala b/src/main/scala/util/PlusArg.scala index bb00793c3dc..43b87721f7d 100644 --- a/src/main/scala/util/PlusArg.scala +++ b/src/main/scala/util/PlusArg.scala @@ -50,7 +50,7 @@ object PlusArg * pass. */ def apply(name: String, default: BigInt = 0, docstring: String = "", width: Int = 32): UInt = { - PlusArgArtefacts.append(name, Some(default), docstring, "INT") + PlusArgArtefacts.append(name, Some(default), docstring) Module(new plusarg_reader(name + "=%d", default, docstring, width)).io.out } @@ -59,7 +59,7 @@ object PlusArg * Default 0 will never assert. */ def timeout(name: String, default: BigInt = 0, docstring: String = "", width: Int = 32)(count: UInt) { - PlusArgArtefacts.append(name, Some(default), docstring, "INT") + PlusArgArtefacts.append(name, Some(default), docstring) Module(new PlusArgTimeout(name + "=%d", default, docstring, width)).io.count := count } } @@ -73,7 +73,7 @@ object PlusArgArtefacts { "Rocket Chip 2020.05" ) def append(name: String, default: BigInt, docstring: String): Unit = - append(name, Some(default), docstring, "INT") + append(name, Some(default), docstring) /** Add a new PlusArg * @@ -83,7 +83,7 @@ object PlusArgArtefacts { * @param docstring text to include in the help * @param doctype description of the Verilog type of the PlusArg value (e.g. STRING, INT) */ - def append[A](name: String, default: Option[A], docstring: String, doctype: String): Unit = + def append[A](name: String, default: Option[A], docstring: String, doctype: String = "INT"): Unit = artefacts = artefacts ++ Map(name -> PlusArgContainer[A](default, docstring, doctype)) /* From plus args, generate help text */ From 0723715945cc7e3bdf1c62d8290c741778765c76 Mon Sep 17 00:00:00 2001 From: John Wright Date: Fri, 8 May 2020 14:52:35 -0700 Subject: [PATCH 4/5] Revert "make doctype have a default of INT" This reverts commit fc6ec5f823c2b4cd06f53cbfebcf88157ffada24. --- src/main/scala/util/PlusArg.scala | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/scala/util/PlusArg.scala b/src/main/scala/util/PlusArg.scala index 43b87721f7d..bb00793c3dc 100644 --- a/src/main/scala/util/PlusArg.scala +++ b/src/main/scala/util/PlusArg.scala @@ -50,7 +50,7 @@ object PlusArg * pass. */ def apply(name: String, default: BigInt = 0, docstring: String = "", width: Int = 32): UInt = { - PlusArgArtefacts.append(name, Some(default), docstring) + PlusArgArtefacts.append(name, Some(default), docstring, "INT") Module(new plusarg_reader(name + "=%d", default, docstring, width)).io.out } @@ -59,7 +59,7 @@ object PlusArg * Default 0 will never assert. */ def timeout(name: String, default: BigInt = 0, docstring: String = "", width: Int = 32)(count: UInt) { - PlusArgArtefacts.append(name, Some(default), docstring) + PlusArgArtefacts.append(name, Some(default), docstring, "INT") Module(new PlusArgTimeout(name + "=%d", default, docstring, width)).io.count := count } } @@ -73,7 +73,7 @@ object PlusArgArtefacts { "Rocket Chip 2020.05" ) def append(name: String, default: BigInt, docstring: String): Unit = - append(name, Some(default), docstring) + append(name, Some(default), docstring, "INT") /** Add a new PlusArg * @@ -83,7 +83,7 @@ object PlusArgArtefacts { * @param docstring text to include in the help * @param doctype description of the Verilog type of the PlusArg value (e.g. STRING, INT) */ - def append[A](name: String, default: Option[A], docstring: String, doctype: String = "INT"): Unit = + def append[A](name: String, default: Option[A], docstring: String, doctype: String): Unit = artefacts = artefacts ++ Map(name -> PlusArgContainer[A](default, docstring, doctype)) /* From plus args, generate help text */ From 17aeccf4dd8b338b63cc435d0ea2545efe052d24 Mon Sep 17 00:00:00 2001 From: John Wright Date: Fri, 8 May 2020 23:11:01 -0700 Subject: [PATCH 5/5] Add implicit doctype conversions. h/t @seldridge --- src/main/scala/util/PlusArg.scala | 39 +++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/src/main/scala/util/PlusArg.scala b/src/main/scala/util/PlusArg.scala index bb00793c3dc..5906a2d25da 100644 --- a/src/main/scala/util/PlusArg.scala +++ b/src/main/scala/util/PlusArg.scala @@ -18,6 +18,30 @@ case class PlusArgInfo(default: BigInt, docstring: String) */ private case class PlusArgContainer[A](default: Option[A], docstring: String, doctype: String) +/** Typeclass for converting a type to a doctype string + * @tparam A some type + */ +trait Doctypeable[A] { + + /** Return the doctype string for some option */ + def toDoctype(a: Option[A]): String + +} + +/** Object containing implementations of the Doctypeable typeclass */ +object Doctypes { + + /** Converts an Int => "INT" */ + implicit val intToDoctype = new Doctypeable[Int] { def toDoctype(a: Option[Int]) = "INT" } + + /** Converts a BigInt => "INT" */ + implicit val bigIntToDoctype = new Doctypeable[BigInt] { def toDoctype(a: Option[BigInt]) = "INT" } + + /** Converts a String => "STRING" */ + implicit val stringToDoctype = new Doctypeable[String] { def toDoctype(a: Option[String]) = "STRING" } + +} + class plusarg_reader(val format: String, val default: BigInt, val docstring: String, val width: Int) extends BlackBox(Map( "FORMAT" -> StringParam(format), "DEFAULT" -> IntParam(default), @@ -41,6 +65,8 @@ class PlusArgTimeout(val format: String, val default: BigInt, val docstring: Str } } +import Doctypes._ + object PlusArg { /** PlusArg("foo") will return 42.U if the simulation is run with +foo=42 @@ -50,7 +76,7 @@ object PlusArg * pass. */ def apply(name: String, default: BigInt = 0, docstring: String = "", width: Int = 32): UInt = { - PlusArgArtefacts.append(name, Some(default), docstring, "INT") + PlusArgArtefacts.append(name, Some(default), docstring) Module(new plusarg_reader(name + "=%d", default, docstring, width)).io.out } @@ -59,7 +85,7 @@ object PlusArg * Default 0 will never assert. */ def timeout(name: String, default: BigInt = 0, docstring: String = "", width: Int = 32)(count: UInt) { - PlusArgArtefacts.append(name, Some(default), docstring, "INT") + PlusArgArtefacts.append(name, Some(default), docstring) Module(new PlusArgTimeout(name + "=%d", default, docstring, width)).io.count := count } } @@ -72,8 +98,7 @@ object PlusArgArtefacts { "Use `Some(BigInt)` to specify a `default` value. This will be removed in Rocket Chip 2020.08", "Rocket Chip 2020.05" ) - def append(name: String, default: BigInt, docstring: String): Unit = - append(name, Some(default), docstring, "INT") + def append(name: String, default: BigInt, docstring: String): Unit = append(name, Some(default), docstring) /** Add a new PlusArg * @@ -81,10 +106,10 @@ object PlusArgArtefacts { * @param name name for the PlusArg * @param default optional default value * @param docstring text to include in the help - * @param doctype description of the Verilog type of the PlusArg value (e.g. STRING, INT) */ - def append[A](name: String, default: Option[A], docstring: String, doctype: String): Unit = - artefacts = artefacts ++ Map(name -> PlusArgContainer[A](default, docstring, doctype)) + def append[A : Doctypeable](name: String, default: Option[A], docstring: String): Unit = + artefacts = artefacts ++ + Map(name -> PlusArgContainer(default, docstring, implicitly[Doctypeable[A]].toDoctype(default))) /* From plus args, generate help text */ private def serializeHelp_cHeader(tab: String = ""): String = artefacts