use crate::crate_prelude::*;
use bit_vec::BitVec;
use num::{BigInt, BigRational};
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum HirNode<'hir> {
Module(&'hir Module<'hir>),
Port(&'hir Port),
Type(&'hir Type),
Expr(&'hir Expr),
InstTarget(&'hir InstTarget),
Inst(&'hir Inst<'hir>),
TypeParam(&'hir TypeParam),
ValueParam(&'hir ValueParam),
VarDecl(&'hir VarDecl),
Proc(&'hir Proc),
Stmt(&'hir Stmt),
EventExpr(&'hir EventExpr),
Gen(&'hir Gen),
GenvarDecl(&'hir GenvarDecl),
Typedef(&'hir Typedef),
Assign(&'hir Assign),
Package(&'hir Package),
EnumVariant(&'hir EnumVariant),
}
impl<'hir> HasSpan for HirNode<'hir> {
fn span(&self) -> Span {
match *self {
HirNode::Module(x) => x.span(),
HirNode::Port(x) => x.span(),
HirNode::Type(x) => x.span(),
HirNode::Expr(x) => x.span(),
HirNode::InstTarget(x) => x.span(),
HirNode::Inst(x) => x.span(),
HirNode::TypeParam(x) => x.span(),
HirNode::ValueParam(x) => x.span(),
HirNode::VarDecl(x) => x.span(),
HirNode::Proc(x) => x.span(),
HirNode::Stmt(x) => x.span(),
HirNode::EventExpr(x) => x.span(),
HirNode::Gen(x) => x.span(),
HirNode::GenvarDecl(x) => x.span(),
HirNode::Typedef(x) => x.span(),
HirNode::Assign(x) => x.span(),
HirNode::Package(x) => x.span(),
HirNode::EnumVariant(x) => x.span(),
}
}
fn human_span(&self) -> Span {
match *self {
HirNode::Module(x) => x.human_span(),
HirNode::Port(x) => x.human_span(),
HirNode::Type(x) => x.human_span(),
HirNode::Expr(x) => x.human_span(),
HirNode::InstTarget(x) => x.human_span(),
HirNode::Inst(x) => x.human_span(),
HirNode::TypeParam(x) => x.human_span(),
HirNode::ValueParam(x) => x.human_span(),
HirNode::VarDecl(x) => x.human_span(),
HirNode::Proc(x) => x.human_span(),
HirNode::Stmt(x) => x.human_span(),
HirNode::EventExpr(x) => x.human_span(),
HirNode::Gen(x) => x.human_span(),
HirNode::GenvarDecl(x) => x.human_span(),
HirNode::Typedef(x) => x.human_span(),
HirNode::Assign(x) => x.human_span(),
HirNode::Package(x) => x.human_span(),
HirNode::EnumVariant(x) => x.human_span(),
}
}
}
impl<'hir> HasDesc for HirNode<'hir> {
fn desc(&self) -> &'static str {
match *self {
HirNode::Module(x) => x.desc(),
HirNode::Port(x) => x.desc(),
HirNode::Type(x) => x.desc(),
HirNode::Expr(x) => x.desc(),
HirNode::InstTarget(x) => x.desc(),
HirNode::Inst(x) => x.desc(),
HirNode::TypeParam(x) => x.desc(),
HirNode::ValueParam(x) => x.desc(),
HirNode::VarDecl(x) => x.desc(),
HirNode::Proc(x) => x.desc(),
HirNode::Stmt(x) => x.desc(),
HirNode::EventExpr(x) => x.desc(),
HirNode::Gen(x) => x.desc(),
HirNode::GenvarDecl(x) => x.desc(),
HirNode::Typedef(x) => x.desc(),
HirNode::Assign(x) => x.desc(),
HirNode::Package(x) => x.desc(),
HirNode::EnumVariant(x) => x.desc(),
}
}
fn desc_full(&self) -> String {
match *self {
HirNode::Module(x) => x.desc_full(),
HirNode::Port(x) => x.desc_full(),
HirNode::Type(x) => x.desc_full(),
HirNode::Expr(x) => x.desc_full(),
HirNode::InstTarget(x) => x.desc_full(),
HirNode::Inst(x) => x.desc_full(),
HirNode::TypeParam(x) => x.desc_full(),
HirNode::ValueParam(x) => x.desc_full(),
HirNode::VarDecl(x) => x.desc_full(),
HirNode::Proc(x) => x.desc_full(),
HirNode::Stmt(x) => x.desc_full(),
HirNode::EventExpr(x) => x.desc_full(),
HirNode::Gen(x) => x.desc_full(),
HirNode::GenvarDecl(x) => x.desc_full(),
HirNode::Typedef(x) => x.desc_full(),
HirNode::Assign(x) => x.desc_full(),
HirNode::Package(x) => x.desc_full(),
HirNode::EnumVariant(x) => x.desc_full(),
}
}
}
#[derive(Debug, PartialEq, Eq)]
pub struct Module<'hir> {
pub id: NodeId,
pub name: Spanned<Name>,
pub span: Span,
pub ports: &'hir [NodeId],
pub params: &'hir [NodeId],
pub block: ModuleBlock,
}
impl HasSpan for Module<'_> {
fn span(&self) -> Span {
self.span
}
fn human_span(&self) -> Span {
self.name.span
}
}
impl HasDesc for Module<'_> {
fn desc(&self) -> &'static str {
"module"
}
fn desc_full(&self) -> String {
format!("module `{}`", self.name.value)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ModuleBlock {
pub insts: Vec<NodeId>,
pub decls: Vec<NodeId>,
pub procs: Vec<NodeId>,
pub gens: Vec<NodeId>,
pub params: Vec<NodeId>,
pub assigns: Vec<NodeId>,
}
#[derive(Debug, PartialEq, Eq)]
pub struct InstTarget {
pub id: NodeId,
pub name: Spanned<Name>,
pub span: Span,
pub pos_params: Vec<PosParam>,
pub named_params: Vec<NamedParam>,
}
impl HasSpan for InstTarget {
fn span(&self) -> Span {
self.span
}
fn human_span(&self) -> Span {
self.name.span
}
}
impl HasDesc for InstTarget {
fn desc(&self) -> &'static str {
"instantiation"
}
fn desc_full(&self) -> String {
format!("`{}` instantiation", self.name.value)
}
}
pub type PosParam = (Span, Option<NodeId>);
pub type NamedParam = (Span, Spanned<Name>, Option<NodeId>);
#[derive(Debug, PartialEq, Eq)]
pub struct Inst<'hir> {
pub id: NodeId,
pub name: Spanned<Name>,
pub span: Span,
pub target: NodeId,
pub pos_ports: Vec<PosParam>,
pub named_ports: Vec<NamedParam>,
pub has_wildcard_port: bool,
pub dummy: std::marker::PhantomData<&'hir ()>,
}
impl HasSpan for Inst<'_> {
fn span(&self) -> Span {
self.span
}
fn human_span(&self) -> Span {
self.name.span
}
}
impl HasDesc for Inst<'_> {
fn desc(&self) -> &'static str {
"instance"
}
fn desc_full(&self) -> String {
format!("instance `{}`", self.name.value)
}
}
#[derive(Debug, PartialEq, Eq)]
pub struct TypeParam {
pub id: NodeId,
pub name: Spanned<Name>,
pub span: Span,
pub local: bool,
pub default: Option<NodeId>,
}
impl HasSpan for TypeParam {
fn span(&self) -> Span {
self.span
}
fn human_span(&self) -> Span {
self.name.span
}
}
impl HasDesc for TypeParam {
fn desc(&self) -> &'static str {
"type parameter"
}
fn desc_full(&self) -> String {
format!("type parameter `{}`", self.name.value)
}
}
#[derive(Debug, PartialEq, Eq)]
pub struct ValueParam {
pub id: NodeId,
pub name: Spanned<Name>,
pub span: Span,
pub local: bool,
pub ty: NodeId,
pub default: Option<NodeId>,
}
impl HasSpan for ValueParam {
fn span(&self) -> Span {
self.span
}
fn human_span(&self) -> Span {
self.name.span
}
}
impl HasDesc for ValueParam {
fn desc(&self) -> &'static str {
"parameter"
}
fn desc_full(&self) -> String {
format!("parameter `{}`", self.name.value)
}
}
#[derive(Debug, PartialEq, Eq)]
pub struct Port {
pub id: NodeId,
pub name: Spanned<Name>,
pub span: Span,
pub dir: ast::PortDir,
pub ty: NodeId,
pub default: Option<NodeId>,
}
impl HasSpan for Port {
fn span(&self) -> Span {
self.span
}
fn human_span(&self) -> Span {
self.name.span
}
}
impl HasDesc for Port {
fn desc(&self) -> &'static str {
"port"
}
fn desc_full(&self) -> String {
format!("port `{}`", self.name.value)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Type {
pub id: NodeId,
pub span: Span,
pub kind: TypeKind,
}
impl Type {
pub fn is_explicit(&self) -> bool {
!self.is_implicit()
}
pub fn is_implicit(&self) -> bool {
self.kind == TypeKind::Implicit
}
}
impl HasSpan for Type {
fn span(&self) -> Span {
self.span
}
}
impl HasDesc for Type {
fn desc(&self) -> &'static str {
self.kind.desc()
}
fn desc_full(&self) -> String {
self.kind.desc_full()
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum TypeKind {
Implicit,
Builtin(BuiltinType),
Named(Spanned<Name>),
Struct(Vec<NodeId>),
PackedArray(Box<TypeKind>, NodeId, NodeId),
Scope(NodeId, Spanned<Name>),
Enum(Vec<(Spanned<Name>, NodeId)>, Option<NodeId>),
}
impl HasDesc for TypeKind {
fn desc(&self) -> &'static str {
#[allow(unreachable_patterns)]
match *self {
TypeKind::Implicit => "implicit type",
TypeKind::Builtin(BuiltinType::Void) => "void type",
TypeKind::Builtin(BuiltinType::Bit) => "bit type",
TypeKind::Builtin(BuiltinType::Logic) => "logic type",
TypeKind::Builtin(BuiltinType::Byte) => "byte type",
TypeKind::Builtin(BuiltinType::ShortInt) => "short int type",
TypeKind::Builtin(BuiltinType::Int) => "int type",
TypeKind::Builtin(BuiltinType::Integer) => "integer type",
TypeKind::Builtin(BuiltinType::LongInt) => "long int type",
TypeKind::Struct(_) => "struct type",
TypeKind::PackedArray(..) => "packed array type",
_ => "type",
}
}
fn desc_full(&self) -> String {
match *self {
TypeKind::Named(n) => format!("type `{}`", n.value),
_ => self.desc().into(),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BuiltinType {
Void,
Bit,
Logic,
Byte,
ShortInt,
Int,
Integer,
LongInt,
Time,
String,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Expr {
pub id: NodeId,
pub span: Span,
pub kind: ExprKind,
}
impl HasSpan for Expr {
fn span(&self) -> Span {
self.span
}
}
impl HasDesc for Expr {
fn desc(&self) -> &'static str {
#[allow(unreachable_patterns)]
match self.kind {
ExprKind::IntConst { .. } => "integer constant",
ExprKind::TimeConst(_) => "time constant",
ExprKind::Ident(_) => "identifier",
_ => "expression",
}
}
fn desc_full(&self) -> String {
#[allow(unreachable_patterns)]
match self.kind {
ExprKind::IntConst { value: ref k, .. } => format!("{} `{}`", self.desc(), k),
ExprKind::TimeConst(ref k) => format!("{} `{}`", self.desc(), k),
ExprKind::Ident(n) => format!("`{}`", n.value),
ExprKind::PositionalPattern(..) => format!("positional pattern"),
ExprKind::NamedPattern(..) => format!("named pattern"),
ExprKind::RepeatPattern(..) => format!("repeat pattern"),
ExprKind::EmptyPattern => format!("empty pattern"),
_ => format!("{} `{}`", self.desc(), self.span().extract()),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ExprKind {
IntConst {
width: usize,
value: BigInt,
signed: bool,
special_bits: BitVec,
x_bits: BitVec,
},
UnsizedConst(char),
TimeConst(BigRational),
StringConst(Spanned<Name>),
Ident(Spanned<Name>),
Unary(UnaryOp, NodeId),
Binary(BinaryOp, NodeId, NodeId),
Field(NodeId, Spanned<Name>),
Index(NodeId, IndexMode),
Builtin(BuiltinCall),
Ternary(NodeId, NodeId, NodeId),
Scope(NodeId, Spanned<Name>),
PositionalPattern(Vec<NodeId>),
NamedPattern(Vec<(PatternMapping, NodeId)>),
RepeatPattern(NodeId, Vec<NodeId>),
EmptyPattern,
Concat(Option<NodeId>, Vec<NodeId>),
Cast(NodeId, NodeId),
Inside(NodeId, Vec<Spanned<InsideRange>>),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum UnaryOp {
Pos,
Neg,
BitNot,
LogicNot,
PreInc,
PreDec,
PostInc,
PostDec,
RedAnd,
RedNand,
RedOr,
RedNor,
RedXor,
RedXnor,
}
impl HasDesc for UnaryOp {
fn desc(&self) -> &'static str {
match *self {
UnaryOp::Pos => "unary `+` operator",
UnaryOp::Neg => "unary `-` operator",
UnaryOp::BitNot => "`~` operator",
UnaryOp::LogicNot => "`!` operator",
UnaryOp::PreInc => "`++` prefix operator",
UnaryOp::PreDec => "`--` prefix operator",
UnaryOp::PostInc => "`++` postfix operator",
UnaryOp::PostDec => "`--` postfix operator",
UnaryOp::RedAnd => "`&` reduction operator",
UnaryOp::RedNand => "`~&` reduction operator",
UnaryOp::RedOr => "`|` reduction operator",
UnaryOp::RedNor => "`~|` reduction operator",
UnaryOp::RedXor => "`^` reduction operator",
UnaryOp::RedXnor => "`^~` reduction operator",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BinaryOp {
Add,
Sub,
Mul,
Div,
Mod,
Pow,
Eq,
Neq,
Lt,
Leq,
Gt,
Geq,
LogicAnd,
LogicOr,
BitAnd,
BitNand,
BitOr,
BitNor,
BitXor,
BitXnor,
LogicShL,
LogicShR,
ArithShL,
ArithShR,
}
impl HasDesc for BinaryOp {
fn desc(&self) -> &'static str {
match *self {
BinaryOp::Add => "`+` operator",
BinaryOp::Sub => "`-` operator",
BinaryOp::Mul => "`*` operator",
BinaryOp::Div => "`/` operator",
BinaryOp::Mod => "`%` operator",
BinaryOp::Pow => "`**` operator",
BinaryOp::Eq => "`==` operator",
BinaryOp::Neq => "`!=` operator",
BinaryOp::Lt => "`<` operator",
BinaryOp::Leq => "`<=` operator",
BinaryOp::Gt => "`>` operator",
BinaryOp::Geq => "`>=` operator",
BinaryOp::LogicAnd => "`&&` operator",
BinaryOp::LogicOr => "`||` operator",
BinaryOp::BitAnd => "`&` operator",
BinaryOp::BitNand => "`~&` operator",
BinaryOp::BitOr => "`|` operator",
BinaryOp::BitNor => "`~|` operator",
BinaryOp::BitXor => "`^` operator",
BinaryOp::BitXnor => "`~^` operator",
BinaryOp::LogicShL => "`<<` operator",
BinaryOp::LogicShR => "`>>` operator",
BinaryOp::ArithShL => "`<<<` operator",
BinaryOp::ArithShR => "`>>>` operator",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum IndexMode {
One(NodeId),
Many(ast::RangeMode, NodeId, NodeId),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BuiltinCall {
Unsupported,
Clog2(NodeId),
Bits(NodeId),
Signed(NodeId),
Unsigned(NodeId),
}
#[derive(Debug, PartialEq, Eq)]
pub struct VarDecl {
pub id: NodeId,
pub name: Spanned<Name>,
pub span: Span,
pub ty: NodeId,
pub init: Option<NodeId>,
}
impl HasSpan for VarDecl {
fn span(&self) -> Span {
self.span
}
fn human_span(&self) -> Span {
self.name.span
}
}
impl HasDesc for VarDecl {
fn desc(&self) -> &'static str {
"variable declaration"
}
fn desc_full(&self) -> String {
format!("variable `{}`", self.name.value)
}
}
#[derive(Debug, PartialEq, Eq)]
pub struct Proc {
pub id: NodeId,
pub span: Span,
pub kind: ast::ProcedureKind,
pub stmt: NodeId,
}
impl HasSpan for Proc {
fn span(&self) -> Span {
self.span
}
}
impl HasDesc for Proc {
fn desc(&self) -> &'static str {
match self.kind {
ast::ProcedureKind::Initial => "`initial` procedure",
ast::ProcedureKind::Always => "`always` procedure",
ast::ProcedureKind::AlwaysComb => "`always_comb` procedure",
ast::ProcedureKind::AlwaysLatch => "`always_latch` procedure",
ast::ProcedureKind::AlwaysFf => "`always_ff` procedure",
ast::ProcedureKind::Final => "`final` procedure",
}
}
}
#[derive(Debug, PartialEq, Eq)]
pub struct Stmt {
pub id: NodeId,
pub label: Option<Spanned<Name>>,
pub span: Span,
pub kind: StmtKind,
}
impl HasSpan for Stmt {
fn span(&self) -> Span {
self.span
}
fn human_span(&self) -> Span {
self.label.map(|l| l.span).unwrap_or(self.span)
}
}
impl HasDesc for Stmt {
fn desc(&self) -> &'static str {
#[allow(unreachable_patterns)]
match self.kind {
StmtKind::Null => "null statement",
StmtKind::Block(_) => "block",
StmtKind::Assign { .. } => "assign statement",
_ => "statement",
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum StmtKind {
Null,
Block(Vec<NodeId>),
Assign {
lhs: NodeId,
rhs: NodeId,
kind: AssignKind,
},
Timed {
control: TimingControl,
stmt: NodeId,
},
Expr(NodeId),
If {
cond: NodeId,
main_stmt: NodeId,
else_stmt: Option<NodeId>,
},
Loop { kind: LoopKind, body: NodeId },
InlineGroup { stmts: Vec<NodeId>, rib: NodeId },
Case {
expr: NodeId,
ways: Vec<(Vec<NodeId>, NodeId)>,
default: Option<NodeId>,
kind: ast::CaseKind,
},
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum AssignKind {
Block(ast::AssignOp),
Nonblock,
NonblockDelay(NodeId),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum LoopKind {
Forever,
Repeat(NodeId),
While(NodeId),
Do(NodeId),
For(NodeId, NodeId, NodeId),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TimingControl {
Delay(NodeId),
ImplicitEvent,
ExplicitEvent(NodeId),
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct EventExpr {
pub id: NodeId,
pub span: Span,
pub events: Vec<Event>,
}
impl HasSpan for EventExpr {
fn span(&self) -> Span {
self.span
}
}
impl HasDesc for EventExpr {
fn desc(&self) -> &'static str {
"event expression"
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Event {
pub span: Span,
pub edge: ast::EdgeIdent,
pub expr: NodeId,
pub iff: Vec<NodeId>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Gen {
pub id: NodeId,
pub span: Span,
pub kind: GenKind,
}
impl HasSpan for Gen {
fn span(&self) -> Span {
self.span
}
}
impl HasDesc for Gen {
fn desc(&self) -> &'static str {
"generate statement"
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum GenKind {
If {
cond: NodeId,
main_body: ModuleBlock,
else_body: Option<ModuleBlock>,
},
For {
init: Vec<NodeId>,
cond: NodeId,
step: NodeId,
body: ModuleBlock,
},
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct GenvarDecl {
pub id: NodeId,
pub name: Spanned<Name>,
pub span: Span,
pub init: Option<NodeId>,
}
impl HasSpan for GenvarDecl {
fn span(&self) -> Span {
self.span
}
fn human_span(&self) -> Span {
self.name.span
}
}
impl HasDesc for GenvarDecl {
fn desc(&self) -> &'static str {
"genvar declaration"
}
fn desc_full(&self) -> String {
format!("genvar `{}`", self.name.value)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Typedef {
pub id: NodeId,
pub name: Spanned<Name>,
pub span: Span,
pub ty: NodeId,
}
impl HasSpan for Typedef {
fn span(&self) -> Span {
self.span
}
fn human_span(&self) -> Span {
self.name.span
}
}
impl HasDesc for Typedef {
fn desc(&self) -> &'static str {
"typedef"
}
fn desc_full(&self) -> String {
format!("typedef `{}`", self.name.value)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Assign {
pub id: NodeId,
pub span: Span,
pub lhs: NodeId,
pub rhs: NodeId,
}
impl HasSpan for Assign {
fn span(&self) -> Span {
self.span
}
}
impl HasDesc for Assign {
fn desc(&self) -> &'static str {
"assignment"
}
}
#[derive(Debug, PartialEq, Eq)]
pub struct Package {
pub id: NodeId,
pub name: Spanned<Name>,
pub span: Span,
pub names: Vec<(Spanned<Name>, NodeId)>,
pub decls: Vec<NodeId>,
pub params: Vec<NodeId>,
pub last_rib: NodeId,
}
impl HasSpan for Package {
fn span(&self) -> Span {
self.span
}
fn human_span(&self) -> Span {
self.name.span
}
}
impl HasDesc for Package {
fn desc(&self) -> &'static str {
"package"
}
fn desc_full(&self) -> String {
format!("package `{}`", self.name.value)
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct EnumVariant {
pub id: NodeId,
pub name: Spanned<Name>,
pub span: Span,
pub enum_id: NodeId,
pub index: usize,
pub value: Option<NodeId>,
}
impl HasSpan for EnumVariant {
fn span(&self) -> Span {
self.span
}
fn human_span(&self) -> Span {
self.name.span
}
}
impl HasDesc for EnumVariant {
fn desc(&self) -> &'static str {
"enum variant"
}
fn desc_full(&self) -> String {
format!("enum variant `{}`", self.name.value)
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum PatternMapping {
Type(NodeId),
Member(NodeId),
Default,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum InsideRange {
Single(NodeId),
Range(NodeId, NodeId),
}