From 368dde4a359b8e4b9d889b46273d40097f60ffcd Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Sun, 30 Jul 2023 13:12:55 -0700 Subject: [PATCH 1/3] Generate 1 file per generic IOCell --- .../barstools/iocell/chisel/IOCell.scala | 58 ++++++++++++++++++- 1 file changed, 55 insertions(+), 3 deletions(-) diff --git a/iocell/src/main/scala/barstools/iocell/chisel/IOCell.scala b/iocell/src/main/scala/barstools/iocell/chisel/IOCell.scala index 457fa12b..bdde178e 100644 --- a/iocell/src/main/scala/barstools/iocell/chisel/IOCell.scala +++ b/iocell/src/main/scala/barstools/iocell/chisel/IOCell.scala @@ -3,7 +3,7 @@ package barstools.iocell.chisel import chisel3._ -import chisel3.util.{Cat, HasBlackBoxResource} +import chisel3.util.{Cat, HasBlackBoxResource, HasBlackBoxInline} import chisel3.experimental.{Analog, BaseModule, DataMirror, IO} // The following four IO cell bundle types are bare-minimum functional connections @@ -93,21 +93,73 @@ trait DigitalOutIOCell extends IOCell { // 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. -abstract class GenericIOCell extends BlackBox with HasBlackBoxResource { - addResource("/barstools/iocell/vsrc/IOCell.v") +abstract class GenericIOCell extends BlackBox with HasBlackBoxInline { + val impl: String + val moduleName = this.getClass.getSimpleName + setInline(s"$moduleName.v", impl); } class GenericAnalogIOCell extends GenericIOCell with AnalogIOCell { val io = IO(new AnalogIOCellBundle) + lazy val impl = s""" +`timescale 1ns/1ps +module GenericAnalogIOCell( + inout pad, + inout core +); + + assign core = 1'bz; + assign pad = core; + +endmodule""" } + class GenericDigitalGPIOCell extends GenericIOCell with DigitalGPIOCell { val io = IO(new DigitalGPIOCellBundle) + lazy val impl = s""" +`timescale 1ns/1ps +module GenericDigitalGPIOCell( + inout pad, + output i, + input ie, + input o, + input oe +); + + assign pad = oe ? o : 1'bz; + assign i = ie ? pad : 1'b0; + +endmodule""" } + class GenericDigitalInIOCell extends GenericIOCell with DigitalInIOCell { val io = IO(new DigitalInIOCellBundle) + lazy val impl = s""" +`timescale 1ns/1ps +module GenericDigitalInIOCell( + input pad, + output i, + input ie +); + + assign i = ie ? pad : 1'b0; + +endmodule""" } + class GenericDigitalOutIOCell extends GenericIOCell with DigitalOutIOCell { val io = IO(new DigitalOutIOCellBundle) + lazy val impl = s""" +`timescale 1ns/1ps +module GenericDigitalOutIOCell( + output pad, + input o, + input oe +); + + assign pad = oe ? o : 1'bz; + +endmodule""" } trait IOCellTypeParams { From c8723f40b15218025216db90fd4cc16d6e9eacfd Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Sun, 30 Jul 2023 13:17:26 -0700 Subject: [PATCH 2/3] Macrocompiler: FIRRTL-elab macros 1-at-a-time Elaborating all macros in a single Circuit with an arbitrary (last) macro selected as the circuit main main cause some macros to be dropped, even with the DCEAnnotation. Work around this for now by elaborating each module in the macrocompiled circuit independently, then concatenating the verilog. --- .../barstools/macros/MacroCompiler.scala | 39 +++++++++++++------ 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/src/main/scala/barstools/macros/MacroCompiler.scala b/src/main/scala/barstools/macros/MacroCompiler.scala index 968e6b30..baed8411 100644 --- a/src/main/scala/barstools/macros/MacroCompiler.scala +++ b/src/main/scala/barstools/macros/MacroCompiler.scala @@ -14,7 +14,6 @@ import firrtl.ir._ import firrtl.options.Dependency import firrtl.stage.TransformManager.TransformDependency import firrtl.stage.{FirrtlSourceAnnotation, FirrtlStage, Forms, OutputFileAnnotation, RunFirrtlTransformAnnotation} -import firrtl.transforms.NoDCEAnnotation import firrtl.{PrimOps, _} import mdf.macrolib.{PolarizedPort, PortPolarity, SRAMCompiler, SRAMGroup, SRAMMacro} @@ -898,16 +897,34 @@ object MacroCompiler extends App { val macroCompiled = (new MacroCompilerTransform).execute(macroCompilerInput) // Run FIRRTL compiler - (new FirrtlStage).execute( - Array.empty, - Seq( - OutputFileAnnotation(params.getOrElse(Verilog, "")), - RunFirrtlTransformAnnotation(new VerilogEmitter), - EmitCircuitAnnotation(classOf[VerilogEmitter]), - NoDCEAnnotation, - FirrtlSourceAnnotation(macroCompiled.circuit.serialize) - ) - ) + // For each generated module, have to create a new circuit with that module + // as top, and all other modules as ExtModules. This guarantees all modules + // are elaborated + val verilog = macroCompiled.circuit.modules + .map(_.name) + .map { macroName => + val (mainMod, otherMods) = macroCompiled.circuit.modules.partition(_.name == macroName) + val extMods = otherMods.map(m => ExtModule(NoInfo, m.name, m.ports, m.name, Nil)) + + val circuit = Circuit(NoInfo, mainMod ++ extMods, macroName) + (new FirrtlStage) + .execute( + Array.empty, + Seq( + RunFirrtlTransformAnnotation(new VerilogEmitter), + EmitCircuitAnnotation(classOf[VerilogEmitter]), + FirrtlSourceAnnotation(circuit.serialize) + ) + ) + .collect { case c: EmittedVerilogCircuitAnnotation => c } + .head + .value + .value + } + .mkString("\n") + val verilogWriter = new FileWriter(new File(params.get(Verilog).get)) + verilogWriter.write(verilog) + verilogWriter.close() params.get(HammerIR) match { case Some(hammerIRFile: String) => From f5fe37c4bf0a37eb5033eeaf930c337895470607 Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Mon, 31 Jul 2023 09:52:15 -0700 Subject: [PATCH 3/3] Delete IOCell.v --- .../resources/barstools/iocell/vsrc/IOCell.v | 46 ------------------- 1 file changed, 46 deletions(-) delete mode 100644 iocell/src/main/resources/barstools/iocell/vsrc/IOCell.v diff --git a/iocell/src/main/resources/barstools/iocell/vsrc/IOCell.v b/iocell/src/main/resources/barstools/iocell/vsrc/IOCell.v deleted file mode 100644 index 8023fb70..00000000 --- a/iocell/src/main/resources/barstools/iocell/vsrc/IOCell.v +++ /dev/null @@ -1,46 +0,0 @@ -// See LICENSE for license details - -`timescale 1ns/1ps - -module GenericAnalogIOCell( - inout pad, - inout core -); - - assign core = 1'bz; - assign pad = core; - -endmodule - -module GenericDigitalGPIOCell( - inout pad, - output i, - input ie, - input o, - input oe -); - - assign pad = oe ? o : 1'bz; - assign i = ie ? pad : 1'b0; - -endmodule - -module GenericDigitalInIOCell( - input pad, - output i, - input ie -); - - assign i = ie ? pad : 1'b0; - -endmodule - -module GenericDigitalOutIOCell( - output pad, - input o, - input oe -); - - assign pad = oe ? o : 1'bz; - -endmodule