#![allow(unused_variables)]
pub use crate::stream_parser::LefDefParseError;
use crate::stream_parser::*;
use itertools::PeekingNext;
use crate::lef_ast::*;
use crate::common::*;
use libreda_db::prelude as db;
use std::io::Read;
fn read_step_pattern<I>(tk: &mut Tokenized<I>) -> Result<StepPattern, LefDefParseError>
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,
})
}
fn read_layer_geometries<I>(tk: &mut Tokenized<I>) -> Result<Option<LayerGeometries>, LefDefParseError>
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")?;
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);
}
loop {
if tk.test("PATH")? {
let iterate = tk.test("ITERATE")?;
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 {
Some(read_step_pattern(tk)?)
} else {
None
};
tk.expect(";")?;
let width = layer.width.unwrap(); 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 {
Some(read_step_pattern(tk)?)
} else {
None
};
tk.expect(";")?;
layer.geometries.push(
Geometry {
step_pattern,
shape: Shape::Rect(p1.into(), p2.into()),
}
)
} else if tk.test("POLYGON")? {
let iterate = tk.test("ITERATE")?;
let mut points = Vec::new();
while !tk.peeking_test("DO")? && !tk.peeking_test(";")? {
points.push(read_point(tk)?.into())
}
let step_pattern = if iterate {
Some(read_step_pattern(tk)?)
} else {
None
};
tk.expect(";")?;
layer.geometries.push(Geometry {
step_pattern,
shape: Shape::Polygon(points),
})
} else if tk.test("VIA")? {
let iterate = tk.test("ITERATE")?;
let point = read_point::<f64, _>(tk)?;
let via_name = tk.take()?;
if iterate {
let step_pattern = read_step_pattern(tk)?;
}
tk.expect(";")?;
return Err(LefDefParseError::NotImplemented("VIA inside layer geometry."));
} else {
break;
}
}
Ok(Some(layer))
} else {
Ok(None)
}
}
fn try_read_pin<I>(tk: &mut Tokenized<I>) -> Result<Option<MacroPin>, LefDefParseError>
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()?;
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()?; 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()?; 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()?; tk.expect(";")?;
port.class = Some(class);
}
while let Some(geo) = read_layer_geometries(tk)? {
port.geometries.push(geo);
}
tk.expect("END")?;
pin.ports.push(port);
} else if tk.test("PROPERTY")? {
tk.skip_until(";")?;
} else {
log::warn!("Skipping ANTENNA* properties of the MACRO PIN (not implemented).");
tk.skip_until(";")?;
}
}
Ok(Some(pin))
} else {
Ok(None)
}
}
fn try_read_obs<I>(tk: &mut Tokenized<I>) -> Result<Option<Vec<LayerGeometries>>, LefDefParseError>
where I: Iterator<Item=char> + PeekingNext {
if tk.test("OBS")? {
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)
}
}
pub fn read_lef_bytes<R: Read>(reader: &mut R) -> Result<LEF, LefDefParseError>
{
read_lef_chars(
reader.bytes().map(|b| b.unwrap() as char)
)
}
pub fn read_lef_chars<I>(chars: I) -> Result<LEF, LefDefParseError>
where I: Iterator<Item=char>
{
let mut line_num = 0;
let mut char_num = 0;
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
}
fn read_lef_impl<I>(chars: I) -> Result<LEF, LefDefParseError>
where I: Iterator<Item=char>
{
let mut library = LEF::default();
let mut tk = tokenize(chars);
library.busbitchars = ('[', ']');
library.dividerchar = '/';
tk.advance();
loop {
if tk.test("END")? {
if tk.test("LIBRARY")? {
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(LefDefParseError::IllegalBusBitChars(start, end));
}
log::debug!("Bus bit chars: '{}' '{}'", start, end);
library.busbitchars = (start, end);
} else {
return Err(LefDefParseError::InvalidCharacter); }
tk.expect(";")?;
} else if tk.test("NAMESCASESENSITIVE")? {
tk.take()?; 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(LefDefParseError::InvalidCharacter); }
tk.expect(";")?;
}
else if tk.test("UNITS")? {
library.technology.units = read_units(&mut tk, library.technology.units)?;
} else if tk.test("CLEARANCEMEASURE")? {
library.technology.clearance_measure = tk.take_and_parse()?;
tk.expect(";")?;
}
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(";")?;
}
library.technology.property_definitions
.insert(prop_name, ());
}
}
}
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(";")?;
}
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(";")?;
}
else if tk.test("NONDEFAULTRULE")? {
let hardspacing = tk.test("HARDSPACING")?;
return Err(LefDefParseError::NotImplemented("NONDEFAULTRULE"));
}
else if tk.test("LAYER")? {
let layer_name = tk.take()?;
tk.expect("TYPE")?;
if tk.test("CUT")? {
let mut layer = read_cut_layer(&mut tk)?;
layer.name = layer_name.clone();
library.technology.layers.push(Layer::Cut(layer));
} else if tk.test("ROUTING")? {
let mut layer = read_routing_layer(&mut tk)?;
layer.name = layer_name.clone();
library.technology.layers.push(Layer::Routing(layer));
} else if tk.test("MASTERSLICE")? {
let mut layer = read_masterslice_layer(&mut tk)?;
layer.name = layer_name.clone();
library.technology.layers.push(Layer::MasterSlice(layer));
} else if tk.test("OVERLAP")? {
loop {
if tk.test("END")? {
break;
} else {
tk.skip_until(";")?;
}
}
} else {
log::error!("Unsupported layer type '{}'.", tk.current_token_str().unwrap());
}
tk.expect(layer_name.as_str())?;
}
else if tk.test("VIA")? {
let _via = read_via(&mut tk)?;
}
else if tk.test("VIARULE")? {
let via_rule_name = tk.take()?;
tk.expect("GENERATE")?;
let is_default = tk.test("DEFAULT")?;
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(";")?;
}
}
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())?;
}
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(";")?;
}
}
}
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![];
while !tk.test("END")? {
if tk.test("CLASS")? {
class = Some(tk.take_and_parse()?); tk.expect(";")?;
} else if tk.test("SYMMETRY")? {
loop {
if tk.test(";")? {
break;
} else {
symmetry = symmetry.union(tk.take_and_parse()?);
}
}
} 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(LefDefParseError::Other("SIZE must be specified in SITE."))?,
symmetry,
class: class.ok_or(LefDefParseError::Other("CLASS must be specified in SITE."))?,
row_pattern,
};
library.sites.insert(site_name, site);
}
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(";")? {
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;
}
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))
}
else if tk.test("ORIGIN")? {
let origin = read_point(&mut tk)?;
tk.expect(";")?;
m.origin = origin.into();
}
else if tk.test("EEQ")? {
let macro_name = tk.take()?;
tk.expect(";")?;
m.eeq = Some(macro_name);
}
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));
}
else if tk.test("SYMMETRY")? {
let mut symmetry = Symmetry::default();
while !tk.test(";")? {
symmetry = symmetry.union(tk.take_and_parse()?);
}
m.symmetry = symmetry;
}
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);
}
else if let Some(pin) = try_read_pin(&mut tk)? {
m.pins.push(pin);
}
else if let Some(obs) = try_read_obs(&mut tk)? {
m.obs.extend(obs);
}
else if tk.test("DENSITY")? {
log::warn!("Skipping DENSITY.");
}
else if tk.test("PROPERTY")? {
let prop_name = tk.take()?;
let prop_value = tk.take()?;
tk.expect(";")?;
log::warn!("Skipping PROPERTY.");
}
}
tk.expect(m.name.as_str())?;
library.library.macros.insert(m.name.clone(), m);
} else {
println!("Unknown token: {}", tk.current_token().unwrap());
return Err(LefDefParseError::UnknownToken(tk.current_token().unwrap()));
}
}
Ok(library)
}
fn read_units<I>(tk: &mut Tokenized<I>, old_units: Units) -> Result<Units, LefDefParseError>
where I: Iterator<Item=char> + PeekingNext {
let mut units = old_units;
loop {
if tk.test("END")? {
tk.expect("UNITS")?;
break;
} else {
let mut time = units.time_ns;
let mut cap = units.capacitance_pf;
let mut res = units.resistance_ohms;
let mut power = units.power_mw;
let mut current = units.current_ma;
let mut voltage = units.voltage_v;
let mut database = units.database_microns;
let mut freq = units.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;
}
}
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,
};
tk.expect(";")?;
}
}
Ok(units)
}
fn read_via<I>(tk: &mut Tokenized<I>) -> Result<(), LefDefParseError>
where I: Iterator<Item=char> + PeekingNext {
let via_name = tk.take()?;
let is_default = tk.test("DEFAULT")?;
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")? {
let cut_pattern = tk.take()?;
tk.expect(";")?;
}
} else {
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(tk)?;
tk.expect(";")?;
let rect: db::Rect<f64> = db::Rect::new(p1, p2);
} else if tk.test("POLYGON")? {
let points = read_polygon::<f64, _>(tk)?;
} else {
break;
}
}
} else {
break;
}
}
}
loop {
if tk.test("END")? {
tk.expect(via_name.as_str())?;
break;
} else {
tk.skip_until(";")?; }
}
Ok(())
}
fn read_routing_layer<I>(tk: &mut Tokenized<I>) -> Result<RoutingLayer, LefDefParseError>
where I: Iterator<Item=char> + PeekingNext {
let mut layer = RoutingLayer::default();
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("AREA")? {
layer.min_area = Some(tk.take_and_parse()?);
tk.expect(";")?;
} else if tk.test("SPACINGTABLE")? {
layer.spacing_table = Some(read_spacing_table(tk)?);
} else if tk.test("WIREEXTENSION")? {
layer.wire_extension = Some(tk.take_and_parse()?);
tk.expect(";")?;
} else if tk.test("MAXWIDTH")? {
layer.max_width = Some(tk.take_and_parse()?);
tk.expect(";")?;
} else if tk.test("MINWIDTH")? {
layer.min_width = Some(tk.take_and_parse()?);
tk.expect(";")?;
} else if tk.test("RESISTANCE")? {
tk.expect("RPERSQ")?;
layer.resistance = Some(tk.take_and_parse()?);
tk.expect(";")?;
} else if tk.test("CAPACITANCE")? {
tk.expect("CPERSQDIST")?;
layer.capacitance = Some(tk.take_and_parse()?);
tk.expect(";")?;
} else if tk.test("HEIGHT")? {
layer.height = Some(tk.take_and_parse()?);
tk.expect(";")?;
} else {
log::debug!("Skip '{}'", tk.current_token_str().unwrap());
tk.skip_until(";")?;
}
}
Ok(layer)
}
fn read_cut_layer<I>(tk: &mut Tokenized<I>) -> Result<CutLayer, LefDefParseError>
where I: Iterator<Item=char> + PeekingNext {
let mut layer = CutLayer::default();
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")?;
} else if tk.test("ADJACENTCUTS")? {
if !tk.peeking_test("WITHIN")? {
let n: u32 = tk.take_and_parse()?; }
tk.expect("WITHIN")?;
let cut_within: f64 = tk.take_and_parse()?;
let except_same_pg_net = tk.test("EXCEPTSAMEPGNET")?;
} else if tk.test("PARALLELOVERLAP")? {
} else if tk.test("AREA")? {
let cut_area: f64 = tk.take_and_parse()?;
}
tk.skip_until(";")?;
layer.spacing.push(cut_spacing);
} else if tk.test("PROPERTY")? {
let property = tk.take()?;
tk.skip_until(";")?;
} else {
log::debug!("Skip '{}'", tk.current_token_str().unwrap());
tk.skip_until(";")?;
}
}
Ok(layer)
}
fn read_masterslice_layer<I>(tk: &mut Tokenized<I>) -> Result<MasterSliceLayer, LefDefParseError>
where I: Iterator<Item=char> + PeekingNext {
let mut layer = MasterSliceLayer::default();
loop {
if tk.test("END")? {
break;
} else if tk.test("MASK")? {
layer.mask_num = Some(tk.take_and_parse()?);
} else {
tk.skip_until(";")?;
}
}
Ok(layer)
}
fn read_spacing<I>(tk: &mut Tokenized<I>) -> Result<SpacingRules, LefDefParseError>
where I: Iterator<Item=char> + PeekingNext {
let mut spacing = SpacingRules::default();
spacing.min_spacing = tk.take_and_parse()?;
tk.skip_until(";")?;
Ok(spacing)
}
fn read_spacing_table<I>(tk: &mut Tokenized<I>) -> Result<SpacingTable, LefDefParseError>
where I: Iterator<Item=char> + PeekingNext {
let mut spacing_table = SpacingTable::default();
tk.expect("PARALLELRUNLENGTH")?;
while !tk.peeking_test("WIDTH")? & !tk.peeking_test(";")? {
let length: f64 = tk.take_and_parse()?;
spacing_table.parallel_run_lengths.push(length);
}
while tk.test("WIDTH")? {
spacing_table.widths.push(tk.take_and_parse()?);
let mut row_values = Vec::new();
while !tk.peeking_test("WIDTH")? & !tk.peeking_test(";")? {
let spacing: f64 = tk.take_and_parse()?;
row_values.push(spacing);
}
spacing_table.spacings.push(row_values)
}
tk.expect(";")?;
{
let table_width = spacing_table.parallel_run_lengths.len();
let consistent_row_sizes = spacing_table.spacings.iter()
.map(|s| s.len())
.all(|l| l == table_width);
if !consistent_row_sizes {
return Err(LefDefParseError::Other("Row sizes of SPACINGTABLE are not consistent."));
}
}
if tk.test("SPACINGTABLE")? {
unimplemented!("INFLUENCE or TWOWIDTHS tables are not implemented yet.");
}
Ok(spacing_table)
}
#[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())
}