make operators work via desugaring

This commit is contained in:
NotAFile 2022-01-17 19:20:51 +01:00
parent 95d9313cdd
commit 057511f56c
6 changed files with 65 additions and 10 deletions

View File

@ -4,9 +4,9 @@ module clockdiv_2 (
output wire out_clk output wire out_clk
) { ) {
proc (clk) { proc (clk) {
match (not(rst)) { match (~rst) {
0 => out_clk = 0, 0 => out_clk = 0,
1 => out_clk = not(out_clk) 1 => out_clk = ~out_clk
} }
} }
} }

View File

@ -3,5 +3,5 @@ module comparator (
input wire [8] b, input wire [8] b,
output wire eq output wire eq
) { ) {
assign eq = not(reduce_or(xor(a, b))); assign eq = ~reduce_or(a ^ b);
} }

View File

@ -5,6 +5,6 @@ module halfadd (
output wire carry output wire carry
) )
{ {
assign sum = xor(a, b); assign sum = a ^ b;
assign carry = and(a, b); assign carry = a & b;
} }

View File

@ -77,5 +77,6 @@ pub fn get_builtins() -> Vec<Callable> {
make_binop_callable("xor", "$xor"), make_binop_callable("xor", "$xor"),
make_binop_callable("xnor", "$xnor"), make_binop_callable("xnor", "$xnor"),
make_unnop_callable("not", "$not"), make_unnop_callable("not", "$not"),
make_unnop_callable("reduce_or", "$reduce_or"),
] ]
} }

View File

@ -140,11 +140,64 @@ fn lower_process(
Ok(()) Ok(())
} }
fn desugar_operation<'a>(op: parser::Operation<'a>) -> parser::Call<'a> {
match op {
parser::Operation::And { a, b } => {
let a = desugar_expression(a);
let b = desugar_expression(b);
parser::Call {
name: "and".into(),
args: vec![a, b]
}
},
parser::Operation::Or { a, b } => {
let a = desugar_expression(a);
let b = desugar_expression(b);
parser::Call {
name: "or".into(),
args: vec![a, b]
}
}
parser::Operation::Xor { a, b } => {
let a = desugar_expression(a);
let b = desugar_expression(b);
parser::Call {
name: "xor".into(),
args: vec![a, b]
}
}
parser::Operation::Not(a) => {
let a = desugar_expression(a);
parser::Call {
name: "not".into(),
args: vec![a]
}
}
}
}
fn desugar_expression<'a>(expr: parser::Expression<'a>) -> parser::Expression<'a> {
// TODO: allow ergonomic traversal of AST
match expr {
parser::Expression::Ident(_) => expr,
parser::Expression::Literal(_) => expr,
parser::Expression::Call(mut call) => {
let new_args = call.args.into_iter().map(|argex| desugar_expression(argex)).collect();
call.args = new_args;
parser::Expression::Call(call)
},
parser::Expression::Operation(op) => {
parser::Expression::Call(Box::new(desugar_operation(*op)))
},
}
}
fn lower_expression( fn lower_expression(
ctx: &Context, ctx: &Context,
module: &mut rtlil::Module, module: &mut rtlil::Module,
expr: &parser::Expression, expr: &parser::Expression,
) -> Result<rtlil::SigSpec, CompileError> { ) -> Result<rtlil::SigSpec, CompileError> {
let expr = desugar_expression(expr.clone());
match expr { match expr {
parser::Expression::Ident(ident) => Ok(rtlil::SigSpec::Wire(make_pubid(ident))), parser::Expression::Ident(ident) => Ok(rtlil::SigSpec::Wire(make_pubid(ident))),
parser::Expression::Call(call) => { parser::Expression::Call(call) => {
@ -181,9 +234,10 @@ fn lower_expression(
module.add_cell(cell); module.add_cell(cell);
Ok(output_gen_wire) Ok(output_gen_wire)
} }
// operations should really just desugar to callables // TODO: instantiate operators directly here instead of desugaring, once the callable infrastructure improves
// to get better errors
parser::Expression::Operation(_op) => todo!("operators not yet implemented"), parser::Expression::Operation(_op) => todo!("operators not yet implemented"),
parser::Expression::Literal(lit) => Ok(rtlil::SigSpec::Const(*lit as i64, TODO_WIDTH)), parser::Expression::Literal(lit) => Ok(rtlil::SigSpec::Const(lit as i64, TODO_WIDTH)),
} }
} }

View File

@ -59,7 +59,7 @@ pub struct Assign<'a> {
pub expr: Expression<'a>, pub expr: Expression<'a>,
} }
#[derive(Debug)] #[derive(Debug, Clone)]
pub enum Operation<'a> { pub enum Operation<'a> {
And { And {
a: Expression<'a>, a: Expression<'a>,
@ -76,13 +76,13 @@ pub enum Operation<'a> {
Not(Expression<'a>), Not(Expression<'a>),
} }
#[derive(Debug)] #[derive(Debug, Clone)]
pub struct Call<'a> { pub struct Call<'a> {
pub name: Span<'a>, pub name: Span<'a>,
pub args: Vec<Expression<'a>>, pub args: Vec<Expression<'a>>,
} }
#[derive(Debug)] #[derive(Debug, Clone)]
pub enum Expression<'a> { pub enum Expression<'a> {
Ident(&'a str), Ident(&'a str),
Literal(u64), Literal(u64),