2014-09-13 00:31:38 +02:00
|
|
|
// See LICENSE for license details.
|
|
|
|
|
2012-09-27 21:59:45 +02:00
|
|
|
package uncore
|
2012-04-03 21:03:05 +02:00
|
|
|
import Chisel._
|
2015-03-24 10:06:53 +01:00
|
|
|
import scala.reflect._
|
|
|
|
import scala.reflect.runtime.universe._
|
2012-04-03 21:03:05 +02:00
|
|
|
|
2014-08-08 21:21:57 +02:00
|
|
|
case object NReleaseTransactors extends Field[Int]
|
2014-12-16 04:23:13 +01:00
|
|
|
case object NProbeTransactors extends Field[Int]
|
2014-08-08 21:21:57 +02:00
|
|
|
case object NAcquireTransactors extends Field[Int]
|
2014-12-16 04:23:13 +01:00
|
|
|
case object NIncoherentClients extends Field[Int]
|
|
|
|
case object NCoherentClients extends Field[Int]
|
2015-03-01 02:02:13 +01:00
|
|
|
case object L2CoherencePolicy extends Field[CoherencePolicy]
|
2014-04-27 04:11:36 +02:00
|
|
|
|
2015-03-01 02:02:13 +01:00
|
|
|
trait CoherenceAgentParameters extends UsesParameters {
|
2014-11-12 21:55:07 +01:00
|
|
|
val nReleaseTransactors = 1
|
2014-08-12 03:35:49 +02:00
|
|
|
val nAcquireTransactors = params(NAcquireTransactors)
|
|
|
|
val nTransactors = nReleaseTransactors + nAcquireTransactors
|
2014-12-16 04:23:13 +01:00
|
|
|
val nCoherentClients = params(NCoherentClients)
|
|
|
|
val nIncoherentClients = params(NIncoherentClients)
|
|
|
|
val nClients = nCoherentClients + nIncoherentClients
|
2015-03-01 02:02:13 +01:00
|
|
|
def outerTLParams = params.alterPartial({ case TLId => params(OuterTLId)})
|
|
|
|
val outerDataBeats = outerTLParams(TLDataBeats)
|
|
|
|
val outerDataBits = outerTLParams(TLDataBits)
|
2015-03-11 23:43:41 +01:00
|
|
|
val outerBeatAddrBits = log2Up(outerDataBeats)
|
|
|
|
val outerByteAddrBits = log2Up(outerDataBits/8)
|
2015-03-01 02:02:13 +01:00
|
|
|
def innerTLParams = params.alterPartial({case TLId => params(InnerTLId)})
|
|
|
|
val innerDataBeats = innerTLParams(TLDataBeats)
|
|
|
|
val innerDataBits = innerTLParams(TLDataBits)
|
|
|
|
val innerBeatAddrBits = log2Up(innerDataBeats)
|
|
|
|
val innerByteAddrBits = log2Up(innerDataBits/8)
|
|
|
|
require(outerDataBeats == innerDataBeats) //TODO: must fix all xact_data Vecs to remove this requirement
|
2014-08-12 03:35:49 +02:00
|
|
|
}
|
2015-03-01 02:02:13 +01:00
|
|
|
abstract class CoherenceAgentBundle extends Bundle with CoherenceAgentParameters
|
|
|
|
abstract class CoherenceAgentModule extends Module with CoherenceAgentParameters
|
|
|
|
|
|
|
|
trait HasCoherenceAgentWiringHelpers {
|
|
|
|
def doOutputArbitration[T <: Data : ClassTag](
|
|
|
|
out: DecoupledIO[T],
|
|
|
|
ins: Seq[DecoupledIO[T]]) {
|
|
|
|
val arb = Module(new RRArbiter(out.bits.clone, ins.size))
|
|
|
|
out <> arb.io.out
|
|
|
|
arb.io.in zip ins map { case (a, in) => a <> in }
|
2014-12-07 12:02:20 +01:00
|
|
|
}
|
|
|
|
|
2015-03-01 02:02:13 +01:00
|
|
|
def doOutputArbitration[T <: HasTileLinkData : ClassTag, S <: LogicalNetworkIO[T] : ClassTag](
|
|
|
|
out: DecoupledIO[S],
|
|
|
|
ins: Seq[DecoupledIO[S]]) {
|
|
|
|
def lock(o: LogicalNetworkIO[T]) = o.payload.hasMultibeatData()
|
|
|
|
val arb = Module(new LockingRRArbiter(
|
|
|
|
out.bits.clone,
|
|
|
|
ins.size,
|
|
|
|
out.bits.payload.tlDataBeats,
|
|
|
|
lock _))
|
|
|
|
out <> arb.io.out
|
|
|
|
arb.io.in zip ins map { case (a, in) => a <> in }
|
2014-12-12 10:11:08 +01:00
|
|
|
}
|
2013-01-17 08:57:35 +01:00
|
|
|
|
2015-03-01 02:02:13 +01:00
|
|
|
def doInputRouting[T <: HasL2Id](in: ValidIO[T], outs: Seq[ValidIO[T]]) {
|
|
|
|
val idx = in.bits.id
|
|
|
|
outs.map(_.bits := in.bits)
|
|
|
|
outs.zipWithIndex.map { case (o,i) => o.valid := in.valid && idx === UInt(i) }
|
2013-01-17 08:57:35 +01:00
|
|
|
}
|
2014-12-07 12:02:20 +01:00
|
|
|
|
2015-03-01 02:02:13 +01:00
|
|
|
def doInputRouting[T <: HasManagerTransactionId](
|
|
|
|
in: DecoupledIO[LogicalNetworkIO[T]],
|
|
|
|
outs: Seq[DecoupledIO[LogicalNetworkIO[T]]]) {
|
|
|
|
val idx = in.bits.payload.manager_xact_id
|
|
|
|
outs.map(_.bits := in.bits)
|
|
|
|
outs.zipWithIndex.map { case (o,i) => o.valid := in.valid && idx === UInt(i) }
|
|
|
|
in.ready := Vec(outs.map(_.ready)).read(idx)
|
2014-11-12 21:55:07 +01:00
|
|
|
}
|
2013-01-17 08:57:35 +01:00
|
|
|
}
|
|
|
|
|
2015-03-01 02:02:13 +01:00
|
|
|
trait HasInnerTLIO extends CoherenceAgentBundle {
|
|
|
|
val inner = Bundle(new TileLinkIO)(innerTLParams).flip
|
2015-03-13 00:22:14 +01:00
|
|
|
val incoherent = Vec.fill(nCoherentClients){Bool()}.asInput
|
2015-03-01 02:02:13 +01:00
|
|
|
def iacq(dummy: Int = 0) = inner.acquire.bits.payload
|
|
|
|
def iprb(dummy: Int = 0) = inner.probe.bits.payload
|
|
|
|
def irel(dummy: Int = 0) = inner.release.bits.payload
|
|
|
|
def ignt(dummy: Int = 0) = inner.grant.bits.payload
|
|
|
|
def ifin(dummy: Int = 0) = inner.finish.bits.payload
|
2013-01-29 01:39:45 +01:00
|
|
|
}
|
|
|
|
|
2015-03-01 02:02:13 +01:00
|
|
|
trait HasUncachedOuterTLIO extends CoherenceAgentBundle {
|
2015-03-24 10:06:53 +01:00
|
|
|
val outer = Bundle(new HeaderlessUncachedTileLinkIO)(outerTLParams)
|
|
|
|
def oacq(dummy: Int = 0) = outer.acquire.bits
|
|
|
|
def ognt(dummy: Int = 0) = outer.grant.bits
|
2013-01-29 01:39:45 +01:00
|
|
|
}
|
2013-01-17 08:57:35 +01:00
|
|
|
|
2015-03-01 02:02:13 +01:00
|
|
|
trait HasCachedOuterTLIO extends CoherenceAgentBundle {
|
2015-03-24 10:06:53 +01:00
|
|
|
val outer = Bundle(new HeaderlessTileLinkIO)(outerTLParams)
|
|
|
|
def oacq(dummy: Int = 0) = outer.acquire.bits
|
|
|
|
def oprb(dummy: Int = 0) = outer.probe.bits
|
|
|
|
def orel(dummy: Int = 0) = outer.release.bits
|
|
|
|
def ognt(dummy: Int = 0) = outer.grant.bits
|
2015-03-01 02:02:13 +01:00
|
|
|
}
|
2014-03-29 18:53:49 +01:00
|
|
|
|
2015-03-01 02:02:13 +01:00
|
|
|
class ManagerTLIO extends HasInnerTLIO with HasUncachedOuterTLIO
|
2013-01-17 08:57:35 +01:00
|
|
|
|
2015-03-01 02:02:13 +01:00
|
|
|
abstract class CoherenceAgent extends CoherenceAgentModule {
|
|
|
|
def innerTL: TileLinkIO
|
2015-03-24 10:06:53 +01:00
|
|
|
def outerTL: HeaderlessTileLinkIO
|
2015-03-01 02:02:13 +01:00
|
|
|
def incoherent: Vec[Bool]
|
|
|
|
}
|
2014-12-12 10:11:08 +01:00
|
|
|
|
2015-03-01 02:02:13 +01:00
|
|
|
abstract class ManagerCoherenceAgent extends CoherenceAgent
|
|
|
|
with HasCoherenceAgentWiringHelpers {
|
|
|
|
val io = new ManagerTLIO
|
|
|
|
def innerTL = io.inner
|
|
|
|
def outerTL = TileLinkIOWrapper(io.outer, outerTLParams)
|
|
|
|
def incoherent = io.incoherent
|
|
|
|
}
|
2014-03-29 18:53:49 +01:00
|
|
|
|
2015-03-01 02:02:13 +01:00
|
|
|
class HierarchicalTLIO extends HasInnerTLIO with HasCachedOuterTLIO
|
2014-03-29 18:53:49 +01:00
|
|
|
|
2015-03-01 02:02:13 +01:00
|
|
|
abstract class HierarchicalCoherenceAgent extends CoherenceAgent {
|
|
|
|
val io = new HierarchicalTLIO
|
|
|
|
def innerTL = io.inner
|
|
|
|
def outerTL = io.outer
|
|
|
|
def incoherent = io.incoherent
|
|
|
|
}
|
2014-03-29 18:53:49 +01:00
|
|
|
|
2015-03-01 02:02:13 +01:00
|
|
|
trait HasTrackerConflictIO extends Bundle {
|
|
|
|
val has_acquire_conflict = Bool(OUTPUT)
|
|
|
|
val has_acquire_match = Bool(OUTPUT)
|
|
|
|
val has_release_match = Bool(OUTPUT)
|
|
|
|
}
|
2014-03-29 18:53:49 +01:00
|
|
|
|
2015-03-01 02:02:13 +01:00
|
|
|
class ManagerXactTrackerIO extends ManagerTLIO with HasTrackerConflictIO
|
|
|
|
class HierarchicalXactTrackerIO extends HierarchicalTLIO with HasTrackerConflictIO
|
2013-01-17 08:57:35 +01:00
|
|
|
|
2015-03-24 10:06:53 +01:00
|
|
|
abstract class XactTracker extends CoherenceAgentModule
|
|
|
|
with HasDataBeatCounters {
|
|
|
|
def addPendingBitWhenBeat[T <: HasBeat](inc: Bool, in: T): UInt = Fill(in.tlDataBeats, inc) & UIntToOH(in.addr_beat)
|
|
|
|
def dropPendingBitWhenBeat[T <: HasBeat](dec: Bool, in: T): UInt = ~Fill(in.tlDataBeats, dec) | ~UIntToOH(in.addr_beat)
|
|
|
|
|
|
|
|
def addPendingBitWhenBeatHasData[T <: Data : TypeTag](in: DecoupledIO[T]): UInt = {
|
|
|
|
in.bits match {
|
|
|
|
case p: HasBeat if typeTag[T].tpe <:< typeTag[HasBeat].tpe =>
|
|
|
|
addPendingBitWhenBeat(in.fire() && p.hasData(), p)
|
|
|
|
case ln: LNAcquire if typeTag[T].tpe <:< typeTag[LNAcquire].tpe =>
|
|
|
|
addPendingBitWhenBeat(in.fire() && ln.payload.hasData(), ln.payload)
|
|
|
|
case ln: LNRelease if typeTag[T].tpe <:< typeTag[LNRelease].tpe =>
|
|
|
|
addPendingBitWhenBeat(in.fire() && ln.payload.hasData(), ln.payload)
|
|
|
|
case ln: LNGrant if typeTag[T].tpe <:< typeTag[LNGrant].tpe =>
|
|
|
|
addPendingBitWhenBeat(in.fire() && ln.payload.hasData(), ln.payload)
|
|
|
|
case _ => { require(false, "Don't know how track beats of " + typeTag[T].tpe); UInt(0) }
|
|
|
|
}
|
2014-12-07 12:02:20 +01:00
|
|
|
}
|
2015-03-18 01:51:00 +01:00
|
|
|
|
2015-03-24 10:06:53 +01:00
|
|
|
def addPendingBitWhenBeatIsGetOrAtomic(in: DecoupledIO[LogicalNetworkIO[Acquire]]): UInt = {
|
|
|
|
val a = in.bits.payload
|
|
|
|
val isGetOrAtomic = a.isBuiltInType() &&
|
|
|
|
(Vec(Acquire.getType, Acquire.getBlockType, Acquire.putAtomicType).contains(a.a_type))
|
|
|
|
addPendingBitWhenBeat(in.fire() && isGetOrAtomic, in.bits.payload)
|
2015-03-18 01:51:00 +01:00
|
|
|
}
|
2015-03-18 04:28:06 +01:00
|
|
|
|
2015-03-24 10:06:53 +01:00
|
|
|
def dropPendingBitWhenBeatHasData[T <: Data : TypeTag](in: DecoupledIO[T]): UInt = {
|
|
|
|
in.bits match {
|
|
|
|
case p: HasBeat if typeTag[T].tpe <:< typeTag[HasBeat].tpe =>
|
|
|
|
dropPendingBitWhenBeat(in.fire() && p.hasData(), p)
|
|
|
|
case ln: LNAcquire if typeTag[T].tpe <:< typeTag[LNAcquire].tpe =>
|
|
|
|
dropPendingBitWhenBeat(in.fire() && ln.payload.hasData(), ln.payload)
|
|
|
|
case ln: LNRelease if typeTag[T].tpe <:< typeTag[LNRelease].tpe =>
|
|
|
|
dropPendingBitWhenBeat(in.fire() && ln.payload.hasData(), ln.payload)
|
|
|
|
case ln: LNGrant if typeTag[T].tpe <:< typeTag[LNGrant].tpe =>
|
|
|
|
dropPendingBitWhenBeat(in.fire() && ln.payload.hasData(), ln.payload)
|
|
|
|
case _ => { require(false, "Don't know how track beats of " + typeTag[T].tpe); UInt(0) }
|
|
|
|
}
|
2015-03-19 01:55:05 +01:00
|
|
|
}
|
|
|
|
|
2015-03-24 10:06:53 +01:00
|
|
|
def dropPendingBitAtDest(in: DecoupledIO[LogicalNetworkIO[Probe]]): UInt = {
|
|
|
|
~Fill(nCoherentClients, in.fire()) | ~UIntToOH(in.bits.header.dst)
|
2015-03-18 04:28:06 +01:00
|
|
|
}
|
2013-01-17 08:57:35 +01:00
|
|
|
}
|