-
Notifications
You must be signed in to change notification settings - Fork 51
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
[ffi] Implement API for interfacing with Calyx modules from Rust #2359
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for splitting out a smaller chunk! However, I would like you to make an even smaller PR by leaving out the whole calyx_ffi_test
machinery. Instead, please just make a PR for everything that is necessary to execute a Calyx design from Rust, afaik, mostly just the code behind the calyx_ffi
macro.
I also added some detailed comments.
I don't understand what you mean by the |
4893af0
to
caf6055
Compare
What I mean is that the |
Oh, I see. Got it. |
The test are dependent on this macro though, so this would mean we merge it in with no tests? Or would we add back the tests with the |
Can you write a couple of "bare metal" tests that do not use the |
I think it should actually be fine, we can just merge the tests back in with the next PR. |
9a37048
to
6ce0fb6
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for splitting up the PR. The current size is much more manageable.
I added some small comments, but my big question is the following:
Why does the backend have to be specified as part of the calyx_ffi
macro? If you look at Serde, you apply their macro to your struct without specifying the backend that you are going to use. The #[derive(Serialize)]
just implements the correct trait such that you can then serialize the struct with all the available Serde backends.
Could we do a similar thing here? I.e. could we have something like:
#[calyx_ffi(
src = "tests/adder.futil",
comp = "main",
)]
struct Adder;
let adder_sim = Adder::start_sim(CiderSimulator);
CiderSimulator
would receive the name of the calyx file and component, generate a generic simulator which would then be saved inside of the Adder
struct. Adder
could even be generic on the type of backend used so that you can avoid any overhead from dynamic dispatch. I.e., the macro generated code would have something like:
struct Adder<B: SimBackend> {
// ....
sim: B, // could also be Option<B> if you want to allow instantiating `Adder` without a backend
}
trait SimBackendFactory { // this is implemented by CiderBackend
type Output;
fn create(path, component_name, ...) -> Output;
}
impl <B: SimBackend> Adder {
fn start_sim<F: SimBackendFactory<Output = B>>(f: &F) -> Self {
let sim = f.create(..., ...);
Self { sim }
}
}
@ekiwi The reason is that I need to know the port field names. I need to be able to hook up port field names with the backends. I agree that there must be a nicer way to do it, but I can't think of one. Also, I have a |
9a37048
to
cedaf99
Compare
Are we good to merge? |
Splits up #2181, making the following changes:
tools/calyx-ffi-macro
crate for the#[calyx_ffi(...)]
procedural macro.tools/calyx-ffi
crate, which includes tests that both serve to check thetools/calyx-ffi-macro
crate (because the tests compile) and the wrapper introduced intools/calyx-ffi
(because the tests pass), under the assumption thatcider2
is fully correct.interp/src/lib.rs
with a trivial change (that @EclecticGriffin has approved).