mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-02 09:45:18 +00:00
explanations and modifications for general ppa use
This commit is contained in:
parent
6f42b88d73
commit
e33ab9e515
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
|
||||
import matplotlib.pyplot as plt
|
||||
import matplotlib.lines as lines
|
||||
import matplotlib as mpl
|
||||
import numpy as np
|
||||
from collections import namedtuple
|
||||
import sklearn.metrics as skm
|
||||
import os
|
||||
|
||||
def synthsfromcsv(filename):
|
||||
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
|
||||
overlays data from both techs
|
||||
'''
|
||||
plt.rcParams["figure.figsize"] = (7,3.46)
|
||||
fig, axs = plt.subplots(2, 2)
|
||||
with mpl.rc_context({"figure.figsize": (7,3.46)}):
|
||||
fig, axs = plt.subplots(2, 2)
|
||||
|
||||
arr = [['delay', 'area'], ['lpower', 'denergy']]
|
||||
|
||||
@ -555,6 +557,8 @@ def plotPPA(mod, freq=None, norm=True, aleOpt=False):
|
||||
# plt.show()
|
||||
|
||||
def makeLineLegend():
|
||||
''' generates legend to accompany normalized plots
|
||||
'''
|
||||
plt.rcParams["figure.figsize"] = (5.5,0.3)
|
||||
fig = plt.figure()
|
||||
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')
|
||||
|
||||
def stdDevError():
|
||||
''' calculates std deviation and error for paper-writing purposes
|
||||
'''
|
||||
for var in ['delay', 'area', 'lpower', 'denergy']:
|
||||
errlist = []
|
||||
for module in modules:
|
||||
@ -668,6 +674,30 @@ def stdDevError():
|
||||
|
||||
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__':
|
||||
##############################
|
||||
@ -686,26 +716,22 @@ if __name__ == '__main__':
|
||||
##############################
|
||||
|
||||
# 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!
|
||||
bestSynths = csvOfBest('bestSynths.csv')
|
||||
makePlotDirectory()
|
||||
|
||||
# ### function examples
|
||||
# squareAreaDelay('sky90', 'add', 32)
|
||||
# oneMetricPlot('mult', 'lpower')
|
||||
# freqPlot('sky90', 'mux4', 16)
|
||||
# plotBestAreas('add')
|
||||
# ### other functions
|
||||
# makeCoefTable()
|
||||
# makeEqTable()
|
||||
# makeLineLegend()
|
||||
# muxPlot()
|
||||
# stdDevError()
|
||||
|
||||
for mod in modules:
|
||||
plotPPA(mod, norm=False)
|
||||
plotPPA(mod, aleOpt=True)
|
||||
for w in widths:
|
||||
freqPlot('sky90', mod, w)
|
||||
freqPlot('tsmc28', mod, w)
|
||||
plotPPA(mod, norm=False)
|
||||
plotPPA(mod, aleOpt=True)
|
||||
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)
|
||||
subprocess.Popen(command, shell=True)
|
||||
|
||||
def deleteRedundant(LoT):
|
||||
def deleteRedundant(synthsToRun):
|
||||
'''removes any previous runs for the current synthesis specifications'''
|
||||
synthStr = "rm -rf runs/ppa_{}_{}_rv32e_{}nm_{}_*"
|
||||
for synth in LoT:
|
||||
for synth in synthsToRun:
|
||||
bashCommand = synthStr.format(*synth)
|
||||
outputCPL = subprocess.check_output(['bash','-c', bashCommand])
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
LoT = []
|
||||
def freqSweep(module, width, tech):
|
||||
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]
|
||||
allSynths = synthsfromcsv('bestSynths.csv')
|
||||
for synth in allSynths:
|
||||
f = 1000/synth.delay
|
||||
for freq in [round(f+f*x/100) for x in arr]:
|
||||
LoT += [[synth.module, str(synth.width), synth.tech, str(freq)]]
|
||||
|
||||
##### Only do syntheses for which a run doesn't already exist
|
||||
if (synth.module == module) & (synth.tech == tech) & (synth.width == width):
|
||||
f = 1000/synth.delay
|
||||
for freq in [round(f+f*x/100) for x in arr]:
|
||||
synthsToRun += [[synth.module, str(synth.width), synth.tech, str(freq)]]
|
||||
return synthsToRun
|
||||
|
||||
def filterRedundant(synthsToRun):
|
||||
bashCommand = "find . -path '*runs/ppa*rv32e*' -prune"
|
||||
output = subprocess.check_output(['bash','-c', bashCommand])
|
||||
specReg = re.compile('[a-zA-Z0-9]+')
|
||||
allSynths = output.decode("utf-8").split('\n')[:-1]
|
||||
allSynths = [specReg.findall(oneSynth)[2:7] 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):
|
||||
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.starmap(runCommand, synthsToRun)
|
||||
pool.starmap(print, synthsToRun)
|
Loading…
Reference in New Issue
Block a user