Skip to content

Commit

Permalink
Clean up ffi and testbench
Browse files Browse the repository at this point in the history
  • Loading branch information
ethanuppal committed Jul 17, 2024
1 parent 28a1f5e commit 91abfd2
Show file tree
Hide file tree
Showing 19 changed files with 105 additions and 110 deletions.
25 changes: 2 additions & 23 deletions Cargo.lock

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

3 changes: 0 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,6 @@ members = [
"tools/yxi",
"tools/calyx-writer",
"tools/tb",
"tools/tb/plugins/cocotb",
"tools/tb/plugins/verilator",
"tools/tb/plugins/calyx",
"tools/calyx-ffi-macro",
"tools/calyx-ffi",
"tools/tb/examples/calyx",
Expand Down
64 changes: 46 additions & 18 deletions tools/calyx-ffi-macro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ pub fn calyx_ffi(attrs: TokenStream, item: TokenStream) -> TokenStream {

#[derive(Default)]
struct CalyxFFITestModuleVisitor {
pub wrappers: Vec<syn::ItemFn>,
pub tests: Vec<syn::ItemFn>,
}

Expand All @@ -122,20 +123,27 @@ impl syn::visit::Visit<'_> for CalyxFFITestModuleVisitor {
.any(|attr| attr.path().is_ident("calyx_ffi_test"));
if has_calyx_ffi_test {
let fn_name = &i.sig.ident;
let gen_fn_name =
format_ident!("calyx_ffi_generated_wrapper_for_{}", fn_name);
let dut_type = get_ffi_test_dut_type(i)
.expect("calyx_ffi_test should enforce this invariant");

self.tests.push(syn::parse_quote! {
unsafe fn #gen_fn_name(ffi: &mut CalyxFFI) {
let dut = ffi.comp::<#dut_type>();
self.wrappers.push(syn::parse_quote! {
pub(crate) unsafe fn #fn_name(ffi: &mut CalyxFFI) {
let dut = ffi.new_comp::<#dut_type>();
let dut_ref = &mut *dut.borrow_mut();
let dut_pointer = dut_ref as *mut dyn CalyxFFIComponent as *mut _ as *mut #dut_type;
let dut_concrete: &mut #dut_type = &mut *dut_pointer;
#fn_name(dut_concrete);
super::#fn_name(dut_concrete);
}
});
self.tests.push(syn::parse_quote! {
#[test]
pub(crate) fn #fn_name() {
let mut ffi = CalyxFFI::new();
unsafe {
super::calyx_ffi_generated_wrappers::#fn_name(&mut ffi);
}
}
})
});
}
}
}
Expand All @@ -154,18 +162,34 @@ pub fn calyx_ffi_tests(args: TokenStream, item: TokenStream) -> TokenStream {

let mut visitor = CalyxFFITestModuleVisitor::default();
syn::visit::visit_item_mod(&mut visitor, &module);
let wrappers = visitor.wrappers;
let tests = visitor.tests;

let test_names = wrappers.iter().map(|test| test.sig.ident.clone());
let generated_wrappers = quote! {
pub(crate) mod calyx_ffi_generated_wrappers {
use super::*;

pub(crate) const CALYX_FFI_TESTS: &'static [unsafe fn(&mut CalyxFFI) -> ()] = &[
#(#test_names),*
];

let test_names = visitor.tests.iter().map(|test| test.sig.ident.clone());
let test_array = quote! {
pub const CALYX_FFI_TESTS: &'static [unsafe fn(&mut CalyxFFI) -> ()] = &[
#(#test_names),*
];
#(#wrappers)*
}
};
let test_array_item: syn::Item = syn::parse2(test_array).unwrap();
let generated_wrappers_item: syn::Item =
syn::parse2(generated_wrappers).unwrap();

let generated_tests = quote! {
pub(crate) mod calyx_ffi_generated_tests {
use super::*;

let mut items_to_add = vec![test_array_item];
items_to_add.extend(visitor.tests.iter().cloned().map(syn::Item::Fn));
#(#tests)*
}
};
let generated_tests_item: syn::Item = syn::parse2(generated_tests).unwrap();

let items_to_add = vec![generated_wrappers_item, generated_tests_item];
if let Some((_, ref mut items)) = module.content {
items.extend(items_to_add);
} else {
Expand All @@ -175,9 +199,13 @@ pub fn calyx_ffi_tests(args: TokenStream, item: TokenStream) -> TokenStream {
quote! {
#module

pub unsafe fn calyx_ffi_test(ffi: &mut CalyxFFI) {
for test in #module_name::CALYX_FFI_TESTS {
test(ffi);
pub mod calyx_ffi_generated_top {
use super::*;

pub unsafe fn run_tests(ffi: &mut CalyxFFI) {
for test in #module_name::calyx_ffi_generated_wrappers::CALYX_FFI_TESTS {
test(ffi);
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion tools/calyx-ffi-macro/src/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ impl Parse for CalyxFFIMacroArgs {
if !input.is_empty() {
return Err(syn::Error::new_spanned(
input.parse::<TokenTree>()?,
"Invalid `calyx_ffi` argument syntax: expected 'src = \"...\", comp = \"...\", backend = ...",
"Invalid `calyx_ffi` argument syntax: expected 'src = \"...\", comp = \"...\", extern = ...",
));
}

Expand Down
1 change: 1 addition & 0 deletions tools/calyx-ffi/src/backend.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/// Example FFI backend.
#[macro_export]
macro_rules! useless_ffi_backend {
(init $dut:ident; $($port:ident),*) => {
Expand Down
27 changes: 20 additions & 7 deletions tools/calyx-ffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,30 +28,43 @@ pub type CalyxFFIComponentRef = Rc<RefCell<dyn CalyxFFIComponent>>;

#[derive(Default)]
pub struct CalyxFFI {
comps: HashMap<&'static str, CalyxFFIComponentRef>,
reuse: HashMap<&'static str, usize>,
comps: Vec<CalyxFFIComponentRef>,
}

impl CalyxFFI {
pub fn new() -> Self {
Self::default()
}

/// Any component `T`.
pub fn comp<T: CalyxFFIComponent + Default>(
&mut self,
) -> CalyxFFIComponentRef {
let name = T::default().name();
if !self.comps.contains_key(name) {
let comp_ref = Rc::new(RefCell::new(T::default()));
comp_ref.borrow_mut().init();
self.comps.insert(name, comp_ref);
if let Some(index) = self.reuse.get(name) {
self.comps[*index].clone()
} else {
self.new_comp::<T>()
}
self.comps.get(name).unwrap().clone()
}

/// A new component `T`.
pub fn new_comp<T: CalyxFFIComponent + Default>(
&mut self,
) -> CalyxFFIComponentRef {
let comp = Rc::new(RefCell::new(T::default()));
comp.borrow_mut().init();
self.comps.push(comp.clone());
self.reuse
.insert(comp.borrow().name(), self.comps.len() - 1);
comp
}
}

impl Drop for CalyxFFI {
fn drop(&mut self) {
for (_, comp) in &self.comps {
for comp in &self.comps {
comp.borrow_mut().deinit();
}
}
Expand Down
2 changes: 2 additions & 0 deletions tools/tb/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,5 @@ libloading = "0.8.4"
log.workspace = true
env_logger.workspace = true
fs_extra = "1.3.0"
makemake = "0.1.3"
toml = "0.8.14"
1 change: 1 addition & 0 deletions tools/tb/examples/calyx/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use calyx_ffi::prelude::*;
)]
struct Adder;

#[cfg(test)]
#[calyx_ffi_tests]
mod tests {
use super::*;
Expand Down
Empty file added tools/tb/plugins/.gitkeep
Empty file.
12 changes: 0 additions & 12 deletions tools/tb/plugins/calyx/Cargo.toml

This file was deleted.

12 changes: 0 additions & 12 deletions tools/tb/plugins/cocotb/Cargo.toml

This file was deleted.

11 changes: 0 additions & 11 deletions tools/tb/plugins/verilator/Cargo.toml

This file was deleted.

3 changes: 3 additions & 0 deletions tools/tb/src/builtin_plugins.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub mod calyx;
pub mod cocotb;
pub mod verilator;
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
use std::fs;
use std::io::{self, Write};
use std::path::PathBuf;
use std::process::Command;
use std::{fs, path::Path};

use tb::declare_plugin;
use tb::{config::Config, error::LocalResult, plugin::Plugin, semver, tempdir};
use crate::{
config::Config, error::LocalResult, plugin::Plugin, semver, tempdir,
};

#[derive(Default)]
pub struct CalyxTB;

mod config_keys {}

const DRIVER_CODE: &str = include_str!("driver.rs");
const DRIVER_CODE: &str = include_str!("resources/driver.rs");

impl Plugin for CalyxTB {
fn name(&self) -> &'static str {
Expand All @@ -22,7 +23,7 @@ impl Plugin for CalyxTB {
semver::Version::new(0, 0, 0)
}

fn setup(&self, config: &mut Config) -> LocalResult<()> {
fn setup(&self, _config: &mut Config) -> LocalResult<()> {
Ok(())
}

Expand All @@ -31,8 +32,11 @@ impl Plugin for CalyxTB {
input: String,
tests: &[String],
work_dir: tempdir::TempDir,
config: &Config,
_config: &Config,
) -> LocalResult<()> {
println!(
"recommendation: Run the #[calyx_ffi_tests] as Rust tests directly"
);
let mut calyx_ffi_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
calyx_ffi_path.push("../../../calyx-ffi");

Expand All @@ -44,7 +48,7 @@ impl Plugin for CalyxTB {
manifest_path.push("Cargo.toml");

let mut lib_path = PathBuf::from(work_dir.path());
lib_path.push("lib.rs");
lib_path.push(input);

for test in tests {
let mut test_path = PathBuf::from(work_dir.path());
Expand Down Expand Up @@ -99,5 +103,3 @@ impl Plugin for CalyxTB {
Ok(())
}
}

declare_plugin!(CalyxTB, CalyxTB::default);
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,13 @@ use std::io::{self, Write};
use std::process::Command;
use std::{fs, path::Path};

use makemake::{emitter::Emitter, makefile::Makefile};
use tb::declare_plugin;
use tb::error::LocalError;
use tb::{
use crate::{
config::{Config, ConfigVarValidator},
error::LocalResult,
error::{LocalError, LocalResult},
plugin::Plugin,
semver, tempdir,
};
use makemake::{emitter::Emitter, makefile::Makefile};

/// v1.8.1 cocotb
#[derive(Default)]
Expand Down Expand Up @@ -145,5 +143,3 @@ impl Plugin for CocoTB {
Ok(())
}
}

declare_plugin!(CocoTB, CocoTB::default);
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use calyx_ffi::prelude::*;
use test_crate::calyx_ffi_test;
use test_crate::calyx_ffi_generated_top::run_tests;

fn main() {
let mut ffi = CalyxFFI::default();
unsafe {
calyx_ffi_test(&mut ffi);
run_tests(&mut ffi);
}
}
Loading

0 comments on commit 91abfd2

Please sign in to comment.