commit
d4c9c13fb4
@ -345,7 +345,7 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Finish TileLink transaction by issuing a GrantAck
|
// Finish TileLink transaction by issuing a GrantAck
|
||||||
grantackq.io.enq.valid := d_done && edge.hasFollowUp(tl_out.d.bits)
|
grantackq.io.enq.valid := d_done && edge.isRequest(tl_out.d.bits)
|
||||||
grantackq.io.enq.bits := edge.GrantAck(tl_out.d.bits)
|
grantackq.io.enq.bits := edge.GrantAck(tl_out.d.bits)
|
||||||
tl_out.e <> grantackq.io.deq
|
tl_out.e <> grantackq.io.deq
|
||||||
assert(!grantackq.io.enq.valid || grantackq.io.enq.ready, "Too many Grants received by dcache.")
|
assert(!grantackq.io.enq.valid || grantackq.io.enq.ready, "Too many Grants received by dcache.")
|
||||||
|
@ -246,7 +246,7 @@ class MSHR(id: Int)(implicit edge: TLEdgeOut, p: Parameters) extends L1HellaCach
|
|||||||
|
|
||||||
val grantackq = Module(new Queue(io.mem_finish.bits, 1))
|
val grantackq = Module(new Queue(io.mem_finish.bits, 1))
|
||||||
val can_finish = state.isOneOf(s_invalid, s_refill_req)
|
val can_finish = state.isOneOf(s_invalid, s_refill_req)
|
||||||
grantackq.io.enq.valid := refill_done && edge.hasFollowUp(io.mem_grant.bits)
|
grantackq.io.enq.valid := refill_done && edge.isRequest(io.mem_grant.bits)
|
||||||
grantackq.io.enq.bits := edge.GrantAck(io.mem_grant.bits)
|
grantackq.io.enq.bits := edge.GrantAck(io.mem_grant.bits)
|
||||||
io.mem_finish.valid := grantackq.io.deq.valid && can_finish
|
io.mem_finish.valid := grantackq.io.deq.valid && can_finish
|
||||||
io.mem_finish.bits := grantackq.io.deq.bits
|
io.mem_finish.bits := grantackq.io.deq.bits
|
||||||
|
@ -40,7 +40,7 @@ class CoreplexLocalInterrupter(address: BigInt = 0x02000000)(implicit p: Paramet
|
|||||||
}
|
}
|
||||||
|
|
||||||
val node = TLRegisterNode(
|
val node = TLRegisterNode(
|
||||||
address = AddressSet(address, size-1),
|
address = Seq(AddressSet(address, size-1)),
|
||||||
device = device,
|
device = device,
|
||||||
beatBytes = p(XLen)/8)
|
beatBytes = p(XLen)/8)
|
||||||
|
|
||||||
|
@ -72,7 +72,7 @@ class TLPLIC(maxPriorities: Int, address: BigInt = 0xC000000)(implicit p: Parame
|
|||||||
}
|
}
|
||||||
|
|
||||||
val node = TLRegisterNode(
|
val node = TLRegisterNode(
|
||||||
address = AddressSet(address, PLICConsts.size-1),
|
address = Seq(AddressSet(address, PLICConsts.size-1)),
|
||||||
device = device,
|
device = device,
|
||||||
beatBytes = p(XLen)/8,
|
beatBytes = p(XLen)/8,
|
||||||
undefZero = false)
|
undefZero = false)
|
||||||
|
@ -57,7 +57,7 @@ class TLEdge(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def hasFollowUp(x: TLChannel): Bool = {
|
def isRequest(x: TLChannel): Bool = {
|
||||||
x match {
|
x match {
|
||||||
case a: TLBundleA => Bool(true)
|
case a: TLBundleA => Bool(true)
|
||||||
case b: TLBundleB => Bool(true)
|
case b: TLBundleB => Bool(true)
|
||||||
@ -71,6 +71,18 @@ class TLEdge(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def isResponse(x: TLChannel): Bool = {
|
||||||
|
x match {
|
||||||
|
case a: TLBundleA => Bool(false)
|
||||||
|
case b: TLBundleB => Bool(false)
|
||||||
|
case c: TLBundleC => !c.opcode(2) || !c.opcode(1)
|
||||||
|
// opcode =/= TLMessages.Release &&
|
||||||
|
// opcode =/= TLMessages.ReleaseData
|
||||||
|
case d: TLBundleD => Bool(true) // Grant isResponse + isRequest
|
||||||
|
case e: TLBundleE => Bool(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
def hasData(x: TLChannel): Bool = {
|
def hasData(x: TLChannel): Bool = {
|
||||||
val opdata = x match {
|
val opdata = x match {
|
||||||
case a: TLBundleA => !a.opcode(2)
|
case a: TLBundleA => !a.opcode(2)
|
||||||
|
@ -110,10 +110,9 @@ class TLMonitor(args: TLMonitorArgs) extends TLMonitorBase(args)
|
|||||||
when (bundle.opcode === TLMessages.Probe) {
|
when (bundle.opcode === TLMessages.Probe) {
|
||||||
assert (edge.client.supportsProbe(bundle.source, bundle.size), "'B' channel carries Probe type unsupported by client" + extra)
|
assert (edge.client.supportsProbe(bundle.source, bundle.size), "'B' channel carries Probe type unsupported by client" + extra)
|
||||||
assert (address_ok, "'B' channel Probe carries unmanaged address" + extra)
|
assert (address_ok, "'B' channel Probe carries unmanaged address" + extra)
|
||||||
assert (bundle.size >= UInt(log2Ceil(edge.manager.beatBytes)), "'B' channel Probe smaller than a beat" + extra)
|
|
||||||
assert (is_aligned, "'B' channel Probe address not aligned to size" + extra)
|
assert (is_aligned, "'B' channel Probe address not aligned to size" + extra)
|
||||||
assert (TLPermissions.isCap(bundle.param), "'B' channel Probe carries invalid cap param" + extra)
|
assert (TLPermissions.isCap(bundle.param), "'B' channel Probe carries invalid cap param" + extra)
|
||||||
assert (~bundle.mask === UInt(0), "'B' channel Probe contains invalid mask" + extra)
|
assert (bundle.mask === mask, "'B' channel Probe contains invalid mask" + extra)
|
||||||
}
|
}
|
||||||
|
|
||||||
when (bundle.opcode === TLMessages.Get) {
|
when (bundle.opcode === TLMessages.Get) {
|
||||||
@ -186,7 +185,6 @@ class TLMonitor(args: TLMonitorArgs) extends TLMonitorBase(args)
|
|||||||
assert (bundle.size >= UInt(log2Ceil(edge.manager.beatBytes)), "'C' channel ProbeAckData smaller than a beat" + extra)
|
assert (bundle.size >= UInt(log2Ceil(edge.manager.beatBytes)), "'C' channel ProbeAckData smaller than a beat" + extra)
|
||||||
assert (is_aligned, "'C' channel ProbeAckData address not aligned to size" + extra)
|
assert (is_aligned, "'C' channel ProbeAckData address not aligned to size" + extra)
|
||||||
assert (TLPermissions.isReport(bundle.param), "'C' channel ProbeAckData carries invalid report param" + extra)
|
assert (TLPermissions.isReport(bundle.param), "'C' channel ProbeAckData carries invalid report param" + extra)
|
||||||
assert (!bundle.error, "'C' channel ProbeData carries an error" + extra)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
when (bundle.opcode === TLMessages.Release) {
|
when (bundle.opcode === TLMessages.Release) {
|
||||||
@ -204,7 +202,6 @@ class TLMonitor(args: TLMonitorArgs) extends TLMonitorBase(args)
|
|||||||
assert (bundle.size >= UInt(log2Ceil(edge.manager.beatBytes)), "'C' channel ReleaseData smaller than a beat" + extra)
|
assert (bundle.size >= UInt(log2Ceil(edge.manager.beatBytes)), "'C' channel ReleaseData smaller than a beat" + extra)
|
||||||
assert (is_aligned, "'C' channel ReleaseData address not aligned to size" + extra)
|
assert (is_aligned, "'C' channel ReleaseData address not aligned to size" + extra)
|
||||||
assert (TLPermissions.isShrink(bundle.param), "'C' channel ReleaseData carries invalid shrink param" + extra)
|
assert (TLPermissions.isShrink(bundle.param), "'C' channel ReleaseData carries invalid shrink param" + extra)
|
||||||
assert (!bundle.error, "'C' channel ReleaseData carries an error" + extra)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
when (bundle.opcode === TLMessages.AccessAck) {
|
when (bundle.opcode === TLMessages.AccessAck) {
|
||||||
@ -411,34 +408,66 @@ class TLMonitor(args: TLMonitorArgs) extends TLMonitorBase(args)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def legalizeSourceUnique(bundle: TLBundleSnoop, edge: TLEdge)(implicit sourceInfo: SourceInfo) {
|
def legalizeADSource(bundle: TLBundleSnoop, edge: TLEdge)(implicit sourceInfo: SourceInfo) {
|
||||||
val inflight = RegInit(UInt(0, width = edge.client.endSourceId))
|
val inflight = RegInit(UInt(0, width = edge.client.endSourceId))
|
||||||
|
|
||||||
val a_last = edge.last(bundle.a.bits, bundle.a.fire())
|
val a_first = edge.first(bundle.a.bits, bundle.a.fire())
|
||||||
val d_last = edge.last(bundle.d.bits, bundle.d.fire())
|
val d_first = edge.first(bundle.d.bits, bundle.d.fire())
|
||||||
|
|
||||||
if (edge.manager.minLatency > 0) {
|
|
||||||
assert(bundle.d.bits.opcode === TLMessages.ReleaseAck || bundle.a.bits.source =/= bundle.d.bits.source || !bundle.a.valid || !bundle.d.valid, s"'A' and 'D' concurrent, despite minlatency ${edge.manager.minLatency}" + extra)
|
|
||||||
}
|
|
||||||
|
|
||||||
val a_set = Wire(init = UInt(0, width = edge.client.endSourceId))
|
val a_set = Wire(init = UInt(0, width = edge.client.endSourceId))
|
||||||
when (bundle.a.fire()) {
|
when (bundle.a.fire() && a_first && edge.isRequest(bundle.a.bits)) {
|
||||||
when (a_last) { a_set := UIntToOH(bundle.a.bits.source) }
|
a_set := UIntToOH(bundle.a.bits.source)
|
||||||
assert(!inflight(bundle.a.bits.source), "'A' channel re-used a source ID" + extra)
|
assert(!inflight(bundle.a.bits.source), "'A' channel re-used a source ID" + extra)
|
||||||
}
|
}
|
||||||
|
|
||||||
val d_clr = Wire(init = UInt(0, width = edge.client.endSourceId))
|
val d_clr = Wire(init = UInt(0, width = edge.client.endSourceId))
|
||||||
when (bundle.d.fire() && bundle.d.bits.opcode =/= TLMessages.ReleaseAck) {
|
val d_release_ack = bundle.d.bits.opcode === TLMessages.ReleaseAck
|
||||||
when (d_last) { d_clr := UIntToOH(bundle.d.bits.source) }
|
when (bundle.d.fire() && d_first && edge.isResponse(bundle.d.bits) && !d_release_ack) {
|
||||||
|
d_clr := UIntToOH(bundle.d.bits.source)
|
||||||
assert((a_set | inflight)(bundle.d.bits.source), "'D' channel acknowledged for nothing inflight" + extra)
|
assert((a_set | inflight)(bundle.d.bits.source), "'D' channel acknowledged for nothing inflight" + extra)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (edge.manager.minLatency > 0) {
|
||||||
|
assert(a_set =/= d_clr || !a_set.orR, s"'A' and 'D' concurrent, despite minlatency ${edge.manager.minLatency}" + extra)
|
||||||
|
}
|
||||||
|
|
||||||
inflight := (inflight | a_set) & ~d_clr
|
inflight := (inflight | a_set) & ~d_clr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def legalizeDESink(bundle: TLBundleSnoop, edge: TLEdge)(implicit sourceInfo: SourceInfo) {
|
||||||
|
val inflight = RegInit(UInt(0, width = edge.manager.endSinkId))
|
||||||
|
|
||||||
|
val d_first = edge.first(bundle.d.bits, bundle.d.fire())
|
||||||
|
val e_first = Bool(true)
|
||||||
|
|
||||||
|
val d_set = Wire(init = UInt(0, width = edge.manager.endSinkId))
|
||||||
|
when (bundle.d.fire() && d_first && edge.isRequest(bundle.d.bits)) {
|
||||||
|
d_set := UIntToOH(bundle.d.bits.sink)
|
||||||
|
assert(!inflight(bundle.d.bits.sink), "'D' channel re-used a sink ID" + extra)
|
||||||
|
}
|
||||||
|
|
||||||
|
val e_clr = Wire(init = UInt(0, width = edge.manager.endSinkId))
|
||||||
|
when (bundle.e.fire() && e_first && edge.isResponse(bundle.e.bits)) {
|
||||||
|
e_clr := UIntToOH(bundle.e.bits.sink)
|
||||||
|
assert((d_set | inflight)(bundle.e.bits.sink), "'E' channel acknowledged for nothing inflight" + extra)
|
||||||
|
}
|
||||||
|
|
||||||
|
// edge.client.minLatency applies to BC, not DE
|
||||||
|
|
||||||
|
inflight := (inflight | d_set) & ~e_clr
|
||||||
|
}
|
||||||
|
|
||||||
|
def legalizeUnique(bundle: TLBundleSnoop, edge: TLEdge)(implicit sourceInfo: SourceInfo) {
|
||||||
|
legalizeADSource(bundle, edge)
|
||||||
|
if (edge.client.anySupportProbe && edge.manager.anySupportAcquireB) {
|
||||||
|
// legalizeBCSourceAddress(bundle, edge) // too much state needed to synthesize...
|
||||||
|
legalizeDESink(bundle, edge)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
def legalize(bundle: TLBundleSnoop, edge: TLEdge, reset: Bool) {
|
def legalize(bundle: TLBundleSnoop, edge: TLEdge, reset: Bool) {
|
||||||
legalizeFormat (bundle, edge)
|
legalizeFormat (bundle, edge)
|
||||||
legalizeMultibeat(bundle, edge)
|
legalizeMultibeat(bundle, edge)
|
||||||
legalizeSourceUnique(bundle, edge)
|
legalizeUnique (bundle, edge)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -189,7 +189,7 @@ case class TLClientParameters(
|
|||||||
case class TLClientPortParameters(
|
case class TLClientPortParameters(
|
||||||
clients: Seq[TLClientParameters],
|
clients: Seq[TLClientParameters],
|
||||||
unsafeAtomics: Boolean = false,
|
unsafeAtomics: Boolean = false,
|
||||||
minLatency: Int = 0) // Atomics are executed as get+put
|
minLatency: Int = 0) // Only applies to B=>C
|
||||||
{
|
{
|
||||||
require (!clients.isEmpty)
|
require (!clients.isEmpty)
|
||||||
require (minLatency >= 0)
|
require (minLatency >= 0)
|
||||||
|
@ -9,7 +9,7 @@ import regmapper._
|
|||||||
import scala.math.{min,max}
|
import scala.math.{min,max}
|
||||||
|
|
||||||
class TLRegisterNode(
|
class TLRegisterNode(
|
||||||
address: AddressSet,
|
address: Seq[AddressSet],
|
||||||
device: Device,
|
device: Device,
|
||||||
deviceKey: String = "reg",
|
deviceKey: String = "reg",
|
||||||
concurrency: Int = 0,
|
concurrency: Int = 0,
|
||||||
@ -18,7 +18,7 @@ class TLRegisterNode(
|
|||||||
executable: Boolean = false)
|
executable: Boolean = false)
|
||||||
extends TLManagerNode(Seq(TLManagerPortParameters(
|
extends TLManagerNode(Seq(TLManagerPortParameters(
|
||||||
Seq(TLManagerParameters(
|
Seq(TLManagerParameters(
|
||||||
address = Seq(address),
|
address = address,
|
||||||
resources = Seq(Resource(device, deviceKey)),
|
resources = Seq(Resource(device, deviceKey)),
|
||||||
executable = executable,
|
executable = executable,
|
||||||
supportsGet = TransferSizes(1, beatBytes),
|
supportsGet = TransferSizes(1, beatBytes),
|
||||||
@ -28,7 +28,12 @@ class TLRegisterNode(
|
|||||||
beatBytes = beatBytes,
|
beatBytes = beatBytes,
|
||||||
minLatency = min(concurrency, 1)))) // the Queue adds at most one cycle
|
minLatency = min(concurrency, 1)))) // the Queue adds at most one cycle
|
||||||
{
|
{
|
||||||
require (address.contiguous)
|
val size = 1 << log2Ceil(1 + address.map(_.max).max - address.map(_.base).min)
|
||||||
|
require (size >= beatBytes)
|
||||||
|
address.foreach { case a =>
|
||||||
|
require (a.widen(size-1).base == address.head.widen(size-1).base,
|
||||||
|
s"TLRegisterNode addresses (${address}) must be aligned to its size ${size}")
|
||||||
|
}
|
||||||
|
|
||||||
// Calling this method causes the matching TL2 bundle to be
|
// Calling this method causes the matching TL2 bundle to be
|
||||||
// configured to route all requests to the listed RegFields.
|
// configured to route all requests to the listed RegFields.
|
||||||
@ -43,7 +48,7 @@ class TLRegisterNode(
|
|||||||
val (sourceEnd, sourceOff) = (edge.bundle.sourceBits + sizeEnd, sizeEnd)
|
val (sourceEnd, sourceOff) = (edge.bundle.sourceBits + sizeEnd, sizeEnd)
|
||||||
val (addrLoEnd, addrLoOff) = (log2Up(beatBytes) + sourceEnd, sourceEnd)
|
val (addrLoEnd, addrLoOff) = (log2Up(beatBytes) + sourceEnd, sourceEnd)
|
||||||
|
|
||||||
val params = RegMapperParams(log2Up((address.mask+1)/beatBytes), beatBytes, addrLoEnd)
|
val params = RegMapperParams(log2Up(size/beatBytes), beatBytes, addrLoEnd)
|
||||||
val in = Wire(Decoupled(new RegMapperInput(params)))
|
val in = Wire(Decoupled(new RegMapperInput(params)))
|
||||||
in.bits.read := a.bits.opcode === TLMessages.Get
|
in.bits.read := a.bits.opcode === TLMessages.Get
|
||||||
in.bits.index := edge.addr_hi(a.bits)
|
in.bits.index := edge.addr_hi(a.bits)
|
||||||
@ -81,7 +86,7 @@ class TLRegisterNode(
|
|||||||
object TLRegisterNode
|
object TLRegisterNode
|
||||||
{
|
{
|
||||||
def apply(
|
def apply(
|
||||||
address: AddressSet,
|
address: Seq[AddressSet],
|
||||||
device: Device,
|
device: Device,
|
||||||
deviceKey: String = "reg",
|
deviceKey: String = "reg",
|
||||||
concurrency: Int = 0,
|
concurrency: Int = 0,
|
||||||
@ -98,7 +103,7 @@ object TLRegisterNode
|
|||||||
abstract class TLRegisterRouterBase(devname: String, devcompat: Seq[String], val address: AddressSet, interrupts: Int, concurrency: Int, beatBytes: Int, undefZero: Boolean, executable: Boolean)(implicit p: Parameters) extends LazyModule
|
abstract class TLRegisterRouterBase(devname: String, devcompat: Seq[String], val address: AddressSet, interrupts: Int, concurrency: Int, beatBytes: Int, undefZero: Boolean, executable: Boolean)(implicit p: Parameters) extends LazyModule
|
||||||
{
|
{
|
||||||
val device = new SimpleDevice(devname, devcompat)
|
val device = new SimpleDevice(devname, devcompat)
|
||||||
val node = TLRegisterNode(address, device, "reg", concurrency, beatBytes, undefZero, executable)
|
val node = TLRegisterNode(Seq(address), device, "reg", concurrency, beatBytes, undefZero, executable)
|
||||||
val intnode = IntSourceNode(IntSourcePortSimple(num = interrupts, resources = Seq(Resource(device, "int"))))
|
val intnode = IntSourceNode(IntSourcePortSimple(num = interrupts, resources = Seq(Resource(device, "int"))))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user