open_vaf/ir/ast/
mod.rs

1//  * ******************************************************************************************
2//  * Copyright (c) 2019 Pascal Kuthe. This file is part of the OpenVAF project.
3//  * It is subject to the license terms in the LICENSE file found in the top-level directory
4//  *  of this distribution and at  https://gitlab.com/DSPOM/OpenVAF/blob/master/LICENSE.
5//  *  No part of OpenVAF, including this file, may be copied, modified, propagated, or
6//  *  distributed except according to the terms contained in the LICENSE file.
7//  * *******************************************************************************************
8
9#![allow(clippy::wildcard_imports)]
10use crate::ir::*;
11
12use core::fmt::Debug;
13use std::ops::Range;
14use crate::symbol::Ident;
15use crate::symbol_table::SymbolTable;
16use crate::Span;
17use index_vec::IndexVec;
18use crate::literals::StringLiteral;
19use crate::ir::ids::IdRange;
20
21// pub use visitor::Visitor;
22
23/*The FOLLOWING MACRO is adapted from https://github.com/llogiq/compact_arena (mk_tiny_arena!) under MIT-License:
24
25    Permission is hereby granted, free of charge, to any person obtaining a copy
26    of this software and associated documentation files (the "Software"), to deal
27    in the Software without restriction, including without limitation the rights
28    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
29    copies of the Software, and to permit persons to whom the Software is
30    furnished to do so, subject to the following conditions:
31
32    The above copyright notice and this permission notice shall be included in all
33    copies or substantial portions of the Software.
34
35    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
36    ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
37    TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
38    PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
39    SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
40    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
41    OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
42    IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
43    DEALINGS IN THE SOFTWARE.
44*/
45
46//pub mod printer;
47// pub mod visitor;
48
49/// An Ast representing a parsed Verilog-AMS project (root file);
50/// It provides stable indicies for every Node because the entire Tree is immutable once created;
51/// It uses preallocated constant size arrays for performance
52
53//TODO configure to use different arena sizes
54pub struct Ast {
55    //Declarations
56    pub branches: IndexVec<BranchId, AttributeNode<BranchDeclaration>>,
57    pub nets: IndexVec<NetId, AttributeNode<Net>>,
58    pub ports: IndexVec<PortId, AttributeNode<Port>>,
59    pub variables: IndexVec<VariableId, AttributeNode<Variable>>,
60    pub parameters: IndexVec<ParameterId, AttributeNode<Parameter>>,
61    pub modules: IndexVec<ModuleId, AttributeNode<Module>>,
62    pub functions: IndexVec<FunctionId, AttributeNode<Function>>,
63    pub disciplines: IndexVec<DisciplineId, AttributeNode<Discipline>>,
64    pub natures: IndexVec<NatureId, AttributeNode<Nature>>,
65    //Ast Items
66    pub expressions: IndexVec<ExpressionId, Node<Expression>>,
67    pub blocks: IndexVec<BlockId, AttributeNode<SeqBlock>>,
68    pub attributes: IndexVec<AttributeId, Attribute>,
69    pub statements: IndexVec<StatementId, Statement>,
70    pub top_symbols: SymbolTable,
71}
72
73impl Ast {
74    #[must_use]
75    pub fn new() -> Self {
76        // Large initial capacity to avoid reallocation
77        // TODO configure this smh
78        Self {
79            branches: IndexVec::with_capacity(32),
80            nets: IndexVec::with_capacity(32),
81            ports: IndexVec::with_capacity(32),
82            variables: IndexVec::with_capacity(512),
83            parameters: IndexVec::with_capacity(512),
84            modules: IndexVec::with_capacity(1),
85            functions: IndexVec::with_capacity(16),
86            disciplines: IndexVec::with_capacity(8),
87            natures: IndexVec::with_capacity(8),
88            expressions: IndexVec::with_capacity(u16::MAX as usize),
89            blocks: IndexVec::with_capacity(32),
90            attributes: IndexVec::with_capacity(128),
91            statements: IndexVec::with_capacity(4096),
92            top_symbols: SymbolTable::with_capacity_and_hasher(32, Default::default()),
93        }
94    }
95}
96
97impl_id_type!(BranchId in Ast::branches -> AttributeNode<BranchDeclaration>);
98
99impl_id_type!(NetId in Ast::nets -> AttributeNode<Net>);
100
101impl_id_type!(PortId in Ast::ports -> AttributeNode<Port>);
102
103impl_id_type!(ParameterId in Ast::parameters -> AttributeNode<Parameter>);
104
105impl_id_type!(VariableId in Ast::variables -> AttributeNode<Variable>);
106
107impl_id_type!(ModuleId in Ast::modules -> AttributeNode<Module>);
108
109impl_id_type!(FunctionId in Ast::functions -> AttributeNode<Function>);
110
111impl_id_type!(DisciplineId in Ast::disciplines -> AttributeNode<Discipline>);
112
113impl_id_type!(ExpressionId in Ast::expressions -> Node<Expression>);
114
115impl_id_type!(AttributeId in Ast::attributes -> Attribute);
116
117impl_id_type!(StatementId in Ast::statements -> Statement);
118
119impl_id_type!(BlockId in Ast::blocks -> AttributeNode<SeqBlock>);
120
121impl_id_type!(NatureId in Ast::natures -> AttributeNode<Nature>);
122
123#[derive(Clone, Debug)]
124pub enum TopNode {
125    Module(ModuleId),
126    Nature(NatureId),
127    Discipline(DisciplineId),
128}
129
130#[derive(Copy, Clone)]
131pub struct Nature {
132    pub name: Ident,
133    pub abstol: ExpressionId,
134    pub units: ExpressionId,
135    pub access: Ident,
136    pub idt_nature: Option<Ident>,
137    pub ddt_nature: Option<Ident>,
138}
139
140pub enum NatureParentType {
141    Nature,
142    DisciplineFlow,
143    DisciplinePotential,
144}
145
146#[derive(Clone)]
147pub struct Module {
148    pub name: Ident,
149    pub port_list: IdRange<PortId>,
150    pub branch_list: IdRange<BranchId>,
151    pub symbol_table: SymbolTable,
152    pub children: Vec<ModuleItem>,
153}
154
155#[derive(Clone, Debug)]
156pub struct Parameter {
157    pub name: Ident,
158    pub parameter_type: ParameterType,
159    pub default_value: ExpressionId,
160}
161
162#[derive(Clone, Debug)]
163pub enum ParameterType {
164    Numerical {
165        parameter_type: VariableType,
166        from_ranges: Vec<Range<NumericalParameterRangeBound<ExpressionId>>>,
167        excluded: Vec<NumericalParameterRangeExclude<ExpressionId>>,
168    },
169    String(
170        //TODO string parameter from/exlude
171    ),
172}
173
174#[derive(Clone, Copy, Debug)]
175pub struct Port {
176    pub name: Ident,
177    pub input: bool,
178    pub output: bool,
179    pub discipline: Ident, //TODO discipline
180    pub signed: bool,
181    pub net_type: NetType,
182}
183
184impl Default for Port {
185    fn default() -> Self {
186        Self {
187            name: Ident::empty(),
188            input: false,
189            output: false,
190            discipline: Ident::empty(),
191            signed: false,
192            net_type: NetType::UNDECLARED,
193        }
194    }
195}
196
197#[derive(Clone, Debug)]
198pub struct BranchDeclaration {
199    pub name: Ident,
200    pub branch: Branch,
201}
202
203#[derive(Clone, Debug)]
204pub enum Branch {
205    Port(HierarchicalId),
206    NetToGround(HierarchicalId),
207    Nets(HierarchicalId, HierarchicalId),
208}
209
210#[derive(Clone, Copy, Debug)]
211pub enum ModuleItem {
212    AnalogStmt(StatementId),
213    GenerateStatement, //TODO
214}
215
216#[derive(Clone, Copy, Debug)]
217pub struct Discipline {
218    pub name: Ident,
219    pub flow_nature: Option<Ident>,
220    pub potential_nature: Option<Ident>,
221    pub continuous: Option<bool>,
222}
223
224#[derive(Clone, Debug)]
225pub struct Function {
226    pub name: Ident,
227    pub args: Vec<FunctionArg>,
228    pub declarations: SymbolTable,
229    pub return_variable: VariableId,
230    pub body: StatementId,
231}
232
233#[derive(Clone, Debug, PartialEq, Eq, Copy)]
234pub struct FunctionArg {
235    pub name: Ident,
236    pub input: bool,
237    pub output: bool,
238}
239
240#[derive(Debug, Clone, Copy)]
241pub struct Net {
242    pub name: Ident,
243    pub discipline: Ident,
244    pub signed: bool,
245    pub net_type: NetType,
246}
247
248#[derive(Clone, Copy, Debug)]
249pub struct Variable {
250    pub name: Ident,
251    pub variable_type: VariableType,
252    pub default_value: Option<ExpressionId>,
253}
254
255#[derive(Clone, Copy, Debug, PartialEq, Eq)]
256pub enum NetType {
257    UNDECLARED,
258    REG,
259    WREAL,
260    SUPPLY0,
261    SUPPLY1,
262    TRI,
263    TRIAND,
264    TRIOR,
265    TRI0,
266    TRI1,
267    WIRE,
268    UWIRE,
269    WAND,
270    WOR,
271    GROUND,
272}
273
274#[derive(Clone, Debug)]
275pub enum Statement {
276    Block(BlockId),
277    Condition(AttributeNode<Condition>),
278    Contribute(Attributes, Ident, Node<BranchAccess>, ExpressionId),
279    //  TODO IndirectContribute(),
280    Assign(Attributes, HierarchicalId, ExpressionId),
281    FunctionCall(Attributes, HierarchicalId, Vec<ExpressionId>),
282    While(AttributeNode<WhileLoop>),
283    DisplayTask(DisplayTaskKind, Vec<ExpressionId>),
284}
285
286#[derive(Clone)]
287pub struct SeqBlock {
288    pub scope: Option<BlockScope>,
289    pub statements: Vec<StatementId>,
290}
291
292#[derive(Clone, Debug)]
293pub struct BlockScope {
294    pub name: Ident,
295    pub symbols: SymbolTable,
296}
297
298#[derive(Clone, Copy, Debug)]
299pub struct WhileLoop {
300    pub condition: ExpressionId,
301    pub body: StatementId,
302}
303
304#[derive(Clone, Debug)]
305pub struct Condition {
306    pub condition: ExpressionId,
307    pub if_statement: StatementId,
308    pub else_statement: Option<StatementId>,
309}
310
311#[derive(Clone, Debug)]
312pub enum Expression {
313    BinaryOperator(ExpressionId, Node<BinaryOperator>, ExpressionId),
314    UnaryOperator(Node<UnaryOperator>, ExpressionId),
315    Condtion(ExpressionId, Span, ExpressionId, Span, ExpressionId),
316    Primary(Primary),
317}
318
319#[derive(Clone, Debug)]
320pub enum BranchAccess {
321    BranchOrNodePotential(HierarchicalId),
322    Implicit(Branch),
323}
324
325#[derive(Clone, Debug)]
326pub enum Primary {
327    Integer(i64),
328    UnsignedInteger(u32),
329    Real(f64),
330    String(StringLiteral),
331    VariableOrNetReference(HierarchicalId),
332    FunctionCall(HierarchicalId, Vec<ExpressionId>),
333    SystemFunctionCall(
334        SystemFunctionCall<ExpressionId, ExpressionId, HierarchicalId, HierarchicalId>,
335    ),
336    BranchAccess(Ident, Node<BranchAccess>),
337    BuiltInFunctionCall1p(BuiltInFunctionCall1p, ExpressionId),
338    BuiltInFunctionCall2p(BuiltInFunctionCall2p, ExpressionId, ExpressionId),
339    Noise(NoiseSource<ExpressionId, ()>, Option<StringLiteral>),
340    DerivativeByBranch(ExpressionId, Ident, Node<BranchAccess>),
341    DerivativeByTime(ExpressionId),
342    DerivativeByTemperature(ExpressionId),
343}
344
345#[derive(Clone, Copy, Debug, PartialEq, Eq)]
346pub enum BinaryOperator {
347    Sum,
348    Subtract,
349    Multiply,
350    Divide,
351    Exponent,
352    Modulus,
353
354    ShiftLeft,
355    ShiftRight,
356
357    LessThen,
358    LessEqual,
359    GreaterThen,
360    GreaterEqual,
361    LogicEqual,
362    LogicalNotEqual,
363
364    LogicOr,
365    LogicAnd,
366
367    Xor,
368    NXor,
369    And,
370    Or,
371}
372
373#[derive(Clone, Copy, Debug, PartialEq, Eq)]
374pub enum UnaryOperator {
375    BitNegate,
376    LogicNegate,
377    ArithmeticNegate,
378    ExplicitPositive,
379}
380
381#[derive(Clone, Copy, Debug, PartialEq, Eq)]
382pub enum VariableType {
383    INTEGER,
384    REAL,
385}
386
387#[derive(Clone, Debug)]
388pub struct HierarchicalId {
389    pub names: Vec<Ident>,
390}
391
392impl HierarchicalId {
393    #[must_use]
394    pub fn span(&self) -> Span {
395        self.names[0]
396            .span
397            .extend(self.names[self.names.len() - 1].span)
398    }
399}
400impl From<Vec<Ident>> for HierarchicalId {
401    fn from(raw: Vec<Ident>) -> Self {
402        Self { names: raw }
403    }
404}