1
0
rocket-chip/src/main/scala/rocket/IBuf.scala

144 lines
6.1 KiB
Scala
Raw Normal View History

// See LICENSE.SiFive for license details.
2016-07-30 01:36:07 +02:00
package rocket
import Chisel._
import Chisel.ImplicitConversions._
import config._
Heterogeneous Tiles (#550) Fundamental new features: * Added tile package: This package is intended to hold components re-usable across different types of tile. Will be the future location of TL2-RoCC accelerators and new diplomatic versions of intra-tile interfaces. * Adopted [ModuleName]Params convention: Code base was very inconsistent about what to name case classes that provide parameters to modules. Settled on calling them [ModuleName]Params to distinguish them from config.Parameters and config.Config. So far applied mostly only to case classes defined within rocket and tile. * Defined RocketTileParams: A nested case class containing case classes for all the components of a tile (L1 caches and core). Allows all such parameters to vary per-tile. * Defined RocketCoreParams: All the parameters that can be varied per-core. * Defined L1CacheParams: A trait defining the parameters common to L1 caches, made concrete in different derived case classes. * Defined RocketTilesKey: A sequence of RocketTileParams, one for every tile to be created. * Provided HeterogeneousDualCoreConfig: An example of making a heterogeneous chip with two cores, one big and one little. * Changes to legacy code: ReplacementPolicy moved to package util. L1Metadata moved to package tile. Legacy L2 cache agent removed because it can no longer share the metadata array implementation with the L1. Legacy GroundTests on life support. Additional changes that got rolled in along the way: * rocket: Fix critical path through BTB for I$ index bits > pgIdxBits * coreplex: tiles connected via :=* * groundtest: updated to use TileParams * tilelink: cache cork requirements are relaxed to allow more cacheless masters
2017-02-09 22:59:09 +01:00
import tile._
import util._
2016-07-30 01:36:07 +02:00
class Instruction(implicit val p: Parameters) extends ParameterizedBundle with HasCoreParameters {
val pf0 = Bool() // page fault on first half of instruction
val pf1 = Bool() // page fault on second half of instruction
val ae0 = Bool() // access exception on first half of instruction
val ae1 = Bool() // access exception on second half of instruction
2016-07-30 01:36:07 +02:00
val replay = Bool()
val btb_hit = Bool()
val rvc = Bool()
val inst = new ExpandedInstruction
val raw = UInt(width = 32)
2016-07-30 01:36:07 +02:00
require(coreInstBits == (if (usingCompressed) 16 else 32))
}
class IBuf(implicit p: Parameters) extends CoreModule {
val io = new Bundle {
val imem = Decoupled(new FrontendResp).flip
val kill = Bool(INPUT)
val pc = UInt(OUTPUT, vaddrBitsExtended)
2016-07-30 01:36:07 +02:00
val btb_resp = new BTBResp().asOutput
val inst = Vec(retireWidth, Decoupled(new Instruction))
}
// This module is meant to be more general, but it's not there yet
2016-08-02 23:52:55 +02:00
require(decodeWidth == 1)
2016-07-30 01:36:07 +02:00
val n = fetchWidth - 1
val nBufValid = if (n == 0) UInt(0) else Reg(init=UInt(0, log2Ceil(fetchWidth)))
val buf = Reg(io.imem.bits)
val ibufBTBHit = Reg(Bool())
val ibufBTBResp = Reg(new BTBResp)
val pcWordMask = UInt(coreInstBytes*fetchWidth-1, vaddrBitsExtended)
val pcWordBits = io.imem.bits.pc.extract(log2Ceil(fetchWidth*coreInstBytes)-1, log2Ceil(coreInstBytes))
val nReady = Wire(init = UInt(0, log2Ceil(fetchWidth+1)))
val nIC = Mux(io.imem.bits.btb.valid && io.imem.bits.btb.bits.taken, io.imem.bits.btb.bits.bridx +& 1, UInt(fetchWidth)) - pcWordBits
val nICReady = nReady - nBufValid
val nValid = Mux(io.imem.valid, nIC, UInt(0)) + nBufValid
io.imem.ready := nReady >= nBufValid && (nICReady >= nIC || n >= nIC - nICReady)
if (n > 0) {
nBufValid := Mux(nReady >= nBufValid, UInt(0), nBufValid - nReady)
if (n > 1) when (nReady > 0 && nReady < nBufValid) {
val shiftedBuf = shiftInsnRight(buf.data(n*coreInstBits-1, coreInstBits), (nReady-1)(log2Ceil(n-1)-1,0))
buf.data := Cat(buf.data(n*coreInstBits-1, (n-1)*coreInstBits), shiftedBuf((n-1)*coreInstBits-1, 0))
buf.pc := buf.pc & ~pcWordMask | (buf.pc + (nReady << log2Ceil(coreInstBytes))) & pcWordMask
ibufBTBResp.bridx := ibufBTBResp.bridx - nReady
}
when (io.imem.valid && nReady >= nBufValid && nICReady < nIC && n >= nIC - nICReady) {
val shamt = pcWordBits + nICReady
nBufValid := nIC - nICReady
buf := io.imem.bits
buf.data := shiftInsnRight(io.imem.bits.data, shamt)(n*coreInstBits-1,0)
buf.pc := io.imem.bits.pc & ~pcWordMask | (io.imem.bits.pc + (nICReady << log2Ceil(coreInstBytes))) & pcWordMask
ibufBTBHit := io.imem.bits.btb.valid
when (io.imem.bits.btb.valid) {
ibufBTBResp := io.imem.bits.btb.bits
ibufBTBResp.bridx := io.imem.bits.btb.bits.bridx + nICReady
}
}
when (io.kill) {
nBufValid := 0
}
}
val icShiftAmt = (fetchWidth + nBufValid - pcWordBits)(log2Ceil(fetchWidth), 0)
val icData = shiftInsnLeft(Cat(io.imem.bits.data, Fill(fetchWidth, io.imem.bits.data(coreInstBits-1, 0))), icShiftAmt)
.extract(3*fetchWidth*coreInstBits-1, 2*fetchWidth*coreInstBits)
val icMask = (~UInt(0, fetchWidth*coreInstBits) << (nBufValid << log2Ceil(coreInstBits)))(fetchWidth*coreInstBits-1,0)
val inst = icData & icMask | buf.data & ~icMask
val valid = (UIntToOH(nValid) - 1)(fetchWidth-1, 0)
val bufMask = UIntToOH(nBufValid) - 1
val pf = valid & (Mux(buf.pf, bufMask, UInt(0)) | Mux(io.imem.bits.pf, ~bufMask, UInt(0)))
val ae = valid & (Mux(buf.ae, bufMask, UInt(0)) | Mux(io.imem.bits.ae, ~bufMask, UInt(0)))
2016-07-30 01:36:07 +02:00
val ic_replay = valid & (Mux(buf.replay, bufMask, UInt(0)) | Mux(io.imem.bits.replay, ~bufMask, UInt(0)))
val ibufBTBHitMask = Mux(ibufBTBHit, UIntToOH(ibufBTBResp.bridx), UInt(0))
assert(!io.imem.bits.btb.valid || io.imem.bits.btb.bits.bridx >= pcWordBits)
2016-07-30 01:36:07 +02:00
val icBTBHitMask = Mux(io.imem.bits.btb.valid, UIntToOH(io.imem.bits.btb.bits.bridx +& nBufValid - pcWordBits), UInt(0))
val btbHitMask = ibufBTBHitMask & bufMask | icBTBHitMask & ~bufMask
io.btb_resp := Mux((ibufBTBHitMask & bufMask).orR, ibufBTBResp, io.imem.bits.btb.bits)
io.pc := Mux(nBufValid > 0, buf.pc, io.imem.bits.pc)
expand(0, 0, inst)
def expand(i: Int, j: UInt, curInst: UInt): Unit = if (i < retireWidth) {
val exp = Module(new RVCExpander)
exp.io.in := curInst
io.inst(i).bits.inst := exp.io.out
io.inst(i).bits.raw := curInst
2016-07-30 01:36:07 +02:00
if (usingCompressed) {
val replay = ic_replay(j) || (!exp.io.rvc && (btbHitMask(j) || ic_replay(j+1)))
io.inst(i).valid := valid(j) && (exp.io.rvc || valid(j+1) || pf(j+1) || ae(j+1) || replay)
io.inst(i).bits.pf0 := pf(j)
io.inst(i).bits.pf1 := !exp.io.rvc && pf(j+1)
io.inst(i).bits.ae0 := ae(j)
io.inst(i).bits.ae1 := !exp.io.rvc && ae(j+1)
2016-07-30 01:36:07 +02:00
io.inst(i).bits.replay := replay
io.inst(i).bits.btb_hit := btbHitMask(j) || (!exp.io.rvc && btbHitMask(j+1))
io.inst(i).bits.rvc := exp.io.rvc
when (io.inst(i).fire()) { nReady := Mux(exp.io.rvc, j+1, j+2) }
expand(i+1, Mux(exp.io.rvc, j+1, j+2), Mux(exp.io.rvc, curInst >> 16, curInst >> 32))
} else {
when (io.inst(i).ready) { nReady := i+1 }
io.inst(i).valid := valid(i)
io.inst(i).bits.pf0 := pf(i)
2016-07-30 01:36:07 +02:00
io.inst(i).bits.pf1 := false
io.inst(i).bits.ae0 := ae(i)
io.inst(i).bits.ae1 := false
2016-07-30 01:36:07 +02:00
io.inst(i).bits.replay := ic_replay(i)
io.inst(i).bits.rvc := false
io.inst(i).bits.btb_hit := btbHitMask(i)
expand(i+1, null, curInst >> 32)
}
}
def shiftInsnLeft(in: UInt, dist: UInt) = {
val r = in.getWidth/coreInstBits
require(in.getWidth % coreInstBits == 0)
val data = Cat(Fill((1 << (log2Ceil(r) + 1)) - r, in >> (r-1)*coreInstBits), in)
data << (dist << log2Ceil(coreInstBits))
}
def shiftInsnRight(in: UInt, dist: UInt) = {
val r = in.getWidth/coreInstBits
require(in.getWidth % coreInstBits == 0)
val data = Cat(Fill((1 << (log2Ceil(r) + 1)) - r, in >> (r-1)*coreInstBits), in)
data >> (dist << log2Ceil(coreInstBits))
}
}