open_vaf/ir/mir/
mod.rs

1/*
2 * ******************************************************************************************
3 * Copyright (c) 2019 Pascal Kuthe. This file is part of the OpenVAF project.
4 * It is subject to the license terms in the LICENSE file found in the top-level directory
5 *  of this distribution and at  https://gitlab.com/DSPOM/OpenVAF/blob/master/LICENSE.
6 *  No part of OpenVAF, including this file, may be copied, modified, propagated, or
7 *  distributed except according to the terms contained in the LICENSE file.
8 * *****************************************************************************************
9 */
10
11use crate::ast::UnaryOperator;
12
13use crate::hir::{BranchDeclaration, Discipline, DisciplineAccess, Net, Port};
14use crate::ir::cfg::ControlFlowGraph;
15use crate::ir::hir::Hir;
16use crate::ir::ids::{IdRange, StringExpressionId};
17use crate::ir::*;
18use crate::literals::StringLiteral;
19use crate::symbol::Ident;
20use crate::Span;
21use index_vec::IndexVec;
22use rustc_hash::FxHashMap;
23use std::mem::take;
24use std::ops::Range;
25
26pub struct Mir {
27    pub branches: IndexVec<BranchId, AttributeNode<BranchDeclaration>>,
28    pub nets: IndexVec<NetId, AttributeNode<Net>>,
29    pub ports: IndexVec<PortId, Port>,
30    pub disciplines: IndexVec<DisciplineId, AttributeNode<Discipline>>,
31
32    // The only thing that changes about these types is that type checking happens
33    pub modules: IndexVec<ModuleId, AttributeNode<Module>>,
34    pub parameters: IndexVec<ParameterId, AttributeNode<Parameter>>,
35    pub variables: IndexVec<VariableId, AttributeNode<Variable>>,
36    pub natures: IndexVec<NatureId, AttributeNode<Nature>>,
37    pub attributes: IndexVec<AttributeId, Attribute>,
38
39    // Expressions
40    pub real_expressions: IndexVec<RealExpressionId, Node<RealExpression>>,
41    pub integer_expressions: IndexVec<IntegerExpressionId, Node<IntegerExpression>>,
42    pub string_expressions: IndexVec<StringExpressionId, Node<StringExpression>>,
43
44    // Statements
45    pub statements: IndexVec<StatementId, Statement>,
46}
47
48impl Mir {
49    /// # Safety
50    /// You should never call this yourself
51    pub(crate) fn initalize(hir: &mut Hir) -> Self {
52        Self {
53            // Nothing about these changes during HIR lowering we can just copy
54            branches: take(&mut hir.branches),
55            nets: take(&mut hir.nets),
56            ports: take(&mut hir.ports),
57            disciplines: take(&mut hir.disciplines),
58
59            parameters: Default::default(),
60            variables: Default::default(),
61            modules: Default::default(),
62            natures: Default::default(),
63            real_expressions: Default::default(),
64            integer_expressions: Default::default(),
65            string_expressions: Default::default(),
66            attributes: Default::default(),
67            statements: Default::default(),
68        }
69    }
70}
71
72impl_id_type!(BranchId in Mir::branches -> AttributeNode<BranchDeclaration>);
73impl_id_type!(NetId in Mir::nets -> AttributeNode<Net>);
74impl_id_type!(PortId in Mir::ports -> Port);
75impl_id_type!(VariableId in Mir::variables ->  AttributeNode<Variable>);
76impl_id_type!(ModuleId in Mir::modules -> AttributeNode<Module>);
77impl_id_type!(DisciplineId in Mir::disciplines -> AttributeNode<Discipline>);
78impl_id_type!(RealExpressionId in Mir::real_expressions -> Node<RealExpression>);
79impl_id_type!(StringExpressionId in Mir::string_expressions -> Node<StringExpression>);
80impl_id_type!(IntegerExpressionId in Mir::integer_expressions -> Node<IntegerExpression>);
81impl_id_type!(AttributeId in Mir::attributes -> Attribute);
82impl_id_type!(StatementId in Mir::statements -> Statement);
83impl_id_type!(NatureId in Mir::natures -> AttributeNode<Nature>);
84impl_id_type!(ParameterId in Mir::parameters -> AttributeNode<Parameter>);
85
86#[derive(Clone, Copy, Debug)]
87pub struct Variable {
88    pub name: Ident,
89    pub variable_type: VariableType,
90}
91
92#[derive(Copy, Clone, Debug)]
93pub struct Attribute {
94    pub name: Ident,
95    pub value: Option<ExpressionId>,
96}
97
98#[derive(Copy, Clone)]
99pub struct Nature {
100    pub name: Ident,
101    pub abstol: f64,
102    pub units: StringLiteral,
103    pub access: Ident,
104    pub idt_nature: NatureId,
105    pub ddt_nature: NatureId,
106}
107
108#[derive(Debug)]
109pub struct Module {
110    pub name: Ident,
111    pub port_list: IdRange<PortId>,
112    pub analog_cfg: ControlFlowGraph,
113}
114
115#[derive(Clone, Copy, Debug)]
116pub enum VariableType {
117    Real(Option<RealExpressionId>),
118    Integer(Option<IntegerExpressionId>),
119}
120
121#[derive(Clone)]
122pub enum Statement {
123    Contribute(Attributes, DisciplineAccess, BranchId, RealExpressionId),
124    //  TODO IndirectContribute
125    Assignment(Attributes, VariableId, ExpressionId),
126}
127
128#[derive(Clone, Debug)]
129pub struct Parameter {
130    pub name: Ident,
131    pub parameter_type: ParameterType,
132}
133
134impl ParameterType {
135    pub fn is_numeric(&self) -> bool {
136        !matches!(self, ParameterType::String(_))
137    }
138}
139
140#[derive(Clone, Debug)]
141pub enum ParameterType {
142    Integer {
143        from_ranges: Vec<Range<NumericalParameterRangeBound<IntegerExpressionId>>>,
144        excluded: Vec<NumericalParameterRangeExclude<IntegerExpressionId>>,
145        default_value: IntegerExpressionId,
146    },
147    Real {
148        from_ranges: Vec<Range<NumericalParameterRangeBound<RealExpressionId>>>,
149        excluded: Vec<NumericalParameterRangeExclude<RealExpressionId>>,
150        default_value: RealExpressionId,
151    },
152    String(StringExpressionId),
153}
154
155#[derive(Clone, Copy, Eq, PartialEq, Debug)]
156pub enum ExpressionId {
157    Real(RealExpressionId),
158    Integer(IntegerExpressionId),
159    String(StringExpressionId),
160}
161
162impl ExpressionId {
163    pub fn source(self, mir: &Mir) -> Span {
164        match self {
165            Self::Real(id) => mir[id].source,
166            Self::Integer(id) => mir[id].source,
167            Self::String(id) => mir[id].source,
168        }
169    }
170}
171
172impl ExpressionId {
173    pub fn is_real(self) -> bool {
174        matches!(self,Self::Real{..})
175    }
176
177    pub fn is_integer(self) -> bool {
178        matches!(self,Self::Integer{..})
179    }
180}
181
182#[derive(Clone, Debug)]
183pub enum IntegerExpression {
184    BinaryOperator(
185        IntegerExpressionId,
186        Node<IntegerBinaryOperator>,
187        IntegerExpressionId,
188    ),
189    UnaryOperator(Node<UnaryOperator>, IntegerExpressionId),
190    IntegerComparison(
191        IntegerExpressionId,
192        Node<ComparisonOperator>,
193        IntegerExpressionId,
194    ),
195    RealComparison(RealExpressionId, Node<ComparisonOperator>, RealExpressionId),
196    StringEq(StringExpressionId, StringExpressionId),
197    StringNEq(StringExpressionId, StringExpressionId),
198    Condition(
199        IntegerExpressionId,
200        Span,
201        IntegerExpressionId,
202        Span,
203        IntegerExpressionId,
204    ),
205    RealCast(RealExpressionId),
206    Literal(i64),
207    VariableReference(VariableId),
208    NetReference(NetId),
209    PortReference(PortId),
210    ParameterReference(ParameterId),
211    FunctionCall(FunctionId, Vec<ExpressionId>),
212    Min(IntegerExpressionId, IntegerExpressionId),
213    Max(IntegerExpressionId, IntegerExpressionId),
214    Abs(IntegerExpressionId),
215
216    ParamGiven(ParameterId),
217    PortConnected(PortId),
218}
219
220#[derive(Clone, Copy, Debug, PartialEq, Eq)]
221pub enum IntegerBinaryOperator {
222    Sum,
223    Subtract,
224    Multiply,
225    Divide,
226    Exponent,
227    Modulus,
228
229    ShiftLeft,
230    ShiftRight,
231
232    Xor,
233    NXor,
234    And,
235    Or,
236
237    LogicOr,
238    LogicAnd,
239}
240impl From<RealBinaryOperator> for IntegerBinaryOperator {
241    fn from(op: RealBinaryOperator) -> Self {
242        match op {
243            RealBinaryOperator::Sum => IntegerBinaryOperator::Sum,
244            RealBinaryOperator::Subtract => IntegerBinaryOperator::Subtract,
245            RealBinaryOperator::Multiply => IntegerBinaryOperator::Multiply,
246            RealBinaryOperator::Divide => IntegerBinaryOperator::Divide,
247            RealBinaryOperator::Exponent => IntegerBinaryOperator::Exponent,
248            RealBinaryOperator::Modulus => IntegerBinaryOperator::Modulus,
249        }
250    }
251}
252#[derive(Clone, Copy, Debug, PartialEq, Eq)]
253pub enum ComparisonOperator {
254    LessThen,
255    LessEqual,
256    GreaterThen,
257    GreaterEqual,
258    LogicEqual,
259    LogicalNotEqual,
260}
261
262#[derive(Clone, Copy, Debug, PartialEq, Eq)]
263pub enum IntegerUnaryOperator {
264    BitNegate,
265    LogicNegate,
266    ArithmeticNegate,
267    ExplicitPositive,
268}
269
270#[derive(Clone, Debug)]
271pub enum RealExpression {
272    BinaryOperator(RealExpressionId, Node<RealBinaryOperator>, RealExpressionId),
273    Negate(Span, RealExpressionId),
274    Condition(
275        IntegerExpressionId,
276        Span,
277        RealExpressionId,
278        Span,
279        RealExpressionId,
280    ),
281    Literal(f64),
282    VariableReference(VariableId),
283    ParameterReference(ParameterId),
284    BranchAccess(DisciplineAccess, BranchId, u8),
285    Noise(NoiseSource<RealExpressionId, ()>, Option<StringLiteral>),
286    BuiltInFunctionCall1p(BuiltInFunctionCall1p, RealExpressionId),
287    BuiltInFunctionCall2p(BuiltInFunctionCall2p, RealExpressionId, RealExpressionId),
288    IntegerConversion(IntegerExpressionId),
289
290    Temperature,
291    Vt(Option<RealExpressionId>),
292    SimParam(StringExpressionId, Option<RealExpressionId>),
293}
294
295#[derive(Clone, Copy, Debug, PartialEq, Eq)]
296pub enum RealBinaryOperator {
297    Sum,
298    Subtract,
299    Multiply,
300    Divide,
301    Exponent,
302    Modulus,
303}
304
305#[derive(Clone, Debug)]
306pub enum StringExpression {
307    Condition(
308        IntegerExpressionId,
309        Span,
310        StringExpressionId,
311        Span,
312        StringExpressionId,
313    ),
314
315    Literal(StringLiteral),
316    SimParam(StringExpressionId),
317
318    VariableReference(VariableId),
319
320    ParameterReference(ParameterId),
321}
322
323impl Mir {
324    pub fn map_real_expr(
325        &mut self,
326        expr: RealExpressionId,
327        variables_to_replace: &FxHashMap<VariableId, VariableId>,
328    ) -> Option<RealExpressionId> {
329        let new_expr = match self[expr].contents {
330            RealExpression::VariableReference(var) => {
331                let new_var = *variables_to_replace.get(&var)?;
332                RealExpression::VariableReference(new_var)
333            }
334
335            RealExpression::BinaryOperator(lhs, op, rhs) => {
336                let mapped_lhs = self.map_real_expr(lhs, variables_to_replace);
337                let mapped_rhs = self.map_real_expr(rhs, variables_to_replace);
338                let (lhs, rhs) = match (mapped_lhs, mapped_rhs) {
339                    (None, None) => return None,
340                    (Some(lhs), None) => (lhs, rhs),
341                    (None, Some(rhs)) => (lhs, rhs),
342                    (Some(lhs), Some(rhs)) => (lhs, rhs),
343                };
344                RealExpression::BinaryOperator(lhs, op, rhs)
345            }
346
347            RealExpression::Negate(span, expr) => {
348                let expr = self.map_real_expr(expr, variables_to_replace)?;
349                RealExpression::Negate(span, expr)
350            }
351
352            RealExpression::Vt(arg) => {
353                let arg =
354                    arg.map(|arg| self.map_real_expr(arg, variables_to_replace).unwrap_or(arg));
355                RealExpression::Vt(arg)
356            }
357
358            RealExpression::Condition(condition, question_span, arg1, colon_span, arg2) => {
359                let mapped_arg1 = self.map_real_expr(arg1, variables_to_replace);
360                let mapped_arg2 = self.map_real_expr(arg2, variables_to_replace);
361                let mapped_condition = self.map_int_expr(condition, variables_to_replace);
362                if mapped_arg1.is_none() && mapped_arg2.is_none() && mapped_condition.is_none() {
363                    return None;
364                }
365                let arg1 = mapped_arg1.unwrap_or(arg1);
366                let arg2 = mapped_arg2.unwrap_or(arg2);
367                let condition = mapped_condition.unwrap_or(condition);
368                RealExpression::Condition(condition, question_span, arg1, colon_span, arg2)
369            }
370
371            RealExpression::BuiltInFunctionCall1p(call, expr) => {
372                let expr = self.map_real_expr(expr, variables_to_replace)?;
373                RealExpression::BuiltInFunctionCall1p(call, expr)
374            }
375
376            RealExpression::BuiltInFunctionCall2p(call, arg1, arg2) => {
377                let mapped_arg1 = self.map_real_expr(arg1, variables_to_replace);
378                let mapped_arg2 = self.map_real_expr(arg2, variables_to_replace);
379                let (arg1, arg2) = match (mapped_arg1, mapped_arg2) {
380                    (None, None) => return None,
381                    (Some(arg1), None) => (arg1, arg2),
382                    (None, Some(arg2)) => (arg1, arg2),
383                    (Some(arg1), Some(arg2)) => (arg1, arg2),
384                };
385                RealExpression::BuiltInFunctionCall2p(call, arg1, arg2)
386            }
387
388            RealExpression::Noise(source, src) => {
389                let source = match source {
390                    NoiseSource::White(expr) => {
391                        NoiseSource::White(self.map_real_expr(expr, variables_to_replace)?)
392                    }
393                    NoiseSource::Flicker(expr1, expr2) => NoiseSource::Flicker(
394                        self.map_real_expr(expr1, variables_to_replace)?,
395                        self.map_real_expr(expr2, variables_to_replace)?,
396                    ),
397                    NoiseSource::Table(_) | NoiseSource::TableLog(_) => todo!(),
398                };
399                RealExpression::Noise(source, src)
400            }
401
402            RealExpression::IntegerConversion(expr) => {
403                let expr = self.map_int_expr(expr, variables_to_replace)?;
404                RealExpression::IntegerConversion(expr)
405            }
406
407            RealExpression::Literal(_)
408            | RealExpression::ParameterReference(_)
409            | RealExpression::BranchAccess(_, _, _)
410            | RealExpression::Temperature => return None,
411
412            RealExpression::SimParam(name, default) => {
413                let new_name = self.map_str_expr(name, variables_to_replace);
414                if let Some(default) = default {
415                    if let Some(new_default) = self.map_real_expr(default, variables_to_replace) {
416                        RealExpression::SimParam(new_name.unwrap_or(name), Some(new_default))
417                    } else {
418                        RealExpression::SimParam(new_name?, Some(default))
419                    }
420                } else {
421                    RealExpression::SimParam(new_name?, None)
422                }
423            }
424        };
425        Some(self.real_expressions.push(self[expr].clone_as(new_expr)))
426    }
427
428    pub fn map_int_expr(
429        &mut self,
430        expr: IntegerExpressionId,
431        variables_to_replace: &FxHashMap<VariableId, VariableId>,
432    ) -> Option<IntegerExpressionId> {
433        let new_expr = match self[expr].contents {
434            IntegerExpression::VariableReference(var) => {
435                let new_var = *variables_to_replace.get(&var)?;
436                IntegerExpression::VariableReference(new_var)
437            }
438
439            IntegerExpression::BinaryOperator(lhs, op, rhs) => {
440                let mapped_lhs = self.map_int_expr(lhs, variables_to_replace);
441                let mapped_rhs = self.map_int_expr(rhs, variables_to_replace);
442                let (lhs, rhs) = match (mapped_lhs, mapped_rhs) {
443                    (None, None) => return None,
444                    (Some(lhs), None) => (lhs, rhs),
445                    (None, Some(rhs)) => (lhs, rhs),
446                    (Some(lhs), Some(rhs)) => (lhs, rhs),
447                };
448                IntegerExpression::BinaryOperator(lhs, op, rhs)
449            }
450
451            IntegerExpression::UnaryOperator(op, expr) => {
452                let expr = self.map_int_expr(expr, variables_to_replace)?;
453                IntegerExpression::UnaryOperator(op, expr)
454            }
455
456            IntegerExpression::Condition(condition, question_span, arg1, colon_span, arg2) => {
457                let mapped_arg1 = self.map_int_expr(arg1, variables_to_replace);
458                let mapped_arg2 = self.map_int_expr(arg2, variables_to_replace);
459                let mapped_condition = self.map_int_expr(condition, variables_to_replace);
460                if mapped_arg1.is_none() && mapped_arg2.is_none() && mapped_condition.is_none() {
461                    return None;
462                }
463                let arg1 = mapped_arg1.unwrap_or(arg1);
464                let arg2 = mapped_arg2.unwrap_or(arg2);
465                let condition = mapped_condition.unwrap_or(condition);
466                IntegerExpression::Condition(condition, question_span, arg1, colon_span, arg2)
467            }
468
469            IntegerExpression::FunctionCall(_, _) => todo!("Function Calls"),
470
471            IntegerExpression::Abs(expr) => {
472                let expr = self.map_int_expr(expr, variables_to_replace)?;
473                IntegerExpression::Abs(expr)
474            }
475
476            IntegerExpression::Min(arg1, arg2) => {
477                let mapped_arg1 = self.map_int_expr(arg1, variables_to_replace);
478                let mapped_arg2 = self.map_int_expr(arg2, variables_to_replace);
479                let (arg1, arg2) = match (mapped_arg1, mapped_arg2) {
480                    (None, None) => return None,
481                    (Some(arg1), None) => (arg1, arg2),
482                    (None, Some(arg2)) => (arg1, arg2),
483                    (Some(arg1), Some(arg2)) => (arg1, arg2),
484                };
485                IntegerExpression::Min(arg1, arg2)
486            }
487
488            IntegerExpression::Max(arg1, arg2) => {
489                let mapped_arg1 = self.map_int_expr(arg1, variables_to_replace);
490                let mapped_arg2 = self.map_int_expr(arg2, variables_to_replace);
491                let (arg1, arg2) = match (mapped_arg1, mapped_arg2) {
492                    (None, None) => return None,
493                    (Some(arg1), None) => (arg1, arg2),
494                    (None, Some(arg2)) => (arg1, arg2),
495                    (Some(arg1), Some(arg2)) => (arg1, arg2),
496                };
497                IntegerExpression::Max(arg1, arg2)
498            }
499
500            IntegerExpression::IntegerComparison(lhs, op, rhs) => {
501                let mapped_lhs = self.map_int_expr(lhs, variables_to_replace);
502                let mapped_rhs = self.map_int_expr(rhs, variables_to_replace);
503                let (lhs, rhs) = match (mapped_lhs, mapped_rhs) {
504                    (None, None) => return None,
505                    (Some(lhs), None) => (lhs, rhs),
506                    (None, Some(rhs)) => (lhs, rhs),
507                    (Some(lhs), Some(rhs)) => (lhs, rhs),
508                };
509                IntegerExpression::IntegerComparison(lhs, op, rhs)
510            }
511
512            IntegerExpression::RealComparison(lhs, op, rhs) => {
513                let mapped_lhs = self.map_real_expr(lhs, variables_to_replace);
514                let mapped_rhs = self.map_real_expr(rhs, variables_to_replace);
515                let (lhs, rhs) = match (mapped_lhs, mapped_rhs) {
516                    (None, None) => return None,
517                    (Some(lhs), None) => (lhs, rhs),
518                    (None, Some(rhs)) => (lhs, rhs),
519                    (Some(lhs), Some(rhs)) => (lhs, rhs),
520                };
521                IntegerExpression::RealComparison(lhs, op, rhs)
522            }
523
524            IntegerExpression::StringEq(arg1, arg2) => {
525                let mapped_arg1 = self.map_str_expr(arg1, variables_to_replace);
526                let mapped_arg2 = self.map_str_expr(arg2, variables_to_replace);
527                let (arg1, arg2) = match (mapped_arg1, mapped_arg2) {
528                    (None, None) => return None,
529                    (Some(arg1), None) => (arg1, arg2),
530                    (None, Some(arg2)) => (arg1, arg2),
531                    (Some(arg1), Some(arg2)) => (arg1, arg2),
532                };
533                IntegerExpression::StringEq(arg1, arg2)
534            }
535            IntegerExpression::StringNEq(arg1, arg2) => {
536                let mapped_arg1 = self.map_str_expr(arg1, variables_to_replace);
537                let mapped_arg2 = self.map_str_expr(arg2, variables_to_replace);
538                let (arg1, arg2) = match (mapped_arg1, mapped_arg2) {
539                    (None, None) => return None,
540                    (Some(arg1), None) => (arg1, arg2),
541                    (None, Some(arg2)) => (arg1, arg2),
542                    (Some(arg1), Some(arg2)) => (arg1, arg2),
543                };
544                IntegerExpression::StringNEq(arg1, arg2)
545            }
546
547            IntegerExpression::RealCast(expr) => {
548                let expr = self.map_real_expr(expr, variables_to_replace)?;
549                IntegerExpression::RealCast(expr)
550            }
551
552            IntegerExpression::Literal(_)
553            | IntegerExpression::ParamGiven(_)
554            | IntegerExpression::PortConnected(_)
555            | IntegerExpression::ParameterReference(_)
556            | IntegerExpression::PortReference(_)
557            | IntegerExpression::NetReference(_) => return None,
558        };
559        Some(self.integer_expressions.push(self[expr].clone_as(new_expr)))
560    }
561
562    pub fn map_str_expr(
563        &mut self,
564        expr: StringExpressionId,
565        variables_to_replace: &FxHashMap<VariableId, VariableId>,
566    ) -> Option<StringExpressionId> {
567        let new_expr = match self[expr].contents {
568            StringExpression::VariableReference(var) => {
569                let new_var = *variables_to_replace.get(&var)?;
570                StringExpression::VariableReference(new_var)
571            }
572
573            StringExpression::Condition(condition, question_span, arg1, colon_span, arg2) => {
574                let mapped_arg1 = self.map_str_expr(arg1, variables_to_replace);
575                let mapped_arg2 = self.map_str_expr(arg2, variables_to_replace);
576                let mapped_condition = self.map_int_expr(condition, variables_to_replace);
577                if mapped_arg1.is_none() && mapped_arg2.is_none() && mapped_condition.is_none() {
578                    return None;
579                }
580                let arg1 = mapped_arg1.unwrap_or(arg1);
581                let arg2 = mapped_arg2.unwrap_or(arg2);
582                let condition = mapped_condition.unwrap_or(condition);
583                StringExpression::Condition(condition, question_span, arg1, colon_span, arg2)
584            }
585
586            StringExpression::SimParam(name) => {
587                StringExpression::SimParam(self.map_str_expr(name, variables_to_replace)?)
588            }
589            StringExpression::Literal(_) | StringExpression::ParameterReference(_) => return None,
590        };
591        Some(self.string_expressions.push(self[expr].clone_as(new_expr)))
592    }
593}