use itertools::Itertools;
use std::collections::{HashMap, HashSet};
use crate::index::*;
use crate::layout::types::*;
use crate::property_storage::PropertyStore;
use crate::rc_string::RcString;
use iron_shapes::CoordinateType;
use iron_shapes::shape::Geometry;
use iron_shapes::transform::SimpleTransform;
use crate::layout::traits::{LayoutBase, LayoutEdit};
use std::hash::Hash;
use std::borrow::Borrow;
pub type CellId<T> = Index<Cell<T>>;
pub type CellInstId<T> = Index<CellInstance<T>>;
pub type ShapeId<T> = Index<Shape<T>>;
pub type LayerId = Index<LayerInfo>;
#[derive(Default, Debug)]
pub struct Layout<C: CoordinateType> {
dbu: UInt,
cells: HashMap<CellId<C>, Cell<C>>,
cell_instances: HashMap<CellInstId<C>, CellInstance<C>>,
cell_index_generator: IndexGenerator<Cell<C>>,
cell_instance_index_generator: IndexGenerator<CellInstance<C>>,
shape_index_generator: IndexGenerator<Shape<C>>,
cells_by_name: HashMap<RcString, CellId<C>>,
layer_index_generator: IndexGenerator<LayerInfo>,
layers_by_name: HashMap<RcString, LayerId>,
layers_by_index_datatype: HashMap<(UInt, UInt), LayerId>,
layer_info: HashMap<LayerId, LayerInfo>,
property_storage: PropertyStore<RcString>,
}
#[derive(Clone, Hash, PartialEq, Debug)]
pub struct LayerInfo {
pub index: UInt,
pub datatype: UInt,
pub name: Option<RcString>,
}
#[derive(Clone, Debug)]
pub struct Cell<C: CoordinateType> {
name: RcString,
index: CellId<C>,
cell_instances: HashSet<CellInstId<C>>,
cell_instances_by_name: HashMap<RcString, CellInstId<C>>,
shapes_map: HashMap<LayerIndex, Shapes<C>>,
cell_references: HashSet<CellInstId<C>>,
dependencies: HashMap<CellId<C>, usize>,
dependent_cells: HashMap<CellId<C>, usize>,
cell_properties: PropertyStore<RcString>,
instance_properties: HashMap<CellInstId<C>, PropertyStore<RcString>>,
}
#[derive(Clone, Debug)]
pub struct CellInstance<C: CoordinateType> {
name: Option<RcString>,
parent_cell_id: CellId<C>,
id: CellInstId<C>,
template_cell: CellId<C>,
transform: SimpleTransform<C>,
}
#[derive(Clone, Debug)]
pub struct Shape<T: CoordinateType> {
index: Index<Self>,
pub geometry: Geometry<T>,
parent_id: Index<Shapes<T>>,
}
#[derive(Clone, Debug)]
pub struct Shapes<C>
where C: CoordinateType {
id: Index<Self>,
parent_cell: CellId<C>,
shapes: HashMap<ShapeId<C>, Shape<C>>,
shape_properties: HashMap<ShapeId<C>, PropertyStore<RcString>>,
}
impl<C: CoordinateType> LayoutBase for Layout<C> {
type Coord = C;
type NameType = RcString;
type LayerId = LayerId;
type CellId = CellId<C>;
type CellInstId = CellInstId<C>;
fn new() -> Self {
Layout {
dbu: 0,
cells: Default::default(),
cell_instances: Default::default(),
cell_index_generator: Default::default(),
cell_instance_index_generator: Default::default(),
shape_index_generator: Default::default(),
cells_by_name: Default::default(),
layer_index_generator: Default::default(),
layers_by_name: Default::default(),
layers_by_index_datatype: Default::default(),
layer_info: Default::default(),
property_storage: Default::default(),
}
}
fn cell_by_name<N: ?Sized + Eq + Hash>(&self, name: &N) -> Option<Self::CellId>
where Self::NameType: Borrow<N> {
self.cells_by_name.get(name).copied()
}
fn each_cell(&self) -> Box<dyn Iterator<Item=Self::CellId> + '_> {
Box::new(self.cells.keys().copied())
}
fn each_cell_instance(&self, cell: &Self::CellId) -> Box<dyn Iterator<Item=Self::CellInstId> + '_> {
Box::new(self.cells[cell].cell_instances.iter().copied())
}
fn each_dependent_cell(&self, cell: &Self::CellId) -> Box<dyn Iterator<Item=Self::CellId> + '_> {
Box::new(self.cells[cell].dependent_cells.keys().copied())
}
fn each_cell_dependency(&self, cell: &Self::CellId) -> Box<dyn Iterator<Item=Self::CellId> + '_> {
Box::new(self.cells[cell].dependencies.keys().copied())
}
fn parent_cell(&self, cell_instance: &Self::CellInstId) -> Self::CellId {
self.cell_instances[cell_instance].parent_cell_id
}
fn template_cell(&self, cell_instance: &Self::CellInstId) -> Self::CellId {
self.cell_instances[cell_instance].template_cell
}
fn find_layer(&self, index: u32, datatype: u32) -> Option<Self::LayerId> {
self.layers_by_index_datatype.get(&(index, datatype)).copied()
}
}
impl<C: CoordinateType> LayoutEdit for Layout<C> {
fn find_or_create_layer(&mut self, index: u32, datatype: u32) -> LayerId {
let layer = self.find_layer(index, datatype);
if let Some(layer) = layer {
layer
} else {
let layer_index = self.layer_index_generator.next();
self.layers_by_index_datatype.insert((index, datatype), layer_index);
let info = LayerInfo { index, datatype, name: None };
self.layer_info.insert(layer_index, info);
layer_index
}
}
fn create_cell(&mut self, name: RcString) -> CellId<C> {
assert!(!self.cells_by_name.contains_key(&name), "Cell with this name already exists.");
let id = self.cell_index_generator.next();
let cell = Cell {
name: name.clone(),
index: id,
cell_instances: Default::default(),
cell_instances_by_name: Default::default(),
shapes_map: Default::default(),
cell_references: Default::default(),
dependencies: Default::default(),
dependent_cells: Default::default(),
cell_properties: Default::default(),
instance_properties: Default::default(),
};
self.cells.insert(id, cell);
self.cells_by_name.insert(name, id);
id
}
fn remove_cell(&mut self, cell_id: &CellId<C>) {
let instances = self.cells[cell_id].cell_instances.iter().copied().collect_vec();
for inst in instances {
self.remove_cell_instance(&inst);
}
let references = self.cells[cell_id].cell_references.iter().copied().collect_vec();
for inst in references {
self.remove_cell_instance(&inst);
}
let name = self.cells[cell_id].name.clone();
self.cells_by_name.remove(&name).unwrap();
self.cells.remove(&cell_id).unwrap();
}
fn create_cell_instance(&mut self, parent_cell: &CellId<C>,
template_cell: &CellId<C>,
name: Option<RcString>,
transform: SimpleTransform<C>) -> CellInstId<C> {
let id = self.cell_instance_index_generator.next();
{
let mut stack: Vec<CellId<C>> = vec![*parent_cell];
while let Some(c) = stack.pop() {
if &c == template_cell {
panic!("Cannot create recursive instances.");
}
stack.extend(self.cells[&c].dependent_cells.keys().copied())
}
}
let inst = CellInstance {
name: name.clone(),
parent_cell_id: *parent_cell,
id: id,
template_cell: *template_cell,
transform: transform,
};
self.cell_instances.insert(id, inst);
self.cells.get_mut(parent_cell).unwrap().cell_instances.insert(id);
self.cells.get_mut(template_cell).unwrap().cell_references.insert(id);
if let Some(name) = name {
debug_assert!(!self.cells[parent_cell].cell_instances_by_name.contains_key(&name),
"Cell instance name already exists.");
self.cells.get_mut(parent_cell).unwrap().cell_instances_by_name.insert(name, id);
}
{
self.cells.get_mut(parent_cell).unwrap()
.dependencies.entry(*template_cell)
.and_modify(|c| *c += 1)
.or_insert(1);
}
{
self.cells.get_mut(template_cell).unwrap()
.dependent_cells.entry(*parent_cell)
.and_modify(|c| *c += 1)
.or_insert(1);
}
id
}
fn remove_cell_instance(&mut self, id: &CellInstId<C>) {
let parent = self.cell_instances[id].parent_cell_id;
let template = self.cell_instances[id].template_cell;
{
let parent_mut = self.cells.get_mut(&parent).unwrap();
let count = parent_mut.dependencies.entry(template)
.or_insert(0);
*count -= 1;
if *count == 0 {
parent_mut.dependencies.remove(&template);
}
}
{
let template_mut = self.cells.get_mut(&template).unwrap();
let count = template_mut.dependent_cells.entry(parent)
.or_insert(0);
*count -= 1;
if *count == 0 {
template_mut.dependent_cells.remove(&parent);
}
}
self.cell_instances.remove(&id).unwrap();
self.cells.get_mut(&parent).unwrap().cell_instances.remove(id);
self.cells.get_mut(&template).unwrap().cell_references.remove(id);
}
}