diff --git a/junctions/src/main/scala/addrmap.scala b/junctions/src/main/scala/addrmap.scala new file mode 100644 index 00000000..8e6dea4e --- /dev/null +++ b/junctions/src/main/scala/addrmap.scala @@ -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))) + }) + } +} diff --git a/junctions/src/main/scala/hasti.scala b/junctions/src/main/scala/hasti.scala index 2e3b1ff7..7a913dfe 100644 --- a/junctions/src/main/scala/hasti.scala +++ b/junctions/src/main/scala/hasti.scala @@ -2,7 +2,7 @@ package junctions import Chisel._ -abstract trait HASTIConstants +trait HastiConstants { val SZ_HTRANS = 2 val HTRANS_IDLE = UInt(0, SZ_HTRANS) @@ -27,16 +27,22 @@ abstract trait HASTIConstants val SZ_HSIZE = 3 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 } -class HASTIMasterIO extends Bundle -{ - val haddr = UInt(OUTPUT, SZ_HADDR) +trait HasHastiParameters { + implicit val p: Parameters + 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 hsize = UInt(OUTPUT, SZ_HSIZE) val hburst = UInt(OUTPUT, SZ_HBURST) @@ -44,16 +50,15 @@ class HASTIMasterIO extends Bundle val htrans = UInt(OUTPUT, SZ_HTRANS) val hmastlock = Bool(OUTPUT) - val hwdata = Bits(OUTPUT, SZ_HDATA) - val hrdata = Bits(INPUT, SZ_HDATA) + val hwdata = Bits(OUTPUT, hastiDataBits) + val hrdata = Bits(INPUT, hastiDataBits) val hready = Bool(INPUT) val hresp = UInt(INPUT, SZ_HRESP) } -class HASTISlaveIO extends Bundle -{ - val haddr = UInt(INPUT, SZ_HADDR) +class HastiSlaveIO(implicit p: Parameters) extends HastiBundle()(p) { + val haddr = UInt(INPUT, hastiAddrBits) val hwrite = Bool(INPUT) val hsize = UInt(INPUT, SZ_HSIZE) val hburst = UInt(INPUT, SZ_HBURST) @@ -61,8 +66,8 @@ class HASTISlaveIO extends Bundle val htrans = UInt(INPUT, SZ_HTRANS) val hmastlock = Bool(INPUT) - val hwdata = Bits(INPUT, SZ_HDATA) - val hrdata = Bits(OUTPUT, SZ_HDATA) + val hwdata = Bits(INPUT, hastiDataBits) + val hrdata = Bits(OUTPUT, hastiDataBits) val hsel = Bool(INPUT) val hreadyin = Bool(INPUT) @@ -70,23 +75,22 @@ class HASTISlaveIO extends Bundle 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 master = new HASTIMasterIO().flip - val slaves = Vec(new HASTISlaveIO, amap.size).flip + val master = new HastiMasterIO().flip + val slaves = Vec(new HastiSlaveIO, amap.size).flip } // skid buffer 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_hsize = Reg(UInt(width = SZ_HSIZE)) val skb_hburst = Reg(UInt(width = SZ_HBURST)) val skb_hprot = Reg(UInt(width = SZ_HPROT)) val skb_htrans = Reg(UInt(width = SZ_HTRANS)) 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_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)) } -class HASTISlaveMux(n: Int) extends Module -{ +class HastiSlaveMux(n: Int)(implicit p: Parameters) extends HastiModule()(p) { val io = new Bundle { - val ins = Vec(new HASTISlaveIO, n) - val out = new HASTISlaveIO().flip + val ins = Vec(new HastiSlaveIO, n) + val out = new HastiSlaveIO().flip } // skid buffers 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_hsize = Array.fill(n){Reg(UInt(width = SZ_HSIZE))} 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 masters = Vec(new HASTIMasterIO, nMasters).flip - val slaves = Vec(new HASTISlaveIO, addressMap.size).flip + val masters = Vec(new HastiMasterIO, nMasters).flip + val slaves = Vec(new HastiSlaveIO, addressMap.size).flip } - val buses = List.fill(nMasters){Module(new HASTIBus(addressMap))} - val muxes = List.fill(addressMap.size){Module(new HASTISlaveMux(nMasters))} + val buses = List.fill(nMasters){Module(new HastiBus(addressMap))} + 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 } (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 in = new HASTISlaveIO - val out = new HASTIMasterIO + val in = new HastiSlaveIO + val out = new HastiMasterIO } io.out.haddr := io.in.haddr diff --git a/junctions/src/main/scala/memserdes.scala b/junctions/src/main/scala/memserdes.scala index 78212952..2fc8ace1 100644 --- a/junctions/src/main/scala/memserdes.scala +++ b/junctions/src/main/scala/memserdes.scala @@ -4,68 +4,62 @@ package junctions import Chisel._ 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 MIFDataBits extends Field[Int] case object MIFTagBits extends Field[Int] case object MIFDataBeats extends Field[Int] -trait MIFParameters extends UsesParameters { - val mifTagBits = params(MIFTagBits) - val mifAddrBits = params(MIFAddrBits) - val mifDataBits = params(MIFDataBits) - val mifDataBeats = params(MIFDataBeats) +trait HasMIFParameters { + implicit val p: Parameters + val mifTagBits = p(MIFTagBits) + val mifAddrBits = p(MIFAddrBits) + val mifDataBits = p(MIFDataBits) + val mifDataBeats = p(MIFDataBeats) } -abstract class MIFBundle extends Bundle with MIFParameters -abstract class MIFModule extends Module with MIFParameters +abstract class MIFModule(implicit val p: Parameters) extends Module with HasMIFParameters +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) } -trait HasMemAddr extends MIFBundle { +trait HasMemAddr extends HasMIFParameters { val addr = UInt(width = mifAddrBits) } -trait HasMemTag extends MIFBundle { +trait HasMemTag extends HasMIFParameters { 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() } -class MemTag extends HasMemTag -class MemData extends HasMemData -class MemResp extends HasMemData with HasMemTag +class MemTag(implicit p: Parameters) extends MIFBundle()(p) with HasMemTag +class MemData(implicit p: Parameters) extends MIFBundle()(p) with HasMemData +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_data = Decoupled(new MemData) 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_data = Decoupled(new MemData) 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 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 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) } -class MemDesserIO(w: Int) extends Bundle { +class MemDesserIO(w: Int)(implicit p: Parameters) extends ParameterizedBundle()(p) { val narrow = new MemSerializedIO(w).flip 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 abits = io.wide.req_cmd.bits.toBits.getWidth val dbits = io.wide.req_data.bits.toBits.getWidth val rbits = io.wide.resp.bits.getWidth - val mifDataBeats = params(MIFDataBeats) + val mifDataBeats = p(MIFDataBeats) require(dbits >= abits && rbits >= dbits) 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)) } -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 - } -} - -class MemIOArbiter(val arbN: Int) extends MIFModule { +class MemIOArbiter(val arbN: Int)(implicit p: Parameters) extends MIFModule { val io = new Bundle { val inner = Vec(new MemIO, arbN).flip val outer = new MemIO @@ -307,7 +249,7 @@ class MemIOArbiter(val arbN: Int) extends MIFModule { } object MemIOMemPipeIOConverter { - def apply(in: MemPipeIO): MemIO = { + def apply(in: MemPipeIO)(implicit p: Parameters): MemIO = { val out = Wire(new MemIO()) in.resp.valid := out.resp.valid 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 cpu = new MemIO().flip val mem = new MemPipeIO diff --git a/junctions/src/main/scala/nasti.scala b/junctions/src/main/scala/nasti.scala index 26306e54..f57ff9fc 100644 --- a/junctions/src/main/scala/nasti.scala +++ b/junctions/src/main/scala/nasti.scala @@ -4,23 +4,19 @@ package junctions import Chisel._ import scala.math.max import scala.collection.mutable.ArraySeq -import scala.collection.mutable.HashMap -case object MMIOBase extends Field[BigInt] -case object NASTIDataBits extends Field[Int] -case object NASTIAddrBits extends Field[Int] -case object NASTIIdBits extends Field[Int] +case object NastiKey extends Field[NastiParameters] -object bigIntPow2 { - def apply(in: BigInt): Boolean = in > 0 && ((in & (in-1)) == 0) -} +case class NastiParameters(dataBits: Int, addrBits: Int, idBits: Int) -trait NASTIParameters extends UsesParameters { - val nastiXDataBits = params(NASTIDataBits) +trait HasNastiParameters { + implicit val p: Parameters + val external = p(NastiKey) + val nastiXDataBits = external.dataBits val nastiWStrobeBits = nastiXDataBits / 8 - val nastiXAddrBits = params(NASTIAddrBits) - val nastiWIdBits = params(NASTIIdBits) - val nastiRIdBits = params(NASTIIdBits) + val nastiXAddrBits = external.addrBits + val nastiWIdBits = external.idBits + val nastiRIdBits = external.idBits val nastiXIdBits = max(nastiWIdBits, nastiRIdBits) val nastiXUserBits = 1 val nastiAWUserBits = nastiXUserBits @@ -48,22 +44,16 @@ trait NASTIParameters extends UsesParameters { UInt(128) -> UInt(7))) } -abstract class NASTIBundle extends Bundle with NASTIParameters -abstract class NASTIModule extends Module with NASTIParameters +abstract class NastiModule(implicit val p: Parameters) extends Module + with HasNastiParameters +abstract class NastiBundle(implicit val p: Parameters) extends ParameterizedBundle()(p) + with HasNastiParameters -trait NASTIChannel extends NASTIBundle -trait NASTIMasterToSlaveChannel extends NASTIChannel -trait NASTISlaveToMasterChannel extends NASTIChannel +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) -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 { +trait HasNastiMetadata extends HasNastiParameters { val addr = UInt(width = nastiXAddrBits) val len = UInt(width = nastiXLenBits) val size = UInt(width = nastiXSizeBits) @@ -75,45 +65,56 @@ trait HasNASTIMetadata extends NASTIBundle { val region = UInt(width = nastiXRegionBits) } -trait HasNASTIData extends NASTIBundle { +trait HasNastiData extends HasNastiParameters { val data = UInt(width = nastiXDataBits) 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) } -class NASTIWriteAddressChannel extends NASTIAddressChannel { +class NastiWriteAddressChannel(implicit p: Parameters) extends NastiAddressChannel()(p) { val id = UInt(width = nastiWIdBits) 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 user = UInt(width = nastiWUserBits) } -class NASTIWriteResponseChannel extends NASTIResponseChannel { +class NastiWriteResponseChannel(implicit p: Parameters) extends NastiResponseChannel()(p) { val id = UInt(width = nastiWIdBits) val user = UInt(width = nastiBUserBits) } -class NASTIReadAddressChannel extends NASTIAddressChannel { +class NastiReadAddressChannel(implicit p: Parameters) extends NastiAddressChannel()(p) { val id = UInt(width = nastiRIdBits) 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 user = UInt(width = nastiRUserBits) } -object NASTIWriteAddressChannel { - def apply(id: UInt, addr: UInt, size: UInt, len: UInt = UInt(0)) = { - val aw = Wire(new NASTIWriteAddressChannel) +object NastiWriteAddressChannel { + def apply(id: UInt, addr: UInt, size: UInt, len: UInt = UInt(0))(implicit p: Parameters) = { + val aw = Wire(new NastiWriteAddressChannel) aw.id := id aw.addr := addr aw.len := len @@ -129,9 +130,9 @@ object NASTIWriteAddressChannel { } } -object NASTIReadAddressChannel { - def apply(id: UInt, addr: UInt, size: UInt, len: UInt = UInt(0)) = { - val ar = Wire(new NASTIReadAddressChannel) +object NastiReadAddressChannel { + def apply(id: UInt, addr: UInt, size: UInt, len: UInt = UInt(0))(implicit p: Parameters) = { + val ar = Wire(new NastiReadAddressChannel) ar.id := id ar.addr := addr ar.len := len @@ -147,22 +148,27 @@ object NASTIReadAddressChannel { } } -object NASTIWriteDataChannel { - private def strobeBits = new NASTIWriteDataChannel().nastiWStrobeBits - def fullStrobe = Fill(strobeBits, UInt(1, 1)) - def apply(data: UInt, strb: UInt = fullStrobe, last: Bool = Bool(true)) = { - val w = Wire(new NASTIWriteDataChannel) - w.strb := strb +object NastiWriteDataChannel { + def apply(data: UInt, last: Bool = Bool(true))(implicit p: Parameters): NastiWriteDataChannel = { + val w = Wire(new NastiWriteDataChannel) + w.strb := Fill(w.nastiWStrobeBits, UInt(1, 1)) w.data := data w.last := last w.user := UInt(0) w } + def apply(data: UInt, strb: UInt, last: Bool) + (implicit p: Parameters): NastiWriteDataChannel = { + val w = apply(data, last) + w.strb := strb + w + } } -object NASTIReadDataChannel { - def apply(id: UInt, data: UInt, last: Bool = Bool(true), resp: UInt = UInt(0)) = { - val r = Wire(new NASTIReadDataChannel) +object NastiReadDataChannel { + def apply(id: UInt, data: UInt, last: Bool = Bool(true), resp: UInt = UInt(0))( + implicit p: Parameters) = { + val r = Wire(new NastiReadDataChannel) r.id := id r.data := data r.last := last @@ -172,9 +178,9 @@ object NASTIReadDataChannel { } } -object NASTIWriteResponseChannel { - def apply(id: UInt, resp: UInt = UInt(0)) = { - val b = Wire(new NASTIWriteResponseChannel) +object NastiWriteResponseChannel { + def apply(id: UInt, resp: UInt = UInt(0))(implicit p: Parameters) = { + val b = Wire(new NastiWriteResponseChannel) b.id := id b.resp := resp 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 nasti = (new NASTIIO).flip + val nasti = (new NastiIO).flip 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) 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)), - "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), - "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), - "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 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 */ -class NASTIArbiter(val arbN: Int) extends NASTIModule { +class NastiArbiter(val arbN: Int)(implicit p: Parameters) extends NastiModule { val io = new Bundle { - val master = Vec(new NASTIIO, arbN).flip - val slave = new NASTIIO + val master = Vec(new NastiIO, arbN).flip + val slave = new NastiIO } if (arbN > 1) { val arbIdBits = log2Up(arbN) - val ar_arb = Module(new RRArbiter(new NASTIReadAddressChannel, arbN)) - val aw_arb = Module(new RRArbiter(new NASTIWriteAddressChannel, arbN)) + val ar_arb = Module(new RRArbiter(new NastiReadAddressChannel, 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_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 } } -/** 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 */ -class NASTIReadDataArbiter(arbN: Int) extends NASTIModule { +class NastiReadDataArbiter(arbN: Int)(implicit p: Parameters) extends NastiModule { val io = new Bundle { - val in = Vec(Decoupled(new NASTIReadDataChannel), arbN).flip - val out = Decoupled(new NASTIReadDataChannel) + val in = Vec(Decoupled(new NastiReadDataChannel), arbN).flip + val out = Decoupled(new NastiReadDataChannel) } 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 */ -class NASTIErrorSlave extends NASTIModule { - val io = (new NASTIIO).flip +class NastiErrorSlave(implicit p: Parameters) extends NastiModule { + val io = (new NastiIO).flip 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) } - val r_queue = Module(new Queue(new NASTIReadAddressChannel, 2)) + val r_queue = Module(new Queue(new NastiReadAddressChannel, 2)) r_queue.io.enq <> io.ar val responding = Reg(init = Bool(false)) @@ -396,15 +403,15 @@ class NASTIErrorSlave extends NASTIModule { 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, * 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 io = new Bundle { - val master = (new NASTIIO).flip - val slave = Vec(new NASTIIO, nSlaves) + val master = (new NastiIO).flip + val slave = Vec(new NastiIO, nSlaves) } 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) } - 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.bits := io.master.ar.bits 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.w.ready := w_ready || err_slave.io.w.ready - val b_arb = Module(new RRArbiter(new NASTIWriteResponseChannel, nSlaves + 1)) - val r_arb = Module(new NASTIReadDataArbiter(nSlaves + 1)) + val b_arb = Module(new RRArbiter(new NastiWriteResponseChannel, nSlaves + 1)) + val r_arb = Module(new NastiReadDataArbiter(nSlaves + 1)) for (i <- 0 until nSlaves) { 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 } -/** Crossbar between multiple NASTI masters and slaves - * @param nMasters the number of NASTI masters - * @param nSlaves the number of NASTI slaves +/** Crossbar between multiple Nasti masters and slaves + * @param nMasters the number of Nasti masters + * @param nSlaves the number of Nasti slaves * @param addrmap a sequence of base - size pairs; * size of addrmap should be nSlaves */ -class NASTICrossbar(nMasters: Int, nSlaves: Int, addrmap: Seq[(BigInt, BigInt)]) - extends NASTIModule { +class NastiCrossbar(nMasters: Int, nSlaves: Int, addrmap: Seq[(BigInt, BigInt)]) + (implicit p: Parameters) extends NastiModule { val io = new Bundle { - val masters = Vec(new NASTIIO, nMasters).flip - val slaves = Vec(new NASTIIO, nSlaves) + val masters = Vec(new NastiIO, nMasters).flip + val slaves = Vec(new NastiIO, nSlaves) } - val routers = Vec.fill(nMasters) { Module(new NASTIRouter(addrmap)).io } - val arbiters = Vec.fill(nSlaves) { Module(new NASTIArbiter(nMasters)).io } + val routers = Vec.fill(nMasters) { Module(new NastiRouter(addrmap)).io } + val arbiters = Vec.fill(nSlaves) { Module(new NastiArbiter(nMasters)).io } for (i <- 0 until nMasters) { 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] -case object NASTINSlaves extends Field[Int] - -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 { +class NastiInterconnectIO(val nMasters: Int, val nSlaves: Int) + (implicit p: Parameters) extends Bundle { /* 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. */ - val masters = Vec(new NASTIIO, nMasters).flip - val slaves = Vec(new NASTIIO, nSlaves) + val masters = Vec(new NastiIO, nMasters).flip + val slaves = Vec(new NastiIO, nSlaves) 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 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 p: Parameters) extends NastiInterconnect { var lastEnd = base var slaveInd = 0 val levelSize = 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 size = region.size realAddrMap(i) = (start, size) @@ -634,25 +541,24 @@ class NASTIRecursiveInterconnect( } 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.slaves } else { - val router = Module(new NASTIRouter(realAddrMap)) + val router = Module(new NastiRouter(realAddrMap)) router.io.master <> io.masters.head router.io.slave } addrmap.zip(realAddrMap).zipWithIndex.foreach { - case (((_, _, region), (start, size)), i) => { - region match { + case ((entry, (start, size)), i) => { + entry.region match { case MemSize(_, _) => io.slaves(slaveInd) <> flatSlaves(i) slaveInd += 1 case MemSubmap(_, submap) => - val subSlaves = mapCountSlaves(submap) - val ic = Module(new NASTIRecursiveInterconnect( - 1, subSlaves, submap, start)) + val subSlaves = submap.countSlaves + val ic = Module(new NastiRecursiveInterconnect(1, subSlaves, submap, start)) ic.io.masters.head <> flatSlaves(i) io.slaves.drop(slaveInd).take(subSlaves).zip(ic.io.slaves).foreach { case (s, m) => s <> m @@ -663,20 +569,15 @@ class NASTIRecursiveInterconnect( } } -class NASTITopInterconnect extends NASTIInterconnect { - val nMasters = params(NASTINMasters) - val nSlaves = params(NASTINSlaves) - - bigIntPow2(params(MMIOBase)) - - val temp = Module(new NASTIRecursiveInterconnect( - nMasters, nSlaves, params(NASTIAddrMap))) +class NastiTopInterconnect(val nMasters: Int, val nSlaves: Int, addrMap: AddrMap) + (implicit p: Parameters) extends NastiInterconnect { + val temp = Module(new NastiRecursiveInterconnect(nMasters, nSlaves, addrMap)) temp.io.masters.zip(io.masters).foreach { case (t, i) => t.ar <> i.ar t.aw <> i.aw // 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) i.b <> t.b i.r <> t.r diff --git a/junctions/src/main/scala/package.scala b/junctions/src/main/scala/package.scala index deb7549d..3181064e 100644 --- a/junctions/src/main/scala/package.scala +++ b/junctions/src/main/scala/package.scala @@ -1 +1 @@ -package object junctions extends HASTIConstants with POCIConstants +package object junctions extends HastiConstants with PociConstants diff --git a/junctions/src/main/scala/poci.scala b/junctions/src/main/scala/poci.scala index bfd581c7..bac75966 100644 --- a/junctions/src/main/scala/poci.scala +++ b/junctions/src/main/scala/poci.scala @@ -2,13 +2,13 @@ package junctions import Chisel._ -abstract trait POCIConstants +abstract trait PociConstants { val SZ_PADDR = 32 val SZ_PDATA = 32 } -class POCIIO extends Bundle +class PociIO extends Bundle { val paddr = UInt(OUTPUT, SZ_PADDR) val pwrite = Bool(OUTPUT) @@ -20,11 +20,10 @@ class POCIIO extends Bundle val pslverr = Bool(INPUT) } -class HASTItoPOCIBridge extends Module -{ +class HastiToPociBridge(implicit p: Parameters) extends HastiModule()(p) { val io = new Bundle { - val in = new HASTISlaveIO - val out = new POCIIO + val in = new HastiSlaveIO + val out = new PociIO } 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 } -class POCIBus(amap: Seq[UInt=>Bool]) extends Module +class PociBus(amap: Seq[UInt=>Bool]) extends Module { val io = new Bundle { - val master = new POCIIO().flip - val slaves = Vec(new POCIIO, amap.size) + val master = new PociIO().flip + val slaves = Vec(new PociIO, amap.size) } val psels = PriorityEncoderOH( diff --git a/junctions/src/main/scala/smi.scala b/junctions/src/main/scala/smi.scala index d2d65067..7d26deb7 100644 --- a/junctions/src/main/scala/smi.scala +++ b/junctions/src/main/scala/smi.scala @@ -87,11 +87,11 @@ class SMIArbiter(val n: Int, val dataWidth: Int, val addrWidth: Int) io.out.resp.ready := io.in(choice).resp.ready } -class SMIIONASTIReadIOConverter(val dataWidth: Int, val addrWidth: Int) - extends NASTIModule { +class SMIIONastiReadIOConverter(val dataWidth: Int, val addrWidth: Int) + (implicit p: Parameters) extends NastiModule()(p) { val io = new Bundle { - val ar = Decoupled(new NASTIReadAddressChannel).flip - val r = Decoupled(new NASTIReadDataChannel) + val ar = Decoupled(new NastiReadAddressChannel).flip + val r = Decoupled(new NastiReadDataChannel) 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.r.valid := (state === s_resp) - io.r.bits := NASTIReadDataChannel( + io.r.bits := NastiReadDataChannel( id = id, data = buffer.toBits, last = (nBeats === UInt(0))) @@ -169,12 +169,12 @@ class SMIIONASTIReadIOConverter(val dataWidth: Int, val addrWidth: Int) } } -class SMIIONASTIWriteIOConverter(val dataWidth: Int, val addrWidth: Int) - extends NASTIModule { +class SMIIONastiWriteIOConverter(val dataWidth: Int, val addrWidth: Int) + (implicit p: Parameters) extends NastiModule()(p) { val io = new Bundle { - val aw = Decoupled(new NASTIWriteAddressChannel).flip - val w = Decoupled(new NASTIWriteDataChannel).flip - val b = Decoupled(new NASTIWriteResponseChannel) + val aw = Decoupled(new NastiWriteAddressChannel).flip + val w = Decoupled(new NastiWriteDataChannel).flip + val b = Decoupled(new NastiWriteResponseChannel) val smi = new SMIIO(dataWidth, addrWidth) } @@ -184,7 +184,7 @@ class SMIIONASTIWriteIOConverter(val dataWidth: Int, val addrWidth: Int) private val addrOffBits = addrWidth + 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 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.resp.ready := (state === s_ack) io.b.valid := (state === s_resp) - io.b.bits := NASTIWriteResponseChannel(id) + io.b.bits := NastiWriteResponseChannel(id) val jump = if (maxWordsPerBeat > 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 } } -/** Convert NASTI protocol to SMI protocol */ -class SMIIONASTIIOConverter(val dataWidth: Int, val addrWidth: Int) - extends NASTIModule { +/** Convert Nasti protocol to SMI protocol */ +class SMIIONastiIOConverter(val dataWidth: Int, val addrWidth: Int) + (implicit p: Parameters) extends NastiModule()(p) { val io = new Bundle { - val nasti = (new NASTIIO).flip + val nasti = (new NastiIO).flip val smi = new SMIIO(dataWidth, addrWidth) } 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 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.w <> io.nasti.w io.nasti.b <> writer.io.b diff --git a/junctions/src/main/scala/util.scala b/junctions/src/main/scala/util.scala new file mode 100644 index 00000000..62b1e189 --- /dev/null +++ b/junctions/src/main/scala/util.scala @@ -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 + } +}