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);
|
||||
}
|
||||
for stmt in pa_module.statements {
|
||||
match stmt {
|
||||
parser::Statement::Assign(assignment) => {
|
||||
for item in pa_module.items {
|
||||
match item {
|
||||
parser::ModuleItem::Assign(assignment) => {
|
||||
lower_assignment(&context, &mut ir_module, assignment)?
|
||||
}
|
||||
parser::ModuleItem::Proc(proc) => todo!("lowering process")
|
||||
}
|
||||
}
|
||||
ir_module.write_rtlil(&mut writer);
|
||||
|
|
|
@ -8,6 +8,7 @@ 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.")]
|
||||
|
@ -28,9 +29,10 @@ fn main() {
|
|||
let input = parser::Span::new(input);
|
||||
let parsed = parser::parse(input);
|
||||
match parsed {
|
||||
Err(nom::Err::Error(_err) | nom::Err::Failure(_err)) => {
|
||||
// TODO: get this working again
|
||||
// print!("{}", convert_error(input, err))
|
||||
Err(nom::Err::Error(err) | nom::Err::Failure(err)) => {
|
||||
// TODO: get pretty errors again
|
||||
// print!("{}", convert_error(*input, err))
|
||||
print!("{}", err);
|
||||
}
|
||||
Err(_) => (),
|
||||
Ok(res) => {
|
||||
|
|
|
@ -66,12 +66,37 @@ pub struct PortDecl<'a> {
|
|||
pub struct Module<'a> {
|
||||
pub name: &'a str,
|
||||
pub ports: Vec<PortDecl<'a>>,
|
||||
pub statements: Vec<Statement<'a>>,
|
||||
pub items: Vec<ModuleItem<'a>>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Statement<'a> {
|
||||
pub enum ModuleItem<'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)]
|
||||
|
@ -180,7 +205,7 @@ fn expression(input: Span) -> IResult<Span, Expression> {
|
|||
))(input)
|
||||
}
|
||||
|
||||
fn assign_statement(input: Span) -> IResult<Span, Statement> {
|
||||
fn assign_statement(input: Span) -> IResult<Span, Assign> {
|
||||
context(
|
||||
"assignment",
|
||||
delimited(
|
||||
|
@ -188,10 +213,10 @@ fn assign_statement(input: Span) -> IResult<Span, Statement> {
|
|||
map(
|
||||
separated_pair(ws0(identifier), char('='), ws0(expression)),
|
||||
|(lhs, expr)| {
|
||||
Statement::Assign(Assign {
|
||||
Assign {
|
||||
lhs: (*lhs.fragment()),
|
||||
expr,
|
||||
})
|
||||
}
|
||||
},
|
||||
),
|
||||
ws0(char(';')),
|
||||
|
@ -199,6 +224,47 @@ fn assign_statement(input: Span) -> IResult<Span, Statement> {
|
|||
)(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> {
|
||||
context(
|
||||
"module",
|
||||
|
@ -209,14 +275,14 @@ pub fn module(input: Span) -> IResult<Span, Module> {
|
|||
ws0(delimited(char('('), ws0(ports_list), char(')'))),
|
||||
ws0(delimited(
|
||||
char('{'),
|
||||
many1(ws0(assign_statement)),
|
||||
many1(ws0(module_item)),
|
||||
char('}'),
|
||||
)),
|
||||
)),
|
||||
|(_, name, ports, statements)| Module {
|
||||
|(_, name, ports, items)| Module {
|
||||
name: (*name.fragment()),
|
||||
ports,
|
||||
statements,
|
||||
items,
|
||||
},
|
||||
),
|
||||
)(input)
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
mod sync;
|
||||
|
||||
use sync::Process;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct ILWriter {
|
||||
data: String,
|
||||
|
@ -120,6 +122,7 @@ pub struct Module {
|
|||
name: String,
|
||||
wires: Vec<Wire>,
|
||||
cells: Vec<Cell>,
|
||||
processes: Vec<Process>,
|
||||
connections: Vec<(SigSpec, SigSpec)>,
|
||||
gen_id: i32,
|
||||
}
|
||||
|
@ -131,6 +134,7 @@ impl Module {
|
|||
wires: Default::default(),
|
||||
cells: Default::default(),
|
||||
connections: Default::default(),
|
||||
processes: Default::default(),
|
||||
gen_id: 0,
|
||||
}
|
||||
}
|
||||
|
@ -147,6 +151,10 @@ impl Module {
|
|||
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 {
|
||||
let res = format!("${}${}", stem, self.gen_id);
|
||||
self.gen_id += 1;
|
||||
|
@ -160,6 +168,7 @@ impl RtlilWrite for Module {
|
|||
writer.indent();
|
||||
writer.write_iter(&self.wires);
|
||||
writer.write_iter(&self.cells);
|
||||
writer.write_iter(&self.processes);
|
||||
for conn in &self.connections {
|
||||
writer.write_line(&format!("connect {} {}", conn.0, conn.1))
|
||||
}
|
||||
|
|
|
@ -1,26 +1,31 @@
|
|||
use crate::rtlil::{RtlilWrite, SigSpec};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Process {
|
||||
id: String,
|
||||
root_case: CaseRule,
|
||||
sync_rules: Vec<SyncRule>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CaseRule {
|
||||
assign: Vec<(SigSpec, SigSpec)>,
|
||||
switches: Vec<SwitchRule>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct SwitchRule {
|
||||
signal: String,
|
||||
cases: Vec<CaseRule>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct SyncRule {
|
||||
cond: SyncCond,
|
||||
assign: Vec<(SigSpec, SigSpec)>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum SyncCond {
|
||||
Always,
|
||||
Posedge(String),
|
||||
|
|
Loading…
Reference in New Issue