def checkNCPins(self, pins: List[Pin]) -> bool: self.invisible_errors = [] self.type_errors = [] for pin in pins: name = pin.name.lower() etype = pin.etype # Check NC pins if self.test(name, self.NC_PINS) or etype == "no_connect": # NC pins should be of type no_connect if not etype == "no_connect": # Not set to NC self.type_errors.append(pin) # NC pins should be invisible if not pin.is_hidden: self.invisible_errors.append(pin) if self.type_errors: self.error("NC pins are not correct pin-type:") for pin in self.type_errors: self.errorExtra( "{pin} should be of type NOT CONNECTED, but is of type {pintype}" .format(pin=pinString(pin), pintype=etype)) if self.invisible_errors: self.warning("NC pins are VISIBLE (should be INVISIBLE):") for pin in self.invisible_errors: self.warningExtra( "{pin} should be INVISIBLE".format(pin=pinString(pin))) return self.invisible_errors or self.type_errors
def checkPinLength(self, errorPinLength: int = 49, warningPinLength: int = 99) -> bool: self.violating_pins = [] for pin in self.component.pins: length = mm_to_mil(pin.length) err = False # ignore zero-length pins e.g. hidden power pins if length == 0: continue if length <= errorPinLength: self.error("{pin} length ({len}mils) is below {pl}mils".format( pin=pinString(pin), len=length, pl=errorPinLength + 1)) elif length <= warningPinLength: self.warning( "{pin} length ({len}mils) is below {pl}mils".format( pin=pinString(pin), len=length, pl=warningPinLength + 1)) if length % 50 != 0: self.warning( "{pin} length ({len}mils) is not a multiple of 50mils". format(pin=pinString(pin), len=length)) # length too long flags a warning if length > 300: err = True self.error( "{pin} length ({length}mils) is longer than maximum (300mils)" .format(pin=pinString(pin), length=length)) if err: self.violating_pins.append(pin) return len(self.violating_pins) > 0
def checkDuplicatePins(self) -> bool: # look for duplicate pin numbers duplicate = False test_pins = list(self.component.pins) for pin0 in test_pins[:]: for pin1 in test_pins[:]: if pin0 != pin1 and pin0.is_duplicate(pin1): duplicate = True self.error("Pin {n} is duplicated:".format(n=pin0.number)) self.errorExtra(pinString(pin0)) break return duplicate
def checkDoubleInversions(self) -> bool: self.inversion_errors = [] for pin in self.component.pins: m = re.search(r"(\~{)(.+)}", pin.name) if m and pin.shape == "inverted": if not self.inversion_errors: self.error( "Pins should not be inverted twice (with inversion-symbol on" " pin and overline on label)") self.inversion_errors.append(pin) self.errorExtra( "{pin} : double inversion (overline + pin type:Inverting)". format(pin=pinString(pin))) return len(self.inversion_errors) > 0
def checkPinOrigin(self, gridspacing: int = 100) -> bool: self.violating_pins = [] err = False for pin in self.component.pins: posx = mm_to_mil(pin.posx) posy = mm_to_mil(pin.posy) if (posx % gridspacing) != 0 or (posy % gridspacing) != 0: self.violating_pins.append(pin) if not err: self.error( "Pins not located on {0}mil (={1:.3}mm) grid:".format( gridspacing, gridspacing * 0.0254)) self.error(" - {0} ".format(pinString(pin, loc=True))) err = True return len(self.violating_pins) > 0
def checkPowerPins(self) -> None: # Positive power pins only PWR = ["^[ad]*v(aa|cc|dd|bat|in)$"] first = True for pin in self.component.pins: name = str(pin.name.lower()) for pwr in PWR: if re.search(pwr, name, flags=re.IGNORECASE) is not None: # Pin orientation should be "down" if ( not self.component.is_power_symbol() ) and not pin.get_direction() == "D": if first: first = False self.warning( "Positive power pins should be placed at top of symbol" ) self.warningExtra(pinString(pin))
def checkGroundPins(self) -> None: # Includes negative power pins GND = ["^[ad]*g(rou)*nd(a)*$", "^[ad]*v(ss)$"] first = True for pin in self.component.pins: name = str(pin.name.lower()) for gnd in GND: if re.search(gnd, name, flags=re.IGNORECASE) is not None: # Pin orientation should be "up" if (not self.component.is_power_symbol()) and ( not pin.get_direction() == "U" ): if first: first = False self.warning( "Ground and negative power pins should be placed at" " bottom of symbol" ) self.warningExtra(pinString(pin))
def checkSuggestions(self) -> bool: self.suggestions = [] for pin in self.component.pins: name = pin.name.lower() etype = pin.etype for pin_type in self.warning_tests.keys(): tests = self.warning_tests[pin_type] if self.test(name, tests): if not pin_type == etype: if not self.suggestions: self.warning("Pin types should match pin function") self.suggestions.append(pin) self.warningExtra( "{pin} is type {t1} : suggested {t2}".format( pin=pinString(pin), t1=etype, t2=pin_type)) break # No error generated for this rule return False
def checkPowerPins(self) -> bool: self.power_errors = [] for stack in self.component.get_pinstacks().values(): visible = [pin for pin in stack if not pin.is_hidden] invisible = [pin for pin in stack if pin.is_hidden] # Due to the implementation of S4.3 it is possible to assume that at maximum one pin is # visible. if visible: checkpins = [visible[0]] else: checkpins = invisible for pin in checkpins: name = pin.name.lower() etype = pin.etype if self.test(name.lower(), self.POWER_INPUTS) and ( not etype.lower() == "power_in"): if not self.power_errors: self.error( "Power pins should be of type POWER INPUT or POWER OUTPUT" ) self.power_errors.append(pin) self.errorExtra("{pin} is of type {t}".format( pin=pinString(pin), t=etype)) if len(stack) > 1 and visible and visible[0].etype.lower( ) == "power_in": for pin in invisible: if pin.etype.lower() != "passive": if not self.power_errors: self.error( "Invisible powerpins in stacks should be of type" " PASSIVE") return len(self.power_errors) > 0
def check(self) -> bool: # no need to check this for a derived symbols if self.component.extends is not None: return False possible_power_pin_stacks = [] # iterate over pinstacks for (pos, pins) in self.component.get_pinstacks().items(): # skip stacks with only one pin if len(pins) == 1: continue common_pin_name = pins[0].name visible_pin = None common_etype = pins[0].etype min_pin_number = self.get_smallest_pin_number(pins) for pin in pins: if pin.number_int is None and pos not in self.non_numeric: self.warning( "Found non-numeric pin in a pinstack: {0}".format( pinString(pin))) self.non_numeric.append(pos) # Check1: If a single pin in a stack is of type NC, we consider this an error if pin.etype == "no_connect": self.error( "NC {pin} (x={x}, y={y}) is stacked on other pins". format(pin=pinString(pin), x=pin.posx, y=pin.posy)) self.NC_stacked.append(pin) # Check2: all pins should have the same name if pin.name != common_pin_name and pos not in self.different_names: self.error("Pin names in the stack have different names") self.different_names.append(pos) for pin in pins: self.errorExtra(pinString(pin)) # Check3: exactly one pin should be visible if not pin.is_hidden: if visible_pin is not None: if not self.more_then_one_visible: self.error( "A pin stack must have exactly one (1) visible pin" ) for pin in pins: self.errorExtra("{pin} is visible".format( pin=pinString(pin))) self.more_then_one_visible = True else: visible_pin = pin # the visible pin should have the lowest pin_number if (pin.number_int is not None and pin.number_int != min_pin_number and pos not in self.visible_pin_not_lowest): self.warning( "The pin with the lowest number in a pinstack should be" " visible") self.warningExtra( "Pin {0} is visible, the lowest number in this stack is {1}" .format(pinString(pin), min_pin_number)) self.visible_pin_not_lowest.append(pos) # Check4: all pins should have the same electrical type. # exceptions are power-pin-stacks if pin.etype != common_etype: # this could be one of the special cases # At least one of the two checked pins needs to be 'special' type. # If not, this is an error. if (pin.etype in self.SPECIAL_POWER_PINS or common_etype in self.SPECIAL_POWER_PINS): possible_power_pin_stacks.append(pos) else: if pos not in self.different_types: self.error( "Pin names in the stack have different electrical types" ) for pin in pins: self.errorExtra("{0} is of type {1}".format( pinString(pin), pin.etype)) self.different_types.append(pos) # check the possible power pin_stacks special_stack_err = False for pos in possible_power_pin_stacks: pins = self.component.get_pinstacks()[pos] min_pin_number = self.get_smallest_pin_number(pins) # 1. consists only of output and passive pins # 2. consists only of power-output and passive pins # 3. consists only of power-input and passive pins # 4. consists only of power-output/output pins # count types of pins n_power_in = self.count_pin_etypes(pins, "power_in") n_power_out = self.count_pin_etypes(pins, "power_out") n_output = self.count_pin_etypes(pins, "output") n_passive = self.count_pin_etypes(pins, "passive") n_others = len( pins) - n_power_in - n_power_out - n_passive - n_output n_total = len(pins) # check for cases 1..3 if n_passive == n_total - 1 and (n_power_in == 1 or n_power_out == 1 or n_output == 1): # find the passive pins, they must be invisible for pin in pins: if pin.etype == "passive" and not pin.is_hidden: self.error("Passive pins in a pinstack are hidden") special_stack_err = True for ipin in pins: if ipin.etype == "passive" and not ipin.is_hidden: self.errorExtra( "{0} is of type {1} and visible".format( pinString(ipin), ipin.etype)) break # Find the non-passive pin, it must be visible. # Also, it should have the lowest pin-number of all. for pin in pins: if pin.etype != "passive": # we found the non-passive pin if pin.is_hidden: self.error( "Non passive pins in a pinstack are visible") special_stack_err = True self.errorExtra( "{0} is of type {1} and invisible".format( pinString(pin), pin.etype)) if (pin.number_int is not None and pin.number_int != min_pin_number and pos not in self.visible_pin_not_lowest): self.warning( "The pin with the lowest number in a pinstack should be" " visible") self.warningExtra( "Pin {0} is visible, the lowest number in this stack" " is {1}".format(pinString(pin), min_pin_number)) self.visible_pin_not_lowest.append(pos) break # check for case 4 elif n_output == n_total or n_power_out == n_total: visible_pin = None # all but one pins should be invisible for pin in pins: if not pin.is_hidden: if visible_pin is None: # this is the first time we found a visible pin in this stack visible_pin = pin if (pin.number_int is not None and pin.number_int != min_pin_number and pos not in self.visible_pin_not_lowest): self.warning( "The pin with the lowest number in a pinstack" " should be visible") self.warningExtra( "Pin {0} is visible, the lowest number in this" " stack is {1}".format( pinString(pin), min_pin_number)) self.visible_pin_not_lowest.append(pos) else: # more than one visible pin found special_stack_err = True self.error("Only one pin in a pinstack is visible") for vpin in (pin for pin in pins if not pin.is_hidden): self.errorExtra("Pin {0} is visible".format( pinString(vpin))) else: # pinstack is none of the above cases. self.error("Illegal pin stack configuration next to {}".format( pinString(pins[0]))) self.errorExtra("Power input pins: {}".format(n_power_in)) self.errorExtra("Power output pins: {}".format(n_power_out)) self.errorExtra("Output pins: {}".format(n_output)) self.errorExtra("Passive pins: {}".format(n_passive)) self.errorExtra("Other type pins: {}".format(n_others)) special_stack_err = True return bool(self.more_then_one_visible or self.different_types or self.NC_stacked or self.different_names or special_stack_err)