Skip to content

Commit

Permalink
Fix demo executables path. Remove MIPS info from the plot and the csv…
Browse files Browse the repository at this point in the history
… log
  • Loading branch information
Shuchita Khare committed Sep 22, 2023
1 parent db0af9a commit 5f957e6
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 49 deletions.
74 changes: 38 additions & 36 deletions doc/python/asrc_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

class asrc_util:
def __init__(self, path, relative, fftPoints, ch0_bins, ch1_bins):
self.path = path
self.path = str(path)
self.relative = relative

# locations for results - note they are purged every time this is run
Expand All @@ -24,14 +24,14 @@ def __init__(self, path, relative, fftPoints, ch0_bins, ch1_bins):
self.inputFolder = self.cleanFolder("_build/input") # put any input test files here
self.expectedFolder = self.cleanFolder("_build/expected") # put C ref model o/p here
self.rstFolder = self.cleanFolder("_build/rst") # put RST o/p here

self.logFile = "/log.csv" # tabulated results

# the C-models and XSIM models which get run
self.asrc_model ="{}/../tmp_models/asrc_demo".format(self.path) # path and file of the reference c model executable
self.ssrc_model ="{}/../tmp_models/ssrc_demo".format(self.path) # path and file of the reference c model executable
self.ds3_model ="{}/../tmp_models/ds3_demo".format(self.path) # path and file of the reference c model executable
self.os3_model ="{}/../tmp_models/os3_demo".format(self.path) # path and file of the reference c model executable
self.asrc_model ="{}/../../build/tests/asrc_test/asrc_golden".format(self.path) # path and file of the reference c model executable
self.ssrc_model ="{}/../../build/tests/ssrc_test/ssrc_golden".format(self.path) # path and file of the reference c model executable
self.ds3_model ="{}/../../build/tests/ds3_test/ds3_golden".format(self.path) # path and file of the reference c model executable
self.os3_model ="{}/../../build/tests/os3_test/os3_golden".format(self.path) # path and file of the reference c model executable
self.xePath = "{}/XSIM/ASRC/asrc_test.xe".format(self.path) # path and file of the xe xsim executable

# definitions of sample ratea
Expand All @@ -40,7 +40,7 @@ def __init__(self, path, relative, fftPoints, ch0_bins, ch1_bins):
self.factors = {"44":0, "48":1, "88":2, "96":3, "176":4, "192":5} # look up to convert rate to the filter bank id needed by the ASRC
self.sampleRates = {"16":16000, "32":32000, "44":44100, "48":48000, "88":88200, "96":96000, "176":176400, "192":192000} #convinience to save typing out sample rates in full
self.sigMax = {"16":7300, "32":14600, "44":20200, "48":21800, "88":40000, "96":47990, "176":80000, "192":85000} # upper limit on input freq for given sample rate

self.numSamples = {} #populated later based on oprate to ensure sufficient samples for fft
self.ignoreSamples = 2000 #worst case for high up-sampling
self.fftPoints = fftPoints
Expand All @@ -56,7 +56,7 @@ def __init__(self, path, relative, fftPoints, ch0_bins, ch1_bins):
self.skip_xsim = True # FIX THIS LATER
self.rstFile = ""


# update the input frequencies
# allows input of frequencies as a list for each channel, or use the autoFill which
# populates channel 1 with mutiple tones, spaced logrithmically, most dense at higher freq, and ch0 is always 10% in
Expand All @@ -65,7 +65,7 @@ def updateSig(self, ipRate, ch0_bins, ch1_bins, autoFill=False):
# this manipultaes the fft size to attempt to force any reflections around the ip sample rate nyquist also ending up
# in an integer fft bin
self.fftPoints = int(10000 *(self.sampleRates[ipRate] * self.fDev) / self.sampleRates[self.opRate])
print("Over-wrote the fft sive to {} points".format(self.fftPoints))
print(f"Over-wrote the fft size to {self.fftPoints} points. ipRate = {ipRate}")

#for channel 0
ch0_ratio = 0.05 # 5% of the way into the fft bins, so 10% on the plot
Expand Down Expand Up @@ -110,13 +110,13 @@ def makePlotTitle(self, simLog, channel):

def logResults(self, source, ipRate, opRate, fDev, ch, SNR, THD, totalmips, ch0mips=None, ch1mips=None, txt=None, snr2=None, mips2=None):
# simple function to append information to a log, which is kept as an array of dictionaries
realRate = self.sampleRates[opRate] / self.fDev
realRate = self.sampleRates[opRate] / self.fDev
sigList = []
for s in self.sig[ch]:
sigList.append("{:.3f}".format(float(mp.fmul(realRate ,mp.fdiv(s, self.fftPoints)))))
signals = ";".join(sigList)
#info = {"source":source, "ipRate(Hz)":self.sampleRates[ipRate], "opRate(Hz)":self.sampleRates[opRate], "fDev":fDev, "ch":ch, "signals(Hz)":signals, "SNR(dB)":SNR, "THD(dB)":THD,"Total MIPS":totalmips, "MIPS(ch0)":ch0mips, "MIPS(ch1)":ch1mips, "Text":txt}
info = {"source":source, "ipRate(Hz)":str(self.sampleRates[ipRate]), "opRate(Hz)":str(self.sampleRates[opRate]), "fDev":str(fDev), "ch":str(ch), "signals(Hz)":signals, "SNR(dB)":"{:.1f}".format(SNR), "THD(dB)":THD,"Total MIPS":"{:.0f}".format(totalmips), "MIPS(ch0)":"{:.0f}".format(ch0mips), "MIPS(ch1)":"{:.0f}".format(ch1mips)}
info = {"source":source, "ipRate(Hz)":str(self.sampleRates[ipRate]), "opRate(Hz)":str(self.sampleRates[opRate]), "fDev":str(fDev), "ch":str(ch), "signals(Hz)":signals, "SNR(dB)":"{:.1f}".format(SNR), "THD(dB)":THD}
self.log.append(info)


Expand All @@ -125,7 +125,7 @@ def log2csv(self):
logfile = open(self.outputFolder + self.logFile, "w")
logfile.write(",".join(self.log[0].keys()) + "\n") # write headings
for i in self.log:
logfile.write((','.join(i.values())).replace("\n", ";") + "\n") # write data
logfile.write((','.join(i.values())).replace("\n", ";") + "\n") # write data
logfile.close()


Expand All @@ -142,7 +142,7 @@ def cleanFolder(self, folder):
if self.relative:
p = p.replace(self.path, ".")
return p

def listFactors(self, x):
factors=[]
for i in range(1,x+1):
Expand All @@ -161,9 +161,9 @@ def makeSignal(self, fsamp, fsig, asig, l, ferr=1.0):
print("Make signal: {:.2f}".format(float(fsig)))
a = asig * 2**31
x = np.linspace(0, float(2*mp.pi*f*(l-1)), l)
ipdata = a * np.sin(x)
ipdata = a * np.sin(x)
return ipdata


def saveInputFile(self, signals, fileName):
# sums the signals into one signal and saves as a file
Expand All @@ -174,9 +174,9 @@ def saveInputFile(self, signals, fileName):
np.savetxt(file, data, fmt='%d', delimiter='\n')
#writewav("/mnt/c/Users/andrewdewhurst/OneDrive - Xmos/Temp/rawdata/test.wav", 44100, (data[0]/2**16).astype(np.int16))
return file, data

def makeInputFiles(self, test_rates, ferr=1.0):
# create two channels of input
# create two channels of input
# define some test signal frequencies w.r.t. op rate
realRate = self.sampleRates[self.opRate] # mp.fdiv(self.sampleRates[self.opRate], self.fDev)
#
Expand Down Expand Up @@ -211,7 +211,7 @@ def makeInputFiles(self, test_rates, ferr=1.0):


def doFFT(self, data, window=False):
# convinient way to select between fft styles. Note that the periodic one will need a lot more samples, so
# convinient way to select between fft styles. Note that the periodic one will need a lot more samples, so
# use window=True for debuging.
if window:
return self.winFFT(data)
Expand Down Expand Up @@ -262,7 +262,7 @@ def plotFFT(self, xydata, combine=False, title=None, subtitles=None, log=True, t
ax.plot(xy[0], xy[1] if log else xy[2], linestyle=slut[i%len(slut)], color=clut[i%len(clut)], linewidth=1, label=subtitles[i])
ax.set_xlabel("Frequency (KHz)")
ax.set_ylabel("dB")
ax.set_ylim(-200,0)
ax.set_ylim(-250,0)
ax.grid()
if text != None:
tl = np.sum([text[x].count("\n") + 1 for x in range(i)]) if combine else 0 # this stacks up the text comments in the case of combined plots
Expand Down Expand Up @@ -292,7 +292,7 @@ def exFileName(self, fin, label, fDev, opRate):
#a simple utility to convert an input file pat+name to an output version, appending the frequency deviation
newName = fin.replace(self.inputFolder, self.expectedFolder).replace(".dat", "_fso{}_fdev{:f}_{}.dat".format(opRate, fDev, label))
return newName


def run_c_model(self, ipFiles, opRate, blocksize, fDev):
# Runs the various simulators across the input files, for the provided opRate and frequency deviation
Expand All @@ -314,21 +314,22 @@ def run_c_model(self, ipFiles, opRate, blocksize, fDev):
ch1 = self.exFileName(ipFile[1], 'c-asrc', fDev, opRate)

cmd = "{} -i{} -j{} -k{} -o{} -p{} -q{} -d{} -l{} -n{} -e{}".format(
self.asrc_model, ipFile[0], ipFile[1] , self.factors[ipFile[2]], ch0, ch1, self.factors[opRate], dither, self.numSamples[ipFile[2]], blocksize, fDev)
self.asrc_model, ipFile[0], ipFile[1] , self.factors[ipFile[2]], ch0, ch1, self.factors[opRate], dither, self.numSamples[ipFile[2]], blocksize, fDev)
p = Popen([cmd], stdin=PIPE, stdout=PIPE, shell=True)
output, error = p.communicate(input=b'\n')
opFiles = np.append(opFiles, np.array([[ch0, ch1, opRate, str(fDev), output, "c-asrc"]]), axis=0)
simLog[ipFile[0]]['asrc']=[str(ch0), 0, opRate, str(fDev), output, "c-asrc"]
simLog[ipFile[1]]['asrc']=[str(ch1), 1, opRate, str(fDev), output, "c-asrc"]


# SSRC C Model
# ------------
if ipFile[2] in self.srcRates and self.opRate in self.srcRates and fDev==1:
ch0 = self.exFileName(ipFile[0], 'c-ssrc', fDev, opRate)
ch1 = self.exFileName(ipFile[1], 'c-ssrc', fDev, opRate)

cmd = "{} -i{} -j{} -k{} -o{} -p{} -q{} -d{} -l{} -n{}".format(
self.ssrc_model, ipFile[0], ipFile[1] , self.factors[ipFile[2]], ch0, ch1, self.factors[opRate], dither, self.numSamples[ipFile[2]], blocksize)
self.ssrc_model, ipFile[0], ipFile[1] , self.factors[ipFile[2]], ch0, ch1, self.factors[opRate], dither, self.numSamples[ipFile[2]], blocksize)
p = Popen([cmd], stdin=PIPE, stdout=PIPE, shell=True)
output, error = p.communicate(input=b'\n')
opFiles = np.append(opFiles, np.array([[ch0, ch1, opRate, "1.0", output, "c-ssrc"]]), axis=0)
Expand Down Expand Up @@ -372,13 +373,14 @@ def run_c_model(self, ipFiles, opRate, blocksize, fDev):
os.remove("./output.dat")

# ASRC XSIM Model
# ---------------
# ---------------
if ipFile[2] in self.srcRates and self.opRate in self.srcRates and not self.skip_xsim:
xsimFiles = self.run_xsim(ipFiles, opRate, fDev, simLog)
opFiles = np.append(opFiles, xsimFiles, axis=0)


return opFiles, simLog


def run_xsim(self, ipFiles, opRate, fDev, simLog):
if os.path.isfile("./asrc_test.lnk"):
Expand All @@ -388,10 +390,10 @@ def run_xsim(self, ipFiles, opRate, fDev, simLog):
for ipFile in ipFiles:
ch0 = self.opFileName(ipFile[0], 'x-asrc', fDev, opRate)
ch1 = self.opFileName(ipFile[1], 'x-asrc', fDev, opRate)

cmd0 = "cd {}".format(self.path)
cmd1 = "xsim --args asrc_test.lnk -i {} {} -o {} {} -f {} -g {} -n {} -e {}".format(
ipFile[0], ipFile[1], ch0, ch1, self.sampleRates[ipFile[2]], self.sampleRates[opRate], self.numSamples[ipFile[2]], fDev)
ipFile[0], ipFile[1], ch0, ch1, self.sampleRates[ipFile[2]], self.sampleRates[opRate], self.numSamples[ipFile[2]], fDev)
cmd = cmd0 + ";pwd;" + cmd1
p = Popen(cmd, stdin=PIPE, stdout=PIPE, shell=True)
output, error = p.communicate(input=b'\n')
Expand Down Expand Up @@ -427,16 +429,16 @@ def scrapeCLog(self, data):
ch0mips = float(m[0].replace("\\n", "").split(":")[1].strip())
ch1mips = float(m[5].replace("\\n", "").split(":")[1].strip())
totalmips = ch0mips + ch1mips
txtmips = "\n".join(m)
txtmips = "\n".join(m)
if data['src'] == "c-ssrc":
p = re.compile("MIPS.*?\n")
m = re.findall(p, str(data['log']).replace("\\n","\n"))
if len(m) > 0:
totalmips = float(m[0].split(":")[1].strip())
totalmips = float(m[0].split(":")[1].strip())

return {"log":txtmips, "total_mips":totalmips, "ch0_mips":ch0mips, "ch1_mips":ch1mips}


return {"log":txtmips, "total_mips":totalmips, "ch0_mips":ch0mips, "ch1_mips":ch1mips}


def makeLabel(self, item):
#utility to generate a title / filename to use in plots from an item from a file list which is in the foramt [file1, file2, rate as str]
#and should work for ipFiles and opFiles
Expand All @@ -448,7 +450,7 @@ def makeLabel(self, item):
def loadDataFromOutputFile(self, file):
#loads an array of files in the format returned by running 'run_c_model' and returns an array of elements, each of which is a dictionary of [ 2 channels of samples], [2 channels of labels], o/p rate
ch0 = np.loadtxt(file[0]).astype("int32")
label = self.makeLabel(file)
label = self.makeLabel(file)
return {'samples':ch0, 'labels':label, 'chan':file[-5], 'rate':file[-4], 'fdev':file[-3], 'log':file[-2], 'src':file[-1]}


Expand Down Expand Up @@ -479,8 +481,8 @@ def calcTHD(self, fftdata, ch):
thd = 10*np.log10((noise/signal))
thd="{:.1f}dB".format(thd) #returned as string so we can pass the "NA" for muti-tone cases
return thd


def makeRST(self, file, ipRate, opRate, fDev, sims):
relFile = os.path.relpath(self.outputFolder, self.rstFolder) + "/" + file
fsi = "{:,d}Hz".format(self.sampleRates[ipRate])
Expand All @@ -490,7 +492,7 @@ def makeRST(self, file, ipRate, opRate, fDev, sims):
self.rstFile = self.rstFile + "\n\n\n" + ".. figure:: {}".format(relFile)
self.rstFile = self.rstFile + "\n" + " :scale: {}".format("90%")
self.rstFile = self.rstFile + "\n\n" + " Input Fs: {}, Output Fs: {}, Fs error: {}, Results for: {}".format(fsi, fso, ferr, plots)


def addRSTHeader(self, title, level):
underline=["=", "+", "-", "."]
Expand All @@ -515,4 +517,4 @@ def addLog2RST(self):
def saveRST(self, file):
rst = open("{}/{}".format(self.rstFolder, file), "w")
rst.write(self.rstFile)
rst.close()
rst.close()
24 changes: 11 additions & 13 deletions doc/python/doc_asrc.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from asrc_utils import asrc_util
import numpy as np
import matplotlib.pyplot as plt
from mpmath import mp
from pathlib import Path

################################################################################################################
# OVERVIEW
Expand All @@ -19,12 +19,12 @@


# Setup some basics
path = '.'
pkg_dir = Path(__file__).parent
xsim = False
fftPoints=1024 # note when updating the test tones with "updateSig" this is overwritten
FERR = 1.0 #this is an additional sample rate deviation applied to the inpt signal to test effect of errors

U = asrc_util(path, True, fftPoints,[200], [500]) # create the util object
U = asrc_util(pkg_dir, True, fftPoints,[200], [500]) # create the util object
U.addRSTHeader("Performance information", 1) # start the RST it generates with a title
U.addRSTHeader("Chart data", 2) # start the RST it generates with a title

Expand All @@ -44,15 +44,15 @@

# Make a set of input files based on range of sample rates supported
ipFiles, sig = U.makeInputFiles([ipRate], FERR) # makes the signals, saves data as files and returns some info about them

# Put the input data through the golden "C" emulators
opFiles, simLog = U.run_c_model(ipFiles, opRate, 4, fDev)
opFiles, simLog = U.run_c_model(ipFiles, opRate, 4, fDev)

# Itterate over all the input data files and channels
for channels in ipFiles: # For each input sata set there will be an output one for each channel
for channel in channels[0:2]:
print(channel)

if len(simLog[channel]) > 0: #at least one simulation ran for this combination of iprate, oprate and fdev
no_results = False
for sim in simLog[channel]:
Expand All @@ -72,11 +72,11 @@
opTHD = U.calcTHD(opfft, opData['chan'])

# Keep the results to plot later
text="SNR:{:.1f}dB\nTHD:{}dB\nMIPS:{}\n{}".format(opSNR, opTHD, info['total_mips'], info['log'])
text="SNR:{:.1f}dB\nTHD:{}dB\n".format(opSNR, opTHD)
U.pushPlotInfo(opfft, oplabel, text)

# Update log with these results
U.logResults(sim, ipRate, opRate, fDev, opData['chan'], opSNR, opTHD, info['total_mips'], info['ch0_mips'], info['ch1_mips'], info['log'])
U.logResults(sim, ipRate, opRate, fDev, opData['chan'], opSNR, opTHD, info['total_mips'], info['ch0_mips'], info['ch1_mips'], info['log'])


#Plot the results
Expand Down Expand Up @@ -104,7 +104,7 @@
# xsim model fft data
xfft = U.doFFT(xdata[r], ch)
xlabel = xdata[r]['labels'][ch]
# Get MHz utilization info from the log
util = U.scrapeXsimLog(xdata[r])
Expand All @@ -118,12 +118,12 @@
# Plot the result, and save the chart - just the "C" results here
text=["C SNR:{:.1f}dB\nMIPS:{:.1f}".format(opSNR, ch0mips + ch1mips),
"XSIM SNR:{:.1f}dB\nMIPS:2Ch CPU:{:.1f}\nPass/Fail:{}".format(xSNR, util, match)]
"XSIM SNR:{:.1f}dB\nMIPS:2Ch CPU:{:.1f}\nPass/Fail:{}".format(xSNR, util, match)]
title = "Channel={}, IP={}, OP={}, FDEV={}, XSIM".format(ch,ipdata[r]['rate'], opRate, fDev)
U.plotFFT([opfft, xfft], combine=False, title=title, subtitles=["FIX ME", xlabel], log=True, text=text)
# Update log with these results
U.logResults("XSIM", ipdata[r]['rate'], opRate, fDev, ch, xSNR, util, txt=match)
U.logResults("XSIM", ipdata[r]['rate'], opRate, fDev, ch, xSNR, util, txt=match)
'''

Expand All @@ -137,5 +137,3 @@
# tidy up call to fft to make windowing a default off option
# go through the functions to use self.opRate, self.fDev everywhere
# legacy "list-factors" code can be removed


0 comments on commit 5f957e6

Please sign in to comment.