Skip to content

Commit

Permalink
add dataview api and clean up codegen
Browse files Browse the repository at this point in the history
  • Loading branch information
rohanku committed Dec 9, 2024
1 parent c0e44c4 commit 0461b9d
Show file tree
Hide file tree
Showing 11 changed files with 317 additions and 144 deletions.
1 change: 0 additions & 1 deletion Cargo.lock

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

1 change: 0 additions & 1 deletion codegen/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ type_dispatch = { version = "0.3.0", registry = "substrate", path = "../libs/typ

[dev-dependencies]
arcstr = "1"
serde = { version = "1", features = ["derive"] }
substrate = { version = "<=0.8.1", registry = "substrate", path = "../substrate" }
sky130pdk = { version = "<=0.8.1", registry = "substrate", path = "../pdks/sky130pdk" }
spectre = { version = "<=0.9.1", registry = "substrate", path = "../tools/spectre" }
Expand Down
5 changes: 0 additions & 5 deletions codegen/src/block/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,6 @@ impl ToTokens for BlockInputReceiver {
} = *self;

let mut generics = generics.clone();
add_trait_bounds(&mut generics, quote!(#substrate::serde::Serialize));
add_trait_bounds(
&mut generics,
quote!(#substrate::serde::de::DeserializeOwned),
);
add_trait_bounds(&mut generics, quote!(::std::hash::Hash));
add_trait_bounds(&mut generics, quote!(::std::cmp::Eq));
add_trait_bounds(&mut generics, quote!(::std::marker::Send));
Expand Down
165 changes: 130 additions & 35 deletions codegen/src/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,19 +67,25 @@ pub(crate) fn schematic_io(input: &IoInputReceiver) -> TokenStream {
let mut data_fields = Vec::new();
let mut terminal_view_fields = Vec::new();
let mut construct_data_fields = Vec::new();
let mut construct_data_ty_fields = Vec::new();
let mut construct_data_nested_ty_fields = Vec::new();
let mut construct_terminal_view_fields = Vec::new();
let mut instantiate_fields = Vec::new();
let mut flatten_dir_fields = Vec::new();
let mut construct_terminal_view_ty_fields = Vec::new();
let mut construct_terminal_view_nested_ty_fields = Vec::new();
let mut instantiate_nodes_fields = Vec::new();
let mut instantiate_terminals_fields = Vec::new();
let mut flatten_node_fields = Vec::new();
let mut terminal_view_flatten_node_fields = Vec::new();
let mut field_list_elems = Vec::new();
let mut field_match_arms = Vec::new();
let mut terminal_view_flatten_terminal_fields = Vec::new();

let data_ident = format_ident!("{}Bundle", ident);
let data_ident = format_ident!("{}NodeBundle", ident);
let data_nested_ident = format_ident!("{}Nested", data_ident);
let terminal_view_ident = format_ident!("{}TerminalBundle", ident);
let terminal_view_nested_ident = format_ident!("{}Nested", terminal_view_ident);

for (i, &f) in fields.iter().enumerate() {
let field_ty = &f.ty;
let field_ty = quote! { <#field_ty as #substrate::types::HasBundleKind>::BundleKind };
let field_vis = &f.vis;
let field_ident = &f.ident;
let attrs = &f.attrs;
Expand Down Expand Up @@ -117,39 +123,49 @@ pub(crate) fn schematic_io(input: &IoInputReceiver) -> TokenStream {
);

data_len.push(quote! {
<<#field_ty as #substrate::types::schematic::SchematicBundleKind>::Bundle as #substrate::io::FlatLen>::len(&#refer)
<<#field_ty as #substrate::types::schematic::SchematicBundleKind>::NodeBundle as #substrate::types::FlatLen>::len(&#refer)
});
terminal_data_len.push(quote! {
<<<#field_ty as #substrate::types::schematic::SchematicBundleKind>::Bundle as #substrate::types::schematic::HasTerminalView>::TerminalView as #substrate::io::FlatLen>::len(&#refer)
<<#field_ty as #substrate::types::schematic::SchematicBundleKind>::TerminalBundle as #substrate::types::FlatLen>::len(&#refer)
});
data_fields.push(quote! {
#declare <#field_ty as #substrate::types::schematic::SchematicBundleKind>::Bundle,
#declare <#field_ty as #substrate::types::schematic::SchematicBundleKind>::NodeBundle,
});
terminal_view_fields.push(quote! {
#declare #substrate::types::schematic::TerminalView<<#field_ty as #substrate::types::schematic::SchematicBundleKind>::Bundle>,
#declare <#field_ty as #substrate::types::schematic::SchematicBundleKind>::TerminalBundle,
});
construct_data_fields.push(quote! {
#assign #temp,
});
construct_data_ty_fields.push(quote! {
#assign <<#field_ty as #substrate::types::schematic::SchematicBundleKind>::NodeBundle as #substrate::types::HasBundleKind>::kind(&#refer),
});
construct_data_nested_ty_fields.push(quote! {
#assign <#substrate::schematic::NestedView<<#field_ty as #substrate::types::schematic::SchematicBundleKind>::NodeBundle> as #substrate::types::HasBundleKind>::kind(&#refer),
});
construct_terminal_view_fields.push(quote! {
#assign <<#field_ty as #substrate::types::schematic::SchematicBundleKind>::Bundle as #substrate::types::schematic::HasTerminalView>::terminal_view(cell, &#cell_io_refer, instance, &#instance_io_refer),
#assign <#field_ty as #substrate::types::schematic::SchematicBundleKind>::terminal_view(cell, &#cell_io_refer, instance, &#instance_io_refer),
});
instantiate_fields.push(quote! {
let (#temp, __substrate_node_ids) = <#field_ty as #substrate::types::schematic::SchematicBundleKind>::instantiate(&#refer, __substrate_node_ids);
construct_terminal_view_ty_fields.push(quote! {
#assign <<#field_ty as #substrate::types::schematic::SchematicBundleKind>::TerminalBundle as #substrate::types::HasBundleKind>::kind(&#refer),
});
flatten_dir_fields.push(quote! {
<#field_ty as #substrate::io::Flatten<#substrate::io::Direction>>::flatten(&#refer, __substrate_output_sink);
construct_terminal_view_nested_ty_fields.push(quote! {
#assign <#substrate::schematic::NestedView<<#field_ty as #substrate::types::schematic::SchematicBundleKind>::TerminalBundle> as #substrate::types::HasBundleKind>::kind(&#refer),
});
instantiate_nodes_fields.push(quote! {
let (#temp, __substrate_node_ids) = <#field_ty as #substrate::types::schematic::SchematicBundleKind>::instantiate_nodes(&#refer, __substrate_node_ids);
});
instantiate_terminals_fields.push(quote! {
let (#temp, __substrate_node_ids) = <#field_ty as #substrate::types::schematic::SchematicBundleKind>::instantiate_terminals(&#refer, __substrate_node_ids);
});
flatten_node_fields.push(quote! {
<<#field_ty as #substrate::types::schematic::SchematicBundleKind>::Bundle as #substrate::io::Flatten<#substrate::types::schematic::Node>>::flatten(&#refer, __substrate_output_sink);
<<#field_ty as #substrate::types::schematic::SchematicBundleKind>::NodeBundle as #substrate::types::Flatten<#substrate::types::schematic::Node>>::flatten(&#refer, __substrate_output_sink);
});
terminal_view_flatten_node_fields.push(quote! {
<<<#field_ty as #substrate::types::schematic::SchematicBundleKind>::Bundle as #substrate::types::schematic::HasTerminalView>::TerminalView as #substrate::io::Flatten<#substrate::types::schematic::Node>>::flatten(&#refer, __substrate_output_sink);
<<#field_ty as #substrate::types::schematic::SchematicBundleKind>::TerminalBundle as #substrate::types::Flatten<#substrate::types::schematic::Node>>::flatten(&#refer, __substrate_output_sink);
});
field_list_elems
.push(quote! { #substrate::arcstr::literal!(::std::stringify!(#pretty_ident)) });
field_match_arms.push(quote! {
::std::stringify!(#pretty_ident) => ::std::option::Option::Some(<<#field_ty as #substrate::types::schematic::SchematicBundleKind>::Bundle as #substrate::io::Flatten<#substrate::types::schematic::Node>>::flatten_vec(&#refer)),
terminal_view_flatten_terminal_fields.push(quote! {
<<#field_ty as #substrate::types::schematic::SchematicBundleKind>::TerminalBundle as #substrate::types::Flatten<#substrate::types::schematic::Terminal>>::flatten(&#refer, __substrate_output_sink);
});
}

Expand All @@ -165,8 +181,28 @@ pub(crate) fn schematic_io(input: &IoInputReceiver) -> TokenStream {
false,
quote!( #(#construct_terminal_view_fields)* ),
);
let construct_terminal_view_ty_body = struct_body(
fields.style,
true,
quote! { #( #construct_terminal_view_ty_fields )* },
);
let construct_terminal_view_nested_ty_body = struct_body(
fields.style,
true,
quote! { #( #construct_terminal_view_nested_ty_fields )* },
);
let construct_data_body =
struct_body(fields.style, false, quote!( #(#construct_data_fields)* ));
let construct_data_ty_body = struct_body(
fields.style,
true,
quote! { #( #construct_data_ty_fields )* },
);
let construct_data_nested_ty_body = struct_body(
fields.style,
true,
quote! { #( #construct_data_nested_ty_fields )* },
);

quote! {
#[derive(Clone, #substrate::schematic::NestedData)]
Expand All @@ -176,51 +212,110 @@ pub(crate) fn schematic_io(input: &IoInputReceiver) -> TokenStream {
#(#attrs)*
#vis struct #terminal_view_ident #st_generics #terminal_view_body

impl #st_imp #substrate::io::FlatLen for #data_ident #st_ty #st_where {
impl #st_imp #data_ident #st_ty #st_where {
#vis fn view_as<__substrate_T: #substrate::types::HasBundleKind<BundleKind: #substrate::types::schematic::SchematicBundleKind>>(&self) -> #substrate::types::schematic::NodeBundle<<__substrate_T as #substrate::types::HasBundleKind>::BundleKind> where <Self as #substrate::types::HasBundleKind>::BundleKind: #substrate::types::schematic::DataView<<__substrate_T as #substrate::types::HasBundleKind>::BundleKind>{
<<Self as #substrate::types::HasBundleKind>::BundleKind as #substrate::types::schematic::DataView<<__substrate_T as #substrate::types::HasBundleKind>::BundleKind>>::view_nodes_as(self)
}
}

impl #st_imp #terminal_view_ident #st_ty #st_where {
#vis fn view_as<__substrate_T: #substrate::types::HasBundleKind<BundleKind: #substrate::types::schematic::SchematicBundleKind>>(&self) -> #substrate::types::schematic::TerminalBundle<<__substrate_T as #substrate::types::HasBundleKind>::BundleKind> where <Self as #substrate::types::HasBundleKind>::BundleKind: #substrate::types::schematic::DataView<<__substrate_T as #substrate::types::HasBundleKind>::BundleKind>{
<<Self as #substrate::types::HasBundleKind>::BundleKind as #substrate::types::schematic::DataView<<__substrate_T as #substrate::types::HasBundleKind>::BundleKind>>::view_terminals_as(self)
}
}

impl #st_imp #substrate::types::FlatLen for #data_ident #st_ty #st_where {
fn len(&self) -> usize {
#( #data_len )+*
}
}

impl #st_imp #substrate::io::Flatten<#substrate::types::schematic::Node> for #data_ident #st_ty #st_where {
impl #st_imp #substrate::types::Flatten<#substrate::types::schematic::Node> for #data_ident #st_ty #st_where {
fn flatten<E>(&self, __substrate_output_sink: &mut E)
where
E: ::std::iter::Extend<#substrate::types::schematic::Node> {
#( #flatten_node_fields )*
}
}

impl #st_any_imp #substrate::types::schematic::HasTerminalView for #data_ident #st_any_ty #st_any_where {
type TerminalView = #terminal_view_ident #st_any_ty;

fn terminal_view(cell: #substrate::schematic::CellId, cell_io: &Self, instance: #substrate::schematic::InstanceId, instance_io: &Self) -> Self::TerminalView {
#terminal_view_ident #construct_terminal_view_body
}
}

impl #st_imp #substrate::io::FlatLen for #terminal_view_ident #st_ty #st_where {
impl #st_imp #substrate::types::FlatLen for #terminal_view_ident #st_ty #st_where {
fn len(&self) -> usize {
#( #terminal_data_len )+*
}
}

impl #st_imp #substrate::io::Flatten<#substrate::types::schematic::Node> for #terminal_view_ident #st_ty #st_where {
impl #st_imp #substrate::types::Flatten<#substrate::types::schematic::Node> for #terminal_view_ident #st_ty #st_where {
fn flatten<E>(&self, __substrate_output_sink: &mut E)
where
E: ::std::iter::Extend<#substrate::types::schematic::Node> {
#( #terminal_view_flatten_node_fields )*
}
}

impl #st_imp #substrate::types::Flatten<#substrate::types::schematic::Terminal> for #terminal_view_ident #st_ty #st_where {
fn flatten<E>(&self, __substrate_output_sink: &mut E)
where
E: ::std::iter::Extend<#substrate::types::schematic::Terminal> {
#( #terminal_view_flatten_terminal_fields )*
}
}

impl #st_any_imp #substrate::types::schematic::SchematicBundleKind for #bundle_type_ident #st_any_ty #st_any_where {
type Bundle = #data_ident #st_any_ty;
type NodeBundle = #data_ident #st_any_ty;
type TerminalBundle = #terminal_view_ident #st_any_ty;

fn instantiate<'n>(&self, __substrate_node_ids: &'n [#substrate::types::schematic::Node]) -> (Self::Bundle, &'n [#substrate::types::schematic::Node]) {
#( #instantiate_fields )*
fn instantiate_nodes<'n>(&self, __substrate_node_ids: &'n [#substrate::types::schematic::Node]) -> (<Self as #substrate::types::schematic::SchematicBundleKind>::NodeBundle, &'n [#substrate::types::schematic::Node]) {
#( #instantiate_nodes_fields )*
#[allow(redundant_field_names)]
(#data_ident #construct_data_body, __substrate_node_ids)
}

fn instantiate_terminals<'n>(&self, __substrate_node_ids: &'n [#substrate::types::schematic::Terminal]) -> (<Self as #substrate::types::schematic::SchematicBundleKind>::TerminalBundle, &'n [#substrate::types::schematic::Terminal]) {
#( #instantiate_terminals_fields )*
#[allow(redundant_field_names)]
(#terminal_view_ident #construct_data_body, __substrate_node_ids)
}

fn terminal_view(
cell: #substrate::schematic::CellId,
cell_io: &<Self as #substrate::types::schematic::SchematicBundleKind>::NodeBundle,
instance: #substrate::schematic::InstanceId,
instance_io: &<Self as #substrate::types::schematic::SchematicBundleKind>::NodeBundle,
) -> <Self as #substrate::types::schematic::SchematicBundleKind>::TerminalBundle {
#terminal_view_ident #construct_terminal_view_body
}
}

impl #st_any_imp #substrate::types::HasBundleKind for #data_ident #st_any_ty #st_any_where {
type BundleKind = #bundle_type_ident #st_any_ty;

fn kind(&self) -> <Self as #substrate::types::HasBundleKind>::BundleKind {
#bundle_type_ident #construct_data_ty_body
}
}

impl #st_any_imp #substrate::types::HasBundleKind for #terminal_view_ident #st_any_ty #st_any_where {
type BundleKind = #bundle_type_ident #st_any_ty;

fn kind(&self) -> <Self as #substrate::types::HasBundleKind>::BundleKind {
#bundle_type_ident #construct_terminal_view_ty_body
}
}

impl #st_any_imp #substrate::types::HasBundleKind for #data_nested_ident #st_any_ty #st_any_where {
type BundleKind = #bundle_type_ident #st_any_ty;

fn kind(&self) -> <Self as #substrate::types::HasBundleKind>::BundleKind {
#bundle_type_ident #construct_data_nested_ty_body
}
}

impl #st_any_imp #substrate::types::HasBundleKind for #terminal_view_nested_ident #st_any_ty #st_any_where {
type BundleKind = #bundle_type_ident #st_any_ty;

fn kind(&self) -> <Self as #substrate::types::HasBundleKind>::BundleKind {
#bundle_type_ident #construct_terminal_view_nested_ty_body
}
}
}
}
Expand Down
3 changes: 1 addition & 2 deletions codegen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,10 +219,9 @@ pub fn derive_nested_data(input: TokenStream) -> TokenStream {
///
/// You must specify the block's IO by adding a `#[substrate(io = "IoType")]` attribute:
/// ```
/// use serde::{Serialize, Deserialize};
/// use substrate::block::Block;
///
/// #[derive(Block, Copy, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, Debug)]
/// #[derive(Block, Copy, Clone, Eq, PartialEq, Hash, Debug)]
/// #[substrate(io = "substrate::io::TestbenchIo")]
/// pub struct MyBlock {
/// // ...
Expand Down
2 changes: 1 addition & 1 deletion libs/spice/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,7 @@ impl Schematic for Resistor {

fn schematic(
&self,
io: &substrate::types::schematic::IoBundle<Self, substrate::types::schematic::Node>,
io: &substrate::types::schematic::IoBundle<Self>,
cell: &mut CellBuilder<<Self as Schematic>::Schema>,
) -> substrate::error::Result<Self::NestedData> {
let mut prim = substrate::schematic::PrimitiveBinding::new(Primitive::Res2 {
Expand Down
8 changes: 4 additions & 4 deletions substrate/src/lut.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ pub type FloatLut2 = Lut2<f64, f64, f64>;

#[cfg(test)]
mod tests {
use float_eq::float_eq;
use approx::assert_relative_eq;

use super::*;

Expand Down Expand Up @@ -141,9 +141,9 @@ mod tests {
.build()
.unwrap();

assert!(float_eq!(lut.getf(5., 2.).unwrap(), 5., r2nd <= 1e-8));
assert!(float_eq!(lut.getf(5., 2.5).unwrap(), 7., r2nd <= 1e-8));
assert!(float_eq!(lut.getf(6.5, 1.5).unwrap(), 3.75, r2nd <= 1e-8));
assert_relative_eq!(lut.getf(5., 2.).unwrap(), 5., max_relative = 1e-8);
assert_relative_eq!(lut.getf(5., 2.5).unwrap(), 7., max_relative = 1e-8);
assert_relative_eq!(lut.getf(6.5, 1.5).unwrap(), 3.75, max_relative = 1e-8);
assert_eq!(lut.getf(4.5, 2.5), None);
}
}
Loading

0 comments on commit 0461b9d

Please sign in to comment.