1
0

refactor NASTI to not use param; new AddrMap class

This commit is contained in:
Henry Cook 2015-10-02 14:19:51 -07:00
parent a08872c0e9
commit 39a749843c
3 changed files with 181 additions and 164 deletions

View File

@ -6,21 +6,20 @@ import scala.math.max
import scala.collection.mutable.ArraySeq import scala.collection.mutable.ArraySeq
import scala.collection.mutable.HashMap import scala.collection.mutable.HashMap
case object NastiBitWidths extends Field[NastiParameters]
case object NastiAddrMap extends Field[AddrMap]
case object MMIOBase extends Field[BigInt] case object MMIOBase extends Field[BigInt]
case object NASTIDataBits extends Field[Int]
case object NASTIAddrBits extends Field[Int]
case object NASTIIdBits extends Field[Int]
object bigIntPow2 { case class NastiParameters(dataBits: Int, addrBits: Int, idBits: Int)
def apply(in: BigInt): Boolean = in > 0 && ((in & (in-1)) == 0)
}
trait NASTIParameters extends UsesParameters { trait HasNastiParameters {
val nastiXDataBits = params(NASTIDataBits) implicit val p: Parameters
val external = p(NastiBitWidths)
val nastiXDataBits = external.dataBits
val nastiWStrobeBits = nastiXDataBits / 8 val nastiWStrobeBits = nastiXDataBits / 8
val nastiXAddrBits = params(NASTIAddrBits) val nastiXAddrBits = external.addrBits
val nastiWIdBits = params(NASTIIdBits) val nastiWIdBits = external.idBits
val nastiRIdBits = params(NASTIIdBits) val nastiRIdBits = external.idBits
val nastiXIdBits = max(nastiWIdBits, nastiRIdBits) val nastiXIdBits = max(nastiWIdBits, nastiRIdBits)
val nastiXUserBits = 1 val nastiXUserBits = 1
val nastiAWUserBits = nastiXUserBits val nastiAWUserBits = nastiXUserBits
@ -48,22 +47,16 @@ trait NASTIParameters extends UsesParameters {
UInt(128) -> UInt(7))) UInt(128) -> UInt(7)))
} }
abstract class NASTIBundle extends Bundle with NASTIParameters abstract class NastiModule extends Module with HasNastiParameters
abstract class NASTIModule extends Module with NASTIParameters abstract class NastiBundle(implicit val p: Parameters) extends Bundle with HasNastiParameters {
override def cloneType = this.getClass.getConstructors.head.newInstance(p).asInstanceOf[this.type]
trait NASTIChannel extends NASTIBundle
trait NASTIMasterToSlaveChannel extends NASTIChannel
trait NASTISlaveToMasterChannel extends NASTIChannel
class NASTIIO extends Bundle {
val aw = Decoupled(new NASTIWriteAddressChannel)
val w = Decoupled(new NASTIWriteDataChannel)
val b = Decoupled(new NASTIWriteResponseChannel).flip
val ar = Decoupled(new NASTIReadAddressChannel)
val r = Decoupled(new NASTIReadDataChannel).flip
} }
trait HasNASTIMetadata extends NASTIBundle { abstract class NastiChannel(implicit p: Parameters) extends NastiBundle()(p)
abstract class NastiMasterToSlaveChannel(implicit p: Parameters) extends NastiChannel()(p)
abstract class NastiSlaveToMasterChannel(implicit p: Parameters) extends NastiChannel()(p)
trait HasNastiMetadata extends HasNastiParameters {
val addr = UInt(width = nastiXAddrBits) val addr = UInt(width = nastiXAddrBits)
val len = UInt(width = nastiXLenBits) val len = UInt(width = nastiXLenBits)
val size = UInt(width = nastiXSizeBits) val size = UInt(width = nastiXSizeBits)
@ -75,45 +68,56 @@ trait HasNASTIMetadata extends NASTIBundle {
val region = UInt(width = nastiXRegionBits) val region = UInt(width = nastiXRegionBits)
} }
trait HasNASTIData extends NASTIBundle { trait HasNastiData extends HasNastiParameters {
val data = UInt(width = nastiXDataBits) val data = UInt(width = nastiXDataBits)
val last = Bool() val last = Bool()
} }
class NASTIAddressChannel extends NASTIMasterToSlaveChannel with HasNASTIMetadata class NastiIO(implicit p: Parameters) extends NastiBundle()(p) {
val aw = Decoupled(new NastiWriteAddressChannel)
val w = Decoupled(new NastiWriteDataChannel)
val b = Decoupled(new NastiWriteResponseChannel).flip
val ar = Decoupled(new NastiReadAddressChannel)
val r = Decoupled(new NastiReadDataChannel).flip
}
class NASTIResponseChannel extends NASTISlaveToMasterChannel { class NastiAddressChannel(implicit p: Parameters) extends NastiMasterToSlaveChannel()(p)
with HasNastiMetadata
class NastiResponseChannel(implicit p: Parameters) extends NastiSlaveToMasterChannel()(p) {
val resp = UInt(width = nastiXRespBits) val resp = UInt(width = nastiXRespBits)
} }
class NASTIWriteAddressChannel extends NASTIAddressChannel { class NastiWriteAddressChannel(implicit p: Parameters) extends NastiAddressChannel()(p) {
val id = UInt(width = nastiWIdBits) val id = UInt(width = nastiWIdBits)
val user = UInt(width = nastiAWUserBits) val user = UInt(width = nastiAWUserBits)
} }
class NASTIWriteDataChannel extends NASTIMasterToSlaveChannel with HasNASTIData { class NastiWriteDataChannel(implicit p: Parameters) extends NastiMasterToSlaveChannel()(p)
with HasNastiData {
val strb = UInt(width = nastiWStrobeBits) val strb = UInt(width = nastiWStrobeBits)
val user = UInt(width = nastiWUserBits) val user = UInt(width = nastiWUserBits)
} }
class NASTIWriteResponseChannel extends NASTIResponseChannel { class NastiWriteResponseChannel(implicit p: Parameters) extends NastiResponseChannel()(p) {
val id = UInt(width = nastiWIdBits) val id = UInt(width = nastiWIdBits)
val user = UInt(width = nastiBUserBits) val user = UInt(width = nastiBUserBits)
} }
class NASTIReadAddressChannel extends NASTIAddressChannel { class NastiReadAddressChannel(implicit p: Parameters) extends NastiAddressChannel()(p) {
val id = UInt(width = nastiRIdBits) val id = UInt(width = nastiRIdBits)
val user = UInt(width = nastiARUserBits) val user = UInt(width = nastiARUserBits)
} }
class NASTIReadDataChannel extends NASTIResponseChannel with HasNASTIData { class NastiReadDataChannel(implicit p: Parameters) extends NastiResponseChannel()(p)
with HasNastiData {
val id = UInt(width = nastiRIdBits) val id = UInt(width = nastiRIdBits)
val user = UInt(width = nastiRUserBits) val user = UInt(width = nastiRUserBits)
} }
object NASTIWriteAddressChannel { object NastiWriteAddressChannel {
def apply(id: UInt, addr: UInt, size: UInt, len: UInt = UInt(0)) = { def apply(id: UInt, addr: UInt, size: UInt, len: UInt = UInt(0))(implicit p: Parameters) = {
val aw = Wire(new NASTIWriteAddressChannel) val aw = Wire(new NastiWriteAddressChannel)
aw.id := id aw.id := id
aw.addr := addr aw.addr := addr
aw.len := len aw.len := len
@ -129,9 +133,9 @@ object NASTIWriteAddressChannel {
} }
} }
object NASTIReadAddressChannel { object NastiReadAddressChannel {
def apply(id: UInt, addr: UInt, size: UInt, len: UInt = UInt(0)) = { def apply(id: UInt, addr: UInt, size: UInt, len: UInt = UInt(0))(implicit p: Parameters) = {
val ar = Wire(new NASTIReadAddressChannel) val ar = Wire(new NastiReadAddressChannel)
ar.id := id ar.id := id
ar.addr := addr ar.addr := addr
ar.len := len ar.len := len
@ -147,22 +151,27 @@ object NASTIReadAddressChannel {
} }
} }
object NASTIWriteDataChannel { object NastiWriteDataChannel {
private def strobeBits = new NASTIWriteDataChannel().nastiWStrobeBits def apply(data: UInt, last: Bool = Bool(true))(implicit p: Parameters): NastiWriteDataChannel = {
def fullStrobe = Fill(strobeBits, UInt(1, 1)) val w = Wire(new NastiWriteDataChannel)
def apply(data: UInt, strb: UInt = fullStrobe, last: Bool = Bool(true)) = { w.strb := Fill(w.nastiWStrobeBits, UInt(1, 1))
val w = Wire(new NASTIWriteDataChannel)
w.strb := strb
w.data := data w.data := data
w.last := last w.last := last
w.user := UInt(0) w.user := UInt(0)
w w
} }
def apply(data: UInt, strb: UInt, last: Bool)
(implicit p: Parameters): NastiWriteDataChannel = {
val w = apply(data, last)
w.strb := strb
w
}
} }
object NASTIReadDataChannel { object NastiReadDataChannel {
def apply(id: UInt, data: UInt, last: Bool = Bool(true), resp: UInt = UInt(0)) = { def apply(id: UInt, data: UInt, last: Bool = Bool(true), resp: UInt = UInt(0))(
val r = Wire(new NASTIReadDataChannel) implicit p: Parameters) = {
val r = Wire(new NastiReadDataChannel)
r.id := id r.id := id
r.data := data r.data := data
r.last := last r.last := last
@ -172,9 +181,9 @@ object NASTIReadDataChannel {
} }
} }
object NASTIWriteResponseChannel { object NastiWriteResponseChannel {
def apply(id: UInt, resp: UInt = UInt(0)) = { def apply(id: UInt, resp: UInt = UInt(0))(implicit p: Parameters) = {
val b = Wire(new NASTIWriteResponseChannel) val b = Wire(new NastiWriteResponseChannel)
b.id := id b.id := id
b.resp := resp b.resp := resp
b.user := UInt(0) b.user := UInt(0)
@ -182,9 +191,10 @@ object NASTIWriteResponseChannel {
} }
} }
class MemIONASTIIOConverter(cacheBlockOffsetBits: Int) extends MIFModule with NASTIParameters { class MemIONastiIOConverter(cacheBlockOffsetBits: Int)(implicit val p: Parameters) extends MIFModule
with HasNastiParameters {
val io = new Bundle { val io = new Bundle {
val nasti = (new NASTIIO).flip val nasti = (new NastiIO).flip
val mem = new MemIO val mem = new MemIO
} }
@ -192,13 +202,13 @@ class MemIONASTIIOConverter(cacheBlockOffsetBits: Int) extends MIFModule with NA
val (mif_cnt_out, mif_wrap_out) = Counter(io.mem.resp.fire(), mifDataBeats) val (mif_cnt_out, mif_wrap_out) = Counter(io.mem.resp.fire(), mifDataBeats)
assert(!io.nasti.aw.valid || io.nasti.aw.bits.size === UInt(log2Up(mifDataBits/8)), assert(!io.nasti.aw.valid || io.nasti.aw.bits.size === UInt(log2Up(mifDataBits/8)),
"NASTI data size does not match MemIO data size") "Nasti data size does not match MemIO data size")
assert(!io.nasti.ar.valid || io.nasti.ar.bits.size === UInt(log2Up(mifDataBits/8)), assert(!io.nasti.ar.valid || io.nasti.ar.bits.size === UInt(log2Up(mifDataBits/8)),
"NASTI data size does not match MemIO data size") "Nasti data size does not match MemIO data size")
assert(!io.nasti.aw.valid || io.nasti.aw.bits.len === UInt(mifDataBeats - 1), assert(!io.nasti.aw.valid || io.nasti.aw.bits.len === UInt(mifDataBeats - 1),
"NASTI length does not match number of MemIO beats") "Nasti length does not match number of MemIO beats")
assert(!io.nasti.ar.valid || io.nasti.ar.bits.len === UInt(mifDataBeats - 1), assert(!io.nasti.ar.valid || io.nasti.ar.bits.len === UInt(mifDataBeats - 1),
"NASTI length does not match number of MemIO beats") "Nasti length does not match number of MemIO beats")
// according to the spec, we can't send b until the last transfer on w // according to the spec, we can't send b until the last transfer on w
val b_ok = Reg(init = Bool(true)) val b_ok = Reg(init = Bool(true))
@ -236,17 +246,17 @@ class MemIONASTIIOConverter(cacheBlockOffsetBits: Int) extends MIFModule with NA
} }
/** Arbitrate among arbN masters requesting to a single slave */ /** Arbitrate among arbN masters requesting to a single slave */
class NASTIArbiter(val arbN: Int) extends NASTIModule { class NastiArbiter(val arbN: Int)(implicit val p: Parameters) extends NastiModule {
val io = new Bundle { val io = new Bundle {
val master = Vec(new NASTIIO, arbN).flip val master = Vec(new NastiIO, arbN).flip
val slave = new NASTIIO val slave = new NastiIO
} }
if (arbN > 1) { if (arbN > 1) {
val arbIdBits = log2Up(arbN) val arbIdBits = log2Up(arbN)
val ar_arb = Module(new RRArbiter(new NASTIReadAddressChannel, arbN)) val ar_arb = Module(new RRArbiter(new NastiReadAddressChannel, arbN))
val aw_arb = Module(new RRArbiter(new NASTIWriteAddressChannel, arbN)) val aw_arb = Module(new RRArbiter(new NastiWriteAddressChannel, arbN))
val slave_r_arb_id = io.slave.r.bits.id(arbIdBits - 1, 0) val slave_r_arb_id = io.slave.r.bits.id(arbIdBits - 1, 0)
val slave_b_arb_id = io.slave.b.bits.id(arbIdBits - 1, 0) val slave_b_arb_id = io.slave.b.bits.id(arbIdBits - 1, 0)
@ -304,12 +314,12 @@ class NASTIArbiter(val arbN: Int) extends NASTIModule {
} else { io.slave <> io.master.head } } else { io.slave <> io.master.head }
} }
/** Locking RR arbiter for NASTI read data channel /** Locking RR arbiter for Nasti read data channel
* Arbiter locks until last message in channel is sent */ * Arbiter locks until last message in channel is sent */
class NASTIReadDataArbiter(arbN: Int) extends NASTIModule { class NastiReadDataArbiter(arbN: Int)(implicit val p: Parameters) extends NastiModule {
val io = new Bundle { val io = new Bundle {
val in = Vec(Decoupled(new NASTIReadDataChannel), arbN).flip val in = Vec(Decoupled(new NastiReadDataChannel), arbN).flip
val out = Decoupled(new NASTIReadDataChannel) val out = Decoupled(new NastiReadDataChannel)
} }
def rotateLeft[T <: Data](norm: Vec[T], rot: UInt): Vec[T] = { def rotateLeft[T <: Data](norm: Vec[T], rot: UInt): Vec[T] = {
@ -347,13 +357,13 @@ class NASTIReadDataArbiter(arbN: Int) extends NASTIModule {
} }
/** A slave that send decode error for every request it receives */ /** A slave that send decode error for every request it receives */
class NASTIErrorSlave extends NASTIModule { class NastiErrorSlave(implicit val p: Parameters) extends NastiModule {
val io = (new NASTIIO).flip val io = (new NastiIO).flip
when (io.ar.fire()) { printf("Invalid read address %x\n", io.ar.bits.addr) } when (io.ar.fire()) { printf("Invalid read address %x\n", io.ar.bits.addr) }
when (io.aw.fire()) { printf("Invalid write address %x\n", io.aw.bits.addr) } when (io.aw.fire()) { printf("Invalid write address %x\n", io.aw.bits.addr) }
val r_queue = Module(new Queue(new NASTIReadAddressChannel, 2)) val r_queue = Module(new Queue(new NastiReadAddressChannel, 2))
r_queue.io.enq <> io.ar r_queue.io.enq <> io.ar
val responding = Reg(init = Bool(false)) val responding = Reg(init = Bool(false))
@ -396,15 +406,15 @@ class NASTIErrorSlave extends NASTIModule {
b_queue.io.deq.ready := io.b.ready && !draining b_queue.io.deq.ready := io.b.ready && !draining
} }
/** Take a single NASTI master and route its requests to various slaves /** Take a single Nasti master and route its requests to various slaves
* @param addrmap a sequence of base address + memory size pairs, * @param addrmap a sequence of base address + memory size pairs,
* on for each slave interface */ * on for each slave interface */
class NASTIRouter(addrmap: Seq[(BigInt, BigInt)]) extends NASTIModule { class NastiRouter(addrmap: Seq[(BigInt, BigInt)])(implicit val p: Parameters) extends NastiModule {
val nSlaves = addrmap.size val nSlaves = addrmap.size
val io = new Bundle { val io = new Bundle {
val master = (new NASTIIO).flip val master = (new NastiIO).flip
val slave = Vec(new NASTIIO, nSlaves) val slave = Vec(new NastiIO, nSlaves)
} }
var ar_ready = Bool(false) var ar_ready = Bool(false)
@ -446,7 +456,7 @@ class NASTIRouter(addrmap: Seq[(BigInt, BigInt)]) extends NASTIModule {
w_ready = w_ready || (s.w.ready && chosen) w_ready = w_ready || (s.w.ready && chosen)
} }
val err_slave = Module(new NASTIErrorSlave) val err_slave = Module(new NastiErrorSlave)
err_slave.io.ar.valid := !r_valid_addr && io.master.ar.valid err_slave.io.ar.valid := !r_valid_addr && io.master.ar.valid
err_slave.io.ar.bits := io.master.ar.bits err_slave.io.ar.bits := io.master.ar.bits
err_slave.io.aw.valid := !w_valid_addr && io.master.aw.valid err_slave.io.aw.valid := !w_valid_addr && io.master.aw.valid
@ -458,8 +468,8 @@ class NASTIRouter(addrmap: Seq[(BigInt, BigInt)]) extends NASTIModule {
io.master.aw.ready := aw_ready || (!w_valid_addr && err_slave.io.aw.ready) io.master.aw.ready := aw_ready || (!w_valid_addr && err_slave.io.aw.ready)
io.master.w.ready := w_ready || err_slave.io.w.ready io.master.w.ready := w_ready || err_slave.io.w.ready
val b_arb = Module(new RRArbiter(new NASTIWriteResponseChannel, nSlaves + 1)) val b_arb = Module(new RRArbiter(new NastiWriteResponseChannel, nSlaves + 1))
val r_arb = Module(new NASTIReadDataArbiter(nSlaves + 1)) val r_arb = Module(new NastiReadDataArbiter(nSlaves + 1))
for (i <- 0 until nSlaves) { for (i <- 0 until nSlaves) {
b_arb.io.in(i) <> io.slave(i).b b_arb.io.in(i) <> io.slave(i).b
@ -473,20 +483,20 @@ class NASTIRouter(addrmap: Seq[(BigInt, BigInt)]) extends NASTIModule {
io.master.r <> r_arb.io.out io.master.r <> r_arb.io.out
} }
/** Crossbar between multiple NASTI masters and slaves /** Crossbar between multiple Nasti masters and slaves
* @param nMasters the number of NASTI masters * @param nMasters the number of Nasti masters
* @param nSlaves the number of NASTI slaves * @param nSlaves the number of Nasti slaves
* @param addrmap a sequence of base - size pairs; * @param addrmap a sequence of base - size pairs;
* size of addrmap should be nSlaves */ * size of addrmap should be nSlaves */
class NASTICrossbar(nMasters: Int, nSlaves: Int, addrmap: Seq[(BigInt, BigInt)]) class NastiCrossbar(nMasters: Int, nSlaves: Int, addrmap: Seq[(BigInt, BigInt)])
extends NASTIModule { (implicit val p: Parameters) extends NastiModule {
val io = new Bundle { val io = new Bundle {
val masters = Vec(new NASTIIO, nMasters).flip val masters = Vec(new NastiIO, nMasters).flip
val slaves = Vec(new NASTIIO, nSlaves) val slaves = Vec(new NastiIO, nSlaves)
} }
val routers = Vec.fill(nMasters) { Module(new NASTIRouter(addrmap)).io } val routers = Vec.fill(nMasters) { Module(new NastiRouter(addrmap)).io }
val arbiters = Vec.fill(nSlaves) { Module(new NASTIArbiter(nMasters)).io } val arbiters = Vec.fill(nSlaves) { Module(new NastiArbiter(nMasters)).io }
for (i <- 0 until nMasters) { for (i <- 0 until nMasters) {
routers(i).master <> io.masters(i) routers(i).master <> io.masters(i)
@ -498,13 +508,7 @@ class NASTICrossbar(nMasters: Int, nSlaves: Int, addrmap: Seq[(BigInt, BigInt)])
} }
} }
case object NASTINMasters extends Field[Int] object AddrMapConsts {
case object NASTINSlaves extends Field[Int]
object AddrMap {
type AddrMapEntry = (String, Option[BigInt], MemRegion)
type AddrMapSeq = Seq[AddrMapEntry]
val R = 0x4 val R = 0x4
val W = 0x2 val W = 0x2
val X = 0x1 val X = 0x1
@ -512,19 +516,6 @@ object AddrMap {
val RX = R | X val RX = R | X
val RWX = R | W | X val RWX = R | W | X
} }
import AddrMap._
abstract class MemRegion { def size: BigInt }
case class MemSize(size: BigInt, prot: Int) extends MemRegion
case class MemSubmap(size: BigInt, entries: AddrMapSeq) extends MemRegion
object Submap {
def apply(size: BigInt, entries: AddrMapEntry*) =
new MemSubmap(size, entries)
}
case class AddrHashMapEntry(port: Int, start: BigInt, size: BigInt, prot: Int)
class AddrMapProt extends Bundle { class AddrMapProt extends Bundle {
val r = Bool() val r = Bool()
@ -532,14 +523,47 @@ class AddrMapProt extends Bundle {
val x = Bool() val x = Bool()
} }
class AddrHashMap(addrmap: AddrMapSeq) { abstract class MemRegion { def size: BigInt }
case class MemSize(size: BigInt, prot: Int) extends MemRegion
case class MemSubmap(size: BigInt, entries: AddrMap) extends MemRegion
//object Submap {
// def apply(size: BigInt, entries: AddrMapEntry*) =
// new MemSubmap(size, entries)
//}
case class AddrMapEntry(name: String, start: Option[BigInt], region: MemRegion)
case class AddrHashMapEntry(port: Int, start: BigInt, size: BigInt, prot: Int)
class AddrMap(entries: Seq[AddrMapEntry]) extends scala.collection.IndexedSeq[AddrMapEntry] {
def apply(index: Int): AddrMapEntry = entries(index)
def length: Int = entries.size
def countSlaves: Int = {
this map { entry: AddrMapEntry => entry.region match {
case MemSize(_, _) => 1
case MemSubmap(_, submap) => submap.countSlaves
}} reduceLeft(_ + _)
}
}
object AddrMap {
def apply(elems: AddrMapEntry*): AddrMap = new AddrMap(elems)
}
class AddrHashMap(addrmap: AddrMap) {
val mapping = new HashMap[String, AddrHashMapEntry] val mapping = new HashMap[String, AddrHashMapEntry]
private def genPairs(addrmap: AddrMapSeq): Seq[(String, AddrHashMapEntry)] = { private def genPairs(am: AddrMap): Seq[(String, AddrHashMapEntry)] = {
var ind = 0 var ind = 0
var base = BigInt(0) var base = BigInt(0)
var pairs = Seq[(String, AddrHashMapEntry)]() var pairs = Seq[(String, AddrHashMapEntry)]()
addrmap.foreach { case (name, startOpt, region) => am.foreach { case AddrMapEntry(name, startOpt, region) =>
region match { region match {
case MemSize(size, prot) => { case MemSize(size, prot) => {
if (!startOpt.isEmpty) base = startOpt.get if (!startOpt.isEmpty) base = startOpt.get
@ -590,43 +614,35 @@ class AddrHashMap(addrmap: AddrMapSeq) {
} }
} }
case object NASTIAddrMap extends Field[AddrMapSeq] class NastiInterconnectIO(val nMasters: Int, val nSlaves: Int)
case object NASTIAddrHashMap extends Field[AddrHashMap] (implicit p: Parameters) extends Bundle {
class NASTIInterconnectIO(val nMasters: Int, val nSlaves: Int) extends Bundle {
/* This is a bit confusing. The interconnect is a slave to the masters and /* This is a bit confusing. The interconnect is a slave to the masters and
* a master to the slaves. Hence why the declarations seem to be backwards. */ * a master to the slaves. Hence why the declarations seem to be backwards. */
val masters = Vec(new NASTIIO, nMasters).flip val masters = Vec(new NastiIO, nMasters).flip
val slaves = Vec(new NASTIIO, nSlaves) val slaves = Vec(new NastiIO, nSlaves)
override def cloneType = override def cloneType =
new NASTIInterconnectIO(nMasters, nSlaves).asInstanceOf[this.type] new NastiInterconnectIO(nMasters, nSlaves).asInstanceOf[this.type]
} }
abstract class NASTIInterconnect extends NASTIModule { abstract class NastiInterconnect extends NastiModule {
val nMasters: Int val nMasters: Int
val nSlaves: Int val nSlaves: Int
lazy val io = new NASTIInterconnectIO(nMasters, nSlaves) lazy val io = new NastiInterconnectIO(nMasters, nSlaves)
}
class NASTIRecursiveInterconnect(
val nMasters: Int, val nSlaves: Int,
addrmap: AddrMapSeq, base: BigInt = 0) extends NASTIInterconnect {
private def mapCountSlaves(addrmap: AddrMapSeq): Int = {
addrmap.map {
case (_, _, MemSize(_, _)) => 1
case (_, _, MemSubmap(_, submap)) => mapCountSlaves(submap)
}.reduceLeft(_ + _)
} }
class NastiRecursiveInterconnect(
val nMasters: Int,
val nSlaves: Int,
addrmap: AddrMap,
base: BigInt = 0)
(implicit val p: Parameters) extends NastiInterconnect {
var lastEnd = base var lastEnd = base
var slaveInd = 0 var slaveInd = 0
val levelSize = addrmap.size val levelSize = addrmap.size
val realAddrMap = new ArraySeq[(BigInt, BigInt)](addrmap.size) val realAddrMap = new ArraySeq[(BigInt, BigInt)](addrmap.size)
addrmap.zipWithIndex.foreach { case ((_, startOpt, region), i) => addrmap.zipWithIndex.foreach { case (AddrMapEntry(_, startOpt, region), i) =>
val start = startOpt.getOrElse(lastEnd) val start = startOpt.getOrElse(lastEnd)
val size = region.size val size = region.size
realAddrMap(i) = (start, size) realAddrMap(i) = (start, size)
@ -634,25 +650,24 @@ class NASTIRecursiveInterconnect(
} }
val flatSlaves = if (nMasters > 1) { val flatSlaves = if (nMasters > 1) {
val xbar = Module(new NASTICrossbar(nMasters, levelSize, realAddrMap)) val xbar = Module(new NastiCrossbar(nMasters, levelSize, realAddrMap))
xbar.io.masters <> io.masters xbar.io.masters <> io.masters
xbar.io.slaves xbar.io.slaves
} else { } else {
val router = Module(new NASTIRouter(realAddrMap)) val router = Module(new NastiRouter(realAddrMap))
router.io.master <> io.masters.head router.io.master <> io.masters.head
router.io.slave router.io.slave
} }
addrmap.zip(realAddrMap).zipWithIndex.foreach { addrmap.zip(realAddrMap).zipWithIndex.foreach {
case (((_, _, region), (start, size)), i) => { case ((entry, (start, size)), i) => {
region match { entry.region match {
case MemSize(_, _) => case MemSize(_, _) =>
io.slaves(slaveInd) <> flatSlaves(i) io.slaves(slaveInd) <> flatSlaves(i)
slaveInd += 1 slaveInd += 1
case MemSubmap(_, submap) => case MemSubmap(_, submap) =>
val subSlaves = mapCountSlaves(submap) val subSlaves = submap.countSlaves
val ic = Module(new NASTIRecursiveInterconnect( val ic = Module(new NastiRecursiveInterconnect(1, subSlaves, submap, start))
1, subSlaves, submap, start))
ic.io.masters.head <> flatSlaves(i) ic.io.masters.head <> flatSlaves(i)
io.slaves.drop(slaveInd).take(subSlaves).zip(ic.io.slaves).foreach { io.slaves.drop(slaveInd).take(subSlaves).zip(ic.io.slaves).foreach {
case (s, m) => s <> m case (s, m) => s <> m
@ -663,20 +678,15 @@ class NASTIRecursiveInterconnect(
} }
} }
class NASTITopInterconnect extends NASTIInterconnect { class NastiTopInterconnect(val nMasters: Int, val nSlaves: Int)
val nMasters = params(NASTINMasters) (implicit val p: Parameters) extends NastiInterconnect {
val nSlaves = params(NASTINSlaves) val temp = Module(new NastiRecursiveInterconnect(nMasters, nSlaves, p(NastiAddrMap)))
bigIntPow2(params(MMIOBase))
val temp = Module(new NASTIRecursiveInterconnect(
nMasters, nSlaves, params(NASTIAddrMap)))
temp.io.masters.zip(io.masters).foreach { case (t, i) => temp.io.masters.zip(io.masters).foreach { case (t, i) =>
t.ar <> i.ar t.ar <> i.ar
t.aw <> i.aw t.aw <> i.aw
// this queue is necessary to break up the aw - w dependence // this queue is necessary to break up the aw - w dependence
// introduced by the TileLink -> NASTI converter // introduced by the TileLink -> Nasti converter
t.w <> Queue(i.w) t.w <> Queue(i.w)
i.b <> t.b i.b <> t.b
i.r <> t.r i.r <> t.r

View File

@ -87,11 +87,11 @@ class SMIArbiter(val n: Int, val dataWidth: Int, val addrWidth: Int)
io.out.resp.ready := io.in(choice).resp.ready io.out.resp.ready := io.in(choice).resp.ready
} }
class SMIIONASTIReadIOConverter(val dataWidth: Int, val addrWidth: Int) class SMIIONastiReadIOConverter(val dataWidth: Int, val addrWidth: Int)
extends NASTIModule { (implicit val p: Parameters) extends NastiModule {
val io = new Bundle { val io = new Bundle {
val ar = Decoupled(new NASTIReadAddressChannel).flip val ar = Decoupled(new NastiReadAddressChannel).flip
val r = Decoupled(new NASTIReadDataChannel) val r = Decoupled(new NastiReadDataChannel)
val smi = new SMIIO(dataWidth, addrWidth) val smi = new SMIIO(dataWidth, addrWidth)
} }
@ -127,7 +127,7 @@ class SMIIONASTIReadIOConverter(val dataWidth: Int, val addrWidth: Int)
io.smi.resp.ready := (state === s_read) io.smi.resp.ready := (state === s_read)
io.r.valid := (state === s_resp) io.r.valid := (state === s_resp)
io.r.bits := NASTIReadDataChannel( io.r.bits := NastiReadDataChannel(
id = id, id = id,
data = buffer.toBits, data = buffer.toBits,
last = (nBeats === UInt(0))) last = (nBeats === UInt(0)))
@ -169,12 +169,12 @@ class SMIIONASTIReadIOConverter(val dataWidth: Int, val addrWidth: Int)
} }
} }
class SMIIONASTIWriteIOConverter(val dataWidth: Int, val addrWidth: Int) class SMIIONastiWriteIOConverter(val dataWidth: Int, val addrWidth: Int)
extends NASTIModule { (implicit val p: Parameters) extends NastiModule {
val io = new Bundle { val io = new Bundle {
val aw = Decoupled(new NASTIWriteAddressChannel).flip val aw = Decoupled(new NastiWriteAddressChannel).flip
val w = Decoupled(new NASTIWriteDataChannel).flip val w = Decoupled(new NastiWriteDataChannel).flip
val b = Decoupled(new NASTIWriteResponseChannel) val b = Decoupled(new NastiWriteResponseChannel)
val smi = new SMIIO(dataWidth, addrWidth) val smi = new SMIIO(dataWidth, addrWidth)
} }
@ -184,7 +184,7 @@ class SMIIONASTIWriteIOConverter(val dataWidth: Int, val addrWidth: Int)
private val addrOffBits = addrWidth + byteOffBits private val addrOffBits = addrWidth + byteOffBits
assert(!io.aw.valid || io.aw.bits.size >= UInt(byteOffBits), assert(!io.aw.valid || io.aw.bits.size >= UInt(byteOffBits),
"NASTI size must be >= SMI size") "Nasti size must be >= SMI size")
val id = Reg(UInt(width = nastiWIdBits)) val id = Reg(UInt(width = nastiWIdBits))
val addr = Reg(UInt(width = addrWidth)) val addr = Reg(UInt(width = addrWidth))
@ -213,7 +213,7 @@ class SMIIONASTIWriteIOConverter(val dataWidth: Int, val addrWidth: Int)
io.smi.req.bits.data := data(dataWidth - 1, 0) io.smi.req.bits.data := data(dataWidth - 1, 0)
io.smi.resp.ready := (state === s_ack) io.smi.resp.ready := (state === s_ack)
io.b.valid := (state === s_resp) io.b.valid := (state === s_resp)
io.b.bits := NASTIWriteResponseChannel(id) io.b.bits := NastiWriteResponseChannel(id)
val jump = PriorityMux(strb(maxWordsPerBeat - 1, 1), val jump = PriorityMux(strb(maxWordsPerBeat - 1, 1),
(1 until maxWordsPerBeat).map(UInt(_))) (1 until maxWordsPerBeat).map(UInt(_)))
@ -249,21 +249,21 @@ class SMIIONASTIWriteIOConverter(val dataWidth: Int, val addrWidth: Int)
when (io.b.fire()) { state := s_idle } when (io.b.fire()) { state := s_idle }
} }
/** Convert NASTI protocol to SMI protocol */ /** Convert Nasti protocol to SMI protocol */
class SMIIONASTIIOConverter(val dataWidth: Int, val addrWidth: Int) class SMIIONastiIOConverter(val dataWidth: Int, val addrWidth: Int)
extends NASTIModule { (implicit val p: Parameters) extends NastiModule {
val io = new Bundle { val io = new Bundle {
val nasti = (new NASTIIO).flip val nasti = (new NastiIO).flip
val smi = new SMIIO(dataWidth, addrWidth) val smi = new SMIIO(dataWidth, addrWidth)
} }
require(isPow2(dataWidth), "SMI data width must be power of 2") require(isPow2(dataWidth), "SMI data width must be power of 2")
val reader = Module(new SMIIONASTIReadIOConverter(dataWidth, addrWidth)) val reader = Module(new SMIIONastiReadIOConverter(dataWidth, addrWidth))
reader.io.ar <> io.nasti.ar reader.io.ar <> io.nasti.ar
io.nasti.r <> reader.io.r io.nasti.r <> reader.io.r
val writer = Module(new SMIIONASTIWriteIOConverter(dataWidth, addrWidth)) val writer = Module(new SMIIONastiWriteIOConverter(dataWidth, addrWidth))
writer.io.aw <> io.nasti.aw writer.io.aw <> io.nasti.aw
writer.io.w <> io.nasti.w writer.io.w <> io.nasti.w
io.nasti.b <> writer.io.b io.nasti.b <> writer.io.b

View File

@ -0,0 +1,7 @@
/// See LICENSE for license details.
package junctions
import Chisel._
object bigIntPow2 {
def apply(in: BigInt): Boolean = in > 0 && ((in & (in-1)) == 0)
}