Skip to content

Commit

Permalink
feat(primitives): revamp schematic primitives (#291)
Browse files Browse the repository at this point in the history
* feat(primitives): revamp schematic primitives

* make substrate compile by adding todos

* get substrate doctests to compile

* try to get tests compiling, running into issue with type system

* checkpoint working implementation

* start fixing tests

* wip

* all tests compiling

* fix nested node api

* remove terminals method

* test tree of schematic implementations

* continue working on SCIR and update enumify

* finish new SCIR implementation

* fix minor SCIR issues and work on fixing Substrate

* get everything to compile

* checkpoint old design

* tests compiling with new schema design

* conversion to SCIR working

* fix spectre netlister

* all tests passing

* improve enumify docs

* clean up enumify code

* finish cleaning up code

* clean up cache API

* clean up cache code

* clean up SCIR and spice libraries

* clean up sky130 PDK and work on simulators

* fix primitives

* fix SCIR cell with IO

* fix all TODOs

* revert to old ngspice test

* get terminal currents working for primitives

* fix spectre tests

* add trace for errors

* fix tests

* fix instance names

* print path

* fix instance names

* fix converted node paths

* fix width and length conversions

* fix tests, lint, and docs

* fix lint and remove schematic hard macro procedural macros

* fix tests

* fix scir tests

* fix substrate doctest

* fix blackbox implementation

* fix spectre tests

* fix lint

* simplify spice primitives

* refactor primitives

* update documentation and naming

* fix format
  • Loading branch information
rohanku authored Nov 2, 2023
1 parent eaf4cc4 commit e5ba06a
Show file tree
Hide file tree
Showing 85 changed files with 8,096 additions and 5,133 deletions.
16 changes: 14 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions codegen/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ serde = { version = "1", features = ["derive"] }
substrate = { version = "<=0.6.1", registry = "substrate", path = "../substrate" }
sky130pdk = { version = "<=0.6.1", registry = "substrate", path = "../pdks/sky130pdk" }
spectre = { version = "<=0.6.1", registry = "substrate", path = "../tools/spectre" }
spice = { version = "<=0.4.0", registry = "substrate", path = "../libs/spice" }

[lib]
proc-macro = true
14 changes: 3 additions & 11 deletions codegen/src/block/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -226,20 +226,12 @@ impl ToTokens for DataInputReceiver {
}

#[derive(Debug, FromDeriveInput)]
#[darling(attributes(substrate), supports(any))]
#[darling(attributes(substrate), supports(any), allow_unknown_fields)]
pub struct HasLayoutInputReceiver {
ident: syn::Ident,
generics: syn::Generics,
#[allow(unused)]
io: darling::util::Ignored,
#[darling(multiple)]
#[allow(unused)]
schematic: Vec<darling::util::Ignored>,
#[darling(multiple)]
layout: Vec<LayoutHardMacro>,
#[darling(default)]
#[allow(unused)]
flatten: darling::util::Ignored,
}

#[derive(Debug, FromMeta)]
Expand All @@ -264,7 +256,7 @@ impl ToTokens for HasLayoutInputReceiver {

let has_layout = quote! {
impl #imp #substrate::layout::ExportsLayoutData for #ident #ty #wher {
type Data = ();
type LayoutData = ();
}
};

Expand All @@ -286,7 +278,7 @@ impl ToTokens for HasLayoutInputReceiver {
&self,
io: &mut <<Self as #substrate::block::Block>::Io as #substrate::io::LayoutType>::Builder,
cell: &mut #substrate::layout::CellBuilder<#pdk, Self>,
) -> #substrate::error::Result<Self::Data> {
) -> #substrate::error::Result<Self::LayoutData> {

let source = { #source };

Expand Down
10 changes: 3 additions & 7 deletions codegen/src/block/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,10 @@ pub struct BlockInputReceiver {
ident: syn::Ident,
generics: syn::Generics,
io: syn::Type,
#[darling(multiple)]
#[allow(unused)]
schematic: Vec<darling::util::Ignored>,
kind: syn::Ident,
#[darling(multiple)]
#[allow(unused)]
layout: Vec<darling::util::Ignored>,
#[darling(default)]
flatten: bool,
}

impl ToTokens for BlockInputReceiver {
Expand All @@ -32,7 +28,7 @@ impl ToTokens for BlockInputReceiver {
ref ident,
ref generics,
ref io,
flatten,
ref kind,
..
} = *self;

Expand All @@ -54,7 +50,7 @@ impl ToTokens for BlockInputReceiver {
tokens.extend(quote! {
impl #imp #substrate::block::Block for #ident #ty #wher {
type Io = #io;
const FLATTEN: bool = #flatten;
type Kind = #substrate::block::#kind;

fn id() -> #substrate::arcstr::ArcStr {
#substrate::arcstr::literal!(::std::concat!(::std::module_path!(), "::", ::std::stringify!(#ident)))
Expand Down
151 changes: 12 additions & 139 deletions codegen/src/block/schematic.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
use darling::ast::{Fields, Style};
use darling::{ast, FromDeriveInput, FromField, FromMeta, FromVariant};
use darling::{ast, FromDeriveInput, FromField, FromVariant};
use proc_macro2::TokenStream;
use quote::{format_ident, quote, ToTokens};
use syn::parse_quote;

use crate::substrate_ident;
use type_dispatch::derive::{add_trait_bounds, struct_body};
Expand Down Expand Up @@ -93,7 +92,7 @@ fn transform_field_decl(_idx: usize, field: &DataField) -> TokenStream {
ref attrs,
} = field;
let substrate = substrate_ident();
let field_ty = quote!(#substrate::schematic::NestedView<'__substrate_derive_lifetime, #ty>);
let field_ty = quote!(#substrate::schematic::NestedView<#ty>);

match ident {
Some(ident) => {
Expand Down Expand Up @@ -147,12 +146,8 @@ impl ToTokens for DataInputReceiver {

let mut generics = generics.clone();
add_trait_bounds(&mut generics, quote!(#substrate::schematic::HasNestedView));
let lifetime: syn::GenericParam = parse_quote!('__substrate_derive_lifetime);
let mut ref_generics = generics.clone();
ref_generics.params.push(lifetime.clone());

let (imp, ty, wher) = generics.split_for_impl();
let (_ref_imp, ref_ty, _ref_wher) = ref_generics.split_for_impl();
let transformed_ident = format_ident!("{}NestedView", ident);

let expanded = match data {
Expand All @@ -174,15 +169,15 @@ impl ToTokens for DataInputReceiver {

quote! {
#(#attrs)*
#vis struct #transformed_ident #ref_generics #body
#vis struct #transformed_ident #generics #body

impl #imp #substrate::schematic::HasNestedView for #ident #ty #wher {
type NestedView<#lifetime> = #transformed_ident #ref_ty;
type NestedView = #transformed_ident #ty;

fn nested_view<#lifetime>(
&#lifetime self,
fn nested_view(
&self,
__substrate_derive_parent: &#substrate::schematic::InstancePath,
) -> Self::NestedView<#lifetime> {
) -> Self::NestedView {
#retval
}
}
Expand All @@ -195,16 +190,16 @@ impl ToTokens for DataInputReceiver {
.map(|v| transform_variant_match_arm(transformed_ident.clone(), v));
quote! {
#(#attrs)*
#vis enum #transformed_ident #ref_generics {
#vis enum #transformed_ident #generics {
#( #decls )*
}
impl #imp #substrate::schematic::HasNestedView for #ident #ty #wher {
type NestedView<#lifetime> = #transformed_ident #ref_ty;
type NestedView = #transformed_ident #ty;

fn nested_view<#lifetime>(
&#lifetime self,
fn nested_view(
&self,
__substrate_derive_parent: &#substrate::schematic::InstancePath,
) -> Self::NestedView<#lifetime> {
) -> Self::NestedView {
match self {
#(#arms)*
}
Expand All @@ -219,125 +214,3 @@ impl ToTokens for DataInputReceiver {
});
}
}

#[derive(Debug, FromDeriveInput)]
#[darling(attributes(substrate), supports(any))]
pub struct HasSchematicInputReceiver {
ident: syn::Ident,
generics: syn::Generics,
#[allow(unused)]
io: darling::util::Ignored,
#[darling(multiple)]
#[allow(unused)]
layout: Vec<darling::util::Ignored>,
#[darling(multiple)]
schematic: Vec<SchematicHardMacro>,
#[darling(default)]
#[allow(unused)]
flatten: darling::util::Ignored,
}

#[derive(Debug, FromMeta)]
pub struct SchematicHardMacro {
source: syn::Expr,
fmt: darling::util::SpannedValue<String>,
pdk: syn::Type,
name: String,
}

impl ToTokens for HasSchematicInputReceiver {
fn to_tokens(&self, tokens: &mut TokenStream) {
let substrate = substrate_ident();
let HasSchematicInputReceiver {
ref ident,
ref generics,
ref schematic,
..
} = *self;

let (imp, ty, wher) = generics.split_for_impl();

let has_schematic = quote! {
impl #imp #substrate::schematic::ExportsSchematicData for #ident #ty #wher {
type Data = ();
}
};

let has_schematic_impls = schematic.iter().map(|schematic| {
let SchematicHardMacro { source, fmt, pdk, name } = schematic;

let parsed_to_scir = quote! {
let mut conv = #substrate::spice::parser::conv::ScirConverter::new(::std::stringify!(#ident), &parsed.ast);

for prim in cell.ctx.pdk.schematic_primitives() {
conv.blackbox(#substrate::arcstr::Substr::full(prim));
}

let lib = ::std::sync::Arc::new(conv.convert().unwrap());
let cell_id = lib.cell_id_named(#name);

(lib, cell_id)
};

// The SCIR token stream must create two variables:
// * lib, of type Arc<scir::Library>
// * cell_id, of type scir::CellId
// The token stream has access to source.
let scir = match fmt.as_str() {
"spice" => quote! {
let parsed = #substrate::spice::parser::Parser::parse_file(source).unwrap();
#parsed_to_scir
},
"inline-spice" | "inline_spice" => quote! {
let parsed = #substrate::spice::parser::Parser::parse(source).unwrap();
#parsed_to_scir
},
fmtstr => proc_macro_error::abort!(fmt.span(), "unsupported schematic hard macro format: `{}`", fmtstr),
};

quote! {
impl #imp #substrate::schematic::Schematic<#pdk> for #ident #ty #wher {
fn schematic(
&self,
io: &<<Self as #substrate::block::Block>::Io as #substrate::io::SchematicType>::Bundle,
cell: &mut #substrate::schematic::CellBuilder<#pdk, Self>,
) -> #substrate::error::Result<Self::Data> {
use #substrate::pdk::Pdk;

let source = {
#source
};

let (lib, cell_id) = { #scir };

use #substrate::io::StructData;
let connections: ::std::collections::HashMap<#substrate::arcstr::ArcStr, ::std::vec::Vec<#substrate::io::Node>> =
::std::collections::HashMap::from_iter(io.fields().into_iter().map(|f| {
let nodes = io.field_nodes(&f).unwrap();
(f, nodes)
}));

cell.add_primitive(#substrate::schematic::PrimitiveDevice::new(
#substrate::schematic::PrimitiveDeviceKind::ScirInstance {
lib,
cell: cell_id,
connections,
}
));
Ok(())
}
}
}
});

let expanded = quote! {
#has_schematic

#(#has_schematic_impls)*
};

tokens.extend(quote! {
#expanded
});
}
}
Loading

0 comments on commit e5ba06a

Please sign in to comment.