|
| 1 | +import { su } from "@tscircuit/soup-util" |
1 | 2 | import type { |
2 | | - CircuitJson, |
3 | 3 | AnyCircuitElement, |
| 4 | + CircuitJson, |
4 | 5 | SourceNet, |
5 | 6 | SourcePort, |
6 | 7 | } from "circuit-json" |
7 | | -import { su } from "@tscircuit/soup-util" |
8 | 8 | import { getFullConnectivityMapFromCircuitJson } from "circuit-json-to-connectivity-map" |
9 | 9 | import { generateNetName } from "./generateNetName" |
10 | 10 | import { getReadableNameForPin } from "./getReadableNameForPin" |
@@ -120,5 +120,63 @@ export const convertCircuitJsonToReadableNetlist = ( |
120 | 120 | } |
121 | 121 | } |
122 | 122 |
|
| 123 | + // build map of port ids to the nets they connect to |
| 124 | + const portIdToNetNames: Record<string, string[]> = {} |
| 125 | + for (const [netId, connectedIds] of Object.entries(netMap)) { |
| 126 | + const portIds = connectedIds.filter((id) => id.startsWith("source_port")) |
| 127 | + if (portIds.length === 0) continue |
| 128 | + const net = source_nets.find((n) => connectedIds.includes(n.source_net_id)) |
| 129 | + let netName = net?.name |
| 130 | + if (!netName) { |
| 131 | + netName = generateNetName({ circuitJson, connectedIds }) |
| 132 | + } |
| 133 | + for (const portId of portIds) { |
| 134 | + if (!portIdToNetNames[portId]) portIdToNetNames[portId] = [] |
| 135 | + portIdToNetNames[portId].push(netName) |
| 136 | + } |
| 137 | + } |
| 138 | + |
| 139 | + if (source_components.length > 0) { |
| 140 | + netlist.push("") |
| 141 | + netlist.push("COMPONENT_PINS:") |
| 142 | + for (const component of source_components) { |
| 143 | + const cadComponent = su(circuitJson).cad_component.getWhere({ |
| 144 | + source_component_id: component.source_component_id, |
| 145 | + }) |
| 146 | + const footprint = cadComponent?.footprinter_string |
| 147 | + let header = component.name |
| 148 | + if (component.ftype === "simple_resistor") { |
| 149 | + header = `${component.name} (${component.display_resistance} ${footprint})` |
| 150 | + } else if (component.ftype === "simple_capacitor") { |
| 151 | + header = `${component.name} (${component.display_capacitance} ${footprint})` |
| 152 | + } else if (component.manufacturer_part_number) { |
| 153 | + header = `${component.name} (${component.manufacturer_part_number})` |
| 154 | + } |
| 155 | + netlist.push(header) |
| 156 | + const ports = source_ports |
| 157 | + .filter((p) => p.source_component_id === component.source_component_id) |
| 158 | + .sort((a, b) => (a.pin_number ?? 0) - (b.pin_number ?? 0)) |
| 159 | + for (const port of ports) { |
| 160 | + const mainPin = |
| 161 | + port.pin_number !== undefined ? `pin${port.pin_number}` : port.name |
| 162 | + const aliases: string[] = [] |
| 163 | + if (port.name && port.name !== mainPin) aliases.push(port.name) |
| 164 | + for (const hint of port.port_hints ?? []) { |
| 165 | + if (hint === String(port.pin_number)) continue |
| 166 | + if (hint !== mainPin && hint !== port.name) aliases.push(hint) |
| 167 | + } |
| 168 | + const aliasPart = |
| 169 | + aliases.length > 0 |
| 170 | + ? `(${Array.from(new Set(aliases)).join(", ")})` |
| 171 | + : "" |
| 172 | + const nets = portIdToNetNames[port.source_port_id] ?? [] |
| 173 | + const netsPart = |
| 174 | + nets.length > 0 ? `NETS(${nets.join(", ")})` : "NOT_CONNECTED" |
| 175 | + netlist.push(`- ${mainPin}${aliasPart}: ${netsPart}`) |
| 176 | + } |
| 177 | + netlist.push("") |
| 178 | + } |
| 179 | + } |
| 180 | + |
123 | 181 | return netlist.join("\n") |
124 | 182 | } |
0 commit comments