Developing a DSP Algorithm using a TTD process Application FIR filter.

Slides:



Advertisements
Similar presentations
DSPs Vs General Purpose Microprocessors
Advertisements

Processor Architecture Needed to handle FFT algoarithm M. Smith.
The Assembly Language Level
Programming Types of Testing.
Programming Logic and Design, Third Edition Comprehensive
This presentation will probably involve audience discussion, which will create action items. Use PowerPoint to keep track of these action items during.
Software and Hardware Circular Buffer Operations First presented in ENCM There are 3 earlier lectures that are useful for midterm review. M. R.
ENCM 515 Review talk on 2001 Final A. Wong, Electrical and Computer Engineering, University of Calgary, Canada ucalgary.ca.
Generation of highly parallel code for TigerSHARC processors An introduction This presentation will probably involve audience discussion, which will create.
Introduction to Analysis of Algorithms
Understanding the TigerSHARC ALU pipeline Determining the speed of one stage of IIR filter.
Chapter 6. 2 Objectives You should be able to describe: Function and Parameter Declarations Returning a Single Value Pass by Reference Variable Scope.
Computer Science 1620 Programming & Problem Solving.
Getting the O in I/O to work on a typical microcontroller Activating a FLASH memory “output line” Part 1 Main part of Laboratory 1 Also needed for “voice.
ECE122 L17: Method Development and Testing April 5, 2007 ECE 122 Engineering Problem Solving with Java Lecture 17 Method Development and Testing.
Kathy Grimes. Signals Electrical Mechanical Acoustic Most real-world signals are Analog – they vary continuously over time Many Limitations with Analog.
Digital Signal Processors for Real-Time Embedded Systems By Jeremy Kohel.
Averaging Filter Basic SHARC assembly and adding automated tests Example of project development on SHARC using C++ and assembly Planned for Tutorial Thursday.
An Introduction Chapter Chapter 1 Introduction2 Computer Systems  Programmable machines  Hardware + Software (program) HardwareProgram.
สาขาวิชาเทคโนโลยี สารสนเทศ คณะเทคโนโลยีสารสนเทศ และการสื่อสาร.
Ultra sound solution Impact of C++ DSP optimization techniques.
Assembly Language Review Being able to repeat on the Blackfin the things we were able to do on the MIPS 9/19/2015 Review of 50% OF ENCM369 in 50 minutes1.
Processor Architecture Needed to handle FFT algoarithm M. Smith.
Operator Precedence First the contents of all parentheses are evaluated beginning with the innermost set of parenthesis. Second all multiplications, divisions,
Data Structures Week 5 Further Data Structures The story so far  We understand the notion of an abstract data type.  Saw some fundamental operations.
CS 360 Lecture 3.  The software process is a structured set of activities required to develop a software system.  Fundamental Assumption:  Good software.
A First Book of C++: From Here To There, Third Edition2 Objectives You should be able to describe: Function and Parameter Declarations Returning a Single.
DEPARTMENT OF COMPUTER SCIENCE & TECHNOLOGY FACULTY OF SCIENCE & TECHNOLOGY UNIVERSITY OF UWA WELLASSA 1 CST 221 OBJECT ORIENTED PROGRAMMING(OOP) ( 2 CREDITS.
Understanding the TigerSHARC ALU pipeline Determining the speed of one stage of IIR filter – Part 3 Understanding the memory pipeline issues.
SE: CHAPTER 7 Writing The Program
Averaging Filter Comparing performance of C++ and ‘our’ ASM Example of program development on SHARC using C++ and assembly Planned for Tuesday 7 rd October.
© Janice Regan, CMPT 300, May CMPT 300 Introduction to Operating Systems Memory: Relocation.
Generating “Rectify( )” Test driven development approach to TigerSHARC assembly code production Assembly code examples Part 1 of 3.
Ultra sound solution Profiles and other optimizations.
Moving Arrays -- 1 Completion of ideas needed for a general and complete program Final concepts needed for Final Review for Final – Loop efficiency.
Blackfin Array Handling Part 1 Making an array of Zeros void MakeZeroASM(int foo[ ], int N);
12/14/2015 Concept of Test Driven Development applied to Embedded Systems M. Smith University of Calgary, Canada 1 Automated Testing Environment Concepts.
CPSC 873 John D. McGregor Session 9 Testing Vocabulary.
A FIRST BOOK OF C++ CHAPTER 6 MODULARITY USING FUNCTIONS.
CPSC 871 John D. McGregor Module 8 Session 1 Testing.
The Instruction Set Architecture. Hardware – Software boundary Java Program C Program Ada Program Compiler Instruction Set Architecture Microcode Hardware.
Systematic development of programs with parallel instructions SHARC ADSP21XXX processor M. Smith, Electrical and Computer Engineering, University of Calgary,
A first attempt at learning about optimizing the TigerSHARC code TigerSHARC assembly syntax.
A First Book of ANSI C Fourth Edition
Software Engineering Algorithms, Compilers, & Lifecycle.
CPSC 372 John D. McGregor Module 8 Session 1 Testing.
Generating a software loop with memory accesses TigerSHARC assembly syntax.
John D. McGregor Session 9 Testing Vocabulary
Algorithm Analysis CSE 2011 Winter September 2018.
John D. McGregor Session 9 Testing Vocabulary
John D. McGregor Session 9 Testing Vocabulary
Software and Hardware Circular Buffer Operations
Generating “Rectify( )”
Trying to avoid pipeline delays
Generating a software loop with memory accesses
Understanding the TigerSHARC ALU pipeline
Handling Arrays Completion of ideas needed for a general and complete program Final concepts needed for Final.
ENCM515 Standard and Custom FIR filters for Lab. 4
VisualDSP++ and Test Driven Development What happened last lecture?
Handling Arrays Completion of ideas needed for a general and complete program Final concepts needed for Final.
* M. R. Smith 07/16/96 This presentation will probably involve audience discussion, which will create action items. Use PowerPoint.
Getting serious about “going fast” on the TigerSHARC
Concept of TDD Test Driven Development
Explaining issues with DCremoval( )
General Optimization Issues
Handling Arrays Completion of ideas needed for a general and complete program Final concepts needed for Final.
Understanding the TigerSHARC ALU pipeline
A first attempt at learning about optimizing the TigerSHARC code
Working with the Compute Block
ENCM515 Standard and Custom FIR filters
Presentation transcript:

Developing a DSP Algorithm using a TTD process Application FIR filter

TTD and XPI and TTD XPI – eXtreme Programming inspired life cycle TTD – test driven development Main tool Automated testing framework Reference:- A More Agile Approach to Embedded System Development, Smith et al., IEEE Software magazine, March, /5/2016 Testing FIR filters Copyright 2 / 33

XP inspired development process Stage 1: Envisioning embedded product This stage produces requirements. The customers or end users (domain-knowledgeable personnel) should be able to specify their ideas as a set of acceptance tests (in conjunction with standard user stories) in a straightforward manner. User stories – Wish list of what you would like the product to do Now prioritize the wish list for the first part that customer identifies as most important. Plan to develop, deliver and demonstrate a prototype. 6/5/2016 Testing FIR filters Copyright 3 / 33

XPI: Stage 2: Prototyping Domain-knowledgeable technical personnel produce an initial prototype to analyze the proposed embedded solution. The solution would revolve around numerical algorithms implemented in a mathematically oriented scripting language such as Matlab. Developing additional acceptance test cases. Using TDD supported by a testing framework designed for Matlab development. Stage 1’s acceptance tests provide the initial skeleton for the prototype, Stage 2 adds “flesh” onto this outline. 6/5/2016 Testing FIR filters Copyright 4 / 33

Stage 3: Initial XPI Production System We must rewrite the system in a high-level compiled language such as C or C++. The biggest issues here surround the refactoring necessary to support moving Matlab floating-point calculations onto high speed, low-cost embedded processors that can handle integer operations. Stage 3 basically repeats the pattern from Stage 2, but in a new programming language using a new unit-testing framework. However, because of the existence of the previous stages, we’ve already constructed numerous tests. 6/5/2016 Testing FIR filters Copyright 5 / 33

Stage 4: Full Production System By the fourth stage, we’re fully involved with the target embedded environment itself. The system, although repeating earlier patterns, now needs to adapt to its new hardware environment with limited memory resources and must support interactions with device-specific peripherals on the target system. The system undergoes further modification to tune for the required performance by rewriting inefficient programming constructs, using signal-processing-specific #pragma state- to direct architecturally aware compilers, and rewriting critical components in low-level, highly customized machine code. 6/5/2016 Testing FIR filters Copyright 6 / 33

Assign. 1 From individual assignment 1 you have C++ un-optimized averaging filter Compiler optimized C++ averaging filter ASM version – software loop – averaging filter Tests for averaging filter (function, timing and theory comparison) 6/5/2016 Testing FIR filters Copyright 7 / 33

Steps in optimizing y[m] = Sum x[m – n] where n = 0 to N-1 Data stored oldest to newest x[m-n+1], x[m-n+2] … x[1], x[0] FIFO[0] ……………………………...FIFO[n-1] so that possible use of hardware circular buffers which go forward We code as sum = 0; for count = 0 to N-1 sum = sum + FIFO[n-1-count]; This “array” code requires specific DAG memory adds – slow because difficult to combine with other instructions (not enough instruction bits) 6/5/2016 Testing FIR filters Copyright 8 / 40

Steps in optimizing – Step 2 We code as sum = 0; for count = 0 to N-1 sum = sum + FIFO[n-1-count]; This “array” code requires specific DAG memory adds – slow because difficult to combine with other instructions (not enough instruction bits) Change to pointer operation using post decrement FIFOpt = & FIFO[n-1-count]; sum = 0; for count = 0 to N-1 sum = sum + * FIFOpt--; Change to averaging FIR filter which access coefficients FIRcoeffs[N ] = {1, 1, 1, … 1, 1}; FIRcoeffpt = &FIRco eff[0] FIFOpt = & FIFO[n-1-count]; sum = 0; for count = 0 to N-1 sum = sum + (* FIFOpt--) * (* FIRcoeffpt++); Note the two meaning of the C++ operator * Multiplication of two variables (integer, float (single and extended), complex int are possible) Contents of memory location pointed to by a pointer 6/5/2016 Testing FIR filters Copyright 9 / 40

Steps in optimizing – Step 3 Change to averaging FIR filter which access coefficients FIRcoeffs[N ] = {1, 1, 1, … 1, 1}; FIRcoeffpt = &FIRco eff[0] FIFOpt = & FIFO[n-1-count]; sum = 0; for count = 0 to N-1 sum = sum + (* FIFOpt--) * (* FIRcoeffpt++); Refactor to take advantage of processor DAG characteristics Most processors are faster at incrementing forward – and the instruction works in parallel with more instructions FIRcoeffs[N ] = {1, 1, 1, … 1, 1}; FIRcoeffpt = &FIRco eff[0] FIFOpt = & FIFO[0]; sum = 0; for count = 0 to N-1 sum = sum + (* FIFOpt++) * (* FIRcoeffpt++); Change away from {1 ….. 1} and you have normal FIR filter code 6/5/2016 Testing FIR filters Copyright 10 / 40

Lab. 1 Code conversion: Averaging to FIR Average Filter -- Do Buffer update loop then do fetch a new data memory value with add loop FIR -- Modify second loop to bring in second data value (FIR coeffs) and perform multiply and add C++ un-optimized FIR -- data and coeffs from dm Compiler optimized C++ FIR -- data and coeffs from dm ASM version – software loop – FIR filter -- data and coeffs from dm Test -- (function, timing and theory comparison) Averaging filter has same functional results as FIR if you test with coefficients coefficients (1/N, 1/N, 1/N …. 6/5/2016 Testing FIR filters Copyright 11 / 33

Lab. 1 Code conversion: New FIR Add new FIR specific tests – discussed today Modify one loop to bring in second data value (FIR coeffs) and perform multiply and add Compiler optimized C++ FIR – data from dm and coeffs from pm ASM version – software loop – FIR filter Other optimizations will become part of Lab. 2 – data from dm and coeffs from pm 6/5/2016 Testing FIR filters Copyright 12 / 33

Lab. 1 – How to test a totally new DSP algorithm For any new algorithm We could write the code in Matlab Then write tests in Matlab to show works We then translate the MatLab code into C Then translate the MatLab tests into C and use them. In Lab. 1, we are going to take a short cut as we know what should be happening with FIR – straight to C and Testing 6/5/2016 Testing FIR filters Copyright 13 / 33

Rough idea of function Insert a new value into the “new” location of a FIFO array Update FIFO filter to throw away oldest value Perform FIR filter operation For (I = 0; I < lengthFIR) sum = sum + FIFO(lengthFIR – I) * FIRcoeffs(I) Return sum Write code in a way that the code is testable 6/5/2016 Testing FIR filters Copyright 14 / 33

Write for Testable means what? Ability to easily test with different length of FIR filters Ability to easily test with different FIR filter coefficients Ability to test with a variety of input values non-Functional test – ability to time execution time Ability to be able to test Outside uTTCOS – automated tests on ‘mock’ data Inside uTTCOS – human acceptance test using real audio data – Should be smooth audio performance – not hick-cups caused by lost signals 6/5/2016 Testing FIR filters Copyright 15 / 33

What to worry about FIR filter of length ? Actual values of FIR coefficient are ???? Unimportant when not inside uTTCOS as we are not expecting ‘acceptable’ audio signals, just correct results Very important when used in human testing – inside uTTCOS Must be stable – otherwise will blow your ears out Must be known so you can use your ears to validate that the correct sort of filtering is occurring 6/5/2016 Testing FIR filters Copyright 16 / 33

Story 1 – Basic ‘does anything work’ test FIR filter of length 4 “Fake” known FIR coefficients – A0, A1, A2 and A3 A0 = 2.0 (never use 1.0 since 1.0 * 1.0 is the same as 1.0 * 1.0 * 1.0 and 1.0 – meaning if there is a mistake in coding you would never know A1 = A2 = A3 = 0.0 (at the moment) Process the “fake” audio array Input[ ] = 0, 0, 0, 3, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0 Note that the impulses of amplitude “3” are further apart than FIRlength 6/5/2016 Testing FIR filters Copyright 17 / 33

Story 1 – Basic ‘does anything work’ test Input[ ] = 0, 0, 0, 3, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0 Note that the impulses of amplitude “3” are further apart than FIRlength Values read out of the array and placed in Leftchannel 1 each time we apply the filter Used as In1 = 0; In2 = 0; In3 = 0; In4 = 0; In5 = 0 etc 6/5/2016 Testing FIR filters Copyright 18 / 33

What is expected result? Write a test, Watch it Fail when only a stub CPP or ASM function is present the test of the test. Must fail when no code is present otherwise is useless test Write the code to satisfy the test The test of the code Remember – the test writing is expected to be easy for the C++ code So generate sensible written tests for the C++ code and modify them for use when we optimize the assembly code 6/5/2016 Testing FIR filters Copyright 19 / 33

What is the expected result? Fake FIR coefficients 2.0, 0, 0, 0 Therefore result (two sets of impulse responses) would be filteredInput[ ] = 0, 0, 0, 6, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0 6/5/2016 Testing FIR filters Copyright 20 / 33 DATA FILTER COEFFS ARRANGED IN REVERSED ORDER as A0 is multiplied by newest value

Go to.xls file 6/5/2016 Testing FIR filters Copyright 21 / 40

FIR in imaging a row FIR filter of size 40 on image of size 256 Get initial and final transients Image might look like this B1, B1, B1, B1, B1, I, I, I, I, I, I, I, I, B2, B2, B2, B2 Where B is background (or more realistically – valid image but not of great interest So we prime the filter to avoid transients by assuming image repeats in space B2, B2, B2, B2, B1, B1, B1, B1, B1, I, I, I, I, I, I, I, I, B2, B2, B2, B2, B1, B1, B1, B1, B1 6/5/2016 Testing FIR filters Copyright 22 / 33

What is the expected result? FIR coefficients 5.0, 0, 0, 0, 0, 0, input[ ] = 0, 0, 0, 3, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0 Therefore result (two sets of scaled impulse response) would be filteredInput[ ] = 0, 0, 0, 15, 0, 0, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0 6/5/2016 Testing FIR filters Copyright 23 / 33

Story Want to be able to evaluate what happens (speed issues with compiler) when you write the code with fixed-length external arrays FIR[32] rather than FIR[N] where N can be any number, and array outside function (global) Want to be able to evaluate what happens (speed issues with compiler) when you write the code with passing array parameters into the filter 6/5/2016 Testing FIR filters Copyright 24 / 33

Write the Test – FIR with parameter passing TEST(Story1_A1) { float input[ ] = 0, 0, 0, 3.3, 0, 0, 0, 0, 0, 4.4, 0, 0, 0, 0, 0, 0; float FIRcoeffs[ ] = 2.0, 0, 0, 0; (4 FIR coeffs) float expectedResult[ ] = 0, 0, 0, 6.6, 0, 0, 0, 0, 0, 8.8, 0, 0, 0, 0, 0, 0; float actualResult[ ] = 0; for (I = 0; I < length(input)) actualResult[I] = FIRparamPassing(input[I], FIRcoeffs, length(FIRcoeffs)); CHECK_ARRAY_CLOSE(expectedResult, actualResult, length(expectedResult), threshold); } 6/5/2016 Testing FIR filters Copyright 25 / 33

Write the Test – FIR with parameter passing V2 TEST(Story1_A2) { float input[ ] = 0, 0, 0, 3.3, 0, 0, 0, 0, 0, 4.4, 0, 0, 0, 0, 0, 0; float FIRcoeffs[ ] = 2.0, 0, 0, 0, 0, 0; (6 coefficients) float expectedResult[ ] = 0, 0, 0, 6.6, 0, 0, 0, 0, 0, 8.8, 0, 0, 0, 0, 0, 0; float actualResult[ ] = 0; for (I = 0; I < length(input)) actualResult[I] = FIRparamPassing(input[I], FIRcoeffs, length(FIRcoeffs)); CHECK_ARRAY_CLOSE(expectedResult, actualResult, length(expectedResult), threshold); } 6/5/2016 Testing FIR filters Copyright 26 / 33

Write the Test – FIR with static array float staticArray[ ] = { 0.} // The C++ optimizer may find FIR filters accessing external arrays might be easier to optimize (fixed location) FIRTEST(Story1_B) { float input[ ] = 0, 0, 0, 3, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0; float FIRcoeffs[ ] = 2.0, 0, 0, 0; float expectedResult[ ] = 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0; float actualResult[ ] = 0; Copy(FIRcoffs, staticFIRcoeffs, length(FIRcoeffs)); for (I = 0; I < length(input)) inValue = input[I]; // Global variable FIRstaticNum4( ); // Read global input, coefficients and produces global output actualResult[I] = outValue; } CHECK_ARRAY_CLOSE(expectedResult, actualResult, length(expectedResult), threshold); } 6/5/2016 Testing FIR filters Copyright 27 / 40

Write the Test – FIR with static array V2 TEST(Story1_B) { float input[ ] = 0, 0, 0, 3, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0; float FIRcoeffs[ ] = 2.0, 0, 0, 0, 0, 0; float expectedResult[ ] = 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0; float actualResult[ ] = 0; Copy(FIRcoffs, staticFIRcoeffs, length(FIRcoeffs)); for (I = 0; I < length(input)) inValue = input[I]; FIRstaticNum6( ); // Using different FIR filter routine for actualResult[I] = outValue; // Each filter length might be faster } CHECK_ARRAY_CLOSE(expectedResult, actualResult, length(expectedResult), threshold); } 6/5/2016 Testing FIR filters Copyright 28 / 33

Write the stubs – expect to fail File 1 float FIRparamPassingIndex(float inValue, float FIRcoeffs[ ], int numCoeffs( ) { return ; } File 2 float FIRparamPassingPointer(float inValue, float *FIRcoeffs, int numCoeffs( ) { return ; } 6/5/2016 Testing FIR filters Copyright 29 / 33

Write the stubs – expect to fail File 3 float outvalueNum4Index = ; float FIRcoeffsNum4[ ] = { 0 }; void FIRstaticNum4Index(void) { // Implement via Index outvalueNum4Index = ; } File 4 float outvalueNum6Index = ; float FIRcoeffsNum6[ ] = { 0 }; void FIRstaticNum6Index(void) {// Implement via Index outvalueNum6Index = ; } 6/5/2016 Testing FIR filters Copyright 30 / 33

Write the Test – FIR with static array – V3 TEST(Story1_C) { float input[ ] = 0, 0, 0, 3, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0; float FIRcoeffs[ ] = 2.0, 3.0, 4.0, 5.0; float expectedResult[ ] = 0, 0, 0, 6, 9.0, 12.0, 15.0, 0, 0, 6, 9.0, 12.0, 15.0, 0, 0, 0; float actualResult[ ] = 0; Copy(FIRcoffs, staticFIRcoeffs, length(FIRcoeffs)); for (I = 0; I < length(input)) inValue = input[I]; FIRstaticNum4( ); actualResult[I] = outValue; } CHECK_ARRAY_CLOSE(expectedResult, actualResult, length(expectedResult), threshold); } 6/5/2016 Testing FIR filters Copyright 31 / 33

Write the Test – FIR with static array – V4 TEST(Story1_C) { Each input produces an “impulse response” float input[ ] = 0, 0, 0, 3, 0, 0, 3, 0, 3, 0, 0, 0, 0; float FIRcoeffs[ ] = 2.0, 3.0, 4.0, 5.0; float expectedResult[ ] = 0, 0, 0, 6, 9, 12, , 0 + 9, , 15+ 9, 12, 15, 0; float actualResult[ ] = 0; Copy(FIRcoffs, staticFIRcoeffs, length(FIRcoeffs)); for (I = 0; I < length(input)) inValue = input[I]; FIRstaticNum4( ); actualResult[I] = outValue; } CHECK_ARRAY_CLOSE(expectedResult, actualResult, length(expectedResult), threshold); } 6/5/2016 Testing FIR filters Copyright 32 / 33

When do you have enough tests? It is a standard question Salary tax function If salary < then no tax If <= salary < then 10% tax If <= salary < then 20% tax If <= salary then 30% tax Partition of space Salary = 5000, 15000, 25000, – typical Salary = , 0 -- special cases Salary = 10000, 9999, – boundary test Etc. 6/5/2016 Testing FIR filters Copyright 33 / 33

How do you test FIR algorithm? void FIRNum4(void) { FIFO[3] = invalue; float sum = 0; for (int I = 0; I < 3; i++) { sum = sum + FIFO[I] * FIRcoeffs[I]; } outValue = sum; for (int I = 0; I < 2; i++) { FIFO[I] = FIFO[I + 1]; } 6/5/2016 Testing FIR filters Copyright 34 / 33

Introduce deliberate mistakes You have a Personal Software Process You know what sort of errors you typically make E.g. Too many times around the loop Forgetting important constants Go in a deliberately make the mistake you commonly make See what sort of tests spot that mistake Always include those sort of tests 6/5/2016 Testing FIR filters Copyright 35 / 33

Test should spot the following error void FIRNum4(void) { FIFO[3] = invalue; float sum; // float sum = 0; for (int I = 0; I < 3; i++) { sum = sum + FIFO[I] * FIRcoeffs[I]; } outValue = sum; for (int I = 0; I < 2; i++) { FIFO[I] = FIFO[I + 1]; } 6/5/2016 Testing FIR filters Copyright 36 / 33

Exam question Why might this incorrect algorithm pass the first test? Give me example code that would probably cause this incorrect algorithm always pass tests void FIRNum4(void) { FIFO[3] = invalue; float sum; // float sum = 0; for (int I = 0; I < 3; i++) { sum = sum + FIFO[I] * FIRcoeffs[I]; } etc 6/5/2016 Testing FIR filters Copyright 37 / 33

Code causing test to pass TEST(Story1_C) { float input[ ] = 0, 0, 0, 3, 0, 0, 3, 0, 3, 0, 0, 0, 0; float FIRcoeffs[ ] = 2.0, 3.0, 4.0, 5.0; float expectedResult[ ] = 0, 0, 0, 6, 9, 12, , 0 + 9, , 15+ 9, 12, 15, 0; float actualResult[ ] = 0; Copy(FIRcoffs, staticFIRcoeffs, length(FIRcoeffs)); for (I = 0; I < length(input)) inValue = input[I]; DoGarbage Function( ); FIRstaticNum4( ); actualResult[I] = outValue; } CHECK_ARRAY_CLOSE(expectedResult, actualResult, length(expectedResult), threshold); } 6/5/2016 Testing FIR filters Copyright 38 / 33

Example – why does DoGarbage( ) make FIRNum4( ) work? void FIRNum4(void) { FIFO[3] = invalue; float sum; // float sum = 0; for (int I = 0; I < 3; i++) { sum = sum + FIFO[I] * FIRcoeffs[I]; } etc void DoGarbage(void) { int garbage = 0; } 6/5/2016 Testing FIR filters Copyright 39 / 33

POSSIBLE solution to incorrect Test results Have a couple of tests that are similar TEST(Story1_C) { float input[ ] = 0, 0, 0, 3, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0; float FIRcoeffs[ ] = 2.0, 3.0, 4.0, 5.0; float expectedResult[ ] = ….. } TEST(Story1_D) { float input[ ] = 3, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0; float FIRcoeffs[ ] = 2.0, 3.0, 9.0, -5.0; float expectedResult[ ] = ….. } Use the automated framework to run the list of tests both forward and backwards 6/5/2016 Testing FIR filters Copyright 40 / 33

Mututation testing Have a tool that deliberately generates a new version of the file with an inserted mistake E.g. change Change + to – Change * to + (note 2 * 2 = 2 + 2) 6/5/2016 Testing FIR filters Copyright 41 / 33

How do you test FIR algorithm? void FIRNum4(void) { FIFO[3] = invalue; float sum = 0; for (int I = 0; I <= 3; i++) { sum = sum + FIFO[I] * FIRcoeffs[I]; } outValue = sum; for (int I = 0; I < 2; i++) { FIFO[I] = FIFO[I + 1]; } 6/5/2016 Testing FIR filters Copyright 42 / 33

How do you test FIR algorithm? void FIRNum4(void) { FIFO[3] = invalue; float sum = 0; for (int I = 0; I < 3; i++) { sum = sum - FIFO[I] * FIRcoeffs[I]; } outValue = sum; for (int I = 0; I < 2; i++) { FIFO[I] = FIFO[I + 1]; } 6/5/2016 Testing FIR filters Copyright 43 / 33

Test should spot the following error void FIRNum4(void) { FIFO[3] = invalue; float sum; // float sum = 0; for (int I = 0; I < 3; i++) { sum = sum + FIFO[I] * FIRcoeffs[I]; } outValue = sum; for (int I = 0; I < 2; i++) { FIFO[I] = FIFO[I + 1]; } 6/5/2016 Testing FIR filters Copyright 44 / 33