Build a SLiCAP library (`.lib`) file holding one subcircuit definition. Format:: .subckt ... par1=def1 par2=def2 ... .param ... (internal parameter definitions, if any) .ends .en
(
components: list, # list[ComponentItem]
wires: list, # list[WireItem]
name: str, # subcircuit (.subckt) name
ports: list, # ordered node names exposed to the parent
params: list = None, # list[(name, default)] overridable parameters
params_items: list = None, # list[ParameterItem] — internal .param definitions
)
| 144 | |
| 145 | |
| 146 | def build_subcircuit( |
| 147 | components: list, # list[ComponentItem] |
| 148 | wires: list, # list[WireItem] |
| 149 | name: str, # subcircuit (.subckt) name |
| 150 | ports: list, # ordered node names exposed to the parent |
| 151 | params: list = None, # list[(name, default)] overridable parameters |
| 152 | params_items: list = None, # list[ParameterItem] — internal .param definitions |
| 153 | ) -> str: |
| 154 | """ |
| 155 | Build a SLiCAP library (`.lib`) file holding one subcircuit definition. |
| 156 | |
| 157 | Format:: |
| 158 | |
| 159 | <name> |
| 160 | |
| 161 | .subckt <name> <port1> <port2> ... par1=def1 par2=def2 ... |
| 162 | |
| 163 | .param ... (internal parameter definitions, if any) |
| 164 | |
| 165 | <element lines> |
| 166 | |
| 167 | .ends |
| 168 | .end |
| 169 | |
| 170 | Ports are emitted in the given order; they are the named nets the parent |
| 171 | wires to. A ``ground`` (node 0) inside the schematic stays global and is |
| 172 | never a port — grounding is the parent's job (it wires a port to 0). |
| 173 | """ |
| 174 | title_line = f'"{name}"' if " " in name else name |
| 175 | |
| 176 | _node = _node_resolver(components, wires) |
| 177 | |
| 178 | subckt = f".subckt {name}" |
| 179 | if ports: |
| 180 | subckt += " " + " ".join(ports) |
| 181 | if params: |
| 182 | subckt += " " + " ".join(f"{k}={v}" for k, v in params if str(k).strip()) |
| 183 | |
| 184 | lines: list[str] = [title_line, "", subckt] |
| 185 | |
| 186 | # ── internal parameter definitions ───────────────────────────────────────── |
| 187 | # A parameter passed in through the .subckt line must NOT be redefined |
| 188 | # internally — the passed value supersedes any local definition. |
| 189 | passed = {str(k).strip().strip("{}") for k, _ in (params or [])} |
| 190 | if params_items: |
| 191 | for param_item in params_items: |
| 192 | param_lines = param_item.param_lines(exclude=passed) |
| 193 | if param_lines: |
| 194 | lines.append("") |
| 195 | lines.extend(param_lines) |
| 196 | |
| 197 | # ── element lines ────────────────────────────────────────────────────────── |
| 198 | lines.append("") |
| 199 | lines.extend(_element_lines(components, _node)) |
| 200 | |
| 201 | lines += ["", ".ends", ".end"] |
| 202 | return "\n".join(lines) |
| 203 |
no test coverage detected