`ifndef COVERAGE `define COVERAGE class coverage; mailbox mon2cov; bit[7:0] A; bit[7:0] B; operation_t op_set; covergroup op_cov; coverpoint op_set { bins single_cycle[] = {[add_op : xor_op], rst_op,no_op}; bins multi_cycle = {mul_op, div_op}; bins opn_rst[] = ([add_op:div_op] => rst_op); bins rst_opn[] = (rst_op => [add_op:div_op]); bins sngl_mul[] = ([add_op:xor_op],no_op => mul_op); bins mul_sngl[] = (mul_op => [add_op:xor_op], no_op); bins sngl_div[] = ([add_op:xor_op],no_op => div_op); bins div_sngl[] = (div_op => [add_op:xor_op], no_op); bins mul_div[] = (mul_op => div_op); bins div_mul[] = (div_op => mul_op); bins twoops[] = ([add_op:div_op] [* 2]); bins manymul = (mul_op [* 3:5]); bins manydiv = (div_op [* 3:5]); } endgroup covergroup zeros_or_ones_on_ops; all_ops : coverpoint op_set { ignore_bins null_ops = {rst_op, no_op};} a_leg: coverpoint A { bins zeros = {'h00}; bins others= {['h01:'hFE]}; bins ones = {'hFF}; } b_leg: coverpoint B { bins zeros = {'h00}; bins others= {['h01:'hFE]}; bins ones = {'hFF}; } op_00_FF: cross a_leg, b_leg, all_ops { bins add_00 = binsof (all_ops) intersect {add_op} && (binsof (a_leg.zeros) || binsof (b_leg.zeros)); bins add_FF = binsof (all_ops) intersect {add_op} && (binsof (a_leg.ones) || binsof (b_leg.ones)); bins and_00 = binsof (all_ops) intersect {and_op} && (binsof (a_leg.zeros) || binsof (b_leg.zeros)); bins and_FF = binsof (all_ops) intersect {and_op} && (binsof (a_leg.ones) || binsof (b_leg.ones)); bins xor_00 = binsof (all_ops) intersect {xor_op} && (binsof (a_leg.zeros) || binsof (b_leg.zeros)); bins xor_FF = binsof (all_ops) intersect {xor_op} && (binsof (a_leg.ones) || binsof (b_leg.ones)); bins mul_00 = binsof (all_ops) intersect {mul_op} && (binsof (a_leg.zeros) || binsof (b_leg.zeros)); bins mul_FF = binsof (all_ops) intersect {mul_op} && (binsof (a_leg.ones) || binsof (b_leg.ones)); bins mul_max = binsof (all_ops) intersect {mul_op} && (binsof (a_leg.ones) && binsof (b_leg.ones)); bins div_00 = binsof (all_ops) intersect {div_op} && (binsof (a_leg.zeros) || binsof (b_leg.zeros)); bins div_FF = binsof (all_ops) intersect {div_op} && (binsof (a_leg.ones) || binsof (b_leg.ones)); bins div_max = binsof (all_ops) intersect {div_op} && (binsof (a_leg.ones) && binsof (b_leg.ones)); ignore_bins others_only = binsof(a_leg.others) && binsof(b_leg.others); } endgroup function new (mailbox mon2cov_new); op_cov = new(); zeros_or_ones_on_ops = new(); if(mon2cov_new == null)begin $display("%0t -> coverage : ERROR -> mon2cov is null",$time); $finish; end else this.mon2cov = mon2cov_new; endfunction task run(); transaction tr; forever begin mon2cov.get(tr); A = tr.A; B = tr.B; op_set = tr.op; op_cov.sample(); zeros_or_ones_on_ops.sample(); $display("%0t -> coverage : tr is %s",$time,tr.convert2string()); end endtask endclass `endif
关于覆盖率的测试一定要自己研究一下,以应对面试。
覆盖率测试主要测试三个参数,分别是A、B以及操作指令op_set,为此定义了两个覆盖组:
op_cov
以及zeros_or_ones_ops
。覆盖组 op_cov
coverpoint op_set
:定义了一个覆盖点op_set
,用于收集操作类型的覆盖率。
bins single_cycle[]
:单周期操作的bins。
bins multi_cycle
:多周期操作的bins。
bins opn_rst[]
和bins rst_opn[]
:操作和复位操作之间的转换。
bins sngl_mul[]
和bins mul_sngl[]
:单周期操作和乘法操作之间的转换。
bins sngl_div[]
和bins div_sngl[]
:单周期操作和除法操作之间的转换。
bins mul_div[]
和bins div_mul[]
:乘法和除法操作之间的转换。
bins twoops[]
:连续两个操作。
bins manymul
和bins manydiv
:连续多个乘法或除法操作。
覆盖组 zeros_or_ones_on_ops
all_ops
:覆盖点op_set
,忽略rst_op
和no_op
。
a_leg
和b_leg
:覆盖点A
和B
,分别定义了zeros
、others
和ones
的bins。
op_00_FF
:交叉覆盖点a_leg
、b_leg
和all_ops
,定义了不同操作类型下A
和B
为00
或FF
的bins。
这两个覆盖组定义了许多覆盖点,总归来说就是就是尽可能覆盖到所有可能的情况,比如单周期,多周期,乘法除法转换等等。更详细地说一下这两个覆盖组的区别,
op_cov
着重考虑所有操作类型都覆盖到,而且强调对连续操作的覆盖测试;zeros_or_ones_ops
更看重操作数A和B取值以及操作类型组合的覆盖测试率,重点表征边缘边界部分的覆盖效果。我的程序主要是功能覆盖率