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.

1141 lines
34 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/>.
*/
//! Data types that are used to populate the LEF data structure.
use std::fmt;
use std::str::FromStr;
use libreda_db::prelude::{Point};
use std::collections::BTreeMap;
use crate::common::*;
/* Generate LEF enums:
```python
def gen_lef_enum(name, values):
#values = [v.capitalize() for v in values]
match_statements = [f'"{v.upper()}" => Ok(Self::{v})' for v in values]
format_statements = [f'Self::{v} => f.write_str("{v.upper()}")' for v in values]
return f"""
///
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum {name} {{
{", ".join(values)}
}}
impl FromStr for {name} {{
type Err = ();
fn from_str(input: &str) -> Result<Self, Self::Err> {{
match input {{
{", ".join(match_statements)},
_ => Err(()),
}}
}}
}}
impl fmt::Display for {name} {{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {{
match self {{
{", ".join(format_statements)}
}}
}}
}}
"""
print(gen_lef_enum("ClearanceMeasure", ["MAXXY", "EUCLIDEAN"]))
print(gen_lef_enum("RoutingDirection", ["Vertical", "Horizontal"]))
print(gen_lef_enum("SignalUse", ["SIGNAL", "ANALOG", "POWER", "GROUND", "CLOCK"]))
print(gen_lef_enum("DEFSignalUse", ["SIGNAL", "POWER", "GROUND", "CLOCK", "TIEOFF", "ANALOG", "SCAN", "RESET"]))
print(gen_lef_enum("PortClass", ["NONE", "CORE", "BUMP"]))
print(gen_lef_enum("PinShape", ["ABUTMENT", "RING", "FEEDTHRU"]))
print(gen_lef_enum("PinDirection", ["INPUT", "OUTPUT", "INOUT", "FEEDTHRU"]))
print(gen_lef_enum("Orient", ["N", "S", "E", "W", "FN", "FS", "FE", "FW"]))
print(gen_lef_enum("PropertyType", ["Integer", "Real", "String"]))
print(gen_lef_enum("PropertyObjectType", ["Component", "ComponentPin", "Design", "Group", "Net", "NonDefaultRule", "Region", "Row", "SpecialNet"]))
print(gen_lef_enum("MacroClass", ["COVER", "RING", "BLOCK", "PAD", "CORE", "ENDCAP"]))
print(gen_lef_enum("MacroClassBlockType", ["BLACKBOX", "SOFT"]))
print(gen_lef_enum("MacroClassPadType", ["INPUT", "OUTPUT", "INOUT", "POWER", "SPACER", "AREAIO"]))
print(gen_lef_enum("MacroClassCoreType", ["FEEDTHRU", "TIEHIGH", "TIELOW", "SPACER", "ANTENNACELL", "WELLTAP"]))
print(gen_lef_enum("MacroClassEndcapType", ["PRE", "POST", "TOPLEFT", "TOPRIGHT", "BOTTOMLEFT", "BOTTOMRIGHT"]))
# Common
print(gen_lef_enum("Symmetry", ["X", "Y", "R90"]))
# DEF
print(gen_lef_enum("ComponentSource", ["Netlist", "Dist", "User", "Timing"]))
print(gen_lef_enum("RegionType", ["Fence", "Guide"]))
```
*/
/// Top-level structure of a LEF library.
#[derive(Clone, Debug)]
pub struct LEF {
/// LEF version.
pub version: Option<String>,
/// Characters used to indicate bus bits. Default is `[` and `]`.
pub busbitchars: (char, char),
/// Character used as path separator. Default is `/`.
pub dividerchar: char,
/// Definitions of fixed VIAs by name.
pub vias: BTreeMap<String, ()>,
/// All SITE definitions by name.
pub sites: BTreeMap<String, SiteDefinition>,
/// Technology information of the design.
pub technology: TechnologyLef,
/// Cell and macro information.
pub library: LibraryLef,
/// Extensions as defined by BEGINEXT blocks.
pub extensions: BTreeMap<String, ()>,
}
impl Default for LEF {
fn default() -> Self {
LEF {
version: None,
busbitchars: ('[', ']'),
dividerchar: '/',
vias: Default::default(),
sites: Default::default(),
technology: Default::default(),
library: Default::default(),
extensions: Default::default(),
}
}
}
/// Library LEF containing macro and standard cell information.
#[derive(Clone, Debug, Default)]
pub struct LibraryLef {
/// All MACRO definitions of the library.
pub macros: BTreeMap<String, Macro>,
}
/// Technology LEF containing technology information.
#[derive(Clone, Debug, Default)]
pub struct TechnologyLef {
/// Units used in this library.
pub units: Units,
/// Grid for geometrical alignment. Cells and shapes snap to locations on this grid.
pub manufacturing_grid: Option<f64>,
///
pub use_min_spacing: Option<()>,
/// Type of distance measure (Euclidean: `dx^2 + dy^2`, MaxXY: `max(dx, dy)`)
pub clearance_measure: ClearanceMeasure,
/// Definitions of custom properties.
pub property_definitions: BTreeMap<String, ()>,
/// Disable shifting of masks.
/// When set, shifting of macro pin mask assignments to other masks is not allowed.
/// Used for technologies that use multi-mask patterning.
pub fixed_mask: bool,
/// Layer definitions (masterslice, cut, routing, ...).
/// Layers are defined in their process order from bottom to top.
pub layers: Vec<Layer>,
/// Maximum number of single-cut vias stacked on top of each other.
/// Optionally defines a range of (bottom layer, top layer) where the rule applies. Otherwise
/// the rule applies to all layers.
pub max_via_stack: Option<(u64, Option<(String, String)>)>,
// /// Fixed vias by name.
// pub vias: BTreeMap<String, ()>,
/// VIA GENERATE rules by name.
pub via_rules_generate: BTreeMap<String, ()>,
/// NONDEFAULTRULEs by name.
pub non_default_rule: (),
// /// All SITE definitions by name.
// pub sites: BTreeMap<String, ()>,
}
/// Units used in the library.
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
pub struct Units {
/// Time in nano seconds.
pub time_ns: u64,
/// Capacitance in pico farads.
pub capacitance_pf: u64,
/// Resistance in ohms.
pub resistance_ohms: u64,
/// Power in milli watts.
pub power_mw: u64,
/// Current in milli amperes.
pub current_ma: u64,
/// Voltage in volts.
pub voltage_v: u64,
/// Length in micro meters.
pub database_microns: u64,
/// Frequency in mega hertz.
pub frequency_mega_hz: u64,
}
/// Macro SITE declaration.
#[derive(Clone, Debug, Default, PartialEq)]
pub struct Site {
/// Name of the site.
pub name: String,
/// Origin of the site within the macro. Unit is microns.
pub origin: (f64, f64),
/// Orientation of the site.
pub site_orient: Orient,
/// Optional repetition pattern.
pub step_pattern: Option<StepPattern>
}
/// SITE definition.
#[derive(Clone, Debug, PartialEq)]
pub struct SiteDefinition {
/// Name of the site.
pub name: String,
/// Dimensions of the site.
pub size: (f64, f64),
/// Define orientations of the site that are considered equivalent.
/// This is used for example to specify whether cell flipping inside
/// a row is allowed.
pub symmetry: Symmetry,
/// Specify site type (IO or CORE).
pub class: SiteClass,
/// Construct this site as a composition of previously defined sites.
/// List of tuples: (previous site, orientation)
pub row_pattern: Vec<(String, Orient)>,
}
/// Array-like repetition of an element.
///
/// Use `each_offset()` to iterate through all offsets described by this pattern.
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct StepPattern {
/// Number of repetitions in x-direction.
pub num_x: u64,
/// Number of repetitions in y-direction.
pub num_y: u64,
/// Spacing in x-direction.
pub space_x: f64,
/// Spacing in y-direction.
pub space_y: f64,
}
impl StepPattern {
/// Return an iterator over each offset of the step pattern.
/// The origin is at (0.0, 0.0).
pub fn each_offset(&self) -> impl Iterator<Item=(f64, f64)> + '_ {
(0..self.num_x).flat_map(move |x|
(0..self.num_y).map(move |y| (x, y))
)
.map(move |(x, y)| (x as f64*self.space_x, y as f64*self.space_y))
}
}
impl Default for StepPattern {
fn default() -> Self {
StepPattern {
num_x: 1,
num_y: 1,
space_x: 0.0,
space_y: 0.0,
}
}
}
/// Holds either the value of the SPACING argument or DESIGNRULEWIDTH argument of a geometrical
/// layer as used in the LAYER definition in PIN or OBS.
#[derive(Clone, Debug)]
pub enum SpacingOrDesignRuleWidth {
/// Minimal allowed spacing between this shape and other shapes.
MinSpacing(f64),
/// Effective design rule width.
DesignRuleWidth(f64),
}
/// Either a path, rectangle or polygon.
#[derive(Clone, Debug)]
pub enum Shape {
/// Width and path.
Path(f64, Vec<Point<f64>>),
/// Corner points of a rectangle.
Rect(Point<f64>, Point<f64>),
/// Vertices of a polygon.
Polygon(Vec<Point<f64>>),
}
/// Shape with an optional array step pattern.
#[derive(Clone, Debug)]
pub struct Geometry {
/// Array-like repetition of the shape.
pub step_pattern: Option<StepPattern>,
/// Geometric primitive.
pub shape: Shape,
}
/// MACRO definition.
#[derive(Clone, Debug, Default)]
pub struct Macro {
/// Name of the macro.
pub name: String,
/// Class of the macro.
pub class: Option<MacroClass>,
/// Disable shifting of masks.
/// When set, shifting of macro pin mask assignments to other masks is not allowed.
/// Used for technologies that use multi-mask patterning.
pub fixed_mask: bool,
/// Name of the corresponding cell layout in the GDS/OASIS file.
/// Associated with an offset and orientation.
pub foreign: Vec<(String, Point<f64>, Orient)>,
/// Coordinate of the origin of the macro. Often (0, 0).
/// A placement of a cell in DEF is given by the location of the origin.
pub origin: Point<f64>,
/// Name of electrically equivalent macro.
pub eeq: Option<String>,
/// Width and height of the macro.
pub size: Option<(f64, f64)>,
/// Symmetry of the macro. Tells how the macro can be mirrored and rotated.
pub symmetry: Symmetry,
/// SITES associated with the macro. Normal macros have only one associated site.
pub sites: Vec<Site>,
/// Definitions of the electrical pins of the macro.
pub pins: Vec<MacroPin>,
/// Obstructions (blockages).
pub obs: Vec<LayerGeometries>,
/// Density specifications.
pub density: Vec<()>,
/// Additional properties of the macro.
pub properties: BTreeMap<String, ()>,
}
/// PIN definition of a MACRO.
#[derive(Clone, Debug, Default)]
pub struct MacroPin {
/// Name of the pin.
pub name: String,
/// Name of the NONDEFAULTRULE to be used when tapering wires to this pin.
pub taper_rule: Option<String>,
/// Signal direction.
pub direction: Option<PinDirection>,
/// Type of the signal for this pin.
pub signal_use: Option<SignalUse>,
/// Net name where this pin should be connected if it is tied HIGH (constant logical 1).
pub supply_sensitivity: Option<String>,
/// Net name where this pin should be connected if it is tied LOW (constant logical 0).
pub ground_sensitivity: Option<String>,
/// Specify special connection requirements of the pin.
pub shape_type: Option<PinShape>,
/// Name of another pin that must be connected to this pin.
pub must_join: Option<String>,
///
pub ports: Vec<MacroPinPort>,
}
/// PORT definition of a MACRO PIN.
/// A port describes where a pin is geometrically located.
/// A pin can have multiple ports. They are electrically equivalent.
#[derive(Clone, Debug, Default)]
pub struct MacroPinPort {
/// Type of the port.
pub class: Option<PortClass>,
/// Geometrical shapes and vias that make this port.
pub geometries: Vec<LayerGeometries>,
}
/// Geometrical shapes on a named layer as used in MACRO PIN and OBS definitions.
#[derive(Clone, Debug, Default)]
pub struct LayerGeometries {
/// Name of the layer.
pub layer_name: String,
/// Obstruction blocks signal routing but not power or ground routing.
pub except_pg_net: bool,
/// Either minimal allowed spacing or an effective width.
pub spacing_or_designrule_width: Option<SpacingOrDesignRuleWidth>,
/// Specify the width to be used for PATH. If not specified the default with for this layer is used.
pub width: Option<f64>,
/// Geometrical shapes (PATH, RECT, POLYGON). Together with a repetition pattern.
pub geometries: Vec<Geometry>,
/// Specify vias to be placed with their locations.
pub vias: Vec<()>,
}
/// Type of distance measurement
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum ClearanceMeasure {
/// Take maximum of x or y distance.
Maxxy,
/// `sqrt(x^2 + y^2)`
Euclidean,
}
impl Default for ClearanceMeasure {
fn default() -> Self {
Self::Euclidean
}
}
impl FromStr for ClearanceMeasure {
type Err = ();
fn from_str(input: &str) -> Result<Self, Self::Err> {
match input {
"MAXXY" => Ok(Self::Maxxy),
"EUCLIDEAN" => Ok(Self::Euclidean),
_ => Err(()),
}
}
}
impl fmt::Display for ClearanceMeasure {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Maxxy => f.write_str("MAXXY"),
Self::Euclidean => f.write_str("EUCLIDEAN")
}
}
}
/// Preferred routing direction on a routing layer.
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum RoutingDirection {
/// Vertical routing direction.
Vertical,
/// Horizontal routing direction.
Horizontal,
/// 45 degree routing direction.
Diag45,
/// 135 degree routing direction.
Diag135,
}
impl FromStr for RoutingDirection {
type Err = ();
fn from_str(input: &str) -> Result<Self, Self::Err> {
match input {
"VERTICAL" => Ok(Self::Vertical),
"HORIZONTAL" => Ok(Self::Horizontal),
"DIAG45" => Ok(Self::Diag45),
"DIAG135" => Ok(Self::Diag135),
_ => Err(()),
}
}
}
impl fmt::Display for RoutingDirection {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Vertical => f.write_str("VERTICAL"),
Self::Horizontal => f.write_str("HORIZONTAL"),
Self::Diag45 => f.write_str("DIAG45"),
Self::Diag135 => f.write_str("DIAG135"),
}
}
}
///
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum SignalUse {
/// Data signal.
Signal,
/// Analog signal.
Analog,
/// Power supply.
Power,
/// Ground.
Ground,
/// Clock signal.
Clock,
}
impl FromStr for SignalUse {
type Err = ();
fn from_str(input: &str) -> Result<Self, Self::Err> {
match input {
"SIGNAL" => Ok(Self::Signal),
"ANALOG" => Ok(Self::Analog),
"POWER" => Ok(Self::Power),
"GROUND" => Ok(Self::Ground),
"CLOCK" => Ok(Self::Clock),
_ => Err(()),
}
}
}
impl fmt::Display for SignalUse {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Signal => f.write_str("SIGNAL"),
Self::Analog => f.write_str("ANALOG"),
Self::Power => f.write_str("POWER"),
Self::Ground => f.write_str("GROUND"),
Self::Clock => f.write_str("CLOCK")
}
}
}
/// TODO: Document.
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum PortClass {
///
None,
///
Core,
///
Bump,
}
impl FromStr for PortClass {
type Err = ();
fn from_str(input: &str) -> Result<Self, Self::Err> {
match input {
"NONE" => Ok(Self::None),
"CORE" => Ok(Self::Core),
"BUMP" => Ok(Self::Bump),
_ => Err(()),
}
}
}
impl fmt::Display for PortClass {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::None => f.write_str("NONE"),
Self::Core => f.write_str("CORE"),
Self::Bump => f.write_str("BUMP")
}
}
}
/// Type of the pin shape.
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum PinShape {
///
Abutment,
///
Ring,
///
Feedthru,
}
impl FromStr for PinShape {
type Err = ();
fn from_str(input: &str) -> Result<Self, Self::Err> {
match input {
"ABUTMENT" => Ok(Self::Abutment),
"RING" => Ok(Self::Ring),
"FEEDTHRU" => Ok(Self::Feedthru),
_ => Err(()),
}
}
}
impl fmt::Display for PinShape {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Abutment => f.write_str("ABUTMENT"),
Self::Ring => f.write_str("RING"),
Self::Feedthru => f.write_str("FEEDTHRU")
}
}
}
/// Spacing rules for a routing layer.
#[derive(Clone, Debug, Default)]
pub struct SpacingRules {}
/// SPACINGTABLE
#[derive(Clone, Debug, Default)]
pub struct SpacingTable {}
/// Layer definition.
/// A layer can have different types:
///
/// * MasterSlice: This is usually the first layer in the stack.
/// * Cut: Via layer that connects the previous and next layer.
/// * Routing: Metal wires.
#[derive(Clone, Debug)]
pub enum Layer {
/// MASTERSLICE (poly) layer.
MasterSlice(MasterSliceLayer),
// /// Implant layer.
// Implant(()),
/// CUT layer.
Cut(CutLayer),
/// ROUTING layer.
Routing(RoutingLayer),
}
impl Layer {
/// Get the name of the layer.
pub fn name(&self) -> &String {
match self {
Layer::MasterSlice(l) => &l.name,
Layer::Cut(l) => &l.name,
Layer::Routing(l) => &l.name,
}
}
}
/// Design rules for a MASTERSLICE or OVERLAP layer.
/// Master slice layers are usually polysilicon layers and are typically used when a MACRO has
/// pins on the poly layer.
#[derive(Clone, Debug, Default)]
pub struct MasterSliceLayer {
/// Name of the masterslice layer.
pub name: String,
/// Number of masks used for double- or triple-patterning.
pub mask_num: Option<u32>,
/// Custom properties.
pub properties: BTreeMap<String, PropertyValue>,
// TODO: PROPERTY_LEF58_TYPE, PROPERTY_LEF58_TRIMMEDMETAL
}
/// Design rules for a CUT (via) layer.
#[derive(Clone, Debug, Default)]
pub struct CutLayer {
/// Name of the cut layer.
pub name: String,
/// Number of masks used for double- or triple-patterning.
pub mask_num: Option<u32>,
/// Minimum spacing rules between cuts of same or different nets.
pub spacing: Vec<CutSpacingRule>,
/// Spacing table to be used on this cut layer.
pub spacing_table: Option<()>,
/// TODO
pub array_spacing: Option<()>,
/// Minimum width of a cut in microns.
/// Usually this is the only allowed size of a cut.
pub width: Option<f64>,
/// Enclosure rules that must be met.
pub enclosure: Vec<EnclosureRule>,
/// Preferred enclosure rules that can be used to improve yield but must not necessarily
/// be met.
pub prefer_enclosure: Vec<EnclosureRule>,
/// Resistance per cut.
pub resistance: Option<f64>,
/// Custom properties.
pub properties: BTreeMap<String, PropertyValue>,
// TODO: Antenna rule definitions.
}
/// ENCLOSURE rules for a CUT (via) layer.
#[derive(Clone, Debug)]
pub struct EnclosureRule {
/// Rule applies for the routing layer above.
pub above: bool,
/// Rule applies for the routing layer below.
pub below: bool,
/// Adjacent routing layers must overhang on the two opposing sides (in x-direction (?)).
pub overhang1: f64,
/// Adjacent routing layers must overhang on the two opposing sides (in y-direction (?)).
pub overhang2: f64,
/// Rule only applies if the width of the adjacent shape of the routing layer is greater or equal
/// than `min_width`.
/// Default is 0.
pub min_width: f64,
/// TODO
/// Don't use the WIDTH rule when another via is present to the current via within this distance.
pub except_extracut_within: f64,
/// Rule only applies if the total length of the longest overhangs is greater or equal
/// to `min_length`.
/// The overhang length is measured from the via cut center.
/// Default is 0.
pub min_length: f64,
}
impl Default for EnclosureRule {
fn default() -> Self {
Self {
above: true,
below: true,
overhang1: 0.0,
overhang2: 0.0,
min_width: 0.0,
except_extracut_within: 0.0,
min_length: 0.0,
}
}
}
/// SPACING rules for a CUT (via) layer.
#[derive(Clone, Debug)]
pub struct CutSpacingRule {
/// Spacing between cuts.
pub spacing: f64,
/// Measure the spacing from center of the cut to the center of another cut
/// instead of from edge to edge.
/// This is enabled by default.
pub center_to_center: bool,
/// Tell if this spacing rule applies for same-net cuts.
pub same_net: bool,
}
impl Default for CutSpacingRule {
fn default() -> Self {
Self {
spacing: 0.0,
center_to_center: true,
same_net: false,
}
}
}
/// Design rules for a routing layer.
#[derive(Clone, Debug)]
pub struct RoutingLayer {
/// Name of the routing layer.
pub name: String,
/// Number of masks used for double- or triple-patterning.
pub mask_num: Option<u32>,
/// Preferred routing direction.
pub direction: RoutingDirection,
/// Routing pitch in x and y direction in microns.
pub pitch: (f64, f64),
/// Routing pitch for diagonal directions in microns.
pub diag_pitch: Option<(f64, f64)>,
/// Default wire width in microns.
pub width: f64,
///
pub offset: Option<(f64, f64)>,
/// Default width for diagonal wires in microns.
pub diag_width: Option<f64>,
/// Default spacing for diagonal wires in microns.
pub diag_spacing: Option<f64>,
/// Minimum edge length for diagonal wires in microns.
pub diag_min_edge_length: Option<f64>,
/// Minimum area for shapes on this layer.
pub min_area: f64,
/// Minimal rectangles that must fit in each shape on this layer.
/// At least one needs to fit for each shape.
/// Tuples of `(minimal width, minimnal length)`.
pub min_size: Vec<(f64, f64)>,
/// Minimal edge length for shapes.
pub min_step: (),
/// Spacing rules.
pub spacing: Vec<SpacingRules>,
/// Spacing tables for spacing between wires.
pub spacing_table: SpacingTable,
/// Length of extension of a wire over a via. The extension must be at least half of the
/// wire width.
pub wire_extension: Option<f64>,
/// Minimal number of cuts of a via depending on the width of the wire.
pub minimum_cut: (),
/// Maximum wire width in microns.
pub max_width: Option<f64>,
/// Minimum wire width in microns.
pub min_width: Option<f64>,
/// Minimum area of holes in metal shapes.
/// `(min area [um^2], width [um])` tuples.
/// If a width is specified the rule only applies if at least one of the wires around the hole
/// has a larger width.
pub min_enclosed_area: Vec<(f64, Option<f64>)>,
/// Width of a protrusion.
pub protrusion_width: (),
/// Sheet resistance `[Ohm/square]`.
pub resistance: Option<f64>,
/// Specify wire-to-ground capacitance per square unit in `[pF/um^2]`.
pub capacitance: Option<f64>,
/// Distance from top of ground plane to bottom of this interconnect layer.
pub height: Option<f64>,
/// Thickness of the layer in microns.
pub thickness: Option<f64>,
/// Amount of loss in width of wires caused by the etching process.
pub shrinkage: Option<f64>,
/// Account for increase in capacitance caused by close wires.
/// Default is 1.
pub cap_multiplier: u32,
/// `[pF/um]`.
pub edge_capacitance: Option<f64>,
/// Maximum allowed metal density in percent.
pub minimum_density: Option<f64>,
/// Minimum allowed metal density in percent.
pub maximum_density: Option<f64>,
/// Length and width of the density check window.
pub density_check_window: Option<(f64, f64)>,
/// Stepping distance for metal density checks.
pub density_check_step: Option<f64>,
/// Spacing between metal fills and active geometries.
pub fill_active_spacing: Option<f64>,
/// Antenna rule definitions.
pub antenna_rules: AntennaRules,
/// AC current density information.
pub ac_current_density: Option<()>,
/// Average DC current density information.
/// Stored as a `(wire width, current density)` table.
/// If only a default value is specified for all widths
/// it is stored as a single entry for wire width `0`: `(0, default_current_density)`.
/// Unit: `[mA/um]`
pub dc_current_density: Vec<(f64, f64)>,
/// Custom properties.
pub properties: BTreeMap<String, PropertyValue>,
}
impl Default for RoutingLayer {
/// Custom implementation of the `Default` trait for `RoutingLayer.
fn default() -> Self {
Self {
name: Default::default(),
mask_num: None,
direction: RoutingDirection::Vertical,
pitch: (0.0, 0.0),
diag_pitch: None,
width: 0.0,
offset: None,
diag_width: None,
diag_spacing: None,
diag_min_edge_length: None,
min_area: 0.0,
min_size: vec![],
min_step: (),
spacing: vec![],
spacing_table: Default::default(),
wire_extension: None,
minimum_cut: (),
max_width: None,
min_width: None,
min_enclosed_area: vec![],
protrusion_width: (),
resistance: None,
capacitance: None,
height: None,
thickness: None,
shrinkage: None,
// Take multiplicative identity as default for the capacitance multiplier.
cap_multiplier: 1,
edge_capacitance: None,
minimum_density: None,
maximum_density: None,
density_check_window: None,
density_check_step: None,
fill_active_spacing: None,
antenna_rules: AntennaRules::default(),
ac_current_density: None,
dc_current_density: vec![],
properties: Default::default(),
}
}
}
///
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum MacroClass {
/// Macro with fixed position.
/// Commonly used for power routing. COVER does not contain active devices.
/// A COVER class can have the sub-class BUMP. Typically BUMP cells have
/// geometries only on the topmost 'bump' layer.
COVER(bool),
/// Big macro with internal power mesh.
RING,
/// Predefined macro.
BLOCK(Option<MacroClassBlockType>),
/// I/O pad.
PAD(Option<MacroClassPadType>),
/// Standard-cell macro used inside the core area.
CORE(Option<MacroClassCoreType>),
/// Start or end of core rows. Typically used to connect to the power grid.
ENDCAP(Option<MacroClassEndcapType>),
}
impl FromStr for MacroClass {
type Err = ();
fn from_str(input: &str) -> Result<Self, Self::Err> {
match input {
"COVER" => Ok(Self::COVER(false)),
"RING" => Ok(Self::RING),
"BLOCK" => Ok(Self::BLOCK(Default::default())),
"PAD" => Ok(Self::PAD(Default::default())),
"CORE" => Ok(Self::CORE(Default::default())),
"ENDCAP" => Ok(Self::ENDCAP(Default::default())),
_ => Err(()),
}
}
}
impl fmt::Display for MacroClass {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::COVER(bump) => {
f.write_str("COVER")?;
if *bump {
f.write_str("BUMP")?;
}
}
Self::RING => f.write_str("RING")?,
Self::BLOCK(sub_class) => {
f.write_str("BLOCK")?;
if let Some(sub_class) = sub_class {
sub_class.fmt(f)?;
}
}
Self::PAD(sub_class) => {
f.write_str("PAD")?;
if let Some(sub_class) = sub_class {
sub_class.fmt(f)?;
}
}
Self::CORE(sub_class) => {
f.write_str("CORE")?;
if let Some(sub_class) = sub_class {
sub_class.fmt(f)?;
}
}
Self::ENDCAP(sub_class) => {
f.write_str("ENDCAP")?;
if let Some(sub_class) = sub_class {
sub_class.fmt(f)?;
}
}
}
Ok(())
}
}
/// Specify the type of a site: Either IO site (PAD) or core site (CORE).
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum SiteClass {
/// A core site.
CORE,
/// An IO site.
PAD
}
impl FromStr for SiteClass {
type Err = ();
fn from_str(input: &str) -> Result<Self, Self::Err> {
match input {
"CORE" => Ok(Self::CORE),
"PAD" => Ok(Self::PAD),
_ => Err(()),
}
}
}
impl fmt::Display for SiteClass {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::CORE => f.write_str("CORE")?,
Self::PAD => f.write_str("PAD")?,
};
Ok(())
}
}
/// Subclass of the BLOCK macro class.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum MacroClassBlockType {
///
BLACKBOX,
///
SOFT,
}
impl FromStr for MacroClassBlockType {
type Err = ();
fn from_str(input: &str) -> Result<Self, Self::Err> {
match input {
"BLACKBOX" => Ok(Self::BLACKBOX),
"SOFT" => Ok(Self::SOFT),
_ => Err(()),
}
}
}
impl fmt::Display for MacroClassBlockType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::BLACKBOX => f.write_str("BLACKBOX"),
Self::SOFT => f.write_str("SOFT")
}
}
}
/// Subclass of the PAD macro class.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum MacroClassPadType {
/// Input pad.
INPUT,
/// Output pad.
OUTPUT,
/// Inout pad.
INOUT,
/// Power pad.
POWER,
/// Spacer in the pad ring.
SPACER,
/// Area for I/O drivers with out connection to a bump. They need routing to a
/// CLASS COVER BUMP macro for proper connection with the IC package.
AREAIO,
}
impl FromStr for MacroClassPadType {
type Err = ();
fn from_str(input: &str) -> Result<Self, Self::Err> {
match input {
"INPUT" => Ok(Self::INPUT),
"OUTPUT" => Ok(Self::OUTPUT),
"INOUT" => Ok(Self::INOUT),
"POWER" => Ok(Self::POWER),
"SPACER" => Ok(Self::SPACER),
"AREAIO" => Ok(Self::AREAIO),
_ => Err(()),
}
}
}
impl fmt::Display for MacroClassPadType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::INPUT => f.write_str("INPUT"),
Self::OUTPUT => f.write_str("OUTPUT"),
Self::INOUT => f.write_str("INOUT"),
Self::POWER => f.write_str("POWER"),
Self::SPACER => f.write_str("SPACER"),
Self::AREAIO => f.write_str("AREAIO")
}
}
}
/// Subclass of the CORE macro class.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum MacroClassCoreType {
/// Connect to another cell.
FEEDTHRU,
/// Logical one.
TIEHIGH,
/// Logical zero.
TIELOW,
/// Spacer/fill cell.
SPACER,
/// Antenna diode.
ANTENNACELL,
/// Well-tap cell.
WELLTAP,
}
impl FromStr for MacroClassCoreType {
type Err = ();
fn from_str(input: &str) -> Result<Self, Self::Err> {
match input {
"FEEDTHRU" => Ok(Self::FEEDTHRU),
"TIEHIGH" => Ok(Self::TIEHIGH),
"TIELOW" => Ok(Self::TIELOW),
"SPACER" => Ok(Self::SPACER),
"ANTENNACELL" => Ok(Self::ANTENNACELL),
"WELLTAP" => Ok(Self::WELLTAP),
_ => Err(()),
}
}
}
impl fmt::Display for MacroClassCoreType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::FEEDTHRU => f.write_str("FEEDTHRU"),
Self::TIEHIGH => f.write_str("TIEHIGH"),
Self::TIELOW => f.write_str("TIELOW"),
Self::SPACER => f.write_str("SPACER"),
Self::ANTENNACELL => f.write_str("ANTENNACELL"),
Self::WELLTAP => f.write_str("WELLTAP")
}
}
}
/// Subclass of the ENDCAP macro class.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum MacroClassEndcapType {
/// Start of the row (left).
PRE,
/// End of the row (right)
POST,
/// I/O corner cell on top left.
TOPLEFT,
/// I/O corner cell on top right.
TOPRIGHT,
/// I/O corner cell on bottom left.
BOTTOMLEFT,
/// I/O corner cell on bottom right.
BOTTOMRIGHT,
}
impl FromStr for MacroClassEndcapType {
type Err = ();
fn from_str(input: &str) -> Result<Self, Self::Err> {
match input {
"PRE" => Ok(Self::PRE),
"POST" => Ok(Self::POST),
"TOPLEFT" => Ok(Self::TOPLEFT),
"TOPRIGHT" => Ok(Self::TOPRIGHT),
"BOTTOMLEFT" => Ok(Self::BOTTOMLEFT),
"BOTTOMRIGHT" => Ok(Self::BOTTOMRIGHT),
_ => Err(()),
}
}
}
impl fmt::Display for MacroClassEndcapType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::PRE => f.write_str("PRE"),
Self::POST => f.write_str("POST"),
Self::TOPLEFT => f.write_str("TOPLEFT"),
Self::TOPRIGHT => f.write_str("TOPRIGHT"),
Self::BOTTOMLEFT => f.write_str("BOTTOMLEFT"),
Self::BOTTOMRIGHT => f.write_str("BOTTOMRIGHT")
}
}
}