Exemple #1
0
def image_to_gds(p: pathlib.Path,
                 layer: int = LayoutDefault.layerTop,
                 *a,
                 **k):

    try:

        import nazca as nd

    except Exception:

        import subprocess

        import sys

        thispath = pathlib.Path(__file__).parent

        nazcapath = thispath / "addOns" / "nazca" / "nazca-0.5.13.zip"

        subprocess.check_call([
            sys.executable, "-m", "pip", "install",
            str(nazcapath.absolute())
        ])

        import nazca as nd

    nd.image(str(p.absolute()), layer=layer, **k).put(0)

    nd.export_gds(filename=str(p.parent / p.stem) + '.gds', flat=True)
 def _plot(self):
     nd.Polyline(points=self.points,
                 width=self.width,
                 olayer=self.olayer,
                 layer=self.layer).put()
     nd.export_gds()
     return
Exemple #3
0
def generate_gds_from_image(path, **kwargs):

    import nazca as nd

    if isinstance(path, pathlib.Path):

        path = str(path.absolute())

    else:

        path = pathlib.Path(path)

    cell = nd.image(path, **kwargs).put()

    path = path.parent / (path.stem + ".gds")

    nd.export_gds(filename=str(path.absolute()))

    return path
                                200)

    rect_w = num.array([3, 5, 8, 10])
    rect_l = 200
    rect_a = 10 * (3.0 + num.arange(7))
    rect_x = 1.25 * rect_l * (1 + num.arange(rect_a.size))
    rect_y = 1.25 * rect_l * num.arange(rect_w.size)
    rect_structs = place_rects('rectangles', rect_l, rect_w, rect_a, rect_x,
                               rect_y)

    with nd.Cell(name='resolution_test') as res_test_bb:
        filename_res = \
            'c:\\users\\micha\documents\\code\\nazca-mask-design\\' + \
            'ms_test_structures\\resolution_test.gds'
        res_test_bb = nd.load_gds(filename=filename_res,
                                  layermap={1: 3},
                                  prefix='res_',
                                  newcellname='res_test')
    res_test_bb = res_test_bb.put(-325, 750)

    with nd.Cell(name='critical_dimsg') as crit_dims_bb:
        filename_crit = \
            'c:\\users\\micha\\documents\code\\nazca-mask-design' + \
            '\\ms_test_structures\\critical_dimension.gds'
        crit_dims_bb = nd.load_gds(filename=filename_crit,
                                   layermap={1: 3},
                                   newcellname='crit_dim_cell',
                                   prefix='dims_')
    dims_bb = crit_dims_bb.put((-325, 450, 0))
    nd.export_gds(filename='ms_test_struct_v2')
Exemple #5
0
def __createWhitePcellLib(gdsin,
                          whitelibrary=None,
                          black2whiteMap=None,
                          prefixb='black_',
                          prefixw='wb_',
                          infolevel=0):
    """
    Create a Pcell library based in cells <gdsin>.

    Args:
        gdsin (str): file name of input GDS.
        gdsout (str): optional file name of output GDS.
        whitelibrary (str): optional file name of generated white cell GDS library.
        black2whitemap (dict): mapping black cell names to white cell functions {name: function}.
        prefixb: blackbox prefix (default = 'black_')
        prefixw (str): whitebox prefix  (default = 'wb_')
        infolevel (int): amount of debug info printed (default = 0)

    Returns:
        str, dict: gds filename of white Pcell library, {black-cellname: white-cellname}
    """

    if whitelibrary is None:
        timestr = time.strftime("%Y-%m-%d")
        whitelibrary = "{}_white_lib_{}.gds".format(gdsin[:-4], timestr)

    # Using the black2whiteMap dictionary:
    # - create a list of all black cellnames in the map,
    # - extract their Pcell parameters,
    # - create a matching list of newly generated white cells using the params.
    # Note the white cell is (should be) generated with a black cell inside.
    # Note that the replaced white cells have the same name for the gds ref
    gdsinstream = nd.GDSII_stream(gdsin)
    allInputCellNames = gdsinstream.cells.keys()
    allBlackCellNames = []
    allWhiteCells = []
    allWhiteCellNames = []
    for blackBasename, whiteFunction in black2whiteMap.items():
        #print('whiteFunction', blackBasename, whiteFunction, )
        if whiteFunction is None:
            continue
        cells_x_Params = __readPcellParams(blackBasename,
                                           gdsinstream,
                                           allInputCellNames,
                                           infolevel=infolevel)
        for cellname, parameters in cells_x_Params.items():
            try:
                whiteCell = whiteFunction(**parameters)
                allWhiteCells.append(whiteCell)
                allBlackCellNames.append(
                    cellname
                )  #inside for loop to sync order of white and black
            except Exception as error:
                print("Error in inside white box function or whitbox function call.\n"\
                     " - can not generate cell '{}'\n"\
                     " - whitebox function: {}\n"\
                     " - parameters: {}\n".\
                     format(cellname, whiteFunction, parameters))
                #traceback.print_exc(file=sys.stdout)
                raise
                #TODO: add empty/error cell to keep black and white list in sync
        #if infolevel > 3:
        #    print('\nblackBasename = ', blackBasename)
        #    print('whiteCellparams:\n', allWhiteCells)

    if infolevel > 3:
        print("\n{:30}{}".format("allBlackCells", "allWhiteCells"))
        for base, cell in zip(allBlackCellNames, allWhiteCells):
            try:
                print("{:40}{}".format(base, cell.cell_name))
            except:
                print("{:40}{}".format(base, cell))

    #generate cell names for all black and white cells
    allBlackCellNamesOut = [prefixb + name for name in allBlackCellNames]
    allWhiteCellNames = [cell.cell_name for cell in allWhiteCells]

    #map input black cellname to output black cellname (for gds debugging).
    blackmap = {
        black: newblack
        for black, newblack in zip(allBlackCellNames, allBlackCellNamesOut)
    }
    #map white cellname to black cellname
    whitemap = {
        white: black
        for white, black in zip(allWhiteCellNames, allBlackCellNames)
    }

    if infolevel > 1:
        print('\nMapping for renaming black cells:')
        pprint(blackmap)
        print(
            '\nMapping to copy white cellnames to original (black) gdsin cellnames:'
        )
        pprint(whitemap)
        #print('\n')

    #Export all white cells into the <whitelibrary> gds file
    nd.export_gds(allWhiteCells, filename=whitelibrary)

    # rename black cells:
    g = nd.GDSII_stream(whitelibrary, cellmap=blackmap)
    g.GDSII_write(whitelibrary)

    # rename white cells into original black cell names:
    #g = nd.GDSII_stream(whitelibrary, cellmap=whitemap)
    #g.GDSII_write(whitelibrary)

    #white to black cell name map:
    b2w = dict(zip(allBlackCellNames, allWhiteCellNames))
    return whitelibrary, b2w
Exemple #6
0
ic1.bend(radius=20, angle=45).put()
y3 = yjunction().put()

ic1.bend(angle=-45, radius=20).put(y2.pin['b0'])
ic1.taper(width1=w_1, width2=w_2, length=t_len).put()
o1 = ic1.strt(length=5, width=w_2).put()

ic1.bend(angle=45, radius=20).put(y2.pin['b1'])
ic1.taper(width1=w_1, width2=w_2, length=t_len).put()
o2 = ic1.strt(length=5, width=w_2).put()

ic1.bend(angle=-45, radius=20).put(y3.pin['b0'])
ic1.taper(width1=w_1, width2=w_2, length=t_len).put()
o3 = ic1.strt(length=5, width=w_2).put()

ic1.bend(angle=45, radius=20).put(y3.pin['b1'])
ic1.taper(width1=w_1, width2=w_2, length=t_len).put()
o4 = ic1.strt(length=5, width=w_2).put()

taperdown = dha(name='taper down', layer=1, olayer=2, owidth=w_trench)
taperdown.strt(length=5)
taperdown.taper(length=t_len, width1=w_2, width2=w_1)
taperdown.strt(length=100)
t = taperdown.getcell()
t.put(o1.pin['b0'].move(-5))
t.put(o2.pin['b0'].move(-5))
t.put(o3.pin['b0'].move(-5))
t.put(o4.pin['b0'].move(-5))

nd.export_gds(filename='testchip.gds')
Exemple #7
0
nd.bend(angle=da*0.5,radius=10000,width=w).put()
nd.strt(length=l,width=w).put()
#nd.bend(angle=da,radius=((10000-12*pitch)/2).put()
#nd.bend(angle=da,radius=((10000-12*pitch-pitch)/2).put()
#nd.bend(angle=ua,radius=((10000-12*pitch-pitch)/2).put()


#cleave mark
nd.strt(length=300,width=8000).put(0,0)
nd.strt(length=300,width=8000).put(25.4*4*1000-5000,0)

nd.strt(length=300,width=15000).put(15000,15000/2)
nd.strt(length=300,width=15000).put(wafer-15000,15000/2)
#nd.text('15000',height=500).put(wafer-15000, 0)
#nd.text('wafer-15000',height=500).put(15000, 0)
nd.strt(length=300,width=15000).put(15000,-15000/2-4500)
nd.strt(length=300,width=15000).put(wafer-15000,-15000/2-4500)

#nd.text('XL',height=5000).put(48000, 20000)
#nd.text('L',height=5000).put(43000, 3000)
#nd.text('M',height=4000).put(35000, -12500)
#nd.text('S',height=4000).put(65500, -9000)
#nd.text('XS',height=4000).put(73000, 7400)
#


nd.bend(angle=360,radius=25.4*1000*2,layer=2,width=w).put(25.4*1000*2,-25.4*1000*2)


nd.export_gds()
Exemple #8
0
yj = split1_2_4_8().put(0,y4)

a.put(yj.pin['b0'])
a.put(yj.pin['b1'])
a.put(yj.pin['b2'])
a.put(yj.pin['b3'])
a.put(yj.pin['b4'])
a.put(yj.pin['b5'])
a.put(yj.pin['b6'])
a.put(yj.pin['b7'])

split1_2_4_8(taper_in=False).put(12000,y4, flop=True)

y4 += 500
yj = split1_2_4_8(taper_in= False).put(0,y4)

a.put(yj.pin['b0'])
a.put(yj.pin['b1'])
a.put(yj.pin['b2'])
a.put(yj.pin['b3'])
a.put(yj.pin['b4'])
a.put(yj.pin['b5'])
a.put(yj.pin['b6'])
a.put(yj.pin['b7'])

split1_2_4_8(taper_in= True).put(12000,y4, flop=True)


nd.export_gds(filename='testchip2.gds', flat=True)
Exemple #9
0
                                                 n * 50 - 20 * 1000)
    n = n + 1
nd.text('XL', height=5000).put(48000, 20000)

# dose 1200mj/cm2

n = 0
while n < 10:
    nd.strt(length=25.4 * 2 * 1000, width=w).put(25.4 * 1000,
                                                 n * 50 - 30 * 1000)
    n = n + 1
nd.text('XL', height=5000).put(48000, 20000)
# dose 1400mj/cm2

n = 0
while n < 10:
    nd.strt(length=25.4 * 2 * 1000, width=w).put(25.4 * 1000,
                                                 n * 50 - 40 * 1000)
    n = n + 1
nd.text('XL', height=5000).put(48000, 20000)
# dose 1400mj/cm2

n = 0
while n < 10:
    nd.strt(length=25.4 * 2 * 1000, width=w).put(25.4 * 1000,
                                                 n * 50 - 30 * 1000)
    n = n + 1
nd.text('XL', height=5000).put(48000, 20000)

nd.export_gds(filename='dose_test.gds')
Exemple #10
0
path_structure.strt(length=20)
path_structure.arc(angle=90, radius=20)
path_structure.eulerbend(p=0.2, angle=-90, radius=20)
path_structure.taper(width1=0.5, width2=5, length=50)
path_structure.strt(length=10)
path_structure.taper(width1=5, width2=0.5, length=20)

# to place the structure, get the cell with the getcell() method, then place that using the cells put() method
# cells can also be place multiple places with specified position

cell = path_structure.getcell()
cell.put()
cell.put(0, -50)

#export to GDS
nd.export_gds(filename='dha_elements_usage_example_1.gds')

# for repeated structures with varying parameters, it is maybe better to define the cell in a function:


def parametrized_cell(w1, w2, bend_radius, length1, length2, trenchwidth=5):
    name = 'parametrized cell with taper lenght = ' + str(length2)
    p = dha(name=name, layer=1, olayer=2, width=w1, owidth=trenchwidth)
    p.strt(length=length1)
    p.taper(width1=w1, width2=w2, length=length2)
    p.eulerbend(radius=bend_radius, angle=90)
    p.taper(width1=w2, width2=w1, length=length2)
    p.strt(length=length1)
    cell = p.getcell()
    return cell
Exemple #11
0
def angle_drc(cell, rules=None, basename=None, version_layer=None):
    """Apply intantiation DRC rules to cell hierarchy and scan for black boxes.

    The format of angle DRC rules:

    rule_dict = {
      'angle':
        <cell_basename>:
          'noflip': # optional level if flip state has to be False
            'values': <list of allowed angles>
            'domain': <list allowed domains>
          'flip': # optional level if flip state has to be True
            'values': <list of allowed angles>
            'domain': <list allowed domains>111
      }

    Example::

    somerules = {
      'laser':
        'angle':
          'values': [0, 180]
      'wild_bb':
        'noflip':
          'domains: [[25, 50], [140, 260]]
        'flip':
          'values': [0]
          'domains': [[150, 210]]
      }
    instance_drc(rules=somerules, cell=<your Cell>)

    Args:
        rules (dict): drc rules for instantiation
        cell (Cell): cell (and subcells) to rundrc on
        version_layer (layer): layer containing the cell's version annotation

    Returns:
        Cell: cell with angle DRC result to overlay with the gds design.
    """
    global cnt, drclog, items

    if basename is None:
        basename = "{}".format(cell.cell_name)

    if rules is None:
        rules = nd.cfg.drc_instance_angle

    if version_layer is None:
        nd.logger.warning(
            'version layer missing. Will not create a black box overview.')
    else:
        version_layer = nd.get_layer(version_layer)
    cnt = 0

    #drclogname = os.path.join(basename+'.'+drc_filename)
    #drclog = open(drclogname, 'w')

    #drclog.write("DRC on cell: {}\n".format(cell.cell_name))
    now = datetime.datetime.now()
    #drclog.write('datetime: {}\n'.format(now.strftime("%Y-%m-%d %H:%M")))

    # Get instance info from topcell down.
    positions = []
    for params in nd.cell_iter(cell, flat=True, infolevel=0):
        if params.cell_start:

            # 1. detect black box (besides DRC check):
            version = ''
            for anno, pos in params.iters['annotation']:
                if anno.layer == version_layer:
                    version = anno.text  # TODO: what if multiple annotations exist?

            # 2. store position for DRC and possible version:
            positions.append((params.cell.cell_basename, params.cell.cell_name,
                              params.transflip_glob, version))

    # cellname order needs to be reverse-ordered match the longest possible base name first:
    cell_rules_angle = OrderedDict(sorted(rules['angle'].items(),
                                          reverse=True))
    for cellbasename, name, (trans, flip), version in positions:
        x, y, a = trans.xya()
        if version != '':
            blocks.append((cellbasename, version))
        for bb, rules in cell_rules_angle.items():
            if name.startswith(bb):
                angle_rules_flip = rules.get('flip', None)
                angle_rules_noflip = rules.get('noflip', None)
                if angle_rules_flip is not None and flip:
                    drc_angle(name,
                              rules=angle_rules_flip,
                              flip_state=True,
                              xya=[x, y, a],
                              flip=flip)

                elif angle_rules_noflip is not None and not flip:
                    drc_angle(name,
                              rules=angle_rules_noflip,
                              flip_state=False,
                              xya=[x, y, a],
                              flip=flip)

                elif flip and angle_rules_flip is None and angle_rules_noflip is not None:
                    cnt += 1
                    msg = "  flip=True not allowed\n"
                    items.append((cnt, name, [x, y, a], flip, msg))
                    msg = "#{} ERROR cell '{}' @ ({:.3f}, {:.3f}, {:.3f}), flip={}\n{}".\
                        format(str(cnt).zfill(4), name, x, y, a, flip, msg)
                    #drclog.write(msg)
                    nd.logger.error(msg)

                elif not flip and angle_rules_noflip is None and angle_rules_flip is not None:
                    cnt += 1
                    msg = "  flip=False not allowed\n"
                    items.append((cnt, name, [x, y, a], flip, msg))
                    msg = "#{} ERROR cell '{}' @ ({:.3f}, {:.3f}, {:.3f}), flip={}\n{}".\
                        format(str(cnt).zfill(4), name, x, y, a, flip, msg)
                    #drclog.write(msg)
                    nd.logger.error(msg)

                elif rules != {}:
                    drc_angle(name,
                              rules=rules,
                              flip_state=None,
                              xya=[x, y, a],
                              flip=flip)
                break  # only the first hit (longest match of a cell in reversed ordered bb is the match
    nd.logger.info("angle violation items found: {}".format(cnt))
    #drclog.write("items found: {}".format(cnt))
    #drclog.close()
    #nd.logger.info("exported {}".format(drclogname))

    # Save DRC results as cells to gds to load on top of the design
    with nd.Cell('{}_drc'.format(cell.cell_name)) as DRC:
        for i in items:
            with nd.Cell(str(i[0]).zfill(4)) as C:
                bbox = nd.cfg.cellnames[i[1]].bbox
                points = [(bbox[0], bbox[1]), (bbox[0], bbox[3]),
                          (bbox[2], bbox[3]), (bbox[2], bbox[1])]
                #print(i[1], i[2], flip, points)
                #print(i)
                nd.Polygon(points=points,
                           layer=nd.cfg.drc_layer_instance_angle).put(
                               0)  # put(*i[2], flop=i[3])
            C.put(*i[2], flip=i[3])
    gdsname = os.path.join(basename + '.drc.gds')
    nd.export_gds(DRC, filename=gdsname, clear=False)

    # Save manifest
    if version_layer is not None:
        countBBs = Counter(blocks)
        bblistname = os.path.join(basename + '.' + blocklist_filename)
        F = open(bblistname, 'w')
        F.write('#datetime: {}\n'.format(now.strftime("%Y-%m-%d %H:%M")))
        L, D, T = nd.cfg.layername2LDT[version_layer]
        F.write("#version_layer: ({}, {})\n".format(L, D))
        F.write("{:6} block_info\n".format('#units'))
        for bb in sorted(countBBs.keys()):
            F.write("{:6} {}\n".format(countBBs[bb], bb))
        F.close()
        nd.logger.info("exported {}".format(bblistname))

    return DRC