Skip to content

Commit

Permalink
fix converted node paths
Browse files Browse the repository at this point in the history
  • Loading branch information
rohanku committed Oct 26, 2023
1 parent 152b86f commit 9e7e16d
Show file tree
Hide file tree
Showing 5 changed files with 171 additions and 34 deletions.
51 changes: 37 additions & 14 deletions substrate/src/schematic/conv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,16 @@ pub(crate) struct ScirLibConversionBuilder {
pub(crate) cells: HashMap<CellId, SubstrateCellConversion>,
}

pub enum ConvertedNodePath {
Cell(scir::SliceOnePath),
Primitive {
id: scir::PrimitiveId,
instances: scir::InstancePath,
port: ArcStr,
index: usize,
},
}

impl ScirLibConversionBuilder {
fn new() -> Self {
Default::default()
Expand Down Expand Up @@ -109,17 +119,22 @@ impl<S: Schema> RawLib<S> {
}

/// Converts a Substrate [`NodePath`] to a SCIR [`scir::SliceOnePath`].
pub fn convert_node_path(&self, path: &NodePath) -> Option<scir::SliceOnePath> {
pub fn convert_node_path(&self, path: &NodePath) -> Option<ConvertedNodePath> {
let (instances, cell) = self.convert_instance_path_inner(path.top, &path.instances)?;

Some(match cell {
SubstrateCellConversionRef::Cell(cell) => {
scir::SliceOnePath::new(instances, *cell.signals.get(&path.node)?).into()
}
SubstrateCellConversionRef::Cell(cell) => ConvertedNodePath::Cell(
scir::SliceOnePath::new(instances, *cell.signals.get(&path.node)?),
),
SubstrateCellConversionRef::Primitive(p) => {
let prim = self.scir.primitive(p.primitive_id);
let (port, index) = p.ports.get(&path.node)?.first()?;
scir::SliceOnePath::new(instances, NamedSliceOne::with_index(port.clone(), *index))
ConvertedNodePath::Primitive {
id: p.primitive_id,
instances,
port: port.clone(),
index: *index,
}
}
})
}
Expand All @@ -135,7 +150,7 @@ impl<S: Schema> RawLib<S> {
///
/// Returns [`None`] if the path is invalid. Only flattened instances will
/// return more than one [`scir::SignalPath`].
pub fn convert_terminal_path(&self, path: &TerminalPath) -> Option<Vec<scir::SliceOnePath>> {
pub fn convert_terminal_path(&self, path: &TerminalPath) -> Option<Vec<ConvertedNodePath>> {
let mut cell = self.conv.cells.get(&path.top)?.as_ref();

let scir_id = self.scir.top_cell()?;
Expand Down Expand Up @@ -177,16 +192,20 @@ impl<S: Schema> RawLib<S> {
);
signals
} else {
vec![scir::SliceOnePath::new(instances, slice)]
vec![ConvertedNodePath::Cell(scir::SliceOnePath::new(
instances, slice,
))]
})
}
SubstrateCellConversionRef::Primitive(p) => {
let mut out = Vec::new();
for (port, index) in p.ports.get(&path.node)? {
out.push(scir::SliceOnePath::new(
instances.clone(),
NamedSliceOne::with_index(port.clone(), *index),
));
out.push(ConvertedNodePath::Primitive {
id: p.primitive_id,
instances: instances.clone(),
port: port.clone(),
index: *index,
});
}
Some(out)
}
Expand All @@ -201,7 +220,7 @@ impl<S: Schema> RawLib<S> {
id: scir::InstanceId,
slice: scir::SliceOne,
instances: &mut scir::InstancePath,
signals: &mut Vec<scir::SliceOnePath>,
signals: &mut Vec<ConvertedNodePath>,
) -> Option<()> {
instances.push(id);
let inst = parent_cell.instance(id);
Expand All @@ -222,13 +241,17 @@ impl<S: Schema> RawLib<S> {
};

if let Some(concat_index) = concat_index {
// TODO: Handle primitive case.
let child_cell = self.scir.cell(inst.child().into_cell()?);
let port = child_cell.port(name);
let port_slice = child_cell.signal(port.signal()).slice();
let tail = port_slice
.slice_one()
.unwrap_or_else(|| port_slice.index(concat_index));
signals.push(scir::SliceOnePath::new(instances.clone(), tail));
signals.push(ConvertedNodePath::Cell(scir::SliceOnePath::new(
instances.clone(),
tail,
)));
}
}
port_index += part.width();
Expand All @@ -246,7 +269,7 @@ impl<S: Schema> RawLib<S> {
parent_cell: &scir::Cell,
slice: scir::SliceOne,
instances: &mut scir::InstancePath,
signals: &mut Vec<scir::SliceOnePath>,
signals: &mut Vec<ConvertedNodePath>,
) -> Option<()> {
for (_, conv) in conv.instances.iter() {
match conv.instance.as_ref() {
Expand Down
16 changes: 6 additions & 10 deletions tests/src/hard_macro.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use serde::{Deserialize, Serialize};
use sky130pdk::Sky130Pdk;

use scir::netlist::{NetlistKind, NetlisterInstance};
#[cfg(feature = "spectre")]
use spectre::Spectre;
use spice::Spice;
use substrate::block::Block;
Expand Down Expand Up @@ -57,15 +56,12 @@ pub struct BufferInlineHardMacro;
fmt = "spice",
pdk = "Spice"
))]
#[cfg_attr(
feature = "spectre",
substrate(schematic(
source = "crate::paths::test_data(\"spice/vdivider_duplicate_subckt.spice\")",
name = "vdivider",
fmt = "spice",
pdk = "Spectre"
))
)]
#[substrate(schematic(
source = "crate::paths::test_data(\"spice/vdivider_duplicate_subckt.spice\")",
name = "vdivider",
fmt = "spice",
pdk = "Spectre"
))]
pub struct VdividerDuplicateSubckt;

#[test]
Expand Down
57 changes: 53 additions & 4 deletions tools/ngspice/src/tran.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ use crate::{node_voltage_path, Ngspice, ProbeStmt, SaveStmt};
use arcstr::ArcStr;
use rust_decimal::Decimal;
use scir::netlist::NetlistLibConversion;
use scir::SliceOnePath;
use scir::{NamedSliceOne, SliceOnePath};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::ops::Deref;
use std::sync::Arc;
use substrate::io::{NodePath, TerminalPath};
use substrate::schematic::conv::RawLib;
use substrate::schematic::conv::{ConvertedNodePath, RawLib};
use substrate::schematic::primitives::Resistor;
use substrate::schematic::{Cell, ExportsNestedData, NestedInstance};
use substrate::simulation::data::{FromSaved, HasSimData, Save};
Expand Down Expand Up @@ -153,6 +153,25 @@ impl Save<Ngspice, Tran, &SliceOnePath> for TranVoltage {
}
}

impl Save<Ngspice, Tran, &ConvertedNodePath> for TranVoltage {
fn save(
ctx: &SimulationContext<Ngspice>,
to_save: &ConvertedNodePath,
opts: &mut <Ngspice as Simulator>::Options,
) -> Self::Key {
Self::save(
ctx,
match to_save {
ConvertedNodePath::Cell(path) => path.clone(),
ConvertedNodePath::Primitive {
instances, port, ..
} => SliceOnePath::new(instances.clone(), NamedSliceOne::new(port.clone())),
},
opts,
)
}
}

impl Save<Ngspice, Tran, &NodePath> for TranVoltage {
fn save(
ctx: &SimulationContext<Ngspice>,
Expand All @@ -163,7 +182,7 @@ impl Save<Ngspice, Tran, &NodePath> for TranVoltage {
}
}

#[impl_dispatch({SliceOnePath; NodePath})]
#[impl_dispatch({SliceOnePath; ConvertedNodePath; NodePath})]
impl<T> Save<Ngspice, Tran, T> for TranVoltage {
fn save(
ctx: &SimulationContext<Ngspice>,
Expand Down Expand Up @@ -251,6 +270,25 @@ impl Save<Ngspice, Tran, &SliceOnePath> for TranCurrent {
}
}

impl Save<Ngspice, Tran, &ConvertedNodePath> for TranCurrent {
fn save(
ctx: &SimulationContext<Ngspice>,
to_save: &ConvertedNodePath,
opts: &mut <Ngspice as Simulator>::Options,
) -> Self::Key {
Self::save(
ctx,
match to_save {
ConvertedNodePath::Cell(path) => path.clone(),
ConvertedNodePath::Primitive {
instances, port, ..
} => SliceOnePath::new(instances.clone(), NamedSliceOne::new(port.clone())),
},
opts,
)
}
}

impl Save<Ngspice, Tran, &TerminalPath> for TranCurrent {
fn save(
ctx: &SimulationContext<Ngspice>,
Expand All @@ -268,7 +306,7 @@ impl Save<Ngspice, Tran, &TerminalPath> for TranCurrent {
}
}

#[impl_dispatch({SliceOnePath; TerminalPath})]
#[impl_dispatch({SliceOnePath; ConvertedNodePath; TerminalPath})]
impl<T> Save<Ngspice, Tran, T> for TranCurrent {
fn save(
ctx: &SimulationContext<Ngspice>,
Expand All @@ -295,6 +333,17 @@ impl HasSimData<SliceOnePath, Vec<f64>> for TranOutput {
}
}

impl HasSimData<ConvertedNodePath, Vec<f64>> for TranOutput {
fn get_data(&self, k: &ConvertedNodePath) -> Option<&Vec<f64>> {
self.get_data(&match k {
ConvertedNodePath::Cell(path) => path.clone(),
ConvertedNodePath::Primitive {
instances, port, ..
} => SliceOnePath::new(instances.clone(), NamedSliceOne::new(port.clone())),
})
}
}

impl HasSimData<NodePath, Vec<f64>> for TranOutput {
fn get_data(&self, k: &NodePath) -> Option<&Vec<f64>> {
self.get_data(&self.lib.convert_node_path(k)?)
Expand Down
24 changes: 22 additions & 2 deletions tools/spectre/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,12 @@ use error::*;
use rust_decimal::Decimal;
use scir::netlist::{Include, NetlistKind, NetlistLibConversion, NetlisterInstance, RenameGround};
use scir::schema::{FromSchema, NoSchema, NoSchemaError};
use scir::{Library, ParamValue, SliceOnePath};
use scir::{Library, NamedSliceOne, ParamValue, SliceOnePath};
use serde::{Deserialize, Serialize};
use substrate::block::Block;
use substrate::execute::Executor;
use substrate::io::{NestedNode, NodePath, SchematicType};
use substrate::schematic::conv::ConvertedNodePath;
use substrate::schematic::primitives::{Capacitor, RawInstance, Resistor};
use substrate::schematic::schema::Schema;
use substrate::schematic::{Primitive, PrimitiveSchematic};
Expand Down Expand Up @@ -187,6 +188,25 @@ impl SetInitialCondition<&SliceOnePath, Decimal, Spectre> for Options {
}
}

impl SetInitialCondition<&ConvertedNodePath, Decimal, Spectre> for Options {
fn set_initial_condition(
&mut self,
key: &ConvertedNodePath,
value: Decimal,
_ctx: &SimulationContext<Spectre>,
) {
self.set_ic_inner(
SimSignal::ScirVoltage(match key {
ConvertedNodePath::Cell(path) => path.clone(),
ConvertedNodePath::Primitive {
instances, port, ..
} => SliceOnePath::new(instances.clone(), NamedSliceOne::new(port.clone())),
}),
value,
);
}
}

impl SetInitialCondition<&NodePath, Decimal, Spectre> for Options {
fn set_initial_condition(
&mut self,
Expand Down Expand Up @@ -220,7 +240,7 @@ impl SetInitialCondition<NestedNode, Decimal, Spectre> for Options {
}
}

#[impl_dispatch({SliceOnePath; NodePath})]
#[impl_dispatch({SliceOnePath; ConvertedNodePath; NodePath})]
impl<T> SetInitialCondition<T, Decimal, Spectre> for Options {
fn set_initial_condition(&mut self, key: T, value: Decimal, ctx: &SimulationContext<Spectre>) {
self.set_initial_condition(&key, value, ctx);
Expand Down
Loading

0 comments on commit 9e7e16d

Please sign in to comment.