verible icon indicating copy to clipboard operation
verible copied to clipboard

Add dff-name-style

Open IEncinas10 opened this issue 11 months ago • 10 comments

Addresses https://github.com/chipsalliance/verible/issues/1913 with some minor changes

  • Suffixes are totally configurable, and different styles can be combined.
  • If a parameter (input/output) is set to "", no checks are performed. Basically, if we configure the rule with "input:;output:", nothing happens. This might be useful if anyone wants to check the naming conventions for just the output or the input.
  • I changed the rule from "dff-name-suffix" to "dff-name-style" to mimic other rules already implemented. I guess it does not matter too much, just pointing it out.

Unimplemented

logic data_d, data_q;
always_ff @(posedge clk) begin
    assign data_d <= a; // should be driven by assign or always_comb
end
assign data_q = b; // should be driven by always_ff

These kinds of checks are not implemented (yet?) although they should be fairly easy to add. My idea for it was:

  • Scan for blocking assignments and match them to valid_output_suffixes https://github.com/chipsalliance/verible/blob/a1cd07b13572f19df5776381eb52287e994df392/verilog/analysis/checkers/always_ff_non_blocking_rule.cc#L94
  • Check the nonblocking assignments lhs against valid_input_suffixes

I wasn't sure it was worth the possible performance downside (!?) (maybe I'm overly pessimistic) I would add it if it is considered relevant.


Pinging @sifferman. Let me know if you have any suggestions/complaints. Sorry for the delay 😄

IEncinas10 avatar Jul 26 '23 21:07 IEncinas10

Codecov Report

Patch coverage: 100.00% and project coverage change: +0.02% :tada:

Comparison is base (fa07295) 92.85% compared to head (d7fb78f) 92.88%. Report is 14 commits behind head on master.

:exclamation: Your organization is not using the GitHub App Integration. As a result you may experience degraded service beginning May 15th. Please install the Github App Integration for your organization. Read more.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1983      +/-   ##
==========================================
+ Coverage   92.85%   92.88%   +0.02%     
==========================================
  Files         355      356       +1     
  Lines       26272    26373     +101     
==========================================
+ Hits        24395    24496     +101     
  Misses       1877     1877              
Files Changed Coverage Δ
verilog/CST/statement.cc 97.85% <100.00%> (+0.06%) :arrow_up:
verilog/analysis/checkers/dff_name_style_rule.cc 100.00% <100.00%> (ø)

... and 4 files with indirect coverage changes

:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.

codecov-commenter avatar Jul 26 '23 22:07 codecov-commenter

Wow! Really fantastic!

I looked through the tests you wrote, and they all look really good.

Though I was hoping for the checks that are unimplemented: that _q/_reg nets are only driven with <=, and that _d/_next nets are not driven with =.

I assume the performance wouldn't be terrible considering that this is a similar check to always-ff-non-blocking and always-comb-blocking.

sifferman avatar Jul 26 '23 22:07 sifferman

You're right! Let's see if https://github.com/chipsalliance/verible/pull/1912 lands. It introduces some helpers to handle blocking assignments that will be helpful.

For those extra checks I would appreciate a bit of help as I'm not too experienced in Verilog. We should detect wrong types of assignments to variables considering their suffixes, but I'm not sure if I'm aware of every possibility.

Using the following references and assuming "_q" and "_n" suffixes:

  • https://github.com/chipsalliance/verible/blob/master/verilog/CST/verilog_nonterminals.h
  • https://github.com/chipsalliance/verible/blob/master/verilog/parser/verilog.y
  • https://www.chipverify.com/verilog/verilog-assignments

DFF Outputs

data_q = x; // Blocking assignment
assign data_q = x; // Continuous assignment
wire data_q = 1; // Net declaration assignment
data_q &= x; // Assign modify statements
data_q++; // Increment/decrement statements
  • Procedural continuous assignments
  • Procedural continuous deassignments
  • Procedural continuous force
  • Procedural continuous release

DFF Inputs

reg data_n = x; // Variable declaration assignment
data_n <= x; // Nonblocking assignment

IEncinas10 avatar Jul 26 '23 23:07 IEncinas10

Hmm, I'm worried about trying to list all the combinational assignments. I feel like a better way is to:

  • ensure all occurrences of a LHS dff-output are assigned by <= inside an always_ff, and
  • ensure all nets driven by <= inside always_ff are dff-outputs

The only way to create DFFs are with always_ff blocks. Everything else is combinational

sifferman avatar Jul 26 '23 23:07 sifferman

Also, non-blocking assignments are generally only valid inside always_ff blocks anyways. So I bet you can just continue using <= as your check for DFFs

Thanks again!

sifferman avatar Jul 26 '23 23:07 sifferman

Also CC @fangism as he might be interested in this. I'll review within the next couple of days as time permits.

What I can already say: there are a bunch of integration tests of lint rules in verilog/tools/lint/ , see the BUILD there and the testdata/ subdirectory. Please add a test there as well.

And, probably for a few of the other rules you have been working on recently, I might've forgotten to point that out then.

hzeller avatar Jul 31 '23 22:07 hzeller

Thanks for the reviews. I'll work on those integration tests.

Separately, I worked a bit on the extra checks, but I'm not sure how to proceed as I added some of the needed helper already in https://github.com/chipsalliance/verible/pull/1912. Should I just add them here? I got away with a cheap trick for most of the cases as a temporary fix. Should this extra check be hidden under another configuration file?

Added screenshot and diff for a quick overview.

image

diff --git a/verilog/analysis/checkers/BUILD b/verilog/analysis/checkers/BUILD
index 7fcfec0d..aeeabb07 100644
--- a/verilog/analysis/checkers/BUILD
+++ b/verilog/analysis/checkers/BUILD
@@ -2134,6 +2134,7 @@ cc_library(
         "//common/analysis:syntax-tree-lint-rule",
         "//common/analysis/matcher",
         "//common/analysis/matcher:bound-symbol-manager",
+        "//common/analysis/matcher:core-matchers",
         "//common/strings:naming-utils",
         "//common/text:config-utils",
         "//common/text:symbol",
diff --git a/verilog/analysis/checkers/dff_name_style_rule.cc b/verilog/analysis/checkers/dff_name_style_rule.cc
index ebcc757a..92d7b685 100644
--- a/verilog/analysis/checkers/dff_name_style_rule.cc
+++ b/verilog/analysis/checkers/dff_name_style_rule.cc
@@ -25,6 +25,7 @@
 #include "absl/strings/string_view.h"
 #include "common/analysis/lint_rule_status.h"
 #include "common/analysis/matcher/bound_symbol_manager.h"
+#include "common/analysis/matcher/core_matchers.h"
 #include "common/analysis/matcher/matcher.h"
 #include "common/strings/naming_utils.h"
 #include "common/text/config_utils.h"
@@ -76,8 +77,37 @@ static const Matcher &AlwaysFFMatcher() {
 void DffNameStyleRule::HandleSymbol(const verible::Symbol &symbol,
                                     const SyntaxTreeContext &context) {
   verible::matcher::BoundSymbolManager manager;
-  if (!AlwaysFFMatcher().Matches(symbol, &manager) ||
-      (valid_input_suffixes.empty() && valid_output_suffixes.empty())) {
+  if (valid_input_suffixes.empty() && valid_output_suffixes.empty()) return;
+
+  // Types of assignments intended for DFF inputs
+  static const Matcher matcher = verible::matcher::AnyOf(
+      NodekContinuousAssignmentStatement(), NodekNetVariableAssignment(),
+      NodekNetDeclarationAssignment(), NodekAssignModifyStatement(),
+      NodekIncrementDecrementExpression());
+  if (matcher.Matches(symbol, &manager)) {
+    const verible::SyntaxTreeNode &node = SymbolCastToNode(symbol);
+    if (node.children().empty()) return;
+    const verible::Symbol *lhs = node.children().front().get();
+    absl::string_view lhs_str = verible::StringSpanOfSymbol(*lhs);
+
+    //TODO: helpers. Also, ++data_ff doesnt work (not 1st child)
+    const bool found_id = std::any_of(valid_output_suffixes.cbegin(),
+                                      valid_output_suffixes.cend(),
+                                      [&](const std::string &suffix) -> bool {
+                                        return lhs_str.size() > suffix.size() &&
+                                               absl::EndsWith(lhs_str, suffix);
+                                      });
+
+    if (!found_id) return;
+    violations_.insert(LintViolation(
+        *lhs,
+        absl::StrCat(lhs_str,
+                     " should be driven by a nonblocking assignment "
+                     "inside an always_ff block"),
+        context));
+  }
+
+  if (!AlwaysFFMatcher().Matches(symbol, &manager)) {
     return;
   }

IEncinas10 avatar Aug 01 '23 13:08 IEncinas10