1
0

Merge remote-tracking branch 'origin/master' into rxia-testharness-refactor

This commit is contained in:
Richard Xia 2016-09-16 17:10:52 -07:00
commit 63f13ae7ce
33 changed files with 632 additions and 337 deletions

@ -1 +1 @@
Subproject commit 2ff229dac5f915e7f583cbf9cc8118674a4e52a5
Subproject commit dda64c1dee16b5da15ac690bd3cd6759c3d5c032

2
firrtl

@ -1 +1 @@
Subproject commit 7c38199ce7a5d9dd7e27ffbb9b2b2770b972ed94
Subproject commit 726c808375fe513c70376bf05e76dd938e578bf9

View File

@ -139,7 +139,7 @@ class BaseCoreplexConfig extends Config (
else new MESICoherence(site(L2DirectoryRepresentation))),
nManagers = site(NBanksPerMemoryChannel)*site(NMemoryChannels) + 1 /* MMIO */,
nCachingClients = site(NCachedTileLinkPorts),
nCachelessClients = site(NCoreplexExtClients).get + site(NUncachedTileLinkPorts),
nCachelessClients = site(NCoreplexExtClients) + site(NUncachedTileLinkPorts),
maxClientXacts = max_int(
// L1 cache
site(DCacheKey).nMSHRs + 1 /* IOMSHR */,
@ -170,7 +170,7 @@ class BaseCoreplexConfig extends Config (
TileLinkParameters(
coherencePolicy = new MICoherence(
new NullRepresentation(site(NBanksPerMemoryChannel))),
nManagers = site(GlobalAddrMap).get.subMap("io").numSlaves,
nManagers = 1,
nCachingClients = 0,
nCachelessClients = 1,
maxClientXacts = 4,

View File

@ -32,7 +32,7 @@ trait HasCoreplexParameters {
lazy val innerParams = p.alterPartial({ case TLId => "L1toL2" })
lazy val outermostParams = p.alterPartial({ case TLId => "Outermost" })
lazy val outermostMMIOParams = p.alterPartial({ case TLId => "MMIO_Outermost" })
lazy val globalAddrMap = p(rocketchip.GlobalAddrMap).get
lazy val globalAddrMap = p(rocketchip.GlobalAddrMap)
}
case class CoreplexConfig(
@ -56,7 +56,7 @@ abstract class Coreplex(implicit val p: Parameters, implicit val c: CoreplexConf
val slave = Vec(c.nSlaves, new ClientUncachedTileLinkIO()(innerParams)).flip
val interrupts = Vec(c.nExtInterrupts, Bool()).asInput
val debug = new DebugBusIO()(p).flip
val prci = Vec(c.nTiles, new PRCITileIO).flip
val clint = Vec(c.nTiles, new CoreplexLocalInterrupts).asInput
val success = Bool(OUTPUT)
}
@ -149,8 +149,8 @@ class DefaultCoreplex(tp: Parameters, tc: CoreplexConfig) extends Coreplex()(tp,
// connect coreplex-internal interrupts to tiles
for (((tile, tileReset), i) <- (tileList zip tileResets) zipWithIndex) {
tileReset := io.prci(i).reset
tile.io.interrupts := io.prci(i).interrupts
tileReset := reset // TODO should tiles be reset separately from coreplex?
tile.io.interrupts := io.clint(i)
tile.io.interrupts.meip := plic.io.harts(plic.cfg.context(i, 'M'))
tile.io.interrupts.seip.foreach(_ := plic.io.harts(plic.cfg.context(i, 'S')))
tile.io.interrupts.debug := debugModule.io.debugInterrupts(i)

View File

@ -338,7 +338,7 @@ class ComparatorSink(implicit val p: Parameters) extends Module
assert (g.is_builtin_type, "grant not builtin")
assert (base.g_type === g.g_type, "g_type mismatch")
assert (base.addr_beat === g.addr_beat || !g.hasData(), "addr_beat mismatch")
assert (base.addr_beat === g.addr_beat || !g.hasMultibeatData(), "addr_beat mismatch")
assert (base.data === g.data || !g.hasData(), "data mismatch")
assert_conds.zipWithIndex.foreach { case (cond, i) =>

View File

@ -92,7 +92,7 @@ class WithGroundTest extends Config(
else new MESICoherence(site(L2DirectoryRepresentation))),
nManagers = site(NBanksPerMemoryChannel)*site(NMemoryChannels) + 1,
nCachingClients = site(NCachedTileLinkPorts),
nCachelessClients = site(NCoreplexExtClients).get + site(NUncachedTileLinkPorts),
nCachelessClients = site(NCoreplexExtClients) + site(NUncachedTileLinkPorts),
maxClientXacts = ((site(DCacheKey).nMSHRs + 1) +:
site(GroundTestKey).map(_.maxXacts))
.reduce(max(_, _)),
@ -137,11 +137,11 @@ class WithComparator extends Config(
case BuildGroundTest =>
(p: Parameters) => Module(new ComparatorCore()(p))
case ComparatorKey => ComparatorParameters(
targets = Seq("mem", "io:ext:testram").map(name =>
site(GlobalAddrMap).get(name).start.longValue),
targets = Seq("mem", "io:ext:TL2:testram").map(name =>
site(GlobalAddrMap)(name).start.longValue),
width = 8,
operations = 1000,
atomics = site(UseAtomics),
atomics = false, // !!! re-enable soon: site(UseAtomics),
prefetches = site("COMPARATOR_PREFETCHES"))
case FPUConfig => None
case UseAtomics => false
@ -168,7 +168,7 @@ class WithMemtest extends Config(
}
case GeneratorKey => GeneratorParameters(
maxRequests = 128,
startAddress = site(GlobalAddrMap).get("mem").start)
startAddress = site(GlobalAddrMap)("mem").start)
case BuildGroundTest =>
(p: Parameters) => Module(new GeneratorTest()(p))
case _ => throw new CDEMatchError
@ -228,7 +228,7 @@ class WithNastiConverterTest extends Config(
}
case GeneratorKey => GeneratorParameters(
maxRequests = 128,
startAddress = site(GlobalAddrMap).get("mem").start)
startAddress = site(GlobalAddrMap)("mem").start)
case BuildGroundTest =>
(p: Parameters) => Module(new NastiConverterTest()(p))
case _ => throw new CDEMatchError
@ -248,7 +248,7 @@ class WithTraceGen extends Config(
val nSets = 32 // L2 NSets
val nWays = 1
val blockOffset = site(CacheBlockOffsetBits)
val baseAddr = site(GlobalAddrMap).get("mem").start
val baseAddr = site(GlobalAddrMap)("mem").start
val nBeats = site(MIFDataBeats)
List.tabulate(4 * nWays) { i =>
Seq.tabulate(nBeats) { j => (j * 8) + ((i * nSets) << blockOffset) }
@ -260,6 +260,7 @@ class WithTraceGen extends Config(
knobValues = {
case "L1D_SETS" => 16
case "L1D_WAYS" => 1
case _ => throw new CDEMatchError
})
class WithPCIeMockupTest extends Config(
@ -270,7 +271,7 @@ class WithPCIeMockupTest extends Config(
GroundTestTileSettings(1))
case GeneratorKey => GeneratorParameters(
maxRequests = 128,
startAddress = site(GlobalAddrMap).get("mem").start)
startAddress = site(GlobalAddrMap)("mem").start)
case BuildGroundTest =>
(p: Parameters) => p(TileId) match {
case 0 => Module(new GeneratorTest()(p))
@ -304,7 +305,7 @@ class WithDirectComparator extends Config(
targets = Seq(0L, 0x100L),
width = 8,
operations = 1000,
atomics = site(UseAtomics),
atomics = false, // !!! re-enable soon: site(UseAtomics),
prefetches = site("COMPARATOR_PREFETCHES"))
case FPUConfig => None
case UseAtomics => false

View File

@ -72,7 +72,7 @@ class IOGetAfterPutBlockRegression(implicit p: Parameters) extends Regression()(
io.mem.grant.ready := Bool(true)
io.cache.req.valid := !get_sent && started
io.cache.req.bits.addr := UInt(addrMap("io:ext:bootrom").start)
io.cache.req.bits.addr := UInt(addrMap("io:ext:TL2:bootrom").start)
io.cache.req.bits.typ := UInt(log2Ceil(32 / 8))
io.cache.req.bits.cmd := M_XRD
io.cache.req.bits.tag := UInt(0)

View File

@ -12,7 +12,7 @@ trait HasAddrMapParameters {
implicit val p: Parameters
val paddrBits = p(PAddrBits)
def addrMap = p(rocketchip.GlobalAddrMap).get
def addrMap = p(rocketchip.GlobalAddrMap)
}
case class MemAttr(prot: Int, cacheable: Boolean = false)

View File

@ -20,9 +20,6 @@ import cde.{Parameters, Config, Dump, Knob, CDEMatchError}
class BasePlatformConfig extends Config(
topDefinitions = {
val configString = new GlobalVariable[String]
val globalAddrMap = new GlobalVariable[AddrMap]
val nCoreplexExtClients = new GlobalVariable[Int]
(pname,site,here) => {
type PF = PartialFunction[Any,Any]
def findBy(sname:Any):Any = here[PF](site[Any](sname))(pname)
@ -55,7 +52,6 @@ class BasePlatformConfig extends Config(
case NExtMMIOTLChannels => 0
case AsyncBusChannels => false
case NExtBusAXIChannels => 0
case NCoreplexExtClients => nCoreplexExtClients
case HastiId => "Ext"
case HastiKey("TL") =>
HastiParameters(
@ -69,8 +65,6 @@ class BasePlatformConfig extends Config(
case NMemoryChannels => Dump("N_MEM_CHANNELS", 1)
case TMemoryChannels => BusType.AXI
case ExtMemSize => Dump("MEM_SIZE", 0x10000000L)
case ConfigString => configString
case GlobalAddrMap => globalAddrMap
case RTCPeriod => 100 // gives 10 MHz RTC assuming 1 GHz uncore clock
case BuildExampleTop =>
(p: Parameters) => uncore.tilelink2.LazyModule(new ExampleTop(p))
@ -152,6 +146,7 @@ class RoccExampleConfig extends Config(new WithRoccExample ++ new BaseConfig)
class WithMIFDataBits(n: Int) extends Config(
(pname, site, here) => pname match {
case MIFDataBits => Dump("MIF_DATA_BITS", n)
case _ => throw new CDEMatchError
})
class MIF128BitConfig extends Config(
@ -182,12 +177,14 @@ class TinyConfig extends Config(
class WithAsyncDebug extends Config (
(pname, site, here) => pname match {
case AsyncDebugBus => true
case AsyncDebugBus => true
case _ => throw new CDEMatchError
}
)
class WithJtagDTM extends Config (
(pname, site, here) => pname match {
case IncludeJtagDTM => true
case IncludeJtagDTM => true
case _ => throw new CDEMatchError
}
)

View File

@ -56,6 +56,10 @@ trait HasGeneratorUtilities {
}
}
object ConfigStringOutput {
var contents: Option[String] = None
}
trait Generator extends App with HasGeneratorUtilities {
lazy val names = {
require(args.size == 5, "Usage: sbt> " +
@ -67,20 +71,25 @@ trait Generator extends App with HasGeneratorUtilities {
configProject = args(3),
configs = args(4))
}
lazy val td = names.targetDir
lazy val config = getConfig(names)
lazy val world = config.toInstance
lazy val params = Parameters.root(world)
lazy val circuit = elaborate(names, params)
lazy val longName = names.topModuleClass + "." + names.configs
def writeOutputFiles() {
TestGeneration.addSuite(new RegressionTestSuite(params(RegressionTestNames)))
writeOutputFile(td, s"$longName.d", TestGeneration.generateMakefrag) // Coreplex-specific test suites
writeOutputFile(td, s"$longName.prm", ParameterDump.getDump) // Parameters flagged with Dump()
writeOutputFile(td, s"${names.configs}.knb", world.getKnobs) // Knobs for DSE
writeOutputFile(td, s"${names.configs}.cst", world.getConstraints) // Constraints for DSE
ConfigStringOutput.contents.foreach(c => writeOutputFile(td, s"${names.configs}.cfg", c)) // String for software
}
}
object RocketChipGenerator extends Generator {
val longName = names.topModuleClass + "." + names.configs
val td = names.targetDir
Driver.dumpFirrtl(circuit, Some(new File(td, s"$longName.fir"))) // FIRRTL
TestGeneration.addSuite(new RegressionTestSuite(params(RegressionTestNames)))
writeOutputFile(td, s"$longName.d", TestGeneration.generateMakefrag) // Coreplex-specific test suites
writeOutputFile(td, s"$longName.prm", ParameterDump.getDump) // Parameters flagged with Dump()
writeOutputFile(td, s"${names.configs}.knb", world.getKnobs) // Knobs for DSE
writeOutputFile(td, s"${names.configs}.cst", world.getConstraints) // Constraints for DSE
writeOutputFile(td, s"${names.configs}.cfg", params(ConfigString).get) // String for software
writeOutputFiles()
}

View File

@ -7,11 +7,13 @@ import cde.{Parameters, Field}
import junctions._
import junctions.NastiConstants._
import uncore.tilelink._
import uncore.tilelink2.{LazyModule, LazyModuleImp}
import uncore.tilelink2._
import uncore.converters._
import uncore.devices._
import uncore.util._
import rocket.Util._
import rocket.XLen
import scala.math.max
import coreplex._
/** Options for memory bus interface */
@ -202,10 +204,10 @@ trait PeripheryMasterMMIOModule extends HasPeripheryParameters {
implicit val p: Parameters
val outer: PeripheryMasterMMIO
val io: PeripheryMasterMMIOBundle
val mmioNetwork: Option[TileLinkRecursiveInterconnect]
val mmioNetwork: TileLinkRecursiveInterconnect
val mmio_ports = p(ExtMMIOPorts) map { port =>
TileLinkWidthAdapter(mmioNetwork.get.port(port.name), "MMIO_Outermost")
TileLinkWidthAdapter(mmioNetwork.port(port.name), "MMIO_Outermost")
}
val mmio_axi_start = 0
@ -277,37 +279,47 @@ trait PeripherySlaveModule extends HasPeripheryParameters {
/////
/** Always-ON block */
trait PeripheryAON extends LazyModule {
trait PeripheryCoreplexLocalInterrupter extends LazyModule with HasPeripheryParameters {
implicit val p: Parameters
val peripheryBus: TLXbar
// CoreplexLocalInterrupter must be at least 64b if XLen >= 64
val beatBytes = (innerMMIOParams(XLen) min 64) / 8
val clintConfig = CoreplexLocalInterrupterConfig(beatBytes)
val clint = LazyModule(new CoreplexLocalInterrupter(clintConfig)(innerMMIOParams))
// The periphery bus is 32-bit, so we may need to adapt its width to XLen
clint.node := TLFragmenter(TLWidthWidget(peripheryBus.node, 4), beatBytes, 256)
// TL1 legacy
val pDevices: ResourceManager[AddrMapEntry]
pDevices.add(AddrMapEntry("prci", MemSize(0x4000000, MemAttr(AddrMapProt.RW))))
pDevices.add(AddrMapEntry("clint", MemRange(clintConfig.address, clintConfig.size, MemAttr(AddrMapProt.RW))))
}
trait PeripheryAONBundle {
trait PeripheryCoreplexLocalInterrupterBundle {
implicit val p: Parameters
}
trait PeripheryAONModule extends HasPeripheryParameters {
trait PeripheryCoreplexLocalInterrupterModule extends HasPeripheryParameters {
implicit val p: Parameters
val outer: PeripheryAON
val io: PeripheryAONBundle
val mmioNetwork: Option[TileLinkRecursiveInterconnect]
val outer: PeripheryCoreplexLocalInterrupter
val io: PeripheryCoreplexLocalInterrupterBundle
val coreplex: Coreplex
val prci = Module(new PRCI()(innerMMIOParams))
prci.io.rtcTick := Counter(p(RTCPeriod)).inc()
prci.io.tl <> mmioNetwork.get.port("prci")
coreplex.io.prci <> prci.io.tiles
outer.clint.module.io.rtcTick := Counter(p(RTCPeriod)).inc()
coreplex.io.clint <> outer.clint.module.io.tiles
}
/////
trait PeripheryBootROM extends LazyModule {
implicit val p: Parameters
val pDevices: ResourceManager[AddrMapEntry]
val peripheryBus: TLXbar
val rom = LazyModule(new TLROM(0x1000, 0x1000, GenerateBootROM(p)))
rom.node := TLFragmenter(peripheryBus.node, 4, 256)
// TL1 legacy address map
val pDevices: ResourceManager[AddrMapEntry]
pDevices.add(AddrMapEntry("bootrom", MemRange(0x1000, 4096, MemAttr(AddrMapProt.RX))))
}
@ -319,20 +331,23 @@ trait PeripheryBootROMModule extends HasPeripheryParameters {
implicit val p: Parameters
val outer: PeripheryBootROM
val io: PeripheryBootROMBundle
val mmioNetwork: Option[TileLinkRecursiveInterconnect]
val bootROM = Module(new ROMSlave(GenerateBootROM(p))(innerMMIOParams))
bootROM.io <> mmioNetwork.get.port("bootrom")
}
/////
trait PeripheryTestRAM extends LazyModule {
implicit val p: Parameters
val pDevices: ResourceManager[AddrMapEntry]
val peripheryBus: TLXbar
val ramBase = 0x52000000
val ramSize = 0x1000
pDevices.add(AddrMapEntry("testram", MemSize(ramSize, MemAttr(AddrMapProt.RW))))
val sram = LazyModule(new TLRAM(AddressSet(ramBase, ramSize-1)))
sram.node := TLFragmenter(peripheryBus.node, 4, 256)
// TL1 legacy address map
val pDevices: ResourceManager[AddrMapEntry]
pDevices.add(AddrMapEntry("testram", MemRange(ramBase, ramSize, MemAttr(AddrMapProt.RW))))
}
trait PeripheryTestRAMBundle {
@ -342,22 +357,16 @@ trait PeripheryTestRAMBundle {
trait PeripheryTestRAMModule extends HasPeripheryParameters {
implicit val p: Parameters
val outer: PeripheryTestRAM
val io: PeripheryTestRAMBundle
val mmioNetwork: Option[TileLinkRecursiveInterconnect]
val testram = Module(new TileLinkTestRAM(outer.ramSize)(innerMMIOParams))
testram.io <> mmioNetwork.get.port("testram")
}
/////
trait PeripheryTestBusMaster extends LazyModule {
implicit val p: Parameters
val pBusMasters: RangeManager
val pDevices: ResourceManager[AddrMapEntry]
val peripheryBus: TLXbar
pBusMasters.add("busmaster", 1)
pDevices.add(AddrMapEntry("busmaster", MemSize(4096, MemAttr(AddrMapProt.RW))))
val fuzzer = LazyModule(new TLFuzzer(5000))
peripheryBus.node := fuzzer.node
}
trait PeripheryTestBusMasterBundle {
@ -367,16 +376,4 @@ trait PeripheryTestBusMasterBundle {
trait PeripheryTestBusMasterModule {
implicit val p: Parameters
val outer: PeripheryTestBusMaster
val io: PeripheryTestBusMasterBundle
val mmioNetwork: Option[TileLinkRecursiveInterconnect]
val coreplex: Coreplex
val busmaster = Module(new groundtest.ExampleBusMaster()(p))
busmaster.io.mmio <> mmioNetwork.get.port("busmaster")
{
val r = outer.pBusMasters.range("busmaster")
require(r._2 - r._1 == 1, "RangeManager should return 1 slot")
coreplex.io.slave(r._1) <> busmaster.io.mem
}
}

View File

@ -12,11 +12,12 @@ import junctions.NastiConstants._
case object BuildExampleTop extends Field[Parameters => ExampleTop]
case object SimMemLatency extends Field[Int]
class TestHarness(implicit val p: Parameters) extends Module with HasAddrMapParameters {
class TestHarness(q: Parameters) extends Module {
val io = new Bundle {
val success = Bool(OUTPUT)
}
val dut = p(BuildExampleTop)(p).module
val dut = q(BuildExampleTop)(q).module
implicit val p = dut.p
// This test harness isn't especially flexible yet
require(dut.io.mem_clk.isEmpty)
@ -34,7 +35,7 @@ class TestHarness(implicit val p: Parameters) extends Module with HasAddrMapPara
int := false
if (dut.io.mem_axi.nonEmpty) {
val memSize = addrMap("mem").size
val memSize = p(GlobalAddrMap)("mem").size
require(memSize % dut.io.mem_axi.size == 0)
for (axi <- dut.io.mem_axi) {
val mem = Module(new SimAXIMem(memSize / dut.io.mem_axi.size))

View File

@ -6,7 +6,7 @@ import Chisel._
import cde.{Parameters, Field}
import junctions._
import uncore.tilelink._
import uncore.tilelink2.{LazyModule, LazyModuleImp}
import uncore.tilelink2._
import uncore.devices._
import util.ParameterizedBundle
import rocket._
@ -14,18 +14,41 @@ import rocket.Util._
import coreplex._
// the following parameters will be refactored properly with TL2
case object GlobalAddrMap extends Field[GlobalVariable[AddrMap]]
case object ConfigString extends Field[GlobalVariable[String]]
case object NCoreplexExtClients extends Field[GlobalVariable[Int]]
case object GlobalAddrMap extends Field[AddrMap]
case object ConfigString extends Field[String]
case object NCoreplexExtClients extends Field[Int]
/** Function for building Coreplex */
case object BuildCoreplex extends Field[(Parameters, CoreplexConfig) => Coreplex]
/** Base Top with no Periphery */
abstract class BaseTop(val p: Parameters) extends LazyModule {
abstract class BaseTop(q: Parameters) extends LazyModule {
// the following variables will be refactored properly with TL2
val pInterrupts = new RangeManager
val pBusMasters = new RangeManager
val pDevices = new ResourceManager[AddrMapEntry]
lazy val c = CoreplexConfig(
nTiles = q(NTiles),
nExtInterrupts = pInterrupts.sum,
nSlaves = pBusMasters.sum,
nMemChannels = q(NMemoryChannels),
hasSupervisor = q(UseVM),
hasExtMMIOPort = true
)
lazy val genGlobalAddrMap = GenerateGlobalAddrMap(q, pDevices.get)
private val qWithMap = q.alterPartial({case GlobalAddrMap => genGlobalAddrMap})
lazy val genConfigString = GenerateConfigString(qWithMap, c, pDevices.get)
implicit val p = qWithMap.alterPartial({
case ConfigString => genConfigString
case NCoreplexExtClients => pBusMasters.sum})
// Add a peripheral bus
val peripheryBus = LazyModule(new TLXbar)
val legacy = LazyModule(new TLLegacy()(p.alterPartial({ case TLId => "L2toMMIO" })))
peripheryBus.node := TLBuffer(TLWidthWidget(TLHintHandler(legacy.node), legacy.tlDataBytes))
}
class BaseTopBundle(val p: Parameters, val c: Coreplex) extends ParameterizedBundle()(p) {
@ -35,24 +58,19 @@ class BaseTopBundle(val p: Parameters, val c: Coreplex) extends ParameterizedBun
class BaseTopModule[+L <: BaseTop, +B <: BaseTopBundle](val p: Parameters, l: L, b: Coreplex => B) extends LazyModuleImp(l) {
val outer: L = l
val c = CoreplexConfig(
nTiles = p(NTiles),
nExtInterrupts = outer.pInterrupts.sum,
nSlaves = outer.pBusMasters.sum,
nMemChannels = p(NMemoryChannels),
hasSupervisor = p(UseVM),
hasExtMMIOPort = !(outer.pDevices.get.isEmpty && p(ExtMMIOPorts).isEmpty)
)
val coreplex = p(BuildCoreplex)(p, outer.c)
val io: B = b(coreplex)
def genGlobalAddrMap = GenerateGlobalAddrMap(p, outer.pDevices.get)
def genConfigString = GenerateConfigString(p, c, outer.pDevices.get)
io.success := coreplex.io.success
p(NCoreplexExtClients).assign(outer.pBusMasters.sum)
p(GlobalAddrMap).assign(genGlobalAddrMap)
p(ConfigString).assign(genConfigString)
val mmioNetwork =
Module(new TileLinkRecursiveInterconnect(1, p(GlobalAddrMap).subMap("io:ext"))(
p.alterPartial({ case TLId => "L2toMMIO" })))
mmioNetwork.io.in.head <> coreplex.io.master.mmio.get
outer.legacy.module.io.legacy <> mmioNetwork.port("TL2")
println("Generated Address Map")
for (entry <- p(GlobalAddrMap).get.flatten) {
for (entry <- p(GlobalAddrMap).flatten) {
val name = entry.name
val start = entry.region.start
val end = entry.region.start + entry.region.size - 1
@ -60,36 +78,27 @@ class BaseTopModule[+L <: BaseTop, +B <: BaseTopBundle](val p: Parameters, l: L,
}
println("Generated Configuration String")
println(p(ConfigString).get)
val coreplex = p(BuildCoreplex)(p, c)
val io: B = b(coreplex)
io.success := coreplex.io.success
val mmioNetwork = c.hasExtMMIOPort.option(
Module(new TileLinkRecursiveInterconnect(1, p(GlobalAddrMap).get.subMap("io:ext"))(
p.alterPartial({ case TLId => "L2toMMIO" }))))
mmioNetwork.foreach { _.io.in.head <> coreplex.io.master.mmio.get }
println(p(ConfigString))
ConfigStringOutput.contents = Some(p(ConfigString))
}
/** Example Top with Periphery */
class ExampleTop(p: Parameters) extends BaseTop(p)
with PeripheryBootROM with PeripheryDebug with PeripheryExtInterrupts with PeripheryAON
class ExampleTop(q: Parameters) extends BaseTop(q)
with PeripheryBootROM with PeripheryDebug with PeripheryExtInterrupts with PeripheryCoreplexLocalInterrupter
with PeripheryMasterMem with PeripheryMasterMMIO with PeripherySlave {
override lazy val module = Module(new ExampleTopModule(p, this, new ExampleTopBundle(p, _)))
}
class ExampleTopBundle(p: Parameters, c: Coreplex) extends BaseTopBundle(p, c)
with PeripheryBootROMBundle with PeripheryDebugBundle with PeripheryExtInterruptsBundle with PeripheryAONBundle
with PeripheryBootROMBundle with PeripheryDebugBundle with PeripheryExtInterruptsBundle with PeripheryCoreplexLocalInterrupterBundle
with PeripheryMasterMemBundle with PeripheryMasterMMIOBundle with PeripherySlaveBundle
class ExampleTopModule[+L <: ExampleTop, +B <: ExampleTopBundle](p: Parameters, l: L, b: Coreplex => B) extends BaseTopModule(p, l, b)
with PeripheryBootROMModule with PeripheryDebugModule with PeripheryExtInterruptsModule with PeripheryAONModule
with PeripheryBootROMModule with PeripheryDebugModule with PeripheryExtInterruptsModule with PeripheryCoreplexLocalInterrupterModule
with PeripheryMasterMemModule with PeripheryMasterMMIOModule with PeripherySlaveModule
/** Example Top with TestRAM */
class ExampleTopWithTestRAM(p: Parameters) extends ExampleTop(p)
class ExampleTopWithTestRAM(q: Parameters) extends ExampleTop(q)
with PeripheryTestRAM {
override lazy val module = Module(new ExampleTopWithTestRAMModule(p, this, new ExampleTopWithTestRAMBundle(p, _)))
}

View File

@ -64,10 +64,8 @@ object GenerateGlobalAddrMap {
new AddrMap(entries)
}
lazy val extIOAddrMap = new AddrMap(
pDevicesEntries ++ p(ExtMMIOPorts),
start = BigInt("50000000", 16),
collapse = true)
lazy val tl2AddrMap = new AddrMap(pDevicesEntries, collapse = true)
lazy val extIOAddrMap = new AddrMap(AddrMapEntry("TL2", tl2AddrMap) +: p(ExtMMIOPorts), collapse = true)
val memBase = 0x80000000L
val memSize = p(ExtMemSize)
@ -83,9 +81,9 @@ object GenerateGlobalAddrMap {
object GenerateConfigString {
def apply(p: Parameters, c: CoreplexConfig, pDevicesEntries: Seq[AddrMapEntry]) = {
val addrMap = p(GlobalAddrMap).get
val addrMap = p(GlobalAddrMap)
val plicAddr = addrMap("io:int:plic").start
val prciAddr = addrMap("io:ext:prci").start
val clint = CoreplexLocalInterrupterConfig(0, addrMap("io:ext:TL2:clint").start)
val xLen = p(XLen)
val res = new StringBuilder
res append "plic {\n"
@ -94,7 +92,7 @@ object GenerateConfigString {
res append s" ndevs ${c.plicKey.nDevices};\n"
res append "};\n"
res append "rtc {\n"
res append s" addr 0x${(prciAddr + PRCI.time).toString(16)};\n"
res append s" addr 0x${clint.timeAddress.toString(16)};\n"
res append "};\n"
if (addrMap contains "mem") {
res append "ram {\n"
@ -117,8 +115,8 @@ object GenerateConfigString {
res append s" $i {\n"
res append " 0 {\n"
res append s" isa $isa;\n"
res append s" timecmp 0x${(prciAddr + PRCI.timecmp(i)).toString(16)};\n"
res append s" ipi 0x${(prciAddr + PRCI.msip(i)).toString(16)};\n"
res append s" timecmp 0x${clint.timecmpAddress(i).toString(16)};\n"
res append s" ipi 0x${clint.msipAddress(i).toString(16)};\n"
res append s" plic {\n"
res append s" m {\n"
res append s" ie 0x${(plicAddr + c.plicKey.enableAddr(i, 'M')).toString(16)};\n"
@ -138,7 +136,7 @@ object GenerateConfigString {
}
res append "};\n"
pDevicesEntries foreach { entry =>
val region = addrMap("io:ext:" + entry.name)
val region = addrMap("io:ext:TL2:" + entry.name)
res append s"${entry.name} {\n"
res append s" addr 0x${region.start.toString(16)};\n"
res append s" size 0x${region.size.toString(16)}; \n"
@ -158,8 +156,8 @@ object GenerateBootROM {
// for now, have the reset vector jump straight to memory
val memBase = (
if (p(GlobalAddrMap).get contains "mem") p(GlobalAddrMap).get("mem")
else p(GlobalAddrMap).get("io:int:dmem0")
if (p(GlobalAddrMap) contains "mem") p(GlobalAddrMap)("mem")
else p(GlobalAddrMap)("io:int:dmem0")
).start
val resetToMemDist = memBase - p(ResetVector)
require(resetToMemDist == (resetToMemDist.toInt >> 12 << 12))
@ -168,6 +166,6 @@ object GenerateBootROM {
require(rom.getInt(12) == 0,
"Config string address position should not be occupied by code")
rom.putInt(12, configStringAddr)
rom.array() ++ (p(ConfigString).get.getBytes.toSeq)
rom.array() ++ (p(ConfigString).getBytes.toSeq)
}
}

View File

@ -1,7 +1,7 @@
package uncore
import Chisel._
import cde.{Config, Parameters, ParameterDump, Knob, Dump}
import cde.{Config, Parameters, ParameterDump, Knob, Dump, CDEMatchError}
import junctions.PAddrBits
import uncore.tilelink._
import uncore.agents._
@ -85,6 +85,7 @@ class DefaultL2Config extends Config (
case ECCCode => None
case AmoAluOperandBits => 64
case SplitMetadata => false
case _ => throw new CDEMatchError
// case XLen => 128
}},
knobValues = {
@ -93,22 +94,24 @@ class DefaultL2Config extends Config (
case "NTILES" => 2
case "N_CACHED_TILES" => 2
case "L2_CAPACITY_IN_KB" => 256
case _ => throw new CDEMatchError
}
)
class WithPLRU extends Config(
(pname, site, here) => pname match {
case L2Replacer => () => new SeqPLRU(site(NSets), site(NWays))
case _ => throw new CDEMatchError
})
class PLRUL2Config extends Config(new WithPLRU ++ new DefaultL2Config)
class With1L2Ways extends Config(knobValues = { case "L2_WAYS" => 1 })
class With2L2Ways extends Config(knobValues = { case "L2_WAYS" => 2 })
class With4L2Ways extends Config(knobValues = { case "L2_WAYS" => 4 })
class With1L2Ways extends Config(knobValues = { case "L2_WAYS" => 1; case _ => throw new CDEMatchError })
class With2L2Ways extends Config(knobValues = { case "L2_WAYS" => 2; case _ => throw new CDEMatchError })
class With4L2Ways extends Config(knobValues = { case "L2_WAYS" => 4; case _ => throw new CDEMatchError })
class With1Cached extends Config(knobValues = { case "N_CACHED_TILES" => 1 })
class With2Cached extends Config(knobValues = { case "N_CACHED_TILES" => 2 })
class With1Cached extends Config(knobValues = { case "N_CACHED_TILES" => 1; case _ => throw new CDEMatchError })
class With2Cached extends Config(knobValues = { case "N_CACHED_TILES" => 2; case _ => throw new CDEMatchError })
class W1Cached1WaysConfig extends Config(new With1L2Ways ++ new With1Cached ++ new DefaultL2Config)

View File

@ -6,114 +6,84 @@ import Chisel._
import rocket.Util._
import junctions._
import junctions.NastiConstants._
import uncore.tilelink._
import uncore.tilelink2._
import uncore.util._
import scala.math.{min,max}
import cde.{Parameters, Field}
/** Number of tiles */
case object NTiles extends Field[Int]
class PRCITileIO(implicit p: Parameters) extends Bundle {
val reset = Bool(OUTPUT)
val interrupts = new Bundle {
val mtip = Bool()
val msip = Bool()
}
override def cloneType: this.type = new PRCITileIO().asInstanceOf[this.type]
class CoreplexLocalInterrupts extends Bundle {
val mtip = Bool()
val msip = Bool()
}
object PRCI {
def msip(hart: Int) = hart * msipBytes
def timecmp(hart: Int) = 0x4000 + hart * timecmpBytes
def time = 0xbff8
case class CoreplexLocalInterrupterConfig(beatBytes: Int, address: BigInt = 0x44000000) {
def msipOffset(hart: Int) = hart * msipBytes
def msipAddress(hart: Int) = address + msipOffset(hart)
def timecmpOffset(hart: Int) = 0x4000 + hart * timecmpBytes
def timecmpAddress(hart: Int) = address + timecmpOffset(hart)
def timeOffset = 0xbff8
def timeAddress = address + timeOffset
def msipBytes = 4
def timecmpBytes = 8
def size = 0xc000
def size = 0x10000
}
trait MixCoreplexLocalInterrupterParameters {
val params: (CoreplexLocalInterrupterConfig, Parameters)
val c = params._1
implicit val p = params._2
}
trait CoreplexLocalInterrupterBundle extends Bundle with MixCoreplexLocalInterrupterParameters {
val tiles = Vec(p(NTiles), new CoreplexLocalInterrupts).asOutput
val rtcTick = Bool(INPUT)
}
trait CoreplexLocalInterrupterModule extends Module with HasRegMap with MixCoreplexLocalInterrupterParameters {
val io: CoreplexLocalInterrupterBundle
val timeWidth = 64
val time = Reg(init=UInt(0, width = timeWidth))
when (io.rtcTick) { time := time + UInt(1) }
val timecmp = Seq.fill(p(NTiles)) { Reg(UInt(width = timeWidth)) }
val ipi = Seq.fill(p(NTiles)) { RegInit(UInt(0, width = 1)) }
for ((tile, i) <- io.tiles zipWithIndex) {
tile.msip := ipi(i)(0)
tile.mtip := time >= timecmp(i)
}
def pad = RegField(8) // each use is a new field
val ipi_fields = ipi.map(r => Seq(RegField(1, r), RegField(7), pad, pad, pad)).flatten
val timecmp_fields = timecmp.map(RegField.bytes(_)).flatten
val time_fields = Seq.fill(c.timeOffset % c.beatBytes)(pad) ++ RegField.bytes(time)
/* 0000 msip hart 0
* 0004 msip hart 1
* 4000 mtimecmp hart 0 lo
* 4004 mtimecmp hart 0 hi
* 4008 mtimecmp hart 1 lo
* 400c mtimecmp hart 1 hi
* bff8 mtime lo
* bffc mtime hi
*/
val ipi_base = 0
val timecmp_base = c.timecmpOffset(0) / c.beatBytes
val time_base = c.timeOffset / c.beatBytes
regmap((
RegField.split(ipi_fields, ipi_base, c.beatBytes) ++
RegField.split(timecmp_fields, timecmp_base, c.beatBytes) ++
RegField.split(time_fields, time_base, c.beatBytes)):_*)
}
/** Power, Reset, Clock, Interrupt */
class PRCI(implicit val p: Parameters) extends Module
with HasTileLinkParameters
with HasAddrMapParameters {
val io = new Bundle {
val tl = new ClientUncachedTileLinkIO().flip
val tiles = Vec(p(NTiles), new PRCITileIO)
val rtcTick = Bool(INPUT)
}
val timeWidth = 64
val timecmp = Reg(Vec(p(NTiles), UInt(width = timeWidth)))
val time = Reg(init=UInt(0, timeWidth))
when (io.rtcTick) { time := time + UInt(1) }
val ipi = Reg(init=Vec.fill(p(NTiles))(UInt(0, 32)))
val acq = Queue(io.tl.acquire, 1)
val addr = acq.bits.full_addr()(log2Ceil(PRCI.size)-1,0)
val read = acq.bits.isBuiltInType(Acquire.getType)
val rdata = Wire(init=UInt(0))
io.tl.grant.valid := acq.valid
acq.ready := io.tl.grant.ready
io.tl.grant.bits := Grant(
is_builtin_type = Bool(true),
g_type = acq.bits.getBuiltInGrantType(),
client_xact_id = acq.bits.client_xact_id,
manager_xact_id = UInt(0),
addr_beat = UInt(0),
data = rdata)
when (addr(log2Floor(PRCI.time))) {
require(log2Floor(PRCI.timecmp(p(NTiles)-1)) < log2Floor(PRCI.time))
rdata := store(Seq(time), acq.bits, io.tl.grant.fire())
}.elsewhen (addr >= PRCI.timecmp(0)) {
rdata := store(timecmp, acq.bits, io.tl.grant.fire())
}.otherwise {
rdata := store(ipi, acq.bits, io.tl.grant.fire()) & Fill(tlDataBits/32, UInt(1, 32))
}
for ((tile, i) <- io.tiles zipWithIndex) {
tile.interrupts.msip := ipi(i)(0)
tile.interrupts.mtip := time >= timecmp(i)
tile.reset := reset
}
// TODO generalize these to help other TL slaves
def load(v: Seq[UInt], acq: Acquire): UInt = {
val w = v.head.getWidth
val a = acq.full_addr()
require(isPow2(w) && w >= 8)
if (w > tlDataBits) {
(v(a.extract(log2Ceil(w/8*v.size)-1,log2Ceil(w/8))) >> a.extract(log2Ceil(w/8)-1,log2Ceil(tlDataBytes)))(tlDataBits-1,0)
} else {
val row: Seq[UInt] = for (i <- 0 until v.size by tlDataBits/w)
yield Cat(v.slice(i, i + tlDataBits/w).reverse)
if (row.size == 1) row.head
else row(a(log2Ceil(w/8*v.size)-1,log2Ceil(tlDataBytes)))
}
}
def store(v: Seq[UInt], acq: Acquire, en: Bool): UInt = {
val w = v.head.getWidth
require(isPow2(w) && w >= 8)
val a = acq.full_addr()
val rdata = load(v, acq)
val wdata = (acq.data & acq.full_wmask()) | (rdata & ~acq.full_wmask())
when (en && acq.isBuiltInType(Acquire.putType)) {
if (w <= tlDataBits) {
val word =
if (tlDataBits/w >= v.size) UInt(0)
else a(log2Up(w/8*v.size)-1,log2Up(tlDataBytes))
for (i <- 0 until v.size) when (word === i/(tlDataBits/w)) {
val base = i % (tlDataBits/w)
v(i) := wdata >> (w * (i % (tlDataBits/w)))
}
} else {
val i = a.extract(log2Ceil(w/8*v.size)-1,log2Ceil(w/8))
val mask = FillInterleaved(tlDataBits, UIntToOH(a.extract(log2Ceil(w/8)-1,log2Ceil(tlDataBytes))))
v(i) := (wdata & mask) | (v(i) & ~mask)
}
}
rdata
}
}
// Magic TL2 Incantation to create a TL2 Slave
class CoreplexLocalInterrupter(c: CoreplexLocalInterrupterConfig)(implicit val p: Parameters)
extends TLRegisterRouter(c.address, 0, c.size, None, c.beatBytes, false)(
new TLRegBundle((c, p), _) with CoreplexLocalInterrupterBundle)(
new TLRegModule((c, p), _, _) with CoreplexLocalInterrupterModule)

View File

@ -4,9 +4,46 @@ import Chisel._
import unittest.UnitTest
import junctions._
import uncore.tilelink._
import uncore.tilelink2._
import uncore.util._
import cde.{Parameters, Field}
class TLROM(val base: BigInt, val size: Int, contentsDelayed: => Seq[Byte], beatBytes: Int = 4) extends LazyModule
{
val node = TLManagerNode(beatBytes, TLManagerParameters(
address = List(AddressSet(base, size-1)),
regionType = RegionType.UNCACHED,
supportsGet = TransferSizes(1, beatBytes),
fifoId = Some(0)))
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val in = node.bundleIn
}
val contents = contentsDelayed
require (contents.size <= size)
val in = io.in(0)
val edge = node.edgesIn(0)
val words = (contents ++ Seq.fill(size-contents.size)(0.toByte)).grouped(beatBytes).toSeq
val bigs = words.map(_.foldRight(BigInt(0)){ case (x,y) => (x.toInt & 0xff) | y << 8})
val rom = Vec(bigs.map(x => UInt(x, width = 8*beatBytes)))
in.d.valid := in.a.valid
in.a.ready := in.d.ready
val index = in.a.bits.addr_hi(log2Ceil(size/beatBytes)-1,0)
in.d.bits := edge.AccessAck(in.a.bits, UInt(0), rom(index))
// Tie off unused channels
in.b.valid := Bool(false)
in.c.ready := Bool(true)
in.e.ready := Bool(true)
}
}
class ROMSlave(contents: Seq[Byte])(implicit val p: Parameters) extends Module
with HasTileLinkParameters
with HasAddrMapParameters {

View File

@ -0,0 +1,118 @@
// See LICENSE for license details.
package uncore.tilelink2
import Chisel._
import scala.math.{max,min}
object AddressDecoder
{
type Port = Seq[AddressSet]
type Ports = Seq[Port]
type Partition = Ports
type Partitions = Seq[Partition]
val addressOrder = Ordering.ordered[AddressSet]
val portOrder = Ordering.Iterable(addressOrder)
val partitionOrder = Ordering.Iterable(portOrder)
// Find the minimum subset of bits needed to disambiguate port addresses.
// ie: inspecting only the bits in the output, you can look at an address
// and decide to which port (outer Seq) the address belongs.
def apply(ports: Ports): BigInt = if (ports.size <= 1) 0 else {
// Every port must have at least one address!
ports.foreach { p => require (!p.isEmpty) }
// Verify the user did not give us an impossible problem
ports.combinations(2).foreach { case Seq(x, y) =>
x.foreach { a => y.foreach { b =>
require (!a.overlaps(b)) // it must be possible to disambiguate addresses!
} }
}
val maxBits = log2Ceil(ports.map(_.map(_.max).max).max + 1)
val bits = (0 until maxBits).map(BigInt(1) << _).toSeq
val selected = recurse(Seq(ports.map(_.sorted).sorted(portOrder)), bits)
selected.reduceLeft(_ | _)
}
// A simpler version that works for a Seq[Int]
def apply(keys: Seq[Int]): Int = {
val ports = keys.map(b => Seq(AddressSet(b, 0)))
apply(ports).toInt
}
// The algorithm has a set of partitions, discriminated by the selected bits.
// Each partion has a set of ports, listing all addresses that lead to that port.
// Seq[Seq[Seq[AddressSet]]]
// ^^^^^^^^^^^^^^^ set of addresses that are routed out this port
// ^^^ the list of ports
// ^^^ cases already distinguished by the selected bits thus far
//
// Solving this problem is NP-hard, so we use a simple greedy heuristic:
// pick the bit which minimizes the number of ports in each partition
// as a secondary goal, reduce the number of AddressSets within a partition
val bigValue = 100000
def bitScore(partitions: Partitions): Int = {
val maxPortsPerPartition = partitions.map(_.size).max
val maxSetsPerPartition = partitions.map(_.map(_.size).sum).max
maxPortsPerPartition * bigValue + maxSetsPerPartition
}
def partitionPort(port: Port, bit: BigInt): (Port, Port) = {
val addr_a = AddressSet(0, ~bit)
val addr_b = AddressSet(bit, ~bit)
// The addresses were sorted, so the filtered addresses are still sorted
val subset_a = port.filter(_.overlaps(addr_a))
val subset_b = port.filter(_.overlaps(addr_b))
(subset_a, subset_b)
}
def partitionPorts(ports: Ports, bit: BigInt): (Ports, Ports) = {
val partitioned_ports = ports.map(p => partitionPort(p, bit))
// because partitionPort dropped AddresSets, the ports might no longer be sorted
val case_a_ports = partitioned_ports.map(_._1).filter(!_.isEmpty).sorted(portOrder)
val case_b_ports = partitioned_ports.map(_._2).filter(!_.isEmpty).sorted(portOrder)
(case_a_ports, case_b_ports)
}
def partitionPartitions(partitions: Partitions, bit: BigInt): Partitions = {
val partitioned_partitions = partitions.map(p => partitionPorts(p, bit))
val case_a_partitions = partitioned_partitions.map(_._1)
val case_b_partitions = partitioned_partitions.map(_._2)
val new_partitions = (case_a_partitions ++ case_b_partitions).sorted(partitionOrder)
// Prevent combinational memory explosion; if two partitions are equal, keep only one
// Note: AddressSets in a port are sorted, and ports in a partition are sorted.
// This makes it easy to structurally compare two partitions for equality
val keep = (new_partitions.init zip new_partitions.tail) filter { case (a,b) => partitionOrder.compare(a,b) != 0 } map { _._2 }
new_partitions.head +: keep
}
// requirement: ports have sorted addresses and are sorted lexicographically
val debug = false
def recurse(partitions: Partitions, bits: Seq[BigInt]): Seq[BigInt] = {
if (debug) {
println("Partitioning:")
partitions.foreach { partition =>
println(" Partition:")
partition.foreach { port =>
print(" ")
port.foreach { a => print(s" ${a}") }
println("")
}
}
}
val candidates = bits.map { bit =>
val result = partitionPartitions(partitions, bit)
val score = bitScore(result)
(score, bit, result)
}
val (bestScore, bestBit, bestPartitions) = candidates.min(Ordering.by[(Int, BigInt, Partitions), Int](_._1))
if (debug) println("=> Selected bit 0x%x".format(bestBit))
if (bestScore < 2*bigValue) {
if (debug) println("---")
Seq(bestBit)
} else {
bestBit +: recurse(bestPartitions, bits.filter(_ != bestBit))
}
}
}

View File

@ -146,7 +146,7 @@ class TLFragmenter(minSize: Int, maxSize: Int, alwaysMin: Boolean = false) exten
val dFragnum = out.d.bits.source(fragmentBits-1, 0)
val dFirst = acknum === UInt(0)
val dsizeOH = UIntToOH (out.d.bits.size, log2Ceil(maxDownSize)+1)
val dsizeOH1 = UIntToOH1(out.d.bits.size, log2Ceil(maxDownSize))
val dsizeOH1 = UIntToOH1(out.d.bits.size, log2Up(maxDownSize))
val dHasData = edgeOut.hasData(out.d.bits)
// calculate new acknum
@ -209,7 +209,7 @@ class TLFragmenter(minSize: Int, maxSize: Int, alwaysMin: Boolean = false) exten
val aOrig = in.a.bits.size
val aFrag = Mux(aOrig > limit, limit, aOrig)
val aOrigOH1 = UIntToOH1(aOrig, log2Ceil(maxSize))
val aFragOH1 = UIntToOH1(aFrag, log2Ceil(maxDownSize))
val aFragOH1 = UIntToOH1(aFrag, log2Up(maxDownSize))
val aHasData = node.edgesIn(0).hasData(in.a.bits)
val aMask = Mux(aHasData, UInt(0), aFragOH1)

View File

@ -32,22 +32,36 @@ class TLHintHandler(supportManagers: Boolean = true, supportClients: Boolean = f
val smartManagers = edgeOut.manager.managers.map(_.supportsHint.max == edgeOut.manager.maxTransfer).reduce(_&&_)
if (supportManagers && !smartManagers) {
// State of the Hint bypass
val counter = RegInit(UInt(0, width = log2Up(edgeOut.manager.maxTransfer/edgeOut.manager.beatBytes)))
val hintHoldsD = RegInit(Bool(false))
val outerHoldsD = counter =/= UInt(0)
// Only one of them can hold it
assert (!hintHoldsD || !outerHoldsD)
// Count outer D beats
val beats1 = edgeOut.numBeats1(out.d.bits)
when (out.d.fire()) { counter := Mux(outerHoldsD, counter - UInt(1), beats1) }
// Who wants what?
val address = edgeIn.address(in.a.bits)
val handleA = if (passthrough) !edgeOut.manager.supportsHint(address, edgeIn.size(in.a.bits)) else Bool(true)
val bypassD = handleA && in.a.bits.opcode === TLMessages.Hint
val hintBitsAtA = handleA && in.a.bits.opcode === TLMessages.Hint
val hintWantsD = in.a.valid && hintBitsAtA
val outerWantsD = out.d.valid
// Prioritize existing D traffic over HintAck (and finish multibeat xfers)
val beats1 = edgeOut.numBeats1(out.d.bits)
val counter = RegInit(UInt(0, width = log2Up(edgeOut.manager.maxTransfer/edgeOut.manager.beatBytes)))
val first = counter === UInt(0)
when (out.d.fire()) { counter := Mux(first, beats1, counter - UInt(1)) }
val hintWinsD = hintHoldsD || (!outerHoldsD && !outerWantsD)
hintHoldsD := hintWantsD && hintWinsD && !in.d.ready
// Hint can only hold D b/c it still wants it from last cycle
assert (!hintHoldsD || hintWantsD)
in.d.valid := out.d.valid || (bypassD && in.a.valid && first)
out.d.ready := in.d.ready
in.d.bits := Mux(out.d.valid, out.d.bits, edgeIn.HintAck(in.a.bits, edgeOut.manager.findId(address)))
in.d.valid := Mux(hintWinsD, hintWantsD, outerWantsD)
in.d.bits := Mux(hintWinsD, edgeIn.HintAck(in.a.bits, edgeOut.manager.findId(address)), out.d.bits)
out.d.ready := in.d.ready && !hintHoldsD
in.a.ready := Mux(bypassD, in.d.ready && first && !out.d.valid, out.a.ready)
out.a.valid := in.a.valid && !bypassD
in.a.ready := Mux(hintBitsAtA, hintWinsD && in.d.ready, out.a.ready)
out.a.valid := in.a.valid && !hintBitsAtA
out.a.bits := in.a.bits
} else {
out.a.valid := in.a.valid
@ -60,21 +74,35 @@ class TLHintHandler(supportManagers: Boolean = true, supportClients: Boolean = f
}
if (supportClients && !smartClients) {
// State of the Hint bypass
val counter = RegInit(UInt(0, width = log2Up(edgeIn.client.maxTransfer/edgeIn.manager.beatBytes)))
val hintHoldsC = RegInit(Bool(false))
val innerHoldsC = counter =/= UInt(0)
// Only one of them can hold it
assert (!hintHoldsC || !innerHoldsC)
// Count inner C beats
val beats1 = edgeIn.numBeats1(in.c.bits)
when (in.c.fire()) { counter := Mux(innerHoldsC, counter - UInt(1), beats1) }
// Who wants what?
val handleB = if (passthrough) !edgeIn.client.supportsHint(out.b.bits.source, edgeOut.size(out.b.bits)) else Bool(true)
val bypassC = handleB && out.b.bits.opcode === TLMessages.Hint
val hintBitsAtB = handleB && out.b.bits.opcode === TLMessages.Hint
val hintWantsC = out.b.valid && hintBitsAtB
val innerWantsC = in.c.valid
// Prioritize existing C traffic over HintAck (and finish multibeat xfers)
val beats1 = edgeIn.numBeats1(in.c.bits)
val counter = RegInit(UInt(0, width = log2Up(edgeIn.client.maxTransfer/edgeIn.manager.beatBytes)))
val first = counter === UInt(0)
when (in.c.fire()) { counter := Mux(first, beats1, counter - UInt(1)) }
val hintWinsC = hintHoldsC || (!innerHoldsC && !innerWantsC)
hintHoldsC := hintWantsC && hintWinsC && !out.c.ready
// Hint can only hold C b/c it still wants it from last cycle
assert (!hintHoldsC || hintWantsC)
out.c.valid := in.c.valid || (bypassC && in.b.valid && first)
in.c.ready := out.c.ready
out.c.bits := Mux(in.c.valid, in.c.bits, edgeOut.HintAck(out.b.bits))
out.c.valid := Mux(hintWinsC, hintWantsC, innerWantsC)
out.c.bits := Mux(hintWinsC, edgeOut.HintAck(out.b.bits), in.c.bits)
in.c.ready := out.c.ready && !hintHoldsC
out.b.ready := Mux(bypassC, out.c.ready && first && !in.c.valid, in.b.ready)
in.b.valid := out.b.valid && !bypassC
out.b.ready := Mux(hintBitsAtB, hintWinsC && out.c.ready, in.b.ready)
in.b.valid := out.b.valid && !hintBitsAtB
in.b.bits := out.b.bits
} else if (bce) {
in.b.valid := out.b.valid

View File

@ -49,7 +49,7 @@ class TLLegacy(implicit val p: Parameters) extends LazyModule with HasTileLinkPa
// During conversion from TL Legacy, we won't support Acquire
// Must be able to fit TL2 sink_id into TL legacy
require ((1 << tlManagerXactIdBits) >= edge.manager.endSinkId)
require ((1 << tlManagerXactIdBits) >= edge.manager.endSinkId || !edge.manager.anySupportAcquire)
val out = io.out(0)
out.a.valid := io.legacy.acquire.valid
@ -78,6 +78,8 @@ class TLLegacy(implicit val p: Parameters) extends LazyModule with HasTileLinkPa
MemoryOpConstants.M_XA_MINU -> edge.Arithmetic(source, address, beat, data, TLAtomics.MINU)._2,
MemoryOpConstants.M_XA_MAXU -> edge.Arithmetic(source, address, beat, data, TLAtomics.MAXU)._2))
} else {
// If no managers support atomics, assert fail if TL1 asks for them
assert (!io.legacy.acquire.valid || io.legacy.acquire.bits.a_type =/= Acquire.putAtomicType)
Wire(new TLBundleA(edge.bundle))
}

View File

@ -406,7 +406,7 @@ object TLMonitor
val last_v = RegNext(irr.valid, Bool(false))
val last_r = RegNext(irr.ready, Bool(false))
val last_b = RegNext(irr.bits)
val bits_changed = irr.bits.toBits === last_b.toBits
val bits_changed = irr.bits.asUInt === last_b.asUInt
when (last_v && !last_r) {
assert(irr.valid, s"${irr.bits.channelName} had contents that were revoked by the supplier (valid lowered)" + extra)

View File

@ -76,7 +76,7 @@ class BaseNode[PO, PI, EO, EI, B <: Data](imp: NodeImp[PO, PI, EO, EI, B])(
def connectOut = bundleOut
def connectIn = bundleIn
protected[tilelink2] def := (y: BaseNode[PO, PI, EO, EI, B])(implicit sourceInfo: SourceInfo) = {
def := (y: BaseNode[PO, PI, EO, EI, B])(implicit sourceInfo: SourceInfo) = {
val x = this // x := y
val info = sourceLine(sourceInfo, " at ", "")
require (!LazyModule.stack.isEmpty, s"${y.name} cannot be connected to ${x.name} outside of LazyModule scope" + info)

View File

@ -63,7 +63,7 @@ case class TransferSizes(min: Int, max: Int)
def contains(x: TransferSizes) = x.none || (min <= x.min && x.max <= max)
def intersect(x: TransferSizes) =
if (x.max < min || min < x.max) TransferSizes.none
if (x.max < min || max < x.min) TransferSizes.none
else TransferSizes(scala.math.max(min, x.min), scala.math.min(max, x.max))
}
@ -78,7 +78,7 @@ object TransferSizes {
// Base is the base address, and mask are the bits consumed by the manager
// e.g: base=0x200, mask=0xff describes a device managing 0x200-0x2ff
// e.g: base=0x1000, mask=0xf0f decribes a device managing 0x1000-0x100f, 0x1100-0x110f, ...
case class AddressSet(base: BigInt, mask: BigInt)
case class AddressSet(base: BigInt, mask: BigInt) extends Ordered[AddressSet]
{
// Forbid misaligned base address (and empty sets)
require ((base & mask) == 0)
@ -97,12 +97,24 @@ case class AddressSet(base: BigInt, mask: BigInt)
// A strided slave serves discontiguous ranges
def strided = alignment1 != mask
// AddressSets have one natural Ordering (the containment order)
def compare(x: AddressSet) = {
val primary = (this.base - x.base).signum // smallest address first
val secondary = (x.mask - this.mask).signum // largest mask first
if (primary != 0) primary else secondary
}
// We always want to see things in hex
override def toString() = "AddressSet(0x%x, 0x%x)".format(base, mask)
}
case class TLManagerParameters(
address: Seq[AddressSet],
sinkId: IdRange = IdRange(0, 1),
regionType: RegionType.T = RegionType.GET_EFFECTS,
sinkId: IdRange = IdRange(0, 1),
regionType: RegionType.T = RegionType.GET_EFFECTS,
executable: Boolean = false, // processor can execute from this memory
nodePath: Seq[TLBaseNode] = Seq(),
// Supports both Acquire+Release+Finish of these sizes
supportsAcquire: TransferSizes = TransferSizes.none,
supportsArithmetic: TransferSizes = TransferSizes.none,
@ -183,6 +195,7 @@ case class TLManagerPortParameters(managers: Seq[TLManagerParameters], beatBytes
def findFifoId(address: UInt) = Mux1H(find(address), managers.map(m => UInt(m.fifoId.map(_+1).getOrElse(0))))
def hasFifoId(address: UInt) = Mux1H(find(address), managers.map(m => Bool(m.fifoId.isDefined)))
lazy val addressMask = AddressDecoder(managers.map(_.address))
// !!! need a cheaper version of find, where we assume a valid address match exists
// Does this Port manage this ID/address?
@ -207,7 +220,8 @@ case class TLManagerPortParameters(managers: Seq[TLManagerParameters], beatBytes
}
case class TLClientParameters(
sourceId: IdRange = IdRange(0,1),
sourceId: IdRange = IdRange(0,1),
nodePath: Seq[TLBaseNode] = Seq(),
// Supports both Probe+Grant of these sizes
supportsProbe: TransferSizes = TransferSizes.none,
supportsArithmetic: TransferSizes = TransferSizes.none,

View File

@ -105,6 +105,28 @@ object RegField
bb.d := data
Bool(true)
}))
// Split a large register into a sequence of byte fields
// The bytes can be individually written, as they are one byte per field
def bytes(x: UInt): Seq[RegField] = {
require (x.getWidth % 8 == 0)
val bytes = Seq.tabulate(x.getWidth/8) { i => x(8*(i+1)-1, 8*i) }
val wires = bytes.map { b => Wire(init = b) }
x := Cat(wires.reverse)
Seq.tabulate(x.getWidth/8) { i =>
RegField(8, bytes(i), RegWriteFn { (valid, data) =>
when (valid) { wires(i) := data }
Bool(true)
})
}
}
// Divide a long sequence of RegFields into a maximum sized registers
// Your input RegFields may not cross a beatBytes boundary!
def split(fields: Seq[RegField], base: Int, beatBytes: Int = 4): Seq[RegField.Map] = {
val offsets = fields.map(_.width).scanLeft(0)(_ + _).init
(offsets zip fields).groupBy(_._1 / (beatBytes*8)).toList.map(r => (r._1 + base, r._2.map(_._2)))
}
}
trait HasRegMap

View File

@ -28,8 +28,8 @@ class RegMapperOutput(params: RegMapperParams) extends GenericParameterizedBundl
object RegMapper
{
// Create a generic register-based device
def apply(bytes: Int, concurrency: Option[Int], in: DecoupledIO[RegMapperInput], mapping: RegField.Map*) = {
val regmap = mapping.toList
def apply(bytes: Int, concurrency: Option[Int], undefZero: Boolean, in: DecoupledIO[RegMapperInput], mapping: RegField.Map*) = {
val regmap = mapping.toList.filter(!_._2.isEmpty)
require (!regmap.isEmpty)
// Ensure no register appears twice
@ -37,15 +37,31 @@ object RegMapper
require (reg1 != reg2)
}
// Flatten the regmap into (Reg:Int, Offset:Int, field:RegField)
val flat = regmap.map { case (reg, fields) =>
val offsets = fields.scanLeft(0)(_ + _.width).init
(offsets zip fields) map { case (o, f) => (reg, o, f) }
}.flatten
require (!flat.isEmpty)
// Convert to and from Bits
def toBits(x: Int, tail: List[Boolean] = List.empty): List[Boolean] =
if (x == 0) tail.reverse else toBits(x >> 1, ((x & 1) == 1) :: tail)
def ofBits(bits: List[Boolean]) = bits.foldRight(0){ case (x,y) => (if (x) 1 else 0) | y << 1 }
// Find the minimal mask that can decide the register map
val mask = AddressDecoder(regmap.map(_._1))
val maskFilter = toBits(mask)
val maskBits = maskFilter.filter(x => x).size
// Calculate size and indexes into the register map
val endIndex = 1 << log2Ceil(regmap.map(_._1).max+1)
val params = RegMapperParams(log2Up(endIndex), bytes, in.bits.params.extraBits)
val regSize = 1 << maskBits
def regIndexI(x: Int) = ofBits((maskFilter zip toBits(x)).filter(_._1).map(_._2))
def regIndexU(x: UInt) = if (maskBits == 0) UInt(0) else
Cat((maskFilter zip x.toBools).filter(_._1).map(_._2).reverse)
// Flatten the regmap into (RegIndex:Int, Offset:Int, field:RegField)
val flat = regmap.map { case (reg, fields) =>
val offsets = fields.scanLeft(0)(_ + _.width).init
val index = regIndexI(reg)
// println("mapping 0x%x -> 0x%x for 0x%x/%d".format(reg, index, mask, maskBits))
(offsets zip fields) map { case (o, f) => (index, o, f) }
}.flatten
val out = Wire(Irrevocable(new RegMapperOutput(params)))
val front = Wire(Irrevocable(new RegMapperInput(params)))
@ -69,13 +85,13 @@ object RegMapper
val woready = Wire(Vec(flat.size, Bool()))
// Per-register list of all control signals needed for data to flow
val rifire = Array.tabulate(endIndex) { i => Seq(Bool(true)) }
val wifire = Array.tabulate(endIndex) { i => Seq(Bool(true)) }
val rofire = Array.tabulate(endIndex) { i => Seq(Bool(true)) }
val wofire = Array.tabulate(endIndex) { i => Seq(Bool(true)) }
val rifire = Array.tabulate(regSize) { i => Seq(Bool(true)) }
val wifire = Array.tabulate(regSize) { i => Seq(Bool(true)) }
val rofire = Array.tabulate(regSize) { i => Seq(Bool(true)) }
val wofire = Array.tabulate(regSize) { i => Seq(Bool(true)) }
// The output values for each register
val dataOut = Array.tabulate(endIndex) { _ => UInt(0) }
val dataOut = Array.tabulate(regSize) { _ => UInt(0) }
// Which bits are touched?
val frontMask = FillInterleaved(8, front.bits.mask)
@ -110,8 +126,10 @@ object RegMapper
val wifireMux = Vec(wifire.map(_.reduce(_ && _)))
val rofireMux = Vec(rofire.map(_.reduce(_ && _)))
val wofireMux = Vec(wofire.map(_.reduce(_ && _)))
val iready = Mux(front.bits.read, rifireMux(front.bits.index), wifireMux(front.bits.index))
val oready = Mux(back .bits.read, rofireMux(back .bits.index), wofireMux(back .bits.index))
val iindex = regIndexU(front.bits.index)
val oindex = regIndexU(back .bits.index)
val iready = Mux(front.bits.read, rifireMux(iindex), wifireMux(iindex))
val oready = Mux(back .bits.read, rofireMux(oindex), wofireMux(oindex))
// Connect the pipeline
in.ready := front.ready && iready
@ -120,11 +138,11 @@ object RegMapper
out.valid := back.valid && oready
// Which register is touched?
val frontSel = UIntToOH(front.bits.index)
val backSel = UIntToOH(back.bits.index)
val frontSel = UIntToOH(iindex)
val backSel = UIntToOH(oindex)
// Include the per-register one-hot selected criteria
for (reg <- 0 until endIndex) {
for (reg <- 0 until regSize) {
rifire(reg) = (in.valid && front.ready && front.bits.read && frontSel(reg)) +: rifire(reg)
wifire(reg) = (in.valid && front.ready && !front.bits.read && frontSel(reg)) +: wifire(reg)
rofire(reg) = (back.valid && out.ready && back .bits.read && backSel (reg)) +: rofire(reg)
@ -141,7 +159,7 @@ object RegMapper
}
out.bits.read := back.bits.read
out.bits.data := Vec(dataOut)(back.bits.index)
out.bits.data := Vec(dataOut)(oindex)
out.bits.extra := back.bits.extra
(endIndex, out)

View File

@ -4,7 +4,7 @@ package uncore.tilelink2
import Chisel._
class TLRegisterNode(address: AddressSet, concurrency: Option[Int] = None, beatBytes: Int = 4)
class TLRegisterNode(address: AddressSet, concurrency: Option[Int] = None, beatBytes: Int = 4, undefZero: Boolean = true)
extends TLManagerNode(beatBytes, TLManagerParameters(
address = Seq(address),
supportsGet = TransferSizes(1, beatBytes),
@ -25,7 +25,7 @@ class TLRegisterNode(address: AddressSet, concurrency: Option[Int] = None, beatB
val baseEnd = 0
val (sizeEnd, sizeOff) = (edge.bundle.sizeBits + baseEnd, baseEnd)
val (sourceEnd, sourceOff) = (edge.bundle.sourceBits + sizeEnd, sizeEnd)
val (addrLoEnd, addrLoOff) = (log2Ceil(beatBytes) + sourceEnd, sourceEnd)
val (addrLoEnd, addrLoOff) = (log2Up(beatBytes) + sourceEnd, sourceEnd)
val params = RegMapperParams(log2Up(address.mask+1), beatBytes, addrLoEnd)
val in = Wire(Decoupled(new RegMapperInput(params)))
@ -36,7 +36,7 @@ class TLRegisterNode(address: AddressSet, concurrency: Option[Int] = None, beatB
in.bits.extra := Cat(edge.addr_lo(a.bits), a.bits.source, a.bits.size)
// Invoke the register map builder
val (endIndex, out) = RegMapper(beatBytes, concurrency, in, mapping:_*)
val (endIndex, out) = RegMapper(beatBytes, concurrency, undefZero, in, mapping:_*)
// All registers must fit inside the device address space
require (address.mask >= (endIndex-1)*beatBytes)
@ -67,17 +67,17 @@ class TLRegisterNode(address: AddressSet, concurrency: Option[Int] = None, beatB
object TLRegisterNode
{
def apply(address: AddressSet, concurrency: Option[Int] = None, beatBytes: Int = 4) =
new TLRegisterNode(address, concurrency, beatBytes)
def apply(address: AddressSet, concurrency: Option[Int] = None, beatBytes: Int = 4, undefZero: Boolean = true) =
new TLRegisterNode(address, concurrency, beatBytes, undefZero)
}
// These convenience methods below combine to make it possible to create a TL2
// register mapped device from a totally abstract register mapped device.
// See GPIO.scala in this directory for an example
abstract class TLRegisterRouterBase(address: AddressSet, interrupts: Int, concurrency: Option[Int], beatBytes: Int) extends LazyModule
abstract class TLRegisterRouterBase(address: AddressSet, interrupts: Int, concurrency: Option[Int], beatBytes: Int, undefZero: Boolean) extends LazyModule
{
val node = TLRegisterNode(address, concurrency, beatBytes)
val node = TLRegisterNode(address, concurrency, beatBytes, undefZero)
val intnode = IntSourceNode(name + s" @ ${address.base}", interrupts)
}
@ -100,10 +100,10 @@ class TLRegModule[P, B <: TLRegBundleBase](val params: P, bundleBuilder: => B, r
}
class TLRegisterRouter[B <: TLRegBundleBase, M <: LazyModuleImp]
(base: BigInt, interrupts: Int = 0, size: BigInt = 4096, concurrency: Option[Int] = None, beatBytes: Int = 4)
(val base: BigInt, val interrupts: Int = 0, val size: BigInt = 4096, val concurrency: Option[Int] = None, val beatBytes: Int = 4, undefZero: Boolean = true)
(bundleBuilder: TLRegBundleArg => B)
(moduleBuilder: (=> B, TLRegisterRouterBase) => M)
extends TLRegisterRouterBase(AddressSet(base, size-1), interrupts, concurrency, beatBytes)
extends TLRegisterRouterBase(AddressSet(base, size-1), interrupts, concurrency, beatBytes, undefZero)
{
require (isPow2(size))
// require (size >= 4096) ... not absolutely required, but highly recommended

View File

@ -9,6 +9,7 @@ class TLRAM(address: AddressSet, beatBytes: Int = 4) extends LazyModule
val node = TLManagerNode(beatBytes, TLManagerParameters(
address = List(address),
regionType = RegionType.UNCACHED,
executable = true,
supportsGet = TransferSizes(1, beatBytes),
supportsPutPartial = TransferSizes(1, beatBytes),
supportsPutFull = TransferSizes(1, beatBytes),

View File

@ -5,13 +5,17 @@ import Chisel._
import cde.{Parameters}
/** This black-boxes an Async Reset
* Reg.
* (or Set)
* Register.
*
* Because Chisel doesn't support
* parameterized black boxes,
* we unfortunately have to
* instantiate a number of these.
*
* We also have to hard-code the set/
* reset behavior.
*
* Do not confuse an asynchronous
* reset signal with an asynchronously
* reset reg. You should still
@ -22,29 +26,25 @@ import cde.{Parameters}
* @param q Data Output
* @param clk Clock Input
* @param rst Reset Input
*
* @param init Value to write at Reset.
* This is a constant,
* but this construction
* will likely make backend flows
* and lint tools unhappy.
* @param en Write Enable Input
*
*/
class AsyncResetReg extends BlackBox {
abstract class AbstractBBReg extends BlackBox {
val io = new Bundle {
val d = Bool(INPUT)
val q = Bool(OUTPUT)
val en = Bool(INPUT)
val clk = Clock(INPUT)
val rst = Bool(INPUT)
val init = Bool(INPUT)
}
}
class AsyncResetReg extends AbstractBBReg
class AsyncSetReg extends AbstractBBReg
class SimpleRegIO(val w: Int) extends Bundle{
@ -55,29 +55,56 @@ class SimpleRegIO(val w: Int) extends Bundle{
}
class AsyncResetRegVec(val w: Int, val init: Int) extends Module {
class AsyncResetRegVec(val w: Int, val init: BigInt) extends Module {
val io = new SimpleRegIO(w)
val bb_q = Wire(UInt(width = w))
val bb_d = Wire(UInt(width = w))
val bb_d = Mux(io.en, io.d, io.q)
val init_val = Wire(UInt(width = w))
init_val := UInt(init, width = w)
val async_regs = List.fill(w)(Module (new AsyncResetReg))
bb_q := (async_regs.map(_.io.q)).asUInt()
bb_d := Mux(io.en , io.d , bb_q)
io.q := bb_q
val async_regs: List[AbstractBBReg] = List.tabulate(w)(
i => Module (
if (((init >> i) % 2) > 0)
new AsyncSetReg
else
new AsyncResetReg)
)
io.q := async_regs.map(_.io.q).asUInt
for ((reg, idx) <- async_regs.zipWithIndex) {
reg.io.clk := clock
reg.io.rst := reset
reg.io.init := init_val(idx)
reg.io.d := bb_d(idx)
reg.io.d := bb_d(idx)
reg.io.en := io.en
}
}
object AsyncResetReg {
def apply(d: Bool, clk: Clock, rst: Bool, init: Boolean): Bool = {
val reg: AbstractBBReg =
if (init) Module (new AsyncSetReg)
else Module(new AsyncResetReg)
reg.io.d := d
reg.io.clk := clk
reg.io.rst := rst
reg.io.en := Bool(true)
reg.io.q
}
def apply(d: Bool, clk: Clock, rst: Bool): Bool = apply(d, clk, rst, false)
def apply(updateData: UInt, resetData: BigInt, enable: Bool): UInt = {
val w = updateData.getWidth max resetData.bitLength
val reg = Module(new AsyncResetRegVec(w, resetData))
reg.io.d := updateData
reg.io.en := enable
reg.io.q
}
def apply(updateData: UInt, resetData: BigInt): UInt = apply(updateData, resetData, enable=Bool(true))
def apply(updateData: UInt, enable: Bool): UInt = apply(updateData, resetData=BigInt(0), enable)
def apply(updateData: UInt): UInt = apply(updateData, resetData=BigInt(0), enable=Bool(true))
}

View File

@ -11,10 +11,10 @@ class TestHarness(implicit val p: Parameters) extends Module {
val success = Bool(OUTPUT)
}
p(NCoreplexExtClients).assign(0)
p(ConfigString).assign("")
val l1params = p.alterPartial({ case uncore.tilelink.TLId => "L1toL2" })
val l1params = p.alterPartial({
case NCoreplexExtClients => 0
case ConfigString => ""
case uncore.tilelink.TLId => "L1toL2" })
val tests = Module(new UnitTestSuite()(l1params))
io.success := tests.io.finished

View File

@ -8,9 +8,10 @@ bb_vsrcs = $(base_dir)/vsrc/DebugTransportModuleJtag.v \
$(base_dir)/vsrc/jtag_vpi.v \
$(base_dir)/vsrc/AsyncMailbox.v \
$(base_dir)/vsrc/AsyncResetReg.v \
$(base_dir)/vsrc/AsyncSetReg.v \
$(base_dir)/vsrc/ClockDivider.v \
$(base_dir)/vsrc/ClockToSignal.v \
$(base_dir)/vsrc/SignalToClock.v \
$(base_dir)/vsrc/ClockToSignal.v \
$(base_dir)/vsrc/SignalToClock.v \
sim_vsrcs = \

View File

@ -8,6 +8,8 @@
* we unfortunately have to
* instantiate a number of these.
*
* We also have to hard-code the set/reset.
*
* Do not confuse an asynchronous
* reset signal with an asynchronously
* reset reg. You should still
@ -18,32 +20,25 @@
* @param q Data Output
* @param clk Clock Input
* @param rst Reset Input
*
* @param init Value to write at Reset.
* This is a constant,
* but this construction
* will likely make backend flows
* and lint tools unhappy.
* @param en Write Enable Input
*
*/
module AsyncResetReg (
input d,
output reg q,
input en,
input clk,
input rst,
input init);
input rst);
always @(posedge clk or posedge rst) begin
if (rst) begin
q <= init;
end else begin
q <= 1'b0;
end else if (en) begin
q <= d;
end
end

47
vsrc/AsyncSetReg.v Normal file
View File

@ -0,0 +1,47 @@
/** This black-boxes an Async Set
* Reg.
*
* Because Chisel doesn't support
* parameterized black boxes,
* we unfortunately have to
* instantiate a number of these.
*
* We also have to hard-code the set/reset.
*
* Do not confuse an asynchronous
* reset signal with an asynchronously
* reset reg. You should still
* properly synchronize your reset
* deassertion.
*
* @param d Data input
* @param q Data Output
* @param clk Clock Input
* @param rst Reset Input
* @param en Write Enable Input
*
*/
module AsyncSetReg (
input d,
output reg q,
input en,
input clk,
input rst);
always @(posedge clk or posedge rst) begin
if (rst) begin
q <= 1'b1;
end else if (en) begin
q <= d;
end
end
endmodule // AsyncSetReg