Skip to content

Commit

Permalink
add l2n capabilities back from
Browse files Browse the repository at this point in the history
  • Loading branch information
sebastian-goeldi committed Aug 31, 2023
1 parent cfd409b commit 2ef56d0
Show file tree
Hide file tree
Showing 8 changed files with 194 additions and 105 deletions.
3 changes: 2 additions & 1 deletion src/kfactory/cells/circular.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ def __call__(
]
]

extrude_path(
center_path = extrude_path(
target=c,
layer=layer,
path=backbone,
Expand All @@ -84,6 +84,7 @@ def __call__(
layer=layer,
)
c.autorename_ports()
c.boundary = center_path
return c


Expand Down
2 changes: 2 additions & 0 deletions src/kfactory/cells/dbu/straight.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ def __call__(
"length_dbu": length,
}
)

c.boundary = c.dbbox()
c.autorename_ports()
return c

Expand Down
3 changes: 2 additions & 1 deletion src/kfactory/cells/dbu/taper.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ def __call__(
"""
c = self.kcl.kcell()

c.shapes(layer).insert(
taper = c.shapes(layer).insert(
kdb.Polygon(
[
kdb.Point(0, int(-width1 / 2)),
Expand All @@ -76,6 +76,7 @@ def __call__(
}
)
c.autorename_ports()
c.boundary = taper.dpolygon

return c

Expand Down
7 changes: 5 additions & 2 deletions src/kfactory/cells/euler.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ def __call__(
dbu = c.layout().dbu
backbone = euler_bend_points(angle, radius=radius, resolution=resolution)

extrude_path(
center_path = extrude_path(
target=c,
layer=layer,
path=backbone,
Expand All @@ -210,6 +210,8 @@ def __call__(
layer=layer,
)

c.boundary = center_path

c.autorename_ports()
return c

Expand Down Expand Up @@ -247,7 +249,7 @@ def __call__(
radius=radius,
resolution=resolution,
)
extrude_path(
center_path = extrude_path(
target=c,
layer=layer,
path=backbone,
Expand Down Expand Up @@ -276,6 +278,7 @@ def __call__(
port_type="optical",
layer=layer,
)
c.boundary = center_path

c.autorename_ports()
return c
Expand Down
47 changes: 25 additions & 22 deletions src/kfactory/enclosure.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ def extrude_path(
enclosure: LayerEnclosure | None = None,
start_angle: float | None = None,
end_angle: float | None = None,
) -> None:
) -> kdb.DPolygon:
"""Extrude a path from a list of points and a static width.
Args:
Expand All @@ -177,41 +177,42 @@ def extrude_path(
autocalculated from the last two elements
"""
layer_list = {layer: LayerSection(sections=[Section(d_max=0)])}
j = 0
if enclosure is not None:
if layer not in enclosure.layer_sections:
layer_list |= enclosure.layer_sections
j = 0
else:
layer_list[layer].sections.copy()
layer_list = enclosure.layer_sections.copy()
for section in layer_list[layer].sections:
layer_list[layer].add_section(section)
j = layer_list[layer].add_section(Section(d_max=0))

for layer, layer_sec in layer_list.items():
for _layer, layer_sec in layer_list.items():
reg = kdb.Region()
for section in layer_sec.sections:
_r = kdb.Region(
path_pts_to_polygon(
for i, section in enumerate(layer_sec.sections):
_path = path_pts_to_polygon(
*extrude_path_points(
path,
width + 2 * section.d_max * target.kcl.dbu,
start_angle,
end_angle,
)
)
_r = kdb.Region(_path.to_itype(target.kcl.dbu))
if section.d_min is not None:
_path = path_pts_to_polygon(
*extrude_path_points(
path,
width + 2 * section.d_max * target.kcl.dbu,
width + 2 * section.d_min * target.kcl.dbu,
start_angle,
end_angle,
)
).to_itype(target.kcl.dbu)
)
if section.d_min is not None:
_r -= kdb.Region(
path_pts_to_polygon(
*extrude_path_points(
path,
width + 2 * section.d_min * target.kcl.dbu,
start_angle,
end_angle,
)
).to_itype(target.kcl.dbu)
)
_r -= kdb.Region(_path.to_itype(target.kcl.dbu))
reg.insert(_r)
if _layer == layer and i == j:
ret_path = _path
target.shapes(layer).insert(reg.merge())
return ret_path


def extrude_path_dynamic_points(
Expand Down Expand Up @@ -453,13 +454,14 @@ class LayerSection(BaseModel):

sections: list[Section] = Field(default=[])

def add_section(self, sec: Section) -> None:
def add_section(self, sec: Section) -> int:
"""Add a new section.
Checks for overlaps after.
"""
if not self.sections:
self.sections.append(sec)
return 0
else:
i = 0
if sec.d_min is not None:
Expand All @@ -477,6 +479,7 @@ def add_section(self, sec: Section) -> None:
if i == len(self.sections):
break
self.sections.insert(i, sec)
return i

def max_size(self) -> int:
"""Maximum size of the sections in this layer section."""
Expand Down
47 changes: 38 additions & 9 deletions src/kfactory/kcell.py
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,7 @@ class KCell:
_info: Info
d: UMKCell
kcl: KCLayout
boundary: kdb.DPolygon | None

def __init__(
self,
Expand Down Expand Up @@ -442,6 +443,8 @@ def __init__(
self.insts.append(Instance(self.kcl, inst))
self.d = UMKCell(self)

self.boundary = None

def __getitem__(self, key: int | str | None) -> Port:
"""Returns port from instance."""
return self.ports[key]
Expand Down Expand Up @@ -1311,29 +1314,54 @@ def ymax(self) -> int:
"""Returns the x-coordinate of the left edge of the bounding box."""
return self._kdb_cell.bbox().top

def netlist(self, port_types: tuple[str] = ("optical",)) -> kdb.Netlist:
"""Return a netlist with this cell as the top cell."""
netlist = kdb.Netlist()
def l2n(self, port_types: Iterable[str] = ("optical",)) -> kdb.LayoutToNetlist:
l2n = kdb.LayoutToNetlist(self.name, self.kcl.dbu)
l2n.extract_netlist()

for ci in self.called_cells():
self.kcl[ci].circuit(netlist, port_types=port_types)
il = l2n.internal_layout()

self.circuit(netlist, port_types=port_types)
def filter_port(port: Port) -> bool:
return port.port_type in port_types

return netlist
for ci in self.called_cells():
c = self.kcl[ci]
c.circuit(l2n, port_types=port_types)
# if il.cell(c.name) is None:
# il.create_cell(c.name)
# [
# il.cell(c.name)
# .shapes(il.layer(c.kcl.get_info(port.layer)))
# .insert(port_polygon(port.width))
# for port in filter(filter_port, c.ports)
# ]
self.circuit(l2n, port_types=port_types)
# if il.cell(self.name) is None:
# il.create_cell(self.name)
# [
# il.cell(self.name)
# .shapes(il.layer(self.kcl.get_info(port.layer)))
# .insert(port_polygon(port.width))
# for port in filter(filter_port, self.ports)
# ]
il.assign(self.kcl.layout)
return l2n

@cachetools.cached(cache={})
def circuit(
self, netlist: kdb.Netlist, port_types: tuple[str] = ("optical",)
self, l2n: kdb.LayoutToNetlist, port_types: Iterable[str] = ("optical",)
) -> None:
"""Create the circuit of the KCell in the given netlist."""
netlist = l2n.netlist()

def port_filter(num_port: tuple[int, Port]) -> bool:
return num_port[1].port_type in port_types

circ = kdb.Circuit()
circ.name = self.name
circ.cell_index = self.cell_index()
print(self.name)
print(circ.boundary)
circ.boundary = self.boundary or self.dbbox()
print(circ.boundary)

inst_ports: dict[
str, dict[str, list[tuple[int, int, Instance, Port, kdb.SubCircuit]]]
Expand Down Expand Up @@ -1384,6 +1412,7 @@ def port_filter(num_port: tuple[int, Port]) -> bool:
subc = circ.create_subcircuit(
netlist.circuit_by_cell_index(inst.cell_index), name
)
subc.trans = inst.dcplx_trans

for j, port in filter(port_filter, enumerate(inst.ports)):
_trans = port.trans.dup()
Expand Down
26 changes: 26 additions & 0 deletions src/kfactory/port.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
from enum import IntEnum
from typing import TYPE_CHECKING, Any

from . import kdb

if TYPE_CHECKING:
from .kcell import KCell, LayerEnum, Port

Expand Down Expand Up @@ -191,3 +193,27 @@ def regex_filter(p: "Port") -> bool:
return False

return filter(regex_filter, ports)


polygon_dict: dict[int, kdb.Polygon] = {}


def port_polygon(width: int) -> kdb.Polygon:
"""Gets a polygon representation for a given port width."""
if width in polygon_dict:
return polygon_dict[width]
else:
poly = kdb.Polygon(
[
kdb.Point(0, width // 2),
kdb.Point(0, -width // 2),
kdb.Point(width // 2, 0),
]
)

hole = kdb.Region(poly).sized(-int(width * 0.05) or -1)
hole -= kdb.Region(kdb.Box(0, 0, width // 2, -width // 2))

poly.insert_hole(list(list(hole.each())[0].each_point_hull()))
polygon_dict[width] = poly
return poly
Loading

0 comments on commit 2ef56d0

Please sign in to comment.