567 lines
15 KiB
Python
Executable File
567 lines
15 KiB
Python
Executable File
import os.path
|
|
import itertools
|
|
import Tools
|
|
import random
|
|
import numpy as np
|
|
import scipy
|
|
import scipy.stats
|
|
import math
|
|
|
|
NBTESTS = 10
|
|
VECDIM = [12,14,20]
|
|
|
|
def entropyTest(config,nb):
|
|
DIMS = [3,8,9,12]
|
|
inputs = []
|
|
outputs = []
|
|
dims=[NBTESTS]
|
|
for i in range(0,NBTESTS):
|
|
vecDim = DIMS[i % len(DIMS)]
|
|
dims.append(vecDim)
|
|
v = np.random.rand(vecDim)
|
|
v = v / np.sum(v)
|
|
e = scipy.stats.entropy(v)
|
|
inputs += list(v)
|
|
outputs.append(e)
|
|
inputs = np.array(inputs)
|
|
outputs = np.array(outputs)
|
|
dims = np.array(dims)
|
|
config.writeInput(nb, inputs,"Input")
|
|
config.writeInputS16(nb, dims,"Dims")
|
|
config.writeReference(nb, outputs,"RefEntropy")
|
|
|
|
def logsumexpTest(config,nb):
|
|
DIMS = [3,8,9,12]
|
|
inputs = []
|
|
outputs = []
|
|
dims=[NBTESTS]
|
|
for i in range(0,NBTESTS):
|
|
vecDim = DIMS[i % len(DIMS)]
|
|
dims.append(vecDim)
|
|
v = np.random.rand(vecDim)
|
|
v = v / np.sum(v)
|
|
e = scipy.special.logsumexp(v)
|
|
inputs += list(v)
|
|
outputs.append(e)
|
|
inputs = np.array(inputs)
|
|
outputs = np.array(outputs)
|
|
dims = np.array(dims)
|
|
config.writeInput(nb, inputs,"Input")
|
|
config.writeInputS16(nb, dims,"Dims")
|
|
config.writeReference(nb, outputs,"RefLogSumExp")
|
|
|
|
def klTest(config,nb):
|
|
DIMS = [3,8,9,12]
|
|
inputsA = []
|
|
inputsB = []
|
|
outputs = []
|
|
vecDim = VECDIM[nb % len(VECDIM)]
|
|
dims=[NBTESTS]
|
|
for i in range(0,NBTESTS):
|
|
vecDim = DIMS[i % len(DIMS)]
|
|
dims.append(vecDim)
|
|
va = np.random.rand(vecDim)
|
|
va = va / np.sum(va)
|
|
|
|
vb = np.random.rand(vecDim)
|
|
vb = vb / np.sum(vb)
|
|
|
|
e = scipy.stats.entropy(va,vb)
|
|
inputsA += list(va)
|
|
inputsB += list(vb)
|
|
outputs.append(e)
|
|
inputsA = np.array(inputsA)
|
|
inputsB = np.array(inputsB)
|
|
outputs = np.array(outputs)
|
|
dims = np.array(dims)
|
|
config.writeInput(nb, inputsA,"InputA")
|
|
config.writeInput(nb, inputsB,"InputB")
|
|
config.writeInputS16(nb, dims,"Dims")
|
|
config.writeReference(nb, outputs,"RefKL")
|
|
|
|
def logSumExpDotTest(config,nb):
|
|
DIMS = [3,8,9,12]
|
|
inputsA = []
|
|
inputsB = []
|
|
outputs = []
|
|
vecDim = VECDIM[nb % len(VECDIM)]
|
|
dims=[NBTESTS]
|
|
for i in range(0,NBTESTS):
|
|
vecDim = DIMS[i % len(DIMS)]
|
|
dims.append(vecDim)
|
|
va = np.random.rand(vecDim)
|
|
va = va / np.sum(va)
|
|
|
|
vb = np.random.rand(vecDim)
|
|
vb = vb / np.sum(vb)
|
|
|
|
d = 0.001
|
|
# It is a proba so must be in [0,1]
|
|
# But restricted to ]d,1] so that the log exists
|
|
va = (1-d)*va + d
|
|
vb = (1-d)*vb + d
|
|
e = np.log(np.dot(va,vb))
|
|
va = np.log(va)
|
|
vb = np.log(vb)
|
|
|
|
inputsA += list(va)
|
|
inputsB += list(vb)
|
|
outputs.append(e)
|
|
inputsA = np.array(inputsA)
|
|
inputsB = np.array(inputsB)
|
|
outputs = np.array(outputs)
|
|
dims = np.array(dims)
|
|
config.writeInput(nb, inputsA,"InputA")
|
|
config.writeInput(nb, inputsB,"InputB")
|
|
config.writeInputS16(nb, dims,"Dims")
|
|
config.writeReference(nb, outputs,"RefLogSumExpDot")
|
|
|
|
def writeF16OnlyTests(config,nb):
|
|
entropyTest(config,nb)
|
|
logsumexpTest(config,nb+1)
|
|
klTest(config,nb+2)
|
|
logSumExpDotTest(config,nb+3)
|
|
return(nb+4)
|
|
|
|
def writeF32OnlyTests(config,nb):
|
|
entropyTest(config,nb)
|
|
logsumexpTest(config,nb+1)
|
|
klTest(config,nb+2)
|
|
logSumExpDotTest(config,nb+3)
|
|
return(nb+4)
|
|
|
|
def writeF64OnlyTests(config,nb):
|
|
entropyTest(config,nb)
|
|
logsumexpTest(config,nb+1)
|
|
klTest(config,nb+2)
|
|
logSumExpDotTest(config,nb+3)
|
|
return(nb+4)
|
|
|
|
# For index in min and max we need to ensure that the difference between values
|
|
# of the input is big enough to be representable on q31, q15 or q7.
|
|
# Otherwise python will compute an index different from the one
|
|
# computed by CMSIS which is normal but then the CMSIS test will fail.
|
|
|
|
#vfunc = np.vectorize(squarer)
|
|
|
|
def floatRound(x,f):
|
|
return(np.round(x * 2**f)/2**f)
|
|
|
|
# Min / Max tests
|
|
def generateMaxTests(config,nb,format,data):
|
|
|
|
|
|
indexes=[]
|
|
maxvals=[]
|
|
|
|
nbiters = Tools.loopnb(format,Tools.TAILONLY)
|
|
index=np.argmax(data[0:nbiters])
|
|
maxvalue=data[index]
|
|
|
|
indexes.append(index)
|
|
maxvals.append(maxvalue)
|
|
|
|
nbiters = Tools.loopnb(format,Tools.BODYONLY)
|
|
index=np.argmax(data[0:nbiters])
|
|
maxvalue=data[index]
|
|
|
|
indexes.append(index)
|
|
maxvals.append(maxvalue)
|
|
|
|
nbiters = Tools.loopnb(format,Tools.BODYANDTAIL)
|
|
index=np.argmax(data[0:nbiters])
|
|
maxvalue=data[index]
|
|
|
|
indexes.append(index)
|
|
maxvals.append(maxvalue)
|
|
|
|
if format == 7:
|
|
# Force max at position 280
|
|
|
|
nbiters = 280
|
|
|
|
data = np.zeros(nbiters)
|
|
|
|
data[nbiters-1] = 0.9
|
|
data[nbiters-2] = 0.8
|
|
|
|
index=np.argmax(data[0:nbiters])
|
|
maxvalue=data[index]
|
|
|
|
indexes.append(index)
|
|
maxvals.append(maxvalue)
|
|
|
|
config.writeInput(nb, data,"InputMaxIndexMax")
|
|
|
|
config.writeReference(nb, maxvals,"MaxVals")
|
|
config.writeInputS16(nb, indexes,"MaxIndexes")
|
|
return(nb+1)
|
|
|
|
def generateMinTests(config,nb,format,data):
|
|
|
|
|
|
indexes=[]
|
|
maxvals=[]
|
|
|
|
nbiters = Tools.loopnb(format,Tools.TAILONLY)
|
|
index=np.argmin(data[0:nbiters])
|
|
maxvalue=data[index]
|
|
|
|
indexes.append(index)
|
|
maxvals.append(maxvalue)
|
|
|
|
nbiters = Tools.loopnb(format,Tools.BODYONLY)
|
|
index=np.argmin(data[0:nbiters])
|
|
maxvalue=data[index]
|
|
|
|
indexes.append(index)
|
|
maxvals.append(maxvalue)
|
|
|
|
nbiters = Tools.loopnb(format,Tools.BODYANDTAIL)
|
|
index=np.argmin(data[0:nbiters])
|
|
maxvalue=data[index]
|
|
|
|
indexes.append(index)
|
|
maxvals.append(maxvalue)
|
|
|
|
if format == 7:
|
|
# Force max at position 280
|
|
nbiters = 280
|
|
|
|
data = 0.9*np.ones(nbiters)
|
|
|
|
data[nbiters-1] = 0.0
|
|
data[nbiters-2] = 0.1
|
|
|
|
index=np.argmin(data[0:nbiters])
|
|
maxvalue=data[index]
|
|
|
|
indexes.append(index)
|
|
maxvals.append(maxvalue)
|
|
|
|
|
|
config.writeInput(nb, data,"InputMinIndexMax")
|
|
config.writeReference(nb, maxvals,"MinVals")
|
|
config.writeInputS16(nb, indexes,"MinIndexes")
|
|
return(nb+1)
|
|
|
|
# Min/Max Abs Tests
|
|
def generateMaxAbsTests(config,nb,format,data):
|
|
data = np.abs(data)
|
|
|
|
indexes=[]
|
|
maxvals=[]
|
|
|
|
nbiters = Tools.loopnb(format,Tools.TAILONLY)
|
|
index=np.argmax(data[0:nbiters])
|
|
maxvalue=data[index]
|
|
|
|
indexes.append(index)
|
|
maxvals.append(maxvalue)
|
|
|
|
nbiters = Tools.loopnb(format,Tools.BODYONLY)
|
|
index=np.argmax(data[0:nbiters])
|
|
maxvalue=data[index]
|
|
|
|
indexes.append(index)
|
|
maxvals.append(maxvalue)
|
|
|
|
nbiters = Tools.loopnb(format,Tools.BODYANDTAIL)
|
|
index=np.argmax(data[0:nbiters])
|
|
maxvalue=data[index]
|
|
|
|
indexes.append(index)
|
|
maxvals.append(maxvalue)
|
|
|
|
if format == 7:
|
|
# Force max at position 280
|
|
|
|
nbiters = 280
|
|
|
|
data = np.zeros(nbiters)
|
|
|
|
data[nbiters-1] = 0.9
|
|
data[nbiters-2] = 0.8
|
|
|
|
index=np.argmax(data[0:nbiters])
|
|
maxvalue=data[index]
|
|
|
|
indexes.append(index)
|
|
maxvals.append(maxvalue)
|
|
|
|
config.writeInput(nb, data,"InputAbsMaxIndexMax")
|
|
|
|
config.writeReference(nb, maxvals,"AbsMaxVals")
|
|
config.writeInputS16(nb, indexes,"AbsMaxIndexes")
|
|
return(nb+1)
|
|
|
|
def generateMinAbsTests(config,nb,format,data):
|
|
data = np.abs(data)
|
|
|
|
indexes=[]
|
|
maxvals=[]
|
|
|
|
nbiters = Tools.loopnb(format,Tools.TAILONLY)
|
|
index=np.argmin(data[0:nbiters])
|
|
maxvalue=data[index]
|
|
|
|
indexes.append(index)
|
|
maxvals.append(maxvalue)
|
|
|
|
nbiters = Tools.loopnb(format,Tools.BODYONLY)
|
|
index=np.argmin(data[0:nbiters])
|
|
maxvalue=data[index]
|
|
|
|
indexes.append(index)
|
|
maxvals.append(maxvalue)
|
|
|
|
nbiters = Tools.loopnb(format,Tools.BODYANDTAIL)
|
|
index=np.argmin(data[0:nbiters])
|
|
maxvalue=data[index]
|
|
|
|
indexes.append(index)
|
|
maxvals.append(maxvalue)
|
|
|
|
if format == 7:
|
|
# Force max at position 280
|
|
nbiters = 280
|
|
|
|
data = 0.9*np.ones(nbiters)
|
|
|
|
data[nbiters-1] = 0.0
|
|
data[nbiters-2] = 0.1
|
|
|
|
index=np.argmin(data[0:nbiters])
|
|
maxvalue=data[index]
|
|
|
|
indexes.append(index)
|
|
maxvals.append(maxvalue)
|
|
|
|
|
|
config.writeInput(nb, data,"InputAbsMinIndexMax")
|
|
config.writeReference(nb, maxvals,"AbsMinVals")
|
|
config.writeInputS16(nb, indexes,"AbsMinIndexes")
|
|
return(nb+1)
|
|
|
|
def averageTest(format,data):
|
|
return(np.average(data))
|
|
|
|
def powerTest(format,data):
|
|
if format == 31:
|
|
return(np.dot(data,data) / 2**15) # CMSIS is 2.28 format
|
|
elif format == 15:
|
|
return(np.dot(data,data) / 2**33) # CMSIS is 34.30 format
|
|
elif format == 7:
|
|
return(np.dot(data,data) / 2**17) # CMSIS is 18.14 format
|
|
else:
|
|
return(np.dot(data,data))
|
|
|
|
def mseTest(format,data1,data2):
|
|
nb = len(data1)
|
|
err = data1 - data2
|
|
return(np.dot(err,err) / nb)
|
|
|
|
def rmsTest(format,data):
|
|
return(math.sqrt(np.dot(data,data)/data.size))
|
|
|
|
def stdTest(format,data):
|
|
return(np.std(data,ddof=1))
|
|
|
|
def varTest(format,data):
|
|
return(np.var(data,ddof=1))
|
|
|
|
def generateFuncTests(config,nb,format,data,func,name):
|
|
|
|
funcvals=[]
|
|
|
|
nbiters = Tools.loopnb(format,Tools.TAILONLY)
|
|
funcvalue=func(format,data[0:nbiters])
|
|
funcvals.append(funcvalue)
|
|
|
|
nbiters = Tools.loopnb(format,Tools.BODYONLY)
|
|
funcvalue=func(format,data[0:nbiters])
|
|
funcvals.append(funcvalue)
|
|
|
|
nbiters = Tools.loopnb(format,Tools.BODYANDTAIL)
|
|
funcvalue=func(format,data[0:nbiters])
|
|
funcvals.append(funcvalue)
|
|
|
|
nbiters = 100
|
|
funcvalue=func(format,data[0:nbiters])
|
|
funcvals.append(funcvalue)
|
|
|
|
config.writeReference(nb, funcvals,name)
|
|
return(nb+1)
|
|
|
|
def generateOperatorTests(config,nb,format,data1,data2,func,name):
|
|
|
|
funcvals=[]
|
|
|
|
nbiters = Tools.loopnb(format,Tools.TAILONLY)
|
|
funcvalue=func(format,data1[0:nbiters],data2[0:nbiters])
|
|
funcvals.append(funcvalue)
|
|
|
|
nbiters = Tools.loopnb(format,Tools.BODYONLY)
|
|
funcvalue=func(format,data1[0:nbiters],data2[0:nbiters])
|
|
funcvals.append(funcvalue)
|
|
|
|
nbiters = Tools.loopnb(format,Tools.BODYANDTAIL)
|
|
funcvalue=func(format,data1[0:nbiters],data2[0:nbiters])
|
|
funcvals.append(funcvalue)
|
|
|
|
nbiters = 100
|
|
funcvalue=func(format,data1[0:nbiters],data2[0:nbiters])
|
|
funcvals.append(funcvalue)
|
|
|
|
config.writeReference(nb, funcvals,name)
|
|
return(nb+1)
|
|
|
|
def generatePowerTests(config,nb,format,data):
|
|
|
|
funcvals=[]
|
|
|
|
nbiters = Tools.loopnb(format,Tools.TAILONLY)
|
|
funcvalue=powerTest(format,data[0:nbiters])
|
|
funcvals.append(funcvalue)
|
|
|
|
nbiters = Tools.loopnb(format,Tools.BODYONLY)
|
|
funcvalue=powerTest(format,data[0:nbiters])
|
|
funcvals.append(funcvalue)
|
|
|
|
nbiters = Tools.loopnb(format,Tools.BODYANDTAIL)
|
|
funcvalue=powerTest(format,data[0:nbiters])
|
|
funcvals.append(funcvalue)
|
|
|
|
if format==31 or format==15:
|
|
config.writeReferenceQ63(nb, funcvals,"PowerVals")
|
|
elif format==7:
|
|
config.writeReferenceQ31(nb, funcvals,"PowerVals")
|
|
else:
|
|
config.writeReference(nb, funcvals,"PowerVals")
|
|
return(nb+1)
|
|
|
|
def writeTests(config,nb,format):
|
|
NBSAMPLES = 300
|
|
data1=np.random.randn(NBSAMPLES)
|
|
data2=np.random.randn(NBSAMPLES)
|
|
|
|
data1 = Tools.normalize(data1)
|
|
data2 = np.abs(data1)
|
|
|
|
# Force quantization so that computation of indexes
|
|
# in min/max is coherent between Python and CMSIS.
|
|
# Otherwise there will be normal differences and the test
|
|
# will be displayed as failed.
|
|
if format==31:
|
|
data1=floatRound(data1,31)
|
|
|
|
if format==15:
|
|
data1=floatRound(data1,15)
|
|
|
|
if format==7:
|
|
data1=floatRound(data1,7)
|
|
|
|
config.writeInput(1, data1,"Input")
|
|
config.writeInput(2, data2,"Input")
|
|
|
|
nb=generateMaxTests(config,nb,format,data1)
|
|
nb=generateFuncTests(config,nb,format,data2,averageTest,"MeanVals")
|
|
nb=generateMinTests(config,nb,format,data1)
|
|
nb=generatePowerTests(config,nb,format,data1)
|
|
nb=generateFuncTests(config,nb,format,data1,rmsTest,"RmsVals")
|
|
nb=generateFuncTests(config,nb,format,data1,stdTest,"StdVals")
|
|
nb=generateFuncTests(config,nb,format,data1,varTest,"VarVals")
|
|
return(nb)
|
|
|
|
# We don't want to change ID number of existing tests.
|
|
# So new tests have to be added after existing ones
|
|
def writeNewsTests(config,nb,format):
|
|
NBSAMPLES = 300
|
|
if format==Tools.F16:
|
|
config.setOverwrite(True)
|
|
data1=np.random.randn(NBSAMPLES)
|
|
data1 = Tools.normalize(data1)
|
|
|
|
data2=np.random.randn(NBSAMPLES)
|
|
data2 = Tools.normalize(data2)
|
|
|
|
config.writeInput(1, data1,"InputNew")
|
|
|
|
nb=generateMaxAbsTests(config,nb,format,data1)
|
|
nb=generateMinAbsTests(config,nb,format,data1)
|
|
|
|
config.writeInput(2, data2,"InputNew")
|
|
nb=generateOperatorTests(config,nb,format,data1,data2,mseTest,"MSEVals")
|
|
config.setOverwrite(False)
|
|
|
|
|
|
def generateBenchmark(config,format):
|
|
NBSAMPLES = 256
|
|
data1=np.random.randn(NBSAMPLES)
|
|
data2=np.random.randn(NBSAMPLES)
|
|
|
|
data1 = Tools.normalize(data1)
|
|
data2 = np.abs(data1)
|
|
|
|
if format==31:
|
|
data1=floatRound(data1,31)
|
|
|
|
if format==15:
|
|
data1=floatRound(data1,15)
|
|
|
|
if format==7:
|
|
data1=floatRound(data1,7)
|
|
|
|
config.writeInput(1, data1,"InputBench")
|
|
config.writeInput(2, data2,"InputBench")
|
|
|
|
|
|
def generatePatterns():
|
|
PATTERNDIR = os.path.join("Patterns","DSP","Stats","Stats")
|
|
PARAMDIR = os.path.join("Parameters","DSP","Stats","Stats")
|
|
|
|
configf64=Tools.Config(PATTERNDIR,PARAMDIR,"f64")
|
|
configf32=Tools.Config(PATTERNDIR,PARAMDIR,"f32")
|
|
configf16=Tools.Config(PATTERNDIR,PARAMDIR,"f16")
|
|
configq31=Tools.Config(PATTERNDIR,PARAMDIR,"q31")
|
|
configq15=Tools.Config(PATTERNDIR,PARAMDIR,"q15")
|
|
configq7 =Tools.Config(PATTERNDIR,PARAMDIR,"q7")
|
|
|
|
configf64.setOverwrite(False)
|
|
configf32.setOverwrite(False)
|
|
configf16.setOverwrite(False)
|
|
configq31.setOverwrite(False)
|
|
configq15.setOverwrite(False)
|
|
configq7.setOverwrite(False)
|
|
|
|
nb=writeTests(configf32,1,0)
|
|
nb=writeF32OnlyTests(configf32,22)
|
|
writeNewsTests(configf32,nb,Tools.F32)
|
|
|
|
nb=writeTests(configf64,1,Tools.F64)
|
|
nb=writeF64OnlyTests(configf64,22)
|
|
writeNewsTests(configf64,nb,Tools.F64)
|
|
|
|
nb=writeTests(configq31,1,31)
|
|
writeNewsTests(configq31,nb,Tools.Q31)
|
|
|
|
nb=writeTests(configq15,1,15)
|
|
writeNewsTests(configq15,nb,Tools.Q15)
|
|
|
|
nb=writeTests(configq7,1,7)
|
|
writeNewsTests(configq7,nb,Tools.Q7)
|
|
|
|
nb=writeTests(configf16,1,16)
|
|
nb=writeF16OnlyTests(configf16,22)
|
|
writeNewsTests(configf16,nb,Tools.F16)
|
|
|
|
generateBenchmark(configf64, Tools.F64)
|
|
generateBenchmark(configf32, Tools.F32)
|
|
generateBenchmark(configf16, Tools.F16)
|
|
generateBenchmark(configq31, Tools.Q31)
|
|
generateBenchmark(configq15, Tools.Q15)
|
|
generateBenchmark(configq7, Tools.Q7)
|
|
|
|
if __name__ == '__main__':
|
|
generatePatterns()
|