VMM - (expanded) RAL/vmm_rw.sv

Expanded versions of source files are the output of the preprocessor. Lines subject to conditional compilation are not shown and all compiler pragmas have been stripped. Macros have been completely expanded.

RAL/vmm_rw.sv unexpanded source

00001: // 
00002: // -------------------------------------------------------------
00003: //    Copyright 2004-2008 Synopsys, Inc.
00004: //    All Rights Reserved Worldwide
00005: // 
00006: //    Licensed under the Apache License, Version 2.0 (the
00007: //    "License"); you may not use this file except in
00008: //    compliance with the License.  You may obtain a copy of
00009: //    the License at
00010: // 
00011: //        http://www.apache.org/licenses/LICENSE-2.0
00012: // 
00013: //    Unless required by applicable law or agreed to in
00014: //    writing, software distributed under the License is
00015: //    distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
00016: //    CONDITIONS OF ANY KIND, either express or implied.  See
00017: //    the License for the specific language governing
00018: //    permissions and limitations under the License.
00019: // -------------------------------------------------------------
00020: // 
00021: 
00022: 
00024: `define RVM_RW__SV
00025: 
00027: 
00030:     `define VMM_RW_ADDR_WIDTH `VMM_RAL_ADDR_WIDTH
     : 
00037:     `define VMM_RW_DATA_WIDTH `VMM_RAL_DATA_WIDTH
     : 
00042: 
00043: 
00044: class vmm_rw;
00045:    typedef enum {
00046:       READ,
00047:       WRITE,
00048:       EXPECT
00049:    } kind_e;
00050: 
00051:    typedef enum {
00052:       IS_OK,
00053:       ERROR,
00054:       RETRY
00055:    } status_e;
00056: endclass: vmm_rw
00057: 
00058: 
00059: class vmm_rw_access extends vmm_data;
00060:    static vmm_log log = new("vmm_rw_access", "class");
00061: 
00062:    rand vmm_rw::kind_e kind;
00063: 
00064:    rand bit   [64-1:0] addr;
00065:    rand logic [64-1:0] data;
00066:    rand int                            n_bits = 64;
00067: 
00068:    vmm_rw::status_e status;
00069: 
00070:    constraint valid_vmm_rw_access {
00071:       n_bits > 0;
00072:       n_bits < 64;
00073:    }
00074: 
00075:    extern function new();
00076:    extern virtual function string psdisplay(string prefix = "");
00077: endclass: vmm_rw_access
00078: 
     : class vmm_rw_access_channel extends vmm_channel; 
     :  
     :    function new(string name, 
     :                 string inst, 
     :                 int    full = 1, 
     :                 int    empty = 0, 
     :                 bit    fill_as_bytes = 0); 
     :       super.new(name, inst, full, empty, fill_as_bytes); 
     :    endfunction: new 
     :  
     :    function vmm_rw_access unput(int offset = -1); 
     :       $cast(unput, super.unput(offset)); 
     :    endfunction: unput 
     :  
     :    task get(output vmm_rw_access obj, input int offset = 0); 
     :       vmm_data o; 
     :       super.get(o, offset); 
     :       $cast(obj, o); 
     :    endtask: get 
     :  
     :    task peek(output vmm_rw_access obj, input int offset = 0); 
     :       vmm_data o; 
     :       super.peek(o, offset); 
     :       $cast(obj, o); 
     :    endtask: peek 
     :  
     :    task activate(output vmm_rw_access obj, input int offset = 0); 
     :       vmm_data o; 
     :       super.activate(o, offset); 
     :       $cast(obj, o); 
     :    endtask: activate 
     :  
     :    function vmm_rw_access active_slot(); 
     :       $cast(active_slot, super.active_slot()); 
     :    endfunction: active_slot 
     :  
     :    function vmm_rw_access start(); 
     :       $cast(start, super.start()); 
     :    endfunction: start 
     :  
     :    function vmm_rw_access complete(vmm_data status = null); 
     :       $cast(complete, super.complete(status)); 
     :    endfunction: complete 
     :  
     :    function vmm_rw_access remove(); 
     :       $cast(remove, super.remove()); 
     :    endfunction: remove 
     :  
     :    task tee(output vmm_rw_access obj); 
     :       vmm_data o; 
     :       super.tee(o); 
     :       $cast(obj, o); 
     :    endtask: tee 
     :  
     :    function vmm_rw_access for_each(bit reset = 0); 
     :       $cast(for_each, super.for_each(reset)); 
     :    endfunction: for_each 
     : endclass
00079: 
00080: 
00081: class vmm_rw_burst extends vmm_rw_access;
00082:    rand int unsigned n_beats;
00083:    rand bit   [64-1:0] incr_addr;
00084:    rand bit   [64-1:0] max_addr;
00085:    rand logic [64-1:0] data[];
00086:         vmm_data                       user_data;
00087: 
00088:    constraint vmm_rw_burst_valid {
00089:       n_beats > 0;
00090:       max_addr >= addr;
00091:       if (kind == vmm_rw::WRITE || kind == vmm_rw::EXPECT) data.size() == n_beats;
00092:       else data.size() == 0;
00093:    }
00094: 
00095:    constraint reasonable {
00096:       n_beats <= 1024;
00097:       incr_addr inside {0, 1, 2, 4, 8, 16, 32};
00098:    }
00099: 
00100:    constraint linear {
00101:       incr_addr == 1;
00102:       max_addr == addr + n_beats - 1;
00103:    }
00104: 
00105:    constraint fifo {
00106:       incr_addr == 0;
00107:       max_addr == addr;
00108:    }
00109: 
00110:    constraint wrap {
00111:       incr_addr > 0;
00112:       max_addr < addr + (n_beats - 1)* incr_addr;
00113:    }
00114: 
00115:    function new();
00116:       this.linear.constraint_mode(0);
00117:       this.fifo.constraint_mode(0);
00118:       this.wrap.constraint_mode(0);
00119:    endfunction: new
00120: endclass: vmm_rw_burst
00121: 
00122: 
00123: typedef class vmm_rw_xactor;
00124: class vmm_rw_xactor_callbacks extends vmm_xactor_callbacks;
00125:    virtual task pre_single(vmm_rw_xactor xactor,
00126:                            vmm_rw_access tr);
00127:    endtask
00128: 
00129:    virtual task pre_burst(vmm_rw_xactor xactor,
00130:                           vmm_rw_burst  tr);
00131:    endtask
00132: 
00133:    virtual task post_single(vmm_rw_xactor xactor,
00134:                             vmm_rw_access tr);
00135:    endtask
00136: 
00137:    virtual task post_burst(vmm_rw_xactor xactor,
00138:                            vmm_rw_burst  tr);
00139:    endtask
00140: endclass: vmm_rw_xactor_callbacks
00141: 
00142: 
00143: class vmm_rw_xactor extends vmm_xactor;
00144:    typedef enum {BURST_DONE = 99990,
00145:                  SINGLE_DONE} notifications_e;
00146: 
00147:    vmm_rw_access_channel exec_chan;
00148: 
00149:    extern function new(string name,
00150:                        string instance,
00151:                        int    stream_id = -1,
00152:                        vmm_rw_access_channel exec_chan = null);
00153: 
00154:    extern protected virtual task execute_single(vmm_rw_access tr);
00155:    extern protected virtual task execute_burst(vmm_rw_burst tr);
00156: 
00157:    extern protected virtual task main();
00158:    extern function void reset_xactor(reset_e rst_typ = SOFT_RST);
00159: endclass: vmm_rw_xactor
00160: 
00161: 
00162: function vmm_rw_access::new();
00163:    super.new(this.log);
00164: endfunction: new
00165: 
00166: function string vmm_rw_access::psdisplay(string prefix);
00167:    string fmt;
00168:    $sformat(fmt, "%0dh", this.n_bits);
00169:    $sformat(psdisplay, {"%s%s @ 0x%h = %0d'h%", fmt, "\n"}, prefix,
00170:             kind.name(), addr, n_bits, data);
00171: endfunction: psdisplay
00172: 
00173: 
00174: function vmm_rw_xactor::new(string                name,
00175:                             string                instance,
00176:                             int                   stream_id,
00177:                             vmm_rw_access_channel exec_chan);
00178:    super.new(name, instance, stream_id);
00179: 
00180:    if (exec_chan == null) exec_chan = new({name, " Input Channel"}, instance);
00181:    this.exec_chan = exec_chan;
00182: 
00183:    this.log.is_above(this.exec_chan.log);
00184: 
00185:    this.notify.configure(BURST_DONE);
00186:    this.notify.configure(SINGLE_DONE);
00187: endfunction: new
00188: 
00189: 
00190: task vmm_rw_xactor::execute_single(vmm_rw_access tr);
00191:    
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::FATAL_SEV)) begin 
     :       void'(this.log.text("Undefined execute_single() method in vmm_rw_xactor extension")); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00192: endtask: execute_single
00193: 
00194: 
00195: task vmm_rw_xactor::execute_burst(vmm_rw_burst tr);
00196:    bit [64-1:0] addr;
00197:    int i;
00198: 
00199:    addr = tr.addr;
00200:    i = 0;
00201:    tr.status = vmm_rw::IS_OK;
00202:    if (tr.kind == vmm_rw::READ) tr.data = new [tr.n_beats];
00203:    repeat (tr.n_beats) begin
00204:       vmm_rw_access s = new;
00205:       s.kind = tr.kind;
00206:       s.addr = addr;
00207:       if (s.kind != vmm_rw::READ) s.data = tr.data[i++];
00208:       this.execute_single(s);
00209:       if (s.kind == vmm_rw::READ) tr.data[i++] = s.data;
00210:       if (s.status != vmm_rw::IS_OK) begin
00211:          tr.status = s.status;
00212:          return;
00213:       end
00214: 
00215:       addr += tr.incr_addr;
00216:       if (addr > tr.max_addr) addr = addr - tr.max_addr + tr.addr;
00217:    end
00218:    tr.status = vmm_rw::IS_OK;
00219: endtask: execute_burst
00220: 
00221: 
00222: task vmm_rw_xactor::main();
00223:    vmm_rw_access tr;
00224:    vmm_rw_burst  br;
00225: 
00226:    fork
00227:       super.main();
00228:    join_none
00229: 
00230:    forever begin
00231:       this.wait_if_stopped_or_empty(this.exec_chan);
00232: 
00233:       this.exec_chan.activate(tr);
00234:       this.exec_chan.start();
00235: 
00236:       if ($cast(br, tr)) begin
00238: 
     : 
     : do foreach (this.callbacks[vmm_i]) begin 
     :    vmm_rw_xactor_callbacks cb; 
     :    if (!$cast(cb, this.callbacks[vmm_i])) continue; 
     :  
     :    cb.pre_burst(this, br); 
     : end while (0);
00239:          this.execute_burst(br);
00241: 
     : 
     : do foreach (this.callbacks[vmm_i]) begin 
     :    vmm_rw_xactor_callbacks cb; 
     :    if (!$cast(cb, this.callbacks[vmm_i])) continue; 
     :  
     :    cb.post_burst(this, br); 
     : end while (0);
00242:          this.notify.indicate(BURST_DONE, br);
00243:       end
00244:       else begin
00245:          
     : 
     : do foreach (this.callbacks[vmm_i]) begin 
     :    vmm_rw_xactor_callbacks cb; 
     :    if (!$cast(cb, this.callbacks[vmm_i])) continue; 
     :  
     :    cb.pre_single(this, tr); 
     : end while (0);
00246:          this.execute_single(tr);
00248: 
     : 
     : do foreach (this.callbacks[vmm_i]) begin 
     :    vmm_rw_xactor_callbacks cb; 
     :    if (!$cast(cb, this.callbacks[vmm_i])) continue; 
     :  
     :    cb.post_single(this, tr); 
     : end while (0);
00249:          this.notify.indicate(SINGLE_DONE, tr);
00250:       end
00251: 
00252:       this.exec_chan.complete();
00253:       this.exec_chan.remove();
00254:    end
00255: endtask: main
00256: 
00257: 
00258: function void vmm_rw_xactor::reset_xactor(reset_e rst_typ);
00259:    vmm_rw_access tr;
00260: 
00261:    super.reset_xactor(rst_typ);
00262: 
00263:    // Force a completion of the transaction to avoid
00264:    // leaving the RAL model blocked
00265:    tr = this.exec_chan.active_slot();
00266:    if (tr != null) begin
00267:       tr.status = vmm_rw::RETRY;
00268:       this.exec_chan.complete();
00269:       this.exec_chan.remove();
00270:    end
00271:    this.exec_chan.flush();
00272: endfunction: reset_xactor
00273: