From 47c351702279558140cb3270e2ec675e58212d89 Mon Sep 17 00:00:00 2001 From: Ronit Nallagatla Date: Wed, 31 Jan 2024 15:23:31 -0500 Subject: [PATCH 01/25] added explanation --- ...taxrules-explanation-implicit_case_default.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 md/syntaxrules-explanation-implicit_case_default.md diff --git a/md/syntaxrules-explanation-implicit_case_default.md b/md/syntaxrules-explanation-implicit_case_default.md new file mode 100644 index 00000000..b0af7c51 --- /dev/null +++ b/md/syntaxrules-explanation-implicit_case_default.md @@ -0,0 +1,16 @@ +This rule is an extension of the **case_default** rule that allows the case default to be implicitly defined. +Case statements without a `default` branch can cause signals to be undriven. Setting default values of signals at the top of an `always` procedures is good practice and ensures that signals are never metastable when a case match fails. For example, +```sv +always_comb begin + y = 0; + case(x) + 1: y = 1; + endcase +end + +``` +If the case match fails, `y` wouldn't infer memory or be undriven because the default value is defined before the `case`. + +See also: + - **case_default** + - **explicit_case_default** From bdd38317aa8bea72e1cb1edf74f6f28a144d02ee Mon Sep 17 00:00:00 2001 From: Ronit Nallagatla Date: Thu, 8 Feb 2024 14:06:11 -0500 Subject: [PATCH 02/25] added pass/fail examples --- ...taxrules-explanation-implicit_case_default.md | 5 +++++ .../syntaxrules/fail/implicit_case_default.sv | 16 ++++++++++++++++ .../syntaxrules/pass/implicit_case_default.sv | 15 +++++++++++++++ 3 files changed, 36 insertions(+) create mode 100644 testcases/syntaxrules/fail/implicit_case_default.sv create mode 100644 testcases/syntaxrules/pass/implicit_case_default.sv diff --git a/md/syntaxrules-explanation-implicit_case_default.md b/md/syntaxrules-explanation-implicit_case_default.md index b0af7c51..cbb72c45 100644 --- a/md/syntaxrules-explanation-implicit_case_default.md +++ b/md/syntaxrules-explanation-implicit_case_default.md @@ -14,3 +14,8 @@ If the case match fails, `y` wouldn't infer memory or be undriven because the de See also: - **case_default** - **explicit_case_default** + +The most relevant clauses of IEEE1800-2017 are: + +- 12.5 Case statement + diff --git a/testcases/syntaxrules/fail/implicit_case_default.sv b/testcases/syntaxrules/fail/implicit_case_default.sv new file mode 100644 index 00000000..03b4a9cf --- /dev/null +++ b/testcases/syntaxrules/fail/implicit_case_default.sv @@ -0,0 +1,16 @@ +module M; + always_comb + case (x) + 1: a = 0; // No implicit or explicit case default + endcase +endmodule +//////////////////////////////////////////////////////////////////////////////// +module M; + always_comb begin + a = 0; + + case(x) + 1: b = 0; + endcase + end +endmodule diff --git a/testcases/syntaxrules/pass/implicit_case_default.sv b/testcases/syntaxrules/pass/implicit_case_default.sv new file mode 100644 index 00000000..0b03c238 --- /dev/null +++ b/testcases/syntaxrules/pass/implicit_case_default.sv @@ -0,0 +1,15 @@ +module M; + always_comb + y = 0; + case(x) + 1: y = 1; // case default is implicit + endcase +endmodule +//////////////////////////////////////////////////////////////////////////////// +module M; + always_comb + case(x) + 1: y = 1; + default: y = 0; + endcase +endmodule From 1c0a7d0e4f3f60daf6b8df0405ea0810d596b203 Mon Sep 17 00:00:00 2001 From: Shreyas Chinnola Date: Thu, 22 Feb 2024 09:14:17 -0500 Subject: [PATCH 03/25] started making changes to implicit_case_default.rs --- src/syntaxrules/implicit_case_default.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/syntaxrules/implicit_case_default.rs b/src/syntaxrules/implicit_case_default.rs index 9b480a50..a8b102e0 100644 --- a/src/syntaxrules/implicit_case_default.rs +++ b/src/syntaxrules/implicit_case_default.rs @@ -5,7 +5,8 @@ use sv_parser::{unwrap_node, Locate, NodeEvent, RefNode, SyntaxTree}; #[derive(Default)] pub struct ImplicitCaseDefault { under_always_construct: bool, - lhs_variables: Vec, + implicit_variables: Vec, + case_variables: Vec, } impl SyntaxRule for ImplicitCaseDefault { @@ -29,9 +30,9 @@ impl SyntaxRule for ImplicitCaseDefault { let id = get_identifier(var); let id = syntax_tree.get_str(&id).unwrap(); - self.lhs_variables.push(String::from(id)); + self.implicit_variables.push(String::from(id)); - println!("LHS Variables: {:?}", self.lhs_variables); + println!("LHS Variables: {:?}", self.implicit_variables); } _ => (), @@ -58,8 +59,8 @@ impl SyntaxRule for ImplicitCaseDefault { println!("Case variable: {id}"); - // check if id is in lhs_variables - if self.lhs_variables.contains(&id.to_string()) { + // check if id is in implicit_variables + if self.implicit_variables.contains(&id.to_string()) { SyntaxRuleResult::Pass } else { SyntaxRuleResult::Fail From 546873f9a02fed9b94f6d5073dcab0b2e9dd6be8 Mon Sep 17 00:00:00 2001 From: Ronit Nallagatla Date: Thu, 22 Feb 2024 21:12:38 -0500 Subject: [PATCH 04/25] New Rule: implicit_case_default -- basic implementation --- src/syntaxrules/implicit_case_default.rs | 92 ++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 src/syntaxrules/implicit_case_default.rs diff --git a/src/syntaxrules/implicit_case_default.rs b/src/syntaxrules/implicit_case_default.rs new file mode 100644 index 00000000..9b480a50 --- /dev/null +++ b/src/syntaxrules/implicit_case_default.rs @@ -0,0 +1,92 @@ +use crate::config::ConfigOption; +use crate::linter::{SyntaxRule, SyntaxRuleResult}; +use sv_parser::{unwrap_node, Locate, NodeEvent, RefNode, SyntaxTree}; + +#[derive(Default)] +pub struct ImplicitCaseDefault { + under_always_construct: bool, + lhs_variables: Vec, +} + +impl SyntaxRule for ImplicitCaseDefault { + fn check( + &mut self, + syntax_tree: &SyntaxTree, + event: &NodeEvent, + _option: &ConfigOption, + ) -> SyntaxRuleResult { + // println!("Syntax Tree: {}", syntax_tree); + + let node = match event { + NodeEvent::Enter(x) => { + match x { + RefNode::AlwaysConstruct(_) => { + self.under_always_construct = true; + } + + RefNode::BlockItemDeclaration(x) => { + let var = unwrap_node!(*x, VariableDeclAssignment).unwrap(); + let id = get_identifier(var); + let id = syntax_tree.get_str(&id).unwrap(); + + self.lhs_variables.push(String::from(id)); + + println!("LHS Variables: {:?}", self.lhs_variables); + } + + _ => (), + } + x + } + NodeEvent::Leave(x) => { + if let RefNode::AlwaysConstruct(_) = x { + self.under_always_construct = false; + } + return SyntaxRuleResult::Pass; + } + }; + match (self.under_always_construct, node) { + (true, RefNode::CaseStatementNormal(x)) => { + let a = unwrap_node!(*x, CaseItemDefault); + if a.is_some() { + SyntaxRuleResult::Pass + } else { + // check if lvalues of case statement have an implicit definition + let var = unwrap_node!(*x, VariableLvalueIdentifier).unwrap(); + let id = get_identifier(var); + let id = syntax_tree.get_str(&id).unwrap(); + + println!("Case variable: {id}"); + + // check if id is in lhs_variables + if self.lhs_variables.contains(&id.to_string()) { + SyntaxRuleResult::Pass + } else { + SyntaxRuleResult::Fail + } + } + } + _ => SyntaxRuleResult::Pass, + } + } + + fn name(&self) -> String { + String::from("implicit_case_default") + } + + fn hint(&self, _option: &ConfigOption) -> String { + String::from("Signal driven in `case` statement does not have a default value.") + } + + fn reason(&self) -> String { + String::from("Default values ensure that signals are always driven.") + } +} + +fn get_identifier(node: RefNode) -> Option { + match unwrap_node!(node, SimpleIdentifier, EscapedIdentifier) { + Some(RefNode::SimpleIdentifier(x)) => Some(x.nodes.0), + Some(RefNode::EscapedIdentifier(x)) => Some(x.nodes.0), + _ => None, + } +} From 68f609bed1b9cf21362cf98a266b27cab94ec01a Mon Sep 17 00:00:00 2001 From: ronitnallagatla Date: Fri, 23 Feb 2024 02:15:19 +0000 Subject: [PATCH 05/25] Commit from GitHub Actions (Run mdgen) --- MANUAL.md | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/MANUAL.md b/MANUAL.md index 56850478..90279703 100644 --- a/MANUAL.md +++ b/MANUAL.md @@ -2030,6 +2030,89 @@ The most relevant clauses of IEEE1800-2017 are: +* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + +## Syntax Rule: `implicit_case_default` + +### Hint + +Signal driven in `case` statement does not have a default value. + +### Reason + +Default values ensure that signals are always driven. + +### Pass Example (1 of 2) +```systemverilog +module M; + always_comb + y = 0; + case(x) + 1: y = 1; // case default is implicit + endcase +endmodule +``` + +### Pass Example (2 of 2) +```systemverilog +module M; + always_comb + case(x) + 1: y = 1; + default: y = 0; + endcase +endmodule +``` + +### Fail Example (1 of 2) +```systemverilog +module M; + always_comb + case (x) + 1: a = 0; // No implicit or explicit case default + endcase +endmodule +``` + +### Fail Example (2 of 2) +```systemverilog +module M; + always_comb begin + a = 0; + + case(x) + 1: b = 0; + endcase + end +endmodule +``` + +### Explanation + +This rule is an extension of the **case_default** rule that allows the case default to be implicitly defined. +Case statements without a `default` branch can cause signals to be undriven. Setting default values of signals at the top of an `always` procedures is good practice and ensures that signals are never metastable when a case match fails. For example, +```sv +always_comb begin + y = 0; + case(x) + 1: y = 1; + endcase +end + +``` +If the case match fails, `y` wouldn't infer memory or be undriven because the default value is defined before the `case`. + +See also: + - **case_default** + - **explicit_case_default** + +The most relevant clauses of IEEE1800-2017 are: + +- 12.5 Case statement + + + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ## Syntax Rule: `inout_with_tri` From 50734759ac3e07b5422f7839db085f2aca6f9c96 Mon Sep 17 00:00:00 2001 From: Shreyas Chinnola Date: Fri, 15 Mar 2024 16:30:57 -0500 Subject: [PATCH 06/25] implicit_case_default works for most implicit declarations, still need to implement default case support --- src/syntaxrules/implicit_case_default.rs | 98 +++++++++++++++---- .../syntaxrules/pass/implicit_case_default.sv | 19 ++-- 2 files changed, 87 insertions(+), 30 deletions(-) diff --git a/src/syntaxrules/implicit_case_default.rs b/src/syntaxrules/implicit_case_default.rs index a8b102e0..25c215d2 100644 --- a/src/syntaxrules/implicit_case_default.rs +++ b/src/syntaxrules/implicit_case_default.rs @@ -5,8 +5,10 @@ use sv_parser::{unwrap_node, Locate, NodeEvent, RefNode, SyntaxTree}; #[derive(Default)] pub struct ImplicitCaseDefault { under_always_construct: bool, - implicit_variables: Vec, - case_variables: Vec, + under_case_statement: bool, + + lhs_variables: Vec, + case_variables: Vec } impl SyntaxRule for ImplicitCaseDefault { @@ -16,7 +18,7 @@ impl SyntaxRule for ImplicitCaseDefault { event: &NodeEvent, _option: &ConfigOption, ) -> SyntaxRuleResult { - // println!("Syntax Tree: {}", syntax_tree); + //println!("{}", syntax_tree); let node = match event { NodeEvent::Enter(x) => { @@ -25,27 +27,78 @@ impl SyntaxRule for ImplicitCaseDefault { self.under_always_construct = true; } - RefNode::BlockItemDeclaration(x) => { - let var = unwrap_node!(*x, VariableDeclAssignment).unwrap(); - let id = get_identifier(var); - let id = syntax_tree.get_str(&id).unwrap(); - - self.implicit_variables.push(String::from(id)); - - println!("LHS Variables: {:?}", self.implicit_variables); + RefNode::CaseItemNondefault(_) => { + self.under_case_statement = true; } - + _ => (), } x } + NodeEvent::Leave(x) => { - if let RefNode::AlwaysConstruct(_) = x { - self.under_always_construct = false; + match x { + RefNode::AlwaysConstruct(_) => { + self.under_always_construct = false; + self.lhs_variables.clear(); + self.case_variables.clear(); + + } + + RefNode::CaseItemNondefault(_) => { + self.under_case_statement = false; + } + + _ => () } return SyntaxRuleResult::Pass; } }; + + //println!("{}", node); + + // match implicit declarations + match (self.under_always_construct, self.under_case_statement, node) { + (true, false, RefNode::BlockItemDeclaration(x)) => { + let var = unwrap_node!(*x, VariableDeclAssignment).unwrap(); + let id = get_identifier(var); + let id = syntax_tree.get_str(&id).unwrap(); + self.lhs_variables.push(String::from(id)); + } + + _ => () + } + + // match case statement declarations + match (self.under_always_construct, self.under_case_statement, node) { + (true, true, RefNode::BlockingAssignment(x)) => { + let var = unwrap_node!(*x, VariableLvalueIdentifier).unwrap(); + let id = get_identifier(var); + let id = syntax_tree.get_str(&id).unwrap(); + + if self.lhs_variables.contains(&id.to_string()) { + return SyntaxRuleResult::Pass + } else { + return SyntaxRuleResult::Fail + } + } + + (true, true, RefNode::BlockItemDeclaration(x)) => { + let var = unwrap_node!(*x, VariableDeclAssignment).unwrap(); + let id = get_identifier(var); + let id = syntax_tree.get_str(&id).unwrap(); + + if self.lhs_variables.contains(&id.to_string()) { + return SyntaxRuleResult::Pass + } else { + return SyntaxRuleResult::Fail + } + } + + _ => () + } + + /* match (self.under_always_construct, node) { (true, RefNode::CaseStatementNormal(x)) => { let a = unwrap_node!(*x, CaseItemDefault); @@ -59,16 +112,21 @@ impl SyntaxRule for ImplicitCaseDefault { println!("Case variable: {id}"); - // check if id is in implicit_variables - if self.implicit_variables.contains(&id.to_string()) { + // check if id is in lhs_variables + if self.lhs_variables.contains(&id.to_string()) { SyntaxRuleResult::Pass } else { SyntaxRuleResult::Fail } } } - _ => SyntaxRuleResult::Pass, - } + + _ => { + SyntaxRuleResult::Pass + } + }*/ + + return SyntaxRuleResult::Pass } fn name(&self) -> String { @@ -76,7 +134,7 @@ impl SyntaxRule for ImplicitCaseDefault { } fn hint(&self, _option: &ConfigOption) -> String { - String::from("Signal driven in `case` statement does not have a default value.") + String::from("Signal driven in `case` statement does not have a default value. Define a default case or implicitly define before `case` statement.") } fn reason(&self) -> String { @@ -90,4 +148,4 @@ fn get_identifier(node: RefNode) -> Option { Some(RefNode::EscapedIdentifier(x)) => Some(x.nodes.0), _ => None, } -} +} \ No newline at end of file diff --git a/testcases/syntaxrules/pass/implicit_case_default.sv b/testcases/syntaxrules/pass/implicit_case_default.sv index 0b03c238..a80a3c54 100644 --- a/testcases/syntaxrules/pass/implicit_case_default.sv +++ b/testcases/syntaxrules/pass/implicit_case_default.sv @@ -1,15 +1,14 @@ module M; - always_comb + always_comb begin y = 0; + z = 0; + //w = 0; case(x) 1: y = 1; // case default is implicit + 2: begin + z = 1; + w = 1; + end endcase -endmodule -//////////////////////////////////////////////////////////////////////////////// -module M; - always_comb - case(x) - 1: y = 1; - default: y = 0; - endcase -endmodule + end +endmodule \ No newline at end of file From f445e1f44560f2c64d46c0c127c37c3b3f0d9042 Mon Sep 17 00:00:00 2001 From: Shreyas Chinnola Date: Mon, 18 Mar 2024 23:06:37 -0400 Subject: [PATCH 07/25] simple case implicit_case_default DONE --- src/syntaxrules/implicit_case_default.rs | 59 ++++++++----------- .../syntaxrules/fail/implicit_case_default.sv | 1 - .../syntaxrules/pass/implicit_case_default.sv | 20 ++++++- 3 files changed, 41 insertions(+), 39 deletions(-) diff --git a/src/syntaxrules/implicit_case_default.rs b/src/syntaxrules/implicit_case_default.rs index 25c215d2..947031a7 100644 --- a/src/syntaxrules/implicit_case_default.rs +++ b/src/syntaxrules/implicit_case_default.rs @@ -5,7 +5,8 @@ use sv_parser::{unwrap_node, Locate, NodeEvent, RefNode, SyntaxTree}; #[derive(Default)] pub struct ImplicitCaseDefault { under_always_construct: bool, - under_case_statement: bool, + under_case_item: bool, + is_default: bool, lhs_variables: Vec, case_variables: Vec @@ -25,10 +26,11 @@ impl SyntaxRule for ImplicitCaseDefault { match x { RefNode::AlwaysConstruct(_) => { self.under_always_construct = true; + self.is_default = false; } RefNode::CaseItemNondefault(_) => { - self.under_case_statement = true; + self.under_case_item = true; } _ => (), @@ -40,13 +42,14 @@ impl SyntaxRule for ImplicitCaseDefault { match x { RefNode::AlwaysConstruct(_) => { self.under_always_construct = false; + self.is_default = false; self.lhs_variables.clear(); self.case_variables.clear(); } RefNode::CaseItemNondefault(_) => { - self.under_case_statement = false; + self.under_case_item = false; } _ => () @@ -56,9 +59,9 @@ impl SyntaxRule for ImplicitCaseDefault { }; //println!("{}", node); - + // match implicit declarations - match (self.under_always_construct, self.under_case_statement, node) { + match (self.under_always_construct, self.under_case_item, node) { (true, false, RefNode::BlockItemDeclaration(x)) => { let var = unwrap_node!(*x, VariableDeclAssignment).unwrap(); let id = get_identifier(var); @@ -69,14 +72,26 @@ impl SyntaxRule for ImplicitCaseDefault { _ => () } + // check if default + match (self.under_always_construct, node) { + (true, RefNode::CaseStatementNormal(x)) => { + let a = unwrap_node!(*x, CaseItemDefault); + if a.is_some() { + self.is_default = true; + } + } + + _ => () + } + // match case statement declarations - match (self.under_always_construct, self.under_case_statement, node) { + match (self.under_always_construct, self.under_case_item, node) { (true, true, RefNode::BlockingAssignment(x)) => { let var = unwrap_node!(*x, VariableLvalueIdentifier).unwrap(); let id = get_identifier(var); let id = syntax_tree.get_str(&id).unwrap(); - if self.lhs_variables.contains(&id.to_string()) { + if self.lhs_variables.contains(&id.to_string()) || self.is_default { return SyntaxRuleResult::Pass } else { return SyntaxRuleResult::Fail @@ -88,7 +103,7 @@ impl SyntaxRule for ImplicitCaseDefault { let id = get_identifier(var); let id = syntax_tree.get_str(&id).unwrap(); - if self.lhs_variables.contains(&id.to_string()) { + if self.lhs_variables.contains(&id.to_string()) || self.is_default { return SyntaxRuleResult::Pass } else { return SyntaxRuleResult::Fail @@ -98,34 +113,6 @@ impl SyntaxRule for ImplicitCaseDefault { _ => () } - /* - match (self.under_always_construct, node) { - (true, RefNode::CaseStatementNormal(x)) => { - let a = unwrap_node!(*x, CaseItemDefault); - if a.is_some() { - SyntaxRuleResult::Pass - } else { - // check if lvalues of case statement have an implicit definition - let var = unwrap_node!(*x, VariableLvalueIdentifier).unwrap(); - let id = get_identifier(var); - let id = syntax_tree.get_str(&id).unwrap(); - - println!("Case variable: {id}"); - - // check if id is in lhs_variables - if self.lhs_variables.contains(&id.to_string()) { - SyntaxRuleResult::Pass - } else { - SyntaxRuleResult::Fail - } - } - } - - _ => { - SyntaxRuleResult::Pass - } - }*/ - return SyntaxRuleResult::Pass } diff --git a/testcases/syntaxrules/fail/implicit_case_default.sv b/testcases/syntaxrules/fail/implicit_case_default.sv index 03b4a9cf..40496c5b 100644 --- a/testcases/syntaxrules/fail/implicit_case_default.sv +++ b/testcases/syntaxrules/fail/implicit_case_default.sv @@ -8,7 +8,6 @@ endmodule module M; always_comb begin a = 0; - case(x) 1: b = 0; endcase diff --git a/testcases/syntaxrules/pass/implicit_case_default.sv b/testcases/syntaxrules/pass/implicit_case_default.sv index a80a3c54..8e2f0450 100644 --- a/testcases/syntaxrules/pass/implicit_case_default.sv +++ b/testcases/syntaxrules/pass/implicit_case_default.sv @@ -1,14 +1,30 @@ +module M; + always_comb + y = 0; + case(x) + 1: y = 1; // case default is implicit + endcase +endmodule +//////////////////////////////////////////////////////////////////////////////// module M; always_comb begin y = 0; z = 0; - //w = 0; + w = 0; case(x) - 1: y = 1; // case default is implicit + 1: y = 1; 2: begin z = 1; w = 1; end endcase end +endmodule +//////////////////////////////////////////////////////////////////////////////// +module M; + always_comb + case(x) + 1: y = 1; + default: y = 0; + endcase endmodule \ No newline at end of file From f665f23e51955291b937d6c4e89cf087266efb19 Mon Sep 17 00:00:00 2001 From: ShreChinno Date: Tue, 19 Mar 2024 03:11:11 +0000 Subject: [PATCH 08/25] Commit from GitHub Actions (Run mdgen) --- MANUAL.md | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/MANUAL.md b/MANUAL.md index 90279703..d82d3e08 100644 --- a/MANUAL.md +++ b/MANUAL.md @@ -2036,13 +2036,13 @@ The most relevant clauses of IEEE1800-2017 are: ### Hint -Signal driven in `case` statement does not have a default value. +Signal driven in `case` statement does not have a default value. Define a default case or implicitly define before `case` statement. ### Reason Default values ensure that signals are always driven. -### Pass Example (1 of 2) +### Pass Example (1 of 3) ```systemverilog module M; always_comb @@ -2053,7 +2053,25 @@ module M; endmodule ``` -### Pass Example (2 of 2) +### Pass Example (2 of 3) +```systemverilog +module M; + always_comb begin + y = 0; + z = 0; + w = 0; + case(x) + 1: y = 1; + 2: begin + z = 1; + w = 1; + end + endcase + end +endmodule +``` + +### Pass Example (3 of 3) ```systemverilog module M; always_comb @@ -2079,7 +2097,6 @@ endmodule module M; always_comb begin a = 0; - case(x) 1: b = 0; endcase From ec897a60587660a5fef172aa41dceea835aff046 Mon Sep 17 00:00:00 2001 From: Shreyas Chinnola Date: Tue, 19 Mar 2024 22:14:07 -0400 Subject: [PATCH 09/25] added another fail testcase --- .../syntaxrules/fail/implicit_case_default.sv | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/testcases/syntaxrules/fail/implicit_case_default.sv b/testcases/syntaxrules/fail/implicit_case_default.sv index 40496c5b..5cefdf41 100644 --- a/testcases/syntaxrules/fail/implicit_case_default.sv +++ b/testcases/syntaxrules/fail/implicit_case_default.sv @@ -5,6 +5,19 @@ module M; endcase endmodule //////////////////////////////////////////////////////////////////////////////// +module M; + always_comb begin + y = 0; + case(x) + 1: y = 1; + 2: begin + z = 1; + w = 1; + end + endcase + end +endmodule +//////////////////////////////////////////////////////////////////////////////// module M; always_comb begin a = 0; @@ -12,4 +25,4 @@ module M; 1: b = 0; endcase end -endmodule +endmodule \ No newline at end of file From 8907da0bb2302af9fdc8e265d2d8b28bf3933529 Mon Sep 17 00:00:00 2001 From: ShreChinno Date: Wed, 20 Mar 2024 02:20:12 +0000 Subject: [PATCH 10/25] Commit from GitHub Actions (Run mdgen) --- MANUAL.md | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/MANUAL.md b/MANUAL.md index d82d3e08..feceff87 100644 --- a/MANUAL.md +++ b/MANUAL.md @@ -2082,7 +2082,7 @@ module M; endmodule ``` -### Fail Example (1 of 2) +### Fail Example (1 of 3) ```systemverilog module M; always_comb @@ -2092,7 +2092,23 @@ module M; endmodule ``` -### Fail Example (2 of 2) +### Fail Example (2 of 3) +```systemverilog +module M; + always_comb begin + y = 0; + case(x) + 1: y = 1; + 2: begin + z = 1; + w = 1; + end + endcase + end +endmodule +``` + +### Fail Example (3 of 3) ```systemverilog module M; always_comb begin From 977e4c349c76bd5c8f78a057a5c5899e35e2b666 Mon Sep 17 00:00:00 2001 From: Shreyas Chinnola Date: Wed, 20 Mar 2024 15:32:53 -0400 Subject: [PATCH 11/25] removed debug prints --- src/syntaxrules/implicit_case_default.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/syntaxrules/implicit_case_default.rs b/src/syntaxrules/implicit_case_default.rs index 947031a7..f1dd50a5 100644 --- a/src/syntaxrules/implicit_case_default.rs +++ b/src/syntaxrules/implicit_case_default.rs @@ -19,8 +19,6 @@ impl SyntaxRule for ImplicitCaseDefault { event: &NodeEvent, _option: &ConfigOption, ) -> SyntaxRuleResult { - //println!("{}", syntax_tree); - let node = match event { NodeEvent::Enter(x) => { match x { @@ -58,8 +56,6 @@ impl SyntaxRule for ImplicitCaseDefault { } }; - //println!("{}", node); - // match implicit declarations match (self.under_always_construct, self.under_case_item, node) { (true, false, RefNode::BlockItemDeclaration(x)) => { From 78df3641b8469eb1111620af96c2a84556a1e365 Mon Sep 17 00:00:00 2001 From: Shreyas Chinnola Date: Thu, 21 Mar 2024 13:43:59 -0400 Subject: [PATCH 12/25] small changes --- src/syntaxrules/implicit_case_default.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/syntaxrules/implicit_case_default.rs b/src/syntaxrules/implicit_case_default.rs index f1dd50a5..76d339dc 100644 --- a/src/syntaxrules/implicit_case_default.rs +++ b/src/syntaxrules/implicit_case_default.rs @@ -9,7 +9,6 @@ pub struct ImplicitCaseDefault { is_default: bool, lhs_variables: Vec, - case_variables: Vec } impl SyntaxRule for ImplicitCaseDefault { @@ -42,8 +41,6 @@ impl SyntaxRule for ImplicitCaseDefault { self.under_always_construct = false; self.is_default = false; self.lhs_variables.clear(); - self.case_variables.clear(); - } RefNode::CaseItemNondefault(_) => { @@ -117,7 +114,7 @@ impl SyntaxRule for ImplicitCaseDefault { } fn hint(&self, _option: &ConfigOption) -> String { - String::from("Signal driven in `case` statement does not have a default value. Define a default case or implicitly define before `case` statement.") + String::from("Signal driven in `case` statement does not have a default value.\n Define a default case or implicitly define before `case` statement.") } fn reason(&self) -> String { From 1a96bf0e799502841cf147643ab0f89914c488e3 Mon Sep 17 00:00:00 2001 From: ShreChinno Date: Thu, 21 Mar 2024 17:46:20 +0000 Subject: [PATCH 13/25] Commit from GitHub Actions (Run mdgen) --- MANUAL.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MANUAL.md b/MANUAL.md index feceff87..f0b549d6 100644 --- a/MANUAL.md +++ b/MANUAL.md @@ -2036,7 +2036,8 @@ The most relevant clauses of IEEE1800-2017 are: ### Hint -Signal driven in `case` statement does not have a default value. Define a default case or implicitly define before `case` statement. +Signal driven in `case` statement does not have a default value. + Define a default case or implicitly define before `case` statement. ### Reason From 3d482393c08adcfc2bc5cdfe10d48bb1379f0f3f Mon Sep 17 00:00:00 2001 From: Shreyas Chinnola Date: Thu, 21 Mar 2024 14:02:57 -0400 Subject: [PATCH 14/25] changed hint --- src/syntaxrules/implicit_case_default.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/syntaxrules/implicit_case_default.rs b/src/syntaxrules/implicit_case_default.rs index 76d339dc..3f99f7e2 100644 --- a/src/syntaxrules/implicit_case_default.rs +++ b/src/syntaxrules/implicit_case_default.rs @@ -114,7 +114,7 @@ impl SyntaxRule for ImplicitCaseDefault { } fn hint(&self, _option: &ConfigOption) -> String { - String::from("Signal driven in `case` statement does not have a default value.\n Define a default case or implicitly define before `case` statement.") + String::from("Signal driven in `case` statement does not have a default value.") } fn reason(&self) -> String { From 611c74fe6766496b496fadb733f9cfba266ef8e0 Mon Sep 17 00:00:00 2001 From: ShreChinno Date: Thu, 21 Mar 2024 18:04:17 +0000 Subject: [PATCH 15/25] Commit from GitHub Actions (Run mdgen) --- MANUAL.md | 1 - 1 file changed, 1 deletion(-) diff --git a/MANUAL.md b/MANUAL.md index f0b549d6..0fabbb80 100644 --- a/MANUAL.md +++ b/MANUAL.md @@ -2037,7 +2037,6 @@ The most relevant clauses of IEEE1800-2017 are: ### Hint Signal driven in `case` statement does not have a default value. - Define a default case or implicitly define before `case` statement. ### Reason From 57e4d5aa8b4a573dd40a80b8d1305ee97c2b7e58 Mon Sep 17 00:00:00 2001 From: Ronit Nallagatla Date: Thu, 21 Mar 2024 15:47:19 -0400 Subject: [PATCH 16/25] add locate on fail --- src/syntaxrules/implicit_case_default.rs | 61 +++++++++++------------- 1 file changed, 28 insertions(+), 33 deletions(-) diff --git a/src/syntaxrules/implicit_case_default.rs b/src/syntaxrules/implicit_case_default.rs index 3f99f7e2..6566bd9b 100644 --- a/src/syntaxrules/implicit_case_default.rs +++ b/src/syntaxrules/implicit_case_default.rs @@ -1,13 +1,12 @@ use crate::config::ConfigOption; use crate::linter::{SyntaxRule, SyntaxRuleResult}; -use sv_parser::{unwrap_node, Locate, NodeEvent, RefNode, SyntaxTree}; +use sv_parser::{unwrap_locate, unwrap_node, Locate, NodeEvent, RefNode, SyntaxTree}; #[derive(Default)] pub struct ImplicitCaseDefault { under_always_construct: bool, under_case_item: bool, is_default: bool, - lhs_variables: Vec, } @@ -29,7 +28,7 @@ impl SyntaxRule for ImplicitCaseDefault { RefNode::CaseItemNondefault(_) => { self.under_case_item = true; } - + _ => (), } x @@ -47,66 +46,62 @@ impl SyntaxRule for ImplicitCaseDefault { self.under_case_item = false; } - _ => () + _ => (), } return SyntaxRuleResult::Pass; } }; // match implicit declarations - match (self.under_always_construct, self.under_case_item, node) { - (true, false, RefNode::BlockItemDeclaration(x)) => { - let var = unwrap_node!(*x, VariableDeclAssignment).unwrap(); - let id = get_identifier(var); - let id = syntax_tree.get_str(&id).unwrap(); - self.lhs_variables.push(String::from(id)); - } - - _ => () + if let (true, false, RefNode::BlockItemDeclaration(x)) = + (self.under_always_construct, self.under_case_item, node) + { + let var = unwrap_node!(*x, VariableDeclAssignment).unwrap(); + let id = get_identifier(var); + let id = syntax_tree.get_str(&id).unwrap(); + self.lhs_variables.push(String::from(id)); } // check if default - match (self.under_always_construct, node) { - (true, RefNode::CaseStatementNormal(x)) => { - let a = unwrap_node!(*x, CaseItemDefault); - if a.is_some() { - self.is_default = true; - } + if let (true, RefNode::CaseStatementNormal(x)) = (self.under_always_construct, node) { + let a = unwrap_node!(*x, CaseItemDefault); + if a.is_some() { + self.is_default = true; } - - _ => () } // match case statement declarations match (self.under_always_construct, self.under_case_item, node) { (true, true, RefNode::BlockingAssignment(x)) => { let var = unwrap_node!(*x, VariableLvalueIdentifier).unwrap(); + let loc = unwrap_locate!(var.clone()).unwrap(); let id = get_identifier(var); let id = syntax_tree.get_str(&id).unwrap(); - + if self.lhs_variables.contains(&id.to_string()) || self.is_default { - return SyntaxRuleResult::Pass + return SyntaxRuleResult::Pass; } else { - return SyntaxRuleResult::Fail + return SyntaxRuleResult::FailLocate(*loc); } } - + (true, true, RefNode::BlockItemDeclaration(x)) => { let var = unwrap_node!(*x, VariableDeclAssignment).unwrap(); + let loc = unwrap_locate!(var.clone()).unwrap(); let id = get_identifier(var); let id = syntax_tree.get_str(&id).unwrap(); - + if self.lhs_variables.contains(&id.to_string()) || self.is_default { - return SyntaxRuleResult::Pass + return SyntaxRuleResult::Pass; } else { - return SyntaxRuleResult::Fail + return SyntaxRuleResult::FailLocate(*loc); } } - - _ => () + + _ => (), } - return SyntaxRuleResult::Pass + SyntaxRuleResult::Pass } fn name(&self) -> String { @@ -118,7 +113,7 @@ impl SyntaxRule for ImplicitCaseDefault { } fn reason(&self) -> String { - String::from("Default values ensure that signals are always driven.") + String::from("Default values ensure that signals are never metastable.") } } @@ -128,4 +123,4 @@ fn get_identifier(node: RefNode) -> Option { Some(RefNode::EscapedIdentifier(x)) => Some(x.nodes.0), _ => None, } -} \ No newline at end of file +} From fc18e123febc34ab33986dc9da67ec57ef3538c2 Mon Sep 17 00:00:00 2001 From: Ronit Nallagatla Date: Thu, 21 Mar 2024 15:48:06 -0400 Subject: [PATCH 17/25] add missing begin/end --- testcases/syntaxrules/fail/implicit_case_default.sv | 8 ++++---- testcases/syntaxrules/pass/implicit_case_default.sv | 13 +++++++------ 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/testcases/syntaxrules/fail/implicit_case_default.sv b/testcases/syntaxrules/fail/implicit_case_default.sv index 5cefdf41..f5e0affd 100644 --- a/testcases/syntaxrules/fail/implicit_case_default.sv +++ b/testcases/syntaxrules/fail/implicit_case_default.sv @@ -8,9 +8,9 @@ endmodule module M; always_comb begin y = 0; - case(x) + case (x) 1: y = 1; - 2: begin + 2: begin z = 1; w = 1; end @@ -21,8 +21,8 @@ endmodule module M; always_comb begin a = 0; - case(x) + case (x) 1: b = 0; endcase end -endmodule \ No newline at end of file +endmodule diff --git a/testcases/syntaxrules/pass/implicit_case_default.sv b/testcases/syntaxrules/pass/implicit_case_default.sv index 8e2f0450..eb02c30f 100644 --- a/testcases/syntaxrules/pass/implicit_case_default.sv +++ b/testcases/syntaxrules/pass/implicit_case_default.sv @@ -1,9 +1,10 @@ module M; - always_comb + always_comb begin y = 0; - case(x) + case (x) 1: y = 1; // case default is implicit endcase + end endmodule //////////////////////////////////////////////////////////////////////////////// module M; @@ -11,9 +12,9 @@ module M; y = 0; z = 0; w = 0; - case(x) + case (x) 1: y = 1; - 2: begin + 2: begin z = 1; w = 1; end @@ -23,8 +24,8 @@ endmodule //////////////////////////////////////////////////////////////////////////////// module M; always_comb - case(x) + case (x) 1: y = 1; default: y = 0; endcase -endmodule \ No newline at end of file +endmodule From 38f0769b791fc5de4d043caacb93821ae7c90fbc Mon Sep 17 00:00:00 2001 From: ronitnallagatla Date: Fri, 22 Mar 2024 00:31:01 +0000 Subject: [PATCH 18/25] Commit from GitHub Actions (Run mdgen) --- MANUAL.md | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/MANUAL.md b/MANUAL.md index 0fabbb80..84db6bc9 100644 --- a/MANUAL.md +++ b/MANUAL.md @@ -2040,16 +2040,17 @@ Signal driven in `case` statement does not have a default value. ### Reason -Default values ensure that signals are always driven. +Default values ensure that signals are never metastable. ### Pass Example (1 of 3) ```systemverilog module M; - always_comb + always_comb begin y = 0; - case(x) + case (x) 1: y = 1; // case default is implicit endcase + end endmodule ``` @@ -2060,9 +2061,9 @@ module M; y = 0; z = 0; w = 0; - case(x) + case (x) 1: y = 1; - 2: begin + 2: begin z = 1; w = 1; end @@ -2075,7 +2076,7 @@ endmodule ```systemverilog module M; always_comb - case(x) + case (x) 1: y = 1; default: y = 0; endcase @@ -2097,9 +2098,9 @@ endmodule module M; always_comb begin y = 0; - case(x) + case (x) 1: y = 1; - 2: begin + 2: begin z = 1; w = 1; end @@ -2113,7 +2114,7 @@ endmodule module M; always_comb begin a = 0; - case(x) + case (x) 1: b = 0; endcase end From 4bdb2c32c71d54b6957551d841c9af1546da4744 Mon Sep 17 00:00:00 2001 From: Ronit Nallagatla Date: Fri, 22 Mar 2024 13:42:15 -0400 Subject: [PATCH 19/25] added more testcases --- .../syntaxrules/pass/implicit_case_default.sv | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/testcases/syntaxrules/pass/implicit_case_default.sv b/testcases/syntaxrules/pass/implicit_case_default.sv index eb02c30f..f703fcdf 100644 --- a/testcases/syntaxrules/pass/implicit_case_default.sv +++ b/testcases/syntaxrules/pass/implicit_case_default.sv @@ -29,3 +29,28 @@ module M; default: y = 0; endcase endmodule +//////////////////////////////////////////////////////////////////////////////// +module M; + always_comb + case (x) + 1: p = 1; + 2: q = 0; + default: begin + p = 0; + q = 0; + end + endcase +endmodule +//////////////////////////////////////////////////////////////////////////////// +module M; + always_comb begin + p = 0; // p -> implicit default + q = 0; // q -> implicit default + case (x) + 1: p = 1; + 2: q = 1; + 3: r = 1; + default: r = 1; // r -> explicit default + endcase + end +endmodule From 67f6a4a46dccfb344e14a6e7283109bf8ffafead Mon Sep 17 00:00:00 2001 From: ronitnallagatla Date: Fri, 22 Mar 2024 17:46:19 +0000 Subject: [PATCH 20/25] Commit from GitHub Actions (Run mdgen) --- MANUAL.md | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/MANUAL.md b/MANUAL.md index 84db6bc9..6a024601 100644 --- a/MANUAL.md +++ b/MANUAL.md @@ -2042,7 +2042,7 @@ Signal driven in `case` statement does not have a default value. Default values ensure that signals are never metastable. -### Pass Example (1 of 3) +### Pass Example (1 of 5) ```systemverilog module M; always_comb begin @@ -2054,7 +2054,7 @@ module M; endmodule ``` -### Pass Example (2 of 3) +### Pass Example (2 of 5) ```systemverilog module M; always_comb begin @@ -2072,7 +2072,7 @@ module M; endmodule ``` -### Pass Example (3 of 3) +### Pass Example (3 of 5) ```systemverilog module M; always_comb @@ -2083,6 +2083,37 @@ module M; endmodule ``` +### Pass Example (4 of 5) +```systemverilog +module M; + always_comb + case (x) + 1: p = 1; + 2: q = 0; + default: begin + p = 0; + q = 0; + end + endcase +endmodule +``` + +### Pass Example (5 of 5) +```systemverilog +module M; + always_comb begin + p = 0; // p -> implicit default + q = 0; // q -> implicit default + case (x) + 1: p = 1; + 2: q = 1; + 3: r = 1; + default: r = 1; // r -> explicit default + endcase + end +endmodule +``` + ### Fail Example (1 of 3) ```systemverilog module M; From 7b753af268f3f1ebe2f35639a9f7ee60dabd29da Mon Sep 17 00:00:00 2001 From: Ronit Nallagatla Date: Fri, 22 Mar 2024 16:06:03 -0400 Subject: [PATCH 21/25] some cleanup/renaming --- src/syntaxrules/implicit_case_default.rs | 33 ++++++++++++------------ 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/src/syntaxrules/implicit_case_default.rs b/src/syntaxrules/implicit_case_default.rs index 6566bd9b..470ce998 100644 --- a/src/syntaxrules/implicit_case_default.rs +++ b/src/syntaxrules/implicit_case_default.rs @@ -1,12 +1,12 @@ use crate::config::ConfigOption; use crate::linter::{SyntaxRule, SyntaxRuleResult}; -use sv_parser::{unwrap_locate, unwrap_node, Locate, NodeEvent, RefNode, SyntaxTree}; +use sv_parser::{unwrap_locate, unwrap_node, NodeEvent, RefNode, SyntaxTree}; #[derive(Default)] pub struct ImplicitCaseDefault { under_always_construct: bool, under_case_item: bool, - is_default: bool, + has_default: bool, lhs_variables: Vec, } @@ -22,7 +22,7 @@ impl SyntaxRule for ImplicitCaseDefault { match x { RefNode::AlwaysConstruct(_) => { self.under_always_construct = true; - self.is_default = false; + self.has_default = false; } RefNode::CaseItemNondefault(_) => { @@ -38,7 +38,7 @@ impl SyntaxRule for ImplicitCaseDefault { match x { RefNode::AlwaysConstruct(_) => { self.under_always_construct = false; - self.is_default = false; + self.has_default = false; self.lhs_variables.clear(); } @@ -57,16 +57,15 @@ impl SyntaxRule for ImplicitCaseDefault { (self.under_always_construct, self.under_case_item, node) { let var = unwrap_node!(*x, VariableDeclAssignment).unwrap(); - let id = get_identifier(var); - let id = syntax_tree.get_str(&id).unwrap(); - self.lhs_variables.push(String::from(id)); + let id = get_identifier(var, syntax_tree); + self.lhs_variables.push(id); } // check if default if let (true, RefNode::CaseStatementNormal(x)) = (self.under_always_construct, node) { let a = unwrap_node!(*x, CaseItemDefault); if a.is_some() { - self.is_default = true; + self.has_default = true; } } @@ -75,10 +74,9 @@ impl SyntaxRule for ImplicitCaseDefault { (true, true, RefNode::BlockingAssignment(x)) => { let var = unwrap_node!(*x, VariableLvalueIdentifier).unwrap(); let loc = unwrap_locate!(var.clone()).unwrap(); - let id = get_identifier(var); - let id = syntax_tree.get_str(&id).unwrap(); + let id = get_identifier(var, syntax_tree); - if self.lhs_variables.contains(&id.to_string()) || self.is_default { + if self.lhs_variables.contains(&id.to_string()) || self.has_default { return SyntaxRuleResult::Pass; } else { return SyntaxRuleResult::FailLocate(*loc); @@ -88,10 +86,9 @@ impl SyntaxRule for ImplicitCaseDefault { (true, true, RefNode::BlockItemDeclaration(x)) => { let var = unwrap_node!(*x, VariableDeclAssignment).unwrap(); let loc = unwrap_locate!(var.clone()).unwrap(); - let id = get_identifier(var); - let id = syntax_tree.get_str(&id).unwrap(); + let id = get_identifier(var, syntax_tree); - if self.lhs_variables.contains(&id.to_string()) || self.is_default { + if self.lhs_variables.contains(&id.to_string()) || self.has_default { return SyntaxRuleResult::Pass; } else { return SyntaxRuleResult::FailLocate(*loc); @@ -117,10 +114,12 @@ impl SyntaxRule for ImplicitCaseDefault { } } -fn get_identifier(node: RefNode) -> Option { - match unwrap_node!(node, SimpleIdentifier, EscapedIdentifier) { +fn get_identifier(node: RefNode, syntax_tree: &SyntaxTree) -> String { + let id = match unwrap_node!(node, SimpleIdentifier, EscapedIdentifier) { Some(RefNode::SimpleIdentifier(x)) => Some(x.nodes.0), Some(RefNode::EscapedIdentifier(x)) => Some(x.nodes.0), _ => None, - } + }; + + String::from(syntax_tree.get_str(&id).unwrap()) } From 321c530214340ae3eb4d48092ae13de78a1199b2 Mon Sep 17 00:00:00 2001 From: Ronit Nallagatla Date: Fri, 22 Mar 2024 16:54:25 -0400 Subject: [PATCH 22/25] fixed line width in explanation --- md/syntaxrules-explanation-implicit_case_default.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/md/syntaxrules-explanation-implicit_case_default.md b/md/syntaxrules-explanation-implicit_case_default.md index cbb72c45..6ec105a4 100644 --- a/md/syntaxrules-explanation-implicit_case_default.md +++ b/md/syntaxrules-explanation-implicit_case_default.md @@ -1,5 +1,8 @@ -This rule is an extension of the **case_default** rule that allows the case default to be implicitly defined. -Case statements without a `default` branch can cause signals to be undriven. Setting default values of signals at the top of an `always` procedures is good practice and ensures that signals are never metastable when a case match fails. For example, +This rule is an extension of the **case_default** rule that allows the case +default to be implicitly defined. Case statements without a `default` branch +can cause signals to be undriven. Setting default values of signals at the top +of an `always` procedures is good practice and ensures that signals are never +metastable when a case match fails. For example, ```sv always_comb begin y = 0; @@ -9,13 +12,13 @@ always_comb begin end ``` -If the case match fails, `y` wouldn't infer memory or be undriven because the default value is defined before the `case`. +If the case match fails, `y` wouldn't infer memory or be undriven because the +default value is defined before the `case`. See also: - **case_default** - **explicit_case_default** The most relevant clauses of IEEE1800-2017 are: - - 12.5 Case statement From cf1215cc4b1cbb486dc82ced7a28a5c9d3da0c11 Mon Sep 17 00:00:00 2001 From: ronitnallagatla Date: Fri, 22 Mar 2024 20:55:39 +0000 Subject: [PATCH 23/25] Commit from GitHub Actions (Run mdgen) --- MANUAL.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/MANUAL.md b/MANUAL.md index 6a024601..fed50358 100644 --- a/MANUAL.md +++ b/MANUAL.md @@ -2154,8 +2154,11 @@ endmodule ### Explanation -This rule is an extension of the **case_default** rule that allows the case default to be implicitly defined. -Case statements without a `default` branch can cause signals to be undriven. Setting default values of signals at the top of an `always` procedures is good practice and ensures that signals are never metastable when a case match fails. For example, +This rule is an extension of the **case_default** rule that allows the case +default to be implicitly defined. Case statements without a `default` branch +can cause signals to be undriven. Setting default values of signals at the top +of an `always` procedures is good practice and ensures that signals are never +metastable when a case match fails. For example, ```sv always_comb begin y = 0; @@ -2165,14 +2168,14 @@ always_comb begin end ``` -If the case match fails, `y` wouldn't infer memory or be undriven because the default value is defined before the `case`. +If the case match fails, `y` wouldn't infer memory or be undriven because the +default value is defined before the `case`. See also: - **case_default** - **explicit_case_default** The most relevant clauses of IEEE1800-2017 are: - - 12.5 Case statement From 986529188120a2c5122ed358a25297d802592ce3 Mon Sep 17 00:00:00 2001 From: Ronit Nallagatla Date: Tue, 9 Apr 2024 21:37:51 -0400 Subject: [PATCH 24/25] implicit_case_default: updated explanation --- ...rules-explanation-implicit_case_default.md | 24 ++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/md/syntaxrules-explanation-implicit_case_default.md b/md/syntaxrules-explanation-implicit_case_default.md index 6ec105a4..5037a197 100644 --- a/md/syntaxrules-explanation-implicit_case_default.md +++ b/md/syntaxrules-explanation-implicit_case_default.md @@ -3,22 +3,34 @@ default to be implicitly defined. Case statements without a `default` branch can cause signals to be undriven. Setting default values of signals at the top of an `always` procedures is good practice and ensures that signals are never metastable when a case match fails. For example, + ```sv always_comb begin y = 0; - case(x) + case (x) 1: y = 1; endcase end ``` -If the case match fails, `y` wouldn't infer memory or be undriven because the -default value is defined before the `case`. + +If the case match on `x` fails, `y` would not infer memory or be undriven +because the default value is defined before the `case`. + +This rule is a more lenient version of `case_default`. It adapts to a specific +coding style of setting default values to signals at the top of a procedural +block to ensure that signals have a default value regardless of the logic in the +procedural block. As such, this rule will only consider values set +**unconditionally** at the top of the procedural block as a default and will +disregard assignments made in conditional blocks like `if`/`else`, etc. If this +coding style is not preferred, it is strongly suggested to use the rules +mentioned below as they offer stricter guarantees. See also: - - **case_default** - - **explicit_case_default** + +- **case_default** +- **explicit_case_default** The most relevant clauses of IEEE1800-2017 are: -- 12.5 Case statement +- 12.5 Case statement From ade2a24c50e5302291ecbf900eaca571f6934e2d Mon Sep 17 00:00:00 2001 From: ronitnallagatla Date: Wed, 10 Apr 2024 01:42:10 +0000 Subject: [PATCH 25/25] Commit from GitHub Actions (Run mdgen) --- MANUAL.md | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/MANUAL.md b/MANUAL.md index fed50358..e3b02d15 100644 --- a/MANUAL.md +++ b/MANUAL.md @@ -2159,25 +2159,37 @@ default to be implicitly defined. Case statements without a `default` branch can cause signals to be undriven. Setting default values of signals at the top of an `always` procedures is good practice and ensures that signals are never metastable when a case match fails. For example, + ```sv always_comb begin y = 0; - case(x) + case (x) 1: y = 1; endcase end ``` -If the case match fails, `y` wouldn't infer memory or be undriven because the -default value is defined before the `case`. + +If the case match on `x` fails, `y` would not infer memory or be undriven +because the default value is defined before the `case`. + +This rule is a more lenient version of `case_default`. It adapts to a specific +coding style of setting default values to signals at the top of a procedural +block to ensure that signals have a default value regardless of the logic in the +procedural block. As such, this rule will only consider values set +**unconditionally** at the top of the procedural block as a default and will +disregard assignments made in conditional blocks like `if`/`else`, etc. If this +coding style is not preferred, it is strongly suggested to use the rules +mentioned below as they offer stricter guarantees. See also: - - **case_default** - - **explicit_case_default** + +- **case_default** +- **explicit_case_default** The most relevant clauses of IEEE1800-2017 are: -- 12.5 Case statement +- 12.5 Case statement