Merge branch 'main' of https://github.com/ucb-bar/chipyard into ucb-bar-main

This commit is contained in:
Richard Yan
2024-05-15 23:22:20 -07:00
142 changed files with 3775 additions and 9699 deletions

View 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

View File

@@ -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))

View File

@@ -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)
:*= _)

View File

@@ -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

View File

@@ -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

View File

@@ -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
)

View File

@@ -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) ++

View File

@@ -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)

View File

@@ -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(

View File

@@ -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)))
})

View File

@@ -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 =>

View File

@@ -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)

View File

@@ -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; }
})

View File

@@ -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._

View File

@@ -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)
})

View File

@@ -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) => {

View File

@@ -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}

View File

@@ -99,6 +99,7 @@ trait HasHarnessInstantiators {
if (p(DontTouchChipTopPorts)) {
duts.map(_ match {
case d: DontTouch => d.dontTouchPorts()
case _ =>
})
}

View File

@@ -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,

View File

@@ -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}

View 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
}

View 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.") }
}
}
}

View File

@@ -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")
)
)
}

View File

@@ -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))
}

View File

@@ -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
}
}

View File

@@ -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
}

View File

@@ -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
}
}

View File

@@ -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))
}
}
}
}

View File

@@ -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
}
}

View File

@@ -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
}
}

View File

@@ -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
}
}

View File

@@ -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
}
}

View File

@@ -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
}

View File

@@ -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
}
}

View File

@@ -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
}
}

View File

@@ -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._

View File

@@ -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/sha3 deleted from 2d38585d64