diff --git a/crates/analyzer/src/analyzer.rs b/crates/analyzer/src/analyzer.rs index 6a3c43d2..952e390f 100644 --- a/crates/analyzer/src/analyzer.rs +++ b/crates/analyzer/src/analyzer.rs @@ -1,13 +1,14 @@ use crate::analyzer_error::AnalyzerError; use crate::handlers::*; use crate::namespace_table; -use crate::symbol::SymbolKind; -use crate::symbol_table; +use crate::symbol::{ + Direction, ParameterValue, SymbolId, SymbolKind, TypeKind, VariableAffiniation, +}; +use crate::symbol_table::{self, AssignPath, ResolveSymbol}; use std::path::Path; use veryl_metadata::{Lint, Metadata}; use veryl_parser::resource_table; use veryl_parser::veryl_grammar_trait::*; -use veryl_parser::veryl_token::VerylToken; use veryl_parser::veryl_walker::{Handler, VerylWalker}; pub struct AnalyzerPass1<'a> { @@ -128,19 +129,15 @@ impl Analyzer { if symbol.token.source == path { if let SymbolKind::Variable(_) = symbol.kind { if symbol.references.is_empty() && !symbol.allow_unused { - let name = format!("{}", symbol.token.text); + let name = symbol.token.to_string(); if name.starts_with('_') { continue; } - let token = VerylToken { - token: symbol.token, - comments: Vec::new(), - }; ret.push(AnalyzerError::unused_variable( - &format!("{}", symbol.token.text), + &symbol.token.to_string(), text, - &token, + &symbol.token, )); } } @@ -148,8 +145,191 @@ impl Analyzer { } // check assignment - let _assign_list = symbol_table::get_assign_list(); + let assign_list = symbol_table::get_assign_list(); + let mut assignable_list = Vec::new(); + for symbol in &symbols { + if symbol.token.source == path { + assignable_list.append(&mut traverse_assignable_symbol( + symbol.id, + &AssignPath::new(symbol.id), + )); + } + } + let mut assignable_list: Vec<_> = assignable_list.iter().map(|x| (x, vec![])).collect(); + for assign in &assign_list { + for assignable in &mut assignable_list { + if assignable.0.included(&assign.path) { + assignable.1.push(assign.position.clone()); + } + } + } + + for (path, position) in &assignable_list { + if position.is_empty() { + let symbol = symbol_table::get(*path.0.first().unwrap()).unwrap(); + ret.push(AnalyzerError::unassign_variable( + &symbol.token.to_string(), + text, + &symbol.token, + )); + } + } ret } } + +fn is_assignable(direction: &Direction) -> bool { + matches!( + direction, + Direction::Ref | Direction::Inout | Direction::Output | Direction::Modport + ) +} + +fn traverse_type_symbol(id: SymbolId, path: &AssignPath) -> Vec { + if let Some(symbol) = symbol_table::get(id) { + match &symbol.kind { + SymbolKind::Variable(x) => { + if let TypeKind::UserDefined(ref x) = x.r#type.kind { + if let Ok(symbol) = symbol_table::resolve((x, &symbol.namespace)) { + if let ResolveSymbol::Symbol(symbol) = symbol.found { + return traverse_type_symbol(symbol.id, path); + } + } + } else { + return vec![path.clone()]; + } + } + SymbolKind::StructMember(x) => { + if let TypeKind::UserDefined(ref x) = x.r#type.kind { + if let Ok(symbol) = symbol_table::resolve((x, &symbol.namespace)) { + if let ResolveSymbol::Symbol(symbol) = symbol.found { + return traverse_type_symbol(symbol.id, path); + } + } + } else { + return vec![path.clone()]; + } + } + SymbolKind::UnionMember(x) => { + if let TypeKind::UserDefined(ref x) = x.r#type.kind { + if let Ok(symbol) = symbol_table::resolve((x, &symbol.namespace)) { + if let ResolveSymbol::Symbol(symbol) = symbol.found { + return traverse_type_symbol(symbol.id, path); + } + } + } else { + return vec![path.clone()]; + } + } + SymbolKind::TypeDef(x) => { + if let TypeKind::UserDefined(ref x) = x.r#type.kind { + if let Ok(symbol) = symbol_table::resolve((x, &symbol.namespace)) { + if let ResolveSymbol::Symbol(symbol) = symbol.found { + return traverse_type_symbol(symbol.id, path); + } + } + } else { + return vec![path.clone()]; + } + } + SymbolKind::Parameter(x) if x.r#type.kind == TypeKind::Type => { + if let ParameterValue::TypeExpression(TypeExpression::ScalarType(ref x)) = x.value { + let r#type: crate::symbol::Type = (&*x.scalar_type).into(); + if let TypeKind::UserDefined(ref x) = r#type.kind { + if let Ok(symbol) = symbol_table::resolve((x, &symbol.namespace)) { + if let ResolveSymbol::Symbol(symbol) = symbol.found { + return traverse_type_symbol(symbol.id, path); + } + } + } else { + return vec![path.clone()]; + } + } + } + SymbolKind::Struct(x) => { + let mut ret = Vec::new(); + for member in &x.members { + let mut path = path.clone(); + path.push(*member); + ret.append(&mut traverse_type_symbol(*member, &path)); + } + return ret; + } + // TODO union support + //SymbolKind::Union(x) => { + // let mut ret = Vec::new(); + // for member in &x.members { + // let mut path = path.clone(); + // path.push(*member); + // ret.append(&mut traverse_type_symbol(*member, &path)); + // } + // return ret; + //} + SymbolKind::Modport(x) => { + let mut ret = Vec::new(); + for member in &x.members { + let mut path = path.clone(); + path.push(*member); + ret.append(&mut traverse_type_symbol(*member, &path)); + } + return ret; + } + SymbolKind::ModportMember(x) if is_assignable(&x.direction) => { + if let Ok(symbol) = symbol_table::resolve(&symbol.token) { + if let ResolveSymbol::Symbol(symbol) = symbol.found { + return traverse_type_symbol(symbol.id, path); + } + } + } + SymbolKind::Enum(_) => { + return vec![path.clone()]; + } + _ => (), + } + } + + vec![] +} + +fn traverse_assignable_symbol(id: SymbolId, path: &AssignPath) -> Vec { + // check cyclic dependency + if path.0.iter().filter(|x| **x == id).count() > 1 { + return vec![]; + } + + if let Some(symbol) = symbol_table::get(id) { + match &symbol.kind { + SymbolKind::Port(x) if is_assignable(&x.direction) => { + if let Some(ref x) = x.r#type { + if let TypeKind::UserDefined(ref x) = x.kind { + if let Ok(symbol) = symbol_table::resolve((x, &symbol.namespace)) { + if let ResolveSymbol::Symbol(symbol) = symbol.found { + return traverse_type_symbol(symbol.id, path); + } + } + } else { + return vec![path.clone()]; + } + } + } + SymbolKind::Variable(x) + if x.affiniation == VariableAffiniation::Module + || x.affiniation == VariableAffiniation::Function => + { + if let TypeKind::UserDefined(ref x) = x.r#type.kind { + if let Ok(symbol) = symbol_table::resolve((x, &symbol.namespace)) { + if let ResolveSymbol::Symbol(symbol) = symbol.found { + return traverse_type_symbol(symbol.id, path); + } + } + } else { + return vec![path.clone()]; + } + } + _ => (), + } + } + + vec![] +} diff --git a/crates/analyzer/src/analyzer_error.rs b/crates/analyzer/src/analyzer_error.rs index d6738156..f5a19f7b 100644 --- a/crates/analyzer/src/analyzer_error.rs +++ b/crates/analyzer/src/analyzer_error.rs @@ -1,6 +1,6 @@ use miette::{self, Diagnostic, NamedSource, SourceSpan}; use thiserror::Error; -use veryl_parser::veryl_token::VerylToken; +use veryl_parser::veryl_token::Token; #[derive(Error, Diagnostic, Debug)] pub enum AnalyzerError { @@ -475,127 +475,124 @@ pub enum AnalyzerError { #[label("Error location")] error_location: SourceSpan, }, + + #[diagnostic( + severity(Warning), + code(unassign_variable), + help(""), + url( + "https://doc.veryl-lang.org/book/06_appendix/02_semantic_error.html#unassign_variable" + ) + )] + #[error("{identifier} is unassigned")] + UnassignVariable { + identifier: String, + #[source_code] + input: NamedSource, + #[label("Error location")] + error_location: SourceSpan, + }, } impl AnalyzerError { - fn named_source(source: &str, token: &VerylToken) -> NamedSource { - NamedSource::new(token.token.source.to_string(), source.to_string()) + fn named_source(source: &str, token: &Token) -> NamedSource { + NamedSource::new(token.source.to_string(), source.to_string()) } - pub fn cyclic_type_dependency( - source: &str, - start: &str, - end: &str, - token: &VerylToken, - ) -> Self { + pub fn cyclic_type_dependency(source: &str, start: &str, end: &str, token: &Token) -> Self { AnalyzerError::CyclicTypeDependency { start: start.into(), end: end.into(), input: AnalyzerError::named_source(source, token), - error_location: token.token.into(), + error_location: token.into(), } } - pub fn duplicated_identifier(identifier: &str, source: &str, token: &VerylToken) -> Self { + pub fn duplicated_identifier(identifier: &str, source: &str, token: &Token) -> Self { AnalyzerError::DuplicatedIdentifier { identifier: identifier.to_string(), input: AnalyzerError::named_source(source, token), - error_location: token.token.into(), + error_location: token.into(), } } - pub fn duplicated_assignment(identifier: &str, source: &str, token: &VerylToken) -> Self { + pub fn duplicated_assignment(identifier: &str, source: &str, token: &Token) -> Self { AnalyzerError::DuplicatedAssignment { identifier: identifier.to_string(), input: AnalyzerError::named_source(source, token), - error_location: token.token.into(), + error_location: token.into(), } } - pub fn invalid_allow(identifier: &str, source: &str, token: &VerylToken) -> Self { + pub fn invalid_allow(identifier: &str, source: &str, token: &Token) -> Self { AnalyzerError::InvalidAllow { identifier: identifier.to_string(), input: AnalyzerError::named_source(source, token), - error_location: token.token.into(), + error_location: token.into(), } } - pub fn invalid_assignment( - identifier: &str, - source: &str, - kind: &str, - token: &VerylToken, - ) -> Self { + pub fn invalid_assignment(identifier: &str, source: &str, kind: &str, token: &Token) -> Self { AnalyzerError::InvalidAssignment { identifier: identifier.into(), kind: kind.into(), input: AnalyzerError::named_source(source, token), - error_location: token.token.into(), + error_location: token.into(), } } - pub fn invalid_direction(kind: &str, source: &str, token: &VerylToken) -> Self { + pub fn invalid_direction(kind: &str, source: &str, token: &Token) -> Self { AnalyzerError::InvalidDirection { kind: kind.to_string(), input: AnalyzerError::named_source(source, token), - error_location: token.token.into(), + error_location: token.into(), } } - pub fn invalid_identifier( - identifier: &str, - rule: &str, - source: &str, - token: &VerylToken, - ) -> Self { + pub fn invalid_identifier(identifier: &str, rule: &str, source: &str, token: &Token) -> Self { AnalyzerError::InvalidIdentifier { identifier: identifier.to_string(), rule: rule.to_string(), input: AnalyzerError::named_source(source, token), - error_location: token.token.into(), + error_location: token.into(), } } - pub fn invalid_import(source: &str, token: &VerylToken) -> Self { + pub fn invalid_import(source: &str, token: &Token) -> Self { AnalyzerError::InvalidImport { input: AnalyzerError::named_source(source, token), - error_location: token.token.into(), + error_location: token.into(), } } - pub fn invalid_lsb(source: &str, token: &VerylToken) -> Self { + pub fn invalid_lsb(source: &str, token: &Token) -> Self { AnalyzerError::InvalidLsb { input: AnalyzerError::named_source(source, token), - error_location: token.token.into(), + error_location: token.into(), } } - pub fn invalid_msb(source: &str, token: &VerylToken) -> Self { + pub fn invalid_msb(source: &str, token: &Token) -> Self { AnalyzerError::InvalidMsb { input: AnalyzerError::named_source(source, token), - error_location: token.token.into(), + error_location: token.into(), } } - pub fn invalid_number_character( - cause: char, - kind: &str, - source: &str, - token: &VerylToken, - ) -> Self { + pub fn invalid_number_character(cause: char, kind: &str, source: &str, token: &Token) -> Self { AnalyzerError::InvalidNumberCharacter { cause, kind: kind.to_string(), input: AnalyzerError::named_source(source, token), - error_location: token.token.into(), + error_location: token.into(), } } - pub fn invalid_statement(kind: &str, source: &str, token: &VerylToken) -> Self { + pub fn invalid_statement(kind: &str, source: &str, token: &Token) -> Self { AnalyzerError::InvalidStatement { kind: kind.to_string(), input: AnalyzerError::named_source(source, token), - error_location: token.token.into(), + error_location: token.into(), } } @@ -604,14 +601,14 @@ impl AnalyzerError { arity: usize, args: usize, source: &str, - token: &VerylToken, + token: &Token, ) -> Self { AnalyzerError::MismatchArity { name: name.to_string(), arity, args, input: AnalyzerError::named_source(source, token), - error_location: token.token.into(), + error_location: token.into(), } } @@ -620,36 +617,36 @@ impl AnalyzerError { expected: &str, actual: &str, source: &str, - token: &VerylToken, + token: &Token, ) -> Self { AnalyzerError::MismatchType { name: name.to_string(), expected: expected.to_string(), actual: actual.to_string(), input: AnalyzerError::named_source(source, token), - error_location: token.token.into(), + error_location: token.into(), } } - pub fn missing_if_reset(source: &str, token: &VerylToken) -> Self { + pub fn missing_if_reset(source: &str, token: &Token) -> Self { AnalyzerError::MissingIfReset { input: AnalyzerError::named_source(source, token), - error_location: token.token.into(), + error_location: token.into(), } } - pub fn missing_reset_signal(source: &str, token: &VerylToken) -> Self { + pub fn missing_reset_signal(source: &str, token: &Token) -> Self { AnalyzerError::MissingResetSignal { input: AnalyzerError::named_source(source, token), - error_location: token.token.into(), + error_location: token.into(), } } - pub fn missing_reset_statement(name: &str, source: &str, token: &VerylToken) -> Self { + pub fn missing_reset_statement(name: &str, source: &str, token: &Token) -> Self { AnalyzerError::MissingResetStatement { name: name.to_string(), input: AnalyzerError::named_source(source, token), - error_location: token.token.into(), + error_location: token.into(), } } @@ -657,22 +654,22 @@ impl AnalyzerError { name: &str, expected: &str, source: &str, - token: &VerylToken, + token: &Token, ) -> Self { AnalyzerError::MismatchAttributeArgs { name: name.to_string(), expected: expected.to_string(), input: AnalyzerError::named_source(source, token), - error_location: token.token.into(), + error_location: token.into(), } } - pub fn missing_port(name: &str, port: &str, source: &str, token: &VerylToken) -> Self { + pub fn missing_port(name: &str, port: &str, source: &str, token: &Token) -> Self { AnalyzerError::MissingPort { name: name.to_string(), port: port.to_string(), input: AnalyzerError::named_source(source, token), - error_location: token.token.into(), + error_location: token.into(), } } @@ -681,22 +678,22 @@ impl AnalyzerError { value: isize, width: usize, source: &str, - token: &VerylToken, + token: &Token, ) -> Self { AnalyzerError::TooLargeEnumVariant { identifier: identifier.to_string(), value, width, input: AnalyzerError::named_source(source, token), - error_location: token.token.into(), + error_location: token.into(), } } - pub fn too_large_number(width: usize, source: &str, token: &VerylToken) -> Self { + pub fn too_large_number(width: usize, source: &str, token: &Token) -> Self { AnalyzerError::TooLargeNumber { width, input: AnalyzerError::named_source(source, token), - error_location: token.token.into(), + error_location: token.into(), } } @@ -705,79 +702,87 @@ impl AnalyzerError { number: usize, width: usize, source: &str, - token: &VerylToken, + token: &Token, ) -> Self { AnalyzerError::TooMuchEnumVariant { identifier: identifier.to_string(), number, width, input: AnalyzerError::named_source(source, token), - error_location: token.token.into(), + error_location: token.into(), } } - pub fn undefined_identifier(identifier: &str, source: &str, token: &VerylToken) -> Self { + pub fn undefined_identifier(identifier: &str, source: &str, token: &Token) -> Self { AnalyzerError::UndefinedIdentifier { identifier: identifier.to_string(), input: AnalyzerError::named_source(source, token), - error_location: token.token.into(), + error_location: token.into(), } } - pub fn unknown_attribute(name: &str, source: &str, token: &VerylToken) -> Self { + pub fn unknown_attribute(name: &str, source: &str, token: &Token) -> Self { AnalyzerError::UnknownAttribute { name: name.to_string(), input: AnalyzerError::named_source(source, token), - error_location: token.token.into(), + error_location: token.into(), } } - pub fn unknown_member(name: &str, member: &str, source: &str, token: &VerylToken) -> Self { + pub fn unknown_member(name: &str, member: &str, source: &str, token: &Token) -> Self { AnalyzerError::UnknownMember { name: name.to_string(), member: member.to_string(), input: AnalyzerError::named_source(source, token), - error_location: token.token.into(), + error_location: token.into(), } } - pub fn private_member(name: &str, source: &str, token: &VerylToken) -> Self { + pub fn private_member(name: &str, source: &str, token: &Token) -> Self { AnalyzerError::PrivateMember { name: name.to_string(), input: AnalyzerError::named_source(source, token), - error_location: token.token.into(), + error_location: token.into(), } } - pub fn unknown_msb(source: &str, token: &VerylToken) -> Self { + pub fn unknown_msb(source: &str, token: &Token) -> Self { AnalyzerError::UnknownMsb { input: AnalyzerError::named_source(source, token), - error_location: token.token.into(), + error_location: token.into(), } } - pub fn unknown_port(name: &str, port: &str, source: &str, token: &VerylToken) -> Self { + pub fn unknown_port(name: &str, port: &str, source: &str, token: &Token) -> Self { AnalyzerError::UnknownPort { name: name.to_string(), port: port.to_string(), input: AnalyzerError::named_source(source, token), - error_location: token.token.into(), + error_location: token.into(), } } - pub fn unused_variable(identifier: &str, source: &str, token: &VerylToken) -> Self { + pub fn unused_variable(identifier: &str, source: &str, token: &Token) -> Self { AnalyzerError::UnusedVariable { identifier: identifier.to_string(), input: AnalyzerError::named_source(source, token), - error_location: token.token.into(), + error_location: token.into(), } } - pub fn unused_return(identifier: &str, source: &str, token: &VerylToken) -> Self { + pub fn unused_return(identifier: &str, source: &str, token: &Token) -> Self { AnalyzerError::UnusedReturn { identifier: identifier.to_string(), input: AnalyzerError::named_source(source, token), - error_location: token.token.into(), + error_location: token.into(), + } + } + + pub fn unassign_variable(identifier: &str, source: &str, token: &Token) -> Self { + AnalyzerError::UnassignVariable { + identifier: identifier.to_string(), + input: AnalyzerError::named_source(source, token), + error_location: token.into(), } } } diff --git a/crates/analyzer/src/handlers/check_assignment.rs b/crates/analyzer/src/handlers/check_assignment.rs index dd8b679e..d4dc2d3e 100644 --- a/crates/analyzer/src/handlers/check_assignment.rs +++ b/crates/analyzer/src/handlers/check_assignment.rs @@ -1,9 +1,8 @@ use crate::analyzer_error::AnalyzerError; -use crate::symbol::Direction as SymDirection; -use crate::symbol::{Symbol, SymbolKind}; -use crate::symbol_table::{self, ResolveSymbol}; +use crate::symbol::{Direction, SymbolId, SymbolKind}; +use crate::symbol_table::{self, AssignPosition, AssignPositionType, ResolveSymbol}; +use std::collections::HashMap; use veryl_parser::veryl_grammar_trait::*; -use veryl_parser::veryl_token::VerylToken; use veryl_parser::veryl_walker::{Handler, HandlerPoint}; use veryl_parser::ParolError; @@ -11,7 +10,7 @@ pub struct CheckAssignment<'a> { pub errors: Vec, text: &'a str, point: HandlerPoint, - current_position: Vec, + assign_position: AssignPosition, in_if_expression: bool, } @@ -21,7 +20,7 @@ impl<'a> CheckAssignment<'a> { errors: Vec::new(), text, point: HandlerPoint::Before, - current_position: Vec::new(), + assign_position: AssignPosition::default(), in_if_expression: false, } } @@ -33,18 +32,42 @@ impl<'a> Handler for CheckAssignment<'a> { } } -fn can_assign(arg: &Symbol) -> bool { - match &arg.kind { - SymbolKind::Variable(_) => true, - SymbolKind::StructMember(_) => true, - SymbolKind::UnionMember(_) => true, - SymbolKind::Port(x) if x.direction == SymDirection::Output => true, - SymbolKind::Port(x) if x.direction == SymDirection::Ref => true, - SymbolKind::Port(x) if x.direction == SymDirection::Inout => true, - SymbolKind::ModportMember(x) if x.direction == SymDirection::Output => true, - SymbolKind::ModportMember(x) if x.direction == SymDirection::Ref => true, - SymbolKind::ModportMember(x) if x.direction == SymDirection::Inout => true, - _ => false, +fn can_assign(full_path: &[SymbolId]) -> bool { + if full_path.is_empty() { + return false; + } + + let leaf_symbol = full_path.last().unwrap(); + if let Some(leaf_symbol) = symbol_table::get(*leaf_symbol) { + match leaf_symbol.kind { + SymbolKind::Variable(_) => true, + SymbolKind::StructMember(_) | SymbolKind::UnionMember(_) => { + let root_symbol = full_path.first().unwrap(); + if let Some(root_symbol) = symbol_table::get(*root_symbol) { + match root_symbol.kind { + SymbolKind::Variable(_) => true, + SymbolKind::Port(x) if x.direction == Direction::Output => true, + SymbolKind::Port(x) if x.direction == Direction::Ref => true, + SymbolKind::Port(x) if x.direction == Direction::Inout => true, + SymbolKind::ModportMember(x) if x.direction == Direction::Output => true, + SymbolKind::ModportMember(x) if x.direction == Direction::Ref => true, + SymbolKind::ModportMember(x) if x.direction == Direction::Inout => true, + _ => false, + } + } else { + false + } + } + SymbolKind::Port(x) if x.direction == Direction::Output => true, + SymbolKind::Port(x) if x.direction == Direction::Ref => true, + SymbolKind::Port(x) if x.direction == Direction::Inout => true, + SymbolKind::ModportMember(x) if x.direction == Direction::Output => true, + SymbolKind::ModportMember(x) if x.direction == Direction::Ref => true, + SymbolKind::ModportMember(x) if x.direction == Direction::Inout => true, + _ => false, + } + } else { + false } } @@ -52,7 +75,14 @@ impl<'a> VerylGrammarTrait for CheckAssignment<'a> { fn r#else(&mut self, arg: &Else) -> Result<(), ParolError> { if let HandlerPoint::Before = self.point { if !self.in_if_expression { - *self.current_position.last_mut().unwrap() = arg.else_token.clone(); + let new_position = if let AssignPositionType::StatementBlock(_) = + self.assign_position.0.last().unwrap() + { + AssignPositionType::StatementBlock(arg.else_token.token) + } else { + AssignPositionType::DeclarationBlock(arg.else_token.token) + }; + *self.assign_position.0.last_mut().unwrap() = new_position; } } Ok(()) @@ -73,8 +103,8 @@ impl<'a> VerylGrammarTrait for CheckAssignment<'a> { fn let_statement(&mut self, arg: &LetStatement) -> Result<(), ParolError> { if let HandlerPoint::Before = self.point { if let Ok(x) = symbol_table::resolve(arg.identifier.as_ref()) { - let mut position = self.current_position.clone(); - position.push(arg.r#let.let_token.clone()); + let mut position = self.assign_position.clone(); + position.push(AssignPositionType::Statement(arg.r#let.let_token.token)); symbol_table::add_assign(x.full_path, position); } } @@ -88,14 +118,15 @@ impl<'a> VerylGrammarTrait for CheckAssignment<'a> { let full_path = x.full_path; match x.found { ResolveSymbol::Symbol(x) => { - if can_assign(&x) { - symbol_table::add_assign(full_path, self.current_position.clone()); + if can_assign(&full_path) { + symbol_table::add_assign(full_path, self.assign_position.clone()); } else { - let token = &arg.expression_identifier.identifier.identifier_token; + let token = + &arg.expression_identifier.identifier.identifier_token.token; self.errors.push(AnalyzerError::invalid_assignment( &x.kind.to_kind_name(), self.text, - &token.text(), + &token.to_string(), token, )); } @@ -112,10 +143,11 @@ impl<'a> VerylGrammarTrait for CheckAssignment<'a> { fn if_statement(&mut self, arg: &IfStatement) -> Result<(), ParolError> { match self.point { HandlerPoint::Before => { - self.current_position.push(arg.r#if.if_token.clone()); + self.assign_position + .push(AssignPositionType::StatementBlock(arg.r#if.if_token.token)); } HandlerPoint::After => { - self.current_position.pop(); + self.assign_position.pop(); } } Ok(()) @@ -124,11 +156,24 @@ impl<'a> VerylGrammarTrait for CheckAssignment<'a> { fn if_reset_statement(&mut self, arg: &IfResetStatement) -> Result<(), ParolError> { match self.point { HandlerPoint::Before => { - self.current_position - .push(arg.if_reset.if_reset_token.clone()); + self.assign_position + .push(AssignPositionType::StatementBlock( + arg.if_reset.if_reset_token.token, + )); } HandlerPoint::After => { - self.current_position.pop(); + self.assign_position.pop(); + } + } + Ok(()) + } + + fn for_statement(&mut self, arg: &ForStatement) -> Result<(), ParolError> { + if let HandlerPoint::Before = self.point { + if let Ok(x) = symbol_table::resolve(arg.identifier.as_ref()) { + let mut position = self.assign_position.clone(); + position.push(AssignPositionType::Statement(arg.r#for.for_token.token)); + symbol_table::add_assign(x.full_path, position); } } Ok(()) @@ -137,10 +182,13 @@ impl<'a> VerylGrammarTrait for CheckAssignment<'a> { fn case_item(&mut self, arg: &CaseItem) -> Result<(), ParolError> { match self.point { HandlerPoint::Before => { - self.current_position.push(arg.colon.colon_token.clone()); + self.assign_position + .push(AssignPositionType::StatementBlock( + arg.colon.colon_token.token, + )); } HandlerPoint::After => { - self.current_position.pop(); + self.assign_position.pop(); } } Ok(()) @@ -149,8 +197,8 @@ impl<'a> VerylGrammarTrait for CheckAssignment<'a> { fn let_declaration(&mut self, arg: &LetDeclaration) -> Result<(), ParolError> { if let HandlerPoint::Before = self.point { if let Ok(x) = symbol_table::resolve(arg.identifier.as_ref()) { - let mut position = self.current_position.clone(); - position.push(arg.r#let.let_token.clone()); + let mut position = self.assign_position.clone(); + position.push(AssignPositionType::Declaration(arg.r#let.let_token.token)); symbol_table::add_assign(x.full_path, position); } } @@ -160,11 +208,12 @@ impl<'a> VerylGrammarTrait for CheckAssignment<'a> { fn always_ff_declaration(&mut self, arg: &AlwaysFfDeclaration) -> Result<(), ParolError> { match self.point { HandlerPoint::Before => { - self.current_position - .push(arg.always_ff.always_ff_token.clone()); + self.assign_position.push(AssignPositionType::Declaration( + arg.always_ff.always_ff_token.token, + )); } HandlerPoint::After => { - self.current_position.pop(); + self.assign_position.pop(); } } Ok(()) @@ -173,11 +222,12 @@ impl<'a> VerylGrammarTrait for CheckAssignment<'a> { fn always_comb_declaration(&mut self, arg: &AlwaysCombDeclaration) -> Result<(), ParolError> { match self.point { HandlerPoint::Before => { - self.current_position - .push(arg.always_comb.always_comb_token.clone()); + self.assign_position.push(AssignPositionType::Declaration( + arg.always_comb.always_comb_token.token, + )); } HandlerPoint::After => { - self.current_position.pop(); + self.assign_position.pop(); } } Ok(()) @@ -189,16 +239,22 @@ impl<'a> VerylGrammarTrait for CheckAssignment<'a> { let full_path = x.full_path; match x.found { ResolveSymbol::Symbol(x) => { - if can_assign(&x) { - let mut position = self.current_position.clone(); - position.push(arg.assign.assign_token.clone()); + if can_assign(&full_path) { + let mut position = self.assign_position.clone(); + position.push(AssignPositionType::Declaration( + arg.assign.assign_token.token, + )); symbol_table::add_assign(full_path, position); } else { - let token = &arg.hierarchical_identifier.identifier.identifier_token; + let token = &arg + .hierarchical_identifier + .identifier + .identifier_token + .token; self.errors.push(AnalyzerError::invalid_assignment( &x.kind.to_kind_name(), self.text, - &token.text(), + &token.to_string(), token, )); } @@ -211,14 +267,68 @@ impl<'a> VerylGrammarTrait for CheckAssignment<'a> { Ok(()) } + fn inst_declaration(&mut self, arg: &InstDeclaration) -> Result<(), ParolError> { + if let HandlerPoint::Before = self.point { + if let Ok(x) = symbol_table::resolve(arg.identifier.as_ref()) { + if let ResolveSymbol::Symbol(ref symbol) = x.found { + if let SymbolKind::Instance(ref x) = symbol.kind { + // get port direction + let mut dirs = HashMap::new(); + let mut dir_unknown = false; + if let Ok(x) = symbol_table::resolve((&x.type_name, &symbol.namespace)) { + if let ResolveSymbol::Symbol(ref symbol) = x.found { + match symbol.kind { + SymbolKind::Module(ref x) => { + for port in &x.ports { + dirs.insert(port.name, port.property.direction); + } + } + SymbolKind::SystemVerilog => dir_unknown = true, + _ => (), + } + } + } + + for (name, target) in &x.connects { + if !target.is_empty() { + let dir_output = if let Some(dir) = dirs.get(name) { + matches!( + dir, + Direction::Ref | Direction::Inout | Direction::Output + ) + } else { + false + }; + + if dir_output | dir_unknown { + if let Ok(x) = + symbol_table::resolve((target, &symbol.namespace)) + { + let mut position = self.assign_position.clone(); + position.push(AssignPositionType::Declaration( + arg.inst.inst_token.token, + )); + symbol_table::add_assign(x.full_path, position); + } + } + } + } + } + } + } + } + Ok(()) + } + fn function_declaration(&mut self, arg: &FunctionDeclaration) -> Result<(), ParolError> { match self.point { HandlerPoint::Before => { - self.current_position - .push(arg.function.function_token.clone()); + self.assign_position.push(AssignPositionType::Declaration( + arg.function.function_token.token, + )); } HandlerPoint::After => { - self.current_position.pop(); + self.assign_position.pop(); } } Ok(()) @@ -227,10 +337,24 @@ impl<'a> VerylGrammarTrait for CheckAssignment<'a> { fn module_if_declaration(&mut self, arg: &ModuleIfDeclaration) -> Result<(), ParolError> { match self.point { HandlerPoint::Before => { - self.current_position.push(arg.r#if.if_token.clone()); + self.assign_position + .push(AssignPositionType::DeclarationBlock( + arg.r#if.if_token.token, + )); } HandlerPoint::After => { - self.current_position.pop(); + self.assign_position.pop(); + } + } + Ok(()) + } + + fn module_for_declaration(&mut self, arg: &ModuleForDeclaration) -> Result<(), ParolError> { + if let HandlerPoint::Before = self.point { + if let Ok(x) = symbol_table::resolve(arg.identifier.as_ref()) { + let mut position = self.assign_position.clone(); + position.push(AssignPositionType::Statement(arg.r#for.for_token.token)); + symbol_table::add_assign(x.full_path, position); } } Ok(()) diff --git a/crates/analyzer/src/handlers/check_attribute.rs b/crates/analyzer/src/handlers/check_attribute.rs index bb81c5cb..0ea65658 100644 --- a/crates/analyzer/src/handlers/check_attribute.rs +++ b/crates/analyzer/src/handlers/check_attribute.rs @@ -55,7 +55,7 @@ impl<'a> VerylGrammarTrait for CheckAttribute<'a> { &identifier, "single identifier", self.text, - &arg.identifier.identifier_token, + &arg.identifier.identifier_token.token, )); } } @@ -76,7 +76,7 @@ impl<'a> VerylGrammarTrait for CheckAttribute<'a> { &identifier, "single string", self.text, - &arg.identifier.identifier_token, + &arg.identifier.identifier_token.token, )); } } @@ -91,7 +91,7 @@ impl<'a> VerylGrammarTrait for CheckAttribute<'a> { self.errors.push(AnalyzerError::invalid_allow( &text, self.text, - &arg.identifier.identifier_token, + &arg.identifier.identifier_token.token, )); } allow_table::push(x.identifier.identifier_token.token.text); @@ -108,7 +108,7 @@ impl<'a> VerylGrammarTrait for CheckAttribute<'a> { &identifier, "error identifier", self.text, - &arg.identifier.identifier_token, + &arg.identifier.identifier_token.token, )); } } @@ -116,7 +116,7 @@ impl<'a> VerylGrammarTrait for CheckAttribute<'a> { self.errors.push(AnalyzerError::unknown_attribute( &identifier, self.text, - &arg.identifier.identifier_token, + &arg.identifier.identifier_token.token, )); } } diff --git a/crates/analyzer/src/handlers/check_direction.rs b/crates/analyzer/src/handlers/check_direction.rs index c39b5d9f..8a2a8f0d 100644 --- a/crates/analyzer/src/handlers/check_direction.rs +++ b/crates/analyzer/src/handlers/check_direction.rs @@ -36,7 +36,7 @@ impl<'a> VerylGrammarTrait for CheckDirection<'a> { self.errors.push(AnalyzerError::invalid_direction( "ref", self.text, - &x.r#ref.ref_token, + &x.r#ref.ref_token.token, )); } } @@ -45,7 +45,7 @@ impl<'a> VerylGrammarTrait for CheckDirection<'a> { self.errors.push(AnalyzerError::invalid_direction( "modport", self.text, - &x.modport.modport_token, + &x.modport.modport_token.token, )); } } diff --git a/crates/analyzer/src/handlers/check_enum.rs b/crates/analyzer/src/handlers/check_enum.rs index f49aecc2..6eb1ee78 100644 --- a/crates/analyzer/src/handlers/check_enum.rs +++ b/crates/analyzer/src/handlers/check_enum.rs @@ -1,7 +1,7 @@ use crate::analyzer_error::AnalyzerError; use crate::evaluator::{Evaluated, Evaluator}; use veryl_parser::veryl_grammar_trait::*; -use veryl_parser::veryl_token::VerylToken; +use veryl_parser::veryl_token::Token; use veryl_parser::veryl_walker::{Handler, HandlerPoint}; use veryl_parser::ParolError; @@ -10,7 +10,7 @@ pub struct CheckEnum<'a> { text: &'a str, point: HandlerPoint, enum_variants: usize, - enum_member_values: Vec<(Evaluated, VerylToken)>, + enum_member_values: Vec<(Evaluated, Token)>, } impl<'a> CheckEnum<'a> { @@ -51,7 +51,7 @@ impl<'a> VerylGrammarTrait for CheckEnum<'a> { self.enum_variants, width, self.text, - &arg.identifier.identifier_token, + &arg.identifier.identifier_token.token, )); } @@ -59,7 +59,7 @@ impl<'a> VerylGrammarTrait for CheckEnum<'a> { if let Evaluated::Fixed { value, .. } = enum_value { if *value as usize >= max_members { self.errors.push(AnalyzerError::too_large_enum_variant( - &token.text(), + &token.to_string(), *value, width, self.text, @@ -78,7 +78,7 @@ impl<'a> VerylGrammarTrait for CheckEnum<'a> { if let HandlerPoint::Before = self.point { self.enum_variants += 1; if let Some(ref x) = arg.enum_item_opt { - let token = arg.identifier.identifier_token.clone(); + let token = arg.identifier.identifier_token.token; let mut evaluator = Evaluator::new(); let evaluated = evaluator.expression(&x.expression); self.enum_member_values.push((evaluated, token)); diff --git a/crates/analyzer/src/handlers/check_function.rs b/crates/analyzer/src/handlers/check_function.rs index 98ad94c9..62f45ab6 100644 --- a/crates/analyzer/src/handlers/check_function.rs +++ b/crates/analyzer/src/handlers/check_function.rs @@ -54,7 +54,7 @@ impl<'a> VerylGrammarTrait for CheckFunction<'a> { self.errors.push(AnalyzerError::unused_return( &name, self.text, - &arg.expression_identifier.identifier.identifier_token, + &arg.expression_identifier.identifier.identifier_token.token, )); } } @@ -111,7 +111,7 @@ impl<'a> VerylGrammarTrait for CheckFunction<'a> { arity, args, self.text, - &x.expression_identifier.identifier.identifier_token, + &x.expression_identifier.identifier.identifier_token.token, )); } } diff --git a/crates/analyzer/src/handlers/check_identifier.rs b/crates/analyzer/src/handlers/check_identifier.rs index 4e61b978..5d39d71d 100644 --- a/crates/analyzer/src/handlers/check_identifier.rs +++ b/crates/analyzer/src/handlers/check_identifier.rs @@ -6,7 +6,7 @@ use inflector::cases::{ }; use veryl_metadata::{Case, Lint}; use veryl_parser::veryl_grammar_trait::*; -use veryl_parser::veryl_token::VerylToken; +use veryl_parser::veryl_token::Token; use veryl_parser::veryl_walker::{Handler, HandlerPoint}; use veryl_parser::ParolError; @@ -50,7 +50,7 @@ impl<'a> CheckIdentifier<'a> { } } - fn check(&mut self, token: &VerylToken, kind: Kind) { + fn check(&mut self, token: &Token, kind: Kind) { let opt = &self.lint_opt.naming; let prefix = match kind { @@ -129,7 +129,7 @@ impl<'a> CheckIdentifier<'a> { Kind::Wire => &opt.re_forbidden_wire, }; - let identifier = token.text(); + let identifier = token.to_string(); if let Some(prefix) = prefix { if !identifier.starts_with(prefix) { self.errors.push(AnalyzerError::invalid_identifier( @@ -200,13 +200,13 @@ impl<'a> VerylGrammarTrait for CheckIdentifier<'a> { if let HandlerPoint::Before = self.point { if self.in_always_comb { self.check( - &arg.expression_identifier.identifier.identifier_token, + &arg.expression_identifier.identifier.identifier_token.token, Kind::Wire, ); } if self.in_always_ff { self.check( - &arg.expression_identifier.identifier.identifier_token, + &arg.expression_identifier.identifier.identifier_token.token, Kind::Reg, ); } @@ -216,21 +216,21 @@ impl<'a> VerylGrammarTrait for CheckIdentifier<'a> { fn local_declaration(&mut self, arg: &LocalDeclaration) -> Result<(), ParolError> { if let HandlerPoint::Before = self.point { - self.check(&arg.identifier.identifier_token, Kind::Parameter); + self.check(&arg.identifier.identifier_token.token, Kind::Parameter); } Ok(()) } fn modport_declaration(&mut self, arg: &ModportDeclaration) -> Result<(), ParolError> { if let HandlerPoint::Before = self.point { - self.check(&arg.identifier.identifier_token, Kind::Modport); + self.check(&arg.identifier.identifier_token.token, Kind::Modport); } Ok(()) } fn enum_declaration(&mut self, arg: &EnumDeclaration) -> Result<(), ParolError> { if let HandlerPoint::Before = self.point { - self.check(&arg.identifier.identifier_token, Kind::Enum); + self.check(&arg.identifier.identifier_token.token, Kind::Enum); } Ok(()) } @@ -239,27 +239,27 @@ impl<'a> VerylGrammarTrait for CheckIdentifier<'a> { if let HandlerPoint::Before = self.point { match &*arg.struct_union { StructUnion::Struct(_) => { - self.check(&arg.identifier.identifier_token, Kind::Struct); + self.check(&arg.identifier.identifier_token.token, Kind::Struct); } StructUnion::Union(_) => { - self.check(&arg.identifier.identifier_token, Kind::Union); + self.check(&arg.identifier.identifier_token.token, Kind::Union); } } - self.check(&arg.identifier.identifier_token, Kind::Struct); + self.check(&arg.identifier.identifier_token.token, Kind::Struct); } Ok(()) } fn inst_declaration(&mut self, arg: &InstDeclaration) -> Result<(), ParolError> { if let HandlerPoint::Before = self.point { - self.check(&arg.identifier.identifier_token, Kind::Instance); + self.check(&arg.identifier.identifier_token.token, Kind::Instance); } Ok(()) } fn with_parameter_item(&mut self, arg: &WithParameterItem) -> Result<(), ParolError> { if let HandlerPoint::Before = self.point { - self.check(&arg.identifier.identifier_token, Kind::Parameter); + self.check(&arg.identifier.identifier_token.token, Kind::Parameter); } Ok(()) } @@ -284,7 +284,7 @@ impl<'a> VerylGrammarTrait for CheckIdentifier<'a> { }; if let Some(kind) = kind { - self.check(&arg.identifier.identifier_token, kind); + self.check(&arg.identifier.identifier_token.token, kind); } } Ok(()) @@ -308,28 +308,28 @@ impl<'a> VerylGrammarTrait for CheckIdentifier<'a> { fn function_declaration(&mut self, arg: &FunctionDeclaration) -> Result<(), ParolError> { if let HandlerPoint::Before = self.point { - self.check(&arg.identifier.identifier_token, Kind::Function); + self.check(&arg.identifier.identifier_token.token, Kind::Function); } Ok(()) } fn module_declaration(&mut self, arg: &ModuleDeclaration) -> Result<(), ParolError> { if let HandlerPoint::Before = self.point { - self.check(&arg.identifier.identifier_token, Kind::Module); + self.check(&arg.identifier.identifier_token.token, Kind::Module); } Ok(()) } fn interface_declaration(&mut self, arg: &InterfaceDeclaration) -> Result<(), ParolError> { if let HandlerPoint::Before = self.point { - self.check(&arg.identifier.identifier_token, Kind::Interface); + self.check(&arg.identifier.identifier_token.token, Kind::Interface); } Ok(()) } fn package_declaration(&mut self, arg: &PackageDeclaration) -> Result<(), ParolError> { if let HandlerPoint::Before = self.point { - self.check(&arg.identifier.identifier_token, Kind::Package); + self.check(&arg.identifier.identifier_token.token, Kind::Package); } Ok(()) } diff --git a/crates/analyzer/src/handlers/check_instance.rs b/crates/analyzer/src/handlers/check_instance.rs index 9e3b4590..4c07e170 100644 --- a/crates/analyzer/src/handlers/check_instance.rs +++ b/crates/analyzer/src/handlers/check_instance.rs @@ -58,7 +58,7 @@ impl<'a> VerylGrammarTrait for CheckInstance<'a> { name, &port, self.text, - &arg.identifier.identifier_token, + &arg.identifier.identifier_token.token, )); } } @@ -69,7 +69,7 @@ impl<'a> VerylGrammarTrait for CheckInstance<'a> { name, &port, self.text, - &arg.identifier.identifier_token, + &arg.identifier.identifier_token.token, )); } } @@ -82,7 +82,7 @@ impl<'a> VerylGrammarTrait for CheckInstance<'a> { "module or interface", &symbol.kind.to_kind_name(), self.text, - &arg.identifier.identifier_token, + &arg.identifier.identifier_token.token, )); } } diff --git a/crates/analyzer/src/handlers/check_msb_lsb.rs b/crates/analyzer/src/handlers/check_msb_lsb.rs index 8c834cd6..1780ceb3 100644 --- a/crates/analyzer/src/handlers/check_msb_lsb.rs +++ b/crates/analyzer/src/handlers/check_msb_lsb.rs @@ -42,7 +42,7 @@ impl<'a> VerylGrammarTrait for CheckMsbLsb<'a> { if let HandlerPoint::Before = self.point { if !(self.in_expression_identifier && self.in_select) { self.errors - .push(AnalyzerError::invalid_lsb(self.text, &arg.lsb_token)); + .push(AnalyzerError::invalid_lsb(self.text, &arg.lsb_token.token)); } } Ok(()) @@ -75,11 +75,11 @@ impl<'a> VerylGrammarTrait for CheckMsbLsb<'a> { }; if !resolved { self.errors - .push(AnalyzerError::unknown_msb(self.text, &arg.msb_token)); + .push(AnalyzerError::unknown_msb(self.text, &arg.msb_token.token)); } } else { self.errors - .push(AnalyzerError::invalid_msb(self.text, &arg.msb_token)); + .push(AnalyzerError::invalid_msb(self.text, &arg.msb_token.token)); } } Ok(()) diff --git a/crates/analyzer/src/handlers/check_number.rs b/crates/analyzer/src/handlers/check_number.rs index 53ae2fdb..67fff7e5 100644 --- a/crates/analyzer/src/handlers/check_number.rs +++ b/crates/analyzer/src/handlers/check_number.rs @@ -32,8 +32,8 @@ impl<'a> Handler for CheckNumber<'a> { impl<'a> VerylGrammarTrait for CheckNumber<'a> { fn based(&mut self, arg: &Based) -> Result<(), ParolError> { if let HandlerPoint::Before = self.point { - let token = &arg.based_token; - let text = token.text(); + let token = &arg.based_token.token; + let text = token.to_string(); let (width, tail) = text.split_once('\'').unwrap(); let base = &tail[0..1]; let number = &tail[1..]; diff --git a/crates/analyzer/src/handlers/check_reset.rs b/crates/analyzer/src/handlers/check_reset.rs index 3cc8c03e..f548294b 100644 --- a/crates/analyzer/src/handlers/check_reset.rs +++ b/crates/analyzer/src/handlers/check_reset.rs @@ -115,7 +115,7 @@ impl<'a> VerylGrammarTrait for CheckReset<'a> { if if_reset_required { self.errors.push(AnalyzerError::missing_if_reset( self.text, - &arg.always_ff.always_ff_token, + &arg.always_ff.always_ff_token.token, )); } @@ -126,7 +126,7 @@ impl<'a> VerylGrammarTrait for CheckReset<'a> { if self.if_reset_exist && arg.always_ff_declaration_opt.is_none() { self.errors.push(AnalyzerError::missing_reset_signal( self.text, - &arg.always_ff.always_ff_token, + &arg.always_ff.always_ff_token.token, )); } @@ -149,7 +149,7 @@ impl<'a> VerylGrammarTrait for CheckReset<'a> { self.errors.push(AnalyzerError::missing_reset_statement( &name, self.text, - &x.identifier.identifier_token, + &x.identifier.identifier_token.token, )); } } diff --git a/crates/analyzer/src/handlers/check_statement.rs b/crates/analyzer/src/handlers/check_statement.rs index 664d7ce5..fefa82d7 100644 --- a/crates/analyzer/src/handlers/check_statement.rs +++ b/crates/analyzer/src/handlers/check_statement.rs @@ -43,9 +43,9 @@ impl<'a> VerylGrammarTrait for CheckStatement<'a> { if let HandlerPoint::Before = self.point { if self.in_initial || self.in_final { let token = match &*arg.assignment_group { - AssignmentGroup::Equ(x) => &x.equ.equ_token, + AssignmentGroup::Equ(x) => &x.equ.equ_token.token, AssignmentGroup::AssignmentOperator(x) => { - &x.assignment_operator.assignment_operator_token + &x.assignment_operator.assignment_operator_token.token } }; self.errors.push(AnalyzerError::invalid_statement( @@ -64,7 +64,7 @@ impl<'a> VerylGrammarTrait for CheckStatement<'a> { self.errors.push(AnalyzerError::invalid_statement( "if_reset", self.text, - &arg.if_reset.if_reset_token, + &arg.if_reset.if_reset_token.token, )); } @@ -72,7 +72,7 @@ impl<'a> VerylGrammarTrait for CheckStatement<'a> { self.errors.push(AnalyzerError::invalid_statement( "if_reset", self.text, - &arg.if_reset.if_reset_token, + &arg.if_reset.if_reset_token.token, )); } } @@ -85,7 +85,7 @@ impl<'a> VerylGrammarTrait for CheckStatement<'a> { self.errors.push(AnalyzerError::invalid_statement( "return", self.text, - &arg.r#return.return_token, + &arg.r#return.return_token.token, )); } } diff --git a/crates/analyzer/src/handlers/create_reference.rs b/crates/analyzer/src/handlers/create_reference.rs index 54ca51ba..3cb3e759 100644 --- a/crates/analyzer/src/handlers/create_reference.rs +++ b/crates/analyzer/src/handlers/create_reference.rs @@ -5,7 +5,7 @@ use crate::symbol::{DocComment, Symbol, SymbolKind}; use crate::symbol_table::{self, ResolveError, ResolveErrorCause, ResolveSymbol, SymbolPath}; use veryl_parser::resource_table::TokenId; use veryl_parser::veryl_grammar_trait::*; -use veryl_parser::veryl_token::{Token, VerylToken}; +use veryl_parser::veryl_token::Token; use veryl_parser::veryl_walker::{Handler, HandlerPoint}; use veryl_parser::ParolError; @@ -28,9 +28,9 @@ impl<'a> CreateReference<'a> { } } - fn push_resolve_error(&mut self, err: ResolveError, token: &VerylToken) { + fn push_resolve_error(&mut self, err: ResolveError, token: &Token) { if let Some(last_found) = err.last_found { - let name = format!("{}", last_found.token.text); + let name = last_found.token.to_string(); match err.cause { ResolveErrorCause::NotFound(not_found) => { let member = format!("{}", not_found); @@ -106,7 +106,7 @@ impl<'a> VerylGrammarTrait for CreateReference<'a> { } // TODO check SV-side member to suppress error - self.push_resolve_error(err, &arg.identifier.identifier_token); + self.push_resolve_error(err, &arg.identifier.identifier_token.token); } } } @@ -141,7 +141,7 @@ impl<'a> VerylGrammarTrait for CreateReference<'a> { } } Err(err) => { - self.push_resolve_error(err, &arg.identifier.identifier_token); + self.push_resolve_error(err, &arg.identifier.identifier_token.token); } } } @@ -187,7 +187,7 @@ impl<'a> VerylGrammarTrait for CreateReference<'a> { return Ok(()); } - self.push_resolve_error(err, &arg.identifier.identifier_token); + self.push_resolve_error(err, &arg.identifier.identifier_token.token); } } } @@ -203,7 +203,7 @@ impl<'a> VerylGrammarTrait for CreateReference<'a> { } } Err(err) => { - self.push_resolve_error(err, &arg.identifier.identifier_token); + self.push_resolve_error(err, &arg.identifier.identifier_token.token); } } } @@ -221,7 +221,7 @@ impl<'a> VerylGrammarTrait for CreateReference<'a> { } } Err(err) => { - self.push_resolve_error(err, &arg.identifier.identifier_token); + self.push_resolve_error(err, &arg.identifier.identifier_token.token); } } } @@ -314,7 +314,7 @@ impl<'a> VerylGrammarTrait for CreateReference<'a> { _ if is_wildcard => { self.errors.push(AnalyzerError::invalid_import( self.text, - &arg.scoped_identifier.identifier.identifier_token, + &arg.scoped_identifier.identifier.identifier_token.token, )); } _ => { @@ -330,7 +330,7 @@ impl<'a> VerylGrammarTrait for CreateReference<'a> { Err(err) => { self.push_resolve_error( err, - &arg.scoped_identifier.identifier.identifier_token, + &arg.scoped_identifier.identifier.identifier_token.token, ); } } diff --git a/crates/analyzer/src/handlers/create_symbol_table.rs b/crates/analyzer/src/handlers/create_symbol_table.rs index ff77fa7f..91558d03 100644 --- a/crates/analyzer/src/handlers/create_symbol_table.rs +++ b/crates/analyzer/src/handlers/create_symbol_table.rs @@ -9,14 +9,14 @@ use crate::symbol::{ InterfaceProperty, ModportMemberProperty, ModportProperty, ModuleProperty, PackageProperty, ParameterProperty, ParameterScope, ParameterValue, PortProperty, StructMemberProperty, StructProperty, Symbol, SymbolId, SymbolKind, TypeDefProperty, TypeKind, UnionMemberProperty, - UnionProperty, VariableProperty, + UnionProperty, VariableAffiniation, VariableProperty, }; -use crate::symbol_table; -use std::collections::HashSet; +use crate::symbol_table::{self, SymbolPath}; +use std::collections::{HashMap, HashSet}; use veryl_parser::doc_comment_table; use veryl_parser::resource_table::{self, StrId}; use veryl_parser::veryl_grammar_trait::*; -use veryl_parser::veryl_token::{TokenRange, TokenSource, VerylToken}; +use veryl_parser::veryl_token::{Token, TokenRange, TokenSource}; use veryl_parser::veryl_walker::{Handler, HandlerPoint}; use veryl_parser::ParolError; @@ -27,12 +27,15 @@ pub struct CreateSymbolTable<'a> { point: HandlerPoint, namespace: Namespace, default_block: Option, - for_identifier: Option, + for_identifier: Option, anonymous_namespace: usize, attribute_lines: HashSet, struct_or_union: Option, enum_members: Vec>, struct_union_members: Vec>, + affiniation: Vec, + connect_targets: Vec>, + connects: HashMap>, } #[derive(Clone)] @@ -49,14 +52,9 @@ impl<'a> CreateSymbolTable<'a> { } } - fn insert_symbol( - &mut self, - token: &VerylToken, - kind: SymbolKind, - public: bool, - ) -> Option { - let line = token.token.line; - let doc_comment = if let TokenSource::File(file) = token.token.source { + fn insert_symbol(&mut self, token: &Token, kind: SymbolKind, public: bool) -> Option { + let line = token.line; + let doc_comment = if let TokenSource::File(file) = token.source { if line == 0 { DocComment::default() } else if let Some(doc_comment) = doc_comment_table::get(file, line) { @@ -80,17 +78,18 @@ impl<'a> CreateSymbolTable<'a> { } else { DocComment::default() }; - let mut symbol = Symbol::new(&token.token, kind, &self.namespace, public, doc_comment); + let mut symbol = Symbol::new(token, kind, &self.namespace, public, doc_comment); if allow_table::contains("unused_variable") { symbol.allow_unused = true; } - let id = symbol_table::insert(&token.token, symbol); + let id = symbol_table::insert(token, symbol); if id.is_none() { - let text = resource_table::get_str_value(token.token.text).unwrap(); self.errors.push(AnalyzerError::duplicated_identifier( - &text, self.text, token, + &token.to_string(), + self.text, + token, )); } id @@ -114,6 +113,24 @@ impl<'a> VerylGrammarTrait for CreateSymbolTable<'a> { Ok(()) } + fn expression_identifier(&mut self, arg: &ExpressionIdentifier) -> Result<(), ParolError> { + if let HandlerPoint::Before = self.point { + if let ExpressionIdentifierGroup::ExpressionIdentifierMember(x) = + arg.expression_identifier_group.as_ref() + { + let mut target = Vec::new(); + target.push(arg.identifier.identifier_token.token.text); + + let x = &x.expression_identifier_member; + for x in &x.expression_identifier_member_list0 { + target.push(x.identifier.identifier_token.token.text); + } + self.connect_targets.push(target); + } + } + Ok(()) + } + fn attribute(&mut self, arg: &Attribute) -> Result<(), ParolError> { if let HandlerPoint::Before = self.point { self.attribute_lines.insert(arg.hash.hash_token.token.line); @@ -124,9 +141,13 @@ impl<'a> VerylGrammarTrait for CreateSymbolTable<'a> { fn let_statement(&mut self, arg: &LetStatement) -> Result<(), ParolError> { if let HandlerPoint::Before = self.point { let r#type: SymType = arg.array_type.as_ref().into(); - let property = VariableProperty { r#type }; + let affiniation = self.affiniation.last().cloned().unwrap(); + let property = VariableProperty { + r#type, + affiniation, + }; let kind = SymbolKind::Variable(property); - self.insert_symbol(&arg.identifier.identifier_token, kind, false); + self.insert_symbol(&arg.identifier.identifier_token.token, kind, false); } Ok(()) } @@ -140,9 +161,13 @@ impl<'a> VerylGrammarTrait for CreateSymbolTable<'a> { self.anonymous_namespace += 1; let r#type: SymType = arg.scalar_type.as_ref().into(); - let property = VariableProperty { r#type }; + let affiniation = self.affiniation.last().cloned().unwrap(); + let property = VariableProperty { + r#type, + affiniation, + }; let kind = SymbolKind::Variable(property); - self.insert_symbol(&arg.identifier.identifier_token, kind, false); + self.insert_symbol(&arg.identifier.identifier_token.token, kind, false); } HandlerPoint::After => self.namespace.pop(), } @@ -152,9 +177,13 @@ impl<'a> VerylGrammarTrait for CreateSymbolTable<'a> { fn let_declaration(&mut self, arg: &LetDeclaration) -> Result<(), ParolError> { if let HandlerPoint::Before = self.point { let r#type: SymType = arg.array_type.as_ref().into(); - let property = VariableProperty { r#type }; + let affiniation = self.affiniation.last().cloned().unwrap(); + let property = VariableProperty { + r#type, + affiniation, + }; let kind = SymbolKind::Variable(property); - self.insert_symbol(&arg.identifier.identifier_token, kind, false); + self.insert_symbol(&arg.identifier.identifier_token.token, kind, false); } Ok(()) } @@ -162,9 +191,13 @@ impl<'a> VerylGrammarTrait for CreateSymbolTable<'a> { fn var_declaration(&mut self, arg: &VarDeclaration) -> Result<(), ParolError> { if let HandlerPoint::Before = self.point { let r#type: SymType = arg.array_type.as_ref().into(); - let property = VariableProperty { r#type }; + let affiniation = self.affiniation.last().cloned().unwrap(); + let property = VariableProperty { + r#type, + affiniation, + }; let kind = SymbolKind::Variable(property); - self.insert_symbol(&arg.identifier.identifier_token, kind, false); + self.insert_symbol(&arg.identifier.identifier_token.token, kind, false); } Ok(()) } @@ -200,7 +233,7 @@ impl<'a> VerylGrammarTrait for CreateSymbolTable<'a> { } }; let kind = SymbolKind::Parameter(property); - self.insert_symbol(&arg.identifier.identifier_token, kind, false); + self.insert_symbol(&arg.identifier.identifier_token.token, kind, false); } Ok(()) } @@ -217,7 +250,7 @@ impl<'a> VerylGrammarTrait for CreateSymbolTable<'a> { let direction: crate::symbol::Direction = item.direction.as_ref().into(); let property = ModportMemberProperty { direction }; let id = self.insert_symbol( - &item.identifier.identifier_token, + &item.identifier.identifier_token.token, SymbolKind::ModportMember(property), false, ); @@ -229,7 +262,7 @@ impl<'a> VerylGrammarTrait for CreateSymbolTable<'a> { let members: Vec<_> = members.into_iter().flatten().collect(); let property = ModportProperty { members }; let kind = SymbolKind::Modport(property); - self.insert_symbol(&arg.identifier.identifier_token, kind, false); + self.insert_symbol(&arg.identifier.identifier_token.token, kind, false); } Ok(()) } @@ -247,7 +280,7 @@ impl<'a> VerylGrammarTrait for CreateSymbolTable<'a> { let members: Vec<_> = self.enum_members.drain(0..).flatten().collect(); let property = EnumProperty { r#type, members }; let kind = SymbolKind::Enum(property); - self.insert_symbol(&arg.identifier.identifier_token, kind, false); + self.insert_symbol(&arg.identifier.identifier_token.token, kind, false); } } Ok(()) @@ -258,7 +291,7 @@ impl<'a> VerylGrammarTrait for CreateSymbolTable<'a> { let value = arg.enum_item_opt.as_ref().map(|x| *x.expression.clone()); let property = EnumMemberProperty { value }; let kind = SymbolKind::EnumMember(property); - let id = self.insert_symbol(&arg.identifier.identifier_token, kind, false); + let id = self.insert_symbol(&arg.identifier.identifier_token.token, kind, false); self.enum_members.push(id); } Ok(()) @@ -290,7 +323,7 @@ impl<'a> VerylGrammarTrait for CreateSymbolTable<'a> { SymbolKind::Union(property) } }; - self.insert_symbol(&arg.identifier.identifier_token, kind, false); + self.insert_symbol(&arg.identifier.identifier_token.token, kind, false); } } Ok(()) @@ -301,7 +334,7 @@ impl<'a> VerylGrammarTrait for CreateSymbolTable<'a> { let r#type = arg.array_type.as_ref().into(); let property = TypeDefProperty { r#type }; let kind = SymbolKind::TypeDef(property); - self.insert_symbol(&arg.identifier.identifier_token, kind, false); + self.insert_symbol(&arg.identifier.identifier_token.token, kind, false); } Ok(()) } @@ -319,21 +352,41 @@ impl<'a> VerylGrammarTrait for CreateSymbolTable<'a> { SymbolKind::UnionMember(property) } }; - let id = self.insert_symbol(&arg.identifier.identifier_token, kind, false); + let id = self.insert_symbol(&arg.identifier.identifier_token.token, kind, false); self.struct_union_members.push(id); } Ok(()) } fn inst_declaration(&mut self, arg: &InstDeclaration) -> Result<(), ParolError> { - if let HandlerPoint::Before = self.point { - let mut type_name = vec![arg.scoped_identifier.identifier.identifier_token.token.text]; - for x in &arg.scoped_identifier.scoped_identifier_list { - type_name.push(x.identifier.identifier_token.token.text); - } - let property = InstanceProperty { type_name }; + if let HandlerPoint::After = self.point { + let type_name: SymbolPath = arg.scoped_identifier.as_ref().into(); + let type_name = type_name.to_vec(); + let connects = self.connects.drain().collect(); + let property = InstanceProperty { + type_name, + connects, + }; let kind = SymbolKind::Instance(property); - self.insert_symbol(&arg.identifier.identifier_token, kind, false); + self.insert_symbol(&arg.identifier.identifier_token.token, kind, false); + } + Ok(()) + } + + fn inst_port_item(&mut self, arg: &InstPortItem) -> Result<(), ParolError> { + match self.point { + HandlerPoint::Before => self.connect_targets.clear(), + HandlerPoint::After => { + let port = arg.identifier.identifier_token.token.text; + let targets = if arg.inst_port_item_opt.is_some() { + self.connect_targets.drain(0..).collect() + } else { + vec![vec![port]] + }; + for target in targets { + self.connects.insert(port, target); + } + } } Ok(()) } @@ -373,7 +426,7 @@ impl<'a> VerylGrammarTrait for CreateSymbolTable<'a> { } }; let kind = SymbolKind::Parameter(property); - self.insert_symbol(&arg.identifier.identifier_token, kind, false); + self.insert_symbol(&arg.identifier.identifier_token.token, kind, false); } Ok(()) } @@ -398,7 +451,7 @@ impl<'a> VerylGrammarTrait for CreateSymbolTable<'a> { }, }; let kind = SymbolKind::Port(property); - self.insert_symbol(&arg.identifier.identifier_token, kind, false); + self.insert_symbol(&arg.identifier.identifier_token.token, kind, false); } Ok(()) } @@ -438,15 +491,19 @@ impl<'a> VerylGrammarTrait for CreateSymbolTable<'a> { ret, }; self.insert_symbol( - &arg.identifier.identifier_token, + &arg.identifier.identifier_token.token, SymbolKind::Function(property), false, ); let name = arg.identifier.identifier_token.token.text; - self.namespace.push(name) + self.namespace.push(name); + self.affiniation.push(VariableAffiniation::Function); + } + HandlerPoint::After => { + self.namespace.pop(); + self.affiniation.pop(); } - HandlerPoint::After => self.namespace.pop(), } Ok(()) } @@ -481,22 +538,26 @@ impl<'a> VerylGrammarTrait for CreateSymbolTable<'a> { ports, }; self.insert_symbol( - &arg.identifier.identifier_token, + &arg.identifier.identifier_token.token, SymbolKind::Module(property), public, ); let name = arg.identifier.identifier_token.token.text; - self.namespace.push(name) + self.namespace.push(name); + self.affiniation.push(VariableAffiniation::Module); + } + HandlerPoint::After => { + self.namespace.pop(); + self.affiniation.pop(); } - HandlerPoint::After => self.namespace.pop(), } Ok(()) } fn module_for_declaration(&mut self, arg: &ModuleForDeclaration) -> Result<(), ParolError> { if let HandlerPoint::Before = self.point { - self.for_identifier = Some(arg.identifier.identifier_token.clone()); + self.for_identifier = Some(arg.identifier.identifier_token.token); } Ok(()) } @@ -504,14 +565,18 @@ impl<'a> VerylGrammarTrait for CreateSymbolTable<'a> { fn module_named_block(&mut self, arg: &ModuleNamedBlock) -> Result<(), ParolError> { match self.point { HandlerPoint::Before => { - self.insert_symbol(&arg.identifier.identifier_token, SymbolKind::Block, false); + self.insert_symbol( + &arg.identifier.identifier_token.token, + SymbolKind::Block, + false, + ); let name = arg.identifier.identifier_token.token.text; self.default_block = Some(name); self.namespace.push(name); if self.for_identifier.is_some() { - let identifier = self.for_identifier.clone().unwrap(); + let identifier = self.for_identifier.unwrap(); self.insert_symbol(&identifier, SymbolKind::Genvar, false); self.for_identifier = None; } @@ -528,7 +593,11 @@ impl<'a> VerylGrammarTrait for CreateSymbolTable<'a> { match self.point { HandlerPoint::Before => { let name = if let Some(ref x) = arg.module_optional_named_block_opt { - self.insert_symbol(&x.identifier.identifier_token, SymbolKind::Block, false); + self.insert_symbol( + &x.identifier.identifier_token.token, + SymbolKind::Block, + false, + ); x.identifier.identifier_token.token.text } else { let name = format!( @@ -564,15 +633,19 @@ impl<'a> VerylGrammarTrait for CreateSymbolTable<'a> { TokenRange::new(&arg.interface.interface_token, &arg.r_brace.r_brace_token); let property = InterfaceProperty { range, parameters }; self.insert_symbol( - &arg.identifier.identifier_token, + &arg.identifier.identifier_token.token, SymbolKind::Interface(property), public, ); let name = arg.identifier.identifier_token.token.text; - self.namespace.push(name) + self.namespace.push(name); + self.affiniation.push(VariableAffiniation::Intarface); + } + HandlerPoint::After => { + self.namespace.pop(); + self.affiniation.pop(); } - HandlerPoint::After => self.namespace.pop(), } Ok(()) } @@ -582,7 +655,7 @@ impl<'a> VerylGrammarTrait for CreateSymbolTable<'a> { arg: &InterfaceForDeclaration, ) -> Result<(), ParolError> { if let HandlerPoint::Before = self.point { - self.for_identifier = Some(arg.identifier.identifier_token.clone()); + self.for_identifier = Some(arg.identifier.identifier_token.token); } Ok(()) } @@ -590,14 +663,18 @@ impl<'a> VerylGrammarTrait for CreateSymbolTable<'a> { fn interface_named_block(&mut self, arg: &InterfaceNamedBlock) -> Result<(), ParolError> { match self.point { HandlerPoint::Before => { - self.insert_symbol(&arg.identifier.identifier_token, SymbolKind::Block, false); + self.insert_symbol( + &arg.identifier.identifier_token.token, + SymbolKind::Block, + false, + ); let name = arg.identifier.identifier_token.token.text; self.default_block = Some(name); self.namespace.push(name); if self.for_identifier.is_some() { - let identifier = self.for_identifier.clone().unwrap(); + let identifier = self.for_identifier.unwrap(); self.insert_symbol(&identifier, SymbolKind::Genvar, false); self.for_identifier = None; } @@ -614,7 +691,11 @@ impl<'a> VerylGrammarTrait for CreateSymbolTable<'a> { match self.point { HandlerPoint::Before => { let name = if let Some(ref x) = arg.interface_optional_named_block_opt { - self.insert_symbol(&x.identifier.identifier_token, SymbolKind::Block, false); + self.insert_symbol( + &x.identifier.identifier_token.token, + SymbolKind::Block, + false, + ); x.identifier.identifier_token.token.text } else { let name = format!( @@ -640,15 +721,19 @@ impl<'a> VerylGrammarTrait for CreateSymbolTable<'a> { let range = TokenRange::new(&arg.package.package_token, &arg.r_brace.r_brace_token); let property = PackageProperty { range }; self.insert_symbol( - &arg.identifier.identifier_token, + &arg.identifier.identifier_token.token, SymbolKind::Package(property), public, ); let name = arg.identifier.identifier_token.token.text; - self.namespace.push(name) + self.namespace.push(name); + self.affiniation.push(VariableAffiniation::Package); + } + HandlerPoint::After => { + self.namespace.pop(); + self.affiniation.pop(); } - HandlerPoint::After => self.namespace.pop(), } Ok(()) } diff --git a/crates/analyzer/src/handlers/create_type_dag.rs b/crates/analyzer/src/handlers/create_type_dag.rs index e0fd4837..01185e56 100644 --- a/crates/analyzer/src/handlers/create_type_dag.rs +++ b/crates/analyzer/src/handlers/create_type_dag.rs @@ -10,7 +10,7 @@ use veryl_parser::{ ScopedIdentifier, StructUnion, StructUnionDeclaration, TypeDefDeclaration, VerylGrammarTrait, }, - veryl_token::VerylToken, + veryl_token::Token, ParolError, }; use veryl_parser::{ @@ -39,7 +39,7 @@ impl<'a> CreateTypeDag<'a> { &mut self, path: &SymbolPathNamespace, name: &str, - token: &VerylToken, + token: &Token, ) -> Option { match type_dag::insert_node(path, name, token) { Ok(n) => Some(n), @@ -53,10 +53,6 @@ impl<'a> CreateTypeDag<'a> { fn to_analyzer_error(&self, de: DagError) -> AnalyzerError { match de { DagError::Cyclic(s, e) => { - let token: VerylToken = VerylToken { - token: e.token, - comments: vec![], - }; let start = match resource_table::get_str_value(s.token.text) { Some(s) => s, None => "".into(), @@ -65,7 +61,7 @@ impl<'a> CreateTypeDag<'a> { Some(s) => s, None => "".into(), }; - AnalyzerError::cyclic_type_dependency(self.text, &start, &end, &token) + AnalyzerError::cyclic_type_dependency(self.text, &start, &end, &e.token) } DagError::UnableToResolve(b) => { let t = b.as_ref(); @@ -104,7 +100,7 @@ impl<'a> VerylGrammarTrait for CreateTypeDag<'a> { HandlerPoint::Before => { let path: SymbolPathNamespace = arg.identifier.as_ref().into(); let name = arg.identifier.identifier_token.text(); - let token = arg.identifier.identifier_token.clone(); + let token = arg.identifier.identifier_token.token; if let Some(x) = self.insert_node(&path, &name, &token) { self.parent.push(x) } @@ -128,7 +124,7 @@ impl<'a> VerylGrammarTrait for CreateTypeDag<'a> { HandlerPoint::Before => { let path: SymbolPathNamespace = arg.identifier.as_ref().into(); let name = arg.identifier.identifier_token.text(); - let token = arg.identifier.identifier_token.clone(); + let token = arg.identifier.identifier_token.token; if let Some(x) = self.insert_node(&path, &name, &token) { self.parent.push(x) } @@ -147,7 +143,7 @@ impl<'a> VerylGrammarTrait for CreateTypeDag<'a> { if !self.ctx.is_empty() { let path: SymbolPathNamespace = arg.into(); let name = to_string(arg); - let token = arg.identifier.identifier_token.clone(); + let token = arg.identifier.identifier_token.token; let child = self.insert_node(&path, &name, &token); if let (Some(parent), Some(child)) = (self.parent.last(), child) { self.insert_edge(*parent, child, *self.ctx.last().unwrap()); @@ -162,7 +158,7 @@ impl<'a> VerylGrammarTrait for CreateTypeDag<'a> { HandlerPoint::Before => { let path: SymbolPathNamespace = arg.identifier.as_ref().into(); let name = arg.identifier.identifier_token.text(); - let token = arg.identifier.identifier_token.clone(); + let token = arg.identifier.identifier_token.token; if let Some(x) = self.insert_node(&path, &name, &token) { self.parent.push(x) } @@ -181,7 +177,7 @@ impl<'a> VerylGrammarTrait for CreateTypeDag<'a> { HandlerPoint::Before => { let path: SymbolPathNamespace = arg.identifier.as_ref().into(); let name = arg.identifier.identifier_token.text(); - let token = arg.identifier.identifier_token.clone(); + let token = arg.identifier.identifier_token.token; if let Some(x) = self.insert_node(&path, &name, &token) { self.parent.push(x) } @@ -200,7 +196,7 @@ impl<'a> VerylGrammarTrait for CreateTypeDag<'a> { HandlerPoint::Before => { let path: SymbolPathNamespace = arg.identifier.as_ref().into(); let name = arg.identifier.identifier_token.text(); - let token = arg.identifier.identifier_token.clone(); + let token = arg.identifier.identifier_token.token; if let Some(x) = self.insert_node(&path, &name, &token) { self.parent.push(x) } @@ -219,7 +215,7 @@ impl<'a> VerylGrammarTrait for CreateTypeDag<'a> { HandlerPoint::Before => { let path: SymbolPathNamespace = arg.identifier.as_ref().into(); let name = arg.identifier.identifier_token.text(); - let token = arg.identifier.identifier_token.clone(); + let token = arg.identifier.identifier_token.token; if let Some(x) = self.insert_node(&path, &name, &token) { self.parent.push(x) } diff --git a/crates/analyzer/src/symbol.rs b/crates/analyzer/src/symbol.rs index ef7aabc8..0932882b 100644 --- a/crates/analyzer/src/symbol.rs +++ b/crates/analyzer/src/symbol.rs @@ -1,6 +1,7 @@ use crate::evaluator::{Evaluated, Evaluator}; use crate::namespace::Namespace; use std::cell::{Cell, RefCell}; +use std::collections::HashMap; use std::fmt; use veryl_parser::resource_table::StrId; use veryl_parser::veryl_grammar_trait as syntax_tree; @@ -258,7 +259,7 @@ impl fmt::Display for SymbolKind { } } -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum Direction { Input, Output, @@ -302,7 +303,7 @@ pub struct Type { pub array: Vec, } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq, Eq)] pub enum TypeKind { Bit, Logic, @@ -463,6 +464,15 @@ impl From<&syntax_tree::ArrayType> for Type { #[derive(Debug, Clone)] pub struct VariableProperty { pub r#type: Type, + pub affiniation: VariableAffiniation, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum VariableAffiniation { + Module, + Intarface, + Package, + Function, } #[derive(Debug, Clone)] @@ -613,6 +623,7 @@ pub struct FunctionProperty { #[derive(Debug, Clone)] pub struct InstanceProperty { pub type_name: Vec, + pub connects: HashMap>, } #[derive(Debug, Clone)] diff --git a/crates/analyzer/src/symbol_table.rs b/crates/analyzer/src/symbol_table.rs index b5282e2e..a0d36e68 100644 --- a/crates/analyzer/src/symbol_table.rs +++ b/crates/analyzer/src/symbol_table.rs @@ -1,13 +1,13 @@ use crate::evaluator::Evaluated; use crate::namespace::Namespace; use crate::namespace_table; -use crate::symbol::{Direction, DocComment, Symbol, SymbolId, SymbolKind, TypeKind}; +use crate::symbol::{DocComment, Symbol, SymbolId, SymbolKind, TypeKind}; use std::cell::RefCell; use std::collections::HashMap; use std::fmt; use veryl_parser::resource_table::{self, PathId, StrId, TokenId}; use veryl_parser::veryl_grammar_trait as syntax_tree; -use veryl_parser::veryl_token::{Token, TokenSource, VerylToken}; +use veryl_parser::veryl_token::{Token, TokenSource}; #[derive(Debug, Default, Clone, PartialEq)] pub struct SymbolPath(Vec); @@ -32,6 +32,10 @@ impl SymbolPath { pub fn as_slice(&self) -> &[StrId] { self.0.as_slice() } + + pub fn to_vec(self) -> Vec { + self.0 + } } impl fmt::Display for SymbolPath { @@ -151,6 +155,13 @@ impl From<(&SymbolPath, &Namespace)> for SymbolPathNamespace { } } +impl From<(&Vec, &Namespace)> for SymbolPathNamespace { + fn from(value: (&Vec, &Namespace)) -> Self { + let path = SymbolPath::new(value.0); + SymbolPathNamespace(path, value.1.clone()) + } +} + impl From<&syntax_tree::Identifier> for SymbolPathNamespace { fn from(value: &syntax_tree::Identifier) -> Self { let namespace = namespace_table::get(value.identifier_token.token.id).unwrap(); @@ -221,8 +232,102 @@ impl ResolveError { #[derive(Clone, Debug)] pub struct Assign { - full_path: Vec, - position: Vec, + pub path: AssignPath, + pub position: AssignPosition, +} + +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct AssignPath(pub Vec); + +impl AssignPath { + pub fn new(x: SymbolId) -> Self { + Self(vec![x]) + } + + pub fn push(&mut self, x: SymbolId) { + self.0.push(x) + } + + pub fn pop(&mut self) -> Option { + self.0.pop() + } + + pub fn included(&self, x: &AssignPath) -> bool { + for (i, x) in x.0.iter().enumerate() { + if let Some(path) = self.0.get(i) { + if path != x { + return false; + } + } else { + return false; + } + } + true + } +} + +impl fmt::Display for AssignPath { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut ret = "".to_string(); + for (i, id) in self.0.iter().enumerate() { + if let Some(symbol) = get(*id) { + if i != 0 { + ret.push('.'); + } + ret.push_str(&symbol.token.to_string()); + } + } + ret.fmt(f) + } +} + +#[derive(Clone, Default, Debug)] +pub struct AssignPosition(pub Vec); + +impl AssignPosition { + pub fn new(x: AssignPositionType) -> Self { + Self(vec![x]) + } + + pub fn push(&mut self, x: AssignPositionType) { + self.0.push(x) + } + + pub fn pop(&mut self) -> Option { + self.0.pop() + } +} + +impl fmt::Display for AssignPosition { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut ret = "".to_string(); + for (i, x) in self.0.iter().enumerate() { + if i != 0 { + ret.push('.'); + } + ret.push_str(&x.token().to_string()); + } + ret.fmt(f) + } +} + +#[derive(Clone, Debug)] +pub enum AssignPositionType { + DeclarationBlock(Token), + Declaration(Token), + StatementBlock(Token), + Statement(Token), +} + +impl AssignPositionType { + pub fn token(&self) -> &Token { + match self { + AssignPositionType::DeclarationBlock(x) => x, + AssignPositionType::Declaration(x) => x, + AssignPositionType::StatementBlock(x) => x, + AssignPositionType::Statement(x) => x, + } + } } #[derive(Clone, Default, Debug)] @@ -377,6 +482,30 @@ impl SymbolTable { } } } + SymbolKind::Port(ref x) => { + if let Some(ref x) = x.r#type { + if let TypeKind::UserDefined(ref x) = x.kind { + let path = SymbolPath::new(x); + if let Ok(symbol) = self.resolve(&path, &namespace) { + if let ResolveSymbol::Symbol(symbol) = symbol.found { + namespace = Namespace::new(); + for path in &symbol.namespace.paths { + namespace.push(*path); + } + namespace.push(symbol.token.text); + inner = true; + } else { + unreachable!(); + } + } else { + return Ok(ResolveResult { + found: ResolveSymbol::External, + full_path, + }); + } + } + } + } SymbolKind::Module(_) => { if other_prj & !ret.public { return Err(ResolveError::new( @@ -419,17 +548,6 @@ impl SymbolTable { } inner = true; } - SymbolKind::Port(ref x) if x.direction == Direction::Modport => { - if let Some(ref x) = x.r#type { - if let TypeKind::UserDefined(ref x) = x.kind { - namespace = Namespace::default(); - for x in x { - namespace.push(*x); - } - inner = true; - } - } - } SymbolKind::SystemVerilog => { namespace = ret.namespace.clone(); namespace.push(ret.token.text); @@ -492,53 +610,17 @@ impl SymbolTable { let mut path_width = 0; let mut pos_width = 0; for assign in &self.assign_list { - path_width = path_width.max( - assign - .full_path - .iter() - .map(|x| self.symbol_table.get(x).unwrap()) - .map(|x| format!("{}", x.token.text).len()) - .sum::() - + assign.full_path.len() - - 1, - ); - pos_width = pos_width.max( - assign - .position - .iter() - .map(|x| x.text().len()) - .sum::() - + assign.position.len() - - 1, - ); + path_width = path_width.max(assign.path.to_string().len()); + pos_width = pos_width.max(assign.position.to_string().len()); } for assign in &self.assign_list { - let mut path = "".to_string(); - for (i, x) in assign.full_path.iter().enumerate() { - let x = self.symbol_table.get(x).unwrap(); - if i == 0 { - path.push_str(&format!("{}", x.token.text)); - } else { - path.push_str(&format!(".{}", x.token.text)); - } - } - - let mut pos = "".to_string(); - for (i, x) in assign.position.iter().enumerate() { - if i == 0 { - pos.push_str(&x.text()); - } else { - pos.push_str(&format!(".{}", x.text())); - } - } - - let last_token = assign.position.last().unwrap().token; + let last_token = assign.position.0.last().unwrap().token(); ret.push_str(&format!( " {:path_width$} / {:pos_width$} @ {}:{}:{}\n", - path, - pos, + assign.path, + assign.position, last_token.source, last_token.line, last_token.column, @@ -608,9 +690,9 @@ impl SymbolTable { self.project_local_table.get(&prj).cloned() } - pub fn add_assign(&mut self, full_path: Vec, position: Vec) { + pub fn add_assign(&mut self, full_path: Vec, position: AssignPosition) { let assign = Assign { - full_path, + path: AssignPath(full_path), position, }; self.assign_list.push(assign); @@ -925,7 +1007,7 @@ pub fn get_project_local(prj: StrId) -> Option> { SYMBOL_TABLE.with(|f| f.borrow().get_project_local(prj)) } -pub fn add_assign(full_path: Vec, position: Vec) { +pub fn add_assign(full_path: Vec, position: AssignPosition) { SYMBOL_TABLE.with(|f| f.borrow_mut().add_assign(full_path, position)) } diff --git a/crates/analyzer/src/type_dag.rs b/crates/analyzer/src/type_dag.rs index a54dc2cf..64598bc7 100644 --- a/crates/analyzer/src/type_dag.rs +++ b/crates/analyzer/src/type_dag.rs @@ -6,7 +6,7 @@ use bimap::BiMap; use std::{cell::RefCell, collections::HashMap, collections::HashSet}; use daggy::{petgraph::algo, Dag, Walker}; -use veryl_parser::veryl_token::VerylToken; +use veryl_parser::veryl_token::Token; #[derive(Default)] pub struct TypeDag { @@ -22,7 +22,7 @@ pub struct TypeDag { pub struct TypeResolveInfo { pub path: SymbolPathNamespace, pub name: String, - pub token: VerylToken, + pub token: Token, } #[derive(Default, Clone, Copy, Debug, PartialOrd, Ord, PartialEq, Eq)] @@ -61,12 +61,12 @@ impl TypeDag { &mut self, path: &SymbolPathNamespace, id: &str, - token: &VerylToken, + token: &Token, ) -> Result { let trinfo = TypeResolveInfo { path: path.clone(), name: id.into(), - token: token.clone(), + token: *token, }; let sym = match symbol_table::resolve(&trinfo.path) { Ok(rr) => match rr.found { @@ -127,12 +127,12 @@ impl TypeDag { } } - fn toposort(&self) -> Vec { + fn toposort(&self) -> Vec { let nodes = algo::toposort(self.dag.graph(), None).unwrap(); let mut ret = vec![]; for node in nodes { if let Some(path) = self.paths.get(&(node.index() as u32)) { - ret.push(path.token.clone()); + ret.push(path.token); } } ret @@ -166,11 +166,7 @@ pub fn insert_edge(start: u32, end: u32, context: Context) -> Result<(), DagErro TYPE_DAG.with(|f| f.borrow_mut().insert_edge(start, end, context)) } -pub fn insert_node( - start: &SymbolPathNamespace, - id: &str, - token: &VerylToken, -) -> Result { +pub fn insert_node(start: &SymbolPathNamespace, id: &str, token: &Token) -> Result { TYPE_DAG.with(|f| f.borrow_mut().insert_node(start, id, token)) } @@ -178,7 +174,7 @@ pub fn get_symbol(node: u32) -> Symbol { TYPE_DAG.with(|f| f.borrow().get_symbol(node)) } -pub fn toposort() -> Vec { +pub fn toposort() -> Vec { TYPE_DAG.with(|f| f.borrow().toposort()) } diff --git a/crates/parser/src/veryl_token.rs b/crates/parser/src/veryl_token.rs index ce7397bc..49112af3 100644 --- a/crates/parser/src/veryl_token.rs +++ b/crates/parser/src/veryl_token.rs @@ -67,6 +67,13 @@ impl Token { } } +impl fmt::Display for Token { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let text = format!("{}", self.text); + text.fmt(f) + } +} + impl<'t> TryFrom<&parol_runtime::lexer::Token<'t>> for Token { type Error = anyhow::Error; fn try_from(x: &parol_runtime::lexer::Token<'t>) -> Result { @@ -138,6 +145,13 @@ pub struct VerylToken { } impl VerylToken { + pub fn new(token: Token) -> Self { + Self { + token, + comments: vec![], + } + } + pub fn replace(&self, text: &str) -> Self { let length = text.len(); let text = resource_table::insert_str(text); diff --git a/crates/veryl/src/cmd_build.rs b/crates/veryl/src/cmd_build.rs index 205649f0..27e64f25 100644 --- a/crates/veryl/src/cmd_build.rs +++ b/crates/veryl/src/cmd_build.rs @@ -126,7 +126,7 @@ impl CmdBuild { let mut ret = vec![]; let sorted_tokens = type_dag::toposort(); for token in sorted_tokens { - if let TokenSource::File(x) = token.token.source { + if let TokenSource::File(x) = token.source { let path = PathBuf::from(format!("{}", x)); if let Some(x) = table.remove(&path) { ret.push(x.clone()); diff --git a/testcases/sv/02_builtin_type.sv b/testcases/sv/02_builtin_type.sv index 9b4df6c2..2aa5ba60 100644 --- a/testcases/sv/02_builtin_type.sv +++ b/testcases/sv/02_builtin_type.sv @@ -1,31 +1,49 @@ module veryl_testcase_Module02; // unsigned integer int unsigned _a ; + always_comb _a = 1; longint unsigned _aa; + always_comb _aa = 1; // signed integer int signed _b ; + always_comb _b = 1; longint signed _bb; + always_comb _bb = 1; // floating point shortreal _c ; + always_comb _c = 1; real _cc; + always_comb _cc = 1; // 4 state (01xz) type logic _d ; + always_comb _d = 1; logic [10-1:0] _dd ; + always_comb _dd = 1; logic [10-1:0][10-1:0] _ddd; + always_comb _ddd = 1; // 2 state (01) type bit _e ; + always_comb _e = 1; bit [10-1:0] _ee ; + always_comb _ee = 1; bit [10-1:0][10-1:0] _eee; + always_comb _eee = 1; // array int unsigned _f [0:10-1]; + always_comb _f = 1; longint unsigned _ff [0:10-1]; + always_comb _ff = 1; int signed _fff [0:10-1]; + always_comb _fff = 1; longint signed _ffff [0:10-1]; + always_comb _ffff = 1; shortreal _fffff [0:10-1]; + always_comb _fffff = 1; real _ffffff [0:10-1]; + always_comb _ffffff = 1; endmodule diff --git a/testcases/sv/04_module.sv b/testcases/sv/04_module.sv index e0014b4c..7ed16b1f 100644 --- a/testcases/sv/04_module.sv +++ b/testcases/sv/04_module.sv @@ -18,8 +18,14 @@ module veryl_testcase_Module04 #( // variable declaration logic _d ; + always_comb _d = 1; logic [10-1:0] _dd ; + always_comb _dd = 1; bit [10-1:0][10-1:0] _ddd; + always_comb _ddd = 1; + + always_comb bb = 0; + always_comb bbb = 0; endmodule interface veryl_testcase_Interface04; diff --git a/testcases/sv/06_function.sv b/testcases/sv/06_function.sv index 5fe527c9..a3efdea8 100644 --- a/testcases/sv/06_function.sv +++ b/testcases/sv/06_function.sv @@ -38,8 +38,11 @@ module veryl_testcase_Module06; endfunction logic [ParamX-1:0] a; + always_comb a = 1; logic [ParamX-1:0] b; + always_comb b = 1; logic [ParamX-1:0] c; + always_comb c = 1; logic [ParamX-1:0] d; // function call diff --git a/testcases/sv/07_statement.sv b/testcases/sv/07_statement.sv index 7d52a0a0..178eaed0 100644 --- a/testcases/sv/07_statement.sv +++ b/testcases/sv/07_statement.sv @@ -2,6 +2,7 @@ module veryl_testcase_Module07; logic a ; logic aa ; logic clk; + always_comb clk = 1; always_comb begin // assignment statement diff --git a/testcases/sv/08_generate_declaration.sv b/testcases/sv/08_generate_declaration.sv index c338aa8c..21902e6d 100644 --- a/testcases/sv/08_generate_declaration.sv +++ b/testcases/sv/08_generate_declaration.sv @@ -1,7 +1,8 @@ module veryl_testcase_Module08; - logic a ; - logic b ; - logic i_clk; + localparam int unsigned a = 1; + localparam int unsigned b = 1; + logic i_clk; + always_comb i_clk = 1; // if declaration if (a == 1) begin :label diff --git a/testcases/sv/09_struct_enum.sv b/testcases/sv/09_struct_enum.sv index 40b983ef..dea57fb3 100644 --- a/testcases/sv/09_struct_enum.sv +++ b/testcases/sv/09_struct_enum.sv @@ -16,6 +16,8 @@ module veryl_testcase_Module09; A a; B b; - always_comb a.a = 1; - always_comb b = B_X; + always_comb a.a = 1; + always_comb a.aa = 1; + always_comb a.aaa = 1; + always_comb b = B_X; endmodule diff --git a/testcases/sv/10_various_line_comment.sv b/testcases/sv/10_various_line_comment.sv index 343a1007..b29dbfc8 100644 --- a/testcases/sv/10_various_line_comment.sv +++ b/testcases/sv/10_various_line_comment.sv @@ -21,6 +21,8 @@ module //a ; logic [2-1:0] up_down; + always_comb o_count = count; + always_comb // a begin up_down = // a diff --git a/testcases/sv/11_let.sv b/testcases/sv/11_let.sv index 11d985f0..cf375fd5 100644 --- a/testcases/sv/11_let.sv +++ b/testcases/sv/11_let.sv @@ -3,6 +3,7 @@ module veryl_testcase_Module11; logic b ; logic [10-1:0] bb ; bit [10-1:0][10-1:0] _bbb; + always_comb _bbb = 1; // variable declaration with assignment logic [10-1:0] _c; diff --git a/testcases/sv/12_always.sv b/testcases/sv/12_always.sv index fbc566be..2019cfec 100644 --- a/testcases/sv/12_always.sv +++ b/testcases/sv/12_always.sv @@ -5,7 +5,9 @@ module veryl_testcase_Module12 ( logic a ; logic aa; logic b ; + always_comb b = 1; logic c ; + always_comb c = 1; // always_ff declaration with default polarity always_ff @ (posedge i_clk, negedge i_rst) begin diff --git a/testcases/sv/13_range_operator.sv b/testcases/sv/13_range_operator.sv index 9a5a22ca..021ac39b 100644 --- a/testcases/sv/13_range_operator.sv +++ b/testcases/sv/13_range_operator.sv @@ -1,6 +1,7 @@ module veryl_testcase_Module13; logic a; logic X; + always_comb X = 1; // bit select always_comb a = X[0]; diff --git a/testcases/sv/14_inst.sv b/testcases/sv/14_inst.sv index 81197be7..c0b5f4e6 100644 --- a/testcases/sv/14_inst.sv +++ b/testcases/sv/14_inst.sv @@ -1,7 +1,10 @@ module veryl_testcase_Module14; logic a ; + always_comb a = 1; logic aa ; + always_comb aa = 1; logic bbb; + always_comb bbb = 1; // module instantiation veryl_testcase_Module14B x (); diff --git a/testcases/sv/15_named_block.sv b/testcases/sv/15_named_block.sv index a9b349ae..53693591 100644 --- a/testcases/sv/15_named_block.sv +++ b/testcases/sv/15_named_block.sv @@ -1,11 +1,14 @@ module veryl_testcase_Module15; logic _a; + always_comb _a = 1; if (1) begin :label logic _a; + always_comb _a = 1; end if (1) begin :label1 logic _a; + always_comb _a = 1; end endmodule diff --git a/testcases/sv/16_case.sv b/testcases/sv/16_case.sv index fb3214a7..155532e1 100644 --- a/testcases/sv/16_case.sv +++ b/testcases/sv/16_case.sv @@ -1,7 +1,9 @@ module veryl_testcase_Module16; logic a; logic x; + always_comb x = 1; logic y; + always_comb y = 1; always_comb begin case (x) diff --git a/testcases/sv/18_concatenation.sv b/testcases/sv/18_concatenation.sv index 586667e2..7a8527f4 100644 --- a/testcases/sv/18_concatenation.sv +++ b/testcases/sv/18_concatenation.sv @@ -1,6 +1,7 @@ module veryl_testcase_Module18; logic a; logic b; + always_comb b = 1; always_comb a = {a[10:0], b}; always_comb a = {{10{a[10:0]}}, {4{b}}}; diff --git a/testcases/sv/20_if_case_expression.sv b/testcases/sv/20_if_case_expression.sv index 0ad6c402..b94915af 100644 --- a/testcases/sv/20_if_case_expression.sv +++ b/testcases/sv/20_if_case_expression.sv @@ -2,7 +2,9 @@ module veryl_testcase_Module20; logic a; logic b; logic x; + always_comb x = 1; logic y; + always_comb y = 1; always_comb a = ((x) ? ( 1 diff --git a/testcases/sv/21_cast.sv b/testcases/sv/21_cast.sv index 86daf3c0..deb240d4 100644 --- a/testcases/sv/21_cast.sv +++ b/testcases/sv/21_cast.sv @@ -1,6 +1,7 @@ module veryl_testcase_Module21; logic a; logic b; + always_comb b = 1; typedef enum logic { EnumA_A, diff --git a/testcases/sv/22_type_modifier.sv b/testcases/sv/22_type_modifier.sv index c3b3507d..ce78d84a 100644 --- a/testcases/sv/22_type_modifier.sv +++ b/testcases/sv/22_type_modifier.sv @@ -1,6 +1,10 @@ module veryl_testcase_Module22; logic signed [10-1:0] _a; + always_comb _a = 1; tri logic signed [10-1:0] _b; + always_comb _b = 1; tri logic signed [10-1:0] _c; + always_comb _c = 1; logic [10-1:0] _d; + always_comb _d = 1; endmodule diff --git a/testcases/sv/23_ifdef.sv b/testcases/sv/23_ifdef.sv index 67d3163d..74d19a0a 100644 --- a/testcases/sv/23_ifdef.sv +++ b/testcases/sv/23_ifdef.sv @@ -26,11 +26,14 @@ module veryl_testcase_Module23 #( `ifdef DEFINE_A `ifdef DEFINE_B logic [10-1:0] _a; + always_comb _a = 1; `endif `endif `ifdef DEFINE_A logic [10-1:0] _b; + always_comb _b = 1; logic [10-1:0] _c; + always_comb _c = 1; `endif endmodule diff --git a/testcases/sv/24_sv_attribute.sv b/testcases/sv/24_sv_attribute.sv index 720409fa..75334046 100644 --- a/testcases/sv/24_sv_attribute.sv +++ b/testcases/sv/24_sv_attribute.sv @@ -1,6 +1,8 @@ module veryl_testcase_Module24; (* ram_style="block" *) logic _a; + always_comb _a = 1; (* mark_debug="true" *) logic _b; + always_comb _b = 1; endmodule diff --git a/testcases/sv/26_array.sv b/testcases/sv/26_array.sv index 93044352..722ac6d1 100644 --- a/testcases/sv/26_array.sv +++ b/testcases/sv/26_array.sv @@ -1,6 +1,10 @@ module veryl_testcase_Module26; logic [10-1:0] _a ; + always_comb _a = 1; logic [10-1:0][10-1:0] _b ; + always_comb _b = 1; logic [10-1:0][10-1:0] _c [0:10-1] ; + always_comb _c = 1; logic [10-1:0][10-1:0] _d [0:10-1][0:10-1]; + always_comb _d = 1; endmodule diff --git a/testcases/sv/28_msblsb.sv b/testcases/sv/28_msblsb.sv index 55bb6996..e7e73d51 100644 --- a/testcases/sv/28_msblsb.sv +++ b/testcases/sv/28_msblsb.sv @@ -3,7 +3,9 @@ module veryl_testcase_Module28; localparam int unsigned WIDTH1 = 20; logic [10-1:0][20-1:0] a; + always_comb a = 1; logic [WIDTH0 + 10-1:0][WIDTH1-1:0] b; + always_comb b = 1; logic _x; always_comb _x = a[((10) - 1)][((20) - 1):0 + 1]; diff --git a/testcases/sv/29_allow.sv b/testcases/sv/29_allow.sv index 9fa84ec7..7fdcd8cf 100644 --- a/testcases/sv/29_allow.sv +++ b/testcases/sv/29_allow.sv @@ -5,6 +5,7 @@ module veryl_testcase_Module29 ( logic a; logic b; logic c; + always_comb c = 1; always_ff @ (posedge clk, negedge rst) begin if (!rst) begin a <= 0; diff --git a/testcases/sv/35_unconnected_port.sv b/testcases/sv/35_unconnected_port.sv index d577711b..51889ac0 100644 --- a/testcases/sv/35_unconnected_port.sv +++ b/testcases/sv/35_unconnected_port.sv @@ -1,5 +1,6 @@ module veryl_testcase_Module35; logic aa; + always_comb aa = 1; veryl_testcase_Module35B xx ( .aa (aa), diff --git a/testcases/sv/36_doc_comment.sv b/testcases/sv/36_doc_comment.sv index ec73bb0e..a515c218 100644 --- a/testcases/sv/36_doc_comment.sv +++ b/testcases/sv/36_doc_comment.sv @@ -12,6 +12,7 @@ module veryl_testcase_Module36 #( input logic [ParamA-1:0] i_data , /// Data input output logic [ParamA-1:0] o_data /// Data output ); + always_comb o_data = 0; endmodule /// Test interface for doc comment diff --git a/testcases/sv/45_let_in_always.sv b/testcases/sv/45_let_in_always.sv index 80114c7f..ff28ce19 100644 --- a/testcases/sv/45_let_in_always.sv +++ b/testcases/sv/45_let_in_always.sv @@ -1,5 +1,6 @@ module veryl_testcase_Module45; logic a; + always_comb a = 1; logic [10-1:0] b; logic [10-1:0] c; diff --git a/testcases/sv/46_let_anywhere.sv b/testcases/sv/46_let_anywhere.sv index a12226c3..f25e8751 100644 --- a/testcases/sv/46_let_anywhere.sv +++ b/testcases/sv/46_let_anywhere.sv @@ -1,5 +1,6 @@ module veryl_testcase_Module46; logic a; + always_comb a = 1; logic [10-1:0] b; logic [10-1:0] c; logic [10-1:0] d; diff --git a/testcases/veryl/02_builtin_type.veryl b/testcases/veryl/02_builtin_type.veryl index ae22ab95..959fa40e 100644 --- a/testcases/veryl/02_builtin_type.veryl +++ b/testcases/veryl/02_builtin_type.veryl @@ -1,31 +1,31 @@ module Module02 { // unsigned integer - var _a : u32; - var _aa: u64; + let _a : u32 = 1; + let _aa: u64 = 1; // signed integer - var _b : i32; - var _bb: i64; + let _b : i32 = 1; + let _bb: i64 = 1; // floating point - var _c : f32; - var _cc: f64; + let _c : f32 = 1; + let _cc: f64 = 1; // 4 state (01xz) type - var _d : logic ; - var _dd : logic<10> ; - var _ddd: logic<10, 10>; + let _d : logic = 1; + let _dd : logic<10> = 1; + let _ddd: logic<10, 10> = 1; // 2 state (01) type - var _e : bit ; - var _ee : bit<10> ; - var _eee: bit<10, 10>; + let _e : bit = 1; + let _ee : bit<10> = 1; + let _eee: bit<10, 10> = 1; // array - var _f : u32 [10]; - var _ff : u64 [10]; - var _fff : i32 [10]; - var _ffff : i64 [10]; - var _fffff : f32 [10]; - var _ffffff: f64 [10]; + let _f : u32 [10] = 1; + let _ff : u64 [10] = 1; + let _fff : i32 [10] = 1; + let _ffff : i64 [10] = 1; + let _fffff : f32 [10] = 1; + let _ffffff: f64 [10] = 1; } diff --git a/testcases/veryl/04_module.veryl b/testcases/veryl/04_module.veryl index 536de800..d9e11c5a 100644 --- a/testcases/veryl/04_module.veryl +++ b/testcases/veryl/04_module.veryl @@ -17,9 +17,12 @@ module Module04 #( local cc: u64 = 1; // variable declaration - var _d : logic ; - var _dd : logic<10> ; - var _ddd: bit <10, 10>; + let _d : logic = 1; + let _dd : logic<10> = 1; + let _ddd: bit <10, 10> = 1; + + assign bb = 0; + assign bbb = 0; } interface Interface04 { diff --git a/testcases/veryl/06_function.veryl b/testcases/veryl/06_function.veryl index b0db00c2..dbf7d4a8 100644 --- a/testcases/veryl/06_function.veryl +++ b/testcases/veryl/06_function.veryl @@ -34,9 +34,9 @@ module Module06 { c = a / 1; } - var a: logic; - var b: logic; - var c: logic; + let a: logic = 1; + let b: logic = 1; + let c: logic = 1; var d: logic; // function call diff --git a/testcases/veryl/07_statement.veryl b/testcases/veryl/07_statement.veryl index 404c09c0..79fbb01a 100644 --- a/testcases/veryl/07_statement.veryl +++ b/testcases/veryl/07_statement.veryl @@ -1,7 +1,7 @@ module Module07 { var a : logic; var aa : logic; - var clk: logic; + let clk: logic = 1; always_comb { // assignment statement diff --git a/testcases/veryl/08_generate_declaration.veryl b/testcases/veryl/08_generate_declaration.veryl index 47e0b3bf..35eec16e 100644 --- a/testcases/veryl/08_generate_declaration.veryl +++ b/testcases/veryl/08_generate_declaration.veryl @@ -1,7 +1,7 @@ module Module08 { - var a : logic; - var b : logic; - var i_clk: logic; + local a : u32 = 1; + local b : u32 = 1; + let i_clk: logic = 1; // if declaration if a == 1 :label { diff --git a/testcases/veryl/09_struct_enum.veryl b/testcases/veryl/09_struct_enum.veryl index 560bef2e..8304841a 100644 --- a/testcases/veryl/09_struct_enum.veryl +++ b/testcases/veryl/09_struct_enum.veryl @@ -16,6 +16,8 @@ module Module09 { var a: A; var b: B; - assign a.a = 1; - assign b = B::X; + assign a.a = 1; + assign a.aa = 1; + assign a.aaa = 1; + assign b = B::X; } diff --git a/testcases/veryl/10_various_line_comment.veryl b/testcases/veryl/10_various_line_comment.veryl index 448b4c91..2afcb5f6 100644 --- a/testcases/veryl/10_various_line_comment.veryl +++ b/testcases/veryl/10_various_line_comment.veryl @@ -20,6 +20,8 @@ module //a ; var up_down: logic<2>; + assign o_count = count; + always_comb // a { up_down = // a diff --git a/testcases/veryl/11_let.veryl b/testcases/veryl/11_let.veryl index 5295e74a..12e2e4e8 100644 --- a/testcases/veryl/11_let.veryl +++ b/testcases/veryl/11_let.veryl @@ -2,7 +2,7 @@ module Module11 { // variable declaration var b : logic ; var bb : logic<10> ; - var _bbb: bit <10, 10>; + let _bbb: bit <10, 10> = 1; // variable declaration with assignment let _c: logic<10> = 1; diff --git a/testcases/veryl/12_always.veryl b/testcases/veryl/12_always.veryl index 26a95438..ae8d85b2 100644 --- a/testcases/veryl/12_always.veryl +++ b/testcases/veryl/12_always.veryl @@ -4,8 +4,8 @@ module Module12 ( ) { var a : logic; var aa: logic; - var b : logic; - var c : logic; + let b : logic = 1; + let c : logic = 1; // always_ff declaration with default polarity always_ff (i_clk, i_rst) { diff --git a/testcases/veryl/13_range_operator.veryl b/testcases/veryl/13_range_operator.veryl index 129b36d5..00a63d6a 100644 --- a/testcases/veryl/13_range_operator.veryl +++ b/testcases/veryl/13_range_operator.veryl @@ -1,6 +1,6 @@ module Module13 { var a: logic; - var X: logic; + let X: logic = 1; // bit select assign a = X[0]; diff --git a/testcases/veryl/14_inst.veryl b/testcases/veryl/14_inst.veryl index 17f0f0e3..c5ad3378 100644 --- a/testcases/veryl/14_inst.veryl +++ b/testcases/veryl/14_inst.veryl @@ -1,7 +1,7 @@ module Module14 { - var a : logic; - var aa : logic; - var bbb: logic; + let a : logic = 1; + let aa : logic = 1; + let bbb: logic = 1; // module instantiation inst x: Module14B; diff --git a/testcases/veryl/15_named_block.veryl b/testcases/veryl/15_named_block.veryl index e2f59141..c41f4e3e 100644 --- a/testcases/veryl/15_named_block.veryl +++ b/testcases/veryl/15_named_block.veryl @@ -1,11 +1,11 @@ module Module15 { - var _a: logic; + let _a: logic = 1; :label { - var _a: logic; + let _a: logic = 1; } :label1 { - var _a: logic; + let _a: logic = 1; } } diff --git a/testcases/veryl/16_case.veryl b/testcases/veryl/16_case.veryl index e15cf5a9..19122ce7 100644 --- a/testcases/veryl/16_case.veryl +++ b/testcases/veryl/16_case.veryl @@ -1,7 +1,7 @@ module Module16 { var a: logic; - var x: logic; - var y: logic; + let x: logic = 1; + let y: logic = 1; always_comb { case x { diff --git a/testcases/veryl/18_concatenation.veryl b/testcases/veryl/18_concatenation.veryl index 853fd206..4540cdd4 100644 --- a/testcases/veryl/18_concatenation.veryl +++ b/testcases/veryl/18_concatenation.veryl @@ -1,6 +1,6 @@ module Module18 { var a: logic; - var b: logic; + let b: logic = 1; assign a = {a[10:0], b}; assign a = {a[10:0] repeat 10, b repeat 4}; diff --git a/testcases/veryl/20_if_case_expression.veryl b/testcases/veryl/20_if_case_expression.veryl index 159c8117..8fb194a7 100644 --- a/testcases/veryl/20_if_case_expression.veryl +++ b/testcases/veryl/20_if_case_expression.veryl @@ -1,8 +1,8 @@ module Module20 { var a: logic; var b: logic; - var x: logic; - var y: logic; + let x: logic = 1; + let y: logic = 1; assign a = if x { 1 diff --git a/testcases/veryl/21_cast.veryl b/testcases/veryl/21_cast.veryl index 42c55b39..cc794c8d 100644 --- a/testcases/veryl/21_cast.veryl +++ b/testcases/veryl/21_cast.veryl @@ -1,6 +1,6 @@ module Module21 { var a: logic; - var b: logic; + let b: logic = 1; enum EnumA: logic { A, diff --git a/testcases/veryl/22_type_modifier.veryl b/testcases/veryl/22_type_modifier.veryl index f2317151..5d803554 100644 --- a/testcases/veryl/22_type_modifier.veryl +++ b/testcases/veryl/22_type_modifier.veryl @@ -1,6 +1,6 @@ module Module22 { - var _a: signed logic <10>; - var _b: tri signed logic<10>; - var _c: signed tri logic<10>; - var _d: logic <10>; + let _a: signed logic <10> = 1; + let _b: tri signed logic<10> = 1; + let _c: signed tri logic<10> = 1; + let _d: logic <10> = 1; } diff --git a/testcases/veryl/23_ifdef.veryl b/testcases/veryl/23_ifdef.veryl index 43c66523..7f583c60 100644 --- a/testcases/veryl/23_ifdef.veryl +++ b/testcases/veryl/23_ifdef.veryl @@ -21,12 +21,12 @@ module Module23 #( ) { #[ifdef(DEFINE_A)] #[ifdef(DEFINE_B)] - var _a: logic<10>; + let _a: logic<10> = 1; #[ifdef(DEFINE_A)] { - var _b: logic<10>; - var _c: logic<10>; + let _b: logic<10> = 1; + let _c: logic<10> = 1; } } diff --git a/testcases/veryl/24_sv_attribute.veryl b/testcases/veryl/24_sv_attribute.veryl index a9a1a52d..44b2429e 100644 --- a/testcases/veryl/24_sv_attribute.veryl +++ b/testcases/veryl/24_sv_attribute.veryl @@ -1,6 +1,6 @@ module Module24 { #[sv("ram_style=\"block\"")] - var _a: logic; + let _a: logic = 1; #[sv("mark_debug=\"true\"")] - var _b: logic; + let _b: logic = 1; } diff --git a/testcases/veryl/26_array.veryl b/testcases/veryl/26_array.veryl index 3be83541..e9d713aa 100644 --- a/testcases/veryl/26_array.veryl +++ b/testcases/veryl/26_array.veryl @@ -1,6 +1,6 @@ module Module26 { - var _a: logic<10> ; - var _b: logic<10, 10> ; - var _c: logic<10, 10> [10] ; - var _d: logic<10, 10> [10, 10]; + let _a: logic<10> = 1; + let _b: logic<10, 10> = 1; + let _c: logic<10, 10> [10] = 1; + let _d: logic<10, 10> [10, 10] = 1; } diff --git a/testcases/veryl/28_msblsb.veryl b/testcases/veryl/28_msblsb.veryl index 60198222..6f11c101 100644 --- a/testcases/veryl/28_msblsb.veryl +++ b/testcases/veryl/28_msblsb.veryl @@ -2,8 +2,8 @@ module Module28 { local WIDTH0: u32 = 10; local WIDTH1: u32 = 20; - var a: logic<10, 20> ; - var b: logic; + let a: logic<10, 20> = 1; + let b: logic = 1; let _x: logic = a[msb][msb:lsb + 1]; let _y: logic = b[msb - 3][msb + 5:lsb]; diff --git a/testcases/veryl/29_allow.veryl b/testcases/veryl/29_allow.veryl index 002eec44..cd2a851e 100644 --- a/testcases/veryl/29_allow.veryl +++ b/testcases/veryl/29_allow.veryl @@ -5,7 +5,7 @@ module Module29 ( var a: logic; var b: logic; #[allow(unused_variable)] - var c: logic; + let c: logic = 1; #[allow(missing_reset_statement)] always_ff (clk, rst) { diff --git a/testcases/veryl/35_unconnected_port.veryl b/testcases/veryl/35_unconnected_port.veryl index b6b63401..7cc9b077 100644 --- a/testcases/veryl/35_unconnected_port.veryl +++ b/testcases/veryl/35_unconnected_port.veryl @@ -1,5 +1,5 @@ module Module35 { - var aa: logic; + let aa: logic = 1; inst xx: Module35B ( aa , diff --git a/testcases/veryl/36_doc_comment.veryl b/testcases/veryl/36_doc_comment.veryl index da3b062a..514ea364 100644 --- a/testcases/veryl/36_doc_comment.veryl +++ b/testcases/veryl/36_doc_comment.veryl @@ -11,7 +11,9 @@ pub module Module36 #( i_rst_n: input logic , /// Reset i_data : input logic, /// Data input o_data : output logic, /// Data output -) {} +) { + assign o_data = 0; +} /// Test interface for doc comment /// diff --git a/testcases/veryl/45_let_in_always.veryl b/testcases/veryl/45_let_in_always.veryl index e71056fb..34f950ba 100644 --- a/testcases/veryl/45_let_in_always.veryl +++ b/testcases/veryl/45_let_in_always.veryl @@ -1,5 +1,5 @@ module Module45 { - var a: logic ; + let a: logic = 1; var b: logic<10>; var c: logic<10>; diff --git a/testcases/veryl/46_let_anywhere.veryl b/testcases/veryl/46_let_anywhere.veryl index 41b1921d..41efa842 100644 --- a/testcases/veryl/46_let_anywhere.veryl +++ b/testcases/veryl/46_let_anywhere.veryl @@ -1,5 +1,5 @@ module Module46 { - var a: logic ; + let a: logic = 1; var b: logic<10>; var c: logic<10>; var d: logic<10>;