Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ The format of this changelog is based on
[Keep a Changelog](https://keepachangelog.com/), and this project adheres to
[Semantic Versioning](https://semver.org/).

## Unreleased

- Fixed issue causing duplicate `Cell` names with paths and composite components, where rendering would use the component's name rather than a unique name

## 1.4.2 (2025-07-16)

- Removed invalid keyword constructor without type parameters for `@compdef`-ed components with type parameters, so it can be overridden without warnings
Expand Down
8 changes: 8 additions & 0 deletions src/paths/paths.jl
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,14 @@ function DeviceLayout._geometry!(cs::CoordinateSystem, p::Path)
return addref!(cs, p)
end

function DeviceLayout.coordsys_name(p::Path)
# If empty, rendering path directly
isempty(p._geometry) && return name(p._geometry)
# If not empty, p._geometry holds `p` (e.g. `build!` was called)
# and the path coordsys needs its own uniquename
return uniquename(name(p))
end

"""
path_in(h::PointHook)

Expand Down
2 changes: 1 addition & 1 deletion src/render/render.jl
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ function _render!(
cur_cell = if already_seen
memoized_cells[cur_cs]
else
Cell{S}(name(cur_cs))
Cell{S}(coordsys_name(cur_cs))
end

# If it's a new CS, render the contents, push refs to the stack, and add to memoized_cells
Expand Down
16 changes: 9 additions & 7 deletions src/schematics/components/builtin_components.jl
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,11 @@ struct BasicComponent{T} <: AbstractComponent{T}
name::String
geometry::CoordinateSystem{T}
hooks
BasicComponent(cs::CoordinateSystem{T}, hooks=compass()) where {T} =
new{T}(name(cs), cs, hooks)
function BasicComponent(cs::CoordinateSystem{T}, hooks=compass()) where {T}
newcs = copy(cs)
newcs.name = uniquename(name(cs))
return new{T}(name(cs), newcs, hooks)
end
end
hooks(c::BasicComponent) = c.hooks
geometry(c::BasicComponent) = c.geometry
Expand Down Expand Up @@ -220,14 +223,13 @@ struct BasicCompositeComponent{T} <: AbstractCompositeComponent{T}
function BasicCompositeComponent(g::SchematicGraph; coordtype=typeof(1.0UPREFERRED))
newg = SchematicGraph(name(g))
add_graph!(newg, g; id_prefix="")
return new{coordtype}(
newg,
Schematic{coordtype}(newg; log_dir=nothing),
Dict{Symbol, Union{Hook, Vector{<:Hook}}}()
)
sch = Schematic{coordtype}(newg; log_dir=nothing)
sch.coordinate_system.name = uniquename(name(g))
return new{coordtype}(newg, sch, Dict{Symbol, Union{Hook, Vector{<:Hook}}}())
end
end
name(c::BasicCompositeComponent) = c.graph.name
coordsys_name(c::BasicCompositeComponent) = c._schematic.coordinate_system.name

function (cc::BasicCompositeComponent)(
compname::String=name(cc),
Expand Down
2 changes: 2 additions & 0 deletions src/schematics/components/components.jl
Original file line number Diff line number Diff line change
Expand Up @@ -414,3 +414,5 @@ function single_component_expr(compname, comptype; params...)
$escname
end
end

DeviceLayout.coordsys_name(comp::AbstractComponent) = name(geometry(comp))
2 changes: 1 addition & 1 deletion src/schematics/components/composite_components.jl
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ function schematic(cc::AbstractCompositeComponent)
floorplan = plan(
graph(cc);
log_dir=nothing,
id_prefix=name(graph(cc)) * COMPOSITE_NODE_ID_SEPARATOR
id_prefix=cc._schematic.coordinate_system.name * COMPOSITE_NODE_ID_SEPARATOR
)
append_coordsys!(cc._schematic.coordinate_system, floorplan.coordinate_system)
for (k, v) in pairs(floorplan.ref_dict)
Expand Down
2 changes: 2 additions & 0 deletions src/structures.jl
Original file line number Diff line number Diff line change
Expand Up @@ -216,5 +216,7 @@ function flatten end

# type of coordinate system created by flatten
function coordsys_type end # defined elsewhere, once CoordinateSystem is defined
# name used by CoordinateSystem representation
coordsys_name(geom::GeometryStructure) = name(geom)

Base.isempty(geom::GeometryStructure) = isempty(elements(geom)) && isempty(refs(geom))
35 changes: 33 additions & 2 deletions test/test_schematicdriven.jl
Original file line number Diff line number Diff line change
Expand Up @@ -617,10 +617,12 @@ end
g3 = copy(g)
@test length(find_components(TestCompVariant, g3)) == 18
@test length(find_components(TestCompVariant, g3, depth=2)) == 12
@test length(find_components(c -> name(c)[1:1] == "z", g3, depth=2)) == 4
# There are two unique components named "z" appearing a combined 4 times up to depth 2
@test length(find_components(c -> name(c) == "z", g3, depth=2)) == 4
@test length(
unique(component.(g3[find_components(c -> name(c)[1:1] == "z", g3, depth=2)]))
unique(component.(g3[find_components(c -> name(c) == "z", g3, depth=2)]))
) == 2

g3_flat = SchematicDrivenLayout.flatten(g3)
g3 = SchematicDrivenLayout.flatten(g3, depth=1)
@test length(components(g3)) == 14
Expand All @@ -633,6 +635,11 @@ end

@test origin(floorplan3, find_components(c -> name(c)[1:1] == "z", g3)[end]) ≈
Point(200.2μm, 0.1μm)
# Make sure that cells for unique "z" have unique names when rendering
c = Cell(floorplan3.coordinate_system)
a = []
traverse!(a, c)
@test length(findall(x -> name(last(x)) == DeviceLayout.coordsys_name(zline), a)) == 2

### Full composite component
p = Path(Point(0μm, 0μm), name="pz")
Expand Down Expand Up @@ -691,6 +698,12 @@ end

@test hooks(bq2, "bq1", :xy) == hooks(bq2, 1 => :xy) # using subcomp name or index=>hsym
@test keys(SchematicDrivenLayout.subcomponents(bq2)) == (:bq1, :bq2, :pz)
# test creating Cell without build uses path's coordsys_name
c = Cell(geometry(bq2); map_meta=_ -> GDSMeta())
a = []
traverse!(a, c)
@test DeviceLayout.coordsys_name(p) != name(p)
@test isempty(findall(x -> name(last(x)) == name(p), a))

g = SchematicGraph("comp")
bq2_node = add_node!(g, bq2)
Expand Down Expand Up @@ -745,6 +758,24 @@ end
c = Cell("test_no_duplicate_names", nm)
render!(c, floorplan.coordinate_system; map_meta=m -> GDSMeta())
@test_nowarn save(joinpath(tdir, "test_duplicates.gds"), c)

## Composite component having multiple instances of a subcomponent
## that is also a composite component with a named component in it
pa = Path(; name="path")
g = SchematicGraph("pathgraph")
add_node!(g, pa)
sub_cc = BasicCompositeComponent(g)
pa = Path(; name="path")
g = SchematicGraph("pathgraph")
add_node!(g, pa)
sub_cc2 = BasicCompositeComponent(g)
g2 = SchematicGraph("supergraph")
add_node!(g2, sub_cc)
add_node!(g2, sub_cc2)
super_cc = BasicCompositeComponent(g2)
c = Cell("test_no_duplicate_names", nm)
render!(c, super_cc; map_meta=m -> GDSMeta())
@test_nowarn save(joinpath(tdir, "test_duplicates.gds"), c)
end

@testset "GDSComponent" begin
Expand Down