Skip to content

Commit

Permalink
Merge pull request chipsalliance#2178 from chipsalliance/diplomatic-i…
Browse files Browse the repository at this point in the history
…o-creation-2

Modernize Port Creation
  • Loading branch information
hcook authored Nov 8, 2019
2 parents 47f9089 + f763667 commit 54237b5
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 103 deletions.
3 changes: 1 addition & 2 deletions src/main/scala/groundtest/GroundTestSubsystem.scala
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,7 @@ class GroundTestSubsystem(implicit p: Parameters) extends BaseSubsystem
override lazy val module = new GroundTestSubsystemModuleImp(this)
}

class GroundTestSubsystemModuleImp[+L <: GroundTestSubsystem](_outer: L) extends BaseSubsystemModuleImp(_outer)
with CanHaveMasterAXI4MemPortModuleImp {
class GroundTestSubsystemModuleImp[+L <: GroundTestSubsystem](_outer: L) extends BaseSubsystemModuleImp(_outer) {
val success = IO(Bool(OUTPUT))

outer.tiles.zipWithIndex.map { case(t, i) => t.module.constants.hartid := UInt(i) }
Expand Down
7 changes: 4 additions & 3 deletions src/main/scala/groundtest/TestHarness.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@
package freechips.rocketchip.groundtest

import Chisel._

import freechips.rocketchip.config.Parameters
import freechips.rocketchip.diplomacy.LazyModule
import freechips.rocketchip.system.SimAXIMem

class TestHarness(implicit p: Parameters) extends Module {
val io = new Bundle { val success = Bool(OUTPUT) }
val dut = Module(LazyModule(new GroundTestSubsystem).module)
val ldut = LazyModule(new GroundTestSubsystem)
val dut = Module(ldut.module)
io.success := dut.success
dut.connectSimAXIMem()
SimAXIMem.connectMem(ldut)
}
140 changes: 49 additions & 91 deletions src/main/scala/subsystem/Ports.scala
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,12 @@ case object ExtIn extends Field[Option[SlavePortParams]](None)

/** Adds a port to the system intended to master an AXI4 DRAM controller. */
trait CanHaveMasterAXI4MemPort { this: BaseSubsystem =>
val module: CanHaveMasterAXI4MemPortModuleImp

val memAXI4Node = p(ExtMem).map { case MemoryPortParams(memPortParams, nMemoryChannels) =>
val portName = "axi4"
val device = new MemoryDevice

val memAXI4Node = AXI4SlaveNode(Seq.tabulate(nMemoryChannels) { channel =>
private val memPortParamsOpt = p(ExtMem)
private val portName = "axi4"
private val device = new MemoryDevice
private val idBits = memPortParamsOpt.map(_.master.idBits).getOrElse(1)
val memAXI4Node = AXI4SlaveNode(memPortParamsOpt.map({ case MemoryPortParams(memPortParams, nMemoryChannels) =>
Seq.tabulate(nMemoryChannels) { channel =>
val base = AddressSet.misaligned(memPortParams.base, memPortParams.size)
val filter = AddressSet(channel * mbus.blockBytes, ~((nMemoryChannels-1) * mbus.blockBytes))

Expand All @@ -50,33 +49,19 @@ trait CanHaveMasterAXI4MemPort { this: BaseSubsystem =>
supportsRead = TransferSizes(1, mbus.blockBytes),
interleavedId = Some(0))), // slave does not interleave read responses
beatBytes = memPortParams.beatBytes)
})

memAXI4Node :*= mbus.toDRAMController(Some(portName)) {
AXI4UserYanker() :*= AXI4IdIndexer(memPortParams.idBits) :*= TLToAXI4()
}

memAXI4Node
}).toList.flatten)

mbus.coupleTo(s"memory_controller_port_named_$portName") {
(memAXI4Node
:*= AXI4UserYanker()
:*= AXI4IdIndexer(idBits)
:*= TLToAXI4()
:*= TLWidthWidget(mbus.beatBytes)
:*= _)
}
}

/** Actually generates the corresponding IO in the concrete Module */
trait CanHaveMasterAXI4MemPortModuleImp extends LazyModuleImp {
val outer: CanHaveMasterAXI4MemPort

val mem_axi4 = outer.memAXI4Node.map(x => IO(HeterogeneousBag.fromNode(x.in)))
(mem_axi4 zip outer.memAXI4Node) foreach { case (io, node) =>
(io zip node.in).foreach { case (io, (bundle, _)) => io <> bundle }
}

def connectSimAXIMem() {
(mem_axi4 zip outer.memAXI4Node).foreach { case (io, node) =>
(io zip node.in).foreach { case (io, (_, edge)) =>
val mem = LazyModule(new SimAXIMem(edge, size = p(ExtMem).get.master.size))
Module(mem.module).io.axi4.head <> io
}
}
}
val mem_axi4 = InModuleBody { memAXI4Node.makeIOs() }
}

/** Adds a AXI4 port to the system intended to master an MMIO device bus */
Expand All @@ -97,30 +82,19 @@ trait CanHaveMasterAXI4MMIOPort { this: BaseSubsystem =>
beatBytes = params.beatBytes)).toSeq)

mmioPortParamsOpt.map { params =>
mmioAXI4Node := sbus.toFixedWidthPort(Some(portName)) {
(AXI4Buffer()
sbus.coupleTo(s"port_named_$portName") {
(mmioAXI4Node
:= AXI4Buffer()
:= AXI4UserYanker()
:= AXI4Deinterleaver(sbus.blockBytes)
:= AXI4IdIndexer(params.idBits)
:= TLToAXI4())
:= TLToAXI4()
:= TLWidthWidget(sbus.beatBytes)
:= _)
}
}
}

/** Actually generates the corresponding IO in the concrete Module */
trait CanHaveMasterAXI4MMIOPortModuleImp extends LazyModuleImp {
val outer: CanHaveMasterAXI4MMIOPort
val mmio_axi4 = IO(HeterogeneousBag.fromNode(outer.mmioAXI4Node.in))

(mmio_axi4 zip outer.mmioAXI4Node.in) foreach { case (io, (bundle, _)) => io <> bundle }

def connectSimAXIMMIO() {
(mmio_axi4 zip outer.mmioAXI4Node.in) foreach { case (io, (_, edge)) =>
// test harness size capped to 4KB (ignoring p(ExtMem).get.master.size)
val mmio_mem = LazyModule(new SimAXIMem(edge, size = 4096))
Module(mmio_mem.module).io.axi4.head <> io
}
}
val mmio_axi4 = InModuleBody { mmioAXI4Node.makeIOs() }
}

/** Adds an AXI4 port to the system intended to be a slave on an MMIO device bus */
Expand All @@ -137,21 +111,20 @@ trait CanHaveSlaveAXI4Port { this: BaseSubsystem =>
id = IdRange(0, 1 << params.idBits))))).toSeq)

slavePortParamsOpt.map { params =>
fbus.fromPort(Some(portName), buffer = BufferParams.default) {
(TLWidthWidget(params.beatBytes)
fbus.coupleFrom(s"port_named_$portName") {
( _
:= TLBuffer(BufferParams.default)
:= TLFIFOFixer(TLFIFOFixer.all)
:= TLWidthWidget(params.beatBytes)
:= AXI4ToTL()
:= AXI4UserYanker(Some(1 << (params.sourceBits - fifoBits - 1)))
:= AXI4Fragmenter()
:= AXI4IdIndexer(fifoBits))
} := l2FrontendAXI4Node
:= AXI4IdIndexer(fifoBits)
:= l2FrontendAXI4Node )
}
}
}

/** Actually generates the corresponding IO in the concrete Module */
trait CanHaveSlaveAXI4PortModuleImp extends LazyModuleImp {
val outer: CanHaveSlaveAXI4Port
val l2_frontend_bus_axi4 = IO(HeterogeneousBag.fromNode(outer.l2FrontendAXI4Node.out).flip)
(outer.l2FrontendAXI4Node.out zip l2_frontend_bus_axi4) foreach { case ((bundle, _), io) => bundle <> io }
val l2_frontend_bus_axi4 = InModuleBody { l2FrontendAXI4Node.makeIOs() }
}

/** Adds a TileLink port to the system intended to master an MMIO device bus */
Expand All @@ -173,18 +146,19 @@ trait CanHaveMasterTLMMIOPort { this: BaseSubsystem =>
beatBytes = params.beatBytes)).toSeq)

mmioPortParamsOpt.map { params =>
mmioTLNode := sbus.toFixedWidthPort(Some(portName)) {
TLBuffer() := TLSourceShrinker(1 << params.idBits)
sbus.coupleTo(s"port_named_$portName") {
(mmioTLNode
:= TLBuffer()
:= TLSourceShrinker(1 << params.idBits)
:= TLWidthWidget(sbus.beatBytes)
:= _ )
}
}
}


/** Actually generates the corresponding IO in the concrete Module */
trait CanHaveMasterTLMMIOPortModuleImp extends LazyModuleImp {
val outer: CanHaveMasterTLMMIOPort
val mmio_tl = IO(HeterogeneousBag.fromNode(outer.mmioTLNode.in))
(mmio_tl zip outer.mmioTLNode.in) foreach { case (io, (bundle, _)) => io <> bundle }
val mmio_tl = InModuleBody {
mmioTLNode.out.foreach { case (_, edge) => println(edge.prettySourceMapping(s"TL MMIO Port")) }
mmioTLNode.makeIOs()
}
}

/** Adds an TL port to the system intended to be a slave on an MMIO device bus.
Expand All @@ -202,29 +176,13 @@ trait CanHaveSlaveTLPort { this: BaseSubsystem =>
sourceId = IdRange(0, 1 << params.idBits))))).toSeq)

slavePortParamsOpt.map { params =>
sbus.fromPort(Some(portName)) {
TLSourceShrinker(1 << params.sourceBits) := TLWidthWidget(params.beatBytes)
} := l2FrontendTLNode
sbus.coupleFrom(s"port_named_$portName") {
( _
:= TLSourceShrinker(1 << params.sourceBits)
:= TLWidthWidget(params.beatBytes)
:= l2FrontendTLNode )
}
}
}

/** Actually generates the corresponding IO in the concrete Module */
trait CanHaveSlaveTLPortModuleImp extends LazyModuleImp {
val outer: CanHaveSlaveTLPort
val l2_frontend_bus_tl = IO(HeterogeneousBag.fromNode(outer.l2FrontendTLNode.out).flip)
(outer.l2FrontendTLNode.out zip l2_frontend_bus_tl) foreach { case ((bundle, _), io) => bundle <> io }
}

/** Memory with AXI port for use in elaboratable test harnesses. */
class SimAXIMem(edge: AXI4EdgeParameters, size: BigInt)(implicit p: Parameters) extends LazyModule {
val node = AXI4MasterNode(List(edge.master))
val srams = AddressSet.misaligned(0, size).map{ aSet => LazyModule(new AXI4RAM(aSet, beatBytes = edge.bundle.dataBits/8))}
val xbar = AXI4Xbar()
srams.foreach{ s => s.node := AXI4Buffer() := AXI4Fragmenter() := xbar }
xbar := node

lazy val module = new LazyModuleImp(this) {
val io = IO(new Bundle { val axi4 = HeterogeneousBag.fromNode(node.out).flip })
(node.out zip io.axi4) foreach { case ((bundle, _), io) => bundle <> io }
}
val l2_frontend_bus_tl = InModuleBody { l2FrontendTLNode.makeIOs() }
}
3 changes: 0 additions & 3 deletions src/main/scala/system/ExampleRocketSystem.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,5 @@ class ExampleRocketSystem(implicit p: Parameters) extends RocketSubsystem
class ExampleRocketSystemModuleImp[+L <: ExampleRocketSystem](_outer: L) extends RocketSubsystemModuleImp(_outer)
with HasRTCModuleImp
with HasExtInterruptsModuleImp
with CanHaveMasterAXI4MemPortModuleImp
with CanHaveMasterAXI4MMIOPortModuleImp
with CanHaveSlaveAXI4PortModuleImp
with HasPeripheryBootROMModuleImp
with DontTouch
40 changes: 40 additions & 0 deletions src/main/scala/system/SimAXIMem.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// See LICENSE.SiFive for license details.

package freechips.rocketchip.system // TODO this should really be in a testharness package

import chisel3._
import freechips.rocketchip.amba.axi4._
import freechips.rocketchip.config.{Parameters}
import freechips.rocketchip.diplomacy._
import freechips.rocketchip.subsystem.{CanHaveMasterAXI4MMIOPort, CanHaveMasterAXI4MemPort, ExtMem}

/** Memory with AXI port for use in elaboratable test harnesses. */
class SimAXIMem(edge: AXI4EdgeParameters, size: BigInt)(implicit p: Parameters) extends SimpleLazyModule {
val node = AXI4MasterNode(List(edge.master))
val srams = AddressSet.misaligned(0, size).map{ aSet => LazyModule(new AXI4RAM(aSet, beatBytes = edge.bundle.dataBits/8))}
val xbar = AXI4Xbar()
srams.foreach{ s => s.node := AXI4Buffer() := AXI4Fragmenter() := xbar }
xbar := node
val io_axi4 = InModuleBody { node.makeIOs() }
}

object SimAXIMem {
def connectMMIO(dut: CanHaveMasterAXI4MMIOPort)(implicit p: Parameters): Seq[SimAXIMem] = {
dut.mmio_axi4.zip(dut.mmioAXI4Node.in).map { case (io, (_, edge)) =>
// test harness size capped to 4KB (ignoring p(ExtMem).get.master.size)
val mmio_mem = LazyModule(new SimAXIMem(edge, size = 4096))
Module(mmio_mem.module).suggestName("mmio_mem")
mmio_mem.io_axi4.head <> io
mmio_mem
}
}

def connectMem(dut: CanHaveMasterAXI4MemPort)(implicit p: Parameters): Seq[SimAXIMem] = {
dut.mem_axi4.zip(dut.memAXI4Node.in).map { case (io, (_, edge)) =>
val mem = LazyModule(new SimAXIMem(edge, size = p(ExtMem).get.master.size))
Module(mem.module).suggestName("mem")
mem.io_axi4.head <> io
mem
}
}
}
9 changes: 5 additions & 4 deletions src/main/scala/system/TestHarness.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,16 @@ class TestHarness()(implicit p: Parameters) extends Module {
val success = Bool(OUTPUT)
}

val dut = Module(LazyModule(new ExampleRocketSystem).module)
val ldut = LazyModule(new ExampleRocketSystem)
val dut = Module(ldut.module)

// Allow the debug ndreset to reset the dut, but not until the initial reset has completed
dut.reset := reset | dut.debug.map { debug => AsyncResetReg(debug.ndreset) }.getOrElse(false.B)

dut.dontTouchPorts()
dut.tieOffInterrupts()
dut.connectSimAXIMem()
dut.connectSimAXIMMIO()
dut.l2_frontend_bus_axi4.foreach(_.tieoff)
SimAXIMem.connectMem(ldut)
SimAXIMem.connectMMIO(ldut)
ldut.l2_frontend_bus_axi4.foreach(_.tieoff)
Debug.connectDebug(dut.debug, dut.psd, clock, reset, io.success)
}

0 comments on commit 54237b5

Please sign in to comment.