Merge branch 'param-refactor'
This commit is contained in:
		
							
								
								
									
										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._ | ||||
|  | ||||
| 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 | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -1 +1 @@ | ||||
| package object junctions extends HASTIConstants with POCIConstants | ||||
| package object junctions extends HastiConstants with PociConstants | ||||
|   | ||||
| @@ -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( | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
							
								
								
									
										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 | ||||
|   } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user