start lowering proc blocks
This commit is contained in:
parent
b8c7d501f6
commit
b77fc1a1f9
|
@ -6,7 +6,7 @@ module clockdiv_2 (
|
||||||
proc (clk) {
|
proc (clk) {
|
||||||
match (rst) {
|
match (rst) {
|
||||||
0 => out_clk = 0,
|
0 => out_clk = 0,
|
||||||
1 => out_clk = ~out_clk,
|
1 => out_clk = ~out_clk
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,6 +59,30 @@ struct Context {
|
||||||
callables: BTreeMap<String, Callable>,
|
callables: BTreeMap<String, Callable>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn lower_process(
|
||||||
|
ctx: &Context,
|
||||||
|
module: &mut rtlil::Module,
|
||||||
|
process: &parser::proc::ProcBlock
|
||||||
|
) -> Result<(), CompileError> {
|
||||||
|
let sync_cond = rtlil::SyncCond::Posedge((*process.net.fragment()).into());
|
||||||
|
let sync_rule = rtlil::SyncRule {
|
||||||
|
cond: sync_cond,
|
||||||
|
assign: Vec::new()
|
||||||
|
};
|
||||||
|
let root_case = rtlil::CaseRule {
|
||||||
|
assign: vec![],
|
||||||
|
switches: vec![],
|
||||||
|
};
|
||||||
|
let ir_proc = rtlil::Process {
|
||||||
|
id: module.make_genid("proc"),
|
||||||
|
root_case,
|
||||||
|
sync_rules: vec![sync_rule],
|
||||||
|
};
|
||||||
|
module.add_process(ir_proc);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn lower_expression(
|
fn lower_expression(
|
||||||
ctx: &Context,
|
ctx: &Context,
|
||||||
module: &mut rtlil::Module,
|
module: &mut rtlil::Module,
|
||||||
|
@ -99,6 +123,7 @@ fn lower_expression(
|
||||||
Ok(output_gen_id)
|
Ok(output_gen_id)
|
||||||
}
|
}
|
||||||
parser::Expression::Operation(_op) => todo!(),
|
parser::Expression::Operation(_op) => todo!(),
|
||||||
|
parser::Expression::Literal(_op) => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,7 +165,9 @@ pub fn lower_module(pa_module: parser::Module) -> Result<String, CompileError> {
|
||||||
parser::ModuleItem::Assign(assignment) => {
|
parser::ModuleItem::Assign(assignment) => {
|
||||||
lower_assignment(&context, &mut ir_module, assignment)?
|
lower_assignment(&context, &mut ir_module, assignment)?
|
||||||
}
|
}
|
||||||
parser::ModuleItem::Proc(_proc) => todo!("lowering process"),
|
parser::ModuleItem::Proc(proc) => {
|
||||||
|
lower_process(&context, &mut ir_module, &proc)?
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ir_module.write_rtlil(&mut writer);
|
ir_module.write_rtlil(&mut writer);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
mod module;
|
pub mod module;
|
||||||
mod proc;
|
pub mod proc;
|
||||||
|
|
||||||
use nom::{
|
use nom::{
|
||||||
branch::alt,
|
branch::alt,
|
||||||
|
@ -63,6 +63,7 @@ pub struct Assign<'a> {
|
||||||
pub enum Operation<'a> {
|
pub enum Operation<'a> {
|
||||||
And { a: String, b: Expression<'a> },
|
And { a: String, b: Expression<'a> },
|
||||||
Or { a: String, b: Expression<'a> },
|
Or { a: String, b: Expression<'a> },
|
||||||
|
Not(Expression<'a>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -74,6 +75,7 @@ pub struct Call<'a> {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Expression<'a> {
|
pub enum Expression<'a> {
|
||||||
Ident(&'a str),
|
Ident(&'a str),
|
||||||
|
Literal(u64),
|
||||||
Call(Box<Call<'a>>),
|
Call(Box<Call<'a>>),
|
||||||
Operation(Box<Operation<'a>>),
|
Operation(Box<Operation<'a>>),
|
||||||
}
|
}
|
||||||
|
@ -111,6 +113,10 @@ fn operation(input: Span) -> IResult<Span, Operation> {
|
||||||
b,
|
b,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
map(
|
||||||
|
preceded(char('~'), expression),
|
||||||
|
|expr| Operation::Not(expr),
|
||||||
|
),
|
||||||
))(input)
|
))(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,6 +136,7 @@ fn call_item(input: Span) -> IResult<Span, Call> {
|
||||||
|
|
||||||
fn expression(input: Span) -> IResult<Span, Expression> {
|
fn expression(input: Span) -> IResult<Span, Expression> {
|
||||||
alt((
|
alt((
|
||||||
|
map(ws0(decimal), |lit| Expression::Literal(lit)),
|
||||||
map(ws0(operation), |op| Expression::Operation(Box::new(op))),
|
map(ws0(operation), |op| Expression::Operation(Box::new(op))),
|
||||||
map(ws0(call_item), |call| Expression::Call(Box::new(call))),
|
map(ws0(call_item), |call| Expression::Call(Box::new(call))),
|
||||||
map(ws0(identifier), |ident| {
|
map(ws0(identifier), |ident| {
|
||||||
|
@ -139,19 +146,12 @@ fn expression(input: Span) -> IResult<Span, Expression> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn assign_statement(input: Span) -> IResult<Span, Assign> {
|
fn assign_statement(input: Span) -> IResult<Span, Assign> {
|
||||||
context(
|
|
||||||
"assignment",
|
|
||||||
delimited(
|
|
||||||
ws0(terminated(tag("assign"), multispace1)),
|
|
||||||
map(
|
map(
|
||||||
separated_pair(ws0(identifier), char('='), ws0(expression)),
|
separated_pair(ws0(identifier), char('='), ws0(expression)),
|
||||||
|(lhs, expr)| Assign {
|
|(lhs, expr)| Assign {
|
||||||
lhs: (*lhs.fragment()),
|
lhs: (*lhs.fragment()),
|
||||||
expr,
|
expr,
|
||||||
},
|
},
|
||||||
),
|
|
||||||
ws0(char(';')),
|
|
||||||
),
|
|
||||||
)(input)
|
)(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,6 +162,7 @@ pub fn parse(input: Span) -> IResult<Span, Module> {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use nom::combinator::all_consuming;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_decl() {
|
fn test_decl() {
|
||||||
|
@ -183,8 +184,9 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_assignment() {
|
fn test_assignment() {
|
||||||
assign_statement(" assign a = b ; ".into()).unwrap();
|
// TODO: make wrapper and use for all tests
|
||||||
assign_statement(" assign a = b | c ; ".into()).unwrap();
|
all_consuming(assign_statement)(" a = b ".into()).unwrap();
|
||||||
|
all_consuming(assign_statement)(" a = b | c ".into()).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
use nom::{
|
use nom::{
|
||||||
branch::alt,
|
branch::alt,
|
||||||
bytes::complete::tag,
|
bytes::complete::tag,
|
||||||
character::complete::char,
|
character::complete::{char, multispace1},
|
||||||
combinator::{consumed, map},
|
combinator::{consumed, map},
|
||||||
error::context,
|
error::context,
|
||||||
multi::{many1, separated_list0},
|
multi::{many1, separated_list0},
|
||||||
sequence::{delimited, tuple},
|
sequence::{delimited, tuple, terminated},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::parser::{
|
use crate::parser::{
|
||||||
|
@ -60,6 +60,17 @@ fn ports_list(input: Span) -> IResult<Span, Vec<PortDecl>> {
|
||||||
separated_list0(ws0(char(',')), ws0(port_decl))(input)
|
separated_list0(ws0(char(',')), ws0(port_decl))(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn assign_item(input: Span) -> IResult<Span, Assign> {
|
||||||
|
context(
|
||||||
|
"assignment",
|
||||||
|
delimited(
|
||||||
|
ws0(terminated(tag("assign"), multispace1)),
|
||||||
|
ws0(assign_statement),
|
||||||
|
ws0(char(';')),
|
||||||
|
),
|
||||||
|
)(input)
|
||||||
|
}
|
||||||
|
|
||||||
fn module_item(input: Span) -> IResult<Span, ModuleItem> {
|
fn module_item(input: Span) -> IResult<Span, ModuleItem> {
|
||||||
alt((
|
alt((
|
||||||
map(assign_statement, ModuleItem::Assign),
|
map(assign_statement, ModuleItem::Assign),
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
use nom::{
|
use nom::{
|
||||||
|
branch::alt,
|
||||||
bytes::complete::tag,
|
bytes::complete::tag,
|
||||||
character::complete::char,
|
character::complete::char,
|
||||||
combinator::map,
|
combinator::map,
|
||||||
error::context,
|
error::context,
|
||||||
multi::many0,
|
multi::{many1, separated_list0, separated_list1},
|
||||||
sequence::{delimited, tuple},
|
sequence::{delimited, tuple, separated_pair},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::parser::{identifier, ws0, Expression, IResult, Span};
|
use crate::parser::{identifier, ws0, expression, Expression, IResult, Span, Assign, assign_statement};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ProcBlock<'a> {
|
pub struct ProcBlock<'a> {
|
||||||
|
@ -18,8 +19,9 @@ pub struct ProcBlock<'a> {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum ProcStatement<'a> {
|
pub enum ProcStatement<'a> {
|
||||||
IfElse(IfElseBlock),
|
IfElse(IfElseBlock),
|
||||||
Assign,
|
Assign(Assign<'a>),
|
||||||
Match(MatchBlock<'a>),
|
Match(MatchBlock<'a>),
|
||||||
|
Block(Vec<ProcStatement<'a>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: postponed because annoying to implement
|
// TODO: postponed because annoying to implement
|
||||||
|
@ -29,17 +31,41 @@ pub struct IfElseBlock {}
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct MatchBlock<'a> {
|
pub struct MatchBlock<'a> {
|
||||||
expr: Expression<'a>,
|
expr: Expression<'a>,
|
||||||
arms: Vec<(&'a str, ProcStatement<'a>)>,
|
arms: Vec<(Expression<'a>, ProcStatement<'a>)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn match_arm(input: Span) -> IResult<Span, (Expression, ProcStatement)> {
|
||||||
|
separated_pair(ws0(expression), tag("=>"), ws0(proc_statement))(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn match_block(input: Span) -> IResult<Span, MatchBlock> {
|
||||||
|
context(
|
||||||
|
"match block",
|
||||||
|
map(
|
||||||
|
tuple((
|
||||||
|
ws0(tag("match")),
|
||||||
|
ws0(delimited(char('('), ws0(expression), char(')'))),
|
||||||
|
ws0(delimited(char('{'), separated_list1(char(','), ws0(match_arm)), char('}'))),
|
||||||
|
)),
|
||||||
|
|(_, expr, arms)| MatchBlock {
|
||||||
|
expr,
|
||||||
|
arms
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn statement_block(input: Span) -> IResult<Span, Vec<ProcStatement>> {
|
||||||
|
delimited(char('{'), separated_list1(char(';'), ws0(proc_statement)), char('}'))(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// parse a statement that is valid inside a proc block
|
/// parse a statement that is valid inside a proc block
|
||||||
fn proc_statement(input: Span) -> IResult<Span, ProcStatement> {
|
fn proc_statement(input: Span) -> IResult<Span, ProcStatement> {
|
||||||
map(nom::character::complete::anychar, |_| {
|
alt((
|
||||||
ProcStatement::Match(MatchBlock {
|
map(match_block, ProcStatement::Match),
|
||||||
expr: Expression::Ident("asdf"),
|
map(statement_block, ProcStatement::Block),
|
||||||
arms: Vec::new(),
|
map(assign_statement, ProcStatement::Assign),
|
||||||
})
|
))(input)
|
||||||
})(input)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn proc_block(input: Span) -> IResult<Span, ProcBlock> {
|
pub fn proc_block(input: Span) -> IResult<Span, ProcBlock> {
|
||||||
|
@ -49,9 +75,35 @@ pub fn proc_block(input: Span) -> IResult<Span, ProcBlock> {
|
||||||
tuple((
|
tuple((
|
||||||
ws0(tag("proc")),
|
ws0(tag("proc")),
|
||||||
ws0(delimited(char('('), ws0(identifier), char(')'))),
|
ws0(delimited(char('('), ws0(identifier), char(')'))),
|
||||||
ws0(delimited(char('{'), many0(ws0(proc_statement)), char('}'))),
|
ws0(delimited(char('{'), many1(ws0(proc_statement)), char('}'))),
|
||||||
)),
|
)),
|
||||||
|(_, net, items)| ProcBlock { net, items },
|
|(_, net, items)| ProcBlock { net, items },
|
||||||
),
|
),
|
||||||
)(input)
|
)(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_statement() {
|
||||||
|
proc_statement(" abc = def ".into()).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_match_arm() {
|
||||||
|
match_arm(" 1 => abc = def ".into()).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_match_block() {
|
||||||
|
let input = "
|
||||||
|
match (asdf) {
|
||||||
|
1 => a = 0,
|
||||||
|
2 => c = ~d
|
||||||
|
}
|
||||||
|
";
|
||||||
|
match_block(input.into()).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
mod sync;
|
mod sync;
|
||||||
|
|
||||||
use sync::Process;
|
pub use sync::{Process, SyncCond, SyncRule, SwitchRule, CaseRule};
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct ILWriter {
|
pub struct ILWriter {
|
||||||
|
|
|
@ -2,15 +2,15 @@ use crate::rtlil::{RtlilWrite, SigSpec};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Process {
|
pub struct Process {
|
||||||
id: String,
|
pub id: String,
|
||||||
root_case: CaseRule,
|
pub root_case: CaseRule,
|
||||||
sync_rules: Vec<SyncRule>,
|
pub sync_rules: Vec<SyncRule>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct CaseRule {
|
pub struct CaseRule {
|
||||||
assign: Vec<(SigSpec, SigSpec)>,
|
pub assign: Vec<(SigSpec, SigSpec)>,
|
||||||
switches: Vec<SwitchRule>,
|
pub switches: Vec<SwitchRule>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -21,8 +21,8 @@ pub struct SwitchRule {
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct SyncRule {
|
pub struct SyncRule {
|
||||||
cond: SyncCond,
|
pub cond: SyncCond,
|
||||||
assign: Vec<(SigSpec, SigSpec)>,
|
pub assign: Vec<(SigSpec, SigSpec)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -35,8 +35,11 @@ pub enum SyncCond {
|
||||||
impl RtlilWrite for Process {
|
impl RtlilWrite for Process {
|
||||||
fn write_rtlil(&self, writer: &mut super::ILWriter) {
|
fn write_rtlil(&self, writer: &mut super::ILWriter) {
|
||||||
writer.write_line(&format!("process {}", self.id));
|
writer.write_line(&format!("process {}", self.id));
|
||||||
|
writer.indent();
|
||||||
self.root_case.write_rtlil(writer);
|
self.root_case.write_rtlil(writer);
|
||||||
writer.write_iter(&self.sync_rules);
|
writer.write_iter(&self.sync_rules);
|
||||||
|
writer.dedent();
|
||||||
|
writer.write_line("end");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue