├── .gitignore ├── LICENSE.Berkeley ├── LICENSE.Cambridge ├── README.md ├── build.sbt └── src └── main └── scala ├── arbiter.scala ├── btb.scala ├── consts.scala ├── csr.scala ├── decode.scala ├── dma.scala ├── dpath_alu.scala ├── fpu.scala ├── frontend.scala ├── icache.scala ├── idecode.scala ├── instructions.scala ├── multiplier.scala ├── nbdcache.scala ├── package.scala ├── ptw.scala ├── rocc.scala ├── rocket.scala ├── tile.scala ├── tlb.scala └── util.scala /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | -------------------------------------------------------------------------------- /LICENSE.Berkeley: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011-2016, The Regents of the University of California 2 | (Regents). All Rights Reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 1. Redistributions of source code must retain the above copyright 7 | notice, this list of conditions and the following disclaimer. 8 | 2. Redistributions in binary form must reproduce the above copyright 9 | notice, this list of conditions and the following disclaimer in the 10 | documentation and/or other materials provided with the distribution. 11 | 3. Neither the name of the Regents nor the 12 | names of its contributors may be used to endorse or promote products 13 | derived from this software without specific prior written permission. 14 | 15 | IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, 16 | SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING 17 | OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS 18 | BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 19 | 20 | REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 21 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 | PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED 23 | HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE 24 | MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 25 | -------------------------------------------------------------------------------- /LICENSE.Cambridge: -------------------------------------------------------------------------------- 1 | Copyright 2014-2017 University of Cambridge 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Rocket Core 2 | =========== 3 | 4 | Rocket is a 6-stage single-issue in-order pipeline that executes the 64-bit 5 | scalar RISC-V ISA. Rocket implements an MMU that supports page-based virtual 6 | memory and is able to boot modern operating systems such as Linux. Rocket 7 | also has an optional IEEE 754-2008-compliant FPU, which implements both 8 | single- and double-precision floating-point operations, including fused 9 | multiply-add. 10 | 11 | This repository is not intended to be a self-running repository. To 12 | instantiate a Rocket core, please use the Rocket chip generator found in the 13 | rocket-chip git repository. 14 | 15 | The following table compares a 32-bit ARM Cortex-A5 core to a 64-bit RISC-V 16 | Rocket core built in the same TSMC process (40GPLUS). Fourth column is the 17 | ratio of RISC-V Rocket to ARM Cortex-A5. Both use single-instruction-issue, 18 | in-order pipelines, yet the RISC-V core is faster, smaller, and uses less 19 | power. 20 | 21 | ISA/Implementation | ARM Cortex-A5 | RISC-V Rocket | R/A 22 | --- | --- | --- | --- 23 | ISA Register Width | 32 bits | 64 bits | 2 24 | Frequency | >1 GHz | >1 GHz | 1 25 | Dhrystone Performance | 1.57 DMIPS/MHz | 1.72 DMIPS/MHz | 1.1 26 | Area excluding caches | 0.27 mm2 | 0.14 mm2 | 0.5 27 | Area with 16KB caches | 0.53 mm2 | 0.39 mm2 | 0.7 28 | Area Efficiency | 2.96 DMIPS/MHz/mm2 | 4.41 DMIPS/MHz/mm2 | 1.5 29 | Dynamic Power | <0.08 mW/MHz | 0.034 mW/MHz | >= 0.4 30 | -------------------------------------------------------------------------------- /build.sbt: -------------------------------------------------------------------------------- 1 | organization := "edu.berkeley.cs" 2 | 3 | version := "1.2" 4 | 5 | name := "rocket" 6 | 7 | scalaVersion := "2.11.6" 8 | 9 | libraryDependencies ++= (Seq("chisel", "hardfloat", "uncore", "junctions", "cde").map { 10 | dep: String => sys.props.get(dep + "Version") map { "edu.berkeley.cs" %% dep % _ }}).flatten 11 | -------------------------------------------------------------------------------- /src/main/scala/arbiter.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package rocket 4 | 5 | import Chisel._ 6 | import uncore._ 7 | import cde.{Parameters, Field} 8 | import junctions.{ParameterizedBundle, DecoupledHelper} 9 | 10 | class HellaCacheArbiter(n: Int)(implicit p: Parameters) extends Module 11 | { 12 | val io = new Bundle { 13 | val requestor = Vec(n, new HellaCacheIO).flip 14 | val mem = new HellaCacheIO 15 | } 16 | 17 | val s1_id = Reg(UInt()) 18 | val s2_id = Reg(next=s1_id) 19 | 20 | io.mem.invalidate_lr := io.requestor.map(_.invalidate_lr).reduce(_||_) 21 | io.mem.req.valid := io.requestor.map(_.req.valid).reduce(_||_) 22 | io.requestor(0).req.ready := io.mem.req.ready 23 | for (i <- 1 until n) 24 | io.requestor(i).req.ready := io.requestor(i-1).req.ready && !io.requestor(i-1).req.valid 25 | 26 | for (i <- n-1 to 0 by -1) { 27 | val req = io.requestor(i).req 28 | def connect_s0() = { 29 | io.mem.req.bits.cmd := req.bits.cmd 30 | io.mem.req.bits.typ := req.bits.typ 31 | io.mem.req.bits.addr := req.bits.addr 32 | io.mem.req.bits.phys := req.bits.phys 33 | io.mem.req.bits.tag := Cat(req.bits.tag, UInt(i, log2Up(n))) 34 | io.mem.req.bits.pc := (if (p(UseTagMem)) req.bits.pc else UInt(0)) 35 | s1_id := UInt(i) 36 | } 37 | def connect_s1() = { 38 | io.mem.s1_kill := io.requestor(i).s1_kill 39 | io.mem.s1_data := io.requestor(i).s1_data 40 | io.mem.s1_dtag := (if (p(UseTagMem)) io.requestor(i).s1_dtag else UInt(0)) 41 | } 42 | 43 | if (i == n-1) { 44 | connect_s0() 45 | connect_s1() 46 | } else { 47 | when (req.valid) { connect_s0() } 48 | when (s1_id === UInt(i)) { connect_s1() } 49 | } 50 | } 51 | 52 | for (i <- 0 until n) { 53 | val resp = io.requestor(i).resp 54 | val tag_hit = io.mem.resp.bits.tag(log2Up(n)-1,0) === UInt(i) 55 | resp.valid := io.mem.resp.valid && tag_hit 56 | io.requestor(i).xcpt := io.mem.xcpt 57 | io.requestor(i).ordered := io.mem.ordered 58 | io.requestor(i).s2_nack := io.mem.s2_nack && s2_id === UInt(i) 59 | resp.bits := io.mem.resp.bits 60 | resp.bits.tag := io.mem.resp.bits.tag >> log2Up(n) 61 | 62 | io.requestor(i).replay_next := io.mem.replay_next 63 | } 64 | } 65 | 66 | class InOrderArbiter[T <: Data, U <: Data](reqTyp: T, respTyp: U, n: Int) 67 | (implicit p: Parameters) extends Module { 68 | val io = new Bundle { 69 | val in_req = Vec(n, Decoupled(reqTyp)).flip 70 | val in_resp = Vec(n, Decoupled(respTyp)) 71 | val out_req = Decoupled(reqTyp) 72 | val out_resp = Decoupled(respTyp).flip 73 | } 74 | 75 | if (n > 1) { 76 | val route_q = Module(new Queue(UInt(width = log2Up(n)), 2)) 77 | val req_arb = Module(new RRArbiter(reqTyp, n)) 78 | req_arb.io.in <> io.in_req 79 | 80 | val req_helper = DecoupledHelper( 81 | req_arb.io.out.valid, 82 | route_q.io.enq.ready, 83 | io.out_req.ready) 84 | 85 | io.out_req.bits := req_arb.io.out.bits 86 | io.out_req.valid := req_helper.fire(io.out_req.ready) 87 | 88 | route_q.io.enq.bits := req_arb.io.chosen 89 | route_q.io.enq.valid := req_helper.fire(route_q.io.enq.ready) 90 | 91 | req_arb.io.out.ready := req_helper.fire(req_arb.io.out.valid) 92 | 93 | val resp_sel = route_q.io.deq.bits 94 | val resp_ready = io.in_resp(resp_sel).ready 95 | val resp_helper = DecoupledHelper( 96 | resp_ready, 97 | route_q.io.deq.valid, 98 | io.out_resp.valid) 99 | 100 | val resp_valid = resp_helper.fire(resp_ready) 101 | for (i <- 0 until n) { 102 | io.in_resp(i).bits := io.out_resp.bits 103 | io.in_resp(i).valid := resp_valid && resp_sel === UInt(i) 104 | } 105 | 106 | route_q.io.deq.ready := resp_helper.fire(route_q.io.deq.valid) 107 | io.out_resp.ready := resp_helper.fire(io.out_resp.valid) 108 | } else { 109 | io.out_req <> io.in_req.head 110 | io.in_resp.head <> io.out_resp 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/main/scala/btb.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package rocket 4 | 5 | import Chisel._ 6 | import junctions._ 7 | import cde.{Parameters, Field} 8 | import Util._ 9 | 10 | case object BtbKey extends Field[BtbParameters] 11 | 12 | case class BtbParameters( 13 | nEntries: Int = 62, 14 | nRAS: Int = 2, 15 | updatesOutOfOrder: Boolean = false) 16 | 17 | abstract trait HasBtbParameters extends HasCoreParameters { 18 | val matchBits = pgIdxBits 19 | val entries = p(BtbKey).nEntries 20 | val nRAS = p(BtbKey).nRAS 21 | val updatesOutOfOrder = p(BtbKey).updatesOutOfOrder 22 | val nPages = ((1 max(log2Up(entries)))+1)/2*2 // control logic assumes 2 divides pages 23 | val opaqueBits = log2Up(entries) 24 | val nBHT = 1 << log2Up(entries*2) 25 | } 26 | 27 | abstract class BtbModule(implicit val p: Parameters) extends Module with HasBtbParameters 28 | abstract class BtbBundle(implicit val p: Parameters) extends ParameterizedBundle()(p) 29 | with HasBtbParameters 30 | 31 | class RAS(nras: Int) { 32 | def push(addr: UInt): Unit = { 33 | when (count < nras) { count := count + 1 } 34 | val nextPos = Mux(Bool(isPow2(nras)) || pos < nras-1, pos+1, UInt(0)) 35 | stack(nextPos) := addr 36 | pos := nextPos 37 | } 38 | def peek: UInt = stack(pos) 39 | def pop: Unit = when (!isEmpty) { 40 | count := count - 1 41 | pos := Mux(Bool(isPow2(nras)) || pos > 0, pos-1, UInt(nras-1)) 42 | } 43 | def clear: Unit = count := UInt(0) 44 | def isEmpty: Bool = count === UInt(0) 45 | 46 | private val count = Reg(init=UInt(0,log2Up(nras+1))) 47 | private val pos = Reg(init=UInt(0,log2Up(nras))) 48 | private val stack = Reg(Vec(nras, UInt())) 49 | } 50 | 51 | class BHTResp(implicit p: Parameters) extends BtbBundle()(p) { 52 | val history = UInt(width = log2Up(nBHT).max(1)) 53 | val value = UInt(width = 2) 54 | } 55 | 56 | // BHT contains table of 2-bit counters and a global history register. 57 | // The BHT only predicts and updates when there is a BTB hit. 58 | // The global history: 59 | // - updated speculatively in fetch (if there's a BTB hit). 60 | // - on a mispredict, the history register is reset (again, only if BTB hit). 61 | // The counter table: 62 | // - each counter corresponds with the address of the fetch packet ("fetch pc"). 63 | // - updated when a branch resolves (and BTB was a hit for that branch). 64 | // The updating branch must provide its "fetch pc". 65 | class BHT(nbht: Int)(implicit p: Parameters) { 66 | val nbhtbits = log2Up(nbht) 67 | def get(addr: UInt, update: Bool): BHTResp = { 68 | val res = Wire(new BHTResp) 69 | val index = addr(nbhtbits+1,2) ^ history 70 | res.value := table(index) 71 | res.history := history 72 | val taken = res.value(0) 73 | when (update) { history := Cat(taken, history(nbhtbits-1,1)) } 74 | res 75 | } 76 | def update(addr: UInt, d: BHTResp, taken: Bool, mispredict: Bool): Unit = { 77 | val index = addr(nbhtbits+1,2) ^ d.history 78 | table(index) := Cat(taken, (d.value(1) & d.value(0)) | ((d.value(1) | d.value(0)) & taken)) 79 | when (mispredict) { history := Cat(taken, d.history(nbhtbits-1,1)) } 80 | } 81 | 82 | private val table = Mem(nbht, UInt(width = 2)) 83 | val history = Reg(UInt(width = nbhtbits)) 84 | } 85 | 86 | // BTB update occurs during branch resolution (and only on a mispredict). 87 | // - "pc" is what future fetch PCs will tag match against. 88 | // - "br_pc" is the PC of the branch instruction. 89 | class BTBUpdate(implicit p: Parameters) extends BtbBundle()(p) { 90 | val prediction = Valid(new BTBResp) 91 | val pc = UInt(width = vaddrBits) 92 | val target = UInt(width = vaddrBits) 93 | val taken = Bool() 94 | val isJump = Bool() 95 | val isReturn = Bool() 96 | val br_pc = UInt(width = vaddrBits) 97 | } 98 | 99 | // BHT update occurs during branch resolution on all conditional branches. 100 | // - "pc" is what future fetch PCs will tag match against. 101 | class BHTUpdate(implicit p: Parameters) extends BtbBundle()(p) { 102 | val prediction = Valid(new BTBResp) 103 | val pc = UInt(width = vaddrBits) 104 | val taken = Bool() 105 | val mispredict = Bool() 106 | } 107 | 108 | class RASUpdate(implicit p: Parameters) extends BtbBundle()(p) { 109 | val isCall = Bool() 110 | val isReturn = Bool() 111 | val returnAddr = UInt(width = vaddrBits) 112 | val prediction = Valid(new BTBResp) 113 | } 114 | 115 | // - "bridx" is the low-order PC bits of the predicted branch (after 116 | // shifting off the lowest log(inst_bytes) bits off). 117 | // - "mask" provides a mask of valid instructions (instructions are 118 | // masked off by the predicted taken branch from the BTB). 119 | class BTBResp(implicit p: Parameters) extends BtbBundle()(p) { 120 | val taken = Bool() 121 | val mask = Bits(width = fetchWidth) 122 | val bridx = Bits(width = log2Up(fetchWidth)) 123 | val target = UInt(width = vaddrBits) 124 | val entry = UInt(width = opaqueBits) 125 | val bht = new BHTResp 126 | } 127 | 128 | class BTBReq(implicit p: Parameters) extends BtbBundle()(p) { 129 | val addr = UInt(width = vaddrBits) 130 | } 131 | 132 | // fully-associative branch target buffer 133 | // Higher-performance processors may cause BTB updates to occur out-of-order, 134 | // which requires an extra CAM port for updates (to ensure no duplicates get 135 | // placed in BTB). 136 | class BTB(implicit p: Parameters) extends BtbModule { 137 | val io = new Bundle { 138 | val req = Valid(new BTBReq).flip 139 | val resp = Valid(new BTBResp) 140 | val btb_update = Valid(new BTBUpdate).flip 141 | val bht_update = Valid(new BHTUpdate).flip 142 | val ras_update = Valid(new RASUpdate).flip 143 | val invalidate = Bool(INPUT) 144 | } 145 | 146 | val idxValid = Reg(init=UInt(0, entries)) 147 | val idxs = Mem(entries, UInt(width=matchBits)) 148 | val idxPages = Mem(entries, UInt(width=log2Up(nPages))) 149 | val tgts = Mem(entries, UInt(width=matchBits)) 150 | val tgtPages = Mem(entries, UInt(width=log2Up(nPages))) 151 | val pages = Mem(nPages, UInt(width=vaddrBits-matchBits)) 152 | val pageValid = Reg(init=UInt(0, nPages)) 153 | val idxPagesOH = idxPages.map(UIntToOH(_)(nPages-1,0)) 154 | val tgtPagesOH = tgtPages.map(UIntToOH(_)(nPages-1,0)) 155 | 156 | val useRAS = Reg(Vec(entries, Bool())) 157 | val isJump = Reg(Vec(entries, Bool())) 158 | val brIdx = Mem(entries, UInt(width=log2Up(fetchWidth))) 159 | 160 | private def page(addr: UInt) = addr >> matchBits 161 | private def pageMatch(addr: UInt) = { 162 | val p = page(addr) 163 | Vec(pages.map(_ === p)).toBits & pageValid 164 | } 165 | private def tagMatch(addr: UInt, pgMatch: UInt) = { 166 | val idx = addr(matchBits-1,0) 167 | val idxMatch = idxs.map(_ === idx).toBits 168 | val idxPageMatch = idxPagesOH.map(_ & pgMatch).map(_.orR).toBits 169 | idxValid & idxMatch & idxPageMatch 170 | } 171 | 172 | val r_btb_update = Pipe(io.btb_update) 173 | val update_target = io.req.bits.addr 174 | 175 | val pageHit = pageMatch(io.req.bits.addr) 176 | val hits = tagMatch(io.req.bits.addr, pageHit) 177 | val updatePageHit = pageMatch(r_btb_update.bits.pc) 178 | val updateHits = tagMatch(r_btb_update.bits.pc, updatePageHit) 179 | 180 | val updateHit = r_btb_update.bits.prediction.valid 181 | val nextRepl = Counter(r_btb_update.valid && !updateHit, entries)._1 182 | 183 | val useUpdatePageHit = updatePageHit.orR 184 | val doIdxPageRepl = !useUpdatePageHit 185 | val idxPageRepl = Wire(UInt(width = nPages)) 186 | val idxPageUpdateOH = Mux(useUpdatePageHit, updatePageHit, idxPageRepl) 187 | val idxPageUpdate = OHToUInt(idxPageUpdateOH) 188 | val idxPageReplEn = Mux(doIdxPageRepl, idxPageRepl, UInt(0)) 189 | 190 | val samePage = page(r_btb_update.bits.pc) === page(update_target) 191 | val usePageHit = (pageHit & ~idxPageReplEn).orR 192 | val doTgtPageRepl = !samePage && !usePageHit 193 | val tgtPageRepl = Mux(samePage, idxPageUpdateOH, idxPageUpdateOH(nPages-2,0) << 1 | idxPageUpdateOH(nPages-1)) 194 | val tgtPageUpdate = OHToUInt(Mux(usePageHit, pageHit, tgtPageRepl)) 195 | val tgtPageReplEn = Mux(doTgtPageRepl, tgtPageRepl, UInt(0)) 196 | val doPageRepl = doIdxPageRepl || doTgtPageRepl 197 | 198 | val pageReplEn = idxPageReplEn | tgtPageReplEn 199 | idxPageRepl := UIntToOH(Counter(r_btb_update.valid && doPageRepl, nPages)._1) 200 | 201 | when (r_btb_update.valid) { 202 | assert(io.req.bits.addr === r_btb_update.bits.target, "BTB request != I$ target") 203 | 204 | val waddr = 205 | if (updatesOutOfOrder) Mux(updateHits.orR, OHToUInt(updateHits), nextRepl) 206 | else Mux(updateHit, r_btb_update.bits.prediction.bits.entry, nextRepl) 207 | 208 | // invalidate entries if we stomp on pages they depend upon 209 | val invalidateMask = Vec.tabulate(entries)(i => (pageReplEn & (idxPagesOH(i) | tgtPagesOH(i))).orR).toBits 210 | val validateMask = UIntToOH(waddr) 211 | idxValid := (idxValid & ~invalidateMask) | validateMask 212 | 213 | idxs(waddr) := r_btb_update.bits.pc 214 | tgts(waddr) := update_target 215 | idxPages(waddr) := idxPageUpdate 216 | tgtPages(waddr) := tgtPageUpdate 217 | useRAS(waddr) := r_btb_update.bits.isReturn 218 | isJump(waddr) := r_btb_update.bits.isJump 219 | if (fetchWidth == 1) { 220 | brIdx(waddr) := UInt(0) 221 | } else { 222 | brIdx(waddr) := r_btb_update.bits.br_pc >> log2Up(coreInstBytes) 223 | } 224 | 225 | require(nPages % 2 == 0) 226 | val idxWritesEven = (idxPageUpdateOH & Fill(nPages/2, UInt(1,2))).orR 227 | 228 | def writeBank(i: Int, mod: Int, en: Bool, data: UInt) = 229 | for (i <- i until nPages by mod) 230 | when (en && pageReplEn(i)) { pages(i) := data } 231 | 232 | writeBank(0, 2, Mux(idxWritesEven, doIdxPageRepl, doTgtPageRepl), 233 | Mux(idxWritesEven, page(r_btb_update.bits.pc), page(update_target))) 234 | writeBank(1, 2, Mux(idxWritesEven, doTgtPageRepl, doIdxPageRepl), 235 | Mux(idxWritesEven, page(update_target), page(r_btb_update.bits.pc))) 236 | 237 | when (doPageRepl) { pageValid := pageValid | pageReplEn } 238 | } 239 | 240 | when (io.invalidate) { 241 | idxValid := 0 242 | pageValid := 0 243 | } 244 | 245 | io.resp.valid := hits.orR 246 | io.resp.bits.taken := io.resp.valid 247 | io.resp.bits.target := Cat(Mux1H(Mux1H(hits, tgtPagesOH), pages), Mux1H(hits, tgts)) 248 | io.resp.bits.entry := OHToUInt(hits) 249 | io.resp.bits.bridx := brIdx(io.resp.bits.entry) 250 | if (fetchWidth == 1) { 251 | io.resp.bits.mask := UInt(1) 252 | } else { 253 | // note: btb_resp is clock gated, so the mask is only relevant for the io.resp.valid case 254 | io.resp.bits.mask := Mux(io.resp.bits.taken, Cat((UInt(1) << brIdx(io.resp.bits.entry))-1, UInt(1)).toSInt, 255 | SInt(-1)).toUInt 256 | } 257 | 258 | if (nBHT > 0) { 259 | val bht = new BHT(nBHT) 260 | val isBranch = !Mux1H(hits, isJump) 261 | val res = bht.get(io.req.bits.addr, io.req.valid && io.resp.valid && isBranch) 262 | val update_btb_hit = io.bht_update.bits.prediction.valid 263 | when (io.bht_update.valid && update_btb_hit) { 264 | bht.update(io.bht_update.bits.pc, io.bht_update.bits.prediction.bits.bht, io.bht_update.bits.taken, io.bht_update.bits.mispredict) 265 | } 266 | when (!res.value(0) && isBranch) { io.resp.bits.taken := false } 267 | io.resp.bits.bht := res 268 | } 269 | 270 | if (nRAS > 0) { 271 | val ras = new RAS(nRAS) 272 | val doPeek = Mux1H(hits, useRAS) 273 | when (!ras.isEmpty && doPeek) { 274 | io.resp.bits.target := ras.peek 275 | } 276 | when (io.ras_update.valid) { 277 | when (io.ras_update.bits.isCall) { 278 | ras.push(io.ras_update.bits.returnAddr) 279 | when (doPeek) { 280 | io.resp.bits.target := io.ras_update.bits.returnAddr 281 | } 282 | }.elsewhen (io.ras_update.bits.isReturn && io.ras_update.bits.prediction.valid) { 283 | ras.pop 284 | } 285 | } 286 | when (io.invalidate) { ras.clear } 287 | } 288 | } 289 | -------------------------------------------------------------------------------- /src/main/scala/consts.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package rocket 4 | package constants 5 | 6 | import Chisel._ 7 | import scala.math._ 8 | 9 | trait ScalarOpConstants { 10 | val SZ_BR = 3 11 | val BR_X = BitPat("b???") 12 | val BR_EQ = UInt(0, 3) 13 | val BR_NE = UInt(1, 3) 14 | val BR_J = UInt(2, 3) 15 | val BR_N = UInt(3, 3) 16 | val BR_LT = UInt(4, 3) 17 | val BR_GE = UInt(5, 3) 18 | val BR_LTU = UInt(6, 3) 19 | val BR_GEU = UInt(7, 3) 20 | 21 | val A1_X = BitPat("b??") 22 | val A1_ZERO = UInt(0, 2) 23 | val A1_RS1 = UInt(1, 2) 24 | val A1_PC = UInt(2, 2) 25 | val A1_RS1_T = UInt(3, 2) 26 | 27 | val IMM_X = BitPat("b???") 28 | val IMM_S = UInt(0, 3) 29 | val IMM_SB = UInt(1, 3) 30 | val IMM_U = UInt(2, 3) 31 | val IMM_UJ = UInt(3, 3) 32 | val IMM_I = UInt(4, 3) 33 | val IMM_Z = UInt(5, 3) 34 | 35 | val A2_X = BitPat("b??") 36 | val A2_ZERO = UInt(0, 2) 37 | val A2_FOUR = UInt(1, 2) 38 | val A2_RS2 = UInt(2, 2) 39 | val A2_IMM = UInt(3, 2) 40 | 41 | val X = BitPat("b?") 42 | val N = BitPat("b0") 43 | val Y = BitPat("b1") 44 | 45 | val SZ_DW = 1 46 | val DW_X = BitPat("b?") 47 | val DW_32 = N 48 | val DW_64 = Y 49 | val DW_XPR = Y 50 | } 51 | -------------------------------------------------------------------------------- /src/main/scala/csr.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package rocket 4 | 5 | import Chisel._ 6 | import Util._ 7 | import Instructions._ 8 | import junctions._ 9 | import cde.{Parameters, Field} 10 | import uncore._ 11 | import scala.math._ 12 | import junctions.AddrHashMap 13 | 14 | class MStatus extends Bundle { 15 | val prv = UInt(width = PRV.SZ) // not truly part of mstatus, but convenient 16 | val sd = Bool() 17 | val zero3 = UInt(width = 31) 18 | val sd_rv32 = Bool() 19 | val zero2 = UInt(width = 2) 20 | val vm = UInt(width = 5) 21 | val zero1 = UInt(width = 4) 22 | val mxr = Bool() 23 | val pum = Bool() 24 | val mprv = Bool() 25 | val xs = UInt(width = 2) 26 | val fs = UInt(width = 2) 27 | val mpp = UInt(width = 2) 28 | val hpp = UInt(width = 2) 29 | val spp = UInt(width = 1) 30 | val mpie = Bool() 31 | val hpie = Bool() 32 | val spie = Bool() 33 | val upie = Bool() 34 | val mie = Bool() 35 | val hie = Bool() 36 | val sie = Bool() 37 | val uie = Bool() 38 | } 39 | 40 | class MIP extends Bundle { 41 | val irq = Bool() 42 | val rocc = Bool() 43 | val meip = Bool() 44 | val heip = Bool() 45 | val seip = Bool() 46 | val ueip = Bool() 47 | val mtip = Bool() 48 | val htip = Bool() 49 | val stip = Bool() 50 | val utip = Bool() 51 | val msip = Bool() 52 | val hsip = Bool() 53 | val ssip = Bool() 54 | val usip = Bool() 55 | } 56 | 57 | object PRV 58 | { 59 | val SZ = 2 60 | val U = 0 61 | val S = 1 62 | val H = 2 63 | val M = 3 64 | } 65 | 66 | object CSR 67 | { 68 | // commands 69 | val SZ = 3 70 | val X = BitPat.DC(SZ) 71 | val N = UInt(0,SZ) 72 | val W = UInt(1,SZ) 73 | val S = UInt(2,SZ) 74 | val C = UInt(3,SZ) 75 | val I = UInt(4,SZ) 76 | val R = UInt(5,SZ) 77 | 78 | val ADDRSZ = 12 79 | } 80 | 81 | class TagCtrlSig(implicit p: Parameters) extends CoreBundle { 82 | val maskFetchChck = Bits(width = tgInstBits) 83 | val maskJmpProp = Bits(width = tgBits) 84 | val maskJmpChck = Bits(width = tgBits) 85 | val maskCFlowIndirBranchTgt = Bits(width = tgInstBits) 86 | val maskCFlowDirBranchTgt = Bits(width = tgInstBits) 87 | val maskStoreKeep = Bits(width = tgBits) 88 | val maskStoreProp = Bits(width = tgBits) 89 | val maskStoreChck = Bits(width = tgBits) 90 | val maskLoadProp = Bits(width = tgBits) 91 | val maskLoadChck = Bits(width = tgBits) 92 | val maskALUProp = Bits(width = tgBits) 93 | val maskALUChck = Bits(width = tgBits) 94 | } 95 | 96 | class CSRFileIO(implicit p: Parameters) extends CoreBundle { 97 | val prci = new PRCITileIO().flip 98 | val rw = new Bundle { 99 | val addr = UInt(INPUT, CSR.ADDRSZ) 100 | val cmd = Bits(INPUT, CSR.SZ) 101 | val rdata = Bits(OUTPUT, xLen) 102 | val rtag = Bits(OUTPUT, tgBits) 103 | val wdata = Bits(INPUT, xLen) 104 | val wtag = Bits(INPUT, tgBits) 105 | } 106 | 107 | val csr_stall = Bool(OUTPUT) 108 | val csr_xcpt = Bool(OUTPUT) 109 | val eret = Bool(OUTPUT) 110 | 111 | val prv = UInt(OUTPUT, PRV.SZ) 112 | val status = new MStatus().asOutput 113 | val ptbr = UInt(OUTPUT, paddrBits) 114 | val evec = UInt(OUTPUT, vaddrBitsExtended) 115 | val evec_tag = UInt(OUTPUT, tgBits) 116 | val exception = Bool(INPUT) 117 | val retire = UInt(INPUT, log2Up(1+retireWidth)) 118 | val uarch_counters = Vec(16, UInt(INPUT, log2Up(1+retireWidth))) 119 | val custom_mrw_csrs = Vec(nCustomMrwCsrs, UInt(INPUT, xLen)) 120 | val cause = UInt(INPUT, xLen) 121 | val pc = UInt(INPUT, vaddrBitsExtended) 122 | val pc_tag = UInt(INPUT, tgBits) 123 | val fatc = Bool(OUTPUT) 124 | val time = UInt(OUTPUT, xLen) 125 | val fcsr_rm = Bits(OUTPUT, FPConstants.RM_SZ) 126 | val fcsr_flags = Valid(Bits(width = FPConstants.FLAGS_SZ)).flip 127 | val rocc = new RoCCInterface().flip 128 | val interrupt = Bool(OUTPUT) 129 | val interrupt_cause = UInt(OUTPUT, xLen) 130 | val irq = Bool(INPUT) 131 | 132 | val tag_ctrl = new TagCtrlSig().asOutput 133 | } 134 | 135 | class CSRFile(id:Int)(implicit p: Parameters) extends CoreModule()(p) 136 | { 137 | val io = new CSRFileIO 138 | 139 | val reset_mstatus = Wire(init=new MStatus().fromBits(0)) 140 | reset_mstatus.mpp := PRV.M 141 | reset_mstatus.prv := PRV.M 142 | val reg_mstatus = Reg(init=reset_mstatus) 143 | 144 | val (supported_interrupts, delegable_interrupts) = { 145 | val sup = Wire(init=new MIP().fromBits(0)) 146 | sup.ssip := Bool(p(UseVM)) 147 | sup.msip := true 148 | sup.stip := Bool(p(UseVM)) 149 | sup.mtip := true 150 | sup.meip := true 151 | sup.seip := Bool(p(UseVM)) 152 | sup.rocc := usingRoCC 153 | sup.irq := true 154 | 155 | val del = Wire(init=sup) 156 | del.msip := false 157 | del.mtip := false 158 | del.meip := false 159 | 160 | (sup.toBits, del.toBits) 161 | } 162 | val delegable_exceptions = UInt(Seq( 163 | Causes.misaligned_fetch, 164 | Causes.fault_fetch, 165 | Causes.breakpoint, 166 | Causes.fault_load, 167 | Causes.fault_store, 168 | Causes.user_ecall, 169 | Causes.tag_check_failure).map(1 << _).sum) 170 | 171 | val reg_mie = Reg(init=UInt(0, xLen)) 172 | val reg_mideleg = Reg(init=UInt(0, xLen)) 173 | val reg_medeleg = Reg(init=UInt(0, xLen)) 174 | val reg_mip = Reg(new MIP) 175 | val reg_mepc = Reg(UInt(width = vaddrBitsExtended)) 176 | val reg_mepc_tag = Reg(init=UInt(0, tgBits)) 177 | val reg_mcause = Reg(Bits(width = xLen)) 178 | val reg_mbadaddr = Reg(UInt(width = vaddrBitsExtended)) 179 | val reg_mscratch = Reg(Bits(width = xLen)) 180 | val reg_mscratch_tag = Reg(Bits(width = tgBits)) 181 | val reg_mtvec = Reg(init=UInt(p(MtvecInit), paddrBits min xLen)) 182 | val reg_mtvec_tag = Reg(init=UInt(0, tgBits)) 183 | val reg_mucounteren = Reg(init=UInt(0, 32)) 184 | val reg_mscounteren = Reg(UInt(0, 32)) 185 | 186 | val reg_sepc = Reg(UInt(width = vaddrBitsExtended)) 187 | val reg_sepc_tag = Reg(init=UInt(0, tgBits)) 188 | val reg_scause = Reg(Bits(width = xLen)) 189 | val reg_sbadaddr = Reg(UInt(width = vaddrBitsExtended)) 190 | val reg_sscratch = Reg(Bits(width = xLen)) 191 | val reg_sscratch_tag = Reg(Bits(width = tgBits)) 192 | val reg_stvec = Reg(UInt(width = vaddrBits)) 193 | val reg_stvec_tag = Reg(init=UInt(0, tgBits)) 194 | val reg_sptbr = Reg(UInt(width = ppnBits)) 195 | val reg_wfi = Reg(init=Bool(false)) 196 | 197 | val reg_uarch_counters = io.uarch_counters.map(WideCounter(xLen, _)) 198 | val reg_fflags = Reg(UInt(width = 5)) 199 | val reg_frm = Reg(UInt(width = 3)) 200 | 201 | val reg_instret = WideCounter(64, io.retire) 202 | val reg_cycle = if (enableCommitLog) reg_instret else WideCounter(64) 203 | 204 | val reg_tagctrl = Reg(init=UInt(0, xLen)) 205 | val reg_mutagctrlen = Reg(init = ~UInt(0, xLen)) 206 | val reg_mstagctrlen = Reg(init = ~UInt(0, xLen)) 207 | 208 | val mip = Wire(init=reg_mip) 209 | mip.irq := io.irq 210 | mip.rocc := io.rocc.interrupt 211 | val read_mip = mip.toBits & supported_interrupts 212 | 213 | val pending_interrupts = read_mip & reg_mie 214 | val m_interrupts = Mux(reg_mstatus.prv < PRV.M || (reg_mstatus.prv === PRV.M && reg_mstatus.mie), pending_interrupts & ~reg_mideleg, UInt(0)) 215 | val s_interrupts = Mux(reg_mstatus.prv < PRV.S || (reg_mstatus.prv === PRV.S && reg_mstatus.sie), pending_interrupts & reg_mideleg, UInt(0)) 216 | val all_interrupts = m_interrupts | s_interrupts 217 | io.interrupt := all_interrupts.orR 218 | io.interrupt_cause := (io.interrupt << (xLen-1)) + PriorityEncoder(all_interrupts) 219 | 220 | val system_insn = io.rw.cmd === CSR.I 221 | val cpu_ren = io.rw.cmd =/= CSR.N && !system_insn 222 | 223 | val isa_string = "IMA" + 224 | (if (usingVM) "S" else "") + 225 | (if (usingFPU) "FD" else "") + 226 | (if (usingRoCC) "X" else "") 227 | val isa = ((if (xLen == 32) BigInt(0) else BigInt(2)) << (xLen-2)) | 228 | isa_string.map(x => 1 << (x - 'A')).reduce(_|_) 229 | val read_mstatus = io.status.toBits()(xLen-1,0) 230 | 231 | val read_mapping = collection.mutable.LinkedHashMap[Int,(Bits, Bits)]( 232 | CSRs.mimpid -> (UInt(2), UInt(0) ), // open-source but not UCB repos 233 | CSRs.marchid -> (UInt(0), UInt(0) ), 234 | CSRs.mvendorid -> (UInt(0), UInt(0) ), 235 | CSRs.mcycle -> (reg_cycle, UInt(0) ), 236 | CSRs.minstret -> (reg_instret, UInt(0) ), 237 | CSRs.mucounteren -> (UInt(0), UInt(0) ), 238 | CSRs.mutime_delta -> (UInt(0), UInt(0) ), 239 | CSRs.mucycle_delta -> (UInt(0), UInt(0) ), 240 | CSRs.muinstret_delta -> (UInt(0), UInt(0) ), 241 | CSRs.misa -> (UInt(isa), UInt(0) ), 242 | CSRs.mstatus -> (read_mstatus, UInt(0) ), 243 | CSRs.mtvec -> (reg_mtvec, reg_mtvec_tag ), 244 | CSRs.mip -> (read_mip, UInt(0) ), 245 | CSRs.mie -> (reg_mie, UInt(0) ), 246 | CSRs.mideleg -> (reg_mideleg, UInt(0) ), 247 | CSRs.medeleg -> (reg_medeleg, UInt(0) ), 248 | CSRs.mscratch -> (reg_mscratch, reg_mscratch_tag ), 249 | CSRs.mepc -> (reg_mepc.sextTo(xLen), 250 | reg_mepc_tag ), 251 | CSRs.mbadaddr -> (reg_mbadaddr.sextTo(xLen), 252 | UInt(0) ), 253 | CSRs.mcause -> (reg_mcause, UInt(0) ), 254 | CSRs.mhartid -> (UInt(id), UInt(0) ), 255 | CSRs.swtrace -> (UInt(0), UInt(0) )) 256 | 257 | if (usingFPU) { 258 | read_mapping += CSRs.fflags -> (reg_fflags, UInt(0)) 259 | read_mapping += CSRs.frm -> (reg_frm, UInt(0)) 260 | read_mapping += CSRs.fcsr -> (Cat(reg_frm, reg_fflags), UInt(0)) 261 | } 262 | 263 | if (usingVM) { 264 | val read_sie = reg_mie & reg_mideleg 265 | val read_sip = read_mip & reg_mideleg 266 | val read_sstatus = Wire(init=io.status) 267 | read_sstatus.vm := 0 268 | read_sstatus.mprv := 0 269 | read_sstatus.mpp := 0 270 | read_sstatus.hpp := 0 271 | read_sstatus.mpie := 0 272 | read_sstatus.hpie := 0 273 | read_sstatus.mie := 0 274 | read_sstatus.hie := 0 275 | 276 | read_mapping += CSRs.sstatus -> ((read_sstatus.toBits())(xLen-1,0), 277 | UInt(0) ) 278 | read_mapping += CSRs.sip -> (read_sip.toBits, UInt(0) ) 279 | read_mapping += CSRs.sie -> (read_sie.toBits, UInt(0) ) 280 | read_mapping += CSRs.sscratch -> (reg_sscratch, reg_sscratch_tag ) 281 | read_mapping += CSRs.scause -> (reg_scause, UInt(0) ) 282 | read_mapping += CSRs.sbadaddr -> (reg_sbadaddr.sextTo(xLen), UInt(0) ) 283 | read_mapping += CSRs.sptbr -> (reg_sptbr, UInt(0) ) 284 | read_mapping += CSRs.sasid -> (UInt(0), UInt(0) ) 285 | read_mapping += CSRs.sepc -> (reg_sepc.sextTo(xLen), reg_sepc_tag ) 286 | read_mapping += CSRs.stvec -> (reg_stvec.sextTo(xLen), reg_stvec_tag ) 287 | read_mapping += CSRs.mscounteren -> (reg_mscounteren, UInt(0) ) 288 | read_mapping += CSRs.mstime_delta -> (UInt(0), UInt(0) ) 289 | read_mapping += CSRs.mscycle_delta -> (UInt(0), UInt(0) ) 290 | read_mapping += CSRs.msinstret_delta -> (UInt(0), UInt(0) ) 291 | read_mapping += CSRs.cycle -> (reg_cycle, UInt(0) ) 292 | read_mapping += CSRs.instret -> (reg_instret, UInt(0) ) 293 | } 294 | 295 | if (usingVM) { // should be usingUser 296 | read_mapping += CSRs.cycle -> (reg_cycle, UInt(0) ) 297 | read_mapping += CSRs.time -> (reg_cycle, UInt(0) ) // should be a memory mapped register mtime 298 | read_mapping += CSRs.instret -> (reg_instret, UInt(0) ) 299 | } 300 | 301 | if (useTagMem) { 302 | read_mapping += CSRs.utagctrl -> (reg_tagctrl, UInt(0) ) 303 | read_mapping += CSRs.stagctrl -> (reg_tagctrl, UInt(0) ) 304 | read_mapping += CSRs.mtagctrl -> (reg_tagctrl, UInt(0) ) 305 | read_mapping += CSRs.mutagctrlen -> (reg_mutagctrlen, UInt(0) ) 306 | read_mapping += CSRs.mstagctrlen -> (reg_mstagctrlen, UInt(0) ) 307 | } 308 | 309 | if (xLen == 32) { 310 | read_mapping += CSRs.mcycleh -> ((reg_cycle >> 32), UInt(0) ) 311 | read_mapping += CSRs.minstreth -> ((reg_instret >> 32), UInt(0) ) 312 | read_mapping += CSRs.mutime_deltah -> (UInt(0), UInt(0) ) 313 | read_mapping += CSRs.mucycle_deltah -> (UInt(0), UInt(0) ) 314 | read_mapping += CSRs.muinstret_deltah -> (UInt(0), UInt(0) ) 315 | if (usingVM) { 316 | read_mapping += CSRs.mstime_deltah -> (UInt(0), UInt(0) ) 317 | read_mapping += CSRs.mscycle_deltah -> (UInt(0), UInt(0) ) 318 | read_mapping += CSRs.msinstret_deltah -> (UInt(0), UInt(0) ) 319 | } 320 | } 321 | 322 | for (i <- 0 until nCustomMrwCsrs) { 323 | val addr = 0xff0 + i 324 | require(addr < (1 << CSR.ADDRSZ)) 325 | require(!read_mapping.contains(addr), "custom MRW CSR address " + i + " is already in use") 326 | read_mapping += addr -> (io.custom_mrw_csrs(i), UInt(0) ) 327 | } 328 | 329 | for ((addr, i) <- roccCsrs.zipWithIndex) { 330 | require(!read_mapping.contains(addr), "RoCC: CSR address " + addr + " is already in use") 331 | read_mapping += addr -> (io.rocc.csr.rdata(i), UInt(0) ) 332 | } 333 | 334 | val decoded_addr = read_mapping map { case (k, (v, _)) => k -> (io.rw.addr === k) } 335 | 336 | val addr_valid = decoded_addr.values.reduce(_||_) 337 | val fp_csr = 338 | if (usingFPU) decoded_addr(CSRs.fflags) || decoded_addr(CSRs.frm) || decoded_addr(CSRs.fcsr) 339 | else Bool(false) 340 | val hpm_csr = if (usingVM) io.rw.addr >= CSRs.cycle && io.rw.addr < CSRs.cycle + 3 else Bool(false) 341 | val hpm_en = reg_mstatus.prv === PRV.M || 342 | (reg_mstatus.prv === PRV.S && reg_mscounteren(io.rw.addr(7, 0))) || 343 | (reg_mstatus.prv === PRV.U && reg_mucounteren(io.rw.addr(7, 0))) 344 | val csr_addr_priv = io.rw.addr(9,8) 345 | val priv_sufficient = reg_mstatus.prv >= csr_addr_priv 346 | val read_only = io.rw.addr(11,10).andR 347 | val cpu_wen = cpu_ren && io.rw.cmd =/= CSR.R && priv_sufficient 348 | val wen = cpu_wen && !read_only 349 | val wdata = Mux(io.rw.cmd === CSR.S, io.rw.rdata | io.rw.wdata, 350 | Mux(io.rw.cmd === CSR.C, io.rw.rdata & ~io.rw.wdata, 351 | io.rw.wdata)) 352 | val wtag = io.rw.wtag 353 | 354 | val do_system_insn = priv_sufficient && system_insn 355 | val opcode = UInt(1) << io.rw.addr(2,0) 356 | val insn_call = do_system_insn && opcode(0) 357 | val insn_break = do_system_insn && opcode(1) 358 | val insn_ret = do_system_insn && opcode(2) 359 | val insn_sfence_vm = do_system_insn && opcode(4) 360 | val insn_wfi = do_system_insn && opcode(5) 361 | 362 | val csr_xcpt = (cpu_wen && read_only) || 363 | (cpu_ren && (!priv_sufficient || !addr_valid || (hpm_csr && !hpm_en) || (fp_csr && !io.status.fs.orR))) | 364 | (system_insn && !priv_sufficient) || 365 | insn_call || insn_break 366 | 367 | when (insn_wfi) { reg_wfi := true } 368 | when (read_mip.orR) { reg_wfi := false } 369 | 370 | val cause = 371 | Mux(!csr_xcpt, io.cause, 372 | Mux(insn_call, reg_mstatus.prv + Causes.user_ecall, 373 | Mux[UInt](insn_break, Causes.breakpoint, Causes.illegal_instruction))) 374 | val cause_lsbs = cause(log2Up(xLen)-1,0) 375 | val delegate = Bool(p(UseVM)) && reg_mstatus.prv < PRV.M && Mux(cause(xLen-1), reg_mideleg(cause_lsbs), reg_medeleg(cause_lsbs)) 376 | val tvec = Mux(delegate, reg_stvec.sextTo(vaddrBitsExtended), reg_mtvec) 377 | val tvec_tag = Mux(delegate, reg_stvec_tag, reg_mtvec_tag) 378 | val epc = Mux(Bool(p(UseVM)) && !csr_addr_priv(1), reg_sepc, reg_mepc) 379 | val epc_tag = Mux(Bool(p(UseVM)) && !csr_addr_priv(1), reg_sepc_tag, reg_mepc_tag) 380 | io.fatc := insn_sfence_vm 381 | io.evec := Mux(io.exception || csr_xcpt, tvec, epc) 382 | io.evec_tag := Mux(io.exception || csr_xcpt, tvec_tag, epc_tag) 383 | io.ptbr := reg_sptbr 384 | io.csr_xcpt := csr_xcpt 385 | io.eret := insn_ret 386 | io.status := reg_mstatus 387 | io.status.sd := io.status.fs.andR || io.status.xs.andR 388 | if (xLen == 32) 389 | io.status.sd_rv32 := io.status.sd 390 | 391 | when (io.exception || csr_xcpt) { 392 | def compressVAddr(addr: UInt) = 393 | if (vaddrBitsExtended == vaddrBits) addr 394 | else { 395 | val (upper, lower) = Split(addr, vaddrBits) 396 | val sign = Mux(lower.toSInt < SInt(0), upper.andR, upper.orR) 397 | Cat(sign, lower) 398 | } 399 | val ldst = 400 | cause === Causes.fault_load || cause === Causes.misaligned_load || 401 | cause === Causes.fault_store || cause === Causes.misaligned_store 402 | val badaddr = Mux(ldst, compressVAddr(io.rw.wdata), io.pc) 403 | val epc = ~(~io.pc | (coreInstBytes-1)) 404 | val epc_tag = io.pc_tag 405 | val pie = read_mstatus(reg_mstatus.prv) 406 | 407 | when (delegate) { 408 | reg_sepc := epc 409 | reg_sepc_tag := epc_tag 410 | reg_scause := cause 411 | reg_sbadaddr := badaddr 412 | reg_mstatus.spie := pie 413 | reg_mstatus.spp := reg_mstatus.prv 414 | reg_mstatus.sie := false 415 | reg_mstatus.prv := PRV.S 416 | }.otherwise { 417 | reg_mepc := epc 418 | reg_mepc_tag := epc_tag 419 | reg_mcause := cause 420 | reg_mbadaddr := badaddr 421 | reg_mstatus.mpie := pie 422 | reg_mstatus.mpp := reg_mstatus.prv 423 | reg_mstatus.mie := false 424 | reg_mstatus.prv := PRV.M 425 | } 426 | } 427 | 428 | when (insn_ret) { 429 | when (Bool(p(UseVM)) && !csr_addr_priv(1)) { 430 | when (reg_mstatus.spp.toBool) { reg_mstatus.sie := reg_mstatus.spie } 431 | reg_mstatus.spie := false 432 | reg_mstatus.spp := PRV.U 433 | reg_mstatus.prv := reg_mstatus.spp 434 | }.otherwise { 435 | when (reg_mstatus.mpp(1)) { reg_mstatus.mie := reg_mstatus.mpie } 436 | when (reg_mstatus.mpp(0)) { reg_mstatus.sie := reg_mstatus.mpie } 437 | reg_mstatus.mpie := false 438 | reg_mstatus.mpp := PRV.U 439 | reg_mstatus.prv := reg_mstatus.mpp 440 | } 441 | } 442 | 443 | assert(PopCount(insn_ret :: io.exception :: csr_xcpt :: Nil) <= 1, "these conditions must be mutually exclusive") 444 | 445 | io.time := reg_cycle 446 | io.csr_stall := reg_wfi 447 | 448 | io.rw.rdata := Mux1H(for ((k, (v, _)) <- read_mapping) yield decoded_addr(k) -> v) 449 | io.rw.rtag := Mux1H(for ((k, (_, v)) <- read_mapping) yield decoded_addr(k) -> v) 450 | 451 | io.fcsr_rm := reg_frm 452 | when (io.fcsr_flags.valid) { 453 | reg_fflags := reg_fflags | io.fcsr_flags.bits 454 | } 455 | 456 | when (wen) { 457 | when (decoded_addr(CSRs.mstatus)) { 458 | val new_mstatus = new MStatus().fromBits(wdata) 459 | reg_mstatus.mie := new_mstatus.mie 460 | reg_mstatus.mpie := new_mstatus.mpie 461 | 462 | val supportedModes = Vec((PRV.M :: PRV.U :: (if (usingVM) List(PRV.S) else Nil)).map(UInt(_))) 463 | if (supportedModes.size > 1) { 464 | reg_mstatus.mprv := new_mstatus.mprv 465 | when (supportedModes contains new_mstatus.mpp) { reg_mstatus.mpp := new_mstatus.mpp } 466 | if (supportedModes.size > 2) { 467 | reg_mstatus.mxr := new_mstatus.mxr 468 | reg_mstatus.pum := new_mstatus.pum 469 | reg_mstatus.spp := new_mstatus.spp 470 | reg_mstatus.spie := new_mstatus.spie 471 | reg_mstatus.sie := new_mstatus.sie 472 | } 473 | } 474 | 475 | if (usingVM) { 476 | require(if (xLen == 32) pgLevels == 2 else pgLevels > 2 && pgLevels < 6) 477 | val vm_on = 6 + pgLevels // TODO Sv48 support should imply Sv39 support 478 | when (new_mstatus.vm === 0) { reg_mstatus.vm := 0 } 479 | when (new_mstatus.vm === vm_on) { reg_mstatus.vm := vm_on } 480 | } 481 | if (usingVM || usingFPU) reg_mstatus.fs := Fill(2, new_mstatus.fs.orR) 482 | if (usingRoCC) reg_mstatus.xs := Fill(2, new_mstatus.xs.orR) 483 | } 484 | when (decoded_addr(CSRs.mip)) { 485 | val new_mip = new MIP().fromBits(wdata) 486 | if (usingVM) { 487 | reg_mip.ssip := new_mip.ssip 488 | reg_mip.stip := new_mip.stip 489 | } 490 | } 491 | when (decoded_addr(CSRs.mie)) { reg_mie := wdata & supported_interrupts } 492 | when (decoded_addr(CSRs.mepc)) { reg_mepc := ~(~wdata | (coreInstBytes-1)); reg_mepc_tag := wtag } 493 | when (decoded_addr(CSRs.mscratch)) { reg_mscratch := wdata; reg_mscratch_tag := wtag } 494 | if (p(MtvecWritable)) 495 | when (decoded_addr(CSRs.mtvec)) { reg_mtvec := wdata >> 2 << 2; reg_mtvec_tag := wtag } 496 | when (decoded_addr(CSRs.mcause)) { reg_mcause := wdata & UInt((BigInt(1) << (xLen-1)) + 31) /* only implement 5 LSBs and MSB */ } 497 | when (decoded_addr(CSRs.mbadaddr)) { reg_mbadaddr := wdata(vaddrBitsExtended-1,0) } 498 | writeCounter(CSRs.mcycle, reg_cycle, wdata) 499 | writeCounter(CSRs.minstret, reg_instret, wdata) 500 | if (usingFPU) { 501 | when (decoded_addr(CSRs.fflags)) { reg_fflags := wdata } 502 | when (decoded_addr(CSRs.frm)) { reg_frm := wdata } 503 | when (decoded_addr(CSRs.fcsr)) { reg_fflags := wdata; reg_frm := wdata >> reg_fflags.getWidth } 504 | } 505 | if (usingVM) { 506 | when (decoded_addr(CSRs.sstatus)) { 507 | val new_sstatus = new MStatus().fromBits(wdata) 508 | reg_mstatus.sie := new_sstatus.sie 509 | reg_mstatus.spie := new_sstatus.spie 510 | reg_mstatus.spp := new_sstatus.spp 511 | reg_mstatus.pum := new_sstatus.pum 512 | reg_mstatus.fs := Fill(2, new_sstatus.fs.orR) // even without an FPU 513 | if (usingRoCC) reg_mstatus.xs := Fill(2, new_sstatus.xs.orR) 514 | } 515 | when (decoded_addr(CSRs.sip)) { 516 | val new_sip = new MIP().fromBits(wdata) 517 | reg_mip.ssip := new_sip.ssip 518 | } 519 | when (decoded_addr(CSRs.sie)) { reg_mie := (reg_mie & ~reg_mideleg) | (wdata & reg_mideleg) } 520 | when (decoded_addr(CSRs.sscratch)) { reg_sscratch := wdata; reg_sscratch_tag := wtag } 521 | when (decoded_addr(CSRs.sptbr)) { reg_sptbr := wdata } 522 | when (decoded_addr(CSRs.sepc)) { reg_sepc := wdata >> log2Up(coreInstBytes) << log2Up(coreInstBytes); reg_sepc_tag := wtag } 523 | when (decoded_addr(CSRs.stvec)) { reg_stvec := wdata >> 2 << 2; reg_stvec_tag := wtag } 524 | when (decoded_addr(CSRs.scause)) { reg_scause := wdata & UInt((BigInt(1) << (xLen-1)) + 31) /* only implement 5 LSBs and MSB */ } 525 | when (decoded_addr(CSRs.sbadaddr)) { reg_sbadaddr := wdata(vaddrBitsExtended-1,0) } 526 | when (decoded_addr(CSRs.mideleg)) { reg_mideleg := wdata & delegable_interrupts } 527 | when (decoded_addr(CSRs.medeleg)) { reg_medeleg := wdata & delegable_exceptions } 528 | when (decoded_addr(CSRs.mscounteren)) { reg_mscounteren := wdata & 7 } 529 | } 530 | if (usingVM) { 531 | when (decoded_addr(CSRs.mucounteren)) { reg_mucounteren := wdata & 7 } 532 | } 533 | if (useTagMem) { 534 | when (decoded_addr(CSRs.utagctrl)) { reg_tagctrl := (wdata & reg_mutagctrlen) | (reg_tagctrl & ~reg_mutagctrlen) } 535 | when (decoded_addr(CSRs.stagctrl)) { reg_tagctrl := (wdata & reg_mstagctrlen) | (reg_tagctrl & ~reg_mstagctrlen) } 536 | when (decoded_addr(CSRs.mtagctrl)) { reg_tagctrl := wdata } 537 | when (decoded_addr(CSRs.mutagctrlen)) { reg_mutagctrlen := wdata } 538 | when (decoded_addr(CSRs.mstagctrlen)) { reg_mstagctrlen := wdata } 539 | } 540 | } 541 | 542 | reg_mip := io.prci.interrupts 543 | 544 | io.rocc.csr.waddr := io.rw.addr 545 | io.rocc.csr.wdata := wdata 546 | io.rocc.csr.wen := wen 547 | 548 | if (useTagMem) { 549 | io.tag_ctrl := new TagCtrlSig().fromBits(reg_tagctrl) 550 | } else { 551 | io.tag_ctrl := new TagCtrlSig().fromBits(UInt(0,xLen)) 552 | } 553 | 554 | def writeCounter(lo: Int, ctr: WideCounter, wdata: UInt) = { 555 | if (xLen == 32) { 556 | val hi = lo + CSRs.mcycleh - CSRs.mcycle 557 | when (decoded_addr(lo)) { ctr := Cat(ctr(63, 32), wdata) } 558 | when (decoded_addr(hi)) { ctr := Cat(wdata, ctr(31, 0)) } 559 | } else { 560 | when (decoded_addr(lo)) { ctr := wdata } 561 | } 562 | } 563 | } 564 | -------------------------------------------------------------------------------- /src/main/scala/decode.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package rocket 4 | 5 | import Chisel._ 6 | 7 | object DecodeLogic 8 | { 9 | def term(lit: BitPat) = 10 | new Term(lit.value, BigInt(2).pow(lit.getWidth)-(lit.mask+1)) 11 | def logic(addr: UInt, addrWidth: Int, cache: scala.collection.mutable.Map[Term,Bool], terms: Seq[Term]) = { 12 | terms.map { t => 13 | cache.getOrElseUpdate(t, (if (t.mask == 0) addr else addr & Bits(BigInt(2).pow(addrWidth)-(t.mask+1), addrWidth)) === Bits(t.value, addrWidth)) 14 | }.foldLeft(Bool(false))(_||_) 15 | } 16 | def apply(addr: UInt, default: BitPat, mapping: Iterable[(BitPat, BitPat)]): UInt = { 17 | val cache = caches.getOrElseUpdate(addr, collection.mutable.Map[Term,Bool]()) 18 | val dterm = term(default) 19 | val (keys, values) = mapping.unzip 20 | val addrWidth = keys.map(_.getWidth).max 21 | val terms = keys.toList.map(k => term(k)) 22 | val termvalues = terms zip values.toList.map(term(_)) 23 | 24 | for (t <- keys.zip(terms).tails; if !t.isEmpty) 25 | for (u <- t.tail) 26 | assert(!t.head._2.intersects(u._2), "DecodeLogic: keys " + t.head + " and " + u + " overlap") 27 | 28 | (0 until default.getWidth.max(values.map(_.getWidth).max)).map({ case (i: Int) => 29 | val mint = termvalues.filter { case (k,t) => ((t.mask >> i) & 1) == 0 && ((t.value >> i) & 1) == 1 }.map(_._1) 30 | val maxt = termvalues.filter { case (k,t) => ((t.mask >> i) & 1) == 0 && ((t.value >> i) & 1) == 0 }.map(_._1) 31 | val dc = termvalues.filter { case (k,t) => ((t.mask >> i) & 1) == 1 }.map(_._1) 32 | 33 | if (((dterm.mask >> i) & 1) != 0) { 34 | logic(addr, addrWidth, cache, SimplifyDC(mint, maxt, addrWidth)).toBits 35 | } else { 36 | val defbit = (dterm.value.toInt >> i) & 1 37 | val t = if (defbit == 0) mint else maxt 38 | val bit = logic(addr, addrWidth, cache, Simplify(t, dc, addrWidth)).toBits 39 | if (defbit == 0) bit else ~bit 40 | } 41 | }).reverse.reduceRight(Cat(_,_)) 42 | } 43 | def apply(addr: UInt, default: Seq[BitPat], mappingIn: Iterable[(BitPat, Seq[BitPat])]): Seq[UInt] = { 44 | val mapping = collection.mutable.ArrayBuffer.fill(default.size)(collection.mutable.ArrayBuffer[(BitPat, BitPat)]()) 45 | for ((key, values) <- mappingIn) 46 | for ((value, i) <- values zipWithIndex) 47 | mapping(i) += key -> value 48 | for ((thisDefault, thisMapping) <- default zip mapping) 49 | yield apply(addr, thisDefault, thisMapping) 50 | } 51 | def apply(addr: UInt, default: Seq[BitPat], mappingIn: List[(UInt, Seq[BitPat])]): Seq[UInt] = 52 | apply(addr, default, mappingIn.map(m => (BitPat(m._1), m._2)).asInstanceOf[Iterable[(BitPat, Seq[BitPat])]]) 53 | def apply(addr: UInt, trues: Iterable[UInt], falses: Iterable[UInt]): Bool = 54 | apply(addr, BitPat.DC(1), trues.map(BitPat(_) -> BitPat("b1")) ++ falses.map(BitPat(_) -> BitPat("b0"))).toBool 55 | private val caches = collection.mutable.Map[UInt,collection.mutable.Map[Term,Bool]]() 56 | } 57 | 58 | class Term(val value: BigInt, val mask: BigInt = 0) 59 | { 60 | var prime = true 61 | 62 | def covers(x: Term) = ((value ^ x.value) &~ mask | x.mask &~ mask) == 0 63 | def intersects(x: Term) = ((value ^ x.value) &~ mask &~ x.mask) == 0 64 | override def equals(that: Any) = that match { 65 | case x: Term => x.value == value && x.mask == mask 66 | case _ => false 67 | } 68 | override def hashCode = value.toInt 69 | def < (that: Term) = value < that.value || value == that.value && mask < that.mask 70 | def similar(x: Term) = { 71 | val diff = value - x.value 72 | mask == x.mask && value > x.value && (diff & diff-1) == 0 73 | } 74 | def merge(x: Term) = { 75 | prime = false 76 | x.prime = false 77 | val bit = value - x.value 78 | new Term(value &~ bit, mask | bit) 79 | } 80 | 81 | override def toString = value.toString(16) + "-" + mask.toString(16) + (if (prime) "p" else "") 82 | } 83 | 84 | object Simplify 85 | { 86 | def getPrimeImplicants(implicants: Seq[Term], bits: Int) = { 87 | var prime = List[Term]() 88 | implicants.foreach(_.prime = true) 89 | val cols = (0 to bits).map(b => implicants.filter(b == _.mask.bitCount)) 90 | val table = cols.map(c => (0 to bits).map(b => collection.mutable.Set(c.filter(b == _.value.bitCount):_*))) 91 | for (i <- 0 to bits) { 92 | for (j <- 0 until bits-i) 93 | table(i)(j).foreach(a => table(i+1)(j) ++= table(i)(j+1).filter(_.similar(a)).map(_.merge(a))) 94 | for (r <- table(i)) 95 | for (p <- r; if p.prime) 96 | prime = p :: prime 97 | } 98 | prime.sortWith(_<_) 99 | } 100 | def getEssentialPrimeImplicants(prime: Seq[Term], minterms: Seq[Term]): (Seq[Term],Seq[Term],Seq[Term]) = { 101 | for (i <- 0 until prime.size) { 102 | val icover = minterms.filter(prime(i) covers _) 103 | for (j <- 0 until prime.size) { 104 | val jcover = minterms.filter(prime(j) covers _) 105 | if (icover.size > jcover.size && jcover.forall(prime(i) covers _)) 106 | return getEssentialPrimeImplicants(prime.filter(_ != prime(j)), minterms) 107 | } 108 | } 109 | 110 | val essentiallyCovered = minterms.filter(t => prime.count(_ covers t) == 1) 111 | val essential = prime.filter(p => essentiallyCovered.exists(p covers _)) 112 | val nonessential = prime.filterNot(essential contains _) 113 | val uncovered = minterms.filterNot(t => essential.exists(_ covers t)) 114 | if (essential.isEmpty || uncovered.isEmpty) 115 | (essential, nonessential, uncovered) 116 | else { 117 | val (a, b, c) = getEssentialPrimeImplicants(nonessential, uncovered) 118 | (essential ++ a, b, c) 119 | } 120 | } 121 | def getCost(cover: Seq[Term], bits: Int) = cover.map(bits - _.mask.bitCount).sum 122 | def cheaper(a: List[Term], b: List[Term], bits: Int) = { 123 | val ca = getCost(a, bits) 124 | val cb = getCost(b, bits) 125 | def listLess(a: List[Term], b: List[Term]): Boolean = !b.isEmpty && (a.isEmpty || a.head < b.head || a.head == b.head && listLess(a.tail, b.tail)) 126 | ca < cb || ca == cb && listLess(a.sortWith(_<_), b.sortWith(_<_)) 127 | } 128 | def getCover(implicants: Seq[Term], minterms: Seq[Term], bits: Int) = { 129 | if (minterms.nonEmpty) { 130 | val cover = minterms.map(m => implicants.filter(_.covers(m)).map(i => collection.mutable.Set(i))) 131 | val all = cover.reduceLeft((c0, c1) => c0.map(a => c1.map(_ ++ a)).reduceLeft(_++_)) 132 | all.map(_.toList).reduceLeft((a, b) => if (cheaper(a, b, bits)) a else b) 133 | } else 134 | Seq[Term]() 135 | } 136 | def stringify(s: Seq[Term], bits: Int) = s.map(t => (0 until bits).map(i => if ((t.mask & (1 << i)) != 0) "x" else ((t.value >> i) & 1).toString).reduceLeft(_+_).reverse).reduceLeft(_+" + "+_) 137 | 138 | def apply(minterms: Seq[Term], dontcares: Seq[Term], bits: Int) = { 139 | val prime = getPrimeImplicants(minterms ++ dontcares, bits) 140 | minterms.foreach(t => assert(prime.exists(_.covers(t)))) 141 | val (eprime, prime2, uncovered) = getEssentialPrimeImplicants(prime, minterms) 142 | val cover = eprime ++ getCover(prime2, uncovered, bits) 143 | minterms.foreach(t => assert(cover.exists(_.covers(t)))) // sanity check 144 | cover 145 | } 146 | } 147 | 148 | object SimplifyDC 149 | { 150 | def getImplicitDC(maxterms: Seq[Term], term: Term, bits: Int, above: Boolean): Term = { 151 | for (i <- 0 until bits) { 152 | var t: Term = null 153 | if (above && ((term.value | term.mask) & (BigInt(1) << i)) == 0) 154 | t = new Term(term.value | (BigInt(1) << i), term.mask) 155 | else if (!above && (term.value & (BigInt(1) << i)) != 0) 156 | t = new Term(term.value & ~(BigInt(1) << i), term.mask) 157 | if (t != null && !maxterms.exists(_.intersects(t))) 158 | return t 159 | } 160 | null 161 | } 162 | def getPrimeImplicants(minterms: Seq[Term], maxterms: Seq[Term], bits: Int) = { 163 | var prime = List[Term]() 164 | minterms.foreach(_.prime = true) 165 | var mint = minterms.map(t => new Term(t.value, t.mask)) 166 | val cols = (0 to bits).map(b => mint.filter(b == _.mask.bitCount)) 167 | val table = cols.map(c => (0 to bits).map(b => collection.mutable.Set(c.filter(b == _.value.bitCount):_*))) 168 | 169 | for (i <- 0 to bits) { 170 | for (j <- 0 until bits-i) { 171 | table(i)(j).foreach(a => table(i+1)(j) ++= table(i)(j+1).filter(_ similar a).map(_ merge a)) 172 | } 173 | for (j <- 0 until bits-i) { 174 | for (a <- table(i)(j).filter(_.prime)) { 175 | val dc = getImplicitDC(maxterms, a, bits, true) 176 | if (dc != null) 177 | table(i+1)(j) += dc merge a 178 | } 179 | for (a <- table(i)(j+1).filter(_.prime)) { 180 | val dc = getImplicitDC(maxterms, a, bits, false) 181 | if (dc != null) 182 | table(i+1)(j) += a merge dc 183 | } 184 | } 185 | for (r <- table(i)) 186 | for (p <- r; if p.prime) 187 | prime = p :: prime 188 | } 189 | prime.sortWith(_<_) 190 | } 191 | 192 | def verify(cover: Seq[Term], minterms: Seq[Term], maxterms: Seq[Term]) = { 193 | assert(minterms.forall(t => cover.exists(_ covers t))) 194 | assert(maxterms.forall(t => !cover.exists(_ intersects t))) 195 | } 196 | def apply(minterms: Seq[Term], maxterms: Seq[Term], bits: Int) = { 197 | val prime = getPrimeImplicants(minterms, maxterms, bits) 198 | val (eprime, prime2, uncovered) = Simplify.getEssentialPrimeImplicants(prime, minterms) 199 | val cover = eprime ++ Simplify.getCover(prime2, uncovered, bits) 200 | verify(cover, minterms, maxterms) 201 | cover 202 | } 203 | } 204 | -------------------------------------------------------------------------------- /src/main/scala/dma.scala: -------------------------------------------------------------------------------- 1 | package rocket 2 | 3 | import Chisel._ 4 | import uncore._ 5 | import uncore.DmaRequest._ 6 | import junctions.{ParameterizedBundle, AddrHashMap} 7 | import cde.Parameters 8 | 9 | trait HasClientDmaParameters extends HasCoreParameters with HasDmaParameters { 10 | val dmaAddrBits = coreMaxAddrBits 11 | val dmaSegmentSizeBits = coreMaxAddrBits 12 | val dmaSegmentBits = 24 13 | } 14 | 15 | abstract class ClientDmaBundle(implicit val p: Parameters) 16 | extends ParameterizedBundle()(p) with HasClientDmaParameters 17 | abstract class ClientDmaModule(implicit val p: Parameters) 18 | extends Module with HasClientDmaParameters 19 | 20 | class ClientDmaRequest(implicit p: Parameters) extends ClientDmaBundle()(p) { 21 | val cmd = UInt(width = DMA_CMD_SZ) 22 | val src_start = UInt(width = dmaAddrBits) 23 | val dst_start = UInt(width = dmaAddrBits) 24 | val src_stride = UInt(width = dmaSegmentSizeBits) 25 | val dst_stride = UInt(width = dmaSegmentSizeBits) 26 | val segment_size = UInt(width = dmaSegmentSizeBits) 27 | val nsegments = UInt(width = dmaSegmentBits) 28 | val word_size = UInt(width = dmaWordSizeBits) 29 | } 30 | 31 | object ClientDmaRequest { 32 | def apply(cmd: UInt, 33 | src_start: UInt, 34 | dst_start: UInt, 35 | segment_size: UInt, 36 | nsegments: UInt = UInt(1), 37 | src_stride: UInt = UInt(0), 38 | dst_stride: UInt = UInt(0), 39 | word_size: UInt = UInt(0)) 40 | (implicit p: Parameters) = { 41 | val req = Wire(new ClientDmaRequest) 42 | req.cmd := cmd 43 | req.src_start := src_start 44 | req.dst_start := dst_start 45 | req.src_stride := src_stride 46 | req.dst_stride := dst_stride 47 | req.segment_size := segment_size 48 | req.nsegments := nsegments 49 | req.word_size := word_size 50 | req 51 | } 52 | } 53 | 54 | object ClientDmaResponse { 55 | val pagefault = UInt("b01") 56 | val invalid_region = UInt("b10") 57 | 58 | def apply(status: UInt = UInt(0))(implicit p: Parameters) = { 59 | val resp = Wire(new ClientDmaResponse) 60 | resp.status := status 61 | resp 62 | } 63 | } 64 | 65 | class ClientDmaResponse(implicit p: Parameters) extends ClientDmaBundle { 66 | val status = UInt(width = dmaStatusBits) 67 | } 68 | 69 | class ClientDmaIO(implicit p: Parameters) extends ParameterizedBundle()(p) { 70 | val req = Decoupled(new ClientDmaRequest) 71 | val resp = Valid(new ClientDmaResponse).flip 72 | } 73 | 74 | class DmaFrontend(implicit p: Parameters) extends CoreModule()(p) 75 | with HasClientDmaParameters with HasTileLinkParameters { 76 | val io = new Bundle { 77 | val cpu = (new ClientDmaIO).flip 78 | val mem = new ClientUncachedTileLinkIO 79 | val ptw = new TLBPTWIO 80 | val busy = Bool(OUTPUT) 81 | val incr_outstanding = Bool(OUTPUT) 82 | val host_id = UInt(INPUT, log2Up(nCores)) 83 | } 84 | 85 | val tlb = Module(new DecoupledTLB()(p.alterPartial({ 86 | case CacheName => "L1D" 87 | }))) 88 | io.ptw <> tlb.io.ptw 89 | 90 | private val pgSize = 1 << pgIdxBits 91 | 92 | val cmd = Reg(UInt(width = DMA_CMD_SZ)) 93 | val adv_ptr = MuxLookup(cmd, UInt("b11"), Seq( 94 | DMA_CMD_PFR -> UInt("b10"), 95 | DMA_CMD_PFW -> UInt("b10"), 96 | DMA_CMD_SIN -> UInt("b10"), 97 | DMA_CMD_SOUT -> UInt("b01"))) 98 | 99 | val segment_size = Reg(UInt(width = dmaSegmentSizeBits)) 100 | val bytes_left = Reg(UInt(width = dmaSegmentSizeBits)) 101 | val segments_left = Reg(UInt(width = dmaSegmentBits)) 102 | val word_size = Reg(UInt(width = dmaWordSizeBits)) 103 | 104 | val src_vaddr = Reg(UInt(width = dmaAddrBits)) 105 | val dst_vaddr = Reg(UInt(width = dmaAddrBits)) 106 | val src_vpn = src_vaddr(dmaAddrBits - 1, pgIdxBits) 107 | val dst_vpn = dst_vaddr(dmaAddrBits - 1, pgIdxBits) 108 | val src_idx = src_vaddr(pgIdxBits - 1, 0) 109 | val dst_idx = dst_vaddr(pgIdxBits - 1, 0) 110 | val src_pglen = UInt(pgSize) - src_idx 111 | val dst_pglen = UInt(pgSize) - dst_idx 112 | 113 | val src_stride = Reg(UInt(width = dmaSegmentSizeBits)) 114 | val dst_stride = Reg(UInt(width = dmaSegmentSizeBits)) 115 | 116 | val src_ppn = Reg(UInt(width = ppnBits)) 117 | val dst_ppn = Reg(UInt(width = ppnBits)) 118 | 119 | val src_paddr = Cat(src_ppn, src_idx) 120 | val dst_paddr = Cat(dst_ppn, dst_idx) 121 | 122 | val last_src_vpn = Reg(UInt(width = vpnBits)) 123 | val last_dst_vpn = Reg(UInt(width = vpnBits)) 124 | 125 | val tx_len = Util.minUInt(src_pglen, dst_pglen, bytes_left) 126 | 127 | val dma_busy = Reg(init = UInt(0, tlMaxClientXacts)) 128 | val dma_xact_id = PriorityEncoder(~dma_busy) 129 | val (dma_req_beat, dma_req_done) = Counter(io.mem.acquire.fire(), tlDataBeats) 130 | 131 | val (s_idle :: s_translate :: s_dma_req :: s_dma_update :: 132 | s_prepare :: s_finish :: Nil) = Enum(Bits(), 6) 133 | val state = Reg(init = s_idle) 134 | 135 | // lower bit is for src, higher bit is for dst 136 | val to_translate = Reg(init = UInt(0, 2)) 137 | val tlb_sent = Reg(init = UInt(0, 2)) 138 | val tlb_to_send = to_translate & ~tlb_sent 139 | val resp_status = Reg(UInt(width = dmaStatusBits)) 140 | 141 | def make_acquire( 142 | addr_beat: UInt, client_xact_id: UInt, client_id: UInt, 143 | cmd: UInt, source: UInt, dest: UInt, 144 | length: UInt, size: UInt): Acquire = { 145 | 146 | val data_blob = Wire(UInt(width = tlDataBeats * tlDataBits)) 147 | data_blob := DmaRequest( 148 | xact_id = UInt(0), 149 | client_id = client_id, 150 | cmd = cmd, 151 | source = source, 152 | dest = dest, 153 | length = length, 154 | size = size).toBits 155 | val data_beats = Vec(tlDataBeats, UInt(width = tlDataBits)).fromBits(data_blob) 156 | val base_addr = addrMap("devices:dma").start 157 | val addr_block = UInt(base_addr >> (tlBeatAddrBits + tlByteAddrBits)) 158 | 159 | PutBlock( 160 | client_xact_id = client_xact_id, 161 | addr_block = addr_block, 162 | addr_beat = addr_beat, 163 | data = data_beats(addr_beat), 164 | alloc = Bool(false)) 165 | } 166 | 167 | def check_region(cmd: UInt, src: UInt, dst: UInt): Bool = { 168 | val src_cacheable = addrMap.isCacheable(src) 169 | val dst_cacheable = addrMap.isCacheable(dst) 170 | val dst_ok = Mux(cmd === DMA_CMD_SOUT, !dst_cacheable, dst_cacheable) 171 | val src_ok = Mux(cmd === DMA_CMD_SIN, !src_cacheable, Bool(true)) 172 | dst_ok && src_ok 173 | } 174 | 175 | tlb.io.req.valid := tlb_to_send.orR 176 | tlb.io.req.bits.vpn := Mux(tlb_to_send(0), src_vpn, dst_vpn) 177 | tlb.io.req.bits.passthrough := Bool(false) 178 | tlb.io.req.bits.instruction := Bool(false) 179 | tlb.io.req.bits.store := !tlb_to_send(0) 180 | tlb.io.resp.ready := tlb_sent.orR 181 | 182 | when (tlb.io.req.fire()) { 183 | tlb_sent := tlb_sent | PriorityEncoderOH(tlb_to_send) 184 | } 185 | 186 | when (tlb.io.resp.fire()) { 187 | val recv_choice = PriorityEncoderOH(to_translate) 188 | val error = Mux(recv_choice(0), 189 | tlb.io.resp.bits.xcpt_ld, tlb.io.resp.bits.xcpt_st) 190 | 191 | when (error) { 192 | resp_status := ClientDmaResponse.pagefault 193 | state := s_finish 194 | } 195 | 196 | // getting the src translation 197 | when (recv_choice(0)) { 198 | src_ppn := tlb.io.resp.bits.ppn 199 | } .otherwise { 200 | dst_ppn := tlb.io.resp.bits.ppn 201 | } 202 | 203 | to_translate := to_translate & ~recv_choice 204 | } 205 | 206 | io.cpu.req.ready := state === s_idle 207 | io.cpu.resp.valid := state === s_finish 208 | io.cpu.resp.bits := ClientDmaResponse(resp_status) 209 | 210 | io.mem.acquire.valid := (state === s_dma_req) && !dma_busy.andR 211 | io.mem.acquire.bits := make_acquire( 212 | addr_beat = dma_req_beat, 213 | client_id = io.host_id, 214 | client_xact_id = dma_xact_id, 215 | cmd = cmd, source = src_paddr, dest = dst_paddr, 216 | length = tx_len, size = word_size) 217 | 218 | io.mem.grant.ready := (state =/= s_dma_req) 219 | 220 | when (io.cpu.req.fire()) { 221 | val req = io.cpu.req.bits 222 | val is_prefetch = req.cmd(2, 1) === UInt("b01") 223 | cmd := req.cmd 224 | src_vaddr := req.src_start 225 | dst_vaddr := req.dst_start 226 | src_stride := req.src_stride 227 | dst_stride := req.dst_stride 228 | segment_size := req.segment_size 229 | segments_left := req.nsegments - UInt(1) 230 | bytes_left := req.segment_size 231 | word_size := req.word_size 232 | to_translate := Mux(is_prefetch, UInt("b10"), UInt("b11")) 233 | tlb_sent := UInt(0) 234 | state := s_translate 235 | } 236 | 237 | when (state === s_translate && !to_translate.orR) { 238 | when (check_region(cmd, src_paddr, dst_paddr)) { 239 | state := s_dma_req 240 | } .otherwise { 241 | resp_status := ClientDmaResponse.invalid_region 242 | state := s_finish 243 | } 244 | } 245 | 246 | def setBusy(set: Bool, xact_id: UInt): UInt = 247 | Mux(set, UIntToOH(xact_id), UInt(0)) 248 | 249 | dma_busy := (dma_busy | 250 | setBusy(dma_req_done, dma_xact_id)) & 251 | ~setBusy(io.mem.grant.fire(), io.mem.grant.bits.client_xact_id) 252 | 253 | 254 | when (dma_req_done) { 255 | src_vaddr := src_vaddr + Mux(adv_ptr(0), tx_len, UInt(0)) 256 | dst_vaddr := dst_vaddr + Mux(adv_ptr(1), tx_len, UInt(0)) 257 | bytes_left := bytes_left - tx_len 258 | state := s_dma_update 259 | } 260 | 261 | when (state === s_dma_update) { 262 | when (bytes_left === UInt(0)) { 263 | when (segments_left === UInt(0)) { 264 | resp_status := UInt(0) 265 | state := s_finish 266 | } .otherwise { 267 | last_src_vpn := src_vpn 268 | last_dst_vpn := dst_vpn 269 | src_vaddr := src_vaddr + src_stride 270 | dst_vaddr := dst_vaddr + dst_stride 271 | bytes_left := segment_size 272 | segments_left := segments_left - UInt(1) 273 | state := s_prepare 274 | } 275 | } .otherwise { 276 | to_translate := adv_ptr & Cat(dst_idx === UInt(0), src_idx === UInt(0)) 277 | tlb_sent := UInt(0) 278 | state := s_translate 279 | } 280 | } 281 | 282 | when (state === s_prepare) { 283 | to_translate := adv_ptr & Cat( 284 | dst_vpn =/= last_dst_vpn, 285 | src_vpn =/= last_src_vpn) 286 | tlb_sent := UInt(0) 287 | state := s_translate 288 | } 289 | 290 | when (state === s_finish) { state := s_idle } 291 | 292 | io.busy := (state =/= s_idle) || dma_busy.orR 293 | io.incr_outstanding := dma_req_done 294 | } 295 | 296 | object DmaCtrlRegNumbers { 297 | val SRC_STRIDE = 0 298 | val DST_STRIDE = 1 299 | val SEGMENT_SIZE = 2 300 | val NSEGMENTS = 3 301 | val WORD_SIZE = 4 302 | val RESP_STATUS = 5 303 | val OUTSTANDING = 6 304 | val NCSRS = 7 305 | val CSR_BASE = 0x800 306 | val CSR_END = CSR_BASE + NCSRS 307 | } 308 | import DmaCtrlRegNumbers._ 309 | 310 | class DmaCtrlRegFile(implicit val p: Parameters) extends Module 311 | with HasClientDmaParameters with HasTileLinkParameters { 312 | 313 | private val nWriteRegs = 5 314 | private val nRegs = nWriteRegs + 2 315 | 316 | val io = new Bundle { 317 | val wen = Bool(INPUT) 318 | val waddr = UInt(INPUT, log2Up(nRegs)) 319 | val wdata = UInt(INPUT, dmaSegmentSizeBits) 320 | 321 | val src_stride = UInt(OUTPUT, dmaSegmentSizeBits) 322 | val dst_stride = UInt(OUTPUT, dmaSegmentSizeBits) 323 | val segment_size = UInt(OUTPUT, dmaSegmentSizeBits) 324 | val nsegments = UInt(OUTPUT, dmaSegmentBits) 325 | val word_size = UInt(OUTPUT, dmaWordSizeBits) 326 | 327 | val incr_outstanding = Bool(INPUT) 328 | val xact_outstanding = Bool(OUTPUT) 329 | } 330 | 331 | val regs = Reg(Vec(nWriteRegs, UInt(width = dmaSegmentSizeBits))) 332 | val waddr = io.waddr(log2Up(NCSRS) - 1, 0) 333 | 334 | io.src_stride := regs(SRC_STRIDE) 335 | io.dst_stride := regs(DST_STRIDE) 336 | io.segment_size := regs(SEGMENT_SIZE) 337 | io.nsegments := regs(NSEGMENTS) 338 | io.word_size := regs(WORD_SIZE) 339 | 340 | when (io.wen && waddr < UInt(nWriteRegs)) { 341 | regs.write(waddr, io.wdata) 342 | } 343 | 344 | val outstanding_cnt = TwoWayCounter( 345 | io.incr_outstanding, 346 | io.wen && io.waddr === UInt(OUTSTANDING), 347 | tlMaxClientXacts) 348 | 349 | io.xact_outstanding := outstanding_cnt > UInt(0) 350 | } 351 | 352 | class DmaController(implicit p: Parameters) extends RoCC()(p) 353 | with HasClientDmaParameters { 354 | io.mem.req.valid := Bool(false) 355 | io.resp.valid := Bool(false) 356 | io.interrupt := Bool(false) 357 | 358 | val cmd = Queue(io.cmd) 359 | val inst = cmd.bits.inst 360 | val is_transfer = inst.funct < UInt(8) 361 | 362 | val reg_status = Reg(UInt(width = dmaStatusBits)) 363 | val crfile = Module(new DmaCtrlRegFile) 364 | crfile.io.waddr := io.csr.waddr 365 | crfile.io.wdata := io.csr.wdata 366 | crfile.io.wen := io.csr.wen 367 | 368 | io.csr.rdata(SRC_STRIDE) := crfile.io.src_stride 369 | io.csr.rdata(DST_STRIDE) := crfile.io.dst_stride 370 | io.csr.rdata(SEGMENT_SIZE) := crfile.io.segment_size 371 | io.csr.rdata(NSEGMENTS) := crfile.io.nsegments 372 | io.csr.rdata(WORD_SIZE) := crfile.io.word_size 373 | io.csr.rdata(RESP_STATUS) := reg_status 374 | 375 | val frontend = Module(new DmaFrontend) 376 | io.ptw(0) <> frontend.io.ptw 377 | io.autl <> frontend.io.mem 378 | crfile.io.incr_outstanding := frontend.io.incr_outstanding 379 | frontend.io.host_id := io.host_id 380 | frontend.io.cpu.req.valid := cmd.valid && is_transfer 381 | frontend.io.cpu.req.bits := ClientDmaRequest( 382 | cmd = cmd.bits.inst.funct, 383 | src_start = cmd.bits.rs2, 384 | dst_start = cmd.bits.rs1, 385 | src_stride = crfile.io.src_stride, 386 | dst_stride = crfile.io.dst_stride, 387 | segment_size = crfile.io.segment_size, 388 | nsegments = crfile.io.nsegments, 389 | word_size = crfile.io.word_size) 390 | cmd.ready := is_transfer && frontend.io.cpu.req.ready 391 | 392 | when (frontend.io.cpu.resp.valid) { 393 | reg_status := frontend.io.cpu.resp.bits.status 394 | } 395 | 396 | io.busy := cmd.valid || frontend.io.busy || crfile.io.xact_outstanding 397 | } 398 | -------------------------------------------------------------------------------- /src/main/scala/dpath_alu.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package rocket 4 | 5 | import Chisel._ 6 | import cde.{Parameters, Field} 7 | import Instructions._ 8 | 9 | object ALU 10 | { 11 | val SZ_ALU_FN = 4 12 | val FN_X = BitPat("b????") 13 | val FN_ADD = UInt(0) 14 | val FN_SL = UInt(1) 15 | val FN_SEQ = UInt(2) 16 | val FN_SNE = UInt(3) 17 | val FN_XOR = UInt(4) 18 | val FN_SR = UInt(5) 19 | val FN_OR = UInt(6) 20 | val FN_AND = UInt(7) 21 | val FN_SUB = UInt(10) 22 | val FN_SRA = UInt(11) 23 | val FN_SLT = UInt(12) 24 | val FN_SGE = UInt(13) 25 | val FN_SLTU = UInt(14) 26 | val FN_SGEU = UInt(15) 27 | 28 | val FN_DIV = FN_XOR 29 | val FN_DIVU = FN_SR 30 | val FN_REM = FN_OR 31 | val FN_REMU = FN_AND 32 | 33 | val FN_MUL = FN_ADD 34 | val FN_MULH = FN_SL 35 | val FN_MULHSU = FN_SLT 36 | val FN_MULHU = FN_SLTU 37 | 38 | def isMulFN(fn: UInt, cmp: UInt) = fn(1,0) === cmp(1,0) 39 | def isSub(cmd: UInt) = cmd(3) 40 | def isCmp(cmd: UInt) = cmd === FN_SEQ || cmd === FN_SNE || cmd >= FN_SLT 41 | def cmpUnsigned(cmd: UInt) = cmd(1) 42 | def cmpInverted(cmd: UInt) = cmd(0) 43 | def cmpEq(cmd: UInt) = !cmd(3) 44 | } 45 | import ALU._ 46 | 47 | class ALU(implicit p: Parameters) extends CoreModule()(p) { 48 | val io = new Bundle { 49 | val dw = Bits(INPUT, SZ_DW) 50 | val fn = Bits(INPUT, SZ_ALU_FN) 51 | val in2 = UInt(INPUT, xLen) 52 | val in1 = UInt(INPUT, xLen) 53 | val out = UInt(OUTPUT, xLen) 54 | val adder_out = UInt(OUTPUT, xLen) 55 | val cmp_out = Bool(OUTPUT) 56 | } 57 | 58 | // ADD, SUB 59 | val in2_inv = Mux(isSub(io.fn), ~io.in2, io.in2) 60 | val in1_xor_in2 = io.in1 ^ in2_inv 61 | io.adder_out := io.in1 + in2_inv + isSub(io.fn) 62 | 63 | // SLT, SLTU 64 | io.cmp_out := cmpInverted(io.fn) ^ 65 | Mux(cmpEq(io.fn), in1_xor_in2 === UInt(0), 66 | Mux(io.in1(xLen-1) === io.in2(xLen-1), io.adder_out(xLen-1), 67 | Mux(cmpUnsigned(io.fn), io.in2(xLen-1), io.in1(xLen-1)))) 68 | 69 | // SLL, SRL, SRA 70 | val (shamt, shin_r) = 71 | if (xLen == 32) (io.in2(4,0), io.in1) 72 | else { 73 | require(xLen == 64) 74 | val shin_hi_32 = Fill(32, isSub(io.fn) && io.in1(31)) 75 | val shin_hi = Mux(io.dw === DW_64, io.in1(63,32), shin_hi_32) 76 | val shamt = Cat(io.in2(5) & (io.dw === DW_64), io.in2(4,0)) 77 | (shamt, Cat(shin_hi, io.in1(31,0))) 78 | } 79 | val shin = Mux(io.fn === FN_SR || io.fn === FN_SRA, shin_r, Reverse(shin_r)) 80 | val shout_r = (Cat(isSub(io.fn) & shin(xLen-1), shin).toSInt >> shamt)(xLen-1,0) 81 | val shout_l = Reverse(shout_r) 82 | val shout = Mux(io.fn === FN_SR || io.fn === FN_SRA, shout_r, UInt(0)) | 83 | Mux(io.fn === FN_SL, shout_l, UInt(0)) 84 | 85 | // AND, OR, XOR 86 | val logic = Mux(io.fn === FN_XOR || io.fn === FN_OR, in1_xor_in2, UInt(0)) | 87 | Mux(io.fn === FN_OR || io.fn === FN_AND, io.in1 & io.in2, UInt(0)) 88 | val shift_logic = (isCmp(io.fn) && io.cmp_out) | logic | shout 89 | val out = Mux(io.fn === FN_ADD || io.fn === FN_SUB, io.adder_out, shift_logic) 90 | 91 | io.out := out 92 | if (xLen > 32) { 93 | require(xLen == 64) 94 | when (io.dw === DW_32) { io.out := Cat(Fill(32, out(31)), out(31,0)) } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/main/scala/fpu.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package rocket 4 | 5 | import Chisel._ 6 | import Instructions._ 7 | import Util._ 8 | import FPConstants._ 9 | import uncore.constants.MemoryOpConstants._ 10 | import cde.{Parameters, Field} 11 | 12 | case object SFMALatency extends Field[Int] 13 | case object DFMALatency extends Field[Int] 14 | 15 | object FPConstants 16 | { 17 | val FCMD_ADD = BitPat("b0??00") 18 | val FCMD_SUB = BitPat("b0??01") 19 | val FCMD_MUL = BitPat("b0??10") 20 | val FCMD_MADD = BitPat("b1??00") 21 | val FCMD_MSUB = BitPat("b1??01") 22 | val FCMD_NMSUB = BitPat("b1??10") 23 | val FCMD_NMADD = BitPat("b1??11") 24 | val FCMD_DIV = BitPat("b?0011") 25 | val FCMD_SQRT = BitPat("b?1011") 26 | val FCMD_SGNJ = BitPat("b??1?0") 27 | val FCMD_MINMAX = BitPat("b?01?1") 28 | val FCMD_CVT_FF = BitPat("b??0??") 29 | val FCMD_CVT_IF = BitPat("b?10??") 30 | val FCMD_CMP = BitPat("b?01??") 31 | val FCMD_MV_XF = BitPat("b?11??") 32 | val FCMD_CVT_FI = BitPat("b??0??") 33 | val FCMD_MV_FX = BitPat("b??1??") 34 | val FCMD_X = BitPat("b?????") 35 | val FCMD_WIDTH = 5 36 | 37 | val RM_SZ = 3 38 | val FLAGS_SZ = 5 39 | } 40 | 41 | class FPUCtrlSigs extends Bundle 42 | { 43 | val cmd = Bits(width = FCMD_WIDTH) 44 | val ldst = Bool() 45 | val wen = Bool() 46 | val ren1 = Bool() 47 | val ren2 = Bool() 48 | val ren3 = Bool() 49 | val swap12 = Bool() 50 | val swap23 = Bool() 51 | val single = Bool() 52 | val fromint = Bool() 53 | val toint = Bool() 54 | val fastpipe = Bool() 55 | val fma = Bool() 56 | val div = Bool() 57 | val sqrt = Bool() 58 | val round = Bool() 59 | val wflags = Bool() 60 | } 61 | 62 | class FPUDecoder extends Module 63 | { 64 | val io = new Bundle { 65 | val inst = Bits(INPUT, 32) 66 | val sigs = new FPUCtrlSigs().asOutput 67 | } 68 | 69 | val decoder = DecodeLogic(io.inst, 70 | List (FCMD_X, X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X), 71 | Array(FLW -> List(FCMD_X, Y,Y,N,N,N,X,X,Y,N,N,N,N,N,N,N,N), 72 | FLD -> List(FCMD_X, Y,Y,N,N,N,X,X,N,N,N,N,N,N,N,N,N), 73 | FSW -> List(FCMD_MV_XF, Y,N,N,Y,N,Y,X,Y,N,Y,N,N,N,N,N,N), 74 | FSD -> List(FCMD_MV_XF, Y,N,N,Y,N,Y,X,N,N,Y,N,N,N,N,N,N), 75 | FMV_S_X -> List(FCMD_MV_FX, N,Y,N,N,N,X,X,Y,Y,N,N,N,N,N,Y,N), 76 | FMV_D_X -> List(FCMD_MV_FX, N,Y,N,N,N,X,X,N,Y,N,N,N,N,N,Y,N), 77 | FCVT_S_W -> List(FCMD_CVT_FI, N,Y,N,N,N,X,X,Y,Y,N,N,N,N,N,Y,Y), 78 | FCVT_S_WU-> List(FCMD_CVT_FI, N,Y,N,N,N,X,X,Y,Y,N,N,N,N,N,Y,Y), 79 | FCVT_S_L -> List(FCMD_CVT_FI, N,Y,N,N,N,X,X,Y,Y,N,N,N,N,N,Y,Y), 80 | FCVT_S_LU-> List(FCMD_CVT_FI, N,Y,N,N,N,X,X,Y,Y,N,N,N,N,N,Y,Y), 81 | FCVT_D_W -> List(FCMD_CVT_FI, N,Y,N,N,N,X,X,N,Y,N,N,N,N,N,Y,Y), 82 | FCVT_D_WU-> List(FCMD_CVT_FI, N,Y,N,N,N,X,X,N,Y,N,N,N,N,N,Y,Y), 83 | FCVT_D_L -> List(FCMD_CVT_FI, N,Y,N,N,N,X,X,N,Y,N,N,N,N,N,Y,Y), 84 | FCVT_D_LU-> List(FCMD_CVT_FI, N,Y,N,N,N,X,X,N,Y,N,N,N,N,N,Y,Y), 85 | FMV_X_S -> List(FCMD_MV_XF, N,N,Y,N,N,N,X,Y,N,Y,N,N,N,N,Y,N), 86 | FMV_X_D -> List(FCMD_MV_XF, N,N,Y,N,N,N,X,N,N,Y,N,N,N,N,Y,N), 87 | FCLASS_S -> List(FCMD_MV_XF, N,N,Y,N,N,N,X,Y,N,Y,N,N,N,N,Y,N), 88 | FCLASS_D -> List(FCMD_MV_XF, N,N,Y,N,N,N,X,N,N,Y,N,N,N,N,Y,N), 89 | FCVT_W_S -> List(FCMD_CVT_IF, N,N,Y,N,N,N,X,Y,N,Y,N,N,N,N,Y,Y), 90 | FCVT_WU_S-> List(FCMD_CVT_IF, N,N,Y,N,N,N,X,Y,N,Y,N,N,N,N,Y,Y), 91 | FCVT_L_S -> List(FCMD_CVT_IF, N,N,Y,N,N,N,X,Y,N,Y,N,N,N,N,Y,Y), 92 | FCVT_LU_S-> List(FCMD_CVT_IF, N,N,Y,N,N,N,X,Y,N,Y,N,N,N,N,Y,Y), 93 | FCVT_W_D -> List(FCMD_CVT_IF, N,N,Y,N,N,N,X,N,N,Y,N,N,N,N,Y,Y), 94 | FCVT_WU_D-> List(FCMD_CVT_IF, N,N,Y,N,N,N,X,N,N,Y,N,N,N,N,Y,Y), 95 | FCVT_L_D -> List(FCMD_CVT_IF, N,N,Y,N,N,N,X,N,N,Y,N,N,N,N,Y,Y), 96 | FCVT_LU_D-> List(FCMD_CVT_IF, N,N,Y,N,N,N,X,N,N,Y,N,N,N,N,Y,Y), 97 | FCVT_S_D -> List(FCMD_CVT_FF, N,Y,Y,N,N,N,X,Y,N,N,Y,N,N,N,Y,Y), 98 | FCVT_D_S -> List(FCMD_CVT_FF, N,Y,Y,N,N,N,X,N,N,N,Y,N,N,N,Y,Y), 99 | FEQ_S -> List(FCMD_CMP, N,N,Y,Y,N,N,N,Y,N,Y,N,N,N,N,N,Y), 100 | FLT_S -> List(FCMD_CMP, N,N,Y,Y,N,N,N,Y,N,Y,N,N,N,N,N,Y), 101 | FLE_S -> List(FCMD_CMP, N,N,Y,Y,N,N,N,Y,N,Y,N,N,N,N,N,Y), 102 | FEQ_D -> List(FCMD_CMP, N,N,Y,Y,N,N,N,N,N,Y,N,N,N,N,N,Y), 103 | FLT_D -> List(FCMD_CMP, N,N,Y,Y,N,N,N,N,N,Y,N,N,N,N,N,Y), 104 | FLE_D -> List(FCMD_CMP, N,N,Y,Y,N,N,N,N,N,Y,N,N,N,N,N,Y), 105 | FSGNJ_S -> List(FCMD_SGNJ, N,Y,Y,Y,N,N,N,Y,N,N,Y,N,N,N,N,N), 106 | FSGNJN_S -> List(FCMD_SGNJ, N,Y,Y,Y,N,N,N,Y,N,N,Y,N,N,N,N,N), 107 | FSGNJX_S -> List(FCMD_SGNJ, N,Y,Y,Y,N,N,N,Y,N,N,Y,N,N,N,N,N), 108 | FSGNJ_D -> List(FCMD_SGNJ, N,Y,Y,Y,N,N,N,N,N,N,Y,N,N,N,N,N), 109 | FSGNJN_D -> List(FCMD_SGNJ, N,Y,Y,Y,N,N,N,N,N,N,Y,N,N,N,N,N), 110 | FSGNJX_D -> List(FCMD_SGNJ, N,Y,Y,Y,N,N,N,N,N,N,Y,N,N,N,N,N), 111 | FMIN_S -> List(FCMD_MINMAX, N,Y,Y,Y,N,N,N,Y,N,N,Y,N,N,N,N,Y), 112 | FMAX_S -> List(FCMD_MINMAX, N,Y,Y,Y,N,N,N,Y,N,N,Y,N,N,N,N,Y), 113 | FMIN_D -> List(FCMD_MINMAX, N,Y,Y,Y,N,N,N,N,N,N,Y,N,N,N,N,Y), 114 | FMAX_D -> List(FCMD_MINMAX, N,Y,Y,Y,N,N,N,N,N,N,Y,N,N,N,N,Y), 115 | FADD_S -> List(FCMD_ADD, N,Y,Y,Y,N,N,Y,Y,N,N,N,Y,N,N,Y,Y), 116 | FSUB_S -> List(FCMD_SUB, N,Y,Y,Y,N,N,Y,Y,N,N,N,Y,N,N,Y,Y), 117 | FMUL_S -> List(FCMD_MUL, N,Y,Y,Y,N,N,N,Y,N,N,N,Y,N,N,Y,Y), 118 | FADD_D -> List(FCMD_ADD, N,Y,Y,Y,N,N,Y,N,N,N,N,Y,N,N,Y,Y), 119 | FSUB_D -> List(FCMD_SUB, N,Y,Y,Y,N,N,Y,N,N,N,N,Y,N,N,Y,Y), 120 | FMUL_D -> List(FCMD_MUL, N,Y,Y,Y,N,N,N,N,N,N,N,Y,N,N,Y,Y), 121 | FMADD_S -> List(FCMD_MADD, N,Y,Y,Y,Y,N,N,Y,N,N,N,Y,N,N,Y,Y), 122 | FMSUB_S -> List(FCMD_MSUB, N,Y,Y,Y,Y,N,N,Y,N,N,N,Y,N,N,Y,Y), 123 | FNMADD_S -> List(FCMD_NMADD, N,Y,Y,Y,Y,N,N,Y,N,N,N,Y,N,N,Y,Y), 124 | FNMSUB_S -> List(FCMD_NMSUB, N,Y,Y,Y,Y,N,N,Y,N,N,N,Y,N,N,Y,Y), 125 | FMADD_D -> List(FCMD_MADD, N,Y,Y,Y,Y,N,N,N,N,N,N,Y,N,N,Y,Y), 126 | FMSUB_D -> List(FCMD_MSUB, N,Y,Y,Y,Y,N,N,N,N,N,N,Y,N,N,Y,Y), 127 | FNMADD_D -> List(FCMD_NMADD, N,Y,Y,Y,Y,N,N,N,N,N,N,Y,N,N,Y,Y), 128 | FNMSUB_D -> List(FCMD_NMSUB, N,Y,Y,Y,Y,N,N,N,N,N,N,Y,N,N,Y,Y), 129 | FDIV_S -> List(FCMD_DIV, N,Y,Y,Y,N,N,N,Y,N,N,N,N,Y,N,Y,Y), 130 | FSQRT_S -> List(FCMD_SQRT, N,Y,Y,N,N,Y,X,Y,N,N,N,N,N,Y,Y,Y), 131 | FDIV_D -> List(FCMD_DIV, N,Y,Y,Y,N,N,N,N,N,N,N,N,Y,N,Y,Y), 132 | FSQRT_D -> List(FCMD_SQRT, N,Y,Y,N,N,Y,X,N,N,N,N,N,N,Y,Y,Y) 133 | )) 134 | val s = io.sigs 135 | val sigs = Seq(s.cmd, s.ldst, s.wen, s.ren1, s.ren2, s.ren3, s.swap12, 136 | s.swap23, s.single, s.fromint, s.toint, s.fastpipe, s.fma, 137 | s.div, s.sqrt, s.round, s.wflags) 138 | sigs zip decoder map {case(s,d) => s := d} 139 | } 140 | 141 | class FPUIO(implicit p: Parameters) extends CoreBundle { 142 | val inst = Bits(INPUT, 32) 143 | val fromint_data = Bits(INPUT, xLen) 144 | 145 | val fcsr_rm = Bits(INPUT, FPConstants.RM_SZ) 146 | val fcsr_flags = Valid(Bits(width = FPConstants.FLAGS_SZ)) 147 | 148 | val store_data = Bits(OUTPUT, 64) 149 | val toint_data = Bits(OUTPUT, xLen) 150 | 151 | val dmem_resp_val = Bool(INPUT) 152 | val dmem_resp_type = Bits(INPUT, 3) 153 | val dmem_resp_tag = UInt(INPUT, 5) 154 | val dmem_resp_data = Bits(INPUT, 64) 155 | 156 | val valid = Bool(INPUT) 157 | val fcsr_rdy = Bool(OUTPUT) 158 | val nack_mem = Bool(OUTPUT) 159 | val illegal_rm = Bool(OUTPUT) 160 | val killx = Bool(INPUT) 161 | val killm = Bool(INPUT) 162 | val dec = new FPUCtrlSigs().asOutput 163 | val sboard_set = Bool(OUTPUT) 164 | val sboard_clr = Bool(OUTPUT) 165 | val sboard_clra = UInt(OUTPUT, 5) 166 | 167 | val cp_req = Decoupled(new FPInput()).flip //cp doesn't pay attn to kill sigs 168 | val cp_resp = Decoupled(new FPResult()) 169 | } 170 | 171 | class FPResult extends Bundle 172 | { 173 | val data = Bits(width = 65) 174 | val exc = Bits(width = 5) 175 | } 176 | 177 | class FPInput extends FPUCtrlSigs { 178 | val rm = Bits(width = 3) 179 | val typ = Bits(width = 2) 180 | val in1 = Bits(width = 65) 181 | val in2 = Bits(width = 65) 182 | val in3 = Bits(width = 65) 183 | } 184 | 185 | object ClassifyRecFN { 186 | def apply(expWidth: Int, sigWidth: Int, in: UInt) = { 187 | val sign = in(sigWidth + expWidth) 188 | val exp = in(sigWidth + expWidth - 1, sigWidth - 1) 189 | val sig = in(sigWidth - 2, 0) 190 | 191 | val code = exp(expWidth,expWidth-2) 192 | val codeHi = code(2, 1) 193 | val isSpecial = codeHi === UInt(3) 194 | 195 | val isHighSubnormalIn = exp(expWidth-2, 0) < UInt(2) 196 | val isSubnormal = code === UInt(1) || codeHi === UInt(1) && isHighSubnormalIn 197 | val isNormal = codeHi === UInt(1) && !isHighSubnormalIn || codeHi === UInt(2) 198 | val isZero = code === UInt(0) 199 | val isInf = isSpecial && !exp(expWidth-2) 200 | val isNaN = code.andR 201 | val isSNaN = isNaN && !sig(sigWidth-2) 202 | val isQNaN = isNaN && sig(sigWidth-2) 203 | 204 | Cat(isQNaN, isSNaN, isInf && !sign, isNormal && !sign, 205 | isSubnormal && !sign, isZero && !sign, isZero && sign, 206 | isSubnormal && sign, isNormal && sign, isInf && sign) 207 | } 208 | } 209 | 210 | class FPToInt extends Module 211 | { 212 | val io = new Bundle { 213 | val in = Valid(new FPInput).flip 214 | val as_double = new FPInput().asOutput 215 | val out = Valid(new Bundle { 216 | val lt = Bool() 217 | val store = Bits(width = 64) 218 | val toint = Bits(width = 64) 219 | val exc = Bits(width = 5) 220 | }) 221 | } 222 | 223 | val in = Reg(new FPInput) 224 | val valid = Reg(next=io.in.valid) 225 | 226 | def upconvert(x: UInt) = { 227 | val s2d = Module(new hardfloat.RecFNToRecFN(8, 24, 11, 53)) 228 | s2d.io.in := x 229 | s2d.io.roundingMode := UInt(0) 230 | s2d.io.out 231 | } 232 | 233 | val in1_upconvert = upconvert(io.in.bits.in1) 234 | val in2_upconvert = upconvert(io.in.bits.in2) 235 | 236 | when (io.in.valid) { 237 | in := io.in.bits 238 | when (io.in.bits.single && !io.in.bits.ldst && io.in.bits.cmd =/= FCMD_MV_XF) { 239 | in.in1 := in1_upconvert 240 | in.in2 := in2_upconvert 241 | } 242 | } 243 | 244 | val unrec_s = hardfloat.fNFromRecFN(8, 24, in.in1) 245 | val unrec_d = hardfloat.fNFromRecFN(11, 53, in.in1) 246 | val unrec_out = Mux(in.single, Cat(Fill(32, unrec_s(31)), unrec_s), unrec_d) 247 | 248 | val classify_s = ClassifyRecFN(8, 24, in.in1) 249 | val classify_d = ClassifyRecFN(11, 53, in.in1) 250 | val classify_out = Mux(in.single, classify_s, classify_d) 251 | 252 | val dcmp = Module(new hardfloat.CompareRecFN(11, 53)) 253 | dcmp.io.a := in.in1 254 | dcmp.io.b := in.in2 255 | dcmp.io.signaling := Bool(true) 256 | val dcmp_out = (~in.rm & Cat(dcmp.io.lt, dcmp.io.eq)).orR 257 | val dcmp_exc = dcmp.io.exceptionFlags 258 | 259 | val d2l = Module(new hardfloat.RecFNToIN(11, 53, 64)) 260 | val d2w = Module(new hardfloat.RecFNToIN(11, 53, 32)) 261 | d2l.io.in := in.in1 262 | d2l.io.roundingMode := in.rm 263 | d2l.io.signedOut := ~in.typ(0) 264 | d2w.io.in := in.in1 265 | d2w.io.roundingMode := in.rm 266 | d2w.io.signedOut := ~in.typ(0) 267 | 268 | io.out.bits.toint := Mux(in.rm(0), classify_out, unrec_out) 269 | io.out.bits.store := unrec_out 270 | io.out.bits.exc := Bits(0) 271 | 272 | when (in.cmd === FCMD_CMP) { 273 | io.out.bits.toint := dcmp_out 274 | io.out.bits.exc := dcmp_exc 275 | } 276 | when (in.cmd === FCMD_CVT_IF) { 277 | io.out.bits.toint := Mux(in.typ(1), d2l.io.out.toSInt, d2w.io.out.toSInt).toUInt 278 | val dflags = Mux(in.typ(1), d2l.io.intExceptionFlags, d2w.io.intExceptionFlags) 279 | io.out.bits.exc := Cat(dflags(2, 1).orR, UInt(0, 3), dflags(0)) 280 | } 281 | 282 | io.out.valid := valid 283 | io.out.bits.lt := dcmp.io.lt 284 | io.as_double := in 285 | } 286 | 287 | class IntToFP(val latency: Int) extends Module 288 | { 289 | val io = new Bundle { 290 | val in = Valid(new FPInput).flip 291 | val out = Valid(new FPResult) 292 | } 293 | 294 | val in = Pipe(io.in) 295 | 296 | val mux = Wire(new FPResult) 297 | mux.exc := Bits(0) 298 | mux.data := hardfloat.recFNFromFN(11, 53, in.bits.in1) 299 | when (in.bits.single) { 300 | mux.data := Cat(SInt(-1, 32), hardfloat.recFNFromFN(8, 24, in.bits.in1)) 301 | } 302 | 303 | val longValue = 304 | Mux(in.bits.typ(1), in.bits.in1.toSInt, 305 | Mux(in.bits.typ(0), in.bits.in1(31,0).zext, in.bits.in1(31,0).toSInt)) 306 | val l2s = Module(new hardfloat.INToRecFN(64, 8, 24)) 307 | l2s.io.signedIn := ~in.bits.typ(0) 308 | l2s.io.in := longValue.toUInt 309 | l2s.io.roundingMode := in.bits.rm 310 | 311 | val l2d = Module(new hardfloat.INToRecFN(64, 11, 53)) 312 | l2d.io.signedIn := ~in.bits.typ(0) 313 | l2d.io.in := longValue.toUInt 314 | l2d.io.roundingMode := in.bits.rm 315 | 316 | when (in.bits.cmd === FCMD_CVT_FI) { 317 | when (in.bits.single) { 318 | mux.data := Cat(SInt(-1, 32), l2s.io.out) 319 | mux.exc := l2s.io.exceptionFlags 320 | }.otherwise { 321 | mux.data := l2d.io.out 322 | mux.exc := l2d.io.exceptionFlags 323 | } 324 | } 325 | 326 | io.out <> Pipe(in.valid, mux, latency-1) 327 | } 328 | 329 | class FPToFP(val latency: Int) extends Module 330 | { 331 | val io = new Bundle { 332 | val in = Valid(new FPInput).flip 333 | val out = Valid(new FPResult) 334 | val lt = Bool(INPUT) // from FPToInt 335 | } 336 | 337 | val in = Pipe(io.in) 338 | 339 | // fp->fp units 340 | val isSgnj = in.bits.cmd === FCMD_SGNJ 341 | def fsgnjSign(in1: Bits, in2: Bits, pos: Int, en: Bool, rm: Bits) = 342 | Mux(rm(1) || !en, in1(pos), rm(0)) ^ (en && in2(pos)) 343 | val sign_s = fsgnjSign(in.bits.in1, in.bits.in2, 32, in.bits.single && isSgnj, in.bits.rm) 344 | val sign_d = fsgnjSign(in.bits.in1, in.bits.in2, 64, !in.bits.single && isSgnj, in.bits.rm) 345 | val fsgnj = Cat(sign_d, in.bits.in1(63,33), sign_s, in.bits.in1(31,0)) 346 | 347 | val s2d = Module(new hardfloat.RecFNToRecFN(8, 24, 11, 53)) 348 | val d2s = Module(new hardfloat.RecFNToRecFN(11, 53, 8, 24)) 349 | s2d.io.in := in.bits.in1 350 | s2d.io.roundingMode := in.bits.rm 351 | d2s.io.in := in.bits.in1 352 | d2s.io.roundingMode := in.bits.rm 353 | 354 | val isnan1 = Mux(in.bits.single, in.bits.in1(31,29).andR, in.bits.in1(63,61).andR) 355 | val isnan2 = Mux(in.bits.single, in.bits.in2(31,29).andR, in.bits.in2(63,61).andR) 356 | val issnan1 = isnan1 && ~Mux(in.bits.single, in.bits.in1(22), in.bits.in1(51)) 357 | val issnan2 = isnan2 && ~Mux(in.bits.single, in.bits.in2(22), in.bits.in2(51)) 358 | val minmax_exc = Cat(issnan1 || issnan2, Bits(0,4)) 359 | val isMax = in.bits.rm(0) 360 | val isLHS = isnan2 || isMax =/= io.lt && !isnan1 361 | 362 | val mux = Wire(new FPResult) 363 | mux.exc := minmax_exc 364 | mux.data := in.bits.in2 365 | 366 | when (isSgnj) { mux.exc := UInt(0) } 367 | when (isSgnj || isLHS) { mux.data := fsgnj } 368 | when (in.bits.cmd === FCMD_CVT_FF) { 369 | when (in.bits.single) { 370 | mux.data := Cat(SInt(-1, 32), d2s.io.out) 371 | mux.exc := d2s.io.exceptionFlags 372 | }.otherwise { 373 | mux.data := s2d.io.out 374 | mux.exc := s2d.io.exceptionFlags 375 | } 376 | } 377 | 378 | io.out <> Pipe(in.valid, mux, latency-1) 379 | } 380 | 381 | class FPUFMAPipe(val latency: Int, expWidth: Int, sigWidth: Int) extends Module 382 | { 383 | val io = new Bundle { 384 | val in = Valid(new FPInput).flip 385 | val out = Valid(new FPResult) 386 | } 387 | 388 | val width = sigWidth + expWidth 389 | val one = UInt(1) << (width-1) 390 | val zero = (io.in.bits.in1(width) ^ io.in.bits.in2(width)) << width 391 | 392 | val valid = Reg(next=io.in.valid) 393 | val in = Reg(new FPInput) 394 | when (io.in.valid) { 395 | in := io.in.bits 396 | val cmd_fma = io.in.bits.ren3 397 | val cmd_addsub = io.in.bits.swap23 398 | in.cmd := Cat(io.in.bits.cmd(1) & (cmd_fma || cmd_addsub), io.in.bits.cmd(0)) 399 | when (cmd_addsub) { in.in2 := one } 400 | unless (cmd_fma || cmd_addsub) { in.in3 := zero } 401 | } 402 | 403 | val fma = Module(new hardfloat.MulAddRecFN(expWidth, sigWidth)) 404 | fma.io.op := in.cmd 405 | fma.io.roundingMode := in.rm 406 | fma.io.a := in.in1 407 | fma.io.b := in.in2 408 | fma.io.c := in.in3 409 | 410 | val res = Wire(new FPResult) 411 | res.data := Cat(SInt(-1, 32), fma.io.out) 412 | res.exc := fma.io.exceptionFlags 413 | io.out := Pipe(valid, res, latency-1) 414 | } 415 | 416 | class FPU(implicit p: Parameters) extends CoreModule()(p) { 417 | require(xLen == 64, "RV32 Rocket FP support missing") 418 | val io = new FPUIO 419 | 420 | val ex_reg_valid = Reg(next=io.valid, init=Bool(false)) 421 | val req_valid = ex_reg_valid || io.cp_req.valid 422 | val ex_reg_inst = RegEnable(io.inst, io.valid) 423 | val ex_cp_valid = io.cp_req.valid && !ex_reg_valid 424 | val mem_reg_valid = Reg(next=ex_reg_valid && !io.killx || ex_cp_valid, init=Bool(false)) 425 | val mem_reg_inst = RegEnable(ex_reg_inst, ex_reg_valid) 426 | val mem_cp_valid = Reg(next=ex_cp_valid, init=Bool(false)) 427 | val killm = (io.killm || io.nack_mem) && !mem_cp_valid 428 | val wb_reg_valid = Reg(next=mem_reg_valid && (!killm || mem_cp_valid), init=Bool(false)) 429 | val wb_cp_valid = Reg(next=mem_cp_valid, init=Bool(false)) 430 | 431 | val fp_decoder = Module(new FPUDecoder) 432 | fp_decoder.io.inst := io.inst 433 | 434 | val cp_ctrl = Wire(new FPUCtrlSigs) 435 | cp_ctrl <> io.cp_req.bits 436 | io.cp_resp.valid := Bool(false) 437 | io.cp_resp.bits.data := UInt(0) 438 | 439 | val id_ctrl = fp_decoder.io.sigs 440 | val ex_ctrl = Mux(ex_reg_valid, RegEnable(id_ctrl, io.valid), cp_ctrl) 441 | val mem_ctrl = RegEnable(ex_ctrl, req_valid) 442 | val wb_ctrl = RegEnable(mem_ctrl, mem_reg_valid) 443 | 444 | // load response 445 | val load_wb = Reg(next=io.dmem_resp_val) 446 | val load_wb_single = RegEnable(io.dmem_resp_type === MT_W || io.dmem_resp_type === MT_WU, io.dmem_resp_val) 447 | val load_wb_data = RegEnable(io.dmem_resp_data, io.dmem_resp_val) 448 | val load_wb_tag = RegEnable(io.dmem_resp_tag, io.dmem_resp_val) 449 | val rec_s = hardfloat.recFNFromFN(8, 24, load_wb_data) 450 | val rec_d = hardfloat.recFNFromFN(11, 53, load_wb_data) 451 | val load_wb_data_recoded = Mux(load_wb_single, Cat(SInt(-1, 32), rec_s), rec_d) 452 | 453 | // regfile 454 | val regfile = Mem(32, Bits(width = 65)) 455 | when (load_wb) { 456 | regfile(load_wb_tag) := load_wb_data_recoded 457 | if (enableCommitLog) { 458 | printf ("f%d p%d 0x%x\n", load_wb_tag, load_wb_tag + UInt(32), 459 | Mux(load_wb_single, load_wb_data(31,0), load_wb_data)) 460 | } 461 | } 462 | 463 | val ex_ra1::ex_ra2::ex_ra3::Nil = List.fill(3)(Reg(UInt())) 464 | when (io.valid) { 465 | when (id_ctrl.ren1) { 466 | when (!id_ctrl.swap12) { ex_ra1 := io.inst(19,15) } 467 | when (id_ctrl.swap12) { ex_ra2 := io.inst(19,15) } 468 | } 469 | when (id_ctrl.ren2) { 470 | when (id_ctrl.swap12) { ex_ra1 := io.inst(24,20) } 471 | when (id_ctrl.swap23) { ex_ra3 := io.inst(24,20) } 472 | when (!id_ctrl.swap12 && !id_ctrl.swap23) { ex_ra2 := io.inst(24,20) } 473 | } 474 | when (id_ctrl.ren3) { ex_ra3 := io.inst(31,27) } 475 | } 476 | val ex_rs1::ex_rs2::ex_rs3::Nil = Seq(ex_ra1, ex_ra2, ex_ra3).map(regfile(_)) 477 | val ex_rm = Mux(ex_reg_inst(14,12) === Bits(7), io.fcsr_rm, ex_reg_inst(14,12)) 478 | 479 | val cp_rs1 = io.cp_req.bits.in1 480 | val cp_rs2 = Mux(io.cp_req.bits.swap23, io.cp_req.bits.in3, io.cp_req.bits.in2) 481 | val cp_rs3 = Mux(io.cp_req.bits.swap23, io.cp_req.bits.in2, io.cp_req.bits.in3) 482 | 483 | val req = Wire(new FPInput) 484 | req := ex_ctrl 485 | req.rm := Mux(ex_reg_valid, ex_rm, io.cp_req.bits.rm) 486 | req.in1 := Mux(ex_reg_valid, ex_rs1, cp_rs1) 487 | req.in2 := Mux(ex_reg_valid, ex_rs2, cp_rs2) 488 | req.in3 := Mux(ex_reg_valid, ex_rs3, cp_rs3) 489 | req.typ := Mux(ex_reg_valid, ex_reg_inst(21,20), io.cp_req.bits.typ) 490 | 491 | val sfma = Module(new FPUFMAPipe(p(SFMALatency), 8, 24)) 492 | sfma.io.in.valid := req_valid && ex_ctrl.fma && ex_ctrl.single 493 | sfma.io.in.bits := req 494 | 495 | val dfma = Module(new FPUFMAPipe(p(DFMALatency), 11, 53)) 496 | dfma.io.in.valid := req_valid && ex_ctrl.fma && !ex_ctrl.single 497 | dfma.io.in.bits := req 498 | 499 | val fpiu = Module(new FPToInt) 500 | fpiu.io.in.valid := req_valid && (ex_ctrl.toint || ex_ctrl.div || ex_ctrl.sqrt || ex_ctrl.cmd === FCMD_MINMAX) 501 | fpiu.io.in.bits := req 502 | io.store_data := fpiu.io.out.bits.store 503 | io.toint_data := fpiu.io.out.bits.toint 504 | when(fpiu.io.out.valid && mem_cp_valid && mem_ctrl.toint){ 505 | io.cp_resp.bits.data := fpiu.io.out.bits.toint 506 | io.cp_resp.valid := Bool(true) 507 | } 508 | 509 | val ifpu = Module(new IntToFP(3)) 510 | ifpu.io.in.valid := req_valid && ex_ctrl.fromint 511 | ifpu.io.in.bits := req 512 | ifpu.io.in.bits.in1 := Mux(ex_reg_valid, io.fromint_data, cp_rs1) 513 | 514 | val fpmu = Module(new FPToFP(2)) 515 | fpmu.io.in.valid := req_valid && ex_ctrl.fastpipe 516 | fpmu.io.in.bits := req 517 | fpmu.io.lt := fpiu.io.out.bits.lt 518 | 519 | val divSqrt_wen = Reg(next=Bool(false)) 520 | val divSqrt_inReady = Wire(init=Bool(false)) 521 | val divSqrt_waddr = Reg(Bits()) 522 | val divSqrt_wdata = Wire(Bits()) 523 | val divSqrt_flags = Wire(Bits()) 524 | val divSqrt_in_flight = Reg(init=Bool(false)) 525 | val divSqrt_killed = Reg(Bool()) 526 | 527 | // writeback arbitration 528 | case class Pipe(p: Module, lat: Int, cond: (FPUCtrlSigs) => Bool, res: FPResult) 529 | val pipes = List( 530 | Pipe(fpmu, fpmu.latency, (c: FPUCtrlSigs) => c.fastpipe, fpmu.io.out.bits), 531 | Pipe(ifpu, ifpu.latency, (c: FPUCtrlSigs) => c.fromint, ifpu.io.out.bits), 532 | Pipe(sfma, sfma.latency, (c: FPUCtrlSigs) => c.fma && c.single, sfma.io.out.bits), 533 | Pipe(dfma, dfma.latency, (c: FPUCtrlSigs) => c.fma && !c.single, dfma.io.out.bits)) 534 | def latencyMask(c: FPUCtrlSigs, offset: Int) = { 535 | require(pipes.forall(_.lat >= offset)) 536 | pipes.map(p => Mux(p.cond(c), UInt(1 << p.lat-offset), UInt(0))).reduce(_|_) 537 | } 538 | def pipeid(c: FPUCtrlSigs) = pipes.zipWithIndex.map(p => Mux(p._1.cond(c), UInt(p._2), UInt(0))).reduce(_|_) 539 | val maxLatency = pipes.map(_.lat).max 540 | val memLatencyMask = latencyMask(mem_ctrl, 2) 541 | 542 | val wen = Reg(init=Bits(0, maxLatency-1)) 543 | val winfo = Reg(Vec(maxLatency-1, Bits())) 544 | val mem_wen = mem_reg_valid && (mem_ctrl.fma || mem_ctrl.fastpipe || mem_ctrl.fromint) 545 | val write_port_busy = RegEnable(mem_wen && (memLatencyMask & latencyMask(ex_ctrl, 1)).orR || (wen & latencyMask(ex_ctrl, 0)).orR, req_valid) 546 | val mem_winfo = Cat(mem_cp_valid, pipeid(mem_ctrl), mem_ctrl.single, mem_reg_inst(11,7)) //single only used for debugging 547 | 548 | for (i <- 0 until maxLatency-2) { 549 | when (wen(i+1)) { winfo(i) := winfo(i+1) } 550 | } 551 | wen := wen >> 1 552 | when (mem_wen) { 553 | when (!killm) { 554 | wen := wen >> 1 | memLatencyMask 555 | } 556 | for (i <- 0 until maxLatency-1) { 557 | when (!write_port_busy && memLatencyMask(i)) { 558 | winfo(i) := mem_winfo 559 | } 560 | } 561 | } 562 | 563 | val waddr = Mux(divSqrt_wen, divSqrt_waddr, winfo(0)(4,0).toUInt) 564 | val wsrc = (winfo(0) >> 6) 565 | val wcp = winfo(0)(6+log2Up(pipes.size)) 566 | val wdata = Mux(divSqrt_wen, divSqrt_wdata, Vec(pipes.map(_.res.data))(wsrc)) 567 | val wexc = Vec(pipes.map(_.res.exc))(wsrc) 568 | when ((!wcp && wen(0)) || divSqrt_wen) { 569 | regfile(waddr) := wdata 570 | if (enableCommitLog) { 571 | val wdata_unrec_s = hardfloat.fNFromRecFN(8, 24, wdata(64,0)) 572 | val wdata_unrec_d = hardfloat.fNFromRecFN(11, 53, wdata(64,0)) 573 | val wb_single = (winfo(0) >> 5)(0) 574 | printf ("f%d p%d 0x%x\n", waddr, waddr+ UInt(32), 575 | Mux(wb_single, Cat(UInt(0,32), wdata_unrec_s), wdata_unrec_d)) 576 | } 577 | } 578 | when (wcp && wen(0)) { 579 | io.cp_resp.bits.data := wdata 580 | io.cp_resp.valid := Bool(true) 581 | } 582 | io.cp_req.ready := !ex_reg_valid 583 | 584 | val wb_toint_valid = wb_reg_valid && wb_ctrl.toint 585 | val wb_toint_exc = RegEnable(fpiu.io.out.bits.exc, mem_ctrl.toint) 586 | io.fcsr_flags.valid := wb_toint_valid || divSqrt_wen || wen(0) 587 | io.fcsr_flags.bits := 588 | Mux(wb_toint_valid, wb_toint_exc, UInt(0)) | 589 | Mux(divSqrt_wen, divSqrt_flags, UInt(0)) | 590 | Mux(wen(0), wexc, UInt(0)) 591 | 592 | val units_busy = mem_reg_valid && (mem_ctrl.div || mem_ctrl.sqrt) && (!divSqrt_inReady || wen.orR) // || mem_reg_valid && mem_ctrl.fma && Reg(next=Mux(ex_ctrl.single, io.sfma.valid, io.dfma.valid)) 593 | io.fcsr_rdy := !(ex_reg_valid && ex_ctrl.wflags || mem_reg_valid && mem_ctrl.wflags || wb_reg_valid && wb_ctrl.toint || wen.orR || divSqrt_in_flight) 594 | io.nack_mem := units_busy || write_port_busy || divSqrt_in_flight 595 | io.dec <> fp_decoder.io.sigs 596 | def useScoreboard(f: ((Pipe, Int)) => Bool) = pipes.zipWithIndex.filter(_._1.lat > 3).map(x => f(x)).fold(Bool(false))(_||_) 597 | io.sboard_set := wb_reg_valid && !wb_cp_valid && Reg(next=useScoreboard(_._1.cond(mem_ctrl)) || mem_ctrl.div || mem_ctrl.sqrt) 598 | io.sboard_clr := !wb_cp_valid && (divSqrt_wen || (wen(0) && useScoreboard(x => wsrc === UInt(x._2)))) 599 | io.sboard_clra := waddr 600 | // we don't currently support round-max-magnitude (rm=4) 601 | io.illegal_rm := ex_rm(2) && ex_ctrl.round 602 | 603 | divSqrt_wdata := 0 604 | divSqrt_flags := 0 605 | if (p(FDivSqrt)) { 606 | val divSqrt_single = Reg(Bool()) 607 | val divSqrt_rm = Reg(Bits()) 608 | val divSqrt_flags_double = Reg(Bits()) 609 | val divSqrt_wdata_double = Reg(Bits()) 610 | 611 | val divSqrt = Module(new hardfloat.DivSqrtRecF64) 612 | divSqrt_inReady := Mux(divSqrt.io.sqrtOp, divSqrt.io.inReady_sqrt, divSqrt.io.inReady_div) 613 | val divSqrt_outValid = divSqrt.io.outValid_div || divSqrt.io.outValid_sqrt 614 | divSqrt.io.inValid := mem_reg_valid && (mem_ctrl.div || mem_ctrl.sqrt) && !divSqrt_in_flight 615 | divSqrt.io.sqrtOp := mem_ctrl.sqrt 616 | divSqrt.io.a := fpiu.io.as_double.in1 617 | divSqrt.io.b := fpiu.io.as_double.in2 618 | divSqrt.io.roundingMode := fpiu.io.as_double.rm 619 | 620 | when (divSqrt.io.inValid && divSqrt_inReady) { 621 | divSqrt_in_flight := true 622 | divSqrt_killed := killm 623 | divSqrt_single := mem_ctrl.single 624 | divSqrt_waddr := mem_reg_inst(11,7) 625 | divSqrt_rm := divSqrt.io.roundingMode 626 | } 627 | 628 | when (divSqrt_outValid) { 629 | divSqrt_wen := !divSqrt_killed 630 | divSqrt_wdata_double := divSqrt.io.out 631 | divSqrt_in_flight := false 632 | divSqrt_flags_double := divSqrt.io.exceptionFlags 633 | } 634 | 635 | val divSqrt_toSingle = Module(new hardfloat.RecFNToRecFN(11, 53, 8, 24)) 636 | divSqrt_toSingle.io.in := divSqrt_wdata_double 637 | divSqrt_toSingle.io.roundingMode := divSqrt_rm 638 | divSqrt_wdata := Mux(divSqrt_single, divSqrt_toSingle.io.out, divSqrt_wdata_double) 639 | divSqrt_flags := divSqrt_flags_double | Mux(divSqrt_single, divSqrt_toSingle.io.exceptionFlags, Bits(0)) 640 | } 641 | } 642 | -------------------------------------------------------------------------------- /src/main/scala/frontend.scala: -------------------------------------------------------------------------------- 1 | package rocket 2 | 3 | import Chisel._ 4 | import uncore._ 5 | import Util._ 6 | import cde.{Parameters, Field} 7 | import scala.math.max 8 | 9 | class FrontendReq(implicit p: Parameters) extends CoreBundle()(p) { 10 | val pc = UInt(width = vaddrBitsExtended) 11 | val pc_tag = UInt(width = tgBits) 12 | } 13 | 14 | class FrontendResp(implicit p: Parameters) extends CoreBundle()(p) { 15 | val pc = UInt(width = vaddrBitsExtended) // ID stage PC 16 | val pc_tag = UInt(width = tgBits) 17 | val data = Vec(fetchWidth, Bits(width = coreInstBits)) 18 | val tag = Vec(fetchWidth, Bits(width = tgInstBits)) 19 | val mask = Bits(width = fetchWidth) 20 | val xcpt_if = Bool() 21 | } 22 | 23 | class FrontendIO(implicit p: Parameters) extends CoreBundle()(p) { 24 | val req = Valid(new FrontendReq) 25 | val resp = Decoupled(new FrontendResp).flip 26 | val btb_resp = Valid(new BTBResp).flip 27 | val btb_update = Valid(new BTBUpdate) 28 | val bht_update = Valid(new BHTUpdate) 29 | val ras_update = Valid(new RASUpdate) 30 | val flush_icache = Bool(OUTPUT) 31 | val flush_tlb = Bool(OUTPUT) 32 | val npc = UInt(INPUT, width = vaddrBitsExtended) 33 | } 34 | 35 | class Frontend(implicit p: Parameters) extends CoreModule()(p) with HasL1CacheParameters { 36 | val io = new Bundle { 37 | val cpu = new FrontendIO().flip 38 | val ptw = new TLBPTWIO() 39 | val mem = new ClientUncachedTileLinkIO 40 | } 41 | 42 | val icache = Module(new ICache) 43 | val tlb = Module(new TLB) 44 | 45 | val s1_pc_ = Reg(UInt(width=vaddrBitsExtended)) 46 | val s1_pc = ~(~s1_pc_ | (coreInstBytes-1)) // discard PC LSBS (this propagates down the pipeline) 47 | val s1_pc_tag = Reg(init=UInt(0, tgBits)) 48 | val s1_same_block = Reg(Bool()) 49 | val s2_valid = Reg(init=Bool(true)) 50 | val s2_pc = Reg(init=UInt(p(ResetVector))) 51 | val s2_pc_tag = Reg(init=UInt(0, tgBits)) 52 | val s2_btb_resp_valid = Reg(init=Bool(false)) 53 | val s2_btb_resp_bits = Reg(new BTBResp) 54 | val s2_xcpt_if = Reg(init=Bool(false)) 55 | val s2_resp_valid = Wire(init=Bool(false)) 56 | val s2_resp_data = Wire(UInt(width = rowBits)) 57 | val s2_resp_tag = Wire(UInt(width = rowTagBits)) 58 | 59 | val ntpc_0 = ~(~s1_pc | (coreInstBytes*fetchWidth-1)) + UInt(coreInstBytes*fetchWidth) 60 | val ntpc = // don't increment PC into virtual address space hole 61 | if (vaddrBitsExtended == vaddrBits) ntpc_0 62 | else Cat(s1_pc(vaddrBits-1) & ntpc_0(vaddrBits-1), ntpc_0) 63 | val predicted_npc = Wire(init = ntpc) 64 | val icmiss = s2_valid && !s2_resp_valid 65 | val npc = Mux(icmiss, s2_pc, predicted_npc).toUInt 66 | val npc_tag = Mux(icmiss, s2_pc_tag, UInt(0)) 67 | val s0_same_block = Wire(init = !icmiss && !io.cpu.req.valid && ((ntpc & rowBytes) === (s1_pc & rowBytes))) 68 | 69 | val stall = io.cpu.resp.valid && !io.cpu.resp.ready 70 | when (!stall) { 71 | s1_same_block := s0_same_block && !tlb.io.resp.miss 72 | s1_pc_ := npc 73 | s1_pc_tag := npc_tag 74 | s2_valid := !icmiss 75 | when (!icmiss) { 76 | s2_pc := s1_pc 77 | s2_pc_tag := s1_pc_tag 78 | s2_xcpt_if := tlb.io.resp.xcpt_if 79 | } 80 | } 81 | when (io.cpu.req.valid) { 82 | s1_same_block := Bool(false) 83 | s1_pc_ := io.cpu.req.bits.pc 84 | s1_pc_tag := io.cpu.req.bits.pc_tag 85 | s2_valid := Bool(false) 86 | } 87 | 88 | if (p(BtbKey).nEntries > 0) { 89 | val btb = Module(new BTB) 90 | btb.io.req.valid := false 91 | btb.io.req.bits.addr := s1_pc 92 | btb.io.btb_update := io.cpu.btb_update 93 | btb.io.bht_update := io.cpu.bht_update 94 | btb.io.ras_update := io.cpu.ras_update 95 | btb.io.invalidate := io.cpu.flush_icache || io.cpu.flush_tlb // virtual tags 96 | when (!stall && !icmiss) { 97 | btb.io.req.valid := true 98 | s2_btb_resp_valid := btb.io.resp.valid 99 | s2_btb_resp_bits := btb.io.resp.bits 100 | } 101 | when (btb.io.resp.bits.taken) { 102 | predicted_npc := btb.io.resp.bits.target.sextTo(vaddrBitsExtended) 103 | s0_same_block := Bool(false) 104 | } 105 | } 106 | 107 | io.ptw <> tlb.io.ptw 108 | tlb.io.req.valid := !stall && !icmiss 109 | tlb.io.req.bits.vpn := s1_pc >> pgIdxBits 110 | tlb.io.req.bits.asid := UInt(0) 111 | tlb.io.req.bits.passthrough := Bool(false) 112 | tlb.io.req.bits.instruction := Bool(true) 113 | tlb.io.req.bits.store := Bool(false) 114 | 115 | io.mem <> icache.io.mem 116 | icache.io.req.valid := !stall && !s0_same_block 117 | icache.io.req.bits.idx := io.cpu.npc 118 | icache.io.invalidate := io.cpu.flush_icache 119 | icache.io.s1_ppn := tlb.io.resp.ppn 120 | icache.io.s1_kill := io.cpu.req.valid || tlb.io.resp.miss || tlb.io.resp.xcpt_if || icmiss || io.cpu.flush_tlb 121 | 122 | io.cpu.resp.valid := s2_valid && (s2_xcpt_if || s2_resp_valid) 123 | io.cpu.resp.bits.pc := s2_pc 124 | io.cpu.resp.bits.pc_tag := s2_pc_tag 125 | io.cpu.npc := Mux(io.cpu.req.valid, io.cpu.req.bits.pc, npc) 126 | 127 | // if the ways are buffered, we don't need to buffer again 128 | if (p(ICacheBufferWays)) { 129 | icache.io.resp.ready := !stall && !s1_same_block 130 | 131 | s2_resp_valid := icache.io.resp.valid 132 | s2_resp_data := icache.io.resp.bits.datablock 133 | s2_resp_tag := icache.io.resp.bits.tagblock 134 | } else { 135 | val icbuf = Module(new Queue(new ICacheResp, 1, pipe=true)) 136 | icbuf.io.enq <> icache.io.resp 137 | icbuf.io.deq.ready := !stall && !s1_same_block 138 | 139 | s2_resp_valid := icbuf.io.deq.valid 140 | s2_resp_data := icbuf.io.deq.bits.datablock 141 | s2_resp_tag := icbuf.io.deq.bits.tagblock 142 | } 143 | 144 | require(fetchWidth * coreInstBytes <= rowBytes) 145 | val fetch_data = 146 | if (fetchWidth * coreInstBytes == rowBytes) s2_resp_data 147 | else s2_resp_data >> (s2_pc(log2Up(rowBytes)-1,log2Up(fetchWidth*coreInstBytes)) << log2Up(fetchWidth*coreInstBits)) 148 | val fetch_tag = 149 | if (fetchWidth * coreInstBytes == rowBytes) s2_resp_tag 150 | else s2_resp_tag >> (s2_pc(log2Up(rowBytes)-1,2) * tgBits / 2) 151 | 152 | val coreInstTagBitsMax = max(coreInstBits, 32) / 32 * (tgBits/2) 153 | for (i <- 0 until fetchWidth) { 154 | io.cpu.resp.bits.data(i) := fetch_data(i*coreInstBits+coreInstBits-1, i*coreInstBits) 155 | io.cpu.resp.bits.tag(i) := fetch_tag(i*coreInstTagBitsMax+tgInstBits-1, i*coreInstTagBitsMax) 156 | } 157 | 158 | val all_ones = UInt((1 << (fetchWidth+1))-1) 159 | val msk_pc = if (fetchWidth == 1) all_ones else all_ones << s2_pc(log2Up(fetchWidth) -1+2,2) 160 | io.cpu.resp.bits.mask := msk_pc 161 | io.cpu.resp.bits.xcpt_if := s2_xcpt_if 162 | 163 | io.cpu.btb_resp.valid := s2_btb_resp_valid 164 | io.cpu.btb_resp.bits := s2_btb_resp_bits 165 | } 166 | -------------------------------------------------------------------------------- /src/main/scala/icache.scala: -------------------------------------------------------------------------------- 1 | package rocket 2 | 3 | import Chisel._ 4 | import uncore._ 5 | import Util._ 6 | import cde.{Parameters, Field} 7 | 8 | case object ICacheBufferWays extends Field[Boolean] 9 | 10 | trait HasL1CacheParameters extends HasCacheParameters with HasCoreParameters with HasTagParameters { 11 | val outerDataBeats = p(TLKey(p(TLId))).dataBeats 12 | val outerDataBits = p(TLKey(p(TLId))).dataBitsPerBeat 13 | val outerDataBytes = outerDataBits/8 14 | val refillCyclesPerBeat = outerDataBits/rowBits 15 | val refillCycles = refillCyclesPerBeat*outerDataBeats 16 | } 17 | 18 | class ICacheReq(implicit p: Parameters) extends CoreBundle()(p) { 19 | val idx = UInt(width = pgIdxBits) 20 | } 21 | 22 | class ICacheResp(implicit p: Parameters) extends CoreBundle()(p) with HasL1CacheParameters { 23 | val data = Bits(width = coreInstBits) 24 | val datablock = Bits(width = rowBits) 25 | val tagblock = Bits(width = rowTagBits) 26 | } 27 | 28 | class ICache(implicit p: Parameters) extends CoreModule()(p) with HasL1CacheParameters { 29 | val io = new Bundle { 30 | val req = Valid(new ICacheReq).flip 31 | val s1_ppn = UInt(INPUT, ppnBits) // delayed one cycle w.r.t. req 32 | val s1_kill = Bool(INPUT) // delayed one cycle w.r.t. req 33 | 34 | val resp = Decoupled(new ICacheResp) 35 | val invalidate = Bool(INPUT) 36 | val mem = new ClientUncachedTileLinkIO 37 | } 38 | require(isPow2(nSets) && isPow2(nWays)) 39 | require(isPow2(coreInstBytes)) 40 | require(pgIdxBits >= untagBits) 41 | 42 | val s_ready :: s_request :: s_refill_wait :: s_refill :: Nil = Enum(UInt(), 4) 43 | val state = Reg(init=s_ready) 44 | val invalidated = Reg(Bool()) 45 | val stall = !io.resp.ready 46 | val rdy = Wire(Bool()) 47 | 48 | val refill_addr = Reg(UInt(width = paddrBits)) 49 | val s1_any_tag_hit = Wire(Bool()) 50 | 51 | val s1_valid = Reg(init=Bool(false)) 52 | val s1_pgoff = Reg(UInt(width = pgIdxBits)) 53 | val s1_addr = Cat(io.s1_ppn, s1_pgoff).toUInt 54 | val s1_tag = s1_addr(tagBits+untagBits-1,untagBits) 55 | 56 | val s0_valid = io.req.valid || s1_valid && stall 57 | val s0_pgoff = Mux(s1_valid && stall, s1_pgoff, io.req.bits.idx) 58 | 59 | s1_valid := io.req.valid && rdy || s1_valid && stall && !io.s1_kill 60 | when (io.req.valid && rdy) { 61 | s1_pgoff := io.req.bits.idx 62 | } 63 | 64 | val out_valid = s1_valid && !io.s1_kill && state === s_ready 65 | val s1_idx = s1_addr(untagBits-1,blockOffBits) 66 | val s1_offset = s1_addr(blockOffBits-1,0) 67 | val s1_hit = out_valid && s1_any_tag_hit 68 | val s1_miss = out_valid && !s1_any_tag_hit 69 | rdy := state === s_ready && !s1_miss 70 | 71 | when (s1_valid && state === s_ready && s1_miss) { 72 | refill_addr := s1_addr 73 | } 74 | val refill_tag = refill_addr(tagBits+untagBits-1,untagBits) 75 | 76 | val narrow_grant = FlowThroughSerializer(io.mem.grant, refillCyclesPerBeat) 77 | val (refill_cnt, refill_wrap) = Counter(narrow_grant.fire(), refillCycles) //TODO Zero width wire 78 | val refill_done = state === s_refill && refill_wrap 79 | narrow_grant.ready := Bool(true) 80 | 81 | val repl_way = if (isDM) UInt(0) else LFSR16(s1_miss)(log2Up(nWays)-1,0) 82 | val entagbits = code.width(tagBits) 83 | val tag_array = SeqMem(nSets, Vec(nWays, Bits(width = entagbits))) 84 | val tag_rdata = tag_array.read(s0_pgoff(untagBits-1,blockOffBits), !refill_done && s0_valid) 85 | when (refill_done) { 86 | val tag = code.encode(refill_tag).toUInt 87 | tag_array.write(s1_idx, Vec.fill(nWays)(tag), Vec.tabulate(nWays)(repl_way === _)) 88 | } 89 | 90 | val vb_array = Reg(init=Bits(0, nSets*nWays)) 91 | when (refill_done && !invalidated) { 92 | vb_array := vb_array.bitSet(Cat(repl_way, s1_idx), Bool(true)) 93 | } 94 | when (io.invalidate) { 95 | vb_array := Bits(0) 96 | invalidated := Bool(true) 97 | } 98 | val s1_disparity = Wire(Vec(nWays, Bool())) 99 | for (i <- 0 until nWays) 100 | when (s1_valid && s1_disparity(i)) { vb_array := vb_array.bitSet(Cat(UInt(i), s1_idx), Bool(false)) } 101 | 102 | val s1_tag_match = Wire(Vec(nWays, Bool())) 103 | val s1_tag_hit = Wire(Vec(nWays, Bool())) 104 | val s1_dout = Wire(Vec(nWays, Bits(width = rowBits))) 105 | val s1_tout = Wire(init=Vec.fill(nWays)(Bits(0, width = rowTagBits))) 106 | 107 | for (i <- 0 until nWays) { 108 | val s1_vb = !io.invalidate && vb_array(Cat(UInt(i), s1_pgoff(untagBits-1,blockOffBits))).toBool 109 | val tag_out = tag_rdata(i) 110 | val s1_tag_disparity = code.decode(tag_out).error 111 | s1_tag_match(i) := tag_out(tagBits-1,0) === s1_tag 112 | s1_tag_hit(i) := s1_vb && s1_tag_match(i) 113 | s1_disparity(i) := s1_vb && (s1_tag_disparity || code.decode(s1_dout(i)).error) 114 | } 115 | s1_any_tag_hit := s1_tag_hit.reduceLeft(_||_) && !s1_disparity.reduceLeft(_||_) 116 | 117 | for (i <- 0 until nWays) { 118 | val data_array = if(useTagMem) SeqMem(nSets * refillCycles, Bits(width = code.width(rowBits)+rowTagBits)) 119 | else SeqMem(nSets * refillCycles, Bits(width = code.width(rowBits))) 120 | val wen = narrow_grant.valid && repl_way === UInt(i) 121 | when (wen) { 122 | val e_d = if(useTagMem) Cat(code.encode(narrow_grant.bits.data).toUInt, narrow_grant.bits.tag) 123 | else code.encode(narrow_grant.bits.data).toUInt 124 | if(refillCycles > 1) data_array.write(Cat(s1_idx, refill_cnt), e_d) 125 | else data_array.write(s1_idx, e_d) 126 | } 127 | val s0_raddr = s0_pgoff(untagBits-1,blockOffBits-(if(refillCycles > 1) refill_cnt.getWidth else 0)) 128 | val rdout = data_array.read(s0_raddr, !wen && s0_valid) 129 | if(useTagMem) { 130 | s1_dout(i) := rdout >> rowTagBits 131 | s1_tout(i) := rdout(rowTagBits-1,0) 132 | } else { 133 | s1_dout(i) := rdout 134 | s1_tout(i) := UInt(0) 135 | } 136 | } 137 | 138 | // output signals 139 | if (p(ICacheBufferWays)) { 140 | val s2_hit = RegEnable(s1_hit, !stall) 141 | val s2_tag_hit = RegEnable(s1_tag_hit, !stall) 142 | val s2_dout = RegEnable(s1_dout, !stall) 143 | val s2_tout = RegEnable(s1_tout, !stall) 144 | io.resp.bits.datablock := Mux1H(s2_tag_hit, s2_dout) 145 | io.resp.bits.tagblock := Mux1H(s2_tag_hit, s2_tout) 146 | io.resp.valid := s2_hit 147 | } else { 148 | io.resp.bits.datablock := Mux1H(s1_tag_hit, s1_dout) 149 | io.resp.bits.tagblock := Mux1H(s1_tag_hit, s1_tout) 150 | io.resp.valid := s1_hit 151 | } 152 | io.mem.acquire.valid := (state === s_request) 153 | io.mem.acquire.bits := GetBlock(addr_block = refill_addr >> blockOffBits) 154 | 155 | // control state machine 156 | switch (state) { 157 | is (s_ready) { 158 | when (s1_miss) { state := s_request } 159 | invalidated := Bool(false) 160 | } 161 | is (s_request) { 162 | when (io.mem.acquire.ready) { state := s_refill_wait } 163 | } 164 | is (s_refill_wait) { 165 | when (io.mem.grant.valid) { state := s_refill } 166 | } 167 | is (s_refill) { 168 | when (refill_done) { state := s_ready } 169 | } 170 | } 171 | } 172 | -------------------------------------------------------------------------------- /src/main/scala/idecode.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details 2 | 3 | package rocket 4 | 5 | import Chisel._ 6 | import Instructions._ 7 | import uncore.constants.MemoryOpConstants._ 8 | import ALU._ 9 | import cde.Parameters 10 | 11 | abstract trait DecodeConstants extends HasCoreParameters 12 | { 13 | val xpr64 = Bool(xLen == 64) 14 | 15 | val table: Array[(BitPat, List[BitPat])] 16 | } 17 | 18 | class IntCtrlSigs extends Bundle { 19 | val legal = Bool() 20 | val fp = Bool() 21 | val rocc = Bool() 22 | val branch = Bool() 23 | val jal = Bool() 24 | val jalr = Bool() 25 | val rxs2 = Bool() 26 | val rxs1 = Bool() 27 | val sel_alu2 = Bits(width = A2_X.getWidth) 28 | val sel_alu1 = Bits(width = A1_X.getWidth) 29 | val sel_imm = Bits(width = IMM_X.getWidth) 30 | val alu_dw = Bool() 31 | val alu_fn = Bits(width = FN_X.getWidth) 32 | val mem = Bool() 33 | val mem_cmd = Bits(width = M_SZ) 34 | val mem_type = Bits(width = MT_SZ) 35 | val rfs1 = Bool() 36 | val rfs2 = Bool() 37 | val rfs3 = Bool() 38 | val wfd = Bool() 39 | val div = Bool() 40 | val wxd = Bool() 41 | val csr = Bits(width = CSR.SZ) 42 | val fence_i = Bool() 43 | val fence = Bool() 44 | val amo = Bool() 45 | val tagr = Bool() 46 | val tagw = Bool() 47 | 48 | def default: List[BitPat] = 49 | // jal renf1 fence.i 50 | // | jalr | renf2 | 51 | // fp_val| | renx2 | | renf3 | tagr 52 | // | rocc| | | renx1 s_alu1 mem_val | | | wfd | | tagw 53 | // val | | br| | | | s_alu2 | imm dw alu | mem_cmd mem_type| | | | div | | | 54 | // | | | | | | | | | | | | | | | | | | | | | wxd | fence | | 55 | // | | | | | | | | | | | | | | | | | | | | | | csr | | amo | | 56 | // | | | | | | | | | | | | | | | | | | | | | | | | | | | | 57 | List(N, X,X,X,X,X,X,X,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, X,X,X,X,X,X,CSR.X,X,X,X, X,X) 58 | 59 | def decode(inst: UInt, table: Iterable[(BitPat, List[BitPat])]) = { 60 | val decoder = DecodeLogic(inst, default, table) 61 | val sigs = Seq(legal, fp, rocc, branch, jal, jalr, rxs2, rxs1, sel_alu2, 62 | sel_alu1, sel_imm, alu_dw, alu_fn, mem, mem_cmd, mem_type, 63 | rfs1, rfs2, rfs3, wfd, div, wxd, csr, fence_i, fence, amo, 64 | tagr, tagw) 65 | sigs zip decoder map {case(s,d) => s := d} 66 | this 67 | } 68 | } 69 | 70 | class XDecode(implicit val p: Parameters) extends DecodeConstants 71 | { 72 | val table: Array[(BitPat, List[BitPat])] = Array( 73 | // jal renf1 fence.i 74 | // | jalr | renf2 | 75 | // fp_val| | renx2 | | renf3 | tagr 76 | // | rocc| | | renx1 s_alu1 mem_val | | | wfd | | tagw 77 | // val | | br| | | | s_alu2 | imm dw alu | mem_cmd mem_type| | | | div | | | 78 | // | | | | | | | | | | | | | | | | | | | | | wxd | fence | | 79 | // | | | | | | | | | | | | | | | | | | | | | | csr | | amo | | 80 | // | | | | | | | | | | | | | | | | | | | | | | | | | | | | 81 | BNE-> List(Y, N,N,Y,N,N,Y,Y,A2_RS2, A1_RS1, IMM_SB,DW_X, FN_SNE, N,M_X, MT_X, N,N,N,N,N,N,CSR.N,N,N,N, N,N), 82 | BEQ-> List(Y, N,N,Y,N,N,Y,Y,A2_RS2, A1_RS1, IMM_SB,DW_X, FN_SEQ, N,M_X, MT_X, N,N,N,N,N,N,CSR.N,N,N,N, N,N), 83 | BLT-> List(Y, N,N,Y,N,N,Y,Y,A2_RS2, A1_RS1, IMM_SB,DW_X, FN_SLT, N,M_X, MT_X, N,N,N,N,N,N,CSR.N,N,N,N, N,N), 84 | BLTU-> List(Y, N,N,Y,N,N,Y,Y,A2_RS2, A1_RS1, IMM_SB,DW_X, FN_SLTU, N,M_X, MT_X, N,N,N,N,N,N,CSR.N,N,N,N, N,N), 85 | BGE-> List(Y, N,N,Y,N,N,Y,Y,A2_RS2, A1_RS1, IMM_SB,DW_X, FN_SGE, N,M_X, MT_X, N,N,N,N,N,N,CSR.N,N,N,N, N,N), 86 | BGEU-> List(Y, N,N,Y,N,N,Y,Y,A2_RS2, A1_RS1, IMM_SB,DW_X, FN_SGEU, N,M_X, MT_X, N,N,N,N,N,N,CSR.N,N,N,N, N,N), 87 | 88 | JAL-> List(Y, N,N,N,Y,N,N,N,A2_FOUR,A1_PC, IMM_UJ,DW_X, FN_ADD, N,M_X, MT_X, N,N,N,N,N,Y,CSR.N,N,N,N, N,N), 89 | JALR-> List(Y, N,N,N,N,Y,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,FN_ADD, N,M_X, MT_X, N,N,N,N,N,Y,CSR.N,N,N,N, N,N), 90 | AUIPC-> List(Y, N,N,N,N,N,N,N,A2_IMM, A1_PC, IMM_U, DW_XPR,FN_ADD, N,M_X, MT_X, N,N,N,N,N,Y,CSR.N,N,N,N, N,N), 91 | 92 | LB-> List(Y, N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,FN_ADD, Y,M_XRD, MT_B, N,N,N,N,N,Y,CSR.N,N,N,N, N,N), 93 | LH-> List(Y, N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,FN_ADD, Y,M_XRD, MT_H, N,N,N,N,N,Y,CSR.N,N,N,N, N,N), 94 | LW-> List(Y, N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,FN_ADD, Y,M_XRD, MT_W, N,N,N,N,N,Y,CSR.N,N,N,N, N,N), 95 | LD-> List(xpr64,N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,FN_ADD, Y,M_XRD, MT_D, N,N,N,N,N,Y,CSR.N,N,N,N, N,N), 96 | LBU-> List(Y, N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,FN_ADD, Y,M_XRD, MT_BU,N,N,N,N,N,Y,CSR.N,N,N,N, N,N), 97 | LHU-> List(Y, N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,FN_ADD, Y,M_XRD, MT_HU,N,N,N,N,N,Y,CSR.N,N,N,N, N,N), 98 | LWU-> List(xpr64,N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,FN_ADD, Y,M_XRD, MT_WU,N,N,N,N,N,Y,CSR.N,N,N,N, N,N), 99 | SB-> List(Y, N,N,N,N,N,Y,Y,A2_IMM, A1_RS1, IMM_S, DW_XPR,FN_ADD, Y,M_XWR, MT_B, N,N,N,N,N,N,CSR.N,N,N,N, N,N), 100 | SH-> List(Y, N,N,N,N,N,Y,Y,A2_IMM, A1_RS1, IMM_S, DW_XPR,FN_ADD, Y,M_XWR, MT_H, N,N,N,N,N,N,CSR.N,N,N,N, N,N), 101 | SW-> List(Y, N,N,N,N,N,Y,Y,A2_IMM, A1_RS1, IMM_S, DW_XPR,FN_ADD, Y,M_XWR, MT_W, N,N,N,N,N,N,CSR.N,N,N,N, N,N), 102 | SD-> List(xpr64,N,N,N,N,N,Y,Y,A2_IMM, A1_RS1, IMM_S, DW_XPR,FN_ADD, Y,M_XWR, MT_D, N,N,N,N,N,N,CSR.N,N,N,N, N,N), 103 | 104 | AMOADD_W-> List(Y, N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, Y,M_XA_ADD, MT_W, N,N,N,N,N,Y,CSR.N,N,N,Y, N,N), 105 | AMOXOR_W-> List(Y, N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, Y,M_XA_XOR, MT_W, N,N,N,N,N,Y,CSR.N,N,N,Y, N,N), 106 | AMOSWAP_W-> List(Y, N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, Y,M_XA_SWAP,MT_W, N,N,N,N,N,Y,CSR.N,N,N,Y, N,N), 107 | AMOAND_W-> List(Y, N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, Y,M_XA_AND, MT_W, N,N,N,N,N,Y,CSR.N,N,N,Y, N,N), 108 | AMOOR_W-> List(Y, N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, Y,M_XA_OR, MT_W, N,N,N,N,N,Y,CSR.N,N,N,Y, N,N), 109 | AMOMIN_W-> List(Y, N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, Y,M_XA_MIN, MT_W, N,N,N,N,N,Y,CSR.N,N,N,Y, N,N), 110 | AMOMINU_W-> List(Y, N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, Y,M_XA_MINU,MT_W, N,N,N,N,N,Y,CSR.N,N,N,Y, N,N), 111 | AMOMAX_W-> List(Y, N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, Y,M_XA_MAX, MT_W, N,N,N,N,N,Y,CSR.N,N,N,Y, N,N), 112 | AMOMAXU_W-> List(Y, N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, Y,M_XA_MAXU,MT_W, N,N,N,N,N,Y,CSR.N,N,N,Y, N,N), 113 | AMOADD_D-> List(xpr64,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, Y,M_XA_ADD, MT_D, N,N,N,N,N,Y,CSR.N,N,N,Y, N,N), 114 | AMOSWAP_D-> List(xpr64,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, Y,M_XA_SWAP,MT_D, N,N,N,N,N,Y,CSR.N,N,N,Y, N,N), 115 | AMOXOR_D-> List(xpr64,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, Y,M_XA_XOR, MT_D, N,N,N,N,N,Y,CSR.N,N,N,Y, N,N), 116 | AMOAND_D-> List(xpr64,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, Y,M_XA_AND, MT_D, N,N,N,N,N,Y,CSR.N,N,N,Y, N,N), 117 | AMOOR_D-> List(xpr64,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, Y,M_XA_OR, MT_D, N,N,N,N,N,Y,CSR.N,N,N,Y, N,N), 118 | AMOMIN_D-> List(xpr64,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, Y,M_XA_MIN, MT_D, N,N,N,N,N,Y,CSR.N,N,N,Y, N,N), 119 | AMOMINU_D-> List(xpr64,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, Y,M_XA_MINU,MT_D, N,N,N,N,N,Y,CSR.N,N,N,Y, N,N), 120 | AMOMAX_D-> List(xpr64,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, Y,M_XA_MAX, MT_D, N,N,N,N,N,Y,CSR.N,N,N,Y, N,N), 121 | AMOMAXU_D-> List(xpr64,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, Y,M_XA_MAXU,MT_D, N,N,N,N,N,Y,CSR.N,N,N,Y, N,N), 122 | 123 | LR_W-> List(Y, N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, Y,M_XLR, MT_W, N,N,N,N,N,Y,CSR.N,N,N,Y, N,N), 124 | LR_D-> List(xpr64,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, Y,M_XLR, MT_D, N,N,N,N,N,Y,CSR.N,N,N,Y, N,N), 125 | SC_W-> List(Y, N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, Y,M_XSC, MT_W, N,N,N,N,N,Y,CSR.N,N,N,Y, N,N), 126 | SC_D-> List(xpr64,N,N,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, Y,M_XSC, MT_D, N,N,N,N,N,Y,CSR.N,N,N,Y, N,N), 127 | 128 | LUI-> List(Y, N,N,N,N,N,N,N,A2_IMM, A1_ZERO,IMM_U, DW_XPR,FN_ADD, N,M_X, MT_X, N,N,N,N,N,Y,CSR.N,N,N,N, N,N), 129 | ADDI-> List(Y, N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,FN_ADD, N,M_X, MT_X, N,N,N,N,N,Y,CSR.N,N,N,N, N,N), 130 | SLTI -> List(Y, N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,FN_SLT, N,M_X, MT_X, N,N,N,N,N,Y,CSR.N,N,N,N, N,N), 131 | SLTIU-> List(Y, N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,FN_SLTU, N,M_X, MT_X, N,N,N,N,N,Y,CSR.N,N,N,N, N,N), 132 | ANDI-> List(Y, N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,FN_AND, N,M_X, MT_X, N,N,N,N,N,Y,CSR.N,N,N,N, N,N), 133 | ORI-> List(Y, N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,FN_OR, N,M_X, MT_X, N,N,N,N,N,Y,CSR.N,N,N,N, N,N), 134 | XORI-> List(Y, N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,FN_XOR, N,M_X, MT_X, N,N,N,N,N,Y,CSR.N,N,N,N, N,N), 135 | SLLI-> List(Y, N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,FN_SL, N,M_X, MT_X, N,N,N,N,N,Y,CSR.N,N,N,N, N,N), 136 | SRLI-> List(Y, N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,FN_SR, N,M_X, MT_X, N,N,N,N,N,Y,CSR.N,N,N,N, N,N), 137 | SRAI-> List(Y, N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,FN_SRA, N,M_X, MT_X, N,N,N,N,N,Y,CSR.N,N,N,N, N,N), 138 | ADD-> List(Y, N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X, MT_X, N,N,N,N,N,Y,CSR.N,N,N,N, N,N), 139 | SUB-> List(Y, N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,FN_SUB, N,M_X, MT_X, N,N,N,N,N,Y,CSR.N,N,N,N, N,N), 140 | SLT-> List(Y, N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,FN_SLT, N,M_X, MT_X, N,N,N,N,N,Y,CSR.N,N,N,N, N,N), 141 | SLTU-> List(Y, N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,FN_SLTU, N,M_X, MT_X, N,N,N,N,N,Y,CSR.N,N,N,N, N,N), 142 | AND-> List(Y, N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,FN_AND, N,M_X, MT_X, N,N,N,N,N,Y,CSR.N,N,N,N, N,N), 143 | OR-> List(Y, N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,FN_OR, N,M_X, MT_X, N,N,N,N,N,Y,CSR.N,N,N,N, N,N), 144 | XOR-> List(Y, N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,FN_XOR, N,M_X, MT_X, N,N,N,N,N,Y,CSR.N,N,N,N, N,N), 145 | SLL-> List(Y, N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,FN_SL, N,M_X, MT_X, N,N,N,N,N,Y,CSR.N,N,N,N, N,N), 146 | SRL-> List(Y, N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,FN_SR, N,M_X, MT_X, N,N,N,N,N,Y,CSR.N,N,N,N, N,N), 147 | SRA-> List(Y, N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,FN_SRA, N,M_X, MT_X, N,N,N,N,N,Y,CSR.N,N,N,N, N,N), 148 | 149 | ADDIW-> List(xpr64,N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_32,FN_ADD, N,M_X, MT_X, N,N,N,N,N,Y,CSR.N,N,N,N, N,N), 150 | SLLIW-> List(xpr64,N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_32,FN_SL, N,M_X, MT_X, N,N,N,N,N,Y,CSR.N,N,N,N, N,N), 151 | SRLIW-> List(xpr64,N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_32,FN_SR, N,M_X, MT_X, N,N,N,N,N,Y,CSR.N,N,N,N, N,N), 152 | SRAIW-> List(xpr64,N,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_32,FN_SRA, N,M_X, MT_X, N,N,N,N,N,Y,CSR.N,N,N,N, N,N), 153 | ADDW-> List(xpr64,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_32,FN_ADD, N,M_X, MT_X, N,N,N,N,N,Y,CSR.N,N,N,N, N,N), 154 | SUBW-> List(xpr64,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_32,FN_SUB, N,M_X, MT_X, N,N,N,N,N,Y,CSR.N,N,N,N, N,N), 155 | SLLW-> List(xpr64,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_32,FN_SL, N,M_X, MT_X, N,N,N,N,N,Y,CSR.N,N,N,N, N,N), 156 | SRLW-> List(xpr64,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_32,FN_SR, N,M_X, MT_X, N,N,N,N,N,Y,CSR.N,N,N,N, N,N), 157 | SRAW-> List(xpr64,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_32,FN_SRA, N,M_X, MT_X, N,N,N,N,N,Y,CSR.N,N,N,N, N,N), 158 | 159 | MUL-> List(Y, N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,FN_MUL, N,M_X, MT_X, N,N,N,N,Y,Y,CSR.N,N,N,N, N,N), 160 | MULH-> List(Y, N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,FN_MULH, N,M_X, MT_X, N,N,N,N,Y,Y,CSR.N,N,N,N, N,N), 161 | MULHU-> List(Y, N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,FN_MULHU, N,M_X, MT_X, N,N,N,N,Y,Y,CSR.N,N,N,N, N,N), 162 | MULHSU-> List(Y, N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,FN_MULHSU,N,M_X, MT_X, N,N,N,N,Y,Y,CSR.N,N,N,N, N,N), 163 | MULW-> List(xpr64,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_32, FN_MUL, N,M_X, MT_X, N,N,N,N,Y,Y,CSR.N,N,N,N, N,N), 164 | 165 | DIV-> List(Y, N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,FN_DIV, N,M_X, MT_X, N,N,N,N,Y,Y,CSR.N,N,N,N, N,N), 166 | DIVU-> List(Y, N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,FN_DIVU, N,M_X, MT_X, N,N,N,N,Y,Y,CSR.N,N,N,N, N,N), 167 | REM-> List(Y, N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,FN_REM, N,M_X, MT_X, N,N,N,N,Y,Y,CSR.N,N,N,N, N,N), 168 | REMU-> List(Y, N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_XPR,FN_REMU, N,M_X, MT_X, N,N,N,N,Y,Y,CSR.N,N,N,N, N,N), 169 | DIVW-> List(xpr64,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_32, FN_DIV, N,M_X, MT_X, N,N,N,N,Y,Y,CSR.N,N,N,N, N,N), 170 | DIVUW-> List(xpr64,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_32, FN_DIVU, N,M_X, MT_X, N,N,N,N,Y,Y,CSR.N,N,N,N, N,N), 171 | REMW-> List(xpr64,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_32, FN_REM, N,M_X, MT_X, N,N,N,N,Y,Y,CSR.N,N,N,N, N,N), 172 | REMUW-> List(xpr64,N,N,N,N,N,Y,Y,A2_RS2, A1_RS1, IMM_X, DW_32, FN_REMU, N,M_X, MT_X, N,N,N,N,Y,Y,CSR.N,N,N,N, N,N), 173 | 174 | FENCE-> List(Y, N,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, N,N,N,N,N,N,CSR.N,N,Y,N, N,N), 175 | FENCE_I-> List(Y, N,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, N,N,N,N,N,N,CSR.N,Y,N,N, N,N), 176 | 177 | SFENCE_VM-> List(Y, N,N,N,N,N,N,X,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, N,N,N,N,N,N,CSR.I,N,N,N, N,N), 178 | SCALL-> List(Y, N,N,N,N,N,N,X,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, N,N,N,N,N,N,CSR.I,N,N,N, N,N), 179 | SBREAK-> List(Y, N,N,N,N,N,N,X,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, N,N,N,N,N,N,CSR.I,N,N,N, N,N), 180 | SRET-> List(Y, N,N,N,N,N,N,X,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, N,N,N,N,N,N,CSR.I,N,N,N, N,N), 181 | MRET-> List(Y, N,N,N,N,N,N,X,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, N,N,N,N,N,N,CSR.I,N,N,N, N,N), 182 | WFI-> List(Y, N,N,N,N,N,N,X,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, N,N,N,N,N,N,CSR.I,N,N,N, N,N), 183 | CSRRW-> List(Y, N,N,N,N,N,N,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X, MT_X, N,N,N,N,N,Y,CSR.W,N,N,N, N,N), 184 | CSRRS-> List(Y, N,N,N,N,N,N,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X, MT_X, N,N,N,N,N,Y,CSR.S,N,N,N, N,N), 185 | CSRRC-> List(Y, N,N,N,N,N,N,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X, MT_X, N,N,N,N,N,Y,CSR.C,N,N,N, N,N), 186 | CSRRWI-> List(Y, N,N,N,N,N,N,N,A2_IMM, A1_ZERO,IMM_Z, DW_XPR,FN_ADD, N,M_X, MT_X, N,N,N,N,N,Y,CSR.W,N,N,N, N,N), 187 | CSRRSI-> List(Y, N,N,N,N,N,N,N,A2_IMM, A1_ZERO,IMM_Z, DW_XPR,FN_ADD, N,M_X, MT_X, N,N,N,N,N,Y,CSR.S,N,N,N, N,N), 188 | CSRRCI-> List(Y, N,N,N,N,N,N,N,A2_IMM, A1_ZERO,IMM_Z, DW_XPR,FN_ADD, N,M_X, MT_X, N,N,N,N,N,Y,CSR.C,N,N,N, N,N)) 189 | } 190 | 191 | class FDecode(implicit val p: Parameters) extends DecodeConstants 192 | { 193 | val table: Array[(BitPat, List[BitPat])] = Array( 194 | // jal renf1 fence.i 195 | // | jalr | renf2 | 196 | // fp_val| | renx2 | | renf3 | tagr 197 | // | rocc| | | renx1 s_alu1 mem_val | | | wfd | | tagw 198 | // val | | br| | | | s_alu2 | imm dw alu | mem_cmd mem_type| | | | div | | | 199 | // | | | | | | | | | | | | | | | | | | | | | wxd | fence | | 200 | // | | | | | | | | | | | | | | | | | | | | | | csr | | amo | | 201 | // | | | | | | | | | | | | | | | | | | | | | | | | | | | | 202 | FCVT_S_D-> List(Y, Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, Y,N,N,Y,N,N,CSR.N,N,N,N, N,N), 203 | FCVT_D_S-> List(Y, Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, Y,N,N,Y,N,N,CSR.N,N,N,N, N,N), 204 | FSGNJ_S-> List(Y, Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, Y,Y,N,Y,N,N,CSR.N,N,N,N, N,N), 205 | FSGNJ_D-> List(Y, Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, Y,Y,N,Y,N,N,CSR.N,N,N,N, N,N), 206 | FSGNJX_S-> List(Y, Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, Y,Y,N,Y,N,N,CSR.N,N,N,N, N,N), 207 | FSGNJX_D-> List(Y, Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, Y,Y,N,Y,N,N,CSR.N,N,N,N, N,N), 208 | FSGNJN_S-> List(Y, Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, Y,Y,N,Y,N,N,CSR.N,N,N,N, N,N), 209 | FSGNJN_D-> List(Y, Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, Y,Y,N,Y,N,N,CSR.N,N,N,N, N,N), 210 | FMIN_S-> List(Y, Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, Y,Y,N,Y,N,N,CSR.N,N,N,N, N,N), 211 | FMIN_D-> List(Y, Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, Y,Y,N,Y,N,N,CSR.N,N,N,N, N,N), 212 | FMAX_S-> List(Y, Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, Y,Y,N,Y,N,N,CSR.N,N,N,N, N,N), 213 | FMAX_D-> List(Y, Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, Y,Y,N,Y,N,N,CSR.N,N,N,N, N,N), 214 | FADD_S-> List(Y, Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, Y,Y,N,Y,N,N,CSR.N,N,N,N, N,N), 215 | FADD_D-> List(Y, Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, Y,Y,N,Y,N,N,CSR.N,N,N,N, N,N), 216 | FSUB_S-> List(Y, Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, Y,Y,N,Y,N,N,CSR.N,N,N,N, N,N), 217 | FSUB_D-> List(Y, Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, Y,Y,N,Y,N,N,CSR.N,N,N,N, N,N), 218 | FMUL_S-> List(Y, Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, Y,Y,N,Y,N,N,CSR.N,N,N,N, N,N), 219 | FMUL_D-> List(Y, Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, Y,Y,N,Y,N,N,CSR.N,N,N,N, N,N), 220 | FMADD_S-> List(Y, Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, Y,Y,Y,Y,N,N,CSR.N,N,N,N, N,N), 221 | FMADD_D-> List(Y, Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, Y,Y,Y,Y,N,N,CSR.N,N,N,N, N,N), 222 | FMSUB_S-> List(Y, Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, Y,Y,Y,Y,N,N,CSR.N,N,N,N, N,N), 223 | FMSUB_D-> List(Y, Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, Y,Y,Y,Y,N,N,CSR.N,N,N,N, N,N), 224 | FNMADD_S-> List(Y, Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, Y,Y,Y,Y,N,N,CSR.N,N,N,N, N,N), 225 | FNMADD_D-> List(Y, Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, Y,Y,Y,Y,N,N,CSR.N,N,N,N, N,N), 226 | FNMSUB_S-> List(Y, Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, Y,Y,Y,Y,N,N,CSR.N,N,N,N, N,N), 227 | FNMSUB_D-> List(Y, Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, Y,Y,Y,Y,N,N,CSR.N,N,N,N, N,N), 228 | FCLASS_S-> List(Y, Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, Y,N,N,N,N,Y,CSR.N,N,N,N, N,N), 229 | FCLASS_D-> List(Y, Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, Y,N,N,N,N,Y,CSR.N,N,N,N, N,N), 230 | FMV_X_S-> List(Y, Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, Y,N,N,N,N,Y,CSR.N,N,N,N, N,N), 231 | FMV_X_D-> List(xpr64,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, Y,N,N,N,N,Y,CSR.N,N,N,N, N,N), 232 | FCVT_W_S-> List(Y, Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, Y,N,N,N,N,Y,CSR.N,N,N,N, N,N), 233 | FCVT_W_D-> List(Y, Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, Y,N,N,N,N,Y,CSR.N,N,N,N, N,N), 234 | FCVT_WU_S-> List(Y, Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, Y,N,N,N,N,Y,CSR.N,N,N,N, N,N), 235 | FCVT_WU_D-> List(Y, Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, Y,N,N,N,N,Y,CSR.N,N,N,N, N,N), 236 | FCVT_L_S-> List(xpr64,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, Y,N,N,N,N,Y,CSR.N,N,N,N, N,N), 237 | FCVT_L_D-> List(xpr64,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, Y,N,N,N,N,Y,CSR.N,N,N,N, N,N), 238 | FCVT_LU_S-> List(xpr64,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, Y,N,N,N,N,Y,CSR.N,N,N,N, N,N), 239 | FCVT_LU_D-> List(xpr64,Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, Y,N,N,N,N,Y,CSR.N,N,N,N, N,N), 240 | FEQ_S-> List(Y, Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, Y,Y,N,N,N,Y,CSR.N,N,N,N, N,N), 241 | FEQ_D-> List(Y, Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, Y,Y,N,N,N,Y,CSR.N,N,N,N, N,N), 242 | FLT_S-> List(Y, Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, Y,Y,N,N,N,Y,CSR.N,N,N,N, N,N), 243 | FLT_D-> List(Y, Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, Y,Y,N,N,N,Y,CSR.N,N,N,N, N,N), 244 | FLE_S-> List(Y, Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, Y,Y,N,N,N,Y,CSR.N,N,N,N, N,N), 245 | FLE_D-> List(Y, Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, Y,Y,N,N,N,Y,CSR.N,N,N,N, N,N), 246 | FMV_S_X-> List(Y, Y,N,N,N,N,N,Y,A2_X, A1_RS1, IMM_X, DW_X, FN_X, N,M_X, MT_X, N,N,N,Y,N,N,CSR.N,N,N,N, N,N), 247 | FMV_D_X-> List(xpr64,Y,N,N,N,N,N,Y,A2_X, A1_RS1, IMM_X, DW_X, FN_X, N,M_X, MT_X, N,N,N,Y,N,N,CSR.N,N,N,N, N,N), 248 | FCVT_S_W-> List(Y, Y,N,N,N,N,N,Y,A2_X, A1_RS1, IMM_X, DW_X, FN_X, N,M_X, MT_X, N,N,N,Y,N,N,CSR.N,N,N,N, N,N), 249 | FCVT_D_W-> List(Y, Y,N,N,N,N,N,Y,A2_X, A1_RS1, IMM_X, DW_X, FN_X, N,M_X, MT_X, N,N,N,Y,N,N,CSR.N,N,N,N, N,N), 250 | FCVT_S_WU-> List(Y, Y,N,N,N,N,N,Y,A2_X, A1_RS1, IMM_X, DW_X, FN_X, N,M_X, MT_X, N,N,N,Y,N,N,CSR.N,N,N,N, N,N), 251 | FCVT_D_WU-> List(Y, Y,N,N,N,N,N,Y,A2_X, A1_RS1, IMM_X, DW_X, FN_X, N,M_X, MT_X, N,N,N,Y,N,N,CSR.N,N,N,N, N,N), 252 | FCVT_S_L-> List(xpr64,Y,N,N,N,N,N,Y,A2_X, A1_RS1, IMM_X, DW_X, FN_X, N,M_X, MT_X, N,N,N,Y,N,N,CSR.N,N,N,N, N,N), 253 | FCVT_D_L-> List(xpr64,Y,N,N,N,N,N,Y,A2_X, A1_RS1, IMM_X, DW_X, FN_X, N,M_X, MT_X, N,N,N,Y,N,N,CSR.N,N,N,N, N,N), 254 | FCVT_S_LU-> List(xpr64,Y,N,N,N,N,N,Y,A2_X, A1_RS1, IMM_X, DW_X, FN_X, N,M_X, MT_X, N,N,N,Y,N,N,CSR.N,N,N,N, N,N), 255 | FCVT_D_LU-> List(xpr64,Y,N,N,N,N,N,Y,A2_X, A1_RS1, IMM_X, DW_X, FN_X, N,M_X, MT_X, N,N,N,Y,N,N,CSR.N,N,N,N, N,N), 256 | FLW-> List(Y, Y,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,FN_ADD, Y,M_XRD, MT_W, N,N,N,Y,N,N,CSR.N,N,N,N, N,N), 257 | FLD-> List(Y, Y,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_I, DW_XPR,FN_ADD, Y,M_XRD, MT_D, N,N,N,Y,N,N,CSR.N,N,N,N, N,N), 258 | FSW-> List(Y, Y,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_S, DW_XPR,FN_ADD, Y,M_XWR, MT_W, N,Y,N,N,N,N,CSR.N,N,N,N, N,N), 259 | FSD-> List(Y, Y,N,N,N,N,N,Y,A2_IMM, A1_RS1, IMM_S, DW_XPR,FN_ADD, Y,M_XWR, MT_D, N,Y,N,N,N,N,CSR.N,N,N,N, N,N)) 260 | } 261 | 262 | class FDivSqrtDecode(implicit val p: Parameters) extends DecodeConstants 263 | { 264 | val table: Array[(BitPat, List[BitPat])] = Array( 265 | FDIV_S-> List(Y, Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, Y,Y,N,Y,N,N,CSR.N,N,N,N,N,N), 266 | FDIV_D-> List(Y, Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, Y,Y,N,Y,N,N,CSR.N,N,N,N,N,N), 267 | FSQRT_S-> List(Y, Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, Y,Y,N,Y,N,N,CSR.N,N,N,N,N,N), 268 | FSQRT_D-> List(Y, Y,N,N,N,N,N,N,A2_X, A1_X, IMM_X, DW_X, FN_X, N,M_X, MT_X, Y,Y,N,Y,N,N,CSR.N,N,N,N,N,N)) 269 | } 270 | 271 | class RoCCDecode(implicit val p: Parameters) extends DecodeConstants 272 | { 273 | val table: Array[(BitPat, List[BitPat])] = Array( 274 | // jal renf1 fence.i 275 | // | jalr | renf2 | 276 | // fp_val| | renx2 | | renf3 | tagr 277 | // | rocc| | | renx1 s_alu1 mem_val | | | wfd | | tagw 278 | // val | | br| | | | s_alu2 | imm dw alu | mem_cmd mem_type| | | | div | | | 279 | // | | | | | | | | | | | | | | | | | | | | | wxd | fence | | 280 | // | | | | | | | | | | | | | | | | | | | | | | csr | | amo | | 281 | // | | | | | | | | | | | | | | | | | | | | | | | | | | | | 282 | CUSTOM0-> List(Y, N,Y,N,N,N,N,N,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X, MT_X, N,N,N,N,N,N,CSR.N,N,N,N, N,N), 283 | CUSTOM0_RS1-> List(Y, N,Y,N,N,N,N,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X, MT_X, N,N,N,N,N,N,CSR.N,N,N,N, N,N), 284 | CUSTOM0_RS1_RS2-> List(Y, N,Y,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X, MT_X, N,N,N,N,N,N,CSR.N,N,N,N, N,N), 285 | CUSTOM0_RD-> List(Y, N,Y,N,N,N,N,N,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X, MT_X, N,N,N,N,N,Y,CSR.N,N,N,N, N,N), 286 | CUSTOM0_RD_RS1-> List(Y, N,Y,N,N,N,N,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X, MT_X, N,N,N,N,N,Y,CSR.N,N,N,N, N,N), 287 | CUSTOM0_RD_RS1_RS2->List(Y, N,Y,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X, MT_X, N,N,N,N,N,Y,CSR.N,N,N,N, N,N), 288 | CUSTOM1-> List(Y, N,Y,N,N,N,N,N,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X, MT_X, N,N,N,N,N,N,CSR.N,N,N,N, N,N), 289 | CUSTOM1_RS1-> List(Y, N,Y,N,N,N,N,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X, MT_X, N,N,N,N,N,N,CSR.N,N,N,N, N,N), 290 | CUSTOM1_RS1_RS2-> List(Y, N,Y,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X, MT_X, N,N,N,N,N,N,CSR.N,N,N,N, N,N), 291 | CUSTOM1_RD-> List(Y, N,Y,N,N,N,N,N,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X, MT_X, N,N,N,N,N,Y,CSR.N,N,N,N, N,N), 292 | CUSTOM1_RD_RS1-> List(Y, N,Y,N,N,N,N,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X, MT_X, N,N,N,N,N,Y,CSR.N,N,N,N, N,N), 293 | CUSTOM1_RD_RS1_RS2->List(Y, N,Y,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X, MT_X, N,N,N,N,N,Y,CSR.N,N,N,N, N,N), 294 | CUSTOM2-> List(Y, N,Y,N,N,N,N,N,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X, MT_X, N,N,N,N,N,N,CSR.N,N,N,N, N,N), 295 | CUSTOM2_RS1-> List(Y, N,Y,N,N,N,N,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X, MT_X, N,N,N,N,N,N,CSR.N,N,N,N, N,N), 296 | CUSTOM2_RS1_RS2-> List(Y, N,Y,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X, MT_X, N,N,N,N,N,N,CSR.N,N,N,N, N,N), 297 | CUSTOM2_RD-> List(Y, N,Y,N,N,N,N,N,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X, MT_X, N,N,N,N,N,Y,CSR.N,N,N,N, N,N), 298 | CUSTOM2_RD_RS1-> List(Y, N,Y,N,N,N,N,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X, MT_X, N,N,N,N,N,Y,CSR.N,N,N,N, N,N), 299 | CUSTOM2_RD_RS1_RS2->List(Y, N,Y,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X, MT_X, N,N,N,N,N,Y,CSR.N,N,N,N, N,N), 300 | CUSTOM3-> List(Y, N,Y,N,N,N,N,N,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X, MT_X, N,N,N,N,N,N,CSR.N,N,N,N, N,N), 301 | CUSTOM3_RS1-> List(Y, N,Y,N,N,N,N,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X, MT_X, N,N,N,N,N,N,CSR.N,N,N,N, N,N), 302 | CUSTOM3_RS1_RS2-> List(Y, N,Y,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X, MT_X, N,N,N,N,N,N,CSR.N,N,N,N, N,N), 303 | CUSTOM3_RD-> List(Y, N,Y,N,N,N,N,N,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X, MT_X, N,N,N,N,N,Y,CSR.N,N,N,N, N,N), 304 | CUSTOM3_RD_RS1-> List(Y, N,Y,N,N,N,N,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X, MT_X, N,N,N,N,N,Y,CSR.N,N,N,N, N,N), 305 | CUSTOM3_RD_RS1_RS2->List(Y, N,Y,N,N,N,Y,Y,A2_ZERO,A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X, MT_X, N,N,N,N,N,Y,CSR.N,N,N,N, N,N)) 306 | } 307 | 308 | class TagDecode(implicit val p: Parameters) extends DecodeConstants 309 | { 310 | val table: Array[(BitPat, List[BitPat])] = Array( 311 | // jal renf1 fence.i 312 | // | jalr | renf2 | 313 | // fp_val| | renx2 | | renf3 | tagr 314 | // | rocc| | | renx1 s_alu1 mem_val | | | wfd | | tagw 315 | // val | | br| | | | s_alu2 | imm dw alu | mem_cmd mem_type| | | | div | | | 316 | // | | | | | | | | | | | | | | | | | | | | | wxd | fence | | 317 | // | | | | | | | | | | | | | | | | | | | | | | csr | | amo | | 318 | // | | | | | | | | | | | | | | | | | | | | | | | | | | | | 319 | TAGR-> List(xpr64,N,N,N,N,N,N,Y,A2_ZERO, A1_RS1 , IMM_X, DW_XPR,FN_ADD, N,M_X, MT_X, N,N,N,N,N,Y,CSR.N,N,N,N, Y,N), 320 | TAGW-> List(xpr64,N,N,N,N,N,Y,Y,A2_ZERO, A1_RS1, IMM_X, DW_XPR,FN_ADD, N,M_X, MT_X, N,N,N,N,N,Y,CSR.N,N,N,N, N,Y)) 321 | } 322 | -------------------------------------------------------------------------------- /src/main/scala/instructions.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package rocket 4 | 5 | import Chisel._ 6 | 7 | /* Automatically generated by parse-opcodes */ 8 | object Instructions { 9 | def BEQ = BitPat("b?????????????????000?????1100011") 10 | def BNE = BitPat("b?????????????????001?????1100011") 11 | def BLT = BitPat("b?????????????????100?????1100011") 12 | def BGE = BitPat("b?????????????????101?????1100011") 13 | def BLTU = BitPat("b?????????????????110?????1100011") 14 | def BGEU = BitPat("b?????????????????111?????1100011") 15 | def JALR = BitPat("b?????????????????000?????1100111") 16 | def JAL = BitPat("b?????????????????????????1101111") 17 | def LUI = BitPat("b?????????????????????????0110111") 18 | def AUIPC = BitPat("b?????????????????????????0010111") 19 | def ADDI = BitPat("b?????????????????000?????0010011") 20 | def SLLI = BitPat("b000000???????????001?????0010011") 21 | def SLTI = BitPat("b?????????????????010?????0010011") 22 | def SLTIU = BitPat("b?????????????????011?????0010011") 23 | def XORI = BitPat("b?????????????????100?????0010011") 24 | def SRLI = BitPat("b000000???????????101?????0010011") 25 | def SRAI = BitPat("b010000???????????101?????0010011") 26 | def ORI = BitPat("b?????????????????110?????0010011") 27 | def ANDI = BitPat("b?????????????????111?????0010011") 28 | def ADD = BitPat("b0000000??????????000?????0110011") 29 | def SUB = BitPat("b0100000??????????000?????0110011") 30 | def SLL = BitPat("b0000000??????????001?????0110011") 31 | def SLT = BitPat("b0000000??????????010?????0110011") 32 | def SLTU = BitPat("b0000000??????????011?????0110011") 33 | def XOR = BitPat("b0000000??????????100?????0110011") 34 | def SRL = BitPat("b0000000??????????101?????0110011") 35 | def SRA = BitPat("b0100000??????????101?????0110011") 36 | def OR = BitPat("b0000000??????????110?????0110011") 37 | def AND = BitPat("b0000000??????????111?????0110011") 38 | def ADDIW = BitPat("b?????????????????000?????0011011") 39 | def SLLIW = BitPat("b0000000??????????001?????0011011") 40 | def SRLIW = BitPat("b0000000??????????101?????0011011") 41 | def SRAIW = BitPat("b0100000??????????101?????0011011") 42 | def ADDW = BitPat("b0000000??????????000?????0111011") 43 | def SUBW = BitPat("b0100000??????????000?????0111011") 44 | def SLLW = BitPat("b0000000??????????001?????0111011") 45 | def SRLW = BitPat("b0000000??????????101?????0111011") 46 | def SRAW = BitPat("b0100000??????????101?????0111011") 47 | def LB = BitPat("b?????????????????000?????0000011") 48 | def LH = BitPat("b?????????????????001?????0000011") 49 | def LW = BitPat("b?????????????????010?????0000011") 50 | def LD = BitPat("b?????????????????011?????0000011") 51 | def LBU = BitPat("b?????????????????100?????0000011") 52 | def LHU = BitPat("b?????????????????101?????0000011") 53 | def LWU = BitPat("b?????????????????110?????0000011") 54 | def SB = BitPat("b?????????????????000?????0100011") 55 | def SH = BitPat("b?????????????????001?????0100011") 56 | def SW = BitPat("b?????????????????010?????0100011") 57 | def SD = BitPat("b?????????????????011?????0100011") 58 | def FENCE = BitPat("b?????????????????000?????0001111") 59 | def FENCE_I = BitPat("b?????????????????001?????0001111") 60 | def MUL = BitPat("b0000001??????????000?????0110011") 61 | def MULH = BitPat("b0000001??????????001?????0110011") 62 | def MULHSU = BitPat("b0000001??????????010?????0110011") 63 | def MULHU = BitPat("b0000001??????????011?????0110011") 64 | def DIV = BitPat("b0000001??????????100?????0110011") 65 | def DIVU = BitPat("b0000001??????????101?????0110011") 66 | def REM = BitPat("b0000001??????????110?????0110011") 67 | def REMU = BitPat("b0000001??????????111?????0110011") 68 | def MULW = BitPat("b0000001??????????000?????0111011") 69 | def DIVW = BitPat("b0000001??????????100?????0111011") 70 | def DIVUW = BitPat("b0000001??????????101?????0111011") 71 | def REMW = BitPat("b0000001??????????110?????0111011") 72 | def REMUW = BitPat("b0000001??????????111?????0111011") 73 | def AMOADD_W = BitPat("b00000????????????010?????0101111") 74 | def AMOXOR_W = BitPat("b00100????????????010?????0101111") 75 | def AMOOR_W = BitPat("b01000????????????010?????0101111") 76 | def AMOAND_W = BitPat("b01100????????????010?????0101111") 77 | def AMOMIN_W = BitPat("b10000????????????010?????0101111") 78 | def AMOMAX_W = BitPat("b10100????????????010?????0101111") 79 | def AMOMINU_W = BitPat("b11000????????????010?????0101111") 80 | def AMOMAXU_W = BitPat("b11100????????????010?????0101111") 81 | def AMOSWAP_W = BitPat("b00001????????????010?????0101111") 82 | def LR_W = BitPat("b00010??00000?????010?????0101111") 83 | def SC_W = BitPat("b00011????????????010?????0101111") 84 | def AMOADD_D = BitPat("b00000????????????011?????0101111") 85 | def AMOXOR_D = BitPat("b00100????????????011?????0101111") 86 | def AMOOR_D = BitPat("b01000????????????011?????0101111") 87 | def AMOAND_D = BitPat("b01100????????????011?????0101111") 88 | def AMOMIN_D = BitPat("b10000????????????011?????0101111") 89 | def AMOMAX_D = BitPat("b10100????????????011?????0101111") 90 | def AMOMINU_D = BitPat("b11000????????????011?????0101111") 91 | def AMOMAXU_D = BitPat("b11100????????????011?????0101111") 92 | def AMOSWAP_D = BitPat("b00001????????????011?????0101111") 93 | def LR_D = BitPat("b00010??00000?????011?????0101111") 94 | def SC_D = BitPat("b00011????????????011?????0101111") 95 | def ECALL = BitPat("b00000000000000000000000001110011") 96 | def EBREAK = BitPat("b00000000000100000000000001110011") 97 | def URET = BitPat("b00000000001000000000000001110011") 98 | def SRET = BitPat("b00010000001000000000000001110011") 99 | def HRET = BitPat("b00100000001000000000000001110011") 100 | def MRET = BitPat("b00110000001000000000000001110011") 101 | def SFENCE_VM = BitPat("b000100000100?????000000001110011") 102 | def WFI = BitPat("b00010000010100000000000001110011") 103 | def CSRRW = BitPat("b?????????????????001?????1110011") 104 | def CSRRS = BitPat("b?????????????????010?????1110011") 105 | def CSRRC = BitPat("b?????????????????011?????1110011") 106 | def CSRRWI = BitPat("b?????????????????101?????1110011") 107 | def CSRRSI = BitPat("b?????????????????110?????1110011") 108 | def CSRRCI = BitPat("b?????????????????111?????1110011") 109 | def FADD_S = BitPat("b0000000??????????????????1010011") 110 | def FSUB_S = BitPat("b0000100??????????????????1010011") 111 | def FMUL_S = BitPat("b0001000??????????????????1010011") 112 | def FDIV_S = BitPat("b0001100??????????????????1010011") 113 | def FSGNJ_S = BitPat("b0010000??????????000?????1010011") 114 | def FSGNJN_S = BitPat("b0010000??????????001?????1010011") 115 | def FSGNJX_S = BitPat("b0010000??????????010?????1010011") 116 | def FMIN_S = BitPat("b0010100??????????000?????1010011") 117 | def FMAX_S = BitPat("b0010100??????????001?????1010011") 118 | def FSQRT_S = BitPat("b010110000000?????????????1010011") 119 | def FADD_D = BitPat("b0000001??????????????????1010011") 120 | def FSUB_D = BitPat("b0000101??????????????????1010011") 121 | def FMUL_D = BitPat("b0001001??????????????????1010011") 122 | def FDIV_D = BitPat("b0001101??????????????????1010011") 123 | def FSGNJ_D = BitPat("b0010001??????????000?????1010011") 124 | def FSGNJN_D = BitPat("b0010001??????????001?????1010011") 125 | def FSGNJX_D = BitPat("b0010001??????????010?????1010011") 126 | def FMIN_D = BitPat("b0010101??????????000?????1010011") 127 | def FMAX_D = BitPat("b0010101??????????001?????1010011") 128 | def FCVT_S_D = BitPat("b010000000001?????????????1010011") 129 | def FCVT_D_S = BitPat("b010000100000?????????????1010011") 130 | def FSQRT_D = BitPat("b010110100000?????????????1010011") 131 | def FLE_S = BitPat("b1010000??????????000?????1010011") 132 | def FLT_S = BitPat("b1010000??????????001?????1010011") 133 | def FEQ_S = BitPat("b1010000??????????010?????1010011") 134 | def FLE_D = BitPat("b1010001??????????000?????1010011") 135 | def FLT_D = BitPat("b1010001??????????001?????1010011") 136 | def FEQ_D = BitPat("b1010001??????????010?????1010011") 137 | def FCVT_W_S = BitPat("b110000000000?????????????1010011") 138 | def FCVT_WU_S = BitPat("b110000000001?????????????1010011") 139 | def FCVT_L_S = BitPat("b110000000010?????????????1010011") 140 | def FCVT_LU_S = BitPat("b110000000011?????????????1010011") 141 | def FMV_X_S = BitPat("b111000000000?????000?????1010011") 142 | def FCLASS_S = BitPat("b111000000000?????001?????1010011") 143 | def FCVT_W_D = BitPat("b110000100000?????????????1010011") 144 | def FCVT_WU_D = BitPat("b110000100001?????????????1010011") 145 | def FCVT_L_D = BitPat("b110000100010?????????????1010011") 146 | def FCVT_LU_D = BitPat("b110000100011?????????????1010011") 147 | def FMV_X_D = BitPat("b111000100000?????000?????1010011") 148 | def FCLASS_D = BitPat("b111000100000?????001?????1010011") 149 | def FCVT_S_W = BitPat("b110100000000?????????????1010011") 150 | def FCVT_S_WU = BitPat("b110100000001?????????????1010011") 151 | def FCVT_S_L = BitPat("b110100000010?????????????1010011") 152 | def FCVT_S_LU = BitPat("b110100000011?????????????1010011") 153 | def FMV_S_X = BitPat("b111100000000?????000?????1010011") 154 | def FCVT_D_W = BitPat("b110100100000?????????????1010011") 155 | def FCVT_D_WU = BitPat("b110100100001?????????????1010011") 156 | def FCVT_D_L = BitPat("b110100100010?????????????1010011") 157 | def FCVT_D_LU = BitPat("b110100100011?????????????1010011") 158 | def FMV_D_X = BitPat("b111100100000?????000?????1010011") 159 | def FLW = BitPat("b?????????????????010?????0000111") 160 | def FLD = BitPat("b?????????????????011?????0000111") 161 | def FSW = BitPat("b?????????????????010?????0100111") 162 | def FSD = BitPat("b?????????????????011?????0100111") 163 | def FMADD_S = BitPat("b?????00??????????????????1000011") 164 | def FMSUB_S = BitPat("b?????00??????????????????1000111") 165 | def FNMSUB_S = BitPat("b?????00??????????????????1001011") 166 | def FNMADD_S = BitPat("b?????00??????????????????1001111") 167 | def FMADD_D = BitPat("b?????01??????????????????1000011") 168 | def FMSUB_D = BitPat("b?????01??????????????????1000111") 169 | def FNMSUB_D = BitPat("b?????01??????????????????1001011") 170 | def FNMADD_D = BitPat("b?????01??????????????????1001111") 171 | def CUSTOM0 = BitPat("b?????????????????000?????0001011") 172 | def CUSTOM0_RS1 = BitPat("b?????????????????010?????0001011") 173 | def CUSTOM0_RS1_RS2 = BitPat("b?????????????????011?????0001011") 174 | def CUSTOM0_RD = BitPat("b?????????????????100?????0001011") 175 | def CUSTOM0_RD_RS1 = BitPat("b?????????????????110?????0001011") 176 | def CUSTOM0_RD_RS1_RS2 = BitPat("b?????????????????111?????0001011") 177 | def CUSTOM1 = BitPat("b?????????????????000?????0101011") 178 | def CUSTOM1_RS1 = BitPat("b?????????????????010?????0101011") 179 | def CUSTOM1_RS1_RS2 = BitPat("b?????????????????011?????0101011") 180 | def CUSTOM1_RD = BitPat("b?????????????????100?????0101011") 181 | def CUSTOM1_RD_RS1 = BitPat("b?????????????????110?????0101011") 182 | def CUSTOM1_RD_RS1_RS2 = BitPat("b?????????????????111?????0101011") 183 | def CUSTOM2 = BitPat("b?????????????????000?????1011011") 184 | def CUSTOM2_RS1 = BitPat("b?????????????????010?????1011011") 185 | def CUSTOM2_RS1_RS2 = BitPat("b?????????????????011?????1011011") 186 | def CUSTOM2_RD = BitPat("b?????????????????100?????1011011") 187 | def CUSTOM2_RD_RS1 = BitPat("b?????????????????110?????1011011") 188 | def CUSTOM2_RD_RS1_RS2 = BitPat("b?????????????????111?????1011011") 189 | def CUSTOM3 = BitPat("b?????????????????000?????1111011") 190 | def CUSTOM3_RS1 = BitPat("b?????????????????010?????1111011") 191 | def CUSTOM3_RS1_RS2 = BitPat("b?????????????????011?????1111011") 192 | def CUSTOM3_RD = BitPat("b?????????????????100?????1111011") 193 | def CUSTOM3_RD_RS1 = BitPat("b?????????????????110?????1111011") 194 | def CUSTOM3_RD_RS1_RS2 = BitPat("b?????????????????111?????1111011") 195 | def TAGR = BitPat("b?????????????????000?????1010111") 196 | def TAGW = BitPat("b?????????????????001?????1010111") 197 | def SLLI_RV32 = BitPat("b0000000??????????001?????0010011") 198 | def SRLI_RV32 = BitPat("b0000000??????????101?????0010011") 199 | def SRAI_RV32 = BitPat("b0100000??????????101?????0010011") 200 | def FRFLAGS = BitPat("b00000000000100000010?????1110011") 201 | def FSFLAGS = BitPat("b000000000001?????001?????1110011") 202 | def FSFLAGSI = BitPat("b000000000001?????101?????1110011") 203 | def FRRM = BitPat("b00000000001000000010?????1110011") 204 | def FSRM = BitPat("b000000000010?????001?????1110011") 205 | def FSRMI = BitPat("b000000000010?????101?????1110011") 206 | def FSCSR = BitPat("b000000000011?????001?????1110011") 207 | def FRCSR = BitPat("b00000000001100000010?????1110011") 208 | def RDCYCLE = BitPat("b11000000000000000010?????1110011") 209 | def RDTIME = BitPat("b11000000000100000010?????1110011") 210 | def RDINSTRET = BitPat("b11000000001000000010?????1110011") 211 | def RDCYCLEH = BitPat("b11001000000000000010?????1110011") 212 | def RDTIMEH = BitPat("b11001000000100000010?????1110011") 213 | def RDINSTRETH = BitPat("b11001000001000000010?????1110011") 214 | def SCALL = BitPat("b00000000000000000000000001110011") 215 | def SBREAK = BitPat("b00000000000100000000000001110011") 216 | } 217 | object Causes { 218 | val misaligned_fetch = 0x0 219 | val fault_fetch = 0x1 220 | val illegal_instruction = 0x2 221 | val breakpoint = 0x3 222 | val misaligned_load = 0x4 223 | val fault_load = 0x5 224 | val misaligned_store = 0x6 225 | val fault_store = 0x7 226 | val user_ecall = 0x8 227 | val supervisor_ecall = 0x9 228 | val hypervisor_ecall = 0xa 229 | val machine_ecall = 0xb 230 | val tag_check_failure = 0x10 // failed tag check (both ALU and memory) 231 | val all = { 232 | val res = collection.mutable.ArrayBuffer[Int]() 233 | res += misaligned_fetch 234 | res += fault_fetch 235 | res += illegal_instruction 236 | res += breakpoint 237 | res += misaligned_load 238 | res += fault_load 239 | res += misaligned_store 240 | res += fault_store 241 | res += user_ecall 242 | res += supervisor_ecall 243 | res += hypervisor_ecall 244 | res += machine_ecall 245 | res += tag_check_failure 246 | res.toArray 247 | } 248 | } 249 | object CSRs { 250 | val fflags = 0x1 251 | val frm = 0x2 252 | val fcsr = 0x3 253 | val cycle = 0xc00 254 | val time = 0xc01 255 | val instret = 0xc02 256 | val sstatus = 0x100 257 | val sie = 0x104 258 | val stvec = 0x105 259 | val sscratch = 0x140 260 | val sepc = 0x141 261 | val scause = 0x142 262 | val sbadaddr = 0x143 263 | val sip = 0x144 264 | val sptbr = 0x180 265 | val sasid = 0x181 266 | val scycle = 0xd00 267 | val stime = 0xd01 268 | val sinstret = 0xd02 269 | val mstatus = 0x300 270 | val medeleg = 0x302 271 | val mideleg = 0x303 272 | val mie = 0x304 273 | val mtvec = 0x305 274 | val mscratch = 0x340 275 | val mepc = 0x341 276 | val mcause = 0x342 277 | val mbadaddr = 0x343 278 | val mip = 0x344 279 | val mipi = 0x345 280 | val mucounteren = 0x320 281 | val mscounteren = 0x321 282 | val mucycle_delta = 0x700 283 | val mutime_delta = 0x701 284 | val muinstret_delta = 0x702 285 | val mscycle_delta = 0x704 286 | val mstime_delta = 0x705 287 | val msinstret_delta = 0x706 288 | val mcycle = 0xf00 289 | val mtime = 0xf01 290 | val minstret = 0xf02 291 | val misa = 0xf10 292 | val mvendorid = 0xf11 293 | val marchid = 0xf12 294 | val mimpid = 0xf13 295 | val mhartid = 0xf14 296 | val mreset = 0x7c2 297 | val cycleh = 0xc80 298 | val timeh = 0xc81 299 | val instreth = 0xc82 300 | val mucycle_deltah = 0x780 301 | val mutime_deltah = 0x781 302 | val muinstret_deltah = 0x782 303 | val mscycle_deltah = 0x784 304 | val mstime_deltah = 0x785 305 | val msinstret_deltah = 0x786 306 | val mcycleh = 0xf80 307 | val minstreth = 0xf82 308 | val utagctrl = 0x8f0 309 | val stagctrl = 0x9f0 310 | val mtagctrl = 0xbf0 311 | val mutagctrlen = 0x7f0 312 | val mstagctrlen = 0x7f1 313 | val swtrace = 0x8ff 314 | val all = { 315 | val res = collection.mutable.ArrayBuffer[Int]() 316 | res += fflags 317 | res += frm 318 | res += fcsr 319 | res += cycle 320 | res += time 321 | res += instret 322 | res += sstatus 323 | res += sie 324 | res += stvec 325 | res += sscratch 326 | res += sepc 327 | res += scause 328 | res += sbadaddr 329 | res += sip 330 | res += sptbr 331 | res += sasid 332 | res += scycle 333 | res += stime 334 | res += sinstret 335 | res += mstatus 336 | res += medeleg 337 | res += mideleg 338 | res += mie 339 | res += mtvec 340 | res += mscratch 341 | res += mepc 342 | res += mcause 343 | res += mbadaddr 344 | res += mip 345 | res += mipi 346 | res += mucounteren 347 | res += mscounteren 348 | res += mucycle_delta 349 | res += mutime_delta 350 | res += muinstret_delta 351 | res += mscycle_delta 352 | res += mstime_delta 353 | res += msinstret_delta 354 | res += mcycle 355 | res += mtime 356 | res += minstret 357 | res += misa 358 | res += mvendorid 359 | res += marchid 360 | res += mimpid 361 | res += mhartid 362 | res += mreset 363 | res += utagctrl 364 | res += stagctrl 365 | res += mtagctrl 366 | res += mutagctrlen 367 | res += mstagctrlen 368 | res += swtrace 369 | res.toArray 370 | } 371 | val all32 = { 372 | val res = collection.mutable.ArrayBuffer(all:_*) 373 | res += cycleh 374 | res += timeh 375 | res += instreth 376 | res += mucycle_deltah 377 | res += mutime_deltah 378 | res += muinstret_deltah 379 | res += mscycle_deltah 380 | res += mstime_deltah 381 | res += msinstret_deltah 382 | res += mcycleh 383 | res += minstreth 384 | res.toArray 385 | } 386 | } 387 | -------------------------------------------------------------------------------- /src/main/scala/multiplier.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package rocket 4 | 5 | import Chisel._ 6 | import ALU._ 7 | import Util._ 8 | 9 | class MultiplierReq(dataBits: Int, tagBits: Int) extends Bundle { 10 | val fn = Bits(width = SZ_ALU_FN) 11 | val dw = Bits(width = SZ_DW) 12 | val in1 = Bits(width = dataBits) 13 | val in2 = Bits(width = dataBits) 14 | val tag = UInt(width = tagBits) 15 | override def cloneType = new MultiplierReq(dataBits, tagBits).asInstanceOf[this.type] 16 | } 17 | 18 | class MultiplierResp(dataBits: Int, tagBits: Int) extends Bundle { 19 | val data = Bits(width = dataBits) 20 | val tag = UInt(width = tagBits) 21 | override def cloneType = new MultiplierResp(dataBits, tagBits).asInstanceOf[this.type] 22 | } 23 | 24 | class MultiplierIO(dataBits: Int, tagBits: Int) extends Bundle { 25 | val req = Decoupled(new MultiplierReq(dataBits, tagBits)).flip 26 | val kill = Bool(INPUT) 27 | val resp = Decoupled(new MultiplierResp(dataBits, tagBits)) 28 | } 29 | 30 | class MulDiv( 31 | width: Int, 32 | nXpr: Int = 32, 33 | unroll: Int = 1, 34 | earlyOut: Boolean = false) extends Module { 35 | val io = new MultiplierIO(width, log2Up(nXpr)) 36 | val w = io.req.bits.in1.getWidth 37 | val mulw = (w+unroll-1)/unroll*unroll 38 | 39 | val s_ready :: s_neg_inputs :: s_busy :: s_move_rem :: s_neg_output :: s_done :: Nil = Enum(UInt(), 6) 40 | val state = Reg(init=s_ready) 41 | 42 | val req = Reg(io.req.bits) 43 | val count = Reg(UInt(width = log2Up(w+1))) 44 | val neg_out = Reg(Bool()) 45 | val isMul = Reg(Bool()) 46 | val isHi = Reg(Bool()) 47 | val divisor = Reg(Bits(width = w+1)) // div only needs w bits 48 | val remainder = Reg(Bits(width = 2*mulw+2)) // div only needs 2*w+1 bits 49 | 50 | val cmdMul :: cmdHi :: lhsSigned :: rhsSigned :: Nil = 51 | DecodeLogic(io.req.bits.fn, List(X, X, X, X), List( 52 | FN_DIV -> List(N, N, Y, Y), 53 | FN_REM -> List(N, Y, Y, Y), 54 | FN_DIVU -> List(N, N, N, N), 55 | FN_REMU -> List(N, Y, N, N), 56 | FN_MUL -> List(Y, N, X, X), 57 | FN_MULH -> List(Y, Y, Y, Y), 58 | FN_MULHU -> List(Y, Y, N, N), 59 | FN_MULHSU -> List(Y, Y, Y, N))).map(_ toBool) 60 | 61 | def sext(x: Bits, signed: Bool) = { 62 | val sign = signed && Mux(io.req.bits.dw === DW_64, x(w-1), x(w/2-1)) 63 | val hi = Mux(io.req.bits.dw === DW_64, x(w-1,w/2), Fill(w/2, sign)) 64 | (Cat(hi, x(w/2-1,0)), sign) 65 | } 66 | val (lhs_in, lhs_sign) = sext(io.req.bits.in1, lhsSigned) 67 | val (rhs_in, rhs_sign) = sext(io.req.bits.in2, rhsSigned) 68 | 69 | val subtractor = remainder(2*w,w) - divisor(w,0) 70 | val less = subtractor(w) 71 | val negated_remainder = -remainder(w-1,0) 72 | 73 | when (state === s_neg_inputs) { 74 | when (remainder(w-1) || isMul) { 75 | remainder := negated_remainder 76 | } 77 | when (divisor(w-1) || isMul) { 78 | divisor := subtractor 79 | } 80 | state := s_busy 81 | } 82 | 83 | when (state === s_neg_output) { 84 | remainder := negated_remainder 85 | state := s_done 86 | } 87 | when (state === s_move_rem) { 88 | remainder := remainder(2*w, w+1) 89 | state := Mux(neg_out, s_neg_output, s_done) 90 | } 91 | when (state === s_busy && isMul) { 92 | val mulReg = Cat(remainder(2*mulw+1,w+1),remainder(w-1,0)) 93 | val mplier = mulReg(mulw-1,0) 94 | val accum = mulReg(2*mulw,mulw).toSInt 95 | val mpcand = divisor.toSInt 96 | val prod = mplier(unroll-1,0) * mpcand + accum 97 | val nextMulReg = Cat(prod, mplier(mulw-1,unroll)).toUInt 98 | 99 | val eOutMask = (SInt(BigInt(-1) << mulw) >> (count * unroll)(log2Up(mulw)-1,0))(mulw-1,0) 100 | val eOut = Bool(earlyOut) && count =/= mulw/unroll-1 && count =/= 0 && 101 | !isHi && (mplier & ~eOutMask) === UInt(0) 102 | val eOutRes = (mulReg >> (mulw - count * unroll)(log2Up(mulw)-1,0)) 103 | val nextMulReg1 = Cat(nextMulReg(2*mulw,mulw), Mux(eOut, eOutRes, nextMulReg)(mulw-1,0)) 104 | remainder := Cat(nextMulReg1 >> w, Bool(false), nextMulReg1(w-1,0)) 105 | 106 | count := count + 1 107 | when (eOut || count === mulw/unroll-1) { 108 | state := Mux(isHi, s_move_rem, s_done) 109 | } 110 | } 111 | when (state === s_busy && !isMul) { 112 | when (count === w) { 113 | state := Mux(isHi, s_move_rem, Mux(neg_out, s_neg_output, s_done)) 114 | } 115 | count := count + 1 116 | 117 | remainder := Cat(Mux(less, remainder(2*w-1,w), subtractor(w-1,0)), remainder(w-1,0), !less) 118 | 119 | val divisorMSB = Log2(divisor(w-1,0), w) 120 | val dividendMSB = Log2(remainder(w-1,0), w) 121 | val eOutPos = UInt(w-1) + divisorMSB - dividendMSB 122 | val eOutZero = divisorMSB > dividendMSB 123 | val eOut = count === 0 && less /* not divby0 */ && (eOutPos > 0 || eOutZero) 124 | when (Bool(earlyOut) && eOut) { 125 | val shift = Mux(eOutZero, UInt(w-1), eOutPos(log2Up(w)-1,0)) 126 | remainder := remainder(w-1,0) << shift 127 | count := shift 128 | } 129 | when (count === 0 && !less /* divby0 */ && !isHi) { neg_out := false } 130 | } 131 | when (io.resp.fire() || io.kill) { 132 | state := s_ready 133 | } 134 | when (io.req.fire()) { 135 | state := Mux(lhs_sign || rhs_sign && !cmdMul, s_neg_inputs, s_busy) 136 | isMul := cmdMul 137 | isHi := cmdHi 138 | count := 0 139 | neg_out := !cmdMul && Mux(cmdHi, lhs_sign, lhs_sign =/= rhs_sign) 140 | divisor := Cat(rhs_sign, rhs_in) 141 | remainder := lhs_in 142 | req := io.req.bits 143 | } 144 | 145 | io.resp.bits := req 146 | io.resp.bits.data := Mux(req.dw === DW_32, Cat(Fill(w/2, remainder(w/2-1)), remainder(w/2-1,0)), remainder(w-1,0)) 147 | io.resp.valid := state === s_done 148 | io.req.ready := state === s_ready 149 | } 150 | -------------------------------------------------------------------------------- /src/main/scala/package.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package object rocket extends 4 | rocket.constants.ScalarOpConstants 5 | -------------------------------------------------------------------------------- /src/main/scala/ptw.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package rocket 4 | 5 | import Chisel._ 6 | import uncore._ 7 | import Util._ 8 | import cde.{Parameters, Field} 9 | 10 | class PTWReq(implicit p: Parameters) extends CoreBundle()(p) { 11 | val prv = Bits(width = 2) 12 | val pum = Bool() 13 | val mxr = Bool() 14 | val addr = UInt(width = vpnBits) 15 | val store = Bool() 16 | val fetch = Bool() 17 | } 18 | 19 | class PTWResp(implicit p: Parameters) extends CoreBundle()(p) { 20 | val pte = new PTE 21 | } 22 | 23 | class TLBPTWIO(implicit p: Parameters) extends CoreBundle()(p) { 24 | val req = Decoupled(new PTWReq) 25 | val resp = Valid(new PTWResp).flip 26 | val status = new MStatus().asInput 27 | val invalidate = Bool(INPUT) 28 | } 29 | 30 | class DatapathPTWIO(implicit p: Parameters) extends CoreBundle()(p) { 31 | val ptbr = UInt(INPUT, ppnBits) 32 | val invalidate = Bool(INPUT) 33 | val status = new MStatus().asInput 34 | } 35 | 36 | class PTE(implicit p: Parameters) extends CoreBundle()(p) { 37 | val reserved_for_hardware = Bits(width = 16) 38 | val ppn = UInt(width = 38) 39 | val reserved_for_software = Bits(width = 2) 40 | val d = Bool() 41 | val a = Bool() 42 | val g = Bool() 43 | val u = Bool() 44 | val x = Bool() 45 | val w = Bool() 46 | val r = Bool() 47 | val v = Bool() 48 | 49 | def table(dummy: Int = 0) = v && !r && !w && !x 50 | def leaf(dummy: Int = 0) = v && (r || (x && !w)) 51 | def ur(dummy: Int = 0) = sr() && u 52 | def uw(dummy: Int = 0) = sw() && u 53 | def ux(dummy: Int = 0) = sx() && u 54 | def sr(dummy: Int = 0) = leaf() && r 55 | def sw(dummy: Int = 0) = leaf() && w 56 | def sx(dummy: Int = 0) = leaf() && x 57 | 58 | def access_ok(req: PTWReq) = { 59 | val perm_ok = Mux(req.fetch, x, Mux(req.store, w, r || (x && req.mxr))) 60 | val priv_ok = Mux(u, !req.pum, req.prv(0)) 61 | leaf() && priv_ok && perm_ok 62 | } 63 | } 64 | 65 | class PTW(n: Int)(implicit p: Parameters) extends CoreModule()(p) { 66 | val io = new Bundle { 67 | val requestor = Vec(n, new TLBPTWIO).flip 68 | val mem = new HellaCacheIO 69 | val dpath = new DatapathPTWIO 70 | } 71 | 72 | val s_ready :: s_req :: s_wait :: s_set_dirty :: s_wait_dirty :: s_done :: Nil = Enum(UInt(), 6) 73 | val state = Reg(init=s_ready) 74 | val count = Reg(UInt(width = log2Up(pgLevels))) 75 | 76 | val r_req = Reg(new PTWReq) 77 | val r_req_dest = Reg(Bits()) 78 | val r_pte = Reg(new PTE) 79 | 80 | val vpn_idx = Vec((0 until pgLevels).map(i => (r_req.addr >> (pgLevels-i-1)*pgLevelBits)(pgLevelBits-1,0)))(count) 81 | 82 | val arb = Module(new RRArbiter(new PTWReq, n)) 83 | arb.io.in <> io.requestor.map(_.req) 84 | arb.io.out.ready := state === s_ready 85 | 86 | val pte = new PTE().fromBits(io.mem.resp.bits.data) 87 | val pte_addr = Cat(r_pte.ppn, vpn_idx).toUInt << log2Up(xLen/8) 88 | 89 | when (arb.io.out.fire()) { 90 | r_req := arb.io.out.bits 91 | r_req_dest := arb.io.chosen 92 | r_pte.ppn := io.dpath.ptbr 93 | } 94 | 95 | val (pte_cache_hit, pte_cache_data) = { 96 | val size = log2Up(pgLevels * 2) 97 | val plru = new PseudoLRU(size) 98 | val valid = Reg(Vec(size, Bool())) 99 | val validBits = valid.toBits 100 | val tags = Mem(size, UInt(width = paddrBits)) 101 | val data = Mem(size, UInt(width = ppnBits)) 102 | 103 | val hits = Vec(tags.map(_ === pte_addr)).toBits & validBits 104 | val hit = hits.orR 105 | when (io.mem.resp.valid && pte.table() && !hit) { 106 | val r = Mux(validBits.andR, plru.replace, PriorityEncoder(~validBits)) 107 | valid(r) := true 108 | tags(r) := pte_addr 109 | data(r) := pte.ppn 110 | } 111 | when (hit && state === s_req) { plru.access(OHToUInt(hits)) } 112 | when (reset || io.dpath.invalidate) { valid.foreach(_ := false) } 113 | 114 | (hit, Mux1H(hits, data)) 115 | } 116 | 117 | val set_dirty_bit = pte.access_ok(r_req) && (!pte.a || (r_req.store && !pte.d)) 118 | when (io.mem.resp.valid && state === s_wait && !set_dirty_bit) { 119 | r_pte := pte 120 | } 121 | 122 | val pte_wdata = Wire(init=new PTE().fromBits(0)) 123 | pte_wdata.a := true 124 | pte_wdata.d := r_req.store 125 | 126 | io.mem.req.valid := state === s_req || state === s_set_dirty 127 | io.mem.req.bits.phys := Bool(true) 128 | io.mem.req.bits.cmd := Mux(state === s_set_dirty, M_XA_OR, M_XRD) 129 | io.mem.req.bits.typ := MT_D 130 | io.mem.req.bits.addr := pte_addr 131 | io.mem.s1_data := pte_wdata.toBits 132 | io.mem.s1_kill := Bool(false) 133 | io.mem.invalidate_lr := Bool(false) 134 | 135 | val r_resp_ppn = io.mem.req.bits.addr >> pgIdxBits 136 | val resp_ppn = Vec((0 until pgLevels-1).map(i => Cat(r_resp_ppn >> pgLevelBits*(pgLevels-i-1), r_req.addr(pgLevelBits*(pgLevels-i-1)-1,0))) :+ r_resp_ppn)(count) 137 | val resp_val = state === s_done 138 | 139 | for (i <- 0 until io.requestor.size) { 140 | io.requestor(i).resp.valid := resp_val && (r_req_dest === i) 141 | io.requestor(i).resp.bits.pte := r_pte 142 | io.requestor(i).resp.bits.pte.ppn := resp_ppn 143 | io.requestor(i).invalidate := io.dpath.invalidate 144 | io.requestor(i).status := io.dpath.status 145 | } 146 | 147 | // control state machine 148 | switch (state) { 149 | is (s_ready) { 150 | when (arb.io.out.valid) { 151 | state := s_req 152 | } 153 | count := UInt(0) 154 | } 155 | is (s_req) { 156 | when (pte_cache_hit && count < pgLevels-1) { 157 | io.mem.req.valid := false 158 | state := s_req 159 | count := count + 1 160 | r_pte.ppn := pte_cache_data 161 | }.elsewhen (io.mem.req.ready) { 162 | state := s_wait 163 | } 164 | } 165 | is (s_wait) { 166 | when (io.mem.s2_nack) { 167 | state := s_req 168 | } 169 | when (io.mem.resp.valid) { 170 | state := s_done 171 | when (set_dirty_bit) { 172 | state := s_set_dirty 173 | } 174 | when (pte.table() && count < pgLevels-1) { 175 | state := s_req 176 | count := count + 1 177 | } 178 | } 179 | } 180 | is (s_set_dirty) { 181 | when (io.mem.req.ready) { 182 | state := s_wait_dirty 183 | } 184 | } 185 | is (s_wait_dirty) { 186 | when (io.mem.s2_nack) { 187 | state := s_set_dirty 188 | } 189 | when (io.mem.resp.valid) { 190 | state := s_req 191 | } 192 | } 193 | is (s_done) { 194 | state := s_ready 195 | } 196 | } 197 | } 198 | -------------------------------------------------------------------------------- /src/main/scala/rocc.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package rocket 4 | 5 | import Chisel._ 6 | import uncore._ 7 | import Util._ 8 | import cde.{Parameters, Field} 9 | 10 | case object RoccMaxTaggedMemXacts extends Field[Int] 11 | case object RoccNMemChannels extends Field[Int] 12 | case object RoccNPTWPorts extends Field[Int] 13 | case object RoccNCSRs extends Field[Int] 14 | 15 | class RoCCCSRs(implicit p: Parameters) extends CoreBundle()(p) { 16 | val rdata = Vec(nRoccCsrs, UInt(INPUT, xLen)) 17 | val waddr = UInt(OUTPUT, CSR.ADDRSZ) 18 | val wdata = UInt(OUTPUT, xLen) 19 | val wen = Bool(OUTPUT) 20 | } 21 | 22 | class RoCCInstruction extends Bundle 23 | { 24 | val funct = Bits(width = 7) 25 | val rs2 = Bits(width = 5) 26 | val rs1 = Bits(width = 5) 27 | val xd = Bool() 28 | val xs1 = Bool() 29 | val xs2 = Bool() 30 | val rd = Bits(width = 5) 31 | val opcode = Bits(width = 7) 32 | } 33 | 34 | class RoCCCommand(implicit p: Parameters) extends CoreBundle()(p) { 35 | val inst = new RoCCInstruction 36 | val rs1 = Bits(width = xLen) 37 | val rs2 = Bits(width = xLen) 38 | } 39 | 40 | class RoCCResponse(implicit p: Parameters) extends CoreBundle()(p) { 41 | val rd = Bits(width = 5) 42 | val data = Bits(width = xLen) 43 | } 44 | 45 | class RoCCInterface(implicit p: Parameters) extends CoreBundle()(p) { 46 | val cmd = Decoupled(new RoCCCommand).flip 47 | val resp = Decoupled(new RoCCResponse) 48 | val mem = new HellaCacheIO()(p.alterPartial({ case CacheName => "L1D" })) 49 | val busy = Bool(OUTPUT) 50 | val status = new MStatus().asInput 51 | val interrupt = Bool(OUTPUT) 52 | 53 | // These should be handled differently, eventually 54 | val autl = new ClientUncachedTileLinkIO 55 | val utl = Vec(p(RoccNMemChannels), new ClientUncachedTileLinkIO) 56 | val ptw = Vec(p(RoccNPTWPorts), new TLBPTWIO) 57 | val fpu_req = Decoupled(new FPInput) 58 | val fpu_resp = Decoupled(new FPResult).flip 59 | val exception = Bool(INPUT) 60 | val csr = (new RoCCCSRs).flip 61 | val host_id = UInt(INPUT, log2Up(nCores)) 62 | 63 | override def cloneType = new RoCCInterface().asInstanceOf[this.type] 64 | } 65 | 66 | abstract class RoCC(implicit p: Parameters) extends CoreModule()(p) { 67 | val io = new RoCCInterface 68 | io.mem.req.bits.phys := Bool(true) // don't perform address translation 69 | } 70 | 71 | class AccumulatorExample(n: Int = 4)(implicit p: Parameters) extends RoCC()(p) { 72 | val regfile = Mem(n, UInt(width = xLen)) 73 | val busy = Reg(init = Vec.fill(n){Bool(false)}) 74 | 75 | val cmd = Queue(io.cmd) 76 | val funct = cmd.bits.inst.funct 77 | val addr = cmd.bits.rs2(log2Up(n)-1,0) 78 | val doWrite = funct === UInt(0) 79 | val doRead = funct === UInt(1) 80 | val doLoad = funct === UInt(2) 81 | val doAccum = funct === UInt(3) 82 | val memRespTag = io.mem.resp.bits.tag(log2Up(n)-1,0) 83 | 84 | // datapath 85 | val addend = cmd.bits.rs1 86 | val accum = regfile(addr) 87 | val wdata = Mux(doWrite, addend, accum + addend) 88 | 89 | when (cmd.fire() && (doWrite || doAccum)) { 90 | regfile(addr) := wdata 91 | } 92 | 93 | when (io.mem.resp.valid) { 94 | regfile(memRespTag) := io.mem.resp.bits.data 95 | } 96 | 97 | // control 98 | when (io.mem.req.fire()) { 99 | busy(addr) := Bool(true) 100 | } 101 | 102 | when (io.mem.resp.valid) { 103 | busy(memRespTag) := Bool(false) 104 | } 105 | 106 | val doResp = cmd.bits.inst.xd 107 | val stallReg = busy(addr) 108 | val stallLoad = doLoad && !io.mem.req.ready 109 | val stallResp = doResp && !io.resp.ready 110 | 111 | cmd.ready := !stallReg && !stallLoad && !stallResp 112 | // command resolved if no stalls AND not issuing a load that will need a request 113 | 114 | // PROC RESPONSE INTERFACE 115 | io.resp.valid := cmd.valid && doResp && !stallReg && !stallLoad 116 | // valid response if valid command, need a response, and no stalls 117 | io.resp.bits.rd := cmd.bits.inst.rd 118 | // Must respond with the appropriate tag or undefined behavior 119 | io.resp.bits.data := accum 120 | // Semantics is to always send out prior accumulator register value 121 | 122 | io.busy := cmd.valid || busy.reduce(_||_) 123 | // Be busy when have pending memory requests or committed possibility of pending requests 124 | io.interrupt := Bool(false) 125 | // Set this true to trigger an interrupt on the processor (please refer to supervisor documentation) 126 | 127 | // MEMORY REQUEST INTERFACE 128 | io.mem.req.valid := cmd.valid && doLoad && !stallReg && !stallResp 129 | io.mem.req.bits.addr := addend 130 | io.mem.req.bits.tag := addr 131 | io.mem.req.bits.cmd := M_XRD // perform a load (M_XWR for stores) 132 | io.mem.req.bits.typ := MT_D // D = 8 bytes, W = 4, H = 2, B = 1 133 | io.mem.req.bits.data := Bits(0) // we're not performing any stores... 134 | io.mem.invalidate_lr := false 135 | 136 | io.autl.acquire.valid := false 137 | io.autl.grant.ready := false 138 | } 139 | 140 | class TranslatorExample(implicit p: Parameters) extends RoCC()(p) { 141 | val req_addr = Reg(UInt(width = coreMaxAddrBits)) 142 | val req_rd = Reg(io.resp.bits.rd) 143 | val req_offset = req_addr(pgIdxBits - 1, 0) 144 | val req_vpn = req_addr(coreMaxAddrBits - 1, pgIdxBits) 145 | val pte = Reg(new PTE) 146 | 147 | val s_idle :: s_ptw_req :: s_ptw_resp :: s_resp :: Nil = Enum(Bits(), 4) 148 | val state = Reg(init = s_idle) 149 | 150 | io.cmd.ready := (state === s_idle) 151 | 152 | when (io.cmd.fire()) { 153 | req_rd := io.cmd.bits.inst.rd 154 | req_addr := io.cmd.bits.rs1 155 | state := s_ptw_req 156 | } 157 | 158 | private val ptw = io.ptw(0) 159 | 160 | when (ptw.req.fire()) { state := s_ptw_resp } 161 | 162 | when (state === s_ptw_resp && ptw.resp.valid) { 163 | pte := ptw.resp.bits.pte 164 | state := s_resp 165 | } 166 | 167 | when (io.resp.fire()) { state := s_idle } 168 | 169 | ptw.req.valid := (state === s_ptw_req) 170 | ptw.req.bits.addr := req_vpn 171 | ptw.req.bits.store := Bool(false) 172 | ptw.req.bits.fetch := Bool(false) 173 | 174 | io.resp.valid := (state === s_resp) 175 | io.resp.bits.rd := req_rd 176 | io.resp.bits.data := Mux(pte.leaf(), Cat(pte.ppn, req_offset), ~UInt(0, xLen)) 177 | 178 | io.busy := (state =/= s_idle) 179 | io.interrupt := Bool(false) 180 | io.mem.req.valid := Bool(false) 181 | io.autl.acquire.valid := Bool(false) 182 | io.autl.grant.ready := Bool(false) 183 | } 184 | 185 | class CharacterCountExample(implicit p: Parameters) extends RoCC()(p) 186 | with HasTileLinkParameters { 187 | 188 | private val blockOffset = tlBeatAddrBits + tlByteAddrBits 189 | 190 | val needle = Reg(UInt(width = 8)) 191 | val addr = Reg(UInt(width = coreMaxAddrBits)) 192 | val count = Reg(UInt(width = xLen)) 193 | val resp_rd = Reg(io.resp.bits.rd) 194 | 195 | val addr_block = addr(coreMaxAddrBits - 1, blockOffset) 196 | val offset = addr(blockOffset - 1, 0) 197 | val next_addr = (addr_block + UInt(1)) << UInt(blockOffset) 198 | 199 | val s_idle :: s_acq :: s_gnt :: s_check :: s_resp :: Nil = Enum(Bits(), 5) 200 | val state = Reg(init = s_idle) 201 | 202 | val gnt = io.autl.grant.bits 203 | val recv_data = Reg(UInt(width = tlDataBits)) 204 | val recv_beat = Reg(UInt(width = tlBeatAddrBits)) 205 | 206 | val data_bytes = Vec.tabulate(tlDataBytes) { i => recv_data(8 * (i + 1) - 1, 8 * i) } 207 | val zero_match = data_bytes.map(_ === UInt(0)) 208 | val needle_match = data_bytes.map(_ === needle) 209 | val first_zero = PriorityEncoder(zero_match) 210 | 211 | val chars_found = PopCount(needle_match.zipWithIndex.map { 212 | case (matches, i) => 213 | val idx = Cat(recv_beat, UInt(i, tlByteAddrBits)) 214 | matches && idx >= offset && UInt(i) <= first_zero 215 | }) 216 | val zero_found = zero_match.reduce(_ || _) 217 | val finished = Reg(Bool()) 218 | 219 | io.cmd.ready := (state === s_idle) 220 | io.resp.valid := (state === s_resp) 221 | io.resp.bits.rd := resp_rd 222 | io.resp.bits.data := count 223 | io.autl.acquire.valid := (state === s_acq) 224 | io.autl.acquire.bits := GetBlock(addr_block = addr_block) 225 | io.autl.grant.ready := (state === s_gnt) 226 | 227 | when (io.cmd.fire()) { 228 | addr := io.cmd.bits.rs1 229 | needle := io.cmd.bits.rs2 230 | resp_rd := io.cmd.bits.inst.rd 231 | count := UInt(0) 232 | finished := Bool(false) 233 | state := s_acq 234 | } 235 | 236 | when (io.autl.acquire.fire()) { state := s_gnt } 237 | 238 | when (io.autl.grant.fire()) { 239 | recv_beat := gnt.addr_beat 240 | recv_data := gnt.data 241 | state := s_check 242 | } 243 | 244 | when (state === s_check) { 245 | when (!finished) { 246 | count := count + chars_found 247 | } 248 | when (zero_found) { finished := Bool(true) } 249 | when (recv_beat === UInt(tlDataBeats - 1)) { 250 | addr := next_addr 251 | state := Mux(zero_found || finished, s_resp, s_acq) 252 | } .otherwise { 253 | state := s_gnt 254 | } 255 | } 256 | 257 | when (io.resp.fire()) { state := s_idle } 258 | 259 | io.busy := (state =/= s_idle) 260 | io.interrupt := Bool(false) 261 | io.mem.req.valid := Bool(false) 262 | } 263 | 264 | class OpcodeSet(val opcodes: Seq[UInt]) { 265 | def |(set: OpcodeSet) = 266 | new OpcodeSet(this.opcodes ++ set.opcodes) 267 | 268 | def matches(oc: UInt) = opcodes.map(_ === oc).reduce(_ || _) 269 | } 270 | 271 | object OpcodeSet { 272 | val custom0 = new OpcodeSet(Seq(Bits("b0001011"))) 273 | val custom1 = new OpcodeSet(Seq(Bits("b0101011"))) 274 | val custom2 = new OpcodeSet(Seq(Bits("b1011011"))) 275 | val custom3 = new OpcodeSet(Seq(Bits("b1111011"))) 276 | val all = custom0 | custom1 | custom2 | custom3 277 | } 278 | 279 | class RoccCommandRouter(opcodes: Seq[OpcodeSet])(implicit p: Parameters) 280 | extends CoreModule()(p) { 281 | val io = new Bundle { 282 | val in = Decoupled(new RoCCCommand).flip 283 | val out = Vec(opcodes.size, Decoupled(new RoCCCommand)) 284 | val busy = Bool(OUTPUT) 285 | } 286 | 287 | val cmd = Queue(io.in) 288 | val cmdReadys = io.out.zip(opcodes).map { case (out, opcode) => 289 | val me = opcode.matches(cmd.bits.inst.opcode) 290 | out.valid := cmd.valid && me 291 | out.bits := cmd.bits 292 | out.ready && me 293 | } 294 | cmd.ready := cmdReadys.reduce(_ || _) 295 | io.busy := cmd.valid 296 | 297 | assert(PopCount(cmdReadys) <= UInt(1), 298 | "Custom opcode matched for more than one accelerator") 299 | } 300 | -------------------------------------------------------------------------------- /src/main/scala/tile.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package rocket 4 | 5 | import Chisel._ 6 | import uncore._ 7 | import open_soc_debug._ 8 | import Util._ 9 | import cde.{Parameters, Field} 10 | 11 | case object CoreName extends Field[String] 12 | case object BuildRoCC extends Field[Seq[RoccParameters]] 13 | 14 | case class RoccParameters( 15 | opcodes: OpcodeSet, 16 | generator: Parameters => RoCC, 17 | nMemChannels: Int = 0, 18 | nPTWPorts : Int = 0, 19 | csrs: Seq[Int] = Nil, 20 | useFPU: Boolean = false) 21 | 22 | abstract class Tile(resetSignal: Bool = null) 23 | (implicit p: Parameters) extends Module(_reset = resetSignal) { 24 | val buildRocc = p(BuildRoCC) 25 | val usingRocc = !buildRocc.isEmpty 26 | val nRocc = buildRocc.size 27 | val nFPUPorts = buildRocc.filter(_.useFPU).size 28 | val nCachedTileLinkPorts = 1 29 | val nUncachedTileLinkPorts = 1 + p(RoccNMemChannels) 30 | val dcacheParams = p.alterPartial({ case CacheName => "L1D" }) 31 | val io = new Bundle { 32 | val cached = Vec(nCachedTileLinkPorts, new ClientTileLinkIO) 33 | val uncached = Vec(nUncachedTileLinkPorts, new ClientUncachedTileLinkIO) 34 | 35 | val irq = Bool(INPUT) 36 | val dbgrst = Bool(INPUT) 37 | val dbgnet = Vec(2, new DiiIO) // debug network 38 | val prci = new PRCITileIO().flip 39 | val dma = new DmaIO 40 | } 41 | } 42 | 43 | class RocketTile(id: Int = 0, resetSignal: Bool = null)(implicit p: Parameters) extends Tile(resetSignal)(p) { 44 | val core = Module(new Rocket(id)(p.alterPartial({ case CoreName => "Rocket" }))) 45 | val icache = Module(new Frontend()(p.alterPartial({ 46 | case CacheName => "L1I" 47 | case CoreName => "Rocket" }))) 48 | val dcache = Module(new HellaCache()(dcacheParams)) 49 | 50 | val ptwPorts = collection.mutable.ArrayBuffer(icache.io.ptw, dcache.io.ptw) 51 | val dcPorts = collection.mutable.ArrayBuffer(core.io.dmem) 52 | val uncachedArbPorts = collection.mutable.ArrayBuffer(icache.io.mem) 53 | val uncachedPorts = collection.mutable.ArrayBuffer[ClientUncachedTileLinkIO]() 54 | val cachedPorts = collection.mutable.ArrayBuffer(dcache.io.mem) 55 | core.io.prci <> io.prci 56 | icache.io.cpu <> core.io.imem 57 | core.io.irq <> io.irq 58 | 59 | val fpuOpt = if (p(UseFPU)) Some(Module(new FPU)) else None 60 | fpuOpt.foreach(fpu => core.io.fpu <> fpu.io) 61 | 62 | if (usingRocc) { 63 | val respArb = Module(new RRArbiter(new RoCCResponse, nRocc)) 64 | core.io.rocc.resp <> respArb.io.out 65 | 66 | val roccOpcodes = buildRocc.map(_.opcodes) 67 | val cmdRouter = Module(new RoccCommandRouter(roccOpcodes)) 68 | cmdRouter.io.in <> core.io.rocc.cmd 69 | 70 | val roccs = buildRocc.zipWithIndex.map { case (accelParams, i) => 71 | val rocc = accelParams.generator(p.alterPartial({ 72 | case RoccNMemChannels => accelParams.nMemChannels 73 | case RoccNPTWPorts => accelParams.nPTWPorts 74 | case RoccNCSRs => accelParams.csrs.size 75 | })) 76 | val dcIF = Module(new SimpleHellaCacheIF()(dcacheParams)) 77 | rocc.io.cmd <> cmdRouter.io.out(i) 78 | rocc.io.status := core.io.rocc.status 79 | rocc.io.exception := core.io.rocc.exception 80 | rocc.io.host_id := UInt(id) 81 | dcIF.io.requestor <> rocc.io.mem 82 | dcPorts += dcIF.io.cache 83 | uncachedArbPorts += rocc.io.autl 84 | rocc 85 | } 86 | 87 | if (nFPUPorts > 0) { 88 | fpuOpt.foreach { fpu => 89 | val fpArb = Module(new InOrderArbiter(new FPInput, new FPResult, nFPUPorts)) 90 | val fp_roccs = roccs.zip(buildRocc) 91 | .filter { case (_, params) => params.useFPU } 92 | .map { case (rocc, _) => rocc.io } 93 | fpArb.io.in_req <> fp_roccs.map(_.fpu_req) 94 | fp_roccs.zip(fpArb.io.in_resp).foreach { 95 | case (rocc, fpu_resp) => rocc.fpu_resp <> fpu_resp 96 | } 97 | fpu.io.cp_req <> fpArb.io.out_req 98 | fpArb.io.out_resp <> fpu.io.cp_resp 99 | } 100 | } 101 | 102 | core.io.rocc.busy := cmdRouter.io.busy || roccs.map(_.io.busy).reduce(_ || _) 103 | core.io.rocc.interrupt := roccs.map(_.io.interrupt).reduce(_ || _) 104 | respArb.io.in <> roccs.map(rocc => Queue(rocc.io.resp)) 105 | 106 | if (p(RoccNCSRs) > 0) { 107 | core.io.rocc.csr.rdata <> roccs.map(_.io.csr.rdata).reduce(_ ++ _) 108 | for ((rocc, accelParams) <- roccs.zip(buildRocc)) { 109 | rocc.io.csr.waddr := core.io.rocc.csr.waddr 110 | rocc.io.csr.wdata := core.io.rocc.csr.wdata 111 | rocc.io.csr.wen := core.io.rocc.csr.wen && 112 | accelParams.csrs 113 | .map(core.io.rocc.csr.waddr === UInt(_)) 114 | .reduce((a, b) => a || b) 115 | } 116 | } 117 | 118 | ptwPorts ++= roccs.flatMap(_.io.ptw) 119 | uncachedPorts ++= roccs.flatMap(_.io.utl) 120 | } 121 | 122 | val uncachedArb = Module(new ClientUncachedTileLinkIOArbiter(uncachedArbPorts.size)) 123 | uncachedArb.io.in <> uncachedArbPorts 124 | uncachedArb.io.out +=: uncachedPorts 125 | 126 | // Connect the caches and RoCC to the outer memory system 127 | io.uncached <> uncachedPorts 128 | io.cached <> cachedPorts 129 | // TODO remove nCached/nUncachedTileLinkPorts parameters and these assertions 130 | require(uncachedPorts.size == nUncachedTileLinkPorts) 131 | require(cachedPorts.size == nCachedTileLinkPorts) 132 | 133 | if (p(UseVM)) { 134 | val ptw = Module(new PTW(ptwPorts.size)(dcacheParams)) 135 | ptw.io.requestor <> ptwPorts 136 | ptw.io.mem +=: dcPorts 137 | core.io.ptw <> ptw.io.dpath 138 | } 139 | 140 | val dcArb = Module(new HellaCacheArbiter(dcPorts.size)(dcacheParams)) 141 | dcArb.io.requestor <> dcPorts 142 | dcache.io.cpu <> dcArb.io.mem 143 | 144 | if (!usingRocc || nFPUPorts == 0) { 145 | fpuOpt.foreach { fpu => 146 | fpu.io.cp_req.valid := Bool(false) 147 | fpu.io.cp_resp.ready := Bool(false) 148 | } 149 | } 150 | 151 | // tagged memory 152 | core.io.dmem.tag_xcpt := dcache.io.cpu.tag_xcpt 153 | core.io.dmem.tag_replay := dcache.io.cpu.tag_replay 154 | dcache.io.cpu.tag_ctrl := core.io.dmem.tag_ctrl 155 | dcache.io.cpu.ex_xcpt := core.io.dmem.ex_xcpt 156 | 157 | // debug 158 | io.dbgnet <> core.io.dbgnet 159 | io.dbgrst <> core.io.dbgrst 160 | } 161 | -------------------------------------------------------------------------------- /src/main/scala/tlb.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package rocket 4 | 5 | import Chisel._ 6 | import Util._ 7 | import junctions._ 8 | import scala.math._ 9 | import cde.{Parameters, Field} 10 | import uncore.PseudoLRU 11 | 12 | case object NTLBEntries extends Field[Int] 13 | 14 | trait HasTLBParameters extends HasCoreParameters { 15 | val entries = p(NTLBEntries) 16 | val camAddrBits = log2Ceil(entries) 17 | val camTagBits = asIdBits + vpnBits 18 | } 19 | 20 | class TLBReq(implicit p: Parameters) extends CoreBundle()(p) { 21 | val asid = UInt(width = asIdBits) 22 | val vpn = UInt(width = vpnBitsExtended) 23 | val passthrough = Bool() 24 | val instruction = Bool() 25 | val store = Bool() 26 | } 27 | 28 | class TLBResp(implicit p: Parameters) extends CoreBundle()(p) { 29 | // lookup responses 30 | val miss = Bool(OUTPUT) 31 | val ppn = UInt(OUTPUT, ppnBits) 32 | val xcpt_ld = Bool(OUTPUT) 33 | val xcpt_st = Bool(OUTPUT) 34 | val xcpt_if = Bool(OUTPUT) 35 | } 36 | 37 | class TLB(implicit val p: Parameters) extends Module with HasTLBParameters { 38 | val io = new Bundle { 39 | val req = Decoupled(new TLBReq).flip 40 | val resp = new TLBResp 41 | val ptw = new TLBPTWIO 42 | } 43 | 44 | val valid = Reg(init = UInt(0, entries)) 45 | val ppns = Reg(Vec(entries, io.ptw.resp.bits.pte.ppn)) 46 | val tags = Reg(Vec(entries, UInt(width = asIdBits + vpnBits))) 47 | 48 | val s_ready :: s_request :: s_wait :: s_wait_invalidate :: Nil = Enum(UInt(), 4) 49 | val state = Reg(init=s_ready) 50 | val r_refill_tag = Reg(UInt(width = asIdBits + vpnBits)) 51 | val r_refill_waddr = Reg(UInt(width = log2Ceil(entries))) 52 | val r_req = Reg(new TLBReq) 53 | 54 | val lookup_tag = Cat(io.req.bits.asid, io.req.bits.vpn).toUInt 55 | val hitsVec = (0 until entries).map(i => valid(i) && tags(i) === lookup_tag) 56 | val hits = hitsVec.toBits 57 | 58 | // permission bit arrays 59 | val pte_array = Reg(new PTE) 60 | val u_array = Reg(UInt(width = entries)) // user permission 61 | val sw_array = Reg(UInt(width = entries)) // write permission 62 | val sx_array = Reg(UInt(width = entries)) // execute permission 63 | val sr_array = Reg(UInt(width = entries)) // read permission 64 | val dirty_array = Reg(UInt(width = entries)) // PTE dirty bit 65 | when (io.ptw.resp.valid) { 66 | val pte = io.ptw.resp.bits.pte 67 | ppns(r_refill_waddr) := pte.ppn 68 | tags(r_refill_waddr) := r_refill_tag 69 | 70 | val mask = UIntToOH(r_refill_waddr) 71 | valid := valid | mask 72 | u_array := Mux(pte.u, u_array | mask, u_array & ~mask) 73 | sr_array := Mux(pte.sr(), sr_array | mask, sr_array & ~mask) 74 | sw_array := Mux(pte.sw(), sw_array | mask, sw_array & ~mask) 75 | sx_array := Mux(pte.sx(), sx_array | mask, sx_array & ~mask) 76 | dirty_array := Mux(pte.d, dirty_array | mask, dirty_array & ~mask) 77 | } 78 | 79 | // high if there are any unused (invalid) entries in the TLB 80 | val plru = new PseudoLRU(entries) 81 | val repl_waddr = Mux(!valid.andR, PriorityEncoder(~valid), plru.replace) 82 | 83 | val do_mprv = io.ptw.status.mprv && !io.req.bits.instruction 84 | val priv = Mux(do_mprv, io.ptw.status.mpp, io.ptw.status.prv) 85 | val priv_s = priv === PRV.S 86 | val priv_uses_vm = priv <= PRV.S 87 | 88 | val priv_ok = Mux(priv_s, ~Mux(io.ptw.status.pum, u_array, UInt(0)), u_array) 89 | val w_array = priv_ok & sw_array 90 | val x_array = priv_ok & sx_array 91 | val r_array = priv_ok & (sr_array | Mux(io.ptw.status.mxr, x_array, UInt(0))) 92 | 93 | val vm_enabled = Bool(usingVM) && io.ptw.status.vm(3) && priv_uses_vm && !io.req.bits.passthrough 94 | val bad_va = 95 | if (vpnBits == vpnBitsExtended) Bool(false) 96 | else io.req.bits.vpn(vpnBits) =/= io.req.bits.vpn(vpnBits-1) 97 | // it's only a store hit if the dirty bit is set 98 | val tag_hits = hits & (dirty_array | ~Mux(io.req.bits.store, w_array, UInt(0))) 99 | val tag_hit = tag_hits.orR 100 | val tlb_hit = vm_enabled && tag_hit 101 | val tlb_miss = vm_enabled && !tag_hit && !bad_va 102 | 103 | when (io.req.valid && tlb_hit) { 104 | plru.access(OHToUInt(hits)) 105 | } 106 | 107 | val paddr = Cat(io.resp.ppn, UInt(0, pgIdxBits)) 108 | val addr_prot = addrMap.getProt(paddr) 109 | 110 | io.req.ready := state === s_ready 111 | io.resp.xcpt_ld := bad_va || (!tlb_miss && !addr_prot.r) || (tlb_hit && !(r_array & hits).orR) 112 | io.resp.xcpt_st := bad_va || (!tlb_miss && !addr_prot.w) || (tlb_hit && !(w_array & hits).orR) 113 | io.resp.xcpt_if := bad_va || (!tlb_miss && !addr_prot.x) || (tlb_hit && !(x_array & hits).orR) 114 | io.resp.miss := tlb_miss 115 | io.resp.ppn := Mux(vm_enabled, Mux1H(hitsVec, ppns), io.req.bits.vpn(ppnBits-1,0)) 116 | 117 | io.ptw.req.valid := state === s_request 118 | io.ptw.req.bits := io.ptw.status 119 | io.ptw.req.bits.addr := r_refill_tag 120 | io.ptw.req.bits.store := r_req.store 121 | io.ptw.req.bits.fetch := r_req.instruction 122 | 123 | if (usingVM) { 124 | when (io.req.fire() && tlb_miss) { 125 | state := s_request 126 | r_refill_tag := lookup_tag 127 | r_refill_waddr := repl_waddr 128 | r_req := io.req.bits 129 | } 130 | when (state === s_request) { 131 | when (io.ptw.invalidate) { 132 | state := s_ready 133 | } 134 | when (io.ptw.req.ready) { 135 | state := s_wait 136 | when (io.ptw.invalidate) { state := s_wait_invalidate } 137 | } 138 | } 139 | when (state === s_wait && io.ptw.invalidate) { 140 | state := s_wait_invalidate 141 | } 142 | when (io.ptw.resp.valid) { 143 | state := s_ready 144 | } 145 | 146 | when (io.ptw.invalidate) { 147 | valid := 0 148 | } 149 | } 150 | } 151 | 152 | class DecoupledTLB(implicit p: Parameters) extends Module { 153 | val io = new Bundle { 154 | val req = Decoupled(new TLBReq).flip 155 | val resp = Decoupled(new TLBResp) 156 | val ptw = new TLBPTWIO 157 | } 158 | 159 | val reqq = Queue(io.req) 160 | val tlb = Module(new TLB) 161 | 162 | val resp_helper = DecoupledHelper( 163 | reqq.valid, tlb.io.req.ready, io.resp.ready) 164 | val tlb_miss = tlb.io.resp.miss 165 | 166 | tlb.io.req.valid := resp_helper.fire(tlb.io.req.ready) 167 | tlb.io.req.bits := reqq.bits 168 | reqq.ready := resp_helper.fire(reqq.valid, !tlb_miss) 169 | 170 | io.resp.valid := resp_helper.fire(io.resp.ready, !tlb_miss) 171 | io.resp.bits := tlb.io.resp 172 | 173 | io.ptw <> tlb.io.ptw 174 | } 175 | -------------------------------------------------------------------------------- /src/main/scala/util.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package rocket 4 | 5 | import Chisel._ 6 | import uncore._ 7 | import scala.math._ 8 | import cde.{Parameters, Field} 9 | 10 | object Util { 11 | implicit def intToUInt(x: Int): UInt = UInt(x) 12 | implicit def booleanToBool(x: Boolean): Bits = Bool(x) 13 | implicit def intSeqToUIntSeq(x: Seq[Int]): Seq[UInt] = x.map(UInt(_)) 14 | implicit def seqToVec[T <: Data](x: Seq[T]): Vec[T] = Vec(x) 15 | implicit def wcToUInt(c: WideCounter): UInt = c.value 16 | implicit def sextToConv(x: UInt) = new AnyRef { 17 | def sextTo(n: Int): UInt = 18 | if (x.getWidth == n) x 19 | else Cat(Fill(n - x.getWidth, x(x.getWidth-1)), x) 20 | } 21 | 22 | implicit def intToUnsigned(x: Int): Unsigned = new Unsigned(x) 23 | implicit def booleanToIntConv(x: Boolean) = new AnyRef { 24 | def toInt: Int = if (x) 1 else 0 25 | } 26 | 27 | def minUInt(values: Seq[UInt]): UInt = 28 | values.reduce((a, b) => Mux(a < b, a, b)) 29 | 30 | def minUInt(first: UInt, rest: UInt*): UInt = 31 | minUInt(first +: rest.toSeq) 32 | } 33 | 34 | import Util._ 35 | 36 | object Str 37 | { 38 | def apply(s: String): UInt = { 39 | var i = BigInt(0) 40 | require(s.forall(validChar _)) 41 | for (c <- s) 42 | i = (i << 8) | c 43 | UInt(i, s.length*8) 44 | } 45 | def apply(x: Char): UInt = { 46 | require(validChar(x)) 47 | UInt(x.toInt, 8) 48 | } 49 | def apply(x: UInt): UInt = apply(x, 10) 50 | def apply(x: UInt, radix: Int): UInt = { 51 | val rad = UInt(radix) 52 | val w = x.getWidth 53 | require(w > 0) 54 | 55 | var q = x 56 | var s = digit(q % rad) 57 | for (i <- 1 until ceil(log(2)/log(radix)*w).toInt) { 58 | q = q / rad 59 | s = Cat(Mux(Bool(radix == 10) && q === UInt(0), Str(' '), digit(q % rad)), s) 60 | } 61 | s 62 | } 63 | def apply(x: SInt): UInt = apply(x, 10) 64 | def apply(x: SInt, radix: Int): UInt = { 65 | val neg = x < SInt(0) 66 | val abs = x.abs 67 | if (radix != 10) { 68 | Cat(Mux(neg, Str('-'), Str(' ')), Str(abs, radix)) 69 | } else { 70 | val rad = UInt(radix) 71 | val w = abs.getWidth 72 | require(w > 0) 73 | 74 | var q = abs 75 | var s = digit(q % rad) 76 | var needSign = neg 77 | for (i <- 1 until ceil(log(2)/log(radix)*w).toInt) { 78 | q = q / rad 79 | val placeSpace = q === UInt(0) 80 | val space = Mux(needSign, Str('-'), Str(' ')) 81 | needSign = needSign && !placeSpace 82 | s = Cat(Mux(placeSpace, space, digit(q % rad)), s) 83 | } 84 | Cat(Mux(needSign, Str('-'), Str(' ')), s) 85 | } 86 | } 87 | 88 | private def digit(d: UInt): UInt = Mux(d < UInt(10), Str('0')+d, Str(('a'-10).toChar)+d)(7,0) 89 | private def validChar(x: Char) = x == (x & 0xFF) 90 | } 91 | 92 | object Split 93 | { 94 | // is there a better way to do do this? 95 | def apply(x: Bits, n0: Int) = { 96 | val w = checkWidth(x, n0) 97 | (x(w-1,n0), x(n0-1,0)) 98 | } 99 | def apply(x: Bits, n1: Int, n0: Int) = { 100 | val w = checkWidth(x, n1, n0) 101 | (x(w-1,n1), x(n1-1,n0), x(n0-1,0)) 102 | } 103 | def apply(x: Bits, n2: Int, n1: Int, n0: Int) = { 104 | val w = checkWidth(x, n2, n1, n0) 105 | (x(w-1,n2), x(n2-1,n1), x(n1-1,n0), x(n0-1,0)) 106 | } 107 | 108 | private def checkWidth(x: Bits, n: Int*) = { 109 | val w = x.getWidth 110 | def decreasing(x: Seq[Int]): Boolean = 111 | if (x.tail.isEmpty) true 112 | else x.head >= x.tail.head && decreasing(x.tail) 113 | require(decreasing(w :: n.toList)) 114 | w 115 | } 116 | } 117 | 118 | // a counter that clock gates most of its MSBs using the LSB carry-out 119 | case class WideCounter(width: Int, inc: UInt = UInt(1)) 120 | { 121 | require(inc.getWidth > 0) 122 | private val isWide = width > 2*inc.getWidth 123 | private val smallWidth = if (isWide) inc.getWidth max log2Up(width) else width 124 | private val small = Reg(init=UInt(0, smallWidth)) 125 | private val doInc = inc.orR 126 | private val nextSmall = 127 | if (inc.getWidth == 1) small + UInt(1, smallWidth+1) 128 | else Cat(UInt(0,1), small) + inc 129 | when (doInc) { small := nextSmall(smallWidth-1,0) } 130 | 131 | private val large = if (isWide) { 132 | val r = Reg(init=UInt(0, width - smallWidth)) 133 | when (doInc && nextSmall(smallWidth)) { r := r + UInt(1) } 134 | r 135 | } else null 136 | 137 | val value = Cat(large, small) 138 | 139 | def := (x: UInt) = { 140 | val w = x.getWidth 141 | small := x(w.min(smallWidth)-1,0) 142 | if (isWide) large := (if (w < smallWidth) UInt(0) else x(w.min(width)-1,smallWidth)) 143 | } 144 | } 145 | 146 | object Random 147 | { 148 | def apply(mod: Int, random: UInt): UInt = { 149 | if (isPow2(mod)) random(log2Up(mod)-1,0) 150 | else PriorityEncoder(partition(apply(1 << log2Up(mod*8), random), mod)) 151 | } 152 | def apply(mod: Int): UInt = apply(mod, randomizer) 153 | def oneHot(mod: Int, random: UInt): UInt = { 154 | if (isPow2(mod)) UIntToOH(random(log2Up(mod)-1,0)) 155 | else PriorityEncoderOH(partition(apply(1 << log2Up(mod*8), random), mod)).toBits 156 | } 157 | def oneHot(mod: Int): UInt = oneHot(mod, randomizer) 158 | 159 | private def randomizer = LFSR16() 160 | private def round(x: Double): Int = 161 | if (x.toInt.toDouble == x) x.toInt else (x.toInt + 1) & -2 162 | private def partition(value: UInt, slices: Int) = 163 | Seq.tabulate(slices)(i => value < round((i << value.getWidth).toDouble / slices)) 164 | } 165 | --------------------------------------------------------------------------------