CMSIS-DSP: Testing framework

Added support for f64
Added benchmarking code for arm_biquad_cascade_df2T_f64
pull/19/head
Christophe Favergeon 6 years ago
parent f96fcb685b
commit 1c97f73bd3

@ -97,6 +97,8 @@ set(TESTSRC
Source/Benchmarks/DECIMF32.cpp
Source/Benchmarks/DECIMQ31.cpp
Source/Benchmarks/DECIMQ15.cpp
Source/Benchmarks/BIQUADF32.cpp
Source/Benchmarks/BIQUADF64.cpp
Source/Benchmarks/FullyConnectedBench.cpp
Source/Benchmarks/PoolingBench.cpp
)

@ -0,0 +1,24 @@
#include "Test.h"
#include "Pattern.h"
class BIQUADF32:public Client::Suite
{
public:
BIQUADF32(Testing::testID_t id);
void setUp(Testing::testID_t,std::vector<Testing::param_t>& params,Client::PatternMgr *mgr);
void tearDown(Testing::testID_t,Client::PatternMgr *mgr);
private:
#include "BIQUADF32_decl.h"
Client::Pattern<float32_t> samples;
Client::Pattern<float32_t> coefs;
Client::LocalPattern<float32_t> output;
Client::LocalPattern<float32_t> state;
arm_biquad_casd_df1_inst_f32 instBiquadDf1;
arm_biquad_cascade_df2T_instance_f32 instBiquadDf2T;
arm_biquad_cascade_stereo_df2T_instance_f32 instStereo;
int nbSamples;
int numStages;
};

@ -0,0 +1,22 @@
#include "Test.h"
#include "Pattern.h"
class BIQUADF64:public Client::Suite
{
public:
BIQUADF64(Testing::testID_t id);
void setUp(Testing::testID_t,std::vector<Testing::param_t>& params,Client::PatternMgr *mgr);
void tearDown(Testing::testID_t,Client::PatternMgr *mgr);
private:
#include "BIQUADF64_decl.h"
Client::Pattern<float64_t> samples;
Client::Pattern<float64_t> coefs;
Client::LocalPattern<float64_t> output;
Client::LocalPattern<float64_t> state;
arm_biquad_cascade_df2T_instance_f64 instBiquadDf2T;
int nbSamples;
int numStages;
};

@ -0,0 +1,47 @@
import os.path
import numpy as np
import itertools
import Tools
# Those patterns are used for tests and benchmarks.
# For tests, there is the need to add tests for saturation
def writeTests(config):
NBSAMPLES=512 # 512 for stereo
NUMSTAGES = 4
samples=np.random.randn(NBSAMPLES)
coefs=np.random.randn(NUMSTAGES*5)
samples = samples/max(samples)
coefs = coefs/max(coefs)
config.writeInput(1, samples,"Samples")
config.writeInput(1, coefs,"Coefs")
PATTERNDIR = os.path.join("Patterns","DSP","Filtering","BIQUAD","BIQUAD")
PARAMDIR = os.path.join("Parameters","DSP","Filtering","BIQUAD","BIQUAD")
configf64=Tools.Config(PATTERNDIR,PARAMDIR,"f64")
configf32=Tools.Config(PATTERNDIR,PARAMDIR,"f32")
configq31=Tools.Config(PATTERNDIR,PARAMDIR,"q31")
configq15=Tools.Config(PATTERNDIR,PARAMDIR,"q15")
#configq7=Tools.Config(PATTERNDIR,PARAMDIR,"q7")
writeTests(configf32)
writeTests(configq31)
writeTests(configq15)
writeTests(configf64)
#writeTests(configq7)

@ -38,6 +38,18 @@ def float_to_hex(f):
"""
return hex(struct.unpack('<I', struct.pack('<f', f))[0])
def float64_to_hex(f):
""" Convert and x86 float to an ARM unsigned long int.
Args:
f (float): value to be converted
Raises:
Nothing
Returns:
str : representation of the hex value
"""
return hex(struct.unpack('<Q', struct.pack('<d', f))[0])
def to_q31(v):
r = int(round(v * 2**31))
if (r > 0x07FFFFFFF):
@ -219,6 +231,31 @@ class Config:
else:
return(os.path.join(self._paramDir,"Params%d.txt" % i))
def _writeVectorF64(self,i,data):
""" Write pattern data
The format is recognized by the text framework script.
First line is the sample width (B,H or W,D for 8,16,32 or 64 bits)
Second line is number of samples
Other lines are hexadecimal representation of the samples in format
which can be read on big endian ARM.
Args:
j (int): ID of pattern file
data (array): Vector containing the data
Raises:
Nothing
Returns:
Nothing
"""
with open(i,"w") as f:
# Write sample dimension nb sample header
#np.savetxt(i, data, newline="\n", header="W\n%d" % len(data),comments ="" )
f.write("D\n%d\n" % len(data))
for v in data:
f.write("// %f\n" % v)
f.write("%s\n" % float64_to_hex(v))
def _writeVectorF32(self,i,data):
""" Write pattern data
@ -420,6 +457,8 @@ class Config:
f.write("%s\n" % s8(v))
def writeReference(self,j,data,name=None):
if (self._ext == "f64"):
self._writeVectorF64(self.refP(j,name),data)
if (self._ext == "f32"):
self._writeVectorF32(self.refP(j,name),data)
if (self._ext == "q31"):
@ -446,6 +485,8 @@ class Config:
self._writeVectorF32(self.refF32P(j,name),data)
def writeInput(self,j,data,name=None):
if (self._ext == "f64"):
self._writeVectorF64(self.inputP(j,name),data)
if (self._ext == "f32"):
self._writeVectorF32(self.inputP(j,name),data)
if (self._ext == "q31"):

@ -0,0 +1,42 @@
W
20
// -0.216994
0xbe5e33bf
// -0.252372
0xbe8136de
// -0.245080
0xbe7af63c
// -0.061335
0xbd7b3abd
// -0.380985
0xbec31072
// 0.476622
0x3ef407d6
// -0.547221
0xbf0c16ad
// 0.092384
0x3dbd33d4
// -0.474231
0xbef2ce75
// -0.252198
0xbe81200e
// 0.426851
0x3eda8c43
// 0.145653
0x3e152600
// -0.208494
0xbe557f8e
// 0.037213
0x3d186c3b
// -0.740137
0xbf3d7997
// -0.506179
0xbf0194f2
// 1.000000
0x3f800000
// -0.287202
0xbe930c2e
// -0.160079
0xbe23ebbe
// -0.758702
0xbf423a54

@ -0,0 +1,42 @@
D
20
// 0.189728
0x3fc848fdfa2cba3d
// 0.463079
0x3fdda31828d734ed
// 0.277779
0x3fd1c7210ce23fd3
// -0.018901
0xbf935ad018deb599
// -1.517551
0xbff847e3b9800889
// 1.000000
0x3ff0000000000000
// -0.916060
0xbfed505c2d5c8477
// 0.224179
0x3fccb1e1e0972ec2
// 0.418142
0x3fdac2d6c07a1302
// 0.452076
0x3fdceeceb2ed0bcb
// 0.451633
0x3fdce78ff56865d4
// 0.533659
0x3fe113bd1388b0b1
// 0.039028
0x3fa3fb6bf5148d29
// -0.390107
0xbfd8f7855ac2e925
// -0.107081
0xbfbb69a870d27b54
// -0.143982
0xbfc26e0113d7ccfa
// -0.555102
0xbfe1c364a049dd71
// -0.390939
0xbfd90524dc35454f
// -0.173341
0xbfc63009b252984b
// 0.153253
0x3fc39dcdb5682e4f

@ -0,0 +1,42 @@
H
20
// -0.366562
0xD115
// -0.010757
0xFEA0
// 0.148644
0x1307
// -0.249282
0xE018
// -0.389653
0xCE20
// 0.359445
0x2E02
// -0.495325
0xC099
// 0.629828
0x509E
// 0.030378
0x03E3
// -0.126306
0xEFD5
// 0.450443
0x39A8
// -0.506737
0xBF23
// 0.950256
0x79A2
// 0.179078
0x16EC
// 0.044884
0x05BF
// 0.382176
0x30EB
// 0.183047
0x176E
// -0.536833
0xBB49
// 0.125072
0x1002
// 1.000000
0x7FFF

@ -0,0 +1,42 @@
W
20
// -1.035123
0x80000000
// 0.178926
0x16E70FD7
// 0.208163
0x1AA5168F
// -0.338903
0xD49ED287
// -0.923956
0x89BBD179
// -0.416131
0xCABC395B
// 1.000000
0x7FFFFFFF
// -0.448811
0xC68D6043
// -1.109852
0x80000000
// 0.637037
0x518A7035
// -0.003498
0xFF8D5E91
// 0.025662
0x0348E15C
// 0.404738
0x33CE720E
// 0.587480
0x4B328C52
// -0.598883
0xB357CB54
// -0.298923
0xD9BCE664
// -0.149724
0xECD5D420
// 0.130835
0x10BF35C8
// 0.264759
0x21E39EBA
// -0.345163
0xD3D1B176

@ -0,0 +1,98 @@
#include "BIQUADF32.h"
#include "Error.h"
void BIQUADF32::test_biquad_cascade_df1_f32()
{
const float32_t *pSrc=samples.ptr();
float32_t *pDst=output.ptr();
arm_biquad_cascade_df1_f32(&instBiquadDf1, pSrc, pDst, this->nbSamples);
}
void BIQUADF32::test_biquad_cascade_df2T_f32()
{
const float32_t *pSrc=samples.ptr();
float32_t *pDst=output.ptr();
arm_biquad_cascade_df2T_f32(&instBiquadDf2T, pSrc, pDst, this->nbSamples);
}
void BIQUADF32::test_biquad_cascade_stereo_df2T_f32()
{
const float32_t *pSrc=samples.ptr();
float32_t *pDst=output.ptr();
arm_biquad_cascade_stereo_df2T_f32(&instStereo, pSrc, pDst, this->nbSamples);
}
void BIQUADF32::setUp(Testing::testID_t id,std::vector<Testing::param_t>& params,Client::PatternMgr *mgr)
{
std::vector<Testing::param_t>::iterator it = params.begin();
this->numStages = *it++;
this->nbSamples = *it;
switch(id)
{
case TEST_BIQUAD_CASCADE_DF1_F32_1:
samples.reload(BIQUADF32::SAMPLES1_F32_ID,mgr,this->nbSamples);
output.create(this->nbSamples,BIQUADF32::OUT_SAMPLES_F32_ID,mgr);
coefs.reload(BIQUADF32::COEFS1_F32_ID,mgr,this->numStages * 5);
state.create(4*this->numStages,BIQUADF32::STATE_F32_ID,mgr);
arm_biquad_cascade_df1_init_f32(&instBiquadDf1,
this->numStages,
coefs.ptr(),
state.ptr());
break;
case TEST_BIQUAD_CASCADE_DF2T_F32_2:
samples.reload(BIQUADF32::SAMPLES1_F32_ID,mgr,this->nbSamples);
output.create(this->nbSamples,BIQUADF32::OUT_SAMPLES_F32_ID,mgr);
coefs.reload(BIQUADF32::COEFS1_F32_ID,mgr,this->numStages * 5);
state.create(2*this->numStages,BIQUADF32::STATE_F32_ID,mgr);
arm_biquad_cascade_df2T_init_f32(&instBiquadDf2T,
this->numStages,
coefs.ptr(),
state.ptr());
break;
case TEST_BIQUAD_CASCADE_STEREO_DF2T_F32_3:
samples.reload(BIQUADF32::SAMPLES1_F32_ID,mgr,2*this->nbSamples);
output.create(2*this->nbSamples,BIQUADF32::OUT_SAMPLES_F32_ID,mgr);
coefs.reload(BIQUADF32::COEFS1_F32_ID,mgr,this->numStages * 5);
state.create(4*this->numStages,BIQUADF32::STATE_F32_ID,mgr);
arm_biquad_cascade_stereo_df2T_init_f32(&instStereo,
this->numStages,
coefs.ptr(),
state.ptr());
break;
}
}
void BIQUADF32::tearDown(Testing::testID_t id,Client::PatternMgr *mgr)
{
}

@ -0,0 +1,52 @@
#include "BIQUADF64.h"
#include "Error.h"
void BIQUADF64::test_biquad_cascade_df2T_f64()
{
const float64_t *pSrc=samples.ptr();
float64_t *pDst=output.ptr();
arm_biquad_cascade_df2T_f64(&instBiquadDf2T, (float64_t *)pSrc, pDst, this->nbSamples);
}
void BIQUADF64::setUp(Testing::testID_t id,std::vector<Testing::param_t>& params,Client::PatternMgr *mgr)
{
std::vector<Testing::param_t>::iterator it = params.begin();
this->numStages = *it++;
this->nbSamples = *it;
switch(id)
{
case TEST_BIQUAD_CASCADE_DF2T_F64_1:
samples.reload(BIQUADF64::SAMPLES1_F64_ID,mgr,this->nbSamples);
output.create(this->nbSamples,BIQUADF64::OUT_SAMPLES_F64_ID,mgr);
coefs.reload(BIQUADF64::COEFS1_F64_ID,mgr,this->numStages * 5);
state.create(2*this->numStages,BIQUADF64::STATE_F64_ID,mgr);
arm_biquad_cascade_df2T_init_f64(&instBiquadDf2T,
this->numStages,
coefs.ptr(),
state.ptr());
break;
}
}
void BIQUADF64::tearDown(Testing::testID_t id,Client::PatternMgr *mgr)
{
}

@ -428,6 +428,39 @@ class CodeGen:
for c in root:
self._genText(c,textFile)
def _write64(self,v,f):
""" Write four integers into a C char array to represent word32
It is used to dump input patterns in include files
or test drive in include file
Args:
v (int) : The int64 to write
f (file) : the opended file
Raises:
Nothing
Returns:
Nothing
"""
a=[0,0,0,0,0,0,0,0]
a[0]= v & 0x0FF
v = v >> 8
a[1]= v & 0x0FF
v = v >> 8
a[2]= v & 0x0FF
v = v >> 8
a[3]= v & 0x0FF
v = v >> 8
a[4]= v & 0x0FF
v = v >> 8
a[5]= v & 0x0FF
v = v >> 8
a[6]= v & 0x0FF
v = v >> 8
a[7]= v & 0x0FF
v = v >> 8
f.write("%d,%d,%d,%d,%d,%d,%d,%d,\n" % (a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7]))
def _write32(self,v,f):
""" Write four integers into a C char array to represent word32
@ -435,7 +468,7 @@ class CodeGen:
or test drive in include file
Args:
v (int) : The int3 to write
v (int) : The int32 to write
f (file) : the opended file
Raises:
Nothing
@ -453,6 +486,7 @@ class CodeGen:
v = v >> 8
f.write("%d,%d,%d,%d,\n" % (a[0],a[1],a[2],a[3]))
def _write16(self,v,f):
""" Write 2 integers into a C char array to represent word32
@ -514,6 +548,8 @@ class CodeGen:
def convertToInt(self,k,s):
v = 0
if k == "D":
v = decodeHex(s,64,0x0FFFFFFFFFFFFFFFF)
if k == "W":
v = decodeHex(s,32,0x0FFFFFFFF)
if k == "H":
@ -554,6 +590,8 @@ class CodeGen:
k =pat.readline().strip()
sampleSize=1
if k == 'D':
sampleSize = 8
if k == 'W':
sampleSize = 4
if k == 'H':
@ -578,6 +616,8 @@ class CodeGen:
v = self.convertToInt(k,pat.readline())
# Depending on the word size, this hex must be writen to
# the C array as 4,2 or 1 number.
if k == 'D':
self._write64(v,includeFile)
if k == 'W':
self._write32(v,includeFile)
if k == 'H':

@ -669,6 +669,77 @@ group Root {
}
}
}
group BIQUAD {
class = BIQUAD
folder = BIQUAD
suite BIQUAD F32 {
class = BIQUADF32
folder = BIQUADF32
ParamList {
NumStages, NB
Summary NumStages, NB
Names "Number of stages","Number of samples"
Formula "NumStages * NB"
}
Pattern SAMPLES1_F32_ID : Samples1_f32.txt
Pattern COEFS1_F32_ID : Coefs1_f32.txt
Output OUT_SAMPLES_F32_ID : Output
Output STATE_F32_ID : State
Params PARAM1_ID = {
NumStages = [1,2,4]
NB = [16,128,256]
}
Functions {
test_biquad_cascade_df1_f32:test_biquad_cascade_df1_f32 {
oldID = 1
}
test_biquad_cascade_df2T_f32:test_biquad_cascade_df2T_f32 {
oldID = 6
}
test_biquad_cascade_stereo_df2T_f32:test_biquad_cascade_stereo_df2T_f32 {
oldID = 8
}
} -> PARAM1_ID
}
suite BIQUAD F64 {
class = BIQUADF64
folder = BIQUADF64
ParamList {
NumStages, NB
Summary NumStages, NB
Names "Number of stages","Number of samples"
Formula "NumStages * NB"
}
Pattern SAMPLES1_F64_ID : Samples1_f64.txt
Pattern COEFS1_F64_ID : Coefs1_f64.txt
Output OUT_SAMPLES_F64_ID : Output
Output STATE_F64_ID : State
Params PARAM1_ID = {
NumStages = [1,2,4]
NB = [16,128,256]
}
Functions {
test_biquad_cascade_df2T_f64:test_biquad_cascade_df2T_f64 {
oldID = 7
}
} -> PARAM1_ID
}
}
}
}

@ -29,7 +29,7 @@ if args.f is not None:
# Parse the test description.
root = p.parse(args.f)
d.deprecate(root,args.others)
print(root)
#print(root)
# Generate code with the tree of tests
c.genCodeForTree(root)
else:

Loading…
Cancel
Save