futilehdl/src/rtlil/sync.rs

88 lines
2.2 KiB
Rust

use crate::rtlil::{RtlilWrite, SigSpec};
#[derive(Debug)]
pub struct Process {
pub id: String,
pub root_case: CaseRule,
pub sync_rules: Vec<SyncRule>,
}
#[derive(Debug)]
pub struct CaseRule {
pub assign: Vec<(SigSpec, SigSpec)>,
pub switches: Vec<SwitchRule>,
}
#[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();
}
}