From ba681676f338af158023c99b4c802009aa0b601b Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Fri, 4 Sep 2020 13:29:31 -0700 Subject: [PATCH 1/4] Clean up IOCell types and parameterization --- iocell/src/main/scala/chisel/IOCell.scala | 85 ++++++++++------------- 1 file changed, 36 insertions(+), 49 deletions(-) diff --git a/iocell/src/main/scala/chisel/IOCell.scala b/iocell/src/main/scala/chisel/IOCell.scala index 14c29603..452aaded 100644 --- a/iocell/src/main/scala/chisel/IOCell.scala +++ b/iocell/src/main/scala/chisel/IOCell.scala @@ -4,7 +4,7 @@ package barstools.iocell.chisel import chisel3._ import chisel3.util.{Cat, HasBlackBoxResource} -import chisel3.experimental.{Analog, DataMirror, IO} +import chisel3.experimental.{Analog, DataMirror, IO, BaseModule} // The following four IO cell bundle types are bare-minimum functional connections // for modeling 4 different IO cell scenarios. The intention is that the user @@ -63,76 +63,68 @@ class DigitalInIOCellBundle extends Bundle { val ie = Input(Bool()) } -abstract class IOCell extends BlackBox +trait IOCell extends BaseModule -abstract class AnalogIOCell extends IOCell { - val io: AnalogIOCellBundle +trait AnalogIOCell extends IOCell { + val io = IO(new AnalogIOCellBundle) } -abstract class DigitalGPIOCell extends IOCell { - val io: DigitalGPIOCellBundle +trait DigitalGPIOCell extends IOCell { + val io = IO(new DigitalGPIOCellBundle) } -abstract class DigitalInIOCell extends IOCell { - val io: DigitalInIOCellBundle +trait DigitalInIOCell extends IOCell { + val io = IO(new DigitalInIOCellBundle) } -abstract class DigitalOutIOCell extends IOCell { - val io: DigitalOutIOCellBundle +trait DigitalOutIOCell extends IOCell { + val io = IO(new DigitalOutIOCellBundle) } // The following Generic IO cell black boxes have verilog models that mimic a very simple // implementation of an IO cell. For building a real chip, it is important to implement // and use similar classes which wrap the foundry-specific IO cells. -trait IsGenericIOCell extends HasBlackBoxResource { +abstract class GenericIOCell extends BlackBox with HasBlackBoxResource { addResource("/barstools/iocell/vsrc/IOCell.v") } -class GenericAnalogIOCell extends AnalogIOCell with IsGenericIOCell { - val io = IO(new AnalogIOCellBundle) +class GenericAnalogIOCell extends GenericIOCell with AnalogIOCell +class GenericDigitalGPIOCell extends GenericIOCell with DigitalGPIOCell +class GenericDigitalInIOCell extends GenericIOCell with DigitalInIOCell +class GenericDigitalOutIOCell extends GenericIOCell with DigitalOutIOCell + +trait IOCellTypeParams { + def analog(): AnalogIOCell + def gpio(): DigitalGPIOCell + def input(): DigitalInIOCell + def output(): DigitalOutIOCell } -class GenericDigitalGPIOCell extends DigitalGPIOCell with IsGenericIOCell { - val io = IO(new DigitalGPIOCellBundle) -} - -class GenericDigitalInIOCell extends DigitalInIOCell with IsGenericIOCell { - val io = IO(new DigitalInIOCellBundle) -} - -class GenericDigitalOutIOCell extends DigitalOutIOCell with IsGenericIOCell { - val io = IO(new DigitalOutIOCellBundle) +case class GenericIOCellParams() extends IOCellTypeParams { + def analog() = Module(new GenericAnalogIOCell) + def gpio() = Module(new GenericDigitalGPIOCell) + def input() = Module(new GenericDigitalInIOCell) + def output() = Module(new GenericDigitalOutIOCell) } object IOCell { - - def genericAnalog() = Module(new GenericAnalogIOCell) - def genericGPIO() = Module(new GenericDigitalGPIOCell) - def genericInput() = Module(new GenericDigitalInIOCell) - def genericOutput() = Module(new GenericDigitalOutIOCell) - /** * From within a RawModule or MultiIOModule context, generate new module IOs from a given * signal and return the new IO and a Seq containing all generated IO cells. * @param coreSignal The signal onto which to add IO cells * @param name An optional name or name prefix to use for naming IO cells - * @param inFn A function to generate a DigitalInIOCell to use for input signals - * @param outFn A function to generate a DigitalOutIOCell to use for output signals - * @param anaFn A function to generate an AnalogIOCell to use for analog signals * @param abstractResetAsAsync When set, will coerce abstract resets to * AsyncReset, and otherwise to Bool (sync reset) * @return A tuple of (the generated IO data node, a Seq of all generated IO cell instances) */ def generateIOFromSignal[T <: Data](coreSignal: T, name: Option[String] = None, - inFn: () => DigitalInIOCell = IOCell.genericInput, - outFn: () => DigitalOutIOCell = IOCell.genericOutput, - anaFn: () => AnalogIOCell = IOCell.genericAnalog, + typeParams: IOCellTypeParams = GenericIOCellParams(), abstractResetAsAsync: Boolean = false): (T, Seq[IOCell]) = { val padSignal = IO(DataMirror.internal.chiselTypeClone[T](coreSignal)) val resetFn = if (abstractResetAsAsync) toAsyncReset else toSyncReset - val iocells = IOCell.generateFromSignal(coreSignal, padSignal, name, inFn, outFn, anaFn, resetFn) + val iocells = IOCell.generateFromSignal(coreSignal, padSignal, name, typeParams, resetFn) (padSignal, iocells) } @@ -142,9 +134,6 @@ object IOCell { * @param coreSignal The core-side (internal) signal onto which to connect/add IO cells * @param padSignal The pad-side (external) signal onto which to connect IO cells * @param name An optional name or name prefix to use for naming IO cells - * @param inFn A function to generate a DigitalInIOCell to use for input signals - * @param outFn A function to generate a DigitalOutIOCell to use for output signals - * @param anaFn A function to generate an AnalogIOCell to use for analog signals * @return A Seq of all generated IO cell instances */ val toSyncReset: (Reset) => Bool = _.toBool @@ -153,9 +142,7 @@ object IOCell { coreSignal: T, padSignal: T, name: Option[String] = None, - inFn: () => DigitalInIOCell = IOCell.genericInput, - outFn: () => DigitalOutIOCell = IOCell.genericOutput, - anaFn: () => AnalogIOCell = IOCell.genericAnalog, + typeParams: IOCellTypeParams = GenericIOCellParams(), concretizeResetFn : (Reset) => R = toSyncReset): Seq[IOCell] = { def genCell[T <: Data]( @@ -165,7 +152,7 @@ object IOCell { padSignal: T): Seq[IOCell] = { DataMirror.directionOf(coreSignal) match { case ActualDirection.Input => { - val iocell = inFn() + val iocell = typeParams.input() name.foreach(n => iocell.suggestName(n)) coreSignal := castFromBool(iocell.io.i) iocell.io.ie := true.B @@ -173,7 +160,7 @@ object IOCell { Seq(iocell) } case ActualDirection.Output => { - val iocell = outFn() + val iocell = typeParams.output() name.foreach(n => iocell.suggestName(n)) iocell.io.o := castToBool(coreSignal) iocell.io.oe := true.B @@ -193,7 +180,7 @@ object IOCell { Seq() } else { require(coreSignal.getWidth == 1, "Analogs wider than 1 bit are not supported because we can't bit-select Analogs (https://github.com/freechipsproject/chisel3/issues/536)") - val iocell = anaFn() + val iocell = typeParams.analog() name.foreach(n => iocell.suggestName(n)) iocell.io.core <> coreSignal padSignal <> iocell.io.pad @@ -215,7 +202,7 @@ object IOCell { DataMirror.directionOf(coreSignal) match { case ActualDirection.Input => { val iocells = padSignal.asBools.zipWithIndex.map { case (sig, i) => - val iocell = inFn() + val iocell = typeParams.input() // Note that we are relying on chisel deterministically naming this in the index order (which it does) // This has the side-effect of naming index 0 with no _0 suffix, which is how chisel names other signals // An alternative solution would be to suggestName(n + "_" + i) @@ -230,7 +217,7 @@ object IOCell { } case ActualDirection.Output => { val iocells = coreSignal.asBools.zipWithIndex.map { case (sig, i) => - val iocell = outFn() + val iocell = typeParams.output() // Note that we are relying on chisel deterministically naming this in the index order (which it does) // This has the side-effect of naming index 0 with no _0 suffix, which is how chisel names other signals // An alternative solution would be to suggestName(n + "_" + i) @@ -251,14 +238,14 @@ object IOCell { case (coreSignal: Vec[_], padSignal: Vec[_]) => { require(padSignal.size == coreSignal.size, "size of Vec for padSignal and coreSignal must be the same") coreSignal.zip(padSignal).zipWithIndex.foldLeft(Seq.empty[IOCell]) { case (total, ((core, pad), i)) => - val ios = IOCell.generateFromSignal(core, pad, name.map(_ + "_" + i), inFn, outFn, anaFn) + val ios = IOCell.generateFromSignal(core, pad, name.map(_ + "_" + i), typeParams) total ++ ios } } case (coreSignal: Record, padSignal: Record) => { coreSignal.elements.foldLeft(Seq.empty[IOCell]) { case (total, (eltName, core)) => val pad = padSignal.elements(eltName) - val ios = IOCell.generateFromSignal(core, pad, name.map(_ + "_" + eltName), inFn, outFn, anaFn) + val ios = IOCell.generateFromSignal(core, pad, name.map(_ + "_" + eltName), typeParams) total ++ ios } } From 31590a7948db47fd16beed266c4833579acc305b Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Mon, 14 Sep 2020 13:24:44 -0700 Subject: [PATCH 2/4] Undo regression in iocell flexibility --- iocell/src/main/scala/chisel/IOCell.scala | 25 +++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/iocell/src/main/scala/chisel/IOCell.scala b/iocell/src/main/scala/chisel/IOCell.scala index 452aaded..93dfac2f 100644 --- a/iocell/src/main/scala/chisel/IOCell.scala +++ b/iocell/src/main/scala/chisel/IOCell.scala @@ -66,19 +66,19 @@ class DigitalInIOCellBundle extends Bundle { trait IOCell extends BaseModule trait AnalogIOCell extends IOCell { - val io = IO(new AnalogIOCellBundle) + val io: AnalogIOCellBundle } trait DigitalGPIOCell extends IOCell { - val io = IO(new DigitalGPIOCellBundle) + val io: DigitalGPIOCellBundle } trait DigitalInIOCell extends IOCell { - val io = IO(new DigitalInIOCellBundle) + val io: DigitalInIOCellBundle } trait DigitalOutIOCell extends IOCell { - val io = IO(new DigitalOutIOCellBundle) + val io: DigitalOutIOCellBundle } // The following Generic IO cell black boxes have verilog models that mimic a very simple @@ -89,10 +89,19 @@ abstract class GenericIOCell extends BlackBox with HasBlackBoxResource { addResource("/barstools/iocell/vsrc/IOCell.v") } -class GenericAnalogIOCell extends GenericIOCell with AnalogIOCell -class GenericDigitalGPIOCell extends GenericIOCell with DigitalGPIOCell -class GenericDigitalInIOCell extends GenericIOCell with DigitalInIOCell -class GenericDigitalOutIOCell extends GenericIOCell with DigitalOutIOCell +class GenericAnalogIOCell extends GenericIOCell with AnalogIOCell { + val io = IO(new AnalogIOCellBundle) +} +class GenericDigitalGPIOCell extends GenericIOCell with DigitalGPIOCell { + val io = IO(new DigitalGPIOCellBundle) +} +class GenericDigitalInIOCell extends GenericIOCell with DigitalInIOCell { + val io = IO(new DigitalInIOCellBundle) +} +class GenericDigitalOutIOCell extends GenericIOCell with DigitalOutIOCell { + val io = IO(new DigitalOutIOCellBundle) +} + trait IOCellTypeParams { def analog(): AnalogIOCell From 847f72eca0fa3207ab7140c07e980ac9f8cf1251 Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Mon, 14 Sep 2020 19:39:44 -0700 Subject: [PATCH 3/4] Support plusarg_reader blackbox in the harness --- tapeout/src/main/scala/transforms/Generate.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tapeout/src/main/scala/transforms/Generate.scala b/tapeout/src/main/scala/transforms/Generate.scala index 89df8b55..3ed105fe 100644 --- a/tapeout/src/main/scala/transforms/Generate.scala +++ b/tapeout/src/main/scala/transforms/Generate.scala @@ -221,7 +221,7 @@ sealed trait GenerateTopAndHarnessApp extends LazyLogging { this: App => // Execute top and get list of ExtModules to avoid collisions val topExtModules = executeTop() - val externals = Seq("SimSerial", "SimDTM") ++ harnessTop ++ synTop + val externals = Seq("SimSerial", "SimDTM", "plusarg_reader") ++ harnessTop ++ synTop val harnessAnnos = tapeoutOptions.harnessDotfOut.map(BlackBoxResourceFileNameAnno(_)).toSeq ++ From 4a5c75fcf85f03af858f1d7db04303d4b0733de7 Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Thu, 17 Sep 2020 13:21:32 -0700 Subject: [PATCH 4/4] Add explicit naming of IOs generated by generateIOFromSignal --- iocell/src/main/scala/chisel/IOCell.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/iocell/src/main/scala/chisel/IOCell.scala b/iocell/src/main/scala/chisel/IOCell.scala index 93dfac2f..a5926030 100644 --- a/iocell/src/main/scala/chisel/IOCell.scala +++ b/iocell/src/main/scala/chisel/IOCell.scala @@ -127,13 +127,13 @@ object IOCell { * AsyncReset, and otherwise to Bool (sync reset) * @return A tuple of (the generated IO data node, a Seq of all generated IO cell instances) */ - def generateIOFromSignal[T <: Data](coreSignal: T, name: Option[String] = None, + def generateIOFromSignal[T <: Data](coreSignal: T, name: String, typeParams: IOCellTypeParams = GenericIOCellParams(), abstractResetAsAsync: Boolean = false): (T, Seq[IOCell]) = { - val padSignal = IO(DataMirror.internal.chiselTypeClone[T](coreSignal)) + val padSignal = IO(DataMirror.internal.chiselTypeClone[T](coreSignal)).suggestName(name) val resetFn = if (abstractResetAsAsync) toAsyncReset else toSyncReset - val iocells = IOCell.generateFromSignal(coreSignal, padSignal, name, typeParams, resetFn) + val iocells = IOCell.generateFromSignal(coreSignal, padSignal, Some(s"iocell_$name"), typeParams, resetFn) (padSignal, iocells) }