make operators work via desugaring
This commit is contained in:
parent
95d9313cdd
commit
057511f56c
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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"),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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),
|
||||||
|
|
Loading…
Reference in New Issue