#![allow(unused_variables)]
use crate::common::*;
use crate::def_ast::*;
use crate::stream_parser::LefDefLexer;
pub use crate::stream_parser::LefDefParseError;
use itertools::PeekingNext;
use libreda_db::prelude as db;
use libreda_stream_parser::{tokenize, Tokenized};
use std::collections::BTreeMap;
use std::io::Read;
use std::str::FromStr;
#[derive(Copy, Clone, Default, Debug)]
pub struct DEFReaderConfig {
pub ignore_non_fatal_errors: bool,
}
pub fn read_def_bytes<R: Read>(reader: &mut R) -> Result<DEF, LefDefParseError> {
read_def_chars(reader.bytes().map(|b| b.unwrap() as char))
}
pub fn read_def_bytes_with_config<R: Read>(
config: &DEFReaderConfig,
reader: &mut R,
) -> Result<DEF, LefDefParseError> {
read_def_chars_with_config(config, reader.bytes().map(|b| b.unwrap() as char))
}
pub fn read_def_chars<I>(chars: I) -> Result<DEF, LefDefParseError>
where
I: Iterator<Item = char>,
{
read_def_chars_with_config(&DEFReaderConfig::default(), chars)
}
pub fn read_def_chars_with_config<I>(
config: &DEFReaderConfig,
chars: I,
) -> Result<DEF, LefDefParseError>
where
I: Iterator<Item = char>,
{
let mut line_num = 1;
let mut char_num = 1; let line_count = chars.inspect(|&c| {
char_num += 1;
if c == '\n' {
line_num += 1;
char_num = 0;
}
});
let result = read_def_impl(config, line_count);
if result.is_err() {
log::error!("DEF error on line: {} (at {})", line_num, char_num);
}
result
}
fn read_regular_wiring<I: Iterator<Item = char> + PeekingNext>(
tk: &mut Tokenized<I, LefDefLexer>,
) -> Result<RegularWiring, LefDefParseError> {
let wiring_class: WiringClass = tk.take_and_parse()?;
let mut wiring = RegularWiring {
class: wiring_class,
wiring: vec![],
};
loop {
let layer_name = tk.take_str()?;
let mut wiring_statement = RegularWiringStatement {
start_layer_name: layer_name,
style_num: 0,
taper_rule: None,
routing_points: vec![],
};
if tk.test_str("TAPER")? {
} else if tk.test_str("TAPERRULE")? {
wiring_statement.taper_rule = Some(tk.take_str()?);
}
if tk.test_str("STYLE")? {
wiring_statement.style_num = tk.take_and_parse()?;
}
let mut prev_point: Option<(db::Coord, db::Coord)> = None;
fn read_path_point<T: FromStr + Copy, I: Iterator<Item = char> + PeekingNext>(
tk: &mut Tokenized<I, LefDefLexer>,
prev_point: &Option<(T, T)>,
) -> Result<((T, T), Option<T>), LefDefParseError> {
tk.expect_str("(")?;
let x = if tk.test_str("*")? {
prev_point
.ok_or(LefDefParseError::Other(
"x-coordinate not yet defined. Cannot use '*'.",
))?
.0
} else {
tk.take_and_parse()?
};
let y = if tk.test_str("*")? {
prev_point
.ok_or(LefDefParseError::Other(
"x-coordinate not yet defined. Cannot use '*'.",
))?
.1
} else {
tk.take_and_parse()?
};
let ext_value = if !tk.test_str(")")? {
let ext_value = tk.take_and_parse()?;
tk.expect_str(")")?;
Some(ext_value)
} else {
None
};
Ok(((x, y), ext_value))
}
let (p, extvalue) = read_path_point(tk, &prev_point)?;
wiring_statement.routing_points.push(RoutingPoint::Point {
point: p.into(),
ext_value: None,
mask_num: None,
});
prev_point = Some(p);
while !tk.peeking_test_str(";")? && !tk.peeking_test_str("NEW")? {
let mut mask_num: Option<u8> = None;
let mut via_mask_num: Option<ViaMaskNum> = None;
if tk.test_str("VIRTUAL")? {
let (p, _extvalue) = read_path_point(tk, &prev_point)?;
prev_point = Some(p);
wiring_statement
.routing_points
.push(RoutingPoint::Virtual(p.into()));
} else {
let mut expect_via = false;
if tk.test_str("MASK")? {
if tk.current_token_str().map(|s| s.len()) == Some(3) {
via_mask_num = Some(tk.take_and_parse()?);
expect_via = true;
} else {
mask_num = Some(tk.take_and_parse()?);
}
}
if expect_via || !tk.peeking_test_str("(")? {
if !expect_via && tk.test_str("RECT")? {
tk.expect_str("(")?;
let delta_x1: db::Coord = tk.take_and_parse()?;
let delta_y1: db::Coord = tk.take_and_parse()?;
let delta_x2: db::Coord = tk.take_and_parse()?;
let delta_y2: db::Coord = tk.take_and_parse()?;
tk.expect_str(")")?;
let d1 = db::Vector::new(delta_x1, delta_y1);
let d2 = db::Vector::new(delta_x2, delta_y2);
let current_point: db::Point<_> = prev_point
.ok_or_else(|| LefDefParseError::Other("Appearance of 'RECT' in a route but no current path point is defined.".into()))?
.into();
let rect = db::Rect::new(current_point + d1, current_point + d2);
todo!("Store the rectangle");
wiring_statement
.routing_points
.push(RoutingPoint::Rect { rect, mask_num });
} else {
let via_name = tk.take_str()?;
let orient: Option<Orient> = if !tk.peeking_test_str("NEW")?
&& !tk.peeking_test_str(";")?
&& !tk.peeking_test_str("(")?
&& !tk.peeking_test_str("+")?
{
Some(tk.take_and_parse()?)
} else {
None
};
wiring_statement.routing_points.push(RoutingPoint::Via {
via_name,
orient,
via_mask_num,
});
}
} else {
let (p, ext_value) = read_path_point(tk, &prev_point)?;
prev_point = Some(p.into());
wiring_statement.routing_points.push(RoutingPoint::Point {
point: p.into(),
ext_value,
mask_num,
});
}
}
}
wiring.wiring.push(wiring_statement);
if !tk.test_str("NEW")? {
break;
} else {
}
}
return Ok(wiring);
}
fn read_vias<I: Iterator<Item = char> + PeekingNext>(
tk: &mut Tokenized<I, LefDefLexer>,
) -> Result<BTreeMap<String, ViaDefinition>, LefDefParseError> {
let mut via_definitions: BTreeMap<String, ViaDefinition> = Default::default();
tk.expect_str("VIAS")?;
let num_vias: u32 = tk.take_and_parse()?;
tk.expect_str(";")?;
while tk.test_str("-")? {
let via_name = tk.take_str()?;
while tk.test_str("+")? {
if tk.test_str("VIARULE")? {
return Err(LefDefParseError::NotImplemented("VIAS/VIARULE"));
} else {
let mut via_geometries = Vec::new();
if tk.test_str("RECT")? {
let layer = tk.take_str()?;
let mask_num = if tk.test_str("MASK")? {
Some(tk.take_and_parse()?)
} else {
None
};
let (p1, p2) = read_rect(tk)?;
let rect = db::Rect::new(p1, p2);
via_geometries.push(ViaGeometry {
layer,
mask_num,
shape: RectOrPolygon::Rect(rect),
});
} else if tk.test_str("POLYGON")? {
let layer = tk.take_str()?;
let mask_num = if tk.test_str("MASK")? {
Some(tk.take_and_parse()?)
} else {
None
};
let points: Vec<(db::Coord, _)> = read_polygon(tk)?;
let points = points.into_iter().map(|p| p.into()).collect();
let polygon = db::SimplePolygon::new(points);
via_geometries.push(ViaGeometry {
layer,
mask_num,
shape: RectOrPolygon::Polygon(polygon),
});
} else {
return Err(LefDefParseError::UnexpectedToken(
"RECT, POLYGON".into(),
tk.take_str()?,
));
}
let via_def = ViaDefinition::ViaGeometry(via_geometries);
via_definitions.insert(via_name.clone(), via_def);
}
}
tk.expect_str(";")?;
}
tk.expect_str("END")?;
tk.expect_str("VIAS")?;
Ok(via_definitions)
}
fn read_def_impl<I>(config: &DEFReaderConfig, chars: I) -> Result<DEF, LefDefParseError>
where
I: Iterator<Item = char>,
{
let mut design = DEF::default();
let mut tk = tokenize(chars, LefDefLexer {});
tk.advance();
loop {
if tk.test_str("END")? {
tk.expect_str("DESIGN")?;
break;
} else if tk.test_str("VERSION")? {
let version = tk.take_str()?;
design.version = Some(version);
tk.expect_str(";")?;
} else if tk.test_str("BUSBITCHARS")? {
let chars = tk.take_str()?;
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(LefDefParseError::IllegalBusBitChars(start, end));
}
log::debug!("Bus bit chars: '{}' '{}'", start, end);
design.busbitchars = (start, end);
} else {
return Err(LefDefParseError::InvalidCharacter); }
tk.expect_str(";")?;
} else if tk.test_str("NAMESCASESENSITIVE")? {
tk.expect_str("ON")
.map_err(|_| LefDefParseError::Other("Support only NAMESCASESENSITIVE ON."))?;
tk.expect_str(";")?;
} else if tk.test_str("DIVIDERCHAR")? {
let divchar = tk.take_str()?;
if divchar.len() == 1 {
design.dividerchar = divchar.chars().nth(0).unwrap();
log::debug!("Divider char: '{}'", design.dividerchar);
} else {
return Err(LefDefParseError::InvalidCharacter); }
tk.expect_str(";")?;
} else if tk.test_str("DESIGN")? {
let design_name = tk.take_str()?;
tk.expect_str(";")?;
design.design_name = Some(design_name);
} else if tk.test_str("TECHNOLOGY")? {
let tech_name = tk.take_str()?;
tk.expect_str(";")?;
design.technology = Some(tech_name);
} else if tk.test_str("UNITS")? {
tk.expect_str("DISTANCE")?;
tk.expect_str("MICRONS")?;
let units = tk.take_and_parse()?;
tk.expect_str(";")?;
design.units = units;
} else if tk.test_str("HISTORY")? {
let mut text = String::new();
while !tk.test_str(";")? {
if let Some(s) = tk.current_token_str() {
if !text.is_empty() {
text.push(' '); }
text.extend(s.chars());
}
tk.advance();
}
design.history.push(text);
} else if tk.test_str("PROPERTYDEFINITIONS")? {
loop {
if tk.test_str("END")? {
tk.expect_str("PROPERTYDEFINITIONS")?;
break;
} else {
let property_object_type: DEFPropertyObjectType = tk.take_and_parse()?;
let property_name = tk.take_str()?;
let property_type: PropertyType = tk.take_and_parse()?;
let mut range = None;
let mut default_value = None;
match property_type {
PropertyType::Integer => {
if tk.test_str("RANGE")? {
let min = tk.take_and_parse()?;
let max = tk.take_and_parse()?;
range = Some((PropertyValue::Int(min), PropertyValue::Int(max)));
}
if !tk.peeking_test_str(";")? {
let default = tk.take_and_parse()?;
default_value = Some(PropertyValue::Int(default));
}
tk.expect_str(";")?;
}
PropertyType::Real => {
if tk.test_str("RANGE")? {
let min = tk.take_and_parse()?;
let max = tk.take_and_parse()?;
range = Some((PropertyValue::Real(min), PropertyValue::Real(max)));
}
if !tk.peeking_test_str(";")? {
let default = tk.take_and_parse()?;
default_value = Some(PropertyValue::Real(default));
}
}
PropertyType::String => {
if !tk.peeking_test_str(";")? {
let default = tk.take_str()?;
default_value = Some(PropertyValue::String(default));
}
}
}
tk.expect_str(";")?;
let property_definition = DEFPropertyDefinition {
object_type: property_object_type,
property_type,
range,
default_value,
};
design
.property_definitions
.insert(property_name, property_definition);
}
}
log::warn!("Skipping PROPERTYDEFINITIONS.");
} else if tk.test_str("DIEAREA")? {
let points = read_polygon(&mut tk)?;
let points: Vec<db::Point<db::SInt>> = points.into_iter().map(|p| p.into()).collect();
let die_area = if points.len() < 2 {
log::error!("DIEAREA must consist of two or more points.");
return Err(LefDefParseError::Other(
"Illegal die area. Must have two or more vertices.",
));
} else if points.len() == 2 {
let rect: db::Rect<db::SInt> = db::Rect::new(points[0], points[1]);
let poly = db::SimpleRPolygon::from(rect);
poly
} else {
let poly = db::SimpleRPolygon::try_new(&points);
if poly.is_none() {
log::error!("DIEAREA polygon is not rectilinear.");
}
if config.ignore_non_fatal_errors {
poly.unwrap_or(db::SimpleRPolygon::empty())
} else {
poly.ok_or(LefDefParseError::Other(
"DIEAREA polygon is not rectilinear.",
))?
}
};
design.die_area = Some(die_area);
} else if tk.test_str("ROW")? {
let row_name = tk.take_str()?;
let site_name = tk.take_str()?;
let orig_x: db::Coord = tk.take_and_parse()?;
let orig_y: db::Coord = tk.take_and_parse()?;
let site_orient: Orient = tk.take_and_parse()?;
let mut step_pattern = RowStepPattern::default();
if tk.test_str("DO")? {
step_pattern.num_x = tk.take_and_parse()?;
tk.expect_str("BY")?;
step_pattern.num_y = tk.take_and_parse()?;
if tk.test_str("STEP")? {
let step_x = tk.take_and_parse()?;
let step_y = tk.take_and_parse()?;
step_pattern.step = Some((step_x, step_y));
}
}
let mut properties = BTreeMap::new();
while tk.test_str("+")? {
tk.expect_str("PROPERTY")?;
while !tk.peeking_test_str("+")? {
if let Some((name, value)) =
read_def_property(&mut design.property_definitions, &mut tk)?
{
properties.insert(name, value);
}
}
}
let row = Row {
site_name,
orig: (orig_x, orig_y),
site_orient,
step_pattern,
properties,
};
tk.expect_str(";")?;
design.rows.insert(row_name, row);
} else if tk.test_str("TRACKS")? {
let is_horizontal = tk.test_str("Y")?;
if !is_horizontal {
tk.expect_str("X")?;
}
let start = tk.take_and_parse()?;
tk.expect_str("DO")?;
let num_tracks = tk.take_and_parse()?;
tk.expect_str("STEP")?;
let step = tk.take_and_parse()?; let mask = if tk.test_str("MASK")? {
let mask_num = tk.take_and_parse()?;
let same_mask = tk.test_str("SAMEMASK")?;
Some((mask_num, same_mask))
} else {
None
};
let mut layers = Vec::new();
if tk.test_str("LAYER")? {
while !tk.peeking_test_str(";")? {
let layer_name = tk.take_str()?;
layers.push(layer_name);
}
}
tk.expect_str(";")?;
let tracks = Tracks {
is_horizontal,
start,
num_tracks,
step,
mask,
layers,
};
design.tracks.push(tracks);
} else if tk.test_str("GCELLGRID")? {
let is_horizontal = tk.test_str("Y")?;
if !is_horizontal {
tk.expect_str("X")?;
}
let start: db::SInt = tk.take_and_parse()?;
tk.expect_str("DO")?;
let num_tracks: u32 = tk.take_and_parse()?;
tk.expect_str("STEP")?;
let space: db::SInt = tk.take_and_parse()?; tk.expect_str(";")?;
design.gcell_grid.push(());
} else if tk.peeking_test_str("VIAS")? {
design.vias = read_vias(&mut tk)?;
} else if tk.test_str("STYLES")? {
return Err(LefDefParseError::NotImplemented("STYLES"));
} else if tk.test_str("NONDEFAULTRULES")? {
return Err(LefDefParseError::NotImplemented("NONDEFAULTRULES"));
} else if tk.test_str("REGIONS")? {
let _num_regions: u32 = tk.take_and_parse()?;
while tk.test_str("-")? {
let mut region = Region::default();
let region_name = tk.take_str()?;
while !tk.peeking_test_str("+")? {
let p1 = read_point(&mut tk)?;
let p2 = read_point(&mut tk)?;
let rect: db::Rect<db::SInt> = db::Rect::new(p1, p2);
region.regions.push(rect);
}
while tk.test_str("+")? {
if tk.test_str("TYPE")? {
region.region_type = Some(tk.take_and_parse()?);
} else if tk.test_str("PROPERTY")? {
while !tk.peeking_test_str("+")? {
if let Some((name, value)) =
read_def_property(&mut design.property_definitions, &mut tk)?
{
}
}
}
}
design.regions.insert(region_name, region);
}
tk.expect_str("END")?;
tk.expect_str("REGIONS")?;
} else if tk.test_str("COMPONENTMASKSHIFT")? {
return Err(LefDefParseError::NotImplemented("COMPONENTMASKSHIFT"));
} else if tk.test_str("COMPONENTS")? {
let num_components: u32 = tk.take_and_parse()?;
design.components.reserve(num_components as usize);
tk.expect_str(";")?;
while tk.test_str("-")? {
let mut component = Component::default();
component.name = tk.take_str()?;
component.model_name = tk.take_str()?;
while tk.test_str("+")? {
if tk.test_str("EEQMASTER")? {
component.eeq_master = Some(tk.take_str()?);
} else if tk.test_str("SOURCE")? {
component.source = tk.take_and_parse()?;
} else if tk.test_str("FIXED")? {
let point: (db::SInt, db::SInt) = read_point(&mut tk)?;
let orient: Orient = tk.take_and_parse()?;
component.position = Some((point.into(), orient, true));
} else if tk.test_str("COVER")? {
let point: (db::SInt, db::SInt) = read_point(&mut tk)?;
let orient: Orient = tk.take_and_parse()?;
component.position = Some((point.into(), orient, true));
} else if tk.test_str("PLACED")? {
let point: (db::SInt, db::SInt) = read_point(&mut tk)?;
let orient: Orient = tk.take_and_parse()?;
component.position = Some((point.into(), orient, false));
} else if tk.test_str("UNPLACED")? {
component.position = None;
} else if tk.test_str("HALO")? {
let soft = tk.test_str("SOFT")?;
let left = tk.take_and_parse()?;
let bottom = tk.take_and_parse()?;
let right = tk.take_and_parse()?;
let top = tk.take_and_parse()?;
component.halo = Some((soft, left, bottom, right, top));
} else if tk.test_str("ROUTEHALO")? {
let halo_dist: db::SInt = tk.take_and_parse()?;
let min_layer = tk.take_str()?;
let max_layer = tk.take_str()?;
} else if tk.test_str("WEIGHT")? {
component.weight = tk.take_and_parse()?;
} else if tk.test_str("REGION")? {
let region_name = tk.take_str()?;
if let Some(region) = design.regions.get(®ion_name) {
component.region = Some(region_name);
} else {
log::error!(
"Ignore region statement. No such region: '{}'",
®ion_name
);
}
} else if tk.test_str("PROPERTY")? {
while !tk.peeking_test_str("+")? {
if let Some((name, value)) =
read_def_property(&mut design.property_definitions, &mut tk)?
{
component.properties.insert(name, value);
}
}
} else {
return Err(LefDefParseError::UnknownToken(
tk.current_token_str().unwrap(),
));
}
}
tk.expect_str(";")?;
design.components.push(component);
}
tk.expect_str("END")?;
tk.expect_str("COMPONENTS")?;
} else if tk.test_str("PINS")? {
let num_pins: usize = tk.take_and_parse()?;
tk.expect_str(";")?;
while tk.test_str("-")? {
let mut pin = Pin::default();
pin.pin_name = tk.take_str()?;
tk.expect_str("+")?;
tk.expect_str("NET")?;
pin.net_name = tk.take_str()?;
let mut current_port: Option<PinPort> = None;
while tk.test_str("+")? {
if tk.test_str("SPECIAL")? {
pin.special = true;
} else if tk.test_str("DIRECTION")? {
pin.direction = Some(tk.take_and_parse()?);
} else if tk.test_str("NETEXPR")? {
pin.net_expr = Some(tk.take_str()?);
} else if tk.test_str("SUPPLYSENSITIVITY")? {
pin.supply_sensitivity = Some(tk.take_str()?);
} else if tk.test_str("GROUNDSENSITIVITY")? {
pin.ground_sensitivity = Some(tk.take_str()?);
} else if tk.test_str("USE")? {
pin.signal_use = tk.take_and_parse()?;
} else if tk.test_str("PORT")? {
if let Some(port) = current_port.take() {
pin.ports.push(port);
};
current_port = Some(PinPort::default()); let port = current_port.as_mut().unwrap();
} else if tk.test_str("LAYER")? {
let layer_name = tk.take_str()?;
let mask_num = if tk.test_str("MASK")? {
Some(tk.take_and_parse()?)
} else {
None
};
let mut spacing_or_width = None;
if tk.test_str("SPACING")? {
let min_spacing = tk.take_and_parse()?;
spacing_or_width =
Some(SpacingOrDesignRuleWidth::MinSpacing(min_spacing));
}
if tk.test_str("DESIGNRULEWIDTH")? {
let effective_width = tk.take_and_parse()?;
spacing_or_width =
Some(SpacingOrDesignRuleWidth::DesignRuleWidth(effective_width));
}
let p1: (db::SInt, db::SInt) = read_point(&mut tk)?;
let p2: (db::SInt, db::SInt) = read_point(&mut tk)?;
let rect = db::Rect::new(p1, p2);
current_port
.get_or_insert(Default::default())
.port_statements
.push(PinPortStatement::Layer {
layer_name,
mask_num,
spacing_or_width,
rect,
});
} else if tk.test_str("POLYGON")? {
let layer_name = tk.take_str()?;
let mask_num = if tk.test_str("MASK")? {
Some(tk.take_and_parse()?)
} else {
None
};
let mut spacing_or_width = None;
if tk.test_str("SPACING")? {
let min_spacing = tk.take_and_parse()?;
spacing_or_width =
Some(SpacingOrDesignRuleWidth::MinSpacing(min_spacing));
}
if tk.test_str("DESIGNRULEWIDTH")? {
let effective_width = tk.take_and_parse()?;
spacing_or_width =
Some(SpacingOrDesignRuleWidth::DesignRuleWidth(effective_width));
}
let points = read_polygon(&mut tk)?;
let polygon = points.into_iter().collect();
current_port
.get_or_insert(Default::default())
.port_statements
.push(PinPortStatement::Polygon {
layer_name,
mask_num,
spacing_or_width,
polygon,
});
} else if tk.test_str("VIA")? {
let port = current_port.as_mut().unwrap();
let via_name = tk.take_str()?;
let mask_num = if tk.test_str("MASK")? {
Some(tk.take_and_parse()?)
} else {
None
};
let location: (db::SInt, db::SInt) = read_point(&mut tk)?;
current_port
.get_or_insert(Default::default())
.port_statements
.push(PinPortStatement::Via {
via_name,
mask_num,
location: location.into(),
});
} else if tk.test_str("ANTENNAPINPARTIALMETALAREA")? {
return Err(LefDefParseError::NotImplemented(
"ANTENNAPINPARTIALMETALAREA",
));
} else if tk.test_str("ANTENNAPINPARTIALMETALSIDEAREA")? {
return Err(LefDefParseError::NotImplemented(
"ANTENNAPINPARTIALMETALSIDEAREA",
));
} else if tk.test_str("ANTENNAPINPARTIALCUTAREA")? {
return Err(LefDefParseError::NotImplemented("ANTENNAPINPARTIALCUTAREA"));
} else if tk.test_str("ANTENNAPINDIFFAREA")? {
return Err(LefDefParseError::NotImplemented("ANTENNAPINDIFFAREA"));
} else if tk.test_str("ANTENNAPINDIFFAREA")? {
return Err(LefDefParseError::NotImplemented("ANTENNAPINDIFFAREA"));
} else if tk.test_str("ANTENNAMODEL")? {
return Err(LefDefParseError::NotImplemented("ANTENNAMODEL"));
} else if tk.test_str("ANTENNAPINGATEAREA")? {
return Err(LefDefParseError::NotImplemented("ANTENNAPINGATEAREA"));
} else if tk.test_str("ANTENNAPINMAXAREACAR")? {
return Err(LefDefParseError::NotImplemented("ANTENNAPINMAXAREACAR"));
} else if tk.test_str("ANTENNAPINMAXSIDEAREACAR")? {
return Err(LefDefParseError::NotImplemented("ANTENNAPINMAXSIDEAREACAR"));
} else if tk.test_str("ANTENNAPINMAXCUTCAR")? {
return Err(LefDefParseError::NotImplemented("ANTENNAPINMAXCUTCAR"));
} else {
return Err(LefDefParseError::UnexpectedToken(
"".to_string(),
tk.current_token_str().unwrap(),
));
}
}
if let Some(port) = current_port.take() {
pin.ports.push(port);
};
design.pins.push(pin);
}
if design.pins.len() != num_pins {
log::debug!(
"Mismatch in announced number of pins ({}) and actual number of pins ({}).",
num_pins,
design.pins.len()
);
}
tk.expect_str("END")?;
tk.expect_str("PINS")?;
} else if tk.test_str("PINPROPERTIES")? {
return Err(LefDefParseError::NotImplemented("PINPROPERTIES"));
} else if tk.test_str("BLOCKAGES")? {
let num_blockages: u32 = tk.take_and_parse()?;
design.blockages.reserve(num_blockages as usize);
tk.expect_str(";")?;
while tk.test_str("-")? {
if tk.test_str("LAYER")? {
let mut blk = LayerBlockage::default();
blk.layer = tk.take_str()?;
while tk.test_str("+")? {
if tk.test_str("SLOTS")? {
blk.slots = true;
} else if tk.test_str("FILLS")? {
blk.fills = true;
} else if tk.test_str("PUSHDOWN")? {
blk.pushdown = true;
} else if tk.test_str("EXCEPTPGNET")? {
blk.except_pg_net = true;
} else if tk.test_str("COMPONENT")? {
blk.component = Some(tk.take_str()?);
} else if tk.test_str("SPACING")? {
let spacing = tk.take_and_parse()?;
blk.spacing_or_designrule_width =
Some(SpacingOrDesignRuleWidth::MinSpacing(spacing));
} else if tk.test_str("DESIGNRULEWIDTH")? {
let width = tk.take_and_parse()?;
blk.spacing_or_designrule_width =
Some(SpacingOrDesignRuleWidth::DesignRuleWidth(width));
} else if tk.test_str("MASK")? {
let mask_num = tk.take_and_parse()?;
blk.mask_num = Some(mask_num);
} else {
return Err(LefDefParseError::UnexpectedToken(
"SLOTS, FILLS, PUSHDOWN, EXCEPTPGNET, SPACING, DESIGNRULEWIDTH or MASK".to_string(),
tk.current_token_str().unwrap(),
));
}
}
while !tk.test_str(";")? {
if tk.test_str("RECT")? {
let (p1, p2) = read_rect(&mut tk)?;
let rect = db::Rect::new(p1, p2);
blk.blockage_shapes.push(RectOrPolygon::Rect(rect));
} else if tk.test_str("POLYGON")? {
let points = read_polygon(&mut tk)?;
let poly = db::SimplePolygon::from(points);
blk.blockage_shapes.push(RectOrPolygon::Polygon(poly));
} else {
return Err(LefDefParseError::UnexpectedToken(
"RECT or POLYGON".to_string(),
tk.current_token_str().unwrap(),
));
}
}
design.blockages.push(Blockage::LayerBlockage(blk));
} else if tk.test_str("PLACEMENT")? {
let mut blk = PlacementBlockage::default();
while tk.test_str("+")? {
if tk.test_str("SOFT")? {
blk.blockage_type = Some(PlacementBlockageType::Soft);
} else if tk.test_str("PARTIAL")? {
let max_density = tk.take_and_parse()?;
blk.blockage_type = Some(PlacementBlockageType::Partial(max_density));
} else if tk.test_str("PUSHDOWN")? {
blk.pushdown = true;
} else if tk.test_str("COMPONENT")? {
blk.component = Some(tk.take_str()?);
} else {
return Err(LefDefParseError::UnexpectedToken(
"SOFT, PARTIAL, PUSHDOWN or COMPONENT".to_string(),
tk.current_token_str().unwrap(),
));
}
}
while !tk.test_str(";")? {
tk.expect_str("RECT")?;
let (p1, p2) = read_rect(&mut tk)?;
let rect = db::Rect::new(p1, p2);
blk.rects.push(rect);
}
design.blockages.push(Blockage::PlacementBlockage(blk));
} else {
return Err(LefDefParseError::UnexpectedToken(
"LAYER of PLACEMENT".to_string(),
tk.current_token_str().unwrap(),
));
}
}
tk.expect_str("END")?;
tk.expect_str("BLOCKAGES")?;
} else if tk.test_str("SLOTS")? {
return Err(LefDefParseError::NotImplemented("SLOTS"));
} else if tk.test_str("FILLS")? {
return Err(LefDefParseError::NotImplemented("FILLS"));
} else if tk.test_str("SPECIALNETS")? {
return Err(LefDefParseError::NotImplemented("SPECIALNETS"));
} else if tk.test_str("NETS")? {
let _num_nets: u32 = tk.take_and_parse()?;
tk.expect_str(";")?;
while tk.test_str("-")? {
let mut net = Net::default();
if tk.test_str("MUSTJOIN")? {
let component_name = tk.take_str()?;
let pin_name = tk.take_str()?;
net.mustjoin = Some(Mustjoin {
component_name,
pin_name,
})
} else {
net.name = Some(tk.take_str()?);
while tk.test_str("(")? {
let term = if tk.test_str("PIN")? {
let pin_name = tk.take_str()?;
NetTerminal::IoPin(pin_name)
} else {
let component_name = tk.take_str()?;
let pin_name = tk.take_str()?;
NetTerminal::ComponentPin {
component_name,
pin_name,
}
};
if tk.test_str("+")? {
tk.expect_str("SYNTHESIZED")?;
}
net.terminals.push(term);
tk.expect_str(")")?;
}
while tk.test_str("+")? {
if tk.test_str("SHIELDNET")? {
net.shield_nets.push(tk.take_str()?);
} else if tk.test_str("VPIN")? {
return Err(LefDefParseError::NotImplemented("VPIN"));
} else if tk.test_str("SUBNET")? {
return Err(LefDefParseError::NotImplemented("SUBNET"));
} else if tk.test_str("XTALK")? {
net.xtalk_class = tk.take_and_parse()?;
} else if tk.test_str("NONDEFAULTRULE")? {
net.non_default_rule = Some(tk.take_str()?);
} else if tk.peeking_test_str("COVER")?
|| tk.peeking_test_str("FIXED")?
|| tk.peeking_test_str("ROUTED")?
|| tk.peeking_test_str("NOSHIELD")?
{
let wiring = read_regular_wiring(&mut tk)?;
net.regular_wiring.push(wiring);
} else if tk.test_str("SOURCE")? {
net.source = tk.take_and_parse()?;
} else if tk.test_str("FIXEDBUMP")? {
net.fixed_bump = true;
} else if tk.test_str("FREQUENCY")? {
net.frequency = Some(tk.take_and_parse()?);
} else if tk.test_str("ORIGINAL")? {
net.original = Some(tk.take_str()?);
} else if tk.test_str("USE")? {
net.net_use = tk.take_and_parse()?;
} else if tk.test_str("PATTERN")? {
net.pattern = tk.take_and_parse()?;
} else if tk.test_str("ESTCAP")? {
net.est_cap = Some(tk.take_and_parse()?);
} else if tk.test_str("WEIGHT")? {
net.weight = tk.take_and_parse()?;
} else if tk.test_str("PROPERTY")? {
while !tk.peeking_test_str("+")? && !tk.peeking_test_str(";")? {
if let Some((name, value)) =
read_def_property(&mut design.property_definitions, &mut tk)?
{
net.properties.insert(name, value);
}
}
} else {
return Err(LefDefParseError::UnexpectedToken(
"".to_string(),
tk.current_token_str().unwrap(),
));
}
}
}
tk.expect_str(";")?; design.nets.push(net);
}
tk.expect_str("END")?;
tk.expect_str("NETS")?;
} else if tk.test_str("SCANCHAINS")? {
return Err(LefDefParseError::NotImplemented("SCANCHAINS"));
} else if tk.test_str("GROUPS")? {
let _num_groups: u32 = tk.take_and_parse()?;
while tk.test_str("-")? {
let group_name = tk.take_str()?;
let mut group = Group::default();
while !tk.peeking_test_str("+")? {
let component = tk.take_str()?;
group.component_names.push(component);
}
while tk.test_str("+")? {
if tk.test_str("REGION")? {
let region_name = tk.take_str()?;
group.region_name = Some(region_name);
} else if tk.test_str("PROPERTY")? {
while !tk.peeking_test_str("+")? {
if let Some((name, value)) =
read_def_property(&mut design.property_definitions, &mut tk)?
{
group.properties.insert(name, value);
}
}
} else {
return Err(LefDefParseError::UnexpectedToken(
"REGION or PROPERTY".to_string(),
tk.current_token_str().unwrap(),
));
}
}
design.groups.entry(group_name).or_default().push(group);
}
tk.expect_str("END")?;
tk.expect_str("GROUPS")?;
} else if tk.test_str("BEGINEXT")? {
tk.skip_until_str("ENDEXT")?;
} else {
return Err(LefDefParseError::UnknownToken(
tk.current_token_str().unwrap(),
));
}
}
Ok(design)
}
#[test]
fn test_read_def() {
let data = r#"
VERSION 5.7 ;
DIVIDERCHAR "/" ;
BUSBITCHARS "[]" ;
DESIGN test_design ;
UNITS DISTANCE MICRONS 2000 ;
TECHNOLOGY FreePDK45 ;
HISTORY This is a test. ;
HISTORY This is an other test. ;
PROPERTYDEFINITIONS
COMPONENTPIN designRuleWidth REAL ;
DESIGN testProperty REAL 0.123 ;
DESIGN testProperty2 STRING "as df" ;
END PROPERTYDEFINITIONS
DIEAREA ( 0 0 ) ( 10000 10000 ) ;
COMPONENTS 3 ;
- _1_ BUF_X2 ;
- _2_ BUF_X2 ;
- _3_ BUF_X2 ;
END COMPONENTS
BLOCKAGES 3 ;
- LAYER metal1
RECT ( -100 200 ) ( 0 100 )
RECT ( -200 200 ) ( 300 500 ) ;
- LAYER metal2 + PUSHDOWN + COMPONENT comp1 + EXCEPTPGNET + SPACING 10
RECT ( -100 200 ) ( 0 100 )
RECT ( -200 200 ) ( 300 500 ) ;
- PLACEMENT
RECT ( -100 200 ) ( 0 100 )
RECT ( -200 200 ) ( 300 500 ) ;
- PLACEMENT
RECT ( -100 200 ) ( 0 100 )
RECT ( -200 200 ) ( 300 500 ) ;
- LAYER metal3
RECT ( -100 200 ) ( 0 100 )
RECT ( -200 200 ) ( 300 500 ) ;
END BLOCKAGES
PINS 2 ;
- IN + NET IN
+ DIRECTION INPUT
- OUT + NET OUT
+ DIRECTION OUTPUT
END PINS
NETS 6 ;
- IN ( PIN IN ) ;
- OUT ( PIN OUT ) ;
- net1 ( _1_ A ) ;
# With more attributes:
- net2 ( _2_ A ) ( _3_ B + SYNTHESIZED ) ( PIN OUT ) + SHIELDNET shieldnet1
+ XTALK 1
+ NONDEFAULTRULE nondefaultrule1
+ SOURCE TEST
+ FIXEDBUMP
+ FREQUENCY 1000000
+ ORIGINAL originalNet
+ USE ANALOG
+ PATTERN BALANCED
+ ESTCAP 0.123
+ WEIGHT 2
+ PROPERTY testProperty 3.14 testProperty2 someText
+ PROPERTY testProperty 3.14 testProperty2 someText
;
# Net with simple wiring.
- net2 ( _1_ A ) ( _2_ A )
+ ROUTED metal1 ( 0 0 ) ( 10 0 )
;
- net3 ( _1_ A ) ( _2_ A )
+ ROUTED metal1 ( 0 0 ) ( 10 0 ) ( * 10 ) ( * 20 )
NEW metal2 ( 0 0 ) ( 10 0 )
;
# Nets with vias.
- net4 ( _1_ A ) ( _2_ A )
+ ROUTED metal1 ( 0 0 ) ( 10 0 ) VIA12 ( * 20 ) ( 40 * )
NEW metal2 ( 0 0 ) ( 10 0 )
;
# Multi patterning
- net4 ( _1_ A ) ( _2_ A )
+ ROUTED metal1 ( 0 0 ) MASK 1 ( 10 0 ) MASK 012 VIA12 ( * 20 ) MASK 2 ( 40 * )
NEW metal2 ( 0 0 ) MASK 1 ( 10 0 )
;
END NETS
BEGINEXT
test 123 ;
ENDEXT
END DESIGN
"#;
let result = read_def_chars(data.chars());
dbg!(&result);
assert!(result.is_ok());
}
pub fn read_def_property<I>(
property_definitions: &mut BTreeMap<String, DEFPropertyDefinition>,
tk: &mut Tokenized<I, LefDefLexer>,
) -> Result<Option<(String, PropertyValue)>, LefDefParseError>
where
I: Iterator<Item = char> + PeekingNext,
{
let property_name = tk.take_str()?;
let property_def = property_definitions.get(&property_name);
if let Some(property_def) = property_def {
let prop_value = match property_def.property_type {
PropertyType::Integer => PropertyValue::Int(tk.take_and_parse()?),
PropertyType::Real => PropertyValue::Real(tk.take_and_parse()?),
PropertyType::String => PropertyValue::String(tk.take_str()?),
};
Ok(Some((property_name, prop_value)))
} else {
log::error!("Property is not defined: '{}'", &property_name);
tk.advance(); Ok(None)
}
}