2017-05-19 07:49:59 +02:00
|
|
|
// See LICENSE.SiFive for license details.
|
|
|
|
|
2017-07-07 19:48:16 +02:00
|
|
|
package freechips.rocketchip.util
|
|
|
|
|
2017-05-19 07:49:59 +02:00
|
|
|
import Chisel._
|
|
|
|
|
2018-01-15 20:21:09 +01:00
|
|
|
case class PlusArgInfo(default: Int, docstring: String)
|
|
|
|
|
2017-06-06 01:16:52 +02:00
|
|
|
class plusarg_reader(val format: String, val default: Int, val docstring: String) extends BlackBox(Map(
|
2017-05-19 07:49:59 +02:00
|
|
|
"FORMAT" -> chisel3.core.StringParam(format),
|
|
|
|
"DEFAULT" -> chisel3.core.IntParam(default))) {
|
|
|
|
val io = new Bundle {
|
|
|
|
val out = UInt(OUTPUT, width = 32)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
object PlusArg
|
|
|
|
{
|
2017-06-06 01:16:52 +02:00
|
|
|
// PlusArg("foo") will return 42.U if the simulation is run with +foo=42
|
2017-05-19 07:49:59 +02:00
|
|
|
// Do not use this as an initial register value. The value is set in an
|
|
|
|
// initial block and thus accessing it from another initial is racey.
|
2017-06-06 01:18:57 +02:00
|
|
|
// Add a docstring to document the arg, which can be dumped in an elaboration
|
2017-06-06 01:16:52 +02:00
|
|
|
// pass.
|
|
|
|
|
2018-01-15 20:21:09 +01:00
|
|
|
def apply(name: String, default: Int = 0, docstring: String = ""): UInt = {
|
|
|
|
PlusArgArtefacts.append(name, default, docstring)
|
2017-06-06 01:16:52 +02:00
|
|
|
Module(new plusarg_reader(name + "=%d", default, docstring)).io.out
|
2018-01-15 20:21:09 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
object PlusArgArtefacts {
|
|
|
|
private var artefacts: Map[String, PlusArgInfo] = Map.empty
|
|
|
|
|
|
|
|
/* Add a new PlusArg */
|
|
|
|
def append(name: String, default: Int, docstring: String): Unit =
|
|
|
|
artefacts = artefacts ++ Map(name -> PlusArgInfo(default, docstring))
|
|
|
|
|
|
|
|
/* From plus args, generate help text */
|
2018-01-15 23:00:12 +01:00
|
|
|
private def serializeHelp_cHeader(tab: String = ""): String = artefacts
|
2018-01-15 20:21:09 +01:00
|
|
|
.map{ case(arg, PlusArgInfo(default, docstring)) =>
|
|
|
|
s"""|$tab+$arg=INT\\n\\
|
|
|
|
|$tab${" "*20}$docstring\\n\\
|
|
|
|
|$tab${" "*22}(default=$default)""".stripMargin }.toSeq
|
|
|
|
.mkString("\\n\\\n") ++ "\""
|
|
|
|
|
|
|
|
/* From plus args, generate a char array of their names */
|
2018-01-15 23:00:12 +01:00
|
|
|
private def serializeArray_cHeader(tab: String = ""): String = {
|
2018-01-15 20:21:09 +01:00
|
|
|
val prettyTab = tab + " " * 44 // Length of 'static const ...'
|
|
|
|
s"${tab}static const char * verilog_plusargs [] = {\\\n" ++
|
|
|
|
artefacts
|
|
|
|
.map{ case(arg, _) => s"""$prettyTab"$arg",\\\n""" }
|
|
|
|
.mkString("")++
|
|
|
|
s"${prettyTab}0};"
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Generate C code to be included in emulator.cc that helps with
|
|
|
|
* argument parsing based on available Verilog PlusArgs */
|
2018-01-15 23:00:12 +01:00
|
|
|
def serialize_cHeader(): String =
|
2018-01-15 20:21:09 +01:00
|
|
|
s"""|#define PLUSARG_USAGE_OPTIONS \"EMULATOR VERILOG PLUSARGS\\n\\
|
2018-01-15 23:00:12 +01:00
|
|
|
|${serializeHelp_cHeader(" "*7)}
|
|
|
|
|${serializeArray_cHeader()}
|
2018-01-15 20:21:09 +01:00
|
|
|
|""".stripMargin
|
2017-05-19 07:49:59 +02:00
|
|
|
}
|