Faces

KQCircuit layers are grouped by faces and functionality. A chip’s “face” intuitively means the bottom or top sides of it. To identify faces in multi chip configurations we number the chips from “1”. For technical reasons we permit multiple faces in a particular side. For example “2b1” denotes the bottom face of the 2nd chip in a typical flip-chip configuration.

The example chips included in KQCircuits use up to four faces, describing a flip-chip architecture. Face 1t1 is the bottom chip, and also the face used for single-face designs. 2b1 is the bottom side of the top chip, connecting to 1t1 with indium bumps. See the DemoTwoface chip for an example flip-chip design. The faces 1b1 and 2t1 (representing the outer side of

Note

The face configuration is defined in default_layer_config.py. To learn about defining a custom configuration for different stackups, see Configuring faces.

Using faces

All KQC elements have a parameter face_ids, which is a list of the faces available to that element. When drawing geometry, the element should not use face_id strings directly, but use indices to self.face_ids. This way, each element can be placed on any face, simply by giving it the appropriate order of faces in face_ids.

Simple KQC elements draw geometry only on a single face, which is always the first face in face_ids. However, many elements (such as connectors, indium bumps, and TSVs) span multiple faces, and they use these faces based on the order they appear in face_ids, as shown in the examples below.

By default, face_ids=["1t1", "2b1", "1b1", "2t1"] for all elements, and this is the order used when dragging an element from the library in the KLayout GUI.

Creating shapes in faces

The function Element.get_layer() returns the correct layer for a face. By default, face 0 is used, i.e. the first face in face_ids. To draw in other faces, pass the index of the face to draw in:

# (the face_id passed to self.get_layer is actually an index to self.face_ids)
self.cell.shapes(self.get_layer("indium_bump", face_id=0)).insert(pya.DBox(0, 500, 500, 0))
self.cell.shapes(self.get_layer("indium_bump", face_id=1)).insert(pya.DBox(100, 400, 400, 100))

In this example, if self.face_ids==["1t1", "2b1"], the first shape is draw in in 1t1_indium_bump, and the second in 2b1_indium_bump.

Placing elements on faces

When inserting a child element in multi-face chips or elements, pass a re-ordered list or subset of self.face_ids to place the element on the desired faces.

For example, in a chip with self.face_ids==["1t1", "2b1"], an element can be placed on 2b1 as follows:

# Placing a single-face element in a different face than the default
self.insert_cell(Launcher, face_ids=[self.face_ids[1]])

For an element that spans multiple faces, one often changes the order of face ids:

# Placing a multi-face element with the parts in different faces swapped
self.insert_cell(FlipChipConnectorRf, face_ids=[self.face_ids[1], self.face_ids[0]])