-
Notifications
You must be signed in to change notification settings - Fork 52
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* WIP, add to backend options * add serde_json dependency for IDL backend * WIP work on IDL * Minimal working version of IDL generator Some open questions: Naming and placement. This is probably not xilinx specific so should be moved up a level into just src. Also, naming is generic and not good and should be changed TODO: Only works withs d1 memories, but should not be hard to alter * Let IDL generator handle multi-dim mems Previously could only handle 1 dimension mems. NOTE: This flattens dimensions into a single size variable that is spit out. However it may be useful to maintain info about shape of memory? Need to think about this more * add basic runt tests * clippy formatting * rename idl to yxi and make serde_json call shorter * add error conversion for serde_json for yxi backend * update runt tests for yxi * update cargo lock with serde_json * formatting * move yxi up a directory * WIP of extracting utility functions * Refactor toplevel and yxi util functions Moved things into calyx-ir/utils. Things like get_mem_info and functions that get memories marked as external, along with their names * clippy and formatting
- Loading branch information
1 parent
746f6a8
commit 062b9a8
Showing
16 changed files
with
508 additions
and
57 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
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 |
---|---|---|
@@ -0,0 +1,73 @@ | ||
use crate::traits::Backend; | ||
use calyx_ir as ir; | ||
use calyx_ir::utils::GetMemInfo; | ||
use calyx_utils::CalyxResult; | ||
use serde::Serialize; | ||
/// Backend that generates the YXI Interface Definition Language. | ||
/// YXI aims to be a description of toplevel hardware modules that we can then consume | ||
/// to create things like AXI wrappers on arbitrary programs | ||
#[derive(Default)] | ||
pub struct YxiBackend; | ||
|
||
#[derive(Serialize)] | ||
struct ProgramInterface<'a> { | ||
toplevel: &'a str, | ||
memories: Vec<Memory<'a>>, | ||
} | ||
|
||
#[derive(Serialize)] | ||
struct Memory<'a> { | ||
name: &'a str, | ||
width: u64, | ||
size: u64, //number of cells in memory | ||
} | ||
|
||
impl Backend for YxiBackend { | ||
fn name(&self) -> &'static str { | ||
"yxi" | ||
} | ||
|
||
fn validate(_ctx: &ir::Context) -> CalyxResult<()> { | ||
Ok(()) | ||
} | ||
|
||
fn link_externs( | ||
_prog: &ir::Context, | ||
_write: &mut calyx_utils::OutputFile, | ||
) -> CalyxResult<()> { | ||
Ok(()) | ||
} | ||
|
||
fn emit( | ||
prog: &ir::Context, | ||
file: &mut calyx_utils::OutputFile, | ||
) -> CalyxResult<()> { | ||
let toplevel = prog | ||
.components | ||
.iter() | ||
.find(|comp| comp.name == prog.entrypoint) | ||
.unwrap(); | ||
|
||
let memory_names = ir::utils::external_memories_names(toplevel); | ||
let mem_infos = toplevel.get_mem_info(); | ||
|
||
let memories: Vec<Memory> = memory_names | ||
.iter() | ||
.zip(mem_infos.iter()) | ||
.map(|(memory_name, mem_info)| Memory { | ||
name: memory_name, | ||
width: mem_info.width, | ||
size: mem_info.size, | ||
}) | ||
.collect(); | ||
|
||
let program_interface = ProgramInterface { | ||
toplevel: toplevel.name.as_ref(), | ||
memories, | ||
}; | ||
|
||
serde_json::to_writer_pretty(file.get_write(), &program_interface)?; | ||
|
||
Ok(()) | ||
} | ||
} |
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 |
---|---|---|
|
@@ -57,3 +57,5 @@ mod macros; | |
|
||
/// Serializer methods for IR nodes. | ||
pub mod serializers; | ||
|
||
pub mod utils; |
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,94 @@ | ||
//! Helpers used to examine calyx programs. Used in Xilinx and Yxi backends among others. | ||
use super::{BoolAttr, Cell, Component, RRC}; | ||
// Returns Vec<String> of memory names | ||
pub fn external_memories_names(comp: &Component) -> Vec<String> { | ||
external_memories_cells(comp) | ||
.iter() | ||
.map(|cell_ref| cell_ref.borrow().name().to_string()) | ||
.collect() | ||
} | ||
|
||
// Gets all memory cells in top level marked external. | ||
pub fn external_memories_cells(comp: &Component) -> Vec<RRC<Cell>> { | ||
comp.cells | ||
.iter() | ||
// find external memories | ||
.filter(|cell_ref| { | ||
let cell = cell_ref.borrow(); | ||
cell.attributes.has(BoolAttr::External) | ||
}) | ||
.cloned() | ||
.collect() | ||
} | ||
|
||
/// Parameters for std memories | ||
pub struct MemInfo { | ||
pub width: u64, | ||
pub size: u64, | ||
//idx port width, in case size is ambiguous | ||
pub idx_sizes: Vec<u64>, | ||
} | ||
|
||
// Returns a vector of tuples containing external memory info of [comp] of form: | ||
// [(WIDTH, SIZE, IDX_SIZE)] | ||
pub trait GetMemInfo { | ||
fn get_mem_info(&self) -> Vec<MemInfo>; | ||
} | ||
|
||
impl GetMemInfo for Vec<RRC<Cell>> { | ||
fn get_mem_info(&self) -> Vec<MemInfo> { | ||
self.iter() | ||
.map(|cr| { | ||
let mem = cr.borrow(); | ||
let mem_size: u64; | ||
let mut idx_sizes: Vec<u64> = Vec::new(); | ||
let idx_count: u64; | ||
match mem.prototype.get_name().unwrap().as_ref() { | ||
"std_mem_d1" | "seq_mem_d1" => { | ||
mem_size = mem.get_parameter("SIZE").unwrap(); | ||
idx_count = 1; | ||
} | ||
"std_mem_d2" | "seq_mem_d2" => { | ||
mem_size = mem.get_parameter("D0_SIZE").unwrap() | ||
* mem.get_parameter("D1_SIZE").unwrap(); | ||
idx_count = 2; | ||
} | ||
"std_mem_d3" | "seq_mem_d3" => { | ||
mem_size = mem.get_parameter("D0_SIZE").unwrap() | ||
* mem.get_parameter("D1_SIZE").unwrap() | ||
* mem.get_parameter("D2_SIZE").unwrap(); | ||
idx_count = 3; | ||
} | ||
"std_mem_d4" | "seq_mem_d4" => { | ||
mem_size = mem.get_parameter("D0_SIZE").unwrap() | ||
* mem.get_parameter("D1_SIZE").unwrap() | ||
* mem.get_parameter("D2_SIZE").unwrap() | ||
* mem.get_parameter("D3_SIZE").unwrap(); | ||
idx_count = 4; | ||
} | ||
_ => { | ||
panic!("cell `{}' marked with `@external' but is not a memory primitive.", mem.name()) | ||
} | ||
}; | ||
if idx_count == 1 { | ||
idx_sizes.push(mem.get_parameter("IDX_SIZE").unwrap()); | ||
} else { | ||
for i in 1..idx_count { | ||
idx_sizes.push(mem.get_parameter(format!("D{}_IDX_SIZE",i)).unwrap()); | ||
} | ||
} | ||
MemInfo { | ||
width: mem.get_parameter("WIDTH").unwrap(), | ||
size: mem_size, | ||
idx_sizes | ||
} | ||
}) | ||
.collect() | ||
} | ||
} | ||
|
||
impl GetMemInfo for Component { | ||
fn get_mem_info(&self) -> Vec<MemInfo> { | ||
external_memories_cells(self).get_mem_info() | ||
} | ||
} |
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
Oops, something went wrong.