From 120a3c59f41f25d25a85b1bcf56b574f6564bbc3 Mon Sep 17 00:00:00 2001 From: NotAFile Date: Tue, 18 Jan 2022 00:11:37 +0100 Subject: [PATCH] allow yosys to read il output --- src/frontend.rs | 47 +++++++++++++++++++++++++++++++++-------------- src/main.rs | 17 ++++++++++++++--- src/rtlil/sync.rs | 5 +++-- 3 files changed, 50 insertions(+), 19 deletions(-) diff --git a/src/frontend.rs b/src/frontend.rs index fb48b34..353dc27 100644 --- a/src/frontend.rs +++ b/src/frontend.rs @@ -76,6 +76,12 @@ impl Signal { } } +/// context used when generating processes +struct ProcContext { + updates: Vec<(rtlil::SigSpec, rtlil::SigSpec)>, + next_sigs: BTreeMap, +} + struct Context { /// map callable name to callable callables: BTreeMap, @@ -96,27 +102,36 @@ impl Context { fn lower_process_statement( ctx: &Context, + pctx: &mut ProcContext, module: &mut rtlil::Module, - updates: &mut Vec<(rtlil::SigSpec, rtlil::SigSpec)>, stmt: &parser::proc::ProcStatement, ) -> Result { let rule = match stmt { parser::proc::ProcStatement::IfElse(_) => todo!("if/else unimplemented"), parser::proc::ProcStatement::Assign(assig) => { // FIXME: actually store this - let next_gen_id = format!("${}$next", assig.lhs); - module.add_wire(rtlil::Wire::new(&next_gen_id, TODO_WIDTH, None)); + let next_sig; + if let Some(sig) = pctx.next_sigs.get(assig.lhs) { + next_sig = sig.clone(); + } + else { + let next_gen_id = format!("${}$next", assig.lhs); + module.add_wire(rtlil::Wire::new(&next_gen_id, TODO_WIDTH, None)); + next_sig = rtlil::SigSpec::Wire(next_gen_id); - let next_wire = rtlil::SigSpec::Wire(next_gen_id); - updates.push(( - rtlil::SigSpec::Wire(assig.lhs.to_owned()), - next_wire.clone(), - )); + pctx.next_sigs.insert(assig.lhs.to_owned(), next_sig.clone()); + + // trigger the modified value to update + pctx.updates.push(( + ctx.try_get_signal(assig.lhs)?.sigspec(), + next_sig.clone(), + )); + }; let next_expr_wire = lower_expression(ctx, module, &assig.expr)?; rtlil::CaseRule { - assign: vec![(next_wire, next_expr_wire)], + assign: vec![(next_sig.clone(), next_expr_wire)], switches: vec![], } } @@ -124,7 +139,7 @@ fn lower_process_statement( let match_sig = lower_expression(ctx, module, &match_block.expr)?; let mut cases = vec![]; for arm in &match_block.arms { - let case = lower_process_statement(ctx, module, updates, &arm.1)?; + let case = lower_process_statement(ctx, pctx, module, &arm.1)?; let compare_sig = lower_expression(ctx, module, &arm.0)?; cases.push((compare_sig, case)); } @@ -147,17 +162,21 @@ fn lower_process( module: &mut rtlil::Module, process: &parser::proc::ProcBlock, ) -> Result<(), CompileError> { - let mut updates = vec![]; + let mut pctx = ProcContext { + updates: vec![], + next_sigs: BTreeMap::new(), + }; let mut cases = vec![]; for stmt in &process.items { - let case = lower_process_statement(ctx, module, &mut updates, stmt)?; + let case = lower_process_statement(ctx, &mut pctx, module, stmt)?; cases.push(case); } - let sync_cond = rtlil::SyncCond::Posedge((*process.net.fragment()).into()); + let sync_sig = ctx.try_get_signal(process.net.fragment())?; + let sync_cond = rtlil::SyncCond::Posedge(sync_sig.sigspec()); let sync_rule = rtlil::SyncRule { cond: sync_cond, - assign: updates, + assign: pctx.updates, }; if cases.len() != 1 { panic!("only one expression per block, for now") diff --git a/src/main.rs b/src/main.rs index c9219d0..7228e9f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -15,6 +15,12 @@ struct Opt { /// Input file #[structopt(parse(from_os_str))] input: PathBuf, + /// Debug AST + #[structopt(short)] + debug: bool, + /// Output file, stdout if not present + #[structopt(short, parse(from_os_str))] + output: Option, } fn main() { @@ -35,11 +41,16 @@ fn main() { } Err(_) => (), Ok(res) => { - println!("{:#?}", res); + if opt.debug { + println!("{:#?}", res); + } let lowered = crate::frontend::lower_module(res.1); match lowered { - Ok(res) => println!("{}", res), - Err(err) => println!("{:#?}", err), + Ok(res) => { + let mut file = File::create(opt.output.unwrap_or("out.rtlil".into())).expect("could not open file"); + file.write_all(res.as_bytes()).expect("failed to write output file"); + }, + Err(err) => eprintln!("{:#?}", err), } } } diff --git a/src/rtlil/sync.rs b/src/rtlil/sync.rs index 2b71139..3d89e17 100644 --- a/src/rtlil/sync.rs +++ b/src/rtlil/sync.rs @@ -29,8 +29,8 @@ pub struct SyncRule { pub enum SyncCond { Always, Init, - Posedge(String), - Negedge(String), + Posedge(SigSpec), + Negedge(SigSpec), } impl RtlilWrite for Process { @@ -64,6 +64,7 @@ impl RtlilWrite for SwitchRule { writer.dedent(); } writer.dedent(); + writer.write_line("end"); } }