use parking_lot::RwLock;
use std::sync::{Arc, Weak};
use indexmap::IndexMap;
use crate::mod_def::ModDefCore;
use crate::mod_inst::HierPathElem;
use crate::{ConvertibleToPortSliceVec, MetadataKey, MetadataValue, ModDef, ModInst, PortSlice};
mod connect;
mod copy;
mod crossover;
mod debug;
mod export;
mod feedthrough;
mod subdivide;
mod tieoff;
mod width;
#[derive(Clone)]
pub enum Intf {
ModDef {
name: String,
mod_def_core: Weak<RwLock<ModDefCore>>,
},
ModInst {
intf_name: String,
hierarchy: Vec<HierPathElem>,
},
}
impl Intf {
pub fn name(&self) -> &str {
match self {
Intf::ModDef { name, .. } => name,
Intf::ModInst { intf_name, .. } => intf_name,
}
}
pub(crate) fn get_mod_def_core(&self) -> Arc<RwLock<ModDefCore>> {
match self {
Intf::ModDef { mod_def_core, .. } => mod_def_core.upgrade().unwrap(),
Intf::ModInst { hierarchy, .. } => hierarchy
.last()
.expect("Intf::ModInst hierarchy cannot be empty")
.mod_def_core
.upgrade()
.expect("Containing ModDefCore has been dropped"),
}
}
pub(crate) fn get_port_slices(&self) -> IndexMap<String, PortSlice> {
match self {
Intf::ModDef {
mod_def_core, name, ..
} => {
let core = mod_def_core.upgrade().unwrap();
let binding = core.read();
let mod_def = ModDef { core: core.clone() };
let mapping = binding.interfaces.get(name).unwrap();
mapping
.iter()
.map(|(func_name, (port_name, msb, lsb))| {
(
func_name.clone(),
mod_def.get_port_slice(port_name, *msb, *lsb),
)
})
.collect()
}
Intf::ModInst {
intf_name,
hierarchy,
..
} => {
let inst = ModInst {
hierarchy: hierarchy.clone(),
};
let inst_core = inst.mod_def_core_of_instance();
let inst_binding = inst_core.read();
let inst_mapping = inst_binding.interfaces.get(intf_name).unwrap();
inst_mapping
.iter()
.map(|(func_name, (port_name, msb, lsb))| {
(
func_name.clone(),
inst.get_port_slice(port_name, *msb, *lsb),
)
})
.collect()
}
}
}
pub fn set_max_distance(&self, max_distance: Option<i64>) {
for (_, port_slice) in self.get_port_slices() {
port_slice.set_max_distance(max_distance);
}
}
pub fn get(&self, func_name: impl AsRef<str>) -> Option<PortSlice> {
let func_name = func_name.as_ref();
match self {
Intf::ModDef {
mod_def_core, name, ..
} => {
let core = mod_def_core.upgrade().unwrap();
let binding = core.read();
let mod_def = ModDef { core: core.clone() };
let mapping = binding.interfaces.get(name)?;
mapping
.get(func_name)
.map(|(port_name, msb, lsb)| mod_def.get_port_slice(port_name, *msb, *lsb))
}
Intf::ModInst {
intf_name,
hierarchy,
..
} => {
let inst = ModInst {
hierarchy: hierarchy.clone(),
};
let inst_core = inst.mod_def_core_of_instance();
let inst_binding = inst_core.read();
let inst_mapping = inst_binding.interfaces.get(intf_name)?;
inst_mapping
.get(func_name)
.map(|(port_name, msb, lsb)| inst.get_port_slice(port_name, *msb, *lsb))
}
}
}
pub fn remove(&self, func_name: impl AsRef<str>) -> Option<PortSlice> {
let func_name = func_name.as_ref();
match self {
Intf::ModDef {
mod_def_core, name, ..
} => {
let core = mod_def_core.upgrade().unwrap();
let mod_def = ModDef { core: core.clone() };
let removed = {
let mut binding = core.write();
let mapping = binding.interfaces.get_mut(name)?;
mapping.shift_remove(func_name)
};
removed.map(|(port_name, msb, lsb)| mod_def.get_port_slice(&port_name, msb, lsb))
}
Intf::ModInst {
intf_name,
hierarchy,
..
} => {
let inst = ModInst {
hierarchy: hierarchy.clone(),
};
let inst_core = inst.mod_def_core_of_instance();
let removed = {
let mut inst_binding = inst_core.write();
let inst_mapping = inst_binding.interfaces.get_mut(intf_name)?;
inst_mapping.shift_remove(func_name)
};
removed.map(|(port_name, msb, lsb)| inst.get_port_slice(&port_name, msb, lsb))
}
}
}
pub fn iter(&self) -> indexmap::map::IntoIter<String, PortSlice> {
self.get_port_slices().into_iter()
}
pub fn keys(&self) -> indexmap::map::IntoKeys<String, PortSlice> {
self.get_port_slices().into_keys()
}
pub fn values(&self) -> indexmap::map::IntoValues<String, PortSlice> {
self.get_port_slices().into_values()
}
pub(crate) fn get_intf_name(&self) -> String {
match self {
Intf::ModDef { name, .. } => name.clone(),
Intf::ModInst { intf_name, .. } => intf_name.clone(),
}
}
pub fn set_metadata(
&self,
key: impl Into<MetadataKey>,
value: impl Into<MetadataValue>,
) -> Self {
let key = key.into();
let value = value.into();
match self {
Intf::ModDef { .. } => {
let core_rc = self.get_mod_def_core();
let mut core = core_rc.write();
core.mod_def_intf_metadata
.entry(self.get_intf_name())
.or_default()
.insert(key, value);
}
Intf::ModInst { hierarchy, .. } => {
let inst_name = hierarchy
.last()
.expect("Intf::ModInst hierarchy cannot be empty")
.inst_name
.to_string();
let core_rc = self.get_mod_def_core();
let mut core = core_rc.write();
core.mod_inst_intf_metadata
.entry(inst_name)
.or_default()
.entry(self.get_intf_name())
.or_default()
.insert(key, value);
}
}
self.clone()
}
pub fn get_metadata(&self, key: impl AsRef<str>) -> Option<MetadataValue> {
match self {
Intf::ModDef { .. } => {
let core_rc = self.get_mod_def_core();
let core = core_rc.read();
core.mod_def_intf_metadata
.get(&self.get_intf_name())
.and_then(|metadata| metadata.get(key.as_ref()).cloned())
}
Intf::ModInst { hierarchy, .. } => {
let inst_name = hierarchy
.last()
.expect("Intf::ModInst hierarchy cannot be empty")
.inst_name
.as_str();
let core_rc = self.get_mod_def_core();
let core = core_rc.read();
core.mod_inst_intf_metadata
.get(inst_name)
.and_then(|intfs| intfs.get(&self.get_intf_name()))
.and_then(|metadata| metadata.get(key.as_ref()).cloned())
}
}
}
pub fn clear_metadata(&self, key: impl AsRef<str>) -> Self {
match self {
Intf::ModDef { .. } => {
let core_rc = self.get_mod_def_core();
let mut core = core_rc.write();
if let Some(metadata) = core.mod_def_intf_metadata.get_mut(&self.get_intf_name()) {
metadata.remove(key.as_ref());
if metadata.is_empty() {
core.mod_def_intf_metadata.remove(&self.get_intf_name());
}
}
}
Intf::ModInst { hierarchy, .. } => {
let inst_name = hierarchy
.last()
.expect("Intf::ModInst hierarchy cannot be empty")
.inst_name
.as_str();
let core_rc = self.get_mod_def_core();
let mut core = core_rc.write();
if let Some(intfs) = core.mod_inst_intf_metadata.get_mut(inst_name) {
let intf_name = self.get_intf_name();
if let Some(metadata) = intfs.get_mut(&intf_name) {
metadata.remove(key.as_ref());
if metadata.is_empty() {
intfs.remove(&intf_name);
}
}
if intfs.is_empty() {
core.mod_inst_intf_metadata.remove(inst_name);
}
}
}
}
self.clone()
}
}
impl ConvertibleToPortSliceVec for Intf {
fn to_port_slice_vec(&self) -> Vec<PortSlice> {
self.get_port_slices().into_values().collect()
}
}