From 8603d3edd6ee0ce3a910de90ca2602628652f9e9 Mon Sep 17 00:00:00 2001 From: mrg Date: Fri, 3 Apr 2020 11:37:06 -0700 Subject: [PATCH] PEP8 cleanup --- compiler/base/hierarchy_spice.py | 166 +++++++++++++++++-------------- 1 file changed, 89 insertions(+), 77 deletions(-) diff --git a/compiler/base/hierarchy_spice.py b/compiler/base/hierarchy_spice.py index 707e7bc8..ee8844c2 100644 --- a/compiler/base/hierarchy_spice.py +++ b/compiler/base/hierarchy_spice.py @@ -15,6 +15,7 @@ from wire_spice_model import * from power_data import * import logical_effort + class spice(): """ This provides a set of useful generic types for hierarchy @@ -30,19 +31,19 @@ class spice(): self.valid_signal_types = ["INOUT", "INPUT", "OUTPUT", "POWER", "GROUND"] # Holds subckts/mods for this module - self.mods = [] + self.mods = [] # Holds the pins for this module self.pins = [] # The type map of each pin: INPUT, OUTPUT, INOUT, POWER, GROUND # for each instance, this is the set of nets/nodes that map to the pins for this instance - self.pin_type = {} + self.pin_type = {} # THE CONNECTIONS MUST MATCH THE ORDER OF THE PINS (restriction imposed by the # Spice format) self.conns = [] # Keep track of any comments to add the the spice try: self.commments - except: + except NameError: self.comments = [] self.sp_read() @@ -56,7 +57,7 @@ class spice(): try: self.commments - except: + except NameError: self.comments = [] self.comments.append(comment) @@ -65,7 +66,9 @@ class spice(): """ Adds a pin to the pins list. Default type is INOUT signal. """ self.pins.append(name) self.pin_type[name]=pin_type - debug.check(pin_type in self.valid_signal_types, "Invalid signaltype for {0}: {1}".format(name,pin_type)) + debug.check(pin_type in self.valid_signal_types, + "Invalid signaltype for {0}: {1}".format(name, + pin_type)) def add_pin_list(self, pin_list, pin_type="INOUT"): """ Adds a pin_list to the pins list """ @@ -73,36 +76,43 @@ class spice(): # or a list that is the same length as the pin list. if type(pin_type)==str: for pin in pin_list: - debug.check(pin_type in self.valid_signal_types, "Invalid signaltype for {0}: {1}".format(pin,pin_type)) - self.add_pin(pin,pin_type) + debug.check(pin_type in self.valid_signal_types, + "Invalid signaltype for {0}: {1}".format(pin, + pin_type)) + self.add_pin(pin, pin_type) elif len(pin_type)==len(pin_list): - for (pin,ptype) in zip(pin_list, pin_type): - debug.check(ptype in self.valid_signal_types, "Invalid signaltype for {0}: {1}".format(pin,ptype)) - self.add_pin(pin,ptype) + for (pin, ptype) in zip(pin_list, pin_type): + debug.check(ptype in self.valid_signal_types, + "Invalid signaltype for {0}: {1}".format(pin, + ptype)) + self.add_pin(pin, ptype) else: debug.error("Mismatch in type and pin list lengths.", -1) def add_pin_types(self, type_list): - """Add pin types for all the cell's pins. - Typically, should only be used for handmade cells.""" - #This only works if self.pins == bitcell.pin_names + """ + Add pin types for all the cell's pins. + Typically, should only be used for handmade cells. + """ + # This only works if self.pins == bitcell.pin_names if self.pin_names != self.pins: debug.error("{} spice subcircuit port names do not match pin_names\ \n SPICE names={}\ \n Module names={}\ - ".format(self.name, self.pin_names, self.pins),1) - self.pin_type = {pin:type for pin,type in zip(self.pin_names, type_list)} + ".format(self.name, self.pin_names, self.pins), 1) + self.pin_type = {pin: type for pin, type in zip(self.pin_names, type_list)} def get_pin_type(self, name): """ Returns the type of the signal pin. """ pin_type = self.pin_type[name] - debug.check(pin_type in self.valid_signal_types, "Invalid signaltype for {0}: {1}".format(name,pin_type)) + debug.check(pin_type in self.valid_signal_types, + "Invalid signaltype for {0}: {1}".format(name, pin_type)) return pin_type def get_pin_dir(self, name): """ Returns the direction of the pin. (Supply/ground are INOUT). """ - if self.pin_type[name] in ["POWER","GROUND"]: + if self.pin_type[name] in ["POWER", "GROUND"]: return "INOUT" else: return self.pin_type[name] @@ -125,11 +135,10 @@ class spice(): output_list.append(pin) return output_list - def copy_pins(self, other_module, suffix=""): """ This will copy all of the pins from the other module and add an optional suffix.""" for pin in other_module.pins: - self.add_pin(pin+suffix, other_module.get_pin_type(pin)) + self.add_pin(pin + suffix, other_module.get_pin_type(pin)) def get_inouts(self): """ These use pin types to determine pin lists. These @@ -144,7 +153,6 @@ class spice(): """Adds a subckt/submodule to the subckt hierarchy""" self.mods.append(mod) - def connect_inst(self, args, check=True): """Connects the pins of the last instance added It is preferred to use the function with the check to find if @@ -169,21 +177,23 @@ class spice(): debug.error("{0} : Not all instance pins ({1}) are connected ({2}).".format(self.name, len(self.insts), len(self.conns))) - debug.error("Instances: \n"+str(insts_string)) + debug.error("Instances: \n" + str(insts_string)) debug.error("-----") - debug.error("Connections: \n"+str(conns_string),1) + debug.error("Connections: \n" + str(conns_string), 1) def get_conns(self, inst): """Returns the connections of a given instance.""" for i in range(len(self.insts)): if inst is self.insts[i]: return self.conns[i] - #If not found, returns None + # If not found, returns None return None def sp_read(self): - """Reads the sp file (and parse the pins) from the library - Otherwise, initialize it to null for dynamic generation""" + """ + Reads the sp file (and parse the pins) from the library + Otherwise, initialize it to null for dynamic generation + """ if self.sp_file and os.path.isfile(self.sp_file): debug.info(3, "opening {0}".format(self.sp_file)) f = open(self.sp_file) @@ -202,13 +212,14 @@ class spice(): def check_net_in_spice(self, net_name): """Checks if a net name exists in the current. Intended to be check nets in hand-made cells.""" - #Remove spaces and lower case then add spaces. Nets are separated by spaces. - net_formatted = ' '+net_name.lstrip().rstrip().lower()+' ' + # Remove spaces and lower case then add spaces. + # Nets are separated by spaces. + net_formatted = ' ' + net_name.lstrip().rstrip().lower() + ' ' for line in self.spice: - #Lowercase the line and remove any part of the line that is a comment. + # Lowercase the line and remove any part of the line that is a comment. line = line.lower().split('*')[0] - #Skip .subckt or .ENDS lines + # Skip .subckt or .ENDS lines if line.find('.') == 0: continue if net_formatted in line: @@ -220,7 +231,7 @@ class spice(): nets_match = True for net in nets: nets_match = nets_match and self.check_net_in_spice(net) - return nets_match + return nets_match def contains(self, mod, modlist): for x in modlist: @@ -244,34 +255,31 @@ class spice(): if self.pins == []: return - # write out the first spice line (the subcircuit) sp.write("\n.SUBCKT {0} {1}\n".format(self.name, " ".join(self.pins))) for pin in self.pins: - sp.write("* {1:6}: {0} \n".format(pin,self.pin_type[pin])) + sp.write("* {1:6}: {0} \n".format(pin, self.pin_type[pin])) for line in self.comments: sp.write("* {}\n".format(line)) # every instance must have a set of connections, even if it is empty. - if len(self.insts)!=len(self.conns): + if len(self.insts) != len(self.conns): debug.error("{0} : Not all instance pins ({1}) are connected ({2}).".format(self.name, len(self.insts), len(self.conns))) - debug.error("Instances: \n"+str(self.insts)) + debug.error("Instances: \n" + str(self.insts)) debug.error("-----") - debug.error("Connections: \n"+str(self.conns),1) - - + debug.error("Connections: \n" + str(self.conns), 1) for i in range(len(self.insts)): # we don't need to output connections of empty instances. # these are wires and paths if self.conns[i] == []: continue - if hasattr(self.insts[i].mod,"spice_device"): + if hasattr(self.insts[i].mod, "spice_device"): sp.write(self.insts[i].mod.spice_device.format(self.insts[i].name, " ".join(self.conns[i]))) sp.write("\n") @@ -286,7 +294,7 @@ class spice(): else: # write the subcircuit itself # Including the file path makes the unit test fail for other users. - #if os.path.isfile(self.sp_file): + # if os.path.isfile(self.sp_file): # sp.write("\n* {0}\n".format(self.sp_file)) sp.write("\n".join(self.spice)) @@ -305,7 +313,8 @@ class spice(): def analytical_delay(self, corner, slew, load=0.0): """Inform users undefined delay module while building new modules""" - # FIXME: Slew is not used in the model right now. Can be added heuristically as linear factor + # FIXME: Slew is not used in the model right now. + # Can be added heuristically as linear factor relative_cap = logical_effort.convert_farad_to_relative_c(load) stage_effort = self.get_stage_effort(relative_cap) @@ -316,7 +325,7 @@ class spice(): abs_delay = stage_effort.get_absolute_delay() corner_delay = self.apply_corners_analytically(abs_delay, corner) SLEW_APPROXIMATION = 0.1 - corner_slew = SLEW_APPROXIMATION*corner_delay + corner_slew = SLEW_APPROXIMATION * corner_delay return delay_data(corner_delay, corner_slew) def get_stage_effort(self, cout, inp_is_rise=True): @@ -326,7 +335,7 @@ class spice(): debug.warning("Class {0} name {1}" .format(self.__class__.__name__, self.name)) - return None + return None def get_cin(self): """Returns input load in Femto-Farads. All values generated using @@ -342,35 +351,35 @@ class spice(): debug.warning("Design Class {0} input capacitance function needs to be defined" .format(self.__class__.__name__)) debug.warning("Class {0} name {1}" - .format(self.__class__.__name__, - self.name)) - return 0 + .format(self.__class__.__name__, + self.name)) + return 0 - def cal_delay_with_rc(self, corner, r, c ,slew, swing = 0.5): - """ - Calculate the delay of a mosfet by + def cal_delay_with_rc(self, corner, r, c, slew, swing=0.5): + """ + Calculate the delay of a mosfet by modeling it as a resistance driving a capacitance """ - swing_factor = abs(math.log(1-swing)) # time constant based on swing - delay = swing_factor * r * c #c is in ff and delay is in fs + swing_factor = abs(math.log(1 - swing)) # time constant based on swing + delay = swing_factor * r * c # c is in ff and delay is in fs delay = self.apply_corners_analytically(delay, corner) - delay = delay * 0.001 #make the unit to ps + delay = delay * 0.001 # make the unit to ps - # Output slew should be linear to input slew which is described + # Output slew should be linear to input slew which is described # as 0.005* slew. # The slew will be also influenced by the delay. - # If no input slew(or too small to make impact) - # The mimum slew should be the time to charge RC. + # If no input slew(or too small to make impact) + # The mimum slew should be the time to charge RC. # Delay * 2 is from 0 to 100% swing. 0.6*2*delay is from 20%-80%. slew = delay * 0.6 * 2 + 0.005 * slew - return delay_data(delay = delay, slew = slew) + return delay_data(delay=delay, slew=slew) def apply_corners_analytically(self, delay, corner): """Multiply delay by corner factors""" - proc,vdd,temp = corner - #FIXME: type of delay is needed to know which process to use. - proc_mult = max(self.get_process_delay_factor(proc)) + proc, vdd, temp = corner + # FIXME: type of delay is needed to know which process to use. + proc_mult = max(self.get_process_delay_factor(proc)) volt_mult = self.get_voltage_delay_factor(vdd) temp_mult = self.get_temp_delay_factor(temp) return delay * proc_mult * volt_mult * temp_mult @@ -385,48 +394,51 @@ class spice(): elif mos_proc == 'F': proc_factors.append(0.9) elif mos_proc == 'S': - proc_factors.append(1.1) + proc_factors.append(1.1) return proc_factors def get_voltage_delay_factor(self, voltage): """Returns delay increase due to voltage. Implemented as linear factor based off nominal voltage. """ - return tech.spice["nom_supply_voltage"]/voltage + return tech.spice["nom_supply_voltage"] / voltage def get_temp_delay_factor(self, temp): """Returns delay increase due to temperature (in C). Determines effect on threshold voltage and then linear factor is estimated. """ - #Some portions of equation condensed (phi_t = k*T/q for T in Kelvin) in mV - #(k/q)/100 = .008625, The division 100 simplifies the conversion from C to K and mV to V - thermal_voltage_nom = 0.008625*tech.spice["nom_temperature"] - thermal_voltage = 0.008625*temp - vthresh = (tech.spice["nom_threshold"]+2*(thermal_voltage-thermal_voltage_nom)) - #Calculate effect on Vdd-Vth. The current vdd is not used here. A separate vdd factor is calculated. - return (tech.spice["nom_supply_voltage"] - tech.spice["nom_threshold"])/(tech.spice["nom_supply_voltage"]-vthresh) + # Some portions of equation condensed (phi_t = k*T/q for T in Kelvin) in mV + # (k/q)/100 = .008625, The division 100 simplifies the conversion from C to K and mV to V + thermal_voltage_nom = 0.008625 * tech.spice["nom_temperature"] + thermal_voltage = 0.008625 * temp + vthresh = (tech.spice["nom_threshold"] + 2 * (thermal_voltage - thermal_voltage_nom)) + # Calculate effect on Vdd-Vth. + # The current vdd is not used here. + # A separate vdd factor is calculated. + return (tech.spice["nom_supply_voltage"] - tech.spice["nom_threshold"]) / (tech.spice["nom_supply_voltage"] - vthresh) def return_delay(self, delay, slew): return delay_data(delay, slew) - def generate_rc_net(self,lump_num, wire_length, wire_width): + def generate_rc_net(self, lump_num, wire_length, wire_width): return wire_spice_model(lump_num, wire_length, wire_width) def calc_dynamic_power(self, corner, c, freq, swing=1.0): - """ + """ Calculate dynamic power using effective capacitance, frequency, and corner (PVT) """ - proc,vdd,temp = corner - net_vswing = vdd*swing - power_dyn = c*vdd*net_vswing*freq + proc, vdd, temp = corner + net_vswing = vdd * swing + power_dyn = c * vdd * net_vswing * freq - #Apply process and temperature factors. Roughly, process and Vdd affect the delay which affects the power. - #No other estimations are currently used. Increased delay->slower freq.->less power - proc_div = max(self.get_process_delay_factor(proc)) + # A pply process and temperature factors. + # Roughly, process and Vdd affect the delay which affects the power. + # No other estimations are currently used. Increased delay->slower freq.->less power + proc_div = max(self.get_process_delay_factor(proc)) temp_div = self.get_temp_delay_factor(temp) - power_dyn = power_dyn/(proc_div*temp_div) + power_dyn = power_dyn / (proc_div * temp_div) - return power_dyn + return power_dyn def return_power(self, dynamic=0.0, leakage=0.0): return power_data(dynamic, leakage)