From 8432c6331cd05688a9210ffe7a0a85901f45dd29 Mon Sep 17 00:00:00 2001 From: Madeleine Masser-Frye <51804758+mmasserfrye@users.noreply.github.com> Date: Fri, 8 Jul 2022 22:16:34 +0000 Subject: [PATCH 1/8] told dc to look in synth directory for hdl and WORK --- synthDC/scripts/synth.tcl | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/synthDC/scripts/synth.tcl b/synthDC/scripts/synth.tcl index 36a72302..2cea1241 100755 --- a/synthDC/scripts/synth.tcl +++ b/synthDC/scripts/synth.tcl @@ -26,11 +26,11 @@ set saifpower $::env(SAIFPOWER) set maxopt $::env(MAXOPT) set drive $::env(DRIVE) -eval file copy -force ${cfg} {hdl/} +eval file copy -force ${cfg} {$outputDir/hdl/} eval file copy -force ${cfg} $outputDir -eval file copy -force [glob ${hdl_src}/../config/shared/*.vh] {hdl/} -eval file copy -force [glob ${hdl_src}/*/*.sv] {hdl/} -eval file copy -force [glob ${hdl_src}/*/flop/*.sv] {hdl/} +eval file copy -force [glob ${hdl_src}/../config/shared/*.vh] {$outputDir/hdl/} +eval file copy -force [glob ${hdl_src}/*/*.sv] {$outputDir/hdl/} +eval file copy -force [glob ${hdl_src}/*/flop/*.sv] {$outputDir/hdl/} # Only for FMA class project; comment out when done # eval file copy -force [glob ${hdl_src}/fma/fma16.v] {hdl/} @@ -41,7 +41,7 @@ if { $saifpower == 1 } { } # Verilog files -set my_verilog_files [glob hdl/*] +set my_verilog_files [glob $outputDir/hdl/*] # Set toplevel set my_toplevel $::env(DESIGN) @@ -56,7 +56,7 @@ set vhdlout_show_unconnected_pins "true" # Due to parameterized Verilog must use analyze/elaborate and not # read_verilog/vhdl (change to pull in Verilog and/or VHDL) # -define_design_lib WORK -path ./WORK +define_design_lib WORK -path ./$outputDir/WORK analyze -f sverilog -lib WORK $my_verilog_files elaborate $my_toplevel -lib WORK @@ -183,9 +183,9 @@ set_fix_multiple_port_nets -all -buffer_constants # group_path -name INPUTS -from [all_inputs] # group_path -name COMBO -from [all_inputs] -to [all_outputs] -# Save Unmapped Design -#set filename [format "%s%s%s%s" $outputDir "/unmapped/" $my_toplevel ".ddc"] -#write_file -format ddc -hierarchy -o $filename +Save Unmapped Design +set filename [format "%s%s%s%s" $outputDir "/unmapped/" $my_toplevel ".ddc"] +write_file -format ddc -hierarchy -o $filename # Compile statements if { $maxopt == 1 } { From 79b93e776ee01ff79da33768731b7537401e698f Mon Sep 17 00:00:00 2001 From: Madeleine Masser-Frye <51804758+mmasserfrye@users.noreply.github.com> Date: Fri, 8 Jul 2022 22:29:18 +0000 Subject: [PATCH 2/8] condensed cleanup, changed bpred_size to 4, moved synth hdl into own directory --- synthDC/Makefile | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/synthDC/Makefile b/synthDC/Makefile index 97cb1ca5..9db24230 100755 --- a/synthDC/Makefile +++ b/synthDC/Makefile @@ -66,18 +66,17 @@ copy: @$(foreach dir, $(DIRS), cp -r $(CONFIGDIR)/$(dir) $(CONFIGDIR)/$(dir)_orig;) @$(foreach dir, $(DIRS), sed -i 's/WAYSIZEINBYTES.*/WAYSIZEINBYTES 512/g' $(CONFIGDIR)/$(dir)_orig/wally-config.vh;) @$(foreach dir, $(DIRS), sed -i 's/NUMWAYS.*/NUMWAYS 1/g' $(CONFIGDIR)/$(dir)_orig/wally-config.vh;) - @$(foreach dir, $(DIRS), sed -i 's/BPRED_SIZE.*/BPRED_SIZE 5/g' $(CONFIGDIR)/$(dir)_orig/wally-config.vh;) + @$(foreach dir, $(DIRS), sed -i 's/BPRED_SIZE.*/BPRED_SIZE 4/g' $(CONFIGDIR)/$(dir)_orig/wally-config.vh;) @$(foreach dir, $(DIRS32), sed -i "s/RAM_RANGE.*/RAM_RANGE 34\'h01FF/g" $(CONFIGDIR)/$(dir)_orig/wally-config.vh ;) @$(foreach dir, $(DIRS64), sed -i "s/RAM_RANGE.*/RAM_RANGE 56\'h01FF/g" $(CONFIGDIR)/$(dir)_orig/wally-config.vh ;) - -del: - rm -rf $(CONFIGDIR)/*_* - configs: $(DIRS) $(DIRS): - #turn off FPU + # remove old config files + rm -rf $(CONFIGDIR)/*_* + + # turn off FPU rm -rf $(CONFIGDIR)/$@_FPUoff cp -r $(CONFIGDIR)/$@_orig $(CONFIGDIR)/$@_FPUoff sed -i 's/1 *<< *3/0 << 3/' $(CONFIGDIR)/$@_FPUoff/wally-config.vh @@ -93,12 +92,12 @@ $(DIRS): cp -r $(CONFIGDIR)/$@_FPUoff $(CONFIGDIR)/$@_PMP0 sed -i 's/PMP_ENTRIES \(64\|16\|0\)/PMP_ENTRIES 0/' $(CONFIGDIR)/$@_PMP0/wally-config.vh - #no muldiv + # no muldiv rm -rf $(CONFIGDIR)/$@_noMulDiv cp -r $(CONFIGDIR)/$@_PMP0 $(CONFIGDIR)/$@_noMulDiv sed -i 's/1 *<< *12/0 << 12/' $(CONFIGDIR)/$@_noMulDiv/wally-config.vh - #no priv + # no priv rm -rf $(CONFIGDIR)/$@_noPriv cp -r $(CONFIGDIR)/$@_noMulDiv $(CONFIGDIR)/$@_noPriv sed -i 's/ZICSR_SUPPORTED *1/ZICSR_SUPPORTED 0/' $(CONFIGDIR)/$@_noPriv/wally-config.vh @@ -111,13 +110,10 @@ allsynth: $(CONFIGFILESTRIM) $(CONFIGFILESTRIM): make synth DESIGN=wallypipelinedcore CONFIG=$@ TECH=sky90 FREQ=3000 MAXCORES=1 - synth: - rm -f hdl/* - rm -rf WORK @echo "DC Synthesis" - @mkdir -p hdl/ @mkdir -p $(OUTPUTDIR) + @mkdir -p $(OUTPUTDIR)/hdl @mkdir -p $(OUTPUTDIR)/reports @mkdir -p $(OUTPUTDIR)/mapped @mkdir -p $(OUTPUTDIR)/unmapped @@ -125,11 +121,11 @@ ifeq ($(SAIFPOWER), 1) cp -f ../pipelined/regression/power.saif . endif dc_shell-xg-t -64bit -f scripts/$(NAME).tcl | tee $(OUTPUTDIR)/$(NAME).out + rm -rf $(OUTPUTDIR)/hdl + rm -rf $(OUTPUTDIR)/WORK clean: -# fix should make del be here - rm -rf alib-52 WORK analyzed $(NAME).out - rm -f hdl/* + rm -rf alib-52 analyzed rm -f default.svf rm -f command.log rm -f filenames*.log @@ -137,6 +133,9 @@ clean: rm -f Synopsys_stack_trace_*.txt rm -f crte_*.txt +fresh: clean copy configs + @echo "synth directory cleaned and fresh config files written" + From a84aa365305c526925b72d279d9922a7f05c87a5 Mon Sep 17 00:00:00 2001 From: Madeleine Masser-Frye <51804758+mmasserfrye@users.noreply.github.com> Date: Fri, 8 Jul 2022 22:39:53 +0000 Subject: [PATCH 3/8] cleaned up old commands and commented --- synthDC/Makefile | 29 +++++++---------------------- 1 file changed, 7 insertions(+), 22 deletions(-) diff --git a/synthDC/Makefile b/synthDC/Makefile index 9db24230..205659dc 100755 --- a/synthDC/Makefile +++ b/synthDC/Makefile @@ -1,14 +1,15 @@ # -# Makefile for synthesis +# Makefile for synthesis # Shreya Sanghai (ssanghai@hmc.edu) 2/28/2022 +# Madeleine Masser-Frye (mmasserfrye@hmc.edu) 7/8/2022 NAME := synth # defaults export DESIGN ?= wallypipelinedcore export FREQ ?= 3000 export CONFIG ?= rv32e +# title to add a note in the synth's directory name TITLE = - # tsmc28, sky130, and sky90 presently supported export TECH ?= sky90 # MAXCORES allows parallel compilation, which is faster but less CPU-efficient @@ -28,13 +29,7 @@ CONFIGDIR ?= ${WALLY}/pipelined/config CONFIGFILES ?= $(shell find $(CONFIGDIR) -name rv*_*) CONFIGFILESTRIM = $(notdir $(CONFIGFILES)) # FREQS = 25 50 100 150 200 250 300 350 400 -k = 3 6 - -ifeq ($(TECH), sky130) - FREQS = 25 50 100 150 200 250 300 350 400 -else ifeq ($(TECH), sky90) - FREQS = 500 550 600 650 700 750 800 850 900 950 1000 -endif +# k = 3 6 print: @echo $(FREQS) @@ -42,14 +37,9 @@ print: default: - @echo "Basic synthesis procedure for Wally:" - @echo " Invoke with make synth" - -test: rv% - echo "Running test on $<" - -rv%.log: rv% - echo $< + @echo " Basic synthesis procedure for Wally:" + @echo " Invoke with make synth" + @echo "Use wallySynth.py to run a concurrent sweep " DIRS32 = rv32e rv32gc rv32ic @@ -105,11 +95,6 @@ $(DIRS): freqs: @$(foreach freq, $(FREQS), make synth DESIGN=wallypipelinedcore CONFIG=rv32e FREQ=$(freq) MAXCORES=1;) -allsynth: $(CONFIGFILESTRIM) - -$(CONFIGFILESTRIM): - make synth DESIGN=wallypipelinedcore CONFIG=$@ TECH=sky90 FREQ=3000 MAXCORES=1 - synth: @echo "DC Synthesis" @mkdir -p $(OUTPUTDIR) From 8dbb45519ed562d65cd3603709b48a84468d6e37 Mon Sep 17 00:00:00 2001 From: Madeleine Masser-Frye <51804758+mmasserfrye@users.noreply.github.com> Date: Fri, 8 Jul 2022 22:52:10 +0000 Subject: [PATCH 4/8] tweaks to run synth without error --- synthDC/Makefile | 11 ++++------- synthDC/scripts/synth.tcl | 6 +++--- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/synthDC/Makefile b/synthDC/Makefile index 205659dc..4b5898e0 100755 --- a/synthDC/Makefile +++ b/synthDC/Makefile @@ -52,6 +52,9 @@ DIRS = $(DIRS32) $(DIRS64) # @$(foreach kval, $(k), sed -i 's/BPRED_SIZE.*/BPRED_SIZE $(kval)/g' $(CONFIGDIR)/rv64gc_bpred_$(kval)/wally-config.vh;) # @$(foreach kval, $(k), make synth DESIGN=wallypipelinedcore CONFIG=rv64gc_bpred_$(kval) TECH=sky90 FREQ=500 MAXCORES=4 --jobs;) copy: + # remove old config files + rm -rf $(CONFIGDIR)/*_* + @$(foreach dir, $(DIRS), rm -rf $(CONFIGDIR)/$(dir)_orig;) @$(foreach dir, $(DIRS), cp -r $(CONFIGDIR)/$(dir) $(CONFIGDIR)/$(dir)_orig;) @$(foreach dir, $(DIRS), sed -i 's/WAYSIZEINBYTES.*/WAYSIZEINBYTES 512/g' $(CONFIGDIR)/$(dir)_orig/wally-config.vh;) @@ -63,9 +66,7 @@ copy: configs: $(DIRS) $(DIRS): - # remove old config files - rm -rf $(CONFIGDIR)/*_* - + # turn off FPU rm -rf $(CONFIGDIR)/$@_FPUoff cp -r $(CONFIGDIR)/$@_orig $(CONFIGDIR)/$@_FPUoff @@ -120,7 +121,3 @@ clean: fresh: clean copy configs @echo "synth directory cleaned and fresh config files written" - - - - diff --git a/synthDC/scripts/synth.tcl b/synthDC/scripts/synth.tcl index 2cea1241..40bab736 100755 --- a/synthDC/scripts/synth.tcl +++ b/synthDC/scripts/synth.tcl @@ -183,9 +183,9 @@ set_fix_multiple_port_nets -all -buffer_constants # group_path -name INPUTS -from [all_inputs] # group_path -name COMBO -from [all_inputs] -to [all_outputs] -Save Unmapped Design -set filename [format "%s%s%s%s" $outputDir "/unmapped/" $my_toplevel ".ddc"] -write_file -format ddc -hierarchy -o $filename +# Save Unmapped Design +# set filename [format "%s%s%s%s" $outputDir "/unmapped/" $my_toplevel ".ddc"] +# write_file -format ddc -hierarchy -o $filename # Compile statements if { $maxopt == 1 } { From 853a3a5df1acc2ba432d385f75ee7a3776983a86 Mon Sep 17 00:00:00 2001 From: Madeleine Masser-Frye <51804758+mmasserfrye@users.noreply.github.com> Date: Fri, 8 Jul 2022 22:52:53 +0000 Subject: [PATCH 5/8] remove outdated scripts --- synthDC/scripts/extractSummary.py | 64 ---------------------------- synthDC/scripts/runConfigsSynth.sh | 9 ---- synthDC/scripts/runFrequencySynth.sh | 7 --- 3 files changed, 80 deletions(-) delete mode 100755 synthDC/scripts/extractSummary.py delete mode 100755 synthDC/scripts/runConfigsSynth.sh delete mode 100755 synthDC/scripts/runFrequencySynth.sh diff --git a/synthDC/scripts/extractSummary.py b/synthDC/scripts/extractSummary.py deleted file mode 100755 index add95068..00000000 --- a/synthDC/scripts/extractSummary.py +++ /dev/null @@ -1,64 +0,0 @@ -#!/usr/bin/python3 -# Shreya Sanghai (ssanghai@hmc.edu) 2/28/2022 -import glob -import re -import csv -import linecache -import os - -# field_names = [ 'Name', 'Critical Path Length', 'Cell Area', 'Synth Time'] -# data = [] -# for name in glob.glob("/home/ssanghai/riscv-wally/synthDC/runs/*/reports/wallypipelinedcore_qor.rep"): -# f = open(name, 'r') -# # trimName = re.search("runs\/(.*?)\/reports", name).group(1) -# trimName = re.search("wallypipelinedcore_(.*?)_sky9",name).group(1) -# for line in f: -# if "Critical Path Length" in line: -# pathLen = re.search("Length: *(.*?)\\n", line).group(1) -# if "Cell Area" in line: -# area = re.search("Area: *(.*?)\\n", line).group(1) -# if "Overall Compile Time" in line: -# time = re.search("Time: *(.*?)\\n", line).group(1) -# data += [{'Name' : trimName, 'Critical Path Length': pathLen, 'Cell Area' : area, 'Synth Time' :time}] - -def main(): - data = [] - curr_dir = os.path.dirname(os.path.abspath(__file__)) - output_file = os.path.join(curr_dir,"..","Summary.csv") - runs_dir = os.path.join(curr_dir,"..","runs/*/reports/wallypipelinedcore_qor.rep") - # cruns_dir = "/home/ssanghai/Desktop/cleanRun/*/reports/wallypipelinedcore_qor.rep" - search_strings = [ - "Critical Path Length:", "Cell Area:", "Overall Compile Time:", - "Critical Path Clk Period:", "Critical Path Slack:" - ] - for name in glob.glob(runs_dir): - f = open(name, 'r') - trimName = re.search("wallypipelinedcore_(.*?)_sky",name).group(1) - - output = {'Name':trimName} - num_lines = len(f.readlines()) - curr_line_index = 0 - - while curr_line_index < num_lines: - line = linecache.getline(name, curr_line_index) - for search_string in search_strings: - if search_string in line: - val = getVal(name,search_string,line,curr_line_index) - output[search_string] = val - curr_line_index +=1 - data += [output] - - with open(output_file, 'w') as csvfile: - writer = csv.DictWriter(csvfile, fieldnames=['Name'] + search_strings) - writer.writeheader() - writer.writerows(data) - -def getVal(filename, search_string, line, line_index): - data = re.search(f"{search_string} *(.*?)\\n", line).group(1) - if data == '': #sometimes data is stored in two line - data = linecache.getline(filename, line_index+1).strip() - return data - -if __name__=="__main__": - main() - \ No newline at end of file diff --git a/synthDC/scripts/runConfigsSynth.sh b/synthDC/scripts/runConfigsSynth.sh deleted file mode 100755 index 84e1f6d7..00000000 --- a/synthDC/scripts/runConfigsSynth.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/bash -# rm -r runs/* -make clean -make del -make copy -make configs -make allsynth -scripts/extractSummary.py -make del \ No newline at end of file diff --git a/synthDC/scripts/runFrequencySynth.sh b/synthDC/scripts/runFrequencySynth.sh deleted file mode 100755 index 5aa99899..00000000 --- a/synthDC/scripts/runFrequencySynth.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/bash -# rm -r runs/* -make clean -make del -make freqs TECH=$1 -scripts/extractSummary.py -make del From 19db618b7fc916efa3782d57be609886f1d35da4 Mon Sep 17 00:00:00 2001 From: Madeleine Masser-Frye <51804758+mmasserfrye@users.noreply.github.com> Date: Sat, 9 Jul 2022 02:40:41 +0000 Subject: [PATCH 6/8] syntheses now write alib in their own directories --- synthDC/Makefile | 2 +- synthDC/scripts/synth.tcl | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/synthDC/Makefile b/synthDC/Makefile index 4b5898e0..2aaa3f39 100755 --- a/synthDC/Makefile +++ b/synthDC/Makefile @@ -109,9 +109,9 @@ endif dc_shell-xg-t -64bit -f scripts/$(NAME).tcl | tee $(OUTPUTDIR)/$(NAME).out rm -rf $(OUTPUTDIR)/hdl rm -rf $(OUTPUTDIR)/WORK + rm -rf $(OUTPUTDIR)/alib-52 clean: - rm -rf alib-52 analyzed rm -f default.svf rm -f command.log rm -f filenames*.log diff --git a/synthDC/scripts/synth.tcl b/synthDC/scripts/synth.tcl index 40bab736..9f2b4647 100755 --- a/synthDC/scripts/synth.tcl +++ b/synthDC/scripts/synth.tcl @@ -56,6 +56,7 @@ set vhdlout_show_unconnected_pins "true" # Due to parameterized Verilog must use analyze/elaborate and not # read_verilog/vhdl (change to pull in Verilog and/or VHDL) # +set alib_library_analysis_path ./$outputDir define_design_lib WORK -path ./$outputDir/WORK analyze -f sverilog -lib WORK $my_verilog_files elaborate $my_toplevel -lib WORK From b196b6b504f46261f2ce0dac76563dfbc15da819 Mon Sep 17 00:00:00 2001 From: Madeleine Masser-Frye <51804758+mmasserfrye@users.noreply.github.com> Date: Sat, 9 Jul 2022 03:24:47 +0000 Subject: [PATCH 7/8] explanations and modifications for general ppa use --- synthDC/ppa/README | 32 ++++++++++++++++++ synthDC/ppa/ppaAnalyze.py | 48 ++++++++++++++++++++------- synthDC/ppa/ppaSynth.py | 69 ++++++++++++++++++++++++--------------- 3 files changed, 112 insertions(+), 37 deletions(-) create mode 100644 synthDC/ppa/README diff --git a/synthDC/ppa/README b/synthDC/ppa/README new file mode 100644 index 00000000..2bdf2eda --- /dev/null +++ b/synthDC/ppa/README @@ -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. diff --git a/synthDC/ppa/ppaAnalyze.py b/synthDC/ppa/ppaAnalyze.py index 9e2d3640..2dce62ae 100755 --- a/synthDC/ppa/ppaAnalyze.py +++ b/synthDC/ppa/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') \ No newline at end of file diff --git a/synthDC/ppa/ppaSynth.py b/synthDC/ppa/ppaSynth.py index 842140b5..cbfd5253 100755 --- a/synthDC/ppa/ppaSynth.py +++ b/synthDC/ppa/ppaSynth.py @@ -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) \ No newline at end of file + pool.starmap(print, synthsToRun) \ No newline at end of file From 0dc3c9462bf011b773dd20bb1653e1e208aff9cd Mon Sep 17 00:00:00 2001 From: Madeleine Masser-Frye <51804758+mmasserfrye@users.noreply.github.com> Date: Sat, 9 Jul 2022 04:51:23 +0000 Subject: [PATCH 8/8] improved command line synth functionality --- synthDC/Makefile | 2 +- synthDC/extractSummary.py | 135 ++++++++++++++++++++++---------------- synthDC/wallySynth.py | 2 +- 3 files changed, 82 insertions(+), 57 deletions(-) diff --git a/synthDC/Makefile b/synthDC/Makefile index 2aaa3f39..369529e3 100755 --- a/synthDC/Makefile +++ b/synthDC/Makefile @@ -22,7 +22,7 @@ export DRIVE ?= FLOP time := $(shell date +%F-%H-%M) hash := $(shell git rev-parse --short HEAD) -export OUTPUTDIR := newRuns/$(DESIGN)_$(CONFIG)_$(TECH)nm_$(FREQ)_MHz_$(time)_$(TITLE)_$(hash) +export OUTPUTDIR := runs/$(DESIGN)_$(CONFIG)_$(TECH)nm_$(FREQ)_MHz_$(time)_$(TITLE)_$(hash) export SAIFPOWER ?= 0 CONFIGDIR ?= ${WALLY}/pipelined/config diff --git a/synthDC/extractSummary.py b/synthDC/extractSummary.py index 71e21cfe..93363a06 100755 --- a/synthDC/extractSummary.py +++ b/synthDC/extractSummary.py @@ -7,10 +7,10 @@ import subprocess from matplotlib.cbook import flatten import matplotlib.pyplot as plt import matplotlib.lines as lines -from wallySynth import testFreq import numpy as np from ppa.ppaAnalyze import noOutliers from matplotlib import ticker +import argparse def synthsintocsv(): @@ -74,14 +74,13 @@ def synthsfromcsv(filename): allSynths[i] = Synth(*allSynths[i]) return allSynths - def freqPlot(tech, width, config): ''' plots delay, area for syntheses with specified tech, module, width ''' freqsL, delaysL, areasL = ([[], []] for i in range(3)) for oneSynth in allSynths: - if (width == oneSynth.width) & (config == oneSynth.config) & (tech == oneSynth.tech) & (oneSynth.special == ''): + if (width == oneSynth.width) & (config == oneSynth.config) & (tech == oneSynth.tech) & ('' == oneSynth.special): ind = (1000/oneSynth.delay < oneSynth.freq) # when delay is within target clock period freqsL[ind] += [oneSynth.freq] delaysL[ind] += [oneSynth.delay] @@ -124,74 +123,93 @@ def freqPlot(tech, width, config): addFO4axis(fig, ax1, tech) plt.savefig('./plots/wally/freqSweep_' + tech + '_' + width + config + '.png') - # plt.show() +def areaDelay(tech, delays, areas, labels, fig, ax, norm=False): -def areaDelay(tech, fig=None, ax=None, freq=None, width=None, config=None, norm=False): - delays, areas, labels = ([] for i in range(3)) + plt.subplots_adjust(left=0.18) - for oneSynth in allSynths: - if (width==None) or (width == oneSynth.width): - if (tech == oneSynth.tech) & (freq == oneSynth.freq): - if (config == None) & (oneSynth.special == 'FPUoff'): #fix - delays += [oneSynth.delay] - areas += [oneSynth.area] - labels += [oneSynth.width + oneSynth.config] - elif (config != None) & (oneSynth.config == config): - delays += [oneSynth.delay] - areas += [oneSynth.area] - labels += [oneSynth.special] - if width == None: - width = '' - if (fig == None) or (ax == None): - fig, (ax) = plt.subplots(1, 1) - ax.ticklabel_format(useOffset=False, style='plain') - plt.subplots_adjust(left=0.18) + fo4 = techdict[tech].fo4 + add32area = techdict[tech].add32area + marker = techdict[tech].shape + color = techdict[tech].color if norm: - delays = [d/techdict[tech][0] for d in delays] - areas = [a/techdict[tech][1] for a in areas] + delays = [d/fo4 for d in delays] + areas = [a/add32area for a in areas] - plt.scatter(delays, areas) + plt.scatter(delays, areas, marker=marker, color=color) plt.xlabel('Cycle time (ns)') plt.ylabel('Area (sq microns)') ytop = ax.get_ylim()[1] plt.ylim(ymin=0, ymax=1.1*ytop) - titleStr = tech + ' ' + width - saveStr = tech + '_' + width - if config: - titleStr += config - saveStr = saveStr + config + '_versions_' - if (config == None): - saveStr = saveStr + '_origConfigs_' - saveStr += str(freq) - titleStr = titleStr - plt.title(titleStr) ax.yaxis.set_major_formatter(ticker.StrMethodFormatter('{x:,.0f}')) for i in range(len(labels)): plt.annotate(labels[i], (delays[i], areas[i]), textcoords="offset points", xytext=(0,10), ha='center') - # addFO4axis(fig, ax1, tech) - - plt.savefig('./plots/wally/areaDelay_' + saveStr + '.png') + return fig + +def plotFeatures(tech, width, config): + delays, areas, labels = ([] for i in range(3)) + freq = techdict[tech].targfreq + for oneSynth in allSynths: + if (tech == oneSynth.tech) & (freq == oneSynth.freq): + if (oneSynth.config == config) & (width == oneSynth.width): + delays += [oneSynth.delay] + areas += [oneSynth.area] + labels += [oneSynth.special] + + fig, (ax) = plt.subplots(1, 1) + + fig = areaDelay(tech, delays, areas, labels, fig, ax) + + titlestr = tech+'_'+width+config + plt.title(titlestr) + plt.savefig('./plots/wally/features_'+titlestr+'.png') + +def plotConfigs(tech, special=''): + delays, areas, labels = ([] for i in range(3)) + freq = techdict[tech].targfreq + for oneSynth in allSynths: + if (tech == oneSynth.tech) & (freq == oneSynth.freq) & (oneSynth.special == special): + delays += [oneSynth.delay] + areas += [oneSynth.area] + labels += [oneSynth.width + oneSynth.config] + + fig, (ax) = plt.subplots(1, 1) + + fig = areaDelay(tech, delays, areas, labels, fig, ax) + + titleStr = tech+'_'+special + plt.title(titleStr) + plt.savefig('./plots/wally/configs_' + titleStr + '.png') + + +def normAreaDelay(special=''): + fig, (ax) = plt.subplots(1, 1) + fullLeg = [] + for tech in list(techdict.keys()): + delays, areas, labels = ([] for i in range(3)) + spec = techdict[tech] + freq = spec.targfreq + for oneSynth in allSynths: + if (tech == oneSynth.tech) & (freq == oneSynth.freq) & (oneSynth.special == special): + delays += [oneSynth.delay] + areas += [oneSynth.area] + labels += [oneSynth.width + oneSynth.config] + areaDelay(tech, delays, areas, labels, fig, ax, norm=True) + fullLeg += [lines.Line2D([0], [0], markerfacecolor=spec.color, label=tech, marker=spec.shape, markersize=10, color='w')] -def normAreaDelay(): - fig2, (ax) = plt.subplots(1, 1) - areaDelay('sky90', fig=fig2, ax=ax, freq=testFreq[0], norm=True) - areaDelay('tsmc28', fig=fig2, ax=ax, freq=testFreq[1], norm=True) ax.set_title('Normalized Area & Cycle Time by Configuration') ax.set_xlabel('Cycle Time (FO4)') - ax.set_ylabel('Area (add32)') - fullLeg = [lines.Line2D([0], [0], color='royalblue', label='tsmc28')] - fullLeg += [lines.Line2D([0], [0], color='orange', label='sky90')] + ax.set_ylabel('Area (add32)') ax.legend(handles = fullLeg, loc='upper left') plt.savefig('./plots/wally/normAreaDelay.png') def addFO4axis(fig, ax, tech): - fo4 = techdict[tech][0] + fo4 = techdict[tech].fo4 ax3 = fig.add_axes((0.125,0.14,0.775,0.0)) ax3.yaxis.set_visible(False) # hide the yaxis @@ -215,15 +233,22 @@ def addFO4axis(fig, ax, tech): if __name__ == '__main__': - techdict = {'sky90': [43.2e-3, 1440.600027], 'tsmc28': [12.2e-3, 209.286002]} + parser = argparse.ArgumentParser() + parser.add_argument("-s", "--skyfreq", type=int, default=3000, help = "Target frequency used for sky90 syntheses") + parser.add_argument("-t", "--tsmcfreq", type=int, default=10000, help = "Target frequency used for tsmc28 syntheses") + args = parser.parse_args() - # synthsintocsv() + TechSpec = namedtuple("TechSpec", "color shape targfreq fo4 add32area add32lpower add32denergy") + techdict = {} + techdict['sky90'] = TechSpec('green', 'o', args.skyfreq, 43.2e-3, 1440.600027, 714.057, 0.658023) + techdict['tsmc28'] = TechSpec('blue', 's', args.tsmcfreq, 12.2e-3, 209.286002, 1060.0, .081533) + + synthsintocsv() synthsfromcsv('Summary.csv') freqPlot('tsmc28', 'rv32', 'e') freqPlot('sky90', 'rv32', 'e') - areaDelay('tsmc28', freq=testFreq[1], width= 'rv64', config='gc') - areaDelay('sky90', freq=testFreq[0], width='rv64', config='gc') - areaDelay('tsmc28', freq=testFreq[1]) - areaDelay('sky90', freq=testFreq[0]) - - # normAreaDelay() + plotFeatures('sky90', 'rv64', 'gc') + plotFeatures('tsmc28', 'rv64', 'gc') + plotConfigs('sky90', special='orig') + plotConfigs('tsmc28', special='orig') + normAreaDelay(special='orig') diff --git a/synthDC/wallySynth.py b/synthDC/wallySynth.py index 6c82b43c..0c157981 100755 --- a/synthDC/wallySynth.py +++ b/synthDC/wallySynth.py @@ -14,7 +14,7 @@ def mask(command): subprocess.Popen(command, shell=True) def freshStart(): - out = subprocess.check_output(['bash','-c', 'make clean']) + out = subprocess.check_output(['bash','-c', 'make fresh']) for x in out.decode("utf-8").split('\n')[:-1]: print(x) return