112 lines
4.2 KiB
Scala
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)
|
|
}
|