Update debug_emitv to include covergroup constructs ; update emit of covergroup debug content

Signed-off-by: Matthew Ballance <matt.ballance@gmail.com>
This commit is contained in:
Matthew Ballance 2026-03-07 01:31:05 +00:00
parent 464be2c85b
commit bcf6e6ac72
3 changed files with 625 additions and 3 deletions

View File

@ -312,6 +312,71 @@ class EmitVBaseVisitorConst VL_NOT_FINAL : public VNVisitorConst {
void visit(AstCoverInc*) override {} // N/A
void visit(AstCoverToggle*) override {} // N/A
void visit(AstCovergroup* nodep) override {
// AstCovergroup appears as a member inside the lowered AstClass body.
// The outer covergroup/endcovergroup wrapper is already emitted by the
// AstNodeModule visitor (verilogKwd()="covergroup" on AstClass::isCovergroup).
// Here we only emit the clocking event, if any.
if (nodep->eventp()) {
putfs(nodep, "");
iterateConst(nodep->eventp());
}
}
void visit(AstCoverpoint* nodep) override {
putfs(nodep, nodep->name() + ": coverpoint ");
iterateAndNextConstNull(nodep->exprp());
if (nodep->binsp() || nodep->optionsp()) {
puts(" {\n");
iterateAndNextConstNull(nodep->optionsp());
iterateAndNextConstNull(nodep->binsp());
puts("}");
}
puts(";\n");
}
void visit(AstCoverBin* nodep) override {
switch (nodep->binsType()) {
case VCoverBinsType::BINS_IGNORE: putfs(nodep, "ignore_bins "); break;
case VCoverBinsType::BINS_ILLEGAL: putfs(nodep, "illegal_bins "); break;
default: putfs(nodep, "bins "); break;
}
puts(nodep->name());
if (nodep->binsType() == VCoverBinsType::DEFAULT) {
puts(" = default");
} else if (nodep->transp()) {
puts(" = ");
for (AstNode* setp = nodep->transp(); setp; setp = setp->nextp()) {
if (setp != nodep->transp()) puts(", ");
iterateConst(setp);
}
} else if (nodep->rangesp()) {
puts(" = {");
for (AstNode* rangep = nodep->rangesp(); rangep; rangep = rangep->nextp()) {
if (rangep != nodep->rangesp()) puts(", ");
iterateConst(rangep);
}
puts("}");
}
puts(";\n");
}
void visit(AstCoverpointRef* nodep) override { putfs(nodep, nodep->name()); }
void visit(AstCoverCross* nodep) override {
putfs(nodep, nodep->name() + ": cross ");
for (AstNode* itemp = nodep->itemsp(); itemp; itemp = itemp->nextp()) {
if (itemp != nodep->itemsp()) puts(", ");
iterateConst(itemp);
}
puts(";\n");
}
void visit(AstCoverTransSet* nodep) override {
puts("(");
for (AstNode* itemp = nodep->itemsp(); itemp; itemp = itemp->nextp()) {
if (itemp != nodep->itemsp()) puts(" => ");
iterateConst(itemp);
}
puts(")");
}
void visit(AstCoverTransItem* nodep) override { iterateChildrenConst(nodep); }
void visit(AstCvtPackString* nodep) override {
putfs(nodep, "");
if (AstConst* const lhsConstp = VN_CAST(nodep->lhsp(), Const)) {
@ -750,6 +815,13 @@ class EmitVBaseVisitorConst VL_NOT_FINAL : public VNVisitorConst {
iterateAndNextConstNull(nodep->elsep());
puts(")");
}
void visit(AstInsideRange* nodep) override {
puts("[");
iterateAndNextConstNull(nodep->lhsp());
puts(":");
iterateAndNextConstNull(nodep->rhsp());
puts("]");
}
void visit(AstRange* nodep) override {
puts("[");
if (VN_IS(nodep->leftp(), Const) && VN_IS(nodep->rightp(), Const)) {
@ -947,6 +1019,9 @@ class EmitVBaseVisitorConst VL_NOT_FINAL : public VNVisitorConst {
puts("\n???? // "s + nodep->prettyTypeName() + " -> UNLINKED\n");
}
}
void visit(AstClassRefDType* nodep) override {
putfs(nodep, nodep->classp() ? EmitCUtil::prefixNameProtect(nodep->classp()) : nodep->prettyDTypeName(false));
}
void visit(AstRequireDType* nodep) override { iterateConst(nodep->lhsp()); }
void visit(AstModport* nodep) override {
puts(nodep->verilogKwd());

View File

@ -667,11 +667,504 @@ module Vt_debug_emitv_t;
end
restrict (@(posedge clk) ##1 a[0]
);
logic [2:0] cg_sig;
logic [1:0] cg_sig2;
covergroup Vt_debug_emitv_cg_basic;
function new;
cp_sig: coverpoint cg_sig {
bins low = {['sh0:'sh3]};
bins high = {['sh4:'sh6]};
bins dflt = default;
ignore_bins ign = {'sh7};
illegal_bins ill = {'sh5};
};
endfunction
int signed __Vint;
struct {
string name;
int signed weight;
int signed goal;
string comment;
int signed at_least;
int signed auto_bin_max;
int signed cross_num_print_missing;
bit cross_retain_auto_bins;
bit detect_overlap;
bit per_instance;
bit get_inst_coverage;
} option;
struct {
int signed weight;
int signed goal;
string comment;
bit strobe;
bit merge_instances;
bit distribute_first;
real real_interval;
} type_option;
function sample;
endfunction
function start;
endfunction
function stop;
endfunction
function get_coverage;
get_coverage =
???? // CRESET
;
input string covered_bins;
input string total_bins;
endfunction
function get_inst_coverage;
get_inst_coverage =
???? // CRESET
;
input string covered_bins;
input string total_bins;
endfunction
function set_inst_name;
input string name;
endfunction
endcovergroup
covergroup Vt_debug_emitv_cg_clocked;
@(posedge clk)function new;
cp_cyc: coverpoint cg_sig;
endfunction
int signed __Vint;
struct {
string name;
int signed weight;
int signed goal;
string comment;
int signed at_least;
int signed auto_bin_max;
int signed cross_num_print_missing;
bit cross_retain_auto_bins;
bit detect_overlap;
bit per_instance;
bit get_inst_coverage;
} option;
struct {
int signed weight;
int signed goal;
string comment;
bit strobe;
bit merge_instances;
bit distribute_first;
real real_interval;
} type_option;
function sample;
endfunction
function start;
endfunction
function stop;
endfunction
function get_coverage;
get_coverage =
???? // CRESET
;
input string covered_bins;
input string total_bins;
endfunction
function get_inst_coverage;
get_inst_coverage =
???? // CRESET
;
input string covered_bins;
input string total_bins;
endfunction
function set_inst_name;
input string name;
endfunction
endcovergroup
covergroup Vt_debug_emitv_cg_trans;
function new;
cp_t: coverpoint cg_sig {
bins t01 = (3'h0 => 3'h1);
bins t12 = (3'h1 => 3'h2);
};
endfunction
int signed __Vint;
struct {
string name;
int signed weight;
int signed goal;
string comment;
int signed at_least;
int signed auto_bin_max;
int signed cross_num_print_missing;
bit cross_retain_auto_bins;
bit detect_overlap;
bit per_instance;
bit get_inst_coverage;
} option;
struct {
int signed weight;
int signed goal;
string comment;
bit strobe;
bit merge_instances;
bit distribute_first;
real real_interval;
} type_option;
function sample;
endfunction
function start;
endfunction
function stop;
endfunction
function get_coverage;
get_coverage =
???? // CRESET
;
input string covered_bins;
input string total_bins;
endfunction
function get_inst_coverage;
get_inst_coverage =
???? // CRESET
;
input string covered_bins;
input string total_bins;
endfunction
function set_inst_name;
input string name;
endfunction
endcovergroup
covergroup Vt_debug_emitv_cg_cross;
function new;
cp_x: coverpoint cg_sig {
bins x0 = {'sh0};
bins x1 = {'sh1};
};
cp_y: coverpoint cg_sig2 {
bins y0 = {'sh0};
bins y1 = {'sh1};
};
cx: cross cp_x, cp_y;
endfunction
int signed __Vint;
struct {
string name;
int signed weight;
int signed goal;
string comment;
int signed at_least;
int signed auto_bin_max;
int signed cross_num_print_missing;
bit cross_retain_auto_bins;
bit detect_overlap;
bit per_instance;
bit get_inst_coverage;
} option;
struct {
int signed weight;
int signed goal;
string comment;
bit strobe;
bit merge_instances;
bit distribute_first;
real real_interval;
} type_option;
function sample;
endfunction
function start;
endfunction
function stop;
endfunction
function get_coverage;
get_coverage =
???? // CRESET
;
input string covered_bins;
input string total_bins;
endfunction
function get_inst_coverage;
get_inst_coverage =
???? // CRESET
;
input string covered_bins;
input string total_bins;
endfunction
function set_inst_name;
input string name;
endfunction
endcovergroup
Vt_debug_emitv_cg_basic cg_basic_instVt_debug_emitv_cg_basic;
cg_basic_inst = new();
Vt_debug_emitv_cg_clocked cg_clocked_instVt_debug_emitv_cg_clocked;
cg_clocked_inst = new();
Vt_debug_emitv_cg_trans cg_trans_instVt_debug_emitv_cg_trans;
cg_trans_inst = new();
Vt_debug_emitv_cg_cross cg_cross_instVt_debug_emitv_cg_cross;
cg_cross_inst = new();
endmodule
package Vt_debug_emitv_std;
class Vt_debug_emitv_semaphore;
int signed m_keyCount;
function new;
input int signed keyCount;
m_keyCount = keyCount;
endfunction
task put;
input int signed keyCount;
m_keyCount = (m_keyCount + keyCount);
endtask
task get;
input int signed keyCount;
while ((m_keyCount < keyCount)) begin
begin
???? // WAIT
(m_keyCount >= keyCount)end
end
m_keyCount = (m_keyCount - keyCount);
endtask
function try_get;
input int signed keyCount;
begin : label3
try_get =
???? // CRESET
;
if ((m_keyCount >= keyCount)) begin
begin
m_keyCount = (m_keyCount -
keyCount);
try_get = 'sh1;
disable label3;
end
end
try_get = 'sh0;
disable label3;
end
endfunction
endclass
class Vt_debug_emitv_process;
typedef enum int signed{
FINISHED = 32'h0,
RUNNING = 32'h1,
WAITING = 32'h2,
SUSPENDED = 32'h3,
KILLED = 32'h4
} state;
VlProcessRef m_process;
function self;
Vt_debug_emitv_process pVt_debug_emitv_process;
begin : label4
self =
???? // CRESET
;
p = new();
$c(p.m_process = vlProcess;);
self = p;
disable label4;
end
endfunction
task set_status;
input int signed s;
$c(m_process->state(s););
endtask
function status;
begin : label5
status =
???? // CRESET
;
status = ($c(m_process->state()));
disable label5;
end
endfunction
task kill;
set_status(process::KILLED);
endtask
task suspend;
$error("std::process::suspend() not supported");
$stop;
endtask
task resume;
set_status(process::RUNNING);
endtask
task await;
???? // WAIT
((status() == process::FINISHED) || (status()
==
process::
KILLED))endtask
task killQueue;
ref Vt_debug_emitv_process processQueue[$]Vt_debug_emitv_process;
while ((processQueue.size() > 'sh0)) begin
begin
kill();
end
end
endtask
???? // SYSTEMCSECTION
???? // SYSTEMCSECTION
???? // SYSTEMCSECTION
???? // SYSTEMCSECTION
???? // SYSTEMCSECTION
???? // SYSTEMCSECTION
???? // SYSTEMCSECTION
???? // SYSTEMCSECTION
???? // SYSTEMCSECTION
???? // SYSTEMCSECTION
???? // SYSTEMCSECTION
???? // SYSTEMCSECTION
???? // SYSTEMCSECTION
???? // SYSTEMCSECTION
???? // SYSTEMCSECTION
???? // SYSTEMCSECTION
???? // SYSTEMCSECTION
???? // SYSTEMCSECTION
function get_randstate;
string s;
begin : label6
get_randstate =
???? // CRESET
;
s = string'($c(0));
$c(s = m_process->randstate(););
get_randstate = s;
disable label6;
end
endfunction
task set_randstate;
input string s;
$c(m_process->randstate(s););
endtask
function new;
endfunction
process::FINISHEDprocess::KILLEDprocess::RUNNINGprocess::SUSPENDEDprocess::WAITINGendclass
function randomize;
randomize = 'sh0;
endfunction
typedef struct {
string name;
int signed weight;
int signed goal;
string comment;
int signed at_least;
int signed auto_bin_max;
int signed cross_num_print_missing;
bit cross_retain_auto_bins;
bit detect_overlap;
bit per_instance;
bit get_inst_coverage;
} vl_covergroup_options_t;
typedef struct {
int signed weight;
int signed goal;
string comment;
int signed at_least;
int signed auto_bin_max;
bit detect_overlap;
} vl_coverpoint_options_t;
typedef struct {
int signed weight;
int signed goal;
string comment;
int signed at_least;
int signed cross_num_print_missing;
bit cross_retain_auto_bins;
} vl_cross_options_t;
typedef struct {
int signed weight;
int signed goal;
string comment;
bit strobe;
bit merge_instances;
bit distribute_first;
real real_interval;
} vl_covergroup_type_options_t;
typedef struct {
int signed weight;
int signed goal;
string comment;
real real_interval;
} vl_coverpoint_type_options_t;
typedef struct {
int signed weight;
int signed goal;
string comment;
} vl_cross_type_options_t;
endpackage
package Vt_debug_emitv___024unit;
class Vt_debug_emitv_Cls;
int signed member;
member = 'sh1;
covergroup Vt_debug_emitv___vlAnonCG_cg_in_class;
function new;
cp_m: coverpoint member {
bins one = {'sh1};
bins two = {'sh2};
};
endfunction
int signed __Vint;
struct {
string name;
int signed weight;
int signed goal;
string comment;
int signed at_least;
int signed auto_bin_max;
int signed cross_num_print_missing;
bit cross_retain_auto_bins;
bit detect_overlap;
bit per_instance;
bit get_inst_coverage;
} option;
struct {
int signed weight;
int signed goal;
string comment;
bit strobe;
bit merge_instances;
bit distribute_first;
real real_interval;
} type_option;
function sample;
endfunction
function start;
endfunction
function stop;
endfunction
function get_coverage;
get_coverage =
???? // CRESET
;
input string covered_bins;
input string total_bins;
endfunction
function get_inst_coverage;
get_inst_coverage =
???? // CRESET
;
input string covered_bins;
input string total_bins;
endfunction
function set_inst_name;
input string name;
endfunction
endcovergroup
Vt_debug_emitv___vlAnonCG_cg_in_class cg_in_classVt_debug_emitv___vlAnonCG_cg_in_class;
task method;
if ((this != this)) begin
$stop;
@ -698,13 +1191,13 @@ module Vt_debug_emitv_sub;
endtask
function f;
input int signed v;
begin : label3
begin : label7
if ((v == 'sh0)) begin
f = 'sh21;
disable label3;
disable label7;
end
f = ({32'h1{{31'h0, v[2]}}} + 32'h1);
disable label3;
disable label7;
end
endfunction
real r;

View File

@ -21,6 +21,12 @@ endpackage
class Cls;
int member = 1;
covergroup cg_in_class;
cp_m: coverpoint member {
bins one = {1};
bins two = {2};
}
endgroup
function void method;
if (this != this) $stop;
endfunction
@ -340,6 +346,54 @@ module t (/*AUTOARG*/
end
restrict property (@(posedge clk) ##1 a[0]);
// Covergroup constructs - exercise AstCovergroup, AstCoverpoint, AstCoverBin, AstCoverCross
logic [2:0] cg_sig;
logic [1:0] cg_sig2;
// Basic covergroup: value bins, default bin, ignore_bins, illegal_bins, options
covergroup cg_basic;
option.per_instance = 1;
option.weight = 2;
cp_sig: coverpoint cg_sig {
bins low = {[0:3]};
bins high = {[4:6]};
bins dflt = default;
ignore_bins ign = {7};
illegal_bins ill = {5};
}
endgroup
// Covergroup with clocking event
covergroup cg_clocked @(posedge clk);
cp_cyc: coverpoint cg_sig;
endgroup
// Covergroup with transition bins
covergroup cg_trans;
cp_t: coverpoint cg_sig {
bins t01 = (3'b000 => 3'b001);
bins t12 = (3'b001 => 3'b010);
}
endgroup
// Covergroup with cross coverage
covergroup cg_cross;
cp_x: coverpoint cg_sig {
bins x0 = {0};
bins x1 = {1};
}
cp_y: coverpoint cg_sig2 {
bins y0 = {0};
bins y1 = {1};
}
cx: cross cp_x, cp_y;
endgroup
cg_basic cg_basic_inst = new;
cg_clocked cg_clocked_inst = new;
cg_trans cg_trans_inst = new;
cg_cross cg_cross_inst = new;
endmodule
module sub(input logic clk);