From 75bd2b46a548b888eeade14fdfa27895ab337e2f Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Thu, 9 Apr 2020 10:02:15 -0700 Subject: [PATCH 1/6] OpenRAM v1.1.5 --- compiler/globals.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/globals.py b/compiler/globals.py index 3277ab1d..dbb1f962 100644 --- a/compiler/globals.py +++ b/compiler/globals.py @@ -19,7 +19,7 @@ import re import copy import importlib -VERSION = "1.1.4" +VERSION = "1.1.5" NAME = "OpenRAM v{}".format(VERSION) USAGE = "openram.py [options] \nUse -h for help.\n" From 7e36cd482855bfa5408ea0fb794be107adb6ada8 Mon Sep 17 00:00:00 2001 From: David Ratchkov Date: Fri, 17 Apr 2020 13:45:57 -0700 Subject: [PATCH 2/6] - Write voltage_map and pg_pin - Remove 'when' condition on leakage power - Remove 'clk*' from 'when' condition on internal_power on the same 'clk*' pin --- compiler/characterizer/lib.py | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/compiler/characterizer/lib.py b/compiler/characterizer/lib.py index 1e68fc2e..b0668ddc 100644 --- a/compiler/characterizer/lib.py +++ b/compiler/characterizer/lib.py @@ -181,17 +181,20 @@ class lib: self.lib.write(" dont_touch : true;\n") self.lib.write(" area : {};\n\n".format(self.sram.width * self.sram.height)) - #Build string of all control signals. + self.write_pg_pin() + + #Build string of all control signals. control_str = 'csb0' #assume at least 1 port for i in range(1, self.total_port_num): control_str += ' & csb{0}'.format(i) # Leakage is included in dynamic when macro is enabled self.lib.write(" leakage_power () {\n") - self.lib.write(" when : \"{0}\";\n".format(control_str)) + # 'when' condition unnecessary when cs pin does not turn power to devices + # self.lib.write(" when : \"{0}\";\n".format(control_str)) self.lib.write(" value : {};\n".format(self.char_sram_results["leakage_power"])) self.lib.write(" }\n") - self.lib.write(" cell_leakage_power : {};\n".format(0)) + self.lib.write(" cell_leakage_power : {};\n".format(self.char_sram_results["leakage_power"])) def write_units(self): @@ -240,6 +243,9 @@ class lib: 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") + def create_list(self,values): """ Helper function to create quoted, line wrapped list """ list_values = ", ".join(str(v) for v in values) @@ -518,7 +524,7 @@ class lib: web_name = " & !web{0}".format(port) avg_write_power = np.mean(self.char_port_results[port]["write1_power"] + self.char_port_results[port]["write0_power"]) self.lib.write(" internal_power(){\n") - self.lib.write(" when : \"!csb{0} & clk{0}{1}\"; \n".format(port, web_name)) + self.lib.write(" when : \"!csb{0}{1}\"; \n".format(port, web_name)) self.lib.write(" rise_power(scalar){\n") self.lib.write(" values(\"{0}\");\n".format(avg_write_power/2.0)) self.lib.write(" }\n") @@ -532,7 +538,7 @@ class lib: web_name = " & web{0}".format(port) avg_read_power = np.mean(self.char_port_results[port]["read1_power"] + self.char_port_results[port]["read0_power"]) self.lib.write(" internal_power(){\n") - self.lib.write(" when : \"!csb{0} & !clk{0}{1}\"; \n".format(port, web_name)) + self.lib.write(" when : \"!csb{0}{1}\"; \n".format(port, web_name)) self.lib.write(" rise_power(scalar){\n") self.lib.write(" values(\"{0}\");\n".format(avg_read_power/2.0)) self.lib.write(" }\n") @@ -552,6 +558,16 @@ class lib: self.lib.write(" }\n") self.lib.write(" }\n") + def write_pg_pin(self): + self.lib.write(" pg_pin(vdd) {\n") + self.lib.write(" voltage_name : VDD;\n") + self.lib.write(" pg_type : primary_power;\n") + self.lib.write(" }\n\n") + self.lib.write(" pg_pin(gnd) {\n") + self.lib.write(" voltage_name : GND;\n") + self.lib.write(" pg_type : primary_ground;\n") + self.lib.write(" }\n\n") + def compute_delay(self): """Compute SRAM delays for current corner""" self.d = delay(self.sram, self.sp_file, self.corner) From 1f816e2823b56c0c3f406d4f7424e7fb6311b236 Mon Sep 17 00:00:00 2001 From: David Ratchkov Date: Fri, 17 Apr 2020 14:55:17 -0700 Subject: [PATCH 3/6] - Characterize actual disabled power (read mode only) - Report rise/fall power individually --- .gitignore | 2 ++ compiler/characterizer/delay.py | 15 +++++++++++++-- compiler/characterizer/lib.py | 22 +++++++++++++--------- compiler/characterizer/simulation.py | 16 ++++++++++++++++ 4 files changed, 44 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index 948e7d19..3d6e4f92 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,5 @@ *.toc *.synctex.gz **/model_data +outputs +technology/freepdk45/ncsu_basekit diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index a9f9542c..2823a415 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -59,7 +59,7 @@ class delay(simulation): """ Create measurement names. The names themselves currently define the type of measurement """ self.delay_meas_names = ["delay_lh", "delay_hl", "slew_lh", "slew_hl"] - self.power_meas_names = ["read0_power", "read1_power", "write0_power", "write1_power"] + self.power_meas_names = ["read0_power", "read1_power", "write0_power", "write1_power", "disabled_read0_power", "disabled_read1_power"] # self.voltage_when_names = ["volt_bl", "volt_br"] # self.bitline_delay_names = ["delay_bl", "delay_br"] @@ -108,6 +108,11 @@ class delay(simulation): self.read_lib_meas.append(power_measure("read0_power", "FALL", measure_scale=1e3)) self.read_lib_meas[-1].meta_str = sram_op.READ_ZERO + self.read_lib_meas.append(power_measure("disabled_read1_power", "RISE", measure_scale=1e3)) + self.read_lib_meas[-1].meta_str = "disabled_read1" + self.read_lib_meas.append(power_measure("disabled_read0_power", "FALL", measure_scale=1e3)) + self.read_lib_meas[-1].meta_str = "disabled_read0" + # This will later add a half-period to the spice time delay. Only for reading 0. for obj in self.read_lib_meas: if obj.meta_str is sram_op.READ_ZERO: @@ -665,7 +670,7 @@ class delay(simulation): if not success: feasible_period = 2 * feasible_period continue - + # Positions of measurements currently hardcoded. First 2 are delays, next 2 are slews feasible_delays = [results[port][mname] for mname in self.delay_meas_names if "delay" in mname] feasible_slews = [results[port][mname] for mname in self.delay_meas_names if "slew" in mname] @@ -1208,6 +1213,9 @@ class delay(simulation): read_port) self.measure_cycles[read_port][sram_op.READ_ZERO] = len(self.cycle_times)-1 + self.add_nop(self.probe_address, data_zeros, read_port) + self.measure_cycles[write_port]["disabled_read0"] = len(self.cycle_times) - 1 + self.add_noop_all_ports("Idle cycle (if read takes >1 cycle)") self.add_write("W data 1 address {} to write value".format(self.probe_address), @@ -1223,6 +1231,9 @@ class delay(simulation): wmask_ones, write_port) + self.add_nop(self.probe_address, data_zeros, read_port) + self.measure_cycles[write_port]["disabled_read1"] = len(self.cycle_times) - 1 + # This also ensures we will have a L->H transition on the next read self.add_read("R data 0 address {} to clear dout caps".format(inverse_address), inverse_address, diff --git a/compiler/characterizer/lib.py b/compiler/characterizer/lib.py index b0668ddc..9f3c12d3 100644 --- a/compiler/characterizer/lib.py +++ b/compiler/characterizer/lib.py @@ -522,39 +522,43 @@ class lib: if port in self.write_ports: if port in self.read_ports: web_name = " & !web{0}".format(port) - avg_write_power = np.mean(self.char_port_results[port]["write1_power"] + self.char_port_results[port]["write0_power"]) + write1_power = np.mean(self.char_port_results[port]["write1_power"]) + write0_power = np.mean(self.char_port_results[port]["write0_power"]) self.lib.write(" internal_power(){\n") self.lib.write(" when : \"!csb{0}{1}\"; \n".format(port, web_name)) self.lib.write(" rise_power(scalar){\n") - self.lib.write(" values(\"{0}\");\n".format(avg_write_power/2.0)) + self.lib.write(" values(\"{0:.6e}\");\n".format(write1_power)) self.lib.write(" }\n") self.lib.write(" fall_power(scalar){\n") - self.lib.write(" values(\"{0}\");\n".format(avg_write_power/2.0)) + self.lib.write(" values(\"{0:.6e}\");\n".format(write0_power)) self.lib.write(" }\n") self.lib.write(" }\n") if port in self.read_ports: if port in self.write_ports: web_name = " & web{0}".format(port) - avg_read_power = np.mean(self.char_port_results[port]["read1_power"] + self.char_port_results[port]["read0_power"]) + read1_power = np.mean(self.char_port_results[port]["read1_power"]) + read0_power = np.mean(self.char_port_results[port]["read0_power"]) self.lib.write(" internal_power(){\n") self.lib.write(" when : \"!csb{0}{1}\"; \n".format(port, web_name)) self.lib.write(" rise_power(scalar){\n") - self.lib.write(" values(\"{0}\");\n".format(avg_read_power/2.0)) + self.lib.write(" values(\"{0:.6e}\");\n".format(read1_power)) self.lib.write(" }\n") self.lib.write(" fall_power(scalar){\n") - self.lib.write(" values(\"{0}\");\n".format(avg_read_power/2.0)) + self.lib.write(" values(\"{0:.6e}\");\n".format(read0_power)) self.lib.write(" }\n") self.lib.write(" }\n") - # Have 0 internal power when disabled, this will be represented as leakage power. + # Disabled power. + disabled_read1_power = np.mean(self.char_port_results[port]["disabled_read1_power"]) + disabled_read0_power = np.mean(self.char_port_results[port]["disabled_read0_power"]) self.lib.write(" internal_power(){\n") self.lib.write(" when : \"csb{0}\"; \n".format(port)) self.lib.write(" rise_power(scalar){\n") - self.lib.write(" values(\"0\");\n") + self.lib.write(" values(\"{0:.6e}\");\n".format(disabled_read1_power)) self.lib.write(" }\n") self.lib.write(" fall_power(scalar){\n") - self.lib.write(" values(\"0\");\n") + self.lib.write(" values(\"{0:.6e}\");\n".format(disabled_read0_power)) self.lib.write(" }\n") self.lib.write(" }\n") diff --git a/compiler/characterizer/simulation.py b/compiler/characterizer/simulation.py index adbe5f5f..0cfc860f 100644 --- a/compiler/characterizer/simulation.py +++ b/compiler/characterizer/simulation.py @@ -210,6 +210,22 @@ class simulation(): if unselected_port != port: self.add_noop_one_port(unselected_port) + def add_nop(self, address, din_data, port): + """ Add the control values for a cycle with clock only. Does not increment the period. """ + debug.check(port in self.read_ports or port in self.write_ports, + "Cannot add read cycle to a write port. Port {0}, Read Ports {1}".format(port, self.read_ports)) + debug.info(2, 'Clock only on port {}'.format(port)) + self.fn_cycle_comments.append('Clock only on port {}'.format(port)) + self.append_cycle_comment(port, 'Clock only on port {}'.format(port)) + + self.cycle_times.append(self.t_current) + self.t_current += self.period + self.add_control_one_port(port, "noop") + # If the port is also a readwrite then add data. + if port in self.write_ports: + self.add_data(din_data, port) + self.add_address(address, port) + def add_noop_all_ports(self, comment): """ Add the control values for a noop to all ports. """ debug.info(2, comment) From 123cc371beabe50a21bdf4382ce332198cd20255 Mon Sep 17 00:00:00 2001 From: David Ratchkov Date: Fri, 17 Apr 2020 16:09:58 -0700 Subject: [PATCH 4/6] - Fix disabled power char --- compiler/characterizer/delay.py | 24 ++++++++++++++---- compiler/characterizer/lib.py | 37 +++++++++++++++++++--------- compiler/characterizer/simulation.py | 33 +++++++++++++------------ 3 files changed, 61 insertions(+), 33 deletions(-) diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index 2823a415..62367d72 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -59,7 +59,8 @@ class delay(simulation): """ Create measurement names. The names themselves currently define the type of measurement """ self.delay_meas_names = ["delay_lh", "delay_hl", "slew_lh", "slew_hl"] - self.power_meas_names = ["read0_power", "read1_power", "write0_power", "write1_power", "disabled_read0_power", "disabled_read1_power"] + self.power_meas_names = ["read0_power", "read1_power", "write0_power", "write1_power", + "disabled_read0_power", "disabled_read1_power", "disabled_write0_power", "disabled_write1_power"] # self.voltage_when_names = ["volt_bl", "volt_br"] # self.bitline_delay_names = ["delay_bl", "delay_br"] @@ -161,6 +162,11 @@ class delay(simulation): self.write_lib_meas.append(power_measure("write0_power", "FALL", measure_scale=1e3)) self.write_lib_meas[-1].meta_str = sram_op.WRITE_ZERO + self.write_lib_meas.append(power_measure("disabled_write1_power", "RISE", measure_scale=1e3)) + self.write_lib_meas[-1].meta_str = "disabled_write1" + self.write_lib_meas.append(power_measure("disabled_write0_power", "FALL", measure_scale=1e3)) + self.write_lib_meas[-1].meta_str = "disabled_write0" + write_measures = [] write_measures.append(self.write_lib_meas) write_measures.append(self.create_write_bit_measures()) @@ -1203,6 +1209,9 @@ class delay(simulation): write_port) self.measure_cycles[write_port][sram_op.WRITE_ZERO] = len(self.cycle_times)-1 + self.add_noop_clock_one_port(write_port) + self.measure_cycles[write_port]["disabled_write0"] = len(self.cycle_times)-1 + # This also ensures we will have a H->L transition on the next read self.add_read("R data 1 address {} to set dout caps".format(inverse_address), inverse_address, @@ -1213,8 +1222,9 @@ class delay(simulation): read_port) self.measure_cycles[read_port][sram_op.READ_ZERO] = len(self.cycle_times)-1 - self.add_nop(self.probe_address, data_zeros, read_port) - self.measure_cycles[write_port]["disabled_read0"] = len(self.cycle_times) - 1 + self.add_noop_clock_one_port(read_port) + self.measure_cycles[read_port]["disabled_read0"] = len(self.cycle_times) - 1 + self.add_noop_all_ports("Idle cycle (if read takes >1 cycle)") @@ -1225,14 +1235,18 @@ class delay(simulation): write_port) self.measure_cycles[write_port][sram_op.WRITE_ONE] = len(self.cycle_times)-1 + self.add_noop_clock_one_port(write_port) + self.measure_cycles[write_port]["disabled_write1"] = len(self.cycle_times)-1 + self.add_write("W data 0 address {} to clear din caps".format(inverse_address), inverse_address, data_zeros, wmask_ones, write_port) - self.add_nop(self.probe_address, data_zeros, read_port) - self.measure_cycles[write_port]["disabled_read1"] = len(self.cycle_times) - 1 + self.add_noop_clock_one_port(read_port) + self.measure_cycles[read_port]["disabled_read1"] = len(self.cycle_times) - 1 + # This also ensures we will have a L->H transition on the next read self.add_read("R data 0 address {} to clear dout caps".format(inverse_address), diff --git a/compiler/characterizer/lib.py b/compiler/characterizer/lib.py index 9f3c12d3..57e21763 100644 --- a/compiler/characterizer/lib.py +++ b/compiler/characterizer/lib.py @@ -534,6 +534,19 @@ class lib: self.lib.write(" }\n") self.lib.write(" }\n") + # Disabled power. + disabled_read1_power = np.mean(self.char_port_results[port]["disabled_read1_power"]) + disabled_read0_power = np.mean(self.char_port_results[port]["disabled_raed0_power"]) + self.lib.write(" internal_power(){\n") + self.lib.write(" when : \"csb{0}{1}\"; \n".format(port, web_name)) + self.lib.write(" rise_power(scalar){\n") + self.lib.write(" values(\"{0:.6e}\");\n".format(disabled_read1_power)) + self.lib.write(" }\n") + self.lib.write(" fall_power(scalar){\n") + self.lib.write(" values(\"{0:.6e}\");\n".format(disabled_read0_power)) + self.lib.write(" }\n") + self.lib.write(" }\n") + if port in self.read_ports: if port in self.write_ports: web_name = " & web{0}".format(port) @@ -549,18 +562,18 @@ class lib: self.lib.write(" }\n") self.lib.write(" }\n") - # Disabled power. - disabled_read1_power = np.mean(self.char_port_results[port]["disabled_read1_power"]) - disabled_read0_power = np.mean(self.char_port_results[port]["disabled_read0_power"]) - self.lib.write(" internal_power(){\n") - self.lib.write(" when : \"csb{0}\"; \n".format(port)) - self.lib.write(" rise_power(scalar){\n") - self.lib.write(" values(\"{0:.6e}\");\n".format(disabled_read1_power)) - self.lib.write(" }\n") - self.lib.write(" fall_power(scalar){\n") - self.lib.write(" values(\"{0:.6e}\");\n".format(disabled_read0_power)) - self.lib.write(" }\n") - self.lib.write(" }\n") + # Disabled power. + disabled_write1_power = np.mean(self.char_port_results[port]["disabled_write1_power"]) + disabled_write0_power = np.mean(self.char_port_results[port]["disabled_write0_power"]) + self.lib.write(" internal_power(){\n") + self.lib.write(" when : \"csb{0}{1}\"; \n".format(port, web_name)) + self.lib.write(" rise_power(scalar){\n") + self.lib.write(" values(\"{0:.6e}\");\n".format(disabled_write1_power)) + self.lib.write(" }\n") + self.lib.write(" fall_power(scalar){\n") + self.lib.write(" values(\"{0:.6e}\");\n".format(disabled_write0_power)) + self.lib.write(" }\n") + self.lib.write(" }\n") def write_pg_pin(self): self.lib.write(" pg_pin(vdd) {\n") diff --git a/compiler/characterizer/simulation.py b/compiler/characterizer/simulation.py index 0cfc860f..0d5cfb25 100644 --- a/compiler/characterizer/simulation.py +++ b/compiler/characterizer/simulation.py @@ -210,22 +210,6 @@ class simulation(): if unselected_port != port: self.add_noop_one_port(unselected_port) - def add_nop(self, address, din_data, port): - """ Add the control values for a cycle with clock only. Does not increment the period. """ - debug.check(port in self.read_ports or port in self.write_ports, - "Cannot add read cycle to a write port. Port {0}, Read Ports {1}".format(port, self.read_ports)) - debug.info(2, 'Clock only on port {}'.format(port)) - self.fn_cycle_comments.append('Clock only on port {}'.format(port)) - self.append_cycle_comment(port, 'Clock only on port {}'.format(port)) - - self.cycle_times.append(self.t_current) - self.t_current += self.period - self.add_control_one_port(port, "noop") - # If the port is also a readwrite then add data. - if port in self.write_ports: - self.add_data(din_data, port) - self.add_address(address, port) - def add_noop_all_ports(self, comment): """ Add the control values for a noop to all ports. """ debug.info(2, comment) @@ -295,6 +279,23 @@ class simulation(): except: self.add_wmask("0"*self.num_wmasks, port) + def add_noop_clock_one_port(self, port): + """ Add the control values for a noop to a single port. Increments the period. """ + debug.info(2, 'Clock only on port {}'.format(port)) + self.fn_cycle_comments.append('Clock only on port {}'.format(port)) + self.append_cycle_comment(port, 'Clock only on port {}'.format(port)) + + self.cycle_times.append(self.t_current) + self.t_current += self.period + + self.add_noop_one_port(port) + + #Add noops to all other ports. + for unselected_port in self.all_ports: + if unselected_port != port: + self.add_noop_one_port(unselected_port) + + def append_cycle_comment(self, port, comment): """Add comment to list to be printed in stimulus file""" #Clean up time before appending. Make spacing dynamic as well. From 5aea45ed690593e4e9b965f84639e12ea29731e9 Mon Sep 17 00:00:00 2001 From: David Ratchkov Date: Fri, 17 Apr 2020 16:23:06 -0700 Subject: [PATCH 5/6] - Fix switched disabled powers --- compiler/characterizer/lib.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/compiler/characterizer/lib.py b/compiler/characterizer/lib.py index 57e21763..276ea767 100644 --- a/compiler/characterizer/lib.py +++ b/compiler/characterizer/lib.py @@ -535,15 +535,15 @@ class lib: self.lib.write(" }\n") # Disabled power. - disabled_read1_power = np.mean(self.char_port_results[port]["disabled_read1_power"]) - disabled_read0_power = np.mean(self.char_port_results[port]["disabled_raed0_power"]) + disabled_write1_power = np.mean(self.char_port_results[port]["disabled_write1_power"]) + disabled_write0_power = np.mean(self.char_port_results[port]["disabled_write0_power"]) self.lib.write(" internal_power(){\n") self.lib.write(" when : \"csb{0}{1}\"; \n".format(port, web_name)) self.lib.write(" rise_power(scalar){\n") - self.lib.write(" values(\"{0:.6e}\");\n".format(disabled_read1_power)) + self.lib.write(" values(\"{0:.6e}\");\n".format(disabled_write1_power)) self.lib.write(" }\n") self.lib.write(" fall_power(scalar){\n") - self.lib.write(" values(\"{0:.6e}\");\n".format(disabled_read0_power)) + self.lib.write(" values(\"{0:.6e}\");\n".format(disabled_write0_power)) self.lib.write(" }\n") self.lib.write(" }\n") @@ -563,18 +563,18 @@ class lib: self.lib.write(" }\n") # Disabled power. - disabled_write1_power = np.mean(self.char_port_results[port]["disabled_write1_power"]) - disabled_write0_power = np.mean(self.char_port_results[port]["disabled_write0_power"]) + disabled_read1_power = np.mean(self.char_port_results[port]["disabled_read1_power"]) + disabled_read0_power = np.mean(self.char_port_results[port]["disabled_read0_power"]) self.lib.write(" internal_power(){\n") self.lib.write(" when : \"csb{0}{1}\"; \n".format(port, web_name)) self.lib.write(" rise_power(scalar){\n") - self.lib.write(" values(\"{0:.6e}\");\n".format(disabled_write1_power)) + self.lib.write(" values(\"{0:.6e}\");\n".format(disabled_read1_power)) self.lib.write(" }\n") self.lib.write(" fall_power(scalar){\n") - self.lib.write(" values(\"{0:.6e}\");\n".format(disabled_write0_power)) + self.lib.write(" values(\"{0:.6e}\");\n".format(disabled_read0_power)) self.lib.write(" }\n") self.lib.write(" }\n") - + def write_pg_pin(self): self.lib.write(" pg_pin(vdd) {\n") self.lib.write(" voltage_name : VDD;\n") From c2419af2e2a61e4caa821ca04abcb90007a0ca0e Mon Sep 17 00:00:00 2001 From: David Ratchkov Date: Mon, 20 Apr 2020 13:36:47 -0700 Subject: [PATCH 6/6] 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 276ea767..e6befc2b 100644 --- a/compiler/characterizer/lib.py +++ b/compiler/characterizer/lib.py @@ -243,8 +243,8 @@ class lib: 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 """