1use 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 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 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 pub statements: IndexVec<StatementId, Statement>,
46}
47
48impl Mir {
49 pub(crate) fn initalize(hir: &mut Hir) -> Self {
52 Self {
53 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 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}