Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 60 additions & 2 deletions lib/convertCircuitJsonToReadableNetlist.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { su } from "@tscircuit/soup-util"
import type {
CircuitJson,
AnyCircuitElement,
CircuitJson,
SourceNet,
SourcePort,
} from "circuit-json"
import { su } from "@tscircuit/soup-util"
import { getFullConnectivityMapFromCircuitJson } from "circuit-json-to-connectivity-map"
import { generateNetName } from "./generateNetName"
import { getReadableNameForPin } from "./getReadableNameForPin"
Expand Down Expand Up @@ -111,5 +111,63 @@ export const convertCircuitJsonToReadableNetlist = (
}
}

// build map of port ids to the nets they connect to
const portIdToNetNames: Record<string, string[]> = {}
for (const [netId, connectedIds] of Object.entries(netMap)) {
const portIds = connectedIds.filter((id) => id.startsWith("source_port"))
if (portIds.length === 0) continue
const net = source_nets.find((n) => connectedIds.includes(n.source_net_id))
let netName = net?.name
if (!netName) {
netName = generateNetName({ circuitJson, connectedIds })
}
for (const portId of portIds) {
if (!portIdToNetNames[portId]) portIdToNetNames[portId] = []
portIdToNetNames[portId].push(netName)
}
}

if (source_components.length > 0) {
netlist.push("")
netlist.push("COMPONENT_PINS:")
for (const component of source_components) {
const cadComponent = su(circuitJson).cad_component.getWhere({
source_component_id: component.source_component_id,
})
const footprint = cadComponent?.footprinter_string
let header = component.name
if (component.ftype === "simple_resistor") {
header = `${component.name} (${component.display_resistance} ${footprint})`
} else if (component.ftype === "simple_capacitor") {
header = `${component.name} (${component.display_capacitance} ${footprint})`
} else if (component.manufacturer_part_number) {
header = `${component.name} (${component.manufacturer_part_number})`
}
netlist.push(header)
const ports = source_ports
.filter((p) => p.source_component_id === component.source_component_id)
.sort((a, b) => (a.pin_number ?? 0) - (b.pin_number ?? 0))
for (const port of ports) {
const mainPin =
port.pin_number !== undefined ? `pin${port.pin_number}` : port.name
const aliases: string[] = []
if (port.name && port.name !== mainPin) aliases.push(port.name)
for (const hint of port.port_hints ?? []) {
if (hint === String(port.pin_number)) continue
if (hint !== mainPin && hint !== port.name) aliases.push(hint)
}
const aliasPart =
aliases.length > 0
? `(${Array.from(new Set(aliases)).join(", ")})`
: ""
const nets = portIdToNetNames[port.source_port_id] ?? []
const netsPart =
nets.length > 0 ? `NETS(${nets.join(", ")})` : "NOT_CONNECTED"
netlist.push(`- ${mainPin}${aliasPart}: ${netsPart}`)
}
netlist.push("")
}
}

return netlist.join("\n")
}
4 changes: 2 additions & 2 deletions lib/getReadableNameForPin.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { su } from "@tscircuit/soup-util"
import type {
CircuitJson,
AnyCircuitElement,
CircuitJson,
SourceNet,
SourcePort,
} from "circuit-json"
import { su } from "@tscircuit/soup-util"
import { scorePhrase } from "./scorePhrase"

export const getReadableNameForPin = ({
Expand Down
14 changes: 12 additions & 2 deletions tests/test1-basic-circuit.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { renderCircuit } from "tests/fixtures/render-circuit"
import { expect, it } from "bun:test"
import { convertCircuitJsonToReadableNetlist } from "lib/convertCircuitJsonToReadableNetlist"
import { it, expect } from "bun:test"
import { renderCircuit } from "tests/fixtures/render-circuit"

declare module "bun:test" {
interface Matchers<T = unknown> {
Expand Down Expand Up @@ -34,6 +34,16 @@ it("test1 should render a basic circuit", () => {
NET: C1_pos
- R1 pin1
- C1 pin1 (+)


COMPONENT_PINS:
R1 (1kΩ 0402)
- pin1(anode, pos, left): NETS(C1_pos)
- pin2(cathode, neg, right): NOT_CONNECTED

C1 (1nF 0402)
- pin1(anode, pos, left): NETS(C1_pos)
- pin2(cathode, neg, right): NOT_CONNECTED
"
`)
})
26 changes: 23 additions & 3 deletions tests/test2-chip.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { renderCircuit } from "tests/fixtures/render-circuit"
import { expect, it } from "bun:test"
import { convertCircuitJsonToReadableNetlist } from "lib/convertCircuitJsonToReadableNetlist"
import { it, expect } from "bun:test"
import { renderCircuit } from "tests/fixtures/render-circuit"

declare module "bun:test" {
interface Matchers<T = unknown> {
Expand Down Expand Up @@ -64,6 +64,26 @@ NET: U1_SDA

EMPTY NET PINS:
- U1 GPIO3
- U1 VDD"
- U1 VDD

COMPONENT_PINS:
U1 (ATMEGA328P)
- pin1(GND): NETS(GND)
- pin2(AGND): NETS(GND)
- pin3(GPIO1, SCL): NETS(GND)
- pin4(GPIO2, SDA): NETS(U1_SDA)
- pin5(GPIO3): NETS(GPIO4)
- pin6(GPIO4, UART_TX): NOT_CONNECTED
- pin7(GPIO5, UART_RX): NOT_CONNECTED
- pin8(VDD): NETS(V5)

R1 (1kΩ 0402)
- pin1(anode, pos, left): NETS(C1_pos)
- pin2(cathode, neg, right): NETS(U1_SDA)

C1 (1nF 0402)
- pin1(anode, pos, left): NETS(C1_pos)
- pin2(cathode, neg, right): NOT_CONNECTED
"
`)
})
Loading