Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(sim): add Sky130CommercialSchema and simplify trait bounds #351

Merged
merged 3 commits into from
Dec 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion libs/scir/src/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
use crate::Instance;
use arcstr::ArcStr;
use serde::{Deserialize, Serialize};
use std::convert::Infallible;

/// A data format for storing SCIR libraries.
// TODO: Add method of validating primitive instances.
Expand Down Expand Up @@ -36,7 +37,7 @@ pub trait FromSchema<S: Schema + ?Sized>: Schema {
}

impl<S: Schema + ?Sized> FromSchema<S> for S {
type Error = ();
type Error = Infallible;

fn convert_primitive(
primitive: <S as Schema>::Primitive,
Expand Down
114 changes: 110 additions & 4 deletions pdks/sky130pdk/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#![warn(missing_docs)]

use std::collections::HashMap;
use std::convert::Infallible;
use std::path::PathBuf;

use arcstr::ArcStr;
Expand All @@ -16,7 +17,7 @@ use unicase::UniCase;

use crate::layers::Sky130Layers;
use crate::mos::{MosKind, MosParams};
use scir::schema::FromSchema;
use scir::schema::{FromSchema, Schema};
use scir::{Instance, ParamValue};
use spice::Spice;
use substrate::context::{ContextBuilder, Installation};
Expand Down Expand Up @@ -142,7 +143,7 @@ impl FromSchema<Spice> for Sky130Pdk {
}

impl FromSchema<Sky130Pdk> for Spice {
type Error = ();
type Error = Infallible;
fn convert_primitive(
primitive: <Sky130Pdk as scir::schema::Schema>::Primitive,
) -> Result<<Spice as scir::schema::Schema>::Primitive, Self::Error> {
Expand Down Expand Up @@ -188,7 +189,7 @@ impl FromSchema<Sky130Pdk> for Spice {
}

impl FromSchema<Sky130Pdk> for Ngspice {
type Error = ();
type Error = Infallible;
fn convert_primitive(
primitive: <Sky130Pdk as scir::schema::Schema>::Primitive,
) -> Result<<Ngspice as scir::schema::Schema>::Primitive, Self::Error> {
Expand All @@ -207,7 +208,108 @@ impl FromSchema<Sky130Pdk> for Ngspice {
}

impl FromSchema<Sky130Pdk> for Spectre {
type Error = ();
type Error = Infallible;
fn convert_primitive(
primitive: <Sky130Pdk as scir::schema::Schema>::Primitive,
) -> Result<<Spectre as scir::schema::Schema>::Primitive, Self::Error> {
Ok(match primitive {
Primitive::RawInstance {
cell,
ports,
params,
} => spectre::Primitive::RawInstance {
cell,
ports,
params,
},
Primitive::Mos { kind, params } => spectre::Primitive::RawInstance {
cell: kind.commercial_subckt(),
ports: vec!["D".into(), "G".into(), "S".into(), "B".into()],
params: HashMap::from_iter([
(arcstr::literal!("w"), Decimal::new(params.w, 3).into()),
(arcstr::literal!("l"), Decimal::new(params.l, 3).into()),
(arcstr::literal!("nf"), Decimal::from(params.nf).into()),
]),
},
})
}
fn convert_instance(
_instance: &mut Instance,
_primitive: &<Sky130Pdk as scir::schema::Schema>::Primitive,
) -> Result<(), Self::Error> {
Ok(())
}
}

impl scir::schema::Schema for Sky130CommercialSchema {
type Primitive = Primitive;
}

impl FromSchema<Sky130Pdk> for Sky130CommercialSchema {
type Error = Infallible;

fn convert_primitive(
primitive: <Sky130Pdk as Schema>::Primitive,
) -> Result<<Self as Schema>::Primitive, Self::Error> {
Ok(primitive)
}

fn convert_instance(
_instance: &mut Instance,
_primitive: &<Sky130Pdk as Schema>::Primitive,
) -> Result<(), Self::Error> {
Ok(())
}
}

impl FromSchema<Sky130CommercialSchema> for Spice {
type Error = Infallible;
fn convert_primitive(
primitive: <Sky130Pdk as scir::schema::Schema>::Primitive,
) -> Result<<Spice as scir::schema::Schema>::Primitive, Self::Error> {
Ok(match primitive {
Primitive::RawInstance {
cell,
ports,
params,
} => spice::Primitive::RawInstance {
cell,
ports,
params: params
.into_iter()
.map(|(k, v)| (UniCase::new(k), v))
.collect(),
},
Primitive::Mos { kind, params } => spice::Primitive::RawInstance {
cell: kind.commercial_subckt(),
ports: vec!["D".into(), "G".into(), "S".into(), "B".into()],
params: HashMap::from_iter([
(
UniCase::new(arcstr::literal!("w")),
Decimal::new(params.w, 3).into(),
),
(
UniCase::new(arcstr::literal!("l")),
Decimal::new(params.l, 3).into(),
),
(
UniCase::new(arcstr::literal!("nf")),
Decimal::from(params.nf).into(),
),
]),
},
})
}
fn convert_instance(
_instance: &mut Instance,
_primitive: &<Sky130Pdk as scir::schema::Schema>::Primitive,
) -> Result<(), Self::Error> {
Ok(())
}
}

impl FromSchema<Sky130CommercialSchema> for Spectre {
type Error = Infallible;
fn convert_primitive(
primitive: <Sky130Pdk as scir::schema::Schema>::Primitive,
) -> Result<<Spectre as scir::schema::Schema>::Primitive, Self::Error> {
Expand Down Expand Up @@ -247,6 +349,10 @@ pub struct Sky130Pdk {
commercial_root_dir: Option<PathBuf>,
}

/// A schema for the commercial PDK.
#[derive(Debug, Clone)]
pub struct Sky130CommercialSchema;

impl Sky130Pdk {
/// Creates an instantiation of the open PDK.
#[inline]
Expand Down
4 changes: 2 additions & 2 deletions substrate/src/simulation/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pub use codegen::FromSaved;
use substrate::schematic::ExportsNestedData;

use crate::schematic::Cell;
use crate::simulation::{Analysis, SimulationContext, Simulator, SupportedBy};
use crate::simulation::{Analysis, SimulationContext, Simulator};

/// A simulation output that can be recovered from the output of a particular analysis.
pub trait FromSaved<S: Simulator, A: Analysis> {
Expand Down Expand Up @@ -32,7 +32,7 @@ impl<S: Simulator, A: Analysis, T: FromSaved<S, A>> FromSaved<S, A> for Vec<T> {
///
/// `T` is any type that can be used as arguments for deciding what should be saved in
/// this simulation output.
pub trait Save<S: Simulator, A: SupportedBy<S>, T>: FromSaved<S, A> {
pub trait Save<S: Simulator, A: Analysis, T>: FromSaved<S, A> {
/// Marks the given output for saving, returning a key that can be used to recover
/// the output once the simulation is complete.
fn save(
Expand Down
6 changes: 3 additions & 3 deletions substrate/src/simulation/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ pub trait Simulator: Installation + Any + Send + Sync {
input: A,
) -> Result<A::Output, Self::Error>
where
A: Analysis + SupportedBy<Self>,
A: SupportedBy<Self>,
Self: Sized,
{
let mut inputs = Vec::new();
Expand Down Expand Up @@ -101,7 +101,7 @@ impl<S: Simulator, T: Testbench<S>> SimController<S, T> {
/// potentially causing simulator errors due to missing models.
///
/// If any PDK primitives are being used by the testbench, make sure to supply a corner.
pub fn simulate_default<A: Analysis + SupportedBy<S>>(
pub fn simulate_default<A: SupportedBy<S>>(
&self,
options: S::Options,
input: A,
Expand All @@ -115,7 +115,7 @@ impl<S: Simulator, T: Testbench<S>> SimController<S, T> {
/// potentially causing simulator errors due to missing models.
///
/// If any PDK primitives are being used by the testbench, make sure to supply a corner.
pub fn simulate<A: Analysis + SupportedBy<S>, O>(
pub fn simulate<A: SupportedBy<S>, O>(
&self,
mut options: S::Options,
input: A,
Expand Down
Loading