1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// Copyright (c) 2017 Fabian Schuiki

//! This module contains the nodes of the tree structure that is the HIR.

use std::collections::HashMap;
pub use moore_common::name::Name;
pub use moore_common::source::Span;
pub use moore_svlog_syntax::ast::NodeId;
use moore_svlog_syntax::ast;


// TODO: Take the AST expressions and split them into lvalue and rvalue
// expressions. This should make a few things easier.


/// The root of the HIR tree. This represents one elaborated design.
pub struct Root {
	pub top: NodeId,
	pub mods: HashMap<NodeId, Module>,
	pub intfs: HashMap<NodeId, Interface>,
	pub pkgs: HashMap<NodeId, Package>,
}

/// An search index of all nodes in a HIR tree.
pub struct NodeIndex<'hir> {
	pub hir: &'hir Root,
	pub nodes: HashMap<NodeId, Node<'hir>>,
}

#[derive(Copy, Clone)]
pub enum Node<'hir> {
	Module(&'hir Module),
	Interface(&'hir Interface),
	Package(&'hir Package),
	Port(&'hir Port),
	PortSlice(&'hir PortSlice),
	TypeParam(&'hir ast::ParamTypeDecl),
	ValueParam(&'hir ast::ParamValueDecl),
	VarDecl(&'hir ast::VarDecl, &'hir ast::VarDeclName),
}

/// A module.
pub struct Module {
	pub id: NodeId,
	pub name: Name,
	pub span: Span,
	pub lifetime: ast::Lifetime,
	pub ports: Vec<Port>,
	pub params: Vec<ast::ParamDecl>,
	pub body: HierarchyBody,
}

/// An interface.
pub struct Interface {
	pub id: NodeId,
	pub name: Name,
	pub span: Span,
	pub lifetime: ast::Lifetime,
	pub ports: Vec<Port>,
	pub params: Vec<ast::ParamDecl>,
	pub body: HierarchyBody,
}

/// A package.
pub struct Package {
	pub name: Name,
	pub span: Span,
	pub lifetime: ast::Lifetime,
	pub body: HierarchyBody,
}

/// A hierarchy body represents the contents of a module, interface, or package.
/// Generate regions and nested modules introduce additional bodies. The point
/// of hierarchy bodies is to take a level of the design hierarchy and group all
/// declarations by type, rather than having them in a single array in
/// declaration order.
pub struct HierarchyBody {
	pub procs: Vec<ast::Procedure>,
	pub nets: Vec<ast::NetDecl>,
	pub vars: Vec<ast::VarDecl>,
	pub assigns: Vec<ast::ContAssign>,
	pub params: Vec<ast::ParamDecl>,
	pub insts: Vec<ast::Inst>,
	pub genreg: Vec<HierarchyBody>,
	pub genvars: Vec<ast::GenvarDecl>,
	pub genfors: Vec<GenerateFor>,
	pub genifs: Vec<GenerateIf>,
	pub gencases: Vec<ast::GenerateCase>,
	pub classes: Vec<ast::ClassDecl>, // TODO: Make this an HIR node, since it contains hierarchy items
	pub subroutines: Vec<ast::SubroutineDecl>, // TODO: Make this an HIR node
	pub asserts: Vec<ast::Assertion>,
	pub typedefs: Vec<ast::Typedef>,
}

#[derive(Debug)]
pub struct Port {
	pub name: Option<Name>,
	pub span: Span,
	pub slices: Vec<PortSlice>,
}

/// A port slice refers to a port declaration within the module. It consists of
/// the name of the declaration and a list of optional member and index accesses
/// that select individual parts of the declaration.
#[derive(Debug)]
pub struct PortSlice {
	pub id: NodeId,
	pub name: Name,
	pub span: Span,
	pub selects: Vec<PortSelect>,
	pub dir: ast::PortDir,
	pub kind: ast::PortKind,
	pub ty: Option<ast::Type>,
	pub dims: Vec<ast::TypeDim>,
}

#[derive(Debug)]
pub enum PortSelect {
	Member(Span, Name),
	Index(Span, Expr),
}

pub struct PortDecl {
	pub dir: ast::PortDir,
}

// pub enum PortDir {

// }

#[derive(Debug)]
pub struct Expr;

pub struct GenerateBlock {
	pub span: Span,
	pub label: Option<Name>,
	pub body: HierarchyBody,
}

pub struct GenerateFor {
	pub span: Span,
	pub init: ast::Stmt,
	pub cond: ast::Expr,
	pub step: ast::Expr,
	pub block: GenerateBlock,
}

pub struct GenerateIf {
	pub span: Span,
	pub cond: ast::Expr,
	pub main_block: GenerateBlock,
	pub else_block: Option<GenerateBlock>,
}