Skip to content

Commit

Permalink
support both side gate contacts for sky130 mos layout (#51)
Browse files Browse the repository at this point in the history
* support both side gate contacts for sky130 mos layout

* consistent punctuation
  • Loading branch information
rahulk29 authored Oct 18, 2024
1 parent c9420cc commit 83de94c
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 21 deletions.
41 changes: 30 additions & 11 deletions pdks/sky130_common_pdk/src/mos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,6 @@ impl Sky130Pdk {
let gate_ct = ctx.instantiate::<Via>(&gate_ctp)?;
let gate_bbox = gate_ct.layer_bbox(poly);

let mut gate_pins = Vec::with_capacity(nf as usize);

let xpoly = x0 - POLY_DIFF_EXTENSION;
let mut ypoly = y0 + DIFF_EDGE_TO_GATE;
let wpoly = cx - xpoly + POLY_DIFF_EXTENSION;
Expand All @@ -141,9 +139,13 @@ impl Sky130Pdk {
let poly_fudge_x = 60;
let mut poly_rects = Vec::with_capacity(nf as usize);
for _ in 0..nf {
let mut p1x = xpoly + wpoly;
if params.contact_strategy == GateContactStrategy::BothSides {
p1x += poly_fudge_x;
};
let rect = Rect {
p0: Point::new(xpoly - poly_fudge_x, ypoly),
p1: Point::new(xpoly + wpoly, ypoly + params.length()),
p1: Point::new(p1x, ypoly + params.length()),
};
poly_rects.push(rect);
ctx.draw(Element {
Expand All @@ -152,17 +154,16 @@ impl Sky130Pdk {
inner: Shape::Rect(rect),
})?;

ypoly += params.length();
ypoly += FINGER_SPACE;
ypoly += params.length() + FINGER_SPACE;
}

let gate_span = Span::new(poly_rects[0].p0.y, poly_rects.last().unwrap().p1.y);
// Place gate contacts and create gate ports
match params.contact_strategy {
GateContactStrategy::SingleSide => {
GateContactStrategy::SingleSide | GateContactStrategy::BothSides => {
assert!(
nf <= 3,
"can only contact nf=3 transistors on a single side"
"can only contact nf>=3 transistors on a single side"
);
let line = gate_bbox.height();
let space = POLY_SPACE;
Expand All @@ -174,6 +175,7 @@ impl Sky130Pdk {
);

let mut npc_boxes = Vec::new();
let mut npc_boxes_x = Vec::new();

for i in 0..nf as i64 {
let empty_rect = Rect::new(Point::zero(), Point::zero());
Expand All @@ -195,16 +197,33 @@ impl Sky130Pdk {
let mut port = CellPort::new(format!("gate_{i}"));
port.add(gate_metal, Shape::Rect(ct_box));
ctx.add_port(port).unwrap();
gate_pins.push(ct_box);

if params.contact_strategy == GateContactStrategy::BothSides {
let mut gate_ct = ctx.instantiate::<Via>(&gate_ctp)?;
let ofsx = rect.p1.x - gate_bbox.p0.x;
let ct_ofs = Point::new(ofsx, ofsy);
gate_ct.translate(ct_ofs);
let ct_box = gate_ct.layer_bbox(gate_metal).into_rect();
let mut port = CellPort::new(format!("gate_{i}_x"));
port.add(gate_metal, Shape::Rect(ct_box));
ctx.add_port(port).unwrap();
let npc_bbox = gate_ct.layer_bbox(npc).into_rect();
npc_boxes_x.push(npc_bbox);
ctx.draw(gate_ct)?;
}

let npc_bbox = gate_ct.layer_bbox(npc).into_rect();
npc_boxes.push(npc_bbox);

ctx.draw(gate_ct)?;
}

let top_npc = npc_boxes.last().unwrap();
for boxes in [npc_boxes, npc_boxes_x] {
if boxes.is_empty() {
continue;
}
let top_npc = boxes.last().unwrap();
let npc_merge_rect = Rect::new(
Point::new(npc_boxes[0].p0.x, npc_boxes[0].p0.y),
Point::new(boxes[0].p0.x, boxes[0].p0.y),
Point::new(top_npc.p1.x, top_npc.p1.y),
);
ctx.draw(Element {
Expand Down
12 changes: 7 additions & 5 deletions substrate/src/pdk/mos/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,17 @@ pub struct LayoutMosParams {
/// Specifies the geometric arrangement of contacts for transistor gates.
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum GateContactStrategy {
/// Attempt to place all contacts on one side (usually the left)
/// Attempt to place all contacts on one side (usually the left).
SingleSide,
/// Alternate contact placement
/// Attempt to place contacts on both sides of the transistor.
BothSides,
/// Alternate contact placement.
Alternate,
/// ABBA placement
/// ABBA placement.
Abba,
/// Merge all contacts on one side (usually the left)
/// Merge all contacts on one side (usually the left).
Merge,
/// Other; effect depends on layout generator
/// Other; effect depends on layout generator.
Other(String),
}

Expand Down
10 changes: 5 additions & 5 deletions substrate/tests/mos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,20 @@ fn test_sky130_mos_nand2() {
&LayoutMosParams {
skip_sd_metal: vec![vec![]; 2],
deep_nwell: false,
contact_strategy: substrate::pdk::mos::GateContactStrategy::Merge,
contact_strategy: substrate::pdk::mos::GateContactStrategy::BothSides,
devices: vec![
MosParams {
w: 200_000,
w: 2000,
l: 150,
m: 1,
nf: 5,
nf: 2,
id: MosId::new(0),
},
MosParams {
w: 100_000,
w: 4000,
l: 150,
m: 1,
nf: 5,
nf: 2,
id: MosId::new(1),
},
],
Expand Down

0 comments on commit 83de94c

Please sign in to comment.