calyx_ir/
utils.rs

1//! Helpers used to examine calyx programs. Used in Xilinx and Yxi backends among others.
2use super::{BoolAttr, Cell, Component, RRC};
3// Returns Vec<String> of memory names
4pub fn external_memories_names(comp: &Component) -> Vec<String> {
5    external_memories_cells(comp)
6        .iter()
7        .map(|cell_ref| cell_ref.borrow().name().to_string())
8        .collect()
9}
10
11// Gets all memory cells in top level marked external.
12pub fn external_memories_cells(comp: &Component) -> Vec<RRC<Cell>> {
13    comp.cells
14        .iter()
15        // find external memories
16        .filter(|cell_ref| {
17            let cell = cell_ref.borrow();
18            cell.attributes.has(BoolAttr::External)
19        })
20        .cloned()
21        .collect()
22}
23
24/// Parameters for std memories
25pub struct MemInfo {
26    pub width: u64,
27    pub size: u64,
28    //idx port width, in case size is ambiguous
29    pub idx_sizes: Vec<u64>,
30}
31
32// Returns a vector of tuples containing external memory info of [comp] of form:
33// [(WIDTH, SIZE, IDX_SIZE)]
34pub trait GetMemInfo {
35    fn get_mem_info(&self) -> Vec<MemInfo>;
36}
37
38impl GetMemInfo for Vec<RRC<Cell>> {
39    fn get_mem_info(&self) -> Vec<MemInfo> {
40        self.iter()
41              .map(|cr| {
42                  let mem = cr.borrow();
43                  let mem_size: u64;
44                  let mut idx_sizes: Vec<u64> = Vec::new();
45                  let idx_count: u64;
46                  match mem.prototype.get_name().unwrap().as_ref() {
47                      "comb_mem_d1" | "seq_mem_d1" => {
48                        mem_size = mem.get_parameter("SIZE").unwrap();
49                        idx_count = 1;
50                      }
51                      "comb_mem_d2" | "seq_mem_d2" => {
52                        mem_size = mem.get_parameter("D0_SIZE").unwrap()
53                              * mem.get_parameter("D1_SIZE").unwrap();
54                        idx_count = 2;
55                    }
56                    "comb_mem_d3" | "seq_mem_d3" => {
57                        mem_size = mem.get_parameter("D0_SIZE").unwrap()
58                        * mem.get_parameter("D1_SIZE").unwrap()
59                        * mem.get_parameter("D2_SIZE").unwrap();
60                        idx_count = 3;
61                    }
62                    "comb_mem_d4" | "seq_mem_d4" => {
63                        mem_size = mem.get_parameter("D0_SIZE").unwrap()
64                        * mem.get_parameter("D1_SIZE").unwrap()
65                        * mem.get_parameter("D2_SIZE").unwrap()
66                        * mem.get_parameter("D3_SIZE").unwrap();
67                        idx_count = 4;
68                      }
69                      _ => {
70                          panic!("cell `{}' marked with `@external' but is not a memory primitive.", mem.name())
71                      }
72                  };
73                  if idx_count == 1 {
74                    idx_sizes.push(mem.get_parameter("IDX_SIZE").unwrap());
75                  } else {
76                    for i in 1..idx_count {
77                        idx_sizes.push(mem.get_parameter(format!("D{}_IDX_SIZE",i)).unwrap());
78                    }
79                  }
80                  MemInfo {
81                      width: mem.get_parameter("WIDTH").unwrap(),
82                      size: mem_size,
83                      idx_sizes
84                  }
85              })
86              .collect()
87    }
88}
89
90impl GetMemInfo for Component {
91    fn get_mem_info(&self) -> Vec<MemInfo> {
92        external_memories_cells(self).get_mem_info()
93    }
94}