Sunday, November 8, 2009

SV: implication constraint and its implication/effect

SystemVerilog has a nice implication constraint feature to guard constraint expressions on their applicability. Last week during our SystemVerilog + methodology workshop one of the attendees faced an interesting issue. She was creating a min-VIP for APB as part of our SystemVerilog 10-day workshop (See details at: http://www.cvcblr.com/trng_profiles/CVC_VSV_WK_profile.pdf ).

She wrote a APB scenario code that was intended to create a sequence of transactions with varying address, kind etc. Here is a code snippet:

constraint cst_xactn_kind{
       if(this.scenario_kind == this.sc_id)
       this.length == 10;
       foreach (items[i])
        {
          (i==0) -> items[i].apb_op_kind == APB_WR;items[i].addr == 'b01; items[i].wdata == 'd11;


               (i==1) -> items[i].apb_op_kind == APB_WR;items[i].addr == 'b11; items[i].wdata == 'd12;
                       }
     }

Spot anything wrong in the above code? Perhaps not for the unsuspecting, bare eyes. Code intention: Keep the:

0th transaction KIND == WRITE, address == 01, data == 11;

1st transaction KIND == WRITE, address == 3, data == 12;

Read again the code – it seems to imply just that, isn’t it? Let’s run it.

Here is what Questa says:

###########################################################################                    
#                     WELCOME !!!
#                      APB PROJECT USING VMM
#                     DONE BY PRIYA @ CVC
#                     DATE:21stOctober2009
############################################################################
# Normal[NOTE] on APB_PROGRAM(0) at                    0:
#     APB PROJECT:       Start of APB Random test!    
# ****************************************************************************
# Normal[NOTE] on APB_ENV(0) at              0.00 ns:
#     APB PROJECT: Sim shall run for 10 number of transactions
# Normal[NOTE] on APB_ENV(0) at              0.00 ns:
#                     Reset!!!!!!!!!               
# Normal[NOTE] on APB_ENV(0) at            230.00 ns:
#                    Reset Release!
# ****************************************************************************
# *FATAL*[FAILURE] on APB Generator Scenario Generator(APB_GENERATOR) at            730.00 ns:
#     Cannot randomize scenario descriptor #0

Puzzled? What is wrong? Review by the code author herself few times didn’t reveal anything wrong (bias towards own code?).

Seek expert assistance.. Questa has a simple flag to bring up solver debugger as: vsim –solvefaildebug Let’s try that now..

 

# ../tb_src_scenario/apb_scenario_gen.sv(1): randomize() failed due to conflicts between the following constraints:
#     ../tb_src_scenario/apb_scenario_gen.sv(25): the_scenario.cst_xactn_kind { (the_scenario.items[0].addr == 32'h00000001); }
#     ../tb_src_scenario/apb_scenario_gen.sv(1): the_scenario.repetition { (the_scenario.repeated == 32'h00000000); }
#     ../tb_src_scenario/apb_scenario_gen.sv(25): the_scenario.cst_xactn_kind { (the_scenario.items[0].apb_op_kind == APB_WR); }
#     ../tb_src_scenario/apb_scenario_gen.sv(26): the_scenario.cst_xactn_kind { (the_scenario.items[0].addr == 32'h00000003); }
#     ../tb_src_scenario/apb_scenario_gen.sv(26): the_scenario.cst_xactn_kind { (the_scenario.items[0].wdata == 32'h0000000c); }
#     ../tb_src_scenario/apb_scenario_gen.sv(26): the_scenario.cst_xactn_kind { (the_scenario.items[1].apb_op_kind == APB_WR); }
#     ../tb_src_scenario/apb_scenario_gen.sv(26): the_scenario.cst_xactn_kind { (the_scenario.items[1].addr == 32'h00000003); }
#     ../tb_src_scenario/apb_scenario_gen.sv(26): the_scenario.cst_xactn_kind { (the_scenario.items[1].wdata == 32'h0000000c); }
#     ../tb_src_scenario/apb_scenario_gen.sv(26): the_scenario.cst_xactn_kind { (the_scenario.items[2].addr == 32'h00000003); }
#     ../tb_src_scenario/apb_scenario_gen.sv(26): the_scenario.cst_xactn_kind { (the_scenario.items[2].wdata == 32'h0000000c); }
#     ../tb_src_scenario/apb_scenario_gen.sv(26): the_scenario.cst_xactn_kind { (the_scenario.items[3].addr == 32'h00000003); }
#     ../tb_src_scenario/apb_scenario_gen.sv(26): the_scenario.cst_xactn_kind { (the_scenario.items[3].wdata == 32'h0000000c); }
#     ../tb_src_scenario/apb_scenario_gen.sv(26): the_scenario.cst_xactn_kind { (the_scenario.items[4].addr == 32'h00000003); }
#     ../tb_src_scenario/apb_scenario_gen.sv(26): the_scenario.cst_xactn_kind { (the_scenario.items[4].wdata == 32'h0000000c); }
#     ../tb_src_scenario/apb_scenario_gen.sv(26): the_scenario.cst_xactn_kind { (the_scenario.items[5].addr == 32'h00000003); }
#     ../tb_src_scenario/apb_scenario_gen.sv(26): the_scenario.cst_xactn_kind { (the_scenario.items[5].wdata == 32'h0000000c); }

Smell something wrong? Why is the constraint on addr, data getting applied across scenario items 2,3,4,5 etc.? Beyond the 0, 1 that the “implication” supposed to guard it? Relook at constraint code:

          (i==0) -> items[i].apb_op_kind == APB_WR;items[i].addr == 'b01; items[i].wdata == 'd11;

Found it? Not yet? The devil lies in details – here in that SEMICOLON “ ; “. A semicolon in Verilog/SV denotes END of a statement and begin of the next one. Hence the effect of “implication” is ENDED with the variable “kind” alone here – thereby it doesn’t affect the addr, data – hence the implication is invisible to them. At line 25, the addr == 1; At line 26, addr == 3; Hence the contradiction!

The fix will be to use && to imply that the guard is applicable to all the 3 variables – kind && addr && data.

  Instead of:

(i==0) -> items[i].apb_op_kind == APB_WR;items[i].addr == 'b01; items[i].wdata == 'd11;

Use:

   (i==0) –> (items[i].apb_op_kind == APB_WR) && (items[i].addr == 'b01) && (items[i].wdata == 'd11);

Morale of the debug session is: you need to be careful while using implication constraints for more than single variable :-)