Merge branch 'dev' of github.com:ucb-bar/chipyard into sodor-integrate

This commit is contained in:
Zitao Fang
2020-09-06 23:09:50 -07:00
56 changed files with 1071 additions and 570 deletions

View File

@@ -82,7 +82,12 @@ search
submodules=("coremark" "firemarshal" "nvdla-workload" "spec2017") submodules=("coremark" "firemarshal" "nvdla-workload" "spec2017")
dir="software" dir="software"
branches=("master") if [ "$CIRCLE_BRANCH" == "master" ] || [ "$CIRCLE_BRANCH" == "dev" ]
then
branches=("master")
else
branches=("master" "dev")
fi
search search
submodules=("DRAMSim2" "axe" "barstools" "chisel-testers" "dsptools" "firrtl-interpreter" "torture" "treadle") submodules=("DRAMSim2" "axe" "barstools" "chisel-testers" "dsptools" "firrtl-interpreter" "torture" "treadle")

View File

@@ -6,7 +6,7 @@ version: 2.1
parameters: parameters:
tools-cache-version: tools-cache-version:
type: string type: string
default: "v5" default: "v6"
# default execution env.s # default execution env.s
executors: executors:
@@ -199,6 +199,11 @@ jobs:
steps: steps:
- prepare-rtl: - prepare-rtl:
project-key: "chipyard-rocket" project-key: "chipyard-rocket"
prepare-chipyard-dmirocket:
executor: main-env
steps:
- prepare-rtl:
project-key: "chipyard-dmirocket"
prepare-chipyard-sha3: prepare-chipyard-sha3:
executor: main-env executor: main-env
steps: steps:
@@ -225,11 +230,6 @@ jobs:
steps: steps:
- prepare-rtl: - prepare-rtl:
project-key: "chipyard-boom" project-key: "chipyard-boom"
prepare-rocketchip:
executor: main-env
steps:
- prepare-rtl:
project-key: "rocketchip"
prepare-chipyard-blkdev: prepare-chipyard-blkdev:
executor: main-env executor: main-env
steps: steps:
@@ -297,6 +297,11 @@ jobs:
steps: steps:
- run-tests: - run-tests:
project-key: "chipyard-rocket" project-key: "chipyard-rocket"
chipyard-dmirocket-run-tests:
executor: main-env
steps:
- run-tests:
project-key: "chipyard-dmirocket"
chipyard-sha3-run-tests: chipyard-sha3-run-tests:
executor: main-env executor: main-env
steps: steps:
@@ -323,11 +328,6 @@ jobs:
steps: steps:
- run-tests: - run-tests:
project-key: "chipyard-boom" project-key: "chipyard-boom"
rocketchip-run-tests:
executor: main-env
steps:
- run-tests:
project-key: "rocketchip"
chipyard-hwacha-run-tests: chipyard-hwacha-run-tests:
executor: main-env executor: main-env
steps: steps:
@@ -451,6 +451,11 @@ workflows:
- install-riscv-toolchain - install-riscv-toolchain
- install-verilator - install-verilator
- prepare-chipyard-dmirocket:
requires:
- install-riscv-toolchain
- install-verilator
- prepare-chipyard-sha3: - prepare-chipyard-sha3:
requires: requires:
- install-riscv-toolchain - install-riscv-toolchain
@@ -476,11 +481,6 @@ workflows:
- install-riscv-toolchain - install-riscv-toolchain
- install-verilator - install-verilator
- prepare-rocketchip:
requires:
- install-riscv-toolchain
- install-verilator
- prepare-chipyard-blkdev: - prepare-chipyard-blkdev:
requires: requires:
- install-riscv-toolchain - install-riscv-toolchain
@@ -547,6 +547,10 @@ workflows:
requires: requires:
- prepare-chipyard-rocket - prepare-chipyard-rocket
- chipyard-dmirocket-run-tests:
requires:
- prepare-chipyard-dmirocket
- chipyard-sha3-run-tests: - chipyard-sha3-run-tests:
requires: requires:
- prepare-chipyard-sha3 - prepare-chipyard-sha3
@@ -567,10 +571,6 @@ workflows:
requires: requires:
- prepare-chipyard-boom - prepare-chipyard-boom
- rocketchip-run-tests:
requires:
- prepare-rocketchip
- chipyard-hwacha-run-tests: - chipyard-hwacha-run-tests:
requires: requires:
- prepare-chipyard-hwacha - prepare-chipyard-hwacha

View File

@@ -48,6 +48,7 @@ LOCAL_FIRESIM_DIR=$LOCAL_CHIPYARD_DIR/sims/firesim/sim
# key value store to get the build strings # key value store to get the build strings
declare -A mapping declare -A mapping
mapping["chipyard-rocket"]="" mapping["chipyard-rocket"]=""
mapping["chipyard-dmirocket"]=" CONFIG=dmiRocketConfig"
mapping["chipyard-sha3"]=" CONFIG=Sha3RocketConfig" mapping["chipyard-sha3"]=" CONFIG=Sha3RocketConfig"
mapping["chipyard-streaming-fir"]=" CONFIG=StreamingFIRRocketConfig" mapping["chipyard-streaming-fir"]=" CONFIG=StreamingFIRRocketConfig"
mapping["chipyard-streaming-passthrough"]=" CONFIG=StreamingPassthroughRocketConfig" mapping["chipyard-streaming-passthrough"]=" CONFIG=StreamingPassthroughRocketConfig"

View File

@@ -59,7 +59,7 @@ run "export RISCV=\"$TOOLS_DIR\"; \
export VERILATOR_ROOT=\"$REMOTE_VERILATOR_DIR\"; \ export VERILATOR_ROOT=\"$REMOTE_VERILATOR_DIR\"; \
export COURSIER_CACHE=\"$REMOTE_WORK_DIR/.coursier-cache\"; \ export COURSIER_CACHE=\"$REMOTE_WORK_DIR/.coursier-cache\"; \
make -C $REMOTE_SIM_DIR clean; \ make -C $REMOTE_SIM_DIR clean; \
make -j$REMOTE_MAKE_NPROC -C $REMOTE_SIM_DIR JAVA_ARGS=\"$REMOTE_JAVA_ARGS\" ${mapping[$1]}" make -j$REMOTE_MAKE_NPROC -C $REMOTE_SIM_DIR FIRRTL_LOGLEVEL=info JAVA_ARGS=\"$REMOTE_JAVA_ARGS\" ${mapping[$1]}"
run "rm -rf $REMOTE_CHIPYARD_DIR/project" run "rm -rf $REMOTE_CHIPYARD_DIR/project"
# copy back the final build # copy back the final build

View File

@@ -32,6 +32,9 @@ case $1 in
chipyard-rocket) chipyard-rocket)
run_bmark ${mapping[$1]} run_bmark ${mapping[$1]}
;; ;;
chipyard-dmirocket)
run_bmark ${mapping[$1]}
;;
chipyard-boom) chipyard-boom)
run_bmark ${mapping[$1]} run_bmark ${mapping[$1]}
;; ;;

1
.gitignore vendored
View File

@@ -6,6 +6,7 @@ target
*.stamp *.stamp
*.vcd *.vcd
*.swp *.swp
*.swo
*.log *.log
*# *#
*~ *~

View File

@@ -3,22 +3,49 @@
######################################################################################### #########################################################################################
SHELL=/bin/bash SHELL=/bin/bash
ifndef RISCV ifndef RISCV
$(error RISCV is unset. You must set RISCV yourself, or through the Chipyard auto-generated env file) $(error RISCV is unset. You must set RISCV yourself, or through the Chipyard auto-generated env file)
else else
$(info Running with RISCV=$(RISCV)) $(info Running with RISCV=$(RISCV))
endif endif
#########################################################################################
# specify user-interface variables
#########################################################################################
HELP_COMPILATION_VARIABLES += \
" EXTRA_GENERATOR_REQS = additional make requirements needed for the main generator" \
" EXTRA_SIM_CXXFLAGS = additional CXXFLAGS for building simulators" \
" EXTRA_SIM_LDFLAGS = additional LDFLAGS for building simulators" \
" EXTRA_SIM_SOURCES = additional simulation sources needed for simulator" \
" EXTRA_SIM_REQS = additional make requirements to build the simulator"
EXTRA_GENERATOR_REQS ?=
EXTRA_SIM_CXXFLAGS ?=
EXTRA_SIM_LDFLAGS ?=
EXTRA_SIM_SOURCES ?=
EXTRA_SIM_REQS ?=
#----------------------------------------------------------------------------
HELP_SIMULATION_VARIABLES += \
" EXTRA_SIM_FLAGS = additional runtime simulation flags (passed within +permissive)" \
" NUMACTL = set to '1' to wrap simulator in the appropriate numactl command"
EXTRA_SIM_FLAGS ?=
NUMACTL ?= 0
NUMA_PREFIX = $(if $(filter $(NUMACTL),0),,$(shell $(base_dir)/scripts/numa_prefix))
#----------------------------------------------------------------------------
HELP_COMMANDS += \
" run-binary = run [./$(shell basename $(sim))] and log instructions to file" \
" run-binary-fast = run [./$(shell basename $(sim))] and don't log instructions" \
" run-binary-debug = run [./$(shell basename $(sim_debug))] and log instructions and waveform to files" \
" verilog = generate intermediate verilog files from chisel elaboration and firrtl passes" \
" run-tests = run all assembly and benchmark tests"
######################################################################################### #########################################################################################
# extra make variables/rules from subprojects # include additional subproject make fragments
# # see HELP_COMPILATION_VARIABLES
# EXTRA_GENERATOR_REQS - requirements needed for the main generator
# EXTRA_SIM_FLAGS - runtime simulation flags
# EXTRA_SIM_CC_FLAGS - cc flags for simulators
# EXTRA_SIM_SOURCES - simulation sources needed for simulator
# EXTRA_SIM_REQS - requirements to build the simulator
######################################################################################### #########################################################################################
include $(base_dir)/generators/ariane/ariane.mk include $(base_dir)/generators/ariane/ariane.mk
include $(base_dir)/generators/tracegen/tracegen.mk include $(base_dir)/generators/tracegen/tracegen.mk
@@ -35,7 +62,8 @@ SOURCE_DIRS = $(addprefix $(base_dir)/,generators sims/firesim/sim tools/barstoo
SCALA_SOURCES = $(call lookup_srcs,$(SOURCE_DIRS),scala) SCALA_SOURCES = $(call lookup_srcs,$(SOURCE_DIRS),scala)
VLOG_SOURCES = $(call lookup_srcs,$(SOURCE_DIRS),sv) $(call lookup_srcs,$(SOURCE_DIRS),v) VLOG_SOURCES = $(call lookup_srcs,$(SOURCE_DIRS),sv) $(call lookup_srcs,$(SOURCE_DIRS),v)
# This assumes no SBT meta-build sources # This assumes no SBT meta-build sources
SBT_SOURCES = $(call lookup_srcs,$(base_dir),sbt) SBT_SOURCE_DIRS = $(addprefix $(base_dir)/,generators sims/firesim/sim tools)
SBT_SOURCES = $(call lookup_srcs,$(SBT_SOURCE_DIRS),sbt) $(base_dir)/build.sbt $(base_dir)/project/plugins.sbt
######################################################################################### #########################################################################################
# jar creation variables and rules # jar creation variables and rules
@@ -55,7 +83,6 @@ $(FIRRTL_TEST_JAR): $(call lookup_srcs,$(CHIPYARD_FIRRTL_DIR),scala)
cp -p $(CHIPYARD_FIRRTL_DIR)/utils/bin/firrtl-test.jar $@ cp -p $(CHIPYARD_FIRRTL_DIR)/utils/bin/firrtl-test.jar $@
touch $@ touch $@
######################################################################################### #########################################################################################
# Bloop Project Definitions # Bloop Project Definitions
######################################################################################### #########################################################################################
@@ -140,20 +167,18 @@ verilog: $(sim_vsrcs)
# helper rules to run simulations # helper rules to run simulations
######################################################################################### #########################################################################################
.PHONY: run-binary run-binary-fast run-binary-debug run-fast .PHONY: run-binary run-binary-fast run-binary-debug run-fast
# run normal binary with hardware-logged insn dissassembly
run-binary: $(output_dir) $(sim) run-binary: $(output_dir) $(sim)
(set -o pipefail && $(sim) $(PERMISSIVE_ON) $(SIM_FLAGS) $(EXTRA_SIM_FLAGS) $(SEED_FLAG) $(VERBOSE_FLAGS) $(PERMISSIVE_OFF) $(BINARY) </dev/null 2> >(spike-dasm > $(sim_out_name).out) | tee $(sim_out_name).log) (set -o pipefail && $(NUMA_PREFIX) $(sim) $(PERMISSIVE_ON) $(SIM_FLAGS) $(EXTRA_SIM_FLAGS) $(SEED_FLAG) $(VERBOSE_FLAGS) $(PERMISSIVE_OFF) $(BINARY) </dev/null 2> >(spike-dasm > $(sim_out_name).out) | tee $(sim_out_name).log)
######################################################################################### # run simulator as fast as possible (no insn disassembly)
# helper rules to run simulator as fast as possible
#########################################################################################
run-binary-fast: $(output_dir) $(sim) run-binary-fast: $(output_dir) $(sim)
(set -o pipefail && $(sim) $(PERMISSIVE_ON) $(SIM_FLAGS) $(EXTRA_SIM_FLAGS) $(SEED_FLAG) $(PERMISSIVE_OFF) $(BINARY) </dev/null | tee $(sim_out_name).log) (set -o pipefail && $(NUMA_PREFIX) $(sim) $(PERMISSIVE_ON) $(SIM_FLAGS) $(EXTRA_SIM_FLAGS) $(SEED_FLAG) $(PERMISSIVE_OFF) $(BINARY) </dev/null | tee $(sim_out_name).log)
######################################################################################### # run simulator with as much debug info as possible
# helper rules to run simulator with as much debug info as possible
#########################################################################################
run-binary-debug: $(output_dir) $(sim_debug) run-binary-debug: $(output_dir) $(sim_debug)
(set -o pipefail && $(sim_debug) $(PERMISSIVE_ON) $(SIM_FLAGS) $(EXTRA_SIM_FLAGS) $(SEED_FLAG) $(VERBOSE_FLAGS) $(WAVEFORM_FLAG) $(PERMISSIVE_OFF) $(BINARY) </dev/null 2> >(spike-dasm > $(sim_out_name).out) | tee $(sim_out_name).log) (set -o pipefail && $(NUMA_PREFIX) $(sim_debug) $(PERMISSIVE_ON) $(SIM_FLAGS) $(EXTRA_SIM_FLAGS) $(SEED_FLAG) $(VERBOSE_FLAGS) $(WAVEFORM_FLAG) $(PERMISSIVE_OFF) $(BINARY) </dev/null 2> >(spike-dasm > $(sim_out_name).out) | tee $(sim_out_name).log)
run-fast: run-asm-tests-fast run-bmark-tests-fast run-fast: run-asm-tests-fast run-bmark-tests-fast
@@ -189,10 +214,10 @@ $(output_dir)/%: $(RISCV)/riscv64-unknown-elf/share/riscv-tests/isa/% $(output_d
ln -sf $< $@ ln -sf $< $@
$(output_dir)/%.run: $(output_dir)/% $(sim) $(output_dir)/%.run: $(output_dir)/% $(sim)
(set -o pipefail && $(sim) $(PERMISSIVE_ON) $(SIM_FLAGS) $(EXTRA_SIM_FLAGS) $(SEED_FLAG) $(PERMISSIVE_OFF) $< </dev/null | tee $<.log) && touch $@ (set -o pipefail && $(NUMA_PREFIX) $(sim) $(PERMISSIVE_ON) $(SIM_FLAGS) $(EXTRA_SIM_FLAGS) $(SEED_FLAG) $(PERMISSIVE_OFF) $< </dev/null | tee $<.log) && touch $@
$(output_dir)/%.out: $(output_dir)/% $(sim) $(output_dir)/%.out: $(output_dir)/% $(sim)
(set -o pipefail && $(sim) $(PERMISSIVE_ON) $(SIM_FLAGS) $(EXTRA_SIM_FLAGS) $(SEED_FLAG) $(VERBOSE_FLAGS) $(PERMISSIVE_OFF) $< </dev/null 2> >(spike-dasm > $@) | tee $<.log) (set -o pipefail && $(NUMA_PREFIX) $(sim) $(PERMISSIVE_ON) $(SIM_FLAGS) $(EXTRA_SIM_FLAGS) $(SEED_FLAG) $(VERBOSE_FLAGS) $(PERMISSIVE_OFF) $< </dev/null 2> >(spike-dasm > $@) | tee $<.log)
######################################################################################### #########################################################################################
# include build/project specific makefrags made from the generator # include build/project specific makefrags made from the generator
@@ -211,6 +236,13 @@ dramsim_lib = $(dramsim_dir)/libdramsim.a
$(dramsim_lib): $(dramsim_lib):
$(MAKE) -C $(dramsim_dir) $(notdir $@) $(MAKE) -C $(dramsim_dir) $(notdir $@)
#########################################################################################
# print help text
#########################################################################################
.PHONY: help
help:
@for line in $(HELP_LINES); do echo "$$line"; done
######################################################################################### #########################################################################################
# Implicit rule handling # Implicit rule handling
######################################################################################### #########################################################################################

View File

@@ -130,38 +130,8 @@ Using the JTAG Interface
------------------------ ------------------------
The main way to use JTAG with a Rocket Chip based system is to instantiate the Debug Transfer Module (DTM) The main way to use JTAG with a Rocket Chip based system is to instantiate the Debug Transfer Module (DTM)
and configure it to use a JTAG interface (by default the DTM is setup to use the DMI interface mentioned above). and configure it to use a JTAG interface. The default Chipyard designs instantiate the DTM and configure it
to use JTAG. You may attach OpenOCD and GDB to any of the default JTAG-enabled designs.
Creating a DTM+JTAG Config
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
First, a DTM config must be created for the system that you want to create.
This step is similar to the DMI simulation section within the :ref:`Starting the TSI or DMI Simulation` section.
The configuration is very similar to a DMI-based configuration. The main difference
is the addition of the ``WithJtagDTM`` config fragment that configures the instantiated DTM to use the JTAG protocol as the
bringup method.
.. literalinclude:: ../../generators/chipyard/src/main/scala/config/RocketConfigs.scala
:language: scala
:start-after: DOC include start: JtagRocket
:end-before: DOC include end: JtagRocket
Building a DTM+JTAG Simulator
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
After creating the config, call the ``make`` command like the following to build a simulator for your RTL:
.. code-block:: bash
cd sims/verilator
# or
cd sims/vcs
make CONFIG=jtagRocketConfig
In this example, the simulation will use the config that you previously specified, as well as set
the other parameters that are needed to satisfy the build system. After that point, you
should have a JTAG enabled simulator that you can attach to using OpenOCD and GDB!
Debugging with JTAG Debugging with JTAG
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@@ -40,8 +40,7 @@ For a proprietry VCS simulation, enter the ``sims/vcs`` directory
# Enter VCS directory # Enter VCS directory
cd sims/vcs cd sims/vcs
.. _sw-sim-help:
.. _sim-default:
Simulating The Default Example Simulating The Default Example
------------------------------- -------------------------------
@@ -82,6 +81,22 @@ For example:
.. _sw-sim-custom: .. _sw-sim-custom:
Makefile Variables and Commands
-------------------------------
You can get a list of useful Makefile variables and commands available from the Verilator or VCS directories. simply run ``make help``:
.. code-block:: shell
# Enter Verilator directory
cd sims/verilator
make help
# Enter VCS directory
cd sims/vcs
make help
.. _sim-default:
Simulating A Custom Project Simulating A Custom Project
------------------------------- -------------------------------
@@ -167,3 +182,18 @@ An open-source vcd-capable waveform viewer is `GTKWave <http://gtkwave.sourcefor
For a VCS simulation, this will generate a vpd file (this is a proprietary waveform representation format used by Synopsys) that can be loaded to vpd-supported waveform viewers. For a VCS simulation, this will generate a vpd file (this is a proprietary waveform representation format used by Synopsys) that can be loaded to vpd-supported waveform viewers.
If you have Synopsys licenses, we recommend using the DVE waveform viewer. If you have Synopsys licenses, we recommend using the DVE waveform viewer.
.. _sw-sim-verilator-opts:
Additional Verilator Options
-------------------------------
When building the verilator simulator there are some additional options:
.. code-block:: shell
make VERILATOR_THREADS=8 NUMACTL=1
The ``VERILATOR_THREADS=<num>`` option enables the compiled Verilator simulator to use ``<num>`` parallel threads.
On a multi-socket machine, you will want to make sure all threads are on the same socket by using ``NUMACTL=1`` to enable ``numactl``.
By enabling this, you will use Chipyard's ``numa_prefix`` wrapper, which is a simple wrapper around ``numactl`` that runs your verilated simulator like this: ``$(numa_prefix) ./simulator-<name> <simulator-args>``.
Note that both these flags are mutually exclusive, you can use either independently (though it makes sense to use ``NUMACTL`` just with ``VERILATOR_THREADS=8`` during a Verilator simulation).

View File

@@ -4,118 +4,64 @@ import chisel3._
import scala.collection.mutable.{ArrayBuffer} import scala.collection.mutable.{ArrayBuffer}
import freechips.rocketchip.prci.{ClockGroupIdentityNode, ClockSinkParameters, ClockSinkNode, ClockGroup}
import freechips.rocketchip.subsystem.{BaseSubsystem, SubsystemDriveAsyncClockGroupsKey}
import freechips.rocketchip.config.{Parameters, Field} import freechips.rocketchip.config.{Parameters, Field}
import freechips.rocketchip.diplomacy.{LazyModule} import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp, LazyRawModuleImp, LazyModuleImpLike}
import freechips.rocketchip.util.{ResetCatchAndSync} import freechips.rocketchip.util.{ResetCatchAndSync}
import chipyard.config.ConfigValName._
import chipyard.iobinders.{IOBinders, TestHarnessFunction, IOBinderTuple} import chipyard.iobinders.{IOBinders, TestHarnessFunction, IOBinderTuple}
import barstools.iocell.chisel._ import barstools.iocell.chisel._
case object BuildSystem extends Field[Parameters => LazyModule]((p: Parameters) => LazyModule(new DigitalTop()(p))) case object BuildSystem extends Field[Parameters => LazyModule]((p: Parameters) => new DigitalTop()(p))
/**
* Chipyard provides three baseline, top-level reset schemes, set using the
* [[GlobalResetSchemeKey]] in a Parameters instance. These are:
*
* 1) Synchronous: The input coming to the chip is synchronous to the provided
* clocks and will be used without modification as a synchronous reset.
* This is safe only for use in FireSim and SW simulation.
*
* 2) Asynchronous: The input reset is asynchronous to the input clock, but it
* is caught and synchronized to that clock before it is dissemenated.
* Thus, downsteam modules will be emitted with synchronously reset state
* elements.
*
* 3) Asynchronous Full: The input reset is asynchronous to the input clock,
* and is used globally as an async reset. Downstream modules will be emitted
* with asynchronously reset state elements.
*
*/
sealed trait GlobalResetScheme {
def pinIsAsync: Boolean
}
sealed trait HasAsyncInput { self: GlobalResetScheme =>
def pinIsAsync = true
}
sealed trait HasSyncInput { self: GlobalResetScheme =>
def pinIsAsync = false
}
case object GlobalResetSynchronous extends GlobalResetScheme with HasSyncInput
case object GlobalResetAsynchronous extends GlobalResetScheme with HasAsyncInput
case object GlobalResetAsynchronousFull extends GlobalResetScheme with HasAsyncInput
case object GlobalResetSchemeKey extends Field[GlobalResetScheme](GlobalResetSynchronous)
/** /**
* The base class used for building chips. This constructor instantiates a module specified by the BuildSystem parameter, * The base class used for building chips. This constructor instantiates a module specified by the BuildSystem parameter,
* named "system", which is an instance of DigitalTop by default. The default clock and reset for "system" are set by two * named "system", which is an instance of DigitalTop by default. The diplomatic clocks of System, as well as its implicit clock,
* wires, "systemClock" and "systemReset", which are intended to be driven by traits mixed-in with this base class. * is aggregated into the clockGroupNode. The parameterized functions controlled by ClockingSchemeKey and GlobalResetSchemeKey
* drive clock and reset generation
*/ */
abstract class BaseChipTop()(implicit val p: Parameters) extends RawModule with HasTestHarnessFunctions {
class ChipTop(implicit p: Parameters) extends LazyModule with HasTestHarnessFunctions {
// A publicly accessible list of IO cells (useful for a floorplanning tool, for example) // A publicly accessible list of IO cells (useful for a floorplanning tool, for example)
val iocells = ArrayBuffer.empty[IOCell] val iocells = ArrayBuffer.empty[IOCell]
// A list of functions to call in the test harness // A list of functions to call in the test harness
val harnessFunctions = ArrayBuffer.empty[TestHarnessFunction] val harnessFunctions = ArrayBuffer.empty[TestHarnessFunction]
// The system clock
// These are given so that IOCell can use DataMirror and generate ports with
// the right flow (Input/Output)
val systemClock = Wire(Input(Clock()))
val systemReset = Wire(Input(Reset()))
// The system module specified by BuildSystem // The system module specified by BuildSystem
val lSystem = p(BuildSystem)(p).suggestName("system") val lSystem = LazyModule(p(BuildSystem)(p)).suggestName("system")
val system = withClockAndReset(systemClock, systemReset) { Module(lSystem.module) }
// Call all of the IOBinders and provide them with a default clock and reset // The implicitClockSinkNode provides the implicit clock and reset for the System
withClockAndReset(systemClock, systemReset) { val implicitClockSinkNode = ClockSinkNode(Seq(ClockSinkParameters()))
// Call each IOBinder on both the lazyModule instance and the module
// instance. Generally, an IOBinder PF should only be defined on one, so // Generate Clocks and Reset
// this should not lead to two invocations. p(ClockingSchemeKey)(this)
val (_ports, _iocells, _harnessFunctions) = p(IOBinders).values.flatMap(f => f(lSystem) ++ f(system)).unzip3
// We ignore _ports for now... // NOTE: Making this a LazyRawModule is moderately dangerous, as anonymous children
iocells ++= _iocells.flatten // of ChipTop (ex: ClockGroup) do not receive clock or reset.
harnessFunctions ++= _harnessFunctions.flatten // However. anonymous children of ChipTop should not need an implicit Clock or Reset
// anyways, they probably need to be explicitly clocked.
lazy val module: LazyModuleImpLike = new LazyRawModuleImp(this) {
// These become the implicit clock and reset to the System
val implicit_clock = implicitClockSinkNode.in.head._1.clock
val implicit_reset = implicitClockSinkNode.in.head._1.reset
// The implicit clock and reset for the system is also, by convention, used for all the IOBinders
// TODO: This may not be the right thing to do in all cases
withClockAndReset(implicit_clock, implicit_reset) {
val (_ports, _iocells, _harnessFunctions) = p(IOBinders).values.flatMap(f => f(lSystem) ++ f(lSystem.module)).unzip3
// We ignore _ports for now...
iocells ++= _iocells.flatten
harnessFunctions ++= _harnessFunctions.flatten
}
// Connect the implicit clock/reset, if present
lSystem.module match { case l: LazyModuleImp => {
l.clock := implicit_clock
l.reset := implicit_reset
}}
} }
} }
/**
* A simple clock and reset implementation that punches out clock and reset ports with the same
* names as the implicit clock and reset for standard Module classes. Three basic reset schemes
* are provided. See [[GlobalResetScheme]].
*/
trait HasChipTopSimpleClockAndReset { this: BaseChipTop =>
val (clock, systemClockIO) = IOCell.generateIOFromSignal(systemClock, Some("iocell_clock"))
val (reset, systemResetIO) = p(GlobalResetSchemeKey) match {
case GlobalResetSynchronous =>
IOCell.generateIOFromSignal(systemReset, Some("iocell_reset"))
case GlobalResetAsynchronousFull =>
IOCell.generateIOFromSignal(systemReset, Some("iocell_reset"), abstractResetAsAsync = true)
case GlobalResetAsynchronous =>
val asyncResetCore = Wire(Input(AsyncReset()))
systemReset := ResetCatchAndSync(systemClock, asyncResetCore.asBool)
IOCell.generateIOFromSignal(asyncResetCore, Some("iocell_reset"), abstractResetAsAsync = true)
}
iocells ++= systemClockIO
iocells ++= systemResetIO
// Add a TestHarnessFunction that connects clock and reset
harnessFunctions += { (th: TestHarness) => {
// Connect clock; it's not done implicitly with RawModule
clock := th.clock
// Connect reset; it's not done implicitly with RawModule
// Note that we need to use dutReset, not harnessReset
reset := th.dutReset
Nil
} }
}
class ChipTop()(implicit p: Parameters) extends BaseChipTop()(p)
with HasChipTopSimpleClockAndReset

View File

@@ -0,0 +1,178 @@
package chipyard
import chisel3._
import scala.collection.mutable.{ArrayBuffer}
import freechips.rocketchip.prci._
import freechips.rocketchip.subsystem.{BaseSubsystem, SubsystemDriveAsyncClockGroupsKey}
import freechips.rocketchip.config.{Parameters, Field}
import freechips.rocketchip.diplomacy.{OutwardNodeHandle, InModuleBody, LazyModule}
import freechips.rocketchip.util.{ResetCatchAndSync, Pow2ClockDivider}
import barstools.iocell.chisel._
/**
* Chipyard provides three baseline, top-level reset schemes, set using the
* [[GlobalResetSchemeKey]] in a Parameters instance. These are:
*
* 1) Synchronous: The input coming to the chip is synchronous to the provided
* clocks and will be used without modification as a synchronous reset.
* This is safe only for use in FireSim and SW simulation.
*
* 2) Asynchronous: The input reset is asynchronous to the input clock, but it
* is caught and synchronized to that clock before it is dissemenated.
* Thus, downsteam modules will be emitted with synchronously reset state
* elements.
*
* 3) Asynchronous Full: The input reset is asynchronous to the input clock,
* and is used globally as an async reset. Downstream modules will be emitted
* with asynchronously reset state elements.
*
*/
sealed trait GlobalResetScheme {
def pinIsAsync: Boolean
}
sealed trait HasAsyncInput { self: GlobalResetScheme =>
def pinIsAsync = true
}
sealed trait HasSyncInput { self: GlobalResetScheme =>
def pinIsAsync = false
}
case object GlobalResetSynchronous extends GlobalResetScheme with HasSyncInput
case object GlobalResetAsynchronous extends GlobalResetScheme with HasAsyncInput
case object GlobalResetAsynchronousFull extends GlobalResetScheme with HasAsyncInput
case object GlobalResetSchemeKey extends Field[GlobalResetScheme](GlobalResetSynchronous)
/**
* A simple reset implementation that punches out reset ports
* for standard Module classes. Three basic reset schemes
* are provided. See [[GlobalResetScheme]].
*/
object GenerateReset {
def apply(chiptop: ChipTop, clock: Clock): Reset = {
implicit val p = chiptop.p
// this needs directionality so generateIOFromSignal works
val reset_wire = Wire(Input(Reset()))
val (reset_io, resetIOCell) = p(GlobalResetSchemeKey) match {
case GlobalResetSynchronous =>
IOCell.generateIOFromSignal(reset_wire, Some("iocell_reset"))
case GlobalResetAsynchronousFull =>
IOCell.generateIOFromSignal(reset_wire, Some("iocell_reset"), abstractResetAsAsync = true)
case GlobalResetAsynchronous => {
val async_reset_wire = Wire(Input(AsyncReset()))
reset_wire := ResetCatchAndSync(clock, async_reset_wire.asBool())
IOCell.generateIOFromSignal(async_reset_wire, Some("iocell_reset"), abstractResetAsAsync = true)
}
}
reset_io.suggestName("reset")
chiptop.iocells ++= resetIOCell
chiptop.harnessFunctions += ((th: HasHarnessSignalReferences) => {
reset_io := th.dutReset
Nil
})
reset_wire
}
}
case object ClockingSchemeKey extends Field[ChipTop => Unit](ClockingSchemeGenerators.harnessClock)
object ClockingSchemeGenerators {
// A simple clock provider, for testing
val harnessClock: ChipTop => Unit = { chiptop =>
implicit val p = chiptop.p
val implicitClockSourceNode = ClockSourceNode(Seq(ClockSourceParameters()))
chiptop.implicitClockSinkNode := implicitClockSourceNode
// Drive the diplomaticclock graph of the DigitalTop (if present)
val simpleClockGroupSourceNode = chiptop.lSystem match {
case l: BaseSubsystem if (p(SubsystemDriveAsyncClockGroupsKey).isEmpty) => {
val n = ClockGroupSourceNode(Seq(ClockGroupSourceParameters()))
l.asyncClockGroupsNode := n
Some(n)
}
case _ => None
}
InModuleBody {
//this needs directionality so generateIOFromSignal works
val clock_wire = Wire(Input(Clock()))
val reset_wire = GenerateReset(chiptop, clock_wire)
val (clock_io, clockIOCell) = IOCell.generateIOFromSignal(clock_wire, Some("iocell_clock"))
chiptop.iocells ++= clockIOCell
clock_io.suggestName("clock")
implicitClockSourceNode.out.unzip._1.map { o =>
o.clock := clock_wire
o.reset := reset_wire
}
simpleClockGroupSourceNode.map { n => n.out.unzip._1.map { out: ClockGroupBundle =>
out.member.data.foreach { o =>
o.clock := clock_wire
o.reset := reset_wire
}
}}
chiptop.harnessFunctions += ((th: HasHarnessSignalReferences) => {
clock_io := th.harnessClock
Nil
})
}
}
val harnessDividedClock: ChipTop => Unit = { chiptop =>
implicit val p = chiptop.p
require(false, "Divided clock is broken until we fix passing onchip clocks to TestHarness objects")
val implicitClockSourceNode = ClockSourceNode(Seq(ClockSourceParameters()))
chiptop.implicitClockSinkNode := implicitClockSourceNode
val simpleClockGroupSourceNode = chiptop.lSystem match {
case l: BaseSubsystem if (p(SubsystemDriveAsyncClockGroupsKey).isEmpty) => {
val n = ClockGroupSourceNode(Seq(ClockGroupSourceParameters()))
l.asyncClockGroupsNode := n
Some(n)
}
case _ => throw new Exception("Harness multiclock assumes BaseSubsystem")
}
InModuleBody {
// this needs directionality so generateIOFromSignal works
val clock_wire = Wire(Input(Clock()))
val reset_wire = GenerateReset(chiptop, clock_wire)
val (clock_io, clockIOCell) = IOCell.generateIOFromSignal(clock_wire, Some("iocell_clock"))
chiptop.iocells ++= clockIOCell
clock_io.suggestName("clock")
val div_clock = Pow2ClockDivider(clock_wire, 2)
implicitClockSourceNode.out.unzip._1.map { o =>
o.clock := div_clock
o.reset := reset_wire
}
simpleClockGroupSourceNode.map { n => n.out.unzip._1.map { out: ClockGroupBundle =>
out.member.elements.map { case (name, data) =>
// This is mega hacks, how are you actually supposed to do this?
data.clock := (if (name.contains("core")) clock_wire else div_clock)
data.reset := reset_wire
}
}}
chiptop.harnessFunctions += ((th: HasHarnessSignalReferences) => {
clock_io := th.harnessClock
Nil
})
}
}
}

View File

@@ -6,12 +6,13 @@ import chisel3.util.{log2Up}
import freechips.rocketchip.config.{Field, Parameters, Config} import freechips.rocketchip.config.{Field, Parameters, Config}
import freechips.rocketchip.subsystem._ import freechips.rocketchip.subsystem._
import freechips.rocketchip.diplomacy.{LazyModule, ValName} import freechips.rocketchip.diplomacy.{LazyModule, ValName}
import freechips.rocketchip.devices.tilelink.BootROMParams import freechips.rocketchip.devices.tilelink.{BootROMLocated}
import freechips.rocketchip.devices.debug.{Debug} import freechips.rocketchip.devices.debug.{Debug, ExportDebug, DebugModuleKey, DMI}
import freechips.rocketchip.groundtest.{GroundTestSubsystem} import freechips.rocketchip.groundtest.{GroundTestSubsystem}
import freechips.rocketchip.tile._ import freechips.rocketchip.tile._
import freechips.rocketchip.rocket.{RocketCoreParams, MulDivParams, DCacheParams, ICacheParams} import freechips.rocketchip.rocket.{RocketCoreParams, MulDivParams, DCacheParams, ICacheParams}
import freechips.rocketchip.util.{AsyncResetReg} import freechips.rocketchip.util.{AsyncResetReg}
import freechips.rocketchip.prci._
import testchipip._ import testchipip._
import tracegen.{TraceGenSystem} import tracegen.{TraceGenSystem}
@@ -25,23 +26,15 @@ import sifive.blocks.devices.gpio._
import sifive.blocks.devices.uart._ import sifive.blocks.devices.uart._
import sifive.blocks.devices.spi._ import sifive.blocks.devices.spi._
import chipyard.{BuildTop, BuildSystem, TestSuitesKey, TestSuiteHelper} import chipyard.{BuildTop, BuildSystem, ClockingSchemeGenerators, ClockingSchemeKey, TestSuitesKey, TestSuiteHelper}
/**
* TODO: Why do we need this?
*/
object ConfigValName {
implicit val valName = ValName("TestHarness")
}
import ConfigValName._
// ----------------------- // -----------------------
// Common Config Fragments // Common Config Fragments
// ----------------------- // -----------------------
class WithBootROM extends Config((site, here, up) => { class WithBootROM extends Config((site, here, up) => {
case BootROMParams => BootROMParams( case BootROMLocated(x) => up(BootROMLocated(x), site).map(_.copy(contentFileName = s"./bootrom/bootrom.rv${site(XLen)}.img"))
contentFileName = s"./bootrom/bootrom.rv${site(XLen)}.img")
}) })
// DOC include start: gpio config fragment // DOC include start: gpio config fragment
@@ -73,7 +66,7 @@ class WithL2TLBs(entries: Int) extends Config((site, here, up) => {
}) })
class WithTracegenSystem extends Config((site, here, up) => { class WithTracegenSystem extends Config((site, here, up) => {
case BuildSystem => (p: Parameters) => LazyModule(new TraceGenSystem()(p)) case BuildSystem => (p: Parameters) => new TraceGenSystem()(p)
}) })
/** /**
@@ -105,7 +98,8 @@ class WithMultiRoCCHwacha(harts: Int*) extends Config(
case MultiRoCCKey => { case MultiRoCCKey => {
up(MultiRoCCKey, site) ++ harts.distinct.map{ i => up(MultiRoCCKey, site) ++ harts.distinct.map{ i =>
(i -> Seq((p: Parameters) => { (i -> Seq((p: Parameters) => {
LazyModule(new Hwacha()(p)).suggestName("hwacha") val hwacha = LazyModule(new Hwacha()(p))
hwacha
})) }))
} }
} }
@@ -156,3 +150,23 @@ class WithHwachaTest extends Config((site, here, up) => {
"SRC_EXTENSION = $(base_dir)/hwacha/$(src_path)/*.scala" + "\nDISASM_EXTENSION = --extension=hwacha" "SRC_EXTENSION = $(base_dir)/hwacha/$(src_path)/*.scala" + "\nDISASM_EXTENSION = --extension=hwacha"
} }
}) })
// The default RocketChip BaseSubsystem drives its diplomatic clock graph
// with the implicit clocks of Subsystem. Don't do that, instead we extend
// the diplomacy graph upwards into the ChipTop, where we connect it to
// our clock drivers
class WithNoSubsystemDrivenClocks extends Config((site, here, up) => {
case SubsystemDriveAsyncClockGroupsKey => None
})
class WithTileDividedClock extends Config((site, here, up) => {
case ClockingSchemeKey => ClockingSchemeGenerators.harnessDividedClock
})
class WithDMIDTM extends Config((site, here, up) => {
case ExportDebug => up(ExportDebug, site).copy(protocols = Set(DMI))
})
class WithNoDebug extends Config((site, here, up) => {
case DebugModuleKey => None
})

View File

@@ -2,11 +2,13 @@ package chipyard
package object iobinders { package object iobinders {
import chisel3._ import chisel3._
import chisel3.util.experimental.{BoringUtils}
import chisel3.experimental.{Analog, IO} import chisel3.experimental.{Analog, IO}
import freechips.rocketchip.config.{Field, Config, Parameters} import freechips.rocketchip.config.{Field, Config, Parameters}
import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImpLike} import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImpLike}
import freechips.rocketchip.devices.debug._ import freechips.rocketchip.devices.debug._
import freechips.rocketchip.jtag.{JTAGIO}
import freechips.rocketchip.subsystem._ import freechips.rocketchip.subsystem._
import freechips.rocketchip.system.{SimAXIMem} import freechips.rocketchip.system.{SimAXIMem}
import freechips.rocketchip.amba.axi4.{AXI4Bundle, AXI4SlaveNode, AXI4MasterNode, AXI4EdgeParameters} import freechips.rocketchip.amba.axi4.{AXI4Bundle, AXI4SlaveNode, AXI4MasterNode, AXI4EdgeParameters}
@@ -41,7 +43,7 @@ import scala.reflect.{ClassTag}
// DOC include start: IOBinders // DOC include start: IOBinders
// This type describes a function callable on the TestHarness instance. Its return type is unused. // This type describes a function callable on the TestHarness instance. Its return type is unused.
type TestHarnessFunction = (chipyard.TestHarness) => Seq[Any] type TestHarnessFunction = (chipyard.HasHarnessSignalReferences) => Seq[Any]
// IOBinders will return a Seq of this tuple, which contains three fields: // IOBinders will return a Seq of this tuple, which contains three fields:
// 1. A Seq containing all IO ports created by the IOBinder function // 1. A Seq containing all IO ports created by the IOBinder function
// 2. A Seq containing all IO cell modules created by the IOBinder function // 2. A Seq containing all IO cell modules created by the IOBinder function
@@ -163,30 +165,62 @@ object AddIOCells {
} }
/** /**
* Add IO cells to a debug module and name the IO ports. * Add IO cells to a debug module and name the IO ports, for debug IO which must go off-chip
* @param psd A PSDIO bundle * For on-chip debug IO, drive them appropriately
* @param resetctrlOpt An optional ResetCtrlIO bundle * Mostly copied from rocket-chip/src/main/scala/devices/debug/Periphery.scala
* @param debugOpt An optional DebugIO bundle * @param system A BaseSubsystem that might have a debug module
* @return Returns a tuple3 of (Top-level PSDIO IO; Optional top-level DebugIO IO; a list of IOCell module references) * @return Returns a tuple2 of (Generated debug io ports, Generated IOCells)
*/ */
def debug(psd: PSDIO, resetctrlOpt: Option[ResetCtrlIO], debugOpt: Option[DebugIO])(implicit p: Parameters): def debug(system: HasPeripheryDebugModuleImp)(implicit p: Parameters): (Seq[Bundle], Seq[IOCell]) = {
(PSDIO, Option[ResetCtrlIO], Option[DebugIO], Seq[IOCell]) = { system.debug.map { debug =>
val (psdPort, psdIOs) = IOCell.generateIOFromSignal( val tlbus = system.outer.asInstanceOf[BaseSubsystem].locateTLBusWrapper(p(ExportDebug).slaveWhere)
psd, Some("iocell_psd"), abstractResetAsAsync = p(GlobalResetSchemeKey).pinIsAsync) val debug_clock = Wire(Clock()).suggestName("debug_clock")
val debugTuple = debugOpt.map(d => val debug_reset = Wire(Reset()).suggestName("debug_reset")
IOCell.generateIOFromSignal(d, Some("iocell_debug"), abstractResetAsAsync = p(GlobalResetSchemeKey).pinIsAsync)) debug_clock := false.B.asClock // must provide default assignment to avoid firrtl unassigned error
val debugPortOpt: Option[DebugIO] = debugTuple.map(_._1) debug_reset := false.B // must provide default assignment to avoid firrtl unassigned error
val debugIOs: Seq[IOCell] = debugTuple.map(_._2).toSeq.flatten BoringUtils.bore(tlbus.module.clock, Seq(debug_clock))
debugPortOpt.foreach(_.suggestName("debug")) BoringUtils.bore(tlbus.module.reset, Seq(debug_reset))
val resetctrlTuple = resetctrlOpt.map(d => // We never use the PSDIO, so tie it off on-chip
IOCell.generateIOFromSignal(d, Some("iocell_resetctrl"), abstractResetAsAsync = p(GlobalResetSchemeKey).pinIsAsync)) system.psd.psd.foreach { _ <> 0.U.asTypeOf(new PSDTestMode) }
val resetctrlPortOpt: Option[ResetCtrlIO] = resetctrlTuple.map(_._1) system.resetctrl.map { rcio => rcio.hartIsInReset.map { _ := debug_reset.asBool } }
val resetctrlIOs: Seq[IOCell] = resetctrlTuple.map(_._2).toSeq.flatten system.debug.map { d =>
resetctrlPortOpt.foreach(_.suggestName("resetctrl")) // Tie off extTrigger
d.extTrigger.foreach { t =>
t.in.req := false.B
t.out.ack := t.out.req
}
// Tie off disableDebug
d.disableDebug.foreach { d => d := false.B }
// Drive JTAG on-chip IOs
d.systemjtag.map { j =>
j.reset := debug_reset
j.mfr_id := system.p(JtagDTMKey).idcodeManufId.U(11.W)
j.part_number := system.p(JtagDTMKey).idcodePartNum.U(16.W)
j.version := system.p(JtagDTMKey).idcodeVersion.U(4.W)
}
}
Debug.connectDebugClockAndReset(Some(debug), debug_clock)(system.p)
psdPort.suggestName("psd") // Add IOCells for the DMI/JTAG/APB ports
(psdPort, resetctrlPortOpt, debugPortOpt, psdIOs ++ debugIOs ++ resetctrlIOs) val dmiTuple = debug.clockeddmi.map { d =>
IOCell.generateIOFromSignal(d, Some("iocell_dmi"), abstractResetAsAsync = p(GlobalResetSchemeKey).pinIsAsync)
}
dmiTuple.map(_._1).foreach(_.suggestName("dmi"))
val jtagTuple = debug.systemjtag.map { j =>
IOCell.generateIOFromSignal(j.jtag, Some("iocell_jtag"), abstractResetAsAsync = p(GlobalResetSchemeKey).pinIsAsync)
}
jtagTuple.map(_._1).foreach(_.suggestName("jtag"))
val apbTuple = debug.apb.map { a =>
IOCell.generateIOFromSignal(a, Some("iocell_apb"), abstractResetAsAsync = p(GlobalResetSchemeKey).pinIsAsync)
}
apbTuple.map(_._1).foreach(_.suggestName("apb"))
val allTuples = (dmiTuple ++ jtagTuple ++ apbTuple).toSeq
(allTuples.map(_._1).toSeq, allTuples.flatMap(_._2).toSeq)
}.getOrElse((Nil, Nil))
} }
/** /**
@@ -201,14 +235,14 @@ object AddIOCells {
} }
def axi4(io: Seq[AXI4Bundle], node: AXI4SlaveNode, name: String): Seq[(AXI4Bundle, AXI4EdgeParameters, Seq[IOCell])] = { def axi4(io: Seq[AXI4Bundle], node: AXI4SlaveNode, name: String): Seq[(AXI4Bundle, AXI4EdgeParameters, Seq[IOCell])] = {
io.zip(node.in).zipWithIndex.map{ case ((mem_axi4, (_, edge)), i) => { io.zip(node.edges.in).zipWithIndex.map{ case ((mem_axi4, edge), i) => {
val (port, ios) = IOCell.generateIOFromSignal(mem_axi4, Some(s"iocell_${name}_axi4_slave_${i}")) val (port, ios) = IOCell.generateIOFromSignal(mem_axi4, Some(s"iocell_${name}_axi4_slave_${i}"))
port.suggestName(s"${name}_axi4_slave_${i}") port.suggestName(s"${name}_axi4_slave_${i}")
(port, edge, ios) (port, edge, ios)
}} }}
} }
def axi4(io: Seq[AXI4Bundle], node: AXI4MasterNode, name: String): Seq[(AXI4Bundle, AXI4EdgeParameters, Seq[IOCell])] = { def axi4(io: Seq[AXI4Bundle], node: AXI4MasterNode, name: String): Seq[(AXI4Bundle, AXI4EdgeParameters, Seq[IOCell])] = {
io.zip(node.out).zipWithIndex.map{ case ((mem_axi4, (_, edge)), i) => { io.zip(node.edges.out).zipWithIndex.map{ case ((mem_axi4, edge), i) => {
//val (port, ios) = IOCell.generateIOFromSignal(mem_axi4, Some(s"iocell_${name}_axi4_master_${i}")) //val (port, ios) = IOCell.generateIOFromSignal(mem_axi4, Some(s"iocell_${name}_axi4_master_${i}"))
val port = IO(Flipped(AXI4Bundle(edge.bundle))) val port = IO(Flipped(AXI4Bundle(edge.bundle)))
val ios = IOCell.generateFromSignal(mem_axi4, port, Some(s"iocell_${name}_axi4_master_${i}")) val ios = IOCell.generateFromSignal(mem_axi4, port, Some(s"iocell_${name}_axi4_master_${i}"))
@@ -228,7 +262,7 @@ object AddIOCells {
class WithGPIOTiedOff extends OverrideIOBinder({ class WithGPIOTiedOff extends OverrideIOBinder({
(system: HasPeripheryGPIOModuleImp) => { (system: HasPeripheryGPIOModuleImp) => {
val (ports2d, ioCells2d) = AddIOCells.gpio(system.gpio) val (ports2d, ioCells2d) = AddIOCells.gpio(system.gpio)
val harnessFn = (th: chipyard.TestHarness) => { ports2d.flatten.foreach(_ <> AnalogConst(0)); Nil } val harnessFn = (th: HasHarnessSignalReferences) => { ports2d.flatten.foreach(_ <> AnalogConst(0)); Nil }
Seq((ports2d.flatten, ioCells2d.flatten, Some(harnessFn))) Seq((ports2d.flatten, ioCells2d.flatten, Some(harnessFn)))
} }
}) })
@@ -237,7 +271,7 @@ class WithGPIOTiedOff extends OverrideIOBinder({
class WithUARTAdapter extends OverrideIOBinder({ class WithUARTAdapter extends OverrideIOBinder({
(system: HasPeripheryUARTModuleImp) => { (system: HasPeripheryUARTModuleImp) => {
val (ports, ioCells2d) = AddIOCells.uart(system.uart) val (ports, ioCells2d) = AddIOCells.uart(system.uart)
val harnessFn = (th: chipyard.TestHarness) => { UARTAdapter.connect(ports)(system.p); Nil } val harnessFn = (th: HasHarnessSignalReferences) => { UARTAdapter.connect(ports)(system.p); Nil }
Seq((ports, ioCells2d.flatten, Some(harnessFn))) Seq((ports, ioCells2d.flatten, Some(harnessFn)))
} }
}) })
@@ -245,7 +279,7 @@ class WithUARTAdapter extends OverrideIOBinder({
class WithSimSPIFlashModel(rdOnly: Boolean = true) extends OverrideIOBinder({ class WithSimSPIFlashModel(rdOnly: Boolean = true) extends OverrideIOBinder({
(system: HasPeripherySPIFlashModuleImp) => { (system: HasPeripherySPIFlashModuleImp) => {
val (ports, ioCells2d) = AddIOCells.spi(system.qspi, "qspi") val (ports, ioCells2d) = AddIOCells.spi(system.qspi, "qspi")
val harnessFn = (th: chipyard.TestHarness) => { SimSPIFlashModel.connect(ports, th.reset, rdOnly)(system.p); Nil } val harnessFn = (th: HasHarnessSignalReferences) => { SimSPIFlashModel.connect(ports, th.harnessReset, rdOnly)(system.p); Nil }
Seq((ports, ioCells2d.flatten, Some(harnessFn))) Seq((ports, ioCells2d.flatten, Some(harnessFn)))
} }
}) })
@@ -253,8 +287,9 @@ class WithSimSPIFlashModel(rdOnly: Boolean = true) extends OverrideIOBinder({
class WithSimBlockDevice extends OverrideIOBinder({ class WithSimBlockDevice extends OverrideIOBinder({
(system: CanHavePeripheryBlockDeviceModuleImp) => system.bdev.map { bdev => (system: CanHavePeripheryBlockDeviceModuleImp) => system.bdev.map { bdev =>
val (port, ios) = AddIOCells.blockDev(bdev) val (port, ios) = AddIOCells.blockDev(bdev)
val harnessFn = (th: chipyard.TestHarness) => { val harnessFn = (th: HasHarnessSignalReferences) => {
SimBlockDevice.connect(th.clock, th.reset.asBool, Some(port))(system.p) // TODO: Using harness clock/reset will be incorrect when systemClock =/= harnessClock
SimBlockDevice.connect(th.harnessClock, th.harnessReset.asBool, Some(port))(system.p)
Nil Nil
} }
Seq((Seq(port), ios, Some(harnessFn))) Seq((Seq(port), ios, Some(harnessFn)))
@@ -264,7 +299,7 @@ class WithSimBlockDevice extends OverrideIOBinder({
class WithBlockDeviceModel extends OverrideIOBinder({ class WithBlockDeviceModel extends OverrideIOBinder({
(system: CanHavePeripheryBlockDeviceModuleImp) => system.bdev.map { bdev => (system: CanHavePeripheryBlockDeviceModuleImp) => system.bdev.map { bdev =>
val (port, ios) = AddIOCells.blockDev(bdev) val (port, ios) = AddIOCells.blockDev(bdev)
val harnessFn = (th: chipyard.TestHarness) => { val harnessFn = (th: HasHarnessSignalReferences) => {
BlockDeviceModel.connect(Some(port))(system.p) BlockDeviceModel.connect(Some(port))(system.p)
Nil Nil
} }
@@ -287,7 +322,7 @@ class WithSimAXIMem extends OverrideIOBinder({
val peiTuples = AddIOCells.axi4(system.mem_axi4, system.memAXI4Node, "mem") val peiTuples = AddIOCells.axi4(system.mem_axi4, system.memAXI4Node, "mem")
// TODO: we are inlining the connectMem method of SimAXIMem because // TODO: we are inlining the connectMem method of SimAXIMem because
// it takes in a dut rather than seq of axi4 ports // it takes in a dut rather than seq of axi4 ports
val harnessFn = (th: chipyard.TestHarness) => { val harnessFn = (th: HasHarnessSignalReferences) => {
peiTuples.map { case (port, edge, ios) => peiTuples.map { case (port, edge, ios) =>
val mem = LazyModule(new SimAXIMem(edge, size = p(ExtMem).get.master.size)) val mem = LazyModule(new SimAXIMem(edge, size = p(ExtMem).get.master.size))
Module(mem.module).suggestName("mem") Module(mem.module).suggestName("mem")
@@ -304,14 +339,15 @@ class WithBlackBoxSimMem extends OverrideIOBinder({
(system: CanHaveMasterAXI4MemPort) => { (system: CanHaveMasterAXI4MemPort) => {
implicit val p: Parameters = GetSystemParameters(system) implicit val p: Parameters = GetSystemParameters(system)
val peiTuples = AddIOCells.axi4(system.mem_axi4, system.memAXI4Node, "mem") val peiTuples = AddIOCells.axi4(system.mem_axi4, system.memAXI4Node, "mem")
val harnessFn = (th: chipyard.TestHarness) => { val harnessFn = (th: HasHarnessSignalReferences) => {
peiTuples.map { case (port, edge, ios) => peiTuples.map { case (port, edge, ios) =>
val memSize = p(ExtMem).get.master.size val memSize = p(ExtMem).get.master.size
val lineSize = p(CacheBlockBytes) val lineSize = p(CacheBlockBytes)
val mem = Module(new SimDRAM(memSize, lineSize, edge.bundle)) val mem = Module(new SimDRAM(memSize, lineSize, edge.bundle))
mem.io.axi <> port mem.io.axi <> port
mem.io.clock := th.clock // TODO: Using harness clock/reset will be incorrect when systemClock =/= harnessClock
mem.io.reset := th.reset mem.io.clock := th.harnessClock
mem.io.reset := th.harnessReset
} }
Nil Nil
} }
@@ -323,7 +359,7 @@ class WithSimAXIMMIO extends OverrideIOBinder({
(system: CanHaveMasterAXI4MMIOPort) => { (system: CanHaveMasterAXI4MMIOPort) => {
implicit val p: Parameters = GetSystemParameters(system) implicit val p: Parameters = GetSystemParameters(system)
val peiTuples = AddIOCells.axi4(system.mmio_axi4, system.mmioAXI4Node, "mmio_mem") val peiTuples = AddIOCells.axi4(system.mmio_axi4, system.mmioAXI4Node, "mmio_mem")
val harnessFn = (th: chipyard.TestHarness) => { val harnessFn = (th: HasHarnessSignalReferences) => {
peiTuples.zipWithIndex.map { case ((port, edge, ios), i) => peiTuples.zipWithIndex.map { case ((port, edge, ios), i) =>
val mmio_mem = LazyModule(new SimAXIMem(edge, size = 4096)) val mmio_mem = LazyModule(new SimAXIMem(edge, size = 4096))
Module(mmio_mem.module).suggestName(s"mmio_mem_${i}") Module(mmio_mem.module).suggestName(s"mmio_mem_${i}")
@@ -343,7 +379,7 @@ class WithTieOffInterrupts extends OverrideIOBinder({
(system: HasExtInterruptsModuleImp) => { (system: HasExtInterruptsModuleImp) => {
val (port, ioCells) = IOCell.generateIOFromSignal(system.interrupts, Some("iocell_interrupts")) val (port, ioCells) = IOCell.generateIOFromSignal(system.interrupts, Some("iocell_interrupts"))
port.suggestName("interrupts") port.suggestName("interrupts")
val harnessFn = (th: chipyard.TestHarness) => { port := 0.U; Nil } val harnessFn = (th: HasHarnessSignalReferences) => { port := 0.U; Nil }
Seq((Seq(port), ioCells, Some(harnessFn))) Seq((Seq(port), ioCells, Some(harnessFn)))
} }
}) })
@@ -351,7 +387,7 @@ class WithTieOffInterrupts extends OverrideIOBinder({
class WithTieOffL2FBusAXI extends OverrideIOBinder({ class WithTieOffL2FBusAXI extends OverrideIOBinder({
(system: CanHaveSlaveAXI4Port) => { (system: CanHaveSlaveAXI4Port) => {
val peiTuples = AddIOCells.axi4(system.l2_frontend_bus_axi4, system.l2FrontendAXI4Node, "l2_fbus") val peiTuples = AddIOCells.axi4(system.l2_frontend_bus_axi4, system.l2FrontendAXI4Node, "l2_fbus")
val harnessFn = (th: chipyard.TestHarness) => { val harnessFn = (th: HasHarnessSignalReferences) => {
peiTuples.zipWithIndex.map { case ((port, edge, ios), i) => peiTuples.zipWithIndex.map { case ((port, edge, ios), i) =>
port := DontCare // tieoff doesn't completely tie-off, for some reason port := DontCare // tieoff doesn't completely tie-off, for some reason
port.tieoff() port.tieoff()
@@ -362,43 +398,60 @@ class WithTieOffL2FBusAXI extends OverrideIOBinder({
} }
}) })
class WithTiedOffDebug extends OverrideIOBinder({ class WithSimDebug extends OverrideIOBinder({
(system: HasPeripheryDebugModuleImp) => { (system: HasPeripheryDebugModuleImp) => {
val (psdPort, resetctrlOpt, debugPortOpt, ioCells) = val (ports, iocells) = AddIOCells.debug(system)(system.p)
AddIOCells.debug(system.psd, system.resetctrl, system.debug)(system.p) val harnessFn = (th: HasHarnessSignalReferences) => {
val harnessFn = (th: chipyard.TestHarness) => { val dtm_success = WireInit(false.B)
Debug.tieoffDebug(debugPortOpt, resetctrlOpt, Some(psdPort))(system.p) when (dtm_success) { th.success := true.B }
// tieoffDebug doesn't actually tie everything off :/ ports.map {
debugPortOpt.foreach { d => case d: ClockedDMIIO =>
d.clockeddmi.foreach({ cdmi => cdmi.dmi.req.bits := DontCare; cdmi.dmiClock := th.clock }) val dtm = Module(new SimDTM()(system.p)).connect(th.harnessClock, th.harnessReset.asBool, d, dtm_success)
d.dmactiveAck := DontCare case j: JTAGIO =>
d.clock := th.clock val jtag = Module(new SimJTAG(tickDelay=3)).connect(j, th.harnessClock, th.harnessReset.asBool, ~(th.harnessReset.asBool), dtm_success)
case _ =>
require(false, "We only support DMI or JTAG simulated debug connections")
} }
Nil Nil
} }
Seq((Seq(psdPort) ++ resetctrlOpt ++ debugPortOpt.toSeq, Nil, Some(harnessFn))) Seq((ports, iocells, Some(harnessFn)))
} }
}) })
class WithSimDebug extends OverrideIOBinder({ class WithTiedOffDebug extends OverrideIOBinder({
(system: HasPeripheryDebugModuleImp) => { (system: HasPeripheryDebugModuleImp) => {
val (psdPort, resetctrlPortOpt, debugPortOpt, ioCells) = val (ports, iocells) = AddIOCells.debug(system)(system.p)
AddIOCells.debug(system.psd, system.resetctrl, system.debug)(system.p) val harnessFn = (th: HasHarnessSignalReferences) => {
val harnessFn = (th: chipyard.TestHarness) => { ports.map {
val dtm_success = Wire(Bool()) case d: ClockedDMIIO =>
Debug.connectDebug(debugPortOpt, resetctrlPortOpt, psdPort, th.clock, th.harnessReset, dtm_success)(system.p) d.dmi.req.valid := false.B
when (dtm_success) { th.success := true.B } d.dmi.req.bits := DontCare
th.dutReset := th.harnessReset | debugPortOpt.map { debug => AsyncResetReg(debug.ndreset).asBool }.getOrElse(false.B) d.dmi.resp.ready := true.B
d.dmiClock := false.B.asClock
d.dmiReset := true.B
case j: JTAGIO =>
j.TCK := true.B.asClock
j.TMS := true.B
j.TDI := true.B
j.TRSTn.foreach { r => r := true.B }
case a: ClockedAPBBundle =>
a.tieoff()
a.clock := false.B.asClock
a.reset := true.B.asAsyncReset
a.psel := false.B
a.penable := false.B
case _ => require(false)
}
Nil Nil
} }
Seq((Seq(psdPort) ++ debugPortOpt.toSeq, ioCells, Some(harnessFn))) Seq((ports, iocells, Some(harnessFn)))
} }
}) })
class WithTiedOffSerial extends OverrideIOBinder({ class WithTiedOffSerial extends OverrideIOBinder({
(system: CanHavePeripherySerialModuleImp) => system.serial.map({ serial => (system: CanHavePeripherySerialModuleImp) => system.serial.map({ serial =>
val (port, ioCells) = AddIOCells.serial(serial) val (port, ioCells) = AddIOCells.serial(serial)
val harnessFn = (th: chipyard.TestHarness) => { val harnessFn = (th: HasHarnessSignalReferences) => {
SerialAdapter.tieoff(port) SerialAdapter.tieoff(port)
Nil Nil
} }
@@ -409,8 +462,8 @@ class WithTiedOffSerial extends OverrideIOBinder({
class WithSimSerial extends OverrideIOBinder({ class WithSimSerial extends OverrideIOBinder({
(system: CanHavePeripherySerialModuleImp) => system.serial.map({ serial => (system: CanHavePeripherySerialModuleImp) => system.serial.map({ serial =>
val (port, ioCells) = AddIOCells.serial(serial) val (port, ioCells) = AddIOCells.serial(serial)
val harnessFn = (th: chipyard.TestHarness) => { val harnessFn = (th: HasHarnessSignalReferences) => {
val ser_success = SerialAdapter.connectSimSerial(port, th.clock, th.harnessReset) val ser_success = SerialAdapter.connectSimSerial(port, th.harnessClock, th.harnessReset)
when (ser_success) { th.success := true.B } when (ser_success) { th.success := true.B }
Nil Nil
} }
@@ -422,7 +475,7 @@ class WithTraceGenSuccessBinder extends OverrideIOBinder({
(system: TraceGenSystemModuleImp) => { (system: TraceGenSystemModuleImp) => {
val (successPort, ioCells) = IOCell.generateIOFromSignal(system.success, Some("iocell_success")) val (successPort, ioCells) = IOCell.generateIOFromSignal(system.success, Some("iocell_success"))
successPort.suggestName("success") successPort.suggestName("success")
val harnessFn = (th: chipyard.TestHarness) => { when (successPort) { th.success := true.B }; Nil } val harnessFn = (th: HasHarnessSignalReferences) => { when (successPort) { th.success := true.B }; Nil }
Seq((Seq(successPort), ioCells, Some(harnessFn))) Seq((Seq(successPort), ioCells, Some(harnessFn)))
} }
}) })

View File

@@ -8,6 +8,7 @@ package chipyard
import chisel3._ import chisel3._
import chisel3.internal.sourceinfo.{SourceInfo} import chisel3.internal.sourceinfo.{SourceInfo}
import freechips.rocketchip.prci._
import freechips.rocketchip.config.{Field, Parameters} import freechips.rocketchip.config.{Field, Parameters}
import freechips.rocketchip.devices.tilelink._ import freechips.rocketchip.devices.tilelink._
import freechips.rocketchip.devices.debug.{HasPeripheryDebug, HasPeripheryDebugModuleImp, ExportDebug} import freechips.rocketchip.devices.debug.{HasPeripheryDebug, HasPeripheryDebugModuleImp, ExportDebug}
@@ -26,12 +27,11 @@ import boom.common.{BoomTile}
import testchipip.{DromajoHelper, CanHavePeripherySerial, SerialKey} import testchipip.{DromajoHelper, CanHavePeripherySerial, SerialKey}
trait CanHaveHTIF { this: BaseSubsystem => trait CanHaveHTIF { this: BaseSubsystem =>
// Advertise HTIF if system can communicate with fesvr // Advertise HTIF if system can communicate with fesvr
if (this match { if (this match {
case _: CanHavePeripherySerial if p(SerialKey) => true case _: CanHavePeripherySerial if p(SerialKey) => true
case _: HasPeripheryDebug if p(ExportDebug).protocols.nonEmpty => true case _: HasPeripheryDebug if p(ExportDebug).dmi => true
case _ => false case _ => false
}) { }) {
ResourceBinding { ResourceBinding {
@@ -47,7 +47,6 @@ trait CanHaveHTIF { this: BaseSubsystem =>
} }
} }
class ChipyardSubsystem(implicit p: Parameters) extends BaseSubsystem class ChipyardSubsystem(implicit p: Parameters) extends BaseSubsystem
with HasTiles with HasTiles
with CanHaveHTIF with CanHaveHTIF
@@ -56,25 +55,17 @@ class ChipyardSubsystem(implicit p: Parameters) extends BaseSubsystem
case r: RocketTile => r.module.core.rocketImpl.coreMonitorBundle case r: RocketTile => r.module.core.rocketImpl.coreMonitorBundle
case b: BoomTile => b.module.core.coreMonitorBundle case b: BoomTile => b.module.core.coreMonitorBundle
}.toList }.toList
override lazy val module = new ChipyardSubsystemModuleImp(this) override lazy val module = new ChipyardSubsystemModuleImp(this)
} }
class ChipyardSubsystemModuleImp[+L <: ChipyardSubsystem](_outer: L) extends BaseSubsystemModuleImp(_outer) class ChipyardSubsystemModuleImp[+L <: ChipyardSubsystem](_outer: L) extends BaseSubsystemModuleImp(_outer)
with HasResetVectorWire
with HasTilesModuleImp with HasTilesModuleImp
{ {
for (i <- 0 until outer.tiles.size) {
val wire = tile_inputs(i)
wire.hartid := outer.hartIdList(i).U
wire.reset_vector := global_reset_vector
}
// create file with core params // create file with core params
ElaborationArtefacts.add("""core.config""", outer.tiles.map(x => x.module.toString).mkString("\n")) ElaborationArtefacts.add("""core.config""", outer.tiles.map(x => x.module.toString).mkString("\n"))
// Generate C header with relevant information for Dromajo // Generate C header with relevant information for Dromajo
// This is included in the `dromajo_params.h` header file // This is included in the `dromajo_params.h` header file
DromajoHelper.addArtefacts() DromajoHelper.addArtefacts(InSubsystem)
} }

View File

@@ -26,8 +26,10 @@ class ChipyardSystem(implicit p: Parameters) extends ChipyardSubsystem
with CanHaveMasterAXI4MemPort with CanHaveMasterAXI4MemPort
with CanHaveMasterAXI4MMIOPort with CanHaveMasterAXI4MMIOPort
with CanHaveSlaveAXI4Port with CanHaveSlaveAXI4Port
with HasPeripheryBootROM
{ {
val bootROM = p(BootROMLocated(location)).map { BootROM.attach(_, this, CBUS) }
val maskROMs = p(MaskROMLocated(location)).map { MaskROM.attach(_, this, CBUS) }
override lazy val module = new ChipyardSystemModule(this) override lazy val module = new ChipyardSystemModule(this)
} }
@@ -37,5 +39,4 @@ class ChipyardSystem(implicit p: Parameters) extends ChipyardSubsystem
class ChipyardSystemModule[+L <: ChipyardSystem](_outer: L) extends ChipyardSubsystemModuleImp(_outer) class ChipyardSystemModule[+L <: ChipyardSystem](_outer: L) extends ChipyardSubsystemModuleImp(_outer)
with HasRTCModuleImp with HasRTCModuleImp
with HasExtInterruptsModuleImp with HasExtInterruptsModuleImp
with HasPeripheryBootROMModuleImp
with DontTouch with DontTouch

View File

@@ -5,33 +5,41 @@ import chisel3._
import freechips.rocketchip.diplomacy.{LazyModule} import freechips.rocketchip.diplomacy.{LazyModule}
import freechips.rocketchip.config.{Field, Parameters} import freechips.rocketchip.config.{Field, Parameters}
import chipyard.iobinders.{TestHarnessFunction} import chipyard.iobinders.{TestHarnessFunction}
import chipyard.config.ConfigValName._
// ------------------------------- // -------------------------------
// BOOM and/or Rocket Test Harness // Chipyard Test Harness
// ------------------------------- // -------------------------------
case object BuildTop extends Field[Parameters => HasTestHarnessFunctions]((p: Parameters) => Module(new ChipTop()(p))) case object BuildTop extends Field[Parameters => LazyModule with HasTestHarnessFunctions]((p: Parameters) => new ChipTop()(p))
trait HasTestHarnessFunctions { trait HasTestHarnessFunctions {
val harnessFunctions: Seq[TestHarnessFunction] val harnessFunctions: Seq[TestHarnessFunction]
} }
class TestHarness(implicit val p: Parameters) extends Module { trait HasHarnessSignalReferences {
def harnessClock: Clock
def harnessReset: Reset
def dutReset: Reset
def success: Bool
}
class TestHarness(implicit val p: Parameters) extends Module with HasHarnessSignalReferences {
val io = IO(new Bundle { val io = IO(new Bundle {
val success = Output(Bool()) val success = Output(Bool())
}) })
val dut = p(BuildTop)(p) val ldut = LazyModule(p(BuildTop)(p)).suggestName("chiptop")
val dut = Module(ldut.module)
io.success := false.B io.success := false.B
val harnessClock = clock
val harnessReset = WireInit(reset)
val success = io.success
// dutReset assignment can be overridden via a harnessFunction, but by default it is just reset // dutReset assignment can be overridden via a harnessFunction, but by default it is just reset
val dutReset = WireDefault(if (p(GlobalResetSchemeKey).pinIsAsync) reset.asAsyncReset else reset) val dutReset = WireDefault(if (p(GlobalResetSchemeKey).pinIsAsync) reset.asAsyncReset else reset)
dut.harnessFunctions.foreach(_(this)) ldut.harnessFunctions.foreach(_(this))
def success = io.success
def harnessReset = this.reset.asBool
} }

View File

@@ -11,12 +11,14 @@ class AbstractConfig extends Config(
new chipyard.iobinders.WithUARTAdapter ++ // display UART with a SimUARTAdapter new chipyard.iobinders.WithUARTAdapter ++ // display UART with a SimUARTAdapter
new chipyard.iobinders.WithTieOffInterrupts ++ // tie off top-level interrupts new chipyard.iobinders.WithTieOffInterrupts ++ // tie off top-level interrupts
new chipyard.iobinders.WithBlackBoxSimMem ++ // drive the master AXI4 memory with a blackbox DRAMSim model new chipyard.iobinders.WithBlackBoxSimMem ++ // drive the master AXI4 memory with a blackbox DRAMSim model
new chipyard.iobinders.WithTiedOffDebug ++ // tie off debug (since we are using SimSerial for testing) new chipyard.iobinders.WithSimDebug ++ // attach SimJTAG
new chipyard.iobinders.WithSimSerial ++ // drive TSI with SimSerial for testing new chipyard.iobinders.WithSimSerial ++ // drive TSI with SimSerial for testing
new testchipip.WithTSI ++ // use testchipip serial offchip link new testchipip.WithTSI ++ // use testchipip serial offchip link
new chipyard.config.WithBootROM ++ // use default bootrom new chipyard.config.WithBootROM ++ // use default bootrom
new chipyard.config.WithUART ++ // add a UART new chipyard.config.WithUART ++ // add a UART
new chipyard.config.WithL2TLBs(1024) ++ // use L2 TLBs new chipyard.config.WithL2TLBs(1024) ++ // use L2 TLBs
new chipyard.config.WithNoSubsystemDrivenClocks ++ // drive the subsystem diplomatic clocks from ChipTop instead of using implicit clocks
new freechips.rocketchip.subsystem.WithJtagDTM ++ // set the debug module to expose a JTAG port
new freechips.rocketchip.subsystem.WithNoMMIOPort ++ // no top-level MMIO master port (overrides default set in rocketchip) new freechips.rocketchip.subsystem.WithNoMMIOPort ++ // no top-level MMIO master port (overrides default set in rocketchip)
new freechips.rocketchip.subsystem.WithNoSlavePort ++ // no top-level MMIO slave port (overrides default set in rocketchip) new freechips.rocketchip.subsystem.WithNoSlavePort ++ // no top-level MMIO slave port (overrides default set in rocketchip)
new freechips.rocketchip.subsystem.WithInclusiveCache ++ // use Sifive L2 cache new freechips.rocketchip.subsystem.WithInclusiveCache ++ // use Sifive L2 cache

View File

@@ -14,6 +14,6 @@ class ArianeConfig extends Config(
class dmiArianeConfig extends Config( class dmiArianeConfig extends Config(
new chipyard.iobinders.WithTiedOffSerial ++ // Tie off the serial port, override default instantiation of SimSerial new chipyard.iobinders.WithTiedOffSerial ++ // Tie off the serial port, override default instantiation of SimSerial
new chipyard.iobinders.WithSimDebug ++ // add SimDebug and use it to drive simulation, override default tie-off debug new chipyard.config.WithDMIDTM ++ // have debug module expose a clocked DMI port
new ariane.WithNArianeCores(1) ++ // single Ariane core new ariane.WithNArianeCores(1) ++ // single Ariane core
new chipyard.config.AbstractConfig) new chipyard.config.AbstractConfig)

View File

@@ -23,18 +23,10 @@ class GemminiRocketConfig extends Config(
new chipyard.config.AbstractConfig) new chipyard.config.AbstractConfig)
// DOC include end: GemminiRocketConfig // DOC include end: GemminiRocketConfig
// DOC include start: JtagRocket
class jtagRocketConfig extends Config(
new chipyard.iobinders.WithSimDebug ++ // add SimDebug, in addition to default SimSerial
new freechips.rocketchip.subsystem.WithJtagDTM ++ // sets DTM communication interface to JTAG
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig)
// DOC include end: JtagRocket
// DOC include start: DmiRocket // DOC include start: DmiRocket
class dmiRocketConfig extends Config( class dmiRocketConfig extends Config(
new chipyard.iobinders.WithTiedOffSerial ++ // tie-off serial, override default add SimSerial new chipyard.iobinders.WithTiedOffSerial ++ // don't use serial to drive the chip, since we use DMI instead
new chipyard.iobinders.WithSimDebug ++ // add SimDebug, override default tie-off debug new chipyard.config.WithDMIDTM ++ // have debug module expose a clocked DMI port
new freechips.rocketchip.subsystem.WithNBigCores(1) ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig) new chipyard.config.AbstractConfig)
// DOC include end: DmiRocket // DOC include end: DmiRocket
@@ -184,3 +176,13 @@ class MMIORocketConfig extends Config(
new freechips.rocketchip.subsystem.WithDefaultSlavePort ++ // add default external slave port new freechips.rocketchip.subsystem.WithDefaultSlavePort ++ // add default external slave port
new freechips.rocketchip.subsystem.WithNBigCores(1) ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig) new chipyard.config.AbstractConfig)
// NOTE: This config doesn't work yet because SimWidgets in the TestHarness
// always get the TestHarness clock. The Tiles and Uncore receive the correct clocks
class DividedClockRocketConfig extends Config(
new chipyard.config.WithTileDividedClock ++ // Put the Tile on its own clock domain
new freechips.rocketchip.subsystem.WithRationalRocketTiles ++ // Add rational crossings between RocketTile and uncore
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig)

View File

@@ -7,6 +7,7 @@ class TraceGenConfig extends Config(
new chipyard.iobinders.WithBlackBoxSimMem ++ new chipyard.iobinders.WithBlackBoxSimMem ++
new chipyard.iobinders.WithTraceGenSuccessBinder ++ new chipyard.iobinders.WithTraceGenSuccessBinder ++
new chipyard.config.WithTracegenSystem ++ new chipyard.config.WithTracegenSystem ++
new chipyard.config.WithNoSubsystemDrivenClocks ++
new tracegen.WithTraceGen()(List.fill(2) { DCacheParams(nMSHRs = 0, nSets = 16, nWays = 2) }) ++ new tracegen.WithTraceGen()(List.fill(2) { DCacheParams(nMSHRs = 0, nSets = 16, nWays = 2) }) ++
new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ new freechips.rocketchip.subsystem.WithCoherentBusTopology ++
new freechips.rocketchip.groundtest.GroundTestBaseConfig) new freechips.rocketchip.groundtest.GroundTestBaseConfig)
@@ -15,6 +16,7 @@ class NonBlockingTraceGenConfig extends Config(
new chipyard.iobinders.WithBlackBoxSimMem ++ new chipyard.iobinders.WithBlackBoxSimMem ++
new chipyard.iobinders.WithTraceGenSuccessBinder ++ new chipyard.iobinders.WithTraceGenSuccessBinder ++
new chipyard.config.WithTracegenSystem ++ new chipyard.config.WithTracegenSystem ++
new chipyard.config.WithNoSubsystemDrivenClocks ++
new tracegen.WithTraceGen()(List.fill(2) { DCacheParams(nMSHRs = 2, nSets = 16, nWays = 2) }) ++ new tracegen.WithTraceGen()(List.fill(2) { DCacheParams(nMSHRs = 2, nSets = 16, nWays = 2) }) ++
new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ new freechips.rocketchip.subsystem.WithCoherentBusTopology ++
new freechips.rocketchip.groundtest.GroundTestBaseConfig) new freechips.rocketchip.groundtest.GroundTestBaseConfig)
@@ -23,6 +25,7 @@ class BoomTraceGenConfig extends Config(
new chipyard.iobinders.WithBlackBoxSimMem ++ new chipyard.iobinders.WithBlackBoxSimMem ++
new chipyard.iobinders.WithTraceGenSuccessBinder ++ new chipyard.iobinders.WithTraceGenSuccessBinder ++
new chipyard.config.WithTracegenSystem ++ new chipyard.config.WithTracegenSystem ++
new chipyard.config.WithNoSubsystemDrivenClocks ++
new tracegen.WithBoomTraceGen()(List.fill(2) { DCacheParams(nMSHRs = 8, nSets = 16, nWays = 2) }) ++ new tracegen.WithBoomTraceGen()(List.fill(2) { DCacheParams(nMSHRs = 8, nSets = 16, nWays = 2) }) ++
new freechips.rocketchip.subsystem.WithInclusiveCache ++ new freechips.rocketchip.subsystem.WithInclusiveCache ++
new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ new freechips.rocketchip.subsystem.WithCoherentBusTopology ++
@@ -32,6 +35,7 @@ class NonBlockingTraceGenL2Config extends Config(
new chipyard.iobinders.WithBlackBoxSimMem ++ new chipyard.iobinders.WithBlackBoxSimMem ++
new chipyard.iobinders.WithTraceGenSuccessBinder ++ new chipyard.iobinders.WithTraceGenSuccessBinder ++
new chipyard.config.WithTracegenSystem ++ new chipyard.config.WithTracegenSystem ++
new chipyard.config.WithNoSubsystemDrivenClocks ++
new tracegen.WithL2TraceGen()(List.fill(2)(DCacheParams(nMSHRs = 2, nSets = 16, nWays = 4))) ++ new tracegen.WithL2TraceGen()(List.fill(2)(DCacheParams(nMSHRs = 2, nSets = 16, nWays = 4))) ++
new freechips.rocketchip.subsystem.WithInclusiveCache ++ new freechips.rocketchip.subsystem.WithInclusiveCache ++
new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ new freechips.rocketchip.subsystem.WithCoherentBusTopology ++
@@ -41,6 +45,7 @@ class NonBlockingTraceGenL2RingConfig extends Config(
new chipyard.iobinders.WithBlackBoxSimMem ++ new chipyard.iobinders.WithBlackBoxSimMem ++
new chipyard.iobinders.WithTraceGenSuccessBinder ++ new chipyard.iobinders.WithTraceGenSuccessBinder ++
new chipyard.config.WithTracegenSystem ++ new chipyard.config.WithTracegenSystem ++
new chipyard.config.WithNoSubsystemDrivenClocks ++
new tracegen.WithL2TraceGen()(List.fill(2)(DCacheParams(nMSHRs = 2, nSets = 16, nWays = 4))) ++ new tracegen.WithL2TraceGen()(List.fill(2)(DCacheParams(nMSHRs = 2, nSets = 16, nWays = 4))) ++
new testchipip.WithRingSystemBus ++ new testchipip.WithRingSystemBus ++
new freechips.rocketchip.subsystem.WithInclusiveCache ++ new freechips.rocketchip.subsystem.WithInclusiveCache ++

View File

@@ -23,7 +23,7 @@ class TutorialStarterConfig extends Config(
new chipyard.iobinders.WithUARTAdapter ++ // Connect a SimUART adapter to display UART on stdout new chipyard.iobinders.WithUARTAdapter ++ // Connect a SimUART adapter to display UART on stdout
new chipyard.iobinders.WithBlackBoxSimMem ++ // Connect simulated external memory new chipyard.iobinders.WithBlackBoxSimMem ++ // Connect simulated external memory
new chipyard.iobinders.WithTieOffInterrupts ++ // Do not simulate external interrupts new chipyard.iobinders.WithTieOffInterrupts ++ // Do not simulate external interrupts
new chipyard.iobinders.WithTiedOffDebug ++ // Disconnect the debug module, since we use TSI for bring-up new chipyard.iobinders.WithSimDebug ++ // Connect SimJTAG (or SimDTM) widgets to debug ios
new chipyard.iobinders.WithSimSerial ++ // Connect external SimSerial widget to drive TSI new chipyard.iobinders.WithSimSerial ++ // Connect external SimSerial widget to drive TSI
// Config fragments below this line affect hardware generation // Config fragments below this line affect hardware generation
@@ -31,6 +31,7 @@ class TutorialStarterConfig extends Config(
new testchipip.WithTSI ++ // Add a TSI (Test Serial Interface) widget to bring-up the core new testchipip.WithTSI ++ // Add a TSI (Test Serial Interface) widget to bring-up the core
new chipyard.config.WithBootROM ++ // Use the Chipyard BootROM new chipyard.config.WithBootROM ++ // Use the Chipyard BootROM
new chipyard.config.WithUART ++ // Add a UART new chipyard.config.WithUART ++ // Add a UART
new chipyard.config.WithNoSubsystemDrivenClocks ++ // Don't drive the subsystem clocks from within the subsystem
// CUSTOMIZE THE CORE // CUSTOMIZE THE CORE
// Uncomment out one (or multiple) of the lines below, and choose // Uncomment out one (or multiple) of the lines below, and choose
@@ -42,13 +43,19 @@ class TutorialStarterConfig extends Config(
// Uncomment this line, and specify a size if you want to have a L2 // Uncomment this line, and specify a size if you want to have a L2
// new freechips.rocketchip.subsystem.WithInclusiveCache(nBanks=1, nWays=4, capacityKB=128) ++ // new freechips.rocketchip.subsystem.WithInclusiveCache(nBanks=1, nWays=4, capacityKB=128) ++
// Set the debug module to expose an external JTAG port
new freechips.rocketchip.subsystem.WithJtagDTM ++
// For simpler designs, we want to minimize IOs on // For simpler designs, we want to minimize IOs on
// our Top. These config fragments remove unnecessary // our Top. These config fragments remove unnecessary
// ports // ports
new freechips.rocketchip.subsystem.WithNoMMIOPort ++ new freechips.rocketchip.subsystem.WithNoMMIOPort ++
new freechips.rocketchip.subsystem.WithNoSlavePort ++ new freechips.rocketchip.subsystem.WithNoSlavePort ++
new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++
new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ // hierarchical buses including mbus+l2
// Use the standard hierarchical bus topology including mbus+l2
new freechips.rocketchip.subsystem.WithCoherentBusTopology ++
// BaseConfig configures "bare" rocketchip system // BaseConfig configures "bare" rocketchip system
new freechips.rocketchip.system.BaseConfig new freechips.rocketchip.system.BaseConfig
) )
@@ -59,12 +66,13 @@ class TutorialMMIOConfig extends Config(
new chipyard.iobinders.WithUARTAdapter ++ new chipyard.iobinders.WithUARTAdapter ++
new chipyard.iobinders.WithBlackBoxSimMem ++ new chipyard.iobinders.WithBlackBoxSimMem ++
new chipyard.iobinders.WithTieOffInterrupts ++ new chipyard.iobinders.WithTieOffInterrupts ++
new chipyard.iobinders.WithTiedOffDebug ++ new chipyard.iobinders.WithSimDebug ++
new chipyard.iobinders.WithSimSerial ++ new chipyard.iobinders.WithSimSerial ++
new testchipip.WithTSI ++ new testchipip.WithTSI ++
new chipyard.config.WithBootROM ++ new chipyard.config.WithBootROM ++
new chipyard.config.WithUART ++ new chipyard.config.WithUART ++
new chipyard.config.WithNoSubsystemDrivenClocks ++
// Attach either a TileLink or AXI4 version of GCD // Attach either a TileLink or AXI4 version of GCD
// Uncomment one of the below lines // Uncomment one of the below lines
@@ -74,6 +82,7 @@ class TutorialMMIOConfig extends Config(
// For this demonstration we assume the base system is a single-core Rocket, for fast elaboration // For this demonstration we assume the base system is a single-core Rocket, for fast elaboration
new freechips.rocketchip.subsystem.WithNBigCores(1) ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new freechips.rocketchip.subsystem.WithInclusiveCache ++ new freechips.rocketchip.subsystem.WithInclusiveCache ++
new freechips.rocketchip.subsystem.WithJtagDTM ++
new freechips.rocketchip.subsystem.WithNoMMIOPort ++ new freechips.rocketchip.subsystem.WithNoMMIOPort ++
new freechips.rocketchip.subsystem.WithNoSlavePort ++ new freechips.rocketchip.subsystem.WithNoSlavePort ++
new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++
@@ -86,18 +95,20 @@ class TutorialSha3Config extends Config(
new chipyard.iobinders.WithUARTAdapter ++ new chipyard.iobinders.WithUARTAdapter ++
new chipyard.iobinders.WithBlackBoxSimMem ++ new chipyard.iobinders.WithBlackBoxSimMem ++
new chipyard.iobinders.WithTieOffInterrupts ++ new chipyard.iobinders.WithTieOffInterrupts ++
new chipyard.iobinders.WithTiedOffDebug ++ new chipyard.iobinders.WithSimDebug ++
new chipyard.iobinders.WithSimSerial ++ new chipyard.iobinders.WithSimSerial ++
new testchipip.WithTSI ++ new testchipip.WithTSI ++
new chipyard.config.WithBootROM ++ new chipyard.config.WithBootROM ++
new chipyard.config.WithUART ++ new chipyard.config.WithUART ++
new chipyard.config.WithNoSubsystemDrivenClocks ++
// Uncomment this line once you added SHA3 to the build.sbt, and cloned the SHA3 repo // Uncomment this line once you added SHA3 to the build.sbt, and cloned the SHA3 repo
// new sha3.WithSha3Accel ++ // new sha3.WithSha3Accel ++
// For this demonstration we assume the base system is a single-core Rocket, for fast elaboration // For this demonstration we assume the base system is a single-core Rocket, for fast elaboration
new freechips.rocketchip.subsystem.WithNBigCores(1) ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new freechips.rocketchip.subsystem.WithJtagDTM ++
new freechips.rocketchip.subsystem.WithInclusiveCache ++ new freechips.rocketchip.subsystem.WithInclusiveCache ++
new freechips.rocketchip.subsystem.WithNoMMIOPort ++ new freechips.rocketchip.subsystem.WithNoMMIOPort ++
new freechips.rocketchip.subsystem.WithNoSlavePort ++ new freechips.rocketchip.subsystem.WithNoSlavePort ++
@@ -111,12 +122,13 @@ class TutorialSha3BlackBoxConfig extends Config(
new chipyard.iobinders.WithUARTAdapter ++ new chipyard.iobinders.WithUARTAdapter ++
new chipyard.iobinders.WithBlackBoxSimMem ++ new chipyard.iobinders.WithBlackBoxSimMem ++
new chipyard.iobinders.WithTieOffInterrupts ++ new chipyard.iobinders.WithTieOffInterrupts ++
new chipyard.iobinders.WithTiedOffDebug ++ new chipyard.iobinders.WithSimDebug ++
new chipyard.iobinders.WithSimSerial ++ new chipyard.iobinders.WithSimSerial ++
new testchipip.WithTSI ++ new testchipip.WithTSI ++
new chipyard.config.WithBootROM ++ new chipyard.config.WithBootROM ++
new chipyard.config.WithUART ++ new chipyard.config.WithUART ++
new chipyard.config.WithNoSubsystemDrivenClocks ++
// Uncomment these lines once SHA3 is integrated // Uncomment these lines once SHA3 is integrated
// new sha3.WithSha3BlackBox ++ // Specify we want the Black-box verilog version of Sha3 Ctrl // new sha3.WithSha3BlackBox ++ // Specify we want the Black-box verilog version of Sha3 Ctrl
@@ -124,6 +136,7 @@ class TutorialSha3BlackBoxConfig extends Config(
// For this demonstration we assume the base system is a single-core Rocket, for fast elaboration // For this demonstration we assume the base system is a single-core Rocket, for fast elaboration
new freechips.rocketchip.subsystem.WithNBigCores(1) ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new freechips.rocketchip.subsystem.WithJtagDTM ++
new freechips.rocketchip.subsystem.WithInclusiveCache ++ new freechips.rocketchip.subsystem.WithInclusiveCache ++
new freechips.rocketchip.subsystem.WithNoMMIOPort ++ new freechips.rocketchip.subsystem.WithNoMMIOPort ++
new freechips.rocketchip.subsystem.WithNoSlavePort ++ new freechips.rocketchip.subsystem.WithNoSlavePort ++

View File

@@ -58,7 +58,7 @@ class WithBlockDeviceBridge extends OverrideIOBinder({
class WithFASEDBridge extends OverrideIOBinder({ class WithFASEDBridge extends OverrideIOBinder({
(system: CanHaveMasterAXI4MemPort) => { (system: CanHaveMasterAXI4MemPort) => {
implicit val p: Parameters = GetSystemParameters(system) implicit val p: Parameters = GetSystemParameters(system)
(system.mem_axi4 zip system.memAXI4Node.in).foreach({ case (axi4, (_, edge)) => (system.mem_axi4 zip system.memAXI4Node.edges.in).foreach({ case (axi4, edge) =>
val nastiKey = NastiParameters(axi4.r.bits.data.getWidth, val nastiKey = NastiParameters(axi4.r.bits.data.getWidth,
axi4.ar.bits.addr.getWidth, axi4.ar.bits.addr.getWidth,
axi4.ar.bits.id.getWidth) axi4.ar.bits.id.getWidth)

View File

@@ -3,13 +3,17 @@
package firesim.firesim package firesim.firesim
import chisel3._ import chisel3._
import chisel3.experimental.{IO}
import freechips.rocketchip.prci._
import freechips.rocketchip.subsystem.{BaseSubsystem, SubsystemDriveAsyncClockGroupsKey}
import freechips.rocketchip.config.{Field, Config, Parameters} import freechips.rocketchip.config.{Field, Config, Parameters}
import freechips.rocketchip.diplomacy.{LazyModule} import freechips.rocketchip.diplomacy.{LazyModule, InModuleBody}
import freechips.rocketchip.util.{ResetCatchAndSync}
import midas.widgets.{Bridge, PeekPokeBridge, RationalClockBridge} import midas.widgets.{Bridge, PeekPokeBridge, RationalClockBridge, RationalClock}
import chipyard.{BuildSystem} import chipyard.{BuildSystem, BuildTop, HasHarnessSignalReferences, ChipyardSubsystem, ClockingSchemeKey, ChipTop}
import chipyard.iobinders.{IOBinders} import chipyard.iobinders.{IOBinders}
// Determines the number of times to instantiate the DUT in the harness. // Determines the number of times to instantiate the DUT in the harness.
@@ -20,6 +24,16 @@ class WithNumNodes(n: Int) extends Config((pname, site, here) => {
case NumNodes => n case NumNodes => n
}) })
// Note, the main prerequisite for supporting an additional clock domain in a
// FireSim simulation is to supply an additional clock parameter
// (RationalClock) to the clock bridge (RationalClockBridge). The bridge
// produces a vector of clocks, based on the provided parameter list, which you
// may use freely without further modifications to your target design.
case class FireSimClockParameters(additionalClocks: Seq[RationalClock]) {
def numClocks(): Int = additionalClocks.size + 1
}
case object FireSimClockKey extends Field[FireSimClockParameters](FireSimClockParameters(Seq()))
// Hacky: Set before each node is generated. Ideally we'd give IO binders // Hacky: Set before each node is generated. Ideally we'd give IO binders
// accesses to the the Harness's parameters instance. We could then alter that. // accesses to the the Harness's parameters instance. We could then alter that.
object NodeIdx { object NodeIdx {
@@ -28,33 +42,125 @@ object NodeIdx {
def apply(): Int = idx def apply(): Int = idx
} }
class FireSim(implicit val p: Parameters) extends RawModule { class WithFireSimSimpleClocks extends Config((site, here, up) => {
freechips.rocketchip.util.property.cover.setPropLib(new midas.passes.FireSimPropertyLibrary()) case ClockingSchemeKey => { chiptop: ChipTop =>
val clockBridge = Module(new RationalClockBridge) implicit val p = chiptop.p
val clock = clockBridge.io.clocks.head
val reset = WireInit(false.B) val implicitClockSourceNode = ClockSourceNode(Seq(ClockSourceParameters()))
withClockAndReset(clock, reset) { chiptop.implicitClockSinkNode := implicitClockSourceNode
// Instantiate multiple instances of the DUT to implement supernode
val targets = Seq.fill(p(NumNodes)) { // Drive the diplomaticclock graph of the DigitalTop (if present)
// It's not a RC bump without some hacks... val simpleClockGroupSourceNode = chiptop.lSystem match {
// Copy the AsyncClockGroupsKey to generate a fresh node on each case l: BaseSubsystem if (p(SubsystemDriveAsyncClockGroupsKey).isEmpty) => {
// instantiation of the dut, otherwise the initial instance will be val n = ClockGroupSourceNode(Seq(ClockGroupSourceParameters()))
// reused across each node l.asyncClockGroupsNode := n
import freechips.rocketchip.subsystem.AsyncClockGroupsKey Some(n)
val lazyModule = p(BuildSystem)(p.alterPartial({ }
case AsyncClockGroupsKey => p(AsyncClockGroupsKey).copy case _ => None
}))
(lazyModule, Module(lazyModule.module))
} }
val peekPokeBridge = PeekPokeBridge(clock, reset) InModuleBody {
// A Seq of partial functions that will instantiate the right bridge only val clock = IO(Input(Clock())).suggestName("clock")
// if that Mixin trait is present in the target's LazyModule class instance val reset = IO(Input(Reset())).suggestName("reset")
//
// Apply each partial function to each DUT instance implicitClockSourceNode.out.unzip._1.map { o =>
for ((lazyModule, module) <- targets) { o.clock := clock
p(IOBinders).values.foreach(f => f(lazyModule) ++ f(module)) o.reset := reset
NodeIdx.increment() }
simpleClockGroupSourceNode.map { n => n.out.unzip._1.map { out: ClockGroupBundle =>
out.member.data.foreach { o =>
o.clock := clock
o.reset := reset
}
}}
chiptop.harnessFunctions += ((th: HasHarnessSignalReferences) => {
clock := th.harnessClock
reset := th.harnessReset
Nil
})
} }
} }
})
class WithFireSimRationalTileDomain(multiplier: Int, divisor: Int) extends Config((site, here, up) => {
case FireSimClockKey => FireSimClockParameters(Seq(RationalClock("TileDomain", multiplier, divisor)))
case ClockingSchemeKey => { chiptop: ChipTop =>
implicit val p = chiptop.p
val implicitClockSourceNode = ClockSourceNode(Seq(ClockSourceParameters()))
chiptop.implicitClockSinkNode := implicitClockSourceNode
// Drive the diplomaticclock graph of the DigitalTop (if present)
val simpleClockGroupSourceNode = chiptop.lSystem match {
case l: BaseSubsystem if (p(SubsystemDriveAsyncClockGroupsKey).isEmpty) => {
val n = ClockGroupSourceNode(Seq(ClockGroupSourceParameters()))
l.asyncClockGroupsNode := n
Some(n)
}
case _ => None
}
InModuleBody {
val uncore_clock = IO(Input(Clock())).suggestName("uncore_clock")
val tile_clock = IO(Input(Clock())).suggestName("tile_clock")
val reset = IO(Input(Reset())).suggestName("reset")
implicitClockSourceNode.out.unzip._1.map { o =>
o.clock := uncore_clock
o.reset := reset
}
simpleClockGroupSourceNode.map { n => n.out.unzip._1.map { out: ClockGroupBundle =>
out.member.elements.map { case (name, data) =>
// This is mega hacks, how are you actually supposed to do this?
if (name.contains("core")) {
data.clock := tile_clock
data.reset := ResetCatchAndSync(tile_clock, reset.asBool)
} else {
data.clock := uncore_clock
data.reset := reset
}
}
}}
chiptop.harnessFunctions += ((th: HasHarnessSignalReferences) => {
uncore_clock := th.harnessClock
reset := th.harnessReset
th match {
case f: FireSim => tile_clock := f.additionalClocks(0)
case _ => throw new Exception("FireSimMultiClock must be used with FireSim")
}
Nil
})
}
}
})
class FireSim(implicit val p: Parameters) extends RawModule with HasHarnessSignalReferences {
freechips.rocketchip.util.property.cover.setPropLib(new midas.passes.FireSimPropertyLibrary())
val clockBridge = Module(new RationalClockBridge(p(FireSimClockKey).additionalClocks:_*))
val harnessClock = clockBridge.io.clocks.head // This is the reference clock
val additionalClocks = clockBridge.io.clocks.tail
val harnessReset = WireInit(false.B)
val peekPokeBridge = PeekPokeBridge(harnessClock, harnessReset)
def dutReset = { require(false, "dutReset should not be used in Firesim"); false.B }
def success = { require(false, "success should not be used in Firesim"); false.B }
// Instantiate multiple instances of the DUT to implement supernode
for (i <- 0 until p(NumNodes)) {
// It's not a RC bump without some hacks...
// Copy the AsyncClockGroupsKey to generate a fresh node on each
// instantiation of the dut, otherwise the initial instance will be
// reused across each node
import freechips.rocketchip.subsystem.AsyncClockGroupsKey
val lazyModule = LazyModule(p(BuildTop)(p.alterPartial({
case AsyncClockGroupsKey => p(AsyncClockGroupsKey).copy
})))
val module = Module(lazyModule.module)
require(lazyModule.harnessFunctions.size == 1, "There should only be 1 harness function to connect clock+reset")
lazyModule.harnessFunctions.foreach(_(this))
NodeIdx.increment()
}
} }

View File

@@ -1,107 +0,0 @@
//See LICENSE for license details.
package firesim.firesim
import chisel3._
import freechips.rocketchip.config.{Field, Config, Parameters}
import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp, RationalCrossing}
import freechips.rocketchip.subsystem._
import freechips.rocketchip.util.{ResetCatchAndSync}
import midas.widgets.{Bridge, PeekPokeBridge, RationalClockBridge, RationalClock}
import firesim.configs._
import boom.common.{WithRationalBoomTiles}
import chipyard.{BuildSystem, DigitalTop, DigitalTopModule}
import chipyard.config.ConfigValName._
import chipyard.iobinders.{IOBinders}
// WIP! This file is a sketch of one means of defining a multiclock target-design
// that can be simulated in FireSim, pending a canonicalized form in Chipyard.
//
// Note, the main prerequisite for supporting an additional clock domain in a
// FireSim simulation is to supply an additional clock parameter
// (RationalClock) to the clock bridge (RationalClockBridge). The bridge
// produces a vector of clocks, based on the provided parameter list, which you
// may use freely without further modifications to your target design.
case class FireSimClockParameters(additionalClocks: Seq[RationalClock]) {
def numClocks(): Int = additionalClocks.size + 1
}
case object FireSimClockKey extends Field[FireSimClockParameters](FireSimClockParameters(Seq()))
trait HasAdditionalClocks extends LazyModuleImp {
val clocks = IO(Vec(p(FireSimClockKey).numClocks, Input(Clock())))
}
// Presupposes only 1 or 2 clocks.
trait HasFireSimClockingImp extends HasAdditionalClocks {
val outer: HasTiles
val (tileClock, tileReset) = p(FireSimClockKey).additionalClocks.headOption match {
case Some(RationalClock(_, numer, denom)) if numer != denom => (clocks(1), ResetCatchAndSync(clocks(1), reset.toBool))
case None => (clocks.head, reset)
}
outer.tiles.foreach({ case tile =>
tile.module.clock := tileClock
tile.module.reset := tileReset
})
}
// Config Fragment
class WithSingleRationalTileDomain(multiplier: Int, divisor: Int) extends Config(
new WithRationalRocketTiles ++
new WithRationalBoomTiles ++
new Config((site, here, up) => {
case FireSimClockKey => FireSimClockParameters(Seq(RationalClock("TileDomain", multiplier, divisor)))
})
)
class HalfRateUncore extends WithSingleRationalTileDomain(2,1)
class WithFiresimMulticlockTop extends Config((site, here, up) => {
case BuildSystem => (p: Parameters) => LazyModule(new FiresimMulticlockTop()(p)).suggestName("system")
})
// Complete Config
class FireSimQuadRocketMulticlockConfig extends Config(
new HalfRateUncore ++
new WithFiresimMulticlockTop ++
new FireSimQuadRocketConfig)
// Top Definition
class FiresimMulticlockTop(implicit p: Parameters) extends chipyard.DigitalTop
{
override lazy val module = new FiresimMulticlockTopModule(this)
}
class FiresimMulticlockTopModule[+L <: DigitalTop](l: L) extends chipyard.DigitalTopModule(l) with HasFireSimClockingImp
// Harness Definition
class FireSimMulticlockPOC(implicit val p: Parameters) extends RawModule {
freechips.rocketchip.util.property.cover.setPropLib(new midas.passes.FireSimPropertyLibrary())
val clockBridge = Module(new RationalClockBridge(p(FireSimClockKey).additionalClocks:_*))
val refClock = clockBridge.io.clocks.head
val reset = WireInit(false.B)
withClockAndReset(refClock, reset) {
// Instantiate multiple instances of the DUT to implement supernode
val targets = Seq.fill(p(NumNodes)) {
val lazyModule = p(BuildSystem)(p)
(lazyModule, Module(lazyModule.module))
}
val peekPokeBridge = PeekPokeBridge(refClock, reset)
// A Seq of partial functions that will instantiate the right bridge only
// if that Mixin trait is present in the target's class instance
//
// Apply each partial function to each DUT instance
for ((lazyModule, module) <- targets) {
p(IOBinders).values.foreach(f => f(lazyModule) ++ f(module))
}
targets.collect({ case (_, t: HasAdditionalClocks) => t.clocks := clockBridge.io.clocks })
}
}

View File

@@ -10,7 +10,7 @@ import freechips.rocketchip.tile._
import freechips.rocketchip.tilelink._ import freechips.rocketchip.tilelink._
import freechips.rocketchip.rocket.DCacheParams import freechips.rocketchip.rocket.DCacheParams
import freechips.rocketchip.subsystem._ import freechips.rocketchip.subsystem._
import freechips.rocketchip.devices.tilelink.BootROMParams import freechips.rocketchip.devices.tilelink.{BootROMLocated, BootROMParams}
import freechips.rocketchip.devices.debug.{DebugModuleParams, DebugModuleKey} import freechips.rocketchip.devices.debug.{DebugModuleParams, DebugModuleKey}
import freechips.rocketchip.diplomacy.LazyModule import freechips.rocketchip.diplomacy.LazyModule
import testchipip.{BlockDeviceKey, BlockDeviceConfig, SerialKey, TracePortKey, TracePortParams} import testchipip.{BlockDeviceKey, BlockDeviceConfig, SerialKey, TracePortKey, TracePortParams}
@@ -22,19 +22,18 @@ import testchipip.WithRingSystemBus
import firesim.bridges._ import firesim.bridges._
import firesim.configs._ import firesim.configs._
import chipyard.config.ConfigValName._
class WithBootROM extends Config((site, here, up) => { class WithBootROM extends Config((site, here, up) => {
case BootROMParams => { case BootROMLocated(x) => {
val chipyardBootROM = new File(s"./generators/testchipip/bootrom/bootrom.rv${site(XLen)}.img") val chipyardBootROM = new File(s"./generators/testchipip/bootrom/bootrom.rv${site(XLen)}.img")
val firesimBootROM = new File(s"./target-rtl/chipyard/generators/testchipip/bootrom/bootrom.rv${site(XLen)}.img") val firesimBootROM = new File(s"./target-rtl/chipyard/generators/testchipip/bootrom/bootrom.rv${site(XLen)}.img")
val bootROMPath = if (chipyardBootROM.exists()) { val bootROMPath = if (chipyardBootROM.exists()) {
chipyardBootROM.getAbsolutePath() chipyardBootROM.getAbsolutePath()
} else { } else {
firesimBootROM.getAbsolutePath() firesimBootROM.getAbsolutePath()
} }
BootROMParams(contentFileName = bootROMPath) up(BootROMLocated(x), site).map(_.copy(contentFileName = bootROMPath))
} }
}) })
@@ -67,6 +66,8 @@ class WithNVDLASmall extends nvidia.blocks.dla.WithNVDLA("small")
// Tweaks that are generally applied to all firesim configs // Tweaks that are generally applied to all firesim configs
class WithFireSimConfigTweaks extends Config( class WithFireSimConfigTweaks extends Config(
// Required*: Uses FireSim ClockBridge and PeekPokeBridge to drive the system with a single clock/reset
new WithFireSimSimpleClocks ++
// Required*: When using FireSim-as-top to provide a correct path to the target bootrom source // Required*: When using FireSim-as-top to provide a correct path to the target bootrom source
new WithBootROM ++ new WithBootROM ++
// Optional*: Removing this will require adjusting the UART baud rate and // Optional*: Removing this will require adjusting the UART baud rate and
@@ -87,7 +88,9 @@ class WithFireSimConfigTweaks extends Config(
// Optional: Removing this will require using an initramfs under linux // Optional: Removing this will require using an initramfs under linux
new testchipip.WithBlockDevice ++ new testchipip.WithBlockDevice ++
// Required*: Scale default baud rate with periphery bus frequency // Required*: Scale default baud rate with periphery bus frequency
new chipyard.config.WithUART(BigInt(3686400L)) new chipyard.config.WithUART(BigInt(3686400L)) ++
// Required: Do not support debug module w. JTAG until FIRRTL stops emitting @(posedge ~clock)
new chipyard.config.WithNoDebug
) )
/******************************************************************************* /*******************************************************************************
@@ -186,3 +189,14 @@ class FireSimArianeConfig extends Config(
new WithDefaultMemModel ++ new WithDefaultMemModel ++
new WithFireSimConfigTweaks ++ new WithFireSimConfigTweaks ++
new chipyard.ArianeConfig) new chipyard.ArianeConfig)
//**********************************************************************************
//* Multiclock Configurations
//*********************************************************************************/
class FireSimMulticlockRocketConfig extends Config(
new WithFireSimRationalTileDomain(2, 1) ++
new WithDefaultFireSimBridges ++
new WithDefaultMemModel ++
new WithFireSimConfigTweaks ++
new chipyard.DividedClockRocketConfig)

View File

@@ -106,8 +106,8 @@ class BoomF1Tests extends FireSimTestSuite("FireSim", "DDR3FRFCFSLLC4MB_FireSimL
class RocketNICF1Tests extends FireSimTestSuite("FireSim", "WithNIC_DDR3FRFCFSLLC4MB_FireSimRocketConfig", "BaseF1Config") class RocketNICF1Tests extends FireSimTestSuite("FireSim", "WithNIC_DDR3FRFCFSLLC4MB_FireSimRocketConfig", "BaseF1Config")
// Multiclock tests // Multiclock tests
class RocketMulticlockF1Tests extends FireSimTestSuite( class RocketMulticlockF1Tests extends FireSimTestSuite(
"FireSimMulticlockPOC", "FireSim",
"FireSimQuadRocketMulticlockConfig", "FireSimMulticlockRocketConfig",
"WithSynthAsserts_BaseF1Config") "WithSynthAsserts_BaseF1Config")
class ArianeF1Tests extends FireSimTestSuite("FireSim", "WithNIC_DDR3FRFCFSLLC4MB_FireSimArianeConfig", "BaseF1Config") class ArianeF1Tests extends FireSimTestSuite("FireSim", "WithNIC_DDR3FRFCFSLLC4MB_FireSimArianeConfig", "BaseF1Config")

View File

@@ -12,6 +12,10 @@ class TraceGenSystem(implicit p: Parameters) extends BaseSubsystem
with CanHaveMasterAXI4MemPort { with CanHaveMasterAXI4MemPort {
def coreMonitorBundles = Nil def coreMonitorBundles = Nil
val tileStatusNodes = tiles.collect {
case t: GroundTestTile => t.statusNode.makeSink()
case t: BoomTraceGenTile => t.statusNode.makeSink()
}
override lazy val module = new TraceGenSystemModuleImp(this) override lazy val module = new TraceGenSystemModuleImp(this)
} }
@@ -20,12 +24,8 @@ class TraceGenSystemModuleImp(outer: TraceGenSystem)
{ {
val success = IO(Output(Bool())) val success = IO(Output(Bool()))
outer.tiles.zipWithIndex.map { case(t, i) => t.module.constants.hartid := i.U } val status = dontTouch(DebugCombiner(outer.tileStatusNodes.map(_.bundle)))
val status = dontTouch(DebugCombiner(outer.tiles.collect {
case t: GroundTestTile => t.module.status
case t: BoomTraceGenTile => t.module.status
}))
success := outer.tileCeaseSinkNode.in.head._1.asUInt.andR success := outer.tileCeaseSinkNode.in.head._1.asUInt.andR
} }

View File

@@ -3,7 +3,7 @@ package tracegen
import chisel3._ import chisel3._
import chisel3.util._ import chisel3.util._
import freechips.rocketchip.config.Parameters import freechips.rocketchip.config.Parameters
import freechips.rocketchip.diplomacy.{SimpleDevice, LazyModule, SynchronousCrossing, ClockCrossingType} import freechips.rocketchip.diplomacy.{SimpleDevice, LazyModule, SynchronousCrossing, ClockCrossingType, BundleBridgeSource}
import freechips.rocketchip.groundtest._ import freechips.rocketchip.groundtest._
import freechips.rocketchip.rocket._ import freechips.rocketchip.rocket._
import freechips.rocketchip.rocket.constants.{MemoryOpConstants} import freechips.rocketchip.rocket.constants.{MemoryOpConstants}
@@ -206,11 +206,13 @@ class BoomTraceGenTile private(
val cpuDevice: SimpleDevice = new SimpleDevice("groundtest", Nil) val cpuDevice: SimpleDevice = new SimpleDevice("groundtest", Nil)
val intOutwardNode: IntOutwardNode = IntIdentityNode() val intOutwardNode: IntOutwardNode = IntIdentityNode()
val slaveNode: TLInwardNode = TLIdentityNode() val slaveNode: TLInwardNode = TLIdentityNode()
val statusNode = BundleBridgeSource(() => new GroundTestStatus)
val boom_params = p.alterMap(Map(TileKey -> BoomTileParams( val boom_params = p.alterMap(Map(TileKey -> BoomTileParams(
dcache=params.dcache, dcache=params.dcache,
core=BoomCoreParams(nPMPs=0, numLdqEntries=32, numStqEntries=32, useVM=false)))) core=BoomCoreParams(nPMPs=0, numLdqEntries=16, numStqEntries=16, useVM=false))))
val dcache = LazyModule(new BoomNonBlockingDCache(hartId)(boom_params)) val dcache = LazyModule(new BoomNonBlockingDCache(staticIdForMetadataUseOnly)(boom_params))
val masterNode: TLOutwardNode = TLIdentityNode() := visibilityNode := dcache.node val masterNode: TLOutwardNode = TLIdentityNode() := visibilityNode := dcache.node
@@ -220,11 +222,11 @@ class BoomTraceGenTile private(
class BoomTraceGenTileModuleImp(outer: BoomTraceGenTile) class BoomTraceGenTileModuleImp(outer: BoomTraceGenTile)
extends BaseTileModuleImp(outer){ extends BaseTileModuleImp(outer){
val status = IO(new GroundTestStatus) val status = outer.statusNode.bundle
val halt_and_catch_fire = None val halt_and_catch_fire = None
val tracegen = Module(new TraceGenerator(outer.params.traceParams)) val tracegen = Module(new TraceGenerator(outer.params.traceParams))
tracegen.io.hartid := constants.hartid tracegen.io.hartid := outer.hartIdSinkNode.bundle
val ptw = Module(new DummyPTW(1)) val ptw = Module(new DummyPTW(1))
val lsu = Module(new LSU()(outer.boom_params, outer.dcache.module.edge)) val lsu = Module(new LSU()(outer.boom_params, outer.dcache.module.edge))

View File

@@ -1,11 +1,15 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
// See LICENSE.Berkeley for license details. // See LICENSE.Berkeley for license details.
#include "verilated.h"
#if VM_TRACE #if VM_TRACE
#include <memory> #include <memory>
#if CY_FST_TRACE
#include "verilated_fst_c.h"
#else
#include "verilated.h"
#include "verilated_vcd_c.h" #include "verilated_vcd_c.h"
#endif #endif // CY_FST_TRACE
#endif // VM_TRACE
#include <fesvr/dtm.h> #include <fesvr/dtm.h>
#include <fesvr/tsi.h> #include <fesvr/tsi.h>
#include "remote_bitbang.h" #include "remote_bitbang.h"
@@ -113,6 +117,7 @@ int main(int argc, char** argv)
// Port numbers are 16 bit unsigned integers. // Port numbers are 16 bit unsigned integers.
uint16_t rbb_port = 0; uint16_t rbb_port = 0;
#if VM_TRACE #if VM_TRACE
const char* vcdfile_name = NULL;
FILE * vcdfile = NULL; FILE * vcdfile = NULL;
uint64_t start = 0; uint64_t start = 0;
#endif #endif
@@ -157,6 +162,7 @@ int main(int argc, char** argv)
case 'o': opterr = 1; break; case 'o': opterr = 1; break;
#if VM_TRACE #if VM_TRACE
case 'v': { case 'v': {
vcdfile_name = optarg;
vcdfile = strcmp(optarg, "-") == 0 ? stdout : fopen(optarg, "w"); vcdfile = strcmp(optarg, "-") == 0 ? stdout : fopen(optarg, "w");
if (!vcdfile) { if (!vcdfile) {
std::cerr << "Unable to open " << optarg << " for VCD write\n"; std::cerr << "Unable to open " << optarg << " for VCD write\n";
@@ -264,17 +270,20 @@ done_processing:
#if VM_TRACE #if VM_TRACE
Verilated::traceEverOn(true); // Verilator must compute traced signals Verilated::traceEverOn(true); // Verilator must compute traced signals
#if CY_FST_TRACE
std::unique_ptr<VerilatedFstC> tfp(new VerilatedFstC);
#else
std::unique_ptr<VerilatedVcdFILE> vcdfd(new VerilatedVcdFILE(vcdfile)); std::unique_ptr<VerilatedVcdFILE> vcdfd(new VerilatedVcdFILE(vcdfile));
std::unique_ptr<VerilatedVcdC> tfp(new VerilatedVcdC(vcdfd.get())); std::unique_ptr<VerilatedVcdC> tfp(new VerilatedVcdC(vcdfd.get()));
if (vcdfile) { #endif // CY_FST_TRACE
if (vcdfile_name) {
tile->trace(tfp.get(), 99); // Trace 99 levels of hierarchy tile->trace(tfp.get(), 99); // Trace 99 levels of hierarchy
tfp->open(""); tfp->open(vcdfile_name);
} }
#endif #endif // VM_TRACE
// RocketChip currently only supports RBB port 0, so this needs to stay here
jtag = new remote_bitbang_t(rbb_port); jtag = new remote_bitbang_t(rbb_port);
dtm = new dtm_t(argc, argv);
tsi = new tsi_t(argc, argv);
signal(SIGTERM, handle_sigterm); signal(SIGTERM, handle_sigterm);
@@ -304,8 +313,7 @@ done_processing:
tile->reset = 0; tile->reset = 0;
done_reset = true; done_reset = true;
while (!dtm->done() && !jtag->done() && !tsi->done() && do {
!tile->io_success && trace_count < max_cycles) {
tile->clock = 0; tile->clock = 0;
tile->eval(); tile->eval();
#if VM_TRACE #if VM_TRACE
@@ -322,6 +330,13 @@ done_processing:
#endif #endif
trace_count++; trace_count++;
} }
// for verilator multithreading. need to do 1 loop before checking if
// tsi exists, since tsi is created by verilated thread on the first
// serial_tick.
while ((!dtm || !dtm->done()) &&
(!jtag || !jtag->done()) &&
(!tsi || !tsi->done()) &&
!tile->io_success && trace_count < max_cycles);
#if VM_TRACE #if VM_TRACE
if (tfp) if (tfp)
@@ -330,17 +345,17 @@ done_processing:
fclose(vcdfile); fclose(vcdfile);
#endif #endif
if (dtm->exit_code()) if (dtm && dtm->exit_code())
{ {
fprintf(stderr, "*** FAILED *** via dtm (code = %d, seed %d) after %ld cycles\n", dtm->exit_code(), random_seed, trace_count); fprintf(stderr, "*** FAILED *** via dtm (code = %d, seed %d) after %ld cycles\n", dtm->exit_code(), random_seed, trace_count);
ret = dtm->exit_code(); ret = dtm->exit_code();
} }
else if (tsi->exit_code()) else if (tsi && tsi->exit_code())
{ {
fprintf(stderr, "*** FAILED *** (code = %d, seed %d) after %ld cycles\n", tsi->exit_code(), random_seed, trace_count); fprintf(stderr, "*** FAILED *** (code = %d, seed %d) after %ld cycles\n", tsi->exit_code(), random_seed, trace_count);
ret = tsi->exit_code(); ret = tsi->exit_code();
} }
else if (jtag->exit_code()) else if (jtag && jtag->exit_code())
{ {
fprintf(stderr, "*** FAILED *** via jtag (code = %d, seed %d) after %ld cycles\n", jtag->exit_code(), random_seed, trace_count); fprintf(stderr, "*** FAILED *** via jtag (code = %d, seed %d) after %ld cycles\n", jtag->exit_code(), random_seed, trace_count);
ret = jtag->exit_code(); ret = jtag->exit_code();

View File

@@ -6,8 +6,8 @@
set -e set -e
set -o pipefail set -o pipefail
RDIR=$(pwd) DIR="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")"
CHIPYARD_DIR="${CHIPYARD_DIR:-$(git rev-parse --show-toplevel)}" CHIPYARD_DIR="$(dirname "$DIR")"
usage() { usage() {
echo "usage: ${0} [OPTIONS] [riscv-tools | esp-tools | ec2fast]" echo "usage: ${0} [OPTIONS] [riscv-tools | esp-tools | ec2fast]"
@@ -134,18 +134,16 @@ SRCDIR="$(pwd)/toolchains" module_all qemu --prefix="${RISCV}" --target-list=ris
git submodule update --init $CHIPYARD_DIR/tools/dromajo/dromajo-src git submodule update --init $CHIPYARD_DIR/tools/dromajo/dromajo-src
make -C $CHIPYARD_DIR/tools/dromajo/dromajo-src/src make -C $CHIPYARD_DIR/tools/dromajo/dromajo-src/src
cd "$RDIR"
# create specific env.sh # create specific env.sh
{ cat > "$CHIPYARD_DIR/env-$TOOLCHAIN.sh" <<EOF
echo "# auto-generated by build-toolchains.sh" # auto-generated by build-toolchains.sh
echo "export CHIPYARD_TOOLCHAIN_SOURCED=1" export CHIPYARD_TOOLCHAIN_SOURCED=1
echo "export RISCV=$(printf '%q' "$RISCV")" export RISCV=$(printf '%q' "$RISCV")
echo "export PATH=\${RISCV}/bin:\${PATH}" export PATH=\${RISCV}/bin:\${PATH}
echo "export LD_LIBRARY_PATH=\${RISCV}/lib\${LD_LIBRARY_PATH:+":\${LD_LIBRARY_PATH}"}" export LD_LIBRARY_PATH=\${RISCV}/lib\${LD_LIBRARY_PATH:+":\${LD_LIBRARY_PATH}"}
} > env-$TOOLCHAIN.sh EOF
# create general env.sh # create general env.sh
echo "# line auto-generated by build-toolchains.sh" >> env.sh echo "# line auto-generated by build-toolchains.sh" >> env.sh
echo "source \$( realpath \$(dirname "\${BASH_SOURCE[0]:-\${\(%\):-%x}}") )/env-$TOOLCHAIN.sh" >> env.sh echo "source $(printf '%q' "$CHIPYARD_DIR/env-$TOOLCHAIN.sh")" >> env.sh
echo "Toolchain Build Complete!" echo "Toolchain Build Complete!"

View File

@@ -15,7 +15,7 @@ case ${ncpu} in
esac esac
# Allow user to override MAKE # Allow user to override MAKE
[ -n "${MAKE}" ] || MAKE=$(command -v gnumake || command -v gmake || command -v make) [ -n "${MAKE:+x}" ] || MAKE=$(command -v gnumake || command -v gmake || command -v make)
readonly MAKE readonly MAKE

View File

@@ -17,10 +17,11 @@ if [ "$MINGIT" != "$(echo -e "$MINGIT\n$MYGIT" | sort -V | head -n1)" ]; then
false false
fi fi
RDIR=$(git rev-parse --show-toplevel) DIR="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")"
CHIPYARD_DIR="$(dirname "$DIR")"
# Ignore toolchain submodules # Ignore toolchain submodules
cd "$RDIR" cd "$CHIPYARD_DIR"
for name in toolchains/*-tools/*/ ; do for name in toolchains/*-tools/*/ ; do
git config submodule."${name%/}".update none git config submodule."${name%/}".update none
done done
@@ -71,8 +72,11 @@ git config submodule.sims/firesim.update none
git submodule update --init software/firemarshal git submodule update --init software/firemarshal
# Configure firemarshal to know where our firesim installation is # Configure firemarshal to know where our firesim installation is
if [ ! -f $RDIR/software/firemarshal/marshal-config.yaml ]; then if [ ! -f ./software/firemarshal/marshal-config.yaml ]; then
echo "firesim-dir: '../../sims/firesim/'" > $RDIR/software/firemarshal/marshal-config.yaml echo "firesim-dir: '../../sims/firesim/'" > ./software/firemarshal/marshal-config.yaml
fi fi
echo "# line auto-generated by init-submodules-no-riscv-tools.sh" >> $RDIR/env.sh
echo "PATH=\$( realpath \$(dirname "\${BASH_SOURCE[0]:-\${\(%\):-%x}}") )/software/firemarshal:\$PATH" >> $RDIR/env.sh echo "# line auto-generated by init-submodules-no-riscv-tools.sh" >> env.sh
echo '__DIR="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")"' >> env.sh
echo "PATH=\$__DIR/bin:\$PATH" >> env.sh
echo "PATH=\$__DIR/software/firemarshal:\$PATH" >> env.sh

76
scripts/numa_prefix Executable file
View File

@@ -0,0 +1,76 @@
#!/usr/bin/env python
#============================================================================
# - really simple script, which just prints out the numactl cmd to
# prefix before your actual command. it determines this based on free
# memory size attached to every node.
# - when you run this on a machine without `numactl`, the output is empty,
# so `$(numa_prefix) <cmd> <args>` turns in to `<cmd> <args>`.
# - when the machine has `numactl` installed, regardless of the socket-count
# on the machine, the resulting command is:
# `numactl -m <socket> -C <core-id list> -- <cmd> <args>`
# - example output from `numactl -H` on a 2 socket machine:
# available: 2 nodes (0-1)
# node 0 cpus: 0 2 4 6 8 10 12 14 16 18 20 22
# node 0 size: 131026 MB
# node 0 free: 7934 MB
# node 1 cpus: 1 3 5 7 9 11 13 15 17 19 21 23
# node 1 size: 65536 MB
# node 1 free: 429 MB
# node distances:
# node 0 1
# 0: 10 20
# 1: 20 10
#============================================================================
import subprocess
import re
import sys
which_proc = subprocess.Popen(["which", "numactl"], stdout=subprocess.PIPE)
out, err = which_proc.communicate()
if out != "":
numactl_proc = subprocess.Popen(["numactl", "-H"], stdout=subprocess.PIPE)
out, err = numactl_proc.communicate()
lines = out.split("\n")
line_idx = 0
head_line = lines[line_idx]
line_idx += 1
node_match = re.match(r"^ *available: +(\d+) nodes", head_line)
if node_match:
avail_nodes = node_match.group(1)
best_node_id = ""
best_cpus = ""
best_free_size = 0
# loop through available nodes, selecting the node with the most free mem
for i in avail_nodes:
cpu_line = lines[line_idx]
# mem. size unused. skip and use mem. free
mem_free_line = lines[line_idx + 2]
line_idx += 3
cpu_match = re.match(r"^ *node (\d+) cpus: (\d.*\d)$", cpu_line)
if cpu_match:
node_id = cpu_match.group(1)
cpus = cpu_match.group(2).replace(" ", ",")
mem_free_match = re.match(r"^ *node " + node_id + " free: (\d+) \S+$", mem_free_line)
if mem_free_match:
free_size = mem_free_match.group(1)
if int(free_size) > int(best_free_size):
best_node_id = node_id
best_cpus = cpus
best_free_size = free_size
else:
sys.exit("[ERROR] Malformed mem free line: " + mem_free_line)
else:
sys.exit("[ERROR] Malformed cpus line: " + cpu_line)
sys.stdout.write("numactl -m " + best_node_id + " -C " + best_cpus + " --")
else:
sys.exit("[ERROR] Malformed head line: " + head_line)

View File

@@ -24,4 +24,4 @@ sudo apt-get install -y device-tree-compiler
git clone http://git.veripool.org/git/verilator git clone http://git.veripool.org/git/verilator
cd verilator cd verilator
git checkout v4.034 git checkout v4.034
autoconf && ./configure && make -j16 && sudo make install autoconf && ./configure && make -j$(nproc) && sudo make install

23
sims/common-sim-flags.mk Normal file
View File

@@ -0,0 +1,23 @@
#----------------------------------------------------------------------------------------
# common gcc configuration/optimization
#----------------------------------------------------------------------------------------
SIM_OPT_CXXFLAGS := -O3
SIM_CXXFLAGS = \
$(CXXFLAGS) \
$(SIM_OPT_CXXFLAGS) \
-std=c++11 \
-I$(RISCV)/include \
-I$(dramsim_dir) \
-I$(build_dir) \
$(EXTRA_SIM_CXXFLAGS)
SIM_LDFLAGS = \
$(LDFLAGS) \
-L$(RISCV)/lib \
-Wl,-rpath,$(RISCV)/lib \
-L$(sim_dir) \
-L$(dramsim_dir) \
-lfesvr \
-ldramsim \
$(EXTRA_SIM_LDFLAGS)

View File

@@ -41,16 +41,24 @@ include $(base_dir)/common.mk
######################################################################################### #########################################################################################
VCS = vcs -full64 VCS = vcs -full64
VCS_OPTS = -notice -line $(VCS_CC_OPTS) $(VCS_NONCC_OPTS) $(VCS_DEFINE_OPTS) $(EXTRA_SIM_SOURCES) VCS_OPTS = $(VCS_CC_OPTS) $(VCS_NONCC_OPTS) $(PREPROC_DEFINES)
#########################################################################################
# vcs build paths
#########################################################################################
model_dir = $(build_dir)/$(long_name)
model_dir_debug = $(build_dir)/$(long_name).debug
######################################################################################### #########################################################################################
# vcs simulator rules # vcs simulator rules
######################################################################################### #########################################################################################
$(sim): $(sim_vsrcs) $(sim_common_files) $(dramsim_lib) $(EXTRA_SIM_REQS) $(sim): $(sim_vsrcs) $(sim_common_files) $(dramsim_lib) $(EXTRA_SIM_REQS)
rm -rf csrc && $(VCS) $(VCS_OPTS) -o $@ rm -rf $(model_dir)
$(VCS) $(VCS_OPTS) $(EXTRA_SIM_SOURCES) -o $@ -Mdir=$(model_dir)
$(sim_debug): $(sim_vsrcs) $(sim_common_files) $(dramsim_lib) $(EXTRA_SIM_REQS) $(sim_debug): $(sim_vsrcs) $(sim_common_files) $(dramsim_lib) $(EXTRA_SIM_REQS)
rm -rf csrc && $(VCS) $(VCS_OPTS) -o $@ \ rm -rf $(model_dir_debug)
$(VCS) $(VCS_OPTS) $(EXTRA_SIM_SOURCES) -o $@ -Mdir=$(model_dir_debug) \
+define+DEBUG +define+DEBUG
######################################################################################### #########################################################################################
@@ -61,8 +69,14 @@ $(output_dir)/%.vpd: $(output_dir)/% $(sim_debug)
(set -o pipefail && $(sim_debug) $(PERMISSIVE_ON) $(SIM_FLAGS) $(EXTRA_SIM_FLAGS) $(VERBOSE_FLAGS) +vcdplusfile=$@ $(PERMISSIVE_OFF) $< </dev/null 2> >(spike-dasm > $<.out) | tee $<.log) (set -o pipefail && $(sim_debug) $(PERMISSIVE_ON) $(SIM_FLAGS) $(EXTRA_SIM_FLAGS) $(VERBOSE_FLAGS) +vcdplusfile=$@ $(PERMISSIVE_OFF) $< </dev/null 2> >(spike-dasm > $<.out) | tee $<.log)
######################################################################################### #########################################################################################
# general cleanup rule # general cleanup rules
######################################################################################### #########################################################################################
.PHONY: clean .PHONY: clean clean-sim clean-sim-debug
clean: clean:
rm -rf $(gen_dir) csrc $(sim_prefix)-* ucli.key vc_hdrs.h rm -rf $(gen_dir) $(sim_prefix)-* ucli.key
clean-sim:
rm -rf $(model_dir) $(build_dir)/vc_hdrs.h $(sim) $(sim).daidir ucli.key
clean-sim-debug:
rm -rf $(model_dir_debug) $(build_dir)/vc_hdrs.h $(sim_debug) $(sim_debug).daidir ucli.key

View File

@@ -22,7 +22,7 @@ include $(base_dir)/variables.mk
sim_name = verilator sim_name = verilator
######################################################################################### #########################################################################################
# vcs simulator types and rules # verilator simulator types and rules
######################################################################################### #########################################################################################
sim_prefix = simulator sim_prefix = simulator
sim = $(sim_dir)/$(sim_prefix)-$(MODEL_PACKAGE)-$(CONFIG) sim = $(sim_dir)/$(sim_prefix)-$(MODEL_PACKAGE)-$(CONFIG)
@@ -47,35 +47,53 @@ debug: $(sim_debug)
include $(base_dir)/common.mk include $(base_dir)/common.mk
######################################################################################### #########################################################################################
# verilator binary and flags # verilator-specific user-interface variables and commands
#########################################################################################
HELP_COMPILATION_VARIABLES += \
" VERILATOR_PROFILE = 'none' if no verilator profiling (default)" \
" 'all' if full verilator runtime profiling" \
" 'threads' if runtime thread profiling only" \
" VERILATOR_THREADS = how many threads the simulator will use (default 1)" \
" VERILATOR_FST_MODE = enable FST waveform instead of VCD. use with debug build"
#########################################################################################
# verilator/cxx binary and flags
######################################################################################### #########################################################################################
VERILATOR := verilator --cc --exe VERILATOR := verilator --cc --exe
CXXFLAGS := \ #----------------------------------------------------------------------------------------
$(CXXFLAGS) -O1 -std=c++11 \ # user configs
-I$(RISCV)/include \ #----------------------------------------------------------------------------------------
-I$(dramsim_dir) \ VERILATOR_PROFILE ?= none
-D__STDC_FORMAT_MACROS \ RUNTIME_PROFILING_CFLAGS := $(if $(filter $(VERILATOR_PROFILE),all),-g -pg,)
$(EXTRA_SIM_CC_FLAGS) RUNTIME_PROFILING_VFLAGS := $(if $(filter $(VERILATOR_PROFILE),all),\
--prof-threads --prof-cfuncs,\
$(if $(filter $(VERILATOR_PROFILE),threads),\
--prof-threads,))
LDFLAGS := \ VERILATOR_THREADS ?= 1
$(LDFLAGS) \ RUNTIME_THREADS := --threads $(VERILATOR_THREADS) --threads-dpi all
-L$(sim_dir) \
-lpthread
VERILATOR_CC_OPTS = \ VERILATOR_FST_MODE ?= 0
TRACING_OPTS := $(if $(filter $(VERILATOR_FST_MODE),0),\
--trace,--trace-fst --trace-threads 1)
TRACING_CFLAGS := $(if $(filter $(VERILATOR_FST_MODE),0),,-DCY_FST_TRACE)
#----------------------------------------------------------------------------------------
# verilation configuration/optimization
#----------------------------------------------------------------------------------------
# we initially had --noassert for performance, but several modules use
# assertions, including dramsim, so we enable --assert by default
VERILATOR_OPT_FLAGS := \
-O3 \ -O3 \
-CFLAGS "$(CXXFLAGS) -DTEST_HARNESS=V$(VLOG_MODEL) -DVERILATOR" \ --x-assign fast \
-CFLAGS "-I$(build_dir) -include $(build_dir)/$(long_name).plusArgs -include $(build_dir)/verilator.h" \ --x-initial fast \
-LDFLAGS "$(LDFLAGS)" \ --output-split 10000 \
$(RISCV)/lib/libfesvr.a \ --output-split-cfuncs 100
$(dramsim_lib)
# default flags added for ariane # default flags added for external IP (ariane/NVDLA)
ARIANE_VERILATOR_FLAGS = \ VERILOG_IP_VERILATOR_FLAGS := \
--unroll-count 256 \ --unroll-count 256 \
-Werror-PINMISSING \
-Werror-IMPLICIT \
-Wno-PINCONNECTEMPTY \ -Wno-PINCONNECTEMPTY \
-Wno-ASSIGNDLY \ -Wno-ASSIGNDLY \
-Wno-DECLFILENAME \ -Wno-DECLFILENAME \
@@ -85,29 +103,66 @@ ARIANE_VERILATOR_FLAGS = \
-Wno-style \ -Wno-style \
-Wall -Wall
# normal flags used for chipyard builds (that are incompatible with ariane) # normal flags used for chipyard builds (that are incompatible with vlog ip aka ariane/NVDLA)
CHIPYARD_VERILATOR_FLAGS = \ CHIPYARD_VERILATOR_FLAGS := \
--assert --assert
# options dependent on whether external IP (ariane/NVDLA) or just chipyard is used
# NOTE: defer the evaluation of this until it is used!
PLATFORM_OPTS = $(shell \
if grep -qiP "module\s+(Ariane|NVDLA)" $(build_dir)/*.*v; \
then echo "$(VERILOG_IP_VERILATOR_FLAGS)"; \
else echo "$(CHIPYARD_VERILATOR_FLAGS)"; fi)
# Use --timescale to approximate timescale behavior of pre-4.034 # Use --timescale to approximate timescale behavior of pre-4.034
TIMESCALE_OPTS := $(shell verilator --version | perl -lne 'if (/(\d.\d+)/ && $$1 >= 4.034) { print "--timescale 1ns/1ps"; }') TIMESCALE_OPTS := $(shell verilator --version | perl -lne 'if (/(\d.\d+)/ && $$1 >= 4.034) { print "--timescale 1ns/1ps"; }')
VERILATOR_NONCC_OPTS = \
$(TIMESCALE_OPTS) \
--top-module $(VLOG_MODEL) \
--vpi \
-Wno-fatal \
$(shell if ! grep -iq "module.*ariane" $(build_dir)/*.*v; then echo "$(CHIPYARD_VERILATOR_FLAGS)"; else echo "$(ARIANE_VERILATOR_FLAGS)"; fi) \
--output-split 10000 \
--output-split-cfuncs 100 \
--max-num-width 1048576 \
-f $(sim_common_files) \
$(sim_vsrcs)
VERILATOR_DEFINES = \ # see: https://github.com/ucb-bar/riscv-mini/issues/31
MAX_WIDTH_OPTS = $(shell verilator --version | perl -lne 'if (/(\d.\d+)/ && $$1 > 4.016) { print "--max-num-width 1048576"; }')
PREPROC_DEFINES := \
+define+PRINTF_COND=\$$c\(\"verbose\",\"\&\&\"\,\"done_reset\"\) \ +define+PRINTF_COND=\$$c\(\"verbose\",\"\&\&\"\,\"done_reset\"\) \
+define+STOP_COND=\$$c\(\"done_reset\"\) +define+STOP_COND=\$$c\(\"done_reset\"\)
VERILATOR_OPTS = $(VERILATOR_CC_OPTS) $(VERILATOR_NONCC_OPTS) $(VERILATOR_DEFINES) $(EXTRA_SIM_SOURCES) VERILATOR_NONCC_OPTS = \
$(RUNTIME_PROFILING_VFLAGS) \
$(RUNTIME_THREADS) \
$(VERILATOR_OPT_FLAGS) \
$(PLATFORM_OPTS) \
-Wno-fatal \
$(TIMESCALE_OPTS) \
$(MAX_WIDTH_OPTS) \
$(PREPROC_DEFINES) \
--top-module $(VLOG_MODEL) \
--vpi \
-f $(sim_common_files) \
$(sim_vsrcs)
#----------------------------------------------------------------------------------------
# gcc configuration/optimization
#----------------------------------------------------------------------------------------
include $(base_dir)/sims/common-sim-flags.mk
VERILATOR_CXXFLAGS = \
$(SIM_CXXFLAGS) \
$(RUNTIME_PROFILING_CFLAGS) \
$(TRACING_CFLAGS) \
-D__STDC_FORMAT_MACROS \
-DTEST_HARNESS=V$(VLOG_MODEL) \
-DVERILATOR \
-include $(build_dir)/$(long_name).plusArgs \
-include $(build_dir)/verilator.h
VERILATOR_LDFLAGS = $(SIM_LDFLAGS)
VERILATOR_CC_OPTS = \
-CFLAGS "$(VERILATOR_CXXFLAGS)" \
-LDFLAGS "$(VERILATOR_LDFLAGS)"
#----------------------------------------------------------------------------------------
# full verilator+gcc opts
#----------------------------------------------------------------------------------------
VERILATOR_OPTS = $(VERILATOR_CC_OPTS) $(VERILATOR_NONCC_OPTS)
######################################################################################### #########################################################################################
# verilator build paths and file names # verilator build paths and file names
@@ -127,13 +182,13 @@ model_mk_debug = $(model_dir_debug)/V$(VLOG_MODEL).mk
$(model_mk): $(sim_vsrcs) $(sim_common_files) $(EXTRA_SIM_REQS) $(model_mk): $(sim_vsrcs) $(sim_common_files) $(EXTRA_SIM_REQS)
rm -rf $(model_dir) rm -rf $(model_dir)
mkdir -p $(model_dir) mkdir -p $(model_dir)
$(VERILATOR) $(VERILATOR_OPTS) -o $(sim) -Mdir $(model_dir) -CFLAGS "-include $(model_header)" $(VERILATOR) $(VERILATOR_OPTS) $(EXTRA_SIM_SOURCES) -o $(sim) -Mdir $(model_dir) -CFLAGS "-include $(model_header)"
touch $@ touch $@
$(model_mk_debug): $(sim_vsrcs) $(sim_common_files) $(EXTRA_SIM_REQS) $(model_mk_debug): $(sim_vsrcs) $(sim_common_files) $(EXTRA_SIM_REQS)
rm -rf $(model_dir_debug) rm -rf $(model_dir_debug)
mkdir -p $(model_dir_debug) mkdir -p $(model_dir_debug)
$(VERILATOR) $(VERILATOR_OPTS) -o $(sim_debug) --trace -Mdir $(model_dir_debug) -CFLAGS "-include $(model_header_debug)" $(VERILATOR) $(VERILATOR_OPTS) $(EXTRA_SIM_SOURCES) -o $(sim_debug) $(TRACING_OPTS) -Mdir $(model_dir_debug) -CFLAGS "-include $(model_header_debug)"
touch $@ touch $@
######################################################################################### #########################################################################################
@@ -150,12 +205,19 @@ $(sim_debug): $(model_mk_debug) $(dramsim_lib)
######################################################################################### #########################################################################################
.PRECIOUS: $(output_dir)/%.vpd %.vcd .PRECIOUS: $(output_dir)/%.vpd %.vcd
$(output_dir)/%.vpd: $(output_dir)/% $(sim_debug) $(output_dir)/%.vpd: $(output_dir)/% $(sim_debug)
touch $@.vpd rm -f $@.vcd && mkfifo $@.vcd
(set -o pipefail && $(sim_debug) $(PERMISSIVE_ON) $(SIM_FLAGS) $(EXTRA_SIM_FLAGS) $(SEED_FLAG) $(VERBOSE_FLAGS) -v $@.vcd $(PERMISSIVE_OFF) $< </dev/null 2> >(spike-dasm > $<.out) | tee $<.log) vcd2vpd $@.vcd $@ > /dev/null &
(set -o pipefail && $(NUMA_PREFIX) $(sim_debug) $(PERMISSIVE_ON) $(SIM_FLAGS) $(EXTRA_SIM_FLAGS) $(SEED_FLAG) $(VERBOSE_FLAGS) -v$@.vcd $(PERMISSIVE_OFF) $< </dev/null 2> >(spike-dasm > $<.out) | tee $<.log)
######################################################################################### #########################################################################################
# general cleanup rule # general cleanup rules
######################################################################################### #########################################################################################
.PHONY: clean .PHONY: clean clean-sim clean-sim-debug
clean: clean:
rm -rf $(gen_dir) $(sim_prefix)-* rm -rf $(gen_dir) $(sim_prefix)-*
clean-sim:
rm -rf $(model_dir) $(sim)
clean-sim-debug:
rm -rf $(model_dir_debug) $(sim_debug)

View File

@@ -49,7 +49,7 @@ ifdef ENABLE_DROMAJO
EXTRA_SIM_FLAGS += $(DROMAJO_FLAGS) EXTRA_SIM_FLAGS += $(DROMAJO_FLAGS)
# CC flags needed for all simulations # CC flags needed for all simulations
EXTRA_SIM_CC_FLAGS += -I$(DROMAJO_DIR) EXTRA_SIM_CXXFLAGS += -I$(DROMAJO_DIR)
# sourced needed for simulation # sourced needed for simulation
EXTRA_SIM_SOURCES += $(DROMAJO_LIB) EXTRA_SIM_SOURCES += $(DROMAJO_LIB)

View File

@@ -1,23 +1,51 @@
######################################################################################### #########################################################################################
# makefile variables shared across multiple makefiles # makefile variables shared across multiple makefiles
# - to use the help text, your Makefile should have a 'help' target that just
# prints all the HELP_LINES
######################################################################################### #########################################################################################
HELP_COMPILATION_VARIABLES =
HELP_PROJECT_VARIABLES = \
" SUB_PROJECT = use the specific subproject default variables [$(SUB_PROJECT)]" \
" SBT_PROJECT = the SBT project that you should find the classes/packages in [$(SBT_PROJECT)]" \
" MODEL = the top level module of the project in Chisel (normally the harness) [$(MODEL)]" \
" VLOG_MODEL = the top level module of the project in Firrtl/Verilog (normally the harness) [$(VLOG_MODEL)]" \
" MODEL_PACKAGE = the scala package to find the MODEL in [$(MODEL_PACKAGE)]" \
" CONFIG = the configuration class to give the parameters for the project [$(CONFIG)]" \
" CONFIG_PACKAGE = the scala package to find the CONFIG class [$(CONFIG_PACKAGE)]" \
" GENERATOR_PACKAGE = the scala package to find the Generator class in [$(GENERATOR_PACKAGE)]" \
" TB = testbench wrapper over the TestHarness needed to simulate in a verilog simulator [$(TB)]" \
" TOP = top level module of the project (normally the module instantiated by the harness) [$(TOP)]"
######################################################################################### HELP_SIMULATION_VARIABLES = \
# variables to invoke the generator " BINARY = riscv elf binary that the simulator will run when using the run-binary* targets" \
# descriptions: " VERBOSE_FLAGS = flags used when doing verbose simulation [$(VERBOSE_FLAGS)]"
# SBT_PROJECT = the SBT project that you should find the classes/packages in
# MODEL = the top level module of the project in Chisel (normally the harness) # include default simulation rules
# VLOG_MODEL = the top level module of the project in Firrtl/Verilog (normally the harness) HELP_COMMANDS = \
# MODEL_PACKAGE = the scala package to find the MODEL in " help = display this help" \
# CONFIG = the configuration class to give the parameters for the project " default = compiles non-debug simulator [./$(shell basename $(sim))]" \
# CONFIG_PACKAGE = the scala package to find the CONFIG class " debug = compiles debug simulator [./$(shell basename $(sim_debug))]" \
# GENERATOR_PACKAGE = the scala package to find the Generator class in " clean = remove all debug/non-debug simulators and intermediate files" \
# TB = wrapper over the TestHarness needed to simulate in a verilog simulator " clean-sim = removes non-debug simulator and simulator-generated files" \
# TOP = top level module of the project (normally the module instantiated by the harness) " clean-sim-debug = removes debug simulator and simulator-generated files"
#
# project specific: HELP_LINES = "" \
# SUB_PROJECT = use the specific subproject default variables " design specifier variables:" \
######################################################################################### " ---------------------------" \
$(HELP_PROJECT_VARIABLES) \
"" \
" compilation variables:" \
" ----------------------" \
$(HELP_COMPILATION_VARIABLES) \
"" \
" simulation variables:" \
" ---------------------" \
$(HELP_SIMULATION_VARIABLES) \
"" \
" some useful general commands:" \
" -----------------------------" \
$(HELP_COMMANDS) \
""
######################################################################################### #########################################################################################
# subproject overrides # subproject overrides
@@ -140,7 +168,7 @@ override SCALA_BUILDTOOL_DEPS += $(BLOOP_CONFIG_DIR)/TIMESTAMP
# 1) the sed removes a leading {file:<path>} that sometimes needs to be # 1) the sed removes a leading {file:<path>} that sometimes needs to be
# provided to SBT when a project but not for bloop. # provided to SBT when a project but not for bloop.
# 2) Generally, one could could pass '--' to indicate all remaining arguments are # 2) Generally, one could could pass '--' to indicate all remaining arguments are
# destined for the scala Main, however a bug in Bloop's argument parsing causes the # destined for the scala Main, however a bug in Bloop's argument parsing causes the
# --nailgun-port argument to be lost in this case. Workaround this by prefixing # --nailgun-port argument to be lost in this case. Workaround this by prefixing
# every main-destined argument with "--args" # every main-destined argument with "--args"
define run_scala_main define run_scala_main

26
vcs.mk
View File

@@ -11,15 +11,23 @@ endif
CLOCK_PERIOD ?= 1.0 CLOCK_PERIOD ?= 1.0
RESET_DELAY ?= 777.7 RESET_DELAY ?= 777.7
#----------------------------------------------------------------------------------------
# gcc configuration/optimization
#----------------------------------------------------------------------------------------
include $(base_dir)/sims/common-sim-flags.mk
VCS_CXXFLAGS = $(SIM_CXXFLAGS)
VCS_LDFLAGS = $(SIM_LDFLAGS)
# vcs requires LDFLAGS to not include library names (i.e. -l needs to be separate)
VCS_CC_OPTS = \ VCS_CC_OPTS = \
-CC "-I$(RISCV)/include" \ -CFLAGS "$(VCS_CXXFLAGS)" \
-CC "-I$(dramsim_dir)" \ -LDFLAGS "$(filter-out -l%,$(VCS_LDFLAGS))" \
-CC "-std=c++11" \ $(filter -l%,$(VCS_LDFLAGS))
-CC "$(EXTRA_SIM_CC_FLAGS)"
VCS_NONCC_OPTS = \ VCS_NONCC_OPTS = \
$(dramsim_lib) \ -notice \
$(RISCV)/lib/libfesvr.a \ -line \
+lint=all,noVCDE,noONGS,noUI \ +lint=all,noVCDE,noONGS,noUI \
-error=PCWM-L \ -error=PCWM-L \
-error=noZMMCM \ -error=noZMMCM \
@@ -27,7 +35,6 @@ VCS_NONCC_OPTS = \
-quiet \ -quiet \
-q \ -q \
+rad \ +rad \
+v2k \
+vcs+lic+wait \ +vcs+lic+wait \
+vc+list \ +vc+list \
-f $(sim_common_files) \ -f $(sim_common_files) \
@@ -35,10 +42,9 @@ VCS_NONCC_OPTS = \
+v2k +verilog2001ext+.v95+.vt+.vp +libext+.v \ +v2k +verilog2001ext+.v95+.vt+.vp +libext+.v \
-debug_pp \ -debug_pp \
+incdir+$(build_dir) \ +incdir+$(build_dir) \
$(sim_vsrcs) \ $(sim_vsrcs)
+libext+.v
VCS_DEFINE_OPTS = \ PREPROC_DEFINES = \
+define+VCS \ +define+VCS \
+define+CLOCK_PERIOD=$(CLOCK_PERIOD) \ +define+CLOCK_PERIOD=$(CLOCK_PERIOD) \
+define+RESET_DELAY=$(RESET_DELAY) \ +define+RESET_DELAY=$(RESET_DELAY) \

View File

@@ -34,7 +34,7 @@ INPUT_CONFS ?= $(if $(filter $(tech_name),nangate45),\
example-asap7.yml) example-asap7.yml)
HAMMER_EXEC ?= example-vlsi HAMMER_EXEC ?= example-vlsi
VLSI_TOP ?= $(TOP) VLSI_TOP ?= $(TOP)
VLSI_HARNESS_DUT_NAME ?= dut VLSI_HARNESS_DUT_NAME ?= chiptop
VLSI_OBJ_DIR ?= $(vlsi_dir)/build VLSI_OBJ_DIR ?= $(vlsi_dir)/build
ifneq ($(CUSTOM_VLOG),) ifneq ($(CUSTOM_VLOG),)
OBJ_DIR ?= $(VLSI_OBJ_DIR)/custom-$(VLSI_TOP) OBJ_DIR ?= $(VLSI_OBJ_DIR)/custom-$(VLSI_TOP)
@@ -115,15 +115,20 @@ $(SIM_CONF): $(VLSI_RTL) $(HARNESS_FILE) $(HARNESS_SMEMS_FILE) $(sim_common_file
done done
echo " options_meta: 'append'" >> $@ echo " options_meta: 'append'" >> $@
echo " defines:" >> $@ echo " defines:" >> $@
for x in $(subst +define+,,$(VCS_DEFINE_OPTS)); do \ for x in $(subst +define+,,$(PREPROC_DEFINES)); do \
echo ' - "'$$x'"' >> $@; \ echo ' - "'$$x'"' >> $@; \
done done
echo " defines_meta: 'append'" >> $@ echo " defines_meta: 'append'" >> $@
echo " compiler_opts:" >> $@ echo " compiler_cc_opts:" >> $@
for x in $(filter-out "",$(filter-out -CC,$(VCS_CC_OPTS))); do \ for x in $(filter-out "",$(VCS_CXXFLAGS)); do \
echo ' - "'$$x'"' >> $@; \ echo ' - "'$$x'"' >> $@; \
done done
echo " compiler_opts_meta: 'append'" >> $@ echo " compiler_cc_opts_meta: 'append'" >> $@
echo " compiler_ld_opts:" >> $@
for x in $(filter-out "",$(VCS_LDFLAGS)); do \
echo ' - "'$$x'"' >> $@; \
done
echo " compiler_ld_opts_meta: 'append'" >> $@
echo " execution_flags_prepend: ['$(PERMISSIVE_ON)']" >> $@ echo " execution_flags_prepend: ['$(PERMISSIVE_ON)']" >> $@
echo " execution_flags_append: ['$(PERMISSIVE_OFF)']" >> $@ echo " execution_flags_append: ['$(PERMISSIVE_OFF)']" >> $@
echo " execution_flags:" >> $@ echo " execution_flags:" >> $@