hrithik18k/punck-tscircuit-recreation
A four-layer Eurorack drum/sampler controller PCB built around an STM32H743, dual QSPI flash, PCM5100 stereo DAC, TL074 analog audio circuitry, input clamps, 12V-to-3.3V power regulation, MIDI/USB/SWD connectors, controls, LEDs, and trigger/audio I/O.
- Version
- 1.0.3
- License
- unset
- Stars
- 0
scripts/verify-native.ts
import fs from 'node:fs'
const report=[]
for(const name of ['components','controls']) {
const original=JSON.parse(fs.readFileSync(`prepared/${name}.circuit.json`,'utf8'))
const data=JSON.parse(fs.readFileSync(`native/${name}.json`,'utf8'))
const actual=JSON.parse(fs.readFileSync(`dist/native/${name}/circuit.json`,'utf8'))
const mismatch:any[]=[]
const sourcePorts=actual.filter((e:any)=>e.type==='source_port')
const srcNets=actual.filter((e:any)=>e.type==='source_net')
const traces=actual.filter((e:any)=>e.type==='source_trace')
for(const part of data.parts.filter((p:any)=>p.pins.length)) {
const component=actual.find((e:any)=>e.type==='source_component'&&e.name===part.name)
for(const pin of part.pins) {
const oldComponent=original.find((e:any)=>e.type==='source_component'&&e.name===part.name)
const oldPort=original.find((e:any)=>e.type==='source_port'&&e.source_component_id===oldComponent?.source_component_id&&e.name.replace(/^pin(?=\d)/,'')===pin.id)
const oldTrace=original.find((e:any)=>e.type==='source_trace'&&e.connected_source_port_ids.includes(oldPort?.source_port_id))
const oldNet=original.find((e:any)=>e.type==='source_net'&&oldTrace?.connected_source_net_ids.includes(e.source_net_id))?.name
if(oldNet!==pin.net)mismatch.push({part:part.name,pin:pin.id,error:'native net differs from original',original:oldNet,native:pin.net})
const port=sourcePorts.find((e:any)=>e.source_component_id===component?.source_component_id&&e.port_hints?.includes(pin.selector))
if(!port){mismatch.push({part:part.name,pin:pin.selector,error:'missing source port'});continue}
const pcb=actual.filter((e:any)=>e.type==='pcb_port'&&e.source_port_id===port.source_port_id)
if(!pcb.length)mismatch.push({part:part.name,pin:pin.selector,error:'missing PCB port'})
if(pin.nc||!pin.net)continue
const attached=new Set(traces.filter((e:any)=>e.connected_source_port_ids.includes(port.source_port_id)).flatMap((e:any)=>e.connected_source_net_ids).map((id:string)=>srcNets.find((n:any)=>n.source_net_id===id)?.name))
if(!attached.has(pin.net))mismatch.push({part:part.name,pin:pin.selector,expected:pin.net,actual:[...attached]})
}
}
const sch=actual.filter((e:any)=>e.type==='schematic_component')
const pcb=actual.filter((e:any)=>e.type==='pcb_component')
const shared=pcb.filter((p:any)=>sch.some((s:any)=>s.source_component_id===p.source_component_id)).length
const errors=actual.filter((e:any)=>e.type.endsWith('_error'))
report.push({name,pcbComponents:pcb.length,schematicComponents:sch.length,sharedComponentIdentities:shared,sourcePorts:sourcePorts.length,padCount:actual.filter((e:any)=>['pcb_smtpad','pcb_plated_hole'].includes(e.type)).length,originalPadCount:original.filter((e:any)=>['pcb_smtpad','pcb_plated_hole'].includes(e.type)).length,routedTraces:actual.filter((e:any)=>e.type==='pcb_trace').length,vias:actual.filter((e:any)=>e.type==='pcb_via').length,mismatch,errors})
}
fs.writeFileSync('evidence/native-verification.json',JSON.stringify(report,null,2))
console.log(JSON.stringify(report,null,2))
if(report.some(r=>r.mismatch.length||r.errors.length||!r.routedTraces||r.sharedComponentIdentities!==r.pcbComponents))process.exitCode=1