From 477b50e08bb243c1eaf2df6e80c8f6e830de84a6 Mon Sep 17 00:00:00 2001 From: Luca Colagrande Date: Tue, 2 Jun 2026 19:18:01 +0200 Subject: [PATCH] Extend Spyglass lint to lint/lint_rtl goal --- lint/spyglass.tcl | 21 ++++++++++++++++++++- src/cc_addr_decode_napot.sv | 37 +++++++++++++++++++++++-------------- src/cc_id_queue.sv | 5 ++--- src/cc_sub_per_hash.sv | 2 +- 4 files changed, 46 insertions(+), 19 deletions(-) diff --git a/lint/spyglass.tcl b/lint/spyglass.tcl index 26bf1a4f..3c6f3e68 100644 --- a/lint/spyglass.tcl +++ b/lint/spyglass.tcl @@ -3,13 +3,32 @@ current_methodology $env(SPYGLASS_HOME)/GuideWare/latest/block/rtl_handoff read_file -type sourcelist analyze.tcl +set_option top $env(IP) set_option enableSV09 yes set_option allow_module_override yes set_option designread_disable_flatten no set_option nopreserve yes +# Ignore unused macro definition automatically defined by bender. waive -rules CMD_define02 -msg "*TARGET_FLIST*" +# Ignore multiple assignments in always_comb block, which is common e.g. with default assignments. +waive -rules W415a +# Suppress warning on variables that are set but not read. It is common e.g. to have variables that +# are only used in assertions. +waive -rules W528 +# Allow unconnected outputs +waive -rules W287b +# In certain IPs, there are intentional blocking assignments in always_ff blocks +if {$env(IP) in {cc_clk_int_div cc_clk_int_div_static}} { + waive -rules W336 +} +# Ignore if clock enable pin is always enabled/disabled +waive -rules FlopEConst +# Suppress warning on inputs that are declared but not read. It is common e.g. to have inputs that +# are only used in certain parameterizations. +waive -rules W240 -set result [compile_design -top $env(IP)] +set result [run_goal -goal lint/lint_rtl] set code [lindex $result 0] + exit -force $code diff --git a/src/cc_addr_decode_napot.sv b/src/cc_addr_decode_napot.sv index b5824ed0..f9310cf0 100644 --- a/src/cc_addr_decode_napot.sv +++ b/src/cc_addr_decode_napot.sv @@ -21,11 +21,16 @@ module cc_addr_decode_napot #( parameter int unsigned NoRules = 32'd1, /// Address type inside the rules and to decode. parameter type addr_t = logic, + /// The output index type `idx_t` can be specified either with the width `IdxWidth` + /// or directly with the type `idx_t`. By default, it will use the maximum index + /// `NoIndices` to calculate the required width. + parameter int unsigned IdxWidth = cc_pkg::idx_width(NoIndices), + parameter type idx_t = logic [IdxWidth-1:0], /// Rule packed struct type. /// The NAPOT address decoder expects three fields in `rule_t`: /// /// typedef struct packed { - /// int unsigned idx; + /// idx_t idx; /// addr_t base; /// addr_t mask; /// } rule_t; @@ -33,15 +38,11 @@ module cc_addr_decode_napot #( /// - `idx`: index of the rule, has to be < `NoIndices`. /// - `base`: base address whose specified bits should match `addr_i`. /// - `mask`: set for bits which are to be checked to determine a match. - parameter type rule_t = logic, - /// Dependent parameter, do **not** overwite! - /// - /// Width of the `idx_o` output port. - localparam int unsigned IdxWidth = cc_pkg::idx_width(NoIndices), - /// Dependent parameter, do **not** overwite! - /// - /// Type of the `idx_o` output port. - localparam type idx_t = logic [IdxWidth-1:0] + parameter type rule_t = struct packed { + idx_t idx; + addr_t base; + addr_t mask; + } ) ( /// Address to decode. input addr_t addr_i, @@ -67,11 +68,19 @@ module cc_addr_decode_napot #( // Rename struct field names to those expected by `cc_addr_decode` typedef struct packed { - int unsigned idx; - addr_t start_addr; - addr_t end_addr; + idx_t idx; + addr_t start_addr; + addr_t end_addr; } rule_range_t; + rule_range_t [NoRules-1:0] range_addr_map; + + for (genvar i = 0; i < NoRules; i++) begin : gen_rule_assign + assign range_addr_map[i].idx = addr_map_i[i].idx; + assign range_addr_map[i].start_addr = addr_map_i[i].base; + assign range_addr_map[i].end_addr = addr_map_i[i].mask; + end + cc_addr_decode_dync #( .NoIndices ( NoIndices ) , .NoRules ( NoRules ), @@ -80,7 +89,7 @@ module cc_addr_decode_napot #( .Napot ( 1 ) ) i_addr_decode_dync ( .addr_i, - .addr_map_i, + .addr_map_i ( range_addr_map ), .idx_o, .dec_valid_o, .dec_error_o, diff --git a/src/cc_id_queue.sv b/src/cc_id_queue.sv index e3556ed3..f8dd60b9 100644 --- a/src/cc_id_queue.sv +++ b/src/cc_id_queue.sv @@ -401,10 +401,9 @@ module cc_id_queue #( always_ff @(posedge clk_i, negedge rst_ni) begin if (!rst_ni) begin // Set free bit of linked data entries, all other bits are don't care. - linked_data_q[i] <= '0; - linked_data_q[i].free <= 1'b1; + linked_data_q[i] <= '{free: 1'b1, default: '0}; end else begin - linked_data_q[i] <= linked_data_d[i]; + linked_data_q[i] <= linked_data_d[i]; end end end diff --git a/src/cc_sub_per_hash.sv b/src/cc_sub_per_hash.sv index 665b4b8c..e691e815 100644 --- a/src/cc_sub_per_hash.sv +++ b/src/cc_sub_per_hash.sv @@ -85,7 +85,7 @@ module cc_sub_per_hash #( // output assignment, take the bottom bits of the last round assign hash_o = xored[NoRounds-1][HashWidth-1:0]; // for onehot run trough a decoder - assign hash_onehot_o = 1 << hash_o; + assign hash_onehot_o = 1'b1 << hash_o; // PRG is MLCG (multiplicative linear congruential generator) // Constant values the same as RtlUniform from Native API