From a1fe71fad813139cf1685b6386583fc0231e5b3e Mon Sep 17 00:00:00 2001 From: David Ratchkov Date: Fri, 17 Apr 2020 19:47:54 -0700 Subject: [PATCH 1/8] Remove file from tracking --- .gitignore | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 .gitignore diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 3d6e4f927..000000000 --- a/.gitignore +++ /dev/null @@ -1,12 +0,0 @@ -.DS_Store -*~ -*.orig -*.rej -*.pyc -*.aux -*.out -*.toc -*.synctex.gz -**/model_data -outputs -technology/freepdk45/ncsu_basekit From 169933f3ccc52b57dae7fea01434f825b789bc07 Mon Sep 17 00:00:00 2001 From: David Ratchkov Date: Mon, 20 Apr 2020 13:36:47 -0700 Subject: [PATCH 2/8] Fix voltage_map names (these do not need to match pg_pin names) --- compiler/characterizer/lib.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/characterizer/lib.py b/compiler/characterizer/lib.py index 276ea767c..e6befc2b0 100644 --- a/compiler/characterizer/lib.py +++ b/compiler/characterizer/lib.py @@ -243,8 +243,8 @@ def write_defaults(self): self.lib.write(" default_max_fanout : 4.0 ;\n") self.lib.write(" default_connection_class : universal ;\n\n") - self.lib.write(" voltage_map ( vdd, {} );\n".format(tech.spice["nom_supply_voltage"])) - self.lib.write(" voltage_map ( gnd, 0 );\n\n") + self.lib.write(" voltage_map ( VDD, {} );\n".format(tech.spice["nom_supply_voltage"])) + self.lib.write(" voltage_map ( GND, 0 );\n\n") def create_list(self,values): """ Helper function to create quoted, line wrapped list """ From 36ac2225012382b61a7c0d06a1b16535a8b5d49f Mon Sep 17 00:00:00 2001 From: David Ratchkov Date: Sun, 7 Jun 2020 20:10:44 -0700 Subject: [PATCH 3/8] Subtract leakage from total power measurement. Leakage is power for the last 2% of the period. --- compiler/characterizer/delay.py | 2 +- compiler/characterizer/stimuli.py | 23 +++++++++++++++++------ 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index 62367d726..b2173972e 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -641,7 +641,7 @@ def write_power_measures(self): t_final = 2*self.period self.stim.gen_meas_power(meas_name="leakage_power", t_initial=t_initial, - t_final=t_final) + t_final=t_final, leakage=True) def find_feasible_period_one_port(self, port): """ diff --git a/compiler/characterizer/stimuli.py b/compiler/characterizer/stimuli.py index b5a143cfb..f6cc6592b 100644 --- a/compiler/characterizer/stimuli.py +++ b/compiler/characterizer/stimuli.py @@ -192,18 +192,29 @@ def gen_meas_find_voltage_at_time(self, meas_name, targ_name, time_at): targ_name, time_at)) - def gen_meas_power(self, meas_name, t_initial, t_final): + def gen_meas_power(self, meas_name, t_initial, t_final, leakage=False): """ Creates the .meas statement for the measurement of avg power """ # power mea cmd is different in different spice: if OPTS.spice_name == "hspice": power_exp = "power" else: power_exp = "par('(-1*v(" + str(self.vdd_name) + ")*I(v" + str(self.vdd_name) + "))')" - self.sf.write(".meas tran {0} avg {1} from={2}n to={3}n\n\n".format(meas_name, - power_exp, - t_initial, - t_final)) - + if leakage: + self.sf.write(".meas tran {0} avg {1} from={2}n to={3}n\n".format(meas_name, + power_exp, + t_initial, + t_final)) + else: + self.sf.write(".meas tran {0}_total avg {1} from={2}n to={3}n\n".format(meas_name, + power_exp, + t_initial, + t_final)) + self.sf.write(".meas tran {0}_leakage avg {1} from={2}n to={3}n\n".format(meas_name, + power_exp, + t_final-0.02*(t_final-t_initial), + t_final)) + self.sf.write(".meas tran {0} param='{0}_total - 50.0 * {0}_leakage'\n\n".format(meas_name)) + def gen_meas_value(self, meas_name, dout, t_intital, t_final): measure_string=".meas tran {0} AVG v({1}) FROM={2}n TO={3}n\n\n".format(meas_name, dout, t_intital, t_final) self.sf.write(measure_string) From c880430d866e33807be757ec12e97c3024506a18 Mon Sep 17 00:00:00 2001 From: David Ratchkov Date: Tue, 30 Jun 2020 16:39:51 -0700 Subject: [PATCH 4/8] alps changes --- compiler/characterizer/stimuli.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/compiler/characterizer/stimuli.py b/compiler/characterizer/stimuli.py index 58a9e3edc..1c43406c2 100644 --- a/compiler/characterizer/stimuli.py +++ b/compiler/characterizer/stimuli.py @@ -227,6 +227,8 @@ def write_control(self, end_time, runlvl=4): # Do not remove this or it may not converge due to some "pa_00" nodes # unless you figure out what these are. self.sf.write(".OPTIONS POST=1 RELTOL={0} PROBE method=gear\n".format(reltol)) + elif OPTS.spice_name == "alps": + self.sf.write(".OPTIONS POST=0 RUNLVL={0} RELTOL={1} PROBE ABSTOL=1e-6 LEAST_DISK_SPACE=2000\n".format(runlvl, reltol)) else: self.sf.write(".OPTIONS POST=1 RUNLVL={0} PROBE\n".format(runlvl)) @@ -288,6 +290,12 @@ def run_sim(self): temp_stim, OPTS.openram_temp) valid_retcode=0 + elif OPTS.spice_name == "alps": + # TODO: Should make multithreading parameter a configuration option + cmd = "{0} -mode pro -mt 2 -lqtimeout 0 -i {1} -o {2}timing".format(OPTS.spice_exe, + temp_stim, + OPTS.openram_temp) + valid_retcode=0 else: # ngspice 27+ supports threading with "set num_threads=4" in the stimulus file or a .spiceinit cmd = "{0} -b -o {2}timing.lis {1}".format(OPTS.spice_exe, From bf3b501dbe5c85b7018a58032f4df5427cdf48d8 Mon Sep 17 00:00:00 2001 From: David Ratchkov Date: Mon, 13 Jul 2020 12:39:57 -0700 Subject: [PATCH 5/8] Fix bus ordering in Liberty --- compiler/characterizer/lib.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/compiler/characterizer/lib.py b/compiler/characterizer/lib.py index e6befc2b0..227e3e98d 100644 --- a/compiler/characterizer/lib.py +++ b/compiler/characterizer/lib.py @@ -325,16 +325,18 @@ def write_bus(self): self.lib.write(" base_type : array;\n") self.lib.write(" data_type : bit;\n") self.lib.write(" bit_width : {0};\n".format(self.sram.word_size)) - self.lib.write(" bit_from : 0;\n") - self.lib.write(" bit_to : {0};\n".format(self.sram.word_size - 1)) + self.lib.write(" bit_from : {0};\n".format(self.sram.word_size - 1)) + self.lib.write(" bit_to : 0;\n") + self.lib.write(" downto : true;\n") self.lib.write(" }\n\n") self.lib.write(" type (addr){\n") self.lib.write(" base_type : array;\n") self.lib.write(" data_type : bit;\n") self.lib.write(" bit_width : {0};\n".format(self.sram.addr_size)) - self.lib.write(" bit_from : 0;\n") - self.lib.write(" bit_to : {0};\n".format(self.sram.addr_size - 1)) + self.lib.write(" bit_from : {0};\n".format(self.sram.addr_size - 1)) + self.lib.write(" bit_to : 0;\n") + self.lib.write(" downto : true;\n") self.lib.write(" }\n\n") if self.sram.write_size: @@ -342,8 +344,9 @@ def write_bus(self): self.lib.write(" base_type : array;\n") self.lib.write(" data_type : bit;\n") self.lib.write(" bit_width : {0};\n".format(self.sram.num_wmasks)) - self.lib.write(" bit_from : 0;\n") - self.lib.write(" bit_to : {0};\n".format(self.sram.num_wmasks - 1)) + self.lib.write(" bit_from : {0};\n".format(self.sram.num_wmasks - 1)) + self.lib.write(" bit_to : 0;\n") + self.lib.write(" downto : true;\n") self.lib.write(" }\n\n") From 9414eeff332d8a299fafd6ba599c00a534758cc3 Mon Sep 17 00:00:00 2001 From: David Ratchkov Date: Mon, 27 Jul 2020 12:10:18 -0700 Subject: [PATCH 6/8] Added support for Empyrean's ALPS Added num_threads option to pass to simulators taht support multi-threading --- compiler/characterizer/__init__.py | 2 +- compiler/characterizer/charutils.py | 3 +++ compiler/characterizer/stimuli.py | 6 ++++-- compiler/globals.py | 6 +++++- compiler/options.py | 3 +++ 5 files changed, 16 insertions(+), 4 deletions(-) diff --git a/compiler/characterizer/__init__.py b/compiler/characterizer/__init__.py index 93dd5bcb5..9ceefde66 100644 --- a/compiler/characterizer/__init__.py +++ b/compiler/characterizer/__init__.py @@ -28,7 +28,7 @@ if OPTS.spice_exe=="" or OPTS.spice_exe==None: debug.error("{0} not found. Unable to perform characterization.".format(OPTS.spice_name),1) else: - (OPTS.spice_name,OPTS.spice_exe) = get_tool("spice",["hspice", "ngspice", "ngspice.exe", "xa"]) + (OPTS.spice_name,OPTS.spice_exe) = get_tool("spice",["hspice", "ngspice", "ngspice.exe", "xa", "alps"]) # set the input dir for spice files if using ngspice if OPTS.spice_name == "ngspice": diff --git a/compiler/characterizer/charutils.py b/compiler/characterizer/charutils.py index fa49b1ed9..a0ca63a6a 100644 --- a/compiler/characterizer/charutils.py +++ b/compiler/characterizer/charutils.py @@ -20,6 +20,9 @@ def parse_spice_list(filename, key): if OPTS.spice_name == "xa" : # customsim has a different output file name full_filename="{0}xa.meas".format(OPTS.openram_temp) + elif OPTS.spice_name == "alps": + # alps using a .measure + full_filename="{0}{1}.measure".format(OPTS.openram_temp, filename) else: # ngspice/hspice using a .lis file full_filename="{0}{1}.lis".format(OPTS.openram_temp, filename) diff --git a/compiler/characterizer/stimuli.py b/compiler/characterizer/stimuli.py index 53812384f..8a4b055ee 100644 --- a/compiler/characterizer/stimuli.py +++ b/compiler/characterizer/stimuli.py @@ -299,13 +299,15 @@ def run_sim(self): valid_retcode=0 elif OPTS.spice_name == "hspice": # TODO: Should make multithreading parameter a configuration option - cmd = "{0} -mt 2 -i {1} -o {2}timing".format(OPTS.spice_exe, + cmd = "{0} -mt {1} -i {2} -o {3}timing".format(OPTS.spice_exe, + OPTS.num_threads, temp_stim, OPTS.openram_temp) valid_retcode=0 elif OPTS.spice_name == "alps": # TODO: Should make multithreading parameter a configuration option - cmd = "{0} -mode pro -mt 2 -lqtimeout 0 -i {1} -o {2}timing".format(OPTS.spice_exe, + cmd = "{0} -mt {1} -i {2} -o {3}timing".format(OPTS.spice_exe, + OPTS.num_threads, temp_stim, OPTS.openram_temp) valid_retcode=0 diff --git a/compiler/globals.py b/compiler/globals.py index dd4ac1779..342b5fd19 100644 --- a/compiler/globals.py +++ b/compiler/globals.py @@ -82,7 +82,11 @@ def parse_args(): "--dontpurge", action="store_false", dest="purge_temp", - help="Don't purge the contents of the temp directory after a successful run") + help="Don't purge the contents of the temp directory after a successful run"), + optparse.make_option( + "--num_threads", + dest="num_threads", + help="Number of threads used by simulator. Default is 2") # -h --help is implicit. } diff --git a/compiler/options.py b/compiler/options.py index d97ea3009..26c18960d 100644 --- a/compiler/options.py +++ b/compiler/options.py @@ -102,6 +102,9 @@ class options(optparse.Values): spice_name = "" # The spice executable being used which is derived from the user PATH. spice_exe = "" + + # Thread number for hspice and alps + num_threads = 2 # Variable to select the variant of drc, lvs, pex drc_name = "" lvs_name = "" From 3f26f3f17368167271b476d13ea64d2bb43d170e Mon Sep 17 00:00:00 2001 From: David Ratchkov Date: Tue, 28 Jul 2020 17:33:59 -0700 Subject: [PATCH 7/8] Fix leakage subtraction Use POST=0 if purge_temp is True, else POST=1 --- compiler/characterizer/stimuli.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/characterizer/stimuli.py b/compiler/characterizer/stimuli.py index 5be560c4c..65f73c3bf 100644 --- a/compiler/characterizer/stimuli.py +++ b/compiler/characterizer/stimuli.py @@ -213,7 +213,7 @@ def gen_meas_power(self, meas_name, t_initial, t_final, leakage=False): power_exp, t_final-0.02*(t_final-t_initial), t_final)) - self.sf.write(".meas tran {0} param='{0}_total - 50.0 * {0}_leakage'\n\n".format(meas_name)) + self.sf.write(".meas tran {0} param='{0}_total - {0}_leakage'\n\n".format(meas_name)) def gen_meas_value(self, meas_name, dout, t_intital, t_final): measure_string=".meas tran {0} AVG v({1}) FROM={2}n TO={3}n\n\n".format(meas_name, dout, t_intital, t_final) @@ -241,11 +241,11 @@ def write_control(self, end_time, runlvl=4): # which is more accurate, but slower than the default trapezoid method # Do not remove this or it may not converge due to some "pa_00" nodes # unless you figure out what these are. - self.sf.write(".OPTIONS POST=1 RELTOL={0} PROBE method=gear\n".format(reltol)) + self.sf.write(".OPTIONS POST={1} RELTOL={0} PROBE method=gear\n".format(reltol, 0 if OPTS.purge_temp else 1)) elif OPTS.spice_name == "alps": - self.sf.write(".OPTIONS POST=0 RUNLVL={0} RELTOL={1} PROBE ABSTOL=1e-6 LEAST_DISK_SPACE=2000\n".format(runlvl, reltol)) + self.sf.write(".OPTIONS POST={2} RUNLVL={0} RELTOL={1} PROBE LEAST_DISK_SPACE=2000\n".format(runlvl, reltol, 0 if OPTS.purge_temp else 1)) else: - self.sf.write(".OPTIONS POST=1 RUNLVL={0} PROBE\n".format(runlvl)) + self.sf.write(".OPTIONS POST={1} RUNLVL={0} PROBE\n".format(runlvl, 0 if OPTS.purge_temp else 1)) # create plots for all signals self.sf.write("* probe is used for hspice/xa, while plot is used in ngspice\n") From f17ae837ff8ef79c2c25733ee66f39e86338877a Mon Sep 17 00:00:00 2001 From: David Ratchkov Date: Mon, 21 Sep 2020 10:18:38 -0700 Subject: [PATCH 8/8] Move power measurements earlier by slew/2+0.05*period, to match when the times when input pins are toggled --- compiler/characterizer/delay.py | 4 ++-- compiler/characterizer/stimuli.py | 2 +- requirements.txt | 2 ++ 3 files changed, 5 insertions(+), 3 deletions(-) create mode 100644 requirements.txt diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index bb50b8460..847e1c35a 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -581,8 +581,8 @@ def get_power_measure_variants(self, port, power_obj, operation): """Get the measurement values that can either vary port to port (time delays)""" # Return value is intended to match the power measure format: t_initial, t_final, port - t_initial = self.cycle_times[self.measure_cycles[port][power_obj.meta_str]] - t_final = self.cycle_times[self.measure_cycles[port][power_obj.meta_str]+1] + t_initial = self.cycle_times[self.measure_cycles[port][power_obj.meta_str]]-self.slew/2-self.period*0.05 + t_final = self.cycle_times[self.measure_cycles[port][power_obj.meta_str]+1]-self.slew/2-self.period*0.05 return (t_initial, t_final, port) diff --git a/compiler/characterizer/stimuli.py b/compiler/characterizer/stimuli.py index 65f73c3bf..915a4071d 100644 --- a/compiler/characterizer/stimuli.py +++ b/compiler/characterizer/stimuli.py @@ -211,7 +211,7 @@ def gen_meas_power(self, meas_name, t_initial, t_final, leakage=False): t_final)) self.sf.write(".meas tran {0}_leakage avg {1} from={2}n to={3}n\n".format(meas_name, power_exp, - t_final-0.02*(t_final-t_initial), + t_final-0.05*(t_final-t_initial), t_final)) self.sf.write(".meas tran {0} param='{0}_total - {0}_leakage'\n\n".format(meas_name)) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 000000000..6bad10388 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +numpy +scipy