Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support importing functions into modport #742

Merged
merged 1 commit into from
Jun 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions crates/analyzer/src/analyzer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ fn is_assignable(direction: &Direction) -> bool {
fn must_be_assigned(kind: &SymbolKind) -> bool {
match kind {
SymbolKind::Port(x) => x.direction == Direction::Output,
SymbolKind::ModportMember(x) => x.direction == Direction::Output,
SymbolKind::ModportVariableMember(x) => x.direction == Direction::Output,
SymbolKind::Variable(_) => true,
SymbolKind::StructMember(_) => true,
_ => false,
Expand Down Expand Up @@ -378,7 +378,7 @@ fn traverse_type_symbol(id: SymbolId, path: &AssignPath) -> Vec<AssignPath> {
}
return ret;
}
SymbolKind::ModportMember(x) if is_assignable(&x.direction) => {
SymbolKind::ModportVariableMember(x) if is_assignable(&x.direction) => {
if let Ok(symbol) = symbol_table::resolve(&symbol.token) {
return traverse_type_symbol(symbol.found.id, path);
}
Expand Down
54 changes: 54 additions & 0 deletions crates/analyzer/src/analyzer_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,36 @@ pub enum AnalyzerError {
error_location: SourceSpan,
},

#[diagnostic(
severity(Error),
code(invalid_modport_variable_item),
help(""),
url("")
)]
#[error("#{identifier} is not a variable")]
InvalidModportVariableItem {
identifier: String,
#[source_code]
input: NamedSource,
#[label("Error location")]
error_location: SourceSpan,
},

#[diagnostic(
severity(Error),
code(invalid_modport_function_item),
help(""),
url("")
)]
#[error("#{identifier} is not a function")]
InvalidModportFunctionItem {
identifier: String,
#[source_code]
input: NamedSource,
#[label("Error location")]
error_location: SourceSpan,
},

#[diagnostic(
severity(Error),
code(missing_default_argument),
Expand Down Expand Up @@ -855,6 +885,30 @@ impl AnalyzerError {
}
}

pub fn invalid_modport_variable_item(
identifier: &str,
source: &str,
token: &TokenRange,
) -> Self {
AnalyzerError::InvalidModportVariableItem {
identifier: identifier.into(),
input: AnalyzerError::named_source(source, token),
error_location: token.into(),
}
}

pub fn invalid_modport_function_item(
identifier: &str,
source: &str,
token: &TokenRange,
) -> Self {
AnalyzerError::InvalidModportFunctionItem {
identifier: identifier.into(),
input: AnalyzerError::named_source(source, token),
error_location: token.into(),
}
}

pub fn missing_default_argument(identifier: &str, source: &str, token: &TokenRange) -> Self {
AnalyzerError::MissingDefaultArgument {
identifier: identifier.into(),
Expand Down
6 changes: 6 additions & 0 deletions crates/analyzer/src/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ pub mod check_enum;
pub mod check_function;
pub mod check_identifier;
pub mod check_instance;
pub mod check_modport;
pub mod check_msb_lsb;
pub mod check_number;
pub mod check_statement;
Expand All @@ -21,6 +22,7 @@ use check_enum::*;
use check_function::*;
use check_identifier::*;
use check_instance::*;
use check_modport::*;
use check_msb_lsb::*;
use check_number::*;
use check_statement::*;
Expand Down Expand Up @@ -83,6 +85,7 @@ impl<'a> Pass1Handlers<'a> {

pub struct Pass2Handlers<'a> {
check_enum: CheckEnum<'a>,
check_modport: CheckModport<'a>,
check_function: CheckFunction<'a>,
check_instance: CheckInstance<'a>,
check_msb_lsb: CheckMsbLsb<'a>,
Expand All @@ -96,6 +99,7 @@ impl<'a> Pass2Handlers<'a> {
pub fn new(text: &'a str, _build_opt: &'a Build, _lint_opt: &'a Lint) -> Self {
Self {
check_enum: CheckEnum::new(text),
check_modport: CheckModport::new(text),
check_function: CheckFunction::new(text),
check_instance: CheckInstance::new(text),
check_msb_lsb: CheckMsbLsb::new(text),
Expand All @@ -109,6 +113,7 @@ impl<'a> Pass2Handlers<'a> {
pub fn get_handlers(&mut self) -> Vec<&mut dyn Handler> {
vec![
&mut self.check_enum as &mut dyn Handler,
&mut self.check_modport as &mut dyn Handler,
&mut self.check_function as &mut dyn Handler,
&mut self.check_instance as &mut dyn Handler,
&mut self.check_msb_lsb as &mut dyn Handler,
Expand All @@ -122,6 +127,7 @@ impl<'a> Pass2Handlers<'a> {
pub fn get_errors(&mut self) -> Vec<AnalyzerError> {
let mut ret = Vec::new();
ret.append(&mut self.check_enum.errors);
ret.append(&mut self.check_modport.errors);
ret.append(&mut self.check_function.errors);
ret.append(&mut self.check_instance.errors);
ret.append(&mut self.check_msb_lsb.errors);
Expand Down
6 changes: 3 additions & 3 deletions crates/analyzer/src/handlers/check_assignment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,9 @@ fn can_assign(full_path: &[SymbolId]) -> bool {
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,
SymbolKind::ModportVariableMember(x) if x.direction == Direction::Output => true,
SymbolKind::ModportVariableMember(x) if x.direction == Direction::Ref => true,
SymbolKind::ModportVariableMember(x) if x.direction == Direction::Inout => true,
_ => false,
};
if can_assign {
Expand Down
20 changes: 19 additions & 1 deletion crates/analyzer/src/handlers/check_direction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ pub struct CheckDirection<'a> {
point: HandlerPoint,
in_function: bool,
in_module: bool,
in_modport: bool,
}

impl<'a> CheckDirection<'a> {
Expand Down Expand Up @@ -66,14 +67,23 @@ impl<'a> VerylGrammarTrait for CheckDirection<'a> {
}
}
Direction::Modport(x) => {
if !self.in_module {
if !self.in_module || self.in_function {
self.errors.push(AnalyzerError::invalid_direction(
"modport",
self.text,
&x.modport.modport_token.token.into(),
));
}
}
Direction::Import(x) => {
if !self.in_modport {
self.errors.push(AnalyzerError::invalid_direction(
"import",
self.text,
&x.import.import_token.token.into(),
));
}
}
_ => (),
}
}
Expand All @@ -95,4 +105,12 @@ impl<'a> VerylGrammarTrait for CheckDirection<'a> {
}
Ok(())
}

fn modport_declaration(&mut self, _arg: &ModportDeclaration) -> Result<(), ParolError> {
match self.point {
HandlerPoint::Before => self.in_modport = true,
HandlerPoint::After => self.in_modport = false,
}
Ok(())
}
}
25 changes: 20 additions & 5 deletions crates/analyzer/src/handlers/check_function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,14 @@ impl<'a> VerylGrammarTrait for CheckFunction<'a> {
}

if let Ok(symbol) = symbol_table::resolve(arg.expression_identifier.as_ref()) {
if let SymbolKind::Function(x) = symbol.found.kind {
let function_symbol = match symbol.found.kind {
SymbolKind::Function(_) => symbol.found,
SymbolKind::ModportFunctionMember(x) => {
symbol_table::get(x.function).unwrap()
}
_ => return Ok(()),
};
if let SymbolKind::Function(x) = function_symbol.kind {
if x.ret.is_some() {
let name = format!(
"{}",
Expand Down Expand Up @@ -86,10 +93,18 @@ impl<'a> VerylGrammarTrait for CheckFunction<'a> {
}

if let Ok(symbol) = symbol_table::resolve(x.expression_identifier.as_ref()) {
let arity = if let SymbolKind::Function(x) = symbol.found.kind {
Some(x.ports.len())
} else {
None
let arity = match symbol.found.kind {
SymbolKind::Function(x) => Some(x.ports.len()),
SymbolKind::ModportFunctionMember(x) => {
if let SymbolKind::Function(x) =
symbol_table::get(x.function).unwrap().kind
{
Some(x.ports.len())
} else {
unreachable!();
}
}
_ => None,
};

let mut args = 0;
Expand Down
61 changes: 61 additions & 0 deletions crates/analyzer/src/handlers/check_modport.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
use crate::analyzer_error::AnalyzerError;
use crate::symbol::SymbolKind;
use crate::symbol_table;
use veryl_parser::veryl_grammar_trait::*;
use veryl_parser::veryl_walker::{Handler, HandlerPoint};
use veryl_parser::ParolError;

pub struct CheckModport<'a> {
pub errors: Vec<AnalyzerError>,
text: &'a str,
point: HandlerPoint,
}

impl<'a> CheckModport<'a> {
pub fn new(text: &'a str) -> Self {
Self {
errors: Vec::new(),
text,
point: HandlerPoint::Before,
}
}
}

impl<'a> Handler for CheckModport<'a> {
fn set_point(&mut self, p: HandlerPoint) {
self.point = p;
}
}

impl<'a> VerylGrammarTrait for CheckModport<'a> {
fn modport_item(&mut self, arg: &ModportItem) -> Result<(), ParolError> {
if let HandlerPoint::Before = self.point {
if let Ok(symbol) = symbol_table::resolve(arg.identifier.as_ref()) {
match &*arg.direction {
Direction::Ref(_) | Direction::Modport(_) => {}
Direction::Import(_) => {
if !matches!(symbol.found.kind, SymbolKind::Function(_)) {
self.errors
.push(AnalyzerError::invalid_modport_function_item(
&arg.identifier.identifier_token.token.to_string(),
self.text,
&arg.identifier.as_ref().into(),
));
}
}
_ => {
if !matches!(symbol.found.kind, SymbolKind::Variable(_)) {
self.errors
.push(AnalyzerError::invalid_modport_variable_item(
&arg.identifier.identifier_token.token.to_string(),
self.text,
&arg.identifier.as_ref().into(),
));
}
}
}
}
}
Ok(())
}
}
Loading
Loading