📄 eth_frame.sv
字号:
// // -------------------------------------------------------------// Copyright 2004-2008 Synopsys, Inc.// All Rights Reserved Worldwide// // Licensed under the Apache License, Version 2.0 (the// "License"); you may not use this file except in// compliance with the License. You may obtain a copy of// the License at// // http://www.apache.org/licenses/LICENSE-2.0// // Unless required by applicable law or agreed to in// writing, software distributed under the License is// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR// CONDITIONS OF ANY KIND, either express or implied. See// the License for the specific language governing// permissions and limitations under the License.// -------------------------------------------------------------//class eth_frame extends vmm_data; static vmm_log log = new("eth_frame", "class"); static eth_utils utils = new; // A frame can either be tagged, untagged or be a control frame typedef enum {UNTAGGED, TAGGED, CONTROL} frame_formats_e; rand frame_formats_e format; rand bit [47:0] dst; rand bit [47:0] src; rand bit [ 2:0] user_priority; // if TAGGED rand bit cfi; // if TAGGED rand bit [11:0] vlan_id; // if TAGGED rand bit [15:0] len_typ; rand bit [15:0] opcode; // if CONTROL rand bit [15:0] pause_time; // if opcode == PAUSE rand bit [ 7:0] data[]; rand bit [31:0] fcs; // // Opcodes // typedef enum [15:0] {PAUSE = 16'h0001} opcodes_e; // // Faclitate expressing constraints // rand int unsigned min_len; rand int unsigned max_len; // // Constraints to always generate a valid frame //`ifdef SOLVER_WEIRDNESS constraint bug { format == UNTAGGED; data.size() == 48; data.size() <= 1500; }`endif constraint eth_frame_valid { min_len <= max_len; } constraint valid_untagged_frame { if (format == UNTAGGED) { len_typ != 16'h8808; len_typ != 16'h8100; min_len == 0; max_len == 1500; } } constraint valid_tagged_frame { if (format == TAGGED) { len_typ != 16'h8808; min_len == 0; max_len == 1500; } } constraint valid_control_frame { if (format == CONTROL) { len_typ == 16'h8808; min_len == max_len; foreach (data[i]) { data[i] == 8'h00; } } } constraint valid_opcode { opcode == PAUSE; } constraint no_control_frames { format != CONTROL; } constraint valid_pause_frame { if (format == CONTROL && opcode == PAUSE) { dst == 48'h0180C2000001; max_len == 42; } } constraint valid_len_typ { (data.size() <= 1500 && len_typ == data.size()) || len_typ >= 16'h0600; } constraint limit_data_size { data.size() < 65536; } constraint interesting_data_size { data.size() dist {min_len :/ 1, [min_len+1:max_len-1] :/ 1, max_len :/ 1}; } constraint valid_fcs { fcs == 32'h0000_0000; } constraint test_constraints1; constraint test_constraints2; constraint test_constraints3; // // Methods // function new(); super.new(this.log); endfunction: new extern virtual function vmm_data allocate(); extern virtual function vmm_data copy(vmm_data to = null); extern virtual function bit compare(vmm_data to, output string diff, input int kind = -1); extern virtual function string psdisplay(string prefix = ""); extern virtual function bit is_valid(bit silent = 1, int kind = -1); extern virtual function int unsigned byte_size(int kind = -1); virtual function int unsigned max_byte_size(int kind = -1); return 1500; endfunction extern virtual function int unsigned byte_pack(ref logic [7:0] array[], input int unsigned offset = 0, input int kind = -1); extern virtual function int unsigned byte_unpack(const ref logic [7:0] array[], input int unsigned offset = 0, input int len = -1, input int kind = -1); extern virtual function bit [31:0] compute_fcs();endclass: eth_frame `vmm_channel(eth_frame)`vmm_atomic_gen(eth_frame, "Ethernet Frame")`vmm_scenario_gen(eth_frame, "Ethernet Frame")function vmm_data eth_frame::allocate(); eth_frame i = new; return i;endfunction: allocatefunction vmm_data eth_frame::copy(vmm_data to); eth_frame cpy; if (to != null) begin if (!$cast(cpy, to)) begin `vmm_error(this.log, "Cannot copy to non-eth_frame instance"); return null; end end else cpy = new; super.copy_data(cpy); cpy.format = this.format; cpy.dst = this.dst; cpy.src = this.src; cpy.user_priority = this.user_priority; cpy.cfi = this.cfi; cpy.vlan_id = this.vlan_id; cpy.len_typ = this.len_typ; cpy.opcode = this.opcode; cpy.pause_time = this.pause_time; cpy.data = this.data; return cpy;endfunction: copyfunction bit eth_frame::compare(vmm_data to, output string diff, input int kind); eth_frame fr; int no_data = 0; if (to == null || !$cast(fr, to)) begin `vmm_error(this.log, "Cannot compare to non-eth_frame instance"); return 0; end if (fr.format !== this.format) begin $sformat(diff, "format (%0s !== %0s)", this.format.name(), fr.format.name()); return 0; end if (fr.dst !== this.dst) begin $sformat(diff, "dst (48'h%h !== 48'h%h)", this.dst, fr.dst); return 0; end if (fr.src !== this.src) begin $sformat(diff, "src (48'h%h !== 48'h%h)", this.src, fr.src); return 0; end if (fr.len_typ !== this.len_typ) begin if (this.len_typ >= 16'h0600) begin $sformat(diff, "len_typ (16'h%h !== 16'h%h)", this.len_typ, fr.len_typ); end else begin $sformat(diff, "len_typ (16'd%0d !== 16'd%0d)", this.len_typ, fr.len_typ); end return 0; end if (this.format == eth_frame::TAGGED) begin 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 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -