VMM - (expanded) std_lib/xvc_xactor.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.

std_lib/xvc_xactor.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: 
00023: 
00024: function xvc_xactor::new(string             name,
00025:                          string             inst,
00026:                          int                stream_id,
00027:                          xvc_action_channel action_chan,
00028:                          xvc_action_channel interrupt_chan
00029:                          );
00030:    super.new(name, inst, stream_id );
00031: 
00032:    this.trace = new({name, " Trace"}, inst);
00033: 
00034:    if (action_chan == null) begin
00035:       action_chan = new({name, "Action Channel"}, inst);
00036:    end else action_chan.reconfigure(1, 0);
00037:    this.action_chan = action_chan;
00038:    this.log.is_above(this.action_chan.log);
00039: 
00040:    if (interrupt_chan == null) begin
00041:       interrupt_chan = new({name, "Interrupt Channel"}, inst, 65535);
00042:    end else interrupt_chan.reconfigure(65535, 0);
00043:    this.interrupt_chan = interrupt_chan;
00044:    this.log.is_above(this.interrupt_chan.log);
00045: 
00046:    this.interrupt = 0;
00047:    this.interrupted = 0;
00048: 
00049:    this.idle = new("Dummy idle action", this.log);
00050: endfunction: new
00051: 
00052: 
00053: function void xvc_xactor::add_action(xvc_action action);
00054:    int i;
00055: 
00056:    if (action == null) begin
00057:       
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text("Attempting to add a NULL action")); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00058:       return;
00059:    end
00060: 
00061:    // Do we already know about this action?
00062:    foreach(this.known_actions[i]) begin
00063:       if (this.known_actions[i] == action) begin
00064:          
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::WARNING_SEV)) begin 
     :       void'(this.log.text("Attempting to add already-known action")); 
     :       this.log.end_msg(); 
     :    end 
     : while(0);
00065:          return;
00066:       end
00067:    end
00068: 
00069:    this.known_actions.push_back(action);
00070: endfunction: add_action
00071: 
00072: 
00073: function xvc_action xvc_xactor::parse(string argv[]);
00074:    int i;
00075: 
00076:    parse = null;
00077: 
00078:    foreach(this.known_actions[i]) begin
00079:       parse = this.known_actions[i].parse(argv);
00080:       if (parse != null) return parse;
00081:    end
00082: 
00083:    if (this.log.start_msg(vmm_log::FAILURE_TYP,
00084:                           vmm_log::ERROR_SEV)) begin
00085:        string msg = "Unknown action command:";
00086:        foreach (argv[i]) begin
00087:           msg = {msg, " ", argv[i]};
00088:        end
00089:        void'(this.log.text(msg));
00090:        this.log.end_msg();
00091:    end
00092: endfunction: parse
00093: 
00094: 
00095: function void xvc_xactor::start_xactor();
00096:    super.start_xactor();
00097: endfunction: start_xactor
00098: 
00099: 
00100: function void xvc_xactor::stop_xactor();
00101:    super.stop_xactor();
00102: endfunction: stop_xactor
00103: 
00104: 
00105: function void xvc_xactor::reset_xactor(vmm_xactor::reset_e rst_typ);
00106:    super.reset_xactor(rst_typ);
00107: 
00108:    this.action_chan.flush();
00109:    this.interrupt_chan.flush();
00110:    this.executing = null;
00111:    this.interrupt = 0;
00112:    this.interrupted = 0;
00113:        
00114:    if (rst_typ > vmm_xactor::HARD_RST) begin
00120:       // Works in VCS2008.03
00121:       this.known_actions = '{};
00123:    end
00124: endfunction: reset_xactor
00125: 
00126: 
00127: function void xvc_xactor::xactor_status(string prefix);
00128:    super.xactor_status(prefix);
00129: 
00130:    if (this.interrupt) begin
00131:       // Pending interrupt
00132:       if (this.interrupted) begin
00133:          // Interrupted...
00134:          if (this.executing == null) begin
00136: 
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text("Internal Error: interrupted but not executing")); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00137:          end else begin
00138:             $display("   Executing interrupt action \"%s\".",
00139:                      this.executing.get_name());
00140:          end
00141:       end else begin
00142:          $display("   Waiting for action \"%s\" to be interrupted.",
00143:                   this.executing.get_name());
00144:       end
00145:    end else begin
00146:       if (this.executing == null) begin
00147:          $display("   Waiting to execute an action...");
00148:       end else begin
00149:          $display("   Executing action \"%s\".",
00150:                 this.executing.get_name());
00151:       end
00152:    end
00153: endfunction: xactor_status
00154: 
00155: 
00156: task xvc_xactor::main();
00157:    fork
00158:        super.main();
00159:        this.execute_actions();
00160:        this.execute_interruptions();
00161:    join_none
00162: endtask: main
00163: 
00164: 
00165: task xvc_xactor::execute_actions();
00166:    xvc_action action;
00167: 
00168:    while (1) begin
00169:       // OK to be interrupted while not executing actions
00170:       this.interrupted = 1;
00171:       this.wait_if_stopped_or_empty(this.action_chan);
00172:       this.action_chan.activate(action);
00173:       this.interrupted = 0;
00174: 
00175:       this.executing = action;
00176:       this.wait_if_interrupted();
00177: 
00178:       this.execute_action(this.action_chan, "action");
00179:    end
00180: endtask: execute_actions
00181: 
00182: 
00183: task xvc_xactor::execute_interruptions();
00184:    xvc_action action;
00185: 
00186:    while (1) begin
00187:       this.wait_if_stopped_or_empty(this.interrupt_chan);
00188:       this.interrupt_chan.activate(action);
00189: 
00190:       this.interrupt = 1;
00191:       if (this.log.start_msg(vmm_log::INTERNAL_TYP, vmm_log::DEBUG_SEV)) begin
00192:          void'(this.log.text("Requesting action interrupt..."));
00193:          this.log.end_msg();
00194:       end
00195:       wait (this.interrupted);
00196: 
00197:       if (this.suspended == null) this.suspended = idle;
00198:       this.execute_action(this.interrupt_chan, "interrupt action");
00199:       if (this.suspended == idle) this.suspended = null;
00200:    
00201:      if (this.interrupt_chan.level() == 0) begin
00202:          this.interrupt = 0;
00203:          -> this.rte;
00204:       end
00205:    end
00206: endtask: execute_interruptions          
00207: 
00208: 
00209: task xvc_xactor::wait_if_interrupted();
00210:    if (this.suspended != null) begin
00211:       if (this.log.start_msg(vmm_log::INTERNAL_TYP, vmm_log::WARNING_SEV)) begin
00212:          void'(this.log.text("Interrupt actions cannot be interrupted. Ignoring call to xvc_xactor::wait_if_interrupted()"));
00213:          this.log.end_msg();
00214:       end
00215:       return;
00216:    end
00217: 
00218:    // Wait, not only for an interrupt action that is
00219:    // requesting execution - but also if there is
00220:    // one ready in the interrupt channel to resolve
00221:    // race condition between the regular executor and
00222:    // the interrupt executor.
00223:    if (this.interrupt || this.interrupt_chan.level() > 0) begin
00224:       if (this.log.start_msg(vmm_log::INTERNAL_TYP, vmm_log::TRACE_SEV)) begin
00225:          void'(this.log.text($psprintf("Interrupting action \"%s\"...",
00226:                                            this.executing.get_name())));
00227:          this.log.end_msg();
00228:       end
00229:       this.suspended = this.executing;
00230:       this.executing = null;
00231:       this.interrupted = 1;
00232: 
00233:       @this.rte;
00234:       this.executing = this.suspended;
00235:       this.suspended = null;
00236:       this.interrupted = 0;
00237:       if (this.log.start_msg(vmm_log::INTERNAL_TYP, vmm_log::TRACE_SEV)) begin
00238:          void'(this.log.text($psprintf("Resuming action \"%s\"...",
00239:                                            this.executing.get_name())));
00240:          this.log.end_msg();
00241:       end
00242:    end
00243: endtask: wait_if_interrupted
00244: 
00245: 
00246: task xvc_xactor::execute_action(xvc_action_channel chan,
00247:                                 string             descr);
00248:    xvc_action action;
00249:    int i;
00250: 
00251:    action = chan.active_slot();
00252: 
00253:    if (this.trace.start_msg(vmm_log::INTERNAL_TYP, vmm_log::TRACE_SEV)) begin
00254:       void'(this.trace.text($psprintf("Executing %s \"%s\"...",
00255:                                           descr, action.get_name())));
00256:       this.trace.end_msg();
00257:    end
00258: 
00259:    this.executing = action;
00260:    this.executing.display({descr,": "});
00261:    // Prepend any callback required by the action
00262:    foreach (action.callbacks[i]) begin
00263:       if (action.callbacks[i] != null) begin
00264:          if (i >= this.xactors.size() || this.xactors[i] == null) begin
00267: 
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::FATAL_SEV)) begin 
     :       void'(this.log.text($psprintf("No xvc_xactor::xactors[%0d] to register callback from action \"%s\".",
     :                                      i, action.get_name()))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00268:             continue;
00269:          end
00270:          this.xactors[i].prepend_callback(action.callbacks[i]);
00271:       end
00272:    end
00273:    
00274:    chan.start();
00275:    action.execute(this.exec_chan, this);
00276:    chan.complete();
00277: 
00278:    // De-register callbacks
00279:    foreach (action.callbacks[i]) begin
00280:       if (action.callbacks[i] != null) begin
00281:          if (i >= this.xactors.size() || this.xactors[i] == null) continue;
00282:          this.xactors[i].unregister_callback(action.callbacks[i]);
00283:       end
00284:    end
00285:    
00286:    this.executing = null;
00287: 
00288:    if (this.trace.start_msg(vmm_log::INTERNAL_TYP, vmm_log::TRACE_SEV)) begin
00289:       void'(this.trace.text($psprintf("Completed %s \"%s\"...",
00290:                                           descr, action.get_name())));
00291:       this.trace.end_msg();
00292:    end
00293:    
00294:    chan.remove();
00295: endtask: execute_action
00296: 
00297: 
00298: function void xvc_xactor::save_rng_state();
00299: endfunction: save_rng_state
00300: 
00301: 
00302: function void xvc_xactor::restore_rng_state();
00303: endfunction: restore_rng_state