use crate::prelude::*;
use super::errors::LayoutDbError;
use std::collections::HashMap;
use std::rc::Rc;
use std::hash::Hash;
use std::borrow::Borrow;
use crate::property_storage::{PropertyStore, WithProperties};
use std::cell::RefCell;
#[derive(Default, Debug)]
pub struct Layout {
pub dbu: UInt,
cells: HashMap<CellIndex, Rc<Cell<Coord>>>,
cell_index_generator: CellIndexGenerator,
cells_by_name: HashMap<String, CellIndex>,
layer_index_generator: LayerIndexGenerator,
layers_by_name: HashMap<String, LayerIndex>,
layers_by_index_datatype: HashMap<(UInt, UInt), LayerIndex>,
layer_info: HashMap<LayerIndex, LayerInfo>,
property_storage: RefCell<PropertyStore<String>>
}
#[derive(Clone, Hash, PartialEq, Debug)]
pub struct LayerInfo {
pub index: UInt,
pub datatype: UInt,
pub name: Option<String>,
}
impl Layout {
pub fn new() -> Self {
let mut l = Layout::default();
l.dbu = 1000;
l
}
pub fn create_cell<S: Into<String>>(&mut self, cell_name: Option<S>) -> CellIndex {
let cell_name = cell_name.map(|n| n.into());
if let Some(cell_name) = &cell_name {
if let Some(_) = self.cell_by_name(cell_name.as_str()) {
panic!("Cell with this name already exists.");
}
}
let cell_index = self.cell_index_generator.next();
let cell = Cell::new(cell_name.to_owned(), cell_index);
let cell = Rc::new(cell);
*cell.self_reference.borrow_mut() = Rc::downgrade(&cell);
self.cells.insert(cell_index, cell);
if let Some(cell_name) = cell_name {
self.cells_by_name.insert(cell_name, cell_index);
}
cell_index
}
pub fn create_and_get_cell<S: Into<String>>(&mut self, cell_name: Option<S>) -> Rc<Cell<Coord>> {
let idx = self.create_cell(cell_name);
self.cell_by_index(idx).unwrap() }
#[inline(always)]
pub fn cell_index_by_name<S: ?Sized>(&self, cell_name: &S) -> Option<CellIndex>
where String: Borrow<S>,
S: Hash + Eq {
self.cells_by_name.get(cell_name).copied()
}
pub fn cell_by_index(&self, cell_index: CellIndex) -> Option<Rc<Cell<Coord>>> {
self.cells.get(&cell_index).cloned()
}
pub fn cell_by_name<S: ?Sized>(&self, cell_name: &S) -> Option<Rc<Cell<Coord>>>
where String: Borrow<S>,
S: Hash + Eq {
self.cell_index_by_name(cell_name)
.map(|i| self.cell_by_index(i).unwrap())
}
pub fn rename_cell<S: Into<String>>(&mut self, cell_index: CellIndex, new_name: Option<S>) -> Result<(), LayoutDbError> {
let new_name = new_name.map(|n| n.into());
let cell = self.cell_by_index(cell_index).ok_or(LayoutDbError::CellIndexNotFound)?;
let old_name = cell.name();
if new_name == old_name {
return Ok(());
}
if let Some(new_name) = &new_name {
if self.cells_by_name.contains_key(new_name) {
return Err(LayoutDbError::CellNameAlreadyExists(new_name.to_owned()));
}
}
cell.set_name(new_name.to_owned());
if let Some(old_name) = old_name {
self.cells_by_name.remove(&old_name);
}
if let Some(new_name) = new_name {
self.cells_by_name.insert(new_name, cell_index);
}
Ok(())
}
pub fn get_or_create_cell_by_name(&mut self, cell_name: &str) -> CellIndex {
match self.cell_index_by_name(cell_name) {
Some(c) => c,
None => self.create_cell(Some(cell_name))
}
}
pub fn each_cell(&self) -> impl Iterator<Item=&Rc<Cell<Coord>>> + ExactSizeIterator {
self.cells.values().into_iter()
}
pub fn has_cell<S: ?Sized>(&self, cell_name: &S) -> bool
where String: Borrow<S>,
S: Hash + Eq {
self.cells_by_name.contains_key(cell_name)
}
pub fn num_cells(&self) -> usize {
self.cells.len()
}
pub fn find_layer_by_name<S: ?Sized>(&self, name: &S) -> Option<LayerIndex>
where String: Borrow<S>,
S: Hash + Eq {
self.layers_by_name.get(name).copied()
}
pub fn find_layer(&self, index: UInt, datatype: UInt) -> Option<LayerIndex> {
self.layers_by_index_datatype.get(&(index, datatype)).copied()
}
pub fn find_or_create_layer(&mut self, index: UInt, datatype: UInt) -> LayerIndex {
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
}
}
pub fn get_layer_info(&self, layer_index: LayerIndex) -> Option<&LayerInfo> {
self.layer_info.get(&layer_index)
}
pub fn get_layer_info_mut(&mut self, layer_index: LayerIndex) -> Option<&mut LayerInfo> {
self.layer_info.get_mut(&layer_index)
}
pub fn set_layer_name(&mut self, layer_index: LayerIndex, name: Option<String>) -> () {
if let Some(i) = self.layer_info.get_mut(&layer_index) {
i.name = name
}
}
}
impl WithProperties for Layout {
type Key = String;
fn with_properties<F, R>(&self, f: F) -> R
where F: FnOnce(Option<&PropertyStore<Self::Key>>) -> R {
f(Some(&self.property_storage.borrow()))
}
fn with_properties_mut<F, R>(&self, f: F) -> R where F: FnOnce(&mut PropertyStore<Self::Key>) -> R {
f(&mut self.property_storage.borrow_mut())
}
}
#[test]
fn test_layout_properties() {
let layout = Layout::default();
layout.set_property("my_string_property".to_string(), "string_value".to_string());
assert!(!layout.property_str("my_string_property").is_none());
}