RMUL2025/lib/cmsis_5/CMSIS/DSP/Testing/PatternGeneration/Tools.py

859 lines
28 KiB
Python
Executable File

import os.path
import struct
import numpy as np
def normalize(a):
return(a/np.max(np.abs(a)))
TAILONLY = 1
BODYONLY = 2
BODYANDTAIL = 3
# Datatype formats
F64 = 64
F32 = 0
F16 = 16
Q31 = 31
Q15 = 15
Q7 = 7
def loopnb(format,loopkind):
nb = 0
if loopkind == TAILONLY:
if format == 64:
nb = 2
if format == 0 or format == 31:
nb = 3
if format == 15 or format == 16:
nb = 7
if format == 7:
nb = 15
if loopkind == BODYONLY:
if format == 64:
nb = 4
if format == 0 or format == 31:
nb = 8
if format == 15 or format == 16:
nb = 16
if format == 7:
nb = 32
if loopkind == BODYANDTAIL:
if format == 64:
nb = 5
if format == 0 or format == 31:
nb = 11 # 9
if format == 15 or format == 16:
nb = 23 # 17
if format == 7:
nb = 47 # 33
return(nb)
# Tools to generate pattern files
def createMissingDir(destPath):
theDir=os.path.normpath(destPath)
if not os.path.exists(theDir):
os.makedirs(theDir)
# Pack an array of boolean into uint32
def packset(a):
b = np.packbits(a)
newSize = int(np.ceil(b.shape[0] / 4.0)) * 4
c = np.copy(b)
c.resize(newSize)
#print(c)
vecSize = round(newSize/4)
c=c.reshape(vecSize,4)
#print(c)
r = np.zeros(vecSize)
result = []
for i in range(0,vecSize):
#print(c[i,:])
#print("%X %X %X %X" % (c[i,0],c[i,1],c[i,2],c[i,3]))
d = (c[i,0] << 24) | (c[i,1] << 16) | (c[i,2] << 8) | c[i,3]
result.append(np.uint32(d))
return(result)
def float_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('<I', struct.pack('<f', f))[0])
def float16_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('<H', struct.pack('<e', 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_q63(v):
r = int(round(v * 2**63))
if (r > 0x07FFFFFFFFFFFFFFF):
r = 0x07FFFFFFFFFFFFFFF
if (r < -0x08000000000000000):
r = -0x08000000000000000
return ("0x%s" % format(struct.unpack('<Q', struct.pack('<q', r))[0],'016X'))
def to_q31(v):
r = int(round(v * 2**31))
if (r > 0x07FFFFFFF):
r = 0x07FFFFFFF
if (r < -0x080000000):
r = -0x080000000
return ("0x%s" % format(struct.unpack('<I', struct.pack('<i', r))[0],'08X'))
def to_q15(v):
r = int(round(v * 2**15))
if (r > 0x07FFF):
r = 0x07FFF
if (r < -0x08000):
r = -0x08000
return ("0x%s" % format(struct.unpack('<H', struct.pack('<h', r))[0],'04X'))
def to_q7(v):
r = int(round(v * 2**7))
if (r > 0x07F):
r = 0x07F
if (r < -0x080):
r = -0x080
return ("0x%s" % format(struct.unpack('<B', struct.pack('<b', r))[0],'02X'))
def s8(r):
return ("0x%s" % format(struct.unpack('<B', struct.pack('<b', r))[0],'02X'))
def s16(r):
return ("0x%s" % format(struct.unpack('<H', struct.pack('<h', r))[0],'04X'))
def s32(r):
return ("0x%s" % format(struct.unpack('<I', struct.pack('<i', r))[0],'08X'))
def u32(r):
return ("0x%s" % format(struct.unpack('<I', struct.pack('<I', r))[0],'08X'))
class Config:
def __init__(self,patternDir,paramDir,ext):
self._patternDir = "%s%s" % (patternDir,ext.upper())
self._paramDir = "%s%s" % (paramDir,ext.upper())
self._ext = ext
self._overwrite=True
createMissingDir(self._patternDir)
createMissingDir(self._paramDir)
def setOverwrite(self,v):
self._overwrite=v
def canOverwrite(self,path):
return(self._overwrite or not os.path.exists(path))
def inputP(self,i,name=None):
""" Path to a reference pattern from the ID
Args:
i (int): ID to the reference pattern
Raises:
Nothing
Returns:
str : path to the file where to generate the pattern data
"""
if name:
return(os.path.join(self._patternDir,"%s%d_%s.txt" % (name,i,self._ext)))
else:
return(os.path.join(self._patternDir,"Input%d_%s.txt" % (i,self._ext)))
def inputS32P(self,i,name=None):
""" Path to a reference pattern from the ID
Args:
i (int): ID to the reference pattern
Raises:
Nothing
Returns:
str : path to the file where to generate the pattern data
"""
if name:
return(os.path.join(self._patternDir,"%s%d_%s.txt" % (name,i,"s32")))
else:
return(os.path.join(self._patternDir,"Input%d_%s.txt" % (i,"s32")))
def inputS16P(self,i,name=None):
""" Path to a reference pattern from the ID
Args:
i (int): ID to the reference pattern
Raises:
Nothing
Returns:
str : path to the file where to generate the pattern data
"""
if name:
return(os.path.join(self._patternDir,"%s%d_%s.txt" % (name,i,"s16")))
else:
return(os.path.join(self._patternDir,"Input%d_%s.txt" % (i,"s16")))
def inputS8P(self,i,name=None):
""" Path to a reference pattern from the ID
Args:
i (int): ID to the reference pattern
Raises:
Nothing
Returns:
str : path to the file where to generate the pattern data
"""
if name:
return(os.path.join(self._patternDir,"%s%d_%s.txt" % (name,i,"s8")))
else:
return(os.path.join(self._patternDir,"Input%d_%s.txt" % (i,"s8")))
def inputF32P(self,i,name=None):
""" Path to a reference pattern from the ID
Args:
i (int): ID to the reference pattern
Raises:
Nothing
Returns:
str : path to the file where to generate the pattern data
"""
if name:
return(os.path.join(self._patternDir,"%s%d_%s.txt" % (name,i,"f32")))
else:
return(os.path.join(self._patternDir,"Input%d_%s.txt" % (i,"f32")))
def inputF16P(self,i,name=None):
""" Path to a reference pattern from the ID
Args:
i (int): ID to the reference pattern
Raises:
Nothing
Returns:
str : path to the file where to generate the pattern data
"""
if name:
return(os.path.join(self._patternDir,"%s%d_%s.txt" % (name,i,"f16")))
else:
return(os.path.join(self._patternDir,"Input%d_%s.txt" % (i,"f16")))
def inputQ31P(self,i,name=None):
""" Path to a reference pattern from the ID
Args:
i (int): ID to the reference pattern
Raises:
Nothing
Returns:
str : path to the file where to generate the pattern data
"""
if name:
return(os.path.join(self._patternDir,"%s%d_%s.txt" % (name,i,"q31")))
else:
return(os.path.join(self._patternDir,"Input%d_%s.txt" % (i,"q31")))
def inputQ15P(self,i,name=None):
""" Path to a reference pattern from the ID
Args:
i (int): ID to the reference pattern
Raises:
Nothing
Returns:
str : path to the file where to generate the pattern data
"""
if name:
return(os.path.join(self._patternDir,"%s%d_%s.txt" % (name,i,"q15")))
else:
return(os.path.join(self._patternDir,"Input%d_%s.txt" % (i,"q15")))
def inputQ7P(self,i,name=None):
""" Path to a reference pattern from the ID
Args:
i (int): ID to the reference pattern
Raises:
Nothing
Returns:
str : path to the file where to generate the pattern data
"""
if name:
return(os.path.join(self._patternDir,"%s%d_%s.txt" % (name,i,"q7")))
else:
return(os.path.join(self._patternDir,"Input%d_%s.txt" % (i,"q7")))
def inputU32P(self,i,name=None):
""" Path to a reference pattern from the ID
Args:
i (int): ID to the reference pattern
Raises:
Nothing
Returns:
str : path to the file where to generate the pattern data
"""
if name:
return(os.path.join(self._patternDir,"%s%d_%s.txt" % (name,i,"u32")))
else:
return(os.path.join(self._patternDir,"Input%d_%s.txt" % (i,"u32")))
def refP(self,i,name=None):
""" Path to a reference pattern from the ID
Args:
i (int): ID to the reference pattern
Raises:
Nothing
Returns:
str : path to the file where to generate the pattern data
"""
if name:
return(os.path.join(self._patternDir,"%s%d_%s.txt" % (name,i,self._ext)))
else:
return(os.path.join(self._patternDir,"Reference%d_%s.txt" % (i,self._ext)))
def refS8P(self,i,name=None):
""" Path to a reference pattern from the ID
Args:
i (int): ID to the reference pattern
Raises:
Nothing
Returns:
str : path to the file where to generate the pattern data
"""
if name:
return(os.path.join(self._patternDir,"%s%d_%s.txt" % (name,i,"s8")))
else:
return(os.path.join(self._patternDir,"Reference%d_%s.txt" % (i,"s8")))
def refS16P(self,i,name=None):
""" Path to a reference pattern from the ID
Args:
i (int): ID to the reference pattern
Raises:
Nothing
Returns:
str : path to the file where to generate the pattern data
"""
if name:
return(os.path.join(self._patternDir,"%s%d_%s.txt" % (name,i,"s16")))
else:
return(os.path.join(self._patternDir,"Reference%d_%s.txt" % (i,"s16")))
def refS32P(self,i,name=None):
""" Path to a reference pattern from the ID
Args:
i (int): ID to the reference pattern
Raises:
Nothing
Returns:
str : path to the file where to generate the pattern data
"""
if name:
return(os.path.join(self._patternDir,"%s%d_%s.txt" % (name,i,"s32")))
else:
return(os.path.join(self._patternDir,"Reference%d_%s.txt" % (i,"s32")))
def refQ63P(self,i,name=None):
""" Path to a reference pattern from the ID
Args:
i (int): ID to the reference pattern
Raises:
Nothing
Returns:
str : path to the file where to generate the pattern data
"""
if name:
return(os.path.join(self._patternDir,"%s%d_%s.txt" % (name,i,"q63")))
else:
return(os.path.join(self._patternDir,"Reference%d_%s.txt" % (i,"q63")))
def refQ31P(self,i,name=None):
""" Path to a reference pattern from the ID
Args:
i (int): ID to the reference pattern
Raises:
Nothing
Returns:
str : path to the file where to generate the pattern data
"""
if name:
return(os.path.join(self._patternDir,"%s%d_%s.txt" % (name,i,"q31")))
else:
return(os.path.join(self._patternDir,"Reference%d_%s.txt" % (i,"q31")))
def refF32P(self,i,name=None):
""" Path to a reference pattern from the ID
Args:
i (int): ID to the reference pattern
Raises:
Nothing
Returns:
str : path to the file where to generate the pattern data
"""
if name:
return(os.path.join(self._patternDir,"%s%d_%s.txt" % (name,i,"f32")))
else:
return(os.path.join(self._patternDir,"Reference%d_%s.txt" % (i,"f32")))
def refF16P(self,i,name=None):
""" Path to a reference pattern from the ID
Args:
i (int): ID to the reference pattern
Raises:
Nothing
Returns:
str : path to the file where to generate the pattern data
"""
if name:
return(os.path.join(self._patternDir,"%s%d_%s.txt" % (name,i,"f16")))
else:
return(os.path.join(self._patternDir,"Reference%d_%s.txt" % (i,"f16")))
def paramP(self,i,name=None):
""" Path to a parameters from the ID
Args:
i (int): ID to the params
Raises:
Nothing
Returns:
str : path to the file where to generate the pattern data
"""
if name:
return(os.path.join(self._paramDir,"%s%d.txt" % (name,i)))
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
"""
if self.canOverwrite(i):
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
The format is recognized by the text framework script.
First line is the sample width (B,H or W for 8,16 or 32 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
"""
if self.canOverwrite(i):
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("W\n%d\n" % len(data))
for v in data:
f.write("// %f\n" % v)
f.write("%s\n" % float_to_hex(v))
def _writeVectorF16(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 for 8,16 or 32 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
"""
if self.canOverwrite(i):
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("H\n%d\n" % len(data))
for v in data:
f.write("// %f\n" % v)
f.write("%s\n" % float16_to_hex(v))
def _writeVectorQ63(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 for 8,16 or 32 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
"""
if self.canOverwrite(i):
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" % to_q63(v))
def _writeVectorQ31(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 for 8,16 or 32 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
"""
if self.canOverwrite(i):
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("W\n%d\n" % len(data))
for v in data:
f.write("// %f\n" % v)
f.write("%s\n" % to_q31(v))
def _writeVectorQ15(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 for 8,16 or 32 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
"""
if self.canOverwrite(i):
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("H\n%d\n" % len(data))
for v in data:
f.write("// %f\n" % v)
f.write("%s\n" % to_q15(v))
def _writeVectorS16(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 for 8,16 or 32 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
"""
if self.canOverwrite(i):
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("H\n%d\n" % len(data))
for v in data:
f.write("// %d\n" % v)
f.write("%s\n" % s16(v))
def _writeVectorS32(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 for 8,16 or 32 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
"""
if self.canOverwrite(i):
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("W\n%d\n" % len(data))
for v in data:
f.write("// %d\n" % v)
f.write("%s\n" % s32(v))
def _writeVectorU32(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 for 8,16 or 32 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
"""
if self.canOverwrite(i):
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("W\n%d\n" % len(data))
for v in data:
f.write("// %s\n" % v)
f.write("%s\n" % u32(v))
def _writeVectorQ7(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 for 8,16 or 32 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
"""
if self.canOverwrite(i):
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("B\n%d\n" % len(data))
for v in data:
f.write("// %f\n" % v)
f.write("%s\n" % to_q7(v))
def _writeVectorS8(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 for 8,16 or 32 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
"""
if self.canOverwrite(i):
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("B\n%d\n" % len(data))
for v in data:
f.write("// %d\n" % v)
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 == "f16"):
self._writeVectorF16(self.refP(j,name),data)
if (self._ext == "q63"):
self._writeVectorQ63(self.refP(j,name),data)
if (self._ext == "q31"):
self._writeVectorQ31(self.refP(j,name),data)
if (self._ext == "q15"):
self._writeVectorQ15(self.refP(j,name),data)
if (self._ext == "q7"):
self._writeVectorQ7(self.refP(j,name),data)
if (self._ext == "u32"):
self._writeVectorU32(self.refP(j,name),data)
if (self._ext == "s8"):
self._writeVectorS8(self.refP(j,name),data)
def writeReferenceQ63(self,j,data,name=None):
self._writeVectorQ63(self.refQ63P(j,name),data)
def writeReferenceQ31(self,j,data,name=None):
self._writeVectorQ31(self.refQ31P(j,name),data)
def writeReferenceS8(self,j,data,name=None):
self._writeVectorS8(self.refS8P(j,name),data)
def writeReferenceS16(self,j,data,name=None):
self._writeVectorS16(self.refS16P(j,name),data)
def writeReferenceS32(self,j,data,name=None):
self._writeVectorS32(self.refS32P(j,name),data)
def writeReferenceF32(self,j,data,name=None):
self._writeVectorF32(self.refF32P(j,name),data)
def writeReferenceF16(self,j,data,name=None):
self._writeVectorF16(self.refF16P(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 == "f16"):
self._writeVectorF16(self.inputP(j,name),data)
if (self._ext == "q31"):
self._writeVectorQ31(self.inputP(j,name),data)
if (self._ext == "q15"):
self._writeVectorQ15(self.inputP(j,name),data)
if (self._ext == "q7"):
self._writeVectorQ7(self.inputP(j,name),data)
if (self._ext == "u32"):
self._writeVectorU32(self.inputP(j,name),data)
if (self._ext == "s8"):
self._writeVectorS8(self.inputP(j,name),data)
def writeInputF32(self,j,data,name=None):
self._writeVectorF32(self.inputF32P(j,name),data)
def writeInputF16(self,j,data,name=None):
self._writeVectorF16(self.inputF16P(j,name),data)
def writeInputQ31(self,j,data,name=None):
self._writeVectorQ31(self.inputQ31P(j,name),data)
def writeInputQ15(self,j,data,name=None):
self._writeVectorQ15(self.inputQ15P(j,name),data)
def writeInputQ7(self,j,data,name=None):
self._writeVectorQ7(self.inputQ7P(j,name),data)
def writeInputS32(self,j,data,name=None):
self._writeVectorS32(self.inputS32P(j,name),data)
def writeInputS16(self,j,data,name=None):
self._writeVectorS16(self.inputS16P(j,name),data)
def writeInputS8(self,j,data,name=None):
self._writeVectorS8(self.inputS8P(j,name),data)
def writeInputU32(self,j,data,name=None):
self._writeVectorU32(self.inputU32P(j,name),data)
def writeParam(self,j,data,name=None):
""" Write pattern data
The format is recognized by the text framework script.
First line is the sample width (B,H or W for 8,16 or 32 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 parameter file
data (array): Vector containing the data
Raises:
Nothing
Returns:
Nothing
"""
i=self.paramP(j,name)
if self.canOverwrite(i):
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" % len(data))
for v in data:
f.write("%d\n" % v)