Technology

In every IPKISS Python script or IPKISS Canvas design you will import a process design kit that has a TECHNOLOGY file.

The goal of the technology file is to describe general settings that are stable across several designs that use the same fab.

These technology settings are managed in a tree structure, rooted in an object created by IPKISS in the module ipkiss.technology. Each leaf of this tree we call a technology key or tech key.

Although you are free to add whatever you want to a TECHNOLOGY file the following aspects of your design process are usually described by it.

  • Layers: Contains all the available process layers, drawing pattern purposes, and combinations thereof: ProcessPurposeLayers

  • Rules and metrics: Contains the general settings for the grid on which shapes are discretized, and design rules for different process layers.

  • GDSII settings: Contains GDSII import and export settings.

  • Display settings: Contains settings that are used in visualization routines of IPKISS.

  • Materials: Materials and materials stacks

  • Virtual fabrication settings: Contains the description of the virtual fabrication processes that can transform a GDSII mask in a virtually fabricated structure.

  • Traces: Contains the description of the default waveguides that are used.

  • Grating Couplers: Contains the description of the default grating couplers that are used.

  • Required technology keys: PICAZZO requires a number of technology settings (‘keys’) to be defined in order to work.

In this guide we will illustrate these concepts so that you can build you own technology file.

Note

This guide assumes knowledge of semiconductor process technology and terminology.

Getting started

Creating a basic new design kit technology, that will enable all features in ipkiss3 to work with default parameters, is simple:

from ipkiss import technology

technology.TECHNOLOGY = technology.TechnologyLibrary(name="DEMO_FAB", defaults=True)

IPKISS relies on the definition of a range of technology keys for its proper functioning and tailoring to a specific technology. The defaults argument of TechnologyLibrary ensures that the technology has all the required technology keys for IPKISS to function.

After that, you can then override values that are specific to your technology. For instance, the default GDSII mask grid is 5nm. To create a technology file with a 1nm GDSII grid, change the technology file as follows:

from ipkiss import technology

technology.TECHNOLOGY = TECH = technology.TechnologyLibrary(name="DEMO_FAB", defaults=True)

TECH.METRICS.GRID = 1e-9

Technology structure

General anatomy of a TECH-tree

A technology in IPKISS is built as a TREE of objects of TechnologyTree

TechnologyTree

TechnologyTree

As depicted in the figure above each purple box is object of the TechnologyTree that can contain settings of any kind (depicted in green). Creating your own TECH amounts to building up such a tree and to place the relevant settings in the leaves.

The code excerpt below illustrates this:

from ipkiss.technology import get_technology
from ipkiss.technology.technology import TechnologyTree

TECH = get_technology()
TECH.MYSETTINGS = TechnologyTree()
TECH.MYSETTINGS.SET1 = 10.0
TECH.MYSETTINGS.MYFIRSTSUBJECT = TechnologyTree()
TECH.MYSETTINGS.MYFIRSTSUBJECT.SET1 = "Hello"
TECH.MYSETTINGS.MYFIRSTSUBJECT.SET2 = 300.0

print(TECH.MYSETTINGS.MYFIRSTSUBJECT.SET1)

Technology tree structure

The general tree hierarchy is as follows. PDK developers can add their own subtrees, but the shown tree is the minimum required for IPKISS to work.

TECH
 ├── ADMIN
 ├── METRICS
 ├── PROCESS
 ├── PURPOSE
 ├── PPLAYER
 ├── DISPLAY
 ├── GDSII
 ├── OPENACCESS
 ├── VFABRICATION
 ├── MATERIALS
 ├── MATERIAL_STACKS
 ├── PCELLS
 ├── BLOCKS
 ├── PORT
 ├── TRACE
 ├── WG_DEFAULTS
 ├── WG
 ├── VIAS
 ├── METAL

Technoloy tree keys

There are many settings in the technology tree that can be overridden. We will elaborate over the most important ones.

Name of the technology

When creating a new technology file, you should give it a name:

from ipkiss import technology

__all__ = ["TECH"]


technology.TECHNOLOGY = TECH = technology.TechnologyLibrary(name="SI_FAB", defaults=True)

Layers

Process layers and drawing purposes define the available ProcessLayers, PatternPurpose, and combinations thereof ProcessPurposeLayer

Process Layers

A ProcessLayer describes a process module with a specific function: waveguide, fiber coupler, rib etch, implants, metalization, …

  • ProcessLayer (e.g. “waveguide patterning”) will typically consist of several process steps (e.g. “waveguide litho”, “waveguide etch”, “resist strip”, “metrology”). These steps are not defined here, only the overall process module.

  • A ProcessLayer is not the same as a drawing layer: there can be multiple drawing layers associated with one ProcessLayer, through the use of drawing pattern purposes. E.g. Process Layer WG (Waveguides) can have drawing layers such as “WG.CORE” and “WG.CLADDING”.

  • Each ProcessLayer has a name (e.g. “Waveguides”) and an mnemonic (e.g. “WG”)

The process layers are gathered in the TECH.PROCESS tree.

This is how it is done in the si\_fab technology.

#
# Process layers typically correspond to a single lithographic
# process step in the fabrication of your design
#
# ###############################################################

TECH.PROCESS.SI = ProcessLayer("Unetched silicon", "SI")  # waveguide layer (required)
TECH.PROCESS.SHALLOW = ProcessLayer("Fiber Couplers and Rib Waveguide (shallow etched Si)", "SHALLOW")
TECH.PROCESS.SIN = ProcessLayer("Silicon nitride", "SIN")
TECH.PROCESS.SIN_SHALLOW = ProcessLayer("Thin silicon nitride layer, used for edge couplers", "SIN_SHALLOW")

TECH.PROCESS.HT = ProcessLayer("Heater", "HT")
TECH.PROCESS.M1 = ProcessLayer("Metallization 1", "M1")
TECH.PROCESS.M2 = ProcessLayer("Metallization 2", "M2")
TECH.PROCESS.V12 = ProcessLayer("Via between M1 and M2", "V12")
TECH.PROCESS.N = ProcessLayer("N+ implant", "N")
TECH.PROCESS.P = ProcessLayer("P+ implant", "P")
TECH.PROCESS.GE = ProcessLayer("Germanium", "GE")
TECH.PROCESS.NPLUS = ProcessLayer("N++ implant", "NPLUS")
TECH.PROCESS.PPLUS = ProcessLayer("P++ implant", "PPLUS")
TECH.PROCESS.CON = ProcessLayer("Contact", "CON")

TECH.PROCESS.NONE = ProcessLayer("No specific process", "NONE")


# The following keys are required by ipkiss / picazzo but not used actively by si_fab
TECH.PROCESS.WG = TECH.PROCESS.SI  # Required for ipkiss, picazzo
TECH.PROCESS.RWG = TECH.PROCESS.SHALLOW  # Required by picazzo
TECH.PROCESS.FC = TECH.PROCESS.SHALLOW  # Required by picazzo (grating couplers)

Pattern Purposes

PatternPurpose describe different purposes for drawing on a mask, to discriminate different types of drawing that will end up on the actual mask (e.g. trenches vs holes vs lines) or different types of data which does not or not directly end up on the mask (e.g. exclusion zones, DRC waiver zones, pin recognition, device recognition, …). As a result, pattern purposes are really described with the process engineer in mind, not the designer who starts from functional devices.

  • The PatternPurpose are gathered in the TECH.PURPOSE tree

  • We define PatternPurposes in two ways: either they have a meaning related to the process, more specifically mask polarity and feature type, or they have a more functional meaning.

The default mask drawing related purposes in Ipkiss are divided according to mask polarity: dark field or light field. How that translates into the specific process depends on the lithographic resist tone (positive or negative), which is not considered here. The process engineer who defines the possible combinations between process layers and pattern purposes knows and the designer should not “care”.

  • Every PatternPurpose has a name (e.g. “Dark-field Line”) and an extension (e.g. “DFLIN”).

This is how we define for Light Field pattern in the si\_fab tech.

#
# Layer Purposes indicate what the meaning is of a pattern on a
# given process layer. e.g. a Line, a documentation, ...
#
# ###############################################################

TECH.PURPOSE.DRAWING = PatternPurpose(name="Drawing", extension="DRW")
TECH.PURPOSE.DRWSUB = PatternPurpose(name="Subtracted drawing", extension="DRWSUB")

TECH.PURPOSE.ERROR = PatternPurpose(name="Error", extension="ERR", doc="Errors")
TECH.PURPOSE.PINREC = PatternPurpose(name="Pin recognition", extension="PIN", doc="Pin marker for extraction")
TECH.PURPOSE.TRACE = PatternPurpose(name="Trace", extension="TRC", doc="Control shape of trace")
TECH.PURPOSE.TEXT = PatternPurpose(name="Text", extension="TXT")

Process-purpose layers

The process engineer defines the possible combinations between ProcessLayer and PatternPurposes. Some ProcessLayers may only have drawings in one PatternPurpose, whereas other ProcessLayer may have many PatternPurpose associated. Each (ProcessLayer, PatternPurpose) pair is defined as a ProcessPurposeLayer (PPLayer).

We make the translation between the process engineer and the designer using these ProcessPurposeLayer: whereas the ProcessLayers and specifically the PatternPurpose make more sense to the process engineer, we give the ProcessPurposeLayer names and descriptions which make functional sense to the designer (e.g. “waveguide core”, “fiber coupler trenches”, “exclusion zone”, “implanted area”)

#
# These are the predefined layer pairs of a Process and a Purpose
# that are allowed in your technology.
#
# ###############################################################

TECH.PPLAYER.SI = PPLayer(TECH.PROCESS.SI, TECH.PURPOSE.DRAWING, name="SI")
TECH.PPLAYER.SI_TRENCH = PPLayer(TECH.PROCESS.SI, TECH.PURPOSE.DRWSUB, name="SI_TRENCH")
TECH.PPLAYER.SI_CLADDING = PPLayer(TECH.PROCESS.SI, TECH.PURPOSE.UNUSED, name="SI_CLADDING")
TECH.PPLAYER.TEXT = PPLayer(TECH.PROCESS.SI, TECH.PURPOSE.TEXT, name="TEXT")
TECH.PPLAYER.SHALLOW = PPLayer(TECH.PROCESS.SHALLOW, TECH.PURPOSE.DRAWING, name="SHALLOW")
TECH.PPLAYER.SHALLOW_TRENCH = PPLayer(TECH.PROCESS.SHALLOW, TECH.PURPOSE.DRWSUB, name="SHALLOW_TRENCH")
TECH.PPLAYER.SIN = PPLayer(TECH.PROCESS.SIN, TECH.PURPOSE.DRAWING, name="SIN")
TECH.PPLAYER.SIN_CLADDING = PPLayer(TECH.PROCESS.SIN, TECH.PURPOSE.UNUSED, name="SIN_CLADDING")
TECH.PPLAYER.SIN_SHALLOW = PPLayer(TECH.PROCESS.SIN_SHALLOW, TECH.PURPOSE.DRAWING, name="SIN_SHALLOW")
TECH.PPLAYER.SIN_SHALLOW_TRENCH = PPLayer(TECH.PROCESS.SIN_SHALLOW, TECH.PURPOSE.DRWSUB, name="SIN_SHALLOW_TRENCH")
TECH.PPLAYER.GE = PPLayer(TECH.PROCESS.GE, TECH.PURPOSE.DRAWING, name="GE")

TECH.PPLAYER.HT = PPLayer(TECH.PROCESS.HT, TECH.PURPOSE.DRAWING, name="HT")
TECH.PPLAYER.M1 = PPLayer(TECH.PROCESS.M1, TECH.PURPOSE.DRAWING, name="M1")
TECH.PPLAYER.M2 = PPLayer(TECH.PROCESS.M2, TECH.PURPOSE.DRAWING, name="M2")
TECH.PPLAYER.V12 = PPLayer(TECH.PROCESS.V12, TECH.PURPOSE.DRAWING, name="V12")

TECH.PPLAYER.N = PPLayer(TECH.PROCESS.N, TECH.PURPOSE.DRAWING, name="N_DRW")
TECH.PPLAYER.NPLUS = PPLayer(TECH.PROCESS.NPLUS, TECH.PURPOSE.DRAWING, name="NPLUS_DRW")
TECH.PPLAYER.P = PPLayer(TECH.PROCESS.P, TECH.PURPOSE.DRAWING, name="P_DRW")
TECH.PPLAYER.PPLUS = PPLayer(TECH.PROCESS.PPLUS, TECH.PURPOSE.DRAWING, name="PPLUS_DRW")

TECH.PPLAYER.PINREC = PPLayer(TECH.PROCESS.NONE, TECH.PURPOSE.PINREC, name="PINREC")  # Used in ports
# TODO: Update si_fab components to not use this layer
TECH.PPLAYER.NONE = PPLayer(TECH.PROCESS.NONE, TECH.PURPOSE.UNUSED, name="NONE")


TECH.PPLAYER.CON = PPLayer(TECH.PROCESS.CON, TECH.PURPOSE.DRAWING, name="CON_DRW")  # Contact layer
TECH.PPLAYER.DOC = PPLayer(TECH.PROCESS.NONE, TECH.PURPOSE.DOC, name="DOC")  # Design documentation

# Routing layers (for routing in EDA tools)
TECH.PPLAYER.WIRE_TRACE = PPLayer(TECH.PROCESS.SI, TECH.PURPOSE.TRACE, name="WIRE_TRC")
TECH.PPLAYER.RIB_TRACE = PPLayer(TECH.PROCESS.SHALLOW, TECH.PURPOSE.TRACE, name="RIB_TRC")


# Required by ipkiss/picazzo
TECH.PPLAYER.M1.LINE = TECH.PPLAYER.M1  # Required by ipkiss
TECH.PPLAYER.M2.LINE = TECH.PPLAYER.M2  # Required by ipkiss
TECH.PPLAYER.V12.PILLAR = TECH.PPLAYER.V12  # Required by ipkiss
TECH.PPLAYER.WG = TechnologyTree()

Note

This is not the same as GDSII layers and datatypes. The mapping between (ProcessLayer, PatternPurpose) pairs and GDSII (Layer, Datatype) pairs is defined in gdsii.py

Note

It is important to add all the PPlayers that are associated with a single process in the same tree. For example TECH.PPLAYER.WG should contain all the PPlayers with TECH.PROCESS.WG as process. The is required for virtual fabrication to work.

Rules and Metrics

Metrics are setting related to standard distance units and discretization settings. You may want to override the mask grid or the default bend fracturing discretization angle.

Many components in PICAZZO are built based on high level design rules. These used as defaults as to ensure sensible defaults in PICAZZO but could be useful for your own components as well.

from ipkiss.technology import get_technology
from ipkiss.technology.technology import TechnologyTree
from ipkiss.geometry.shapes.basic import ShapeRectangle

TECH = get_technology()

#####################
# MASK GRID SETTINGS
#####################
TECH.METRICS.GRID = 1e-9  # Default manufacturing grid, in m
TECH.METRICS.ANGLE_STEP = 1.0  # Default angle step used in curve discretisation, in degrees


####################################################################
# WG SETTINGS
####################################################################

TECH.WIREWG = TechnologyTree()
TECH.WIREWG.WIRE_WIDTH = 0.45
TECH.WIREWG.TRENCH_WIDTH = 2.5
TECH.WIREWG.CLADDING_WIDTH = TECH.WIREWG.WIRE_WIDTH + 2 * TECH.WIREWG.TRENCH_WIDTH

TECH.WIREWG.BEND_RADIUS = 5.0
TECH.WIREWG.SPACING = 2.0
TECH.WIREWG.DC_SPACING = TECH.WIREWG.WIRE_WIDTH + 0.18
TECH.WIREWG.SHORT_STRAIGHT = 2.0
TECH.WIREWG.SHORT_TRANSITION_LENGTH = 5.0
TECH.WIREWG.SHORT_TAPER_LENGTH = TECH.WIREWG.SHORT_TRANSITION_LENGTH
TECH.WIREWG.OVERLAP_EXTENSION = 0.020
TECH.WIREWG.OVERLAP_TRENCH = 0.010
TECH.WIREWG.EXPANDED_WIDTH = 0.8
TECH.WIREWG.EXPANDED_TAPER_LENGTH = 3.0
TECH.WIREWG.EXPANDED_STRAIGHT = 5.0
TECH.WIREWG.ANGLE_STEP = 1.0
TECH.WIREWG.SLOT_WIDTH = 0.15
TECH.WIREWG.SLOTTED_WIRE_WIDTH = 0.7

TECH.RIBWG = TechnologyTree()
TECH.RIBWG.RIB_WIDTH = 0.45
TECH.RIBWG.TRENCH_WIDTH = 2.0
TECH.RIBWG.CLADDING_WIDTH = TECH.RIBWG.RIB_WIDTH + 2 * TECH.RIBWG.TRENCH_WIDTH
TECH.RIBWG.BEND_RADIUS = 15.0
TECH.RIBWG.SPACING = 5.0

TECH.SINWG = TechnologyTree()
TECH.SINWG.WIRE_WIDTH = 0.9
TECH.SINWG.TRENCH_WIDTH = 6.0
TECH.SINWG.CLADDING_WIDTH = TECH.RIBWG.RIB_WIDTH + 2 * TECH.RIBWG.TRENCH_WIDTH
TECH.SINWG.BEND_RADIUS = 60.0
TECH.SINWG.SPACING = 10.0

TECH.WG = TECH.WIREWG  # Required for ipkiss waveguides

#################################
### Contact and metal settings
#################################

TECH.CON = TechnologyTree()
TECH.CON.WIDTH = 0.5


TECH.METAL.LINE_WIDTH = 1.0  # Default line width of metal wire
TECH.METAL.DEFAULT_PROCESS = TECH.PROCESS.M1  # Default process for metal wiring

TECH.M1 = TechnologyTree()
TECH.M1.LINE_WIDTH = TECH.METAL.LINE_WIDTH
TECH.M2 = TechnologyTree()
TECH.M2.LINE_WIDTH = TECH.METAL.LINE_WIDTH

TECH.V12 = TechnologyTree()
TECH.V12.WIDTH = 0.5
TECH.V12.TOP_SHAPE = TECH.VIAS.DEFAULT.TOP_SHAPE
TECH.V12.VIA_SHAPE = TECH.VIAS.DEFAULT.VIA_SHAPE
TECH.V12.BOTTOM_SHAPE = TECH.VIAS.DEFAULT.BOTTOM_SHAPE
TECH.V12.DEFAULT_VIA_PITCH = (0.6, 0.6)

# Default bottom shape (M1) for a via
TECH.VIAS.DEFAULT.TOP_SHAPE = ShapeRectangle(box_size=(0.6, 0.6))
TECH.VIAS.DEFAULT.VIA_SHAPE = ShapeRectangle(box_size=(0.5, 0.5))  # Default via shape
TECH.VIAS.DEFAULT.BOTTOM_SHAPE = ShapeRectangle(box_size=(0.6, 0.6))  # Default top shape (M2) for a via


TECH.BONDPAD = TechnologyTree()
TECH.BONDPAD.M1_SIZE = (50.0, 50.0)
TECH.BONDPAD.M2_SIZE = (50.0, 50.0)
TECH.BONDPAD.VIA_PITCH = (2.0, 2.0)

# At the moment, minimum line and space are specified on a global level, not per layer.
TECH.TECH = TechnologyTree()
TECH.TECH.MINIMUM_LINE = 0.120
TECH.TECH.MINIMUM_SPACE = 0.120

GDSII

The TECH tree contains GDSII import and export settings from IPKISS to GDSII. The settings make sure that there is a mapping between each PPlayer (ProcessLayer, PatternPurpose) in IPKISS and (Layer, Datatype) in GDSII.

In addition, several settings and filters ensure that we can export GDSII files compatible with the back-end maskprep tools used. These are made by default and we don’t need to touch.

GDSII layer tables

TECH.GDSII.LAYERTABLE: maps (ProcessLayer, PatternPurpose) and GDSII (Layer, Datatype) pairs Only these layers are exported/imported. Others are ignored upon export, or an error is raised upon import.

GenericGdsiiPPLayerOutputMap and GenericGdsiiPPLayerInputMap are used to achieve this mapping (usually the same map is used).

In the silicon photonics tech this is done like so:


TECH.GDSII.LAYERTABLE = {
    # (ProcessLayer, PatternPurpose) : (GDSIILayer, GDSIIDatatype)
    (TECH.PROCESS.SI, TECH.PURPOSE.DRAWING): (1, 0),
    (TECH.PROCESS.SI, TECH.PURPOSE.TEXT): (1, 1),
    (TECH.PROCESS.SI, TECH.PURPOSE.DRWSUB): (1, 2),
    (TECH.PROCESS.SHALLOW, TECH.PURPOSE.DRAWING): (2, 0),
    (TECH.PROCESS.SHALLOW, TECH.PURPOSE.DRWSUB): (2, 2),
    (TECH.PROCESS.SIN, TECH.PURPOSE.DRAWING): (3, 0),
    (TECH.PROCESS.SIN_SHALLOW, TECH.PURPOSE.DRAWING): (4, 0),
    (TECH.PROCESS.SIN_SHALLOW, TECH.PURPOSE.DRWSUB): (4, 2),
    (TECH.PROCESS.N, TECH.PURPOSE.DRAWING): (5, 0),
    (TECH.PROCESS.NPLUS, TECH.PURPOSE.DRAWING): (6, 0),
    (TECH.PROCESS.P, TECH.PURPOSE.DRAWING): (7, 0),
    (TECH.PROCESS.PPLUS, TECH.PURPOSE.DRAWING): (8, 0),
    (TECH.PROCESS.CON, TECH.PURPOSE.DRAWING): (11, 0),
    (TECH.PROCESS.HT, TECH.PURPOSE.DRAWING): (15, 0),
    (TECH.PROCESS.M1, TECH.PURPOSE.DRAWING): (20, 0),
    (TECH.PROCESS.V12, TECH.PURPOSE.DRAWING): (21, 0),
    (TECH.PROCESS.M2, TECH.PURPOSE.DRAWING): (22, 0),
    (TECH.PROCESS.GE, TECH.PURPOSE.DRAWING): (30, 0),
    (TECH.PROCESS.NONE, TECH.PURPOSE.DOC): (50, 0),
    (TECH.PROCESS.NONE, TECH.PURPOSE.ERROR): (50, 1),
    (TECH.PROCESS.SI, TECH.PURPOSE.UNUSED): (50, 2),
    (TECH.PROCESS.SIN, TECH.PURPOSE.UNUSED): (50, 12),
    (TECH.PROCESS.NONE, TECH.PURPOSE.PINREC): (50, 3),
}

# GDSII export map - required
TECH.GDSII.EXPORT_LAYER_MAP = GenericGdsiiPPLayerOutputMap(
    pplayer_map=TECH.GDSII.LAYERTABLE, ignore_undefined_mappings=False
)
TECH.GDSII.IMPORT_LAYER_MAP = GenericGdsiiPPLayerInputMap(pplayer_map=TECH.GDSII.LAYERTABLE)

Display Settings

IPKISS contains several visualization functions such as visualize. The display settings and their association with the ProcessPurposeLayer for visualization is defined in the TECH.DISPLAY tree. The display settings are set in an object of the DisplayStyle. Each ProcessPurposeLayer that needs to be visualized can be then be associated with a DisplayStyle to form a DisplayStyleSet.

The DisplayStyleSet is then added to TECH.DISPLAY.DEFAULT_DISPLAY_STYLE_SET

Here is a simplified example - the same technique is used in the silicon photonics technology.

from ipkiss.technology import get_technology
from ipkiss.technology.technology import TechnologyTree
from ipkiss.visualisation.display_style.display_style import DisplayStyle, DisplayStyleSet
from ipkiss.visualisation.display_style import color
from ipkiss.process import PPLayer

TECH = get_technology()

TECH.DISPLAY.PREDEFINED_STYLE_SETS = TechnologyTree()

# colorful purpose map
DISPLAY_WG = DisplayStyle(color = color.COLOR_GREEN, alpha = 0.5, edgewidth = 1.0)
DISPLAY_WHITE = DisplayStyle(color=color.COLOR_WHITE, alpha=1.0, edgewidth=1.0)
DISPLAY_IGNORE = DisplayStyle(color=color.COLOR_WHITE, alpha=0.0, edgewidth=0.0)
DISPLAY_DOC = DisplayStyle(color=color.COLOR_RED, edgecolor=color.COLOR_RED, alpha=0.2, edgewidth=1.0)

style_set = DisplayStyleSet()
style_set.background = DISPLAY_WHITE

style_set += [(TECH.PPLAYER.WG.CORE, DISPLAY_WG),
              (TECH.PPLAYER.WG.CLADDING, DISPLAY_IGNORE),
              (TECH.PPLAYER.NONE.DOC, DISPLAY_DOC),
             ]

TECH.DISPLAY.PREDEFINED_STYLE_SETS.PURPOSE_HIGHLIGHT  = style_set
TECH.DISPLAY.DEFAULT_DISPLAY_STYLE_SET = style_set

TECH.DISPLAY = TechDisplayTree()

Design Rules

Materials

Materials and their settings are added using two trees in the TECH tree.

TECH.MATERIALS

Here actual physical materials are defined. This is done using the class i3.Material that are added to a i3.MaterialFactory. Each material is associate with a DisplayStyle and with a boolean that determines if it is a solid or not.

TECH.MATERIALS = MaterialFactory()
TECH.MATERIALS.AIR = Air(name="air", display_style=DisplayStyle(color=color.COLOR_BLUE_CRAYOLA, alpha=0.1), solid=False)
TECH.MATERIALS.SILICON = Silicon(name="Silicon", display_style=DisplayStyle(color=COLOR_UGLY_PINK))
TECH.MATERIALS.SILICON_NITRIDE = SiNitride(
    name="Silicon Nitride", display_style=DisplayStyle(color=COLOR_DARK_BABY_BLUE)
)
TECH.MATERIALS.SILICON_OXIDE = SiOxide(
    name="Silicon Oxide", display_style=DisplayStyle(color=COLOR_BABY_BLUE, alpha=0.2)
)
TECH.MATERIALS.P_SILICON = Material(name="P+ Silicon", display_style=DisplayStyle(color=COLOR_LIGHT_RED))
TECH.MATERIALS.N_SILICON = Material(name="N+ Silicon", display_style=DisplayStyle(color=COLOR_LIGHT_BLUE))
TECH.MATERIALS.PPLUS_SILICON = Material(name="P++-Silicon", display_style=DisplayStyle(color=COLOR_DARK_RED))
TECH.MATERIALS.NPLUS_SILICON = Material(name="N++-Silicon", display_style=DisplayStyle(color=COLOR_DARK_BLUE))
TECH.MATERIALS.GERMANIUM = Material(name="Germanium", display_style=DisplayStyle(color=color.COLOR_CHERRY))
TECH.MATERIALS.SILICIDE = Material(name="Silicide", display_style=DisplayStyle(color=color.COLOR_COPPER))
TECH.MATERIALS.TUNGSTEN = Material(name="Tungsten", display_style=DisplayStyle(color=COLOR_TUNGSTEN))
TECH.MATERIALS.TIN = Material(name="Titanium Nitride", display_style=DisplayStyle(color=COLOR_TIN))
TECH.MATERIALS.COPPER = Material(name="Copper", display_style=DisplayStyle(color=COLOR_COPPER_BROWN))
TECH.MATERIALS.ALUMINIUM = Material(name="Aluminium", display_style=DisplayStyle(color=COLOR_AL_GRAY))

TECH.MATERIALS.SILICON.epsilon = 3.47643493603882**2
TECH.MATERIALS.SILICON_NITRIDE.epsilon = 2.025742**2
TECH.MATERIALS.SILICON_OXIDE.epsilon = 1.444023622**2
TECH.MATERIALS.AIR.epsilon = 1.0

####################################################################
# MATERIALS STACKS
####################################################################

TECH.MATERIAL_STACKS

Here actual stack of materials are defined. Material stacks are build by a sequence of a material with a height. These stacks are then used for virtual fabrication. In analogy with Materials, you create i3.MaterialStack that are added to a i3.MaterialStackFactory. Each MaterialStack is associate with a DisplayStyle.

Note

All the material stacks in a single factory must have the same height.

TECH.MATERIAL_STACKS = MaterialStackFactory()

# Thicknesses of the differents layers

MSTACK_SOI_SILICON_OXIDE_HEIGHT = 1.00
MSTACK_SOI_SILICON_HEIGHT = 0.22
MSTACK_SOI_SIN_HEIGHT = 0.300
MSTACK_SOI_SIN_RIB_HEIGHT = 0.150
MSTACK_SOI_RIB_HEIGHT = 0.100

# always have 0.5 contact thickness in total
MSTACK_GAP_HEIGHT = 0.15
MSTACK_CON1_HEIGHT = 1.0
MSTACK_MHT_HEIGHT = 0.15
MSTACK_M1_HEIGHT = 0.5
MSTACK_IMD12_HEIGHT = 1.0
MSTACK_M2_HEIGHT = 0.5

MSTACK_CON_HEIGHT = MSTACK_CON1_HEIGHT + MSTACK_GAP_HEIGHT + MSTACK_SOI_SIN_HEIGHT

# Material stacks in the Silicon layer
TECH.MATERIAL_STACKS.MSTACK_SOI_INVALID = MaterialStack(
    name="INVALID",
    materials_heights=[
        (TECH.MATERIALS.AIR, MSTACK_SOI_SILICON_OXIDE_HEIGHT),
        (TECH.MATERIALS.AIR, MSTACK_SOI_SILICON_HEIGHT),
        (TECH.MATERIALS.AIR, MSTACK_CON_HEIGHT),
    ],
    display_style=DisplayStyle(color=color.COLOR_WHITE),
)

TECH.MATERIAL_STACKS.MSTACK_SOI_OX = MaterialStack(
    name="Oxide",
    materials_heights=[
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_SOI_SILICON_OXIDE_HEIGHT),
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_SOI_SILICON_HEIGHT),
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_CON_HEIGHT),
    ],
    display_style=DisplayStyle(color=COLOR_BABY_BLUE),
)

TECH.MATERIAL_STACKS.MSTACK_SOI_SI = MaterialStack(
    name=f"{int(MSTACK_SOI_SILICON_HEIGHT * 1000)}nm Si",
    materials_heights=[
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_SOI_SILICON_OXIDE_HEIGHT),
        (TECH.MATERIALS.SILICON, MSTACK_SOI_SILICON_HEIGHT),
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_CON_HEIGHT),
    ],
    display_style=DisplayStyle(color=COLOR_DARK_UGLY_PINK),
)

TECH.MATERIAL_STACKS.MSTACK_SOI_SIN = MaterialStack(
    name=f"{int(MSTACK_SOI_SIN_HEIGHT * 1000)}nm SiN",
    materials_heights=[
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_SOI_SILICON_OXIDE_HEIGHT + MSTACK_SOI_SILICON_HEIGHT + MSTACK_GAP_HEIGHT),
        (TECH.MATERIALS.SILICON_NITRIDE, MSTACK_SOI_SIN_HEIGHT),
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_CON1_HEIGHT),
    ],
    display_style=DisplayStyle(color=COLOR_DARK_BABY_BLUE),
)

TECH.MATERIAL_STACKS.MSTACK_SOI_SI_SIN = MaterialStack(
    name=f" {int(MSTACK_SOI_SILICON_HEIGHT * 1000)} nm Si + {int(MSTACK_SOI_SIN_HEIGHT * 1000)}nm SiN",
    materials_heights=[
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_SOI_SILICON_OXIDE_HEIGHT),
        (TECH.MATERIALS.SILICON, MSTACK_SOI_SILICON_HEIGHT),
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_GAP_HEIGHT),
        (TECH.MATERIALS.SILICON_NITRIDE, MSTACK_SOI_SIN_HEIGHT),
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_CON1_HEIGHT),
    ],
    display_style=DisplayStyle(color=COLOR_DARK_BABY_BLUE),
)

TECH.MATERIAL_STACKS.MSTACK_SOI_RIB = MaterialStack(
    name=f"{int(MSTACK_SOI_RIB_HEIGHT * 1000)}nm Si",
    materials_heights=[
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_SOI_SILICON_OXIDE_HEIGHT),
        (TECH.MATERIALS.SILICON, MSTACK_SOI_RIB_HEIGHT),
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_SOI_SILICON_HEIGHT - MSTACK_SOI_RIB_HEIGHT + MSTACK_CON_HEIGHT),
    ],
    display_style=DisplayStyle(color=COLOR_LIGHT_UGLY_PINK),
)

TECH.MATERIAL_STACKS.MSTACK_SOI_SIN_RIB = MaterialStack(
    name=f"{int(MSTACK_SOI_SIN_RIB_HEIGHT * 1000)}nm SiN",
    materials_heights=[
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_SOI_SILICON_OXIDE_HEIGHT + MSTACK_SOI_SILICON_HEIGHT + MSTACK_GAP_HEIGHT),
        (TECH.MATERIALS.SILICON_NITRIDE, MSTACK_SOI_SIN_RIB_HEIGHT),
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_SOI_SIN_HEIGHT - MSTACK_SOI_SIN_RIB_HEIGHT + MSTACK_CON1_HEIGHT),
    ],
    display_style=DisplayStyle(color=COLOR_LIGHT_UGLY_PINK),
)

TECH.MATERIAL_STACKS.MSTACK_SOI_RIB_SIN = MaterialStack(
    name=f"{int(MSTACK_SOI_RIB_HEIGHT * 1000)}nm Si + {int(MSTACK_SOI_SIN_HEIGHT * 1000)}nm SiN",
    materials_heights=[
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_SOI_SILICON_OXIDE_HEIGHT),
        (TECH.MATERIALS.SILICON, MSTACK_SOI_RIB_HEIGHT),
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_SOI_SILICON_HEIGHT - MSTACK_SOI_RIB_HEIGHT + MSTACK_GAP_HEIGHT),
        (TECH.MATERIALS.SILICON_NITRIDE, MSTACK_SOI_SIN_HEIGHT),
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_CON1_HEIGHT),
    ],
    display_style=DisplayStyle(color=COLOR_LIGHT_UGLY_PINK),
)

TECH.MATERIAL_STACKS.MSTACK_SOI_N = MaterialStack(
    name=f"{int(MSTACK_SOI_SILICON_HEIGHT * 1000)}nm N+ implant",
    materials_heights=[
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_SOI_SILICON_OXIDE_HEIGHT),
        (TECH.MATERIALS.N_SILICON, MSTACK_SOI_SILICON_HEIGHT),
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_CON_HEIGHT),
    ],
    display_style=DisplayStyle(color=color.COLOR_BLUE),
)

TECH.MATERIAL_STACKS.MSTACK_SOI_N_SIN = MaterialStack(
    name=f"{int(MSTACK_SOI_SILICON_HEIGHT * 1000)}nm N+ implant + {int(MSTACK_SOI_SIN_HEIGHT * 1000)}nm SiN",
    materials_heights=[
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_SOI_SILICON_OXIDE_HEIGHT),
        (TECH.MATERIALS.N_SILICON, MSTACK_SOI_SILICON_HEIGHT),
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_GAP_HEIGHT),
        (TECH.MATERIALS.SILICON_NITRIDE, MSTACK_SOI_SIN_HEIGHT),
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_CON1_HEIGHT),
    ],
    display_style=DisplayStyle(color=color.COLOR_BLUE),
)

TECH.MATERIAL_STACKS.MSTACK_SOI_RIB_N = MaterialStack(
    name=f"{int(MSTACK_SOI_RIB_HEIGHT * 1000)}nm N+ implant",
    materials_heights=[
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_SOI_SILICON_OXIDE_HEIGHT),
        (TECH.MATERIALS.N_SILICON, MSTACK_SOI_RIB_HEIGHT),
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_SOI_SILICON_HEIGHT + MSTACK_CON_HEIGHT - MSTACK_SOI_RIB_HEIGHT),
    ],
    display_style=DisplayStyle(color=COLOR_LIGHT_BLUE),
)

TECH.MATERIAL_STACKS.MSTACK_SOI_RIB_N_SIN = MaterialStack(
    name=f"{int(MSTACK_SOI_RIB_HEIGHT * 1000)}nm N+ implant + {int(MSTACK_SOI_SIN_HEIGHT * 1000)}nm SiN",
    materials_heights=[
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_SOI_SILICON_OXIDE_HEIGHT),
        (TECH.MATERIALS.N_SILICON, MSTACK_SOI_RIB_HEIGHT),
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_SOI_SILICON_HEIGHT - MSTACK_SOI_RIB_HEIGHT + MSTACK_GAP_HEIGHT),
        (TECH.MATERIALS.SILICON_NITRIDE, MSTACK_SOI_SIN_HEIGHT),
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_CON1_HEIGHT),
    ],
    display_style=DisplayStyle(color=COLOR_LIGHT_BLUE),
)

TECH.MATERIAL_STACKS.MSTACK_SOI_NPLUS = MaterialStack(
    name=f"{int(MSTACK_SOI_RIB_HEIGHT * 1000)}nm N++ implant",
    materials_heights=[
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_SOI_SILICON_OXIDE_HEIGHT),
        (TECH.MATERIALS.NPLUS_SILICON, MSTACK_SOI_RIB_HEIGHT),
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_SOI_SILICON_HEIGHT - MSTACK_SOI_RIB_HEIGHT + MSTACK_CON_HEIGHT),
    ],
    display_style=DisplayStyle(color=COLOR_DARK_BLUE),
)

TECH.MATERIAL_STACKS.MSTACK_SOI_NPLUS_SIN = MaterialStack(
    name=f"{int(MSTACK_SOI_RIB_HEIGHT * 1000)}nm N++ implant + {int(MSTACK_SOI_SIN_HEIGHT * 1000)}nm SiN",
    materials_heights=[
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_SOI_SILICON_OXIDE_HEIGHT),
        (TECH.MATERIALS.NPLUS_SILICON, MSTACK_SOI_RIB_HEIGHT),
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_SOI_SILICON_HEIGHT - MSTACK_SOI_RIB_HEIGHT + MSTACK_GAP_HEIGHT),
        (TECH.MATERIALS.SILICON_NITRIDE, MSTACK_SOI_SIN_HEIGHT),
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_CON1_HEIGHT),
    ],
    display_style=DisplayStyle(color=COLOR_DARK_BLUE),
)

TECH.MATERIAL_STACKS.MSTACK_SOI_NPLUS_CON = MaterialStack(
    name=f"{int(MSTACK_SOI_RIB_HEIGHT * 1000)}nm N++ implant + Contact",
    materials_heights=[
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_SOI_SILICON_OXIDE_HEIGHT),
        (TECH.MATERIALS.NPLUS_SILICON, MSTACK_SOI_RIB_HEIGHT),
        (TECH.MATERIALS.TUNGSTEN, MSTACK_SOI_SILICON_HEIGHT - MSTACK_SOI_RIB_HEIGHT + MSTACK_CON_HEIGHT),
    ],
    display_style=DisplayStyle(color=COLOR_TUNGSTEN),
)

TECH.MATERIAL_STACKS.MSTACK_SOI_P = MaterialStack(
    name=f"{int(MSTACK_SOI_SILICON_HEIGHT * 1000)}nm P+ implant",
    materials_heights=[
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_SOI_SILICON_OXIDE_HEIGHT),
        (TECH.MATERIALS.P_SILICON, MSTACK_SOI_SILICON_HEIGHT),
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_CON_HEIGHT),
    ],
    display_style=DisplayStyle(color=color.COLOR_RED),
)

TECH.MATERIAL_STACKS.MSTACK_SOI_P_SIN = MaterialStack(
    name=f"{int(MSTACK_SOI_SILICON_HEIGHT * 1000)}nm P+ implant + {int(MSTACK_SOI_SIN_HEIGHT * 1000)}nm SiN",
    materials_heights=[
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_SOI_SILICON_OXIDE_HEIGHT),
        (TECH.MATERIALS.P_SILICON, MSTACK_SOI_SILICON_HEIGHT),
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_GAP_HEIGHT),
        (TECH.MATERIALS.SILICON_NITRIDE, MSTACK_SOI_SIN_HEIGHT),
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_CON1_HEIGHT),
    ],
    display_style=DisplayStyle(color=color.COLOR_RED),
)

TECH.MATERIAL_STACKS.MSTACK_SOI_RIB_P = MaterialStack(
    name=f"{int(MSTACK_SOI_RIB_HEIGHT * 1000)}nm P+ implant",
    materials_heights=[
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_SOI_SILICON_OXIDE_HEIGHT),
        (TECH.MATERIALS.P_SILICON, MSTACK_SOI_RIB_HEIGHT),
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_SOI_SILICON_HEIGHT - MSTACK_SOI_RIB_HEIGHT + MSTACK_CON_HEIGHT),
    ],
    display_style=DisplayStyle(color=COLOR_LIGHT_RED),
)

TECH.MATERIAL_STACKS.MSTACK_SOI_RIB_P_SIN = MaterialStack(
    name=f"{int(MSTACK_SOI_RIB_HEIGHT * 1000)}nm P+ implant + {int(MSTACK_SOI_SIN_HEIGHT * 1000)}nm SiN",
    materials_heights=[
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_SOI_SILICON_OXIDE_HEIGHT),
        (TECH.MATERIALS.P_SILICON, MSTACK_SOI_RIB_HEIGHT),
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_SOI_SILICON_HEIGHT - MSTACK_SOI_RIB_HEIGHT + MSTACK_GAP_HEIGHT),
        (TECH.MATERIALS.SILICON_NITRIDE, MSTACK_SOI_SIN_HEIGHT),
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_CON1_HEIGHT),
    ],
    display_style=DisplayStyle(color=COLOR_LIGHT_RED),
)

TECH.MATERIAL_STACKS.MSTACK_SOI_PPLUS = MaterialStack(
    name=f"{int(MSTACK_SOI_RIB_HEIGHT * 1000)}nm P++ implant",
    materials_heights=[
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_SOI_SILICON_OXIDE_HEIGHT),
        (TECH.MATERIALS.PPLUS_SILICON, MSTACK_SOI_RIB_HEIGHT),
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_SOI_SILICON_HEIGHT - MSTACK_SOI_RIB_HEIGHT + MSTACK_CON_HEIGHT),
    ],
    display_style=DisplayStyle(color=COLOR_DARK_RED),
)

TECH.MATERIAL_STACKS.MSTACK_SOI_PPLUS_SIN = MaterialStack(
    name=f"{int(MSTACK_SOI_RIB_HEIGHT * 1000)}nm P++ implant + {int(MSTACK_SOI_SIN_HEIGHT * 1000)}nm SiN",
    materials_heights=[
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_SOI_SILICON_OXIDE_HEIGHT),
        (TECH.MATERIALS.PPLUS_SILICON, MSTACK_SOI_RIB_HEIGHT),
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_SOI_SILICON_HEIGHT - MSTACK_SOI_RIB_HEIGHT + MSTACK_GAP_HEIGHT),
        (TECH.MATERIALS.SILICON_NITRIDE, MSTACK_SOI_SIN_HEIGHT),
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_CON1_HEIGHT),
    ],
    display_style=DisplayStyle(color=COLOR_DARK_RED),
)

TECH.MATERIAL_STACKS.MSTACK_SOI_PPLUS_CON = MaterialStack(
    name=f"{int(MSTACK_SOI_RIB_HEIGHT * 1000)}nm P++ implant + Contact",
    materials_heights=[
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_SOI_SILICON_OXIDE_HEIGHT),
        (TECH.MATERIALS.PPLUS_SILICON, MSTACK_SOI_RIB_HEIGHT),
        (TECH.MATERIALS.TUNGSTEN, MSTACK_SOI_SILICON_HEIGHT - MSTACK_SOI_RIB_HEIGHT + MSTACK_CON_HEIGHT),
    ],
    display_style=DisplayStyle(color=COLOR_TUNGSTEN),
)

# Material stacks in the metal1 and heater layers
TECH.MATERIAL_STACKS.MSTACK_METAL_DIEL = MaterialStack(
    name="BEOL Oxide",
    materials_heights=[(TECH.MATERIALS.SILICON_OXIDE, MSTACK_M1_HEIGHT + MSTACK_MHT_HEIGHT)],
    display_style=DisplayStyle(color=COLOR_BABY_BLUE),
)

TECH.MATERIAL_STACKS.MSTACK_METAL_M1 = MaterialStack(
    name="M1",
    materials_heights=[(TECH.MATERIALS.SILICON_OXIDE, MSTACK_MHT_HEIGHT), (TECH.MATERIALS.ALUMINIUM, MSTACK_M1_HEIGHT)],
    display_style=DisplayStyle(color=COLOR_AL_GRAY),
)

TECH.MATERIAL_STACKS.MSTACK_METAL_MHT = MaterialStack(
    name="MHT",
    materials_heights=[(TECH.MATERIALS.TIN, MSTACK_MHT_HEIGHT), (TECH.MATERIALS.SILICON_OXIDE, MSTACK_M1_HEIGHT)],
    display_style=DisplayStyle(color=COLOR_TIN),
)

TECH.MATERIAL_STACKS.MSTACK_METAL_M1_MHT = MaterialStack(
    name="M1_MHT",
    materials_heights=[(TECH.MATERIALS.TIN, MSTACK_MHT_HEIGHT), (TECH.MATERIALS.ALUMINIUM, MSTACK_M1_HEIGHT)],
    display_style=DisplayStyle(color=COLOR_AL_GRAY),
)

TECH.MATERIAL_STACKS.MSTACK_METAL_M1_CON = MaterialStack(
    name="M1_CON",
    materials_heights=[(TECH.MATERIALS.TUNGSTEN, MSTACK_MHT_HEIGHT), (TECH.MATERIALS.ALUMINIUM, MSTACK_M1_HEIGHT)],
    display_style=DisplayStyle(color=COLOR_TUNGSTEN),
)

# Material stacks in the metal layer (only M2)
TECH.MATERIAL_STACKS.MSTACK_METAL2_DIEL = MaterialStack(
    name="Oxide",
    materials_heights=[
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_IMD12_HEIGHT),
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_M2_HEIGHT),
    ],
    display_style=DisplayStyle(color=COLOR_BABY_BLUE),
)

TECH.MATERIAL_STACKS.MSTACK_METAL2_M = MaterialStack(
    name="M2",
    materials_heights=[
        (TECH.MATERIALS.SILICON_OXIDE, MSTACK_IMD12_HEIGHT),
        (TECH.MATERIALS.ALUMINIUM, MSTACK_M2_HEIGHT),
    ],
    display_style=DisplayStyle(color=COLOR_AL_GRAY),
)

TECH.MATERIAL_STACKS.MSTACK_METAL_M2_CON = MaterialStack(
    name="M2 + Contact",
    materials_heights=[(TECH.MATERIALS.TUNGSTEN, MSTACK_IMD12_HEIGHT), (TECH.MATERIALS.ALUMINIUM, MSTACK_M2_HEIGHT)],
    display_style=DisplayStyle(color=COLOR_TUNGSTEN),
)

Virtual Fabrication

Virtual fabrication generates a 3D representation of a component starting from a Layout. This is done by transforming a Layout constituted of elements (ProcessPurposeLayer on a shape) to a series of non-overlapping shapes that are associated with a material stack.

In order to set this up, you will need to specify a virtual fabrication process flow: i3.VFabricationProcessFlow:

  • active_processes: Which (masked) process steps (ProcessLayer objects) are used within the virtual fabrication flow.

  • process_layer_map: How the mask layer for each process layer is generated. A fabrication mask for a process step could be defined by just a single drawn layer in the layout, but could also be a generated layer: the result of a boolean operation between multiple drawn layers.

  • process_to_material_stack_map: How a combination of process layers relates to a specific material stack

  • is_lf_fabrication: Whether a mask layer is to be interpreted as light-field (LF) or dark-field (DF). Absent layers are interpreted as dark-field (DF).

Mask layers

All the drawn layers associated with a fabrication process step (ipkiss.process.layer.ProcessLayer) need to be combined to a mask that tells if a process is either 1 or 0 at a specific point. This is done through a set of boolean operations between the drawn layers.

Assume the following example: we have a process which has 2 process layers:

  • PROCESS1, for which the mask is directly defined by LAYER1, and

  • PROCESS2, for which the mask is generated by the boolean xor between LAYER2 and LAYER3.

PPLayers

Layout of the structure to be virtually fabricated

We can write the process_layer_map as follows:

process_layer_map = {
    TECH.PROCESS.PROCESS1: TECH.PPLAYER.LAYER1,
    TECH.PROCESS.PROCESS2: TECH.PPLAYER.LAYER2 ^ TECH.PPLAYER.LAYER3
}

For the virtual fabrication, it does not matter whether the layers are i3.Layer or PPLayer objects.

These specified boolean operations defined will be used to create a final mask layer for each process:

VFab

Final mask layers generated for each process layer

From mask layers to material stacks

The final mask layers are mapped to material stacks with a combination of two specifications:

  • process_to_material_stack_map: related combinations of final mask layers to a material stack (i3.MaterialStack), where for every point in the layout there is a one (1) or a zero (0) for each final mask layer.

  • is_lf_fabrication: specifies whether drawn areas on the final mask layer are 1 or 0.

    • If the corresponding entry is False, then a drawn shape on the final mask will be associated with a 1 in the process_to_material_stack_map table.

    • If the corresponding entry is True, then a drawn shape on the final mask will be associated with a 0 in the process_to_material_stack_map table.

TECH.VFABRICATION = TechnologyTree()
TECH.VFABRICATION.PROCESS_FLOW = VFabricationProcessFlow(
  active_processes=[
      TECH.PROCESS.PROCESS1,
      TECH.PROCESS.PROCESS2
  ],
  process_layer_map={
      TECH.PROCESS.PROCESS1: TECH.PPLAYER.LAYER1,
      TECH.PROCESS.PROCESS2: TECH.PPLAYER.LAYER2 ^ TECH.PPLAYER.LAYER3
  },
  process_to_material_stack_map=[
      ((0, 0), TECH.MATERIAL_STACKS.STACK_0),
      ((0, 1), TECH.MATERIAL_STACKS.STACK_1),
      ((1, 0), TECH.MATERIAL_STACKS.STACK_2),
      ((1, 1), TECH.MATERIAL_STACKS.STACK_3),
  ],
  is_lf_fabrication={
      TECH.PROCESS.PROCESS1: False,
      TECH.PROCESS.PROCESS2: False
  }
)

Note

The first entry in the process_material_stack_map is used as the default (background) material stack.

As illustrated below the masks are then combined to create virtually fabricated structure.

VFab

Mechanism used for the virtual fabrication.

Our samples contain an executable example on how to define a virtual fabrication and how visualize it or use it for cross sections. It’s a good start to experiment with it to get a better understanding about its inner behavior. You can find it at samples/technology/virtual_fabrication_example.py or download it here

# This is an advanced example on how to build Virtual Fabrication Process Flows.
# It's meant for PDK and library builders who want to include this process information
# in their technology. This way users of the PDK can with little effort export their
# components to 3rd party solvers.

import ipkiss3.all as i3
from ipkiss.visualisation.display_style import DisplayStyle
from ipkiss.visualisation import color

dummy_mat = i3.Material(name="dummy0_mat", epsilon=1, display_style=DisplayStyle(color=color.COLOR_SANGRIA))

# We'll have 4 material stacks
dummy_mstack0 = i3.MaterialStack(
    name="dummy0", materials_heights=[(dummy_mat, 1.0)], display_style=DisplayStyle(color=color.COLOR_CHERRY)
)

dummy_mstack1 = i3.MaterialStack(
    name="dummy1", materials_heights=[(dummy_mat, 2.0)], display_style=DisplayStyle(color=color.COLOR_DARK_GREEN)
)

dummy_mstack2 = i3.MaterialStack(
    name="dummy2", materials_heights=[(dummy_mat, 3.0)], display_style=DisplayStyle(color=color.COLOR_GRAY)
)

dummy_mstack3 = i3.MaterialStack(
    name="dummy3", materials_heights=[(dummy_mat, 0.5)], display_style=DisplayStyle(color=color.COLOR_MAGENTA)
)


# We'll use 3 Layers in our test structure
LAY0 = i3.Layer(0)
LAY1 = i3.Layer(1)
LAY2 = i3.Layer(2)

# and our technology uses 3 processes
PROCESS1 = i3.ProcessLayer(extension="ext1", name="dummyproc1")
PROCESS2 = i3.ProcessLayer(extension="ext2", name="dummyproc2")
PROCESS3 = i3.ProcessLayer(extension="ext3", name="dummyproc3")

vfab_flow = i3.VFabricationProcessFlow(
    active_processes=[PROCESS1, PROCESS2, PROCESS3],
    process_layer_map={
        # any of LAY0, LAY1 or LAY2 :
        PROCESS1: LAY0 | LAY1 | LAY2,
        # everwhere LAY1 or LAY2 :
        PROCESS2: (LAY1 & LAY2) | (LAY1 & LAY0) | (LAY2 & LAY0),
        # only when all layers are present:
        PROCESS3: LAY0 & LAY1 & LAY2,
    },
    process_to_material_stack_map=[
        ((0, 0, 0), dummy_mstack2),
        ((1, 0, 0), dummy_mstack0),  # mstack 0 where only 1 layer is present
        ((1, 1, 0), dummy_mstack1),  # mstack 1 where any combination of 2 layers is present
        ((1, 1, 1), dummy_mstack3),  # mstack 3 where all layers are present
    ],
)

# We make a Venn - Diagram like teststructure
lay = i3.LayoutCell().Layout(
    elements=[
        i3.Circle(layer=LAY0, center=(-3, 0), radius=5.0),
        i3.Circle(layer=LAY1, center=(3, 0), radius=5.0),
        i3.Circle(layer=LAY2, center=(0, 5), radius=5.0),
    ]
)

# We visualize the layers
lay.visualize()

# visualize_2d displays a top down view of the fabricated layout
lay.visualize_2d(vfabrication_process_flow=vfab_flow)

# we can also calculate and visualize the cross_section
lay.cross_section(i3.Shape([(-9, 3), (9, 3)]), process_flow=vfab_flow).visualize()
../../../../_images/virtual_fabrication_example_00.png
../../../../_images/virtual_fabrication_example_01.png
../../../../_images/virtual_fabrication_example_02.png

Traces

Contains the default settings for drawing traces such as waveguides and electrical traces. Three different trees need to be built. Default waveguide templates for optical and electrical routing are defined as well.


# Generic trace defaults
TECH.TRACE.DEFAULT_LAYER = TECH.PPLAYER.SI
TECH.TRACE.CONTROL_SHAPE_LAYER = TECH.PPLAYER.WIRE_TRACE

TECH.DEFAULT_WAVELENGTH = 1.55

# Generic port defaults
TECH.PORT.DEFAULT_LAYER = TECH.PPLAYER.PINREC  # Default layer for drawing pins

# Waveguide defaults

TECH.WG_DEFAULTS.N_EFF = 2.4
TECH.WG_DEFAULTS.N_GROUP = 4.4
TECH.WG_DEFAULTS.LOSS_DB_PERM = 0.0
TECH.WG_DEFAULTS.CORE_LAYER = Layer(0)

# Default waveguide routing template
TECH.PCELLS.WG = TechnologyTree()
TECH.PCELLS.WG.WIRE = SiWireWaveguideTemplate()
TECH.PCELLS.WG.RIB = SiRibWaveguideTemplate()
TECH.PCELLS.WG.DEFAULT = TECH.PCELLS.WG.WIRE

# Default metal routing template
TECH.PCELLS.METAL.DEFAULT = M1WireTemplate()

Grating Couplers

Here the grating coupler that are used in PICAZZO are defined. This is required to adapt the default fiber couplers used by IOFibcoup.

####################################################################
# DEFAULT FIBER COUPLER
#
# This file contains the required default settings for the fibre couplers in Picazzo.
# Note: They are not used by the classes 'Socket', 'Grating', 'GratingCoupler', 'FC_TE_1550' and 'FC_TE_1300' in SiFab.
####################################################################


from ipkiss.technology import get_technology
from ipkiss.technology.technology import TechnologyTree, TechnologyLibrary
from picazzo3.container.iofibcoup import IoFibcoup
from picazzo3.traces.wire_wg import WireWaveguideTemplate
from picazzo3.fibcoup.uniform import UniformLineGrating as _ULG
from si_fab.components.waveguides.wire import SiWireWaveguideTemplate
from si_fab.components.grating_coupler.pcell.cell import FC_TE_1550
from numpy import floor

TECH = get_technology()
TECH.IO = TechnologyTree()
TECH.IO.DEFAULT_FIBCOUP_SPACING = 25.0  # Default spacing between fibercouplers for IOFibCoup


def set_straight_fibcoup_defaults(tech: TechnologyLibrary):
    # Create tech settings for default straight fiber coupler gratings
    tree = tech.IO.FIBCOUP.STRAIGHT = TechnologyTree()
    tree.SOCKET = TechnologyTree()
    tree.SOCKET.LENGTH = 50.0
    tree.SOCKET.WIDTH = 10.0

    wide_trace_template = WireWaveguideTemplate()
    wide_trace_template.Layout(core_width=10.0, cladding_width=14.0)

    tree.SOCKET.TRACE_TEMPLATE = wide_trace_template  # Wide trace template.

    # TE Grating
    tree.GRATING_TE = TechnologyTree()
    tree.GRATING_TE.N_O_LINES = 25  # Default number of lines used.
    tree.GRATING_TE.PERIOD = 0.63  # Default period used in the grating.
    tree.GRATING_TE.LINE_WIDTH = 0.315  # Default linewidth used in the grating.
    tree.GRATING_TE.BOX_WIDTH = 14.0  # Default box width

    # TM Grating
    tree.GRATING_TM = TechnologyTree()
    tree.GRATING_TM.N_O_LINES = 16  # Default number of lines used.
    tree.GRATING_TM.PERIOD = 1.080  # Default period used in the grating.
    tree.GRATING_TM.LINE_WIDTH = 0.540  # Default linewidth used in the grating.
    tree.GRATING_TM.BOX_WIDTH = 14.0  # Default box width

    # default
    tree.GRATING = tree.GRATING_TE

    cells_tree = tech.IO.FIBCOUP.STRAIGHT.PCELLS = TechnologyTree()
    STANDARD_GRATING_1550_TE = _ULG(
        name="std_grating_1550", trace_template=tree.SOCKET.TRACE_TEMPLATE, library=TECH.PCELLS.LIB
    )
    STANDARD_GRATING_1550_TE.Layout(
        period=tree.GRATING.PERIOD,
        line_width=tree.GRATING_TE.LINE_WIDTH,
        line_length=tree.GRATING_TE.BOX_WIDTH,
        n_o_periods=tree.GRATING_TE.N_O_LINES,
    )
    tech.PCELLS.LIB.add(STANDARD_GRATING_1550_TE.dependencies())

    std1550_grating_trench = 0.540
    std1550_grating_period = 1.080
    std1550_grating_n_o_periods = 16
    wg_t = WireWaveguideTemplate(name="STD_FIBCOUP_SOCKET_WG_TM_T")
    wg_t.Layout(core_width=10.0, cladding_width=14.0)
    STANDARD_GRATING_1550_TM = _ULG(name="std_grating_1550_tm", trace_template=wg_t, library=TECH.PCELLS.LIB)
    STANDARD_GRATING_1550_TM.Layout(
        period=std1550_grating_period,
        line_width=std1550_grating_trench,
        n_o_periods=std1550_grating_n_o_periods,
    )
    TECH.PCELLS.LIB.add(STANDARD_GRATING_1550_TM.dependencies())

    cells_tree.DEFAULT_GRATING_TE = STANDARD_GRATING_1550_TE
    cells_tree.DEFAULT_GRATING_TM = STANDARD_GRATING_1550_TM
    cells_tree.DEFAULT_GRATING = STANDARD_GRATING_1550_TE


def set_curved_fibcoup_defaults(tech: TechnologyLibrary):
    # Create tech settings for default curved fiber coupler gratings
    tree = tech.IO.FIBCOUP.CURVED = TechnologyTree()
    # Socket
    tree.SOCKET = TechnologyTree()
    tree.SOCKET.LENGTH = 20.0
    tree.SOCKET.STRAIGHT_EXTENSION = (0.0, 0.05)  # Default straight extentions used for the socket taper.
    # Distance between the last grating line and the end of the socket by default
    tree.SOCKET.MARGIN_FROM_GRATING = TECH.WG.SHORT_STRAIGHT
    tree.SOCKET.START_TRACE_TEMPLATE = TECH.PCELLS.WG.DEFAULT
    tree.SOCKET.TRANSITION_LENGTH = 5.0

    wide_trace_template = SiWireWaveguideTemplate(name="LinearTransitionSocket_WGT")
    wide_trace_template.Layout(core_width=17.0, cladding_width=2 * TECH.WG.TRENCH_WIDTH + 17.0)

    tree.SOCKET.WIDE_TRACE_TEMPLATE = wide_trace_template  # Wide trace template.

    # Curved grating coupler defaults
    tree.GRATING = TechnologyTree()
    tree.GRATING.PERIOD = 1.0  # Default period used in the grating.
    # Default focal distance of curved gratings.
    tree.GRATING.FOCAL_DISTANCE = 20 * tree.GRATING.PERIOD
    tree.GRATING.BOX_WIDTH = 15.5  # Default box width
    tree.GRATING.N_O_LINES = int(floor(tree.GRATING.BOX_WIDTH / tree.GRATING.PERIOD))
    # Default first radius of the grating.
    tree.GRATING.START_RADIUS = tree.GRATING.FOCAL_DISTANCE - tree.GRATING.BOX_WIDTH / 2.0

    tree.GRATING.ANGLE_SPAN = 90  # Default angle span of a curved grating when it is not boxed.

    tree.PCELLS = TechnologyTree()
    tree.PCELLS.DEFAULT_GRATING = FC_TE_1550()
    # make sure that the child cells are also added to the technology library
    tech.PCELLS.LIB.add(tree.PCELLS.DEFAULT_GRATING.dependencies())


TECH.IO.FIBCOUP = TechnologyTree()

set_straight_fibcoup_defaults(TECH)
set_curved_fibcoup_defaults(TECH)

TECH.IO.FIBCOUP.DEFAULT = TECH.IO.FIBCOUP.CURVED

TECH.IO.ADAPTER = TechnologyTree()
TECH.IO.ADAPTER.IOFIBCOUP = TechnologyTree()
TECH.IO.ADAPTER.IOFIBCOUP.FANOUT_LENGTH = 40.0
TECH.IO.ADAPTER.IOFIBCOUP.S_BEND_ANGLE = 60.0
TECH.IO.ADAPTER.IOFIBCOUP.CONNECT_TRANSITION_LENGTH = None  # automatic
TECH.IO.ADAPTER.IOFIBCOUP.FIBER_COUPLER_TRANSITION_LENGTH = None  # automatic
TECH.IO.ADAPTER.DEFAULT_ADAPTER = TECH.IO.ADAPTER.IOFIBCOUP
TECH.IO.ADAPTER.IOFIBCOUP.PCELLS = TechnologyTree()
TECH.IO.ADAPTER.IOFIBCOUP.PCELLS.ADAPTER = IoFibcoup

Required Technology Keys: IPKISS

IPKISS requires a number of technology keys to be defined in order for all the parts of ipkiss to work. These are automatically created if you create a technology with TechnologyLibrary(default=True), so you can focus on overriding the settings that matter. The list is given below so that you can find which settings can be overridden.

Name generation

The name generator is used to automatically calculate a name for each cell, if a name is not given during initialization. By default, it causes pcells to get the PCELL_ name prefix, and counting starts at 0. If _name_prefix is defined in your pcell, that will be used for the prefix, instead.

  • TECH.ADMIN.NAME_GENERATOR: Name generator for your PCells.

Discretization metrics

These values affect how the output of the layout is generated.

  • TECH.METRICS.ANGLE_STEP: Angle step (in degrees) used for discretization of bends.

  • TECH.METRICS.GRID: Discretization of the grid GDSII file (in meter).

  • TECH.METRICS.UNIT: Unit of the GDSII file (in meter).

Port properties

An optical port is exported with a box drawn on DEFAULT_LAYER. The box dimensions are (TECH.PORT.DEFAULT_LENGTH, self.width)

  • TECH.PORT.DEFAULT_LAYER: Default layer used for ports.

  • TECH.PORT.DEFAULT_LENGTH: Default length used for ports.

Generic trace properties.

  • TECH.TRACE.BEND_RADIUS: Default bend radius, used during automatic routing.

  • TECH.TRACE.DRAW_CONTROL_SHAPE: Turn on/off the drawing of a control shape.

  • TECH.TRACE.CONTROL_SHAPE_LAYER: Layer used for the drawing of the control shape.

  • TECH.TRACE.DEFAULT_LAYER: Default layer used of the drawing of shapes.

Default model parameters

  • TECH.DEFAULT_WAVELENGTH: Default wavelength used for waveguide models.

  • TECH.WG_DEFAULTS.N_EFF: Default n_eff for waveguide models.

  • TECH.WG_DEFAULTS.N_GROUP: Default group index used for waveguide models.

  • TECH.WG_DEFAULTS.LOSS_DB_PERM: Default loss per m in dB used for waveguide models.

Default waveguide parameters.

  • TECH.WG_DEFAULTS.CORE_LAYER: Default core layer used in waveguides.

  • TECH.WG.SPACING: Default waveguide spacing used in adaptors.

  • TECH.WG.WIRE_WIDTH: Default wire width (needed for backward compatibility).

  • TECH.WG.EXPANDED_TAPER_LENGTH: Default length of an extended taper for extended waveguides.

  • TECH.WG.EXPANDED_WIDTH: Default width of expanded waveguides.

  • TECH.WG.TRENCH_WIDTH: Default width of a trench of a wavguide.

Used during routing.

  • TECH.WG.SHORT_STRAIGHT: Default minimum length required for any of the straight sections in a route.

  • TECH.WG.EXPANDED_STRAIGHT: Default length of an expanded straight waveguide.

  • TECH.PROCESS.WG: Default process for waveguides.

  • TECH.PROCESS.NONE: Default process for things that are not added to the GDSII.

  • TECH.PPLAYER.M1.LINE: Default layer for M1 guides.

  • TECH.PPLAYER.M2.LINE: Default layer for M2 guides.

  • TECH.PPLAYER.V12.PILLAR: Default layer for M12 vias.

  • TECH.PPLAYER.WG.TEXT: Default layer for text on a design.

  • TECH.PPLAYER.ERROR.GENERIC: Default layer for drawing errors.

  • TECH.PCELLS.WG.DEFAULT: Default waveguide template for this technology.

  • TECH.PCELLS.LIB: Default PCELL library.

  • TECH.PCELLS.METAL.DEFAULT: Default Metal trace template.

  • TECH.METAL.DEFAULT_PROCESS: Default process used for metals.

  • TECH.METAL.LINE_WIDTH: Default width of metal traces.

  • TECH.VIAS.DEFAULT.TOP_SHAPE: Default top_shape of a via.

  • TECH.VIAS.DEFAULT.BOTTOM_SHAPE: Default bottom_shape of a via.

  • TECH.VIAS.DEFAULT.VIA_SHAPE: Default pillar shape of a via.

GDS export settings.

These affect how your designs are exported to GDS. The default EXPORT_LAYER_MAP and IMPORT_LAYER_MAP automatically convert IPKISS layers to a gds number/datatype and vice versa (through AutoGdsiiLayerOutputMap / AutoGdsiiLayerInputMap). This is in general not very useful as you want to have control over how the layers are exported. The best way to do this is to define a layer map manually, and use GenericGdsiiPPLayerOutputMap and GenericGdsiiPPLayerInputMap.

  • TECH.GDSII.MAX_NAME_LENGTH: Max name length of a cell in char.

  • TECH.GDSII.EXPORT_LAYER_MAP: GDSII export layer map.

  • TECH.GDSII.IMPORT_LAYER_MAP: GDSII import layer map.

  • TECH.GDSII.NAME_FILTER: Filter applied on the names of the PCells before being exported to GDSII.

  • TECH.GDSII.MAX_VERTEX_COUNT: Max number of vertices in a polygon shape. Splitted otherwise.

  • TECH.GDSII.MAX_PATH_LENGTH: Max path length of the GDSII file. Splitted otherwise.

  • TECH.GDSII.STRNAME_CHARACTER_DICT: Dict for the mapping of illegal characters on legal. Applied to all cell names.

  • TECH.GDSII.STRNAME_ALLOWED_CHARACTERS: All allowed characters in a cell name.

Filters are functions that are that are applied upon conversion from IPKISS to GDSII. There is a wide range of filters and you can define your own. This is advanced functionality - please contact us if you think you would need them we would be happy to assist.

  • TECH.GDSII.FILTER: List of filters applied to your PCells before export to GDSII.

Blocks

Blocks are the basic elements added to IoColumn. Below are default values for the spacing and width of the blocks.

  • TECH.BLOCKS.DEFAULT_YSPACING: Default spacing between blocks.

  • TECH.BLOCKS.DEFAULT_WIDTH: Default width of a block.

The default adapter (i.e., A PCell that ‘adapts’ or ‘wraps’ another PCell in an IoBlock to fit it into an IoColumn):

  • TECH.IO.ADAPTER.DEFAULT_ADAPTER.PCELLS.ADAPTER: Default adapter for I/O blocks.

Drawing purposes

  • TECH.PURPOSE.BBOX: Purpose for the bounding boxes.

  • TECH.PURPOSE.LF_AREA: Purpose for light field areas.

  • TECH.PURPOSE.LF.LINE: Purpose for light field lines.

  • TECH.PURPOSE.DF.LINE: Purpose for dark field areas.

  • TECH.PURPOSE.TEXT: Purpose for text.

Visualization

  • TECH.DISPLAY.DEFAULT_DISPLAY_STYLE_SET: Default display set for visualization in IPKISS.

Transitions

The AUTO_TRANSITION_DATABASE consists of a list of valid transitions (tapers). During automatic routing, if transitions have to be added between two given trace templates (e.g., rib and strib waveguide), the AUTO_TRANSITION_DATABASE is used to look up whether there is a valid transition between both.

  • TECH.PCELLS.TRANSITION.AUTO_TRANSITION_DATABASE: Default autotransition database.

Errors

  • TECH.PPLAYER.ERROR.CROSSING: error layer to indicate crossing waveguides

  • TECH.PPLAYER.ERROR.GENERIC: error layer to indicate other errors

Required Technology Keys: PICAZZO

In order to make the PICAZZO pcell library work on your technology, a set of technology keys are required.

Containers

  • TECH.CONTAINER.TERMINATE_PORTS.CHILD_SUFFIX: Suffix that will be added to the children of TerminatePorts.

  • TECH.CONTAINER.TERMINATE_PORTS.TERMINATION_INSTANCE_PREFIX: Suffix that will be added to the instances of the termination cells in TerminatePorts.

Fiber couplers and IoFibcoup adapters

These provide default values for the parameters of IoFibcoup and the picazzo fiber couplers.

  • TECH.IO.ADAPTER.IOFIBCOUP.CONNECT_TRANSITION_LENGTH: default length of the transition between the ‘fanout’ section and the straight connection traces to the fiber coupler in IoFibcoup.

  • TECH.IO.ADAPTER.IOFIBCOUP.FANOUT_LENGTH: default length of the ‘fanout’ section in IoFibcoup.

  • TECH.IO.ADAPTER.IOFIBCOUP.FIBER_COUPLER_TRANSITION_LENGTH: default transition length to the fiber coupler in IoFibcoup.

  • TECH.IO.ADAPTER.IOFIBCOUP.S_BEND_ANGLE: maximum s-bend angle to use in IoFibcouop.

  • TECH.IO.FIBCOUP.CURVED.SOCKET.MARGIN_FROM_GRATING: margin behind the grating before the coupler socket ends.

  • TECH.IO.FIBCOUP.CURVED.GRATING.ANGLE_SPAN: default angular span of curved grating.

  • TECH.IO.FIBCOUP.CURVED.GRATING.BOX_WIDTH: default box width of curved grating.

  • TECH.IO.FIBCOUP.CURVED.GRATING.FOCAL_DISTANCE: default focal distance of curved grating.

  • TECH.IO.FIBCOUP.CURVED.GRATING.N_O_LINES: default number of grating lines of curved grating.

  • TECH.IO.FIBCOUP.CURVED.GRATING.PERIOD: default period of curved grating.

  • TECH.IO.FIBCOUP.CURVED.GRATING.START_RADIUS: default radius of the first grating line of curved grating.

  • TECH.IO.FIBCOUP.CURVED.PCELLS.DEFAULT_GRATING: default curved grating cell.

  • TECH.IO.FIBCOUP.CURVED.SOCKET.LENGTH: default socket length.

  • TECH.IO.FIBCOUP.CURVED.SOCKET.START_TRACE_TEMPLATE: default start trace template of curved grating socket.

  • TECH.IO.FIBCOUP.CURVED.SOCKET.STRAIGHT_EXTENSION: default straight extension of curved grating behind the grating socket.

  • TECH.IO.FIBCOUP.CURVED.SOCKET.WIDE_TRACE_TEMPLATE: default end trace template of curved grating socket.

  • TECH.IO.FIBCOUP.DEFAULT.PCELLS.DEFAULT_GRATING: default grating coupler.

  • TECH.IO.FIBCOUP.DEFAULT.SOCKET.LENGTH: Default property value for curved grating couplers.

  • TECH.IO.FIBCOUP.STRAIGHT.GRATING.BOX_WIDTH: default box width of straight grating.

  • TECH.IO.FIBCOUP.STRAIGHT.GRATING.LINE_WIDTH: default linewidth of straight grating.

  • TECH.IO.FIBCOUP.STRAIGHT.GRATING.N_O_LINES: default number fo periods of straight grating.

  • TECH.IO.FIBCOUP.STRAIGHT.GRATING.PERIOD: default period of straight grating.

  • TECH.IO.FIBCOUP.STRAIGHT.PCELLS.DEFAULT_GRATING_TM: default TM grating.

  • TECH.IO.FIBCOUP.STRAIGHT.SOCKET.LENGTH: default socket length of straight grating.

  • TECH.IO.FIBCOUP.STRAIGHT.SOCKET.TRACE_TEMPLATE: default trace template of straight grating.

Modulators

These provide default values for the parameters of LateralPNPhaseShifterTemplate and py:class:LongitudinalPNPhaseShifterTemplate<picazzo3.modulators.phase.trace.LongitudinalPNPhaseShifterTemplate>

  • TECH.MODULATORS.PHASESHIFTER.LATPN.BRIDGE_PITCH

  • TECH.MODULATORS.PHASESHIFTER.LATPN.BRIDGE_WIDTH

  • TECH.MODULATORS.PHASESHIFTER.LATPN.JUNCTION_OFFSET

  • TECH.MODULATORS.PHASESHIFTER.LONGPN.N_LENGTH

  • TECH.MODULATORS.PHASESHIFTER.LONGPN.N_WIDTH

  • TECH.MODULATORS.PHASESHIFTER.LONGPN.P_LENGTH

  • TECH.MODULATORS.PHASESHIFTER.LONGPN.P_WIDTH

  • TECH.MODULATORS.PHASESHIFTER.PN.JUNCTION_OVERLAP

  • TECH.MODULATORS.PHASESHIFTER.PN.NPLUS_EXTENSION

  • TECH.MODULATORS.PHASESHIFTER.PN.NPLUS_OFFSET

  • TECH.MODULATORS.PHASESHIFTER.PN.NPLUS_WIDTH

  • TECH.MODULATORS.PHASESHIFTER.PN.N_CONT_OFFSETS

  • TECH.MODULATORS.PHASESHIFTER.PN.N_CONT_PITCH

  • TECH.MODULATORS.PHASESHIFTER.PN.N_METAL1_OFFSET

  • TECH.MODULATORS.PHASESHIFTER.PN.N_METAL1_WIDTH

  • TECH.MODULATORS.PHASESHIFTER.PN.N_SIL_EXTENSION

  • TECH.MODULATORS.PHASESHIFTER.PN.N_SIL_OFFSET

  • TECH.MODULATORS.PHASESHIFTER.PN.N_SIL_WIDTH

  • TECH.MODULATORS.PHASESHIFTER.PN.N_WIDTH

  • TECH.MODULATORS.PHASESHIFTER.PN.PPLUS_EXTENSION

  • TECH.MODULATORS.PHASESHIFTER.PN.PPLUS_OFFSET

  • TECH.MODULATORS.PHASESHIFTER.PN.PPLUS_WIDTH

  • TECH.MODULATORS.PHASESHIFTER.PN.P_CONT_OFFSETS

  • TECH.MODULATORS.PHASESHIFTER.PN.P_CONT_PITCH

  • TECH.MODULATORS.PHASESHIFTER.PN.P_METAL1_OFFSET

  • TECH.MODULATORS.PHASESHIFTER.PN.P_METAL1_WIDTH

  • TECH.MODULATORS.PHASESHIFTER.PN.P_SIL_EXTENSION

  • TECH.MODULATORS.PHASESHIFTER.PN.P_SIL_OFFSET

  • TECH.MODULATORS.PHASESHIFTER.PN.P_SIL_WIDTH

  • TECH.MODULATORS.PHASESHIFTER.PN.P_WIDTH

waveguides

  • TECH.PCELLS.WG.RIB: Default ‘rib’ waveguide template

  • TECH.PCELLS.WG.RIBWIRE: Default ‘ribwire’ waveguide template

  • TECH.PCELLS.WG.WIRE: Default ‘wire’ waveguide template

PPLayers, ProcessLayers and PatternPurposes

  • TECH.PPLAYER.FC.TRENCH: Default fiber coupler trench layer

  • TECH.PPLAYER.N.LINE: Default N implant layer

  • TECH.PPLAYER.P.LINE: Default P implant layer

  • TECH.PPLAYER.NONE.DOC: Default documentation layer

  • TECH.PPLAYER.WG.CLADDING: Default waveguide cladding layer

  • TECH.PPLAYER.WG.CORE: Default waveguide core layer

  • TECH.PPLAYER.WG.TRENCH: Default waveguide trench layer

  • TECH.PROCESS.CON: Default contact hole process

  • TECH.PROCESS.FC: Default fiber coupler grating process

  • TECH.PROCESS.HFW: Default HF etch window process (oxide removal)

  • TECH.PROCESS.M1: Default metal1 process

  • TECH.PROCESS.M2: Default metal2 process

  • TECH.PROCESS.N: Default N implant process

  • TECH.PROCESS.P: Default P implant process

  • TECH.PROCESS.NPLUS: Default N++ implant process

  • TECH.PROCESS.PPLUS: Default P++ implant process

  • TECH.PROCESS.RWG: Default rib waveguide process

  • TECH.PROCESS.SIL: Default silicide process

  • TECH.PROCESS.SK: Default socket waveguide process

  • TECH.PROCESS.V12: Default via12 process

  • TECH.PURPOSE.DF.POLYGON: Default dark-field polygon drawing purpose

  • TECH.PURPOSE.DF_AREA: Default dark-field area drawing purpose

  • TECH.PURPOSE.DRAWING: Default drawing purpose

Rules

  • TECH.RWG.CLADDING_WIDTH: Default rib waveguide cladding width

  • TECH.RWG.RIB_WIDTH: Default rib waveguide rib width (shallow part)

  • TECH.RWG.STRIP_WIDTH: Default rib waveguide strip core width

  • TECH.SK.CLADDING_WIDTH: Default socket waveguide cladding width

  • TECH.TECH.MINIMUM_LINE: Overall minimum linewidth

  • TECH.TECH.MINIMUM_SPACE: Overall minimum spacing

  • TECH.VIAS.CONTACT_HOLE.M1_WIDTH: Default metal1 width on contact hole

  • TECH.VIAS.CONTACT_HOLE.PCELLS.DEFAULT_VIA: Default contact hole cell

  • TECH.VIAS.CONTACT_HOLE.SIL_WIDTH: Default silicide width on contact hole

  • TECH.VIAS.CONTACT_HOLE.VIA_WIDTH: Default via width on contact hole

  • TECH.VIAS.V12.M1_WIDTH: Default metal1 width on via12

  • TECH.VIAS.V12.M2_WIDTH: Default metal2 width on via12

  • TECH.VIAS.V12.N_O_SIDES: Default number of sides on via12 polygon

  • TECH.VIAS.V12.PCELLS.DEFAULT_VIA: Default default via12 cell

  • TECH.VIAS.V12.VIA_WIDTH: Default width of via12

  • TECH.WG.BEND_RADIUS: Default waveguide bend radius

  • TECH.WG.CLADDING_WIDTH: Default strip waveguide cladding width

  • TECH.WG.DC_SPACING: Default strip waveguide directional coupler spacing

  • TECH.WG.SHORT_TRANSITION_LENGTH: Default length of transitions

  • TECH.WG.SLOT_WIDTH: Default slot width for slot waveguides

Advanced cases

Resolving circular dependencies

Technology keys can be any python object. In some cases, you will want to store Ipkiss objects in the TECH tree which in their turn depend on TECH values, creating a circular dependency. These circular dependencies can be managed by using a DelayedInitTechnologyTree.

from ipkiss.technology import get_technology
from ipkiss.technology.technology import DelayedInitTechnologyTree

TECH = get_technology()

class MySettingsTree(DelayedInitTechnologyTree):
    def initialize(self):
        from mymodule import MyClass
        self.MYOBJ = MyClass()
        # now the technology tree can be fully imported at the start
        # of the main script, even if mymodule uses TECH settings

TECH.MYSETTINGS = MySettingsTree()

The initialize routine will only be called when TECH.MYSETTINGS.MYOBJ will be called.

Note this is not necessary for mainstream design kit implementation.