My Tips for using the OSVVM Scoreboard
Why OSVVM™? › Forums › OSVVM › My Tips for using the OSVVM Scoreboard
- This topic has 0 replies, 1 voice, and was last updated 6 years, 3 months ago by Richard Head.
-
AuthorPosts
-
August 13, 2018 at 03:19 #1473Richard HeadMember
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>
-
AuthorPosts
- You must be logged in to reply to this topic.