Skip to content

Commit

Permalink
adding code and a test for parsing/storing DENSITY in a MACRO
Browse files Browse the repository at this point in the history
  • Loading branch information
nanobowers committed Jul 16, 2024
1 parent c771aa7 commit 76cb7ea
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 11 deletions.
52 changes: 43 additions & 9 deletions lef21/src/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,11 +208,12 @@ pub struct LefMacro {
#[builder(default)]
pub fixed_mask: bool,

/// Density Objects
#[serde(default, skip_serializing_if = "Option::is_none")]
#[builder(default, setter(strip_option))]
pub density: Option<Vec<LefDensityGeometries>>,

// Unsupported
/// Density Objects (Unsupported)
#[serde(default, skip_serializing)]
#[builder(default)]
pub density: Option<Unsupported>,
/// Properties (Unsupported)
#[serde(default, skip_serializing)]
#[builder(default)]
Expand Down Expand Up @@ -391,6 +392,37 @@ pub struct LefLayerGeometries {
#[builder(default, setter(strip_option))]
pub width: Option<LefDecimal>,
}

/// # Lef Density Geometry Store
///
/// Most LEF spatial data (e.g. ports, blockages) is organized by layer.
/// [LefDensityGeometries] stores the combination of a layer (name)
/// and a suite of rectangle density data on that layer.
///
/// [LefDensityGeometries] are the primary building block of [LefDensity].
///
#[derive(Clone, Default, Builder, Debug, Deserialize, Serialize, JsonSchema, PartialEq, Eq)]
#[builder(pattern = "owned", setter(into))]
pub struct LefDensityGeometries {
// Required
/// Layer Name
pub layer_name: String,
/// Geometries
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub geometries: Vec<LefDensityRectangle>,
}

/// # Lef Density Rectangle
/// Defined as a rectangle with a numeric density value. One or more of these geometries are associated
/// with a layer name in [LefDensityGeometries]
#[derive(Clone, Debug, Deserialize, Serialize, JsonSchema, PartialEq, Eq)]
pub struct LefDensityRectangle {
/// Location
pub pt1: LefPoint,
pub pt2: LefPoint,
/// Density Value
pub density_value: LefDecimal,
}
/// # Lef Via Instance
///
/// A located instance of via-type `via_name`, typically used as part of a [LefLayerGeometries] definition.
Expand Down Expand Up @@ -648,6 +680,13 @@ enumstr!(
Mask: "MASK",
UseMinSpacing: "USEMINSPACING",

Density: "DENSITY",
TaperRule: "TAPERRULE",
NetExpr: "NETEXPR",
SupplySensitivity: "SUPPLYSENSITIVITY",
GroundSensitivity: "GROUNDSENSITIVITY",
MustJoin: "MUSTJOIN",

// UNITS Fields
Units: "UNITS",
Time: "TIME",
Expand Down Expand Up @@ -680,11 +719,6 @@ enumstr!(
AntennaMaxCutCar: "ANTENNAMAXCUTCAR",

// Unsupported
TaperRule: "TAPERRULE",
NetExpr: "NETEXPR",
SupplySensitivity: "SUPPLYSENSITIVITY",
GroundSensitivity: "GROUNDSENSITIVITY",
MustJoin: "MUSTJOIN",
Property: "PROPERTY",
ManufacturingGrid: "MANUFACTURINGGRID",
ClearanceMeasure: "CLEARANCEMEASURE",
Expand Down
56 changes: 54 additions & 2 deletions lef21/src/read.rs
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,7 @@ pub enum LefParseContext {
Geometry,
Site,
Units,
Density,
Unknown,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
Expand Down Expand Up @@ -623,6 +624,9 @@ impl<'src> LefParser<'src> {
self.expect(TokenType::SemiColon)?;
mac.source(e)
}
LefKey::Density => {
mac.density(self.parse_density()?)
}
LefKey::End => {
self.advance()?; // End of Macro. Eat the END key
break;
Expand Down Expand Up @@ -790,6 +794,54 @@ impl<'src> LefParser<'src> {
self.ctx.pop();
Ok(LefPort { layers, class })
}
/// Parse a MACRO::DENSITY definition into a [Vec<LefDensityGeometries>]
fn parse_density(&mut self) -> LefResult<Vec<LefDensityGeometries>> {
self.ctx.push(LefParseContext::Density);
self.expect_key(LefKey::Density)?;
let mut dens_geoms: Vec<LefDensityGeometries> = Vec::new();

// Parse attributes and geometries
// Note this peeks rather than taking the next token,
// largely to accommodate the closing-delimeter-free `LAYER` / [LefDensityGeometries] definitions.
// Other keys generally advance by a Token *after* matching.

loop {
match self.peek_key()? {
LefKey::Layer => {
self.expect_key(LefKey::Layer)?; // Eat the opening LAYER keyword
let mut layer = LefDensityGeometriesBuilder::default();
layer = layer.layer_name(self.parse_ident()?); // Parse the layer-name
self.expect(TokenType::SemiColon)?;
let mut rects: Vec<LefDensityRectangle> = Vec::new();

loop {
match self.peek_key()? {
LefKey::Layer | LefKey::End => break, // End of geometries. (Really start/end of something else.)
LefKey::Rect => {
self.advance()?; // Eat the RECT keyword
let p1: LefPoint = self.parse_point()?;
let p2: LefPoint = self.parse_point()?;
let dens_value: LefDecimal = self.parse_number()?;
rects.push(LefDensityRectangle { pt1: p1, pt2: p2, density_value: dens_value });
self.expect(TokenType::SemiColon)?;
}
_ => self.fail(LefParseErrorType::InvalidKey)?,
}
}
layer = layer.geometries(rects);
let layer = layer.build()?;
dens_geoms.push(layer);
}
LefKey::End => {
self.advance()?; // Eat the END Token
break;
}
_ => self.fail(LefParseErrorType::InvalidKey)?,
}
}
self.ctx.pop();
Ok(dens_geoms)
}
/// Parse a [LefMacro]'s obstruction definitions
fn parse_obstructions(&mut self) -> LefResult<Vec<LefLayerGeometries>> {
self.expect_key(LefKey::Obs)?;
Expand Down Expand Up @@ -835,7 +887,7 @@ impl<'src> LefParser<'src> {
// and exit when another LAYER or END (of a higher-level thing) turn up.
// Note that on end-of-file, i.e. `peek_token` returning `None`, this will exit and return a valid [LefLayerGeometries].
// (Objects above it in the tree may error instead.)
let mut geoms = Vec::new();
let mut geoms: Vec<LefGeometry> = Vec::new();
let mut vias = Vec::new();
loop {
if self.peek_token().is_none() {
Expand Down Expand Up @@ -890,7 +942,7 @@ impl<'src> LefParser<'src> {
}
// Parse the two points
let p1 = self.parse_point()?;
let p2 = self.parse_point()?;
let p2: LefPoint = self.parse_point()?;
self.expect(TokenType::SemiColon)?;
// And return the Rect
Ok(LefGeometry::Shape(LefShape::Rect(mask, p1, p2)))
Expand Down
22 changes: 22 additions & 0 deletions lef21/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,28 @@ fn it_parses_lib2() -> LefResult<()> {
Ok(())
}

#[test]
fn it_parses_density_lib() -> LefResult<()> {
let src = r#"
VERSION 5.8 ;
UNITS DATABASE MICRONS 2000 ; END UNITS
MACRO macro_dens
CLASS BLOCK ;
SIZE 100.0 BY 100.0 ;
DENSITY
LAYER met6 ;
RECT 0.0 0.0 40.0 50.0 46.6 ;
RECT 0.0 50.0 100.0 100.0 90 ;
LAYER met2 ;
RECT 1.0 2.0 3.0 4.0 5.55 ;
END
END macro_dens
"#;
let lib = parse_str(src)?;
//check_yaml(&lib, &resource("lib2.yaml"));
Ok(())
}

#[test]
fn it_parses_no_end_library_5p6() -> LefResult<()> {
let src = r#"
Expand Down

0 comments on commit 76cb7ea

Please sign in to comment.