diff --git a/src/frontend.rs b/src/frontend.rs index a1995f0..13d9add 100644 --- a/src/frontend.rs +++ b/src/frontend.rs @@ -1,17 +1,22 @@ +use std::borrow::Borrow; +use std::cell::Cell; use std::collections::BTreeMap; -use crate::builtin_cells::get_builtins; -use crate::parser; -use crate::parser::expression::Expression; +use super::parser; use crate::rtlil; -use crate::rtlil::RtlilWrite; pub use callable::Callable; pub use types::{make_primitives, Type, TypeStruct}; mod callable; +#[cfg(never)] +pub mod lowering; pub mod typed_ir; pub mod types; +use crate::builtin_cells::get_builtins; + +// pub use lowering::lower_module; + /// lots of code is still not width-aware, this constant keeps track of that const TODO_WIDTH: u32 = 1; @@ -23,6 +28,7 @@ fn make_pubid(id: &str) -> String { pub enum CompileErrorKind { UndefinedReference(String), BadArgCount { received: usize, expected: usize }, + TodoError(String), } #[derive(Debug)] @@ -54,291 +60,119 @@ impl<'ctx> Signal<'ctx> { } } -/// context used when generating processes -struct ProcContext { - updates: Vec<(rtlil::SigSpec, rtlil::SigSpec)>, - next_sigs: BTreeMap, -} - -struct Context<'ctx> { +pub struct Context<'ctx> { /// map callable name to callable callables: BTreeMap>, /// types types: BTreeMap>, /// map signal name to Signal - signals: BTreeMap>, + signals: BTreeMap>, + /// incrementing counter for unique IDs + ids: Counter, +} + +struct Counter(Cell); + +impl Counter { + fn new() -> Counter { + Counter(Cell::new(0)) + } + fn next(&self) -> usize { + let next = self.0.get() + 1; + self.0.set(next); + next + } } impl<'ctx> Context<'ctx> { - fn get_signal(&self, signame: &str) -> Option<&Signal> { + pub fn new() -> Self { + Context { + callables: get_builtins() + .into_iter() + .map(|clb| (clb.name().to_owned(), clb)) + .collect(), + signals: BTreeMap::new(), + types: make_primitives().into_iter().collect(), + ids: Counter::new(), + } + } + fn get_signal(&self, signame: &str) -> Option<&typed_ir::Signal> { self.signals.get(signame) } - fn try_get_signal(&self, signame: &str) -> Result<&Signal, CompileError> { + fn try_get_signal(&self, signame: &str) -> Result<&typed_ir::Signal, CompileError> { self.get_signal(signame).ok_or_else(|| { CompileError::new(CompileErrorKind::UndefinedReference(signame.to_owned())) }) } - fn try_get_type(&self, typename: &str) -> Result { + fn try_get_type(&'ctx self, typename: &str) -> Result, CompileError> { self.types.get(typename).ok_or_else(|| { CompileError::new(CompileErrorKind::UndefinedReference(typename.to_owned())) }) } -} -fn lower_process_statement( - ctx: &Context, - pctx: &mut ProcContext, - module: &mut rtlil::Module, - 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_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); - - 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_sig, next_expr_wire)], - switches: vec![], - } - } - parser::proc::ProcStatement::Match(match_block) => { - 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, pctx, module, &arm.1)?; - let compare_sig = lower_expression(ctx, module, &arm.0)?; - cases.push((compare_sig, case)); - } - let switch_rule = rtlil::SwitchRule { - signal: match_sig, - cases, - }; - rtlil::CaseRule { - assign: vec![], - switches: vec![switch_rule], - } - } - parser::proc::ProcStatement::Block(_) => todo!("blocks unimplemented"), - }; - Ok(rule) -} - -fn lower_process( - ctx: &Context, - module: &mut rtlil::Module, - process: &parser::proc::ProcBlock, -) -> Result<(), CompileError> { - 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, &mut pctx, module, stmt)?; - cases.push(case); - } - - 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: pctx.updates, - }; - if cases.len() != 1 { - panic!("only one expression per block, for now") - } - assert_eq!(cases.len(), 1); - let ir_proc = rtlil::Process { - id: module.make_genid("proc"), - root_case: cases.into_iter().next().unwrap(), - sync_rules: vec![sync_rule], - }; - module.add_process(ir_proc); - Ok(()) -} - -fn desugar_binop<'a>(op: parser::expression::BinOp<'a>) -> parser::expression::Call<'a> { - let a = desugar_expression(op.a); - let b = desugar_expression(op.b); - let op_func = match op.kind { - parser::expression::BinOpKind::And => "and", - parser::expression::BinOpKind::Or => "or", - parser::expression::BinOpKind::Xor => "xor", - }; - parser::expression::Call { - name: op_func.into(), - args: vec![a, b], - } -} - -fn desugar_unop<'a>(op: parser::expression::UnOp<'a>) -> parser::expression::Call<'a> { - let a = desugar_expression(op.a); - let op_func = match op.kind { - parser::expression::UnOpKind::BitNot => "not", - parser::expression::UnOpKind::Not => todo!(), - }; - parser::expression::Call { - name: op_func.into(), - args: vec![a], - } -} - -fn desugar_expression<'a>(expr: Expression<'a>) -> Expression<'a> { - // TODO: allow ergonomic traversal of AST - match expr { - Expression::Path(_) => expr, - Expression::Literal(_) => expr, - Expression::Call(mut call) => { - let new_args = call.args.into_iter().map(desugar_expression).collect(); - call.args = new_args; - Expression::Call(call) - } - Expression::BinOp(op) => Expression::Call(Box::new(desugar_binop(*op))), - Expression::UnOp(op) => Expression::Call(Box::new(desugar_unop(*op))), - } -} - -fn lower_expression( - ctx: &Context, - module: &mut rtlil::Module, - expr: &Expression, -) -> Result { - let expr = desugar_expression(expr.clone()); - match expr { - Expression::Path(ident) => { - let signal = ctx.try_get_signal(ident)?; - Ok(signal.sigspec()) - } - Expression::Call(call) => { - let args_resolved = call - .args - .iter() - .map(|expr| lower_expression(ctx, module, expr)) - .collect::, _>>()?; - - let callable = ctx - .callables - .get(call.name.fragment() as &str) - .ok_or_else(|| { - CompileError::new(CompileErrorKind::UndefinedReference( - call.name.fragment().to_string(), - )) - })?; - - if args_resolved.len() != callable.argcount() { - return Err(CompileError::new(CompileErrorKind::BadArgCount { - expected: callable.argcount(), - received: args_resolved.len(), - })); - } - - let cell_id = module.make_genid(callable.name()); - - let output_gen_id = format!("{}$out", &cell_id); - module.add_wire(rtlil::Wire::new(&output_gen_id, TODO_WIDTH, None)); - let output_gen_wire = rtlil::SigSpec::Wire(output_gen_id); - - // let cell = - // (*callable.instantiate)(&cell_id, args_resolved.as_slice(), &output_gen_wire); - // module.add_cell(cell); - Ok(output_gen_wire) - } - // TODO: instantiate operators directly here instead of desugaring, once the callable infrastructure improves - // to get better errors - Expression::Literal(lit) => Ok(rtlil::SigSpec::Const( - lit.span().fragment().parse().unwrap(), - TODO_WIDTH, - )), - Expression::UnOp(_) => todo!(), - Expression::BinOp(_) => todo!(), - } -} - -fn lower_assignment( - ctx: &Context, - module: &mut rtlil::Module, - assignment: parser::Assign, -) -> Result<(), CompileError> { - let target_id = ctx.try_get_signal(assignment.lhs)?.sigspec(); - let return_wire = lower_expression(ctx, module, &assignment.expr)?; - module.add_connection(&target_id, &return_wire); - Ok(()) -} - -fn lower_comb( - ctx: &mut Context, - module: &mut rtlil::Module, - pa_comb: parser::comb::CombBlock, -) -> Result<(), CompileError> { - for (num, port) in pa_comb.ports.iter().enumerate() { - let port_id = make_pubid(port.net.name.fragment()); - let port_tyname = &port.net.typ; - ctx.try_get_type(port_tyname.name.fragment())?; - module.add_wire(rtlil::Wire::new( - port_id.clone(), - TODO_WIDTH, - Some(rtlil::PortOption::Input((num + 1) as i32)), - )); - let typ = TypeStruct::logic_width(TODO_WIDTH); - let signal = Signal { - name: port.net.name.fragment().to_string(), - il_id: port_id, - // TODO: CRIMES CRIMES CRIMES - typ: Box::leak(Box::new(typ)), + fn type_expression( + &self, + expr: &parser::expression::Expression, + ) -> Result { + let typ = match expr { + parser::expression::Expression::Path(name) => self.try_get_signal(name)?.typ, + parser::expression::Expression::Literal(_) => todo!(), + parser::expression::Expression::UnOp(op) => self.type_expression(&op.a)?.typ, + parser::expression::Expression::BinOp(_) => todo!(), + parser::expression::Expression::Call(call) => todo!(), }; - ctx.signals - .insert(port.net.name.fragment().to_string(), signal); + Ok(typed_ir::Expr { + id: 0, + inputs: vec![], + typ: typ, + }) } - let ret_id = module.make_genid("ret"); - module.add_wire(rtlil::Wire::new( - ret_id.clone(), - TODO_WIDTH, - Some(rtlil::PortOption::Output(99)), - )); - let out_sig = lower_expression(ctx, module, &pa_comb.expr)?; - module.add_connection(&rtlil::SigSpec::Wire(ret_id), &out_sig); - Ok(()) -} -pub fn lower_module(pa_module: parser::Module) -> Result { - let mut writer = rtlil::ILWriter::new(); - let mut ir_module = rtlil::Module::new(make_pubid("test")); - let mut context = Context { - callables: get_builtins() - .into_iter() - .map(|clb| (clb.name().to_owned(), clb)) - .collect(), - signals: BTreeMap::new(), - types: make_primitives().into_iter().collect(), - }; + fn type_comb( + &mut self, + comb: &parser::comb::CombBlock, + ) -> Result { + let mut signals = Vec::new(); - writer.write_line("autoidx 1"); - for item in pa_module.items { - match item { - parser::ModuleItem::Comb(comb) => lower_comb(&mut context, &mut ir_module, comb)?, - parser::ModuleItem::Proc(_) => todo!(), - parser::ModuleItem::State(_) => todo!(), + for port in comb.ports.iter() { + let sig_id = self.ids.next(); + let sig_typename = &port.net.typ; + let sig_type = self.try_get_type(sig_typename.name.fragment())?; + let sig = typed_ir::Signal { + id: sig_id as u32, + typ: sig_type, + }; + signals.push(sig); + self.signals.insert(port.net.name.to_string(), sig); } + + let ret_typename = &comb.ret.name; + let ret_type = self.try_get_type(&ret_typename.fragment())?; + + let root_expr = self.type_expression(&comb.expr)?; + + Ok(typed_ir::Block { + signals, + expr: root_expr, + }) + } + + pub fn type_module( + &'ctx mut self, + module: parser::Module, + ) -> Result, CompileError> { + for item in module.items { + let block = match &item { + parser::ModuleItem::Comb(comb) => self.type_comb(comb)?, + parser::ModuleItem::Proc(_) => todo!(), + parser::ModuleItem::State(_) => todo!(), + }; + return Ok(block); + } + Err(CompileError::new(CompileErrorKind::TodoError( + "no blocks in module".to_string(), + ))) } - ir_module.write_rtlil(&mut writer); - Ok(writer.finish()) } diff --git a/src/frontend/lowering.rs b/src/frontend/lowering.rs new file mode 100644 index 0000000..7e3ca43 --- /dev/null +++ b/src/frontend/lowering.rs @@ -0,0 +1,256 @@ +use std::collections::BTreeMap; + +use super::types::{make_primitives, TypeStruct}; +use super::{make_pubid, CompileError, CompileErrorKind, Context, Signal, TODO_WIDTH}; +use crate::builtin_cells::get_builtins; +use crate::parser; +use crate::parser::expression::Expression; +use crate::rtlil; +use crate::rtlil::RtlilWrite; + +/// context used when generating processes +struct ProcContext { + updates: Vec<(rtlil::SigSpec, rtlil::SigSpec)>, + next_sigs: BTreeMap, +} + +fn lower_process_statement( + ctx: &Context, + pctx: &mut ProcContext, + module: &mut rtlil::Module, + 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_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); + + 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_sig, next_expr_wire)], + switches: vec![], + } + } + parser::proc::ProcStatement::Match(match_block) => { + 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, pctx, module, &arm.1)?; + let compare_sig = lower_expression(ctx, module, &arm.0)?; + cases.push((compare_sig, case)); + } + let switch_rule = rtlil::SwitchRule { + signal: match_sig, + cases, + }; + rtlil::CaseRule { + assign: vec![], + switches: vec![switch_rule], + } + } + parser::proc::ProcStatement::Block(_) => todo!("blocks unimplemented"), + }; + Ok(rule) +} + +fn lower_process( + ctx: &Context, + module: &mut rtlil::Module, + process: &parser::proc::ProcBlock, +) -> Result<(), CompileError> { + 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, &mut pctx, module, stmt)?; + cases.push(case); + } + + 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: pctx.updates, + }; + if cases.len() != 1 { + panic!("only one expression per block, for now") + } + assert_eq!(cases.len(), 1); + let ir_proc = rtlil::Process { + id: module.make_genid("proc"), + root_case: cases.into_iter().next().unwrap(), + sync_rules: vec![sync_rule], + }; + module.add_process(ir_proc); + Ok(()) +} + +fn desugar_binop<'a>(op: parser::expression::BinOp<'a>) -> parser::expression::Call<'a> { + let a = desugar_expression(op.a); + let b = desugar_expression(op.b); + let op_func = match op.kind { + parser::expression::BinOpKind::And => "and", + parser::expression::BinOpKind::Or => "or", + parser::expression::BinOpKind::Xor => "xor", + }; + parser::expression::Call { + name: op_func.into(), + args: vec![a, b], + } +} + +fn desugar_unop<'a>(op: parser::expression::UnOp<'a>) -> parser::expression::Call<'a> { + let a = desugar_expression(op.a); + let op_func = match op.kind { + parser::expression::UnOpKind::BitNot => "not", + parser::expression::UnOpKind::Not => todo!(), + }; + parser::expression::Call { + name: op_func.into(), + args: vec![a], + } +} + +fn desugar_expression<'a>(expr: Expression<'a>) -> Expression<'a> { + // TODO: allow ergonomic traversal of AST + match expr { + Expression::Path(_) => expr, + Expression::Literal(_) => expr, + Expression::Call(mut call) => { + let new_args = call.args.into_iter().map(desugar_expression).collect(); + call.args = new_args; + Expression::Call(call) + } + Expression::BinOp(op) => Expression::Call(Box::new(desugar_binop(*op))), + Expression::UnOp(op) => Expression::Call(Box::new(desugar_unop(*op))), + } +} + +fn lower_expression( + ctx: &Context, + module: &mut rtlil::Module, + expr: &Expression, +) -> Result { + let expr = desugar_expression(expr.clone()); + match expr { + Expression::Path(ident) => { + let signal = ctx.try_get_signal(ident)?; + Ok(signal.sigspec()) + } + Expression::Call(call) => { + let args_resolved = call + .args + .iter() + .map(|expr| lower_expression(ctx, module, expr)) + .collect::, _>>()?; + + let callable = ctx + .callables + .get(call.name.fragment() as &str) + .ok_or_else(|| { + CompileError::new(CompileErrorKind::UndefinedReference( + call.name.fragment().to_string(), + )) + })?; + + if args_resolved.len() != callable.argcount() { + return Err(CompileError::new(CompileErrorKind::BadArgCount { + expected: callable.argcount(), + received: args_resolved.len(), + })); + } + + let cell_id = module.make_genid(callable.name()); + + let output_gen_id = format!("{}$out", &cell_id); + module.add_wire(rtlil::Wire::new(&output_gen_id, TODO_WIDTH, None)); + let output_gen_wire = rtlil::SigSpec::Wire(output_gen_id); + + // let cell = + // (*callable.instantiate)(&cell_id, args_resolved.as_slice(), &output_gen_wire); + // module.add_cell(cell); + Ok(output_gen_wire) + } + // TODO: instantiate operators directly here instead of desugaring, once the callable infrastructure improves + // to get better errors + Expression::Literal(lit) => Ok(rtlil::SigSpec::Const( + lit.span().fragment().parse().unwrap(), + TODO_WIDTH, + )), + Expression::UnOp(_) => todo!(), + Expression::BinOp(_) => todo!(), + } +} + +fn lower_assignment( + ctx: &Context, + module: &mut rtlil::Module, + assignment: parser::Assign, +) -> Result<(), CompileError> { + let target_id = ctx.try_get_signal(assignment.lhs)?.sigspec(); + let return_wire = lower_expression(ctx, module, &assignment.expr)?; + module.add_connection(&target_id, &return_wire); + Ok(()) +} + +fn lower_comb( + ctx: &mut Context, + module: &mut rtlil::Module, + pa_comb: parser::comb::CombBlock, +) -> Result<(), CompileError> { + for (num, port) in pa_comb.ports.iter().enumerate() { + let port_id = make_pubid(port.net.name.fragment()); + let port_tyname = &port.net.typ; + ctx.try_get_type(port_tyname.name.fragment())?; + module.add_wire(rtlil::Wire::new( + port_id.clone(), + TODO_WIDTH, + Some(rtlil::PortOption::Input((num + 1) as i32)), + )); + let typ = TypeStruct::logic_width(TODO_WIDTH); + let signal = Signal { + name: port.net.name.fragment().to_string(), + il_id: port_id, + // TODO: CRIMES CRIMES CRIMES + typ: Box::leak(Box::new(typ)), + }; + ctx.signals + .insert(port.net.name.fragment().to_string(), signal); + } + let ret_id = module.make_genid("ret"); + module.add_wire(rtlil::Wire::new( + ret_id.clone(), + TODO_WIDTH, + Some(rtlil::PortOption::Output(99)), + )); + let out_sig = lower_expression(ctx, module, &pa_comb.expr)?; + module.add_connection(&rtlil::SigSpec::Wire(ret_id), &out_sig); + Ok(()) +} + +pub fn lower_module(pa_module: parser::Module) -> Result { + let mut writer = rtlil::ILWriter::new(); + let mut ir_module = rtlil::Module::new(make_pubid("test")); + + writer.write_line("autoidx 1"); + ir_module.write_rtlil(&mut writer); + Ok(writer.finish()) +} diff --git a/src/frontend/typed_ir.rs b/src/frontend/typed_ir.rs index d25bb64..c3c61d8 100644 --- a/src/frontend/typed_ir.rs +++ b/src/frontend/typed_ir.rs @@ -1,15 +1,22 @@ -use super::types::Type; +use super::{types::Type, Context}; -/// an abstract element that performs some kind of computation on a value -struct Element<'ty> { +/// an abstract element that performs some kind of computation on inputs +#[derive(Debug)] +pub struct Expr<'ty> { pub id: u32, - pub inputs: Vec>, + pub inputs: Vec>, pub typ: Type<'ty>, } -struct Signal<'ty> { +#[derive(Debug)] +pub struct Signal<'ty> { pub id: u32, pub typ: Type<'ty>, } -struct Expression {} +/// A block of HDL code, e.g. comb block +#[derive(Debug)] +pub struct Block<'ty> { + pub signals: Vec>, + pub expr: Expr<'ty>, +} diff --git a/src/frontend/types.rs b/src/frontend/types.rs index a217325..698b7d7 100644 --- a/src/frontend/types.rs +++ b/src/frontend/types.rs @@ -7,6 +7,7 @@ pub struct TypeStruct<'ty> { kind: TypeKind<'ty>, } +#[derive(Debug)] enum TypeKind<'ty> { /// Elaboration-time types ElabType(ElabKind), @@ -18,11 +19,13 @@ enum TypeKind<'ty> { Callable, } +#[derive(Debug)] struct ElabData<'ty> { typ: Type<'ty>, value: ElabValue<'ty>, } +#[derive(Debug)] enum ElabValue<'ty> { /// the value is not given and has to be inferred Infer, @@ -30,12 +33,14 @@ enum ElabValue<'ty> { Concrete(ElabValueData<'ty>), } +#[derive(Debug)] enum ElabValueData<'ty> { U32(u32), Bytes(&'ty [u8]), } /// Types that are only valid during Elaboration +#[derive(Debug)] enum ElabKind { /// general, unsized number type Num, @@ -90,6 +95,24 @@ impl<'ty> TypeStruct<'ty> { } } +impl std::fmt::Debug for TypeStruct<'_> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match &self.kind { + TypeKind::Logic(width) => { + if let Some(num) = width.try_u32() { + write!(f, "Logic<{}>", num) + } else { + write!(f, "Logic") + } + } + _ => f + .debug_struct("TypeStruct") + .field("kind", &self.kind) + .finish(), + } + } +} + /// Helper functions to create primitive elaboration values impl<'ty> ElabData<'ty> { /// an integer @@ -105,9 +128,12 @@ impl<'ty> ElabData<'ty> { /// return Some(u32) if this is a number pub fn try_u32(&self) -> Option { // TODO: assert this is actually a number - match self.value { + match &self.value { ElabValue::Infer => None, - ElabValue::Concrete(_) => todo!(), + ElabValue::Concrete(val) => match val { + ElabValueData::U32(num) => Some(*num), + ElabValueData::Bytes(_) => todo!(), + }, } } } diff --git a/src/main.rs b/src/main.rs index 13e6dcb..dc6ca3f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -58,7 +58,12 @@ fn main() { if opt.debug { println!("{:#?}", res); } - let lowered = crate::frontend::lower_module(res.1); + let mut frontendcontext = crate::frontend::Context::new(); + let typed = frontendcontext.type_module(res.1); + if opt.debug { + println!("{:#?}", typed); + } + /* match lowered { Ok(res) => { let mut file = File::create(opt.output.unwrap_or_else(|| "out.rtlil".into())) @@ -68,6 +73,7 @@ fn main() { } Err(err) => eprintln!("{:#?}", err), } + */ } } }