L2Prefetcher.scala 3.6 KB
Newer Older
1 2 3 4 5 6 7 8
package xiangshan.cache.prefetch

import chisel3._
import chisel3.util._
import freechips.rocketchip.tilelink.ClientMetadata
import xiangshan._
import xiangshan.cache._
import utils._
9
import chisel3.ExcitingUtils._
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

import chipsalliance.rocketchip.config.Parameters
import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp, IdRange}
import freechips.rocketchip.tilelink.{TLClientNode, TLClientParameters,
  TLMasterParameters, TLMasterPortParameters, TLArbiter,
  TLEdgeOut, TLBundleA, TLBundleD,
  ClientStates, ClientMetadata, TLHints
}

case class L2PrefetcherParameters(
  enable: Boolean,
  _type: String,
  streamParams: StreamPrefetchParameters
) {
  def nEntries: Int = streamParams.streamCnt * streamParams.streamSize
}

class L2Prefetcher()(implicit p: Parameters) extends LazyModule with HasPrefetchParameters {
  val clientParameters = TLMasterPortParameters.v1(
    Seq(TLMasterParameters.v1(
      name = "l2prefetcher",
31
      sourceId = IdRange(0, l2PrefetcherParameters.nEntries)
32 33 34 35 36 37 38 39 40
    ))
  )

  val clientNode = TLClientNode(Seq(clientParameters))

  lazy val module = new L2PrefetcherImp(this)
}

// prefetch DCache lines in L2 using StreamPrefetch
41
class L2PrefetcherImp(outer: L2Prefetcher) extends LazyModuleImp(outer) with HasPrefetchParameters with HasXSLog {  
42 43 44 45 46 47 48 49 50 51
  val io = IO(new Bundle {
    val in = Flipped(DecoupledIO(new MissReq))
    // prefetch
    // val mem_acquire = Decoupled(new TLBundleA(edge.bundle))
    // val mem_grant   = Flipped(Decoupled(new TLBundleD(edge.bundle)))
    // val mem_finish  = Decoupled(new TLBundleE(edge.bundle))
  })

  val (bus, edge) = outer.clientNode.out.head
  if (l2PrefetcherParameters.enable && l2PrefetcherParameters._type == "stream") {
52 53
    val streamParams = l2PrefetcherParameters.streamParams
    val dPrefetch = Module(new StreamPrefetch(streamParams))
54 55 56 57 58
    dPrefetch.io.train.valid := io.in.fire()
    dPrefetch.io.train.bits.addr := io.in.bits.addr
    dPrefetch.io.train.bits.write := MemoryOpConstants.isWrite(io.in.bits.cmd)
    dPrefetch.io.train.bits.miss := true.B
    io.in.ready := true.B
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82

    bus.a.valid := dPrefetch.io.req.valid
    bus.a.bits := DontCare
    bus.a.bits := edge.Hint(
      fromSource = dPrefetch.io.req.bits.id,
      toAddress = dPrefetch.io.req.bits.addr,
      lgSize = log2Up(streamParams.blockBytes).U,
      param = Mux(dPrefetch.io.req.bits.write, TLHints.PREFETCH_WRITE, TLHints.PREFETCH_READ) // TODO
    )._2
    dPrefetch.io.req.ready := bus.a.ready

    bus.b.ready := true.B

    bus.c.valid := false.B
    bus.c.bits := DontCare

    dPrefetch.io.resp.valid := bus.d.valid
    dPrefetch.io.resp.bits.id := bus.d.bits.source(streamParams.totalWidth - 1, 0)
    bus.d.ready := dPrefetch.io.resp.ready

    bus.e.valid := false.B
    bus.e.bits := DontCare
    dPrefetch.io.finish.ready := true.B

83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
    if (!env.FPGAPlatform) {
      ExcitingUtils.addSource(bus.a.fire(), "perfCntL2PrefetchReqCnt", Perf)
      def idWidth = log2Up(l2PrefetcherParameters.nEntries)
      (0 until l2PrefetcherParameters.nEntries).foreach(i =>
        ExcitingUtils.addSource(
          BoolStopWatch(
            start = bus.a.fire() && dPrefetch.io.req.bits.id(streamParams.totalWidth - 1, 0) === i.U,
            stop = bus.d.fire() && bus.d.bits.source(streamParams.totalWidth - 1, 0) === i.U,
            startHighPriority = true
          ),
          "perfCntL2PrefetchPenaltyEntry" + Integer.toString(i, 10),
          Perf
        )
      )
    }

99 100 101 102 103 104 105 106 107 108 109 110
  } else {
    bus.a.valid := false.B
    bus.a.bits := DontCare
    bus.b.ready := true.B
    bus.c.valid := false.B
    bus.c.bits := DontCare
    bus.d.ready := true.B
    bus.e.valid := false.B
    bus.e.bits := DontCare
  }
}