diff --git a/src/frontend.rs b/src/frontend.rs index 7cbd4d9..b36e694 100644 --- a/src/frontend.rs +++ b/src/frontend.rs @@ -3,6 +3,7 @@ use std::collections::BTreeMap; use crate::builtin_cells::get_builtins; use crate::parser; use crate::rtlil; +use crate::rtlil::RtlilWrite; fn make_pubid(id: &str) -> String { "\\".to_owned() + id diff --git a/src/rtlil.rs b/src/rtlil.rs index 7146f5d..8f8bb37 100644 --- a/src/rtlil.rs +++ b/src/rtlil.rs @@ -1,3 +1,5 @@ +mod sync; + #[derive(Debug, Default)] pub struct ILWriter { data: String, @@ -17,6 +19,13 @@ impl ILWriter { self.data += "\n"; } + // TODO: make this actually take an iterator + pub fn write_iter(&mut self, iter: &[impl RtlilWrite]) { + for item in iter { + item.write_rtlil(self) + } + } + pub fn indent(&mut self) { self.indent += 1 } @@ -33,11 +42,8 @@ impl ILWriter { } } -// the proper way -#[derive(Debug)] -pub enum PortOption { - Input(i32), - Output(i32), +pub trait RtlilWrite { + fn write_rtlil(&self, writer: &mut ILWriter); } #[derive(Debug)] @@ -50,6 +56,12 @@ pub struct Wire { port_info: Option, } +#[derive(Debug)] +pub enum PortOption { + Input(i32), + Output(i32), +} + impl Wire { pub fn new(id: impl Into, width: u32, port_info: Option) -> Self { Self { @@ -58,7 +70,9 @@ impl Wire { port_info, } } +} +impl RtlilWrite for Wire { fn write_rtlil(&self, writer: &mut ILWriter) { let mut line = String::from("wire "); @@ -111,27 +125,25 @@ impl Module { self.cells.push(cell) } - pub fn write_rtlil(&self, writer: &mut ILWriter) { + pub fn make_genid(&mut self, stem: &str) -> String { + let res = format!("${}${}", stem, self.gen_id); + self.gen_id += 1; + res + } +} + +impl RtlilWrite for Module { + fn write_rtlil(&self, writer: &mut ILWriter) { writer.write_line(&format!("module {}", self.name)); writer.indent(); - for wire in &self.wires { - wire.write_rtlil(writer); - } - for cell in &self.cells { - cell.write_rtlil(writer); - } + writer.write_iter(&self.wires); + writer.write_iter(&self.cells); for conn in &self.connections { writer.write_line(&format!("connect {} {}", conn.0, conn.1)) } writer.dedent(); writer.write_line("end"); } - - pub fn make_genid(&mut self, stem: &str) -> String { - let res = format!("${}${}", stem, self.gen_id); - self.gen_id += 1; - res - } } #[derive(Debug)] @@ -159,7 +171,9 @@ impl Cell { pub fn add_connection(&mut self, from: &str, to: &str) { self.connections.push((from.into(), to.into())) } +} +impl RtlilWrite for Cell { fn write_rtlil(&self, writer: &mut ILWriter) { writer.write_line(&format!("cell {} {}", self.celltype, self.id)); writer.indent(); diff --git a/src/rtlil/sync.rs b/src/rtlil/sync.rs new file mode 100644 index 0000000..3f708c4 --- /dev/null +++ b/src/rtlil/sync.rs @@ -0,0 +1,71 @@ +use crate::rtlil::RtlilWrite; + +pub struct Process { + id: String, + root_case: CaseRule, + sync_rules: Vec, +} + +pub struct CaseRule { + assign: Vec<(String, String)>, + switches: Vec, +} + +pub struct SwitchRule { + signal: String, + cases: Vec, +} + +pub struct SyncRule { + cond: SyncCond, + assign: Vec<(String, String)>, +} + +pub enum SyncCond { + Always, + Posedge(String), + Negedge(String), +} + +impl RtlilWrite for Process { + fn write_rtlil(&self, writer: &mut super::ILWriter) { + writer.write_line(&format!("process {}", self.id)); + self.root_case.write_rtlil(writer); + writer.write_iter(&self.sync_rules); + } +} + +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(); + writer.write_iter(&self.cases); + writer.dedent(); + } +} + +impl RtlilWrite for SyncRule { + fn write_rtlil(&self, writer: &mut super::ILWriter) { + let sync_expr = match &self.cond { + SyncCond::Always => "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(); + } +}