use crate::ast;
use crate::ast::Int;
use crate::lexer::*;
grammar;
extern {
type Location = usize;
type Error = LexicalError;
enum Token {
"indent" => Token::Indent,
"dedent" => Token::Dedent,
"info" => Token::Info(<String>),
"annotations" => Token::Annotations(<String>),
"id" => Token::ID(<Int>),
" " => Token::Space,
"\t" => Token::Tab,
"\n" => Token::Newline,
"radixint" => Token::RadixInt(<String>),
"int" => Token::IntegerDec(<Int>),
"identifier" => Token::Identifier(<String>),
"string" => Token::String(<String>),
"/" => Token::Slash,
"[" => Token::LeftSquare,
"]" => Token::RightSquare,
"<" => Token::LeftAngle,
">" => Token::RightAngle,
"{" => Token::LeftBracket,
"}" => Token::RightBracket,
"(" => Token::LeftParenthesis,
")" => Token::RightParenthesis,
"@" => Token::AtSymbol,
"`" => Token::Backtick,
"%[[" => Token::AnnoStart,
"<<" => Token::DoubleLeft,
">>" => Token::DoubleRight,
"clock" => Token::Clock,
"reset" => Token::Reset,
"async_reset" => Token::AsyncReset,
"uint" => Token::UInt,
"sint" => Token::SInt,
"probe_type" => Token::ProbeType,
"probe" => Token::Probe,
"analog" => Token::Analog,
"fixed" => Token::Fixed,
"flip" => Token::Flip,
"primop_e2" => Token::E2Op(<String>),
"primop_e1" => Token::E1Op(<String>),
"primop_e1i1" => Token::E1I1Op(<String>),
"primop_e1i2" => Token::E1I2Op(<String>),
"mux" => Token::Mux,
"validif" => Token::ValidIf,
"smem" => Token::SMem,
"cmem" => Token::CMem,
"write" => Token::Write,
"read" => Token::Read,
"infer" => Token::Infer,
"mport" => Token::Mport,
"datatype" => Token::DataType,
"depth" => Token::Depth,
"read_lat" => Token::ReadLatency,
"write_lat" => Token::WriteLatency,
"read_under_write" => Token::ReadUnderWrite,
"wire" => Token::Wire,
"reg" => Token::Reg,
"reg_reset" => Token::RegReset,
"inst" => Token::Inst,
"of" => Token::Of,
"node" => Token::Node,
"invalidate" => Token::Invalidate,
"attach" => Token::Attach,
"when" => Token::When,
"else" => Token::Else,
"stop" => Token::Stop,
"printf" => Token::Printf,
"assert" => Token::Assert,
"skip" => Token::Skip,
"input" => Token::Input,
"output" => Token::Output,
"module" => Token::Module,
"extmodule" => Token::ExtModule,
"intmodule" => Token::IntModule,
"defname" => Token::DefName,
"parameter" => Token::Parameter,
"intrinsic" => Token::Intrinsic,
"FIRRTL" => Token::FIRRTL,
"version" => Token::Version,
"circuit" => Token::Circuit,
"connect" => Token::Connect,
"public" => Token::Public,
"define" => Token::Define,
"const" => Token::Const,
"symbol" => Token::Symbol(<String>),
"." => Token::Period,
}
}
pub Float: ast::Float = {
<integer: "int"> "." <decimal: "id"> => ast::Float::new(integer.to_u32(), decimal.to_u32()),
};
pub Info: ast::Info = {
<info: "info"> => ast::Info(info)
};
// TODO: Add radint case
pub Width: ast::Width = {
"<" <w: "int"> ">" => ast::Width(w.to_u32()),
};
pub TypeGround: ast::TypeGround = {
"reset" => ast::TypeGround::Reset,
"clock" => ast::TypeGround::Clock,
"async_reset" => ast::TypeGround::AsyncReset,
"uint" <w: Width> => ast::TypeGround::UInt(Some(w)),
"uint" => ast::TypeGround::UInt(None),
"sint" <w: Width> => ast::TypeGround::SInt(Some(w)),
"sint" => ast::TypeGround::SInt(None),
};
pub Fields: ast::Fields = {
<mut head: Fields> "symbol" <tail: Field> => { head.push(Box::new(tail)); head } ,
<head: Field> => vec![Box::new(head)],
};
pub Field: ast::Field = {
<name: Identifier> "symbol" <tpe: Type> => ast::Field::Straight(name, Box::new(tpe)),
"flip" <name: Identifier> "symbol" <tpe: Type> => ast::Field::Flipped(name, Box::new(tpe)),
};
pub TypeAggregate: ast::TypeAggregate = {
"{" "}" => ast::TypeAggregate::Fields(Box::new(vec![])),
"{" <fields: Fields> "}" => ast::TypeAggregate::Fields(Box::new(fields)),
<tpe: Type> "[" <i: "int"> "]" => ast::TypeAggregate::Array(Box::new(tpe), i),
<tpe: Type> "[" <i: "id"> "]" => ast::TypeAggregate::Array(Box::new(tpe), i),
};
pub Type: ast::Type = {
<tg: TypeGround> => ast::Type::TypeGround(tg),
// "const" <tg: TypeGround> => ast::Type::ConstTypeGround(tg),
<ta: TypeAggregate> => ast::Type::TypeAggregate(Box::new(ta)),
// "const" <ta: TypeAggregate> => ast::Type::ConstTypeAggregate(Box::new(ta)),
};
pub Identifier: ast::Identifier = {
<id: "id"> => ast::Identifier::ID(id),
"inst" => ast::Identifier::Name("inst".to_string()),
"printf" => ast::Identifier::Name("printf".to_string()),
"assert" => ast::Identifier::Name("assert".to_string()),
"smem" => ast::Identifier::Name("smem".to_string()),
"cmem" => ast::Identifier::Name("cmem".to_string()),
"of" => ast::Identifier::Name("of".to_string()),
"reg" => ast::Identifier::Name("reg".to_string()),
"input" => ast::Identifier::Name("input".to_string()),
"output" => ast::Identifier::Name("output".to_string()),
"invalidate" => ast::Identifier::Name("invalidate".to_string()),
"mux" => ast::Identifier::Name("mux".to_string()),
"stop" => ast::Identifier::Name("stop".to_string()),
"depth" => ast::Identifier::Name("depth".to_string()),
"skip" => ast::Identifier::Name("skip".to_string()),
"write" => ast::Identifier::Name("write".to_string()),
"read" => ast::Identifier::Name("read".to_string()),
"version" => ast::Identifier::Name("version".to_string()),
"probe" => ast::Identifier::Name("probe".to_string()),
"module" => ast::Identifier::Name("module".to_string()),
"const" => ast::Identifier::Name("const".to_string()),
<x: "primop_e2"> => ast::Identifier::Name(x),
<x: "primop_e1"> => ast::Identifier::Name(x),
<x: "primop_e1i1"> => ast::Identifier::Name(x),
<identifier: "identifier"> => ast::Identifier::Name(identifier),
};
pub PrimOp2Expr: ast::PrimOp2Expr = {
<op: "primop_e2"> "(" => ast::PrimOp2Expr::from(op),
};
pub PrimOp1Expr: ast::PrimOp1Expr = {
<op: "primop_e1"> "(" => ast::PrimOp1Expr::from(op),
};
pub PrimOp1Expr1Int: ast::PrimOp1Expr1Int = {
<op: "primop_e1i1"> "(" => ast::PrimOp1Expr1Int::from(op),
};
pub PrimOp1Expr2Int: ast::PrimOp1Expr2Int = {
<op: "primop_e1i2"> => ast::PrimOp1Expr2Int::from(op),
};
pub Exprs: ast::Exprs = {
<mut head: Exprs> "symbol" <tail: Expr> => { head.push(Box::new(tail)); head },
<head: Expr> => vec![Box::new(head)],
};
pub Expr: ast::Expr = {
<u: "uint"> <w: Width> "(" ")" => ast::Expr::UIntNoInit(w),
<u: "uint"> <w: Width> "(" <i: "int"> ")" => ast::Expr::UIntInit(w, i),
<u: "uint"> <w: Width> "(" <ri: "radixint"> ")" => ast::Expr::UIntInit(w, ast::Expr::parse_radixint(&ri).expect("parse_radixint")),
<s: "sint"> <w: Width> "(" ")" => ast::Expr::SIntNoInit(w),
<s: "sint"> <w: Width> "(" <i: "int"> ")" => ast::Expr::SIntInit(w, i),
<s: "sint"> <w: Width> "(" <ri: "radixint"> ")" => ast::Expr::SIntInit(w, ast::Expr::parse_radixint(&ri).expect("parse_radixint")),
<r: Reference> => ast::Expr::Reference(r),
<m: "mux"> "(" <sel: Expr> "symbol" <exp_true: Expr> "symbol" <exp_false: Expr> ")" => ast::Expr::Mux(Box::new(sel), Box::new(exp_true), Box::new(exp_false)),
<vif: "validif"> "(" <if_expr: Expr> "symbol" <expr: Expr> ")" => ast::Expr::ValidIf(Box::new(if_expr), Box::new(expr)),
<op: PrimOp2Expr> <e1: Expr> "symbol" <e2: Expr> ")" => ast::Expr::PrimOp2Expr(op, Box::new(e1), Box::new(e2)),
<op: PrimOp1Expr> <e1: Expr> ")" => ast::Expr::PrimOp1Expr(op, Box::new(e1)),
<op: PrimOp1Expr1Int> <e1: Expr> "symbol" <int: "int"> ")" => ast::Expr::PrimOp1Expr1Int(op, Box::new(e1), int),
<op: PrimOp1Expr2Int> <e1: Expr> "symbol" <int1: "int"> "symbol" <int2: "int"> ")" => ast::Expr::PrimOp1Expr2Int(op, Box::new(e1), int1, int2),
// TODO: add all other primop cases
// <op: PrimOp1Expr2Int> <e1: "primop_e1i1"> "symbol" <int1: "int"> "symbol" <int2: "int"> ")" => {
// ast::Expr::PrimOp1Expr2Int(op, Box::new(ast::Expr::Reference(ast::Reference::Ref(ast::Identifier::Name(e1)))), int1, int2)
// },
};
pub ChirrtlMemoryDataType: ast::Type = {
<tpe: Type> => { tpe }
};
pub ChirrtlMemoryReadUnderWrite: ast::ChirrtlMemoryReadUnderWrite = {
// FIXME: Properly set this flag
"read_under_write" => ast::ChirrtlMemoryReadUnderWrite::default(),
};
pub ChirrtlMemory: ast::ChirrtlMemory = {
"smem" <name: Identifier> "symbol" <tpe: ChirrtlMemoryDataType> "symbol" <ruw: ChirrtlMemoryReadUnderWrite> <info: Info> => ast::ChirrtlMemory::SMem(name, tpe, Some(ruw), info),
"smem" <name: Identifier> "symbol" <tpe: ChirrtlMemoryDataType> <info: Info> => ast::ChirrtlMemory::SMem(name, tpe, None, info),
"cmem" <name: Identifier> "symbol" <tpe: ChirrtlMemoryDataType> <info: Info> => ast::ChirrtlMemory::CMem(name, tpe, info),
// TODO: add all other primop cases
// "smem" <name: "primop_e1i1"> "symbol" <tpe: ChirrtlMemoryDataType> "symbol" <ruw: ChirrtlMemoryReadUnderWrite> <info: Info> => ast::ChirrtlMemory::SMem(ast::Identifier::Name(name), tpe, Some(ruw), info),
// "smem" <name: "primop_e1i1"> "symbol" <tpe: ChirrtlMemoryDataType> <info: Info> => ast::ChirrtlMemory::SMem(ast::Identifier::Name(name), tpe, None, info),
// "cmem" <name: "primop_e1i1"> "symbol" <tpe: ChirrtlMemoryDataType> <info: Info> => ast::ChirrtlMemory::CMem(ast::Identifier::Name(name), tpe, info),
};
pub ChirrtlMemoryPort: ast::ChirrtlMemoryPort = {
"write" "mport" <name: Identifier> "symbol" <mem_ref: Identifier> "[" <addr_ref: Expr> "]" "symbol" <clk_ref: Reference> <info: Info> => ast::ChirrtlMemoryPort::Write(name, mem_ref, addr_ref, clk_ref, info),
"read" "mport" <name: Identifier> "symbol" <mem_ref: Identifier> "[" <addr_ref: Expr> "]" "symbol" <clk_ref: Reference> <info: Info> => ast::ChirrtlMemoryPort::Read(name, mem_ref, addr_ref, clk_ref, info),
"infer" "mport" <name: Identifier> "symbol" <mem_ref: Identifier> "[" <addr_ref: Expr> "]" "symbol" <clk_ref: Reference> <info: Info> => ast::ChirrtlMemoryPort::Infer(name, mem_ref, addr_ref, clk_ref, info),
}
// pub Refs = Comma<Ref>;
pub Reference: ast::Reference = {
<name: Identifier> => ast::Reference::Ref(name),
<r: Reference> "." <idx: Identifier> => ast::Reference::RefDot(Box::new(r), idx),
<r: Reference> "[" <idx: "int"> "]" => ast::Reference::RefIdxInt(Box::new(r), idx),
<r: Reference> "[" <idx: Expr> "]" => ast::Reference::RefIdxExpr(Box::new(r), Box::new(idx)),
};
pub Stmts: ast::Stmts = {
<mut head: Stmts> <tail: Stmt> => { head.push(Box::new(tail)); head } ,
<head: Stmt> => vec![Box::new(head)],
};
pub Stmt: ast::Stmt = {
"wire" <name: Identifier> "symbol" <tpe: Type> <info: Info> => ast::Stmt::Wire(name, tpe, info),
"wire" <name: Identifier> "symbol" <tpe: Type> => ast::Stmt::Wire(name, tpe, ast::Info::default()),
"reg" <name: Identifier> "symbol" <tpe: Type> "symbol" <clk: Expr> <info: Info> => ast::Stmt::Reg(name, tpe, clk, info),
"reg" <name: Identifier> "symbol" <tpe: Type> "symbol" <clk: Expr> => ast::Stmt::Reg(name, tpe, clk, ast::Info::default()),
"reg_reset" <name: Identifier> "symbol" <tpe: Type> "symbol" <clk: Expr> "symbol" <rst: Expr> "symbol" <init: Expr> <info: Info> => ast::Stmt::RegReset(name, tpe, clk, rst, init, info),
"reg_reset" <name: Identifier> "symbol" <tpe: Type> "symbol" <clk: Expr> "symbol" <rst: Expr> "symbol" <init: Expr> => ast::Stmt::RegReset(name, tpe, clk, rst, init, ast::Info::default()),
<m: ChirrtlMemory> => ast::Stmt::ChirrtlMemory(m),
<mp: ChirrtlMemoryPort> => ast::Stmt::ChirrtlMemoryPort(mp),
"inst" <inst: Identifier> "of" <module: Identifier> <info: Info> => ast::Stmt::Inst(inst, module, info),
"inst" <inst: Identifier> "of" <module: Identifier> => ast::Stmt::Inst(inst, module, ast::Info::default()),
"node" <name: Identifier> "symbol" <expr: Expr> <info: Info> => ast::Stmt::Node(name, expr, info),
"node" <name: Identifier> "symbol" <expr: Expr> => ast::Stmt::Node(name, expr, ast::Info::default()),
// TODO: add all other primop cases
// "node" <name: "primop_e1i1"> "symbol" <expr: Expr> <info: Info> => ast::Stmt::Node(ast::Identifier::Name(name), expr, info),
"connect" <sink: Expr> "symbol" <driver: Expr> <info: Info> => ast::Stmt::Connect(sink, driver, info),
"connect" <sink: Expr> "symbol" <driver: Expr> => ast::Stmt::Connect(sink, driver, ast::Info::default()),
"invalidate" <exp: Expr> <info: Info> => ast::Stmt::Invalidate(exp, info),
"invalidate" <exp: Expr> => ast::Stmt::Invalidate(exp, ast::Info::default()),
"when" <cond: Expr> "symbol" <info: Info> "indent" <stmts_true: Stmts> "dedent" "else" "symbol" "indent" <stmts_false: Stmts> "dedent" => ast::Stmt::When(cond, info, stmts_true, Some(stmts_false)),
"when" <cond: Expr> "symbol" <info: Info> "indent" <stmts_true: Stmts> "dedent" => ast::Stmt::When(cond, info, stmts_true, None),
"when" <cond: Expr> "symbol" "indent" <stmts_true: Stmts> "dedent" "else" "symbol" "indent" <stmts_false: Stmts> "dedent" => ast::Stmt::When(cond, ast::Info::default(), stmts_true, Some(stmts_false)),
"when" <cond: Expr> "symbol" "indent" <stmts_true: Stmts> "dedent" => ast::Stmt::When(cond, ast::Info::default(), stmts_true, None),
"printf" "(" <clk: Expr> "symbol" <clk_val: Expr> "symbol" <msg: "string"> "symbol" <exprs: Exprs> ")" "symbol" <name: Identifier> <info: Info> => ast::Stmt::Printf(clk, clk_val, msg, Some(exprs), info),
"printf" "(" <clk: Expr> "symbol" <clk_val: Expr> "symbol" <msg: "string"> "symbol" <exprs: Exprs> ")" <info: Info> => ast::Stmt::Printf(clk, clk_val, msg, Some(exprs), info),
"printf" "(" <clk: Expr> "symbol" <clk_val: Expr> "symbol" <msg: "string"> ")" "symbol" <name: Identifier> <info: Info> => ast::Stmt::Printf(clk, clk_val, msg, None, info),
"printf" "(" <clk: Expr> "symbol" <clk_val: Expr> "symbol" <msg: "string"> ")" <info: Info> => ast::Stmt::Printf(clk, clk_val, msg, None, info),
"printf" "(" <clk: Expr> "symbol" <clk_val: Expr> "symbol" <msg: "string"> "symbol" <exprs: Exprs> ")" "symbol" <name: Identifier> => ast::Stmt::Printf(clk, clk_val, msg, Some(exprs), ast::Info::default()),
"printf" "(" <clk: Expr> "symbol" <clk_val: Expr> "symbol" <msg: "string"> "symbol" <exprs: Exprs> ")" => ast::Stmt::Printf(clk, clk_val, msg, Some(exprs), ast::Info::default()),
"printf" "(" <clk: Expr> "symbol" <clk_val: Expr> "symbol" <msg: "string"> ")" "symbol" <name: Identifier> => ast::Stmt::Printf(clk, clk_val, msg, None, ast::Info::default()),
"printf" "(" <clk: Expr> "symbol" <clk_val: Expr> "symbol" <msg: "string"> ")" => ast::Stmt::Printf(clk, clk_val, msg, None, ast::Info::default()),
"assert" "(" <clk: Expr> "symbol" <pred: Expr> "symbol" <cond: Expr> "symbol" <msg: "string"> ")" "symbol" <name: Identifier> <info: Info> => ast::Stmt::Assert(clk, pred, cond, msg, info),
"assert" "(" <clk: Expr> "symbol" <pred: Expr> "symbol" <cond: Expr> "symbol" <msg: "string"> ")" "symbol" <name: Identifier> => ast::Stmt::Assert(clk, pred, cond, msg, ast::Info::default()),
"skip" => ast::Stmt::Skip(ast::Info::default()),
"skip" <info: Info> => ast::Stmt::Skip(info),
};
pub Ports: ast::Ports = {
<mut head: Ports> <tail: Port> => { head.push(Box::new(tail)); head } ,
<head: Port> => vec![Box::new(head)],
};
pub Port: ast::Port = {
"input" <name: Identifier> "symbol" <tpe: Type> <info: Info> => ast::Port::Input(name, tpe, info),
"input" <name: Identifier> "symbol" <tpe: Type> => ast::Port::Input(name, tpe, ast::Info::default()),
"output" <name: Identifier> "symbol" <tpe: Type> <info: Info> => ast::Port::Output(name, tpe, info),
"output" <name: Identifier> "symbol" <tpe: Type> => ast::Port::Output(name, tpe, ast::Info::default()),
};
pub Module: ast::Module = {
"module" <name: Identifier> "symbol" <info: Info> "indent" <ports: Ports> <stmts: Stmts> "dedent" => ast::Module::new(name, ports, stmts, info),
"public" "module" <name: Identifier> "symbol" <info: Info> "indent" <ports: Ports> <stmts: Stmts> "dedent" => ast::Module::new(name, ports, stmts, info),
};
pub DefName: ast::DefName = {
"defname" "symbol" <name: Identifier> => ast::DefName::from(name),
};
pub Parameter: ast::Parameter = {
"parameter" <name: Identifier> "symbol" <msg: "string"> => ast::Parameter::StringParam(name, msg),
"parameter" <name: Identifier> "symbol" <val: Float> => ast::Parameter::FloatParam(name, val),
"parameter" <name: Identifier> "symbol" <val: "int"> => ast::Parameter::IntParam(name, val),
};
pub Parameters: ast::Parameters = {
<mut head: Parameters> <tail: Parameter> => { head.push(Box::new(tail)); head } ,
<head: Parameter> => vec![Box::new(head)],
};
pub ExtModule: ast::ExtModule = {
"extmodule" <name: Identifier> "symbol" <info: Info> "indent" <ports: Ports> <defname: DefName> <params: Parameters> "dedent" => ast::ExtModule::new(name, ports, defname, params, info),
"extmodule" <name: Identifier> "symbol" <info: Info> "indent" <ports: Ports> <defname: DefName> "dedent" => ast::ExtModule::new(name, ports, defname, vec![], info),
};
pub Annotations: ast::Annotations = {
<a: "annotations"> => ast::Annotations::from_str(a)
};
pub Version: ast::Version = {
"FIRRTL" "version" <a: "int"> "." <b: "id"> "." <c: "id"> => ast::Version(a.to_u32(), b.to_u32(), c.to_u32()),
};
pub CircuitModule: ast::CircuitModule = {
<m: Module> => ast::CircuitModule::Module(m),
<em: ExtModule> => ast::CircuitModule::ExtModule(em),
};
pub CircuitModules: ast::CircuitModules = {
<mut head: CircuitModules> <tail: CircuitModule> => { head.push(Box::new(tail)); head } ,
<head: CircuitModule> => vec![Box::new(head)],
};
pub Circuit: ast::Circuit = {
"circuit" <name: Identifier> "symbol" "indent" <modules: CircuitModules> "dedent" => ast::Circuit::new(ast::Version::default(), name, ast::Annotations::default(), modules),
<version: Version> "circuit" <name: Identifier> "symbol" "indent" <modules: CircuitModules> "dedent" => ast::Circuit::new(version, name, ast::Annotations::default(), modules),
"circuit" <name: Identifier> "symbol" <annos: Annotations> "indent" <modules: CircuitModules> "dedent" => ast::Circuit::new(ast::Version::default(), name, annos, modules),
<version: Version> "circuit" <name: Identifier> "symbol" <annos: Annotations> "indent" <modules: CircuitModules> "dedent" => ast::Circuit::new(version, name, annos, modules),
}