From a4214697544cbd0eab58a1f2197d35625e161d56 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Thu, 22 Sep 2016 17:45:42 -0700 Subject: [PATCH 1/5] tilelink2: change adapters to use TLAdapter(params, defaults)(node) This API makes it much more readable when you have multiple adapters combined into a single line. The arguments for each adapter stay beside the adapter. For example, this: peripheryBus.node := TLWidthWidget(TLBuffer(TLAtomicAutomata()(TLHintHandler(legacy.node))), legacy.tlDataBytes) becomes this: peripheryBus.node := TLWidthWidget(legacy.tlDataBytes)(TLBuffer()(TLAtomicAutomata()(TLHintHandler()(legacy.node)))) --- src/main/scala/rocketchip/BaseTop.scala | 2 +- src/main/scala/rocketchip/Periphery.scala | 6 +++--- src/main/scala/uncore/tilelink2/Buffer.scala | 12 ++++++------ src/main/scala/uncore/tilelink2/Fragmenter.scala | 2 +- src/main/scala/uncore/tilelink2/Fuzzer.scala | 8 ++++---- src/main/scala/uncore/tilelink2/HintHandler.scala | 2 +- src/main/scala/uncore/tilelink2/WidthWidget.scala | 2 +- 7 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/main/scala/rocketchip/BaseTop.scala b/src/main/scala/rocketchip/BaseTop.scala index 32b925d2..69c501ee 100644 --- a/src/main/scala/rocketchip/BaseTop.scala +++ b/src/main/scala/rocketchip/BaseTop.scala @@ -49,7 +49,7 @@ abstract class BaseTop(q: Parameters) extends LazyModule { val legacy = LazyModule(new TLLegacy()(p.alterPartial({ case TLId => "L2toMMIO" }))) - peripheryBus.node := TLWidthWidget(TLBuffer(TLAtomicAutomata()(TLHintHandler(legacy.node))), legacy.tlDataBytes) + peripheryBus.node := TLWidthWidget(legacy.tlDataBytes)(TLBuffer()(TLAtomicAutomata()(TLHintHandler()(legacy.node)))) } abstract class BaseTopBundle(val p: Parameters) extends Bundle { diff --git a/src/main/scala/rocketchip/Periphery.scala b/src/main/scala/rocketchip/Periphery.scala index a5fe8d6b..53bdfd09 100644 --- a/src/main/scala/rocketchip/Periphery.scala +++ b/src/main/scala/rocketchip/Periphery.scala @@ -288,7 +288,7 @@ trait PeripheryCoreplexLocalInterrupter extends LazyModule with HasPeripheryPara val clintConfig = CoreplexLocalInterrupterConfig(beatBytes) val clint = LazyModule(new CoreplexLocalInterrupter(clintConfig)(innerMMIOParams)) // The periphery bus is 32-bit, so we may need to adapt its width to XLen - clint.node := TLFragmenter(TLWidthWidget(peripheryBus.node, 4), beatBytes, 256) + clint.node := TLFragmenter(beatBytes, 256)(TLWidthWidget(4)(peripheryBus.node)) } trait PeripheryCoreplexLocalInterrupterBundle { @@ -314,7 +314,7 @@ trait PeripheryBootROM extends LazyModule { val address = 0x1000 val size = 0x1000 val rom = LazyModule(new TLROM(address, size, GenerateBootROM(p, address)) { override def name = "bootrom" }) - rom.node := TLFragmenter(peripheryBus.node, 4, 256) + rom.node := TLFragmenter(4, 256)(peripheryBus.node) } trait PeripheryBootROMBundle { @@ -337,7 +337,7 @@ trait PeripheryTestRAM extends LazyModule { val ramSize = 0x1000 val sram = LazyModule(new TLRAM(AddressSet(ramBase, ramSize-1)) { override def name = "testram" }) - sram.node := TLFragmenter(peripheryBus.node, 4, 256) + sram.node := TLFragmenter(4, 256)(peripheryBus.node) } trait PeripheryTestRAMBundle { diff --git a/src/main/scala/uncore/tilelink2/Buffer.scala b/src/main/scala/uncore/tilelink2/Buffer.scala index e4ba752b..75f8794b 100644 --- a/src/main/scala/uncore/tilelink2/Buffer.scala +++ b/src/main/scala/uncore/tilelink2/Buffer.scala @@ -48,12 +48,12 @@ class TLBuffer(a: Int = 2, b: Int = 2, c: Int = 2, d: Int = 2, e: Int = 2, pipe: object TLBuffer { // applied to the TL source node; y.node := TLBuffer(x.node) - def apply(x: TLBaseNode) (implicit sourceInfo: SourceInfo): TLBaseNode = apply(x, 2) - def apply(x: TLBaseNode, entries: Int) (implicit sourceInfo: SourceInfo): TLBaseNode = apply(x, entries, true) - def apply(x: TLBaseNode, entries: Int, pipe: Boolean) (implicit sourceInfo: SourceInfo): TLBaseNode = apply(x, entries, entries, pipe) - def apply(x: TLBaseNode, ace: Int, bd: Int) (implicit sourceInfo: SourceInfo): TLBaseNode = apply(x, ace, bd, true) - def apply(x: TLBaseNode, ace: Int, bd: Int, pipe: Boolean)(implicit sourceInfo: SourceInfo): TLBaseNode = apply(x, ace, bd, ace, bd, ace, pipe) - def apply(x: TLBaseNode, a: Int, b: Int, c: Int, d: Int, e: Int, pipe: Boolean = true)(implicit sourceInfo: SourceInfo): TLBaseNode = { + def apply() (x: TLBaseNode)(implicit sourceInfo: SourceInfo): TLBaseNode = apply(2)(x) + def apply(entries: Int) (x: TLBaseNode)(implicit sourceInfo: SourceInfo): TLBaseNode = apply(entries, true)(x) + def apply(entries: Int, pipe: Boolean) (x: TLBaseNode)(implicit sourceInfo: SourceInfo): TLBaseNode = apply(entries, entries, pipe)(x) + def apply(ace: Int, bd: Int) (x: TLBaseNode)(implicit sourceInfo: SourceInfo): TLBaseNode = apply(ace, bd, true)(x) + def apply(ace: Int, bd: Int, pipe: Boolean)(x: TLBaseNode)(implicit sourceInfo: SourceInfo): TLBaseNode = apply(ace, bd, ace, bd, ace, pipe)(x) + def apply(a: Int, b: Int, c: Int, d: Int, e: Int, pipe: Boolean = true)(x: TLBaseNode)(implicit sourceInfo: SourceInfo): TLBaseNode = { val buffer = LazyModule(new TLBuffer(a, b, c, d, e, pipe)) buffer.node := x buffer.node diff --git a/src/main/scala/uncore/tilelink2/Fragmenter.scala b/src/main/scala/uncore/tilelink2/Fragmenter.scala index 05e663eb..511863d3 100644 --- a/src/main/scala/uncore/tilelink2/Fragmenter.scala +++ b/src/main/scala/uncore/tilelink2/Fragmenter.scala @@ -244,7 +244,7 @@ class TLFragmenter(minSize: Int, maxSize: Int, alwaysMin: Boolean = false) exten object TLFragmenter { // applied to the TL source node; y.node := TLFragmenter(x.node, 256, 4) - def apply(x: TLBaseNode, minSize: Int, maxSize: Int, alwaysMin: Boolean = false)(implicit sourceInfo: SourceInfo): TLBaseNode = { + def apply(minSize: Int, maxSize: Int, alwaysMin: Boolean = false)(x: TLBaseNode)(implicit sourceInfo: SourceInfo): TLBaseNode = { val fragmenter = LazyModule(new TLFragmenter(minSize, maxSize, alwaysMin)) fragmenter.node := x fragmenter.node diff --git a/src/main/scala/uncore/tilelink2/Fuzzer.scala b/src/main/scala/uncore/tilelink2/Fuzzer.scala index aa7e0d2a..4c3d58de 100644 --- a/src/main/scala/uncore/tilelink2/Fuzzer.scala +++ b/src/main/scala/uncore/tilelink2/Fuzzer.scala @@ -222,11 +222,11 @@ class TLFuzzRAM extends LazyModule model.node := fuzz.node xbar2.node := TLAtomicAutomata()(model.node) - ram2.node := TLFragmenter(xbar2.node, 16, 256) - xbar.node := TLWidthWidget(TLHintHandler(xbar2.node), 16) - cross.node := TLFragmenter(TLBuffer(xbar.node), 4, 256) + ram2.node := TLFragmenter(16, 256)(xbar2.node) + xbar.node := TLWidthWidget(16)(TLHintHandler()(xbar2.node)) + cross.node := TLFragmenter(4, 256)(TLBuffer()(xbar.node)) val monitor = (ram.node := cross.node) - gpio.node := TLFragmenter(TLBuffer(xbar.node), 4, 32) + gpio.node := TLFragmenter(4, 32)(TLBuffer()(xbar.node)) lazy val module = new LazyModuleImp(this) with HasUnitTestIO { io.finished := fuzz.module.io.finished diff --git a/src/main/scala/uncore/tilelink2/HintHandler.scala b/src/main/scala/uncore/tilelink2/HintHandler.scala index 6ebef935..5480dd67 100644 --- a/src/main/scala/uncore/tilelink2/HintHandler.scala +++ b/src/main/scala/uncore/tilelink2/HintHandler.scala @@ -135,7 +135,7 @@ class TLHintHandler(supportManagers: Boolean = true, supportClients: Boolean = f object TLHintHandler { // applied to the TL source node; y.node := TLHintHandler(x.node) - def apply(x: TLBaseNode, supportManagers: Boolean = true, supportClients: Boolean = false, passthrough: Boolean = true)(implicit sourceInfo: SourceInfo): TLBaseNode = { + def apply(supportManagers: Boolean = true, supportClients: Boolean = false, passthrough: Boolean = true)(x: TLBaseNode)(implicit sourceInfo: SourceInfo): TLBaseNode = { val hints = LazyModule(new TLHintHandler(supportManagers, supportClients, passthrough)) hints.node := x hints.node diff --git a/src/main/scala/uncore/tilelink2/WidthWidget.scala b/src/main/scala/uncore/tilelink2/WidthWidget.scala index 87e66903..a555f2a0 100644 --- a/src/main/scala/uncore/tilelink2/WidthWidget.scala +++ b/src/main/scala/uncore/tilelink2/WidthWidget.scala @@ -174,7 +174,7 @@ class TLWidthWidget(innerBeatBytes: Int) extends LazyModule object TLWidthWidget { // applied to the TL source node; y.node := WidthWidget(x.node, 16) - def apply(x: TLBaseNode, innerBeatBytes: Int)(implicit sourceInfo: SourceInfo): TLBaseNode = { + def apply(innerBeatBytes: Int)(x: TLBaseNode)(implicit sourceInfo: SourceInfo): TLBaseNode = { val widget = LazyModule(new TLWidthWidget(innerBeatBytes)) widget.node := x widget.node From 972ca06729152b0d90116afebe1046f3cda00a24 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Thu, 22 Sep 2016 17:51:33 -0700 Subject: [PATCH 2/5] RegField: remove RegField.bytes; it was dangerous The implementation unconditionally drove the register. This made it incompatible with drivers from the device itself. Besides, writing only parts of a register at a time is ultra-shady. --- src/main/scala/uncore/tilelink2/RegField.scala | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/main/scala/uncore/tilelink2/RegField.scala b/src/main/scala/uncore/tilelink2/RegField.scala index 2b372208..365649dc 100644 --- a/src/main/scala/uncore/tilelink2/RegField.scala +++ b/src/main/scala/uncore/tilelink2/RegField.scala @@ -106,21 +106,6 @@ object RegField Bool(true) })) - // 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): 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) } - x := Cat(wires.reverse) - Seq.tabulate(x.getWidth/8) { i => - RegField(8, bytes(i), RegWriteFn { (valid, data) => - when (valid) { wires(i) := data } - Bool(true) - }) - } - } - // 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] = { From 5e34b313ee0c1e4762a3bd8dde1c3eb5fbb4c13d Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Thu, 22 Sep 2016 19:49:29 -0700 Subject: [PATCH 3/5] RegMapper: regmap(...) now takes BYTE addresses If a device has configurable bus-width, we need a stable way of enumerating registers. The byte offset stays unchanged. This change also makes it possible to put an arbitrary number of RegFields starting at some address which are then chopped up into appropriately bus- sized registers. --- src/main/scala/uncore/devices/Prci.scala | 11 ++-- src/main/scala/uncore/tilelink2/Example.scala | 2 +- .../scala/uncore/tilelink2/RegField.scala | 2 + .../scala/uncore/tilelink2/RegMapper.scala | 50 ++++++++++++------- .../uncore/tilelink2/RegisterRouterTest.scala | 20 ++++---- 5 files changed, 49 insertions(+), 36 deletions(-) diff --git a/src/main/scala/uncore/devices/Prci.scala b/src/main/scala/uncore/devices/Prci.scala index ce32e8c2..50315a6d 100644 --- a/src/main/scala/uncore/devices/Prci.scala +++ b/src/main/scala/uncore/devices/Prci.scala @@ -74,14 +74,11 @@ trait CoreplexLocalInterrupterModule extends Module with HasRegMap with MixCorep * bff8 mtime lo * bffc mtime hi */ - val ipi_base = 0 - val timecmp_base = c.timecmpOffset(0) / c.beatBytes - val time_base = c.timeOffset / c.beatBytes - regmap(( - RegField.split(makeRegFields(ipi), ipi_base, c.beatBytes) ++ - RegField.split(makeRegFields(timecmp.flatten), timecmp_base, c.beatBytes) ++ - RegField.split(makeRegFields(time), time_base, c.beatBytes)):_*) + regmap( + 0 -> makeRegFields(ipi), + c.timecmpOffset(0) -> makeRegFields(timecmp.flatten), + c.timeOffset -> makeRegFields(time)) def makeRegFields(s: Seq[UInt]) = s.map(r => RegField(regWidth, r)) } diff --git a/src/main/scala/uncore/tilelink2/Example.scala b/src/main/scala/uncore/tilelink2/Example.scala index fb62bbed..84fa377e 100644 --- a/src/main/scala/uncore/tilelink2/Example.scala +++ b/src/main/scala/uncore/tilelink2/Example.scala @@ -27,7 +27,7 @@ trait ExampleModule extends HasRegMap regmap( 0 -> Seq( RegField(params.num, state)), - 1 -> Seq( + 4 -> Seq( RegField.w1ToClear(4, pending, state))) } diff --git a/src/main/scala/uncore/tilelink2/RegField.scala b/src/main/scala/uncore/tilelink2/RegField.scala index 365649dc..5db870d6 100644 --- a/src/main/scala/uncore/tilelink2/RegField.scala +++ b/src/main/scala/uncore/tilelink2/RegField.scala @@ -85,7 +85,9 @@ case class RegField(width: Int, read: RegReadFn, write: RegWriteFn) object RegField { + // Byte address => sequence of bitfields, lowest index => lowest address type Map = (Int, Seq[RegField]) + def apply(n: Int) : RegField = apply(n, (), ()) def apply(n: Int, rw: UInt) : RegField = apply(n, rw, rw) def r(n: Int, r: RegReadFn) : RegField = apply(n, r, ()) diff --git a/src/main/scala/uncore/tilelink2/RegMapper.scala b/src/main/scala/uncore/tilelink2/RegMapper.scala index 5a661af8..714f416a 100644 --- a/src/main/scala/uncore/tilelink2/RegMapper.scala +++ b/src/main/scala/uncore/tilelink2/RegMapper.scala @@ -29,26 +29,35 @@ object RegMapper { // Create a generic register-based device def apply(bytes: Int, concurrency: Int, undefZero: Boolean, in: DecoupledIO[RegMapperInput], mapping: RegField.Map*) = { - val regmap = mapping.toList.filter(!_._2.isEmpty) - require (!regmap.isEmpty) - - // Ensure no register appears twice - regmap.combinations(2).foreach { case Seq((reg1, _), (reg2, _)) => - require (reg1 != reg2) - } + val bytemap = mapping.toList // Don't be an asshole... - regmap.foreach { reg => require (reg._1 >= 0) } + bytemap.foreach { byte => require (byte._1 >= 0) } + + // Transform all fields into bit offsets Seq[(bit, field)] + val bitmap = bytemap.map { case (byte, fields) => + val bits = fields.scanLeft(byte * 8)(_ + _.width).init + bits zip fields + }.flatten.sortBy(_._1) + + // Detect overlaps + (bitmap.init zip bitmap.tail) foreach { case ((lbit, lfield), (rbit, rfield)) => + require (lbit + lfield.width <= rbit, s"Register map overlaps at bit ${rbit}.") + } + + // Group those fields into bus words Map[word, List[(bit, field)]] + val wordmap = bitmap.groupBy(_._1 / (8*bytes)) + // Make sure registers fit val inParams = in.bits.params val inBits = inParams.indexBits - assert (regmap.map(_._1).max < (1 << inBits)) + assert (wordmap.keySet.max < (1 << inBits), "Register map does not fit in device") val out = Wire(Irrevocable(new RegMapperOutput(inParams))) val front = Wire(Irrevocable(new RegMapperInput(inParams))) front.bits := in.bits // Must this device pipeline the control channel? - val pipelined = regmap.map(_._2.map(_.pipelined)).flatten.reduce(_ || _) + val pipelined = wordmap.values.map(_.map(_._2.pipelined)).flatten.reduce(_ || _) val depth = concurrency require (depth >= 0) require (!pipelined || depth > 0, "Register-based device with request/response handshaking needs concurrency > 0") @@ -60,7 +69,7 @@ object RegMapper def ofBits(bits: List[Boolean]) = bits.foldRight(0){ case (x,y) => (if (x) 1 else 0) | y << 1 } // Find the minimal mask that can decide the register map - val mask = AddressDecoder(regmap.map(_._1)) + val mask = AddressDecoder(wordmap.keySet.toList) val maskMatch = ~UInt(mask, width = inBits) val maskFilter = toBits(mask) val maskBits = maskFilter.filter(x => x).size @@ -75,17 +84,22 @@ object RegMapper val iRightReg = Array.fill(regSize) { Bool(true) } val oRightReg = Array.fill(regSize) { Bool(true) } - // Flatten the regmap into (RegIndex:Int, Offset:Int, field:RegField) - val flat = regmap.map { case (reg, fields) => - val offsets = fields.scanLeft(0)(_ + _.width).init - val index = regIndexI(reg) - val uint = UInt(reg, width = inBits) + // Transform the wordmap into minimal decoded indexes, Seq[(index, bit, field)] + val flat = wordmap.toList.map { case (word, fields) => + val index = regIndexI(word) + val uint = UInt(word, width = inBits) if (undefZero) { iRightReg(index) = ((front.bits.index ^ uint) & maskMatch) === UInt(0) oRightReg(index) = ((back .bits.index ^ uint) & maskMatch) === UInt(0) } - // println("mapping 0x%x -> 0x%x for 0x%x/%d".format(reg, index, mask, maskBits)) - (offsets zip fields) map { case (o, f) => (index, o, f) } + // Confirm that no field spans a word boundary + fields foreach { case (bit, field) => + val off = bit - 8*bytes*word + // println(s"Reg ${word}: [${off}, ${off+field.width})") + require (off + field.width <= bytes * 8, s"Field at word ${word}*(${bytes}B) has bits [${off}, ${off+field.width}), which exceeds word limit.") + } + // println("mapping 0x%x -> 0x%x for 0x%x/%d".format(word, index, mask, maskBits)) + fields.map { case (bit, field) => (index, bit-8*bytes*word, field) } }.flatten // Forward declaration of all flow control signals diff --git a/src/main/scala/uncore/tilelink2/RegisterRouterTest.scala b/src/main/scala/uncore/tilelink2/RegisterRouterTest.scala index 395bae81..36297152 100644 --- a/src/main/scala/uncore/tilelink2/RegisterRouterTest.scala +++ b/src/main/scala/uncore/tilelink2/RegisterRouterTest.scala @@ -183,14 +183,14 @@ object RRTest0Map // All fields must respect byte alignment, or else it won't behave like an SRAM val map = Seq( - 0 -> Seq(aa(8), ar(8), ad(8), ae(8)), - 1 -> Seq(ra(8), rr(8), rd(8), re(8)), - 2 -> Seq(da(8), dr(8), dd(8), de(8)), - 3 -> Seq(ea(8), er(8), ed(8), ee(8)), - 4 -> Seq(aa(3), ar(5), ad(1), ae(7), ra(2), rr(6), rd(4), re(4)), - 5 -> Seq(da(3), dr(5), dd(1), de(7), ea(2), er(6), ed(4), ee(4)), - 6 -> Seq(aa(8), rr(8), dd(8), ee(8)), - 7 -> Seq(ar(8), rd(8), de(8), ea(8))) + 0 -> Seq(aa(8), ar(8), ad(8), ae(8)), + 4 -> Seq(ra(8), rr(8), rd(8), re(8)), + 8 -> Seq(da(8), dr(8), dd(8), de(8)), + 12 -> Seq(ea(8), er(8), ed(8), ee(8)), + 16 -> Seq(aa(3), ar(5), ad(1), ae(7), ra(2), rr(6), rd(4), re(4)), + 20 -> Seq(da(3), dr(5), dd(1), de(7), ea(2), er(6), ed(4), ee(4)), + 24 -> Seq(aa(8), rr(8), dd(8), ee(8)), + 28 -> Seq(ar(8), rd(8), de(8), ea(8))) } object RRTest1Map @@ -203,8 +203,8 @@ object RRTest1Map def bb(bits: Int) = request(bits, busy, busy) val map = RRTest0Map.map.take(6) ++ Seq( - 6 -> Seq(pp(8), pb(8), bp(8), bb(8)), - 7 -> Seq(pp(3), pb(5), bp(1), bb(7), pb(5), bp(3), pp(4), bb(4))) + 24 -> Seq(pp(8), pb(8), bp(8), bb(8)), + 28 -> Seq(pp(3), pb(5), bp(1), bb(7), pb(5), bp(3), pp(4), bb(4))) } trait RRTest0Bundle From fc44151f10ad7117b70ca94cd25569739498f2ea Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Thu, 22 Sep 2016 19:59:35 -0700 Subject: [PATCH 4/5] RegField: add name and description fields In the future we can generate interesting documentation and headers. --- src/main/scala/uncore/tilelink2/RegField.scala | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/main/scala/uncore/tilelink2/RegField.scala b/src/main/scala/uncore/tilelink2/RegField.scala index 5db870d6..715c64ae 100644 --- a/src/main/scala/uncore/tilelink2/RegField.scala +++ b/src/main/scala/uncore/tilelink2/RegField.scala @@ -77,7 +77,7 @@ object RegWriteFn implicit def apply(x: Unit): RegWriteFn = RegWriteFn((valid, data) => { Bool(true) }) } -case class RegField(width: Int, read: RegReadFn, write: RegWriteFn) +case class RegField(width: Int, read: RegReadFn, write: RegWriteFn, name: String, description: String) { require (width > 0) def pipelined = !read.combinational || !write.combinational @@ -88,10 +88,12 @@ object RegField // Byte address => sequence of bitfields, lowest index => lowest address type Map = (Int, Seq[RegField]) - def apply(n: Int) : RegField = apply(n, (), ()) - def apply(n: Int, rw: UInt) : RegField = apply(n, rw, rw) - def r(n: Int, r: RegReadFn) : RegField = apply(n, r, ()) - def w(n: Int, w: RegWriteFn) : RegField = apply(n, (), w) + def apply(n: Int) : RegField = apply(n, (), (), "", "") + def apply(n: Int, r: RegReadFn, w: RegWriteFn) : RegField = apply(n, r, w, "", "") + def apply(n: Int, rw: UInt) : RegField = apply(n, rw, rw, "", "") + def apply(n: Int, rw: UInt, name: String, description: String) : RegField = apply(n, rw, rw, name, description) + def r(n: Int, r: RegReadFn, name: String = "", description: String = "") : RegField = apply(n, r, (), name, description) + def w(n: Int, w: RegWriteFn, name: String = "", description: String = "") : RegField = apply(n, (), w, name, description) // This RegField allows 'set' to set bits in 'reg'. // and to clear bits when the bus writes bits of value 1. From c5706afc1148c8989200f7d873d4b1537a9db7e0 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Thu, 22 Sep 2016 20:00:49 -0700 Subject: [PATCH 5/5] RegField: remove obsolete split method This is now natively supported by the regmap(...) invocation. --- src/main/scala/uncore/tilelink2/RegField.scala | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/main/scala/uncore/tilelink2/RegField.scala b/src/main/scala/uncore/tilelink2/RegField.scala index 715c64ae..e33dc3a8 100644 --- a/src/main/scala/uncore/tilelink2/RegField.scala +++ b/src/main/scala/uncore/tilelink2/RegField.scala @@ -109,13 +109,6 @@ object RegField bb.d := data Bool(true) })) - - // 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