Merge branch 'main' of https://github.com/ucb-bar/chipyard into ucb-bar-main
This commit is contained in:
Submodule generators/bar-fetchers updated: 45380026ff...bd02692fe6
11
generators/chipyard/src/main/resources/vsrc/Analog.v
Normal file
11
generators/chipyard/src/main/resources/vsrc/Analog.v
Normal file
@@ -0,0 +1,11 @@
|
||||
// See LICENSE for license details
|
||||
|
||||
`timescale 1ns/1ps
|
||||
|
||||
module AnalogConst #(CONST, WIDTH) (
|
||||
output [WIDTH-1:0] io
|
||||
);
|
||||
|
||||
assign io = CONST;
|
||||
|
||||
endmodule
|
||||
@@ -10,7 +10,7 @@ import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp, LazyRawModuleI
|
||||
import freechips.rocketchip.util.{DontTouch}
|
||||
import chipyard.iobinders._
|
||||
|
||||
import barstools.iocell.chisel._
|
||||
import chipyard.iocell._
|
||||
|
||||
case object BuildSystem extends Field[Parameters => LazyModule]((p: Parameters) => new DigitalTop()(p))
|
||||
|
||||
|
||||
@@ -80,9 +80,10 @@ trait CanHaveMasterTLMemPort { this: BaseSubsystem =>
|
||||
}
|
||||
}).toList.flatten)
|
||||
|
||||
// disable inwards monitors from node since the class with this trait (i.e. DigitalTop)
|
||||
// doesn't provide an implicit clock to those monitors
|
||||
mbus.coupleTo(s"memory_controller_port_named_$portName") {
|
||||
(memTLNode
|
||||
:*= TLBuffer()
|
||||
(DisableMonitors { implicit p => memTLNode :*= TLBuffer() }
|
||||
:*= TLSourceShrinker(1 << idBits)
|
||||
:*= TLWidthWidget(mbus.beatBytes)
|
||||
:*= _)
|
||||
|
||||
@@ -7,7 +7,7 @@ import freechips.rocketchip.prci._
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.subsystem._
|
||||
import freechips.rocketchip.tilelink._
|
||||
import barstools.iocell.chisel._
|
||||
import chipyard.iocell._
|
||||
|
||||
// This uses the FakePLL, which uses a ClockAtFreq Verilog blackbox to generate
|
||||
// the requested clocks. This also adds TileLink ClockDivider and ClockSelector
|
||||
|
||||
@@ -12,36 +12,6 @@ class LargeBoomAndRocketConfig extends Config(
|
||||
new chipyard.config.WithSystemBusWidth(128) ++
|
||||
new chipyard.config.AbstractConfig)
|
||||
|
||||
// DOC include start: BoomAndRocketWithHwacha
|
||||
class HwachaLargeBoomAndHwachaRocketConfig extends Config(
|
||||
new chipyard.config.WithHwachaTest ++
|
||||
new hwacha.DefaultHwachaConfig ++ // add hwacha to all harts
|
||||
new boom.v3.common.WithNLargeBooms(1) ++ // add 1 boom core
|
||||
new freechips.rocketchip.subsystem.WithNBigCores(1) ++ // add 1 rocket core
|
||||
new chipyard.config.WithSystemBusWidth(128) ++
|
||||
new chipyard.config.AbstractConfig)
|
||||
// DOC include end: BoomAndRocketWithHwacha
|
||||
|
||||
class LargeBoomAndHwachaRocketConfig extends Config(
|
||||
new chipyard.config.WithMultiRoCC ++ // support heterogeneous rocc
|
||||
new chipyard.config.WithMultiRoCCHwacha(0) ++ // put hwacha on hart-0 (rocket)
|
||||
new hwacha.DefaultHwachaConfig ++ // set default hwacha config keys
|
||||
new boom.v3.common.WithNLargeBooms(1) ++ // add 1 boom core
|
||||
new freechips.rocketchip.subsystem.WithNBigCores(1) ++ // add 1 rocket core
|
||||
new chipyard.config.WithSystemBusWidth(128) ++
|
||||
new chipyard.config.AbstractConfig)
|
||||
|
||||
// DOC include start: DualBoomAndRocketOneHwacha
|
||||
class DualLargeBoomAndHwachaRocketConfig extends Config(
|
||||
new chipyard.config.WithMultiRoCC ++ // support heterogeneous rocc
|
||||
new chipyard.config.WithMultiRoCCHwacha(0) ++ // put hwacha on hart-0 (rocket)
|
||||
new hwacha.DefaultHwachaConfig ++ // set default hwacha config keys
|
||||
new boom.v3.common.WithNLargeBooms(2) ++ // add 2 boom cores
|
||||
new freechips.rocketchip.subsystem.WithNBigCores(1) ++ // add 1 rocket core
|
||||
new chipyard.config.WithSystemBusWidth(128) ++
|
||||
new chipyard.config.AbstractConfig)
|
||||
// DOC include end: DualBoomAndRocketOneHwacha
|
||||
|
||||
class DualLargeBoomAndDualRocketConfig extends Config(
|
||||
new boom.v3.common.WithNLargeBooms(2) ++ // add 2 boom cores
|
||||
new freechips.rocketchip.subsystem.WithNBigCores(2) ++ // add 2 rocket cores
|
||||
|
||||
@@ -17,3 +17,9 @@ class NoCoresConfig extends Config(
|
||||
new chipyard.config.WithNoDebug ++
|
||||
new chipyard.config.WithNoPLIC ++
|
||||
new chipyard.config.AbstractConfig)
|
||||
|
||||
// A config that uses a empty chiptop module with no rocket-chip soc components
|
||||
class EmptyChipTopConfig extends Config(
|
||||
new chipyard.example.WithEmptyChipTop ++
|
||||
new chipyard.config.AbstractConfig // since we aren't using rocket-chip, this doesn't do anything
|
||||
)
|
||||
|
||||
@@ -33,13 +33,6 @@ class LeanGemminiPrintfRocketConfig extends Config(
|
||||
new chipyard.config.WithSystemBusWidth(128) ++
|
||||
new chipyard.config.AbstractConfig)
|
||||
|
||||
class HwachaRocketConfig extends Config(
|
||||
new chipyard.config.WithHwachaTest ++
|
||||
new hwacha.DefaultHwachaConfig ++ // use Hwacha vector accelerator
|
||||
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
|
||||
new chipyard.config.WithSystemBusWidth(128) ++
|
||||
new chipyard.config.AbstractConfig)
|
||||
|
||||
class MempressRocketConfig extends Config(
|
||||
new mempress.WithMemPress ++ // use Mempress (memory traffic generation) accelerator
|
||||
new chipyard.config.WithExtMemIdBits(7) ++ // use 7 bits for tl like request id
|
||||
@@ -50,13 +43,6 @@ class MempressRocketConfig extends Config(
|
||||
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
|
||||
new chipyard.config.AbstractConfig)
|
||||
|
||||
class HwachaLargeBoomV3Config extends Config(
|
||||
new chipyard.config.WithHwachaTest ++
|
||||
new hwacha.DefaultHwachaConfig ++ // use Hwacha vector accelerator
|
||||
new boom.v3.common.WithNLargeBooms(1) ++
|
||||
new chipyard.config.WithSystemBusWidth(128) ++
|
||||
new chipyard.config.AbstractConfig)
|
||||
|
||||
class AES256ECBRocketConfig extends Config(
|
||||
new aes.WithAES256ECBAccel ++ // use Caliptra AES 256 ECB accelerator
|
||||
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
package chipyard
|
||||
|
||||
import org.chipsalliance.cde.config.{Config}
|
||||
import freechips.rocketchip.diplomacy.{AsynchronousCrossing}
|
||||
|
||||
// --------------
|
||||
// Rocket+SHA3 Configs
|
||||
// These live in a separate file to simplify patching out for the tutorials.
|
||||
// --------------
|
||||
|
||||
// DOC include start: Sha3Rocket
|
||||
class Sha3RocketConfig extends Config(
|
||||
new sha3.WithSha3Accel ++ // add SHA3 rocc accelerator
|
||||
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
|
||||
new chipyard.config.AbstractConfig)
|
||||
// DOC include end: Sha3Rocket
|
||||
|
||||
class Sha3RocketPrintfConfig extends Config(
|
||||
new sha3.WithSha3Printf ++
|
||||
new sha3.WithSha3Accel ++ // add SHA3 rocc accelerator
|
||||
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
|
||||
new chipyard.config.AbstractConfig)
|
||||
@@ -12,10 +12,6 @@ import scala.collection.immutable.ListMap
|
||||
// For each of 4 phases, participants will customize and build a
|
||||
// small demonstration config.
|
||||
|
||||
// This file is designed to be used after running chipyard/scripts/tutorial-setup.sh,
|
||||
// which removes the SHA3 accelerator RTL, and provides participants
|
||||
// the experience of integrating external RTL.
|
||||
|
||||
// This file was originally developed for the cancelled ASPLOS-2020
|
||||
// Chipyard tutorial. While the configs here work, the corresponding
|
||||
// slideware has not yet been created.
|
||||
@@ -54,26 +50,6 @@ class TutorialMMIOConfig extends Config(
|
||||
new chipyard.config.AbstractConfig
|
||||
)
|
||||
|
||||
// Tutorial Phase 3: Integrate a SHA3 RoCC accelerator
|
||||
class TutorialSha3Config extends Config(
|
||||
// Uncomment this line once you added SHA3 to the build.sbt, and cloned the SHA3 repo
|
||||
// new sha3.WithSha3Accel ++
|
||||
|
||||
// For this demonstration we assume the base system is a single-core Rocket, for fast elaboration
|
||||
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
|
||||
new chipyard.config.AbstractConfig
|
||||
)
|
||||
|
||||
// Tutorial Phase 4: Integrate a Black-box verilog version of the SHA3 RoCC accelerator
|
||||
class TutorialSha3BlackBoxConfig extends Config(
|
||||
// Uncomment these lines once SHA3 is integrated
|
||||
// new sha3.WithSha3BlackBox ++ // Specify we want the Black-box verilog version of Sha3 Ctrl
|
||||
// new sha3.WithSha3Accel ++
|
||||
|
||||
// For this demonstration we assume the base system is a single-core Rocket, for fast elaboration
|
||||
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
|
||||
new chipyard.config.AbstractConfig
|
||||
)
|
||||
|
||||
// Tutorial Phase 5: Map a multicore heterogeneous SoC with multiple cores and memory-mapped accelerators
|
||||
class TutorialNoCConfig extends Config(
|
||||
|
||||
@@ -89,9 +89,12 @@ class WithFbusToSbusCrossingType(xType: ClockCrossingType) extends Config((site,
|
||||
* Mixins to set the dtsFrequency field of BusParams -- these will percolate its way
|
||||
* up the diplomatic graph to the clock sources.
|
||||
*/
|
||||
class WithPeripheryBusFrequency(freqMHz: Double) extends Config((site, here, up) => {
|
||||
case PeripheryBusKey => up(PeripheryBusKey, site).copy(dtsFrequency = Some(BigInt((freqMHz * 1e6).toLong)))
|
||||
})
|
||||
class WithPeripheryBusFrequency(freqMHz: Double) extends Config(
|
||||
new freechips.rocketchip.subsystem.WithTimebase((freqMHz * 1e3).toLong) ++ // Match DTS timebase to PBUS (i.e. RTC) frequency. Makes RTC 'tick' at the PBUS rate.
|
||||
new Config((site, here, up) => {
|
||||
case PeripheryBusKey => up(PeripheryBusKey, site).copy(dtsFrequency = Some(BigInt((freqMHz * 1e6).toLong)))
|
||||
})
|
||||
)
|
||||
class WithMemoryBusFrequency(freqMHz: Double) extends Config((site, here, up) => {
|
||||
case MemoryBusKey => up(MemoryBusKey, site).copy(dtsFrequency = Some(BigInt((freqMHz * 1e6).toLong)))
|
||||
})
|
||||
|
||||
@@ -6,7 +6,6 @@ import org.chipsalliance.cde.config.{Field, Parameters, Config}
|
||||
import freechips.rocketchip.tile._
|
||||
import freechips.rocketchip.diplomacy._
|
||||
|
||||
import hwacha.{Hwacha}
|
||||
import gemmini._
|
||||
|
||||
import chipyard.{TestSuitesKey, TestSuiteHelper}
|
||||
@@ -34,47 +33,6 @@ class WithMultiRoCCFromBuildRoCC(harts: Int*) extends Config((site, here, up) =>
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* Config fragment to add Hwachas to cores based on hart
|
||||
*
|
||||
* For ex:
|
||||
* Core 0, 1, 2, 3 have been defined earlier
|
||||
* with tileIds of 0, 1, 2, 3 respectively
|
||||
* And you call WithMultiRoCCHwacha(0,1)
|
||||
* Then Core 0 and 1 will get a Hwacha
|
||||
*
|
||||
* @param harts harts to specify which will get a Hwacha
|
||||
*/
|
||||
class WithMultiRoCCHwacha(harts: Int*) extends Config(
|
||||
new chipyard.config.WithHwachaTest ++
|
||||
new Config((site, here, up) => {
|
||||
case MultiRoCCKey => {
|
||||
up(MultiRoCCKey, site) ++ harts.distinct.map{ i =>
|
||||
(i -> Seq((p: Parameters) => {
|
||||
val hwacha = LazyModule(new Hwacha()(p))
|
||||
hwacha
|
||||
}))
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
class WithHwachaTest extends Config((site, here, up) => {
|
||||
case TestSuitesKey => (tileParams: Seq[TileParams], suiteHelper: TestSuiteHelper, p: Parameters) => {
|
||||
up(TestSuitesKey).apply(tileParams, suiteHelper, p)
|
||||
import hwacha.HwachaTestSuites._
|
||||
suiteHelper.addSuites(rv64uv.map(_("p")))
|
||||
suiteHelper.addSuites(rv64uv.map(_("vp")))
|
||||
suiteHelper.addSuite(rv64sv("p"))
|
||||
suiteHelper.addSuite(hwachaBmarks)
|
||||
"SRC_EXTENSION = $(base_dir)/hwacha/$(src_path)/*.scala" + "\nDISASM_EXTENSION = --extension=hwacha"
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* The MultiRoCCGemmini fragment functions similarly to the
|
||||
* WithMultiRoCCHwacha fragment defined above
|
||||
*/
|
||||
class WithMultiRoCCGemmini[T <: Data : Arithmetic, U <: Data, V <: Data](
|
||||
harts: Int*)(gemminiConfig: GemminiArrayConfig[T,U,V] = GemminiConfigs.defaultConfig) extends Config((site, here, up) => {
|
||||
case MultiRoCCKey => up(MultiRoCCKey, site) ++ harts.distinct.map { i =>
|
||||
|
||||
@@ -18,10 +18,6 @@ class WithSystemBusWidth(bitWidth: Int) extends Config((site, here, up) => {
|
||||
case SystemBusKey => up(SystemBusKey, site).copy(beatBytes=bitWidth/8)
|
||||
})
|
||||
|
||||
class WithDTSTimebase(freqMHz: BigInt) extends Config((site, here, up) => {
|
||||
case DTSTimebase => freqMHz
|
||||
})
|
||||
|
||||
// Adds buffers on the interior of the inclusive LLC, to improve PD
|
||||
class WithInclusiveCacheInteriorBuffer(buffer: InclusiveCachePortParameters = InclusiveCachePortParameters.full) extends Config((site, here, up) => {
|
||||
case InclusiveCacheKey => up(InclusiveCacheKey).copy(bufInnerInterior=buffer, bufOuterInterior=buffer)
|
||||
|
||||
@@ -131,3 +131,8 @@ class WithRocketBoundaryBuffers(buffers: Option[RocketTileBoundaryBufferParams]
|
||||
class WithSV48IfPossible extends Config((site, here, up) => {
|
||||
case PgLevels => if (site(XLen) == 64) 4 /* Sv48 */ else up(PgLevels)
|
||||
})
|
||||
|
||||
// Uses SV39 if possible, otherwise default to the Rocket Chip core default
|
||||
class WithSV39 extends Config((site, here, up) => {
|
||||
case PgLevels => { require(site(XLen) == 64); 3; }
|
||||
})
|
||||
|
||||
@@ -6,7 +6,7 @@ import chipyard.iobinders._
|
||||
import org.chipsalliance.cde.config._
|
||||
import freechips.rocketchip.diplomacy.{InModuleBody}
|
||||
import freechips.rocketchip.subsystem.{PBUS, HasTileLinkLocations}
|
||||
import barstools.iocell.chisel._
|
||||
import chipyard.iocell._
|
||||
import chipyard._
|
||||
import chipyard.harness.{BuildTop}
|
||||
import sifive.blocks.devices.uart._
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
package chipyard.example
|
||||
|
||||
import chisel3._
|
||||
|
||||
import org.chipsalliance.cde.config._
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.util.{DontTouch}
|
||||
|
||||
import chipyard._
|
||||
import chipyard.harness.{BuildTop}
|
||||
|
||||
class EmptyChipTop(implicit p: Parameters) extends LazyModule {
|
||||
override lazy val module = new Impl
|
||||
class Impl extends LazyRawModuleImp(this) with DontTouch {
|
||||
// Your custom non-rocketchip-soc stuff here
|
||||
}
|
||||
}
|
||||
|
||||
class WithEmptyChipTop extends Config((site, here, up) => {
|
||||
case BuildTop => (p: Parameters) => new EmptyChipTop()(p)
|
||||
})
|
||||
@@ -13,7 +13,7 @@ import chipyard.{BuildSystem, DigitalTop}
|
||||
import chipyard.harness.{BuildTop}
|
||||
import chipyard.clocking._
|
||||
import chipyard.iobinders._
|
||||
import barstools.iocell.chisel._
|
||||
import chipyard.iocell._
|
||||
import testchipip.serdes.{SerialTLKey}
|
||||
|
||||
class WithFlatChipTop extends Config((site, here, up) => {
|
||||
|
||||
@@ -12,7 +12,7 @@ import freechips.rocketchip.subsystem._
|
||||
import freechips.rocketchip.util._
|
||||
import freechips.rocketchip.jtag.{JTAGIO}
|
||||
import freechips.rocketchip.devices.debug.{SimJTAG}
|
||||
import barstools.iocell.chisel._
|
||||
import chipyard.iocell._
|
||||
import testchipip.dram.{SimDRAM}
|
||||
import testchipip.tsi.{SimTSI, SerialRAM, TSI, TSIIO}
|
||||
import testchipip.soc.{TestchipSimDTM}
|
||||
|
||||
@@ -99,6 +99,7 @@ trait HasHarnessInstantiators {
|
||||
if (p(DontTouchChipTopPorts)) {
|
||||
duts.map(_ match {
|
||||
case d: DontTouch => d.dontTouchPorts()
|
||||
case _ =>
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -30,30 +30,29 @@ object ApplyMultiHarnessBinders {
|
||||
}
|
||||
}
|
||||
|
||||
class MultiHarnessBinder[T <: Port[_], S <: HasHarnessInstantiators](
|
||||
class MultiHarnessBinder[T <: Port[_], U <: Port[_], S <: HasHarnessInstantiators](
|
||||
chip0: Int, chip1: Int,
|
||||
chip0portFn: T => Boolean, chip1portFn: T => Boolean,
|
||||
connectFn: (S, T, T) => Unit
|
||||
)(implicit tag0: ClassTag[T], tag1: ClassTag[S]) extends Config((site, here, up) => {
|
||||
chip0portFn: T => Boolean, chip1portFn: U => Boolean,
|
||||
connectFn: (S, T, U) => Unit
|
||||
)(implicit tag0: ClassTag[T], tag1: ClassTag[U], tag2: ClassTag[S]) extends Config((site, here, up) => {
|
||||
// Override any HarnessBinders for chip0/chip1
|
||||
case MultiChipParameters(`chip0`) => new Config(
|
||||
new HarnessBinder({case (th: S, port: T, chipId: Int) if chip0portFn(port) => }) ++ up(MultiChipParameters(chip0))
|
||||
)
|
||||
case MultiChipParameters(`chip1`) => new Config(
|
||||
new HarnessBinder({case (th: S, port: T, chipId: Int) if chip1portFn(port) => }) ++ up(MultiChipParameters(chip1))
|
||||
new HarnessBinder({case (th: S, port: U, chipId: Int) if chip1portFn(port) => }) ++ up(MultiChipParameters(chip1))
|
||||
)
|
||||
// Set the multiharnessbinder key
|
||||
case MultiHarnessBinders(`chip0`, `chip1`) => up(MultiHarnessBinders(chip0, chip1)) :+ {
|
||||
((th: S, chip0Ports: Seq[Port[_]], chip1Ports: Seq[Port[_]]) => {
|
||||
val chip0Port: Seq[T] = chip0Ports.collect { case (p: T) if chip0portFn(p) => p }
|
||||
val chip1Port: Seq[T] = chip1Ports.collect { case (p: T) if chip1portFn(p) => p }
|
||||
val chip1Port: Seq[U] = chip1Ports.collect { case (p: U) if chip1portFn(p) => p }
|
||||
require(chip0Port.size == 1 && chip1Port.size == 1)
|
||||
connectFn(th, chip0Port(0), chip1Port(0))
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
class WithMultiChipSerialTL(chip0: Int, chip1: Int, chip0portId: Int = 0, chip1portId: Int = 0) extends MultiHarnessBinder(
|
||||
chip0, chip1,
|
||||
(p0: SerialTLPort) => p0.portId == chip0portId,
|
||||
|
||||
@@ -27,7 +27,7 @@ import sifive.blocks.devices.spi._
|
||||
import sifive.blocks.devices.i2c._
|
||||
import tracegen.{TraceGenSystemModuleImp}
|
||||
|
||||
import barstools.iocell.chisel._
|
||||
import chipyard.iocell._
|
||||
|
||||
import testchipip.serdes.{CanHavePeripheryTLSerial, SerialTLKey}
|
||||
import testchipip.spi.{SPIChipIO}
|
||||
|
||||
18
generators/chipyard/src/main/scala/iocell/Analog.scala
Normal file
18
generators/chipyard/src/main/scala/iocell/Analog.scala
Normal file
@@ -0,0 +1,18 @@
|
||||
// See LICENSE for license details
|
||||
|
||||
package chipyard.iocell
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util.{HasBlackBoxResource}
|
||||
import chisel3.experimental.{Analog, IntParam}
|
||||
|
||||
class AnalogConst(value: Int, width: Int = 1)
|
||||
extends BlackBox(Map("CONST" -> IntParam(value), "WIDTH" -> IntParam(width)))
|
||||
with HasBlackBoxResource {
|
||||
val io = IO(new Bundle { val io = Analog(width.W) })
|
||||
addResource("/vsrc/Analog.v")
|
||||
}
|
||||
|
||||
object AnalogConst {
|
||||
def apply(value: Int, width: Int = 1) = Module(new AnalogConst(value, width)).io.io
|
||||
}
|
||||
338
generators/chipyard/src/main/scala/iocell/IOCell.scala
Normal file
338
generators/chipyard/src/main/scala/iocell/IOCell.scala
Normal file
@@ -0,0 +1,338 @@
|
||||
// See LICENSE for license details
|
||||
|
||||
package chipyard.iocell
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util.{Cat, HasBlackBoxInline}
|
||||
import chisel3.reflect.DataMirror
|
||||
import chisel3.experimental.{Analog, BaseModule}
|
||||
|
||||
// The following four IO cell bundle types are bare-minimum functional connections
|
||||
// for modeling 4 different IO cell scenarios. The intention is that the user
|
||||
// would create wrapper modules that extend these interfaces with additional
|
||||
// control signals. These are loosely similar to the sifive-blocks PinCtrl bundles
|
||||
// (https://github.com/sifive/sifive-blocks/blob/master/src/main/scala/devices/pinctrl/PinCtrl.scala),
|
||||
// but we want to avoid a dependency on an external libraries.
|
||||
|
||||
/** The base IO bundle for an analog signal (typically something with no digital buffers inside)
|
||||
* pad: off-chip (external) connection
|
||||
* core: internal connection
|
||||
*/
|
||||
class AnalogIOCellBundle extends Bundle {
|
||||
val pad = Analog(1.W) // Pad/bump signal (off-chip)
|
||||
val core = Analog(1.W) // core signal (on-chip)
|
||||
}
|
||||
|
||||
/** The base IO bundle for a signal with runtime-controllable direction
|
||||
* pad: off-chip (external) connection
|
||||
* i: input to chip logic (output from IO cell)
|
||||
* ie: enable signal for i
|
||||
* o: output from chip logic (input to IO cell)
|
||||
* oe: enable signal for o
|
||||
*/
|
||||
class DigitalGPIOCellBundle extends Bundle {
|
||||
val pad = Analog(1.W)
|
||||
val i = Output(Bool())
|
||||
val ie = Input(Bool())
|
||||
val o = Input(Bool())
|
||||
val oe = Input(Bool())
|
||||
}
|
||||
|
||||
/** The base IO bundle for a digital output signal
|
||||
* pad: off-chip (external) connection
|
||||
* o: output from chip logic (input to IO cell)
|
||||
* oe: enable signal for o
|
||||
*/
|
||||
class DigitalOutIOCellBundle extends Bundle {
|
||||
val pad = Output(Bool())
|
||||
val o = Input(Bool())
|
||||
val oe = Input(Bool())
|
||||
}
|
||||
|
||||
/** The base IO bundle for a digital input signal
|
||||
* pad: off-chip (external) connection
|
||||
* i: input to chip logic (output from IO cell)
|
||||
* ie: enable signal for i
|
||||
*/
|
||||
class DigitalInIOCellBundle extends Bundle {
|
||||
val pad = Input(Bool())
|
||||
val i = Output(Bool())
|
||||
val ie = Input(Bool())
|
||||
}
|
||||
|
||||
trait IOCell extends BaseModule {
|
||||
var iocell_name: Option[String] = None
|
||||
|
||||
/** Set IOCell name
|
||||
* @param s Proposed name for the IOCell
|
||||
*
|
||||
* @return An inherited IOCell with given the proposed name
|
||||
*/
|
||||
def suggestName(s: String): this.type = {
|
||||
iocell_name = Some(s)
|
||||
super.suggestName(s)
|
||||
}
|
||||
}
|
||||
|
||||
trait AnalogIOCell extends IOCell {
|
||||
val io: AnalogIOCellBundle
|
||||
}
|
||||
|
||||
trait DigitalGPIOCell extends IOCell {
|
||||
val io: DigitalGPIOCellBundle
|
||||
}
|
||||
|
||||
trait DigitalInIOCell extends IOCell {
|
||||
val io: DigitalInIOCellBundle
|
||||
}
|
||||
|
||||
trait DigitalOutIOCell extends IOCell {
|
||||
val io: DigitalOutIOCellBundle
|
||||
}
|
||||
|
||||
// The following Generic IO cell black boxes have verilog models that mimic a very simple
|
||||
// implementation of an IO cell. For building a real chip, it is important to implement
|
||||
// and use similar classes which wrap the foundry-specific IO cells.
|
||||
|
||||
abstract class GenericIOCell extends BlackBox with HasBlackBoxInline {
|
||||
val impl: String
|
||||
val moduleName = this.getClass.getSimpleName
|
||||
setInline(s"$moduleName.v", impl);
|
||||
}
|
||||
|
||||
class GenericAnalogIOCell extends GenericIOCell with AnalogIOCell {
|
||||
val io = IO(new AnalogIOCellBundle)
|
||||
lazy val impl = s"""
|
||||
`timescale 1ns/1ps
|
||||
module GenericAnalogIOCell(
|
||||
inout pad,
|
||||
inout core
|
||||
);
|
||||
|
||||
assign core = 1'bz;
|
||||
assign pad = core;
|
||||
|
||||
endmodule"""
|
||||
}
|
||||
|
||||
class GenericDigitalGPIOCell extends GenericIOCell with DigitalGPIOCell {
|
||||
val io = IO(new DigitalGPIOCellBundle)
|
||||
lazy val impl = s"""
|
||||
`timescale 1ns/1ps
|
||||
module GenericDigitalGPIOCell(
|
||||
inout pad,
|
||||
output i,
|
||||
input ie,
|
||||
input o,
|
||||
input oe
|
||||
);
|
||||
|
||||
assign pad = oe ? o : 1'bz;
|
||||
assign i = ie ? pad : 1'b0;
|
||||
|
||||
endmodule"""
|
||||
}
|
||||
|
||||
class GenericDigitalInIOCell extends GenericIOCell with DigitalInIOCell {
|
||||
val io = IO(new DigitalInIOCellBundle)
|
||||
lazy val impl = s"""
|
||||
`timescale 1ns/1ps
|
||||
module GenericDigitalInIOCell(
|
||||
input pad,
|
||||
output i,
|
||||
input ie
|
||||
);
|
||||
|
||||
assign i = ie ? pad : 1'b0;
|
||||
|
||||
endmodule"""
|
||||
}
|
||||
|
||||
class GenericDigitalOutIOCell extends GenericIOCell with DigitalOutIOCell {
|
||||
val io = IO(new DigitalOutIOCellBundle)
|
||||
lazy val impl = s"""
|
||||
`timescale 1ns/1ps
|
||||
module GenericDigitalOutIOCell(
|
||||
output pad,
|
||||
input o,
|
||||
input oe
|
||||
);
|
||||
|
||||
assign pad = oe ? o : 1'bz;
|
||||
|
||||
endmodule"""
|
||||
}
|
||||
|
||||
trait IOCellTypeParams {
|
||||
def analog(): AnalogIOCell
|
||||
def gpio(): DigitalGPIOCell
|
||||
def input(): DigitalInIOCell
|
||||
def output(): DigitalOutIOCell
|
||||
}
|
||||
|
||||
case class GenericIOCellParams() extends IOCellTypeParams {
|
||||
def analog() = Module(new GenericAnalogIOCell)
|
||||
def gpio() = Module(new GenericDigitalGPIOCell)
|
||||
def input() = Module(new GenericDigitalInIOCell)
|
||||
def output() = Module(new GenericDigitalOutIOCell)
|
||||
}
|
||||
|
||||
object IOCell {
|
||||
|
||||
/** From within a RawModule or MultiIOModule context, generate new module IOs from a given
|
||||
* signal and return the new IO and a Seq containing all generated IO cells.
|
||||
* @param coreSignal The signal onto which to add IO cells
|
||||
* @param name An optional name or name prefix to use for naming IO cells
|
||||
* @param abstractResetAsAsync When set, will coerce abstract resets to
|
||||
* AsyncReset, and otherwise to Bool (sync reset)
|
||||
* @return A tuple of (the generated IO data node, a Seq of all generated IO cell instances)
|
||||
*/
|
||||
def generateIOFromSignal[T <: Data](
|
||||
coreSignal: T,
|
||||
name: String,
|
||||
typeParams: IOCellTypeParams = GenericIOCellParams(),
|
||||
abstractResetAsAsync: Boolean = false
|
||||
): (T, Seq[IOCell]) = {
|
||||
val padSignal = IO(DataMirror.internal.chiselTypeClone[T](coreSignal)).suggestName(name)
|
||||
val resetFn = if (abstractResetAsAsync) toAsyncReset else toSyncReset
|
||||
val iocells = IOCell.generateFromSignal(coreSignal, padSignal, Some(s"iocell_$name"), typeParams, resetFn)
|
||||
(padSignal, iocells)
|
||||
}
|
||||
|
||||
/** Connect two identical signals together by adding IO cells between them and return a Seq
|
||||
* containing all generated IO cells.
|
||||
* @param coreSignal The core-side (internal) signal onto which to connect/add IO cells
|
||||
* @param padSignal The pad-side (external) signal onto which to connect IO cells
|
||||
* @param name An optional name or name prefix to use for naming IO cells
|
||||
* @return A Seq of all generated IO cell instances
|
||||
*/
|
||||
val toSyncReset: (Reset) => Bool = _.asBool
|
||||
val toAsyncReset: (Reset) => AsyncReset = _.asAsyncReset
|
||||
def generateFromSignal[T <: Data, R <: Reset](
|
||||
coreSignal: T,
|
||||
padSignal: T,
|
||||
name: Option[String] = None,
|
||||
typeParams: IOCellTypeParams = GenericIOCellParams(),
|
||||
concretizeResetFn: (Reset) => R = toSyncReset
|
||||
): Seq[IOCell] = {
|
||||
def genCell[T <: Data](
|
||||
castToBool: (T) => Bool,
|
||||
castFromBool: (Bool) => T
|
||||
)(coreSignal: T,
|
||||
padSignal: T
|
||||
): Seq[IOCell] = {
|
||||
DataMirror.directionOf(coreSignal) match {
|
||||
case ActualDirection.Input => {
|
||||
val iocell = typeParams.input()
|
||||
name.foreach(n => {
|
||||
iocell.suggestName(n)
|
||||
})
|
||||
coreSignal := castFromBool(iocell.io.i)
|
||||
iocell.io.ie := true.B
|
||||
iocell.io.pad := castToBool(padSignal)
|
||||
Seq(iocell)
|
||||
}
|
||||
case ActualDirection.Output => {
|
||||
val iocell = typeParams.output()
|
||||
name.foreach(n => {
|
||||
iocell.suggestName(n)
|
||||
})
|
||||
iocell.io.o := castToBool(coreSignal)
|
||||
iocell.io.oe := true.B
|
||||
padSignal := castFromBool(iocell.io.pad)
|
||||
Seq(iocell)
|
||||
}
|
||||
case _ => throw new Exception(s"Signal does not have a direction and cannot be matched to an IOCell")
|
||||
}
|
||||
}
|
||||
def genCellForClock = genCell[Clock](_.asUInt.asBool, _.asClock) _
|
||||
def genCellForAsyncReset = genCell[AsyncReset](_.asBool, _.asAsyncReset) _
|
||||
def genCellForAbstractReset = genCell[Reset](_.asBool, concretizeResetFn) _
|
||||
|
||||
(coreSignal, padSignal) match {
|
||||
case (coreSignal: Analog, padSignal: Analog) => {
|
||||
if (coreSignal.getWidth == 0) {
|
||||
Seq()
|
||||
} else {
|
||||
require(
|
||||
coreSignal.getWidth == 1,
|
||||
"Analogs wider than 1 bit are not supported because we can't bit-select Analogs (https://github.com/freechipsproject/chisel3/issues/536)"
|
||||
)
|
||||
val iocell = typeParams.analog()
|
||||
name.foreach(n => iocell.suggestName(n))
|
||||
iocell.io.core <> coreSignal
|
||||
padSignal <> iocell.io.pad
|
||||
Seq(iocell)
|
||||
}
|
||||
}
|
||||
case (coreSignal: Clock, padSignal: Clock) => genCellForClock(coreSignal, padSignal)
|
||||
case (coreSignal: AsyncReset, padSignal: AsyncReset) => genCellForAsyncReset(coreSignal, padSignal)
|
||||
case (coreSignal: Bits, padSignal: Bits) => {
|
||||
require(padSignal.getWidth == coreSignal.getWidth, "padSignal and coreSignal must be the same width")
|
||||
if (padSignal.getWidth == 0) {
|
||||
// This dummy assignment will prevent invalid firrtl from being emitted
|
||||
DataMirror.directionOf(coreSignal) match {
|
||||
case ActualDirection.Input => coreSignal := 0.U
|
||||
case _ => {}
|
||||
}
|
||||
Seq()
|
||||
} else {
|
||||
DataMirror.directionOf(coreSignal) match {
|
||||
case ActualDirection.Input => {
|
||||
val iocells = padSignal.asBools.zipWithIndex.map { case (sig, i) =>
|
||||
val iocell = typeParams.input()
|
||||
// Note that we are relying on chisel deterministically naming this in the index order (which it does)
|
||||
// This has the side-effect of naming index 0 with no _0 suffix, which is how chisel names other signals
|
||||
// An alternative solution would be to suggestName(n + "_" + i)
|
||||
name.foreach(n => {
|
||||
iocell.suggestName(n)
|
||||
})
|
||||
iocell.io.pad := sig
|
||||
iocell.io.ie := true.B
|
||||
iocell
|
||||
}
|
||||
// Note that the reverse here is because Cat(Seq(a,b,c,d)) yields abcd, but a is index 0 of the Seq
|
||||
coreSignal := Cat(iocells.map(_.io.i).reverse)
|
||||
iocells
|
||||
}
|
||||
case ActualDirection.Output => {
|
||||
val iocells = coreSignal.asBools.zipWithIndex.map { case (sig, i) =>
|
||||
val iocell = typeParams.output()
|
||||
// Note that we are relying on chisel deterministically naming this in the index order (which it does)
|
||||
// This has the side-effect of naming index 0 with no _0 suffix, which is how chisel names other signals
|
||||
// An alternative solution would be to suggestName(n + "_" + i)
|
||||
name.foreach(n => {
|
||||
iocell.suggestName(n)
|
||||
})
|
||||
iocell.io.o := sig
|
||||
iocell.io.oe := true.B
|
||||
iocell
|
||||
}
|
||||
// Note that the reverse here is because Cat(Seq(a,b,c,d)) yields abcd, but a is index 0 of the Seq
|
||||
padSignal := Cat(iocells.map(_.io.pad).reverse)
|
||||
iocells
|
||||
}
|
||||
case _ => throw new Exception("Bits signal does not have a direction and cannot be matched to IOCell(s)")
|
||||
}
|
||||
}
|
||||
}
|
||||
case (coreSignal: Reset, padSignal: Reset) => genCellForAbstractReset(coreSignal, padSignal)
|
||||
case (coreSignal: Vec[_], padSignal: Vec[_]) => {
|
||||
require(padSignal.size == coreSignal.size, "size of Vec for padSignal and coreSignal must be the same")
|
||||
coreSignal.zip(padSignal).zipWithIndex.foldLeft(Seq.empty[IOCell]) { case (total, ((core, pad), i)) =>
|
||||
val ios = IOCell.generateFromSignal(core, pad, name.map(_ + "_" + i), typeParams)
|
||||
total ++ ios
|
||||
}
|
||||
}
|
||||
case (coreSignal: Record, padSignal: Record) => {
|
||||
coreSignal.elements.foldLeft(Seq.empty[IOCell]) { case (total, (eltName, core)) =>
|
||||
val pad = padSignal.elements(eltName)
|
||||
val ios = IOCell.generateFromSignal(core, pad, name.map(_ + "_" + eltName), typeParams)
|
||||
total ++ ios
|
||||
}
|
||||
}
|
||||
case _ => { throw new Exception("Oops, I don't know how to handle this signal.") }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
// See LICENSE for license details.
|
||||
// Based on Rocket Chip's stage implementation
|
||||
|
||||
package chipyard.stage
|
||||
|
||||
import chisel3.experimental.BaseModule
|
||||
import firrtl.annotations.{Annotation, NoTargetAnnotation}
|
||||
import firrtl.options.{HasShellOptions, ShellOption, Unserializable}
|
||||
|
||||
trait ChipyardOption extends Unserializable { this: Annotation => }
|
||||
|
||||
/** This hijacks the existing ConfigAnnotation to accept the legacy _-delimited format */
|
||||
private[stage] object UnderscoreDelimitedConfigsAnnotation extends HasShellOptions {
|
||||
override val options = Seq(
|
||||
new ShellOption[String](
|
||||
longOption = "legacy-configs",
|
||||
toAnnotationSeq = a => {
|
||||
val split = a.split(':')
|
||||
assert(split.length == 2, s"'${a}' split by ':' doesn't yield two things")
|
||||
val packageName = split.head
|
||||
val configs = split.last.split("_")
|
||||
Seq(new ConfigsAnnotation(configs map { config => if (config contains ".") s"${config}" else s"${packageName}.${config}" } ))
|
||||
},
|
||||
helpText = "A string of underscore-delimited configs (configs have decreasing precendence from left to right).",
|
||||
shortOption = Some("LC")
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/** Paths to config classes */
|
||||
case class ConfigsAnnotation(configNames: Seq[String]) extends NoTargetAnnotation with ChipyardOption
|
||||
private[stage] object ConfigsAnnotation extends HasShellOptions {
|
||||
override val options = Seq(
|
||||
new ShellOption[Seq[String]](
|
||||
longOption = "configs",
|
||||
toAnnotationSeq = a => Seq(ConfigsAnnotation(a)),
|
||||
helpText = "<comma-delimited configs>",
|
||||
shortOption = Some("C")
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
case class TopModuleAnnotation(clazz: Class[_ <: Any]) extends NoTargetAnnotation with ChipyardOption
|
||||
private[stage] object TopModuleAnnotation extends HasShellOptions {
|
||||
override val options = Seq(
|
||||
new ShellOption[String](
|
||||
longOption = "top-module",
|
||||
toAnnotationSeq = a => Seq(TopModuleAnnotation(Class.forName(a).asInstanceOf[Class[_ <: BaseModule]])),
|
||||
helpText = "<top module>",
|
||||
shortOption = Some("T")
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/** Optional base name for generated files' filenames */
|
||||
case class OutputBaseNameAnnotation(outputBaseName: String) extends NoTargetAnnotation with ChipyardOption
|
||||
private[stage] object OutputBaseNameAnnotation extends HasShellOptions {
|
||||
override val options = Seq(
|
||||
new ShellOption[String](
|
||||
longOption = "name",
|
||||
toAnnotationSeq = a => Seq(OutputBaseNameAnnotation(a)),
|
||||
helpText = "<base name of output files>",
|
||||
shortOption = Some("n")
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
// See LICENSE for license details.
|
||||
// Based on Rocket Chip's stage implementation
|
||||
|
||||
package chipyard.stage
|
||||
|
||||
import firrtl.options.Shell
|
||||
|
||||
trait ChipyardCli { this: Shell =>
|
||||
|
||||
parser.note("Chipyard Generator Options")
|
||||
Seq(
|
||||
TopModuleAnnotation,
|
||||
ConfigsAnnotation,
|
||||
OutputBaseNameAnnotation,
|
||||
UnderscoreDelimitedConfigsAnnotation
|
||||
).foreach(_.addOptions(parser))
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
// See LICENSE
|
||||
|
||||
package chipyard.stage
|
||||
|
||||
class ChipyardOptions private[stage] (
|
||||
val topModule: Option[Class[_ <: Any]] = None,
|
||||
val configNames: Option[Seq[String]] = None,
|
||||
val outputBaseName: Option[String] = None) {
|
||||
|
||||
private[stage] def copy(
|
||||
topModule: Option[Class[_ <: Any]] = topModule,
|
||||
configNames: Option[Seq[String]] = configNames,
|
||||
outputBaseName: Option[String] = outputBaseName,
|
||||
): ChipyardOptions = {
|
||||
|
||||
new ChipyardOptions(
|
||||
topModule=topModule,
|
||||
configNames=configNames,
|
||||
outputBaseName=outputBaseName,
|
||||
)
|
||||
}
|
||||
|
||||
lazy val topPackage: Option[String] = topModule match {
|
||||
case Some(a) => Some(a.getPackage.getName)
|
||||
case _ => None
|
||||
}
|
||||
|
||||
lazy val configClass: Option[String] = configNames match {
|
||||
case Some(names) =>
|
||||
val classNames = names.map{ n => n.split('.').last }
|
||||
Some(classNames.mkString("_"))
|
||||
case _ => None
|
||||
}
|
||||
|
||||
lazy val longName: Option[String] = outputBaseName match {
|
||||
case Some(name) => Some(name)
|
||||
case _ =>
|
||||
if (!topPackage.isEmpty && !configClass.isEmpty) Some(s"${topPackage.get}.${configClass.get}") else None
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
// See LICENSE for license details.
|
||||
// Based on Rocket Chip's stage implementation
|
||||
|
||||
package chipyard.stage
|
||||
|
||||
import chisel3.stage.{ChiselCli, ChiselStage}
|
||||
import firrtl.options.PhaseManager.PhaseDependency
|
||||
import firrtl.options.{Phase, PreservesAll, Shell}
|
||||
import firrtl.stage.FirrtlCli
|
||||
|
||||
import firrtl.options.{Phase, PhaseManager, PreservesAll, Shell, Stage, StageError, StageMain, Dependency}
|
||||
import firrtl.options.phases.DeletedWrapper
|
||||
|
||||
final class ChipyardChiselStage extends ChiselStage {
|
||||
|
||||
override val targets = Seq(
|
||||
Dependency[chisel3.stage.phases.Checks],
|
||||
Dependency[chisel3.stage.phases.Elaborate],
|
||||
Dependency[chisel3.stage.phases.AddImplicitOutputFile],
|
||||
Dependency[chisel3.stage.phases.AddImplicitOutputAnnotationFile],
|
||||
Dependency[chisel3.stage.phases.MaybeAspectPhase],
|
||||
Dependency[chisel3.stage.phases.Emitter],
|
||||
Dependency[chisel3.stage.phases.Convert]
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
class ChipyardStage extends ChiselStage {
|
||||
override val shell = new Shell("chipyard") with ChipyardCli with ChiselCli with FirrtlCli
|
||||
override val targets: Seq[PhaseDependency] = Seq(
|
||||
Dependency[chipyard.stage.phases.Checks],
|
||||
Dependency[chipyard.stage.phases.TransformAnnotations],
|
||||
Dependency[chipyard.stage.phases.PreElaboration],
|
||||
Dependency[ChipyardChiselStage],
|
||||
Dependency[chipyard.stage.phases.GenerateFirrtlAnnos],
|
||||
Dependency[chipyard.stage.phases.AddDefaultTests],
|
||||
Dependency[chipyard.stage.phases.GenerateTestSuiteMakefrags],
|
||||
Dependency[chipyard.stage.phases.GenerateArtefacts],
|
||||
)
|
||||
override final def invalidates(a: Phase): Boolean = false
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
// See LICENSE
|
||||
|
||||
package chipyard.stage
|
||||
|
||||
import java.io.{File, FileWriter}
|
||||
|
||||
import org.chipsalliance.cde.config.{Config, Parameters}
|
||||
import chisel3.internal.firrtl.Circuit
|
||||
import freechips.rocketchip.util.{BlackBoxedROM, ROMGenerator}
|
||||
|
||||
trait HasChipyardStageUtils {
|
||||
|
||||
def getConfig(fullConfigClassNames: Seq[String]): Config = {
|
||||
new Config(fullConfigClassNames.foldRight(Parameters.empty) { case (currentName, config) =>
|
||||
val currentConfig = try {
|
||||
Class.forName(currentName).newInstance.asInstanceOf[Config]
|
||||
} catch {
|
||||
case e: java.lang.ClassNotFoundException =>
|
||||
throw new Exception(s"""Unable to find part "$currentName" from "$fullConfigClassNames", did you misspell it or specify the wrong package path?""", e)
|
||||
}
|
||||
currentConfig ++ config
|
||||
})
|
||||
}
|
||||
|
||||
def enumerateROMs(circuit: Circuit): String = {
|
||||
val res = new StringBuilder
|
||||
val configs =
|
||||
circuit.components flatMap { m =>
|
||||
m.id match {
|
||||
case rom: BlackBoxedROM => Some((rom.name, ROMGenerator.lookup(rom)))
|
||||
case _ => None
|
||||
}
|
||||
}
|
||||
configs foreach { case (name, c) =>
|
||||
res append s"name ${name} depth ${c.depth} width ${c.width}\n"
|
||||
}
|
||||
res.toString
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
// See LICENSE
|
||||
|
||||
package chipyard
|
||||
|
||||
import firrtl.AnnotationSeq
|
||||
import firrtl.options.OptionsView
|
||||
|
||||
package object stage {
|
||||
|
||||
implicit object ChipyardOptionsView extends OptionsView[ChipyardOptions] {
|
||||
|
||||
def view(annotations: AnnotationSeq): ChipyardOptions = annotations
|
||||
.collect { case a: ChipyardOption => a }
|
||||
.foldLeft(new ChipyardOptions()){ (c, x) =>
|
||||
x match {
|
||||
case TopModuleAnnotation(a) => c.copy(topModule = Some(a))
|
||||
case ConfigsAnnotation(a) => c.copy(configNames = Some(a))
|
||||
case OutputBaseNameAnnotation(a) => c.copy(outputBaseName = Some(a))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
// See LICENSE for license details.
|
||||
// Based on Rocket Chip's stage implementation
|
||||
|
||||
package chipyard.stage.phases
|
||||
|
||||
import scala.util.Try
|
||||
import scala.collection.mutable
|
||||
|
||||
import org.chipsalliance.cde.config.Parameters
|
||||
import chisel3.stage.phases.Elaborate
|
||||
import firrtl.AnnotationSeq
|
||||
import firrtl.annotations.{Annotation, NoTargetAnnotation}
|
||||
import firrtl.options._
|
||||
import firrtl.options.Viewer._
|
||||
import freechips.rocketchip.system.{RocketTestSuite, TestGeneration}
|
||||
import freechips.rocketchip.subsystem.{TilesLocated, InSubsystem}
|
||||
import freechips.rocketchip.tile.XLen
|
||||
|
||||
import chipyard.TestSuiteHelper
|
||||
import chipyard.TestSuitesKey
|
||||
import chipyard.stage._
|
||||
|
||||
/** Annotation that contains a list of [[RocketTestSuite]]s to run */
|
||||
case class ChipyardTestSuiteAnnotation(tests: Seq[RocketTestSuite]) extends NoTargetAnnotation with Unserializable
|
||||
|
||||
|
||||
class AddDefaultTests extends Phase with PreservesAll[Phase] with HasChipyardStageUtils {
|
||||
override val prerequisites = Seq(Dependency[ChipyardChiselStage])
|
||||
override val dependents = Seq(Dependency[GenerateTestSuiteMakefrags])
|
||||
|
||||
private def addTestSuiteAnnotations(implicit p: Parameters): Seq[Annotation] = {
|
||||
val annotations = mutable.ArrayBuffer[Annotation]()
|
||||
val suiteHelper = new TestSuiteHelper
|
||||
// Use Xlen as a proxy for detecting if we are a processor-like target
|
||||
// The underlying test suites expect this field to be defined
|
||||
val tileParams = p(TilesLocated(InSubsystem)) map (tp => tp.tileParams)
|
||||
if (p.lift(XLen).nonEmpty)
|
||||
// If a custom test suite is set up, use the custom test suite
|
||||
annotations += CustomMakefragSnippet(p(TestSuitesKey).apply(tileParams, suiteHelper, p))
|
||||
|
||||
ChipyardTestSuiteAnnotation(suiteHelper.suites.values.toSeq) +: annotations.toSeq
|
||||
}
|
||||
|
||||
|
||||
override def transform(annotations: AnnotationSeq): AnnotationSeq = {
|
||||
val (testSuiteAnnos, oAnnos) = annotations.partition {
|
||||
case ChipyardTestSuiteAnnotation(_) => true
|
||||
case o => false
|
||||
}
|
||||
implicit val p = getConfig(view[ChipyardOptions](annotations).configNames.get).toInstance
|
||||
addTestSuiteAnnotations(p) ++ oAnnos
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
// See LICENSE
|
||||
|
||||
package chipyard.stage.phases
|
||||
|
||||
import firrtl.AnnotationSeq
|
||||
import firrtl.annotations.Annotation
|
||||
import firrtl.options.{OptionsException, Phase, PreservesAll, TargetDirAnnotation}
|
||||
import chipyard.stage._
|
||||
|
||||
import scala.collection.mutable
|
||||
|
||||
/** Checks for the correct type and number of command line arguments */
|
||||
class Checks extends Phase with PreservesAll[Phase] {
|
||||
|
||||
override def transform(annotations: AnnotationSeq): AnnotationSeq = {
|
||||
val targetDir, topModule, configNames, outputBaseName = mutable.ListBuffer[Annotation]()
|
||||
|
||||
annotations.foreach {
|
||||
case a: TargetDirAnnotation => a +=: targetDir
|
||||
case a: TopModuleAnnotation => a +=: topModule
|
||||
case a: ConfigsAnnotation => a +=: configNames
|
||||
case a: OutputBaseNameAnnotation => a +=: outputBaseName
|
||||
case _ =>
|
||||
}
|
||||
|
||||
def required(annoList: mutable.ListBuffer[Annotation], option: String): Unit = {
|
||||
if (annoList.size != 1) {
|
||||
throw new OptionsException(s"Exactly one $option required")
|
||||
}
|
||||
}
|
||||
|
||||
def optional(annoList: mutable.ListBuffer[Annotation], option: String): Unit = {
|
||||
if (annoList.size > 1) {
|
||||
throw new OptionsException(s"Too many $option options have been specified")
|
||||
}
|
||||
}
|
||||
|
||||
required(targetDir, "target directory")
|
||||
required(topModule, "top module")
|
||||
required(configNames, "configs string (','-delimited)")
|
||||
|
||||
optional(outputBaseName, "output base name")
|
||||
|
||||
annotations
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
// See LICENSE
|
||||
|
||||
package chipyard.stage.phases
|
||||
|
||||
import firrtl.AnnotationSeq
|
||||
import firrtl.options.{Dependency, Phase, PreservesAll, StageOptions}
|
||||
import firrtl.options.Viewer.view
|
||||
import chipyard.stage._
|
||||
import freechips.rocketchip.util.{ElaborationArtefacts}
|
||||
|
||||
/** Writes [[ElaborationArtefacts]] into files */
|
||||
class GenerateArtefacts extends Phase with PreservesAll[Phase] with HasChipyardStageUtils {
|
||||
|
||||
override val prerequisites = Seq(Dependency[chipyard.stage.ChipyardChiselStage])
|
||||
|
||||
override def transform(annotations: AnnotationSeq): AnnotationSeq = {
|
||||
val targetDir = view[StageOptions](annotations).targetDir
|
||||
|
||||
ElaborationArtefacts.files.foreach { case (extension, contents) =>
|
||||
writeOutputFile(targetDir, s"${view[ChipyardOptions](annotations).longName.get}.${extension}", contents ())
|
||||
}
|
||||
|
||||
annotations
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
// See LICENSE
|
||||
|
||||
package chipyard.stage.phases
|
||||
|
||||
import firrtl.AnnotationSeq
|
||||
import firrtl.annotations.{DeletedAnnotation, JsonProtocol}
|
||||
import firrtl.options.Viewer.view
|
||||
import firrtl.options._
|
||||
import chipyard.stage._
|
||||
|
||||
/** Writes FIRRTL annotations into a file */
|
||||
class GenerateFirrtlAnnos extends Phase with PreservesAll[Phase] with HasChipyardStageUtils {
|
||||
|
||||
override val prerequisites = Seq(Dependency[chipyard.stage.ChipyardChiselStage])
|
||||
|
||||
override def transform(annotations: AnnotationSeq): AnnotationSeq = {
|
||||
val targetDir = view[StageOptions](annotations).targetDir
|
||||
val fileName = s"${view[ChipyardOptions](annotations).longName.get}.anno.json"
|
||||
|
||||
val annos = annotations.view.flatMap {
|
||||
// Remove TargetDirAnnotation so that we can pass as argument to FIRRTL
|
||||
// Remove CustomFileEmission, those are serialized automatically by Stages
|
||||
case (_: Unserializable | _: TargetDirAnnotation | _: CustomFileEmission) =>
|
||||
None
|
||||
case DeletedAnnotation(_, (_: Unserializable | _: CustomFileEmission)) =>
|
||||
None
|
||||
case a =>
|
||||
Some(a)
|
||||
}
|
||||
|
||||
writeOutputFile(targetDir, fileName, JsonProtocol.serialize(annos.toSeq))
|
||||
|
||||
annotations
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
// See LICENSE for license details.
|
||||
// Based on Rocket Chip's stage implementation
|
||||
|
||||
package chipyard.stage.phases
|
||||
|
||||
import scala.collection.mutable
|
||||
|
||||
import firrtl.AnnotationSeq
|
||||
import firrtl.annotations.{Annotation, NoTargetAnnotation}
|
||||
import firrtl.options.{Phase, PreservesAll, StageOptions, Unserializable, Dependency}
|
||||
import firrtl.options.Viewer.view
|
||||
import chipyard.stage._
|
||||
import freechips.rocketchip.system.TestGeneration
|
||||
|
||||
trait MakefragSnippet { self: Annotation =>
|
||||
def toMakefrag: String
|
||||
}
|
||||
|
||||
case class CustomMakefragSnippet(val toMakefrag: String) extends NoTargetAnnotation with MakefragSnippet with Unserializable
|
||||
|
||||
/** Generates a make script to run tests in [[RocketTestSuiteAnnotation]]. */
|
||||
class GenerateTestSuiteMakefrags extends Phase with HasChipyardStageUtils {
|
||||
|
||||
// Our annotations tend not to be serializable, but are not marked as such.
|
||||
override val prerequisites = Seq(Dependency[chipyard.stage.phases.GenerateFirrtlAnnos],
|
||||
Dependency[chipyard.stage.phases.AddDefaultTests])
|
||||
|
||||
override def transform(annotations: AnnotationSeq): AnnotationSeq = {
|
||||
val targetDir = view[StageOptions](annotations).targetDir
|
||||
val fileName = s"${view[ChipyardOptions](annotations).longName.get}.d"
|
||||
|
||||
val makefragBuilder = new mutable.StringBuilder()
|
||||
val outputAnnotations = annotations.flatMap {
|
||||
case ChipyardTestSuiteAnnotation(tests) =>
|
||||
// Unfortunately the gen method of TestGeneration is rocketchip package
|
||||
// private, so we either have to copy code in or use the stateful form
|
||||
TestGeneration.addSuites(tests)
|
||||
None
|
||||
case a: MakefragSnippet =>
|
||||
makefragBuilder :+ ("\n" + a.toMakefrag)
|
||||
None
|
||||
case a => Some(a)
|
||||
}
|
||||
writeOutputFile(targetDir, fileName, TestGeneration.generateMakeFrag ++ makefragBuilder.toString)
|
||||
outputAnnotations
|
||||
}
|
||||
|
||||
override final def invalidates(a: Phase): Boolean = false
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
// See LICENSE
|
||||
|
||||
package chipyard.stage.phases
|
||||
|
||||
import chisel3.RawModule
|
||||
import chisel3.stage.ChiselGeneratorAnnotation
|
||||
import firrtl.AnnotationSeq
|
||||
import firrtl.options.Viewer.view
|
||||
import firrtl.options.{Dependency, Phase, PreservesAll, StageOptions}
|
||||
import org.chipsalliance.cde.config.{Field, Parameters}
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import chipyard.stage._
|
||||
|
||||
case object TargetDirKey extends Field[String](".")
|
||||
|
||||
/** Constructs a generator function that returns a top module with given config parameters */
|
||||
class PreElaboration extends Phase with PreservesAll[Phase] with HasChipyardStageUtils {
|
||||
|
||||
override val prerequisites = Seq(Dependency[Checks])
|
||||
override val dependents = Seq(Dependency[chisel3.stage.phases.Elaborate])
|
||||
|
||||
override def transform(annotations: AnnotationSeq): AnnotationSeq = {
|
||||
|
||||
val stageOpts = view[StageOptions](annotations)
|
||||
val rOpts = view[ChipyardOptions](annotations)
|
||||
val topMod = rOpts.topModule.get
|
||||
|
||||
val config = getConfig(rOpts.configNames.get).alterPartial {
|
||||
case TargetDirKey => stageOpts.targetDir
|
||||
}
|
||||
|
||||
val gen = () =>
|
||||
topMod
|
||||
.getConstructor(classOf[Parameters])
|
||||
.newInstance(config) match {
|
||||
case a: RawModule => a
|
||||
case a: LazyModule => LazyModule(a).module
|
||||
}
|
||||
|
||||
ChiselGeneratorAnnotation(gen) +: annotations
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
// See LICENSE
|
||||
|
||||
package chipyard.stage.phases
|
||||
|
||||
import chisel3.stage.ChiselOutputFileAnnotation
|
||||
import firrtl.AnnotationSeq
|
||||
import firrtl.options.Viewer.view
|
||||
import firrtl.options.{Dependency, Phase, PreservesAll}
|
||||
import chipyard.stage._
|
||||
|
||||
/** Transforms RocketChipAnnotations into those used by other stages */
|
||||
class TransformAnnotations extends Phase with PreservesAll[Phase] with HasChipyardStageUtils {
|
||||
|
||||
override val prerequisites = Seq(Dependency[Checks])
|
||||
override val dependents = Seq(Dependency[chisel3.stage.phases.AddImplicitOutputFile])
|
||||
|
||||
override def transform(annotations: AnnotationSeq): AnnotationSeq = {
|
||||
/** Construct output file annotation for emission */
|
||||
new ChiselOutputFileAnnotation(view[ChipyardOptions](annotations).longName.get) +: annotations
|
||||
}
|
||||
}
|
||||
Submodule generators/diplomacy updated: edf375300d...055be698f4
Submodule generators/fft-generator updated: 490b975d36...6a6413b526
@@ -26,7 +26,7 @@ import firesim.configs.MemModelKey
|
||||
import tracegen.{TraceGenSystemModuleImp}
|
||||
import cva6.CVA6Tile
|
||||
|
||||
import barstools.iocell.chisel._
|
||||
import chipyard.iocell._
|
||||
import chipyard.iobinders._
|
||||
import chipyard._
|
||||
import chipyard.harness._
|
||||
|
||||
@@ -367,3 +367,11 @@ class FireSimRadianceClusterSynConfig extends Config(
|
||||
new WithDefaultMemModel ++
|
||||
new WithFireSimConfigTweaks ++
|
||||
new chipyard.RadianceClusterSynConfig)
|
||||
|
||||
class FireSimLargeBoomSV39CospikeConfig extends Config(
|
||||
new firesim.firesim.WithCospikeBridge ++
|
||||
new WithDefaultFireSimBridges ++
|
||||
new WithDefaultMemModel ++
|
||||
new WithFireSimConfigTweaks++
|
||||
new chipyard.config.WithSV39 ++
|
||||
new chipyard.LargeBoomV3Config)
|
||||
|
||||
Submodule generators/gemmini updated: 5bcbead0ad...8a9c423900
Submodule generators/hwacha deleted from bf799dc482
Submodule generators/ibex updated: c2174aba4f...89c19c2d7b
Submodule generators/icenet updated: ab30e23e8e...969bc8f9a0
Submodule generators/mempress updated: 415f55b583...0b362f9031
Submodule generators/riscv-sodor updated: bbfc3c3510...ca0431493e
Submodule generators/rocket-chip updated: 8c8b3f5dcf...cf654499ab
Submodule generators/rocket-chip-inclusive-cache updated: 1332d2268a...45d184f2fd
Submodule generators/sha3 deleted from 2d38585d64
Reference in New Issue
Block a user