1
0

Merge pull request #1034 from freechipsproject/base-tile

Generalize Tile/Coreplex hierarchy
This commit is contained in:
Andrew Waterman 2017-10-09 11:42:20 -07:00 committed by GitHub
commit d78ad857ee
11 changed files with 106 additions and 86 deletions

View File

@ -6,6 +6,9 @@ import Chisel._
import freechips.rocketchip.config.Parameters
import freechips.rocketchip.diplomacy._
import freechips.rocketchip.tilelink._
import freechips.rocketchip.devices.tilelink._
import freechips.rocketchip.tile.{BaseTile, TileParams, SharedMemoryTLEdge, HasExternallyDrivenTileConstants}
import freechips.rocketchip.devices.debug.{HasPeripheryDebug, HasPeripheryDebugModuleImp}
import freechips.rocketchip.util._
/** Enumerates the three types of clock crossing between tiles and system bus */
@ -29,6 +32,21 @@ abstract class BareCoreplexModule[+L <: BareCoreplex](_outer: L) extends LazyMod
println(outer.dts)
}
trait HasTiles extends HasSystemBus {
protected def tileParams: Seq[TileParams]
def nRocketTiles = tileParams.size
def hartIdList = tileParams.map(_.hartid)
// Handle interrupts to be routed directly into each tile
// TODO: figure out how to merge the localIntNodes and coreIntXbar
def localIntCounts = tileParams.map(_.core.nLocalInterrupts)
def localIntNodes = tileParams map { t =>
(t.core.nLocalInterrupts > 0).option(LazyModule(new IntXbar).intnode)
}
val tiles: Seq[BaseTile]
}
/** Base Coreplex class with no peripheral devices or ports added */
abstract class BaseCoreplex(implicit p: Parameters) extends BareCoreplex
with HasInterruptBus
@ -87,6 +105,46 @@ abstract class BaseCoreplex(implicit p: Parameters) extends BareCoreplex
}
}
class ClockedTileInputs(implicit val p: Parameters) extends ParameterizedBundle
with HasExternallyDrivenTileConstants
with Clocked
trait HasTilesBundle {
val tile_inputs: Vec[ClockedTileInputs]
}
trait HasTilesModuleImp extends LazyModuleImp
with HasTilesBundle
with HasResetVectorWire {
val outer: HasTiles
def resetVectorBits: Int = {
// Consider using the minimum over all widths, rather than enforcing homogeneity
val vectors = outer.tiles.map(_.module.io.reset_vector)
require(vectors.tail.forall(_.getWidth == vectors.head.getWidth))
vectors.head.getWidth
}
val tile_inputs = Wire(Vec(outer.nRocketTiles, new ClockedTileInputs()(p.alterPartial {
case SharedMemoryTLEdge => outer.sharedMemoryTLEdge
})))
// Unconditionally wire up the non-diplomatic tile inputs
outer.tiles.map(_.module).zip(tile_inputs).foreach { case(tile, wire) =>
tile.clock := wire.clock
tile.reset := wire.reset
tile.io.hartid := wire.hartid
tile.io.reset_vector := wire.reset_vector
}
// Default values for tile inputs; may be overriden in other traits
tile_inputs.zip(outer.hartIdList).foreach { case(wire, i) =>
wire.clock := clock
wire.reset := reset
wire.hartid := UInt(i)
wire.reset_vector := global_reset_vector
}
}
abstract class BaseCoreplexModule[+L <: BaseCoreplex](_outer: L) extends BareCoreplexModule(_outer) {
println("Generated Address Map")
private val aw = (outer.sharedMemoryTLEdge.bundle.addressBits-1)/4 + 1

View File

@ -14,7 +14,7 @@ import freechips.rocketchip.util._
case object RocketTilesKey extends Field[Seq[RocketTileParams]](Nil)
case object RocketCrossing extends Field[CoreplexClockCrossing](SynchronousCrossing())
trait HasRocketTiles extends HasSystemBus
trait HasRocketTiles extends HasTiles
with HasPeripheryBus
with HasPeripheryPLIC
with HasPeripheryClint
@ -22,21 +22,11 @@ trait HasRocketTiles extends HasSystemBus
val module: HasRocketTilesModuleImp
private val crossing = p(RocketCrossing)
private val tileParams = p(RocketTilesKey)
val nRocketTiles = tileParams.size
val hartIdList = tileParams.map(_.hartid)
// Handle interrupts to be routed directly into each tile
// TODO: figure out how to merge the localIntNodes and coreIntXbar below
val localIntCounts = tileParams.map(_.core.nLocalInterrupts)
val localIntNodes = tileParams map { t =>
(t.core.nLocalInterrupts > 0).option(LazyModule(new IntXbar).intnode)
}
protected val tileParams = p(RocketTilesKey)
// Make a wrapper for each tile that will wire it to coreplex devices and crossbars,
// according to the specified type of clock crossing.
val wiringTuple = localIntNodes.zip(tileParams)
val rocket_tiles: Seq[RocketTileWrapper] = wiringTuple.map { case (lip, tp) =>
val tiles: Seq[BaseTile] = localIntNodes.zip(tileParams).map { case (lip, tp) =>
val pWithExtra = p.alterPartial {
case TileKey => tp
case BuildRoCC => tp.rocc
@ -95,45 +85,9 @@ trait HasRocketTiles extends HasSystemBus
}
}
class ClockedRocketTileInputs(implicit val p: Parameters) extends ParameterizedBundle
with HasExternallyDrivenTileConstants
with Clocked
trait HasRocketTilesBundle {
val rocket_tile_inputs: Vec[ClockedRocketTileInputs]
}
trait HasRocketTilesModuleImp extends LazyModuleImp
with HasRocketTilesBundle
with HasResetVectorWire
trait HasRocketTilesModuleImp extends HasTilesModuleImp
with HasPeripheryDebugModuleImp {
val outer: HasRocketTiles
def resetVectorBits: Int = {
// Consider using the minimum over all widths, rather than enforcing homogeneity
val vectors = outer.rocket_tiles.map(_.module.io.reset_vector)
require(vectors.tail.forall(_.getWidth == vectors.head.getWidth))
vectors.head.getWidth
}
val rocket_tile_inputs = Wire(Vec(outer.nRocketTiles, new ClockedRocketTileInputs()(p.alterPartial {
case SharedMemoryTLEdge => outer.sharedMemoryTLEdge
})))
// Unconditionally wire up the non-diplomatic tile inputs
outer.rocket_tiles.map(_.module).zip(rocket_tile_inputs).foreach { case(tile, wire) =>
tile.clock := wire.clock
tile.reset := wire.reset
tile.io.hartid := wire.hartid
tile.io.reset_vector := wire.reset_vector
}
// Default values for tile inputs; may be overriden in other traits
rocket_tile_inputs.zip(outer.hartIdList).foreach { case(wire, i) =>
wire.clock := clock
wire.reset := reset
wire.hartid := UInt(i)
wire.reset_vector := global_reset_vector
}
}
class RocketCoreplex(implicit p: Parameters) extends BaseCoreplex

View File

@ -25,7 +25,7 @@ class GroundTestCoreplex(implicit p: Parameters) extends BaseCoreplex
})
)}
tiles.foreach { sbus.fromSyncTiles(BufferParams.default) :=* _.masterNode }
tiles.flatMap(_.dcacheOpt).foreach { sbus.fromSyncTiles(BufferParams.default) :=* _.node }
val pbusRAM = LazyModule(new TLRAM(AddressSet(testRamAddr, 0xffff), false, pbus.beatBytes))
pbusRAM.node := pbus.toVariableWidthSlaves

View File

@ -31,13 +31,13 @@ case object GroundTestTilesKey extends Field[Seq[GroundTestTileParams]]
abstract class GroundTestTile(params: GroundTestTileParams)(implicit p: Parameters) extends BaseTile(params)(p) {
val slave = None
val dcacheOpt = params.dcache.map { dc => LazyModule(HellaCache(0, dc.nMSHRs == 0)) }
dcacheOpt.foreach { tileBus.node := _.node }
override lazy val module = new GroundTestTileModule(this, () => new GroundTestTileBundle(this))
}
class GroundTestTileBundle[+L <: GroundTestTile](_outer: L) extends BaseTileBundle(_outer) {
val status = new GroundTestStatus
val halt_and_catch_fire = None
}
class GroundTestTileModule[+L <: GroundTestTile, +B <: GroundTestTileBundle[L]](_outer: L, _io: () => B) extends BaseTileModule(_outer, _io) {

View File

@ -65,6 +65,7 @@ case class TraceGenParams(
memStart: BigInt, //p(ExtMem).base
numGens: Int) extends GroundTestTileParams {
def build(i: Int, p: Parameters): GroundTestTile = new TraceGenTile(i, this)(p)
val hartid = 0
val trace = false
}

View File

@ -38,7 +38,7 @@ object ALU
def isMulFN(fn: UInt, cmp: UInt) = fn(1,0) === cmp(1,0)
def isSub(cmd: UInt) = cmd(3)
def isCmp(cmd: UInt) = cmd === FN_SEQ || cmd === FN_SNE || cmd >= FN_SLT
def isCmp(cmd: UInt) = cmd >= FN_SLT
def cmpUnsigned(cmd: UInt) = cmd(1)
def cmpInverted(cmd: UInt) = cmd(0)
def cmpEq(cmd: UInt) = !cmd(3)
@ -64,10 +64,10 @@ class ALU(implicit p: Parameters) extends CoreModule()(p) {
io.adder_out := io.in1 + in2_inv + isSub(io.fn)
// SLT, SLTU
io.cmp_out := cmpInverted(io.fn) ^
Mux(cmpEq(io.fn), in1_xor_in2 === UInt(0),
val slt =
Mux(io.in1(xLen-1) === io.in2(xLen-1), io.adder_out(xLen-1),
Mux(cmpUnsigned(io.fn), io.in2(xLen-1), io.in1(xLen-1))))
Mux(cmpUnsigned(io.fn), io.in2(xLen-1), io.in1(xLen-1)))
io.cmp_out := cmpInverted(io.fn) ^ Mux(cmpEq(io.fn), in1_xor_in2 === UInt(0), slt)
// SLL, SRL, SRA
val (shamt, shin_r) =
@ -88,7 +88,7 @@ class ALU(implicit p: Parameters) extends CoreModule()(p) {
// AND, OR, XOR
val logic = Mux(io.fn === FN_XOR || io.fn === FN_OR, in1_xor_in2, UInt(0)) |
Mux(io.fn === FN_OR || io.fn === FN_AND, io.in1 & io.in2, UInt(0))
val shift_logic = (isCmp(io.fn) && io.cmp_out) | logic | shout
val shift_logic = (isCmp(io.fn) && slt) | logic | shout
val out = Mux(io.fn === FN_ADD || io.fn === FN_SUB, io.adder_out, shift_logic)
io.out := out

View File

@ -85,9 +85,6 @@ class PTW(n: Int)(implicit edge: TLEdgeOut, p: Parameters) extends CoreModule()(
val r_req_dest = Reg(Bits())
val r_pte = Reg(new PTE)
val vpn_idxs = (0 until pgLevels).map(i => (r_req.addr >> (pgLevels-i-1)*pgLevelBits)(pgLevelBits-1,0))
val vpn_idx = vpn_idxs(count)
val arb = Module(new RRArbiter(new PTWReq, n))
arb.io.in <> io.requestor.map(_.req)
arb.io.out.ready := state === s_ready
@ -104,7 +101,11 @@ class PTW(n: Int)(implicit edge: TLEdgeOut, p: Parameters) extends CoreModule()(
(res, (tmp.ppn >> ppnBits) =/= 0)
}
val traverse = pte.table() && !invalid_paddr && count < pgLevels-1
val pte_addr = Cat(r_pte.ppn, vpn_idx) << log2Ceil(xLen/8)
val pte_addr = if (!usingVM) 0.U else {
val vpn_idxs = (0 until pgLevels).map(i => (r_req.addr >> (pgLevels-i-1)*pgLevelBits)(pgLevelBits-1,0))
val vpn_idx = vpn_idxs(count)
Cat(r_pte.ppn, vpn_idx) << log2Ceil(xLen/8)
}
when (arb.io.out.fire()) {
r_req := arb.io.out.bits

View File

@ -152,6 +152,7 @@ class Rocket(implicit p: Parameters) extends CoreModule()(p)
val mem_reg_raw_inst = Reg(UInt())
val mem_reg_wdata = Reg(Bits())
val mem_reg_rs2 = Reg(Bits())
val mem_br_taken = Reg(Bool())
val take_pc_mem = Wire(Bool())
val wb_reg_valid = Reg(Bool())
@ -361,7 +362,6 @@ class Rocket(implicit p: Parameters) extends CoreModule()(p)
// memory stage
val mem_pc_valid = mem_reg_valid || mem_reg_replay || mem_reg_xcpt_interrupt
val mem_br_taken = mem_reg_wdata(0)
val mem_br_target = mem_reg_pc.asSInt +
Mux(mem_ctrl.branch && mem_br_taken, ImmGen(IMM_SB, mem_reg_inst),
Mux(mem_ctrl.jal, ImmGen(IMM_UJ, mem_reg_inst),
@ -403,6 +403,7 @@ class Rocket(implicit p: Parameters) extends CoreModule()(p)
mem_reg_raw_inst := ex_reg_raw_inst
mem_reg_pc := ex_reg_pc
mem_reg_wdata := alu.io.out
mem_br_taken := alu.io.cmp_out
when (ex_ctrl.rxs2 && (ex_ctrl.mem || ex_ctrl.rocc || ex_sfence)) {
val typ = Mux(ex_ctrl.rocc, log2Ceil(xLen/8).U, ex_ctrl.mem_type)

View File

@ -97,7 +97,7 @@ class TLB(instruction: Boolean, lgMaxSize: Int, nEntries: Int)(implicit edge: TL
val vm_enabled = Bool(usingVM) && io.ptw.ptbr.mode(io.ptw.ptbr.mode.getWidth-1) && priv_uses_vm && !io.req.bits.passthrough
// share a single physical memory attribute checker (unshare if critical path)
val (vpn, pgOffset) = Split(io.req.bits.vaddr, pgIdxBits)
val vpn = io.req.bits.vaddr(vaddrBits-1, pgIdxBits)
val refill_ppn = io.ptw.resp.bits.pte.ppn(ppnBits-1, 0)
val do_refill = Bool(usingVM) && io.ptw.resp.valid
val invalidate_refill = state.isOneOf(s_request /* don't care */, s_wait_invalidate)
@ -121,8 +121,8 @@ class TLB(instruction: Boolean, lgMaxSize: Int, nEntries: Int)(implicit edge: TL
val prot_x = fastCheck(_.executable) && pmp.io.x
val prot_eff = fastCheck(Seq(RegionType.PUT_EFFECTS, RegionType.GET_EFFECTS) contains _.regionType)
val lookup_tag = Cat(io.ptw.ptbr.asid, vpn(vpnBits-1,0))
val hitsVec = (0 until totalEntries).map { i => vm_enabled && {
val lookup_tag = Cat(io.ptw.ptbr.asid, vpn)
val hitsVec = (0 until totalEntries).map { i => if (!usingVM) false.B else vm_enabled && {
var tagMatch = valid(i)
for (j <- 0 until pgLevels) {
val base = vpnBits - (j + 1) * pgLevelBits
@ -133,7 +133,7 @@ class TLB(instruction: Boolean, lgMaxSize: Int, nEntries: Int)(implicit edge: TL
val hits = hitsVec.asUInt
val level = Mux1H(hitsVec.init, entries.map(_.level))
val partialPPN = Mux1H(hitsVec.init, entries.map(_.ppn))
val ppn = {
val ppn = if (!usingVM) vpn else {
var ppn = Mux(vm_enabled, partialPPN, vpn)(pgLevelBits*pgLevels - 1, pgLevelBits*(pgLevels - 1))
for (i <- 1 until pgLevels)
ppn = Cat(ppn, (Mux(level < i, vpn, 0.U) | partialPPN)(vpnBits - i*pgLevelBits - 1, vpnBits - (i + 1)*pgLevelBits))
@ -187,7 +187,7 @@ class TLB(instruction: Boolean, lgMaxSize: Int, nEntries: Int)(implicit edge: TL
val misaligned = (io.req.bits.vaddr & (UIntToOH(io.req.bits.size) - 1)).orR
val bad_va = vm_enabled &&
(if (vpnBits == vpnBitsExtended) Bool(false)
else vpn(vpnBits) =/= vpn(vpnBits-1))
else (io.req.bits.vaddr.asSInt < 0.S) =/= (vpn.asSInt < 0.S))
val lrscAllowed = Mux(Bool(usingDataScratchpad), 0.U, c_array)
val ae_array =
@ -230,7 +230,7 @@ class TLB(instruction: Boolean, lgMaxSize: Int, nEntries: Int)(implicit edge: TL
io.resp.cacheable := (c_array & hits).orR
io.resp.prefetchable := (prefetchable_array & hits).orR && edge.manager.managers.forall(m => !m.supportsAcquireB || m.supportsHint)
io.resp.miss := do_refill || tlb_miss || multipleHits
io.resp.paddr := Cat(ppn, pgOffset)
io.resp.paddr := Cat(ppn, io.req.bits.vaddr(pgIdxBits-1, 0))
io.ptw.req.valid := state === s_request
io.ptw.req.bits <> io.ptw.status
@ -256,7 +256,7 @@ class TLB(instruction: Boolean, lgMaxSize: Int, nEntries: Int)(implicit edge: TL
}
when (sfence) {
assert((io.req.bits.sfence.bits.addr >> pgIdxBits) === vpn(vpnBits-1,0))
assert((io.req.bits.sfence.bits.addr >> pgIdxBits) === vpn)
valid := Mux(io.req.bits.sfence.bits.rs1, valid & ~hits(totalEntries-1, 0),
Mux(io.req.bits.sfence.bits.rs2, valid & entries.map(_.g).asUInt, 0))
}

View File

@ -22,6 +22,7 @@ trait TileParams {
val rocc: Seq[RoCCParams]
val btb: Option[BTBParams]
val trace: Boolean
val hartid: Int
}
trait HasTileParameters {
@ -41,7 +42,14 @@ trait HasTileParameters {
def iLen: Int = 32
def pgIdxBits: Int = 12
def pgLevelBits: Int = 10 - log2Ceil(xLen / 32)
def vaddrBits: Int = pgIdxBits + pgLevels * pgLevelBits
def vaddrBits: Int =
if (usingVM) {
val v = pgIdxBits + pgLevels * pgLevelBits
require(v == xLen || xLen > v && v > paddrBits)
v
} else {
paddrBits min xLen
}
def paddrBits: Int = p(SharedMemoryTLEdge).bundle.addressBits
def vpnBits: Int = vaddrBits - pgIdxBits
def ppnBits: Int = paddrBits - pgIdxBits
@ -52,7 +60,7 @@ trait HasTileParameters {
def maxPAddrBits: Int = xLen match { case 32 => 34; case 64 => 56 }
def hartIdLen: Int = p(MaxHartIdBits)
def resetVectorLen: Int = paddrBits min vaddrBitsExtended
def resetVectorLen: Int = paddrBits
def dcacheArbPorts = 1 + usingVM.toInt + usingDataScratchpad.toInt + tileParams.rocc.size
}
@ -99,19 +107,17 @@ trait CanHaveInstructionTracePort extends Bundle with HasTileParameters {
/** Base class for all Tiles that use TileLink */
abstract class BaseTile(tileParams: TileParams)(implicit p: Parameters) extends BareTile
with HasTileParameters
with HasTileLinkMasterPort {
override lazy val module = new BaseTileModule(this, () => new BaseTileBundle(this))
with HasTileParameters {
def module: BaseTileModule[BaseTile, BaseTileBundle[BaseTile]]
}
class BaseTileBundle[+L <: BaseTile](_outer: L) extends BareTileBundle(_outer)
with HasTileLinkMasterPortBundle
abstract class BaseTileBundle[+L <: BaseTile](_outer: L) extends BareTileBundle(_outer)
with HasExternallyDrivenTileConstants
with CanHaveInstructionTracePort
with CanHaltAndCatchFire
class BaseTileModule[+L <: BaseTile, +B <: BaseTileBundle[L]](_outer: L, _io: () => B) extends BareTileModule(_outer, _io)
with HasTileParameters
with HasTileLinkMasterPortModule {
with HasTileParameters {
require(xLen == 32 || xLen == 64)
require(paddrBits <= maxPAddrBits)
require(resetVectorLen <= xLen)

View File

@ -181,7 +181,12 @@ class RocketTileModule(outer: RocketTile) extends BaseTileModule(outer, () => ne
ptw.io.requestor <> ptwPorts
}
abstract class RocketTileWrapper(rtp: RocketTileParams)(implicit p: Parameters) extends LazyModule {
class RocketTileWrapperBundle[+L <: RocketTileWrapper](_outer: L) extends BaseTileBundle(_outer)
with CanHaltAndCatchFire {
val halt_and_catch_fire = _outer.rocket.module.io.halt_and_catch_fire.map(_.cloneType)
}
abstract class RocketTileWrapper(rtp: RocketTileParams)(implicit p: Parameters) extends BaseTile(rtp) {
val rocket = LazyModule(new RocketTile(rtp))
val asyncIntNode : IntInwardNode
val periphIntNode : IntInwardNode
@ -213,13 +218,7 @@ abstract class RocketTileWrapper(rtp: RocketTileParams)(implicit p: Parameters)
def outputInterruptXingLatency: Int
lazy val module = new LazyModuleImp(this) {
val io = IO(new CoreBundle
with HasExternallyDrivenTileConstants
with CanHaveInstructionTracePort
with CanHaltAndCatchFire {
val halt_and_catch_fire = rocket.module.io.halt_and_catch_fire.map(_.cloneType)
})
override lazy val module = new BaseTileModule(this, () => new RocketTileWrapperBundle(this)) {
// signals that do not change based on crossing type:
rocket.module.io.hartid := io.hartid
rocket.module.io.reset_vector := io.reset_vector