LEF/DEF input and output module for LibrEDA.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1146 lines
38 KiB

/*
* Copyright (c) 2021-2021 Thomas Kramer.
*
* This file is part of LibrEDA
* (see https://codeberg.org/libreda/libreda-lefdef).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//! Parser for LEF data streams.
//!
//! # References
//!
//! 1) LEF/DEF 5.7 <http://www.ispd.cc/contests/18/lefdefref.pdf>
//! 2) LEF/DEF 5.8 <http://coriolis.lip6.fr/doc/lefdef/lefdefref/lefdefref.pdf>
// TODO: Remove this once this module is finished.
#![allow(unused_variables)]
use crate::stream_parser::*;
use itertools::PeekingNext;
use crate::lef_ast::*;
use crate::common::*;
use crate::stream_parser::LefDefError;
use libreda_db::prelude as db;
use std::io::Read;
/// Read a step pattern (repetition).
/// Expects a "DO" keyword at the beginning.
fn read_step_pattern<I>(tk: &mut Tokenized<I>) -> Result<StepPattern, LefDefError>
where I: Iterator<Item=char> + PeekingNext {
tk.expect("DO")?;
let num_x: u64 = tk.take_and_parse()?;
tk.expect("BY")?;
let num_y: u64 = tk.take_and_parse()?;
tk.expect("STEP")?;
let space_x: f64 = tk.take_and_parse()?;
let space_y: f64 = tk.take_and_parse()?;
Ok(StepPattern {
num_x,
num_y,
space_x,
space_y,
})
}
/// Read layer geometries as used in macro obstructions and pin ports (OBS, PIN).
fn read_layer_geometries<I>(tk: &mut Tokenized<I>) -> Result<Option<LayerGeometries>, LefDefError>
where I: Iterator<Item=char> + PeekingNext {
if tk.test("LAYER")? {
let mut layer = LayerGeometries::default();
let layer_name = tk.take()?;
layer.layer_name = layer_name;
layer.except_pg_net = tk.test("EXCEPTPGNET")?;
// SPACING and DESIGNRULEWIDTH are mutually exclusive.
let spacing_or_min_design_rule_width = if tk.test("SPACING")? {
let min_spacing: f64 = tk.take_and_parse()?;
Some(SpacingOrDesignRuleWidth::MinSpacing(min_spacing))
} else if tk.test("DESIGNRULEWIDTH")? {
let effective_width: f64 = tk.take_and_parse()?;
Some(SpacingOrDesignRuleWidth::DesignRuleWidth(effective_width))
} else {
None
};
tk.expect(";")?;
layer.spacing_or_designrule_width = spacing_or_min_design_rule_width;
if tk.test("WIDTH")? {
let width: f64 = tk.take_and_parse()?;
tk.expect(";")?;
layer.width = Some(width);
}
// PATH, RECT, POLYGON ...
loop {
if tk.test("PATH")? {
let iterate = tk.test("ITERATE")?;
// Read points.
let mut points = Vec::new();
while !tk.peeking_test("DO")? && !tk.peeking_test(";")? {
points.push(read_point::<f64, _>(tk)?.into())
}
let step_pattern = if iterate {
// Read step pattern.
Some(read_step_pattern(tk)?)
} else {
None
};
tk.expect(";")?;
let width = layer.width.unwrap(); // TODO: Is this correct?
layer.geometries.push(Geometry {
step_pattern,
shape: Shape::Path(width, points),
})
} else if tk.test("RECT")? {
let iterate = tk.test("ITERATE")?;
let (p1, p2) = read_rect(tk)?;
let step_pattern = if iterate {
// Read step pattern.
Some(read_step_pattern(tk)?)
} else {
None
};
tk.expect(";")?;
// let rect = Rect::new(p1, p2);
layer.geometries.push(
Geometry {
step_pattern,
shape: Shape::Rect(p1.into(), p2.into()),
}
)
} else if tk.test("POLYGON")? {
let iterate = tk.test("ITERATE")?;
// Read points.
let mut points = Vec::new();
while !tk.peeking_test("DO")? && !tk.peeking_test(";")? {
points.push(read_point(tk)?.into())
}
let step_pattern = if iterate {
// Read step pattern.
Some(read_step_pattern(tk)?)
} else {
None
};
tk.expect(";")?;
layer.geometries.push(Geometry {
step_pattern,
shape: Shape::Polygon(points),
})
} else if tk.test("VIA")? {
// TODO
let iterate = tk.test("ITERATE")?;
let point = read_point::<f64, _>(tk)?;
let via_name = tk.take()?;
if iterate {
// Read step pattern.
let step_pattern = read_step_pattern(tk)?;
}
tk.expect(";")?;
return Err(LefDefError::NotImplemented("VIA inside layer geometry."));
} else {
break;
}
}
Ok(Some(layer))
} else {
Ok(None)
}
}
/// Try to read a MACRO PIN definition.
/// Returns `None` if there is none.
fn try_read_pin<I>(tk: &mut Tokenized<I>) -> Result<Option<MacroPin>, LefDefError>
where I: Iterator<Item=char> + PeekingNext {
if tk.test("PIN")? {
let mut pin = MacroPin::default();
let pin_name = tk.take()?;
pin.name = pin_name;
loop {
if tk.test("END")? {
tk.expect(pin.name.as_str())?;
break;
} else if tk.test("TAPERRULE")? {
let rule_name = tk.take()?;
tk.expect(";")?;
pin.taper_rule = Some(rule_name);
} else if tk.test("DIRECTION")? {
let direction: PinDirection = tk.take_and_parse()?; // INPUT | OUTPUT [TRISTATE] | INOUT | FEEDTHRU
// In case of OUTPUT read the optional TRISTATE flag.
let direction = match direction {
PinDirection::Output(_) => {
let tristate = tk.test("TRISTATE")?;
PinDirection::Output(tristate)
}
d => d
};
tk.expect(";")?;
pin.direction = Some(direction);
} else if tk.test("USE")? {
let signal_use: SignalUse = tk.take_and_parse()?; // SIGNAL | ANALOG | POWER | GROUND | CLOCK
tk.expect(";")?;
pin.signal_use = Some(signal_use);
} else if tk.test("NETEXPR")? {
let net_expr = tk.take()?;
tk.expect(";")?;
log::warn!("Skipping NETEXPR of the MACRO PIN (not implemented).");
} else if tk.test("SUPPLYSENSITIVITY")? {
let pin_name = tk.take()?;
tk.expect(";")?;
pin.supply_sensitivity = Some(pin_name);
} else if tk.test("GROUNDSENSITIVITY")? {
let pin_name = tk.take()?;
tk.expect(";")?;
pin.ground_sensitivity = Some(pin_name);
} else if tk.test("SHAPE")? {
let shape: PinShape = tk.take_and_parse()?; // ABUTMENT | RING | FEEDTHRU
tk.expect(";")?;
pin.shape_type = Some(shape);
} else if tk.test("MUSTJOIN")? {
let pin_name = tk.take()?;
tk.expect(";")?;
pin.must_join = Some(pin_name);
} else if tk.test("PORT")? {
let mut port = MacroPinPort::default();
if tk.test("CLASS")? {
let class: PortClass = tk.take_and_parse()?; // NONE | CORE | BUMP
tk.expect(";")?;
port.class = Some(class);
}
// Layer geometries.
while let Some(geo) = read_layer_geometries(tk)? {
port.geometries.push(geo);
}
tk.expect("END")?;
pin.ports.push(port);
} else if tk.test("PROPERTY")? {
// TODO
tk.skip_until(";")?;
} else {
// ANTENNA related
log::warn!("Skipping ANTENNA* properties of the MACRO PIN (not implemented).");
tk.skip_until(";")?;
}
}
Ok(Some(pin))
} else {
Ok(None)
}
}
/// Read obstructions as used in MACRO definitions.
/// Obstruction are defined by syntax of layer geometries.
fn try_read_obs<I>(tk: &mut Tokenized<I>) -> Result<Option<Vec<LayerGeometries>>, LefDefError>
where I: Iterator<Item=char> + PeekingNext {
if tk.test("OBS")? {
// Layer geometries.
let mut geometries = Vec::new();
while let Some(geo) = read_layer_geometries(tk)? {
geometries.push(geo)
}
tk.expect("END")?;
Ok(Some(geometries))
} else {
Ok(None)
}
}
/// Parse a LEF file from byte stream.
pub fn read_lef_bytes<R: Read>(reader: &mut R) -> Result<LEF, LefDefError>
{
read_lef_chars(
reader.bytes().map(|b| b.unwrap() as char)
)
}
/// Parse a LEF file from an iterator over `char`s.
pub fn read_lef_chars<I>(chars: I) -> Result<LEF, LefDefError>
where I: Iterator<Item=char>
{
let mut line_num = 0;
let mut char_num = 0; // Position on the line.
// Count newlines.
let line_count = chars.inspect(|&c| {
char_num += 1;
if c == '\n' {
line_num += 1;
char_num = 0;
}
});
let result = read_lef_impl(line_count);
if result.is_err() {
eprintln!("LEF error on line: {} (at {})", line_num, char_num);
log::error!("LEF error on line: {} (at {})", line_num, char_num);
}
result
}
/// Parse a LEF file from an iterator over `char`s.
fn read_lef_impl<I>(chars: I) -> Result<LEF, LefDefError>
where I: Iterator<Item=char>
{
let mut library = LEF::default();
// Token stream.
let mut tk = tokenize(chars);
library.busbitchars = ('[', ']');
library.dividerchar = '/';
// let mut name_case_sensitive = true;
tk.advance(); // Go to first token.
loop {
// dbg!(tk.current_token_str());
if tk.test("END")? {
if tk.test("LIBRARY")? {
// END of library file.
break;
}
} else if tk.test("VERSION")? {
let version = tk.take()?;
tk.expect(";")?;
library.version = Some(version);
} else if tk.test("BUSBITCHARS")? {
let chars = tk.take()?;
if chars.len() == 2 {
let start = chars.chars().nth(0).unwrap();
let end = chars.chars().nth(1).unwrap();
if start == end {
log::error!("Bus bit chars cannot be equal: {}", start);
return Err(LefDefError::IllegalBusBitChars(start, end));
}
log::debug!("Bus bit chars: '{}' '{}'", start, end);
library.busbitchars = (start, end);
} else {
return Err(LefDefError::InvalidCharacter); // TODO: More precise error.
}
tk.expect(";")?;
} else if tk.test("NAMESCASESENSITIVE")? {
tk.take()?; // TODO
tk.expect(";")?;
} else if tk.test("DIVIDERCHAR")? {
let divchar = tk.take()?;
if divchar.len() == 1 {
library.dividerchar = divchar.chars().nth(0).unwrap();
log::debug!("Divider char: '{}'", library.dividerchar);
} else {
return Err(LefDefError::InvalidCharacter); // TODO: More precise error.
}
tk.expect(";")?;
}
// UNITS
else if tk.test("UNITS")? {
loop {
if tk.test("END")? {
tk.expect("UNITS")?;
break;
} else {
let u = library.technology.units;
let mut time = u.time_ns;
let mut cap = u.capacitance_pf;
let mut res = u.resistance_ohms;
let mut power = u.power_mw;
let mut current = u.current_ma;
let mut voltage = u.voltage_v;
let mut database = u.database_microns;
let mut freq = u.frequency_mega_hz;
let mut unit_types = [
("TIME", "NANOSECONDS", &mut time),
("CAPACITANCE", "PICOFARADS", &mut cap),
("RESISTANCE", "OHMS", &mut res),
("POWER", "MILLIWATTS", &mut power),
("CURRENT", "MILLIAMPS", &mut current),
("VOLTAGE", "VOLTS", &mut voltage),
("DATABASE", "MICRONS", &mut database),
("FREQUENCY", "MEGAHERTZ", &mut freq),
];
for (unit_type, unit, value) in unit_types.iter_mut() {
if tk.test(unit_type)? {
tk.expect(unit)?;
let parsed = tk.take_and_parse::<u64>()?;
log::debug!("Unit: {} {} {}", unit_type, unit, parsed);
**value = parsed;
break;
}
}
// Create data structure of units.
let units = Units {
time_ns: time,
capacitance_pf: cap,
resistance_ohms: res,
power_mw: power,
current_ma: current,
voltage_v: voltage,
database_microns: database,
frequency_mega_hz: freq,
};
// Write units to library.
library.technology.units = units;
tk.expect(";")?;
}
}
} else if tk.test("CLEARANCEMEASURE")? {
library.technology.clearance_measure = tk.take_and_parse()?;
tk.expect(";")?;
}
// PROPERTYDEFINITIONS
else if tk.test("PROPERTYDEFINITIONS")? {
loop {
if tk.test("END")? {
tk.expect("PROPERTYDEFINITIONS")?;
break;
} else {
let object_type = tk.take()?;
let prop_name = tk.take()?;
let prop_type = tk.take()?;
if tk.test("RANGE")? {
let range_start = tk.take()?;
let range_end = tk.take()?;
}
if !(tk.test(";")?) {
let default_value = tk.take()?;
tk.expect(";")?;
}
// TODO: Store the property.
library.technology.property_definitions
.insert(prop_name, ());
}
}
}
// MANUFACTURINGGRID
else if tk.test("MANUFACTURINGGRID")? {
let grid: f64 = tk.take_and_parse()?;
if grid < 0. {
log::warn!("MANUFACTURINGGRID must be positive ({}).", grid);
}
library.technology.manufacturing_grid = Some(grid);
tk.expect(";")?;
}
// MAXVIASTACK
else if tk.test("MAXVIASTACK")? {
let value: u64 = tk.take_and_parse()?;
let range = if tk.test("RANGE")? {
let bottom_layer = tk.take()?;
let top_layer = tk.take()?;
Some((bottom_layer, top_layer))
} else {
None
};
library.technology.max_via_stack = Some((value, range));
tk.expect(";")?;
}
// NONDEFAULTRULE
else if tk.test("NONDEFAULTRULE")? {
// [1] p. 203
let hardspacing = tk.test("HARDSPACING")?;
return Err(LefDefError::NotImplemented("NONDEFAULTRULE"));
}
// LAYER
else if tk.test("LAYER")? {
let layer_name = tk.take()?;
tk.expect("TYPE")?;
if tk.test("CUT")? {
// TYPE CUT
let mut layer = CutLayer::default();
layer.name = layer_name.clone();
loop {
if tk.test("END")? {
break;
} else if tk.test("MASK")? {
layer.mask_num = Some(tk.take_and_parse()?);
} else if tk.test("SPACING")? {
let mut cut_spacing = CutSpacingRule::default();
cut_spacing.spacing = tk.take_and_parse()?;
cut_spacing.center_to_center = tk.test("CENTERTOCENTER")?;
cut_spacing.same_net = tk.test("SAMENET")?;
if tk.test("LAYER")? {
let second_layer_name = tk.take()?;
let stack = tk.test("STACK")?;
// TODO
} else if tk.test("ADJACENTCUTS")? {
if !tk.peeking_test("WITHIN")? {
let n: u32 = tk.take_and_parse()?; // {2 | 3 | 4}
}
tk.expect("WITHIN")?;
let cut_within: f64 = tk.take_and_parse()?;
let except_same_pg_net = tk.test("EXCEPTSAMEPGNET")?;
// TODO
} else if tk.test("PARALLELOVERLAP")? {
// TODO
} else if tk.test("AREA")? {
let cut_area: f64 = tk.take_and_parse()?;
// TODO
}
// TODO
tk.skip_until(";")?;
layer.spacing.push(cut_spacing);
} else if tk.test("PROPERTY")? {
let property = tk.take()?;
// TODO
tk.skip_until(";")?;
// tokens.expect(";")?;
} else {
// Skip
log::debug!("Skip '{}'", tk.current_token_str().unwrap());
tk.skip_until(";")?;
}
}
// Store the layer rules.
library.technology.layers.push(Layer::Cut(layer));
} else if tk.test("ROUTING")? {
// TYPE ROUTING
let mut layer = RoutingLayer::default();
layer.name = layer_name.clone();
loop {
if tk.test("END")? {
break;
} else if tk.test("MASK")? {
layer.mask_num = Some(tk.take_and_parse()?);
} else if tk.test("DIRECTION")? {
layer.direction = tk.take_and_parse()?;
tk.expect(";")?;
} else if tk.test("PITCH")? {
let x_pitch = tk.take_and_parse()?;
let y_pitch = if tk.test(";")? {
x_pitch
} else {
let y_pitch = tk.take_and_parse()?;
tk.expect(";")?;
y_pitch
};
layer.pitch = (x_pitch, y_pitch);
} else if tk.test("WIDTH")? {
layer.width = tk.take_and_parse()?;
tk.expect(";")?;
} else if tk.test("RESISTANCE")? {
tk.expect("RPERSQ")?;
layer.resistance = Some(tk.take_and_parse()?);
tk.expect(";")?;
} else {
// TODO: Read other routing layer rules.
// Skip
log::debug!("Skip '{}'", tk.current_token_str().unwrap());
tk.skip_until(";")?;
}
}
// Store the layer rules.
library.technology.layers.push(Layer::Routing(layer));
} else if tk.test("MASTERSLICE")? {
// TYPE MASTERSLICE
// Typically polysilicon layer.
// This is used if MACROs have pins on the polysilicon layer.
let mut layer = MasterSliceLayer::default();
layer.name = layer_name.clone();
loop {
if tk.test("END")? {
break;
} else if tk.test("MASK")? {
layer.mask_num = Some(tk.take_and_parse()?);
} else {
// TODO: Store properties.
tk.skip_until(";")?;
}
}
} else if tk.test("OVERLAP")? {
// TYPE OVERLAP
loop {
if tk.test("END")? {
break;
} else {
// TODO: Store properties.
tk.skip_until(";")?;
}
}
} else {
log::error!("Unsupported layer type '{}'.", tk.current_token_str().unwrap());
}
tk.expect(layer_name.as_str())?;
}
// VIA
else if tk.test("VIA")? {
let via_name = tk.take()?;
let is_default = tk.test("DEFAULT")?;
// Vias can be generated or fixed.
let is_generated = tk.test("VIARULE")?;
if is_generated {
let rule_name = tk.take()?;
tk.expect(";")?;
tk.expect("CUTSIZE")?;
let x_size: f64 = tk.take_and_parse()?;
let y_size: f64 = tk.take_and_parse()?;
tk.expect(";")?;
tk.expect("LAYERS")?;
let bottom_metal_layer = tk.take()?;
let cut_layer = tk.take()?;
let top_metal_layer = tk.take()?;
tk.expect(";")?;
tk.expect("CUTSPACING")?;
let x_cut_spacing: f64 = tk.take_and_parse()?;
let y_cut_spacing: f64 = tk.take_and_parse()?;
tk.expect(";")?;
tk.expect("ENCLOSURE")?;
let x_bot_enc: f64 = tk.take_and_parse()?;
let y_bot_enc: f64 = tk.take_and_parse()?;
let x_top_enc: f64 = tk.take_and_parse()?;
let y_top_enc: f64 = tk.take_and_parse()?;
tk.expect(";")?;
if tk.test("ROWCOL")? {
let num_cut_rows: u64 = tk.take_and_parse()?;
let num_cut_cols: u64 = tk.take_and_parse()?;
tk.expect(";")?;
}
if tk.test("ORIGIN")? {
let x: u64 = tk.take_and_parse()?;
let y: u64 = tk.take_and_parse()?;
tk.expect(";")?;
}
if tk.test("OFFSET")? {
let x_bot_offset: f64 = tk.take_and_parse()?;
let y_bot_offset: f64 = tk.take_and_parse()?;
let x_top_offset: f64 = tk.take_and_parse()?;
let y_top_offset: f64 = tk.take_and_parse()?;
tk.expect(";")?;
}
if tk.test("PATTERN")? {
// Cut pattern specified as an ASCII string.
let cut_pattern = tk.take()?;
tk.expect(";")?;
}
} else {
// Fixed VIA.
// Fixed vias are defined by shapes on layers.
loop {
if tk.test("RESISTANCE")? {
let resist_value: f64 = tk.take_and_parse()?;
tk.expect(";")?
} else if tk.test("LAYER")? {
let layer_name = tk.take()?;
loop {
if tk.test("RECT")? {
let (p1, p2) = read_rect(&mut tk)?;
tk.expect(";")?;
let rect: db::Rect<f64> = db::Rect::new(p1, p2);
// TODO: Store the rectangle.
} else if tk.test("POLYGON")? {
// Read points until ';'.
let points = read_polygon::<f64, _>(&mut tk)?;
// TODO: Store the polygon.
} else {
break;
}
}
} else {
break;
}
}
}
// Read properties.
loop {
if tk.test("END")? {
tk.expect(via_name.as_str())?;
break;
} else {
// TODO: Read properties.
tk.skip_until(";")?; // Skip properties.
}
}
}
// VIARULE GENERATE
else if tk.test("VIARULE")? {
let via_rule_name = tk.take()?;
// non-GENERATE VIARULES are not supported.
tk.expect("GENERATE")?;
let is_default = tk.test("DEFAULT")?;
// Read both routing layers.
for i in 0..2 {
tk.expect("LAYER")?;
let routing_layer_name = tk.take()?;
tk.expect(";")?;
tk.expect("ENCLOSURE")?;
let overhang1: f64 = tk.take_and_parse()?;
let overhang2: f64 = tk.take_and_parse()?;
tk.expect(";")?;
if tk.test("WIDTH")? {
let min_width: f64 = tk.take_and_parse()?;
tk.expect("TO")?;
let max_width: f64 = tk.take_and_parse()?;
tk.expect(";")?;
}
}
// Read via layers.
tk.expect("LAYER")?;
let cut_layer_name = tk.take()?;
tk.expect(";")?;
tk.expect("RECT")?;
let (p1, p2) = read_rect(&mut tk)?;
let rect: db::Rect<f64> = db::Rect::new(p1, p2);
tk.expect(";")?;
tk.expect("SPACING")?;
let x_spacing: f64 = tk.take_and_parse()?;
tk.expect("BY")?;
let y_spacing: f64 = tk.take_and_parse()?;
tk.expect(";")?;
if tk.test("RESISTANCE")? {
let resistance_per_cut: f64 = tk.take_and_parse()?;
tk.expect(";")?;
}
tk.expect("END")?;
tk.expect(via_rule_name.as_str())?;
}
// SPACING
else if tk.test("SPACING")? {
loop {
if tk.test("END")? {
tk.expect("SPACING")?;
break;
} else {
tk.expect("SAMENET")?;
let layer1 = tk.take()?;
let layer2 = tk.take()?;
let min_space: f64 = tk.take_and_parse()?;
let stack = tk.test("STACK")?;
tk.expect(";")?;
// TODO
}
}
}
// SITE
else if tk.test("SITE")? {
let site_name = tk.take()?;
let mut class: Option<SiteClass> = None;
let mut size: Option<(f64, f64)> = None;
let mut symmetry = Symmetry::default();
let mut row_pattern = vec![];
// Read content of SITE definition.
while !tk.test("END")? {
if tk.test("CLASS")? {
class = Some(tk.take_and_parse()?); // Either PAD or CORE.
tk.expect(";")?;
} else if tk.test("SYMMETRY")? {
loop {
if tk.test(";")? {
break;
} else {
symmetry = symmetry.union(tk.take_and_parse()?);
}
}
// TODO: Store symmetry.
} else if tk.test("ROWPATTERN")? {
loop {
if tk.test(";")? {
break;
} else {
let previous_site_name = tk.take()?;
let site_orient: Orient = tk.take_and_parse()?;
row_pattern.push((previous_site_name, site_orient));
}
}
} else if tk.test("SIZE")? {
let width: f64 = tk.take_and_parse()?;
tk.expect("BY")?;
let heigth: f64 = tk.take_and_parse()?;
tk.expect(";")?;
size = Some((width, heigth));
}
}
tk.expect(site_name.as_str())?;
let site = SiteDefinition {
name: site_name.clone(),
size: size.ok_or(LefDefError::Other("SIZE must be specified in SITE."))?,
symmetry,
class: class.ok_or(LefDefError::Other("CLASS must be specified in SITE."))?,
row_pattern
};
library.sites.insert(site_name, site);
}
// MACRO
else if tk.test("MACRO")? {
let mut m = Macro::default();
let macro_name = tk.take()?;
m.name = macro_name;
if tk.test("CLASS")? {
let class: MacroClass = tk.take_and_parse()?;
let with_sub_class = if !tk.test(";")? {
// Read sub class.
let with_sub_class = match class {
MacroClass::COVER(_) => {
let bump = tk.test("BUMP")?;
MacroClass::COVER(bump)
}
MacroClass::RING => MacroClass::RING,
MacroClass::BLOCK(_) => MacroClass::BLOCK(Some(tk.take_and_parse()?)),
MacroClass::PAD(_) => MacroClass::PAD(Some(tk.take_and_parse()?)),
MacroClass::CORE(_) => MacroClass::CORE(Some(tk.take_and_parse()?)),
MacroClass::ENDCAP(_) => MacroClass::ENDCAP(Some(tk.take_and_parse()?)),
};
tk.expect(";")?;
with_sub_class
} else {
class
};
m.class = Some(with_sub_class);
};
loop {
if tk.test("END")? {
break;
}
// FOREIGN
else if tk.test("FOREIGN")? {
let foreign_cell_name = tk.take()?;
let (point, orient) = if !tk.test(";")? {
let point = read_point(&mut tk)?;
let orient = if !tk.test(";")? {
let orient: Orient = tk.take_and_parse()?;
tk.expect(";")?;
orient
} else {
Default::default()
};
(point, orient)
} else {
(Default::default(), Default::default())
};
m.foreign.push((foreign_cell_name, point.into(), orient))
}
// ORIGIN
else if tk.test("ORIGIN")? {
let origin = read_point(&mut tk)?;
tk.expect(";")?;
m.origin = origin.into();
}
// EEQ
else if tk.test("EEQ")? {
let macro_name = tk.take()?;
tk.expect(";")?;
m.eeq = Some(macro_name);
}
// SIZE
else if tk.test("SIZE")? {
let width: f64 = tk.take_and_parse()?;
tk.expect("BY")?;
let height: f64 = tk.take_and_parse()?;
tk.expect(";")?;
m.size = Some((width, height));
}
// SYMMETRY
else if tk.test("SYMMETRY")? {
let mut symmetry = Symmetry::default();
while !tk.test(";")? {
symmetry = symmetry.union(tk.take_and_parse()?);
}
m.symmetry = symmetry;
}
// SITE
else if tk.test("SITE")? {
let mut site = Site::default();
site.name = tk.take()?;
if !tk.test(";")? {
let x_origin: f64 = tk.take_and_parse()?;
let y_origin: f64 = tk.take_and_parse()?;
site.origin = (x_origin, y_origin);
site.site_orient = tk.take_and_parse()?;
if !tk.test(";")? {
site.step_pattern = Some(read_step_pattern(&mut tk)?);
tk.expect(";")?;
}
}
m.sites.push(site);
}
// PIN
else if let Some(pin) = try_read_pin(&mut tk)? {
m.pins.push(pin);
}
// OBS
else if let Some(obs) = try_read_obs(&mut tk)? {
m.obs.extend(obs);
}
// DENSITY
else if tk.test("DENSITY")? {
// TODO append density
log::warn!("Skipping DENSITY.");
}
// PROPERTY
else if tk.test("PROPERTY")? {
let prop_name = tk.take()?;
let prop_value = tk.take()?;
tk.expect(";")?;
// TODO: Append property
log::warn!("Skipping PROPERTY.");
}
}
tk.expect(m.name.as_str())?;
// Store macro.
library.library.macros.insert(m.name.clone(), m);
} else {
println!("Unknown token: {}", tk.current_token().unwrap());
return Err(LefDefError::UnknownToken(tk.current_token().unwrap()));
}
}
Ok(library)
}
#[test]
fn test_read_lef_small() {
let data = r#"
# Parts from gscl45nm.lef.
VERSION 5.5 ;
NAMESCASESENSITIVE ON ;
BUSBITCHARS "[]" ;
DIVIDERCHAR "/" ;
PROPERTYDEFINITIONS
LAYER contactResistance REAL ;
END PROPERTYDEFINITIONS
UNITS
DATABASE MICRONS 2000 ;
END UNITS
MANUFACTURINGGRID 0.0025 ;
LAYER poly
TYPE MASTERSLICE ;
END poly
LAYER contact
TYPE CUT ;
SPACING 0.075 ;
PROPERTY contactResistance 10.5 ;
END contact
LAYER metal1
TYPE ROUTING ;
DIRECTION HORIZONTAL ;
PITCH 0.19 ;
WIDTH 0.065 ;
SPACING 0.065 ;
RESISTANCE RPERSQ 0.38 ;
END metal1
LAYER via1
TYPE CUT ;
SPACING 0.075 ;
PROPERTY contactResistance 5.69 ;
END via1
LAYER OVERLAP
TYPE OVERLAP ;
END OVERLAP
VIA M2_M1_via DEFAULT
LAYER metal1 ;
RECT -0.0675 -0.0325 0.0675 0.0325 ;
LAYER via1 ;
RECT -0.0325 -0.0325 0.0325 0.0325 ;
LAYER metal2 ;
RECT -0.035 -0.0675 0.035 0.0675 ;
END M2_M1_via
VIARULE M2_M1 GENERATE
LAYER metal1 ;
ENCLOSURE 0 0.035 ;
LAYER metal2 ;
ENCLOSURE 0 0.035 ;
LAYER via1 ;
RECT -0.0325 -0.0325 0.0325 0.0325 ;
SPACING 0.14 BY 0.14 ;
END M2_M1
VIARULE M1_POLY GENERATE
LAYER poly ;
ENCLOSURE 0 0 ;
LAYER metal1 ;
ENCLOSURE 0 0.035 ;
LAYER contact ;
RECT -0.0325 -0.0325 0.0325 0.0325 ;
SPACING 0.14 BY 0.14 ;
END M1_POLY
SPACING
SAMENET metal1 metal1 0.065 ;
SAMENET metal2 metal2 0.07 ;
SAMENET metal6 metal6 0.14 ;
SAMENET metal5 metal5 0.14 ;
SAMENET metal4 metal4 0.14 ;
SAMENET metal3 metal3 0.07 ;
SAMENET metal7 metal7 0.4 ;
SAMENET metal8 metal8 0.4 ;
SAMENET metal9 metal9 0.8 ;
SAMENET metal10 metal10 0.8 ;
END SPACING
SITE CoreSite
CLASS CORE ;
SIZE 0.38 BY 2.47 ;
END CoreSite
MACRO INVX1
CLASS CORE ;
ORIGIN 0 0 ;
FOREIGN INVX1 0 0 ;
SIZE 0.57 BY 2.47 ;
SYMMETRY X Y ;
SITE CoreSite ;
PIN A
DIRECTION INPUT ;
USE SIGNAL ;
PORT
LAYER metal1 ;
RECT 0.1575 0.4875 0.2575 0.6225 ;
END
END A
PIN Y
DIRECTION OUTPUT ;
USE SIGNAL ;
PORT
LAYER metal1 ;
RECT 0.3475 0.2175 0.4125 1.815 ;
RECT 0.3125 0.2175 0.4475 0.4225 ;
END
END Y
PIN gnd
DIRECTION INOUT ;
USE GROUND ;
SHAPE ABUTMENT ;
PORT
LAYER metal1 ;
RECT 0.1625 -0.065 0.2275 0.4225 ;
RECT 0 -0.065 0.57 0.065 ;
END
END gnd
PIN vdd
DIRECTION INOUT ;
USE POWER ;
SHAPE ABUTMENT ;
PORT
LAYER metal1 ;
RECT 0.1625 1.265 0.2275 2.535 ;
RECT 0 2.405 0.57 2.535 ;
END
END vdd
END INVX1
END LIBRARY
"#;
let result = read_lef_chars(data.chars());
dbg!(&result);
assert!(result.is_ok())
}