Merge pull request #323 from ucb-bar/unittest-config
Factor testsuite makefrag generation out of Configs and into Generator
This commit is contained in:
commit
a1d5102da9
2
Makefrag
2
Makefrag
@ -23,8 +23,6 @@ $(FIRRTL_JAR): $(shell find $(base_dir)/firrtl/src/main/scala -iname "*.scala")
|
|||||||
$(MAKE) -C $(base_dir)/firrtl SBT="$(SBT)" root_dir=$(base_dir)/firrtl build-scala
|
$(MAKE) -C $(base_dir)/firrtl SBT="$(SBT)" root_dir=$(base_dir)/firrtl build-scala
|
||||||
touch $(FIRRTL_JAR)
|
touch $(FIRRTL_JAR)
|
||||||
|
|
||||||
CHISEL_ARGS := --targetDir $(generated_dir)
|
|
||||||
|
|
||||||
src_path = src/main/scala
|
src_path = src/main/scala
|
||||||
default_submodules = . hardfloat context-dependent-environments chisel3
|
default_submodules = . hardfloat context-dependent-environments chisel3
|
||||||
chisel_srcs = $(foreach submodule,$(default_submodules) $(ROCKETCHIP_ADDONS),$(shell find $(base_dir)/$(submodule)/$(src_path) -name "*.scala"))
|
chisel_srcs = $(foreach submodule,$(default_submodules) $(ROCKETCHIP_ADDONS),$(shell find $(base_dir)/$(submodule)/$(src_path) -name "*.scala"))
|
||||||
|
@ -23,10 +23,7 @@ debug: $(emu_debug)
|
|||||||
clean:
|
clean:
|
||||||
rm -rf *.o *.a emulator-* $(generated_dir) $(generated_dir_debug) DVEfiles $(output_dir)
|
rm -rf *.o *.a emulator-* $(generated_dir) $(generated_dir_debug) DVEfiles $(output_dir)
|
||||||
|
|
||||||
test:
|
.PHONY: default all debug clean
|
||||||
cd $(base_dir) && $(SBT) "~make $(CURDIR) run-fast $(CHISEL_ARGS)"
|
|
||||||
|
|
||||||
.PHONY: default all debug clean test
|
|
||||||
|
|
||||||
#--------------------------------------------------------------------
|
#--------------------------------------------------------------------
|
||||||
# Run assembly tests and benchmarks
|
# Run assembly tests and benchmarks
|
||||||
|
@ -10,11 +10,11 @@ verilog_debug = $(generated_dir_debug)/$(long_name).v
|
|||||||
|
|
||||||
$(generated_dir)/%.fir $(generated_dir)/%.prm $(generated_dir)/%.d: $(chisel_srcs) $(bootrom_img)
|
$(generated_dir)/%.fir $(generated_dir)/%.prm $(generated_dir)/%.d: $(chisel_srcs) $(bootrom_img)
|
||||||
mkdir -p $(dir $@)
|
mkdir -p $(dir $@)
|
||||||
cd $(base_dir) && $(SBT) "run $(generated_dir) $(PROJECT) $(MODEL) $(CFG_PROJECT) $(CONFIG)"
|
cd $(base_dir) && $(SBT) "run-main $(PROJECT).Generator $(generated_dir) $(PROJECT) $(MODEL) $(CFG_PROJECT) $(CONFIG)"
|
||||||
|
|
||||||
$(generated_dir_debug)/%.fir $(generated_dir_debug)/%.prm $(generated_dir_debug)/%.d: $(chisel_srcs) $(bootrom_img)
|
$(generated_dir_debug)/%.fir $(generated_dir_debug)/%.prm $(generated_dir_debug)/%.d: $(chisel_srcs) $(bootrom_img)
|
||||||
mkdir -p $(dir $@)
|
mkdir -p $(dir $@)
|
||||||
cd $(base_dir) && $(SBT) "run $(generated_dir_debug) $(PROJECT) $(MODEL) $(CFG_PROJECT) $(CONFIG)"
|
cd $(base_dir) && $(SBT) "run-main $(PROJECT).Generator $(generated_dir_debug) $(PROJECT) $(MODEL) $(CFG_PROJECT) $(CONFIG)"
|
||||||
|
|
||||||
%.v: %.fir $(FIRRTL_JAR)
|
%.v: %.fir $(FIRRTL_JAR)
|
||||||
mkdir -p $(dir $@)
|
mkdir -p $(dir $@)
|
||||||
|
@ -32,7 +32,7 @@ object BuildSettings extends Build {
|
|||||||
a.split(" ")
|
a.split(" ")
|
||||||
},
|
},
|
||||||
unmanagedSourceDirectories in Compile ++= addons.value.map(baseDirectory.value / _ / "src/main/scala"),
|
unmanagedSourceDirectories in Compile ++= addons.value.map(baseDirectory.value / _ / "src/main/scala"),
|
||||||
mainClass in (Compile, run) := Some("rocketchip.RocketChipGenerator"),
|
mainClass in (Compile, run) := Some("rocketchip.Generator"),
|
||||||
make := {
|
make := {
|
||||||
val jobs = java.lang.Runtime.getRuntime.availableProcessors
|
val jobs = java.lang.Runtime.getRuntime.availableProcessors
|
||||||
val (makeDir, target) = setMake.parsed
|
val (makeDir, target) = setMake.parsed
|
||||||
|
@ -52,7 +52,7 @@ endif
|
|||||||
|
|
||||||
ifeq ($(SUITE),UnittestSuite)
|
ifeq ($(SUITE),UnittestSuite)
|
||||||
PROJECT=unittest
|
PROJECT=unittest
|
||||||
CONFIGS=UnitTestConfig
|
CONFIGS=JunctionsUnitTestConfig UncoreUnitTestConfig
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(SUITE), JtagDtmSuite)
|
ifeq ($(SUITE), JtagDtmSuite)
|
||||||
|
@ -13,8 +13,6 @@ import rocket._
|
|||||||
import rocket.Util._
|
import rocket.Util._
|
||||||
import util.ConfigUtils._
|
import util.ConfigUtils._
|
||||||
import rocketchip.{GlobalAddrMap, NCoreplexExtClients}
|
import rocketchip.{GlobalAddrMap, NCoreplexExtClients}
|
||||||
import scala.collection.mutable.{LinkedHashSet, ListBuffer}
|
|
||||||
import DefaultTestSuites._
|
|
||||||
import cde.{Parameters, Config, Dump, Knob, CDEMatchError}
|
import cde.{Parameters, Config, Dump, Knob, CDEMatchError}
|
||||||
|
|
||||||
class BaseCoreplexConfig extends Config (
|
class BaseCoreplexConfig extends Config (
|
||||||
@ -71,28 +69,6 @@ class BaseCoreplexConfig extends Config (
|
|||||||
case NUncachedTileLinkPorts => 1
|
case NUncachedTileLinkPorts => 1
|
||||||
//Tile Constants
|
//Tile Constants
|
||||||
case BuildTiles => {
|
case BuildTiles => {
|
||||||
val env = if(site(UseVM)) List("p","v") else List("p")
|
|
||||||
site(FPUKey) foreach { case cfg =>
|
|
||||||
if (site(XLen) == 32) {
|
|
||||||
TestGeneration.addSuites(env.map(rv32ufNoDiv))
|
|
||||||
} else {
|
|
||||||
TestGeneration.addSuite(rv32udBenchmarks)
|
|
||||||
TestGeneration.addSuites(env.map(rv64ufNoDiv))
|
|
||||||
TestGeneration.addSuites(env.map(rv64udNoDiv))
|
|
||||||
if (cfg.divSqrt) {
|
|
||||||
TestGeneration.addSuites(env.map(rv64uf))
|
|
||||||
TestGeneration.addSuites(env.map(rv64ud))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (site(UseAtomics)) TestGeneration.addSuites(env.map(if (site(XLen) == 64) rv64ua else rv32ua))
|
|
||||||
if (site(UseCompressed)) TestGeneration.addSuites(env.map(if (site(XLen) == 64) rv64uc else rv32uc))
|
|
||||||
val (rvi, rvu) =
|
|
||||||
if (site(XLen) == 64) ((if (site(UseVM)) rv64i else rv64pi), rv64u)
|
|
||||||
else ((if (site(UseVM)) rv32i else rv32pi), rv32u)
|
|
||||||
TestGeneration.addSuites(rvi.map(_("p")))
|
|
||||||
TestGeneration.addSuites((if(site(UseVM)) List("v") else List()).flatMap(env => rvu.map(_(env))))
|
|
||||||
TestGeneration.addSuite(benchmarks)
|
|
||||||
List.tabulate(site(NTiles)){ i => (r: Bool, p: Parameters) =>
|
List.tabulate(site(NTiles)){ i => (r: Bool, p: Parameters) =>
|
||||||
Module(new RocketTile(resetSignal = r)(p.alterPartial({
|
Module(new RocketTile(resetSignal = r)(p.alterPartial({
|
||||||
case TileId => i
|
case TileId => i
|
||||||
@ -187,32 +163,6 @@ class BaseCoreplexConfig extends Config (
|
|||||||
case CacheBlockBytes => Dump("CACHE_BLOCK_BYTES", 64)
|
case CacheBlockBytes => Dump("CACHE_BLOCK_BYTES", 64)
|
||||||
case CacheBlockOffsetBits => log2Up(here(CacheBlockBytes))
|
case CacheBlockOffsetBits => log2Up(here(CacheBlockBytes))
|
||||||
case EnableL2Logging => false
|
case EnableL2Logging => false
|
||||||
case RegressionTestNames => LinkedHashSet(
|
|
||||||
"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")
|
|
||||||
case _ => throw new CDEMatchError
|
case _ => throw new CDEMatchError
|
||||||
}},
|
}},
|
||||||
knobValues = {
|
knobValues = {
|
||||||
@ -327,14 +277,6 @@ class WithRV32 extends Config(
|
|||||||
(pname,site,here) => pname match {
|
(pname,site,here) => pname match {
|
||||||
case XLen => 32
|
case XLen => 32
|
||||||
case FPUKey => Some(FPUConfig(divSqrt = false))
|
case FPUKey => Some(FPUConfig(divSqrt = false))
|
||||||
case RegressionTestNames => LinkedHashSet(
|
|
||||||
"rv32mi-p-ma_addr",
|
|
||||||
"rv32mi-p-csr",
|
|
||||||
"rv32ui-p-sh",
|
|
||||||
"rv32ui-p-lh",
|
|
||||||
"rv32uc-p-rvc",
|
|
||||||
"rv32mi-p-sbreak",
|
|
||||||
"rv32ui-p-sll")
|
|
||||||
case _ => throw new CDEMatchError
|
case _ => throw new CDEMatchError
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -7,8 +7,6 @@ import uncore.coherence._
|
|||||||
import uncore.agents._
|
import uncore.agents._
|
||||||
import uncore.devices.NTiles
|
import uncore.devices.NTiles
|
||||||
import junctions._
|
import junctions._
|
||||||
import scala.collection.mutable.LinkedHashSet
|
|
||||||
import scala.collection.immutable.HashMap
|
|
||||||
import cde.{Parameters, Config, Dump, Knob, CDEMatchError}
|
import cde.{Parameters, Config, Dump, Knob, CDEMatchError}
|
||||||
import scala.math.max
|
import scala.math.max
|
||||||
import coreplex._
|
import coreplex._
|
||||||
@ -102,12 +100,6 @@ class WithGroundTest extends Config(
|
|||||||
dataBits = site(CacheBlockBytes)*8)
|
dataBits = site(CacheBlockBytes)*8)
|
||||||
}
|
}
|
||||||
case BuildTiles => {
|
case BuildTiles => {
|
||||||
val groundtest = if (site(XLen) == 64)
|
|
||||||
DefaultTestSuites.groundtest64
|
|
||||||
else
|
|
||||||
DefaultTestSuites.groundtest32
|
|
||||||
TestGeneration.addSuite(groundtest("p"))
|
|
||||||
TestGeneration.addSuite(DefaultTestSuites.emptyBmarks)
|
|
||||||
(0 until site(NTiles)).map { i =>
|
(0 until site(NTiles)).map { i =>
|
||||||
val tileSettings = site(GroundTestKey)(i)
|
val tileSettings = site(GroundTestKey)(i)
|
||||||
(r: Bool, p: Parameters) => {
|
(r: Bool, p: Parameters) => {
|
||||||
@ -125,7 +117,6 @@ class WithGroundTest extends Config(
|
|||||||
case FPUKey => None
|
case FPUKey => None
|
||||||
case UseAtomics => false
|
case UseAtomics => false
|
||||||
case UseCompressed => false
|
case UseCompressed => false
|
||||||
case RegressionTestNames => LinkedHashSet("rv64ui-p-simple")
|
|
||||||
case _ => throw new CDEMatchError
|
case _ => throw new CDEMatchError
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -166,7 +157,7 @@ class WithMemtest extends Config(
|
|||||||
case GroundTestKey => Seq.fill(site(NTiles)) {
|
case GroundTestKey => Seq.fill(site(NTiles)) {
|
||||||
GroundTestTileSettings(1, 1)
|
GroundTestTileSettings(1, 1)
|
||||||
}
|
}
|
||||||
case GeneratorKey => GeneratorParameters(
|
case GeneratorKey => TrafficGeneratorParameters(
|
||||||
maxRequests = 128,
|
maxRequests = 128,
|
||||||
startAddress = site(GlobalAddrMap)("mem").start)
|
startAddress = site(GlobalAddrMap)("mem").start)
|
||||||
case BuildGroundTest =>
|
case BuildGroundTest =>
|
||||||
@ -226,7 +217,7 @@ class WithNastiConverterTest extends Config(
|
|||||||
case GroundTestKey => Seq.fill(site(NTiles)) {
|
case GroundTestKey => Seq.fill(site(NTiles)) {
|
||||||
GroundTestTileSettings(uncached = 1)
|
GroundTestTileSettings(uncached = 1)
|
||||||
}
|
}
|
||||||
case GeneratorKey => GeneratorParameters(
|
case GeneratorKey => TrafficGeneratorParameters(
|
||||||
maxRequests = 128,
|
maxRequests = 128,
|
||||||
startAddress = site(GlobalAddrMap)("mem").start)
|
startAddress = site(GlobalAddrMap)("mem").start)
|
||||||
case BuildGroundTest =>
|
case BuildGroundTest =>
|
||||||
@ -241,7 +232,7 @@ class WithTraceGen extends Config(
|
|||||||
}
|
}
|
||||||
case BuildGroundTest =>
|
case BuildGroundTest =>
|
||||||
(p: Parameters) => Module(new GroundTestTraceGenerator()(p))
|
(p: Parameters) => Module(new GroundTestTraceGenerator()(p))
|
||||||
case GeneratorKey => GeneratorParameters(
|
case GeneratorKey => TrafficGeneratorParameters(
|
||||||
maxRequests = 256,
|
maxRequests = 256,
|
||||||
startAddress = 0)
|
startAddress = 0)
|
||||||
case AddressBag => {
|
case AddressBag => {
|
||||||
@ -269,7 +260,7 @@ class WithPCIeMockupTest extends Config(
|
|||||||
case GroundTestKey => Seq(
|
case GroundTestKey => Seq(
|
||||||
GroundTestTileSettings(1, 1),
|
GroundTestTileSettings(1, 1),
|
||||||
GroundTestTileSettings(1))
|
GroundTestTileSettings(1))
|
||||||
case GeneratorKey => GeneratorParameters(
|
case GeneratorKey => TrafficGeneratorParameters(
|
||||||
maxRequests = 128,
|
maxRequests = 128,
|
||||||
startAddress = site(GlobalAddrMap)("mem").start)
|
startAddress = site(GlobalAddrMap)("mem").start)
|
||||||
case BuildGroundTest =>
|
case BuildGroundTest =>
|
||||||
@ -285,7 +276,7 @@ class WithDirectMemtest extends Config(
|
|||||||
val nGens = 8
|
val nGens = 8
|
||||||
pname match {
|
pname match {
|
||||||
case GroundTestKey => Seq(GroundTestTileSettings(uncached = nGens))
|
case GroundTestKey => Seq(GroundTestTileSettings(uncached = nGens))
|
||||||
case GeneratorKey => GeneratorParameters(
|
case GeneratorKey => TrafficGeneratorParameters(
|
||||||
maxRequests = 1024,
|
maxRequests = 1024,
|
||||||
startAddress = 0)
|
startAddress = 0)
|
||||||
case BuildGroundTest =>
|
case BuildGroundTest =>
|
||||||
|
@ -1,213 +1,10 @@
|
|||||||
|
// See LICENSE for license details.
|
||||||
|
|
||||||
package groundtest
|
package groundtest
|
||||||
|
|
||||||
import Chisel._
|
object Generator extends util.GeneratorApp {
|
||||||
import uncore.tilelink._
|
val longName = names.topModuleProject + "." + names.configs
|
||||||
import uncore.devices.NTiles
|
generateFirrtl
|
||||||
import uncore.constants._
|
generateTestSuiteMakefrags // TODO: Needed only for legacy make targets
|
||||||
import junctions._
|
generateParameterDump // TODO: Needed only for legacy make targets
|
||||||
import rocket._
|
|
||||||
import util.SimpleTimer
|
|
||||||
import scala.util.Random
|
|
||||||
import cde.{Parameters, Field}
|
|
||||||
|
|
||||||
case class GeneratorParameters(
|
|
||||||
maxRequests: Int,
|
|
||||||
startAddress: BigInt)
|
|
||||||
case object GeneratorKey extends Field[GeneratorParameters]
|
|
||||||
|
|
||||||
trait HasGeneratorParameters extends HasGroundTestParameters {
|
|
||||||
implicit val p: Parameters
|
|
||||||
|
|
||||||
val genParams = p(GeneratorKey)
|
|
||||||
val nGens = p(GroundTestKey).map(
|
|
||||||
cs => cs.uncached + cs.cached).reduce(_ + _)
|
|
||||||
val genTimeout = 8192
|
|
||||||
val maxRequests = genParams.maxRequests
|
|
||||||
val startAddress = genParams.startAddress
|
|
||||||
|
|
||||||
val genWordBits = 32
|
|
||||||
val genWordBytes = genWordBits / 8
|
|
||||||
val wordOffset = log2Ceil(genWordBytes)
|
|
||||||
val wordSize = UInt(log2Ceil(genWordBytes))
|
|
||||||
|
|
||||||
require(startAddress % BigInt(genWordBytes) == 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
class UncachedTileLinkGenerator(id: Int)
|
|
||||||
(implicit p: Parameters) extends TLModule()(p) with HasGeneratorParameters {
|
|
||||||
|
|
||||||
private val tlBlockOffset = tlBeatAddrBits + tlByteAddrBits
|
|
||||||
|
|
||||||
val io = new Bundle {
|
|
||||||
val mem = new ClientUncachedTileLinkIO
|
|
||||||
val status = new GroundTestStatus
|
|
||||||
}
|
|
||||||
|
|
||||||
val (s_start :: s_put :: s_get :: s_finished :: Nil) = Enum(Bits(), 4)
|
|
||||||
val state = Reg(init = s_start)
|
|
||||||
|
|
||||||
val (req_cnt, req_wrap) = Counter(io.mem.grant.fire(), maxRequests)
|
|
||||||
|
|
||||||
val sending = Reg(init = Bool(false))
|
|
||||||
|
|
||||||
when (state === s_start) {
|
|
||||||
sending := Bool(true)
|
|
||||||
state := s_put
|
|
||||||
}
|
|
||||||
|
|
||||||
when (io.mem.acquire.fire()) { sending := Bool(false) }
|
|
||||||
when (io.mem.grant.fire()) { sending := Bool(true) }
|
|
||||||
when (req_wrap) { state := Mux(state === s_put, s_get, s_finished) }
|
|
||||||
|
|
||||||
val timeout = SimpleTimer(genTimeout, io.mem.acquire.fire(), io.mem.grant.fire())
|
|
||||||
assert(!timeout, s"Uncached generator ${id} timed out waiting for grant")
|
|
||||||
|
|
||||||
io.status.finished := (state === s_finished)
|
|
||||||
io.status.timeout.valid := timeout
|
|
||||||
io.status.timeout.bits := UInt(id)
|
|
||||||
|
|
||||||
val part_of_full_addr =
|
|
||||||
if (log2Ceil(nGens) > 0) {
|
|
||||||
Cat(UInt(id, log2Ceil(nGens)),
|
|
||||||
UInt(0, wordOffset))
|
|
||||||
} else {
|
|
||||||
UInt(0, wordOffset)
|
|
||||||
}
|
|
||||||
val full_addr = UInt(startAddress) + Cat(req_cnt, part_of_full_addr)
|
|
||||||
|
|
||||||
val addr_block = full_addr >> UInt(tlBlockOffset)
|
|
||||||
val addr_beat = full_addr(tlBlockOffset - 1, tlByteAddrBits)
|
|
||||||
val addr_byte = full_addr(tlByteAddrBits - 1, 0)
|
|
||||||
|
|
||||||
val data_prefix = Cat(UInt(id, log2Up(nGens)), req_cnt)
|
|
||||||
val word_data = Wire(UInt(width = genWordBits))
|
|
||||||
word_data := Cat(data_prefix, part_of_full_addr)
|
|
||||||
val beat_data = Fill(tlDataBits / genWordBits, word_data)
|
|
||||||
val wshift = Cat(beatOffset(full_addr), UInt(0, wordOffset))
|
|
||||||
val wmask = Fill(genWordBits / 8, Bits(1, 1)) << wshift
|
|
||||||
|
|
||||||
val put_acquire = Put(
|
|
||||||
client_xact_id = UInt(0),
|
|
||||||
addr_block = addr_block,
|
|
||||||
addr_beat = addr_beat,
|
|
||||||
data = beat_data,
|
|
||||||
wmask = Some(wmask),
|
|
||||||
alloc = Bool(false))
|
|
||||||
|
|
||||||
val get_acquire = Get(
|
|
||||||
client_xact_id = UInt(0),
|
|
||||||
addr_block = addr_block,
|
|
||||||
addr_beat = addr_beat,
|
|
||||||
addr_byte = addr_byte,
|
|
||||||
operand_size = wordSize,
|
|
||||||
alloc = Bool(false))
|
|
||||||
|
|
||||||
io.mem.acquire.valid := sending && !io.status.finished
|
|
||||||
io.mem.acquire.bits := Mux(state === s_put, put_acquire, get_acquire)
|
|
||||||
io.mem.grant.ready := !sending && !io.status.finished
|
|
||||||
|
|
||||||
def wordFromBeat(addr: UInt, dat: UInt) = {
|
|
||||||
val shift = Cat(beatOffset(addr), UInt(0, wordOffset + 3))
|
|
||||||
(dat >> shift)(genWordBits - 1, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
val data_mismatch = io.mem.grant.fire() && state === s_get &&
|
|
||||||
wordFromBeat(full_addr, io.mem.grant.bits.data) =/= word_data
|
|
||||||
|
|
||||||
io.status.error.valid := data_mismatch
|
|
||||||
io.status.error.bits := UInt(id)
|
|
||||||
|
|
||||||
assert(!data_mismatch,
|
|
||||||
s"Get received incorrect data in uncached generator ${id}")
|
|
||||||
|
|
||||||
def beatOffset(addr: UInt) = // TODO zero-width
|
|
||||||
if (tlByteAddrBits > wordOffset) addr(tlByteAddrBits - 1, wordOffset)
|
|
||||||
else UInt(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
class HellaCacheGenerator(id: Int)
|
|
||||||
(implicit p: Parameters) extends L1HellaCacheModule()(p) with HasGeneratorParameters {
|
|
||||||
val io = new Bundle {
|
|
||||||
val mem = new HellaCacheIO
|
|
||||||
val status = new GroundTestStatus
|
|
||||||
}
|
|
||||||
|
|
||||||
val timeout = SimpleTimer(genTimeout, io.mem.req.fire(), io.mem.resp.valid)
|
|
||||||
assert(!timeout, s"Cached generator ${id} timed out waiting for response")
|
|
||||||
io.status.timeout.valid := timeout
|
|
||||||
io.status.timeout.bits := UInt(id)
|
|
||||||
|
|
||||||
val (s_start :: s_write :: s_read :: s_finished :: Nil) = Enum(Bits(), 4)
|
|
||||||
val state = Reg(init = s_start)
|
|
||||||
val sending = Reg(init = Bool(false))
|
|
||||||
|
|
||||||
val (req_cnt, req_wrap) = Counter(io.mem.resp.valid, maxRequests)
|
|
||||||
|
|
||||||
val part_of_req_addr =
|
|
||||||
if (log2Ceil(nGens) > 0) {
|
|
||||||
Cat(UInt(id, log2Ceil(nGens)),
|
|
||||||
UInt(0, wordOffset))
|
|
||||||
} else {
|
|
||||||
UInt(0, wordOffset)
|
|
||||||
}
|
|
||||||
val req_addr = UInt(startAddress) + Cat(req_cnt, part_of_req_addr)
|
|
||||||
val req_data = Cat(UInt(id, log2Up(nGens)), req_cnt, part_of_req_addr)
|
|
||||||
|
|
||||||
io.mem.req.valid := sending && !io.status.finished
|
|
||||||
io.mem.req.bits.addr := req_addr
|
|
||||||
io.mem.req.bits.data := req_data
|
|
||||||
io.mem.req.bits.typ := wordSize
|
|
||||||
io.mem.req.bits.cmd := Mux(state === s_write, M_XWR, M_XRD)
|
|
||||||
io.mem.req.bits.tag := UInt(0)
|
|
||||||
|
|
||||||
when (state === s_start) { sending := Bool(true); state := s_write }
|
|
||||||
|
|
||||||
when (io.mem.req.fire()) { sending := Bool(false) }
|
|
||||||
when (io.mem.resp.valid) { sending := Bool(true) }
|
|
||||||
|
|
||||||
when (req_wrap) { state := Mux(state === s_write, s_read, s_finished) }
|
|
||||||
|
|
||||||
io.status.finished := (state === s_finished)
|
|
||||||
|
|
||||||
def data_match(recv: Bits, expected: Bits): Bool = {
|
|
||||||
val recv_resized = Wire(Bits(width = genWordBits))
|
|
||||||
val exp_resized = Wire(Bits(width = genWordBits))
|
|
||||||
|
|
||||||
recv_resized := recv
|
|
||||||
exp_resized := expected
|
|
||||||
recv_resized === exp_resized
|
|
||||||
}
|
|
||||||
|
|
||||||
val data_mismatch = io.mem.resp.valid && io.mem.resp.bits.has_data &&
|
|
||||||
!data_match(io.mem.resp.bits.data, req_data)
|
|
||||||
|
|
||||||
io.status.error.valid := data_mismatch
|
|
||||||
io.status.error.bits := UInt(id)
|
|
||||||
|
|
||||||
assert(!data_mismatch,
|
|
||||||
s"Received incorrect data in cached generator ${id}")
|
|
||||||
}
|
|
||||||
|
|
||||||
class GeneratorTest(implicit p: Parameters)
|
|
||||||
extends GroundTest()(p) with HasGeneratorParameters {
|
|
||||||
|
|
||||||
val idStart = p(GroundTestKey).take(p(TileId))
|
|
||||||
.map(settings => settings.cached + settings.uncached)
|
|
||||||
.foldLeft(0)(_ + _)
|
|
||||||
|
|
||||||
val cached = List.tabulate(nCached) { i =>
|
|
||||||
val realId = idStart + i
|
|
||||||
Module(new HellaCacheGenerator(realId))
|
|
||||||
}
|
|
||||||
|
|
||||||
val uncached = List.tabulate(nUncached) { i =>
|
|
||||||
val realId = idStart + nCached + i
|
|
||||||
Module(new UncachedTileLinkGenerator(realId))
|
|
||||||
}
|
|
||||||
|
|
||||||
io.cache <> cached.map(_.io.mem)
|
|
||||||
io.mem <> uncached.map(_.io.mem)
|
|
||||||
|
|
||||||
val gen_debug = cached.map(_.io.status) ++ uncached.map(_.io.status)
|
|
||||||
io.status := DebugCombiner(gen_debug)
|
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ class NastiGenerator(id: Int)(implicit val p: Parameters) extends Module
|
|||||||
with HasNastiParameters
|
with HasNastiParameters
|
||||||
with HasMIFParameters
|
with HasMIFParameters
|
||||||
with HasAddrMapParameters
|
with HasAddrMapParameters
|
||||||
with HasGeneratorParameters {
|
with HasTrafficGeneratorParameters {
|
||||||
|
|
||||||
val io = new Bundle {
|
val io = new Bundle {
|
||||||
val status = new GroundTestStatus
|
val status = new GroundTestStatus
|
||||||
|
213
src/main/scala/groundtest/TrafficGenerator.scala
Normal file
213
src/main/scala/groundtest/TrafficGenerator.scala
Normal file
@ -0,0 +1,213 @@
|
|||||||
|
package groundtest
|
||||||
|
|
||||||
|
import Chisel._
|
||||||
|
import uncore.tilelink._
|
||||||
|
import uncore.devices.NTiles
|
||||||
|
import uncore.constants._
|
||||||
|
import junctions._
|
||||||
|
import rocket._
|
||||||
|
import util.SimpleTimer
|
||||||
|
import scala.util.Random
|
||||||
|
import cde.{Parameters, Field}
|
||||||
|
|
||||||
|
case class TrafficGeneratorParameters(
|
||||||
|
maxRequests: Int,
|
||||||
|
startAddress: BigInt)
|
||||||
|
case object GeneratorKey extends Field[TrafficGeneratorParameters]
|
||||||
|
|
||||||
|
trait HasTrafficGeneratorParameters extends HasGroundTestParameters {
|
||||||
|
implicit val p: Parameters
|
||||||
|
|
||||||
|
val genParams = p(GeneratorKey)
|
||||||
|
val nGens = p(GroundTestKey).map(
|
||||||
|
cs => cs.uncached + cs.cached).reduce(_ + _)
|
||||||
|
val genTimeout = 8192
|
||||||
|
val maxRequests = genParams.maxRequests
|
||||||
|
val startAddress = genParams.startAddress
|
||||||
|
|
||||||
|
val genWordBits = 32
|
||||||
|
val genWordBytes = genWordBits / 8
|
||||||
|
val wordOffset = log2Ceil(genWordBytes)
|
||||||
|
val wordSize = UInt(log2Ceil(genWordBytes))
|
||||||
|
|
||||||
|
require(startAddress % BigInt(genWordBytes) == 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
class UncachedTileLinkGenerator(id: Int)
|
||||||
|
(implicit p: Parameters) extends TLModule()(p) with HasTrafficGeneratorParameters {
|
||||||
|
|
||||||
|
private val tlBlockOffset = tlBeatAddrBits + tlByteAddrBits
|
||||||
|
|
||||||
|
val io = new Bundle {
|
||||||
|
val mem = new ClientUncachedTileLinkIO
|
||||||
|
val status = new GroundTestStatus
|
||||||
|
}
|
||||||
|
|
||||||
|
val (s_start :: s_put :: s_get :: s_finished :: Nil) = Enum(Bits(), 4)
|
||||||
|
val state = Reg(init = s_start)
|
||||||
|
|
||||||
|
val (req_cnt, req_wrap) = Counter(io.mem.grant.fire(), maxRequests)
|
||||||
|
|
||||||
|
val sending = Reg(init = Bool(false))
|
||||||
|
|
||||||
|
when (state === s_start) {
|
||||||
|
sending := Bool(true)
|
||||||
|
state := s_put
|
||||||
|
}
|
||||||
|
|
||||||
|
when (io.mem.acquire.fire()) { sending := Bool(false) }
|
||||||
|
when (io.mem.grant.fire()) { sending := Bool(true) }
|
||||||
|
when (req_wrap) { state := Mux(state === s_put, s_get, s_finished) }
|
||||||
|
|
||||||
|
val timeout = SimpleTimer(genTimeout, io.mem.acquire.fire(), io.mem.grant.fire())
|
||||||
|
assert(!timeout, s"Uncached generator ${id} timed out waiting for grant")
|
||||||
|
|
||||||
|
io.status.finished := (state === s_finished)
|
||||||
|
io.status.timeout.valid := timeout
|
||||||
|
io.status.timeout.bits := UInt(id)
|
||||||
|
|
||||||
|
val part_of_full_addr =
|
||||||
|
if (log2Ceil(nGens) > 0) {
|
||||||
|
Cat(UInt(id, log2Ceil(nGens)),
|
||||||
|
UInt(0, wordOffset))
|
||||||
|
} else {
|
||||||
|
UInt(0, wordOffset)
|
||||||
|
}
|
||||||
|
val full_addr = UInt(startAddress) + Cat(req_cnt, part_of_full_addr)
|
||||||
|
|
||||||
|
val addr_block = full_addr >> UInt(tlBlockOffset)
|
||||||
|
val addr_beat = full_addr(tlBlockOffset - 1, tlByteAddrBits)
|
||||||
|
val addr_byte = full_addr(tlByteAddrBits - 1, 0)
|
||||||
|
|
||||||
|
val data_prefix = Cat(UInt(id, log2Up(nGens)), req_cnt)
|
||||||
|
val word_data = Wire(UInt(width = genWordBits))
|
||||||
|
word_data := Cat(data_prefix, part_of_full_addr)
|
||||||
|
val beat_data = Fill(tlDataBits / genWordBits, word_data)
|
||||||
|
val wshift = Cat(beatOffset(full_addr), UInt(0, wordOffset))
|
||||||
|
val wmask = Fill(genWordBits / 8, Bits(1, 1)) << wshift
|
||||||
|
|
||||||
|
val put_acquire = Put(
|
||||||
|
client_xact_id = UInt(0),
|
||||||
|
addr_block = addr_block,
|
||||||
|
addr_beat = addr_beat,
|
||||||
|
data = beat_data,
|
||||||
|
wmask = Some(wmask),
|
||||||
|
alloc = Bool(false))
|
||||||
|
|
||||||
|
val get_acquire = Get(
|
||||||
|
client_xact_id = UInt(0),
|
||||||
|
addr_block = addr_block,
|
||||||
|
addr_beat = addr_beat,
|
||||||
|
addr_byte = addr_byte,
|
||||||
|
operand_size = wordSize,
|
||||||
|
alloc = Bool(false))
|
||||||
|
|
||||||
|
io.mem.acquire.valid := sending && !io.status.finished
|
||||||
|
io.mem.acquire.bits := Mux(state === s_put, put_acquire, get_acquire)
|
||||||
|
io.mem.grant.ready := !sending && !io.status.finished
|
||||||
|
|
||||||
|
def wordFromBeat(addr: UInt, dat: UInt) = {
|
||||||
|
val shift = Cat(beatOffset(addr), UInt(0, wordOffset + 3))
|
||||||
|
(dat >> shift)(genWordBits - 1, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
val data_mismatch = io.mem.grant.fire() && state === s_get &&
|
||||||
|
wordFromBeat(full_addr, io.mem.grant.bits.data) =/= word_data
|
||||||
|
|
||||||
|
io.status.error.valid := data_mismatch
|
||||||
|
io.status.error.bits := UInt(id)
|
||||||
|
|
||||||
|
assert(!data_mismatch,
|
||||||
|
s"Get received incorrect data in uncached generator ${id}")
|
||||||
|
|
||||||
|
def beatOffset(addr: UInt) = // TODO zero-width
|
||||||
|
if (tlByteAddrBits > wordOffset) addr(tlByteAddrBits - 1, wordOffset)
|
||||||
|
else UInt(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
class HellaCacheGenerator(id: Int)
|
||||||
|
(implicit p: Parameters) extends L1HellaCacheModule()(p) with HasTrafficGeneratorParameters {
|
||||||
|
val io = new Bundle {
|
||||||
|
val mem = new HellaCacheIO
|
||||||
|
val status = new GroundTestStatus
|
||||||
|
}
|
||||||
|
|
||||||
|
val timeout = SimpleTimer(genTimeout, io.mem.req.fire(), io.mem.resp.valid)
|
||||||
|
assert(!timeout, s"Cached generator ${id} timed out waiting for response")
|
||||||
|
io.status.timeout.valid := timeout
|
||||||
|
io.status.timeout.bits := UInt(id)
|
||||||
|
|
||||||
|
val (s_start :: s_write :: s_read :: s_finished :: Nil) = Enum(Bits(), 4)
|
||||||
|
val state = Reg(init = s_start)
|
||||||
|
val sending = Reg(init = Bool(false))
|
||||||
|
|
||||||
|
val (req_cnt, req_wrap) = Counter(io.mem.resp.valid, maxRequests)
|
||||||
|
|
||||||
|
val part_of_req_addr =
|
||||||
|
if (log2Ceil(nGens) > 0) {
|
||||||
|
Cat(UInt(id, log2Ceil(nGens)),
|
||||||
|
UInt(0, wordOffset))
|
||||||
|
} else {
|
||||||
|
UInt(0, wordOffset)
|
||||||
|
}
|
||||||
|
val req_addr = UInt(startAddress) + Cat(req_cnt, part_of_req_addr)
|
||||||
|
val req_data = Cat(UInt(id, log2Up(nGens)), req_cnt, part_of_req_addr)
|
||||||
|
|
||||||
|
io.mem.req.valid := sending && !io.status.finished
|
||||||
|
io.mem.req.bits.addr := req_addr
|
||||||
|
io.mem.req.bits.data := req_data
|
||||||
|
io.mem.req.bits.typ := wordSize
|
||||||
|
io.mem.req.bits.cmd := Mux(state === s_write, M_XWR, M_XRD)
|
||||||
|
io.mem.req.bits.tag := UInt(0)
|
||||||
|
|
||||||
|
when (state === s_start) { sending := Bool(true); state := s_write }
|
||||||
|
|
||||||
|
when (io.mem.req.fire()) { sending := Bool(false) }
|
||||||
|
when (io.mem.resp.valid) { sending := Bool(true) }
|
||||||
|
|
||||||
|
when (req_wrap) { state := Mux(state === s_write, s_read, s_finished) }
|
||||||
|
|
||||||
|
io.status.finished := (state === s_finished)
|
||||||
|
|
||||||
|
def data_match(recv: Bits, expected: Bits): Bool = {
|
||||||
|
val recv_resized = Wire(Bits(width = genWordBits))
|
||||||
|
val exp_resized = Wire(Bits(width = genWordBits))
|
||||||
|
|
||||||
|
recv_resized := recv
|
||||||
|
exp_resized := expected
|
||||||
|
recv_resized === exp_resized
|
||||||
|
}
|
||||||
|
|
||||||
|
val data_mismatch = io.mem.resp.valid && io.mem.resp.bits.has_data &&
|
||||||
|
!data_match(io.mem.resp.bits.data, req_data)
|
||||||
|
|
||||||
|
io.status.error.valid := data_mismatch
|
||||||
|
io.status.error.bits := UInt(id)
|
||||||
|
|
||||||
|
assert(!data_mismatch,
|
||||||
|
s"Received incorrect data in cached generator ${id}")
|
||||||
|
}
|
||||||
|
|
||||||
|
class GeneratorTest(implicit p: Parameters)
|
||||||
|
extends GroundTest()(p) with HasTrafficGeneratorParameters {
|
||||||
|
|
||||||
|
val idStart = p(GroundTestKey).take(p(TileId))
|
||||||
|
.map(settings => settings.cached + settings.uncached)
|
||||||
|
.foldLeft(0)(_ + _)
|
||||||
|
|
||||||
|
val cached = List.tabulate(nCached) { i =>
|
||||||
|
val realId = idStart + i
|
||||||
|
Module(new HellaCacheGenerator(realId))
|
||||||
|
}
|
||||||
|
|
||||||
|
val uncached = List.tabulate(nUncached) { i =>
|
||||||
|
val realId = idStart + nCached + i
|
||||||
|
Module(new UncachedTileLinkGenerator(realId))
|
||||||
|
}
|
||||||
|
|
||||||
|
io.cache <> cached.map(_.io.mem)
|
||||||
|
io.mem <> uncached.map(_.io.mem)
|
||||||
|
|
||||||
|
val gen_debug = cached.map(_.io.status) ++ uncached.map(_.io.status)
|
||||||
|
io.status := DebugCombiner(gen_debug)
|
||||||
|
}
|
@ -8,7 +8,7 @@ import junctions._
|
|||||||
import uncore.tilelink._
|
import uncore.tilelink._
|
||||||
import uncore.tilelink2._
|
import uncore.tilelink2._
|
||||||
import uncore.devices._
|
import uncore.devices._
|
||||||
import util.ParameterizedBundle
|
import util.{ParameterizedBundle, ConfigStringOutput}
|
||||||
import rocket._
|
import rocket._
|
||||||
import rocket.Util._
|
import rocket.Util._
|
||||||
import coreplex._
|
import coreplex._
|
||||||
|
@ -2,122 +2,78 @@
|
|||||||
|
|
||||||
package rocketchip
|
package rocketchip
|
||||||
|
|
||||||
import Chisel._
|
import rocket.{XLen, UseVM, UseAtomics, UseCompressed, FPUKey}
|
||||||
import scala.collection.mutable.{LinkedHashSet,LinkedHashMap}
|
import scala.collection.mutable.LinkedHashSet
|
||||||
import cde._
|
|
||||||
import coreplex._
|
|
||||||
import java.io.{File, FileWriter}
|
|
||||||
|
|
||||||
/** Representation of the information this Generator needs to collect from external sources. */
|
/** A Generator for platforms containing Rocket Coreplexes */
|
||||||
case class ParsedInputNames(
|
object Generator extends util.GeneratorApp {
|
||||||
targetDir: String,
|
|
||||||
topModuleProject: String,
|
|
||||||
topModuleClass: String,
|
|
||||||
configProject: String,
|
|
||||||
configs: String) {
|
|
||||||
val configClasses: Seq[String] = configs.split('_')
|
|
||||||
val fullConfigClasses: Seq[String] = configClasses.map(configProject + "." + _)
|
|
||||||
val fullTopModuleClass: String = topModuleProject + "." + topModuleClass
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Common utilities we supply to all Generators. In particular, supplies the
|
val rv64RegrTestNames = LinkedHashSet(
|
||||||
* canonical ways of building various JVM elaboration-time structures.
|
"rv64ud-v-fcvt",
|
||||||
*/
|
"rv64ud-p-fdiv",
|
||||||
trait HasGeneratorUtilities {
|
"rv64ud-v-fadd",
|
||||||
def getConfig(names: ParsedInputNames): Config = {
|
"rv64uf-v-fadd",
|
||||||
names.fullConfigClasses.foldRight(new Config()) { case (currentName, config) =>
|
"rv64um-v-mul",
|
||||||
val currentConfig = try {
|
"rv64mi-p-breakpoint",
|
||||||
Class.forName(currentName).newInstance.asInstanceOf[Config]
|
"rv64uc-v-rvc",
|
||||||
} catch {
|
"rv64ud-v-structural",
|
||||||
case e: java.lang.ClassNotFoundException =>
|
"rv64si-p-wfi",
|
||||||
throwException(s"""Unable to find part "$currentName" from "${names.configs}", did you misspell it?""", e)
|
"rv64um-v-divw",
|
||||||
}
|
"rv64ua-v-lrsc",
|
||||||
currentConfig ++ config
|
"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 {
|
||||||
|
import DefaultTestSuites._
|
||||||
|
val xlen = params(XLen)
|
||||||
|
val vm = params(UseVM)
|
||||||
|
val env = if (vm) List("p","v") else List("p")
|
||||||
|
params(FPUKey) foreach { case cfg =>
|
||||||
|
if (xlen == 32) {
|
||||||
|
TestGeneration.addSuites(env.map(rv32ufNoDiv))
|
||||||
|
} else {
|
||||||
|
TestGeneration.addSuite(rv32udBenchmarks)
|
||||||
|
TestGeneration.addSuites(env.map(rv64ufNoDiv))
|
||||||
|
TestGeneration.addSuites(env.map(rv64udNoDiv))
|
||||||
|
if (cfg.divSqrt) {
|
||||||
|
TestGeneration.addSuites(env.map(rv64uf))
|
||||||
|
TestGeneration.addSuites(env.map(rv64ud))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (params(UseAtomics)) TestGeneration.addSuites(env.map(if (xlen == 64) rv64ua else rv32ua))
|
||||||
|
if (params(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)
|
||||||
|
|
||||||
def getParameters(names: ParsedInputNames): Parameters = getParameters(getConfig(names))
|
TestGeneration.addSuites(rvi.map(_("p")))
|
||||||
|
TestGeneration.addSuites((if (vm) List("v") else List()).flatMap(env => rvu.map(_(env))))
|
||||||
def getParameters(config: Config): Parameters = Parameters.root(config.toInstance)
|
TestGeneration.addSuite(benchmarks)
|
||||||
|
TestGeneration.addSuite(new RegressionTestSuite(if (xlen == 64) rv64RegrTestNames else rv32RegrTestNames))
|
||||||
import chisel3.internal.firrtl.Circuit
|
|
||||||
def elaborate(names: ParsedInputNames, params: Parameters): Circuit = {
|
|
||||||
val gen = () =>
|
|
||||||
Class.forName(names.fullTopModuleClass)
|
|
||||||
.getConstructor(classOf[cde.Parameters])
|
|
||||||
.newInstance(params)
|
|
||||||
.asInstanceOf[Module]
|
|
||||||
|
|
||||||
Driver.elaborate(gen)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def writeOutputFile(targetDir: String, fname: String, contents: String): File = {
|
|
||||||
val f = new File(targetDir, fname)
|
|
||||||
val fw = new FileWriter(f)
|
|
||||||
fw.write(contents)
|
|
||||||
fw.close
|
|
||||||
f
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Standardized command line interface for Scala entry point */
|
|
||||||
trait Generator extends App with HasGeneratorUtilities {
|
|
||||||
lazy val names: ParsedInputNames = {
|
|
||||||
require(args.size == 5, "Usage: sbt> " +
|
|
||||||
"run TargetDir TopModuleProjectName TopModuleName ConfigProjectName ConfigNameString")
|
|
||||||
ParsedInputNames(
|
|
||||||
targetDir = args(0),
|
|
||||||
topModuleProject = args(1),
|
|
||||||
topModuleClass = args(2),
|
|
||||||
configProject = args(3),
|
|
||||||
configs = args(4))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Canonical ways of building various JVM elaboration-time structures
|
|
||||||
lazy val td = names.targetDir
|
|
||||||
lazy val config = getConfig(names)
|
|
||||||
lazy val world = config.toInstance
|
|
||||||
lazy val params = Parameters.root(world)
|
|
||||||
lazy val circuit = elaborate(names, params)
|
|
||||||
|
|
||||||
val longName: String // Exhaustive name used to interface with external build tool targets
|
|
||||||
|
|
||||||
/** Output FIRRTL, which an external compiler can turn into Verilog. */
|
|
||||||
def generateFirrtl {
|
|
||||||
Driver.dumpFirrtl(circuit, Some(new File(td, s"$longName.fir"))) // FIRRTL
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Output software test Makefrags, which provide targets for integration testing. */
|
|
||||||
def generateTestSuiteMakefrags {
|
|
||||||
TestGeneration.addSuite(new RegressionTestSuite(params(RegressionTestNames)))
|
|
||||||
writeOutputFile(td, s"$longName.d", TestGeneration.generateMakefrag) // Coreplex-specific test suites
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Output Design Space Exploration knobs and constraints. */
|
|
||||||
def generateDSEConstraints {
|
|
||||||
writeOutputFile(td, s"${names.configs}.knb", world.getKnobs) // Knobs for DSE
|
|
||||||
writeOutputFile(td, s"${names.configs}.cst", world.getConstraints) // Constraints for DSE
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Output a global Parameter dump, which an external script can turn into Verilog headers. */
|
|
||||||
def generateParameterDump {
|
|
||||||
writeOutputFile(td, s"$longName.prm", ParameterDump.getDump) // Parameters flagged with Dump()
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Output a global ConfigString, for use by the RISC-V software ecosystem. */
|
|
||||||
def generateConfigString {
|
|
||||||
ConfigStringOutput.contents.foreach(c => writeOutputFile(td, s"${names.configs}.cfg", c)) // String for software
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
object ConfigStringOutput {
|
|
||||||
var contents: Option[String] = None
|
|
||||||
}
|
|
||||||
|
|
||||||
/** An example Generator */
|
|
||||||
object RocketChipGenerator extends Generator
|
|
||||||
{
|
|
||||||
val longName = names.topModuleProject + "." + names.configs
|
val longName = names.topModuleProject + "." + names.configs
|
||||||
generateFirrtl
|
generateFirrtl
|
||||||
generateTestSuiteMakefrags
|
generateTestSuiteMakefrags
|
||||||
|
@ -1,12 +1,9 @@
|
|||||||
// See LICENSE for license details.
|
// See LICENSE for license details.
|
||||||
|
|
||||||
package coreplex
|
package rocketchip
|
||||||
|
|
||||||
import Chisel._
|
import Chisel._
|
||||||
import scala.collection.mutable.{LinkedHashSet,LinkedHashMap}
|
import scala.collection.mutable.{LinkedHashSet, LinkedHashMap}
|
||||||
import cde.{Parameters, ParameterDump, Config, Field, CDEMatchError}
|
|
||||||
|
|
||||||
case object RegressionTestNames extends Field[LinkedHashSet[String]]
|
|
||||||
|
|
||||||
abstract class RocketTestSuite {
|
abstract class RocketTestSuite {
|
||||||
val dir: String
|
val dir: String
|
||||||
@ -175,6 +172,8 @@ object DefaultTestSuites {
|
|||||||
val emptyBmarks = new BenchmarkTestSuite("empty",
|
val emptyBmarks = new BenchmarkTestSuite("empty",
|
||||||
"$(RISCV)/riscv64-unknown-elf/share/riscv-tests/benchmarks", LinkedHashSet.empty)
|
"$(RISCV)/riscv64-unknown-elf/share/riscv-tests/benchmarks", LinkedHashSet.empty)
|
||||||
|
|
||||||
|
val singleRegression = new RegressionTestSuite(LinkedHashSet("rv64ui-p-simple"))
|
||||||
|
|
||||||
val mtBmarks = new BenchmarkTestSuite("mt", "$(RISCV)/riscv64-unknown-elf/share/riscv-tests/mt",
|
val mtBmarks = new BenchmarkTestSuite("mt", "$(RISCV)/riscv64-unknown-elf/share/riscv-tests/mt",
|
||||||
LinkedHashSet(((0 to 4).map("vvadd"+_) ++
|
LinkedHashSet(((0 to 4).map("vvadd"+_) ++
|
||||||
List("ad","ae","af","ag","ai","ak","al","am","an","ap","aq","ar","at","av","ay","az",
|
List("ad","ae","af","ag","ai","ak","al","am","an","ap","aq","ar","at","av","ay","az",
|
@ -2,30 +2,33 @@
|
|||||||
|
|
||||||
package unittest
|
package unittest
|
||||||
|
|
||||||
import scala.collection.mutable.LinkedHashSet
|
|
||||||
|
|
||||||
import Chisel._
|
import Chisel._
|
||||||
import cde.{Parameters, Config, CDEMatchError}
|
import cde.{Parameters, Config, CDEMatchError}
|
||||||
import coreplex._
|
import rocketchip.{BaseConfig, BasePlatformConfig}
|
||||||
import rocketchip._
|
|
||||||
|
|
||||||
class WithUnitTests extends Config(
|
class WithJunctionsUnitTests extends Config(
|
||||||
(pname, site, here) => pname match {
|
(pname, site, here) => pname match {
|
||||||
case uncore.tilelink.TLId => "L1toL2"
|
case junctions.PAddrBits => 32
|
||||||
case NCoreplexExtClients => 0
|
case rocket.XLen => 64
|
||||||
case RegressionTestNames => LinkedHashSet("rv64ui-p-simple")
|
case UnitTests => (p: Parameters) => Seq(
|
||||||
case UnitTests => (p: Parameters) => {
|
|
||||||
TestGeneration.addSuite(DefaultTestSuites.groundtest64("p")) // TODO why
|
|
||||||
TestGeneration.addSuite(DefaultTestSuites.emptyBmarks)
|
|
||||||
Seq(
|
|
||||||
Module(new junctions.MultiWidthFifoTest),
|
Module(new junctions.MultiWidthFifoTest),
|
||||||
Module(new junctions.NastiMemoryDemuxTest()(p)),
|
Module(new junctions.NastiMemoryDemuxTest()(p)),
|
||||||
Module(new junctions.HastiTest()(p)),
|
Module(new junctions.HastiTest()(p)))
|
||||||
Module(new uncore.devices.ROMSlaveTest()(p)),
|
|
||||||
Module(new uncore.devices.TileLinkRAMTest()(p)),
|
|
||||||
Module(new uncore.tilelink2.TLFuzzRAMTest))
|
|
||||||
}
|
|
||||||
case _ => throw new CDEMatchError
|
case _ => throw new CDEMatchError
|
||||||
})
|
})
|
||||||
|
|
||||||
class UnitTestConfig extends Config(new WithUnitTests ++ new BaseConfig)
|
class JunctionsUnitTestConfig extends Config(new WithJunctionsUnitTests ++ new BasePlatformConfig)
|
||||||
|
|
||||||
|
class WithUncoreUnitTests extends Config(
|
||||||
|
(pname, site, here) => pname match {
|
||||||
|
case rocketchip.NCoreplexExtClients => 0
|
||||||
|
case uncore.tilelink.TLId => "L1toL2"
|
||||||
|
case UnitTests => (p: Parameters) => Seq(
|
||||||
|
Module(new uncore.devices.ROMSlaveTest()(p)),
|
||||||
|
Module(new uncore.devices.TileLinkRAMTest()(p)),
|
||||||
|
Module(new uncore.tilelink2.TLFuzzRAMTest))
|
||||||
|
case _ => throw new CDEMatchError
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
class UncoreUnitTestConfig extends Config(new WithUncoreUnitTests ++ new BaseConfig)
|
||||||
|
10
src/main/scala/unittest/Generator.scala
Normal file
10
src/main/scala/unittest/Generator.scala
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
// See LICENSE for license details.
|
||||||
|
|
||||||
|
package unittest
|
||||||
|
|
||||||
|
object Generator extends util.GeneratorApp {
|
||||||
|
val longName = names.topModuleProject + "." + names.configs
|
||||||
|
generateFirrtl
|
||||||
|
generateTestSuiteMakefrags // TODO: Needed only for legacy make targets
|
||||||
|
generateParameterDump // TODO: Needed only for legacy make targets
|
||||||
|
}
|
125
src/main/scala/util/GeneratorUtils.scala
Normal file
125
src/main/scala/util/GeneratorUtils.scala
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
// See LICENSE for license details.
|
||||||
|
|
||||||
|
package util
|
||||||
|
|
||||||
|
import Chisel._
|
||||||
|
import cde._
|
||||||
|
import java.io.{File, FileWriter}
|
||||||
|
|
||||||
|
/** Representation of the information this Generator needs to collect from external sources. */
|
||||||
|
case class ParsedInputNames(
|
||||||
|
targetDir: String,
|
||||||
|
topModuleProject: String,
|
||||||
|
topModuleClass: String,
|
||||||
|
configProject: String,
|
||||||
|
configs: String) {
|
||||||
|
val configClasses: Seq[String] = configs.split('_')
|
||||||
|
val fullConfigClasses: Seq[String] = configClasses.map(configProject + "." + _)
|
||||||
|
val fullTopModuleClass: String = topModuleProject + "." + topModuleClass
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Common utilities we supply to all Generators. In particular, supplies the
|
||||||
|
* canonical ways of building various JVM elaboration-time structures.
|
||||||
|
*/
|
||||||
|
trait HasGeneratorUtilities {
|
||||||
|
def getConfig(names: ParsedInputNames): Config = {
|
||||||
|
names.fullConfigClasses.foldRight(new Config()) { case (currentName, config) =>
|
||||||
|
val currentConfig = try {
|
||||||
|
Class.forName(currentName).newInstance.asInstanceOf[Config]
|
||||||
|
} catch {
|
||||||
|
case e: java.lang.ClassNotFoundException =>
|
||||||
|
throwException(s"""Unable to find part "$currentName" from "${names.configs}", did you misspell it?""", e)
|
||||||
|
}
|
||||||
|
currentConfig ++ config
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def getParameters(names: ParsedInputNames): Parameters = getParameters(getConfig(names))
|
||||||
|
|
||||||
|
def getParameters(config: Config): Parameters = Parameters.root(config.toInstance)
|
||||||
|
|
||||||
|
import chisel3.internal.firrtl.Circuit
|
||||||
|
def elaborate(names: ParsedInputNames, params: Parameters): Circuit = {
|
||||||
|
val gen = () =>
|
||||||
|
Class.forName(names.fullTopModuleClass)
|
||||||
|
.getConstructor(classOf[cde.Parameters])
|
||||||
|
.newInstance(params)
|
||||||
|
.asInstanceOf[Module]
|
||||||
|
|
||||||
|
Driver.elaborate(gen)
|
||||||
|
}
|
||||||
|
|
||||||
|
def writeOutputFile(targetDir: String, fname: String, contents: String): File = {
|
||||||
|
val f = new File(targetDir, fname)
|
||||||
|
val fw = new FileWriter(f)
|
||||||
|
fw.write(contents)
|
||||||
|
fw.close
|
||||||
|
f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Standardized command line interface for Scala entry point */
|
||||||
|
trait GeneratorApp extends App with HasGeneratorUtilities {
|
||||||
|
lazy val names: ParsedInputNames = {
|
||||||
|
require(args.size == 5, "Usage: sbt> " +
|
||||||
|
"run TargetDir TopModuleProjectName TopModuleName " +
|
||||||
|
"ConfigProjectName ConfigNameString")
|
||||||
|
ParsedInputNames(
|
||||||
|
targetDir = args(0),
|
||||||
|
topModuleProject = args(1),
|
||||||
|
topModuleClass = args(2),
|
||||||
|
configProject = args(3),
|
||||||
|
configs = args(4))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Canonical ways of building various JVM elaboration-time structures
|
||||||
|
lazy val td = names.targetDir
|
||||||
|
lazy val config = getConfig(names)
|
||||||
|
lazy val world = config.toInstance
|
||||||
|
lazy val params = Parameters.root(world)
|
||||||
|
lazy val circuit = elaborate(names, params)
|
||||||
|
|
||||||
|
val longName: String // Exhaustive name used to interface with external build tool targets
|
||||||
|
|
||||||
|
/** Output FIRRTL, which an external compiler can turn into Verilog. */
|
||||||
|
def generateFirrtl {
|
||||||
|
Driver.dumpFirrtl(circuit, Some(new File(td, s"$longName.fir"))) // FIRRTL
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Output software test Makefrags, which provide targets for integration testing. */
|
||||||
|
def generateTestSuiteMakefrags {
|
||||||
|
addTestSuites
|
||||||
|
writeOutputFile(td, s"$longName.d", rocketchip.TestGeneration.generateMakefrag) // Coreplex-specific test suites
|
||||||
|
}
|
||||||
|
|
||||||
|
def addTestSuites {
|
||||||
|
// TODO: better job of Makefrag generation
|
||||||
|
// for non-RocketChip testing platforms
|
||||||
|
import rocketchip.{DefaultTestSuites, TestGeneration}
|
||||||
|
TestGeneration.addSuite(DefaultTestSuites.groundtest64("p"))
|
||||||
|
TestGeneration.addSuite(DefaultTestSuites.emptyBmarks)
|
||||||
|
TestGeneration.addSuite(DefaultTestSuites.singleRegression)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Output Design Space Exploration knobs and constraints. */
|
||||||
|
def generateDSEConstraints {
|
||||||
|
writeOutputFile(td, s"${names.configs}.knb", world.getKnobs) // Knobs for DSE
|
||||||
|
writeOutputFile(td, s"${names.configs}.cst", world.getConstraints) // Constraints for DSE
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Output a global Parameter dump, which an external script can turn into Verilog headers. */
|
||||||
|
def generateParameterDump {
|
||||||
|
writeOutputFile(td, s"$longName.prm", ParameterDump.getDump) // Parameters flagged with Dump()
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Output a global ConfigString, for use by the RISC-V software ecosystem. */
|
||||||
|
def generateConfigString {
|
||||||
|
ConfigStringOutput.contents.foreach(c => writeOutputFile(td, s"${names.configs}.cfg", c))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object ConfigStringOutput {
|
||||||
|
var contents: Option[String] = None
|
||||||
|
}
|
||||||
|
|
@ -10,7 +10,7 @@ verilog = $(generated_dir)/$(long_name).v
|
|||||||
|
|
||||||
$(generated_dir)/%.fir $(generated_dir)/%.prm $(generated_dir)/%.d: $(chisel_srcs) $(bootrom_img)
|
$(generated_dir)/%.fir $(generated_dir)/%.prm $(generated_dir)/%.d: $(chisel_srcs) $(bootrom_img)
|
||||||
mkdir -p $(dir $@)
|
mkdir -p $(dir $@)
|
||||||
cd $(base_dir) && $(SBT) "run $(generated_dir) $(PROJECT) $(MODEL) $(CFG_PROJECT) $(CONFIG)"
|
cd $(base_dir) && $(SBT) "run-main $(PROJECT).Generator $(generated_dir) $(PROJECT) $(MODEL) $(CFG_PROJECT) $(CONFIG)"
|
||||||
|
|
||||||
$(generated_dir)/$(long_name).v $(generated_dir)/$(long_name).conf : $(firrtl) $(FIRRTL_JAR)
|
$(generated_dir)/$(long_name).v $(generated_dir)/$(long_name).conf : $(firrtl) $(FIRRTL_JAR)
|
||||||
mkdir -p $(dir $@)
|
mkdir -p $(dir $@)
|
||||||
|
Loading…
Reference in New Issue
Block a user