WIP on new memory map
This commit is contained in:
parent
48170fd9aa
commit
1f211b37df
@ -365,7 +365,6 @@ Top.DefaultVLSIConfig.conf file:
|
|||||||
Top.DefaultVLSIConfig.prm
|
Top.DefaultVLSIConfig.prm
|
||||||
Top.DefaultVLSIConfig.v
|
Top.DefaultVLSIConfig.v
|
||||||
consts.DefaultVLSIConfig.vh
|
consts.DefaultVLSIConfig.vh
|
||||||
memdessertMemDessert.DefaultVLSIConfig.v
|
|
||||||
$ cat $ROCKETCHIP/vsim/generated-src/*.conf
|
$ cat $ROCKETCHIP/vsim/generated-src/*.conf
|
||||||
name MetadataArray_tag_arr depth 128 width 84 ports mwrite,read mask_gran 21
|
name MetadataArray_tag_arr depth 128 width 84 ports mwrite,read mask_gran 21
|
||||||
name ICache_tag_array depth 128 width 38 ports mrw mask_gran 19
|
name ICache_tag_array depth 128 width 38 ports mrw mask_gran 19
|
||||||
|
2
chisel3
2
chisel3
@ -1 +1 @@
|
|||||||
Subproject commit 19046381ae319915c4e8fff7b108e6b5dd100509
|
Subproject commit 6183533596a1706c65cb20d07a9d42eadac32df2
|
@ -111,7 +111,6 @@ int main(int argc, char** argv)
|
|||||||
// reset for one host_clk cycle to handle pipelined reset
|
// reset for one host_clk cycle to handle pipelined reset
|
||||||
tile.Top__io_host_in_valid = LIT<1>(0);
|
tile.Top__io_host_in_valid = LIT<1>(0);
|
||||||
tile.Top__io_host_out_ready = LIT<1>(0);
|
tile.Top__io_host_out_ready = LIT<1>(0);
|
||||||
tile.Top__io_mem_backup_ctrl_en = LIT<1>(0);
|
|
||||||
for (int i = 0; i < 3; i += tile.Top__io_host_clk_edge.to_bool())
|
for (int i = 0; i < 3; i += tile.Top__io_host_clk_edge.to_bool())
|
||||||
{
|
{
|
||||||
tile.clock_lo(LIT<1>(1));
|
tile.clock_lo(LIT<1>(1));
|
||||||
|
2
firrtl
2
firrtl
@ -1 +1 @@
|
|||||||
Subproject commit ec32c852b57a42c7741f8ae27d59c21fcdb86a82
|
Subproject commit 54184c2a08aea4c8682d2fe899718c369e00a240
|
@ -8,9 +8,7 @@
|
|||||||
sim_vsrcs = \
|
sim_vsrcs = \
|
||||||
$(generated_dir)/$(MODEL).$(CONFIG).v \
|
$(generated_dir)/$(MODEL).$(CONFIG).v \
|
||||||
$(generated_dir)/consts.$(CONFIG).vh \
|
$(generated_dir)/consts.$(CONFIG).vh \
|
||||||
$(generated_dir)/memdessertMemDessert.$(CONFIG).v \
|
|
||||||
$(base_dir)/vsrc/$(TB).v \
|
$(base_dir)/vsrc/$(TB).v \
|
||||||
$(base_dir)/vsrc/backup_mem.v \
|
|
||||||
|
|
||||||
# C sources
|
# C sources
|
||||||
|
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit cd3d2ca2190f1c16fa65840dbc86527e50613b5f
|
Subproject commit d9c4e92a21de34515f745893bcb4e76ed8f1cd60
|
2
rocket
2
rocket
@ -1 +1 @@
|
|||||||
Subproject commit bcc378aa717daf1a3dfcadd6cd1f77c58ba3ed47
|
Subproject commit 43baccd10a23a4e1e11b3ee0c571bae1729ae035
|
@ -25,24 +25,23 @@ class DefaultConfig extends Config (
|
|||||||
type PF = PartialFunction[Any,Any]
|
type PF = PartialFunction[Any,Any]
|
||||||
def findBy(sname:Any):Any = here[PF](site[Any](sname))(pname)
|
def findBy(sname:Any):Any = here[PF](site[Any](sname))(pname)
|
||||||
def genCsrAddrMap: AddrMap = {
|
def genCsrAddrMap: AddrMap = {
|
||||||
val deviceTree = AddrMapEntry("devicetree", None, MemSize(1 << 15, AddrMapConsts.R))
|
val deviceTree = AddrMapEntry("devicetree", MemSize(1 << 15, AddrMapConsts.R))
|
||||||
val csrSize = (1 << 12) * (site(XLen) / 8)
|
val rtc = AddrMapEntry("rtc", MemSize(1 << 12, AddrMapConsts.RW))
|
||||||
val csrs = (0 until site(NTiles)).map{ i =>
|
new AddrMap(Seq(deviceTree, rtc))
|
||||||
AddrMapEntry(s"csr$i", None, MemSize(csrSize, AddrMapConsts.RW))
|
|
||||||
}
|
|
||||||
val scrSize = site(HtifKey).nSCR * (site(XLen) / 8)
|
|
||||||
val scr = AddrMapEntry("scr", None, MemSize(scrSize, AddrMapConsts.RW))
|
|
||||||
new AddrMap(deviceTree +: csrs :+ scr)
|
|
||||||
}
|
}
|
||||||
def makeConfigString() = {
|
def makeConfigString() = {
|
||||||
val addrMap = new AddrHashMap(site(GlobalAddrMap))
|
val addrMap = new AddrHashMap(site(GlobalAddrMap))
|
||||||
val xLen = site(XLen)
|
val xLen = site(XLen)
|
||||||
val res = new StringBuilder
|
val res = new StringBuilder
|
||||||
val memSize = addrMap(s"mem").size
|
val memSize = addrMap("mem").size
|
||||||
|
val rtcAddr = addrMap("conf:rtc").start
|
||||||
res append "platform {\n"
|
res append "platform {\n"
|
||||||
res append " vendor ucb;\n"
|
res append " vendor ucb;\n"
|
||||||
res append " arch rocket;\n"
|
res append " arch rocket;\n"
|
||||||
res append "};\n"
|
res append "};\n"
|
||||||
|
res append "rtc {\n"
|
||||||
|
res append s" addr 0x${rtcAddr.toString(16)};\n"
|
||||||
|
res append "};\n"
|
||||||
res append "ram {\n"
|
res append "ram {\n"
|
||||||
res append " 0 {\n"
|
res append " 0 {\n"
|
||||||
res append " addr 0;\n"
|
res append " addr 0;\n"
|
||||||
@ -51,11 +50,11 @@ class DefaultConfig extends Config (
|
|||||||
res append "};\n"
|
res append "};\n"
|
||||||
res append "core {\n"
|
res append "core {\n"
|
||||||
for (i <- 0 until site(NTiles)) {
|
for (i <- 0 until site(NTiles)) {
|
||||||
val csrAddr = addrMap(s"conf:csr$i").start
|
val timecmpAddr = rtcAddr + 8*(i+1)
|
||||||
res append s" $i {\n"
|
res append s" $i {\n"
|
||||||
res append " 0 {\n"
|
res append " 0 {\n"
|
||||||
res append s" isa rv$xLen;\n"
|
res append s" isa rv$xLen;\n"
|
||||||
res append s" addr 0x${csrAddr.toString(16)};\n"
|
res append s" timecmp 0x${timecmpAddr.toString(16)};\n"
|
||||||
res append " };\n"
|
res append " };\n"
|
||||||
res append " };\n"
|
res append " };\n"
|
||||||
}
|
}
|
||||||
@ -187,7 +186,7 @@ class DefaultConfig extends Config (
|
|||||||
case LNEndpoints => site(TLKey(site(TLId))).nManagers + site(TLKey(site(TLId))).nClients
|
case LNEndpoints => site(TLKey(site(TLId))).nManagers + site(TLKey(site(TLId))).nClients
|
||||||
case LNHeaderBits => log2Ceil(site(TLKey(site(TLId))).nManagers) +
|
case LNHeaderBits => log2Ceil(site(TLKey(site(TLId))).nManagers) +
|
||||||
log2Up(site(TLKey(site(TLId))).nClients)
|
log2Up(site(TLKey(site(TLId))).nClients)
|
||||||
case ExtraL1Clients => 2 // RTC and HTIF
|
case ExtraL1Clients => 1 // HTIF // TODO not really a parameter
|
||||||
case TLKey("L1toL2") =>
|
case TLKey("L1toL2") =>
|
||||||
TileLinkParameters(
|
TileLinkParameters(
|
||||||
coherencePolicy = new MESICoherence(site(L2DirectoryRepresentation)),
|
coherencePolicy = new MESICoherence(site(L2DirectoryRepresentation)),
|
||||||
@ -201,9 +200,7 @@ class DefaultConfig extends Config (
|
|||||||
// L1 cache
|
// L1 cache
|
||||||
site(NMSHRs) + 1,
|
site(NMSHRs) + 1,
|
||||||
// RoCC
|
// RoCC
|
||||||
if (site(BuildRoCC).isEmpty) 1 else site(RoccMaxTaggedMemXacts),
|
if (site(BuildRoCC).isEmpty) 1 else site(RoccMaxTaggedMemXacts)),
|
||||||
// RTC
|
|
||||||
site(NTiles)),
|
|
||||||
maxClientsPerPort = if (site(BuildRoCC).isEmpty) 1 else 2,
|
maxClientsPerPort = if (site(BuildRoCC).isEmpty) 1 else 2,
|
||||||
maxManagerXacts = site(NAcquireTransactors) + 2,
|
maxManagerXacts = site(NAcquireTransactors) + 2,
|
||||||
dataBits = site(CacheBlockBytes)*8)
|
dataBits = site(CacheBlockBytes)*8)
|
||||||
@ -245,18 +242,15 @@ class DefaultConfig extends Config (
|
|||||||
case BankIdLSB => 0
|
case BankIdLSB => 0
|
||||||
case CacheBlockBytes => Dump("CACHE_BLOCK_BYTES", 64)
|
case CacheBlockBytes => Dump("CACHE_BLOCK_BYTES", 64)
|
||||||
case CacheBlockOffsetBits => log2Up(here(CacheBlockBytes))
|
case CacheBlockOffsetBits => log2Up(here(CacheBlockBytes))
|
||||||
case UseBackupMemoryPort => false
|
|
||||||
case UseHtifClockDiv => true
|
case UseHtifClockDiv => true
|
||||||
case ConfigString => makeConfigString()
|
case ConfigString => makeConfigString()
|
||||||
case GlobalAddrMap => {
|
case GlobalAddrMap => {
|
||||||
val memsize = BigInt(1L << 30)
|
val memsize = BigInt(1L << 30)
|
||||||
Dump("MEM_SIZE", memsize)
|
Dump("MEM_SIZE", memsize)
|
||||||
AddrMap(
|
AddrMap(
|
||||||
AddrMapEntry("mem", None, MemSize(memsize, AddrMapConsts.RWX, true)),
|
AddrMapEntry("mem", MemSize(memsize, AddrMapConsts.RWX, true)),
|
||||||
AddrMapEntry("conf", None,
|
AddrMapEntry("conf", MemSubmap(BigInt(1L << 30), genCsrAddrMap)),
|
||||||
MemSubmap(BigInt(1L << 30), genCsrAddrMap)),
|
AddrMapEntry("devices", MemSubmap(BigInt(1L << 31), site(GlobalDeviceSet).getAddrMap)))
|
||||||
AddrMapEntry("devices", None,
|
|
||||||
MemSubmap(BigInt(1L << 31), site(GlobalDeviceSet).getAddrMap)))
|
|
||||||
}
|
}
|
||||||
case GlobalDeviceSet => {
|
case GlobalDeviceSet => {
|
||||||
val devset = new DeviceSet
|
val devset = new DeviceSet
|
||||||
|
@ -29,7 +29,7 @@ class DeviceSet {
|
|||||||
val entries = devices.map { case Device(name, size, _, readable, writeable) =>
|
val entries = devices.map { case Device(name, size, _, readable, writeable) =>
|
||||||
val prot = (if (readable) R else 0) | (if (writeable) W else 0)
|
val prot = (if (readable) R else 0) | (if (writeable) W else 0)
|
||||||
val realsize = roundup(size)
|
val realsize = roundup(size)
|
||||||
new AddrMapEntry(name, None, new MemSize(realsize, prot))
|
new AddrMapEntry(name, new MemSize(realsize, prot))
|
||||||
}
|
}
|
||||||
new AddrMap(entries)
|
new AddrMap(entries)
|
||||||
}
|
}
|
||||||
|
@ -25,8 +25,6 @@ case object MemoryChannelMuxConfigs extends Field[List[Int]]
|
|||||||
case object BankIdLSB extends Field[Int]
|
case object BankIdLSB extends Field[Int]
|
||||||
/** Number of outstanding memory requests */
|
/** Number of outstanding memory requests */
|
||||||
case object NOutstandingMemReqsPerChannel extends Field[Int]
|
case object NOutstandingMemReqsPerChannel extends Field[Int]
|
||||||
/** Whether to use the slow backup memory port [VLSI] */
|
|
||||||
case object UseBackupMemoryPort extends Field[Boolean]
|
|
||||||
/** Whether to divide HTIF clock */
|
/** Whether to divide HTIF clock */
|
||||||
case object UseHtifClockDiv extends Field[Boolean]
|
case object UseHtifClockDiv extends Field[Boolean]
|
||||||
/** Function for building some kind of coherence manager agent */
|
/** Function for building some kind of coherence manager agent */
|
||||||
@ -78,7 +76,6 @@ class MemBackupCtrlIO extends Bundle {
|
|||||||
class BasicTopIO(implicit val p: Parameters) extends ParameterizedBundle()(p)
|
class BasicTopIO(implicit val p: Parameters) extends ParameterizedBundle()(p)
|
||||||
with HasTopLevelParameters {
|
with HasTopLevelParameters {
|
||||||
val host = new HostIO(htifW)
|
val host = new HostIO(htifW)
|
||||||
val mem_backup_ctrl = new MemBackupCtrlIO
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class TopIO(implicit p: Parameters) extends BasicTopIO()(p) {
|
class TopIO(implicit p: Parameters) extends BasicTopIO()(p) {
|
||||||
@ -95,6 +92,11 @@ object TopUtils {
|
|||||||
inner.r <> Queue(outer.r, mifDataBeats)
|
inner.r <> Queue(outer.r, mifDataBeats)
|
||||||
inner.b <> Queue(outer.b)
|
inner.b <> Queue(outer.b)
|
||||||
}
|
}
|
||||||
|
def connectTilelinkNasti(nasti: NastiIO, tl: ClientUncachedTileLinkIO)(implicit p: Parameters) = {
|
||||||
|
val conv = Module(new NastiIOTileLinkIOConverter())
|
||||||
|
conv.io.tl <> tl
|
||||||
|
TopUtils.connectNasti(nasti, conv.io.nasti)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Top-level module for the chip */
|
/** Top-level module for the chip */
|
||||||
@ -111,19 +113,17 @@ class Top(topParams: Parameters) extends Module with HasTopLevelParameters {
|
|||||||
// Connect each tile to the HTIF
|
// Connect each tile to the HTIF
|
||||||
uncore.io.htif.zip(tileList).zipWithIndex.foreach {
|
uncore.io.htif.zip(tileList).zipWithIndex.foreach {
|
||||||
case ((hl, tile), i) =>
|
case ((hl, tile), i) =>
|
||||||
|
tile.io.host.timerIRQ := uncore.io.timerIRQs(i)
|
||||||
tile.io.host.id := UInt(i)
|
tile.io.host.id := UInt(i)
|
||||||
tile.io.host.reset := Reg(next=Reg(next=hl.reset))
|
tile.io.host.reset := Reg(next=Reg(next=hl.reset))
|
||||||
tile.io.host.csr.req <> Queue(hl.csr.req)
|
tile.io.host.csr.req <> Queue(hl.csr.req)
|
||||||
hl.csr.resp <> Queue(tile.io.host.csr.resp)
|
hl.csr.resp <> Queue(tile.io.host.csr.resp)
|
||||||
hl.debug_stats_csr := tile.io.host.debug_stats_csr
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Connect the uncore to the tile memory ports, HostIO and MemIO
|
// Connect the uncore to the tile memory ports, HostIO and MemIO
|
||||||
uncore.io.tiles_cached <> tileList.map(_.io.cached).flatten
|
uncore.io.tiles_cached <> tileList.map(_.io.cached).flatten
|
||||||
uncore.io.tiles_uncached <> tileList.map(_.io.uncached).flatten
|
uncore.io.tiles_uncached <> tileList.map(_.io.uncached).flatten
|
||||||
io.host <> uncore.io.host
|
io.host <> uncore.io.host
|
||||||
if (p(UseBackupMemoryPort)) { io.mem_backup_ctrl <> uncore.io.mem_backup_ctrl }
|
|
||||||
else { uncore.io.mem_backup_ctrl.en := Bool(false) }
|
|
||||||
|
|
||||||
io.mem.zip(uncore.io.mem).foreach { case (outer, inner) =>
|
io.mem.zip(uncore.io.mem).foreach { case (outer, inner) =>
|
||||||
TopUtils.connectNasti(outer, inner)
|
TopUtils.connectNasti(outer, inner)
|
||||||
@ -146,7 +146,7 @@ class Uncore(implicit val p: Parameters) extends Module
|
|||||||
val tiles_cached = Vec(nCachedTilePorts, new ClientTileLinkIO).flip
|
val tiles_cached = Vec(nCachedTilePorts, new ClientTileLinkIO).flip
|
||||||
val tiles_uncached = Vec(nUncachedTilePorts, new ClientUncachedTileLinkIO).flip
|
val tiles_uncached = Vec(nUncachedTilePorts, new ClientUncachedTileLinkIO).flip
|
||||||
val htif = Vec(nTiles, new HtifIO).flip
|
val htif = Vec(nTiles, new HtifIO).flip
|
||||||
val mem_backup_ctrl = new MemBackupCtrlIO
|
val timerIRQs = Vec(nTiles, Bool()).asOutput
|
||||||
val mmio = new NastiIO
|
val mmio = new NastiIO
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,25 +160,20 @@ class Uncore(implicit val p: Parameters) extends Module
|
|||||||
for (i <- 0 until nTiles) {
|
for (i <- 0 until nTiles) {
|
||||||
io.htif(i).reset := htif.io.cpu(i).reset
|
io.htif(i).reset := htif.io.cpu(i).reset
|
||||||
io.htif(i).id := htif.io.cpu(i).id
|
io.htif(i).id := htif.io.cpu(i).id
|
||||||
htif.io.cpu(i).debug_stats_csr <> io.htif(i).debug_stats_csr
|
io.htif(i).csr <> htif.io.cpu(i).csr
|
||||||
|
|
||||||
val csr_arb = Module(new SmiArbiter(2, xLen, csrAddrBits))
|
|
||||||
csr_arb.io.in(0) <> htif.io.cpu(i).csr
|
|
||||||
csr_arb.io.in(1) <> outmemsys.io.csr(i)
|
|
||||||
io.htif(i).csr <> csr_arb.io.out
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Arbitrate SCR access between MMIO and HTIF
|
val addrMap = p(GlobalAddrMap)
|
||||||
val addrHashMap = new AddrHashMap(p(GlobalAddrMap))
|
val addrHashMap = new AddrHashMap(addrMap)
|
||||||
val scrFile = Module(new SCRFile("UNCORE_SCR",addrHashMap("conf:scr").start))
|
val memSize = addrHashMap("mem").size
|
||||||
val scrArb = Module(new SmiArbiter(2, scrDataBits, scrAddrBits))
|
val scrFile = Module(new SCRFile("UNCORE_SCR", 0))
|
||||||
scrArb.io.in(0) <> htif.io.scr
|
scrFile.io.smi <> htif.io.scr
|
||||||
scrArb.io.in(1) <> outmemsys.io.scr
|
|
||||||
scrFile.io.smi <> scrArb.io.out
|
|
||||||
scrFile.io.scr.attach(Wire(init = UInt(nTiles)), "N_CORES")
|
scrFile.io.scr.attach(Wire(init = UInt(nTiles)), "N_CORES")
|
||||||
scrFile.io.scr.attach(Wire(init = UInt(addrHashMap("mem").size >> 20)), "MMIO_BASE")
|
scrFile.io.scr.attach(Wire(init = UInt(memSize >> 20)), "MMIO_BASE")
|
||||||
// scrFile.io.scr <> (... your SCR connections ...)
|
// scrFile.io.scr <> (... your SCR connections ...)
|
||||||
|
|
||||||
|
buildMMIONetwork(p.alterPartial({case TLId => "MMIO_Outermost"}))
|
||||||
|
|
||||||
// Configures the enabled memory channels. This can't be changed while the
|
// Configures the enabled memory channels. This can't be changed while the
|
||||||
// chip is actively using memory, as it both drops Nasti messages and garbles
|
// chip is actively using memory, as it both drops Nasti messages and garbles
|
||||||
// all of memory.
|
// all of memory.
|
||||||
@ -187,19 +182,40 @@ class Uncore(implicit val p: Parameters) extends Module
|
|||||||
"MEMORY_CHANNEL_MUX_SELECT")
|
"MEMORY_CHANNEL_MUX_SELECT")
|
||||||
outmemsys.io.memory_channel_mux_select := memory_channel_mux_select
|
outmemsys.io.memory_channel_mux_select := memory_channel_mux_select
|
||||||
|
|
||||||
val deviceTree = Module(new NastiROM(p(ConfigString).toSeq))
|
|
||||||
deviceTree.io <> outmemsys.io.deviceTree
|
|
||||||
|
|
||||||
// Wire the htif to the memory port(s) and host interface
|
// Wire the htif to the memory port(s) and host interface
|
||||||
io.host.debug_stats_csr := htif.io.host.debug_stats_csr
|
|
||||||
io.mem <> outmemsys.io.mem
|
io.mem <> outmemsys.io.mem
|
||||||
if(p(UseHtifClockDiv)) {
|
if(p(UseHtifClockDiv)) {
|
||||||
outmemsys.io.mem_backup_en := io.mem_backup_ctrl.en
|
VLSIUtils.padOutHTIFWithDividedClock(htif.io.host, scrFile.io.scr, io.host, htifW)
|
||||||
VLSIUtils.padOutHTIFWithDividedClock(htif.io.host, scrFile.io.scr,
|
|
||||||
outmemsys.io.mem_backup, io.mem_backup_ctrl, io.host, htifW)
|
|
||||||
} else {
|
} else {
|
||||||
io.host.out <> htif.io.host.out
|
io.host <> htif.io.host
|
||||||
htif.io.host.in <> io.host.in
|
}
|
||||||
|
|
||||||
|
def buildMMIONetwork(implicit p: Parameters) = {
|
||||||
|
val mmioNarrower = Module(new TileLinkIONarrower("L2toMMIO", "MMIO_Outermost"))
|
||||||
|
val mmioNetwork = Module(new TileLinkRecursiveInterconnect(1, addrMap.tail, memSize))
|
||||||
|
|
||||||
|
mmioNarrower.io.in <> outmemsys.io.mmio
|
||||||
|
mmioNetwork.io.in.head <> mmioNarrower.io.out
|
||||||
|
|
||||||
|
if (p(UseStreamLoopback)) {
|
||||||
|
val lo_width = p(StreamLoopbackWidth)
|
||||||
|
val lo_size = p(StreamLoopbackSize)
|
||||||
|
val lo_conv = Module(new NastiIOStreamIOConverter(lo_width))
|
||||||
|
val lo_port = addrHashMap("devices:loopback").port - 1
|
||||||
|
TopUtils.connectTilelinkNasti(lo_conv.io.nasti, mmioNetwork.io.out(lo_port))
|
||||||
|
lo_conv.io.stream.in <> Queue(lo_conv.io.stream.out, lo_size)
|
||||||
|
}
|
||||||
|
|
||||||
|
val rtc = Module(new RTC(p(NTiles)))
|
||||||
|
val rtcAddr = addrHashMap("conf:rtc")
|
||||||
|
val rtcPort = rtcAddr.port - 1
|
||||||
|
require(rtc.size <= rtcAddr.size)
|
||||||
|
rtc.io.tl <> mmioNetwork.io.out(rtcPort)
|
||||||
|
io.timerIRQs := rtc.io.irqs
|
||||||
|
|
||||||
|
val deviceTree = Module(new ROMSlave(p(ConfigString).toSeq))
|
||||||
|
val dtPort = addrHashMap("conf:devicetree").port - 1
|
||||||
|
deviceTree.io <> mmioNetwork.io.out(dtPort)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,25 +229,18 @@ class OuterMemorySystem(implicit val p: Parameters) extends Module with HasTopLe
|
|||||||
val htif_uncached = (new ClientUncachedTileLinkIO).flip
|
val htif_uncached = (new ClientUncachedTileLinkIO).flip
|
||||||
val incoherent = Vec(nTiles, Bool()).asInput
|
val incoherent = Vec(nTiles, Bool()).asInput
|
||||||
val mem = Vec(nMemChannels, new NastiIO)
|
val mem = Vec(nMemChannels, new NastiIO)
|
||||||
val mem_backup = new MemSerializedIO(htifW)
|
|
||||||
val mem_backup_en = Bool(INPUT)
|
|
||||||
val memory_channel_mux_select = UInt(INPUT, log2Up(memoryChannelMuxConfigs.size))
|
val memory_channel_mux_select = UInt(INPUT, log2Up(memoryChannelMuxConfigs.size))
|
||||||
val csr = Vec(nTiles, new SmiIO(xLen, csrAddrBits))
|
val mmio = new ClientUncachedTileLinkIO()(p.alterPartial({case TLId => "L2toMMIO"}))
|
||||||
val scr = new SmiIO(xLen, scrAddrBits)
|
|
||||||
val deviceTree = new NastiIO
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val addrMap = p(GlobalAddrMap)
|
val addrHashMap = new AddrHashMap(p(GlobalAddrMap))
|
||||||
val addrHashMap = new AddrHashMap(addrMap)
|
|
||||||
val memSize = addrHashMap("mem").size
|
|
||||||
|
|
||||||
// Create a simple L1toL2 NoC between the tiles+htif and the banks of outer memory
|
// Create a simple L1toL2 NoC between the tiles+htif and the banks of outer memory
|
||||||
// Cached ports are first in client list, making sharerToClientId just an indentity function
|
// Cached ports are first in client list, making sharerToClientId just an indentity function
|
||||||
// addrToBank is sed to hash physical addresses (of cache blocks) to banks (and thereby memory channels)
|
// addrToBank is sed to hash physical addresses (of cache blocks) to banks (and thereby memory channels)
|
||||||
def sharerToClientId(sharerId: UInt) = sharerId
|
def sharerToClientId(sharerId: UInt) = sharerId
|
||||||
def addrToBank(addr: Bits): UInt = {
|
def addrToBank(addr: UInt): UInt = {
|
||||||
val isMemory = addrHashMap.isInRegion("mem",
|
val isMemory = addrHashMap.isInRegion("mem", addr << log2Up(p(CacheBlockBytes)))
|
||||||
addr.toUInt << log2Up(p(CacheBlockBytes)))
|
|
||||||
Mux(isMemory,
|
Mux(isMemory,
|
||||||
if (nBanks > 1) addr(lsb + log2Up(nBanks) - 1, lsb) else UInt(0),
|
if (nBanks > 1) addr(lsb + log2Up(nBanks) - 1, lsb) else UInt(0),
|
||||||
UInt(nBanks))
|
UInt(nBanks))
|
||||||
@ -248,13 +257,12 @@ class OuterMemorySystem(implicit val p: Parameters) extends Module with HasTopLe
|
|||||||
case InnerTLId => "L1toL2"
|
case InnerTLId => "L1toL2"
|
||||||
case OuterTLId => "L2toMMIO"
|
case OuterTLId => "L2toMMIO"
|
||||||
})))
|
})))
|
||||||
|
io.mmio <> mmioManager.io.outer
|
||||||
val rtc = Module(new RTC(CSRs.mtime))
|
|
||||||
|
|
||||||
// Wire the tiles and htif to the TileLink client ports of the L1toL2 network,
|
// Wire the tiles and htif to the TileLink client ports of the L1toL2 network,
|
||||||
// and coherence manager(s) to the other side
|
// and coherence manager(s) to the other side
|
||||||
l1tol2net.io.clients_cached <> io.tiles_cached
|
l1tol2net.io.clients_cached <> io.tiles_cached
|
||||||
l1tol2net.io.clients_uncached <> io.tiles_uncached ++ Seq(rtc.io, io.htif_uncached)
|
l1tol2net.io.clients_uncached <> io.tiles_uncached ++ Seq(io.htif_uncached)
|
||||||
l1tol2net.io.managers <> managerEndpoints.map(_.innerTL) :+ mmioManager.io.inner
|
l1tol2net.io.managers <> managerEndpoints.map(_.innerTL) :+ mmioManager.io.inner
|
||||||
|
|
||||||
// Create a converter between TileLinkIO and MemIO for each channel
|
// Create a converter between TileLinkIO and MemIO for each channel
|
||||||
@ -262,7 +270,6 @@ class OuterMemorySystem(implicit val p: Parameters) extends Module with HasTopLe
|
|||||||
val outermostTLParams = p.alterPartial({case TLId => "Outermost"})
|
val outermostTLParams = p.alterPartial({case TLId => "Outermost"})
|
||||||
val backendBuffering = TileLinkDepths(0,0,0,0,0)
|
val backendBuffering = TileLinkDepths(0,0,0,0,0)
|
||||||
|
|
||||||
|
|
||||||
// TODO: the code to print this stuff should live somewhere else
|
// TODO: the code to print this stuff should live somewhere else
|
||||||
println("Generated Address Map")
|
println("Generated Address Map")
|
||||||
for ((name, base, size, _, _) <- addrHashMap.sortedEntries) {
|
for ((name, base, size, _, _) <- addrHashMap.sortedEntries) {
|
||||||
@ -295,67 +302,6 @@ class OuterMemorySystem(implicit val p: Parameters) extends Module with HasTopLe
|
|||||||
mem_ic.io.in(i) <> narrow.io.out
|
mem_ic.io.in(i) <> narrow.io.out
|
||||||
}
|
}
|
||||||
|
|
||||||
val mmioOutermostTLParams = p.alterPartial({case TLId => "MMIO_Outermost"})
|
for ((nasti, tl) <- io.mem zip mem_ic.io.out)
|
||||||
|
TopUtils.connectTilelinkNasti(nasti, tl)(outermostTLParams)
|
||||||
val mmio_narrow = Module(new TileLinkIONarrower("L2toMMIO", "MMIO_Outermost"))
|
|
||||||
val mmio_net = Module(new TileLinkRecursiveInterconnect(
|
|
||||||
1, addrHashMap.nEntries - 1, addrMap.tail, memSize)(mmioOutermostTLParams))
|
|
||||||
|
|
||||||
//val mmio_conv = Module(new NastiIOTileLinkIOConverter()(outermostTLParams))
|
|
||||||
mmio_narrow.io.in <> mmioManager.io.outer
|
|
||||||
mmio_net.io.in.head <> mmio_narrow.io.out
|
|
||||||
|
|
||||||
def connectTilelinkNasti(nasti: NastiIO, tl: ClientUncachedTileLinkIO)(implicit p: Parameters) = {
|
|
||||||
val conv = Module(new NastiIOTileLinkIOConverter())
|
|
||||||
conv.io.tl <> tl
|
|
||||||
TopUtils.connectNasti(nasti, conv.io.nasti)
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i <- 0 until nTiles) {
|
|
||||||
val csrName = s"conf:csr$i"
|
|
||||||
val csrPort = addrHashMap(csrName).port - 1
|
|
||||||
val conv = Module(new SmiIONastiIOConverter(xLen, csrAddrBits))
|
|
||||||
connectTilelinkNasti(conv.io.nasti, mmio_net.io.out(csrPort))(mmioOutermostTLParams)
|
|
||||||
io.csr(i) <> conv.io.smi
|
|
||||||
}
|
|
||||||
|
|
||||||
val scrPort = addrHashMap("conf:scr").port - 1
|
|
||||||
val scr_conv = Module(new SmiIONastiIOConverter(scrDataBits, scrAddrBits))
|
|
||||||
connectTilelinkNasti(scr_conv.io.nasti, mmio_net.io.out(scrPort))(mmioOutermostTLParams)
|
|
||||||
io.scr <> scr_conv.io.smi
|
|
||||||
|
|
||||||
if (p(UseStreamLoopback)) {
|
|
||||||
val lo_width = p(StreamLoopbackWidth)
|
|
||||||
val lo_size = p(StreamLoopbackSize)
|
|
||||||
val lo_conv = Module(new NastiIOStreamIOConverter(lo_width))
|
|
||||||
val lo_port = addrHashMap("devices:loopback").port - 1
|
|
||||||
connectTilelinkNasti(lo_conv.io.nasti, mmio_net.io.out(lo_port))(mmioOutermostTLParams)
|
|
||||||
lo_conv.io.stream.in <> Queue(lo_conv.io.stream.out, lo_size)
|
|
||||||
}
|
|
||||||
|
|
||||||
val dtPort = addrHashMap("conf:devicetree").port - 1
|
|
||||||
connectTilelinkNasti(io.deviceTree, mmio_net.io.out(dtPort))(mmioOutermostTLParams)
|
|
||||||
|
|
||||||
val mem_channels = Wire(Vec(nMemChannels, new NastiIO))
|
|
||||||
|
|
||||||
mem_channels.zip(mem_ic.io.out).foreach { case (ch, out) =>
|
|
||||||
connectTilelinkNasti(ch, out)(outermostTLParams)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a SerDes for backup memory port
|
|
||||||
if(p(UseBackupMemoryPort)) {
|
|
||||||
VLSIUtils.doOuterMemorySystemSerdes(
|
|
||||||
mem_channels, io.mem, io.mem_backup, io.mem_backup_en,
|
|
||||||
1, htifW, p(CacheBlockOffsetBits))
|
|
||||||
for (i <- 1 until nMemChannels) { io.mem(i) <> mem_channels(i) }
|
|
||||||
val mem_request = mem_channels.map(io => io.ar.valid || io.aw.valid).reduce(_ || _)
|
|
||||||
val config_nchannels = Vec(channelConfigs.map(i => UInt(i)))(io.memory_channel_mux_select)
|
|
||||||
assert(!mem_request || !io.mem_backup_en || config_nchannels === UInt(1),
|
|
||||||
"Backup memory port only works when 1 memory channel is enabled")
|
|
||||||
require(channelConfigs.sortWith(_ < _)(0) == 1,
|
|
||||||
"Backup memory port requires a single memory port mux config")
|
|
||||||
} else {
|
|
||||||
io.mem <> mem_channels
|
|
||||||
io.mem_backup.req.valid := Bool(false)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,6 @@ object TestBenchGeneration extends FileSystemUtilities {
|
|||||||
wire [`HTIF_WIDTH-1:0] htif_in_bits;
|
wire [`HTIF_WIDTH-1:0] htif_in_bits;
|
||||||
wire htif_in_ready, htif_out_valid;
|
wire htif_in_ready, htif_out_valid;
|
||||||
wire [`HTIF_WIDTH-1:0] htif_out_bits;
|
wire [`HTIF_WIDTH-1:0] htif_out_bits;
|
||||||
wire htif_out_stats;
|
|
||||||
|
|
||||||
wire mem_bk_in_valid;
|
wire mem_bk_in_valid;
|
||||||
wire mem_bk_out_valid;
|
wire mem_bk_out_valid;
|
||||||
@ -74,12 +73,6 @@ object TestBenchGeneration extends FileSystemUtilities {
|
|||||||
wire htif_out_ready_delay;
|
wire htif_out_ready_delay;
|
||||||
wire [`HTIF_WIDTH-1:0] htif_out_bits_delay;
|
wire [`HTIF_WIDTH-1:0] htif_out_bits_delay;
|
||||||
|
|
||||||
wire htif_out_stats_delay;
|
|
||||||
|
|
||||||
wire mem_bk_out_ready_delay;
|
|
||||||
wire mem_bk_in_valid_delay;
|
|
||||||
wire mem_bk_out_valid_delay;
|
|
||||||
|
|
||||||
assign #0.1 htif_in_valid_delay = htif_in_valid;
|
assign #0.1 htif_in_valid_delay = htif_in_valid;
|
||||||
assign #0.1 htif_in_ready = htif_in_ready_delay;
|
assign #0.1 htif_in_ready = htif_in_ready_delay;
|
||||||
assign #0.1 htif_in_bits_delay = htif_in_bits;
|
assign #0.1 htif_in_bits_delay = htif_in_bits;
|
||||||
@ -87,12 +80,6 @@ object TestBenchGeneration extends FileSystemUtilities {
|
|||||||
assign #0.1 htif_out_valid = htif_out_valid_delay;
|
assign #0.1 htif_out_valid = htif_out_valid_delay;
|
||||||
assign #0.1 htif_out_ready_delay = htif_out_ready;
|
assign #0.1 htif_out_ready_delay = htif_out_ready;
|
||||||
assign #0.1 htif_out_bits = htif_out_bits_delay;
|
assign #0.1 htif_out_bits = htif_out_bits_delay;
|
||||||
|
|
||||||
assign #0.1 htif_out_stats = htif_out_stats_delay;
|
|
||||||
|
|
||||||
assign #0.1 mem_bk_out_ready_delay = mem_bk_out_ready;
|
|
||||||
assign #0.1 mem_bk_in_valid_delay = mem_bk_in_valid;
|
|
||||||
assign #0.1 mem_bk_out_valid = mem_bk_out_valid_delay;
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
val nasti_delays = (0 until nMemChannel) map { i => s"""
|
val nasti_delays = (0 until nMemChannel) map { i => s"""
|
||||||
@ -216,8 +203,6 @@ object TestBenchGeneration extends FileSystemUtilities {
|
|||||||
|
|
||||||
val instantiation = s"""
|
val instantiation = s"""
|
||||||
`ifdef FPGA
|
`ifdef FPGA
|
||||||
assign mem_bk_out_valid_delay = 1'b0;
|
|
||||||
assign htif_out_stats_delay = 1'b0;
|
|
||||||
assign htif_clk = clk;
|
assign htif_clk = clk;
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
@ -231,25 +216,9 @@ object TestBenchGeneration extends FileSystemUtilities {
|
|||||||
`ifndef FPGA
|
`ifndef FPGA
|
||||||
.io_host_clk(htif_clk),
|
.io_host_clk(htif_clk),
|
||||||
.io_host_clk_edge(),
|
.io_host_clk_edge(),
|
||||||
.io_host_debug_stats_csr(htif_out_stats_delay),
|
|
||||||
|
|
||||||
`ifdef MEM_BACKUP_EN
|
|
||||||
.io_mem_backup_ctrl_en(1'b1),
|
|
||||||
`else
|
|
||||||
.io_mem_backup_ctrl_en(1'b0),
|
|
||||||
`endif // MEM_BACKUP_EN
|
|
||||||
.io_mem_backup_ctrl_in_valid(mem_bk_in_valid_delay),
|
|
||||||
.io_mem_backup_ctrl_out_ready(mem_bk_out_ready_delay),
|
|
||||||
.io_mem_backup_ctrl_out_valid(mem_bk_out_valid_delay),
|
|
||||||
`else
|
`else
|
||||||
.io_host_clk (),
|
.io_host_clk (),
|
||||||
.io_host_clk_edge (),
|
.io_host_clk_edge (),
|
||||||
.io_host_debug_stats_csr (),
|
|
||||||
|
|
||||||
.io_mem_backup_ctrl_en (1'b0),
|
|
||||||
.io_mem_backup_ctrl_in_valid (1'b0),
|
|
||||||
.io_mem_backup_ctrl_out_ready (1'b0),
|
|
||||||
.io_mem_backup_ctrl_out_valid (),
|
|
||||||
`endif // FPGA
|
`endif // FPGA
|
||||||
|
|
||||||
.io_host_in_valid(htif_in_valid_delay),
|
.io_host_in_valid(htif_in_valid_delay),
|
||||||
|
@ -7,14 +7,6 @@ import cde.Parameters
|
|||||||
import junctions._
|
import junctions._
|
||||||
import uncore._
|
import uncore._
|
||||||
|
|
||||||
class MemDessert(topParams: Parameters) extends Module {
|
|
||||||
implicit val p = topParams
|
|
||||||
val io = new MemDesserIO(p(HtifKey).width)
|
|
||||||
val x = Module(new MemDesser(p(HtifKey).width))
|
|
||||||
x.io.narrow <> io.narrow
|
|
||||||
io.wide <> x.io.wide
|
|
||||||
}
|
|
||||||
|
|
||||||
object VLSIUtils {
|
object VLSIUtils {
|
||||||
def doOuterMemorySystemSerdes(
|
def doOuterMemorySystemSerdes(
|
||||||
llcs: Seq[NastiIO],
|
llcs: Seq[NastiIO],
|
||||||
@ -65,6 +57,30 @@ object VLSIUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private def makeHTIFClockDivider(scr: SCRIO, host: HostIO, htifW: Int) = {
|
||||||
|
val hio = Module((new SlowIO(512)) { Bits(width = htifW) })
|
||||||
|
hio.io.set_divisor.valid := scr.wen && (scr.waddr === UInt(63))
|
||||||
|
hio.io.set_divisor.bits := scr.wdata
|
||||||
|
scr.rdata(63) := hio.io.divisor
|
||||||
|
scr.allocate(63, "HTIF_IO_CLOCK_DIVISOR")
|
||||||
|
host.clk := hio.io.clk_slow
|
||||||
|
host.clk_edge := Reg(next=host.clk && !Reg(next=host.clk))
|
||||||
|
hio
|
||||||
|
}
|
||||||
|
|
||||||
|
def padOutHTIFWithDividedClock(
|
||||||
|
htif: HostIO,
|
||||||
|
scr: SCRIO,
|
||||||
|
host: HostIO,
|
||||||
|
htifW: Int) {
|
||||||
|
val hio = makeHTIFClockDivider(scr, host, htifW)
|
||||||
|
|
||||||
|
hio.io.out_fast <> htif.out
|
||||||
|
host.out <> hio.io.out_slow
|
||||||
|
hio.io.in_slow <> host.in
|
||||||
|
htif.in <> hio.io.in_fast
|
||||||
|
}
|
||||||
|
|
||||||
def padOutHTIFWithDividedClock(
|
def padOutHTIFWithDividedClock(
|
||||||
htif: HostIO,
|
htif: HostIO,
|
||||||
scr: SCRIO,
|
scr: SCRIO,
|
||||||
@ -72,11 +88,7 @@ object VLSIUtils {
|
|||||||
parent: MemBackupCtrlIO,
|
parent: MemBackupCtrlIO,
|
||||||
host: HostIO,
|
host: HostIO,
|
||||||
htifW: Int) {
|
htifW: Int) {
|
||||||
val hio = Module((new SlowIO(512)) { Bits(width = htifW+1) })
|
val hio = makeHTIFClockDivider(scr, host, htifW+1)
|
||||||
hio.io.set_divisor.valid := scr.wen && (scr.waddr === UInt(63))
|
|
||||||
hio.io.set_divisor.bits := scr.wdata
|
|
||||||
scr.rdata(63) := hio.io.divisor
|
|
||||||
scr.allocate(63, "HTIF_IO_CLOCK_DIVISOR")
|
|
||||||
|
|
||||||
hio.io.out_fast.valid := htif.out.valid || child.req.valid
|
hio.io.out_fast.valid := htif.out.valid || child.req.valid
|
||||||
hio.io.out_fast.bits := Cat(htif.out.valid, Mux(htif.out.valid, htif.out.bits, child.req.bits))
|
hio.io.out_fast.bits := Cat(htif.out.valid, Mux(htif.out.valid, htif.out.bits, child.req.bits))
|
||||||
@ -96,7 +108,5 @@ object VLSIUtils {
|
|||||||
htif.in.valid := hio.io.in_fast.valid && !hio.io.in_fast.bits(htifW)
|
htif.in.valid := hio.io.in_fast.valid && !hio.io.in_fast.bits(htifW)
|
||||||
htif.in.bits := hio.io.in_fast.bits
|
htif.in.bits := hio.io.in_fast.bits
|
||||||
hio.io.in_fast.ready := Mux(hio.io.in_fast.bits(htifW), Bool(true), htif.in.ready)
|
hio.io.in_fast.ready := Mux(hio.io.in_fast.bits(htifW), Bool(true), htif.in.ready)
|
||||||
host.clk := hio.io.clk_slow
|
|
||||||
host.clk_edge := Reg(next=host.clk && !Reg(next=host.clk))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
2
uncore
2
uncore
@ -1 +1 @@
|
|||||||
Subproject commit 6aac33ff3eefdca9e0eda2540e7f4a311cd3c02c
|
Subproject commit 291a0bbf58006bc1d2587c58fa7d63abd7d57083
|
@ -7,9 +7,7 @@
|
|||||||
sim_vsrcs = \
|
sim_vsrcs = \
|
||||||
$(generated_dir)/$(MODEL).$(CONFIG).v \
|
$(generated_dir)/$(MODEL).$(CONFIG).v \
|
||||||
$(generated_dir)/consts.$(CONFIG).vh \
|
$(generated_dir)/consts.$(CONFIG).vh \
|
||||||
$(generated_dir)/memdessertMemDessert.$(CONFIG).v \
|
|
||||||
$(base_dir)/vsrc/$(TB).v \
|
$(base_dir)/vsrc/$(TB).v \
|
||||||
$(base_dir)/vsrc/backup_mem.v \
|
|
||||||
|
|
||||||
# C sources
|
# C sources
|
||||||
|
|
||||||
|
@ -10,9 +10,6 @@ $(generated_dir)/$(MODEL).$(CONFIG).v $(generated_dir)/$(MODEL).$(CONFIG).d $(ge
|
|||||||
$(mem_gen) $(generated_dir)/$(MODEL).$(CONFIG).conf >> $(generated_dir)/$(MODEL).$(CONFIG).v; \
|
$(mem_gen) $(generated_dir)/$(MODEL).$(CONFIG).conf >> $(generated_dir)/$(MODEL).$(CONFIG).v; \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
$(generated_dir)/memdessertMemDessert.$(CONFIG).v $(generated_dir)/memdessertMemDessert.$(CONFIG).d: $(base_dir)/$(src_path)/*.scala $(base_dir)/uncore/$(src_path)/*.scala
|
|
||||||
cd $(base_dir) && mkdir -p $(generated_dir) && $(SBT) "run $(PROJECT) MemDessert $(CONFIG) --backend v --targetDir $(generated_dir) --W0W --moduleNamePrefix memdessert --configName $(CONFIG)"
|
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
FIRRTL ?= $(base_dir)/firrtl/utils/bin/firrtl
|
FIRRTL ?= $(base_dir)/firrtl/utils/bin/firrtl
|
||||||
@ -23,7 +20,6 @@ $(FIRRTL):
|
|||||||
# If I don't mark these as .SECONDARY then make will delete these internal
|
# If I don't mark these as .SECONDARY then make will delete these internal
|
||||||
# files.
|
# files.
|
||||||
.SECONDARY: $(generated_dir)/$(MODEL).$(CONFIG).fir
|
.SECONDARY: $(generated_dir)/$(MODEL).$(CONFIG).fir
|
||||||
.SECONDARY: $(generated_dir)/MemDessert.$(CONFIG).fir
|
|
||||||
|
|
||||||
$(generated_dir)/%.$(CONFIG).fir: $(chisel_srcs)
|
$(generated_dir)/%.$(CONFIG).fir: $(chisel_srcs)
|
||||||
mkdir -p $(dir $@)
|
mkdir -p $(dir $@)
|
||||||
@ -34,12 +30,6 @@ $(generated_dir)/%.v $(generated_dir)/%.prm: $(generated_dir)/%.fir $(FIRRTL)
|
|||||||
mkdir -p $(dir $@)
|
mkdir -p $(dir $@)
|
||||||
$(FIRRTL) $(patsubst %,-i %,$(filter %.fir,$^)) -o $@ -X verilog
|
$(FIRRTL) $(patsubst %,-i %,$(filter %.fir,$^)) -o $@ -X verilog
|
||||||
|
|
||||||
$(generated_dir)/memdessertMemDessert.$(CONFIG).v: $(generated_dir)/MemDessert.$(CONFIG).v
|
|
||||||
cat $(filter %.v,$^) \
|
|
||||||
| sed 's@MemDessert@memdessertMemDessert@g' \
|
|
||||||
| sed 's@Queue@memdessetQueue@g' \
|
|
||||||
> $@
|
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
$(generated_dir)/consts.$(CONFIG).vh: $(generated_dir)/$(MODEL).$(CONFIG).prm
|
$(generated_dir)/consts.$(CONFIG).vh: $(generated_dir)/$(MODEL).$(CONFIG).prm
|
||||||
|
@ -1,122 +0,0 @@
|
|||||||
// See LICENSE for license details.
|
|
||||||
|
|
||||||
`define ceilLog2(x) ( \
|
|
||||||
(x) > 2**30 ? 31 : \
|
|
||||||
(x) > 2**29 ? 30 : \
|
|
||||||
(x) > 2**28 ? 29 : \
|
|
||||||
(x) > 2**27 ? 28 : \
|
|
||||||
(x) > 2**26 ? 27 : \
|
|
||||||
(x) > 2**25 ? 26 : \
|
|
||||||
(x) > 2**24 ? 25 : \
|
|
||||||
(x) > 2**23 ? 24 : \
|
|
||||||
(x) > 2**22 ? 23 : \
|
|
||||||
(x) > 2**21 ? 22 : \
|
|
||||||
(x) > 2**20 ? 21 : \
|
|
||||||
(x) > 2**19 ? 20 : \
|
|
||||||
(x) > 2**18 ? 19 : \
|
|
||||||
(x) > 2**17 ? 18 : \
|
|
||||||
(x) > 2**16 ? 17 : \
|
|
||||||
(x) > 2**15 ? 16 : \
|
|
||||||
(x) > 2**14 ? 15 : \
|
|
||||||
(x) > 2**13 ? 14 : \
|
|
||||||
(x) > 2**12 ? 13 : \
|
|
||||||
(x) > 2**11 ? 12 : \
|
|
||||||
(x) > 2**10 ? 11 : \
|
|
||||||
(x) > 2**9 ? 10 : \
|
|
||||||
(x) > 2**8 ? 9 : \
|
|
||||||
(x) > 2**7 ? 8 : \
|
|
||||||
(x) > 2**6 ? 7 : \
|
|
||||||
(x) > 2**5 ? 6 : \
|
|
||||||
(x) > 2**4 ? 5 : \
|
|
||||||
(x) > 2**3 ? 4 : \
|
|
||||||
(x) > 2**2 ? 3 : \
|
|
||||||
(x) > 2**1 ? 2 : \
|
|
||||||
(x) > 2**0 ? 1 : 0)
|
|
||||||
|
|
||||||
`ifdef MEM_BACKUP_EN
|
|
||||||
module BackupMemory
|
|
||||||
(
|
|
||||||
input clk,
|
|
||||||
input reset,
|
|
||||||
|
|
||||||
input mem_req_valid,
|
|
||||||
output mem_req_ready,
|
|
||||||
input mem_req_rw,
|
|
||||||
input [`MIF_ADDR_BITS-1:0] mem_req_addr,
|
|
||||||
input [`MIF_TAG_BITS-1:0] mem_req_tag,
|
|
||||||
|
|
||||||
input mem_req_data_valid,
|
|
||||||
output mem_req_data_ready,
|
|
||||||
input [`MIF_DATA_BITS-1:0] mem_req_data_bits,
|
|
||||||
|
|
||||||
output reg mem_resp_valid,
|
|
||||||
output reg [`MIF_DATA_BITS-1:0] mem_resp_data,
|
|
||||||
output reg [`MIF_TAG_BITS-1:0] mem_resp_tag
|
|
||||||
);
|
|
||||||
|
|
||||||
localparam DATA_CYCLES = 8;
|
|
||||||
localparam DEPTH = 2*1024*1024;
|
|
||||||
|
|
||||||
reg [`ceilLog2(DATA_CYCLES)-1:0] cnt;
|
|
||||||
reg [`MIF_TAG_BITS-1:0] tag;
|
|
||||||
reg state_busy, state_rw;
|
|
||||||
reg [`MIF_ADDR_BITS-1:0] addr;
|
|
||||||
|
|
||||||
reg [127:0] ram [DEPTH-1:0];
|
|
||||||
wire [`ceilLog2(DEPTH)-1:0] ram_addr = state_busy ? {addr[`ceilLog2(DEPTH/DATA_CYCLES)-1:0], cnt}
|
|
||||||
: {mem_req_addr[`ceilLog2(DEPTH/DATA_CYCLES)-1:0], cnt};
|
|
||||||
wire do_read = mem_req_valid && mem_req_ready && !mem_req_rw || state_busy && !state_rw;
|
|
||||||
wire do_write = mem_req_data_valid && mem_req_data_ready;
|
|
||||||
|
|
||||||
initial
|
|
||||||
begin : zero
|
|
||||||
integer i;
|
|
||||||
for (i = 0; i < DEPTH; i = i+1)
|
|
||||||
ram[i] = 1'b0;
|
|
||||||
end
|
|
||||||
|
|
||||||
always @(posedge clk)
|
|
||||||
begin
|
|
||||||
if (reset)
|
|
||||||
state_busy <= 1'b0;
|
|
||||||
else if ((do_read || do_write) && cnt == DATA_CYCLES-1)
|
|
||||||
state_busy <= 1'b0;
|
|
||||||
else if (mem_req_valid && mem_req_ready)
|
|
||||||
state_busy <= 1'b1;
|
|
||||||
|
|
||||||
if (!state_busy && mem_req_valid)
|
|
||||||
begin
|
|
||||||
state_rw <= mem_req_rw;
|
|
||||||
tag <= mem_req_tag;
|
|
||||||
addr <= mem_req_addr;
|
|
||||||
end
|
|
||||||
|
|
||||||
if (reset)
|
|
||||||
cnt <= 1'b0;
|
|
||||||
else if(do_read || do_write)
|
|
||||||
cnt <= cnt + 1'b1;
|
|
||||||
|
|
||||||
if (do_write)
|
|
||||||
if (ram_addr[0] == 1'b0)
|
|
||||||
ram[ram_addr/2][63:0] <= mem_req_data_bits;
|
|
||||||
else
|
|
||||||
ram[ram_addr/2][127:64] <= mem_req_data_bits;
|
|
||||||
else
|
|
||||||
if (ram_addr[0] == 1'b0)
|
|
||||||
mem_resp_data <= ram[ram_addr/2][63:0];
|
|
||||||
else
|
|
||||||
mem_resp_data <= ram[ram_addr/2][127:64];
|
|
||||||
|
|
||||||
if (reset)
|
|
||||||
mem_resp_valid <= 1'b0;
|
|
||||||
else
|
|
||||||
mem_resp_valid <= do_read;
|
|
||||||
|
|
||||||
mem_resp_tag <= state_busy ? tag : mem_req_tag;
|
|
||||||
end
|
|
||||||
|
|
||||||
assign mem_req_ready = !state_busy;
|
|
||||||
assign mem_req_data_ready = state_busy && state_rw;
|
|
||||||
|
|
||||||
endmodule
|
|
||||||
`endif
|
|
@ -75,8 +75,6 @@ module rocketTestHarness;
|
|||||||
reg [1023:0] loadmem = 0;
|
reg [1023:0] loadmem = 0;
|
||||||
reg [1023:0] vcdplusfile = 0;
|
reg [1023:0] vcdplusfile = 0;
|
||||||
reg [1023:0] vcdfile = 0;
|
reg [1023:0] vcdfile = 0;
|
||||||
reg stats_active = 0;
|
|
||||||
reg stats_tracking = 0;
|
|
||||||
reg verbose = 0;
|
reg verbose = 0;
|
||||||
wire printf_cond = verbose && !reset;
|
wire printf_cond = verbose && !reset;
|
||||||
integer stderr = 32'h80000002;
|
integer stderr = 32'h80000002;
|
||||||
@ -88,81 +86,11 @@ module rocketTestHarness;
|
|||||||
r_reset <= reset;
|
r_reset <= reset;
|
||||||
end
|
end
|
||||||
|
|
||||||
wire mem_bk_req_valid, mem_bk_req_rw, mem_bk_req_data_valid;
|
|
||||||
wire [`MIF_TAG_BITS-1:0] mem_bk_req_tag;
|
|
||||||
wire [`MIF_ADDR_BITS-1:0] mem_bk_req_addr;
|
|
||||||
wire [`MIF_DATA_BITS-1:0] mem_bk_req_data_bits;
|
|
||||||
wire mem_bk_req_ready, mem_bk_req_data_ready, mem_bk_resp_valid;
|
|
||||||
wire [`MIF_TAG_BITS-1:0] mem_bk_resp_tag;
|
|
||||||
wire [`MIF_DATA_BITS-1:0] mem_bk_resp_data;
|
|
||||||
|
|
||||||
`ifdef MEM_BACKUP_EN
|
|
||||||
memdessertMemDessert dessert
|
|
||||||
(
|
|
||||||
.clk(htif_clk),
|
|
||||||
.reset(reset),
|
|
||||||
|
|
||||||
.io_narrow_req_valid(mem_bk_out_valid),
|
|
||||||
.io_narrow_req_ready(mem_bk_out_ready),
|
|
||||||
.io_narrow_req_bits(htif_out_bits),
|
|
||||||
|
|
||||||
.io_narrow_resp_valid(mem_bk_in_valid),
|
|
||||||
.io_narrow_resp_bits(mem_in_bits),
|
|
||||||
|
|
||||||
.io_wide_req_cmd_valid(mem_bk_req_valid),
|
|
||||||
.io_wide_req_cmd_ready(mem_bk_req_ready),
|
|
||||||
.io_wide_req_cmd_bits_rw(mem_bk_req_rw),
|
|
||||||
.io_wide_req_cmd_bits_addr(mem_bk_req_addr),
|
|
||||||
.io_wide_req_cmd_bits_tag(mem_bk_req_tag),
|
|
||||||
|
|
||||||
.io_wide_req_data_valid(mem_bk_req_data_valid),
|
|
||||||
.io_wide_req_data_ready(mem_bk_req_data_ready),
|
|
||||||
.io_wide_req_data_bits_data(mem_bk_req_data_bits),
|
|
||||||
|
|
||||||
.io_wide_resp_valid(mem_bk_resp_valid),
|
|
||||||
.io_wide_resp_ready(),
|
|
||||||
.io_wide_resp_bits_data(mem_bk_resp_data),
|
|
||||||
.io_wide_resp_bits_tag(mem_bk_resp_tag)
|
|
||||||
);
|
|
||||||
|
|
||||||
BackupMemory mem
|
|
||||||
(
|
|
||||||
.clk(htif_clk),
|
|
||||||
.reset(reset),
|
|
||||||
|
|
||||||
.mem_req_valid(mem_bk_req_valid),
|
|
||||||
.mem_req_ready(mem_bk_req_ready),
|
|
||||||
.mem_req_rw(mem_bk_req_rw),
|
|
||||||
.mem_req_addr(mem_bk_req_addr),
|
|
||||||
.mem_req_tag(mem_bk_req_tag),
|
|
||||||
|
|
||||||
.mem_req_data_valid(mem_bk_req_data_valid),
|
|
||||||
.mem_req_data_ready(mem_bk_req_data_ready),
|
|
||||||
.mem_req_data_bits(mem_bk_req_data_bits),
|
|
||||||
|
|
||||||
.mem_resp_valid(mem_bk_resp_valid),
|
|
||||||
.mem_resp_data(mem_bk_resp_data),
|
|
||||||
.mem_resp_tag(mem_bk_resp_tag)
|
|
||||||
);
|
|
||||||
`else
|
|
||||||
// set dessert outputs to zero when !backupmem_en
|
|
||||||
assign mem_bk_out_ready = 1'b0;
|
|
||||||
assign mem_bk_in_valid = 1'b0;
|
|
||||||
assign mem_in_bits = {`HTIF_WIDTH {1'b0}};
|
|
||||||
assign mem_bk_req_valid = 1'b0;
|
|
||||||
assign mem_bk_req_ready = 1'b0;
|
|
||||||
assign mem_bk_req_addr = {`MIF_ADDR_BITS {1'b0}};
|
|
||||||
assign mem_bk_req_rw = 1'b0;
|
|
||||||
assign mem_bk_req_tag = {`MIF_TAG_BITS {1'b0}};
|
|
||||||
assign mem_bk_req_data_valid = 1'b0;
|
|
||||||
assign mem_bk_req_data_bits = 16'd0;
|
|
||||||
`endif
|
|
||||||
|
|
||||||
reg htif_in_valid_premux;
|
reg htif_in_valid_premux;
|
||||||
reg [`HTIF_WIDTH-1:0] htif_in_bits_premux;
|
reg [`HTIF_WIDTH-1:0] htif_in_bits_premux;
|
||||||
assign htif_in_bits = mem_bk_in_valid ? mem_in_bits : htif_in_bits_premux;
|
assign htif_in_bits = htif_in_bits_premux;
|
||||||
assign htif_in_valid = htif_in_valid_premux && !mem_bk_in_valid;
|
assign htif_in_valid = htif_in_valid_premux;
|
||||||
wire htif_in_ready_premux = htif_in_ready && !mem_bk_in_valid;
|
wire htif_in_ready_premux = htif_in_ready;
|
||||||
reg [31:0] exit = 0;
|
reg [31:0] exit = 0;
|
||||||
|
|
||||||
always @(posedge htif_clk)
|
always @(posedge htif_clk)
|
||||||
@ -191,40 +119,6 @@ module rocketTestHarness;
|
|||||||
//-----------------------------------------------
|
//-----------------------------------------------
|
||||||
// Start the simulation
|
// Start the simulation
|
||||||
|
|
||||||
// Some helper functions for turning on, stopping, and finishing stat tracking
|
|
||||||
task start_stats;
|
|
||||||
begin
|
|
||||||
if(!reset || !stats_active)
|
|
||||||
begin
|
|
||||||
`ifdef DEBUG
|
|
||||||
if(vcdplusfile)
|
|
||||||
begin
|
|
||||||
$vcdpluson(0);
|
|
||||||
$vcdplusmemon(0);
|
|
||||||
end
|
|
||||||
if(vcdfile)
|
|
||||||
begin
|
|
||||||
$dumpon;
|
|
||||||
end
|
|
||||||
`endif
|
|
||||||
assign stats_tracking = 1;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
endtask
|
|
||||||
task stop_stats;
|
|
||||||
begin
|
|
||||||
`ifdef DEBUG
|
|
||||||
$vcdplusoff; $dumpoff;
|
|
||||||
`endif
|
|
||||||
assign stats_tracking = 0;
|
|
||||||
end
|
|
||||||
endtask
|
|
||||||
`ifdef DEBUG
|
|
||||||
`define VCDPLUSCLOSE $vcdplusclose; $dumpoff;
|
|
||||||
`else
|
|
||||||
`define VCDPLUSCLOSE
|
|
||||||
`endif
|
|
||||||
|
|
||||||
// Read input arguments and initialize
|
// Read input arguments and initialize
|
||||||
initial
|
initial
|
||||||
begin
|
begin
|
||||||
@ -236,27 +130,22 @@ module rocketTestHarness;
|
|||||||
`endif
|
`endif
|
||||||
verbose = $test$plusargs("verbose");
|
verbose = $test$plusargs("verbose");
|
||||||
`ifdef DEBUG
|
`ifdef DEBUG
|
||||||
stats_active = $test$plusargs("stats");
|
|
||||||
if ($value$plusargs("vcdplusfile=%s", vcdplusfile))
|
if ($value$plusargs("vcdplusfile=%s", vcdplusfile))
|
||||||
begin
|
begin
|
||||||
$vcdplusfile(vcdplusfile);
|
$vcdplusfile(vcdplusfile);
|
||||||
|
$vcdpluson(0);
|
||||||
|
$vcdplusmemon(0);
|
||||||
end
|
end
|
||||||
|
|
||||||
if ($value$plusargs("vcdfile=%s", vcdfile))
|
if ($value$plusargs("vcdfile=%s", vcdfile))
|
||||||
begin
|
begin
|
||||||
$dumpfile(vcdfile);
|
$dumpfile(vcdfile);
|
||||||
$dumpvars(0, dut);
|
$dumpvars(0, dut);
|
||||||
|
$dumpon;
|
||||||
end
|
end
|
||||||
if (!stats_active)
|
`define VCDPLUSCLOSE $vcdplusclose; $dumpoff;
|
||||||
begin
|
`else
|
||||||
start_stats;
|
`define VCDPLUSCLOSE
|
||||||
end
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
if(vcdfile)
|
|
||||||
begin
|
|
||||||
$dumpoff;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
// Strobe reset
|
// Strobe reset
|
||||||
@ -286,32 +175,6 @@ module rocketTestHarness;
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
//-----------------------------------------------
|
|
||||||
// Tracing code
|
|
||||||
|
|
||||||
always @(posedge clk)
|
|
||||||
begin
|
|
||||||
if(stats_active)
|
|
||||||
begin
|
|
||||||
if(!stats_tracking && htif_out_stats)
|
|
||||||
begin
|
|
||||||
start_stats;
|
|
||||||
end
|
|
||||||
if(stats_tracking && !htif_out_stats)
|
|
||||||
begin
|
|
||||||
stop_stats;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
always @(posedge htif_clk)
|
|
||||||
begin
|
|
||||||
if (verbose && mem_bk_req_valid && mem_bk_req_ready)
|
|
||||||
begin
|
|
||||||
$fdisplay(stderr, "MB: rw=%d addr=%x", mem_bk_req_rw, {mem_bk_req_addr,6'd0});
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
always @(posedge clk)
|
always @(posedge clk)
|
||||||
begin
|
begin
|
||||||
trace_count = trace_count + 1;
|
trace_count = trace_count + 1;
|
||||||
|
Loading…
Reference in New Issue
Block a user