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 | ||||
| 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