Skip to content

Commit

Permalink
feat(atoll): use virtual layer for tile outline
Browse files Browse the repository at this point in the history
feat(atoll): make abstract generator function part of Abstract
  • Loading branch information
rahulk29 committed Dec 31, 2023
1 parent 1e3d42b commit b0231d7
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 78 deletions.
151 changes: 80 additions & 71 deletions libs/atoll/src/abs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@ use substrate::geometry::bbox::Bbox;
use substrate::geometry::transform::Transformation;
use substrate::layout::element::Text;

use substrate::context::PdkContext;
use substrate::geometry::point::Point;
use substrate::geometry::rect::Rect;
use substrate::io::layout::Builder;
use substrate::layout::bbox::LayerBbox;
use substrate::layout::element::Shape;
use substrate::layout::element::{CellId, Element, RawCell};
use substrate::layout::{CellBuilder, Draw, DrawReceiver, ExportsLayoutData, Layout};
use substrate::pdk::layers::HasPin;
use substrate::pdk::layers::{HasPin, Layer};
use substrate::pdk::Pdk;
use substrate::schematic::ExportsNestedData;
use substrate::{arcstr, layout};
Expand Down Expand Up @@ -148,6 +150,83 @@ impl AtollAbstract {
pub fn physical_origin(&self) -> Point {
self.lcm_bounds.lower_left() * self.slice().lcm_units()
}

/// Generates an abstract view of a layout cell.
pub fn generate<PDK: Pdk, T: ExportsNestedData + ExportsLayoutData>(
ctx: &PdkContext<PDK>,
layout: &layout::Cell<T>,
) -> AtollAbstract {
let stack = ctx
.get_installation::<LayerStack<PdkLayer>>()
.expect("must install ATOLL layer stack");
let virtual_layers = ctx.install_layers::<crate::VirtualLayers>();

let cell = layout.raw();
let bbox = cell
.layer_bbox(virtual_layers.outline.id())
.expect("cell must provide an outline on ATOLL virtual layer");

let top = top_layer(cell, &*stack)
.expect("cell did not have any ATOLL routing layers; cannot produce an abstract");
let top = if top == 0 { 1 } else { top };

let slice = stack.slice(0..top + 1);

let xmin = div_floor(bbox.left(), slice.lcm_unit_width());
let xmax = div_ceil(bbox.right(), slice.lcm_unit_width());
let ymin = div_floor(bbox.bot(), slice.lcm_unit_height());
let ymax = div_ceil(bbox.top(), slice.lcm_unit_height());
let lcm_bounds = Rect::from_sides(xmin, ymin, xmax, ymax);

let nx = lcm_bounds.width();
let ny = lcm_bounds.height();

let grid = RoutingGrid::new((*stack).clone(), 0..top + 1);
let mut state = RoutingState::new((*stack).clone(), top, nx, ny);
let mut ports = Vec::new();
for (i, (name, geom)) in cell.ports().enumerate() {
let net = NetId(i);
ports.push(net);
if let Some(layer) = stack.layer_idx(geom.primary.layer().drawing()) {
let rect = match geom.primary.shape() {
substrate::geometry::shape::Shape::Rect(r) => *r,
substrate::geometry::shape::Shape::Polygon(p) => {
p.bbox().expect("empty polygons are unsupported")
}
};
println!("source rect = {rect:?}");
if let Some(rect) = grid.shrink_to_grid(rect, layer) {
println!("grid rect = {rect:?}");
for x in rect.left()..=rect.right() {
for y in rect.bot()..=rect.top() {
let xofs = xmin * slice.lcm_unit_width() / grid.xpitch(layer);
let yofs = ymin * slice.lcm_unit_height() / grid.ypitch(layer);
state.layer_mut(layer)[((x - xofs) as usize, (y - yofs) as usize)] =
PointState::Routed {
net,
via_down: false,
via_up: false,
};
}
}
}
}
}

let layers = state
.layers
.into_iter()
.map(|states| LayerAbstract::Detailed { states })
.collect();

AtollAbstract {
top_layer: top,
lcm_bounds,
grid: RoutingGrid::new((*stack).clone(), 0..top + 1),
ports,
layers,
}
}
}

/// The abstracted state of a single routing layer.
Expand Down Expand Up @@ -197,76 +276,6 @@ fn top_layer_inner(
top
}

/// Generates an abstract view of a layout cell.
pub fn generate_abstract<T: ExportsNestedData + ExportsLayoutData>(
layout: &layout::Cell<T>,
stack: &LayerStack<PdkLayer>,
) -> AtollAbstract {
let cell = layout.raw();
let bbox = cell.bbox().unwrap();

let top = top_layer(cell, stack)
.expect("cell did not have any ATOLL routing layers; cannot produce an abstract");
let top = if top == 0 { 1 } else { top };

let slice = stack.slice(0..top + 1);

let xmin = div_floor(bbox.left(), slice.lcm_unit_width());
let xmax = div_ceil(bbox.right(), slice.lcm_unit_width());
let ymin = div_floor(bbox.bot(), slice.lcm_unit_height());
let ymax = div_ceil(bbox.top(), slice.lcm_unit_height());
let lcm_bounds = Rect::from_sides(xmin, ymin, xmax, ymax);

let nx = lcm_bounds.width();
let ny = lcm_bounds.height();

let grid = RoutingGrid::new(stack.clone(), 0..top + 1);
let mut state = RoutingState::new(stack.clone(), top, nx, ny);
let mut ports = Vec::new();
for (i, (name, geom)) in cell.ports().enumerate() {
let net = NetId(i);
ports.push(net);
if let Some(layer) = stack.layer_idx(geom.primary.layer().drawing()) {
let rect = match geom.primary.shape() {
substrate::geometry::shape::Shape::Rect(r) => *r,
substrate::geometry::shape::Shape::Polygon(p) => {
p.bbox().expect("empty polygons are unsupported")
}
};
println!("source rect = {rect:?}");
if let Some(rect) = grid.shrink_to_grid(rect, layer) {
println!("grid rect = {rect:?}");
for x in rect.left()..=rect.right() {
for y in rect.bot()..=rect.top() {
let xofs = xmin * slice.lcm_unit_width() / grid.xpitch(layer);
let yofs = ymin * slice.lcm_unit_height() / grid.ypitch(layer);
state.layer_mut(layer)[((x - xofs) as usize, (y - yofs) as usize)] =
PointState::Routed {
net,
via_down: false,
via_up: false,
};
}
}
}
}
}

let layers = state
.layers
.into_iter()
.map(|states| LayerAbstract::Detailed { states })
.collect();

AtollAbstract {
top_layer: top,
lcm_bounds,
grid: RoutingGrid::new(stack.clone(), 0..top + 1),
ports,
layers,
}
}

#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
pub struct DebugAbstract {
pub abs: AtollAbstract,
Expand Down
6 changes: 3 additions & 3 deletions libs/atoll/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@
pub mod abs;
pub mod grid;

use crate::abs::{generate_abstract, AtollAbstract};
use crate::abs::AtollAbstract;
use crate::grid::{LayerStack, PdkLayer};
use ::grid::Grid;
use ena::unify::{UnifyKey, UnifyValue};
Expand Down Expand Up @@ -503,7 +503,7 @@ impl<'a, PDK: Pdk + Schema> AtollTileBuilder<'a, PDK> {
) -> Instance<B> {
let layout = self.layout.generate(block.clone());
let schematic = self.schematic.instantiate(block);
let abs = generate_abstract(layout.raw_cell(), self.layer_stack.as_ref());
let abs = AtollAbstract::generate(&self.layout.ctx, layout.raw_cell());
let top = abs.top_layer;
Instance {
layout,
Expand All @@ -522,7 +522,7 @@ impl<'a, PDK: Pdk + Schema> AtollTileBuilder<'a, PDK> {
let layout = self.layout.generate(wrapper.clone());
let schematic = self.schematic.instantiate(wrapper);
// todo: generate abstract from AtollTile trait directly
let abs = generate_abstract(layout.raw_cell(), self.layer_stack.as_ref());
let abs = AtollAbstract::generate(&self.layout.ctx, layout.raw_cell());
let top = abs.top_layer;
Instance {
layout,
Expand Down
8 changes: 4 additions & 4 deletions tests/src/atoll/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::paths::get_path;
use crate::shared::pdk::sky130_open_ctx;
use atoll::abs::{generate_abstract, DebugAbstract};
use atoll::abs::{DebugAbstract, AtollAbstract};
use atoll::grid::{LayerStack, PdkLayer};
use atoll::{AtollIo, AtollTile, AtollTileBuilder, AtollTileWrapper};
use geometry::point::Point;
Expand Down Expand Up @@ -59,7 +59,7 @@ fn sky130_atoll_nmos_tile() {
// todo: add mechanism to have multiple ATOLL layer stacks (one per PDK)
let stack = ctx.get_installation::<LayerStack<PdkLayer>>().unwrap();

let abs = generate_abstract(handle.cell(), &*stack);
let abs = AtollAbstract::generate(&ctx, handle.cell());
ctx.write_layout(
DebugAbstract {
abs,
Expand Down Expand Up @@ -100,7 +100,7 @@ fn sky130_atoll_pmos_tile() {

let stack = ctx.get_installation::<LayerStack<PdkLayer>>().unwrap();

let abs = generate_abstract(handle.cell(), &*stack);
let abs = AtollAbstract::generate(&ctx, handle.cell());
ctx.write_layout(
DebugAbstract {
abs,
Expand Down Expand Up @@ -195,7 +195,7 @@ fn sky130_atoll_nmos_tile_autoroute() {
let handle = ctx.generate_layout(block);
let stack = ctx.get_installation::<LayerStack<PdkLayer>>().unwrap();

let abs = generate_abstract(handle.cell(), &stack);
let abs = AtollAbstract::generate(&ctx, handle.cell());
ctx.write_layout(
DebugAbstract {
abs,
Expand Down

0 comments on commit b0231d7

Please sign in to comment.