Targets
DeviceLayout.SchematicDrivenLayout.Target — Typeabstract type TargetA Target can customize behavior during plan, build!, and/or render!.
Given a target::Target, you would use it like this:
g = SchematicGraph("example")
# ... build up schematic graph here
floorplan = plan(g, target)
check!(floorplan)
build!(floorplan, target)
output = Cell(floorplan, target)DeviceLayout.SchematicDrivenLayout.LayoutTarget — Typestruct LayoutTarget <: Target
technology::ProcessTechnology
rendering_options::NamedTuple
levels::Vector{Int}
level_increment::GDSMeta
indexed_layers::Vector{Symbol}
map_meta_dict::Dict{DeviceLayout.Meta, Union{GDSMeta,Nothing}}
endContains information about how to render schematics, typically to a Cell (for the GDSII backend).
A LayoutTarget contains:
technology::ProcessTechnology: used to map semantic layers to output layers whenrendering to an output format (usinglayer_record(technology)).rendering_options: aNamedTupleof keyword arguments to be supplied torender!levels::Vector{Int}: a list of metadata levels to be renderedlevel_increment::GDSMeta: if there are multiple levels in the list, each successive level in the list will have its GDSMeta remapped by this incrementindexed_layers::Vector{Symbol}: a list of layer symbols whose entities should have GDS datatype incremented by their metadata index, for example to give distinct layers to different port boundaries for simulationmap_meta_dict::Dict{SemanticMeta, Union{GDSMeta,Nothing}}: used for memoization of theSemanticMeta -> GDSMetamap; it can also be populated manually to customize behavior
Rendering options might include tolerance (atol) or keyword flags like simulation=true that determine how or whether entities with an OptionalStyle with the corresponding flag are rendered.
When rendering ent::GeometryEntity with target::LayoutTarget, its metadata m is handled as follows:
- If
mis already aGDSMeta, use as is. - If
target.map_meta_dict[m]exists (as aGDSMetainstance ornothing), use that. This can be manually assigned before rendering, overriding the default that would result from the steps below. If it does not yet exist, then the result of the steps below will be stored intarget.map_meta_dict[m]. - If
layer(m) == layer(DeviceLayout.NORENDER_META)(that is,:norender), usenothing. - If
!(level(m) in target.levels), usenothing. - If
layer(m)is not present as a key inlayer_record(target.technology)and is not of the form:GDS<layer>_<datatype>, then emit a warning and useGDSMeta(0,0), ignoring level and layer index. - If
layer(m)is not present as a key inlayer_record(target.technology)but is of the form:GDS<layer>_<datatype>, then takeGDSMeta(layer, datatype)and add any increments according tolevel(m)andlayerindex(m)as below. - If
layer(m)is present as a key inlayer_record(target.technology), then maplayer(m)to aGDSMetaornothingusinglayer_record(target.technology)[layer(m)]. If the result isnothing, use that. Otherwise, also considerlevel(m)andlayerindex(m)as below. - If
target.levelshas more than one element andlevel(m)is thenth element, increment the result by(n-1)times the GDS layer and datatype oftarget.level_increment. - If
layer(m) in target.indexed_layers, then increment the GDS datatype of the result bylayerindex(m).
If the result is nothing, then ent is not rendered. Here are some examples:
julia> using DeviceLayout, DeviceLayout.SchematicDrivenLayout, DeviceLayout.PreferredUnits
julia> tech = ProcessTechnology((; base_negative=GDSMeta()), (;));
julia> meta = SemanticMeta(:base_negative);
julia> cs = CoordinateSystem("test", nm);
julia> render!.(cs, Ref(Rectangle(10μm, 10μm)), [
meta,
facing(meta),
SemanticMeta(:GDS2_2, index=2, level=2),
DeviceLayout.UNDEF_META,
DeviceLayout.NORENDER_META,
GDSMeta(2, 2)
]);
julia> cell = Cell("test", nm);
julia> render!(cell, cs, ArtworkTarget(tech; levels=[1, 2], indexed_layers=[:GDS2_2]));
│ ┌ Warning: Target technology does not have a mapping for layer `:undefined`; mapping to GDS layer/datatype 0/0
│ [...]
julia> cell.element_metadata == [
GDSMeta(), # :base_negative => GDSMeta()
GDSMeta(300), # :base_negative => GDSMeta() => GDSMeta(300) [level increment]
GDSMeta(302, 4), # :GDS2_2 => GDSMeta(2, 2) => GDSMeta(302, 2) [level] => GDSMeta(302, 4) [index]
GDSMeta(), # UNDEF_META is not in the layer record, so it's mapped to GDSMeta(0, 0)
# NORENDER_META is skipped
GDSMeta(2, 2) # GDSMeta(2, 2) is passed through without modification
]
trueDeviceLayout.SchematicDrivenLayout.ArtworkTarget — FunctionArtworkTarget(technology::ProcessTechnology;
rendering_options = (; simulation=false, artwork=true),
levels = [1,2],
level_increment = GDSMeta(300,0),
indexed_layers = Symbol[],
map_meta_dict = Dict{SemanticMeta, Union{GDSMeta,Nothing}}()
)A LayoutTarget with defaults set for artwork.
DeviceLayout.SchematicDrivenLayout.SimulationTarget — FunctionSimulationTarget(technology::ProcessTechnology;
rendering_options = (; simulation=true, artwork=false),
levels = [1,2],
level_increment = GDSMeta(300,0),
indexed_layers = Symbol[],
map_meta_dict = Dict{SemanticMeta, Union{GDSMeta,Nothing}}()
)A LayoutTarget with defaults set for simulation.
Metadata handling
SchematicDrivenLayout provides the facing and backing functions to be used with a specific interpretation of level in SemanticMeta. The level of a geometric entity describes the vertical index of its substrate surface in a "flipchip"-style stack of substrates. Metadata types without a level attribute will default to level 1.
▒ ... ▒
▒ level 3 ↓ ▒
█████████████████
▒ level 2 ↑ ▒
▒ ▒
▒ level 1 ↓ ▒
█████████████████
▒ level 0 ↑ ▒DeviceLayout.SchematicDrivenLayout.backing — Functionbacking(l::Int)
backing(s::SemanticMeta)
backing(m::Meta)The level backing l or metadata like s in the level backing level(s).
For example, level 3 backs level 2, so backing(2) == 3 and backing(SemanticMeta("lyr"; level=2)) == SemanticMeta(lyr; level=3)
If a metadata object m has no layer attribute, then backing(m) == m.
DeviceLayout.SchematicDrivenLayout.facing — Functionfacing(l::Int)
facing(s::SemanticMeta)
facing(m::Meta)The level facing l or metadata like s in the level facing level(s).
For example, level 2 faces level 1, so facing(2) == 1 and facing(SemanticMeta("lyr"; level=1)) == SemanticMeta(lyr; level=2)
If a metadata object m has no layer attribute, then facing(m) == m.
Rendering
A Schematic can be rendered to different geometry representations like Cell or SolidModel using different Targets to control rendering options. See SchematicDrivenLayout.render!(::SchematicDrivenLayout.AbstractCoordinateSystem, ::SchematicDrivenLayout.Schematic, ::SchematicDrivenLayout.LayoutTarget) and SchematicDrivenLayout.render!(::DeviceLayout.SolidModel, ::SchematicDrivenLayout.Schematic, ::SchematicDrivenLayout.Target).
Rendering flags
The built-in targets ArtworkTarget and SimulationTarget have the rendering options (artwork=true, simulation=false) and (artwork=false, simulation=true). A pair of functions are provided for designating entities to be rendered or not based on the simulation option (using DeviceLayout.OptionalStyle).
DeviceLayout.SchematicDrivenLayout.not_simulated — Functionnot_simulated(ent::GeometryEntity)Return a version of ent that is rendered unless simulation=true in the rendering options.
The simulation option can be set as a keyword argument to render! or as an element in rendering_options in the Target provided to render!.
DeviceLayout.SchematicDrivenLayout.only_simulated — Functiononly_simulated(ent::GeometryEntity)Return a GeometryEntity that is rendered if and only if simulation=true in the rendering options.
The simulation option can be set as a keyword argument to render! or as an element in rendering_options in the Target provided to render!.