├── tests ├── __init__.py ├── _03_structures │ ├── __init__.py │ ├── _02_jtl.py │ ├── _03_jtl_d.py │ ├── _04_jtl_b.py │ ├── _05_jtl_bp.py │ ├── _07_jj_c.py │ └── _06_jtl_bph.py ├── _01_docs │ ├── _overview_parameters.0.py │ ├── _overview_parameters.2.py │ ├── _overview_elements.py │ ├── _overview_parameters.3.py │ ├── _overview_shapes.py │ ├── _framework_ports.py │ ├── _overview_parameters.1.py │ ├── _overview_group_0.py │ ├── _overview_routes_0.py │ ├── _overview_routes_1.py │ ├── _overview_routes_2.py │ ├── _overview_ports_1.py │ ├── _overview_group_2.py │ ├── _overview_ports_0.py │ ├── _overview_ports_2.py │ ├── _overview_routes_3.py │ ├── _overview_parameters.4.py │ ├── _overview_routes_4.py │ └── _overview_group_1.py ├── 8-parse │ └── _0_input.py └── _04_edges │ ├── _3_erc_h.py │ └── _2_erc_f.py ├── spira ├── core │ ├── __init__.py │ ├── transforms │ │ ├── __init__.py │ │ ├── reflection.py │ │ ├── identity.py │ │ └── translation.py │ ├── all.py │ ├── mixin.py │ ├── decorators.py │ └── transformable.py ├── enginex │ ├── __init__.py │ ├── engine.py │ └── simulation.py ├── validatex │ ├── __init__.py │ ├── drc │ │ ├── __init__.py │ │ ├── overlap.py │ │ ├── rules.py │ │ ├── width.py │ │ └── density.py │ └── lvs │ │ ├── __init__.py │ │ └── device_recognition.py ├── technologies │ ├── __init__.py │ ├── default │ │ ├── circuits │ │ │ ├── __init__.py │ │ │ └── ytron_circuit.py │ │ ├── devices │ │ │ └── __init__.py │ │ └── __init__.py │ └── waterloo │ │ ├── README.md │ │ ├── circuits │ │ └── __init__.py │ │ ├── __init__.py │ │ └── process │ │ └── __init__.py ├── yevon │ ├── __init__.py │ ├── engines │ │ ├── __init__.py │ │ └── simulation.py │ ├── geometry │ │ ├── __init__.py │ │ ├── edges │ │ │ └── __init__.py │ │ ├── route │ │ │ └── __init__.py │ │ ├── ports │ │ │ └── __init__.py │ │ ├── nets │ │ │ └── __init__.py │ │ └── shapes │ │ │ └── __init__.py │ ├── utils │ │ ├── __init__.py │ │ └── debugging.py │ ├── process │ │ ├── settings.py │ │ ├── derived_layers.py │ │ ├── all.py │ │ ├── __init__.py │ │ ├── process_flow.py │ │ ├── process_layer.py │ │ └── layer_map.py │ ├── vmodel │ │ ├── __init__.py │ │ ├── boundary.py │ │ ├── derived.py │ │ └── elements.py │ ├── io │ │ ├── __init__.py │ │ ├── file_type.py │ │ ├── collector.py │ │ ├── input.py │ │ └── output_gdsii.py │ ├── visualization │ │ └── __init__.py │ ├── aspects │ │ ├── base.py │ │ ├── cell.py │ │ ├── netlist.py │ │ ├── shape.py │ │ ├── clipper.py │ │ ├── geometry.py │ │ ├── __init__.py │ │ ├── output.py │ │ └── polygon.py │ ├── filters │ │ ├── __init__.py │ │ ├── empty_filter.py │ │ ├── layer_filter.py │ │ └── edge_filter.py │ ├── gdsii │ │ ├── __init__.py │ │ ├── containers.py │ │ ├── generators.py │ │ ├── unit_grid.py │ │ └── label.py │ ├── all.py │ └── constants.py ├── all.py └── __init__.py ├── docs ├── _4_reference.rst ├── _build │ ├── html │ │ ├── _static │ │ │ ├── _3_reference.rst │ │ │ ├── _4_reference.rst │ │ │ ├── file.png │ │ │ ├── plus.png │ │ │ ├── minus.png │ │ │ ├── figures │ │ │ │ └── hole.png │ │ │ ├── _figures │ │ │ │ ├── _9_ports.png │ │ │ │ ├── _group.png │ │ │ │ ├── _ports.png │ │ │ │ ├── _routes.png │ │ │ │ ├── _3_layout.png │ │ │ │ ├── _4_ports_0.png │ │ │ │ ├── _4_ports_1.png │ │ │ │ ├── _6_hierarchy_0 │ │ │ │ ├── _9_factor.png │ │ │ │ ├── _elements.png │ │ │ │ ├── spira_logo.png │ │ │ │ ├── RouteConnect.png │ │ │ │ ├── _5_routes_0.png │ │ │ │ ├── _9_expanded.png │ │ │ │ ├── _9_transform.png │ │ │ │ ├── _9_translate.png │ │ │ │ ├── _adv_0_ytron.png │ │ │ │ ├── _adv_erc_jtl.png │ │ │ │ ├── _adv_jtl_erc.png │ │ │ │ ├── _adv_jtl_net.png │ │ │ │ ├── _6_hierarchy_0.png │ │ │ │ ├── _6_hierarchy_1.png │ │ │ │ ├── _adv_erc_jtl_m5.png │ │ │ │ ├── _adv_jtl_false.png │ │ │ │ ├── _4_ports_0_enabled.png │ │ │ │ ├── _adv_0_ytron_pcell.png │ │ │ │ ├── _adv_jtl_netlist.png │ │ │ │ ├── _adv_junction_bot.png │ │ │ │ ├── _adv_junction_top.png │ │ │ │ ├── _adv_junction_true.png │ │ │ │ ├── _adv_0_ytron_circuit.png │ │ │ │ └── _adv_junction_false.png │ │ │ ├── fonts │ │ │ │ ├── Inconsolata.ttf │ │ │ │ ├── Lato-Bold.ttf │ │ │ │ ├── Lato-Regular.ttf │ │ │ │ ├── Inconsolata-Bold.ttf │ │ │ │ ├── Lato │ │ │ │ │ ├── lato-bold.eot │ │ │ │ │ ├── lato-bold.ttf │ │ │ │ │ ├── lato-bold.woff │ │ │ │ │ ├── lato-bold.woff2 │ │ │ │ │ ├── lato-italic.eot │ │ │ │ │ ├── lato-italic.ttf │ │ │ │ │ ├── lato-italic.woff │ │ │ │ │ ├── lato-italic.woff2 │ │ │ │ │ ├── lato-regular.eot │ │ │ │ │ ├── lato-regular.ttf │ │ │ │ │ ├── lato-regular.woff │ │ │ │ │ ├── lato-bolditalic.eot │ │ │ │ │ ├── lato-bolditalic.ttf │ │ │ │ │ ├── lato-bolditalic.woff │ │ │ │ │ ├── lato-regular.woff2 │ │ │ │ │ └── lato-bolditalic.woff2 │ │ │ │ ├── RobotoSlab-Bold.ttf │ │ │ │ ├── RobotoSlab-Regular.ttf │ │ │ │ ├── Inconsolata-Regular.ttf │ │ │ │ ├── fontawesome-webfont.eot │ │ │ │ ├── fontawesome-webfont.ttf │ │ │ │ ├── fontawesome-webfont.woff │ │ │ │ ├── fontawesome-webfont.woff2 │ │ │ │ └── RobotoSlab │ │ │ │ │ ├── roboto-slab-v7-bold.eot │ │ │ │ │ ├── roboto-slab-v7-bold.ttf │ │ │ │ │ ├── roboto-slab-v7-bold.woff │ │ │ │ │ ├── roboto-slab-v7-bold.woff2 │ │ │ │ │ ├── roboto-slab-v7-regular.eot │ │ │ │ │ ├── roboto-slab-v7-regular.ttf │ │ │ │ │ ├── roboto-slab-v7-regular.woff │ │ │ │ │ └── roboto-slab-v7-regular.woff2 │ │ │ ├── documentation_options.js │ │ │ ├── Makefile │ │ │ ├── gdsii.rst │ │ │ ├── pcell_examples.rst │ │ │ ├── parameters.rst │ │ │ ├── make.bat │ │ │ ├── conf.py │ │ │ ├── _5_developers.rst │ │ │ ├── gettingstarted.rst │ │ │ ├── developers.rst │ │ │ └── tutorials.rst │ │ ├── _sources │ │ │ ├── _3_reference.rst.txt │ │ │ ├── _4_reference.rst.txt │ │ │ ├── gdsii.rst.txt │ │ │ ├── pcell_examples.rst.txt │ │ │ ├── parameters.rst.txt │ │ │ ├── _5_developers.rst.txt │ │ │ ├── gettingstarted.rst.txt │ │ │ ├── developers.rst.txt │ │ │ └── tutorials.rst.txt │ │ ├── objects.inv │ │ ├── _images │ │ │ ├── _group.png │ │ │ ├── _ports.png │ │ │ ├── _routes.png │ │ │ ├── _3_layout.png │ │ │ ├── _9_factor.png │ │ │ ├── _9_ports.png │ │ │ ├── _elements.png │ │ │ ├── RouteConnect.png │ │ │ ├── _4_ports_0.png │ │ │ ├── _4_ports_1.png │ │ │ ├── _5_routes_0.png │ │ │ ├── _9_expanded.png │ │ │ ├── _9_transform.png │ │ │ ├── _9_translate.png │ │ │ ├── _adv_0_ytron.png │ │ │ ├── _adv_erc_jtl.png │ │ │ ├── _adv_jtl_erc.png │ │ │ ├── _adv_jtl_net.png │ │ │ ├── _6_hierarchy_0.png │ │ │ ├── _6_hierarchy_1.png │ │ │ ├── _adv_jtl_false.png │ │ │ ├── _adv_jtl_netlist.png │ │ │ ├── _adv_junction_bot.png │ │ │ ├── _adv_junction_top.png │ │ │ ├── _4_ports_0_enabled.png │ │ │ ├── _adv_0_ytron_pcell.png │ │ │ ├── _adv_junction_false.png │ │ │ ├── _adv_junction_true.png │ │ │ └── _adv_0_ytron_circuit.png │ │ ├── .doctrees │ │ │ ├── pdk.doctree │ │ │ ├── gdsii.doctree │ │ │ ├── index.doctree │ │ │ ├── _2_basic.doctree │ │ │ ├── overview.doctree │ │ │ ├── _1_overview.doctree │ │ │ ├── _3_advanced.doctree │ │ │ ├── developers.doctree │ │ │ ├── framework.doctree │ │ │ ├── parameters.doctree │ │ │ ├── rdd_schema.doctree │ │ │ ├── tutorials.doctree │ │ │ ├── _2_tutorials.doctree │ │ │ ├── _3_reference.doctree │ │ │ ├── _4_reference.doctree │ │ │ ├── _5_developers.doctree │ │ │ ├── overview_old.doctree │ │ │ ├── _0_methodology.doctree │ │ │ ├── gettingstarted.doctree │ │ │ └── pcell_examples.doctree │ │ └── .buildinfo │ └── doctrees │ │ ├── pdk.doctree │ │ ├── gdsii.doctree │ │ ├── index.doctree │ │ ├── _2_basic.doctree │ │ ├── overview.doctree │ │ ├── tutorials.doctree │ │ ├── _1_overview.doctree │ │ ├── _3_advanced.doctree │ │ ├── _4_reference.doctree │ │ ├── developers.doctree │ │ ├── overview_old.doctree │ │ ├── parameters.doctree │ │ ├── rdd_schema.doctree │ │ ├── _0_methodology.doctree │ │ ├── _5_developers.doctree │ │ └── pcell_examples.doctree ├── _figures │ ├── _9_ports.png │ ├── _group.png │ ├── _ports.png │ ├── _routes.png │ ├── _3_layout.png │ ├── _4_ports_0.png │ ├── _4_ports_1.png │ ├── _9_factor.png │ ├── _elements.png │ ├── spira_logo.png │ ├── RouteConnect.png │ ├── _5_routes_0.png │ ├── _9_expanded.png │ ├── _9_transform.png │ ├── _9_translate.png │ ├── _adv_0_ytron.png │ ├── _adv_erc_jtl.png │ ├── _adv_jtl_erc.png │ ├── _adv_jtl_net.png │ ├── _6_hierarchy_0.png │ ├── _6_hierarchy_1.png │ ├── _adv_erc_jtl_m5.png │ ├── _adv_jtl_false.png │ ├── _4_ports_0_enabled.png │ ├── _adv_0_ytron_pcell.png │ ├── _adv_jtl_netlist.png │ ├── _adv_junction_bot.png │ ├── _adv_junction_top.png │ ├── _adv_junction_true.png │ ├── _adv_0_ytron_circuit.png │ └── _adv_junction_false.png ├── Makefile ├── make.bat ├── conf.py └── _5_developers.rst ├── .ipynb_checkpoints └── Untitled-checkpoint.ipynb ├── tutorials ├── basic │ ├── _2_process_1.py │ ├── _10_edge_generator.py │ ├── _1_pcell.py │ ├── _2_process_0.py │ ├── _3_layout_1.py │ ├── _3_layout_0.py │ ├── _9_stretch_0.py │ ├── _12_nets.py │ ├── _4_ports_1.py │ ├── _4_ports_0.py │ ├── _5_routes_1.py │ ├── _14_nets.py │ ├── _13_nets.py │ ├── _6_hierarchy.py │ ├── _5_routes_0.py │ └── _11_shapes.py └── reference │ ├── _0_filters.py │ ├── caching.py │ ├── _8_transforms.py │ ├── _0_rdd.py │ ├── _5_boolean.py │ ├── _0-ports.py │ └── _1-shapes.py ├── requirements.txt ├── .travis.yml ├── .gitignore ├── LICENSE └── setup.py /tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /spira/core/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /spira/enginex/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /spira/validatex/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /spira/technologies/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /spira/validatex/drc/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /spira/validatex/lvs/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /spira/yevon/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /spira/yevon/engines/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /spira/yevon/geometry/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/_03_structures/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /spira/yevon/utils/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /spira/technologies/default/circuits/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /spira/technologies/default/devices/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /spira/technologies/waterloo/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /docs/_4_reference.rst: -------------------------------------------------------------------------------- 1 | ######### 2 | Reference 3 | ######### 4 | 5 | 6 | -------------------------------------------------------------------------------- /spira/technologies/waterloo/circuits/__init__.py: -------------------------------------------------------------------------------- 1 | # from .resistor import * -------------------------------------------------------------------------------- /spira/yevon/geometry/edges/__init__.py: -------------------------------------------------------------------------------- 1 | from .edges import * 2 | 3 | 4 | -------------------------------------------------------------------------------- /spira/yevon/geometry/route/__init__.py: -------------------------------------------------------------------------------- 1 | from .routes import * 2 | 3 | 4 | -------------------------------------------------------------------------------- /spira/yevon/geometry/ports/__init__.py: -------------------------------------------------------------------------------- 1 | from .port import * 2 | from .port_list import * -------------------------------------------------------------------------------- /docs/_build/html/_static/_3_reference.rst: -------------------------------------------------------------------------------- 1 | ######### 2 | Reference 3 | ######### 4 | 5 | 6 | -------------------------------------------------------------------------------- /docs/_build/html/_static/_4_reference.rst: -------------------------------------------------------------------------------- 1 | ######### 2 | Reference 3 | ######### 4 | 5 | 6 | -------------------------------------------------------------------------------- /spira/yevon/geometry/nets/__init__.py: -------------------------------------------------------------------------------- 1 | from .net import * 2 | from .branch import * 3 | 4 | -------------------------------------------------------------------------------- /docs/_build/html/_sources/_3_reference.rst.txt: -------------------------------------------------------------------------------- 1 | ######### 2 | Reference 3 | ######### 4 | 5 | 6 | -------------------------------------------------------------------------------- /docs/_build/html/_sources/_4_reference.rst.txt: -------------------------------------------------------------------------------- 1 | ######### 2 | Reference 3 | ######### 4 | 5 | 6 | -------------------------------------------------------------------------------- /spira/technologies/waterloo/__init__.py: -------------------------------------------------------------------------------- 1 | # from .devices import * 2 | # from .circuits import * 3 | 4 | -------------------------------------------------------------------------------- /docs/_figures/_9_ports.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_figures/_9_ports.png -------------------------------------------------------------------------------- /docs/_figures/_group.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_figures/_group.png -------------------------------------------------------------------------------- /docs/_figures/_ports.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_figures/_ports.png -------------------------------------------------------------------------------- /docs/_figures/_routes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_figures/_routes.png -------------------------------------------------------------------------------- /spira/yevon/process/settings.py: -------------------------------------------------------------------------------- 1 | 2 | from . import get_rule_deck 3 | 4 | RDD = get_rule_deck() 5 | 6 | -------------------------------------------------------------------------------- /docs/_build/html/objects.inv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/objects.inv -------------------------------------------------------------------------------- /docs/_figures/_3_layout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_figures/_3_layout.png -------------------------------------------------------------------------------- /docs/_figures/_4_ports_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_figures/_4_ports_0.png -------------------------------------------------------------------------------- /docs/_figures/_4_ports_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_figures/_4_ports_1.png -------------------------------------------------------------------------------- /docs/_figures/_9_factor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_figures/_9_factor.png -------------------------------------------------------------------------------- /docs/_figures/_elements.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_figures/_elements.png -------------------------------------------------------------------------------- /docs/_figures/spira_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_figures/spira_logo.png -------------------------------------------------------------------------------- /docs/_figures/RouteConnect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_figures/RouteConnect.png -------------------------------------------------------------------------------- /docs/_figures/_5_routes_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_figures/_5_routes_0.png -------------------------------------------------------------------------------- /docs/_figures/_9_expanded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_figures/_9_expanded.png -------------------------------------------------------------------------------- /docs/_figures/_9_transform.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_figures/_9_transform.png -------------------------------------------------------------------------------- /docs/_figures/_9_translate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_figures/_9_translate.png -------------------------------------------------------------------------------- /docs/_figures/_adv_0_ytron.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_figures/_adv_0_ytron.png -------------------------------------------------------------------------------- /docs/_figures/_adv_erc_jtl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_figures/_adv_erc_jtl.png -------------------------------------------------------------------------------- /docs/_figures/_adv_jtl_erc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_figures/_adv_jtl_erc.png -------------------------------------------------------------------------------- /docs/_figures/_adv_jtl_net.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_figures/_adv_jtl_net.png -------------------------------------------------------------------------------- /spira/yevon/vmodel/__init__.py: -------------------------------------------------------------------------------- 1 | from .elements import * 2 | from .boundary import * 3 | # from .geometry import * 4 | -------------------------------------------------------------------------------- /docs/_build/doctrees/pdk.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/doctrees/pdk.doctree -------------------------------------------------------------------------------- /docs/_build/html/_static/file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/file.png -------------------------------------------------------------------------------- /docs/_build/html/_static/plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/plus.png -------------------------------------------------------------------------------- /docs/_figures/_6_hierarchy_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_figures/_6_hierarchy_0.png -------------------------------------------------------------------------------- /docs/_figures/_6_hierarchy_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_figures/_6_hierarchy_1.png -------------------------------------------------------------------------------- /docs/_figures/_adv_erc_jtl_m5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_figures/_adv_erc_jtl_m5.png -------------------------------------------------------------------------------- /docs/_figures/_adv_jtl_false.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_figures/_adv_jtl_false.png -------------------------------------------------------------------------------- /spira/yevon/io/__init__.py: -------------------------------------------------------------------------------- 1 | from spira.yevon.io.input_gdsii import * 2 | from spira.yevon.io.output_gdsii import * 3 | 4 | -------------------------------------------------------------------------------- /spira/yevon/visualization/__init__.py: -------------------------------------------------------------------------------- 1 | from .color import * 2 | from .display import * 3 | from .patterns import * 4 | 5 | -------------------------------------------------------------------------------- /docs/_build/doctrees/gdsii.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/doctrees/gdsii.doctree -------------------------------------------------------------------------------- /docs/_build/doctrees/index.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/doctrees/index.doctree -------------------------------------------------------------------------------- /docs/_build/html/_images/_group.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_images/_group.png -------------------------------------------------------------------------------- /docs/_build/html/_images/_ports.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_images/_ports.png -------------------------------------------------------------------------------- /docs/_build/html/_images/_routes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_images/_routes.png -------------------------------------------------------------------------------- /docs/_build/html/_static/minus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/minus.png -------------------------------------------------------------------------------- /docs/_figures/_4_ports_0_enabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_figures/_4_ports_0_enabled.png -------------------------------------------------------------------------------- /docs/_figures/_adv_0_ytron_pcell.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_figures/_adv_0_ytron_pcell.png -------------------------------------------------------------------------------- /docs/_figures/_adv_jtl_netlist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_figures/_adv_jtl_netlist.png -------------------------------------------------------------------------------- /docs/_figures/_adv_junction_bot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_figures/_adv_junction_bot.png -------------------------------------------------------------------------------- /docs/_figures/_adv_junction_top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_figures/_adv_junction_top.png -------------------------------------------------------------------------------- /docs/_figures/_adv_junction_true.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_figures/_adv_junction_true.png -------------------------------------------------------------------------------- /spira/yevon/geometry/shapes/__init__.py: -------------------------------------------------------------------------------- 1 | from .basic import * 2 | from .shape import * 3 | from .advance import * 4 | 5 | 6 | -------------------------------------------------------------------------------- /docs/_build/doctrees/_2_basic.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/doctrees/_2_basic.doctree -------------------------------------------------------------------------------- /docs/_build/doctrees/overview.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/doctrees/overview.doctree -------------------------------------------------------------------------------- /docs/_build/doctrees/tutorials.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/doctrees/tutorials.doctree -------------------------------------------------------------------------------- /docs/_build/html/.doctrees/pdk.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/.doctrees/pdk.doctree -------------------------------------------------------------------------------- /docs/_build/html/_images/_3_layout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_images/_3_layout.png -------------------------------------------------------------------------------- /docs/_build/html/_images/_9_factor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_images/_9_factor.png -------------------------------------------------------------------------------- /docs/_build/html/_images/_9_ports.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_images/_9_ports.png -------------------------------------------------------------------------------- /docs/_build/html/_images/_elements.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_images/_elements.png -------------------------------------------------------------------------------- /docs/_figures/_adv_0_ytron_circuit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_figures/_adv_0_ytron_circuit.png -------------------------------------------------------------------------------- /docs/_figures/_adv_junction_false.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_figures/_adv_junction_false.png -------------------------------------------------------------------------------- /spira/yevon/aspects/base.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | class __Aspects__(object): 4 | """ Base class for properties. """ 5 | pass 6 | 7 | -------------------------------------------------------------------------------- /docs/_build/doctrees/_1_overview.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/doctrees/_1_overview.doctree -------------------------------------------------------------------------------- /docs/_build/doctrees/_3_advanced.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/doctrees/_3_advanced.doctree -------------------------------------------------------------------------------- /docs/_build/doctrees/_4_reference.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/doctrees/_4_reference.doctree -------------------------------------------------------------------------------- /docs/_build/doctrees/developers.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/doctrees/developers.doctree -------------------------------------------------------------------------------- /docs/_build/doctrees/overview_old.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/doctrees/overview_old.doctree -------------------------------------------------------------------------------- /docs/_build/doctrees/parameters.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/doctrees/parameters.doctree -------------------------------------------------------------------------------- /docs/_build/doctrees/rdd_schema.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/doctrees/rdd_schema.doctree -------------------------------------------------------------------------------- /docs/_build/html/.doctrees/gdsii.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/.doctrees/gdsii.doctree -------------------------------------------------------------------------------- /docs/_build/html/.doctrees/index.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/.doctrees/index.doctree -------------------------------------------------------------------------------- /docs/_build/html/_images/RouteConnect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_images/RouteConnect.png -------------------------------------------------------------------------------- /docs/_build/html/_images/_4_ports_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_images/_4_ports_0.png -------------------------------------------------------------------------------- /docs/_build/html/_images/_4_ports_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_images/_4_ports_1.png -------------------------------------------------------------------------------- /docs/_build/html/_images/_5_routes_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_images/_5_routes_0.png -------------------------------------------------------------------------------- /docs/_build/html/_images/_9_expanded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_images/_9_expanded.png -------------------------------------------------------------------------------- /docs/_build/html/_images/_9_transform.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_images/_9_transform.png -------------------------------------------------------------------------------- /docs/_build/html/_images/_9_translate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_images/_9_translate.png -------------------------------------------------------------------------------- /docs/_build/html/_images/_adv_0_ytron.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_images/_adv_0_ytron.png -------------------------------------------------------------------------------- /docs/_build/html/_images/_adv_erc_jtl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_images/_adv_erc_jtl.png -------------------------------------------------------------------------------- /docs/_build/html/_images/_adv_jtl_erc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_images/_adv_jtl_erc.png -------------------------------------------------------------------------------- /docs/_build/html/_images/_adv_jtl_net.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_images/_adv_jtl_net.png -------------------------------------------------------------------------------- /docs/_build/html/_static/figures/hole.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/figures/hole.png -------------------------------------------------------------------------------- /spira/all.py: -------------------------------------------------------------------------------- 1 | 2 | from spira.yevon.all import * 3 | 4 | from spira.yevon.process import get_rule_deck 5 | 6 | RDD = get_rule_deck() 7 | -------------------------------------------------------------------------------- /.ipynb_checkpoints/Untitled-checkpoint.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [], 3 | "metadata": {}, 4 | "nbformat": 4, 5 | "nbformat_minor": 2 6 | } 7 | -------------------------------------------------------------------------------- /docs/_build/doctrees/_0_methodology.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/doctrees/_0_methodology.doctree -------------------------------------------------------------------------------- /docs/_build/doctrees/_5_developers.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/doctrees/_5_developers.doctree -------------------------------------------------------------------------------- /docs/_build/doctrees/pcell_examples.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/doctrees/pcell_examples.doctree -------------------------------------------------------------------------------- /docs/_build/html/.doctrees/_2_basic.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/.doctrees/_2_basic.doctree -------------------------------------------------------------------------------- /docs/_build/html/.doctrees/overview.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/.doctrees/overview.doctree -------------------------------------------------------------------------------- /docs/_build/html/_images/_6_hierarchy_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_images/_6_hierarchy_0.png -------------------------------------------------------------------------------- /docs/_build/html/_images/_6_hierarchy_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_images/_6_hierarchy_1.png -------------------------------------------------------------------------------- /docs/_build/html/_images/_adv_jtl_false.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_images/_adv_jtl_false.png -------------------------------------------------------------------------------- /tutorials/basic/_2_process_1.py: -------------------------------------------------------------------------------- 1 | import spira.all as spira 2 | 3 | from spira.technologies.mit.process.database import RDD 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /docs/_build/html/.doctrees/_1_overview.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/.doctrees/_1_overview.doctree -------------------------------------------------------------------------------- /docs/_build/html/.doctrees/_3_advanced.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/.doctrees/_3_advanced.doctree -------------------------------------------------------------------------------- /docs/_build/html/.doctrees/developers.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/.doctrees/developers.doctree -------------------------------------------------------------------------------- /docs/_build/html/.doctrees/framework.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/.doctrees/framework.doctree -------------------------------------------------------------------------------- /docs/_build/html/.doctrees/parameters.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/.doctrees/parameters.doctree -------------------------------------------------------------------------------- /docs/_build/html/.doctrees/rdd_schema.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/.doctrees/rdd_schema.doctree -------------------------------------------------------------------------------- /docs/_build/html/.doctrees/tutorials.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/.doctrees/tutorials.doctree -------------------------------------------------------------------------------- /docs/_build/html/_images/_adv_jtl_netlist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_images/_adv_jtl_netlist.png -------------------------------------------------------------------------------- /docs/_build/html/_images/_adv_junction_bot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_images/_adv_junction_bot.png -------------------------------------------------------------------------------- /docs/_build/html/_images/_adv_junction_top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_images/_adv_junction_top.png -------------------------------------------------------------------------------- /docs/_build/html/_static/_figures/_9_ports.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/_figures/_9_ports.png -------------------------------------------------------------------------------- /docs/_build/html/_static/_figures/_group.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/_figures/_group.png -------------------------------------------------------------------------------- /docs/_build/html/_static/_figures/_ports.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/_figures/_ports.png -------------------------------------------------------------------------------- /docs/_build/html/_static/_figures/_routes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/_figures/_routes.png -------------------------------------------------------------------------------- /docs/_build/html/_static/fonts/Inconsolata.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/fonts/Inconsolata.ttf -------------------------------------------------------------------------------- /docs/_build/html/_static/fonts/Lato-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/fonts/Lato-Bold.ttf -------------------------------------------------------------------------------- /docs/_build/html/.doctrees/_2_tutorials.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/.doctrees/_2_tutorials.doctree -------------------------------------------------------------------------------- /docs/_build/html/.doctrees/_3_reference.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/.doctrees/_3_reference.doctree -------------------------------------------------------------------------------- /docs/_build/html/.doctrees/_4_reference.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/.doctrees/_4_reference.doctree -------------------------------------------------------------------------------- /docs/_build/html/.doctrees/_5_developers.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/.doctrees/_5_developers.doctree -------------------------------------------------------------------------------- /docs/_build/html/.doctrees/overview_old.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/.doctrees/overview_old.doctree -------------------------------------------------------------------------------- /docs/_build/html/_images/_4_ports_0_enabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_images/_4_ports_0_enabled.png -------------------------------------------------------------------------------- /docs/_build/html/_images/_adv_0_ytron_pcell.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_images/_adv_0_ytron_pcell.png -------------------------------------------------------------------------------- /docs/_build/html/_images/_adv_junction_false.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_images/_adv_junction_false.png -------------------------------------------------------------------------------- /docs/_build/html/_images/_adv_junction_true.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_images/_adv_junction_true.png -------------------------------------------------------------------------------- /docs/_build/html/_static/_figures/_3_layout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/_figures/_3_layout.png -------------------------------------------------------------------------------- /docs/_build/html/_static/_figures/_4_ports_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/_figures/_4_ports_0.png -------------------------------------------------------------------------------- /docs/_build/html/_static/_figures/_4_ports_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/_figures/_4_ports_1.png -------------------------------------------------------------------------------- /docs/_build/html/_static/_figures/_6_hierarchy_0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/_figures/_6_hierarchy_0 -------------------------------------------------------------------------------- /docs/_build/html/_static/_figures/_9_factor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/_figures/_9_factor.png -------------------------------------------------------------------------------- /docs/_build/html/_static/_figures/_elements.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/_figures/_elements.png -------------------------------------------------------------------------------- /docs/_build/html/_static/_figures/spira_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/_figures/spira_logo.png -------------------------------------------------------------------------------- /docs/_build/html/_static/fonts/Lato-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/fonts/Lato-Regular.ttf -------------------------------------------------------------------------------- /docs/_build/html/.doctrees/_0_methodology.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/.doctrees/_0_methodology.doctree -------------------------------------------------------------------------------- /docs/_build/html/.doctrees/gettingstarted.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/.doctrees/gettingstarted.doctree -------------------------------------------------------------------------------- /docs/_build/html/.doctrees/pcell_examples.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/.doctrees/pcell_examples.doctree -------------------------------------------------------------------------------- /docs/_build/html/_images/_adv_0_ytron_circuit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_images/_adv_0_ytron_circuit.png -------------------------------------------------------------------------------- /docs/_build/html/_static/_figures/RouteConnect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/_figures/RouteConnect.png -------------------------------------------------------------------------------- /docs/_build/html/_static/_figures/_5_routes_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/_figures/_5_routes_0.png -------------------------------------------------------------------------------- /docs/_build/html/_static/_figures/_9_expanded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/_figures/_9_expanded.png -------------------------------------------------------------------------------- /docs/_build/html/_static/_figures/_9_transform.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/_figures/_9_transform.png -------------------------------------------------------------------------------- /docs/_build/html/_static/_figures/_9_translate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/_figures/_9_translate.png -------------------------------------------------------------------------------- /docs/_build/html/_static/_figures/_adv_0_ytron.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/_figures/_adv_0_ytron.png -------------------------------------------------------------------------------- /docs/_build/html/_static/_figures/_adv_erc_jtl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/_figures/_adv_erc_jtl.png -------------------------------------------------------------------------------- /docs/_build/html/_static/_figures/_adv_jtl_erc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/_figures/_adv_jtl_erc.png -------------------------------------------------------------------------------- /docs/_build/html/_static/_figures/_adv_jtl_net.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/_figures/_adv_jtl_net.png -------------------------------------------------------------------------------- /docs/_build/html/_static/fonts/Inconsolata-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/fonts/Inconsolata-Bold.ttf -------------------------------------------------------------------------------- /docs/_build/html/_static/fonts/Lato/lato-bold.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/fonts/Lato/lato-bold.eot -------------------------------------------------------------------------------- /docs/_build/html/_static/fonts/Lato/lato-bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/fonts/Lato/lato-bold.ttf -------------------------------------------------------------------------------- /docs/_build/html/_static/fonts/Lato/lato-bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/fonts/Lato/lato-bold.woff -------------------------------------------------------------------------------- /docs/_build/html/_static/fonts/Lato/lato-bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/fonts/Lato/lato-bold.woff2 -------------------------------------------------------------------------------- /docs/_build/html/_static/fonts/Lato/lato-italic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/fonts/Lato/lato-italic.eot -------------------------------------------------------------------------------- /docs/_build/html/_static/fonts/Lato/lato-italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/fonts/Lato/lato-italic.ttf -------------------------------------------------------------------------------- /docs/_build/html/_static/fonts/RobotoSlab-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/fonts/RobotoSlab-Bold.ttf -------------------------------------------------------------------------------- /spira/yevon/process/derived_layers.py: -------------------------------------------------------------------------------- 1 | # from spira.yevon.process.layer import __Layer__ 2 | # from spira.yevon.process.layer_list import LayerList 3 | 4 | -------------------------------------------------------------------------------- /docs/_build/html/_static/_figures/_6_hierarchy_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/_figures/_6_hierarchy_0.png -------------------------------------------------------------------------------- /docs/_build/html/_static/_figures/_6_hierarchy_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/_figures/_6_hierarchy_1.png -------------------------------------------------------------------------------- /docs/_build/html/_static/_figures/_adv_erc_jtl_m5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/_figures/_adv_erc_jtl_m5.png -------------------------------------------------------------------------------- /docs/_build/html/_static/_figures/_adv_jtl_false.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/_figures/_adv_jtl_false.png -------------------------------------------------------------------------------- /docs/_build/html/_static/fonts/Lato/lato-italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/fonts/Lato/lato-italic.woff -------------------------------------------------------------------------------- /docs/_build/html/_static/fonts/Lato/lato-italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/fonts/Lato/lato-italic.woff2 -------------------------------------------------------------------------------- /docs/_build/html/_static/fonts/Lato/lato-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/fonts/Lato/lato-regular.eot -------------------------------------------------------------------------------- /docs/_build/html/_static/fonts/Lato/lato-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/fonts/Lato/lato-regular.ttf -------------------------------------------------------------------------------- /docs/_build/html/_static/fonts/Lato/lato-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/fonts/Lato/lato-regular.woff -------------------------------------------------------------------------------- /docs/_build/html/_static/fonts/RobotoSlab-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/fonts/RobotoSlab-Regular.ttf -------------------------------------------------------------------------------- /docs/_build/html/_static/_figures/_4_ports_0_enabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/_figures/_4_ports_0_enabled.png -------------------------------------------------------------------------------- /docs/_build/html/_static/_figures/_adv_0_ytron_pcell.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/_figures/_adv_0_ytron_pcell.png -------------------------------------------------------------------------------- /docs/_build/html/_static/_figures/_adv_jtl_netlist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/_figures/_adv_jtl_netlist.png -------------------------------------------------------------------------------- /docs/_build/html/_static/_figures/_adv_junction_bot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/_figures/_adv_junction_bot.png -------------------------------------------------------------------------------- /docs/_build/html/_static/_figures/_adv_junction_top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/_figures/_adv_junction_top.png -------------------------------------------------------------------------------- /docs/_build/html/_static/_figures/_adv_junction_true.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/_figures/_adv_junction_true.png -------------------------------------------------------------------------------- /docs/_build/html/_static/fonts/Inconsolata-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/fonts/Inconsolata-Regular.ttf -------------------------------------------------------------------------------- /docs/_build/html/_static/fonts/Lato/lato-bolditalic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/fonts/Lato/lato-bolditalic.eot -------------------------------------------------------------------------------- /docs/_build/html/_static/fonts/Lato/lato-bolditalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/fonts/Lato/lato-bolditalic.ttf -------------------------------------------------------------------------------- /docs/_build/html/_static/fonts/Lato/lato-bolditalic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/fonts/Lato/lato-bolditalic.woff -------------------------------------------------------------------------------- /docs/_build/html/_static/fonts/Lato/lato-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/fonts/Lato/lato-regular.woff2 -------------------------------------------------------------------------------- /docs/_build/html/_static/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /docs/_build/html/_static/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /docs/_build/html/_static/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /docs/_build/html/_static/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /docs/_build/html/_static/_figures/_adv_0_ytron_circuit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/_figures/_adv_0_ytron_circuit.png -------------------------------------------------------------------------------- /docs/_build/html/_static/_figures/_adv_junction_false.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/_figures/_adv_junction_false.png -------------------------------------------------------------------------------- /docs/_build/html/_static/fonts/Lato/lato-bolditalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/fonts/Lato/lato-bolditalic.woff2 -------------------------------------------------------------------------------- /docs/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.eot -------------------------------------------------------------------------------- /docs/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.ttf -------------------------------------------------------------------------------- /docs/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff -------------------------------------------------------------------------------- /docs/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff2 -------------------------------------------------------------------------------- /docs/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.eot -------------------------------------------------------------------------------- /docs/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.ttf -------------------------------------------------------------------------------- /docs/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff -------------------------------------------------------------------------------- /docs/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubenvanstaden/spira/HEAD/docs/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff2 -------------------------------------------------------------------------------- /tests/_01_docs/_overview_parameters.0.py: -------------------------------------------------------------------------------- 1 | import spira.all as spira 2 | 3 | 4 | class Layer(spira.ParameterInitializer): 5 | number = spira.Parameter() 6 | 7 | 8 | layer = Layer(number=9) 9 | print(layer.number) 10 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | gdspy 2 | numpy 3 | networkx 4 | pandoc 5 | meshio 6 | scipy 7 | plotly 8 | pytest 9 | pyclipper 10 | pygmsh 11 | matplotlib 12 | shapely 13 | lxml 14 | termcolor 15 | colorama 16 | sphinxcontrib-napoleon 17 | # halo 18 | -------------------------------------------------------------------------------- /spira/__init__.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | 4 | def initialize(): 5 | from spira import log as LOG 6 | from . import settings 7 | LOG.start(name=settings.LIB_NAME, text=settings.START_MESSAGE) 8 | 9 | 10 | initialize() 11 | 12 | 13 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | python: 3 | - "3.7-dev" # 3.7 development branch 4 | # command to install dependencies 5 | install: 6 | - pip install -r requirements.txt 7 | # command to run tests 8 | script: 9 | - pytest tests/geo_test.py 10 | -------------------------------------------------------------------------------- /docs/_build/html/.buildinfo: -------------------------------------------------------------------------------- 1 | # Sphinx build info version 1 2 | # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. 3 | config: 7471fab6c1a18c1104d55b4919740668 4 | tags: 645f666f9bcd5a90fca523b33c5a78b7 5 | -------------------------------------------------------------------------------- /spira/yevon/engines/simulation.py: -------------------------------------------------------------------------------- 1 | # from spira.yevon.gdsii.cell import Cell 2 | 3 | 4 | # class CellSimulation(object): 5 | # """ """ 6 | 7 | # def create_simulation(self, params): 8 | # pass 9 | 10 | 11 | # Cell.mixin(CellSimulation) 12 | -------------------------------------------------------------------------------- /spira/yevon/process/all.py: -------------------------------------------------------------------------------- 1 | from .purpose_layer import * 2 | from .physical_layer import * 3 | from .process_layer import * 4 | from .layer_list import * 5 | from .gdsii_layer import * 6 | from .layer_map import * 7 | from .technology import * 8 | from .process_flow import * 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | dist/ 3 | env/ 4 | mit/ 5 | aist/ 6 | .vscode/ 7 | debug/ 8 | .eggs/ 9 | *.html 10 | *.egg-info/ 11 | .DS_Store 12 | .pos 13 | .msh 14 | env-spira/ 15 | env-mac/ 16 | env* 17 | *.gds 18 | __pycache__/ 19 | *.pos 20 | *.msh 21 | *.pyc 22 | MANIFEST.in 23 | -------------------------------------------------------------------------------- /spira/yevon/aspects/cell.py: -------------------------------------------------------------------------------- 1 | import gdspy 2 | import numpy as np 3 | 4 | from copy import deepcopy 5 | from spira.yevon.gdsii.group import __Group__ 6 | from spira.yevon.aspects.geometry import __GeometryAspects__ 7 | 8 | 9 | class CellAspects(__Group__, __GeometryAspects__): 10 | pass 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /spira/core/transforms/__init__.py: -------------------------------------------------------------------------------- 1 | from spira.core.transforms.identity import * 2 | from spira.core.transforms.translation import * 3 | from spira.core.transforms.rotation import * 4 | from spira.core.transforms.reflection import * 5 | from spira.core.transforms.magnification import * 6 | from spira.core.transforms.stretching import * 7 | 8 | -------------------------------------------------------------------------------- /spira/yevon/filters/__init__.py: -------------------------------------------------------------------------------- 1 | from .filter import * 2 | from .empty_filter import * 3 | from .layer_filter import * 4 | from .boolean_filter import * 5 | from .net_label_filter import * 6 | from .net_branch_filters import * 7 | from .edge_filter import * 8 | from .polygon_filters import * 9 | from .device_filters import * 10 | 11 | 12 | -------------------------------------------------------------------------------- /spira/yevon/utils/debugging.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | __all__ = ['debug_view'] 4 | 5 | 6 | def debug_view(cell): 7 | D = cell.expand_flat_copy() 8 | print('\n---------------------------------') 9 | print('[*] List of Ports:') 10 | print(D.ports) 11 | print('---------------------------------\n') 12 | D.gdsii_output() 13 | 14 | -------------------------------------------------------------------------------- /spira/yevon/gdsii/__init__.py: -------------------------------------------------------------------------------- 1 | from spira.yevon.gdsii.cell import * 2 | from spira.yevon.gdsii.cell_list import * 3 | from spira.yevon.gdsii.group import * 4 | from spira.yevon.gdsii.label import * 5 | from spira.yevon.gdsii.library import * 6 | from spira.yevon.gdsii.polygon import * 7 | from spira.yevon.gdsii.sref import * 8 | from spira.yevon.gdsii.pcell import * 9 | -------------------------------------------------------------------------------- /tests/_01_docs/_overview_parameters.2.py: -------------------------------------------------------------------------------- 1 | import spira.all as spira 2 | 3 | 4 | class Layer(spira.ParameterInitializer): 5 | number = spira.Parameter(default=0) 6 | datatype = spira.Parameter(fdef_name='create_datatype') 7 | 8 | def create_datatype(self): 9 | return 2 + 3 10 | 11 | 12 | layer = Layer() 13 | print(layer.number) 14 | print(layer.datatype) 15 | 16 | -------------------------------------------------------------------------------- /spira/enginex/engine.py: -------------------------------------------------------------------------------- 1 | # from spira.core.parameters.initializer import ParameterInitializer 2 | 3 | 4 | # class __SimulationEngine__(ParameterInitializer): 5 | # pass 6 | 7 | 8 | # class InductEx(__SimulationEngine__): 9 | # pass 10 | 11 | 12 | # class JoSim(__SimulationEngine__): 13 | # pass 14 | 15 | 16 | # class Durendal(__SimulationEngine__): 17 | # pass 18 | 19 | -------------------------------------------------------------------------------- /docs/_build/html/_static/documentation_options.js: -------------------------------------------------------------------------------- 1 | var DOCUMENTATION_OPTIONS = { 2 | URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), 3 | VERSION: 'Auron [Beta]', 4 | LANGUAGE: 'None', 5 | COLLAPSE_INDEX: false, 6 | FILE_SUFFIX: '.html', 7 | HAS_SOURCE: true, 8 | SOURCELINK_SUFFIX: '.txt', 9 | NAVIGATION_WITH_KEYS: false 10 | }; -------------------------------------------------------------------------------- /spira/validatex/drc/overlap.py: -------------------------------------------------------------------------------- 1 | import spira.all as spira 2 | from spira.lrc.rules import __DoubleLayerDesignRule__ 3 | 4 | 5 | RDD = spira.get_rule_deck() 6 | 7 | 8 | class Overlap(__DoubleLayerDesignRule__): 9 | minimum = param.FloatParameter() 10 | 11 | def __repr__(self): 12 | return 'Rule surround: min={}'.format(self.minimum) 13 | 14 | def apply(self, elems): 15 | pass 16 | -------------------------------------------------------------------------------- /spira/yevon/process/__init__.py: -------------------------------------------------------------------------------- 1 | from .technology import TechnologyLibrary 2 | 3 | 4 | global RULE_DECK_DATABASE 5 | RULE_DECK_DATABASE = TechnologyLibrary('EMPTY') 6 | 7 | 8 | def get_rule_deck(): 9 | global RULE_DECK_DATABASE 10 | if RULE_DECK_DATABASE.name == 'EMPTY': 11 | initialize_default() 12 | return RULE_DECK_DATABASE 13 | 14 | 15 | def initialize_default(): 16 | from spira.technologies import default 17 | -------------------------------------------------------------------------------- /tests/_01_docs/_overview_elements.py: -------------------------------------------------------------------------------- 1 | import spira.all as spira 2 | 3 | 4 | class PolygonExample(spira.Cell): 5 | 6 | def create_elements(self, elems): 7 | pts = [[0, 0], [2, 2], [2, 6], [-6, 6], [-6, -6], [-4, -4], [-4, 4], [0, 4]] 8 | shape = spira.Shape(points=pts) 9 | elems += spira.Polygon(shape=shape, layer=spira.Layer(1)) 10 | return elems 11 | 12 | 13 | D = PolygonExample() 14 | D.gdsii_output(name='Element') -------------------------------------------------------------------------------- /spira/core/all.py: -------------------------------------------------------------------------------- 1 | from spira.core.parameters.variables import * 2 | from spira.core.parameters.restrictions import * 3 | 4 | from spira.core.parameters.descriptor import * 5 | from spira.core.parameters.initializer import * 6 | 7 | from spira.core.transformable import * 8 | from spira.core.transformation import * 9 | from spira.core.transforms import * 10 | 11 | from spira.core.parameters.processors import * 12 | 13 | from spira.core.decorators import * 14 | -------------------------------------------------------------------------------- /tutorials/reference/_0_filters.py: -------------------------------------------------------------------------------- 1 | import spira.all as spira 2 | 3 | 4 | ll = spira.LayerList() 5 | ll += spira.Layer(1) 6 | ll += spira.Layer(2) 7 | print(ll) 8 | # lf = spira.LayerFilterDelete(layers=ll) 9 | lf = spira.LayerFilterAllow(layers=ll) 10 | print(lf.layers) 11 | print(len(lf.layers)) 12 | 13 | print(lf) 14 | 15 | p1 = spira.Rectangle(layer=spira.Layer(1)) 16 | p2 = spira.Rectangle(layer=spira.Layer(3)) 17 | 18 | F = lf([p1, p2]) 19 | print(F) 20 | 21 | -------------------------------------------------------------------------------- /tests/_01_docs/_overview_parameters.3.py: -------------------------------------------------------------------------------- 1 | import spira.all as spira 2 | 3 | 4 | class Layer(spira.ParameterInitializer): 5 | # number = spira.Parameter(default=0, restriction=spira.RestrictRange(2,5)) 6 | number = spira.IntegerParameter(default=0, restriction=spira.RestrictRange(2,5)) 7 | 8 | 9 | layer = Layer() 10 | layer.number = 3 11 | print(layer.number) 12 | layer.number = 6 13 | print(layer.number) 14 | layer.number = 1 15 | print(layer.number) 16 | 17 | -------------------------------------------------------------------------------- /tests/_01_docs/_overview_shapes.py: -------------------------------------------------------------------------------- 1 | import spira.all as spira 2 | 3 | 4 | class ShapeExample(spira.Shape): 5 | 6 | def create_points(self, points): 7 | points = [[0, 0], [2, 2], [2, 6], [-6, 6], [-6, -6], [-4, -4], [-4, 4], [0, 4]] 8 | return points 9 | 10 | 11 | shape = ShapeExample() 12 | print(shape.points) 13 | print(shape.area) 14 | shape.move((10, 0)) 15 | print([list([c[0], c[1]]) for c in shape.points]) 16 | print(shape.x_coords) 17 | 18 | 19 | -------------------------------------------------------------------------------- /tutorials/reference/caching.py: -------------------------------------------------------------------------------- 1 | import spira.all as spira 2 | 3 | 4 | cnt = 0 5 | class MyClass(spira.FieldInitializer): 6 | 7 | prop_a = spira.StringField(default='a') 8 | prop_aa = spira.DataField(fdef_name='create_prop_aa') 9 | 10 | def create_prop_aa(self): 11 | global cnt 12 | cnt = cnt + 1 13 | print("called '_default_prop_aa' {} times".format(cnt)) 14 | return self.prop_a * 2 15 | 16 | 17 | my_cls = MyClass() 18 | my_cls.prop_aa 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /spira/core/mixin.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | class MetaMixinBowl(type): 4 | """ Base SPiRA metaclass. """ 5 | def mixin(cls, mixin_class): 6 | if not mixin_class in cls.__bases__: 7 | if cls.__bases__ == (object,): 8 | cls.__bases__ = (mixin_class,) 9 | else: 10 | cls.__bases__ = (mixin_class,) + cls.__bases__ 11 | 12 | 13 | class MixinBowl(metaclass=MetaMixinBowl): 14 | """ Base mixin class for the SPiRA framework. """ 15 | pass 16 | -------------------------------------------------------------------------------- /spira/yevon/aspects/netlist.py: -------------------------------------------------------------------------------- 1 | from spira.yevon.aspects.base import __Aspects__ 2 | from spira.core.parameters.descriptor import Parameter 3 | from spira.yevon.geometry.nets.net import Net 4 | from spira.yevon.geometry.nets.net_list import NetListParameter 5 | 6 | 7 | class NetlistAspects(__Aspects__): 8 | """ Defines the nets from the defined elements. """ 9 | 10 | netlist = Parameter(fdef_name='create_netlist') 11 | 12 | def create_netlist(self): 13 | net = Net() 14 | return net 15 | 16 | -------------------------------------------------------------------------------- /spira/yevon/gdsii/containers.py: -------------------------------------------------------------------------------- 1 | from spira.yevon.gdsii.cell import Cell, CellParameter 2 | from spira.yevon.gdsii.sref import SRef 3 | from copy import deepcopy 4 | from spira.core.parameters.descriptor import Parameter 5 | from spira.yevon.gdsii.elem_list import ElementListParameter 6 | 7 | 8 | class __CellContainer__(Cell): 9 | 10 | cell = CellParameter(allow_none=True, default=None) 11 | 12 | def create_elements(self, elems): 13 | elems += SRef(reference=self.cell) 14 | return elems 15 | 16 | -------------------------------------------------------------------------------- /tests/_01_docs/_framework_ports.py: -------------------------------------------------------------------------------- 1 | import spira.all as spira 2 | 3 | 4 | class PortExample(spira.Cell): 5 | 6 | def create_elements(self, elems): 7 | elems += spira.Rectangle(p1=(0,0), p2=(20,5), layer=spira.Layer(1)) 8 | return elems 9 | 10 | def create_ports(self, ports): 11 | ports += spira.Port(name='P1', midpoint=(0,2.5), orientation=180) 12 | ports += spira.Port(name='P2', midpoint=(20,2.5), orientation=0) 13 | return ports 14 | 15 | 16 | D = PortExample() 17 | D.gdsii_output() 18 | -------------------------------------------------------------------------------- /spira/technologies/waterloo/process/__init__.py: -------------------------------------------------------------------------------- 1 | from spira.yevon.process import get_rule_deck 2 | 3 | 4 | __all__ = ['RDD'] 5 | 6 | 7 | RDD = get_rule_deck() 8 | 9 | # --- Initialize ------------------------------------------------------------------- 10 | 11 | RDD.name = 'MiTLL' 12 | RDD.desc = 'The MIT LL SFQ5ee fabrication process.' 13 | 14 | # --- Imports ---------------------------------------------------------------------- 15 | 16 | from .general import * 17 | from .database import * 18 | from .display_resources import * 19 | 20 | -------------------------------------------------------------------------------- /tests/_01_docs/_overview_parameters.1.py: -------------------------------------------------------------------------------- 1 | import spira.all as spira 2 | 3 | 4 | class Layer(spira.ParameterInitializer): 5 | number = spira.Parameter(default=0, restrictions=spira.INTEGER, preprocess=spira.ProcessorInt(), doc='Advanced parameter.') 6 | 7 | 8 | layer = Layer() 9 | print(layer.number) 10 | 11 | layer.number = 9 12 | print(layer.number) 13 | 14 | layer.number = 1.2 15 | print(layer.number) 16 | 17 | layer.number = '8' 18 | print(layer.number) 19 | 20 | layer.number = '1.2' 21 | print(layer.number) 22 | 23 | layer.number = 'Hi' 24 | -------------------------------------------------------------------------------- /spira/yevon/filters/empty_filter.py: -------------------------------------------------------------------------------- 1 | from spira.log import SPIRA_LOG as LOG 2 | from spira.yevon.filters.filter import Filter 3 | 4 | 5 | __all__ = ['EmptyFilter'] 6 | 7 | 8 | class EmptyFilter(Filter): 9 | """ Empty filter used for concatenation. """ 10 | 11 | def filter_default(self, item): 12 | if hasattr(item, 'is_empty'): 13 | if item.is_empty(): 14 | LOG.debug('Emptyfilter is filtering out : {}'.format(item)) 15 | return [] 16 | return [item] 17 | 18 | def __repr__(self): 19 | return '' -------------------------------------------------------------------------------- /spira/yevon/io/file_type.py: -------------------------------------------------------------------------------- 1 | from spira.core.parameters.initializer import ParameterInitializer 2 | from spira.core.parameters.variables import StringParameter 3 | 4 | 5 | class FileType(ParameterInitializer): 6 | """ """ 7 | 8 | name = StringParameter(default='') 9 | doc = StringParameter(default='') 10 | 11 | def __str__(self): 12 | return self.name 13 | 14 | 15 | GDSII = FileType(name='GDSII', doc='GDSII file format.') 16 | SPICE = FileType(name='SPICE', doc='JoSIM file format.') 17 | LEFDEF = FileType(name='LEFDEF', doc='LEF and DEF file format.') 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /spira/technologies/default/__init__.py: -------------------------------------------------------------------------------- 1 | from spira.yevon.process import get_rule_deck 2 | 3 | 4 | __all__ = ['RDD'] 5 | 6 | 7 | RDD = get_rule_deck() 8 | 9 | # --- Initialize ------------------------------------------------------------------------------- 10 | 11 | RDD.name = 'SPiRA-DEFAULT' 12 | RDD.desc = 'Default SPiRA process information, that mimics a general SFQ fabrication process.' 13 | 14 | # --- Imports ---------------------------------------------------------------------------------- 15 | 16 | from .general import * 17 | from .database import * 18 | from .display_resources import * 19 | 20 | -------------------------------------------------------------------------------- /spira/yevon/all.py: -------------------------------------------------------------------------------- 1 | from spira.yevon.constants import * 2 | 3 | from spira.core.all import * 4 | 5 | import spira.yevon.aspects 6 | 7 | from spira.yevon.geometry.coord import * 8 | from spira.yevon.geometry.edges import * 9 | from spira.yevon.geometry.shapes import * 10 | from spira.yevon.geometry.ports import * 11 | from spira.yevon.geometry.nets import * 12 | from spira.yevon.geometry.route import * 13 | 14 | from spira.yevon.io import * 15 | from spira.yevon.vmodel import * 16 | from spira.yevon.process.all import * 17 | from spira.yevon.gdsii import * 18 | from spira.yevon.filters import * 19 | from spira.yevon.visualization import * 20 | 21 | 22 | -------------------------------------------------------------------------------- /tests/_01_docs/_overview_group_0.py: -------------------------------------------------------------------------------- 1 | import spira.all as spira 2 | 3 | 4 | class GroupExample(spira.Cell): 5 | 6 | def create_elements(self, elems): 7 | 8 | group = spira.Group() 9 | group += spira.Rectangle(p1=(0,0), p2=(10,10), layer=spira.Layer(1)) 10 | group += spira.Rectangle(p1=(0,15), p2=(10,30), layer=spira.Layer(1)) 11 | 12 | group.rotate(30) 13 | 14 | elems += group 15 | 16 | bbox_shape = group.bbox_info.bounding_box(margin=1) 17 | elems += spira.Polygon(shape=bbox_shape, layer=spira.Layer(2)) 18 | 19 | return elems 20 | 21 | 22 | D = GroupExample() 23 | D.gdsii_view() 24 | 25 | -------------------------------------------------------------------------------- /spira/yevon/aspects/shape.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from spira.yevon.utils import clipping 3 | from spira.yevon.aspects.clipper import __ClipperAspects__ 4 | 5 | 6 | class ShapeClipperAspects(__ClipperAspects__): 7 | """ 8 | 9 | Examples 10 | -------- 11 | """ 12 | 13 | def __and__(self, other): 14 | return clipping.boolean(subj=[self.points], clip=[other.points], clip_type='and') 15 | 16 | def __sub__(self, other): 17 | return clipping.boolean(subj=[self.points], clip=[other.points], clip_type='not') 18 | 19 | def __or__(self, other): 20 | return clipping.boolean(subj=[self.points], clip=[other.points], clip_type='or') 21 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | SPHINXPROJ = Yuna 8 | SOURCEDIR = . 9 | BUILDDIR = _build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) -------------------------------------------------------------------------------- /docs/_build/html/_static/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | SPHINXPROJ = Yuna 8 | SOURCEDIR = . 9 | BUILDDIR = _build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) -------------------------------------------------------------------------------- /tutorials/basic/_10_edge_generator.py: -------------------------------------------------------------------------------- 1 | import spira.all as spira 2 | from spira.yevon import filters 3 | from spira.yevon import constants 4 | from spira.all import RDD 5 | 6 | 7 | ply1 = spira.Rectangle(p1=(0,0), p2=(10,2), layer=RDD.PLAYER.M1.METAL) 8 | D = spira.Cell(name='TopLevel', elements=[ply1]) 9 | 10 | # D += ply1.edges 11 | 12 | for edge in ply1.edges: 13 | EF = filters.EdgeToPolygonFilter() 14 | D += EF(edge) 15 | 16 | # for e in ply1.edges: 17 | # D += spira.EdgeAdapter(original_edge=e, edge_type=constants.EDGE_TYPE_OUTSIDE) 18 | 19 | # EF = filters.EdgeFilter(edge_type=constants.EDGE_TYPE_OUTSIDE) 20 | # D = EF(D) 21 | 22 | D.gdsii_output(file_name='Edges') 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /tests/_01_docs/_overview_routes_0.py: -------------------------------------------------------------------------------- 1 | import spira.all as spira 2 | 3 | 4 | class RouteExample(spira.Cell): 5 | 6 | @spira.cache() 7 | def get_io_ports(self): 8 | p1 = spira.Port(name='P1_M1', midpoint=(0,0), orientation=180) 9 | p2 = spira.Port(name='P2_M1', midpoint=(20,10), orientation=0) 10 | return [p1, p2] 11 | 12 | def create_elements(self, elems): 13 | ports = self.get_io_ports() 14 | elems += spira.RouteManhattan(ports=ports, layer=spira.RDD.PLAYER.M1.METAL) 15 | return elems 16 | 17 | def create_ports(self, ports): 18 | ports += self.get_io_ports() 19 | return ports 20 | 21 | 22 | D = RouteExample() 23 | D.gdsii_view() 24 | 25 | -------------------------------------------------------------------------------- /spira/yevon/process/process_flow.py: -------------------------------------------------------------------------------- 1 | from spira.core.parameters.initializer import ParameterInitializer 2 | from spira.core.parameters.descriptor import Parameter, RestrictedParameter 3 | from spira.core.parameters.restrictions import RestrictType 4 | 5 | 6 | __all__ = ['VModelProcessFlow', 'VModelProcessFlowParameter'] 7 | 8 | 9 | class VModelProcessFlow(ParameterInitializer): 10 | """ """ 11 | 12 | active_processes = Parameter(doc='Active process layers for virtual model creation.') 13 | 14 | 15 | def VModelProcessFlowParameter(local_name=None, restriction=None, **kwargs): 16 | R = RestrictType(VModelProcessFlow) & restriction 17 | return RestrictedParameter(local_name, restriction=R, **kwargs) 18 | 19 | -------------------------------------------------------------------------------- /spira/yevon/io/collector.py: -------------------------------------------------------------------------------- 1 | import gdspy 2 | from spira.core.parameters.initializer import ParameterInitializer 3 | 4 | 5 | class __Collector__(ParameterInitializer): 6 | 7 | def __init__(self, **kwargs): 8 | self.reset() 9 | super().__init__(**kwargs) 10 | 11 | def reset(self): 12 | return self 13 | 14 | 15 | class ListCollector(__Collector__): 16 | 17 | def __init__(self, **kwargs): 18 | super().__init__(**kwargs) 19 | self._list = {} 20 | 21 | def __iadd__(self, item): 22 | self._list.update(item) 23 | return self 24 | 25 | def reset(self): 26 | return self 27 | 28 | def cells(self): 29 | return self._list.values() 30 | 31 | 32 | -------------------------------------------------------------------------------- /tests/_01_docs/_overview_routes_1.py: -------------------------------------------------------------------------------- 1 | import spira.all as spira 2 | 3 | 4 | class RouteExample(spira.Cell): 5 | 6 | @spira.cache() 7 | def get_io_ports(self): 8 | p1 = spira.Port(name='P1', midpoint=(0,0), orientation=180) 9 | p2 = spira.Port(name='P2', midpoint=(20,10), orientation=0) 10 | return [p1, p2] 11 | 12 | def create_elements(self, elems): 13 | ports = self.get_io_ports() 14 | elems += spira.RouteManhattan(ports=ports, layer=spira.RDD.PLAYER.M1.METAL) 15 | return elems 16 | 17 | def create_ports(self, ports): 18 | ports += self.get_io_ports() 19 | return ports 20 | 21 | 22 | D = RouteExample() 23 | D.gdsii_output(name='Routes') 24 | 25 | -------------------------------------------------------------------------------- /tests/_01_docs/_overview_routes_2.py: -------------------------------------------------------------------------------- 1 | import spira.all as spira 2 | 3 | 4 | class RouteExample(spira.Cell): 5 | 6 | @spira.cache() 7 | def get_io_ports(self): 8 | p1 = spira.Port(name='P1', midpoint=(0,0), orientation=180, process=spira.RDD.PROCESS.M1) 9 | p2 = spira.Port(name='P2', midpoint=(20,10), orientation=0, process=spira.RDD.PROCESS.M1) 10 | return [p1, p2] 11 | 12 | def create_elements(self, elems): 13 | ports = self.get_io_ports() 14 | elems += spira.RouteManhattan(ports=ports, layer=spira.RDD.PLAYER.M1.METAL) 15 | return elems 16 | 17 | def create_ports(self, ports): 18 | ports += self.get_io_ports() 19 | return ports 20 | 21 | 22 | D = RouteExample() 23 | D.gdsii_view() 24 | 25 | -------------------------------------------------------------------------------- /docs/_build/html/_static/gdsii.rst: -------------------------------------------------------------------------------- 1 | GDSII Elementals 2 | ################ 3 | 4 | 5 | .. Classes 6 | .. ******* 7 | 8 | .. .. .. py:function:: create_elements 9 | .. .. Creates an elemental. 10 | 11 | .. .. .. function:: format_exception(etype, value, tb[, limit=None]) 12 | 13 | .. .. Format the exception with a traceback. 14 | 15 | .. .. :param etype: exception type 16 | .. .. :param value: exception value 17 | .. .. :param tb: traceback object 18 | .. .. :param limit: maximum number of stack frames to show 19 | .. .. :type limit: integer or None 20 | .. .. :rtype: list of strings 21 | 22 | .. .. autoclass:: spira.Cell 23 | .. :members: 24 | .. :undoc-members: 25 | .. .. :inherited-members: 26 | .. .. :show-inheritance: 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /tutorials/basic/_1_pcell.py: -------------------------------------------------------------------------------- 1 | import spira.all as spira 2 | 3 | 4 | class Resistor(spira.PCell): 5 | 6 | width = spira.FloatParameter(default=0.3, doc='Width of the shunt resistance.') 7 | length = spira.FloatParameter(default=1.0, doc='Length of the shunt resistance.') 8 | 9 | def validate_parameters(self): 10 | if self.width > self.length: 11 | raise ValueError('`Width` cannot be larger than `length`.') 12 | return True 13 | 14 | 15 | if __name__ == '__main__': 16 | 17 | D = Resistor() 18 | 19 | print(D.width, D.length) 20 | 21 | # Width parameter is valid. 22 | D.width = 0.5 23 | print(D.width, D.length) 24 | 25 | # Throws a parameter invalid error. 26 | D.width = 1.1 27 | print(D.width, D.length) 28 | 29 | -------------------------------------------------------------------------------- /docs/_build/html/_sources/gdsii.rst.txt: -------------------------------------------------------------------------------- 1 | GDSII Elementals 2 | ################ 3 | 4 | 5 | .. Classes 6 | .. ******* 7 | 8 | .. .. .. py:function:: create_elements 9 | .. .. Creates an elemental. 10 | 11 | .. .. .. function:: format_exception(etype, value, tb[, limit=None]) 12 | 13 | .. .. Format the exception with a traceback. 14 | 15 | .. .. :param etype: exception type 16 | .. .. :param value: exception value 17 | .. .. :param tb: traceback object 18 | .. .. :param limit: maximum number of stack frames to show 19 | .. .. :type limit: integer or None 20 | .. .. :rtype: list of strings 21 | 22 | .. .. autoclass:: spira.Cell 23 | .. :members: 24 | .. :undoc-members: 25 | .. .. :inherited-members: 26 | .. .. :show-inheritance: 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /docs/_build/html/_static/pcell_examples.rst: -------------------------------------------------------------------------------- 1 | PCell Examples 2 | ============== 3 | 4 | .. Junction PCell 5 | .. -------------- 6 | 7 | .. A basic Junction PCell that creates physical layers instead of using native polygon structures. 8 | 9 | .. :download:`Download sample file <../demo/pdks/components/junction.py>` 10 | 11 | .. .. literalinclude:: ../demo/pdks/components/junction.py 12 | .. :language: python 13 | .. :linenos: 14 | 15 | .. SQUID PCell 16 | .. ----------- 17 | 18 | .. The following code shows a basic SQUID that uses the already defined Junction PCell to create a composite PCell. 19 | 20 | .. :download:`Download sample file <../demo/pdks/components/jj_squid.py>` 21 | 22 | .. .. literalinclude:: ../demo/pdks/components/jj_squid.py 23 | .. :language: python 24 | .. :linenos: 25 | 26 | -------------------------------------------------------------------------------- /tutorials/reference/_8_transforms.py: -------------------------------------------------------------------------------- 1 | import spira.all as spira 2 | 3 | R = spira.Rotation(30) 4 | T = spira.Translation((30, 0)) 5 | F = spira.Reflection(True) 6 | 7 | G0 = R + T + F 8 | G1 = spira.GenericTransform(translation=spira.Coord(-10, 0), rotation=45) 9 | G2 = spira.GenericTransform(translation=spira.Coord(-10, 0), rotation=45, reflection=True) 10 | G3 = spira.GenericTransform() 11 | G3 += R 12 | G3 += T 13 | G3 += F 14 | 15 | print(R) 16 | print(type(R)) 17 | print('') 18 | 19 | print(T) 20 | print(type(T)) 21 | print('') 22 | 23 | print(F) 24 | print(type(F)) 25 | print('') 26 | 27 | print(G0) 28 | print(type(G0)) 29 | print('') 30 | 31 | print(G1) 32 | print(type(G1)) 33 | print('') 34 | 35 | print(G2) 36 | print(type(G2)) 37 | print('') 38 | 39 | print(G3) 40 | print(type(G3)) 41 | print('') 42 | -------------------------------------------------------------------------------- /docs/_build/html/_sources/pcell_examples.rst.txt: -------------------------------------------------------------------------------- 1 | PCell Examples 2 | ============== 3 | 4 | .. Junction PCell 5 | .. -------------- 6 | 7 | .. A basic Junction PCell that creates physical layers instead of using native polygon structures. 8 | 9 | .. :download:`Download sample file <../demo/pdks/components/junction.py>` 10 | 11 | .. .. literalinclude:: ../demo/pdks/components/junction.py 12 | .. :language: python 13 | .. :linenos: 14 | 15 | .. SQUID PCell 16 | .. ----------- 17 | 18 | .. The following code shows a basic SQUID that uses the already defined Junction PCell to create a composite PCell. 19 | 20 | .. :download:`Download sample file <../demo/pdks/components/jj_squid.py>` 21 | 22 | .. .. literalinclude:: ../demo/pdks/components/jj_squid.py 23 | .. :language: python 24 | .. :linenos: 25 | 26 | -------------------------------------------------------------------------------- /tests/_01_docs/_overview_ports_1.py: -------------------------------------------------------------------------------- 1 | import spira.all as spira 2 | from spira.yevon.geometry import shapes 3 | 4 | 5 | class BoxDevice(spira.Cell): 6 | 7 | width = spira.NumberParameter(default=1) 8 | height = spira.NumberParameter(default=1) 9 | layer = spira.LayerParameter(default=spira.Layer(1)) 10 | 11 | def create_elements(self, elems): 12 | shape = shapes.BoxShape(width=self.width, height=self.height) 13 | elems += spira.Polygon(shape=shape, layer=self.layer) 14 | return elems 15 | 16 | def create_ports(self, ports): 17 | ports += spira.Port(name='P1', midpoint=(-0.5,0), orientation=180, width=1) 18 | ports += spira.Port(name='P2', midpoint=(0.5,0), orientation=0, width=1) 19 | return ports 20 | 21 | 22 | D = BoxDevice() 23 | D.gdsii_view() 24 | 25 | -------------------------------------------------------------------------------- /tutorials/basic/_2_process_0.py: -------------------------------------------------------------------------------- 1 | import spira.all as spira 2 | 3 | 4 | class Resistor(spira.PCell): 5 | 6 | width = spira.NumberParameter(default=spira.RDD.R1.MIN_WIDTH, doc='Width of the shunt resistance.') 7 | length = spira.NumberParameter(default=spira.RDD.R1.MIN_LENGTH, doc='Length of the shunt resistance.') 8 | 9 | def validate_parameters(self): 10 | if self.width > self.length: 11 | raise ValueError('`Width` cannot be larger than `length`.') 12 | return True 13 | 14 | 15 | if __name__ == '__main__': 16 | 17 | D = Resistor() 18 | 19 | print(D.width, D.length) 20 | 21 | # Width parameter is valid. 22 | D.width = 0.5 23 | print(D.width, D.length) 24 | 25 | # Throws a parameter invalid error. 26 | D.width = 1.1 27 | print(D.width, D.length) 28 | 29 | -------------------------------------------------------------------------------- /tutorials/basic/_3_layout_1.py: -------------------------------------------------------------------------------- 1 | import spira.all as spira 2 | from spira.all import RDD 3 | 4 | 5 | class Resistor(spira.PCell): 6 | 7 | width = spira.NumberParameter(default=RDD.R1.MIN_WIDTH, doc='Width of the shunt resistance.') 8 | length = spira.NumberParameter(default=RDD.R1.MIN_LENGTH, doc='Length of the shunt resistance.') 9 | 10 | def validate_parameters(self): 11 | if self.width > self.length: 12 | raise ValueError('`Width` cannot be larger than `length`.') 13 | return True 14 | 15 | def create_elements(self, elems): 16 | elems += spira.Box(width=self.length, height=self.width, layer=spira.RDD.PLAYER.R1.METAL) 17 | return elems 18 | 19 | 20 | if __name__ == '__main__': 21 | 22 | D = Resistor() 23 | D.gdsii_output(file_name='Resistor') 24 | 25 | 26 | -------------------------------------------------------------------------------- /spira/yevon/aspects/clipper.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from spira.yevon.aspects.base import __Aspects__ 3 | 4 | 5 | class __ClipperAspects__(__Aspects__): 6 | 7 | def __sub__(self, shape): 8 | raise Exception("Method __sub__ not implemented in abstract class __ShapeBooleanOpsAspect__") 9 | 10 | def __and__(self, shape): 11 | raise Exception("Method __and__ not implemented in abstract class __ShapeBooleanOpsAspect__") 12 | 13 | def __or__(self, shape): 14 | raise Exception("Method __or__ not implemented in abstract class __ShapeBooleanOpsAspect__") 15 | 16 | def union(self, other): 17 | return self.__or__(other) 18 | 19 | def intersection(self, other): 20 | return self.__and__(other) 21 | 22 | def difference(self, other): 23 | return self.__sub__(other) 24 | 25 | -------------------------------------------------------------------------------- /tests/_01_docs/_overview_group_2.py: -------------------------------------------------------------------------------- 1 | import spira.all as spira 2 | 3 | 4 | class GroupExample(spira.Cell): 5 | 6 | group_transform = spira.TransformationParameter(doc='Transform parameter for a group of elements.') 7 | 8 | def create_elements(self, elems): 9 | 10 | group = spira.Group() 11 | group += spira.Rectangle(p1=(0,0), p2=(10,10), layer=spira.Layer(1)) 12 | group += spira.Rectangle(p1=(0,15), p2=(10,30), layer=spira.Layer(1)) 13 | 14 | group.transform(self.group_transform) 15 | 16 | elems += group 17 | 18 | bbox_shape = group.bbox_info.bounding_box(margin=1) 19 | elems += spira.Polygon(shape=bbox_shape, layer=spira.Layer(2)) 20 | 21 | return elems 22 | 23 | 24 | # D = GroupExample() 25 | D = GroupExample(group_transform=spira.Rotation(45)) 26 | D.gdsii_view() 27 | 28 | -------------------------------------------------------------------------------- /tests/_01_docs/_overview_ports_0.py: -------------------------------------------------------------------------------- 1 | import spira.all as spira 2 | from spira.yevon.geometry import shapes 3 | 4 | 5 | class BoxDevice(spira.Cell): 6 | 7 | width = spira.NumberParameter(default=1) 8 | height = spira.NumberParameter(default=1) 9 | layer = spira.LayerParameter(default=spira.RDD.PLAYER.M1.METAL) 10 | 11 | def create_elements(self, elems): 12 | shape = shapes.BoxShape(width=self.width, height=self.height) 13 | elems += spira.Polygon(shape=shape, layer=self.layer) 14 | return elems 15 | 16 | def create_ports(self, ports): 17 | ports += spira.Port(name='M1:P1', midpoint=(-0.5,0), orientation=180, width=1) 18 | ports += spira.Port(name='M1:P2', midpoint=(0.5,0), orientation=0, width=1) 19 | return ports 20 | 21 | 22 | D = BoxDevice() 23 | D.gdsii_view() 24 | D.gdsii_output(file_name='ports') 25 | 26 | -------------------------------------------------------------------------------- /tests/_01_docs/_overview_ports_2.py: -------------------------------------------------------------------------------- 1 | import spira.all as spira 2 | from spira.yevon.geometry import shapes 3 | 4 | 5 | class BoxDevice(spira.Cell): 6 | 7 | width = spira.NumberParameter(default=1) 8 | height = spira.NumberParameter(default=1) 9 | layer = spira.LayerParameter(default=spira.Layer(1)) 10 | 11 | def create_elements(self, elems): 12 | shape = shapes.BoxShape(width=self.width, height=self.height) 13 | elems += spira.Polygon(shape=shape, layer=self.layer) 14 | return elems 15 | 16 | def create_ports(self, ports): 17 | ports += spira.Port(name='P1', midpoint=(-0.5,0), orientation=180, width=1, process=spira.RDD.PROCESS.M1) 18 | ports += spira.Port(name='P2', midpoint=(0.5,0), orientation=0, width=1, process=spira.RDD.PROCESS.M1) 19 | return ports 20 | 21 | 22 | D = BoxDevice() 23 | D.gdsii_view() 24 | 25 | -------------------------------------------------------------------------------- /tutorials/basic/_3_layout_0.py: -------------------------------------------------------------------------------- 1 | import spira.all as spira 2 | 3 | 4 | class Resistor(spira.PCell): 5 | 6 | width = spira.NumberParameter(default=spira.RDD.R1.MIN_WIDTH, doc='Width of the shunt resistance.') 7 | length = spira.NumberParameter(default=spira.RDD.R1.MIN_LENGTH, doc='Length of the shunt resistance.') 8 | 9 | def validate_parameters(self): 10 | if self.width > self.length: 11 | raise ValueError('`Width` cannot be larger than `length`.') 12 | return True 13 | 14 | def create_elements(self, elems): 15 | w, l = self.width, self.length 16 | # shape = spira.Shape(points=[[0,0], [l,0], [l,w], [0,w]]) 17 | # elems += spira.Polygon(shape=shape, layer=spira.RDD.PLAYER.R1.METAL) 18 | return elems 19 | 20 | 21 | if __name__ == '__main__': 22 | 23 | D = Resistor() 24 | D.gdsii_output() 25 | 26 | 27 | -------------------------------------------------------------------------------- /docs/_build/html/_static/parameters.rst: -------------------------------------------------------------------------------- 1 | Layout Parameters 2 | ================= 3 | 4 | 5 | 6 | .. Constraints 7 | .. ----------- 8 | 9 | 10 | 11 | .. Variables 12 | .. --------- 13 | 14 | .. Variables are primitive parameters such as intergers and strings. 15 | .. The following variables are supported and initialized as shown. 16 | 17 | .. * Integer 18 | .. * Float 19 | .. * String 20 | .. * Dictionary 21 | .. * List 22 | 23 | .. Structured 24 | .. ---------- 25 | 26 | .. Structured parameters are newly defined custom parameters introduced 27 | .. in the SPiRA framework. The purpose of this parameters is to structure 28 | .. data that can be manipulated using extended futures. 29 | 30 | .. ElementalList 31 | .. ~~~~~~~~~~~~~ 32 | 33 | .. List that contains all the layout elementals. 34 | 35 | .. PortList 36 | .. ~~~~~~~~ 37 | 38 | .. List that contains all the port elementals of a layout. 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /docs/_build/html/_sources/parameters.rst.txt: -------------------------------------------------------------------------------- 1 | Layout Parameters 2 | ================= 3 | 4 | 5 | 6 | .. Constraints 7 | .. ----------- 8 | 9 | 10 | 11 | .. Variables 12 | .. --------- 13 | 14 | .. Variables are primitive parameters such as intergers and strings. 15 | .. The following variables are supported and initialized as shown. 16 | 17 | .. * Integer 18 | .. * Float 19 | .. * String 20 | .. * Dictionary 21 | .. * List 22 | 23 | .. Structured 24 | .. ---------- 25 | 26 | .. Structured parameters are newly defined custom parameters introduced 27 | .. in the SPiRA framework. The purpose of this parameters is to structure 28 | .. data that can be manipulated using extended futures. 29 | 30 | .. ElementalList 31 | .. ~~~~~~~~~~~~~ 32 | 33 | .. List that contains all the layout elementals. 34 | 35 | .. PortList 36 | .. ~~~~~~~~ 37 | 38 | .. List that contains all the port elementals of a layout. 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /tests/_01_docs/_overview_routes_3.py: -------------------------------------------------------------------------------- 1 | import spira.all as spira 2 | 3 | 4 | class RouteExample(spira.Cell): 5 | 6 | layer = spira.LayerParameter(default=spira.RDD.PLAYER.M1.METAL, doc='Layer to be used when creating the route object.') 7 | 8 | @spira.cache() 9 | def get_io_ports(self): 10 | p1 = spira.Port(name='P1', midpoint=(0,0), orientation=180, process=self.layer.process) 11 | p2 = spira.Port(name='P2', midpoint=(20,10), orientation=0, process=self.layer.process) 12 | return [p1, p2] 13 | 14 | def create_elements(self, elems): 15 | ports = self.get_io_ports() 16 | elems += spira.RouteManhattan(ports=ports, layer=self.layer) 17 | return elems 18 | 19 | def create_ports(self, ports): 20 | ports += self.get_io_ports() 21 | return ports 22 | 23 | 24 | D = RouteExample() 25 | D.gdsii_view() 26 | D.gdsii_output(file_name='Route') 27 | 28 | -------------------------------------------------------------------------------- /tests/_01_docs/_overview_parameters.4.py: -------------------------------------------------------------------------------- 1 | import spira.all as spira 2 | 3 | 4 | class Layer(spira.ParameterInitializer): 5 | number = spira.Parameter(default=0, preprocess=spira.ProcessorInt()) 6 | int_number = spira.IntegerParameter(default=1, preprocess=spira.ProcessorInt()) 7 | 8 | 9 | # --- Test number 10 | 11 | # layer = Layer() 12 | # layer.number = 1 13 | # print(layer.number) 14 | 15 | # layer.number = 2.1 16 | # print(layer.number) 17 | 18 | # layer.number = 'Hi' 19 | # print(layer.number) 20 | 21 | # --- Test int_number 22 | 23 | layer = Layer() 24 | layer.int_number = 2 25 | print(layer.int_number) 26 | 27 | layer.int_number = 2.1 28 | print(layer.int_number) 29 | 30 | layer.int_number = "2" 31 | print(layer.int_number) 32 | 33 | # Still thows an error, but cannot be fixed right away, 34 | # since we will have to apply compound casting like this: int(float(int_number)) 35 | layer.int_number = "2.1" 36 | print(layer.int_number) 37 | 38 | -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=. 11 | set BUILDDIR=_build 12 | set SPHINXPROJ=Yuna 13 | 14 | if "%1" == "" goto help 15 | 16 | %SPHINXBUILD% >NUL 2>NUL 17 | if errorlevel 9009 ( 18 | echo. 19 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 20 | echo.installed, then set the SPHINXBUILD environment variable to point 21 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 22 | echo.may add the Sphinx directory to PATH. 23 | echo. 24 | echo.If you don't have Sphinx installed, grab it from 25 | echo.http://sphinx-doc.org/ 26 | exit /b 1 27 | ) 28 | 29 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% 30 | goto end 31 | 32 | :help 33 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% 34 | 35 | :end 36 | popd 37 | -------------------------------------------------------------------------------- /spira/yevon/constants.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from spira.yevon.geometry.coord import Coord 3 | 4 | 5 | DEG2RAD = np.pi / 180.0 6 | RAD2DEG = 180.0 / np.pi 7 | 8 | SCALE_UP = 1e+6 9 | SCALE_DOWN = 1e-6 10 | OFFSET = 0.3 11 | 12 | PATH_TYPE_NORMAL = 0 13 | PATH_TYPE_ROUNDED = 1 14 | PATH_TYPE_EXTENDED = 2 15 | 16 | PATH_TYPES = [ 17 | PATH_TYPE_NORMAL, 18 | PATH_TYPE_ROUNDED, 19 | PATH_TYPE_EXTENDED 20 | ] 21 | 22 | EDGE_TYPE_NORMAL = 0 23 | EDGE_TYPE_INSIDE = 1 24 | EDGE_TYPE_OUTSIDE = 2 25 | EDGE_TYPE_EUCLIDEAN = 3 26 | EDGE_TYPE_SQUARE = 4 27 | EDGE_TYPE_SIDE_EXTEND = 5 28 | 29 | EDGE_TYPES = [ 30 | EDGE_TYPE_NORMAL, 31 | EDGE_TYPE_INSIDE, 32 | EDGE_TYPE_OUTSIDE, 33 | EDGE_TYPE_EUCLIDEAN, 34 | EDGE_TYPE_SQUARE, 35 | EDGE_TYPE_SIDE_EXTEND 36 | ] 37 | 38 | CLIPPER_SCALE = 2**30 39 | 40 | NORTH = Coord(0.0, 1.0) 41 | SOUTH = Coord(0.0, -1.0) 42 | EAST = Coord(1.0, 0.0) 43 | WEST = Coord(-1.0, 0.0) 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /tests/_01_docs/_overview_routes_4.py: -------------------------------------------------------------------------------- 1 | import spira.all as spira 2 | 3 | 4 | class RouteExample(spira.Cell): 5 | 6 | layer = spira.LayerParameter(default=spira.RDD.PLAYER.M1.METAL, doc='Layer to be used when creating the route object.') 7 | 8 | p1 = spira.Parameter(fdef_name='create_p1') 9 | p2 = spira.Parameter(fdef_name='create_p2') 10 | 11 | def create_p1(self): 12 | return spira.Port(name='P1', midpoint=(0,0), orientation=180, process=self.layer.process) 13 | 14 | def create_p2(self): 15 | return spira.Port(name='P2', midpoint=(20,10), orientation=0, process=self.layer.process) 16 | 17 | def create_elements(self, elems): 18 | elems += spira.RouteManhattan(ports=[self.p1, self.p2], layer=self.layer) 19 | return elems 20 | 21 | def create_ports(self, ports): 22 | ports += self.p1 23 | ports += self.p2 24 | return ports 25 | 26 | 27 | D = RouteExample() 28 | D.gdsii_view() 29 | 30 | -------------------------------------------------------------------------------- /tutorials/basic/_9_stretch_0.py: -------------------------------------------------------------------------------- 1 | import spira.all as spira 2 | from spira.yevon.geometry import shapes 3 | from spira.yevon.geometry.coord import Coord 4 | from spira.yevon import process as pc 5 | from spira.yevon.process import get_rule_deck 6 | 7 | 8 | RDD = get_rule_deck() 9 | 10 | 11 | # ply = spira.Rectangle(p1=(0, 0), p2=(20, 5), layer=RDD.PLAYER.M2.METAL) 12 | 13 | 14 | # T = spira.Stretch(stretch_factor=(1,4)) 15 | # # ply = ply.transform(T) 16 | # # print(ply.transformation) 17 | 18 | 19 | # cell = spira.Cell(name='Stretcth') 20 | # cell += ply 21 | 22 | 23 | # # cell.gdsii_view() 24 | # cell.gdsii_output(file_name='no_stretch') 25 | 26 | 27 | T = spira.Stretch(stretch_factor=(1,4)) 28 | ply = spira.Rectangle(p1=(0, 0), p2=(20, 5), layer=RDD.PLAYER.M2.METAL, transformation=T) 29 | 30 | cell = spira.Cell(name='Stretcth', elements=[ply]) 31 | 32 | cell.gdsii_view() 33 | # cell.gdsii_output(file_name='no_stretch') 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /docs/_build/html/_static/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=. 11 | set BUILDDIR=_build 12 | set SPHINXPROJ=Yuna 13 | 14 | if "%1" == "" goto help 15 | 16 | %SPHINXBUILD% >NUL 2>NUL 17 | if errorlevel 9009 ( 18 | echo. 19 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 20 | echo.installed, then set the SPHINXBUILD environment variable to point 21 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 22 | echo.may add the Sphinx directory to PATH. 23 | echo. 24 | echo.If you don't have Sphinx installed, grab it from 25 | echo.http://sphinx-doc.org/ 26 | exit /b 1 27 | ) 28 | 29 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% 30 | goto end 31 | 32 | :help 33 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% 34 | 35 | :end 36 | popd 37 | -------------------------------------------------------------------------------- /tests/_01_docs/_overview_group_1.py: -------------------------------------------------------------------------------- 1 | import spira.all as spira 2 | 3 | 4 | class GroupExample(spira.Cell): 5 | 6 | def create_elements(self, elems): 7 | 8 | group = spira.Group() 9 | # group += spira.Rectangle(p1=(0,0), p2=(10,10), layer=spira.Layer(1)) 10 | # group += spira.Rectangle(p1=(0,15), p2=(10,30), layer=spira.Layer(1)) 11 | group += spira.Rectangle(p1=(0,0), p2=(10,10), layer=spira.RDD.PLAYER.M1.METAL) 12 | group += spira.Rectangle(p1=(0,15), p2=(10,30), layer=spira.RDD.PLAYER.M1.METAL) 13 | 14 | group.transform(spira.Rotation(-45)) 15 | 16 | elems += group 17 | 18 | bbox_shape = group.bbox_info.bounding_box(margin=1) 19 | # elems += spira.Polygon(shape=bbox_shape, layer=spira.Layer(2)) 20 | elems += spira.Polygon(shape=bbox_shape, layer=spira.RDD.PLAYER.M2.METAL) 21 | 22 | return elems 23 | 24 | 25 | D = GroupExample() 26 | D.gdsii_view() 27 | D.gdsii_output(file_name='bbox') 28 | 29 | -------------------------------------------------------------------------------- /spira/core/decorators.py: -------------------------------------------------------------------------------- 1 | import hashlib 2 | 3 | 4 | __all__ = ['cache', 'parameter'] 5 | 6 | 7 | def cache(): 8 | """ Caching decorator for caching the result of a 9 | function called on an object. If not in cache call 10 | the underlying function, then case the result """ 11 | def _cache(function): 12 | def __cache(*args, **kw): 13 | fstring = function.__name__.encode('utf-8') 14 | key = hashlib.sha1(fstring).hexdigest() 15 | obj = args[0] 16 | if not hasattr(obj, '__SPIRA_CACHE__'): 17 | obj.__SPIRA_CACHE__ = dict() 18 | 19 | if key in obj.__SPIRA_CACHE__: 20 | return obj.__SPIRA_CACHE__[key] 21 | 22 | result = function(*args, **kw) 23 | obj.__SPIRA_CACHE__[key] = result 24 | return result 25 | return __cache 26 | return _cache 27 | 28 | 29 | def parameter(object): 30 | """ Parameter decorator for getter and setter methods. """ 31 | pass 32 | 33 | 34 | -------------------------------------------------------------------------------- /spira/yevon/gdsii/generators.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | class NameGenerator(object): 4 | """ Generate a unique name based on a counter for every prefix. """ 5 | 6 | def __init__(self, prefix_attribute='__name_prefix__', process_name='DEFAULT', counter=0): 7 | self.prefix_attribute = prefix_attribute 8 | self.counter = counter 9 | self.process_name = process_name 10 | self.names_counters = {} 11 | 12 | def __call__(self, obj): 13 | if hasattr(obj, self.prefix_attribute): 14 | prefix = getattr(obj, self.prefix_attribute) 15 | else: 16 | prefix = '' 17 | prefix = '{}{}'.format(prefix, self.process_name) 18 | c = self.names_counters.get(prefix, self.counter) 19 | c += 1 20 | self.names_counters[prefix] = c 21 | c = self.names_counters[prefix] 22 | return '{}_{}'.format(prefix, c) 23 | 24 | def reset(self): 25 | self.prefix_attribute = '__name_prefix__' 26 | self.counter = 0 27 | self.names_counters = {} 28 | 29 | -------------------------------------------------------------------------------- /tutorials/basic/_12_nets.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | from spira.technologies.mit.process import RDD 4 | 5 | import spira.all as spira 6 | 7 | 8 | class NetBranchTest(spira.Circuit): 9 | """ """ 10 | 11 | @spira.cache() 12 | def get_ports(self): 13 | p1 = spira.Port(name='M6:P1', midpoint=(0,0), orientation=0) 14 | p2 = spira.Port(name='M6:P2', midpoint=(5,15), orientation=270) 15 | p3 = spira.Port(name='M6:P3', midpoint=(10,0), orientation=180) 16 | return [p1, p2, p3] 17 | 18 | def create_elements(self, elems): 19 | elems += spira.Rectangle(p1=(0, -0.5), p2=(10, 0.5), layer=RDD.PLAYER.M5.METAL) 20 | elems += spira.Rectangle(p1=(4.5, 0), p2=(5.5, 15), layer=RDD.PLAYER.M5.METAL) 21 | return elems 22 | 23 | def create_ports(self, ports): 24 | ports += self.get_ports() 25 | return ports 26 | 27 | 28 | if __name__ == '__main__': 29 | 30 | D = NetBranchTest() 31 | 32 | D = RDD.FILTERS.MASK(D) 33 | 34 | # D.gdsii_view() 35 | D.netlist_view() 36 | 37 | 38 | -------------------------------------------------------------------------------- /spira/yevon/gdsii/unit_grid.py: -------------------------------------------------------------------------------- 1 | from spira.core.parameters.initializer import ParameterInitializer 2 | from spira.core.parameters.descriptor import Parameter 3 | from spira.core.parameters.variables import NumberParameter 4 | from spira.yevon.process import get_rule_deck 5 | 6 | 7 | RDD = get_rule_deck() 8 | 9 | 10 | __all__ = ['UnitGridContainer'] 11 | 12 | 13 | class UnitGridContainer(ParameterInitializer): 14 | """ """ 15 | 16 | grids_per_unit = Parameter(fdef_name='create_grids_per_unit') 17 | units_per_grid = Parameter(fdef_name='create_units_per_grid') 18 | unit = NumberParameter(default=RDD.GDSII.UNIT) 19 | grid = NumberParameter(default=RDD.GDSII.GRID) 20 | 21 | def create_grids_per_unit(self): 22 | return self.unit / self.grid 23 | 24 | def create_units_per_grid(self): 25 | return self.grid / self.unit 26 | 27 | def validate_parameters(self): 28 | if self.grid > self.unit: 29 | raise ValueError('The grid should be smaller than the unit.') 30 | return True 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /spira/yevon/aspects/geometry.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from spira.yevon.aspects.base import __Aspects__ 3 | 4 | 5 | class __GeometryAspects__(__Aspects__): 6 | 7 | @property 8 | def xmax(self): 9 | return self.bbox[1][0] 10 | 11 | @property 12 | def ymax(self): 13 | return self.bbox[1][1] 14 | 15 | @property 16 | def xmin(self): 17 | return self.bbox[0][0] 18 | 19 | @property 20 | def ymin(self): 21 | return self.bbox[0][1] 22 | 23 | @property 24 | def dx(self): 25 | return (self.xmax - self.xmin) 26 | 27 | @property 28 | def dy(self): 29 | return (self.ymax - self.ymin) 30 | 31 | @property 32 | def xpos(self): 33 | return self.center[0] 34 | 35 | @property 36 | def ypos(self): 37 | return self.center[1] 38 | 39 | @property 40 | def center(self): 41 | return self.bbox_info.center 42 | 43 | @center.setter 44 | def center(self, destination): 45 | self.move(midpoint=self.center, destination=destination) 46 | 47 | -------------------------------------------------------------------------------- /tutorials/basic/_4_ports_1.py: -------------------------------------------------------------------------------- 1 | import spira.all as spira 2 | 3 | 4 | class Resistor(spira.PCell): 5 | 6 | width = spira.NumberParameter(default=spira.RDD.R1.MIN_WIDTH, doc='Width of the shunt resistance.') 7 | length = spira.NumberParameter(default=spira.RDD.R1.MIN_LENGTH, doc='Length of the shunt resistance.') 8 | 9 | def validate_parameters(self): 10 | if self.width > self.length: 11 | raise ValueError('`Width` cannot be larger than `length`.') 12 | return True 13 | 14 | def create_elements(self, elems): 15 | elems += spira.Box(alias='ply1', width=self.length, height=self.width, center=(0,0), layer=spira.RDD.PLAYER.R1.METAL) 16 | return elems 17 | 18 | def create_ports(self, ports): 19 | # Process symbol will automatically be added to the port name. 20 | ports += self.elements['ply1'].ports['E1_R1'].copy(name='P1') 21 | ports += self.elements['ply1'].ports['E3_R1'].copy(name='P2') 22 | return ports 23 | 24 | 25 | if __name__ == '__main__': 26 | 27 | D = Resistor() 28 | D.gdsii_output(name='Resistor') 29 | 30 | 31 | -------------------------------------------------------------------------------- /spira/validatex/drc/rules.py: -------------------------------------------------------------------------------- 1 | import spira.all as spira 2 | from spira.core.parameters.initializer import ParameterInitializer 3 | 4 | 5 | class __DesignRule__(ParameterInitializer): 6 | """ Base class for design rules. """ 7 | doc = param.StringParameter() 8 | name = param.StringParameter() 9 | violate = param.BoolParameter() 10 | 11 | 12 | class __SingleLayerDesignRule__(__DesignRule__): 13 | """ Rule applying to a single specific layer. """ 14 | # layer1 = param.LayerParameter() 15 | layer1 = param.PhysicalLayerParameter() 16 | 17 | 18 | class __DoubleLayerDesignRule__(__DesignRule__): 19 | """ Rule applying to two differnet layers. """ 20 | layer1 = param.LayerParameter() 21 | layer2 = param.LayerParameter() 22 | 23 | 24 | class Rule(ParameterInitializer): 25 | """ """ 26 | 27 | design_rule = param.DesignRuleParameter() 28 | error_layer = param.PurposeLayerParameter() 29 | 30 | def __repr__(self): 31 | return '[SPiRA: Rule] {}'.format(self.design_rule.__class__.__name__) 32 | 33 | def __str__(self): 34 | return self.__repr__() 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Ruben van Staden 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /tutorials/basic/_4_ports_0.py: -------------------------------------------------------------------------------- 1 | import spira.all as spira 2 | 3 | 4 | class Resistor(spira.PCell): 5 | 6 | width = spira.NumberParameter(default=spira.RDD.R1.MIN_WIDTH, doc='Width of the shunt resistance.') 7 | length = spira.NumberParameter(default=spira.RDD.R1.MIN_LENGTH, doc='Length of the shunt resistance.') 8 | 9 | def validate_parameters(self): 10 | if self.width > self.length: 11 | raise ValueError('`Width` cannot be larger than `length`.') 12 | return True 13 | 14 | def create_elements(self, elems): 15 | elems += spira.Box(width=self.length, height=self.width, center=(0,0), layer=spira.RDD.PLAYER.R1.METAL) 16 | return elems 17 | 18 | def create_ports(self, ports): 19 | w, l = self.width, self.length 20 | ports += spira.Port(name='P1_R1', midpoint=(-l/2,0), orientation=180, width=self.width) 21 | ports += spira.Port(name='P2', midpoint=(l/2,0), orientation=0, width=self.width, process=spira.RDD.PROCESS.R1) 22 | return ports 23 | 24 | 25 | if __name__ == '__main__': 26 | 27 | D = Resistor() 28 | D.gdsii_output(name='Resistor') 29 | 30 | 31 | -------------------------------------------------------------------------------- /spira/core/transforms/reflection.py: -------------------------------------------------------------------------------- 1 | import spira.all as spira 2 | from spira.core.transforms.generic import GenericTransform 3 | from spira.core.transformable import Transformable 4 | 5 | 6 | class Reflection(GenericTransform): 7 | 8 | def __init__(self, reflection=False, **kwargs): 9 | super().__init__(reflection=reflection, **kwargs) 10 | 11 | reflection = getattr(GenericTransform, 'reflection') 12 | 13 | def apply_to_coord(self, coord): 14 | coord = self.__reflect__(coord) 15 | coord = self.__translate__(coord) 16 | return coord 17 | 18 | def apply_to_array(self, coords): 19 | coords = self.__reflect_array__(coords) 20 | coords = self.__translate_array__(coords) 21 | return coords 22 | 23 | 24 | def shape_reflect(shape, reflection=False): 25 | return Reflection(reflection=reflection)(shape) 26 | 27 | 28 | class __ReflectionMixin__(object): 29 | 30 | def reflect(self, reflection=False): 31 | return self.transform(Reflection(reflection)) 32 | 33 | def reflect_copy(self, reflection=False): 34 | return self.transform_copy(Reflection(reflection)) 35 | 36 | 37 | Transformable.mixin(__ReflectionMixin__) 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /tests/8-parse/_0_input.py: -------------------------------------------------------------------------------- 1 | import os 2 | from spira.technologies.mit.process import RDD 3 | import spira.all as spira 4 | import spira.yevon.io.input_gdsii as io 5 | from copy import copy, deepcopy 6 | 7 | 8 | if __name__ == '__main__': 9 | 10 | # file_name = '/home/therealtyler/code/phd/spira/tests/8-parse/jj_mitll.gds' 11 | # file_name = '/home/therealtyler/code/phd/spira/tests/8-parse/mit/ruben/jtl_mitll_diff.gds' 12 | file_name = '/home/therealtyler/code/phd/spira/tests/8-parse/mit/lieze/jtl.gds' 13 | # file_name = '/home/therealtyler/code/phd/spira/tests/8-parse/mit/lieze/LSmitll_jtlt.gds' 14 | # file_name = '/home/therealtyler/code/phd/spira/tests/8-parse/mit/lieze/ptlrx_gs.gds' 15 | # file_name = '/home/therealtyler/code/phd/spira/tests/8-parse/mit/lieze/dfft.gds' 16 | # file_name = '/home/therealtyler/code/phd/spira/tests/8-parse/mit/lieze/circuit.gds' 17 | 18 | # input_gdsii = spira.InputGdsii(file_name=file_name) 19 | # input_gdsii.layer_map = RDD.GDSII.IMPORT_LAYER_MAP 20 | 21 | input_gdsii = spira.InputGdsii(file_name=file_name, layer_map=RDD.GDSII.IMPORT_LAYER_MAP) 22 | D = input_gdsii.parse() 23 | 24 | D.gdsii_view() 25 | # D.gdsii_output(file_name='input') 26 | 27 | -------------------------------------------------------------------------------- /spira/enginex/simulation.py: -------------------------------------------------------------------------------- 1 | # import spira.all as spira 2 | 3 | # from spira.core.parameters.variables import * 4 | # from spira.core.parameters.initializer import ParameterInitializer 5 | 6 | 7 | # class SimulationParameters(ParameterInitializer): 8 | 9 | # def __set_parameters__(self, obj, **kwargs): 10 | # pass 11 | 12 | # def __init__(self, **kwargs): 13 | # pass 14 | 15 | 16 | # class SimulationDefinition(): 17 | # simul_params = DictParameter(doc='A set of simulation parameters.') 18 | 19 | 20 | # class CellSimulationDefinition(SimulationDefinition): 21 | 22 | # def __init__(self, simul_params): 23 | # pass 24 | 25 | 26 | # class __SimulationGeometry__(SimulationParameters): 27 | 28 | # cell = spira.CellParameter() 29 | # geometry = spira.Parameter(fdef_name='create_geometry') 30 | 31 | # def __init__(self, **kwargs): 32 | # super().__init__(**kwargs) 33 | 34 | 35 | # class CellSimulationGeometry(__SimulationGeometry__): 36 | 37 | # def create_geometry(self): 38 | # vp = virtual_process_model() 39 | # return vp.geometry 40 | 41 | 42 | # def generate_simulation_geometry(cell, output=None): 43 | 44 | # simul_geom = CellSimulationGeometry() 45 | 46 | 47 | -------------------------------------------------------------------------------- /tutorials/basic/_5_routes_1.py: -------------------------------------------------------------------------------- 1 | import spira.all as spira 2 | 3 | 4 | class Resistor(spira.PCell): 5 | 6 | width = spira.NumberParameter(default=spira.RDD.R1.MIN_WIDTH, doc='Width of the shunt resistance.') 7 | length = spira.NumberParameter(default=spira.RDD.R1.MIN_LENGTH, doc='Length of the shunt resistance.') 8 | 9 | def validate_parameters(self): 10 | if self.width > self.length: 11 | raise ValueError('`Width` cannot be larger than `length`.') 12 | return True 13 | 14 | @spira.cache() 15 | def get_ports(self): 16 | p1 = spira.Port(name='P1', midpoint=(-self.length/2,0), orientation=180, width=self.width, process=spira.RDD.PROCESS.R1) 17 | p2 = spira.Port(name='P2', midpoint=(self.length/2,0), orientation=0, width=self.width, process=spira.RDD.PROCESS.R1) 18 | return [p1, p2] 19 | 20 | def create_elements(self, elems): 21 | p1, p2 = self.get_ports() 22 | elems += spira.RouteStraight(p1=p1, p2=p2, layer=spira.RDD.PLAYER.R1.METAL) 23 | return elems 24 | 25 | def create_ports(self, ports): 26 | ports += self.get_ports() 27 | return ports 28 | 29 | 30 | if __name__ == '__main__': 31 | 32 | D = Resistor() 33 | D.gdsii_output(file_name='Resistor') 34 | 35 | 36 | -------------------------------------------------------------------------------- /tutorials/basic/_14_nets.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | from spira.technologies.mit.process import RDD 4 | 5 | import spira.all as spira 6 | 7 | 8 | class NetBranchTest(spira.Circuit): 9 | """ """ 10 | 11 | @spira.cache() 12 | def get_ports(self): 13 | p1 = spira.Port(name='P1_M6', midpoint=(0,0), orientation=0) 14 | p2 = spira.Port(name='P2_M6', midpoint=(5,15), orientation=270) 15 | p3 = spira.Port(name='P3_M6', midpoint=(10,0), orientation=180) 16 | p4 = spira.Port(name='P4_M6', midpoint=(2,15), orientation=270) 17 | return [p1, p2, p3, p4] 18 | 19 | def create_elements(self, elems): 20 | 21 | elems += spira.Rectangle(p1=(0, -0.5), p2=(10, 0.5), layer=RDD.PLAYER.M5.METAL) 22 | elems += spira.Rectangle(p1=(4.5, 0), p2=(5.5, 15), layer=RDD.PLAYER.M5.METAL) 23 | elems += spira.Rectangle(p1=(1.5, 0), p2=(2.5, 15), layer=RDD.PLAYER.M5.METAL) 24 | elems += spira.Rectangle(p1=(5, 7.5), p2=(10, 8.5), layer=RDD.PLAYER.M5.METAL) 25 | 26 | return elems 27 | 28 | def create_ports(self, ports): 29 | ports += self.get_ports() 30 | return ports 31 | 32 | 33 | if __name__ == '__main__': 34 | 35 | print(RDD) 36 | 37 | D = NetBranchTest() 38 | 39 | D = RDD.FILTERS.MASK(D) 40 | 41 | D.gdsii_view() 42 | D.netlist_view() 43 | 44 | 45 | -------------------------------------------------------------------------------- /spira/validatex/drc/width.py: -------------------------------------------------------------------------------- 1 | import spira.all as spira 2 | from spira.lrc.rules import __SingleLayerDesignRule__ 3 | from copy import deepcopy 4 | 5 | 6 | RDD = spira.get_rule_deck() 7 | 8 | 9 | class Width(__SingleLayerDesignRule__): 10 | minimum = param.FloatParameter(allow_none=True, default=None) 11 | maximum = param.FloatParameter(allow_none=True, default=None) 12 | 13 | def __repr__(self): 14 | return "'{}' must have a width between: min={} max={}".format(self.layer1, self.minimum, self.maximum) 15 | 16 | def edge_to_minimum_width(self, e1): 17 | ports = spira.ElementList() 18 | for p in e1.edge_ports: 19 | p.length = 2*self.minimum 20 | ports += p 21 | return ports 22 | 23 | def apply(self, e1): 24 | adjusted_edges = self.edge_to_minimum_width(e1=e1) 25 | for e in adjusted_edges: 26 | clip = e.edge 27 | subj = e1.polygon 28 | overlap = clip & subj 29 | if overlap: 30 | clip_area = round(clip.ply_area) 31 | overlap_area = round(overlap.ply_area) 32 | pct = 100*(1 - (clip_area-overlap_area)/clip_area) 33 | if pct < 50: 34 | return False 35 | return True 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /spira/yevon/aspects/__init__.py: -------------------------------------------------------------------------------- 1 | from spira.yevon.gdsii.cell import Cell 2 | from spira.yevon.gdsii.sref import SRef 3 | from spira.yevon.gdsii.polygon import Polygon 4 | from spira.yevon.aspects.cell import CellAspects 5 | from spira.yevon.aspects.polygon import PolygonAspects, PolygonClipperAspects 6 | from spira.yevon.aspects.port import PortAspects, SRefPortAspects, PolygonPortAspects, CellPortAspects 7 | from spira.yevon.aspects.netlist import NetlistAspects 8 | from spira.core.transformable import Transformable 9 | from spira.yevon.aspects.output import OutputGdsiiAspect, OutputPlotlyNetlist 10 | from spira.yevon.aspects.shape import ShapeClipperAspects 11 | from spira.yevon.geometry.shapes import Shape 12 | 13 | 14 | def load_aspect(): 15 | """ Mix the aspects into their corresponding classes. """ 16 | 17 | Shape.mixin(ShapeClipperAspects) 18 | 19 | Polygon.mixin(PolygonAspects) 20 | Polygon.mixin(NetlistAspects) 21 | Polygon.mixin(PolygonPortAspects) 22 | Polygon.mixin(PolygonClipperAspects) 23 | Polygon.mixin(OutputPlotlyNetlist) 24 | 25 | SRef.mixin(SRefPortAspects) 26 | SRef.mixin(NetlistAspects) 27 | 28 | Cell.mixin(CellAspects) 29 | Cell.mixin(CellPortAspects) 30 | Cell.mixin(NetlistAspects) 31 | Cell.mixin(Transformable) 32 | Cell.mixin(OutputGdsiiAspect) 33 | Cell.mixin(OutputPlotlyNetlist) 34 | 35 | 36 | load_aspect() 37 | -------------------------------------------------------------------------------- /tutorials/reference/_0_rdd.py: -------------------------------------------------------------------------------- 1 | import spira.all as spira 2 | from spira.yevon.process import get_rule_deck 3 | 4 | 5 | RDD = get_rule_deck() 6 | 7 | 8 | print('\n[*] RDD.PLAYER.values:') 9 | for v in RDD.PLAYER.values: 10 | print(v) 11 | 12 | 13 | print('\n[*] RDD.PLAYER.keys:') 14 | for k in RDD.PLAYER.keys: 15 | print(k) 16 | 17 | 18 | print('\n[*] RDD.PLAYER.items:') 19 | for v, k in RDD.PLAYER.items: 20 | print(v, k) 21 | 22 | 23 | print(RDD.PLAYER['M1']) 24 | print(RDD.PLAYER['M1'].keys) 25 | print(RDD.PLAYER['M1'].values) 26 | print(RDD.PLAYER['M1']['METAL']) 27 | print(RDD.PLAYER['M1']['METAL'].process) 28 | print(RDD.PLAYER['M1']['METAL'].purpose) 29 | 30 | 31 | print('\nMetal players:') 32 | for m in RDD.get_physical_layers_by_purpose(purposes='METAL'): 33 | print(m) 34 | 35 | print('\nMetal players:') 36 | for m in RDD.get_physical_layers_by_process(processes='M1'): 37 | print(m) 38 | # for p in RDD.PLAYER['M1'].values: 39 | # if p.purpose.symbol == 'METAL': 40 | # print(p) 41 | 42 | # print('\nMetal players:') 43 | # for key in RDD.PLAYER.keys: 44 | # for value in RDD.PLAYER[key].values: 45 | # if value.purpose.symbol == 'METAL': 46 | # print(value) 47 | 48 | # print('\nProcess Layers:') 49 | # for p in RDD.PLAYER.M1.get_process_layers(): 50 | # print(p) 51 | 52 | 53 | # print('\nRDD.PLAYER.find_item_key') 54 | # print(RDD.PLAYER.find ) 55 | -------------------------------------------------------------------------------- /tutorials/basic/_13_nets.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | from spira.technologies.mit.process import RDD 4 | 5 | import spira.all as spira 6 | 7 | 8 | class NetBranchTest(spira.Circuit): 9 | """ """ 10 | 11 | @spira.cache() 12 | def get_ports(self): 13 | p1 = spira.Port(name='P1_M6', midpoint=(0,0), orientation=0) 14 | p2 = spira.Port(name='P2_M6', midpoint=(5,15), orientation=270) 15 | p3 = spira.Port(name='P3_M6', midpoint=(10,0), orientation=180) 16 | p4 = spira.Port(name='P4_M6', midpoint=(2,15), orientation=270) 17 | p5 = spira.Port(name='P5_M6', midpoint=(10,8), orientation=180) 18 | return [p1, p2, p3, p4, p5] 19 | 20 | def create_elements(self, elems): 21 | 22 | elems += spira.Rectangle(p1=(0, -0.5), p2=(10, 0.5), layer=RDD.PLAYER.M5.METAL) 23 | elems += spira.Rectangle(p1=(4.5, 0), p2=(5.5, 15), layer=RDD.PLAYER.M5.METAL) 24 | elems += spira.Rectangle(p1=(1.5, 0), p2=(2.5, 15), layer=RDD.PLAYER.M5.METAL) 25 | elems += spira.Rectangle(p1=(5, 7.5), p2=(10, 8.5), layer=RDD.PLAYER.M5.METAL) 26 | 27 | return elems 28 | 29 | def create_ports(self, ports): 30 | ports += self.get_ports() 31 | return ports 32 | 33 | 34 | if __name__ == '__main__': 35 | 36 | print(RDD) 37 | 38 | D = NetBranchTest() 39 | 40 | D = RDD.FILTERS.MASK(D) 41 | 42 | D.gdsii_view() 43 | D.netlist_view() 44 | 45 | 46 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | sys.path.insert(0, os.path.abspath('.')) 4 | 5 | # extensions = ['sphinx.ext.todo', 'sphinx.ext.viewcode', 'sphinx.ext.autodoc', 'sphinx.ext.napoleon'] 6 | extensions = ['sphinx.ext.todo', 'sphinx.ext.viewcode', 'sphinx.ext.autodoc'] 7 | 8 | import sphinx_rtd_theme 9 | from spira.settings import __version__, __release__ 10 | 11 | templates_path = ['_templates'] 12 | source_suffix = ['.rst', '.md'] 13 | 14 | master_doc = 'index' 15 | 16 | project = u'SPiRA' 17 | copyright = u'2019, Ruben van Staden' 18 | author = u'Ruben van Staden' 19 | 20 | version = __version__ 21 | release = __release__ 22 | 23 | language = None 24 | exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] 25 | pygments_style = 'sphinx' 26 | todo_include_todos = True 27 | html_theme = 'sphinx_rtd_theme' 28 | 29 | html_static_path = [''] 30 | 31 | html_sidebars = { 32 | '**': [ 33 | 'relations.html', 34 | 'searchbox.html', 35 | ] 36 | } 37 | 38 | htmlhelp_basename = 'spiradoc' 39 | 40 | latex_elements = {} 41 | 42 | latex_documents = [ 43 | (master_doc, 'spira.tex', u'SPiRA Documentation', 44 | u'Ruben van Staden', 'manual'), 45 | ] 46 | 47 | man_pages = [ 48 | (master_doc, 'spira', u'SPiRA Documentation', 49 | [author], 1) 50 | ] 51 | 52 | texinfo_documents = [ 53 | (master_doc, 'spira', u'SPiRA Documentation', 54 | author, 'spira', 'One line description of project.', 55 | 'Miscellaneous'), 56 | ] 57 | -------------------------------------------------------------------------------- /tests/_03_structures/_02_jtl.py: -------------------------------------------------------------------------------- 1 | import spira.all as spira 2 | 3 | from tests._03_structures._02_jj import Junction 4 | from spira.yevon.process import get_rule_deck 5 | 6 | 7 | RDD = get_rule_deck() 8 | 9 | 10 | class Jtl(spira.Circuit): 11 | """ """ 12 | 13 | def get_transforms(self): 14 | t1 = spira.Translation(translation=(0, 0)) 15 | t2 = spira.Translation(translation=(150, 0)) 16 | return [t1, t2] 17 | 18 | def create_routes(self, elems): 19 | elems += spira.Rectangle(p1=(4, -4), p2=(146, 4), layer=RDD.PLAYER.M2.METAL) 20 | elems += spira.Rectangle(p1=(-3, -4), p2=(-30, 4), layer=RDD.PLAYER.M2.METAL) 21 | return elems 22 | 23 | def create_elements(self, elems): 24 | t1, t2 = self.get_transforms() 25 | jj = Junction() 26 | elems += spira.SRef(alias='S1', reference=jj, transformation=t1) 27 | return elems 28 | 29 | 30 | # ---------------------------------------------------------------------------------------- 31 | 32 | 33 | if __name__ == '__main__': 34 | 35 | D = Jtl(pcell=False) 36 | 37 | D = D.expand_flat_copy() 38 | 39 | from spira.yevon.vmodel.virtual import virtual_connect 40 | v_model = virtual_connect(device=D) 41 | v_model.gdsii_output_virtual_connect() 42 | 43 | from spira.yevon.filters.boolean_filter import MetalConnectFilter 44 | D = MetalConnectFilter()(D) 45 | 46 | # D.gdsii_output() 47 | D.netlist_output() 48 | 49 | 50 | -------------------------------------------------------------------------------- /docs/_build/html/_static/conf.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | sys.path.insert(0, os.path.abspath('.')) 4 | 5 | # extensions = ['sphinx.ext.todo', 'sphinx.ext.viewcode', 'sphinx.ext.autodoc', 'sphinx.ext.napoleon'] 6 | extensions = ['sphinx.ext.todo', 'sphinx.ext.viewcode', 'sphinx.ext.autodoc'] 7 | 8 | import sphinx_rtd_theme 9 | from spira.settings import __version__, __release__ 10 | 11 | templates_path = ['_templates'] 12 | source_suffix = ['.rst', '.md'] 13 | 14 | master_doc = 'index' 15 | 16 | project = u'SPiRA' 17 | copyright = u'2019, Ruben van Staden' 18 | author = u'Ruben van Staden' 19 | 20 | version = __version__ 21 | release = __release__ 22 | 23 | language = None 24 | exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] 25 | pygments_style = 'sphinx' 26 | todo_include_todos = True 27 | html_theme = 'sphinx_rtd_theme' 28 | 29 | html_static_path = [''] 30 | 31 | html_sidebars = { 32 | '**': [ 33 | 'relations.html', 34 | 'searchbox.html', 35 | ] 36 | } 37 | 38 | htmlhelp_basename = 'spiradoc' 39 | 40 | latex_elements = {} 41 | 42 | latex_documents = [ 43 | (master_doc, 'spira.tex', u'SPiRA Documentation', 44 | u'Ruben van Staden', 'manual'), 45 | ] 46 | 47 | man_pages = [ 48 | (master_doc, 'spira', u'SPiRA Documentation', 49 | [author], 1) 50 | ] 51 | 52 | texinfo_documents = [ 53 | (master_doc, 'spira', u'SPiRA Documentation', 54 | author, 'spira', 'One line description of project.', 55 | 'Miscellaneous'), 56 | ] 57 | -------------------------------------------------------------------------------- /tutorials/reference/_5_boolean.py: -------------------------------------------------------------------------------- 1 | import spira.all as spira 2 | from spira.yevon.geometry import shapes 3 | 4 | 5 | # Boolean operations on the shapes 6 | # -------------------------------- 7 | 8 | s1 = shapes.CircleShape(box_size=(2,2)) 9 | s2 = shapes.CircleShape(box_size=(2,2), center=(1,0)) 10 | 11 | p1 = spira.Polygon(shape=s1, layer=spira.Layer(1)) 12 | p2 = spira.Polygon(shape=s2, layer=spira.Layer(1)) 13 | 14 | elems = [p1, p2] 15 | for bs in s1 & s2: 16 | elems.append(spira.Polygon(shape=bs, layer=spira.Layer(2))) 17 | for bs in s1 - s2: 18 | elems.append(spira.Polygon(shape=bs, layer=spira.Layer(3))) 19 | for bs in s2 - s1: 20 | elems.append(spira.Polygon(shape=bs, layer=spira.Layer(4))) 21 | for bs in s1 | s2: 22 | elems.append(spira.Polygon(shape=bs, layer=spira.Layer(5))) 23 | 24 | 25 | # Boolean operations on the polygons 26 | # ---------------------------------- 27 | 28 | b_and = p1 & p2 29 | for b in b_and: 30 | b.layer = spira.Layer(2) 31 | 32 | b_sub1 = p1 - p2 33 | for b in b_sub1: 34 | b.layer = spira.Layer(3) 35 | 36 | b_sub2 = p2 - p1 37 | for b in b_sub2: 38 | b.layer = spira.Layer(4) 39 | 40 | b_or = p1 | p2 41 | for b in b_or: 42 | b.layer = spira.Layer(5) 43 | 44 | 45 | # ---------------------------------- 46 | 47 | 48 | D = spira.Cell(name='Boolean') 49 | 50 | c1 = spira.Cell(elements=elems) 51 | c2 = spira.Cell(elements=b_and + b_sub1 + b_sub2 + b_or) 52 | 53 | D += spira.SRef(c1, midpoint=(0,0)) 54 | D += spira.SRef(c2, midpoint=(10,0)) 55 | 56 | D.gdsii_output() 57 | 58 | 59 | -------------------------------------------------------------------------------- /tutorials/reference/_0-ports.py: -------------------------------------------------------------------------------- 1 | import spira.all as spira 2 | from spira.yevon.geometry import shapes 3 | from spira.yevon import constants 4 | from spira.yevon.geometry.vector import * 5 | 6 | 7 | class PortBasics(spira.Cell): 8 | 9 | def create_elementals(self, elems): 10 | shape = shapes.RectangleShape(p1=(-2.5, -2.5), p2=(2.5, 2.5)) 11 | elems += spira.Polygon(shape=shape, layer=spira.Layer(number=1), enable_edges=False) 12 | return elems 13 | 14 | def create_ports(self, ports): 15 | ports += spira.Port(midpoint=(2.5, 0), orientation=0, width=5) 16 | return ports 17 | 18 | 19 | class PortVectorBasics(spira.Cell): 20 | 21 | def create_ports(self, ports): 22 | 23 | p1 = spira.Port(midpoint=(2.5, 0), orientation=0, width=5) 24 | p2 = spira.Port(midpoint=(0, 2.5), orientation=90, width=5) 25 | 26 | T = vector_match_transform(p2, p1) 27 | print(T) 28 | print(type(T)) 29 | p2.transform(T) 30 | 31 | ports += p1 32 | ports += p2 33 | 34 | return ports 35 | 36 | 37 | class PortConstants(spira.Cell): 38 | 39 | def create_ports(self, ports): 40 | ports += spira.Port(midpoint=constants.NORTH*10.0, orientation=90, width=5) 41 | ports += spira.Port(midpoint=constants.SOUTH*10.0, orientation=270, width=5) 42 | return ports 43 | 44 | 45 | if __name__ == '__main__': 46 | 47 | # D = PortBasics() 48 | D = PortVectorBasics() 49 | # D = PortConstants() 50 | D.gdsii_output() 51 | 52 | 53 | -------------------------------------------------------------------------------- /spira/validatex/drc/density.py: -------------------------------------------------------------------------------- 1 | import spira.all as spira 2 | 3 | 4 | RDD = spira.get_rule_deck() 5 | 6 | 7 | class Density(__DoubleLayerDesignRule__): 8 | minimum = param.IntegerParameter() 9 | 10 | # TODO: Detect holes in die polygon 11 | 12 | def __repr__(self): 13 | return 'Rule density: min={}'.format(self.minimum) 14 | 15 | def get_layer_area(self, elems): 16 | area = 0.0 17 | for e in elems: 18 | area += e.ply_area 19 | return area 20 | 21 | def apply(self, elems): 22 | 23 | pos_elems = spira.ElementList() 24 | neg_elems = spira.ElementList() 25 | 26 | for C in elems.dependencies(): 27 | if C.layer.number == self.layer1.number: 28 | pos_elems = C.elements 29 | elif C.layer.number == self.layer2.number: 30 | neg_elems = C.elements 31 | 32 | fails = False 33 | 34 | Ap = self.get_layer_area(pos_elems) 35 | An = self.get_layer_area(neg_elems) 36 | 37 | if (Ap > 0) and (An > 0): 38 | presentage = 100 - (An/Ap)*100 39 | 40 | if presentage < self.minimum: 41 | fails = True 42 | message = '[DRC: Density ({})]: (layer1 {}, layer2 {}, extracted_value {}%, rule_value {}%)'.format('fail', self.layer1.number, self.layer2.number, int(round(presentage)), self.min) 43 | raise ValueError(message) 44 | else: 45 | fails = False 46 | 47 | return fails 48 | 49 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | 4 | from pprint import pprint 5 | from setuptools import setup, find_packages 6 | from spira.settings import __version__, __release__ 7 | 8 | sys.dont_write_bytecode = True 9 | 10 | packages=find_packages(exclude=["*.tests", "*.tests.*", "tests.*", "tests"]), 11 | 12 | setup( 13 | name="spira", 14 | version='{}-{}'.format(__version__, __release__), 15 | description="Superconducting Circuit Modeling and Verification", 16 | author="Ruben van Staden", 17 | author_email="rubenvanstaden@gmail.com", 18 | setup_requires=['setuptools-markdown'], 19 | license="MIT", 20 | url="https://github.com/rubenvanstaden/spira", 21 | 22 | install_requires=[ 23 | # # Developer packages 24 | # 'halo', 25 | # 'pytest', 26 | 27 | # Visual packages 28 | 'sphinxcontrib-napoleon', 29 | 'matplotlib', 30 | 'plotly', 31 | 'pyqt5', 32 | 'lxml', 33 | 34 | # Core packages 35 | 'termcolor', 36 | 'colorama', 37 | 'pandoc', 38 | 'scipy', 39 | 'numpy', 40 | 'gdspy', 41 | 'shapely', 42 | 'pyclipper', 43 | 'networkx', 44 | 'pygmsh', 45 | 'meshio', 46 | ], 47 | 48 | packages=find_packages(exclude=["*.tests", "*.tests.*", "tests.*", "tests"]), 49 | # packages=['spira', 50 | # 'spira.core', 51 | # 'spira', 52 | # 'spira.validatex', 53 | # 'spira.inductex', 54 | # 'spira.josim', 55 | # ], 56 | 57 | # package_dir={'spira': 'spira'} 58 | ) 59 | -------------------------------------------------------------------------------- /spira/yevon/vmodel/boundary.py: -------------------------------------------------------------------------------- 1 | from spira.yevon.gdsii.cell import Cell 2 | from spira.yevon.aspects.base import __Aspects__ 3 | from spira.yevon.gdsii.elem_list import ElementListParameter, ElementList 4 | from spira.yevon.gdsii.polygon import Polygon 5 | from spira.yevon.process import get_rule_deck 6 | 7 | 8 | RDD = get_rule_deck() 9 | 10 | 11 | def reference_metal_blocks(S): 12 | from copy import deepcopy 13 | elems = ElementList() 14 | for layer in RDD.get_physical_layers_by_purpose(purposes=['METAL', 'GND']): 15 | layer = deepcopy(layer) 16 | if S.reference.is_layer_in_cell(layer): 17 | bbox_shape = S.bbox_info.bounding_box() 18 | layer.purpose = RDD.PURPOSE.BOUNDARY_BOX 19 | elems += Polygon(shape=bbox_shape, layer=layer) 20 | return elems 21 | 22 | 23 | class ReferenceBlocks(__Aspects__): 24 | """ Create a boundary block around the cell 25 | references in the current cell structure. """ 26 | 27 | block_elements = ElementListParameter() 28 | 29 | def create_block_elements(self, elems): 30 | for e in self.elements.sref: 31 | for layer in RDD.get_physical_layers_by_purpose(purposes=['METAL', 'GND']): 32 | if e.reference.is_layer_in_cell(layer): 33 | bbox_shape = e.bbox_info.bounding_box() 34 | elems += Polygon(shape=bbox_shape, layer=layer) 35 | return elems 36 | 37 | def write_gdsii_blocks(self, **kwargs): 38 | D = Cell(name=self.name + '_BLOCKS', elements=self.block_elements) 39 | D.gdsii_output() 40 | 41 | 42 | Cell.mixin(ReferenceBlocks) 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /tests/_03_structures/_03_jtl_d.py: -------------------------------------------------------------------------------- 1 | import spira.all as spira 2 | 3 | from tests._03_structures._02_jj import Junction 4 | from spira.yevon.process import get_rule_deck 5 | 6 | 7 | RDD = get_rule_deck() 8 | 9 | 10 | class Jtl(spira.Circuit): 11 | """ """ 12 | 13 | def get_transforms(self): 14 | t1 = spira.Translation(translation=(0, 0)) 15 | t2 = spira.Translation(translation=(150, 0)) 16 | return [t1, t2] 17 | 18 | def create_routes(self, elems): 19 | elems += spira.Rectangle(p1=(4, -4), p2=(146, 4), layer=RDD.PLAYER.M2.METAL) 20 | elems += spira.Rectangle(p1=(-3, -4), p2=(-30, 4), layer=RDD.PLAYER.M2.METAL) 21 | elems += spira.Rectangle(p1=(153, -4), p2=(180, 4), layer=RDD.PLAYER.M2.METAL) 22 | return elems 23 | 24 | def create_elements(self, elems): 25 | t1, t2 = self.get_transforms() 26 | jj = Junction() 27 | elems += spira.SRef(alias='S1', reference=jj, transformation=t1) 28 | elems += spira.SRef(alias='S2', reference=jj, transformation=t2) 29 | return elems 30 | 31 | 32 | # ---------------------------------------------------------------------------------------- 33 | 34 | 35 | if __name__ == '__main__': 36 | 37 | C = Jtl(pcell=True) 38 | 39 | D = C.expand_flat_copy() 40 | 41 | from spira.yevon.vmodel.virtual import virtual_connect 42 | v_model = virtual_connect(device=D) 43 | v_model.gdsii_output_virtual_connect() 44 | 45 | from spira.yevon.filters.boolean_filter import MetalConnectFilter 46 | D = MetalConnectFilter()(D) 47 | 48 | # D.gdsii_output() 49 | D.netlist_output() 50 | # C.netlist_output() 51 | 52 | -------------------------------------------------------------------------------- /spira/yevon/io/input.py: -------------------------------------------------------------------------------- 1 | from spira.core.parameters.variables import * 2 | from spira.core.parameters.descriptor import Parameter 3 | from spira.core.parameters.initializer import ParameterInitializer 4 | from spira.yevon.process.gdsii_layer import __Layer__, Layer 5 | from spira.yevon.process import get_rule_deck 6 | 7 | 8 | RDD = get_rule_deck() 9 | 10 | 11 | class __InputBasic__(ParameterInitializer): 12 | """ """ 13 | 14 | file_name = StringParameter() 15 | cell_name = StringParameter(allow_none=True, default=None) 16 | 17 | def __init__(self, file_name, **kwargs): 18 | super().__init__(file_name=file_name, **kwargs) 19 | 20 | def read(self): 21 | raise NotImplementedError('Must provide implementation in subclass.') 22 | 23 | def parse(self, item): 24 | raise NotImplementedError('Must provide implementation in subclass.') 25 | 26 | 27 | class InputBasic(__InputBasic__): 28 | """ """ 29 | 30 | prefix = StringParameter(default='') 31 | flatten = BoolParameter() 32 | layer_map = Parameter(default=RDD.GDSII.IMPORT_LAYER_MAP) 33 | 34 | def __init__(self, file_name, **kwargs): 35 | super().__init__(file_name=file_name, **kwargs) 36 | self.library = None 37 | 38 | def read(self): 39 | self.library = Library('Imported') 40 | for cell in self.parse.dependencies(): 41 | self.library += cell 42 | return self.library 43 | 44 | def map_layer(self, layer): 45 | L = self.layer_map.get(layer, None) 46 | if isinstance(L, __Layer__): 47 | return L 48 | elif L is None: 49 | return L 50 | else: 51 | return Layer(L) 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /tests/_03_structures/_04_jtl_b.py: -------------------------------------------------------------------------------- 1 | import spira.all as spira 2 | 3 | from tests._03_structures._02_jj import Junction 4 | from spira.yevon.process import get_rule_deck 5 | 6 | 7 | RDD = get_rule_deck() 8 | 9 | 10 | class JtlBias(spira.Circuit): 11 | 12 | def get_transforms(self): 13 | t1 = spira.Translation(translation=(0, 0)) 14 | t2 = spira.Translation(translation=(150, 0)) 15 | return [t1, t2] 16 | 17 | def create_routes(self, elems): 18 | elems += spira.Rectangle(p1=(4, -4), p2=(146, 4), layer=RDD.PLAYER.M2.METAL) 19 | elems += spira.Rectangle(p1=(-3, -4), p2=(-30, 4), layer=RDD.PLAYER.M2.METAL) 20 | elems += spira.Rectangle(p1=(153, -4), p2=(180, 4), layer=RDD.PLAYER.M2.METAL) 21 | elems += spira.Rectangle(p1=(60, 0), p2=(80, 50), layer=RDD.PLAYER.M2.METAL) 22 | return elems 23 | 24 | def create_elements(self, elems): 25 | t1, t2 = self.get_transforms() 26 | 27 | jj = Junction() 28 | 29 | elems += spira.SRef(alias='S1', reference=jj, transformation=t1) 30 | elems += spira.SRef(alias='S2', reference=jj, transformation=t2) 31 | 32 | return elems 33 | 34 | 35 | # ------------------------------------------------------------------------------------ 36 | 37 | 38 | if __name__ == '__main__': 39 | 40 | D = JtlBias(pcell=True) 41 | 42 | D = D.expand_flat_copy() 43 | 44 | from spira.yevon.vmodel.virtual import virtual_connect 45 | v_model = virtual_connect(device=D) 46 | v_model.gdsii_output_virtual_connect() 47 | 48 | from spira.yevon.filters.boolean_filter import MetalConnectFilter 49 | D = MetalConnectFilter()(D) 50 | 51 | # D.gdsii_output() 52 | D.netlist_output() 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /spira/core/transformable.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from copy import deepcopy 3 | from numpy.linalg import norm 4 | from spira.core.mixin import MixinBowl 5 | from spira.core.transformation import Transform 6 | from spira.core.transformation import TransformationParameter 7 | 8 | 9 | class __Transformable__(MixinBowl): 10 | """ Transformable base class. """ 11 | 12 | def transform(self, transformation): 13 | return self 14 | 15 | def transform_copy(self, transformation): 16 | T = deepcopy(self) 17 | T.transform(transformation) 18 | return T 19 | 20 | def reverse_transform(self, transformation): 21 | return self.transform(-transformation) 22 | 23 | def reverse_transform_copy(self, transformation): 24 | T = deepcopy(self) 25 | T.reverse_transform(transformation) 26 | return T 27 | 28 | 29 | class Transformable(__Transformable__): 30 | """ Object that can be transformed. """ 31 | 32 | __transform_type__ = Transform 33 | 34 | transformation = TransformationParameter() 35 | 36 | def __init__(self, transformation=None, **kwargs): 37 | if (not 'transformation' in kwargs) or (transformation != None): 38 | kwargs['transformation'] = transformation 39 | super().__init__(**kwargs) 40 | 41 | def transform(self, transformation=None): 42 | if issubclass(type(transformation), self.__transform_type__): 43 | self.transformation = self.transformation + transformation 44 | # self.transformation += transformation 45 | elif transformation is None: 46 | return 47 | else: 48 | raise TypeError("Wrong type " + str(type(transformation)) + " for transformation in Transformable") 49 | return self 50 | 51 | 52 | -------------------------------------------------------------------------------- /tutorials/reference/_1-shapes.py: -------------------------------------------------------------------------------- 1 | import spira.all as spira 2 | from spira.yevon.geometry.shapes.basic import * 3 | from spira.yevon.geometry.shapes.advance import * 4 | 5 | 6 | if __name__ == '__main__': 7 | 8 | circle_shape = CircleShape() 9 | hexagon_shape = ConvexShape() 10 | arrow_shape = ArrowShape() 11 | rect_shape = RectangleShape() 12 | box_shape = BoxShape() 13 | basic_tri_shape = BasicTriangle() 14 | tri_shape = TriangleShape() 15 | 16 | cell = spira.Cell(name='Basic Shapes') 17 | 18 | # circle = spira.Polygon(shape=circle_shape, layer=spira.Layer(number=13)) 19 | # circle.center = (0,0) 20 | # cell += circle 21 | 22 | # hexagon = spira.Polygon(shape=hexagon_shape, layer=spira.Layer(number=14)) 23 | # hexagon.center = (5,0) 24 | # cell += hexagon 25 | 26 | # rect = spira.Polygon(shape=rect_shape, layer=spira.Layer(number=16)) 27 | # rect.center = (15,0) 28 | # cell += rect 29 | 30 | # box = spira.Polygon(shape=box_shape, layer=spira.Layer(number=17)) 31 | # box.center = (20,0) 32 | # cell += box 33 | 34 | # FIXME 35 | # basic = spira.Polygon(shape=basic_tri_shape, layer=spira.Layer(number=18)) 36 | # basic.center = (25,0) 37 | # cell += basic 38 | 39 | # FIXME 40 | # tri = spira.Polygon(shape=tri_shape, layer=spira.Layer(number=19)) 41 | # tri.center = (30,0) 42 | # cell += tri 43 | 44 | # FIXME 45 | # arrow = spira.Polygon(shape=arrow_shape, layer=spira.Layer(number=15)) 46 | # arrow.center = (10,0) 47 | # cell += arrow 48 | 49 | # NOTE: Advanced shapes 50 | ytron_shape = YtronShape() 51 | ytron = spira.Polygon(shape=ytron_shape, layer=spira.Layer(number=20)) 52 | ytron.center = (35,0) 53 | cell += ytron 54 | 55 | cell.gdsii_output() 56 | 57 | -------------------------------------------------------------------------------- /tests/_04_edges/_3_erc_h.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import spira.all as spira 3 | 4 | from spira.yevon.vmodel.virtual import virtual_connect 5 | from spira.yevon.filters.boolean_filter import MetalConnectFilter 6 | from spira.technologies.mit.process import RDD 7 | 8 | 9 | el = spira.ElementList() 10 | 11 | # Main Cell 12 | c1 = spira.Cell(name='Ply1') 13 | c1 += spira.Rectangle(p1=(0, 0), p2=(4, 10), layer=RDD.PLAYER.M5.METAL) 14 | el += spira.SRef(reference=c1) 15 | 16 | # el += spira.Rectangle(p1=(3, 4), p2=(8, 6), layer=RDD.PLAYER.M5.METAL) 17 | 18 | # el += spira.Rectangle(p1=(8, 4), p2=(-4, 6), layer=RDD.PLAYER.M5.METAL) 19 | 20 | # el += spira.Rectangle(p1=(-4, 4), p2=(1, 6), layer=RDD.PLAYER.M5.METAL) 21 | # el += spira.Rectangle(p1=(3, 4), p2=(8, 6), layer=RDD.PLAYER.M5.METAL) 22 | 23 | # el += spira.Rectangle(p1=(-4, 8), p2=(8, 12), layer=RDD.PLAYER.M5.METAL) 24 | 25 | # el += spira.Rectangle(p1=(1, 9), p2=(3, 14), layer=RDD.PLAYER.M5.METAL) 26 | 27 | # el += spira.Rectangle(p1=(-1, 9), p2=(5, 14), layer=RDD.PLAYER.M5.METAL) 28 | 29 | # NOTE: Edge cases. 30 | el += spira.Rectangle(p1=(0, 10), p2=(4, 14), layer=RDD.PLAYER.M5.METAL) 31 | # el += spira.Rectangle(p1=(-4, 4), p2=(0, 6), layer=RDD.PLAYER.M5.METAL) 32 | # el += spira.Rectangle(p1=(4, 4), p2=(7, 6), layer=RDD.PLAYER.M5.METAL) 33 | # el += spira.Rectangle(p1=(4, 9), p2=(7, 11), layer=RDD.PLAYER.M5.METAL) 34 | # el += spira.Rectangle(p1=(3, 10), p2=(7, 11), layer=RDD.PLAYER.M5.METAL) 35 | 36 | device = spira.Cell(name='Device', elements=el) 37 | device = device.expand_flat_copy() 38 | 39 | v_model = virtual_connect(device=device) 40 | v_model.gdsii_output_virtual_connect() 41 | 42 | F = MetalConnectFilter() 43 | D = F(device) 44 | 45 | D = spira.Circuit(name='TestElectricalConnections', elements=D.elements) 46 | # D.gdsii_output() 47 | D.netlist_output() 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /spira/validatex/lvs/device_recognition.py: -------------------------------------------------------------------------------- 1 | import spira.all as spira 2 | from copy import deepcopy 3 | from spira.yevon.process import get_rule_deck 4 | 5 | 6 | RDD = get_rule_deck() 7 | 8 | 9 | __all__ = ['device_detector', 'circuit_detector'] 10 | 11 | 12 | def device_detector(cell): 13 | from spira.netex.devices import Device 14 | from spira.netex.contact import DeviceTemplate 15 | 16 | c2dmap = {} 17 | for C in cell.dependencies(): 18 | cc = deepcopy(C) 19 | L = DeviceTemplate(name=C.name, cell=cc, level=1) 20 | if L.__type__ is not None: 21 | for key in RDD.DEVICES.keys: 22 | if L.__type__ == key: 23 | D = RDD.DEVICES[key].PCELL( 24 | metals=L.metals, 25 | contacts=L.contacts, 26 | ports=L.ports 27 | ) 28 | c2dmap.update({C: D}) 29 | for key in RDD.VIAS.keys: 30 | if L.__type__ == key: 31 | D = RDD.VIAS[key].DEFAULT( 32 | metals=L.metals, 33 | contacts=L.contacts, 34 | ports=L.ports 35 | ) 36 | c2dmap.update({C: D}) 37 | else: 38 | c2dmap.update({C: C}) 39 | 40 | return c2dmap[cell] 41 | 42 | 43 | def circuit_detector(cell): 44 | from spira.netex.devices import Device 45 | from spira.netex.circuits import Circuit 46 | 47 | c2dmap = {} 48 | for C in cell.dependencies(): 49 | if not issubclass(type(C), Device): 50 | if ('Metal' not in C.name) and ('Native' not in C.name): 51 | D = Circuit(cell=C, level=2) 52 | c2dmap.update({C: D}) 53 | else: 54 | c2dmap.update({C: C}) 55 | 56 | return c2dmap[cell] 57 | -------------------------------------------------------------------------------- /tutorials/basic/_6_hierarchy.py: -------------------------------------------------------------------------------- 1 | import spira.all as spira 2 | 3 | 4 | class Resistor(spira.PCell): 5 | 6 | width = spira.NumberParameter(default=spira.RDD.R1.MIN_WIDTH, doc='Width of the shunt resistance.') 7 | length = spira.NumberParameter(default=spira.RDD.R1.MIN_LENGTH, doc='Length of the shunt resistance.') 8 | 9 | p1 = spira.Parameter(fdef_name='create_p1') 10 | p2 = spira.Parameter(fdef_name='create_p2') 11 | 12 | def validate_parameters(self): 13 | if self.width > self.length: 14 | raise ValueError('`Width` cannot be larger than `length`.') 15 | return True 16 | 17 | def create_p1(self): 18 | return spira.Port(name='P1', midpoint=(-self.length/2,0), orientation=180, width=self.width, process=spira.RDD.PROCESS.R1) 19 | 20 | def create_p2(self): 21 | return spira.Port(name='P2', midpoint=(self.length/2,2), orientation=0, width=self.width, process=spira.RDD.PROCESS.R1) 22 | 23 | def create_elements(self, elems): 24 | elems += spira.RouteManhattan(ports=[self.p1, self.p2], layer=spira.RDD.PLAYER.R1.METAL) 25 | return elems 26 | 27 | def create_ports(self, ports): 28 | ports += [self.p1, self.p2] 29 | return ports 30 | 31 | 32 | class ResistorExtended(Resistor): 33 | 34 | p3 = spira.Parameter(fdef_name='create_p3') 35 | 36 | def create_p3(self): 37 | return spira.Port(name='P3', midpoint=(self.length,0), orientation=90, width=self.width, process=spira.RDD.PROCESS.R1) 38 | 39 | def create_elements(self, elems): 40 | elems = super().create_elements(elems) 41 | elems += spira.RouteManhattan(ports=[self.p2, self.p3], corners='round', layer=spira.RDD.PLAYER.R1.METAL) 42 | return elems 43 | 44 | 45 | if __name__ == '__main__': 46 | 47 | D = Resistor() 48 | # D = ResistorExtended() 49 | D.gdsii_output(file_name='Resistor') 50 | 51 | 52 | -------------------------------------------------------------------------------- /tutorials/basic/_5_routes_0.py: -------------------------------------------------------------------------------- 1 | import spira.all as spira 2 | 3 | 4 | class Resistor(spira.PCell): 5 | 6 | width = spira.NumberParameter(default=spira.RDD.R1.MIN_WIDTH, doc='Width of the shunt resistance.') 7 | length = spira.NumberParameter(default=spira.RDD.R1.MIN_LENGTH, doc='Length of the shunt resistance.') 8 | 9 | p1 = spira.Parameter(fdef_name='create_p1') 10 | p2 = spira.Parameter(fdef_name='create_p2') 11 | 12 | def validate_parameters(self): 13 | if self.width > self.length: 14 | raise ValueError('`Width` cannot be larger than `length`.') 15 | return True 16 | 17 | def create_p1(self): 18 | return spira.Port(name='P1', midpoint=(-self.length/2,0), orientation=180, width=self.width, process=spira.RDD.PROCESS.R1) 19 | 20 | def create_p2(self): 21 | return spira.Port(name='P2', midpoint=(self.length/2,0), orientation=0, width=self.width, process=spira.RDD.PROCESS.R1) 22 | 23 | def create_elements(self, elems): 24 | elems += spira.RouteStraight(p1=self.p1, p2=self.p2, layer=spira.RDD.PLAYER.R1.METAL) 25 | return elems 26 | 27 | def create_ports(self, ports): 28 | ports += [self.p1, self.p2] 29 | return ports 30 | 31 | 32 | if __name__ == '__main__': 33 | 34 | D = Resistor() 35 | D.gdsii_output(name='Resistor') 36 | 37 | 38 | 39 | # class RouteExample2(spira.Cell): 40 | 41 | # @spira.cache() 42 | # def get_ports(self): 43 | # print('get ports') 44 | # p1 = spira.Port(name='P1', midpoint=(0,0), orientation=180) 45 | # p2 = spira.Port(name='P2', midpoint=(20,10), orientation=0) 46 | # return [p1, p2] 47 | 48 | # def create_elements(self, elems): 49 | # elems += spira.RouteManhattan(ports=self.get_ports(), layer=spira.Layer(1)) 50 | # return elems 51 | 52 | # def create_ports(self, ports): 53 | # ports += self.get_ports() 54 | # return ports 55 | -------------------------------------------------------------------------------- /spira/yevon/aspects/output.py: -------------------------------------------------------------------------------- 1 | from spira.yevon.aspects.base import __Aspects__ 2 | from spira.log import SPIRA_LOG as LOG 3 | from spira.yevon import filters 4 | from copy import deepcopy 5 | from spira.yevon.gdsii.library import Library 6 | from spira.yevon.io.output_gdsii import OutputGdsii 7 | from spira.yevon.process import get_rule_deck 8 | 9 | 10 | RDD = get_rule_deck() 11 | 12 | 13 | class OutputGdsiiAspect(__Aspects__): 14 | """ """ 15 | 16 | def gdsii_view(self, unit=RDD.GDSII.UNIT, grid=RDD.GDSII.GRID, layer_map=None): 17 | library = Library(name=self.name, unit=unit, grid=grid) 18 | 19 | D = deepcopy(self) 20 | 21 | F = RDD.FILTERS.OUTPUT.PORTS 22 | 23 | library += F(D) 24 | 25 | if layer_map is None: 26 | layer_map = RDD.GDSII.EXPORT_LAYER_MAP 27 | 28 | output = OutputGdsii(file_name='', layer_map=layer_map) 29 | output.viewer(library) 30 | 31 | def gdsii_output(self, file_name=None, unit=RDD.GDSII.UNIT, grid=RDD.GDSII.GRID, layer_map=None): 32 | library = Library(name=self.name, unit=unit, grid=grid) 33 | 34 | D = deepcopy(self) 35 | 36 | F = RDD.FILTERS.OUTPUT.PORTS 37 | 38 | library += F(D) 39 | 40 | if layer_map is None: 41 | layer_map = RDD.GDSII.EXPORT_LAYER_MAP 42 | 43 | output = OutputGdsii(file_name=file_name, layer_map=layer_map) 44 | output.write(library) 45 | 46 | LOG.debug("Finished writing structure to GDS2.") 47 | 48 | 49 | class OutputPlotlyNetlist(__Aspects__): 50 | 51 | def netlist_view(self, net=None): 52 | from spira.yevon.io.output_netlist import PlotlyGraph 53 | output = PlotlyGraph() 54 | if net is None: 55 | output._plotly_netlist(G=self.netlist.g, graphname=self.name) 56 | else: 57 | output._plotly_netlist(G=net.g, graphname=self.name) 58 | 59 | 60 | class OutputBokehNetlist(__Aspects__): 61 | pass 62 | -------------------------------------------------------------------------------- /docs/_5_developers.rst: -------------------------------------------------------------------------------- 1 | Developers 2 | ========== 3 | 4 | Documentation for developers for maintaining and extending. 5 | 6 | Distribtuion 7 | ------------ 8 | 9 | Uploading package to PyPi using *twine*. 10 | Remember to remove all Eggs before doing a push to PyPi. 11 | 12 | .. code-block:: bash 13 | :linenos: 14 | 15 | sudo python3 setup.py bdist_wheel 16 | twine upload dist/* 17 | 18 | To install package systemwide set the prefix value when running setuptools: 19 | 20 | .. code-block:: bash 21 | :linenos: 22 | 23 | sudo python3 setup.py install --prefix=/usr 24 | 25 | .. code-block:: bash 26 | :linenos: 27 | 28 | sudo python3 -m pip install --upgrade . 29 | 30 | * https://docs.python.org/3.3/install/index.html 31 | 32 | Unit testing overview: http://docs.python-guide.org/en/latest/writing/tests/ 33 | 34 | Documentation 35 | ------------- 36 | 37 | If you want to generate the docs make sure the Napoleon package is installed: 38 | 39 | .. code-block:: bash 40 | :linenos: 41 | 42 | pip install sphinxcontrib-napoleon 43 | 44 | Coding standards for parsing the correct docs is given in: 45 | 46 | * https://sphinxcontrib-napoleon.readthedocs.io/en/latest/ 47 | 48 | * https://github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt 49 | 50 | Introduction to Python Virtual Enviroments: 51 | 52 | * https://realpython.com/python-virtual-environments-a-primer/ 53 | * https://stackoverflow.com/questions/15746675/how-to-write-a-python-module-package 54 | 55 | .. --------------------------------------------------------------------------------------------- 56 | 57 | Mixins 58 | ------ 59 | 60 | The following are useful links to some of the mixin implementations used in the SPiRA framework, 61 | 62 | * http://tobyho.com/2009/01/18/auto-mixin-in-python/ 63 | * http://code.activestate.com/recipes/577730-mixin-and-overlay/ 64 | * https://stackoverflow.com/questions/6966772/using-the-call- 65 | * method-of-a-metaclass-instead-of-new 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /docs/_build/html/_static/_5_developers.rst: -------------------------------------------------------------------------------- 1 | Developers 2 | ========== 3 | 4 | Documentation for developers for maintaining and extending. 5 | 6 | Distribtuion 7 | ------------ 8 | 9 | Uploading package to PyPi using *twine*. 10 | Remember to remove all Eggs before doing a push to PyPi. 11 | 12 | .. code-block:: bash 13 | :linenos: 14 | 15 | sudo python3 setup.py bdist_wheel 16 | twine upload dist/* 17 | 18 | To install package systemwide set the prefix value when running setuptools: 19 | 20 | .. code-block:: bash 21 | :linenos: 22 | 23 | sudo python3 setup.py install --prefix=/usr 24 | 25 | .. code-block:: bash 26 | :linenos: 27 | 28 | sudo python3 -m pip install --upgrade . 29 | 30 | * https://docs.python.org/3.3/install/index.html 31 | 32 | Unit testing overview: http://docs.python-guide.org/en/latest/writing/tests/ 33 | 34 | Documentation 35 | ------------- 36 | 37 | If you want to generate the docs make sure the Napoleon package is installed: 38 | 39 | .. code-block:: bash 40 | :linenos: 41 | 42 | pip install sphinxcontrib-napoleon 43 | 44 | Coding standards for parsing the correct docs is given in: 45 | 46 | * https://sphinxcontrib-napoleon.readthedocs.io/en/latest/ 47 | 48 | * https://github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt 49 | 50 | Introduction to Python Virtual Enviroments: 51 | 52 | * https://realpython.com/python-virtual-environments-a-primer/ 53 | * https://stackoverflow.com/questions/15746675/how-to-write-a-python-module-package 54 | 55 | .. --------------------------------------------------------------------------------------------- 56 | 57 | Mixins 58 | ------ 59 | 60 | The following are useful links to some of the mixin implementations used in the SPiRA framework, 61 | 62 | * http://tobyho.com/2009/01/18/auto-mixin-in-python/ 63 | * http://code.activestate.com/recipes/577730-mixin-and-overlay/ 64 | * https://stackoverflow.com/questions/6966772/using-the-call- 65 | * method-of-a-metaclass-instead-of-new 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /docs/_build/html/_sources/_5_developers.rst.txt: -------------------------------------------------------------------------------- 1 | Developers 2 | ========== 3 | 4 | Documentation for developers for maintaining and extending. 5 | 6 | Distribtuion 7 | ------------ 8 | 9 | Uploading package to PyPi using *twine*. 10 | Remember to remove all Eggs before doing a push to PyPi. 11 | 12 | .. code-block:: bash 13 | :linenos: 14 | 15 | sudo python3 setup.py bdist_wheel 16 | twine upload dist/* 17 | 18 | To install package systemwide set the prefix value when running setuptools: 19 | 20 | .. code-block:: bash 21 | :linenos: 22 | 23 | sudo python3 setup.py install --prefix=/usr 24 | 25 | .. code-block:: bash 26 | :linenos: 27 | 28 | sudo python3 -m pip install --upgrade . 29 | 30 | * https://docs.python.org/3.3/install/index.html 31 | 32 | Unit testing overview: http://docs.python-guide.org/en/latest/writing/tests/ 33 | 34 | Documentation 35 | ------------- 36 | 37 | If you want to generate the docs make sure the Napoleon package is installed: 38 | 39 | .. code-block:: bash 40 | :linenos: 41 | 42 | pip install sphinxcontrib-napoleon 43 | 44 | Coding standards for parsing the correct docs is given in: 45 | 46 | * https://sphinxcontrib-napoleon.readthedocs.io/en/latest/ 47 | 48 | * https://github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt 49 | 50 | Introduction to Python Virtual Enviroments: 51 | 52 | * https://realpython.com/python-virtual-environments-a-primer/ 53 | * https://stackoverflow.com/questions/15746675/how-to-write-a-python-module-package 54 | 55 | .. --------------------------------------------------------------------------------------------- 56 | 57 | Mixins 58 | ------ 59 | 60 | The following are useful links to some of the mixin implementations used in the SPiRA framework, 61 | 62 | * http://tobyho.com/2009/01/18/auto-mixin-in-python/ 63 | * http://code.activestate.com/recipes/577730-mixin-and-overlay/ 64 | * https://stackoverflow.com/questions/6966772/using-the-call- 65 | * method-of-a-metaclass-instead-of-new 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /spira/yevon/gdsii/label.py: -------------------------------------------------------------------------------- 1 | import gdspy 2 | import pyclipper 3 | import numpy as np 4 | from copy import copy, deepcopy 5 | from spira.yevon.gdsii.base import __LayerElement__ 6 | from spira.core.parameters.variables import * 7 | from spira.yevon.geometry.coord import Coord, CoordParameter 8 | from spira.yevon.process import get_rule_deck 9 | 10 | 11 | RDD = get_rule_deck() 12 | 13 | 14 | __all__ = ['Label'] 15 | 16 | 17 | class __Label__(__LayerElement__): 18 | """ Base class for label element. """ 19 | 20 | text = StringParameter(default='no_text') 21 | 22 | def __init__(self, position, **kwargs): 23 | super().__init__(position=position, **kwargs) 24 | 25 | def encloses(self, ply): 26 | if isinstance(ply, spira.Polygon): 27 | return pyclipper.PointInPolygon(self.position, ply.shape.points) != 0 28 | elif isinstance(ply, (list, set, np.ndarray)): 29 | return pyclipper.PointInPolygon(self.position, ply) != 0 30 | else: 31 | raise ValueError('Not Implemented!') 32 | 33 | def flat_copy(self, level=-1, commit_to_gdspy=False): 34 | c_label = self.copy(position=self.position) 35 | if commit_to_gdspy: self.gdspy_commit = True 36 | return c_label 37 | 38 | def id_string(self): 39 | return self.__repr__() 40 | 41 | 42 | class Label(__Label__): 43 | """ Label that contains a text description. 44 | 45 | Example 46 | ------- 47 | >>> lbl = spira.Label(text='P1', position=(0,0)) 48 | >>> [SPiRA: Label] (P1 at (0,0), texttype 0) 49 | """ 50 | 51 | position = CoordParameter(default=(0,0)) 52 | orientation = NumberParameter(default=0) 53 | 54 | def __init__(self, position, **kwargs): 55 | super().__init__(position=position, **kwargs) 56 | 57 | def __repr__(self): 58 | if self is None: 59 | return 'Label is None!' 60 | string = "[SPiRA: Label] ({} at ({}), layer {})" 61 | return string.format(self.text, self.position, self.layer.name) 62 | 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /docs/_build/html/_static/gettingstarted.rst: -------------------------------------------------------------------------------- 1 | Getting Started 2 | =============== 3 | 4 | GDSII files contain a hierarchical representation of any polygonal geometry. 5 | They are mainly used in the microelectronics industry for the design of mask layouts, but are also employed in other areas. 6 | 7 | Because it is a hierarchical format, repeated structures, such as identical transistors, can be defined once and referenced multiple times in the layout, reducing the file size. 8 | 9 | There is one important limitation in the GDSII format: it only supports `weakly simple polygons `_, that is, polygons whose segments are allowed to intersect, but not cross. 10 | 11 | In particular, curves and shapes with holes are *not* directly supported. 12 | Holes can be defined, nonetheless, by connecting their boundary to the boundary of the enclosing shape. 13 | In the case of curves, they must be approximated by a polygon. 14 | The number of points in the polygonal approximation can be increased to better approximate the original curve up to some acceptable error. 15 | 16 | The original GDSII format limits the number of vertices in a polygon to 199. 17 | Most modern software disregards this limit and allows an arbitrary number of points per polygon. 18 | Gdspy follows the modern version of GDSII, but this is an important issue to keep in mind if the generated file is to be used in older systems. 19 | 20 | The units used to represent shapes in the GDSII format are defined by the user. 21 | The default unit in gdspy is 1 µm (10⁻⁶ m), but that can be easily changed by the user. 22 | 23 | 24 | First GDSII 25 | ----------- 26 | 27 | Let's create our first GDSII file: 28 | 29 | .. code-block:: python 30 | 31 | import gdspy 32 | 33 | # Create the geometry: a single rectangle. 34 | rect = gdspy.Rectangle((0, 0), (2, 1)) 35 | cell = gdspy.Cell('FIRST') 36 | cell.add(rect) 37 | 38 | # Save all created cells in file 'first.gds'. 39 | gdspy.write_gds('first.gds') 40 | 41 | # Optionally, display all cells using the internal viewer. 42 | gdspy.LayoutViewer() 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /docs/_build/html/_sources/gettingstarted.rst.txt: -------------------------------------------------------------------------------- 1 | Getting Started 2 | =============== 3 | 4 | GDSII files contain a hierarchical representation of any polygonal geometry. 5 | They are mainly used in the microelectronics industry for the design of mask layouts, but are also employed in other areas. 6 | 7 | Because it is a hierarchical format, repeated structures, such as identical transistors, can be defined once and referenced multiple times in the layout, reducing the file size. 8 | 9 | There is one important limitation in the GDSII format: it only supports `weakly simple polygons `_, that is, polygons whose segments are allowed to intersect, but not cross. 10 | 11 | In particular, curves and shapes with holes are *not* directly supported. 12 | Holes can be defined, nonetheless, by connecting their boundary to the boundary of the enclosing shape. 13 | In the case of curves, they must be approximated by a polygon. 14 | The number of points in the polygonal approximation can be increased to better approximate the original curve up to some acceptable error. 15 | 16 | The original GDSII format limits the number of vertices in a polygon to 199. 17 | Most modern software disregards this limit and allows an arbitrary number of points per polygon. 18 | Gdspy follows the modern version of GDSII, but this is an important issue to keep in mind if the generated file is to be used in older systems. 19 | 20 | The units used to represent shapes in the GDSII format are defined by the user. 21 | The default unit in gdspy is 1 µm (10⁻⁶ m), but that can be easily changed by the user. 22 | 23 | 24 | First GDSII 25 | ----------- 26 | 27 | Let's create our first GDSII file: 28 | 29 | .. code-block:: python 30 | 31 | import gdspy 32 | 33 | # Create the geometry: a single rectangle. 34 | rect = gdspy.Rectangle((0, 0), (2, 1)) 35 | cell = gdspy.Cell('FIRST') 36 | cell.add(rect) 37 | 38 | # Save all created cells in file 'first.gds'. 39 | gdspy.write_gds('first.gds') 40 | 41 | # Optionally, display all cells using the internal viewer. 42 | gdspy.LayoutViewer() 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /tests/_03_structures/_05_jtl_bp.py: -------------------------------------------------------------------------------- 1 | import spira.all as spira 2 | 3 | from tests._03_structures._02_jj import Junction 4 | from spira.yevon.process import get_rule_deck 5 | 6 | 7 | RDD = get_rule_deck() 8 | 9 | 10 | class JtlBiasPorts(spira.Circuit): 11 | 12 | def get_transforms(self): 13 | t1 = spira.Translation(translation=(0, 0)) 14 | t2 = spira.Translation(translation=(150, 0)) 15 | return [t1, t2] 16 | 17 | def create_routes(self, elems): 18 | elems += spira.Rectangle(p1=(4, -4), p2=(146, 4), layer=RDD.PLAYER.M2.METAL) 19 | elems += spira.Rectangle(p1=(-3, -4), p2=(-30, 4), layer=RDD.PLAYER.M2.METAL) 20 | elems += spira.Rectangle(p1=(153, -4), p2=(180, 4), layer=RDD.PLAYER.M2.METAL) 21 | elems += spira.Rectangle(p1=(60, 0), p2=(80, 50), layer=RDD.PLAYER.M2.METAL) 22 | return elems 23 | 24 | def create_elements(self, elems): 25 | t1, t2 = self.get_transforms() 26 | 27 | jj = Junction() 28 | 29 | elems += spira.SRef(alias='S1', reference=jj, transformation=t1) 30 | elems += spira.SRef(alias='S2', reference=jj, transformation=t2) 31 | 32 | return elems 33 | 34 | def create_ports(self, ports): 35 | ports += spira.Port(name='P1_M2', process=RDD.PROCESS.M2, midpoint=(-28, 0), orientation=180, width=8) 36 | ports += spira.Port(name='P2_M2', process=RDD.PROCESS.M2, midpoint=(180, 0), orientation=0, width=8) 37 | ports += spira.Port(name='P3_M2', process=RDD.PROCESS.M2, midpoint=(70, 50), orientation=90, width=20) 38 | return ports 39 | 40 | 41 | # ------------------------------------------------------------------------------------------------------------------- 42 | 43 | 44 | if __name__ == '__main__': 45 | 46 | D = JtlBiasPorts(pcell=True) 47 | 48 | # from spira.yevon.vmodel.virtual import virtual_connect 49 | # v_model = virtual_connect(device=D) 50 | # v_model.gdsii_output_virtual_connect() 51 | 52 | # from spira.yevon.filters.boolean_filter import MetalConnectFilter 53 | # D = MetalConnectFilter()(D) 54 | 55 | # D.gdsii_output() 56 | D.netlist_view() 57 | -------------------------------------------------------------------------------- /spira/technologies/default/circuits/ytron_circuit.py: -------------------------------------------------------------------------------- 1 | import spira.all as spira 2 | from spira.all import RDD 3 | from tutorials.advanced._0_devices import YtronDevice, YtronShape 4 | 5 | 6 | class YtronCircuit(spira.Circuit): 7 | 8 | ytron = spira.Parameter(fdef_name='create_ytron') 9 | 10 | @spira.cache() 11 | def get_io_ports(self): 12 | p1 = spira.Port(name='P1_M1', midpoint=(-10,10), orientation=0) 13 | p2 = spira.Port(name='P2_M1', midpoint=(5,10), width=0.5, orientation=270) 14 | p3 = spira.Port(name='P3_M1', midpoint=(0,-10), width=1, orientation=90) 15 | return [p1, p2, p3] 16 | 17 | def create_ytron(self): 18 | shape = YtronShape(rho=0.5, theta=5) 19 | D = YtronDevice(shape=shape) 20 | return spira.SRef(alias='ytron', reference=D) 21 | 22 | def create_elements(self, elems): 23 | p1, p2, p3 = self.get_io_ports() 24 | 25 | elems += self.ytron 26 | 27 | elems += spira.RouteManhattan( 28 | ports=[self.ytron.ports['Pl_M1'], p1], 29 | width=self.ytron.reference.shape.arm_widths[0], 30 | layer=RDD.PLAYER.M1.METAL, 31 | corners=self.corners) 32 | 33 | elems += spira.RouteStraight(p1=p2, 34 | p2=self.ytron.ports['Pr_M1'], 35 | layer=RDD.PLAYER.M1.METAL, 36 | path_type='sine', width_type='sine') 37 | 38 | elems += spira.RouteStraight(p1=p3, 39 | p2=self.ytron.ports['Psrc_M1'], 40 | layer=RDD.PLAYER.M1.METAL, 41 | path_type='sine', width_type='sine') 42 | 43 | return elems 44 | 45 | def create_ports(self, ports): 46 | ports += self.get_io_ports() 47 | return ports 48 | 49 | 50 | # class YtronCircuit(spira.Circuit): 51 | 52 | # ytron = spira.CellParameter(restriction=spira.RestrictType([YtronDevice])) 53 | 54 | # def create_elements(self, elems): 55 | # return elems 56 | 57 | # def create_ports(self, ports): 58 | # return port 59 | 60 | 61 | if __name__ == '__main__': 62 | 63 | D = YtronCircuit() 64 | # D.gdsii_output(name='YtronPCell') 65 | D.gdsii_output(name='YtronCircuit') 66 | 67 | -------------------------------------------------------------------------------- /docs/_build/html/_static/developers.rst: -------------------------------------------------------------------------------- 1 | Developers 2 | ========== 3 | 4 | Documentation for developers for maintaining and extending. Extra information is added 5 | to better understand specific code implementations. 6 | 7 | .. Distribtuion 8 | .. ------------ 9 | 10 | .. Uploading package to PyPi using *twine*. 11 | .. Remember to remove all Eggs before doing a push to PyPi. 12 | 13 | .. .. code-block:: bash 14 | .. :linenos: 15 | 16 | .. sudo python3 setup.py bdist_wheel 17 | .. twine upload dist/* 18 | 19 | .. To install package systemwide set the prefix value when running setuptools: 20 | 21 | .. .. code-block:: bash 22 | .. :linenos: 23 | 24 | .. sudo python3 setup.py install --prefix=/usr 25 | 26 | .. .. code-block:: bash 27 | .. :linenos: 28 | 29 | .. sudo python3 -m pip install --upgrade . 30 | 31 | .. * https://docs.python.org/3.3/install/index.html 32 | 33 | .. Unit testing overview: http://docs.python-guide.org/en/latest/writing/tests/ 34 | 35 | .. Documentation 36 | .. ------------- 37 | 38 | .. If you want to generate the docs make sure the Napoleon package is installed: 39 | 40 | .. .. code-block:: bash 41 | .. :linenos: 42 | 43 | .. pip install sphinxcontrib-napoleon 44 | 45 | .. Coding standards for parsing the correct docs is given in: 46 | 47 | .. * https://sphinxcontrib-napoleon.readthedocs.io/en/latest/ 48 | 49 | .. * https://github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt 50 | 51 | .. Introduction to Python Virtual Enviroments: 52 | 53 | .. * https://realpython.com/python-virtual-environments-a-primer/ 54 | .. * https://stackoverflow.com/questions/15746675/how-to-write-a-python-module-package 55 | 56 | .. .. --------------------------------------------------------------------------------------------- 57 | 58 | .. Mixins 59 | .. ------ 60 | 61 | .. The following are useful links to some of the mixin implementations used in the SPiRA framework, 62 | 63 | .. * http://tobyho.com/2009/01/18/auto-mixin-in-python/ 64 | .. * http://code.activestate.com/recipes/577730-mixin-and-overlay/ 65 | .. * https://stackoverflow.com/questions/6966772/using-the-call- 66 | .. * method-of-a-metaclass-instead-of-new 67 | 68 | .. Metaprogramming 69 | .. --------------- 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /spira/yevon/aspects/polygon.py: -------------------------------------------------------------------------------- 1 | import gdspy 2 | import hashlib 3 | import numpy as np 4 | 5 | from spira.yevon.utils import clipping 6 | from spira.yevon.gdsii.polygon import Polygon 7 | from spira.yevon.gdsii.elem_list import ElementList 8 | from spira.yevon.aspects.clipper import __ClipperAspects__ 9 | from spira.yevon.aspects.geometry import __GeometryAspects__ 10 | from spira.yevon.process import get_rule_deck 11 | 12 | 13 | RDD = get_rule_deck() 14 | 15 | 16 | class PolygonAspects(__GeometryAspects__): 17 | pass 18 | 19 | 20 | class PolygonClipperAspects(__ClipperAspects__): 21 | """ 22 | 23 | """ 24 | 25 | def __and__(self, other): 26 | if self.layer == other.layer: 27 | s1 = self.shape.transform_copy(self.transformation) 28 | s2 = other.shape.transform_copy(other.transformation) 29 | shapes = s1.__and__(s2) 30 | elems = [Polygon(shape=s, layer=self.layer) for s in shapes] 31 | return elems 32 | return ElementList([]) 33 | 34 | def __sub__(self, other): 35 | if self.layer == other.layer: 36 | s1 = self.shape.transform_copy(self.transformation) 37 | s2 = other.shape.transform_copy(other.transformation) 38 | shapes = s1.__sub__(s2) 39 | elems = [Polygon(shape=s, layer=self.layer) for s in shapes] 40 | return elems 41 | return ElementList([self]) 42 | 43 | def __or__(self, other): 44 | if self.layer == other.layer: 45 | s1 = self.shape.transform_copy(self.transformation) 46 | s2 = other.shape.transform_copy(other.transformation) 47 | shapes = s1.__or__(s2) 48 | elems = [Polygon(shape=s, layer=self.layer) for s in shapes] 49 | return elems 50 | return ElementList([self, other]) 51 | 52 | # NOTE: Does not require to check for layer equivalence. 53 | def intersection(self, other): 54 | from copy import deepcopy 55 | s1 = self.shape.transform_copy(self.transformation) 56 | s2 = other.shape.transform_copy(other.transformation) 57 | shapes = s1.__and__(s2) 58 | elems = [Polygon(shape=s, layer=self.layer) for s in shapes] 59 | return elems 60 | 61 | -------------------------------------------------------------------------------- /docs/_build/html/_sources/developers.rst.txt: -------------------------------------------------------------------------------- 1 | Developers 2 | ========== 3 | 4 | Documentation for developers for maintaining and extending. Extra information is added 5 | to better understand specific code implementations. 6 | 7 | .. Distribtuion 8 | .. ------------ 9 | 10 | .. Uploading package to PyPi using *twine*. 11 | .. Remember to remove all Eggs before doing a push to PyPi. 12 | 13 | .. .. code-block:: bash 14 | .. :linenos: 15 | 16 | .. sudo python3 setup.py bdist_wheel 17 | .. twine upload dist/* 18 | 19 | .. To install package systemwide set the prefix value when running setuptools: 20 | 21 | .. .. code-block:: bash 22 | .. :linenos: 23 | 24 | .. sudo python3 setup.py install --prefix=/usr 25 | 26 | .. .. code-block:: bash 27 | .. :linenos: 28 | 29 | .. sudo python3 -m pip install --upgrade . 30 | 31 | .. * https://docs.python.org/3.3/install/index.html 32 | 33 | .. Unit testing overview: http://docs.python-guide.org/en/latest/writing/tests/ 34 | 35 | .. Documentation 36 | .. ------------- 37 | 38 | .. If you want to generate the docs make sure the Napoleon package is installed: 39 | 40 | .. .. code-block:: bash 41 | .. :linenos: 42 | 43 | .. pip install sphinxcontrib-napoleon 44 | 45 | .. Coding standards for parsing the correct docs is given in: 46 | 47 | .. * https://sphinxcontrib-napoleon.readthedocs.io/en/latest/ 48 | 49 | .. * https://github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt 50 | 51 | .. Introduction to Python Virtual Enviroments: 52 | 53 | .. * https://realpython.com/python-virtual-environments-a-primer/ 54 | .. * https://stackoverflow.com/questions/15746675/how-to-write-a-python-module-package 55 | 56 | .. .. --------------------------------------------------------------------------------------------- 57 | 58 | .. Mixins 59 | .. ------ 60 | 61 | .. The following are useful links to some of the mixin implementations used in the SPiRA framework, 62 | 63 | .. * http://tobyho.com/2009/01/18/auto-mixin-in-python/ 64 | .. * http://code.activestate.com/recipes/577730-mixin-and-overlay/ 65 | .. * https://stackoverflow.com/questions/6966772/using-the-call- 66 | .. * method-of-a-metaclass-instead-of-new 67 | 68 | .. Metaprogramming 69 | .. --------------- 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /spira/yevon/filters/layer_filter.py: -------------------------------------------------------------------------------- 1 | from spira.log import SPIRA_LOG as LOG 2 | from spira.yevon.filters.filter import Filter 3 | from spira.core.parameters.variables import ListParameter 4 | from spira.yevon.process.gdsii_layer import LayerList, LayerListParameter 5 | 6 | 7 | __all__ = ['LayerFilterAllow', 'LayerFilterDelete', 'PurposeFilterAllow', 'PurposeFilterDelete'] 8 | 9 | 10 | class __LayerFilter__(Filter): 11 | layers = LayerListParameter() 12 | 13 | 14 | class LayerFilterAllow(__LayerFilter__): 15 | def filter___LayerElement__(self, item): 16 | if item.layer in self.layers: 17 | return [item] 18 | else: 19 | LOG.debug("LayerFilterAllow is filtering out item %s" %item) 20 | return [] 21 | 22 | def __repr__(self): 23 | return "[SPiRA: LayerFilterDelete] (layer count {})".format(len(self.layers)) 24 | 25 | 26 | # FIXME: Not implemented. 27 | class LayerFilterDelete(__LayerFilter__): 28 | def filter___LayerElement__(self, item): 29 | if item.layer in self.layers: 30 | LOG.debug("LayerFilterDelete is filtering out item %s" %item) 31 | return [] 32 | else: 33 | return [item] 34 | 35 | def __repr__(self): 36 | return "[SPiRA: LayerFilterDelete] (layer count {})".format(len(self.layers)) 37 | 38 | 39 | class __PurposeFilter__(Filter): 40 | purposes = ListParameter() 41 | 42 | 43 | class PurposeFilterAllow(__PurposeFilter__): 44 | def filter___LayerElement__(self, item): 45 | if item.layer.purpose.symbol in self.purposes: 46 | return [item] 47 | else: 48 | LOG.debug("LayerFilterAllow is filtering out item %s" %item) 49 | return [] 50 | 51 | def __repr__(self): 52 | return "[SPiRA: LayerFilterDelete] (layer count {})".format(len(self.purposes)) 53 | 54 | 55 | # FIXME: Not implemented. 56 | class PurposeFilterDelete(__PurposeFilter__): 57 | def filter___LayerElement__(self, item): 58 | if item.layer in self.purposes: 59 | return [item] 60 | else: 61 | LOG.debug("LayerFilterAllow is filtering out item %s" %item) 62 | return [] 63 | 64 | def __repr__(self): 65 | return "[SPiRA: LayerFilterDelete] (layer count {})".format(len(self.purposes)) 66 | 67 | 68 | -------------------------------------------------------------------------------- /spira/yevon/io/output_gdsii.py: -------------------------------------------------------------------------------- 1 | import gdspy 2 | from spira.yevon.io.output import OutputBasic 3 | from spira.yevon.process import get_rule_deck 4 | 5 | 6 | RDD = get_rule_deck() 7 | 8 | 9 | __all__ = ['OutputGdsii'] 10 | 11 | 12 | class OutputGdsii(OutputBasic): 13 | """ Writes GDS output to a stream """ 14 | 15 | def __init__(self, file_name=None, **kwargs): 16 | if file_name is None: 17 | raise ValueError('No GDSII file name specified.') 18 | super().__init__(file_name=file_name, **kwargs) 19 | 20 | def write(self, item): 21 | self.collect(item) 22 | writer = gdspy.GdsWriter('{}.gds'.format(self.file_name), unit=1.0e-6, precision=1.0e-12) 23 | for cell in self.collector.values(): 24 | writer.write_cell(cell) 25 | del cell 26 | writer.close() 27 | 28 | def viewer(self, item): 29 | self.collect(item) 30 | library = gdspy.GdsLibrary(name=self.file_name) 31 | for c in self.collector.values(): 32 | library.add(c) 33 | gdspy.LayoutViewer(library=library) 34 | 35 | def collect_reference(self, ref_cell, origin, rotation, reflection, magnification): 36 | e = gdspy.CellReference( 37 | ref_cell=ref_cell, 38 | origin=origin, 39 | rotation=rotation, 40 | magnification=magnification, 41 | x_reflection=reflection 42 | ) 43 | self.collector[self._current_cell].add(e) 44 | return self 45 | 46 | def collect_label(self, text, position, rotation, layer): 47 | layer = self.map_layer(layer) 48 | if layer is None: return self 49 | e = gdspy.Label( 50 | text=text, 51 | position=position, 52 | rotation=rotation, 53 | layer=layer.number, 54 | texttype=layer.datatype 55 | ) 56 | self.collector[self._current_cell].add(e) 57 | return self 58 | 59 | def collect_polygon(self, points, layer): 60 | layer = self.map_layer(layer) 61 | if layer is None: return self 62 | e = gdspy.Polygon( 63 | points=points, 64 | layer=layer.number, 65 | datatype=layer.datatype 66 | ) 67 | self.collector[self._current_cell].add(e) 68 | return self 69 | 70 | -------------------------------------------------------------------------------- /docs/_build/html/_static/tutorials.rst: -------------------------------------------------------------------------------- 1 | Tutorials 2 | ========= 3 | 4 | The following tutorials will help you understand the basic methodology behind the 5 | SPiRA framework. This will show you how to use the framework to connect metadata 6 | to generated layout instances. 7 | 8 | .. Parameterized Cells 9 | .. ------------------- 10 | 11 | .. .. include:: ../demo/projects/tutorials/0-vanilla/readme.rst 12 | 13 | .. .. literalinclude:: ../demo/projects/tutorials/0-vanilla/run_vanilla.py 14 | .. :language: python 15 | .. :linenos: 16 | 17 | .. .. ----------------------------------------------------------------------------------- 18 | 19 | .. Database 20 | .. -------- 21 | 22 | .. .. include:: ../demo/projects/tutorials/2-database/readme.rst 23 | 24 | .. .. literalinclude:: ../demo/projects/tutorials/2-database/run_database.py 25 | .. :language: python 26 | .. :linenos: 27 | 28 | .. .. ----------------------------------------------------------------------------------- 29 | 30 | .. Shapes 31 | .. ------ 32 | 33 | .. .. include:: ../demo/projects/tutorials/3-shapes/readme.rst 34 | 35 | .. .. literalinclude:: ../demo/projects/tutorials/3-shapes/run_shapes.py 36 | .. :language: python 37 | .. :linenos: 38 | 39 | .. .. ----------------------------------------------------------------------------------- 40 | 41 | .. Elementals 42 | .. ---------- 43 | 44 | .. .. include:: ../demo/projects/tutorials/4-elementals/readme.rst 45 | 46 | .. .. literalinclude:: ../demo/projects/tutorials/4-elementals/run_elementals.py 47 | .. :language: python 48 | .. :linenos: 49 | 50 | .. .. ----------------------------------------------------------------------------------- 51 | 52 | .. Subcells 53 | .. -------- 54 | 55 | .. .. include:: ../demo/projects/tutorials/5-subcells/readme.rst 56 | 57 | .. .. literalinclude:: ../demo/projects/tutorials/5-subcells/run_subcells.py 58 | .. :language: python 59 | .. :linenos: 60 | 61 | .. .. ----------------------------------------------------------------------------------- 62 | 63 | .. Ports 64 | .. ----- 65 | 66 | .. .. include:: ../demo/projects/tutorials/6-ports/readme.rst 67 | 68 | .. .. literalinclude:: ../demo/projects/tutorials/6-ports/run_ports.py 69 | .. :language: python 70 | .. :linenos: 71 | 72 | .. .. literalinclude:: ../demo/projects/tutorials/6-ports/run_ports_1.py 73 | .. :language: python 74 | .. :linenos: 75 | 76 | .. .. ----------------------------------------------------------------------------------- 77 | 78 | 79 | -------------------------------------------------------------------------------- /spira/yevon/process/process_layer.py: -------------------------------------------------------------------------------- 1 | from spira.core.parameters.restrictions import RestrictType 2 | from spira.core.parameters.variables import StringParameter, IntegerParameter 3 | from spira.core.parameters.initializer import ParameterInitializer, MetaInitializer 4 | from spira.core.parameters.descriptor import RestrictedParameter, Parameter 5 | 6 | 7 | DEFINED_PROCESS_LAYERS = {} 8 | 9 | 10 | __all__ = ['ProcessLayer', 'ProcessParameter'] 11 | 12 | 13 | class MetaProcessLayer(MetaInitializer): 14 | """ 15 | Metaclass which creates unique process layers. 16 | It is called when a new object is created. 17 | """ 18 | 19 | def __call__(cls, *params, **keyword_params): 20 | if 'symbol' in keyword_params: 21 | symbol = keyword_params['symbol'] 22 | elif len(params) >= 1: 23 | symbol = params[1] 24 | else: 25 | symbol = "XX" 26 | raise AttributeError("Extension for a process layer should not be empty. Reset to XX") 27 | 28 | # extract the name of the new structure based on the arguments of 29 | # the constructor. For default structures, the name is passed as the first argument 30 | 31 | L = type.__call__(cls, *params, **keyword_params) 32 | exist = DEFINED_PROCESS_LAYERS.get(symbol, None) 33 | if exist: 34 | return exist 35 | else: 36 | DEFINED_PROCESS_LAYERS[symbol] = L 37 | return L 38 | 39 | 40 | class ProcessLayer(ParameterInitializer, metaclass=MetaProcessLayer): 41 | """ """ 42 | 43 | name = StringParameter() 44 | symbol = StringParameter() 45 | 46 | def __init__(self, name, symbol, **kwargs): 47 | super().__init__(name = name, symbol = symbol, **kwargs) 48 | 49 | def __eq__(self, other): 50 | if not isinstance(other, ProcessLayer): return False 51 | return self.symbol == other.symbol 52 | 53 | def __ne__(self, other): 54 | return (not self.__eq__(other)) 55 | 56 | def __repr__(self): 57 | return "[SPiRA: Process] (name {}, symbol {})".format(self.name, self.symbol) 58 | 59 | def __str__(self): 60 | return self.__repr__() 61 | 62 | def __hash__(self): 63 | return hash(self.__str__()) 64 | 65 | 66 | def ProcessParameter(local_name=None, restriction=None, **kwargs): 67 | R = RestrictType(ProcessLayer) & restriction 68 | return RestrictedParameter(local_name, restriction=R, **kwargs) 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /docs/_build/html/_sources/tutorials.rst.txt: -------------------------------------------------------------------------------- 1 | Tutorials 2 | ========= 3 | 4 | The following tutorials will help you understand the basic methodology behind the 5 | SPiRA framework. This will show you how to use the framework to connect metadata 6 | to generated layout instances. 7 | 8 | .. Parameterized Cells 9 | .. ------------------- 10 | 11 | .. .. include:: ../demo/projects/tutorials/0-vanilla/readme.rst 12 | 13 | .. .. literalinclude:: ../demo/projects/tutorials/0-vanilla/run_vanilla.py 14 | .. :language: python 15 | .. :linenos: 16 | 17 | .. .. ----------------------------------------------------------------------------------- 18 | 19 | .. Database 20 | .. -------- 21 | 22 | .. .. include:: ../demo/projects/tutorials/2-database/readme.rst 23 | 24 | .. .. literalinclude:: ../demo/projects/tutorials/2-database/run_database.py 25 | .. :language: python 26 | .. :linenos: 27 | 28 | .. .. ----------------------------------------------------------------------------------- 29 | 30 | .. Shapes 31 | .. ------ 32 | 33 | .. .. include:: ../demo/projects/tutorials/3-shapes/readme.rst 34 | 35 | .. .. literalinclude:: ../demo/projects/tutorials/3-shapes/run_shapes.py 36 | .. :language: python 37 | .. :linenos: 38 | 39 | .. .. ----------------------------------------------------------------------------------- 40 | 41 | .. Elementals 42 | .. ---------- 43 | 44 | .. .. include:: ../demo/projects/tutorials/4-elementals/readme.rst 45 | 46 | .. .. literalinclude:: ../demo/projects/tutorials/4-elementals/run_elementals.py 47 | .. :language: python 48 | .. :linenos: 49 | 50 | .. .. ----------------------------------------------------------------------------------- 51 | 52 | .. Subcells 53 | .. -------- 54 | 55 | .. .. include:: ../demo/projects/tutorials/5-subcells/readme.rst 56 | 57 | .. .. literalinclude:: ../demo/projects/tutorials/5-subcells/run_subcells.py 58 | .. :language: python 59 | .. :linenos: 60 | 61 | .. .. ----------------------------------------------------------------------------------- 62 | 63 | .. Ports 64 | .. ----- 65 | 66 | .. .. include:: ../demo/projects/tutorials/6-ports/readme.rst 67 | 68 | .. .. literalinclude:: ../demo/projects/tutorials/6-ports/run_ports.py 69 | .. :language: python 70 | .. :linenos: 71 | 72 | .. .. literalinclude:: ../demo/projects/tutorials/6-ports/run_ports_1.py 73 | .. :language: python 74 | .. :linenos: 75 | 76 | .. .. ----------------------------------------------------------------------------------- 77 | 78 | 79 | -------------------------------------------------------------------------------- /spira/yevon/vmodel/derived.py: -------------------------------------------------------------------------------- 1 | from copy import deepcopy 2 | from spira.yevon.process.gdsii_layer import Layer 3 | from spira.yevon.process.gdsii_layer import _DerivedDoubleLayer 4 | from spira.yevon.process.gdsii_layer import _DerivedAndLayer 5 | from spira.yevon.process.gdsii_layer import _DerivedXorLayer 6 | 7 | from spira.yevon.gdsii.elem_list import ElementList 8 | from spira.yevon.gdsii.polygon import Polygon 9 | from spira.yevon.gdsii.polygon_group import PolygonGroup 10 | from spira.yevon.filters.layer_filter import LayerFilterAllow 11 | from spira.yevon.geometry.edges.edges import Edge 12 | from spira.yevon.process import get_rule_deck 13 | 14 | 15 | RDD = get_rule_deck() 16 | 17 | 18 | __all__ = ['get_derived_elements'] 19 | 20 | 21 | def _derived_elements(elems, derived_layer): 22 | """ Derived elements are generated from derived layers using 23 | layer operations as specified in the RDD. """ 24 | 25 | if isinstance(derived_layer, Layer): 26 | LF = LayerFilterAllow(layers=[derived_layer]) 27 | el = LF(elems.polygons) 28 | pg = PolygonGroup(elements=el, layer=derived_layer) 29 | return pg 30 | elif isinstance(derived_layer, _DerivedDoubleLayer): 31 | p1 = _derived_elements(elems, derived_layer.layer1) 32 | p2 = _derived_elements(elems, derived_layer.layer2) 33 | if isinstance(derived_layer, _DerivedAndLayer): 34 | pg = p1 & p2 35 | elif isinstance(derived_layer, _DerivedXorLayer): 36 | pg = p1 ^ p2 37 | return pg 38 | else: 39 | raise Exception("Unexpected type for parameter 'derived_layer' : %s" % str(type(derived_layer))) 40 | 41 | 42 | def get_derived_elements(elements, mapping, store_as_edge=False): 43 | """ Given a list of elements and a list of tuples (DerivedLayer, PPLayer), 44 | create new elements according to the boolean operations of the DerivedLayer 45 | and place these elements on the specified PPLayer. """ 46 | 47 | derived_layers = mapping.keys() 48 | export_layers = mapping.values() 49 | elems = ElementList() 50 | for derived_layer, export_layer in zip(derived_layers, export_layers): 51 | pg = _derived_elements(elems=elements, derived_layer=derived_layer) 52 | for p in pg.elements: 53 | if store_as_edge is True: 54 | elems += Edge(shape=p.shape, layer=deepcopy(export_layer)) 55 | else: 56 | elems += Polygon(shape=p.shape, layer=deepcopy(export_layer)) 57 | return elems 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /tests/_03_structures/_07_jj_c.py: -------------------------------------------------------------------------------- 1 | import spira.all as spira 2 | from spira.yevon.geometry import shapes 3 | from spira.yevon.geometry.coord import Coord 4 | from spira.yevon.process import get_rule_deck 5 | 6 | 7 | RDD = get_rule_deck() 8 | 9 | 10 | class ResistorCell(spira.Cell): 11 | 12 | def create_elements(self, elems): 13 | elems += spira.Rectangle(alias='RES', p1=(-5*1e6, -10*1e6), p2=(5*1e6, 10*1e6), layer=RDD.PLAYER.M3.METAL) 14 | return elems 15 | 16 | def create_ports(self, ports): 17 | 18 | ply = self.elementals['RES'] 19 | # print(ply.ports) 20 | 21 | ports += ply.ports['E3_M3'].copy(name='P3_M3') 22 | 23 | return ports 24 | 25 | 26 | class PolygonCell(spira.Cell): 27 | 28 | def create_elements(self, elems): 29 | 30 | c1 = ResistorCell() 31 | s1 = spira.SRef(c1) 32 | elems += s1 33 | 34 | elems += spira.Rectangle(p1=(-10*1e6, -15*1e6), p2=(10*1e6, 15*1e6), layer=RDD.PLAYER.M2.METAL) 35 | 36 | return elems 37 | 38 | 39 | class Junction(spira.Cell): 40 | 41 | def create_elements(self, elems): 42 | 43 | c1 = PolygonCell() 44 | 45 | s1 = spira.SRef(c1, midpoint=(0,0)) 46 | elems += s1 47 | 48 | T = spira.Translation((0*1e6, -40*1e6)) + spira.Rotation(180) 49 | s2 = spira.SRef(c1, midpoint=(0,0), transformation=T) 50 | elems += s2 51 | 52 | # port1 = s1.ports['RES_e3'] 53 | # port2 = s2.ports['RES_e3'] 54 | 55 | # print(port1) 56 | # print(port2) 57 | 58 | # R = spira.Route( 59 | # port1=s1.ports['RES_e3'], 60 | # port2=s2.ports['RES_e3'], 61 | # ps_layer=RDD.PLAYER.RES 62 | # ) 63 | # elems += spira.SRef(R) 64 | 65 | return elems 66 | 67 | # expand_elems = elems.expand_transform() 68 | # print(expand_elems) 69 | # return expand_elems 70 | 71 | 72 | from spira.yevon.gdsii.containers import __CellContainer__ 73 | class JunctionStretch(__CellContainer__): 74 | 75 | def create_elementals(self, elems): 76 | elems = self.cell.elementals 77 | return elems 78 | 79 | def create_ports(self, ports): 80 | # elems = self.cell.elementals 81 | return ports 82 | 83 | 84 | if __name__ == '__main__': 85 | 86 | cell = spira.Cell(name='TopLevel') 87 | 88 | D = Junction() 89 | S = spira.SRef(reference=D) 90 | cell += S 91 | 92 | # T = spira.Stretch(stretch_factor=(2,1)) 93 | # S1 = T(S) 94 | # cell += S1 95 | 96 | cell.gdsii_output() 97 | -------------------------------------------------------------------------------- /tests/_04_edges/_2_erc_f.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import spira.all as spira 3 | 4 | from spira.yevon.vmodel.virtual import virtual_connect 5 | from spira.technologies.mit.process import RDD 6 | 7 | 8 | el = spira.ElementList() 9 | 10 | p1 = spira.Rectangle(p1=(0, 0), p2=(4, 10), layer=RDD.PLAYER.M5.METAL) 11 | p2 = spira.Rectangle(p1=(0, 0), p2=(4, 12), layer=RDD.PLAYER.M5.METAL) 12 | # FIXME: Throught a weird polygon error. 13 | # p2 = spira.Rectangle(p1=(0, 0), p2=(4, 10), layer=RDD.PLAYER.M5.METAL) 14 | p2.shape.move(pos=(7,0)) 15 | 16 | # --------------- NOTE: overlapping cases. 17 | # p3 = spira.Rectangle(p1=(3, 4), p2=(8, 6), layer=RDD.PLAYER.M5.METAL) 18 | 19 | # el += spira.Rectangle(p1=(8, 4), p2=(-4, 6), layer=RDD.PLAYER.M5.METAL) 20 | 21 | # p3 = spira.Rectangle(p1=(-4, 4), p2=(1, 6), layer=RDD.PLAYER.M5.METAL) 22 | # p4 = spira.Rectangle(p1=(3, 4), p2=(8, 6), layer=RDD.PLAYER.M5.METAL) 23 | 24 | # p3 = spira.Rectangle(p1=(-4, 8), p2=(8, 12), layer=RDD.PLAYER.M5.METAL) 25 | 26 | # p3 = spira.Rectangle(p1=(1, 9), p2=(3, 14), layer=RDD.PLAYER.M5.METAL) 27 | 28 | # p3 = spira.Rectangle(p1=(-1, 9), p2=(5, 14), layer=RDD.PLAYER.M5.METAL) 29 | 30 | # --------------- NOTE: Edge cases. 31 | # p3 = spira.Rectangle(p1=(0, 10), p2=(4, 14), layer=RDD.PLAYER.M5.METAL) 32 | 33 | # p3 = spira.Rectangle(p1=(-4, 4), p2=(0, 6), layer=RDD.PLAYER.M5.METAL) 34 | 35 | # p3 = spira.Rectangle(p1=(4, 4), p2=(7, 6), layer=RDD.PLAYER.M5.METAL) 36 | 37 | # p3 = spira.Rectangle(p1=(3, 10), p2=(7, 11), layer=RDD.PLAYER.M5.METAL) 38 | 39 | # --------------- NOTE: Both cases. 40 | # p3 = spira.Rectangle(p1=(3, 10), p2=(8, 11), layer=RDD.PLAYER.M5.METAL) 41 | # p3 = spira.Rectangle(p1=(3, 9), p2=(8, 11), layer=RDD.PLAYER.M5.METAL) 42 | p3 = spira.Rectangle(p1=(2, 7), p2=(7, 11), layer=RDD.PLAYER.M5.METAL) 43 | 44 | # # # --------------- NOTE: Angle cases. 45 | # # p3 = spira.Rectangle(p1=(1, 8), p2=(7, 11), layer=RDD.PLAYER.M5.METAL) 46 | # p3 = spira.Rectangle(p1=(2.5, 8), p2=(7, 11), layer=RDD.PLAYER.M5.METAL) 47 | # p3.rotate(5) 48 | # p1.rotate(-10) 49 | 50 | # ------------------------------------------------------------------------ 51 | 52 | el += p1 53 | el += p2 54 | el += p3 55 | # el += p4 56 | 57 | D = spira.Cell(name='Device', elements=el) 58 | 59 | v_model = virtual_connect(device=D) 60 | v_model.view_virtual_connect(show_layers=True, write=True) 61 | 62 | # F = MetalConnectFilter() 63 | # D = F(device) 64 | 65 | # D = spira.Circuit(name='TestElectricalConnections', elements=D.elements) 66 | # # D.gdsii_output() 67 | # D.netlist_output() 68 | 69 | # D = RDD.FILTERS.MASK(D) 70 | 71 | D.netlist_view() 72 | 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /spira/yevon/process/layer_map.py: -------------------------------------------------------------------------------- 1 | from spira.core.parameters.variables import DictParameter 2 | from spira.core.parameters.initializer import ParameterInitializer 3 | from spira.core.parameters.descriptor import Parameter 4 | from spira.yevon.process.all import * 5 | from spira.yevon.process import get_rule_deck 6 | 7 | 8 | RDD = get_rule_deck() 9 | 10 | 11 | __all__ = ['MapGdsiiToPhysical', 'MapPhysicalToGdsii'] 12 | 13 | 14 | class MapGdsiiToPhysical(ParameterInitializer): 15 | """ Map the GDSII Layers onto ProcessLayers, and the Datatypes onto PurposeLayers. """ 16 | 17 | process_layer_map = DictParameter() 18 | purpose_datatype_map = DictParameter() 19 | 20 | @property 21 | def layer_process_map(self): 22 | return dict([(v, k) for k, v in self.process_layer_map.items()]) 23 | 24 | @property 25 | def datatype_purpose_map(self): 26 | return dict([(v, k) for k, v in self.purpose_datatype_map.items()]) 27 | 28 | def __getitem__(self, key, default=None): 29 | if isinstance(key, PhysicalLayer): 30 | return key 31 | elif isinstance(key, Layer): 32 | # print(key) 33 | # print(self.layer_process_map.keys()) 34 | # FIXME: Implement error checking for if layer number is not found in RDD. 35 | if key.number in self.layer_process_map: 36 | pc = self.layer_process_map[key.number] 37 | pp = self.datatype_purpose_map[key.datatype] 38 | return PhysicalLayer(process=pc, purpose=pp) 39 | raise ValueError('Layer number not found in {}.'.format(RDD)) 40 | # return PhysicalLayer(process=RDD.PROCESS.VIRTUAL, purpose=RDD.PURPOSE.TEXT) 41 | else: 42 | raise Exception("Key should be of type PhysicalLayer, but is of type %s." %type(key)) 43 | 44 | def get(self, key, default): 45 | return self.__getitem__(key, default) 46 | 47 | 48 | class MapPhysicalToGdsii(ParameterInitializer): 49 | """ """ 50 | 51 | process_layer_map = DictParameter() 52 | purpose_datatype_map = DictParameter() 53 | 54 | def __getitem__(self, key, default=None): 55 | if isinstance(key, PhysicalLayer): 56 | ln = self.process_layer_map[key.process] 57 | dt = self.purpose_datatype_map[key.purpose] 58 | return Layer(number=ln, datatype=dt) 59 | elif isinstance(key, Layer): 60 | return key 61 | else: 62 | raise Exception("Key should be of type PhysicalLayer, but is of type %s." %type(key)) 63 | 64 | def get(self, key, default): 65 | return self.__getitem__(key, default) 66 | -------------------------------------------------------------------------------- /tests/_03_structures/_06_jtl_bph.py: -------------------------------------------------------------------------------- 1 | import spira.all as spira 2 | 3 | from tests._03_structures._02_jj import Junction 4 | from spira.yevon.process import get_rule_deck 5 | 6 | 7 | RDD = get_rule_deck() 8 | 9 | 10 | class VirtualBias(spira.Cell): 11 | 12 | def create_elementals(self, elems): 13 | 14 | elems += spira.Rectangle(p1=(60, 45), p2=(80, 80), layer=RDD.PLAYER.M2.METAL) 15 | 16 | c1 = spira.Cell(name='ply1') 17 | c1 += spira.Rectangle(p1=(60, 80), p2=(80, 100), layer=RDD.PLAYER.M2.METAL) 18 | c1 += spira.Rectangle(p1=(70, 60), p2=(100, 70), layer=RDD.PLAYER.M2.METAL) 19 | elems += spira.SRef(c1) 20 | 21 | return elems 22 | 23 | 24 | class JtlBiasPorts(spira.Circuit): 25 | 26 | def get_transforms(self): 27 | t1 = spira.Translation(translation=(0, 0)) 28 | t2 = spira.Translation(translation=(150, 0)) 29 | return [t1, t2] 30 | 31 | def create_routes(self, elems): 32 | elems += spira.Rectangle(p1=(4, -4), p2=(146, 4), layer=RDD.PLAYER.M2.METAL) 33 | elems += spira.Rectangle(p1=(-3, -4), p2=(-30, 4), layer=RDD.PLAYER.M2.METAL) 34 | elems += spira.Rectangle(p1=(153, -4), p2=(180, 4), layer=RDD.PLAYER.M2.METAL) 35 | elems += spira.Rectangle(p1=(60, 0), p2=(80, 50), layer=RDD.PLAYER.M2.METAL) 36 | return elems 37 | 38 | def create_elementals(self, elems): 39 | t1, t2 = self.get_transforms() 40 | 41 | jj = Junction() 42 | 43 | elems += spira.SRef(alias='S1', reference=jj, transformation=t1) 44 | elems += spira.SRef(alias='S2', reference=jj, transformation=t2) 45 | 46 | elems += spira.SRef(reference=VirtualBias()) 47 | 48 | return elems 49 | 50 | def create_ports(self, ports): 51 | ports += spira.Port(name='P1', process=RDD.PROCESS.M2, midpoint=(-28, 0), orientation=180, width=8) 52 | ports += spira.Port(name='P2', process=RDD.PROCESS.M2, midpoint=(180, 0), orientation=0, width=8) 53 | ports += spira.Port(name='P3', process=RDD.PROCESS.M2, midpoint=(100, 65), orientation=0, width=20) 54 | ports += spira.Port(name='P4', process=RDD.PROCESS.M2, midpoint=(70, 100), orientation=90, width=20) 55 | return ports 56 | 57 | 58 | # ------------------------------------------------------------------------------------------------------------------- 59 | 60 | 61 | if __name__ == '__main__': 62 | 63 | D = JtlBiasPorts(pcell=False) 64 | 65 | # from spira.yevon.filters.boolean_filter import MetalConnectFilter 66 | # F = MetalConnectFilter() 67 | # D = F(D) 68 | 69 | D.gdsii_output() 70 | D.netlist_output() 71 | 72 | 73 | -------------------------------------------------------------------------------- /spira/core/transforms/identity.py: -------------------------------------------------------------------------------- 1 | from spira.core.transforms.translation import Translation 2 | from spira.core.transforms.rotation import Rotation 3 | from spira.core.transforms.magnification import Magnification 4 | from spira.yevon.geometry.coord import Coord 5 | from spira.core.transforms.generic import __ConvertableTransform__ 6 | 7 | 8 | __all__ = ['IdentityTransform'] 9 | 10 | 11 | class IdentityTransform(Translation, Rotation, Magnification, __ConvertableTransform__): 12 | """ Transform that leaves an object unchanged. """ 13 | 14 | def __init__(self, **kwargs): 15 | kwargs['rotation_center'] = (0.0, 0.0) 16 | kwargs['magnification_center'] = (0.0, 0.0) 17 | super().__init__(**kwargs) 18 | 19 | def apply(self, item): 20 | if isinstance(item, list): 21 | raise TypeError("Cannot add object of type " + str(type(other)) + " to transform") 22 | # return shape.Shape(item) 23 | else: 24 | return item 25 | 26 | def reverse(self, shape): 27 | if isinstance(item, list): 28 | pass 29 | # return shape.Shape(item) 30 | else: 31 | return item 32 | 33 | def apply_to_coord(self, coord): 34 | return coord 35 | 36 | def reverse_on_coord(self, coord): 37 | return coord 38 | 39 | def apply_to_coord3(self, coord): 40 | return coord 41 | 42 | def reverse_on_coord3(self, coord): 43 | return coord 44 | 45 | def apply_to_array(self, coords): 46 | return coords 47 | 48 | def reverse_on_array(self, coords): 49 | return coords 50 | 51 | def __neg__(self): 52 | return IdentityTransform() 53 | 54 | def __add__(self, other): 55 | if other is None: 56 | return IdentityTransform() 57 | elif isinstance(other, IdentityTransform): 58 | return IdentityTransform() 59 | elif isinstance(other, Translation): 60 | return Translation(other.translation) 61 | elif isinstance(other, Rotation): 62 | return Rotation(other.rotation, other.rotation_center) 63 | elif isinstance(other, Magnification): 64 | return Magnification(other.magnification, other.magnification_center) 65 | else: 66 | return __ConvertableTransform__.__add__(self, other) 67 | 68 | def __iadd__(self, other): 69 | if other is None: 70 | return self 71 | elif isinstance(other, IdentityTransform): 72 | return self 73 | else: 74 | return __ConvertableTransform__.__iadd__(self, other) 75 | 76 | def is_identity(self): 77 | return True 78 | 79 | 80 | -------------------------------------------------------------------------------- /spira/yevon/filters/edge_filter.py: -------------------------------------------------------------------------------- 1 | from spira.yevon import constants 2 | from spira.log import SPIRA_LOG as LOG 3 | from spira.yevon.filters.filter import Filter 4 | from spira.yevon.gdsii.elem_list import ElementList 5 | from spira.yevon.gdsii.polygon import Polygon 6 | from spira.yevon.geometry.shapes.adapters import ShapeEdge 7 | from spira.core.parameters.variables import * 8 | from spira.yevon.process.purpose_layer import PurposeLayerParameter 9 | 10 | 11 | __all__ = ['EdgeShapeFilter', 'EdgeToPolygonFilter'] 12 | 13 | 14 | class __EdgeFilter__(Filter): 15 | """ Base class for edge filters. """ 16 | 17 | purposes = PurposeLayerParameter() 18 | width = NumberParameter(allow_none=True, default=None) 19 | edge_type = IntegerParameter(default=constants.EDGE_TYPE_NORMAL) 20 | 21 | 22 | class EdgeShapeFilter(__EdgeFilter__): 23 | """ Filter only passes edges with the specified purpose. """ 24 | 25 | def filter_Cell(self, item): 26 | from copy import deepcopy 27 | from spira.yevon.gdsii.cell import Cell 28 | 29 | elems = ElementList() 30 | if self.width is None: 31 | for p1 in deepcopy(item.elements.polygons): 32 | if p1.layer.purpose in self.purposes: 33 | for edge in p1.edges: 34 | shape = ShapeEdge( 35 | original_shape=edge.line_shape, 36 | edge_width=edge.width, 37 | edge_type=self.edge_type 38 | ) 39 | elems += edge.copy(shape=shape) 40 | elems += p1 41 | else: 42 | for p1 in deepcopy(item.elements.polygons): 43 | if p1.layer.purpose in self.purposes: 44 | for edge in p1.edges: 45 | shape = ShapeEdge( 46 | original_shape=edge.line_shape, 47 | edge_width=self.width, 48 | edge_type=self.edge_type 49 | ) 50 | elems += edge.copy(shape=shape) 51 | elems += p1 52 | 53 | 54 | cell = Cell(elements=elems) 55 | return cell 56 | 57 | def filter_Group(self, item): 58 | pass 59 | 60 | def __repr__(self): 61 | return "[SPiRA: EdgeShapeFilter] ())".format() 62 | 63 | 64 | class EdgeToPolygonFilter(__EdgeFilter__): 65 | 66 | def filter_Edge(self, item): 67 | edge_ply = Polygon(shape=item.shape, layer=item.layer, transformation=item.transformation) 68 | return edge_ply 69 | 70 | def __repr__(self): 71 | return "[SPiRA: EdgeShapeFilter] ())".format() 72 | 73 | -------------------------------------------------------------------------------- /spira/yevon/vmodel/elements.py: -------------------------------------------------------------------------------- 1 | from spira.yevon.gdsii.cell import Cell 2 | from spira.yevon.aspects.base import __Aspects__ 3 | from spira.yevon.gdsii.elem_list import ElementListParameter, ElementList 4 | from spira.yevon.process import get_rule_deck 5 | 6 | 7 | RDD = get_rule_deck() 8 | 9 | 10 | def get_process_polygons(elements, operation='or'): 11 | from spira.yevon.gdsii.polygon_group import PolygonGroup 12 | from spira.yevon.filters.layer_filter import LayerFilterAllow 13 | 14 | elems = ElementList() 15 | for process in RDD.VMODEL.PROCESS_FLOW.active_processes: 16 | for layer in RDD.get_physical_layers_by_process(processes=process): 17 | LF = LayerFilterAllow(layers=[layer]) 18 | el = LF(elements.polygons) 19 | if operation == 'or': 20 | pg = PolygonGroup(elements=el, layer=layer).union 21 | elif operation == 'and': 22 | pg = PolygonGroup(elements=el, layer=layer).intersect 23 | elif operation == 'not': 24 | pg = PolygonGroup(elements=el, layer=layer).difference 25 | elems += pg 26 | return elems 27 | 28 | 29 | class DerivedElements(__Aspects__): 30 | """ Convert the cell elements into a new set 31 | of elements for every active process. """ 32 | 33 | derived_merged_elements = ElementListParameter() 34 | derived_overlap_elements = ElementListParameter() 35 | derived_diff_elements = ElementListParameter() 36 | 37 | def create_derived_merged_elements(self, elems): 38 | elems += get_process_polygons(self.elements, 'or') 39 | return elems 40 | 41 | def create_derived_overlap_elements(self, elems): 42 | elems += get_process_polygons(self.elements, 'and') 43 | return elems 44 | 45 | def create_derived_diff_elements(self, elems): 46 | elems += get_process_polygons(self.elements, 'not') 47 | return elems 48 | 49 | def view_derived_merged_elements(self, **kwargs): 50 | elems = ElementList() 51 | for pg in self.derived_merged_elements: 52 | for e in pg.elements: 53 | elems += e 54 | name = '{}_{}'.format(self.name, 'DERIVED_MERGED_ELEMENTS') 55 | D = Cell(name=name, elements=elems) 56 | D.gdsii_view() 57 | 58 | def view_derived_overlap_elements(self, **kwargs): 59 | elems = ElementList() 60 | for pg in self.derived_overlap_elements: 61 | for e in pg.elements: 62 | elems += e 63 | name = '{}_{}'.format(self.name, 'DERIVED_OVERLAP_ELEMENTS') 64 | D = Cell(name=name, elements=elems) 65 | D.gdsii_view() 66 | 67 | 68 | Cell.mixin(DerivedElements) 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /tutorials/basic/_11_shapes.py: -------------------------------------------------------------------------------- 1 | import spira.all as spira 2 | 3 | 4 | class ShapesExample(spira.Cell): 5 | """ """ 6 | 7 | def create_elements(self, elems): 8 | 9 | points = [(10.0, 0.0), (15.0, 10.0), 10 | (0.0, 10.0), (0.0, 5.0), 11 | (-15.0, 5.0), (-5.0, 0.0), 12 | (-10.0, -10.0), (-5.0, -15.0), 13 | (10.0, -15.0), (5.0, -10.0), (5.0, -5.0)] 14 | s = spira.Shape(points=points) 15 | 16 | S1 = spira.Cell(name='shape', elements=spira.Polygon(shape=s, layer=spira.Layer(1))) 17 | 18 | # #translate a copy of the shape 19 | # t = s.move_copy((0.0, 20.0)) 20 | # S2 = Structure("shape_trans", Boundary(Layer(0), t)) 21 | 22 | # #rotate the shape (angle in degree) 23 | # t = s.rotate_copy((0.0, 0.0), 50) 24 | # S3 = Structure("shape_rot", Boundary(Layer(0), t)) 25 | 26 | # #scale the shape 27 | # t = s.magnify_copy((0.0, 0.0), 1.2) 28 | # S4 = Structure("shape_scale", Boundary(Layer(0), t)) 29 | 30 | # #stretch the shape horizontally and squeeze vertically 31 | # t = Stretch(stretch_center = (0.0, 0.0), stretch_factor = (1.5, 0.5))(s) 32 | # S5 = Structure("shape_stretch", Boundary(Layer(0), t)) 33 | 34 | # #fit the shape in a box 35 | # south_west = (-7.0, -7.0) 36 | # north_east = (7.0, 7.0) 37 | # t = ShapeFit(s, south_west, north_east) 38 | # S6 = Structure("shape_fit", Boundary(Layer(0), t)) 39 | 40 | # #create a shape which traces the contour with a certain line width 41 | # t = ShapePath(original_shape = s, path_width = 0.5) 42 | # S7 = Structure("ShapePath1", Boundary(Layer(0), t)) 43 | 44 | # t = ShapePathRounded(original_shape = s, path_width = 0.5) 45 | # S8 = Structure("ShapePath2", Boundary(Layer(0), t)) 46 | 47 | # #expand the shape with a certain distance 48 | # t = ShapeGrow(s, 1.0) 49 | # S9 = Structure("shape_grow", Boundary(Layer(1), t) + Boundary(Layer(0), s)) 50 | 51 | # #round the shape with a given radius 52 | # t = ShapeRound(original_shape = s, radius = 2.0) 53 | # S10 = Structure("shape_round", Boundary(Layer(1), t) + Boundary(Layer(0), s)) 54 | 55 | elems += [ 56 | spira.SRef(S1, (0.0, 200.0)), 57 | ] 58 | 59 | return elems 60 | 61 | 62 | if __name__ == '__main__': 63 | 64 | D = ShapesExample() 65 | D.gdsii_output(file_name='shape_example') 66 | # lib = Library(name="Shapes", unit=1e-6, grid=1e-9) 67 | # lib += layout 68 | # output = OutputGdsii('shape_example') 69 | # output.write(my_lib) 70 | 71 | 72 | -------------------------------------------------------------------------------- /spira/core/transforms/translation.py: -------------------------------------------------------------------------------- 1 | import spira.all as spira 2 | from copy import deepcopy 3 | from spira.core.transformable import Transformable 4 | from spira.yevon.geometry.coord import Coord 5 | from spira.core.transforms.generic import __ConvertableTransform__, GenericTransform 6 | 7 | 8 | class Translation(__ConvertableTransform__): 9 | """ """ 10 | 11 | def __init__(self, translation=(0,0), **kwargs): 12 | super().__init__(translation=translation, **kwargs) 13 | 14 | translation = getattr(GenericTransform, 'translation') 15 | 16 | def apply_to_coord(self, coord): 17 | return self.__translate__(coord) 18 | 19 | def apply_to_array(self, coords): 20 | return self.__translate_array__(coords) 21 | 22 | def reverse_on_coord(self, coord): 23 | return self.__inv_translate__(coord) 24 | 25 | def reverse_on_array(self, coords): 26 | return self.__inv_translate_array__(coords) 27 | 28 | def __add__(self, other): 29 | """ Returns the concatenation of this transform and other """ 30 | if other is None: 31 | return deepcopy(self) 32 | if isinstance(other, Translation): 33 | x = self.translation.x + other.translation.x 34 | y = self.translation.y + other.translation.y 35 | return Translation(Coord(x, y)) 36 | else: 37 | # return GenericTransform.__add__(self, other) 38 | return __ConvertableTransform__.__add__(self, other) 39 | 40 | def __iadd__(self, other): 41 | """ Concatenates other to this transform. """ 42 | if other is None: 43 | return self 44 | if isinstance(other, Translation): 45 | x = self.translation.x + other.translation.x 46 | y = self.translation.y + other.translation.y 47 | self.translation = Coord(x, y) 48 | return self 49 | else: 50 | # return GenericTransform.__iadd__(self, other) 51 | return __ConvertableTransform__.__iadd__(self, other) 52 | 53 | def __neg__(self): 54 | """ Helper methods which returns the reverse transformation """ 55 | return Translation(Coord(-self.translation.x, -self.translation.y)) 56 | 57 | def is_identity(self): 58 | return ((self.translation.x == 0.0) and (self.translation.y == 0.0)) 59 | 60 | 61 | def shape_translate(shape, translation=(1,0)): 62 | return Translation(translation)(shape) 63 | 64 | 65 | class __TranslationMixin__(object): 66 | 67 | def translate(self, translation=(0,0)): 68 | return self.transform(Translation(translation)) 69 | 70 | def translate_copy(self, position): 71 | return self.transform_copy(Translation(position)) 72 | 73 | 74 | Transformable.mixin(__TranslationMixin__) 75 | 76 | 77 | 78 | 79 | --------------------------------------------------------------------------------