krishnax12/t113-minimal-linux

Allwinner T113-S3 dual-Cortex-A7 SoC with integrated 128MB DDR3, multi-rail decoupling, 24MHz and 32.768kHz oscillators, filtering, and exposed test points.

Version
0.1.1
License
unset
Stars
0

scripts/check-design.py

"""Verify the schematic against an independent T113-S3 pin-number contract."""
import json, math, sys
from pathlib import Path
from routing_geometry import Nets

source = Path(sys.argv[1] if len(sys.argv)>1 else 'dist/index/circuit.json')
circuit = json.loads(source.read_text())
nets = Nets(circuit)
components = {c['name']:c for c in nets.of('source_component')}
checks = []
def pin(component_pin):
    component, number = component_pin
    matches = [p for p in nets.of('source_port') if p['source_component_id']==components[component]['source_component_id'] and p.get('pin_number')==number]
    if len(matches)!=1: raise ValueError(f'Expected one pin: {component}.{number}')
    return matches[0]
def tied(component_pin, net):
    return nets.source(pin(component_pin)['source_port_id'])==net
def check(name, passed):
    checks.append({'id':name,'passed':bool(passed)})

rails={'GND':[91,129],'VRTC1V8':[26],'V3V3':[29,34,66,77,83,128],'V0V9':[46,51,81,116,117],'V1V5':[48,49],'LDOA1V8':[20,28,50,65,89,97,107]}
for rail,pins in rails.items():check('soc_rail_'+rail,all(tied(('U_SOC',p),rail) for p in pins))
signals={7:'SD_D1',8:'SD_D0',9:'SD_CLK_SOC',10:'SD_CMD',11:'SD_D3',12:'SD_D2',13:'SD_CD_N',14:'PC7',15:'PC6',16:'PC5',17:'PC4',18:'PC3',21:'REFCLK24M',22:'DXOUT',23:'DXIN',24:'X32KOUT',25:'X32KIN',27:'RESET_N',30:'LDOB_OUT',33:'UART0_RX',35:'UART0_TX',47:'DDR_ZQ',52:'PD22',90:'VRA2',92:'VRA1',100:'HPOUTFB',110:'TVIN_VRP',111:'TVIN_VRN',114:'USB0_DM',115:'USB0_DP'}
check('soc_signals',all(tied(('U_SOC',p),net) for p,net in signals.items()))
used=set(signals)|{p for pins in rails.values() for p in pins}
check('unused_soc_pins_nc',all(pin(('U_SOC',p)).get('do_not_connect') is True for p in range(1,130) if p not in used))
soc_ids={pin(('U_SOC',p))['source_port_id'] for p in range(1,130)}
physical={p['source_port_id']:p['pcb_port_id'] for p in nets.of('pcb_port')}
check('soc_129_physical_pins',all(sid in physical and any(pad.get('pcb_port_id')==physical[sid] for pad in nets.of('pcb_smtpad')) for sid in soc_ids))
sd={1:'SD_D2',2:'SD_D3',3:'SD_CMD',4:'V3V3',5:'SD_CLK',6:'GND',7:'SD_D0',8:'SD_D1',9:'SD_CD_N',10:'GND',11:'GND',12:'GND',13:'GND'}
usb={13:'GND',14:'GND',15:'GND',26:'GND',16:'USB0_VBUS',25:'USB0_VBUS',18:'USB_CC1',24:'USB_CC2',20:'USB0_DP',22:'USB0_DP',19:'USB0_DM',21:'USB0_DM'}
check('sd_pinout',all(tied(('J_SD',p),net) for p,net in sd.items()))
check('usb_pinout',all(tied(('J_USB_FEL',p),net) for p,net in usb.items()))
check('uart_pinout',all(tied(('J_UART',p),net) for p,net in enumerate(['GND','UART_HEADER_TX','UART_HEADER_RX'],1)))
for name in ['R_FEL_CC1','R_FEL_CC2']:check(name+'_5k1',math.isclose(components[name]['resistance'],5100) and tied((name,2),'GND'))
check('cc_independent',nets.find(pin(('R_FEL_CC1',1))['source_port_id'])!=nets.find(pin(('R_FEL_CC2',1))['source_port_id']))
check('vbus_gpio_isolation',not tied(('U_SOC',52),'USB0_VBUS') and tied(('Q_USB0_SENSE',2),'GND'))
check('input_fuse',tied(('F_USB_1A1',1),'USB0_VBUS') and tied(('F_USB_1A1',2),'V5'))
check('rtc_ldo',tied(('U104',1),'V5') and tied(('U104',5),'VRTC1V8'))
check('rtc_before_io',tied(('U105',5),'VRTC1V8') and tied(('U105',1),'EN_IO') and tied(('U101',1),'EN_IO'))
check('io_before_core_ddr',tied(('U106',5),'V3V3') and tied(('U106',1),'EN_CORE_DDR') and all(tied((f'U{p}',1),'EN_CORE_DDR') for p in [102,103]))
check('pg_holds_reset',all(tied((f'U{p}',5),'RESET_REQUEST_N') for p in [101,102,103]) and tied(('U107',3),'RESET_REQUEST_N'))
check('reset_1v8_domain',tied(('U107',1),'RESET_N') and tied(('R114',1),'VRTC1V8'))
for upper,lower,expected in [('R101','R102',3.318),('R103','R104',0.8994),('R105','R106',1.5)]:check('buck_divider_'+upper,math.isclose(0.6*(1+components[upper]['resistance']/components[lower]['resistance']),expected,abs_tol=.0001))
check('ldob_not_ddr',nets.find(nets.ids['LDOB_OUT'])!=nets.find(nets.ids['V1V5']))
check('four_layers',nets.of('pcb_board')[0]['num_layers']==4)
check('no_circuit_errors',not any(r['type'].endswith('_error') for r in circuit))
report={'passed':all(c['passed'] for c in checks),'checks':checks,'sourceComponents':len(components),'source':str(source)}
Path('routing/design-check.json').write_text(json.dumps(report,indent=2)+'\n')
print(json.dumps(report,indent=2))
if not report['passed']:sys.exit(1)