use crate::common::*;
use libreda_db::prelude::Point;
use std::collections::BTreeMap;
use std::fmt;
use std::str::FromStr;
#[derive(Clone, Debug)]
pub struct LEF {
pub version: Option<String>,
pub busbitchars: (char, char),
pub dividerchar: char,
pub vias: BTreeMap<String, ViaDefinition>,
pub sites: BTreeMap<String, SiteDefinition>,
pub technology: TechnologyLef,
pub library: LibraryLef,
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(),
}
}
}
#[derive(Clone, Debug, Default)]
pub struct LibraryLef {
pub macros: BTreeMap<String, Macro>,
}
#[derive(Clone, Debug, Default)]
pub struct TechnologyLef {
pub units: Units,
pub manufacturing_grid: Option<f64>,
pub use_min_spacing: Option<()>,
pub clearance_measure: ClearanceMeasure,
pub property_definitions: BTreeMap<String, ()>,
pub fixed_mask: bool,
pub layers: Vec<Layer>,
pub max_via_stack: Option<(u64, Option<(String, String)>)>,
pub via_rules_generate: BTreeMap<String, ()>,
pub non_default_rule: (),
}
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
pub struct Units {
pub time_ns: u64,
pub capacitance_pf: u64,
pub resistance_ohms: u64,
pub power_mw: u64,
pub current_ma: u64,
pub voltage_v: u64,
pub database_microns: u64,
pub frequency_mega_hz: u64,
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct Site {
pub name: String,
pub origin: (f64, f64),
pub site_orient: Orient,
pub step_pattern: Option<StepPattern>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct SiteDefinition {
pub name: String,
pub size: (f64, f64),
pub symmetry: Symmetry,
pub class: SiteClass,
pub row_pattern: Vec<(String, Orient)>,
}
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct StepPattern {
pub num_x: u64,
pub num_y: u64,
pub space_x: f64,
pub space_y: f64,
}
impl StepPattern {
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,
}
}
}
#[derive(Clone, Debug)]
pub enum SpacingOrDesignRuleWidth {
MinSpacing(f64),
DesignRuleWidth(f64),
}
#[derive(Clone, Debug)]
pub enum Shape {
Path(f64, Vec<Point<f64>>),
Rect(Point<f64>, Point<f64>),
Polygon(Vec<Point<f64>>),
}
#[derive(Clone, Debug)]
pub struct Geometry {
pub step_pattern: Option<StepPattern>,
pub shape: Shape,
}
#[derive(Clone, Debug)]
pub enum ViaDefinition {
GeneratedVia(GeneratedVia),
FixedVia(FixedVia),
}
#[derive(Clone, Debug, Default)]
pub struct GeneratedVia {
pub is_default: bool,
pub rule_name: String,
pub cut_size: (f64, f64),
pub layers: (String, String, String),
pub cut_spacing: (f64, f64),
pub enclosure: (f64, f64, f64, f64),
pub num_rows_cols: Option<(u32, u32)>,
pub origin: Option<(f64, f64)>,
pub offset: Option<(f64, f64, f64, f64)>,
pub cut_pattern: Option<String>,
}
#[derive(Clone, Debug)]
pub enum RectOrPolygon {
Rect((Point<f64>, Point<f64>)),
Polygon(Vec<Point<f64>>),
}
#[derive(Clone, Debug)]
pub struct ViaShape {
pub mask_num: Option<u8>,
pub shape: RectOrPolygon,
}
#[derive(Clone, Debug, Default)]
pub struct FixedVia {
pub is_default: bool,
pub resistance: Option<f64>,
pub geometry: BTreeMap<String, Vec<ViaShape>>,
}
#[derive(Clone, Debug, Default)]
pub struct Macro {
pub name: String,
pub class: Option<MacroClass>,
pub fixed_mask: bool,
pub foreign: Vec<(String, Point<f64>, Orient)>,
pub origin: Point<f64>,
pub eeq: Option<String>,
pub size: Option<(f64, f64)>,
pub symmetry: Symmetry,
pub sites: Vec<Site>,
pub pins: Vec<MacroPin>,
pub obs: Vec<LayerGeometries>,
pub density: Vec<()>,
pub properties: BTreeMap<String, ()>,
}
#[derive(Clone, Debug, Default)]
pub struct MacroPin {
pub name: String,
pub taper_rule: Option<String>,
pub direction: Option<PinDirection>,
pub signal_use: Option<SignalUse>,
pub supply_sensitivity: Option<String>,
pub ground_sensitivity: Option<String>,
pub shape_type: Option<PinShape>,
pub must_join: Option<String>,
pub ports: Vec<MacroPinPort>,
}
#[derive(Clone, Debug, Default)]
pub struct MacroPinPort {
pub class: Option<PortClass>,
pub geometries: Vec<LayerGeometries>,
}
#[derive(Clone, Debug, Default)]
pub struct LayerGeometries {
pub layer_name: String,
pub except_pg_net: bool,
pub spacing_or_designrule_width: Option<SpacingOrDesignRuleWidth>,
pub width: Option<f64>,
pub geometries: Vec<Geometry>,
pub vias: Vec<()>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum ClearanceMeasure {
Maxxy,
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"),
}
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum RoutingDirection {
Vertical,
Horizontal,
Diag45,
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(Copy, Clone, Debug, PartialEq, Eq)]
pub enum SignalUse {
Signal,
Analog,
Power,
Ground,
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"),
}
}
}
#[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"),
}
}
}
#[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"),
}
}
}
#[allow(missing_docs)]
#[derive(Clone, Debug, Default)]
pub struct SpacingRules {
pub min_spacing: f64,
pub spacing_type: Option<SpacingType>,
}
#[allow(missing_docs)]
#[derive(Clone, Debug)]
pub enum SpacingType {
Range {
min_width: f64,
max_width: f64,
spacing_range_type: Option<SpacingRangeType>,
},
EndOfLine {
eol_width: f64,
eol_widthing: f64,
},
SameNet {
power_ground_only: bool,
},
NotchLength {
min_notch_length: bool,
},
EndOfNotchWidth {
end_of_notch_width: f64,
min_notch_spacing: f64,
min_notch_length: f64,
},
}
#[allow(missing_docs)]
#[derive(Clone, Debug)]
pub enum SpacingRangeType {
UseLengthThreshold,
Influence { influence_length: f64 },
}
#[derive(Clone, Debug, Default)]
pub struct SpacingTable {
pub parallel_run_lengths: Vec<f64>,
pub widths: Vec<f64>,
pub spacings: Vec<Vec<f64>>,
}
#[derive(Clone, Debug)]
pub enum Layer {
MasterSlice(MasterSliceLayer),
Cut(CutLayer),
Routing(RoutingLayer),
}
impl Layer {
pub fn name(&self) -> &String {
match self {
Layer::MasterSlice(l) => &l.name,
Layer::Cut(l) => &l.name,
Layer::Routing(l) => &l.name,
}
}
}
#[derive(Clone, Debug, Default)]
pub struct MasterSliceLayer {
pub name: String,
pub mask_num: Option<u32>,
pub properties: BTreeMap<String, PropertyValue>,
}
#[derive(Clone, Debug, Default)]
pub struct CutLayer {
pub name: String,
pub mask_num: Option<u32>,
pub spacing: Vec<CutSpacingRule>,
pub spacing_table: Option<()>,
pub array_spacing: Option<()>,
pub width: Option<f64>,
pub enclosure: Vec<EnclosureRule>,
pub prefer_enclosure: Vec<EnclosureRule>,
pub resistance: Option<f64>,
pub properties: BTreeMap<String, PropertyValue>,
}
#[derive(Clone, Debug)]
pub struct EnclosureRule {
pub above: bool,
pub below: bool,
pub overhang1: f64,
pub overhang2: f64,
pub min_width: f64,
pub except_extracut_within: f64,
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,
}
}
}
#[derive(Clone, Debug)]
pub struct CutSpacingRule {
pub spacing: f64,
pub center_to_center: bool,
pub same_net: bool,
}
impl Default for CutSpacingRule {
fn default() -> Self {
Self {
spacing: 0.0,
center_to_center: true,
same_net: false,
}
}
}
#[derive(Clone, Debug)]
pub struct RoutingLayer {
pub name: String,
pub mask_num: Option<u32>,
pub direction: RoutingDirection,
pub pitch: (f64, f64),
pub diag_pitch: Option<(f64, f64)>,
pub width: f64,
pub offset: Option<(f64, f64)>,
pub diag_width: Option<f64>,
pub diag_spacing: Option<f64>,
pub diag_min_edge_length: Option<f64>,
pub min_area: Option<f64>,
pub min_size: Vec<(f64, f64)>,
pub min_step: (),
pub spacing: Vec<SpacingRules>,
pub spacing_table: Option<SpacingTable>,
pub wire_extension: Option<f64>,
pub minimum_cut: (),
pub max_width: Option<f64>,
pub min_width: Option<f64>,
pub min_enclosed_area: Vec<(f64, Option<f64>)>,
pub protrusion_width: (),
pub resistance: Option<f64>,
pub capacitance: Option<f64>,
pub height: Option<f64>,
pub thickness: Option<f64>,
pub shrinkage: Option<f64>,
pub cap_multiplier: u32,
pub edge_capacitance: Option<f64>,
pub minimum_density: Option<f64>,
pub maximum_density: Option<f64>,
pub density_check_window: Option<(f64, f64)>,
pub density_check_step: Option<f64>,
pub fill_active_spacing: Option<f64>,
pub antenna_rules: AntennaRules,
pub ac_current_density: Option<()>,
pub dc_current_density: Vec<(f64, f64)>,
pub properties: BTreeMap<String, PropertyValue>,
}
impl Default for RoutingLayer {
fn default() -> Self {
Self {
name: Default::default(),
mask_num: Default::default(),
direction: RoutingDirection::Vertical,
pitch: (0.0, 0.0),
diag_pitch: Default::default(),
width: 0.0,
offset: Default::default(),
diag_width: Default::default(),
diag_spacing: Default::default(),
diag_min_edge_length: Default::default(),
min_area: Default::default(),
min_size: Default::default(),
min_step: Default::default(),
spacing: Default::default(),
spacing_table: Default::default(),
wire_extension: Default::default(),
minimum_cut: Default::default(),
max_width: Default::default(),
min_width: Default::default(),
min_enclosed_area: Default::default(),
protrusion_width: Default::default(),
resistance: Default::default(),
capacitance: Default::default(),
height: Default::default(),
thickness: Default::default(),
shrinkage: Default::default(),
cap_multiplier: 1,
edge_capacitance: Default::default(),
minimum_density: Default::default(),
maximum_density: Default::default(),
density_check_window: Default::default(),
density_check_step: Default::default(),
fill_active_spacing: Default::default(),
antenna_rules: AntennaRules::default(),
ac_current_density: Default::default(),
dc_current_density: Default::default(),
properties: Default::default(),
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum MacroClass {
COVER(bool),
RING,
BLOCK(Option<MacroClassBlockType>),
PAD(Option<MacroClassPadType>),
CORE(Option<MacroClassCoreType>),
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(())
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum SiteClass {
CORE,
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(())
}
}
#[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"),
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum MacroClassPadType {
INPUT,
OUTPUT,
INOUT,
POWER,
SPACER,
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"),
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum MacroClassCoreType {
FEEDTHRU,
TIEHIGH,
TIELOW,
SPACER,
ANTENNACELL,
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"),
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum MacroClassEndcapType {
PRE,
POST,
TOPLEFT,
TOPRIGHT,
BOTTOMLEFT,
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"),
}
}
}