diff --git a/src/frontend.rs b/src/frontend.rs index 704f72d..ca65f01 100644 --- a/src/frontend.rs +++ b/src/frontend.rs @@ -140,7 +140,7 @@ pub fn lower_module(pa_module: parser::Module) -> Result { parser::ModuleItem::Assign(assignment) => { lower_assignment(&context, &mut ir_module, assignment)? } - parser::ModuleItem::Proc(proc) => todo!("lowering process") + parser::ModuleItem::Proc(proc) => todo!("lowering process"), } } ir_module.write_rtlil(&mut writer); diff --git a/src/main.rs b/src/main.rs index af238c3..e64ca98 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,11 +4,11 @@ mod literals; mod parser; mod rtlil; +use nom::error::convert_error; use std::fs::File; use std::io::prelude::*; use std::path::PathBuf; use structopt::StructOpt; -use nom::error::convert_error; #[derive(Debug, StructOpt)] #[structopt(name = "example", about = "An example of StructOpt usage.")] diff --git a/src/parser.rs b/src/parser.rs index 81e5de8..9e56ada 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,3 +1,6 @@ +mod module; +mod proc; + use nom::{ branch::alt, bytes::complete::tag, @@ -17,6 +20,7 @@ pub type Span<'a> = LocatedSpan<&'a str>; pub type IResult> = nom::IResult; use crate::literals::hexadecimal; +pub use crate::parser::module::{module, Module, ModuleItem, PortDirection}; fn ws0<'a, F: 'a, O, E: ParseError>>( inner: F, @@ -49,56 +53,6 @@ pub struct NetDecl<'a> { pub value: Option<(u64, u64)>, } -#[derive(Debug)] -pub enum PortDirection { - Input, - Output, -} - -#[derive(Debug)] -pub struct PortDecl<'a> { - pub pos: Span<'a>, - pub direction: PortDirection, - pub net: NetDecl<'a>, -} - -#[derive(Debug)] -pub struct Module<'a> { - pub name: &'a str, - pub ports: Vec>, - pub items: Vec>, -} - -#[derive(Debug)] -pub enum ModuleItem<'a> { - Assign(Assign<'a>), - Proc(ProcBlock<'a>), -} - -#[derive(Debug)] -pub struct ProcBlock<'a> { - pub net: Span<'a>, - pub items: Vec>, -} - -#[derive(Debug)] -pub enum ProcStatement<'a> { - IfElse(IfElseBlock), - Assign, - Match(MatchBlock<'a>), -} - -// TODO: postponed because annoying to implement -#[derive(Debug)] -pub struct IfElseBlock { -} - -#[derive(Debug)] -pub struct MatchBlock<'a> { - expr: Expression<'a>, - arms: Vec<(&'a str, ProcStatement<'a>)> -} - #[derive(Debug)] pub struct Assign<'a> { pub lhs: &'a str, @@ -140,27 +94,6 @@ fn declaration(i: Span) -> IResult { )(i) } -fn port_decl(i: Span) -> IResult { - map( - consumed(tuple(( - alt(( - map(tag("input"), |_| PortDirection::Input), - map(tag("output"), |_| PortDirection::Output), - )), - declaration, - ))), - |(pos, (direction, net))| PortDecl { - pos, - direction, - net, - }, - )(i) -} - -fn ports_list(input: Span) -> IResult> { - separated_list0(ws0(char(',')), ws0(port_decl))(input) -} - fn operation(input: Span) -> IResult { // temporarily given up on before I learn the shunting yard algorithm alt(( @@ -212,11 +145,9 @@ fn assign_statement(input: Span) -> IResult { ws0(terminated(tag("assign"), multispace1)), map( separated_pair(ws0(identifier), char('='), ws0(expression)), - |(lhs, expr)| { - Assign { - lhs: (*lhs.fragment()), - expr, - } + |(lhs, expr)| Assign { + lhs: (*lhs.fragment()), + expr, }, ), ws0(char(';')), @@ -224,70 +155,6 @@ fn assign_statement(input: Span) -> IResult { )(input) } -/// parse a statement that is valid inside a proc block -fn proc_statement(input: Span) -> IResult { - map( - nom::character::complete::anychar, - |_| { - ProcStatement::Match(MatchBlock { - expr: Expression::Ident("asdf"), - arms: Vec::new(), - }) - } - )(input) -} - -fn proc_block(input: Span) -> IResult { - context( - "proc block", - map( - tuple(( - ws0(tag("proc")), - ws0(delimited(char('('), ws0(identifier), char(')'))), - ws0(delimited(char('{'), many0(ws0(proc_statement)), char('}'))) - )), - |(_, net, items)| { - ProcBlock { - net, - items, - } - } - ) - )(input) - -} - -fn module_item(input: Span) -> IResult { - alt(( - map(assign_statement, |assig| ModuleItem::Assign(assig)), - map(proc_block, |proc| ModuleItem::Proc(proc)), - ))(input) -} - -/// parse a top-level module declaration -pub fn module(input: Span) -> IResult { - context( - "module", - map( - tuple(( - tag("module"), - ws0(identifier), - ws0(delimited(char('('), ws0(ports_list), char(')'))), - ws0(delimited( - char('{'), - many1(ws0(module_item)), - char('}'), - )), - )), - |(_, name, ports, items)| Module { - name: (*name.fragment()), - ports, - items, - }, - ), - )(input) -} - pub fn parse(input: Span) -> IResult { module(input) } diff --git a/src/parser/module.rs b/src/parser/module.rs new file mode 100644 index 0000000..33b78f3 --- /dev/null +++ b/src/parser/module.rs @@ -0,0 +1,89 @@ +use nom::{ + branch::alt, + bytes::complete::tag, + character::complete::{alpha1, alphanumeric1, char, multispace0, multispace1, u64 as decimal}, + combinator::{consumed, map, opt, recognize}, + error::{context, ParseError, VerboseError}, + multi::{many0, many1, separated_list0}, + sequence::{delimited, pair, preceded, separated_pair, terminated, tuple}, +}; + +use crate::parser::proc::{proc_block, ProcBlock}; +use crate::parser::{ + assign_statement, declaration, identifier, intliteral, widthspec, ws0, Assign, IResult, + NetDecl, Span, +}; + +#[derive(Debug)] +pub enum PortDirection { + Input, + Output, +} + +#[derive(Debug)] +pub struct PortDecl<'a> { + pub pos: Span<'a>, + pub direction: PortDirection, + pub net: NetDecl<'a>, +} + +#[derive(Debug)] +pub struct Module<'a> { + pub name: &'a str, + pub ports: Vec>, + pub items: Vec>, +} + +#[derive(Debug)] +pub enum ModuleItem<'a> { + Assign(Assign<'a>), + Proc(ProcBlock<'a>), +} + +fn port_decl(i: Span) -> IResult { + map( + consumed(tuple(( + alt(( + map(tag("input"), |_| PortDirection::Input), + map(tag("output"), |_| PortDirection::Output), + )), + declaration, + ))), + |(pos, (direction, net))| PortDecl { + pos, + direction, + net, + }, + )(i) +} + +fn ports_list(input: Span) -> IResult> { + separated_list0(ws0(char(',')), ws0(port_decl))(input) +} + +fn module_item(input: Span) -> IResult { + alt(( + map(assign_statement, |assig| ModuleItem::Assign(assig)), + map(proc_block, |proc| ModuleItem::Proc(proc)), + ))(input) +} + +/// parse a top-level module declaration +pub fn module(input: Span) -> IResult { + context( + "module", + map( + tuple(( + tag("module"), + ws0(identifier), + ws0(delimited(char('('), ws0(ports_list), char(')'))), + ws0(delimited(char('{'), many1(ws0(module_item)), char('}'))), + )), + |(_, name, ports, items)| Module { + name: (*name.fragment()), + ports, + items, + }, + ), + )(input) +} diff --git a/src/parser/proc.rs b/src/parser/proc.rs new file mode 100644 index 0000000..a87e6da --- /dev/null +++ b/src/parser/proc.rs @@ -0,0 +1,58 @@ +use nom::{ + branch::alt, + bytes::complete::tag, + character::complete::{alpha1, alphanumeric1, char, multispace0, multispace1, u64 as decimal}, + combinator::{consumed, map, opt, recognize}, + error::{context, ParseError, VerboseError}, + multi::{many0, many1, separated_list0}, + sequence::{delimited, pair, preceded, separated_pair, terminated, tuple}, +}; + +use crate::parser::{identifier, ws0, Expression, IResult, Span}; + +#[derive(Debug)] +pub struct ProcBlock<'a> { + pub net: Span<'a>, + pub items: Vec>, +} + +#[derive(Debug)] +pub enum ProcStatement<'a> { + IfElse(IfElseBlock), + Assign, + Match(MatchBlock<'a>), +} + +// TODO: postponed because annoying to implement +#[derive(Debug)] +pub struct IfElseBlock {} + +#[derive(Debug)] +pub struct MatchBlock<'a> { + expr: Expression<'a>, + arms: Vec<(&'a str, ProcStatement<'a>)>, +} + +/// parse a statement that is valid inside a proc block +fn proc_statement(input: Span) -> IResult { + map(nom::character::complete::anychar, |_| { + ProcStatement::Match(MatchBlock { + expr: Expression::Ident("asdf"), + arms: Vec::new(), + }) + })(input) +} + +pub fn proc_block(input: Span) -> IResult { + context( + "proc block", + map( + tuple(( + ws0(tag("proc")), + ws0(delimited(char('('), ws0(identifier), char(')'))), + ws0(delimited(char('{'), many0(ws0(proc_statement)), char('}'))), + )), + |(_, net, items)| ProcBlock { net, items }, + ), + )(input) +} diff --git a/src/rtlil.rs b/src/rtlil.rs index 5495208..28cb98f 100644 --- a/src/rtlil.rs +++ b/src/rtlil.rs @@ -144,7 +144,8 @@ impl Module { } pub fn add_connection(&mut self, target: &str, source: &str) { - self.connections.push((SigSpec::wire(target), SigSpec::wire(source))) + self.connections + .push((SigSpec::wire(target), SigSpec::wire(source))) } pub fn add_cell(&mut self, cell: Cell) { @@ -200,7 +201,8 @@ impl Cell { } pub fn add_connection(&mut self, from: &str, to: &str) { - self.connections.push((SigSpec::wire(from), SigSpec::wire(to))) + self.connections + .push((SigSpec::wire(from), SigSpec::wire(to))) } }