Cheat sheet
A compact reference. Skim this once before reading anything else.
Boilerplate
import lumicron as lm
import lumicron.pdks.elyon_demo.all as pdk
chip = lm.CELL("Chip")
# ... build ...
chip.to_gds("chip.gds")
Cells & shapes
| Call |
What you get |
lm.CELL("Name") |
New cell |
lm.Rectangle(x_dim=, y_dim=, layer=) |
Centered rectangle |
lm.Rectangle(..., centered=False) |
Origin at lower-left |
lm.Circle(radius=, layer=) |
Filled circle |
lm.Ring(outer_radius=, width=, layer=) |
Annulus |
lm.Polygon(points=[(x,y), …], layer=) |
Arbitrary polygon |
lm.ARRAY(child, count=, pitch=(dx, dy)) |
Periodic array |
c.add(thing) |
Add to cell, returns handle |
Placement
| Chain method |
Effect |
.at((x, y)) |
Set the selected anchor’s target |
.using("W"/"E"/"N"/"S"/"NE"/...) |
Use a child anchor instead of its origin |
.using("C") (not .using(handle.C)) |
Select a local anchor; handle properties are world points |
.rotate_by(deg) |
Rotate CCW |
.move_by(dx, dy) |
Accumulate a parent-coordinate shift for references |
.right_of(other), .left_of(other) |
Anchor-to-anchor align |
.above(other), .below(other) |
Anchor-to-anchor align |
.using("i1").at(other.ports["o1"]) |
Snap a port onto another (translate only) |
| Call |
Effect |
c.Join(a.ports["in"], b.ports["out"]) |
Mate two ports: a’s cell moves + rotates onto b’s port; warns on width/layer mismatch |
Ports
| Call |
What it does |
lm.PORT("name", position=, direction=, width=, layer=) |
Define a port |
lm.PORT(..., port_type="electrical") |
Electrical (vs optical) |
lm.PORT(..., route_profile=...) |
Attach a profile |
c.ports["name"] / handle.ports["name"] |
Look up a port |
handle.promote(ports=[...], prefix="...") |
Re-publish child ports |
c.show_ports() |
Print port table |
Direction: degrees CCW from +X. 0 = E, 90 = N, 180 = W, 270 = S.
Routing - global kwargs
chip.Route(a, b,
radius=10, # bend radius (µm)
bend="circular", # "circular" | "euler" | CELL
p=0.5, # euler fraction (0–1)
profile=pdk.RP.silc_strip, # cross-section recipe
style=None, # automatic; or "manhattan", "direct", "sbend"
start_straight=0, # min straight after port_a
end_straight=0, # min straight before port_b
clearance=0, # detour around obstacles by this µm
transition_offset=50, # auto layer-transition position
transitions=None) # custom TransitionRegistry
Routing - chain methods
| Method |
Effect |
.go("E"/"N"/"W"/"S", by=, to=) |
Manhattan section |
.go("NE"/"NW"/"SE"/"SW", by=(dx, dy)) |
S-bend section |
.jog(dir, by=) |
U-shaped detour |
.style(arg=, profile=, layer=, radius=, width=, bend=) |
Section-level style overrides |
.style("default") |
Revert all section overrides |
.radius(r) |
Override radius for next section |
.bend(b, p=) |
Override bend type for next section |
.width(w) |
Override width - auto-taper on boundary |
.taper(offset=, width=, length=) |
Insert a positional taper |
.start_taper(width=, length=) |
Configure port_a-side taper |
.end_taper(width=, length=) |
Configure port_b-side taper |
.match_length_to(other, delta=, …) |
Length-match this route to another |
Routing bundles
bundle = chip.Route(ports_a, ports_b,
spacing=10, radius=15,
style="manhattan", sort=False)
bundle.match_lengths() # target, delta, mirror, tolerance
first_channel = bundle.routes[0]
Then call .go(...) for Manhattan-mode bundles, or chain .taper(...) / .match_lengths(...) to broadcast.
Bookmarks
chip.Place(thing).at(...).add_bookmark(name="...", group="...", notes="...")
chip.add(lm.Bookmark("alignment", at=(x, y)))
chip.add(lm.Bookmark("dicing_lane", bbox=(xmin, ymin, xmax, ymax)))
Output
chip.to_gds("chip.gds")
chip.to_oas("chip.oas") # OASIS
chip.to_gds(max_points=199) # legacy GDS-II compat
Useful introspection
c.show_ports()
pdk.LAYER.print_rules()
pdk.RP.print_rules()
any_obj.rules() # most objects support this