use crate::rtlil::{RtlilWrite, SigSpec}; #[derive(Debug)] pub struct Process { pub id: String, pub root_case: CaseRule, pub sync_rules: Vec, } #[derive(Debug)] pub struct CaseRule { pub assign: Vec<(SigSpec, SigSpec)>, pub switches: Vec, } #[derive(Debug)] pub struct SwitchRule { pub signal: SigSpec, pub cases: Vec<(SigSpec, CaseRule)>, } #[derive(Debug)] pub struct SyncRule { pub cond: SyncCond, pub assign: Vec<(SigSpec, SigSpec)>, } #[derive(Debug)] pub enum SyncCond { Always, Init, Posedge(SigSpec), Negedge(SigSpec), } impl RtlilWrite for Process { fn write_rtlil(&self, writer: &mut super::ILWriter) { writer.write_line(&format!("process {}", self.id)); writer.indent(); self.root_case.write_rtlil(writer); writer.write_iter(&self.sync_rules); writer.dedent(); writer.write_line("end"); } } impl RtlilWrite for CaseRule { fn write_rtlil(&self, writer: &mut super::ILWriter) { for assign in &self.assign { writer.write_line(&format!("assign {} {}", assign.0, assign.1)); } writer.write_iter(&self.switches); } } impl RtlilWrite for SwitchRule { fn write_rtlil(&self, writer: &mut super::ILWriter) { writer.write_line(&format!("switch {}", self.signal)); writer.indent(); for case in &self.cases { writer.write_line(&format!("case {}", case.0)); writer.indent(); case.1.write_rtlil(writer); writer.dedent(); } writer.dedent(); writer.write_line("end"); } } impl RtlilWrite for SyncRule { fn write_rtlil(&self, writer: &mut super::ILWriter) { let sync_expr = match &self.cond { SyncCond::Always => "always".to_owned(), SyncCond::Init => "always".to_owned(), SyncCond::Posedge(sig) => format!("posedge {}", sig), SyncCond::Negedge(sig) => format!("negedge {}", sig), }; writer.write_line(&format!("sync {}", sync_expr)); writer.indent(); for update in &self.assign { writer.write_line(&format!("update {} {}", update.0, update.1)); } writer.dedent(); } }