use scir::{NamedSliceOne, NetlistLibConversion, SliceOnePath};
use spice::Spice;
use std::sync::Arc;
use substrate::io::schematic::{NestedNode, Node};
use substrate::schematic::conv::{ConvertedNodePath, RawLib};
use substrate::schematic::{HasNestedView, InstancePath};
#[derive(Debug, Clone)]
pub struct DspfNodes<T> {
pub lib: RawLib<Spice>,
pub inner: Arc<T>,
}
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct DspfNestedNodes<T> {
pub dspf_instance: InstancePath,
pub inner: T,
}
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct DspfNode {
pub dspf_instance: InstancePath,
pub path: String,
}
pub trait HasNestedDspfView: Sized {
type Strings: ReconstructDspfView<Self>;
fn flatten(&self) -> (Vec<Node>, Vec<NestedNode>);
}
pub trait ReconstructDspfView<T> {
fn unflatten(source: &T, nodes: Vec<String>, nested_nodes: Vec<String>) -> Self;
}
impl<T> HasNestedView for DspfNodes<T>
where
T: HasNestedDspfView,
<T as HasNestedDspfView>::Strings: Send + Sync,
{
type NestedView = DspfNestedNodes<<T as HasNestedDspfView>::Strings>;
fn nested_view(&self, parent: &InstancePath) -> Self::NestedView {
let (nodes, nested_nodes) = self.inner.flatten();
let nodes = nodes
.into_iter()
.map(|n| {
let path = self.lib.convert_node(&n).unwrap();
let path = match path {
ConvertedNodePath::Cell(path) => path,
ConvertedNodePath::Primitive {
instances, port, ..
} => SliceOnePath::new(instances.clone(), NamedSliceOne::new(port.clone())),
};
let path = self.lib.scir.simplify_path(path);
Spice::node_path_with_prefix_and_separator(
&self.lib.scir,
&NetlistLibConversion::new(),
&path,
"X",
"/",
)
.to_uppercase()
})
.collect();
let nested_nodes = nested_nodes
.into_iter()
.map(|n| {
let path = self.lib.convert_node_path(&n.path()).unwrap();
let path = match path {
ConvertedNodePath::Cell(path) => path,
ConvertedNodePath::Primitive {
instances, port, ..
} => SliceOnePath::new(instances.clone(), NamedSliceOne::new(port.clone())),
};
let path = self.lib.scir.simplify_path(path);
Spice::node_path_with_prefix_and_separator(
&self.lib.scir,
&NetlistLibConversion::new(),
&path,
"X",
"/",
)
.to_uppercase()
})
.collect();
let inner = <T as HasNestedDspfView>::Strings::unflatten(&self.inner, nodes, nested_nodes);
DspfNestedNodes {
dspf_instance: parent.clone(),
inner,
}
}
}
impl<T> HasNestedView for DspfNestedNodes<T>
where
T: Send + Sync + Clone,
{
type NestedView = DspfNestedNodes<T>;
fn nested_view(&self, parent: &InstancePath) -> Self::NestedView {
Self {
dspf_instance: self.dspf_instance.prepend(parent),
inner: self.inner.clone(),
}
}
}
impl HasNestedDspfView for () {
type Strings = ();
fn flatten(&self) -> (Vec<Node>, Vec<NestedNode>) {
(Vec::new(), Vec::new())
}
}
impl ReconstructDspfView<()> for () {
fn unflatten(_source: &(), _nodes: Vec<String>, _nested_nodes: Vec<String>) -> Self {}
}