0hmX/am62l-lpddr4-breakout-repro

This code defines React components that instantiate circuits representing dedicated DDR address control and byte0 data lines.

Version
1.0.11
License
unset
Stars
0

scripts/verify-circuit-json.ts

import { readdir } from "node:fs/promises"
import { DDR_CONNECTIONS } from "../ddr-connections"

type CircuitJsonElement = Record<string, unknown> & { type: string }

const circuitJsonPath = process.argv[2] ?? "dist/index/circuit.json"
const circuitJson = (await Bun.file(circuitJsonPath).json()) as CircuitJsonElement[]

const elementsOfType = (type: string) =>
  circuitJson.filter((element) => element.type === type)
const namesOf = (elements: CircuitJsonElement[]) =>
  elements
    .map((element) => element.name)
    .filter((name): name is string => typeof name === "string")
    .sort()

const expectedTraceNames = DDR_CONNECTIONS.map(({ traceName }) => traceName).sort()
const sourceTraces = elementsOfType("source_trace")
const sourceTraceNames = namesOf(sourceTraces)
const breakoutNames = ["RAM_BREAKOUT", "SOC_BREAKOUT"]
const sourceBreakoutGroups = elementsOfType("source_group").filter((element) =>
  breakoutNames.includes(String(element.name)),
)
const pcbBreakoutGroups = elementsOfType("pcb_group").filter((element) =>
  breakoutNames.includes(String(element.name)),
)
const breakoutPoints = elementsOfType("pcb_breakout_point")
const pcbTraces = elementsOfType("pcb_trace")
const pcbVias = elementsOfType("pcb_via")

const assert: (condition: unknown, message: string) => asserts condition = (
  condition,
  message,
) => {
  if (!condition) throw new Error(message)
}

assert(sourceTraces.length === 33, `Expected 33 source traces, got ${sourceTraces.length}`)
assert(
  JSON.stringify(sourceTraceNames) === JSON.stringify(expectedTraceNames),
  `Source trace names differ:\nexpected ${expectedTraceNames.join(", ")}\nactual ${sourceTraceNames.join(", ")}`,
)
assert(
  sourceBreakoutGroups.length === 2,
  `Expected two source breakout groups, got ${sourceBreakoutGroups.length}`,
)
assert(
  pcbBreakoutGroups.length === 2,
  `Expected two breakout PCB groups, got ${pcbBreakoutGroups.length}`,
)

const source = await Bun.file("index.circuit.tsx").text()
const forbiddenSourcePatterns: Array<[RegExp, string]> = [
  [/<via(?:\s|>)/i, "<via>"],
  [/<breakoutpoint(?:\s|>)/i, "<breakoutpoint>"],
  [/<pcbtrace(?:\s|>)/i, "manual PCB trace primitive"],
  [/algorithmFn/, "algorithmFn"],
  [/GenericLocalAutorouter/, "GenericLocalAutorouter"],
  [/\broutingDisabled\b/, "routingDisabled"],
  [/\bpcbRoutingDisabled\b/, "pcbRoutingDisabled"],
  [/am62l-classified-autorouter/, "am62l-classified-autorouter"],
  [/ti-am62l-evm-ddr-routes/, "ti-am62l-evm-ddr-routes"],
]
const forbiddenMatches = forbiddenSourcePatterns
  .filter(([pattern]) => pattern.test(source))
  .map(([, label]) => label)
assert(
  forbiddenMatches.length === 0,
  `Forbidden source-level routing constructs found: ${forbiddenMatches.join(", ")}`,
)

const breakoutPointCounts = Object.fromEntries(
  pcbBreakoutGroups.map((group) => [
    String(group.name),
    breakoutPoints.filter(
      (point) => point.pcb_group_id === group.pcb_group_id,
    ).length,
  ]),
)

const errorTypes = [
  "pcb_autorouting_error",
  "pcb_trace_error",
  "pcb_pad_trace_clearance_error",
  "pcb_via_clearance_error",
]
const errors = Object.fromEntries(
  errorTypes.map((type) => [
    type,
    elementsOfType(type).map((error) => ({
      id: error[`${type}_id`] ?? error.pcb_error_id,
      message: error.message,
    })),
  ]),
)

const debugDirectory = "dist/autorouter-debug"
let phaseInputs: Array<{
  file: string
  connectionCount: number
  routingPcbGroupIds: string[]
}> = []
try {
  const debugFiles = await readdir(debugDirectory)
  const phaseInputFiles = debugFiles
    .filter((file) => /^phase-\d+\.input\.simple-route\.json$/.test(file))
    .sort((left, right) =>
      left.localeCompare(right, undefined, { numeric: true }),
    )
  phaseInputs = await Promise.all(
    phaseInputFiles.map(async (file) => {
      const input = (await Bun.file(`${debugDirectory}/${file}`).json()) as {
        connections?: Array<{ routingPcbGroupId?: string }>
      }
      const connections = input.connections ?? []
      return {
        file,
        connectionCount: connections.length,
        routingPcbGroupIds: [
          ...new Set(
            connections
              .map((connection) => connection.routingPcbGroupId)
              .filter((id): id is string => Boolean(id)),
          ),
        ],
      }
    }),
  )
} catch {
  phaseInputs = []
}

const installedCorePackage = (await Bun.file(
  "node_modules/@tscircuit/core/package.json",
).json()) as { version: string }
assert(
  installedCorePackage.version === "0.0.1703",
  `Expected installed @tscircuit/core 0.0.1703, got ${installedCorePackage.version}`,
)

let routingTiming: unknown = null
if (await Bun.file("dist/routing-timing.json").exists()) {
  routingTiming = await Bun.file("dist/routing-timing.json").json()
}

const report = {
  circuitJsonPath,
  expectedCore: {
    version: "0.0.1703",
    gitHead: "23817c9f55dc36a1b647b52dd27152ee51e55ba5",
  },
  installedCoreVersion: installedCorePackage.version,
  sourceTraceCount: sourceTraces.length,
  sourceTraceNames,
  sourceBreakoutGroupCount: sourceBreakoutGroups.length,
  pcbBreakoutGroupCount: pcbBreakoutGroups.length,
  breakoutPointCount: breakoutPoints.length,
  breakoutPointCounts,
  automaticPcbTraceCount: pcbTraces.length,
  automaticPcbViaCount: pcbVias.length,
  forbiddenSourceConstructs: forbiddenMatches,
  phaseInputs,
  errors,
  routingTiming,
}

await Bun.write(
  "dist/verification-report.json",
  `${JSON.stringify(report, null, 2)}\n`,
)
console.log(JSON.stringify(report, null, 2))

if (breakoutPoints.length !== 66) {
  console.warn(`Expected ideally 66 breakout points, got ${breakoutPoints.length}`)
}