From 4b1de82c1db7c0cc3c758648a5b579d6424356b0 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Fri, 16 Sep 2016 14:19:42 -0700 Subject: [PATCH] RegField: separate UInt=>bytes and bytes=>regs --- src/main/scala/uncore/devices/Prci.scala | 31 +++++++------------ .../scala/uncore/tilelink2/RegField.scala | 11 +++++-- 2 files changed, 20 insertions(+), 22 deletions(-) diff --git a/src/main/scala/uncore/devices/Prci.scala b/src/main/scala/uncore/devices/Prci.scala index 334072b5..d43beea3 100644 --- a/src/main/scala/uncore/devices/Prci.scala +++ b/src/main/scala/uncore/devices/Prci.scala @@ -62,6 +62,11 @@ trait PRCIModule extends Module with HasRegMap with MixPRCIParameters { 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 * 0004 msip hart 1 * 4000 mtimecmp hart 0 lo @@ -71,26 +76,14 @@ trait PRCIModule extends Module with HasRegMap with MixPRCIParameters { * bff8 mtime lo * 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... - // bytes=1 -> pad to 7, step 4, group 1 - // bytes=2 -> pad to 15, step 2, group 1 - // bytes=4 -> pad to 31, step 1, group 1 - // 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):_*) + regmap(( + RegField.split(ipi_fields, ipi_base, c.beatBytes) ++ + RegField.split(timecmp_fields, timecmp_base, c.beatBytes) ++ + RegField.split(time_fields, time_base, c.beatBytes)):_*) } /** Power, Reset, Clock, Interrupt */ diff --git a/src/main/scala/uncore/tilelink2/RegField.scala b/src/main/scala/uncore/tilelink2/RegField.scala index 7a51cb1f..2b372208 100644 --- a/src/main/scala/uncore/tilelink2/RegField.scala +++ b/src/main/scala/uncore/tilelink2/RegField.scala @@ -108,7 +108,7 @@ object RegField // Split a large register into a sequence of byte fields // 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) val bytes = Seq.tabulate(x.getWidth/8) { i => x(8*(i+1)-1, 8*i) } val wires = bytes.map { b => Wire(init = b) } @@ -118,10 +118,15 @@ object RegField when (valid) { wires(i) := data } 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