Improve GCD example

This commit is contained in:
Jerry Zhao
2024-01-22 18:32:48 -08:00
parent 45f5fe832d
commit 5a553741f0

View File

@@ -4,6 +4,7 @@ import chisel3._
import chisel3.util._ import chisel3.util._
import chisel3.experimental.{IntParam, BaseModule} import chisel3.experimental.{IntParam, BaseModule}
import freechips.rocketchip.amba.axi4._ import freechips.rocketchip.amba.axi4._
import freechips.rocketchip.prci._
import freechips.rocketchip.subsystem.BaseSubsystem import freechips.rocketchip.subsystem.BaseSubsystem
import org.chipsalliance.cde.config.{Parameters, Field, Config} import org.chipsalliance.cde.config.{Parameters, Field, Config}
import freechips.rocketchip.diplomacy._ import freechips.rocketchip.diplomacy._
@@ -36,27 +37,24 @@ class GCDIO(val w: Int) extends Bundle {
val busy = Output(Bool()) val busy = Output(Bool())
} }
trait GCDTopIO extends Bundle { class GCDTopIO extends Bundle {
val gcd_busy = Output(Bool()) val gcd_busy = Output(Bool())
} }
trait HasGCDIO extends BaseModule { trait HasGCDTopIO {
val w: Int def io: GCDTopIO
val io = IO(new GCDIO(w))
} }
// DOC include start: GCD blackbox // DOC include start: GCD blackbox
class GCDMMIOBlackBox(val w: Int) extends BlackBox(Map("WIDTH" -> IntParam(w))) with HasBlackBoxResource class GCDMMIOBlackBox(val w: Int) extends BlackBox(Map("WIDTH" -> IntParam(w))) with HasBlackBoxResource {
with HasGCDIO val io = IO(new GCDIO(w))
{
addResource("/vsrc/GCDMMIOBlackBox.v") addResource("/vsrc/GCDMMIOBlackBox.v")
} }
// DOC include end: GCD blackbox // DOC include end: GCD blackbox
// DOC include start: GCD chisel // DOC include start: GCD chisel
class GCDMMIOChiselModule(val w: Int) extends Module class GCDMMIOChiselModule(val w: Int) extends Module {
with HasGCDIO val io = IO(new GCDIO(w))
{
val s_idle :: s_run :: s_done :: Nil = Enum(3) val s_idle :: s_run :: s_done :: Nil = Enum(3)
val state = RegInit(s_idle) val state = RegInit(s_idle)
@@ -90,70 +88,111 @@ class GCDMMIOChiselModule(val w: Int) extends Module
} }
// DOC include end: GCD chisel // DOC include end: GCD chisel
// DOC include start: GCD instance regmap
trait GCDModule extends HasRegMap {
val io: GCDTopIO
implicit val p: Parameters
def params: GCDParams
val clock: Clock
val reset: Reset
// How many clock cycles in a PWM cycle?
val x = Reg(UInt(params.width.W))
val y = Wire(new DecoupledIO(UInt(params.width.W)))
val gcd = Wire(new DecoupledIO(UInt(params.width.W)))
val status = Wire(UInt(2.W))
val impl = if (params.useBlackBox) {
Module(new GCDMMIOBlackBox(params.width))
} else {
Module(new GCDMMIOChiselModule(params.width))
}
impl.io.clock := clock
impl.io.reset := reset.asBool
impl.io.x := x
impl.io.y := y.bits
impl.io.input_valid := y.valid
y.ready := impl.io.input_ready
gcd.bits := impl.io.gcd
gcd.valid := impl.io.output_valid
impl.io.output_ready := gcd.ready
status := Cat(impl.io.input_ready, impl.io.output_valid)
io.gcd_busy := impl.io.busy
regmap(
0x00 -> Seq(
RegField.r(2, status)), // a read-only register capturing current status
0x04 -> Seq(
RegField.w(params.width, x)), // a plain, write-only register
0x08 -> Seq(
RegField.w(params.width, y)), // write-only, y.valid is set on write
0x0C -> Seq(
RegField.r(params.width, gcd))) // read-only, gcd.ready is set on read
}
// DOC include end: GCD instance regmap
// DOC include start: GCD router // DOC include start: GCD router
class GCDTL(params: GCDParams, beatBytes: Int)(implicit p: Parameters) class GCDTL(params: GCDParams, beatBytes: Int)(implicit p: Parameters) extends ClockSinkDomain(ClockSinkParameters())(p) {
extends TLRegisterRouter( val device = new SimpleDevice("gcd", Seq("ucbbar,gcd")) {
params.address, "gcd", Seq("ucbbar,gcd"), override def describe(resources: ResourceBindings): Description = {
beatBytes = beatBytes)( val Description(name, mapping) = super.describe(resources)
new TLRegBundle(params, _) with GCDTopIO)( Description(name, mapping)
new TLRegModule(params, _, _) with GCDModule) }
}
val node = TLRegisterNode(Seq(AddressSet(params.address, 4096-1)), device, "reg/control", beatBytes=beatBytes)
class GCDAXI4(params: GCDParams, beatBytes: Int)(implicit p: Parameters) override lazy val module = new GCDImpl
extends AXI4RegisterRouter( class GCDImpl extends Impl with HasGCDTopIO {
params.address, val io = IO(new GCDTopIO)
beatBytes=beatBytes)( withClockAndReset(clock, reset) {
new AXI4RegBundle(params, _) with GCDTopIO)( // How many clock cycles in a PWM cycle?
new AXI4RegModule(params, _, _) with GCDModule) val x = Reg(UInt(params.width.W))
val y = Wire(new DecoupledIO(UInt(params.width.W)))
val gcd = Wire(new DecoupledIO(UInt(params.width.W)))
val status = Wire(UInt(2.W))
val impl_io = if (params.useBlackBox) {
val impl = Module(new GCDMMIOBlackBox(params.width))
impl.io
} else {
val impl = Module(new GCDMMIOChiselModule(params.width))
impl.io
}
impl_io.clock := clock
impl_io.reset := reset.asBool
impl_io.x := x
impl_io.y := y.bits
impl_io.input_valid := y.valid
y.ready := impl_io.input_ready
gcd.bits := impl_io.gcd
gcd.valid := impl_io.output_valid
impl_io.output_ready := gcd.ready
status := Cat(impl_io.input_ready, impl_io.output_valid)
io.gcd_busy := impl_io.busy
// DOC include start: GCD instance regmap
node.regmap(
0x00 -> Seq(
RegField.r(2, status)), // a read-only register capturing current status
0x04 -> Seq(
RegField.w(params.width, x)), // a plain, write-only register
0x08 -> Seq(
RegField.w(params.width, y)), // write-only, y.valid is set on write
0x0C -> Seq(
RegField.r(params.width, gcd))) // read-only, gcd.ready is set on read
// DOC include end: GCD instance regmap
}
}
}
class GCDAXI4(params: GCDParams, beatBytes: Int)(implicit p: Parameters) extends ClockSinkDomain(ClockSinkParameters())(p) {
val node = AXI4RegisterNode(AddressSet(params.address, 4096-1), beatBytes=beatBytes)
override lazy val module = new GCDImpl
class GCDImpl extends Impl with HasGCDTopIO {
val io = IO(new GCDTopIO)
withClockAndReset(clock, reset) {
// How many clock cycles in a PWM cycle?
val x = Reg(UInt(params.width.W))
val y = Wire(new DecoupledIO(UInt(params.width.W)))
val gcd = Wire(new DecoupledIO(UInt(params.width.W)))
val status = Wire(UInt(2.W))
val impl_io = if (params.useBlackBox) {
val impl = Module(new GCDMMIOBlackBox(params.width))
impl.io
} else {
val impl = Module(new GCDMMIOChiselModule(params.width))
impl.io
}
impl_io.clock := clock
impl_io.reset := reset.asBool
impl_io.x := x
impl_io.y := y.bits
impl_io.input_valid := y.valid
y.ready := impl_io.input_ready
gcd.bits := impl_io.gcd
gcd.valid := impl_io.output_valid
impl_io.output_ready := gcd.ready
status := Cat(impl_io.input_ready, impl_io.output_valid)
io.gcd_busy := impl_io.busy
node.regmap(
0x00 -> Seq(
RegField.r(2, status)), // a read-only register capturing current status
0x04 -> Seq(
RegField.w(params.width, x)), // a plain, write-only register
0x08 -> Seq(
RegField.w(params.width, y)), // write-only, y.valid is set on write
0x0C -> Seq(
RegField.r(params.width, gcd))) // read-only, gcd.ready is set on read
}
}
}
// DOC include end: GCD router // DOC include end: GCD router
// DOC include start: GCD lazy trait // DOC include start: GCD lazy trait
@@ -164,7 +203,8 @@ trait CanHavePeripheryGCD { this: BaseSubsystem =>
val gcd_busy = p(GCDKey) match { val gcd_busy = p(GCDKey) match {
case Some(params) => { case Some(params) => {
val gcd = if (params.useAXI4) { val gcd = if (params.useAXI4) {
val gcd = pbus { LazyModule(new GCDAXI4(params, pbus.beatBytes)(p)) } val gcd = LazyModule(new GCDAXI4(params, pbus.beatBytes)(p))
gcd.clockNode := pbus.fixedClockNode
pbus.coupleTo(portName) { pbus.coupleTo(portName) {
gcd.node := gcd.node :=
AXI4Buffer () := AXI4Buffer () :=
@@ -174,18 +214,14 @@ trait CanHavePeripheryGCD { this: BaseSubsystem =>
} }
gcd gcd
} else { } else {
val gcd = pbus { LazyModule(new GCDTL(params, pbus.beatBytes)(p)) } val gcd = LazyModule(new GCDTL(params, pbus.beatBytes)(p))
gcd.clockNode := pbus.fixedClockNode
pbus.coupleTo(portName) { gcd.node := TLFragmenter(pbus.beatBytes, pbus.blockBytes) := _ } pbus.coupleTo(portName) { gcd.node := TLFragmenter(pbus.beatBytes, pbus.blockBytes) := _ }
gcd gcd
} }
val pbus_io = pbus { InModuleBody {
val busy = IO(Output(Bool()))
busy := gcd.module.io.gcd_busy
busy
}}
val gcd_busy = InModuleBody { val gcd_busy = InModuleBody {
val busy = IO(Output(Bool())).suggestName("gcd_busy") val busy = IO(Output(Bool())).suggestName("gcd_busy")
busy := pbus_io busy := gcd.module.io.gcd_busy
busy busy
} }
Some(gcd_busy) Some(gcd_busy)