Problems with OSVVM Functional Coverage

Why OSVVM™? Forums OSVVM Problems with OSVVM Functional Coverage

Viewing 4 posts - 1 through 4 (of 4 total)
  • Author
    Posts
  • #2672
    Alex
    Member

    I am exploring functional coverage. But cannot get a simple coverage running. Please point out what is wrong here:
    rx_cnt_s counts upto 20 which has been verified.

    Background: This is a VUNIT testbench with where the DUT has AXI slaves. I use the Axi4Lite Manager as a master to access the AXI slaves in the DUT. The snippet below is part of the testbench where I am trying to do a functional coverage.

    Still does not work when I added delta delays before Icover as suggested by Jim. Strange that the coverage is always zero. Could it be a framework or structural issue that I am missing?

    RxCov is a signal.

    rx_process : process is 
          variable cnt : integer := 0;
    
          variable rd_data     : std_logic_vector(31 downto 0) := (others => '0');
    
        begin
                  rx_cnt_s <= 0;
                  RxCov <= NewID("RxCov") ;                         -- Get a Coverage ID
    
                  wait for 0 ns ;
    
                  osvvm.CoveragePkg.AddBins(RxCov, "count", GenBin(1,20,1) ) ;     
    
                  loop
    
                    WaitForClock(InterruptRec, 1) ;
                    report "Interrupt Handler Started" ;
    
                    Read(InterruptRec, X"A80", rd_data);
                   
                    if (rd_data(10) = '1') then 
    
                      Read(InterruptRec, x"920", rd_data);
                      if (rd_data(30 downto 26) = rd_data(20 downto 16)) then 
                         report "RX FIFO EMPTY";
                      else
                                             
                         osvvm.TbUtilPkg.WaitForClock(clk, 2);
                         cnt := rx_cnt_s;
                         cnt := cnt + 1;
                         rx_cnt_s <= cnt;
    
                         
                          osvvm.CoveragePkg.ICover(RxCov, rx_cnt_s) ;      -- Collect functional coverage
    
                      end if;
                    end if;
                    report "Interrupt Handler Done" ;
                    InterruptReturn(InterruptRec) ;
                    wait for 1 ns ;                
    
                  end loop;
                  osvvm.CoveragePkg.WriteBin(RxCov); --print results
                  wait;
    
        end process;

    Also the control Process:

    -----------------------------------------------------------
      -- ControlProc
      --   Set up AlertLog and wait for end of test
      ------------------------------------------------------------
      ControlProc : process
      begin
        -- Initialization of test
        SetTestName("test") ;
        SetLogEnable(PASSED, TRUE) ;   -- Enable PASSED logs
        SetLogEnable(INFO, TRUE) ;     -- Enable INFO logs
        -- SetLogEnable(DEBUG, TRUE) ;    -- Enable INFO logs
    
        -- Wait for testbench initialization
        wait for 0 ns ;  wait for 0 ns ;
        TranscriptOpen(OSVVM_RESULTS_DIR & "test.txt") ;
        SetTranscriptMirror(TRUE) ;
        SetAlertLogOptions(WriteTimeLast => FALSE) ; 
        SetAlertLogOptions(TimeJustifyAmount => 15) ; 
        SetAlertLogJustify ; 
    
        -- Wait for Design Reset
        wait until nreset = '1' ;
        ClearAlerts ;
    
        -- Wait for test to finish
        WaitForBarrier(TestDone, 1 ms) ;
        AlertIf(now >= 20 ms, "Test finished due to timeout") ;
        AlertIf(GetAffirmCount < 1, "Test is not Self-Checking");
       
        TranscriptClose ;
    
        EndOfTestReports ;
       -- std.env.stop ;
        wait for 7ms ;
      end process ControlProc ;

    Generated YAML Coverage report:

    Version: "1.0"
    Coverage: 0.00
    Settings: 
      WritePassFail: 0
    Models: 
      - Name: "RxCov"
        TestCases: 
          - "count"
        Coverage: 0.00
        Settings: 
          CovWeight: 1
          Goal: 100.0
          WeightMode: "AT_LEAST"
          Seeds: [1129194420, 352562534]
          CountMode: "COUNT_FIRST"
          IllegalMode: "ILLEGAL_ON"
          Threshold: 45.0
          ThresholdEnable: "FALSE"
          IsRequirement: "FALSE"
          TotalCovCount: 0
          TotalCovGoal: 1
        BinInfo: 
          Dimensions: 1
          FieldNames: 
            - "Bin1"
          NumBins: 1
        Bins: 
          - Name: "count"
            Type: "COUNT"
            Range: 
              - {Min: 1, Max: 20}
            Count: 0
            AtLeast: 1
            PercentCov: 0.0000
    #2674
    Jim Lewis
    Member

    Hi ALex,
    I added the two suggestions I made previously to the code. Choose one of them.
    I also changed the WaitForClock(clk, 2) to WaitForClock(InterruptRec, 2).
    Usually I do not put clock in TestCtrl. The reason being is if you have lots of
    different clocks in your system, it is easy to use the wrong one.

    rx_process : process is 
          variable cnt : integer := 0; -- this value is applied at time 0 ns
          variable rd_data     : std_logic_vector(31 downto 0) := (others => '0');
        begin
                  rx_cnt_s <= 0;
                  RxCov <= NewID("RxCov") ;                         -- Get a Coverage ID
    
                  wait for 0 ns ;
    
    -- This puts all counts in a single bin with range 1 to 20
                  osvvm.CoveragePkg.AddBins(RxCov, "count", GenBin(1,20,1) ) ;     
    -- This puts all counts in a separate bins range 1 to 1, 2 to 2, ...
                  osvvm.CoveragePkg.AddBins(RxCov, "count", GenBin(1,20) ) ;     
    
                  loop
    
                    WaitForClock(InterruptRec, 1) ;
                    report "Interrupt Handler Started" ;
    
                    Read(InterruptRec, X"A80", rd_data);
                   
                    if (rd_data(10) = '1') then 
    
                      Read(InterruptRec, x"920", rd_data);
                      if (rd_data(30 downto 26) = rd_data(20 downto 16)) then 
                         report "RX FIFO EMPTY";
                      else
    -- The following is a problem if you do not have clk here - I generally recommend against clock here                                      
    --                     osvvm.TbUtilPkg.WaitForClock(clk, 2);
    -- Instead let the VC do the waiting
                         WaitForClock(InterruptRec, 2);  -- wait for VC number of clocks
    -- Note the previous waits are not needed by OSVVM.
    
                         cnt := rx_cnt_s;
                         cnt := cnt + 1;
    -- Either Check cnt in ICover because rx_cnt_s does not update until a delta cycle later                    
                         osvvm.CoveragePkg.ICover(RxCov, cnt) ;      -- Collect functional coverage
                         log("cnt value: " & to_string(cnt)) ;  -- log values of cnt to correlate with functional coverage
                         rx_cnt_s <= cnt;
    -- Or add a delta cycle by doing wait for 0 ns here:
                         rx_cnt_s <= cnt;
                         wait for 0 ns ; 
                         osvvm.CoveragePkg.ICover(RxCov, rx_cnt_s ) ;      -- Collect functional coverage
                         log("cnt value: " & to_string(rx_cnt_s)) ;  -- log values of cnt to correlate with functional coverage
                      end if;
                    end if;
                    report "Interrupt Handler Done" ;
                    InterruptReturn(InterruptRec) ;
                    wait for 1 ns ;                
    
                  end loop;
    -- The loop is never exited so this code never runs.
                  osvvm.CoveragePkg.WriteBin(RxCov); -- generates a test report 
                  wait;
    
        end process;
    

    Your control process cannot iterate, so change it as follows:

    
      ControlProc : process
      begin
        -- Initialization of test
        SetTestName("test") ;
        SetLogEnable(PASSED, TRUE) ;   -- Enable PASSED logs
        SetLogEnable(INFO, TRUE) ;     -- Enable INFO logs
        -- SetLogEnable(DEBUG, TRUE) ;    -- Enable INFO logs
    
        -- Wait for testbench initialization
        wait for 0 ns ;  wait for 0 ns ;
        TranscriptOpen(OSVVM_RESULTS_DIR & "test.txt") ;
        SetTranscriptMirror(TRUE) ;
        SetAlertLogOptions(WriteTimeLast => FALSE) ; 
        SetAlertLogOptions(TimeJustifyAmount => 15) ; 
        SetAlertLogJustify ; 
    
        -- Wait for Design Reset
        wait until nreset = '1' ;
        ClearAlerts ;
    
        -- Wait for test to finish
    -- If you have a process that uses WaitForBarrier(TestDone) somewhere else the following is ok
        WaitForBarrier(TestDone, 20 ms) ;   -- note I change the wait time to match the timeout period
        AlertIf(now >= 20 ms, "Test finished due to timeout") ;
    -- If not, replace the WaitForBarrier with
        wait for 20 ms ; 
    
        AlertIf(GetAffirmCount < 1, "Test is not Self-Checking");
       
        TranscriptClose ;
    
        EndOfTestReports ;
    -- add stop, remove wait for 7 ms
       std.env.stop ;
       -- wait for 7ms ;
       wait ;  
     end process ControlProc ;
    
    #2675
    Alex
    Member

    I tried printing the logs with writebin. The coverage seems to work. its onyl the YAML reports which does not print it right I suppose:

    %% WriteBin: RxCov
    %% count  PASSED Bin:(1)   Count = 1  AtLeast = 1
    %% count  PASSED Bin:(2)   Count = 1  AtLeast = 1
    %% count  PASSED Bin:(3)   Count = 1  AtLeast = 1
    %% count  PASSED Bin:(4)   Count = 1  AtLeast = 1
    %% count  PASSED Bin:(5)   Count = 1  AtLeast = 1
    %% count  PASSED Bin:(6)   Count = 1  AtLeast = 1
    %% count  PASSED Bin:(7)   Count = 1  AtLeast = 1
    %% count  PASSED Bin:(8)   Count = 1  AtLeast = 1
    %% count  PASSED Bin:(9)   Count = 1  AtLeast = 1
    %% count  PASSED Bin:(10)   Count = 1  AtLeast = 1
    %% count  PASSED Bin:(11)   Count = 1  AtLeast = 1
    %% count  PASSED Bin:(12)   Count = 1  AtLeast = 1
    %% count  PASSED Bin:(13)   Count = 1  AtLeast = 1
    %% count  PASSED Bin:(14)   Count = 1  AtLeast = 1
    %% count  PASSED Bin:(15)   Count = 1  AtLeast = 1
    %% count  PASSED Bin:(16)   Count = 1  AtLeast = 1
    %% count  PASSED Bin:(17)   Count = 1  AtLeast = 1
    %% count  PASSED Bin:(18)   Count = 1  AtLeast = 1
    %% count  PASSED Bin:(19)   Count = 1  AtLeast = 1
    %% count  PASSED Bin:(20)   Count = 1  AtLeast = 1
    #2676
    Jim Lewis
    Member

    These above write bin values were not generated by the code you posted. See annotations in the code.

Viewing 4 posts - 1 through 4 (of 4 total)
  • You must be logged in to reply to this topic.