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 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 { 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) =>