calyx_backend/
yxi.rs

1use crate::traits::Backend;
2use calyx_ir as ir;
3use calyx_ir::utils::GetMemInfo;
4use calyx_utils::CalyxResult;
5use serde::Serialize;
6/// Backend that generates the YXI Interface Definition Language.
7/// YXI aims to be a description of toplevel hardware modules that we can then consume
8/// to create things like AXI wrappers on arbitrary programs
9#[derive(Default)]
10pub struct YxiBackend;
11
12#[derive(Serialize)]
13struct ProgramInterface<'a> {
14    toplevel: &'a str,
15    memories: Vec<Memory<'a>>,
16}
17
18#[derive(Serialize)]
19struct Memory<'a> {
20    name: &'a str,
21    width: u64,
22    size: u64, //number of cells in memory
23}
24
25impl Backend for YxiBackend {
26    fn name(&self) -> &'static str {
27        "yxi"
28    }
29
30    fn validate(_ctx: &ir::Context) -> CalyxResult<()> {
31        Ok(())
32    }
33
34    fn link_externs(
35        _prog: &ir::Context,
36        _write: &mut calyx_utils::OutputFile,
37    ) -> CalyxResult<()> {
38        Ok(())
39    }
40
41    fn emit(
42        prog: &ir::Context,
43        file: &mut calyx_utils::OutputFile,
44    ) -> CalyxResult<()> {
45        let toplevel = prog
46            .components
47            .iter()
48            .find(|comp| comp.name == prog.entrypoint)
49            .unwrap();
50
51        let memory_names = ir::utils::external_memories_names(toplevel);
52        let mem_infos = toplevel.get_mem_info();
53
54        let memories: Vec<Memory> = memory_names
55            .iter()
56            .zip(mem_infos.iter())
57            .map(|(memory_name, mem_info)| Memory {
58                name: memory_name,
59                width: mem_info.width,
60                size: mem_info.size,
61            })
62            .collect();
63
64        let program_interface = ProgramInterface {
65            toplevel: toplevel.name.as_ref(),
66            memories,
67        };
68
69        serde_json::to_writer_pretty(file.get_write(), &program_interface)?;
70
71        Ok(())
72    }
73}