1
0
rocket-chip/src/main/scala/uncore/ahb/RegisterRouter.scala
2016-12-08 18:00:39 -08:00

112 lines
4.2 KiB
Scala

// See LICENSE.SiFive for license details.
package uncore.ahb
import Chisel._
import config._
import diplomacy._
import regmapper._
import scala.math.{min,max}
class AHBRegisterNode(address: AddressSet, concurrency: Int = 0, beatBytes: Int = 4, undefZero: Boolean = true, executable: Boolean = false)
extends AHBSlaveNode(AHBSlavePortParameters(
Seq(AHBSlaveParameters(
address = Seq(address),
executable = executable,
supportsWrite = TransferSizes(1, beatBytes * AHBParameters.maxTransfer),
supportsRead = TransferSizes(1, beatBytes * AHBParameters.maxTransfer))),
beatBytes = beatBytes))
{
require (address.contiguous)
// Calling this method causes the matching AHB bundle to be
// configured to route all requests to the listed RegFields.
def regmap(mapping: RegField.Map*) = {
val ahb = bundleIn(0)
val indexBits = log2Up((address.mask+1)/beatBytes)
val params = RegMapperParams(indexBits, beatBytes, 1)
val in = Wire(Decoupled(new RegMapperInput(params)))
val out = RegMapper(beatBytes, concurrency, undefZero, in, mapping:_*)
val d_phase = RegInit(Bool(false))
val d_taken = Reg(Bool())
val d_read = Reg(Bool())
val d_index = Reg(UInt(width = indexBits))
val d_mask = Reg(UInt(width = beatBytes))
// Only send the request to the RR once
d_taken := d_phase && in.ready
in.valid := d_phase && !d_taken
in.bits.read := d_read
in.bits.index := d_index
in.bits.data := ahb.hwdata
in.bits.mask := d_mask
in.bits.extra := UInt(0)
ahb.hreadyout := !d_phase || out.valid
ahb.hresp := AHBParameters.RESP_OKAY
ahb.hrdata := out.bits.data
val request = ahb.htrans === AHBParameters.TRANS_NONSEQ || ahb.htrans === AHBParameters.TRANS_SEQ
when (ahb.hready && ahb.hsel && request) {
assert (!d_phase || in.ready)
d_phase := Bool(true)
d_taken := Bool(false)
d_read := !ahb.hwrite
d_index := ahb.haddr >> log2Ceil(beatBytes)
d_mask := uncore.tilelink2.maskGen(ahb.haddr, ahb.hsize, beatBytes)
}
out.ready := Bool(true)
assert (d_phase || !out.valid)
}
}
object AHBRegisterNode
{
def apply(address: AddressSet, concurrency: Int = 0, beatBytes: Int = 4, undefZero: Boolean = true, executable: Boolean = false) =
new AHBRegisterNode(address, concurrency, beatBytes, undefZero, executable)
}
// These convenience methods below combine to make it possible to create a AHB
// register mapped device from a totally abstract register mapped device.
abstract class AHBRegisterRouterBase(address: AddressSet, interrupts: Int, concurrency: Int, beatBytes: Int, undefZero: Boolean, executable: Boolean)(implicit p: Parameters) extends LazyModule
{
val node = AHBRegisterNode(address, concurrency, beatBytes, undefZero, executable)
val intnode = uncore.tilelink2.IntSourceNode(interrupts)
}
case class AHBRegBundleArg(interrupts: Vec[Vec[Bool]], in: Vec[AHBBundle])(implicit val p: Parameters)
class AHBRegBundleBase(arg: AHBRegBundleArg) extends Bundle
{
implicit val p = arg.p
val interrupts = arg.interrupts
val in = arg.in
}
class AHBRegBundle[P](val params: P, arg: AHBRegBundleArg) extends AHBRegBundleBase(arg)
class AHBRegModule[P, B <: AHBRegBundleBase](val params: P, bundleBuilder: => B, router: AHBRegisterRouterBase)
extends LazyModuleImp(router) with HasRegMap
{
val io = bundleBuilder
val interrupts = if (io.interrupts.isEmpty) Vec(0, Bool()) else io.interrupts(0)
def regmap(mapping: RegField.Map*) = router.node.regmap(mapping:_*)
}
class AHBRegisterRouter[B <: AHBRegBundleBase, M <: LazyModuleImp]
(val base: BigInt, val interrupts: Int = 0, val size: BigInt = 4096, val concurrency: Int = 0, val beatBytes: Int = 4, undefZero: Boolean = true, executable: Boolean = false)
(bundleBuilder: AHBRegBundleArg => B)
(moduleBuilder: (=> B, AHBRegisterRouterBase) => M)(implicit p: Parameters)
extends AHBRegisterRouterBase(AddressSet(base, size-1), interrupts, concurrency, beatBytes, undefZero, executable)
{
require (isPow2(size))
// require (size >= 4096) ... not absolutely required, but highly recommended
lazy val module = moduleBuilder(bundleBuilder(AHBRegBundleArg(intnode.bundleOut, node.bundleIn)), this)
}