From fa7ead6357675b50856a2d95fc3c14c61b731fa2 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Mon, 27 Mar 2017 15:19:05 -0700 Subject: [PATCH 01/11] Revert "Use Reg(Vec) instead of Seq(Reg) for DCache MMIO" This reverts commit fb6498f2c30fc9fa13756e025e44dbca53108af7. --- src/main/scala/rocket/DCache.scala | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/main/scala/rocket/DCache.scala b/src/main/scala/rocket/DCache.scala index 1c17ff42..5f44cb00 100644 --- a/src/main/scala/rocket/DCache.scala +++ b/src/main/scala/rocket/DCache.scala @@ -87,8 +87,8 @@ 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 uncachedInFlight = Seq.fill(cacheParams.nMMIOs) { RegInit(Bool(false)) } + val uncachedReqs = Seq.fill(cacheParams.nMMIOs) { Reg(new HellaCacheReq) } // hit initiation path dataArb.io.in(3).valid := io.cpu.req.valid && isRead(io.cpu.req.bits.cmd) @@ -285,10 +285,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, cacheParams.nMMIOs) 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 +312,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, cacheParams.nMMIOs) + 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 From 4959771c97f48f16737b1ebf31c5ad5e1ff4e99b Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Mon, 27 Mar 2017 15:19:16 -0700 Subject: [PATCH 02/11] Revert "For D$, use source 0 through N-1 for MMIO, not 1 through N" This reverts commit 0538dc77ce8c0d017d8168298c4dcb99034977b7. --- src/main/scala/rocket/DCache.scala | 15 ++++++++------- src/main/scala/rocket/HellaCache.scala | 1 + 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/main/scala/rocket/DCache.scala b/src/main/scala/rocket/DCache.scala index 5f44cb00..480aa9c4 100644 --- a/src/main/scala/rocket/DCache.scala +++ b/src/main/scala/rocket/DCache.scala @@ -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 = Seq.fill(cacheParams.nMMIOs) { RegInit(Bool(false)) } - val uncachedReqs = Seq.fill(cacheParams.nMMIOs) { Reg(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) @@ -251,13 +252,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,7 +286,7 @@ 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, cacheParams.nMMIOs) + val a_sel = UIntToOH(a_source, maxUncachedInFlight+mmioOffset) >> mmioOffset when (tl_out.a.fire()) { when (s2_uncached) { (a_sel.toBools zip (uncachedInFlight zip uncachedReqs)) foreach { case (s, (f, r)) => @@ -312,7 +313,7 @@ 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) { - val d_sel = UIntToOH(tl_out.d.bits.source, cacheParams.nMMIOs) + 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) { @@ -390,7 +391,7 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) { val voluntaryReleaseMessage = if (edge.manager.anySupportAcquireB) { edge.Release( - fromSource = UInt(cacheParams.nMMIOs - 1), + fromSource = UInt(maxUncachedInFlight - 1), toAddress = probe_bits.address, lgSize = lgCacheBlockBytes, shrinkPermissions = s2_shrink_param, diff --git a/src/main/scala/rocket/HellaCache.scala b/src/main/scala/rocket/HellaCache.scala index e9ccfd88..bafd4289 100644 --- a/src/main/scala/rocket/HellaCache.scala +++ b/src/main/scala/rocket/HellaCache.scala @@ -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)") From 75eba294ec4a575d0ad6bf746ef98cd27acb1801 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Mon, 27 Mar 2017 15:21:08 -0700 Subject: [PATCH 03/11] DCache: Release from the correct ID as well --- src/main/scala/rocket/DCache.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/rocket/DCache.scala b/src/main/scala/rocket/DCache.scala index 480aa9c4..1083e5bb 100644 --- a/src/main/scala/rocket/DCache.scala +++ b/src/main/scala/rocket/DCache.scala @@ -391,7 +391,7 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) { val voluntaryReleaseMessage = if (edge.manager.anySupportAcquireB) { edge.Release( - fromSource = UInt(maxUncachedInFlight - 1), + fromSource = UInt(0), toAddress = probe_bits.address, lgSize = lgCacheBlockBytes, shrinkPermissions = s2_shrink_param, From 5b339b6bbdaad6e1599c3738ae598983b6add2ba Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Mon, 27 Mar 2017 15:24:03 -0700 Subject: [PATCH 04/11] tilelink2 Monitor: catch incorrect use of source ID --- src/main/scala/uncore/tilelink2/Monitor.scala | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/scala/uncore/tilelink2/Monitor.scala b/src/main/scala/uncore/tilelink2/Monitor.scala index 626f0817..05e6905f 100644 --- a/src/main/scala/uncore/tilelink2/Monitor.scala +++ b/src/main/scala/uncore/tilelink2/Monitor.scala @@ -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) From ea0714bfcba3546e14cd022faafe8a4c0c27e968 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Sun, 26 Mar 2017 21:56:35 -0700 Subject: [PATCH 05/11] rocket: hard-wire UXL/SXL fields to 0 https://github.com/riscv/riscv-isa-manual/commit/a2a3346e7345619efe3b5e8620d4a87c72d21ad0 --- src/main/scala/rocket/CSR.scala | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/main/scala/rocket/CSR.scala b/src/main/scala/rocket/CSR.scala index 88cff329..ea0c265d 100644 --- a/src/main/scala/rocket/CSR.scala +++ b/src/main/scala/rocket/CSR.scala @@ -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() @@ -363,7 +361,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 @@ -465,8 +462,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 @@ -570,7 +565,7 @@ 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 } From 069858a20ce101310c49900af0da211838931e92 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Sun, 26 Mar 2017 18:18:35 -0700 Subject: [PATCH 06/11] rocket: separate page faults from physical memory access exceptions --- riscv-tools | 2 +- src/main/scala/rocket/CSR.scala | 21 +++++--- src/main/scala/rocket/DCache.scala | 6 ++- src/main/scala/rocket/Frontend.scala | 22 +++++--- src/main/scala/rocket/HellaCache.scala | 1 + src/main/scala/rocket/IBuf.scala | 17 ++++-- src/main/scala/rocket/Instructions.scala | 18 ++++--- src/main/scala/rocket/NBDcache.scala | 6 ++- src/main/scala/rocket/PTW.scala | 20 ++++--- src/main/scala/rocket/Rocket.scala | 12 +++-- src/main/scala/rocket/TLB.scala | 68 +++++++++++++----------- 11 files changed, 120 insertions(+), 73 deletions(-) diff --git a/riscv-tools b/riscv-tools index 4f430b18..89d48702 160000 --- a/riscv-tools +++ b/riscv-tools @@ -1 +1 @@ -Subproject commit 4f430b184ed07890cd30ad144ded6d7cb07dcdf0 +Subproject commit 89d487023c1e59ff574872e2f51ee479cda380ab diff --git a/src/main/scala/rocket/CSR.scala b/src/main/scala/rocket/CSR.scala index ea0c265d..cd028a28 100644 --- a/src/main/scala/rocket/CSR.scala +++ b/src/main/scala/rocket/CSR.scala @@ -119,10 +119,15 @@ object CSR def R = UInt(5,SZ) val ADDRSZ = 12 - def debugIntCause = new MIP().getWidth + def debugIntCause = { + val res = 14 + require(res >= new MIP().getWidth) + res + } def debugTriggerCause = { - require(debugIntCause >= Causes.all.max) - debugIntCause + val res = 14 + require(!(Causes.all contains res)) + res } val firstCtr = CSRs.cycle @@ -224,10 +229,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)) @@ -483,7 +488,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 diff --git a/src/main/scala/rocket/DCache.scala b/src/main/scala/rocket/DCache.scala index 1083e5bb..b8f44c16 100644 --- a/src/main/scala/rocket/DCache.scala +++ b/src/main/scala/rocket/DCache.scala @@ -185,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 diff --git a/src/main/scala/rocket/Frontend.scala b/src/main/scala/rocket/Frontend.scala index 80d3b1e7..80aa8dde 100644 --- a/src/main/scala/rocket/Frontend.scala +++ b/src/main/scala/rocket/Frontend.scala @@ -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 diff --git a/src/main/scala/rocket/HellaCache.scala b/src/main/scala/rocket/HellaCache.scala index bafd4289..2d4f1178 100644 --- a/src/main/scala/rocket/HellaCache.scala +++ b/src/main/scala/rocket/HellaCache.scala @@ -113,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 diff --git a/src/main/scala/rocket/IBuf.scala b/src/main/scala/rocket/IBuf.scala index d81f9a4b..ac50ac10 100644 --- a/src/main/scala/rocket/IBuf.scala +++ b/src/main/scala/rocket/IBuf.scala @@ -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) diff --git a/src/main/scala/rocket/Instructions.scala b/src/main/scala/rocket/Instructions.scala index 5ac87564..81579f57 100644 --- a/src/main/scala/rocket/Instructions.scala +++ b/src/main/scala/rocket/Instructions.scala @@ -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 } } diff --git a/src/main/scala/rocket/NBDcache.scala b/src/main/scala/rocket/NBDcache.scala index 9ec9ec4f..b840f527 100644 --- a/src/main/scala/rocket/NBDcache.scala +++ b/src/main/scala/rocket/NBDcache.scala @@ -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) diff --git a/src/main/scala/rocket/PTW.scala b/src/main/scala/rocket/PTW.scala index cab539ea..edeef24b 100644 --- a/src/main/scala/rocket/PTW.scala +++ b/src/main/scala/rocket/PTW.scala @@ -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 } diff --git a/src/main/scala/rocket/Rocket.scala b/src/main/scala/rocket/Rocket.scala index 51dd8316..03857960 100644 --- a/src/main/scala/rocket/Rocket.scala +++ b/src/main/scala/rocket/Rocket.scala @@ -225,12 +225,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 +425,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 diff --git a/src/main/scala/rocket/TLB.scala b/src/main/scala/rocket/TLB.scala index 51f84459..b2714a35 100644 --- a/src/main/scala/rocket/TLB.scala +++ b/src/main/scala/rocket/TLB.scala @@ -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 @@ -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 From c7c357e71674fc0b5ca018d4ac040ade2cb0b5ce Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Fri, 24 Mar 2017 14:49:12 -0700 Subject: [PATCH 07/11] Add local interrupts to core (but not yet to coreplex) --- chisel3 | 2 +- src/main/scala/rocket/CSR.scala | 31 +++++++++++++++++++--------- src/main/scala/rocket/Rocket.scala | 1 + src/main/scala/tile/Core.scala | 1 + src/main/scala/tile/Interrupts.scala | 1 + 5 files changed, 25 insertions(+), 11 deletions(-) diff --git a/chisel3 b/chisel3 index 3e6ef13f..8e4ddc62 160000 --- a/chisel3 +++ b/chisel3 @@ -1 +1 @@ -Subproject commit 3e6ef13ff5cda2e65efbbf5d306cc101582ad0e5 +Subproject commit 8e4ddc62db448b613ae327792e72defca4d115d4 diff --git a/src/main/scala/rocket/CSR.scala b/src/main/scala/rocket/CSR.scala index cd028a28..30cc1662 100644 --- a/src/main/scala/rocket/CSR.scala +++ b/src/main/scala/rocket/CSR.scala @@ -65,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() @@ -119,13 +124,9 @@ object CSR def R = UInt(5,SZ) val ADDRSZ = 12 - def debugIntCause = { - val res = 14 - require(res >= new MIP().getWidth) - res - } + def debugIntCause = 14 // keep in sync with MIP.debug def debugTriggerCause = { - val res = 14 + val res = debugIntCause require(!(Causes.all contains res)) res } @@ -211,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 @@ -680,7 +691,7 @@ class CSRFile(perfEventSets: EventSets = new EventSets(Seq()))(implicit p: Param } } - reg_mip <> io.interrupts + reg_mip := io.interrupts reg_dcsr.debugint := io.interrupts.debug if (!usingVM) { diff --git a/src/main/scala/rocket/Rocket.scala b/src/main/scala/rocket/Rocket.scala index 03857960..b3bc820c 100644 --- a/src/main/scala/rocket/Rocket.scala +++ b/src/main/scala/rocket/Rocket.scala @@ -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, diff --git a/src/main/scala/tile/Core.scala b/src/main/scala/tile/Core.scala index 3212ac77..a17544e6 100644 --- a/src/main/scala/tile/Core.scala +++ b/src/main/scala/tile/Core.scala @@ -23,6 +23,7 @@ trait CoreParams { val decodeWidth: Int val retireWidth: Int val instBits: Int + val nLocalInterrupts: Int } trait HasCoreParameters extends HasTileParameters { diff --git a/src/main/scala/tile/Interrupts.scala b/src/main/scala/tile/Interrupts.scala index 2b1071e7..00a00663 100644 --- a/src/main/scala/tile/Interrupts.scala +++ b/src/main/scala/tile/Interrupts.scala @@ -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() From d42d8aaea7678e615b6e24aed9173d281a389898 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Mon, 27 Mar 2017 16:35:47 -0700 Subject: [PATCH 08/11] Make SEIP writable --- src/main/scala/rocket/CSR.scala | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/main/scala/rocket/CSR.scala b/src/main/scala/rocket/CSR.scala index 30cc1662..4b85aa44 100644 --- a/src/main/scala/rocket/CSR.scala +++ b/src/main/scala/rocket/CSR.scala @@ -291,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 @@ -430,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) @@ -588,10 +589,15 @@ class CSRFile(perfEventSets: EventSets = new EventSets(Seq()))(implicit p: Param 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 } @@ -691,7 +697,10 @@ class CSRFile(perfEventSets: EventSets = new EventSets(Seq()))(implicit p: Param } } - reg_mip := io.interrupts + reg_mip.lip zip io.interrupts.lip foreach { case (r, i) => r := i } + 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) { @@ -734,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)) From 3fc74f3d080fba084c186b4c367c5ca2a6ed4823 Mon Sep 17 00:00:00 2001 From: Megan Wachs Date: Mon, 27 Mar 2017 17:27:20 -0700 Subject: [PATCH 09/11] Create README_TRAVIS.md --- README_TRAVIS.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 README_TRAVIS.md diff --git a/README_TRAVIS.md b/README_TRAVIS.md new file mode 100644 index 00000000..0eeff8f3 --- /dev/null +++ b/README_TRAVIS.md @@ -0,0 +1,18 @@ +# 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`. + From ab300f798564ec42ac453b56703021550ca92419 Mon Sep 17 00:00:00 2001 From: Megan Wachs Date: Mon, 27 Mar 2017 17:28:04 -0700 Subject: [PATCH 10/11] Update README_TRAVIS.md --- README_TRAVIS.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README_TRAVIS.md b/README_TRAVIS.md index 0eeff8f3..f7c4ac0f 100644 --- a/README_TRAVIS.md +++ b/README_TRAVIS.md @@ -6,8 +6,6 @@ This is because someone committed a PR to `master` which bumped `riscv-tools` an 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`. From 05cbdced78d66be7e8f2491c04641113f008b0c8 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Mon, 27 Mar 2017 17:53:48 -0700 Subject: [PATCH 11/11] Work around zero-entry vec issue in Chisel --- src/main/scala/rocket/CSR.scala | 2 +- src/main/scala/rocket/TLB.scala | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/scala/rocket/CSR.scala b/src/main/scala/rocket/CSR.scala index 4b85aa44..5ff0626a 100644 --- a/src/main/scala/rocket/CSR.scala +++ b/src/main/scala/rocket/CSR.scala @@ -697,7 +697,7 @@ class CSRFile(perfEventSets: EventSets = new EventSets(Seq()))(implicit p: Param } } - reg_mip.lip zip io.interrupts.lip foreach { case (r, i) => r := i } + 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 diff --git a/src/main/scala/rocket/TLB.scala b/src/main/scala/rocket/TLB.scala index b2714a35..de3a90d1 100644 --- a/src/main/scala/rocket/TLB.scala +++ b/src/main/scala/rocket/TLB.scala @@ -99,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) =