use crate::{IO, ModDef, ParameterType, Usage, mod_def::ParameterSpec};
use indexmap::IndexMap;
use num_bigint::BigInt;
#[derive(Debug, Clone)]
pub struct PipelineConfig {
pub clk: String,
pub depth: usize,
pub inst_name: Option<String>,
}
impl Default for PipelineConfig {
fn default() -> Self {
PipelineConfig {
clk: "clk".to_string(),
depth: 0,
inst_name: None,
}
}
}
impl PipelineConfig {
pub fn to_mod_def(&self, width: usize) -> ModDef {
let mod_def = ModDef::new("br_delay_nr");
mod_def.add_port("clk", IO::Input(1));
mod_def.add_port("in", IO::Input(width));
mod_def.add_port("out", IO::Output(width));
mod_def.add_port("out_stages", IO::Output(width * self.depth));
let mut parameters = IndexMap::new();
parameters.insert(
"Width".to_string(),
ParameterSpec {
value: BigInt::from(width),
ty: ParameterType::Unsigned(32),
},
);
parameters.insert(
"NumStages".to_string(),
ParameterSpec {
value: BigInt::from(self.depth),
ty: ParameterType::Unsigned(32),
},
);
mod_def.core.write().parameters = parameters;
mod_def.set_usage(Usage::EmitNothingAndStop);
mod_def
}
}
impl ModDef {
pub(crate) fn resolve_pipeline_instance_name(&self, pipeline: &PipelineConfig) -> String {
if let Some(inst_name) = pipeline.inst_name.as_ref() {
let core = self.core.read();
assert!(
!core.instances.contains_key(inst_name),
"Cannot use pipeline instance name {}, since that instance name is already used in module definition {}.",
inst_name,
core.name
);
inst_name.clone()
} else {
let mut core = self.core.write();
loop {
let name = format!("pipeline_conn_{}", core.pipeline_counter.next().unwrap());
if !core.instances.contains_key(&name) {
break name;
}
}
}
}
}