Skip to content

Download notebook (.ipynb)

5-Minute Quickstart

This page walks through the essential kfnetlist operations: creating a netlist, adding instances, wiring them up with nets, and serializing the result.

from kfnetlist import Netlist, NetlistPort, PortRef

Creating a netlist

A Netlist is the top-level container. It holds instances, nets, and top-level ports.

nl = Netlist()

Adding instances

create_inst registers a sub-cell instance. Each instance records its PDK (kcl), component name, and settings.

nl.create_inst(
    "wg1",
    kcl="MY_PDK",
    component="straight",
    settings={"width": 500, "length": 10_000},
)
nl.create_inst(
    "wg2",
    kcl="MY_PDK",
    component="straight",
    settings={"width": 500, "length": 10_000},
)

print("Instances:", nl.instance_names())
Instances: ['wg1', 'wg2']

Adding top-level ports

create_port adds a cell-level port — an externally visible connection point.

p_in = nl.create_port("in")
p_out = nl.create_port("out")

print("Ports:", [p.name for p in nl.ports])
Ports: ['in', 'out']

Creating nets

create_net connects two or more port members. Members can be NetlistPort (cell-level ports) or PortRef (instance ports).

# Cell-level "in" connects to wg1's input
nl.create_net(p_in, PortRef(instance="wg1", port="o1"))

# Internal: wg1's output connects to wg2's input
nl.create_net(
    PortRef(instance="wg1", port="o2"),
    PortRef(instance="wg2", port="o1"),
)

# wg2's output connects to cell-level "out"
nl.create_net(PortRef(instance="wg2", port="o2"), p_out)

print(f"Nets ({len(nl.nets)}):")
for i, net in enumerate(nl.nets):
    members = []
    for m in net:
        if isinstance(m, PortRef):
            members.append(f"{m.instance}.{m.port}")
        elif isinstance(m, NetlistPort):
            members.append(f"<{m.name}>")
    print(f"  net[{i}]: {' — '.join(members)}")
Nets (3):
  net[0]: <in> — wg1.o1
  net[1]: wg1.o2 — wg2.o1
  net[2]: <out> — wg2.o2

Sorting for stable comparison

Port ordering within a net and net ordering across the netlist can vary. sort() normalises both, making equality checks reproducible.

nl.sort()
print("Sorted instance names:", nl.instance_names())
Sorted instance names: ['wg1', 'wg2']

Serialization

Every kfnetlist type supports to_json() / from_json() and to_dict() / from_dict() for round-trip serialization.

import json

json_str = nl.to_json()
print(json.loads(json_str))
{'instances': {'wg1': {'kcl': 'MY_PDK', 'component': 'straight', 'settings': {'length': 10000, 'width': 500}, 'array': {'na': 1, 'nb': 1}}, 'wg2': {'kcl': 'MY_PDK', 'component': 'straight', 'settings': {'length': 10000, 'width': 500}, 'array': {'na': 1, 'nb': 1}}}, 'nets': [[{'name': 'in'}, {'instance': 'wg1', 'port': 'o1'}], [{'name': 'out'}, {'instance': 'wg2', 'port': 'o2'}], [{'instance': 'wg1', 'port': 'o2'}, {'instance': 'wg2', 'port': 'o1'}]], 'ports': [{'name': 'in'}, {'name': 'out'}]}
# Round-trip: reconstruct from JSON
nl2 = Netlist.from_json(json_str)
nl2.sort()
assert nl.to_dict() == nl2.to_dict()
print("Round-trip ✓")
Round-trip ✓

Summary

Operation API
Create a netlist Netlist()
Add an instance nl.create_inst(name, kcl, component, settings)
Add a top-level port nl.create_port(name)
Wire ports together nl.create_net(member1, member2, ...)
Normalise for comparison nl.sort()
Serialize to JSON nl.to_json() / Netlist.from_json(s)
Serialize to dict nl.to_dict() / Netlist.from_dict(d)

See Also

Topic Where
Full data model Concepts: Netlist Model
Port types Concepts: Ports & Refs
JSON / dict details Concepts: Serialization