Merge branch 'param-refactor'
This commit is contained in:
commit
da5fe84f53
134
junctions/src/main/scala/addrmap.scala
Normal file
134
junctions/src/main/scala/addrmap.scala
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
// See LICENSE for license details.
|
||||||
|
|
||||||
|
package junctions
|
||||||
|
|
||||||
|
import Chisel._
|
||||||
|
import scala.collection.mutable.HashMap
|
||||||
|
|
||||||
|
case object PAddrBits extends Field[Int]
|
||||||
|
case object VAddrBits extends Field[Int]
|
||||||
|
case object PgIdxBits extends Field[Int]
|
||||||
|
case object PgLevels extends Field[Int]
|
||||||
|
case object PgLevelBits extends Field[Int]
|
||||||
|
case object ASIdBits extends Field[Int]
|
||||||
|
case object PPNBits extends Field[Int]
|
||||||
|
case object VPNBits extends Field[Int]
|
||||||
|
|
||||||
|
case object GlobalAddrMap extends Field[AddrMap]
|
||||||
|
case object MMIOBase extends Field[BigInt]
|
||||||
|
|
||||||
|
trait HasAddrMapParameters {
|
||||||
|
implicit val p: Parameters
|
||||||
|
|
||||||
|
val paddrBits = p(PAddrBits)
|
||||||
|
val vaddrBits = p(VAddrBits)
|
||||||
|
val pgIdxBits = p(PgIdxBits)
|
||||||
|
val ppnBits = p(PPNBits)
|
||||||
|
val vpnBits = p(VPNBits)
|
||||||
|
val pgLevels = p(PgLevels)
|
||||||
|
val pgLevelBits = p(PgLevelBits)
|
||||||
|
val asIdBits = p(ASIdBits)
|
||||||
|
|
||||||
|
val addrMap = new AddrHashMap(p(GlobalAddrMap))
|
||||||
|
}
|
||||||
|
|
||||||
|
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 AddrMapConsts {
|
||||||
|
val R = 0x4
|
||||||
|
val W = 0x2
|
||||||
|
val X = 0x1
|
||||||
|
val RW = R | W
|
||||||
|
val RX = R | X
|
||||||
|
val RWX = R | W | X
|
||||||
|
}
|
||||||
|
|
||||||
|
class AddrMapProt extends Bundle {
|
||||||
|
val r = Bool()
|
||||||
|
val w = Bool()
|
||||||
|
val x = Bool()
|
||||||
|
}
|
||||||
|
|
||||||
|
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]
|
||||||
|
|
||||||
|
private def genPairs(am: AddrMap): Seq[(String, AddrHashMapEntry)] = {
|
||||||
|
var ind = 0
|
||||||
|
var base = BigInt(0)
|
||||||
|
var pairs = Seq[(String, AddrHashMapEntry)]()
|
||||||
|
am.foreach { case AddrMapEntry(name, startOpt, region) =>
|
||||||
|
region match {
|
||||||
|
case MemSize(size, prot) => {
|
||||||
|
if (!startOpt.isEmpty) base = startOpt.get
|
||||||
|
pairs = (name, AddrHashMapEntry(ind, base, size, prot)) +: pairs
|
||||||
|
base += size
|
||||||
|
ind += 1
|
||||||
|
}
|
||||||
|
case MemSubmap(size, submap) => {
|
||||||
|
if (!startOpt.isEmpty) base = startOpt.get
|
||||||
|
val subpairs = genPairs(submap).map {
|
||||||
|
case (subname, AddrHashMapEntry(subind, subbase, subsize, prot)) =>
|
||||||
|
(name + ":" + subname,
|
||||||
|
AddrHashMapEntry(ind + subind, base + subbase, subsize, prot))
|
||||||
|
}
|
||||||
|
pairs = subpairs ++ pairs
|
||||||
|
ind += subpairs.size
|
||||||
|
base += size
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pairs
|
||||||
|
}
|
||||||
|
|
||||||
|
for ((name, ind) <- genPairs(addrmap)) { mapping(name) = ind }
|
||||||
|
|
||||||
|
def nEntries: Int = mapping.size
|
||||||
|
def apply(name: String): AddrHashMapEntry = mapping(name)
|
||||||
|
def get(name: String): Option[AddrHashMapEntry] = mapping.get(name)
|
||||||
|
def sortedEntries(): Seq[(String, BigInt, BigInt, Int)] = {
|
||||||
|
val arr = new Array[(String, BigInt, BigInt, Int)](mapping.size)
|
||||||
|
mapping.foreach { case (name, AddrHashMapEntry(port, base, size, prot)) =>
|
||||||
|
arr(port) = (name, base, size, prot)
|
||||||
|
}
|
||||||
|
arr.toSeq
|
||||||
|
}
|
||||||
|
|
||||||
|
def isValid(addr: UInt): Bool = {
|
||||||
|
sortedEntries().map { case (_, base, size, _) =>
|
||||||
|
addr >= UInt(base) && addr < UInt(base + size)
|
||||||
|
}.reduceLeft(_ || _)
|
||||||
|
}
|
||||||
|
|
||||||
|
def getProt(addr: UInt): AddrMapProt = {
|
||||||
|
Mux1H(sortedEntries().map { case (_, base, size, prot) =>
|
||||||
|
(addr >= UInt(base) && addr < UInt(base + size),
|
||||||
|
new AddrMapProt().fromBits(Bits(prot, 3)))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -2,7 +2,7 @@ package junctions
|
|||||||
|
|
||||||
import Chisel._
|
import Chisel._
|
||||||
|
|
||||||
abstract trait HASTIConstants
|
trait HastiConstants
|
||||||
{
|
{
|
||||||
val SZ_HTRANS = 2
|
val SZ_HTRANS = 2
|
||||||
val HTRANS_IDLE = UInt(0, SZ_HTRANS)
|
val HTRANS_IDLE = UInt(0, SZ_HTRANS)
|
||||||
@ -27,16 +27,22 @@ abstract trait HASTIConstants
|
|||||||
val SZ_HSIZE = 3
|
val SZ_HSIZE = 3
|
||||||
val SZ_HPROT = 4
|
val SZ_HPROT = 4
|
||||||
|
|
||||||
// TODO: Parameterize
|
|
||||||
val SZ_HADDR = 32
|
|
||||||
val SZ_HDATA = 32
|
|
||||||
|
|
||||||
def dgate(valid: Bool, b: UInt) = Fill(b.getWidth, valid) & b
|
def dgate(valid: Bool, b: UInt) = Fill(b.getWidth, valid) & b
|
||||||
}
|
}
|
||||||
|
|
||||||
class HASTIMasterIO extends Bundle
|
trait HasHastiParameters {
|
||||||
{
|
implicit val p: Parameters
|
||||||
val haddr = UInt(OUTPUT, SZ_HADDR)
|
val hastiAddrBits = 32
|
||||||
|
val hastiDataBits = 32
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class HastiModule(implicit val p: Parameters) extends Module
|
||||||
|
with HasHastiParameters
|
||||||
|
abstract class HastiBundle(implicit val p: Parameters) extends ParameterizedBundle()(p)
|
||||||
|
with HasHastiParameters
|
||||||
|
|
||||||
|
class HastiMasterIO(implicit p: Parameters) extends HastiBundle()(p) {
|
||||||
|
val haddr = UInt(OUTPUT, hastiAddrBits)
|
||||||
val hwrite = Bool(OUTPUT)
|
val hwrite = Bool(OUTPUT)
|
||||||
val hsize = UInt(OUTPUT, SZ_HSIZE)
|
val hsize = UInt(OUTPUT, SZ_HSIZE)
|
||||||
val hburst = UInt(OUTPUT, SZ_HBURST)
|
val hburst = UInt(OUTPUT, SZ_HBURST)
|
||||||
@ -44,16 +50,15 @@ class HASTIMasterIO extends Bundle
|
|||||||
val htrans = UInt(OUTPUT, SZ_HTRANS)
|
val htrans = UInt(OUTPUT, SZ_HTRANS)
|
||||||
val hmastlock = Bool(OUTPUT)
|
val hmastlock = Bool(OUTPUT)
|
||||||
|
|
||||||
val hwdata = Bits(OUTPUT, SZ_HDATA)
|
val hwdata = Bits(OUTPUT, hastiDataBits)
|
||||||
val hrdata = Bits(INPUT, SZ_HDATA)
|
val hrdata = Bits(INPUT, hastiDataBits)
|
||||||
|
|
||||||
val hready = Bool(INPUT)
|
val hready = Bool(INPUT)
|
||||||
val hresp = UInt(INPUT, SZ_HRESP)
|
val hresp = UInt(INPUT, SZ_HRESP)
|
||||||
}
|
}
|
||||||
|
|
||||||
class HASTISlaveIO extends Bundle
|
class HastiSlaveIO(implicit p: Parameters) extends HastiBundle()(p) {
|
||||||
{
|
val haddr = UInt(INPUT, hastiAddrBits)
|
||||||
val haddr = UInt(INPUT, SZ_HADDR)
|
|
||||||
val hwrite = Bool(INPUT)
|
val hwrite = Bool(INPUT)
|
||||||
val hsize = UInt(INPUT, SZ_HSIZE)
|
val hsize = UInt(INPUT, SZ_HSIZE)
|
||||||
val hburst = UInt(INPUT, SZ_HBURST)
|
val hburst = UInt(INPUT, SZ_HBURST)
|
||||||
@ -61,8 +66,8 @@ class HASTISlaveIO extends Bundle
|
|||||||
val htrans = UInt(INPUT, SZ_HTRANS)
|
val htrans = UInt(INPUT, SZ_HTRANS)
|
||||||
val hmastlock = Bool(INPUT)
|
val hmastlock = Bool(INPUT)
|
||||||
|
|
||||||
val hwdata = Bits(INPUT, SZ_HDATA)
|
val hwdata = Bits(INPUT, hastiDataBits)
|
||||||
val hrdata = Bits(OUTPUT, SZ_HDATA)
|
val hrdata = Bits(OUTPUT, hastiDataBits)
|
||||||
|
|
||||||
val hsel = Bool(INPUT)
|
val hsel = Bool(INPUT)
|
||||||
val hreadyin = Bool(INPUT)
|
val hreadyin = Bool(INPUT)
|
||||||
@ -70,23 +75,22 @@ class HASTISlaveIO extends Bundle
|
|||||||
val hresp = UInt(OUTPUT, SZ_HRESP)
|
val hresp = UInt(OUTPUT, SZ_HRESP)
|
||||||
}
|
}
|
||||||
|
|
||||||
class HASTIBus(amap: Seq[UInt=>Bool]) extends Module
|
class HastiBus(amap: Seq[UInt=>Bool])(implicit p: Parameters) extends HastiModule()(p) {
|
||||||
{
|
|
||||||
val io = new Bundle {
|
val io = new Bundle {
|
||||||
val master = new HASTIMasterIO().flip
|
val master = new HastiMasterIO().flip
|
||||||
val slaves = Vec(new HASTISlaveIO, amap.size).flip
|
val slaves = Vec(new HastiSlaveIO, amap.size).flip
|
||||||
}
|
}
|
||||||
|
|
||||||
// skid buffer
|
// skid buffer
|
||||||
val skb_valid = Reg(init = Bool(false))
|
val skb_valid = Reg(init = Bool(false))
|
||||||
val skb_haddr = Reg(UInt(width = SZ_HADDR))
|
val skb_haddr = Reg(UInt(width = hastiAddrBits))
|
||||||
val skb_hwrite = Reg(Bool())
|
val skb_hwrite = Reg(Bool())
|
||||||
val skb_hsize = Reg(UInt(width = SZ_HSIZE))
|
val skb_hsize = Reg(UInt(width = SZ_HSIZE))
|
||||||
val skb_hburst = Reg(UInt(width = SZ_HBURST))
|
val skb_hburst = Reg(UInt(width = SZ_HBURST))
|
||||||
val skb_hprot = Reg(UInt(width = SZ_HPROT))
|
val skb_hprot = Reg(UInt(width = SZ_HPROT))
|
||||||
val skb_htrans = Reg(UInt(width = SZ_HTRANS))
|
val skb_htrans = Reg(UInt(width = SZ_HTRANS))
|
||||||
val skb_hmastlock = Reg(Bool())
|
val skb_hmastlock = Reg(Bool())
|
||||||
val skb_hwdata = Reg(UInt(width = SZ_HDATA))
|
val skb_hwdata = Reg(UInt(width = hastiDataBits))
|
||||||
|
|
||||||
val master_haddr = Mux(skb_valid, skb_haddr, io.master.haddr)
|
val master_haddr = Mux(skb_valid, skb_haddr, io.master.haddr)
|
||||||
val master_hwrite = Mux(skb_valid, skb_hwrite, io.master.hwrite)
|
val master_hwrite = Mux(skb_valid, skb_hwrite, io.master.hwrite)
|
||||||
@ -142,16 +146,15 @@ class HASTIBus(amap: Seq[UInt=>Bool]) extends Module
|
|||||||
io.master.hresp := Mux1H(s1_hsels, io.slaves.map(_.hresp))
|
io.master.hresp := Mux1H(s1_hsels, io.slaves.map(_.hresp))
|
||||||
}
|
}
|
||||||
|
|
||||||
class HASTISlaveMux(n: Int) extends Module
|
class HastiSlaveMux(n: Int)(implicit p: Parameters) extends HastiModule()(p) {
|
||||||
{
|
|
||||||
val io = new Bundle {
|
val io = new Bundle {
|
||||||
val ins = Vec(new HASTISlaveIO, n)
|
val ins = Vec(new HastiSlaveIO, n)
|
||||||
val out = new HASTISlaveIO().flip
|
val out = new HastiSlaveIO().flip
|
||||||
}
|
}
|
||||||
|
|
||||||
// skid buffers
|
// skid buffers
|
||||||
val skb_valid = Array.fill(n){Reg(init = Bool(false))}
|
val skb_valid = Array.fill(n){Reg(init = Bool(false))}
|
||||||
val skb_haddr = Array.fill(n){Reg(UInt(width = SZ_HADDR))}
|
val skb_haddr = Array.fill(n){Reg(UInt(width = hastiAddrBits))}
|
||||||
val skb_hwrite = Array.fill(n){Reg(Bool())}
|
val skb_hwrite = Array.fill(n){Reg(Bool())}
|
||||||
val skb_hsize = Array.fill(n){Reg(UInt(width = SZ_HSIZE))}
|
val skb_hsize = Array.fill(n){Reg(UInt(width = SZ_HSIZE))}
|
||||||
val skb_hburst = Array.fill(n){Reg(UInt(width = SZ_HBURST))}
|
val skb_hburst = Array.fill(n){Reg(UInt(width = SZ_HBURST))}
|
||||||
@ -212,15 +215,15 @@ class HASTISlaveMux(n: Int) extends Module
|
|||||||
} }
|
} }
|
||||||
}
|
}
|
||||||
|
|
||||||
class HASTIXbar(nMasters: Int, addressMap: Seq[UInt=>Bool]) extends Module
|
class HastiXbar(nMasters: Int, addressMap: Seq[UInt=>Bool])
|
||||||
{
|
(implicit p: Parameters) extends HastiModule()(p) {
|
||||||
val io = new Bundle {
|
val io = new Bundle {
|
||||||
val masters = Vec(new HASTIMasterIO, nMasters).flip
|
val masters = Vec(new HastiMasterIO, nMasters).flip
|
||||||
val slaves = Vec(new HASTISlaveIO, addressMap.size).flip
|
val slaves = Vec(new HastiSlaveIO, addressMap.size).flip
|
||||||
}
|
}
|
||||||
|
|
||||||
val buses = List.fill(nMasters){Module(new HASTIBus(addressMap))}
|
val buses = List.fill(nMasters){Module(new HastiBus(addressMap))}
|
||||||
val muxes = List.fill(addressMap.size){Module(new HASTISlaveMux(nMasters))}
|
val muxes = List.fill(addressMap.size){Module(new HastiSlaveMux(nMasters))}
|
||||||
|
|
||||||
(buses.map(b => b.io.master) zip io.masters) foreach { case (b, m) => b <> m }
|
(buses.map(b => b.io.master) zip io.masters) foreach { case (b, m) => b <> m }
|
||||||
(muxes.map(m => m.io.out) zip io.slaves ) foreach { case (x, s) => x <> s }
|
(muxes.map(m => m.io.out) zip io.slaves ) foreach { case (x, s) => x <> s }
|
||||||
@ -229,11 +232,10 @@ class HASTIXbar(nMasters: Int, addressMap: Seq[UInt=>Bool]) extends Module
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class HASTISlaveToMaster extends Module
|
class HastiSlaveToMaster(implicit p: Parameters) extends HastiModule()(p) {
|
||||||
{
|
|
||||||
val io = new Bundle {
|
val io = new Bundle {
|
||||||
val in = new HASTISlaveIO
|
val in = new HastiSlaveIO
|
||||||
val out = new HASTIMasterIO
|
val out = new HastiMasterIO
|
||||||
}
|
}
|
||||||
|
|
||||||
io.out.haddr := io.in.haddr
|
io.out.haddr := io.in.haddr
|
||||||
|
@ -4,68 +4,62 @@ package junctions
|
|||||||
import Chisel._
|
import Chisel._
|
||||||
import scala.math._
|
import scala.math._
|
||||||
|
|
||||||
case object PAddrBits extends Field[Int]
|
|
||||||
case object VAddrBits extends Field[Int]
|
|
||||||
case object PgIdxBits extends Field[Int]
|
|
||||||
case object PgLevels extends Field[Int]
|
|
||||||
case object PgLevelBits extends Field[Int]
|
|
||||||
case object ASIdBits extends Field[Int]
|
|
||||||
case object PPNBits extends Field[Int]
|
|
||||||
case object VPNBits extends Field[Int]
|
|
||||||
|
|
||||||
case object MIFAddrBits extends Field[Int]
|
case object MIFAddrBits extends Field[Int]
|
||||||
case object MIFDataBits extends Field[Int]
|
case object MIFDataBits extends Field[Int]
|
||||||
case object MIFTagBits extends Field[Int]
|
case object MIFTagBits extends Field[Int]
|
||||||
case object MIFDataBeats extends Field[Int]
|
case object MIFDataBeats extends Field[Int]
|
||||||
|
|
||||||
trait MIFParameters extends UsesParameters {
|
trait HasMIFParameters {
|
||||||
val mifTagBits = params(MIFTagBits)
|
implicit val p: Parameters
|
||||||
val mifAddrBits = params(MIFAddrBits)
|
val mifTagBits = p(MIFTagBits)
|
||||||
val mifDataBits = params(MIFDataBits)
|
val mifAddrBits = p(MIFAddrBits)
|
||||||
val mifDataBeats = params(MIFDataBeats)
|
val mifDataBits = p(MIFDataBits)
|
||||||
|
val mifDataBeats = p(MIFDataBeats)
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class MIFBundle extends Bundle with MIFParameters
|
abstract class MIFModule(implicit val p: Parameters) extends Module with HasMIFParameters
|
||||||
abstract class MIFModule extends Module with MIFParameters
|
abstract class MIFBundle(implicit val p: Parameters) extends ParameterizedBundle()(p)
|
||||||
|
with HasMIFParameters
|
||||||
|
|
||||||
trait HasMemData extends MIFBundle {
|
trait HasMemData extends HasMIFParameters {
|
||||||
val data = Bits(width = mifDataBits)
|
val data = Bits(width = mifDataBits)
|
||||||
}
|
}
|
||||||
|
|
||||||
trait HasMemAddr extends MIFBundle {
|
trait HasMemAddr extends HasMIFParameters {
|
||||||
val addr = UInt(width = mifAddrBits)
|
val addr = UInt(width = mifAddrBits)
|
||||||
}
|
}
|
||||||
|
|
||||||
trait HasMemTag extends MIFBundle {
|
trait HasMemTag extends HasMIFParameters {
|
||||||
val tag = UInt(width = mifTagBits)
|
val tag = UInt(width = mifTagBits)
|
||||||
}
|
}
|
||||||
|
|
||||||
class MemReqCmd extends HasMemAddr with HasMemTag {
|
class MemReqCmd(implicit p: Parameters) extends MIFBundle()(p) with HasMemAddr with HasMemTag {
|
||||||
val rw = Bool()
|
val rw = Bool()
|
||||||
}
|
}
|
||||||
|
|
||||||
class MemTag extends HasMemTag
|
class MemTag(implicit p: Parameters) extends MIFBundle()(p) with HasMemTag
|
||||||
class MemData extends HasMemData
|
class MemData(implicit p: Parameters) extends MIFBundle()(p) with HasMemData
|
||||||
class MemResp extends HasMemData with HasMemTag
|
class MemResp(implicit p: Parameters) extends MIFBundle()(p) with HasMemData with HasMemTag
|
||||||
|
|
||||||
class MemIO extends Bundle {
|
class MemIO(implicit p: Parameters) extends ParameterizedBundle()(p) {
|
||||||
val req_cmd = Decoupled(new MemReqCmd)
|
val req_cmd = Decoupled(new MemReqCmd)
|
||||||
val req_data = Decoupled(new MemData)
|
val req_data = Decoupled(new MemData)
|
||||||
val resp = Decoupled(new MemResp).flip
|
val resp = Decoupled(new MemResp).flip
|
||||||
}
|
}
|
||||||
|
|
||||||
class MemPipeIO extends Bundle {
|
class MemPipeIO(implicit p: Parameters) extends ParameterizedBundle()(p) {
|
||||||
val req_cmd = Decoupled(new MemReqCmd)
|
val req_cmd = Decoupled(new MemReqCmd)
|
||||||
val req_data = Decoupled(new MemData)
|
val req_data = Decoupled(new MemData)
|
||||||
val resp = Valid(new MemResp).flip
|
val resp = Valid(new MemResp).flip
|
||||||
}
|
}
|
||||||
|
|
||||||
class MemSerializedIO(w: Int) extends Bundle {
|
class MemSerializedIO(w: Int)(implicit p: Parameters) extends ParameterizedBundle()(p) {
|
||||||
val req = Decoupled(Bits(width = w))
|
val req = Decoupled(Bits(width = w))
|
||||||
val resp = Valid(Bits(width = w)).flip
|
val resp = Valid(Bits(width = w)).flip
|
||||||
|
//override def cloneType = new MemSerializedIO(w)(p).asInstanceOf[this.type]
|
||||||
}
|
}
|
||||||
|
|
||||||
class MemSerdes(w: Int) extends MIFModule
|
class MemSerdes(w: Int)(implicit p: Parameters) extends MIFModule
|
||||||
{
|
{
|
||||||
val io = new Bundle {
|
val io = new Bundle {
|
||||||
val wide = new MemIO().flip
|
val wide = new MemIO().flip
|
||||||
@ -140,18 +134,18 @@ class MemSerdes(w: Int) extends MIFModule
|
|||||||
io.wide.resp.bits := io.wide.resp.bits.fromBits(in_buf)
|
io.wide.resp.bits := io.wide.resp.bits.fromBits(in_buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
class MemDesserIO(w: Int) extends Bundle {
|
class MemDesserIO(w: Int)(implicit p: Parameters) extends ParameterizedBundle()(p) {
|
||||||
val narrow = new MemSerializedIO(w).flip
|
val narrow = new MemSerializedIO(w).flip
|
||||||
val wide = new MemIO
|
val wide = new MemIO
|
||||||
}
|
}
|
||||||
|
|
||||||
class MemDesser(w: Int) extends Module // test rig side
|
class MemDesser(w: Int)(implicit p: Parameters) extends Module // test rig side
|
||||||
{
|
{
|
||||||
val io = new MemDesserIO(w)
|
val io = new MemDesserIO(w)
|
||||||
val abits = io.wide.req_cmd.bits.toBits.getWidth
|
val abits = io.wide.req_cmd.bits.toBits.getWidth
|
||||||
val dbits = io.wide.req_data.bits.toBits.getWidth
|
val dbits = io.wide.req_data.bits.toBits.getWidth
|
||||||
val rbits = io.wide.resp.bits.getWidth
|
val rbits = io.wide.resp.bits.getWidth
|
||||||
val mifDataBeats = params(MIFDataBeats)
|
val mifDataBeats = p(MIFDataBeats)
|
||||||
|
|
||||||
require(dbits >= abits && rbits >= dbits)
|
require(dbits >= abits && rbits >= dbits)
|
||||||
val recv_cnt = Reg(init=UInt(0, log2Up((rbits+w-1)/w)))
|
val recv_cnt = Reg(init=UInt(0, log2Up((rbits+w-1)/w)))
|
||||||
@ -211,59 +205,7 @@ class MemDesser(w: Int) extends Module // test rig side
|
|||||||
io.narrow.resp.bits := dataq.io.deq.bits.toBits >> (recv_cnt * UInt(w))
|
io.narrow.resp.bits := dataq.io.deq.bits.toBits >> (recv_cnt * UInt(w))
|
||||||
}
|
}
|
||||||
|
|
||||||
class HellaFlowQueue[T <: Data](val entries: Int)(data: => T) extends Module
|
class MemIOArbiter(val arbN: Int)(implicit p: Parameters) extends MIFModule {
|
||||||
{
|
|
||||||
val io = new QueueIO(data, entries)
|
|
||||||
require(entries > 1)
|
|
||||||
|
|
||||||
val do_flow = Wire(Bool())
|
|
||||||
val do_enq = io.enq.fire() && !do_flow
|
|
||||||
val do_deq = io.deq.fire() && !do_flow
|
|
||||||
|
|
||||||
val maybe_full = Reg(init=Bool(false))
|
|
||||||
val enq_ptr = Counter(do_enq, entries)._1
|
|
||||||
val (deq_ptr, deq_done) = Counter(do_deq, entries)
|
|
||||||
when (do_enq != do_deq) { maybe_full := do_enq }
|
|
||||||
|
|
||||||
val ptr_match = enq_ptr === deq_ptr
|
|
||||||
val empty = ptr_match && !maybe_full
|
|
||||||
val full = ptr_match && maybe_full
|
|
||||||
val atLeastTwo = full || enq_ptr - deq_ptr >= UInt(2)
|
|
||||||
do_flow := empty && io.deq.ready
|
|
||||||
|
|
||||||
val ram = SeqMem(data, entries)
|
|
||||||
when (do_enq) { ram.write(enq_ptr, io.enq.bits) }
|
|
||||||
|
|
||||||
val ren = io.deq.ready && (atLeastTwo || !io.deq.valid && !empty)
|
|
||||||
val raddr = Mux(io.deq.valid, Mux(deq_done, UInt(0), deq_ptr + UInt(1)), deq_ptr)
|
|
||||||
val ram_out_valid = Reg(next = ren)
|
|
||||||
|
|
||||||
io.deq.valid := Mux(empty, io.enq.valid, ram_out_valid)
|
|
||||||
io.enq.ready := !full
|
|
||||||
io.deq.bits := Mux(empty, io.enq.bits, ram.read(raddr, ren))
|
|
||||||
}
|
|
||||||
|
|
||||||
class HellaQueue[T <: Data](val entries: Int)(data: => T) extends Module
|
|
||||||
{
|
|
||||||
val io = new QueueIO(data, entries)
|
|
||||||
|
|
||||||
val fq = Module(new HellaFlowQueue(entries)(data))
|
|
||||||
fq.io.enq <> io.enq
|
|
||||||
io.deq <> Queue(fq.io.deq, 1, pipe = true)
|
|
||||||
}
|
|
||||||
|
|
||||||
object HellaQueue
|
|
||||||
{
|
|
||||||
def apply[T <: Data](enq: DecoupledIO[T], entries: Int) = {
|
|
||||||
val q = Module((new HellaQueue(entries)) { enq.bits })
|
|
||||||
q.io.enq.valid := enq.valid // not using <> so that override is allowed
|
|
||||||
q.io.enq.bits := enq.bits
|
|
||||||
enq.ready := q.io.enq.ready
|
|
||||||
q.io.deq
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class MemIOArbiter(val arbN: Int) extends MIFModule {
|
|
||||||
val io = new Bundle {
|
val io = new Bundle {
|
||||||
val inner = Vec(new MemIO, arbN).flip
|
val inner = Vec(new MemIO, arbN).flip
|
||||||
val outer = new MemIO
|
val outer = new MemIO
|
||||||
@ -307,7 +249,7 @@ class MemIOArbiter(val arbN: Int) extends MIFModule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
object MemIOMemPipeIOConverter {
|
object MemIOMemPipeIOConverter {
|
||||||
def apply(in: MemPipeIO): MemIO = {
|
def apply(in: MemPipeIO)(implicit p: Parameters): MemIO = {
|
||||||
val out = Wire(new MemIO())
|
val out = Wire(new MemIO())
|
||||||
in.resp.valid := out.resp.valid
|
in.resp.valid := out.resp.valid
|
||||||
in.resp.bits := out.resp.bits
|
in.resp.bits := out.resp.bits
|
||||||
@ -322,7 +264,7 @@ object MemIOMemPipeIOConverter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MemPipeIOMemIOConverter(numRequests: Int) extends MIFModule {
|
class MemPipeIOMemIOConverter(numRequests: Int)(implicit p: Parameters) extends MIFModule {
|
||||||
val io = new Bundle {
|
val io = new Bundle {
|
||||||
val cpu = new MemIO().flip
|
val cpu = new MemIO().flip
|
||||||
val mem = new MemPipeIO
|
val mem = new MemPipeIO
|
||||||
|
@ -4,23 +4,19 @@ package junctions
|
|||||||
import Chisel._
|
import Chisel._
|
||||||
import scala.math.max
|
import scala.math.max
|
||||||
import scala.collection.mutable.ArraySeq
|
import scala.collection.mutable.ArraySeq
|
||||||
import scala.collection.mutable.HashMap
|
|
||||||
|
|
||||||
case object MMIOBase extends Field[BigInt]
|
case object NastiKey extends Field[NastiParameters]
|
||||||
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(NastiKey)
|
||||||
|
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 +44,16 @@ trait NASTIParameters extends UsesParameters {
|
|||||||
UInt(128) -> UInt(7)))
|
UInt(128) -> UInt(7)))
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class NASTIBundle extends Bundle with NASTIParameters
|
abstract class NastiModule(implicit val p: Parameters) extends Module
|
||||||
abstract class NASTIModule extends Module with NASTIParameters
|
with HasNastiParameters
|
||||||
|
abstract class NastiBundle(implicit val p: Parameters) extends ParameterizedBundle()(p)
|
||||||
|
with HasNastiParameters
|
||||||
|
|
||||||
trait NASTIChannel extends NASTIBundle
|
abstract class NastiChannel(implicit p: Parameters) extends NastiBundle()(p)
|
||||||
trait NASTIMasterToSlaveChannel extends NASTIChannel
|
abstract class NastiMasterToSlaveChannel(implicit p: Parameters) extends NastiChannel()(p)
|
||||||
trait NASTISlaveToMasterChannel extends NASTIChannel
|
abstract class NastiSlaveToMasterChannel(implicit p: Parameters) extends NastiChannel()(p)
|
||||||
|
|
||||||
class NASTIIO extends Bundle {
|
trait HasNastiMetadata extends HasNastiParameters {
|
||||||
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 {
|
|
||||||
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 +65,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 val p: Parameters) extends ParameterizedBundle()(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 +130,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 +148,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 +178,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 +188,10 @@ object NASTIWriteResponseChannel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MemIONASTIIOConverter(cacheBlockOffsetBits: Int) extends MIFModule with NASTIParameters {
|
class MemIONastiIOConverter(cacheBlockOffsetBits: Int)(implicit 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 +199,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 +243,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 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 +311,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 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 +354,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 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 +403,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 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 +453,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 +465,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 +480,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 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,135 +505,35 @@ class NASTICrossbar(nMasters: Int, nSlaves: Int, addrmap: Seq[(BigInt, BigInt)])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case object NASTINMasters extends Field[Int]
|
class NastiInterconnectIO(val nMasters: Int, val nSlaves: Int)
|
||||||
case object NASTINSlaves extends Field[Int]
|
(implicit p: Parameters) extends Bundle {
|
||||||
|
|
||||||
object AddrMap {
|
|
||||||
type AddrMapEntry = (String, Option[BigInt], MemRegion)
|
|
||||||
type AddrMapSeq = Seq[AddrMapEntry]
|
|
||||||
|
|
||||||
val R = 0x4
|
|
||||||
val W = 0x2
|
|
||||||
val X = 0x1
|
|
||||||
val RW = R | W
|
|
||||||
val RX = R | 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 {
|
|
||||||
val r = Bool()
|
|
||||||
val w = Bool()
|
|
||||||
val x = Bool()
|
|
||||||
}
|
|
||||||
|
|
||||||
class AddrHashMap(addrmap: AddrMapSeq) {
|
|
||||||
val mapping = new HashMap[String, AddrHashMapEntry]
|
|
||||||
|
|
||||||
private def genPairs(addrmap: AddrMapSeq): Seq[(String, AddrHashMapEntry)] = {
|
|
||||||
var ind = 0
|
|
||||||
var base = BigInt(0)
|
|
||||||
var pairs = Seq[(String, AddrHashMapEntry)]()
|
|
||||||
addrmap.foreach { case (name, startOpt, region) =>
|
|
||||||
region match {
|
|
||||||
case MemSize(size, prot) => {
|
|
||||||
if (!startOpt.isEmpty) base = startOpt.get
|
|
||||||
pairs = (name, AddrHashMapEntry(ind, base, size, prot)) +: pairs
|
|
||||||
base += size
|
|
||||||
ind += 1
|
|
||||||
}
|
|
||||||
case MemSubmap(size, submap) => {
|
|
||||||
if (!startOpt.isEmpty) base = startOpt.get
|
|
||||||
val subpairs = genPairs(submap).map {
|
|
||||||
case (subname, AddrHashMapEntry(subind, subbase, subsize, prot)) =>
|
|
||||||
(name + ":" + subname,
|
|
||||||
AddrHashMapEntry(ind + subind, base + subbase, subsize, prot))
|
|
||||||
}
|
|
||||||
pairs = subpairs ++ pairs
|
|
||||||
ind += subpairs.size
|
|
||||||
base += size
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pairs
|
|
||||||
}
|
|
||||||
|
|
||||||
for ((name, ind) <- genPairs(addrmap)) { mapping(name) = ind }
|
|
||||||
|
|
||||||
def nEntries: Int = mapping.size
|
|
||||||
def apply(name: String): AddrHashMapEntry = mapping(name)
|
|
||||||
def get(name: String): Option[AddrHashMapEntry] = mapping.get(name)
|
|
||||||
def sortedEntries(): Seq[(String, BigInt, BigInt, Int)] = {
|
|
||||||
val arr = new Array[(String, BigInt, BigInt, Int)](mapping.size)
|
|
||||||
mapping.foreach { case (name, AddrHashMapEntry(port, base, size, prot)) =>
|
|
||||||
arr(port) = (name, base, size, prot)
|
|
||||||
}
|
|
||||||
arr.toSeq
|
|
||||||
}
|
|
||||||
|
|
||||||
def isValid(addr: UInt): Bool = {
|
|
||||||
sortedEntries().map { case (_, base, size, _) =>
|
|
||||||
addr >= UInt(base) && addr < UInt(base + size)
|
|
||||||
}.reduceLeft(_ || _)
|
|
||||||
}
|
|
||||||
|
|
||||||
def getProt(addr: UInt): AddrMapProt = {
|
|
||||||
Mux1H(sortedEntries().map { case (_, base, size, prot) =>
|
|
||||||
(addr >= UInt(base) && addr < UInt(base + size),
|
|
||||||
new AddrMapProt().fromBits(Bits(prot, 3)))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case object NASTIAddrMap extends Field[AddrMapSeq]
|
|
||||||
case object NASTIAddrHashMap extends Field[AddrHashMap]
|
|
||||||
|
|
||||||
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(implicit p: Parameters) extends NastiModule()(p) {
|
||||||
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(
|
class NastiRecursiveInterconnect(
|
||||||
val nMasters: Int, val nSlaves: Int,
|
val nMasters: Int,
|
||||||
addrmap: AddrMapSeq, base: BigInt = 0) extends NASTIInterconnect {
|
val nSlaves: Int,
|
||||||
|
addrmap: AddrMap,
|
||||||
private def mapCountSlaves(addrmap: AddrMapSeq): Int = {
|
base: BigInt = 0)
|
||||||
addrmap.map {
|
(implicit p: Parameters) extends NastiInterconnect {
|
||||||
case (_, _, MemSize(_, _)) => 1
|
|
||||||
case (_, _, MemSubmap(_, submap)) => mapCountSlaves(submap)
|
|
||||||
}.reduceLeft(_ + _)
|
|
||||||
}
|
|
||||||
|
|
||||||
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 +541,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 +569,15 @@ class NASTIRecursiveInterconnect(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class NASTITopInterconnect extends NASTIInterconnect {
|
class NastiTopInterconnect(val nMasters: Int, val nSlaves: Int, addrMap: AddrMap)
|
||||||
val nMasters = params(NASTINMasters)
|
(implicit p: Parameters) extends NastiInterconnect {
|
||||||
val nSlaves = params(NASTINSlaves)
|
val temp = Module(new NastiRecursiveInterconnect(nMasters, nSlaves, addrMap))
|
||||||
|
|
||||||
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
|
||||||
|
@ -1 +1 @@
|
|||||||
package object junctions extends HASTIConstants with POCIConstants
|
package object junctions extends HastiConstants with PociConstants
|
||||||
|
@ -2,13 +2,13 @@ package junctions
|
|||||||
|
|
||||||
import Chisel._
|
import Chisel._
|
||||||
|
|
||||||
abstract trait POCIConstants
|
abstract trait PociConstants
|
||||||
{
|
{
|
||||||
val SZ_PADDR = 32
|
val SZ_PADDR = 32
|
||||||
val SZ_PDATA = 32
|
val SZ_PDATA = 32
|
||||||
}
|
}
|
||||||
|
|
||||||
class POCIIO extends Bundle
|
class PociIO extends Bundle
|
||||||
{
|
{
|
||||||
val paddr = UInt(OUTPUT, SZ_PADDR)
|
val paddr = UInt(OUTPUT, SZ_PADDR)
|
||||||
val pwrite = Bool(OUTPUT)
|
val pwrite = Bool(OUTPUT)
|
||||||
@ -20,11 +20,10 @@ class POCIIO extends Bundle
|
|||||||
val pslverr = Bool(INPUT)
|
val pslverr = Bool(INPUT)
|
||||||
}
|
}
|
||||||
|
|
||||||
class HASTItoPOCIBridge extends Module
|
class HastiToPociBridge(implicit p: Parameters) extends HastiModule()(p) {
|
||||||
{
|
|
||||||
val io = new Bundle {
|
val io = new Bundle {
|
||||||
val in = new HASTISlaveIO
|
val in = new HastiSlaveIO
|
||||||
val out = new POCIIO
|
val out = new PociIO
|
||||||
}
|
}
|
||||||
|
|
||||||
val s_idle :: s_setup :: s_access :: Nil = Enum(UInt(), 3)
|
val s_idle :: s_setup :: s_access :: Nil = Enum(UInt(), 3)
|
||||||
@ -62,11 +61,11 @@ class HASTItoPOCIBridge extends Module
|
|||||||
io.in.hresp := io.out.pslverr
|
io.in.hresp := io.out.pslverr
|
||||||
}
|
}
|
||||||
|
|
||||||
class POCIBus(amap: Seq[UInt=>Bool]) extends Module
|
class PociBus(amap: Seq[UInt=>Bool]) extends Module
|
||||||
{
|
{
|
||||||
val io = new Bundle {
|
val io = new Bundle {
|
||||||
val master = new POCIIO().flip
|
val master = new PociIO().flip
|
||||||
val slaves = Vec(new POCIIO, amap.size)
|
val slaves = Vec(new PociIO, amap.size)
|
||||||
}
|
}
|
||||||
|
|
||||||
val psels = PriorityEncoderOH(
|
val psels = PriorityEncoderOH(
|
||||||
|
@ -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 p: Parameters) extends NastiModule()(p) {
|
||||||
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 p: Parameters) extends NastiModule()(p) {
|
||||||
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 = if (maxWordsPerBeat > 1)
|
val jump = if (maxWordsPerBeat > 1)
|
||||||
PriorityMux(strb(maxWordsPerBeat - 1, 1),
|
PriorityMux(strb(maxWordsPerBeat - 1, 1),
|
||||||
@ -250,21 +250,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 p: Parameters) extends NastiModule()(p) {
|
||||||
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
|
||||||
|
60
junctions/src/main/scala/util.scala
Normal file
60
junctions/src/main/scala/util.scala
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
/// See LICENSE for license details.
|
||||||
|
package junctions
|
||||||
|
import Chisel._
|
||||||
|
|
||||||
|
object bigIntPow2 {
|
||||||
|
def apply(in: BigInt): Boolean = in > 0 && ((in & (in-1)) == 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
class ParameterizedBundle(implicit p: Parameters) extends Bundle {
|
||||||
|
override def cloneType = this.getClass.getConstructors.head.newInstance(p).asInstanceOf[this.type]
|
||||||
|
}
|
||||||
|
|
||||||
|
class HellaFlowQueue[T <: Data](val entries: Int)(data: => T) extends Module {
|
||||||
|
val io = new QueueIO(data, entries)
|
||||||
|
require(entries > 1)
|
||||||
|
|
||||||
|
val do_flow = Wire(Bool())
|
||||||
|
val do_enq = io.enq.fire() && !do_flow
|
||||||
|
val do_deq = io.deq.fire() && !do_flow
|
||||||
|
|
||||||
|
val maybe_full = Reg(init=Bool(false))
|
||||||
|
val enq_ptr = Counter(do_enq, entries)._1
|
||||||
|
val (deq_ptr, deq_done) = Counter(do_deq, entries)
|
||||||
|
when (do_enq != do_deq) { maybe_full := do_enq }
|
||||||
|
|
||||||
|
val ptr_match = enq_ptr === deq_ptr
|
||||||
|
val empty = ptr_match && !maybe_full
|
||||||
|
val full = ptr_match && maybe_full
|
||||||
|
val atLeastTwo = full || enq_ptr - deq_ptr >= UInt(2)
|
||||||
|
do_flow := empty && io.deq.ready
|
||||||
|
|
||||||
|
val ram = SeqMem(data, entries)
|
||||||
|
when (do_enq) { ram.write(enq_ptr, io.enq.bits) }
|
||||||
|
|
||||||
|
val ren = io.deq.ready && (atLeastTwo || !io.deq.valid && !empty)
|
||||||
|
val raddr = Mux(io.deq.valid, Mux(deq_done, UInt(0), deq_ptr + UInt(1)), deq_ptr)
|
||||||
|
val ram_out_valid = Reg(next = ren)
|
||||||
|
|
||||||
|
io.deq.valid := Mux(empty, io.enq.valid, ram_out_valid)
|
||||||
|
io.enq.ready := !full
|
||||||
|
io.deq.bits := Mux(empty, io.enq.bits, ram.read(raddr, ren))
|
||||||
|
}
|
||||||
|
|
||||||
|
class HellaQueue[T <: Data](val entries: Int)(data: => T) extends Module {
|
||||||
|
val io = new QueueIO(data, entries)
|
||||||
|
|
||||||
|
val fq = Module(new HellaFlowQueue(entries)(data))
|
||||||
|
fq.io.enq <> io.enq
|
||||||
|
io.deq <> Queue(fq.io.deq, 1, pipe = true)
|
||||||
|
}
|
||||||
|
|
||||||
|
object HellaQueue {
|
||||||
|
def apply[T <: Data](enq: DecoupledIO[T], entries: Int) = {
|
||||||
|
val q = Module((new HellaQueue(entries)) { enq.bits })
|
||||||
|
q.io.enq.valid := enq.valid // not using <> so that override is allowed
|
||||||
|
q.io.enq.bits := enq.bits
|
||||||
|
enq.ready := q.io.enq.ready
|
||||||
|
q.io.deq
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user