use std::{collections::HashSet, io};
use crate::traits::Backend;
use calyx_ir as ir;
use calyx_utils::{CalyxResult, OutputFile};
use serde::{Deserialize, Serialize};
#[derive(Default)]
pub struct PrimitiveUsesBackend;
impl Backend for PrimitiveUsesBackend {
fn name(&self) -> &'static str {
"primitive_uses"
}
fn validate(_ctx: &ir::Context) -> CalyxResult<()> {
Ok(())
}
fn link_externs(
_ctx: &ir::Context,
_file: &mut OutputFile,
) -> CalyxResult<()> {
Ok(())
}
fn emit(ctx: &ir::Context, file: &mut OutputFile) -> CalyxResult<()> {
let main_comp = ctx.entrypoint();
let mut primitive_set: HashSet<PrimitiveUse> = HashSet::new();
gen_primitive_set(ctx, main_comp, &mut primitive_set);
write_json(primitive_set.clone(), file)?;
Ok(())
}
}
#[derive(PartialEq, Eq, Hash, Clone, Serialize, Deserialize)]
struct PrimitiveUse {
name: String,
params: Vec<PrimitiveParam>,
}
#[derive(PartialEq, Eq, Hash, Clone, Serialize, Deserialize)]
struct PrimitiveParam {
param_name: String,
param_value: u64,
}
fn gen_primitive_set(
ctx: &ir::Context,
main_comp: &ir::Component,
primitive_set: &mut HashSet<PrimitiveUse>,
) {
for cell in main_comp.cells.iter() {
let cell_ref = cell.borrow();
match &cell_ref.prototype {
ir::CellType::Primitive {
name,
param_binding,
..
} => {
let curr_params = param_binding
.iter()
.map(|(param_name, param_size)| PrimitiveParam {
param_name: param_name.to_string(),
param_value: *param_size,
})
.collect();
let curr_primitive = PrimitiveUse {
name: name.to_string(),
params: curr_params,
};
(*primitive_set).insert(curr_primitive);
}
ir::CellType::Component { name } => {
let component = ctx
.components
.iter()
.find(|comp| comp.name == name)
.unwrap();
gen_primitive_set(ctx, component, primitive_set);
}
_ => (),
}
}
}
fn write_json(
primitive_set: HashSet<PrimitiveUse>,
file: &mut OutputFile,
) -> Result<(), io::Error> {
let created_vec: Vec<PrimitiveUse> = primitive_set.into_iter().collect();
serde_json::to_writer_pretty(file.get_write(), &created_vec)?;
Ok(())
}