def test_1_Trans(self): a = pya.Trans() b = pya.Trans( pya.Trans.M135, pya.Point( 17, 5 )) c = pya.Trans( 3, True, pya.Point( 17, 5 )) d = pya.Trans( pya.Point( 17, 5 )) e = pya.Trans( pya.Trans.M135 ) e2 = pya.Trans.from_dtrans( pya.DTrans.M135 ) f = pya.Trans( pya.DTrans( pya.DTrans.M135, pya.DPoint( 17, 5 )) ) self.assertEqual( str(a), "r0 0,0" ) self.assertEqual( str(pya.Trans.from_s(str(a))), str(a) ) self.assertEqual( str(b), "m135 17,5" ) self.assertEqual( str(c), "m135 17,5" ) self.assertEqual( str(d), "r0 17,5" ) self.assertEqual( str(e), "m135 0,0" ) self.assertEqual( str(e2), "m135 0,0" ) self.assertEqual( str(f), "m135 17,5" ) self.assertEqual( str(pya.Trans.from_s(str(f))), str(f) ) self.assertEqual( str(b.trans( pya.Point( 1, 0 ))), "17,4" ) self.assertEqual( a == b, False ) self.assertEqual( a == a, True ) self.assertEqual( a != b, True ) self.assertEqual( a != a, False ) self.assertEqual( (d * e) == b, True ) self.assertEqual( (e * d) == b, False ) i = c.inverted() self.assertEqual( str(i), "m135 5,17" ) self.assertEqual( (i * b) == a, True ) self.assertEqual( (b * i) == a, True ) c = pya.Trans( 3, True, pya.Point( 17, 5 )) self.assertEqual( str(c), "m135 17,5" ) c.disp = pya.Point(1, 7) self.assertEqual( str(c), "m135 1,7" ) c.angle = 1 self.assertEqual( str(c), "m45 1,7" ) c.rot = 3 self.assertEqual( str(c), "r270 1,7" ) c.mirror = True self.assertEqual( str(c), "m135 1,7" ) self.assertEqual( str(e.trans( pya.Edge(0, 1, 2, 3) )), "(-3,-2;-1,0)" ) self.assertEqual( str(( e * pya.Edge(0, 1, 2, 3) )), "(-3,-2;-1,0)" ) self.assertEqual( str(e.trans( pya.Box(0, 1, 2, 3) )), "(-3,-2;-1,0)" ) self.assertEqual( str(( e * pya.Box(0, 1, 2, 3) )), "(-3,-2;-1,0)" ) self.assertEqual( str(e.trans( pya.Text("text", pya.Vector(0, 1)) )), "('text',m135 -1,0)" ) self.assertEqual( str(( e * pya.Text("text", pya.Vector(0, 1)) )), "('text',m135 -1,0)" ) self.assertEqual( str(e.trans( pya.Polygon( [ pya.Point(0, 1), pya.Point(2, -3), pya.Point(4, 5) ] ) )), "(-5,-4;-1,0;3,-2)" ) self.assertEqual( str(( e * pya.Polygon( [ pya.Point(0, 1), pya.Point(2, -3), pya.Point(4, 5) ] ) )), "(-5,-4;-1,0;3,-2)" ) self.assertEqual( str(e.trans( pya.Path( [ pya.Point(0, 1), pya.Point(2, 3) ], 10 ) )), "(-1,0;-3,-2) w=10 bx=0 ex=0 r=false" ) self.assertEqual( str(( e * pya.Path( [ pya.Point(0, 1), pya.Point(2, 3) ], 10 ) )), "(-1,0;-3,-2) w=10 bx=0 ex=0 r=false" )
def test_4_Trans(self): a = pya.Trans() m = pya.CplxTrans(a, 1.1) da = pya.DTrans() dm = pya.DCplxTrans(da, 1.1) self.assertEqual(str(m), "r0 *1.1 0,0") self.assertEqual(str(pya.DCplxTrans.from_s(str(m))), str(m)) self.assertEqual(str(m.trans(pya.Point(5, -7))), "5.5,-7.7") im = pya.ICplxTrans(a, 0.5) im_old = im.dup() self.assertEqual(str(im), "r0 *0.5 0,0") self.assertEqual(str(pya.ICplxTrans.from_s(str(im))), str(im)) self.assertEqual(str(im.trans(pya.Point(5, -7))), "3,-4") im = pya.ICplxTrans(m) self.assertEqual(str(im), "r0 *1.1 0,0") self.assertEqual(str(im.trans(pya.Point(5, -7))), "6,-8") im = pya.ICplxTrans(dm) self.assertEqual(str(im), "r0 *1.1 0,0") self.assertEqual(str(im.trans(pya.Point(5, -7))), "6,-8") im.assign(im_old) self.assertEqual(str(im), "r0 *0.5 0,0") self.assertEqual(str(im.trans(pya.Point(5, -7))), "3,-4") self.assertEqual(str(pya.ICplxTrans(5, -7)), "r0 *1 5,-7") self.assertEqual(str(pya.ICplxTrans(pya.ICplxTrans.R180, 1.5, 5, -7)), "r180 *1.5 5,-7") self.assertEqual( str(pya.ICplxTrans(pya.ICplxTrans.R180, 1.5, pya.Point(5, -7))), "r180 *1.5 5,-7") self.assertEqual( str(pya.ICplxTrans(pya.ICplxTrans.R180, 1.5, pya.Vector(5, -7))), "r180 *1.5 5,-7") self.assertEqual( str(pya.ICplxTrans(pya.ICplxTrans.R180, 1.5, pya.DVector(5, -7))), "r180 *1.5 5,-7") self.assertEqual(str(pya.ICplxTrans(pya.ICplxTrans.R180, 1.5)), "r180 *1.5 0,0") c = pya.ICplxTrans.from_dtrans(pya.DCplxTrans.M135) self.assertEqual(str(c), "m135 *1 0,0") c = pya.ICplxTrans.from_trans(pya.CplxTrans.M135) self.assertEqual(str(c), "m135 *1 0,0")
def main(): # [1] Create TOP layout (LAYOUT_TOP, where layouts A,B,... would be merged) import pya LAYOUT_TOP = pya.Layout() CELL_TOP = LAYOUT_TOP.create_cell("CELL_TOP") # Create layer #'s import layer_numbers as lm l_TP_outline = LAYOUT_TOP.layer(lm.layer_num_TP_outline, 0) # One touch pixel Outline # Insert box outline for unit touch pixel dimensions CELL_TOP.shapes(l_TP_outline).insert(pya.Box(0, 0, p * 14, p * 14)) for ind, (k, v) in enumerate(gds_files_d.items()): print("\nProcessing ... : ", ind, k, v) # 0 | 2_unit_1_7.gds | [1, 7] # [2] Loop over each GDS, create separate layouts (LAYOUT_A, LAYOUT_B, ...), and read each GDS files LAYOUT_A = pya.Layout() LAYOUT_A.read(k) # From GDS name, get # of repeats in x-y dir [nx, ny] = get_nx_ny(k) #[nx, ny] = [1, 1] # [3] In TOP layout, create (empty) target cells (ta, tb, ...) CELL_TA = LAYOUT_TOP.create_cell("CELL_" + str(v[0]) + "_" + str(v[1])) # CELL_2_7, CELL_14_5, ... CELL_TOP.insert( pya.CellInstArray( CELL_TA.cell_index(), pya.Trans(pya.Point(p * (v[1] - 1), p * (v[0] - 1))), pya.Vector(p, 0), pya.Vector(0, p), nx, ny)) # v : value (e.g. [1, 7]) --> x = v[1], y = v[0] # [4] From [3], copy over the layouts from A to TA, using ta.move_tree(layout_A.top_cell() ) CELL_TA.move_tree(LAYOUT_A.top_cell()) # Export GDS LAYOUT_TOP.write("3_PANEL_wip.gds")
def test_3_DTrans(self): c = pya.DCplxTrans(5.0, -7.0) self.assertEqual(str(c), "r0 *1 5,-7") c = pya.DCplxTrans(pya.DCplxTrans.M135) self.assertEqual(str(c), "m135 *1 0,0") self.assertEqual(c.is_unity(), False) self.assertEqual(c.is_ortho(), True) self.assertEqual(c.is_mag(), False) self.assertEqual(c.is_mirror(), True) self.assertEqual(c.rot(), pya.DCplxTrans.M135.rot()) self.assertEqual(str(c.s_trans()), "m135 0,0") self.assertAlmostEqual(c.angle, 270) self.assertEqual(str(c.trans(pya.DEdge(0, 1, 2, 3))), "(-3,-2;-1,0)") self.assertEqual(str((c * pya.DEdge(0, 1, 2, 3))), "(-3,-2;-1,0)") self.assertEqual(str(c.trans(pya.DBox(0, 1, 2, 3))), "(-3,-2;-1,0)") self.assertEqual(str((c * pya.DBox(0, 1, 2, 3))), "(-3,-2;-1,0)") self.assertEqual(str(c.trans(pya.DText("text", pya.DVector(0, 1)))), "('text',m135 -1,0)") self.assertEqual(str((c * pya.DText("text", pya.DVector(0, 1)))), "('text',m135 -1,0)") self.assertEqual( str( c.trans( pya.DPolygon([ pya.DPoint(0, 1), pya.DPoint(2, -3), pya.DPoint(4, 5) ]))), "(-5,-4;-1,0;3,-2)") self.assertEqual( str((c * pya.DPolygon( [pya.DPoint(0, 1), pya.DPoint(2, -3), pya.DPoint(4, 5)]))), "(-5,-4;-1,0;3,-2)") self.assertEqual( str(c.trans(pya.DPath( [pya.DPoint(0, 1), pya.DPoint(2, 3)], 10))), "(-1,0;-3,-2) w=10 bx=0 ex=0 r=false") self.assertEqual( str((c * pya.DPath( [pya.DPoint(0, 1), pya.DPoint(2, 3)], 10))), "(-1,0;-3,-2) w=10 bx=0 ex=0 r=false") c = pya.DCplxTrans.from_itrans(pya.CplxTrans.M135) self.assertEqual(str(c), "m135 *1 0,0") c = pya.DCplxTrans(1.5) self.assertEqual(str(c), "r0 *1.5 0,0") self.assertEqual(c.is_unity(), False) self.assertEqual(c.is_ortho(), True) self.assertEqual(c.is_mag(), True) self.assertEqual(c.is_mirror(), False) self.assertEqual(c.rot(), pya.DCplxTrans.R0.rot()) self.assertEqual(str(c.s_trans()), "r0 0,0") self.assertAlmostEqual(c.angle, 0) c = pya.DCplxTrans(0.75, 45, True, 2.5, -12.5) self.assertEqual(str(c), "m22.5 *0.75 2.5,-12.5") c = pya.DCplxTrans(0.75, 45, True, pya.DPoint(2.5, -12.5)) self.assertEqual(str(c), "m22.5 *0.75 2.5,-12.5") self.assertEqual(c.is_unity(), False) self.assertEqual(c.is_ortho(), False) self.assertEqual(c.is_mag(), True) self.assertEqual(c.rot(), pya.DCplxTrans.M0.rot()) self.assertEqual(str(c.s_trans()), "m0 2.5,-12.5") self.assertAlmostEqual(c.angle, 45) self.assertEqual(str(c.ctrans(5)), "3.75") self.assertEqual(str(c.trans(pya.DPoint(12, 16))), "17.3492424049,-14.6213203436") self.assertEqual(str(pya.DCplxTrans()), "r0 *1 0,0") self.assertEqual(pya.DCplxTrans().is_unity(), True) self.assertEqual((c * c.inverted()).is_unity(), True) c.mirror = False self.assertEqual(str(c), "r45 *0.75 2.5,-12.5") c.mag = 1.5 self.assertEqual(str(c), "r45 *1.5 2.5,-12.5") c.disp = pya.DPoint(-1.0, 5.5) self.assertEqual(str(c), "r45 *1.5 -1,5.5") self.assertEqual(c.mag, 1.5) c.angle = 60 self.assertEqual(str(c), "r60 *1.5 -1,5.5") self.assertEqual(("%g" % c.angle), "60") # Constructor variations self.assertEqual(str(pya.ICplxTrans()), "r0 *1 0,0") self.assertEqual(str(pya.ICplxTrans(1.5)), "r0 *1.5 0,0") self.assertEqual(str(pya.ICplxTrans(pya.Trans(1, False, 10, 20), 1.5)), "r90 *1.5 10,20") self.assertEqual(str(pya.ICplxTrans(pya.Trans(1, False, 10, 20))), "r90 *1 10,20") self.assertEqual( str(pya.ICplxTrans(1.5, 80, True, pya.Vector(100, 200))), "m40 *1.5 100,200") self.assertEqual(str(pya.ICplxTrans(1.5, 80, True, 100, 200)), "m40 *1.5 100,200") self.assertEqual(str(pya.ICplxTrans(pya.Vector(100, 200))), "r0 *1 100,200") self.assertEqual(str(pya.ICplxTrans(100, 200)), "r0 *1 100,200") self.assertEqual(str(pya.ICplxTrans(pya.ICplxTrans(100, 200))), "r0 *1 100,200") self.assertEqual(str(pya.ICplxTrans(pya.ICplxTrans(100, 200), 1.5)), "r0 *1.5 150,300") self.assertEqual( str( pya.ICplxTrans(pya.ICplxTrans(100, 200), 1.5, pya.Vector(10, 20))), "r0 *1.5 160,320") self.assertEqual( str(pya.ICplxTrans(pya.ICplxTrans(100, 200), 1.5, 10, 20)), "r0 *1.5 160,320") self.assertEqual(str(pya.DCplxTrans()), "r0 *1 0,0") self.assertEqual(str(pya.DCplxTrans(1.5)), "r0 *1.5 0,0") self.assertEqual( str(pya.DCplxTrans(pya.DTrans(1, False, 0.01, 0.02), 1.5)), "r90 *1.5 0.01,0.02") self.assertEqual(str(pya.DCplxTrans(pya.DTrans(1, False, 0.01, 0.02))), "r90 *1 0.01,0.02") self.assertEqual( str(pya.DCplxTrans(1.5, 80, True, pya.DVector(0.1, 0.2))), "m40 *1.5 0.1,0.2") self.assertEqual(str(pya.DCplxTrans(1.5, 80, True, 0.1, 0.2)), "m40 *1.5 0.1,0.2") self.assertEqual(str(pya.DCplxTrans(pya.DVector(0.1, 0.2))), "r0 *1 0.1,0.2") self.assertEqual(str(pya.DCplxTrans(0.1, 0.2)), "r0 *1 0.1,0.2") self.assertEqual(str(pya.DCplxTrans(pya.DCplxTrans(0.1, 0.2))), "r0 *1 0.1,0.2") self.assertEqual(str(pya.DCplxTrans(pya.DCplxTrans(0.1, 0.2), 1.5)), "r0 *1.5 0.15,0.3") self.assertEqual( str( pya.DCplxTrans(pya.DCplxTrans(0.1, 0.2), 1.5, pya.DVector(0.01, 0.02))), "r0 *1.5 0.16,0.32") self.assertEqual( str(pya.DCplxTrans(pya.DCplxTrans(0.1, 0.2), 1.5, 0.01, 0.02)), "r0 *1.5 0.16,0.32")
current = via_iter.shape().bbox() v_x = (current.left - init_loc[0]) // m1_track_pitch v_y = (current.bottom - init_loc[1] - m1_enc) // m2_track_pitch if not check_via_pitch_pass(v_x, v_y, via_mtx, m1_track_pitch, m2_track_pitch, min_via_pitch_y=min_via1_pitch_y): via_iter.shape().delete() via_mtx[v_y, v_x] = 0 via_iter.next() '''draw sraf forbidden and access region / store via/contact coordinates''' l_forbidden = layout.layer(210, 0) l_access = layout.layer(230, 0) offset_forbidden = pya.Vector(100, 100) offset_access = pya.Vector(500, 500) via_iter = layout.begin_shapes(cell, l_via1) tmp_iter = 0 while not via_iter.at_end(): current = via_iter.shape().bbox() llp = current.p1 urp = current.p2 llp_forbidden = llp - offset_forbidden urp_forbidden = urp + offset_forbidden cell.shapes(l_forbidden).insert( pya.Box(llp_forbidden, urp_forbidden)) llp_access = llp - offset_access urp_access = urp + offset_access cell.shapes(l_access).insert(pya.Box(llp_access, urp_access))
# Define array of GDS files to read gds_files = ["0_unit_1x1.gds"] # Read each GDS files for each_gds in gds_files: KLAYOUT.read(each_gds) # Read Top Cell for each GDS file for top_cell_read in KLAYOUT.top_cells(): if (top_cell_read.name != "1_UNIT"): # Don't insert TOP_CELL("1_UNIT") on itself # print ( "Adding " + top_cell_read.name ) cell_index = top_cell_read.cell_index() new_instance = pya.CellInstArray(cell_index, pya.Trans(pya.Point(0, 0)), pya.Vector(pitch, 0), pya.Vector(0, pitch), 3, 3) # pya.Trans(pya.Point(0,0)) --> defines the LOCATION at which instance should be placed # pya.Vector(pitch, 0) --> defines the PITCH at which instance should repeat # 3, 3 --> defines number of repeats TOP_CELL.insert(new_instance) # Create layer #'s l_3x3_outline = KLAYOUT.layer(3, 0) # 3x3 Outline # Draw outline (of 3x3) TOP_CELL.shapes(l_3x3_outline).insert(pya.Box(0, 0, 3 * pitch, 3 * pitch)) # Export GDS KLAYOUT.write("1_unit_3x3.gds")
def coerce_parameters_impl(self): """Method called by Klayout to update a PCell. For photonic PCells the ports are updated/calculated in the parameter of the PCell. And desired movement transformations are performed. Because the calculated ports of our own PCell are used by parent cells and are needed before `~produce_impl`, we must calculate them twice. First to calculate where our own ports are and then again to instantiate the child cells. This is unfortunate but not a big problem, since dataprep and DR-cleaning take the majority of computation time. :return: """ self.clear_ports() instances_and_ports = self.create_param_inst() if not instances_and_ports: return if isnamedtupleinstance(instances_and_ports) or isinstance( instances_and_ports, InstanceHolder): instances_and_ports = [instances_and_ports] id = 0 insts = [] for inst_port in instances_and_ports: # For each object test if it is a list of InstanceHolders/Port or plain objects and then separate them accordingly if isinstance(inst_port, InstanceHolder): inst_port.id = id id += 1 insts.append(inst_port) elif isnamedtupleinstance(inst_port): self.create_port(inst_port.x, inst_port.y, inst_port.rot, inst_port.length) elif type(inst_port) is list: for iinst_port in inst_port: if isinstance(iinst_port, InstanceHolder): iinst_port.id = id id += 1 insts.append(iinst_port) elif isnamedtupleinstance(iinst_port): self.create_port(iinst_port.x, iinst_port.y, iinst_port.rot, iinst_port.length) else: raise ValueError( "Expected type instances (InstanceHolder), ports (PortCreation) or a list of instances,ports. Instead got {}" .format(str(type(inst_port)))) self.transformations = '' # If child instances have requested movements in their InstanceHolder move them now for i, inst in enumerate(insts): if self.transformations: self.transformations += ';' if inst.movement: # Adjust movement for database inst.movement.disp = pya.Vector( inst.movement.disp.x / self.layout.dbu, inst.movement.disp.y / self.layout.dbu) self.transformations += inst.movement.to_s() inst.placed = True elif inst.connection: self.transformations += pya.ICplxTrans.R0.to_s() else: self.transformations += pya.ICplxTrans.R0.to_s() inst.placed = True # If the InstanceHolder object has a Port to connect to, calculate the transformation all_placed = False count = 0 while (not all_placed) and count < 50: all_placed = True count += 1 for i, inst in enumerate(insts): if inst.connection: if not inst.connection.placed: all_placed = False continue retcode = self.connect_port(inst.connection.id, inst.connection.params_mod[0], inst.connection_port, inst.id, inst.params_mod[0], inst.port_to_connect) if retcode < 0: msg = pya.QMessageBox( pya.Application.instance().main_window()) msg.text = 'Port {} of {} cannot be connected to Port {} of {}'.format( inst.port_to_connect, inst.connection.params['cellname'], inst.port_to_connect, inst.params['cellname']) msg.windowTitle = 'ImportError' msg.exec_() return False inst.placed = True # Update the transformations and self.portlist with the calculated transformations of the children self.calculate_ports(insts)
xpos = xpos + 4 * Xcell_size t = pya.Trans(xpos, ypos) n += 1 #-----------------------------DECODERS-------------------------- if (n_decoders and decoders25): decoder_cell = layout.create_cell("decoder_cell") xpos1 = pmos_placement_width * 4 ypos1 = 0 xpos2 = -nmos_placement_width * 4 ypos2 = 0 num_addr_bus = find_pwr2(num_words, 0) for i in range(0, num_addr_bus): t1 = pya.Trans(1, False, pya.Vector(xpos1, ypos1)) t2 = pya.Trans(1, False, pya.Vector(xpos2, ypos2)) pmos.place(decoder_cell, t1) nmos.place(decoder_cell, t2) xpos1 = xpos1 + pmos_placement_width * 4 xpos2 = xpos2 - nmos_placement_width * 4 # GND Via # Vdd Via #MANUAL PLACEMENT! xpos1 = pmos_placement_width * 4 + 250 xpos2 = -nmos_placement_width * 4 + 250 ypos1 = -nmos_width * 2 - 60 ypos2 = -nmos_width * 2 - 60 for i in range(0, num_addr_bus): t1 = pya.Trans(1, False, pya.Vector(xpos1, ypos1))