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))
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)
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)
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)
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
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
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)
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)
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]
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)
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
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)
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)
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"))
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)
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]))
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
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
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
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)
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
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)
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
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)))
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
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)
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)
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())
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)
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()
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
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)
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)
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)