My Tips for using the OSVVM Scoreboard

Why OSVVM™?ForumsOSVVMMy Tips for using the OSVVM Scoreboard

This topic has 1 voice, contains 0 replies, and was last updated by Avatar of Richard Head Richard Head 42 days ago.

Viewing 1 post
Author Posts
Author Posts
August 13, 2018 at 03:19 #1473
Avatar of Richard Head
Richard Head

So, Ive been using the OSVVM scoreboard very successfully verifying AXI based systems with custom AXI record types, one for each channel (streaming, awaddr, araddr etc) But at the start, I hit a couple of problems:

1. Its a bit of a chore creating compare functions for every single axi type, or any other type I want to create in the future.

2. How do I compare only half of a bus? For example, if tkeep is 0x0F, I really dont care whats in the top 4 bytes of the tdata bus. How can I pass that info into the scoreboard when checking?

The answer to both of these questions – compare everything using strings. This way, all you need to define is a “to_string” function for your custom type (which you need to do anyway for the scoreboard_generic_pkg). 

Obviously, if you were doing a straight compare, then the “=” would be automatically available for your new custom type that you could assign to the scoreboard, but this doesnt solve the 2nd problem.

Using strings, and string processing during the compare, allows you to define a custom “match” function that allows you to replace chars before they are matched. For example – I dont care what the top 4 bytes of tdata are, in the expected string, I can place “—-” or “XXXX” where a match will happen by replacing data in the actual string with “XXXX” also, and when the strings are compared they now match. Now I can have a generic function that processes the strings from any custom type with a “to_string” function defined.

Here are the functions I have developed, that I now use for all custom types, that allow me to compare any custom type, and (IMO) is better at quickly seeing where errors have occured, because it lays the two strings on top of each other, and marks and ‘X’ underneath any chars that missmatch. (standard OSVVM lays them side by side, which can be harder to match when the types are record types):

<code>

——————————————————————————————–

    — Takes 2 strings and produces another strings that marks missmatches

    ——————————————————————————————–

    function match_string(s1, s2          : string;

                          match_char      : character := ‘ ‘;

                          missmatch_char  : character := ‘X’;

                          s1_ignore       : string    := “”;

                          s2_ignore       : string    := “” ) return string is

      variable ret      : string(s1′range);

      variable s1_local : string(s1′range) := s1;

      variable s2_local : string(s2′range) := s2;

    begin

      assert (s1′length = s2′length)

        report “S1 and S2 lengths must match”

          severity FAILURE;

      for i in s1′range loop

        —————————————————————————-

        — Force a match on ignore chars

        —————————————————————————-

        for j in s1_ignore’range loop

          s1_local(i) := s2_local(i) when s1_local(i) = s1_ignore(j);

        end loop;

        for j in s2_ignore’range loop

          s2_local(i) := s1_local(i) when s2_local(i) = s2_ignore(j);

        end loop;

        ret(i) := match_char when (s1_local(i) = s2_local(i)) else missmatch_char;

      end loop;

      return ret;

    end function match_string;

    —————————————————————————-

    — Procedure version of the above, that also returns if a match was good

    —————————————————————————-

    procedure match_string( constant s1, s2          :       string;

                            constant match_char      :       character := ‘ ‘;

                            constant missmatch_char  :       character := ‘X’;

                            constant s1_ignore       :       string    := “”;

                            constant s2_ignore       :       string    := “”;

                            variable match_str       : inout line;

                            variable matched         :   out boolean )   is

    begin

      DEALLOCATE(match_str);

      matched       := false;

      match_str     := new string’( match_string(s1, s2, match_char, missmatch_char, s1_ignore, s2_ignore) );

      — return missmatch on any missmatch char

      for i in s1′range loop

        if match_str(i) = missmatch_char then return; end if;

      end loop;

      matched       := true;

    end procedure;

    ———————————————————————————————-

    — This Function assumes you want to match two

    — This should plug in nicely to the OSVVM scoreboard that requires a matching function

    — but this allows you to match any std_logic type to Xs

    ———————————————————————————————-

    function match_X_generic generic ( type data_t;

                                       function to_string(d : data_t) return string is <> )

                             parameter( act, exp    : data_t )

                             return boolean is

      variable matched    : boolean;

      variable match_str  : line;

    begin

      match_string( s1          => to_string(act),

                    s2          => to_string(exp),

                    s2_ignore   => “X-”          ,

                    match_str   => match_str     ,

                    matched     => matched        );

      if not matched then

        — Dont Use Alert, as this will come in Scoreboard

        log(TBTOOLS_ALERT_ID, “act: ” & to_string(act), ALWAYS);

        log(TBTOOLS_ALERT_ID, “exp: ” & to_string(exp), ALWAYS);

        log(TBTOOLS_ALERT_ID, “     ” & match_str.all , ALWAYS);

      end if;

      DEALLOCATE(match_str);

      return matched;

    end function match_X_generic;

– And then In my real system:

type axis_trans_t is record

    tid       : std_logic_vector(7 downto 0);

    tdata     : std_logic_vector;

    tuser     : std_logic_vector;

    tdest     : std_logic_vector;

    tkeep     : std_logic_vector;

    tstrb     : std_logic_vector;

    tlast     : std_logic;

  end record axis_trans_t;

function to_string(a : axis_trans_t) return string;

function match_x is new match_X_generic generic map ( data_t => axis_trans_t        );

package axis_trans_sb_pkg is new Osvvm.ScoreboardGenericPkg generic map ( ExpectedType        => axis_trans_t,

                                                                          ActualType          => axis_trans_t,

                                                                          Match               => match_x,

                                                                          expected_to_string  => to_string,

                                                                          actual_to_string    => to_string );

</code>

Viewing 1 post

You must be logged in to reply to this topic.