Merge pull request #1192 from seldridge/auto-plusargs
Automatic PlusArg for emulator.cc
This commit is contained in:
commit
9a56221566
@ -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)
|
||||||
@ -110,7 +115,7 @@ int main(int argc, char** argv)
|
|||||||
#endif
|
#endif
|
||||||
char ** htif_argv = NULL;
|
char ** htif_argv = NULL;
|
||||||
int verilog_plusargs_legal = 1;
|
int verilog_plusargs_legal = 1;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
static struct option long_options[] = {
|
static struct option long_options[] = {
|
||||||
{"cycle-count", no_argument, 0, 'c' },
|
{"cycle-count", no_argument, 0, 'c' },
|
||||||
@ -174,7 +179,7 @@ int main(int argc, char** argv)
|
|||||||
else if (arg.substr(0, 12) == "+cycle-count")
|
else if (arg.substr(0, 12) == "+cycle-count")
|
||||||
c = 'c';
|
c = 'c';
|
||||||
// If we don't find a legacy '+' EMULATOR argument, it still could be
|
// If we don't find a legacy '+' EMULATOR argument, it still could be
|
||||||
// a VERILOG_PLUSARG and not an error.
|
// a VERILOG_PLUSARG and not an error.
|
||||||
else if (verilog_plusargs_legal) {
|
else if (verilog_plusargs_legal) {
|
||||||
const char ** plusarg = &verilog_plusargs[0];
|
const char ** plusarg = &verilog_plusargs[0];
|
||||||
int legal_verilog_plusarg = 0;
|
int legal_verilog_plusarg = 0;
|
||||||
@ -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;
|
||||||
|
@ -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)/$(PROJECT).$(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)
|
||||||
|
|
||||||
|
@ -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_cHeader)
|
||||||
println(outer.dts)
|
println(outer.dts)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -286,7 +286,7 @@ class Rocket(implicit p: Parameters) extends CoreModule()(p)
|
|||||||
alu.io.fn := ex_ctrl.alu_fn
|
alu.io.fn := ex_ctrl.alu_fn
|
||||||
alu.io.in2 := ex_op2.asUInt
|
alu.io.in2 := ex_op2.asUInt
|
||||||
alu.io.in1 := ex_op1.asUInt
|
alu.io.in1 := ex_op1.asUInt
|
||||||
|
|
||||||
// multiplier and divider
|
// multiplier and divider
|
||||||
val div = Module(new MulDiv(mulDivParams, width = xLen))
|
val div = Module(new MulDiv(mulDivParams, width = xLen))
|
||||||
div.io.req.valid := ex_reg_valid && ex_ctrl.div
|
div.io.req.valid := ex_reg_valid && ex_ctrl.div
|
||||||
@ -525,7 +525,7 @@ class Rocket(implicit p: Parameters) extends CoreModule()(p)
|
|||||||
|
|
||||||
val wb_valid = wb_reg_valid && !replay_wb && !wb_xcpt
|
val wb_valid = wb_reg_valid && !replay_wb && !wb_xcpt
|
||||||
val wb_wen = wb_valid && wb_ctrl.wxd
|
val wb_wen = wb_valid && wb_ctrl.wxd
|
||||||
val rf_wen = wb_wen || ll_wen
|
val rf_wen = wb_wen || ll_wen
|
||||||
val rf_waddr = Mux(ll_wen, ll_waddr, wb_waddr)
|
val rf_waddr = Mux(ll_wen, ll_waddr, wb_waddr)
|
||||||
val rf_wdata = Mux(dmem_resp_valid && dmem_resp_xpu, io.dmem.resp.bits.data,
|
val rf_wdata = Mux(dmem_resp_valid && dmem_resp_xpu, io.dmem.resp.bits.data,
|
||||||
Mux(ll_wen, ll_wdata,
|
Mux(ll_wen, ll_wdata,
|
||||||
@ -728,7 +728,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.")
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
@ -5,7 +5,7 @@ package freechips.rocketchip.unittest
|
|||||||
import Chisel._
|
import Chisel._
|
||||||
import chisel3.experimental.MultiIOModule
|
import chisel3.experimental.MultiIOModule
|
||||||
import freechips.rocketchip.config._
|
import freechips.rocketchip.config._
|
||||||
import freechips.rocketchip.util.SimpleTimer
|
import freechips.rocketchip.util._
|
||||||
|
|
||||||
trait UnitTestIO {
|
trait UnitTestIO {
|
||||||
val finished = Bool(OUTPUT)
|
val finished = Bool(OUTPUT)
|
||||||
@ -22,6 +22,7 @@ trait UnitTestLegacyModule extends HasUnitTestIO {
|
|||||||
|
|
||||||
trait UnitTestModule extends MultiIOModule with HasUnitTestIO {
|
trait UnitTestModule extends MultiIOModule with HasUnitTestIO {
|
||||||
val io = IO(new Bundle with UnitTestIO)
|
val io = IO(new Bundle with UnitTestIO)
|
||||||
|
ElaborationArtefacts.add("plusArgs", PlusArgArtefacts.serialize_cHeader)
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class UnitTest(val timeout: Int = 4096) extends Module with UnitTestLegacyModule {
|
abstract class UnitTest(val timeout: Int = 4096) extends Module with UnitTestLegacyModule {
|
||||||
|
@ -74,7 +74,7 @@ trait HasGeneratorUtilities {
|
|||||||
/** Standardized command line interface for Scala entry point */
|
/** Standardized command line interface for Scala entry point */
|
||||||
trait GeneratorApp extends App with HasGeneratorUtilities {
|
trait GeneratorApp extends App with HasGeneratorUtilities {
|
||||||
lazy val names: ParsedInputNames = {
|
lazy val names: ParsedInputNames = {
|
||||||
require(args.size == 5, "Usage: sbt> " +
|
require(args.size == 5, "Usage: sbt> " +
|
||||||
"run TargetDir TopModuleProjectName TopModuleName " +
|
"run TargetDir TopModuleProjectName TopModuleName " +
|
||||||
"ConfigProjectName ConfigNameString")
|
"ConfigProjectName ConfigNameString")
|
||||||
ParsedInputNames(
|
ParsedInputNames(
|
||||||
@ -115,7 +115,7 @@ trait GeneratorApp extends App with HasGeneratorUtilities {
|
|||||||
TestGeneration.addSuite(DefaultTestSuites.groundtest64("p"))
|
TestGeneration.addSuite(DefaultTestSuites.groundtest64("p"))
|
||||||
TestGeneration.addSuite(DefaultTestSuites.emptyBmarks)
|
TestGeneration.addSuite(DefaultTestSuites.emptyBmarks)
|
||||||
TestGeneration.addSuite(DefaultTestSuites.singleRegression)
|
TestGeneration.addSuite(DefaultTestSuites.singleRegression)
|
||||||
}
|
}
|
||||||
|
|
||||||
def generateROMs {
|
def generateROMs {
|
||||||
writeOutputFile(td, s"$longName.rom.conf", enumerateROMs(circuit))
|
writeOutputFile(td, s"$longName.rom.conf", enumerateROMs(circuit))
|
||||||
@ -124,7 +124,7 @@ trait GeneratorApp extends App with HasGeneratorUtilities {
|
|||||||
/** Output files created as a side-effect of elaboration */
|
/** Output files created as a side-effect of elaboration */
|
||||||
def generateArtefacts {
|
def generateArtefacts {
|
||||||
ElaborationArtefacts.files.foreach { case (extension, contents) =>
|
ElaborationArtefacts.files.foreach { case (extension, contents) =>
|
||||||
writeOutputFile(td, s"${names.configs}.${extension}", contents ())
|
writeOutputFile(td, s"$longName.$extension", contents ())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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_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
|
||||||
|
.mkString("\\n\\\n") ++ "\""
|
||||||
|
|
||||||
|
/* From plus args, generate a char array of their names */
|
||||||
|
private def serializeArray_cHeader(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_cHeader(): String =
|
||||||
|
s"""|#define PLUSARG_USAGE_OPTIONS \"EMULATOR VERILOG PLUSARGS\\n\\
|
||||||
|
|${serializeHelp_cHeader(" "*7)}
|
||||||
|
|${serializeArray_cHeader()}
|
||||||
|
|""".stripMargin
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user