Source / Read the circuit
stream_reference.py
lessons/adc_digital/models/stream_reference.py
#!/usr/bin/env python3
"""ADC analog mathematical model -> RTL stream -> exact oracle and FFT."""
import argparse
import json
from pathlib import Path
from experiments import corrected, spectral, ti_signal
def require(condition,message):
if not condition: raise AssertionError(message)
def packed(values):
return sum((v & ((1<<18)-1)) << (18*i) for i,v in enumerate(values))
def generate(output, model_report):
output.mkdir(parents=True,exist_ok=True)
report=json.loads(model_report.read_text())
o=report['lessons']['AD15']['offset_q']; g=report['lessons']['AD15']['inverse_gain_q']
n,fs,b=65536,4e6,6001
raw=ti_signal(n+4,fs,fs*b/n,1000,[-8,4,10,-6],[.99,1.02,.98,1.01])
with (output/'raw.txt').open('w') as f:
for r in raw: f.write(str(r)+'\n')
(output/'coefficients.txt').write_text(f'{packed(o):x} {packed(g):x}\n')
(output/'manifest.json').write_text(json.dumps({'n':n,'fs':fs,'bin':b,
'offset_q':o,'gain_q':g,'raw':raw,'skip':4,'epoch':3,'version':1,
'model_source_sha256':report['source_sha256'],
'calibration':report['lessons']['AD13'],'evidence':'behavioral ADC + RTL, no analog signoff'},indent=2)+'\n')
print('ADC_STREAM_INPUT_COMPLETE samples=65540')
def verify(output):
m=json.loads((output/'manifest.json').read_text())
rows=(output/'stream.txt').read_text().splitlines()
require(len(rows)==m['n']+m['skip'],'stream count')
wave=[]
for n,line in enumerate(rows):
sid,value,sat,version,epoch=map(int,line.split())
require(sid==n and epoch==m['epoch'],'stream identity/epoch')
o=m['offset_q'][n%4] if n>=4 else 0
g=m['gain_q'][n%4] if n>=4 else 65536
expected,es=corrected(m['raw'][n],o,g)
require((value,sat)==(expected,es),f'stream integer mismatch {n}')
require(version==int(n>=4),'stream coefficient version')
require(sat==0,'stream saturation invalidates spectrum')
if n>=4: wave.append(value/16)
before=spectral(m['raw'][4:],m['bin']); after=spectral(wave,m['bin'])
require(after['sfdr_db']>before['sfdr_db']+15,'RTL controlled calibration SFDR improvement')
results={'before':before,'after_rtl':after,'samples':len(wave),'startup_skip':4,
'window':'coherent rectangular','power_units':'ADC LSB squared',
'meaning':'synthetic mismatch corrected by RTL; not real ADC performance'}
(output/'spectrum.json').write_text(json.dumps(results,indent=2)+'\n')
print(f'PASS RTL_STREAM samples={len(wave)} sfdr_before={before["sfdr_db"]:.3f} '
f'sfdr_after={after["sfdr_db"]:.3f} sndr_after={after["sndr_db"]:.3f}')
print('ADC_STREAM_VERIFICATION_COMPLETE')
if __name__=='__main__':
p=argparse.ArgumentParser(); p.add_argument('--generate',type=Path); p.add_argument('--models',type=Path)
p.add_argument('--verify',type=Path); a=p.parse_args()
if a.generate: generate(a.generate,a.models)
else: verify(a.verify)