📄 eth_frame.sv
字号:
if (fr.vlan.id !== this.vlan.id) begin $sformat(diff, "vlan_id (12'h%h !== 12'h%h)", this.vlan.id, fr.vlan.id); return 0; end`else if (fr.user_priority !== this.user_priority) begin $sformat(diff, "user_priority (3'd%0d !== 3'd%0d)", this.user_priority, fr.user_priority); return 0; end if (fr.cfi !== this.cfi) begin $sformat(diff, "cfi (1'b%b !== 1'b%b)", this.cfi, fr.cfi); return 0; end if (fr.vlan_id !== this.vlan_id) begin $sformat(diff, "vlan_id (12'h%h !== 12'h%h)", this.vlan_id, fr.vlan_id); return 0; end`endif end if (this.format == eth_frame::CONTROL) begin if (fr.opcode !== this.opcode) begin $sformat(diff, "opcode (%0s !== %0s)", this.opcode, fr.opcode); return 0; end if (this.opcode == eth_frame::PAUSE) begin if (fr.pause_time !== this.pause_time) begin $sformat(diff, "pause_time (16'd%0d !== 16'd%0d)", this.pause_time, fr.pause_time); return 0; end no_data = 1; end end if (!no_data) begin if (fr.data.size() !== this.data.size()) begin $sformat(diff, "data.size() (16'd%0d !== 16'd%0d)", this.data.size(), fr.data.size()); return 0; end foreach (this.data[i]) begin if (fr.data[i] !== this.data[i]) begin $sformat(diff, "data[%0d] (8'h%h !== 8'h%h)", i, this.data[i], fr.data[i]); return 0; end end end // For FCS, we only care whether they indicate valid or not if ((fr.fcs === 32'h0000_0000) !== (this.fcs === 32'h0000_0000)) begin $sformat(diff, "FCS (%0s !== %0s)", (fr.fcs === 32'h0000_0000) ? "valid" : "invalid", (this.fcs === 32'h0000_0000) ? "valid" : "invalid"); return 0; end compare = 1;endfunction: compare// Example 4-39 function string eth_frame::psdisplay(string prefix); bit no_data = 0; $sformat(psdisplay, "%sEthernet Frame #%0d.%0d.%0d:\n", prefix, this.stream_id, this.scenario_id, this.data_id); $sformat(psdisplay, "%s%s dst=48'h%h, src=48'h%h, len/typ=16'h%h\n", psdisplay, prefix, this.dst, this.src, this.len_typ); case (this.format) TAGGED: begin $sformat(psdisplay, "%s%s (tagged) pri=3'd%0d cfi=%b vlan=12'h%h\n", psdisplay, prefix,`ifdef ETH_USE_COMPOSITION this.vlan.user_priority, this.vlan.cfi, this.vlan.id);`else this.user_priority, this.cfi, this.vlan_id);`endif end CONTROL: begin case (this.opcode) PAUSE: begin $sformat(psdisplay, "%s%s PAUSE for %0d quantas\n", psdisplay, prefix, this.pause_time); no_data = 1; end default: begin $sformat(psdisplay, "%s%s opcode=16'h%h\n", psdisplay, prefix, this.opcode); end endcase end endcase if (!no_data) begin int i; $sformat(psdisplay, "%s%s len=%0d, data=", psdisplay, prefix, data.size()); for (i = 0; i < data.size(); i++) begin $sformat(psdisplay, "%s 0x%h", psdisplay, this.data[i]); if (this.data.size() > 8 && i == 5) begin $sformat(psdisplay, "%s ..", psdisplay); i = this.data.size() - 3; end end $sformat(psdisplay, "%s\n", psdisplay); end $sformat(psdisplay, "%s%s FCS is %0s", psdisplay, prefix, (fcs) ? "BAD" : "good");endfunction: psdisplayfunction bit eth_frame::is_valid(bit silent, int kind); is_valid = 1; /*this.randomize(null);*/ if (!is_valid && !silent) begin `vmm_error(this.log, "Frame is not valid"); endendfunction: is_validfunction int unsigned eth_frame::byte_size(int kind); byte_size = 14 + data.size(); if (format == TAGGED) byte_size += 4;endfunction: byte_sizefunction int unsigned eth_frame::byte_pack(ref logic [7:0] array[], input int unsigned offset, input int kind); int i; if (array.size() < offset + this.byte_size(kind)) begin array = new [offset + this.byte_size(kind)] (array); end i = offset; {array[i ], array[i+1], array[i+2], array[i+3], array[i+ 4], array[i+ 5]} = this.dst; {array[i+6], array[i+7], array[i+8], array[i+9], array[i+10], array[i+11]} = this.src; i += 12; case (this.format) UNTAGGED: begin {array[i], array[i+1]} = this.len_typ; i += 2; end TAGGED: begin {array[i], array[i+1]} = 16'h8100; i += 2;`ifdef ETH_USE_COMPOSITION {array[i], array[i+1]} = {this.vlan.user_priority, this.vlan.cfi, this.vlan.id};`else {array[i], array[i+1]} = {this.user_priority, this.cfi, this.vlan_id};`endif i += 2; {array[i], array[i+1]} = this.len_typ; i += 2; end // Example 4-38 CONTROL: begin {array[i], array[i+1]} = 16'h8808; i += 2; {array[i], array[i+1]} = this.opcode; i += 2; case (this.opcode) PAUSE: begin {array[i], array[i+1]} = this.pause_time; i += 2; end endcase end endcase foreach (this.data[j]) begin array[i++] = this.data[j]; end byte_pack = i - offset;endfunction: byte_packfunction int unsigned eth_frame::byte_unpack(const ref logic [7:0] array[], input int unsigned offset, input int len, input int kind); int array_len; int i, j, k; int no_data = 0; // Invalidate this instance to make sure we // do not have left-over data from a previous instance // in case of not enough data supplied this.dst = 48'hx; this.src = 48'hx;`ifdef ETH_USE_COMPOSITION this.vlan = null;`else this.user_priority = 3'bx; this.cfi = 1'bx; this.vlan_id = 12'hx;`endif this.len_typ = 16'hx; this.opcode = 16'hx; this.pause_time = 16'hx; this.data = new [0]; this.fcs = 32'hXXXX_XXXX; array_len = array.size(); if (len > 0) begin array_len = len + offset; if (array_len > array.size()) array_len = array.size(); end i = offset; byte_unpack = 0; this.fcs = 32'hx; // Assume untagged data frame by default this.format = eth_frame::UNTAGGED; // Unpack the dst and src addresses for (k = 0; i < array_len && k < 6; k++) begin this.dst[47-k*8 -:8] = array[i]; i++; byte_unpack++; end if (i >= array_len) return byte_unpack; for (k = 0; i < array_len && k < 6; k++) begin this.src[47-k*8 -:8] = array[i]; i++; byte_unpack++; end if (i >= array_len) return byte_unpack; // Is this a tagged frame? if (i+1 >= array_len) return byte_unpack; // Example 4-41 if ({array[i], array[i+1]} == 16'h8100) begin this.format = eth_frame::TAGGED;`ifdef ETH_USE_COMPOSITION this.vlan = new;`endif i += 2; byte_unpack += 2; if (i+1 >= array_len) return byte_unpack;`ifdef ETH_USE_COMPOSITION {this.vlan.user_priority, this.vlan.cfi, this.vlan.id} = {array[i], array[i+1]};`else {this.user_priority, this.cfi, this.vlan_id} = {array[i], array[i+1]};`endif i += 2; byte_unpack += 2; if (i+1 >= array_len) return byte_unpack; this.len_typ = {array[i], array[i+1]}; i += 2; byte_unpack += 2; end else if ({array[i], array[i+1]} == 16'h8808) begin this.len_typ = 16'h8808; this.format = eth_frame::CONTROL; i += 2; byte_unpack += 2; if (i+1 >= array_len) return byte_unpack; this.opcode = {array[i], array[i+1]}; i += 2; byte_unpack += 2; case (this.opcode) PAUSE: begin if (i+1 >= array_len) return byte_unpack; this.pause_time = {array[i], array[i+1]}; i += 2; byte_unpack += 2; no_data = 1; end endcase end else begin this.len_typ = {array[i], array[i+1]}; i += 2; byte_unpack += 2; end if (i >= array_len) return byte_unpack; if (no_data == 0) begin int l = (this.len_typ >= 'h0600 || this.len_typ > array_len - i) ? array_len - i : this.len_typ; this.data = new [l]; foreach (this.data[k]) begin this.data[k] = array[i]; i++; byte_unpack++; end end this.fcs = 32'hx;endfunction: byte_unpack// Example 4-37function bit [31:0] eth_frame::compute_fcs(); logic [7:0] bytes[]; void'(this.byte_pack(bytes)); compute_fcs = this.utils.compute_crc32(bytes, 0, bytes.size() - 4);endfunction: compute_fcs
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -