Beispiel #1
0
    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
Beispiel #6
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))
Beispiel #7
0
    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
Beispiel #10
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)