Open uduse opened 1 year ago
This would be a welcome addition!
A few notes:
All instances in the module are PrimitiveCalls or other types of leaf nodes.
Particularly re the "other types of leaf nodes": Hdl21 has four Instantiable
types -
Instantiable = Union[Module, ExternalModuleCall, GeneratorCall, PrimitiveCall]
I.e. those are the four kinds of things that can be the target of an hdl21.Instance
.
Of those, two are "irreducible": primitives (PrimitiveCall
) and external-modules (ExternalModuleCall
). These would be the leaf-nodes when flattening.
Another (bonus!) feature would be adding the capacity for a "stop list" of Module
s and/or GeneratorCall
s, which when detected would just be turned into ExternalModuleCall
s. Such things are common in popular "big EDA" software.
Module signals are the signals from all levels and the ports from all non-root levels.
I think that is potentially true, depending whether you'd want to include "floating" Signal
s, i.e. those which don't ultimately reach a leaf-level component.
Do Modules actually have these? Sure! They have all kinds of weird stuff, both intentionally and not. E.g. for:
Does it matter whether we do? Probably not; if the source-Module has floating Signals, I suppose it makes sense to just transfer them along to the flattened-Module. (Inside of a SPICE simulator, in contrast, you'd need to filter these out, or generally get a singular matrix due to them.)
Where should this feature go in Hdl21 file structure? elab
? Additionally, what role does Bundle
play in this feature? (I have no idea how Bundle
works...)
I think a package-level hdl21.flatten
module, with a flatten()
function, would be a good place.
And you shouldn't have to even notice Bundles are a thing, if you invoke elaboration before the flattening-work. So flatten()
might look something like:
def flatten(m: Module) -> Module:
elaborate(m)
return flattening_stuff_youre_already_doing(m)
def flattening_stuff_youre_already_doing(m: Module) -> Module:
# Ya know, the stuff you're already doing!
Why we need it
Hierarchical information might not be needed for some use cases. For example, listing out all MOSes and compute their total area. It would be nice to have a functionality that flattens a module into a module with a single layer.
Specifications
(partial credit from @dan-fritchman)
PrimitiveCall
s or other types of leaf nodes.Example
I have a small script to do this for simple cases (will PR later).
Source Module Vlsir
``` modules { name: "src.hdl.Inverter" ports { signal: "vdd" direction: NONE } ports { signal: "vss" direction: NONE } ports { signal: "vin" direction: NONE } ports { signal: "vout" direction: NONE } signals { name: "vdd" width: 1 } signals { name: "vss" width: 1 } signals { name: "vin" width: 1 } signals { name: "vout" width: 1 } instances { name: "pmos" module { external { domain: "hdl21.primitives" name: "Mos" } } parameters { name: "tp" value { literal: "PMOS" } } connections { portname: "d" target { sig: "vout" } } connections { portname: "g" target { sig: "vin" } } connections { portname: "s" target { sig: "vdd" } } } instances { name: "nmos" module { external { domain: "hdl21.primitives" name: "Mos" } } parameters { name: "tp" value { literal: "NMOS" } } connections { portname: "d" target { sig: "vout" } } connections { portname: "g" target { sig: "vin" } } connections { portname: "s" target { sig: "vss" } } } } modules { name: "src.hdl.Buffer" ports { signal: "vdd" direction: NONE } ports { signal: "vss" direction: NONE } ports { signal: "vin" direction: NONE } ports { signal: "vout" direction: NONE } signals { name: "n0" width: 1 } signals { name: "vdd" width: 1 } signals { name: "vss" width: 1 } signals { name: "vin" width: 1 } signals { name: "vout" width: 1 } instances { name: "inv_1" module { local: "src.hdl.Inverter" } connections { portname: "vdd" target { sig: "vdd" } } connections { portname: "vss" target { sig: "vss" } } connections { portname: "vin" target { sig: "vin" } } connections { portname: "vout" target { sig: "n0" } } } instances { name: "inv_2" module { local: "src.hdl.Inverter" } connections { portname: "vdd" target { sig: "vdd" } } connections { portname: "vss" target { sig: "vss" } } connections { portname: "vin" target { sig: "n0" } } connections { portname: "vout" target { sig: "vout" } } } } ```Flattened Module Vlsir
``` modules { name: "Buffer_flat" ports { signal: "vdd" direction: NONE } ports { signal: "vss" direction: NONE } ports { signal: "vin" direction: NONE } ports { signal: "vout" direction: NONE } signals { name: "n0" width: 1 } signals { name: "vdd" width: 1 } signals { name: "vss" width: 1 } signals { name: "vin" width: 1 } signals { name: "vout" width: 1 } instances { name: "inv_1:pmos" module { external { domain: "hdl21.primitives" name: "Mos" } } parameters { name: "tp" value { literal: "PMOS" } } connections { portname: "d" target { sig: "n0" } } connections { portname: "g" target { sig: "vin" } } connections { portname: "s" target { sig: "vdd" } } } instances { name: "inv_1:nmos" module { external { domain: "hdl21.primitives" name: "Mos" } } parameters { name: "tp" value { literal: "NMOS" } } connections { portname: "d" target { sig: "n0" } } connections { portname: "g" target { sig: "vin" } } connections { portname: "s" target { sig: "vss" } } } instances { name: "inv_2:pmos" module { external { domain: "hdl21.primitives" name: "Mos" } } parameters { name: "tp" value { literal: "PMOS" } } connections { portname: "d" target { sig: "vout" } } connections { portname: "g" target { sig: "n0" } } connections { portname: "s" target { sig: "vdd" } } } instances { name: "inv_2:nmos" module { external { domain: "hdl21.primitives" name: "Mos" } } parameters { name: "tp" value { literal: "NMOS" } } connections { portname: "d" target { sig: "vout" } } connections { portname: "g" target { sig: "n0" } } connections { portname: "s" target { sig: "vss" } } } } ```