Example #1
0
    def setup_layout_constants(self):
        """ Determine the design rules for the enclosure layers """

        self.contact_width = drc("minwidth_{0}".format(self.via_layer_name))
        contact_to_contact = drc("{0}_to_{0}".format(self.via_layer_name))
        self.contact_pitch = self.contact_width + contact_to_contact

        self.contact_array_width = self.contact_width + (
            self.dimensions[0] - 1) * self.contact_pitch
        self.contact_array_height = self.contact_width + (
            self.dimensions[1] - 1) * self.contact_pitch

        # DRC rules
        # The extend rule applies to asymmetric enclosures in one direction.
        # The enclosure rule applies to symmetric enclosure component.

        self.first_layer_minwidth = drc("minwidth_{0}".format(
            self.first_layer_name))
        self.first_layer_enclosure = drc("{0}_enclose_{1}".format(
            self.first_layer_name, self.via_layer_name))
        # If there's a different rule for active
        # FIXME: Make this more elegant
        if self.is_well_contact and self.first_layer_name == "active" and "tap_extend_contact" in drc.keys(
        ):
            self.first_layer_extend = drc("tap_extend_contact")
        else:
            self.first_layer_extend = drc("{0}_extend_{1}".format(
                self.first_layer_name, self.via_layer_name))

        self.second_layer_minwidth = drc("minwidth_{0}".format(
            self.second_layer_name))
        self.second_layer_enclosure = drc("{0}_enclose_{1}".format(
            self.second_layer_name, self.via_layer_name))
        self.second_layer_extend = drc("{0}_extend_{1}".format(
            self.second_layer_name, self.via_layer_name))

        # In some technologies, the minimum width may be larger
        # than the overlap requirement around the via, so
        # check this for each dimension.
        if self.directions[0] == "V":
            self.first_layer_horizontal_enclosure = max(
                self.first_layer_enclosure,
                (self.first_layer_minwidth - self.contact_array_width) / 2)
            self.first_layer_vertical_enclosure = max(
                self.first_layer_extend,
                (self.first_layer_minwidth - self.contact_array_height) / 2)
        elif self.directions[0] == "H":
            self.first_layer_horizontal_enclosure = max(
                self.first_layer_extend,
                (self.first_layer_minwidth - self.contact_array_width) / 2)
            self.first_layer_vertical_enclosure = max(
                self.first_layer_enclosure,
                (self.first_layer_minwidth - self.contact_array_height) / 2)
        else:
            debug.error(
                "Invalid first layer direction: ".format(self.directions[0]),
                -1)

        # In some technologies, the minimum width may be larger
        # than the overlap requirement around the via, so
        # check this for each dimension.
        if self.directions[1] == "V":
            self.second_layer_horizontal_enclosure = max(
                self.second_layer_enclosure,
                (self.second_layer_minwidth - self.contact_array_width) / 2)
            self.second_layer_vertical_enclosure = max(
                self.second_layer_extend,
                (self.second_layer_minwidth - self.contact_array_height) / 2)
        elif self.directions[1] == "H":
            self.second_layer_horizontal_enclosure = max(
                self.second_layer_extend,
                (self.second_layer_minwidth - self.contact_array_height) / 2)
            self.second_layer_vertical_enclosure = max(
                self.second_layer_enclosure,
                (self.second_layer_minwidth - self.contact_array_width) / 2)
        else:
            debug.error(
                "Invalid secon layer direction: ".format(self.directions[1]),
                -1)
Example #2
0
    def setup_drc_constants(self):
        """
        These are some DRC constants used in many places
        in the compiler.
        """
        # Make some local rules for convenience
        from tech import drc
        for rule in drc.keys():
            # Single layer width rules
            match = re.search(r"minwidth_(.*)", rule)
            if match:
                if match.group(1) == "active_contact":
                    setattr(self, "contact_width", drc(match.group(0)))
                else:
                    setattr(self,
                            match.group(1) + "_width", drc(match.group(0)))

            # Single layer area rules
            match = re.search(r"minarea_(.*)", rule)
            if match:
                setattr(self, match.group(0), drc(match.group(0)))

            # Single layer spacing rules
            match = re.search(r"(.*)_to_(.*)", rule)
            if match and match.group(1) == match.group(2):
                setattr(self, match.group(1) + "_space", drc(match.group(0)))
            elif match and match.group(1) != match.group(2):
                if match.group(2) == "poly_active":
                    setattr(self,
                            match.group(1) + "_to_contact",
                            drc(match.group(0)))
                else:
                    setattr(self, match.group(0), drc(match.group(0)))

            match = re.search(r"(.*)_enclose_(.*)", rule)
            if match:
                setattr(self, match.group(0), drc(match.group(0)))

            match = re.search(r"(.*)_extend_(.*)", rule)
            if match:
                setattr(self, match.group(0), drc(match.group(0)))

        # Create the maximum well extend active that gets used
        # by cells to extend the wells for interaction with other cells
        from tech import layer
        self.well_extend_active = 0
        if "nwell" in layer:
            self.well_extend_active = max(self.well_extend_active,
                                          self.nwell_extend_active)
        if "pwell" in layer:
            self.well_extend_active = max(self.well_extend_active,
                                          self.pwell_extend_active)

        # The active offset is due to the well extension
        if "pwell" in layer:
            self.pwell_enclose_active = drc("pwell_enclose_active")
        else:
            self.pwell_enclose_active = 0
        if "nwell" in layer:
            self.nwell_enclose_active = drc("nwell_enclose_active")
        else:
            self.nwell_enclose_active = 0
        # Use the max of either so that the poly gates will align properly
        self.well_enclose_active = max(self.pwell_enclose_active,
                                       self.nwell_enclose_active,
                                       self.active_space)

        # These are for debugging previous manual rules
        if False:
            print("poly_width", self.poly_width)
            print("poly_space", self.poly_space)
            print("m1_width", self.m1_width)
            print("m1_space", self.m1_space)
            print("m2_width", self.m2_width)
            print("m2_space", self.m2_space)
            print("m3_width", self.m3_width)
            print("m3_space", self.m3_space)
            print("m4_width", self.m4_width)
            print("m4_space", self.m4_space)
            print("active_width", self.active_width)
            print("active_space", self.active_space)
            print("contact_width", self.contact_width)
            print("poly_to_active", self.poly_to_active)
            print("poly_extend_active", self.poly_extend_active)
            print("poly_to_contact", self.poly_to_contact)
            print("active_contact_to_gate", self.active_contact_to_gate)
            print("poly_contact_to_gate", self.poly_contact_to_gate)
            print("well_enclose_active", self.well_enclose_active)
            print("implant_enclose_active", self.implant_enclose_active)
            print("implant_space", self.implant_space)
            import sys
            sys.exit(1)