VMM - (expanded) std_lib/vmm_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/vmm_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: function vmm_xactor::new(string name,
00024:                          string inst,
00025:      	                 int    stream_id
00026:                          );
00027: 
00028: 
00032: 
00033:    this.log  = new(name, inst);
00034:    this.notify = new(this.log);
00035:    this.notify.configure(XACTOR_IDLE, vmm_notify::ON_OFF);
00036:    this.notify.configure(XACTOR_BUSY, vmm_notify::ON_OFF);
00037:    this.notify.configure(XACTOR_STARTED);
00038:    this.notify.configure(XACTOR_STOPPING, vmm_notify::ON_OFF);
00039:    this.notify.configure(XACTOR_STOPPED);
00040:    this.notify.configure(XACTOR_RESET);
00041: 
00042:    this.notify.indicate(XACTOR_IDLE);
00043:    this.notify.reset(XACTOR_BUSY);
00044: 
00045:    this.stream_id   = stream_id;
00046: 
00047:    this.start_it   = 0;
00048:    this.stop_it    = 1;
00049:    this.n_threads_to_stop = 0;
00050:    this.n_threads_stopped = 0;
00051:    this.reset_it   = 0;
00052:    this.resetable  = 0;
00053:    this.main_running = 0;
00054: 
00055:    fork
00056:       begin
00057:       this.save_main_rng_state    = 1;
00058:       this.restore_main_rng_state = 0;
00059:       this.main_rng_state = get_randstate();
00060: 
00061:       while (1) begin
00062:          this.main_running = 0;
00063: 
00064:          // wait to start
00065:          while (!this.start_it) begin
00066:             @ (this.start_it_event);
00067:             // Reset has no effect since we are not started yet
00068:             this.reset_it = 0;
00069:          end
00070:          this.start_it = 0;
00071:          this.stop_it = 0;
00072:          this.n_threads_to_stop = 0;
00073:          this.n_threads_stopped = 0;
00074: 
00075:          // We may be held back by on-going reset operation
00076:          fork
00077:             if (this.log.start_msg(vmm_log::INTERNAL_TYP, vmm_log::TRACE_SEV)) begin
00078:                void'(this.log.text("Start delayed by on-going reset activity"));
00079:                this.log.end_msg();
00080:             end
00081:          join_none
00082: 
00083:          while (this.reset_pending > 0) begin
00084:             
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::FATAL_SEV)) begin 
     :       void'(this.log.text("Pending resets not currently supported")); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00085:             // `wait(@(this.reset_pending)); // Not supported yet.
00086:          end
00087:          disable fork;
00088: 
00089:          //
00090:          // Fork the main body
00091:          //
00092:                
00093:          if (this.save_main_rng_state) begin
00094:             this.main_rng_state = get_randstate();
00095:          end
00096:          if (this.restore_main_rng_state) begin
00097:             set_randstate(main_rng_state);
00098:          end
00099:          this.save_main_rng_state    = 0;
00100:          this.restore_main_rng_state = 0;
00101: 
00102:          fork
00103:             begin
00104:                if (this.log.start_msg(vmm_log::INTERNAL_TYP, vmm_log::TRACE_SEV )) begin
00105:                   void'(this.log.text("Started"));
00106:                   this.log.end_msg();
00107:                end
00108: 
00109:                this.notify.reset(XACTOR_IDLE);
00110:                this.notify.indicate(XACTOR_BUSY);
00111:                this.notify.indicate(XACTOR_STARTED);
00112:                main();
00113:             end
00114: 
00115:             begin
00116:                // Check that super.main() was called in all
00117:                // extensions of this class
00118:                #1;
00119:                if (!this.main_running) begin
00120:                   
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::WARNING_SEV)) begin 
     :       void'(this.log.text("Virtual vmm_xactor::main() does not call super.main()")); 
     :       this.log.end_msg(); 
     :    end 
     : while(0);
00121:                end
00122:             end
00123:          join_none
00124: 
00125:          // Wait to reset
00126:          this.resetable = 1;
00127:          do
00128:             @ (this.reset_it_event);
00129:          while (!this.reset_it);
00130:          this.resetable = 0;
00131:          this.reset_it = 0;
00132:          this.stop_it = 1;
00133:          this.n_threads_to_stop = 0;
00134:          this.n_threads_stopped = 0;
00135:          if (this.log.start_msg(vmm_log::INTERNAL_TYP, vmm_log::TRACE_SEV)) begin
00136:             void'(this.log.text("Reset"));
00137:             this.log.end_msg();
00138:          end
00139:          this.notify.reset(XACTOR_BUSY);
00140:          this.notify.indicate(XACTOR_IDLE);
00141:          this.notify.reset(XACTOR_STOPPING);
00142:          this.notify.indicate(XACTOR_STOPPED);
00143:          this.notify.indicate(XACTOR_RESET);
00144:          disable fork;
00145:          // Pending start?
00146:          if (this.start_it) begin
00147:             ->this.start_it_event;
00148:          end
00149:       end
00150:    end
00151:    join_none
00152: endfunction: new
00153: 
00154: 
00155: function string vmm_xactor::get_name();
00156:    get_name = this.log.get_name();
00157: endfunction:get_name
00158: 
00159: 
00160: function string vmm_xactor::get_instance();
00161:    get_instance = this.log.get_instance();
00162: endfunction: get_instance
00163: 
00164: 
00165: function void vmm_xactor::start_xactor();
00166:    this.start_it = 1;
00167:    -> this.start_it_event;
00168:    this.notify.reset(XACTOR_STOPPING);
00169: endfunction: start_xactor
00170: 
00171: 
00172: function void vmm_xactor::stop_xactor();
00173:    this.stop_it = 1;
00174:    this.start_it = 0;
00175:    this.notify.indicate(XACTOR_STOPPING);
00176: 
00177:    if (this.log.start_msg(vmm_log::INTERNAL_TYP, vmm_log::TRACE_SEV)) begin
00178:       void'(this.log.text("Stop requested"));
00179:       this.log.end_msg();
00180:    end
00181: endfunction: stop_xactor
00182: 
00183: 
00184: function void vmm_xactor::reset_xactor(reset_e rst_typ);
00185:    this.reset_it = 1;
00186:    -> this.reset_it_event;
00187:    this.start_it = 0;
00188: 
00189:    // Reset notifier & RNG state on FIRM and above
00190:    if (rst_typ == FIRM_RST ||
00191:        rst_typ == HARD_RST) begin
00192:       this.notify.reset(-1, vmm_notify::HARD);
00193:       this.restore_rng_state();
00194:    end
00195:    else begin
00196:       this.notify.reset(-1, vmm_notify::SOFT);
00197:    end
00198: 
00199:    // Unregister all callbacks on HARD reset
00200:    if (rst_typ == HARD_RST) begin
00206:       // Works in VCS2008.03
00207:       this.callbacks = '{};
00209:    end
00210: endfunction: reset_xactor
00211: 
00212: 
00213: function void vmm_xactor::save_rng_state();
00214:    if (this.log.start_msg(vmm_log::INTERNAL_TYP, vmm_log::TRACE_SEV)) begin
00215:       void'(this.log.text("Saving RNG state information..."));
00216:       this.log.end_msg();
00217:    end
00218: 
00219:    if (!this.stop_it) begin
00220:       
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::WARNING_SEV)) begin 
     :       void'(this.log.text("save_rng_state() called while transactor is still running")); 
     :       this.log.end_msg(); 
     :    end 
     : while(0);
00221:    end
00222:    this.save_main_rng_state = 1;
00223: endfunction: save_rng_state
00224: 
00225: 
00226: function void vmm_xactor::restore_rng_state();
00227:    if (this.log.start_msg(vmm_log::INTERNAL_TYP, vmm_log::TRACE_SEV)) begin
00228:       void'(this.log.text("Restoring RNG state information..."));
00229:       this.log.end_msg();
00230:    end
00231: 
00232:    if (!this.stop_it) begin
00233:       
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::WARNING_SEV)) begin 
     :       void'(this.log.text("restore_rng_state() called while transactor is still running")); 
     :       this.log.end_msg(); 
     :    end 
     : while(0);
00234:    end
00235:    this.restore_main_rng_state = 1;
00236: endfunction: restore_rng_state
00237: 
00238: 
00239: function void vmm_xactor::xactor_status(string prefix);
00240:    if (this.stop_it) begin
00241:       if (this.n_threads_to_stop == 0) begin
00242:          
     : do 
     :    if (this.log.start_msg(vmm_log::NOTE_TYP)) begin 
     :       void'(this.log.text({prefix, "Transactor is STOPPING (no threads stopped yet)"})); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00243:       end
00244:       else if (this.n_threads_to_stop < this.n_threads_stopped) begin
00247: 
     : do 
     :    if (this.log.start_msg(vmm_log::NOTE_TYP)) begin 
     :       void'(this.log.text($psprintf("%sTransactor is STOPPING (%0d out of %0d threads stopped)",
     :                                            prefix, this.n_threads_stopped,
     :                                            this.n_threads_to_stop))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00248:       end
00249:       else begin
00250:          
     : do 
     :    if (this.log.start_msg(vmm_log::NOTE_TYP)) begin 
     :       void'(this.log.text({prefix, "Transactor is STOPPED"})); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00251:       end
00252:    end
00253:    else 
     : do 
     :    if (this.log.start_msg(vmm_log::NOTE_TYP)) begin 
     :       void'(this.log.text({prefix, "Transactor is RUNNING"})); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00254: endfunction: xactor_status
00255: 
00256: 
00257: task vmm_xactor::main();
00258:    this.main_running = 1;
00259: endtask: main
00260: 
00261: 
00262: task vmm_xactor::wait_if_stopped(int unsigned n_threads);
00263:    if (n_threads == 0) begin
00264:       if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin
00265:          void'(this.log.text("Number of threads to stop specified to vmm_xactor::wait_if_stopped() must be greater than 0"));
00266:          this.log.end_msg();
00267:       end
00268:       n_threads = 1;
00269:    end
00270: 
00271:    if (this.stop_it) begin
00272:        if (this.n_threads_to_stop == 0) this.n_threads_to_stop = n_threads;
00273:        else if (this.n_threads_to_stop != n_threads) begin
00274:           if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin
00275:              void'(this.log.text("All threads must specify the same number of threads to stop to vmm_xactor::wait_if_stopped()"));
00276:              this.log.end_msg();
00277:           end
00278:           if (this.n_threads_to_stop < n_threads) this.n_threads_to_stop = n_threads;
00279:        end
00280: 
00281:        this.n_threads_stopped++;
00282:        if (this.n_threads_stopped >= this.n_threads_to_stop) begin
00283:           if (this.log.start_msg(vmm_log::INTERNAL_TYP, vmm_log::TRACE_SEV)) begin
00284:              void'(this.log.text("Stopped"));
00285:              this.log.end_msg();
00286:           end
00287: 
00288:           this.notify.reset(XACTOR_BUSY);
00289:           this.notify.indicate(XACTOR_IDLE);
00290:           this.notify.reset(XACTOR_STOPPING);
00291:           this.notify.indicate(XACTOR_STOPPED);
00292:        end
00293: 
00294:        @(this.start_it_event);
00295:        this.start_it = 0;
00296:        this.stop_it = 0;
00297:        this.n_threads_stopped = 0;
00298:        this.n_threads_to_stop = 0;
00299: 
00300:        if (this.log.start_msg(vmm_log::INTERNAL_TYP, vmm_log::TRACE_SEV)) begin
00301:           void'(this.log.text("Started"));
00302:           this.log.end_msg();
00303:        end
00304:        this.notify.reset(XACTOR_IDLE);
00305:        this.notify.indicate(XACTOR_BUSY);
00306:        this.notify.indicate(XACTOR_STARTED);
00307:    end
00308: endtask: wait_if_stopped
00309: 
00310: 
00311: task vmm_xactor::wait_if_stopped_or_empty(vmm_channel  chan,
00312:                                           int unsigned n_threads);
00313:    this.wait_if_stopped(n_threads); 
00314:    while (chan.level() == 0) begin
00315:        vmm_data data;
00316: 
00317:        // Indicate IDLE because we are going to block on the channel
00318:        this.notify.reset(XACTOR_BUSY);
00319:        this.notify.indicate(XACTOR_IDLE);
00320: 
00321:        chan.peek(data);
00322:        this.wait_if_stopped(n_threads);
00323:   end
00324: 
00325:   this.notify.reset(XACTOR_IDLE);
00326:   this.notify.indicate(XACTOR_BUSY);
00327: endtask: wait_if_stopped_or_empty
00328: 
00329: 
00330: function void vmm_xactor::prepend_callback(vmm_xactor_callbacks cb);
00331:    if (cb == null) begin
00332:       
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text("Attempting to prepend a NULL callback extension")); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00333:       return;
00334:    end
00335: 
00336:    foreach(this.callbacks[i]) begin
00337:       if (this.callbacks[i] == cb) begin
00338:          
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::WARNING_SEV)) begin 
     :       void'(this.log.text("Callback has already been registered")); 
     :       this.log.end_msg(); 
     :    end 
     : while(0);
00339:          return;
00340:       end
00341:    end
00342:    //Prepend new callback
00343:    this.callbacks.push_front(cb);
00344: endfunction: prepend_callback
00345: 
00346: 
00347: function void vmm_xactor::append_callback(vmm_xactor_callbacks cb);
00348:    if (cb == null) begin
00349:       
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text("Attempting to append a NULL callback extension")); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00350:       return;
00351:    end
00352: 
00353:    foreach(this.callbacks[i]) begin
00354:       if (this.callbacks[i] == cb) begin
00355:          
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::WARNING_SEV)) begin 
     :       void'(this.log.text("Callback has already been registered")); 
     :       this.log.end_msg(); 
     :    end 
     : while(0);
00356:          return;
00357:       end
00358:    end
00359:    //Append new callback
00360:    this.callbacks.push_back(cb);
00361: endfunction: append_callback
00362: 
00363: 
00364: function void vmm_xactor::unregister_callback(vmm_xactor_callbacks cb);
00365:    foreach(this.callbacks[i]) begin
00366:       if (this.callbacks[i] == cb) begin
00367:          // Unregister it
00368:          this.callbacks.delete(i);
00369:          return;
00370:       end
00371:    end
00372: 
00373:    
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::WARNING_SEV)) begin 
     :       void'(this.log.text("Callback was not registered")); 
     :       this.log.end_msg(); 
     :    end 
     : while(0);
00374: endfunction: unregister_callback
00375: 
00376: 
00377: 
00378: 
00379: