-
Notifications
You must be signed in to change notification settings - Fork 53
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Continue work on testbench; cider2 stubs in place
- Loading branch information
1 parent
91abfd2
commit 0f3fc81
Showing
10 changed files
with
206 additions
and
93 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,32 +1,2 @@ | ||
/// Example FFI backend. | ||
#[macro_export] | ||
macro_rules! useless_ffi_backend { | ||
(init $dut:ident; $($port:ident),*) => { | ||
println!("useless_ffi_backend init"); | ||
}; | ||
(deinit $dut:ident; $($port:ident),*) => { | ||
println!("useless_ffi_backend deinit"); | ||
}; | ||
(reset $dut:ident; $($port:ident),*) => { | ||
println!("useless_ffi_backend reset"); | ||
$dut.done = 0; | ||
$dut.reset = 1; | ||
for i in 0..5 { | ||
$dut.tick(); | ||
} | ||
$dut.reset = 0; | ||
}; | ||
(tick $dut:ident; $($port:ident),*) => { | ||
println!("useless_ffi_backend tick"); | ||
if $dut.done == 1 { | ||
$dut.done = 0; | ||
} | ||
}; | ||
(go $dut:ident; $($port:ident),*) => { | ||
println!("useless_ffi_backend go"); | ||
$dut.go = 1; | ||
$dut.go = 0; | ||
$dut.done = 1; | ||
$dut.tick(); | ||
}; | ||
} | ||
pub mod cider; | ||
pub mod useless; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
use calyx_ir::Context; | ||
use interp::flatten::structures::{ | ||
context::Context as CiderContext, | ||
environment::{Environment, Simulator}, | ||
}; | ||
use std::{mem::MaybeUninit, rc::Rc}; | ||
|
||
pub struct CiderFFIBackend { | ||
simulator: Simulator<Rc<CiderContext>>, | ||
} | ||
|
||
impl CiderFFIBackend { | ||
pub fn from(context: &Context, name: &'static str) -> Self { | ||
let cider_context = CiderContext::new(); | ||
let environment = Environment::new(Rc::new(cider_context), None); | ||
let simulator = Simulator::new(environment); | ||
Self { simulator } | ||
} | ||
|
||
pub fn write_port(&mut self, name: &'static str, value: u64) { | ||
todo!("no way to set port on a component yet I think") | ||
// self.simulator. | ||
} | ||
|
||
pub fn read_port(&self, name: &'static str) -> u64 { | ||
todo!("no way to get port on a component yet I think") | ||
} | ||
|
||
pub fn step(&mut self) { | ||
self.simulator.step().expect( | ||
"this function isn't documented so don't know what went wrong", | ||
); | ||
} | ||
} | ||
|
||
/// Runs the component using cider2. | ||
#[macro_export] | ||
macro_rules! cider_ffi_backend { | ||
(@user_data_type) => { | ||
$crate::backend::cider::CiderFFIBackend | ||
}; | ||
(@init $dut:ident, $ctx:expr; $($port:ident),*) => { | ||
$dut.user_data | ||
.write($crate::backend::cider::CiderFFIBackend::from( | ||
$ctx, | ||
$dut.name(), | ||
)); | ||
}; | ||
(@reset $dut:ident; $($port:ident),*) => { | ||
println!("cider_ffi_backend reset"); | ||
$dut.done = 0; | ||
$dut.reset = 1; | ||
for i in 0..5 { | ||
$dut.tick(); | ||
} | ||
$dut.reset = 0; | ||
}; | ||
(@can_tick $dut:ident; $($port:ident),*) => { | ||
true | ||
}; | ||
(@tick $dut:ident; $($port:ident),*) => { | ||
println!("cider_ffi_backend tick"); | ||
let cider = unsafe { $dut.user_data.assume_init_mut() }; | ||
$( | ||
cider.write_port(stringify!($port), $dut.$port); | ||
)* | ||
cider.step(); | ||
$( | ||
$dut.$port = cider.read_port(stringify!($port)); | ||
)* | ||
}; | ||
(@go $dut:ident; $($port:ident),*) => { | ||
println!("cider_ffi_backend go"); | ||
$dut.go = 1; | ||
while ($dut.done != 1) { | ||
$dut.tick(); | ||
} | ||
$dut.go = 0; | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
/// Example FFI backend. | ||
#[macro_export] | ||
macro_rules! useless_ffi_backend { | ||
(@user_data_type) => { | ||
() // unit type | ||
}; | ||
(@init $dut:ident, $ctx:expr; $($port:ident),*) => { | ||
println!("useless_ffi_backend init"); | ||
}; | ||
(@reset $dut:ident; $($port:ident),*) => { | ||
println!("useless_ffi_backend reset"); | ||
$dut.done = 0; | ||
$dut.reset = 1; | ||
for i in 0..5 { | ||
$dut.tick(); | ||
} | ||
$dut.reset = 0; | ||
}; | ||
(@can_tick $dut:ident; $($port:ident),*) => { | ||
true | ||
}; | ||
(@tick $dut:ident; $($port:ident),*) => { | ||
println!("useless_ffi_backend tick"); | ||
if $dut.done == 1 { | ||
$dut.done = 0; | ||
} | ||
}; | ||
(@go $dut:ident; $($port:ident),*) => { | ||
println!("useless_ffi_backend go"); | ||
$dut.go = 1; | ||
$dut.go = 0; | ||
$dut.done = 1; | ||
$dut.tick(); | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,71 +1,76 @@ | ||
use std::{any, cell::RefCell, collections::HashMap, rc::Rc}; | ||
use calyx_ir::Context; | ||
use std::{ | ||
any, cell::RefCell, collections::HashMap, env, path::PathBuf, rc::Rc, | ||
}; | ||
|
||
pub mod backend; | ||
pub mod prelude; | ||
|
||
/// A non-combinational calyx component. | ||
pub trait CalyxFFIComponent: any::Any { | ||
/// The in-source name of this component. | ||
/// The path to the component source file. Must be a constant expression. | ||
fn path(&self) -> &'static str; | ||
|
||
/// The in-source name of this component. Must be a constant expression. | ||
fn name(&self) -> &'static str; | ||
|
||
/// Internal initialization routine. Do not call! | ||
fn init(&mut self); | ||
|
||
/// Internal deinitialization routine. Do not call! | ||
fn deinit(&mut self); | ||
fn init(&mut self, context: &Context); | ||
|
||
// Resets this component. | ||
/// Resets this component. | ||
fn reset(&mut self); | ||
|
||
// Advances this component by one clock cycle. May not always be available. | ||
/// Whether this component's backend supports ticking. | ||
fn can_tick(&self) -> bool; | ||
|
||
/// Advances this component by one clock cycle. May not always be available, so check [`has_tick`]([CalyxFFIComponent::has_tick]). | ||
fn tick(&mut self); | ||
|
||
/// Calls this component. | ||
/// Calls this component, blocking until it is done executing. | ||
fn go(&mut self); | ||
} | ||
|
||
pub type CalyxFFIComponentRef = Rc<RefCell<dyn CalyxFFIComponent>>; | ||
|
||
fn box_calyx_ffi_component<T: CalyxFFIComponent>( | ||
comp: T, | ||
) -> CalyxFFIComponentRef { | ||
Rc::new(RefCell::new(comp)) | ||
} | ||
|
||
#[derive(Default)] | ||
pub struct CalyxFFI { | ||
reuse: HashMap<&'static str, usize>, | ||
comps: Vec<CalyxFFIComponentRef>, | ||
contexts: HashMap<&'static str, Context>, | ||
} | ||
|
||
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 let Some(index) = self.reuse.get(name) { | ||
self.comps[*index].clone() | ||
} else { | ||
self.new_comp::<T>() | ||
} | ||
} | ||
|
||
/// A new component `T`. | ||
/// Constructs a new calyx component of the given type. | ||
/// | ||
/// The `path` implementation for `CalyxFFIComponent` must be a constant | ||
/// expression and should derived via the `calyx_ffi` procedural macro. | ||
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 { | ||
comp.borrow_mut().deinit(); | ||
} | ||
let mut comp = unsafe { T::default() }; | ||
let path = comp.path(); | ||
let context = self.contexts.entry(path).or_insert_with_key(|path| { | ||
// there has to be a better way to find lib | ||
let home_dir = env::var("HOME").expect("user home not set"); | ||
let mut lib_path = PathBuf::from(home_dir); | ||
lib_path.push(".calyx"); | ||
let ws = calyx_frontend::Workspace::construct( | ||
&Some(path.into()), | ||
&lib_path, | ||
) | ||
.expect("couldn't parse calyx"); | ||
calyx_ir::from_ast::ast_to_ir(ws) | ||
.expect("couldn't construct calyx ir") | ||
}); | ||
comp.init(context); | ||
box_calyx_ffi_component(comp) | ||
} | ||
} |
Oops, something went wrong.