Code Browser Pages:
| //////////////////////////////////////////////// ////s~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~s//// ////s www.testbench.in s//// ////s s//// ////s VMM Tutorial s//// ////s gopi@testbench.in s//// ////s~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~s//// //////////////////////////////////////////////// `ifndef GUARD_PACKET `define GUARD_PACKET //Define the enumerated types for packet types typedef enum { GOOD_FCS, BAD_FCS } fcs_kind_t; typedef enum { GOOD_LENGTH, BAD_LENGTH } length_kind_t; class Packet extends vmm_data; static vmm_log log = new("Packet","Class"); rand fcs_kind_t fcs_kind; rand length_kind_t length_kind; 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 address_c { da inside {`P0,`P1,`P2,`P3} ; } constraint payload_size_c { data.size inside { [1 : 6]};} constraint length_kind_c { (length_kind == GOOD_LENGTH) -> length == data.size; (length_kind == BAD_LENGTH) -> length == data.size + 2 ; } constraint solve_size_length { solve data.size before length; } function new(); super.new(this.log); endfunction:new function void post_randomize(); if(fcs_kind == GOOD_FCS) fcs = 8'b0; else fcs = 8'b1; fcs = cal_fcs(); endfunction : post_randomize ///// method to calculate the fcs ///// virtual function byte cal_fcs; integer i; byte result ; result = 0; result = result ^ da; result = result ^ sa; result = result ^ length; for (i = 0;i< data.size;i++) result = result ^ data[i]; result = fcs ^ result; return result; endfunction : cal_fcs virtual function vmm_data allocate(); Packet pkt; pkt = new(); return pkt; endfunction:allocate virtual function string psdisplay(string prefix = ""); int i; $write(psdisplay, " packet #0.0.0\n", prefix,this.stream_id, this.scenario_id, this.data_id); $write(psdisplay, " da:0x%h\n", psdisplay, prefix,this.da); $write(psdisplay, " sa:0x%h\n", psdisplay, prefix,this.sa); $write(psdisplay, " length:0x%h (data.size=0)\n", psdisplay, prefix,this.length,this.data.size()); $write(psdisplay, " data[0]:0x%h", psdisplay, prefix,0,data[0]); if(data.size() > 1) $write(psdisplay, " data[0]:0x%h", 1,data[1]); if(data.size() > 4) $write(psdisplay, " .... "); if(data.size() > 2) $write(psdisplay, " data[0]:0x%h", data.size() -2,data[data.size() -2]); if(data.size() > 3) $write(psdisplay, " data[0]:0x%h", data.size() -1,data[data.size() -1]); $write(psdisplay, "\n 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 bit compare(input vmm_data to,output string diff,input int 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: 0 != 0", this.da, cmp.da); compare = 0; return compare; end if (this.sa != cmp.sa) begin diff = $psprintf("Different SA values: 0 != 0", this.sa, cmp.sa); compare = 0; return compare; end if (this.length != cmp.length) begin diff = $psprintf("Different LEN values: 0 != 0", this.length, cmp.length); compare = 0; return compare; end foreach(data[i]) if (this.data[i] != cmp.data[i]) begin diff = $psprintf("Different data[0] 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: 0 != 0", this.fcs, cmp.fcs); compare = 0; return compare; end endfunction:compare virtual function int unsigned 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 int unsigned 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 ///////////////////////////////////////////////////////// //// Create vmm_channel and vmm_atomic_gen for packet//// ///////////////////////////////////////////////////////// `vmm_channel(Packet) `vmm_atomic_gen(Packet, "Packet Gen") ///////////////////////////////////////////////////////// //// Test to check the packet implementation //// ///////////////////////////////////////////////////////// /* program test; Packet pkt1 = new(); Packet pkt2 = new(); string diff; logic [7:0] bytes[]; initial repeat(10) if(pkt1.randomize) begin $display(" Randomization Sucessesfull."); $display(pkt1.psdisplay("Pkt1")); void'(pkt1.byte_pack(bytes)); pkt2 = new(); pkt2.byte_unpack(bytes); $display(pkt1.psdisplay("Pkt2")); if(pkt2.compare(pkt1,diff)) $display(" Packing,Unpacking and compare worked"); else $display(" *** Something went wrong in Packing or Unpacking or compare *** \n \n ",diff); end else $display(" *** Randomization Failed ***"); final $display(" ******************** End of testcase *****************"); endprogram */ `endif |