krishnax12/watchy-eink-smartwatch
Unfinished prototype (not production-ready): 4 native DRC errors, 2 display-flex intersections, and missing antenna radiator copper remain
- Version
- 1.2.7
- License
- MIT
- Stars
- 1
scripts/check-reference-connectivity.mjs
import fs from "node:fs/promises";
import { XMLParser } from "fast-xml-parser";
const netlistPath = process.argv[2] ?? "reports/official-v3-netlist.xml";
const circuitPath = process.argv[3] ?? "dist/index/circuit.json";
const reference = new XMLParser({
ignoreAttributes: false,
attributeNamePrefix: "",
}).parse(await fs.readFile(netlistPath, "utf8"));
const circuit = JSON.parse(await fs.readFile(circuitPath, "utf8"));
const referenceComponents = new Set(
reference.export.components.comp.map((component) => component.ref),
);
const boardComponents = new Map(
circuit
.filter((element) => element.type === "source_component")
.map((component) => [component.source_component_id, component.name]),
);
const referenceNets = reference.export.nets.net
.filter((net) => !net.name.startsWith("unconnected-"))
.map((net) => ({
name: net.name,
pins: (Array.isArray(net.node) ? net.node : [net.node])
.filter((node) => !node.ref.startsWith("#"))
.map((node) => `${node.ref}.${node.pin}`)
.sort(),
}))
.filter((net) => net.pins.length > 1);
const referencePins = new Set(referenceNets.flatMap((net) => net.pins));
const boardNets = new Map();
const additionalConnectedPins = [];
const connectedPortIds = new Set(
circuit
.filter((element) => element.type === "source_trace")
.flatMap((trace) => trace.connected_source_port_ids),
);
for (const port of circuit.filter(
(element) => element.type === "source_port",
)) {
const componentName = boardComponents.get(port.source_component_id);
const pin = `${componentName}.${port.pin_number}`;
if (!referencePins.has(pin)) {
if (
!referenceComponents.has(componentName) &&
connectedPortIds.has(port.source_port_id)
)
additionalConnectedPins.push(pin);
continue;
}
const netKey = port.subcircuit_connectivity_map_key;
if (!netKey) throw new Error(`Missing connectivity for ${pin}`);
boardNets.set(netKey, [...(boardNets.get(netKey) ?? []), pin]);
}
const boardNetSignatures = new Set(
[...boardNets.values()].map((pins) => pins.sort().join("|")),
);
const mismatches = referenceNets.filter(
(net) => !boardNetSignatures.has(net.pins.join("|")),
);
const missingComponents = [...referenceComponents].filter(
(name) =>
!name.startsWith("#") && ![...boardComponents.values()].includes(name),
);
const report = {
netlistPath,
circuitPath,
scope:
"Pin-to-pin reference connectivity, not PCB routing or functional qualification. Additional test points are reported separately, not silently included in the official reference.",
matchedReferenceNets: referenceNets.length - mismatches.length,
referenceConnectedPins: referencePins.size,
additionalComponents: [...boardComponents.values()].filter(
(name) => !referenceComponents.has(name),
),
additionalConnectedPins,
missingComponents,
mismatches,
};
await fs.writeFile(
"reports/reference-connectivity.json",
JSON.stringify(report, null, 2),
);
console.log(report);
if (mismatches.length || missingComponents.length) process.exitCode = 1;