Factory Functions
A factory in kfactory is a function that returns another function — a
cell-making function bound to a specific KCLayout. Factories are the
recommended way to build production PDKs because they:
- Tie cells to a specific layout — every cell built by the factory lives in
the same
KCLayout, so layer indices are consistent. - Cache automatically — the returned function is decorated with
@kcl.cell, so repeated calls with the same arguments return the same cell object. - Carry typed protocols — each factory returns a typed
Protocolcallable, so IDEs and type-checkers can validate arguments at the call site. - Enable routing — the built-in routers (
route_bundle,place_manhattan) require factory functions, not raw cells, so they can create bend/straight geometry on demand.
Available factories
| Factory | Module | Page |
|---|---|---|
straight_dbu_factory |
kf.factories.straight |
Straight |
bend_euler_factory / bend_s_euler_factory |
kf.factories.euler |
Euler |
bend_circular_factory |
kf.factories.circular |
Circular |
bend_s_bezier_factory |
kf.factories.bezier |
Bezier |
taper_factory |
kf.factories.taper |
Taper |
Factories and routing
The built-in optical router (kf.routing.optical.route_bundle) requires factory
callables — it uses them to instantiate bends and straights while building a
route. Passing cells directly is not supported.
routes = kf.routing.optical.route_bundle(
c,
start_ports=[...],
end_ports=[...],
bend90_cell=bend_euler, # factory callable
straight_factory=straight, # factory callable
)
Because each factory is bound to a KCLayout, all route geometry automatically
lands in the correct layout and uses the correct layer indices.
Bundling factories in a PDK module
The recommended pattern for a production PDK is to define all factories in one place and import them wherever routing or assembly is needed:
# my_pdk/factories.py
import kfactory as kf
from kfactory.factories.straight import straight_dbu_factory
from kfactory.factories.euler import bend_euler_factory
from kfactory.factories.taper import taper_factory
from my_pdk.layers import LAYER
pdk = kf.KCLayout("MY_PDK", infos=LAYER)
straight = straight_dbu_factory(pdk)
bend_euler = bend_euler_factory(pdk)
taper = taper_factory(pdk)
__all__ = ["pdk", "straight", "bend_euler", "taper"]
Key rules
straight_dbu_factory/taper_factory— arguments in DBUbend_euler_factory/bend_circular_factory—widthandradiusin µm- Always bind the factory to the same
KCLayoutthat owns the cells being routed
See Also
| Topic | Where |
|---|---|
| PCells & caching | Components: PCells |
| Cross-sections | Cross-Sections |
| Routing integration | Routing: Overview |
| PDK bundling pattern | PDK: Creating a PDK |