diff --git a/src/V3EmitV.cpp b/src/V3EmitV.cpp index 1cc1245f3..5e7eccb70 100644 --- a/src/V3EmitV.cpp +++ b/src/V3EmitV.cpp @@ -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()); diff --git a/test_regress/t/t_debug_emitv.out b/test_regress/t/t_debug_emitv.out index ac97e5a60..c4da728af 100644 --- a/test_regress/t/t_debug_emitv.out +++ b/test_regress/t/t_debug_emitv.out @@ -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; diff --git a/test_regress/t/t_debug_emitv.v b/test_regress/t/t_debug_emitv.v index 9594487f1..3d2dd6607 100644 --- a/test_regress/t/t_debug_emitv.v +++ b/test_regress/t/t_debug_emitv.v @@ -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);