start plumbing process blocks
This commit is contained in:
parent
42349a6273
commit
7238d6991c
|
@ -0,0 +1,12 @@
|
||||||
|
module clockdiv_2 (
|
||||||
|
input wire clk,
|
||||||
|
input wire rst,
|
||||||
|
output wire out_clk
|
||||||
|
) {
|
||||||
|
proc (clk) {
|
||||||
|
match (rst) {
|
||||||
|
0 => out_clk = 0,
|
||||||
|
1 => out_clk = ~out_clk,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -135,11 +135,12 @@ pub fn lower_module(pa_module: parser::Module) -> Result<String, CompileError> {
|
||||||
);
|
);
|
||||||
ir_module.add_wire(wire);
|
ir_module.add_wire(wire);
|
||||||
}
|
}
|
||||||
for stmt in pa_module.statements {
|
for item in pa_module.items {
|
||||||
match stmt {
|
match item {
|
||||||
parser::Statement::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")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ir_module.write_rtlil(&mut writer);
|
ir_module.write_rtlil(&mut writer);
|
||||||
|
|
|
@ -8,6 +8,7 @@ use std::fs::File;
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use structopt::StructOpt;
|
use structopt::StructOpt;
|
||||||
|
use nom::error::convert_error;
|
||||||
|
|
||||||
#[derive(Debug, StructOpt)]
|
#[derive(Debug, StructOpt)]
|
||||||
#[structopt(name = "example", about = "An example of StructOpt usage.")]
|
#[structopt(name = "example", about = "An example of StructOpt usage.")]
|
||||||
|
@ -28,9 +29,10 @@ fn main() {
|
||||||
let input = parser::Span::new(input);
|
let input = parser::Span::new(input);
|
||||||
let parsed = parser::parse(input);
|
let parsed = parser::parse(input);
|
||||||
match parsed {
|
match parsed {
|
||||||
Err(nom::Err::Error(_err) | nom::Err::Failure(_err)) => {
|
Err(nom::Err::Error(err) | nom::Err::Failure(err)) => {
|
||||||
// TODO: get this working again
|
// TODO: get pretty errors again
|
||||||
// print!("{}", convert_error(input, err))
|
// print!("{}", convert_error(*input, err))
|
||||||
|
print!("{}", err);
|
||||||
}
|
}
|
||||||
Err(_) => (),
|
Err(_) => (),
|
||||||
Ok(res) => {
|
Ok(res) => {
|
||||||
|
|
|
@ -66,12 +66,37 @@ pub struct PortDecl<'a> {
|
||||||
pub struct Module<'a> {
|
pub struct Module<'a> {
|
||||||
pub name: &'a str,
|
pub name: &'a str,
|
||||||
pub ports: Vec<PortDecl<'a>>,
|
pub ports: Vec<PortDecl<'a>>,
|
||||||
pub statements: Vec<Statement<'a>>,
|
pub items: Vec<ModuleItem<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Statement<'a> {
|
pub enum ModuleItem<'a> {
|
||||||
Assign(Assign<'a>),
|
Assign(Assign<'a>),
|
||||||
|
Proc(ProcBlock<'a>),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct ProcBlock<'a> {
|
||||||
|
pub net: Span<'a>,
|
||||||
|
pub items: Vec<ProcStatement<'a>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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)]
|
#[derive(Debug)]
|
||||||
|
@ -180,7 +205,7 @@ fn expression(input: Span) -> IResult<Span, Expression> {
|
||||||
))(input)
|
))(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn assign_statement(input: Span) -> IResult<Span, Statement> {
|
fn assign_statement(input: Span) -> IResult<Span, Assign> {
|
||||||
context(
|
context(
|
||||||
"assignment",
|
"assignment",
|
||||||
delimited(
|
delimited(
|
||||||
|
@ -188,10 +213,10 @@ fn assign_statement(input: Span) -> IResult<Span, Statement> {
|
||||||
map(
|
map(
|
||||||
separated_pair(ws0(identifier), char('='), ws0(expression)),
|
separated_pair(ws0(identifier), char('='), ws0(expression)),
|
||||||
|(lhs, expr)| {
|
|(lhs, expr)| {
|
||||||
Statement::Assign(Assign {
|
Assign {
|
||||||
lhs: (*lhs.fragment()),
|
lhs: (*lhs.fragment()),
|
||||||
expr,
|
expr,
|
||||||
})
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
ws0(char(';')),
|
ws0(char(';')),
|
||||||
|
@ -199,6 +224,47 @@ fn assign_statement(input: Span) -> IResult<Span, Statement> {
|
||||||
)(input)
|
)(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// parse a statement that is valid inside a proc block
|
||||||
|
fn proc_statement(input: Span) -> IResult<Span, ProcStatement> {
|
||||||
|
map(
|
||||||
|
nom::character::complete::anychar,
|
||||||
|
|_| {
|
||||||
|
ProcStatement::Match(MatchBlock {
|
||||||
|
expr: Expression::Ident("asdf"),
|
||||||
|
arms: Vec::new(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn proc_block(input: Span) -> IResult<Span, ProcBlock> {
|
||||||
|
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<Span, ModuleItem> {
|
||||||
|
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<Span, Module> {
|
pub fn module(input: Span) -> IResult<Span, Module> {
|
||||||
context(
|
context(
|
||||||
"module",
|
"module",
|
||||||
|
@ -209,14 +275,14 @@ pub fn module(input: Span) -> IResult<Span, Module> {
|
||||||
ws0(delimited(char('('), ws0(ports_list), char(')'))),
|
ws0(delimited(char('('), ws0(ports_list), char(')'))),
|
||||||
ws0(delimited(
|
ws0(delimited(
|
||||||
char('{'),
|
char('{'),
|
||||||
many1(ws0(assign_statement)),
|
many1(ws0(module_item)),
|
||||||
char('}'),
|
char('}'),
|
||||||
)),
|
)),
|
||||||
)),
|
)),
|
||||||
|(_, name, ports, statements)| Module {
|
|(_, name, ports, items)| Module {
|
||||||
name: (*name.fragment()),
|
name: (*name.fragment()),
|
||||||
ports,
|
ports,
|
||||||
statements,
|
items,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
)(input)
|
)(input)
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
mod sync;
|
mod sync;
|
||||||
|
|
||||||
|
use sync::Process;
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct ILWriter {
|
pub struct ILWriter {
|
||||||
data: String,
|
data: String,
|
||||||
|
@ -120,6 +122,7 @@ pub struct Module {
|
||||||
name: String,
|
name: String,
|
||||||
wires: Vec<Wire>,
|
wires: Vec<Wire>,
|
||||||
cells: Vec<Cell>,
|
cells: Vec<Cell>,
|
||||||
|
processes: Vec<Process>,
|
||||||
connections: Vec<(SigSpec, SigSpec)>,
|
connections: Vec<(SigSpec, SigSpec)>,
|
||||||
gen_id: i32,
|
gen_id: i32,
|
||||||
}
|
}
|
||||||
|
@ -131,6 +134,7 @@ impl Module {
|
||||||
wires: Default::default(),
|
wires: Default::default(),
|
||||||
cells: Default::default(),
|
cells: Default::default(),
|
||||||
connections: Default::default(),
|
connections: Default::default(),
|
||||||
|
processes: Default::default(),
|
||||||
gen_id: 0,
|
gen_id: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -147,6 +151,10 @@ impl Module {
|
||||||
self.cells.push(cell)
|
self.cells.push(cell)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn add_process(&mut self, proc: Process) {
|
||||||
|
self.processes.push(proc)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn make_genid(&mut self, stem: &str) -> String {
|
pub fn make_genid(&mut self, stem: &str) -> String {
|
||||||
let res = format!("${}${}", stem, self.gen_id);
|
let res = format!("${}${}", stem, self.gen_id);
|
||||||
self.gen_id += 1;
|
self.gen_id += 1;
|
||||||
|
@ -160,6 +168,7 @@ impl RtlilWrite for Module {
|
||||||
writer.indent();
|
writer.indent();
|
||||||
writer.write_iter(&self.wires);
|
writer.write_iter(&self.wires);
|
||||||
writer.write_iter(&self.cells);
|
writer.write_iter(&self.cells);
|
||||||
|
writer.write_iter(&self.processes);
|
||||||
for conn in &self.connections {
|
for conn in &self.connections {
|
||||||
writer.write_line(&format!("connect {} {}", conn.0, conn.1))
|
writer.write_line(&format!("connect {} {}", conn.0, conn.1))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,26 +1,31 @@
|
||||||
use crate::rtlil::{RtlilWrite, SigSpec};
|
use crate::rtlil::{RtlilWrite, SigSpec};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct Process {
|
pub struct Process {
|
||||||
id: String,
|
id: String,
|
||||||
root_case: CaseRule,
|
root_case: CaseRule,
|
||||||
sync_rules: Vec<SyncRule>,
|
sync_rules: Vec<SyncRule>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct CaseRule {
|
pub struct CaseRule {
|
||||||
assign: Vec<(SigSpec, SigSpec)>,
|
assign: Vec<(SigSpec, SigSpec)>,
|
||||||
switches: Vec<SwitchRule>,
|
switches: Vec<SwitchRule>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct SwitchRule {
|
pub struct SwitchRule {
|
||||||
signal: String,
|
signal: String,
|
||||||
cases: Vec<CaseRule>,
|
cases: Vec<CaseRule>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct SyncRule {
|
pub struct SyncRule {
|
||||||
cond: SyncCond,
|
cond: SyncCond,
|
||||||
assign: Vec<(SigSpec, SigSpec)>,
|
assign: Vec<(SigSpec, SigSpec)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub enum SyncCond {
|
pub enum SyncCond {
|
||||||
Always,
|
Always,
|
||||||
Posedge(String),
|
Posedge(String),
|
||||||
|
|
Loading…
Reference in New Issue