Automated Python Test Frameworks for Hardware Verification and Validation

21
Automated Python Test Frameworks for Hardware Validation and Verification Barbara Jones

description

Codemash 2012

Transcript of Automated Python Test Frameworks for Hardware Verification and Validation

Page 1: Automated Python Test Frameworks for Hardware Verification and Validation

Automated Python Test Frameworks for Hardware Validation and Verification

Barbara Jones

Page 2: Automated Python Test Frameworks for Hardware Verification and Validation

About Me

Barbara [email protected]

Test & Measurement Data Acquisition

Page 3: Automated Python Test Frameworks for Hardware Verification and Validation

Boeing 787 Fatigue Test

Rack of instruments to measure strain

Page 4: Automated Python Test Frameworks for Hardware Verification and Validation

Definitions & Theory Strain gauge Thermocouple Channel Sample rate Waveform Waveform generator

Page 5: Automated Python Test Frameworks for Hardware Verification and Validation

Why test hardware?

VerificationValidation

Page 6: Automated Python Test Frameworks for Hardware Verification and Validation

Software Techniques Don’t Help

Unit TestsMockingTDD

Page 7: Automated Python Test Frameworks for Hardware Verification and Validation

What does help?

Spec-based testingTest stand automationA good test framework

Page 8: Automated Python Test Frameworks for Hardware Verification and Validation

Bed-of-nails tester

Engineeringtest rig

Page 9: Automated Python Test Frameworks for Hardware Verification and Validation
Page 10: Automated Python Test Frameworks for Hardware Verification and Validation

Test Framework Requirements Easily design

broad tests from spec

Control external equipment

Easy math handling

def module_test_1(suite, cl, slave_cls): def verify(result, success, args): if not success: return False if result[-1] != args: return False return True arg1 = 0.1 arg2 = 0.2 calls = [Call(cl.InstrumentSpecific.ThisIsAMethod, arg1, arg2), Set(cl.InstrumentSpecific, "ThisIsAProperty", arg1), Get(cl.InstrumentSpecific, "ThisIsAProperty")] suite.add(calls, verify, arg1) def add(suite, cl, slave_cls): module_test_1(suite, cl, slave_cls)

Page 11: Automated Python Test Frameworks for Hardware Verification and Validation

Designing tests based on hardware specsPhase alignment on multiple instruments must

be within 0.000010 arc seconds

𝑋𝑘=∑𝑛=0

𝑁− 1

𝑥𝑛𝑒−2𝜋 𝑘

𝑁𝑛

𝐴𝑘=|𝑋𝑘|=√ℜ ( 𝑋𝑘)2+ℑ (𝑋𝑘 )2

Discrete Fourier Transform

Amplitude

Phase

𝜙𝑘=atan 2( ℑ (𝑋𝑘 ) ,ℜ (𝑋𝑘 ) )

Page 12: Automated Python Test Frameworks for Hardware Verification and Validation

Phase Alignment

Aligned

Out of Phase

Page 13: Automated Python Test Frameworks for Hardware Verification and Validation

Controlling external equipment

Agilent 33220A Waveform Generator

Specifications IEEE 488.2 (1975) SCPI (1990) VXI-11 (1995)

Page 14: Automated Python Test Frameworks for Hardware Verification and Validation

from vxi11client import * class ag33120(TCPVXI11Client): timeout = 10000 def __init__(self, hostname, gpib): TCPVXI11Client.__init__(self, hostname, 1, gpib) def query(self, str): self.device_write(self.lid, self.timeout, self.timeout, 0, str) return self.device_read(self.lid, 256, self.timeout, self.timeout, 0x80, 0x0a) def check_error(self): res = self.query(":SYST:ERR?\n") err, msg = res.data.split(",") if int(err) != 0: raise Exception(res.data) def reset(self): self.device_write(self.lid, self.timeout, self.timeout, 0, "*RST;\n") def apply(self, func, freq=None, amp=None, off=None): freq = self._defopt(freq) amp = self._defopt(amp) off = self._defopt(off) return self.query("APPLY:%s %s, %s, %s; *OPC?\n" % (func, freq, amp, off)) def _defopt(self, arg): if arg == None: return "DEF" return "%12.7e" % arg

Controlling external equipment

Page 15: Automated Python Test Frameworks for Hardware Verification and Validation

def dc(self, off=None): return self.query("APPLY:DC 1, 1, %s; *OPC?\n" % (off)) def set_highimpedance_mode(self): return self.query("OUTP:LOAD 9.9E37; *OPC?\n") def sine(self, freq=None, amp=None, off=None): return self.apply("SIN", freq, amp, off) def square(self, freq=None, amp=None, off=None): return self.apply("SQU", freq, amp, off) def triangle(self, freq=None, amp=None, off=None): return self.apply("TRI", freq, amp, off) def ramp(self, freq=None, amp=None, off=None): return self.apply("RAMP", freq, amp, off)

Controlling external equipment

Page 16: Automated Python Test Frameworks for Hardware Verification and Validation

Phase Alignment Test

# Data acquisition characteristics: FILTER_TYPE = ex1629constants.IIRFILTER_TYPE_NONE SAMP_FREQ = 1000.0 SAMPLE_COUNT = 1000 # Expected input: 1V peak (2V peak-to-peak) sine wave at 10Hz. INPUT_AMPLITUDE = 1 INPUT_FREQ = 10 # Maximum tolerated skew (in seconds): MAX_PERMISSIBLE_SKEW = 0.000010 def add_phase_test(suite, cl, slave_cls, wavegen) def add(suite, cl, slave_cls): wavegen = require_slaves(slave_cls, "ag33120") slaves = require_slaves(slave_cls, "ex1629") add_phase_test(suite, cl, slaves, wavegen)

Page 17: Automated Python Test Frameworks for Hardware Verification and Validation

def add_phase_test(suite, cl, slave_cls, wavegen): # Constant parameters PI = 4*atan(1) if suite.test_level == test.FULL_TEST: NUM_INNER_LOOPS = 2000 # approximately 13 hours with two devices else: NUM_INNER_LOOPS = 10 # approximately 4 minutes with 2 devices def verify(result, success, args): # Since the actual data analysis was performed in analyze_data, # we only need to check the function call returns to determine # overall success/failure. for call_result in result: if call_result == False: return False return success # set up the waveform generator # Sine wave at 10Hz, 1V peak (2V peak-to-peak), no offset calls = [Call(wavegen.reset), Call(wavegen.set_highimpedance_mode), Call(wavegen.sine(INPUT_FREQ, INPUT_AMPLITUDE, 0)] suite.add(calls) for config_name in config_sequence

Setup & Verify

Page 18: Automated Python Test Frameworks for Hardware Verification and Validation

for config_name in config_sequence: calls = [] # Configure the master & slave devices calls += configure_device(cl) calls += configure_device_trigger(cl, configs[config_name]['master']) for slave_cl in slave_cls: calls += configure_device(slave_cl) calls += configure_device_trigger(slave_cl, configs[config_name]['slave']) suite.add(calls, verify, None) for inner_loop in range(0, NUM_INNER_LOOPS): calls = [] # Instruct the master device to issue a sync pulse calls += [Call(cl.soft_sync)] # Start acquiring data on each slave device for slave_cl in slave_cls: calls += [Call(slave_cl.trig_init)] # Start acquiring data on the master device calls += [Call(cl.trig_init)] # Issue a soft trigger command to the master device calls += [Call(cl.soft_trig)] # Read the data calls += [Call(analyze_data, cl, slave_cls, config_name)] suite.add(calls, verify, None) # Reset the slave devices & the master device calls = [] for slave_cl in slave_cls: calls += [Call(slave_cl.reset)] calls += [Call(cl.reset)] suite.add(calls, verify, None)

Test Sequence

Page 19: Automated Python Test Frameworks for Hardware Verification and Validation

N = len(device_result.datapages) n = INPUT_FREQ * N / SAMP_FREQ val_dft_real = val_dft_imag = 0.0 k = 0 for page in device_result.datapages: val_dft_real += page.dataset[board][0].data[0] * cos(2*PI*n*k/N) val_dft_imag -= page.dataset[board][0].data[0] * sin(2*PI*n*k/N) k += 1 val_magnitude = sqrt(pow(val_dft_imag, 2) + pow(val_dft_real, 2))/N val_phase = atan2(val_dft_imag , val_dft_real)

DFT Calculation

Page 20: Automated Python Test Frameworks for Hardware Verification and Validation

Phase Alignment Test Data

Page 21: Automated Python Test Frameworks for Hardware Verification and Validation

Questions?