diff --git a/tools/calyx-ffi-macro/src/lib.rs b/tools/calyx-ffi-macro/src/lib.rs index c0ee70c70..e030a9560 100644 --- a/tools/calyx-ffi-macro/src/lib.rs +++ b/tools/calyx-ffi-macro/src/lib.rs @@ -1,6 +1,6 @@ use parse::CalyxFFIMacroArgs; use proc_macro::TokenStream; -use quote::{format_ident, quote}; +use quote::quote; use syn::{parse_macro_input, spanned::Spanned}; mod calyx; @@ -116,9 +116,41 @@ pub fn calyx_ffi(attrs: TokenStream, item: TokenStream) -> TokenStream { } }; + let mut derive_impls = Vec::new(); + + for derive in args.derives { + let trait_name = derive.name; + + let mut getters = Vec::new(); + for output in derive.outputs { + getters.push(quote! { + fn #output(&self) -> u64 { + self.#output + } + }) + } + + let mut setters = Vec::new(); + for input in derive.inputs { + setters.push(quote! { + fn #input(&mut self) -> &mut u64 { + &mut self.#input + } + }) + } + + derive_impls.push(quote! { + impl #trait_name for #name { + #(#getters)* + #(#setters)* + } + }); + } + quote! { #struct_def #impl_block + #(#derive_impls)* } .into() } diff --git a/tools/calyx-ffi-macro/src/parse.rs b/tools/calyx-ffi-macro/src/parse.rs index 91dfa4bb3..f0642e575 100644 --- a/tools/calyx-ffi-macro/src/parse.rs +++ b/tools/calyx-ffi-macro/src/parse.rs @@ -1,7 +1,40 @@ use std::path::PathBuf; use proc_macro2::{Span, TokenTree}; -use syn::parse::{Parse, ParseStream}; +use syn::{ + bracketed, parenthesized, + parse::{Parse, ParseStream}, +}; + +pub struct CalyxInterface { + pub name: syn::Ident, + pub inputs: Vec, + pub outputs: Vec, +} + +impl Parse for CalyxInterface { + fn parse(input: ParseStream) -> syn::Result { + let name = input.parse::()?; + let inputs; + let outputs; + parenthesized!(inputs in input); + let inputs = inputs + .parse_terminated(syn::Ident::parse, syn::Token![,])? + .into_iter() + .collect(); + input.parse::]>()?; + parenthesized!(outputs in input); + let outputs = outputs + .parse_terminated(syn::Ident::parse, syn::Token![,])? + .into_iter() + .collect(); + Ok(Self { + name, + inputs, + outputs, + }) + } +} pub struct CalyxFFIMacroArgs { pub src_attr_span: Span, @@ -9,6 +42,7 @@ pub struct CalyxFFIMacroArgs { pub comp_attr_span: Span, pub comp: String, pub backend: syn::Path, + pub derives: Vec, } impl Parse for CalyxFFIMacroArgs { @@ -16,6 +50,7 @@ impl Parse for CalyxFFIMacroArgs { syn::custom_keyword!(src); syn::custom_keyword!(comp); syn::custom_keyword!(backend); + syn::custom_keyword!(derive); let src_ident = input.parse::()?; input.parse::()?; @@ -32,6 +67,20 @@ impl Parse for CalyxFFIMacroArgs { input.parse::()?; let backend_path = input.parse::()?; + let _ = input.parse::(); + + let derives = if input.parse::().is_ok() { + input.parse::()?; + let content; + bracketed!(content in input); + content + .parse_terminated(CalyxInterface::parse, syn::Token![,])? + .into_iter() + .collect() + } else { + vec![] + }; + if !input.is_empty() { return Err(syn::Error::new_spanned( input.parse::()?, @@ -45,6 +94,7 @@ impl Parse for CalyxFFIMacroArgs { comp_attr_span: comp_ident.span, comp: comp_lit, backend: backend_path, + derives, }) } } diff --git a/tools/calyx-ffi/src/prelude.rs b/tools/calyx-ffi/src/prelude.rs index 80281ce75..93bc88911 100644 --- a/tools/calyx-ffi/src/prelude.rs +++ b/tools/calyx-ffi/src/prelude.rs @@ -1,2 +1,16 @@ pub use super::{CalyxFFI, CalyxFFIComponent, CalyxFFIComponentRef}; pub use calyx_ffi_macro::{calyx_ffi, calyx_ffi_test, calyx_ffi_tests}; + +#[macro_export] +macro_rules! declare_calyx_interface { + ($name:ident($($input:ident),*) -> ($($output:ident),*)) => { + pub trait $name: CalyxFFIComponent { + $( + fn $input(&mut self) -> &mut u64; + )* + $( + fn $output(&self) -> u64; + )* + } + }; +} diff --git a/tools/tb/examples/calyx/test.rs b/tools/tb/examples/calyx/test.rs index 9e87468fd..66172f65d 100644 --- a/tools/tb/examples/calyx/test.rs +++ b/tools/tb/examples/calyx/test.rs @@ -1,11 +1,19 @@ +use calyx_ffi::declare_calyx_interface; use calyx_ffi::prelude::*; use calyx_ffi::cider_ffi_backend; +declare_calyx_interface! { + In2Out1(lhs, rhs) -> (result) +} + #[calyx_ffi( src = "/Users/ethan/Documents/GitHub/calyx/tools/tb/examples/calyx/adder.futil", comp = "main", - backend = cider_ffi_backend + backend = cider_ffi_backend, + derive = [ + In2Out1(lhs, rhs) -> (result) + ] )] struct Adder; @@ -14,9 +22,9 @@ struct Adder; mod tests { use super::*; - fn add(adder: &mut Adder, lhs: u64, rhs: u64) -> u64 { - adder.lhs = lhs; - adder.rhs = rhs; + fn add(adder: &mut I, lhs: u64, rhs: u64) -> u64 { + *adder.lhs() = lhs; + *adder.rhs() = rhs; adder.go(); adder.result() }