From 74653dc98e955a2d94001fd1bbdbf6a5c46d43f1 Mon Sep 17 00:00:00 2001
From: Blebowski <34539154+Blebowski@users.noreply.github.com>
Date: Sun, 26 Feb 2023 18:40:22 +0100
Subject: [PATCH] Add verbose option to Coverage Report generation. (#632)
---
nvc.1 | 2 +
src/nvc.c | 1 +
src/rt/cover.c | 116 ++++++++++++++++++++++++++++++++++++-------------
3 files changed, 88 insertions(+), 31 deletions(-)
diff --git a/nvc.1 b/nvc.1
index fc5b0eac..483d2da4 100644
--- a/nvc.1
+++ b/nvc.1
@@ -411,6 +411,8 @@ a single hierarchy in the code coverage report. Default
value of
.Ar limit
is 5000.
+.It Fl V , Fl -verbose
+Prints detailed hierarchy coverage when generating code coverage report.
.El
.El
.\" ------------------------------------------------------------
diff --git a/src/nvc.c b/src/nvc.c
index a8aa3c0c..e8e2f14f 100644
--- a/src/nvc.c
+++ b/src/nvc.c
@@ -1087,6 +1087,7 @@ static int coverage(int argc, char **argv)
{ "merge", required_argument, 0, 'm' },
{ "dont-print", required_argument, 0, 'd' },
{ "item-limit", required_argument, 0, 'l' },
+ { "verbose", no_argument, 0, 'V' },
{ 0, 0, 0, 0 }
};
diff --git a/src/rt/cover.c b/src/rt/cover.c
index 020b49e2..20472cbf 100644
--- a/src/rt/cover.c
+++ b/src/rt/cover.c
@@ -57,6 +57,7 @@ typedef struct _cover_report_ctx cover_report_ctx_t;
typedef struct _cover_file cover_file_t;
typedef struct _cover_scope cover_scope_t;
typedef struct _cover_exclude_ctx cover_exclude_ctx_t;
+typedef struct _cover_rpt_buf cover_rpt_buf_t;
typedef struct _cover_scope {
ident_t name;
@@ -68,19 +69,25 @@ typedef struct _cover_scope {
int sig_pos;
} cover_scope_t;
+struct _cover_rpt_buf {
+ text_buf_t *tb;
+ cover_rpt_buf_t *prev;
+};
+
struct _cover_tagging {
- int next_stmt_tag;
- int next_branch_tag;
- int next_toggle_tag;
- int next_expression_tag;
- int next_hier_tag;
- ident_t hier;
- tag_array_t tags;
- cover_mask_t mask;
- int array_limit;
- int array_depth;
- int report_item_limit;
- cover_scope_t *top_scope;
+ int next_stmt_tag;
+ int next_branch_tag;
+ int next_toggle_tag;
+ int next_expression_tag;
+ int next_hier_tag;
+ ident_t hier;
+ tag_array_t tags;
+ cover_mask_t mask;
+ int array_limit;
+ int array_depth;
+ int report_item_limit;
+ cover_rpt_buf_t *rpt_buf;
+ cover_scope_t *top_scope;
};
typedef struct {
@@ -136,6 +143,7 @@ struct _cover_report_ctx {
cover_chain_t ch_branch;
cover_chain_t ch_toggle;
cover_chain_t ch_expression;
+ int lvl;
};
static cover_file_t *files;
@@ -1281,10 +1289,16 @@ static void cover_print_timestamp(FILE *f)
fprintf(f, "");
}
-static void cover_print_hierarchy_summary(FILE *f, cover_stats_t *stats, ident_t hier,
- bool top, bool full_hier)
+static void cover_print_hierarchy_summary(FILE *f, cover_report_ctx_t *ctx, ident_t hier,
+ bool top, bool full_hier, bool flat)
{
ident_t print_hier = (full_hier) ? hier : ident_rfrom(hier, '.');
+ cover_stats_t *stats;
+
+ if (flat)
+ stats = &(ctx->flat_stats);
+ else
+ stats = &(ctx->nested_stats);
fprintf(f, "
\n"
" %s | \n",
@@ -1304,37 +1318,62 @@ static void cover_print_hierarchy_summary(FILE *f, cover_stats_t *stats, ident_t
fprintf(f, "
\n");
+ float perc_stmt = 0.0f;
+ float perc_branch = 0.0f;
+ float perc_toggle = 0.0f;
+ float perc_expr = 0.0f;
+
+ if (stats->total_stmts > 0)
+ perc_stmt = 100.0 * ((float)stats->hit_stmts) / stats->total_stmts;
+ if (stats->total_branches > 0)
+ perc_branch = 100.0 * ((float)stats->hit_branches) / stats->total_branches;
+ if (stats->total_toggles > 0)
+ perc_toggle = 100.0 * ((float)stats->hit_toggles) / stats->total_toggles;
+ if (stats->total_expressions > 0)
+ perc_expr = 100.0 * ((float)stats->hit_expressions) / stats->total_expressions;
+
if (top) {
notef("code coverage results for: %s", istr(hier));
- if (stats->total_stmts > 0)
- notef(" statement: %.1f %% (%d/%d)",
- 100.0 * ((double)stats->hit_stmts) / stats->total_stmts,
+ if (perc_stmt > 0)
+ notef(" statement: %.1f %% (%d/%d)", perc_stmt,
stats->hit_stmts, stats->total_stmts);
else
notef(" statement: N.A.");
- if (stats->total_branches > 0)
- notef(" branch: %.1f %% (%d/%d)",
- 100.0 * ((double)stats->hit_branches) / stats->total_branches,
+ if (perc_branch > 0)
+ notef(" branch: %.1f %% (%d/%d)", perc_branch,
stats->hit_branches, stats->total_branches);
else
notef(" branch: N.A.");
- if (stats->total_toggles > 0)
- notef(" toggle: %.1f %% (%d/%d)",
- 100.0 * ((double)stats->hit_toggles) / stats->total_toggles,
+ if (perc_toggle > 0)
+ notef(" toggle: %.1f %% (%d/%d)", perc_toggle,
stats->hit_toggles, stats->total_toggles);
else
notef(" toggle: N.A.");
- if (stats->total_expressions > 0)
- notef(" expression: %.1f %% (%d/%d)",
- 100.0 * ((double)stats->hit_expressions) / stats->total_expressions,
+ if (perc_expr > 0)
+ notef(" expression: %.1f %% (%d/%d)", perc_expr,
stats->hit_expressions, stats->total_expressions);
else
notef(" expression: N.A.");
}
+ else if (opt_get_int(OPT_VERBOSE) && !flat) {
+
+ cover_rpt_buf_t *new = xcalloc(sizeof(cover_rpt_buf_t));
+ new->tb = tb_new();
+ new->prev = ctx->tagging->rpt_buf;
+ ctx->tagging->rpt_buf = new;
+
+ tb_printf(new->tb,
+ "%*s %-*s %10.1f %% (%d/%d) %10.1f %% (%d/%d) %10.1f %% (%d/%d) %10.1f %% (%d/%d)",
+ ctx->lvl, "", 50-ctx->lvl, istr(ident_rfrom(ctx->start_tag->hier, '.')),
+ perc_stmt, stats->hit_stmts, stats->total_stmts,
+ perc_branch, stats->hit_branches, stats->total_branches,
+ perc_toggle, stats->hit_toggles, stats->total_toggles,
+ perc_expr, stats->hit_expressions, stats->total_expressions);
+ }
}
static void cover_print_code_line(FILE *f, loc_t loc, cover_line_t *line)
@@ -1831,9 +1870,10 @@ static cover_tag_t* cover_report_hierarchy(cover_report_ctx_t *ctx,
sub_ctx.start_tag = tag;
sub_ctx.parent = ctx;
sub_ctx.tagging = ctx->tagging;
+ sub_ctx.lvl = ctx->lvl + 2;
tag = cover_report_hierarchy(&sub_ctx, dir);
- cover_print_hierarchy_summary(f, &(sub_ctx.nested_stats),
- tag->hier, false, false);
+ cover_print_hierarchy_summary(f, &sub_ctx,
+ tag->hier, false, false, false);
// Add coverage from sub-hierarchies
ctx->nested_stats.hit_stmts += sub_ctx.nested_stats.hit_stmts;
@@ -1942,7 +1982,7 @@ static cover_tag_t* cover_report_hierarchy(cover_report_ctx_t *ctx,
fprintf(f, " Current Instance:
\n");
cover_print_hierarchy_header(f);
- cover_print_hierarchy_summary(f, &(ctx->flat_stats), tag->hier, false, true);
+ cover_print_hierarchy_summary(f, ctx, tag->hier, false, true, true);
cover_print_hierarchy_footer(f);
fprintf(f, " Details:
\n");
@@ -2003,10 +2043,24 @@ void cover_report(const char *path, cover_tagging_t *tagging, int item_limit)
cover_print_html_header(f, &top_ctx, true, "NVC code coverage report");
cover_print_hierarchy_header(f);
- cover_print_hierarchy_summary(f, &(top_ctx.nested_stats),
- top_ctx.start_tag->hier, true, true);
+ cover_print_hierarchy_summary(f, &top_ctx, top_ctx.start_tag->hier,
+ true, true, false);
cover_print_hierarchy_footer(f);
cover_print_timestamp(f);
+ if (opt_get_int(OPT_VERBOSE)) {
+ notef("Coverage for sub-hierarchies:");
+ printf("%-55s %-20s %-20s %-20s %-20s\n",
+ "Hierarchy", "Statement", "Branch", "Toggle", "Expression");
+ cover_rpt_buf_t *buf = tagging->rpt_buf;
+ while (buf) {
+ printf("%s\n", tb_get(buf->tb));
+ tb_free(buf->tb);
+ tagging->rpt_buf = buf->prev;
+ free(buf);
+ buf = tagging->rpt_buf;
+ };
+ }
+
fclose(f);
}
--
2.39.2