Merge pull request #622 from ucb-bar/priv-1.10
Various priv-1.10 changes
This commit is contained in:
		
							
								
								
									
										16
									
								
								README_TRAVIS.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								README_TRAVIS.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
			
		||||
# Travis Notes for Administrators
 | 
			
		||||
 | 
			
		||||
Administrators: Are PRs taking > 1 hr to run through Travis? If you look at the Travis logs is it building `riscv-tools`?
 | 
			
		||||
 | 
			
		||||
This is because someone committed a PR to `master` which bumped `riscv-tools` and the master cache needs to be updated.
 | 
			
		||||
This is the procedure to follow to get 
 | 
			
		||||
things fast again. We don't generally build on merges to master, just PRs.
 | 
			
		||||
 | 
			
		||||
1. Wait for your PR that you want to merge to go green. This will take a long time.
 | 
			
		||||
2. On Travis, click `More Options -> Caches` on the upper right.
 | 
			
		||||
3. Click `Delete all Repository Caches`. 
 | 
			
		||||
4. Click `More Options->Settings`
 | 
			
		||||
5. On the `General Settings` section, switch the `Build Branch Updates` toggle to `ON`.
 | 
			
		||||
6. perform your PR's merge to master. This will cause the master cache to build `riscv-tools`.
 | 
			
		||||
7. Once the merge commit goes green on Jenkins, switch the `Build Branch Updates` toggle to `OFF`.
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										2
									
								
								chisel3
									
									
									
									
									
								
							
							
								
								
								
								
								
							
						
						
									
										2
									
								
								chisel3
									
									
									
									
									
								
							 Submodule chisel3 updated: 3e6ef13ff5...8e4ddc62db
									
								
							 Submodule riscv-tools updated: 4f430b184e...89d487023c
									
								
							@@ -21,9 +21,7 @@ class MStatus extends Bundle {
 | 
			
		||||
  val dprv = UInt(width = PRV.SZ) // effective privilege for data accesses
 | 
			
		||||
  val prv = UInt(width = PRV.SZ) // not truly part of mstatus, but convenient
 | 
			
		||||
  val sd = Bool()
 | 
			
		||||
  val zero2 = UInt(width = 27)
 | 
			
		||||
  val sxl = UInt(width = 2)
 | 
			
		||||
  val uxl = UInt(width = 2)
 | 
			
		||||
  val zero2 = UInt(width = 31)
 | 
			
		||||
  val sd_rv32 = Bool()
 | 
			
		||||
  val zero1 = UInt(width = 8)
 | 
			
		||||
  val tsr = Bool()
 | 
			
		||||
@@ -67,7 +65,12 @@ class DCSR extends Bundle {
 | 
			
		||||
  val prv = UInt(width = PRV.SZ)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class MIP extends Bundle {
 | 
			
		||||
class MIP(implicit p: Parameters) extends CoreBundle()(p)
 | 
			
		||||
    with HasRocketCoreParameters {
 | 
			
		||||
  val lip = Vec(coreParams.nLocalInterrupts, Bool())
 | 
			
		||||
  val zero2 = Bool()
 | 
			
		||||
  val debug = Bool() // keep in sync with CSR.debugIntCause
 | 
			
		||||
  val zero1 = Bool()
 | 
			
		||||
  val rocc = Bool()
 | 
			
		||||
  val meip = Bool()
 | 
			
		||||
  val heip = Bool()
 | 
			
		||||
@@ -121,10 +124,11 @@ object CSR
 | 
			
		||||
  def R = UInt(5,SZ)
 | 
			
		||||
 | 
			
		||||
  val ADDRSZ = 12
 | 
			
		||||
  def debugIntCause = new MIP().getWidth
 | 
			
		||||
  def debugIntCause = 14 // keep in sync with MIP.debug
 | 
			
		||||
  def debugTriggerCause = {
 | 
			
		||||
    require(debugIntCause >= Causes.all.max)
 | 
			
		||||
    debugIntCause
 | 
			
		||||
    val res = debugIntCause
 | 
			
		||||
    require(!(Causes.all contains res))
 | 
			
		||||
    res
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  val firstCtr = CSRs.cycle
 | 
			
		||||
@@ -208,14 +212,24 @@ class CSRFile(perfEventSets: EventSets = new EventSets(Seq()))(implicit p: Param
 | 
			
		||||
  val reg_dcsr = Reg(init=reset_dcsr)
 | 
			
		||||
 | 
			
		||||
  val (supported_interrupts, delegable_interrupts) = {
 | 
			
		||||
    val sup = Wire(init=new MIP().fromBits(0))
 | 
			
		||||
    val sup = Wire(new MIP)
 | 
			
		||||
    sup.usip := false
 | 
			
		||||
    sup.ssip := Bool(usingVM)
 | 
			
		||||
    sup.hsip := false
 | 
			
		||||
    sup.msip := true
 | 
			
		||||
    sup.utip := false
 | 
			
		||||
    sup.stip := Bool(usingVM)
 | 
			
		||||
    sup.htip := false
 | 
			
		||||
    sup.mtip := true
 | 
			
		||||
    sup.meip := true
 | 
			
		||||
    sup.ueip := false
 | 
			
		||||
    sup.seip := Bool(usingVM)
 | 
			
		||||
    sup.heip := false
 | 
			
		||||
    sup.meip := true
 | 
			
		||||
    sup.rocc := usingRoCC
 | 
			
		||||
    sup.zero1 := false
 | 
			
		||||
    sup.debug := false
 | 
			
		||||
    sup.zero2 := false
 | 
			
		||||
    sup.lip foreach { _ := true }
 | 
			
		||||
 | 
			
		||||
    val del = Wire(init=sup)
 | 
			
		||||
    del.msip := false
 | 
			
		||||
@@ -226,10 +240,10 @@ class CSRFile(perfEventSets: EventSets = new EventSets(Seq()))(implicit p: Param
 | 
			
		||||
  }
 | 
			
		||||
  val delegable_exceptions = UInt(Seq(
 | 
			
		||||
    Causes.misaligned_fetch,
 | 
			
		||||
    Causes.fault_fetch,
 | 
			
		||||
    Causes.fetch_page_fault,
 | 
			
		||||
    Causes.breakpoint,
 | 
			
		||||
    Causes.fault_load,
 | 
			
		||||
    Causes.fault_store,
 | 
			
		||||
    Causes.load_page_fault,
 | 
			
		||||
    Causes.store_page_fault,
 | 
			
		||||
    Causes.user_ecall).map(1 << _).sum)
 | 
			
		||||
 | 
			
		||||
  val reg_debug = Reg(init=Bool(false))
 | 
			
		||||
@@ -277,6 +291,8 @@ class CSRFile(perfEventSets: EventSets = new EventSets(Seq()))(implicit p: Param
 | 
			
		||||
  val hpm_mask = reg_mcounteren & Mux((!usingVM).B || reg_mstatus.prv === PRV.S, delegable_counters.U, reg_scounteren)
 | 
			
		||||
 | 
			
		||||
  val mip = Wire(init=reg_mip)
 | 
			
		||||
  // seip is the OR of reg_mip.seip and the actual line from the PLIC
 | 
			
		||||
  io.interrupts.seip.foreach { mip.seip := reg_mip.seip || RegNext(_) }
 | 
			
		||||
  mip.rocc := io.rocc_interrupt
 | 
			
		||||
  val read_mip = mip.asUInt & supported_interrupts
 | 
			
		||||
 | 
			
		||||
@@ -363,7 +379,6 @@ class CSRFile(perfEventSets: EventSets = new EventSets(Seq()))(implicit p: Param
 | 
			
		||||
    val read_sip = read_mip & reg_mideleg
 | 
			
		||||
    val read_sstatus = Wire(init = 0.U.asTypeOf(new MStatus))
 | 
			
		||||
    read_sstatus.sd := io.status.sd
 | 
			
		||||
    read_sstatus.uxl := io.status.uxl
 | 
			
		||||
    read_sstatus.sd_rv32 := io.status.sd_rv32
 | 
			
		||||
    read_sstatus.mxr := io.status.mxr
 | 
			
		||||
    read_sstatus.sum := io.status.sum
 | 
			
		||||
@@ -417,8 +432,7 @@ class CSRFile(perfEventSets: EventSets = new EventSets(Seq()))(implicit p: Param
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  val decoded_addr = read_mapping map { case (k, v) => k -> (io.rw.addr === k) }
 | 
			
		||||
  val wdata = (Mux(io.rw.cmd.isOneOf(CSR.S, CSR.C), io.rw.rdata, UInt(0)) | io.rw.wdata) &
 | 
			
		||||
              ~Mux(io.rw.cmd === CSR.C, io.rw.wdata, UInt(0))
 | 
			
		||||
  val wdata = readModifyWriteCSR(io.rw.cmd, io.rw.rdata, io.rw.wdata)
 | 
			
		||||
 | 
			
		||||
  val system_insn = io.rw.cmd === CSR.I
 | 
			
		||||
  val opcode = UInt(1) << io.rw.addr(2,0)
 | 
			
		||||
@@ -465,8 +479,6 @@ class CSRFile(perfEventSets: EventSets = new EventSets(Seq()))(implicit p: Param
 | 
			
		||||
  io.status.sd := io.status.fs.andR || io.status.xs.andR
 | 
			
		||||
  io.status.debug := reg_debug
 | 
			
		||||
  io.status.isa := reg_misa
 | 
			
		||||
  io.status.uxl := (if (usingUser) log2Ceil(xLen) - 4 else 0)
 | 
			
		||||
  io.status.sxl := (if (usingVM) log2Ceil(xLen) - 4 else 0)
 | 
			
		||||
  io.status.dprv := Reg(next = Mux(reg_mstatus.mprv && !reg_debug, reg_mstatus.mpp, reg_mstatus.prv))
 | 
			
		||||
  if (xLen == 32)
 | 
			
		||||
    io.status.sd_rv32 := io.status.sd
 | 
			
		||||
@@ -488,7 +500,9 @@ class CSRFile(perfEventSets: EventSets = new EventSets(Seq()))(implicit p: Param
 | 
			
		||||
 | 
			
		||||
    val write_badaddr = cause isOneOf (Causes.breakpoint,
 | 
			
		||||
      Causes.misaligned_load, Causes.misaligned_store, Causes.misaligned_fetch,
 | 
			
		||||
      Causes.fault_load, Causes.fault_store, Causes.fault_fetch)
 | 
			
		||||
      Causes.load_access, Causes.store_access, Causes.fetch_access,
 | 
			
		||||
      Causes.load_page_fault, Causes.store_page_fault, Causes.fetch_page_fault
 | 
			
		||||
      )
 | 
			
		||||
 | 
			
		||||
    when (trapToDebug) {
 | 
			
		||||
      reg_debug := true
 | 
			
		||||
@@ -570,15 +584,20 @@ class CSRFile(perfEventSets: EventSets = new EventSets(Seq()))(implicit p: Param
 | 
			
		||||
      if (usingRoCC) reg_mstatus.xs := Fill(2, new_mstatus.xs.orR)
 | 
			
		||||
    }
 | 
			
		||||
    when (decoded_addr(CSRs.misa)) {
 | 
			
		||||
      val mask = UInt(isaStringToMask(isaMaskString))
 | 
			
		||||
      val mask = UInt(isaStringToMask(isaMaskString), xLen)
 | 
			
		||||
      val f = wdata('f' - 'a')
 | 
			
		||||
      reg_misa := ~(~wdata | (!f << ('d' - 'a'))) & mask | reg_misa & ~mask
 | 
			
		||||
    }
 | 
			
		||||
    when (decoded_addr(CSRs.mip)) {
 | 
			
		||||
      val new_mip = new MIP().fromBits(wdata)
 | 
			
		||||
      // MIP should be modified based on the value in reg_mip, not the value
 | 
			
		||||
      // in read_mip, since read_mip.seip is the OR of reg_mip.seip and
 | 
			
		||||
      // io.interrupts.seip.  We don't want the value on the PLIC line to
 | 
			
		||||
      // inadvertently be OR'd into read_mip.seip.
 | 
			
		||||
      val new_mip = readModifyWriteCSR(io.rw.cmd, reg_mip.asUInt, io.rw.wdata).asTypeOf(new MIP)
 | 
			
		||||
      if (usingVM) {
 | 
			
		||||
        reg_mip.ssip := new_mip.ssip
 | 
			
		||||
        reg_mip.stip := new_mip.stip
 | 
			
		||||
        reg_mip.seip := new_mip.seip
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    when (decoded_addr(CSRs.mie))      { reg_mie := wdata & supported_interrupts }
 | 
			
		||||
@@ -678,7 +697,10 @@ class CSRFile(perfEventSets: EventSets = new EventSets(Seq()))(implicit p: Param
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  reg_mip <> io.interrupts
 | 
			
		||||
  reg_mip.lip := (io.interrupts.lip: Seq[Bool])
 | 
			
		||||
  reg_mip.mtip := io.interrupts.mtip
 | 
			
		||||
  reg_mip.msip := io.interrupts.msip
 | 
			
		||||
  reg_mip.meip := io.interrupts.meip
 | 
			
		||||
  reg_dcsr.debugint := io.interrupts.debug
 | 
			
		||||
 | 
			
		||||
  if (!usingVM) {
 | 
			
		||||
@@ -721,6 +743,9 @@ class CSRFile(perfEventSets: EventSets = new EventSets(Seq()))(implicit p: Param
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  def readModifyWriteCSR(cmd: UInt, rdata: UInt, wdata: UInt) =
 | 
			
		||||
    (Mux(cmd.isOneOf(CSR.S, CSR.C), rdata, UInt(0)) | wdata) & ~Mux(cmd === CSR.C, wdata, UInt(0))
 | 
			
		||||
 | 
			
		||||
  def legalizePrivilege(priv: UInt): UInt =
 | 
			
		||||
    if (usingVM) Mux(priv === PRV.H, PRV.U, priv)
 | 
			
		||||
    else if (usingUser) Fill(2, priv(0))
 | 
			
		||||
 
 | 
			
		||||
@@ -87,8 +87,9 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) {
 | 
			
		||||
  io.cpu.req.ready := (release_state === s_ready) && !cached_grant_wait && !s1_nack
 | 
			
		||||
 | 
			
		||||
  // I/O MSHRs
 | 
			
		||||
  val uncachedInFlight = Reg(init = Vec.fill(cacheParams.nMMIOs)(false.B))
 | 
			
		||||
  val uncachedReqs = Reg(Vec(cacheParams.nMMIOs, new HellaCacheReq))
 | 
			
		||||
  val mmioOffset = if (outer.scratch().isDefined) 0 else 1
 | 
			
		||||
  val uncachedInFlight = Seq.fill(maxUncachedInFlight) { RegInit(Bool(false)) }
 | 
			
		||||
  val uncachedReqs = Seq.fill(maxUncachedInFlight) { Reg(new HellaCacheReq) }
 | 
			
		||||
 | 
			
		||||
  // hit initiation path
 | 
			
		||||
  dataArb.io.in(3).valid := io.cpu.req.valid && isRead(io.cpu.req.bits.cmd)
 | 
			
		||||
@@ -184,8 +185,10 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) {
 | 
			
		||||
  val no_xcpt = Bool(usingDataScratchpad) && s1_req.phys /* slave port */ && s1_hit_state.isValid()
 | 
			
		||||
  io.cpu.xcpt.ma.ld := !no_xcpt && s1_read && s1_storegen.misaligned
 | 
			
		||||
  io.cpu.xcpt.ma.st := !no_xcpt && s1_write && s1_storegen.misaligned
 | 
			
		||||
  io.cpu.xcpt.pf.ld := !no_xcpt && s1_read && tlb.io.resp.xcpt_ld
 | 
			
		||||
  io.cpu.xcpt.pf.st := !no_xcpt && s1_write && tlb.io.resp.xcpt_st
 | 
			
		||||
  io.cpu.xcpt.pf.ld := !no_xcpt && s1_read && tlb.io.resp.pf.ld
 | 
			
		||||
  io.cpu.xcpt.pf.st := !no_xcpt && s1_write && tlb.io.resp.pf.st
 | 
			
		||||
  io.cpu.xcpt.ae.ld := !no_xcpt && s1_read && tlb.io.resp.ae.ld
 | 
			
		||||
  io.cpu.xcpt.ae.st := !no_xcpt && s1_write && tlb.io.resp.ae.st
 | 
			
		||||
 | 
			
		||||
  // load reservations
 | 
			
		||||
  val s2_lr = Bool(usingAtomics) && s2_req.cmd === M_XLR
 | 
			
		||||
@@ -251,13 +254,13 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) {
 | 
			
		||||
  metaWriteArb.io.in(0).bits.data.tag := s2_req.addr(paddrBits-1, untagBits)
 | 
			
		||||
 | 
			
		||||
  // Prepare a TileLink request message that initiates a transaction
 | 
			
		||||
  val a_source = PriorityEncoder(~uncachedInFlight.asUInt) // skip the MSHR
 | 
			
		||||
  val a_source = PriorityEncoder(~uncachedInFlight.asUInt << mmioOffset) // skip the MSHR
 | 
			
		||||
  val acquire_address = s2_req_block_addr
 | 
			
		||||
  val access_address = s2_req.addr
 | 
			
		||||
  val a_size = s2_req.typ(MT_SZ-2, 0)
 | 
			
		||||
  val a_data = Fill(beatWords, pstore1_storegen.data)
 | 
			
		||||
  val acquire = if (edge.manager.anySupportAcquireB) {
 | 
			
		||||
    edge.Acquire(UInt(cacheParams.nMMIOs), acquire_address, lgCacheBlockBytes, s2_grow_param)._2 // Cacheability checked by tlb
 | 
			
		||||
    edge.Acquire(UInt(0), acquire_address, lgCacheBlockBytes, s2_grow_param)._2 // Cacheability checked by tlb
 | 
			
		||||
  } else {
 | 
			
		||||
    Wire(new TLBundleA(edge.bundle))
 | 
			
		||||
  }
 | 
			
		||||
@@ -285,10 +288,15 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) {
 | 
			
		||||
  tl_out.a.bits := Mux(!s2_uncached, acquire, Mux(!s2_write, get, Mux(!pstore1_amo, put, atomics)))
 | 
			
		||||
 | 
			
		||||
  // Set pending bits for outstanding TileLink transaction
 | 
			
		||||
  val a_sel = UIntToOH(a_source, maxUncachedInFlight+mmioOffset) >> mmioOffset
 | 
			
		||||
  when (tl_out.a.fire()) {
 | 
			
		||||
    when (s2_uncached) {
 | 
			
		||||
      uncachedInFlight(a_source) := true
 | 
			
		||||
      uncachedReqs(a_source) := s2_req
 | 
			
		||||
      (a_sel.toBools zip (uncachedInFlight zip uncachedReqs)) foreach { case (s, (f, r)) =>
 | 
			
		||||
        when (s) {
 | 
			
		||||
          f := Bool(true)
 | 
			
		||||
          r := s2_req
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }.otherwise {
 | 
			
		||||
      cached_grant_wait := true
 | 
			
		||||
    }
 | 
			
		||||
@@ -307,10 +315,14 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) {
 | 
			
		||||
      assert(cached_grant_wait, "A GrantData was unexpected by the dcache.")
 | 
			
		||||
      when(d_last) { cached_grant_wait := false }
 | 
			
		||||
    } .elsewhen (grantIsUncached) {
 | 
			
		||||
      assert(d_last, "DCache MMIO responses must be single-beat")
 | 
			
		||||
      assert(uncachedInFlight(tl_out.d.bits.source), "An AccessAck was unexpected by the dcache.") // TODO must handle Ack coming back on same cycle!
 | 
			
		||||
      uncachedInFlight(tl_out.d.bits.source) := false
 | 
			
		||||
      val req = uncachedReqs(tl_out.d.bits.source)
 | 
			
		||||
      val d_sel = UIntToOH(tl_out.d.bits.source, maxUncachedInFlight+mmioOffset) >> mmioOffset
 | 
			
		||||
      val req = Mux1H(d_sel, uncachedReqs)
 | 
			
		||||
      (d_sel.toBools zip uncachedInFlight) foreach { case (s, f) =>
 | 
			
		||||
        when (s && d_last) {
 | 
			
		||||
          assert(f, "An AccessAck was unexpected by the dcache.") // TODO must handle Ack coming back on same cycle!
 | 
			
		||||
          f := false
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      when (grantIsUncachedData) {
 | 
			
		||||
        s2_data := tl_out.d.bits.data
 | 
			
		||||
        s2_req.cmd := M_XRD
 | 
			
		||||
@@ -381,7 +393,7 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) {
 | 
			
		||||
 | 
			
		||||
  val voluntaryReleaseMessage = if (edge.manager.anySupportAcquireB) {
 | 
			
		||||
                                edge.Release(
 | 
			
		||||
                                  fromSource = UInt(cacheParams.nMMIOs - 1),
 | 
			
		||||
                                  fromSource = UInt(0),
 | 
			
		||||
                                  toAddress = probe_bits.address,
 | 
			
		||||
                                  lgSize = lgCacheBlockBytes,
 | 
			
		||||
                                  shrinkPermissions = s2_shrink_param,
 | 
			
		||||
 
 | 
			
		||||
@@ -22,7 +22,8 @@ class FrontendResp(implicit p: Parameters) extends CoreBundle()(p) {
 | 
			
		||||
  val pc = UInt(width = vaddrBitsExtended)  // ID stage PC
 | 
			
		||||
  val data = UInt(width = fetchWidth * coreInstBits)
 | 
			
		||||
  val mask = Bits(width = fetchWidth)
 | 
			
		||||
  val xcpt_if = Bool()
 | 
			
		||||
  val pf = Bool()
 | 
			
		||||
  val ae = Bool()
 | 
			
		||||
  val replay = Bool()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -72,9 +73,12 @@ class FrontendModule(outer: Frontend) extends LazyModuleImp(outer)
 | 
			
		||||
  val s2_pc = Reg(init=io.resetVector)
 | 
			
		||||
  val s2_btb_resp_valid = Reg(init=Bool(false))
 | 
			
		||||
  val s2_btb_resp_bits = Reg(new BTBResp)
 | 
			
		||||
  val s2_maybe_xcpt_if = Reg(init=Bool(false))
 | 
			
		||||
  val s2_maybe_pf = Reg(init=Bool(false))
 | 
			
		||||
  val s2_maybe_ae = Reg(init=Bool(false))
 | 
			
		||||
  val s2_tlb_miss = Reg(Bool())
 | 
			
		||||
  val s2_xcpt_if = s2_maybe_xcpt_if && !s2_tlb_miss
 | 
			
		||||
  val s2_pf = s2_maybe_pf && !s2_tlb_miss
 | 
			
		||||
  val s2_ae = s2_maybe_ae && !s2_tlb_miss
 | 
			
		||||
  val s2_xcpt = s2_pf || s2_ae
 | 
			
		||||
  val s2_speculative = Reg(init=Bool(false))
 | 
			
		||||
  val s2_cacheable = Reg(init=Bool(false))
 | 
			
		||||
 | 
			
		||||
@@ -101,7 +105,8 @@ class FrontendModule(outer: Frontend) extends LazyModuleImp(outer)
 | 
			
		||||
      s2_pc := s1_pc
 | 
			
		||||
      s2_speculative := s1_speculative
 | 
			
		||||
      s2_cacheable := tlb.io.resp.cacheable
 | 
			
		||||
      s2_maybe_xcpt_if := tlb.io.resp.xcpt_if
 | 
			
		||||
      s2_maybe_pf := tlb.io.resp.pf.inst
 | 
			
		||||
      s2_maybe_ae := tlb.io.resp.ae.inst
 | 
			
		||||
      s2_tlb_miss := tlb.io.resp.miss
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
@@ -144,18 +149,19 @@ class FrontendModule(outer: Frontend) extends LazyModuleImp(outer)
 | 
			
		||||
  icache.io.invalidate := io.cpu.flush_icache
 | 
			
		||||
  icache.io.s1_paddr := tlb.io.resp.paddr
 | 
			
		||||
  icache.io.s1_kill := io.cpu.req.valid || tlb.io.resp.miss || icmiss
 | 
			
		||||
  icache.io.s2_kill := s2_speculative && !s2_cacheable || s2_xcpt_if
 | 
			
		||||
  icache.io.s2_kill := s2_speculative && !s2_cacheable || s2_xcpt
 | 
			
		||||
  icache.io.resp.ready := !stall && !s1_same_block
 | 
			
		||||
 | 
			
		||||
  io.cpu.resp.valid := s2_valid && (icache.io.resp.valid || icache.io.s2_kill || s2_xcpt_if)
 | 
			
		||||
  io.cpu.resp.valid := s2_valid && (icache.io.resp.valid || icache.io.s2_kill || s2_xcpt)
 | 
			
		||||
  io.cpu.resp.bits.pc := s2_pc
 | 
			
		||||
  io.cpu.npc := Mux(io.cpu.req.valid, io.cpu.req.bits.pc, npc)
 | 
			
		||||
 | 
			
		||||
  require(fetchWidth * coreInstBytes <= rowBytes && isPow2(fetchWidth))
 | 
			
		||||
  io.cpu.resp.bits.data := icache.io.resp.bits.datablock >> (s2_pc.extract(log2Ceil(rowBytes)-1,log2Ceil(fetchWidth*coreInstBytes)) << log2Ceil(fetchWidth*coreInstBits))
 | 
			
		||||
  io.cpu.resp.bits.mask := UInt((1 << fetchWidth)-1) << s2_pc.extract(log2Ceil(fetchWidth)+log2Ceil(coreInstBytes)-1, log2Ceil(coreInstBytes))
 | 
			
		||||
  io.cpu.resp.bits.xcpt_if := s2_xcpt_if
 | 
			
		||||
  io.cpu.resp.bits.replay := icache.io.s2_kill && !icache.io.resp.valid && !s2_xcpt_if
 | 
			
		||||
  io.cpu.resp.bits.pf := s2_pf
 | 
			
		||||
  io.cpu.resp.bits.ae := s2_ae
 | 
			
		||||
  io.cpu.resp.bits.replay := icache.io.s2_kill && !icache.io.resp.valid && !s2_xcpt
 | 
			
		||||
  io.cpu.resp.bits.btb.valid := s2_btb_resp_valid
 | 
			
		||||
  io.cpu.resp.bits.btb.bits := s2_btb_resp_bits
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -60,6 +60,7 @@ trait HasL1HellaCacheParameters extends HasL1CacheParameters with HasCoreParamet
 | 
			
		||||
  def encRowBits = encDataBits*rowWords
 | 
			
		||||
  def lrscCycles = 32 // ISA requires 16-insn LRSC sequences to succeed
 | 
			
		||||
  def nIOMSHRs = cacheParams.nMMIOs
 | 
			
		||||
  def maxUncachedInFlight = cacheParams.nMMIOs
 | 
			
		||||
  def dataScratchpadSize = cacheParams.dataScratchpadBytes
 | 
			
		||||
 | 
			
		||||
  require(rowBits >= coreDataBits, s"rowBits($rowBits) < coreDataBits($coreDataBits)")
 | 
			
		||||
@@ -112,6 +113,7 @@ class AlignmentExceptions extends Bundle {
 | 
			
		||||
class HellaCacheExceptions extends Bundle {
 | 
			
		||||
  val ma = new AlignmentExceptions
 | 
			
		||||
  val pf = new AlignmentExceptions
 | 
			
		||||
  val ae = new AlignmentExceptions
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// interface between D$ and processor/DTLB
 | 
			
		||||
 
 | 
			
		||||
@@ -11,6 +11,8 @@ import util._
 | 
			
		||||
class Instruction(implicit val p: Parameters) extends ParameterizedBundle with HasCoreParameters {
 | 
			
		||||
  val pf0 = Bool() // page fault on first half of instruction
 | 
			
		||||
  val pf1 = Bool() // page fault on second half of instruction
 | 
			
		||||
  val ae0 = Bool() // access exception on first half of instruction
 | 
			
		||||
  val ae1 = Bool() // access exception on second half of instruction
 | 
			
		||||
  val replay = Bool()
 | 
			
		||||
  val btb_hit = Bool()
 | 
			
		||||
  val rvc = Bool()
 | 
			
		||||
@@ -78,7 +80,8 @@ class IBuf(implicit p: Parameters) extends CoreModule {
 | 
			
		||||
 | 
			
		||||
  val valid = (UIntToOH(nValid) - 1)(fetchWidth-1, 0)
 | 
			
		||||
  val bufMask = UIntToOH(nBufValid) - 1
 | 
			
		||||
  val xcpt_if = valid & (Mux(buf.xcpt_if, bufMask, UInt(0)) | Mux(io.imem.bits.xcpt_if, ~bufMask, UInt(0)))
 | 
			
		||||
  val pf = valid & (Mux(buf.pf, bufMask, UInt(0)) | Mux(io.imem.bits.pf, ~bufMask, UInt(0)))
 | 
			
		||||
  val ae = valid & (Mux(buf.ae, bufMask, UInt(0)) | Mux(io.imem.bits.ae, ~bufMask, UInt(0)))
 | 
			
		||||
  val ic_replay = valid & (Mux(buf.replay, bufMask, UInt(0)) | Mux(io.imem.bits.replay, ~bufMask, UInt(0)))
 | 
			
		||||
  val ibufBTBHitMask = Mux(ibufBTBHit, UIntToOH(ibufBTBResp.bridx), UInt(0))
 | 
			
		||||
  assert(!io.imem.bits.btb.valid || io.imem.bits.btb.bits.bridx >= pcWordBits)
 | 
			
		||||
@@ -97,9 +100,11 @@ class IBuf(implicit p: Parameters) extends CoreModule {
 | 
			
		||||
 | 
			
		||||
    if (usingCompressed) {
 | 
			
		||||
      val replay = ic_replay(j) || (!exp.io.rvc && (btbHitMask(j) || ic_replay(j+1)))
 | 
			
		||||
      io.inst(i).valid := valid(j) && (exp.io.rvc || valid(j+1) || xcpt_if(j+1) || replay)
 | 
			
		||||
      io.inst(i).bits.pf0 := xcpt_if(j)
 | 
			
		||||
      io.inst(i).bits.pf1 := !exp.io.rvc && xcpt_if(j+1)
 | 
			
		||||
      io.inst(i).valid := valid(j) && (exp.io.rvc || valid(j+1) || pf(j+1) || ae(j+1) || replay)
 | 
			
		||||
      io.inst(i).bits.pf0 := pf(j)
 | 
			
		||||
      io.inst(i).bits.pf1 := !exp.io.rvc && pf(j+1)
 | 
			
		||||
      io.inst(i).bits.ae0 := ae(j)
 | 
			
		||||
      io.inst(i).bits.ae1 := !exp.io.rvc && ae(j+1)
 | 
			
		||||
      io.inst(i).bits.replay := replay
 | 
			
		||||
      io.inst(i).bits.btb_hit := btbHitMask(j) || (!exp.io.rvc && btbHitMask(j+1))
 | 
			
		||||
      io.inst(i).bits.rvc := exp.io.rvc
 | 
			
		||||
@@ -110,8 +115,10 @@ class IBuf(implicit p: Parameters) extends CoreModule {
 | 
			
		||||
    } else {
 | 
			
		||||
      when (io.inst(i).ready) { nReady := i+1 }
 | 
			
		||||
      io.inst(i).valid := valid(i)
 | 
			
		||||
      io.inst(i).bits.pf0 := xcpt_if(i)
 | 
			
		||||
      io.inst(i).bits.pf0 := pf(i)
 | 
			
		||||
      io.inst(i).bits.pf1 := false
 | 
			
		||||
      io.inst(i).bits.ae0 := ae(i)
 | 
			
		||||
      io.inst(i).bits.ae1 := false
 | 
			
		||||
      io.inst(i).bits.replay := ic_replay(i)
 | 
			
		||||
      io.inst(i).bits.rvc := false
 | 
			
		||||
      io.inst(i).bits.btb_hit := btbHitMask(i)
 | 
			
		||||
 
 | 
			
		||||
@@ -216,31 +216,37 @@ object Instructions {
 | 
			
		||||
}
 | 
			
		||||
object Causes {
 | 
			
		||||
  val misaligned_fetch = 0x0
 | 
			
		||||
  val fault_fetch = 0x1
 | 
			
		||||
  val fetch_access = 0x1
 | 
			
		||||
  val illegal_instruction = 0x2
 | 
			
		||||
  val breakpoint = 0x3
 | 
			
		||||
  val misaligned_load = 0x4
 | 
			
		||||
  val fault_load = 0x5
 | 
			
		||||
  val load_access = 0x5
 | 
			
		||||
  val misaligned_store = 0x6
 | 
			
		||||
  val fault_store = 0x7
 | 
			
		||||
  val store_access = 0x7
 | 
			
		||||
  val user_ecall = 0x8
 | 
			
		||||
  val supervisor_ecall = 0x9
 | 
			
		||||
  val hypervisor_ecall = 0xa
 | 
			
		||||
  val machine_ecall = 0xb
 | 
			
		||||
  val fetch_page_fault = 0xc
 | 
			
		||||
  val load_page_fault = 0xd
 | 
			
		||||
  val store_page_fault = 0xf
 | 
			
		||||
  val all = {
 | 
			
		||||
    val res = collection.mutable.ArrayBuffer[Int]()
 | 
			
		||||
    res += misaligned_fetch
 | 
			
		||||
    res += fault_fetch
 | 
			
		||||
    res += fetch_access
 | 
			
		||||
    res += illegal_instruction
 | 
			
		||||
    res += breakpoint
 | 
			
		||||
    res += misaligned_load
 | 
			
		||||
    res += fault_load
 | 
			
		||||
    res += load_access
 | 
			
		||||
    res += misaligned_store
 | 
			
		||||
    res += fault_store
 | 
			
		||||
    res += store_access
 | 
			
		||||
    res += user_ecall
 | 
			
		||||
    res += supervisor_ecall
 | 
			
		||||
    res += hypervisor_ecall
 | 
			
		||||
    res += machine_ecall
 | 
			
		||||
    res += fetch_page_fault
 | 
			
		||||
    res += load_page_fault
 | 
			
		||||
    res += store_page_fault
 | 
			
		||||
    res.toArray
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -745,8 +745,10 @@ class NonBlockingDCacheModule(outer: NonBlockingDCache) extends HellaCacheModule
 | 
			
		||||
  val misaligned = new StoreGen(s1_req.typ, s1_req.addr, UInt(0), wordBytes).misaligned
 | 
			
		||||
  io.cpu.xcpt.ma.ld := s1_read && misaligned
 | 
			
		||||
  io.cpu.xcpt.ma.st := s1_write && misaligned
 | 
			
		||||
  io.cpu.xcpt.pf.ld := s1_read && dtlb.io.resp.xcpt_ld
 | 
			
		||||
  io.cpu.xcpt.pf.st := s1_write && dtlb.io.resp.xcpt_st
 | 
			
		||||
  io.cpu.xcpt.pf.ld := s1_read && dtlb.io.resp.pf.ld
 | 
			
		||||
  io.cpu.xcpt.pf.st := s1_write && dtlb.io.resp.pf.st
 | 
			
		||||
  io.cpu.xcpt.ae.ld := s1_read && dtlb.io.resp.ae.ld
 | 
			
		||||
  io.cpu.xcpt.ae.st := s1_write && dtlb.io.resp.ae.st
 | 
			
		||||
 | 
			
		||||
  // tags
 | 
			
		||||
  def onReset = L1Metadata(UInt(0), ClientMetadata.onReset)
 | 
			
		||||
 
 | 
			
		||||
@@ -19,6 +19,7 @@ class PTWReq(implicit p: Parameters) extends CoreBundle()(p) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class PTWResp(implicit p: Parameters) extends CoreBundle()(p) {
 | 
			
		||||
  val ae = Bool()
 | 
			
		||||
  val pte = new PTE
 | 
			
		||||
  val level = UInt(width = log2Ceil(pgLevels))
 | 
			
		||||
  val homogeneous = Bool()
 | 
			
		||||
@@ -77,7 +78,7 @@ class PTW(n: Int)(implicit edge: TLEdgeOut, p: Parameters) extends CoreModule()(
 | 
			
		||||
  val count = Reg(UInt(width = log2Up(pgLevels)))
 | 
			
		||||
  val s1_kill = Reg(next = Bool(false))
 | 
			
		||||
  val resp_valid = Reg(next = Vec.fill(io.requestor.size)(Bool(false)))
 | 
			
		||||
  val exception = Reg(next = io.mem.xcpt.pf.ld)
 | 
			
		||||
  val ae = Reg(next = io.mem.xcpt.ae.ld)
 | 
			
		||||
 | 
			
		||||
  val r_req = Reg(new PTWReq)
 | 
			
		||||
  val r_req_dest = Reg(Bits())
 | 
			
		||||
@@ -90,14 +91,15 @@ class PTW(n: Int)(implicit edge: TLEdgeOut, p: Parameters) extends CoreModule()(
 | 
			
		||||
  arb.io.in <> io.requestor.map(_.req)
 | 
			
		||||
  arb.io.out.ready := state === s_ready
 | 
			
		||||
 | 
			
		||||
  val pte = {
 | 
			
		||||
  val (pte, invalid_paddr) = {
 | 
			
		||||
    val tmp = new PTE().fromBits(io.mem.resp.bits.data)
 | 
			
		||||
    val res = Wire(init = new PTE().fromBits(io.mem.resp.bits.data))
 | 
			
		||||
    res.ppn := tmp.ppn(ppnBits-1, 0)
 | 
			
		||||
    when ((tmp.ppn >> ppnBits) =/= 0) { res.v := false }
 | 
			
		||||
    res
 | 
			
		||||
    (res, (tmp.ppn >> ppnBits) =/= 0)
 | 
			
		||||
  }
 | 
			
		||||
  val traverse = pte.table() && !invalid_paddr && count < pgLevels-1
 | 
			
		||||
  val pte_addr = Cat(r_pte.ppn, vpn_idx) << log2Ceil(xLen/8)
 | 
			
		||||
  val resp_ae = Reg(next = ae || invalid_paddr)
 | 
			
		||||
 | 
			
		||||
  when (arb.io.out.fire()) {
 | 
			
		||||
    r_req := arb.io.out.bits
 | 
			
		||||
@@ -114,7 +116,7 @@ class PTW(n: Int)(implicit edge: TLEdgeOut, p: Parameters) extends CoreModule()(
 | 
			
		||||
 | 
			
		||||
    val hits = tags.map(_ === pte_addr).asUInt & valid
 | 
			
		||||
    val hit = hits.orR
 | 
			
		||||
    when (io.mem.resp.valid && pte.table() && !hit) {
 | 
			
		||||
    when (io.mem.resp.valid && traverse && !hit) {
 | 
			
		||||
      val r = Mux(valid.andR, plru.replace, PriorityEncoder(~valid))
 | 
			
		||||
      valid := valid | UIntToOH(r)
 | 
			
		||||
      tags(r) := pte_addr
 | 
			
		||||
@@ -142,6 +144,7 @@ class PTW(n: Int)(implicit edge: TLEdgeOut, p: Parameters) extends CoreModule()(
 | 
			
		||||
 | 
			
		||||
  for (i <- 0 until io.requestor.size) {
 | 
			
		||||
    io.requestor(i).resp.valid := resp_valid(i)
 | 
			
		||||
    io.requestor(i).resp.bits.ae := resp_ae
 | 
			
		||||
    io.requestor(i).resp.bits.pte := r_pte
 | 
			
		||||
    io.requestor(i).resp.bits.level := count
 | 
			
		||||
    io.requestor(i).resp.bits.pte.ppn := pte_addr >> pgIdxBits
 | 
			
		||||
@@ -177,16 +180,17 @@ class PTW(n: Int)(implicit edge: TLEdgeOut, p: Parameters) extends CoreModule()(
 | 
			
		||||
      }
 | 
			
		||||
      when (io.mem.resp.valid) {
 | 
			
		||||
        r_pte := pte
 | 
			
		||||
        when (pte.table() && count < pgLevels-1) {
 | 
			
		||||
        when (traverse) {
 | 
			
		||||
          state := s_req
 | 
			
		||||
          count := count + 1
 | 
			
		||||
        }.otherwise {
 | 
			
		||||
          resp_ae := invalid_paddr
 | 
			
		||||
          state := s_ready
 | 
			
		||||
          resp_valid(r_req_dest) := true
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      when (exception) {
 | 
			
		||||
        r_pte.v := false
 | 
			
		||||
      when (ae) {
 | 
			
		||||
        resp_ae := true
 | 
			
		||||
        state := s_ready
 | 
			
		||||
        resp_valid(r_req_dest) := true
 | 
			
		||||
      }
 | 
			
		||||
 
 | 
			
		||||
@@ -17,6 +17,7 @@ case class RocketCoreParams(
 | 
			
		||||
  useDebug: Boolean = true,
 | 
			
		||||
  useAtomics: Boolean = true,
 | 
			
		||||
  useCompressed: Boolean = true,
 | 
			
		||||
  nLocalInterrupts: Int = 0,
 | 
			
		||||
  nBreakpoints: Int = 1,
 | 
			
		||||
  nPMPs: Int = 8,
 | 
			
		||||
  nPerfCounters: Int = 0,
 | 
			
		||||
@@ -225,12 +226,14 @@ class Rocket(implicit p: Parameters) extends CoreModule()(p)
 | 
			
		||||
  bpu.io.pc := ibuf.io.pc
 | 
			
		||||
  bpu.io.ea := mem_reg_wdata
 | 
			
		||||
 | 
			
		||||
  val id_xcpt_if = ibuf.io.inst(0).bits.pf0 || ibuf.io.inst(0).bits.pf1
 | 
			
		||||
  val id_xcpt_pf = ibuf.io.inst(0).bits.pf0 || ibuf.io.inst(0).bits.pf1
 | 
			
		||||
  val id_xcpt_ae = ibuf.io.inst(0).bits.ae0 || ibuf.io.inst(0).bits.ae1
 | 
			
		||||
  val (id_xcpt, id_cause) = checkExceptions(List(
 | 
			
		||||
    (csr.io.interrupt, csr.io.interrupt_cause),
 | 
			
		||||
    (bpu.io.debug_if,  UInt(CSR.debugTriggerCause)),
 | 
			
		||||
    (bpu.io.xcpt_if,   UInt(Causes.breakpoint)),
 | 
			
		||||
    (id_xcpt_if,       UInt(Causes.fault_fetch)),
 | 
			
		||||
    (id_xcpt_pf,       UInt(Causes.fetch_page_fault)),
 | 
			
		||||
    (id_xcpt_ae,       UInt(Causes.fetch_access)),
 | 
			
		||||
    (id_illegal_insn,  UInt(Causes.illegal_instruction))))
 | 
			
		||||
 | 
			
		||||
  val dcache_bypass_data =
 | 
			
		||||
@@ -423,8 +426,10 @@ class Rocket(implicit p: Parameters) extends CoreModule()(p)
 | 
			
		||||
 | 
			
		||||
  val (wb_xcpt, wb_cause) = checkExceptions(List(
 | 
			
		||||
    (wb_reg_xcpt,  wb_reg_cause),
 | 
			
		||||
    (wb_reg_valid && wb_ctrl.mem && RegEnable(io.dmem.xcpt.pf.st, mem_pc_valid), UInt(Causes.fault_store)),
 | 
			
		||||
    (wb_reg_valid && wb_ctrl.mem && RegEnable(io.dmem.xcpt.pf.ld, mem_pc_valid), UInt(Causes.fault_load))
 | 
			
		||||
    (wb_reg_valid && wb_ctrl.mem && RegEnable(io.dmem.xcpt.pf.st, mem_pc_valid), UInt(Causes.store_page_fault)),
 | 
			
		||||
    (wb_reg_valid && wb_ctrl.mem && RegEnable(io.dmem.xcpt.pf.ld, mem_pc_valid), UInt(Causes.load_page_fault)),
 | 
			
		||||
    (wb_reg_valid && wb_ctrl.mem && RegEnable(io.dmem.xcpt.ae.st, mem_pc_valid), UInt(Causes.store_access)),
 | 
			
		||||
    (wb_reg_valid && wb_ctrl.mem && RegEnable(io.dmem.xcpt.ae.ld, mem_pc_valid), UInt(Causes.load_access))
 | 
			
		||||
  ))
 | 
			
		||||
 | 
			
		||||
  val wb_wxd = wb_reg_valid && wb_ctrl.wxd
 | 
			
		||||
 
 | 
			
		||||
@@ -33,20 +33,25 @@ class TLBReq(lgMaxSize: Int)(implicit p: Parameters) extends CoreBundle()(p) {
 | 
			
		||||
  override def cloneType = new TLBReq(lgMaxSize).asInstanceOf[this.type]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class TLBExceptions extends Bundle {
 | 
			
		||||
  val ld = Bool()
 | 
			
		||||
  val st = Bool()
 | 
			
		||||
  val inst = Bool()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class TLBResp(implicit p: Parameters) extends CoreBundle()(p) {
 | 
			
		||||
  // lookup responses
 | 
			
		||||
  val miss = Bool(OUTPUT)
 | 
			
		||||
  val paddr = UInt(OUTPUT, paddrBits)
 | 
			
		||||
  val xcpt_ld = Bool(OUTPUT)
 | 
			
		||||
  val xcpt_st = Bool(OUTPUT)
 | 
			
		||||
  val xcpt_if = Bool(OUTPUT)
 | 
			
		||||
  val cacheable = Bool(OUTPUT)
 | 
			
		||||
  val miss = Bool()
 | 
			
		||||
  val paddr = UInt(width = paddrBits)
 | 
			
		||||
  val pf = new TLBExceptions
 | 
			
		||||
  val ae = new TLBExceptions
 | 
			
		||||
  val cacheable = Bool()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class TLB(lgMaxSize: Int, nEntries: Int)(implicit edge: TLEdgeOut, p: Parameters) extends CoreModule()(p) {
 | 
			
		||||
  val io = new Bundle {
 | 
			
		||||
    val req = Decoupled(new TLBReq(lgMaxSize)).flip
 | 
			
		||||
    val resp = new TLBResp
 | 
			
		||||
    val resp = new TLBResp().asOutput
 | 
			
		||||
    val ptw = new TLBPTWIO
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -59,8 +64,10 @@ class TLB(lgMaxSize: Int, nEntries: Int)(implicit edge: TLEdgeOut, p: Parameters
 | 
			
		||||
    val sw = Bool()
 | 
			
		||||
    val sx = Bool()
 | 
			
		||||
    val sr = Bool()
 | 
			
		||||
    val xr = Bool()
 | 
			
		||||
    val cacheable = Bool()
 | 
			
		||||
    val pw = Bool()
 | 
			
		||||
    val px = Bool()
 | 
			
		||||
    val pr = Bool()
 | 
			
		||||
    val c = Bool()
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  val totalEntries = nEntries + 1
 | 
			
		||||
@@ -92,7 +99,7 @@ class TLB(lgMaxSize: Int, nEntries: Int)(implicit edge: TLEdgeOut, p: Parameters
 | 
			
		||||
  val pmp = Module(new PMPChecker(lgMaxSize))
 | 
			
		||||
  pmp.io.addr := mpu_physaddr
 | 
			
		||||
  pmp.io.size := io.req.bits.size
 | 
			
		||||
  pmp.io.pmp := io.ptw.pmp
 | 
			
		||||
  pmp.io.pmp := (io.ptw.pmp: Seq[PMP])
 | 
			
		||||
  pmp.io.prv := Mux(Bool(usingVM) && (do_refill || io.req.bits.passthrough /* PTW */), PRV.S, priv)
 | 
			
		||||
  val legal_address = edge.manager.findSafe(mpu_physaddr).reduce(_||_)
 | 
			
		||||
  def fastCheck(member: TLManagerParameters => Boolean) =
 | 
			
		||||
@@ -101,7 +108,7 @@ class TLB(lgMaxSize: Int, nEntries: Int)(implicit edge: TLEdgeOut, p: Parameters
 | 
			
		||||
  val prot_w = fastCheck(_.supportsPutFull) && pmp.io.w
 | 
			
		||||
  val prot_x = fastCheck(_.executable) && pmp.io.x
 | 
			
		||||
  val cacheable = fastCheck(_.supportsAcquireB)
 | 
			
		||||
  val isSpecial = !io.ptw.resp.bits.homogeneous
 | 
			
		||||
  val isSpecial = !(io.ptw.resp.bits.homogeneous || io.ptw.resp.bits.ae)
 | 
			
		||||
 | 
			
		||||
  val lookup_tag = Cat(io.ptw.ptbr.asid, vpn(vpnBits-1,0))
 | 
			
		||||
  val hitsVec = (0 until totalEntries).map { i => vm_enabled && {
 | 
			
		||||
@@ -123,13 +130,6 @@ class TLB(lgMaxSize: Int, nEntries: Int)(implicit edge: TLEdgeOut, p: Parameters
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // permission bit arrays
 | 
			
		||||
  val u_array = Reg(Vec(totalEntries, Bool())) // user permission
 | 
			
		||||
  val g_array = Reg(Vec(totalEntries, Bool())) // global mapping
 | 
			
		||||
  val sw_array = Reg(Vec(totalEntries, Bool())) // write permission
 | 
			
		||||
  val sx_array = Reg(Vec(totalEntries, Bool())) // execute permission
 | 
			
		||||
  val sr_array = Reg(Vec(totalEntries, Bool())) // read permission
 | 
			
		||||
  val xr_array = Reg(Vec(totalEntries, Bool())) // read permission to executable page
 | 
			
		||||
  val cash_array = Reg(Vec(normalEntries, Bool())) // cacheable
 | 
			
		||||
  when (do_refill && !invalidate_refill) {
 | 
			
		||||
    val waddr = Mux(isSpecial, specialEntry.U, r_refill_waddr)
 | 
			
		||||
    val pte = io.ptw.resp.bits.pte
 | 
			
		||||
@@ -137,13 +137,15 @@ class TLB(lgMaxSize: Int, nEntries: Int)(implicit edge: TLEdgeOut, p: Parameters
 | 
			
		||||
    newEntry.ppn := pte.ppn
 | 
			
		||||
    newEntry.tag := r_refill_tag
 | 
			
		||||
    newEntry.level := io.ptw.resp.bits.level
 | 
			
		||||
    newEntry.c := cacheable
 | 
			
		||||
    newEntry.u := pte.u
 | 
			
		||||
    newEntry.g := pte.g
 | 
			
		||||
    newEntry.sw := pte.sw() && (isSpecial || prot_w)
 | 
			
		||||
    newEntry.sx := pte.sx() && (isSpecial || prot_x)
 | 
			
		||||
    newEntry.sr := pte.sr() && (isSpecial || prot_r)
 | 
			
		||||
    newEntry.xr := pte.sx() && (isSpecial || prot_r)
 | 
			
		||||
    newEntry.cacheable := isSpecial || cacheable
 | 
			
		||||
    newEntry.sr := pte.sr()
 | 
			
		||||
    newEntry.sw := pte.sw()
 | 
			
		||||
    newEntry.sx := pte.sx()
 | 
			
		||||
    newEntry.pr := prot_r && !io.ptw.resp.bits.ae
 | 
			
		||||
    newEntry.pw := prot_w && !io.ptw.resp.bits.ae
 | 
			
		||||
    newEntry.px := prot_x && !io.ptw.resp.bits.ae
 | 
			
		||||
 | 
			
		||||
    valid := valid | UIntToOH(waddr)
 | 
			
		||||
    reg_entries(waddr) := newEntry.asUInt
 | 
			
		||||
@@ -153,10 +155,13 @@ class TLB(lgMaxSize: Int, nEntries: Int)(implicit edge: TLEdgeOut, p: Parameters
 | 
			
		||||
  val repl_waddr = Mux(!valid(normalEntries-1, 0).andR, PriorityEncoder(~valid(normalEntries-1, 0)), plru.replace)
 | 
			
		||||
 | 
			
		||||
  val priv_ok = Mux(priv_s, ~Mux(io.ptw.status.sum, UInt(0), entries.map(_.u).asUInt), entries.map(_.u).asUInt)
 | 
			
		||||
  val w_array = Cat(prot_w, priv_ok & ~(~prot_w << specialEntry) & entries.map(_.sw).asUInt)
 | 
			
		||||
  val x_array = Cat(prot_x, priv_ok & ~(~prot_x << specialEntry) & entries.map(_.sx).asUInt)
 | 
			
		||||
  val r_array = Cat(prot_r, priv_ok & ~(~prot_r << specialEntry) & (entries.map(_.sr).asUInt | Mux(io.ptw.status.mxr, entries.map(_.xr).asUInt, UInt(0))))
 | 
			
		||||
  val c_array = Cat(cacheable, ~(~cacheable << specialEntry) & entries.map(_.cacheable).asUInt)
 | 
			
		||||
  val r_array = Cat(true.B, priv_ok & (entries.map(_.sr).asUInt | Mux(io.ptw.status.mxr, entries.map(_.sx).asUInt, UInt(0))))
 | 
			
		||||
  val w_array = Cat(true.B, priv_ok & entries.map(_.sw).asUInt)
 | 
			
		||||
  val x_array = Cat(true.B, priv_ok & entries.map(_.sx).asUInt)
 | 
			
		||||
  val pr_array = Cat(Fill(2, prot_r), entries.init.map(_.pr).asUInt)
 | 
			
		||||
  val pw_array = Cat(Fill(2, prot_w), entries.init.map(_.pw).asUInt)
 | 
			
		||||
  val px_array = Cat(Fill(2, prot_x), entries.init.map(_.px).asUInt)
 | 
			
		||||
  val c_array = Cat(Fill(2, cacheable), entries.init.map(_.c).asUInt)
 | 
			
		||||
 | 
			
		||||
  val bad_va =
 | 
			
		||||
    if (vpnBits == vpnBitsExtended) Bool(false)
 | 
			
		||||
@@ -176,9 +181,12 @@ class TLB(lgMaxSize: Int, nEntries: Int)(implicit edge: TLEdgeOut, p: Parameters
 | 
			
		||||
  val multipleHits = PopCountAtLeast(hits(totalEntries-1, 0), 2)
 | 
			
		||||
 | 
			
		||||
  io.req.ready := state === s_ready
 | 
			
		||||
  io.resp.xcpt_ld := bad_va || (~r_array & hits).orR
 | 
			
		||||
  io.resp.xcpt_st := bad_va || (~w_array & hits).orR
 | 
			
		||||
  io.resp.xcpt_if := bad_va || (~x_array & hits).orR
 | 
			
		||||
  io.resp.pf.ld := bad_va || (~r_array & hits).orR
 | 
			
		||||
  io.resp.pf.st := bad_va || (~w_array & hits).orR
 | 
			
		||||
  io.resp.pf.inst := bad_va || (~x_array & hits).orR
 | 
			
		||||
  io.resp.ae.ld := (~pr_array & hits).orR
 | 
			
		||||
  io.resp.ae.st := (~pw_array & hits).orR
 | 
			
		||||
  io.resp.ae.inst := (~px_array & hits).orR
 | 
			
		||||
  io.resp.cacheable := (c_array & hits).orR
 | 
			
		||||
  io.resp.miss := do_refill || tlb_miss || multipleHits
 | 
			
		||||
  io.resp.paddr := Cat(ppn, pgOffset)
 | 
			
		||||
@@ -208,7 +216,7 @@ class TLB(lgMaxSize: Int, nEntries: Int)(implicit edge: TLEdgeOut, p: Parameters
 | 
			
		||||
 | 
			
		||||
    when (sfence) {
 | 
			
		||||
      valid := Mux(io.req.bits.sfence.bits.rs1, valid & ~hits(totalEntries-1, 0),
 | 
			
		||||
               Mux(io.req.bits.sfence.bits.rs2, valid & g_array.asUInt, 0))
 | 
			
		||||
               Mux(io.req.bits.sfence.bits.rs2, valid & entries.map(_.g).asUInt, 0))
 | 
			
		||||
    }
 | 
			
		||||
    when (multipleHits) {
 | 
			
		||||
      valid := 0
 | 
			
		||||
 
 | 
			
		||||
@@ -23,6 +23,7 @@ trait CoreParams {
 | 
			
		||||
  val decodeWidth: Int
 | 
			
		||||
  val retireWidth: Int
 | 
			
		||||
  val instBits: Int
 | 
			
		||||
  val nLocalInterrupts: Int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
trait HasCoreParameters extends HasTileParameters {
 | 
			
		||||
 
 | 
			
		||||
@@ -7,6 +7,7 @@ import config.Parameters
 | 
			
		||||
import util._
 | 
			
		||||
 | 
			
		||||
class TileInterrupts(implicit p: Parameters) extends CoreBundle()(p) {
 | 
			
		||||
  val lip = Vec(coreParams.nLocalInterrupts, Bool())
 | 
			
		||||
  val debug = Bool()
 | 
			
		||||
  val mtip = Bool()
 | 
			
		||||
  val msip = Bool()
 | 
			
		||||
 
 | 
			
		||||
@@ -44,6 +44,7 @@ class TLMonitor(args: TLMonitorArgs) extends TLMonitorBase(args)
 | 
			
		||||
 | 
			
		||||
    when (bundle.opcode === TLMessages.Acquire) {
 | 
			
		||||
      assert (edge.manager.supportsAcquireBSafe(edge.address(bundle), bundle.size), "'A' channel carries Acquire type unsupported by manager" + extra)
 | 
			
		||||
      assert (edge.client.supportsProbe(edge.source(bundle), bundle.size), "'A' channel carries Acquire from a client which does not support Probe" + extra)
 | 
			
		||||
      assert (source_ok, "'A' channel Acquire carries invalid source ID" + extra)
 | 
			
		||||
      assert (bundle.size >= UInt(log2Ceil(edge.manager.beatBytes)), "'A' channel Acquire smaller than a beat" + extra)
 | 
			
		||||
      assert (is_aligned, "'A' channel Acquire address not aligned to size" + extra)
 | 
			
		||||
@@ -189,6 +190,7 @@ class TLMonitor(args: TLMonitorArgs) extends TLMonitorBase(args)
 | 
			
		||||
 | 
			
		||||
    when (bundle.opcode === TLMessages.Release) {
 | 
			
		||||
      assert (edge.manager.supportsAcquireBSafe(edge.address(bundle), bundle.size), "'C' channel carries Release type unsupported by manager" + extra)
 | 
			
		||||
      assert (edge.client.supportsProbe(edge.source(bundle), bundle.size), "'C' channel carries Release from a client which does not support Probe" + extra)
 | 
			
		||||
      assert (source_ok, "'C' channel Release carries invalid source ID" + extra)
 | 
			
		||||
      assert (bundle.size >= UInt(log2Ceil(edge.manager.beatBytes)), "'C' channel Release smaller than a beat" + extra)
 | 
			
		||||
      assert (is_aligned, "'C' channel Release address not aligned to size" + extra)
 | 
			
		||||
@@ -198,6 +200,7 @@ class TLMonitor(args: TLMonitorArgs) extends TLMonitorBase(args)
 | 
			
		||||
 | 
			
		||||
    when (bundle.opcode === TLMessages.ReleaseData) {
 | 
			
		||||
      assert (edge.manager.supportsAcquireBSafe(edge.address(bundle), bundle.size), "'C' channel carries ReleaseData type unsupported by manager" + extra)
 | 
			
		||||
      assert (edge.client.supportsProbe(edge.source(bundle), bundle.size), "'C' channel carries Release from a client which does not support Probe" + extra)
 | 
			
		||||
      assert (source_ok, "'C' channel ReleaseData carries invalid source ID" + 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)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user