-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2 from 6biscuits/zd_additions
Zd additions
- Loading branch information
Showing
9 changed files
with
275 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
import gdspy | ||
import os | ||
from SQDMetal.Utilities.MakeGDS import MakeGDS | ||
from SQDMetal.Utilities.QUtilities import QUtilities | ||
|
||
class ManipulateGDS: | ||
def __init__(self, import_path_gds, export_path_gds, import_cells=None, origin=(0,0)): | ||
''' | ||
Class that will load a GDS file and perform actions such as making an array of the passed design (or a subsection of) | ||
Inputs: | ||
import_path_gds - path to GDS file for import | ||
''' | ||
# clear gds library | ||
gdspy.current_library.cells.clear() | ||
# initialise ManipulateGDS | ||
self.infile = import_path_gds | ||
self.outfile = export_path_gds | ||
self.import_cells = import_cells | ||
self.origin = origin | ||
self.gds_units = 1e-6 | ||
# initiate gds cell and temp cell to help with copying | ||
self.lib = gdspy.GdsLibrary() | ||
# self.cell = self.lib.new_cell('Array') | ||
self.gds_in = gdspy.GdsLibrary(infile=import_path_gds) | ||
# list available cells and import cells | ||
print(f'\n\nAvailable cells:\n\t{list(self.gds_in.cells.keys())}\n') | ||
if import_cells == None: | ||
print(f'Imported: All\n') | ||
else: | ||
print(f'Imported:\n\t{import_cells}\n') | ||
|
||
def flatten_cells(self, cell_keys=None, export=False): | ||
""" | ||
Takes `cell_keys` (or all cells by default) from a GdsLibrary object and flattens them as seperate layers to a single cell export object. | ||
""" | ||
|
||
self.cell_flattened = self.lib.new_cell('Flattened') | ||
self.cell_temp = self.lib.new_cell('Temp') | ||
|
||
if not isinstance(cell_keys, list): | ||
print(f'Single cell: {cell_keys}') | ||
# get list of import cells (default: all) | ||
if cell_keys==None: | ||
cell_keys = list(self.gds_in.cells.keys()) | ||
else: | ||
cell_keys = list(cell_keys) | ||
# flatten all cells to single cell with different layers | ||
for layer_idx, key in enumerate(cell_keys): | ||
print(f"Copying cell '{key}' --> layer {layer_idx}") | ||
# copy polygons to temp cell (and shift origin if needed) | ||
self.cell_temp.add((gdspy.CellReference(self.gds_in.cells[key], origin=self.origin)).get_polygonsets()) | ||
|
||
self.cell_temp.flatten(single_layer=layer_idx) | ||
# add to cell 'Flattened' | ||
self.cell_flattened.add(self.cell_temp.get_polygonsets()) | ||
# reset temp cell | ||
self.cell_temp.remove_polygons(lambda pts, layer, datatype: layer==layer_idx) | ||
self.lib.remove(cell='Temp') | ||
if export: | ||
print(f"\nOutputting cell 'Flattened' ({len(self.cell_flattened.get_polygonsets())} polygons)\n\t--> {self.outfile}\n\n") | ||
|
||
self.lib.write_gds(self.outfile, cells=['Flattened']) | ||
|
||
|
||
|
||
def make_array_onChip(self, columns, rows, | ||
spacing=("0um", "0um"), chip_dimension=("20mm", "20mm"), export=True, export_path=None, use_cells=None): | ||
# import assertions | ||
assert (isinstance(chip_dimension, tuple) and isinstance(chip_dimension[0], str)), r"Input argument 'chip_dimension' should be a tuple contining strings of the chip's (x, y) dimensions with units - e.g. 'chip_dimension=('20mm', '20mm')', as in qiskit and SQDMetal." | ||
|
||
# default: copy all cells. Else use function input (if any), finally use class init input (if any) | ||
if use_cells != None: | ||
self.flatten_cells(cell_keys=use_cells) | ||
elif (self.import_cells == None) and (use_cells == None): | ||
self.flatten_cells(cell_keys=None) | ||
else: | ||
self.flatten_cells(cell_keys=self.import_cells) | ||
|
||
# initialise an array cell | ||
self.cell_array = self.lib.new_cell('Array') | ||
|
||
# do arraying | ||
arrays_of_polygonsets = gdspy.CellArray(self.cell_flattened, | ||
columns=columns, | ||
rows=rows, | ||
spacing=(QUtilities.parse_value_length(spacing[0])/self.gds_units,QUtilities.parse_value_length(spacing[1])/self.gds_units) | ||
).get_polygonsets() | ||
self.cell_array.add(arrays_of_polygonsets) | ||
|
||
# export if option is set | ||
if export: | ||
if export_path == None: | ||
array_export = self.outfile | ||
else: | ||
array_export = export_path | ||
self.lib.write_gds(array_export, cells=['Array']) | ||
print(f"\nOutputting cell 'Array' ({len(self.cell_array.get_polygonsets())} polygons)\n\t--> {array_export}\n\n") | ||
|
||
# TODO: add centering by default (i.e. so that the whole array is centred on (0,0)) | ||
|
||
return self.cell_array | ||
|
||
|
||
f = ManipulateGDS( | ||
import_path_gds="/Users/uqzdegna/Documents/Uni/PhD/qDesignDesk/junctions/manhattan_one_geo_v1.gds", | ||
export_path_gds="/Users/uqzdegna/Documents/Uni/PhD/qDesignDesk/junctions/ManipulateGDS_test.gds", | ||
origin=(0, 4000) | ||
) | ||
|
||
m = f.make_array_onChip(columns=16, | ||
rows=16, | ||
export=True, | ||
spacing=("500um", "500um"), | ||
use_cells=['TOP_main_2', 'TOP_main_1'], | ||
export_path="/Users/uqzdegna/Documents/Uni/PhD/qDesignDesk/junctions/ManipulateGDS_array.gds") | ||
|
||
exit() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
# Full chip maker | ||
|
||
Modules found under `SQDMetal.Utilities.FullChipMaker` used for semi-automated generation of circuits commonly used for research of superconducting quantum circuits, taking inputs for important wafer-scale parameters (wafer size, die size, die layout), and all relevant circuit parameters (frequencies, materials, width dimension, etc.). | ||
|
||
This module relies on `SQDMetal` modules such as `SQDMetal.Utilities.QUtilities`, `SQDMetal.Utilities.MakeGDS`, `SQDMetal.Utilities.Material`, and functions for the calculation of resonator parameters located in `SQDMetal.Utilities.QubitDesigner`. | ||
|
||
Currently, the supported circuits are: | ||
|
||
- `MultiDieChip.make_resonator_chip()` - creates a `.gds` full-wafer layout file for a simple coplanar waveguide $\lambda/4$ resonator chip containing a number of resonators (usually 5) capacitively coupled to a transmission line | ||
|
||
|
||
## Circuit types | ||
|
||
The circuits listed within the section are called as functions within the `MultiDieChip` class. | ||
|
||
|
||
### Hanger-mode $\lambda/4$ resonator chip | ||
|
||
To import, use: | ||
```python | ||
from SQDMetal.Utilities.FullChipMaker import MultiDieChip | ||
``` | ||
|
||
You can now generate a `.gds` file for the full multi-die chip with the function `make_resonator_chip` as follows: | ||
|
||
```python | ||
d = MultiDieChip.make_resonator_chip(export_filename="FullChipMakerDemo", export_path='gds_designs', cpw_width="25um",export_type="positive", text_label="Just a demo :)", chip_dimension=("8.4mm", "10.6mm"), text_size=400, text_position=(0.2, 0.9)) | ||
``` | ||
|
||
The above call mostly uses the default function values (which can be found in the source code), and user-input arguments. This produces the `.gds` shown below. | ||
|
||
![Example output from the make_resonator_chip function in the MultiDieChip class.](FullChipMaker.png) | ||
|
||
The full list of inputs are as follows: | ||
- `export_filename` - Filename for gds export (e.g. "test") | ||
- `export_path` - Path for export (e.g. 'exports'); the file will then be output to `/exports/test.gds` | ||
- `export_type` - (Defaults to "all") Export type for lithography as per `MakeGDS` (options: "all", "positive", "negative") | ||
- `frequency_range` - (Defaults to (6e9, 7e9)) Tuple containing minimum and maximum resonator frequencies in Hz | ||
- `num_resonators` - (Defaults to 5) Number of resonators per die | ||
- `cpw_width` - (Defaults to "9um") Width of the central trace on the feedline and resonators. The gap will be automatically calculated for 50 Ohm impedance based on the `substrate_material` | ||
- `coupling_gap` - (Defaults to "20um") Amount of ground plane in the coupling gap between the feedline and the resonator | ||
- `tl_y` - (Defaults to "0um") The die-relative y-value for the main straight of the feedline (NOTE: currently only "0um" is supported) | ||
- `res_vertical` - (Defaults to "1500um") Vertical length of resonator meanders | ||
- `lp_to_res` - (Defaults to "300um") Minimum distance between the launchpad taper and the coupling length of the left-most resonator | ||
- `lp_inset` - (Defaults to "0um") Inset of the launchpads along the x-axis relative to the die boundaries | ||
- `lp_dimension` - (Defaults to "600um") Width of the launchpads' conductive centre pad (the launchpad gap scales accordingly) | ||
- `lp_taper` - (Defaults to "300um") Length of the taper from launchpad to feedline | ||
- `substrate_material` - (Defaults to "silicon") Substrate material (currently only "silicon" and "sapphire" are supported) | ||
- `substrate_thickness` - (Defaults to "0.5mm") Substrate thickness | ||
- `film_thickness` - (Defaults to "100nm") Film thickness | ||
- `chip_dimension` - (Defaults to ("20mm", "20mm")) Dimensions of the chip as an (x, y) Tuple | ||
- `chip_border` - (Defaults to "500um") Chip border to leave un-patterned | ||
- `die_dimension` - (Defaults to ("7.1mm", "4.4mm")) Dimensions of the die as an (x, y) Tuple | ||
- `die_num` - (Defaults to [1, 1]) Die layout in [x, y] as a length-2 list | ||
- `fill_chip` - (Defaults to True) Boolean to choose whether the full chip is automatically populated with dies (over-rides `die_num` if True) | ||
- `markers_on` - (Defaults to True) Print dicing markers on export | ||
- `text_label` - (Optional) Text label to print on chip | ||
- `text_size` - (Defaults to 600) Text size | ||
- `text_position` - (Optional) Tuple of text label location as normalised (x, y) (e.g. (0.1, 0.9) will place the text label 1/10th of the way along the chip in the x-direction, and 9/10ths of the way up the chip in the y-direction) | ||
- `print_all_infos` - (Defaults to True) Choose whether to print info as the `.gds` is being generated | ||
|
||
|
||
|
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Oops, something went wrong.