2016-08-27 00:48:48 +02:00
|
|
|
// See LICENSE for license details.
|
|
|
|
|
|
|
|
package uncore.tilelink2
|
|
|
|
|
|
|
|
import Chisel._
|
|
|
|
|
2016-08-30 00:33:10 +02:00
|
|
|
class TLRegisterNode(address: AddressSet, concurrency: Option[Int] = None, beatBytes: Int = 4)
|
2016-08-27 00:48:48 +02:00
|
|
|
extends TLManagerNode(beatBytes, TLManagerParameters(
|
|
|
|
address = Seq(address),
|
|
|
|
supportsGet = TransferSizes(1, beatBytes),
|
|
|
|
supportsPutPartial = TransferSizes(1, beatBytes),
|
|
|
|
supportsPutFull = TransferSizes(1, beatBytes),
|
|
|
|
fifoId = Some(0))) // requests are handled in order
|
|
|
|
{
|
|
|
|
require (!address.strided)
|
|
|
|
|
|
|
|
// Calling this method causes the matching TL2 bundle to be
|
|
|
|
// configured to route all requests to the listed RegFields.
|
|
|
|
def regmap(mapping: RegField.Map*) = {
|
2016-08-30 00:33:10 +02:00
|
|
|
val a = bundleIn(0).a
|
2016-08-27 00:48:48 +02:00
|
|
|
val d = bundleIn(0).d
|
2016-08-30 00:33:10 +02:00
|
|
|
val edge = edgesIn(0)
|
|
|
|
|
2016-08-31 22:37:20 +02:00
|
|
|
val params = RegMapperParams(log2Up(address.mask+1), beatBytes, edge.bundle.sourceBits + edge.bundle.sizeBits)
|
|
|
|
val in = Wire(Decoupled(new RegMapperInput(params)))
|
2016-08-30 00:33:10 +02:00
|
|
|
in.bits.read := a.bits.opcode === TLMessages.Get
|
|
|
|
in.bits.index := a.bits.address >> log2Ceil(beatBytes)
|
|
|
|
in.bits.data := a.bits.data
|
2016-08-31 00:06:37 +02:00
|
|
|
in.bits.mask := a.bits.mask
|
2016-08-30 00:33:10 +02:00
|
|
|
in.bits.extra := Cat(a.bits.source, a.bits.size)
|
|
|
|
|
|
|
|
// Invoke the register map builder
|
2016-08-31 22:37:20 +02:00
|
|
|
val (endIndex, out) = RegMapper(beatBytes, concurrency, in, mapping:_*)
|
2016-08-27 00:48:48 +02:00
|
|
|
|
2016-08-30 00:33:10 +02:00
|
|
|
// All registers must fit inside the device address space
|
|
|
|
require (address.mask >= (endIndex-1)*beatBytes)
|
2016-08-27 00:48:48 +02:00
|
|
|
|
2016-08-30 00:33:10 +02:00
|
|
|
// No flow control needed
|
|
|
|
in.valid := a.valid
|
|
|
|
a.ready := in.ready
|
|
|
|
d.valid := out.valid
|
|
|
|
out.ready := d.ready
|
2016-08-27 00:48:48 +02:00
|
|
|
|
2016-08-30 00:33:10 +02:00
|
|
|
val sizeBits = edge.bundle.sizeBits
|
|
|
|
d.bits := edge.AccessAck(out.bits.extra >> sizeBits, out.bits.extra(sizeBits-1, 0))
|
2016-08-27 00:48:48 +02:00
|
|
|
// avoid a Mux on the data bus by manually overriding two fields
|
2016-08-30 00:33:10 +02:00
|
|
|
d.bits.data := out.bits.data
|
|
|
|
d.bits.opcode := Mux(out.bits.read, TLMessages.AccessAckData, TLMessages.AccessAck)
|
2016-08-27 00:48:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
object TLRegisterNode
|
|
|
|
{
|
2016-08-30 00:33:10 +02:00
|
|
|
def apply(address: AddressSet, concurrency: Option[Int] = None, beatBytes: Int = 4) =
|
|
|
|
new TLRegisterNode(address, concurrency, beatBytes)
|
2016-08-27 00:48:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// These convenience methods below combine to make it possible to create a TL2
|
|
|
|
// register mapped device from a totally abstract register mapped device.
|
|
|
|
// See GPIO.scala in this directory for an example
|
|
|
|
|
2016-08-31 19:25:46 +02:00
|
|
|
abstract class TLRegisterRouterBase(address: AddressSet, concurrency: Option[Int], beatBytes: Int) extends LazyModule
|
2016-08-27 00:48:48 +02:00
|
|
|
{
|
2016-08-30 00:33:10 +02:00
|
|
|
val node = TLRegisterNode(address, concurrency, beatBytes)
|
2016-08-27 00:48:48 +02:00
|
|
|
}
|
|
|
|
|
2016-08-30 19:40:54 +02:00
|
|
|
class TLRegBundle[P](val params: P, val in: Vec[TLBundle]) extends Bundle
|
2016-08-27 00:48:48 +02:00
|
|
|
|
2016-08-31 19:25:46 +02:00
|
|
|
class TLRegModule[P, B <: Bundle](val params: P, bundleBuilder: => B, router: TLRegisterRouterBase)
|
|
|
|
extends LazyModuleImp(router) with HasRegMap
|
2016-08-27 00:48:48 +02:00
|
|
|
{
|
2016-08-29 20:08:37 +02:00
|
|
|
val io = bundleBuilder
|
2016-08-31 19:25:46 +02:00
|
|
|
def regmap(mapping: RegField.Map*) = router.node.regmap(mapping:_*)
|
2016-08-27 00:48:48 +02:00
|
|
|
}
|
|
|
|
|
2016-08-31 19:25:46 +02:00
|
|
|
class TLRegisterRouter[B <: Bundle, M <: LazyModuleImp]
|
2016-08-31 23:49:18 +02:00
|
|
|
(base: BigInt, size: BigInt = 4096, concurrency: Option[Int] = None, beatBytes: Int = 4)
|
2016-08-27 00:48:48 +02:00
|
|
|
(bundleBuilder: Vec[TLBundle] => B)
|
2016-08-31 19:25:46 +02:00
|
|
|
(moduleBuilder: (=> B, TLRegisterRouterBase) => M)
|
2016-08-31 23:49:18 +02:00
|
|
|
extends TLRegisterRouterBase(AddressSet(base, size-1), concurrency, beatBytes)
|
2016-08-27 00:48:48 +02:00
|
|
|
{
|
|
|
|
require (size % 4096 == 0) // devices should be 4K aligned
|
|
|
|
require (isPow2(size))
|
|
|
|
require (size >= 4096)
|
|
|
|
|
|
|
|
lazy val module = Module(moduleBuilder(bundleBuilder(node.bundleIn), this))
|
|
|
|
}
|