2016-11-28 01:16:37 +01:00
|
|
|
// See LICENSE.SiFive for license details.
|
2016-10-09 06:39:49 +02:00
|
|
|
|
|
|
|
package uncore.axi4
|
|
|
|
|
|
|
|
import Chisel._
|
2016-12-02 02:46:52 +01:00
|
|
|
import config._
|
2016-10-09 06:39:49 +02:00
|
|
|
import diplomacy._
|
|
|
|
import regmapper._
|
|
|
|
import scala.math.{min,max}
|
|
|
|
|
2016-10-28 03:38:14 +02:00
|
|
|
class AXI4RegisterNode(address: AddressSet, concurrency: Int = 0, beatBytes: Int = 4, undefZero: Boolean = true, executable: Boolean = false)
|
2017-01-30 00:17:52 +01:00
|
|
|
extends AXI4SlaveNode(Seq(AXI4SlavePortParameters(
|
2016-10-09 06:39:49 +02:00
|
|
|
Seq(AXI4SlaveParameters(
|
|
|
|
address = Seq(address),
|
2016-10-28 03:38:14 +02:00
|
|
|
executable = executable,
|
2016-10-09 06:39:49 +02:00
|
|
|
supportsWrite = TransferSizes(1, beatBytes),
|
|
|
|
supportsRead = TransferSizes(1, beatBytes),
|
|
|
|
interleavedId = Some(0))),
|
2017-01-24 02:54:27 +01:00
|
|
|
beatBytes = beatBytes,
|
2017-04-22 01:59:59 +02:00
|
|
|
minLatency = 1)))
|
2016-10-09 06:39:49 +02:00
|
|
|
{
|
|
|
|
require (address.contiguous)
|
|
|
|
|
|
|
|
// Calling this method causes the matching AXI4 bundle to be
|
|
|
|
// configured to route all requests to the listed RegFields.
|
|
|
|
def regmap(mapping: RegField.Map*) = {
|
|
|
|
val ar = bundleIn(0).ar
|
|
|
|
val aw = bundleIn(0).aw
|
|
|
|
val w = bundleIn(0).w
|
|
|
|
val r = bundleIn(0).r
|
|
|
|
val b = bundleIn(0).b
|
|
|
|
|
2017-04-21 02:58:07 +02:00
|
|
|
val params = RegMapperParams(log2Up((address.mask+1)/beatBytes), beatBytes, ar.bits.params.idBits + ar.bits.params.userBits)
|
2016-10-09 06:39:49 +02:00
|
|
|
val in = Wire(Decoupled(new RegMapperInput(params)))
|
|
|
|
|
|
|
|
// Prefer to execute reads first
|
|
|
|
in.valid := ar.valid || (aw.valid && w.valid)
|
|
|
|
ar.ready := in.ready
|
|
|
|
aw.ready := in.ready && !ar.valid && w .valid
|
|
|
|
w .ready := in.ready && !ar.valid && aw.valid
|
|
|
|
|
2017-04-21 02:58:07 +02:00
|
|
|
val ar_extra = Cat(Seq(ar.bits.id) ++ ar.bits.user.toList)
|
|
|
|
val aw_extra = Cat(Seq(aw.bits.id) ++ aw.bits.user.toList)
|
|
|
|
val in_extra = Mux(ar.valid, ar_extra, aw_extra)
|
|
|
|
val addr = Mux(ar.valid, ar.bits.addr, aw.bits.addr)
|
2016-10-09 06:39:49 +02:00
|
|
|
val mask = uncore.tilelink2.maskGen(ar.bits.addr, ar.bits.size, beatBytes)
|
|
|
|
|
|
|
|
in.bits.read := ar.valid
|
|
|
|
in.bits.index := addr >> log2Ceil(beatBytes)
|
|
|
|
in.bits.data := w.bits.data
|
|
|
|
in.bits.mask := Mux(ar.valid, mask, w.bits.strb)
|
2017-04-21 02:58:07 +02:00
|
|
|
in.bits.extra := in_extra
|
2016-10-09 06:39:49 +02:00
|
|
|
|
|
|
|
// Invoke the register map builder and make it Irrevocable
|
|
|
|
val out = Queue.irrevocable(
|
|
|
|
RegMapper(beatBytes, concurrency, undefZero, in, mapping:_*),
|
2017-04-22 01:59:59 +02:00
|
|
|
entries = 2)
|
2016-10-09 06:39:49 +02:00
|
|
|
|
|
|
|
// No flow control needed
|
|
|
|
out.ready := Mux(out.bits.read, r.ready, b.ready)
|
|
|
|
r.valid := out.valid && out.bits.read
|
|
|
|
b.valid := out.valid && !out.bits.read
|
|
|
|
|
2017-04-21 02:58:07 +02:00
|
|
|
val out_id = if (r.bits.params.idBits == 0) UInt(0) else (out.bits.extra >> ar.bits.params.userBits)
|
2016-10-09 06:39:49 +02:00
|
|
|
|
|
|
|
r.bits.id := out_id
|
|
|
|
r.bits.data := out.bits.data
|
|
|
|
r.bits.last := Bool(true)
|
|
|
|
r.bits.resp := AXI4Parameters.RESP_OKAY
|
2017-04-21 02:58:07 +02:00
|
|
|
r.bits.user.foreach { _ := out.bits.extra }
|
|
|
|
|
2016-10-09 06:39:49 +02:00
|
|
|
b.bits.id := out_id
|
|
|
|
b.bits.resp := AXI4Parameters.RESP_OKAY
|
2017-04-21 02:58:07 +02:00
|
|
|
b.bits.user.foreach { _ := out.bits.extra }
|
2016-10-09 06:39:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
object AXI4RegisterNode
|
|
|
|
{
|
2016-10-28 03:38:14 +02:00
|
|
|
def apply(address: AddressSet, concurrency: Int = 0, beatBytes: Int = 4, undefZero: Boolean = true, executable: Boolean = false) =
|
|
|
|
new AXI4RegisterNode(address, concurrency, beatBytes, undefZero, executable)
|
2016-10-09 06:39:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// These convenience methods below combine to make it possible to create a AXI4
|
|
|
|
// register mapped device from a totally abstract register mapped device.
|
|
|
|
|
2016-12-02 02:46:52 +01:00
|
|
|
abstract class AXI4RegisterRouterBase(address: AddressSet, interrupts: Int, concurrency: Int, beatBytes: Int, undefZero: Boolean, executable: Boolean)(implicit p: Parameters) extends LazyModule
|
2016-10-09 06:39:49 +02:00
|
|
|
{
|
2016-10-28 03:38:14 +02:00
|
|
|
val node = AXI4RegisterNode(address, concurrency, beatBytes, undefZero, executable)
|
2017-03-02 03:23:28 +01:00
|
|
|
val intnode = uncore.tilelink2.IntSourceNode(uncore.tilelink2.IntSourcePortSimple(num = interrupts))
|
2016-10-09 06:39:49 +02:00
|
|
|
}
|
|
|
|
|
2017-02-23 02:05:22 +01:00
|
|
|
case class AXI4RegBundleArg(interrupts: util.HeterogeneousBag[Vec[Bool]], in: util.HeterogeneousBag[AXI4Bundle])(implicit val p: Parameters)
|
2016-10-09 06:39:49 +02:00
|
|
|
|
|
|
|
class AXI4RegBundleBase(arg: AXI4RegBundleArg) extends Bundle
|
|
|
|
{
|
2016-12-02 02:46:52 +01:00
|
|
|
implicit val p = arg.p
|
2016-10-09 06:39:49 +02:00
|
|
|
val interrupts = arg.interrupts
|
|
|
|
val in = arg.in
|
|
|
|
}
|
|
|
|
|
|
|
|
class AXI4RegBundle[P](val params: P, arg: AXI4RegBundleArg) extends AXI4RegBundleBase(arg)
|
|
|
|
|
|
|
|
class AXI4RegModule[P, B <: AXI4RegBundleBase](val params: P, bundleBuilder: => B, router: AXI4RegisterRouterBase)
|
|
|
|
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 AXI4RegisterRouter[B <: AXI4RegBundleBase, M <: LazyModuleImp]
|
2016-10-28 03:38:14 +02:00
|
|
|
(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)
|
2016-10-09 06:39:49 +02:00
|
|
|
(bundleBuilder: AXI4RegBundleArg => B)
|
2016-12-02 02:46:52 +01:00
|
|
|
(moduleBuilder: (=> B, AXI4RegisterRouterBase) => M)(implicit p: Parameters)
|
2016-10-28 03:38:14 +02:00
|
|
|
extends AXI4RegisterRouterBase(AddressSet(base, size-1), interrupts, concurrency, beatBytes, undefZero, executable)
|
2016-10-09 06:39:49 +02:00
|
|
|
{
|
|
|
|
require (isPow2(size))
|
|
|
|
// require (size >= 4096) ... not absolutely required, but highly recommended
|
|
|
|
|
|
|
|
lazy val module = moduleBuilder(bundleBuilder(AXI4RegBundleArg(intnode.bundleOut, node.bundleIn)), this)
|
|
|
|
}
|