[examples] fixup examples and add port_pather example

This commit is contained in:
Jan Petykiewicz 2026-02-14 16:07:19 -08:00
commit 37418d2137
4 changed files with 176 additions and 67 deletions

View file

@ -1,10 +1,10 @@
"""
Manual wire routing tutorial: Pather and BasicTool
Manual wire routing tutorial: Pather and AutoTool
"""
from collections.abc import Callable
from numpy import pi
from masque import Pather, RenderPather, Library, Pattern, Port, layer_t, map_layers
from masque.builder.tools import BasicTool, PathTool
from masque.builder.tools import AutoTool, PathTool
from masque.file.gdsii import writefile
from basic_shapes import GDS_OPTS
@ -110,28 +110,24 @@ def map_layer(layer: layer_t) -> layer_t:
return layer_mapping.get(layer, layer)
#
# Now we can start building up our library (collection of static cells) and pathing tools.
#
# If any of the operations below are confusing, you can cross-reference against the `RenderPather`
# tutorial, which handles some things more explicitly (e.g. via placement) and simplifies others
# (e.g. geometry definition).
#
def main() -> None:
def prepare_tools() -> tuple[Library, Tool, Tool]:
"""
Create some basic library elements and tools for drawing M1 and M2
"""
# Build some patterns (static cells) using the above functions and store them in a library
library = Library()
library['pad'] = make_pad()
library['m1_bend'] = make_bend(layer='M1', ptype='m1wire', width=M1_WIDTH)
library['m2_bend'] = make_bend(layer='M2', ptype='m2wire', width=M2_WIDTH)
library['v1_via'] = make_via(
layer_top='M2',
layer_via='V1',
layer_bot='M1',
width_top=M2_WIDTH,
width_via=V1_WIDTH,
width_bot=M1_WIDTH,
ptype_bot='m1wire',
ptype_top='m2wire',
layer_top = 'M2',
layer_via = 'V1',
layer_bot = 'M1',
width_top = M2_WIDTH,
width_via = V1_WIDTH,
width_bot = M1_WIDTH,
ptype_bot = 'm1wire',
ptype_top = 'm2wire',
)
#
@ -140,53 +136,79 @@ def main() -> None:
# M2_tool will route on M2, using wires with M2_WIDTH
# Both tools are able to automatically transition from the other wire type (with a via)
#
# Note that while we use BasicTool for this tutorial, you can define your own `Tool`
# Note that while we use AutoTool for this tutorial, you can define your own `Tool`
# with arbitrary logic inside -- e.g. with single-use bends, complex transition rules,
# transmission line geometry, or other features.
#
M1_tool = BasicTool(
straight = (
# First, we need a function which takes in a length and spits out an M1 wire
lambda length: make_straight_wire(layer='M1', ptype='m1wire', width=M1_WIDTH, length=length),
'input', # When we get a pattern from make_straight_wire, use the port named 'input' as the input
'output', # and use the port named 'output' as the output
),
bend = (
library.abstract('m1_bend'), # When we need a bend, we'll reference the pattern we generated earlier
'input', # To orient it clockwise, use the port named 'input' as the input
'output', # and 'output' as the output
),
M1_tool = AutoTool(
# First, we need a function which takes in a length and spits out an M1 wire
straights = [
AutoTool.Straight(
ptype = 'm1wire',
fn = lambda length: make_straight_wire(layer='M1', ptype='m1wire', width=M1_WIDTH, length=length),
in_port_name = 'input', # When we get a pattern from make_straight_wire, use the port named 'input' as the input
out_port_name = 'output', # and use the port named 'output' as the output
),
],
bends = [
AutoTool.Bend(
abstract = library.abstract('m1_bend'), # When we need a bend, we'll reference the pattern we generated earlier
in_port_name = 'input',
out_port_name = 'output',
clockwise = True,
),
],
transitions = { # We can automate transitions for different (normally incompatible) port types
'm2wire': ( # For example, when we're attaching to a port with type 'm2wire'
('m2wire', 'm1wire'): AutoTool.Transition( # For example, when we're attaching to a port with type 'm2wire'
library.abstract('v1_via'), # we can place a V1 via
'top', # using the port named 'top' as the input (i.e. the M2 side of the via)
'bottom', # and using the port named 'bottom' as the output
),
},
sbends = [],
default_out_ptype = 'm1wire', # Unless otherwise requested, we'll default to trying to stay on M1
)
M2_tool = BasicTool(
straight = (
M2_tool = AutoTool(
straights = [
# Again, we use make_straight_wire, but this time we set parameters for M2
lambda length: make_straight_wire(layer='M2', ptype='m2wire', width=M2_WIDTH, length=length),
'input',
'output',
),
bend = (
library.abstract('m2_bend'), # and we use an M2 bend
'input',
'output',
),
AutoTool.Straight(
ptype = 'm2wire',
fn = lambda length: make_straight_wire(layer='M2', ptype='m2wire', width=M2_WIDTH, length=length),
in_port_name = 'input',
out_port_name = 'output',
),
],
bends = [
# and we use an M2 bend
AutoTool.Bend(
abstract = library.abstract('m2_bend'),
in_port_name = 'input',
out_port_name = 'output',
),
],
transitions = {
'm1wire': (
('m1wire', 'm2wire'): AutoTool.Transition(
library.abstract('v1_via'), # We still use the same via,
'bottom', # but the input port is now 'bottom'
'top', # and the output port is now 'top'
),
},
sbends = [],
default_out_ptype = 'm2wire', # We default to trying to stay on M2
)
return library, M1_tool, M2_tool
#
# Now we can start building up our library (collection of static cells) and pathing tools.
#
# If any of the operations below are confusing, you can cross-reference against the `RenderPather`
# tutorial, which handles some things more explicitly (e.g. via placement) and simplifies others
# (e.g. geometry definition).
#
def main() -> None:
library, M1_tool, M2_tool = prepare_tools()
#
# Create a new pather which writes to `library` and uses `M2_tool` as its default tool.
@ -272,7 +294,7 @@ def main() -> None:
pather.path_to('GND', None, -50_000)
# Save the pather's pattern into our library
library['Pather_and_BasicTool'] = pather.pattern
library['Pather_and_AutoTool'] = pather.pattern
# Convert from text-based layers to numeric layers for GDS, and output the file
library.map_layers(map_layer)