Merge remote-tracking branch 'origin/dev' into boom-ci
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -7,4 +7,6 @@ target
|
|||||||
*.swp
|
*.swp
|
||||||
.idea
|
.idea
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
env.sh
|
||||||
|
riscv-tools-install
|
||||||
tags
|
tags
|
||||||
|
|||||||
17
.gitmodules
vendored
17
.gitmodules
vendored
@@ -21,13 +21,22 @@
|
|||||||
url = https://github.com/ucb-bar/esp-tools.git
|
url = https://github.com/ucb-bar/esp-tools.git
|
||||||
[submodule "tools/torture"]
|
[submodule "tools/torture"]
|
||||||
path = tools/torture
|
path = tools/torture
|
||||||
url = git@github.com:ucb-bar/riscv-torture.git
|
url = https://github.com/ucb-bar/riscv-torture.git
|
||||||
[submodule "generators/boom"]
|
[submodule "generators/boom"]
|
||||||
path = generators/boom
|
path = generators/boom
|
||||||
url = git@github.com:riscv-boom/riscv-boom.git
|
url = https://github.com/riscv-boom/riscv-boom.git
|
||||||
[submodule "generators/sifive-blocks"]
|
[submodule "generators/sifive-blocks"]
|
||||||
path = generators/sifive-blocks
|
path = generators/sifive-blocks
|
||||||
url = git@github.com:sifive/sifive-blocks.git
|
url = https://github.com/sifive/sifive-blocks.git
|
||||||
[submodule "generators/hwacha"]
|
[submodule "generators/hwacha"]
|
||||||
path = generators/hwacha
|
path = generators/hwacha
|
||||||
url = git@github.com:ucb-bar/hwacha.git
|
url = https://github.com/ucb-bar/hwacha.git
|
||||||
|
[submodule "sims/firesim"]
|
||||||
|
path = sims/firesim
|
||||||
|
url = https://github.com/firesim/firesim.git
|
||||||
|
[submodule "generators/icenet"]
|
||||||
|
path = generators/icenet
|
||||||
|
url = https://github.com/firesim/icenet.git
|
||||||
|
[submodule "generators/block-inclusivecache-sifive"]
|
||||||
|
path = generators/sifive-cache
|
||||||
|
url = https://github.com/sifive/block-inclusivecache-sifive.git
|
||||||
|
|||||||
95
build.sbt
95
build.sbt
@@ -1,3 +1,5 @@
|
|||||||
|
import Tests._
|
||||||
|
|
||||||
lazy val commonSettings = Seq(
|
lazy val commonSettings = Seq(
|
||||||
organization := "edu.berkeley.cs",
|
organization := "edu.berkeley.cs",
|
||||||
version := "1.0",
|
version := "1.0",
|
||||||
@@ -9,7 +11,7 @@ lazy val commonSettings = Seq(
|
|||||||
case _ => MergeStrategy.first}},
|
case _ => MergeStrategy.first}},
|
||||||
scalacOptions ++= Seq("-deprecation","-unchecked","-Xsource:2.11"),
|
scalacOptions ++= Seq("-deprecation","-unchecked","-Xsource:2.11"),
|
||||||
libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.5" % "test",
|
libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.5" % "test",
|
||||||
libraryDependencies += "org.json4s" %% "json4s-native" % "3.6.1",
|
libraryDependencies += "org.json4s" %% "json4s-jackson" % "3.6.1",
|
||||||
libraryDependencies += "org.scala-lang" % "scala-reflect" % scalaVersion.value,
|
libraryDependencies += "org.scala-lang" % "scala-reflect" % scalaVersion.value,
|
||||||
libraryDependencies += "edu.berkeley.cs" %% "firrtl-interpreter" % "1.2-SNAPSHOT",
|
libraryDependencies += "edu.berkeley.cs" %% "firrtl-interpreter" % "1.2-SNAPSHOT",
|
||||||
libraryDependencies += "com.github.scopt" %% "scopt" % "3.7.0",
|
libraryDependencies += "com.github.scopt" %% "scopt" % "3.7.0",
|
||||||
@@ -19,18 +21,14 @@ lazy val commonSettings = Seq(
|
|||||||
Resolver.sonatypeRepo("releases"),
|
Resolver.sonatypeRepo("releases"),
|
||||||
Resolver.mavenLocal))
|
Resolver.mavenLocal))
|
||||||
|
|
||||||
lazy val chipyardFirrtl = (project in file("tools/firrtl"))
|
val rocketChipDir = file("generators/rocket-chip")
|
||||||
.settings(commonSettings)
|
|
||||||
|
|
||||||
lazy val rocketchip = RootProject(file("generators/rocket-chip"))
|
lazy val firesimAsLibrary = sys.env.get("FIRESIM_STANDALONE") == None
|
||||||
|
lazy val firesimDir = if (firesimAsLibrary) {
|
||||||
lazy val chipyardrocketchip = project
|
file("sims/firesim/sim/")
|
||||||
.dependsOn(rocketchip)
|
} else {
|
||||||
.settings(commonSettings)
|
file("../../")
|
||||||
|
}
|
||||||
lazy val testchipip = (project in file("generators/testchipip"))
|
|
||||||
.dependsOn(chipyardrocketchip)
|
|
||||||
.settings(commonSettings)
|
|
||||||
|
|
||||||
// Checks for -DROCKET_USE_MAVEN.
|
// Checks for -DROCKET_USE_MAVEN.
|
||||||
// If it's there, use a maven dependency.
|
// If it's there, use a maven dependency.
|
||||||
@@ -45,33 +43,90 @@ def conditionalDependsOn(prj: Project): Project = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fork each scala test for now, to work around persistent mutable state
|
||||||
|
// in Rocket-Chip based generators
|
||||||
|
def isolateAllTests(tests: Seq[TestDefinition]) = tests map { test =>
|
||||||
|
val options = ForkOptions()
|
||||||
|
new Group(test.name, Seq(test), SubProcess(options))
|
||||||
|
} toSeq
|
||||||
|
|
||||||
|
// Subproject definitions begin
|
||||||
|
|
||||||
|
// NB: FIRRTL dependency is unmanaged (and dropped in sim/lib)
|
||||||
|
lazy val chisel = (project in rocketChipDir / "chisel3")
|
||||||
|
|
||||||
|
// Contains annotations & firrtl passes you may wish to use in rocket-chip without
|
||||||
|
// introducing a circular dependency between RC and MIDAS
|
||||||
|
lazy val midasTargetUtils = ProjectRef(firesimDir, "targetutils")
|
||||||
|
|
||||||
|
// Rocket-chip dependencies (subsumes making RC a RootProject)
|
||||||
|
lazy val hardfloat = (project in rocketChipDir / "hardfloat")
|
||||||
|
.settings(commonSettings).dependsOn(midasTargetUtils)
|
||||||
|
|
||||||
|
lazy val rocketMacros = (project in rocketChipDir / "macros")
|
||||||
|
.settings(commonSettings)
|
||||||
|
|
||||||
|
// HACK: I'm strugging to override settings in rocket-chip's build.sbt (i want
|
||||||
|
// the subproject to register a new library dependendency on midas's targetutils library)
|
||||||
|
// So instead, avoid the existing build.sbt altogether and specify the project's root at src/
|
||||||
|
lazy val rocketchip = (project in rocketChipDir / "src")
|
||||||
|
.settings(
|
||||||
|
commonSettings,
|
||||||
|
scalaSource in Compile := baseDirectory.value / "main" / "scala",
|
||||||
|
resourceDirectory in Compile := baseDirectory.value / "main" / "resources")
|
||||||
|
.dependsOn(chisel, hardfloat, rocketMacros)
|
||||||
|
|
||||||
|
lazy val testchipip = (project in file("generators/testchipip"))
|
||||||
|
.dependsOn(rocketchip)
|
||||||
|
.settings(commonSettings)
|
||||||
|
|
||||||
lazy val example = conditionalDependsOn(project in file("generators/example"))
|
lazy val example = conditionalDependsOn(project in file("generators/example"))
|
||||||
.dependsOn(boom, hwacha, sifive_blocks)
|
.dependsOn(boom, hwacha, sifive_blocks, sifive_cache)
|
||||||
.settings(commonSettings)
|
.settings(commonSettings)
|
||||||
|
|
||||||
lazy val utilities = conditionalDependsOn(project in file("generators/utilities"))
|
lazy val utilities = conditionalDependsOn(project in file("generators/utilities"))
|
||||||
.settings(commonSettings)
|
.settings(commonSettings)
|
||||||
|
|
||||||
lazy val hwacha = (project in file ("generators/hwacha"))
|
lazy val icenet = (project in file("generators/icenet"))
|
||||||
.dependsOn(chipyardrocketchip)
|
.dependsOn(rocketchip, testchipip)
|
||||||
|
.settings(commonSettings)
|
||||||
|
|
||||||
|
lazy val hwacha = (project in file("generators/hwacha"))
|
||||||
|
.dependsOn(rocketchip)
|
||||||
.settings(commonSettings)
|
.settings(commonSettings)
|
||||||
|
|
||||||
lazy val boom = (project in file("generators/boom"))
|
lazy val boom = (project in file("generators/boom"))
|
||||||
.dependsOn(chipyardrocketchip)
|
.dependsOn(rocketchip)
|
||||||
.settings(commonSettings)
|
.settings(commonSettings)
|
||||||
|
|
||||||
lazy val tapeout = conditionalDependsOn(project in file("./tools/barstools/tapeout/"))
|
lazy val tapeout = conditionalDependsOn(project in file("./tools/barstools/tapeout/"))
|
||||||
.dependsOn(chipyardFirrtl)
|
|
||||||
.settings(commonSettings)
|
.settings(commonSettings)
|
||||||
|
|
||||||
lazy val mdf = (project in file("./tools/barstools/mdf/scalalib/"))
|
lazy val mdf = (project in file("./tools/barstools/mdf/scalalib/"))
|
||||||
.settings(commonSettings)
|
.settings(commonSettings)
|
||||||
|
|
||||||
lazy val `barstools-macros` = (project in file("./tools/barstools/macros/"))
|
lazy val barstoolsMacros = (project in file("./tools/barstools/macros/"))
|
||||||
.dependsOn(mdf, chipyardrocketchip, chipyardFirrtl)
|
.dependsOn(mdf, rocketchip)
|
||||||
.enablePlugins(sbtassembly.AssemblyPlugin)
|
.enablePlugins(sbtassembly.AssemblyPlugin)
|
||||||
.settings(commonSettings)
|
.settings(commonSettings)
|
||||||
|
|
||||||
lazy val sifive_blocks = (project in file("generators/sifive-blocks"))
|
lazy val sifive_blocks = (project in file("generators/sifive-blocks"))
|
||||||
.dependsOn(chipyardrocketchip)
|
.dependsOn(rocketchip)
|
||||||
.settings(commonSettings)
|
.settings(commonSettings)
|
||||||
|
|
||||||
|
lazy val sifive_cache = (project in file("generators/sifive-cache")).settings(
|
||||||
|
commonSettings,
|
||||||
|
scalaSource in Compile := baseDirectory.value / "craft"
|
||||||
|
).dependsOn(rocketchip)
|
||||||
|
|
||||||
|
// Library components of FireSim
|
||||||
|
lazy val midas = ProjectRef(firesimDir, "midas")
|
||||||
|
lazy val firesimLib = ProjectRef(firesimDir, "firesimLib")
|
||||||
|
|
||||||
|
lazy val firechip = (project in file("generators/firechip"))
|
||||||
|
.dependsOn(boom, icenet, testchipip, sifive_blocks, sifive_cache, midasTargetUtils, midas, firesimLib % "test->test;compile->compile")
|
||||||
|
.settings(
|
||||||
|
commonSettings,
|
||||||
|
testGrouping in Test := isolateAllTests( (definedTests in Test).value )
|
||||||
|
)
|
||||||
|
|
||||||
|
|||||||
16
common.mk
16
common.mk
@@ -8,23 +8,25 @@ SHELL=/bin/bash
|
|||||||
#########################################################################################
|
#########################################################################################
|
||||||
lookup_scala_srcs = $(shell find -L $(1)/ -iname "*.scala" 2> /dev/null)
|
lookup_scala_srcs = $(shell find -L $(1)/ -iname "*.scala" 2> /dev/null)
|
||||||
|
|
||||||
PACKAGES=rocket-chip testchipip boom hwacha sifive-blocks example
|
PACKAGES=$(addprefix generators/, rocket-chip testchipip boom hwacha sifive-blocks sifive-cache example) \
|
||||||
SCALA_SOURCES=$(foreach pkg,$(PACKAGES),$(call lookup_scala_srcs,$(base_dir)/generators/$(pkg)/src/main/scala))
|
$(addprefix sims/firesim/sim/, . firesim-lib midas midas/targetutils)
|
||||||
|
SCALA_SOURCES=$(foreach pkg,$(PACKAGES),$(call lookup_scala_srcs,$(base_dir)/$(pkg)/src/main/scala))
|
||||||
|
|
||||||
#########################################################################################
|
#########################################################################################
|
||||||
# rocket and testchipip classes
|
# rocket and testchipip classes
|
||||||
#########################################################################################
|
#########################################################################################
|
||||||
ROCKET_CLASSES ?= "$(ROCKETCHIP_DIR)/target/scala-$(SCALA_VERSION_MAJOR)/classes:$(ROCKETCHIP_DIR)/chisel3/target/scala-$(SCALA_VERSION_MAJOR)/*"
|
# NB: target/ lives under source ----V , due to how we're handling midas dependency injection
|
||||||
|
ROCKET_CLASSES ?= "$(ROCKETCHIP_DIR)/src/target/scala-$(SCALA_VERSION_MAJOR)/classes:$(ROCKETCHIP_DIR)/chisel3/target/scala-$(SCALA_VERSION_MAJOR)/*"
|
||||||
TESTCHIPIP_CLASSES ?= "$(TESTCHIP_DIR)/target/scala-$(SCALA_VERSION_MAJOR)/classes"
|
TESTCHIPIP_CLASSES ?= "$(TESTCHIP_DIR)/target/scala-$(SCALA_VERSION_MAJOR)/classes"
|
||||||
|
|
||||||
#########################################################################################
|
#########################################################################################
|
||||||
# jar creation variables and rules
|
# jar creation variables and rules
|
||||||
#########################################################################################
|
#########################################################################################
|
||||||
FIRRTL_JAR ?= $(ROCKETCHIP_DIR)/lib/firrtl.jar
|
FIRRTL_JAR := $(base_dir)/lib/firrtl.jar
|
||||||
|
|
||||||
$(FIRRTL_JAR): $(call lookup_scala_srcs, $(CHIPYARD_FIRRTL_DIR)/src/main/scala)
|
$(FIRRTL_JAR): $(call lookup_scala_srcs, $(CHIPYARD_FIRRTL_DIR)/src/main/scala)
|
||||||
$(MAKE) -C $(CHIPYARD_FIRRTL_DIR) SBT="$(SBT)" root_dir=$(CHIPYARD_FIRRTL_DIR) build-scala
|
$(MAKE) -C $(CHIPYARD_FIRRTL_DIR) SBT="$(SBT)" root_dir=$(CHIPYARD_FIRRTL_DIR) build-scala
|
||||||
mkdir -p $(dir $@)
|
mkdir -p $(@D)
|
||||||
cp -p $(CHIPYARD_FIRRTL_DIR)/utils/bin/firrtl.jar $@
|
cp -p $(CHIPYARD_FIRRTL_DIR)/utils/bin/firrtl.jar $@
|
||||||
touch $@
|
touch $@
|
||||||
|
|
||||||
@@ -58,11 +60,11 @@ $(HARNESS_FILE) $(HARNESS_ANNO) $(HARNESS_FIR) $(sim_harness_blackboxes): $(FIRR
|
|||||||
# This file is for simulation only. VLSI flows should replace this file with one containing hard SRAMs
|
# This file is for simulation only. VLSI flows should replace this file with one containing hard SRAMs
|
||||||
MACROCOMPILER_MODE ?= --mode synflops
|
MACROCOMPILER_MODE ?= --mode synflops
|
||||||
$(SMEMS_FILE) $(SMEMS_FIR): $(SMEMS_CONF)
|
$(SMEMS_FILE) $(SMEMS_FIR): $(SMEMS_CONF)
|
||||||
cd $(base_dir) && $(SBT) "project barstools-macros" "runMain barstools.macros.MacroCompiler -n $(SMEMS_CONF) -v $(SMEMS_FILE) -f $(SMEMS_FIR) $(MACROCOMPILER_MODE)"
|
cd $(base_dir) && $(SBT) "project barstoolsMacros" "runMain barstools.macros.MacroCompiler -n $(SMEMS_CONF) -v $(SMEMS_FILE) -f $(SMEMS_FIR) $(MACROCOMPILER_MODE)"
|
||||||
|
|
||||||
HARNESS_MACROCOMPILER_MODE = --mode synflops
|
HARNESS_MACROCOMPILER_MODE = --mode synflops
|
||||||
$(HARNESS_SMEMS_FILE) $(HARNESS_SMEMS_FIR): $(HARNESS_SMEMS_CONF)
|
$(HARNESS_SMEMS_FILE) $(HARNESS_SMEMS_FIR): $(HARNESS_SMEMS_CONF)
|
||||||
cd $(base_dir) && $(SBT) "project barstools-macros" "runMain barstools.macros.MacroCompiler -n $(HARNESS_SMEMS_CONF) -v $(HARNESS_SMEMS_FILE) -f $(HARNESS_SMEMS_FIR) $(HARNESS_MACROCOMPILER_MODE)"
|
cd $(base_dir) && $(SBT) "project barstoolsMacros" "runMain barstools.macros.MacroCompiler -n $(HARNESS_SMEMS_CONF) -v $(HARNESS_SMEMS_FILE) -f $(HARNESS_SMEMS_FIR) $(HARNESS_MACROCOMPILER_MODE)"
|
||||||
|
|
||||||
#########################################################################################
|
#########################################################################################
|
||||||
# helper rule to just make verilog files
|
# helper rule to just make verilog files
|
||||||
|
|||||||
126
docs/Advanced-Usage/Heterogeneous-SoCs.rst
Normal file
126
docs/Advanced-Usage/Heterogeneous-SoCs.rst
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
Heterogeneous SoCs
|
||||||
|
===============================
|
||||||
|
|
||||||
|
The Chipyard framework involves multiple cores and accelerators that can be composed in arbitrary ways.
|
||||||
|
This discussion will focus on how you combine Rocket, BOOM and Hwacha in particular ways to create a unique SoC.
|
||||||
|
|
||||||
|
Creating a Rocket and BOOM System
|
||||||
|
-------------------------------------------
|
||||||
|
|
||||||
|
Instantiating an SoC with Rocket and BOOM cores is all done with the configuration system and two specific mixins.
|
||||||
|
Both BOOM and Rocket have mixins labelled ``WithNBoomCores(X)`` and ``WithNBigCores(X)`` that automatically create ``X`` copies of the core.
|
||||||
|
When used together you can create a heterogeneous system.
|
||||||
|
The following example shows a dual core BOOM with a single core Rocket.
|
||||||
|
|
||||||
|
.. code-block:: scala
|
||||||
|
|
||||||
|
class DualBoomAndOneRocketConfig extends Config(
|
||||||
|
new WithNormalBoomRocketTop ++
|
||||||
|
new WithBootROM ++
|
||||||
|
new boom.system.WithRenumberHarts ++
|
||||||
|
new boom.common.WithRVC ++
|
||||||
|
new boom.common.DefaultBoomConfig ++
|
||||||
|
new boom.system.WithNBoomCores(2) ++
|
||||||
|
new freechips.rocketchip.subsystem.WithoutTLMonitors ++
|
||||||
|
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
|
||||||
|
new freechips.rocketchip.system.BaseConfig)
|
||||||
|
|
||||||
|
In this example, the ``WithNBoomCores`` and ``WithNBigCores`` mixins set up the default parameters for the multiple BOOM and Rocket cores, respectively.
|
||||||
|
However, for BOOM, an extra mixin called ``DefaultBoomConfig`` is added to override the default parameters with a different set of more common default parameters.
|
||||||
|
This mixin applies to all BOOM cores in the system and changes the parameters for each.
|
||||||
|
|
||||||
|
Great! Now you have a heterogeneous setup with BOOMs and Rockets.
|
||||||
|
The final thing you need to make this system work is to renumber the ``hartId``'s of the cores so that each core has a unique ``hartId`` (a ``hartId`` is the hardware thread id of the core).
|
||||||
|
This is done with ``WithRenumberHarts`` (which can label the Rocket cores first or the BOOM cores first).
|
||||||
|
The reason this is needed is because by default the ``WithN...Cores(X)`` mixin assumes that there are only BOOM or only Rocket cores in the system.
|
||||||
|
Thus, without the ``WithRenumberHarts`` mixin, each set of cores is labeled starting from zero causing multiple cores to be assigned the same ``hartId``.
|
||||||
|
|
||||||
|
Another alternative option to create a multi heterogeneous core system is to override the parameters yourself so you can specify the core parameters per core.
|
||||||
|
The mixin to add to your system would look something like the following.
|
||||||
|
|
||||||
|
.. code-block:: scala
|
||||||
|
|
||||||
|
// create 6 cores (4 boom and 2 rocket)
|
||||||
|
class WithHeterCoresSetup extends Config((site, here, up) => {
|
||||||
|
case BoomTilesKey => {
|
||||||
|
val boomTile0 = BoomTileParams(...) // params for boom core 0
|
||||||
|
val boomTile1 = BoomTileParams(...) // params for boom core 1
|
||||||
|
val boomTile2 = BoomTileParams(...) // params for boom core 2
|
||||||
|
val boomTile3 = BoomTileParams(...) // params for boom core 3
|
||||||
|
boomTile0 ++ boomTile1 ++ boomTile2 ++ boomTile3
|
||||||
|
}
|
||||||
|
|
||||||
|
case RocketTilesKey => {
|
||||||
|
val rocketTile0 = RocketTileParams(...) // params for rocket core 0
|
||||||
|
val rocketTile1 = RocketTileParams(...) // params for rocket core 1
|
||||||
|
rocketTile0 ++ rocketTile1
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
Then you could use this new mixin like the following.
|
||||||
|
|
||||||
|
.. code-block:: scala
|
||||||
|
|
||||||
|
class SixCoreConfig extends Config(
|
||||||
|
new WithNormalBoomRocketTop ++
|
||||||
|
new WithBootROM ++
|
||||||
|
new WithHeterCoresSetup ++
|
||||||
|
new freechips.rocketchip.system.BaseConfig)
|
||||||
|
|
||||||
|
Note, in this setup you need to specify the ``hartId`` of each core in the "TileParams", where each ``hartId`` is unique.
|
||||||
|
|
||||||
|
Adding Hwachas
|
||||||
|
-------------------------------------------
|
||||||
|
|
||||||
|
Adding a Hwacha accelerator is as easy as adding the ``DefaultHwachaConfig`` so that it can setup the Hwacha parameters and add itself to the ``BuildRoCC`` parameter.
|
||||||
|
An example of adding a Hwacha to all tiles in the system is below.
|
||||||
|
|
||||||
|
.. code-block:: scala
|
||||||
|
|
||||||
|
class DualBoomAndRocketWithHwachasConfig extends Config(
|
||||||
|
new WithNormalBoomRocketTop ++
|
||||||
|
new WithBootROM ++
|
||||||
|
new hwacha.DefaultHwachaConfig ++
|
||||||
|
new boom.system.WithRenumberHarts ++
|
||||||
|
new boom.common.WithRVC ++
|
||||||
|
new boom.common.DefaultBoomConfig ++
|
||||||
|
new boom.system.WithNBoomCores(2) ++
|
||||||
|
new freechips.rocketchip.subsystem.WithoutTLMonitors ++
|
||||||
|
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
|
||||||
|
new freechips.rocketchip.system.BaseConfig)
|
||||||
|
|
||||||
|
In this example, Hwachas are added to both BOOM tiles and to the Rocket tile.
|
||||||
|
All with the same Hwacha parameters.
|
||||||
|
|
||||||
|
Assigning Accelerators to Specific Tiles with MultiRoCC
|
||||||
|
-------------------------------------------------------
|
||||||
|
|
||||||
|
Located in ``generators/example/src/main/scala/ConfigMixins.scala`` is a mixin that provides support for adding RoCC accelerators to specific tiles in your SoC.
|
||||||
|
Named ``MultiRoCCKey``, this key allows you to attach RoCC accelerators based on the ``hartId`` of the tile.
|
||||||
|
For example, using this allows you to create a 8 tile system with a RoCC accelerator on only a subset of the tiles.
|
||||||
|
An example is shown below with two BOOM cores, and one Rocket tile with a RoCC accelerator (Hwacha) attached.
|
||||||
|
|
||||||
|
.. code-block:: scala
|
||||||
|
|
||||||
|
class DualBoomAndOneHwachaRocketConfig extends Config(
|
||||||
|
new WithNormalBoomRocketTop ++
|
||||||
|
new WithBootROM ++
|
||||||
|
new WithMultiRoCC ++
|
||||||
|
new WithMultiRoCCHwacha(0) ++ // put Hwacha just on hart0 which was renumbered to Rocket
|
||||||
|
new boom.system.WithRenumberHarts(rocketFirst = true) ++
|
||||||
|
new hwacha.DefaultHwachaConfig ++
|
||||||
|
new boom.common.WithRVC ++
|
||||||
|
new boom.common.DefaultBoomConfig ++
|
||||||
|
new boom.system.WithNBoomCores(2) ++
|
||||||
|
new freechips.rocketchip.subsystem.WithoutTLMonitors ++
|
||||||
|
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
|
||||||
|
new freechips.rocketchip.system.BaseConfig)
|
||||||
|
|
||||||
|
In this example, the ``WithRenumberHarts`` relabels the ``hartId``'s of all the BOOM/Rocket cores.
|
||||||
|
Then after that is applied to the parameters, the ``WithMultiRoCCHwacha(0)`` is used to assign to ``hartId`` zero a Hwacha (in this case ``hartId`` zero is Rocket).
|
||||||
|
Finally, the ``WithMultiRoCC`` mixin is called.
|
||||||
|
This mixin sets the ``BuildRoCC`` key to use the ``MultiRoCCKey`` instead of the default.
|
||||||
|
This must be used after all the RoCC parameters are set because it needs to override the ``BuildRoCC`` parameter.
|
||||||
|
If this is used earlier in the configuration sequence, then MultiRoCC does not work.
|
||||||
|
|
||||||
|
This mixin can be changed to put more accelerators on more cores by changing the arguments to cover more ``hartId``'s (i.e. ``WithMultiRoCCHwacha(0,1,3,6,...)``).
|
||||||
11
docs/Advanced-Usage/index.rst
Normal file
11
docs/Advanced-Usage/index.rst
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
Advanced Usage
|
||||||
|
================================
|
||||||
|
|
||||||
|
The following sections are advanced topics about how to use Chipyard and special features of the framework.
|
||||||
|
They expect you to know about Chisel, Parameters, Configs, etc.
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
:caption: Getting Started:
|
||||||
|
|
||||||
|
Heterogeneous-SoCs
|
||||||
@@ -37,6 +37,10 @@ New to Chipyard? Jump to the :ref:`Getting Started` page for more info.
|
|||||||
:numbered:
|
:numbered:
|
||||||
VLSI/index
|
VLSI/index
|
||||||
|
|
||||||
|
:maxdepth: 3
|
||||||
|
:caption: Advanced Usage:
|
||||||
|
:numbered:
|
||||||
|
Advanced-Usage/index
|
||||||
|
|
||||||
Indices and tables
|
Indices and tables
|
||||||
==================
|
==================
|
||||||
|
|||||||
Submodule generators/boom updated: 22c5f9ec3f...80a680745c
@@ -3,7 +3,7 @@ package example
|
|||||||
import chisel3._
|
import chisel3._
|
||||||
|
|
||||||
import freechips.rocketchip.config.{Config}
|
import freechips.rocketchip.config.{Config}
|
||||||
import freechips.rocketchip.subsystem.{WithRoccExample, WithNMemoryChannels, WithNBigCores, WithRV32, WithExtMemSize, WithNBanks}
|
import freechips.rocketchip.subsystem.{WithRoccExample, WithNMemoryChannels, WithNBigCores, WithRV32, WithExtMemSize, WithNBanks, WithInclusiveCache}
|
||||||
|
|
||||||
import testchipip._
|
import testchipip._
|
||||||
|
|
||||||
@@ -62,13 +62,16 @@ class GB1MemoryConfig extends Config(
|
|||||||
new WithExtMemSize((1<<30) * 1L) ++
|
new WithExtMemSize((1<<30) * 1L) ++
|
||||||
new DefaultRocketConfig)
|
new DefaultRocketConfig)
|
||||||
|
|
||||||
|
class RocketL2Config extends Config(
|
||||||
|
new WithInclusiveCache ++ new DefaultRocketConfig)
|
||||||
|
|
||||||
// ------------
|
// ------------
|
||||||
// BOOM Configs
|
// BOOM Configs
|
||||||
// ------------
|
// ------------
|
||||||
|
|
||||||
class BaseBoomConfig extends Config(
|
class BaseBoomConfig extends Config(
|
||||||
new WithBootROM ++
|
new WithBootROM ++
|
||||||
new boom.system.BoomConfig)
|
new boom.system.LargeBoomConfig)
|
||||||
|
|
||||||
class SmallBaseBoomConfig extends Config(
|
class SmallBaseBoomConfig extends Config(
|
||||||
new WithBootROM ++
|
new WithBootROM ++
|
||||||
@@ -121,7 +124,8 @@ class DualCoreBoomConfig extends Config(
|
|||||||
new WithNormalBoomRocketTop ++
|
new WithNormalBoomRocketTop ++
|
||||||
new WithBootROM ++
|
new WithBootROM ++
|
||||||
new boom.common.WithRVC ++
|
new boom.common.WithRVC ++
|
||||||
new boom.common.DefaultBoomConfig ++
|
new boom.common.WithLargeBooms ++
|
||||||
|
new boom.common.BaseBoomConfig ++
|
||||||
new boom.system.WithNBoomCores(2) ++
|
new boom.system.WithNBoomCores(2) ++
|
||||||
new freechips.rocketchip.subsystem.WithoutTLMonitors ++
|
new freechips.rocketchip.subsystem.WithoutTLMonitors ++
|
||||||
new freechips.rocketchip.system.BaseConfig)
|
new freechips.rocketchip.system.BaseConfig)
|
||||||
@@ -131,7 +135,7 @@ class DualCoreSmallBoomConfig extends Config(
|
|||||||
new WithBootROM ++
|
new WithBootROM ++
|
||||||
new boom.common.WithRVC ++
|
new boom.common.WithRVC ++
|
||||||
new boom.common.WithSmallBooms ++
|
new boom.common.WithSmallBooms ++
|
||||||
new boom.common.DefaultBoomConfig ++
|
new boom.common.BaseBoomConfig ++
|
||||||
new boom.system.WithNBoomCores(2) ++
|
new boom.system.WithNBoomCores(2) ++
|
||||||
new freechips.rocketchip.subsystem.WithoutTLMonitors ++
|
new freechips.rocketchip.subsystem.WithoutTLMonitors ++
|
||||||
new freechips.rocketchip.system.BaseConfig)
|
new freechips.rocketchip.system.BaseConfig)
|
||||||
@@ -141,6 +145,9 @@ class RV32UnifiedBoomConfig extends Config(
|
|||||||
new WithBootROM ++
|
new WithBootROM ++
|
||||||
new boom.system.SmallRV32UnifiedBoomConfig)
|
new boom.system.SmallRV32UnifiedBoomConfig)
|
||||||
|
|
||||||
|
class BoomL2Config extends Config(
|
||||||
|
new WithInclusiveCache ++ new SmallDefaultBoomConfig)
|
||||||
|
|
||||||
// ---------------------
|
// ---------------------
|
||||||
// BOOM and Rocket Configs
|
// BOOM and Rocket Configs
|
||||||
// ---------------------
|
// ---------------------
|
||||||
@@ -149,7 +156,8 @@ class BaseBoomAndRocketConfig extends Config(
|
|||||||
new WithBootROM ++
|
new WithBootROM ++
|
||||||
new boom.system.WithRenumberHarts ++
|
new boom.system.WithRenumberHarts ++
|
||||||
new boom.common.WithRVC ++
|
new boom.common.WithRVC ++
|
||||||
new boom.common.DefaultBoomConfig ++
|
new boom.common.WithLargeBooms ++
|
||||||
|
new boom.common.BaseBoomConfig ++
|
||||||
new boom.system.WithNBoomCores(1) ++
|
new boom.system.WithNBoomCores(1) ++
|
||||||
new freechips.rocketchip.subsystem.WithoutTLMonitors ++
|
new freechips.rocketchip.subsystem.WithoutTLMonitors ++
|
||||||
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
|
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
|
||||||
@@ -160,7 +168,7 @@ class SmallBaseBoomAndRocketConfig extends Config(
|
|||||||
new boom.system.WithRenumberHarts ++
|
new boom.system.WithRenumberHarts ++
|
||||||
new boom.common.WithRVC ++
|
new boom.common.WithRVC ++
|
||||||
new boom.common.WithSmallBooms ++
|
new boom.common.WithSmallBooms ++
|
||||||
new boom.common.DefaultBoomConfig ++
|
new boom.common.BaseBoomConfig ++
|
||||||
new boom.system.WithNBoomCores(1) ++
|
new boom.system.WithNBoomCores(1) ++
|
||||||
new freechips.rocketchip.subsystem.WithoutTLMonitors ++
|
new freechips.rocketchip.subsystem.WithoutTLMonitors ++
|
||||||
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
|
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
|
||||||
@@ -210,21 +218,23 @@ class DualCoreBoomAndOneRocketConfig extends Config(
|
|||||||
new WithBootROM ++
|
new WithBootROM ++
|
||||||
new boom.system.WithRenumberHarts ++
|
new boom.system.WithRenumberHarts ++
|
||||||
new boom.common.WithRVC ++
|
new boom.common.WithRVC ++
|
||||||
new boom.common.DefaultBoomConfig ++
|
new boom.common.WithLargeBooms ++
|
||||||
|
new boom.common.BaseBoomConfig ++
|
||||||
new boom.system.WithNBoomCores(2) ++
|
new boom.system.WithNBoomCores(2) ++
|
||||||
new freechips.rocketchip.subsystem.WithoutTLMonitors ++
|
new freechips.rocketchip.subsystem.WithoutTLMonitors ++
|
||||||
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
|
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
|
||||||
new freechips.rocketchip.system.BaseConfig)
|
new freechips.rocketchip.system.BaseConfig)
|
||||||
|
|
||||||
class DualCoreBoomAndOneHwachaRocketConfig extends Config(
|
class DualBoomAndOneHwachaRocketConfig extends Config(
|
||||||
new WithNormalBoomRocketTop ++
|
new WithNormalBoomRocketTop ++
|
||||||
new WithBootROM ++
|
new WithBootROM ++
|
||||||
new WithMultiRoCC ++
|
new WithMultiRoCC ++
|
||||||
new WithMultiRoCCHwacha(0) ++ // put Hwacha just on hart0 which was renumbered to Rocket
|
new WithMultiRoCCHwacha(0) ++ // put Hwacha just on hart0 which was renumbered to Rocket
|
||||||
new boom.system.WithRenumberHarts ++
|
new boom.system.WithRenumberHarts(rocketFirst = true) ++
|
||||||
new hwacha.DefaultHwachaConfig ++
|
new hwacha.DefaultHwachaConfig ++
|
||||||
new boom.common.WithRVC ++
|
new boom.common.WithRVC ++
|
||||||
new boom.common.DefaultBoomConfig ++
|
new boom.common.WithLargeBooms ++
|
||||||
|
new boom.common.BaseBoomConfig ++
|
||||||
new boom.system.WithNBoomCores(2) ++
|
new boom.system.WithNBoomCores(2) ++
|
||||||
new freechips.rocketchip.subsystem.WithoutTLMonitors ++
|
new freechips.rocketchip.subsystem.WithoutTLMonitors ++
|
||||||
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
|
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
|
||||||
@@ -236,9 +246,13 @@ class RV32BoomAndRocketConfig extends Config(
|
|||||||
new boom.system.WithRenumberHarts ++
|
new boom.system.WithRenumberHarts ++
|
||||||
new boom.common.WithBoomRV32 ++
|
new boom.common.WithBoomRV32 ++
|
||||||
new boom.common.WithRVC ++
|
new boom.common.WithRVC ++
|
||||||
new boom.common.DefaultBoomConfig ++
|
new boom.common.WithLargeBooms ++
|
||||||
|
new boom.common.BaseBoomConfig ++
|
||||||
new boom.system.WithNBoomCores(1) ++
|
new boom.system.WithNBoomCores(1) ++
|
||||||
new freechips.rocketchip.subsystem.WithoutTLMonitors ++
|
new freechips.rocketchip.subsystem.WithoutTLMonitors ++
|
||||||
new WithRV32 ++
|
new freechips.rocketchip.subsystem.WithRV32 ++
|
||||||
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
|
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
|
||||||
new freechips.rocketchip.system.BaseConfig)
|
new freechips.rocketchip.system.BaseConfig)
|
||||||
|
|
||||||
|
class DualCoreRocketL2Config extends Config(
|
||||||
|
new WithInclusiveCache ++ new DualCoreRocketConfig)
|
||||||
|
|||||||
@@ -1,140 +1,24 @@
|
|||||||
package example
|
package example
|
||||||
|
|
||||||
import scala.collection.mutable.LinkedHashSet
|
|
||||||
|
|
||||||
import chisel3._
|
import chisel3._
|
||||||
import chisel3.experimental._
|
|
||||||
|
|
||||||
import firrtl.transforms.{BlackBoxResourceAnno, BlackBoxSourceHelper}
|
import freechips.rocketchip.config.{Parameters}
|
||||||
|
|
||||||
import freechips.rocketchip.subsystem.{RocketTilesKey}
|
|
||||||
import freechips.rocketchip.diplomacy.{LazyModule}
|
|
||||||
import freechips.rocketchip.config.{Field, Parameters}
|
|
||||||
import freechips.rocketchip.util.{GeneratorApp}
|
import freechips.rocketchip.util.{GeneratorApp}
|
||||||
import freechips.rocketchip.tile.{XLen}
|
|
||||||
import freechips.rocketchip.system.{TestGeneration, RegressionTestSuite}
|
|
||||||
|
|
||||||
import boom.system.{BoomTilesKey, BoomTestSuites}
|
import boom.system.{BoomTilesKey, TestSuiteHelper}
|
||||||
|
|
||||||
object Generator extends GeneratorApp {
|
object Generator extends GeneratorApp {
|
||||||
val rv64RegrTestNames = LinkedHashSet(
|
// add unique test suites
|
||||||
"rv64ud-v-fcvt",
|
|
||||||
"rv64ud-p-fdiv",
|
|
||||||
"rv64ud-v-fadd",
|
|
||||||
"rv64uf-v-fadd",
|
|
||||||
"rv64um-v-mul",
|
|
||||||
"rv64mi-p-breakpoint",
|
|
||||||
"rv64uc-v-rvc",
|
|
||||||
"rv64ud-v-structural",
|
|
||||||
"rv64si-p-wfi",
|
|
||||||
"rv64um-v-divw",
|
|
||||||
"rv64ua-v-lrsc",
|
|
||||||
"rv64ui-v-fence_i",
|
|
||||||
"rv64ud-v-fcvt_w",
|
|
||||||
"rv64uf-v-fmin",
|
|
||||||
"rv64ui-v-sb",
|
|
||||||
"rv64ua-v-amomax_d",
|
|
||||||
"rv64ud-v-move",
|
|
||||||
"rv64ud-v-fclass",
|
|
||||||
"rv64ua-v-amoand_d",
|
|
||||||
"rv64ua-v-amoxor_d",
|
|
||||||
"rv64si-p-sbreak",
|
|
||||||
"rv64ud-v-fmadd",
|
|
||||||
"rv64uf-v-ldst",
|
|
||||||
"rv64um-v-mulh",
|
|
||||||
"rv64si-p-dirty")
|
|
||||||
|
|
||||||
val rv32RegrTestNames = LinkedHashSet(
|
|
||||||
"rv32mi-p-ma_addr",
|
|
||||||
"rv32mi-p-csr",
|
|
||||||
"rv32ui-p-sh",
|
|
||||||
"rv32ui-p-lh",
|
|
||||||
"rv32uc-p-rvc",
|
|
||||||
"rv32mi-p-sbreak",
|
|
||||||
"rv32ui-p-sll")
|
|
||||||
|
|
||||||
override def addTestSuites {
|
override def addTestSuites {
|
||||||
import freechips.rocketchip.system.DefaultTestSuites._
|
implicit val p: Parameters = params
|
||||||
val xlen = params(XLen)
|
TestSuiteHelper.addRocketTestSuites
|
||||||
|
TestSuiteHelper.addBoomTestSuites
|
||||||
// TODO: support heterogenous systems?
|
|
||||||
// TODO: generate tests for hart0 of the system since asm tests run on hart0 by default
|
|
||||||
|
|
||||||
// rocket specific tests
|
|
||||||
params(RocketTilesKey).find(_.hartId == 0).map { tileParams =>
|
|
||||||
val coreParams = tileParams.core
|
|
||||||
val vm = coreParams.useVM
|
|
||||||
val env = if (vm) List("p","v") else List("p")
|
|
||||||
coreParams.fpu foreach { case cfg =>
|
|
||||||
if (xlen == 32) {
|
|
||||||
TestGeneration.addSuites(env.map(rv32uf))
|
|
||||||
if (cfg.fLen >= 64)
|
|
||||||
TestGeneration.addSuites(env.map(rv32ud))
|
|
||||||
} else {
|
|
||||||
TestGeneration.addSuite(rv32udBenchmarks)
|
|
||||||
TestGeneration.addSuites(env.map(rv64uf))
|
|
||||||
if (cfg.fLen >= 64)
|
|
||||||
TestGeneration.addSuites(env.map(rv64ud))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (coreParams.useAtomics) {
|
|
||||||
if (tileParams.dcache.flatMap(_.scratch).isEmpty)
|
|
||||||
TestGeneration.addSuites(env.map(if (xlen == 64) rv64ua else rv32ua))
|
|
||||||
else
|
|
||||||
TestGeneration.addSuites(env.map(if (xlen == 64) rv64uaSansLRSC else rv32uaSansLRSC))
|
|
||||||
}
|
|
||||||
if (coreParams.useCompressed) TestGeneration.addSuites(env.map(if (xlen == 64) rv64uc else rv32uc))
|
|
||||||
val (rvi, rvu) =
|
|
||||||
if (xlen == 64) ((if (vm) rv64i else rv64pi), rv64u)
|
|
||||||
else ((if (vm) rv32i else rv32pi), rv32u)
|
|
||||||
|
|
||||||
TestGeneration.addSuites(rvi.map(_("p")))
|
|
||||||
TestGeneration.addSuites((if (vm) List("v") else List()).flatMap(env => rvu.map(_(env))))
|
|
||||||
TestGeneration.addSuite(benchmarks)
|
|
||||||
TestGeneration.addSuite(new RegressionTestSuite(if (xlen == 64) rv64RegrTestNames else rv32RegrTestNames))
|
|
||||||
}
|
|
||||||
|
|
||||||
// boom specific tests
|
|
||||||
params(BoomTilesKey).find(_.hartId == 0).map { tileParams =>
|
|
||||||
val coreParams = tileParams.core
|
|
||||||
val vm = coreParams.useVM
|
|
||||||
val env = if (vm) List("p","v") else List("p")
|
|
||||||
coreParams.fpu foreach { case cfg =>
|
|
||||||
if (xlen == 32) {
|
|
||||||
TestGeneration.addSuites(env.map(rv32uf))
|
|
||||||
if (cfg.fLen >= 64) {
|
|
||||||
TestGeneration.addSuites(env.map(rv32ud))
|
|
||||||
}
|
|
||||||
} else if (cfg.fLen >= 64) {
|
|
||||||
TestGeneration.addSuites(env.map(rv64ud))
|
|
||||||
TestGeneration.addSuites(env.map(rv64uf))
|
|
||||||
TestGeneration.addSuite(rv32udBenchmarks)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (coreParams.useAtomics) {
|
|
||||||
if (tileParams.dcache.flatMap(_.scratch).isEmpty) {
|
|
||||||
TestGeneration.addSuites(env.map(if (xlen == 64) rv64ua else rv32ua))
|
|
||||||
} else {
|
|
||||||
TestGeneration.addSuites(env.map(if (xlen == 64) rv64uaSansLRSC else rv32uaSansLRSC))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (coreParams.useCompressed) TestGeneration.addSuites(env.map(if (xlen == 64) rv64uc else rv32uc))
|
|
||||||
|
|
||||||
// Include our BOOM-specific overrides.
|
|
||||||
val (rvi, rvu) =
|
|
||||||
if (xlen == 64) ((if (vm) BoomTestSuites.rv64i else BoomTestSuites.rv64pi), rv64u)
|
|
||||||
else ((if (vm) rv32i else rv32pi), rv32u)
|
|
||||||
|
|
||||||
TestGeneration.addSuites(rvi.map(_("p")))
|
|
||||||
TestGeneration.addSuites(rvu.map(_("p")))
|
|
||||||
TestGeneration.addSuites((if (vm) List("v") else List()).flatMap(env => rvu.map(_(env))))
|
|
||||||
TestGeneration.addSuite(benchmarks)
|
|
||||||
rv64RegrTestNames -= "rv64mi-p-breakpoint" // TODO: breakpoints not implemented yet
|
|
||||||
TestGeneration.addSuite(new RegressionTestSuite(if (xlen == 64) rv64RegrTestNames else rv32RegrTestNames))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// specify the name that the generator outputs files as
|
||||||
val longName = names.topModuleProject + "." + names.topModuleClass + "." + names.configs
|
val longName = names.topModuleProject + "." + names.topModuleClass + "." + names.configs
|
||||||
|
|
||||||
|
// generate files
|
||||||
generateFirrtl
|
generateFirrtl
|
||||||
generateAnno
|
generateAnno
|
||||||
generateTestSuiteMakefrags
|
generateTestSuiteMakefrags
|
||||||
|
|||||||
133
generators/firechip/src/main/scala/Generator.scala
Normal file
133
generators/firechip/src/main/scala/Generator.scala
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
//See LICENSE for license details.
|
||||||
|
|
||||||
|
package firesim.firesim
|
||||||
|
|
||||||
|
import java.io.{File}
|
||||||
|
|
||||||
|
import chisel3.experimental.RawModule
|
||||||
|
import chisel3.internal.firrtl.{Circuit, Port}
|
||||||
|
|
||||||
|
import freechips.rocketchip.diplomacy.{ValName, AutoBundle}
|
||||||
|
import freechips.rocketchip.devices.debug.DebugIO
|
||||||
|
import freechips.rocketchip.util.{HasGeneratorUtilities, ParsedInputNames, ElaborationArtefacts}
|
||||||
|
import freechips.rocketchip.system.DefaultTestSuites._
|
||||||
|
import freechips.rocketchip.system.{TestGeneration, RegressionTestSuite}
|
||||||
|
import freechips.rocketchip.config.Parameters
|
||||||
|
import freechips.rocketchip.subsystem.RocketTilesKey
|
||||||
|
import freechips.rocketchip.tile.XLen
|
||||||
|
|
||||||
|
import boom.system.{BoomTilesKey, BoomTestSuites}
|
||||||
|
|
||||||
|
import firesim.util.{GeneratorArgs, HasTargetAgnosticUtilites, HasFireSimGeneratorUtilities}
|
||||||
|
|
||||||
|
trait HasTestSuites {
|
||||||
|
val rv64RegrTestNames = collection.mutable.LinkedHashSet(
|
||||||
|
"rv64ud-v-fcvt",
|
||||||
|
"rv64ud-p-fdiv",
|
||||||
|
"rv64ud-v-fadd",
|
||||||
|
"rv64uf-v-fadd",
|
||||||
|
"rv64um-v-mul",
|
||||||
|
// "rv64mi-p-breakpoint", // Not implemented in BOOM
|
||||||
|
// "rv64uc-v-rvc", // Not implemented in BOOM
|
||||||
|
"rv64ud-v-structural",
|
||||||
|
"rv64si-p-wfi",
|
||||||
|
"rv64um-v-divw",
|
||||||
|
"rv64ua-v-lrsc",
|
||||||
|
"rv64ui-v-fence_i",
|
||||||
|
"rv64ud-v-fcvt_w",
|
||||||
|
"rv64uf-v-fmin",
|
||||||
|
"rv64ui-v-sb",
|
||||||
|
"rv64ua-v-amomax_d",
|
||||||
|
"rv64ud-v-move",
|
||||||
|
"rv64ud-v-fclass",
|
||||||
|
"rv64ua-v-amoand_d",
|
||||||
|
"rv64ua-v-amoxor_d",
|
||||||
|
"rv64si-p-sbreak",
|
||||||
|
"rv64ud-v-fmadd",
|
||||||
|
"rv64uf-v-ldst",
|
||||||
|
"rv64um-v-mulh",
|
||||||
|
"rv64si-p-dirty")
|
||||||
|
|
||||||
|
val rv32RegrTestNames = collection.mutable.LinkedHashSet(
|
||||||
|
"rv32mi-p-ma_addr",
|
||||||
|
"rv32mi-p-csr",
|
||||||
|
"rv32ui-p-sh",
|
||||||
|
"rv32ui-p-lh",
|
||||||
|
"rv32uc-p-rvc",
|
||||||
|
"rv32mi-p-sbreak",
|
||||||
|
"rv32ui-p-sll")
|
||||||
|
|
||||||
|
def addTestSuites(targetName: String, params: Parameters) {
|
||||||
|
val coreParams =
|
||||||
|
if (params(RocketTilesKey).nonEmpty) {
|
||||||
|
params(RocketTilesKey).head.core
|
||||||
|
} else {
|
||||||
|
params(BoomTilesKey).head.core
|
||||||
|
}
|
||||||
|
val xlen = params(XLen)
|
||||||
|
val vm = coreParams.useVM
|
||||||
|
val env = if (vm) List("p","v") else List("p")
|
||||||
|
coreParams.fpu foreach { case cfg =>
|
||||||
|
if (xlen == 32) {
|
||||||
|
TestGeneration.addSuites(env.map(rv32uf))
|
||||||
|
if (cfg.fLen >= 64)
|
||||||
|
TestGeneration.addSuites(env.map(rv32ud))
|
||||||
|
} else {
|
||||||
|
TestGeneration.addSuite(rv32udBenchmarks)
|
||||||
|
TestGeneration.addSuites(env.map(rv64uf))
|
||||||
|
if (cfg.fLen >= 64)
|
||||||
|
TestGeneration.addSuites(env.map(rv64ud))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (coreParams.useAtomics) TestGeneration.addSuites(env.map(if (xlen == 64) rv64ua else rv32ua))
|
||||||
|
if (coreParams.useCompressed) TestGeneration.addSuites(env.map(if (xlen == 64) rv64uc else rv32uc))
|
||||||
|
val (rvi, rvu) =
|
||||||
|
if (params(BoomTilesKey).nonEmpty) ((if (vm) BoomTestSuites.rv64i else BoomTestSuites.rv64pi), rv64u)
|
||||||
|
else if (xlen == 64) ((if (vm) rv64i else rv64pi), rv64u)
|
||||||
|
else ((if (vm) rv32i else rv32pi), rv32u)
|
||||||
|
|
||||||
|
TestGeneration.addSuites(rvi.map(_("p")))
|
||||||
|
TestGeneration.addSuites((if (vm) List("v") else List()).flatMap(env => rvu.map(_(env))))
|
||||||
|
TestGeneration.addSuite(benchmarks)
|
||||||
|
TestGeneration.addSuite(new RegressionTestSuite(if (xlen == 64) rv64RegrTestNames else rv32RegrTestNames))
|
||||||
|
TestGeneration.addSuite(FastBlockdevTests)
|
||||||
|
TestGeneration.addSuite(SlowBlockdevTests)
|
||||||
|
if (!targetName.contains("NoNIC"))
|
||||||
|
TestGeneration.addSuite(NICLoopbackTests)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mixed into an App or into a TestSuite
|
||||||
|
trait IsFireSimGeneratorLike extends HasFireSimGeneratorUtilities with HasTestSuites {
|
||||||
|
/** Output software test Makefrags, which provide targets for integration testing. */
|
||||||
|
def generateTestSuiteMakefrags {
|
||||||
|
addTestSuites(names.topModuleClass, targetParams)
|
||||||
|
writeOutputFile(s"$longName.d", TestGeneration.generateMakefrag) // Subsystem-specific test suites
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output miscellaneous files produced as a side-effect of elaboration
|
||||||
|
def generateArtefacts {
|
||||||
|
ElaborationArtefacts.files.foreach { case (extension, contents) =>
|
||||||
|
writeOutputFile(s"${longName}.${extension}", contents ())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object FireSimGenerator extends App with IsFireSimGeneratorLike {
|
||||||
|
lazy val generatorArgs = GeneratorArgs(args)
|
||||||
|
lazy val genDir = new File(names.targetDir)
|
||||||
|
elaborateAndCompileWithMidas
|
||||||
|
generateTestSuiteMakefrags
|
||||||
|
generateHostVerilogHeader
|
||||||
|
generateArtefacts
|
||||||
|
generateTclEnvFile
|
||||||
|
}
|
||||||
|
|
||||||
|
// For now, provide a separate generator app when not specifically building for FireSim
|
||||||
|
object Generator extends freechips.rocketchip.util.GeneratorApp with HasTestSuites {
|
||||||
|
val longName = names.topModuleProject + "." + names.topModuleClass + "." + names.configs
|
||||||
|
generateFirrtl
|
||||||
|
generateAnno
|
||||||
|
generateTestSuiteMakefrags
|
||||||
|
generateArtefacts
|
||||||
|
}
|
||||||
54
generators/firechip/src/main/scala/SimConfigs.scala
Normal file
54
generators/firechip/src/main/scala/SimConfigs.scala
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
//See LICENSE for license details.
|
||||||
|
package firesim.firesim
|
||||||
|
|
||||||
|
import freechips.rocketchip.config.{Parameters, Config, Field}
|
||||||
|
|
||||||
|
import midas.{EndpointKey}
|
||||||
|
import midas.widgets.{EndpointMap}
|
||||||
|
import midas.models._
|
||||||
|
|
||||||
|
import firesim.endpoints._
|
||||||
|
import firesim.configs._
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Full PLATFORM_CONFIG Configurations. These set simulator parameters.
|
||||||
|
*
|
||||||
|
* In general, if you're adding or removing features from any of these, you
|
||||||
|
* should CREATE A NEW ONE, WITH A NEW NAME. This is because the manager
|
||||||
|
* will store this name as part of the tags for the AGFI, so that later you can
|
||||||
|
* reconstruct what is in a particular AGFI. These tags are also used to
|
||||||
|
* determine which driver to build.
|
||||||
|
*******************************************************************************/
|
||||||
|
class FireSimConfig extends Config(
|
||||||
|
new WithSerialWidget ++
|
||||||
|
new WithUARTWidget ++
|
||||||
|
new WithSimpleNICWidget ++
|
||||||
|
new WithBlockDevWidget ++
|
||||||
|
new WithDefaultMemModel ++
|
||||||
|
new WithTracerVWidget ++
|
||||||
|
new BasePlatformConfig)
|
||||||
|
|
||||||
|
class FireSimClockDivConfig extends Config(
|
||||||
|
new WithDefaultMemModel(clockDivision = 2) ++
|
||||||
|
new FireSimConfig)
|
||||||
|
|
||||||
|
class FireSimDDR3Config extends Config(
|
||||||
|
new FCFS16GBQuadRank ++
|
||||||
|
new FireSimConfig)
|
||||||
|
|
||||||
|
class FireSimDDR3LLC4MBConfig extends Config(
|
||||||
|
new FCFS16GBQuadRankLLC4MB ++
|
||||||
|
new FireSimConfig)
|
||||||
|
|
||||||
|
class FireSimDDR3FRFCFSConfig extends Config(
|
||||||
|
new FRFCFS16GBQuadRank ++
|
||||||
|
new FireSimConfig)
|
||||||
|
|
||||||
|
class FireSimDDR3FRFCFSLLC4MBConfig extends Config(
|
||||||
|
new FRFCFS16GBQuadRankLLC4MB ++
|
||||||
|
new FireSimConfig)
|
||||||
|
|
||||||
|
class FireSimDDR3FRFCFSLLC4MB3ClockDivConfig extends Config(
|
||||||
|
new FRFCFS16GBQuadRankLLC4MB3Div ++
|
||||||
|
new FireSimConfig)
|
||||||
|
|
||||||
205
generators/firechip/src/main/scala/TargetConfigs.scala
Normal file
205
generators/firechip/src/main/scala/TargetConfigs.scala
Normal file
@@ -0,0 +1,205 @@
|
|||||||
|
package firesim.firesim
|
||||||
|
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
import chisel3.util.{log2Up}
|
||||||
|
import freechips.rocketchip.config.{Parameters, Config}
|
||||||
|
import freechips.rocketchip.tile._
|
||||||
|
import freechips.rocketchip.tilelink._
|
||||||
|
import freechips.rocketchip.subsystem._
|
||||||
|
import freechips.rocketchip.devices.tilelink.BootROMParams
|
||||||
|
import freechips.rocketchip.devices.debug.DebugModuleParams
|
||||||
|
import boom.system.BoomTilesKey
|
||||||
|
import testchipip.{WithBlockDevice, BlockDeviceKey, BlockDeviceConfig}
|
||||||
|
import sifive.blocks.devices.uart.{PeripheryUARTKey, UARTParams}
|
||||||
|
import icenet._
|
||||||
|
|
||||||
|
class WithBootROM extends Config((site, here, up) => {
|
||||||
|
case BootROMParams => {
|
||||||
|
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 bootROMPath = if (chipyardBootROM.exists()) {
|
||||||
|
chipyardBootROM.getAbsolutePath()
|
||||||
|
} else {
|
||||||
|
firesimBootROM.getAbsolutePath()
|
||||||
|
}
|
||||||
|
BootROMParams(contentFileName = bootROMPath)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
class WithPeripheryBusFrequency(freq: BigInt) extends Config((site, here, up) => {
|
||||||
|
case PeripheryBusKey => up(PeripheryBusKey).copy(frequency=freq)
|
||||||
|
})
|
||||||
|
|
||||||
|
class WithUARTKey extends Config((site, here, up) => {
|
||||||
|
case PeripheryUARTKey => List(UARTParams(
|
||||||
|
address = BigInt(0x54000000L),
|
||||||
|
nTxEntries = 256,
|
||||||
|
nRxEntries = 256))
|
||||||
|
})
|
||||||
|
|
||||||
|
class WithNICKey extends Config((site, here, up) => {
|
||||||
|
case NICKey => NICConfig(
|
||||||
|
inBufFlits = 8192,
|
||||||
|
ctrlQueueDepth = 64)
|
||||||
|
})
|
||||||
|
|
||||||
|
class WithRocketL2TLBs(entries: Int) extends Config((site, here, up) => {
|
||||||
|
case RocketTilesKey => up(RocketTilesKey) map (tile => tile.copy(
|
||||||
|
core = tile.core.copy(
|
||||||
|
nL2TLBEntries = entries
|
||||||
|
)
|
||||||
|
))
|
||||||
|
})
|
||||||
|
|
||||||
|
class WithPerfCounters extends Config((site, here, up) => {
|
||||||
|
case RocketTilesKey => up(RocketTilesKey) map (tile => tile.copy(
|
||||||
|
core = tile.core.copy(nPerfCounters = 29)
|
||||||
|
))
|
||||||
|
})
|
||||||
|
|
||||||
|
class WithBoomL2TLBs(entries: Int) extends Config((site, here, up) => {
|
||||||
|
case BoomTilesKey => up(BoomTilesKey) map (tile => tile.copy(
|
||||||
|
core = tile.core.copy(nL2TLBEntries = entries)
|
||||||
|
))
|
||||||
|
})
|
||||||
|
|
||||||
|
// Disables clock-gating; doesn't play nice with our FAME-1 pass
|
||||||
|
class WithoutClockGating extends Config((site, here, up) => {
|
||||||
|
case DebugModuleParams => up(DebugModuleParams, site).copy(clockGate = false)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Testing configurations
|
||||||
|
// This enables printfs used in testing
|
||||||
|
class WithScalaTestFeatures extends Config((site, here, up) => {
|
||||||
|
case PrintTracePort => true
|
||||||
|
})
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Full TARGET_CONFIG configurations. These set parameters of the target being
|
||||||
|
* simulated.
|
||||||
|
*
|
||||||
|
* In general, if you're adding or removing features from any of these, you
|
||||||
|
* should CREATE A NEW ONE, WITH A NEW NAME. This is because the manager
|
||||||
|
* will store this name as part of the tags for the AGFI, so that later you can
|
||||||
|
* reconstruct what is in a particular AGFI. These tags are also used to
|
||||||
|
* determine which driver to build.
|
||||||
|
*******************************************************************************/
|
||||||
|
class FireSimRocketChipConfig extends Config(
|
||||||
|
new WithBootROM ++
|
||||||
|
new WithPeripheryBusFrequency(BigInt(3200000000L)) ++
|
||||||
|
new WithExtMemSize(0x400000000L) ++ // 16GB
|
||||||
|
new WithoutTLMonitors ++
|
||||||
|
new WithUARTKey ++
|
||||||
|
new WithNICKey ++
|
||||||
|
new WithBlockDevice ++
|
||||||
|
new WithRocketL2TLBs(1024) ++
|
||||||
|
new WithPerfCounters ++
|
||||||
|
new WithoutClockGating ++
|
||||||
|
new freechips.rocketchip.system.DefaultConfig)
|
||||||
|
|
||||||
|
class WithNDuplicatedRocketCores(n: Int) extends Config((site, here, up) => {
|
||||||
|
case RocketTilesKey => List.tabulate(n)(i => up(RocketTilesKey).head.copy(hartId = i))
|
||||||
|
})
|
||||||
|
|
||||||
|
// single core config
|
||||||
|
class FireSimRocketChipSingleCoreConfig extends Config(new FireSimRocketChipConfig)
|
||||||
|
|
||||||
|
// dual core config
|
||||||
|
class FireSimRocketChipDualCoreConfig extends Config(
|
||||||
|
new WithNDuplicatedRocketCores(2) ++
|
||||||
|
new FireSimRocketChipSingleCoreConfig)
|
||||||
|
|
||||||
|
// quad core config
|
||||||
|
class FireSimRocketChipQuadCoreConfig extends Config(
|
||||||
|
new WithNDuplicatedRocketCores(4) ++
|
||||||
|
new FireSimRocketChipSingleCoreConfig)
|
||||||
|
|
||||||
|
// hexa core config
|
||||||
|
class FireSimRocketChipHexaCoreConfig extends Config(
|
||||||
|
new WithNDuplicatedRocketCores(6) ++
|
||||||
|
new FireSimRocketChipSingleCoreConfig)
|
||||||
|
|
||||||
|
// octa core config
|
||||||
|
class FireSimRocketChipOctaCoreConfig extends Config(
|
||||||
|
new WithNDuplicatedRocketCores(8) ++
|
||||||
|
new FireSimRocketChipSingleCoreConfig)
|
||||||
|
|
||||||
|
class FireSimBoomConfig extends Config(
|
||||||
|
new WithBootROM ++
|
||||||
|
new WithPeripheryBusFrequency(BigInt(3200000000L)) ++
|
||||||
|
new WithExtMemSize(0x400000000L) ++ // 16GB
|
||||||
|
new WithoutTLMonitors ++
|
||||||
|
new WithUARTKey ++
|
||||||
|
new WithNICKey ++
|
||||||
|
new WithBlockDevice ++
|
||||||
|
new WithBoomL2TLBs(1024) ++
|
||||||
|
new WithoutClockGating ++
|
||||||
|
// Using a small config because it has 64-bit system bus, and compiles quickly
|
||||||
|
new boom.system.SmallBoomConfig)
|
||||||
|
|
||||||
|
// A safer implementation than the one in BOOM in that it
|
||||||
|
// duplicates whatever BOOMTileKey.head is present N times. This prevents
|
||||||
|
// accidentally (and silently) blowing away configurations that may change the
|
||||||
|
// tile in the "up" view
|
||||||
|
class WithNDuplicatedBoomCores(n: Int) extends Config((site, here, up) => {
|
||||||
|
case BoomTilesKey => List.tabulate(n)(i => up(BoomTilesKey).head.copy(hartId = i))
|
||||||
|
case MaxHartIdBits => log2Up(site(BoomTilesKey).size)
|
||||||
|
})
|
||||||
|
|
||||||
|
class FireSimBoomDualCoreConfig extends Config(
|
||||||
|
new WithNDuplicatedBoomCores(2) ++
|
||||||
|
new FireSimBoomConfig)
|
||||||
|
|
||||||
|
class FireSimBoomQuadCoreConfig extends Config(
|
||||||
|
new WithNDuplicatedBoomCores(4) ++
|
||||||
|
new FireSimBoomConfig)
|
||||||
|
|
||||||
|
//**********************************************************************************
|
||||||
|
//* Supernode Configurations
|
||||||
|
//*********************************************************************************/
|
||||||
|
class WithNumNodes(n: Int) extends Config((pname, site, here) => {
|
||||||
|
case NumNodes => n
|
||||||
|
})
|
||||||
|
|
||||||
|
class SupernodeFireSimRocketChipConfig extends Config(
|
||||||
|
new WithNumNodes(4) ++
|
||||||
|
new WithExtMemSize(0x200000000L) ++ // 8GB
|
||||||
|
new FireSimRocketChipConfig)
|
||||||
|
|
||||||
|
class SupernodeFireSimRocketChipSingleCoreConfig extends Config(
|
||||||
|
new WithNumNodes(4) ++
|
||||||
|
new WithExtMemSize(0x200000000L) ++ // 8GB
|
||||||
|
new FireSimRocketChipSingleCoreConfig)
|
||||||
|
|
||||||
|
class SupernodeSixNodeFireSimRocketChipSingleCoreConfig extends Config(
|
||||||
|
new WithNumNodes(6) ++
|
||||||
|
new WithExtMemSize(0x40000000L) ++ // 1GB
|
||||||
|
new FireSimRocketChipSingleCoreConfig)
|
||||||
|
|
||||||
|
class SupernodeEightNodeFireSimRocketChipSingleCoreConfig extends Config(
|
||||||
|
new WithNumNodes(8) ++
|
||||||
|
new WithExtMemSize(0x40000000L) ++ // 1GB
|
||||||
|
new FireSimRocketChipSingleCoreConfig)
|
||||||
|
|
||||||
|
class SupernodeFireSimRocketChipDualCoreConfig extends Config(
|
||||||
|
new WithNumNodes(4) ++
|
||||||
|
new WithExtMemSize(0x200000000L) ++ // 8GB
|
||||||
|
new FireSimRocketChipDualCoreConfig)
|
||||||
|
|
||||||
|
class SupernodeFireSimRocketChipQuadCoreConfig extends Config(
|
||||||
|
new WithNumNodes(4) ++
|
||||||
|
new WithExtMemSize(0x200000000L) ++ // 8GB
|
||||||
|
new FireSimRocketChipQuadCoreConfig)
|
||||||
|
|
||||||
|
class SupernodeFireSimRocketChipHexaCoreConfig extends Config(
|
||||||
|
new WithNumNodes(4) ++
|
||||||
|
new WithExtMemSize(0x200000000L) ++ // 8GB
|
||||||
|
new FireSimRocketChipHexaCoreConfig)
|
||||||
|
|
||||||
|
class SupernodeFireSimRocketChipOctaCoreConfig extends Config(
|
||||||
|
new WithNumNodes(4) ++
|
||||||
|
new WithExtMemSize(0x200000000L) ++ // 8GB
|
||||||
|
new FireSimRocketChipOctaCoreConfig)
|
||||||
|
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
//See LICENSE for license details.
|
||||||
|
package firesim.firesim
|
||||||
|
|
||||||
|
import scala.collection.mutable.LinkedHashSet
|
||||||
|
|
||||||
|
import freechips.rocketchip.system.{TestGeneration, RocketTestSuite}
|
||||||
|
|
||||||
|
/* This imports tests from FireChip to test devices that aren't natively
|
||||||
|
* tested by the riscv assembly tests.
|
||||||
|
* Firesim's target-specific makefrag gives the recipes for building the
|
||||||
|
* binaries.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class BlockdevTestSuite(prefix: String, val names: LinkedHashSet[String]) extends RocketTestSuite {
|
||||||
|
val envName = ""
|
||||||
|
// fc_test_dir is is defined in firesim's Makefrag
|
||||||
|
val dir = "$(fc_test_dir)"
|
||||||
|
val makeTargetName = prefix + "-blkdev-tests"
|
||||||
|
def kind = "blockdev"
|
||||||
|
// Blockdev tests need an image, which complicates this
|
||||||
|
def additionalArgs = "+blkdev-in-mem0=128 +nic-loopback0"
|
||||||
|
override def toString = s"$makeTargetName = \\\n" +
|
||||||
|
// Make variable with the binaries of the suite
|
||||||
|
names.map(n => s"\t$n.riscv").mkString(" \\\n") + "\n\n" +
|
||||||
|
// Variables with binary specific arguments
|
||||||
|
names.map(n => s"$n.riscv_ARGS=$additionalArgs").mkString(" \n") +
|
||||||
|
postScript
|
||||||
|
}
|
||||||
|
|
||||||
|
object FastBlockdevTests extends BlockdevTestSuite("fast", LinkedHashSet("blkdev"))
|
||||||
|
object SlowBlockdevTests extends BlockdevTestSuite("slow", LinkedHashSet("big-blkdev"))
|
||||||
|
|
||||||
|
class NICTestSuite(prefix: String, val names: LinkedHashSet[String]) extends RocketTestSuite {
|
||||||
|
val envName = ""
|
||||||
|
val dir = "$(fc_test_dir)"
|
||||||
|
val makeTargetName = prefix + "-nic-tests"
|
||||||
|
def kind = "nic"
|
||||||
|
def additionalArgs = "+netbw0=100 +linklatency0=6405 +netburst0=8 +slotid=0 +nic-loopback0"
|
||||||
|
override def toString = s"$makeTargetName = \\\n" +
|
||||||
|
names.map(n => s"\t$n.riscv").mkString(" \\\n") + "\n\n" +
|
||||||
|
names.map(n => s"$n.riscv_ARGS=$additionalArgs").mkString(" \n") +
|
||||||
|
postScript
|
||||||
|
}
|
||||||
|
|
||||||
|
object NICLoopbackTests extends NICTestSuite("loopback", LinkedHashSet("nic-loopback"))
|
||||||
130
generators/firechip/src/main/scala/TargetMixins.scala
Normal file
130
generators/firechip/src/main/scala/TargetMixins.scala
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
package firesim.firesim
|
||||||
|
|
||||||
|
import chisel3._
|
||||||
|
import freechips.rocketchip.config.{Field, Parameters}
|
||||||
|
import freechips.rocketchip.diplomacy._
|
||||||
|
import freechips.rocketchip.tilelink._
|
||||||
|
import freechips.rocketchip.subsystem._
|
||||||
|
import freechips.rocketchip.amba.axi4._
|
||||||
|
import freechips.rocketchip.util._
|
||||||
|
import freechips.rocketchip.subsystem._
|
||||||
|
import freechips.rocketchip.rocket.TracedInstruction
|
||||||
|
import firesim.endpoints.{TraceOutputTop, DeclockedTracedInstruction}
|
||||||
|
|
||||||
|
import midas.models.AXI4BundleWithEdge
|
||||||
|
import midas.targetutils.ExcludeInstanceAsserts
|
||||||
|
|
||||||
|
/** Ties together Subsystem buses in the same fashion done in the example top of Rocket Chip */
|
||||||
|
trait HasDefaultBusConfiguration {
|
||||||
|
this: BaseSubsystem =>
|
||||||
|
// The sbus masters the cbus; here we convert TL-UH -> TL-UL
|
||||||
|
sbus.crossToBus(cbus, NoCrossing)
|
||||||
|
|
||||||
|
// The cbus masters the pbus; which might be clocked slower
|
||||||
|
cbus.crossToBus(pbus, SynchronousCrossing())
|
||||||
|
|
||||||
|
// The fbus masters the sbus; both are TL-UH or TL-C
|
||||||
|
FlipRendering { implicit p =>
|
||||||
|
sbus.crossFromBus(fbus, SynchronousCrossing())
|
||||||
|
}
|
||||||
|
|
||||||
|
// The sbus masters the mbus; here we convert TL-C -> TL-UH
|
||||||
|
private val BankedL2Params(nBanks, coherenceManager) = p(BankedL2Key)
|
||||||
|
private val (in, out, halt) = coherenceManager(this)
|
||||||
|
if (nBanks != 0) {
|
||||||
|
sbus.coupleTo("coherence_manager") { in :*= _ }
|
||||||
|
mbus.coupleFrom("coherence_manager") { _ :=* BankBinder(mbus.blockBytes * (nBanks-1)) :*= out }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Copied from RC and modified to change the IO type of the Imp to include the Diplomatic edges
|
||||||
|
* associated with each port. This drives FASED functional model sizing
|
||||||
|
*/
|
||||||
|
trait CanHaveFASEDOptimizedMasterAXI4MemPort { this: BaseSubsystem =>
|
||||||
|
val module: CanHaveFASEDOptimizedMasterAXI4MemPortModuleImp
|
||||||
|
|
||||||
|
val memAXI4Node = p(ExtMem).map { case MemoryPortParams(memPortParams, nMemoryChannels) =>
|
||||||
|
val portName = "axi4"
|
||||||
|
val device = new MemoryDevice
|
||||||
|
|
||||||
|
val memAXI4Node = AXI4SlaveNode(Seq.tabulate(nMemoryChannels) { channel =>
|
||||||
|
val base = AddressSet.misaligned(memPortParams.base, memPortParams.size)
|
||||||
|
val filter = AddressSet(channel * mbus.blockBytes, ~((nMemoryChannels-1) * mbus.blockBytes))
|
||||||
|
|
||||||
|
AXI4SlavePortParameters(
|
||||||
|
slaves = Seq(AXI4SlaveParameters(
|
||||||
|
address = base.flatMap(_.intersect(filter)),
|
||||||
|
resources = device.reg,
|
||||||
|
regionType = RegionType.UNCACHED, // cacheable
|
||||||
|
executable = true,
|
||||||
|
supportsWrite = TransferSizes(1, mbus.blockBytes),
|
||||||
|
supportsRead = TransferSizes(1, mbus.blockBytes),
|
||||||
|
interleavedId = Some(0))), // slave does not interleave read responses
|
||||||
|
beatBytes = memPortParams.beatBytes)
|
||||||
|
})
|
||||||
|
|
||||||
|
memAXI4Node := mbus.toDRAMController(Some(portName)) {
|
||||||
|
AXI4UserYanker() := AXI4IdIndexer(memPortParams.idBits) := TLToAXI4()
|
||||||
|
}
|
||||||
|
|
||||||
|
memAXI4Node
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Actually generates the corresponding IO in the concrete Module */
|
||||||
|
trait CanHaveFASEDOptimizedMasterAXI4MemPortModuleImp extends LazyModuleImp {
|
||||||
|
val outer: CanHaveFASEDOptimizedMasterAXI4MemPort
|
||||||
|
|
||||||
|
val mem_axi4 = outer.memAXI4Node.map(x => IO(HeterogeneousBag(AXI4BundleWithEdge.fromNode(x.in))))
|
||||||
|
(mem_axi4 zip outer.memAXI4Node) foreach { case (io, node) =>
|
||||||
|
(io zip node.in).foreach { case (io, (bundle, _)) => io <> bundle }
|
||||||
|
}
|
||||||
|
|
||||||
|
def connectSimAXIMem() {
|
||||||
|
(mem_axi4 zip outer.memAXI4Node).foreach { case (io, node) =>
|
||||||
|
(io zip node.in).foreach { case (io, (_, edge)) =>
|
||||||
|
val mem = LazyModule(new SimAXIMem(edge, size = p(ExtMem).get.master.size))
|
||||||
|
Module(mem.module).io.axi4.head <> io
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wires out tile trace ports to the top; and wraps them in a Bundle that the
|
||||||
|
* TracerV endpoint can match on.
|
||||||
|
*/
|
||||||
|
object PrintTracePort extends Field[Boolean](false)
|
||||||
|
|
||||||
|
trait HasTraceIO {
|
||||||
|
this: HasTiles =>
|
||||||
|
val module: HasTraceIOImp
|
||||||
|
|
||||||
|
// Bind all the trace nodes to a BB; we'll use this to generate the IO in the imp
|
||||||
|
val traceNexus = BundleBridgeNexus[Vec[TracedInstruction]]
|
||||||
|
val tileTraceNodes = tiles.map(tile => tile.traceNode)
|
||||||
|
tileTraceNodes foreach { traceNexus := _ }
|
||||||
|
}
|
||||||
|
|
||||||
|
trait HasTraceIOImp extends LazyModuleImp {
|
||||||
|
val outer: HasTraceIO
|
||||||
|
|
||||||
|
val traceIO = IO(Output(new TraceOutputTop(
|
||||||
|
DeclockedTracedInstruction.fromNode(outer.traceNexus.in))))
|
||||||
|
(traceIO.traces zip outer.traceNexus.in).foreach({ case (port, (tileTrace, _)) =>
|
||||||
|
port := DeclockedTracedInstruction.fromVec(tileTrace)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Enabled to test TracerV trace capture
|
||||||
|
if (p(PrintTracePort)) {
|
||||||
|
val traceprint = Wire(UInt(512.W))
|
||||||
|
traceprint := traceIO.asUInt
|
||||||
|
printf("TRACEPORT: %x\n", traceprint)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prevent MIDAS from synthesizing assertions in the dummy TLB included in BOOM
|
||||||
|
trait ExcludeInvalidBoomAssertions extends LazyModuleImp {
|
||||||
|
ExcludeInstanceAsserts(("NonBlockingDCache", "dtlb"))
|
||||||
|
}
|
||||||
|
|
||||||
176
generators/firechip/src/main/scala/Targets.scala
Normal file
176
generators/firechip/src/main/scala/Targets.scala
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
package firesim.firesim
|
||||||
|
|
||||||
|
import chisel3._
|
||||||
|
import freechips.rocketchip._
|
||||||
|
import freechips.rocketchip.subsystem._
|
||||||
|
import freechips.rocketchip.diplomacy._
|
||||||
|
import freechips.rocketchip.tilelink._
|
||||||
|
import freechips.rocketchip.devices.tilelink._
|
||||||
|
import freechips.rocketchip.config.Parameters
|
||||||
|
import freechips.rocketchip.util.{HeterogeneousBag}
|
||||||
|
import freechips.rocketchip.amba.axi4.AXI4Bundle
|
||||||
|
import freechips.rocketchip.config.{Field, Parameters}
|
||||||
|
import freechips.rocketchip.diplomacy.LazyModule
|
||||||
|
import boom.system.{BoomRocketSubsystem, BoomRocketSubsystemModuleImp}
|
||||||
|
import icenet._
|
||||||
|
import testchipip._
|
||||||
|
import testchipip.SerialAdapter.SERIAL_IF_WIDTH
|
||||||
|
import sifive.blocks.devices.uart._
|
||||||
|
import midas.models.AXI4BundleWithEdge
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Top level DESIGN configurations. These describe the basic instantiations of
|
||||||
|
* the designs being simulated.
|
||||||
|
*
|
||||||
|
* In general, if you're adding or removing features from any of these, you
|
||||||
|
* should CREATE A NEW ONE, WITH A NEW NAME. This is because the manager
|
||||||
|
* will store this name as part of the tags for the AGFI, so that later you can
|
||||||
|
* reconstruct what is in a particular AGFI. These tags are also used to
|
||||||
|
* determine which driver to build.
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
class FireSim(implicit p: Parameters) extends RocketSubsystem
|
||||||
|
with HasDefaultBusConfiguration
|
||||||
|
with CanHaveFASEDOptimizedMasterAXI4MemPort
|
||||||
|
with HasPeripheryBootROM
|
||||||
|
with HasNoDebug
|
||||||
|
with HasPeripherySerial
|
||||||
|
with HasPeripheryUART
|
||||||
|
with HasPeripheryIceNIC
|
||||||
|
with HasPeripheryBlockDevice
|
||||||
|
with HasTraceIO
|
||||||
|
{
|
||||||
|
override lazy val module = new FireSimModuleImp(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
class FireSimModuleImp[+L <: FireSim](l: L) extends RocketSubsystemModuleImp(l)
|
||||||
|
with HasRTCModuleImp
|
||||||
|
with CanHaveFASEDOptimizedMasterAXI4MemPortModuleImp
|
||||||
|
with HasPeripheryBootROMModuleImp
|
||||||
|
with HasNoDebugModuleImp
|
||||||
|
with HasPeripherySerialModuleImp
|
||||||
|
with HasPeripheryUARTModuleImp
|
||||||
|
with HasPeripheryIceNICModuleImpValidOnly
|
||||||
|
with HasPeripheryBlockDeviceModuleImp
|
||||||
|
with HasTraceIOImp
|
||||||
|
|
||||||
|
|
||||||
|
class FireSimNoNIC(implicit p: Parameters) extends RocketSubsystem
|
||||||
|
with HasDefaultBusConfiguration
|
||||||
|
with CanHaveFASEDOptimizedMasterAXI4MemPort
|
||||||
|
with HasPeripheryBootROM
|
||||||
|
with HasNoDebug
|
||||||
|
with HasPeripherySerial
|
||||||
|
with HasPeripheryUART
|
||||||
|
with HasPeripheryBlockDevice
|
||||||
|
with HasTraceIO
|
||||||
|
{
|
||||||
|
override lazy val module = new FireSimNoNICModuleImp(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
class FireSimNoNICModuleImp[+L <: FireSimNoNIC](l: L) extends RocketSubsystemModuleImp(l)
|
||||||
|
with HasRTCModuleImp
|
||||||
|
with CanHaveFASEDOptimizedMasterAXI4MemPortModuleImp
|
||||||
|
with HasPeripheryBootROMModuleImp
|
||||||
|
with HasNoDebugModuleImp
|
||||||
|
with HasPeripherySerialModuleImp
|
||||||
|
with HasPeripheryUARTModuleImp
|
||||||
|
with HasPeripheryBlockDeviceModuleImp
|
||||||
|
with HasTraceIOImp
|
||||||
|
|
||||||
|
|
||||||
|
class FireBoom(implicit p: Parameters) extends BoomRocketSubsystem
|
||||||
|
with HasDefaultBusConfiguration
|
||||||
|
with CanHaveFASEDOptimizedMasterAXI4MemPort
|
||||||
|
with HasPeripheryBootROM
|
||||||
|
with HasNoDebug
|
||||||
|
with HasPeripherySerial
|
||||||
|
with HasPeripheryUART
|
||||||
|
with HasPeripheryIceNIC
|
||||||
|
with HasPeripheryBlockDevice
|
||||||
|
with HasTraceIO
|
||||||
|
{
|
||||||
|
override lazy val module = new FireBoomModuleImp(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
class FireBoomModuleImp[+L <: FireBoom](l: L) extends BoomRocketSubsystemModuleImp(l)
|
||||||
|
with HasRTCModuleImp
|
||||||
|
with CanHaveFASEDOptimizedMasterAXI4MemPortModuleImp
|
||||||
|
with HasPeripheryBootROMModuleImp
|
||||||
|
with HasNoDebugModuleImp
|
||||||
|
with HasPeripherySerialModuleImp
|
||||||
|
with HasPeripheryUARTModuleImp
|
||||||
|
with HasPeripheryIceNICModuleImpValidOnly
|
||||||
|
with HasPeripheryBlockDeviceModuleImp
|
||||||
|
with HasTraceIOImp
|
||||||
|
with ExcludeInvalidBoomAssertions
|
||||||
|
|
||||||
|
class FireBoomNoNIC(implicit p: Parameters) extends BoomRocketSubsystem
|
||||||
|
with HasDefaultBusConfiguration
|
||||||
|
with CanHaveFASEDOptimizedMasterAXI4MemPort
|
||||||
|
with HasPeripheryBootROM
|
||||||
|
with HasNoDebug
|
||||||
|
with HasPeripherySerial
|
||||||
|
with HasPeripheryUART
|
||||||
|
with HasPeripheryBlockDevice
|
||||||
|
with HasTraceIO
|
||||||
|
{
|
||||||
|
override lazy val module = new FireBoomNoNICModuleImp(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
class FireBoomNoNICModuleImp[+L <: FireBoomNoNIC](l: L) extends BoomRocketSubsystemModuleImp(l)
|
||||||
|
with HasRTCModuleImp
|
||||||
|
with CanHaveFASEDOptimizedMasterAXI4MemPortModuleImp
|
||||||
|
with HasPeripheryBootROMModuleImp
|
||||||
|
with HasNoDebugModuleImp
|
||||||
|
with HasPeripherySerialModuleImp
|
||||||
|
with HasPeripheryUARTModuleImp
|
||||||
|
with HasPeripheryBlockDeviceModuleImp
|
||||||
|
with HasTraceIOImp
|
||||||
|
with ExcludeInvalidBoomAssertions
|
||||||
|
|
||||||
|
case object NumNodes extends Field[Int]
|
||||||
|
|
||||||
|
class SupernodeIO(
|
||||||
|
nNodes: Int,
|
||||||
|
serialWidth: Int,
|
||||||
|
bagPrototype: HeterogeneousBag[AXI4BundleWithEdge])(implicit p: Parameters)
|
||||||
|
extends Bundle {
|
||||||
|
|
||||||
|
val serial = Vec(nNodes, new SerialIO(serialWidth))
|
||||||
|
val mem_axi = Vec(nNodes, bagPrototype.cloneType)
|
||||||
|
val bdev = Vec(nNodes, new BlockDeviceIO)
|
||||||
|
val net = Vec(nNodes, new NICIOvonly)
|
||||||
|
val uart = Vec(nNodes, new UARTPortIO)
|
||||||
|
|
||||||
|
override def cloneType = new SupernodeIO(nNodes, serialWidth, bagPrototype).asInstanceOf[this.type]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class FireSimSupernode(implicit p: Parameters) extends Module {
|
||||||
|
val nNodes = p(NumNodes)
|
||||||
|
val nodes = Seq.fill(nNodes) {
|
||||||
|
Module(LazyModule(new FireSim).module)
|
||||||
|
}
|
||||||
|
|
||||||
|
val io = IO(new SupernodeIO(nNodes, SERIAL_IF_WIDTH, nodes(0).mem_axi4.get))
|
||||||
|
|
||||||
|
io.mem_axi.zip(nodes.map(_.mem_axi4)).foreach {
|
||||||
|
case (out, mem_axi4) => out <> mem_axi4.get
|
||||||
|
}
|
||||||
|
io.serial <> nodes.map(_.serial)
|
||||||
|
io.bdev <> nodes.map(_.bdev)
|
||||||
|
io.net <> nodes.map(_.net)
|
||||||
|
io.uart <> nodes.map(_.uart(0))
|
||||||
|
nodes.foreach{ case n => {
|
||||||
|
n.debug.clockeddmi.get.dmi.req.valid := false.B
|
||||||
|
n.debug.clockeddmi.get.dmi.resp.ready := false.B
|
||||||
|
n.debug.clockeddmi.get.dmiClock := clock
|
||||||
|
n.debug.clockeddmi.get.dmiReset := reset.toBool
|
||||||
|
n.debug.clockeddmi.get.dmi.req.bits.data := DontCare
|
||||||
|
n.debug.clockeddmi.get.dmi.req.bits.addr := DontCare
|
||||||
|
n.debug.clockeddmi.get.dmi.req.bits.op := DontCare
|
||||||
|
} }
|
||||||
|
}
|
||||||
|
|
||||||
138
generators/firechip/src/test/scala/ScalaTestSuite.scala
Normal file
138
generators/firechip/src/test/scala/ScalaTestSuite.scala
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
//See LICENSE for license details.
|
||||||
|
package firesim.firesim
|
||||||
|
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
import scala.concurrent.{Future, Await, ExecutionContext}
|
||||||
|
import scala.sys.process.{stringSeqToProcess, ProcessLogger}
|
||||||
|
import scala.io.Source
|
||||||
|
|
||||||
|
import freechips.rocketchip.diplomacy._
|
||||||
|
import freechips.rocketchip.system.{RocketTestSuite, BenchmarkTestSuite}
|
||||||
|
import freechips.rocketchip.system.TestGeneration._
|
||||||
|
import freechips.rocketchip.system.DefaultTestSuites._
|
||||||
|
|
||||||
|
import firesim.util.GeneratorArgs
|
||||||
|
|
||||||
|
abstract class FireSimTestSuite(
|
||||||
|
topModuleClass: String,
|
||||||
|
targetConfigs: String,
|
||||||
|
platformConfigs: String,
|
||||||
|
N: Int = 8
|
||||||
|
) extends firesim.TestSuiteCommon with IsFireSimGeneratorLike {
|
||||||
|
import scala.concurrent.duration._
|
||||||
|
import ExecutionContext.Implicits.global
|
||||||
|
|
||||||
|
lazy val generatorArgs = GeneratorArgs(
|
||||||
|
midasFlowKind = "midas",
|
||||||
|
targetDir = "generated-src",
|
||||||
|
topModuleProject = "firesim.firesim",
|
||||||
|
topModuleClass = topModuleClass,
|
||||||
|
targetConfigProject = "firesim.firesim",
|
||||||
|
targetConfigs = targetConfigs ++ "_WithScalaTestFeatures",
|
||||||
|
platformConfigProject = "firesim.firesim",
|
||||||
|
platformConfigs = platformConfigs)
|
||||||
|
|
||||||
|
// From HasFireSimGeneratorUtilities
|
||||||
|
// For the firesim utilities to use the same directory as the test suite
|
||||||
|
override lazy val testDir = genDir
|
||||||
|
|
||||||
|
// From TestSuiteCommon
|
||||||
|
val targetTuple = generatorArgs.tupleName
|
||||||
|
val commonMakeArgs = Seq(s"DESIGN=${generatorArgs.topModuleClass}",
|
||||||
|
s"TARGET_CONFIG=${generatorArgs.targetConfigs}",
|
||||||
|
s"PLATFORM_CONFIG=${generatorArgs.platformConfigs}")
|
||||||
|
override lazy val platform = hostParams(midas.Platform)
|
||||||
|
|
||||||
|
def invokeMlSimulator(backend: String, name: String, debug: Boolean, additionalArgs: Seq[String] = Nil) = {
|
||||||
|
make((Seq(s"${outDir.getAbsolutePath}/${name}.%s".format(if (debug) "vpd" else "out"),
|
||||||
|
s"EMUL=${backend}")
|
||||||
|
++ additionalArgs):_*)
|
||||||
|
}
|
||||||
|
|
||||||
|
def runTest(backend: String, name: String, debug: Boolean, additionalArgs: Seq[String] = Nil) = {
|
||||||
|
behavior of s"${name} running on ${backend} in MIDAS-level simulation"
|
||||||
|
compileMlSimulator(backend, debug)
|
||||||
|
if (isCmdAvailable(backend)) {
|
||||||
|
it should s"pass" in {
|
||||||
|
assert(invokeMlSimulator(backend, name, debug, additionalArgs) == 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//def runReplay(backend: String, replayBackend: String, name: String) = {
|
||||||
|
// val dir = (new File(outDir, backend)).getAbsolutePath
|
||||||
|
// (Seq("make", s"replay-$replayBackend",
|
||||||
|
// s"SAMPLE=${dir}/${name}.sample", s"output_dir=$dir") ++ makeArgs).!
|
||||||
|
//}
|
||||||
|
|
||||||
|
def runSuite(backend: String, debug: Boolean = false)(suite: RocketTestSuite) {
|
||||||
|
// compile emulators
|
||||||
|
behavior of s"${suite.makeTargetName} running on $backend"
|
||||||
|
if (isCmdAvailable(backend)) {
|
||||||
|
val postfix = suite match {
|
||||||
|
case _: BenchmarkTestSuite | _: BlockdevTestSuite | _: NICTestSuite => ".riscv"
|
||||||
|
case _ => ""
|
||||||
|
}
|
||||||
|
val results = suite.names.toSeq sliding (N, N) map { t =>
|
||||||
|
val subresults = t map (name =>
|
||||||
|
Future(name -> invokeMlSimulator(backend, s"$name$postfix", debug)))
|
||||||
|
Await result (Future sequence subresults, Duration.Inf)
|
||||||
|
}
|
||||||
|
results.flatten foreach { case (name, exitcode) =>
|
||||||
|
it should s"pass $name" in { assert(exitcode == 0) }
|
||||||
|
}
|
||||||
|
//replayBackends foreach { replayBackend =>
|
||||||
|
// if (platformParams(midas.EnableSnapshot) && isCmdAvailable("vcs")) {
|
||||||
|
// assert((Seq("make", s"vcs-$replayBackend") ++ makeArgs).! == 0) // compile vcs
|
||||||
|
// suite.names foreach { name =>
|
||||||
|
// it should s"replay $name in $replayBackend" in {
|
||||||
|
// assert(runReplay(backend, replayBackend, s"$name$postfix") == 0)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// suite.names foreach { name =>
|
||||||
|
// ignore should s"replay $name in $backend"
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
} else {
|
||||||
|
ignore should s"pass $backend"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks the collected trace log matches the behavior of a chisel printf
|
||||||
|
def diffTracelog(verilatedLog: String) {
|
||||||
|
behavior of "captured instruction trace"
|
||||||
|
it should s"match the chisel printf in ${verilatedLog}" in {
|
||||||
|
def getLines(file: File, dropLines: Int = 0): Seq[String] = {
|
||||||
|
val lines = Source.fromFile(file).getLines.toList
|
||||||
|
lines.filter(_.startsWith("TRACEPORT")).drop(dropLines)
|
||||||
|
}
|
||||||
|
val resetLength = 50
|
||||||
|
val verilatedOutput = getLines(new File(outDir, s"/${verilatedLog}"))
|
||||||
|
val synthPrintOutput = getLines(new File(genDir, s"/TRACEFILE"), resetLength + 1)
|
||||||
|
assert(verilatedOutput.size == synthPrintOutput.size, "Outputs differ in length")
|
||||||
|
assert(verilatedOutput.nonEmpty)
|
||||||
|
for ( (vPrint, sPrint) <- verilatedOutput.zip(synthPrintOutput) ) {
|
||||||
|
assert(vPrint == sPrint)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
clean
|
||||||
|
mkdirs
|
||||||
|
elaborateAndCompileWithMidas
|
||||||
|
generateTestSuiteMakefrags
|
||||||
|
runTest("verilator", "rv64ui-p-simple", false, Seq(s"""EXTRA_SIM_ARGS=+trace-test-output0"""))
|
||||||
|
diffTracelog("rv64ui-p-simple.out")
|
||||||
|
runSuite("verilator")(benchmarks)
|
||||||
|
runSuite("verilator")(FastBlockdevTests)
|
||||||
|
}
|
||||||
|
|
||||||
|
class RocketF1Tests extends FireSimTestSuite("FireSimNoNIC", "FireSimRocketChipConfig", "FireSimConfig")
|
||||||
|
class RocketF1ClockDivTests extends FireSimTestSuite("FireSimNoNIC", "FireSimRocketChipConfig", "FireSimClockDivConfig")
|
||||||
|
class BoomF1Tests extends FireSimTestSuite("FireBoomNoNIC", "FireSimBoomConfig", "FireSimConfig")
|
||||||
|
class RocketNICF1Tests extends FireSimTestSuite("FireSim", "FireSimRocketChipConfig", "FireSimConfig") {
|
||||||
|
runSuite("verilator")(NICLoopbackTests)
|
||||||
|
}
|
||||||
1
generators/icenet
Submodule
1
generators/icenet
Submodule
Submodule generators/icenet added at bba264d68d
1
generators/sifive-cache
Submodule
1
generators/sifive-cache
Submodule
Submodule generators/sifive-cache added at 13d0c2f178
Submodule generators/testchipip updated: 855a4dd482...532d4a4291
@@ -121,7 +121,6 @@ int main(int argc, char** argv)
|
|||||||
FILE * vcdfile = NULL;
|
FILE * vcdfile = NULL;
|
||||||
uint64_t start = 0;
|
uint64_t start = 0;
|
||||||
#endif
|
#endif
|
||||||
char ** htif_argv = NULL;
|
|
||||||
int verilog_plusargs_legal = 1;
|
int verilog_plusargs_legal = 1;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
@@ -243,10 +242,6 @@ done_processing:
|
|||||||
usage(argv[0]);
|
usage(argv[0]);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
int htif_argc = 1 + argc - optind;
|
|
||||||
htif_argv = (char **) malloc((htif_argc) * sizeof (char *));
|
|
||||||
htif_argv[0] = argv[0];
|
|
||||||
for (int i = 1; optind < argc;) htif_argv[i++] = argv[optind++];
|
|
||||||
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
fprintf(stderr, "using random seed %u\n", random_seed);
|
fprintf(stderr, "using random seed %u\n", random_seed);
|
||||||
@@ -269,8 +264,8 @@ done_processing:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
jtag = new remote_bitbang_t(rbb_port);
|
jtag = new remote_bitbang_t(rbb_port);
|
||||||
dtm = new dtm_t(htif_argc, htif_argv);
|
dtm = new dtm_t(argc, argv);
|
||||||
tsi = new tsi_t(htif_argc, htif_argv);
|
tsi = new tsi_t(argc, argv);
|
||||||
|
|
||||||
signal(SIGTERM, handle_sigterm);
|
signal(SIGTERM, handle_sigterm);
|
||||||
|
|
||||||
@@ -351,6 +346,5 @@ done_processing:
|
|||||||
if (tsi) delete tsi;
|
if (tsi) delete tsi;
|
||||||
if (jtag) delete jtag;
|
if (jtag) delete jtag;
|
||||||
if (tile) delete tile;
|
if (tile) delete tile;
|
||||||
if (htif_argv) free(htif_argv);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
18
scripts/firesim-setup.sh
Executable file
18
scripts/firesim-setup.sh
Executable file
@@ -0,0 +1,18 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Sets up FireSim for use as a library within REBAR
|
||||||
|
|
||||||
|
set -e
|
||||||
|
set -o pipefail
|
||||||
|
|
||||||
|
RDIR=$(pwd)
|
||||||
|
scripts_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||||
|
sims_dir=$scripts_dir/../sims/
|
||||||
|
|
||||||
|
# Reenable the FireSim submodule
|
||||||
|
git config --unset submodule.sims/firesim.update || true
|
||||||
|
cd $sims_dir
|
||||||
|
git submodule update --init firesim
|
||||||
|
cd firesim
|
||||||
|
./build-setup.sh $@ --library
|
||||||
|
cd $RDIR
|
||||||
@@ -6,6 +6,7 @@ set -o pipefail
|
|||||||
|
|
||||||
unamestr=$(uname)
|
unamestr=$(uname)
|
||||||
RDIR=$(pwd)
|
RDIR=$(pwd)
|
||||||
|
scripts_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||||
|
|
||||||
# ignore riscv-tools for submodule init recursive
|
# ignore riscv-tools for submodule init recursive
|
||||||
# you must do this globally (otherwise riscv-tools deep
|
# you must do this globally (otherwise riscv-tools deep
|
||||||
@@ -13,7 +14,19 @@ RDIR=$(pwd)
|
|||||||
git config --global submodule.riscv-tools.update none
|
git config --global submodule.riscv-tools.update none
|
||||||
git config --global submodule.esp-tools.update none
|
git config --global submodule.esp-tools.update none
|
||||||
git config --global submodule.experimental-blocks.update none
|
git config --global submodule.experimental-blocks.update none
|
||||||
|
# Disable updates to the FireSim submodule until explicitly requested
|
||||||
|
git config submodule.sims/firesim.update none
|
||||||
git submodule update --init --recursive #--jobs 8
|
git submodule update --init --recursive #--jobs 8
|
||||||
# unignore riscv-tools,catapult-shell2 globally
|
# unignore riscv-tools,catapult-shell2 globally
|
||||||
git config --global --unset submodule.riscv-tools.update
|
git config --global --unset submodule.riscv-tools.update
|
||||||
git config --global --unset submodule.experimental-blocks.update
|
git config --global --unset submodule.experimental-blocks.update
|
||||||
|
|
||||||
|
# Renable firesim and init only the required submodules to provide
|
||||||
|
# all required scala deps, without doing a full build-setup
|
||||||
|
git config --unset submodule.sims/firesim.update
|
||||||
|
cd $scripts_dir/../sims/
|
||||||
|
git submodule update --init firesim
|
||||||
|
cd firesim/sim
|
||||||
|
git submodule update --init midas
|
||||||
|
cd $RDIR
|
||||||
|
git config submodule.sims/firesim.update none
|
||||||
|
|||||||
1
sims/firesim
Submodule
1
sims/firesim
Submodule
Submodule sims/firesim added at 7f8152e511
@@ -3,7 +3,7 @@ OBJDUMP=riscv64-unknown-elf-objdump
|
|||||||
CFLAGS=-mcmodel=medany -std=gnu99 -O2 -fno-common -fno-builtin-printf -Wall
|
CFLAGS=-mcmodel=medany -std=gnu99 -O2 -fno-common -fno-builtin-printf -Wall
|
||||||
LDFLAGS=-static -nostdlib -nostartfiles -lgcc
|
LDFLAGS=-static -nostdlib -nostartfiles -lgcc
|
||||||
|
|
||||||
PROGRAMS = pwm blkdev accum charcount
|
PROGRAMS = pwm blkdev accum charcount nic-loopback big-blkdev pingd
|
||||||
|
|
||||||
default: $(addsuffix .riscv,$(PROGRAMS))
|
default: $(addsuffix .riscv,$(PROGRAMS))
|
||||||
|
|
||||||
|
|||||||
79
tests/big-blkdev.c
Normal file
79
tests/big-blkdev.c
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "mmio.h"
|
||||||
|
#include "blkdev.h"
|
||||||
|
|
||||||
|
#define SECTOR_WORDS (BLKDEV_SECTOR_SIZE / sizeof(uint64_t))
|
||||||
|
#define TEST_SECTORS 128
|
||||||
|
|
||||||
|
unsigned long sector_buf[SECTOR_WORDS];
|
||||||
|
|
||||||
|
void write_sector(unsigned int secnum)
|
||||||
|
{
|
||||||
|
int req_tag, resp_tag;
|
||||||
|
|
||||||
|
for (int i = 0; i < SECTOR_WORDS; i++)
|
||||||
|
sector_buf[i] = (secnum << 6) | i;
|
||||||
|
|
||||||
|
while (reg_read8(BLKDEV_NREQUEST) == 0);
|
||||||
|
req_tag = blkdev_send_request((unsigned long) sector_buf, secnum, 1, 1);
|
||||||
|
while (reg_read8(BLKDEV_NCOMPLETE) == 0);
|
||||||
|
resp_tag = reg_read8(BLKDEV_COMPLETE);
|
||||||
|
|
||||||
|
if (req_tag != resp_tag) {
|
||||||
|
printf("Response tag %d does not match request tag %d\n",
|
||||||
|
req_tag, resp_tag);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void check_sector(unsigned int secnum)
|
||||||
|
{
|
||||||
|
int req_tag, resp_tag;
|
||||||
|
|
||||||
|
while (reg_read8(BLKDEV_NREQUEST) == 0);
|
||||||
|
req_tag = blkdev_send_request((unsigned long) sector_buf, secnum, 1, 0);
|
||||||
|
while (reg_read8(BLKDEV_NCOMPLETE) == 0);
|
||||||
|
resp_tag = reg_read8(BLKDEV_COMPLETE);
|
||||||
|
|
||||||
|
if (req_tag != resp_tag) {
|
||||||
|
printf("Response tag %d does not match request tag %d\n",
|
||||||
|
req_tag, resp_tag);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < SECTOR_WORDS; i++) {
|
||||||
|
unsigned long expected = (secnum << 6) | i;
|
||||||
|
unsigned long actual = sector_buf[i];
|
||||||
|
if (actual != expected) {
|
||||||
|
printf("Word %d in sector %x does not match expected\n",
|
||||||
|
i, secnum);
|
||||||
|
printf("Expected %lx, got %lx\n",
|
||||||
|
expected, actual);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
unsigned int nsectors = blkdev_nsectors();
|
||||||
|
unsigned int stride = nsectors / TEST_SECTORS;
|
||||||
|
|
||||||
|
printf("Writing %u of %u sectors\n", TEST_SECTORS, nsectors);
|
||||||
|
|
||||||
|
for (int i = 0; i < TEST_SECTORS; i++) {
|
||||||
|
int sector = i * stride;
|
||||||
|
write_sector(sector);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Checking sectors\n", nsectors);
|
||||||
|
|
||||||
|
for (int i = 0; i < TEST_SECTORS; i++) {
|
||||||
|
int sector = i * stride;
|
||||||
|
check_sector(sector);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -2,30 +2,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "mmio.h"
|
#include "mmio.h"
|
||||||
|
#include "blkdev.h"
|
||||||
#define BLKDEV_BASE 0x10015000
|
|
||||||
#define BLKDEV_ADDR BLKDEV_BASE
|
|
||||||
#define BLKDEV_OFFSET (BLKDEV_BASE + 8)
|
|
||||||
#define BLKDEV_LEN (BLKDEV_BASE + 12)
|
|
||||||
#define BLKDEV_WRITE (BLKDEV_BASE + 16)
|
|
||||||
#define BLKDEV_REQUEST (BLKDEV_BASE + 17)
|
|
||||||
#define BLKDEV_NREQUEST (BLKDEV_BASE + 18)
|
|
||||||
#define BLKDEV_COMPLETE (BLKDEV_BASE + 19)
|
|
||||||
#define BLKDEV_NCOMPLETE (BLKDEV_BASE + 20)
|
|
||||||
#define BLKDEV_NSECTORS (BLKDEV_BASE + 24)
|
|
||||||
#define BLKDEV_MAX_REQUEST_LENGTH (BLKDEV_BASE + 28)
|
|
||||||
#define BLKDEV_SECTOR_SIZE 512
|
|
||||||
#define BLKDEV_SECTOR_SHIFT 9
|
|
||||||
|
|
||||||
size_t blkdev_nsectors(void)
|
|
||||||
{
|
|
||||||
return reg_read32(BLKDEV_NSECTORS);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t blkdev_max_req_len(void)
|
|
||||||
{
|
|
||||||
return reg_read32(BLKDEV_MAX_REQUEST_LENGTH);
|
|
||||||
}
|
|
||||||
|
|
||||||
void blkdev_read(void *addr, unsigned long offset, size_t nsectors)
|
void blkdev_read(void *addr, unsigned long offset, size_t nsectors)
|
||||||
{
|
{
|
||||||
@@ -38,12 +15,9 @@ void blkdev_read(void *addr, unsigned long offset, size_t nsectors)
|
|||||||
printf("sending %d reads\n", ntags);
|
printf("sending %d reads\n", ntags);
|
||||||
|
|
||||||
for (i = 0; i < ntags; i++) {
|
for (i = 0; i < ntags; i++) {
|
||||||
reg_write64(BLKDEV_ADDR, (unsigned long) addr);
|
req_tag = blkdev_send_request(
|
||||||
reg_write32(BLKDEV_OFFSET, offset);
|
(unsigned long) addr, offset,
|
||||||
reg_write32(BLKDEV_LEN, nsectors_per_tag);
|
nsectors_per_tag, 0);
|
||||||
reg_write8(BLKDEV_WRITE, 0);
|
|
||||||
|
|
||||||
req_tag = reg_read8(BLKDEV_REQUEST);
|
|
||||||
addr += (nsectors_per_tag << BLKDEV_SECTOR_SHIFT);
|
addr += (nsectors_per_tag << BLKDEV_SECTOR_SHIFT);
|
||||||
offset += nsectors_per_tag;
|
offset += nsectors_per_tag;
|
||||||
}
|
}
|
||||||
@@ -67,12 +41,9 @@ void blkdev_write(unsigned long offset, void *addr, size_t nsectors)
|
|||||||
printf("sending %d writes\n", ntags);
|
printf("sending %d writes\n", ntags);
|
||||||
|
|
||||||
for (i = 0; i < ntags; i++) {
|
for (i = 0; i < ntags; i++) {
|
||||||
reg_write64(BLKDEV_ADDR, (unsigned long) addr);
|
req_tag = blkdev_send_request(
|
||||||
reg_write32(BLKDEV_OFFSET, offset);
|
(unsigned long) addr, offset,
|
||||||
reg_write32(BLKDEV_LEN, nsectors_per_tag);
|
nsectors_per_tag, 1);
|
||||||
reg_write8(BLKDEV_WRITE, 1);
|
|
||||||
|
|
||||||
req_tag = reg_read8(BLKDEV_REQUEST);
|
|
||||||
addr += (nsectors_per_tag << BLKDEV_SECTOR_SHIFT);
|
addr += (nsectors_per_tag << BLKDEV_SECTOR_SHIFT);
|
||||||
offset += nsectors_per_tag;
|
offset += nsectors_per_tag;
|
||||||
}
|
}
|
||||||
|
|||||||
38
tests/blkdev.h
Normal file
38
tests/blkdev.h
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
#define BLKDEV_BASE 0x10015000
|
||||||
|
#define BLKDEV_ADDR BLKDEV_BASE
|
||||||
|
#define BLKDEV_OFFSET (BLKDEV_BASE + 8)
|
||||||
|
#define BLKDEV_LEN (BLKDEV_BASE + 12)
|
||||||
|
#define BLKDEV_WRITE (BLKDEV_BASE + 16)
|
||||||
|
#define BLKDEV_REQUEST (BLKDEV_BASE + 17)
|
||||||
|
#define BLKDEV_NREQUEST (BLKDEV_BASE + 18)
|
||||||
|
#define BLKDEV_COMPLETE (BLKDEV_BASE + 19)
|
||||||
|
#define BLKDEV_NCOMPLETE (BLKDEV_BASE + 20)
|
||||||
|
#define BLKDEV_NSECTORS (BLKDEV_BASE + 24)
|
||||||
|
#define BLKDEV_MAX_REQUEST_LENGTH (BLKDEV_BASE + 28)
|
||||||
|
#define BLKDEV_SECTOR_SIZE 512
|
||||||
|
#define BLKDEV_SECTOR_SHIFT 9
|
||||||
|
|
||||||
|
static inline size_t blkdev_nsectors(void)
|
||||||
|
{
|
||||||
|
return reg_read32(BLKDEV_NSECTORS);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline size_t blkdev_max_req_len(void)
|
||||||
|
{
|
||||||
|
return reg_read32(BLKDEV_MAX_REQUEST_LENGTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline unsigned int blkdev_send_request(
|
||||||
|
unsigned long addr,
|
||||||
|
unsigned int offset,
|
||||||
|
unsigned int len,
|
||||||
|
unsigned char write)
|
||||||
|
{
|
||||||
|
reg_write64(BLKDEV_ADDR, addr);
|
||||||
|
reg_write32(BLKDEV_OFFSET, offset);
|
||||||
|
reg_write32(BLKDEV_LEN, len);
|
||||||
|
reg_write8(BLKDEV_WRITE, write);
|
||||||
|
|
||||||
|
asm volatile ("fence");
|
||||||
|
return reg_read8(BLKDEV_REQUEST);
|
||||||
|
}
|
||||||
98
tests/nic-loopback.c
Normal file
98
tests/nic-loopback.c
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
#include "mmio.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "nic.h"
|
||||||
|
#include "encoding.h"
|
||||||
|
|
||||||
|
#define NPACKETS 10
|
||||||
|
#define TEST_OFFSET 3
|
||||||
|
#define TEST_LEN 356
|
||||||
|
#define ARRAY_LEN 360
|
||||||
|
#define NTRIALS 3
|
||||||
|
|
||||||
|
uint32_t src[NPACKETS][ARRAY_LEN];
|
||||||
|
uint32_t dst[NPACKETS][ARRAY_LEN];
|
||||||
|
uint64_t lengths[NPACKETS];
|
||||||
|
|
||||||
|
static inline void send_recv()
|
||||||
|
{
|
||||||
|
uint64_t send_packet, recv_addr;
|
||||||
|
int ncomps, send_comps_left = NPACKETS, recv_comps_left = NPACKETS;
|
||||||
|
int recv_idx = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < NPACKETS; i++) {
|
||||||
|
uint64_t pkt_size = TEST_LEN * sizeof(uint32_t);
|
||||||
|
uint64_t src_addr = (uint64_t) &src[i][TEST_OFFSET];
|
||||||
|
send_packet = (pkt_size << 48) | src_addr;
|
||||||
|
recv_addr = (uint64_t) dst[i];
|
||||||
|
reg_write64(SIMPLENIC_SEND_REQ, send_packet);
|
||||||
|
reg_write64(SIMPLENIC_RECV_REQ, recv_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (send_comps_left > 0 || recv_comps_left > 0) {
|
||||||
|
ncomps = nic_send_comp_avail();
|
||||||
|
asm volatile ("fence");
|
||||||
|
for (int i = 0; i < ncomps; i++)
|
||||||
|
reg_read16(SIMPLENIC_SEND_COMP);
|
||||||
|
send_comps_left -= ncomps;
|
||||||
|
|
||||||
|
ncomps = nic_recv_comp_avail();
|
||||||
|
asm volatile ("fence");
|
||||||
|
for (int i = 0; i < ncomps; i++) {
|
||||||
|
lengths[recv_idx] = reg_read16(SIMPLENIC_RECV_COMP);
|
||||||
|
recv_idx++;
|
||||||
|
}
|
||||||
|
recv_comps_left -= ncomps;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void run_test(void)
|
||||||
|
{
|
||||||
|
unsigned long start, end;
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
memset(dst, 0, sizeof(dst));
|
||||||
|
asm volatile ("fence");
|
||||||
|
|
||||||
|
start = rdcycle();
|
||||||
|
send_recv();
|
||||||
|
end = rdcycle();
|
||||||
|
|
||||||
|
printf("send/recv %lu cycles\n", end - start);
|
||||||
|
|
||||||
|
for (i = 0; i < NPACKETS; i++) {
|
||||||
|
if (lengths[i] != TEST_LEN * sizeof(uint32_t)) {
|
||||||
|
printf("recv got wrong # bytes\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j = 0; j < TEST_LEN; j++) {
|
||||||
|
if (dst[i][j] != src[i][j + TEST_OFFSET]) {
|
||||||
|
printf("Data mismatch @ %d, %d: %x != %x\n",
|
||||||
|
i, j, dst[i][j], src[i][j + TEST_OFFSET]);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
for (i = 0; i < NPACKETS; i++) {
|
||||||
|
for (j = 0; j < ARRAY_LEN; j++)
|
||||||
|
src[i][j] = i * ARRAY_LEN + j;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < NTRIALS; i++) {
|
||||||
|
printf("Trial %d\n", i);
|
||||||
|
run_test();
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("All correct\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -8,22 +8,22 @@
|
|||||||
|
|
||||||
static inline int nic_send_req_avail(void)
|
static inline int nic_send_req_avail(void)
|
||||||
{
|
{
|
||||||
return reg_read16(SIMPLENIC_COUNTS) & 0xf;
|
return reg_read32(SIMPLENIC_COUNTS) & 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int nic_recv_req_avail(void)
|
static inline int nic_recv_req_avail(void)
|
||||||
{
|
{
|
||||||
return (reg_read16(SIMPLENIC_COUNTS) >> 4) & 0xf;
|
return (reg_read32(SIMPLENIC_COUNTS) >> 8) & 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int nic_send_comp_avail(void)
|
static inline int nic_send_comp_avail(void)
|
||||||
{
|
{
|
||||||
return (reg_read16(SIMPLENIC_COUNTS) >> 8) & 0xf;
|
return (reg_read32(SIMPLENIC_COUNTS) >> 16) & 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int nic_recv_comp_avail(void)
|
static inline int nic_recv_comp_avail(void)
|
||||||
{
|
{
|
||||||
return (reg_read16(SIMPLENIC_COUNTS) >> 12) & 0xf;
|
return (reg_read32(SIMPLENIC_COUNTS) >> 24) & 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void nic_send(void *data, unsigned long len)
|
static void nic_send(void *data, unsigned long len)
|
||||||
|
|||||||
254
tests/pingd.c
Normal file
254
tests/pingd.c
Normal file
@@ -0,0 +1,254 @@
|
|||||||
|
#include "mmio.h"
|
||||||
|
#include "nic.h"
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define ETH_MAX_WORDS 190
|
||||||
|
#define NET_IP_ALIGN 2
|
||||||
|
#define ETH_HEADER_SIZE 14
|
||||||
|
#define MAC_ADDR_SIZE 6
|
||||||
|
#define IP_ADDR_SIZE 4
|
||||||
|
|
||||||
|
#define IPV4_ETHTYPE 0x0800
|
||||||
|
#define ARP_ETHTYPE 0x0806
|
||||||
|
#define ICMP_PROT 1
|
||||||
|
#define ECHO_REPLY 0
|
||||||
|
#define ECHO_REQUEST 8
|
||||||
|
#define ARP_REQUEST 1
|
||||||
|
#define ARP_REPLY 2
|
||||||
|
#define HTYPE_ETH 1
|
||||||
|
|
||||||
|
static inline uint16_t ntohs(uint16_t nint)
|
||||||
|
{
|
||||||
|
return ((nint & 0xff) << 8) | ((nint >> 8) & 0xff);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint16_t htons(uint16_t nint)
|
||||||
|
{
|
||||||
|
return ntohs(nint);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct eth_header {
|
||||||
|
uint8_t padding[NET_IP_ALIGN];
|
||||||
|
uint8_t dst_mac[MAC_ADDR_SIZE];
|
||||||
|
uint8_t src_mac[MAC_ADDR_SIZE];
|
||||||
|
uint16_t ethtype;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct arp_header {
|
||||||
|
uint16_t htype;
|
||||||
|
uint16_t ptype;
|
||||||
|
uint8_t hlen;
|
||||||
|
uint8_t plen;
|
||||||
|
uint16_t oper;
|
||||||
|
uint8_t sha[MAC_ADDR_SIZE];
|
||||||
|
uint8_t spa[IP_ADDR_SIZE];
|
||||||
|
uint8_t tha[MAC_ADDR_SIZE];
|
||||||
|
uint8_t tpa[IP_ADDR_SIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ipv4_header {
|
||||||
|
uint8_t ver_ihl;
|
||||||
|
uint8_t dscp_ecn;
|
||||||
|
uint16_t length;
|
||||||
|
uint16_t ident;
|
||||||
|
uint16_t flags_frag_off;
|
||||||
|
uint8_t ttl;
|
||||||
|
uint8_t prot;
|
||||||
|
uint16_t cksum;
|
||||||
|
uint32_t src_addr;
|
||||||
|
uint32_t dst_addr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct icmp_header {
|
||||||
|
uint8_t type;
|
||||||
|
uint8_t code;
|
||||||
|
uint16_t cksum;
|
||||||
|
uint32_t rest;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int checksum(uint16_t *data, int len)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
uint32_t sum = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
|
sum += ntohs(data[i]);
|
||||||
|
|
||||||
|
while ((sum >> 16) != 0)
|
||||||
|
sum = (sum & 0xffff) + (sum >> 16);
|
||||||
|
|
||||||
|
sum = ~sum & 0xffff;
|
||||||
|
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ceil_div(n, d) (((n) - 1) / (d) + 1)
|
||||||
|
|
||||||
|
static int process_arp(void *buf, uint8_t *mac)
|
||||||
|
{
|
||||||
|
struct eth_header *eth = buf;
|
||||||
|
struct arp_header *arp;
|
||||||
|
size_t size = ETH_HEADER_SIZE + sizeof(*arp);
|
||||||
|
uint8_t tmp_addr[IP_ADDR_SIZE];
|
||||||
|
|
||||||
|
// Verify arp packet
|
||||||
|
arp = buf + sizeof(*eth);
|
||||||
|
if (ntohs(arp->oper) != ARP_REQUEST) {
|
||||||
|
printf("Wrong arp operation: %d\n", ntohs(arp->oper));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ntohs(arp->htype) != HTYPE_ETH) {
|
||||||
|
printf("Wrong ARP HTYPE\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ntohs(arp->ptype) != IPV4_ETHTYPE) {
|
||||||
|
printf("Wrong ARP PTYPE\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arp->hlen != 6) {
|
||||||
|
printf("Wrong ARP HLEN: %d\n", arp->hlen);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arp->plen != 4) {
|
||||||
|
printf("Wrong ARP PLEN: %d\n", arp->plen);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make the source the destination, and add our mac address
|
||||||
|
memcpy(eth->dst_mac, eth->src_mac, MAC_ADDR_SIZE);
|
||||||
|
memcpy(eth->src_mac, mac, MAC_ADDR_SIZE);
|
||||||
|
|
||||||
|
// create ARP reply
|
||||||
|
arp->oper = htons(ARP_REPLY);
|
||||||
|
|
||||||
|
// Make tha the sha, and fill in sha with actual mac address
|
||||||
|
memcpy(arp->tha, arp->sha, MAC_ADDR_SIZE);
|
||||||
|
memcpy(arp->sha, mac, MAC_ADDR_SIZE);
|
||||||
|
|
||||||
|
// Swap spa and tpa in arp packet
|
||||||
|
memcpy(tmp_addr, arp->tpa, IP_ADDR_SIZE);
|
||||||
|
memcpy(arp->tpa, arp->spa, IP_ADDR_SIZE);
|
||||||
|
memcpy(arp->spa, tmp_addr, IP_ADDR_SIZE);
|
||||||
|
|
||||||
|
size = ceil_div(size + NET_IP_ALIGN, 8) * 8;
|
||||||
|
nic_send(buf, size);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static int process_icmp(void *buf, uint8_t *mac)
|
||||||
|
{
|
||||||
|
struct eth_header *eth = buf;
|
||||||
|
struct ipv4_header *ipv4;
|
||||||
|
struct icmp_header *icmp;
|
||||||
|
int ihl, icmp_size;
|
||||||
|
ssize_t size;
|
||||||
|
uint32_t tmp_addr;
|
||||||
|
|
||||||
|
// verify IPv4
|
||||||
|
ipv4 = buf + sizeof(*eth);
|
||||||
|
ihl = ipv4->ver_ihl & 0xf;
|
||||||
|
|
||||||
|
if (checksum((uint16_t *) ipv4, ihl << 1) != 0) {
|
||||||
|
printf("Bad IP header checksum %04x\n", ipv4->cksum);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ipv4->prot != ICMP_PROT) {
|
||||||
|
printf("Wrong IP protocol %d\n", ipv4->prot);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// verify ICMP
|
||||||
|
icmp = (buf + sizeof(*eth) + (ihl << 2));
|
||||||
|
|
||||||
|
if (icmp->type != ECHO_REQUEST) {
|
||||||
|
printf("Wrong ICMP type %d\n", icmp->type);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (icmp->code != 0) {
|
||||||
|
printf("Wrong ICMP code %d\n", icmp->code);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
icmp_size = ntohs(ipv4->length) - (ihl << 2);
|
||||||
|
if (checksum((uint16_t *) icmp, icmp_size >> 1) != 0) {
|
||||||
|
printf("Bad ICMP checksum %04x\n", icmp->cksum);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the destination and source MACs
|
||||||
|
memcpy(eth->dst_mac, eth->src_mac, MAC_ADDR_SIZE);
|
||||||
|
memcpy(eth->src_mac, mac, MAC_ADDR_SIZE);
|
||||||
|
|
||||||
|
// Swap the source and destination IP addresses
|
||||||
|
tmp_addr = ipv4->dst_addr;
|
||||||
|
ipv4->dst_addr = ipv4->src_addr;
|
||||||
|
ipv4->src_addr = tmp_addr;
|
||||||
|
|
||||||
|
// compute the IPv4 header checksum
|
||||||
|
ipv4->cksum = 0;
|
||||||
|
ipv4->cksum = htons(checksum((uint16_t *) ipv4, ihl << 1));
|
||||||
|
|
||||||
|
// set the ICMP type to reply and compute checksum
|
||||||
|
icmp->cksum = 0;
|
||||||
|
icmp->type = ECHO_REPLY;
|
||||||
|
icmp->cksum = htons(checksum((uint16_t *) icmp, icmp_size >> 1));
|
||||||
|
size = ntohs(ipv4->length) + ETH_HEADER_SIZE;
|
||||||
|
|
||||||
|
size = ceil_div(size + NET_IP_ALIGN, 8) * 8;
|
||||||
|
nic_send(buf, size);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int process_packet(void *buf, uint8_t *mac)
|
||||||
|
{
|
||||||
|
struct eth_header *eth;
|
||||||
|
|
||||||
|
// read the ICMP request
|
||||||
|
nic_recv(buf);
|
||||||
|
eth = buf;
|
||||||
|
printf("Got packet: [ethtype=%04x]\n", ntohs(eth->ethtype));
|
||||||
|
// Check ethernet type
|
||||||
|
switch (ntohs(eth->ethtype)) {
|
||||||
|
case IPV4_ETHTYPE:
|
||||||
|
return process_icmp(buf, mac);
|
||||||
|
case ARP_ETHTYPE:
|
||||||
|
return process_arp(buf, mac);
|
||||||
|
default:
|
||||||
|
printf("Wrong ethtype %x\n", ntohs(eth->ethtype));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t buffer[ETH_MAX_WORDS];
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
uint64_t macaddr_long;
|
||||||
|
uint8_t *macaddr;
|
||||||
|
|
||||||
|
macaddr_long = nic_macaddr();
|
||||||
|
macaddr = (uint8_t *) &macaddr_long;
|
||||||
|
|
||||||
|
printf("macaddr - %02x", macaddr[0]);
|
||||||
|
for (int i = 1; i < MAC_ADDR_SIZE; i++)
|
||||||
|
printf(":%02x", macaddr[i]);
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
if (process_packet(buffer, macaddr))
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
17
variables.mk
17
variables.mk
@@ -44,7 +44,7 @@ ifeq ($(SUB_PROJECT),boom)
|
|||||||
MODEL ?= TestHarness
|
MODEL ?= TestHarness
|
||||||
VLOG_MODEL ?= TestHarness
|
VLOG_MODEL ?= TestHarness
|
||||||
MODEL_PACKAGE ?= boom.system
|
MODEL_PACKAGE ?= boom.system
|
||||||
CONFIG ?= BoomConfig
|
CONFIG ?= LargeBoomConfig
|
||||||
CONFIG_PACKAGE ?= boom.system
|
CONFIG_PACKAGE ?= boom.system
|
||||||
GENERATOR_PACKAGE ?= boom.system
|
GENERATOR_PACKAGE ?= boom.system
|
||||||
TB ?= TestDriver
|
TB ?= TestDriver
|
||||||
@@ -52,7 +52,7 @@ ifeq ($(SUB_PROJECT),boom)
|
|||||||
endif
|
endif
|
||||||
# for Rocket-chip developers
|
# for Rocket-chip developers
|
||||||
ifeq ($(SUB_PROJECT),rocketchip)
|
ifeq ($(SUB_PROJECT),rocketchip)
|
||||||
SBT_PROJECT ?= chipyardrocketchip
|
SBT_PROJECT ?= rocketchip
|
||||||
MODEL ?= TestHarness
|
MODEL ?= TestHarness
|
||||||
VLOG_MODEL ?= TestHarness
|
VLOG_MODEL ?= TestHarness
|
||||||
MODEL_PACKAGE ?= freechips.rocketchip.system
|
MODEL_PACKAGE ?= freechips.rocketchip.system
|
||||||
@@ -74,6 +74,19 @@ ifeq ($(SUB_PROJECT),hwacha)
|
|||||||
TB ?= TestDriver
|
TB ?= TestDriver
|
||||||
TOP ?= ExampleRocketSystem
|
TOP ?= ExampleRocketSystem
|
||||||
endif
|
endif
|
||||||
|
# Stand-in firechip variables:
|
||||||
|
# TODO: need a seperate generator and test harnesses for each target
|
||||||
|
#ifeq ($(SUB_PROJECT),firechip)
|
||||||
|
# SBT_PROJECT ?= $(SUB_PROJECT)
|
||||||
|
# MODEL ?= TestHarness
|
||||||
|
# VLOG_MODEL ?= TestHarness
|
||||||
|
# MODEL_PACKAGE ?= freechips.rocketchip.system
|
||||||
|
# CONFIG ?= FireSimRocketChipConfig
|
||||||
|
# CONFIG_PACKAGE ?= firesim.firesim
|
||||||
|
# GENERATOR_PACKAGE ?= firesim.firesim
|
||||||
|
# TB ?= TestDriver
|
||||||
|
# TOP ?= FireSimNoNIC
|
||||||
|
#endif
|
||||||
|
|
||||||
#########################################################################################
|
#########################################################################################
|
||||||
# path to rocket-chip and testchipip
|
# path to rocket-chip and testchipip
|
||||||
|
|||||||
Reference in New Issue
Block a user