diff --git a/build.sc b/build.sc index 8baed34e596..da98c7ce2ae 100644 --- a/build.sc +++ b/build.sc @@ -6,6 +6,7 @@ import $file.dependencies.hardfloat.common import $file.dependencies.cde.common import $file.dependencies.diplomacy.common import $file.dependencies.chisel.build +import $file.rocketutils.{common => utilsCommon} import $file.common object v { @@ -25,6 +26,29 @@ object v { ) } +object rocketutils extends Module { + + object rocketutils extends Cross[rocketutils](v.chiselCrossVersions.view.filterKeys(_ != "source").keys.toSeq) + + trait rocketutils extends utilsCommon.ChiselCrossModule with RocketChipPublishModule{ + def scalaVersion = T(v.scala) + + def moduleDeps = super.moduleDeps ++ Seq(cde, diplomacy(crossValue)) + def ivyDeps = T(super.ivyDeps() ++ Agg(v.json4sJackson)) + } + + object rocketutilsSourceMod extends utilsCommon.ChiselSourceModule with RocketChipPublishModule { + def millSourcePath = millOuterCtx.millSourcePath / "rocketutils" + + def scalaVersion = T(v.scala) + + def chiselModule = chisel + def chiselPluginJar = T(chiselModule.pluginModule.jar()) + + def moduleDeps = super.moduleDeps ++ Seq(cde, diplomacy("source")) + } +} + // Build form source only for dev object chisel extends Chisel @@ -131,6 +155,14 @@ trait RocketChip def cdeModule = cde + def rocketUtilsModule = { + if (crossValue == "source") { + rocketutils.rocketutilsSourceMod + } else { + rocketutils.rocketutils(crossValue) + } + } + def diplomacyModule = diplomacy(crossValue) def diplomacyIvy = None diff --git a/common.sc b/common.sc index d11edcc116a..c9c805a9fc3 100644 --- a/common.sc +++ b/common.sc @@ -38,6 +38,8 @@ trait RocketChipModule override def mainClass = T(Some("freechips.rocketchip.diplomacy.Main")) def macrosModule: MacrosModule + + def rocketUtilsModule: ScalaModule // should be hardfloat/common.sc#HardfloatModule def hardfloatModule: ScalaModule @@ -48,7 +50,7 @@ trait RocketChipModule def json4sJacksonIvy: Dep - override def moduleDeps = super.moduleDeps ++ Seq(macrosModule, hardfloatModule, diplomacyModule) + override def moduleDeps = super.moduleDeps ++ Seq(macrosModule, hardfloatModule, diplomacyModule, rocketUtilsModule) override def ivyDeps = T( super.ivyDeps() ++ Agg( diff --git a/rocketutils/build.sc b/rocketutils/build.sc new file mode 100644 index 00000000000..2e12e39be49 --- /dev/null +++ b/rocketutils/build.sc @@ -0,0 +1,36 @@ +import mill._ +import mill.scalalib._ + +import $file.common + +val scala = "2.13.12" +val chisel = "6.3.0" + +val json4sJackson = ivy"org.json4s::json4s-jackson:4.0.5" +val sourcecode = ivy"com.lihaoyi::sourcecode:0.3.1" + +object dependencies extends Module { + object cde extends ScalaModule { + def scalaVersion: T[String] = T(scala) + def millSourcePath = super.millSourcePath / "cde" + } + + object diplomacy extends Cross[DiplomacyCross](chisel) + + trait DiplomacyCross extends common.ChiselCrossModule { + def scalaVersion: T[String] = T(scala) + def millSourcePath = super.millSourcePath / "diplomacy" + def moduleDeps = super.moduleDeps ++ Seq(cde) + def ivyDeps = T(super.ivyDeps() ++ Agg(sourcecode)) + } +} + +object rocketutils extends Cross[RocketutilsCross](chisel) + +trait RocketutilsCross extends common.ChiselCrossModule { + def scalaVersion = T(scala) + + def moduleDeps = super.moduleDeps ++ Seq(dependencies.cde, dependencies.diplomacy(crossValue)) + + def ivyDeps = T(super.ivyDeps() ++ Agg(json4sJackson)) +} diff --git a/rocketutils/common.sc b/rocketutils/common.sc new file mode 100644 index 00000000000..28252c0a6d1 --- /dev/null +++ b/rocketutils/common.sc @@ -0,0 +1,29 @@ +import mill._ +import mill.scalalib._ + +trait ChiselModule extends ScalaModule { + def scalaVersion: T[String] + def chiselVersion: T[String] + + def ivyDeps = T(super.ivyDeps() ++ Some(ivy"org.chipsalliance::chisel:${chiselVersion()}")) + def scalacPluginIvyDeps = T(super.ivyDeps() ++ Agg(ivy"org.chipsalliance:::chisel-plugin:${chiselVersion()}")) +} + +trait ChiselCrossModule extends ScalaModule with Cross.Module[String] { + def scalaVersion: T[String] + def chiselVersion: T[String] = T(crossValue) + + def ivyDeps = T(super.ivyDeps() ++ Some(ivy"org.chipsalliance::chisel:${chiselVersion()}")) + def scalacPluginIvyDeps = T(super.ivyDeps() ++ Agg(ivy"org.chipsalliance:::chisel-plugin:${chiselVersion()}")) +} + +trait ChiselSourceModule extends ScalaModule { + def scalaVersion: T[String] + + def chiselModule: ScalaModule + def chiselPluginJar: T[PathRef] + + def moduleDeps = super.moduleDeps ++ Agg(chiselModule) + def scalacOptions = T(super.scalacOptions() ++ Seq(s"-Xplugin:${chiselPluginJar().path}")) + def scalacPluginClasspath: T[Agg[PathRef]] = T(super.scalacPluginClasspath() ++ Agg(chiselPluginJar())) +} diff --git a/rocketutils/rocketutils/src/rocketutils/Annotations.scala b/rocketutils/rocketutils/src/rocketutils/Annotations.scala new file mode 100644 index 00000000000..ae64f688cd4 --- /dev/null +++ b/rocketutils/rocketutils/src/rocketutils/Annotations.scala @@ -0,0 +1,126 @@ +// See LICENSE.SiFive for license details. + +package org.chipsalliance.rocketutils + +import chisel3._ +import chisel3.experimental.{annotate, ChiselAnnotation} + +import firrtl.annotations._ + +/** Record a sram. */ +case class SRAMAnnotation(target: Named, + address_width: Int, + name: String, + data_width: Int, + depth: BigInt, + description: String, + write_mask_granularity: Int) extends SingleTargetAnnotation[Named] { + def duplicate(n: Named) = this.copy(n) +} + +/** Record a set of interrupts. */ +case class InterruptsPortAnnotation(target: Named, name: String, interruptIndexes: Seq[Int]) extends SingleTargetAnnotation[Named] { + def duplicate(n: Named) = this.copy(n) +} + +/** Record a case class that was used to parameterize this target. */ +case class GlobalConstantsAnnotation(target: Named, xLen: Int) extends SingleTargetAnnotation[Named] { + def duplicate(n: Named) = this.copy(n) +} + +case class GlobalConstantsChiselAnnotation[T <: Product](target: InstanceId, xLen: Int) extends ChiselAnnotation { + def toFirrtl = GlobalConstantsAnnotation(target.toNamed, xLen) +} + +/** Record a case class that was used to parameterize this target. */ +case class ParamsAnnotation(target: Named, paramsClassName: String, params: Map[String,Any]) extends SingleTargetAnnotation[Named] { + def duplicate(n: Named) = this.copy(n) +} + +case class ParamsChiselAnnotation[T <: Product](target: InstanceId, params: T) extends ChiselAnnotation { + private val paramMap = params.getClass.getDeclaredFields.map(_.getName).zip(params.productIterator).toMap + def toFirrtl = ParamsAnnotation(target.toNamed, params.getClass.getName, paramMap) +} + +/** Marks this module as a candidate for register retiming */ +case class RetimeModuleAnnotation(target: ModuleName) extends SingleTargetAnnotation[ModuleName] { + def duplicate(n: ModuleName) = this.copy(n) +} + +/** Record the resetVector. */ +case class ResetVectorAnnotation(target: Named, resetVec: BigInt) extends SingleTargetAnnotation[Named] { + def duplicate(n: Named): ResetVectorAnnotation = this.copy(n) +} + +/** Helper object containing methods for applying annotations to targets */ +object Annotated { + + def srams( + component: InstanceId, + name: String, + address_width: Int, + data_width: Int, + depth: BigInt, + description: String, + write_mask_granularity: Int): Unit = { + annotate(new ChiselAnnotation {def toFirrtl: Annotation = SRAMAnnotation( + component.toNamed, + address_width = address_width, + name = name, + data_width = data_width, + depth = depth, + description = description, + write_mask_granularity = write_mask_granularity + )})} + + def interrupts(component: InstanceId, name: String, interrupts: Seq[Int]): Unit = { + annotate(new ChiselAnnotation {def toFirrtl: Annotation = InterruptsPortAnnotation( + component.toNamed, + name, + interrupts + )}) + } + + def resetVector(component: InstanceId, resetVec: BigInt): Unit = { + annotate(new ChiselAnnotation {def toFirrtl: Annotation = ResetVectorAnnotation(component.toNamed, resetVec)}) + } + + def constants(component: InstanceId, xLen: Int): Unit = { + annotate(GlobalConstantsChiselAnnotation(component, xLen )) + } + + def params[T <: Product](component: InstanceId, params: T): T = { + annotate(ParamsChiselAnnotation(component, params)) + params + } +} + +/** Mix this into a Module class or instance to mark its ports as untouchable */ +trait DontTouch { self: RawModule => + // TODO: replace this with an implicit class from UserModule that uses getPorts + // TODO: this is a workaround for firrtl #756 + def dontTouch(data: Data): Unit = data match { + case agg: Aggregate => agg.getElements.foreach(dontTouch) + case elt: Element => chisel3.dontTouch(elt) + } + + /** Marks every port as don't touch + * + * @note This method can only be called after the Module has been fully constructed + * (after Module(...)) + */ + def dontTouchPorts(): this.type = { + self.getModulePorts.foreach(dontTouch(_)) + self + } + + def dontTouchPortsExcept(f: Data => Boolean): this.type = { + self.getModulePorts.filterNot(f).foreach(dontTouch(_)) + self + } +} + +/** Mix this into a Module class or instance to mark it for register retiming */ +trait ShouldBeRetimed { self: RawModule => + chisel3.experimental.annotate(new ChiselAnnotation { def toFirrtl: RetimeModuleAnnotation = RetimeModuleAnnotation(self.toNamed) }) +} diff --git a/rocketutils/rocketutils/src/rocketutils/Arbiters.scala b/rocketutils/rocketutils/src/rocketutils/Arbiters.scala new file mode 100644 index 00000000000..c03af124314 --- /dev/null +++ b/rocketutils/rocketutils/src/rocketutils/Arbiters.scala @@ -0,0 +1,146 @@ +// See LICENSE.Berkeley for license details. + +package org.chipsalliance.rocketutils + +import chisel3._ +import chisel3.util._ +import org.chipsalliance.cde.config.Parameters + +/** A generalized locking RR arbiter that addresses the limitations of the + * version in the Chisel standard library */ +abstract class HellaLockingArbiter[T <: Data](typ: T, arbN: Int, rr: Boolean = false) + extends Module { + + val io = IO(new Bundle { + val in = Flipped(Vec(arbN, Decoupled(typ.cloneType))) + val out = Decoupled(typ.cloneType) + }) + + def rotateLeft[T <: Data](norm: Vec[T], rot: UInt): Vec[T] = { + val n = norm.size + VecInit.tabulate(n) { i => + Mux(rot < (n - i).U, norm(i.U + rot), norm(rot - (n - i).U)) + } + } + + val lockIdx = RegInit(0.U(log2Up(arbN).W)) + val locked = RegInit(false.B) + + val choice = if (rr) { + PriorityMux( + rotateLeft(VecInit(io.in.map(_.valid)), lockIdx + 1.U), + rotateLeft(VecInit((0 until arbN).map(_.U)), lockIdx + 1.U)) + } else { + PriorityEncoder(io.in.map(_.valid)) + } + + val chosen = Mux(locked, lockIdx, choice) + + for (i <- 0 until arbN) { + io.in(i).ready := io.out.ready && chosen === i.U + } + + io.out.valid := io.in(chosen).valid + io.out.bits := io.in(chosen).bits +} + +/** This locking arbiter determines when it is safe to unlock + * by peeking at the data */ +class HellaPeekingArbiter[T <: Data]( + typ: T, arbN: Int, + canUnlock: T => Bool, + needsLock: Option[T => Bool] = None, + rr: Boolean = false) + extends HellaLockingArbiter(typ, arbN, rr) { + + def realNeedsLock(data: T): Bool = + needsLock.map(_(data)).getOrElse(true.B) + + when (io.out.fire) { + when (!locked && realNeedsLock(io.out.bits)) { + lockIdx := choice + locked := true.B + } + // the unlock statement takes precedent + when (canUnlock(io.out.bits)) { + locked := false.B + } + } +} + +/** This arbiter determines when it is safe to unlock by counting transactions */ +class HellaCountingArbiter[T <: Data]( + typ: T, arbN: Int, count: Int, + val needsLock: Option[T => Bool] = None, + rr: Boolean = false) + extends HellaLockingArbiter(typ, arbN, rr) { + + def realNeedsLock(data: T): Bool = + needsLock.map(_(data)).getOrElse(true.B) + + // if count is 1, you should use a non-locking arbiter + require(count > 1, "CountingArbiter cannot have count <= 1") + + val lock_ctr = Counter(count) + + when (io.out.fire) { + when (!locked && realNeedsLock(io.out.bits)) { + lockIdx := choice + locked := true.B + lock_ctr.inc() + } + + when (locked) { + when (lock_ctr.inc()) { locked := false.B } + } + } +} + +/** This arbiter preserves the order of responses */ +class InOrderArbiter[T <: Data, U <: Data](reqTyp: T, respTyp: U, n: Int) + (implicit p: Parameters) extends Module { + val io = IO(new Bundle { + val in_req = Flipped(Vec(n, Decoupled(reqTyp))) + val in_resp = Vec(n, Decoupled(respTyp)) + val out_req = Decoupled(reqTyp) + val out_resp = Flipped(Decoupled(respTyp)) + }) + + if (n > 1) { + val route_q = Module(new Queue(UInt(log2Up(n).W), 2)) + val req_arb = Module(new RRArbiter(reqTyp, n)) + req_arb.io.in <> io.in_req + + val req_helper = DecoupledHelper( + req_arb.io.out.valid, + route_q.io.enq.ready, + io.out_req.ready) + + io.out_req.bits := req_arb.io.out.bits + io.out_req.valid := req_helper.fire(io.out_req.ready) + + route_q.io.enq.bits := req_arb.io.chosen + route_q.io.enq.valid := req_helper.fire(route_q.io.enq.ready) + + req_arb.io.out.ready := req_helper.fire(req_arb.io.out.valid) + + val resp_sel = route_q.io.deq.bits + val resp_ready = io.in_resp(resp_sel).ready + val resp_helper = DecoupledHelper( + resp_ready, + route_q.io.deq.valid, + io.out_resp.valid) + + val resp_valid = resp_helper.fire(resp_ready) + for (i <- 0 until n) { + io.in_resp(i).bits := io.out_resp.bits + io.in_resp(i).valid := resp_valid && resp_sel === i.U + } + + route_q.io.deq.ready := resp_helper.fire(route_q.io.deq.valid) + io.out_resp.ready := resp_helper.fire(io.out_resp.valid) + } else { + io.out_req <> io.in_req.head + io.in_resp.head <> io.out_resp + } +} diff --git a/rocketutils/rocketutils/src/rocketutils/AsyncQueue.scala b/rocketutils/rocketutils/src/rocketutils/AsyncQueue.scala new file mode 100644 index 00000000000..1965a9e3d87 --- /dev/null +++ b/rocketutils/rocketutils/src/rocketutils/AsyncQueue.scala @@ -0,0 +1,232 @@ +// See LICENSE.SiFive for license details. + +package org.chipsalliance.rocketutils + +import chisel3._ +import chisel3.util._ + +import org.chipsalliance.rocketutils.conversions._ + +case class AsyncQueueParams( + depth: Int = 8, + sync: Int = 3, + safe: Boolean = true, +// If safe is true, then effort is made to resynchronize the crossing indices when either side is reset. +// This makes it safe/possible to reset one side of the crossing (but not the other) when the queue is empty. + narrow: Boolean = false) +// If narrow is true then the read mux is moved to the source side of the crossing. +// This reduces the number of level shifters in the case where the clock crossing is also a voltage crossing, +// at the expense of a combinational path from the sink to the source and back to the sink. +{ + require (depth > 0 && isPow2(depth)) + require (sync >= 2) + + val bits = log2Ceil(depth) + val wires = if (narrow) 1 else depth +} + +object AsyncQueueParams { + // When there is only one entry, we don't need narrow. + def singleton(sync: Int = 3, safe: Boolean = true) = AsyncQueueParams(1, sync, safe, false) +} + +class AsyncBundleSafety extends Bundle { + val ridx_valid = Input (Bool()) + val widx_valid = Output(Bool()) + val source_reset_n = Output(Bool()) + val sink_reset_n = Input (Bool()) +} + +class AsyncBundle[T <: Data](private val gen: T, val params: AsyncQueueParams = AsyncQueueParams()) extends Bundle { + // Data-path synchronization + val mem = Output(Vec(params.wires, gen)) + val ridx = Input (UInt((params.bits+1).W)) + val widx = Output(UInt((params.bits+1).W)) + val index = params.narrow.option(Input(UInt(params.bits.W))) + + // Signals used to self-stabilize a safe AsyncQueue + val safe = params.safe.option(new AsyncBundleSafety) +} + +object GrayCounter { + def apply(bits: Int, increment: Bool = true.B, clear: Bool = false.B, name: String = "binary"): UInt = { + val incremented = Wire(UInt(bits.W)) + val binary = RegNext(next=incremented, init=0.U).suggestName(name) + incremented := Mux(clear, 0.U, binary + increment.asUInt) + incremented ^ (incremented >> 1) + } +} + +class AsyncValidSync(sync: Int, desc: String) extends RawModule { + val io = IO(new Bundle { + val in = Input(Bool()) + val out = Output(Bool()) + }) + val clock = IO(Input(Clock())) + val reset = IO(Input(AsyncReset())) + withClockAndReset(clock, reset){ + io.out := AsyncResetSynchronizerShiftReg(io.in, sync, Some(desc)) + } +} + +class AsyncQueueSource[T <: Data](gen: T, params: AsyncQueueParams = AsyncQueueParams()) extends Module { + val io = IO(new Bundle { + // These come from the source domain + val enq = Flipped(Decoupled(gen)) + // These cross to the sink clock domain + val async = new AsyncBundle(gen, params) + }) + + val bits = params.bits + val sink_ready = WireInit(true.B) + val mem = Reg(Vec(params.depth, gen)) // This does NOT need to be reset at all. + val widx = withReset(reset.asAsyncReset)(GrayCounter(bits+1, io.enq.fire, !sink_ready, "widx_bin")) + val ridx = AsyncResetSynchronizerShiftReg(io.async.ridx, params.sync, Some("ridx_gray")) + val ready = sink_ready && widx =/= (ridx ^ (params.depth | params.depth >> 1).U) + + val index = if (bits == 0) 0.U else io.async.widx(bits-1, 0) ^ (io.async.widx(bits, bits) << (bits-1)) + when (io.enq.fire) { mem(index) := io.enq.bits } + + val ready_reg = withReset(reset.asAsyncReset)(RegNext(next=ready, init=false.B).suggestName("ready_reg")) + io.enq.ready := ready_reg && sink_ready + + val widx_reg = withReset(reset.asAsyncReset)(RegNext(next=widx, init=0.U).suggestName("widx_gray")) + io.async.widx := widx_reg + + io.async.index match { + case Some(index) => io.async.mem(0) := mem(index) + case None => io.async.mem := mem + } + + io.async.safe.foreach { sio => + val source_valid_0 = Module(new AsyncValidSync(params.sync, "source_valid_0")) + val source_valid_1 = Module(new AsyncValidSync(params.sync, "source_valid_1")) + + val sink_extend = Module(new AsyncValidSync(params.sync, "sink_extend")) + val sink_valid = Module(new AsyncValidSync(params.sync, "sink_valid")) + source_valid_0.reset := (reset.asBool || !sio.sink_reset_n).asAsyncReset + source_valid_1.reset := (reset.asBool || !sio.sink_reset_n).asAsyncReset + sink_extend .reset := (reset.asBool || !sio.sink_reset_n).asAsyncReset + sink_valid .reset := reset.asAsyncReset + + source_valid_0.clock := clock + source_valid_1.clock := clock + sink_extend .clock := clock + sink_valid .clock := clock + + source_valid_0.io.in := true.B + source_valid_1.io.in := source_valid_0.io.out + sio.widx_valid := source_valid_1.io.out + sink_extend.io.in := sio.ridx_valid + sink_valid.io.in := sink_extend.io.out + sink_ready := sink_valid.io.out + sio.source_reset_n := !reset.asBool + + // Assert that if there is stuff in the queue, then reset cannot happen + // Impossible to write because dequeue can occur on the receiving side, + // then reset allowed to happen, but write side cannot know that dequeue + // occurred. + // TODO: write some sort of sanity check assertion for users + // that denote don't reset when there is activity + // assert (!(reset || !sio.sink_reset_n) || !io.enq.valid, "Enqueue while sink is reset and AsyncQueueSource is unprotected") + // assert (!reset_rise || prev_idx_match.asBool, "Sink reset while AsyncQueueSource not empty") + } +} + +class AsyncQueueSink[T <: Data](gen: T, params: AsyncQueueParams = AsyncQueueParams()) extends Module { + val io = IO(new Bundle { + // These come from the sink domain + val deq = Decoupled(gen) + // These cross to the source clock domain + val async = Flipped(new AsyncBundle(gen, params)) + }) + + val bits = params.bits + val source_ready = WireInit(true.B) + val ridx = withReset(reset.asAsyncReset)(GrayCounter(bits+1, io.deq.fire, !source_ready, "ridx_bin")) + val widx = AsyncResetSynchronizerShiftReg(io.async.widx, params.sync, Some("widx_gray")) + val valid = source_ready && ridx =/= widx + + // The mux is safe because timing analysis ensures ridx has reached the register + // On an ASIC, changes to the unread location cannot affect the selected value + // On an FPGA, only one input changes at a time => mem updates don't cause glitches + // The register only latches when the selected valued is not being written + val index = if (bits == 0) 0.U else ridx(bits-1, 0) ^ (ridx(bits, bits) << (bits-1)) + io.async.index.foreach { _ := index } + // This register does not NEED to be reset, as its contents will not + // be considered unless the asynchronously reset deq valid register is set. + // It is possible that bits latches when the source domain is reset / has power cut + // This is safe, because isolation gates brought mem low before the zeroed widx reached us + val deq_bits_nxt = io.async.mem(if (params.narrow) 0.U else index) + io.deq.bits := ClockCrossingReg(deq_bits_nxt, en = valid, doInit = false, name = Some("deq_bits_reg")) + + val valid_reg = withReset(reset.asAsyncReset)(RegNext(next=valid, init=false.B).suggestName("valid_reg")) + io.deq.valid := valid_reg && source_ready + + val ridx_reg = withReset(reset.asAsyncReset)(RegNext(next=ridx, init=0.U).suggestName("ridx_gray")) + io.async.ridx := ridx_reg + + io.async.safe.foreach { sio => + val sink_valid_0 = Module(new AsyncValidSync(params.sync, "sink_valid_0")) + val sink_valid_1 = Module(new AsyncValidSync(params.sync, "sink_valid_1")) + + val source_extend = Module(new AsyncValidSync(params.sync, "source_extend")) + val source_valid = Module(new AsyncValidSync(params.sync, "source_valid")) + sink_valid_0 .reset := (reset.asBool || !sio.source_reset_n).asAsyncReset + sink_valid_1 .reset := (reset.asBool || !sio.source_reset_n).asAsyncReset + source_extend.reset := (reset.asBool || !sio.source_reset_n).asAsyncReset + source_valid .reset := reset.asAsyncReset + + sink_valid_0 .clock := clock + sink_valid_1 .clock := clock + source_extend.clock := clock + source_valid .clock := clock + + sink_valid_0.io.in := true.B + sink_valid_1.io.in := sink_valid_0.io.out + sio.ridx_valid := sink_valid_1.io.out + source_extend.io.in := sio.widx_valid + source_valid.io.in := source_extend.io.out + source_ready := source_valid.io.out + sio.sink_reset_n := !reset.asBool + + // TODO: write some sort of sanity check assertion for users + // that denote don't reset when there is activity + // + // val reset_and_extend = !source_ready || !sio.source_reset_n || reset.asBool + // val reset_and_extend_prev = RegNext(reset_and_extend, true.B) + // val reset_rise = !reset_and_extend_prev && reset_and_extend + // val prev_idx_match = AsyncResetReg(updateData=(io.async.widx===io.async.ridx), resetData=0) + // assert (!reset_rise || prev_idx_match.asBool, "Source reset while AsyncQueueSink not empty") + } +} + +object FromAsyncBundle +{ + // Sometimes it makes sense for the sink to have different sync than the source + def apply[T <: Data](x: AsyncBundle[T]): DecoupledIO[T] = apply(x, x.params.sync) + def apply[T <: Data](x: AsyncBundle[T], sync: Int): DecoupledIO[T] = { + val sink = Module(new AsyncQueueSink(chiselTypeOf(x.mem(0)), x.params.copy(sync = sync))) + sink.io.async <> x + sink.io.deq + } +} + +object ToAsyncBundle +{ + def apply[T <: Data](x: ReadyValidIO[T], params: AsyncQueueParams = AsyncQueueParams()): AsyncBundle[T] = { + val source = Module(new AsyncQueueSource(chiselTypeOf(x.bits), params)) + source.io.enq <> x + source.io.async + } +} + +class AsyncQueue[T <: Data](gen: T, params: AsyncQueueParams = AsyncQueueParams()) extends Crossing[T] { + val io = IO(new CrossingIO(gen)) + val source = withClockAndReset(io.enq_clock, io.enq_reset) { Module(new AsyncQueueSource(gen, params)) } + val sink = withClockAndReset(io.deq_clock, io.deq_reset) { Module(new AsyncQueueSink (gen, params)) } + + source.io.enq <> io.enq + io.deq <> sink.io.deq + sink.io.async <> source.io.async +} diff --git a/rocketutils/rocketutils/src/rocketutils/AsyncResetReg.scala b/rocketutils/rocketutils/src/rocketutils/AsyncResetReg.scala new file mode 100644 index 00000000000..7b149163603 --- /dev/null +++ b/rocketutils/rocketutils/src/rocketutils/AsyncResetReg.scala @@ -0,0 +1,105 @@ +// See LICENSE.SiFive for license details. + +package org.chipsalliance.rocketutils + +import chisel3._ + +/** This black-boxes an Async Reset + * (or Set) + * Register. + * + * Because Chisel doesn't support + * parameterized black boxes, + * we unfortunately have to + * instantiate a number of these. + * + * We also have to hard-code the set/ + * reset behavior. + * + * 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 en Write Enable Input + * + */ + +class AsyncResetReg(resetValue: Int = 0) extends RawModule { + val io = IO(new Bundle { + val d = Input(Bool()) + val q = Output(Bool()) + val en = Input(Bool()) + + val clk = Input(Clock()) + val rst = Input(Reset()) + }) + + val reg = withClockAndReset(io.clk, io.rst.asAsyncReset)(RegInit(resetValue.U(1.W))) + when (io.en) { + reg := io.d + } + io.q := reg +} + +class SimpleRegIO(val w: Int) extends Bundle{ + val d = Input(UInt(w.W)) + val q = Output(UInt(w.W)) + val en = Input(Bool()) +} + +class AsyncResetRegVec(val w: Int, val init: BigInt) extends Module { + override def desiredName = s"AsyncResetRegVec_w${w}_i${init}" + + val io = IO(new SimpleRegIO(w)) + + val reg = withReset(reset.asAsyncReset)(RegInit(init.U(w.W))) + when (io.en) { + reg := io.d + } + io.q := reg +} + +object AsyncResetReg { + // Create Single Registers + def apply(d: Bool, clk: Clock, rst: Bool, init: Boolean, name: Option[String]): Bool = { + val reg = Module(new AsyncResetReg(if (init) 1 else 0)) + reg.io.d := d + reg.io.clk := clk + reg.io.rst := rst + reg.io.en := true.B + name.foreach(reg.suggestName(_)) + reg.io.q + } + + def apply(d: Bool, clk: Clock, rst: Bool): Bool = apply(d, clk, rst, false, None) + def apply(d: Bool, clk: Clock, rst: Bool, name: String): Bool = apply(d, clk, rst, false, Some(name)) + + // Create Vectors of Registers + def apply(updateData: UInt, resetData: BigInt, enable: Bool, name: Option[String] = None): UInt = { + val w = updateData.getWidth max resetData.bitLength + val reg = Module(new AsyncResetRegVec(w, resetData)) + name.foreach(reg.suggestName(_)) + reg.io.d := updateData + reg.io.en := enable + reg.io.q + } + def apply(updateData: UInt, resetData: BigInt, enable: Bool, name: String): UInt = apply(updateData, + resetData, enable, Some(name)) + + + def apply(updateData: UInt, resetData: BigInt): UInt = apply(updateData, resetData, enable = true.B) + def apply(updateData: UInt, resetData: BigInt, name: String): UInt = apply(updateData, resetData, enable = true.B, Some(name)) + + def apply(updateData: UInt, enable: Bool): UInt = apply(updateData, resetData=BigInt(0), enable) + def apply(updateData: UInt, enable: Bool, name: String): UInt = apply(updateData, resetData = BigInt(0), enable, Some(name)) + + def apply(updateData: UInt): UInt = apply(updateData, resetData = BigInt(0), enable = true.B) + def apply(updateData: UInt, name:String): UInt = apply(updateData, resetData = BigInt(0), enable = true.B, Some(name)) +} + diff --git a/rocketutils/rocketutils/src/rocketutils/BlockDuringReset.scala b/rocketutils/rocketutils/src/rocketutils/BlockDuringReset.scala new file mode 100644 index 00000000000..50d5bc181fb --- /dev/null +++ b/rocketutils/rocketutils/src/rocketutils/BlockDuringReset.scala @@ -0,0 +1,19 @@ +// See LICENSE.SiFive for license details. + +package org.chipsalliance.rocketutils + +import chisel3._ +import chisel3.util.{Counter, RegEnable} + +/** Blocks transactions until the cycle after reset. */ +object BlockDuringReset +{ + private def outOfReset(stretchCycles: Int): Bool = stretchCycles match { + case 0 => RegNext(true.B, false.B) + case i => RegEnable(true.B, false.B, Counter(true.B, i)._2) + } + + def apply[T <: Data : Blockable](data: T, stretchCycles: Int = 0): T = { + implicitly[Blockable[T]].blockWhile(!outOfReset(stretchCycles), data) + } +} diff --git a/rocketutils/rocketutils/src/rocketutils/Blockable.scala b/rocketutils/rocketutils/src/rocketutils/Blockable.scala new file mode 100644 index 00000000000..4667c81e8e8 --- /dev/null +++ b/rocketutils/rocketutils/src/rocketutils/Blockable.scala @@ -0,0 +1,78 @@ +// See LICENSE.SiFive for license details. + +package org.chipsalliance.rocketutils + +import chisel3._ +import chisel3.util.DecoupledIO + +import org.chipsalliance.rocketutils.conversions._ + +/** A trait supplying a function allowing the contents of data + * to be supressed for a time period, i.e. be blocked. + */ +trait Blockable[T <: Data] { + def blockWhile(enable_blocking: Bool, data: T): T +} + +object Blockable { + implicit object BlockableBool extends Blockable[Bool] { + def blockWhile(enable_blocking: Bool, x: Bool): Bool = x && !enable_blocking + } + + implicit def BlockableDataCanBeValid[T <: DataCanBeValid]: Blockable[T] = new Blockable[T] { + def blockWhile(enable_blocking: Bool, data: T): T = { + val blocked: T = Wire(chiselTypeOf(data)) + blocked := data + when (enable_blocking) { blocked.valid := false.B } + blocked + } + } + + implicit def BlockableDecoupled[T <: Data]: Blockable[DecoupledIO[T]] = new Blockable[DecoupledIO[T]] { + def blockWhile(enable_blocking: Bool, data: DecoupledIO[T]): DecoupledIO[T] = { + val res = Wire(chiselTypeOf(data)) + res.valid := data.valid + data.ready := res.ready + res.bits := data.bits + when (enable_blocking) { + res.valid := false.B + data.ready := false.B + } + res + } + } + + implicit def BlockableCredited[T <: Data]: Blockable[CreditedIO[T]] = new Blockable[CreditedIO[T]] { + def blockWhile(enable_blocking: Bool, data: CreditedIO[T]): CreditedIO[T] = { + val res = Wire(chiselTypeOf(data)) + res.debit := data.debit + data.credit := res.credit + res.bits := data.bits + when (enable_blocking) { + res.debit := false.B + data.credit := false.B + } + res + } + } + + implicit def BlockableVec[T <: Data : Blockable]: Blockable[Vec[T]] = new Blockable[Vec[T]] { + def blockWhile(enable_blocking: Bool, data: Vec[T]): Vec[T] = { + VecInit(data.map(x => implicitly[Blockable[T]].blockWhile(enable_blocking, x))) + } + } + + implicit object BlockableTraceCoreInterface extends Blockable[TraceCoreInterface] { + def blockWhile(enable_blocking: Bool, data: TraceCoreInterface): TraceCoreInterface = { + val blocked: TraceCoreInterface = Wire(chiselTypeOf(data)) + blocked := data + when (enable_blocking) { + blocked.group.foreach { g => + g.iretire := 0.U + g.itype := TraceItype.ITNothing + } + } + blocked + } + } +} diff --git a/rocketutils/rocketutils/src/rocketutils/Broadcaster.scala b/rocketutils/rocketutils/src/rocketutils/Broadcaster.scala new file mode 100644 index 00000000000..622570f94d3 --- /dev/null +++ b/rocketutils/rocketutils/src/rocketutils/Broadcaster.scala @@ -0,0 +1,49 @@ +// See LICENSE.SiFive for license details. +// See LICENSE.Berkeley for license details. + +package org.chipsalliance.rocketutils + +import chisel3._ +import chisel3.util._ + +/** Takes in data on one decoupled interface and broadcasts it + * to N decoupled output interfaces. + */ +class Broadcaster[T <: Data](typ: T, n: Int) extends Module { + val io = IO(new Bundle { + val in = Flipped(Decoupled(typ)) + val out = Vec(n, Decoupled(typ)) + }) + + require (n > 0) + + if (n == 1) { + io.out.head <> io.in + } else { + val idx = RegInit(0.U(log2Up(n).W)) + val save = Reg(typ) + + io.out.head.valid := idx === 0.U && io.in.valid + io.out.head.bits := io.in.bits + for (i <- 1 until n) { + io.out(i).valid := idx === i.U + io.out(i).bits := save + } + io.in.ready := io.out.head.ready && idx === 0.U + + when (io.in.fire) { save := io.in.bits } + + when (io.out(idx).fire) { + when (idx === (n - 1).U) { idx := 0.U } + .otherwise { idx := idx + 1.U } + } + } +} + +object Broadcaster { + def apply[T <: Data](in: DecoupledIO[T], n: Int): Vec[DecoupledIO[T]] = { + val split = Module(new Broadcaster(in.bits, n)) + split.io.in <> in + split.io.out + } +} diff --git a/rocketutils/rocketutils/src/rocketutils/BundleMap.scala b/rocketutils/rocketutils/src/rocketutils/BundleMap.scala new file mode 100644 index 00000000000..0e849ed07a2 --- /dev/null +++ b/rocketutils/rocketutils/src/rocketutils/BundleMap.scala @@ -0,0 +1,159 @@ +// See LICENSE.SiFive for license details. +package org.chipsalliance.rocketutils + +import chisel3._ +import chisel3.reflect.DataMirror + +import scala.collection.immutable.SeqMap +import scala.collection.immutable.HashMap + +/* BundleMaps include IOs for every BundleField they are constructed with. + * A given BundleField in a BundleMap is accessed by a BundleKey. + * + * So, for example: + * val myBundleMap = BundleMap(Seq(MyBundleDataField(width = 8), ...)) + * myBundleMap(MyBundleData) := 7.U + * + * case object MyBundleData extends DataKey[UInt]("data") // "data" is the name of the IO used in BundleMaps + * case class MyBundleDataField(width: Int) extends BundleField(MyBundleData) { + * def data = Output(UInt(width.W)) + * def default(x: UInt) { x := 0.U } + * } + * OR: + * case class MyBundleDataField(width: Int) extends SimpleBundleField(MyBundleData)(Output(UInt(width.W)), 0.U) + */ + +sealed trait BundleFieldBase { + def key: BundleKeyBase + def data: Data // the field's chisel type with a direction + def setDataDefault(x: Data): Unit + + // Overload this if there is a way to unify differently parameterized cases of a field + // (For example, by selecting the widest width) + def unify(that: BundleFieldBase): BundleFieldBase = { + require (this == that, s"Attempted to unify two BundleMaps with conflicting fields: ${this} and ${that}") + that + } +} + +abstract class BundleField[T <: Data](val key: BundleKey[T], typeT: => T, val default: T => Unit) extends BundleFieldBase { + def data: T = typeT + def defaultFlip(x: T): Unit = {} + def setDataDefault(x: Data): Unit = default(x.asInstanceOf[T]) + def setDataDefaultFlip(x: Data): Unit = defaultFlip(x.asInstanceOf[T]) +} + +abstract class SimpleBundleField[T <: Data](key: BundleKey[T])(typeT: => T, defaultT: => T) extends BundleField(key, typeT, { x: T => x := defaultT }) + +object BundleField { + /* Consider an arbiter that receives two request streams A and B and combines them to C. + * The output stream C should have the union of all keys from A and B. + * When a key from A and B have the same name: + * - it is an error if they are not equal. + * - the union contains only one copy. + */ + def union(fields: Seq[BundleFieldBase]): Seq[BundleFieldBase] = + fields.groupBy(_.key.name).map(_._2.reduce(_ unify _)).toList + /* There is no point in carrying an extra field if the other end does not use it. + */ + def accept(fields: Seq[BundleFieldBase], keys: Seq[BundleKeyBase]): Seq[BundleFieldBase] = { + def hk = HashMap(keys.map(k => (k.name, k)):_*) + fields.filter(f => hk.lift(f.key.name) == Some(f.key)) + } +} + +sealed trait BundleKeyBase { + def name: String + + def isControl: Boolean = this match { + case _: IsControlKey => true + case _ => false + } + + def isData: Boolean = this match { + case _: IsDataKey => true + case _ => false + } +} + +/* Custom bundle fields have two broad categories: + * - data fields (which are per-beat/byte and should be widened by bus-width adapters) + * - control fields (which are per-burst and are unaffected by width adapters) + */ +sealed trait IsDataKey extends BundleKeyBase +sealed trait IsControlKey extends BundleKeyBase + +sealed class BundleKey[T <: Data](val name: String) extends BundleKeyBase +abstract class ControlKey[T <: Data](name: String) extends BundleKey[T](name) with IsControlKey +abstract class DataKey [T <: Data](name: String) extends BundleKey[T](name) with IsDataKey + +/* Signals can be further categorized in a request-response protocol: + * - request fields flow from master to slave + * - response fields flow from slave to master + * - echo fields flow from master to slave to master; a master must receive the same value in the response as he sent in the request + * Generally, this categorization belongs in different BundleMaps + */ + +class BundleMap(val fields: Seq[BundleFieldBase]) extends Record { + // All fields must have distinct key.names + require(fields.map(_.key.name).distinct.size == fields.size) + + val elements: SeqMap[String, Data] = SeqMap(fields.map { bf => bf.key.name -> chisel3.reflect.DataMirror.internal.chiselTypeClone(bf.data) } :_*) + + // A BundleMap is best viewed as a map from BundleKey to Data + def keydata: Seq[(BundleKeyBase, Data)] = (fields zip elements) map { case (field, (_, data)) => (field.key, data) } + + def apply[T <: Data](key: BundleKey[T]): T = elements(key.name).asInstanceOf[T] + def lift [T <: Data](key: BundleKey[T]): Option[T] = elements.lift(key.name).map(_.asInstanceOf[T]) + + def apply(key: BundleKeyBase): Data = elements(key.name) + def lift (key: BundleKeyBase): Option[Data] = elements.lift(key.name) + + // Create a new BundleMap with only the selected Keys retained + def subset(fn: BundleKeyBase => Boolean): BundleMap = { + val out = Wire(BundleMap(fields.filter(x => fn(x.key)))) + out :<= this.waiveAll + out + } +} + +object BundleMap { + def apply(fields: Seq[BundleFieldBase] = Nil) = new BundleMap(fields) + /** Sets the default values of all bundle map elements that are aligned w.r.t. d */ + def setAlignedDefaults[T <: Data](c: Connectable[T]): Connectable[T] = { + DataMirror.collectAlignedDeep(c.base) { case member: BundleMap => + member.fields.foreach { f => + f.setDataDefault(member.elements(f.key.name)) + } + } + c + } + /** Sets the default values of all bundle map elements that are flipped w.r.t. d */ + def setFlippedDefaults[T <: Data](c: Connectable[T]): Connectable[T] = { + DataMirror.collectFlippedDeep(c.base) { case member: BundleMap => + member.fields.foreach { f => + f.setDataDefault(member.elements(f.key.name)) + } + } + c + } + /** Waives all bundle map elements */ + def waive[T <: Data](c: Connectable[T]): Connectable[T] = { + val bundleFields = DataMirror + .collectMembers(c.base) { case member: BundleMap => + member.getElements + } + .flatten + Connectable(c.base, bundleFields.toSet) + } + /** Waives all bundle map elements and sets the default values of all bundle map elements that are aligned w.r.t. d */ + def waiveAndSetAlignedDefaults[T <: Data](c: Connectable[T]): Connectable[T] = { + setAlignedDefaults(c) + waive(c) + } + /** Waives all bundle map elements and sets the default values of all bundle map elements that are flipped w.r.t. d */ + def waiveAndSetFlippedDefaults[T <: Data](c: Connectable[T]): Connectable[T] = { + setFlippedDefaults(c) + waive(c) + } +} diff --git a/rocketutils/rocketutils/src/rocketutils/CRC.scala b/rocketutils/rocketutils/src/rocketutils/CRC.scala new file mode 100644 index 00000000000..1d42194b70c --- /dev/null +++ b/rocketutils/rocketutils/src/rocketutils/CRC.scala @@ -0,0 +1,37 @@ +// See LICENSE.SiFive for license details. + +package org.chipsalliance.rocketutils + +import chisel3._ +import chisel3.util._ + +object CRC +{ + // A divisor is interpretted using an explicit+1 CRC notation where bit 0 is required to be one. + // For example, a divisor of 0x1d5 is interpretted to be x^8 + x^7 + x^6 + x^4 + x^2 + 1 + // Let n be the highest term in the divisor; n=8 in 0x1d5. + // Then, this function calculates c mod d, returning an n-bit UInt. + // coefficient.width must be <= width + def apply(divisor: BigInt, coefficient: UInt, width: Integer): UInt = { + require (divisor > 0 && divisor.testBit(0)) + require (width > 0) + assert (coefficient >> width === 0.U) + val n = log2Floor(divisor) + val m = width + if (m <= n) return coefficient + + // Initialize the reduction matrix + val array = Array.tabulate(m) { BigInt(1) << _ } + // Reduce the matrix of terms larger than n + for { + i <- (n until m).reverse + j <- 0 to n + if divisor.testBit(j) + } array(i-(n-j)) ^= array(i) + // Construct the circuit + Cat(Seq.tabulate(n) { i => (array(i).U & coefficient).xorR } .reverse) + } + + // Find more great CRC polynomials (using implicit+1 notation) here: https://users.ece.cmu.edu/~koopman/crc/ + val CRC_16F_4_2 = BigInt(0x1a2eb) // HD=4 for <32751 bits and HD=6 for <93 bits, 0xd175 in implicit+1 notation +} diff --git a/rocketutils/rocketutils/src/rocketutils/ClockDivider.scala b/rocketutils/rocketutils/src/rocketutils/ClockDivider.scala new file mode 100644 index 00000000000..489b51ec0f7 --- /dev/null +++ b/rocketutils/rocketutils/src/rocketutils/ClockDivider.scala @@ -0,0 +1,59 @@ +// See LICENSE.Berkeley for license details. + +package org.chipsalliance.rocketutils + +import chisel3._ +import chisel3.withClock +import chisel3.util.HasBlackBoxResource + +/** This black-boxes a Clock Divider by 2. + * The output clock is phase-aligned to the input clock. + * If you use this in synthesis, make sure your sdc + * declares that you want it to do the same. + * + * Because Chisel does not support + * blocking assignments, it is impossible + * to create a deterministic divided clock. + */ +class ClockDivider2 extends BlackBox with HasBlackBoxResource { + val io = IO(new Bundle { + val clk_out = Output(Clock()) + val clk_in = Input(Clock()) + }) + + addResource("/vsrc/ClockDivider2.v") +} +class ClockDivider3 extends BlackBox with HasBlackBoxResource { + val io = IO(new Bundle { + val clk_out = Output(Clock()) + val clk_in = Input(Clock()) + }) + + addResource("/vsrc/ClockDivider3.v") +} + +/** Divide the clock by power of 2 times. + * @param pow2 divides the clock 2 ^ pow2 times */ +class Pow2ClockDivider(pow2: Int) extends Module { + val io = IO(new Bundle { + val clock_out = Output(Clock()) + }) + + if (pow2 == 0) { + io.clock_out := clock + } else { + val dividers = Seq.fill(pow2) { Module(new ClockDivider2) } + + dividers.init.zip(dividers.tail).map { case (last, next) => + next.io.clk_in := last.io.clk_out + } + + dividers.head.io.clk_in := clock + io.clock_out := dividers.last.io.clk_out + } +} + +object Pow2ClockDivider { + def apply(pow2: Int): Clock = Module(new Pow2ClockDivider(pow2)).io.clock_out + def apply(clock_in: Clock, pow2: Int): Clock = withClock(clock_in) { apply(pow2) } +} diff --git a/rocketutils/rocketutils/src/rocketutils/ClockGate.scala b/rocketutils/rocketutils/src/rocketutils/ClockGate.scala new file mode 100644 index 00000000000..19495c9c6cb --- /dev/null +++ b/rocketutils/rocketutils/src/rocketutils/ClockGate.scala @@ -0,0 +1,54 @@ +// See LICENSE.SiFive for license details. + +package org.chipsalliance.rocketutils + +import chisel3._ +import chisel3.util.{HasBlackBoxResource, HasBlackBoxPath} +import org.chipsalliance.cde.config.{Field, Parameters} + +import java.nio.file.{Files, Paths} + +case object ClockGateImpl extends Field[() => ClockGate](() => new EICG_wrapper) +case object ClockGateModelFile extends Field[Option[String]](None) + +abstract class ClockGate extends BlackBox + with HasBlackBoxResource with HasBlackBoxPath { + val io = IO(new Bundle{ + val in = Input(Clock()) + val test_en = Input(Bool()) + val en = Input(Bool()) + val out = Output(Clock()) + }) + + def addVerilogResource(vsrc: String): Unit = { + if (Files.exists(Paths.get(vsrc))) + addPath(vsrc) + else + addResource(vsrc) + } +} + +object ClockGate { + def apply[T <: ClockGate]( + in: Clock, + en: Bool, + name: Option[String] = None)(implicit p: Parameters): Clock = { + val cg = Module(p(ClockGateImpl)()) + name.foreach(cg.suggestName(_)) + p(ClockGateModelFile).map(cg.addVerilogResource(_)) + + cg.io.in := in + cg.io.test_en := false.B + cg.io.en := en + cg.io.out + } + + def apply[T <: ClockGate]( + in: Clock, + en: Bool, + name: String)(implicit p: Parameters): Clock = + apply(in, en, Some(name)) +} + +// behavioral model of Integrated Clock Gating cell +class EICG_wrapper extends ClockGate diff --git a/rocketutils/rocketutils/src/rocketutils/CoreMonitor.scala b/rocketutils/rocketutils/src/rocketutils/CoreMonitor.scala new file mode 100644 index 00000000000..0dda0c08184 --- /dev/null +++ b/rocketutils/rocketutils/src/rocketutils/CoreMonitor.scala @@ -0,0 +1,33 @@ +// See LICENSE.Berkeley for license details. +// See LICENSE.SiFive for license details. + +package org.chipsalliance.rocketutils + +import chisel3._ + +// this bundle is used to expose some internal core signals +// to verification monitors which sample instruction commits +class CoreMonitorBundle(val xLen: Int, val fLen: Int) extends Bundle with Clocked { + val excpt = Bool() + val priv_mode = UInt(width = 3.W) + val hartid = UInt(width = xLen.W) + val timer = UInt(width = 32.W) + val valid = Bool() + val pc = UInt(width = xLen.W) + val wrdst = UInt(width = 5.W) + val wrdata = UInt(width = (xLen max fLen).W) + val wrenx = Bool() + val wrenf = Bool() + @deprecated("replace wren with wrenx or wrenf to specify integer or floating point","Rocket Chip 2020.05") + def wren: Bool = wrenx || wrenf + val rd0src = UInt(width = 5.W) + val rd0val = UInt(width = xLen.W) + val rd1src = UInt(width = 5.W) + val rd1val = UInt(width = xLen.W) + val inst = UInt(width = 32.W) +} + +// mark a module that has cores with CoreMonitorBundles +trait HasCoreMonitorBundles { + def coreMonitorBundles: List[CoreMonitorBundle] +} diff --git a/rocketutils/rocketutils/src/rocketutils/Counters.scala b/rocketutils/rocketutils/src/rocketutils/Counters.scala new file mode 100644 index 00000000000..5b4ae9c348d --- /dev/null +++ b/rocketutils/rocketutils/src/rocketutils/Counters.scala @@ -0,0 +1,70 @@ +// See LICENSE.Berkeley for license details. +// See LICENSE.SiFive for license details. + +package org.chipsalliance.rocketutils + +import chisel3._ +import chisel3.util._ + +// Produces 0-width value when counting to 1 +class ZCounter(val n: Int) { + val value = RegInit(0.U(log2Ceil(n).W)) + def inc(): Bool = { + if (n == 1) true.B + else { + val wrap = value === (n-1).U + value := Mux(!isPow2(n).B && wrap, 0.U, value + 1.U) + wrap + } + } +} + +object ZCounter { + def apply(n: Int) = new ZCounter(n) + def apply(cond: Bool, n: Int): (UInt, Bool) = { + val c = new ZCounter(n) + var wrap: Bool = null + when (cond) { wrap = c.inc() } + (c.value, cond && wrap) + } +} + +object TwoWayCounter { + def apply(up: Bool, down: Bool, max: Int): UInt = { + val cnt = RegInit(0.U(log2Up(max + 1).W)) + when (up && !down) { cnt := cnt + 1.U } + when (down && !up) { cnt := cnt - 1.U } + cnt + } +} + +// a counter that clock gates most of its MSBs using the LSB carry-out +case class WideCounter(width: Int, inc: UInt = 1.U, reset: Boolean = true, inhibit: Bool = false.B) { + private val isWide = width > (2 * inc.getWidth) + private val smallWidth = if (isWide) inc.getWidth max log2Up(width) else width + private val small = if (reset) RegInit(0.U(smallWidth.W)) else Reg(UInt(smallWidth.W)) + private val nextSmall = small +& inc + when (!inhibit) { small := nextSmall } + + private val large = if (isWide) { + val r = if (reset) RegInit(0.U((width - smallWidth).W)) else Reg(UInt((width - smallWidth).W)) + when (nextSmall(smallWidth) && !inhibit) { r := r + 1.U } + r + } else null + + val value = if (isWide) Cat(large, small) else small + lazy val carryOut = { + val lo = (small ^ nextSmall) >> 1 + if (!isWide) + lo + else { + val hi = Mux(nextSmall(smallWidth), large ^ (large +& 1.U), 0.U) >> 1 + Cat(hi, lo) + } + } + + def := (x: UInt) = { + small := x + if (isWide) large := x >> smallWidth + } +} diff --git a/rocketutils/rocketutils/src/rocketutils/CreditedIO.scala b/rocketutils/rocketutils/src/rocketutils/CreditedIO.scala new file mode 100644 index 00000000000..16362a4c08b --- /dev/null +++ b/rocketutils/rocketutils/src/rocketutils/CreditedIO.scala @@ -0,0 +1,151 @@ +// See LICENSE.SiFive for license details. + +package org.chipsalliance.rocketutils + +import chisel3._ +import chisel3.util._ + +/** Transmission delay in credit-debit systems. + * debit delay is the number of cycles it takes debit+'bits' to transit the link. + * credit delay is the number of cycles it takes credits to be returned. + * round trip / total delay is the sum of debit and credit delay. + * The system must have a positive total delay, otherwise you have a combinational loop. + */ +case class CreditedDelay(debit: Int, credit: Int) +{ + val total = debit + credit + require (debit >= 0) + require (credit >= 0) + + def flip: CreditedDelay = CreditedDelay(credit, debit) + + def +(that: CreditedDelay): CreditedDelay = + CreditedDelay(debit + that.debit, credit + that.credit) + + override def toString = s"${debit}:${credit}" +} + +/** CreditedIO provides credit-debit-based flow control for arbitrary Data. + * The sender may only transmit Data when it has non-zero credits. + * Receivers provide 0 or 1 credits to senders using the credit field. + * Senders consume 0 or 1 credits by setting the debit field. + * The bits Data field is DontCare when debit=0. + * credit MAY depend combinationally on debit. + * debit MAY depend combinationally on credit. + * WARNING: The user must ensure the round trip time is > 0. + * Failure to comply will result in a combinational loop! + */ +final class CreditedIO[T <: Data](gen: T) extends Bundle +{ + def genType: T = gen + + val credit = Input (Bool()) // 1: a credit is given to the sender by the receiver + val debit = Output(Bool()) // 1: a credit is consumed by the sender to transfer 'bits' + val bits = Output(genType) + + /** Provide a DecoupledIO interface for sending CreditedIO[Data]. + * Convert an IrrevocableIO input to DecoupledIO via Decoupled(). + * depth controls the maximum number of Data beats inflight. + * Sender powers on with credits=depth, so sender and receiver must agree on depth. + * pipe=false increases the receiver=>sender trip time by one cycle. + * pipe=true causes debit to depend on credit. + */ + def toSender(depth: Int, pipe: Boolean = true): DecoupledIO[T] = { + require (depth >= 1) + val res = Wire(DecoupledIO(genType)) + val counter = new CreditedIOCounter(depth, depth) + counter.update(this) + res.ready := !counter.empty || (pipe.B && credit) + debit := res.fire + bits := res.bits + res + } + + /** Provide an IrrevocableIO interface for receiving CreditedIO[Data]. + * Conversion to DecoupledIO is done via application of Decoupled(). + * depth controls the Queue depth and thus maximum number of elements inflight. + * flow=false increases the sender=>receiver trip time by one cycle. + * flow=true causes credit to depend on debit. + */ + def toReceiver(depth: Int, flow: Boolean = true): IrrevocableIO[T] = { + require (depth >= 1) + val enq = Wire(DecoupledIO(genType)) + enq.valid := debit + enq.bits := bits + assert (!enq.valid || enq.ready) + val res = Queue.irrevocable(enq, depth, pipe=true, flow=flow) + credit := res.fire + res + } + + /** Add register stages to the sender and receiver paths. + * Apply this method to the producer/sender-facing bundle. + * The round-trip-time (RTT) is increased by sender+receiver. + */ + def pipeline(debitDelay: Int, creditDelay: Int): CreditedIO[T] = { + val res = Wire(CreditedIO(genType)) + if (debitDelay <= 0) { + credit := ShiftRegister(res.credit, creditDelay, false.B, true.B) + res.debit := debit + res.bits := bits + } else { + // We can't use ShiftRegister, because we want debit-gated enables + val out = pipeline(debitDelay-1, creditDelay) + out.credit := res.credit + res.debit := RegNext(out.debit, false.B) + res.bits := RegEnable(out.bits, out.debit) + } + res + } + + def pipeline(delay: CreditedDelay): CreditedIO[T] = + pipeline(delay.debit, delay.credit) +} + +object CreditedIO +{ + def apply[T <: Data](genType: T) = new CreditedIO(genType) + + def fromSender[T <: Data](x: ReadyValidIO[T], depth: Int, pipe: Boolean = true): CreditedIO[T] = { + val res = Wire(CreditedIO(chiselTypeOf(x.bits))) + val dec = res.toSender(depth, pipe) + dec.valid := x.valid + dec.bits := x.bits + x.ready := dec.ready + res + } + + def fromReceiver[T <: Data](x: ReadyValidIO[T], depth: Int, flow: Boolean = true): CreditedIO[T] = { + val res = Wire(CreditedIO(chiselTypeOf(x.bits))) + val irr = res.toReceiver(depth, flow) + x.valid := irr.valid + x.bits := irr.bits + irr.ready := x.ready + res + } +} + +class CreditedIOCounter(val init: Int, val depth: Int) { + require (0 <= init) + require (init <= depth) + + private val v = RegInit(init.U(log2Ceil(depth+1).W)) + private val nextV = WireInit(v) + + val value = v + 0.U + val nextValue = nextV + 0.U + + def full: Bool = v === depth.U + def empty: Bool = v === 0.U + + def update(credit: Bool, debit: Bool): Unit = { + assert((!(credit && full) || debit) && (!(debit && empty) || credit)) + val next = Mux(credit, v + 1.U, v - 1.U) + when (credit =/= debit) { + nextV := next + v := next + } + } + + def update(c: CreditedIO[_]): Unit = { update(c.credit, c.debit) } +} diff --git a/rocketutils/rocketutils/src/rocketutils/Crossing.scala b/rocketutils/rocketutils/src/rocketutils/Crossing.scala new file mode 100644 index 00000000000..757d3a0176b --- /dev/null +++ b/rocketutils/rocketutils/src/rocketutils/Crossing.scala @@ -0,0 +1,21 @@ +// See LICENSE.SiFive for license details. + +package org.chipsalliance.rocketutils + +import chisel3._ +import chisel3.util._ + +class CrossingIO[T <: Data](gen: T) extends Bundle { + // Enqueue clock domain + val enq_clock = Input(Clock()) + val enq_reset = Input(Bool()) // synchronously deasserted wrt. enq_clock + val enq = Flipped(Decoupled(gen)) + // Dequeue clock domain + val deq_clock = Input(Clock()) + val deq_reset = Input(Bool()) // synchronously deasserted wrt. deq_clock + val deq = Decoupled(gen) +} + +abstract class Crossing[T <: Data] extends RawModule { + val io: CrossingIO[T] +} diff --git a/rocketutils/rocketutils/src/rocketutils/DelayQueue.scala b/rocketutils/rocketutils/src/rocketutils/DelayQueue.scala new file mode 100644 index 00000000000..8e05ae04c26 --- /dev/null +++ b/rocketutils/rocketutils/src/rocketutils/DelayQueue.scala @@ -0,0 +1,96 @@ +// See LICENSE.SiFive for license details. + +package org.chipsalliance.rocketutils + +import chisel3._ +import chisel3.util._ + +/** A queue that delays elements by a certain cycle count. + * + * @param gen queue element type + * @param entries queue size + * + * @param enq enqueue + * @param deq dequeue + * @param timer cycle count timer + * @param entries cycle delay + */ +class DelayQueue[T <: Data](gen: T, entries: Int) extends Module { + val io = IO(new Bundle { + val enq = Flipped(DecoupledIO(gen)) + val deq = DecoupledIO(gen) + val timer = Input(UInt()) + val delay = Input(UInt()) + }) + + val q = Module(new Queue(new Bundle { + val data = gen + val time = UInt(io.timer.getWidth.W) + }, entries, flow=true)) + + val delay_r = RegInit(0.U(io.delay.getWidth.W)) + when (delay_r =/= io.delay) { + delay_r := io.delay + assert(q.io.count == 0, "Undefined behavior when delay is changed while queue has elements.") + } + + q.io.enq.bits.data := io.enq.bits + q.io.enq.bits.time := io.timer + q.io.enq.valid := io.enq.fire + io.enq.ready := q.io.enq.ready + + io.deq.bits := q.io.deq.bits.data + io.deq.valid := q.io.deq.valid && ((io.timer - q.io.deq.bits.time) >= delay_r) + q.io.deq.ready := io.deq.fire +} + +object DelayQueue { + /** Helper to connect a delay queue. + * + * @param source decoupled queue input + * @param timer cycle count timer + * @param delay cycle delay + * @param depth queue size + */ + def apply[T <: Data](source: DecoupledIO[T], timer: UInt, delay: UInt, depth: Int): DecoupledIO[T] = { + val delayQueue = Module(new DelayQueue(chiselTypeOf(source.bits), depth)) + delayQueue.io.enq <> source + delayQueue.io.timer := timer + delayQueue.io.delay := delay + delayQueue.io.deq + } + + /** Helper to connect a delay queue and instantiate a timer to keep track of cycle count. + * + * @param source decoupled queue input + * @param timerWidth width of cycle count timer + * @param delay cycle delay + * @param depth queue size + */ + def apply[T <: Data](source: DecoupledIO[T], timerWidth: Int, delay: UInt, depth: Int): DecoupledIO[T] = { + val timer = RegInit(0.U(timerWidth.W)) + timer := timer + 1.U + apply(source, timer, delay, depth) + } + + /** Helper to connect a delay queue that delays elements by a statically defined cycle count. + * + * @param source decoupled queue input + * @param delay static cycle delay + */ + def apply[T <: Data](source: DecoupledIO[T], delay: Int): DecoupledIO[T] = { + val mDelay = delay.max(1) + apply(source, (1 + log2Ceil(mDelay)), delay.U, mDelay) + } + + /** Helper to connect a delay queue that delays elements by a dynamically set cycle count. + * + * @param source decoupled queue input + * @param delay cycle delay + * @param maxDelay maximum cycle delay + */ + def apply[T <: Data](source: DecoupledIO[T], delay: UInt, maxDelay: Int = 4096): DecoupledIO[T] = { + val mDelay = maxDelay.max(1) + apply(source, (1 + log2Ceil(mDelay)), delay, mDelay) + } +} diff --git a/rocketutils/rocketutils/src/rocketutils/DescribedSRAM.scala b/rocketutils/rocketutils/src/rocketutils/DescribedSRAM.scala new file mode 100644 index 00000000000..5726d525086 --- /dev/null +++ b/rocketutils/rocketutils/src/rocketutils/DescribedSRAM.scala @@ -0,0 +1,40 @@ +// See LICENSE.Berkeley for license details. +// See LICENSE.SiFive for license details. + +package org.chipsalliance.rocketutils + +import chisel3.{Data, SyncReadMem, Vec} +import chisel3.util.log2Ceil + +object DescribedSRAM { + def apply[T <: Data]( + name: String, + desc: String, + size: BigInt, // depth + data: T + ): SyncReadMem[T] = { + + val mem = SyncReadMem(size, data) + + mem.suggestName(name) + + val granWidth = data match { + case v: Vec[_] => v.head.getWidth + case d => d.getWidth + } + + val uid = 0 + + Annotated.srams( + component = mem, + name = name, + address_width = log2Ceil(size), + data_width = data.getWidth, + depth = size, + description = desc, + write_mask_granularity = granWidth + ) + + mem + } +} diff --git a/rocketutils/rocketutils/src/rocketutils/ECC.scala b/rocketutils/rocketutils/src/rocketutils/ECC.scala new file mode 100644 index 00000000000..0c401407c7e --- /dev/null +++ b/rocketutils/rocketutils/src/rocketutils/ECC.scala @@ -0,0 +1,233 @@ +// See LICENSE.Berkeley for license details. + +package org.chipsalliance.rocketutils + +import chisel3._ +import chisel3.util._ +import chisel3.util.random.LFSR + +abstract class Decoding +{ + def uncorrected: UInt + def corrected: UInt + def correctable: Bool + def uncorrectable: Bool // If true, correctable should be ignored + def error = correctable || uncorrectable +} + +abstract class Code +{ + def canDetect: Boolean + def canCorrect: Boolean + + def width(w0: Int): Int + + /** Takes the unencoded width and returns a list of indices indicating which + * bits of the encoded value will be used for ecc + */ + def eccIndices(width: Int): Seq[Int] + + /** Encode x to a codeword suitable for decode. + * If poison is true, the decoded value will report uncorrectable + * error despite uncorrected == corrected == x. + */ + def encode(x: UInt, poison: Bool = false.B): UInt + def decode(x: UInt): Decoding + + /** Copy the bits in x to the right bit positions in an encoded word, + * so that x === decode(swizzle(x)).uncorrected; but don't generate + * the other code bits, so decode(swizzle(x)).error might be true. + * For codes for which this operation is not trivial, throw an + * UnsupportedOperationException. */ + def swizzle(x: UInt): UInt +} + +class IdentityCode extends Code +{ + def canDetect = false + def canCorrect = false + + def width(w0: Int) = w0 + def eccIndices(width: Int) = Seq.empty[Int] + def encode(x: UInt, poison: Bool = false.B) = { + require (poison.isLit && poison.litValue == 0, "IdentityCode can not be poisoned") + x + } + def swizzle(x: UInt) = x + def decode(y: UInt) = new Decoding { + def uncorrected = y + def corrected = y + def correctable = false.B + def uncorrectable = false.B + } +} + +class ParityCode extends Code +{ + def canDetect = true + def canCorrect = false + + def width(w0: Int) = w0+1 + def eccIndices(w0: Int) = Seq(w0) + def encode(x: UInt, poison: Bool = false.B) = Cat(x.xorR ^ poison, x) + def swizzle(x: UInt) = Cat(false.B, x) + def decode(y: UInt) = new Decoding { + val uncorrected = y(y.getWidth-2,0) + val corrected = uncorrected + val correctable = false.B + val uncorrectable = y.xorR + } +} + +class SECCode extends Code +{ + def canDetect = true + def canCorrect = true + + // SEC codes may or may not be poisonous depending on the length + // If the code is perfect, every non-codeword is correctable + def poisonous(n: Int) = !isPow2(n+1) + + def width(k: Int) = { + val m = log2Floor(k) + 1 + k + m + (if((1 << m) < m+k+1) 1 else 0) + } + + def eccIndices(w0: Int) = { + (0 until width(w0)).collect { + case i if i >= w0 => i + } + } + + def swizzle(x: UInt) = { + val k = x.getWidth + val n = width(k) + Cat(0.U((n-k).W), x) + } + + // An (n=16, k=11) Hamming code is naturally encoded as: + // PPxPxxxPxxxxxxxP where P are parity bits and x are data + // Indexes typically start at 1, because then the P are on powers of two + // In systematic coding, you put all the data in the front: + // xxxxxxxxxxxPPPPP + // Indexes typically start at 0, because Computer Science + // For sanity when reading SRAMs, you want systematic form. + + private def impl(n: Int, k: Int) = { + require (n >= 3 && k >= 1 && !isPow2(n)) + val hamm2sys = IndexedSeq.tabulate(n+1) { i => + if (i == 0) { + n /* undefined */ + } else if (isPow2(i)) { + k + log2Ceil(i) + } else { + i - 1 - log2Ceil(i) + } + } + val sys2hamm = hamm2sys.zipWithIndex.sortBy(_._1).map(_._2).toIndexedSeq + def syndrome(j: Int) = { + val bit = 1 << j + ("b" + Seq.tabulate(n) { i => + if ((sys2hamm(i) & bit) != 0) "1" else "0" + }.reverse.mkString).U + } + (hamm2sys, sys2hamm, syndrome _) + } + + def encode(x: UInt, poison: Bool = false.B) = { + val k = x.getWidth + val n = width(k) + val (_, _, syndrome) = impl(n, k) + + require ((poison.isLit && poison.litValue == 0) || poisonous(n), s"SEC code of length ${n} cannot be poisoned") + + /* By setting the entire syndrome on poison, the corrected bit falls off the end of the code */ + val syndromeUInt = VecInit.tabulate(n-k) { j => (syndrome(j)(k-1, 0) & x).xorR ^ poison }.asUInt + Cat(syndromeUInt, x) + } + + def decode(y: UInt) = new Decoding { + val n = y.getWidth + val k = n - log2Ceil(n) + val (_, sys2hamm, syndrome) = impl(n, k) + + val syndromeUInt = VecInit.tabulate(n-k) { j => (syndrome(j) & y).xorR }.asUInt + + val hammBadBitOH = UIntToOH(syndromeUInt, n+1) + val sysBadBitOH = VecInit.tabulate(k) { i => hammBadBitOH(sys2hamm(i)) }.asUInt + + val uncorrected = y(k-1, 0) + val corrected = uncorrected ^ sysBadBitOH + val correctable = syndromeUInt.orR + val uncorrectable = if (poisonous(n)) { syndromeUInt > n.U } else { false.B } + } +} + +class SECDEDCode extends Code +{ + def canDetect = true + def canCorrect = true + + private val sec = new SECCode + private val par = new ParityCode + + def width(k: Int) = sec.width(k)+1 + def eccIndices(w0: Int) = { + (0 until width(w0)).collect { + case i if i >= w0 => i + } + } + def encode(x: UInt, poison: Bool = false.B) = { + // toggling two bits ensures the error is uncorrectable + // to ensure corrected == uncorrected, we pick one redundant + // bit from SEC (the highest); correcting it does not affect + // corrected == uncorrected. the second toggled bit is the + // parity bit, which also does not appear in the decoding + val toggle_lo = Cat(poison.asUInt, poison.asUInt) + val toggle_hi = toggle_lo << (sec.width(x.getWidth)-1) + par.encode(sec.encode(x)) ^ toggle_hi + } + def swizzle(x: UInt) = par.swizzle(sec.swizzle(x)) + def decode(x: UInt) = new Decoding { + val secdec = sec.decode(x(x.getWidth-2,0)) + val pardec = par.decode(x) + + val uncorrected = secdec.uncorrected + val corrected = secdec.corrected + val correctable = pardec.uncorrectable + val uncorrectable = !pardec.uncorrectable && secdec.correctable + } +} + +object ErrGen +{ + // generate a 1-bit error with approximate probability 2^-f + def apply(width: Int, f: Int): UInt = { + require(width > 0 && f >= 0 && log2Up(width) + f <= 16) + UIntToOH(LFSR(16)(log2Up(width)+f-1,0))(width-1,0) + } + def apply(x: UInt, f: Int): UInt = x ^ apply(x.getWidth, f) +} + +trait CanHaveErrors extends Bundle { + val correctable: Option[ValidIO[UInt]] + val uncorrectable: Option[ValidIO[UInt]] +} + +case class ECCParams( + bytes: Int = 1, + code: Code = new IdentityCode, + notifyErrors: Boolean = false, +) + +object Code { + def fromString(s: Option[String]): Code = fromString(s.getOrElse("none")) + def fromString(s: String): Code = s.toLowerCase match { + case "none" => new IdentityCode + case "identity" => new IdentityCode + case "parity" => new ParityCode + case "sec" => new SECCode + case "secded" => new SECDEDCode + case _ => throw new IllegalArgumentException("Unknown ECC type") + } +} diff --git a/rocketutils/rocketutils/src/rocketutils/ElaborationArtefactAnnotation.scala b/rocketutils/rocketutils/src/rocketutils/ElaborationArtefactAnnotation.scala new file mode 100644 index 00000000000..7c9ca94aa7f --- /dev/null +++ b/rocketutils/rocketutils/src/rocketutils/ElaborationArtefactAnnotation.scala @@ -0,0 +1,155 @@ +// See LICENSE.SiFive for license details. + +package org.chipsalliance.rocketutils + +import firrtl.RenameMap +import firrtl.annotations.{Annotation, HasSerializationHints} +import firrtl.annotations.{IsModule, ReferenceTarget} + +import chisel3.{Data, SyncReadMem} +import chisel3.experimental.{BaseModule, ChiselAnnotation} + +import scala.collection.mutable + +/** Like [[ElaborationArtefact]] but in annotation form. + * + * Does not implement [[CustomFileEmission]] because outputFile should be + * interpreted as the final, static filepath instead of computing from + * [[StageOptions]]. This is because the full outputFile path is computed by + * chisel but the contents are emitted by firrtl, which may have a different + * set of [[StageOptions]]. + * + * FIXME: tokens should be [[List[Token]]] but JSON serialization fails with + * "no usable constructor for Token" + */ +case class ElaborationArtefactAnnotation(outputFile: String, tokens: List[Any]) extends Annotation with HasSerializationHints { + def update(renames: RenameMap): Seq[Annotation] = { + Seq(this.copy(tokens = tokens.collect { + case t: Token => t.update(renames) + case other => Seq(other) + }.flatten)) + } + + def typeHints: Seq[Class[_]] = Seq( + classOf[Token], + classOf[StringToken], + classOf[ModulePathToken], + classOf[ReferencePathToken], + ) +} + +object ElaborationArtefactAnnotation { + /** Emits [[ElaborationArtefactAnnotation]] for the given filename extension and tokens. + */ + def annotate(filename: String, tokens: => Seq[Token]): Unit = { + chisel3.experimental.annotate(new ChiselAnnotation { + def toFirrtl = ElaborationArtefactAnnotation(filename, tokens.toList) + }) + } +} + + +sealed trait Token { + def update(renames: RenameMap): Seq[Token] +} + +case class StringToken(value: String) extends Token { + def update(renames: RenameMap) = Seq(this) +} + +case class ModulePathToken(target: IsModule) extends Token { + def update(renames: RenameMap) = { + renames.get(target) match { + case None => Seq(this) + case Some(Seq(newModule: IsModule)) => Seq(this.copy(target = newModule)) + case Some(other) => throw new Exception(s"module $target cannot be renamed to $other") + } + } +} + +case class MemoryPathToken(target: ReferenceTarget) extends Token { + def update(renames: RenameMap) = { + renames.get(target) match { + case None => Seq(this) + case Some(Seq()) => throw new Exception(s"memory $target was deleted") + case Some(Seq(one: ReferenceTarget)) => Seq(this.copy(target = one)) + case Some(many) => + many.tail.foldLeft(Seq[Token](MemoryPathToken(many.head.asInstanceOf[ReferenceTarget]))) { + case (tokens, r: ReferenceTarget) => this.copy(target = r) +: StringToken(" ") +: tokens + }.reverse + } + } +} + +case class ReferencePathToken(target: ReferenceTarget) extends Token { + def update(renames: RenameMap) = { + renames.get(target) match { + case None => Seq(this) + case Some(Seq(newRef: ReferenceTarget)) => Seq(this.copy(target = newRef)) + case Some(other) => throw new Exception(s"reference $target cannot be renamed to $other") + } + } +} + +object Token { + /** An interpolator that generates tokens. Arguments for which a + * [[Tokenizer]] instance is defined will be turned into a [[Token]] using + * the [[Tokenizer]] instance, [[Seq]] elements will be recursively + * converted to Tokens, and all other values will be turned into + * [[StringToken]]s using their .toString method. + */ + implicit class TokensInterpolator(private val sc: StringContext) extends AnyVal { + def tokens(args: Any*): Seq[Token] = { + val strings = sc.parts.map(StringContext.treatEscapes).iterator + val expressions = args.iterator + var tokenBuf = new mutable.ArrayBuffer[Token]() + // buffer to build up the next string token + val stringBuf = new StringBuilder(strings.next()) + def append(any: Any): Unit = { + var nonStringToken: Option[Token] = None + any match { + case s: String => stringBuf ++= s + case d: Data => nonStringToken = Some(Token(d)) + case m: SyncReadMem[_] => nonStringToken= Some(Token(m)) + case m: BaseModule => nonStringToken = Some(Token(m)) + case t: Token => nonStringToken = Some(t) + case seq: Seq[_] => seq.foreach(append) + case other => stringBuf ++= other.toString + } + if (nonStringToken.isDefined) { + if (stringBuf.nonEmpty) { + tokenBuf += StringToken(stringBuf.toString) + stringBuf.clear() + } + tokenBuf += nonStringToken.get + } + } + while (strings.hasNext) { + append(expressions.next()) + stringBuf ++= strings.next() + } + tokenBuf += StringToken(stringBuf.toString) + tokenBuf.toSeq + } + } + + def apply[T: Tokenizer](t: T): Token = Tokenizer[T].toToken(t) +} + + +sealed trait Tokenizer[T] { + def toToken(t: T): Token +} + +object Tokenizer { + def apply[T: Tokenizer] = implicitly[Tokenizer[T]] + + private def tokenizer[T](fn: T => Token): Tokenizer[T] = new Tokenizer[T] { + def toToken(t: T) = fn(t) + } + + implicit def stringTokenizer: Tokenizer[String] = tokenizer(StringToken(_: String)) + implicit def modulePathTokenizer: Tokenizer[BaseModule] = tokenizer((m: BaseModule) => ModulePathToken(m.toTarget)) + implicit def memPathTokenizer[T <: Data]: Tokenizer[SyncReadMem[T]] = tokenizer((m: SyncReadMem[_]) => MemoryPathToken(m.toTarget)) + implicit def refPathTokenizer[T <: Data]: Tokenizer[T] = tokenizer((d: T) => ReferencePathToken(d.toTarget)) +} diff --git a/rocketutils/rocketutils/src/rocketutils/Frequency.scala b/rocketutils/rocketutils/src/rocketutils/Frequency.scala new file mode 100644 index 00000000000..de3d02e8dff --- /dev/null +++ b/rocketutils/rocketutils/src/rocketutils/Frequency.scala @@ -0,0 +1,44 @@ +// See LICENSE.SiFive for license details. +// See LICENSE.Berkeley for license details. + +package org.chipsalliance.rocketutils + +import chisel3._ +import chisel3.util._ + +/** Given a list of (frequency, value) pairs, return a random value + * according to the frequency distribution. The sum of the + * frequencies in the distribution must be a power of two. + */ +object Frequency { + def apply(dist : List[(Int, Bits)]) : Bits = { + // Distribution must be non-empty + require(dist.length > 0) + + // Require that the frequencies sum to a power of two + val (freqs, vals) = dist.unzip + val total = freqs.sum + require(isPow2(total)) + + // First item in the distribution + val (firstFreq, firstVal) = dist.head + + // Result wire + val result = Wire(Bits(firstVal.getWidth.W)) + result := 0.U + + // Random value + val randVal = LCG(log2Up(total)) + + // Pick return value + var count = firstFreq + var select = when (randVal < firstFreq.U) { result := firstVal } + for (p <- dist.drop(1)) { + count = count + p._1 + select = select.elsewhen(randVal < count.U) { result := p._2 } + } + + return result + } +} + diff --git a/rocketutils/rocketutils/src/rocketutils/GeneratorUtils.scala b/rocketutils/rocketutils/src/rocketutils/GeneratorUtils.scala new file mode 100644 index 00000000000..d7a51d0a052 --- /dev/null +++ b/rocketutils/rocketutils/src/rocketutils/GeneratorUtils.scala @@ -0,0 +1,15 @@ +// See LICENSE.SiFive for license details. + +package org.chipsalliance.rocketutils + +object ElaborationArtefacts { + var files: Seq[(String, () => String)] = Nil + + def add(extension: String, contents: => String): Unit = { + files = (extension, () => contents) +: files + } + + def contains(extension: String): Boolean = { + files.foldLeft(false)((t, s) => {s._1 == extension | t}) + } +} diff --git a/rocketutils/rocketutils/src/rocketutils/HellaQueue.scala b/rocketutils/rocketutils/src/rocketutils/HellaQueue.scala new file mode 100644 index 00000000000..01fa53d1ca4 --- /dev/null +++ b/rocketutils/rocketutils/src/rocketutils/HellaQueue.scala @@ -0,0 +1,63 @@ +// See LICENSE.Berkeley for license details. + +package org.chipsalliance.rocketutils + +import chisel3._ +import chisel3.util._ + +class HellaFlowQueue[T <: Data](val entries: Int)(data: => T) extends Module { + val io = IO(new QueueIO(data, entries)) + require(entries > 1) + + val do_flow = Wire(Bool()) + val do_enq = io.enq.fire && !do_flow + val do_deq = io.deq.fire && !do_flow + + val maybe_full = RegInit(false.B) + val enq_ptr = Counter(do_enq, entries)._1 + val (deq_ptr, deq_done) = Counter(do_deq, entries) + when (do_enq =/= do_deq) { maybe_full := do_enq } + + val ptr_match = enq_ptr === deq_ptr + val empty = ptr_match && !maybe_full + val full = ptr_match && maybe_full + val atLeastTwo = full || enq_ptr - deq_ptr >= 2.U + do_flow := empty && io.deq.ready + + val ram = SyncReadMem(entries, data) + when (do_enq) { ram.write(enq_ptr, io.enq.bits) } + + // BUG! does not hold the output of the SRAM when !ready + // ... However, HellaQueue is correct due to the pipe stage + val ren = io.deq.ready && (atLeastTwo || !io.deq.valid && !empty) + val raddr = Mux(io.deq.valid, Mux(deq_done, 0.U, deq_ptr + 1.U), deq_ptr) + val ram_out_valid = RegNext(ren) + + io.deq.valid := Mux(empty, io.enq.valid, ram_out_valid) + io.enq.ready := !full + io.deq.bits := Mux(empty, io.enq.bits, ram.read(raddr, ren)) + + // Count was never correctly set. To keep the same behavior across chisel3 upgrade, we are explicitly setting it to DontCare + io.count := DontCare +} + +class HellaQueue[T <: Data](val entries: Int)(data: => T) extends Module { + val io = IO(new QueueIO(data, entries)) + + val fq = Module(new HellaFlowQueue(entries)(data)) + fq.io.enq <> io.enq + io.deq <> Queue(fq.io.deq, 1, pipe = true) + io.count := fq.io.count +} + +object HellaQueue { + def apply[T <: Data](enq: DecoupledIO[T], entries: Int) = { + val q = Module((new HellaQueue(entries)) { enq.bits }) + q.io.enq.valid := enq.valid // not using <> so that override is allowed + q.io.enq.bits := enq.bits + enq.ready := q.io.enq.ready + q.io.deq + } +} + + diff --git a/rocketutils/rocketutils/src/rocketutils/IDPool.scala b/rocketutils/rocketutils/src/rocketutils/IDPool.scala new file mode 100644 index 00000000000..cd8901433fa --- /dev/null +++ b/rocketutils/rocketutils/src/rocketutils/IDPool.scala @@ -0,0 +1,55 @@ +// See LICENSE.SiFive for license details. + +package org.chipsalliance.rocketutils + +import chisel3._ +import chisel3.util._ + +class IDPool(numIds: Int, lateValid: Boolean = false, revocableSelect: Boolean = false) extends Module { + require (numIds > 0) + val idWidth = log2Up(numIds) + + val io = IO(new Bundle { + val free = Flipped(Valid(UInt(idWidth.W))) + val alloc = if (revocableSelect) Decoupled(UInt(idWidth.W)) else Irrevocable(UInt(idWidth.W)) + }) + + // True indicates that the id is available + val bitmap = RegInit(UInt(numIds.W), -1.S(numIds.W).asUInt) + val select = RegInit(0.U(idWidth.W)) + val valid = RegInit(true.B) + + io.alloc.valid := (if (lateValid) bitmap.orR else valid) + io.alloc.bits := (if (revocableSelect) PriorityEncoder(bitmap) else select) + + val taken = Mux(io.alloc.ready, UIntToOH(io.alloc.bits, numIds), 0.U) + val allocated = Mux(io.free .valid, UIntToOH(io.free .bits, numIds), 0.U) + val bitmap1 = (bitmap & ~taken) | allocated + val select1 = PriorityEncoder(bitmap1) + val valid1 = ( (bitmap.orR && !((PopCount(bitmap) === 1.U) && io.alloc.ready)) // bitmap not zero, and not allocating last bit + || io.free.valid) + + // Clock gate the bitmap + when (io.alloc.ready || io.free.valid) { + bitmap := bitmap1 + valid := valid1 + } + + // Make select irrevocable + when (io.alloc.ready || (!io.alloc.valid && io.free.valid)) { + select := select1 + } + + // No double freeing + assert (!io.free.valid || !(bitmap & ~taken)(io.free.bits)) + + // pre-calculations for timing + if (!lateValid) { + assert (valid === bitmap.orR) + } + if (!revocableSelect) { + when (io.alloc.valid && RegNext(io.alloc.ready || (!io.alloc.valid && io.free.valid))) { + assert (select === PriorityEncoder(bitmap)) + } + } +} diff --git a/rocketutils/rocketutils/src/rocketutils/LCG.scala b/rocketutils/rocketutils/src/rocketutils/LCG.scala new file mode 100644 index 00000000000..5882e99ceb4 --- /dev/null +++ b/rocketutils/rocketutils/src/rocketutils/LCG.scala @@ -0,0 +1,56 @@ +// See LICENSE.SiFive for license details. +// See LICENSE.Berkeley for license details. + +package org.chipsalliance.rocketutils + +import chisel3._ +import chisel3.util.Cat + +/** A 16-bit psuedo-random generator based on a linear conguential + * generator (LCG). The state is stored in an unitialised register. + * When using the C++ backend, it is straigtforward to arrange a + * random initial value for each uninitialised register, effectively + * seeding each LCG16 instance with a different seed. + */ +class LCG16 extends Module { + val io = IO(new Bundle { + val out = Output(UInt(16.W)) + val inc = Input(Bool()) + }) + val state = Reg(UInt(32.W)) + when (io.inc) { + state := state * 1103515245.U(32.W) + 12345.U(32.W) + } + io.out := state(30, 15) +} + +/** An n-bit psuedo-random generator made from many instances of a + * 16-bit LCG. Parameter 'width' must be larger than 0. + */ +class LCG(val w: Int) extends Module { + val io = IO(new Bundle { + val out = Output(UInt(w.W)) + val inc = Input(Bool()) + }) + require(w > 0) + val numLCG16s : Int = (w+15)/16 + val outs = Seq.fill(numLCG16s) { LCG16(io.inc) } + io.out := Cat(outs) +} + +object LCG16 { + def apply(inc: Bool = true.B): UInt = { + val lcg = Module(new LCG16) + lcg.io.inc := inc + lcg.io.out + } +} + +object LCG { + def apply(w: Int, inc: Bool = true.B): UInt = { + val lcg = Module(new LCG(w)) + lcg.io.inc := inc + lcg.io.out + } +} + diff --git a/rocketutils/rocketutils/src/rocketutils/LanePositionedQueue.scala b/rocketutils/rocketutils/src/rocketutils/LanePositionedQueue.scala new file mode 100644 index 00000000000..347c573dea2 --- /dev/null +++ b/rocketutils/rocketutils/src/rocketutils/LanePositionedQueue.scala @@ -0,0 +1,510 @@ +// See LICENSE.SiFive for license details. + +package org.chipsalliance.rocketutils + +import chisel3._ +import chisel3.util._ + +import org.chipsalliance.rocketutils.conversions._ + +/////////////////////////////// Abstract API for the Queue ///////////////////////// + +class LanePositionedDecoupledIO[T <: Data](private val gen: T, val maxValid: Int, val maxReady: Int) extends Bundle { + val validBits1 = log2Ceil(maxValid+1) // [0, maxValid] + val readyBits1 = log2Ceil(maxReady+1) // [0, maxReady] + val lanes = maxValid min maxReady // at most this many element flow per-cycle + + val ready = Input (UInt(readyBits1.W)) + val valid = Output(UInt(validBits1.W)) + val bits = Output(Vec(lanes, gen)) + + def cap_ready(l: Int = lanes) = if (l == maxReady) { + ready + } else { + val lo = if (l==1) 0.U else ready(log2Ceil(l)-1,0) + Mux(ready >= l.U, l.U, lo) + } + + def cap_valid(l: Int = lanes) = if (l == maxValid) { + valid + } else { + val lo = if (l==1) 0.U else valid(log2Ceil(l)-1,0) + Mux(valid >= l.U, l.U, lo) + } + + def min(x: UInt, y: UInt, lanes: Int) = { + val xlo = if (lanes==1) 0.U else x(log2Ceil(lanes)-1, 0) + val ylo = if (lanes==1) 0.U else y(log2Ceil(lanes)-1, 0) + val xhi = x >= lanes.U + val yhi = y >= lanes.U + val xly = xlo <= ylo + Mux(xhi && yhi, lanes.U, Mux(Mux(xly, !xhi, yhi), xlo, ylo)) + } + + def clamp_ready(x: UInt): Unit = { ready := min(x, valid, lanes) } + def clamp_valid(x: UInt): Unit = { valid := min(x, ready, lanes) } + + // Feed from LPQ from another + def driveWith(x: LanePositionedDecoupledIO[T], selfRotation: UInt = 0.U, xRotation: UInt = 0.U): Unit = { + val limit = lanes min x.lanes + val moved = min(ready, x.valid, limit) + valid := moved + x.ready := moved + + if (lanes == x.lanes) { + bits := RotateVector.left(x.bits, selfRotation - xRotation) + } else { + val right = RotateVector.right(x.bits, xRotation) + val padding = Wire(Vec(lanes, gen)) + val pad = (right ++ padding).take(lanes) + val left = RotateVector.left(pad, selfRotation) + padding := DontCare + bits := left + } + } +} + +case class LanePositionedQueueArgs( + lanes: Int, + rows: Int, + flow: Boolean = false, // single cycle feedback from enq=>deq + pipe: Boolean = false, // single cycle feedback from deq=>enq + free: Boolean = false, // split deq pointer from free pointer + enable free IO + commit: Boolean = false, // split enq pointer from commit pointer + enable commit IO + rewind: Boolean = false, // enable the 'rewind' feature + abort: Boolean = false) // enable the 'abort' feature +{ + require (!rewind || free) + require (!abort || commit) +} + +class LanePositionedQueueIO[T <: Data](private val gen: T, val args: LanePositionedQueueArgs) extends Bundle { + val lanes = args.lanes + val depth = args.rows * lanes + val laneBitsU = log2Up(lanes) + val depthBitsU = log2Up(depth) + + // enq.valid elements are enqueued; enq.valid must be <= enq.ready min lanes + val enq = Flipped(new LanePositionedDecoupledIO(gen, lanes, depth)) + // deq.ready elements are dequeued; deq.ready must be <= deq.valid min lanes + val deq = new LanePositionedDecoupledIO(gen, depth, lanes) + + // The 0th element enqueued comes from enq.bits(enq_0_lane), later elements wrap + val enq_0_lane = Output(UInt(laneBitsU.W)) + val deq_0_lane = Output(UInt(laneBitsU.W)) + + // Free-up space for enq; ready only if free.bits would not pass deq + // free.ready includes same-cycle space from deq.ready + val free = if (args.free) Some(Flipped(Decoupled(UInt(depthBitsU.W)))) else None + // Rewind the deq/read pointer to the free pointer + // Same-cycle free is included in the 'rewound' pointer state + // deq.valid may go to 0 for a few cycles after rewind + val rewind = if (args.rewind) Some(Input(Bool())) else None + + // Advance the commited space; ready only if commit.bits would not pass enq + // commit.ready includes same-cycle space from enq.valid + val commit = if (args.commit) Some(Flipped(Decoupled(UInt(depthBitsU.W)))) else None + // Restore the enq/write pointer to the commit pointer + // Same-cycle commit is included into the 'aborted' pointer state + // enq.ready may go to 0 for a few cycles after abort + val abort = if (args.abort) Some(Input(Bool())) else None + + // Connect two LPQs (enq <= deq) + def driveWith(x: LanePositionedQueueIO[T]): Unit = { enq.driveWith(x.deq, enq_0_lane, x.deq_0_lane) } +} + +trait LanePositionedQueueModule[T <: Data] extends Module { + val io: LanePositionedQueueIO[T] +} + +trait LanePositionedQueue { + def apply[T <: Data](gen: T, args: LanePositionedQueueArgs): LanePositionedQueueModule[T] + def apply[T <: Data]( + gen: T, + lanes: Int, + rows: Int, + flow: Boolean = false, + pipe: Boolean = false, + free: Boolean = false, + commit: Boolean = false, + rewind: Boolean = false, + abort: Boolean = false): LanePositionedQueueModule[T] = + apply(gen, LanePositionedQueueArgs(lanes, rows, flow, pipe, free, commit, rewind, abort)) +} + +/////////////////////////////// Index math implementation ////////////////////////// + +// A shared base class that keeps track of the indexing and flow control +class LanePositionedQueueBase[T <: Data](val gen: T, args: LanePositionedQueueArgs) extends Module with LanePositionedQueueModule[T] { + val LanePositionedQueueArgs(lanes, rows, flow, pipe, free, commit, rewind, abort) = args + + require (rows >= 1) + require (lanes >= 1) + + val io = IO(new LanePositionedQueueIO(gen, args)) + + val capacity = rows * lanes + val rowBits = log2Ceil(rows) + val laneBits = log2Ceil(lanes) + val laneBits1 = log2Ceil(lanes+1) // [0, lanes] + + def lane(add: UInt): (UInt, Bool) = { + if (lanes == 1) (0.U, add(0)) else { + val out = RegInit(0.U(laneBits.W)) + val z = out +& add + if (isPow2(lanes)) { + out := z + (out, z(laneBits)) + } else { + val s = z - lanes.U + val wrap = s.asSInt >= 0.S + out := Mux(wrap, s, z) + (out, wrap) + } + } + } + + def row(inc: Bool): (UInt, UInt) = { + if (rows == 1) (0.U, 0.U) else { + val out = RegInit(0.U(rowBits.W)) + val out1 = WireInit(out + 1.U) + if (!isPow2(rows)) { + when (out === (rows-1).U) { out1 := 0.U } + } + when (inc) { out := out1 } + (out, out1) + } + } + + val (enq_lane, enq_wrap) = lane(io.enq.valid) + val (deq_lane, deq_wrap) = lane(io.deq.ready) + val (enq_row, enq_row1) = row(enq_wrap) + val (deq_row, deq_row1) = row(deq_wrap) + + val capBits1 = log2Ceil(capacity+1) + val nDeq = RegInit( 0.U(capBits1.W)) // deq.valid + val nFree = RegInit( 0.U(capBits1.W)) // free.ready + val nEnq = RegInit(capacity.U(capBits1.W)) // enq.ready + val nCommit = RegInit( 0.U(capBits1.W)) // commit.ready + + val freed = io.free .map(x => Mux(x.fire, x.bits, 0.U)).getOrElse(io.deq.ready) + val committed = io.commit.map(x => Mux(x.fire, x.bits, 0.U)).getOrElse(io.enq.valid) + io.free.foreach { x => x.ready := x.bits <= nFree + io.deq.ready } + io.commit.foreach { x => x.ready := x.bits <= nCommit + io.enq.valid } + + // Note: can be negative (abort coincides with commit of all remaining enq) + val abortSize = nCommit - committed + val rewindSize = nFree - freed + + val nDeq_next = nDeq + committed - io.deq.ready + val nFree_next = rewindSize + io.deq.ready + val nEnq_next = nEnq + freed - io.enq.valid + val nCommit_next = abortSize + io.enq.valid + + nDeq := nDeq_next + nFree := nFree_next + nEnq := nEnq_next + nCommit := nCommit_next + + val doAbort = io.abort .getOrElse(false.B) + val doRewind = io.rewind.getOrElse(false.B) + + // Updating the indexing for non-power of two is too hard for now. + require (!abort || (isPow2(lanes) && isPow2(rows))) + val enq_set = (if (lanes == 1) enq_row else Cat(enq_row, enq_lane)) - abortSize + when (doAbort) { + if (lanes > 1) enq_lane := enq_set(laneBits-1, 0) + if (rows > 1) enq_row := enq_set >> laneBits + nEnq := nEnq_next + nCommit_next + nCommit := 0.U + } + + require (!rewind || (isPow2(lanes) && isPow2(rows))) + val deq_set = (if (lanes == 1) deq_row else Cat(deq_row, deq_lane)) - rewindSize + when (doRewind) { + if (lanes > 1) deq_lane := deq_set(laneBits-1, 0) + if (rows > 1) deq_row := deq_set >> laneBits + nDeq := nDeq_next + nFree_next + nFree := 0.U + } + + // These variables are only used for the assertion below + val enq_pos = enq_row * lanes.U + enq_lane + val deq_pos = deq_row * lanes.U + deq_lane + val diff_pos = enq_pos + Mux(enq_pos >= deq_pos, 0.U, capacity.U) - deq_pos + assert (nDeq + nCommit === diff_pos || (diff_pos === 0.U && nDeq + nCommit === capacity.U)) + assert (nDeq + nFree + nEnq + nCommit === capacity.U) + + io.enq_0_lane := enq_lane + io.deq_0_lane := deq_lane + io.enq.ready := (if (pipe) nEnq +& freed else nEnq) + io.deq.valid := (if (flow) nDeq +& committed else nDeq) + + // Constraints the user must uphold + assert (io.enq.valid <= io.enq.ready) + assert (io.deq.ready <= io.deq.valid) + assert (io.enq.valid <= lanes.U) + assert (io.deq.ready <= lanes.U) + + val enq_vmask = UIntToOH1(io.enq.valid +& enq_lane, 2*lanes-1).pad(2*lanes) + val enq_lmask = (if (lanes==1) 0.U else UIntToOH1( enq_lane, lanes-1)).pad(2*lanes) + val enq_mask = enq_vmask & ~enq_lmask + + val deq_rmask = UIntToOH1(io.deq.ready +& deq_lane, 2*lanes-1).pad(2*lanes) + val deq_lmask = (if (lanes==1) 0.U else UIntToOH1(deq_lane, lanes-1)).pad(2*lanes) + val deq_mask = deq_rmask & ~deq_lmask + + val deq_bits = Wire(Vec(lanes, gen)) + io.deq.bits := deq_bits + + // Bypass data when enq/deq rows overlap + if (flow) { + val logL = log2Floor((rows-1)*lanes) - 1 + val L = BigInt(1) << logL + val maybe_empty = if (lanes <= L && L <= (rows-1)*lanes/2) { + (free.B && (nFree>>logL).orR) || (nEnq>>logL).orR // nFree >= L || nEnq >= L + } else if (free) { + nFree + nEnq >= lanes.U + } else { + nEnq >= lanes.U + } + + val row0 = deq_row === enq_row && maybe_empty + val row1 = deq_row1 === enq_row + for (i <- 0 until lanes) { + val set = Mux(deq_lmask(i), + Mux(row0, false.B, Mux(row1, enq_lmask(i), true.B)), + Mux(row1, true.B, Mux(row0, enq_lmask(i), true.B))) + when (!set) { io.deq.bits(i) := io.enq.bits(i) } + } + } +} + +/////////////////////////////// Registered implementation ////////////////////////// + +class FloppedLanePositionedQueueModule[T <: Data](gen: T, args: LanePositionedQueueArgs) + extends LanePositionedQueueBase(gen, args) { + + require (rows % 2 == 0) + val bank = Seq.fill(2) { Mem(rows/2, Vec(lanes, gen)) } + + val b0_out = bank(0).read(deq_row1 >> 1) + val b1_out = bank(1).read(deq_row >> 1) + for (l <- 0 until lanes) { + deq_bits(l) := Mux(deq_row(0) ^ deq_lmask(l), b1_out(l), b0_out(l)) + } + + val hi_mask = enq_mask(2*lanes-1, lanes) + val lo_mask = enq_mask(lanes-1, 0) + val b0_mask = Mux(enq_row(0), hi_mask, lo_mask).asBools + val b1_mask = Mux(enq_row(0), lo_mask, hi_mask).asBools + val b0_row = enq_row1 >> 1 + val b1_row = enq_row >> 1 + + bank(0).write(b0_row, io.enq.bits, b0_mask) + bank(1).write(b1_row, io.enq.bits, b1_mask) +} + +object FloppedLanePositionedQueue extends LanePositionedQueue { + def apply[T <: Data](gen: T, args: LanePositionedQueueArgs) = + new FloppedLanePositionedQueueModule(gen, args) +} + +/////////////////////////////// One port implementation //////////////////////////// + +class OnePortLanePositionedQueueModule[T <: Data](ecc: Code)(gen: T, args: LanePositionedQueueArgs) + extends LanePositionedQueueBase(gen, args) { + + require (rows >= 8 && rows % 4 == 0) + // If rows <= 8, use FloppedLanePositionedQueue instead + + // Make the SRAM twice as wide, so that we can use 1RW port + // Read accesses have priority, but we never do two back-back + val codeBits = ecc.width(2*lanes*gen.getWidth) + val ram = SyncReadMem(rows/2, UInt(codeBits.W)) + + val deq_push = deq_wrap && deq_row(0) + val enq_push = enq_wrap && enq_row(0) + val pre_enq_row = Mux(enq_wrap, enq_row1, enq_row) + val pre_deq_row = Mux(deq_wrap, deq_row1, deq_row) + + // Enq refill FSM schedule + val enq_refill = RegInit(0.U(3.W)) + val enq_gap = RegInit(false.B) + val enq_refill_idle = enq_refill === 0.U + val enq_refill_wait0 = enq_refill === 1.U + val enq_refill_wait1 = enq_refill === 2.U + val enq_refill_ren0 = enq_refill === 3.U + val enq_refill_flop0 = enq_refill === 4.U + val enq_refill_ren1 = enq_refill === 5.U + val enq_refill_flop1 = enq_refill === 6.U + + // Deq refill FSM schedule + val deq_refill = RegInit(0.U(3.W)) + val deq_refill_idle = deq_refill === 0.U + val deq_refill_wait0 = deq_refill === 1.U + val deq_refill_ren0 = deq_refill === 2.U + val deq_refill_flop0 = deq_refill === 3.U + val deq_refill_ren1 = deq_refill === 4.U + val deq_refill_flop1 = deq_refill === 5.U + + // The contract between the abort FSM and deq readers is: + // If enq_refill_idle, then all valid data is in SRAM + // If !enq_refill_idle, then partial data must be bypassed + + // Advance enq refill FSM conditionally + io.abort.foreach { a => + enq_gap := false.B + when (enq_refill_idle) { + when (a) { + when (enq_set(laneBits+rowBits-1, laneBits+1) === (pre_enq_row >> 1) && nCommit_next < (2*lanes).U) { + // If we have unwritten data, don't overwrite those values + enq_gap := true.B + } .otherwise { + enq_refill := 1.U + } + } + } .elsewhen (enq_refill_wait0) { + enq_refill := 2.U + } .elsewhen (enq_refill_wait1) { + enq_refill := 3.U + } .elsewhen (enq_refill_ren0) { + when (!deq_push) { enq_refill := 4.U } + } .elsewhen (enq_refill_flop0) { + enq_refill := 5.U + } .elsewhen (enq_refill_ren1) { + when (!deq_push) { enq_refill := 6.U } + } .otherwise { + enq_refill := 0.U + } + } + + // Advance deq_refill FSM on rewind until complete + io.rewind.foreach { r => + when (deq_refill_idle) { + when (r) { deq_refill := 1.U } + } .elsewhen (deq_refill_wait0) { + deq_refill := 2.U + } .elsewhen (deq_refill_ren0) { + when (enq_refill_idle) { deq_refill := 3.U } + } .elsewhen (deq_refill_flop0) { + deq_refill := 4.U + } .elsewhen (deq_refill_ren1) { + when (enq_refill_idle) { deq_refill := 5.U } + } .otherwise { + deq_refill := 0.U + } + } + + // Block deq while deq_refilling after rewinding + when (!deq_refill_idle) { io.deq.valid := 0.U } + // Block enq while enq_refilling after abort + when (!enq_refill_idle) { io.enq.ready := 0.U } + // Also block enq while pipeline clears + when (enq_gap) { io.enq.ready := 0.U } + + val enq_buffer = Reg(Vec(4, Vec(lanes, gen))) + val deq_buffer = Reg(Vec(4, Vec(lanes, gen))) + + val logL = log2Floor((rows-2)*lanes) - 1 // rows >= 8 + val L = BigInt(1) << logL + val next_maybe_empty = if (2*lanes <= L && L <= (rows-2)*lanes/2) { + (free.B && (nFree_next>>logL).orR) || (nEnq_next>>logL).orR // nFree >= L || nEnq >= L + // free <= deq <= commit <= enq <= free + rows*lanes + // nFree nDeq nCommit nEnq + // next_maybe_empty + // => nFree >= L || nEnq >= L + // => deq+capacity - enq >= nFree+nEnq >= L >= 2*lanes + // => (deq+capacity)/(2*lanes) != enq/(2*lanes) + // => not full + // !next_maybe_empty + // => nFree < L && nEnq < L + // => enq-deq = nCommit+nDeq = rows*lanes - nFree - nEnq >= rows*lanes - 2L >= 2*lanes + // => enq/(2*lanes) != deq/(2*lanes) + // => not empty + } else if (free) { + nEnq_next + nFree_next >= (2*lanes).U + } else { + nEnq_next >= (2*lanes).U + } + + val pre_gap = (pre_enq_row >> 1).zext - (pre_deq_row >> 1).zext + val pre_gap0 = pre_gap === 0.S && next_maybe_empty + val pre_gap1 = pre_gap0 || pre_gap === (1-rows/2).S || pre_gap === 1.S + val pre_gap2 = pre_gap1 || pre_gap === (2-rows/2).S || pre_gap === 2.S + val gap0 = RegNext(pre_gap0) + val gap1 = RegNext(pre_gap1) + val gap2 = RegNext(pre_gap2) + + val ren = (deq_push && (!enq_refill_idle || !pre_gap2)) || (enq_refill_idle && (deq_refill_ren0 || deq_refill_ren1)) || enq_refill_ren0 || enq_refill_ren1 + val wen = RegInit(false.B) + + when (!ren) { wen := false.B } + when (enq_push && (rewind.B || !gap1)) { wen := true.B } + + val deq_row_half = deq_row >> 1 + val enq_row_half = enq_row >> 1 + val write_row = RegEnable(enq_row_half, enq_push) + val ram_i = Mux(write_row(0), + VecInit(enq_buffer(2) ++ enq_buffer(3)), + VecInit(enq_buffer(0) ++ enq_buffer(1))) + val read_row = + Mux(enq_refill_ren0 && !deq_push, enq_row_half, + Mux(enq_refill_ren1 && !deq_push, enq_row_half - 1.U, // requires isPow2(rows) + Mux(deq_refill_ren0, deq_row_half, + Mux(deq_refill_ren1, deq_row_half + 1.U, // requires isPow2(rows) + Mux(!isPow2(rows).B && deq_row_half === (rows/2-1).U, 1.U, + Mux(!isPow2(rows).B && deq_row_half === (rows/2-2).U, 0.U, + deq_row_half + 2.U)))))) + val ram_o = ecc.decode(ram.read(read_row, ren)).corrected.asTypeOf(Vec(2*lanes, gen)) + when (wen && !ren) { ram.write(write_row, ecc.encode(ram_i.asUInt)) } + + val abort_bypass = if (abort) { wen && write_row === read_row } else { false.B } + val bypass = RegNext((deq_push && pre_gap2 && enq_refill_idle) || (deq_refill_ren1 && pre_gap2) || (deq_refill_ren0 && pre_gap1) || abort_bypass) + val dlatch0 = RegNext((deq_push && !deq_row(1)) || (deq_refill_ren1 && deq_row(1)) || (deq_refill_ren0 && !deq_row(1))) + val dlatch1 = RegNext((deq_push && deq_row(1)) || (deq_refill_ren1 && !deq_row(1)) || (deq_refill_ren0 && deq_row(1))) + val elatch0 = RegNext((enq_refill_ren1 && enq_row(1)) || (enq_refill_ren0 && !enq_row(1))) + val elatch1 = RegNext((enq_refill_ren1 && !enq_row(1)) || (enq_refill_ren0 && enq_row(1))) + + for (l <- 0 until lanes) { + when (dlatch0) { + deq_buffer(0)(l) := Mux(bypass, enq_buffer(0)(l), ram_o(l)) + deq_buffer(1)(l) := Mux(bypass, enq_buffer(1)(l), ram_o(l+lanes)) + } + when (dlatch1) { + deq_buffer(2)(l) := Mux(bypass, enq_buffer(2)(l), ram_o(l)) + deq_buffer(3)(l) := Mux(bypass, enq_buffer(3)(l), ram_o(l+lanes)) + } + when (elatch0) { + enq_buffer(0)(l) := ram_o(l) + enq_buffer(1)(l) := ram_o(l+lanes) + } + when (elatch1) { + enq_buffer(2)(l) := ram_o(l) + enq_buffer(3)(l) := ram_o(l+lanes) + } + for (r <- 0 until 4) { + val rn = (r+3) % 4 + when ((enq_mask(l) && enq_row(1,0) === r.U) || + (enq_mask(l+lanes) && enq_row(1,0) === rn.U)) { + enq_buffer(r)(l) := io.enq.bits(l) + } + val gap = if (r % 2 == 0) gap0 else gap1 + when ((gap1 && enq_mask(l) && enq_row(1,0) === r.U) || + (gap && enq_mask(l+lanes) && enq_row(1,0) === rn.U)) { + deq_buffer(r)(l) := io.enq.bits(l) + } + } + } + + val deq_buf0 = deq_buffer(deq_row(1,0)) + val deq_buf1 = VecInit.tabulate(4) { i => deq_buffer((i+1) % 4) } (deq_row(1,0)) + for (l <- 0 until lanes) { + deq_bits(l) := Mux(deq_lmask(l), deq_buf1(l), deq_buf0(l)) + } +} + +case class OnePortLanePositionedQueue(ecc: Code) extends LanePositionedQueue { + def apply[T <: Data](gen: T, args: LanePositionedQueueArgs) = + new OnePortLanePositionedQueueModule(ecc)(gen, args) +} diff --git a/rocketutils/rocketutils/src/rocketutils/LatencyPipe.scala b/rocketutils/rocketutils/src/rocketutils/LatencyPipe.scala new file mode 100644 index 00000000000..3f35650830c --- /dev/null +++ b/rocketutils/rocketutils/src/rocketutils/LatencyPipe.scala @@ -0,0 +1,26 @@ +// See LICENSE.Berkeley for license details. + +package org.chipsalliance.rocketutils + +import chisel3._ +import chisel3.util._ + +class LatencyPipe[T <: Data](typ: T, latency: Int) extends Module { + val io = IO(new Bundle { + val in = Flipped(Decoupled(typ)) + val out = Decoupled(typ) + }) + + def doN[T](n: Int, func: T => T, in: T): T = + (0 until n).foldLeft(in)((last, _) => func(last)) + + io.out <> doN(latency, (last: DecoupledIO[T]) => Queue(last, 1, true), io.in) +} + +object LatencyPipe { + def apply[T <: Data](in: DecoupledIO[T], latency: Int): DecoupledIO[T] = { + val pipe = Module(new LatencyPipe(chiselTypeOf(in.bits), latency)) + pipe.io.in <> in + pipe.io.out + } +} diff --git a/rocketutils/rocketutils/src/rocketutils/Location.scala b/rocketutils/rocketutils/src/rocketutils/Location.scala new file mode 100644 index 00000000000..0839bb9b428 --- /dev/null +++ b/rocketutils/rocketutils/src/rocketutils/Location.scala @@ -0,0 +1,36 @@ +// See LICENSE.SiFive for license details. + +package org.chipsalliance.rocketutils + +import scala.language.dynamics +import scala.collection.mutable.Map + +class Location[T](val name: String) extends Dynamic { + def selectDynamic[A](portname: String): Location[A] = new Location[A](s"${name}_${portname}") + def applyDynamic[A](portname: String)(args: A*): (Location[A], A) = { + require(args.size == 1, "Location: can't support multiple things at one port yet") + (new Location[A](s"${name}_${portname}"), args.head) + } + override def toString = s"Location($name)" +} + +object Location { + def apply[T](name: String): Location[T] = new Location[T](name) +} + +class LocationMap[T] private (val internalMap: Map[String, T]) extends Map[Location[_], T] { + def addOne(kv: (Location[_], T)) = { (internalMap += (kv._1.name -> kv._2)); this } + def subtractOne(key: Location[_]) = { (internalMap -= key.name); this } + def get(key: Location[_]) = internalMap.get(key.name) + def iterator = internalMap.iterator.map(kv => (new Location(kv._1), kv._2)) + // TODO override def default to provide specific exception on missing location? + // TODO figure out how to be more clever about applying sub-type casting + // for other the other Map trait methods + def required[L <: T](key: Location[_]): L = internalMap(key.name).asInstanceOf[L] + def optional[L <: T](key: Location[_]): Option[L] = internalMap.lift(key.name).map(_.asInstanceOf[L]) +} + +object LocationMap { + def apply[T](lm: Map[String, T]): LocationMap[T] = new LocationMap(lm) + def empty[T]: LocationMap[T] = new LocationMap(Map.empty[String, T]) +} diff --git a/rocketutils/rocketutils/src/rocketutils/Misc.scala b/rocketutils/rocketutils/src/rocketutils/Misc.scala new file mode 100644 index 00000000000..946aad488c3 --- /dev/null +++ b/rocketutils/rocketutils/src/rocketutils/Misc.scala @@ -0,0 +1,228 @@ +// See LICENSE.Berkeley for license details. +// See LICENSE.SiFive for license details. + +package org.chipsalliance.rocketutils + +import chisel3._ +import chisel3.util._ +import chisel3.util.random.LFSR + +import org.chipsalliance.cde.config.Parameters + +import org.chipsalliance.rocketutils.conversions._ + +import scala.math._ + +class ParameterizedBundle(implicit p: Parameters) extends Bundle + +trait Clocked extends Bundle { + val clock = Clock() + val reset = Bool() +} + +object DecoupledHelper { + def apply(rvs: Bool*) = new DecoupledHelper(rvs) +} + +class DecoupledHelper(val rvs: Seq[Bool]) { + def fire(exclude: Bool, includes: Bool*) = { + require(rvs.contains(exclude), "Excluded Bool not present in DecoupledHelper! Note that DecoupledHelper uses referential equality for exclusion! If you don't want to exclude anything, use fire()!") + (rvs.filter(_ ne exclude) ++ includes).reduce(_ && _) + } + def fire() = { + rvs.reduce(_ && _) + } +} + +object MuxT { + def apply[T <: Data, U <: Data](cond: Bool, con: (T, U), alt: (T, U)): (T, U) = + (Mux(cond, con._1, alt._1), Mux(cond, con._2, alt._2)) + + def apply[T <: Data, U <: Data, W <: Data](cond: Bool, con: (T, U, W), alt: (T, U, W)): (T, U, W) = + (Mux(cond, con._1, alt._1), Mux(cond, con._2, alt._2), Mux(cond, con._3, alt._3)) + + def apply[T <: Data, U <: Data, W <: Data, X <: Data](cond: Bool, con: (T, U, W, X), alt: (T, U, W, X)): (T, U, W, X) = + (Mux(cond, con._1, alt._1), Mux(cond, con._2, alt._2), Mux(cond, con._3, alt._3), Mux(cond, con._4, alt._4)) +} + +/** Creates a cascade of n MuxTs to search for a key value. */ +object MuxTLookup { + def apply[S <: UInt, T <: Data, U <: Data](key: S, default: (T, U), mapping: Seq[(S, (T, U))]): (T, U) = { + var res = default + for ((k, v) <- mapping.reverse) + res = MuxT(k === key, v, res) + res + } + + def apply[S <: UInt, T <: Data, U <: Data, W <: Data](key: S, default: (T, U, W), mapping: Seq[(S, (T, U, W))]): (T, U, W) = { + var res = default + for ((k, v) <- mapping.reverse) + res = MuxT(k === key, v, res) + res + } +} + +object ValidMux { + def apply[T <: Data](v1: ValidIO[T], v2: ValidIO[T]*): ValidIO[T] = { + apply(v1 +: v2.toSeq) + } + def apply[T <: Data](valids: Seq[ValidIO[T]]): ValidIO[T] = { + val out = Wire(Valid(valids.head.bits.cloneType)) + out.valid := valids.map(_.valid).reduce(_ || _) + out.bits := MuxCase(valids.head.bits, + valids.map(v => (v.valid -> v.bits))) + out + } +} + +object Str +{ + def apply(s: String): UInt = { + var i = BigInt(0) + require(s.forall(validChar _)) + for (c <- s) + i = (i << 8) | c + i.U((s.length*8).W) + } + def apply(x: Char): UInt = { + require(validChar(x)) + x.U(8.W) + } + def apply(x: UInt): UInt = apply(x, 10) + def apply(x: UInt, radix: Int): UInt = { + val rad = radix.U + val w = x.getWidth + require(w > 0) + + var q = x + var s = digit(q % rad) + for (i <- 1 until ceil(log(2)/log(radix)*w).toInt) { + q = q / rad + s = Cat(Mux((radix == 10).B && q === 0.U, Str(' '), digit(q % rad)), s) + } + s + } + def apply(x: SInt): UInt = apply(x, 10) + def apply(x: SInt, radix: Int): UInt = { + val neg = x < 0.S + val abs = x.abs.asUInt + if (radix != 10) { + Cat(Mux(neg, Str('-'), Str(' ')), Str(abs, radix)) + } else { + val rad = radix.U + val w = abs.getWidth + require(w > 0) + + var q = abs + var s = digit(q % rad) + var needSign = neg + for (i <- 1 until ceil(log(2)/log(radix)*w).toInt) { + q = q / rad + val placeSpace = q === 0.U + val space = Mux(needSign, Str('-'), Str(' ')) + needSign = needSign && !placeSpace + s = Cat(Mux(placeSpace, space, digit(q % rad)), s) + } + Cat(Mux(needSign, Str('-'), Str(' ')), s) + } + } + + private def digit(d: UInt): UInt = Mux(d < 10.U, Str('0')+d, Str(('a'-10).toChar)+d)(7,0) + private def validChar(x: Char) = x == (x & 0xFF) +} + +object Split +{ + def apply(x: UInt, n0: Int) = { + val w = x.getWidth + (x.extract(w-1,n0), x.extract(n0-1,0)) + } + def apply(x: UInt, n1: Int, n0: Int) = { + val w = x.getWidth + (x.extract(w-1,n1), x.extract(n1-1,n0), x.extract(n0-1,0)) + } + def apply(x: UInt, n2: Int, n1: Int, n0: Int) = { + val w = x.getWidth + (x.extract(w-1,n2), x.extract(n2-1,n1), x.extract(n1-1,n0), x.extract(n0-1,0)) + } +} + +object Random +{ + def apply(mod: Int, random: UInt): UInt = { + if (isPow2(mod)) random.extract(log2Ceil(mod)-1,0) + else PriorityEncoder(partition(apply(1 << log2Up(mod*8), random), mod)) + } + def apply(mod: Int): UInt = apply(mod, randomizer) + def oneHot(mod: Int, random: UInt): UInt = { + if (isPow2(mod)) UIntToOH(random(log2Up(mod)-1,0)) + else PriorityEncoderOH(partition(apply(1 << log2Up(mod*8), random), mod)).asUInt + } + def oneHot(mod: Int): UInt = oneHot(mod, randomizer) + + private def randomizer = LFSR(16) + private def partition(value: UInt, slices: Int) = + Seq.tabulate(slices)(i => value < (((i + 1) << value.getWidth) / slices).U) +} + +object Majority { + def apply(in: Set[Bool]): Bool = { + val n = (in.size >> 1) + 1 + val clauses = in.subsets(n).map(_.reduce(_ && _)) + clauses.reduce(_ || _) + } + + def apply(in: Seq[Bool]): Bool = apply(in.toSet) + + def apply(in: UInt): Bool = apply(in.asBools.toSet) +} + +object PopCountAtLeast { + private def two(x: UInt): (Bool, Bool) = x.getWidth match { + case 1 => (x.asBool, false.B) + case n => + val half = x.getWidth / 2 + val (leftOne, leftTwo) = two(x(half - 1, 0)) + val (rightOne, rightTwo) = two(x(x.getWidth - 1, half)) + (leftOne || rightOne, leftTwo || rightTwo || (leftOne && rightOne)) + } + def apply(x: UInt, n: Int): Bool = n match { + case 0 => true.B + case 1 => x.orR + case 2 => two(x)._2 + case 3 => PopCount(x) >= n.U + } +} + +// This gets used everywhere, so make the smallest circuit possible ... +// Given an address and size, create a mask of beatBytes size +// eg: (0x3, 0, 4) => 0001, (0x3, 1, 4) => 0011, (0x3, 2, 4) => 1111 +// groupBy applies an interleaved OR reduction; groupBy=2 take 0010 => 01 +object MaskGen { + def apply(addr_lo: UInt, lgSize: UInt, beatBytes: Int, groupBy: Int = 1): UInt = { + require (groupBy >= 1 && beatBytes >= groupBy) + require (isPow2(beatBytes) && isPow2(groupBy)) + val lgBytes = log2Ceil(beatBytes) + val sizeOH = UIntToOH(lgSize | 0.U(log2Up(beatBytes).W), log2Up(beatBytes)) | (groupBy*2 - 1).U + + def helper(i: Int): Seq[(Bool, Bool)] = { + if (i == 0) { + Seq((lgSize >= lgBytes.asUInt, true.B)) + } else { + val sub = helper(i-1) + val size = sizeOH(lgBytes - i) + val bit = addr_lo(lgBytes - i) + val nbit = !bit + Seq.tabulate (1 << i) { j => + val (sub_acc, sub_eq) = sub(j/2) + val eq = sub_eq && (if (j % 2 == 1) bit else nbit) + val acc = sub_acc || (size && eq) + (acc, eq) + } + } + } + + if (groupBy == beatBytes) 1.U else + Cat(helper(lgBytes-log2Ceil(groupBy)).map(_._1).reverse) + } +} diff --git a/rocketutils/rocketutils/src/rocketutils/MultiLaneQueue.scala b/rocketutils/rocketutils/src/rocketutils/MultiLaneQueue.scala new file mode 100644 index 00000000000..29093d985bd --- /dev/null +++ b/rocketutils/rocketutils/src/rocketutils/MultiLaneQueue.scala @@ -0,0 +1,59 @@ +// See LICENSE.SiFive for license details. + +package org.chipsalliance.rocketutils + +import chisel3._ +import chisel3.util._ + +class MultiLaneQueue[T <: Data](gen: T, val lanes: Int, val rows: Int, val flow: Boolean = false, storage: LanePositionedQueue = FloppedLanePositionedQueue) extends Module { + val laneBits1 = log2Ceil(lanes+1) // [0, lanes] + + val io = IO(new Bundle { + val enq_ready = Output(Bool()) + val enq_valid = Input(UInt(laneBits1.W)) + val enq_bits = Input(Vec(lanes, gen)) + // NOTE: deq_valid depends on deq_ready + val deq_ready = Input(UInt(laneBits1.W)) + val deq_valid = Output(Bool()) + val deq_bits = Output(Vec(lanes, gen)) + }) + + val queue = Module(storage(gen, lanes, rows, flow)) + + io.enq_ready := io.enq_valid <= queue.io.enq.ready + queue.io.enq.valid := Mux(io.enq_ready, io.enq_valid, 0.U) + queue.io.enq.bits := RotateVector.left(io.enq_bits, queue.io.enq_0_lane) + + io.deq_valid := io.deq_ready <= queue.io.deq.valid + queue.io.deq.ready := Mux(io.deq_valid, io.deq_ready, 0.U) + io.deq_bits := RotateVector.right(queue.io.deq.bits, queue.io.deq_0_lane) +} + +object RotateVector { + def left[T <: Data](input: Seq[T], shift: UInt): Vec[T] = { + val bools = shift.asBools.toVector + def helper(bit: Int, offset: Int, x: Vector[T]): Vector[T] = { + if (offset >= input.size) { + x + } else { + helper(bit+1, offset+offset, Vector.tabulate(x.size) { i => + Mux(bools(bit), x((i+x.size-offset) % x.size), x(i)) + }) + } + } + VecInit(helper(0, 1, input.toVector)) + } + def right[T <: Data](input: Seq[T], shift: UInt): Vec[T] = { + val bools = shift.asBools.toVector + def helper(bit: Int, offset: Int, x: Vector[T]): Vector[T] = { + if (offset >= input.size) { + x + } else { + helper(bit+1, offset+offset, Vector.tabulate(x.size) { i => + Mux(bools(bit), x((i+offset) % x.size), x(i)) + }) + } + } + VecInit(helper(0, 1, input.toVector)) + } +} diff --git a/rocketutils/rocketutils/src/rocketutils/MultiPortQueue.scala b/rocketutils/rocketutils/src/rocketutils/MultiPortQueue.scala new file mode 100644 index 00000000000..41b49aa15aa --- /dev/null +++ b/rocketutils/rocketutils/src/rocketutils/MultiPortQueue.scala @@ -0,0 +1,71 @@ +// See LICENSE.SiFive for license details. + +package org.chipsalliance.rocketutils + +import chisel3._ +import chisel3.util._ + +import org.chipsalliance.rocketutils.conversions._ + +class MultiPortQueue[T <: Data](gen: T, val enq_lanes: Int, val deq_lanes: Int, val lanes: Int, val rows: Int, val flow: Boolean = false, storage: LanePositionedQueue = FloppedLanePositionedQueue) extends Module { + val io = IO(new Bundle { + val enq = Flipped(Vec(enq_lanes, Decoupled(gen))) + // NOTE: deq.{valid,bits} depend on deq.ready of lower-indexed ports + val deq = Vec(deq_lanes, Decoupled(gen)) + }) + + val queue = Module(storage(gen, lanes, rows, flow)) + + MultiPortQueue.gather (io.enq, queue.io.enq, queue.io.enq_0_lane) + MultiPortQueue.scatter(io.deq, queue.io.deq, queue.io.deq_0_lane) +} + +object MultiPortQueue { + def gather[T <: Data](sparse: Seq[DecoupledIO[T]], dense: LanePositionedDecoupledIO[T], offset: UInt = 0.U): Unit = { + // Compute per-enq-port ready + val enq_valid = DensePrefixSum(sparse.map(_.valid.asUInt))(_ +& _) + val low_ready = if (dense.lanes == 1) 0.U else dense.ready(log2Ceil(dense.lanes)-1, 0) + val cap_ready = Mux(dense.ready >= dense.lanes.U, dense.lanes.U, low_ready) + val ready = if (dense.lanes >= sparse.size) dense.ready else cap_ready + dense.valid := Mux(enq_valid.last <= ready, enq_valid.last, ready) + (sparse zip (0.U +: enq_valid)) foreach { case (s, v) => s.ready := v < ready } + + // Gather data from enq ports to rotated lanes + val popBits = log2Ceil(dense.lanes + sparse.size) + val lowHoles = dense.lanes.U(popBits.W) - offset + val highHoles = sparse.map(x => WireInit(UInt(popBits.W), !x.valid)) + val enq_dense = Gather( + Seq.fill(dense.lanes) { 0.U.asTypeOf(chiselTypeOf(sparse.head.bits)) } ++ sparse.map(_.bits), + Seq.fill(dense.lanes) { lowHoles } ++ DensePrefixSum(lowHoles +: highHoles)(_ + _).tail) + + val enq_1hot = UIntToOH1(offset, dense.lanes).pad(dense.lanes) + dense.bits.zipWithIndex.foreach { case (bits, i) => + if (i < sparse.size) { + bits := Mux(enq_1hot(i), enq_dense(i+dense.lanes), enq_dense(i)) + } else { + bits := enq_dense(i) + } + } + } + + def scatter[T <: Data](sparse: Seq[DecoupledIO[T]], dense: LanePositionedDecoupledIO[T], offset: UInt = 0.U): Unit = { + // Computer per-deq-port valid + val deq_ready = DensePrefixSum(sparse.map(_.ready.asUInt))(_ +& _) + val low_valid = if (dense.lanes == 1) 0.U else dense.valid(log2Ceil(dense.lanes)-1, 0) + val cap_valid = Mux(dense.valid >= dense.lanes.U, dense.lanes.U, low_valid) + val valid = if (dense.lanes >= sparse.size) dense.valid else cap_valid + dense.ready := Mux(deq_ready.last <= valid, deq_ready.last, valid) + (sparse zip (0.U +: deq_ready)) foreach { case (s, r) => s.valid := r < valid } + + // Scatter data from rotated lanes to deq ports + val bits = dense.bits ++ dense.bits ++ Seq.fill(sparse.size) { 0.U.asTypeOf(chiselTypeOf(sparse.head.bits)) } + val popBits = log2Ceil(dense.lanes + sparse.size) + val lowHoles = dense.lanes.U(popBits.W) - offset + val highHoles = sparse.map(x => WireInit(UInt(popBits.W), !x.ready)) + val deq_sparse = Scatter( + bits.take(dense.lanes + sparse.size), + Seq.fill(dense.lanes) { lowHoles } ++ DensePrefixSum(lowHoles +: highHoles)(_ + _).tail) + + sparse.zipWithIndex.foreach { case (s, i) => s.bits := deq_sparse(i+dense.lanes) } + } +} diff --git a/rocketutils/rocketutils/src/rocketutils/MultiWidthFifo.scala b/rocketutils/rocketutils/src/rocketutils/MultiWidthFifo.scala new file mode 100644 index 00000000000..44af08e6ef3 --- /dev/null +++ b/rocketutils/rocketutils/src/rocketutils/MultiWidthFifo.scala @@ -0,0 +1,80 @@ +// See LICENSE.Berkeley for license details. + +package org.chipsalliance.rocketutils + +import chisel3._ +import chisel3.util._ + +class MultiWidthFifo(inW: Int, outW: Int, n: Int) extends Module { + val io = IO(new Bundle { + val in = Flipped(Decoupled(Bits(inW.W))) + val out = Decoupled(Bits(outW.W)) + val count = Output(UInt(log2Up(n + 1).W)) + }) + + if (inW == outW) { + val q = Module(new Queue(Bits(inW.W), n)) + q.io.enq <> io.in + io.out <> q.io.deq + io.count := q.io.count + } else if (inW > outW) { + val nBeats = inW / outW + + require(inW % outW == 0, s"MultiWidthFifo: in: $inW not divisible by out: $outW") + require(n % nBeats == 0, s"Cannot store $n output words when output beats is $nBeats") + + val wdata = Reg(Vec(n / nBeats, Bits(inW.W))) + val rdata = VecInit(wdata.flatMap { indat => + (0 until nBeats).map(i => indat(outW * (i + 1) - 1, outW * i)) }) + + val head = RegInit(0.U(log2Up(n / nBeats).W)) + val tail = RegInit(0.U(log2Up(n).W)) + val size = RegInit(0.U(log2Up(n + 1).W)) + + when (io.in.fire) { + wdata(head) := io.in.bits + head := head + 1.U + } + + when (io.out.fire) { tail := tail + 1.U } + + size := MuxCase(size, Seq( + (io.in.fire && io.out.fire) -> (size + (nBeats - 1).U), + io.in.fire -> (size + nBeats.U), + io.out.fire -> (size - 1.U))) + + io.out.valid := size > 0.U + io.out.bits := rdata(tail) + io.in.ready := size < n.U + io.count := size + } else { + val nBeats = outW / inW + + require(outW % inW == 0, s"MultiWidthFifo: out: $outW not divisible by in: $inW") + + val wdata = Reg(Vec(n * nBeats, Bits(inW.W))) + val rdata = VecInit(Seq.tabulate(n) { i => + Cat(wdata.slice(i * nBeats, (i + 1) * nBeats).reverse)}) + + val head = RegInit(0.U(log2Up(n * nBeats).W)) + val tail = RegInit(0.U(log2Up(n).W)) + val size = RegInit(0.U(log2Up(n * nBeats + 1).W)) + + when (io.in.fire) { + wdata(head) := io.in.bits + head := head + 1.U + } + + when (io.out.fire) { tail := tail + 1.U } + + size := MuxCase(size, Seq( + (io.in.fire && io.out.fire) -> (size - (nBeats - 1).U), + io.in.fire -> (size + 1.U), + io.out.fire -> (size - nBeats.U))) + + io.count := size >> log2Up(nBeats).U + io.out.valid := io.count > 0.U + io.out.bits := rdata(tail) + io.in.ready := size < (n * nBeats).U + } +} diff --git a/rocketutils/rocketutils/src/rocketutils/MuxLiteral.scala b/rocketutils/rocketutils/src/rocketutils/MuxLiteral.scala new file mode 100644 index 00000000000..6c6b371e2cb --- /dev/null +++ b/rocketutils/rocketutils/src/rocketutils/MuxLiteral.scala @@ -0,0 +1,59 @@ +// See LICENSE.SiFive for license details. + +package org.chipsalliance.rocketutils + +import chisel3._ +import chisel3.util.log2Ceil +import scala.reflect.ClassTag + +/* MuxLiteral creates a lookup table from a key to a list of values. + * Unlike MuxLookup, the table keys must be exclusive literals. + */ +object MuxLiteral +{ + def apply[T <: Data:ClassTag](index: UInt, default: T, first: (UInt, T), rest: (UInt, T)*): T = + apply(index, default, first :: rest.toList) + def apply[T <: Data:ClassTag](index: UInt, default: T, cases: Seq[(UInt, T)]): T = + MuxTable(index, default, cases.map { case (k, v) => (k.litValue, v) }) +} + +object MuxSeq +{ + def apply[T <: Data:ClassTag](index: UInt, default: T, first: T, rest: T*): T = + apply(index, default, first :: rest.toList) + def apply[T <: Data:ClassTag](index: UInt, default: T, cases: Seq[T]): T = + MuxTable(index, default, cases.zipWithIndex.map { case (v, i) => (BigInt(i), v) }) +} + +object MuxTable +{ + def apply[T <: Data:ClassTag](index: UInt, default: T, first: (BigInt, T), rest: (BigInt, T)*): T = + apply(index, default, first :: rest.toList) + def apply[T <: Data:ClassTag](index: UInt, default: T, cases: Seq[(BigInt, T)]): T = { + /* All keys must be >= 0 and distinct */ + cases.foreach { case (k, _) => require (k >= 0) } + require (cases.map(_._1).distinct.size == cases.size) + + /* Filter out any cases identical to the default */ + val simple = cases.filter { case (k, v) => !default.isLit || !v.isLit || v.litValue != default.litValue } + + val maxKey = (BigInt(0) +: simple.map(_._1)).max + val endIndex = BigInt(1) << log2Ceil(maxKey+1) + + if (simple.isEmpty) { + default + } else if (endIndex <= 2*simple.size) { + /* The dense encoding case uses a Vec */ + val table = Array.fill(endIndex.toInt) { default } + simple.foreach { case (k, v) => table(k.toInt) = v } + Mux(index >= endIndex.U, default, VecInit(table)(index)) + } else { + /* The sparse encoding case uses switch */ + val out = WireDefault(default) + simple.foldLeft(new chisel3.util.SwitchContext(index, None, Set.empty)) { case (acc, (k, v)) => + acc.is (k.U) { out := v } + } + out + } + } +} diff --git a/rocketutils/rocketutils/src/rocketutils/PSDTestMode.scala b/rocketutils/rocketutils/src/rocketutils/PSDTestMode.scala new file mode 100644 index 00000000000..fed9a27a428 --- /dev/null +++ b/rocketutils/rocketutils/src/rocketutils/PSDTestMode.scala @@ -0,0 +1,27 @@ +// See LICENSE.SiFive for license details. + +package org.chipsalliance.rocketutils + +import chisel3._ + +import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy._ +import org.chipsalliance.diplomacy.bundlebridge._ + +import org.chipsalliance.rocketutils.conversions._ + +case object IncludePSDTest extends Field[Boolean](false) +case object PSDTestModeBroadcastKey extends Field( + BundleBridgeEphemeralNode[PSDTestMode]()(ValName("global_psd_test_mode")) +) + +class PSDTestMode extends Bundle { + val test_mode = Bool() + val test_mode_reset = Bool() + // TODO: Clocks? +} + +trait CanHavePSDTestModeIO { + implicit val p: Parameters + val psd = p(IncludePSDTest).option(Input(new PSDTestMode())) +} diff --git a/rocketutils/rocketutils/src/rocketutils/PlusArg.scala b/rocketutils/rocketutils/src/rocketutils/PlusArg.scala new file mode 100644 index 00000000000..80b0f49bb5f --- /dev/null +++ b/rocketutils/rocketutils/src/rocketutils/PlusArg.scala @@ -0,0 +1,140 @@ +// See LICENSE.SiFive for license details. + +package org.chipsalliance.rocketutils + +import chisel3._ +import chisel3.experimental._ +import chisel3.util.HasBlackBoxResource + +@deprecated("This will be removed in Rocket Chip 2020.08", "Rocket Chip 2020.05") +case class PlusArgInfo(default: BigInt, docstring: String) + +/** Case class for PlusArg information + * + * @tparam A scala type of the PlusArg value + * @param default optional default value + * @param docstring text to include in the help + * @param doctype description of the Verilog type of the PlusArg value (e.g. STRING, INT) + */ +private case class PlusArgContainer[A](default: Option[A], docstring: String, doctype: String) + +/** Typeclass for converting a type to a doctype string + * @tparam A some type + */ +trait Doctypeable[A] { + + /** Return the doctype string for some option */ + def toDoctype(a: Option[A]): String + +} + +/** Object containing implementations of the Doctypeable typeclass */ +object Doctypes { + + /** Converts an Int => "INT" */ + implicit val intToDoctype: Doctypeable[Int] = new Doctypeable[Int] {def toDoctype(a: Option[Int]) = "INT"} + + /** Converts a BigInt => "INT" */ + implicit val bigIntToDoctype: Doctypeable[BigInt] = new Doctypeable[BigInt] { def toDoctype(a: Option[BigInt]) = "INT"} + + /** Converts a String => "STRING" */ + implicit val stringToDoctype: Doctypeable[String] = new Doctypeable[String] {def toDoctype(a: Option[String]) = "STRING"} + +} + +class plusarg_reader(val format: String, val default: BigInt, val docstring: String, val width: Int) extends BlackBox(Map( + "FORMAT" -> StringParam(format), + "DEFAULT" -> IntParam(default), + "WIDTH" -> IntParam(width) + )) with HasBlackBoxResource { + val io = IO(new Bundle { + val out = Output(UInt(width.W)) + }) + + addResource("/vsrc/plusarg_reader.v") +} + +/* This wrapper class has no outputs, making it clear it is a simulation-only construct */ +class PlusArgTimeout(val format: String, val default: BigInt, val docstring: String, val width: Int) extends Module { + val io = IO(new Bundle { + val count = Input(UInt(width.W)) + }) + val max = Module(new plusarg_reader(format, default, docstring, width)).io.out + when (max > 0.U) { + assert (io.count < max, s"Timeout exceeded: $docstring") + } +} + +import Doctypes._ + +object PlusArg +{ + /** PlusArg("foo") will return 42.U if the simulation is run with +foo=42 + * Do not use this as an initial register value. The value is set in an + * initial block and thus accessing it from another initial is racey. + * Add a docstring to document the arg, which can be dumped in an elaboration + * pass. + */ + def apply(name: String, default: BigInt = 0, docstring: String = "", width: Int = 32): UInt = { + PlusArgArtefacts.append(name, Some(default), docstring) + Module(new plusarg_reader(name + "=%d", default, docstring, width)).io.out + } + + /** PlusArg.timeout(name, default, docstring)(count) will use chisel.assert + * to kill the simulation when count exceeds the specified integer argument. + * Default 0 will never assert. + */ + def timeout(name: String, default: BigInt = 0, docstring: String = "", width: Int = 32)(count: UInt): Unit = { + PlusArgArtefacts.append(name, Some(default), docstring) + Module(new PlusArgTimeout(name + "=%d", default, docstring, width)).io.count := count + } +} + +object PlusArgArtefacts { + private var artefacts: Map[String, PlusArgContainer[_]] = Map.empty + + /* Add a new PlusArg */ + @deprecated( + "Use `Some(BigInt)` to specify a `default` value. This will be removed in Rocket Chip 2020.08", + "Rocket Chip 2020.05" + ) + def append(name: String, default: BigInt, docstring: String): Unit = append(name, Some(default), docstring) + + /** Add a new PlusArg + * + * @tparam A scala type of the PlusArg value + * @param name name for the PlusArg + * @param default optional default value + * @param docstring text to include in the help + */ + def append[A : Doctypeable](name: String, default: Option[A], docstring: String): Unit = + artefacts = artefacts ++ + Map(name -> PlusArgContainer(default, docstring, implicitly[Doctypeable[A]].toDoctype(default))) + + /* From plus args, generate help text */ + private def serializeHelp_cHeader(tab: String = ""): String = artefacts + .map{ case(arg, info) => + s"""|$tab+$arg=${info.doctype}\\n\\ + |$tab${" "*20}${info.docstring}\\n\\ + |""".stripMargin ++ info.default.map{ case default => + s"$tab${" "*22}(default=${default})\\n\\\n"}.getOrElse("") + }.toSeq.mkString("\\n\\\n") ++ "\"" + + /* From plus args, generate a char array of their names */ + private def serializeArray_cHeader(tab: String = ""): String = { + val prettyTab = tab + " " * 44 // Length of 'static const ...' + s"${tab}static const char * verilog_plusargs [] = {\\\n" ++ + artefacts + .map{ case(arg, _) => s"""$prettyTab"$arg",\\\n""" } + .mkString("")++ + s"${prettyTab}0};" + } + + /* Generate C code to be included in emulator.cc that helps with + * argument parsing based on available Verilog PlusArgs */ + def serialize_cHeader(): String = + s"""|#define PLUSARG_USAGE_OPTIONS \"EMULATOR VERILOG PLUSARGS\\n\\ + |${serializeHelp_cHeader(" "*7)} + |${serializeArray_cHeader()} + |""".stripMargin +} diff --git a/rocketutils/rocketutils/src/rocketutils/PrefixSum.scala b/rocketutils/rocketutils/src/rocketutils/PrefixSum.scala new file mode 100644 index 00000000000..4ceb9aee4ba --- /dev/null +++ b/rocketutils/rocketutils/src/rocketutils/PrefixSum.scala @@ -0,0 +1,139 @@ +// See LICENSE.SiFive for license details. + +package org.chipsalliance.rocketutils + +import chisel3.util.{log2Ceil, log2Floor} + +trait PrefixSum { + // out[0] = summands[0] + // out[1] = summands[0] + summands[1] + // out[2] = summands[0] + summands[1] + summands[2] + // ... + // where + is your associative operator (reflexivity not required) + // layerOp is called on each level of the circuit + def apply[T](summands: Seq[T])(associativeOp: (T, T) => T, layerOp: (Int, Vector[T]) => Vector[T] = idLayer[T] _): Vector[T] + def layers(size: Int): Int + def idLayer[T](x: Int, y: Vector[T]) = y +} + +// N-1 area, N-1 depth +object RipplePrefixSum extends PrefixSum { + def layers(size: Int) = if (size == 0) 1 else size + def apply[T](summands: Seq[T])(associativeOp: (T, T) => T, layerOp: (Int, Vector[T]) => Vector[T]): Vector[T] = { + def helper(layer: Int, offset: Int, x: Vector[T]): Vector[T] = { + if (offset >= x.size) { + x + } else { + helper(layer+1, offset+1, layerOp(layer, Vector.tabulate(x.size) { i => + if (i != offset) { + x(i) + } else { + associativeOp(x(i-1), x(i)) + } + })) + } + } + helper(1, 1, layerOp(0, summands.toVector)) + } +} + +// O(NlogN) area, logN depth +object DensePrefixSum extends PrefixSum { + def layers(size: Int) = if (size == 0) 1 else 1+log2Ceil(size) + def apply[T](summands: Seq[T])(associativeOp: (T, T) => T, layerOp: (Int, Vector[T]) => Vector[T]): Vector[T] = { + def helper(layer: Int, offset: Int, x: Vector[T]): Vector[T] = { + if (offset >= x.size) { + x + } else { + helper(layer+1, offset << 1, layerOp(layer, Vector.tabulate(x.size) { i => + if (i < offset) { + x(i) + } else { + associativeOp(x(i-offset), x(i)) + } + })) + } + } + helper(1, 1, layerOp(0, summands.toVector)) + } +} + +// 2N area, 2logN depth +object SparsePrefixSum extends PrefixSum { + def layers(size: Int) = if (size <= 1) 1 else 2*log2Floor(size) + + (if (2*size >= (3 << log2Floor(size))) 1 else 0) + def apply[T](summands: Seq[T])(associativeOp: (T, T) => T, layerOp: (Int, Vector[T]) => Vector[T]): Vector[T] = { + def contract(layer: Int, offset: Int, x: Vector[T]): Vector[T] = { + val double = offset << 1 + val offset1 = offset - 1 + if (offset <= 0) { + x + } else if (double+offset1 >= x.size) { + contract(layer, offset >> 1, x) + } else { + contract(layer+1, offset >> 1, layerOp(layer, Vector.tabulate(x.size) { i => + if (i % double == offset1 && i >= offset) { + associativeOp(x(i-offset), x(i)) + } else { + x(i) + } + })) + } + } + def expand(layer: Int, offset: Int, x: Vector[T]): Vector[T] = { + val double = offset << 1 + val double1 = double - 1 + if (double1 >= x.size) { + contract(layer, offset >> 1, x) + } else { + expand(layer+1, double, layerOp(layer, Vector.tabulate(x.size) { i => + if (i % double == double1) { + associativeOp(x(i-offset), x(i)) + } else { + x(i) + } + })) + } + } + expand(1, 1, layerOp(0, summands.toVector)) + } +} + +object TestPrefixSums { + def testSize(size: Int): Unit = { + val input = Seq.tabulate(size) { i => Seq(i) } + var last: Int = 0 + var value: Vector[Seq[Int]] = Vector.empty + def layers(layer: Int, x: Vector[Seq[Int]]) = { + require (layer == last, "Discontiguous layers") + require (x != value, "Useless layer detected") + last += 1 + value = x + x + } + + last = 0 + value = Vector.fill(1) { Seq(9) } + val ripple = RipplePrefixSum(input)(_ ++ _, layers) + val rippleL = RipplePrefixSum.layers(input.size) + require (last == rippleL, s"Wrong layers for RipplePrefixSum; ${last} != ${rippleL}") + + last = 0 + value = Vector.fill(1) { Seq(9) } + val dense = DensePrefixSum (input)(_ ++ _, layers) + val denseL = DensePrefixSum.layers(input.size) + require (last == denseL, s"Wrong layers for DensePrefixSum; ${last} != ${denseL}") + require (ripple == dense, s"DensePrefixSum bug: ${ripple} != ${dense}") + + last = 0 + value = Vector.fill(1) { Seq(9) } + val sparse = SparsePrefixSum(input)(_ ++ _, layers) + val sparseL = SparsePrefixSum.layers(input.size) + require (last == sparseL, s"Wrong layers for SparsePrefixSum; ${last} != ${sparseL}") + require (ripple == sparse, s"SparsePrefixSum bug: ${ripple} != ${sparse}") + + println(s"PrefixSums correct for size ${size}") + } + + def test: Unit = { Seq.tabulate(519){i=>i}.foreach(testSize) } +} diff --git a/rocketutils/rocketutils/src/rocketutils/Property.scala b/rocketutils/rocketutils/src/rocketutils/Property.scala new file mode 100644 index 00000000000..21e7f139c2c --- /dev/null +++ b/rocketutils/rocketutils/src/rocketutils/Property.scala @@ -0,0 +1,154 @@ +// See LICENSE.SiFive for license details. + +package org.chipsalliance.rocketutils.property + +import chisel3._ +import chisel3.experimental.SourceInfo +import chisel3.util.{ReadyValidIO} + +sealed abstract class PropertyType(name: String) { + override def toString: String = name +} + +object PropertyType { + object Assert extends PropertyType("Assert") + object Assume extends PropertyType("Assume") + object Cover extends PropertyType("Cover") +} + +trait BasePropertyParameters { + val pType: PropertyType + val cond: Bool + val label: String + val message: String +} + +case class CoverPropertyParameters( + cond: Bool, + label: String = "", + message: String = "") extends BasePropertyParameters { + val pType = PropertyType.Cover +} + +abstract class BasePropertyLibrary { + def generateProperty(prop_param: BasePropertyParameters)(implicit sourceInfo: SourceInfo): Unit +} + +class DefaultPropertyLibrary extends BasePropertyLibrary { + def generateProperty(prop_param: BasePropertyParameters)(implicit sourceInfo: SourceInfo): Unit = { + // default is to do nothing + () + } +} + +abstract class BaseProperty { + def generateProperties(): Seq[BasePropertyParameters] +} + +case class CoverBoolean(cond: Bool, labels: Seq[String]) { +} + +// CrossProperty.generateProperties() will generate Boolean crosses for the cond sequence +// E.g. +// Cond = [ [A1, A2, A3], +// [B2], +// [C1, C2] ] +// It will generate the following properties +// [ A1 && B2 && C1, +// A1 && B2 && C2, +// A2 && B2 && C1, +// A2 && B2 && C2, +// A3 && B2 && C1, +// A3 && B2 && C2 ] +// Each of the boolean expression (A1, A2, C1, etc.) have a label associated with it +// User can exclude a particular cross from being generated by adding it to the exclude list +// e.g. +// exclude = [ ["A1_label", "C2_Label"], +// ["A3_label", "B2_label"] ] +// will exclude all crosses with those labels, so the new cross list will be +// [ A1 && B2 && C1, +// A2 && B2 && C1, +// A2 && B2 && C2 ] + +// Each boolean expression can be associated with more than one label + +class CrossProperty(cond: Seq[Seq[CoverBoolean]], exclude: Seq[Seq[String]], message: String) extends BaseProperty { + def listProperties(c1: CoverBoolean, c2: Seq[CoverBoolean]): Seq[CoverBoolean] = { + if (c2.isEmpty) { + Seq(c1) + } else { + c2.map( (c: CoverBoolean) => { + new CoverBoolean(c1.cond && c.cond, c1.labels ++ c.labels) + }) + } + } + + def crossProperties(cond: Seq[Seq[CoverBoolean]]): Seq[CoverBoolean] = { + if (cond.isEmpty) { + Seq() + } else { + cond.head.map( (c1: CoverBoolean) => { + listProperties(c1, crossProperties(cond.tail)) + }).reduce(_ ++ _) + } + } + def inSequence(search: Seq[String], find: Seq[String]): Boolean = { + if (find.isEmpty) { + true + } else { + find.map( (s:String) => { + search.contains(s) + }).reduce( _ && _ ) + } + } + def SeqsinSequence(search: Seq[String], find: Seq[Seq[String]]): Boolean = { + if (find.isEmpty) { + false + } else { + find.map( (s: Seq[String]) => { + inSequence(search, s) + }).reduce (_ || _) + } + } + + def generateProperties(): Seq[CoverPropertyParameters] = { + crossProperties(cond).filter(c => !SeqsinSequence(c.labels, exclude)).map( (c: CoverBoolean) => { + new CoverPropertyParameters( + cond = c.cond, + label = c.labels.reduce( (s1: String, s2: String) => {s1 + "_" + s2} ), + message = message + " " + c.labels.map("<" + _ + ">").reduce ( (s1: String, s2: String) => { s1 + " X " + s2 })) + }) + } + +} + +// The implementation using a setable global is bad, but removes dependence on Parameters +// This change was made in anticipation of a proper cover library +object cover { + private var propLib: BasePropertyLibrary = new DefaultPropertyLibrary + def setPropLib(lib: BasePropertyLibrary): Unit = this.synchronized { + propLib = lib + } + def apply(cond: Bool)(implicit sourceInfo: SourceInfo): Unit = { + propLib.generateProperty(CoverPropertyParameters(cond)) + } + def apply(cond: Bool, label: String)(implicit sourceInfo: SourceInfo): Unit = { + propLib.generateProperty(CoverPropertyParameters(cond, label)) + } + def apply(cond: Bool, label: String, message: String)(implicit sourceInfo: SourceInfo): Unit = { + propLib.generateProperty(CoverPropertyParameters(cond, label, message)) + } + def apply(prop: BaseProperty)(implicit sourceInfo: SourceInfo): Unit = { + prop.generateProperties().foreach( (pp: BasePropertyParameters) => { + if (pp.pType == PropertyType.Cover) { + propLib.generateProperty(CoverPropertyParameters(pp.cond, pp.label, pp.message)) + } + }) + } + def apply[T <: Data](rv: ReadyValidIO[T], label: String, message: String)(implicit sourceInfo: SourceInfo): Unit = { + apply( rv.valid && rv.ready, label + "_FIRE", message + ": valid and ready") + apply( rv.valid && !rv.ready, label + "_STALL", message + ": valid and not ready") + apply(!rv.valid && rv.ready, label + "_IDLE", message + ": not valid and ready") + apply(!rv.valid && !rv.ready, label + "_FULL", message + ": not valid and not ready") + } +} diff --git a/rocketutils/rocketutils/src/rocketutils/ROMGenerator.scala b/rocketutils/rocketutils/src/rocketutils/ROMGenerator.scala new file mode 100644 index 00000000000..c41916741f6 --- /dev/null +++ b/rocketutils/rocketutils/src/rocketutils/ROMGenerator.scala @@ -0,0 +1,36 @@ +// See LICENSE.SiFive for license details. + +package org.chipsalliance.rocketutils + +import chisel3._ +import chisel3.util.log2Ceil +import scala.collection.mutable.{HashMap} + +case class ROMConfig(name: String, depth: Int, width: Int) + +class BlackBoxedROM(c: ROMConfig) extends BlackBox { + val io = IO(new Bundle { + val clock = Input(Clock()) + val address = Input(UInt(log2Ceil(c.depth).W)) + val oe = Input(Bool()) + val me = Input(Bool()) + val q = Output(UInt(c.width.W)) + }) + + override def desiredName: String = c.name +} + +object ROMGenerator { + private var finalized = false + private val roms = HashMap[BlackBoxedROM, ROMConfig]() + def apply(c: ROMConfig): BlackBoxedROM = { + require(!finalized) + val m = Module(new BlackBoxedROM(c)) + roms(m) = c + m + } + def lookup(m: BlackBoxedROM): ROMConfig = { + finalized = true + roms(m) + } +} diff --git a/rocketutils/rocketutils/src/rocketutils/RationalCrossing.scala b/rocketutils/rocketutils/src/rocketutils/RationalCrossing.scala new file mode 100644 index 00000000000..ae5ff750dc0 --- /dev/null +++ b/rocketutils/rocketutils/src/rocketutils/RationalCrossing.scala @@ -0,0 +1,170 @@ +// See LICENSE.SiFive for license details. + +package org.chipsalliance.rocketutils + +import chisel3._ +import chisel3.util._ + +// If you know two clocks are related with an N:M relationship, you +// can cross the clock domains with lower latency than an AsyncQueue. +// This crossing adds 1 cycle in the target clock domain. + +// A rational crossing must put registers on the slow side. +// This trait covers the options of how/where to put the registers. +// BEWARE: the source+sink must agree on the direction! +sealed trait RationalDirection { + def flip: RationalDirection +} + +// If it's unclear which side will be slow (or it is variable), +// place registers on both sides of the crossing, by splitting +// a Queue into flow and pipe parts on either side. This is safe +// for all possible clock ratios, but has the downside that the +// timing must be met for the least-common-multiple of the clocks. +case object Symmetric extends RationalDirection { + def flip = Symmetric +} + +// Like Symmetric, this crossing works for all ratios N:M. +// However, unlike the other crossing options, this varient adds +// a full flow+pipe buffer on both sides of the crossing. This +// ends up costing potentially two cycles of delay, but gives +// both clock domains a full clock period to close timing. +case object Flexible extends RationalDirection { + def flip = Flexible +} + +// If the source is N:1 of the sink, place the registers at the sink. +// This imposes only a single clock cycle of delay and both side of +// the crossing have a full clock period to close timing. +case object FastToSlow extends RationalDirection { + def flip = SlowToFast +} + +// If the source is 1:N of the sink, place the registers at the source. +// This imposes only a single clock cycle of delay and both side of +// the crossing have a full clock period to close timing. +case object SlowToFast extends RationalDirection { + def flip = FastToSlow +} + +final class RationalIO[T <: Data](gen: T) extends Bundle +{ + val bits0 = Output(gen) + val bits1 = Output(gen) + val valid = Output(Bool()) + val source = Output(UInt(2.W)) + val ready = Input(Bool()) + val sink = Input(UInt(2.W)) + +} + +object RationalIO +{ + def apply[T <: Data](gen: T) = new RationalIO(gen) +} + +class RationalCrossingSource[T <: Data](gen: T, direction: RationalDirection = Symmetric) extends Module +{ + val io = IO(new Bundle { + val enq = Flipped(DecoupledIO(gen)) + val deq = RationalIO(gen) + }) + + val enq_in = BlockDuringReset(io.enq) + val deq = io.deq + val enq = direction match { + case Symmetric => ShiftQueue(enq_in, 1, true) + case Flexible => ShiftQueue(enq_in, 2) + case FastToSlow => enq_in + case SlowToFast => ShiftQueue(enq_in, 2) + } + + val count = RegInit(0.U(2.W)) + val equal = count === deq.sink + + deq.valid := enq.valid + deq.source := count + deq.bits0 := enq.bits + deq.bits1 := RegEnable(enq.bits, equal) + enq.ready := Mux(equal, deq.ready, count(1) =/= deq.sink(0)) + + when (enq.fire) { count := Cat(count(0), !count(1)) } + + // Ensure the clocking is setup correctly + direction match { + case Symmetric => () // always safe + case Flexible => () + case FastToSlow => assert (equal || count(1) === deq.sink(0)) + case SlowToFast => assert (equal || count(1) =/= deq.sink(0)) + } +} + +class RationalCrossingSink[T <: Data](gen: T, direction: RationalDirection = Symmetric) extends Module +{ + val io = IO(new Bundle { + val enq = Flipped(RationalIO(gen)) + val deq = Decoupled(gen) + }) + + val enq = io.enq + val deq = Wire(chiselTypeOf(io.deq)) + direction match { + case Symmetric => io.deq <> ShiftQueue(deq, 1, true) + case Flexible => io.deq <> ShiftQueue(deq, 2) + case FastToSlow => io.deq <> ShiftQueue(deq, 2) + case SlowToFast => io.deq <> deq + } + + val count = RegInit(0.U(2.W)) + val equal = count === enq.source + + enq.ready := deq.ready + enq.sink := count + deq.bits := Mux(equal, enq.bits0, enq.bits1) + deq.valid := Mux(equal, enq.valid, count(1) =/= enq.source(0)) + + when (deq.fire) { count := Cat(count(0), !count(1)) } + + // Ensure the clocking is setup correctly + direction match { + case Symmetric => () // always safe + case Flexible => () + case FastToSlow => assert (equal || count(1) =/= enq.source(0)) + case SlowToFast => assert (equal || count(1) === enq.source(0)) + } +} + +class RationalCrossingFull[T <: Data](gen: T, direction: RationalDirection = Symmetric) extends Module +{ + val io = IO(new CrossingIO(gen)) + + val source = Module(new RationalCrossingSource(gen, direction)) + val sink = Module(new RationalCrossingSink(gen, direction)) + + source.clock := io.enq_clock + source.reset := io.enq_reset + sink .clock := io.deq_clock + sink .reset := io.deq_reset + + source.io.enq <> io.enq + io.deq <> sink.io.deq +} + +object ToRational +{ + def apply[T <: Data](x: DecoupledIO[T], direction: RationalDirection = Symmetric): RationalIO[T] = { + val source = Module(new RationalCrossingSource(chiselTypeOf(x.bits), direction)) + source.io.enq <> x + source.io.deq + } +} + +object FromRational +{ + def apply[T <: Data](x: RationalIO[T], direction: RationalDirection = Symmetric): DecoupledIO[T] = { + val sink = Module(new RationalCrossingSink(chiselTypeOf(x.bits0), direction)) + sink.io.enq <> x + sink.io.deq + } +} diff --git a/rocketutils/rocketutils/src/rocketutils/RecordMap.scala b/rocketutils/rocketutils/src/rocketutils/RecordMap.scala new file mode 100644 index 00000000000..c7b5903f993 --- /dev/null +++ b/rocketutils/rocketutils/src/rocketutils/RecordMap.scala @@ -0,0 +1,32 @@ +// See LICENSE.SiFive for license details. + +package org.chipsalliance.rocketutils + +import chisel3._ +import scala.collection.immutable.ListMap +import chisel3.experimental.requireIsChiselType +import chisel3.reflect.DataMirror.internal.chiselTypeClone + +final class RecordMap[T <: Data] (eltMap: ListMap[String, T]) + extends Record { + + eltMap.foreach { case (name, elt) => requireIsChiselType(elt, name) } + + // This is needed for Record + val elements = ListMap[String, T]() ++ eltMap.mapValues(chiselTypeClone(_).asInstanceOf[T]) // mapValues return value is lazy + + def apply(x: Int) = elements.values.toSeq(x) + def apply(x: String) = elements.get(x) + def size = elements.size + def data = elements.values + +} + +object RecordMap { + + def apply[T <: Data](eltMap: ListMap[String, T]) = new RecordMap(eltMap) + + def apply[T <: Data](elements: (String, T)*): RecordMap[T] = { + new RecordMap[T](ListMap[String, T](elements:_*)) + } +} diff --git a/rocketutils/rocketutils/src/rocketutils/ReduceOthers.scala b/rocketutils/rocketutils/src/rocketutils/ReduceOthers.scala new file mode 100644 index 00000000000..cb574e0ccf0 --- /dev/null +++ b/rocketutils/rocketutils/src/rocketutils/ReduceOthers.scala @@ -0,0 +1,55 @@ +// See LICENSE.SiFive for license details. + +package org.chipsalliance.rocketutils + +import chisel3._ + +object ReduceOthers { + // Given a list of bools, create this output: + // out[i] = AND[j=0..out.size, j!=i] in[j] + def apply(x: Seq[Bool]): Seq[Bool] = { + val (literals, variables) = x.partition(_.isLit) + + val falses = literals.count(_.litValue == 0) + if (falses > 2) { + Seq.fill(x.size) { false.B } + } else if (falses == 1) { + x.map { b => + if (b.isLit && b.litValue == 0) { + variables.foldLeft(true.B)(_ && _) + } else { + false.B + } + } + } else { + var (out, all) = helper(variables) + x.map { b => + if (b.isLit) { + all + } else { + val sel = out.head + out = out.tail + sel + } + } + } + } + // Take pairs of (output_wire, input_bool) + def apply(x: Seq[(Bool, Bool)]): Unit = { + (x.map(_._1) zip apply(x.map(_._2))) foreach { case (w, x) => w := x } + } + private def helper(x: Seq[Bool]): (Seq[Bool], Bool) = { + if (x.size <= 1) { + (Seq.fill(x.size) { true.B }, x.headOption.getOrElse(true.B)) + } else if (x.size <= 3) { + (Seq.tabulate(x.size) { i => + (x.take(i) ++ x.drop(i+1)).reduce(_ && _) + }, x.reduce(_ && _)) + } else { + val (half, all) = helper(x.grouped(2).map(_.reduce(_ && _)).toList) + (Seq.tabulate(x.size) { i => + if ((i ^ 1) >= x.size) half(i/2) else x(i ^ 1) && half(i / 2) + }, all) + } + } +} diff --git a/rocketutils/rocketutils/src/rocketutils/ReorderQueue.scala b/rocketutils/rocketutils/src/rocketutils/ReorderQueue.scala new file mode 100644 index 00000000000..2a648772d5b --- /dev/null +++ b/rocketutils/rocketutils/src/rocketutils/ReorderQueue.scala @@ -0,0 +1,82 @@ +// See LICENSE.SiFive for license details. +// See LICENSE.Berkeley for license details. + +package org.chipsalliance.rocketutils + +import chisel3._ +import chisel3.util.{DecoupledIO, Mux1H, OHToUInt, PriorityEncoder, PriorityEncoderOH} + +class ReorderQueueWrite[T <: Data](dType: T, tagWidth: Int) extends Bundle { + val data = dType.cloneType + val tag = UInt(tagWidth.W) + +} + +class ReorderEnqueueIO[T <: Data](dType: T, tagWidth: Int) + extends DecoupledIO(new ReorderQueueWrite(dType, tagWidth)) { + +} + +class ReorderDequeueIO[T <: Data](dType: T, tagWidth: Int) extends Bundle { + val valid = Input(Bool()) + val tag = Input(UInt(tagWidth.W)) + val data = Output(dType.cloneType) + val matches = Output(Bool()) + +} + +class ReorderQueue[T <: Data](dType: T, tagWidth: Int, size: Option[Int] = None) + extends Module { + val io = IO(new Bundle { + val enq = Flipped(new ReorderEnqueueIO(dType, tagWidth)) + val deq = new ReorderDequeueIO(dType, tagWidth) + }) + + val tagSpaceSize = 1 << tagWidth + val actualSize = size.getOrElse(tagSpaceSize) + + if (tagSpaceSize > actualSize) { + val roq_data = Reg(Vec(actualSize, dType)) + val roq_tags = Reg(Vec(actualSize, UInt(tagWidth.W))) + val roq_free = RegInit(VecInit(Seq.fill(actualSize)(true.B))) + + val roq_enq_addr = PriorityEncoder(roq_free) + val roq_matches = roq_tags.zip(roq_free) + .map { case (tag, free) => tag === io.deq.tag && !free } + val roq_deq_onehot = PriorityEncoderOH(roq_matches) + + io.enq.ready := roq_free.reduce(_ || _) + io.deq.data := Mux1H(roq_deq_onehot, roq_data) + io.deq.matches := roq_matches.reduce(_ || _) + + when (io.enq.valid && io.enq.ready) { + roq_data(roq_enq_addr) := io.enq.bits.data + roq_tags(roq_enq_addr) := io.enq.bits.tag + roq_free(roq_enq_addr) := false.B + } + + when (io.deq.valid) { + roq_free(OHToUInt(roq_deq_onehot)) := true.B + } + + println(s"Warning - using a CAM for ReorderQueue, tagBits: ${tagWidth} size: ${actualSize}") + } else { + val roq_data = Mem(tagSpaceSize, dType) + val roq_free = RegInit(VecInit(Seq.fill(tagSpaceSize)(true.B))) + + io.enq.ready := roq_free(io.enq.bits.tag) + io.deq.data := roq_data(io.deq.tag) + io.deq.matches := !roq_free(io.deq.tag) + + when (io.enq.valid && io.enq.ready) { + roq_data(io.enq.bits.tag) := io.enq.bits.data + roq_free(io.enq.bits.tag) := false.B + } + + when (io.deq.valid) { + roq_free(io.deq.tag) := true.B + } + } +} + + diff --git a/rocketutils/rocketutils/src/rocketutils/Repeater.scala b/rocketutils/rocketutils/src/rocketutils/Repeater.scala new file mode 100644 index 00000000000..a8e92543bcd --- /dev/null +++ b/rocketutils/rocketutils/src/rocketutils/Repeater.scala @@ -0,0 +1,40 @@ +// See LICENSE.SiFive for license details. + +package org.chipsalliance.rocketutils + +import chisel3._ +import chisel3.util.{Decoupled, DecoupledIO} + +// A Repeater passes its input to its output, unless repeat is asserted. +// When repeat is asserted, the Repeater copies the input and repeats it next cycle. +class Repeater[T <: Data](gen: T) extends Module +{ + val io = IO( new Bundle { + val repeat = Input(Bool()) + val full = Output(Bool()) + val enq = Flipped(Decoupled(gen.cloneType)) + val deq = Decoupled(gen.cloneType) + } ) + + val full = RegInit(false.B) + val saved = Reg(gen.cloneType) + + // When !full, a repeater is pass-through + io.deq.valid := io.enq.valid || full + io.enq.ready := io.deq.ready && !full + io.deq.bits := Mux(full, saved, io.enq.bits) + io.full := full + + when (io.enq.fire && io.repeat) { full := true.B; saved := io.enq.bits } + when (io.deq.fire && !io.repeat) { full := false.B } +} + +object Repeater +{ + def apply[T <: Data](enq: DecoupledIO[T], repeat: Bool): DecoupledIO[T] = { + val repeater = Module(new Repeater(chiselTypeOf(enq.bits))) + repeater.io.repeat := repeat + repeater.io.enq <> enq + repeater.io.deq + } +} diff --git a/rocketutils/rocketutils/src/rocketutils/Replacement.scala b/rocketutils/rocketutils/src/rocketutils/Replacement.scala new file mode 100644 index 00000000000..74e456ab7df --- /dev/null +++ b/rocketutils/rocketutils/src/rocketutils/Replacement.scala @@ -0,0 +1,327 @@ +// See LICENSE.Berkeley for license details. +// See LICENSE.SiFive for license details. + +package org.chipsalliance.rocketutils + +import chisel3._ +import chisel3.util._ +import chisel3.util.random.LFSR + +import org.chipsalliance.rocketutils.property.cover + +import org.chipsalliance.rocketutils.conversions.{BooleanToAugmentedBoolean, SeqBoolBitwiseOps, UIntToAugmentedUInt} + +abstract class ReplacementPolicy { + def nBits: Int + def perSet: Boolean + def way: UInt + def miss: Unit + def hit: Unit + def access(touch_way: UInt): Unit + def access(touch_ways: Seq[Valid[UInt]]): Unit + def state_read: UInt + def get_next_state(state: UInt, touch_way: UInt): UInt + def get_next_state(state: UInt, touch_ways: Seq[Valid[UInt]]): UInt = { + touch_ways.foldLeft(state)((prev, touch_way) => Mux(touch_way.valid, get_next_state(prev, touch_way.bits), prev)) + } + def get_replace_way(state: UInt): UInt +} + +object ReplacementPolicy { + def fromString(s: String, n_ways: Int): ReplacementPolicy = s.toLowerCase match { + case "random" => new RandomReplacement(n_ways) + case "lru" => new TrueLRU(n_ways) + case "plru" => new PseudoLRU(n_ways) + case t => throw new IllegalArgumentException(s"unknown Replacement Policy type $t") + } +} + +class RandomReplacement(n_ways: Int) extends ReplacementPolicy { + private val replace = Wire(Bool()) + replace := false.B + def nBits = 16 + def perSet = false + private val lfsr = LFSR(nBits, replace) + def state_read = WireDefault(lfsr) + + def way = Random(n_ways, lfsr) + def miss = replace := true.B + def hit = {} + def access(touch_way: UInt) = {} + def access(touch_ways: Seq[Valid[UInt]]) = {} + def get_next_state(state: UInt, touch_way: UInt) = 0.U //DontCare + def get_replace_way(state: UInt) = way +} + +abstract class SeqReplacementPolicy { + def access(set: UInt): Unit + def update(valid: Bool, hit: Bool, set: UInt, way: UInt): Unit + def way: UInt +} + +abstract class SetAssocReplacementPolicy { + def access(set: UInt, touch_way: UInt): Unit + def access(sets: Seq[UInt], touch_ways: Seq[Valid[UInt]]): Unit + def way(set: UInt): UInt +} + +class SeqRandom(n_ways: Int) extends SeqReplacementPolicy { + val logic = new RandomReplacement(n_ways) + def access(set: UInt) = { } + def update(valid: Bool, hit: Bool, set: UInt, way: UInt) = { + when (valid && !hit) { logic.miss } + } + def way = logic.way +} + +class TrueLRU(n_ways: Int) extends ReplacementPolicy { + // True LRU replacement policy, using a triangular matrix to track which sets are more recently used than others. + // The matrix is packed into a single UInt (or Bits). Example 4-way (6-bits): + // [5] - 3 more recent than 2 + // [4] - 3 more recent than 1 + // [3] - 2 more recent than 1 + // [2] - 3 more recent than 0 + // [1] - 2 more recent than 0 + // [0] - 1 more recent than 0 + def nBits = (n_ways * (n_ways-1)) / 2 + def perSet = true + private val state_reg = RegInit(0.U(nBits.W)) + def state_read = WireDefault(state_reg) + + private def extractMRUVec(state: UInt): Seq[UInt] = { + // Extract per-way information about which higher-indexed ways are more recently used + val moreRecentVec = Wire(Vec(n_ways-1, UInt(n_ways.W))) + var lsb = 0 + for (i <- 0 until n_ways-1) { + moreRecentVec(i) := Cat(state(lsb+n_ways-i-2,lsb), 0.U((i+1).W)) + lsb = lsb + (n_ways - i - 1) + } + moreRecentVec + } + + def get_next_state(state: UInt, touch_way: UInt): UInt = { + val nextState = Wire(Vec(n_ways-1, UInt(n_ways.W))) + val moreRecentVec = extractMRUVec(state) // reconstruct lower triangular matrix + val wayDec = UIntToOH(touch_way, n_ways) + + // Compute next value of triangular matrix + // set the touched way as more recent than every other way + nextState.zipWithIndex.map { case (e, i) => + e := Mux(i.U === touch_way, 0.U(n_ways.W), moreRecentVec(i) | wayDec) + } + + nextState.zipWithIndex.tail.foldLeft((nextState.head.apply(n_ways-1,1),0)) { case ((pe,pi),(ce,ci)) => (Cat(ce.apply(n_ways-1,ci+1), pe), ci) }._1 + } + + def access(touch_way: UInt): Unit = { + state_reg := get_next_state(state_reg, touch_way) + } + def access(touch_ways: Seq[Valid[UInt]]): Unit = { + when (touch_ways.map(_.valid).orR) { + state_reg := get_next_state(state_reg, touch_ways) + } + for (i <- 1 until touch_ways.size) { + cover(PopCount(touch_ways.map(_.valid)) === i.U, s"LRU_UpdateCount$i", s"LRU Update $i simultaneous") + } + } + + def get_replace_way(state: UInt): UInt = { + val moreRecentVec = extractMRUVec(state) // reconstruct lower triangular matrix + // For each way, determine if all other ways are more recent + val mruWayDec = (0 until n_ways).map { i => + val upperMoreRecent = (if (i == n_ways-1) true.B else moreRecentVec(i).apply(n_ways-1,i+1).andR) + val lowerMoreRecent = (if (i == 0) true.B else moreRecentVec.map(e => !e(i)).reduce(_ && _)) + upperMoreRecent && lowerMoreRecent + } + OHToUInt(mruWayDec) + } + + def way = get_replace_way(state_reg) + def miss = access(way) + def hit = {} + @deprecated("replace 'replace' with 'way' from abstract class ReplacementPolicy","Rocket Chip 2020.05") + def replace: UInt = way +} + +class PseudoLRU(n_ways: Int) extends ReplacementPolicy { + // Pseudo-LRU tree algorithm: https://en.wikipedia.org/wiki/Pseudo-LRU#Tree-PLRU + // + // + // - bits storage example for 4-way PLRU binary tree: + // bit[2]: ways 3+2 older than ways 1+0 + // / \ + // bit[1]: way 3 older than way 2 bit[0]: way 1 older than way 0 + // + // + // - bits storage example for 3-way PLRU binary tree: + // bit[1]: way 2 older than ways 1+0 + // \ + // bit[0]: way 1 older than way 0 + // + // + // - bits storage example for 8-way PLRU binary tree: + // bit[6]: ways 7-4 older than ways 3-0 + // / \ + // bit[5]: ways 7+6 > 5+4 bit[2]: ways 3+2 > 1+0 + // / \ / \ + // bit[4]: way 7>6 bit[3]: way 5>4 bit[1]: way 3>2 bit[0]: way 1>0 + + def nBits = n_ways - 1 + def perSet = true + private val state_reg = if (nBits == 0) Reg(UInt(0.W)) else RegInit(0.U(nBits.W)) + def state_read = WireDefault(state_reg) + + def access(touch_way: UInt): Unit = { + state_reg := get_next_state(state_reg, touch_way) + } + def access(touch_ways: Seq[Valid[UInt]]): Unit = { + when (touch_ways.map(_.valid).orR) { + state_reg := get_next_state(state_reg, touch_ways) + } + for (i <- 1 until touch_ways.size) { + cover(PopCount(touch_ways.map(_.valid)) === i.U, s"PLRU_UpdateCount$i", s"PLRU Update $i simultaneous") + } + } + + + /** @param state state_reg bits for this sub-tree + * @param touch_way touched way encoded value bits for this sub-tree + * @param tree_nways number of ways in this sub-tree + */ + def get_next_state(state: UInt, touch_way: UInt, tree_nways: Int): UInt = { + require(state.getWidth == (tree_nways-1), s"wrong state bits width ${state.getWidth} for $tree_nways ways") + require(touch_way.getWidth == (log2Ceil(tree_nways) max 1), s"wrong encoded way width ${touch_way.getWidth} for $tree_nways ways") + + if (tree_nways > 2) { + // we are at a branching node in the tree, so recurse + val right_nways: Int = 1 << (log2Ceil(tree_nways) - 1) // number of ways in the right sub-tree + val left_nways: Int = tree_nways - right_nways // number of ways in the left sub-tree + val set_left_older = !touch_way(log2Ceil(tree_nways)-1) + val left_subtree_state = state.extract(tree_nways-3, right_nways-1) + val right_subtree_state = state(right_nways-2, 0) + + if (left_nways > 1) { + // we are at a branching node in the tree with both left and right sub-trees, so recurse both sub-trees + Cat(set_left_older, + Mux(set_left_older, + left_subtree_state, // if setting left sub-tree as older, do NOT recurse into left sub-tree + get_next_state(left_subtree_state, touch_way.extract(log2Ceil(left_nways)-1,0), left_nways)), // recurse left if newer + Mux(set_left_older, + get_next_state(right_subtree_state, touch_way(log2Ceil(right_nways)-1,0), right_nways), // recurse right if newer + right_subtree_state)) // if setting right sub-tree as older, do NOT recurse into right sub-tree + } else { + // we are at a branching node in the tree with only a right sub-tree, so recurse only right sub-tree + Cat(set_left_older, + Mux(set_left_older, + get_next_state(right_subtree_state, touch_way(log2Ceil(right_nways)-1,0), right_nways), // recurse right if newer + right_subtree_state)) // if setting right sub-tree as older, do NOT recurse into right sub-tree + } + } else if (tree_nways == 2) { + // we are at a leaf node at the end of the tree, so set the single state bit opposite of the lsb of the touched way encoded value + !touch_way(0) + } else { // tree_nways <= 1 + // we are at an empty node in an empty tree for 1 way, so return single zero bit for Chisel (no zero-width wires) + 0.U(1.W) + } + } + + def get_next_state(state: UInt, touch_way: UInt): UInt = { + val touch_way_sized = if (touch_way.getWidth < log2Ceil(n_ways)) touch_way.padTo (log2Ceil(n_ways)) + else touch_way.extract(log2Ceil(n_ways)-1,0) + get_next_state(state, touch_way_sized, n_ways) + } + + + /** @param state state_reg bits for this sub-tree + * @param tree_nways number of ways in this sub-tree + */ + def get_replace_way(state: UInt, tree_nways: Int): UInt = { + require(state.getWidth == (tree_nways-1), s"wrong state bits width ${state.getWidth} for $tree_nways ways") + + // this algorithm recursively descends the binary tree, filling in the way-to-replace encoded value from msb to lsb + if (tree_nways > 2) { + // we are at a branching node in the tree, so recurse + val right_nways: Int = 1 << (log2Ceil(tree_nways) - 1) // number of ways in the right sub-tree + val left_nways: Int = tree_nways - right_nways // number of ways in the left sub-tree + val left_subtree_older = state(tree_nways-2) + val left_subtree_state = state.extract(tree_nways-3, right_nways-1) + val right_subtree_state = state(right_nways-2, 0) + + if (left_nways > 1) { + // we are at a branching node in the tree with both left and right sub-trees, so recurse both sub-trees + Cat(left_subtree_older, // return the top state bit (current tree node) as msb of the way-to-replace encoded value + Mux(left_subtree_older, // if left sub-tree is older, recurse left, else recurse right + get_replace_way(left_subtree_state, left_nways), // recurse left + get_replace_way(right_subtree_state, right_nways))) // recurse right + } else { + // we are at a branching node in the tree with only a right sub-tree, so recurse only right sub-tree + Cat(left_subtree_older, // return the top state bit (current tree node) as msb of the way-to-replace encoded value + Mux(left_subtree_older, // if left sub-tree is older, return and do not recurse right + 0.U(1.W), + get_replace_way(right_subtree_state, right_nways))) // recurse right + } + } else if (tree_nways == 2) { + // we are at a leaf node at the end of the tree, so just return the single state bit as lsb of the way-to-replace encoded value + state(0) + } else { // tree_nways <= 1 + // we are at an empty node in an unbalanced tree for non-power-of-2 ways, so return single zero bit as lsb of the way-to-replace encoded value + 0.U(1.W) + } + } + + def get_replace_way(state: UInt): UInt = get_replace_way(state, n_ways) + + def way = get_replace_way(state_reg) + def miss = access(way) + def hit = {} +} + +class SeqPLRU(n_sets: Int, n_ways: Int) extends SeqReplacementPolicy { + val logic = new PseudoLRU(n_ways) + val state = SyncReadMem(n_sets, UInt(logic.nBits.W)) + val current_state = Wire(UInt(logic.nBits.W)) + val next_state = Wire(UInt(logic.nBits.W)) + val plru_way = logic.get_replace_way(current_state) + + def access(set: UInt) = { + current_state := state.read(set) + } + + def update(valid: Bool, hit: Bool, set: UInt, way: UInt) = { + val update_way = Mux(hit, way, plru_way) + next_state := logic.get_next_state(current_state, update_way) + when (valid) { state.write(set, next_state) } + } + + def way = plru_way +} + + +class SetAssocLRU(n_sets: Int, n_ways: Int, policy: String) extends SetAssocReplacementPolicy { + val logic = policy.toLowerCase match { + case "plru" => new PseudoLRU(n_ways) + case "lru" => new TrueLRU(n_ways) + case t => throw new IllegalArgumentException(s"unknown Replacement Policy type $t") + } + val state_vec = + if (logic.nBits == 0) Reg(Vec(n_sets, UInt(logic.nBits.W))) // Work around elaboration error on following line + else RegInit(VecInit(Seq.fill(n_sets)(0.U(logic.nBits.W)))) + + def access(set: UInt, touch_way: UInt) = { + state_vec(set) := logic.get_next_state(state_vec(set), touch_way) + } + + def access(sets: Seq[UInt], touch_ways: Seq[Valid[UInt]]) = { + require(sets.size == touch_ways.size, "internal consistency check: should be same number of simultaneous updates for sets and touch_ways") + for (set <- 0 until n_sets) { + val set_touch_ways = (sets zip touch_ways).map { case (touch_set, touch_way) => + Pipe(touch_way.valid && (touch_set === set.U), touch_way.bits, 0)} + when (set_touch_ways.map(_.valid).orR) { + state_vec(set) := logic.get_next_state(state_vec(set), set_touch_ways) + } + } + } + + def way(set: UInt) = logic.get_replace_way(state_vec(set)) + +} diff --git a/rocketutils/rocketutils/src/rocketutils/ResetCatchAndSync.scala b/rocketutils/rocketutils/src/rocketutils/ResetCatchAndSync.scala new file mode 100644 index 00000000000..04a16222a86 --- /dev/null +++ b/rocketutils/rocketutils/src/rocketutils/ResetCatchAndSync.scala @@ -0,0 +1,54 @@ +// See LICENSE.SiFive for license details. + +package org.chipsalliance.rocketutils + +import chisel3._ +import chisel3.{withClockAndReset, withReset} + +/** Reset: asynchronous assert, + * synchronous de-assert + * + */ + +class ResetCatchAndSync (sync: Int = 3) extends Module { + + override def desiredName = s"ResetCatchAndSync_d${sync}" + + val io = IO(new Bundle { + val sync_reset = Output(Bool()) + val psd = Input(new PSDTestMode()) + }) + + // Bypass both the resets to the flops themselves (to prevent DFT holes on + // those flops) and on the output of the synchronizer circuit (to control + // reset to any flops this circuit drives). + + val post_psd_reset = Mux(io.psd.test_mode, io.psd.test_mode_reset, reset.asBool) + withReset(post_psd_reset) { + io.sync_reset := Mux(io.psd.test_mode, io.psd.test_mode_reset, + ~AsyncResetSynchronizerShiftReg(true.B, sync)) + } +} + +object ResetCatchAndSync { + + def apply(clk: Clock, rst: Bool, sync: Int = 3, name: Option[String] = None, + psd: Option[PSDTestMode] = None): Bool = { + + withClockAndReset(clk, rst) { + val catcher = Module (new ResetCatchAndSync(sync)) + if (name.isDefined) {catcher.suggestName(name.get)} + catcher.io.psd <> psd.getOrElse(WireDefault(0.U.asTypeOf(new PSDTestMode()))) + catcher.io.sync_reset + } + } + + def apply(clk: Clock, rst: Bool, sync: Int, name: String): Bool = apply(clk, rst, sync, Some(name)) + def apply(clk: Clock, rst: Bool, name: String): Bool = apply(clk, rst, name = Some(name)) + + def apply(clk: Clock, rst: Bool, sync: Int, name: String, psd: PSDTestMode): Bool = + apply(clk, rst, sync, Some(name), Some(psd)) + def apply(clk: Clock, rst: Bool, name: String, psd: PSDTestMode): Bool = + apply(clk, rst, name = Some(name), psd = Some(psd)) + +} diff --git a/rocketutils/rocketutils/src/rocketutils/ScatterGather.scala b/rocketutils/rocketutils/src/rocketutils/ScatterGather.scala new file mode 100644 index 00000000000..3aeed10e379 --- /dev/null +++ b/rocketutils/rocketutils/src/rocketutils/ScatterGather.scala @@ -0,0 +1,70 @@ +// See LICENSE.SiFive for license details. + +package org.chipsalliance.rocketutils + +import chisel3._ +import chisel3.util._ + +object Gather { + // Compress all the valid data to the lowest indices + def apply[T <: Data](data: Seq[ValidIO[T]]): Vec[T] = apply(data, DensePrefixSum) + def apply[T <: Data](data: Seq[ValidIO[T]], prefixSum: PrefixSum): Vec[T] = { + val popBits = log2Ceil(data.size) + val holes = data.map(x => WireInit(UInt(popBits.W), (!x.valid).asUInt)) + apply(data.map(_.bits), prefixSum(holes)(_ + _)) + } + def apply[T <: Data](data: Seq[T], holeSum: Seq[UInt], layerOp: (Int, Seq[T], Seq[UInt]) => (Seq[T], Seq[UInt]) = idLayer[T] _): Vec[T] = { + def helper(layer: Int, offset: Int, holeSum0: Vector[UInt], data0: Vector[T]): Vector[T] = { + val (a, b) = layerOp(layer, data0, holeSum0) + val data = a.toVector + val holeSum = b.toVector + if (offset >= data.size) { + data + } else { + val bit = log2Ceil(offset) + helper(layer + 1, offset << 1, holeSum, Vector.tabulate(data.size) { i => + if (i+offset >= data.size) { + data(i) + } else { + Mux(holeSum(i+offset-1)(bit), data(i+offset), data(i)) + } + }) + } + } + VecInit(helper(0, 1, holeSum.toVector, data.toVector)) + } + def layers(size: Int) = if (size == 0) 1 else 1+log2Ceil(size) + def idLayer[T](layer: Int, data: Seq[T], holeSum: Seq[UInt]) = (data, holeSum) +} + +object Scatter { + def apply[T <: Data](data: Seq[ValidIO[T]]): Vec[T] = apply(data, DensePrefixSum) + def apply[T <: Data](data: Seq[ValidIO[T]], prefixSum: PrefixSum): Vec[T] = { + val popBits = log2Ceil(data.size) + val holes = data.map(x => WireInit(UInt(popBits.W), (!x.valid).asUInt)) + apply(data.map(_.bits), prefixSum(holes)(_ + _)) + } + def apply[T <: Data](data: Seq[T], holeSum: Seq[UInt], layerOp: (Int, Seq[T], Seq[UInt]) => (Seq[T], Seq[UInt]) = idLayer[T] _): Vec[T] = { + def helper(layer: Int, offset: Int, holeSum0: Vector[UInt], data0: Vector[T]): Vector[T] = { + val (a, b) = layerOp(layer, data0, holeSum0) + val data = a.toVector + val holeSum = b.toVector + if (offset <= 0) { + data + } else { + val bit = log2Ceil(offset) + helper(layer + 1, offset >> 1, holeSum, Vector.tabulate(data.size) { i => + if (i < offset) { + data(i) + } else { + Mux(holeSum(i-1)(bit), data(i-offset), data(i)) + } + }) + } + } + val offset = if (data.size <= 1) 0 else 1 << log2Floor(data.size-1) + VecInit(helper(0, offset, holeSum.toVector, data.toVector)) + } + def layers(size: Int) = if (size == 0) 1 else 1+log2Ceil(size) + def idLayer[T](layer: Int, data: Seq[T], holeSum: Seq[UInt]) = (data, holeSum) +} diff --git a/rocketutils/rocketutils/src/rocketutils/SeededRandom.scala b/rocketutils/rocketutils/src/rocketutils/SeededRandom.scala new file mode 100644 index 00000000000..dbdbb3e75db --- /dev/null +++ b/rocketutils/rocketutils/src/rocketutils/SeededRandom.scala @@ -0,0 +1,11 @@ +// See LICENSE.SiFive for license details. + +package org.chipsalliance.rocketutils + +/** Using e.g. Random.nextInt makes your hardware generation non-repoducible, + * which is almost certainly undesirable. Use LCG to increment random numbers in HW, + * or use this SeededRandom.fromSeed to make reproducible Scala PRNGs. + */ +object SeededRandom { + val fromSeed = new scala.util.Random(42) +} diff --git a/rocketutils/rocketutils/src/rocketutils/ShiftQueue.scala b/rocketutils/rocketutils/src/rocketutils/ShiftQueue.scala new file mode 100644 index 00000000000..25313d9718c --- /dev/null +++ b/rocketutils/rocketutils/src/rocketutils/ShiftQueue.scala @@ -0,0 +1,64 @@ +// See LICENSE.SiFive for license details. + +package org.chipsalliance.rocketutils + +import chisel3._ +import chisel3.util._ + +/** Implements the same interface as chisel3.util.Queue, but uses a shift + * register internally. It is less energy efficient whenever the queue + * has more than one entry populated, but is faster on the dequeue side. + * It is efficient for usually-empty flow-through queues. */ +class ShiftQueue[T <: Data](gen: T, + val entries: Int, + pipe: Boolean = false, + flow: Boolean = false) + extends Module { + val io = IO(new QueueIO(gen, entries) { + val mask = Output(UInt(this.entries.W)) + }) + + private val valid = RegInit(VecInit(Seq.fill(entries) { false.B })) + private val elts = Reg(Vec(entries, gen)) + + for (i <- 0 until entries) { + def paddedValid(i: Int) = if (i == -1) true.B else if (i == entries) false.B else valid(i) + + val wdata = if (i == entries-1) io.enq.bits else Mux(valid(i+1), elts(i+1), io.enq.bits) + val wen = + Mux(io.deq.ready, + paddedValid(i+1) || io.enq.fire && ((i == 0 && !flow).B || valid(i)), + io.enq.fire && paddedValid(i-1) && !valid(i)) + when (wen) { elts(i) := wdata } + + valid(i) := + Mux(io.deq.ready, + paddedValid(i+1) || io.enq.fire && ((i == 0 && !flow).B || valid(i)), + io.enq.fire && paddedValid(i-1) || valid(i)) + } + + io.enq.ready := !valid(entries-1) + io.deq.valid := valid(0) + io.deq.bits := elts.head + + if (flow) { + when (io.enq.valid) { io.deq.valid := true.B } + when (!valid(0)) { io.deq.bits := io.enq.bits } + } + + if (pipe) { + when (io.deq.ready) { io.enq.ready := true.B } + } + + io.mask := valid.asUInt + io.count := PopCount(io.mask) +} + +object ShiftQueue +{ + def apply[T <: Data](enq: DecoupledIO[T], entries: Int = 2, pipe: Boolean = false, flow: Boolean = false): DecoupledIO[T] = { + val q = Module(new ShiftQueue(enq.bits.cloneType, entries, pipe, flow)) + q.io.enq <> enq + q.io.deq + } +} diff --git a/rocketutils/rocketutils/src/rocketutils/ShiftReg.scala b/rocketutils/rocketutils/src/rocketutils/ShiftReg.scala new file mode 100644 index 00000000000..c4e2b840ba4 --- /dev/null +++ b/rocketutils/rocketutils/src/rocketutils/ShiftReg.scala @@ -0,0 +1,83 @@ +// See LICENSE.SiFive for license details. + +package org.chipsalliance.rocketutils + +import chisel3._ + +// Similar to the Chisel ShiftRegister but allows the user to suggest a +// name to the registers that get instantiated, and +// to provide a reset value. +object ShiftRegInit { + def apply[T <: Data](in: T, n: Int, init: T, name: Option[String] = None): T = + + (0 until n).foldRight(in) { + case (i, next) => { + val r = RegNext(next, init) + name.foreach { na => r.suggestName(s"${na}_${i}") } + r + } + } +} + +/** These wrap behavioral + * shift registers into specific modules to allow for + * backend flows to replace or constrain + * them properly when used for CDC synchronization, + * rather than buffering. + * + * The different types vary in their reset behavior: + * AsyncResetShiftReg -- Asynchronously reset register array + * A W(width) x D(depth) sized array is constructed from D instantiations of a + * W-wide register vector. Functionally identical to AsyncResetSyncrhonizerShiftReg, + * but only used for timing applications + */ + +abstract class AbstractPipelineReg(w: Int = 1) extends Module { + val io = IO(new Bundle { + val d = Input(UInt(w.W)) + val q = Output(UInt(w.W)) + } + ) +} + +object AbstractPipelineReg { + def apply [T <: Data](gen: => AbstractPipelineReg, in: T, name: Option[String] = None): T = { + val chain = Module(gen) + name.foreach{ chain.suggestName(_) } + chain.io.d := in.asUInt + chain.io.q.asTypeOf(in) + } +} + +class AsyncResetShiftReg(w: Int = 1, depth: Int = 1, init: Int = 0, name: String = "pipe") extends AbstractPipelineReg(w) { + require(depth > 0, "Depth must be greater than 0.") + + override def desiredName = s"AsyncResetShiftReg_w${w}_d${depth}_i${init}" + + val chain = List.tabulate(depth) { i => + Module (new AsyncResetRegVec(w, init)).suggestName(s"${name}_${i}") + } + + chain.last.io.d := io.d + chain.last.io.en := true.B + + (chain.init zip chain.tail).foreach { case (sink, source) => + sink.io.d := source.io.q + sink.io.en := true.B + } + io.q := chain.head.io.q +} + +object AsyncResetShiftReg { + def apply [T <: Data](in: T, depth: Int, init: Int = 0, name: Option[String] = None): T = + AbstractPipelineReg(new AsyncResetShiftReg(in.getWidth, depth, init), in, name) + + def apply [T <: Data](in: T, depth: Int, name: Option[String]): T = + apply(in, depth, 0, name) + + def apply [T <: Data](in: T, depth: Int, init: T, name: Option[String]): T = + apply(in, depth, init.litValue.toInt, name) + + def apply [T <: Data](in: T, depth: Int, init: T): T = + apply (in, depth, init.litValue.toInt, None) +} diff --git a/rocketutils/rocketutils/src/rocketutils/SimpleProduct.scala b/rocketutils/rocketutils/src/rocketutils/SimpleProduct.scala new file mode 100644 index 00000000000..c90f1aca35c --- /dev/null +++ b/rocketutils/rocketutils/src/rocketutils/SimpleProduct.scala @@ -0,0 +1,39 @@ +// See LICENSE.SiFive for license details. + +package org.chipsalliance.rocketutils + +// To mix this trait, you must supply: +// override def canEqual(that: Any): Boolean = that.isInstanceOf[YourClass] +// override def productPrefix: String = "YourClass" +// def productArity: Int = # of fields +// def productElement(n: Int): Any = field accessors +// In exchange you get: +// def equals(that: Any): Boolean = same type and same fields +// def hashCode: Int = hash of all fields (and productPrefix) +// def toString: String = formats as "productPrefix(field1, field2, ...)" +trait SimpleProduct extends Product with Equals { + override def equals(other: Any): Boolean = other match { + case that: SimpleProduct => + def canEq = that.canEqual(this) && this.canEqual(that) + def iter = that.productIterator zip this.productIterator + canEq && iter.forall { case (a, b) => a == b } + case _ => false + } + + override def hashCode: Int = scala.util.hashing.MurmurHash3.productHash(this) + + override def toString: String = { + val b = new StringBuilder(productPrefix) + val iter = productIterator + b += '(' + if (iter.hasNext) { + b ++= iter.next().toString + while (iter.hasNext) { + b ++= ", " + b ++= iter.next().toString + } + } + b += ')' + b.toString + } +} diff --git a/rocketutils/rocketutils/src/rocketutils/SynchronizerReg.scala b/rocketutils/rocketutils/src/rocketutils/SynchronizerReg.scala new file mode 100644 index 00000000000..85f088ea5a2 --- /dev/null +++ b/rocketutils/rocketutils/src/rocketutils/SynchronizerReg.scala @@ -0,0 +1,213 @@ +// See LICENSE.SiFive for license details. + +package org.chipsalliance.rocketutils + +import chisel3._ +import chisel3.util.{RegEnable, Cat} + +/** These wrap behavioral + * shift and next registers into specific modules to allow for + * backend flows to replace or constrain + * them properly when used for CDC synchronization, + * rather than buffering. + * + * + * These are built up of *ResetSynchronizerPrimitiveShiftReg, + * intended to be replaced by the integrator's metastable flops chains or replaced + * at this level if they have a multi-bit wide synchronizer primitive. + * The different types vary in their reset behavior: + * NonSyncResetSynchronizerShiftReg -- Register array which does not have a reset pin + * AsyncResetSynchronizerShiftReg -- Asynchronously reset register array, constructed from W instantiations of D deep + * 1-bit-wide shift registers. + * SyncResetSynchronizerShiftReg -- Synchronously reset register array, constructed similarly to AsyncResetSynchronizerShiftReg + * + * [Inferred]ResetSynchronizerShiftReg -- TBD reset type by chisel3 reset inference. + * + * ClockCrossingReg -- Not made up of SynchronizerPrimitiveShiftReg. This is for single-deep flops which cross + * Clock Domains. +*/ + +object SynchronizerResetType extends Enumeration { + val NonSync, Inferred, Sync, Async = Value +} + + +// Note: this should not be used directly. +// Use the companion object to generate this with the correct reset type mixin. +private class SynchronizerPrimitiveShiftReg( + sync: Int, + init: Boolean, + resetType: SynchronizerResetType.Value) + extends AbstractPipelineReg(1) { + + val initInt = if (init) 1 else 0 + val initPostfix = resetType match { + case SynchronizerResetType.NonSync => "" + case _ => s"_i${initInt}" + } + override def desiredName = s"${resetType.toString}ResetSynchronizerPrimitiveShiftReg_d${sync}${initPostfix}" + + val chain = List.tabulate(sync) { i => + val reg = if (resetType == SynchronizerResetType.NonSync) Reg(Bool()) else RegInit(init.B) + reg.suggestName(s"sync_$i") + } + chain.last := io.d.asBool + + (chain.init zip chain.tail).foreach { case (sink, source) => + sink := source + } + io.q := chain.head.asUInt +} + +private object SynchronizerPrimitiveShiftReg { + def apply (in: Bool, sync: Int, init: Boolean, resetType: SynchronizerResetType.Value): Bool = { + val gen: () => SynchronizerPrimitiveShiftReg = resetType match { + case SynchronizerResetType.NonSync => + () => new SynchronizerPrimitiveShiftReg(sync, init, resetType) + case SynchronizerResetType.Async => + () => new SynchronizerPrimitiveShiftReg(sync, init, resetType) with RequireAsyncReset + case SynchronizerResetType.Sync => + () => new SynchronizerPrimitiveShiftReg(sync, init, resetType) with RequireSyncReset + case SynchronizerResetType.Inferred => + () => new SynchronizerPrimitiveShiftReg(sync, init, resetType) + } + AbstractPipelineReg(gen(), in) + } +} + +// Note: This module may end up with a non-AsyncReset type reset. +// But the Primitives within will always have AsyncReset type. +class AsyncResetSynchronizerShiftReg(w: Int = 1, sync: Int, init: Int) + extends AbstractPipelineReg(w) { + require(sync > 1, s"Sync must be greater than 1, not ${sync}.") + override def desiredName = s"AsyncResetSynchronizerShiftReg_w${w}_d${sync}_i${init}" + val output = Seq.tabulate(w) { i => + val initBit = ((init >> i) & 1) > 0 + withReset(reset.asAsyncReset){ + SynchronizerPrimitiveShiftReg(io.d(i), sync, initBit, SynchronizerResetType.Async) + } + } + io.q := Cat(output.reverse) +} + +object AsyncResetSynchronizerShiftReg { + def apply [T <: Data](in: T, sync: Int, init: Int, name: Option[String] = None): T = + AbstractPipelineReg(new AsyncResetSynchronizerShiftReg(in.getWidth, sync, init), in, name) + + def apply [T <: Data](in: T, sync: Int, name: Option[String]): T = + apply (in, sync, 0, name) + + def apply [T <: Data](in: T, sync: Int): T = + apply (in, sync, 0, None) + + def apply [T <: Data](in: T, sync: Int, init: T, name: Option[String]): T = + apply(in, sync, init.litValue.toInt, name) + + def apply [T <: Data](in: T, sync: Int, init: T): T = + apply (in, sync, init.litValue.toInt, None) +} + +// Note: This module may end up with a non-Bool type reset. +// But the Primitives within will always have Bool reset type. +@deprecated("SyncResetSynchronizerShiftReg is unecessary with Chisel3 inferred resets. Use ResetSynchronizerShiftReg which will use the inferred reset type.", "rocket-chip 1.2") +class SyncResetSynchronizerShiftReg(w: Int = 1, sync: Int, init: Int) extends AbstractPipelineReg(w) { + require(sync > 1, s"Sync must be greater than 1, not ${sync}.") + override def desiredName = s"SyncResetSynchronizerShiftReg_w${w}_d${sync}_i${init}" + val output = Seq.tabulate(w) { i => + val initBit = ((init >> i) & 1) > 0 + withReset(reset.asBool){ + SynchronizerPrimitiveShiftReg(io.d(i), sync, initBit, SynchronizerResetType.Sync) + } + } + io.q := Cat(output.reverse) +} + +object SyncResetSynchronizerShiftReg { + def apply [T <: Data](in: T, sync: Int, init: Int, name: Option[String] = None): T = + if (sync == 0) in else AbstractPipelineReg(new SyncResetSynchronizerShiftReg(in.getWidth, sync, init), in, name) + + def apply [T <: Data](in: T, sync: Int, name: Option[String]): T = + apply (in, sync, 0, name) + + def apply [T <: Data](in: T, sync: Int): T = + apply (in, sync, 0, None) + + def apply [T <: Data](in: T, sync: Int, init: T, name: Option[String]): T = + apply(in, sync, init.litValue.toInt, name) + + def apply [T <: Data](in: T, sync: Int, init: T): T = + apply (in, sync, init.litValue.toInt, None) +} + +class ResetSynchronizerShiftReg(w: Int = 1, sync: Int, init: Int) extends AbstractPipelineReg(w) { + require(sync > 1, s"Sync must be greater than 1, not ${sync}.") + override def desiredName = s"ResetSynchronizerShiftReg_w${w}_d${sync}_i${init}" + val output = Seq.tabulate(w) { i => + val initBit = ((init >> i) & 1) > 0 + SynchronizerPrimitiveShiftReg(io.d(i), sync, initBit, SynchronizerResetType.Inferred) + } + io.q := Cat(output.reverse) +} + +object ResetSynchronizerShiftReg { + def apply [T <: Data](in: T, sync: Int, init: Int, name: Option[String] = None): T = + AbstractPipelineReg(new ResetSynchronizerShiftReg(in.getWidth, sync, init), in, name) + + def apply [T <: Data](in: T, sync: Int, name: Option[String]): T = + apply (in, sync, 0, name) + + def apply [T <: Data](in: T, sync: Int): T = + apply (in, sync, 0, None) + + def apply [T <: Data](in: T, sync: Int, init: T, name: Option[String]): T = + apply(in, sync, init.litValue.toInt, name) + + def apply [T <: Data](in: T, sync: Int, init: T): T = + apply (in, sync, init.litValue.toInt, None) +} + +class SynchronizerShiftReg(w: Int = 1, sync: Int = 3) extends AbstractPipelineReg(w) { + require(sync > 1, s"Sync must be greater than 1, not ${sync}.") + override def desiredName = s"SynchronizerShiftReg_w${w}_d${sync}" + val output = Seq.tabulate(w) { i => + SynchronizerPrimitiveShiftReg(io.d(i), sync, false, SynchronizerResetType.NonSync) + } + io.q := Cat(output.reverse) +} + +object SynchronizerShiftReg { + def apply [T <: Data](in: T, sync: Int, name: Option[String] = None): T = + if (sync == 0) in else AbstractPipelineReg(new SynchronizerShiftReg(in.getWidth, sync), in, name) + + def apply [T <: Data](in: T, sync: Int): T = + apply (in, sync, None) + + def apply [T <: Data](in: T): T = + apply (in, 3, None) + + +} + +class ClockCrossingReg(w: Int = 1, doInit: Boolean) extends Module { + + override def desiredName = s"ClockCrossingReg_w${w}" + + val io = IO(new Bundle{ + val d = Input(UInt(w.W)) + val q = Output(UInt(w.W)) + val en = Input(Bool()) + }) + + val cdc_reg = if (doInit) RegEnable(io.d, 0.U(w.W), io.en) else RegEnable(io.d, io.en) + io.q := cdc_reg +} + +object ClockCrossingReg { + def apply [T <: Data](in: T, en: Bool, doInit: Boolean, name: Option[String] = None): T = { + val cdc_reg = Module(new ClockCrossingReg(in.getWidth, doInit)) + name.foreach{ cdc_reg.suggestName(_) } + cdc_reg.io.d := in.asUInt + cdc_reg.io.en := en + cdc_reg.io.q.asTypeOf(in) + } +} diff --git a/rocketutils/rocketutils/src/rocketutils/Timer.scala b/rocketutils/rocketutils/src/rocketutils/Timer.scala new file mode 100644 index 00000000000..b6c925db8c8 --- /dev/null +++ b/rocketutils/rocketutils/src/rocketutils/Timer.scala @@ -0,0 +1,96 @@ +// See LICENSE.SiFive for license details. +// See LICENSE.Berkeley for license details. + +package org.chipsalliance.rocketutils + +import chisel3._ +import chisel3.util.{PriorityEncoder, Valid, log2Up} + +/** Timer with a statically-specified period. + * Can take multiple inflight start-stop events with ID + * Will continue to count down as long as at least one event is inflight + */ +class Timer(initCount: Int, maxInflight: Int) extends Module { + val io = IO(new Bundle { + val start = Flipped(Valid(UInt(log2Up(maxInflight).W))) + val stop = Flipped(Valid(UInt(log2Up(maxInflight).W))) + val timeout = Valid(UInt(log2Up(maxInflight).W)) + }) + + val inflight = RegInit(VecInit(Seq.fill(maxInflight) { false.B })) + val countdown = Reg(UInt(log2Up(initCount).W)) + val active = inflight.reduce(_ || _) + + when (active) { countdown := countdown - 1.U } + + when (io.start.valid) { + inflight(io.start.bits) := true.B + countdown := (initCount - 1).U + } + + when (io.stop.valid) { inflight(io.stop.bits) := false.B } + + io.timeout.valid := countdown === 0.U && active + io.timeout.bits := PriorityEncoder(inflight) + + assert(!io.stop.valid || inflight(io.stop.bits), + "Timer stop for transaction that's not inflight") +} + +/** Simplified Timer with a statically-specified period. + * Can be stopped repeatedly, even when not active. + */ +class SimpleTimer(initCount: Int) extends Module { + val io = IO(new Bundle { + val start = Input(Bool()) + val stop = Input(Bool()) + val timeout = Output(Bool()) + }) + + val countdown = Reg(UInt(log2Up(initCount).W)) + val active = RegInit(false.B) + + when (active) { countdown := countdown - 1.U } + + when (io.start) { + active := true.B + countdown := (initCount - 1).U + } + + when (io.stop) { active := false.B } + + io.timeout := countdown === 0.U && active +} + +object SimpleTimer { + def apply(initCount: Int, start: Bool, stop: Bool): Bool = { + val timer = Module(new SimpleTimer(initCount)) + timer.io.start := start + timer.io.stop := stop + timer.io.timeout + } +} + +/** Timer with a dynamically-specified period. */ +class DynamicTimer(w: Int) extends Module { + val io = IO(new Bundle { + val start = Input(Bool()) + val period = Input(UInt(w.W)) + val stop = Input(Bool()) + val timeout = Output(Bool()) + }) + + val countdown = RegInit(0.U(w.W)) + val active = RegInit(false.B) + + when (io.start) { + countdown := io.period + active := true.B + } .elsewhen (io.stop || countdown === 0.U) { + active := false.B + } .elsewhen (active) { + countdown := countdown - 1.U + } + + io.timeout := countdown === 0.U && active +} diff --git a/rocketutils/rocketutils/src/rocketutils/TraceCoreInterface.scala b/rocketutils/rocketutils/src/rocketutils/TraceCoreInterface.scala new file mode 100644 index 00000000000..ea671f73d11 --- /dev/null +++ b/rocketutils/rocketutils/src/rocketutils/TraceCoreInterface.scala @@ -0,0 +1,48 @@ +// See LICENSE.Berkeley for license details. +// See LICENSE.SiFive for license details. + +package org.chipsalliance.rocketutils + +import chisel3._ + +// Definitions for Trace core Interface defined in RISC-V Processor Trace Specification V1.0 +object TraceItype extends ChiselEnum { + val ITNothing = Value(0.U) + val ITException = Value(1.U) + val ITInterrupt = Value(2.U) + val ITExcReturn = Value(3.U) + val ITBrNTaken = Value(4.U) + val ITBrTaken = Value(5.U) + val ITReserved6 = Value(6.U) + val ITReserved7 = Value(7.U) + val ITUnCall = Value(8.U) + val ITInCall = Value(9.U) + val ITUnTail = Value(10.U) + val ITInTail = Value(11.U) + val ITCoSwap = Value(12.U) + val ITReturn = Value(13.U) + val ITUnJump = Value(14.U) + val ITInJump = Value(15.U) +} + +class TraceCoreParams ( + val nGroups: Int = 1, + val iretireWidth: Int = 1, + val xlen: Int = 32, + val iaddrWidth: Int = 32 +) + +class TraceCoreGroup (val params: TraceCoreParams) extends Bundle { + val iretire = UInt(params.iretireWidth.W) + val iaddr = UInt(params.iaddrWidth.W) + val itype = TraceItype() + val ilastsize = UInt(1.W) +} + +class TraceCoreInterface (val params: TraceCoreParams) extends Bundle { + val group = Vec(params.nGroups, new TraceCoreGroup(params)) + val priv = UInt(4.W) + val tval = UInt(params.xlen.W) + val cause = UInt(params.xlen.W) +} + diff --git a/rocketutils/rocketutils/src/rocketutils/conversions/package.scala b/rocketutils/rocketutils/src/rocketutils/conversions/package.scala new file mode 100644 index 00000000000..adbf2c1b0d5 --- /dev/null +++ b/rocketutils/rocketutils/src/rocketutils/conversions/package.scala @@ -0,0 +1,298 @@ +// See LICENSE.SiFive for license details. + +package org.chipsalliance.rocketutils + +import chisel3._ +import chisel3.util._ + +import scala.math.min +import scala.collection.{immutable, mutable} + +package object conversions { + implicit class UnzippableOption[S, T](val x: Option[(S, T)]) { + def unzip = (x.map(_._1), x.map(_._2)) + } + + implicit class UIntIsOneOf(private val x: UInt) extends AnyVal { + def isOneOf(s: Seq[UInt]): Bool = s.map(x === _).orR + + def isOneOf(u1: UInt, u2: UInt*): Bool = isOneOf(u1 +: u2.toSeq) + } + + implicit class VecToAugmentedVec[T <: Data](private val x: Vec[T]) extends AnyVal { + + /** Like Vec.apply(idx), but tolerates indices of mismatched width */ + def extract(idx: UInt): T = x((idx | 0.U(log2Ceil(x.size).W)).extract(log2Ceil(x.size) - 1, 0)) + } + + implicit class SeqToAugmentedSeq[T <: Data](private val x: Seq[T]) extends AnyVal { + def apply(idx: UInt): T = { + if (x.size <= 1) { + x.head + } else if (!isPow2(x.size)) { + // For non-power-of-2 seqs, reflect elements to simplify decoder + (x ++ x.takeRight(x.size & -x.size)).toSeq(idx) + } else { + // Ignore MSBs of idx + val truncIdx = + if (idx.isWidthKnown && idx.getWidth <= log2Ceil(x.size)) idx + else (idx | 0.U(log2Ceil(x.size).W))(log2Ceil(x.size)-1, 0) + x.zipWithIndex.tail.foldLeft(x.head) { case (prev, (cur, i)) => Mux(truncIdx === i.U, cur, prev) } + } + } + + def extract(idx: UInt): T = VecInit(x).extract(idx) + + def asUInt: UInt = Cat(x.map(_.asUInt).reverse) + + def rotate(n: Int): Seq[T] = x.drop(n) ++ x.take(n) + + def rotate(n: UInt): Seq[T] = { + if (x.size <= 1) { + x + } else { + require(isPow2(x.size)) + val amt = n.padTo(log2Ceil(x.size)) + (0 until log2Ceil(x.size)).foldLeft(x)((r, i) => (r.rotate(1 << i) zip r).map { case (s, a) => Mux(amt(i), s, a) }) + } + } + + def rotateRight(n: Int): Seq[T] = x.takeRight(n) ++ x.dropRight(n) + + def rotateRight(n: UInt): Seq[T] = { + if (x.size <= 1) { + x + } else { + require(isPow2(x.size)) + val amt = n.padTo(log2Ceil(x.size)) + (0 until log2Ceil(x.size)).foldLeft(x)((r, i) => (r.rotateRight(1 << i) zip r).map { case (s, a) => Mux(amt(i), s, a) }) + } + } + } + + // allow bitwise ops on Seq[Bool] just like UInt + implicit class SeqBoolBitwiseOps(private val x: Seq[Bool]) extends AnyVal { + def & (y: Seq[Bool]): Seq[Bool] = (x zip y).map { case (a, b) => a && b } + def | (y: Seq[Bool]): Seq[Bool] = padZip(x, y).map { case (a, b) => a || b } + def ^ (y: Seq[Bool]): Seq[Bool] = padZip(x, y).map { case (a, b) => a ^ b } + def << (n: Int): Seq[Bool] = Seq.fill(n)(false.B) ++ x + def >> (n: Int): Seq[Bool] = x drop n + def unary_~ : Seq[Bool] = x.map(!_) + def andR: Bool = if (x.isEmpty) true.B else x.reduce(_&&_) + def orR: Bool = if (x.isEmpty) false.B else x.reduce(_||_) + def xorR: Bool = if (x.isEmpty) false.B else x.reduce(_^_) + + private def padZip(y: Seq[Bool], z: Seq[Bool]): Seq[(Bool, Bool)] = y.padTo(z.size, false.B) zip z.padTo(y.size, false.B) + } + + implicit class DataToAugmentedData[T <: Data](private val x: T) extends AnyVal { + def holdUnless(enable: Bool): T = Mux(enable, x, RegEnable(x, enable)) + + def getElements: Seq[Element] = x match { + case e: Element => Seq(e) + case a: Aggregate => a.getElements.flatMap(_.getElements) + } + } + + /** Any Data subtype that has a Bool member named valid. */ + type DataCanBeValid = Data { val valid: Bool } + + implicit class SeqMemToAugmentedSeqMem[T <: Data](private val x: SyncReadMem[T]) extends AnyVal { + def readAndHold(addr: UInt, enable: Bool): T = x.read(addr, enable) holdUnless RegNext(enable) + } + + implicit class StringToAugmentedString(private val x: String) extends AnyVal { + /** converts from camel case to to underscores, also removing all spaces */ + def underscore: String = x.tail.foldLeft(x.headOption.map(_.toLower + "") getOrElse "") { + case (acc, c) if c.isUpper => acc + "_" + c.toLower + case (acc, c) if c == ' ' => acc + case (acc, c) => acc + c + } + + /** converts spaces or underscores to hyphens, also lowering case */ + def kebab: String = x.toLowerCase map { + case ' ' => '-' + case '_' => '-' + case c => c + } + + def named(name: Option[String]): String = { + x + name.map("_named_" + _ ).getOrElse("_with_no_name") + } + + def named(name: String): String = named(Some(name)) + } + + implicit def uintToBitPat(x: UInt): BitPat = BitPat(x) + implicit def wcToUInt(c: WideCounter): UInt = c.value + + implicit class UIntToAugmentedUInt(private val x: UInt) extends AnyVal { + def sextTo(n: Int): UInt = { + require(x.getWidth <= n) + if (x.getWidth == n) x + else Cat(Fill(n - x.getWidth, x(x.getWidth-1)), x) + } + + def padTo(n: Int): UInt = { + require(x.getWidth <= n) + if (x.getWidth == n) x + else Cat(0.U((n - x.getWidth).W), x) + } + + // shifts left by n if n >= 0, or right by -n if n < 0 + def << (n: SInt): UInt = { + val w = n.getWidth - 1 + require(w <= 30) + + val shifted = x << n(w-1, 0) + Mux(n(w), shifted >> (1 << w), shifted) + } + + // shifts right by n if n >= 0, or left by -n if n < 0 + def >> (n: SInt): UInt = { + val w = n.getWidth - 1 + require(w <= 30) + + val shifted = x << (1 << w) >> n(w-1, 0) + Mux(n(w), shifted, shifted >> (1 << w)) + } + + // Like UInt.apply(hi, lo), but returns 0.U for zero-width extracts + def extract(hi: Int, lo: Int): UInt = { + require(hi >= lo-1) + if (hi == lo-1) 0.U + else x(hi, lo) + } + + // Like Some(UInt.apply(hi, lo)), but returns None for zero-width extracts + def extractOption(hi: Int, lo: Int): Option[UInt] = { + require(hi >= lo-1) + if (hi == lo-1) None + else Some(x(hi, lo)) + } + + // like x & ~y, but first truncate or zero-extend y to x's width + def andNot(y: UInt): UInt = x & ~(y | (x & 0.U)) + + def rotateRight(n: Int): UInt = if (n == 0) x else Cat(x(n-1, 0), x >> n) + + def rotateRight(n: UInt): UInt = { + if (x.getWidth <= 1) { + x + } else { + val amt = n.padTo(log2Ceil(x.getWidth)) + (0 until log2Ceil(x.getWidth)).foldLeft(x)((r, i) => Mux(amt(i), r.rotateRight(1 << i), r)) + } + } + + def rotateLeft(n: Int): UInt = if (n == 0) x else Cat(x(x.getWidth-1-n,0), x(x.getWidth-1,x.getWidth-n)) + + def rotateLeft(n: UInt): UInt = { + if (x.getWidth <= 1) { + x + } else { + val amt = n.padTo(log2Ceil(x.getWidth)) + (0 until log2Ceil(x.getWidth)).foldLeft(x)((r, i) => Mux(amt(i), r.rotateLeft(1 << i), r)) + } + } + + // compute (this + y) % n, given (this < n) and (y < n) + def addWrap(y: UInt, n: Int): UInt = { + val z = x +& y + if (isPow2(n)) z(n.log2-1, 0) else Mux(z >= n.U, z - n.U, z)(log2Ceil(n)-1, 0) + } + + // compute (this - y) % n, given (this < n) and (y < n) + def subWrap(y: UInt, n: Int): UInt = { + val z = x -& y + if (isPow2(n)) z(n.log2-1, 0) else Mux(z(z.getWidth-1), z + n.U, z)(log2Ceil(n)-1, 0) + } + + def grouped(width: Int): Seq[UInt] = + (0 until x.getWidth by width).map(base => x(base + width - 1, base)) + + def inRange(base: UInt, bounds: UInt) = x >= base && x < bounds + + def ## (y: Option[UInt]): UInt = y.map(x ## _).getOrElse(x) + + // Like >=, but prevents x-prop for ('x >= 0) + def >== (y: UInt): Bool = x >= y || y === 0.U + } + + implicit class OptionUIntToAugmentedOptionUInt(private val x: Option[UInt]) extends AnyVal { + def ## (y: UInt): UInt = x.map(_ ## y).getOrElse(y) + def ## (y: Option[UInt]): Option[UInt] = x.map(_ ## y) + } + + implicit class BooleanToAugmentedBoolean(private val x: Boolean) extends AnyVal { + def toInt: Int = if (x) 1 else 0 + + // this one's snagged from scalaz + def option[T](z: => T): Option[T] = if (x) Some(z) else None + } + + implicit class IntToAugmentedInt(private val x: Int) extends AnyVal { + // exact log2 + def log2: Int = { + require(isPow2(x)) + log2Ceil(x) + } + } + + def OH1ToOH(x: UInt): UInt = (x << 1 | 1.U) & ~Cat(0.U(1.W), x) + def OH1ToUInt(x: UInt): UInt = OHToUInt(OH1ToOH(x)) + def UIntToOH1(x: UInt, width: Int): UInt = ~((-1).S(width.W).asUInt << x)(width-1, 0) + def UIntToOH1(x: UInt): UInt = UIntToOH1(x, (1 << x.getWidth) - 1) + + def trailingZeros(x: Int): Option[Int] = if (x > 0) Some(log2Ceil(x & -x)) else None + + // Fill 1s from low bits to high bits + def leftOR(x: UInt): UInt = leftOR(x, x.getWidth, x.getWidth) + def leftOR(x: UInt, width: Integer, cap: Integer = 999999): UInt = { + val stop = min(width, cap) + def helper(s: Int, x: UInt): UInt = + if (s >= stop) x else helper(s+s, x | (x << s)(width-1,0)) + helper(1, x)(width-1, 0) + } + + // Fill 1s form high bits to low bits + def rightOR(x: UInt): UInt = rightOR(x, x.getWidth, x.getWidth) + def rightOR(x: UInt, width: Integer, cap: Integer = 999999): UInt = { + val stop = min(width, cap) + def helper(s: Int, x: UInt): UInt = + if (s >= stop) x else helper(s+s, x | (x >> s)) + helper(1, x)(width-1, 0) + } + + def OptimizationBarrier[T <: Data](in: T): T = { + val barrier = Module(new Module { + val io = IO(new Bundle { + val x = Input(chiselTypeOf(in)) + val y = Output(chiselTypeOf(in)) + }) + io.y := io.x + override def desiredName = "OptimizationBarrier" + }) + barrier.io.x := in + barrier.io.y + } + + /** Similar to Seq.groupBy except this returns a Seq instead of a Map + * Useful for deterministic code generation + */ + def groupByIntoSeq[A, K](xs: Seq[A])(f: A => K): immutable.Seq[(K, immutable.Seq[A])] = { + val map = mutable.LinkedHashMap.empty[K, mutable.ListBuffer[A]] + for (x <- xs) { + val key = f(x) + val l = map.getOrElseUpdate(key, mutable.ListBuffer.empty[A]) + l += x + } + map.view.map({ case (k, vs) => k -> vs.toList }).toList + } + + def heterogeneousOrGlobalSetting[T](in: Seq[T], n: Int): Seq[T] = in.size match { + case 1 => List.fill(n)(in.head) + case x if x == n => in + case _ => throw new Exception(s"must provide exactly 1 or $n of some field, but got:\n$in") + } +} diff --git a/src/main/scala/amba/ahb/Bundles.scala b/src/main/scala/amba/ahb/Bundles.scala index 662087aae86..95eb9caa75c 100644 --- a/src/main/scala/amba/ahb/Bundles.scala +++ b/src/main/scala/amba/ahb/Bundles.scala @@ -3,7 +3,8 @@ package freechips.rocketchip.amba.ahb import chisel3._ -import freechips.rocketchip.util._ + +import org.chipsalliance.rocketutils.BundleMap // Signal directions are from the master's point-of-view class AHBSlaveBundle(val params: AHBBundleParameters) extends Bundle diff --git a/src/main/scala/amba/ahb/Parameters.scala b/src/main/scala/amba/ahb/Parameters.scala index 0039b928b7c..e32db9c55ab 100644 --- a/src/main/scala/amba/ahb/Parameters.scala +++ b/src/main/scala/amba/ahb/Parameters.scala @@ -8,10 +8,10 @@ import chisel3.util._ import org.chipsalliance.cde.config.Parameters import org.chipsalliance.diplomacy.nodes.BaseNode +import org.chipsalliance.rocketutils.{BundleField, BundleFieldBase, BundleKeyBase} import freechips.rocketchip.resources.{Resource, Device, ResourceAddress, ResourcePermissions} import freechips.rocketchip.diplomacy.{AddressSet, RegionType, TransferSizes} -import freechips.rocketchip.util.{BundleField, BundleFieldBase, BundleKeyBase} import scala.math.{max, min} diff --git a/src/main/scala/amba/ahb/RegisterRouter.scala b/src/main/scala/amba/ahb/RegisterRouter.scala index e2619b66c8c..6594f758c69 100644 --- a/src/main/scala/amba/ahb/RegisterRouter.scala +++ b/src/main/scala/amba/ahb/RegisterRouter.scala @@ -8,12 +8,13 @@ import chisel3.util.{log2Up, log2Ceil, Decoupled} import org.chipsalliance.cde.config.Parameters import org.chipsalliance.diplomacy.ValName -import org.chipsalliance.diplomacy.nodes.{SinkNode} +import org.chipsalliance.diplomacy.nodes.SinkNode + +import org.chipsalliance.rocketutils.MaskGen import freechips.rocketchip.diplomacy.{AddressSet, TransferSizes} import freechips.rocketchip.regmapper.{RegMapperParams, RegField, RegMapperInput, RegisterRouter, RegMapper} import freechips.rocketchip.interrupts.{IntSourceNode, IntSourcePortSimple} -import freechips.rocketchip.util.MaskGen import scala.math.min diff --git a/src/main/scala/amba/ahb/SRAM.scala b/src/main/scala/amba/ahb/SRAM.scala index a4a8bdeae3b..6ac8517ded9 100644 --- a/src/main/scala/amba/ahb/SRAM.scala +++ b/src/main/scala/amba/ahb/SRAM.scala @@ -6,11 +6,13 @@ import chisel3._ import chisel3.util._ import org.chipsalliance.cde.config.Parameters import org.chipsalliance.diplomacy.lazymodule.{LazyModule, LazyModuleImp} +import org.chipsalliance.rocketutils.{MaskGen, PlusArg} import freechips.rocketchip.diplomacy.{AddressSet, RegionType, TransferSizes} import freechips.rocketchip.resources.{DiplomaticSRAM, HasJustOneSeqMem} import freechips.rocketchip.tilelink.LFSRNoiseMaker -import freechips.rocketchip.util.{MaskGen, DataToAugmentedData, SeqMemToAugmentedSeqMem, PlusArg} + +import org.chipsalliance.rocketutils.conversions.{DataToAugmentedData, SeqMemToAugmentedSeqMem} class AHBRAM( address: AddressSet, diff --git a/src/main/scala/amba/ahb/ToTL.scala b/src/main/scala/amba/ahb/ToTL.scala index e34d7c262ba..f712a9abf70 100644 --- a/src/main/scala/amba/ahb/ToTL.scala +++ b/src/main/scala/amba/ahb/ToTL.scala @@ -11,10 +11,13 @@ import org.chipsalliance.diplomacy.ValName import org.chipsalliance.diplomacy.nodes.{MixedAdapterNode} import org.chipsalliance.diplomacy.lazymodule.{LazyModule, LazyModuleImp} +import org.chipsalliance.rocketutils.{BundleMap, MaskGen} + import freechips.rocketchip.amba.{AMBAProtField, AMBAProt} import freechips.rocketchip.diplomacy.TransferSizes import freechips.rocketchip.tilelink.{TLImp, TLMasterPortParameters, TLMessages, TLMasterParameters, TLMasterToSlaveTransferSizes} -import freechips.rocketchip.util.{BundleMap, MaskGen, DataToAugmentedData} + +import org.chipsalliance.rocketutils.conversions.DataToAugmentedData case class AHBToTLNode()(implicit valName: ValName) extends MixedAdapterNode(AHBImpSlave, TLImp)( dFn = { case mp => diff --git a/src/main/scala/amba/ahb/Xbar.scala b/src/main/scala/amba/ahb/Xbar.scala index d685ac1bed9..d598cf863f1 100644 --- a/src/main/scala/amba/ahb/Xbar.scala +++ b/src/main/scala/amba/ahb/Xbar.scala @@ -8,8 +8,9 @@ import chisel3.util.Mux1H import org.chipsalliance.cde.config.Parameters import org.chipsalliance.diplomacy.lazymodule.{LazyModule, LazyModuleImp} +import org.chipsalliance.rocketutils.BundleField + import freechips.rocketchip.diplomacy.AddressDecoder -import freechips.rocketchip.util.BundleField class AHBFanout()(implicit p: Parameters) extends LazyModule { diff --git a/src/main/scala/amba/apb/Bundles.scala b/src/main/scala/amba/apb/Bundles.scala index 59129c15aa5..0915f8972c9 100644 --- a/src/main/scala/amba/apb/Bundles.scala +++ b/src/main/scala/amba/apb/Bundles.scala @@ -3,7 +3,8 @@ package freechips.rocketchip.amba.apb import chisel3._ -import freechips.rocketchip.util._ + +import org.chipsalliance.rocketutils.BundleMap // Signal directions are from the master's point-of-view class APBBundle(val params: APBBundleParameters) extends Bundle diff --git a/src/main/scala/amba/apb/Parameters.scala b/src/main/scala/amba/apb/Parameters.scala index f39c8b03fef..d72733fa2c3 100644 --- a/src/main/scala/amba/apb/Parameters.scala +++ b/src/main/scala/amba/apb/Parameters.scala @@ -6,12 +6,11 @@ import chisel3.util.{isPow2, log2Up} import chisel3.experimental.SourceInfo import org.chipsalliance.cde.config.Parameters - import org.chipsalliance.diplomacy.nodes.BaseNode +import org.chipsalliance.rocketutils.{BundleField, BundleKeyBase, BundleFieldBase} import freechips.rocketchip.diplomacy.{AddressSet, RegionType} import freechips.rocketchip.resources.{Resource, Device, ResourceAddress, ResourcePermissions} -import freechips.rocketchip.util.{BundleField, BundleKeyBase, BundleFieldBase} import scala.math.max diff --git a/src/main/scala/amba/apb/SRAM.scala b/src/main/scala/amba/apb/SRAM.scala index 8c5a9c27487..d08e61aca28 100644 --- a/src/main/scala/amba/apb/SRAM.scala +++ b/src/main/scala/amba/apb/SRAM.scala @@ -12,7 +12,8 @@ import org.chipsalliance.diplomacy.lazymodule.{LazyModule, LazyModuleImp} import freechips.rocketchip.diplomacy.{AddressSet, RegionType} import freechips.rocketchip.resources.{DiplomaticSRAM, HasJustOneSeqMem} import freechips.rocketchip.tilelink.LFSRNoiseMaker -import freechips.rocketchip.util.SeqMemToAugmentedSeqMem + +import org.chipsalliance.rocketutils.conversions.SeqMemToAugmentedSeqMem class APBRAM( address: AddressSet, diff --git a/src/main/scala/amba/apb/Xbar.scala b/src/main/scala/amba/apb/Xbar.scala index 3f50fbb4ea1..d7e1ad7d902 100644 --- a/src/main/scala/amba/apb/Xbar.scala +++ b/src/main/scala/amba/apb/Xbar.scala @@ -9,8 +9,9 @@ import org.chipsalliance.cde.config.Parameters import org.chipsalliance.diplomacy.lazymodule.{LazyModule, LazyModuleImp} +import org.chipsalliance.rocketutils.BundleField + import freechips.rocketchip.diplomacy.AddressDecoder -import freechips.rocketchip.util.BundleField class APBFanout()(implicit p: Parameters) extends LazyModule { val node = new APBNexusNode( diff --git a/src/main/scala/amba/axi4/AsyncCrossing.scala b/src/main/scala/amba/axi4/AsyncCrossing.scala index b9303e5c108..007b2e2bc26 100644 --- a/src/main/scala/amba/axi4/AsyncCrossing.scala +++ b/src/main/scala/amba/axi4/AsyncCrossing.scala @@ -8,12 +8,12 @@ import org.chipsalliance.cde.config.Parameters import org.chipsalliance.diplomacy.nodes.{NodeHandle} import org.chipsalliance.diplomacy.lazymodule.{LazyModule, LazyModuleImp} +import org.chipsalliance.rocketutils.{ToAsyncBundle, FromAsyncBundle, AsyncQueueParams, Pow2ClockDivider} import freechips.rocketchip.diplomacy.{AddressSet} import freechips.rocketchip.prci.{AsynchronousCrossing} import freechips.rocketchip.tilelink.{TLRAMModel, TLFuzzer, TLToAXI4} import freechips.rocketchip.subsystem.CrossingWrapper -import freechips.rocketchip.util.{ToAsyncBundle, FromAsyncBundle, AsyncQueueParams, Pow2ClockDivider} /** * Source(Master) side for AXI4 crossing clock domain diff --git a/src/main/scala/amba/axi4/Bundles.scala b/src/main/scala/amba/axi4/Bundles.scala index 96b62e2ef1d..0290b77fa7c 100644 --- a/src/main/scala/amba/axi4/Bundles.scala +++ b/src/main/scala/amba/axi4/Bundles.scala @@ -4,7 +4,8 @@ package freechips.rocketchip.amba.axi4 import chisel3._ import chisel3.util._ -import freechips.rocketchip.util._ + +import org.chipsalliance.rocketutils.{AsyncBundle, BundleMap, CreditedIO} abstract class AXI4BundleBase(val params: AXI4BundleParameters) extends Bundle diff --git a/src/main/scala/amba/axi4/Credited.scala b/src/main/scala/amba/axi4/Credited.scala index 3dbea790f8b..93671a891da 100644 --- a/src/main/scala/amba/axi4/Credited.scala +++ b/src/main/scala/amba/axi4/Credited.scala @@ -5,14 +5,13 @@ package freechips.rocketchip.amba.axi4 import chisel3._ import org.chipsalliance.cde.config.Parameters - import org.chipsalliance.diplomacy.lazymodule.{LazyModule, LazyModuleImp} +import org.chipsalliance.rocketutils.{CreditedDelay, CreditedIO} import freechips.rocketchip.diplomacy.{AddressSet} import freechips.rocketchip.prci.{CreditedCrossing} import freechips.rocketchip.subsystem.CrossingWrapper import freechips.rocketchip.tilelink._ -import freechips.rocketchip.util._ class AXI4CreditedBuffer(delay: AXI4CreditedDelay)(implicit p: Parameters) extends LazyModule { diff --git a/src/main/scala/amba/axi4/Deinterleaver.scala b/src/main/scala/amba/axi4/Deinterleaver.scala index 461507a5e0c..cc08b8a55b2 100644 --- a/src/main/scala/amba/axi4/Deinterleaver.scala +++ b/src/main/scala/amba/axi4/Deinterleaver.scala @@ -11,7 +11,8 @@ import org.chipsalliance.cde.config.Parameters import org.chipsalliance.diplomacy.lazymodule.{LazyModule, LazyModuleImp} import freechips.rocketchip.diplomacy.{BufferParams, TransferSizes} -import freechips.rocketchip.util.leftOR + +import org.chipsalliance.rocketutils.conversions.leftOR /** This adapter deinterleaves read responses on the R channel. * diff --git a/src/main/scala/amba/axi4/Fragmenter.scala b/src/main/scala/amba/axi4/Fragmenter.scala index 85505374088..1cd6228a300 100644 --- a/src/main/scala/amba/axi4/Fragmenter.scala +++ b/src/main/scala/amba/axi4/Fragmenter.scala @@ -9,8 +9,11 @@ import org.chipsalliance.cde.config.Parameters import org.chipsalliance.diplomacy.lazymodule.{LazyModule, LazyModuleImp} +import org.chipsalliance.rocketutils.{ControlKey, SimpleBundleField} + import freechips.rocketchip.diplomacy.{AddressDecoder, AddressSet, TransferSizes} -import freechips.rocketchip.util.{ControlKey, SimpleBundleField, rightOR, leftOR, OH1ToOH, UIntToOH1} + +import org.chipsalliance.rocketutils.conversions.{rightOR, leftOR, OH1ToOH, UIntToOH1} case object AXI4FragLast extends ControlKey[Bool]("real_last") case class AXI4FragLastField() extends SimpleBundleField(AXI4FragLast)(Output(Bool()), false.B) diff --git a/src/main/scala/amba/axi4/IdIndexer.scala b/src/main/scala/amba/axi4/IdIndexer.scala index 4687d5dc0f8..aace7613167 100644 --- a/src/main/scala/amba/axi4/IdIndexer.scala +++ b/src/main/scala/amba/axi4/IdIndexer.scala @@ -9,8 +9,9 @@ import org.chipsalliance.cde.config.Parameters import org.chipsalliance.diplomacy.lazymodule.{LazyModule, LazyModuleImp} +import org.chipsalliance.rocketutils.{ControlKey, SimpleBundleField} + import freechips.rocketchip.diplomacy.IdRange -import freechips.rocketchip.util.{ControlKey, SimpleBundleField} case object AXI4ExtraId extends ControlKey[UInt]("extra_id") case class AXI4ExtraIdField(width: Int) extends SimpleBundleField(AXI4ExtraId)(Output(UInt(width.W)), 0.U) diff --git a/src/main/scala/amba/axi4/Nodes.scala b/src/main/scala/amba/axi4/Nodes.scala index da53aa92ea6..45e6a33e59e 100644 --- a/src/main/scala/amba/axi4/Nodes.scala +++ b/src/main/scala/amba/axi4/Nodes.scala @@ -10,7 +10,7 @@ import org.chipsalliance.cde.config.{Parameters, Field} import org.chipsalliance.diplomacy.ValName import org.chipsalliance.diplomacy.nodes.{SimpleNodeImp, RenderedEdge, OutwardNode, InwardNode, SourceNode, SinkNode, NexusNode, AdapterNode, IdentityNode, MixedAdapterNode} -import freechips.rocketchip.util.AsyncQueueParams +import org.chipsalliance.rocketutils.AsyncQueueParams case object AXI4MonitorBuilder extends Field[AXI4MonitorArgs => AXI4MonitorBase] diff --git a/src/main/scala/amba/axi4/Parameters.scala b/src/main/scala/amba/axi4/Parameters.scala index 088c226d825..a323d110a40 100644 --- a/src/main/scala/amba/axi4/Parameters.scala +++ b/src/main/scala/amba/axi4/Parameters.scala @@ -8,10 +8,10 @@ import chisel3.util.{isPow2, log2Up} import org.chipsalliance.cde.config.Parameters import org.chipsalliance.diplomacy.nodes.BaseNode +import org.chipsalliance.rocketutils.{BundleField, BundleFieldBase, BundleKeyBase, AsyncQueueParams, CreditedDelay} import freechips.rocketchip.diplomacy.{AddressSet, RegionType, TransferSizes, IdRange, BufferParams, IdMap, IdMapEntry, DirectedBuffers} import freechips.rocketchip.resources.{Resource, Device, ResourceAddress, ResourcePermissions} -import freechips.rocketchip.util.{BundleField, BundleFieldBase, BundleKeyBase, AsyncQueueParams, CreditedDelay} import scala.math.max diff --git a/src/main/scala/amba/axi4/RegisterRouter.scala b/src/main/scala/amba/axi4/RegisterRouter.scala index be48fa2eaf9..e35267f07ef 100644 --- a/src/main/scala/amba/axi4/RegisterRouter.scala +++ b/src/main/scala/amba/axi4/RegisterRouter.scala @@ -9,12 +9,12 @@ import org.chipsalliance.cde.config.Parameters import org.chipsalliance.diplomacy.ValName import org.chipsalliance.diplomacy.nodes.{SinkNode} +import org.chipsalliance.rocketutils.{ControlKey, SimpleBundleField, BundleFieldBase, BundleMap, MaskGen} import freechips.rocketchip.diplomacy.{AddressSet, TransferSizes} import freechips.rocketchip.prci.{NoCrossing} import freechips.rocketchip.regmapper.{RegField, RegMapper, RegMapperInput, RegMapperParams, RegisterRouter} import freechips.rocketchip.interrupts.{IntSourceNode, IntSourcePortSimple} -import freechips.rocketchip.util._ case object AXI4RRId extends ControlKey[UInt]("extra_id") case class AXI4RRIdField(width: Int) extends SimpleBundleField(AXI4RRId)(Output(UInt((1 max width).W)), 0.U) diff --git a/src/main/scala/amba/axi4/SRAM.scala b/src/main/scala/amba/axi4/SRAM.scala index f4838b73ab0..83a4373f3ca 100644 --- a/src/main/scala/amba/axi4/SRAM.scala +++ b/src/main/scala/amba/axi4/SRAM.scala @@ -8,11 +8,13 @@ import chisel3.util.{Cat, log2Ceil} import org.chipsalliance.cde.config.Parameters import org.chipsalliance.diplomacy.lazymodule.{LazyModule, LazyModuleImp} +import org.chipsalliance.rocketutils.BundleMap import freechips.rocketchip.amba.AMBACorrupt import freechips.rocketchip.diplomacy.{AddressSet, RegionType, TransferSizes} import freechips.rocketchip.resources.{DiplomaticSRAM, HasJustOneSeqMem} -import freechips.rocketchip.util.{BundleMap, SeqMemToAugmentedSeqMem} + +import org.chipsalliance.rocketutils.conversions.SeqMemToAugmentedSeqMem /** * AXI4 slave device to provide a RAM storage diff --git a/src/main/scala/amba/axi4/ToTL.scala b/src/main/scala/amba/axi4/ToTL.scala index 833be2e4e28..5cd0ef7cf1d 100644 --- a/src/main/scala/amba/axi4/ToTL.scala +++ b/src/main/scala/amba/axi4/ToTL.scala @@ -14,7 +14,8 @@ import org.chipsalliance.diplomacy.lazymodule.{LazyModule, LazyModuleImp} import freechips.rocketchip.amba.{AMBACorrupt, AMBAProt, AMBAProtField} import freechips.rocketchip.diplomacy.{IdRange, IdMapEntry, TransferSizes} import freechips.rocketchip.tilelink.{TLImp, TLMasterParameters, TLMasterPortParameters, TLArbiter} -import freechips.rocketchip.util.{OH1ToUInt, UIntToOH1} + +import org.chipsalliance.rocketutils.conversions.{OH1ToUInt, UIntToOH1} case class AXI4ToTLIdMapEntry(tlId: IdRange, axi4Id: IdRange, name: String) extends IdMapEntry diff --git a/src/main/scala/amba/axi4/UserYanker.scala b/src/main/scala/amba/axi4/UserYanker.scala index 93e69cd4b92..a2f4c87229f 100644 --- a/src/main/scala/amba/axi4/UserYanker.scala +++ b/src/main/scala/amba/axi4/UserYanker.scala @@ -9,7 +9,8 @@ import org.chipsalliance.cde.config.Parameters import org.chipsalliance.diplomacy.lazymodule.{LazyModule, LazyModuleImp} -import freechips.rocketchip.util.BundleMap +import org.chipsalliance.rocketutils.BundleMap + /** This adapter prunes all user bit fields of the echo type from request messages, * storing them in queues and echoing them back when matching response messages are received. diff --git a/src/main/scala/amba/axi4/Xbar.scala b/src/main/scala/amba/axi4/Xbar.scala index 291e92acdbe..63c3efa81e7 100644 --- a/src/main/scala/amba/axi4/Xbar.scala +++ b/src/main/scala/amba/axi4/Xbar.scala @@ -9,10 +9,11 @@ import org.chipsalliance.cde.config.Parameters import org.chipsalliance.diplomacy.lazymodule.{LazyModule, LazyModuleImp} +import org.chipsalliance.rocketutils.BundleField + import freechips.rocketchip.diplomacy.{AddressDecoder, AddressSet, BufferParams} import freechips.rocketchip.tilelink.{TLArbiter, TLXbar, TLFilter, TLFuzzer, TLToAXI4, TLRAMModel} import freechips.rocketchip.unittest.{UnitTest, UnitTestModule} -import freechips.rocketchip.util.BundleField /** * AXI4 Crossbar. It connects multiple AXI4 masters to slaves. diff --git a/src/main/scala/amba/axis/Bundles.scala b/src/main/scala/amba/axis/Bundles.scala index c8a7832d8e2..9c64fad07d6 100644 --- a/src/main/scala/amba/axis/Bundles.scala +++ b/src/main/scala/amba/axis/Bundles.scala @@ -3,7 +3,8 @@ package freechips.rocketchip.amba.axis import chisel3._ import chisel3.util._ -import freechips.rocketchip.util._ + +import org.chipsalliance.rocketutils.{BundleField, BundleFieldBase, BundleMap, ControlKey, DataKey, SimpleBundleField} sealed trait AXISKey case object AXISLast extends ControlKey[Bool]("last") with AXISKey diff --git a/src/main/scala/amba/axis/Parameters.scala b/src/main/scala/amba/axis/Parameters.scala index bcc928bf36e..79eeb5f0039 100644 --- a/src/main/scala/amba/axis/Parameters.scala +++ b/src/main/scala/amba/axis/Parameters.scala @@ -6,10 +6,10 @@ import chisel3.util.{isPow2, log2Ceil} import org.chipsalliance.cde.config.Parameters import org.chipsalliance.diplomacy.nodes.BaseNode +import org.chipsalliance.rocketutils.{BundleFieldBase, BundleField} import freechips.rocketchip.diplomacy.{TransferSizes, IdRange} import freechips.rocketchip.resources.{Resource} -import freechips.rocketchip.util.{BundleFieldBase, BundleField} class AXISSlaveParameters private ( diff --git a/src/main/scala/amba/package.scala b/src/main/scala/amba/package.scala index 75a971c7f75..f0769df8093 100644 --- a/src/main/scala/amba/package.scala +++ b/src/main/scala/amba/package.scala @@ -4,7 +4,7 @@ package freechips.rocketchip import chisel3._ -import freechips.rocketchip.util.{ControlKey, DataKey, BundleField} +import org.chipsalliance.rocketutils.{ControlKey, DataKey, BundleField} package object amba { class AMBAProtBundle extends Bundle { diff --git a/src/main/scala/devices/debug/DMI.scala b/src/main/scala/devices/debug/DMI.scala index eeffdc2917c..a5b1c373924 100644 --- a/src/main/scala/devices/debug/DMI.scala +++ b/src/main/scala/devices/debug/DMI.scala @@ -7,10 +7,10 @@ import chisel3.util._ import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy.lazymodule._ +import org.chipsalliance.rocketutils.ParameterizedBundle import freechips.rocketchip.diplomacy.TransferSizes import freechips.rocketchip.tilelink.{TLClientNode, TLMasterParameters, TLMasterPortParameters, TLMasterToSlaveTransferSizes} -import freechips.rocketchip.util.ParameterizedBundle /** Constant values used by both Debug Bus Response & Request */ diff --git a/src/main/scala/devices/debug/Debug.scala b/src/main/scala/devices/debug/Debug.scala index cd099215155..76916e15fb3 100755 --- a/src/main/scala/devices/debug/Debug.scala +++ b/src/main/scala/devices/debug/Debug.scala @@ -8,6 +8,7 @@ import chisel3.util._ import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy.lazymodule._ +import org.chipsalliance.rocketutils.{Annotated, AsyncBundle, AsyncQueueParams, AsyncResetSynchronizerShiftReg, FromAsyncBundle, ParameterizedBundle, ResetSynchronizerShiftReg, ToAsyncBundle} import freechips.rocketchip.amba.apb.{APBFanout, APBToTL} import freechips.rocketchip.devices.debug.systembusaccess.{SBToTL, SystemBusAccessModule} @@ -19,11 +20,8 @@ import freechips.rocketchip.regmapper.{RegField, RegFieldAccessType, RegFieldDes import freechips.rocketchip.rocket.{CSRs, Instructions} import freechips.rocketchip.tile.MaxHartIdBits import freechips.rocketchip.tilelink.{TLAsyncCrossingSink, TLAsyncCrossingSource, TLBuffer, TLRegisterNode, TLXbar} -import freechips.rocketchip.util.{Annotated, AsyncBundle, AsyncQueueParams, AsyncResetSynchronizerShiftReg, FromAsyncBundle, ParameterizedBundle, ResetSynchronizerShiftReg, ToAsyncBundle} -import freechips.rocketchip.util.SeqBoolBitwiseOps -import freechips.rocketchip.util.SeqToAugmentedSeq -import freechips.rocketchip.util.BooleanToAugmentedBoolean +import org.chipsalliance.rocketutils.conversions.{SeqBoolBitwiseOps, SeqToAugmentedSeq, BooleanToAugmentedBoolean} object DsbBusConsts { def sbAddrWidth = 12 diff --git a/src/main/scala/devices/debug/DebugTransport.scala b/src/main/scala/devices/debug/DebugTransport.scala index 190dff11c27..c725f155e59 100644 --- a/src/main/scala/devices/debug/DebugTransport.scala +++ b/src/main/scala/devices/debug/DebugTransport.scala @@ -6,8 +6,9 @@ import chisel3._ import chisel3.util._ import org.chipsalliance.cde.config._ +import org.chipsalliance.rocketutils.property + import freechips.rocketchip.jtag._ -import freechips.rocketchip.util.property case class JtagDTMConfig ( diff --git a/src/main/scala/devices/debug/Periphery.scala b/src/main/scala/devices/debug/Periphery.scala index 056604dbcfe..b078be0bdca 100644 --- a/src/main/scala/devices/debug/Periphery.scala +++ b/src/main/scala/devices/debug/Periphery.scala @@ -8,6 +8,7 @@ import chisel3.util._ import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy.lazymodule._ +import org.chipsalliance.rocketutils.{AsyncResetSynchronizerShiftReg, CanHavePSDTestModeIO, ClockGate, PSDTestMode, PlusArg, ResetSynchronizerShiftReg} import freechips.rocketchip.amba.apb.{APBBundle, APBBundleParameters, APBMasterNode, APBMasterParameters, APBMasterPortParameters} import freechips.rocketchip.interrupts.{IntSyncXbar, NullIntSyncSource} @@ -15,9 +16,8 @@ import freechips.rocketchip.jtag.JTAGIO import freechips.rocketchip.prci.{ClockSinkNode, ClockSinkParameters} import freechips.rocketchip.subsystem.{BaseSubsystem, CBUS, FBUS, ResetSynchronous, SubsystemResetSchemeKey, TLBusWrapperLocation} import freechips.rocketchip.tilelink.{TLFragmenter, TLWidthWidget} -import freechips.rocketchip.util.{AsyncResetSynchronizerShiftReg, CanHavePSDTestModeIO, ClockGate, PSDTestMode, PlusArg, ResetSynchronizerShiftReg} -import freechips.rocketchip.util.BooleanToAugmentedBoolean +import org.chipsalliance.rocketutils.conversions.BooleanToAugmentedBoolean /** Protocols used for communicating with external debugging tools */ sealed trait DebugExportProtocol diff --git a/src/main/scala/devices/debug/SBA.scala b/src/main/scala/devices/debug/SBA.scala index 568291a221f..fdbfb7a1c17 100644 --- a/src/main/scala/devices/debug/SBA.scala +++ b/src/main/scala/devices/debug/SBA.scala @@ -7,13 +7,13 @@ import chisel3.util._ import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy.lazymodule._ +import org.chipsalliance.rocketutils.property import freechips.rocketchip.amba.{AMBAProt, AMBAProtField} import freechips.rocketchip.devices.debug.{DebugModuleKey, RWNotify, SBCSFields, WNotifyVal} import freechips.rocketchip.diplomacy.TransferSizes import freechips.rocketchip.regmapper.{RegField, RegFieldDesc, RegFieldGroup, RegFieldWrType} import freechips.rocketchip.tilelink.{TLClientNode, TLMasterParameters, TLMasterPortParameters} -import freechips.rocketchip.util.property object SystemBusAccessState extends scala.Enumeration { type SystemBusAccessState = Value diff --git a/src/main/scala/devices/tilelink/CLINT.scala b/src/main/scala/devices/tilelink/CLINT.scala index dd67ab76de7..8050c1a633c 100644 --- a/src/main/scala/devices/tilelink/CLINT.scala +++ b/src/main/scala/devices/tilelink/CLINT.scala @@ -7,6 +7,7 @@ import chisel3.util._ import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy.lazymodule._ +import org.chipsalliance.rocketutils.Annotated import freechips.rocketchip.diplomacy.{AddressSet} import freechips.rocketchip.resources.{Resource, SimpleDevice} @@ -14,7 +15,6 @@ import freechips.rocketchip.interrupts.{IntNexusNode, IntSinkParameters, IntSink import freechips.rocketchip.regmapper.{RegField, RegFieldDesc, RegFieldGroup} import freechips.rocketchip.subsystem.{BaseSubsystem, CBUS, TLBusWrapperLocation} import freechips.rocketchip.tilelink.{TLFragmenter, TLRegisterNode} -import freechips.rocketchip.util.Annotated object CLINTConsts { diff --git a/src/main/scala/devices/tilelink/ClockBlocker.scala b/src/main/scala/devices/tilelink/ClockBlocker.scala index 6ee0f482288..b32c274f37e 100644 --- a/src/main/scala/devices/tilelink/ClockBlocker.scala +++ b/src/main/scala/devices/tilelink/ClockBlocker.scala @@ -5,13 +5,13 @@ package freechips.rocketchip.devices.tilelink import chisel3._ import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy.lazymodule._ +import org.chipsalliance.rocketutils.ClockGate import freechips.rocketchip.diplomacy.{AddressSet} import freechips.rocketchip.resources.{SimpleDevice} import freechips.rocketchip.prci.ClockAdapterNode import freechips.rocketchip.regmapper.{RegField, RegFieldDesc} import freechips.rocketchip.tilelink.TLRegisterNode -import freechips.rocketchip.util.ClockGate /** This device extends a basic bus blocker by allowing it to gate the clocks of the device * whose tilelink port is being blocked. For now it is only possible to block diff --git a/src/main/scala/devices/tilelink/MaskROM.scala b/src/main/scala/devices/tilelink/MaskROM.scala index 8a01ec5fd7b..80d100b8c06 100644 --- a/src/main/scala/devices/tilelink/MaskROM.scala +++ b/src/main/scala/devices/tilelink/MaskROM.scala @@ -7,14 +7,14 @@ import chisel3.util._ import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy.lazymodule._ +import org.chipsalliance.rocketutils.{ROMConfig, ROMGenerator} import freechips.rocketchip.diplomacy.{RegionType, AddressSet, TransferSizes} import freechips.rocketchip.resources.{SimpleDevice} import freechips.rocketchip.subsystem.{Attachable, HierarchicalLocation, TLBusWrapperLocation} import freechips.rocketchip.tilelink.{TLFragmenter, TLManagerNode, TLSlaveParameters, TLSlavePortParameters, TLWidthWidget} -import freechips.rocketchip.util.{ROMConfig, ROMGenerator} -import freechips.rocketchip.util.DataToAugmentedData +import org.chipsalliance.rocketutils.conversions.DataToAugmentedData case class MaskROMParams(address: BigInt, name: String, depth: Int = 2048, width: Int = 32) diff --git a/src/main/scala/devices/tilelink/PhysicalFilter.scala b/src/main/scala/devices/tilelink/PhysicalFilter.scala index 24570d19e99..7f58bfe5265 100644 --- a/src/main/scala/devices/tilelink/PhysicalFilter.scala +++ b/src/main/scala/devices/tilelink/PhysicalFilter.scala @@ -13,7 +13,7 @@ import freechips.rocketchip.resources.{SimpleDevice} import freechips.rocketchip.regmapper.{RegField, RegFieldDesc, RegFieldGroup, RegFieldWrType, RegReadFn, RegWriteFn} import freechips.rocketchip.tilelink.{TLAdapterNode, TLMessages, TLPermissions, TLRegisterNode} -import freechips.rocketchip.util.DataToAugmentedData +import org.chipsalliance.rocketutils.conversions.DataToAugmentedData case class DevicePMPParams(addressBits: Int, pageBits: Int) diff --git a/src/main/scala/devices/tilelink/Plic.scala b/src/main/scala/devices/tilelink/Plic.scala index d0a7b7f0178..72d233fe459 100644 --- a/src/main/scala/devices/tilelink/Plic.scala +++ b/src/main/scala/devices/tilelink/Plic.scala @@ -8,6 +8,7 @@ import chisel3.util._ import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy.lazymodule._ +import org.chipsalliance.rocketutils.{Annotated, MuxT, property} import freechips.rocketchip.diplomacy.{AddressSet} import freechips.rocketchip.resources.{Description, Resource, ResourceBinding, ResourceBindings, ResourceInt, SimpleDevice} @@ -15,12 +16,10 @@ import freechips.rocketchip.interrupts.{IntNexusNode, IntSinkParameters, IntSink import freechips.rocketchip.regmapper.{RegField, RegFieldDesc, RegFieldRdAction, RegFieldWrType, RegReadFn, RegWriteFn} import freechips.rocketchip.subsystem.{BaseSubsystem, CBUS, TLBusWrapperLocation} import freechips.rocketchip.tilelink.{TLFragmenter, TLRegisterNode} -import freechips.rocketchip.util.{Annotated, MuxT, property} import scala.math.min -import freechips.rocketchip.util.UIntToAugmentedUInt -import freechips.rocketchip.util.SeqToAugmentedSeq +import org.chipsalliance.rocketutils.conversions.{UIntToAugmentedUInt, SeqToAugmentedSeq} class GatewayPLICIO extends Bundle { val valid = Output(Bool()) diff --git a/src/main/scala/diplomacy/Main.scala b/src/main/scala/diplomacy/Main.scala index d14a542ea4c..cd3dac57dc6 100644 --- a/src/main/scala/diplomacy/Main.scala +++ b/src/main/scala/diplomacy/Main.scala @@ -5,8 +5,9 @@ import chisel3.stage.ChiselGeneratorAnnotation import chisel3.stage.phases.{Elaborate, Convert} import firrtl.AnnotationSeq import firrtl.options.TargetDirAnnotation -import freechips.rocketchip.diplomacy.LazyModule import org.chipsalliance.cde.config.{Config, Parameters} +import org.chipsalliance.diplomacy.lazymodule.LazyModule +import org.chipsalliance.rocketutils.ElaborationArtefacts import mainargs._ object Main { @@ -48,7 +49,7 @@ object Main { case a => Some(a) } os.write(os.Path(dir) / s"$topName.anno.json", firrtl.annotations.JsonProtocol.serialize(annos)) - freechips.rocketchip.util.ElaborationArtefacts.files.foreach{ case (ext, contents) => os.write.over(os.Path(dir) / s"${config.mkString("_")}.${ext}", contents()) } + ElaborationArtefacts.files.foreach{ case (ext, contents) => os.write.over(os.Path(dir) / s"${config.mkString("_")}.${ext}", contents()) } } def main(args: Array[String]): Unit = ParserForMethods(this).runOrExit(args) diff --git a/src/main/scala/diplomacy/Parameters.scala b/src/main/scala/diplomacy/Parameters.scala index ef28b918aa5..f02b12b51d3 100644 --- a/src/main/scala/diplomacy/Parameters.scala +++ b/src/main/scala/diplomacy/Parameters.scala @@ -4,7 +4,8 @@ package freechips.rocketchip.diplomacy import chisel3._ import chisel3.util.{DecoupledIO, Queue, ReadyValidIO, isPow2, log2Ceil, log2Floor} -import freechips.rocketchip.util.ShiftQueue + +import org.chipsalliance.rocketutils.ShiftQueue /** Options for describing the attributes of memory regions */ object RegionType { @@ -119,7 +120,7 @@ object TransferSizes { def mincover(seq: Seq[TransferSizes]) = seq.foldLeft(none)(_ mincover _) def intersect(seq: Seq[TransferSizes]) = seq.reduce(_ intersect _) - implicit def asBool(x: TransferSizes) = !x.none + implicit def asBool(x: TransferSizes): Boolean = !x.none } // AddressSets specify the address space managed by the manager diff --git a/src/main/scala/diplomacy/package.scala b/src/main/scala/diplomacy/package.scala index f6f0ed668a8..020e1967ae3 100644 --- a/src/main/scala/diplomacy/package.scala +++ b/src/main/scala/diplomacy/package.scala @@ -59,7 +59,7 @@ package object diplomacy { @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") def ValName(value: String) = _root_.org.chipsalliance.diplomacy.ValName(value) @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") - implicit def SourcecodeNameExt(x: sourcecode.Name) = _root_.org.chipsalliance.diplomacy.SourcecodeNameExt(x) + implicit def SourcecodeNameExt(x: sourcecode.Name): org.chipsalliance.diplomacy.SourcecodeNameExt = _root_.org.chipsalliance.diplomacy.SourcecodeNameExt(x) // LazyModule.scala @deprecated("Diplomacy has been split to a standalone library", "rocketchip 2.0.0") diff --git a/src/main/scala/groundtest/DummyPTW.scala b/src/main/scala/groundtest/DummyPTW.scala index 4dadd95a739..fd38256806e 100644 --- a/src/main/scala/groundtest/DummyPTW.scala +++ b/src/main/scala/groundtest/DummyPTW.scala @@ -7,9 +7,10 @@ import chisel3._ import chisel3.util._ import org.chipsalliance.cde.config._ +import org.chipsalliance.rocketutils.ParameterizedBundle + import freechips.rocketchip.rocket._ import freechips.rocketchip.tile.CoreModule -import freechips.rocketchip.util.ParameterizedBundle class DummyPTW(n: Int)(implicit p: Parameters) extends CoreModule()(p) { val io = IO(new Bundle { diff --git a/src/main/scala/groundtest/Status.scala b/src/main/scala/groundtest/Status.scala index c062845374a..5ed72aa605f 100644 --- a/src/main/scala/groundtest/Status.scala +++ b/src/main/scala/groundtest/Status.scala @@ -4,7 +4,8 @@ package freechips.rocketchip.groundtest import chisel3._ import chisel3.util._ -import freechips.rocketchip.util.ValidMux + +import org.chipsalliance.rocketutils.ValidMux class GroundTestStatus extends Bundle { val timeout = Valid(UInt(4.W)) diff --git a/src/main/scala/groundtest/TraceGen.scala b/src/main/scala/groundtest/TraceGen.scala index dfcb6cc426b..f0e440019bd 100644 --- a/src/main/scala/groundtest/TraceGen.scala +++ b/src/main/scala/groundtest/TraceGen.scala @@ -23,12 +23,12 @@ import chisel3._ import chisel3.util._ import org.chipsalliance.cde.config._ +import org.chipsalliance.rocketutils._ import freechips.rocketchip.rocket._ import freechips.rocketchip.tile._ import freechips.rocketchip.tilelink._ import freechips.rocketchip.subsystem.{HierarchicalElementCrossingParamsLike, CanAttachTile} -import freechips.rocketchip.util._ import freechips.rocketchip.prci.{ClockSinkParameters, ClockCrossingType} // ======= diff --git a/src/main/scala/interrupts/BlockDuringReset.scala b/src/main/scala/interrupts/BlockDuringReset.scala index a94c295b062..f88c69ddbfd 100644 --- a/src/main/scala/interrupts/BlockDuringReset.scala +++ b/src/main/scala/interrupts/BlockDuringReset.scala @@ -5,7 +5,7 @@ package freechips.rocketchip.interrupts import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy.lazymodule._ -import freechips.rocketchip.util.BlockDuringReset +import org.chipsalliance.rocketutils.BlockDuringReset /** BlockDuringReset ensures that no interrupt is raised while reset is raised. */ class IntBlockDuringReset(stretchResetCycles: Int = 0)(implicit p: Parameters) extends LazyModule diff --git a/src/main/scala/interrupts/Bundles.scala b/src/main/scala/interrupts/Bundles.scala index fd193f7d84b..e1f4974f5f4 100644 --- a/src/main/scala/interrupts/Bundles.scala +++ b/src/main/scala/interrupts/Bundles.scala @@ -3,7 +3,6 @@ package freechips.rocketchip.interrupts import chisel3._ -import freechips.rocketchip.util._ class SyncInterrupts(val params: IntEdge) extends Bundle { diff --git a/src/main/scala/interrupts/Crossing.scala b/src/main/scala/interrupts/Crossing.scala index 79260aa1c34..febfcf689b3 100644 --- a/src/main/scala/interrupts/Crossing.scala +++ b/src/main/scala/interrupts/Crossing.scala @@ -7,7 +7,7 @@ import chisel3.util._ import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy.lazymodule._ -import freechips.rocketchip.util.{SynchronizerShiftReg, AsyncResetReg} +import org.chipsalliance.rocketutils.{SynchronizerShiftReg, AsyncResetReg} @deprecated("IntXing does not ensure interrupt source is glitch free. Use IntSyncSource and IntSyncSink", "rocket-chip 1.2") class IntXing(sync: Int = 3)(implicit p: Parameters) extends LazyModule diff --git a/src/main/scala/interrupts/CrossingHelper.scala b/src/main/scala/interrupts/CrossingHelper.scala index d9cdd18b1ee..49b6f396e14 100644 --- a/src/main/scala/interrupts/CrossingHelper.scala +++ b/src/main/scala/interrupts/CrossingHelper.scala @@ -4,9 +4,9 @@ package freechips.rocketchip.interrupts import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy.lazymodule._ +import org.chipsalliance.rocketutils.CreditedDelay import freechips.rocketchip.prci.{ResetCrossingType, NoResetCrossing, StretchedResetCrossing, CrossingType, ClockCrossingType, NoCrossing, AsynchronousCrossing, RationalCrossing, SynchronousCrossing, CreditedCrossing} -import freechips.rocketchip.util.CreditedDelay trait IntOutwardCrossingHelper { type HelperCrossingType <: CrossingType diff --git a/src/main/scala/jtag/JtagShifter.scala b/src/main/scala/jtag/JtagShifter.scala index d76ac3535fb..34405e7c74c 100644 --- a/src/main/scala/jtag/JtagShifter.scala +++ b/src/main/scala/jtag/JtagShifter.scala @@ -8,7 +8,7 @@ import chisel3.internal.firrtl.KnownWidth import chisel3.util.{Cat, Valid} import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.util.property +import org.chipsalliance.rocketutils.property /** Base JTAG shifter IO, viewed from input to shift register chain. * Can be chained together. diff --git a/src/main/scala/jtag/JtagStateMachine.scala b/src/main/scala/jtag/JtagStateMachine.scala index 755b7cb66c2..a74dfc3c0bb 100644 --- a/src/main/scala/jtag/JtagStateMachine.scala +++ b/src/main/scala/jtag/JtagStateMachine.scala @@ -5,7 +5,7 @@ package freechips.rocketchip.jtag import chisel3._ import chisel3.util._ import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.util.property +import org.chipsalliance.rocketutils.property object JtagState { sealed abstract class State(val id: Int) { @@ -15,7 +15,7 @@ object JtagState { object State { import scala.language.implicitConversions - implicit def toInt(x: State) = x.id + implicit def toInt(x: State): Int = x.id implicit def toBigInt(x: State):BigInt = x.id // TODO: this could be automatically generated with macros and stuff diff --git a/src/main/scala/jtag/package.scala b/src/main/scala/jtag/package.scala index 8ceceae50fe..33c386e4cd6 100644 --- a/src/main/scala/jtag/package.scala +++ b/src/main/scala/jtag/package.scala @@ -11,5 +11,5 @@ package object jtag { * * This is limited to value types of Chain to limit application scope. */ - implicit def instructionIntKeyToBigInt[V <: Chain](x: (Int, V)) = (BigInt(x._1), x._2) + implicit def instructionIntKeyToBigInt[V <: Chain](x: (Int, V)): (scala.math.BigInt, V) = (BigInt(x._1), x._2) } diff --git a/src/main/scala/prci/BundleBridgeBlockDuringReset.scala b/src/main/scala/prci/BundleBridgeBlockDuringReset.scala index 7bb37f98ace..564d5bfd0b0 100644 --- a/src/main/scala/prci/BundleBridgeBlockDuringReset.scala +++ b/src/main/scala/prci/BundleBridgeBlockDuringReset.scala @@ -7,10 +7,9 @@ import chisel3._ import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy.bundlebridge._ import org.chipsalliance.diplomacy.lazymodule._ - import org.chipsalliance.diplomacy.bundlebridge.BundleBridgeNexus.fillN -import freechips.rocketchip.util.{BlockDuringReset, Blockable} +import org.chipsalliance.rocketutils.{Blockable, BlockDuringReset} object BundleBridgeBlockDuringReset { def apply[T <: Data : Blockable]( diff --git a/src/main/scala/prci/ClockBundles.scala b/src/main/scala/prci/ClockBundles.scala index 0cf06cca6e5..1ece27088b0 100644 --- a/src/main/scala/prci/ClockBundles.scala +++ b/src/main/scala/prci/ClockBundles.scala @@ -2,7 +2,7 @@ package freechips.rocketchip.prci import chisel3._ -import freechips.rocketchip.util.RecordMap +import org.chipsalliance.rocketutils.RecordMap class ClockBundle(val params: ClockBundleParameters = ClockBundleParameters()) extends Bundle diff --git a/src/main/scala/prci/ClockCrossingType.scala b/src/main/scala/prci/ClockCrossingType.scala index cbb5183a6db..aecb8dfa375 100644 --- a/src/main/scala/prci/ClockCrossingType.scala +++ b/src/main/scala/prci/ClockCrossingType.scala @@ -1,9 +1,11 @@ // See LICENSE.SiFive for license details. package freechips.rocketchip.prci + import org.chipsalliance.diplomacy.lazymodule.{LazyScope, LazyModule} +import org.chipsalliance.rocketutils.{RationalDirection, FastToSlow, AsyncQueueParams, CreditedDelay} + import freechips.rocketchip.diplomacy.{BufferParams} -import freechips.rocketchip.util.{RationalDirection, FastToSlow, AsyncQueueParams, CreditedDelay} trait CrossingType diff --git a/src/main/scala/prci/ClockDivider.scala b/src/main/scala/prci/ClockDivider.scala index 8c913f04c8c..b0ba9c3dce2 100644 --- a/src/main/scala/prci/ClockDivider.scala +++ b/src/main/scala/prci/ClockDivider.scala @@ -6,8 +6,7 @@ import chisel3.util._ import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy.lazymodule._ - -import freechips.rocketchip.util.{ClockDivider3, Pow2ClockDivider} +import org.chipsalliance.rocketutils.{ClockDivider3, Pow2ClockDivider} /* An example clock adapter that divides all clocks passed through this node by an integer factor */ diff --git a/src/main/scala/prci/ResetSynchronizer.scala b/src/main/scala/prci/ResetSynchronizer.scala index c66ce4576a7..2bd373dc597 100644 --- a/src/main/scala/prci/ResetSynchronizer.scala +++ b/src/main/scala/prci/ResetSynchronizer.scala @@ -4,8 +4,7 @@ package freechips.rocketchip.prci import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy._ import org.chipsalliance.diplomacy.lazymodule._ - -import freechips.rocketchip.util.ResetCatchAndSync +import org.chipsalliance.rocketutils.ResetCatchAndSync /** * Synchronizes the reset of a diplomatic clock-reset pair to its accompanying clock. diff --git a/src/main/scala/prci/ResetWrangler.scala b/src/main/scala/prci/ResetWrangler.scala index 59b289bc3e6..8a9b89d8897 100644 --- a/src/main/scala/prci/ResetWrangler.scala +++ b/src/main/scala/prci/ResetWrangler.scala @@ -5,8 +5,7 @@ import chisel3._ import chisel3.util._ import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy.lazymodule._ - -import freechips.rocketchip.util.{AsyncResetReg, ResetCatchAndSync} +import org.chipsalliance.rocketutils.{AsyncResetReg, ResetCatchAndSync} class ResetWrangler(debounceNs: Double = 100000)(implicit p: Parameters) extends LazyModule { diff --git a/src/main/scala/regmapper/DescribedReg.scala b/src/main/scala/regmapper/DescribedReg.scala index 13f12350ec6..14a42dcfbdb 100644 --- a/src/main/scala/regmapper/DescribedReg.scala +++ b/src/main/scala/regmapper/DescribedReg.scala @@ -2,7 +2,7 @@ package freechips.rocketchip.regmapper import chisel3._ -import freechips.rocketchip.util.{AsyncResetRegVec, SimpleRegIO} +import org.chipsalliance.rocketutils.{AsyncResetRegVec, SimpleRegIO} object DescribedReg { import freechips.rocketchip.regmapper.RegFieldAccessType._ diff --git a/src/main/scala/regmapper/RegField.scala b/src/main/scala/regmapper/RegField.scala index 1b7abfec234..a9118e19ab3 100644 --- a/src/main/scala/regmapper/RegField.scala +++ b/src/main/scala/regmapper/RegField.scala @@ -8,7 +8,7 @@ import chisel3.util.{DecoupledIO, ReadyValidIO} import org.json4s.JsonDSL._ import org.json4s.JsonAST.JValue -import freechips.rocketchip.util.{SimpleRegIO} +import org.chipsalliance.rocketutils.SimpleRegIO case class RegReadFn private(combinational: Boolean, fn: (Bool, Bool) => (Bool, Bool, UInt)) object RegReadFn @@ -18,7 +18,7 @@ object RegReadFn // all other combinational dependencies forbidden (e.g. ovalid <= ivalid) // effects must become visible on the cycle after ovalid && oready // data is only inspected when ovalid && oready - implicit def apply(x: (Bool, Bool) => (Bool, Bool, UInt)) = + implicit def apply(x: (Bool, Bool) => (Bool, Bool, UInt)): RegReadFn = new RegReadFn(false, x) implicit def apply(x: RegisterReadIO[UInt]): RegReadFn = RegReadFn((ivalid, oready) => { @@ -29,7 +29,7 @@ object RegReadFn // (ready: Bool) => (valid: Bool, data: UInt) // valid must not combinationally depend on ready // effects must become visible on the cycle after valid && ready - implicit def apply(x: Bool => (Bool, UInt)) = + implicit def apply(x: Bool => (Bool, UInt)): RegReadFn = new RegReadFn(true, { case (_, oready) => val (ovalid, data) = x(oready) (true.B, ovalid, data) @@ -50,7 +50,7 @@ object RegWriteFn // all other combinational dependencies forbidden (e.g. ovalid <= ivalid) // effects must become visible on the cycle after ovalid && oready // data should only be used for an effect when ivalid && iready - implicit def apply(x: (Bool, Bool, UInt) => (Bool, Bool)) = + implicit def apply(x: (Bool, Bool, UInt) => (Bool, Bool)): RegWriteFn = new RegWriteFn(false, x) implicit def apply(x: RegisterWriteIO[UInt]): RegWriteFn = RegWriteFn((ivalid, oready, data) => { @@ -62,7 +62,7 @@ object RegWriteFn // (valid: Bool, data: UInt) => (ready: Bool) // ready may combinationally depend on data (but not valid) // effects must become visible on the cycle after valid && ready - implicit def apply(x: (Bool, UInt) => Bool) = + implicit def apply(x: (Bool, UInt) => Bool): RegWriteFn = // combinational => data valid on oready new RegWriteFn(true, { case (_, oready, data) => (true.B, x(oready, data)) diff --git a/src/main/scala/regmapper/RegMapper.scala b/src/main/scala/regmapper/RegMapper.scala index b892cc866f6..6d7fb78213d 100644 --- a/src/main/scala/regmapper/RegMapper.scala +++ b/src/main/scala/regmapper/RegMapper.scala @@ -6,9 +6,9 @@ import chisel3._ import chisel3.experimental.SourceInfo import chisel3.util._ -import freechips.rocketchip.diplomacy.AddressDecoder +import org.chipsalliance.rocketutils.{BundleFieldBase, BundleMap, MuxSeq, ReduceOthers, property} -import freechips.rocketchip.util.{BundleFieldBase, BundleMap, MuxSeq, ReduceOthers, property} +import freechips.rocketchip.diplomacy.AddressDecoder // A bus agnostic register interface to a register-based device case class RegMapperParams(indexBits: Int, maskBits: Int, extraFields: Seq[BundleFieldBase] = Nil) diff --git a/src/main/scala/regmapper/RegisterCrossing.scala b/src/main/scala/regmapper/RegisterCrossing.scala index 37fce9ed40e..d75f5c6c1bf 100644 --- a/src/main/scala/regmapper/RegisterCrossing.scala +++ b/src/main/scala/regmapper/RegisterCrossing.scala @@ -5,7 +5,7 @@ package freechips.rocketchip.regmapper import chisel3._ import chisel3.util.{Decoupled, Irrevocable} -import freechips.rocketchip.util.{AsyncQueue,AsyncQueueParams,AsyncResetRegVec} +import org.chipsalliance.rocketutils.{AsyncQueue, AsyncQueueParams, AsyncResetRegVec} // A very simple flow control state machine, run in the specified clock domain class BusyRegisterCrossing extends Module { diff --git a/src/main/scala/regmapper/Test.scala b/src/main/scala/regmapper/Test.scala index 0faedd84cfb..2f9c42afbd6 100644 --- a/src/main/scala/regmapper/Test.scala +++ b/src/main/scala/regmapper/Test.scala @@ -8,7 +8,7 @@ import chisel3.util._ import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy.lazymodule._ -import freechips.rocketchip.util.Pow2ClockDivider +import org.chipsalliance.rocketutils.Pow2ClockDivider object LFSR16Seed { diff --git a/src/main/scala/resources/SRAM.scala b/src/main/scala/resources/SRAM.scala index 8fc3c16e0d8..9c681d29c7a 100644 --- a/src/main/scala/resources/SRAM.scala +++ b/src/main/scala/resources/SRAM.scala @@ -4,9 +4,12 @@ package freechips.rocketchip.resources import chisel3._ import chisel3.util.log2Ceil + import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.util.{DescribedSRAM, Code} -import freechips.rocketchip.diplomacy.{AddressSet, LazyModule} +import org.chipsalliance.diplomacy.lazymodule.LazyModule +import org.chipsalliance.rocketutils.{DescribedSRAM, Code} + +import freechips.rocketchip.diplomacy.AddressSet abstract class DiplomaticSRAM( val address: AddressSet, diff --git a/src/main/scala/rocket/BTB.scala b/src/main/scala/rocket/BTB.scala index 75126dd121b..ecb1eeb0cb4 100644 --- a/src/main/scala/rocket/BTB.scala +++ b/src/main/scala/rocket/BTB.scala @@ -5,10 +5,14 @@ package freechips.rocketchip.rocket import chisel3._ import chisel3.util._ + import org.chipsalliance.cde.config.Parameters +import org.chipsalliance.rocketutils.{Annotated, PopCountAtLeast, PseudoLRU} + import freechips.rocketchip.subsystem.CacheBlockBytes import freechips.rocketchip.tile.HasCoreParameters -import freechips.rocketchip.util._ + +import org.chipsalliance.rocketutils.conversions.{SeqToAugmentedSeq, IntToAugmentedInt} case class BHTParams( nEntries: Int = 512, diff --git a/src/main/scala/rocket/Breakpoint.scala b/src/main/scala/rocket/Breakpoint.scala index ea3b362d066..0233e44319e 100644 --- a/src/main/scala/rocket/Breakpoint.scala +++ b/src/main/scala/rocket/Breakpoint.scala @@ -3,10 +3,13 @@ package freechips.rocketchip.rocket import chisel3._ -import chisel3.util.{Cat} +import chisel3.util.Cat + import org.chipsalliance.cde.config.Parameters + import freechips.rocketchip.tile.{CoreBundle, HasCoreParameters} -import freechips.rocketchip.util._ + +import org.chipsalliance.rocketutils.conversions.SeqToAugmentedSeq class BPControl(implicit p: Parameters) extends CoreBundle()(p) { val ttype = UInt(4.W) diff --git a/src/main/scala/rocket/CSR.scala b/src/main/scala/rocket/CSR.scala index 1081c2de755..50880c9fe19 100644 --- a/src/main/scala/rocket/CSR.scala +++ b/src/main/scala/rocket/CSR.scala @@ -5,11 +5,14 @@ package freechips.rocketchip.rocket import chisel3._ import chisel3.util.{BitPat, Cat, Fill, Mux1H, PopCount, PriorityMux, RegEnable, UIntToOH, Valid, log2Ceil, log2Up} + import org.chipsalliance.cde.config.Parameters +import org.chipsalliance.rocketutils.{property, WideCounter} + import freechips.rocketchip.devices.debug.DebugModuleKey import freechips.rocketchip.tile._ -import freechips.rocketchip.util._ -import freechips.rocketchip.util.property + +import org.chipsalliance.rocketutils.conversions.{BooleanToAugmentedBoolean, SeqToAugmentedSeq, IntToAugmentedInt, UIntToAugmentedUInt, UIntIsOneOf, wcToUInt} import scala.collection.mutable.LinkedHashMap import Instructions._ diff --git a/src/main/scala/rocket/Consts.scala b/src/main/scala/rocket/Consts.scala index 66e45f733ba..81b579ff3d1 100644 --- a/src/main/scala/rocket/Consts.scala +++ b/src/main/scala/rocket/Consts.scala @@ -4,7 +4,8 @@ package freechips.rocketchip.rocket.constants import chisel3._ import chisel3.util._ -import freechips.rocketchip.util._ + +import org.chipsalliance.rocketutils.conversions.UIntIsOneOf trait ScalarOpConstants { val SZ_BR = 3 diff --git a/src/main/scala/rocket/DCache.scala b/src/main/scala/rocket/DCache.scala index 842ad05fb68..11f108f7636 100644 --- a/src/main/scala/rocket/DCache.scala +++ b/src/main/scala/rocket/DCache.scala @@ -7,6 +7,7 @@ import chisel3.util._ import chisel3.experimental.SourceInfo import org.chipsalliance.cde.config._ +import org.chipsalliance.rocketutils.{CanHaveErrors, ClockGate, IdentityCode, ReplacementPolicy, DescribedSRAM, property} import freechips.rocketchip.amba.AMBAProt import freechips.rocketchip.diplomacy.{BufferParams} @@ -14,14 +15,10 @@ import freechips.rocketchip.prci.{ClockCrossingType, RationalCrossing, Synchrono import freechips.rocketchip.tile.{CoreBundle, LookupByHartId} import freechips.rocketchip.tilelink.{TLFIFOFixer,ClientMetadata, TLBundleA, TLAtomics, TLBundleB, TLPermissions} import freechips.rocketchip.tilelink.TLMessages.{AccessAck, HintAck, AccessAckData, Grant, GrantData, ReleaseAck} -import freechips.rocketchip.util.{CanHaveErrors, ClockGate, IdentityCode, ReplacementPolicy, DescribedSRAM, property} - -import freechips.rocketchip.util.BooleanToAugmentedBoolean -import freechips.rocketchip.util.UIntToAugmentedUInt -import freechips.rocketchip.util.UIntIsOneOf -import freechips.rocketchip.util.IntToAugmentedInt -import freechips.rocketchip.util.SeqToAugmentedSeq -import freechips.rocketchip.util.SeqBoolBitwiseOps + +import org.chipsalliance.rocketutils.conversions.{ + BooleanToAugmentedBoolean, UIntToAugmentedUInt, UIntIsOneOf, + IntToAugmentedInt, SeqToAugmentedSeq, SeqBoolBitwiseOps} // TODO: delete this trait once deduplication is smart enough to avoid globally inlining matching circuits trait InlineInstance { self: chisel3.experimental.BaseModule => diff --git a/src/main/scala/rocket/DebugROB.scala b/src/main/scala/rocket/DebugROB.scala index 39dec03a78c..c59c5d6fc3e 100644 --- a/src/main/scala/rocket/DebugROB.scala +++ b/src/main/scala/rocket/DebugROB.scala @@ -5,10 +5,12 @@ package freechips.rocketchip.rocket import chisel3._ import chisel3.util._ -import chisel3.experimental.{IntParam} -import org.chipsalliance.cde.config.{Parameters} -import freechips.rocketchip.tile.{HasCoreParameters} -import freechips.rocketchip.util.DecoupledHelper +import chisel3.experimental.IntParam + +import org.chipsalliance.cde.config.Parameters +import org.chipsalliance.rocketutils.DecoupledHelper + +import freechips.rocketchip.tile.HasCoreParameters case class DebugROBParams(size: Int) diff --git a/src/main/scala/rocket/Events.scala b/src/main/scala/rocket/Events.scala index a3504ff497b..d4c77b6a717 100644 --- a/src/main/scala/rocket/Events.scala +++ b/src/main/scala/rocket/Events.scala @@ -5,8 +5,10 @@ package freechips.rocketchip.rocket import chisel3._ import chisel3.util.log2Ceil -import freechips.rocketchip.util._ -import freechips.rocketchip.util.property + +import org.chipsalliance.rocketutils.property + +import org.chipsalliance.rocketutils.conversions.SeqToAugmentedSeq class EventSet(val gate: (UInt, UInt) => Bool, val events: Seq[(String, () => Bool)]) { def size = events.size diff --git a/src/main/scala/rocket/Frontend.scala b/src/main/scala/rocket/Frontend.scala index 8156e51c475..f73dbecfd30 100644 --- a/src/main/scala/rocket/Frontend.scala +++ b/src/main/scala/rocket/Frontend.scala @@ -10,12 +10,12 @@ import chisel3.experimental.SourceInfo import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy.bundlebridge._ import org.chipsalliance.diplomacy.lazymodule._ +import org.chipsalliance.rocketutils.{ClockGate, ShiftQueue, property} import freechips.rocketchip.tile.{CoreBundle, BaseTile} import freechips.rocketchip.tilelink.{TLWidthWidget, TLEdgeOut} -import freechips.rocketchip.util.{ClockGate, ShiftQueue, property} -import freechips.rocketchip.util.UIntToAugmentedUInt +import org.chipsalliance.rocketutils.conversions.UIntToAugmentedUInt class FrontendReq(implicit p: Parameters) extends CoreBundle()(p) { val pc = UInt(vaddrBitsExtended.W) diff --git a/src/main/scala/rocket/HellaCache.scala b/src/main/scala/rocket/HellaCache.scala index 29333c13fa3..ae113ca7597 100644 --- a/src/main/scala/rocket/HellaCache.scala +++ b/src/main/scala/rocket/HellaCache.scala @@ -9,14 +9,14 @@ import chisel3.util._ import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy.bundlebridge._ import org.chipsalliance.diplomacy.lazymodule._ +import org.chipsalliance.rocketutils.{Code, RandomReplacement, ParameterizedBundle} import freechips.rocketchip.amba.AMBAProtField import freechips.rocketchip.diplomacy.{IdRange, TransferSizes, RegionType} import freechips.rocketchip.tile.{L1CacheParams, HasL1CacheParameters, HasCoreParameters, CoreBundle, HasNonDiplomaticTileParameters, BaseTile, HasTileParameters} import freechips.rocketchip.tilelink.{TLMasterParameters, TLClientNode, TLMasterPortParameters, TLEdgeOut, TLWidthWidget, TLFIFOFixer, ClientMetadata} -import freechips.rocketchip.util.{Code, RandomReplacement, ParameterizedBundle} -import freechips.rocketchip.util.{BooleanToAugmentedBoolean, IntToAugmentedInt} +import org.chipsalliance.rocketutils.conversions.{BooleanToAugmentedBoolean, IntToAugmentedInt} import scala.collection.mutable.ListBuffer diff --git a/src/main/scala/rocket/IBuf.scala b/src/main/scala/rocket/IBuf.scala index c0a383d79ca..c6705872c24 100644 --- a/src/main/scala/rocket/IBuf.scala +++ b/src/main/scala/rocket/IBuf.scala @@ -3,10 +3,14 @@ package freechips.rocketchip.rocket import chisel3._ -import chisel3.util.{Decoupled,log2Ceil,Cat,UIntToOH,Fill} +import chisel3.util._ + import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.tile._ -import freechips.rocketchip.util._ +import org.chipsalliance.rocketutils.ParameterizedBundle + +import freechips.rocketchip.tile.{CoreModule, HasCoreParameters} + +import org.chipsalliance.rocketutils.conversions.{SeqToAugmentedSeq, UIntToAugmentedUInt} class Instruction(implicit val p: Parameters) extends ParameterizedBundle with HasCoreParameters { val xcpt0 = new FrontendExceptions // exceptions on first half of instruction diff --git a/src/main/scala/rocket/ICache.scala b/src/main/scala/rocket/ICache.scala index 86129bd5ae4..7a7fc53003f 100644 --- a/src/main/scala/rocket/ICache.scala +++ b/src/main/scala/rocket/ICache.scala @@ -11,18 +11,15 @@ import chisel3.experimental.SourceInfo import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy.bundlebridge._ import org.chipsalliance.diplomacy.lazymodule._ +import org.chipsalliance.rocketutils.{Code, CanHaveErrors, DescribedSRAM, RandomReplacement, Split, IdentityCode, property} import freechips.rocketchip.amba.{AMBAProt, AMBAProtField} import freechips.rocketchip.diplomacy.{IdRange, AddressSet, RegionType, TransferSizes} import freechips.rocketchip.resources.{SimpleDevice, ResourceBindings, Binding, ResourceAddress, Description, ResourceString, ResourceValue} import freechips.rocketchip.tile.{L1CacheParams, HasL1CacheParameters, HasCoreParameters, CoreBundle, TileKey, LookupByHartId} import freechips.rocketchip.tilelink.{TLClientNode, TLMasterPortParameters, TLManagerNode, TLSlavePortParameters, TLSlaveParameters, TLMasterParameters, TLHints} -import freechips.rocketchip.util.{Code, CanHaveErrors, DescribedSRAM, RandomReplacement, Split, IdentityCode, property} -import freechips.rocketchip.util.BooleanToAugmentedBoolean -import freechips.rocketchip.util.UIntToAugmentedUInt -import freechips.rocketchip.util.SeqToAugmentedSeq -import freechips.rocketchip.util.OptionUIntToAugmentedOptionUInt +import org.chipsalliance.rocketutils.conversions.{BooleanToAugmentedBoolean, UIntToAugmentedUInt, SeqToAugmentedSeq, OptionUIntToAugmentedOptionUInt} /** Parameter of [[ICache]]. * @@ -33,8 +30,8 @@ import freechips.rocketchip.util.OptionUIntToAugmentedOptionUInt * @param nTLBWays TLB ways * @param nTLBBasePageSectors TLB BasePageSectors * @param nTLBSuperpages TLB Superpages - * @param tagECC tag ECC, will be parsed to [[freechips.rocketchip.util.Code]]. - * @param dataECC data ECC, will be parsed to [[freechips.rocketchip.util.Code]]. + * @param tagECC tag ECC, will be parsed to [[org.chipsalliance.rocketutils.Code]]. + * @param dataECC data ECC, will be parsed to [[org.chipsalliance.rocketutils.Code]]. * @param itimAddr optional base ITIM address, * if None, ITIM won't be generated, * if Some, ITIM will be generated, with itimAddr as ITIM base address. diff --git a/src/main/scala/rocket/IDecode.scala b/src/main/scala/rocket/IDecode.scala index 7c3aea6ecb6..60a91cc07c4 100644 --- a/src/main/scala/rocket/IDecode.scala +++ b/src/main/scala/rocket/IDecode.scala @@ -6,9 +6,11 @@ package freechips.rocketchip.rocket import chisel3._ import chisel3.util._ import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.util._ -import Instructions._ -import CustomInstructions._ + +import freechips.rocketchip.rocket.Instructions._ +import freechips.rocketchip.rocket.CustomInstructions._ + +import org.chipsalliance.rocketutils.conversions.{uintToBitPat} abstract trait DecodeConstants { diff --git a/src/main/scala/rocket/Multiplier.scala b/src/main/scala/rocket/Multiplier.scala index 741d61389a6..4cef844a863 100644 --- a/src/main/scala/rocket/Multiplier.scala +++ b/src/main/scala/rocket/Multiplier.scala @@ -4,8 +4,11 @@ package freechips.rocketchip.rocket import chisel3._ -import chisel3.util.{Cat, log2Up, log2Ceil, log2Floor, Log2, Decoupled, Enum, Fill, Valid, Pipe} -import freechips.rocketchip.util._ +import chisel3.util._ + +import org.chipsalliance.rocketutils.ShouldBeRetimed + +import org.chipsalliance.rocketutils.conversions.{BooleanToAugmentedBoolean, UIntToAugmentedUInt} class MultiplierReq(dataBits: Int, tagBits: Int, aluFn: ALUFN = new ALUFN) extends Bundle { val fn = Bits(aluFn.SZ_ALU_FN.W) diff --git a/src/main/scala/rocket/NBDcache.scala b/src/main/scala/rocket/NBDcache.scala index a0f9f72b91b..c127d01ee0e 100644 --- a/src/main/scala/rocket/NBDcache.scala +++ b/src/main/scala/rocket/NBDcache.scala @@ -6,9 +6,13 @@ package freechips.rocketchip.rocket import chisel3._ import chisel3.util._ import chisel3.experimental.dataview._ + import org.chipsalliance.cde.config.Parameters +import org.chipsalliance.rocketutils.{DescribedSRAM, IdentityCode} + import freechips.rocketchip.tilelink._ -import freechips.rocketchip.util._ + +import org.chipsalliance.rocketutils.conversions.{UIntIsOneOf, SeqToAugmentedSeq, SeqBoolBitwiseOps, UIntToAugmentedUInt} trait HasMissInfo extends Bundle with HasL1HellaCacheParameters { val tag_match = Bool() diff --git a/src/main/scala/rocket/PMP.scala b/src/main/scala/rocket/PMP.scala index 11fe95d9e0b..e4303f80476 100644 --- a/src/main/scala/rocket/PMP.scala +++ b/src/main/scala/rocket/PMP.scala @@ -4,9 +4,12 @@ package freechips.rocketchip.rocket import chisel3._ import chisel3.util.{Cat, log2Ceil} -import org.chipsalliance.cde.config._ -import freechips.rocketchip.tile._ -import freechips.rocketchip.util._ +import org.chipsalliance.cde.config.Parameters +import org.chipsalliance.rocketutils.property + +import freechips.rocketchip.tile.{CoreBundle, HasCoreParameters} + +import org.chipsalliance.rocketutils.conversions.{IntToAugmentedInt, UIntToOH1, SeqToAugmentedSeq} class PMPConfig extends Bundle { val l = Bool() diff --git a/src/main/scala/rocket/PTW.scala b/src/main/scala/rocket/PTW.scala index a4262843f99..9c992120fd9 100644 --- a/src/main/scala/rocket/PTW.scala +++ b/src/main/scala/rocket/PTW.scala @@ -3,19 +3,21 @@ package freechips.rocketchip.rocket -import chisel3._ -import chisel3.util.{Arbiter, Cat, Decoupled, Enum, Mux1H, OHToUInt, PopCount, PriorityEncoder, PriorityEncoderOH, RegEnable, UIntToOH, Valid, is, isPow2, log2Ceil, switch} -import chisel3.withClock +import chisel3.{withClock, _} +import chisel3.util._ import chisel3.experimental.SourceInfo + import org.chipsalliance.cde.config.Parameters +import org.chipsalliance.rocketutils.{ClockGate, DescribedSRAM, ParityCode, PseudoLRU, SetAssocLRU, Split, property} + import freechips.rocketchip.subsystem.CacheBlockBytes -import freechips.rocketchip.tile._ +import freechips.rocketchip.tile.{BaseTile, CoreBundle, CoreModule, HasCoreParameters, HasTileParameters} import freechips.rocketchip.tilelink._ -import freechips.rocketchip.util._ -import freechips.rocketchip.util.property import scala.collection.mutable.ListBuffer +import org.chipsalliance.rocketutils.conversions.{BooleanToAugmentedBoolean, SeqBoolBitwiseOps, IntToAugmentedInt, OptimizationBarrier, SeqToAugmentedSeq, UIntToAugmentedUInt} + /** PTE request from TLB to PTW * * TLB send a PTE request to PTW when L1TLB miss diff --git a/src/main/scala/rocket/RVC.scala b/src/main/scala/rocket/RVC.scala index 71ac35ee480..0d4ed3e9e40 100644 --- a/src/main/scala/rocket/RVC.scala +++ b/src/main/scala/rocket/RVC.scala @@ -4,9 +4,12 @@ package freechips.rocketchip.rocket import chisel3._ import chisel3.util._ + import org.chipsalliance.cde.config.Parameters + import freechips.rocketchip.tile._ -import freechips.rocketchip.util._ + +import org.chipsalliance.rocketutils.conversions.SeqToAugmentedSeq class ExpandedInstruction extends Bundle { val bits = UInt(32.W) diff --git a/src/main/scala/rocket/RocketCore.scala b/src/main/scala/rocket/RocketCore.scala index 2e96155cca7..c88704b7917 100644 --- a/src/main/scala/rocket/RocketCore.scala +++ b/src/main/scala/rocket/RocketCore.scala @@ -6,12 +6,18 @@ package freechips.rocketchip.rocket import chisel3._ import chisel3.util._ import chisel3.withClock + import org.chipsalliance.cde.config.Parameters +import org.chipsalliance.rocketutils.{PlusArg, CoreMonitorBundle} + import freechips.rocketchip.tile._ -import freechips.rocketchip.util._ -import freechips.rocketchip.util.property + +import org.chipsalliance.rocketutils.{ClockGate, property} + import scala.collection.mutable.ArrayBuffer +import org.chipsalliance.rocketutils.conversions.{BooleanToAugmentedBoolean, UIntToAugmentedUInt, UIntIsOneOf, SeqBoolBitwiseOps, SeqToAugmentedSeq} + case class RocketCoreParams( bootFreqHz: BigInt = 0, useVM: Boolean = true, diff --git a/src/main/scala/rocket/ScratchpadSlavePort.scala b/src/main/scala/rocket/ScratchpadSlavePort.scala index 8b613aa09de..e8ef82e7594 100644 --- a/src/main/scala/rocket/ScratchpadSlavePort.scala +++ b/src/main/scala/rocket/ScratchpadSlavePort.scala @@ -13,8 +13,7 @@ import freechips.rocketchip.resources.{SimpleDevice} import freechips.rocketchip.tilelink.{TLManagerNode, TLSlavePortParameters, TLSlaveParameters, TLBundleA, TLMessages, TLAtomics} -import freechips.rocketchip.util.UIntIsOneOf -import freechips.rocketchip.util.DataToAugmentedData +import org.chipsalliance.rocketutils.conversions.{UIntIsOneOf, DataToAugmentedData} /* This adapter converts between diplomatic TileLink and non-diplomatic HellaCacheIO */ class ScratchpadSlavePort(address: Seq[AddressSet], coreDataBytes: Int, usingAtomics: Boolean)(implicit p: Parameters) extends LazyModule { diff --git a/src/main/scala/rocket/SimpleHellaCacheIF.scala b/src/main/scala/rocket/SimpleHellaCacheIF.scala index a722770a434..71943ea3888 100644 --- a/src/main/scala/rocket/SimpleHellaCacheIF.scala +++ b/src/main/scala/rocket/SimpleHellaCacheIF.scala @@ -4,10 +4,10 @@ package freechips.rocketchip.rocket import chisel3._ -import chisel3.util.{Valid,Decoupled,Queue,log2Up,OHToUInt,UIntToOH,PriorityEncoderOH,Arbiter,RegEnable,Cat} +import chisel3.util._ import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.util._ +import org.chipsalliance.rocketutils.DecoupledHelper /** * This module buffers requests made by the SimpleHellaCacheIF in case they diff --git a/src/main/scala/rocket/TLB.scala b/src/main/scala/rocket/TLB.scala index 6f78db43cb7..283cac9bb5f 100644 --- a/src/main/scala/rocket/TLB.scala +++ b/src/main/scala/rocket/TLB.scala @@ -8,20 +8,17 @@ import chisel3.util._ import chisel3.experimental.SourceInfo import org.chipsalliance.cde.config._ +import org.chipsalliance.rocketutils.{SetAssocLRU, PseudoLRU, PopCountAtLeast, property} import freechips.rocketchip.devices.debug.DebugModuleKey import freechips.rocketchip.diplomacy.RegionType import freechips.rocketchip.subsystem.CacheBlockBytes import freechips.rocketchip.tile.{CoreModule, CoreBundle} import freechips.rocketchip.tilelink._ -import freechips.rocketchip.util.{OptimizationBarrier, SetAssocLRU, PseudoLRU, PopCountAtLeast, property} - -import freechips.rocketchip.util.BooleanToAugmentedBoolean -import freechips.rocketchip.util.IntToAugmentedInt -import freechips.rocketchip.util.UIntToAugmentedUInt -import freechips.rocketchip.util.UIntIsOneOf -import freechips.rocketchip.util.SeqToAugmentedSeq -import freechips.rocketchip.util.SeqBoolBitwiseOps + +import org.chipsalliance.rocketutils.conversions.{ + BooleanToAugmentedBoolean, IntToAugmentedInt, UIntToAugmentedUInt, + UIntIsOneOf, SeqToAugmentedSeq, SeqBoolBitwiseOps, OptimizationBarrier} case object PgLevels extends Field[Int](2) case object ASIdBits extends Field[Int](0) diff --git a/src/main/scala/subsystem/Attachable.scala b/src/main/scala/subsystem/Attachable.scala index 9f3f720a04a..9dd8876382c 100644 --- a/src/main/scala/subsystem/Attachable.scala +++ b/src/main/scala/subsystem/Attachable.scala @@ -4,10 +4,10 @@ package freechips.rocketchip.subsystem import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy.lazymodule._ +import org.chipsalliance.rocketutils.{Location, LocationMap} import freechips.rocketchip.prci.ClockGroupNode import freechips.rocketchip.tilelink.TLBusWrapper -import freechips.rocketchip.util.{Location, LocationMap} /** These traits are intended to make it possible to configure to which * buses optional devices are attached, even after a subsystem has been instantiated. diff --git a/src/main/scala/subsystem/BankedCoherenceParams.scala b/src/main/scala/subsystem/BankedCoherenceParams.scala index 235cd1eebbd..2ed4163f775 100644 --- a/src/main/scala/subsystem/BankedCoherenceParams.scala +++ b/src/main/scala/subsystem/BankedCoherenceParams.scala @@ -6,6 +6,7 @@ import chisel3.util._ import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy.lazymodule._ +import org.chipsalliance.rocketutils.Location import freechips.rocketchip.devices.tilelink.BuiltInDevices import freechips.rocketchip.diplomacy.AddressSet @@ -15,7 +16,6 @@ import freechips.rocketchip.tilelink.{ TLJbar, TLEdge, TLOutwardNode, TLTempNode, TLInwardNode, BankBinder, TLBroadcastParams, TLBroadcastControlParams, TLBuffer, TLFragmenter, TLNameNode } -import freechips.rocketchip.util.Location import CoherenceManagerWrapper._ diff --git a/src/main/scala/subsystem/BaseSubsystem.scala b/src/main/scala/subsystem/BaseSubsystem.scala index e5aaa6242aa..d4600bfe5fe 100644 --- a/src/main/scala/subsystem/BaseSubsystem.scala +++ b/src/main/scala/subsystem/BaseSubsystem.scala @@ -7,15 +7,17 @@ import chisel3.util._ import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy.lazymodule._ +import org.chipsalliance.rocketutils.{Location, ElaborationArtefacts, PlusArgArtefacts} -import freechips.rocketchip.diplomacy.{AddressRange} +import freechips.rocketchip.diplomacy.AddressRange import freechips.rocketchip.resources.{ BindingScope, DTS, DTB, ResourceBinding, JSON, ResourceInt, DTSModel, DTSCompat, DTSTimebase, ResourceString, Resource, ResourceAnchors, AddressMapEntry} import freechips.rocketchip.prci.{ClockGroupIdentityNode, ClockGroupAggregator, ClockGroupSourceNode, ClockGroupSourceParameters} import freechips.rocketchip.tilelink.TLBusWrapper -import freechips.rocketchip.util.{Location, ElaborationArtefacts, PlusArgArtefacts, RecordMap, Annotated} + +import freechips.rocketchip.util.{Annotated, RecordMap} case object SubsystemDriveClockGroupsFromIO extends Field[Boolean](true) case class TLNetworkTopologyLocated(where: HierarchicalLocation) extends Field[Seq[CanInstantiateWithinContextThatHasTileLinkLocations with CanConnectWithinContextThatHasTileLinkLocations]] diff --git a/src/main/scala/subsystem/BusTopology.scala b/src/main/scala/subsystem/BusTopology.scala index 5b3dd7c452a..1e5f480d248 100644 --- a/src/main/scala/subsystem/BusTopology.scala +++ b/src/main/scala/subsystem/BusTopology.scala @@ -7,7 +7,8 @@ import org.chipsalliance.diplomacy.nodes._ import freechips.rocketchip.prci.{ClockCrossingType, NoCrossing, SynchronousCrossing} import freechips.rocketchip.tilelink.{TLBusWrapper, TLBusWrapperTopology, TLBusWrapperConnection} -import freechips.rocketchip.util.Location + +import org.chipsalliance.rocketutils.Location // These fields control parameters of the five traditional tilelink bus wrappers. // They continue to exist for backwards compatiblity reasons but could eventually be retired. diff --git a/src/main/scala/subsystem/Cluster.scala b/src/main/scala/subsystem/Cluster.scala index 9d82ad616ca..825185216c4 100644 --- a/src/main/scala/subsystem/Cluster.scala +++ b/src/main/scala/subsystem/Cluster.scala @@ -4,16 +4,18 @@ import chisel3._ import chisel3.util._ import org.chipsalliance.cde.config._ +import org.chipsalliance.diplomacy.FlipRendering import org.chipsalliance.diplomacy.bundlebridge._ import org.chipsalliance.diplomacy.lazymodule._ +import org.chipsalliance.rocketutils.TraceCoreInterface -import freechips.rocketchip.devices.debug.{TLDebugModule} -import freechips.rocketchip.diplomacy.{FlipRendering} +import freechips.rocketchip.devices.debug.TLDebugModule import freechips.rocketchip.interrupts.{IntIdentityNode, IntSyncIdentityNode, NullIntSource} import freechips.rocketchip.prci.{ClockCrossingType, NoCrossing, ClockSinkParameters, ClockGroupIdentityNode, BundleBridgeBlockDuringReset} import freechips.rocketchip.tile.{RocketTile, NMI, TraceBundle} import freechips.rocketchip.tilelink.TLWidthWidget -import freechips.rocketchip.util.TraceCoreInterface + +import freechips.rocketchip.util.BlockableTrace.BlockableTraceBundle import scala.collection.immutable.SortedMap diff --git a/src/main/scala/subsystem/Configs.scala b/src/main/scala/subsystem/Configs.scala index c3d11aca16e..8f04b716ace 100644 --- a/src/main/scala/subsystem/Configs.scala +++ b/src/main/scala/subsystem/Configs.scala @@ -7,6 +7,7 @@ import chisel3.util._ import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy.lazymodule._ +import org.chipsalliance.rocketutils.ClockGateModelFile import freechips.rocketchip.devices.debug.{DebugModuleKey, DefaultDebugModuleParams, ExportDebug, JTAG, APB} import freechips.rocketchip.devices.tilelink.{ @@ -23,7 +24,6 @@ import freechips.rocketchip.rocket.{PgLevels, RocketCoreParams, MulDivParams, DC import freechips.rocketchip.tile.{ XLen, MaxHartIdBits, RocketTileParams, BuildRoCC, AccumulatorExample, OpcodeSet, TranslatorExample, CharacterCountExample, BlackBoxExample } -import freechips.rocketchip.util.ClockGateModelFile class BaseSubsystemConfig extends Config ((site, here, up) => { // Tile parameters diff --git a/src/main/scala/subsystem/FrontBus.scala b/src/main/scala/subsystem/FrontBus.scala index e968246a130..ea37cea61b9 100644 --- a/src/main/scala/subsystem/FrontBus.scala +++ b/src/main/scala/subsystem/FrontBus.scala @@ -4,10 +4,10 @@ package freechips.rocketchip.subsystem import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy.lazymodule._ +import org.chipsalliance.rocketutils.Location import freechips.rocketchip.devices.tilelink.{BuiltInErrorDeviceParams, BuiltInZeroDeviceParams, BuiltInDevices, HasBuiltInDeviceParams} import freechips.rocketchip.tilelink.{HasTLBusParams, TLBusWrapper, TLBusWrapperInstantiationLike, HasTLXbarPhy} -import freechips.rocketchip.util.{Location} case class FrontBusParams( beatBytes: Int, diff --git a/src/main/scala/subsystem/HasHierarchicalElements.scala b/src/main/scala/subsystem/HasHierarchicalElements.scala index d026395a417..74a14baf530 100644 --- a/src/main/scala/subsystem/HasHierarchicalElements.scala +++ b/src/main/scala/subsystem/HasHierarchicalElements.scala @@ -7,6 +7,7 @@ import chisel3._ import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy.bundlebridge._ import org.chipsalliance.diplomacy.lazymodule._ +import org.chipsalliance.rocketutils.TraceCoreInterface import freechips.rocketchip.devices.debug.{TLDebugModule, HasPeripheryDebug} import freechips.rocketchip.devices.tilelink.{BasicBusBlocker, BasicBusBlockerParams, CLINT, TLPLIC, CLINTConsts} @@ -18,7 +19,6 @@ import freechips.rocketchip.tile.{TileParams, TilePRCIDomain, BaseTile, NMI, Tra import freechips.rocketchip.tilelink.{TLNode, TLBuffer, TLCacheCork, TLTempNode, TLFragmenter} import freechips.rocketchip.prci.{ClockCrossingType, ClockGroup, ResetCrossingType, ClockGroupNode, ClockDomain} import freechips.rocketchip.rocket.TracedInstruction -import freechips.rocketchip.util.TraceCoreInterface import scala.collection.immutable.SortedMap diff --git a/src/main/scala/subsystem/HasTiles.scala b/src/main/scala/subsystem/HasTiles.scala index ea1f34f7e7b..b5c83596940 100644 --- a/src/main/scala/subsystem/HasTiles.scala +++ b/src/main/scala/subsystem/HasTiles.scala @@ -7,6 +7,7 @@ import chisel3._ import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy.bundlebridge._ import org.chipsalliance.diplomacy.lazymodule._ +import org.chipsalliance.rocketutils.TraceCoreInterface import freechips.rocketchip.devices.debug.TLDebugModule import freechips.rocketchip.diplomacy.{DisableMonitors, FlipRendering} @@ -15,7 +16,8 @@ import freechips.rocketchip.tile.{MaxHartIdBits, BaseTile, InstantiableTileParam import freechips.rocketchip.tilelink.TLWidthWidget import freechips.rocketchip.prci.{ClockGroup, BundleBridgeBlockDuringReset, NoCrossing, SynchronousCrossing, CreditedCrossing, RationalCrossing, AsynchronousCrossing} import freechips.rocketchip.rocket.TracedInstruction -import freechips.rocketchip.util.TraceCoreInterface + +import freechips.rocketchip.util.BlockableTrace.BlockableTraceBundle import scala.collection.immutable.SortedMap diff --git a/src/main/scala/subsystem/HierarchicalElementPRCIDomain.scala b/src/main/scala/subsystem/HierarchicalElementPRCIDomain.scala index b38f208701e..a2215b316b8 100644 --- a/src/main/scala/subsystem/HierarchicalElementPRCIDomain.scala +++ b/src/main/scala/subsystem/HierarchicalElementPRCIDomain.scala @@ -5,6 +5,7 @@ import chisel3.util._ import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy.lazymodule._ +import org.chipsalliance.rocketutils.TraceCoreInterface import freechips.rocketchip.devices.debug.TLDebugModule import freechips.rocketchip.diplomacy.{DisableMonitors, FlipRendering} @@ -12,7 +13,6 @@ import freechips.rocketchip.interrupts.{IntInwardNode, IntOutwardNode} import freechips.rocketchip.prci.{ClockCrossingType, ResetCrossingType, ResetDomain, ClockSinkNode, ClockSinkParameters, ClockIdentityNode, FixedClockBroadcast, ClockDomain} import freechips.rocketchip.tile.{RocketTile, TraceBundle} import freechips.rocketchip.tilelink.{TLInwardNode, TLOutwardNode} -import freechips.rocketchip.util.TraceCoreInterface import freechips.rocketchip.tilelink.TLClockDomainCrossing import freechips.rocketchip.tilelink.TLResetDomainCrossing diff --git a/src/main/scala/subsystem/MemoryBus.scala b/src/main/scala/subsystem/MemoryBus.scala index b8b4e9919a4..141f381c002 100644 --- a/src/main/scala/subsystem/MemoryBus.scala +++ b/src/main/scala/subsystem/MemoryBus.scala @@ -4,6 +4,7 @@ package freechips.rocketchip.subsystem import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy.lazymodule._ +import org.chipsalliance.rocketutils.Location import freechips.rocketchip.devices.tilelink.{BuiltInDevices, HasBuiltInDeviceParams, BuiltInErrorDeviceParams, BuiltInZeroDeviceParams} import freechips.rocketchip.tilelink.{ @@ -11,7 +12,6 @@ import freechips.rocketchip.tilelink.{ TLBusWrapperInstantiationLike, RegionReplicator, TLXbar, TLInwardNode, TLOutwardNode, ProbePicker, TLEdge, TLFIFOFixer } -import freechips.rocketchip.util.Location /** Parameterization of the memory-side bus created for each memory channel */ case class MemoryBusParams( diff --git a/src/main/scala/subsystem/PeripheryBus.scala b/src/main/scala/subsystem/PeripheryBus.scala index 6b0a66f9987..1cf941d6880 100644 --- a/src/main/scala/subsystem/PeripheryBus.scala +++ b/src/main/scala/subsystem/PeripheryBus.scala @@ -4,6 +4,7 @@ package freechips.rocketchip.subsystem import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy.lazymodule._ +import org.chipsalliance.rocketutils.Location import freechips.rocketchip.devices.tilelink.{BuiltInZeroDeviceParams, BuiltInErrorDeviceParams, HasBuiltInDeviceParams, BuiltInDevices} import freechips.rocketchip.diplomacy.BufferParams @@ -12,7 +13,6 @@ import freechips.rocketchip.tilelink.{ TLBusWrapperInstantiationLike, TLFIFOFixer, TLNode, TLXbar, TLInwardNode, TLOutwardNode, TLBuffer, TLWidthWidget, TLAtomicAutomata, TLEdge } -import freechips.rocketchip.util.Location case class BusAtomics( arithmetic: Boolean = true, diff --git a/src/main/scala/subsystem/Ports.scala b/src/main/scala/subsystem/Ports.scala index d3ed70c5e98..69b72a5941c 100644 --- a/src/main/scala/subsystem/Ports.scala +++ b/src/main/scala/subsystem/Ports.scala @@ -25,7 +25,8 @@ import freechips.rocketchip.tilelink.{ TLFIFOFixer, TLSlavePortParameters, TLManagerNode, TLSlaveParameters, TLClientNode, TLSourceShrinker, TLMasterParameters, TLMasterPortParameters } -import freechips.rocketchip.util.StringToAugmentedString + +import org.chipsalliance.rocketutils.conversions.StringToAugmentedString import freechips.rocketchip.tilelink.TLClockDomainCrossing import freechips.rocketchip.tilelink.TLResetDomainCrossing diff --git a/src/main/scala/subsystem/RocketSubsystem.scala b/src/main/scala/subsystem/RocketSubsystem.scala index a10903d050f..5213cb0db93 100644 --- a/src/main/scala/subsystem/RocketSubsystem.scala +++ b/src/main/scala/subsystem/RocketSubsystem.scala @@ -3,12 +3,12 @@ package freechips.rocketchip.subsystem import org.chipsalliance.cde.config._ +import org.chipsalliance.rocketutils.HasCoreMonitorBundles import freechips.rocketchip.devices.debug.HasPeripheryDebug import freechips.rocketchip.devices.tilelink.{CanHavePeripheryCLINT, CanHavePeripheryPLIC} import freechips.rocketchip.prci.{ResetCrossingType, NoResetCrossing, SynchronousCrossing, ClockCrossingType} import freechips.rocketchip.tile.{RocketTile, RocketTileParams} -import freechips.rocketchip.util.HasCoreMonitorBundles case class RocketCrossingParams( crossingType: ClockCrossingType = SynchronousCrossing(), diff --git a/src/main/scala/subsystem/SystemBus.scala b/src/main/scala/subsystem/SystemBus.scala index c80bb793b92..86239e954d3 100644 --- a/src/main/scala/subsystem/SystemBus.scala +++ b/src/main/scala/subsystem/SystemBus.scala @@ -4,6 +4,7 @@ package freechips.rocketchip.subsystem import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy.lazymodule._ +import org.chipsalliance.rocketutils.Location import freechips.rocketchip.devices.tilelink.{ BuiltInDevices, BuiltInZeroDeviceParams, BuiltInErrorDeviceParams, HasBuiltInDeviceParams @@ -13,7 +14,6 @@ import freechips.rocketchip.tilelink.{ TLBusWrapperInstantiationLike, TLXbar, TLEdge, TLInwardNode, TLOutwardNode, TLFIFOFixer, TLTempNode } -import freechips.rocketchip.util.Location case class SystemBusParams( beatBytes: Int, diff --git a/src/main/scala/system/ExampleRocketSystem.scala b/src/main/scala/system/ExampleRocketSystem.scala index 7267915c8fc..913606de563 100644 --- a/src/main/scala/system/ExampleRocketSystem.scala +++ b/src/main/scala/system/ExampleRocketSystem.scala @@ -3,9 +3,11 @@ package freechips.rocketchip.system import org.chipsalliance.cde.config.Parameters + +import org.chipsalliance.rocketutils.DontTouch + import freechips.rocketchip.subsystem._ import freechips.rocketchip.devices.tilelink._ -import freechips.rocketchip.util.DontTouch /** Example Top with periphery devices and ports, and a Rocket subsystem */ class ExampleRocketSystem(implicit p: Parameters) extends RocketSubsystem diff --git a/src/main/scala/system/TestHarness.scala b/src/main/scala/system/TestHarness.scala index 80c711880aa..8593ea29dcb 100644 --- a/src/main/scala/system/TestHarness.scala +++ b/src/main/scala/system/TestHarness.scala @@ -7,8 +7,9 @@ import chisel3._ import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy.lazymodule._ +import org.chipsalliance.rocketutils.AsyncResetReg + import freechips.rocketchip.devices.debug.Debug -import freechips.rocketchip.util.AsyncResetReg class TestHarness()(implicit p: Parameters) extends Module { val io = IO(new Bundle { diff --git a/src/main/scala/tile/BaseTile.scala b/src/main/scala/tile/BaseTile.scala index 598c829c75f..cd102c3e75d 100644 --- a/src/main/scala/tile/BaseTile.scala +++ b/src/main/scala/tile/BaseTile.scala @@ -8,7 +8,7 @@ import chisel3.util.{log2Ceil, log2Up} import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy._ import org.chipsalliance.diplomacy.bundlebridge._ - +import org.chipsalliance.rocketutils.{TraceCoreParams, TraceCoreInterface} import freechips.rocketchip.resources.{PropertyMap, PropertyOption, ResourceReference, DTSTimebase} import freechips.rocketchip.interrupts.{IntInwardNode, IntOutwardNode} @@ -19,10 +19,9 @@ import freechips.rocketchip.subsystem.{ } import freechips.rocketchip.tilelink.{TLEphemeralNode, TLOutwardNode, TLNode, TLFragmenter, EarlyAck, TLWidthWidget, TLManagerParameters, ManagerUnification} import freechips.rocketchip.prci.{ClockCrossingType, ClockSinkParameters} -import freechips.rocketchip.util.{TraceCoreParams, TraceCoreInterface} - import freechips.rocketchip.resources.{BigIntToProperty, IntToProperty, StringToProperty} -import freechips.rocketchip.util.BooleanToAugmentedBoolean + +import org.chipsalliance.rocketutils.conversions.BooleanToAugmentedBoolean case object TileVisibilityNodeKey extends Field[TLEphemeralNode] case object TileKey extends Field[TileParams] diff --git a/src/main/scala/tile/BusErrorUnit.scala b/src/main/scala/tile/BusErrorUnit.scala index bbfe3fb3628..ee4be09b217 100644 --- a/src/main/scala/tile/BusErrorUnit.scala +++ b/src/main/scala/tile/BusErrorUnit.scala @@ -7,14 +7,14 @@ import chisel3.util._ import org.chipsalliance.cde.config.Parameters import org.chipsalliance.diplomacy.lazymodule._ +import org.chipsalliance.rocketutils.property import freechips.rocketchip.rocket.{DCacheErrors, ICacheErrors} -import freechips.rocketchip.diplomacy.{AddressSet} -import freechips.rocketchip.resources.{SimpleDevice} +import freechips.rocketchip.diplomacy.AddressSet +import freechips.rocketchip.resources.SimpleDevice import freechips.rocketchip.regmapper.{DescribedReg, RegField, RegFieldDesc, RegFieldGroup} import freechips.rocketchip.tilelink.TLRegisterNode import freechips.rocketchip.interrupts.{IntSourceNode, IntSourcePortSimple} -import freechips.rocketchip.util.property trait BusErrors extends Bundle { def toErrorList: List[Option[(Valid[UInt], String, String)]] diff --git a/src/main/scala/tile/Core.scala b/src/main/scala/tile/Core.scala index dd3e0058bee..6e73f9b38fd 100644 --- a/src/main/scala/tile/Core.scala +++ b/src/main/scala/tile/Core.scala @@ -5,8 +5,9 @@ package freechips.rocketchip.tile import chisel3._ import chisel3.util.isPow2 import org.chipsalliance.cde.config._ +import org.chipsalliance.rocketutils.ParameterizedBundle + import freechips.rocketchip.rocket._ -import freechips.rocketchip.util._ case object XLen extends Field[Int] case object MaxHartIdBits extends Field[Int] diff --git a/src/main/scala/tile/FPU.scala b/src/main/scala/tile/FPU.scala index f3347078fed..39c4e714f65 100644 --- a/src/main/scala/tile/FPU.scala +++ b/src/main/scala/tile/FPU.scala @@ -8,11 +8,14 @@ import chisel3.util._ import chisel3.{DontCare, WireInit, withClock, withReset} import chisel3.experimental.SourceInfo import chisel3.experimental.dataview._ + import org.chipsalliance.cde.config.Parameters +import org.chipsalliance.rocketutils.{ClockGate, CoreMonitorBundle, ShouldBeRetimed, property} + import freechips.rocketchip.rocket._ import freechips.rocketchip.rocket.Instructions._ -import freechips.rocketchip.util._ -import freechips.rocketchip.util.property + +import org.chipsalliance.rocketutils.conversions.{uintToBitPat, SeqToAugmentedSeq, UIntToAugmentedUInt, UIntIsOneOf, BooleanToAugmentedBoolean} case class FPUParams( minFLen: Int = 32, diff --git a/src/main/scala/tile/Interrupts.scala b/src/main/scala/tile/Interrupts.scala index 6ae4da3d5d2..1d84b74eae6 100644 --- a/src/main/scala/tile/Interrupts.scala +++ b/src/main/scala/tile/Interrupts.scala @@ -6,13 +6,13 @@ import chisel3._ import chisel3.util._ import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy._ +import org.chipsalliance.rocketutils.CanHaveErrors import freechips.rocketchip.resources.{Device, DeviceSnippet, Description, ResourceBinding, ResourceInt} import freechips.rocketchip.interrupts.{IntIdentityNode, IntSinkNode, IntSinkPortSimple, IntSourceNode, IntSourcePortSimple} -import freechips.rocketchip.util.CanHaveErrors import freechips.rocketchip.resources.{IntToProperty, StringToProperty} -import freechips.rocketchip.util.BooleanToAugmentedBoolean +import org.chipsalliance.rocketutils.conversions.BooleanToAugmentedBoolean class NMI(val w: Int) extends Bundle { val rnmi = Bool() diff --git a/src/main/scala/tile/LazyRoCC.scala b/src/main/scala/tile/LazyRoCC.scala index 3b869b9aca4..67d907b73b0 100644 --- a/src/main/scala/tile/LazyRoCC.scala +++ b/src/main/scala/tile/LazyRoCC.scala @@ -17,7 +17,7 @@ import freechips.rocketchip.rocket.{ import freechips.rocketchip.tilelink.{ TLNode, TLIdentityNode, TLClientNode, TLMasterParameters, TLMasterPortParameters } -import freechips.rocketchip.util.InOrderArbiter +import org.chipsalliance.rocketutils.InOrderArbiter case object BuildRoCC extends Field[Seq[Parameters => LazyRoCC]](Nil) diff --git a/src/main/scala/tile/RocketTile.scala b/src/main/scala/tile/RocketTile.scala index 42cf9b644ed..8a46c890b53 100644 --- a/src/main/scala/tile/RocketTile.scala +++ b/src/main/scala/tile/RocketTile.scala @@ -7,6 +7,7 @@ import chisel3._ import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy.lazymodule._ +import org.chipsalliance.rocketutils.{Annotated, InOrderArbiter} import freechips.rocketchip.devices.tilelink.{BasicBusBlockerParams, BasicBusBlocker} import freechips.rocketchip.diplomacy.{ @@ -24,9 +25,8 @@ import freechips.rocketchip.rocket.{ } import freechips.rocketchip.subsystem.HierarchicalElementCrossingParamsLike import freechips.rocketchip.prci.{ClockSinkParameters, RationalCrossing, ClockCrossingType} -import freechips.rocketchip.util.{Annotated, InOrderArbiter} -import freechips.rocketchip.util.BooleanToAugmentedBoolean +import org.chipsalliance.rocketutils.conversions.BooleanToAugmentedBoolean case class RocketTileBoundaryBufferParams(force: Boolean = false) diff --git a/src/main/scala/tile/TilePRCIDomain.scala b/src/main/scala/tile/TilePRCIDomain.scala index 80c31f5a4d7..e56bafdef44 100644 --- a/src/main/scala/tile/TilePRCIDomain.scala +++ b/src/main/scala/tile/TilePRCIDomain.scala @@ -5,11 +5,11 @@ package freechips.rocketchip.tile import chisel3._ import org.chipsalliance.cde.config._ +import org.chipsalliance.rocketutils.TraceCoreInterface import freechips.rocketchip.prci.ClockSinkParameters import freechips.rocketchip.rocket.TracedInstruction import freechips.rocketchip.subsystem.{HierarchicalElementCrossingParamsLike, HierarchicalElementPRCIDomain} -import freechips.rocketchip.util.TraceCoreInterface /** A wrapper containing all logic necessary to safely place a tile diff --git a/src/main/scala/tilelink/Arbiter.scala b/src/main/scala/tilelink/Arbiter.scala index 452c1ba2665..fcc4354a87d 100644 --- a/src/main/scala/tilelink/Arbiter.scala +++ b/src/main/scala/tilelink/Arbiter.scala @@ -6,7 +6,7 @@ import chisel3._ import chisel3.util._ import chisel3.util.random.LFSR import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.util._ +import org.chipsalliance.rocketutils.conversions._ object TLArbiter { diff --git a/src/main/scala/tilelink/AsyncCrossing.scala b/src/main/scala/tilelink/AsyncCrossing.scala index 53ea462f37c..454db0ccea6 100644 --- a/src/main/scala/tilelink/AsyncCrossing.scala +++ b/src/main/scala/tilelink/AsyncCrossing.scala @@ -6,11 +6,11 @@ import chisel3._ import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy.lazymodule._ +import org.chipsalliance.rocketutils.{AsyncQueueParams, ToAsyncBundle, FromAsyncBundle, Pow2ClockDivider, property} import freechips.rocketchip.diplomacy.{AddressSet, NodeHandle} import freechips.rocketchip.prci.{AsynchronousCrossing} import freechips.rocketchip.subsystem.CrossingWrapper -import freechips.rocketchip.util.{AsyncQueueParams, ToAsyncBundle, FromAsyncBundle, Pow2ClockDivider, property} class TLAsyncCrossingSource(sync: Option[Int])(implicit p: Parameters) extends LazyModule { diff --git a/src/main/scala/tilelink/AtomicAutomata.scala b/src/main/scala/tilelink/AtomicAutomata.scala index ad573b718e5..b4020bb9746 100644 --- a/src/main/scala/tilelink/AtomicAutomata.scala +++ b/src/main/scala/tilelink/AtomicAutomata.scala @@ -9,10 +9,11 @@ import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy.lazymodule._ import freechips.rocketchip.diplomacy.{AddressSet, TransferSizes} -import freechips.rocketchip.util.leftOR import scala.math.{min,max} +import org.chipsalliance.rocketutils.conversions.leftOR + // Ensures that all downstream RW managers support Atomic operations. // If !passthrough, intercept all Atomics. Otherwise, only intercept those unsupported downstream. class TLAtomicAutomata(logical: Boolean = true, arithmetic: Boolean = true, concurrency: Int = 1, passthrough: Boolean = true)(implicit p: Parameters) extends LazyModule diff --git a/src/main/scala/tilelink/BlockDuringReset.scala b/src/main/scala/tilelink/BlockDuringReset.scala index 4dc6b2c29ce..f235523b7af 100644 --- a/src/main/scala/tilelink/BlockDuringReset.scala +++ b/src/main/scala/tilelink/BlockDuringReset.scala @@ -6,8 +6,8 @@ import chisel3._ import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy.lazymodule._ +import org.chipsalliance.rocketutils.BlockDuringReset -import freechips.rocketchip.util.BlockDuringReset /** BlockDuringReset ensures that no channel admits to be ready or valid while reset is raised. */ class TLBlockDuringReset(stretchResetCycles: Int = 0) diff --git a/src/main/scala/tilelink/Broadcast.scala b/src/main/scala/tilelink/Broadcast.scala index f73cdb97cd0..a9429cd467f 100644 --- a/src/main/scala/tilelink/Broadcast.scala +++ b/src/main/scala/tilelink/Broadcast.scala @@ -13,12 +13,11 @@ import freechips.rocketchip.diplomacy.{AddressDecoder, AddressSet, IdRange, Regi import freechips.rocketchip.resources.{SimpleDevice} import freechips.rocketchip.regmapper.RegField import freechips.rocketchip.interrupts.{IntSourceNode, IntSourcePortSimple} -import freechips.rocketchip.util.leftOR - -import freechips.rocketchip.util.DataToAugmentedData import scala.math.{min,max} +import org.chipsalliance.rocketutils.conversions.{DataToAugmentedData, leftOR} + case class TLBroadcastControlParams( address: AddressSet, beatBytes: Int) diff --git a/src/main/scala/tilelink/Bundles.scala b/src/main/scala/tilelink/Bundles.scala index 5bb53dfe429..ffd0d6d4ad7 100644 --- a/src/main/scala/tilelink/Bundles.scala +++ b/src/main/scala/tilelink/Bundles.scala @@ -3,12 +3,15 @@ package freechips.rocketchip.tilelink import chisel3._ -import freechips.rocketchip.util._ -import scala.collection.immutable.ListMap -import chisel3.util.Decoupled -import chisel3.util.DecoupledIO +import chisel3.util._ import chisel3.reflect.DataMirror +import org.chipsalliance.rocketutils.{AsyncBundle, BundleMap, CreditedIO, RationalIO} + +import scala.collection.immutable.ListMap + +import org.chipsalliance.rocketutils.conversions.BooleanToAugmentedBoolean + abstract class TLBundleBase(val params: TLBundleParameters) extends Bundle // common combos in lazy policy: diff --git a/src/main/scala/tilelink/BusWrapper.scala b/src/main/scala/tilelink/BusWrapper.scala index 8a9a2434e74..78c24566682 100644 --- a/src/main/scala/tilelink/BusWrapper.scala +++ b/src/main/scala/tilelink/BusWrapper.scala @@ -10,6 +10,7 @@ import org.chipsalliance.diplomacy._ import org.chipsalliance.diplomacy.bundlebridge._ import org.chipsalliance.diplomacy.lazymodule._ import org.chipsalliance.diplomacy.nodes._ +import org.chipsalliance.rocketutils.Location import freechips.rocketchip.diplomacy.{AddressSet, NoHandle, NodeHandle, NodeBinding} @@ -25,7 +26,6 @@ import freechips.rocketchip.subsystem.{ HasTileLinkLocations, CanConnectWithinContextThatHasTileLinkLocations, CanInstantiateWithinContextThatHasTileLinkLocations } -import freechips.rocketchip.util.Location /** Specifies widths of various attachement points in the SoC */ trait HasTLBusParams { diff --git a/src/main/scala/tilelink/CacheCork.scala b/src/main/scala/tilelink/CacheCork.scala index a8518d97dee..0f68f2fe460 100644 --- a/src/main/scala/tilelink/CacheCork.scala +++ b/src/main/scala/tilelink/CacheCork.scala @@ -7,15 +7,15 @@ import chisel3.util._ import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy.lazymodule._ +import org.chipsalliance.rocketutils.IDPool import freechips.rocketchip.diplomacy.{IdRange, RegionType, TransferSizes} import freechips.rocketchip.tilelink.TLMessages.{ AcquireBlock, AcquirePerm, Get, PutFullData, PutPartialData, Release, ReleaseData, Grant, GrantData, AccessAck, AccessAckData, ReleaseAck } -import freechips.rocketchip.util.IDPool -import freechips.rocketchip.util.DataToAugmentedData +import org.chipsalliance.rocketutils.conversions.DataToAugmentedData case class TLCacheCorkParams( unsafe: Boolean = false, diff --git a/src/main/scala/tilelink/Credited.scala b/src/main/scala/tilelink/Credited.scala index e8a1085f273..29ed2eb8587 100644 --- a/src/main/scala/tilelink/Credited.scala +++ b/src/main/scala/tilelink/Credited.scala @@ -7,11 +7,11 @@ import chisel3.util._ import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy.lazymodule._ +import org.chipsalliance.rocketutils.{CreditedDelay, CreditedIO} import freechips.rocketchip.diplomacy.{AddressSet} import freechips.rocketchip.prci.{CreditedCrossing} import freechips.rocketchip.subsystem.CrossingWrapper -import freechips.rocketchip.util.{CreditedDelay, CreditedIO} class TLCreditedBuffer(delay: TLCreditedDelay)(implicit p: Parameters) extends LazyModule { diff --git a/src/main/scala/tilelink/Edges.scala b/src/main/scala/tilelink/Edges.scala index ef56eb733c6..08ac5822178 100644 --- a/src/main/scala/tilelink/Edges.scala +++ b/src/main/scala/tilelink/Edges.scala @@ -6,7 +6,9 @@ import chisel3._ import chisel3.util._ import chisel3.experimental.SourceInfo import org.chipsalliance.cde.config.Parameters -import freechips.rocketchip.util._ +import org.chipsalliance.rocketutils.MaskGen + +import org.chipsalliance.rocketutils.conversions.UIntToOH1 class TLEdge( client: TLClientPortParameters, diff --git a/src/main/scala/tilelink/ErrorEvaluator.scala b/src/main/scala/tilelink/ErrorEvaluator.scala index e8931e9c650..0f55815c606 100644 --- a/src/main/scala/tilelink/ErrorEvaluator.scala +++ b/src/main/scala/tilelink/ErrorEvaluator.scala @@ -8,9 +8,8 @@ import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy.lazymodule._ import freechips.rocketchip.diplomacy.AddressSet -import freechips.rocketchip.util.UIntToOH1 -import freechips.rocketchip.util.DataToAugmentedData +import org.chipsalliance.rocketutils.conversions.{DataToAugmentedData, UIntToOH1} // Check if a request satisfies some interesting property class RequestPattern(test: TLBundleA => Bool) diff --git a/src/main/scala/tilelink/FIFOFixer.scala b/src/main/scala/tilelink/FIFOFixer.scala index efa0e966b46..031db2f1cf8 100644 --- a/src/main/scala/tilelink/FIFOFixer.scala +++ b/src/main/scala/tilelink/FIFOFixer.scala @@ -8,9 +8,9 @@ import chisel3.util._ import org.chipsalliance.cde.config.Parameters import org.chipsalliance.diplomacy.lazymodule._ import org.chipsalliance.diplomacy.nodes._ +import org.chipsalliance.rocketutils.property import freechips.rocketchip.diplomacy.RegionType -import freechips.rocketchip.util.property class TLFIFOFixer(policy: TLFIFOFixer.Policy = TLFIFOFixer.all)(implicit p: Parameters) extends LazyModule { diff --git a/src/main/scala/tilelink/Fragmenter.scala b/src/main/scala/tilelink/Fragmenter.scala index a9f77c15ec0..2ca73088a1c 100644 --- a/src/main/scala/tilelink/Fragmenter.scala +++ b/src/main/scala/tilelink/Fragmenter.scala @@ -8,13 +8,13 @@ import chisel3.util._ import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy._ import org.chipsalliance.diplomacy.lazymodule._ +import org.chipsalliance.rocketutils.Repeater import freechips.rocketchip.diplomacy.{AddressSet, BufferParams, IdRange, TransferSizes} -import freechips.rocketchip.util.{Repeater, OH1ToUInt, UIntToOH1} import scala.math.min -import freechips.rocketchip.util.DataToAugmentedData +import org.chipsalliance.rocketutils.conversions.{DataToAugmentedData, OH1ToUInt, UIntToOH1} object EarlyAck { sealed trait T diff --git a/src/main/scala/tilelink/Fuzzer.scala b/src/main/scala/tilelink/Fuzzer.scala index 0dbf21fc831..6017bf940a4 100644 --- a/src/main/scala/tilelink/Fuzzer.scala +++ b/src/main/scala/tilelink/Fuzzer.scala @@ -9,9 +9,8 @@ import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy.lazymodule._ import freechips.rocketchip.diplomacy.{AddressSet, IdRange} -import freechips.rocketchip.util.{leftOR, UIntToOH1} -import freechips.rocketchip.util.DataToAugmentedData +import org.chipsalliance.rocketutils.conversions.{DataToAugmentedData, leftOR, UIntToOH1} class IDMapGenerator(numIds: Int) extends Module { require (numIds > 0) diff --git a/src/main/scala/tilelink/HintHandler.scala b/src/main/scala/tilelink/HintHandler.scala index 982a1461d81..c1018e227eb 100644 --- a/src/main/scala/tilelink/HintHandler.scala +++ b/src/main/scala/tilelink/HintHandler.scala @@ -6,9 +6,9 @@ import chisel3._ import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy.lazymodule._ +import org.chipsalliance.rocketutils.Repeater import freechips.rocketchip.diplomacy.{AddressSet, RegionType, IdRange, TransferSizes} -import freechips.rocketchip.util.Repeater import freechips.rocketchip.devices.tilelink.TLROM // Acks Hints for managers that don't support them or Acks all Hints if !passthrough diff --git a/src/main/scala/tilelink/Isolation.scala b/src/main/scala/tilelink/Isolation.scala index 90ebe4dd07a..b54eb3f902e 100644 --- a/src/main/scala/tilelink/Isolation.scala +++ b/src/main/scala/tilelink/Isolation.scala @@ -6,8 +6,8 @@ import chisel3._ import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy.lazymodule._ +import org.chipsalliance.rocketutils.AsyncBundle -import freechips.rocketchip.util.AsyncBundle // READ the comments in the TLIsolation object before you instantiate this module class TLIsolation(fOut: (Bool, UInt) => UInt, fIn: (Bool, UInt) => UInt)(implicit p: Parameters) extends LazyModule diff --git a/src/main/scala/tilelink/Metadata.scala b/src/main/scala/tilelink/Metadata.scala index 7f4f2854c7e..ace3f6ed2c6 100644 --- a/src/main/scala/tilelink/Metadata.scala +++ b/src/main/scala/tilelink/Metadata.scala @@ -5,8 +5,10 @@ package freechips.rocketchip.tilelink import chisel3._ import chisel3.util._ + +import org.chipsalliance.rocketutils.MuxTLookup + import freechips.rocketchip.rocket.constants.MemoryOpConstants -import freechips.rocketchip.util._ object ClientStates { val width = 2 diff --git a/src/main/scala/tilelink/Monitor.scala b/src/main/scala/tilelink/Monitor.scala index 0c5586cd583..d860abaa4fe 100644 --- a/src/main/scala/tilelink/Monitor.scala +++ b/src/main/scala/tilelink/Monitor.scala @@ -8,10 +8,10 @@ import chisel3.experimental.SourceLine import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy._ +import org.chipsalliance.rocketutils.PlusArg import freechips.rocketchip.diplomacy.EnableMonitors import freechips.rocketchip.formal.{MonitorDirection, IfThen, Property, PropertyClass, TestplanTestType, TLMonitorStrictMode} -import freechips.rocketchip.util.PlusArg case class TLMonitorArgs(edge: TLEdge) diff --git a/src/main/scala/tilelink/Nodes.scala b/src/main/scala/tilelink/Nodes.scala index 6b193f8ec0b..c6484f62ec2 100644 --- a/src/main/scala/tilelink/Nodes.scala +++ b/src/main/scala/tilelink/Nodes.scala @@ -8,8 +8,8 @@ import chisel3.experimental.SourceInfo import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy._ import org.chipsalliance.diplomacy.nodes._ +import org.chipsalliance.rocketutils.{AsyncQueueParams,RationalDirection} -import freechips.rocketchip.util.{AsyncQueueParams,RationalDirection} case object TLMonitorBuilder extends Field[TLMonitorArgs => TLMonitorBase](args => new TLMonitor(args)) diff --git a/src/main/scala/tilelink/Parameters.scala b/src/main/scala/tilelink/Parameters.scala index 3be0c2bd845..b1723208395 100644 --- a/src/main/scala/tilelink/Parameters.scala +++ b/src/main/scala/tilelink/Parameters.scala @@ -8,19 +8,21 @@ import chisel3.experimental.SourceInfo import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy.nodes._ +import org.chipsalliance.rocketutils.{ + AsyncQueueParams, BundleField, BundleFieldBase, BundleKeyBase, + CreditedDelay, RationalDirection, SimpleProduct +} import freechips.rocketchip.diplomacy.{ AddressDecoder, AddressSet, BufferParams, DirectedBuffers, IdMap, IdMapEntry, IdRange, RegionType, TransferSizes } import freechips.rocketchip.resources.{Resource, ResourceAddress, ResourcePermissions} -import freechips.rocketchip.util.{ - AsyncQueueParams, BundleField, BundleFieldBase, BundleKeyBase, - CreditedDelay, groupByIntoSeq, RationalDirection, SimpleProduct -} import scala.math.max +import org.chipsalliance.rocketutils.conversions.groupByIntoSeq + //These transfer sizes describe requests issued from masters on the A channel that will be responded by slaves on the D channel case class TLMasterToSlaveTransferSizes( // Supports both Acquire+Release of the following two sizes: diff --git a/src/main/scala/tilelink/PatternPusher.scala b/src/main/scala/tilelink/PatternPusher.scala index 08e9eaba740..b0122f3e415 100644 --- a/src/main/scala/tilelink/PatternPusher.scala +++ b/src/main/scala/tilelink/PatternPusher.scala @@ -8,7 +8,7 @@ import chisel3.util._ import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy.lazymodule._ -import freechips.rocketchip.util.DataToAugmentedData +import org.chipsalliance.rocketutils.conversions.DataToAugmentedData trait Pattern { def address: BigInt diff --git a/src/main/scala/tilelink/RAMModel.scala b/src/main/scala/tilelink/RAMModel.scala index 4a785242906..06c4c9bfecf 100644 --- a/src/main/scala/tilelink/RAMModel.scala +++ b/src/main/scala/tilelink/RAMModel.scala @@ -7,10 +7,9 @@ import chisel3.util._ import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy.lazymodule._ +import org.chipsalliance.rocketutils.CRC -import freechips.rocketchip.util.{CRC, UIntToOH1} - -import freechips.rocketchip.util.DataToAugmentedData +import org.chipsalliance.rocketutils.conversions.{DataToAugmentedData, UIntToOH1} // We detect concurrent puts that put memory into an undefined state. // put0, put0Ack, put1, put1Ack => ok: defined diff --git a/src/main/scala/tilelink/RationalCrossing.scala b/src/main/scala/tilelink/RationalCrossing.scala index 3dd7ad289b9..49141b4fabe 100644 --- a/src/main/scala/tilelink/RationalCrossing.scala +++ b/src/main/scala/tilelink/RationalCrossing.scala @@ -13,12 +13,12 @@ import chisel3._ import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy.lazymodule._ - -import freechips.rocketchip.diplomacy.{AddressSet, NodeHandle} -import freechips.rocketchip.util.{ +import org.chipsalliance.rocketutils.{ FromRational, ToRational, RationalDirection, Symmetric, FastToSlow, SlowToFast, Pow2ClockDivider, ClockDivider3 } +import freechips.rocketchip.diplomacy.{AddressSet, NodeHandle} + class TLRationalCrossingSource(implicit p: Parameters) extends LazyModule { diff --git a/src/main/scala/tilelink/RegisterRouter.scala b/src/main/scala/tilelink/RegisterRouter.scala index f66a018bf23..8e8769d7440 100644 --- a/src/main/scala/tilelink/RegisterRouter.scala +++ b/src/main/scala/tilelink/RegisterRouter.scala @@ -8,15 +8,17 @@ import chisel3.util._ import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy._ import org.chipsalliance.diplomacy.nodes._ +import org.chipsalliance.rocketutils.{BundleField, ControlKey, ElaborationArtefacts} import freechips.rocketchip.diplomacy.{AddressSet, TransferSizes} import freechips.rocketchip.resources.{Device, Resource, ResourceBindings} import freechips.rocketchip.prci.{NoCrossing} import freechips.rocketchip.regmapper.{RegField, RegMapper, RegMapperParams, RegMapperInput, RegisterRouter} -import freechips.rocketchip.util.{BundleField, ControlKey, ElaborationArtefacts, GenRegDescsAnno} import scala.math.min +import freechips.rocketchip.util.GenRegDescsAnno + class TLRegisterRouterExtraBundle(val sourceBits: Int, val sizeBits: Int) extends Bundle { val source = UInt((sourceBits max 1).W) val size = UInt((sizeBits max 1).W) diff --git a/src/main/scala/tilelink/SRAM.scala b/src/main/scala/tilelink/SRAM.scala index 6703bac3c37..9c624027350 100644 --- a/src/main/scala/tilelink/SRAM.scala +++ b/src/main/scala/tilelink/SRAM.scala @@ -8,13 +8,12 @@ import chisel3.util._ import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy.bundlebridge._ import org.chipsalliance.diplomacy.lazymodule._ +import org.chipsalliance.rocketutils.{CanHaveErrors, ECCParams, property, SECDEDCode} import freechips.rocketchip.diplomacy.{AddressSet, RegionType, TransferSizes} import freechips.rocketchip.resources.{Device, DeviceRegName, DiplomaticSRAM, HasJustOneSeqMem} -import freechips.rocketchip.util.{CanHaveErrors, ECCParams, property, SECDEDCode} -import freechips.rocketchip.util.DataToAugmentedData -import freechips.rocketchip.util.BooleanToAugmentedBoolean +import org.chipsalliance.rocketutils.conversions.{DataToAugmentedData, BooleanToAugmentedBoolean} class TLRAMErrors(val params: ECCParams, val addrBits: Int) extends Bundle with CanHaveErrors { val correctable = (params.code.canCorrect && params.notifyErrors).option(Valid(UInt(addrBits.W))) diff --git a/src/main/scala/tilelink/SourceShrinker.scala b/src/main/scala/tilelink/SourceShrinker.scala index c72d42f3e85..ac32a218503 100644 --- a/src/main/scala/tilelink/SourceShrinker.scala +++ b/src/main/scala/tilelink/SourceShrinker.scala @@ -9,9 +9,8 @@ import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy.lazymodule._ import freechips.rocketchip.diplomacy.IdRange -import freechips.rocketchip.util.leftOR -import freechips.rocketchip.util.DataToAugmentedData +import org.chipsalliance.rocketutils.conversions.{DataToAugmentedData, leftOR} class TLSourceShrinker(maxInFlight: Int)(implicit p: Parameters) extends LazyModule { diff --git a/src/main/scala/tilelink/ToAHB.scala b/src/main/scala/tilelink/ToAHB.scala index a5267704295..f874c4df7bb 100644 --- a/src/main/scala/tilelink/ToAHB.scala +++ b/src/main/scala/tilelink/ToAHB.scala @@ -9,12 +9,14 @@ import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy._ import org.chipsalliance.diplomacy.lazymodule._ import org.chipsalliance.diplomacy.nodes._ +import org.chipsalliance.rocketutils.{BundleMap} import freechips.rocketchip.amba.{AMBAProt, AMBAProtField} import freechips.rocketchip.amba.ahb.{AHBImpMaster, AHBParameters, AHBMasterParameters, AHBMasterPortParameters} import freechips.rocketchip.amba.ahb.AHBParameters.{BURST_INCR, BURST_SINGLE, TRANS_NONSEQ, TRANS_SEQ, TRANS_IDLE, TRANS_BUSY, PROT_DEFAULT} import freechips.rocketchip.diplomacy.TransferSizes -import freechips.rocketchip.util.{BundleMap, UIntToOH1} + +import org.chipsalliance.rocketutils.conversions.UIntToOH1 case class TLToAHBNode(supportHints: Boolean)(implicit valName: ValName) extends MixedAdapterNode(TLImp, AHBImpMaster)( dFn = { cp => diff --git a/src/main/scala/tilelink/ToAXI4.scala b/src/main/scala/tilelink/ToAXI4.scala index a01ad75cf7a..70bed4421da 100644 --- a/src/main/scala/tilelink/ToAXI4.scala +++ b/src/main/scala/tilelink/ToAXI4.scala @@ -9,13 +9,13 @@ import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy._ import org.chipsalliance.diplomacy.lazymodule._ import org.chipsalliance.diplomacy.nodes._ +import org.chipsalliance.rocketutils.{BundleField, ControlKey, ElaborationArtefacts} import freechips.rocketchip.amba.{AMBACorrupt, AMBACorruptField, AMBAProt, AMBAProtField} import freechips.rocketchip.amba.axi4.{AXI4BundleARW, AXI4MasterParameters, AXI4MasterPortParameters, AXI4Parameters, AXI4Imp} import freechips.rocketchip.diplomacy.{IdMap, IdMapEntry, IdRange} -import freechips.rocketchip.util.{BundleField, ControlKey, ElaborationArtefacts, UIntToOH1} -import freechips.rocketchip.util.DataToAugmentedData +import org.chipsalliance.rocketutils.conversions.{DataToAugmentedData, UIntToOH1} class AXI4TLStateBundle(val sourceBits: Int) extends Bundle { val size = UInt(4.W) diff --git a/src/main/scala/tilelink/WidthWidget.scala b/src/main/scala/tilelink/WidthWidget.scala index 37796c043f6..75cd6ac4b3f 100644 --- a/src/main/scala/tilelink/WidthWidget.scala +++ b/src/main/scala/tilelink/WidthWidget.scala @@ -7,9 +7,11 @@ import chisel3.util._ import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy.lazymodule._ +import org.chipsalliance.rocketutils.Repeater import freechips.rocketchip.diplomacy.AddressSet -import freechips.rocketchip.util.{Repeater, UIntToOH1} + +import org.chipsalliance.rocketutils.conversions.UIntToOH1 // innBeatBytes => the new client-facing bus width class TLWidthWidget(innerBeatBytes: Int)(implicit p: Parameters) extends LazyModule diff --git a/src/main/scala/tilelink/Xbar.scala b/src/main/scala/tilelink/Xbar.scala index 13f51f1cd7e..e6d9ef29c7c 100644 --- a/src/main/scala/tilelink/Xbar.scala +++ b/src/main/scala/tilelink/Xbar.scala @@ -7,9 +7,9 @@ import chisel3.util._ import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy.lazymodule._ +import org.chipsalliance.rocketutils.BundleField import freechips.rocketchip.diplomacy.{AddressDecoder, AddressSet, RegionType, IdRange, TriStateValue} -import freechips.rocketchip.util.BundleField // Trades off slave port proximity against routing resource cost object ForceFanout diff --git a/src/main/scala/unittest/Configs.scala b/src/main/scala/unittest/Configs.scala index 655811576b8..74669cfdb15 100644 --- a/src/main/scala/unittest/Configs.scala +++ b/src/main/scala/unittest/Configs.scala @@ -3,14 +3,18 @@ package freechips.rocketchip.unittest import chisel3._ + +import org.chipsalliance.cde.config.{Config, Field, Parameters} +import org.chipsalliance.rocketutils.{FloppedLanePositionedQueue, OnePortLanePositionedQueue, IdentityCode} + import freechips.rocketchip.amba.ahb._ import freechips.rocketchip.amba.apb._ import freechips.rocketchip.amba.axi4._ -import org.chipsalliance.cde.config._ -import freechips.rocketchip.subsystem.{BaseSubsystemConfig} +import freechips.rocketchip.subsystem.BaseSubsystemConfig import freechips.rocketchip.devices.tilelink._ import freechips.rocketchip.tilelink._ -import freechips.rocketchip.util._ + +import freechips.rocketchip.unittest.hwtests.{ECCTest, GatherTest, ScatterTest, PLRUTest, PositionedQueueTest, MultiPortQueueTest, MultiLaneQueueTest} case object TestDurationMultiplier extends Field[Int] diff --git a/src/main/scala/unittest/UnitTest.scala b/src/main/scala/unittest/UnitTest.scala index d911f66602a..f8db8475036 100644 --- a/src/main/scala/unittest/UnitTest.scala +++ b/src/main/scala/unittest/UnitTest.scala @@ -3,9 +3,11 @@ package freechips.rocketchip.unittest import chisel3._ -import chisel3.util._ -import org.chipsalliance.cde.config._ -import freechips.rocketchip.util._ +import chisel3.util.Enum + +import org.chipsalliance.cde.config.{Field, Parameters} + +import org.chipsalliance.rocketutils.{ElaborationArtefacts, PlusArgArtefacts, SimpleTimer} trait UnitTestIO { val finished = Output(Bool()) diff --git a/src/main/scala/unittest/hwtests/ECC.scala b/src/main/scala/unittest/hwtests/ECC.scala new file mode 100644 index 00000000000..a24556e1ef6 --- /dev/null +++ b/src/main/scala/unittest/hwtests/ECC.scala @@ -0,0 +1,57 @@ +// See LICENSE.Berkeley for license details. + +package freechips.rocketchip.unittest.hwtests + +import chisel3._ +import chisel3.util.PopCount + +import org.chipsalliance.rocketutils.SECDEDCode + +import freechips.rocketchip.unittest.UnitTest + +class ECCTest(k: Int, timeout: Int = 500000) extends UnitTest(timeout) { + val code = new SECDEDCode + val n = code.width(k) + + // Brute force the decode space + val test = RegInit(0.U((n+1).W)) + val last = test(n) + test := test + !last + io.finished := RegNext(last, false.B) + + // Confirm the decoding matches the encoding + val decoded = code.decode(test(n-1, 0)) + val recoded = code.encode(decoded.corrected) + val distance = PopCount(recoded ^ test) + + // Count the cases + val correct = RegInit(0.U(n.W)) + val correctable = RegInit(0.U(n.W)) + val uncorrectable = RegInit(0.U(n.W)) + + when (!last) { + when (decoded.uncorrectable) { + assert (distance >= 2.U) // uncorrectable + uncorrectable := uncorrectable + 1.U + } .elsewhen (decoded.correctable) { + assert (distance(0)) // correctable => odd bit errors + correctable := correctable + 1.U + } .otherwise { + assert (distance === 0.U) // correct + assert (decoded.uncorrected === decoded.corrected) + correct := correct + 1.U + } + } + + // Expected number of each case + val nCodes = BigInt(1) << n + val nCorrect = BigInt(1) << k + val nCorrectable = nCodes / 2 + val nUncorrectable = nCodes - nCorrectable - nCorrect + + when (last) { + assert (correct === nCorrect.U) + assert (correctable === nCorrectable.U) + assert (uncorrectable === nUncorrectable.U) + } +} diff --git a/src/main/scala/unittest/hwtests/LanePositionedQueue.scala b/src/main/scala/unittest/hwtests/LanePositionedQueue.scala new file mode 100644 index 00000000000..abdc0fa96e8 --- /dev/null +++ b/src/main/scala/unittest/hwtests/LanePositionedQueue.scala @@ -0,0 +1,72 @@ +// See LICENSE.SiFive for license details. + +package freechips.rocketchip.unittest.hwtests + +import chisel3._ +import chisel3.util.log2Ceil + +import org.chipsalliance.rocketutils.LanePositionedQueue + +import freechips.rocketchip.unittest.UnitTest +import freechips.rocketchip.tilelink.LFSR64 + +class PositionedQueueTest(queueFactory: LanePositionedQueue, lanes: Int, rows: Int, rewind: Boolean, abort: Boolean, cycles: Int, timeout: Int = 500000) extends UnitTest(timeout) { + val ids = (cycles+1) * lanes + val bits = log2Ceil(ids+1) + + val q = Module(queueFactory(UInt(bits.W), lanes, rows, true, false, rewind, abort, rewind, abort)) + + val enq = RegInit(0.U(bits.W)) + val deq = RegInit(0.U(bits.W)) + val com = RegInit(0.U(bits.W)) + val abt = RegInit(0.U(bits.W)) + val done = RegInit(false.B) + + def cap(x: UInt) = Mux(x > lanes.U, lanes.U, x) +& 1.U + q.io.enq.valid := (LFSR64() * cap(q.io.enq.ready)) >> 64 + q.io.deq.ready := (LFSR64() * cap(q.io.deq.valid)) >> 64 + + enq := enq + q.io.enq.valid + deq := deq + q.io.deq.ready + + q.io.commit.foreach { c => + val legal = enq + q.io.enq.valid - com + assert (c.ready || c.bits > legal) + c.valid := LFSR64()(0) + c.bits := ((legal + 1.U) * LFSR64()) >> 63 // 50% likely to be legal + when (c.fire) { com := com + c.bits } + } + + q.io.free.foreach { f => + val legal = deq + q.io.deq.ready - abt + assert (f.ready || f.bits > legal) + f.valid := LFSR64()(0) + f.bits := ((legal + 1.U) * LFSR64()) >> 63 + when (f.fire) { abt := abt + f.bits } + } + + q.io.rewind.foreach { r => + val f = q.io.free.get + r := (LFSR64() & 0xf.U) === 0.U + when (r) { deq := Mux(f.fire, abt + f.bits, abt) } + } + + q.io.abort .foreach { a => + val c = q.io.commit.get + a := (LFSR64() & 0xf.U) === 0.U + when (a) { enq := Mux(c.fire, com + c.bits, com) } + } + + when (enq >= (cycles*lanes).U) { done := true.B } + io.finished := done + + q.io.enq.bits := VecInit.tabulate(lanes) { i => + val pos = Mux(i.U >= q.io.enq_0_lane, i.U, (i + lanes).U) - q.io.enq_0_lane + Mux (pos >= q.io.enq.valid, 0.U, enq + pos) + } + + q.io.deq.bits.zipWithIndex.foreach { case (d, i) => + val pos = Mux(i.U >= q.io.deq_0_lane, i.U, (i + lanes).U) - q.io.deq_0_lane + assert (pos >= q.io.deq.valid || d === deq + pos) + } +} diff --git a/src/main/scala/unittest/hwtests/MultiLaneQueue.scala b/src/main/scala/unittest/hwtests/MultiLaneQueue.scala new file mode 100644 index 00000000000..f70fc1d8251 --- /dev/null +++ b/src/main/scala/unittest/hwtests/MultiLaneQueue.scala @@ -0,0 +1,38 @@ +// See LICENSE.SiFive for license details. + +package freechips.rocketchip.unittest.hwtests + +import chisel3._ +import chisel3.util.log2Ceil + +import org.chipsalliance.rocketutils.MultiLaneQueue + +import freechips.rocketchip.unittest.UnitTest +import freechips.rocketchip.tilelink.LFSR64 + +class MultiLaneQueueTest(lanes: Int, rows: Int, cycles: Int, timeout: Int = 500000) extends UnitTest(timeout) { + val ids = (cycles+1) * lanes + val bits = log2Ceil(ids+1) + + val q = Module(new MultiLaneQueue(UInt(bits.W), lanes, rows)) + + val enq = RegInit(0.U(bits.W)) + val deq = RegInit(0.U(bits.W)) + val done = RegInit(false.B) + + when (enq >= (cycles*lanes).U) { done := true.B } + io.finished := done + + q.io.enq_valid := (LFSR64() * (1+lanes).U) >> 64 + q.io.deq_ready := (LFSR64() * (1+lanes).U) >> 64 + + when (q.io.enq_ready) { enq := enq + q.io.enq_valid } + when (q.io.deq_valid) { deq := deq + q.io.deq_ready } + + for (i <- 0 until lanes) { + q.io.enq_bits(i) := enq + i.U + when (q.io.deq_valid) { + assert (i.U >= q.io.deq_ready || q.io.deq_bits(i) === deq + i.U) + } + } +} diff --git a/src/main/scala/unittest/hwtests/MultiPortQueue.scala b/src/main/scala/unittest/hwtests/MultiPortQueue.scala new file mode 100644 index 00000000000..dd062c4e37c --- /dev/null +++ b/src/main/scala/unittest/hwtests/MultiPortQueue.scala @@ -0,0 +1,41 @@ +// See LICENSE.SiFive for license details. + +package freechips.rocketchip.unittest.hwtests + +import chisel3._ +import chisel3.util.{log2Ceil, PopCount} + +import org.chipsalliance.rocketutils.{MultiPortQueue, RipplePrefixSum} + +import freechips.rocketchip.unittest.UnitTest +import freechips.rocketchip.tilelink.LFSR64 + +class MultiPortQueueTest(lanes: Int, wlanes: Int, rows: Int, cycles: Int, timeout: Int = 500000) extends UnitTest(timeout) { + val ids = (cycles+1) * lanes + val bits = log2Ceil(ids+1) + + val q = Module(new MultiPortQueue(UInt(bits.W), lanes, lanes, wlanes, rows)) + + val enq = RegInit(0.U(bits.W)) + val deq = RegInit(0.U(bits.W)) + val done = RegInit(false.B) + + when (enq >= (cycles*lanes).U) { done := true.B } + io.finished := done + + val valid = LFSR64()(lanes-1, 0) + val ready = LFSR64()(lanes-1, 0) + + enq := enq + PopCount(q.io.enq.map(_.fire)) + deq := deq + PopCount(q.io.deq.map(_.fire)) + + val enq_bits = RipplePrefixSum(enq +: valid.asBools.map(x => WireInit(UInt(bits.W), x)))(_ + _) + val deq_bits = RipplePrefixSum(deq +: ready.asBools.map(x => WireInit(UInt(bits.W), x)))(_ + _) + + for (i <- 0 until lanes) { + q.io.enq(i).valid := valid(i) + q.io.enq(i).bits := Mux(valid(i), enq_bits(i), 0.U) + q.io.deq(i).ready := ready(i) + assert (!q.io.deq(i).fire || q.io.deq(i).bits === deq_bits(i)) + } +} diff --git a/src/main/scala/unittest/hwtests/MultiWidthFifo.scala b/src/main/scala/unittest/hwtests/MultiWidthFifo.scala new file mode 100644 index 00000000000..6a6ebd6a891 --- /dev/null +++ b/src/main/scala/unittest/hwtests/MultiWidthFifo.scala @@ -0,0 +1,90 @@ +// See LICENSE.Berkeley for license details. + +package freechips.rocketchip.unittest.hwtests + +import chisel3._ +import chisel3.util.{Cat, Counter} + +import org.chipsalliance.rocketutils.MultiWidthFifo + +import freechips.rocketchip.unittest.UnitTest + +class MultiWidthFifoTest extends UnitTest { + val big2little = Module(new MultiWidthFifo(16, 8, 8)) + val little2big = Module(new MultiWidthFifo(8, 16, 4)) + + val bl_send = RegInit(false.B) + val lb_send = RegInit(false.B) + val bl_recv = RegInit(false.B) + val lb_recv = RegInit(false.B) + val bl_finished = RegInit(false.B) + val lb_finished = RegInit(false.B) + + val bl_data = VecInit(Seq.tabulate(4){i => ((2 * i + 1) * 256 + 2 * i).U(16.W)}) + val lb_data = VecInit(Seq.tabulate(8){i => i.U(8.W)}) + + val (bl_send_cnt, bl_send_done) = Counter(big2little.io.in.fire, 4) + val (lb_send_cnt, lb_send_done) = Counter(little2big.io.in.fire, 8) + + val (bl_recv_cnt, bl_recv_done) = Counter(big2little.io.out.fire, 8) + val (lb_recv_cnt, lb_recv_done) = Counter(little2big.io.out.fire, 4) + + big2little.io.in.valid := bl_send + big2little.io.in.bits := bl_data(bl_send_cnt) + big2little.io.out.ready := bl_recv + + little2big.io.in.valid := lb_send + little2big.io.in.bits := lb_data(lb_send_cnt) + little2big.io.out.ready := lb_recv + + val bl_recv_data_idx = bl_recv_cnt >> 1.U + val bl_recv_data = Mux(bl_recv_cnt(0), + bl_data(bl_recv_data_idx)(15, 8), + bl_data(bl_recv_data_idx)(7, 0)) + + val lb_recv_data = Cat( + lb_data(Cat(lb_recv_cnt, 1.U(1.W))), + lb_data(Cat(lb_recv_cnt, 0.U(1.W)))) + + when (io.start) { + bl_send := true.B + lb_send := true.B + } + + when (bl_send_done) { + bl_send := false.B + bl_recv := true.B + } + + when (lb_send_done) { + lb_send := false.B + lb_recv := true.B + } + + when (bl_recv_done) { + bl_recv := false.B + bl_finished := true.B + } + + when (lb_recv_done) { + lb_recv := false.B + lb_finished := true.B + } + + io.finished := bl_finished && lb_finished + + val bl_start_recv = RegNext(bl_send_done) + val lb_start_recv = RegNext(lb_send_done) + + assert(!little2big.io.out.valid || little2big.io.out.bits === lb_recv_data, + "Little to Big data mismatch") + assert(!big2little.io.out.valid || big2little.io.out.bits === bl_recv_data, + "Bit to Little data mismatch") + + assert(!lb_start_recv || little2big.io.count === 4.U, + "Little to Big count incorrect") + assert(!bl_start_recv || big2little.io.count === 8.U, + "Big to Little count incorrect") +} + + diff --git a/src/main/scala/unittest/hwtests/Replacement.scala b/src/main/scala/unittest/hwtests/Replacement.scala new file mode 100644 index 00000000000..c9ad8653f59 --- /dev/null +++ b/src/main/scala/unittest/hwtests/Replacement.scala @@ -0,0 +1,229 @@ +// See LICENSE.Berkeley for license details. +// See LICENSE.SiFive for license details. + +package freechips.rocketchip.unittest.hwtests + +import chisel3._ +import chisel3.util.log2Ceil +import chisel3.util.random.LFSR + +import org.chipsalliance.rocketutils.PseudoLRU +import org.chipsalliance.rocketutils.property.cover + +import freechips.rocketchip.unittest.UnitTest + +class PLRUTest(n_ways: Int, timeout: Int = 500) extends UnitTest(timeout) { + val plru = new PseudoLRU(n_ways) + + // step + io.finished := RegNext(true.B, false.B) + + val get_replace_ways = (0 until (1 << (n_ways-1))).map(state => + plru.get_replace_way(state = state.U((n_ways-1).W))) + val get_next_states = (0 until (1 << (n_ways-1))).map(state => (0 until n_ways).map(way => + plru.get_next_state (state = state.U((n_ways-1).W), touch_way = way.U(log2Ceil(n_ways).W)))) + + n_ways match { + case 2 => { + assert(get_replace_ways(0) === 0.U(log2Ceil(n_ways).W), s"get_replace_way state=0: expected=0 actual=%d", get_replace_ways(0)) + assert(get_replace_ways(1) === 1.U(log2Ceil(n_ways).W), s"get_replace_way state=1: expected=1 actual=%d", get_replace_ways(1)) + assert(get_next_states(0)(0) === 1.U(plru.nBits.W), s"get_next_state state=0 way=0: expected=1 actual=%d", get_next_states(0)(0)) + assert(get_next_states(0)(1) === 0.U(plru.nBits.W), s"get_next_state state=0 way=1: expected=0 actual=%d", get_next_states(0)(1)) + assert(get_next_states(1)(0) === 1.U(plru.nBits.W), s"get_next_state state=1 way=0: expected=1 actual=%d", get_next_states(1)(0)) + assert(get_next_states(1)(1) === 0.U(plru.nBits.W), s"get_next_state state=1 way=1: expected=0 actual=%d", get_next_states(1)(1)) + } + case 3 => { + assert(get_replace_ways(0) === 0.U(log2Ceil(n_ways).W), s"get_replace_way state=0: expected=0 actual=%d", get_replace_ways(0)) + assert(get_replace_ways(1) === 1.U(log2Ceil(n_ways).W), s"get_replace_way state=1: expected=1 actual=%d", get_replace_ways(1)) + assert(get_replace_ways(2) === 2.U(log2Ceil(n_ways).W), s"get_replace_way state=2: expected=2 actual=%d", get_replace_ways(2)) + assert(get_replace_ways(3) === 2.U(log2Ceil(n_ways).W), s"get_replace_way state=3: expected=2 actual=%d", get_replace_ways(3)) + assert(get_next_states(0)(0) === 3.U(plru.nBits.W), s"get_next_state state=0 way=0: expected=3 actual=%d", get_next_states(0)(0)) + assert(get_next_states(0)(1) === 2.U(plru.nBits.W), s"get_next_state state=0 way=1: expected=2 actual=%d", get_next_states(0)(1)) + assert(get_next_states(0)(2) === 0.U(plru.nBits.W), s"get_next_state state=0 way=2: expected=0 actual=%d", get_next_states(0)(2)) + assert(get_next_states(1)(0) === 3.U(plru.nBits.W), s"get_next_state state=1 way=0: expected=3 actual=%d", get_next_states(1)(0)) + assert(get_next_states(1)(1) === 2.U(plru.nBits.W), s"get_next_state state=1 way=1: expected=2 actual=%d", get_next_states(1)(1)) + assert(get_next_states(1)(2) === 1.U(plru.nBits.W), s"get_next_state state=1 way=2: expected=1 actual=%d", get_next_states(1)(2)) + assert(get_next_states(2)(0) === 3.U(plru.nBits.W), s"get_next_state state=2 way=0: expected=3 actual=%d", get_next_states(2)(0)) + assert(get_next_states(2)(1) === 2.U(plru.nBits.W), s"get_next_state state=2 way=1: expected=2 actual=%d", get_next_states(2)(1)) + assert(get_next_states(2)(2) === 0.U(plru.nBits.W), s"get_next_state state=2 way=2: expected=0 actual=%d", get_next_states(2)(2)) + assert(get_next_states(3)(0) === 3.U(plru.nBits.W), s"get_next_state state=3 way=0: expected=3 actual=%d", get_next_states(3)(0)) + assert(get_next_states(3)(1) === 2.U(plru.nBits.W), s"get_next_state state=3 way=1: expected=2 actual=%d", get_next_states(3)(1)) + assert(get_next_states(3)(2) === 1.U(plru.nBits.W), s"get_next_state state=3 way=2: expected=1 actual=%d", get_next_states(3)(2)) + } + case 4 => { + assert(get_replace_ways(0) === 0.U(log2Ceil(n_ways).W), s"get_replace_way state=0: expected=0 actual=%d", get_replace_ways(0)) + assert(get_replace_ways(1) === 1.U(log2Ceil(n_ways).W), s"get_replace_way state=1: expected=1 actual=%d", get_replace_ways(1)) + assert(get_replace_ways(2) === 0.U(log2Ceil(n_ways).W), s"get_replace_way state=2: expected=0 actual=%d", get_replace_ways(2)) + assert(get_replace_ways(3) === 1.U(log2Ceil(n_ways).W), s"get_replace_way state=3: expected=1 actual=%d", get_replace_ways(3)) + assert(get_replace_ways(4) === 2.U(log2Ceil(n_ways).W), s"get_replace_way state=4: expected=2 actual=%d", get_replace_ways(4)) + assert(get_replace_ways(5) === 2.U(log2Ceil(n_ways).W), s"get_replace_way state=5: expected=2 actual=%d", get_replace_ways(5)) + assert(get_replace_ways(6) === 3.U(log2Ceil(n_ways).W), s"get_replace_way state=6: expected=3 actual=%d", get_replace_ways(6)) + assert(get_replace_ways(7) === 3.U(log2Ceil(n_ways).W), s"get_replace_way state=7: expected=3 actual=%d", get_replace_ways(7)) + assert(get_next_states(0)(0) === 5.U(plru.nBits.W), s"get_next_state state=0 way=0: expected=5 actual=%d", get_next_states(0)(0)) + assert(get_next_states(0)(1) === 4.U(plru.nBits.W), s"get_next_state state=0 way=1: expected=4 actual=%d", get_next_states(0)(1)) + assert(get_next_states(0)(2) === 2.U(plru.nBits.W), s"get_next_state state=0 way=2: expected=2 actual=%d", get_next_states(0)(2)) + assert(get_next_states(0)(3) === 0.U(plru.nBits.W), s"get_next_state state=0 way=3: expected=0 actual=%d", get_next_states(0)(3)) + assert(get_next_states(1)(0) === 5.U(plru.nBits.W), s"get_next_state state=1 way=0: expected=5 actual=%d", get_next_states(1)(0)) + assert(get_next_states(1)(1) === 4.U(plru.nBits.W), s"get_next_state state=1 way=1: expected=4 actual=%d", get_next_states(1)(1)) + assert(get_next_states(1)(2) === 3.U(plru.nBits.W), s"get_next_state state=1 way=2: expected=3 actual=%d", get_next_states(1)(2)) + assert(get_next_states(1)(3) === 1.U(plru.nBits.W), s"get_next_state state=1 way=3: expected=1 actual=%d", get_next_states(1)(3)) + assert(get_next_states(2)(0) === 7.U(plru.nBits.W), s"get_next_state state=2 way=0: expected=7 actual=%d", get_next_states(2)(0)) + assert(get_next_states(2)(1) === 6.U(plru.nBits.W), s"get_next_state state=2 way=1: expected=6 actual=%d", get_next_states(2)(1)) + assert(get_next_states(2)(2) === 2.U(plru.nBits.W), s"get_next_state state=2 way=2: expected=2 actual=%d", get_next_states(2)(2)) + assert(get_next_states(2)(3) === 0.U(plru.nBits.W), s"get_next_state state=2 way=3: expected=0 actual=%d", get_next_states(2)(3)) + assert(get_next_states(3)(0) === 7.U(plru.nBits.W), s"get_next_state state=3 way=0: expected=7 actual=%d", get_next_states(3)(0)) + assert(get_next_states(3)(1) === 6.U(plru.nBits.W), s"get_next_state state=3 way=1: expected=6 actual=%d", get_next_states(3)(1)) + assert(get_next_states(3)(2) === 3.U(plru.nBits.W), s"get_next_state state=3 way=2: expected=3 actual=%d", get_next_states(3)(2)) + assert(get_next_states(3)(3) === 1.U(plru.nBits.W), s"get_next_state state=3 way=3: expected=1 actual=%d", get_next_states(3)(3)) + assert(get_next_states(4)(0) === 5.U(plru.nBits.W), s"get_next_state state=4 way=0: expected=5 actual=%d", get_next_states(4)(0)) + assert(get_next_states(4)(1) === 4.U(plru.nBits.W), s"get_next_state state=4 way=1: expected=4 actual=%d", get_next_states(4)(1)) + assert(get_next_states(4)(2) === 2.U(plru.nBits.W), s"get_next_state state=4 way=2: expected=2 actual=%d", get_next_states(4)(2)) + assert(get_next_states(4)(3) === 0.U(plru.nBits.W), s"get_next_state state=4 way=3: expected=0 actual=%d", get_next_states(4)(3)) + assert(get_next_states(5)(0) === 5.U(plru.nBits.W), s"get_next_state state=5 way=0: expected=5 actual=%d", get_next_states(5)(0)) + assert(get_next_states(5)(1) === 4.U(plru.nBits.W), s"get_next_state state=5 way=1: expected=4 actual=%d", get_next_states(5)(1)) + assert(get_next_states(5)(2) === 3.U(plru.nBits.W), s"get_next_state state=5 way=2: expected=3 actual=%d", get_next_states(5)(2)) + assert(get_next_states(5)(3) === 1.U(plru.nBits.W), s"get_next_state state=5 way=3: expected=1 actual=%d", get_next_states(5)(3)) + assert(get_next_states(6)(0) === 7.U(plru.nBits.W), s"get_next_state state=6 way=0: expected=7 actual=%d", get_next_states(6)(0)) + assert(get_next_states(6)(1) === 6.U(plru.nBits.W), s"get_next_state state=6 way=1: expected=6 actual=%d", get_next_states(6)(1)) + assert(get_next_states(6)(2) === 2.U(plru.nBits.W), s"get_next_state state=6 way=2: expected=2 actual=%d", get_next_states(6)(2)) + assert(get_next_states(6)(3) === 0.U(plru.nBits.W), s"get_next_state state=6 way=3: expected=0 actual=%d", get_next_states(6)(3)) + assert(get_next_states(7)(0) === 7.U(plru.nBits.W), s"get_next_state state=7 way=0: expected=7 actual=%d", get_next_states(7)(0)) + assert(get_next_states(7)(1) === 6.U(plru.nBits.W), s"get_next_state state=7 way=5: expected=6 actual=%d", get_next_states(7)(1)) + assert(get_next_states(7)(2) === 3.U(plru.nBits.W), s"get_next_state state=7 way=2: expected=3 actual=%d", get_next_states(7)(2)) + assert(get_next_states(7)(3) === 1.U(plru.nBits.W), s"get_next_state state=7 way=3: expected=1 actual=%d", get_next_states(7)(3)) + } + case 5 => { + assert(get_replace_ways( 0) === 0.U(log2Ceil(n_ways).W), s"get_replace_way state=00: expected=0 actual=%d", get_replace_ways( 0)) + assert(get_replace_ways( 1) === 1.U(log2Ceil(n_ways).W), s"get_replace_way state=01: expected=1 actual=%d", get_replace_ways( 1)) + assert(get_replace_ways( 2) === 0.U(log2Ceil(n_ways).W), s"get_replace_way state=02: expected=0 actual=%d", get_replace_ways( 2)) + assert(get_replace_ways( 3) === 1.U(log2Ceil(n_ways).W), s"get_replace_way state=03: expected=1 actual=%d", get_replace_ways( 3)) + assert(get_replace_ways( 4) === 2.U(log2Ceil(n_ways).W), s"get_replace_way state=04: expected=2 actual=%d", get_replace_ways( 4)) + assert(get_replace_ways( 5) === 2.U(log2Ceil(n_ways).W), s"get_replace_way state=05: expected=2 actual=%d", get_replace_ways( 5)) + assert(get_replace_ways( 6) === 3.U(log2Ceil(n_ways).W), s"get_replace_way state=06: expected=3 actual=%d", get_replace_ways( 6)) + assert(get_replace_ways( 7) === 3.U(log2Ceil(n_ways).W), s"get_replace_way state=07: expected=3 actual=%d", get_replace_ways( 7)) + assert(get_replace_ways( 8) === 4.U(log2Ceil(n_ways).W), s"get_replace_way state=08: expected=4 actual=%d", get_replace_ways( 8)) + assert(get_replace_ways( 9) === 4.U(log2Ceil(n_ways).W), s"get_replace_way state=09: expected=4 actual=%d", get_replace_ways( 9)) + assert(get_replace_ways(10) === 4.U(log2Ceil(n_ways).W), s"get_replace_way state=10: expected=4 actual=%d", get_replace_ways(10)) + assert(get_replace_ways(11) === 4.U(log2Ceil(n_ways).W), s"get_replace_way state=11: expected=4 actual=%d", get_replace_ways(11)) + assert(get_replace_ways(12) === 4.U(log2Ceil(n_ways).W), s"get_replace_way state=12: expected=4 actual=%d", get_replace_ways(12)) + assert(get_replace_ways(13) === 4.U(log2Ceil(n_ways).W), s"get_replace_way state=13: expected=4 actual=%d", get_replace_ways(13)) + assert(get_replace_ways(14) === 4.U(log2Ceil(n_ways).W), s"get_replace_way state=14: expected=4 actual=%d", get_replace_ways(14)) + assert(get_replace_ways(15) === 4.U(log2Ceil(n_ways).W), s"get_replace_way state=15: expected=4 actual=%d", get_replace_ways(15)) + assert(get_next_states( 0)(0) === 13.U(plru.nBits.W), s"get_next_state state=00 way=0: expected=13 actual=%d", get_next_states( 0)(0)) + assert(get_next_states( 0)(1) === 12.U(plru.nBits.W), s"get_next_state state=00 way=1: expected=12 actual=%d", get_next_states( 0)(1)) + assert(get_next_states( 0)(2) === 10.U(plru.nBits.W), s"get_next_state state=00 way=2: expected=10 actual=%d", get_next_states( 0)(2)) + assert(get_next_states( 0)(3) === 8.U(plru.nBits.W), s"get_next_state state=00 way=3: expected=08 actual=%d", get_next_states( 0)(3)) + assert(get_next_states( 0)(4) === 0.U(plru.nBits.W), s"get_next_state state=00 way=4: expected=00 actual=%d", get_next_states( 0)(4)) + assert(get_next_states( 1)(0) === 13.U(plru.nBits.W), s"get_next_state state=01 way=0: expected=13 actual=%d", get_next_states( 1)(0)) + assert(get_next_states( 1)(1) === 12.U(plru.nBits.W), s"get_next_state state=01 way=1: expected=12 actual=%d", get_next_states( 1)(1)) + assert(get_next_states( 1)(2) === 11.U(plru.nBits.W), s"get_next_state state=01 way=2: expected=11 actual=%d", get_next_states( 1)(2)) + assert(get_next_states( 1)(3) === 9.U(plru.nBits.W), s"get_next_state state=01 way=3: expected=09 actual=%d", get_next_states( 1)(3)) + assert(get_next_states( 1)(4) === 1.U(plru.nBits.W), s"get_next_state state=01 way=4: expected=01 actual=%d", get_next_states( 1)(4)) + assert(get_next_states( 2)(0) === 15.U(plru.nBits.W), s"get_next_state state=02 way=0: expected=15 actual=%d", get_next_states( 2)(0)) + assert(get_next_states( 2)(1) === 14.U(plru.nBits.W), s"get_next_state state=02 way=1: expected=14 actual=%d", get_next_states( 2)(1)) + assert(get_next_states( 2)(2) === 10.U(plru.nBits.W), s"get_next_state state=02 way=2: expected=10 actual=%d", get_next_states( 2)(2)) + assert(get_next_states( 2)(3) === 8.U(plru.nBits.W), s"get_next_state state=02 way=3: expected=08 actual=%d", get_next_states( 2)(3)) + assert(get_next_states( 2)(4) === 2.U(plru.nBits.W), s"get_next_state state=02 way=4: expected=02 actual=%d", get_next_states( 2)(4)) + assert(get_next_states( 3)(0) === 15.U(plru.nBits.W), s"get_next_state state=03 way=0: expected=15 actual=%d", get_next_states( 3)(0)) + assert(get_next_states( 3)(1) === 14.U(plru.nBits.W), s"get_next_state state=03 way=1: expected=14 actual=%d", get_next_states( 3)(1)) + assert(get_next_states( 3)(2) === 11.U(plru.nBits.W), s"get_next_state state=03 way=2: expected=11 actual=%d", get_next_states( 3)(2)) + assert(get_next_states( 3)(3) === 9.U(plru.nBits.W), s"get_next_state state=03 way=3: expected=09 actual=%d", get_next_states( 3)(3)) + assert(get_next_states( 3)(4) === 3.U(plru.nBits.W), s"get_next_state state=03 way=4: expected=03 actual=%d", get_next_states( 3)(4)) + assert(get_next_states( 4)(0) === 13.U(plru.nBits.W), s"get_next_state state=04 way=0: expected=13 actual=%d", get_next_states( 4)(0)) + assert(get_next_states( 4)(1) === 12.U(plru.nBits.W), s"get_next_state state=04 way=1: expected=12 actual=%d", get_next_states( 4)(1)) + assert(get_next_states( 4)(2) === 10.U(plru.nBits.W), s"get_next_state state=04 way=2: expected=10 actual=%d", get_next_states( 4)(2)) + assert(get_next_states( 4)(3) === 8.U(plru.nBits.W), s"get_next_state state=04 way=3: expected=08 actual=%d", get_next_states( 4)(3)) + assert(get_next_states( 4)(4) === 4.U(plru.nBits.W), s"get_next_state state=04 way=4: expected=04 actual=%d", get_next_states( 4)(4)) + assert(get_next_states( 5)(0) === 13.U(plru.nBits.W), s"get_next_state state=05 way=0: expected=13 actual=%d", get_next_states( 5)(0)) + assert(get_next_states( 5)(1) === 12.U(plru.nBits.W), s"get_next_state state=05 way=1: expected=12 actual=%d", get_next_states( 5)(1)) + assert(get_next_states( 5)(2) === 11.U(plru.nBits.W), s"get_next_state state=05 way=2: expected=11 actual=%d", get_next_states( 5)(2)) + assert(get_next_states( 5)(3) === 9.U(plru.nBits.W), s"get_next_state state=05 way=3: expected=09 actual=%d", get_next_states( 5)(3)) + assert(get_next_states( 5)(4) === 5.U(plru.nBits.W), s"get_next_state state=05 way=4: expected=05 actual=%d", get_next_states( 5)(4)) + assert(get_next_states( 6)(0) === 15.U(plru.nBits.W), s"get_next_state state=06 way=0: expected=15 actual=%d", get_next_states( 6)(0)) + assert(get_next_states( 6)(1) === 14.U(plru.nBits.W), s"get_next_state state=06 way=1: expected=14 actual=%d", get_next_states( 6)(1)) + assert(get_next_states( 6)(2) === 10.U(plru.nBits.W), s"get_next_state state=06 way=2: expected=10 actual=%d", get_next_states( 6)(2)) + assert(get_next_states( 6)(3) === 8.U(plru.nBits.W), s"get_next_state state=06 way=3: expected=08 actual=%d", get_next_states( 6)(3)) + assert(get_next_states( 6)(4) === 6.U(plru.nBits.W), s"get_next_state state=06 way=4: expected=06 actual=%d", get_next_states( 6)(4)) + assert(get_next_states( 7)(0) === 15.U(plru.nBits.W), s"get_next_state state=07 way=0: expected=15 actual=%d", get_next_states( 7)(0)) + assert(get_next_states( 7)(1) === 14.U(plru.nBits.W), s"get_next_state state=07 way=5: expected=14 actual=%d", get_next_states( 7)(1)) + assert(get_next_states( 7)(2) === 11.U(plru.nBits.W), s"get_next_state state=07 way=2: expected=11 actual=%d", get_next_states( 7)(2)) + assert(get_next_states( 7)(3) === 9.U(plru.nBits.W), s"get_next_state state=07 way=3: expected=09 actual=%d", get_next_states( 7)(3)) + assert(get_next_states( 7)(4) === 7.U(plru.nBits.W), s"get_next_state state=07 way=4: expected=07 actual=%d", get_next_states( 7)(4)) + assert(get_next_states( 8)(0) === 13.U(plru.nBits.W), s"get_next_state state=08 way=0: expected=13 actual=%d", get_next_states( 8)(0)) + assert(get_next_states( 8)(1) === 12.U(plru.nBits.W), s"get_next_state state=08 way=1: expected=12 actual=%d", get_next_states( 8)(1)) + assert(get_next_states( 8)(2) === 10.U(plru.nBits.W), s"get_next_state state=08 way=2: expected=10 actual=%d", get_next_states( 8)(2)) + assert(get_next_states( 8)(3) === 8.U(plru.nBits.W), s"get_next_state state=08 way=3: expected=08 actual=%d", get_next_states( 8)(3)) + assert(get_next_states( 8)(4) === 0.U(plru.nBits.W), s"get_next_state state=08 way=4: expected=00 actual=%d", get_next_states( 8)(4)) + assert(get_next_states( 9)(0) === 13.U(plru.nBits.W), s"get_next_state state=09 way=0: expected=13 actual=%d", get_next_states( 9)(0)) + assert(get_next_states( 9)(1) === 12.U(plru.nBits.W), s"get_next_state state=09 way=1: expected=12 actual=%d", get_next_states( 9)(1)) + assert(get_next_states( 9)(2) === 11.U(plru.nBits.W), s"get_next_state state=09 way=2: expected=11 actual=%d", get_next_states( 9)(2)) + assert(get_next_states( 9)(3) === 9.U(plru.nBits.W), s"get_next_state state=09 way=3: expected=09 actual=%d", get_next_states( 9)(3)) + assert(get_next_states( 9)(4) === 1.U(plru.nBits.W), s"get_next_state state=09 way=4: expected=01 actual=%d", get_next_states( 9)(4)) + assert(get_next_states(10)(0) === 15.U(plru.nBits.W), s"get_next_state state=10 way=0: expected=15 actual=%d", get_next_states(10)(0)) + assert(get_next_states(10)(1) === 14.U(plru.nBits.W), s"get_next_state state=10 way=1: expected=14 actual=%d", get_next_states(10)(1)) + assert(get_next_states(10)(2) === 10.U(plru.nBits.W), s"get_next_state state=10 way=2: expected=10 actual=%d", get_next_states(10)(2)) + assert(get_next_states(10)(3) === 8.U(plru.nBits.W), s"get_next_state state=10 way=3: expected=08 actual=%d", get_next_states(10)(3)) + assert(get_next_states(10)(4) === 2.U(plru.nBits.W), s"get_next_state state=10 way=4: expected=02 actual=%d", get_next_states(10)(4)) + assert(get_next_states(11)(0) === 15.U(plru.nBits.W), s"get_next_state state=11 way=0: expected=15 actual=%d", get_next_states(11)(0)) + assert(get_next_states(11)(1) === 14.U(plru.nBits.W), s"get_next_state state=11 way=1: expected=14 actual=%d", get_next_states(11)(1)) + assert(get_next_states(11)(2) === 11.U(plru.nBits.W), s"get_next_state state=11 way=2: expected=11 actual=%d", get_next_states(11)(2)) + assert(get_next_states(11)(3) === 9.U(plru.nBits.W), s"get_next_state state=11 way=3: expected=09 actual=%d", get_next_states(11)(3)) + assert(get_next_states(11)(4) === 3.U(plru.nBits.W), s"get_next_state state=11 way=4: expected=03 actual=%d", get_next_states(11)(4)) + assert(get_next_states(12)(0) === 13.U(plru.nBits.W), s"get_next_state state=12 way=0: expected=13 actual=%d", get_next_states(12)(0)) + assert(get_next_states(12)(1) === 12.U(plru.nBits.W), s"get_next_state state=12 way=1: expected=12 actual=%d", get_next_states(12)(1)) + assert(get_next_states(12)(2) === 10.U(plru.nBits.W), s"get_next_state state=12 way=2: expected=10 actual=%d", get_next_states(12)(2)) + assert(get_next_states(12)(3) === 8.U(plru.nBits.W), s"get_next_state state=12 way=3: expected=08 actual=%d", get_next_states(12)(3)) + assert(get_next_states(12)(4) === 4.U(plru.nBits.W), s"get_next_state state=12 way=4: expected=04 actual=%d", get_next_states(12)(4)) + assert(get_next_states(13)(0) === 13.U(plru.nBits.W), s"get_next_state state=13 way=0: expected=13 actual=%d", get_next_states(13)(0)) + assert(get_next_states(13)(1) === 12.U(plru.nBits.W), s"get_next_state state=13 way=1: expected=12 actual=%d", get_next_states(13)(1)) + assert(get_next_states(13)(2) === 11.U(plru.nBits.W), s"get_next_state state=13 way=2: expected=11 actual=%d", get_next_states(13)(2)) + assert(get_next_states(13)(3) === 9.U(plru.nBits.W), s"get_next_state state=13 way=3: expected=09 actual=%d", get_next_states(13)(3)) + assert(get_next_states(13)(4) === 5.U(plru.nBits.W), s"get_next_state state=13 way=4: expected=05 actual=%d", get_next_states(13)(4)) + assert(get_next_states(14)(0) === 15.U(plru.nBits.W), s"get_next_state state=14 way=0: expected=15 actual=%d", get_next_states(14)(0)) + assert(get_next_states(14)(1) === 14.U(plru.nBits.W), s"get_next_state state=14 way=1: expected=14 actual=%d", get_next_states(14)(1)) + assert(get_next_states(14)(2) === 10.U(plru.nBits.W), s"get_next_state state=14 way=2: expected=10 actual=%d", get_next_states(14)(2)) + assert(get_next_states(14)(3) === 8.U(plru.nBits.W), s"get_next_state state=14 way=3: expected=08 actual=%d", get_next_states(14)(3)) + assert(get_next_states(14)(4) === 6.U(plru.nBits.W), s"get_next_state state=14 way=4: expected=06 actual=%d", get_next_states(14)(4)) + assert(get_next_states(15)(0) === 15.U(plru.nBits.W), s"get_next_state state=15 way=0: expected=15 actual=%d", get_next_states(15)(0)) + assert(get_next_states(15)(1) === 14.U(plru.nBits.W), s"get_next_state state=15 way=5: expected=14 actual=%d", get_next_states(15)(1)) + assert(get_next_states(15)(2) === 11.U(plru.nBits.W), s"get_next_state state=15 way=2: expected=11 actual=%d", get_next_states(15)(2)) + assert(get_next_states(15)(3) === 9.U(plru.nBits.W), s"get_next_state state=15 way=3: expected=09 actual=%d", get_next_states(15)(3)) + assert(get_next_states(15)(4) === 7.U(plru.nBits.W), s"get_next_state state=15 way=4: expected=07 actual=%d", get_next_states(15)(4)) + } + case 6 => { + assert(get_replace_ways( 0) === 0.U(log2Ceil(n_ways).W), s"get_replace_way state=00: expected=0 actual=%d", get_replace_ways( 0)) + assert(get_replace_ways( 1) === 1.U(log2Ceil(n_ways).W), s"get_replace_way state=01: expected=1 actual=%d", get_replace_ways( 1)) + assert(get_replace_ways( 2) === 0.U(log2Ceil(n_ways).W), s"get_replace_way state=02: expected=0 actual=%d", get_replace_ways( 2)) + assert(get_replace_ways( 3) === 1.U(log2Ceil(n_ways).W), s"get_replace_way state=03: expected=1 actual=%d", get_replace_ways( 3)) + assert(get_replace_ways( 4) === 2.U(log2Ceil(n_ways).W), s"get_replace_way state=04: expected=2 actual=%d", get_replace_ways( 4)) + assert(get_replace_ways( 5) === 2.U(log2Ceil(n_ways).W), s"get_replace_way state=05: expected=2 actual=%d", get_replace_ways( 5)) + assert(get_replace_ways( 6) === 3.U(log2Ceil(n_ways).W), s"get_replace_way state=06: expected=3 actual=%d", get_replace_ways( 6)) + assert(get_replace_ways( 7) === 3.U(log2Ceil(n_ways).W), s"get_replace_way state=07: expected=3 actual=%d", get_replace_ways( 7)) + assert(get_replace_ways( 8) === 0.U(log2Ceil(n_ways).W), s"get_replace_way state=08: expected=0 actual=%d", get_replace_ways( 8)) + assert(get_replace_ways( 9) === 1.U(log2Ceil(n_ways).W), s"get_replace_way state=09: expected=1 actual=%d", get_replace_ways( 9)) + assert(get_replace_ways(10) === 0.U(log2Ceil(n_ways).W), s"get_replace_way state=10: expected=0 actual=%d", get_replace_ways(10)) + assert(get_replace_ways(11) === 1.U(log2Ceil(n_ways).W), s"get_replace_way state=11: expected=1 actual=%d", get_replace_ways(11)) + assert(get_replace_ways(12) === 2.U(log2Ceil(n_ways).W), s"get_replace_way state=12: expected=2 actual=%d", get_replace_ways(12)) + assert(get_replace_ways(13) === 2.U(log2Ceil(n_ways).W), s"get_replace_way state=13: expected=2 actual=%d", get_replace_ways(13)) + assert(get_replace_ways(14) === 3.U(log2Ceil(n_ways).W), s"get_replace_way state=14: expected=3 actual=%d", get_replace_ways(14)) + assert(get_replace_ways(15) === 3.U(log2Ceil(n_ways).W), s"get_replace_way state=15: expected=3 actual=%d", get_replace_ways(15)) + assert(get_replace_ways(16) === 4.U(log2Ceil(n_ways).W), s"get_replace_way state=16: expected=4 actual=%d", get_replace_ways(16)) + assert(get_replace_ways(17) === 4.U(log2Ceil(n_ways).W), s"get_replace_way state=17: expected=4 actual=%d", get_replace_ways(17)) + assert(get_replace_ways(18) === 4.U(log2Ceil(n_ways).W), s"get_replace_way state=18: expected=4 actual=%d", get_replace_ways(18)) + assert(get_replace_ways(19) === 4.U(log2Ceil(n_ways).W), s"get_replace_way state=19: expected=4 actual=%d", get_replace_ways(19)) + assert(get_replace_ways(20) === 4.U(log2Ceil(n_ways).W), s"get_replace_way state=20: expected=4 actual=%d", get_replace_ways(20)) + assert(get_replace_ways(21) === 4.U(log2Ceil(n_ways).W), s"get_replace_way state=21: expected=4 actual=%d", get_replace_ways(21)) + assert(get_replace_ways(22) === 4.U(log2Ceil(n_ways).W), s"get_replace_way state=22: expected=4 actual=%d", get_replace_ways(22)) + assert(get_replace_ways(23) === 4.U(log2Ceil(n_ways).W), s"get_replace_way state=23: expected=4 actual=%d", get_replace_ways(23)) + assert(get_replace_ways(24) === 5.U(log2Ceil(n_ways).W), s"get_replace_way state=24: expected=5 actual=%d", get_replace_ways(24)) + assert(get_replace_ways(25) === 5.U(log2Ceil(n_ways).W), s"get_replace_way state=25: expected=5 actual=%d", get_replace_ways(25)) + assert(get_replace_ways(26) === 5.U(log2Ceil(n_ways).W), s"get_replace_way state=26: expected=5 actual=%d", get_replace_ways(26)) + assert(get_replace_ways(27) === 5.U(log2Ceil(n_ways).W), s"get_replace_way state=27: expected=5 actual=%d", get_replace_ways(27)) + assert(get_replace_ways(28) === 5.U(log2Ceil(n_ways).W), s"get_replace_way state=28: expected=5 actual=%d", get_replace_ways(28)) + assert(get_replace_ways(29) === 5.U(log2Ceil(n_ways).W), s"get_replace_way state=29: expected=5 actual=%d", get_replace_ways(29)) + assert(get_replace_ways(30) === 5.U(log2Ceil(n_ways).W), s"get_replace_way state=30: expected=5 actual=%d", get_replace_ways(30)) + assert(get_replace_ways(31) === 5.U(log2Ceil(n_ways).W), s"get_replace_way state=31: expected=5 actual=%d", get_replace_ways(31)) + } + case _ => throw new IllegalArgumentException(s"no test pattern found for n_ways=$n_ways") + } +} diff --git a/src/main/scala/unittest/hwtests/ScatterGather.scala b/src/main/scala/unittest/hwtests/ScatterGather.scala new file mode 100644 index 00000000000..dea76c64026 --- /dev/null +++ b/src/main/scala/unittest/hwtests/ScatterGather.scala @@ -0,0 +1,46 @@ +// See LICENSE.SiFive for license details. + +package freechips.rocketchip.unittest.hwtests + +import chisel3._ +import chisel3.util.{log2Ceil, PopCount, Valid} + +import org.chipsalliance.rocketutils.{Scatter, Gather, RipplePrefixSum} + +import freechips.rocketchip.unittest.UnitTest + +class GatherTest(size: Int, timeout: Int = 500000) extends UnitTest(timeout) { + val bits = log2Ceil(size+1) + val mask = RegInit(0.U(size.W)) + io.finished := mask.andR + mask := mask + !io.finished + + // Put 0, 1, 2, 3 ... at all of the lanes with mask=1 + val sum = RipplePrefixSum(0.U(bits.W) +: mask.asBools.map { x => WireInit(UInt(bits.W), x) })(_+_) + val input = Wire(Vec(size, Valid(UInt(bits.W)))) + for (i <- 0 until size) { + input(i).valid := mask(i) + input(i).bits := Mux(mask(i), sum(i), sum.last) + } + + val output = Gather(input) + val total = PopCount(mask) + for (i <- 0 until size) assert (i.U >= total || output(i) === i.U) +} + +class ScatterTest(size: Int, timeout: Int = 500000) extends UnitTest(timeout) { + val bits = log2Ceil(size+1) + val mask = RegInit(0.U(size.W)) + io.finished := mask.andR + mask := mask + !io.finished + + val input = Wire(Vec(size, Valid(UInt(bits.W)))) + for (i <- 0 until size) { + input(i).valid := mask(i) + input(i).bits := i.U + } + + val output = Scatter(input) + val sum = RipplePrefixSum(0.U(bits.W) +: mask.asBools.map { x => WireInit(UInt(bits.W), x) })(_+_) + for (i <- 0 until size) assert (!mask(i) || output(i) === sum(i)) +} diff --git a/src/main/scala/util/Annotations.scala b/src/main/scala/util/Annotations.scala index 851571ba46e..c170f0e9d4e 100644 --- a/src/main/scala/util/Annotations.scala +++ b/src/main/scala/util/Annotations.scala @@ -7,8 +7,6 @@ import chisel3.experimental.{annotate, ChiselAnnotation} import firrtl.annotations._ -import org.chipsalliance.diplomacy - import freechips.rocketchip.diplomacy.{AddressRange, AddressSet} import freechips.rocketchip.resources.{AddressMapEntry, ResourcePermissions} import freechips.rocketchip.regmapper.{RegField, RegFieldDescSer, RegistersSer} @@ -17,6 +15,7 @@ import org.json4s.JsonDSL._ import org.json4s.jackson.JsonMethods.{pretty, render} /** Record a sram. */ +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") case class SRAMAnnotation(target: Named, address_width: Int, name: String, @@ -28,24 +27,29 @@ case class SRAMAnnotation(target: Named, } /** Record a set of interrupts. */ +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") case class InterruptsPortAnnotation(target: Named, name: String, interruptIndexes: Seq[Int]) extends SingleTargetAnnotation[Named] { def duplicate(n: Named) = this.copy(n) } /** Record a case class that was used to parameterize this target. */ +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") case class GlobalConstantsAnnotation(target: Named, xLen: Int) extends SingleTargetAnnotation[Named] { def duplicate(n: Named) = this.copy(n) } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") case class GlobalConstantsChiselAnnotation[T <: Product](target: InstanceId, xLen: Int) extends ChiselAnnotation { def toFirrtl = GlobalConstantsAnnotation(target.toNamed, xLen) } /** Record a case class that was used to parameterize this target. */ +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") case class ParamsAnnotation(target: Named, paramsClassName: String, params: Map[String,Any]) extends SingleTargetAnnotation[Named] { def duplicate(n: Named) = this.copy(n) } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") case class ParamsChiselAnnotation[T <: Product](target: InstanceId, params: T) extends ChiselAnnotation { private val paramMap = params.getClass.getDeclaredFields.map(_.getName).zip(params.productIterator).toMap def toFirrtl = ParamsAnnotation(target.toNamed, params.getClass.getName, paramMap) @@ -66,6 +70,7 @@ case class AddressMapAnnotation(target: Named, mapping: Seq[AddressMapEntry], la } /** Marks this module as a candidate for register retiming */ +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") case class RetimeModuleAnnotation(target: ModuleName) extends SingleTargetAnnotation[ModuleName] { def duplicate(n: ModuleName) = this.copy(n) } @@ -94,13 +99,15 @@ case class TopLevelPortAnnotation( } /** Record the resetVector. */ +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") case class ResetVectorAnnotation(target: Named, resetVec: BigInt) extends SingleTargetAnnotation[Named] { def duplicate(n: Named): ResetVectorAnnotation = this.copy(n) } /** Helper object containing methods for applying annotations to targets */ object Annotated { - + + @deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") def srams( component: InstanceId, name: String, @@ -119,6 +126,7 @@ object Annotated { write_mask_granularity = write_mask_granularity )})} + @deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") def interrupts(component: InstanceId, name: String, interrupts: Seq[Int]): Unit = { annotate(new ChiselAnnotation {def toFirrtl: Annotation = InterruptsPortAnnotation( component.toNamed, @@ -127,14 +135,17 @@ object Annotated { )}) } + @deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") def resetVector(component: InstanceId, resetVec: BigInt): Unit = { annotate(new ChiselAnnotation {def toFirrtl: Annotation = ResetVectorAnnotation(component.toNamed, resetVec)}) } + @deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") def constants(component: InstanceId, xLen: Int): Unit = { annotate(GlobalConstantsChiselAnnotation(component, xLen )) } + @deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") def params[T <: Product](component: InstanceId, params: T): T = { annotate(ParamsChiselAnnotation(component, params)) params @@ -145,6 +156,7 @@ object Annotated { mapping } + @deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") def port[T <: Data]( data: T, protocol: String, @@ -158,6 +170,7 @@ object Annotated { } /** Mix this into a Module class or instance to mark its ports as untouchable */ +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") trait DontTouch { self: RawModule => // TODO: replace this with an implicit class from UserModule that uses getPorts // TODO: this is a workaround for firrtl #756 @@ -183,6 +196,7 @@ trait DontTouch { self: RawModule => } /** Mix this into a Module class or instance to mark it for register retiming */ +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") trait ShouldBeRetimed { self: RawModule => chisel3.experimental.annotate(new ChiselAnnotation { def toFirrtl: RetimeModuleAnnotation = RetimeModuleAnnotation(self.toNamed) }) } diff --git a/src/main/scala/util/Arbiters.scala b/src/main/scala/util/Arbiters.scala index 00a32d3b950..ce427a7acb0 100644 --- a/src/main/scala/util/Arbiters.scala +++ b/src/main/scala/util/Arbiters.scala @@ -8,6 +8,7 @@ import org.chipsalliance.cde.config.Parameters /** A generalized locking RR arbiter that addresses the limitations of the * version in the Chisel standard library */ +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") abstract class HellaLockingArbiter[T <: Data](typ: T, arbN: Int, rr: Boolean = false) extends Module { @@ -46,6 +47,7 @@ abstract class HellaLockingArbiter[T <: Data](typ: T, arbN: Int, rr: Boolean = f /** This locking arbiter determines when it is safe to unlock * by peeking at the data */ +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class HellaPeekingArbiter[T <: Data]( typ: T, arbN: Int, canUnlock: T => Bool, @@ -69,6 +71,7 @@ class HellaPeekingArbiter[T <: Data]( } /** This arbiter determines when it is safe to unlock by counting transactions */ +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class HellaCountingArbiter[T <: Data]( typ: T, arbN: Int, count: Int, val needsLock: Option[T => Bool] = None, @@ -97,6 +100,7 @@ class HellaCountingArbiter[T <: Data]( } /** This arbiter preserves the order of responses */ +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class InOrderArbiter[T <: Data, U <: Data](reqTyp: T, respTyp: U, n: Int) (implicit p: Parameters) extends Module { val io = IO(new Bundle { diff --git a/src/main/scala/util/AsyncQueue.scala b/src/main/scala/util/AsyncQueue.scala index a7332358c56..cf0f8e1c1ef 100644 --- a/src/main/scala/util/AsyncQueue.scala +++ b/src/main/scala/util/AsyncQueue.scala @@ -5,6 +5,7 @@ package freechips.rocketchip.util import chisel3._ import chisel3.util._ +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") case class AsyncQueueParams( depth: Int = 8, sync: Int = 3, @@ -23,11 +24,13 @@ case class AsyncQueueParams( val wires = if (narrow) 1 else depth } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object AsyncQueueParams { // When there is only one entry, we don't need narrow. def singleton(sync: Int = 3, safe: Boolean = true) = AsyncQueueParams(1, sync, safe, false) } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class AsyncBundleSafety extends Bundle { val ridx_valid = Input (Bool()) val widx_valid = Output(Bool()) @@ -35,6 +38,7 @@ class AsyncBundleSafety extends Bundle { val sink_reset_n = Input (Bool()) } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class AsyncBundle[T <: Data](private val gen: T, val params: AsyncQueueParams = AsyncQueueParams()) extends Bundle { // Data-path synchronization val mem = Output(Vec(params.wires, gen)) @@ -46,6 +50,7 @@ class AsyncBundle[T <: Data](private val gen: T, val params: AsyncQueueParams = val safe = params.safe.option(new AsyncBundleSafety) } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object GrayCounter { def apply(bits: Int, increment: Bool = true.B, clear: Bool = false.B, name: String = "binary"): UInt = { val incremented = Wire(UInt(bits.W)) @@ -55,6 +60,7 @@ object GrayCounter { } } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class AsyncValidSync(sync: Int, desc: String) extends RawModule { val io = IO(new Bundle { val in = Input(Bool()) @@ -67,6 +73,7 @@ class AsyncValidSync(sync: Int, desc: String) extends RawModule { } } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class AsyncQueueSource[T <: Data](gen: T, params: AsyncQueueParams = AsyncQueueParams()) extends Module { val io = IO(new Bundle { // These come from the source domain @@ -131,6 +138,7 @@ class AsyncQueueSource[T <: Data](gen: T, params: AsyncQueueParams = AsyncQueueP } } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class AsyncQueueSink[T <: Data](gen: T, params: AsyncQueueParams = AsyncQueueParams()) extends Module { val io = IO(new Bundle { // These come from the sink domain @@ -199,6 +207,7 @@ class AsyncQueueSink[T <: Data](gen: T, params: AsyncQueueParams = AsyncQueuePar } } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object FromAsyncBundle { // Sometimes it makes sense for the sink to have different sync than the source @@ -210,6 +219,7 @@ object FromAsyncBundle } } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object ToAsyncBundle { def apply[T <: Data](x: ReadyValidIO[T], params: AsyncQueueParams = AsyncQueueParams()): AsyncBundle[T] = { @@ -219,6 +229,7 @@ object ToAsyncBundle } } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class AsyncQueue[T <: Data](gen: T, params: AsyncQueueParams = AsyncQueueParams()) extends Crossing[T] { val io = IO(new CrossingIO(gen)) val source = withClockAndReset(io.enq_clock, io.enq_reset) { Module(new AsyncQueueSource(gen, params)) } diff --git a/src/main/scala/util/AsyncResetReg.scala b/src/main/scala/util/AsyncResetReg.scala index a687115d157..1b7986c6a9a 100644 --- a/src/main/scala/util/AsyncResetReg.scala +++ b/src/main/scala/util/AsyncResetReg.scala @@ -30,6 +30,7 @@ import chisel3._ * */ +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class AsyncResetReg(resetValue: Int = 0) extends RawModule { val io = IO(new Bundle { val d = Input(Bool()) @@ -47,12 +48,14 @@ class AsyncResetReg(resetValue: Int = 0) extends RawModule { io.q := reg } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class SimpleRegIO(val w: Int) extends Bundle{ val d = Input(UInt(w.W)) val q = Output(UInt(w.W)) val en = Input(Bool()) } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class AsyncResetRegVec(val w: Int, val init: BigInt) extends Module { override def desiredName = s"AsyncResetRegVec_w${w}_i${init}" @@ -65,6 +68,7 @@ class AsyncResetRegVec(val w: Int, val init: BigInt) extends Module { io.q := reg } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object AsyncResetReg { // Create Single Registers def apply(d: Bool, clk: Clock, rst: Bool, init: Boolean, name: Option[String]): Bool = { diff --git a/src/main/scala/util/BarrelShifter.scala b/src/main/scala/util/BarrelShifter.scala index e69de29bb2d..90272ebc93c 100644 --- a/src/main/scala/util/BarrelShifter.scala +++ b/src/main/scala/util/BarrelShifter.scala @@ -0,0 +1,3 @@ +package util + + diff --git a/src/main/scala/util/BlockDuringReset.scala b/src/main/scala/util/BlockDuringReset.scala index 2d33d5484e6..8c8e885a75c 100644 --- a/src/main/scala/util/BlockDuringReset.scala +++ b/src/main/scala/util/BlockDuringReset.scala @@ -6,13 +6,16 @@ import chisel3._ import chisel3.util.{Counter, RegEnable} /** Blocks transactions until the cycle after reset. */ +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object BlockDuringReset { + @deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") private def outOfReset(stretchCycles: Int): Bool = stretchCycles match { case 0 => RegNext(true.B, false.B) case i => RegEnable(true.B, false.B, Counter(true.B, i)._2) } + @deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") def apply[T <: Data : Blockable](data: T, stretchCycles: Int = 0): T = { implicitly[Blockable[T]].blockWhile(!outOfReset(stretchCycles), data) } diff --git a/src/main/scala/util/Blockable.scala b/src/main/scala/util/Blockable.scala index 3b96995dcf7..72a616ff179 100644 --- a/src/main/scala/util/Blockable.scala +++ b/src/main/scala/util/Blockable.scala @@ -4,21 +4,25 @@ package freechips.rocketchip.util import chisel3._ import chisel3.util.DecoupledIO -import freechips.rocketchip.tile.{TraceBundle} -import freechips.rocketchip.rocket.{TracedInstruction} -/** A trait supplying a function allowing the contents of data - * to be supressed for a time period, i.e. be blocked. - */ +import org.chipsalliance.rocketutils + +import freechips.rocketchip.tile.TraceBundle +import freechips.rocketchip.rocket.TracedInstruction + +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") trait Blockable[T <: Data] { def blockWhile(enable_blocking: Bool, data: T): T } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object Blockable { + @deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") implicit object BlockableBool extends Blockable[Bool] { def blockWhile(enable_blocking: Bool, x: Bool): Bool = x && !enable_blocking } + @deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") implicit def BlockableDataCanBeValid[T <: DataCanBeValid]: Blockable[T] = new Blockable[T] { def blockWhile(enable_blocking: Bool, data: T): T = { val blocked: T = Wire(chiselTypeOf(data)) @@ -28,6 +32,7 @@ object Blockable { } } + @deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") implicit def BlockableDecoupled[T <: Data]: Blockable[DecoupledIO[T]] = new Blockable[DecoupledIO[T]] { def blockWhile(enable_blocking: Bool, data: DecoupledIO[T]): DecoupledIO[T] = { val res = Wire(chiselTypeOf(data)) @@ -42,6 +47,7 @@ object Blockable { } } + @deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") implicit def BlockableCredited[T <: Data]: Blockable[CreditedIO[T]] = new Blockable[CreditedIO[T]] { def blockWhile(enable_blocking: Bool, data: CreditedIO[T]): CreditedIO[T] = { val res = Wire(chiselTypeOf(data)) @@ -56,12 +62,14 @@ object Blockable { } } + @deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") implicit def BlockableVec[T <: Data : Blockable]: Blockable[Vec[T]] = new Blockable[Vec[T]] { def blockWhile(enable_blocking: Bool, data: Vec[T]): Vec[T] = { VecInit(data.map(x => implicitly[Blockable[T]].blockWhile(enable_blocking, x))) } } + @deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") implicit object BlockableTraceCoreInterface extends Blockable[TraceCoreInterface] { def blockWhile(enable_blocking: Bool, data: TraceCoreInterface): TraceCoreInterface = { val blocked: TraceCoreInterface = Wire(chiselTypeOf(data)) @@ -75,11 +83,14 @@ object Blockable { blocked } } +} - implicit object BlockableTraceBundle extends Blockable[TraceBundle] { +// TODO: update to remove package scope when Blockable is fully deprecated +object BlockableTrace { + implicit object BlockableTraceBundle extends rocketutils.Blockable[TraceBundle] { def blockWhile(enable_blocking: Bool, data: TraceBundle) = { val blocked = WireInit(data) - blocked.insns := implicitly[Blockable[Vec[TracedInstruction]]].blockWhile(enable_blocking, data.insns) + blocked.insns := implicitly[rocketutils.Blockable[Vec[TracedInstruction]]].blockWhile(enable_blocking, data.insns) blocked } } diff --git a/src/main/scala/util/Broadcaster.scala b/src/main/scala/util/Broadcaster.scala index b2b0a78dc6c..91d2f40a797 100644 --- a/src/main/scala/util/Broadcaster.scala +++ b/src/main/scala/util/Broadcaster.scala @@ -9,6 +9,7 @@ import chisel3.util._ /** Takes in data on one decoupled interface and broadcasts it * to N decoupled output interfaces. */ +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class Broadcaster[T <: Data](typ: T, n: Int) extends Module { val io = IO(new Bundle { val in = Flipped(Decoupled(typ)) @@ -40,6 +41,7 @@ class Broadcaster[T <: Data](typ: T, n: Int) extends Module { } } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object Broadcaster { def apply[T <: Data](in: DecoupledIO[T], n: Int): Vec[DecoupledIO[T]] = { val split = Module(new Broadcaster(in.bits, n)) diff --git a/src/main/scala/util/BundleMap.scala b/src/main/scala/util/BundleMap.scala index 2b8dc0a1911..7c05c9a5d31 100644 --- a/src/main/scala/util/BundleMap.scala +++ b/src/main/scala/util/BundleMap.scala @@ -23,6 +23,7 @@ import scala.collection.immutable.HashMap * case class MyBundleDataField(width: Int) extends SimpleBundleField(MyBundleData)(Output(UInt(width.W)), 0.U) */ +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") sealed trait BundleFieldBase { def key: BundleKeyBase def data: Data // the field's chisel type with a direction @@ -36,6 +37,7 @@ sealed trait BundleFieldBase { } } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") abstract class BundleField[T <: Data](val key: BundleKey[T], typeT: => T, val default: T => Unit) extends BundleFieldBase { def data: T = typeT def defaultFlip(x: T): Unit = {} @@ -43,8 +45,10 @@ abstract class BundleField[T <: Data](val key: BundleKey[T], typeT: => T, val de def setDataDefaultFlip(x: Data): Unit = defaultFlip(x.asInstanceOf[T]) } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") abstract class SimpleBundleField[T <: Data](key: BundleKey[T])(typeT: => T, defaultT: => T) extends BundleField(key, typeT, { x: T => x := defaultT }) +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object BundleField { /* Consider an arbiter that receives two request streams A and B and combines them to C. * The output stream C should have the union of all keys from A and B. @@ -62,6 +66,7 @@ object BundleField { } } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") sealed trait BundleKeyBase { def name: String @@ -80,11 +85,16 @@ sealed trait BundleKeyBase { * - data fields (which are per-beat/byte and should be widened by bus-width adapters) * - control fields (which are per-burst and are unaffected by width adapters) */ +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") sealed trait IsDataKey extends BundleKeyBase +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") sealed trait IsControlKey extends BundleKeyBase +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") sealed class BundleKey[T <: Data](val name: String) extends BundleKeyBase +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") abstract class ControlKey[T <: Data](name: String) extends BundleKey[T](name) with IsControlKey +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") abstract class DataKey [T <: Data](name: String) extends BundleKey[T](name) with IsDataKey /* Signals can be further categorized in a request-response protocol: @@ -94,6 +104,7 @@ abstract class DataKey [T <: Data](name: String) extends BundleKey[T](name) wi * Generally, this categorization belongs in different BundleMaps */ +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class BundleMap(val fields: Seq[BundleFieldBase]) extends Record { // All fields must have distinct key.names require(fields.map(_.key.name).distinct.size == fields.size) @@ -117,6 +128,7 @@ class BundleMap(val fields: Seq[BundleFieldBase]) extends Record { } } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object BundleMap { def apply(fields: Seq[BundleFieldBase] = Nil) = new BundleMap(fields) /** Sets the default values of all bundle map elements that are aligned w.r.t. d */ diff --git a/src/main/scala/util/CRC.scala b/src/main/scala/util/CRC.scala index 0fc1da7c970..b9ce43baf3c 100644 --- a/src/main/scala/util/CRC.scala +++ b/src/main/scala/util/CRC.scala @@ -5,6 +5,7 @@ package freechips.rocketchip.util import chisel3._ import chisel3.util._ +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object CRC { // A divisor is interpretted using an explicit+1 CRC notation where bit 0 is required to be one. diff --git a/src/main/scala/util/ClockDivider.scala b/src/main/scala/util/ClockDivider.scala index 3460681de85..3e40356234e 100644 --- a/src/main/scala/util/ClockDivider.scala +++ b/src/main/scala/util/ClockDivider.scala @@ -15,6 +15,7 @@ import chisel3.util.HasBlackBoxResource * blocking assignments, it is impossible * to create a deterministic divided clock. */ +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class ClockDivider2 extends BlackBox with HasBlackBoxResource { val io = IO(new Bundle { val clk_out = Output(Clock()) @@ -23,6 +24,7 @@ class ClockDivider2 extends BlackBox with HasBlackBoxResource { addResource("/vsrc/ClockDivider2.v") } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class ClockDivider3 extends BlackBox with HasBlackBoxResource { val io = IO(new Bundle { val clk_out = Output(Clock()) @@ -34,6 +36,7 @@ class ClockDivider3 extends BlackBox with HasBlackBoxResource { /** Divide the clock by power of 2 times. * @param pow2 divides the clock 2 ^ pow2 times */ +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class Pow2ClockDivider(pow2: Int) extends Module { val io = IO(new Bundle { val clock_out = Output(Clock()) @@ -53,6 +56,7 @@ class Pow2ClockDivider(pow2: Int) extends Module { } } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object Pow2ClockDivider { def apply(pow2: Int): Clock = Module(new Pow2ClockDivider(pow2)).io.clock_out def apply(clock_in: Clock, pow2: Int): Clock = withClock(clock_in) { apply(pow2) } diff --git a/src/main/scala/util/ClockGate.scala b/src/main/scala/util/ClockGate.scala index e8c7a70bb1a..800c726a45a 100644 --- a/src/main/scala/util/ClockGate.scala +++ b/src/main/scala/util/ClockGate.scala @@ -8,9 +8,12 @@ import org.chipsalliance.cde.config.{Field, Parameters} import java.nio.file.{Files, Paths} +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") case object ClockGateImpl extends Field[() => ClockGate](() => new EICG_wrapper) +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") case object ClockGateModelFile extends Field[Option[String]](None) +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") abstract class ClockGate extends BlackBox with HasBlackBoxResource with HasBlackBoxPath { val io = IO(new Bundle{ @@ -28,6 +31,7 @@ abstract class ClockGate extends BlackBox } } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object ClockGate { def apply[T <: ClockGate]( in: Clock, @@ -51,4 +55,5 @@ object ClockGate { } // behavioral model of Integrated Clock Gating cell +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class EICG_wrapper extends ClockGate diff --git a/src/main/scala/util/CoreMonitor.scala b/src/main/scala/util/CoreMonitor.scala index 0ffaaa772ff..9b5009ed53a 100644 --- a/src/main/scala/util/CoreMonitor.scala +++ b/src/main/scala/util/CoreMonitor.scala @@ -7,6 +7,7 @@ import chisel3._ // this bundle is used to expose some internal core signals // to verification monitors which sample instruction commits +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class CoreMonitorBundle(val xLen: Int, val fLen: Int) extends Bundle with Clocked { val excpt = Bool() val priv_mode = UInt(width = 3.W) @@ -28,6 +29,7 @@ class CoreMonitorBundle(val xLen: Int, val fLen: Int) extends Bundle with Clocke } // mark a module that has cores with CoreMonitorBundles +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") trait HasCoreMonitorBundles { def coreMonitorBundles: List[CoreMonitorBundle] } diff --git a/src/main/scala/util/Counters.scala b/src/main/scala/util/Counters.scala index e1a700c9e64..10f000458db 100644 --- a/src/main/scala/util/Counters.scala +++ b/src/main/scala/util/Counters.scala @@ -7,6 +7,7 @@ import chisel3._ import chisel3.util._ // Produces 0-width value when counting to 1 +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class ZCounter(val n: Int) { val value = RegInit(0.U(log2Ceil(n).W)) def inc(): Bool = { @@ -19,6 +20,7 @@ class ZCounter(val n: Int) { } } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object ZCounter { def apply(n: Int) = new ZCounter(n) def apply(cond: Bool, n: Int): (UInt, Bool) = { @@ -29,6 +31,7 @@ object ZCounter { } } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object TwoWayCounter { def apply(up: Bool, down: Bool, max: Int): UInt = { val cnt = RegInit(0.U(log2Up(max + 1).W)) @@ -39,6 +42,7 @@ object TwoWayCounter { } // a counter that clock gates most of its MSBs using the LSB carry-out +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") case class WideCounter(width: Int, inc: UInt = 1.U, reset: Boolean = true, inhibit: Bool = false.B) { private val isWide = width > (2 * inc.getWidth) private val smallWidth = if (isWide) inc.getWidth max log2Up(width) else width diff --git a/src/main/scala/util/CreditedIO.scala b/src/main/scala/util/CreditedIO.scala index 4b81f0eb789..94bb113cbfc 100644 --- a/src/main/scala/util/CreditedIO.scala +++ b/src/main/scala/util/CreditedIO.scala @@ -11,6 +11,7 @@ import chisel3.util._ * round trip / total delay is the sum of debit and credit delay. * The system must have a positive total delay, otherwise you have a combinational loop. */ +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") case class CreditedDelay(debit: Int, credit: Int) { val total = debit + credit @@ -35,6 +36,7 @@ case class CreditedDelay(debit: Int, credit: Int) * WARNING: The user must ensure the round trip time is > 0. * Failure to comply will result in a combinational loop! */ +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") final class CreditedIO[T <: Data](gen: T) extends Bundle { def genType: T = gen @@ -102,6 +104,7 @@ final class CreditedIO[T <: Data](gen: T) extends Bundle pipeline(delay.debit, delay.credit) } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object CreditedIO { def apply[T <: Data](genType: T) = new CreditedIO(genType) @@ -125,6 +128,7 @@ object CreditedIO } } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class CreditedIOCounter(val init: Int, val depth: Int) { require (0 <= init) require (init <= depth) diff --git a/src/main/scala/util/Crossing.scala b/src/main/scala/util/Crossing.scala index 70ace66c574..c910952b837 100644 --- a/src/main/scala/util/Crossing.scala +++ b/src/main/scala/util/Crossing.scala @@ -5,6 +5,7 @@ package freechips.rocketchip.util import chisel3._ import chisel3.util._ +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class CrossingIO[T <: Data](gen: T) extends Bundle { // Enqueue clock domain val enq_clock = Input(Clock()) @@ -16,6 +17,7 @@ class CrossingIO[T <: Data](gen: T) extends Bundle { val deq = Decoupled(gen) } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") abstract class Crossing[T <: Data] extends RawModule { val io: CrossingIO[T] } diff --git a/src/main/scala/util/DelayQueue.scala b/src/main/scala/util/DelayQueue.scala index 47a9ace983a..9db49dffb4c 100644 --- a/src/main/scala/util/DelayQueue.scala +++ b/src/main/scala/util/DelayQueue.scala @@ -15,6 +15,7 @@ import chisel3.util._ * @param timer cycle count timer * @param entries cycle delay */ +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class DelayQueue[T <: Data](gen: T, entries: Int, width: Int) extends Module { val io = IO(new Bundle { val enq = Flipped(DecoupledIO(gen)) @@ -44,6 +45,7 @@ class DelayQueue[T <: Data](gen: T, entries: Int, width: Int) extends Module { q.io.deq.ready := io.deq.fire } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object DelayQueue { /** Helper to connect a delay queue. * diff --git a/src/main/scala/util/DescribedSRAM.scala b/src/main/scala/util/DescribedSRAM.scala index 2484a56b278..b1b43bca7d3 100644 --- a/src/main/scala/util/DescribedSRAM.scala +++ b/src/main/scala/util/DescribedSRAM.scala @@ -6,6 +6,7 @@ package freechips.rocketchip.util import chisel3.{Data, SyncReadMem, Vec} import chisel3.util.log2Ceil +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object DescribedSRAM { def apply[T <: Data]( name: String, diff --git a/src/main/scala/util/ECC.scala b/src/main/scala/util/ECC.scala index 245c3093bdb..2da12186858 100644 --- a/src/main/scala/util/ECC.scala +++ b/src/main/scala/util/ECC.scala @@ -6,6 +6,7 @@ import chisel3._ import chisel3.util._ import chisel3.util.random.LFSR +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") abstract class Decoding { def uncorrected: UInt @@ -15,6 +16,7 @@ abstract class Decoding def error = correctable || uncorrectable } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") abstract class Code { def canDetect: Boolean @@ -42,6 +44,7 @@ abstract class Code def swizzle(x: UInt): UInt } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class IdentityCode extends Code { def canDetect = false @@ -62,6 +65,7 @@ class IdentityCode extends Code } } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class ParityCode extends Code { def canDetect = true @@ -79,6 +83,7 @@ class ParityCode extends Code } } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class SECCode extends Code { def canDetect = true @@ -163,6 +168,7 @@ class SECCode extends Code } } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class SECDEDCode extends Code { def canDetect = true @@ -199,6 +205,7 @@ class SECDEDCode extends Code } } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object ErrGen { // generate a 1-bit error with approximate probability 2^-f @@ -209,17 +216,20 @@ object ErrGen def apply(x: UInt, f: Int): UInt = x ^ apply(x.getWidth, f) } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") trait CanHaveErrors extends Bundle { val correctable: Option[ValidIO[UInt]] val uncorrectable: Option[ValidIO[UInt]] } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") case class ECCParams( bytes: Int = 1, code: Code = new IdentityCode, notifyErrors: Boolean = false, ) +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object Code { def fromString(s: Option[String]): Code = fromString(s.getOrElse("none")) def fromString(s: String): Code = s.toLowerCase match { diff --git a/src/main/scala/util/ElaborationArtefactAnnotation.scala b/src/main/scala/util/ElaborationArtefactAnnotation.scala index 4f7f6cf7ccd..adcafe7e69a 100644 --- a/src/main/scala/util/ElaborationArtefactAnnotation.scala +++ b/src/main/scala/util/ElaborationArtefactAnnotation.scala @@ -22,6 +22,7 @@ import scala.collection.mutable * FIXME: tokens should be [[List[Token]]] but JSON serialization fails with * "no usable constructor for Token" */ +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") case class ElaborationArtefactAnnotation(outputFile: String, tokens: List[Any]) extends Annotation with HasSerializationHints { def update(renames: RenameMap): Seq[Annotation] = { Seq(this.copy(tokens = tokens.collect { @@ -38,6 +39,7 @@ case class ElaborationArtefactAnnotation(outputFile: String, tokens: List[Any]) ) } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object ElaborationArtefactAnnotation { /** Emits [[ElaborationArtefactAnnotation]] for the given filename extension and tokens. */ @@ -49,14 +51,17 @@ object ElaborationArtefactAnnotation { } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") sealed trait Token { def update(renames: RenameMap): Seq[Token] } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") case class StringToken(value: String) extends Token { def update(renames: RenameMap) = Seq(this) } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") case class ModulePathToken(target: IsModule) extends Token { def update(renames: RenameMap) = { renames.get(target) match { @@ -67,6 +72,7 @@ case class ModulePathToken(target: IsModule) extends Token { } } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") case class MemoryPathToken(target: ReferenceTarget) extends Token { def update(renames: RenameMap) = { renames.get(target) match { @@ -81,6 +87,7 @@ case class MemoryPathToken(target: ReferenceTarget) extends Token { } } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") case class ReferencePathToken(target: ReferenceTarget) extends Token { def update(renames: RenameMap) = { renames.get(target) match { @@ -91,6 +98,7 @@ case class ReferencePathToken(target: ReferenceTarget) extends Token { } } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object Token { /** An interpolator that generates tokens. Arguments for which a * [[Tokenizer]] instance is defined will be turned into a [[Token]] using @@ -137,10 +145,12 @@ object Token { } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") sealed trait Tokenizer[T] { def toToken(t: T): Token } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object Tokenizer { def apply[T: Tokenizer] = implicitly[Tokenizer[T]] diff --git a/src/main/scala/util/Frequency.scala b/src/main/scala/util/Frequency.scala index 7cef2a08abb..039431c650f 100644 --- a/src/main/scala/util/Frequency.scala +++ b/src/main/scala/util/Frequency.scala @@ -10,6 +10,7 @@ import chisel3.util._ * according to the frequency distribution. The sum of the * frequencies in the distribution must be a power of two. */ +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object Frequency { def apply(dist : List[(Int, Bits)]) : Bits = { // Distribution must be non-empty diff --git a/src/main/scala/util/GeneratorUtils.scala b/src/main/scala/util/GeneratorUtils.scala index d987cd4badd..ae02d55bc76 100644 --- a/src/main/scala/util/GeneratorUtils.scala +++ b/src/main/scala/util/GeneratorUtils.scala @@ -2,6 +2,7 @@ package freechips.rocketchip.util +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object ElaborationArtefacts { var files: Seq[(String, () => String)] = Nil diff --git a/src/main/scala/util/GenericParameterizedBundle.scala b/src/main/scala/util/GenericParameterizedBundle.scala index e69de29bb2d..90272ebc93c 100644 --- a/src/main/scala/util/GenericParameterizedBundle.scala +++ b/src/main/scala/util/GenericParameterizedBundle.scala @@ -0,0 +1,3 @@ +package util + + diff --git a/src/main/scala/util/HellaQueue.scala b/src/main/scala/util/HellaQueue.scala index b05cde563de..98b3e64049e 100644 --- a/src/main/scala/util/HellaQueue.scala +++ b/src/main/scala/util/HellaQueue.scala @@ -5,6 +5,7 @@ package freechips.rocketchip.util import chisel3._ import chisel3.util._ +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class HellaFlowQueue[T <: Data](val entries: Int)(data: => T) extends Module { val io = IO(new QueueIO(data, entries)) require(entries > 1) @@ -41,6 +42,7 @@ class HellaFlowQueue[T <: Data](val entries: Int)(data: => T) extends Module { io.count := DontCare } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class HellaQueue[T <: Data](val entries: Int)(data: => T) extends Module { val io = IO(new QueueIO(data, entries)) @@ -50,6 +52,7 @@ class HellaQueue[T <: Data](val entries: Int)(data: => T) extends Module { io.count := fq.io.count } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object HellaQueue { def apply[T <: Data](enq: DecoupledIO[T], entries: Int) = { val q = Module((new HellaQueue(entries)) { enq.bits }) diff --git a/src/main/scala/util/IDPool.scala b/src/main/scala/util/IDPool.scala index dd233b6518a..245d72b69b2 100644 --- a/src/main/scala/util/IDPool.scala +++ b/src/main/scala/util/IDPool.scala @@ -5,6 +5,7 @@ package freechips.rocketchip.util import chisel3._ import chisel3.util._ +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class IDPool(numIds: Int, lateValid: Boolean = false, revocableSelect: Boolean = false) extends Module { require (numIds > 0) val idWidth = log2Up(numIds) diff --git a/src/main/scala/util/IdentityModule.scala b/src/main/scala/util/IdentityModule.scala index f9865313e1f..9376a43e799 100644 --- a/src/main/scala/util/IdentityModule.scala +++ b/src/main/scala/util/IdentityModule.scala @@ -4,6 +4,7 @@ package freechips.rocketchip.tilelink import chisel3._ +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class IdentityModule[T <: Data](gen: T) extends Module { val io = IO(new Bundle { @@ -14,6 +15,7 @@ class IdentityModule[T <: Data](gen: T) extends Module io.out := io.in } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object IdentityModule { def apply[T <: Data](x: T): T = { diff --git a/src/main/scala/util/LCG.scala b/src/main/scala/util/LCG.scala index cc638e0976e..ffb51a3cc19 100644 --- a/src/main/scala/util/LCG.scala +++ b/src/main/scala/util/LCG.scala @@ -12,6 +12,7 @@ import chisel3.util.Cat * random initial value for each uninitialised register, effectively * seeding each LCG16 instance with a different seed. */ +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class LCG16 extends Module { val io = IO(new Bundle { val out = Output(UInt(16.W)) @@ -27,6 +28,7 @@ class LCG16 extends Module { /** An n-bit psuedo-random generator made from many instances of a * 16-bit LCG. Parameter 'width' must be larger than 0. */ +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class LCG(val w: Int) extends Module { val io = IO(new Bundle { val out = Output(UInt(w.W)) @@ -38,6 +40,7 @@ class LCG(val w: Int) extends Module { io.out := Cat(outs) } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object LCG16 { def apply(inc: Bool = true.B): UInt = { val lcg = Module(new LCG16) @@ -46,6 +49,7 @@ object LCG16 { } } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object LCG { def apply(w: Int, inc: Bool = true.B): UInt = { val lcg = Module(new LCG(w)) diff --git a/src/main/scala/util/LanePositionedQueue.scala b/src/main/scala/util/LanePositionedQueue.scala index 6a359dbf1a2..bd5db9829c4 100644 --- a/src/main/scala/util/LanePositionedQueue.scala +++ b/src/main/scala/util/LanePositionedQueue.scala @@ -7,6 +7,7 @@ import chisel3.util._ /////////////////////////////// Abstract API for the Queue ///////////////////////// +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class LanePositionedDecoupledIO[T <: Data](private val gen: T, val maxValid: Int, val maxReady: Int) extends Bundle { val validBits1 = log2Ceil(maxValid+1) // [0, maxValid] val readyBits1 = log2Ceil(maxReady+1) // [0, maxReady] @@ -62,6 +63,7 @@ class LanePositionedDecoupledIO[T <: Data](private val gen: T, val maxValid: Int } } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") case class LanePositionedQueueArgs( lanes: Int, rows: Int, @@ -76,6 +78,7 @@ case class LanePositionedQueueArgs( require (!abort || commit) } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class LanePositionedQueueIO[T <: Data](private val gen: T, val args: LanePositionedQueueArgs) extends Bundle { val lanes = args.lanes val depth = args.rows * lanes @@ -111,10 +114,12 @@ class LanePositionedQueueIO[T <: Data](private val gen: T, val args: LanePositio def driveWith(x: LanePositionedQueueIO[T]): Unit = { enq.driveWith(x.deq, enq_0_lane, x.deq_0_lane) } } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") trait LanePositionedQueueModule[T <: Data] extends Module { val io: LanePositionedQueueIO[T] } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") trait LanePositionedQueue { def apply[T <: Data](gen: T, args: LanePositionedQueueArgs): LanePositionedQueueModule[T] def apply[T <: Data]( @@ -133,6 +138,7 @@ trait LanePositionedQueue { /////////////////////////////// Index math implementation ////////////////////////// // A shared base class that keeps track of the indexing and flow control +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class LanePositionedQueueBase[T <: Data](val gen: T, args: LanePositionedQueueArgs) extends Module with LanePositionedQueueModule[T] { val LanePositionedQueueArgs(lanes, rows, flow, pipe, free, commit, rewind, abort) = args @@ -280,6 +286,7 @@ class LanePositionedQueueBase[T <: Data](val gen: T, args: LanePositionedQueueAr /////////////////////////////// Registered implementation ////////////////////////// +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class FloppedLanePositionedQueueModule[T <: Data](gen: T, args: LanePositionedQueueArgs) extends LanePositionedQueueBase(gen, args) { @@ -303,6 +310,7 @@ class FloppedLanePositionedQueueModule[T <: Data](gen: T, args: LanePositionedQu bank(1).write(b1_row, io.enq.bits, b1_mask) } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object FloppedLanePositionedQueue extends LanePositionedQueue { def apply[T <: Data](gen: T, args: LanePositionedQueueArgs) = new FloppedLanePositionedQueueModule(gen, args) @@ -310,6 +318,7 @@ object FloppedLanePositionedQueue extends LanePositionedQueue { /////////////////////////////// One port implementation //////////////////////////// +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class OnePortLanePositionedQueueModule[T <: Data](ecc: Code)(gen: T, args: LanePositionedQueueArgs) extends LanePositionedQueueBase(gen, args) { @@ -502,6 +511,7 @@ class OnePortLanePositionedQueueModule[T <: Data](ecc: Code)(gen: T, args: LaneP } } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") case class OnePortLanePositionedQueue(ecc: Code) extends LanePositionedQueue { def apply[T <: Data](gen: T, args: LanePositionedQueueArgs) = new OnePortLanePositionedQueueModule(ecc)(gen, args) diff --git a/src/main/scala/util/LatencyPipe.scala b/src/main/scala/util/LatencyPipe.scala index f11b2c9f2ed..3ac948ccf96 100644 --- a/src/main/scala/util/LatencyPipe.scala +++ b/src/main/scala/util/LatencyPipe.scala @@ -5,6 +5,7 @@ package freechips.rocketchip.util import chisel3._ import chisel3.util._ +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class LatencyPipe[T <: Data](typ: T, latency: Int) extends Module { val io = IO(new Bundle { val in = Flipped(Decoupled(typ)) @@ -17,6 +18,7 @@ class LatencyPipe[T <: Data](typ: T, latency: Int) extends Module { io.out <> doN(latency, (last: DecoupledIO[T]) => Queue(last, 1, true), io.in) } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object LatencyPipe { def apply[T <: Data](in: DecoupledIO[T], latency: Int): DecoupledIO[T] = { val pipe = Module(new LatencyPipe(chiselTypeOf(in.bits), latency)) diff --git a/src/main/scala/util/Location.scala b/src/main/scala/util/Location.scala index 5234eb0ccfa..bd153d22e58 100644 --- a/src/main/scala/util/Location.scala +++ b/src/main/scala/util/Location.scala @@ -5,6 +5,7 @@ package freechips.rocketchip.util import scala.language.dynamics import scala.collection.mutable.Map +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class Location[T](val name: String) extends Dynamic { def selectDynamic[A](portname: String): Location[A] = new Location[A](s"${name}_${portname}") def applyDynamic[A](portname: String)(args: A*): (Location[A], A) = { @@ -14,10 +15,12 @@ class Location[T](val name: String) extends Dynamic { override def toString = s"Location($name)" } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object Location { def apply[T](name: String): Location[T] = new Location[T](name) } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class LocationMap[T] private (val internalMap: Map[String, T]) extends Map[Location[_], T] { def addOne(kv: (Location[_], T)) = { (internalMap += (kv._1.name -> kv._2)); this } def subtractOne(key: Location[_]) = { (internalMap -= key.name); this } @@ -30,6 +33,7 @@ class LocationMap[T] private (val internalMap: Map[String, T]) extends Map[Locat def optional[L <: T](key: Location[_]): Option[L] = internalMap.lift(key.name).map(_.asInstanceOf[L]) } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object LocationMap { def apply[T](lm: Map[String, T]): LocationMap[T] = new LocationMap(lm) def empty[T]: LocationMap[T] = new LocationMap(Map.empty[String, T]) diff --git a/src/main/scala/util/Misc.scala b/src/main/scala/util/Misc.scala index fbf31eb771d..2c2db0b9143 100644 --- a/src/main/scala/util/Misc.scala +++ b/src/main/scala/util/Misc.scala @@ -9,17 +9,21 @@ import chisel3.util.random.LFSR import org.chipsalliance.cde.config.Parameters import scala.math._ +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class ParameterizedBundle(implicit p: Parameters) extends Bundle +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") trait Clocked extends Bundle { val clock = Clock() val reset = Bool() } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object DecoupledHelper { def apply(rvs: Bool*) = new DecoupledHelper(rvs) } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class DecoupledHelper(val rvs: Seq[Bool]) { def fire(exclude: Bool, includes: Bool*) = { require(rvs.contains(exclude), "Excluded Bool not present in DecoupledHelper! Note that DecoupledHelper uses referential equality for exclusion! If you don't want to exclude anything, use fire()!") @@ -30,6 +34,7 @@ class DecoupledHelper(val rvs: Seq[Bool]) { } } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object MuxT { def apply[T <: Data, U <: Data](cond: Bool, con: (T, U), alt: (T, U)): (T, U) = (Mux(cond, con._1, alt._1), Mux(cond, con._2, alt._2)) @@ -42,6 +47,7 @@ object MuxT { } /** Creates a cascade of n MuxTs to search for a key value. */ +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object MuxTLookup { def apply[S <: UInt, T <: Data, U <: Data](key: S, default: (T, U), mapping: Seq[(S, (T, U))]): (T, U) = { var res = default @@ -58,6 +64,7 @@ object MuxTLookup { } } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object ValidMux { def apply[T <: Data](v1: ValidIO[T], v2: ValidIO[T]*): ValidIO[T] = { apply(v1 +: v2.toSeq) @@ -71,6 +78,7 @@ object ValidMux { } } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object Str { def apply(s: String): UInt = { @@ -127,6 +135,7 @@ object Str private def validChar(x: Char) = x == (x & 0xFF) } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object Split { def apply(x: UInt, n0: Int) = { @@ -143,6 +152,7 @@ object Split } } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object Random { def apply(mod: Int, random: UInt): UInt = { @@ -161,6 +171,7 @@ object Random Seq.tabulate(slices)(i => value < (((i + 1) << value.getWidth) / slices).U) } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object Majority { def apply(in: Set[Bool]): Bool = { val n = (in.size >> 1) + 1 @@ -173,6 +184,7 @@ object Majority { def apply(in: UInt): Bool = apply(in.asBools.toSet) } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object PopCountAtLeast { private def two(x: UInt): (Bool, Bool) = x.getWidth match { case 1 => (x.asBool, false.B) @@ -194,6 +206,7 @@ object PopCountAtLeast { // Given an address and size, create a mask of beatBytes size // eg: (0x3, 0, 4) => 0001, (0x3, 1, 4) => 0011, (0x3, 2, 4) => 1111 // groupBy applies an interleaved OR reduction; groupBy=2 take 0010 => 01 +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object MaskGen { def apply(addr_lo: UInt, lgSize: UInt, beatBytes: Int, groupBy: Int = 1): UInt = { require (groupBy >= 1 && beatBytes >= groupBy) diff --git a/src/main/scala/util/MultiLaneQueue.scala b/src/main/scala/util/MultiLaneQueue.scala index 2ac763f6eb1..22d86e5f8a9 100644 --- a/src/main/scala/util/MultiLaneQueue.scala +++ b/src/main/scala/util/MultiLaneQueue.scala @@ -5,6 +5,7 @@ package freechips.rocketchip.util import chisel3._ import chisel3.util._ +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class MultiLaneQueue[T <: Data](gen: T, val lanes: Int, val rows: Int, val flow: Boolean = false, storage: LanePositionedQueue = FloppedLanePositionedQueue) extends Module { val laneBits1 = log2Ceil(lanes+1) // [0, lanes] @@ -29,6 +30,7 @@ class MultiLaneQueue[T <: Data](gen: T, val lanes: Int, val rows: Int, val flow: io.deq_bits := RotateVector.right(queue.io.deq.bits, queue.io.deq_0_lane) } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object RotateVector { def left[T <: Data](input: Seq[T], shift: UInt): Vec[T] = { val bools = shift.asBools.toVector diff --git a/src/main/scala/util/MultiPortQueue.scala b/src/main/scala/util/MultiPortQueue.scala index d497d9d14ef..29b885b519e 100644 --- a/src/main/scala/util/MultiPortQueue.scala +++ b/src/main/scala/util/MultiPortQueue.scala @@ -5,6 +5,7 @@ package freechips.rocketchip.util import chisel3._ import chisel3.util._ +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class MultiPortQueue[T <: Data](gen: T, val enq_lanes: Int, val deq_lanes: Int, val lanes: Int, val rows: Int, val flow: Boolean = false, storage: LanePositionedQueue = FloppedLanePositionedQueue) extends Module { val io = IO(new Bundle { val enq = Flipped(Vec(enq_lanes, Decoupled(gen))) @@ -18,6 +19,7 @@ class MultiPortQueue[T <: Data](gen: T, val enq_lanes: Int, val deq_lanes: Int, MultiPortQueue.scatter(io.deq, queue.io.deq, queue.io.deq_0_lane) } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object MultiPortQueue { def gather[T <: Data](sparse: Seq[DecoupledIO[T]], dense: LanePositionedDecoupledIO[T], offset: UInt = 0.U): Unit = { // Compute per-enq-port ready diff --git a/src/main/scala/util/MultiWidthFifo.scala b/src/main/scala/util/MultiWidthFifo.scala index 2d589283c77..b575af59375 100644 --- a/src/main/scala/util/MultiWidthFifo.scala +++ b/src/main/scala/util/MultiWidthFifo.scala @@ -6,6 +6,7 @@ import chisel3._ import chisel3.util._ import freechips.rocketchip.unittest.UnitTest +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class MultiWidthFifo(inW: Int, outW: Int, n: Int) extends Module { val io = IO(new Bundle { val in = Flipped(Decoupled(Bits(inW.W))) diff --git a/src/main/scala/util/MuxLiteral.scala b/src/main/scala/util/MuxLiteral.scala index 60fcf2d38dd..4dcea5b6944 100644 --- a/src/main/scala/util/MuxLiteral.scala +++ b/src/main/scala/util/MuxLiteral.scala @@ -9,6 +9,7 @@ import scala.reflect.ClassTag /* MuxLiteral creates a lookup table from a key to a list of values. * Unlike MuxLookup, the table keys must be exclusive literals. */ +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object MuxLiteral { def apply[T <: Data:ClassTag](index: UInt, default: T, first: (UInt, T), rest: (UInt, T)*): T = @@ -17,6 +18,7 @@ object MuxLiteral MuxTable(index, default, cases.map { case (k, v) => (k.litValue, v) }) } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object MuxSeq { def apply[T <: Data:ClassTag](index: UInt, default: T, first: T, rest: T*): T = @@ -25,6 +27,7 @@ object MuxSeq MuxTable(index, default, cases.zipWithIndex.map { case (v, i) => (BigInt(i), v) }) } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object MuxTable { def apply[T <: Data:ClassTag](index: UInt, default: T, first: (BigInt, T), rest: (BigInt, T)*): T = diff --git a/src/main/scala/util/PSDTestMode.scala b/src/main/scala/util/PSDTestMode.scala index 30c97a9078c..80a648c3ba2 100644 --- a/src/main/scala/util/PSDTestMode.scala +++ b/src/main/scala/util/PSDTestMode.scala @@ -8,17 +8,21 @@ import org.chipsalliance.cde.config._ import org.chipsalliance.diplomacy._ import org.chipsalliance.diplomacy.bundlebridge._ +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") case object IncludePSDTest extends Field[Boolean](false) +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") case object PSDTestModeBroadcastKey extends Field( BundleBridgeEphemeralNode[PSDTestMode]()(ValName("global_psd_test_mode")) ) +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class PSDTestMode extends Bundle { val test_mode = Bool() val test_mode_reset = Bool() // TODO: Clocks? } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") trait CanHavePSDTestModeIO { implicit val p: Parameters val psd = p(IncludePSDTest).option(Input(new PSDTestMode())) diff --git a/src/main/scala/util/PlusArg.scala b/src/main/scala/util/PlusArg.scala index 59a1b4ec3bc..3d3bd7bc514 100644 --- a/src/main/scala/util/PlusArg.scala +++ b/src/main/scala/util/PlusArg.scala @@ -16,11 +16,13 @@ case class PlusArgInfo(default: BigInt, docstring: String) * @param docstring text to include in the help * @param doctype description of the Verilog type of the PlusArg value (e.g. STRING, INT) */ +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") private case class PlusArgContainer[A](default: Option[A], docstring: String, doctype: String) /** Typeclass for converting a type to a doctype string * @tparam A some type */ +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") trait Doctypeable[A] { /** Return the doctype string for some option */ @@ -29,19 +31,21 @@ trait Doctypeable[A] { } /** Object containing implementations of the Doctypeable typeclass */ +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object Doctypes { /** Converts an Int => "INT" */ - implicit val intToDoctype = new Doctypeable[Int] { def toDoctype(a: Option[Int]) = "INT" } + implicit val intToDoctype: Doctypeable[Int] = new Doctypeable[Int] { def toDoctype(a: Option[Int]) = "INT" } /** Converts a BigInt => "INT" */ - implicit val bigIntToDoctype = new Doctypeable[BigInt] { def toDoctype(a: Option[BigInt]) = "INT" } + implicit val bigIntToDoctype: Doctypeable[BigInt] = new Doctypeable[BigInt] { def toDoctype(a: Option[BigInt]) = "INT" } /** Converts a String => "STRING" */ - implicit val stringToDoctype = new Doctypeable[String] { def toDoctype(a: Option[String]) = "STRING" } + implicit val stringToDoctype: Doctypeable[String] = new Doctypeable[String] { def toDoctype(a: Option[String]) = "STRING" } } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class plusarg_reader(val format: String, val default: BigInt, val docstring: String, val width: Int) extends BlackBox(Map( "FORMAT" -> StringParam(format), "DEFAULT" -> IntParam(default), @@ -55,6 +59,7 @@ class plusarg_reader(val format: String, val default: BigInt, val docstring: Str } /* This wrapper class has no outputs, making it clear it is a simulation-only construct */ +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class PlusArgTimeout(val format: String, val default: BigInt, val docstring: String, val width: Int) extends Module { val io = IO(new Bundle { val count = Input(UInt(width.W)) @@ -67,6 +72,7 @@ class PlusArgTimeout(val format: String, val default: BigInt, val docstring: Str import Doctypes._ +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object PlusArg { /** PlusArg("foo") will return 42.U if the simulation is run with +foo=42 @@ -90,6 +96,7 @@ object PlusArg } } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object PlusArgArtefacts { private var artefacts: Map[String, PlusArgContainer[_]] = Map.empty diff --git a/src/main/scala/util/PrefixSum.scala b/src/main/scala/util/PrefixSum.scala index 1c6c90549d3..7fff76e58d8 100644 --- a/src/main/scala/util/PrefixSum.scala +++ b/src/main/scala/util/PrefixSum.scala @@ -4,6 +4,7 @@ package freechips.rocketchip.util import chisel3.util.{log2Ceil, log2Floor} +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") trait PrefixSum { // out[0] = summands[0] // out[1] = summands[0] + summands[1] @@ -17,6 +18,7 @@ trait PrefixSum { } // N-1 area, N-1 depth +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object RipplePrefixSum extends PrefixSum { def layers(size: Int) = if (size == 0) 1 else size def apply[T](summands: Seq[T])(associativeOp: (T, T) => T, layerOp: (Int, Vector[T]) => Vector[T]): Vector[T] = { @@ -38,6 +40,7 @@ object RipplePrefixSum extends PrefixSum { } // O(NlogN) area, logN depth +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object DensePrefixSum extends PrefixSum { def layers(size: Int) = if (size == 0) 1 else 1+log2Ceil(size) def apply[T](summands: Seq[T])(associativeOp: (T, T) => T, layerOp: (Int, Vector[T]) => Vector[T]): Vector[T] = { @@ -59,6 +62,7 @@ object DensePrefixSum extends PrefixSum { } // 2N area, 2logN depth +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object SparsePrefixSum extends PrefixSum { def layers(size: Int) = if (size <= 1) 1 else 2*log2Floor(size) + (if (2*size >= (3 << log2Floor(size))) 1 else 0) @@ -99,6 +103,7 @@ object SparsePrefixSum extends PrefixSum { } } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object TestPrefixSums { def testSize(size: Int): Unit = { val input = Seq.tabulate(size) { i => Seq(i) } diff --git a/src/main/scala/util/Property.scala b/src/main/scala/util/Property.scala index 644d388bcdc..97520ca3359 100644 --- a/src/main/scala/util/Property.scala +++ b/src/main/scala/util/Property.scala @@ -6,16 +6,19 @@ import chisel3._ import chisel3.experimental.SourceInfo import chisel3.util.{ReadyValidIO} +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") sealed abstract class PropertyType(name: String) { override def toString: String = name } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object PropertyType { object Assert extends PropertyType("Assert") object Assume extends PropertyType("Assume") object Cover extends PropertyType("Cover") } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") trait BasePropertyParameters { val pType: PropertyType val cond: Bool @@ -23,6 +26,7 @@ trait BasePropertyParameters { val message: String } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") case class CoverPropertyParameters( cond: Bool, label: String = "", @@ -30,10 +34,12 @@ case class CoverPropertyParameters( val pType = PropertyType.Cover } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") abstract class BasePropertyLibrary { def generateProperty(prop_param: BasePropertyParameters)(implicit sourceInfo: SourceInfo): Unit } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class DefaultPropertyLibrary extends BasePropertyLibrary { def generateProperty(prop_param: BasePropertyParameters)(implicit sourceInfo: SourceInfo): Unit = { // default is to do nothing @@ -41,10 +47,12 @@ class DefaultPropertyLibrary extends BasePropertyLibrary { } } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") abstract class BaseProperty { def generateProperties(): Seq[BasePropertyParameters] } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") case class CoverBoolean(cond: Bool, labels: Seq[String]) { } @@ -72,6 +80,7 @@ case class CoverBoolean(cond: Bool, labels: Seq[String]) { // Each boolean expression can be associated with more than one label +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class CrossProperty(cond: Seq[Seq[CoverBoolean]], exclude: Seq[Seq[String]], message: String) extends BaseProperty { def listProperties(c1: CoverBoolean, c2: Seq[CoverBoolean]): Seq[CoverBoolean] = { if (c2.isEmpty) { @@ -124,6 +133,7 @@ class CrossProperty(cond: Seq[Seq[CoverBoolean]], exclude: Seq[Seq[String]], mes // The implementation using a setable global is bad, but removes dependence on Parameters // This change was made in anticipation of a proper cover library +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object cover { private var propLib: BasePropertyLibrary = new DefaultPropertyLibrary def setPropLib(lib: BasePropertyLibrary): Unit = this.synchronized { diff --git a/src/main/scala/util/ROMGenerator.scala b/src/main/scala/util/ROMGenerator.scala index feae7798698..44cca4895ee 100644 --- a/src/main/scala/util/ROMGenerator.scala +++ b/src/main/scala/util/ROMGenerator.scala @@ -6,8 +6,10 @@ import chisel3._ import chisel3.util.log2Ceil import scala.collection.mutable.{HashMap} +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") case class ROMConfig(name: String, depth: Int, width: Int) +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class BlackBoxedROM(c: ROMConfig) extends BlackBox { val io = IO(new Bundle { val clock = Input(Clock()) @@ -20,6 +22,7 @@ class BlackBoxedROM(c: ROMConfig) extends BlackBox { override def desiredName: String = c.name } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object ROMGenerator { private var finalized = false private val roms = HashMap[BlackBoxedROM, ROMConfig]() diff --git a/src/main/scala/util/RationalCrossing.scala b/src/main/scala/util/RationalCrossing.scala index 3ad9b12c36c..9da22c87a5d 100644 --- a/src/main/scala/util/RationalCrossing.scala +++ b/src/main/scala/util/RationalCrossing.scala @@ -12,6 +12,7 @@ import chisel3.util._ // A rational crossing must put registers on the slow side. // This trait covers the options of how/where to put the registers. // BEWARE: the source+sink must agree on the direction! +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") sealed trait RationalDirection { def flip: RationalDirection } @@ -21,6 +22,7 @@ sealed trait RationalDirection { // a Queue into flow and pipe parts on either side. This is safe // for all possible clock ratios, but has the downside that the // timing must be met for the least-common-multiple of the clocks. +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") case object Symmetric extends RationalDirection { def flip = Symmetric } @@ -30,6 +32,7 @@ case object Symmetric extends RationalDirection { // a full flow+pipe buffer on both sides of the crossing. This // ends up costing potentially two cycles of delay, but gives // both clock domains a full clock period to close timing. +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") case object Flexible extends RationalDirection { def flip = Flexible } @@ -37,6 +40,7 @@ case object Flexible extends RationalDirection { // If the source is N:1 of the sink, place the registers at the sink. // This imposes only a single clock cycle of delay and both side of // the crossing have a full clock period to close timing. +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") case object FastToSlow extends RationalDirection { def flip = SlowToFast } @@ -44,10 +48,12 @@ case object FastToSlow extends RationalDirection { // If the source is 1:N of the sink, place the registers at the source. // This imposes only a single clock cycle of delay and both side of // the crossing have a full clock period to close timing. +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") case object SlowToFast extends RationalDirection { def flip = FastToSlow } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") final class RationalIO[T <: Data](gen: T) extends Bundle { val bits0 = Output(gen) @@ -59,11 +65,13 @@ final class RationalIO[T <: Data](gen: T) extends Bundle } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object RationalIO { def apply[T <: Data](gen: T) = new RationalIO(gen) } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class RationalCrossingSource[T <: Data](gen: T, direction: RationalDirection = Symmetric) extends Module { val io = IO(new Bundle { @@ -100,6 +108,7 @@ class RationalCrossingSource[T <: Data](gen: T, direction: RationalDirection = S } } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class RationalCrossingSink[T <: Data](gen: T, direction: RationalDirection = Symmetric) extends Module { val io = IO(new Bundle { @@ -135,6 +144,7 @@ class RationalCrossingSink[T <: Data](gen: T, direction: RationalDirection = Sym } } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class RationalCrossingFull[T <: Data](gen: T, direction: RationalDirection = Symmetric) extends Module { val io = IO(new CrossingIO(gen)) @@ -151,6 +161,7 @@ class RationalCrossingFull[T <: Data](gen: T, direction: RationalDirection = Sym io.deq <> sink.io.deq } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object ToRational { def apply[T <: Data](x: DecoupledIO[T], direction: RationalDirection = Symmetric): RationalIO[T] = { @@ -160,6 +171,7 @@ object ToRational } } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object FromRational { def apply[T <: Data](x: RationalIO[T], direction: RationalDirection = Symmetric): DecoupledIO[T] = { diff --git a/src/main/scala/util/RecordMap.scala b/src/main/scala/util/RecordMap.scala index fb2b227164c..be1c44199ab 100644 --- a/src/main/scala/util/RecordMap.scala +++ b/src/main/scala/util/RecordMap.scala @@ -7,6 +7,7 @@ import scala.collection.immutable.ListMap import chisel3.experimental.requireIsChiselType import chisel3.reflect.DataMirror.internal.chiselTypeClone +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") final class RecordMap[T <: Data] (eltMap: ListMap[String, T]) extends Record { @@ -22,6 +23,7 @@ final class RecordMap[T <: Data] (eltMap: ListMap[String, T]) } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object RecordMap { def apply[T <: Data](eltMap: ListMap[String, T]) = new RecordMap(eltMap) diff --git a/src/main/scala/util/ReduceOthers.scala b/src/main/scala/util/ReduceOthers.scala index fa79d52b2c2..5590bf343c0 100644 --- a/src/main/scala/util/ReduceOthers.scala +++ b/src/main/scala/util/ReduceOthers.scala @@ -4,6 +4,7 @@ package freechips.rocketchip.util import chisel3._ +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object ReduceOthers { // Given a list of bools, create this output: // out[i] = AND[j=0..out.size, j!=i] in[j] diff --git a/src/main/scala/util/ReorderQueue.scala b/src/main/scala/util/ReorderQueue.scala index c087c9b776e..6460b41f327 100644 --- a/src/main/scala/util/ReorderQueue.scala +++ b/src/main/scala/util/ReorderQueue.scala @@ -6,17 +6,20 @@ package freechips.rocketchip.util import chisel3._ import chisel3.util.{DecoupledIO, Mux1H, OHToUInt, PriorityEncoder, PriorityEncoderOH} +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class ReorderQueueWrite[T <: Data](dType: T, tagWidth: Int) extends Bundle { val data = dType.cloneType val tag = UInt(tagWidth.W) } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class ReorderEnqueueIO[T <: Data](dType: T, tagWidth: Int) extends DecoupledIO(new ReorderQueueWrite(dType, tagWidth)) { } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class ReorderDequeueIO[T <: Data](dType: T, tagWidth: Int) extends Bundle { val valid = Input(Bool()) val tag = Input(UInt(tagWidth.W)) @@ -25,6 +28,7 @@ class ReorderDequeueIO[T <: Data](dType: T, tagWidth: Int) extends Bundle { } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class ReorderQueue[T <: Data](dType: T, tagWidth: Int, size: Option[Int] = None) extends Module { val io = IO(new Bundle { diff --git a/src/main/scala/util/Repeater.scala b/src/main/scala/util/Repeater.scala index a0b0c5b297d..3184978f7c7 100644 --- a/src/main/scala/util/Repeater.scala +++ b/src/main/scala/util/Repeater.scala @@ -7,6 +7,7 @@ import chisel3.util.{Decoupled, DecoupledIO} // A Repeater passes its input to its output, unless repeat is asserted. // When repeat is asserted, the Repeater copies the input and repeats it next cycle. +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class Repeater[T <: Data](gen: T) extends Module { val io = IO( new Bundle { @@ -29,6 +30,7 @@ class Repeater[T <: Data](gen: T) extends Module when (io.deq.fire && !io.repeat) { full := false.B } } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object Repeater { def apply[T <: Data](enq: DecoupledIO[T], repeat: Bool): DecoupledIO[T] = { diff --git a/src/main/scala/util/Replacement.scala b/src/main/scala/util/Replacement.scala index f3a48aa7e26..d50b9c699c1 100644 --- a/src/main/scala/util/Replacement.scala +++ b/src/main/scala/util/Replacement.scala @@ -8,6 +8,7 @@ import chisel3.util._ import chisel3.util.random.LFSR import freechips.rocketchip.util.property.cover +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") abstract class ReplacementPolicy { def nBits: Int def perSet: Boolean @@ -24,6 +25,7 @@ abstract class ReplacementPolicy { def get_replace_way(state: UInt): UInt } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object ReplacementPolicy { def fromString(s: String, n_ways: Int): ReplacementPolicy = s.toLowerCase match { case "random" => new RandomReplacement(n_ways) @@ -33,6 +35,7 @@ object ReplacementPolicy { } } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class RandomReplacement(n_ways: Int) extends ReplacementPolicy { private val replace = Wire(Bool()) replace := false.B @@ -50,18 +53,21 @@ class RandomReplacement(n_ways: Int) extends ReplacementPolicy { def get_replace_way(state: UInt) = way } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") abstract class SeqReplacementPolicy { def access(set: UInt): Unit def update(valid: Bool, hit: Bool, set: UInt, way: UInt): Unit def way: UInt } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") abstract class SetAssocReplacementPolicy { def access(set: UInt, touch_way: UInt): Unit def access(sets: Seq[UInt], touch_ways: Seq[Valid[UInt]]): Unit def way(set: UInt): UInt } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class SeqRandom(n_ways: Int) extends SeqReplacementPolicy { val logic = new RandomReplacement(n_ways) def access(set: UInt) = { } @@ -71,6 +77,7 @@ class SeqRandom(n_ways: Int) extends SeqReplacementPolicy { def way = logic.way } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class TrueLRU(n_ways: Int) extends ReplacementPolicy { // True LRU replacement policy, using a triangular matrix to track which sets are more recently used than others. // The matrix is packed into a single UInt (or Bits). Example 4-way (6-bits): @@ -140,6 +147,7 @@ class TrueLRU(n_ways: Int) extends ReplacementPolicy { def replace: UInt = way } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class PseudoLRU(n_ways: Int) extends ReplacementPolicy { // Pseudo-LRU tree algorithm: https://en.wikipedia.org/wiki/Pseudo-LRU#Tree-PLRU // @@ -273,6 +281,7 @@ class PseudoLRU(n_ways: Int) extends ReplacementPolicy { def hit = {} } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class SeqPLRU(n_sets: Int, n_ways: Int) extends SeqReplacementPolicy { val logic = new PseudoLRU(n_ways) val state = SyncReadMem(n_sets, UInt(logic.nBits.W)) @@ -294,6 +303,7 @@ class SeqPLRU(n_sets: Int, n_ways: Int) extends SeqReplacementPolicy { } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class SetAssocLRU(n_sets: Int, n_ways: Int, policy: String) extends SetAssocReplacementPolicy { val logic = policy.toLowerCase match { case "plru" => new PseudoLRU(n_ways) diff --git a/src/main/scala/util/ResetCatchAndSync.scala b/src/main/scala/util/ResetCatchAndSync.scala index 82e0bef077d..606ff3d02f8 100644 --- a/src/main/scala/util/ResetCatchAndSync.scala +++ b/src/main/scala/util/ResetCatchAndSync.scala @@ -10,6 +10,7 @@ import chisel3.{withClockAndReset, withReset} * */ +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class ResetCatchAndSync (sync: Int = 3) extends Module { override def desiredName = s"ResetCatchAndSync_d${sync}" @@ -30,6 +31,7 @@ class ResetCatchAndSync (sync: Int = 3) extends Module { } } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object ResetCatchAndSync { def apply(clk: Clock, rst: Bool, sync: Int = 3, name: Option[String] = None, diff --git a/src/main/scala/util/ScatterGather.scala b/src/main/scala/util/ScatterGather.scala index 714ae6f9320..b3ae1e4b570 100644 --- a/src/main/scala/util/ScatterGather.scala +++ b/src/main/scala/util/ScatterGather.scala @@ -5,6 +5,7 @@ package freechips.rocketchip.util import chisel3._ import chisel3.util._ +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object Gather { // Compress all the valid data to the lowest indices def apply[T <: Data](data: Seq[ValidIO[T]]): Vec[T] = apply(data, DensePrefixSum) @@ -37,6 +38,7 @@ object Gather { def idLayer[T](layer: Int, data: Seq[T], holeSum: Seq[UInt]) = (data, holeSum) } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object Scatter { def apply[T <: Data](data: Seq[ValidIO[T]]): Vec[T] = apply(data, DensePrefixSum) def apply[T <: Data](data: Seq[ValidIO[T]], prefixSum: PrefixSum): Vec[T] = { diff --git a/src/main/scala/util/SeededRandom.scala b/src/main/scala/util/SeededRandom.scala index e3471eff50f..b947c58728d 100644 --- a/src/main/scala/util/SeededRandom.scala +++ b/src/main/scala/util/SeededRandom.scala @@ -6,6 +6,7 @@ package freechips.rocketchip.util * which is almost certainly undesirable. Use LCG to increment random numbers in HW, * or use this SeededRandom.fromSeed to make reproducible Scala PRNGs. */ +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object SeededRandom { val fromSeed = new scala.util.Random(42) } diff --git a/src/main/scala/util/ShiftQueue.scala b/src/main/scala/util/ShiftQueue.scala index a1790b04c6c..535a27956af 100644 --- a/src/main/scala/util/ShiftQueue.scala +++ b/src/main/scala/util/ShiftQueue.scala @@ -9,13 +9,14 @@ import chisel3.util._ * register internally. It is less energy efficient whenever the queue * has more than one entry populated, but is faster on the dequeue side. * It is efficient for usually-empty flow-through queues. */ +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class ShiftQueue[T <: Data](gen: T, val entries: Int, pipe: Boolean = false, flow: Boolean = false) extends Module { val io = IO(new QueueIO(gen, entries) { - val mask = Output(UInt(entries.W)) + val mask = Output(UInt(this.entries.W)) }) private val valid = RegInit(VecInit(Seq.fill(entries) { false.B })) @@ -54,6 +55,7 @@ class ShiftQueue[T <: Data](gen: T, io.count := PopCount(io.mask) } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object ShiftQueue { def apply[T <: Data](enq: DecoupledIO[T], entries: Int = 2, pipe: Boolean = false, flow: Boolean = false): DecoupledIO[T] = { diff --git a/src/main/scala/util/ShiftReg.scala b/src/main/scala/util/ShiftReg.scala index fb17892bcf2..5d3e7b24c89 100644 --- a/src/main/scala/util/ShiftReg.scala +++ b/src/main/scala/util/ShiftReg.scala @@ -7,6 +7,7 @@ import chisel3._ // Similar to the Chisel ShiftRegister but allows the user to suggest a // name to the registers that get instantiated, and // to provide a reset value. +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object ShiftRegInit { def apply[T <: Data](in: T, n: Int, init: T, name: Option[String] = None): T = @@ -32,6 +33,7 @@ object ShiftRegInit { * but only used for timing applications */ +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") abstract class AbstractPipelineReg(w: Int = 1) extends Module { val io = IO(new Bundle { val d = Input(UInt(w.W)) @@ -40,6 +42,7 @@ abstract class AbstractPipelineReg(w: Int = 1) extends Module { ) } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object AbstractPipelineReg { def apply [T <: Data](gen: => AbstractPipelineReg, in: T, name: Option[String] = None): T = { val chain = Module(gen) @@ -49,6 +52,7 @@ object AbstractPipelineReg { } } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class AsyncResetShiftReg(w: Int = 1, depth: Int = 1, init: Int = 0, name: String = "pipe") extends AbstractPipelineReg(w) { require(depth > 0, "Depth must be greater than 0.") @@ -68,6 +72,7 @@ class AsyncResetShiftReg(w: Int = 1, depth: Int = 1, init: Int = 0, name: String io.q := chain.head.io.q } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object AsyncResetShiftReg { def apply [T <: Data](in: T, depth: Int, init: Int = 0, name: Option[String] = None): T = AbstractPipelineReg(new AsyncResetShiftReg(in.getWidth, depth, init), in, name) diff --git a/src/main/scala/util/SimpleProduct.scala b/src/main/scala/util/SimpleProduct.scala index 50e99307c23..ab5489a54bb 100644 --- a/src/main/scala/util/SimpleProduct.scala +++ b/src/main/scala/util/SimpleProduct.scala @@ -11,6 +11,7 @@ package freechips.rocketchip.util // def equals(that: Any): Boolean = same type and same fields // def hashCode: Int = hash of all fields (and productPrefix) // def toString: String = formats as "productPrefix(field1, field2, ...)" +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") trait SimpleProduct extends Product with Equals { override def equals(other: Any): Boolean = other match { case that: SimpleProduct => diff --git a/src/main/scala/util/SynchronizerReg.scala b/src/main/scala/util/SynchronizerReg.scala index 18c0d94d3dc..d3babe18ec7 100644 --- a/src/main/scala/util/SynchronizerReg.scala +++ b/src/main/scala/util/SynchronizerReg.scala @@ -27,6 +27,7 @@ import chisel3.util.{RegEnable, Cat} * Clock Domains. */ +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object SynchronizerResetType extends Enumeration { val NonSync, Inferred, Sync, Async = Value } @@ -34,6 +35,7 @@ object SynchronizerResetType extends Enumeration { // Note: this should not be used directly. // Use the companion object to generate this with the correct reset type mixin. +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") private class SynchronizerPrimitiveShiftReg( sync: Int, init: Boolean, @@ -59,6 +61,7 @@ private class SynchronizerPrimitiveShiftReg( io.q := chain.head.asUInt } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") private object SynchronizerPrimitiveShiftReg { def apply (in: Bool, sync: Int, init: Boolean, resetType: SynchronizerResetType.Value): Bool = { val gen: () => SynchronizerPrimitiveShiftReg = resetType match { @@ -77,6 +80,7 @@ private object SynchronizerPrimitiveShiftReg { // Note: This module may end up with a non-AsyncReset type reset. // But the Primitives within will always have AsyncReset type. +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class AsyncResetSynchronizerShiftReg(w: Int = 1, sync: Int, init: Int) extends AbstractPipelineReg(w) { require(sync > 1, s"Sync must be greater than 1, not ${sync}.") @@ -90,6 +94,7 @@ class AsyncResetSynchronizerShiftReg(w: Int = 1, sync: Int, init: Int) io.q := Cat(output.reverse) } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object AsyncResetSynchronizerShiftReg { def apply [T <: Data](in: T, sync: Int, init: Int, name: Option[String] = None): T = AbstractPipelineReg(new AsyncResetSynchronizerShiftReg(in.getWidth, sync, init), in, name) @@ -122,6 +127,7 @@ class SyncResetSynchronizerShiftReg(w: Int = 1, sync: Int, init: Int) extends Ab io.q := Cat(output.reverse) } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object SyncResetSynchronizerShiftReg { def apply [T <: Data](in: T, sync: Int, init: Int, name: Option[String] = None): T = if (sync == 0) in else AbstractPipelineReg(new SyncResetSynchronizerShiftReg(in.getWidth, sync, init), in, name) @@ -139,6 +145,7 @@ object SyncResetSynchronizerShiftReg { apply (in, sync, init.litValue.toInt, None) } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class ResetSynchronizerShiftReg(w: Int = 1, sync: Int, init: Int) extends AbstractPipelineReg(w) { require(sync > 1, s"Sync must be greater than 1, not ${sync}.") override def desiredName = s"ResetSynchronizerShiftReg_w${w}_d${sync}_i${init}" @@ -149,6 +156,7 @@ class ResetSynchronizerShiftReg(w: Int = 1, sync: Int, init: Int) extends Abstra io.q := Cat(output.reverse) } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object ResetSynchronizerShiftReg { def apply [T <: Data](in: T, sync: Int, init: Int, name: Option[String] = None): T = AbstractPipelineReg(new ResetSynchronizerShiftReg(in.getWidth, sync, init), in, name) @@ -166,6 +174,7 @@ object ResetSynchronizerShiftReg { apply (in, sync, init.litValue.toInt, None) } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class SynchronizerShiftReg(w: Int = 1, sync: Int = 3) extends AbstractPipelineReg(w) { require(sync > 1, s"Sync must be greater than 1, not ${sync}.") override def desiredName = s"SynchronizerShiftReg_w${w}_d${sync}" @@ -175,6 +184,7 @@ class SynchronizerShiftReg(w: Int = 1, sync: Int = 3) extends AbstractPipelineRe io.q := Cat(output.reverse) } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object SynchronizerShiftReg { def apply [T <: Data](in: T, sync: Int, name: Option[String] = None): T = if (sync == 0) in else AbstractPipelineReg(new SynchronizerShiftReg(in.getWidth, sync), in, name) @@ -188,6 +198,7 @@ object SynchronizerShiftReg { } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class ClockCrossingReg(w: Int = 1, doInit: Boolean) extends Module { override def desiredName = s"ClockCrossingReg_w${w}" @@ -202,6 +213,7 @@ class ClockCrossingReg(w: Int = 1, doInit: Boolean) extends Module { io.q := cdc_reg } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object ClockCrossingReg { def apply [T <: Data](in: T, en: Bool, doInit: Boolean, name: Option[String] = None): T = { val cdc_reg = Module(new ClockCrossingReg(in.getWidth, doInit)) diff --git a/src/main/scala/util/Timer.scala b/src/main/scala/util/Timer.scala index f8ec834d9f9..474b3104425 100644 --- a/src/main/scala/util/Timer.scala +++ b/src/main/scala/util/Timer.scala @@ -10,6 +10,7 @@ import chisel3.util.{PriorityEncoder, Valid, log2Up} * Can take multiple inflight start-stop events with ID * Will continue to count down as long as at least one event is inflight */ +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class Timer(initCount: Int, maxInflight: Int) extends Module { val io = IO(new Bundle { val start = Flipped(Valid(UInt(log2Up(maxInflight).W))) @@ -40,6 +41,7 @@ class Timer(initCount: Int, maxInflight: Int) extends Module { /** Simplified Timer with a statically-specified period. * Can be stopped repeatedly, even when not active. */ +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class SimpleTimer(initCount: Int) extends Module { val io = IO(new Bundle { val start = Input(Bool()) @@ -62,6 +64,7 @@ class SimpleTimer(initCount: Int) extends Module { io.timeout := countdown === 0.U && active } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object SimpleTimer { def apply(initCount: Int, start: Bool, stop: Bool): Bool = { val timer = Module(new SimpleTimer(initCount)) @@ -72,6 +75,7 @@ object SimpleTimer { } /** Timer with a dynamically-specified period. */ +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class DynamicTimer(w: Int) extends Module { val io = IO(new Bundle { val start = Input(Bool()) diff --git a/src/main/scala/util/TraceCoreInterface.scala b/src/main/scala/util/TraceCoreInterface.scala index fad9263a47d..9c85a5e82e4 100644 --- a/src/main/scala/util/TraceCoreInterface.scala +++ b/src/main/scala/util/TraceCoreInterface.scala @@ -6,6 +6,7 @@ package freechips.rocketchip.util import chisel3._ // Definitions for Trace core Interface defined in RISC-V Processor Trace Specification V1.0 +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") object TraceItype extends ChiselEnum { val ITNothing = Value(0.U) val ITException = Value(1.U) @@ -25,6 +26,7 @@ object TraceItype extends ChiselEnum { val ITInJump = Value(15.U) } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class TraceCoreParams ( val nGroups: Int = 1, val iretireWidth: Int = 1, @@ -32,6 +34,7 @@ class TraceCoreParams ( val iaddrWidth: Int = 32 ) +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class TraceCoreGroup (val params: TraceCoreParams) extends Bundle { val iretire = UInt(params.iretireWidth.W) val iaddr = UInt(params.iaddrWidth.W) @@ -39,6 +42,7 @@ class TraceCoreGroup (val params: TraceCoreParams) extends Bundle { val ilastsize = UInt(1.W) } +@deprecated("moved to standalone rocketutils library", "rocketchip 2.0.0") class TraceCoreInterface (val params: TraceCoreParams) extends Bundle { val group = Vec(params.nGroups, new TraceCoreGroup(params)) val priv = UInt(4.W) diff --git a/src/main/scala/util/package.scala b/src/main/scala/util/package.scala index f67fc7f8d9b..cdf188dce4c 100644 --- a/src/main/scala/util/package.scala +++ b/src/main/scala/util/package.scala @@ -8,22 +8,26 @@ import scala.math.min import scala.collection.{immutable, mutable} package object util { + @deprecated("moved to standalone rocketutils conversion library", "rocketchip 2.0.0") implicit class UnzippableOption[S, T](val x: Option[(S, T)]) { def unzip = (x.map(_._1), x.map(_._2)) } + @deprecated("moved to standalone rocketutils conversion library", "rocketchip 2.0.0") implicit class UIntIsOneOf(private val x: UInt) extends AnyVal { def isOneOf(s: Seq[UInt]): Bool = s.map(x === _).orR def isOneOf(u1: UInt, u2: UInt*): Bool = isOneOf(u1 +: u2.toSeq) } + @deprecated("moved to standalone rocketutils conversion library", "rocketchip 2.0.0") implicit class VecToAugmentedVec[T <: Data](private val x: Vec[T]) extends AnyVal { /** Like Vec.apply(idx), but tolerates indices of mismatched width */ def extract(idx: UInt): T = x((idx | 0.U(log2Ceil(x.size).W)).extract(log2Ceil(x.size) - 1, 0)) } + @deprecated("moved to standalone rocketutils conversion library", "rocketchip 2.0.0") implicit class SeqToAugmentedSeq[T <: Data](private val x: Seq[T]) extends AnyVal { def apply(idx: UInt): T = { if (x.size <= 1) { @@ -70,6 +74,7 @@ package object util { } // allow bitwise ops on Seq[Bool] just like UInt + @deprecated("moved to standalone rocketutils conversion library", "rocketchip 2.0.0") implicit class SeqBoolBitwiseOps(private val x: Seq[Bool]) extends AnyVal { def & (y: Seq[Bool]): Seq[Bool] = (x zip y).map { case (a, b) => a && b } def | (y: Seq[Bool]): Seq[Bool] = padZip(x, y).map { case (a, b) => a || b } @@ -84,6 +89,7 @@ package object util { private def padZip(y: Seq[Bool], z: Seq[Bool]): Seq[(Bool, Bool)] = y.padTo(z.size, false.B) zip z.padTo(y.size, false.B) } + @deprecated("moved to standalone rocketutils conversion library", "rocketchip 2.0.0") implicit class DataToAugmentedData[T <: Data](private val x: T) extends AnyVal { def holdUnless(enable: Bool): T = Mux(enable, x, RegEnable(x, enable)) @@ -94,12 +100,15 @@ package object util { } /** Any Data subtype that has a Bool member named valid. */ + @deprecated("moved to standalone rocketutils conversion library", "rocketchip 2.0.0") type DataCanBeValid = Data { val valid: Bool } + @deprecated("moved to standalone rocketutils conversion library", "rocketchip 2.0.0") implicit class SeqMemToAugmentedSeqMem[T <: Data](private val x: SyncReadMem[T]) extends AnyVal { def readAndHold(addr: UInt, enable: Bool): T = x.read(addr, enable) holdUnless RegNext(enable) } + @deprecated("moved to standalone rocketutils conversion library", "rocketchip 2.0.0") implicit class StringToAugmentedString(private val x: String) extends AnyVal { /** converts from camel case to to underscores, also removing all spaces */ def underscore: String = x.tail.foldLeft(x.headOption.map(_.toLower + "") getOrElse "") { @@ -122,9 +131,12 @@ package object util { def named(name: String): String = named(Some(name)) } + @deprecated("moved to standalone rocketutils conversion library", "rocketchip 2.0.0") implicit def uintToBitPat(x: UInt): BitPat = BitPat(x) + @deprecated("moved to standalone rocketutils conversion library", "rocketchip 2.0.0") implicit def wcToUInt(c: WideCounter): UInt = c.value + @deprecated("moved to standalone rocketutils conversion library", "rocketchip 2.0.0") implicit class UIntToAugmentedUInt(private val x: UInt) extends AnyVal { def sextTo(n: Int): UInt = { require(x.getWidth <= n) @@ -218,11 +230,13 @@ package object util { def >== (y: UInt): Bool = x >= y || y === 0.U } + @deprecated("moved to standalone rocketutils conversion library", "rocketchip 2.0.0") implicit class OptionUIntToAugmentedOptionUInt(private val x: Option[UInt]) extends AnyVal { def ## (y: UInt): UInt = x.map(_ ## y).getOrElse(y) def ## (y: Option[UInt]): Option[UInt] = x.map(_ ## y) } + @deprecated("moved to standalone rocketutils conversion library", "rocketchip 2.0.0") implicit class BooleanToAugmentedBoolean(private val x: Boolean) extends AnyVal { def toInt: Int = if (x) 1 else 0 @@ -230,6 +244,7 @@ package object util { def option[T](z: => T): Option[T] = if (x) Some(z) else None } + @deprecated("moved to standalone rocketutils conversion library", "rocketchip 2.0.0") implicit class IntToAugmentedInt(private val x: Int) extends AnyVal { // exact log2 def log2: Int = { @@ -238,15 +253,22 @@ package object util { } } + @deprecated("moved to standalone rocketutils conversion library", "rocketchip 2.0.0") def OH1ToOH(x: UInt): UInt = (x << 1 | 1.U) & ~Cat(0.U(1.W), x) + @deprecated("moved to standalone rocketutils conversion library", "rocketchip 2.0.0") def OH1ToUInt(x: UInt): UInt = OHToUInt(OH1ToOH(x)) + @deprecated("moved to standalone rocketutils conversion library", "rocketchip 2.0.0") def UIntToOH1(x: UInt, width: Int): UInt = ~((-1).S(width.W).asUInt << x)(width-1, 0) + @deprecated("moved to standalone rocketutils conversion library", "rocketchip 2.0.0") def UIntToOH1(x: UInt): UInt = UIntToOH1(x, (1 << x.getWidth) - 1) + @deprecated("moved to standalone rocketutils conversion library", "rocketchip 2.0.0") def trailingZeros(x: Int): Option[Int] = if (x > 0) Some(log2Ceil(x & -x)) else None // Fill 1s from low bits to high bits + @deprecated("moved to standalone rocketutils conversion library", "rocketchip 2.0.0") def leftOR(x: UInt): UInt = leftOR(x, x.getWidth, x.getWidth) + @deprecated("moved to standalone rocketutils conversion library", "rocketchip 2.0.0") def leftOR(x: UInt, width: Integer, cap: Integer = 999999): UInt = { val stop = min(width, cap) def helper(s: Int, x: UInt): UInt = @@ -255,7 +277,9 @@ package object util { } // Fill 1s form high bits to low bits + @deprecated("moved to standalone rocketutils conversion library", "rocketchip 2.0.0") def rightOR(x: UInt): UInt = rightOR(x, x.getWidth, x.getWidth) + @deprecated("moved to standalone rocketutils conversion library", "rocketchip 2.0.0") def rightOR(x: UInt, width: Integer, cap: Integer = 999999): UInt = { val stop = min(width, cap) def helper(s: Int, x: UInt): UInt = @@ -263,6 +287,7 @@ package object util { helper(1, x)(width-1, 0) } + @deprecated("moved to standalone rocketutils conversion library", "rocketchip 2.0.0") def OptimizationBarrier[T <: Data](in: T): T = { val barrier = Module(new Module { val io = IO(new Bundle { @@ -279,6 +304,7 @@ package object util { /** Similar to Seq.groupBy except this returns a Seq instead of a Map * Useful for deterministic code generation */ + @deprecated("moved to standalone rocketutils conversion library", "rocketchip 2.0.0") def groupByIntoSeq[A, K](xs: Seq[A])(f: A => K): immutable.Seq[(K, immutable.Seq[A])] = { val map = mutable.LinkedHashMap.empty[K, mutable.ListBuffer[A]] for (x <- xs) { @@ -289,6 +315,7 @@ package object util { map.view.map({ case (k, vs) => k -> vs.toList }).toList } + @deprecated("moved to standalone rocketutils conversion library", "rocketchip 2.0.0") def heterogeneousOrGlobalSetting[T](in: Seq[T], n: Int): Seq[T] = in.size match { case 1 => List.fill(n)(in.head) case x if x == n => in