1
0
rocket-chip/uncore/src/main/scala/scr.scala
Palmer Dabbelt 1ac9f59b31 Allow SCR files to be enumerated in C headers
Right now there's no way to ensure that SCR addresses don't conflict within
RocketChip.  Since upstream only has one of them this isn't a big deal, but we
want to add a whole bunch more to control all the IP on Hurricane.

This patch adds some Scala code to allocate registers inside the SCR file,
ensure they don't conflict, to provide names for SCRs, attach registers to the
SCR file, and generate a C header file that contains the addresses of every SCR
on a chip.

With this patch we'll be able to get rid of that constant in the testbench.
This also allows us to kill one of the Raven diffs, which is does pretty much
the same thing (just in a second SCR file, and hacked in).
2016-02-17 14:21:12 -08:00

98 lines
3.0 KiB
Scala

package uncore
import Chisel._
import junctions.{SmiIO, MMIOBase}
import cde.Parameters
import scala.collection.mutable.HashMap
import scala.collection.mutable.ArrayBuffer
/** Stores a map between SCR file names and address in the SCR file, which can
* later be dumped to a header file for the test bench. */
class SCRFileMap(prefix: String, maxAddress: Int) {
private val addr2name = HashMap.empty[Int, String]
private val name2addr = HashMap.empty[String, Int]
def allocate(address: Int, name: String): Int = {
Predef.assert(!addr2name.contains(address), "address already allocated")
Predef.assert(!name2addr.contains(name), "name already allocated")
Predef.assert(address < maxAddress, "address too large")
addr2name += (address -> name)
name2addr += (name -> address)
println(prefix + ": " + address + " -> " + name)
address
}
def allocate(name: String): Int = {
val addr = (0 until maxAddress).filter{ addr => !addr2name.contains(addr) }(0)
allocate(addr, name)
}
def as_c_header(): String = {
addr2name.map{ case(address, name) =>
"#define " + prefix + "__" + name + " " + address
}.mkString("\n") + "\n"
}
}
class SCRIO(map: SCRFileMap)(implicit p: Parameters) extends HtifBundle()(p) {
val rdata = Vec(nSCR, Bits(INPUT, scrDataBits))
val wen = Bool(OUTPUT)
val waddr = UInt(OUTPUT, log2Up(nSCR))
val wdata = Bits(OUTPUT, scrDataBits)
def attach(reg: Data, name: String): Data = {
val addr = map.allocate(name)
when (wen && (waddr === UInt(addr))) {
reg := wdata
}
rdata(addr) := reg
reg
}
def allocate(address: Int, name: String): Unit = {
map.allocate(address, name)
}
}
class SCRFile(prefix: String)(implicit p: Parameters) extends HtifModule()(p) {
val map = new SCRFileMap(prefix, 64)
AllSCRFiles += map
val io = new Bundle {
val smi = new SmiIO(scrDataBits, scrAddrBits).flip
val scr = new SCRIO(map)
}
val scr_rdata = Wire(Vec(io.scr.rdata.size, Bits(width=scrDataBits)))
for (i <- 0 until scr_rdata.size)
scr_rdata(i) := io.scr.rdata(i)
scr_rdata(0) := UInt(nCores); map.allocate(0, "N_CORES")
scr_rdata(1) := UInt(p(MMIOBase) >> 20); map.allocate(1, "MMIO_BASE")
val read_addr = Reg(init = UInt(0, scrAddrBits))
val resp_valid = Reg(init = Bool(false))
io.smi.req.ready := !resp_valid
io.smi.resp.valid := resp_valid
io.smi.resp.bits := scr_rdata(read_addr)
io.scr.wen := io.smi.req.fire() && io.smi.req.bits.rw
io.scr.wdata := io.smi.req.bits.data
io.scr.waddr := io.smi.req.bits.addr
when (io.smi.req.fire()) {
read_addr := io.smi.req.bits.addr
resp_valid := Bool(true)
}
when (io.smi.resp.fire()) { resp_valid := Bool(false) }
}
/** Every elaborated SCR file ends up in this global arry so it can be printed
* out later. */
object AllSCRFiles {
private var maps = ArrayBuffer.empty[SCRFileMap]
def +=(map: SCRFileMap): Unit = { maps += map }
def foreach( f: (SCRFileMap => Unit) ): Unit = { maps.foreach{ m => f(m) } }
}