1use super::{BoolAttr, Cell, Component, RRC};
3use calyx_utils::Id;
4#[cfg(feature = "serialize")]
5use serde::Serialize;
6
7pub fn external_and_ref_memories_names(comp: &Component) -> Vec<String> {
9 external_and_ref_memories_cells(comp)
10 .iter()
11 .map(|cell_ref| cell_ref.borrow().name().to_string())
12 .collect()
13}
14
15pub fn external_and_ref_memories_cells(comp: &Component) -> Vec<RRC<Cell>> {
17 comp.cells
18 .iter()
19 .filter(|cell_ref| {
21 let cell = cell_ref.borrow();
22 cell.attributes.has(BoolAttr::External) || cell.is_reference()
23 })
24 .cloned()
25 .collect()
26}
27
28#[cfg_attr(feature = "serialize", derive(Serialize))]
29#[derive(Clone, Copy)]
30pub enum MemoryType {
31 Combinational,
32 Sequential,
33 Dynamic,
34}
35
36pub struct MemInfo {
38 pub name: String,
39 pub memory_type: MemoryType,
40 pub data_width: u64,
41 pub dimensions: u64,
42 pub dimension_sizes: Vec<u64>,
44 pub total_size: u64,
45 pub idx_sizes: Vec<u64>,
47}
48
49pub trait GetMemInfo {
52 fn get_mem_info(&self) -> Vec<MemInfo>;
53}
54
55impl GetMemInfo for Vec<RRC<Cell>> {
56 fn get_mem_info(&self) -> Vec<MemInfo> {
57 let dimension_params = ["D0_SIZE", "D1_SIZE", "D2_SIZE", "D3_SIZE"];
59 self.iter()
60 .map(|cr| {
61 let mem = cr.borrow();
62 let mut dimension_sizes: Vec<u64> = Vec::new();
63 let mut idx_sizes: Vec<u64> = Vec::new();
64 let mem_cell_type = mem.prototype.get_name().unwrap(); let mem_type : MemoryType = if mem_cell_type.to_string().contains("comb") {
66 MemoryType::Combinational
67 } else if mem_cell_type.to_string().contains("seq") {
68 MemoryType::Sequential
69 } else {
70 MemoryType::Dynamic
71 };
72
73 let dimensions = dimension_count(mem_cell_type);
74 if dimensions == 1{
75 dimension_sizes.push(mem.get_parameter("SIZE").unwrap());
76 idx_sizes.push(mem.get_parameter("IDX_SIZE").unwrap());
77 }
78 else if dimensions > 1 && dimensions <= 4{
79 for i in 0..dimensions {
80 dimension_sizes.push(mem.get_parameter(dimension_params[i as usize]).unwrap());
81 idx_sizes.push(mem.get_parameter(format!("D{i}_IDX_SIZE")).unwrap());
82 }
83 }
84 else{
85 unreachable!("It is not expected for memory primitives to have more than 4 dimensions.");
86 };
87 let total_size = dimension_sizes.clone().iter().product();
88 MemInfo {
89 name: mem.name().to_string(),
90 memory_type: mem_type,
91 data_width: mem.get_parameter("WIDTH").unwrap(),
92 dimensions,
93 dimension_sizes,
94 total_size,
95 idx_sizes
96 }
97 })
98 .collect()
99 }
100}
101
102impl GetMemInfo for Component {
103 fn get_mem_info(&self) -> Vec<MemInfo> {
104 external_and_ref_memories_cells(self).get_mem_info()
105 }
106}
107
108fn dimension_count(mem_id: Id) -> u64 {
109 let mem_name = mem_id.as_ref();
110
111 if mem_name.contains("d1") {
112 1
113 } else if mem_name.contains("d2") {
114 2
115 } else if mem_name.contains("d3") {
116 3
117 } else if mem_name.contains("d4") {
118 4
119 } else {
120 panic!(
121 "Cell {mem_name} does not seem to be a memory primitive. Memory primitives are expected to have 1-4 dimensions inclusive."
122 );
123 }
124}