move core traits to libreda-core crate

This commit is contained in:
Thomas Kramer
2024-09-10 08:15:07 +02:00
parent 7e51a19428
commit b76b550c6e
33 changed files with 39 additions and 1946 deletions

View File

@@ -22,6 +22,7 @@ num-traits = "0.2"
num-derive = "0.4"
portrait = "0.3.0" # For delegating trait implementations.
petgraph = "0.6"
libreda-core = { version = "0.0.1", path = "../libreda-core", features = ["serde"] }
iron-shapes = { version = "0.1.1", path = "../iron-shapes", features = ["serde"] }
iron-shapes-booleanop = { version = "0.1", path = '../iron-shapes-booleanop' }
serde = { version = "1", optional = true, features = ["derive", "rc"] }

View File

@@ -1,65 +0,0 @@
// SPDX-FileCopyrightText: 2023 Thomas Kramer
//
// SPDX-License-Identifier: AGPL-3.0-or-later
//! Blanket implementations of hierarchy traits for reference types, `Rc`, `Arc` and `Box`.
use super::traits::*;
use std::rc::Rc;
use std::sync::Arc;
macro_rules! blanket {
($type:ty, $trait:ident) => {
#[portrait::fill(portrait::delegate(T; *self))]
impl<T> $trait for $type where T: $trait {}
};
}
macro_rules! blanket_ids {
($type:ty, $trait:ident) => {
#[portrait::fill(portrait::delegate(T))]
impl<T> $trait for $type where T: $trait {}
};
}
macro_rules! blanket_id_impls {
($trait:ident) => {
blanket_ids!(&T, $trait);
blanket_ids!(&mut T, $trait);
blanket_ids!(Rc<T>, $trait);
blanket_ids!(Arc<T>, $trait);
blanket_ids!(Box<T>, $trait);
};
}
macro_rules! blanket_impls {
($trait:ident) => {
blanket!(&T, $trait);
blanket!(&mut T, $trait);
blanket!(Rc<T>, $trait);
blanket!(Arc<T>, $trait);
blanket!(Box<T>, $trait);
};
}
macro_rules! blanket_impls_mut {
($trait:ident) => {
blanket!(&mut T, $trait);
blanket!(Box<T>, $trait);
};
}
blanket_id_impls!(HierarchyIds);
blanket_impls!(HierarchyBase);
blanket_impls_mut!(HierarchyEdit);
blanket_id_impls!(NetlistIds);
blanket_impls!(NetlistBase);
blanket_impls_mut!(NetlistEdit);
blanket_id_impls!(LayoutIds);
blanket_impls!(LayoutBase);
blanket_impls_mut!(LayoutEdit);
blanket_impls!(L2NBase);
blanket_impls_mut!(L2NEdit);

View File

@@ -26,12 +26,11 @@ use std::borrow::{Borrow, BorrowMut};
use std::collections::HashMap;
use std::hash::Hash;
use crate::netlist::direction::Direction;
// use crate::rc_string::RcString;
use std::fmt::Debug;
use crate::layout::types::LayerInfo;
use crate::property_storage::{PropertyStore, PropertyValue};
use crate::property_storage::PropertyStore;
use libreda_core::prelude::{Direction, LayerInfo, PropertyValue};
// Use an alternative hasher that has better performance for integer keys.
use fnv::{FnvHashMap, FnvHashSet};

View File

@@ -6,5 +6,4 @@
//! Concept of 'hierarchy' which is used in layouts and netlists.
pub mod prelude;
pub mod traits;
pub mod util;

View File

@@ -5,5 +5,4 @@
//! Include the most important structs and traits from this module.
pub use super::traits::*;
pub use super::util::*;

View File

@@ -1,421 +0,0 @@
// Copyright (c) 2020-2021 Thomas Kramer.
// SPDX-FileCopyrightText: 2022 Thomas Kramer
//
// SPDX-License-Identifier: AGPL-3.0-or-later
//! Basic traits that for the representation of chip data structures.
#![allow(unused_variables)]
#![allow(missing_docs)] // Necessary because portrait does not generate docs.
use crate::prelude::PropertyValue;
use crate::traits::{IdType, IdTypeMT};
use std::borrow::Borrow;
use std::hash::Hash;
/// Identifier types used for components of hierarchical netlists and layouts.
#[portrait::make]
pub trait HierarchyIds {
/// Cell/module identifier type.
type CellId: IdType;
/// Cell instance identifier type.
type CellInstId: IdType;
}
/// Helper trait which constrains [`trait@HierarchyBase`] for such that ID types
/// are [`Send`] and [`Sync`] as commonly used for parallel algorithms.
#[portrait::make]
pub trait HierarchyBaseMT:
HierarchyBase<CellId = Self::CellIdMT, CellInstId = Self::CellInstIdMT> + Sync
{
/// Identifier type for cells.
type CellIdMT: IdTypeMT;
/// Identifier type for cell instances.
type CellInstIdMT: IdTypeMT;
}
impl<H> HierarchyBaseMT for H
where
H: HierarchyBase + Sync,
H::CellId: Send + Sync,
H::CellInstId: Send + Sync,
{
type CellIdMT = H::CellId;
type CellInstIdMT = H::CellInstId;
}
/// Most basic trait for the hierarchical flyweight pattern which is
/// used to efficiently represent chip layouts and netlists.
///
/// ## Component relations
///
/// A netlist consists of cells which are templates for cell instances.
/// Each cell may contain such instances of other cells.
///
/// The following diagram illustrates how this composition graph can be traversed using the functions
/// defined by `HierarchyBase`.
///
/// ```txt
/// each_cell_dependency
/// +---------------------------+
/// | |
/// + v
/// +----------------+ each_dependent_cell +------------------+
/// |Circuit (Top) |<----------------------+|Circuit (Sub) |
/// +----------------+ +------------------+
/// |+ ^| | ^ + |
/// ||each_instance || | | | |
/// || || | | | |
/// || |parent | | | |
/// || || | | | |
/// ||+-----------+ || | | | |
/// +--> |>|Inst1 (Sub)|-+| | | | |
/// | ||+-----------+ | | | | |
/// | || | | | | |
/// | || | +-|---|------------+
/// | || | | |
/// | ||+-----------+ | template | |
/// +--> |>|Inst2 (Sub)|+----------------------------+ |
/// | | +-----------+ | |
/// | | | |
/// | | | |
/// | +----------------+ |
/// | |
/// | each_reference |
/// +----------------------------------------------------+
/// ```
///
/// # Example
///
/// Basic hierchy operations:
///
/// ```
/// use libreda_db::chip::Chip;
/// use libreda_db::traits::{HierarchyBase, HierarchyEdit};
///
/// // Create a simple hierarchical structure.
/// let mut chip = Chip::new();
/// let top_cell = chip.create_cell("MyTopCell".into());
/// let sub_cell = chip.create_cell("MySubCell".into());
/// // Create an instance of `sub_cell` inside `top_cell`.
/// let inst = chip.create_cell_instance(&top_cell, &sub_cell, Some("inst1".into()));
///
/// // Get all cells.
/// assert_eq!(chip.each_cell().count(), 2);
///
/// // Iterate over child instances.
/// assert_eq!(chip.each_cell_instance(&top_cell).next().as_ref(), Some(&inst));
///
/// // Get the template of an instance.
/// assert_eq!(&chip.template_cell(&inst), &sub_cell);
///
/// // Get the parent of an instance.
/// assert_eq!(&chip.parent_cell(&inst), &top_cell);
/// ```
#[portrait::make(import(crate::prelude::PropertyValue))]
pub trait HierarchyBase: HierarchyIds {
/// Type for names of cells, instances, etc.
type NameType: Eq
+ Hash
+ From<String>
+ Into<String>
+ Clone
+ Borrow<String>
+ Borrow<str>
+ PartialOrd
+ Ord
+ std::fmt::Display
+ std::fmt::Debug;
/// Find a cell by its name.
/// Return the cell with the given name. Returns `None` if the cell does not exist.
fn cell_by_name(&self, name: &str) -> Option<Self::CellId>;
/// Find a cell instance by its name.
/// Returns `None` if the name does not exist.
fn cell_instance_by_name(
&self,
parent_cell: &Self::CellId,
name: &str,
) -> Option<Self::CellInstId>;
/// Get the name of the cell.
fn cell_name(&self, cell: &Self::CellId) -> Self::NameType;
/// Get the name of the cell instance.
fn cell_instance_name(&self, cell_inst: &Self::CellInstId) -> Option<Self::NameType>;
/// Get the ID of the parent cell of this instance.
fn parent_cell(&self, cell_instance: &Self::CellInstId) -> Self::CellId;
/// Get the ID of the template cell of this instance.
fn template_cell(&self, cell_instance: &Self::CellInstId) -> Self::CellId;
/// Call a function on each cell of the netlist.
fn for_each_cell<F>(&self, f: F)
where
F: FnMut(Self::CellId);
/// Get a `Vec` of all cell IDs in this netlist.
fn each_cell_vec(&self) -> Vec<Self::CellId> {
let mut v = Vec::new();
self.for_each_cell(|c| v.push(c));
v
}
/// Iterate over all cells.
fn each_cell(&self) -> Box<dyn Iterator<Item = Self::CellId> + '_> {
Box::new(self.each_cell_vec().into_iter())
}
/// Call a function on each instance in this cell.
fn for_each_cell_instance<F>(&self, cell: &Self::CellId, f: F)
where
F: FnMut(Self::CellInstId);
/// Get a `Vec` of the IDs of all instances in this cell.
fn each_cell_instance_vec(&self, cell: &Self::CellId) -> Vec<Self::CellInstId> {
let mut v = Vec::new();
self.for_each_cell_instance(cell, |c| v.push(c));
v
}
/// Iterate over all instances in a cell.
fn each_cell_instance(
&self,
cell: &Self::CellId,
) -> Box<dyn Iterator<Item = Self::CellInstId> + '_> {
Box::new(self.each_cell_instance_vec(cell).into_iter())
}
/// Call a function for each cell that is a child of this `cell`.
fn for_each_cell_dependency<F>(&self, cell: &Self::CellId, f: F)
where
F: FnMut(Self::CellId);
/// Get a `Vec` of each cell that is a child of this `cell`.
fn each_cell_dependency_vec(&self, cell: &Self::CellId) -> Vec<Self::CellId> {
let mut v = Vec::new();
self.for_each_cell_dependency(cell, |c| v.push(c));
v
}
/// Iterate over all cells that are instantiated in this `cell`.
fn each_cell_dependency<'a>(
&'a self,
cell: &Self::CellId,
) -> Box<dyn Iterator<Item = Self::CellId> + 'a> {
Box::new(self.each_cell_dependency_vec(cell).into_iter())
}
/// Count all cells that are dependencies of `cell`.
fn num_cell_dependencies(&self, cell: &Self::CellId) -> usize {
// Inefficient default implementation.
let mut counter = 0;
self.for_each_cell_dependency(cell, |_| counter += 1);
counter
}
/// Call a function for each cell that directly depends on `cell`.
fn for_each_dependent_cell<F>(&self, cell: &Self::CellId, f: F)
where
F: FnMut(Self::CellId);
/// Get a `Vec` of each cell that directly depends on `cell`.
fn each_dependent_cell_vec(&self, cell: &Self::CellId) -> Vec<Self::CellId> {
let mut v = Vec::new();
self.for_each_dependent_cell(cell, |c| v.push(c));
v
}
/// Iterate over each cell that directly depends on `cell`.
fn each_dependent_cell<'a>(
&'a self,
cell: &Self::CellId,
) -> Box<dyn Iterator<Item = Self::CellId> + 'a> {
Box::new(self.each_dependent_cell_vec(cell).into_iter())
}
/// Count all cells that are directly dependent on `cell`, i.e. contain an instance of `cell`.
fn num_dependent_cells(&self, cell: &Self::CellId) -> usize {
// Inefficient default implementation.
let mut counter = 0;
self.for_each_dependent_cell(cell, |_| counter += 1);
counter
}
/// Iterate over all instances of this `cell`, i.e. instances that use this cell as
/// a template.
fn for_each_cell_reference<F>(&self, cell: &Self::CellId, f: F)
where
F: FnMut(Self::CellInstId);
/// Get a `Vec` with all cell instances referencing this cell.
fn each_cell_reference_vec(&self, cell: &Self::CellId) -> Vec<Self::CellInstId> {
let mut v = Vec::new();
self.for_each_cell_reference(cell, |c| v.push(c));
v
}
/// Iterate over all instances of this `cell`, i.e. instances that use this cell as
/// a template.
fn each_cell_reference(
&self,
cell: &Self::CellId,
) -> Box<dyn Iterator<Item = Self::CellInstId> + '_> {
// Provide an inefficient default implementation.
Box::new(self.each_cell_reference_vec(cell).into_iter())
}
/// Count all instantiations of `cell`.
fn num_cell_references(&self, cell: &Self::CellId) -> usize {
// Inefficient default implementation.
let mut counter = 0;
self.for_each_cell_reference(cell, |_| counter += 1);
counter
}
/// Get the number of cell instances inside the `cell`.
fn num_child_instances(&self, cell: &Self::CellId) -> usize;
/// Get the number of cell templates.
fn num_cells(&self) -> usize;
/// Get a property of the top-level chip data structure.
fn get_chip_property(&self, key: &Self::NameType) -> Option<PropertyValue> {
None
}
/// Get a property of a cell.
fn get_cell_property(
&self,
cell: &Self::CellId,
key: &Self::NameType,
) -> Option<PropertyValue> {
None
}
/// Get a property of a cell instance.
fn get_cell_instance_property(
&self,
inst: &Self::CellInstId,
key: &Self::NameType,
) -> Option<PropertyValue> {
None
}
}
/// Edit functions for a hierarchical flyweight structure like a netlist or a cell-based layout.
#[portrait::make(import(crate::prelude::PropertyValue))]
pub trait HierarchyEdit: HierarchyBase {
///// Create a new empty data structure.
//fn new() -> Self;
/// Create a new and empty cell template.
/// A cell template can be be instantiated in other cells.
///
/// # Example
/// ```
/// use libreda_db::prelude::*;
/// let mut chip = Chip::new();
/// let my_cell = chip.create_cell("myCell".into());
///
/// assert_eq!(chip.num_cells(), 1);
/// assert_eq!(chip.cell_by_name("myCell"), Some(my_cell));
/// ```
fn create_cell(&mut self, name: Self::NameType) -> Self::CellId;
/// Remove a cell and all the instances of it.
///
/// # Example
/// ```
/// use libreda_db::prelude::*;
/// let mut chip = Chip::new();
/// let top = chip.create_cell("TOP".into());
/// assert_eq!(chip.num_cells(), 1);
/// chip.remove_cell(&top);
/// assert_eq!(chip.num_cells(), 0);
/// ```
fn remove_cell(&mut self, cell_id: &Self::CellId);
/// Create a new instance of `template_cell` in `parent_cell`.
/// Recursive instantiation is forbidden and might panic.
///
/// # Example
/// ```
/// use libreda_db::prelude::*;
/// let mut chip = Chip::new();
/// let top = chip.create_cell("TOP".into());
/// let sub = chip.create_cell("SUB".into());
///
/// // Create two instances of "SUB" inside "TOP".
/// let inst1 = chip.create_cell_instance(&top, &sub, Some("sub1".into())); // Create named instance.
/// let inst2 = chip.create_cell_instance(&top, &sub, None); // Create unnamed instance.
///
/// assert_eq!(chip.num_child_instances(&top), 2);
/// assert_eq!(chip.num_cell_references(&sub), 2);
/// ```
fn create_cell_instance(
&mut self,
parent_cell: &Self::CellId,
template_cell: &Self::CellId,
name: Option<Self::NameType>,
) -> Self::CellInstId;
/// Remove cell instance if it exists.
/// # Example
/// ```
/// use libreda_db::prelude::*;
/// let mut chip = Chip::new();
/// let top = chip.create_cell("TOP".into());
/// let sub = chip.create_cell("SUB".into());
///
/// // Create two instances of "SUB" inside "TOP".
/// let inst1 = chip.create_cell_instance(&top, &sub, Some("sub1".into())); // Create named instance.
/// let inst2 = chip.create_cell_instance(&top, &sub, None); // Create unnamed instance.
///
/// assert_eq!(chip.num_child_instances(&top), 2);
/// assert_eq!(chip.num_cell_references(&sub), 2);
///
/// chip.remove_cell_instance(&inst2);
///
/// assert_eq!(chip.num_child_instances(&top), 1);
/// assert_eq!(chip.num_cell_references(&sub), 1);
/// ```
fn remove_cell_instance(&mut self, inst: &Self::CellInstId);
/// Change the name of a cell instance.
///
/// Clears the name when `None` is passed.
///
/// # Panics
/// Panics if an instance with this name already exists in the parent cell.
fn rename_cell_instance(&mut self, inst: &Self::CellInstId, new_name: Option<Self::NameType>);
/// Change the name of a cell.
///
/// # Panics
/// Panics if a cell with this name already exists.
fn rename_cell(&mut self, cell: &Self::CellId, new_name: Self::NameType);
/// Set a property of the top-level chip data structure..
fn set_chip_property(&mut self, key: Self::NameType, value: PropertyValue) {}
/// Set a property of a cell.
fn set_cell_property(
&mut self,
cell: &Self::CellId,
key: Self::NameType,
value: PropertyValue,
) {
}
/// Set a property of a cell instance.
fn set_cell_instance_property(
&mut self,
inst: &Self::CellInstId,
key: Self::NameType,
value: PropertyValue,
) {
}
}

View File

@@ -5,8 +5,8 @@
//! Utility functions for dealing with the hierarchy of netlists or layouts.
use super::traits::{HierarchyBase, HierarchyEdit};
use fnv::FnvHashSet;
use libreda_core::traits::{HierarchyBase, HierarchyEdit};
/// Non-modifying utility functions for the cell hierarchy..
/// Import the this trait to use the utility functions all types that implement the `HierarchyBase` trait.

View File

@@ -12,10 +12,6 @@
//! Each cell instance also holds the placement information, i.e. the location, rotation, mirroring and
//! possibly magnification.
pub use libreda_core::layout::*;
pub mod prelude;
pub mod io;
pub mod traits;
pub mod types;
pub mod util;

View File

@@ -5,8 +5,5 @@
//! The `prelude` helps to import most commonly used modules.
pub use super::io::*;
pub use super::traits::*;
pub use super::types::*;
pub use super::util::*;
pub use iron_shapes::prelude::*;
pub use libreda_core::layout::prelude::*;

View File

@@ -1,262 +0,0 @@
// Copyright (c) 2020-2021 Thomas Kramer.
// SPDX-FileCopyrightText: 2022 Thomas Kramer
//
// SPDX-License-Identifier: AGPL-3.0-or-later
//! Traits for layout data types.
#![allow(unused_variables)]
#![allow(missing_docs)] // Necessary because portrait does not generate docs.
use crate::layout::types::{LayerInfo, UInt};
use crate::prelude::PropertyValue;
use crate::prelude::{Geometry, Rect};
use crate::traits::{
HierarchyBase, HierarchyBaseMT, HierarchyEdit, HierarchyIds, IdType, IdTypeMT,
};
use iron_shapes::transform::SimpleTransform;
use iron_shapes::CoordinateType;
use num_traits::Num;
use std::hash::Hash;
/// Helper trait which constrains [`trait@LayoutBase`] for such that ID types
/// are [`Send`] and [`Sync`] as commonly used for parallel algorithms.
#[portrait::make]
pub trait LayoutBaseMT:
LayoutBase<LayerId = Self::LayerIdMT, ShapeId = Self::ShapeIdMT> + HierarchyBaseMT
{
/// Identifier for layers.
type LayerIdMT: IdTypeMT;
/// Identifier for shapes.
type ShapeIdMT: IdTypeMT;
}
impl<L> LayoutBaseMT for L
where
L: LayoutBase + HierarchyBaseMT,
L::LayerId: Send + Sync,
L::ShapeId: Send + Sync,
{
type LayerIdMT = L::LayerId;
type ShapeIdMT = L::ShapeId;
}
/// Define ID types used in layouts.
#[portrait::make(import(crate::prelude::*))]
pub trait LayoutIds: HierarchyIds {
/// Number type used for coordinates and distances.
type Coord: CoordinateType + std::fmt::Debug + std::fmt::Display + Hash + 'static + Send + Sync;
/// Number type for areas.
/// This is possibly another type then `Coord` for the following reasons:
/// * Distances and areas are semantically different.
/// * In practice `i32` is a good choice for coordinates. However, computing areas in `i32` might
/// easily lead to overflows. Hence a 64-bit integer type might be a better choice.
type Area: Num + Copy + PartialOrd + From<Self::Coord> + 'static + Send + Sync;
/// Layer identifier type.
type LayerId: IdType;
/// Shape identifier type.
type ShapeId: IdType;
}
/// Most basic trait of a layout.
///
/// This traits specifies methods for accessing the components of a layout.
#[portrait::make(import(crate::prelude::*))]
pub trait LayoutBase: LayoutIds + HierarchyBase {
/// Get the distance unit used in this layout in 'pixels per micron'.
fn dbu(&self) -> Self::Coord;
/// Iterate over all defined layers.
fn each_layer(&self) -> Box<dyn Iterator<Item = Self::LayerId> + '_>;
/// Get the `LayerInfo` data structure for this layer.
fn layer_info(&self, layer: &Self::LayerId) -> LayerInfo<Self::NameType>;
/// Find layer index by the (index, data type) tuple.
fn find_layer(&self, index: UInt, datatype: UInt) -> Option<Self::LayerId>;
/// Find layer index by the name.
fn layer_by_name(&self, name: &str) -> Option<Self::LayerId>;
/// Compute the bounding box of the shapes on one layer.
/// The bounding box also includes all child cell instances.
fn bounding_box_per_layer(
&self,
cell: &Self::CellId,
layer: &Self::LayerId,
) -> Option<Rect<Self::Coord>>;
/// Compute the bounding box of the cell over all layers.
/// The bounding box is not defined if the cell is empty. In this
/// case return `None`.
fn bounding_box(&self, cell: &Self::CellId) -> Option<Rect<Self::Coord>> {
self.each_layer()
.map(|layer| self.bounding_box_per_layer(cell, &layer))
.fold(None, |a, b| match (a, b) {
(None, None) => None,
(Some(a), None) | (None, Some(a)) => Some(a),
(Some(a), Some(b)) => Some(a.add_rect(&b)),
})
}
/// Iterate over the IDs of all shapes in the cell on a specific layer.
fn each_shape_id(
&self,
cell: &Self::CellId,
layer: &Self::LayerId,
) -> Box<dyn Iterator<Item = Self::ShapeId> + '_>;
/// Call a function for each shape on this layer.
fn for_each_shape<F>(&self, cell: &Self::CellId, layer: &Self::LayerId, f: F)
where
F: FnMut(&Self::ShapeId, &Geometry<Self::Coord>);
/// Access a shape by its ID.
fn with_shape<F, R>(&self, shape_id: &Self::ShapeId, f: F) -> R
where
F: FnMut(&Self::LayerId, &Geometry<Self::Coord>) -> R;
/// Get a clone of the shape geometry.
fn shape_geometry(&self, shape_id: &Self::ShapeId) -> Geometry<Self::Coord> {
self.with_shape(shape_id, |_, geo| geo.clone())
}
/// Get the layer of a shape.
fn shape_layer(&self, shape_id: &Self::ShapeId) -> Self::LayerId {
self.with_shape(shape_id, |layer, _| layer.clone())
}
/// Get the parent cell and the layer of a shape as a (cell, layer) tuple.
fn parent_of_shape(&self, shape_id: &Self::ShapeId) -> (Self::CellId, Self::LayerId);
/// Call a function `f` for each shape of this cell and its sub cells.
/// Along to the geometric shape `f` also gets a transformation as argument.
/// The transformation describes the actual position of the geometric shape relative to the `cell`.
fn for_each_shape_recursive<F>(&self, cell: &Self::CellId, layer: &Self::LayerId, mut f: F)
where
F: FnMut(SimpleTransform<Self::Coord>, &Self::ShapeId, &Geometry<Self::Coord>),
{
// This recursive iteration through the cells is implemented iteratively.
// A plain recursive implementation is more difficult to handle due to the type system.
// Stack for resolved recursion.
let mut stack = Vec::new();
stack.push((cell.clone(), SimpleTransform::identity()));
while let Some((cell, tf)) = stack.pop() {
// Push child instances.
self.for_each_cell_instance(&cell, |inst| {
let template = self.template_cell(&inst);
let transform = self.get_transform(&inst);
let tf2 = transform.then(&tf);
stack.push((template, tf2));
});
// Process shapes of this cell.
self.for_each_shape(&cell, layer, |id, g| f(tf, id, g));
}
}
/// Get the geometric transform that describes the location of a cell instance relative to its parent.
fn get_transform(&self, cell_inst: &Self::CellInstId) -> SimpleTransform<Self::Coord>;
/// Get a property of a shape.
fn get_shape_property(
&self,
shape: &Self::ShapeId,
key: &Self::NameType,
) -> Option<PropertyValue> {
None
}
}
/// Access shapes and instances in a layout based on their locations.
#[portrait::make]
pub trait RegionSearch: LayoutBase {
/// Iterate over the IDs of all shapes (on all layers) whose bounding-box overlaps with the `search_region`.
fn each_shape_in_region(
&self,
cell: &Self::CellId,
search_region: &Rect<Self::Coord>,
) -> Box<dyn Iterator<Item = Self::ShapeId> + '_> {
let cell = cell.clone(); // Get an owned ID.
let search_region = *search_region; // Get an owned rectangle.
Box::new(self.each_layer().flat_map(move |layer_id| {
self.each_shape_in_region_per_layer(&cell, &layer_id, &search_region)
}))
}
/// Iterate over the IDs of all shapes (on a specific layer) whose bounding-box overlaps with the `search_region`.
fn each_shape_in_region_per_layer(
&self,
cell: &Self::CellId,
layer_id: &Self::LayerId,
search_region: &Rect<Self::Coord>,
) -> Box<dyn Iterator<Item = Self::ShapeId> + '_>;
/// Iterate over the IDs of all instances within the `cell` whose bounding-box overlaps with the `search_region`.
fn each_cell_instance_in_region(
&self,
cell: &Self::CellId,
search_region: &Rect<Self::Coord>,
) -> Box<dyn Iterator<Item = Self::CellInstId> + '_>;
}
/// Trait for layouts that support editing.
#[portrait::make(import(crate::prelude::*))]
pub trait LayoutEdit: LayoutBase + HierarchyEdit {
/// Set the distance unit used in this layout in 'pixels per micron'.
fn set_dbu(&mut self, dbu: Self::Coord) {} // TODO: Remove default implementation.
/// Create a new layer.
/// Use `set_layer_name()` to define a name.
fn create_layer(&mut self, index: UInt, datatype: UInt) -> Self::LayerId;
/// Create a new layer with a specific ID. This is used to clone layer-stacks between layouts while preserving their IDs.
/// Returns an `Err` when the ID already exists.
fn create_layer_with_id(
&mut self,
layer_id: Self::LayerId,
index: UInt,
datatype: UInt,
) -> Result<(), ()>;
/// Set the name of a layer or clear the layer name when passing `None`.
/// This method should not change the ID of the layer.
/// Returns the previous name of the layer.
fn set_layer_name(
&mut self,
layer: &Self::LayerId,
name: Option<Self::NameType>,
) -> Option<Self::NameType>;
/// Insert a geometric shape into the parent cell.
fn insert_shape(
&mut self,
parent_cell: &Self::CellId,
layer: &Self::LayerId,
geometry: Geometry<Self::Coord>,
) -> Self::ShapeId;
/// Remove shape from the parent cell.
fn remove_shape(&mut self, shape_id: &Self::ShapeId) -> Option<Geometry<Self::Coord>>;
/// Replace the geometry of a shape.
fn replace_shape(
&mut self,
shape_id: &Self::ShapeId,
geometry: Geometry<Self::Coord>,
) -> Geometry<Self::Coord>;
/// Set the geometric transform that describes the location of a cell instance relative to its parent.
fn set_transform(&mut self, cell_inst: &Self::CellInstId, tf: SimpleTransform<Self::Coord>);
/// Set a property of a shape.
fn set_shape_property(
&mut self,
shape: &Self::ShapeId,
key: Self::NameType,
value: PropertyValue,
) {
}
}

View File

@@ -1,26 +0,0 @@
// Copyright (c) 2020-2021 Thomas Kramer.
// SPDX-FileCopyrightText: 2022 Thomas Kramer
//
// SPDX-License-Identifier: AGPL-3.0-or-later
//! Data types used in the data base.
/// Default unsigned integer type.
pub type UInt = u32;
/// Default signed integer type.
pub type SInt = i32;
/// Integer coordinate type.
pub type Coord = i32;
/// Meta-data of a layer.
#[derive(Clone, Hash, PartialEq, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct LayerInfo<NameType> {
/// Identifier of the layer.
pub index: UInt,
/// Identifier of the layer.
pub datatype: UInt,
/// Name of the layer.
pub name: Option<NameType>,
}

View File

@@ -88,6 +88,9 @@ extern crate num_derive;
pub use iron_shapes;
pub use iron_shapes_booleanop;
pub use libreda_core as core;
pub use libreda_core::technology;
/// Helpers for deriving trait implementations of core traits.
pub mod derive {
pub use portrait::delegate;
@@ -105,14 +108,10 @@ pub mod netlist;
pub mod prelude;
pub mod profile;
pub mod property_storage;
pub mod rc_string;
pub mod reference_access;
pub mod rw_reference_access;
pub mod traits;
pub mod undo;
pub mod technology;
mod blanket_impl;
mod library;
mod slab_alloc;

View File

@@ -5,7 +5,7 @@
//! ID of an arc (net segment). The arc is defined by two terminals (pin or pin instance).
use super::prelude::*;
use libreda_core::prelude::*;
use std::hash::Hash;
/// An arc represents the direct path from one pin to another.

View File

@@ -1,43 +0,0 @@
// Copyright (c) 2020-2021 Thomas Kramer.
// SPDX-FileCopyrightText: 2022 Thomas Kramer
//
// SPDX-License-Identifier: AGPL-3.0-or-later
//! The type of a pin is specified by a signal direction.
/// Signal type for pins.
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, Default)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum Direction {
/// No direction specified.
#[default]
None,
/// Data input.
Input,
/// Data output.
Output,
/// Input and output.
InOut,
/// Clock input.
Clock,
/// Power VDD.
Supply,
/// Power ground.
Ground,
}
impl Direction {
/// Check if this direction is 'input'.
pub fn is_input(&self) -> bool {
self == &Direction::Input
}
/// Check if this direction is 'output'.
pub fn is_output(&self) -> bool {
self == &Direction::Output
}
/// Check if this direciton is either 'Supply' or 'Ground'.
pub fn is_power(&self) -> bool {
matches!(self, Direction::Supply | Direction::Ground)
}
}

View File

@@ -1,47 +0,0 @@
// Copyright (c) 2020-2021 Thomas Kramer.
// SPDX-FileCopyrightText: 2022 Thomas Kramer
//
// SPDX-License-Identifier: AGPL-3.0-or-later
//! Input and output interface definitions for netlists.
//!
//! Implementations for the various netlist formats are located in other crates.
use crate::netlist::traits::{NetlistBase, NetlistEdit};
use std::io::{Read, Write};
/// Read a netlist from a byte stream.
pub trait NetlistReader {
/// Type of error that could happen while reading a netlist.
type Error;
/// Read a netlist from a byte stream and populate the netlist data structure.
fn read_into_netlist<R: Read, N: NetlistEdit>(
&self,
reader: &mut R,
netlist: &mut N,
) -> Result<(), Self::Error>;
/// Read a netlist from a byte stream.
fn read_netlist<R: Read, N: NetlistEdit + Default>(
&self,
reader: &mut R,
) -> Result<N, Self::Error> {
let mut netlist = N::default();
self.read_into_netlist(reader, &mut netlist)?;
Ok(netlist)
}
}
/// Write a netlist to a byte stream.
pub trait NetlistWriter {
/// Type of error that could happen while writing a netlist.
type Error;
/// Write the netlist data structure to a byte stream.
fn write_netlist<W: Write, N: NetlistBase>(
&self,
writer: &mut W,
netlist: &N,
) -> Result<(), Self::Error>;
}

View File

@@ -22,10 +22,13 @@
//! [`NetlistBase`]: trait@traits::NetlistBase
//! [`NetlistEdit`]: trait@traits::NetlistEdit
pub use libreda_core::netlist::prelude::*;
pub mod arc_id;
pub mod direction;
pub mod io;
pub mod prelude;
pub mod terminal_id;
pub mod traits;
pub mod util;
/// Re-export of traits related to netlists.
pub mod traits {
pub use super::util::{NetlistEditUtil, NetlistUtil};
pub use libreda_core::netlist::traits::*;
}

View File

@@ -1,13 +0,0 @@
// Copyright (c) 2020-2021 Thomas Kramer.
// SPDX-FileCopyrightText: 2022 Thomas Kramer
//
// SPDX-License-Identifier: AGPL-3.0-or-later
//! The `prelude` helps to import most commonly used modules.
pub use super::arc_id::*;
pub use super::direction::*;
pub use super::io::*;
pub use super::terminal_id::*;
pub use super::traits::*;
pub use super::util::*;

View File

@@ -1,80 +0,0 @@
// Copyright (c) 2020-2022 Thomas Kramer.
// SPDX-FileCopyrightText: 2022 Thomas Kramer
//
// SPDX-License-Identifier: AGPL-3.0-or-later
//! Generalization of pins and pin instances.
use super::prelude::*;
use std::hash::{Hash, Hasher};
/// A terminal is a generalization of pins and pin instances.
pub enum TerminalId<N: NetlistIds + ?Sized> {
/// Terminal is a pin.
PinId(N::PinId),
/// Terminal is a pin instance.
PinInstId(N::PinInstId),
}
impl<N1> TerminalId<N1>
where
N1: NetlistIds,
{
/// Cast the ID to other netlist types.
pub fn cast<N2>(self) -> TerminalId<N2>
where
N2: NetlistIds<PinId = N1::PinId, PinInstId = N1::PinInstId>,
{
match self {
TerminalId::PinId(p) => TerminalId::PinId(p),
TerminalId::PinInstId(p) => TerminalId::PinInstId(p),
}
}
}
impl<N: NetlistIds + ?Sized> std::fmt::Debug for TerminalId<N>
where
N::PinId: std::fmt::Debug,
N::PinInstId: std::fmt::Debug,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
TerminalId::PinId(p) => write!(f, "{:?}", p),
TerminalId::PinInstId(p) => write!(f, "{:?}", p),
}
}
}
impl<N: NetlistIds + ?Sized> Hash for TerminalId<N> {
fn hash<H: Hasher>(&self, state: &mut H) {
match self {
TerminalId::PinId(p) => p.hash(state),
TerminalId::PinInstId(p) => p.hash(state),
}
}
}
impl<N: NetlistIds + ?Sized> Eq for TerminalId<N> {}
impl<N: NetlistIds + ?Sized> PartialEq for TerminalId<N> {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(Self::PinId(p1), Self::PinId(p2)) => p1 == p2,
(Self::PinInstId(p1), Self::PinInstId(p2)) => p1 == p2,
(_, _) => false,
}
}
}
impl<N: NetlistIds + ?Sized> Clone for TerminalId<N>
where
N::PinId: Clone,
N::PinInstId: Clone,
{
fn clone(&self) -> Self {
match self {
TerminalId::PinId(p) => Self::PinId(p.clone()),
TerminalId::PinInstId(p) => Self::PinInstId(p.clone()),
}
}
}

View File

@@ -1,375 +0,0 @@
// Copyright (c) 2020-2021 Thomas Kramer.
// SPDX-FileCopyrightText: 2022 Thomas Kramer
//
// SPDX-License-Identifier: AGPL-3.0-or-later
//! Traits for netlist data types.
//!
//! Instead of putting a netlist data structure into the center of the world,
//! this data base concentrates on the way *how* a netlist can be accessed and modified.
//! The basic necessary operations are defined in the [`NetlistBase'] trait and in the
//! [`NetlistEdit`] trait.
//!
//! More complex operations on netlist are provided by the [`NetlistUtil`] and [`NetlistEditUtil`] traits.
//!
//! [`NetlistBase`]: trait@NetlistBase
//! [`NetlistEdit`]: trait@NetlistEdit
//! [`NetlistUtil`]: trait@crate::netlist::util::NetlistUtil
//! [`NetlistEditUtil`]: trait@crate::netlist::util::NetlistEditUtil
#![allow(missing_docs)] // Necessary because portrait does not generate docs.
use super::prelude::*;
pub use super::util::{NetlistEditUtil, NetlistUtil};
pub use crate::traits::{HierarchyBase, HierarchyEdit};
use crate::traits::{HierarchyBaseMT, HierarchyIds, IdType, IdTypeMT};
/// Identifier types used for components of netlists.
#[portrait::make]
pub trait NetlistIds: HierarchyIds {
/// Pin identifier type. Uniquely identifies a pin in the whole netlist.
type PinId: IdType;
/// Pin instance identifier type. Uniquely identifies a pin instance in the whole netlist.
/// A pin instance is a pin of a circuit instance.
type PinInstId: IdType;
/// Net identifier type. Uniquely identifies a net in the whole netlist.
type NetId: IdType;
}
/// Helper trait which constrains [`trait@NetlistBase`] for such that ID types
/// are [`Send`] and [`Sync`] as commonly used for parallel algorithms.
#[portrait::make]
pub trait NetlistBaseMT:
NetlistBase<PinId = Self::PinIdMT, PinInstId = Self::PinInstIdMT, NetId = Self::NetIdMT>
+ HierarchyBaseMT
{
/// ID of a pin.
type PinIdMT: IdTypeMT;
/// ID of a pin instance.
type PinInstIdMT: IdTypeMT;
/// ID of a net.
type NetIdMT: IdTypeMT;
}
impl<N> NetlistBaseMT for N
where
N: NetlistBase + HierarchyBaseMT,
N::PinId: Send + Sync,
N::PinInstId: Send + Sync,
N::NetId: Send + Sync,
{
type PinIdMT = N::PinId;
type PinInstIdMT = N::PinInstId;
type NetIdMT = N::NetId;
}
/// Most basic trait for traversing a netlist.
/// A netlist extends the `HierarchyBase` and hence is hierarchical.
/// `NetlistBase` extends the components of the hierarchy with pins and nets.
/// Each cell can have pins. Each cell instance has pin instances that correspond one-to-one
/// to the pins of the template cell. Cells can contain nets. Each pin and each pin instance can be
/// connected to one or zero nets. A net can be connected to an arbitrary number of pins and pin instances.
///
/// Pins must have a name and also a signal direction.
///
/// Nets *can* have a name.
///
#[portrait::make(import(crate::prelude::Direction))]
pub trait NetlistBase: HierarchyBase + NetlistIds {
/// Get the ID of the template pin of this pin instance.
fn template_pin(&self, pin_instance: &Self::PinInstId) -> Self::PinId;
/// Get the signal direction of the pin.
fn pin_direction(&self, pin: &Self::PinId) -> Direction;
/// Get the name of the pin.
fn pin_name(&self, pin: &Self::PinId) -> Self::NameType;
/// Find a pin by its name.
/// Returns `None` if no such pin can be found.
fn pin_by_name(&self, parent_circuit: &Self::CellId, name: &str) -> Option<Self::PinId>;
/// Get the ID of the parent circuit of this pin.
fn parent_cell_of_pin(&self, pin: &Self::PinId) -> Self::CellId;
/// Get the ID of the circuit instance that holds this pin instance.
fn parent_of_pin_instance(&self, pin_inst: &Self::PinInstId) -> Self::CellInstId;
/// Get the ID of a pin instance given the cell instance and the pin ID.
fn pin_instance(&self, cell_inst: &Self::CellInstId, pin: &Self::PinId) -> Self::PinInstId {
// Inefficient default implementation.
self.each_pin_instance(cell_inst)
.find(|inst| &self.template_pin(inst) == pin)
.expect("No such pin found in this cell.")
}
/// Get the ID of the parent circuit of this net.
fn parent_cell_of_net(&self, net: &Self::NetId) -> Self::CellId;
/// Get the internal net attached to this pin.
fn net_of_pin(&self, pin: &Self::PinId) -> Option<Self::NetId>;
/// Get the external net attached to this pin instance.
fn net_of_pin_instance(&self, pin_instance: &Self::PinInstId) -> Option<Self::NetId>;
/// Get the net of the logical constant zero.
fn net_zero(&self, parent_circuit: &Self::CellId) -> Self::NetId;
/// Get the net of the logical constant one.
fn net_one(&self, parent_circuit: &Self::CellId) -> Self::NetId;
/// Find a net by its name inside the parent circuit.
/// Returns `None` if no such net can be found.
fn net_by_name(&self, parent_circuit: &Self::CellId, name: &str) -> Option<Self::NetId>;
/// Get the name of the net.
fn net_name(&self, net: &Self::NetId) -> Option<Self::NameType>;
/// Call a function for each pin of the circuit.
fn for_each_pin<F>(&self, circuit: &Self::CellId, f: F)
where
F: FnMut(Self::PinId);
/// Get a `Vec` with the IDs of all pins of this circuit.
fn each_pin_vec(&self, circuit: &Self::CellId) -> Vec<Self::PinId> {
let mut v = Vec::new();
self.for_each_pin(circuit, |c| v.push(c));
v
}
/// Iterate over all pins of a circuit.
fn each_pin<'a>(
&'a self,
circuit: &Self::CellId,
) -> Box<dyn Iterator<Item = Self::PinId> + 'a> {
Box::new(self.each_pin_vec(circuit).into_iter())
}
// /// Find the position of the pin.
// fn pin_position(&self, pin: &Self::PinId) -> usize {
// self.for_each_pin(&self.parent_cell_of_pin(pin))
// .enumerate()
// .find(|(_, p)| p == pin)
// .map(|(idx, _)| idx)
// .expect("pin ID does not exist")
// }
/// Call a function for each pin instance of the circuit instance.
fn for_each_pin_instance<F>(&self, circuit_inst: &Self::CellInstId, f: F)
where
F: FnMut(Self::PinInstId);
/// Get a `Vec` with the IDs of all pin instance of this circuit instance.
fn each_pin_instance_vec(&self, circuit_instance: &Self::CellInstId) -> Vec<Self::PinInstId> {
let mut v = Vec::new();
self.for_each_pin_instance(circuit_instance, |c| v.push(c));
v
}
/// Iterate over all pin instances of a circuit.
fn each_pin_instance<'a>(
&'a self,
circuit_instance: &Self::CellInstId,
) -> Box<dyn Iterator<Item = Self::PinInstId> + 'a> {
Box::new(self.each_pin_instance_vec(circuit_instance).into_iter())
}
/// Iterate over all external nets connected to the circuit instance.
/// A net might appear more than once.
fn each_external_net<'a>(
&'a self,
circuit_instance: &Self::CellInstId,
) -> Box<dyn Iterator<Item = Self::NetId> + 'a> {
Box::new(
self.each_pin_instance(circuit_instance)
.flat_map(move |pin_id| self.net_of_pin_instance(&pin_id)),
)
}
/// Iterate over all external nets connected to the circuit instance.
/// A net might appear more than once.
fn for_each_external_net<F>(&self, circuit_instance: &Self::CellInstId, mut f: F)
where
F: FnMut(Self::NetId),
{
self.for_each_pin_instance(circuit_instance, |i| {
self.net_of_pin_instance(&i)
.iter()
.cloned()
.for_each(|n| f(n))
});
}
/// Get a vector of all external nets connected to the circuit instance.
/// A net might appear more than once.
fn each_external_net_vec(&self, circuit_instance: &Self::CellInstId) -> Vec<Self::NetId> {
let mut v = Vec::new();
self.for_each_external_net(circuit_instance, |n| v.push(n));
v
}
/// Call a function for net of the circuit.
fn for_each_internal_net<F>(&self, circuit: &Self::CellId, f: F)
where
F: FnMut(Self::NetId);
/// Get a `Vec` with all nets in this circuit.
fn each_internal_net_vec(&self, circuit: &Self::CellId) -> Vec<Self::NetId> {
let mut v = Vec::new();
self.for_each_internal_net(circuit, |c| v.push(c));
v
}
/// Iterate over all defined nets inside a circuit.
fn each_internal_net<'a>(
&'a self,
circuit: &Self::CellId,
) -> Box<dyn Iterator<Item = Self::NetId> + 'a> {
Box::new(self.each_internal_net_vec(circuit).into_iter())
}
/// Return the number of nets defined inside a cell.
fn num_internal_nets(&self, circuit: &Self::CellId) -> usize {
// Inefficient default implementation.
let mut counter = 0;
self.for_each_internal_net(circuit, |_| counter += 1);
counter
}
/// Get the number of pins that are connected to this net.
fn num_net_pins(&self, net: &Self::NetId) -> usize {
let mut n = 0;
self.for_each_pin_of_net(net, |_| n += 1);
n
}
/// Get the number of pin instances that are connected to this net.
fn num_net_pin_instances(&self, net: &Self::NetId) -> usize {
let mut n = 0;
self.for_each_pin_instance_of_net(net, |_| n += 1);
n
}
/// Get the number of terminals that are connected to this net.
fn num_net_terminals(&self, net: &Self::NetId) -> usize {
self.num_net_pins(net) + self.num_net_pin_instances(net)
}
/// Get the number of pins of a circuit.
fn num_pins(&self, circuit: &Self::CellId) -> usize;
/// Call a function for each pin connected to this net.
fn for_each_pin_of_net<F>(&self, net: &Self::NetId, f: F)
where
F: FnMut(Self::PinId);
/// Get a `Vec` with all pin IDs connected to this net.
fn each_pin_of_net_vec(&self, net: &Self::NetId) -> Vec<Self::PinId> {
let mut v = Vec::new();
self.for_each_pin_of_net(net, |c| v.push(c));
v
}
/// Iterate over all pins of a net.
fn each_pin_of_net<'a>(
&'a self,
net: &Self::NetId,
) -> Box<dyn Iterator<Item = Self::PinId> + 'a> {
Box::new(self.each_pin_of_net_vec(net).into_iter())
}
/// Call a function for each pin instance connected to this net.
fn for_each_pin_instance_of_net<F>(&self, net: &Self::NetId, f: F)
where
F: FnMut(Self::PinInstId);
/// Get a `Vec` with all pin instance IDs connected to this net.
fn each_pin_instance_of_net_vec(&self, net: &Self::NetId) -> Vec<Self::PinInstId> {
let mut v = Vec::new();
self.for_each_pin_instance_of_net(net, |c| v.push(c));
v
}
/// Iterate over all pins of a net.
fn each_pin_instance_of_net<'a>(
&'a self,
net: &Self::NetId,
) -> Box<dyn Iterator<Item = Self::PinInstId> + 'a> {
Box::new(self.each_pin_instance_of_net_vec(net).into_iter())
}
}
/// Trait for netlists that support editing.
///
/// This includes:
///
/// * creation and removal of pins and nets
/// * connecting pins and pin instances to nets
/// * renaming nets
/// * renaming pins
///
/// More complex operations which can be build on top of the basic operations
/// are provided by the [`NetlistEditUtil`] trait.
///
/// [`NetlistEditUtil`]: crate::netlist::util::NetlistEditUtil
#[portrait::make(import(crate::prelude::Direction))]
pub trait NetlistEdit: NetlistBase + HierarchyEdit {
// /// Create a multi-bit port.
// /// Internally creates a pin for every bit of the port.
// fn create_bus(&mut self, circuit: &Self::CellId, name: Self::NameType, direction: Direction, width: usize) -> Vec<Self::PinId>;
/// Create a new pin in this cell.
/// Also adds the pin to all instances of the cell.
fn create_pin(
&mut self,
cell: &Self::CellId,
name: Self::NameType,
direction: Direction,
) -> Self::PinId;
/// Remove the pin from this circuit and from all instances of this circuit.
fn remove_pin(&mut self, id: &Self::PinId);
/// Change the name of the pin, returns the old name.
/// # Panics
/// Panics when the name is already occupied.
fn rename_pin(&mut self, pin: &Self::PinId, new_name: Self::NameType) -> Self::NameType;
/// Create a net net that lives in the `parent` circuit.
fn create_net(&mut self, parent: &Self::CellId, name: Option<Self::NameType>) -> Self::NetId;
/// Set a new name for the net. This might panic if the name already exists.
/// Returns the old name.
fn rename_net(
&mut self,
net_id: &Self::NetId,
new_name: Option<Self::NameType>,
) -> Option<Self::NameType>;
/// Delete the net if it exists and disconnect all connected terminals.
fn remove_net(&mut self, net: &Self::NetId);
/// Connect a pin to a net.
/// Returns the old connected net, if any.
fn connect_pin(&mut self, pin: &Self::PinId, net: Option<Self::NetId>) -> Option<Self::NetId>;
/// Disconnect the pin from any connected net.
/// Returns the old connected net, if any.
fn disconnect_pin(&mut self, pin: &Self::PinId) -> Option<Self::NetId> {
self.connect_pin(pin, None)
}
/// Connect a pin instance to a net.
/// Returns the old connected net, if any.
fn connect_pin_instance(
&mut self,
pin: &Self::PinInstId,
net: Option<Self::NetId>,
) -> Option<Self::NetId>;
/// Disconnect the pin instance from any connected net.
/// Returns the old connected net, if any.
fn disconnect_pin_instance(&mut self, pin_instance: &Self::PinInstId) -> Option<Self::NetId> {
self.connect_pin_instance(pin_instance, None)
}
}

View File

@@ -7,30 +7,19 @@
pub use crate::chip::Chip;
pub use crate::flat_view::FlatView;
pub use crate::hierarchy::prelude::*;
pub use crate::l2n::*;
pub use crate::layout::prelude::*;
pub use crate::netlist::prelude::*;
pub use crate::layout::util::*;
pub use crate::netlist::util::*;
pub use crate::profile::*;
pub use crate::property_storage::PropertyValue;
pub use crate::rc_string::RcString;
pub use crate::reference_access;
pub use crate::reference_access::*;
pub use crate::technology;
pub use crate::technology::prelude::*;
pub use crate::traits::*;
pub use libreda_core::prelude::*;
/// Re-export of most traits.
/// This can be useful if only traits should be used but not the rest.
pub mod traits {
pub use crate::hierarchy::traits::*;
pub use crate::hierarchy::util::*;
pub use crate::l2n::*;
pub use crate::layout::traits::*;
pub use crate::layout::util::*;
pub use crate::netlist::traits::*;
pub use crate::netlist::util::*;
pub use crate::reference_access::*;
pub use crate::traits::*;
pub use iron_shapes::traits::*;
pub use libreda_core::traits::*;
}

View File

@@ -5,174 +5,10 @@
//! Container structs for user defined properties.
use crate::rc_string::RcString;
use libreda_core::prelude::{PropertyValue, RcString};
use std::borrow::Borrow;
use std::collections::HashMap;
use std::convert::TryInto;
use std::hash::Hash;
use std::sync::Arc;
// trait AnyValue: Any + Clone + std::fmt::Debug {}
/// Property value type.
/// Properties can hold different types that are encapsulated in this enum.
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum PropertyValue {
/// Property is a string.
String(RcString),
/// Property is a byte string.
Bytes(Vec<u8>),
/// Property is a signed integer.
SInt(i32),
/// Property is an unsigned integer.
UInt(u32),
/// Property is a float.
Float(f64),
// /// Dynamically typed value.
// Any(Box<dyn AnyValue>),
}
impl PropertyValue {
/// Try to get a string value.
pub fn get_string(&self) -> Option<RcString> {
match self {
PropertyValue::String(s) => Some(s.clone()),
_ => None,
}
}
/// Try to get a `&str` value. Works for `String` property values.
pub fn get_str(&self) -> Option<&str> {
match self {
PropertyValue::String(s) => Some(s.as_str()),
_ => None,
}
}
/// Try to get a byte string value.
pub fn get_bytes(&self) -> Option<&Vec<u8>> {
match self {
PropertyValue::Bytes(s) => Some(s),
_ => None,
}
}
/// Try to get a float value.
pub fn get_float(&self) -> Option<f64> {
match self {
PropertyValue::Float(v) => Some(*v),
_ => None,
}
}
/// Try to get an i32 value.
pub fn get_sint(&self) -> Option<i32> {
match self {
PropertyValue::SInt(v) => Some(*v),
_ => None,
}
}
/// Try to get an i32 value.
pub fn get_uint(&self) -> Option<u32> {
match self {
PropertyValue::UInt(v) => Some(*v),
_ => None,
}
}
// /// Try to get a dynamically typed value.
// pub fn get_any(&self) -> Option<&Box<dyn AnyValue>> {
// match self {
// PropertyValue::Any(v) => Some(v),
// _ => None
// }
// }
}
// pub enum PropertyKey {
// String(String),
//
// }
impl From<String> for PropertyValue {
fn from(v: String) -> Self {
PropertyValue::String(v.into())
}
}
impl From<Arc<String>> for PropertyValue {
fn from(v: Arc<String>) -> Self {
PropertyValue::String(v.into())
}
}
impl From<&Arc<String>> for PropertyValue {
fn from(v: &Arc<String>) -> Self {
PropertyValue::String(v.into())
}
}
impl From<&str> for PropertyValue {
fn from(v: &str) -> Self {
PropertyValue::String(v.into())
}
}
impl From<Vec<u8>> for PropertyValue {
fn from(v: Vec<u8>) -> Self {
PropertyValue::Bytes(v)
}
}
impl<'a> TryInto<&'a str> for &'a PropertyValue {
type Error = ();
fn try_into(self) -> Result<&'a str, Self::Error> {
if let PropertyValue::String(s) = self {
Ok(s.as_str())
} else {
Err(())
}
}
}
impl From<i32> for PropertyValue {
fn from(v: i32) -> Self {
PropertyValue::SInt(v)
}
}
impl TryInto<i32> for &PropertyValue {
type Error = ();
fn try_into(self) -> Result<i32, Self::Error> {
if let PropertyValue::SInt(v) = self {
Ok(*v)
} else {
Err(())
}
}
}
impl From<u32> for PropertyValue {
fn from(v: u32) -> Self {
PropertyValue::UInt(v)
}
}
impl From<f64> for PropertyValue {
fn from(v: f64) -> Self {
PropertyValue::Float(v)
}
}
// impl From<Box<dyn Any>> for PropertyValue {
// fn from(v: Box<dyn Any>) -> Self {
// PropertyValue::Any(v)
// }
// }
/// Look-up table for property values.
#[derive(Debug, Clone)]
@@ -238,51 +74,3 @@ impl<K: Hash + Eq> PropertyStore<K> {
})
}
}
/// A trait for associating user defined properties with a type.
pub trait WithProperties {
/// Property key type.
type Key: Hash + Eq;
/// Call a function with maybe the property storage as argument.
///
/// The property store might not always be initialized. For instance for
/// objects without any defined properties, it will likely be `None`.
fn with_properties<F, R>(&self, f: F) -> R
where
F: FnOnce(Option<&PropertyStore<Self::Key>>) -> R;
/// Get mutable reference to the property storage.
fn with_properties_mut<F, R>(&self, f: F) -> R
where
F: FnOnce(&mut PropertyStore<Self::Key>) -> R;
/// Get a property value by the property key.
fn property<Q: ?Sized>(&self, key: &Q) -> Option<PropertyValue>
where
Self::Key: Borrow<Q>,
Q: Eq + Hash,
{
self.with_properties(|p| p.and_then(|p| p.get(key).cloned()))
}
/// Get a string property value by key.
/// If the property value is not a string `None` is returned.
fn property_str<Q: ?Sized>(&self, key: &Q) -> Option<RcString>
where
Self::Key: Borrow<Q>,
Q: Eq + Hash,
{
self.with_properties(|p| p.and_then(|p| p.get_string(key).cloned()))
}
/// Insert a property.
/// Returns the old property value if there was already a property stored under this key.
fn set_property<V: Into<PropertyValue>>(
&self,
key: Self::Key,
value: V,
) -> Option<PropertyValue> {
self.with_properties_mut(|p| p.insert(key, value))
}
}

View File

@@ -1,112 +0,0 @@
// Copyright (c) 2020-2021 Thomas Kramer.
// SPDX-FileCopyrightText: 2022 Thomas Kramer
//
// SPDX-License-Identifier: AGPL-3.0-or-later
//! `RcString` is a simple data structure for the representation of strings.
//! In contrast to `String`, `RcString` can be efficiently cloned. It is intended
//! to be used in cases where objects are indexed by a human readable name.
//!
//! # Example
//!
//! ```
//! use libreda_db::rc_string::RcString;
//!
//! let a: String = "A".to_string();
//!
//! let a1_rc = RcString::from(a);
//! let a2_rc = RcString::from("A");
//!
//! // No string data is copied here.
//! let a3_rc = a1_rc.clone();
//!
//! assert_eq!(a1_rc, a2_rc);
//! assert_eq!(a1_rc, a3_rc);
//!
//! ```
use iron_shapes::point::Deref;
use std::borrow::Borrow;
use std::hash::{Hash, Hasher};
use std::sync::Arc;
/// Resource counted string, used for names.
/// `RcString`s can be efficiently cloned.
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct RcString {
string: Arc<String>,
}
impl std::fmt::Display for RcString {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.string.as_str(), f)
}
}
impl RcString {
/// Create a new resource counted string.
pub fn new(string: String) -> Self {
RcString {
string: Arc::new(string),
}
}
}
impl Hash for RcString {
fn hash<H: Hasher>(&self, state: &mut H) {
self.string.hash(state)
}
}
impl Deref for RcString {
type Target = String;
fn deref(&self) -> &Self::Target {
self.string.deref()
}
}
impl Borrow<str> for RcString {
fn borrow(&self) -> &str {
self.as_str()
}
}
impl Borrow<String> for RcString {
fn borrow(&self) -> &String {
self.string.deref()
}
}
impl From<String> for RcString {
fn from(string: String) -> Self {
Self::new(string)
}
}
impl From<Arc<String>> for RcString {
fn from(string: Arc<String>) -> Self {
Self { string }
}
}
impl From<&Arc<String>> for RcString {
fn from(string: &Arc<String>) -> Self {
Self {
string: string.clone(),
}
}
}
impl From<&str> for RcString {
fn from(s: &str) -> Self {
Self::new(s.to_string())
}
}
impl From<RcString> for String {
fn from(val: RcString) -> Self {
val.string.to_string()
}
}

View File

@@ -3,7 +3,7 @@
//
// SPDX-License-Identifier: AGPL-3.0-or-later
use crate::traits::HierarchyBase;
use libreda_core::traits::HierarchyBase;
/// Trait that provides object-like read access to a cell hierarchy structure and its elements.
pub trait HierarchyReferenceAccess: HierarchyBase {

View File

@@ -1,5 +1,4 @@
// Copyright (c) 2020-2021 Thomas Kramer.
// SPDX-FileCopyrightText: 2022 Thomas Kramer
// SPDX-FileCopyrightText: 2020-2024 Thomas Kramer
//
// SPDX-License-Identifier: AGPL-3.0-or-later

View File

@@ -3,8 +3,7 @@
//
// SPDX-License-Identifier: AGPL-3.0-or-later
use crate::netlist::prelude::*;
use crate::traits::NetlistBase;
use crate::netlist::*;
use super::hierarchy_reference_access::*;

View File

@@ -1,114 +0,0 @@
// Copyright (c) 2020-2021 Thomas Kramer.
// SPDX-FileCopyrightText: 2022 Thomas Kramer
//
// SPDX-License-Identifier: AGPL-3.0-or-later
//! Definition of the metal layer stack as it is needed for routers.
use super::rules::RuleBase;
/// A routing layer is either a 'via' or 'routing/metal' layer.
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
pub enum RoutingLayerType {
/// Via layer.
Cut,
/// Routing layer.
Routing,
}
/// Annotate a layer ID as 'via' or 'routing' layer.
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
pub struct RoutingLayer<LayerId> {
/// ID of the layer. This identifies the layer in the data-base structures.
pub id: LayerId,
/// Type of the routing layer (via or metal).
pub layer_type: RoutingLayerType,
}
impl<LayerId> RoutingLayer<LayerId> {
/// Associate a layer ID with a layer type.
pub fn new(id: LayerId, layer_type: RoutingLayerType) -> Self {
Self { id, layer_type }
}
/// Get the a reference to the ID of the layer.
pub fn as_id(&self) -> &LayerId {
&self.id
}
/// Get the ID of the layer.
pub fn id(self) -> LayerId {
self.id
}
/// Type of the layer.
pub fn layer_type(&self) -> RoutingLayerType {
self.layer_type
}
/// Check if layer is a via/cut layer.
pub fn is_via_layer(&self) -> bool {
match self.layer_type() {
RoutingLayerType::Cut => true,
RoutingLayerType::Routing => false,
}
}
/// Check if layer is a metal layer.
pub fn is_metal_layer(&self) -> bool {
match self.layer_type() {
RoutingLayerType::Cut => false,
RoutingLayerType::Routing => true,
}
}
}
/// Define standardized access for routing and via layers.
pub trait RoutingLayerStack: RuleBase {
/// Get the stack of routing and via layers in process order.
fn layer_stack(&self) -> Vec<RoutingLayer<Self::LayerId>>;
/// Get the layer ids of the layer stack (routing layers and via layers).
fn layer_stack_ids(&self) -> Vec<Self::LayerId> {
self.layer_stack().into_iter().map(|l| l.id).collect()
}
/// Get the stack of routing metal layers in process order.
fn routing_layer_stack(&self) -> Vec<Self::LayerId> {
self.layer_stack()
.into_iter()
.filter(|l| l.is_metal_layer())
.map(|l| l.id())
.collect()
}
/// Get the stack of via layers in process order.
fn via_layer_stack(&self) -> Vec<Self::LayerId> {
self.layer_stack()
.into_iter()
.filter(|l| l.is_via_layer())
.map(|l| l.id())
.collect()
}
/// Find the closest metal layer above the given layer.
fn get_upper_metal_layer(&self, layer: &Self::LayerId) -> Option<Self::LayerId> {
self.layer_stack()
.into_iter()
.skip_while(|l| l.as_id() != layer)
.skip(1)
.find(|l| l.is_metal_layer())
.map(|l| l.id())
}
/// Find the closest metal layer under the given layer.
fn get_lower_metal_layer(&self, layer: &Self::LayerId) -> Option<Self::LayerId> {
self.layer_stack()
.into_iter()
.rev()
.skip_while(|l| l.as_id() != layer)
.skip(1)
.find(|l| l.is_metal_layer())
.map(|l| l.id())
}
}

View File

@@ -1,10 +0,0 @@
// Copyright (c) 2020-2021 Thomas Kramer.
// SPDX-FileCopyrightText: 2022 Thomas Kramer
//
// SPDX-License-Identifier: AGPL-3.0-or-later
//! Traits and datastructures for the representation of technology related properties,
//! especially design rules.
pub mod layerstack;
pub mod prelude;
pub mod rules;

View File

@@ -1,8 +0,0 @@
// SPDX-FileCopyrightText: 2022 Thomas Kramer
//
// SPDX-License-Identifier: AGPL-3.0-or-later
//! Helper to include all traits and structures related to design rules and technology descriptions.
pub use super::layerstack::*;
pub use super::rules::*;

View File

@@ -1,88 +0,0 @@
// Copyright (c) 2020-2021 Thomas Kramer.
// SPDX-FileCopyrightText: 2022 Thomas Kramer
//
// SPDX-License-Identifier: AGPL-3.0-or-later
//! Traits that define how certain design rules are represented.
//!
//! TBD
use crate::prelude::Orientation2D;
use num_traits::Num;
/// Define essential types used for expressing design rules.
pub trait RuleBase {
/// Type used as layer identifier.
type LayerId: Eq + Clone;
}
/// Define essential types used for expressing design rules based on distance relations.
pub trait DistanceRuleBase: RuleBase {
/// Type used to express distances.
type Distance: Num + Copy + PartialOrd;
/// Type used to express areas.
type Area: Num + Copy + PartialOrd;
}
/// Minimum spacing rules between shapes on the same layer.
pub trait MinimumSpacing: DistanceRuleBase {
/// Absolute minimum spacing between two shapes on the `layer`.
fn min_spacing_absolute(&self, layer: &Self::LayerId) -> Option<Self::Distance>;
/// Minimum spacing between two shapes on the `layer` dependent on the geometries.
fn min_spacing(
&self,
layer: &Self::LayerId,
run_length: Self::Distance,
width: Self::Distance,
) -> Option<Self::Distance>;
// Use another MinimumSpacing instance for same-net spacing.
// fn min_spacing_same_net(layer: &Self::LayerId) -> Self::Distance;
}
/// Minimum width rules.
pub trait MinimumWidth: DistanceRuleBase {
/// Minimal width of a shape with a certain length.
fn min_width(
&self,
layer: &Self::LayerId,
shape_length: Option<Self::Distance>,
) -> Option<Self::Distance>;
}
/// Default width rules.
pub trait DefaultWidth: DistanceRuleBase {
/// Default width of a wire segment of a certain length.
fn default_width(
&self,
layer: &Self::LayerId,
shape_length: Option<Self::Distance>,
) -> Option<Self::Distance>;
}
/// Preferred routing direction on metal layers.
pub trait PreferredRoutingDirection: RuleBase {
/// Get the preferred routing direction on this metal layer.
fn preferred_routing_direction(&self, layer: &Self::LayerId) -> Option<Orientation2D>;
}
/// Rules commonly used for routing.
pub trait RoutingRules:
PreferredRoutingDirection + DefaultWidth + MinimumSpacing + MinimumWidth
{
/// Get the default routing pitch on this layer for x and y directions.
fn default_pitch(&self, layer: &Self::LayerId) -> Option<(Self::Distance, Self::Distance)>;
/// Get the default routing pitch for wires with the preferred routing direction.
/// Return `None` if no default pitch or no routing direction is defined for this layer.
fn default_pitch_preferred_direction(&self, layer: &Self::LayerId) -> Option<Self::Distance> {
let pitch = self.default_pitch(layer)?;
let preferred_direction = self.preferred_routing_direction(layer)?;
match preferred_direction {
Orientation2D::Horizontal => Some(pitch.1),
Orientation2D::Vertical => Some(pitch.0),
}
}
}

View File

@@ -5,17 +5,10 @@
//! Re-export all traits defined in this crate.
pub use crate::hierarchy::traits::*;
pub use crate::l2n::*;
pub use crate::layout::traits::*;
pub use crate::netlist::traits::*;
/// Trait used for identifier types.
pub trait IdType: std::fmt::Debug + Clone + Eq + std::hash::Hash + 'static {}
impl<T> IdType for T where T: std::fmt::Debug + Clone + Eq + std::hash::Hash + 'static {}
/// Traid used for thread-safe.
pub trait IdTypeMT: IdType + Sync + Send {}
impl<T> IdTypeMT for T where T: IdType + Sync + Send {}
pub use crate::hierarchy::util::*;
pub use crate::layout::util::*;
pub use crate::netlist::util::*;
pub use libreda_core::l2n::*;
pub use libreda_core::layout::traits::*;
pub use libreda_core::netlist::traits::*;
pub use libreda_core::traits::*;

View File

@@ -17,10 +17,10 @@
//! For example if a cell is deleted this can be undone. The restored cell, pins, instances, etc.
//! will have the same properties but different IDs.
use crate::layout::prelude::{Geometry, SimpleTransform};
use crate::netlist::direction::Direction;
use crate::prelude::PropertyValue;
use crate::traits::*;
use libreda_core::netlist::direction::Direction;
use libreda_core::prelude::PropertyValue;
use libreda_core::prelude::{Geometry, SimpleTransform};
use libreda_core::traits::*;
use std::ops::Deref;
/// Undo operations on the netlist.

View File

@@ -11,9 +11,3 @@ fn chip_is_normal_type() {
use libreda_db::chip::Chip;
is_normal::<Chip>();
}
#[test]
fn rc_string_is_normal_type() {
use libreda_db::rc_string::RcString;
is_normal::<RcString>();
}

View File

@@ -249,6 +249,8 @@ fn test_rename_net() {
#[test]
fn test_flatten_circuit_instance() {
use libreda_db::prelude::*;
let mut chip = Chip::new();
// Create cells.