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:
00023: function vmm_xactor::new(string name,
00024: string inst,
00025: int stream_id = -1
00026: );
00027:
00028:
00032:
00033: this.log = new(name, inst);
00034: this.notify = new(this.log);
00035:
00036:
00037: void'(this.notify.configure(XACTOR_IDLE, vmm_notify::ON_OFF));
00038: void'(this.notify.configure(XACTOR_BUSY, vmm_notify::ON_OFF));
00039: void'(this.notify.configure(XACTOR_STARTED));
00040: void'(this.notify.configure(XACTOR_STOPPING, vmm_notify::ON_OFF));
00041: void'(this.notify.configure(XACTOR_IS_STOPPED, vmm_notify::ON_OFF));
00042: void'(this.notify.configure(XACTOR_STOPPED));
00043: void'(this.notify.configure(XACTOR_RESET));
00044:
00045: this.is_stopped = 1;
00046: this.notify.indicate(XACTOR_IS_STOPPED);
00047: this.notify.indicate(XACTOR_IDLE);
00048: this.notify.reset(XACTOR_BUSY);
00049:
00050: this.stream_id = stream_id;
00051:
00052: this.start_it = 0;
00053: this.stop_it = 1;
00054: this.reset_it = 0;
00055: this.n_threads_to_stop = -1;
00056: this.n_threads_stopped = 0;
00057: this.main_running = 0;
00058:
00059: this._vmm_available_xactor.push_back(this);
00060:
00061: fork
00062: begin
00063: this.save_main_rng_state = 1;
00064: this.restore_main_rng_state = 0;
00065: this.main_rng_state = get_randstate();
00066:
00067: while (1) begin
00068: this.main_running = 0;
00069:
00070: // wait to start
00071: while (!this.start_it) @(this.control_event);
00072: this.start_it = 0;
00073: this.stop_it = 0;
00074: this.reset_it = 0;
00075: this.n_threads_to_stop = -1;
00076: this.n_threads_stopped = 0;
00077: this.is_stopped = 0;
00078:
00079: // We may be held back by on-going reset operation
00080: fork
00081: if (this.log.start_msg(vmm_log::INTERNAL_TYP, vmm_log::TRACE_SEV)) begin
00082: void'(this.log.text("Start delayed by on-going reset activity"));
00083: this.log.end_msg();
00084: end
00085: join_none
00086:
00087: while (this.reset_pending > 0) begin
00088:
: do
: /* synopsys translate_off */
: if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::FATAL_SEV, "", -1)) begin
: void'(this.log.text("Pending resets not currently supported"));
: this.log.end_msg();
: end
: /* synopsys translate_on */
: while (0);
00089: // `wait(@(this.reset_pending)); // Not supported yet.
00090: end
00091: disable fork;
00092:
00093: //
00094: // Fork the main body
00095: //
00096:
00097: if (this.save_main_rng_state) begin
00098: this.main_rng_state = get_randstate();
00099: end
00100: if (this.restore_main_rng_state) begin
00101: set_randstate(main_rng_state);
00102: end
00103: this.save_main_rng_state = 0;
00104: this.restore_main_rng_state = 0;
00105:
00106: fork
00107: begin
00108: if (this.log.start_msg(vmm_log::INTERNAL_TYP, vmm_log::TRACE_SEV )) begin
00109: void'(this.log.text("Started"));
00110: this.log.end_msg();
00111: end
00112:
00113: this.is_stopped = 0;
00114: this.notify.reset(XACTOR_IDLE);
00115: this.notify.reset(XACTOR_IS_STOPPED);
00116: this.notify.indicate(XACTOR_BUSY);
00117: this.notify.indicate(XACTOR_STARTED);
00118: main();
00119: end
00120:
00121: begin
00122: // Check that super.main() was called in all
00123: // extensions of this class
00124: #1;
00125: if (!this.main_running) begin
00126:
: do
: /* synopsys translate_off */
: if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::WARNING_SEV, "", -1)) begin
: void'(this.log.text("Virtual vmm_xactor::main does not call super.main"));
: this.log.end_msg();
: end
: /* synopsys translate_on */
: while(0);
00127: end
00128: end
00129: join_none
00130:
00131: // Wait to reset
00132: while (!this.reset_it) @(this.control_event);
00133: this.reset_it = 0;
00134: this.n_threads_to_stop = -1;
00135: this.n_threads_stopped = 0;
00136: if (this.log.start_msg(vmm_log::INTERNAL_TYP, vmm_log::TRACE_SEV)) begin
00137: void'(this.log.text("Reset"));
00138: this.log.end_msg();
00139: end
00140: this.is_stopped = 1;
00141: this.notify.reset(XACTOR_BUSY);
00142: this.notify.indicate(XACTOR_IDLE);
00143: this.notify.reset(XACTOR_STOPPING);
00144: this.notify.indicate(XACTOR_IS_STOPPED);
00145: this.notify.indicate(XACTOR_STOPPED);
00146: this.notify.indicate(XACTOR_RESET);
00147: disable fork;
00148: end
00149: end
00150: join_none
00151: endfunction: new
00152:
00153:
00154: function string vmm_xactor::get_name();
00155: get_name = this.log.get_name();
00156: endfunction:get_name
00157:
00158:
00159: function string vmm_xactor::get_instance();
00160: get_instance = this.log.get_instance();
00161: endfunction: get_instance
00162:
00163:
00164: function void vmm_xactor::start_xactor();
00165: this.start_it = 1;
00166: this.stop_it = 0;
00167: -> this.control_event;
00168: this.notify.reset(XACTOR_STOPPING);
00169: endfunction: start_xactor
00170:
00171:
00172: function void vmm_xactor::stop_xactor();
00173: this.start_it = 0;
00174: this.stop_it = 1;
00175: -> this.control_event;
00176: this.notify.indicate(XACTOR_STOPPING);
00177:
00178: // Is it already stopped?
00179: if (this.is_stopped) begin
00180: if (this.log.start_msg(vmm_log::INTERNAL_TYP, vmm_log::TRACE_SEV)) begin
00181: void'(this.log.text("Already stopped"));
00182: this.log.end_msg();
00183: end
00184: this.notify.indicate(XACTOR_STOPPED);
00185: return;
00186: end
00187:
00188: if (this.log.start_msg(vmm_log::INTERNAL_TYP, vmm_log::TRACE_SEV)) begin
00189: void'(this.log.text("Stop requested"));
00190: this.log.end_msg();
00191: end
00192: this.check_all_threads_stopped();
00193: endfunction: stop_xactor
00194:
00195:
00196: function void vmm_xactor::reset_xactor(vmm_xactor::reset_e rst_typ = SOFT_RST);
00197: this.start_it = 0;
00198: this.reset_it = 1;
00199: -> this.control_event;
00200: this.is_stopped = 1;
00201:
00202: // Reset notifier & RNG state on FIRM and above
00203: if (rst_typ == FIRM_RST ||
00204: rst_typ == HARD_RST) begin
00205: this.notify.reset(-1, vmm_notify::HARD);
00206: this.restore_rng_state();
00207: end
00208: else begin
00209: this.notify.reset(-1, vmm_notify::SOFT);
00210: end
00211:
00212: // Unregister all callbacks on HARD reset
00213: if (rst_typ == HARD_RST) begin
00219: // Works in VCS2008.03 or later
00220: // IEEE 1800-2005 compliant
00221: this.callbacks = '{};
00223: end
00224: endfunction: reset_xactor
00225:
00226:
00227: function void vmm_xactor::save_rng_state();
00228: if (this.log.start_msg(vmm_log::INTERNAL_TYP, vmm_log::TRACE_SEV)) begin
00229: void'(this.log.text("Saving RNG state information..."));
00230: this.log.end_msg();
00231: end
00232:
00233: if (!this.is_stopped) begin
00234:
: do
: /* synopsys translate_off */
: if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::WARNING_SEV, "", -1)) begin
: void'(this.log.text("save_rng_state called while transactor is still running"));
: this.log.end_msg();
: end
: /* synopsys translate_on */
: while(0);
00235: end
00236: this.save_main_rng_state = 1;
00237: endfunction: save_rng_state
00238:
00239:
00240: function void vmm_xactor::restore_rng_state();
00241: if (this.log.start_msg(vmm_log::INTERNAL_TYP, vmm_log::TRACE_SEV)) begin
00242: void'(this.log.text("Restoring RNG state information..."));
00243: this.log.end_msg();
00244: end
00245:
00246: if (!this.is_stopped) begin
00247:
: do
: /* synopsys translate_off */
: if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::WARNING_SEV, "", -1)) begin
: void'(this.log.text("restore_rng_state called while transactor is still running"));
: this.log.end_msg();
: end
: /* synopsys translate_on */
: while(0);
00248: end
00249: this.restore_main_rng_state = 1;
00250: endfunction: restore_rng_state
00251:
00252:
00253: function string vmm_xactor::psdisplay(string prefix = "");
00254: $sformat(psdisplay, "%sTransactor %s (%s):", prefix,
00255: this.log.get_name(), this.log.get_instance());
00256:
00257: if (this.is_stopped) begin
00258: return {psdisplay, "\n", prefix, "Transactor is STOPPED"};
00259: end
00260:
00261: if (this.n_threads_stopped < this.n_threads_to_stop) begin
00262: return $psprintf("%s\n%sTransactor is STOPPING (%0d out of %0d threads stopped)",
00263: psdisplay, prefix, this.n_threads_stopped,
00264: this.n_threads_to_stop);
00265: end
00266:
00267: return {psdisplay, "\n", prefix, "Transactor is RUNNING"};
00268: endfunction: psdisplay
00269:
00270:
00271: function void vmm_xactor::xactor_status(string prefix = "");
00272:
: do
: /* synopsys translate_off */
: if (this.log.start_msg(vmm_log::NOTE_TYP, , "", -1)) begin
: void'(this.log.text(this.psdisplay(prefix)));
: this.log.end_msg();
: end
: /* synopsys translate_on */
: while (0);
00273: endfunction: xactor_status
00274:
00275:
00276: task vmm_xactor::main();
00277: this.main_running = 1;
00278: endtask: main
00279:
00280:
00281: function void vmm_xactor::check_all_threads_stopped();
00282: if (this.n_threads_to_stop > 0) begin
00283: if (this.log.start_msg(vmm_log::INTERNAL_TYP, vmm_log::TRACE_SEV)) begin
00284: void'(this.log.text($psprintf("%0d out of %0d threads have now stopped",n_threads_stopped,this.n_threads_to_stop)));
00285: this.log.end_msg();
00286: end
00287:
00288: if (this.n_threads_stopped >= this.n_threads_to_stop) begin
00289: if (this.log.start_msg(vmm_log::INTERNAL_TYP, vmm_log::TRACE_SEV)) begin
00290: void'(this.log.text("Stopped"));
00291: this.log.end_msg();
00292: end
00293:
00294: this.is_stopped = 1;
00295: this.notify.reset(XACTOR_BUSY);
00296: this.notify.indicate(XACTOR_IDLE);
00297: this.notify.reset(XACTOR_STOPPING);
00298: this.notify.indicate(XACTOR_IS_STOPPED);
00299: this.notify.indicate(XACTOR_STOPPED);
00300: end
00301: end
00302: endfunction
00303:
00304:
00305: task vmm_xactor::wait_if_stopped(int unsigned n_threads = 1);
00306: if (n_threads == 0) begin
00307: if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin
00308: void'(this.log.text("Number of threads to stop specified to vmm_xactor::wait_if_stopped() must be greater than 0"));
00309: this.log.end_msg();
00310: end
00311: n_threads = 1;
00312: end
00313:
00314: if (this.n_threads_to_stop <= 0) this.n_threads_to_stop = n_threads;
00315: else if (this.n_threads_to_stop != n_threads) begin
00316: if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin
00317: void'(this.log.text("All threads must specify the same number of threads to stop to vmm_xactor::wait_if_stopped() and vmm_xactor::wait_if_stopped_or_empty()"));
00318: this.log.end_msg();
00319: end
00320: if (this.n_threads_to_stop < n_threads) this.n_threads_to_stop = n_threads;
00321: end
00322:
00323: if (this.stop_it) begin
00324: this.n_threads_stopped++;
00325: this.check_all_threads_stopped();
00326:
00327: while (this.stop_it) @(this.control_event);
00328: // Make sure these are done only once if
00329: // there are multiple stopped threads
00330: if (this.is_stopped) begin
00331: if (this.log.start_msg(vmm_log::INTERNAL_TYP, vmm_log::TRACE_SEV)) begin
00332: void'(this.log.text("Restarted"));
00333: this.log.end_msg();
00334: end
00335: this.is_stopped = 0;
00336: this.notify.indicate(XACTOR_STARTED);
00337: this.notify.reset(XACTOR_IS_STOPPED);
00338: this.notify.reset(XACTOR_IDLE);
00339: this.notify.indicate(XACTOR_BUSY);
00340: end
00341: this.n_threads_stopped--;
00342: end
00343: endtask: wait_if_stopped
00344:
00345:
00346: task vmm_xactor::wait_if_stopped_or_empty(vmm_channel chan,
00347: int unsigned n_threads = 1);
00348: this.wait_if_stopped(n_threads);
00349: while (chan.level() == 0) begin
00350: vmm_data data;
00351:
00352: this.n_threads_stopped++;
00353: // If all other threads are blocked, indicate IDLE
00354: // because we are going to block on the channel
00355: if (this.n_threads_stopped >= this.n_threads_to_stop) begin
00356: this.notify.reset(XACTOR_BUSY);
00357: this.notify.indicate(XACTOR_IDLE);
00358: end
00359:
00360: if (this.log.start_msg(vmm_log::INTERNAL_TYP, vmm_log::TRACE_SEV)) begin
00361: void'(this.log.text($psprintf("%0d threads have now stopped or blocked",n_threads_stopped)));
00362: this.log.end_msg();
00363: end
00364:
00365: chan.peek(data);
00366: this.n_threads_stopped--;
00367: this.wait_if_stopped(n_threads);
00368: end
00369:
00370: this.notify.reset(XACTOR_IDLE);
00371: this.notify.indicate(XACTOR_BUSY);
00372: endtask: wait_if_stopped_or_empty
00373:
00374:
00375: function void vmm_xactor::prepend_callback(vmm_xactor_callbacks cb);
00376: if (cb == null) begin
00377:
: do
: /* synopsys translate_off */
: if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV, "", -1)) begin
: void'(this.log.text("Attempting to prepend a NULL callback extension"));
: this.log.end_msg();
: end
: /* synopsys translate_on */
: while (0);
00378: return;
00379: end
00380:
00381: foreach(this.callbacks[i]) begin
00382: if (this.callbacks[i] == cb) begin
00383:
: do
: /* synopsys translate_off */
: if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::WARNING_SEV, "", -1)) begin
: void'(this.log.text("Callback has already been registered"));
: this.log.end_msg();
: end
: /* synopsys translate_on */
: while(0);
00384: return;
00385: end
00386: end
00387: //Prepend new callback
00388: this.callbacks.push_front(cb);
00389: endfunction: prepend_callback
00390:
00391:
00392: function void vmm_xactor::append_callback(vmm_xactor_callbacks cb);
00393: if (cb == null) begin
00394:
: do
: /* synopsys translate_off */
: if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV, "", -1)) begin
: void'(this.log.text("Attempting to append a NULL callback extension"));
: this.log.end_msg();
: end
: /* synopsys translate_on */
: while (0);
00395: return;
00396: end
00397:
00398: foreach(this.callbacks[i]) begin
00399: if (this.callbacks[i] == cb) begin
00400:
: do
: /* synopsys translate_off */
: if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::WARNING_SEV, "", -1)) begin
: void'(this.log.text("Callback has already been registered"));
: this.log.end_msg();
: end
: /* synopsys translate_on */
: while(0);
00401: return;
00402: end
00403: end
00404: //Append new callback
00405: this.callbacks.push_back(cb);
00406: endfunction: append_callback
00407:
00408:
00409: function void vmm_xactor::unregister_callback(vmm_xactor_callbacks cb);
00410: foreach(this.callbacks[i]) begin
00411: if (this.callbacks[i] == cb) begin
00412: // Unregister it
00413: this.callbacks.delete(i);
00414: return;
00415: end
00416: end
00417:
00418:
: do
: /* synopsys translate_off */
: if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::WARNING_SEV, "", -1)) begin
: void'(this.log.text("Callback was not registered"));
: this.log.end_msg();
: end
: /* synopsys translate_on */
: while(0);
00419: endfunction: unregister_callback
00420:
00421:
00422: function void vmm_xactor::get_input_channels(ref vmm_channel chans[$]);
00423: chans = this.Xinput_chansX;
00424: endfunction: get_input_channels
00425:
00426:
00427: function void vmm_xactor::get_output_channels(ref vmm_channel chans[$]);
00428: chans = this.Xoutput_chansX;
00429: endfunction: get_output_channels
00430:
00431:
00432: function void vmm_xactor::kill();
00433: vmm_channel ins[$] = this.Xinput_chansX;
00434: vmm_channel outs[$] = this.Xoutput_chansX;
00435:
00442: // Works in VCS2008.03 or later
00443: // IEEE 1800-2005 compliant
00444: this.Xinput_chansX = '{};
00445: this.Xoutput_chansX = '{};
00447:
00448: foreach(ins[i]) begin
00449: if (ins[i].get_consumer() == this) begin
00450: ins[i].set_consumer(null);
00451: if (ins[i].get_producer() == null) ins[i].kill();
00452: end
00453: end
00454:
00455: foreach(outs[i]) begin
00456: if (outs[i].get_producer() == this) begin
00457: outs[i].set_producer(null);
00458: if (outs[i].get_consumer() == null) outs[i].kill();
00459: end
00460: end
00461:
00462: foreach(this._vmm_available_xactor[i]) begin
00463: if (this._vmm_available_xactor[i] == this) begin
00464: this._vmm_available_xactor.delete(i);
00465: break;
00466: end
00467: end
00468:
00469: this.log.kill();
00470: endfunction: kill
00471:
00472:
00473:
00474:
00475:
00542:
00543:
00544: function string vmm_xactor::do_psdisplay(string prefix = "");
00545: this.__vmm_done_user = 0;
00546: endfunction
00547:
00548:
00549: function void vmm_xactor::do_start_xactor();
00550: this.__vmm_done_user = 0;
00551: endfunction
00552:
00553:
00554: function void vmm_xactor::do_stop_xactor();
00555: this.__vmm_done_user = 0;
00556: endfunction
00557:
00558:
00559: function void vmm_xactor::do_reset_xactor(vmm_xactor::reset_e rst_typ);
00560: this.__vmm_done_user = 0;
00561: endfunction
00562:
00563:
00564: function void vmm_xactor::do_kill_xactor();
00565: this.__vmm_done_user = 0;
00566: endfunction
00567:
00568:
00569: function vmm_xactor_iter::new(string name = "",
00570: string inst = "");
00571: if (name == "") this.name = ".";
00572: else begin
00573: // Remove "/" surrounding the pattern, if any
00574: if (vmm_str_match(name, "^/.*/$")) name = vmm_str_backref(0+1);
00575: this.name = name;
00576: end
00577:
00578: if (inst == "") this.inst = ".";
00579: else begin
00580: // Remove "/" surrounding the pattern, if any
00581: if (vmm_str_match(inst, "^/.*/$")) inst = vmm_str_backref(0+1);
00582: this.inst = inst;
00583: end
00584:
00585: void'(this.first());
00586: endfunction: new
00587:
00588:
00589: function void vmm_xactor_iter::move_iterator();
00590: string xa_name;
00591: string xa_inst;
00592: int n = _vmm_xactor._vmm_available_xactor.size();
00593:
00594: if (this.idx >= n || n <= 1) return;
00595:
00596: for (int x = this.idx+1; x < n; x++) begin
00597: xa_name = _vmm_xactor._vmm_available_xactor[x].log.get_name();
00598: xa_inst = _vmm_xactor._vmm_available_xactor[x].log.get_instance();
00599:
00600: if (vmm_str_match(xa_name, this.name) &&
00601: vmm_str_match(xa_inst, this.inst)) begin
00602: this.idx = x;
00603: return;
00604: end
00605: end
00606: this.idx = 0;
00607: endfunction
00608:
00609:
00610: function vmm_xactor vmm_xactor_iter::xactor();
00611: if (this.idx <= 0 ||
00612: this.idx >= _vmm_xactor._vmm_available_xactor.size())
00613: return null;
00614:
00615: return _vmm_xactor._vmm_available_xactor[this.idx];
00616: endfunction
00617:
00618:
00619: function vmm_xactor vmm_xactor_iter::first();
00620: this.idx = 0;
00621: this.move_iterator();
00622: return this.xactor();
00623: endfunction
00624:
00625:
00626: function vmm_xactor vmm_xactor_iter::next();
00627: this.move_iterator();
00628: return this.xactor();
00629: endfunction