├── .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 |
--------------------------------------------------------------------------------