astra/f1c100s
The code defines the physical pin layout, labels, and footprint for the F1C100S system-on-chip (SoC) component used in electronic devices.
- Version
- 0.9.2
- License
- unset
- Stars
- 0
scripts/save-trace-paths.ts
import { EXTERNAL_NETS } from "../src/pin-map";
import { readFile, writeFile } from "node:fs/promises";
import { fanoutTracePath } from "@tscircuit/props";
import { LAYOUT_PROFILES } from "../src/profiles";
const reverse = (route: any[]) =>
route
.toReversed()
.map((p) =>
p.route_type === "via"
? { ...p, from_layer: p.to_layer, to_layer: p.from_layer }
: { ...p },
);
for (const profile of LAYOUT_PROFILES) {
const json = JSON.parse(
await readFile(`src/generated/${profile}.circuit.json`, "utf8"),
);
const ports = json.filter((e: any) => e.type === "pcb_port");
const sourcePorts = new Map<string, any>(
json
.filter((e: any) => e.type === "source_port")
.map((e: any) => [e.source_port_id, e]),
);
const components = new Map<string, any>(
json
.filter((e: any) => e.type === "source_component")
.map((e: any) => [e.source_component_id, e]),
);
const paths: any[] = [];
for (const net of json.filter((e: any) => e.type === "source_trace")) {
const members = ports.filter((p: any) =>
net.connected_source_port_ids.includes(p.source_port_id),
);
const name = (p: any) =>
components.get(sourcePorts.get(p.source_port_id).source_component_id)
.name;
const root =
members.find((p: any) =>
(EXTERNAL_NETS as readonly string[]).includes(name(p)),
) ??
members.find((p: any) => name(p) === "Y1") ??
members[0];
const graph = new Map<string, { to: string; route: any[] }[]>();
for (const trace of json.filter(
(e: any) =>
e.type === "pcb_trace" && e.source_trace_id === net.source_trace_id,
)) {
const route = trace.route.map((p: any) =>
p.route_type === "wire"
? {
route_type: "wire",
x: p.x,
y: p.y,
layer: p.layer,
width: p.width,
}
: {
route_type: "via",
x: p.x,
y: p.y,
from_layer: p.from_layer,
to_layer: p.to_layer,
via_diameter: 0.45,
via_hole_diameter: 0.2,
},
);
const find = (q: any) =>
members.find(
(p: any) =>
Math.hypot(p.x - q.x, p.y - q.y) < 1e-4 &&
p.layers.includes(q.layer),
);
const a = find(route[0]),
b = find(route.at(-1));
if (!a || !b)
throw Error(`Missing endpoint ${profile} ${trace.pcb_trace_id}`);
for (const [from, to, r] of [
[a, b, route],
[b, a, reverse(route)],
] as any) {
if (!graph.has(from.pcb_port_id)) graph.set(from.pcb_port_id, []);
graph.get(from.pcb_port_id)!.push({ to: to.pcb_port_id, route: r });
}
}
const routes = new Map<string, any[]>([[root.pcb_port_id, []]]),
queue = [root.pcb_port_id];
while (queue.length) {
const id = queue.shift()!;
for (const edge of graph.get(id) ?? []) {
if (routes.has(edge.to)) continue;
routes.set(edge.to, [
...reverse(edge.route),
...routes.get(id)!.slice(1),
]);
queue.push(edge.to);
}
}
for (const port of members) {
if (port === root) continue;
const route = routes.get(port.pcb_port_id);
if (!route) throw Error(`Disconnected stored net ${net.name}`);
const source = sourcePorts.get(port.source_port_id);
paths.push(
fanoutTracePath.parse({
connection: `${name(port)}.pin${source.pin_number}`,
route,
}),
);
}
}
await writeFile(
`src/generated/${profile}.trace-paths.json`,
JSON.stringify(paths, null, 2) + "\n",
);
console.log(profile, paths.length, "saved paths");
}