rocket: connect interrupt map for Plic+Clint
This commit is contained in:
@ -17,11 +17,6 @@ import tile.XLen
|
||||
/** Number of tiles */
|
||||
case object NTiles extends Field[Int]
|
||||
|
||||
class CoreplexLocalInterrupts extends Bundle {
|
||||
val mtip = Bool()
|
||||
val msip = Bool()
|
||||
}
|
||||
|
||||
object ClintConsts
|
||||
{
|
||||
def msipOffset(hart: Int) = hart * msipBytes
|
||||
@ -30,71 +25,78 @@ object ClintConsts
|
||||
def msipBytes = 4
|
||||
def timecmpBytes = 8
|
||||
def size = 0x10000
|
||||
def timeWidth = 64
|
||||
def regWidth = 32
|
||||
def ints = 2
|
||||
}
|
||||
|
||||
trait MixCoreplexLocalInterrupterParameters {
|
||||
implicit val p: Parameters
|
||||
}
|
||||
|
||||
trait CoreplexLocalInterrupterBundle extends Bundle with MixCoreplexLocalInterrupterParameters {
|
||||
val tiles = Vec(p(NTiles), new CoreplexLocalInterrupts).asOutput
|
||||
val rtcTick = Bool(INPUT)
|
||||
}
|
||||
|
||||
trait CoreplexLocalInterrupterModule extends Module with HasRegMap with MixCoreplexLocalInterrupterParameters {
|
||||
val io: CoreplexLocalInterrupterBundle
|
||||
val address: AddressSet
|
||||
|
||||
val timeWidth = 64
|
||||
val regWidth = 32
|
||||
|
||||
val time = Seq.fill(timeWidth/regWidth)(Reg(init=UInt(0, width = regWidth)))
|
||||
when (io.rtcTick) {
|
||||
val newTime = time.asUInt + UInt(1)
|
||||
for ((reg, i) <- time zip (0 until timeWidth by regWidth))
|
||||
reg := newTime >> i
|
||||
}
|
||||
|
||||
val timecmp = Seq.fill(p(NTiles)) { Seq.fill(timeWidth/regWidth)(Reg(UInt(width = regWidth))) }
|
||||
val ipi = Seq.fill(p(NTiles)) { RegInit(UInt(0, width = 1)) }
|
||||
|
||||
for ((tile, i) <- io.tiles zipWithIndex) {
|
||||
tile.msip := ipi(i)(0)
|
||||
tile.mtip := time.asUInt >= timecmp(i).asUInt
|
||||
}
|
||||
|
||||
/* 0000 msip hart 0
|
||||
* 0004 msip hart 1
|
||||
* 4000 mtimecmp hart 0 lo
|
||||
* 4004 mtimecmp hart 0 hi
|
||||
* 4008 mtimecmp hart 1 lo
|
||||
* 400c mtimecmp hart 1 hi
|
||||
* bff8 mtime lo
|
||||
* bffc mtime hi
|
||||
*/
|
||||
|
||||
regmap(
|
||||
0 -> makeRegFields(ipi),
|
||||
ClintConsts.timecmpOffset(0) -> makeRegFields(timecmp.flatten),
|
||||
ClintConsts.timeOffset -> makeRegFields(time))
|
||||
|
||||
def makeRegFields(s: Seq[UInt]) = s.map(r => RegField(regWidth, r))
|
||||
}
|
||||
|
||||
/** Power, Reset, Clock, Interrupt */
|
||||
// Magic TL2 Incantation to create a TL2 Slave
|
||||
// prci0 => at most 4095 devices
|
||||
class CoreplexLocalInterrupter(address: BigInt = 0x02000000)(implicit p: Parameters)
|
||||
extends TLRegisterRouter(address, "clint", Seq("riscv,clint0"), size = ClintConsts.size, beatBytes = p(XLen)/8, undefZero = true)(
|
||||
new TLRegBundle((), _) with CoreplexLocalInterrupterBundle)(
|
||||
new TLRegModule((), _, _) with CoreplexLocalInterrupterModule)
|
||||
class CoreplexLocalInterrupter(address: BigInt = 0x02000000)(implicit p: Parameters) extends LazyModule
|
||||
{
|
||||
import ClintConsts._
|
||||
|
||||
// clint0 => at most 4095 devices
|
||||
val device = new SimpleDevice("clint", Seq("riscv,clint0")) {
|
||||
override val alwaysExtended = true
|
||||
}
|
||||
|
||||
val node = TLRegisterNode(
|
||||
address = AddressSet(address, size-1),
|
||||
device = device,
|
||||
beatBytes = p(XLen)/8)
|
||||
|
||||
val intnode = IntNexusNode(
|
||||
numSourcePorts = 0 to 1024,
|
||||
numSinkPorts = 0 to 0,
|
||||
sourceFn = { _ => IntSourcePortParameters(Seq(IntSourceParameters(ints, Seq(Resource(device, "int"))))) },
|
||||
sinkFn = { _ => IntSinkPortParameters(Seq(IntSinkParameters())) })
|
||||
|
||||
// Legacy stuff:
|
||||
val globalConfigString = Seq(
|
||||
s"rtc {\n",
|
||||
s" addr 0x${(address + ClintConsts.timeOffset).toString(16)};\n",
|
||||
s" addr 0x${(address + timeOffset).toString(16)};\n",
|
||||
s"};\n").mkString
|
||||
val hartConfigStrings = (0 until p(NTiles)).map { i => Seq(
|
||||
s" timecmp 0x${(address + ClintConsts.timecmpOffset(i)).toString(16)};\n",
|
||||
s" ipi 0x${(address + ClintConsts.msipOffset(i)).toString(16)};\n").mkString
|
||||
s" timecmp 0x${(address + timecmpOffset(i)).toString(16)};\n",
|
||||
s" ipi 0x${(address + msipOffset(i)).toString(16)};\n").mkString
|
||||
}
|
||||
|
||||
lazy val module = new LazyModuleImp(this) {
|
||||
val io = new Bundle {
|
||||
val rtcTick = Bool(INPUT)
|
||||
val int = intnode.bundleOut
|
||||
val in = node.bundleIn
|
||||
}
|
||||
|
||||
val time = Seq.fill(timeWidth/regWidth)(Reg(init=UInt(0, width = regWidth)))
|
||||
when (io.rtcTick) {
|
||||
val newTime = time.asUInt + UInt(1)
|
||||
for ((reg, i) <- time zip (0 until timeWidth by regWidth))
|
||||
reg := newTime >> i
|
||||
}
|
||||
|
||||
val timecmp = Seq.fill(p(NTiles)) { Seq.fill(timeWidth/regWidth)(Reg(UInt(width = regWidth))) }
|
||||
val ipi = Seq.fill(p(NTiles)) { RegInit(UInt(0, width = 1)) }
|
||||
|
||||
io.int.zipWithIndex.foreach { case (int, i) =>
|
||||
int(0) := ipi(i)(0) // msip
|
||||
int(1) := time.asUInt >= timecmp(i).asUInt // mtip
|
||||
}
|
||||
|
||||
/* 0000 msip hart 0
|
||||
* 0004 msip hart 1
|
||||
* 4000 mtimecmp hart 0 lo
|
||||
* 4004 mtimecmp hart 0 hi
|
||||
* 4008 mtimecmp hart 1 lo
|
||||
* 400c mtimecmp hart 1 hi
|
||||
* bff8 mtime lo
|
||||
* bffc mtime hi
|
||||
*/
|
||||
|
||||
def makeRegFields(s: Seq[UInt]) = s.map(r => RegField(regWidth, r))
|
||||
|
||||
node.regmap(
|
||||
0 -> makeRegFields(ipi),
|
||||
timecmpOffset(0) -> makeRegFields(timecmp.flatten),
|
||||
timeOffset -> makeRegFields(time))
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user