forked from Github_Repos/cvw
explanations and modifications for general ppa use
This commit is contained in:
parent
19db618b7f
commit
b196b6b504
32
synthDC/ppa/README
Normal file
32
synthDC/ppa/README
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
Wally PPA Study
|
||||||
|
July 8, 2022
|
||||||
|
Madeleine Masser-Frye
|
||||||
|
mmasserfrye@hmc.edu
|
||||||
|
___________________
|
||||||
|
Apologies for issues in this folder, code was written originally for individual use and documentation was compiled in haste. Please feel free to contact the author with questions.
|
||||||
|
|
||||||
|
-------------------
|
||||||
|
ppaSynth.py
|
||||||
|
|
||||||
|
Run to synthesize datapath modules from src/ppa.
|
||||||
|
To run a specific combination of widths, modules, techs, and freqs,
|
||||||
|
modify those lists and use allCombos() to generate synthsToRun (comment out freqSweep).
|
||||||
|
To run a sweep of frequencies around the best delay found in existing syntheses (according to bestSynths.csv), modify the parameters and use freqSweep to generate synthsToRun.
|
||||||
|
To remove synths to be run that already exist in /runs from synthsToRun, use filterRedundant().
|
||||||
|
Syntheses run in parallel but you may encounter issues doing more than a dozen or so at once.
|
||||||
|
-------------------
|
||||||
|
ppaAnalyze.py
|
||||||
|
|
||||||
|
Run to plot results of PPA syntheses. See docstrings for individual function info.
|
||||||
|
-------------------
|
||||||
|
bestSynths.csv
|
||||||
|
|
||||||
|
Results of the synthesis for each combination of module, width, and tech with the best achievable delay. Generated by csvOfBest() in ppaAnalyze.py
|
||||||
|
-------------------
|
||||||
|
ppaFitting.csv & ppaEquations.csv
|
||||||
|
|
||||||
|
Representations of the regression fit for each module and metric. Generated in ppaAnalyze.py by makeCoefTable() and makeEqTable().
|
||||||
|
-------------------
|
||||||
|
ppaData.csv
|
||||||
|
|
||||||
|
Results from all synthesis runs. Generated by synthsintocsv() and used by synthsfromcsv in ppaAnalyze.py.
|
@ -8,9 +8,11 @@ import re
|
|||||||
from matplotlib.cbook import flatten
|
from matplotlib.cbook import flatten
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
import matplotlib.lines as lines
|
import matplotlib.lines as lines
|
||||||
|
import matplotlib as mpl
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
import sklearn.metrics as skm
|
import sklearn.metrics as skm
|
||||||
|
import os
|
||||||
|
|
||||||
def synthsfromcsv(filename):
|
def synthsfromcsv(filename):
|
||||||
Synth = namedtuple("Synth", "module tech width freq delay area lpower denergy")
|
Synth = namedtuple("Synth", "module tech width freq delay area lpower denergy")
|
||||||
@ -518,8 +520,8 @@ def plotPPA(mod, freq=None, norm=True, aleOpt=False):
|
|||||||
if no freq specified, uses the synthesis with best achievable delay for each width
|
if no freq specified, uses the synthesis with best achievable delay for each width
|
||||||
overlays data from both techs
|
overlays data from both techs
|
||||||
'''
|
'''
|
||||||
plt.rcParams["figure.figsize"] = (7,3.46)
|
with mpl.rc_context({"figure.figsize": (7,3.46)}):
|
||||||
fig, axs = plt.subplots(2, 2)
|
fig, axs = plt.subplots(2, 2)
|
||||||
|
|
||||||
arr = [['delay', 'area'], ['lpower', 'denergy']]
|
arr = [['delay', 'area'], ['lpower', 'denergy']]
|
||||||
|
|
||||||
@ -555,6 +557,8 @@ def plotPPA(mod, freq=None, norm=True, aleOpt=False):
|
|||||||
# plt.show()
|
# plt.show()
|
||||||
|
|
||||||
def makeLineLegend():
|
def makeLineLegend():
|
||||||
|
''' generates legend to accompany normalized plots
|
||||||
|
'''
|
||||||
plt.rcParams["figure.figsize"] = (5.5,0.3)
|
plt.rcParams["figure.figsize"] = (5.5,0.3)
|
||||||
fig = plt.figure()
|
fig = plt.figure()
|
||||||
fullLeg = [lines.Line2D([0], [0], color='black', label='fastest', linestyle='-')]
|
fullLeg = [lines.Line2D([0], [0], color='black', label='fastest', linestyle='-')]
|
||||||
@ -619,6 +623,8 @@ def muxPlot(fits='clsgn', norm=True):
|
|||||||
plt.savefig('./plots/mux.png')
|
plt.savefig('./plots/mux.png')
|
||||||
|
|
||||||
def stdDevError():
|
def stdDevError():
|
||||||
|
''' calculates std deviation and error for paper-writing purposes
|
||||||
|
'''
|
||||||
for var in ['delay', 'area', 'lpower', 'denergy']:
|
for var in ['delay', 'area', 'lpower', 'denergy']:
|
||||||
errlist = []
|
errlist = []
|
||||||
for module in modules:
|
for module in modules:
|
||||||
@ -668,6 +674,30 @@ def stdDevError():
|
|||||||
|
|
||||||
print(var, ' ', avgErr, ' ', stdv)
|
print(var, ' ', avgErr, ' ', stdv)
|
||||||
|
|
||||||
|
def makePlotDirectory():
|
||||||
|
''' creates plots directory in same level as this script to store plots in
|
||||||
|
'''
|
||||||
|
current_directory = os.getcwd()
|
||||||
|
final_directory = os.path.join(current_directory, 'plots')
|
||||||
|
if not os.path.exists(final_directory):
|
||||||
|
os.makedirs(final_directory)
|
||||||
|
os.chdir(final_directory)
|
||||||
|
|
||||||
|
for folder in ['freqBuckshot', 'normalized', 'unnormalized']:
|
||||||
|
new_directory = os.path.join(final_directory, folder)
|
||||||
|
if not os.path.exists(new_directory):
|
||||||
|
os.makedirs(new_directory)
|
||||||
|
os.chdir(new_directory)
|
||||||
|
if 'freq' in folder:
|
||||||
|
for tech in ['sky90', 'tsmc28']:
|
||||||
|
for mod in modules:
|
||||||
|
tech_directory = os.path.join(new_directory, tech)
|
||||||
|
mod_directory = os.path.join(tech_directory, mod)
|
||||||
|
if not os.path.exists(mod_directory):
|
||||||
|
os.makedirs(mod_directory)
|
||||||
|
os.chdir('..')
|
||||||
|
|
||||||
|
os.chdir(current_directory)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
##############################
|
##############################
|
||||||
@ -686,26 +716,22 @@ if __name__ == '__main__':
|
|||||||
##############################
|
##############################
|
||||||
|
|
||||||
# cleanup() # run to remove garbage synth runs
|
# cleanup() # run to remove garbage synth runs
|
||||||
# synthsintocsv() # slow, run only when new synth runs to add to csv
|
synthsintocsv() # slow, run only when new synth runs to add to csv
|
||||||
|
|
||||||
allSynths = synthsfromcsv('ppaData.csv') # your csv here!
|
allSynths = synthsfromcsv('ppaData.csv') # your csv here!
|
||||||
bestSynths = csvOfBest('bestSynths.csv')
|
bestSynths = csvOfBest('bestSynths.csv')
|
||||||
|
makePlotDirectory()
|
||||||
|
|
||||||
# ### function examples
|
# ### other functions
|
||||||
# squareAreaDelay('sky90', 'add', 32)
|
|
||||||
# oneMetricPlot('mult', 'lpower')
|
|
||||||
# freqPlot('sky90', 'mux4', 16)
|
|
||||||
# plotBestAreas('add')
|
|
||||||
# makeCoefTable()
|
# makeCoefTable()
|
||||||
# makeEqTable()
|
# makeEqTable()
|
||||||
# makeLineLegend()
|
|
||||||
# muxPlot()
|
# muxPlot()
|
||||||
# stdDevError()
|
# stdDevError()
|
||||||
|
|
||||||
for mod in modules:
|
for mod in modules:
|
||||||
plotPPA(mod, norm=False)
|
|
||||||
plotPPA(mod, aleOpt=True)
|
|
||||||
for w in widths:
|
for w in widths:
|
||||||
freqPlot('sky90', mod, w)
|
freqPlot('sky90', mod, w)
|
||||||
freqPlot('tsmc28', mod, w)
|
freqPlot('tsmc28', mod, w)
|
||||||
|
plotPPA(mod, norm=False)
|
||||||
|
plotPPA(mod, aleOpt=True)
|
||||||
plt.close('all')
|
plt.close('all')
|
@ -10,47 +10,64 @@ def runCommand(module, width, tech, freq):
|
|||||||
command = "make synth DESIGN=ppa_{}_{} TECH={} DRIVE=INV FREQ={} MAXOPT=1 MAXCORES=1".format(module, width, tech, freq)
|
command = "make synth DESIGN=ppa_{}_{} TECH={} DRIVE=INV FREQ={} MAXOPT=1 MAXCORES=1".format(module, width, tech, freq)
|
||||||
subprocess.Popen(command, shell=True)
|
subprocess.Popen(command, shell=True)
|
||||||
|
|
||||||
def deleteRedundant(LoT):
|
def deleteRedundant(synthsToRun):
|
||||||
'''removes any previous runs for the current synthesis specifications'''
|
'''removes any previous runs for the current synthesis specifications'''
|
||||||
synthStr = "rm -rf runs/ppa_{}_{}_rv32e_{}nm_{}_*"
|
synthStr = "rm -rf runs/ppa_{}_{}_rv32e_{}nm_{}_*"
|
||||||
for synth in LoT:
|
for synth in synthsToRun:
|
||||||
bashCommand = synthStr.format(*synth)
|
bashCommand = synthStr.format(*synth)
|
||||||
outputCPL = subprocess.check_output(['bash','-c', bashCommand])
|
outputCPL = subprocess.check_output(['bash','-c', bashCommand])
|
||||||
|
|
||||||
if __name__ == '__main__':
|
def freqSweep(module, width, tech):
|
||||||
|
|
||||||
LoT = []
|
|
||||||
synthsToRun = []
|
synthsToRun = []
|
||||||
|
|
||||||
##### Run specific syntheses
|
|
||||||
# widths = [8]
|
|
||||||
# modules = ['mult', 'add', 'shiftleft', 'flop', 'comparator', 'priorityencoder', 'add', 'csa', 'mux2', 'mux4', 'mux8']
|
|
||||||
# techs = ['sky90']
|
|
||||||
# freqs = [5000]
|
|
||||||
# for w in widths:
|
|
||||||
# for module in modules:
|
|
||||||
# for tech in techs:
|
|
||||||
# for freq in freqs:
|
|
||||||
# LoT += [[module, str(w), tech, str(freq)]]
|
|
||||||
|
|
||||||
##### Run a sweep based on best delay found in existing syntheses
|
|
||||||
arr = [-8, -6, -4, -2, 0, 2, 4, 6, 8]
|
arr = [-8, -6, -4, -2, 0, 2, 4, 6, 8]
|
||||||
allSynths = synthsfromcsv('bestSynths.csv')
|
allSynths = synthsfromcsv('bestSynths.csv')
|
||||||
for synth in allSynths:
|
for synth in allSynths:
|
||||||
f = 1000/synth.delay
|
if (synth.module == module) & (synth.tech == tech) & (synth.width == width):
|
||||||
for freq in [round(f+f*x/100) for x in arr]:
|
f = 1000/synth.delay
|
||||||
LoT += [[synth.module, str(synth.width), synth.tech, str(freq)]]
|
for freq in [round(f+f*x/100) for x in arr]:
|
||||||
|
synthsToRun += [[synth.module, str(synth.width), synth.tech, str(freq)]]
|
||||||
##### Only do syntheses for which a run doesn't already exist
|
return synthsToRun
|
||||||
|
|
||||||
|
def filterRedundant(synthsToRun):
|
||||||
bashCommand = "find . -path '*runs/ppa*rv32e*' -prune"
|
bashCommand = "find . -path '*runs/ppa*rv32e*' -prune"
|
||||||
output = subprocess.check_output(['bash','-c', bashCommand])
|
output = subprocess.check_output(['bash','-c', bashCommand])
|
||||||
specReg = re.compile('[a-zA-Z0-9]+')
|
specReg = re.compile('[a-zA-Z0-9]+')
|
||||||
allSynths = output.decode("utf-8").split('\n')[:-1]
|
allSynths = output.decode("utf-8").split('\n')[:-1]
|
||||||
allSynths = [specReg.findall(oneSynth)[2:7] for oneSynth in allSynths]
|
allSynths = [specReg.findall(oneSynth)[2:7] for oneSynth in allSynths]
|
||||||
allSynths = [oneSynth[0:2] + [oneSynth[3][:-2]] + [oneSynth[4]] for oneSynth in allSynths]
|
allSynths = [oneSynth[0:2] + [oneSynth[3][:-2]] + [oneSynth[4]] for oneSynth in allSynths]
|
||||||
for synth in LoT:
|
output = []
|
||||||
|
for synth in synthsToRun:
|
||||||
if (synth not in allSynths):
|
if (synth not in allSynths):
|
||||||
synthsToRun += [synth]
|
output += [synth]
|
||||||
|
return output
|
||||||
|
|
||||||
|
def allCombos(widths, modules, techs, freqs):
|
||||||
|
synthsToRun = []
|
||||||
|
for w in widths:
|
||||||
|
for module in modules:
|
||||||
|
for tech in techs:
|
||||||
|
for freq in freqs:
|
||||||
|
synthsToRun += [[module, str(w), tech, str(freq)]]
|
||||||
|
return synthsToRun
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
|
||||||
|
##### Run specific syntheses
|
||||||
|
widths = [8, 16, 32, 64, 128]
|
||||||
|
modules = ['mult', 'add', 'shiftleft', 'flop', 'comparator', 'priorityencoder', 'add', 'csa', 'mux2', 'mux4', 'mux8']
|
||||||
|
techs = ['sky90', 'tsmc28']
|
||||||
|
freqs = [5000]
|
||||||
|
synthsToRun = allCombos(widths, modules, techs, freqs)
|
||||||
|
|
||||||
|
##### Run a sweep based on best delay found in existing syntheses
|
||||||
|
module = 'add'
|
||||||
|
width = 32
|
||||||
|
tech = 'sky90'
|
||||||
|
synthsToRun = freqSweep(module, width, tech)
|
||||||
|
|
||||||
|
##### Only do syntheses for which a run doesn't already exist
|
||||||
|
synthsToRun = filterRedundant(synthsToRun)
|
||||||
|
|
||||||
pool = Pool(processes=25)
|
pool = Pool(processes=25)
|
||||||
pool.starmap(runCommand, synthsToRun)
|
pool.starmap(print, synthsToRun)
|
Loading…
Reference in New Issue
Block a user