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.
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: TIMEOUT
00056: } status_e;
00057: endclass: vmm_rw
00058:
00059:
00060: class vmm_rw_access extends vmm_data;
00061: static vmm_log log = new("vmm_rw_access", "class");
00062:
00063: rand vmm_rw::kind_e kind;
00064:
00065: rand bit [64-1:0] addr;
00066: rand logic [64-1:0] data;
00067: rand int n_bits = 64;
00068:
00069: vmm_rw::status_e status;
00070:
00071: constraint valid_vmm_rw_access {
00072: n_bits > 0;
00073: n_bits < 64;
00074: }
00075:
00076: extern function new();
00077: extern virtual function string psdisplay(string prefix = "");
00078: endclass: vmm_rw_access
00079:
: 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
00080:
00081:
00082: class vmm_rw_burst extends vmm_rw_access;
00083: rand int unsigned n_beats;
00084: rand bit [64-1:0] incr_addr;
00085: rand bit [64-1:0] max_addr;
00086: rand logic [64-1:0] data[];
00087: vmm_data user_data;
00088:
00089: constraint vmm_rw_burst_valid {
00090: n_beats > 0;
00091: max_addr >= addr;
00092: if (kind == vmm_rw::WRITE || kind == vmm_rw::EXPECT) data.size() == n_beats;
00093: else data.size() == 0;
00094: }
00095:
00096: constraint reasonable {
00097: n_beats <= 1024;
00098: incr_addr inside {0, 1, 2, 4, 8, 16, 32};
00099: }
00100:
00101: constraint linear {
00102: incr_addr == 1;
00103: max_addr == addr + n_beats - 1;
00104: }
00105:
00106: constraint fifo {
00107: incr_addr == 0;
00108: max_addr == addr;
00109: }
00110:
00111: constraint wrap {
00112: incr_addr > 0;
00113: max_addr < addr + (n_beats - 1)* incr_addr;
00114: }
00115:
00116: function new();
00117: this.linear.constraint_mode(0);
00118: this.fifo.constraint_mode(0);
00119: this.wrap.constraint_mode(0);
00120: endfunction: new
00121: endclass: vmm_rw_burst
00122:
00123:
00124: typedef class vmm_rw_xactor;
00125: class vmm_rw_xactor_callbacks extends vmm_xactor_callbacks;
00126: virtual task pre_single(vmm_rw_xactor xactor,
00127: vmm_rw_access tr);
00128: endtask
00129:
00130: virtual task pre_burst(vmm_rw_xactor xactor,
00131: vmm_rw_burst tr);
00132: endtask
00133:
00134: virtual task post_single(vmm_rw_xactor xactor,
00135: vmm_rw_access tr);
00136: endtask
00137:
00138: virtual task post_burst(vmm_rw_xactor xactor,
00139: vmm_rw_burst tr);
00140: endtask
00141: endclass: vmm_rw_xactor_callbacks
00142:
00143:
00144: class vmm_rw_xactor extends vmm_xactor;
00145: typedef enum {BURST_DONE = 99990,
00146: SINGLE_DONE} notifications_e;
00147:
00148: vmm_rw_access_channel exec_chan;
00149:
00150: extern function new(string name,
00151: string inst,
00152: int stream_id = -1,
00153: vmm_rw_access_channel exec_chan = null);
00154:
00155: extern protected virtual task execute_single(vmm_rw_access tr);
00156: extern protected virtual task execute_burst(vmm_rw_burst tr);
00157:
00158: extern protected virtual task main();
00159: extern function void reset_xactor(vmm_xactor::reset_e rst_typ = SOFT_RST);
00160: endclass: vmm_rw_xactor
00161:
00162:
00163: function vmm_rw_access::new();
00164: super.new(this.log);
00165: endfunction: new
00166:
00167: function string vmm_rw_access::psdisplay(string prefix = "");
00168: string fmt;
00169: $sformat(fmt, "%0dh", this.n_bits);
00170: $sformat(psdisplay, {"%s%s @ 0x%h = %0d'h%", fmt, "\n"}, prefix,
00171: kind.name(), addr, n_bits, data);
00172: endfunction: psdisplay
00173:
00174:
00175: function vmm_rw_xactor::new(string name,
00176: string inst,
00177: int stream_id = -1,
00178: vmm_rw_access_channel exec_chan = null);
00179: super.new(name, inst, stream_id);
00180:
00181: if (exec_chan == null) exec_chan = new({name, " Input Channel"}, inst);
00182: this.exec_chan = exec_chan;
00183:
00184: this.log.is_above(this.exec_chan.log);
00185:
00186: void'(this.notify.configure(BURST_DONE));
00187: void'(this.notify.configure(SINGLE_DONE));
00188: endfunction: new
00189:
00190:
00191: task vmm_rw_xactor::execute_single(vmm_rw_access tr);
00192:
: do
: /* synopsys translate_off */
: if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::FATAL_SEV, "", -1)) begin
: void'(this.log.text("Undefined execute_single method in vmm_rw_xactor extension"));
: this.log.end_msg();
: end
: /* synopsys translate_on */
: while (0);
00193: endtask: execute_single
00194:
00195:
00196: task vmm_rw_xactor::execute_burst(vmm_rw_burst tr);
00197: bit [64-1:0] addr;
00198: int i;
00199:
00200: addr = tr.addr;
00201: i = 0;
00202: tr.status = vmm_rw::IS_OK;
00203: if (tr.kind == vmm_rw::READ) tr.data = new [tr.n_beats];
00204: repeat (tr.n_beats) begin
00205: vmm_rw_access s = new;
00206: s.kind = tr.kind;
00207: s.addr = addr;
00208: if (s.kind != vmm_rw::READ) s.data = tr.data[i++];
00209: this.execute_single(s);
00210: if (s.kind == vmm_rw::READ) tr.data[i++] = s.data;
00211: if (s.status != vmm_rw::IS_OK) begin
00212: tr.status = s.status;
00213: return;
00214: end
00215:
00216: addr += tr.incr_addr;
00217: if (addr > tr.max_addr) addr = addr - tr.max_addr + tr.addr;
00218: end
00219: tr.status = vmm_rw::IS_OK;
00220: endtask: execute_burst
00221:
00222:
00223: task vmm_rw_xactor::main();
00224: vmm_rw_access tr;
00225: vmm_rw_burst br;
00226:
00227: fork
00228: super.main();
00229: join_none
00230:
00231: forever begin
00232: this.wait_if_stopped_or_empty(this.exec_chan);
00233:
00234: this.exec_chan.activate(tr);
00235: void'(this.exec_chan.start());
00236:
00237: 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);
00240: 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);
00243: this.notify.indicate(BURST_DONE, br);
00244: end
00245: else begin
00246:
:
: 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);
00247: 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);
00250: this.notify.indicate(SINGLE_DONE, tr);
00251: end
00252:
00253: void'(this.exec_chan.complete());
00254: void'(this.exec_chan.remove());
00255: end
00256: endtask: main
00257:
00258:
00259: function void vmm_rw_xactor::reset_xactor(vmm_xactor::reset_e rst_typ= SOFT_RST);
00260: vmm_rw_access tr;
00261:
00262: super.reset_xactor(rst_typ);
00263:
00264: // Force a completion of the transaction to avoid
00265: // leaving the RAL model blocked
00266: tr = this.exec_chan.active_slot();
00267: if (tr != null) begin
00268: tr.status = vmm_rw::RETRY;
00269: void'(this.exec_chan.complete());
00270: void'(this.exec_chan.remove());
00271: end
00272: this.exec_chan.flush();
00273: endfunction: reset_xactor
00274: