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.

1290 lines
53 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 DEF (Design Exchange Format).
// TODO: Remove this once this module is finished.
#![allow(unused_variables)]
use crate::stream_parser::{LefDefError, tokenize, Tokenized};
use std::collections::BTreeMap;
use crate::common::*;
use crate::def_ast::*;
use libreda_db::prelude as db;
use itertools::PeekingNext;
use std::str::FromStr;
use std::io::Read;
/// Configuration for the DEF reader.
#[derive(Copy, Clone, Default, Debug)]
pub struct DEFReaderConfig {
/// Ignore errors that still allow to parse the rest of the DEF file.
pub ignore_non_fatal_errors: bool,
}
/// Parse a DEF file from byte stream.
pub fn read_def_bytes<R: Read>(reader: &mut R) -> Result<DEF, LefDefError>
{
read_def_chars(
reader.bytes().map(|b| b.unwrap() as char)
)
}
/// Parse a DEF file from byte stream.
pub fn read_def_bytes_with_config<R: Read>(config: &DEFReaderConfig, reader: &mut R) -> Result<DEF, LefDefError>
{
read_def_chars_with_config(
config,
reader.bytes().map(|b| b.unwrap() as char)
)
}
/// Parse a DEF file from an iterator over `char`s.
/// This calls `read_def_with_config()` with default configuration options.
pub fn read_def_chars<I>(chars: I) -> Result<DEF, LefDefError>
where I: Iterator<Item=char>
{
read_def_chars_with_config(&DEFReaderConfig::default(), chars)
}
/// Parse a DEF file from an iterator over `char`s.
pub fn read_def_chars_with_config<I>(config: &DEFReaderConfig, chars: I) -> Result<DEF, 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_def_impl(config, line_count);
if result.is_err() {
println!("DEF error on line: {} (at {})", line_num, char_num);
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>)
-> Result<RegularWiring, LefDefError> {
let wiring_class: WiringClass = tk.take_and_parse()?;
let mut wiring = RegularWiring {
class: wiring_class,
wiring: vec![],
};
// Read wiring segments.
loop {
let layer_name = tk.take()?;
let mut wiring_statement = RegularWiringStatement {
start_layer_name: layer_name,
style_num: 0,
taper_rule: None,
wiring_segments: vec![],
};
if tk.test("TAPER")? {} else if tk.test("TAPERRULE")? {
wiring_statement.taper_rule = Some(tk.take()?);
}
if tk.test("STYLE")? {
wiring_statement.style_num = tk.take_and_parse()?;
}
// The previous point of the path.
// This is used to resolve implicit coordinates like `( 0 0 ) ( * 1 )`.
let mut prev_point: Option<(db::Coord, db::Coord)> = None;
// Read a point of the form `( x y [extvalue] )`.
// x and y can be `*` and refer to the previous value.
fn read_path_point<T: FromStr + Copy, I: Iterator<Item=char> + PeekingNext>
(tk: &mut Tokenized<I>, prev_point: &Option<(T, T)>)
-> Result<((T, T), Option<T>), LefDefError>
{
// Read point.
tk.expect("(")?;
let x = if tk.test("*")? {
// Implicit x-coordinate.
prev_point.ok_or(LefDefError::Other("x-coordinate not yet defined. Cannot use '*'."))?.0
} else {
// Explicit y-coordinate.
tk.take_and_parse()?
};
let y = if tk.test("*")? {
// Implicit y-coordinate.
prev_point.ok_or(LefDefError::Other("x-coordinate not yet defined. Cannot use '*'."))?.1
} else {
// Explicit y-coordinate.
tk.take_and_parse()?
};
let ext_value = if !tk.test(")")? {
// There's an optional [extValue].
let ext_value = tk.take_and_parse()?;
tk.expect(")")?;
Some(ext_value)
} else {
None
};
Ok(((x, y), ext_value))
}
// Read the first point.
let (p, extvalue) = read_path_point(tk, &prev_point)?;
prev_point = Some(p);
// TODO: Store the first point.
// Read path points.
// TODO
while !tk.peeking_test(";")? && !tk.peeking_test("NEW")? {
let mut mask_num: Option<u8> = None;
let mut via_mask_num: Option<ViaMaskNum> = None;
if tk.test("VIRTUAL")? {
// Read the virtual point.
let (p, _extvalue) = read_path_point(tk, &prev_point)?;
// extvalue should be `None`.
prev_point = Some(p);
// TODO: Store virtual point.
} else {
let mut expect_via = false;
if tk.test("MASK")? {
if tk.current_token_str().map(|s| s.len()) == Some(3) {
// This is a 3-letter via mask number.
via_mask_num = Some(tk.take_and_parse()?);
expect_via = true;
// TODO: Store mask num.
} else {
// Single-digit mask number.
mask_num = Some(tk.take_and_parse()?);
// TODO: Store mask num.
}
}
if !tk.peeking_test("(")? {
if tk.test("RECT")? {
tk.expect("(")?;
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(")")?;
} else {
// Via extension.
let via_name = tk.take()?;
let orient: Option<Orient> = if !tk.peeking_test("NEW")?
&& !tk.peeking_test(";")?
&& !tk.peeking_test("(")?
&& !tk.peeking_test("+")? {
Some(tk.take_and_parse()?)
} else {
None
};
}
} else {
let (p, extvalue) = read_path_point(tk, &prev_point)?;
prev_point = Some(p);
// TODO: Store point.
}
}
}
// Store the wiring statement.
dbg!(&wiring_statement);
wiring.wiring.push(wiring_statement);
if !tk.test("NEW")? {
break;
} else {
// NEW -> Continue with reading next wiring statement.
}
}
Ok(wiring)
}
/// Parse a DEF file from an iterator over `char`s.
fn read_def_impl<I>(config: &DEFReaderConfig, chars: I) -> Result<DEF, LefDefError>
where I: Iterator<Item=char>
{
let mut design = DEF::default();
// Token stream.
let mut tk = tokenize(chars);
tk.advance();
loop {
// dbg!(tk.current_token_str());
if tk.test("END")? {
// End of DEF file.
tk.expect("DESIGN")?;
break;
} else if tk.test("VERSION")? {
let version = tk.take()?;
design.version = Some(version);
tk.expect(";")?;
} 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);
design.busbitchars = (start, end);
} else {
return Err(LefDefError::InvalidCharacter); // TODO: More precise error.
}
tk.expect(";")?;
} else if tk.test("NAMESCASESENSITIVE")? {
tk.expect("ON")
.map_err(|_| LefDefError::Other("Support only NAMESCASESENSITIVE ON."))?;
// TODO: OFF is not supported.
tk.expect(";")?;
} else if tk.test("DIVIDERCHAR")? {
let divchar = tk.take()?;
if divchar.len() == 1 {
design.dividerchar = divchar.chars().nth(0).unwrap();
log::debug!("Divider char: '{}'", design.dividerchar);
} else {
return Err(LefDefError::InvalidCharacter); // TODO: More precise error.
}
tk.expect(";")?;
} else if tk.test("DESIGN")? {
let design_name = tk.take()?;
tk.expect(";")?;
design.design_name = Some(design_name);
} else if tk.test("TECHNOLOGY")? {
let tech_name = tk.take()?;
tk.expect(";")?;
design.technology = Some(tech_name);
} else if tk.test("UNITS")? {
tk.expect("DISTANCE")?;
tk.expect("MICRONS")?;
let units = tk.take_and_parse()?;
tk.expect(";")?;
design.units = units;
} else if tk.test("HISTORY")? {
let mut text = String::new();
// Read all text until ';'.
while !tk.test(";")? {
if let Some(s) = tk.current_token_str() {
if !text.is_empty() {
text.push(' '); // Put a space between words.
}
text.extend(s.chars());
}
tk.advance();
}
design.history.push(text);
} else if tk.test("PROPERTYDEFINITIONS")? {
loop {
if tk.test("END")? {
tk.expect("PROPERTYDEFINITIONS")?;
break;
} else {
let property_object_type: DEFPropertyObjectType = tk.take_and_parse()?;
let property_name = tk.take()?;
let property_type: PropertyType = tk.take_and_parse()?;
// Read allowed range of property value.
let mut range = None;
let mut default_value = None;
match property_type {
PropertyType::Integer => {
if tk.test("RANGE")? {
// Limit of property values.
let min = tk.take_and_parse()?;
let max = tk.take_and_parse()?;
range = Some((PropertyValue::Int(min), PropertyValue::Int(max)));
}
if !tk.peeking_test(";")? {
let default = tk.take_and_parse()?;
default_value = Some(PropertyValue::Int(default));
}
tk.expect(";")?;
}
PropertyType::Real => {
if tk.test("RANGE")? {
// Limit of property values.
let min = tk.take_and_parse()?;
let max = tk.take_and_parse()?;
range = Some((PropertyValue::Real(min), PropertyValue::Real(max)));
}
if !tk.peeking_test(";")? {
let default = tk.take_and_parse()?;
default_value = Some(PropertyValue::Real(default));
}
}
PropertyType::String => {
// No limits defined.
if !tk.peeking_test(";")? {
let default = tk.take()?;
default_value = Some(PropertyValue::String(default));
}
}
}
tk.expect(";")?;
let property_definition = DEFPropertyDefinition {
object_type: property_object_type,
property_type,
range,
default_value,
};
// TODO: Store property definition.
design.property_definitions.insert(property_name, property_definition);
}
}
log::warn!("Skipping PROPERTYDEFINITIONS.");
} else if tk.test("DIEAREA")? {
// Die area can be a rectangle or a rectilinear polygon.
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 {
// Illegal die area.
log::error!("DIEAREA must consist of two or more points.");
return Err(LefDefError::Other("Illegal die area. Must have two or more vertices."));
} else if points.len() == 2 {
// Is a rectangle.
let rect: db::Rect<db::SInt> = db::Rect::new(points[0], points[1]);
let poly = db::SimpleRPolygon::from(rect);
poly
} else {
// Is a polygon.
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(LefDefError::Other("DIEAREA polygon is not rectilinear."))?
}
};
design.die_area = Some(die_area);
} else if tk.test("ROW")? {
let row_name = tk.take()?;
let site_name = tk.take()?;
let orig_x: db::Coord = tk.take_and_parse()?;
let orig_y: db::Coord = tk.take_and_parse()?;
// Orientation of all sites in the row.
let site_orient: Orient = tk.take_and_parse()?;
let mut step_pattern = RowStepPattern::default();
if tk.test("DO")? {
step_pattern.num_x = tk.take_and_parse()?;
tk.expect("BY")?;
step_pattern.num_y = tk.take_and_parse()?;
if tk.test("STEP")? {
let step_x = tk.take_and_parse()?;
let step_y = tk.take_and_parse()?;
step_pattern.step = Some((step_x, step_y));
}
}
// Read custom properties.
let mut properties = BTreeMap::new();
while tk.test("+")? {
tk.expect("PROPERTY")?;
while !tk.peeking_test("+")? {
if let Some((name, value)) = read_def_property(&mut design.property_definitions, &mut tk)? {
// Store property.
properties.insert(name, value);
}
}
}
// Create the row data structure.
let row = Row {
site_name,
orig: (orig_x, orig_y),
site_orient,
step_pattern,
properties,
};
tk.expect(";")?;
// Store the row.
design.rows.insert(row_name, row);
} else if tk.test("TRACKS")? {
let is_horizontal = tk.test("Y")?;
if !is_horizontal {
tk.expect("X")?;
}
// X or Y coordinate of the row.
let start = tk.take_and_parse()?;
tk.expect("DO")?;
let num_tracks = tk.take_and_parse()?;
tk.expect("STEP")?;
let step = tk.take_and_parse()?; // Space between tracks.
let mask = if tk.test("MASK")? {
let mask_num = tk.take_and_parse()?;
let same_mask = tk.test("SAMEMASK")?;
Some((mask_num, same_mask))
} else {
None
};
let mut layers = Vec::new();
if tk.test("LAYER")? {
while !tk.peeking_test(";")? {
// Routing layers used for this tracks.
let layer_name = tk.take()?;
layers.push(layer_name);
}
}
tk.expect(";")?;
let tracks = Tracks {
is_horizontal,
start,
num_tracks,
step,
mask,
layers,
};
// Store track.
design.tracks.push(tracks);
} else if tk.test("GCELLGRID")? {
let is_horizontal = tk.test("Y")?;
if !is_horizontal {
tk.expect("X")?;
}
// X or Y coordinate of the row.
let start: db::SInt = tk.take_and_parse()?;
tk.expect("DO")?;
let num_tracks: u32 = tk.take_and_parse()?;
tk.expect("STEP")?;
let space: db::SInt = tk.take_and_parse()?; // Space between tracks.
tk.expect(";")?;
// TODO: Store grid information.
design.gcell_grid.push(());
} else if tk.test("VIAS")? {
return Err(LefDefError::NotImplemented("VIAS"));
} else if tk.test("STYLES")? {
return Err(LefDefError::NotImplemented("STYLES"));
} else if tk.test("NONDEFAULTRULES")? {
return Err(LefDefError::NotImplemented("NONDEFAULTRULES"));
} else if tk.test("REGIONS")? {
let _num_regions: u32 = tk.take_and_parse()?;
while tk.test("-")? {
let mut region = Region::default();
let region_name = tk.take()?;
while !tk.peeking_test("+")? {
// Read rectangles.
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("+")? {
if tk.test("TYPE")? {
region.region_type = Some(tk.take_and_parse()?);
} else if tk.test("PROPERTY")? {
while !tk.peeking_test("+")? {
if let Some((name, value)) = read_def_property(&mut design.property_definitions, &mut tk)? {
// TODO: Store property. Name and type must match the property definitions.
}
}
}
}
design.regions.insert(region_name, region);
}
tk.expect("END")?;
tk.expect("REGIONS")?;
} else if tk.test("COMPONENTMASKSHIFT")? {
return Err(LefDefError::NotImplemented("COMPONENTMASKSHIFT"));
} else if tk.test("COMPONENTS")? {
let num_components: u32 = tk.take_and_parse()?;
design.components.reserve(num_components as usize);
tk.expect(";")?;
while tk.test("-")? {
let mut component = Component::default();
component.name = tk.take()?;
component.model_name = tk.take()?;
while tk.test("+")? {
if tk.test("EEQMASTER")? {
component.eeq_master = Some(tk.take()?);
} else if tk.test("SOURCE")? {
component.source = tk.take_and_parse()?;
} else if tk.test("FIXED")? {
// Cannot be moved by automatic tools.
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("COVER")? {
// Cannot be moved by automatic tools nor interactive commands.
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("PLACED")? {
// Cannot be moved by automatic tools.
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("UNPLACED")? {
// Component is not placed yet.
component.position = None;
} else if tk.test("HALO")? {
let soft = tk.test("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("ROUTEHALO")? {
let halo_dist: db::SInt = tk.take_and_parse()?;
let min_layer = tk.take()?;
let max_layer = tk.take()?;
// TODO
} else if tk.test("WEIGHT")? {
// Specify how close the component should stay near
// to the original location during automated placement.
// Default is 0.
component.weight = tk.take_and_parse()?;
} else if tk.test("REGION")? {
// Name of the region in which the component should be placed.
// If the bounding box of the component is larger than the region
// issue an error message and ignore this argument.
let region_name = tk.take()?;
if let Some(region) = design.regions.get(&region_name) {
// TODO.
component.region = Some(region_name);
} else {
// Ignore the region statement.
log::error!("Ignore region statement. No such region: '{}'", &region_name);
}
} else if tk.test("PROPERTY")? {
while !tk.peeking_test("+")? {
if let Some((name, value)) = read_def_property(&mut design.property_definitions, &mut tk)? {
// Store property.
component.properties.insert(name, value);
}
}
} else {
return Err(LefDefError::UnknownToken(tk.current_token().unwrap()));
}
}
tk.expect(";")?;
design.components.push(component);
}
tk.expect("END")?;
tk.expect("COMPONENTS")?;
} else if tk.test("PINS")? {
let num_pins: usize = tk.take_and_parse()?;
tk.expect(";")?;
while tk.test("-")? {
let mut pin = Pin::default();
pin.pin_name = tk.take()?;
tk.expect("+")?;
tk.expect("NET")?;
pin.net_name = tk.take()?;
let mut current_port: Option<PinPort> = None;
while tk.test("+")? {
if tk.test("SPECIAL")? {
pin.special = true;
} else if tk.test("DIRECTION")? {
pin.direction = Some(tk.take_and_parse()?);
} else if tk.test("NETEXPR")? {
pin.net_expr = Some(tk.take()?);
} else if tk.test("SUPPLYSENSITIVITY")? {
pin.supply_sensitivity = Some(tk.take()?);
} else if tk.test("GROUNDSENSITIVITY")? {
pin.ground_sensitivity = Some(tk.take()?);
} else if tk.test("USE")? {
pin.signal_use = tk.take_and_parse()?;
} else if tk.test("PORT")? {
if let Some(port) = current_port.take() {
pin.ports.push(port);
};
current_port = Some(PinPort::default()); // Define a new port.
let port = current_port.as_mut().unwrap();
} else if tk.test("LAYER")? {
if current_port.is_none() {
current_port = Some(PinPort::default());
}
let port = current_port.as_mut().unwrap();
let layer_name = tk.take()?;
if tk.test("MASK")? {
let mask_num: u32 = tk.take_and_parse()?;
}
if tk.test("SPACING")? {
let min_spacing: u32 = tk.take_and_parse()?;
}
if tk.test("DESIGNRULEWIDTH")? {
let effective_width: u32 = tk.take_and_parse()?;
}
let p1: (db::SInt, db::SInt) = read_point(&mut tk)?;
let p2: (db::SInt, db::SInt) = read_point(&mut tk)?;
} else if tk.test("POLYGON")? {
if current_port.is_none() {
current_port = Some(PinPort::default());
}
let port = current_port.as_mut().unwrap();
let layer_name = tk.take()?;
if tk.test("MASK")? {
let mask_num: u32 = tk.take_and_parse()?;
}
if tk.test("SPACING")? {
let min_spacing: u32 = tk.take_and_parse()?;
}
if tk.test("DESIGNRULEWIDTH")? {
let effective_width: u32 = tk.take_and_parse()?;
}
let points: Vec<(db::SInt, db::SInt)> = read_polygon(&mut tk)?;
} else if tk.test("VIA")? {
if current_port.is_none() {
current_port = Some(PinPort::default());
}
let port = current_port.as_mut().unwrap();
if tk.test("MASK")? {
// Via mask num is encoded as a three-digit hex number
// Of the form <topMaskNum><cutMaskNum><bottomMaskNum>.
let via_mask_num: ViaMaskNum = tk.take_and_parse()?;
}
} else if tk.test("ANTENNAPINPARTIALMETALAREA")? {
return Err(LefDefError::NotImplemented("ANTENNAPINPARTIALMETALAREA"));
} else if tk.test("ANTENNAPINPARTIALMETALSIDEAREA")? {
return Err(LefDefError::NotImplemented("ANTENNAPINPARTIALMETALSIDEAREA"));
} else if tk.test("ANTENNAPINPARTIALCUTAREA")? {
return Err(LefDefError::NotImplemented("ANTENNAPINPARTIALCUTAREA"));
} else if tk.test("ANTENNAPINDIFFAREA")? {
return Err(LefDefError::NotImplemented("ANTENNAPINDIFFAREA"));
} else if tk.test("ANTENNAPINDIFFAREA")? {
return Err(LefDefError::NotImplemented("ANTENNAPINDIFFAREA"));
} else if tk.test("ANTENNAMODEL")? {
return Err(LefDefError::NotImplemented("ANTENNAMODEL"));
} else if tk.test("ANTENNAPINGATEAREA")? {
return Err(LefDefError::NotImplemented("ANTENNAPINGATEAREA"));
} else if tk.test("ANTENNAPINMAXAREACAR")? {
return Err(LefDefError::NotImplemented("ANTENNAPINMAXAREACAR"));
} else if tk.test("ANTENNAPINMAXSIDEAREACAR")? {
return Err(LefDefError::NotImplemented("ANTENNAPINMAXSIDEAREACAR"));
} else if tk.test("ANTENNAPINMAXCUTCAR")? {
return Err(LefDefError::NotImplemented("ANTENNAPINMAXCUTCAR"));
} else {
return Err(LefDefError::UnexpectedToken(
"".to_string(),
tk.current_token().unwrap(),
));
}
}
// Store the current port, if there's any.
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("END")?;
tk.expect("PINS")?;
} else if tk.test("PINPROPERTIES")? {
return Err(LefDefError::NotImplemented("PINPROPERTIES"));
} else if tk.test("BLOCKAGES")? {
let num_blockages: u32 = tk.take_and_parse()?;
design.blockages.reserve(num_blockages as usize);
tk.expect(";")?;
while tk.test("-")? {
if tk.test("LAYER")? {
let mut blk = LayerBlockage::default();
blk.layer = tk.take()?;
while tk.test("+")? {
if tk.test("SLOTS")? {
blk.slots = true;
} else if tk.test("FILLS")? {
blk.fills = true;
} else if tk.test("PUSHDOWN")? {
blk.pushdown = true;
} else if tk.test("EXCEPTPGNET")? {
blk.except_pg_net = true;
} else if tk.test("COMPONENT")? {
blk.component = Some(tk.take()?);
} else if tk.test("SPACING")? {
let spacing = tk.take_and_parse()?;
blk.spacing_or_designrule_width = Some(SpacingOrDesignRuleWidth::MinSpacing(spacing));
} else if tk.test("DESIGNRULEWIDTH")? {
let width = tk.take_and_parse()?;
blk.spacing_or_designrule_width = Some(SpacingOrDesignRuleWidth::DesignRuleWidth(width));
} else if tk.test("MASK")? {
let mask_num = tk.take_and_parse()?;
blk.mask_num = Some(mask_num);
} else {
return Err(LefDefError::UnexpectedToken(
"SLOTS, FILLS, PUSHDOWN, EXCEPTPGNET, SPACING, DESIGNRULEWIDTH or MASK".to_string(),
tk.current_token().unwrap(),
));
}
}
while !tk.test(";")? {
if tk.test("RECT")? {
let (p1, p2) = read_rect(&mut tk)?;
let rect = db::Rect::new(p1, p2);
blk.blockage_shapes.push(BlockageShape::Rect(rect));
} else if tk.test("POLYGON")? {
let points = read_polygon(&mut tk)?;
let poly = db::SimplePolygon::from(points);
blk.blockage_shapes.push(BlockageShape::Polygon(poly));
} else {
return Err(LefDefError::UnexpectedToken(
"RECT or POLYGON".to_string(),
tk.current_token().unwrap(),
));
}
}
design.blockages.push(Blockage::LayerBlockage(blk));
} else if tk.test("PLACEMENT")? {
let mut blk = PlacementBlockage::default();
while tk.test("+")? {
if tk.test("SOFT")? {
blk.blockage_type = Some(PlacementBlockageType::Soft);
} else if tk.test("PARTIAL")? {
let max_density = tk.take_and_parse()?;
blk.blockage_type = Some(PlacementBlockageType::Partial(max_density));
} else if tk.test("PUSHDOWN")? {
blk.pushdown = true;
} else if tk.test("COMPONENT")? {
blk.component = Some(tk.take()?);
} else {
return Err(LefDefError::UnexpectedToken(
"SOFT, PARTIAL, PUSHDOWN or COMPONENT".to_string(),
tk.current_token().unwrap(),
));
}
}
while !tk.test(";")? {
tk.expect("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(LefDefError::UnexpectedToken(
"LAYER of PLACEMENT".to_string(),
tk.current_token().unwrap(),
));
}
}
tk.expect("END")?;
tk.expect("BLOCKAGES")?;
} else if tk.test("SLOTS")? {
return Err(LefDefError::NotImplemented("SLOTS"));
} else if tk.test("FILLS")? {
return Err(LefDefError::NotImplemented("FILLS"));
} else if tk.test("SPECIALNETS")? {
return Err(LefDefError::NotImplemented("SPECIALNETS"));
} else if tk.test("NETS")? {
let _num_nets: u32 = tk.take_and_parse()?;
tk.expect(";")?;
// design.nets.reserve(num_nets);
while tk.test("-")? {
let mut net = Net::default();
if tk.test("MUSTJOIN")? {
let component_name = tk.take()?;
let pin_name = tk.take()?;
net.mustjoin = Some(
Mustjoin {
component_name,
pin_name,
}
)
} else {
net.name = Some(tk.take()?);
while tk.test("(")? {
let term = if tk.test("PIN")? {
let pin_name = tk.take()?;
NetTerminal::IoPin(pin_name)
} else {
let component_name = tk.take()?;
let pin_name = tk.take()?;
NetTerminal::ComponentPin { component_name, pin_name }
};
if tk.test("+")? {
tk.expect("SYNTHESIZED")?;
// TODO: Store synthesized flag.
}
net.terminals.push(term);
tk.expect(")")?;
}
while tk.test("+")? {
if tk.test("SHIELDNET")? {
net.shield_nets.push(tk.take()?);
} else if tk.test("VPIN")? {
unimplemented!()
} else if tk.test("SUBNET")? {
unimplemented!()
} else if tk.test("XTALK")? {
net.xtalk_class = tk.take_and_parse()?;
} else if tk.test("NONDEFAULTRULE")? {
net.non_default_rule = Some(tk.take()?);
} else if tk.peeking_test("COVER")?
|| tk.peeking_test("FIXED")?
|| tk.peeking_test("ROUTED")?
|| tk.peeking_test("NOSHIELD")? {
// Regular wiring
let wiring_class: WiringClass = tk.take_and_parse()?;
let mut wiring = RegularWiring {
class: wiring_class,
wiring: vec![],
};
// Read wiring segments.
loop {
let layer_name = tk.take()?;
let mut wiring_statement = RegularWiringStatement {
start_layer_name: layer_name,
style_num: 0,
taper_rule: None,
wiring_segments: vec![],
};
if tk.test("TAPER")? {} else if tk.test("TAPERRULE")? {
wiring_statement.taper_rule = Some(tk.take()?);
}
if tk.test("STYLE")? {
wiring_statement.style_num = tk.take_and_parse()?;
}
// The previous point of the path.
// This is used to resolve implicit coordinates like `( 0 0 ) ( * 1 )`.
let mut prev_point: Option<(db::Coord, db::Coord)> = None;
// Read a point of the form `( x y [extvalue] )`.
// x and y can be `*` and refer to the previous value.
fn read_path_point<T: FromStr + Copy, I: Iterator<Item=char> + PeekingNext>
(tk: &mut Tokenized<I>, prev_point: &Option<(T, T)>)
-> Result<((T, T), Option<T>), LefDefError>
{
// Read point.
tk.expect("(")?;
let x = if tk.test("*")? {
// Implicit x-coordinate.
prev_point.ok_or(LefDefError::Other("x-coordinate not yet defined. Cannot use '*'."))?.0
} else {
// Explicit y-coordinate.
tk.take_and_parse()?
};
let y = if tk.test("*")? {
// Implicit y-coordinate.
prev_point.ok_or(LefDefError::Other("x-coordinate not yet defined. Cannot use '*'."))?.1
} else {
// Explicit y-coordinate.
tk.take_and_parse()?
};
let ext_value = if !tk.test(")")? {
// There's an optional [extValue].
let ext_value = tk.take_and_parse()?;
tk.expect(")")?;
Some(ext_value)
} else {
None
};
Ok(((x, y), ext_value))
}
// Read the first point.
let (p, extvalue) = read_path_point(&mut tk, &prev_point)?;
prev_point = Some(p);
// TODO: Store the first point.
// Read path points.
// TODO
while !tk.peeking_test(";")? && !tk.peeking_test("NEW")? {
let mut mask_num: Option<u8> = None;
let mut via_mask_num: Option<ViaMaskNum> = None;
if tk.test("VIRTUAL")? {
// Read the virtual point.
let (p, _extvalue) = read_path_point(&mut tk, &prev_point)?;
// extvalue should be `None`.
prev_point = Some(p);
// TODO: Store virtual point.
} else {
let mut expect_via = false;
if tk.test("MASK")? {
if tk.current_token_str().map(|s| s.len()) == Some(3) {
// This is a 3-letter via mask number.
via_mask_num = Some(tk.take_and_parse()?);
expect_via = true;
// TODO: Store mask num.
} else {
// Single-digit mask number.
mask_num = Some(tk.take_and_parse()?);
// TODO: Store mask num.
}
}
if !tk.peeking_test("(")? {
if tk.test("RECT")? {
tk.expect("(")?;
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(")")?;
} else {
// Via extension.
let via_name = tk.take()?;
let orient: Option<Orient> = if !tk.peeking_test("NEW")?
&& !tk.peeking_test(";")?
&& !tk.peeking_test("(")?
&& !tk.peeking_test("+")? {
Some(tk.take_and_parse()?)
} else {
None
};
}
} else {
let (p, extvalue) = read_path_point(&mut tk, &prev_point)?;
prev_point = Some(p);
// TODO: Store point.
}
}
}
// Store the wiring statement.
dbg!(&wiring_statement);
wiring.wiring.push(wiring_statement);
if !tk.test("NEW")? {
break;
} else {
// NEW -> Continue with reading next wiring statement.
}
}
// Store the wiring statements.
net.regular_wiring.push(wiring);
} else if tk.test("SOURCE")? {
net.source = tk.take_and_parse()?;
} else if tk.test("FIXEDBUMP")? {
net.fixed_bump = true;
} else if tk.test("FREQUENCY")? {
net.frequency = Some(tk.take_and_parse()?);
} else if tk.test("ORIGINAL")? {
net.original = Some(tk.take()?);
} else if tk.test("USE")? {
net.net_use = tk.take_and_parse()?;
} else if tk.test("PATTERN")? {
net.pattern = tk.take_and_parse()?;
} else if tk.test("ESTCAP")? {
net.est_cap = Some(tk.take_and_parse()?);
} else if tk.test("WEIGHT")? {
net.weight = tk.take_and_parse()?;
} else if tk.test("PROPERTY")? {
while !tk.peeking_test("+")? && !tk.peeking_test(";")? {
if let Some((name, value)) = read_def_property(&mut design.property_definitions, &mut tk)? {
// Store property.
net.properties.insert(name, value);
}
}
} else {
return Err(LefDefError::UnexpectedToken(
"".to_string(),
tk.current_token().unwrap(),
));
}
}
}
tk.expect(";")?; // End of net.
dbg!(&net);
design.nets.push(net);
}
tk.expect("END")?;
tk.expect("NETS")?;
// return Err(LefDefError::NotImplemented("NETS"));
} else if tk.test("SCANCHAINS")? {
return Err(LefDefError::NotImplemented("SCANCHAINS"));
} else if tk.test("GROUPS")? {
let _num_groups: u32 = tk.take_and_parse()?;
// TODO: Reserve space.
//design.groups.extend_reserve(num_groups);
while tk.test("-")? {
let group_name = tk.take()?;
let mut group = Group::default();
// Read component names.
while !tk.peeking_test("+")? {
let component = tk.take()?;
group.component_names.push(component);
}
while tk.test("+")? {
if tk.test("REGION")? {
let region_name = tk.take()?;
group.region_name = Some(region_name);
} else if tk.test("PROPERTY")? {
while !tk.peeking_test("+")? {
if let Some((name, value)) = read_def_property(&mut design.property_definitions, &mut tk)? {
// Store property. Name and type must match the property definitions.
group.properties.insert(name, value);
}
}
} else {
return Err(LefDefError::UnexpectedToken(
"REGION or PROPERTY".to_string(),
tk.current_token().unwrap(),
));
}
}
// Store the group.
design.groups.entry(group_name)
.or_default()
.push(group);
}
tk.expect("END")?;
tk.expect("GROUPS")?;
} else if tk.test("BEGINEXT")? {
// Ignore extensions.
tk.skip_until("ENDEXT")?;
} else {
return Err(LefDefError::UnknownToken(tk.current_token().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
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());
}
/// Read a property name and a property value.
/// Checks if the property is specified in the PROPERTYDEFINITIONS. If not, an error is returned
/// and the property should be ignored.
///
/// Returns `(property_name, value)`.
pub fn read_def_property<I>(
property_definitions: &mut BTreeMap<String, DEFPropertyDefinition>,
tk: &mut Tokenized<I>,
) -> Result<Option<(String, PropertyValue)>, LefDefError>
where I: Iterator<Item=char> + PeekingNext {
let property_name = tk.take()?;
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()?),
};
// TODO: Store property.
Ok(Some((property_name, prop_value)))
} else {
log::error!("Property is not defined: '{}'", &property_name);
tk.advance(); // Skip property name.
// Err((LefDefError::UndefinedProperty(prop_name)))
Ok(None)
}
}