RegField: separate UInt=>bytes and bytes=>regs
This commit is contained in:
parent
943c36954d
commit
4b1de82c1d
@ -62,6 +62,11 @@ trait PRCIModule extends Module with HasRegMap with MixPRCIParameters {
|
|||||||
tile.reset := reset
|
tile.reset := reset
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def pad = RegField(8) // each use is a new field
|
||||||
|
val ipi_fields = ipi.map(r => Seq(RegField(1, r), RegField(7), pad, pad, pad)).flatten
|
||||||
|
val timecmp_fields = timecmp.map(RegField.bytes(_)).flatten
|
||||||
|
val time_fields = Seq.fill(PRCI.time%c.beatBytes)(pad) ++ RegField.bytes(time)
|
||||||
|
|
||||||
/* 0000 msip hart 0
|
/* 0000 msip hart 0
|
||||||
* 0004 msip hart 1
|
* 0004 msip hart 1
|
||||||
* 4000 mtimecmp hart 0 lo
|
* 4000 mtimecmp hart 0 lo
|
||||||
@ -71,26 +76,14 @@ trait PRCIModule extends Module with HasRegMap with MixPRCIParameters {
|
|||||||
* bff8 mtime lo
|
* bff8 mtime lo
|
||||||
* bffc mtime hi
|
* bffc mtime hi
|
||||||
*/
|
*/
|
||||||
|
val ipi_base = 0
|
||||||
|
val timecmp_base = PRCI.timecmp(0) / c.beatBytes
|
||||||
|
val time_base = PRCI.time / c.beatBytes
|
||||||
|
|
||||||
// laying out IPI fields suck...
|
regmap((
|
||||||
// bytes=1 -> pad to 7, step 4, group 1
|
RegField.split(ipi_fields, ipi_base, c.beatBytes) ++
|
||||||
// bytes=2 -> pad to 15, step 2, group 1
|
RegField.split(timecmp_fields, timecmp_base, c.beatBytes) ++
|
||||||
// bytes=4 -> pad to 31, step 1, group 1
|
RegField.split(time_fields, time_base, c.beatBytes)):_*)
|
||||||
// bytes=8 -> pad to 31, step 1, group 2
|
|
||||||
// bytes=16-> pad to 31, step 1, group 4
|
|
||||||
val pad = min(c.beatBytes*8,32) - 1
|
|
||||||
val step = max(1, 4/c.beatBytes)
|
|
||||||
val group = max(1, c.beatBytes/4)
|
|
||||||
val ipi_regs = ipi.map { reg => Seq(RegField(1, reg), RegField(pad)) }.flatten.grouped(group*2).
|
|
||||||
zipWithIndex.map { case (fields, i) => (i*step -> fields) }
|
|
||||||
|
|
||||||
// Just split up time fields by bytes
|
|
||||||
val timecmp_regs = timecmp.zipWithIndex.map { case (reg, i) =>
|
|
||||||
RegField.bytes(reg, PRCI.timecmp(i)/c.beatBytes, c.beatBytes)
|
|
||||||
}.flatten
|
|
||||||
val time_reg = RegField.bytes(time, PRCI.time/c.beatBytes, c.beatBytes)
|
|
||||||
|
|
||||||
regmap((timecmp_regs ++ time_reg ++ ipi_regs):_*)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Power, Reset, Clock, Interrupt */
|
/** Power, Reset, Clock, Interrupt */
|
||||||
|
@ -108,7 +108,7 @@ object RegField
|
|||||||
|
|
||||||
// Split a large register into a sequence of byte fields
|
// Split a large register into a sequence of byte fields
|
||||||
// The bytes can be individually written, as they are one byte per field
|
// The bytes can be individually written, as they are one byte per field
|
||||||
def bytes(x: UInt, base: Int = 0, beatBytes: Int = 4): Seq[RegField.Map] = {
|
def bytes(x: UInt): Seq[RegField] = {
|
||||||
require (x.getWidth % 8 == 0)
|
require (x.getWidth % 8 == 0)
|
||||||
val bytes = Seq.tabulate(x.getWidth/8) { i => x(8*(i+1)-1, 8*i) }
|
val bytes = Seq.tabulate(x.getWidth/8) { i => x(8*(i+1)-1, 8*i) }
|
||||||
val wires = bytes.map { b => Wire(init = b) }
|
val wires = bytes.map { b => Wire(init = b) }
|
||||||
@ -118,10 +118,15 @@ object RegField
|
|||||||
when (valid) { wires(i) := data }
|
when (valid) { wires(i) := data }
|
||||||
Bool(true)
|
Bool(true)
|
||||||
})
|
})
|
||||||
}.grouped(beatBytes).toSeq.zipWithIndex.map { case (reg, i) =>
|
|
||||||
(i+base, reg)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Divide a long sequence of RegFields into a maximum sized registers
|
||||||
|
// Your input RegFields may not cross a beatBytes boundary!
|
||||||
|
def split(fields: Seq[RegField], base: Int, beatBytes: Int = 4): Seq[RegField.Map] = {
|
||||||
|
val offsets = fields.map(_.width).scanLeft(0)(_ + _).init
|
||||||
|
(offsets zip fields).groupBy(_._1 / (beatBytes*8)).toList.map(r => (r._1 + base, r._2.map(_._2)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait HasRegMap
|
trait HasRegMap
|
||||||
|
Loading…
Reference in New Issue
Block a user