AnasSarkiz/am625sip-linux

An electronic component representing an AM625 system-in-package with mapped pins and physical footprint for PCB integration.

Version
1.0.3
License
unset
Stars
0

scripts/validate-artifact.mjs

import assert from "node:assert/strict"
import { readFileSync } from "node:fs"

const circuitJson = JSON.parse(readFileSync("dist/index/circuit.json", "utf8"))
const expectedBreakoutCount = Number(process.argv[2] ?? 2)
const errors = circuitJson.filter((element) => element.type.endsWith("_error"))
assert.equal(errors.length, 0, JSON.stringify(errors, null, 2))

const processor = circuitJson.find(
  (element) => element.type === "source_component" && element.name === "U1",
)
assert.ok(processor, "Processor must be present")
const ports = circuitJson.filter(
  (element) => element.type === "source_port" && element.source_component_id === processor.source_component_id,
)
assert.equal(ports.length, 425, "The full 425-ball processor must be present")
const traces = circuitJson.filter((element) => element.type === "pcb_trace")
const sourceTraces = circuitJson.filter((element) => element.type === "source_trace")
const breakoutPoints = circuitJson.filter((element) => element.type === "pcb_breakout_point")
assert.equal(sourceTraces.length, expectedBreakoutCount)
assert.equal(breakoutPoints.length, expectedBreakoutCount)
assert.equal(traces.length, 2 * expectedBreakoutCount, "Every connection needs fanout and downstream copper")
for (const sourceTrace of sourceTraces) {
  const netTraces = traces.filter((trace) => trace.source_trace_id === sourceTrace.source_trace_id)
  assert.equal(netTraces.length, 2)
  const fanoutTrace = netTraces.find((trace) => trace.pcb_trace_id.startsWith("fanout:"))
  const downstreamTrace = netTraces.find((trace) => !trace.pcb_trace_id.startsWith("fanout:"))
  assert.ok(fanoutTrace && downstreamTrace, "Both routing phases must produce copper")
  const breakoutPoint = breakoutPoints.find((point) => point.source_trace_id === sourceTrace.source_trace_id)
  assert.ok(breakoutPoint)
  const fanoutEnd = fanoutTrace.route.at(-1)
  assert.equal(fanoutEnd.layer, breakoutPoint.layer, "Breakout layer must match actual copper")
  assert.ok(Math.hypot(fanoutEnd.x - breakoutPoint.x, fanoutEnd.y - breakoutPoint.y) < 0.001)
  const downstreamEnds = [downstreamTrace.route[0], downstreamTrace.route.at(-1)]
  assert.ok(downstreamEnds.some((end) => end.layer === fanoutEnd.layer &&
    Math.hypot(end.x - fanoutEnd.x, end.y - fanoutEnd.y) < 0.001), "Routing phases must join physically")
  const pcbPorts = sourceTrace.connected_source_port_ids.map((sourcePortId) =>
    circuitJson.find((element) => element.type === "pcb_port" && element.source_port_id === sourcePortId))
  assert.ok(pcbPorts.every(Boolean))
  for (const pcbPort of pcbPorts) {
    assert.ok(netTraces.some((trace) => [trace.route[0], trace.route.at(-1)].some((end) =>
      pcbPort.layers.includes(end.layer) && Math.hypot(end.x - pcbPort.x, end.y - pcbPort.y) < 0.001)),
    "Both physical endpoints must be reached")
  }
}
const schematicPorts = circuitJson.filter((element) => element.type === "schematic_port" &&
  ports.some((port) => port.source_port_id === element.source_port_id))
assert.equal(schematicPorts.length, 425)
assert.equal(new Set(schematicPorts.map((port) => port.source_port_id)).size, 425,
  "Schematic units must represent every processor ball exactly once")
assert.equal(circuitJson.filter((element) => element.type === "schematic_sheet").length, 2)
assert.ok(circuitJson.some((element) => element.type === "source_group" && element.is_subcircuit), "Processor must be a real subcircuit")
console.log(`PASS: 425 processor ports, ${traces.length} routed breakout traces, zero circuit JSON errors`)