[tutorial] include a repetition and update docs
This commit is contained in:
parent
abf236a046
commit
59e996e680
4 changed files with 56 additions and 12 deletions
|
|
@ -18,11 +18,14 @@ Contents
|
||||||
* Design a pattern which is meant to plug into an existing pattern (via `.interface()`)
|
* Design a pattern which is meant to plug into an existing pattern (via `.interface()`)
|
||||||
- [pather](pather.py)
|
- [pather](pather.py)
|
||||||
* Use `Pather` to route individual wires and wire bundles
|
* Use `Pather` to route individual wires and wire bundles
|
||||||
* Use `BasicTool` to generate paths
|
* Use `AutoTool` to generate paths
|
||||||
* Use `BasicTool` to automatically transition between path types
|
* Use `AutoTool` to automatically transition between path types
|
||||||
- [renderpather](rendpather.py)
|
- [renderpather](renderpather.py)
|
||||||
* Use `RenderPather` and `PathTool` to build a layout similar to the one in [pather](pather.py),
|
* Use `RenderPather` and `PathTool` to build a layout similar to the one in [pather](pather.py),
|
||||||
but using `Path` shapes instead of `Polygon`s.
|
but using `Path` shapes instead of `Polygon`s.
|
||||||
|
- [port_pather](port_pather.py)
|
||||||
|
* Use `PortPather` and the `.at()` syntax for more concise routing
|
||||||
|
* Advanced port manipulation and connections
|
||||||
|
|
||||||
|
|
||||||
Additionaly, [pcgen](pcgen.py) is a utility module for generating photonic crystal lattices.
|
Additionaly, [pcgen](pcgen.py) is a utility module for generating photonic crystal lattices.
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,8 @@
|
||||||
import numpy
|
import numpy
|
||||||
from numpy import pi
|
from numpy import pi
|
||||||
|
|
||||||
from masque import (
|
from masque import layer_t, Pattern, Circle, Arc, Polygon, Ref
|
||||||
layer_t, Pattern, Circle, Arc, Polygon,
|
from masque.repetition import Grid
|
||||||
)
|
|
||||||
import masque.file.gdsii
|
import masque.file.gdsii
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -37,6 +36,45 @@ def hole(
|
||||||
return pat
|
return pat
|
||||||
|
|
||||||
|
|
||||||
|
def hole_array(
|
||||||
|
radius: float,
|
||||||
|
num_x: int = 5,
|
||||||
|
num_y: int = 3,
|
||||||
|
pitch: float = 2000,
|
||||||
|
layer: layer_t = (1, 0),
|
||||||
|
) -> Pattern:
|
||||||
|
"""
|
||||||
|
Generate an array of circular holes using `Repetition`.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
radius: Circle radius.
|
||||||
|
num_x, num_y: Number of holes in x and y.
|
||||||
|
pitch: Center-to-center spacing.
|
||||||
|
layer: Layer to draw the holes on.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Pattern containing a grid of holes.
|
||||||
|
"""
|
||||||
|
# First, make a pattern for a single hole
|
||||||
|
hpat = hole(radius, layer)
|
||||||
|
|
||||||
|
# Now, create a pattern that references it multiple times using a Grid
|
||||||
|
pat = Pattern()
|
||||||
|
pat.refs['hole'] = [
|
||||||
|
Ref(
|
||||||
|
offset=(0, 0),
|
||||||
|
repetition=Grid(a_vector=(pitch, 0), a_count=num_x,
|
||||||
|
b_vector=(0, pitch), b_count=num_y)
|
||||||
|
)]
|
||||||
|
|
||||||
|
# We can also add transformed references (rotation, mirroring, etc.)
|
||||||
|
pat.refs['hole'].append(
|
||||||
|
Ref(offset=(0, -pitch), rotation=pi / 4, mirrored=True)
|
||||||
|
)
|
||||||
|
|
||||||
|
return pat, hpat
|
||||||
|
|
||||||
|
|
||||||
def triangle(
|
def triangle(
|
||||||
radius: float,
|
radius: float,
|
||||||
layer: layer_t = (1, 0),
|
layer: layer_t = (1, 0),
|
||||||
|
|
@ -58,9 +96,7 @@ def triangle(
|
||||||
]) * radius
|
]) * radius
|
||||||
|
|
||||||
pat = Pattern()
|
pat = Pattern()
|
||||||
pat.shapes[layer].extend([
|
pat.polygon(layer, vertices=vertices)
|
||||||
Polygon(offset=(0, 0), vertices=vertices),
|
|
||||||
])
|
|
||||||
return pat
|
return pat
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -109,9 +145,13 @@ def main() -> None:
|
||||||
lib['smile'] = smile(1000)
|
lib['smile'] = smile(1000)
|
||||||
lib['triangle'] = triangle(1000)
|
lib['triangle'] = triangle(1000)
|
||||||
|
|
||||||
|
# Use a Grid to make many holes efficiently
|
||||||
|
lib['grid'], lib['hole'] = hole_array(1000)
|
||||||
|
|
||||||
masque.file.gdsii.writefile(lib, 'basic_shapes.gds', **GDS_OPTS)
|
masque.file.gdsii.writefile(lib, 'basic_shapes.gds', **GDS_OPTS)
|
||||||
|
|
||||||
lib['triangle'].visualize()
|
lib['triangle'].visualize()
|
||||||
|
lib['grid'].visualize(lib)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
|
||||||
|
|
@ -239,7 +239,7 @@ def main() -> None:
|
||||||
pather.path_to('GND', None, x=pather['VCC'].offset[0])
|
pather.path_to('GND', None, x=pather['VCC'].offset[0])
|
||||||
|
|
||||||
# Now, start using M1_tool for GND.
|
# Now, start using M1_tool for GND.
|
||||||
# Since we have defined an M2-to-M1 transition for BasicPather, we don't need to place one ourselves.
|
# Since we have defined an M2-to-M1 transition for Pather, we don't need to place one ourselves.
|
||||||
# If we wanted to place our via manually, we could add `pather.plug('m1_via', {'GND': 'top'})` here
|
# If we wanted to place our via manually, we could add `pather.plug('m1_via', {'GND': 'top'})` here
|
||||||
# and achieve the same result without having to define any transitions in M1_tool.
|
# and achieve the same result without having to define any transitions in M1_tool.
|
||||||
# Note that even though we have changed the tool used for GND, the via doesn't get placed until
|
# Note that even though we have changed the tool used for GND, the via doesn't get placed until
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ from pather import M1_WIDTH, V1_WIDTH, M2_WIDTH, map_layer, make_pad, make_via
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
#
|
#
|
||||||
# To illustrate the advantages of using `RenderPather`, we use `PathTool` instead
|
# To illustrate the advantages of using `RenderPather`, we use `PathTool` instead
|
||||||
# of `BasicTool`. `PathTool` lacks some sophistication (e.g. no automatic transitions)
|
# of `AutoTool`. `PathTool` lacks some sophistication (e.g. no automatic transitions)
|
||||||
# but when used with `RenderPather`, it can consolidate multiple routing steps into
|
# but when used with `RenderPather`, it can consolidate multiple routing steps into
|
||||||
# a single `Path` shape.
|
# a single `Path` shape.
|
||||||
#
|
#
|
||||||
|
|
@ -34,7 +34,7 @@ def main() -> None:
|
||||||
ptype_top = 'm2wire',
|
ptype_top = 'm2wire',
|
||||||
)
|
)
|
||||||
|
|
||||||
# `PathTool` is more limited than `BasicTool`. It only generates one type of shape
|
# `PathTool` is more limited than `AutoTool`. It only generates one type of shape
|
||||||
# (`Path`), so it only needs to know what layer to draw on, what width to draw with,
|
# (`Path`), so it only needs to know what layer to draw on, what width to draw with,
|
||||||
# and what port type to present.
|
# and what port type to present.
|
||||||
M1_ptool = PathTool(layer='M1', width=M1_WIDTH, ptype='m1wire')
|
M1_ptool = PathTool(layer='M1', width=M1_WIDTH, ptype='m1wire')
|
||||||
|
|
@ -77,6 +77,7 @@ def main() -> None:
|
||||||
# to account for it.
|
# to account for it.
|
||||||
v1pat = library['v1_via']
|
v1pat = library['v1_via']
|
||||||
via_size = abs(v1pat.ports['top'].x - v1pat.ports['bottom'].x)
|
via_size = abs(v1pat.ports['top'].x - v1pat.ports['bottom'].x)
|
||||||
|
|
||||||
# alternatively, via_size = v1pat.ports['top'].measure_travel(v1pat.ports['bottom'])[0][0]
|
# alternatively, via_size = v1pat.ports['top'].measure_travel(v1pat.ports['bottom'])[0][0]
|
||||||
# would take into account the port orientations if we didn't already know they're along x
|
# would take into account the port orientations if we didn't already know they're along x
|
||||||
rpather.path_to('VCC', None, -50_000 + via_size)
|
rpather.path_to('VCC', None, -50_000 + via_size)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue