VMM DATA
vmm_data class is to be used to model all transactions in the infrastructure . It provides a standard set of methods expected to be found in all transactions. All transactions in the verification environment inherit this object and
override its main generic virtual tasks such as copy(), byte_pack(), byte_unpack(), compare() and psdisplay().
vmm_data has 3 unique identifiers for identifying transaction instance.
int stream_id; // Stream identifier
int scenario_id;// Sequence identifier within stream
int data_id; // instance identifier within sequence
This class is used to generate random, constraint random and directed transactions.
We will see the implementation of some methods.
Let us implement a simple packet using vmm_data.
Packet Specification
-------------------------------
Packet has DA,SA,Len and ..... few more feilds.
All the feilds are 8 bit.
1) Define a packet class by extending vmm_data
class Packet
extends vmm_data;
2) Define all the packet fields as rand variables
rand
bit [7:0] da;
rand
bit [7:0] sa;
rand
bit [7:0] length;
....
....
3) Constraint the rand variables based on the specification.
constraint address_c
{ da inside
{`P0,`P1,`P2,`P3};
}
....
.....
4) Define psdisplay() method.
psdisplay() method displays the current value of the transaction or data described by this instance in a human-readable format on the standard output.
virtual
function string psdisplay(string prefix=
"");
int i;
$write(psdisplay," %s%s da:0x%h\n", psdisplay,
prefix,this.da);
$write(psdisplay," %s%s sa:0x%h\n", psdisplay,
prefix,this.sa);
$write(psdisplay," %s%s length:0x%h (data.size=%0d)\n", psdisplay,
prefix,this.length,this.data.size());
.........
endfunction
5) Define copy() method.
copy() method copies the current value of the object instance to the specified object instance.
virtual
function vmm_data copy(vmm_data to=
null);
Packet cpy;
cpy = new;
super.copy_data(cpy);
cpy.da =this.da;
cpy.sa =this.sa;
cpy.length
= this.length;
...........
注:copy函数的返回值类型为vmm_data类,而不是扩展类类型,这是因为扩展类的虚函数必须跟其基类的函数相匹配,包括所有的参数和返回类型。
6) Define compare() method.
Compare method compares the current value of the object instance with the current value of the specified object instance.
virtual
function bitcompare(input vmm_data to,outputstring
diff,inputint kind
= -1);
Packet cmp;
compare =1;
// Assume success by default.
diff =
"No differences found";
// data types are the same, do comparison:
if
(this.da!= cmp.da)
begin
diff =
$psprintf("Different DA values: %b != %b",this.da,
cmp.da);
compare
= 0;
end
if
(this.sa!= cmp.sa)
begin
diff =
$psprintf("Different SA values: %b != %b",this.sa,
cmp.sa);
compare
= 0;
end
........
........
7) Define byte_pack() method.
byte_pack() method Packs the content of the transaction or data into the specified dynamic array of bytes.
virtual
function intunsigned byte_pack(
ref
logic [7:0] bytes[],
input
int unsigned offset=0
,
input
int kind =
-1);
byte_pack =
0;
bytes = new[this.data.size()+
4];
bytes[0]=
this.da;
bytes[1]=
this.sa;
bytes[2]=
this.length;
........
........
8) Define byte_unpack() method.
byte_unpack() method unpacket the array in to different data feilds.
virtual
function intunsigned byte_unpack(
const
ref logic[7:0]
bytes[],
input
int unsigned offset=
0,
input
int len
= -1,
input
int kind =
-1);
this.da= bytes[0];
this.sa= bytes[1];
this.length= bytes[2];
.........
.........
Complete Packet Class
class Packet
extends vmm_data;
static vmm_log log
= new("Packet","Class");
rand
bit [7:0] length;
rand
bit [7:0] da;
rand
bit [7:0] sa;
rand
bit [7:0]data[];//Payload
using Dynamic array,size is generated on the fly
rand
byte fcs;
constraint payload_size_c
{ data.sizeinside
{ [1:
6]};}
function
new();
super.new(this.log);
endfunction:new
virtual
function vmm_data allocate();
Packet pkt;
pkt = new();
return pkt;
endfunction:allocate
virtual
function string psdisplay(string prefix=
"");
int i;
$write(psdisplay," %s packet #%0d.%0d.%0d\n", prefix,this.stream_id,this.scenario_id,this.data_id);
$write(psdisplay," %s%s da:0x%h\n", psdisplay,
prefix,this.da);
$write(psdisplay," %s%s sa:0x%h\n", psdisplay,
prefix,this.sa);
$write(psdisplay," %s%s length:0x%h (data.size=%0d)\n", psdisplay,
prefix,this.length,this.data.size());
$write(psdisplay," %s%s data[%0d]:0x%h", psdisplay,
prefix,0,data[0]);
if(data.size()>
1)
$write(psdisplay," data[%0d]:0x%h",1,data[1]);
if(data.size()>
4)
$write(psdisplay," .... ");
if(data.size()>
2)
$write(psdisplay," data[%0d]:0x%h",data.size()-2,data[data.size()-2]);
if(data.size()>
3)
$write(psdisplay," data[%0d]:0x%h",data.size()-1,data[data.size()-1]);
$write(psdisplay,"\n %s%s fcs:0x%h \n", psdisplay,
prefix,this.fcs);
endfunction
virtual
function vmm_data copy(vmm_data to=
null);
Packet cpy;
// Copying to a new instance?
if
(to == null)
cpy = new;
else
// Copying to an existing instance. Correct type?
if
(!$cast(cpy, to))
begin
`vmm_fatal(this.log,"Attempting
to copy to a non packet instance");
copy = null;
return copy;
end
super.copy_data(cpy);
cpy.da =this.da;
cpy.sa =this.sa;
cpy.length =this.length;
cpy.data=
new[this.data.size()];
foreach(data[i])
begin
cpy.data[i]=
this.data[i];
end
cpy.fcs =this.fcs;
copy = cpy;
endfunction:copy
virtual
function bitcompare(input vmm_data to,outputstring
diff,inputint kind
= -1);
Packet cmp;
compare =1;
// Assume success by default.
diff = "No differences found";
if
(!$cast(cmp, to))
begin
`vmm_fatal(this.log,"Attempting
to compare to a non packet instance");
compare =0;
diff = "Cannot compare non packets";
return
compare;
end
// data types are the same, do comparison:
if
(this.da!= cmp.da)
begin
diff = $psprintf("Different DA values: %b != %b",this.da,
cmp.da);
compare =0;
return
compare;
end
if
(this.sa!= cmp.sa)
begin
diff = $psprintf("Different SA values: %b != %b",this.sa,
cmp.sa);
compare =0;
return
compare;
end
if
(this.length!= cmp.length)
begin
diff = $psprintf("Different LEN values: %b != %b",this.length,
cmp.length);
compare =0;
return
compare;
end
foreach(data[i])
if
(this.data[i]!= cmp.data[i])
begin
diff = $psprintf("Different data[%0d] values: 0x%h != 0x%h",i,this.data[i],
cmp.data[i]);
compare
= 0;
return
compare;
end
if
(this.fcs!= cmp.fcs)
begin
diff = $psprintf("Different FCS values: %b != %b",this.fcs,
cmp.fcs);
compare =0;
return
compare;
end
endfunction:compare
virtual
function intunsigned byte_pack(
ref
logic [7:0] bytes[],
input
int unsigned offset=0
,
input
int kind =
-1);
byte_pack =
0;
bytes = new[this.data.size()+
4];
bytes[0]=
this.da;
bytes[1]=
this.sa;
bytes[2]=
this.length;
foreach(data[i])
bytes[3+i]=
data[i];
bytes[this.data.size()+
3 ]
= fcs;
byte_pack =
this.data.size()+
4;
endfunction:byte_pack
virtual
function intunsigned byte_unpack(
const
ref logic[7:0]
bytes[],
input
int unsigned offset=
0,
input
int len
= -1,
input
int kind =
-1);
this.da= bytes[0];
this.sa= bytes[1];
this.length= bytes[2];
this.fcs= bytes[bytes.size()-1];
this.data=
new[bytes.size()-
4];
foreach(data[i])
this.data[i]= bytes[i+3];
return bytes.size();
endfunction:byte_unpack
endclass
Vmm_data Methods
virtual
function string psdisplay(
string prefix=
"" );
virtual
function bit is_valid(
bit silent=
1,int kind
= -1);
virtual
function vmm_data allocate ();
virtual
function vmm_data copy ( vmm_data to=
null);
virtual
function bitcompare
(
input vmm_data to,output
string diff,
input
int kind=
-1);
function
void display(string prefix=
"");
virtual
protected functionvoid copy_data
( vmm_data to );
virtual
function intunsigned byte_pack
(
ref
logic [7:0] bytes[
], int
unsigned offset=
0,int kind
= -1);
virtual
function intunsigned byte_unpack
(
const
ref logic[7:0]
bytes[ ],
input intunsigned offset
= 0,
input
int len
= -1,input
int kind
= -1
);
virtual
function intunsigned byte_size
( int kind
= -1);
virtual
function intunsigned max_byte_size
( int kind
= -1);
virtual
function void save(
int file);
virtual
function bit load(
int file);