1
0

Link PlusArg to emulator command line options

- adds a mutable singleton (PlusArgArtefacts) to store information
  about Rocket PlusArgs
- adds methods to PlusArgArtefacts to emit C snippets that are
  consumed by emulator.cc for correct argument parsing and help text
  generation
- emits snippets in $(CONFIG).plusArgs via BaseCoreplex-set
  ElaborationArtefacts
- modify emulator/Makefrag-verilator to include $(CONFIG).plusArgs
- cleanup help text (docstring) for existing PlusArgs

Signed-off-by: Schuyler Eldridge <schuyler.eldridge@gmail.com>
This commit is contained in:
Schuyler Eldridge 2018-01-15 14:21:09 -05:00
parent 8799508b1f
commit e52d52ae99
6 changed files with 71 additions and 25 deletions

View File

@ -15,12 +15,20 @@
#include <unistd.h> #include <unistd.h>
#include <getopt.h> #include <getopt.h>
//TODO: GENERATE THESE AUTOMATICALLY! // For option parsing, which is split across this file, Verilog, and
static const char * verilog_plusargs [] = { "max-core-cycles", // FESVR's HTIF, a few external files must be pulled in. The list of
"jtag_rbb_enable", // files and what they provide is enumerated:
"tilelink_timeout", //
0}; // $RISCV/include/fesvr/htif.h:
// defines:
// - HTIF_USAGE_OPTIONS
// - HTIF_LONG_OPTIONS_OPTIND
// - HTIF_LONG_OPTIONS
// $(ROCKETCHIP_DIR)/generated-src(-debug)?/$(CONFIG).plusArgs:
// defines:
// - PLUSARG_USAGE_OPTIONS
// variables:
// - static const char * verilog_plusargs
extern dtm_t* dtm; extern dtm_t* dtm;
extern remote_bitbang_t * jtag; extern remote_bitbang_t * jtag;
@ -66,7 +74,7 @@ EMULATOR OPTIONS\n\
#if VM_TRACE == 0 #if VM_TRACE == 0
fputs("\ fputs("\
\n\ \n\
EMULATOR OPTIONS (only supported in debug build -- try `make debug`)\n", EMULATOR DEBUG OPTIONS (only supported in debug build -- try `make debug`)\n",
stdout); stdout);
#endif #endif
fputs("\ fputs("\
@ -74,14 +82,7 @@ EMULATOR OPTIONS (only supported in debug build -- try `make debug`)\n",
-x, --dump-start=CYCLE Start VCD tracing at CYCLE\n\ -x, --dump-start=CYCLE Start VCD tracing at CYCLE\n\
+dump-start\n\ +dump-start\n\
", stdout); ", stdout);
fputs("\ fputs("\n" PLUSARG_USAGE_OPTIONS, stdout);
\n\
VERILOG PLUSARGS (accepted by the Verilog itself):\n" , stdout);
const char ** vpa = &verilog_plusargs[0];
while (*vpa) {
fprintf(stdout, " +%s=...\n", *vpa);
vpa ++;
}
fputs("\n" HTIF_USAGE_OPTIONS, stdout); fputs("\n" HTIF_USAGE_OPTIONS, stdout);
printf("\n" printf("\n"
"EXAMPLES\n" "EXAMPLES\n"
@ -95,7 +96,11 @@ VERILOG PLUSARGS (accepted by the Verilog itself):\n" , stdout);
#endif #endif
" - run an ELF (you wrote, called 'hello') using the proxy kernel:\n" " - run an ELF (you wrote, called 'hello') using the proxy kernel:\n"
" %s pk hello\n", " %s pk hello\n",
program_name, program_name, program_name, program_name); program_name, program_name, program_name
#if VM_TRACE
, program_name
#endif
);
} }
int main(int argc, char** argv) int main(int argc, char** argv)
@ -204,7 +209,8 @@ int main(int argc, char** argv)
} }
htif_option++; htif_option++;
} }
std::cerr << argv[0] << ": invalid HTIF legacy plus-arg \"" << arg << "\"\n"; std::cerr << argv[0] << ": invalid plus-arg (Verilog or HTIF) \""
<< arg << "\"\n";
c = '?'; c = '?';
} }
goto retry; goto retry;

View File

@ -60,7 +60,7 @@ VERILATOR_FLAGS := --top-module $(MODEL) \
--output-split-cfuncs 20000 \ --output-split-cfuncs 20000 \
-Wno-STMTDLY --x-assign unique \ -Wno-STMTDLY --x-assign unique \
-I$(base_dir)/vsrc \ -I$(base_dir)/vsrc \
-O3 -CFLAGS "$(CXXFLAGS) -DVERILATOR -DTEST_HARNESS=V$(MODEL) -include $(base_dir)/csrc/verilator.h" -O3 -CFLAGS "$(CXXFLAGS) -DVERILATOR -DTEST_HARNESS=V$(MODEL) -include $(base_dir)/csrc/verilator.h -include $(generated_dir)/$(CONFIG).plusArgs"
cppfiles = $(addprefix $(base_dir)/csrc/, $(addsuffix .cc, $(CXXSRCS))) cppfiles = $(addprefix $(base_dir)/csrc/, $(addsuffix .cc, $(CXXSRCS)))
headers = $(wildcard $(base_dir)/csrc/*.h) headers = $(wildcard $(base_dir)/csrc/*.h)

View File

@ -21,6 +21,7 @@ abstract class BareCoreplexModule[+L <: BareCoreplex](_outer: L) extends LazyMod
ElaborationArtefacts.add("graphml", outer.graphML) ElaborationArtefacts.add("graphml", outer.graphML)
ElaborationArtefacts.add("dts", outer.dts) ElaborationArtefacts.add("dts", outer.dts)
ElaborationArtefacts.add("json", outer.json) ElaborationArtefacts.add("json", outer.json)
ElaborationArtefacts.add("plusArgs", PlusArgArtefacts.serialize)
println(outer.dts) println(outer.dts)
} }

View File

@ -724,7 +724,7 @@ class Rocket(implicit p: Parameters) extends CoreModule()(p)
val max_core_cycles = PlusArg("max-core-cycles", val max_core_cycles = PlusArg("max-core-cycles",
default = 0, default = 0,
docstring = "Maximum Core Clock cycles simulation may run before timeout. Ignored if 0 (Default).") docstring = "Kill the emulation after INT rdtime cycles. Off if 0.")
when (max_core_cycles > UInt(0)) { when (max_core_cycles > UInt(0)) {
assert (csr.io.time < max_core_cycles, "Maximum Core Cycles reached.") assert (csr.io.time < max_core_cycles, "Maximum Core Cycles reached.")
} }

View File

@ -442,7 +442,8 @@ class TLMonitor(args: TLMonitorArgs) extends TLMonitorBase(args)
inflight := (inflight | a_set) & ~d_clr inflight := (inflight | a_set) & ~d_clr
val watchdog = RegInit(UInt(0, width = 32)) val watchdog = RegInit(UInt(0, width = 32))
val limit = PlusArg("tilelink_timeout") val limit = PlusArg("tilelink_timeout",
docstring="Kill emulation after INT waiting TileLink cycles. Off if 0.")
assert (!inflight.orR || limit === UInt(0) || watchdog < limit, "TileLink timeout expired" + extra) assert (!inflight.orR || limit === UInt(0) || watchdog < limit, "TileLink timeout expired" + extra)
watchdog := watchdog + UInt(1) watchdog := watchdog + UInt(1)

View File

@ -4,6 +4,8 @@ package freechips.rocketchip.util
import Chisel._ import Chisel._
case class PlusArgInfo(default: Int, docstring: String)
class plusarg_reader(val format: String, val default: Int, val docstring: String) extends BlackBox(Map( class plusarg_reader(val format: String, val default: Int, val docstring: String) extends BlackBox(Map(
"FORMAT" -> chisel3.core.StringParam(format), "FORMAT" -> chisel3.core.StringParam(format),
"DEFAULT" -> chisel3.core.IntParam(default))) { "DEFAULT" -> chisel3.core.IntParam(default))) {
@ -20,6 +22,42 @@ object PlusArg
// Add a docstring to document the arg, which can be dumped in an elaboration // Add a docstring to document the arg, which can be dumped in an elaboration
// pass. // pass.
def apply(name: String, default: Int = 0, docstring: String = ""): UInt = def apply(name: String, default: Int = 0, docstring: String = ""): UInt = {
PlusArgArtefacts.append(name, default, docstring)
Module(new plusarg_reader(name + "=%d", default, docstring)).io.out Module(new plusarg_reader(name + "=%d", default, docstring)).io.out
}
}
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 */
private def serializeHelp(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
.mkString("\\n\\\n") ++ "\""
/* From plus args, generate a char array of their names */
private def serializeArray(tab: String = ""): String = {
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 */
def serialize(): String =
s"""|#define PLUSARG_USAGE_OPTIONS \"EMULATOR VERILOG PLUSARGS\\n\\
|${serializeHelp(" "*7)}
|${serializeArray()}
|""".stripMargin
} }