From 0307d0537c619202a3ae85182da007f7855e53ae Mon Sep 17 00:00:00 2001 From: NotAFile Date: Tue, 5 Apr 2022 00:02:45 +0200 Subject: [PATCH] add match lowering --- src/frontend/lowering.rs | 43 ++++++++++++++++++++++++++++++++++++---- src/frontend/types.rs | 10 ++++++++++ 2 files changed, 49 insertions(+), 4 deletions(-) diff --git a/src/frontend/lowering.rs b/src/frontend/lowering.rs index 8fb1a61..004464a 100644 --- a/src/frontend/lowering.rs +++ b/src/frontend/lowering.rs @@ -66,17 +66,52 @@ fn lower_expression( Ok(rtlil::SigSpec::Wire(expr_wire_name)) } ExprKind::Literal(lit) => Ok(rtlil::SigSpec::Const( - todo!(), + ctx.types + .elab_as_u32(lit) + .expect("const does not fit in 32 bits") as i64, ctx.types.get_width(expr.typ).expect("signal has no size"), )), - ExprKind::Match(_) => todo!(), + ExprKind::Match(match_) => { + let cases = match_ + .arms + .iter() + .map(|(pat, val)| { + Ok(( + lower_expression(ctx, module, pat)?, + rtlil::CaseRule { + assign: vec![( + rtlil::SigSpec::Wire(expr_wire_name.clone()), + lower_expression(ctx, module, val)?, + )], + switches: vec![], + }, + )) + }) + .collect::, CompileError>>() + .unwrap(); + let root_switch = rtlil::SwitchRule { + signal: lower_expression(ctx, module, &match_.expr)?, + cases, + }; + let root_case = rtlil::CaseRule { + assign: vec![], + switches: vec![root_switch], + }; + let proc = rtlil::Process { + id: module.make_genid("match"), + root_case, + sync_rules: vec![], + }; + module.add_process(proc); + Ok(rtlil::SigSpec::Wire(expr_wire_name)) + } } } fn lower_comb( ctx: &mut Context, module: &mut rtlil::Module, - block: typed_ir::Block, + block: &typed_ir::Block, ) -> Result<(), CompileError> { for (num, sig) in block.signals.iter().enumerate() { let sig_id = format!("\\$sig_{}", sig.id.0); @@ -101,7 +136,7 @@ fn lower_comb( Ok(()) } -pub fn lower_block(context: &mut Context, block: typed_ir::Block) -> Result { +pub fn lower_block(context: &mut Context, block: &typed_ir::Block) -> Result { let mut writer = rtlil::ILWriter::new(); let mut ir_module = rtlil::Module::new(make_pubid("test")); diff --git a/src/frontend/types.rs b/src/frontend/types.rs index 602c3de..c372854 100644 --- a/src/frontend/types.rs +++ b/src/frontend/types.rs @@ -150,6 +150,16 @@ impl TypingContext { } } + pub fn elab_as_u32(&self, data: &ElabData) -> Option { + match &data.value { + ElabValue::Infer => None, + ElabValue::Concrete(val) => match val { + ElabValueData::U32(val) => Some(*val), + ElabValueData::Bytes(_val) => None, + }, + } + } + pub fn make_logic_size(&self, width: u32) -> Type { let widthnum = self.make_elabnum_u32(width); self.parameterize(self.primitives.logic, &[GenericArg::Elab(widthnum)])