0hmX/am3352-ddr-track-a-local-dfm-wip-20261007
Experimental RJ45-corrected board with isolated PG indication. 1005/1005 source joins pass; 15 expanded-guard physical errors, sourcing and qualification gates remain. Not fabrication-ready.
- Version
- 0.0.14
- License
- unset
- Stars
- 0
simulations-next/saved-board.tsx
// Adapted from tscircuit/pcb-spice-pipeline commit63d15671 (MIT). Only change: preserve saved board.outline during preview inflation.
import { createElement, Fragment, useLayoutEffect, useRef } from 'react';
export const importedBoardRecords = Symbol.for('pcb-spice-pipeline.imported-board.v2');
export const importedBoardDeclarations = Symbol.for('pcb-spice-pipeline.imported-board-declarations.v2');
export function savedRecords(circuitJson) {
return circuitJson.map(record => {
if (!record || typeof record !== 'object' || !('type' in record) || typeof record.type !== 'string')
throw new Error('ImportedBoard requires Circuit JSON records');
return record;
});
}
/** Preserves a routed board while core renders native simulation declarations. */
export function ImportedBoard({ circuitJson, children, fabricatorPreset, material }) {
const boardRef = useRef(null);
const declarationsRef = useRef(null);
const records = savedRecords(circuitJson);
if (records.some(record => record.type.startsWith('simulation_') && record.type !== 'simulation_voltage_source' && record.type !== 'simulation_current_source'))
throw new Error('ImportedBoard requires a physical saved board without existing simulation declarations or results; export circuitJson directly to run existing declarations');
for (const port of records.filter(record => record.type === 'source_port' && !record.source_component_id)) {
const group = records.find(record => record.type === 'source_group' && record.source_group_id === port.source_group_id);
if (port.source_component_id !== null || (group && group.parent_source_group_id))
throw new Error(`ImportedBoard cannot recover the owner of saved group pin ${port.name}; use ordinary TSX or export circuitJson directly`);
}
const board = records.find(record => record.type === 'pcb_board');
if (!board)
throw new Error('ImportedBoard requires a saved pcb_board record');
// Legacy component types are displayed as chips; simulation always receives
// the original saved records, including every route, pad and component type.
const preview = records.filter(record => record.type !== 'schematic_component').map(record => {
if (record.type === 'source_component')
return { ...record, ftype: 'simple_chip' };
return record;
});
for (const component of records.filter(record => record.type === 'source_component')) {
const ports = records.filter(record => record.type === 'source_port' && record.source_component_id === component.source_component_id);
const labels = Object.fromEntries(ports.map((port, index) => {
let pinNumber = port.pin_number;
if (pinNumber === undefined)
pinNumber = index + 1;
let aliases = [];
if (Array.isArray(port.port_hints))
aliases = port.port_hints;
return [`pin${pinNumber}`, [...new Set([port.name, ...aliases].filter((value) => typeof value === 'string' && value.length > 0))]];
}));
preview.push({ type: 'schematic_component', schematic_component_id: `preview_${component.source_component_id}`,
source_component_id: component.source_component_id, port_labels: labels });
}
useLayoutEffect(() => {
const instance = boardRef.current;
if (!instance)
throw new Error('ImportedBoard native board was not mounted');
instance[importedBoardRecords] = records;
const group = declarationsRef.current;
if (!group)
return;
instance[importedBoardDeclarations] = group;
// The saved-board importer requires circuitJson without JSX children. Move
// the native declaration group into the board before core render phases.
instance.add(group);
return () => { instance.remove(group); };
}, [circuitJson, children]);
return createElement(Fragment, null, createElement('board', { ref: boardRef, fabricatorPreset, material: material ?? board.material, width: board.width, height: board.height, thickness: board.thickness,
outline: board.outline, layers: board.num_layers, routingDisabled: true, schematicDisabled: true, placementDrcChecksDisabled: true,
circuitJson: preview }), createElement('group', { ref: declarationsRef, name: '__simulation_declarations' }, children));
}