未验证 提交 666dc712 编写于 作者: Y Yinan Xu 提交者: GitHub

Merge pull request #393 from RISCVERS/dualcore-plic

Dualcore plic
package device
import chisel3._
import chisel3.util._
import chipsalliance.rocketchip.config._
import freechips.rocketchip.diplomacy._
import utils.MaskExpand
import utils.{HasTLDump, XSDebug, RegMap}
/* base + 0x000000: Reserved (interrupt source 0 does not exist)
base + 0x000004: Interrupt source 1 priority
base + 0x000008: Interrupt source 2 priority
...
base + 0x000FFC: Interrupt source 1023 priority
base + 0x001000: Interrupt Pending bit 0-31
base + 0x00107C: Interrupt Pending bit 992-1023
...
base + 0x002000: Enable bits for sources 0-31 on context 0
base + 0x002004: Enable bits for sources 32-63 on context 0
...
base + 0x00207F: Enable bits for sources 992-1023 on context 0
base + 0x002080: Enable bits for sources 0-31 on context 1
base + 0x002084: Enable bits for sources 32-63 on context 1
...
base + 0x0020FF: Enable bits for sources 992-1023 on context 1
base + 0x002100: Enable bits for sources 0-31 on context 2
base + 0x002104: Enable bits for sources 32-63 on context 2
...
base + 0x00217F: Enable bits for sources 992-1023 on context 2
...
base + 0x1F1F80: Enable bits for sources 0-31 on context 15871
base + 0x1F1F84: Enable bits for sources 32-63 on context 15871
base + 0x1F1FFF: Enable bits for sources 992-1023 on context 15871
...
base + 0x1FFFFC: Reserved
base + 0x200000: Priority threshold for context 0
base + 0x200004: Claim/complete for context 0
base + 0x200008: Reserved
...
base + 0x200FFC: Reserved
base + 0x201000: Priority threshold for context 1
base + 0x201004: Claim/complete for context 1
...
base + 0x3FFE000: Priority threshold for context 15871
base + 0x3FFE004: Claim/complete for context 15871
base + 0x3FFE008: Reserved
...
base + 0x3FFFFFC: Reserved */
object PLICConsts
{
def maxDevices = 1023
def maxHarts = 15872
def priorityBase = 0x0
def pendingBase = 0x1000
def enableBase = 0x2000
def hartBase = 0x200000
def claimOffset = 4
def priorityBytes = 4
def enableOffset(i: Int) = i * ((maxDevices+7)/8)
def hartOffset(i: Int) = i * 0x1000
def enableBase(i: Int):Int = enableOffset(i) + enableBase
def hartBase(i: Int):Int = hartOffset(i) + hartBase
def size(maxHarts: Int): Int = {
require(maxHarts > 0 && maxHarts <= maxHarts, s"Must be: maxHarts=$maxHarts > 0 && maxHarts <= PLICConsts.maxHarts=${PLICConsts.maxHarts}")
1 << log2Ceil(hartBase(maxHarts))
}
require(hartBase >= enableBase(maxHarts))
}
class PlicIO extends Bundle with xiangshan.HasXSParameter {
val intrVec = Input(UInt(NrExtIntr.W))
val meip = Output(Vec(top.Parameters.get.socParameters.NumCores, Bool()))
}
class AXI4Plic
(
address: Seq[AddressSet],
sim: Boolean = false
)(implicit p: Parameters)
extends AXI4SlaveModule(address, executable = false, _extra = new PlicIO) with xiangshan.HasXSParameter
{
override lazy val module = new AXI4SlaveModuleImp[PlicIO](this) {
val NumCores = top.Parameters.get.socParameters.NumCores
require(NrExtIntr <= PLICConsts.maxDevices)
require(NumCores <= PLICConsts.maxHarts)
val addressSpaceSize = 0x4000000
val addressBits = log2Up(addressSpaceSize)
def getOffset(addr: UInt) = addr(addressBits - 1, 0)
val priority = List.fill(NrExtIntr)(Reg(UInt(32.W)))
val priorityMap = priority.zipWithIndex.map { case (r, intr) => RegMap((intr + 1) * 4, r) }.toMap
val nrIntrWord = (NrExtIntr + 31) / 32 // roundup
// pending bits are updated in the unit of bit by PLIC,
// so define it as vectors of bits, instead of UInt(32.W)
val pending = List.fill(nrIntrWord)(RegInit(0.U.asTypeOf(Vec(32, Bool()))))
val pendingMap = pending.zipWithIndex.map { case (r, intrWord) =>
RegMap(0x1000 + intrWord * 4, Cat(r.reverse), RegMap.Unwritable)
}.toMap
val enable = List.fill(NumCores)(List.fill(nrIntrWord)(RegInit(0.U(32.W))))
val enableMap = enable.zipWithIndex.map { case (l, hart) =>
l.zipWithIndex.map { case (r, intrWord) => RegMap(0x2000 + hart * 0x80 + intrWord * 4, r) }
}.reduce(_ ++ _).toMap
val threshold = List.fill(NumCores)(Reg(UInt(32.W)))
val thresholdMap = threshold.zipWithIndex.map {
case (r, hart) => RegMap(0x200000 + hart * 0x1000, r)
}.toMap
val inHandle = RegInit(0.U.asTypeOf(Vec(NrExtIntr + 1, Bool())))
def completionFn(wdata: UInt) = {
inHandle(wdata(31, 0)) := false.B
0.U
}
val claimCompletion = List.fill(NumCores)(Reg(UInt(32.W)))
val claimCompletionMap = claimCompletion.zipWithIndex.map {
case (r, hart) => {
val addr = 0x200004 + hart * 0x1000
when(in.r.fire() && (getOffset(raddr) === addr.U)) {
inHandle(r) := true.B
}
RegMap(addr, r, completionFn)
}
}.toMap
io.extra.get.intrVec.asBools.zipWithIndex.map { case (intr, i) => {
val id = i + 1
when(intr) {
pending(id / 32)(id % 32) := true.B
}
when(inHandle(id)) {
pending(id / 32)(id % 32) := false.B
}
}
}
val pendingVec = Cat(pending.map(x => Cat(x.reverse)))
claimCompletion.zipWithIndex.map { case (r, hart) => {
val takenVec = pendingVec & Cat(enable(hart))
r := Mux(takenVec === 0.U, 0.U, PriorityEncoder(takenVec))
}
}
val mapping = priorityMap ++ pendingMap ++ enableMap ++ thresholdMap ++ claimCompletionMap
val rdata = Wire(UInt(32.W))
RegMap.generate(mapping, getOffset(raddr), rdata,
getOffset(waddr), in.w.fire(), in.w.bits.data, MaskExpand(in.w.bits.strb >> waddr(2, 0)))
// narrow read
in.r.bits.data := Fill(2, rdata)
io.extra.get.meip.zipWithIndex.map { case (ip, hart) => ip := claimCompletion(hart) =/= 0.U }
}
}
......@@ -13,16 +13,17 @@ class TLTimer(address: Seq[AddressSet], sim: Boolean)(implicit p: Parameters) ex
val device = new SimpleDevice("clint", Seq("XiangShan", "clint"))
val node = TLRegisterNode(address, device, beatBytes = 8)
val NumCores = top.Parameters.get.socParameters.NumCores
lazy val module = new LazyModuleImp(this) with HasXSLog with HasTLDump{
val io = IO(new Bundle() {
val mtip = Output(Bool())
val msip = Output(Bool())
val mtip = Output(Vec(NumCores, Bool()))
val msip = Output(Vec(NumCores, Bool()))
})
val mtime = RegInit(0.U(64.W)) // unit: us
val mtimecmp = RegInit(0.U(64.W))
val msip = RegInit(0.U(64.W))
val mtimecmp = Seq.fill(NumCores)(RegInit(0.U(64.W)))
val msip = Seq.fill(NumCores)(RegInit(0.U(32.W)))
val clk = (if (!sim) 40 /* 40MHz / 1000000 */ else 100)
val freq = RegInit(clk.U(16.W))
......@@ -34,13 +35,19 @@ class TLTimer(address: Seq[AddressSet], sim: Boolean)(implicit p: Parameters) ex
val tick = (nextCnt === freq)
when (tick) { mtime := mtime + inc }
node.regmap( mapping =
0x0000 -> RegField.bytes(msip),
0x4000 -> RegField.bytes(mtimecmp),
var clintMapping = Seq(
0x8000 -> RegField.bytes(freq),
0x8008 -> RegField.bytes(inc),
0xbff8 -> RegField.bytes(mtime)
)
0xbff8 -> RegField.bytes(mtime))
for (i <- 0 until NumCores) {
clintMapping = clintMapping ++ Seq(
0x0000 + i*4 -> RegField.bytes(msip(i)),
0x4000 + i*8 -> RegField.bytes(mtimecmp(i))
)
}
node.regmap( mapping = clintMapping:_* )
val in = node.in.head._1
when(in.a.valid){
......@@ -51,7 +58,9 @@ class TLTimer(address: Seq[AddressSet], sim: Boolean)(implicit p: Parameters) ex
// val gtime = GTimer()
// printf(p"[$gtime][Timer] mtime=$mtime cnt=$cnt freq=$freq\n")
io.mtip := RegNext(mtime >= mtimecmp)
io.msip := RegNext(msip =/= 0.U)
for (i <- 0 until NumCores) {
io.mtip(i) := RegNext(mtime >= mtimecmp(i))
io.msip(i) := RegNext(msip(i) =/= 0.U)
}
}
}
package system
import chipsalliance.rocketchip.config.Parameters
import device.{AXI4Timer, TLTimer}
import device.{AXI4Timer, TLTimer, AXI4Plic}
import chisel3._
import chisel3.util._
import freechips.rocketchip.diplomacy.{AddressSet, LazyModule, LazyModuleImp}
......@@ -154,15 +154,27 @@ class XSSoc()(implicit p: Parameters) extends LazyModule with HasSoCParameter {
clint.node := mmioXbar
extDev := AXI4UserYanker() := TLToAXI4() := mmioXbar
val plic = LazyModule(new AXI4Plic(
Seq(AddressSet(0x3c000000L, 0x03ffffffL)),
sim = !env.FPGAPlatform
))
val plicIdentity = AXI4IdentityNode()
plic.node := plicIdentity := AXI4UserYanker() := TLToAXI4() := mmioXbar
lazy val module = new LazyModuleImp(this){
val io = IO(new Bundle{
val meip = Input(Bool())
val extIntrs = Input(Vec(NrExtIntr, Bool()))
// val meip = Input(Vec(NumCores, Bool()))
val ila = if(env.FPGAPlatform && EnableILA) Some(Output(new ILABundle)) else None
})
plic.module.io.extra.get.intrVec <> RegNext(RegNext(Cat(io.extIntrs)))
for (i <- 0 until NumCores) {
xs_core(i).module.io.externalInterrupt.mtip := clint.module.io.mtip
xs_core(i).module.io.externalInterrupt.msip := clint.module.io.msip
xs_core(i).module.io.externalInterrupt.meip := RegNext(RegNext(io.meip))
xs_core(i).module.io.externalInterrupt.mtip := clint.module.io.mtip(i)
xs_core(i).module.io.externalInterrupt.msip := clint.module.io.msip(i)
// xs_core(i).module.io.externalInterrupt.meip := RegNext(RegNext(io.meip(i)))
xs_core(i).module.io.externalInterrupt.meip := plic.module.io.extra.get.meip(i)
}
// do not let dma AXI signals optimized out
chisel3.dontTouch(dma.out.head._1)
......
......@@ -24,6 +24,9 @@ object Parameters {
val simParameters = Parameters(envParameters = EnviromentParameters(FPGAPlatform = false)) // sim only, disable log
val debugParameters = Parameters(envParameters = simParameters.envParameters.copy(EnableDebug = true)) // open log
val simDualCoreParameters = Parameters(socParameters = SoCParameters(NumCores = 2), envParameters = EnviromentParameters(FPGAPlatform = false))
val debugDualCoreParameters = Parameters(socParameters = SoCParameters(NumCores = 2), envParameters = simParameters.envParameters.copy(EnableDebug = true))
private var parameters = Parameters() // a default parameter, can be updated before use
def get: Parameters = parameters
def set(p: Parameters): Unit = {
......
......@@ -89,7 +89,8 @@ case class XSCoreParameters
TlbL2EntrySize: Int = 256, // or 512
PtwL1EntrySize: Int = 16,
PtwL2EntrySize: Int = 256,
NumPerfCounters: Int = 16
NumPerfCounters: Int = 16,
NrExtIntr: Int = 1
)
trait HasXSParameter {
......@@ -164,6 +165,7 @@ trait HasXSParameter {
val PtwL1EntrySize = core.PtwL1EntrySize
val PtwL2EntrySize = core.PtwL2EntrySize
val NumPerfCounters = core.NumPerfCounters
val NrExtIntr = core.NrExtIntr
val icacheParameters = ICacheParameters(
tagECC = Some("secded"),
......
......@@ -16,6 +16,14 @@ object debugId extends Function0[Integer] {
}
}
object hartId extends Function0[Int] {
var x = 0
def apply(): Int = {
x = x + 1
return x-1
}
}
trait HasCSRConst {
// User Trap Setup
val Ustatus = 0x000
......@@ -284,7 +292,8 @@ class CSR extends FunctionUnit with HasCSRConst
val mvendorid = RegInit(UInt(XLEN.W), 0.U) // this is a non-commercial implementation
val marchid = RegInit(UInt(XLEN.W), 0.U) // return 0 to indicate the field is not implemented
val mimpid = RegInit(UInt(XLEN.W), 0.U) // provides a unique encoding of the version of the processor implementation
val mhartid = RegInit(UInt(XLEN.W), 0.U) // the hardware thread running the code
val mhartNo = hartId()
val mhartid = RegInit(UInt(XLEN.W), mhartNo.asUInt) // the hardware thread running the code
val mstatus = RegInit(UInt(XLEN.W), "h00001800".U)
// val mstatus = RegInit(UInt(XLEN.W), "h8000c0100".U)
// mstatus Value Table
......
......@@ -124,7 +124,10 @@ class XSSimSoC(axiSim: Boolean)(implicit p: config.Parameters) extends LazyModul
dontTouch(io.uart)
io.uart <> axiMMIO.module.io.uart
soc.module.io.meip := false.B
val NumCores = top.Parameters.get.socParameters.NumCores
for (i <- 0 until NrExtIntr) {
soc.module.io.extIntrs(i) := false.B
}
val difftest = WireInit(0.U.asTypeOf(new DiffTestIO))
if (!env.FPGAPlatform) {
......@@ -236,12 +239,14 @@ object TestMain extends App {
// set soc parameters
val socArgs = args.filterNot(_ == "--with-dramsim3")
Parameters.set(
if(socArgs.contains("--fpga-platform")) {
if (socArgs.contains("--dual-core")) Parameters.dualCoreParameters
else Parameters()
(socArgs.contains("--fpga-platform"), socArgs.contains("--dual-core"), socArgs.contains("--disable-log")) match {
case (true, false, _) => Parameters()
case (true, true, _) => Parameters.dualCoreParameters
case (false, true, true) => Parameters.simDualCoreParameters
case (false, false, true) => Parameters.simParameters
case (false, true, false) => Parameters.debugDualCoreParameters
case (false, false, false) => Parameters.debugParameters
}
else if(socArgs.contains("--disable-log")) Parameters.simParameters // sim only, disable log
else Parameters.debugParameters // open log
)
val otherArgs = socArgs.filterNot(_ == "--disable-log").filterNot(_ == "--fpga-platform").filterNot(_ == "--dual-core")
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册