Skip to content

Commit

Permalink
Merge pull request #893 from veryl-lang/check_sv_reset
Browse files Browse the repository at this point in the history
Check reset connection to SV module
  • Loading branch information
dalance authored Aug 16, 2024
2 parents b62047c + 66a7e46 commit fd86245
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 3 deletions.
23 changes: 22 additions & 1 deletion crates/analyzer/src/analyzer_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ pub enum AnalyzerError {
},

#[diagnostic(severity(Error), code(invalid_cast), help(""), url(""))]
#[error("Casting from #{from} to #{to} is incompatible")]
#[error("Casting from {from} to {to} is incompatible")]
InvalidCast {
from: String,
to: String,
Expand Down Expand Up @@ -568,6 +568,20 @@ pub enum AnalyzerError {
error_location: SourceSpan,
},

#[diagnostic(
severity(Error),
code(sv_with_implicit_reset),
help("Use types with explicit synchronisity and polarity like `reset_async_low`"),
url("https://doc.veryl-lang.org/book/07_appendix/02_semantic_error.html#sv_with_implicit_reset")
)]
#[error("Reset type with implicit synchronisity and polarity can't be connected to SystemVerilog module")]
SvWithImplicitReset {
#[source_code]
input: NamedSource<String>,
#[label("Error location")]
error_location: SourceSpan,
},

#[diagnostic(
severity(Error),
code(too_large_enum_variant),
Expand Down Expand Up @@ -1274,6 +1288,13 @@ impl AnalyzerError {
}
}

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

pub fn too_large_enum_variant(
identifier: &str,
value: isize,
Expand Down
28 changes: 26 additions & 2 deletions crates/analyzer/src/handlers/check_assignment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::assign::{
use crate::attribute::AllowItem;
use crate::attribute::Attribute as Attr;
use crate::attribute_table;
use crate::symbol::{Direction, SymbolId, SymbolKind};
use crate::symbol::{Direction, SymbolId, SymbolKind, TypeKind};
use crate::symbol_table;
use std::collections::HashMap;
use veryl_parser::veryl_grammar_trait::*;
Expand Down Expand Up @@ -390,14 +390,18 @@ impl<'a> VerylGrammarTrait for CheckAssignment<'a> {
// get port property
let mut ports = HashMap::new();
let mut port_unknown = false;
let mut sv_instance = false;
if let Ok(x) = symbol_table::resolve((&x.type_name, &symbol.found.namespace)) {
match x.found.kind {
SymbolKind::Module(ref x) => {
for port in &x.ports {
ports.insert(port.name, port.property());
}
}
SymbolKind::SystemVerilog => port_unknown = true,
SymbolKind::SystemVerilog => {
port_unknown = true;
sv_instance = true;
}
// TODO this should be removed after implementing bounded generic
// parameter
SymbolKind::GenericParameter(_) => port_unknown = true,
Expand Down Expand Up @@ -471,6 +475,26 @@ impl<'a> VerylGrammarTrait for CheckAssignment<'a> {
&token.into(),
));
}

// Check implicit reset to SV instance
let is_implicit_reset = match &symbol.found.kind {
SymbolKind::Port(x) => {
if let Some(x) = &x.r#type {
x.kind == TypeKind::Reset
} else {
false
}
}
SymbolKind::Variable(x) => x.r#type.kind == TypeKind::Reset,
_ => false,
};

if sv_instance && is_implicit_reset {
self.errors.push(AnalyzerError::sv_with_implicit_reset(
self.text,
&token.into(),
));
}
}
}
}
Expand Down
17 changes: 17 additions & 0 deletions crates/analyzer/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,23 @@ impl Symbol {
Evaluated::Unknown
}
}
SymbolKind::Port(x) => {
if let Some(x) = &x.r#type {
match x.kind {
TypeKind::Clock => Evaluated::Clock,
TypeKind::ClockPosedge => Evaluated::ClockPosedge,
TypeKind::ClockNegedge => Evaluated::ClockNegedge,
TypeKind::Reset => Evaluated::Reset,
TypeKind::ResetAsyncHigh => Evaluated::ResetAsyncHigh,
TypeKind::ResetAsyncLow => Evaluated::ResetAsyncLow,
TypeKind::ResetSyncHigh => Evaluated::ResetSyncHigh,
TypeKind::ResetSyncLow => Evaluated::ResetSyncLow,
_ => Evaluated::Unknown,
}
} else {
Evaluated::Unknown
}
}
SymbolKind::Parameter(x) => {
let mut evaluator = Evaluator::new();
if let Some(width) = evaluator.type_width(x.r#type.clone()) {
Expand Down
32 changes: 32 additions & 0 deletions crates/analyzer/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2159,6 +2159,38 @@ fn sv_keyword_usage() {
assert!(matches!(errors[0], AnalyzerError::SvKeywordUsage { .. }));
}

#[test]
fn sv_with_implicit_reset() {
let code = r#"
module ModuleA {
var rst: reset;
inst u: $sv::Module (
rst,
);
}
"#;

let errors = analyze(code);
assert!(matches!(
errors[0],
AnalyzerError::SvWithImplicitReset { .. }
));

let code = r#"
module ModuleB {
var rst: reset_async_low;
inst u: $sv::Module (
rst,
);
}
"#;

let errors = analyze(code);
assert!(errors.is_empty());
}

#[test]
fn conflict_with_mangled_enum_member() {
let code = r#"
Expand Down

0 comments on commit fd86245

Please sign in to comment.