From cbf06701566cef7888b6bf8db4052f273cec63f7 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Thu, 8 Sep 2016 19:32:00 -0700 Subject: [PATCH 1/3] tilelink2 Legacy: it's only an error if it's valid --- src/main/scala/uncore/tilelink2/Legacy.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/uncore/tilelink2/Legacy.scala b/src/main/scala/uncore/tilelink2/Legacy.scala index d21503cb..99ccc2fe 100644 --- a/src/main/scala/uncore/tilelink2/Legacy.scala +++ b/src/main/scala/uncore/tilelink2/Legacy.scala @@ -107,7 +107,7 @@ class TLLegacy(implicit val p: Parameters) extends LazyModule with HasTileLinkPa out.a.bits.addr_hi := ~(~address | addressMask) >> log2Ceil(tlDataBytes) // TL legacy does not support bus errors - assert (!out.d.bits.error) + assert (!out.d.valid || !out.d.bits.error) // Recreate the beat address counter val beatCounter = RegInit(UInt(0, width = tlBeatAddrBits)) From c1eb1f12a208acce2a48587b1a91644a045c78f5 Mon Sep 17 00:00:00 2001 From: Megan Wachs Date: Thu, 8 Sep 2016 13:49:29 -0700 Subject: [PATCH 2/3] tilelink2: Rename GPIO to Example to avoid conflicts with real GPIO devices --- src/main/scala/uncore/tilelink2/Example.scala | 29 +++++++++++++++++++ src/main/scala/uncore/tilelink2/GPIO.scala | 29 ------------------- 2 files changed, 29 insertions(+), 29 deletions(-) create mode 100644 src/main/scala/uncore/tilelink2/Example.scala delete mode 100644 src/main/scala/uncore/tilelink2/GPIO.scala diff --git a/src/main/scala/uncore/tilelink2/Example.scala b/src/main/scala/uncore/tilelink2/Example.scala new file mode 100644 index 00000000..a9fe6c56 --- /dev/null +++ b/src/main/scala/uncore/tilelink2/Example.scala @@ -0,0 +1,29 @@ +// See LICENSE for license details. + +package uncore.tilelink2 + +import Chisel._ + +case class ExampleParams(num: Int, address: BigInt) + +trait ExampleBundle +{ + val params: ExampleParams + val gpio = UInt(width = params.num) +} + +trait ExampleModule extends HasRegMap +{ + val params: ExampleParams + val io: ExampleBundle + + val state = RegInit(UInt(0)) + io.gpio := state + + regmap(0 -> Seq(RegField(params.num, state))) +} + +// Create a concrete TL2 version of the abstract Example slave +class TLExample(p: ExampleParams) extends TLRegisterRouter(p.address)( + new TLRegBundle(p, _) with ExampleBundle)( + new TLRegModule(p, _, _) with ExampleModule) diff --git a/src/main/scala/uncore/tilelink2/GPIO.scala b/src/main/scala/uncore/tilelink2/GPIO.scala deleted file mode 100644 index a9050882..00000000 --- a/src/main/scala/uncore/tilelink2/GPIO.scala +++ /dev/null @@ -1,29 +0,0 @@ -// See LICENSE for license details. - -package uncore.tilelink2 - -import Chisel._ - -case class GPIOParams(num: Int, address: BigInt) - -trait GPIOBundle -{ - val params: GPIOParams - val gpio = UInt(width = params.num) -} - -trait GPIOModule extends HasRegMap -{ - val params: GPIOParams - val io: GPIOBundle - - val state = RegInit(UInt(0)) - io.gpio := state - - regmap(0 -> Seq(RegField(params.num, state))) -} - -// Create a concrete TL2 version of the abstract GPIO slave -class TLGPIO(p: GPIOParams) extends TLRegisterRouter(p.address)( - new TLRegBundle(p, _) with GPIOBundle)( - new TLRegModule(p, _, _) with GPIOModule) From fda4c2bd7696d79444b094cae2af6c9267f43534 Mon Sep 17 00:00:00 2001 From: Megan Wachs Date: Thu, 8 Sep 2016 20:01:03 -0700 Subject: [PATCH 3/3] Add a way to create Async Reset Registers and a way to easily access them with TL2 --- .../scala/uncore/tilelink2/RegField.scala | 11 +++ src/main/scala/uncore/util/BlackBoxRegs.scala | 84 +++++++++++++++++++ vsim/Makefrag | 3 +- vsrc/AsyncResetReg.v | 51 +++++++++++ 4 files changed, 148 insertions(+), 1 deletion(-) create mode 100644 src/main/scala/uncore/util/BlackBoxRegs.scala create mode 100644 vsrc/AsyncResetReg.v diff --git a/src/main/scala/uncore/tilelink2/RegField.scala b/src/main/scala/uncore/tilelink2/RegField.scala index 32a65c0d..d4b34743 100644 --- a/src/main/scala/uncore/tilelink2/RegField.scala +++ b/src/main/scala/uncore/tilelink2/RegField.scala @@ -4,6 +4,8 @@ package uncore.tilelink2 import Chisel._ +import uncore.util.{SimpleRegIO} + case class RegReadFn private(combinational: Boolean, fn: (Bool, Bool) => (Bool, Bool, UInt)) object RegReadFn { @@ -81,6 +83,15 @@ object RegField // Setting takes priority over clearing. def w1ToClear(n: Int, reg: UInt, set: UInt): RegField = RegField(n, reg, RegWriteFn((valid, data) => { reg := ~(~reg | Mux(valid, data, UInt(0))) | set; Bool(true) })) + + // This RegField wraps an explicit register + // (e.g. Black-Boxed Register) to create a R/W register. + def rwReg(n: Int, bb: SimpleRegIO) : RegField = + RegField(n, bb.q, RegWriteFn((valid, data) => { + bb.en := valid + bb.d := data + Bool(true) + })) } trait HasRegMap diff --git a/src/main/scala/uncore/util/BlackBoxRegs.scala b/src/main/scala/uncore/util/BlackBoxRegs.scala new file mode 100644 index 00000000..21fe09f0 --- /dev/null +++ b/src/main/scala/uncore/util/BlackBoxRegs.scala @@ -0,0 +1,84 @@ +package uncore.util + +import Chisel._ + +import cde.{Parameters} +import junctions.{ParameterizedBundle} + +/** This black-boxes an Async Reset + * Reg. + * + * Because Chisel doesn't support + * parameterized black boxes, + * we unfortunately have to + * instantiate a number of these. + * + * Do not confuse an asynchronous + * reset signal with an asynchronously + * reset reg. You should still + * properly synchronize your reset + * deassertion. + * + * @param d Data input + * @param q Data Output + * @param clk Clock Input + * @param rst Reset Input + * + * @param init Value to write at Reset. + * This is a constant, + * but this construction + * will likely make backend flows + * and lint tools unhappy. + * + */ + +class AsyncResetReg extends BlackBox { + + val io = new Bundle { + val d = Bool(INPUT) + val q = Bool(OUTPUT) + + val clk = Clock(INPUT) + val rst = Bool(INPUT) + + val init = Bool(INPUT) + } + +} + + +class SimpleRegIO(val w: Int)(implicit val p: Parameters) extends ParameterizedBundle()(p){ + + val d = UInt(INPUT, width = w) + val q = UInt(OUTPUT, width = w) + + val en = Bool(INPUT) + +} + +class AsyncResetRegVec(val w: Int, val init: Int)(implicit val p: Parameters) extends Module { + + val io = new SimpleRegIO(w)(p) + + val bb_q = Wire(UInt(width = w)) + val bb_d = Wire(UInt(width = w)) + + val init_val = Wire(UInt(width = w)) + init_val := UInt(init, width = w) + + val async_regs = List.fill(w)(Module (new AsyncResetReg)) + + bb_q := (async_regs.map(_.io.q)).asUInt() + bb_d := Mux(io.en , io.d , bb_q) + + io.q := bb_q + + + for ((reg, idx) <- async_regs.zipWithIndex) { + reg.io.clk := clock + reg.io.rst := reset + reg.io.init := init_val(idx) + reg.io.d := bb_d(idx) + } + +} diff --git a/vsim/Makefrag b/vsim/Makefrag index a2f5559d..3abb2b4e 100644 --- a/vsim/Makefrag +++ b/vsim/Makefrag @@ -6,7 +6,8 @@ bb_vsrcs = $(base_dir)/vsrc/DebugTransportModuleJtag.v \ $(base_dir)/vsrc/jtag_vpi.v \ - $(base_dir)/vsrc/AsyncMailbox.v + $(base_dir)/vsrc/AsyncMailbox.v \ + $(base_dir)/vsrc/AsyncResetReg.v sim_vsrcs = \ $(generated_dir)/$(MODEL).$(CONFIG).v \ diff --git a/vsrc/AsyncResetReg.v b/vsrc/AsyncResetReg.v new file mode 100644 index 00000000..3adf16b1 --- /dev/null +++ b/vsrc/AsyncResetReg.v @@ -0,0 +1,51 @@ + + +/** This black-boxes an Async Reset + * Reg. + * + * Because Chisel doesn't support + * parameterized black boxes, + * we unfortunately have to + * instantiate a number of these. + * + * Do not confuse an asynchronous + * reset signal with an asynchronously + * reset reg. You should still + * properly synchronize your reset + * deassertion. + * + * @param d Data input + * @param q Data Output + * @param clk Clock Input + * @param rst Reset Input + * + * @param init Value to write at Reset. + * This is a constant, + * but this construction + * will likely make backend flows + * and lint tools unhappy. + * + */ + +module AsyncResetReg ( + input d, + output reg q, + + input clk, + input rst, + + input init); + + always @(posedge clk or posedge rst) begin + + if (rst) begin + q <= init; + end else begin + q <= d; + end + + end + + +endmodule // AsyncResetReg +