Пример #1
0
    def setup_layout_constants(self):
        self.contact_width = drc["minwidth_{0}".format(self.via_layer_name)]
        self.contact_to_contact = drc["{0}_to_{0}".format(self.via_layer_name)]
        self.contact_pitch = self.contact_width + self.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

        # FIME break this up
        self.first_layer_horizontal_enclosure = max(
            (drc["minwidth_{0}".format(self.first_layer_name)] -
             self.contact_array_width) / 2,
            drc["{0}_enclosure_{1}".format(self.first_layer_name,
                                           self.via_layer_name)])
        self.first_layer_vertical_enclosure = max(
            utils.ceil((drc["minarea_{0}".format(self.first_layer_name)] /
                        (self.contact_array_width +
                         2 * self.first_layer_horizontal_enclosure) -
                        self.contact_array_height) / 2),
            (drc["minheight_{0}".format(self.first_layer_name)] -
             self.contact_array_height) / 2,
            drc["{0}_extend_{1}".format(self.first_layer_name,
                                        self.via_layer_name)])

        self.second_layer_horizontal_enclosure = max(
            (drc["minwidth_{0}".format(self.second_layer_name)] -
             self.contact_array_width) / 2,
            drc["{0}_enclosure_{1}".format(self.second_layer_name,
                                           self.via_layer_name)])
        self.second_layer_vertical_enclosure = max(
            utils.ceil((drc["minarea_{0}".format(self.second_layer_name)] /
                        (self.contact_array_width +
                         2 * self.second_layer_horizontal_enclosure) -
                        self.contact_array_height) / 2),
            (drc["minheight_{0}".format(self.second_layer_name)] -
             self.contact_array_height) / 2,
            drc["{0}_extend_{1}".format(self.second_layer_name,
                                        self.via_layer_name)])
        # offset for the via array
        self.via_layer_position = vector(
            max(self.first_layer_horizontal_enclosure,
                self.second_layer_horizontal_enclosure),
            max(self.first_layer_vertical_enclosure,
                self.second_layer_vertical_enclosure))
        # this is if the first and second layers are different
        self.first_layer_position = vector(
            max(
                self.second_layer_horizontal_enclosure -
                self.first_layer_horizontal_enclosure, 0),
            max(
                self.second_layer_vertical_enclosure -
                self.first_layer_vertical_enclosure, 0))
        self.second_layer_position = vector(
            max(
                self.first_layer_horizontal_enclosure -
                self.second_layer_horizontal_enclosure, 0),
            max(
                self.first_layer_vertical_enclosure -
                self.second_layer_vertical_enclosure, 0))
Пример #2
0
    def add_well_contacts(self):
        """ Add n/p well taps to the layout and connect to supplies """

        layer_stack = ("active", "contact", "metal1")
        nw_contact_off=vector(self.well_enclose_active, 
                              self.height-contact.well.height-self.well_enclose_active)
        self.add_contact(layers=layer_stack, 
                         offset=(nw_contact_off.x+contact.active.height, nw_contact_off.y),
                         implant_type="n", well_type="n", rotate=90)

        pw_contact_off= vector(self.nmos_inst[0].lr().x+self.implant_enclose_body_active, 
                               self.well_enclose_active)
        self.add_contact(layers=layer_stack, 
                         offset=(pw_contact_off.x+contact.active.height, pw_contact_off.y),
                         implant_type="p", well_type="p", rotate=90)
        
        self.active_height = ceil(self.active_minarea/(1.5*contact.well.height))
        
        active_off1 = nw_contact_off-vector(0, self.active_height-self.well_enclose_active)
        metal_off1= nw_contact_off + vector(0,self.active_enclose_contact)
        metal_height1 = self.height -  nw_contact_off.y - self.active_enclose_contact
        pimplant_off = (0, 0)
        implant_width = self.well_enclose_active+1.5*contact.well.height+\
                        self.implant_enclose_body_active

        active_off2 = pw_contact_off
        metal_off2= (pw_contact_off.x, 0)
        metal_height2 = pw_contact_off.y + self.active_enclose_contact
        nimplant_off = (self.nmos_inst[0].lr().x, 0)


        self.add_active_implant("nimplant", active_off1, metal_off1, metal_height1, 
                                pimplant_off, implant_width)
        self.add_active_implant("pimplant", active_off2, metal_off2, metal_height2, 
                               nimplant_off, implant_width)
Пример #3
0
    def add_sync_din_pins(self):
        """ Adds the output data pins """

        for i in range(self.size):
            if i % 2:
                yshift = 0
                yshift2 = -1
                ypin=self.din_inst[i].get_pin("Dp2").cc()-\
                     vector(0.5*contact.active.height,0.5*contact.active.width)
            else:
                yshift = 1
                yshift2 = 1
                ypin=self.din_inst[i].get_pin("Dp2").cc()-\
                     vector(0.5*contact.active.height, -0.5*contact.active.width)

            xpos = self.din_inv_inst[i].lx() - self.m_pitch("m1")

            pos1 = self.din_inv_inst[i].get_pin("A").lc()
            pos2 = vector(pos1.x - self.m_pitch("m1"), pos1.y)
            pos3 = vector(pos2.x, ypin.y)
            self.add_wire(self.m1_stack, [pos1, pos2, pos3, ypin])

            width = ceil(self.m1_minarea / contact.m1m2.first_layer_width)
            net = self.din_inv_inst[i].get_pin("Z")
            self.add_metal_minarea(
                "metal1",
                (net.lx() - contact.m1m2.width + 0.5 * width, net.lc().y))

            # add final sync_din pins as outputs (syn_datain)
            self.add_layout_pin(text="sync_din[{0}]".format(i),
                                layer=self.m1_pin_layer,
                                offset=net.ll(),
                                width=self.m1_width,
                                height=self.m1_width)
Пример #4
0
    def add_dummy_poly(self):
        """ Add the dummy poly to tx"""

        # dummy poly is added on both side (left & right) of active region
        dummy_poly_width = self.poly_width
        dummy_poly_height = max(ceil(self.poly_minarea / self.poly_width),
                                self.poly_height)
        #SAMIRA  changed 2*self.poly_to_active to 2.5*self.poly_to_active!!
        xoff = max(1.5 * self.poly_to_active, self.well_enclose_active)
        #self.dummy_poly_offset1 = self.active_offset - vector(xoff, 0.5*(dummy_poly_height-self.active.height))
        self.dummy_poly_offset1 = self.active_offset - vector(
            xoff, self.poly_extend_active)

        #dummy poly on left
        self.add_rect(layer="poly",
                      offset=self.dummy_poly_offset1,
                      height=dummy_poly_height,
                      width=dummy_poly_width)

        #dummy poly on right
        #self.dummy_poly_offset2 = self.active_offset + vector(self.active.width+xoff-self.poly_width , -0.5*(dummy_poly_height-self.active.height))
        self.dummy_poly_offset2 = self.active_offset + vector(
            self.active.width + xoff - self.poly_width,
            -self.poly_extend_active)
        #SAMIRA  changed 2*self.poly_to_active to 2.5*self.poly_to_active!!
        self.add_rect(layer="poly",
                      offset=self.dummy_poly_offset2,
                      height=dummy_poly_height,
                      width=dummy_poly_width)
Пример #5
0
def EMSAPSSVER(M, EM, emBits, sLen = 16):
    mHash = SHA.new(M).digest()
    hLen = len(mHash)
    emLen = utils.ceil(emBits, 8)

    if emLen < hLen + sLen + 2 or EM[len(EM) - 1] != '\xbc':
        print "Inconsistent"
        return False

    maskedDB, h = EM[:emLen - hLen - 1], EM[emLen - hLen - 1: -1]

    octets, bits = (8 * emLen - emBits) / 8, (8 * emLen - emBits) % 8
    zero = maskedDB[:octets] + chr(ord(maskedDB[octets]) & ~(255 >>bits))

    for c in zero:
        if c != '\x00':
            return False

    dbMask = MGF(h, emLen - hLen - 1)
    DB = stringXOR(maskedDB, dbMask)
    newByte = chr(ord(DB[octets]) & (255 >> bits))
    DB = ('\x00' * octets) + newByte + DB[octets+1:]

    for c in DB[:emLen - hLen - sLen - 2]:
        if c != '\x00':
            return False

    if DB[emLen - hLen - sLen - 2] != '\x01':
        return False

    salt = DB[-sLen:]
    m_prime = ('\x00' * 8) + mHash + salt
    h_prime = SHA.new(m_prime).digest()

    return h_prime == h
Пример #6
0
def EMSAPSSVER(M, EM, emBits, sLen=16):
    mHash = SHA.new(M).digest()
    hLen = len(mHash)
    emLen = utils.ceil(emBits, 8)

    if emLen < hLen + sLen + 2 or EM[len(EM) - 1] != '\xbc':
        print "Inconsistent"
        return False

    maskedDB, h = EM[:emLen - hLen - 1], EM[emLen - hLen - 1:-1]

    octets, bits = (8 * emLen - emBits) / 8, (8 * emLen - emBits) % 8
    zero = maskedDB[:octets] + chr(ord(maskedDB[octets]) & ~(255 >> bits))

    for c in zero:
        if c != '\x00':
            return False

    dbMask = MGF(h, emLen - hLen - 1)
    DB = stringXOR(maskedDB, dbMask)
    newByte = chr(ord(DB[octets]) & (255 >> bits))
    DB = ('\x00' * octets) + newByte + DB[octets + 1:]

    for c in DB[:emLen - hLen - sLen - 2]:
        if c != '\x00':
            return False

    if DB[emLen - hLen - sLen - 2] != '\x01':
        return False

    salt = DB[-sLen:]
    m_prime = ('\x00' * 8) + mHash + salt
    h_prime = SHA.new(m_prime).digest()

    return h_prime == h
Пример #7
0
    def setup_layout_constants(self):
        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
        first_layer_minwidth = drc("minwidth_{0}".format(
            self.first_layer_name))
        first_layer_minarea = drc("minarea_{0}".format(self.first_layer_name))
        first_layer_enclosure = drc("{0}_enclosure_{1}".format(
            self.first_layer_name, self.via_layer_name))
        first_layer_extend = drc("{0}_extend_{1}".format(
            self.first_layer_name, self.via_layer_name))
        second_layer_minwidth = drc("minwidth_{0}".format(
            self.second_layer_name))
        second_layer_minarea = drc("minarea_{0}".format(
            self.second_layer_name))
        second_layer_enclosure = drc("{0}_enclosure_{1}".format(
            self.second_layer_name, self.via_layer_name))
        second_layer_extend = drc("{0}_extend_{1}".format(
            self.second_layer_name, self.via_layer_name))

        self.first_layer_horizontal_enclosure = max(
            (first_layer_minwidth - self.contact_array_width) / 2,
            first_layer_enclosure)
        self.first_layer_vertical_enclosure = max(
            utils.ceil((first_layer_minarea /
                        (self.contact_array_width +
                         2 * self.first_layer_horizontal_enclosure) -
                        self.contact_array_height) / 2),
            (first_layer_minwidth - self.contact_array_height) / 2,
            first_layer_extend)

        self.second_layer_horizontal_enclosure = max(
            (second_layer_minwidth - self.contact_array_width) / 2,
            second_layer_enclosure)
        self.second_layer_vertical_enclosure = max(
            utils.ceil((second_layer_minarea /
                        (self.contact_array_width +
                         2 * self.second_layer_horizontal_enclosure) -
                        self.contact_array_height) / 2),
            (second_layer_minwidth - self.contact_array_height) / 2,
            second_layer_extend)
Пример #8
0
def from_jd(jd, adj=0):
    '''Calculate Islamic date from Julian day'''

    jd = trunc(jd) + 0.5
    year = trunc(((30 * (jd - EPOCH)) + 10646) / 10631)
    month = min(12, ceil((jd - (29 + to_jd(year, 1, 1, adj=adj))) / 29.5) + 1)
    day = int(jd - to_jd(year, month, 1, adj=adj)) + 1
    return (year, month, day)
Пример #9
0
def MGF(mgfSeed, maskLen):
    hLen = len(SHA.new("").digest())
    if maskLen > pow(2, 32) * hLen:
        print "Mask too long"
        return -1

    T = ""

    for i in range(utils.ceil(maskLen, hLen)):
        C = I2OSP(i, 4)
        T += CryptoBox.generateHash(mgfSeed + C)

    return T[:maskLen]
Пример #10
0
def MGF(mgfSeed, maskLen):
    hLen = len(SHA.new("").digest())
    if maskLen > pow(2, 32) * hLen:
        print "Mask too long"
        return -1

    T = ""

    for i in range(utils.ceil(maskLen, hLen)):
        C = I2OSP(i, 4)
        T += CryptoBox.generateHash(mgfSeed + C)

    return T[:maskLen]
Пример #11
0
    def add_metal_minarea(self, layer, pin):
        """ Adds horizontal metal rail to avoid DRC min_area"""

        if layer == "metal1":
            min_area = self.m1_minarea
        else:
            min_area = self.m2_minarea

        self.add_rect_center(layer=layer,
                             offset=pin,
                             width=ceil(min_area /
                                        contact.m1m2.first_layer_width),
                             height=contact.m1m2.first_layer_width)
Пример #12
0
    def get_context_data(self, **kwargs):
        """
        index => monitor index
        lastDate.l1,l7,l30 => last 1,7,30 days time range
        rg => timerange
        tl => till the end 
        fr => from  the begin
        host => the instance id
        hn => the instance display name
        """
        index = ["cpu", "mem", "disk", "net"]
        now = datetime.datetime.now()
        context = super(IndexView, self).get_context_data(**kwargs)
        instances, m = api.nova.server_list(self.request)
        insLis = [i.to_dict() for i in instances]
        insLis = [[i["id"], i["name"]] for i in insLis]

        lasttime = {}

        l1 = lastDate(now, 1)
        l7 = lastDate(now, 7)
        l30 = lastDate(now, 30)

        lasttime["l1"] = ["l1", l1, 1]
        lasttime["l7"] = ["l7", l7, 7]
        lasttime["l30"] = ["l30", l30, 30]
        rg = "l1"
        tl = ""
        fr = ""

        if insLis:
            c = ceil(insLis[0][0], l1)
            context["host"] = insLis[0][0]
            context["hn"] = insLis[0][1]
            ind = "CPU"
            ret = c.cpu()
        else:
            context["host"] = "no instance"
            context["hn"] = "no instance"
            ind = "no instance"
            ret = ""

        context["ind"] = ind
        context["ret"] = ret
        context["ins"] = insLis
        context["index"] = index
        context["lasttime"] = lasttime
        context["rg"] = rg
        context["tl"] = tl
        context["fr"] = fr
        return context
Пример #13
0
def verifySignature(N, e, message, signature):
    k = numOctets(N)
    modBits = bitSize(N)

    if len(signature) != k:
        print "Invalid signature"
        return

    s = OS2IP(signature)
    m = RSAVP1(N, e, s)
    emLen = utils.ceil((modBits -1), 8)
    EM = I2OSP(m, emLen)
    
    return EMSAPSSVER(message, EM, modBits - 1)
Пример #14
0
def verifySignature(N, e, message, signature):
    k = numOctets(N)
    modBits = bitSize(N)

    if len(signature) != k:
        print "Invalid signature"
        return

    s = OS2IP(signature)
    m = RSAVP1(N, e, s)
    emLen = utils.ceil((modBits - 1), 8)
    EM = I2OSP(m, emLen)

    return EMSAPSSVER(message, EM, modBits - 1)
Пример #15
0
    def writePackedBytesImpl(self, strng, dataType):
        strng = encodeUTF8(strng)
        numBytes = len(strng)
        if numBytes > WATags.PACKED_MAX:
            raise ValueError("too many bytes to nibble-encode: len = " +
                             str(numBytes))

        self.pushByte(dataType)
        self.pushByte((128 if (numBytes % 2) > 0 else 0) | ceil(numBytes / 2))

        for i in range(numBytes // 2):
            self.pushByte(
                self.packBytePair(dataType, strng[2 * i], str[2 * i + 1]))
        if (numBytes % 2) != 0:
            self.pushByte(
                self.packBytePair(dataType, strng[numBytes - 1], "\x00"))
Пример #16
0
    def starter_connections(self):
        """ Connections in pull_up_pulll_down network of starter gate"""

        #connect output of inv1 to input B of nand2
        self.add_path("poly", [
            self.starter_inst.get_pin("Gp0").lc(),
            self.starter_inst.get_pin("Gn0").lc()
        ])
        self.add_path("metal1", [
            self.starter_inst.get_pin("Sp0").lc(),
            self.starter_inst.get_pin("Sn0").lc()
        ])
        for pin in ["Dn2", "Dn1", "Dn0", "Dp0"]:
            self.add_rect_center(layer="metal1",
                                 offset=self.starter_inst.get_pin(pin).cc(),
                                 width=ceil(self.m1_minarea /
                                            contact.m1m2.width),
                                 height=contact.m1m2.width)
Пример #17
0
def display_accuracy(clf_string, clf):
    """
    Convenience method for printing results
    :param clf_string: name of classifier
    :param clf: classify
    :return: prints results to standard output
    """
    if clf is k_means:
        param_grid = {'n_init': range(1, 11)}
    else:
        param_grid = {
            'max_depth': range(1, max_tree_height(105)),
            'min_samples_split': range(2, ceil(105 / 2)),
            'min_samples_leaf': range(1, 11)
        }

    scores = average_scores(clf,
                            param_grid,
                            metrics=[accuracy_score, fowlkes_mallows_score])
    scores[0] = [round(100 * score, 2) for score in scores[0]]
    scores[1] = [round(score, 2) for score in scores[1]]

    # keep lines the same length
    length = len(clf_string)
    indent = " " * (45 - length)
    # initial accuracy
    print("{} Accuracy:{}{}%".format(clf_string, indent, scores[0][0]))
    indent = " " * (33 - length)
    # optimized accuracy
    print("Grid Search {} Accuracy:{}{}%".format(clf_string, indent,
                                                 scores[0][1]))
    indent = " " * (38 - length)
    # initial fowlkes_mallows_score
    print("{} Fowlkes Mallows:{}{}".format(clf_string, indent, scores[1][0]))
    indent = " " * (26 - length)
    # optimized fowlkes_mallows_score
    print("Grid Search {} Fowlkes Mallows:{}{}".format(clf_string, indent,
                                                       scores[1][1]))
Пример #18
0
    def system_simulator(x, d, pvt, t0, tf, pi_array):

        T = tf - t0
        # use the ceiling function from utils to detect and fix
        # floating point issues
        num_segments = int(U.ceil(T / sys.delta_t, np.ceil))
        # num_points = num_segments + 1
        trace = traces.Trace(sys.num_dims, num_segments + 1)
        t = t0

        #print('num_segments:', num_segments)
        # need the below try catch shenanigans to print the error message,
        # because matlab does not.
        #try:
        #    raise e
        for i in range(num_segments):
            pi = pi_array[i]
            (t_, x_, d_, pvt_) = step_sim(t, x, d, pvt, pi)
            trace.append(t=t, x=x, d=d, pi=pi)
            (t, x, d, pvt) = (t_, x_, d_, pvt_)

        trace.append(t=t, x=x, d=d, pi=pi)
        return trace
Пример #19
0
def EMSAPSSENC(M, emBits, sLen=16):
    mHash = SHA.new(M).digest()
    hLen = len(mHash)
    emLen = utils.ceil(emBits, 8)

    if emLen < hLen + sLen + 2:
        print "Encoding error"
        return

    salt = I2OSP(utils.gen_random(sLen * 8), sLen)
    m_prime = '\x00' * 8 + mHash + salt
    H = SHA.new(m_prime).digest()
    PS = '\x00' * (emLen - sLen - hLen - 2)
    DB = PS + '\x01' + salt
    dbMask = MGF(H, emLen - hLen - 1)
    maskedDB = stringXOR(DB, dbMask)
    octets, bits = (8 * emLen - emBits) / 8, (8 * emLen - emBits) % 8
    maskedDB = ('\x00' * octets) + maskedDB[octets:]
    newByte = chr(ord(maskedDB[octets]) & (255 >> bits))
    maskedDB = maskedDB[:octets] + newByte + maskedDB[octets + 1:]
    EM = maskedDB + H + '\xbc'

    return EM
Пример #20
0
def EMSAPSSENC(M, emBits, sLen = 16):
    mHash = SHA.new(M).digest()
    hLen = len(mHash)
    emLen = utils.ceil(emBits, 8)
    
    if emLen < hLen + sLen + 2:
        print "Encoding error"
        return
    
    salt = I2OSP(utils.gen_random(sLen * 8), sLen)
    m_prime = '\x00' * 8 + mHash + salt
    H = SHA.new(m_prime).digest()
    PS = '\x00' * (emLen - sLen - hLen - 2)
    DB = PS + '\x01' + salt
    dbMask = MGF(H, emLen - hLen - 1)
    maskedDB = stringXOR(DB, dbMask)
    octets, bits = (8 * emLen - emBits) / 8, (8 * emLen - emBits) % 8
    maskedDB = ('\x00' * octets) + maskedDB[octets:]
    newByte = chr(ord(maskedDB[octets]) & (255 >> bits))
    maskedDB = maskedDB[:octets] + newByte + maskedDB[octets+1:]
    EM = maskedDB + H + '\xbc'

    return EM
Пример #21
0
    def connect_to_bitlines(self):
        """ Route bitlines to pmoses"""
        
        pmos3_s = self.pmos3_inst.get_pin("S")
        pmos2_s = self.pmos2_inst.get_pin("S")
        pmos1_s = self.pmos1_inst.get_pin("S")
        
        edge = abs(drc["metal1_extend_via1"] - drc["metal2_extend_via1"])
        self.add_path("metal1", [pmos1_s.uc(), self.pmos3_inst.get_pin("D").uc()], 
                      width= contact.m1m2.first_layer_height)
        
        pos1=(pmos3_s.uc().x-0.5*contact.active.height, pmos3_s.by()-0.5*self.m1_width)
        pos2=(pmos2_s.uc().x+0.5*contact.m1m2.height-edge, pmos3_s.by()-0.5*self.m1_width)
        self.add_path("metal1", [pos1, pos2])

        self.add_via_center(self.m1_stack, (pmos2_s.uc().x, pmos2_s.lc().y), rotate=90)
        self.add_via_center(self.m1_stack, (pmos1_s.uc().x, pmos1_s.lc().y), rotate=90)
        self.add_via_center(self.m1_stack, (pmos2_s.uc().x, pmos3_s.by()), rotate=90)
        
        height = ceil(self.m1_minarea/contact.m1m2.first_layer_height)
        self.add_rect_center(layer="metal1", 
                             offset = (pmos2_s.uc().x, pmos2_s.by()-0.5*height),
                             width= contact.m1m2.first_layer_height,
                             height= height)
Пример #22
0
    def get_context_data(self, **kwargs):
        index = ["cpu", "mem", "disk", "net"]
        now = datetime.datetime.utcnow()
        context = super(HostView, self).get_context_data(**kwargs)
        hid = kwargs["hostid"]
        ind = self.request.GET.get("index").lower()
        hn = self.request.GET.get("hn")
        instances, m = api.nova.server_list(self.request)
        insLis = [i.to_dict() for i in instances]
        insLis = [[i["id"], i["name"]] for i in insLis]

        lasttime = {}

        l1 = lastDate(now, 1)
        l7 = lastDate(now, 7)
        l30 = lastDate(now, 30)

        lasttime["l1"] = ["l1", l1, 1]
        lasttime["l7"] = ["l7", l7, 7]
        lasttime["l30"] = ["l30", l30, 30]
        rg = ""
        tl = ""
        fr = ""

        if hn == "no instance":
            ret = ""

        elif self.request.GET.has_key(
                "rg") and not self.request.GET.has_key("tl"):
            rg = self.request.GET.get("rg")
            lastd = lasttime[rg][1]
            #print lastd
            c = ceil(hid, lastd)
            indfuc = getattr(c, ind)
            ret = indfuc()

        elif self.request.GET.has_key("tl") and self.request.GET.has_key("fr"):
            tl = self.request.GET.get("tl")
            fr = self.request.GET.get("fr")
            tl1 = ptime(tl)
            fr1 = ptime(fr)
            c = ceil(hid, (tl1, fr1))
            indfuc = getattr(c, ind)
            ret = indfuc()
        else:
            c = ceil(hid, l1)
            indfuc = getattr(c, ind)
            ret = indfuc()
            rg = "l1"

        #print "====>", ret
        #print "====>", m

        context["host"] = hid
        context["hn"] = hn
        context["ind"] = ind
        context["ret"] = ret
        context["ins"] = insLis
        context["index"] = index
        context["lasttime"] = lasttime
        context["rg"] = rg
        context["tl"] = tl
        context["fr"] = fr
        return context
Пример #23
0
    def ptx_connections(self):
        """ Connections of NMOS and PMOS  terminals in stopper gate """

        #connect gates and source of nmos1 and pmos1
        self.add_path(
            "poly",
            [self.nmos1.get_pin("G").lc(),
             self.pmos1.get_pin("G").lc()])
        self.add_path(
            "metal1",
            [self.nmos1.get_pin("S").lc(),
             self.pmos1.get_pin("S").lc()])

        #connect gates and drain of nmos2 and pmos2
        self.add_path(
            "poly",
            [self.nmos2.get_pin("G").lc(),
             self.pmos2.get_pin("G").lc()])
        self.add_path(
            "metal1",
            [self.nmos2.get_pin("D").lc(),
             self.pmos2.get_pin("D").lc()])

        #connect gate of nmos1 to source of pmos2
        pos1 = vector(
            self.nmos1.get_pin("G").lc().x + 1.5 * self.m_pitch("m1"),
            self.nmos1.get_pin("G").uy())
        shift = contact.m1m2.width + contact.poly.height
        self.add_contact(self.poly_stack, (pos1.x + shift, pos1.y), rotate=90)
        self.add_via(self.m1_stack, pos1)

        pos2 = self.pmos2.by() - self.m1_space
        pos3 = self.pmos2.get_pin("S").uc()
        self.add_wire(self.m1_stack, [(pos1.x + 0.5 * self.m2_width, pos1.y),
                                      (pos1.x, pos2), (pos3.x, pos2), pos3])
        self.add_via_center(self.m1_stack,
                            self.pmos2.get_pin("S").cc(),
                            rotate=90)

        width = max(ceil(self.m1_minarea / contact.poly.width), shift)
        self.add_rect(layer="metal1",
                      offset=pos1,
                      width=width,
                      height=contact.poly.width)

        #connect gate of nmos2 to source of pmos1
        pin = self.nmos2.get_pin("G")
        pos1 = vector(pin.lc().x + 2.5 * self.m_pitch("m1"),
                      pin.by() - contact.m1m2.height)
        yoff = pin.by() - contact.poly.width
        self.add_contact(self.poly_stack, (pos1.x + shift, yoff), rotate=90)
        self.add_via(self.m1_stack, pos1)
        pos2 = self.pmos1.uy() + self.m1_space
        pos3 = self.pmos1.get_pin("D").uc()
        self.add_wire(
            self.m1_stack,
            [(pos1.x + 0.5 * self.m2_width, pos1.y + contact.m1m2.height),
             (pos1.x, pos2), (pos3.x, pos2), pos3])
        self.add_via_center(self.m1_stack,
                            self.pmos1.get_pin("D").cc(),
                            rotate=90)
        self.add_rect(layer="metal1",
                      offset=(pos1.x, yoff),
                      width=width,
                      height=contact.poly.width)

        #connect drain of nmos1 and source of nmos2 together and to gnd of nand1
        self.add_path(
            "metal1",
            [self.nmos1.get_pin("D").uc(),
             self.nmos2.get_pin("S").uc()])
        pos1 = self.nand1_inst.get_pin("gnd").lc()
        pos2 = vector(self.nand1_inst.rx() + 2 * self.m_pitch("m1"), pos1.y)
        pos3 = vector(pos2.x, pos2.y - self.m_pitch("m1"))
        pos5 = self.nmos1.get_pin("D").uc()
        pos4 = vector(pos5.x, pos3.y)

        self.add_wire(self.m1_stack, [pos1, pos2, pos3, pos4])
        self.add_path("metal2", [pos3, pos4, pos5])
        self.add_via_center(self.m1_stack,
                            self.nmos1.get_pin("D").cc(),
                            rotate=90)

        #add metal1 in drain of pmos1 and source of pmos2 to avoid min_area violation
        for metal in ["metal1", "metal2"]:
            for off in [
                    self.pmos1.get_pin("D").cc(),
                    self.pmos2.get_pin("S").cc()
            ]:
                self.add_rect_center(layer=metal,
                                     offset=off,
                                     width=ceil(self.m1_minarea /
                                                contact.m1m2.width),
                                     height=contact.m1m2.width)

        #connect nand1 out to nmos1 gate
        pin = self.nmos1.get_pin("G")
        pos1 = self.nand1_inst.get_pin("Z").lc()
        pos2 = vector(self.nmos1.lx() - 2 * self.m1_space, pos1.y)
        pos3 = vector(pos2.x, pin.by())
        self.add_path("metal1", [pos1, pos2, pos3])
        self.add_path("poly", [pin.lc(), (pos2.x, pin.lc().y)])
        self.add_contact_center(self.poly_stack, (pos2.x, pos3.y))

        #connect nand2 out to nmos2 gate
        pin = self.nmos2.get_pin("G")
        pos1 = self.nand2_inst.get_pin("Z").lc()
        pos2 = vector(self.nmos2.lx() - 2 * self.m1_space, pos1.y)
        pos3 = vector(pos2.x, pin.by())
        self.add_path("metal1", [pos1, pos2, pos3])
        self.add_path("poly", [pin.lc(), (pos2.x, pin.lc().y)])
        self.add_contact_center(self.poly_stack, (pos2.x, pos3.y))

        if info["tx_dummy_poly"]:
            shift1 = vector(self.pmos.dummy_poly_offset1.y,
                            self.pmos.dummy_poly_offset1.x)
            shift2 = vector(self.pmos.dummy_poly_offset2.y,
                            self.pmos.dummy_poly_offset2.x)
            offset = [
                self.nmos1.ll(),
                self.nmos2.ll(),
                self.pmos1.ll(),
                self.pmos2.ll()
            ]
            for off in offset:
                for i in [off + shift1, off + shift2]:
                    self.add_rect(layer="poly",
                                  offset=i,
                                  width=ceil(drc["minarea_poly_merge"] /
                                             self.poly_width),
                                  height=self.poly_width)
Пример #24
0
def to_jd(year, month, day, adj=0):
    '''Determine Julian day count from Islamic date'''
    return (day + ceil(29.5 * (month - 1)) + (year - 1) * 354 + trunc(
        (3 + (11 * year)) / 30) + EPOCH) - 1 + adj
Пример #25
0
    def add_ptx(self):
        """ Add PMOS and NMOS to the layout at the upper-most and lowest position """

        # place PMOS right to nwell contact
        x_off = self.well_enclose_active + 3*contact.well.height + \
                self.implant_enclose_body_active + drc["extra_to_poly"] + self.pmos.height
        #if drc["extra_to_poly"] != 0:
        #x_off = x_off + contact.well.height

        y_off = self.top_bottom_space

        self.pmos_inst = {}
        self.nmos_inst = {}

        for i in range(self.num_pmos):
            pmos_pos = vector(x_off, y_off + i * self.overlap_offset)
            self.pmos_inst[i] = self.add_inst(
                name="pullup-down_pmos{0}".format(i),
                mod=self.pmos,
                offset=pmos_pos,
                rotate=90)
            if i == 0:
                self.connect_inst(
                    ["Dp{0}".format(i), "Gp{0}".format(i), "Sp0", "vdd"])
            else:
                self.connect_inst([
                    "Dp{0}".format(i), "Gp{0}".format(i),
                    "Dp{0}".format(i - 1), "vdd"
                ])

        # place NMOS right to pmos
        x_off = self.pmos_inst[0].rx() + self.poly_space + self.nmos.height
        for i in range(self.num_nmos):
            nmos_pos = vector(x_off, y_off + i * self.overlap_offset)
            self.nmos_inst[i] = self.add_inst(
                name="pullup-down_nmos{0}".format(i),
                mod=self.nmos,
                offset=nmos_pos,
                rotate=90)
            if i == 0:
                self.connect_inst(
                    ["Dn{0}".format(i), "Gn{0}".format(i), "Sn0", "gnd"])
            else:
                self.connect_inst([
                    "Dn{0}".format(i), "Gn{0}".format(i),
                    "Dn{0}".format(i - 1), "gnd"
                ])

        # This should be placed at the top of the NMOS well
        nwell_pos = vector(0, 0)
        nwell_width = max(self.nmos_inst[0].lx(),
                          ceil(self.well_minarea / self.height))
        if ceil(self.well_minarea / self.height) > self.nmos_inst[0].lx():
            nwell_pos = vector(
                -(ceil(self.well_minarea / self.height) -
                  self.nmos_inst[0].lx()), 0)
        pimplant_pos = vector(self.pmos_inst[0].lx(), 0)

        # This should be placed below the PMOS well
        pwell_pos = vector(self.nmos_inst[0].lx(), 0)
        pwell_width= self.nmos.height + ceil(self.active_minarea/contact.well.height) + \
                     drc["extra_to_poly"]+self.implant_enclose_body_active+self.well_enclose_active
        nimplant_pos = vector(self.nmos_inst[0].lx(), 0)

        self.width = nwell_width + pwell_width

        if info["has_nwell"]:
            self.add_rect(layer="nwell",
                          offset=nwell_pos,
                          width=nwell_width,
                          height=self.height)
        if info["has_pimplant"]:
            self.add_rect(layer="pimplant",
                          offset=pimplant_pos,
                          width=self.nmos_inst[0].lx() - pimplant_pos.x,
                          height=self.height)

        if info["has_pwell"]:
            # This should cover pwell-contact and nmos
            self.add_rect(layer="pwell",
                          offset=pwell_pos,
                          width=pwell_width,
                          height=self.height)
        if info["has_nimplant"]:
            self.add_rect(layer="nimplant",
                          offset=nimplant_pos,
                          width=self.nmos.height,
                          height=self.height)

        vt_offset = vector(self.pmos_inst[0].lx(), 0)
        self.add_rect(layer="vt",
                      offset=vt_offset,
                      layer_dataType=layer["vt_dataType"],
                      width=self.nmos_inst[0].rx() - self.pmos_inst[0].lx(),
                      height=self.height)

        if info["tx_dummy_poly"]:
            width = self.nmos_inst[0].rx() - self.pmos_inst[0].lx(
            ) - 2 * self.poly_extend_active
            pos1 = self.pmos_inst[0].ll() + vector(self.poly_extend_active, 0)
            pos2 = self.nmos_inst[0].ll() + vector(self.poly_extend_active, 0)
            self.add_rect(layer="poly",
                          offset=pos1,
                          width=width,
                          height=self.poly_width)

            if abs(self.num_nmos - self.num_pmos) < 3:
                yoff = max(self.nmos_inst[self.num_nmos - 1].uy(),
                           self.pmos_inst[self.num_pmos - 1].uy())
                pos3 = vector(pos1.x, yoff)
                self.add_rect(layer="poly",
                              offset=pos3,
                              width=width,
                              height=self.poly_width)

            else:
                pos = [(pos1.x, self.pmos_inst[self.num_pmos - 1].uy()),
                       (pos2.x, self.nmos_inst[self.num_nmos - 1].uy())]
                for off in pos:
                    self.add_rect(layer="poly",
                                  offset=off,
                                  width=self.pmos.poly_height,
                                  height=max(
                                      self.poly_width,
                                      ceil(drc["minarea_poly_merge"] /
                                           self.pmos.poly_height)))
Пример #26
0
    def render(self):
        if (utils.sum_points_inside_flat_poly(*self.parent.canvas) <= 4):
            return
        color_profile = random.choice(self.colors)

        min_x = utils.floor(min([p.x for p in self.parent.canvas]))
        max_x = utils.ceil(max([p.x for p in self.parent.canvas]))
        min_z = utils.floor(min([p.z for p in self.parent.canvas]))
        max_z = utils.ceil(max([p.z for p in self.parent.canvas]))
        min_y = utils.floor(min([p.y for p in self.parent.canvas]))

        # Cut the canvas into quarters and fill one quarter with colors.
        # Then, copy that quarter into the other three quarters.
        width = utils.floor(((max_x - min_x + 1) + 1) / 2)
        depth = utils.floor(((max_z - min_z + 1) + 1) / 2)

        points = [[-1 for j in xrange(depth)] for i in xrange(width)]
        points_left = []
        for i in xrange(width):
            for j in xrange(depth):
                points_left.append((i, j))
        bounds = utils.Box(Vec(0, 0, 0), width, 1, depth)
        p = Vec(0, 0, 0)
        color_num = 0
        prev_dir = random.randint(0, 3)
        next_dir = random.randint(0, 3)
        while len(points_left) > 0:
            # pick random starting point and walk around the matrix
            point_index = random.randint(0, len(points_left) - 1)
            p = Vec(points_left[point_index][0], 0,
                    points_left[point_index][1])

            while (bounds.containsPoint(p) and points[p.x][p.z] == -1
                   and len(points_left) > 0):
                points[p.x][p.z] = color_num
                points_left.remove((p.x, p.z))

                # pick random direction to walk, try to keep walking same
                # direction
                if random.randint(0, self._walk_weight) != 0:
                    next_dir = prev_dir
                else:
                    while next_dir == prev_dir:
                        next_dir = random.randint(0, 3)
                if next_dir == 0:  # right
                    p += Vec(1, 0, 0)
                elif next_dir == 1:  # down
                    p += Vec(0, 0, 1)
                elif next_dir == 2:  # left
                    p += Vec(-1, 0, 0)
                else:  # up
                    p += Vec(0, 0, -1)
                prev_dir = next_dir
            color_num = (color_num + 1) % len(color_profile)

        for j in xrange(max_z - min_z + 1):
            for i in xrange(max_x - min_x + 1):
                p = self.parent.loc + Vec(min_x + i, min_y, min_z + j)
                self.parent.parent.setblock(p, self.mat)
                if i < width:
                    i_adj = i
                else:
                    i_adj = 2 * width - 1 - i
                if j < depth:
                    j_adj = j
                else:
                    j_adj = 2 * depth - 1 - j
                self.parent.parent.blocks[p].data = \
                    color_profile[points[i_adj][j_adj]]

        if not self.ruin:
            return
        # this chunk of code is copied from CheckerRug's render() method
        pn = perlin.SimplexNoise(256)
        c = self.parent.canvasCenter()
        y = self.parent.canvasHeight()
        r = random.randint(1, 1000)
        maxd = max(1, self.parent.canvasWidth(), self.parent.canvasLength())
        for x in utils.iterate_points_inside_flat_poly(*self.parent.canvas):
            p = x + self.parent.loc
            d = ((Vec2f(x.x, x.z) - c).mag()) / maxd
            n = (pn.noise3((p.x + r) / 4.0, y / 4.0, p.z / 4.0) + 1.0) / 2.0
            if (n < d):
                self.parent.parent.setblock(p, materials._floor)
                self.parent.parent.blocks[p].data = 0
Пример #27
0
    def connect_modules(self):
        """ connect in and out pins to nfet and pfet terminals modules """

        #output routing
        self.out=vector(self.pfet1.rx()+2*self.m_pitch("m1"), self.pfet1.get_pin("D").lc().y)
        pos1= self.nfet1.get_pin("D").lc()
        mid_pos1 = (self.nfet1.rx()+0.5*self.m1_width, pos1.y)
        mid_pos2 = (self.nfet1.rx()+0.5*self.m1_width, self.out.y)
        self.add_path("metal1", [pos1, mid_pos1, mid_pos2,self.out])

        #input 1 routing        
        self.in1=vector(self.nfet1.lx()-2*self.m_pitch("m1"), self.nfet1.get_pin("S").lc().y)
        self.add_path("metal1", [self.pfet1.get_pin("S").uc(), self.in1 ])

        #input 2 routing
        pos1 = self.pfet2.get_pin("D").lc()
        self.in2=vector(self.nfet2.lx()-2*self.m_pitch("m1"), pos1.y)
        mid_pos2 = self.nfet2.get_pin("D").uc()
        mid_pos1 = (mid_pos2.x, pos1.y)
        mid_pos3 = (mid_pos2.x, pos1.y)
        self.add_path("metal1", [pos1, mid_pos1, mid_pos2, mid_pos3, self.in2])
        
        #connect gates: nmos2 to pmos1
        pos1=vector(self.nfet2.lx()-self.m_pitch("m1"), self.nfet2.get_pin("G").lc().y)
        self.add_path("poly", [pos1, self.pfet1.get_pin("G").lc()])
        
        pos2=vector(pos1.x, self.nfet2.get_pin("G").by()-contact.poly.height)
        self.add_contact(self.poly_stack, (pos2.x, pos2.y+self.via_shift("co")))
        
        self.up_down_off= vector(pos1.x-contact.m1m2.width, pos2.y)
        self.add_via(self.m1_stack, self.up_down_off)
        height1 = max(contact.poly.height, contact.m1m2.height-self.via_shift("v1"))
        width1 =  max(ceil(self.m1_minarea/height1), contact.poly.width+2*contact.m1m2.width)
        self.add_rect(layer= "metal1", 
                      offset= self.up_down_off-(0.5*contact.m1m2.width, 0) , 
                      width= width1, 
                      height= height1)
        
        #connect gates nmos1 to pmos2
        pos1=self.nfet1.get_pin("G").lc()
        pos11=vector(self.nfet1.rx()+self.m1_width, pos1.y)
        pos12=vector(pos11.x, pos1.y-self.poly_to_active)
        pos2= vector(self.pfet2.rx() + 2*self.m_pitch("m1")-self.implant_enclose_poly, pos12.y)
        self.add_path("poly", [pos1, pos11, pos12, pos2])
        pos4= self.pfet2.get_pin("G").lc()
        pos3=vector(pos2.x, pos4.y)
        self.add_path("poly", [pos3, pos4])
        
        pos5= vector(pos2.x-contact.poly.width, pos1.y-self.poly_to_active)
        pos6=vector(pos5.x, pos4.y+self.poly_width)
        self.add_rect(layer="poly", 
                      offset=(pos5.x, pos4.y), 
                      width=contact.poly.width, 
                      height=2*self.poly_width)
        
        self.add_contact(self.poly_stack, pos5)
        self.add_contact(self.poly_stack, pos6)
        
        self.add_via(self.m1_stack, (pos2.x-contact.poly.width-contact.m1m2.width, pos5.y))
        self.add_via(self.m1_stack, (pos2.x-contact.poly.width-contact.m1m2.width, pos6.y))
        
        self.updown_boff= vector(pos2.x-contact.poly.width-self.m2_width, pos5.y)
        offset = [self.updown_boff-(contact.m1m2.width,0),(self.updown_boff.x-contact.m1m2.width,pos6.y)]
        for off in offset:
            self.add_rect(layer= "metal1", offset= off, width= width1, height= height1)
        
        layers=[]
        if info["has_nimplant"]:
            layers.append("nimplant")
        if info["has_pwell"]:
            layers.append("pwell")

        for layer in layers:
            self.add_rect(layer= layer, 
                          offset= (self.nfet1.lx()-2*self.m_pitch("m1"), 0), 
                          width= self.nmos.height+2*self.m_pitch("m1") , 
                          height= self.nmos.width+2*self.nmos_overlap)

        layers=[]
        if info["has_pimplant"]:
            layers.append("pimplant")
        if info["has_nwell"]:
            layers.append("nwell")

        for layer in layers:
             self.add_rect(layer=layer, 
                           offset=(self.nfet1.rx(), 0), 
                           width = self.pmos.height+2*self.m_pitch("m1")+self.poly_space , 
                           height = self.pmos.width+2*self.nmos_overlap)


        #connect all vt layers to avoid min-space vt DRC
        vt_width = self.pfet2.rx() - self.nfet1.lx()
        vt_height = self.pfet2.uy() - self.nfet1.by()
        self.add_rect(layer="vt",
                      offset=self.nfet1.ll(),
                      layer_dataType = 164,
                      width=vt_width,
                      height=vt_height)
    
        width = ceil(drc["minarea_poly_merge"]/self.poly_width)
        offset=[self.nfet1.lr()-(width,0), 
                self.nfet2.ur()-(width,0), 
                self.pfet1.ll()-(0, 0.5*self.poly_width), 
                self.pfet2.ul()-(0, self.poly_width)]
        if info["tx_dummy_poly"]:
             for off in offset:
                 self.add_rect(layer="poly", offset=off, width = width, height = self.poly_width)
Пример #28
0
    def setup_layout_constants(self):
        """ Pre-compute some handy layout parameters. """

        if self.num_contacts == None:
            self.num_contacts = self.calculate_num_contacts()

        # Determine layer types needed
        if self.tx_type == "nmos":
            self.implant_type = "n"
            self.well_type = "p"
        elif self.tx_type == "pmos":
            self.implant_type = "p"
            self.well_type = "n"
        else:
            self.error("Invalid transitor type.", -1)

        # This is not actually instantiated but used for calculations
        self.active_contact = contact(layer_stack=("active", "contact",
                                                   "metal1"),
                                      dimensions=(1, self.num_contacts))

        # The contacted poly pitch
        self.poly_pitch = max(
            2 * self.contact_to_gate + self.contact_width + self.poly_width,
            self.poly_space)

        # This is the distance from the edge of poly to the contacted end of active
        self.end_to_poly = max(
            self.active_enclose_contact + self.contact_width +
            self.contact_to_gate, self.active_enclose_gate)

        # The contacted poly pitch
        self.contact_pitch = 2 * self.contact_to_gate + self.contact_width + self.poly_width

        # Active height is just the transistor width
        self.active_height = self.tx_width

        # Poly height must include poly extension over active
        self.poly_height = self.active_height + 2 * self.poly_extend_active

        # Active width is determined by enclosure on both ends and contacted pitch,
        # at least one poly and n-1 poly pitches
        self.active_width = 2 * self.end_to_poly + self.poly_width + (
            self.mults - 1) * self.poly_pitch

        if ((self.active_width * self.active_height) < drc["minarea_active"]
                and self.min_area):
            end_to_poly = ceil(
                drc["minarea_active"] /
                (2 * self.active_height)) - (self.poly_width / 2)
            self.active_width = 2 * end_to_poly + self.poly_width

        self.active_offset = vector(self.well_enclose_active,
                                    self.well_enclose_active)
        # Well enclosure of active, ensure minwidth as well
        if info["has_{}well".format(self.well_type)]:
            self.cell_well_width = max(
                self.active_width + 2 * self.well_enclose_active,
                self.well_width)
            self.cell_well_height = max(
                self.poly_height,
                self.active_height + 2 * self.well_enclose_active,
                self.well_width)
            self.cell_vt_width = self.active_width + 2 * drc["vt_extend_active"]
            self.cell_vt_height = self.active_height + 2 * drc[
                "vt_extend_active"]
            self.width = max(self.cell_well_width, self.cell_vt_width)
            self.height = max(self.cell_well_height, self.cell_vt_height)

        else:
            # If no well, use the boundary of the active and poly
            self.cell_well_width = self.active_width + 2 * self.well_enclose_active
            self.cell_well_height = max(
                self.poly_height,
                self.active_height + 2 * self.well_enclose_active)
            self.cell_vt_width = self.active_width + 2 * drc["vt_extend_active"]
            self.cell_vt_height = self.active_height + 2 * drc[
                "vt_extend_active"]
            self.width = max(self.cell_well_width, self.cell_vt_width)
            self.height = max(self.poly_height, self.cell_vt_height)

        if info["tx_dummy_poly"]:
            self.height = max(self.height,
                              ceil(self.poly_minarea / self.poly_width))

        # This is the center of the first active contact offset (centered vertically)
        y_shift = max(
            self.active_enclose_contact, self.active_enclose_gate -
            self.contact_width - self.contact_to_gate)
        self.contact_offset = self.active_offset + vector(
            y_shift + 0.5 * self.contact_width, 0.5 * self.active_height)
Пример #29
0
    def add_well_and_wellcontact(self):
        """Adds a nwell tap to connect to the vdd rail"""

        nwell_contact = vector(self.width-self.well_enclose_active, self.well_enclose_active)
        
        if info["has_nwell"]:
            nwell_type = "n"
        else:
            nwell_type = None

        if info["has_nimplant"]:
            nimplant_type = "n"
        else:
            nimplant_type = None

        
        self.add_contact(layers=("active", "contact", "metal1"),
                         offset=nwell_contact,
                         rotate=90,
                         implant_type=nimplant_type, 
                         well_type=nwell_type, 
                         add_extra_layer=info["well_contact_extra"])
        active_width = self.active_minarea/contact.well.width
        active_off = vector(nwell_contact.x-active_width, nwell_contact.y)
        self.add_rect(layer="active",
                      offset=active_off,
                      width=active_width,
                      height=contact.well.width)
        extra_off = active_off-vector(self.extra_enclose, self.extra_enclose)
        extra_width = self.width-active_off.x+self.extra_enclose
        extra_height = max(contact.well.width + 2*self.extra_enclose, ceil(self.extra_minarea/extra_width))
        self.add_rect(layer="extra_layer",
                      layer_dataType = layer["extra_layer_dataType"],
                      offset= extra_off,
                      width= extra_width,
                      height= extra_height)
        
        pos1=(self.width-0.5*contact.m1m2.width, self.vdd_position.y)
        pos2=(nwell_contact.x-contact.well.height,nwell_contact.y+0.5*contact.well.width)
        self.add_path("metal1", [pos1, pos2], width=contact.m1m2.width)

        #adding nwell to cover all pmoses and nwell contact
        x_off =  self.width-2*self.well_enclose_active-active_width
        if info["has_nwell"]:
            self.add_rect(layer="nwell",
                          offset=vector(0,0),
                          width=self.width,
                          height=self.height)
        
        
        if info["has_pimplant"]:
            # pimplant for pmoses
            self.add_rect(layer="pimplant",
                          offset=vector(0,0),
                          width=x_off,
                          height=self.height)
            self.add_rect(layer="pimplant",
                          offset=vector(x_off,self.pmos2_inst.by()),
                          width=self.width-x_off,
                          height=self.height-self.pmos2_inst.by())

        if info["has_nimplant"]:
            # nimplant for nwell contact
            self.add_rect(layer="nimplant",
                          offset=vector(x_off,0),
                          width=self.width-x_off,
                          height=self.pmos2_inst.by())


        # pimplant for pmoses
        self.add_rect(layer="vt",
                      offset=vector(0,0),
                      layer_dataType = layer["vt_dataType"],
                      width=x_off,
                      height=self.height)
        self.add_rect(layer="vt",
                      offset=vector(x_off,self.pmos2_inst.by()),
                      layer_dataType = layer["vt_dataType"],
                      width=self.width-x_off,
                      height=self.height-self.pmos2_inst.by())
Пример #30
0
    def add_well_contacts(self):
        """ Add n/p well taps to the layout and connect to supplies """

        layer_stack = ("active", "contact", "metal1")
        nm_xoff = self.well_enclose_active
        nw_yoff = self.height - contact.well.height-\
                 max(self.well_enclose_active, self.active_to_active-0.5*(self.active_to_active-contact.m1m2.width))
        nw_contact_off = vector(nm_xoff, nw_yoff)

        if info["has_nimplant"]:
            nimplant_type = "n"
        else:
            nimplant_type = None

        if info["has_nwell"]:
            nwell_type = "n"
        else:
            nwell_type = None

        self.add_contact(layers=layer_stack,
                         offset=(nw_contact_off.x + contact.active.height,
                                 nw_contact_off.y),
                         implant_type=nimplant_type,
                         well_type=nwell_type,
                         rotate=90,
                         add_extra_layer=info["well_contact_extra"])

        pw_contact_off = vector(
            self.nmos_inst[0].rx() + self.implant_enclose_body_active +
            drc["extra_to_poly"], self.well_enclose_active)
        if info["has_pimplant"]:
            pimplant_type = "p"
        else:
            pimplant_type = None

        if info["has_pwell"]:
            pwell_type = "p"
        else:
            pwell_type = None

        self.add_contact(layers=layer_stack,
                         offset=(pw_contact_off.x + contact.active.height,
                                 pw_contact_off.y),
                         implant_type=pimplant_type,
                         well_type=pwell_type,
                         rotate=90,
                         add_extra_layer=info["well_contact_extra"])

        self.active_height = contact.well.width
        self.active_width = ceil(self.active_minarea / self.active_height)

        active_off1 = nw_contact_off - vector(
            0, self.active_height - contact.well.first_layer_width)
        metal_off1 = nw_contact_off + vector(0, self.active_enclose_contact)
        metal_height1 = self.height - nw_contact_off.y - self.active_enclose_contact
        pimplant_off = (0, 0)

        extra_height1 = extra_height2 = self.height - active_off1.y + self.extra_enclose
        extra_width1 = max(
            ceil(self.extra_minarea / extra_height1),
            active_off1.x + self.active_width + self.extra_enclose)
        extra_off1 = (0, self.height - extra_height1)

        active_off2 = pw_contact_off
        metal_off2 = (pw_contact_off.x, 0)
        metal_height2 = pw_contact_off.y + self.active_enclose_contact + self.m1_width
        nimplant_off = (self.nmos_inst[0].rx(), 0)
        extra_off2 = (self.nmos_inst[0].rx() + drc["extra_to_poly"], 0)
        extra_width2 = max(
            self.width - self.nmos_inst[0].rx() - drc["extra_to_poly"],
            extra_width1)

        implant_width = max(self.well_enclose_active+self.active_width+\
                        self.implant_enclose_body_active, extra_width2) +2*drc["extra_to_poly"]

        self.width = max(self.width, nimplant_off[0] + implant_width)
        if info["has_nimplant"]:
            self.add_rect(layer="nimplant",
                          offset=pimplant_off,
                          width=max(implant_width, self.pmos_inst[0].lx()),
                          height=self.height)

        if info["has_pimplant"]:
            self.add_rect(layer="pimplant",
                          offset=nimplant_off,
                          width=implant_width,
                          height=self.height)

        self.add_active_implant(active_off1, metal_off1, metal_height1,
                                extra_width1, extra_height1, extra_off1)
        self.add_active_implant(active_off2, metal_off2, metal_height2,
                                extra_width2, extra_height2, extra_off2)
Пример #31
0
    def render(self):
        if (utils.sum_points_inside_flat_poly(*self.parent.canvas) <= 4):
            return
        color_profile = random.choice(self.colors)

        min_x = utils.floor(min([p.x for p in self.parent.canvas]))
        max_x = utils.ceil(max([p.x for p in self.parent.canvas]))
        min_z = utils.floor(min([p.z for p in self.parent.canvas]))
        max_z = utils.ceil(max([p.z for p in self.parent.canvas]))
        min_y = utils.floor(min([p.y for p in self.parent.canvas]))

        # Cut the canvas into quarters and fill one quarter with colors.
        # Then, copy that quarter into the other three quarters.
        width = utils.floor(((max_x - min_x + 1) + 1) / 2)
        depth = utils.floor(((max_z - min_z + 1) + 1) / 2)

        points = [[-1 for j in xrange(depth)] for i in xrange(width)]
        points_left = []
        for i in xrange(width):
            for j in xrange(depth):
                points_left.append((i, j))
        bounds = utils.Box(Vec(0, 0, 0), width, 1, depth)
        p = Vec(0, 0, 0)
        color_num = 0
        prev_dir = random.randint(0, 3)
        next_dir = random.randint(0, 3)
        while len(points_left) > 0:
            # pick random starting point and walk around the matrix
            point_index = random.randint(0, len(points_left) - 1)
            p = Vec(points_left[point_index][0], 0,
                    points_left[point_index][1])

            while (bounds.containsPoint(p) and points[p.x][p.z] == -1
                   and len(points_left) > 0):
                points[p.x][p.z] = color_num
                points_left.remove((p.x, p.z))

                # pick random direction to walk, try to keep walking same
                # direction
                if random.randint(0, self._walk_weight) != 0:
                    next_dir = prev_dir
                else:
                    while next_dir == prev_dir:
                        next_dir = random.randint(0, 3)
                if next_dir == 0:  # right
                    p += Vec(1, 0, 0)
                elif next_dir == 1:  # down
                    p += Vec(0, 0, 1)
                elif next_dir == 2:  # left
                    p += Vec(-1, 0, 0)
                else:  # up
                    p += Vec(0, 0, -1)
                prev_dir = next_dir
            color_num = (color_num + 1) % len(color_profile)

        for j in xrange(max_z - min_z + 1):
            for i in xrange(max_x - min_x + 1):
                p = self.parent.loc + Vec(min_x + i, min_y, min_z + j)
                self.parent.parent.setblock(p, self.mat)
                if i < width:
                    i_adj = i
                else:
                    i_adj = 2 * width - 1 - i
                if j < depth:
                    j_adj = j
                else:
                    j_adj = 2 * depth - 1 - j
                self.parent.parent.blocks[p].data = \
                    color_profile[points[i_adj][j_adj]]
        # Ruined
        if (self.ruin):
            self.ruinrender()
Пример #32
0
    def render(self):
        if (utils.sum_points_inside_flat_poly(*self.parent.canvas) <= 4):
            return
        color_profile = random.choice(self.colors)

        min_x = utils.floor(min([p.x for p in self.parent.canvas]))
        max_x = utils.ceil(max([p.x for p in self.parent.canvas]))
        min_z = utils.floor(min([p.z for p in self.parent.canvas]))
        max_z = utils.ceil(max([p.z for p in self.parent.canvas]))
        min_y = utils.floor(min([p.y for p in self.parent.canvas]))

        # Cut the canvas into quarters and fill one quarter with colors.
        # Then, copy that quarter into the other three quarters.
        width = utils.floor(((max_x - min_x + 1) + 1) / 2)
        depth = utils.floor(((max_z - min_z + 1) + 1) / 2)

        points = [[-1 for j in xrange(depth)] for i in xrange(width)]
        points_left = []
        for i in xrange(width):
            for j in xrange(depth):
                points_left.append((i, j))
        bounds = utils.Box(Vec(0, 0, 0), width, 1, depth)
        p = Vec(0, 0, 0)
        color_num = 0
        prev_dir = random.randint(0, 3)
        next_dir = random.randint(0, 3)
        while len(points_left) > 0:
            # pick random starting point and walk around the matrix
            point_index = random.randint(0, len(points_left) - 1)
            p = Vec(points_left[point_index][0],
                    0,
                    points_left[point_index][1])

            while (bounds.containsPoint(p) and
                   points[p.x][p.z] == -1 and
                   len(points_left) > 0):
                points[p.x][p.z] = color_num
                points_left.remove((p.x, p.z))

                # pick random direction to walk, try to keep walking same
                # direction
                if random.randint(0, self._walk_weight) != 0:
                    next_dir = prev_dir
                else:
                    while next_dir == prev_dir:
                        next_dir = random.randint(0, 3)
                if next_dir == 0:  # right
                    p += Vec(1, 0, 0)
                elif next_dir == 1:  # down
                    p += Vec(0, 0, 1)
                elif next_dir == 2:  # left
                    p += Vec(-1, 0, 0)
                else:  # up
                    p += Vec(0, 0, -1)
                prev_dir = next_dir
            color_num = (color_num + 1) % len(color_profile)

        for j in xrange(max_z - min_z + 1):
            for i in xrange(max_x - min_x + 1):
                p = self.parent.loc + Vec(min_x + i, min_y, min_z + j)
                self.parent.parent.setblock(p, self.mat)
                if i < width:
                    i_adj = i
                else:
                    i_adj = 2 * width - 1 - i
                if j < depth:
                    j_adj = j
                else:
                    j_adj = 2 * depth - 1 - j
                self.parent.parent.blocks[p].data = \
                    color_profile[points[i_adj][j_adj]]
        # Ruined
        if (self.ruin):
            self.ruinrender()
Пример #33
0
    def render(self):
        if (utils.sum_points_inside_flat_poly(*self.parent.canvas) <= 4):
            return
        color_profile = random.choice(self.colors)

        min_x = utils.floor(min([p.x for p in self.parent.canvas]))
        max_x = utils.ceil(max([p.x for p in self.parent.canvas]))
        min_z = utils.floor(min([p.z for p in self.parent.canvas]))
        max_z = utils.ceil(max([p.z for p in self.parent.canvas]))
        min_y = utils.floor(min([p.y for p in self.parent.canvas]))

        # Cut the canvas into quarters and fill one quarter with colors.
        # Then, copy that quarter into the other three quarters.
        width = utils.floor(((max_x - min_x + 1) + 1) / 2)
        depth = utils.floor(((max_z - min_z + 1) + 1) / 2)

        points = [[-1 for j in xrange(depth)] for i in xrange(width)]
        points_left = []
        for i in xrange(width):
            for j in xrange(depth):
                points_left.append((i, j))
        bounds = utils.Box(Vec(0, 0, 0), width, 1, depth)
        p = Vec(0, 0, 0)
        color_num = 0
        prev_dir = random.randint(0, 3)
        next_dir = random.randint(0, 3)
        while len(points_left) > 0:
            # pick random starting point and walk around the matrix
            point_index = random.randint(0, len(points_left)-1)
            p = Vec(points_left[point_index][0],
                    0,
                    points_left[point_index][1])

            while (bounds.containsPoint(p) and
                   points[p.x][p.z] == -1 and
                   len(points_left) > 0):
                points[p.x][p.z] = color_num
                points_left.remove((p.x, p.z))

                # pick random direction to walk, try to keep walking same direction
                if random.randint(0, self._walk_weight) != 0:
                    next_dir = prev_dir
                else:
                    while next_dir == prev_dir:
                        next_dir = random.randint(0, 3)
                if next_dir == 0:  # right
                    p += Vec(1, 0, 0)
                elif next_dir == 1:  # down
                    p += Vec(0, 0, 1)
                elif next_dir == 2:  # left
                    p += Vec(-1, 0, 0)
                else:  # up
                    p += Vec(0, 0, -1)
                prev_dir = next_dir
            color_num = (color_num + 1) % len(color_profile)

        for j in xrange(max_z - min_z + 1):
            for i in xrange(max_x - min_x + 1):
                p = self.parent.loc + Vec(min_x+i, min_y, min_z+j)
                self.parent.parent.setblock(p, self.mat)
                if i < width:
                    i_adj = i
                else:
                    i_adj = 2*width - 1 - i
                if j < depth:
                    j_adj = j
                else:
                    j_adj = 2*depth - 1 - j
                self.parent.parent.blocks[p].data = \
                    color_profile[points[i_adj][j_adj]]

        if not self.ruin:
            return
        # this chunk of code is copied from CheckerRug's render() method
        pn = perlin.SimplexNoise(256)
        c = self.parent.canvasCenter()
        y = self.parent.canvasHeight()
        r = random.randint(1, 1000)
        maxd = max(1, self.parent.canvasWidth(), self.parent.canvasLength())
        for x in utils.iterate_points_inside_flat_poly(*self.parent.canvas):
            p = x+self.parent.loc
            d = ((Vec2f(x.x, x.z) - c).mag()) / maxd
            n = (pn.noise3((p.x+r) / 4.0, y / 4.0, p.z / 4.0) + 1.0) / 2.0
            if (n < d):
                self.parent.parent.setblock(p, materials._floor)
                self.parent.parent.blocks[p].data = 0
Пример #34
0
    def create_gate_array(self):
        """ Creating nor2+inv for words_per_row==2 and nor2+nand2 for words_per_row==4 """

        # Adding central metal2 bus for wc[i], vdd and gnd connections
        for i in range(self.w_per_row + 2):
            self.add_rect(layer="metal2",
                          offset=(-(i + 2) * self.m_pitch("m1"),
                                  self.m_pitch("m1")),
                          width=contact.m1m2.width,
                          height=self.height - self.m_pitch("m1"))

        if self.w_per_row == 2:
            nor2_offset = vector(-(self.w_per_row + 4) * self.m_pitch("m1"),
                                 self.m_pitch("m1"))
            self.wc_nor2_inst = self.add_inst(name="wc_nor2",
                                              mod=self.nor2,
                                              offset=nor2_offset,
                                              mirror="MY")
            self.connect_inst(["wc[0]", "wc[1]", "Z", "vdd", "gnd"])

            inv_offset = vector(
                -self.nor2.width - (self.w_per_row + 4) * self.m_pitch("m1"),
                self.m_pitch("m1"))
            self.wc_inv_inst = self.add_inst(name="wc_inv",
                                             mod=self.inv,
                                             offset=inv_offset,
                                             mirror="MY")
            self.connect_inst(["Z", "write_complete", "vdd", "gnd"])

            # connect nor2 inputs to central metal2 bus
            pin_list = ["A", "B", "gnd", "vdd"]
            for i in pin_list:
                nor_pin = self.wc_nor2_inst.get_pin(i)
                self.add_rect(layer="metal1",
                              offset=nor_pin.ll(),
                              width=-nor_pin.ll().x -
                              (pin_list.index(i) + 2) * self.m_pitch("m1"),
                              height=self.m1_width)
                self.add_via_center(self.m1_stack,[-(pin_list.index(i)+2)*self.m_pitch("m1")+\
                                                  0.5*contact.m1m2.width, nor_pin.lc().y], rotate=90)

            # Connect nor2 output to inv input
            nor2_Z = self.wc_nor2_inst.get_pin("Z")
            inv_input = self.wc_inv_inst.get_pin("A")
            self.inv_output = self.wc_inv_inst.get_pin("Z")
            self.add_path("metal1", [inv_input.lc(), nor2_Z.lc()])
            self.add_rect(layer="metal1",
                          offset=self.inv_output.ll(),
                          width=contact.m1m2.width + self.m1_width,
                          height=ceil(self.m1_minarea /
                                      (contact.m1m2.width + self.m1_width)))

            # Connect write_complete output to central metal2 bus
            for i in range(0, self.cols, self.w_size):
                wc_pos = self.wc_inst[i].get_pin("write_complete").uc()
                y_pos = wc_pos.y + (i / self.w_size + 2) * self.m_pitch("m1")
                self.add_wire(self.m1_stack, [
                    wc_pos, (wc_pos.x, y_pos),
                    (-(i / self.w_size + 2) * self.m_pitch("m1"), y_pos)
                ])
                self.add_via_center(self.m1_stack, (-(i/self.w_size+2)*self.m_pitch("m1")+\
                                                    0.5*contact.m1m2.width,y_pos), rotate=90)

            # Connect write_complete vdd and gnd to nor2 vdd and gnd
            vdd_pos = self.wc_inst[0].get_pin("vdd")
            nor2_vdd = self.wc_nor2_inst.get_pin("vdd")
            self.add_path("metal1", [
                nor2_vdd.lc(),
                (vdd_pos.ll().x - self.m_pitch("m1"), nor2_vdd.lc().y),
                (vdd_pos.ll().x - self.m_pitch("m1"), vdd_pos.lc().y),
                (self.cols * self.wc.width, vdd_pos.lc().y)
            ])
            gnd_pos = vector(-4 * self.m_pitch("m1"),
                             self.wc_inst[0].get_pin("gnd").lc().y)
            self.add_path("metal1",
                          [gnd_pos, (self.cols * self.wc.width, gnd_pos.y)])
            self.add_via_center(self.m1_stack, [
                -4 * self.m_pitch("m1") + 0.5 * contact.m1m2.width, gnd_pos.y
            ],
                                rotate=90)

            self.wc_x_shift = self.inv.width + self.nor2.width + (
                self.w_per_row + 4) * self.m_pitch("m1")

        if self.w_per_row == 4:
            nor2_Z = {}
            self.nor2_vdd = {}
            self.nor2_gnd = {}
            for i in range(2):
                nor2_offset = vector(-(self.w_per_row+4)*self.m_pitch("m1"), i*(self.nor2.height+\
                                     2*max(self.well_space, self.implant_space,
                                     (contact.m1m2.width+contact.m1m2.height)))+self.m_pitch("m1"))
                self.wc_nor2_inst = self.add_inst(name="wc_nor2_{0}".format(i),
                                                  mod=self.nor2,
                                                  offset=nor2_offset,
                                                  mirror="MY")
                self.connect_inst([
                    "wc[{0}]".format(2 * i), "wc[{0}]".format(2 * i + 1),
                    "Z[{0}]".format(i), "vdd", "gnd"
                ])

                # connect nor2 pins to central metal2 bus
                pin_list = ["A", "B"]
                for j in pin_list:
                    nor_pin = self.wc_nor2_inst.get_pin(j)
                    self.add_rect(
                        layer="metal1",
                        offset=nor_pin.ll(),
                        width=-nor_pin.ll().x -
                        (2 * i + 2 + pin_list.index(j)) * self.m_pitch("m1"),
                        height=self.m1_width)
                    self.add_via_center(self.m1_stack,[-(2*i+2+pin_list.index(j))*self.m_pitch("m1")+\
                                                      0.5*contact.m1m2.width, nor_pin.lc().y],rotate=90)
                self.nor2_gnd[i] = self.wc_nor2_inst.get_pin("gnd")
                self.add_rect(layer="metal1",
                              offset=self.nor2_gnd[i].ll(),
                              width=-self.nor2_gnd[i].ll().x -
                              6 * self.m_pitch("m1"),
                              height=self.m1_width)
                self.add_via_center(self.m1_stack, [
                    -6 * self.m_pitch("m1") + 0.5 * contact.m1m2.width,
                    self.nor2_gnd[i].lc().y
                ],
                                    rotate=90)

                self.nor2_vdd[i] = self.wc_nor2_inst.get_pin("vdd")
                self.add_rect(layer="metal1",
                              offset=self.nor2_vdd[i].ll(),
                              width=-self.nor2_vdd[i].ll().x -
                              7 * self.m_pitch("m1"),
                              height=self.m1_width)
                self.add_via_center(self.m1_stack, [
                    -7 * self.m_pitch("m1") + 0.5 * contact.m1m2.width,
                    self.nor2_vdd[i].lc().y
                ],
                                    rotate=90)

                nor2_Z[i] = self.wc_nor2_inst.get_pin("Z")

            # Add nand2 gate
            nand2_offset = vector(-self.nor2.width- (self.w_per_row + 4)*self.m_pitch("m1")-\
                           max(self.m_pitch("m1")+self.m1_width,self.well_space,self.implant_space),self.m_pitch("m1"))
            self.wc_nand2_inst2 = self.add_inst(name="wc_nand2",
                                                mod=self.nand2,
                                                offset=nand2_offset,
                                                mirror="MY")
            self.connect_inst(["Z[1]", "Z[0]", "write_complete", "vdd", "gnd"])

            # Connect nor2 output to nand2 inputs
            nand2_A_input = self.wc_nand2_inst2.get_pin("A").lc()
            nand2_B_input = self.wc_nand2_inst2.get_pin("B").lc()
            nand2_vdd = self.wc_nand2_inst2.get_pin("vdd").lc()
            nand2_gnd = self.wc_nand2_inst2.get_pin("gnd").lc()

            self.add_path("metal1", [self.nor2_vdd[0].lc(), nand2_vdd])
            self.add_path("metal1", [self.nor2_gnd[0].lc(), nand2_gnd])
            self.add_path("metal1", [nor2_Z[0].ll(), nand2_B_input])
            self.add_wire(self.m1_stack, [
                nor2_Z[1].lc(),
                (nand2_offset.x + 0.5 * self.m1_width, nor2_Z[1].lc().y),
                (nand2_offset.x + 0.5 * self.m1_width, nand2_A_input.y),
                nand2_A_input
            ])

            # Connect write_complete output to central metal2 bus
            for i in range(0, self.cols, self.w_size):
                wc_pos = self.wc_inst[i].get_pin("write_complete").uc()
                y_pos = max(
                    nor2_Z[1].lc().y,
                    wc_pos.y) + (i / self.w_size + 1) * self.m_pitch("m1")
                self.add_wire(self.m1_stack, [
                    wc_pos, (wc_pos.x, y_pos),
                    (-(i / self.w_size + 2) * self.m_pitch("m1"), y_pos)
                ])
                self.add_via_center(self.m1_stack,(-(i/self.w_size+2)*self.m_pitch("m1")+\
                                                   0.5*contact.m1m2.width,y_pos), rotate=90)

            # Connect write_complete vdd and gnd to nor2 vdd and gnd
            vdd_pos = self.wc_inst[0].get_pin("vdd")
            self.add_path("metal1", [
                self.nor2_vdd[0].lc(),
                (vdd_pos.ll().x - self.m_pitch("m1"), self.nor2_vdd[0].lc().y),
                (vdd_pos.ll().x - self.m_pitch("m1"), vdd_pos.lc().y),
                (self.cols * self.wc.width, vdd_pos.lc().y)
            ])
            gnd_pos = self.wc_inst[0].get_pin("gnd")
            self.add_path("metal1", [
                self.nor2_gnd[1].lc(),
                (gnd_pos.ll().x - self.m_pitch("m1"), self.nor2_gnd[1].lc().y),
                (gnd_pos.ll().x - self.m_pitch("m1"), gnd_pos.lc().y),
                (self.cols * self.wc.width, gnd_pos.lc().y)
            ])

            self.wc_x_shift=self.nand2.width+self.nor2.width+(self.w_per_row+5)*self.m_pitch("m1")+\
                            max(self.m_pitch("m1")+self.m1_width,self.well_space,self.implant_space)
Пример #35
0
    def add_well_contact(self):
        """ Add nwell and pwell contacts """

        #nwell contact
        if info["has_pwell"]:
            self.add_rect(layer="pwell",
                          offset=self.nmos_inst[self.size - 1].lr(),
                          width=2 * self.shift,
                          height=self.nmos.width)
        if info["has_pimplant"]:
            self.add_rect(layer="pimplant",
                          offset=self.nmos_inst[self.size - 1].lr(),
                          width=2 * self.shift,
                          height=self.pmos_inst[self.size - 1].by() +
                          self.implant_space)

        xoff = self.well_enclose_active + contact.well.height
        yoff = self.well_enclose_active
        self.nwell_co_off = self.nmos_inst[self.size - 1].lr() + vector(
            xoff, yoff)
        self.add_contact(("active", "contact", "metal1"),
                         self.nwell_co_off,
                         rotate=90)
        self.add_rect(layer="active",
                      offset=(self.nwell_co_off.x - contact.well.height,
                              self.nwell_co_off.y),
                      width=ceil(self.active_minarea / contact.well.width),
                      height=contact.well.width)
        #pwell contact
        if info["has_nwell"]:
            self.add_rect(layer="nwell",
                          offset=self.pmos_inst[0].ll() -
                          vector(0, 0.5 * self.space),
                          width=self.shift * (self.size + 2),
                          height=self.pmos.width + self.space)
        if info["has_nimplant"]:
            self.add_rect(layer="nimplant",
                          offset=self.pmos_inst[self.size - 1].lr() +
                          vector(0, self.implant_space),
                          width=2 * self.shift,
                          height=self.nmos.width - self.implant_space)

        xoff = self.well_enclose_active + contact.well.height
        yoff = self.well_enclose_active + contact.well.width
        self.pwell_co_off = self.pmos_inst[self.size - 1].ur() + vector(
            xoff, -yoff)

        self.add_contact(("active", "contact", "metal1"),
                         self.pwell_co_off,
                         rotate=90)
        self.add_rect(layer="active",
                      offset=(self.pwell_co_off.x - contact.well.height,
                              self.pwell_co_off.y),
                      width=ceil(self.active_minarea / contact.well.width),
                      height=contact.well.width)

        extra_height = contact.well.width + 2 * self.extra_enclose
        extra_width = max(
            ceil(self.active_minarea / contact.well.width) +
            2 * self.extra_enclose, ceil(self.extra_minarea / extra_height))
        shift = vector(contact.well.height + self.extra_enclose,
                       self.extra_enclose)
        for off in [self.nwell_co_off - shift, self.pwell_co_off - shift]:
            self.add_rect(layer="extra_layer",
                          layer_dataType=layer["extra_layer_dataType"],
                          offset=off,
                          width=extra_width,
                          height=extra_height)
Пример #36
0
    def connect_modules(self):
        """ Connect NMOS and PMOS terminals to in/out pins """

        minx_tx = min(self.pmos_inst[0].lx(), self.nmos_inst[0].lx())

        #connect all NMOS gates to data0 pin
        self.add_path(
            "poly",
            [(self.nmos_inst[0].get_pin("G").lc() - vector(self.pin_off, 0)),
             self.nmos_inst[self.size - 1].get_pin("G").lc()])
        #connect all PMOS gates to data1 pin
        self.add_path(
            "poly",
            [(self.pmos_inst[0].get_pin("G").lc() - vector(self.pin_off, 0)),
             self.pmos_inst[self.size - 1].get_pin("G").lc()])

        #extend implant to cover poly for DRC violation
        if info["has_nimplant"]:
            self.add_rect(layer="nimplant",
                          offset=(minx_tx - self.pin_off,
                                  self.nmos_inst[0].by()),
                          width=self.pin_off + self.shift * self.size,
                          height=self.pmos_inst[0].by())
        if info["has_pimplant"]:
            self.add_rect(layer="pimplant",
                          offset=(minx_tx - self.pin_off,
                                  self.pmos_inst[0].by()),
                          width=self.pin_off + self.shift * self.size,
                          height=self.pmos.width)

        #connect all NMOS sources to gnd pin
        pos1 = self.nmos_inst[0].get_pin("S").lc() - vector(
            self.pin_off - self.m_pitch("m1"), 0)
        pos2 = (self.nwell_co_off.x,
                self.nmos_inst[self.size - 1].get_pin("S").lc().y)
        self.add_path("metal1", [pos1, pos2])

        #connect all PMOS drains to vdd pin
        pos1 = self.pmos_inst[0].get_pin("D").lc() - vector(
            self.pin_off - self.m_pitch("m1"), 0)
        pos2 = (self.nwell_co_off.x,
                self.pmos_inst[self.size - 1].get_pin("D").lc().y)
        self.add_path("metal1", [pos1, pos2])

        #connect all NMOS drains to PMOS sources
        for i in range(self.size):
            pos1 = self.pmos_inst[i].get_pin("S").uc()
            pos2 = self.nmos_inst[i].get_pin("D").uc()
            self.add_path("metal1", [pos1, pos2], width=contact.m1m2.width)
            via_off = vector(pos1.x, self.pmos_inst[0].by())
            self.add_via_center(self.m1_stack, via_off)
            self.add_path("metal2", [
                via_off,
                (via_off.x, self.pmos_inst[0].uy() + self.m_pitch("m1"))
            ])

        #connect all dummy polies to avoid min-space poly DRC
        if info["tx_dummy_poly"]:
            shift = vector(
                self.nmos.dummy_poly_offset1.y,
                self.nmos.dummy_poly_offset1.x + 0.5 * self.poly_width)
            self.add_path("poly", [
                vector(minx_tx, self.nmos_inst[0].by()) + shift,
                self.nmos_inst[self.size - 1].lr() + shift
            ])
            self.add_path("poly", [
                vector(minx_tx, self.pmos_inst[0].by()) + shift,
                self.pmos_inst[self.size - 1].lr() + shift
            ])

            shift = (self.nmos.dummy_poly_offset2.y,
                     self.nmos.dummy_poly_offset2.x + 0.5 * self.poly_width)
            self.add_path("poly", [
                vector(minx_tx, self.nmos_inst[0].by()) + shift,
                self.nmos_inst[self.size - 1].lr() + shift
            ])
            self.add_path("poly", [
                vector(minx_tx, self.pmos_inst[0].by()) + shift,
                self.pmos_inst[self.size - 1].lr() + shift
            ])

        #connect all vt layers to avoid min-space vt DRC
        vt_offset = (minx_tx, self.nmos_inst[0].by())
        vt_height = ceil(self.pmos.width) + ceil(self.nmos.width) + self.space
        self.add_rect(layer="vt",
                      offset=vt_offset,
                      layer_dataType=layer["vt_dataType"],
                      width=self.shift * self.size,
                      height=vt_height)