// See LICENSE for license details. package uncore.agents import Chisel._ import cde.{Parameters, Field} import junctions._ import uncore.tilelink._ import uncore.converters._ import uncore.coherence._ import uncore.util._ case object NReleaseTransactors extends Field[Int] case object NProbeTransactors extends Field[Int] case object NAcquireTransactors extends Field[Int] trait HasCoherenceAgentParameters { implicit val p: Parameters val nReleaseTransactors = 1 val nAcquireTransactors = p(NAcquireTransactors) val nTransactors = nReleaseTransactors + nAcquireTransactors val blockAddrBits = p(PAddrBits) - p(CacheBlockOffsetBits) val outerTLId = p(OuterTLId) val outerTLParams = p(TLKey(outerTLId)) val outerDataBeats = outerTLParams.dataBeats val outerDataBits = outerTLParams.dataBitsPerBeat val outerBeatAddrBits = log2Up(outerDataBeats) val outerByteAddrBits = log2Up(outerDataBits/8) val outerWriteMaskBits = outerTLParams.writeMaskBits val innerTLId = p(InnerTLId) val innerTLParams = p(TLKey(innerTLId)) val innerDataBeats = innerTLParams.dataBeats val innerDataBits = innerTLParams.dataBitsPerBeat val innerWriteMaskBits = innerTLParams.writeMaskBits val innerBeatAddrBits = log2Up(innerDataBeats) val innerByteAddrBits = log2Up(innerDataBits/8) val innerNCachingClients = innerTLParams.nCachingClients val maxManagerXacts = innerTLParams.maxManagerXacts require(outerDataBeats == innerDataBeats) //TODO: fix all xact_data Vecs to remove this requirement } abstract class CoherenceAgentModule(implicit val p: Parameters) extends Module with HasCoherenceAgentParameters abstract class CoherenceAgentBundle(implicit val p: Parameters) extends junctions.ParameterizedBundle()(p) with HasCoherenceAgentParameters trait HasCoherenceAgentWiringHelpers { def doOutputArbitration[T <: TileLinkChannel]( out: DecoupledIO[T], ins: Seq[DecoupledIO[T]]) { def lock(o: T) = o.hasMultibeatData() val arb = Module(new LockingRRArbiter(out.bits, ins.size, out.bits.tlDataBeats, Some(lock _))) out <> arb.io.out arb.io.in <> ins } def doInputRouting[T <: Bundle with HasManagerTransactionId]( in: DecoupledIO[T], outs: Seq[DecoupledIO[T]]) { val idx = in.bits.manager_xact_id outs.map(_.bits := in.bits) outs.zipWithIndex.map { case (o,i) => o.valid := in.valid && idx === UInt(i) } in.ready := outs.map(_.ready).apply(idx) } /** Broadcasts valid messages on this channel to all trackers, * but includes logic to allocate a new tracker in the case where * no previously allocated tracker matches the new req's addr. * * When a match is reported, if ready is high the new transaction * is merged; when ready is low the transaction is being blocked. * When no match is reported, any high idles are presumed to be * from trackers that are available for allocation, and one is * assigned via alloc based on priority; if no idles are high then * all trackers are busy with other transactions. If idle is high * but ready is low, the tracker will be allocated but does not * have sufficient buffering for the data. */ def doInputRoutingWithAllocation[T <: TileLinkChannel with HasTileLinkData]( in: DecoupledIO[T], outs: Seq[DecoupledIO[T]], allocs: Seq[TrackerAllocation], dataOverrides: Option[Seq[UInt]] = None, allocOverride: Option[Bool] = None, matchOverride: Option[Bool] = None) { val ready_bits = outs.map(_.ready).asUInt val can_alloc_bits = allocs.map(_.can).asUInt val should_alloc_bits = PriorityEncoderOH(can_alloc_bits) val match_bits = allocs.map(_.matches).asUInt val no_matches = !match_bits.orR val alloc_ok = allocOverride.getOrElse(Bool(true)) val match_ok = matchOverride.getOrElse(Bool(true)) in.ready := (Mux(no_matches, can_alloc_bits, match_bits) & ready_bits).orR && alloc_ok && match_ok outs.zip(allocs).zipWithIndex.foreach { case((out, alloc), i) => out.valid := in.valid && match_ok && alloc_ok out.bits := in.bits dataOverrides foreach { d => out.bits.data := d(i) } alloc.should := should_alloc_bits(i) && no_matches && alloc_ok } } } trait HasInnerTLIO extends HasCoherenceAgentParameters { val inner = new ManagerTileLinkIO()(p.alterPartial({case TLId => p(InnerTLId)})) val incoherent = Vec(inner.tlNCachingClients, Bool()).asInput def iacq(dummy: Int = 0) = inner.acquire.bits def iprb(dummy: Int = 0) = inner.probe.bits def irel(dummy: Int = 0) = inner.release.bits def ignt(dummy: Int = 0) = inner.grant.bits def ifin(dummy: Int = 0) = inner.finish.bits } trait HasUncachedOuterTLIO extends HasCoherenceAgentParameters { val outer = new ClientUncachedTileLinkIO()(p.alterPartial({case TLId => p(OuterTLId)})) def oacq(dummy: Int = 0) = outer.acquire.bits def ognt(dummy: Int = 0) = outer.grant.bits } trait HasCachedOuterTLIO extends HasCoherenceAgentParameters { val outer = new ClientTileLinkIO()(p.alterPartial({case TLId => p(OuterTLId)})) 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 } class ManagerTLIO(implicit p: Parameters) extends CoherenceAgentBundle()(p) with HasInnerTLIO with HasUncachedOuterTLIO abstract class CoherenceAgent(implicit p: Parameters) extends CoherenceAgentModule()(p) { def innerTL: ManagerTileLinkIO def outerTL: ClientTileLinkIO def incoherent: Vec[Bool] } abstract class ManagerCoherenceAgent(implicit p: Parameters) extends CoherenceAgent()(p) with HasCoherenceAgentWiringHelpers { val io = new ManagerTLIO def innerTL = io.inner def outerTL = TileLinkIOWrapper(io.outer)(p.alterPartial({case TLId => p(OuterTLId)})) def incoherent = io.incoherent } class HierarchicalTLIO(implicit p: Parameters) extends CoherenceAgentBundle()(p) with HasInnerTLIO with HasCachedOuterTLIO abstract class HierarchicalCoherenceAgent(implicit p: Parameters) extends CoherenceAgent()(p) with HasCoherenceAgentWiringHelpers { val io = new HierarchicalTLIO def innerTL = io.inner def outerTL = io.outer def incoherent = io.incoherent // TODO: Remove this function (and all its calls) when we support probing the L2 def disconnectOuterProbeAndFinish() { io.outer.probe.ready := Bool(false) io.outer.finish.valid := Bool(false) assert(!io.outer.probe.valid, "L2 agent got illegal probe") } }