1use crate::HashMap;
2use crate::attribute::EnumEncodingItem;
3use crate::conv::Context;
4use crate::conv::utils::{TypePosition, eval_generic_expr, eval_size, eval_type};
5use crate::definition_table::DefinitionId;
6use crate::ir::{self, Shape};
7use crate::literal::Literal;
8use crate::literal_table;
9use crate::namespace::Namespace;
10use crate::namespace_table;
11use crate::symbol_path::{GenericSymbolPath, GenericSymbolPathKind, SymbolPath};
12use crate::symbol_table::{self, Import};
13use crate::value::Value;
14use std::cell::RefCell;
15use std::fmt;
16use std::hash::{DefaultHasher, Hash, Hasher};
17use veryl_parser::Stringifier;
18use veryl_parser::resource_table::{self, PathId, StrId};
19use veryl_parser::token_range::TokenRange;
20use veryl_parser::veryl_grammar_trait::{self as syntax_tree, ArrayType};
21use veryl_parser::veryl_token::{Token, VerylToken};
22use veryl_parser::veryl_walker::VerylWalker;
23
24#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
25pub struct SymbolId(pub usize);
26
27thread_local!(static SYMBOL_ID: RefCell<usize> = const { RefCell::new(0) });
28
29pub fn new_symbol_id() -> SymbolId {
30 SYMBOL_ID.with(|f| {
31 let mut ret = f.borrow_mut();
32 *ret += 1;
33 SymbolId(*ret)
34 })
35}
36
37#[derive(Debug, Clone)]
39pub struct DocCommentLine {
40 pub text: StrId,
41 pub line: u32,
42}
43
44#[derive(Debug, Default, Clone)]
45pub struct DocComment(pub Vec<DocCommentLine>);
46
47impl DocComment {
48 pub fn format(&self, single_line: bool) -> String {
49 let mut ret = String::new();
50 for entry in &self.0 {
51 let t = format!("{}", entry.text);
52 let t = t.trim_start_matches("///");
53 ret.push_str(t);
54 if single_line {
55 break;
56 }
57 }
58 ret
59 }
60
61 pub fn is_empty(&self) -> bool {
62 self.0.is_empty()
63 }
64
65 pub fn extract_wavedrom(&self) -> Option<String> {
67 self.extract_wavedrom_block(false).map(|block| block.json)
68 }
69
70 pub fn extract_wavedrom_test(&self) -> Option<String> {
72 self.extract_wavedrom_block(true).map(|block| block.json)
73 }
74
75 pub fn extract_wavedrom_block(&self, test_only: bool) -> Option<WavedromBlock> {
77 let mut in_wavedrom = false;
78 let mut json_lines = Vec::new();
79 let mut fence_line = 0u32;
80 let mut end_line = 0u32;
81 let mut content_lines: Vec<(String, u32)> = Vec::new();
82
83 for entry in &self.0 {
84 let text = format!("{}", entry.text);
85 let trimmed = text.trim_start_matches("///").trim();
86 if !in_wavedrom {
87 let is_match = if test_only {
88 if let Some(rest) = trimmed.strip_prefix("```wavedrom")
89 && let Some(attrs) = rest.trim().strip_prefix(',')
90 {
91 attrs.trim() == "test"
92 } else {
93 false
94 }
95 } else {
96 trimmed.starts_with("```wavedrom")
97 };
98 if is_match {
99 in_wavedrom = true;
100 json_lines.clear();
101 content_lines.clear();
102 fence_line = entry.line;
103 }
104 } else if trimmed == "```" {
105 end_line = entry.line;
106 let json = json_lines.join("\n");
107 if !json.trim().is_empty() {
108 return Some(WavedromBlock {
109 json,
110 fence_line,
111 end_line,
112 content_lines,
113 });
114 }
115 in_wavedrom = false;
116 } else {
117 json_lines.push(trimmed.to_string());
118 content_lines.push((trimmed.to_string(), entry.line));
119 }
120 }
121
122 None
123 }
124}
125
126#[derive(Debug)]
128pub struct WavedromBlock {
129 pub json: String,
130 pub fence_line: u32,
131 pub end_line: u32,
132 pub content_lines: Vec<(String, u32)>,
133}
134
135impl WavedromBlock {
136 pub fn find_line_containing(&self, needle: &str) -> Option<u32> {
138 self.content_lines
139 .iter()
140 .find(|(text, _)| text.contains(needle))
141 .map(|(_, line)| *line)
142 }
143}
144
145pub type GenericTable = HashMap<StrId, GenericSymbolPath>;
146pub type GenericTables = HashMap<Namespace, GenericTable>;
147
148#[derive(Clone, Debug, Default)]
149pub struct GenericMap {
150 pub id: Option<SymbolId>,
151 pub map: GenericTable,
152}
153
154impl GenericMap {
155 pub fn generic(&self) -> bool {
156 !self.map.is_empty()
157 }
158
159 pub fn name(&self, include_namspace_prefix: bool, hashed_name: bool) -> String {
160 let symbol = symbol_table::get(self.id.unwrap()).unwrap();
161 if let SymbolKind::GenericInstance(x) = symbol.kind {
162 let base = symbol_table::get(x.base).unwrap();
163 if hashed_name {
164 format!(
165 "{}__{}__{:x}",
166 self.get_name_prefix(&base, include_namspace_prefix),
167 base.token,
168 self.calc_args_hash(&x.arguments),
169 )
170 } else {
171 format!(
172 "{}{}",
173 self.get_name_prefix(&base, include_namspace_prefix),
174 symbol.token
175 )
176 }
177 } else {
178 format!(
179 "{}{}",
180 self.get_name_prefix(&symbol, include_namspace_prefix),
181 symbol.token
182 )
183 }
184 }
185
186 fn get_name_prefix(&self, symbol: &Symbol, include_namspace_prefix: bool) -> String {
187 let emit_namespace_preffix = match &symbol.kind {
188 SymbolKind::Module(_) | SymbolKind::Interface(_) | SymbolKind::Package(_) => {
189 include_namspace_prefix
190 }
191 SymbolKind::Function(x) => include_namspace_prefix && x.is_global(),
192 _ => false,
193 };
194 if emit_namespace_preffix {
195 format!("{}_", symbol.namespace)
196 } else {
197 "".to_string()
198 }
199 }
200
201 fn calc_args_hash(&self, args: &[GenericSymbolPath]) -> u64 {
202 let string_args: Vec<_> = args.iter().map(|x| x.to_string()).collect();
203 let mut hasher = DefaultHasher::new();
204 string_args.hash(&mut hasher);
205 hasher.finish()
206 }
207}
208
209impl fmt::Display for GenericMap {
210 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
211 let mut ret = String::new();
212
213 for (k, v) in &self.map {
214 ret.push_str(&format!("{k}: {v}"));
215 }
216
217 ret.fmt(f)
218 }
219}
220
221#[derive(Debug, Clone)]
222pub struct Symbol {
223 pub token: Token,
224 pub id: SymbolId,
225 pub kind: SymbolKind,
226 pub namespace: Namespace,
227 pub references: Vec<Token>,
228 pub generic_instances: Vec<SymbolId>,
229 pub imported: Vec<Import>,
230 pub allow_unused: bool,
231 pub public: bool,
232 pub doc_comment: DocComment,
233}
234
235impl Symbol {
236 pub fn new(
237 token: &Token,
238 kind: SymbolKind,
239 namespace: &Namespace,
240 public: bool,
241 doc_comment: DocComment,
242 ) -> Self {
243 Self {
244 token: *token,
245 id: new_symbol_id(),
246 kind,
247 namespace: namespace.to_owned(),
248 references: Vec::new(),
249 generic_instances: Vec::new(),
250 imported: Vec::new(),
251 allow_unused: false,
252 public,
253 doc_comment,
254 }
255 }
256
257 pub fn get_parent(&self) -> Option<Symbol> {
258 self.namespace.get_symbol()
259 }
260
261 pub fn get_parent_component(&self) -> Option<Symbol> {
262 let parent = self.get_parent()?;
263 Symbol::trace_component_symbol(&parent)
264 }
265
266 fn trace_component_symbol(symbol: &Symbol) -> Option<Symbol> {
267 match &symbol.kind {
268 SymbolKind::Module(_)
269 | SymbolKind::ProtoModule(_)
270 | SymbolKind::Interface(_)
271 | SymbolKind::ProtoInterface(_)
272 | SymbolKind::Package(_)
273 | SymbolKind::ProtoPackage(_)
274 | SymbolKind::SystemVerilog => Some(symbol.clone()),
275 SymbolKind::AliasModule(x) | SymbolKind::ProtoAliasModule(x) => {
276 let symbol =
277 symbol_table::resolve((&x.target.generic_path(), &symbol.namespace)).ok()?;
278 Symbol::trace_component_symbol(&symbol.found)
279 }
280 SymbolKind::AliasInterface(x) | SymbolKind::ProtoAliasInterface(x) => {
281 let symbol =
282 symbol_table::resolve((&x.target.generic_path(), &symbol.namespace)).ok()?;
283 Symbol::trace_component_symbol(&symbol.found)
284 }
285 SymbolKind::AliasPackage(x) | SymbolKind::ProtoAliasPackage(x) => {
286 let symbol =
287 symbol_table::resolve((&x.target.generic_path(), &symbol.namespace)).ok()?;
288 Symbol::trace_component_symbol(&symbol.found)
289 }
290 SymbolKind::GenericInstance(x) => {
291 let symbol = symbol_table::get(x.base)?;
292 Symbol::trace_component_symbol(&symbol)
293 }
294 SymbolKind::GenericParameter(x) => {
295 if let Ok(ProtoBound::ProtoPackage(x)) =
296 x.bound.resolve_proto_bound(&symbol.namespace)
297 {
298 Symbol::trace_component_symbol(&x)
299 } else {
300 None
301 }
302 }
303 _ => None,
304 }
305 }
306
307 pub fn get_parent_package(&self) -> Option<Symbol> {
308 let parent = self.get_parent_component()?;
309 if parent.is_package(true) {
310 Some(parent)
311 } else {
312 None
313 }
314 }
315
316 pub fn inner_namespace(&self) -> Namespace {
317 let mut ret = self.namespace.clone();
318 ret.push(self.token.text);
319 ret
320 }
321
322 pub fn generic_maps(&self) -> Vec<GenericMap> {
323 let mut ret = Vec::new();
324
325 let generic_instances = if matches!(self.kind, SymbolKind::GenericInstance(_)) {
326 &vec![self.id]
327 } else {
328 &self.generic_instances
329 };
330 for i in generic_instances {
331 let symbol = symbol_table::get(*i).unwrap();
332 let map = if let SymbolKind::GenericInstance(ref x) = symbol.kind {
333 self.generic_map(Some(symbol.id), &x.arguments)
334 } else {
335 self.generic_map(Some(symbol.id), &[])
336 };
337 ret.push(map);
338 }
339
340 if ret.is_empty() && !self.kind.is_generic() {
342 ret.push(GenericMap::default());
343 }
344 ret
345 }
346
347 pub fn generic_map(&self, id: Option<SymbolId>, arguments: &[GenericSymbolPath]) -> GenericMap {
348 let map = if arguments.is_empty() {
349 HashMap::default()
350 } else {
351 self.generic_table(arguments)
352 };
353 GenericMap { id, map }
354 }
355
356 pub fn generic_table(&self, arguments: &[GenericSymbolPath]) -> GenericTable {
357 let params = self.generic_parameters();
358 let n_args = arguments.len();
359 let mut map = GenericMap::default();
360
361 let match_arity = if params.len() > n_args {
362 params[n_args].1.default_value.is_some()
363 } else {
364 params.len() == n_args
365 };
366 if !match_arity {
367 return map.map;
370 }
371
372 for (i, arg) in arguments.iter().enumerate() {
373 if let Some((p, _)) = params.get(i) {
374 map.map.insert(*p, arg.clone());
375 }
376 }
377
378 for param in params.iter().skip(n_args) {
379 map.map
380 .insert(param.0, param.1.default_value.as_ref().unwrap().clone());
381 }
382
383 self.eval_generic_consts(&mut map);
384
385 map.map
386 }
387
388 pub fn eval_generic_consts(&self, generic_map: &mut GenericMap) {
389 for (name, r#const) in self.generic_consts() {
390 if let Some(path) = Self::expr_to_generic_symbol_path(&r#const.value, generic_map) {
391 generic_map.map.insert(name, path);
392 }
393 }
394 }
395
396 fn expr_to_generic_symbol_path(
397 expr: &syntax_tree::Expression,
398 generic_map: &GenericMap,
399 ) -> Option<GenericSymbolPath> {
400 fn eval_value(
401 context: &mut Context,
402 expr: &syntax_tree::Expression,
403 ) -> Option<(Value, TokenRange)> {
404 let (comptime, _) = eval_generic_expr(context, expr).ok()?;
405 comptime
406 .get_value()
407 .cloned()
408 .ok()
409 .map(|x| (x, comptime.token))
410 }
411
412 if let Some(factor) = expr.unwrap_factor() {
413 match factor {
414 syntax_tree::Factor::Number(x) => return Some(x.number.as_ref().into()),
415 syntax_tree::Factor::BooleanLiteral(x) => {
416 return Some(x.boolean_literal.as_ref().into());
417 }
418 syntax_tree::Factor::IdentifierFactor(x)
419 if x.identifier_factor.identifier_factor_opt.is_none() =>
420 {
421 let mut context = Context::default();
422 context.push_generic_map(vec![generic_map.clone()]);
423
424 let path = context
425 .resolve_path(x.identifier_factor.expression_identifier.as_ref().into());
426 return Some(path);
427 }
428 syntax_tree::Factor::LParenExpressionRParen(x) => {
429 return Self::expr_to_generic_symbol_path(&x.expression, generic_map);
430 }
431 syntax_tree::Factor::TypeExpression(x) => {
432 return Self::expr_to_generic_symbol_path(
433 &x.type_expression.expression,
434 generic_map,
435 );
436 }
437 syntax_tree::Factor::FactorTypeFactor(x) => {
438 match x.factor_type_factor.factor_type.factor_type_group.as_ref() {
439 syntax_tree::FactorTypeGroup::FixedType(x) => {
440 return Some(x.fixed_type.as_ref().into());
441 }
442 syntax_tree::FactorTypeGroup::VariableTypeFactorTypeOpt(x) => {
443 let mut width = Vec::new();
444 if let Some(x) = &x.factor_type_opt {
445 let mut context = Context::default();
446 context.push_generic_map(vec![generic_map.clone()]);
447
448 for expr in Vec::from(x.width.as_ref()) {
449 if let Some((x, _)) = eval_value(&mut context, expr)
450 && let Some(x) = x.to_usize()
451 {
452 width.push(x);
453 } else {
454 return None;
455 }
456 }
457 }
458
459 let path = (x.variable_type.as_ref(), &width).into();
460 return Some(path);
461 }
462 }
463 }
464 _ => {}
465 }
466 };
467
468 let mut context = Context::default();
469 context.push_generic_map(vec![generic_map.clone()]);
470 if let Some((value, token)) = eval_value(&mut context, expr)
471 && !value.is_xz()
472 {
473 let text = format!("{}", value.payload());
474 let text = resource_table::insert_str(&text);
475 let token = Token::generate(text, token.beg.source.get_path().unwrap());
476
477 let literal_value = Literal::Value(value);
478 literal_table::insert(token.id, literal_value);
479
480 let mut path: GenericSymbolPath = (&token).into();
481 path.kind = GenericSymbolPathKind::ValueLiteral;
482 Some(path)
483 } else {
484 None
485 }
486 }
487
488 pub fn generic_parameters(&self) -> Vec<(StrId, GenericParameterProperty)> {
489 fn get_generic_parameter(id: SymbolId) -> (StrId, GenericParameterProperty) {
490 let symbol = symbol_table::get(id).unwrap();
491 if let SymbolKind::GenericParameter(x) = symbol.kind {
492 (symbol.token.text, x)
493 } else {
494 unreachable!()
495 }
496 }
497
498 match &self.kind {
499 SymbolKind::Function(x) => x
500 .generic_parameters
501 .iter()
502 .map(|x| get_generic_parameter(*x))
503 .collect(),
504 SymbolKind::Module(x) => x
505 .generic_parameters
506 .iter()
507 .map(|x| get_generic_parameter(*x))
508 .collect(),
509 SymbolKind::Interface(x) => x
510 .generic_parameters
511 .iter()
512 .map(|x| get_generic_parameter(*x))
513 .collect(),
514 SymbolKind::Package(x) => x
515 .generic_parameters
516 .iter()
517 .map(|x| get_generic_parameter(*x))
518 .collect(),
519 SymbolKind::Struct(x) => x
520 .generic_parameters
521 .iter()
522 .map(|x| get_generic_parameter(*x))
523 .collect(),
524 SymbolKind::Union(x) => x
525 .generic_parameters
526 .iter()
527 .map(|x| get_generic_parameter(*x))
528 .collect(),
529 SymbolKind::GenericInstance(x) => {
530 let symbol = symbol_table::get(x.base).unwrap();
531 symbol.generic_parameters()
532 }
533 _ => Vec::new(),
534 }
535 }
536
537 pub fn has_generic_paramters(&self) -> bool {
538 match &self.kind {
539 SymbolKind::Function(x) => !x.generic_parameters.is_empty(),
540 SymbolKind::Module(x) => !x.generic_parameters.is_empty(),
541 SymbolKind::Interface(x) => !x.generic_parameters.is_empty(),
542 SymbolKind::Package(x) => !x.generic_parameters.is_empty(),
543 SymbolKind::Struct(x) => !x.generic_parameters.is_empty(),
544 SymbolKind::Union(x) => !x.generic_parameters.is_empty(),
545 SymbolKind::GenericInstance(x) => {
546 let symbol = symbol_table::get(x.base).unwrap();
547 symbol.has_generic_paramters()
548 }
549 _ => false,
550 }
551 }
552
553 pub fn generic_consts(&self) -> Vec<(StrId, GenericConstProperty)> {
554 fn get_generic_const(id: SymbolId) -> (StrId, GenericConstProperty) {
555 let symbol = symbol_table::get(id).unwrap();
556 if let SymbolKind::GenericConst(x) = symbol.kind {
557 (symbol.token.text, x)
558 } else {
559 unreachable!()
560 }
561 }
562
563 match &self.kind {
564 SymbolKind::Function(x) => x
565 .generic_consts
566 .iter()
567 .map(|x| get_generic_const(*x))
568 .collect(),
569 SymbolKind::Module(x) => x
570 .generic_consts
571 .iter()
572 .map(|x| get_generic_const(*x))
573 .collect(),
574 SymbolKind::Interface(x) => x
575 .generic_consts
576 .iter()
577 .map(|x| get_generic_const(*x))
578 .collect(),
579 SymbolKind::Package(x) => x
580 .generic_consts
581 .iter()
582 .map(|x| get_generic_const(*x))
583 .collect(),
584 SymbolKind::GenericInstance(x) => {
585 let symbol = symbol_table::get(x.base).unwrap();
586 symbol.generic_consts()
587 }
588 _ => Vec::new(),
589 }
590 }
591
592 pub fn generic_references(&self) -> Vec<GenericSymbolPath> {
593 let references = match &self.kind {
594 SymbolKind::Function(x) => &x.generic_references,
595 SymbolKind::Module(x) => &x.generic_references,
596 SymbolKind::Interface(x) => &x.generic_references,
597 SymbolKind::Package(x) => &x.generic_references,
598 SymbolKind::Struct(x) => &x.generic_references,
599 SymbolKind::Union(x) => &x.generic_references,
600 _ => return Vec::new(),
601 };
602 references
603 .iter()
604 .filter(|r| r.is_generic_reference())
605 .cloned()
606 .collect()
607 }
608
609 pub fn proto(&self) -> Option<Symbol> {
610 match &self.kind {
611 SymbolKind::Module(x) => {
612 if let Some(proto) = &x.proto {
613 return symbol_table::resolve((&proto.generic_path(), &self.namespace))
614 .map(|x| (*x.found).clone())
615 .ok();
616 }
617 }
618 SymbolKind::AliasModule(x) => {
619 let symbol =
620 symbol_table::resolve((&x.target.generic_path(), &self.namespace)).ok()?;
621 return symbol.found.proto();
622 }
623 SymbolKind::ProtoAliasModule(x) => {
624 return symbol_table::resolve((&x.target.generic_path(), &self.namespace))
625 .map(|x| (*x.found).clone())
626 .ok();
627 }
628 SymbolKind::Interface(x) => {
629 if let Some(proto) = &x.proto {
630 return symbol_table::resolve((&proto.generic_path(), &self.namespace))
631 .map(|x| (*x.found).clone())
632 .ok();
633 } else if x.generic_parameters.is_empty() {
634 return Some(self.clone());
635 }
636 }
637 SymbolKind::AliasInterface(x) => {
638 let symbol =
639 symbol_table::resolve((&x.target.generic_path(), &self.namespace)).ok()?;
640 return symbol.found.proto();
641 }
642 SymbolKind::ProtoAliasInterface(x) => {
643 return symbol_table::resolve((&x.target.generic_path(), &self.namespace))
644 .map(|x| (*x.found).clone())
645 .ok();
646 }
647 SymbolKind::Package(x) => {
648 if let Some(proto) = &x.proto {
649 return symbol_table::resolve((&proto.generic_path(), &self.namespace))
650 .map(|x| (*x.found).clone())
651 .ok();
652 }
653 }
654 SymbolKind::AliasPackage(x) => {
655 let symbol =
656 symbol_table::resolve((&x.target.generic_path(), &self.namespace)).ok()?;
657 return symbol.found.proto();
658 }
659 SymbolKind::ProtoAliasPackage(x) => {
660 return symbol_table::resolve((&x.target.generic_path(), &self.namespace))
661 .map(|x| (*x.found).clone())
662 .ok();
663 }
664 SymbolKind::GenericParameter(x) => {
665 let proto = x.bound.resolve_proto_bound(&self.namespace).ok()?;
666 return proto.get_symbol();
667 }
668 _ => {}
669 }
670
671 None
672 }
673
674 pub fn alias_target(&self, include_proto: bool) -> Option<GenericSymbolPath> {
675 match &self.kind {
676 SymbolKind::AliasModule(x) => Some(x.target.clone()),
677 SymbolKind::ProtoAliasModule(x) if include_proto => Some(x.target.clone()),
678 SymbolKind::AliasInterface(x) => Some(x.target.clone()),
679 SymbolKind::ProtoAliasInterface(x) if include_proto => Some(x.target.clone()),
680 SymbolKind::AliasPackage(x) => Some(x.target.clone()),
681 SymbolKind::ProtoAliasPackage(x) if include_proto => Some(x.target.clone()),
682 _ => None,
683 }
684 }
685
686 pub fn is_module(&self, include_proto: bool) -> bool {
687 match &self.kind {
688 SymbolKind::Module(_) | SymbolKind::AliasModule(_) => return true,
689 SymbolKind::ProtoModule(_) => return include_proto,
690 SymbolKind::GenericInstance(x) => {
691 let symbol = symbol_table::get(x.base).unwrap();
692 return symbol.is_module(false);
693 }
694 SymbolKind::GenericParameter(x) => {
695 if let Ok(ProtoBound::ProtoModule(x)) = x.bound.resolve_proto_bound(&self.namespace)
696 {
697 return x.is_module(true);
698 }
699 }
700 _ => {}
701 }
702 false
703 }
704
705 pub fn is_proto_module(&self, trace_generic_param: bool) -> bool {
706 match &self.kind {
707 SymbolKind::ProtoModule(_) => return true,
708 SymbolKind::GenericParameter(x) if trace_generic_param => {
709 if let Ok(ProtoBound::ProtoModule(x)) = x.bound.resolve_proto_bound(&self.namespace)
710 {
711 return x.is_proto_module(trace_generic_param);
712 }
713 }
714 _ => {}
715 }
716 false
717 }
718
719 pub fn is_interface(&self, include_proto: bool) -> bool {
720 match &self.kind {
721 SymbolKind::Interface(_) | SymbolKind::AliasInterface(_) => return true,
722 SymbolKind::ProtoInterface(_) => return include_proto,
723 SymbolKind::GenericInstance(x) => {
724 let symbol = symbol_table::get(x.base).unwrap();
725 return symbol.is_interface(false);
726 }
727 SymbolKind::GenericParameter(x) => {
728 if let Ok(ProtoBound::ProtoInterface(x)) =
729 x.bound.resolve_proto_bound(&self.namespace)
730 {
731 return x.is_interface(true);
732 }
733 }
734 _ => {}
735 }
736 false
737 }
738
739 pub fn is_proto_interface(
740 &self,
741 trace_generic_param: bool,
742 include_non_generic_interface: bool,
743 ) -> bool {
744 match &self.kind {
745 SymbolKind::Interface(x) => {
746 return include_non_generic_interface && x.generic_parameters.is_empty();
747 }
748 SymbolKind::ProtoInterface(_) => return true,
749 SymbolKind::GenericParameter(x) if trace_generic_param => {
750 if let Ok(ProtoBound::ProtoInterface(x)) =
751 x.bound.resolve_proto_bound(&self.namespace)
752 {
753 return x
754 .is_proto_interface(trace_generic_param, include_non_generic_interface);
755 }
756 }
757 _ => {}
758 }
759 false
760 }
761
762 pub fn is_package(&self, include_proto: bool) -> bool {
763 match &self.kind {
764 SymbolKind::Package(_) | SymbolKind::AliasPackage(_) => return true,
765 SymbolKind::ProtoPackage(_) => return include_proto,
766 SymbolKind::GenericInstance(x) => {
767 let symbol = symbol_table::get(x.base).unwrap();
768 return symbol.is_package(false);
769 }
770 SymbolKind::GenericParameter(x) => {
771 if let Ok(ProtoBound::ProtoPackage(x)) =
772 x.bound.resolve_proto_bound(&self.namespace)
773 {
774 return x.is_package(true);
775 }
776 }
777 _ => {}
778 }
779 false
780 }
781
782 pub fn is_component(&self, include_proto: bool) -> bool {
783 match &self.kind {
784 SymbolKind::Module(_)
785 | SymbolKind::AliasModule(_)
786 | SymbolKind::Interface(_)
787 | SymbolKind::AliasInterface(_)
788 | SymbolKind::Package(_)
789 | SymbolKind::AliasPackage(_) => return true,
790 SymbolKind::ProtoModule(_)
791 | SymbolKind::ProtoInterface(_)
792 | SymbolKind::ProtoPackage(_) => return include_proto,
793 SymbolKind::GenericInstance(x) => {
794 let symbol = symbol_table::get(x.base).unwrap();
795 return symbol.is_component(false);
796 }
797 SymbolKind::GenericParameter(x) => {
798 if let Ok(ProtoBound::ProtoInterface(x)) =
799 x.bound.resolve_proto_bound(&self.namespace)
800 {
801 return x.is_component(true);
802 }
803 }
804 _ => {}
805 }
806 false
807 }
808
809 pub fn is_proto_package(&self, trace_generic_param: bool) -> bool {
810 match &self.kind {
811 SymbolKind::ProtoPackage(_) => return true,
812 SymbolKind::GenericParameter(x) if trace_generic_param => {
813 if let Ok(ProtoBound::ProtoPackage(x)) =
814 x.bound.resolve_proto_bound(&self.namespace)
815 {
816 return x.is_proto_package(trace_generic_param);
817 }
818 }
819 _ => {}
820 }
821 false
822 }
823
824 pub fn is_importable(&self, include_proto: bool) -> bool {
825 match &self.kind {
826 SymbolKind::ProtoConst(_)
827 | SymbolKind::ProtoTypeDef(_)
828 | SymbolKind::ProtoFunction(_) => {
829 return include_proto;
830 }
831 SymbolKind::Parameter(_)
832 | SymbolKind::TypeDef(_)
833 | SymbolKind::Enum(_)
834 | SymbolKind::Struct(_)
835 | SymbolKind::Union(_)
836 | SymbolKind::Function(_) => {
837 if let Some(parent) = self.get_parent() {
838 return parent.is_package(include_proto);
839 }
840 }
841 SymbolKind::EnumMember(_) | SymbolKind::EnumMemberMangled => {
842 if let Some(parent) = self.get_parent() {
843 return parent.is_importable(include_proto);
844 }
845 }
846 _ => {}
847 }
848 false
849 }
850
851 pub fn is_variable_type(&self) -> bool {
852 match &self.kind {
853 SymbolKind::Enum(_)
854 | SymbolKind::Union(_)
855 | SymbolKind::Struct(_)
856 | SymbolKind::TypeDef(_)
857 | SymbolKind::ProtoTypeDef(_)
858 | SymbolKind::SystemVerilog => true,
859 SymbolKind::Parameter(x) => matches!(x.r#type.kind, TypeKind::Type),
860 SymbolKind::ProtoConst(x) => matches!(x.r#type.kind, TypeKind::Type),
861 SymbolKind::GenericParameter(x) => matches!(x.bound, GenericBoundKind::Type),
862 SymbolKind::GenericConst(x) => matches!(x.bound, GenericBoundKind::Type),
863 SymbolKind::GenericInstance(x) => symbol_table::get(x.base)
864 .map(|x| x.is_variable_type())
865 .unwrap_or(false),
866 _ => false,
867 }
868 }
869
870 pub fn is_casting_type(&self) -> bool {
871 let type_kind = match &self.kind {
872 SymbolKind::Parameter(x) => &x.r#type.kind,
873 SymbolKind::ProtoConst(x) => &x.r#type.kind,
874 SymbolKind::GenericParameter(x) => {
875 if let GenericBoundKind::Proto(x) = &x.bound {
876 &x.kind
877 } else {
878 return matches!(x.bound, GenericBoundKind::Type);
879 }
880 }
881 SymbolKind::GenericConst(x) => {
882 if let GenericBoundKind::Proto(x) = &x.bound {
883 &x.kind
884 } else {
885 return matches!(x.bound, GenericBoundKind::Type);
886 }
887 }
888 _ => return self.is_variable_type(),
889 };
890 matches!(
891 type_kind,
892 TypeKind::Type
893 | TypeKind::U8
894 | TypeKind::U16
895 | TypeKind::U32
896 | TypeKind::U64
897 | TypeKind::I8
898 | TypeKind::I16
899 | TypeKind::I32
900 | TypeKind::I64
901 | TypeKind::P8
902 | TypeKind::P16
903 | TypeKind::P32
904 | TypeKind::P64
905 )
906 }
907
908 pub fn is_struct(&self) -> bool {
909 match &self.kind {
910 SymbolKind::Struct(_) => true,
911 SymbolKind::TypeDef(x) => {
912 let namespace = Some(&self.namespace);
913 if let Some((_, Some(symbol))) = x.r#type.trace_user_defined(namespace) {
914 symbol.is_struct()
915 } else {
916 false
917 }
918 }
919 _ => false,
920 }
921 }
922
923 pub fn is_union(&self) -> bool {
924 match &self.kind {
925 SymbolKind::Union(_) => true,
926 SymbolKind::TypeDef(x) => {
927 let namespace = Some(&self.namespace);
928 if let Some((_, Some(symbol))) = x.r#type.trace_user_defined(namespace) {
929 symbol.is_union()
930 } else {
931 false
932 }
933 }
934 _ => false,
935 }
936 }
937
938 pub fn is_global_function(&self) -> bool {
939 match &self.kind {
940 SymbolKind::Function(x) => x.is_global(),
941 SymbolKind::GenericInstance(x) => {
942 let symbol = symbol_table::get(x.base).unwrap();
943 symbol.is_global_function()
944 }
945 _ => false,
946 }
947 }
948}
949
950#[derive(Debug, Clone)]
951pub enum SymbolKind {
952 Port(PortProperty),
953 Variable(VariableProperty),
954 Module(ModuleProperty),
955 ProtoModule(ProtoModuleProperty),
956 AliasModule(AliasModuleProperty),
957 ProtoAliasModule(AliasModuleProperty),
958 Interface(InterfaceProperty),
959 ProtoInterface(ProtoInterfaceProperty),
960 AliasInterface(AliasInterfaceProperty),
961 ProtoAliasInterface(AliasInterfaceProperty),
962 Function(FunctionProperty),
963 ProtoFunction(FunctionProperty),
964 Parameter(ParameterProperty),
965 ProtoConst(ProtoConstProperty),
966 Instance(InstanceProperty),
967 Block,
968 Package(PackageProperty),
969 ProtoPackage(ProtoPackageProperty),
970 AliasPackage(AliasPackageProperty),
971 ProtoAliasPackage(AliasPackageProperty),
972 Struct(StructProperty),
973 StructMember(StructMemberProperty),
974 Union(UnionProperty),
975 UnionMember(UnionMemberProperty),
976 TypeDef(TypeDefProperty),
977 ProtoTypeDef(ProtoTypeDefProperty),
978 Enum(EnumProperty),
979 EnumMember(EnumMemberProperty),
980 EnumMemberMangled,
981 Modport(ModportProperty),
982 Genvar,
983 ModportVariableMember(ModportVariableMemberProperty),
984 ModportFunctionMember(ModportFunctionMemberProperty),
985 SystemVerilog,
986 Namespace,
987 SystemFunction(SystemFuncitonProperty),
988 GenericParameter(GenericParameterProperty),
989 GenericConst(GenericConstProperty),
990 GenericInstance(GenericInstanceProperty),
991 ClockDomain,
992 Test(TestProperty),
993 Embed,
994 TbComponent(TbComponentProperty),
995}
996
997impl SymbolKind {
998 pub fn to_kind_name(&self) -> String {
999 match self {
1000 SymbolKind::Port(x) => match x.direction {
1001 Direction::Modport => "modport".to_string(),
1002 Direction::Import => "function import".to_string(),
1003 _ => format!("{} port", x.direction),
1004 },
1005 SymbolKind::Variable(_) => "variable".to_string(),
1006 SymbolKind::Module(_) => "module".to_string(),
1007 SymbolKind::ProtoModule(_) => "proto module".to_string(),
1008 SymbolKind::AliasModule(_) => "alias module".to_string(),
1009 SymbolKind::ProtoAliasModule(_) => "proto alias module".to_string(),
1010 SymbolKind::Interface(_) => "interface".to_string(),
1011 SymbolKind::ProtoInterface(_) => "proto interface".to_string(),
1012 SymbolKind::AliasInterface(_) => "alias interface".to_string(),
1013 SymbolKind::ProtoAliasInterface(_) => "proto alias interface".to_string(),
1014 SymbolKind::Function(_) => "function".to_string(),
1015 SymbolKind::ProtoFunction(_) => "proto function".to_string(),
1016 SymbolKind::Parameter(_) => "parameter".to_string(),
1017 SymbolKind::ProtoConst(_) => "proto const".to_string(),
1018 SymbolKind::Instance(_) => "instance".to_string(),
1019 SymbolKind::Block => "block".to_string(),
1020 SymbolKind::Package(_) => "package".to_string(),
1021 SymbolKind::ProtoPackage(_) => "proto package".to_string(),
1022 SymbolKind::AliasPackage(_) => "alias package".to_string(),
1023 SymbolKind::ProtoAliasPackage(_) => "proto alias package".to_string(),
1024 SymbolKind::Struct(_) => "struct".to_string(),
1025 SymbolKind::StructMember(_) => "struct member".to_string(),
1026 SymbolKind::Union(_) => "union".to_string(),
1027 SymbolKind::UnionMember(_) => "union member".to_string(),
1028 SymbolKind::TypeDef(_) => "typedef".to_string(),
1029 SymbolKind::ProtoTypeDef(_) => "proto typedef".to_string(),
1030 SymbolKind::Enum(_) => "enum".to_string(),
1031 SymbolKind::EnumMember(_) => "enum member".to_string(),
1032 SymbolKind::EnumMemberMangled => "enum member mangled".to_string(),
1033 SymbolKind::Modport(_) => "modport".to_string(),
1034 SymbolKind::Genvar => "genvar".to_string(),
1035 SymbolKind::ModportVariableMember(x) => match x.direction {
1036 Direction::Input | Direction::Output | Direction::Inout => {
1037 format!("modport {} variable member", x.direction)
1038 }
1039 _ => unreachable!(),
1040 },
1041 SymbolKind::ModportFunctionMember(_) => "modport function member".to_string(),
1042 SymbolKind::SystemVerilog => "systemverilog item".to_string(),
1043 SymbolKind::Namespace => "namespace".to_string(),
1044 SymbolKind::SystemFunction(_) => "system function".to_string(),
1045 SymbolKind::GenericParameter(_) => "generic parameter".to_string(),
1046 SymbolKind::GenericConst(_) => "generic const".to_string(),
1047 SymbolKind::GenericInstance(_) => "generic instance".to_string(),
1048 SymbolKind::ClockDomain => "clock domain".to_string(),
1049 SymbolKind::Test(_) => "test".to_string(),
1050 SymbolKind::Embed => "embed".to_string(),
1051 SymbolKind::TbComponent(x) => format!("testbench {}", x.kind),
1052 }
1053 }
1054
1055 pub fn is_generic(&self) -> bool {
1056 match self {
1057 SymbolKind::Module(x) => !x.generic_parameters.is_empty(),
1058 SymbolKind::Interface(x) => !x.generic_parameters.is_empty(),
1059 SymbolKind::Function(x) => !x.generic_parameters.is_empty(),
1060 SymbolKind::Package(x) => !x.generic_parameters.is_empty(),
1061 SymbolKind::Struct(x) => !x.generic_parameters.is_empty(),
1062 SymbolKind::Union(x) => !x.generic_parameters.is_empty(),
1063 _ => false,
1064 }
1065 }
1066
1067 pub fn is_clock(&self) -> bool {
1068 match self {
1069 SymbolKind::Port(x) => x.r#type.kind.is_clock(),
1070 SymbolKind::Variable(x) => x.r#type.kind.is_clock(),
1071 _ => false,
1072 }
1073 }
1074
1075 pub fn can_be_default_clock(&self) -> bool {
1076 match self {
1077 SymbolKind::Port(x) => x.r#type.can_be_default_clock(),
1078 SymbolKind::Variable(x) => x.r#type.can_be_default_clock(),
1079 _ => false,
1080 }
1081 }
1082
1083 pub fn is_reset(&self) -> bool {
1084 match self {
1085 SymbolKind::Port(x) => x.r#type.kind.is_reset(),
1086 SymbolKind::Variable(x) => x.r#type.kind.is_reset(),
1087 _ => false,
1088 }
1089 }
1090
1091 pub fn can_be_default_reset(&self) -> bool {
1092 match self {
1093 SymbolKind::Port(x) => x.r#type.can_be_default_reset(),
1094 SymbolKind::Variable(x) => x.r#type.can_be_default_reset(),
1095 _ => false,
1096 }
1097 }
1098
1099 pub fn is_function(&self) -> bool {
1100 match self {
1101 SymbolKind::Function(_)
1102 | SymbolKind::ProtoFunction(_)
1103 | SymbolKind::SystemVerilog
1104 | SymbolKind::ModportFunctionMember(..)
1105 | SymbolKind::SystemFunction(_) => true,
1106 SymbolKind::GenericInstance(x) => {
1107 let base = symbol_table::get(x.base).unwrap();
1108 matches!(
1109 base.kind,
1110 SymbolKind::Function(_)
1111 | SymbolKind::SystemVerilog
1112 | SymbolKind::ModportFunctionMember(..)
1113 | SymbolKind::SystemFunction(_)
1114 )
1115 }
1116 _ => false,
1117 }
1118 }
1119
1120 pub fn get_type(&self) -> Option<&Type> {
1121 match self {
1122 SymbolKind::Port(x) => Some(&x.r#type),
1123 SymbolKind::Variable(x) => Some(&x.r#type),
1124 SymbolKind::Function(x) => x.ret.as_ref(),
1125 SymbolKind::ProtoFunction(x) => x.ret.as_ref(),
1126 SymbolKind::Parameter(x) => Some(&x.r#type),
1127 SymbolKind::ProtoConst(x) => Some(&x.r#type),
1128 SymbolKind::StructMember(x) => Some(&x.r#type),
1129 SymbolKind::UnionMember(x) => Some(&x.r#type),
1130 SymbolKind::TypeDef(x) => Some(&x.r#type),
1131 _ => None,
1132 }
1133 }
1134
1135 pub fn get_type_mut(&mut self) -> Option<&mut Type> {
1136 match self {
1137 SymbolKind::Port(x) => Some(&mut x.r#type),
1138 SymbolKind::Variable(x) => Some(&mut x.r#type),
1139 SymbolKind::Function(x) => x.ret.as_mut(),
1140 SymbolKind::ProtoFunction(x) => x.ret.as_mut(),
1141 SymbolKind::Parameter(x) => Some(&mut x.r#type),
1142 SymbolKind::ProtoConst(x) => Some(&mut x.r#type),
1143 SymbolKind::StructMember(x) => Some(&mut x.r#type),
1144 SymbolKind::UnionMember(x) => Some(&mut x.r#type),
1145 SymbolKind::TypeDef(x) => Some(&mut x.r#type),
1146 _ => None,
1147 }
1148 }
1149
1150 pub fn get_parameters(&self) -> &[Parameter] {
1151 match self {
1152 SymbolKind::Module(x) => &x.parameters,
1153 SymbolKind::Interface(x) => &x.parameters,
1154 _ => &[],
1155 }
1156 }
1157
1158 pub fn get_generic_parameters(&self) -> &[SymbolId] {
1159 match self {
1160 SymbolKind::Module(x) => &x.generic_parameters,
1161 SymbolKind::Interface(x) => &x.generic_parameters,
1162 SymbolKind::Function(x) => &x.generic_parameters,
1163 SymbolKind::Package(x) => &x.generic_parameters,
1164 SymbolKind::Struct(x) => &x.generic_parameters,
1165 SymbolKind::Union(x) => &x.generic_parameters,
1166 _ => &[],
1167 }
1168 }
1169
1170 pub fn get_definition(&self) -> Option<DefinitionId> {
1171 match self {
1172 SymbolKind::Module(x) => Some(x.definition),
1173 SymbolKind::Interface(x) => Some(x.definition),
1174 SymbolKind::Function(x) => x.definition,
1175 _ => None,
1176 }
1177 }
1178}
1179
1180impl fmt::Display for SymbolKind {
1181 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1182 let text = match self {
1183 SymbolKind::Port(x) => {
1184 format!("port ({} {})", x.direction, x.r#type)
1185 }
1186 SymbolKind::Variable(x) => {
1187 format!("variable ({})", x.r#type)
1188 }
1189 SymbolKind::Module(x) => {
1190 format!(
1191 "module ({} generic, {} params, {} ports)",
1192 x.generic_parameters.len(),
1193 x.parameters.len(),
1194 x.ports.len()
1195 )
1196 }
1197 SymbolKind::ProtoModule(x) => {
1198 format!(
1199 "proto module ({} params, {} ports)",
1200 x.parameters.len(),
1201 x.ports.len()
1202 )
1203 }
1204 SymbolKind::AliasModule(x) => {
1205 format!("alias module (target {})", x.target)
1206 }
1207 SymbolKind::ProtoAliasModule(x) => {
1208 format!("proto alias module (target {})", x.target)
1209 }
1210 SymbolKind::Interface(x) => {
1211 format!(
1212 "interface ({} generic, {} params)",
1213 x.generic_parameters.len(),
1214 x.parameters.len()
1215 )
1216 }
1217 SymbolKind::ProtoInterface(x) => {
1218 format!("proto interface ({} params)", x.parameters.len())
1219 }
1220 SymbolKind::AliasInterface(x) => {
1221 format!("alias interface (target {})", x.target)
1222 }
1223 SymbolKind::ProtoAliasInterface(x) => {
1224 format!("proto alias interface (target {})", x.target)
1225 }
1226 SymbolKind::Function(x) => {
1227 format!(
1228 "function ({} generic, {} args)",
1229 x.generic_parameters.len(),
1230 x.ports.len()
1231 )
1232 }
1233 SymbolKind::ProtoFunction(x) => {
1234 format!(
1235 "proto function ({} generic, {} args)",
1236 x.generic_parameters.len(),
1237 x.ports.len()
1238 )
1239 }
1240 SymbolKind::Parameter(x) => {
1241 if let Some(value) = &x.value {
1242 let mut stringifier = Stringifier::new();
1243 stringifier.expression(value);
1244 format!(
1245 "{} ({}) = {}",
1246 x.kind.to_sv_snippet(),
1247 x.r#type,
1248 stringifier.as_str()
1249 )
1250 } else {
1251 format!("{} ({})", x.kind.to_sv_snippet(), x.r#type)
1252 }
1253 }
1254 SymbolKind::ProtoConst(x) => {
1255 format!("proto localparam ({})", x.r#type)
1256 }
1257 SymbolKind::Instance(x) => {
1258 let type_name = x.type_name.to_string();
1259 format!("instance ({type_name})")
1260 }
1261 SymbolKind::Block => "block".to_string(),
1262 SymbolKind::Package(x) => {
1263 format!("package ({} generic)", x.generic_parameters.len())
1264 }
1265 SymbolKind::ProtoPackage(_) => "proto package".to_string(),
1266 SymbolKind::AliasPackage(x) => {
1267 format!("alias package (target {})", x.target)
1268 }
1269 SymbolKind::ProtoAliasPackage(x) => {
1270 format!("proto alias package (target {})", x.target)
1271 }
1272 SymbolKind::Struct(_) => "struct".to_string(),
1273 SymbolKind::StructMember(x) => {
1274 format!("struct member ({})", x.r#type)
1275 }
1276 SymbolKind::Union(_) => "union".to_string(),
1277 SymbolKind::UnionMember(x) => {
1278 format!("union member ({})", x.r#type)
1279 }
1280 SymbolKind::TypeDef(x) => {
1281 format!("typedef alias ({})", x.r#type)
1282 }
1283 SymbolKind::ProtoTypeDef(x) => {
1284 if let Some(ref r#type) = x.r#type {
1285 format!("proto typedef alias ({type})")
1286 } else {
1287 "proto typedef".to_string()
1288 }
1289 }
1290 SymbolKind::Enum(x) => {
1291 if let Some(ref r#type) = x.r#type {
1292 format!("enum ({type})")
1293 } else {
1294 "enum ()".to_string()
1295 }
1296 }
1297 SymbolKind::EnumMember(x) => {
1298 if let EnumMemberValue::ExplicitValue(ref expression, ref _evaluated) = x.value {
1299 let mut stringifier = Stringifier::new();
1300 stringifier.expression(expression);
1301 format!("enum member = {}", stringifier.as_str())
1302 } else {
1303 "enum member".to_string()
1304 }
1305 }
1306 SymbolKind::EnumMemberMangled => "enum member mangled".to_string(),
1307 SymbolKind::Modport(x) => {
1308 format!("modport ({} ports)", x.members.len())
1309 }
1310 SymbolKind::Genvar => "genvar".to_string(),
1311 SymbolKind::ModportVariableMember(x) => {
1312 format!("modport variable member ({})", x.direction)
1313 }
1314 SymbolKind::ModportFunctionMember(_) => "modport function member".to_string(),
1315 SymbolKind::SystemVerilog => "systemverilog item".to_string(),
1316 SymbolKind::Namespace => "namespace".to_string(),
1317 SymbolKind::SystemFunction(_) => "system function".to_string(),
1318 SymbolKind::GenericParameter(_) => "generic parameter".to_string(),
1319 SymbolKind::GenericConst(_) => "generic const".to_string(),
1320 SymbolKind::GenericInstance(_) => "generic instance".to_string(),
1321 SymbolKind::ClockDomain => "clock domain".to_string(),
1322 SymbolKind::Test(_) => "test".to_string(),
1323 SymbolKind::Embed => "embed".to_string(),
1324 SymbolKind::TbComponent(x) => format!("testbench {} component", x.kind),
1325 };
1326 text.fmt(f)
1327 }
1328}
1329
1330#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
1331pub enum Direction {
1332 Input,
1333 Output,
1334 Inout,
1335 Interface,
1336 Modport,
1337 Import,
1338}
1339
1340impl Direction {
1341 pub fn converse(&self) -> Direction {
1342 match self {
1343 Direction::Input => Direction::Output,
1344 Direction::Output => Direction::Input,
1345 _ => *self,
1346 }
1347 }
1348
1349 pub fn is_input(&self) -> bool {
1350 self == &Direction::Input
1351 }
1352
1353 pub fn is_output(&self) -> bool {
1354 self == &Direction::Output
1355 }
1356}
1357
1358impl fmt::Display for Direction {
1359 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1360 let text = match self {
1361 Direction::Input => "input".to_string(),
1362 Direction::Output => "output".to_string(),
1363 Direction::Inout => "inout".to_string(),
1364 Direction::Interface => "interface".to_string(),
1365 Direction::Modport => "modport".to_string(),
1366 Direction::Import => "import".to_string(),
1367 };
1368 text.fmt(f)
1369 }
1370}
1371
1372impl From<&syntax_tree::Direction> for Direction {
1373 fn from(value: &syntax_tree::Direction) -> Self {
1374 match value {
1375 syntax_tree::Direction::Input(_) => Direction::Input,
1376 syntax_tree::Direction::Output(_) => Direction::Output,
1377 syntax_tree::Direction::Inout(_) => Direction::Inout,
1378 syntax_tree::Direction::Modport(_) => Direction::Modport,
1379 syntax_tree::Direction::Import(_) => Direction::Import,
1380 }
1381 }
1382}
1383
1384#[derive(Debug, Clone)]
1385pub struct Type {
1386 pub modifier: Vec<TypeModifier>,
1387 pub kind: TypeKind,
1388 pub width: Vec<syntax_tree::Expression>,
1389 pub array: Vec<syntax_tree::Expression>,
1390 pub array_type: Option<syntax_tree::ArrayType>,
1391 pub is_const: bool,
1392 pub token: TokenRange,
1393}
1394
1395impl Type {
1396 pub fn create_inferred(token: TokenRange) -> Self {
1397 Self {
1398 modifier: vec![],
1399 kind: TypeKind::Inferred,
1400 width: vec![],
1401 array: vec![],
1402 array_type: None,
1403 is_const: false,
1404 token,
1405 }
1406 }
1407
1408 pub fn is_compatible(&self, other: &Type) -> bool {
1409 self.to_string() == other.to_string()
1410 }
1411
1412 pub fn has_modifier(&self, kind: &TypeModifierKind) -> bool {
1413 self.modifier.iter().any(|x| x.kind == *kind)
1414 }
1415
1416 pub fn find_modifier(&self, kind: &TypeModifierKind) -> Option<TypeModifier> {
1417 self.modifier.iter().find(|x| x.kind == *kind).cloned()
1418 }
1419
1420 pub fn is_signed(&self) -> bool {
1421 if self.kind.is_fixed() {
1422 self.kind.is_signed()
1423 } else {
1424 self.has_modifier(&TypeModifierKind::Signed)
1425 }
1426 }
1427
1428 pub fn is_inferred(&self) -> bool {
1429 matches!(self.kind, TypeKind::Inferred)
1430 }
1431
1432 pub fn can_be_default_clock(&self) -> bool {
1433 self.kind.is_clock() && self.width.is_empty() && self.array.is_empty()
1434 }
1435
1436 pub fn can_be_default_reset(&self) -> bool {
1437 self.kind.is_reset() && self.width.is_empty() && self.array.is_empty()
1438 }
1439
1440 pub fn get_user_defined(&self) -> Option<UserDefinedType> {
1441 if let TypeKind::UserDefined(x) = &self.kind {
1442 return Some(x.clone());
1443 }
1444
1445 None
1446 }
1447
1448 pub fn trace_user_defined(
1449 &self,
1450 namespace: Option<&Namespace>,
1451 ) -> Option<(Type, Option<Symbol>)> {
1452 if let TypeKind::UserDefined(x) = &self.kind {
1453 let symbol = if let Some(namespace) = namespace {
1454 symbol_table::resolve((&x.path.generic_path(), namespace)).ok()?
1455 } else {
1456 let namespace = namespace_table::get(x.path.paths[0].base.id).unwrap();
1457 symbol_table::resolve((&x.path.generic_path(), &namespace)).ok()?
1458 };
1459 match &symbol.found.kind {
1460 SymbolKind::TypeDef(x) => {
1461 return x.r#type.trace_user_defined(Some(&symbol.found.namespace));
1462 }
1463 SymbolKind::ProtoTypeDef(x) => {
1464 if let Some(r#type) = &x.r#type {
1465 return r#type.trace_user_defined(Some(&symbol.found.namespace));
1466 } else {
1467 return Some((self.clone(), Some((*symbol.found).clone())));
1468 }
1469 }
1470 SymbolKind::Module(_)
1471 | SymbolKind::ProtoModule(_)
1472 | SymbolKind::Interface(_)
1473 | SymbolKind::ProtoInterface(_)
1474 | SymbolKind::Package(_)
1475 | SymbolKind::ProtoPackage(_)
1476 | SymbolKind::Enum(_)
1477 | SymbolKind::Struct(_)
1478 | SymbolKind::Union(_)
1479 | SymbolKind::Modport(_) => {
1480 return Some((self.clone(), Some((*symbol.found).clone())));
1481 }
1482 _ => {}
1483 }
1484 }
1485
1486 Some((self.clone(), None))
1487 }
1488
1489 pub fn to_ir_type(&self, context: &mut Context, pos: TypePosition) -> ir::IrResult<ir::Type> {
1490 let mut width = match &self.kind {
1491 TypeKind::U8 => Shape::new(vec![Some(8)]),
1492 TypeKind::U16 => Shape::new(vec![Some(16)]),
1493 TypeKind::U32 => Shape::new(vec![Some(32)]),
1494 TypeKind::U64 => Shape::new(vec![Some(64)]),
1495 TypeKind::P8 => Shape::new(vec![Some(8)]),
1496 TypeKind::P16 => Shape::new(vec![Some(16)]),
1497 TypeKind::P32 => Shape::new(vec![Some(32)]),
1498 TypeKind::P64 => Shape::new(vec![Some(64)]),
1499 TypeKind::I8 => Shape::new(vec![Some(8)]),
1500 TypeKind::I16 => Shape::new(vec![Some(16)]),
1501 TypeKind::I32 => Shape::new(vec![Some(32)]),
1502 TypeKind::I64 => Shape::new(vec![Some(64)]),
1503 TypeKind::F32 => Shape::new(vec![Some(32)]),
1504 TypeKind::F64 => Shape::new(vec![Some(64)]),
1505 TypeKind::Clock
1506 | TypeKind::ClockPosedge
1507 | TypeKind::ClockNegedge
1508 | TypeKind::Reset
1509 | TypeKind::ResetAsyncHigh
1510 | TypeKind::ResetAsyncLow
1511 | TypeKind::ResetSyncHigh
1512 | TypeKind::ResetSyncLow
1513 | TypeKind::Bit
1514 | TypeKind::Logic => {
1515 let mut ret = Shape::default();
1516
1517 if self.width.is_empty() {
1518 ret.push(Some(1));
1519 } else {
1520 let allow_inferable = matches!(&self.kind, TypeKind::Bit | TypeKind::Logic)
1521 && self.width.len() == 1
1522 && pos == TypePosition::Enum;
1523 for w in &self.width {
1524 let (_, value) = eval_size(context, w, allow_inferable)?;
1525 ret.push(value);
1526 }
1527 }
1528
1529 ret
1530 }
1531 TypeKind::UserDefined(_) => {
1532 let mut ret = Shape::default();
1533 for w in &self.width {
1534 let (_, value) = eval_size(context, w, false)?;
1535 ret.push(value);
1536 }
1537
1538 ret
1539 }
1540 TypeKind::BBool
1541 | TypeKind::LBool
1542 | TypeKind::Type
1543 | TypeKind::String
1544 | TypeKind::AbstractInterface(_) => {
1545 Shape::default()
1547 }
1548 TypeKind::Any => Shape::default(),
1549 TypeKind::Inferred => Shape::default(),
1550 };
1551
1552 let mut array = Shape::default();
1553
1554 for w in &self.array {
1555 let (_, value) = eval_size(context, w, false)?;
1556 array.push(value);
1557 }
1558
1559 let mut signed = match &self.kind {
1560 TypeKind::I8 | TypeKind::I16 | TypeKind::I32 | TypeKind::I64 => true,
1561 TypeKind::Bit | TypeKind::Logic => self.is_signed(),
1562 _ => {
1563 if let Some(x) = self.find_modifier(&TypeModifierKind::Signed) {
1564 context.insert_error(crate::AnalyzerError::fixed_type_with_signed_modifier(
1565 &x.token.token.into(),
1566 ));
1567 }
1568 false
1569 }
1570 };
1571
1572 let is_positive = matches!(
1573 &self.kind,
1574 TypeKind::P8 | TypeKind::P16 | TypeKind::P32 | TypeKind::P64
1575 );
1576
1577 let kind = match &self.kind {
1578 TypeKind::Clock => ir::TypeKind::Clock,
1579 TypeKind::ClockPosedge => ir::TypeKind::ClockPosedge,
1580 TypeKind::ClockNegedge => ir::TypeKind::ClockNegedge,
1581 TypeKind::Reset => ir::TypeKind::Reset,
1582 TypeKind::ResetAsyncHigh => ir::TypeKind::ResetAsyncHigh,
1583 TypeKind::ResetAsyncLow => ir::TypeKind::ResetAsyncLow,
1584 TypeKind::ResetSyncHigh => ir::TypeKind::ResetSyncHigh,
1585 TypeKind::ResetSyncLow => ir::TypeKind::ResetSyncLow,
1586 TypeKind::Bit
1587 | TypeKind::BBool
1588 | TypeKind::P8
1589 | TypeKind::P16
1590 | TypeKind::P32
1591 | TypeKind::P64
1592 | TypeKind::U8
1593 | TypeKind::U16
1594 | TypeKind::U32
1595 | TypeKind::U64
1596 | TypeKind::I8
1597 | TypeKind::I16
1598 | TypeKind::I32
1599 | TypeKind::I64 => ir::TypeKind::Bit,
1600 TypeKind::F32 => ir::TypeKind::F32,
1601 TypeKind::F64 => ir::TypeKind::F64,
1602 TypeKind::LBool | TypeKind::Logic => ir::TypeKind::Logic,
1603 TypeKind::Type => ir::TypeKind::Type,
1604 TypeKind::String => ir::TypeKind::String,
1605 TypeKind::UserDefined(x) => {
1606 let mut r#type = eval_type(context, &x.path, pos)?;
1607
1608 width.append(r#type.width_mut());
1609 array.append(&mut r#type.array);
1610 signed = r#type.signed;
1611
1612 r#type.kind
1613 }
1614 TypeKind::AbstractInterface(x) => ir::TypeKind::AbstractInterface(*x),
1615 TypeKind::Any => ir::TypeKind::Unknown,
1616 TypeKind::Inferred => ir::TypeKind::Unknown,
1617 };
1618
1619 let width_expr = build_width_expr(&self.width, &width);
1620 let mut r#type = ir::Type::new(kind);
1621 r#type.signed = signed;
1622 r#type.is_positive = is_positive;
1623 r#type.array = array;
1624 if width_expr.len() == width.as_slice().len() {
1625 r#type.set_parametric_width(width, width_expr);
1626 } else {
1627 r#type.set_concrete_width(width);
1628 }
1629 Ok(r#type)
1630 }
1631}
1632
1633fn build_width_expr(sources: &[syntax_tree::Expression], width: &Shape) -> Vec<ir::WidthExpr> {
1634 let shape_slice = width.as_slice();
1635 if sources.len() != shape_slice.len() {
1636 return ir::WidthExpr::from_shape(width);
1637 }
1638 let mut result = Vec::with_capacity(shape_slice.len());
1639 for (src, slot) in sources.iter().zip(shape_slice.iter()) {
1640 if let Some(expr) = try_syntax_expr_to_param_width(src) {
1641 result.push(expr);
1642 } else if let Some(n) = slot {
1643 result.push(ir::WidthExpr::Concrete(*n));
1644 } else {
1645 return ir::WidthExpr::from_shape(width);
1646 }
1647 }
1648 result
1649}
1650
1651fn try_syntax_expr_to_param_width(expr: &syntax_tree::Expression) -> Option<ir::WidthExpr> {
1652 let if_expr = &*expr.if_expression;
1653 if !if_expr.if_expression_list.is_empty() {
1654 return None;
1655 }
1656 let e01 = &*if_expr.expression01;
1657 if !e01.expression01_list.is_empty() {
1658 return None;
1659 }
1660 let e02 = &*e01.expression02;
1661 if !e02.expression02_list.is_empty() || e02.expression02_opt.is_some() {
1662 return None;
1663 }
1664 let factor = &*e02.factor;
1665 let id_factor = match factor {
1666 syntax_tree::Factor::IdentifierFactor(x) => &x.identifier_factor,
1667 _ => return None,
1668 };
1669 if id_factor.identifier_factor_opt.is_some() {
1670 return None;
1671 }
1672 let scoped = &*id_factor.expression_identifier;
1673 if scoped.expression_identifier_opt.is_some()
1674 || !scoped.expression_identifier_list.is_empty()
1675 || !scoped.expression_identifier_list0.is_empty()
1676 {
1677 return None;
1678 }
1679 let symbol = symbol_table::resolve(scoped.scoped_identifier.as_ref()).ok()?;
1680 if !matches!(symbol.found.kind, SymbolKind::Parameter(_)) {
1681 return None;
1682 }
1683 let parent = symbol.found.get_parent()?;
1684 match parent.kind {
1685 SymbolKind::Module(_) | SymbolKind::Interface(_) | SymbolKind::Package(_) => {
1686 Some(ir::WidthExpr::Param(symbol.found.token.text))
1687 }
1688 _ => None,
1689 }
1690}
1691
1692#[derive(Debug, Clone, PartialEq, Eq)]
1693pub enum TypeKind {
1694 Clock,
1695 ClockPosedge,
1696 ClockNegedge,
1697 Reset,
1698 ResetAsyncHigh,
1699 ResetAsyncLow,
1700 ResetSyncHigh,
1701 ResetSyncLow,
1702 Bit,
1703 Logic,
1704 U8,
1705 U16,
1706 U32,
1707 U64,
1708 I8,
1709 I16,
1710 I32,
1711 I64,
1712 F32,
1713 F64,
1714 Type,
1715 BBool,
1716 LBool,
1717 String,
1718 UserDefined(UserDefinedType),
1719 AbstractInterface(Option<StrId>),
1720 P8,
1721 P16,
1722 P32,
1723 P64,
1724 Any,
1725 Inferred,
1726}
1727
1728impl TypeKind {
1729 pub fn is_clock(&self) -> bool {
1730 matches!(
1731 self,
1732 TypeKind::Clock | TypeKind::ClockPosedge | TypeKind::ClockNegedge
1733 )
1734 }
1735
1736 pub fn is_reset(&self) -> bool {
1737 matches!(
1738 self,
1739 TypeKind::Reset
1740 | TypeKind::ResetAsyncHigh
1741 | TypeKind::ResetAsyncLow
1742 | TypeKind::ResetSyncHigh
1743 | TypeKind::ResetSyncLow
1744 )
1745 }
1746
1747 pub fn is_2state(&self) -> bool {
1748 matches!(
1749 self,
1750 TypeKind::Bit
1751 | TypeKind::BBool
1752 | TypeKind::U8
1753 | TypeKind::U16
1754 | TypeKind::U32
1755 | TypeKind::U64
1756 | TypeKind::I8
1757 | TypeKind::I16
1758 | TypeKind::I32
1759 | TypeKind::I64
1760 | TypeKind::F32
1761 | TypeKind::F64
1762 )
1763 }
1764
1765 pub fn is_4state(&self) -> bool {
1766 self.is_clock() | self.is_reset() | (*self == TypeKind::Logic)
1767 }
1768
1769 pub fn is_fixed(&self) -> bool {
1770 matches!(
1771 self,
1772 TypeKind::U8
1773 | TypeKind::U16
1774 | TypeKind::U32
1775 | TypeKind::U64
1776 | TypeKind::I8
1777 | TypeKind::I16
1778 | TypeKind::I32
1779 | TypeKind::I64
1780 | TypeKind::F32
1781 | TypeKind::F64
1782 | TypeKind::BBool
1783 | TypeKind::LBool
1784 | TypeKind::String
1785 )
1786 }
1787
1788 pub fn is_signed(&self) -> bool {
1789 matches!(
1790 self,
1791 TypeKind::I8
1792 | TypeKind::I16
1793 | TypeKind::I32
1794 | TypeKind::I64
1795 | TypeKind::F32
1796 | TypeKind::F64
1797 )
1798 }
1799
1800 pub fn is_type(&self) -> bool {
1801 matches!(self, TypeKind::Type)
1802 }
1803}
1804
1805#[derive(Debug, Clone, PartialEq, Eq)]
1806pub struct UserDefinedType {
1807 pub path: GenericSymbolPath,
1808 pub symbol: Option<SymbolId>,
1811}
1812
1813impl From<&syntax_tree::ScopedIdentifier> for UserDefinedType {
1814 fn from(value: &syntax_tree::ScopedIdentifier) -> Self {
1815 let path: GenericSymbolPath = value.into();
1816 Self { path, symbol: None }
1817 }
1818}
1819
1820#[derive(Debug, Clone, PartialEq, Eq)]
1821pub enum TypeModifierKind {
1822 Tri,
1823 Signed,
1824 Default,
1825}
1826
1827#[derive(Debug, Clone)]
1828pub struct TypeModifier {
1829 pub kind: TypeModifierKind,
1830 pub token: VerylToken,
1831}
1832
1833impl From<&syntax_tree::TypeModifier> for TypeModifier {
1834 fn from(value: &syntax_tree::TypeModifier) -> Self {
1835 let (kind, token) = match value {
1836 syntax_tree::TypeModifier::Tri(x) => (TypeModifierKind::Tri, &x.tri.tri_token),
1837 syntax_tree::TypeModifier::Signed(x) => {
1838 (TypeModifierKind::Signed, &x.signed.signed_token)
1839 }
1840 syntax_tree::TypeModifier::Defaul(x) => {
1841 (TypeModifierKind::Default, &x.defaul.default_token)
1842 }
1843 };
1844 TypeModifier {
1845 kind,
1846 token: token.clone(),
1847 }
1848 }
1849}
1850
1851impl fmt::Display for TypeModifier {
1852 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1853 match self.kind {
1854 TypeModifierKind::Tri => "tri".to_string().fmt(f),
1855 TypeModifierKind::Signed => "signed".to_string().fmt(f),
1856 TypeModifierKind::Default => "default".to_string().fmt(f),
1857 }
1858 }
1859}
1860
1861impl fmt::Display for Type {
1862 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1863 let mut text = String::new();
1864 for x in &self.modifier {
1865 text.push_str(&x.to_string());
1866 }
1867 match &self.kind {
1868 TypeKind::Clock => text.push_str("clock"),
1869 TypeKind::ClockPosedge => text.push_str("clock posedge"),
1870 TypeKind::ClockNegedge => text.push_str("clock negedge"),
1871 TypeKind::Reset => text.push_str("reset"),
1872 TypeKind::ResetAsyncHigh => text.push_str("reset async high"),
1873 TypeKind::ResetAsyncLow => text.push_str("reset async low"),
1874 TypeKind::ResetSyncHigh => text.push_str("reset sync high"),
1875 TypeKind::ResetSyncLow => text.push_str("reset sync low"),
1876 TypeKind::Bit => text.push_str("bit"),
1877 TypeKind::Logic => text.push_str("logic"),
1878 TypeKind::P8 => text.push_str("p8"),
1879 TypeKind::P16 => text.push_str("p16"),
1880 TypeKind::P32 => text.push_str("p32"),
1881 TypeKind::P64 => text.push_str("p64"),
1882 TypeKind::U8 => text.push_str("u8"),
1883 TypeKind::U16 => text.push_str("u16"),
1884 TypeKind::U32 => text.push_str("u32"),
1885 TypeKind::U64 => text.push_str("u64"),
1886 TypeKind::I8 => text.push_str("i8"),
1887 TypeKind::I16 => text.push_str("i16"),
1888 TypeKind::I32 => text.push_str("i32"),
1889 TypeKind::I64 => text.push_str("i64"),
1890 TypeKind::F32 => text.push_str("f32"),
1891 TypeKind::F64 => text.push_str("f64"),
1892 TypeKind::Type => text.push_str("type"),
1893 TypeKind::BBool => text.push_str("bbool"),
1894 TypeKind::LBool => text.push_str("lbool"),
1895 TypeKind::String => text.push_str("string"),
1896 TypeKind::UserDefined(x) => {
1897 text.push_str(&x.path.to_string());
1898 }
1899 TypeKind::AbstractInterface(x) => {
1900 if let Some(x) = x {
1901 text.push_str(&format!("interface::{x}"));
1902 } else {
1903 text.push_str("interface");
1904 }
1905 }
1906 TypeKind::Any => text.push_str("any"),
1907 TypeKind::Inferred => text.push('_'),
1908 }
1909 if !self.width.is_empty() {
1910 text.push('<');
1911 for (i, x) in self.width.iter().enumerate() {
1912 if i != 0 {
1913 text.push_str(", ");
1914 }
1915 let mut stringifier = Stringifier::new();
1916 stringifier.expression(x);
1917 text.push_str(stringifier.as_str());
1918 }
1919 text.push('>');
1920 }
1921 if !self.array.is_empty() {
1922 text.push_str(" [");
1923 for (i, x) in self.array.iter().enumerate() {
1924 if i != 0 {
1925 text.push_str(", ");
1926 }
1927 let mut stringifier = Stringifier::new();
1928 stringifier.expression(x);
1929 text.push_str(stringifier.as_str());
1930 }
1931 text.push(']');
1932 }
1933 text.fmt(f)
1934 }
1935}
1936
1937impl TryFrom<&syntax_tree::Expression> for Type {
1938 type Error = ();
1939
1940 fn try_from(value: &syntax_tree::Expression) -> Result<Self, Self::Error> {
1941 let value = value.if_expression.as_ref();
1942 let value = if value.if_expression_list.is_empty() {
1943 value.expression01.as_ref()
1944 } else {
1945 return Err(());
1946 };
1947 let value = if value.expression01_list.is_empty() {
1948 value.expression02.as_ref()
1949 } else {
1950 return Err(());
1951 };
1952 let value = if !value.expression02_list.is_empty() || value.expression02_opt.is_some() {
1953 return Err(());
1954 } else {
1955 value.factor.as_ref()
1956 };
1957
1958 match value {
1959 syntax_tree::Factor::FactorTypeFactor(x) => {
1960 let factor = &x.factor_type_factor;
1961
1962 let mut modifier = Vec::new();
1963 for x in &factor.factor_type_factor_list {
1964 modifier.push(TypeModifier::from(&*x.type_modifier));
1965 }
1966 let mut factor_type: Type = factor.factor_type.as_ref().into();
1967 factor_type.modifier = modifier;
1968 Ok(factor_type)
1969 }
1970 syntax_tree::Factor::IdentifierFactor(x) => {
1971 let factor = &x.identifier_factor;
1972
1973 if factor.identifier_factor_opt.is_some() {
1974 Err(())
1975 } else {
1976 let x = factor.expression_identifier.as_ref();
1977 if !x.expression_identifier_list.is_empty() {
1978 return Err(());
1979 }
1980 if !x.expression_identifier_list0.is_empty() {
1981 return Err(());
1982 }
1983
1984 let r#type: UserDefinedType = x.scoped_identifier.as_ref().into();
1985 let kind = TypeKind::UserDefined(r#type);
1986 let width: Vec<_> = if let Some(ref x) = x.expression_identifier_opt {
1987 let width: Vec<_> = x.width.as_ref().into();
1988 width.iter().map(|x| (*x).clone()).collect()
1989 } else {
1990 Vec::new()
1991 };
1992 Ok(Type {
1993 kind,
1994 modifier: vec![],
1995 width,
1996 array: vec![],
1997 array_type: None,
1998 is_const: false,
1999 token: factor.as_ref().into(),
2000 })
2001 }
2002 }
2003 _ => Err(()),
2004 }
2005 }
2006}
2007
2008impl From<&syntax_tree::FixedType> for Type {
2009 fn from(value: &syntax_tree::FixedType) -> Self {
2010 let kind = match value {
2011 syntax_tree::FixedType::P8(_) => TypeKind::P8,
2012 syntax_tree::FixedType::P16(_) => TypeKind::P16,
2013 syntax_tree::FixedType::P32(_) => TypeKind::P32,
2014 syntax_tree::FixedType::P64(_) => TypeKind::P64,
2015 syntax_tree::FixedType::U8(_) => TypeKind::U8,
2016 syntax_tree::FixedType::U16(_) => TypeKind::U16,
2017 syntax_tree::FixedType::U32(_) => TypeKind::U32,
2018 syntax_tree::FixedType::U64(_) => TypeKind::U64,
2019 syntax_tree::FixedType::I8(_) => TypeKind::I8,
2020 syntax_tree::FixedType::I16(_) => TypeKind::I16,
2021 syntax_tree::FixedType::I32(_) => TypeKind::I32,
2022 syntax_tree::FixedType::I64(_) => TypeKind::I64,
2023 syntax_tree::FixedType::F32(_) => TypeKind::F32,
2024 syntax_tree::FixedType::F64(_) => TypeKind::F64,
2025 syntax_tree::FixedType::BBool(_) => TypeKind::BBool,
2026 syntax_tree::FixedType::LBool(_) => TypeKind::LBool,
2027 syntax_tree::FixedType::Strin(_) => TypeKind::String,
2028 };
2029 Type {
2030 kind,
2031 modifier: vec![],
2032 width: vec![],
2033 array: vec![],
2034 array_type: None,
2035 is_const: false,
2036 token: value.into(),
2037 }
2038 }
2039}
2040
2041impl From<&syntax_tree::FactorType> for Type {
2042 fn from(value: &syntax_tree::FactorType) -> Self {
2043 match value.factor_type_group.as_ref() {
2044 syntax_tree::FactorTypeGroup::VariableTypeFactorTypeOpt(x) => {
2045 let kind = match x.variable_type.as_ref() {
2046 syntax_tree::VariableType::Clock(_) => TypeKind::Clock,
2047 syntax_tree::VariableType::ClockPosedge(_) => TypeKind::ClockPosedge,
2048 syntax_tree::VariableType::ClockNegedge(_) => TypeKind::ClockNegedge,
2049 syntax_tree::VariableType::Reset(_) => TypeKind::Reset,
2050 syntax_tree::VariableType::ResetAsyncHigh(_) => TypeKind::ResetAsyncHigh,
2051 syntax_tree::VariableType::ResetAsyncLow(_) => TypeKind::ResetAsyncLow,
2052 syntax_tree::VariableType::ResetSyncHigh(_) => TypeKind::ResetSyncHigh,
2053 syntax_tree::VariableType::ResetSyncLow(_) => TypeKind::ResetSyncLow,
2054 syntax_tree::VariableType::Logic(_) => TypeKind::Logic,
2055 syntax_tree::VariableType::Bit(_) => TypeKind::Bit,
2056 };
2057 let width: Vec<_> = if let Some(ref x) = x.factor_type_opt {
2058 let width: Vec<_> = x.width.as_ref().into();
2059 width.iter().map(|x| (*x).clone()).collect()
2060 } else {
2061 Vec::new()
2062 };
2063 Type {
2064 kind,
2065 modifier: vec![],
2066 width,
2067 array: vec![],
2068 array_type: None,
2069 is_const: false,
2070 token: value.into(),
2071 }
2072 }
2073 syntax_tree::FactorTypeGroup::FixedType(x) => {
2074 let kind = match x.fixed_type.as_ref() {
2075 syntax_tree::FixedType::P8(_) => TypeKind::P8,
2076 syntax_tree::FixedType::P16(_) => TypeKind::P16,
2077 syntax_tree::FixedType::P32(_) => TypeKind::P32,
2078 syntax_tree::FixedType::P64(_) => TypeKind::P64,
2079 syntax_tree::FixedType::U8(_) => TypeKind::U8,
2080 syntax_tree::FixedType::U16(_) => TypeKind::U16,
2081 syntax_tree::FixedType::U32(_) => TypeKind::U32,
2082 syntax_tree::FixedType::U64(_) => TypeKind::U64,
2083 syntax_tree::FixedType::I8(_) => TypeKind::I8,
2084 syntax_tree::FixedType::I16(_) => TypeKind::I16,
2085 syntax_tree::FixedType::I32(_) => TypeKind::I32,
2086 syntax_tree::FixedType::I64(_) => TypeKind::I64,
2087 syntax_tree::FixedType::F32(_) => TypeKind::F32,
2088 syntax_tree::FixedType::F64(_) => TypeKind::F64,
2089 syntax_tree::FixedType::BBool(_) => TypeKind::BBool,
2090 syntax_tree::FixedType::LBool(_) => TypeKind::LBool,
2091 syntax_tree::FixedType::Strin(_) => TypeKind::String,
2092 };
2093 Type {
2094 kind,
2095 modifier: vec![],
2096 width: vec![],
2097 array: vec![],
2098 array_type: None,
2099 is_const: false,
2100 token: value.into(),
2101 }
2102 }
2103 }
2104 }
2105}
2106
2107impl From<&syntax_tree::ScalarType> for Type {
2108 fn from(value: &syntax_tree::ScalarType) -> Self {
2109 let mut modifier = Vec::new();
2110 for x in &value.scalar_type_list {
2111 modifier.push(TypeModifier::from(&*x.type_modifier));
2112 }
2113
2114 let array_type = ArrayType {
2115 scalar_type: Box::new(value.clone()),
2116 array_type_opt: None,
2117 };
2118
2119 match &*value.scalar_type_group {
2120 syntax_tree::ScalarTypeGroup::UserDefinedTypeScalarTypeOpt(x) => {
2121 let r#type: UserDefinedType = x.user_defined_type.scoped_identifier.as_ref().into();
2122 let kind = TypeKind::UserDefined(r#type);
2123 let width: Vec<_> = if let Some(ref x) = x.scalar_type_opt {
2124 let width: Vec<_> = x.width.as_ref().into();
2125 width.iter().map(|x| (*x).clone()).collect()
2126 } else {
2127 Vec::new()
2128 };
2129 Type {
2130 kind,
2131 modifier,
2132 width,
2133 array: vec![],
2134 array_type: Some(array_type),
2135 is_const: false,
2136 token: value.into(),
2137 }
2138 }
2139 syntax_tree::ScalarTypeGroup::FactorType(x) => {
2140 let factor_type: Type = x.factor_type.as_ref().into();
2141 Type {
2142 kind: factor_type.kind,
2143 modifier,
2144 width: factor_type.width,
2145 array: vec![],
2146 array_type: Some(array_type),
2147 is_const: false,
2148 token: value.into(),
2149 }
2150 }
2151 }
2152 }
2153}
2154
2155impl From<&syntax_tree::ArrayType> for Type {
2156 fn from(value: &syntax_tree::ArrayType) -> Self {
2157 let scalar_type: Type = value.scalar_type.as_ref().into();
2158 let mut array_type = scalar_type.array_type.unwrap();
2159 let array: Vec<_> = if let Some(ref x) = value.array_type_opt {
2160 array_type.array_type_opt.replace(x.clone());
2161 let x: Vec<_> = x.array.as_ref().into();
2162 x.iter().map(|x| (*x).clone()).collect()
2163 } else {
2164 Vec::new()
2165 };
2166 Type {
2167 kind: scalar_type.kind,
2168 modifier: scalar_type.modifier,
2169 width: scalar_type.width,
2170 array,
2171 array_type: Some(array_type),
2172 is_const: false,
2173 token: value.into(),
2174 }
2175 }
2176}
2177
2178impl From<&syntax_tree::ScopedIdentifier> for Type {
2179 fn from(value: &syntax_tree::ScopedIdentifier) -> Self {
2180 let r#type: UserDefinedType = value.into();
2181 let kind = TypeKind::UserDefined(r#type);
2182 Type {
2183 kind,
2184 modifier: vec![],
2185 width: vec![],
2186 array: vec![],
2187 array_type: None,
2188 is_const: false,
2189 token: value.into(),
2190 }
2191 }
2192}
2193
2194impl From<&syntax_tree::GenericProtoBound> for Type {
2195 fn from(value: &syntax_tree::GenericProtoBound) -> Self {
2196 match value {
2197 syntax_tree::GenericProtoBound::ScopedIdentifier(x) => {
2198 x.scoped_identifier.as_ref().into()
2199 }
2200 syntax_tree::GenericProtoBound::FixedType(x) => x.fixed_type.as_ref().into(),
2201 }
2202 }
2203}
2204
2205#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
2206pub enum ClockDomain {
2207 Explicit(SymbolId),
2208 Inferred(SymbolId),
2209 Implicit,
2210 #[default]
2211 None,
2212}
2213
2214impl ClockDomain {
2215 pub fn domain_id(&self) -> Option<SymbolId> {
2216 match self {
2217 ClockDomain::Explicit(id) | ClockDomain::Inferred(id) => Some(*id),
2218 _ => None,
2219 }
2220 }
2221
2222 pub fn compatible(&self, x: &ClockDomain) -> bool {
2223 match (self, x) {
2224 (ClockDomain::None, _) | (_, ClockDomain::None) => true,
2225 (a, b) => match (a.domain_id(), b.domain_id()) {
2226 (Some(a), Some(b)) => a == b,
2227 (None, None) => true,
2228 _ => false,
2229 },
2230 }
2231 }
2232}
2233
2234impl fmt::Display for ClockDomain {
2235 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2236 let text = match self {
2237 ClockDomain::Explicit(x) | ClockDomain::Inferred(x) => {
2238 format!("'{}", symbol_table::get(*x).unwrap().token)
2239 }
2240 ClockDomain::Implicit => "'_".to_string(),
2241 ClockDomain::None => "".to_string(),
2242 };
2243 text.fmt(f)
2244 }
2245}
2246
2247#[derive(Debug, Clone)]
2248pub struct VariableProperty {
2249 pub r#type: Type,
2250 pub affiliation: Affiliation,
2251 pub prefix: Option<String>,
2252 pub suffix: Option<String>,
2253 pub clock_domain: ClockDomain,
2254 pub loop_variable: bool,
2255}
2256
2257#[derive(Debug, Clone, Copy, PartialEq, Eq)]
2258pub enum Affiliation {
2259 ProjectNamespace,
2260 Module,
2261 Interface,
2262 Package,
2263 StatementBlock,
2264 Function,
2265 Modport,
2266 ProtoModule,
2267 ProtoInterface,
2268 ProtoPackage,
2269 AlwaysComb,
2270 AlwaysFf,
2271}
2272
2273#[derive(Debug, Clone)]
2274pub struct PortProperty {
2275 pub token: Token,
2276 pub r#type: Type,
2277 pub direction: Direction,
2278 pub prefix: Option<String>,
2279 pub suffix: Option<String>,
2280 pub clock_domain: ClockDomain,
2281 pub default_value: Option<syntax_tree::Expression>,
2282 pub is_proto: bool,
2283}
2284
2285#[derive(Debug, Clone)]
2286pub struct Port {
2287 pub token: VerylToken,
2288 pub symbol: SymbolId,
2289}
2290
2291impl fmt::Display for Port {
2292 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2293 let text = format!("{} [{}]", self.name(), self.property().direction);
2294 text.fmt(f)
2295 }
2296}
2297
2298impl Port {
2299 pub fn property(&self) -> PortProperty {
2300 if let SymbolKind::Port(x) = self.symbol().kind {
2301 x.clone()
2302 } else {
2303 unreachable!()
2304 }
2305 }
2306
2307 pub fn symbol(&self) -> Symbol {
2308 symbol_table::get(self.symbol).unwrap()
2309 }
2310
2311 pub fn name(&self) -> StrId {
2312 self.token.token.text
2313 }
2314}
2315
2316#[derive(Debug, Clone, Eq, PartialEq)]
2317pub enum ParameterKind {
2318 Param,
2319 Const,
2320}
2321
2322impl ParameterKind {
2323 pub fn is_const(&self) -> bool {
2324 matches!(self, ParameterKind::Const)
2325 }
2326
2327 pub fn to_sv_snippet(&self) -> String {
2328 if self.is_const() {
2329 "localparam".to_string()
2330 } else {
2331 "parameter".to_string()
2332 }
2333 }
2334}
2335
2336impl From<&ParameterKind> for ir::VarKind {
2337 fn from(value: &ParameterKind) -> Self {
2338 match value {
2339 ParameterKind::Param => ir::VarKind::Param,
2340 ParameterKind::Const => ir::VarKind::Const,
2341 }
2342 }
2343}
2344
2345#[derive(Debug, Clone)]
2346pub struct ParameterProperty {
2347 pub token: Token,
2348 pub r#type: Type,
2349 pub kind: ParameterKind,
2350 pub value: Option<syntax_tree::Expression>,
2351}
2352
2353#[derive(Debug, Clone)]
2354pub struct ProtoConstProperty {
2355 pub token: Token,
2356 pub r#type: Type,
2357}
2358
2359#[derive(Debug, Clone)]
2360pub struct Parameter {
2361 pub name: StrId,
2362 pub symbol: SymbolId,
2363}
2364
2365impl fmt::Display for Parameter {
2366 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2367 let text = format!("{} [{}]", self.name, self.property().r#type);
2368 text.fmt(f)
2369 }
2370}
2371
2372impl Parameter {
2373 pub fn property(&self) -> ParameterProperty {
2374 if let SymbolKind::Parameter(x) = symbol_table::get(self.symbol).unwrap().kind {
2375 x.clone()
2376 } else {
2377 unreachable!()
2378 }
2379 }
2380}
2381
2382#[derive(Debug, Clone)]
2383pub struct ModuleProperty {
2384 pub range: TokenRange,
2385 pub proto: Option<GenericSymbolPath>,
2386 pub generic_parameters: Vec<SymbolId>,
2387 pub generic_consts: Vec<SymbolId>,
2388 pub generic_references: Vec<GenericSymbolPath>,
2389 pub parameters: Vec<Parameter>,
2390 pub ports: Vec<Port>,
2391 pub default_clock: Option<SymbolId>,
2392 pub default_reset: Option<SymbolId>,
2393 pub definition: DefinitionId,
2394 pub test: Option<TestProperty>,
2395}
2396
2397#[derive(Debug, Clone)]
2398pub struct ProtoModuleProperty {
2399 pub range: TokenRange,
2400 pub parameters: Vec<Parameter>,
2401 pub ports: Vec<Port>,
2402 pub definition: DefinitionId,
2403}
2404
2405#[derive(Debug, Clone)]
2406pub struct AliasModuleProperty {
2407 pub target: GenericSymbolPath,
2408}
2409
2410#[derive(Debug, Clone)]
2411pub struct InterfaceProperty {
2412 pub range: TokenRange,
2413 pub proto: Option<GenericSymbolPath>,
2414 pub generic_parameters: Vec<SymbolId>,
2415 pub generic_consts: Vec<SymbolId>,
2416 pub generic_references: Vec<GenericSymbolPath>,
2417 pub parameters: Vec<Parameter>,
2418 pub members: Vec<SymbolId>,
2419 pub definition: DefinitionId,
2420}
2421
2422#[derive(Debug, Clone)]
2423pub struct ProtoInterfaceProperty {
2424 pub range: TokenRange,
2425 pub parameters: Vec<Parameter>,
2426 pub members: Vec<SymbolId>,
2427}
2428
2429#[derive(Debug, Clone)]
2430pub struct AliasInterfaceProperty {
2431 pub target: GenericSymbolPath,
2432}
2433
2434#[derive(Debug, Clone)]
2435pub struct FunctionProperty {
2436 pub affiliation: Affiliation,
2437 pub range: TokenRange,
2438 pub generic_parameters: Vec<SymbolId>,
2439 pub generic_consts: Vec<SymbolId>,
2440 pub generic_references: Vec<GenericSymbolPath>,
2441 pub ports: Vec<Port>,
2442 pub ret: Option<Type>,
2443 pub reference_paths: Vec<GenericSymbolPath>,
2444 pub constantable: Option<bool>,
2445 pub definition: Option<DefinitionId>,
2446}
2447
2448impl FunctionProperty {
2449 pub fn is_global(&self) -> bool {
2450 self.affiliation == Affiliation::ProjectNamespace
2451 }
2452}
2453
2454#[derive(Debug, Clone)]
2455pub struct SystemFuncitonProperty {
2456 pub ports: Vec<Port>,
2457}
2458
2459#[derive(Debug, Clone)]
2460pub struct ConnectTarget {
2461 pub identifiers: Vec<ConnectTargetIdentifier>,
2462 pub expression: syntax_tree::Expression,
2463}
2464
2465#[derive(Debug, Clone)]
2466pub struct ConnectTargetIdentifier {
2467 pub path: Vec<(StrId, Vec<syntax_tree::Expression>)>,
2468}
2469
2470impl ConnectTargetIdentifier {
2471 pub fn path(&self) -> Vec<StrId> {
2472 self.path.iter().map(|x| x.0).collect()
2473 }
2474
2475 pub fn is_empty(&self) -> bool {
2476 self.path.is_empty()
2477 }
2478
2479 pub fn is_partial(&self) -> bool {
2480 self.path.iter().any(|x| !x.1.is_empty())
2481 }
2482}
2483
2484impl From<&syntax_tree::ExpressionIdentifier> for ConnectTargetIdentifier {
2485 fn from(value: &syntax_tree::ExpressionIdentifier) -> Self {
2486 let path: SymbolPath = value.scoped_identifier.as_ref().into();
2487
2488 let mut ret = vec![];
2489 for (i, x) in path.as_slice().iter().enumerate() {
2490 if i == path.as_slice().len() - 1 {
2491 let select: Vec<_> = value
2492 .expression_identifier_list
2493 .iter()
2494 .map(|x| x.select.expression.as_ref().clone())
2495 .collect();
2496 ret.push((*x, select));
2497 } else {
2498 ret.push((*x, vec![]));
2499 }
2500 }
2501
2502 for x in &value.expression_identifier_list0 {
2503 let text = x.identifier.identifier_token.token.text;
2504 let select: Vec<_> = x
2505 .expression_identifier_list0_list
2506 .iter()
2507 .map(|x| x.select.expression.as_ref().clone())
2508 .collect();
2509 ret.push((text, select));
2510 }
2511 Self { path: ret }
2512 }
2513}
2514
2515#[derive(Debug, Clone)]
2516pub struct InstanceProperty {
2517 pub array: Vec<syntax_tree::Expression>,
2518 pub type_name: GenericSymbolPath,
2519 pub parameter_connects: HashMap<Token, ConnectTarget>,
2520 pub port_connects: HashMap<Token, ConnectTarget>,
2521 pub clock_domain: ClockDomain,
2522}
2523
2524#[derive(Debug, Clone)]
2525pub struct PackageProperty {
2526 pub range: TokenRange,
2527 pub proto: Option<GenericSymbolPath>,
2528 pub generic_parameters: Vec<SymbolId>,
2529 pub generic_consts: Vec<SymbolId>,
2530 pub generic_references: Vec<GenericSymbolPath>,
2531 pub members: Vec<SymbolId>,
2532}
2533
2534#[derive(Debug, Clone)]
2535pub struct AliasPackageProperty {
2536 pub target: GenericSymbolPath,
2537}
2538
2539#[derive(Debug, Clone)]
2540pub struct ProtoPackageProperty {
2541 pub range: TokenRange,
2542 pub members: Vec<SymbolId>,
2543}
2544
2545#[derive(Debug, Clone)]
2546pub struct StructProperty {
2547 pub members: Vec<SymbolId>,
2548 pub generic_parameters: Vec<SymbolId>,
2549 pub generic_references: Vec<GenericSymbolPath>,
2550}
2551
2552#[derive(Debug, Clone)]
2553pub struct StructMemberProperty {
2554 pub r#type: Type,
2555}
2556
2557#[derive(Debug, Clone)]
2558pub struct UnionProperty {
2559 pub members: Vec<SymbolId>,
2560 pub generic_parameters: Vec<SymbolId>,
2561 pub generic_references: Vec<GenericSymbolPath>,
2562}
2563
2564#[derive(Debug, Clone)]
2565pub struct UnionMemberProperty {
2566 pub r#type: Type,
2567}
2568
2569#[derive(Debug, Clone)]
2570pub struct TypeDefProperty {
2571 pub r#type: Type,
2572}
2573
2574#[derive(Debug, Clone)]
2575pub struct ProtoTypeDefProperty {
2576 pub r#type: Option<Type>,
2577}
2578
2579#[derive(Debug, Clone)]
2580pub struct EnumProperty {
2581 pub r#type: Option<Type>,
2582 pub width: usize,
2583 pub members: Vec<SymbolId>,
2584 pub encoding: EnumEncodingItem,
2585}
2586
2587#[derive(Debug, Clone)]
2588pub enum EnumMemberValue {
2589 ImplicitValue(usize),
2590 ExplicitValue(syntax_tree::Expression, Option<usize>),
2591 UnevaluableValue,
2592}
2593
2594impl EnumMemberValue {
2595 pub fn value(&self) -> Option<usize> {
2596 match self {
2597 EnumMemberValue::ImplicitValue(value) => Some(*value),
2598 EnumMemberValue::ExplicitValue(_expression, evaluated) => *evaluated,
2599 EnumMemberValue::UnevaluableValue => None,
2600 }
2601 }
2602}
2603
2604#[derive(Debug, Clone)]
2605pub struct EnumMemberProperty {
2606 pub value: EnumMemberValue,
2607 pub prefix: String,
2608}
2609
2610#[derive(Debug, Clone)]
2611pub struct ModportProperty {
2612 pub interface: SymbolId,
2613 pub members: Vec<SymbolId>,
2614 pub default: Option<ModportDefault>,
2615}
2616
2617#[derive(Debug, Clone)]
2618pub enum ModportDefault {
2619 Input,
2620 Output,
2621 Same(Vec<Token>),
2622 Converse(Vec<Token>),
2623}
2624
2625#[derive(Debug, Clone)]
2626pub struct ModportVariableMemberProperty {
2627 pub direction: Direction,
2628 pub variable: SymbolId,
2629}
2630
2631#[derive(Debug, Clone)]
2632pub struct ModportFunctionMemberProperty {
2633 pub function: SymbolId,
2634}
2635
2636#[derive(Debug, Clone)]
2637pub enum GenericBoundKind {
2638 Type,
2639 Inst(GenericSymbolPath),
2640 Proto(Box<Type>),
2641}
2642
2643#[derive(Debug, Clone)]
2644pub enum ProtoBound {
2645 ProtoModule(Symbol),
2646 ProtoInterface(Symbol),
2647 ProtoPackage(Symbol),
2648 FactorType(Type),
2649 Enum((Symbol, Type)),
2650 Struct((Symbol, Type)),
2651 Union((Symbol, Type)),
2652}
2653
2654impl ProtoBound {
2655 pub fn get_symbol(&self) -> Option<Symbol> {
2656 match self {
2657 ProtoBound::ProtoModule(x)
2658 | ProtoBound::ProtoInterface(x)
2659 | ProtoBound::ProtoPackage(x)
2660 | ProtoBound::Enum((x, _))
2661 | ProtoBound::Struct((x, _))
2662 | ProtoBound::Union((x, _)) => Some(x.clone()),
2663 _ => None,
2664 }
2665 }
2666
2667 pub fn is_variable_type(&self) -> bool {
2668 matches!(
2669 self,
2670 ProtoBound::FactorType(_)
2671 | ProtoBound::Enum(_)
2672 | ProtoBound::Struct(_)
2673 | ProtoBound::Union(_)
2674 )
2675 }
2676}
2677
2678impl GenericBoundKind {
2679 pub fn is_compatible(&self, other: &GenericBoundKind) -> bool {
2680 self.to_string() == other.to_string()
2681 }
2682
2683 pub fn resolve_inst_bound(&self, namespace: &Namespace) -> Result<Symbol, Option<SymbolId>> {
2684 let GenericBoundKind::Inst(path) = self else {
2685 return Err(None);
2686 };
2687
2688 if let Ok(symbol) = symbol_table::resolve((&path.mangled_path(), namespace)) {
2689 if symbol.found.is_proto_interface(false, true) {
2690 Ok((*symbol.found).clone())
2691 } else {
2692 Err(Some(symbol.found.id))
2693 }
2694 } else {
2695 Err(None)
2696 }
2697 }
2698
2699 pub fn resolve_proto_bound(
2700 &self,
2701 namespace: &Namespace,
2702 ) -> Result<ProtoBound, Option<SymbolId>> {
2703 let GenericBoundKind::Proto(proto) = self else {
2704 return Err(None);
2705 };
2706
2707 let Some((r#type, symbol)) = proto.trace_user_defined(Some(namespace)) else {
2708 return Err(None);
2709 };
2710 if symbol.is_none() {
2711 return Ok(ProtoBound::FactorType(r#type));
2712 }
2713
2714 let symbol = symbol.unwrap();
2715 match &symbol.kind {
2716 SymbolKind::ProtoModule(_) => Ok(ProtoBound::ProtoModule(symbol)),
2717 SymbolKind::ProtoInterface(_) => Ok(ProtoBound::ProtoInterface(symbol)),
2718 SymbolKind::ProtoPackage(_) => Ok(ProtoBound::ProtoPackage(symbol)),
2719 SymbolKind::Enum(_) => Ok(ProtoBound::Enum((symbol, r#type))),
2720 SymbolKind::Struct(_) => Ok(ProtoBound::Struct((symbol, r#type))),
2721 SymbolKind::Union(_) => Ok(ProtoBound::Union((symbol, r#type))),
2722 _ => Err(Some(symbol.id)),
2723 }
2724 }
2725}
2726
2727impl fmt::Display for GenericBoundKind {
2728 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2729 let text = match self {
2730 GenericBoundKind::Type => "type".to_string(),
2731 GenericBoundKind::Inst(x) => x.to_string(),
2732 GenericBoundKind::Proto(x) => x.to_string(),
2733 };
2734 text.fmt(f)
2735 }
2736}
2737
2738#[derive(Debug, Clone)]
2739pub struct GenericParameterProperty {
2740 pub bound: GenericBoundKind,
2741 pub default_value: Option<GenericSymbolPath>,
2742}
2743
2744#[derive(Debug, Clone)]
2745pub struct GenericConstProperty {
2746 pub bound: GenericBoundKind,
2747 pub value: syntax_tree::Expression,
2748}
2749
2750#[derive(Debug, Clone)]
2751pub struct GenericInstanceProperty {
2752 pub base: SymbolId,
2753 pub arguments: Vec<GenericSymbolPath>,
2754 pub affiliation_symbol: Option<SymbolId>,
2755}
2756
2757impl GenericInstanceProperty {
2758 pub fn base_symbol(&self) -> Symbol {
2759 symbol_table::get(self.base).unwrap()
2760 }
2761}
2762
2763#[derive(Debug, Clone)]
2764pub enum TestType {
2765 Inline,
2766 CocotbEmbed(Box<syntax_tree::EmbedContent>),
2767 CocotbInclude(StrId),
2768 Native,
2769}
2770
2771#[derive(Debug, Clone)]
2772pub struct TestProperty {
2773 pub r#type: TestType,
2774 pub path: PathId,
2775 pub top: Option<StrId>,
2776 pub ignored: bool,
2777}
2778
2779#[derive(Debug, Clone)]
2780pub enum TbComponentKind {
2781 ClockGen,
2782 ResetGen,
2783}
2784
2785impl std::fmt::Display for TbComponentKind {
2786 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2787 match self {
2788 TbComponentKind::ClockGen => write!(f, "clock_gen"),
2789 TbComponentKind::ResetGen => write!(f, "reset_gen"),
2790 }
2791 }
2792}
2793
2794#[derive(Debug, Clone)]
2795pub struct TbComponentProperty {
2796 pub kind: TbComponentKind,
2797}