VMM - (expanded) std_lib/vmm_notify.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_notify.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: 
00026: class vmm_notification_config;
00027:    event      the_event;	
00028:    bit        the_event_bit; //for ON_OFF_TRIGGERING (1:ON, 0:OFF)
00029:    time       stamp;
00030:    int        n_waiting_for;
00031:    event      reset;
00032:    event      abort;
00033:    vmm_notification watch;
00034:    int unsigned     trig_mode;
00035:    vmm_data         status;
00036:    vmm_notify_callbacks cbs[$];
00040: endclass
00041: 
00042: 
00043: function vmm_notify::new(vmm_log log);
00047: 
00048:    this.log = log;
00049: endfunction
00050: 
00051: function void vmm_notify::display(string prefix);
00052:    $write(this.psdisplay(prefix), "\n");
00053: endfunction
00054: 
00055: function string vmm_notify::psdisplay(string prefix);
00056:    int i, ok;
00057:    $sformat(psdisplay, "%sConfigured%s: [",
00058:             prefix, (log == null) ? "" : $psprintf(" in %s(%s)",
00059:                                                        log.get_name(),
00060:                                                        log.get_instance()));
00061:    for (ok = this.configs.first(i); 
00062:         ok;
00063:         ok = this.configs.next(i)) begin
00064:       $sformat(psdisplay, "%0s %0d", psdisplay, i);
00065:    end
00066:    psdisplay = {psdisplay, "]"};
00067: endfunction: psdisplay
00068: 
00069:    
00070: function vmm_notify vmm_notify::copy(vmm_notify to);
00071:    int i, ok;
00072: 
00073:    if (to == null) to = new(this.log);
00074: 
00075:    to.last_notification_id = this.last_notification_id;
00076:    for (ok = this.configs.first(i); ok;
00077:         ok = this.configs.next(i)) begin
00078: 
00079:       vmm_notification_config cfg = new;
00080: 
00081:       cfg.trig_mode     = this.configs[i].trig_mode;
00082:       cfg.stamp         = 0;
00083:       cfg.status        = null;
00084:       cfg.n_waiting_for = 0;
00085:       cfg.watch         = null;
00086:       to.configs[i] = cfg;
00087:    end
00088: 
00089:    return to;
00090: endfunction : copy
00091: 
00092:    
00093: function int vmm_notify::configure(int notification_id,
00094:      			           sync_e sync);
00095: 
00096:    // Warn if an event is being re-configured
00097:    if (this.configs.exists(notification_id))
00098:    begin
00099:       if (log == null) begin
00100:          $write("vmm_notify::WARNING: Reconfiguring notification #%0d...\n",
00101:                 notification_id);
00102:       end
00103:       else if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::WARNING_SEV))
00104:       begin
00105:          string txt;
00106:          $sformat(txt, "Reconfiguring notification #%0d...", notification_id);
00107:          void'(this.log.text(txt));
00108:          this.log.end_msg();
00109:       end
00110:    end
00111:    else if (notification_id > 1_000_000)
00112:    begin
00113:       // New notification ID > 1,000,000 are reserved
00114:       if (log == null) begin
00115:          $write("vmm_notify::FATAL: Notification notification IDs > 1,000,000 are reserved\n");
00116:          $finish();
00117:       end
00118:       else if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::FATAL_SEV))
00119:       begin
00120:          void'(this.log.text("Notification notification IDs > 1,000,000 are reserved"));
00121:          this.log.end_msg();
00122:       end
00123:       return -1;
00124:    end
00125: 
00126:    // Automatically generate a unique notification ID if notification ID
00127:    // is not positive.
00128:    if (notification_id < 0)
00129:    begin
00130:       last_notification_id++;
00131:       notification_id  = last_notification_id;
00132:    end
00133:    configure = notification_id;
00134: 
00146: 
00147:    begin
00148:       vmm_notification_config cfg = new;
00149: 
00150:       cfg.trig_mode     = sync;
00151:       cfg.stamp         = 0;
00152:       cfg.status        = null;
00153:       cfg.n_waiting_for = 0;
00154:       cfg.the_event_bit = 0; 
00155: 
00156:       this.configs[notification_id] = cfg;
00157:    end
00158: endfunction: configure   
00159: 
00160:    
00161: function int vmm_notify::is_configured(int notification_id);
00162:    if (!this.configs.exists(notification_id)) return 0;
00163: 
00164:    is_configured = this.configs[notification_id].trig_mode;
00165: endfunction: is_configured
00166: 
00167: 
00168: function bit vmm_notify::is_on(int notification_id);
00169:    vmm_notification_config cfg;
00170:        
00171:    if (!this.configs.exists(notification_id))
00172:    begin
00173:       if (this.log == null) begin
00174:          $write("vmm_notify::FATAL: Checking undefined notification #%0d\n",
00175:                 notification_id);
00176:          $finish();
00177:       end
00178:       else if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::FATAL_SEV))
00179:       begin
00180:          string txt;
00181:          $sformat(txt, "Checking undefined notification #%0d", notification_id);
00182:          void'(this.log.text(txt));
00183:          this.log.end_msg();
00184:       end
00185:       return 0;
00186:    end
00187: 
00188:    cfg = this.configs[notification_id];
00189:        
00190:    if (cfg.trig_mode != ON_OFF) begin
00191:       if (this.log == null) begin
00192:          $write("vmm_notify::WARNING: Cannot check non-ON_OFF notification #%0d\n",
00193:                 notification_id);
00194:       end
00195:       else if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::WARNING_SEV)) begin
00196:          string txt;
00197:          $sformat(txt, "Cannot check non-ON_OFF notification #%0d", notification_id);
00198:          void'(this.log.text(txt));
00199:          this.log.end_msg();
00200:       end
00201:       return 0;
00202:    end
00203: 
00204:    is_on = cfg.the_event_bit;
00205: endfunction: is_on
00206: 
00207:    
00208: task vmm_notify::wait_for(int notification_id);
00209:    vmm_notification_config cfg;
00210:        
00211:    if (!this.configs.exists(notification_id))
00212:    begin
00213:       if (this.log == null) begin
00214:          $write("vmm_notify::FATAL Waiting for undefined notification #%0d\n",
00215:                 notification_id);
00216:          $finish();
00217:       end
00218:       else if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::FATAL_SEV))
00219:       begin
00220:          string txt;
00221:          $sformat(txt, "Waiting for undefined notification #%0d", notification_id);
00222:          void'(this.log.text(txt));
00223:          this.log.end_msg();
00224:       end
00225:    
00226:       return;
00227:    end
00228: 
00229:    cfg = this.configs[notification_id];
00230:        
00231:    cfg.n_waiting_for++;
00232:    case(cfg.trig_mode)
00233:       ON_OFF   : while (cfg.the_event_bit !== 1) begin
00234:                                  @(cfg.the_event);
00235:                               end
00236:       ONE_SHOT : @(cfg.the_event);
00237:       BLAST    : wait (cfg.the_event.triggered); 
00238:       default  : begin
00239:          if (this.log == null) begin
00240:             $write("Invalid notification type\n");
00241:          end else 
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::FATAL_SEV)) begin 
     :       void'(this.log.text("Invalid notification type")); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00242:       end
00243:    endcase
00244:    if (cfg.n_waiting_for > 0) cfg.n_waiting_for--;
00245: endtask: wait_for
00246: 
00247: 
00248: task vmm_notify::wait_for_off(int notification_id);
00249:    vmm_notification_config cfg;
00250:        
00251:    if (!this.configs.exists(notification_id))
00252:    begin
00253:       if (this.log == null) begin
00254:          $write("vmm_notify::FATAL: Waiting for undefined notification #%0d\n",
00255:                 notification_id);
00256:          $finish();
00257:       end
00258:       else if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::FATAL_SEV))
00259:       begin
00260:          string txt;
00261:          $sformat(txt, "Waiting for undefined notification #%0d", notification_id);
00262:          void'(this.log.text(txt));
00263:          this.log.end_msg();
00264:       end
00265:       return;
00266:    end
00267: 
00268:    cfg = this.configs[notification_id];
00269:        
00270:    cfg.n_waiting_for++;
00271:    case(cfg.trig_mode)
00272:       ON_OFF  : while (cfg.the_event_bit !== 0) begin
00273:                    @(cfg.the_event);
00274:                 end
00275:       default : begin
00276:          if (this.log == null) begin
00277:             $write("Cannot use vmm_notify::wait_for_off() on non-ON/OFF notification\n");
00278:          end else 
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::FATAL_SEV)) begin 
     :       void'(this.log.text("Cannot use vmm_notify::wait_for_off() on non-ON/OFF notification")); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00279:       end
00280:    endcase
00281:    if (cfg.n_waiting_for > 0) cfg.n_waiting_for--;
00282: endtask: wait_for_off
00283: 
00284: 
00285: function bit vmm_notify::is_waited_for(int notification_id);
00286:    vmm_notification_config cfg;
00287:        
00288:    if (!this.configs.exists(notification_id))
00289:    begin
00290:       if (this.log == null) begin
00291:          $write("vmm_notify::FATAL: is_waited_for() called for undefined notification #%0d\n",
00292:      	   notification_id);
00293:          $finish();
00294:       end
00295:       else if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::FATAL_SEV))
00296:       begin
00297:          string txt;
00298:          $sformat(txt, "vmm_notify::is_waited_for called for undefined notification #%0d",
00299:      	     notification_id);
00300:          void'(this.log.text(txt));
00301:          this.log.end_msg();
00302:       end
00303:      	 
00304:       return 0;
00305:    end
00306: 
00307:    cfg = this.configs[notification_id];
00308: 
00309:    is_waited_for = (cfg.n_waiting_for > 0);
00310: endfunction: is_waited_for
00311: 
00312:    
00313: function void vmm_notify::terminated(int notification_id);
00314:    vmm_notification_config cfg;
00315:        
00316:    if (!this.configs.exists(notification_id))
00317:    begin
00318:       if (this.log == null) begin
00319:          $write("vmm_notify::FATAL: terminated() called for undefined notification #%0d\n",
00320:      	   notification_id);
00321:          $finish();
00322:       end
00323:       else if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::FATAL_SEV))
00324:       begin
00325:          string txt;
00326:          $sformat(txt, "vmm_notify::terminated called for undefined notification #%0d",
00327:      	     notification_id);
00328:          void'(this.log.text(txt));
00329:          this.log.end_msg();
00330:       end
00331:       return;
00332:    end
00333: 
00334:    cfg = this.configs[notification_id];
00335: 
00336:    if (cfg.n_waiting_for > 0) cfg.n_waiting_for--;
00337: endfunction: terminated 
00338: 
00339: function vmm_data vmm_notify::status(int notification_id);
00340:    vmm_notification_config cfg;
00341:        
00342:    if (!this.configs.exists(notification_id))
00343:    begin
00344:       if (this.log == null) begin
00345:          $write("vmm_notify::FATAL: Requesting status for undefined notification #%0d\n",
00346:      	   notification_id);
00347:          $finish();
00348:       end
00349:       else if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::FATAL_SEV))
00350:       begin
00351:          string txt;
00352:          $sformat(txt, "Requesting status for undefined notification #%0d",
00353:      	     notification_id);
00354:          void'(this.log.text(txt));
00355:          this.log.end_msg();
00356:       end
00357:       return null;
00358:    end
00359: 
00360:    cfg = this.configs[notification_id];
00361:        
00362:    status = cfg.status;
00363: endfunction: status
00364: 
00365: function time vmm_notify::timestamp(int notification_id);
00366:    vmm_notification_config cfg;
00367:        
00368:    if (!this.configs.exists(notification_id))
00369:    begin
00370:       if (this.log == null) begin
00371:          $write("vmm_notify::FATAL: Requesting timestamp for undefined notification #%0d\n",
00372:      	   notification_id);
00373:          $finish();
00374:       end
00375:       else if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::FATAL_SEV))
00376:       begin
00377:          string txt;
00378:          $sformat(txt, "Requesting timestamp for undefined notification #%0d",
00379:      	     notification_id);
00380:          void'(this.log.text(txt));
00381:          this.log.end_msg();
00382:       end
00383:       return 0;
00384:    end
00385: 
00386:    cfg = this.configs[notification_id];
00387:        
00388:    timestamp = cfg.stamp;
00389: endfunction: timestamp
00390: 
00391: function void vmm_notify::indicate(int notification_id,
00392:                  		   vmm_data status);
00393:    vmm_notification_config cfg;
00394:        
00395:    if (!this.configs.exists(notification_id))
00396:    begin
00397:       if (this.log == null) begin
00398:          $write("vmm_notify::FATAL: Indicating undefined notification #%0d\n",
00399:      	   notification_id);
00400:          $finish();
00401:       end
00402:       else if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::FATAL_SEV))
00403:       begin
00404:          string txt;
00405:          $sformat(txt, "Indicating undefined notification #%0d",
00406:      	     notification_id);
00407:          void'(this.log.text(txt));
00408:          this.log.end_msg();
00409:       end
00410:       return;
00411:    end
00412: 
00413:    cfg = this.configs[notification_id];
00414: 
00415:    if (cfg.trig_mode == ON_OFF) cfg.the_event_bit = 1;
00416:    -> cfg.the_event;
00417:      	 
00418:    cfg.stamp  = $realtime();
00419:    cfg.status = status;
00420: 
00421:    foreach (cfg.cbs[i]) begin
00422:       cfg.cbs[i].indicated(status);
00423:    end
00424: 
00449: endfunction: indicate
00450: 
00451: 
00452: function void vmm_notify::set_notification(int          notification_id,
00453:  				              vmm_notification ntfy);
00454:    vmm_notification_config cfg;
00455:        
00456:    if (!this.configs.exists(notification_id))
00457:    begin
00458:       if (this.log == null) begin
00459:          $write("vmm_notify::FATAL: Setting notification on undefined notification #%0d\n",
00460:                 notification_id);
00461:          $finish();
00462:       end
00463:       else if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::FATAL_SEV))
00464:       begin
00465:          string txt;
00466:          $sformat(txt, "Setting notification on undefined notification #%0d", notification_id);
00467:          void'(this.log.text(txt));
00468:          this.log.end_msg();
00469:       end
00470:       return;
00471:    end
00472: 
00473:    cfg = this.configs[notification_id];
00474: 
00475:    // Was there an event before?
00476:    if (cfg.watch != null)
00477:    begin
00478:       // Terminate it
00479:       ->cfg.abort;
00480:    end
00481:    if (ntfy == null)
00482:    begin
00483:       cfg.watch = null;
00484:       return;
00485:    end
00486: 
00487:    // Watch for the specified event
00488:    cfg.watch = ntfy;
00489:    fork
00490:       begin
00491:          fork
00492:             while (1)
00493:             begin
00494:                fork
00495:           	  while (1)
00496:                   begin
00497:           	     vmm_data status;
00498:           	     ntfy.indicate(status);
00499:           	     this.indicate(notification_id, status);
00500:           	  end
00501:                   
00502:                   while (cfg.trig_mode == ON_OFF) // persistent?
00503:                   begin
00504:           	     ntfy.reset();
00505:           	     cfg.the_event_bit = 0;
00506:                      -> cfg.the_event;
00507:           	  end
00508:                join_none
00509:                   
00510:                @(cfg.reset);
00511:                disable fork;
00512:             end
00513:          join_none
00514:             
00515:          @(cfg.abort);
00516:          disable fork;
00517:       end
00518:    join_none
00519: endfunction: set_notification
00520: 
00521:    
00522: function vmm_notification vmm_notify::get_notification(int notification_id);
00523:    if (!this.configs.exists(notification_id))
00524:    begin
00525:       if (this.log == null) begin
00526:          $write("vmm_notify::FATAL: Requesting notification for undefined notification #%0d\n",
00527:      	   notification_id);
00528:          $finish();
00529:       end
00530:       else if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::FATAL_SEV))
00531:       begin
00532:          string txt;
00533:          $sformat(txt, "Requesting notification for undefined notification #%0d",
00534:      	     notification_id);
00535:          void'(this.log.text(txt));
00536:          this.log.end_msg();
00537:       end
00538:       return null;
00539:    end
00540: 
00541:    get_notification = this.configs[notification_id].watch;
00542: endfunction: get_notification
00543: 
00544: 
00545: function void vmm_notify::reset(int     notification_id,
00546:                                 reset_e rst_typ);
00547:    vmm_notification_config cfg;
00548:        
00549:    if (notification_id < 0)
00550:    begin
00551:       int i, ok;
00552: 
00553:       for (ok = this.configs.first(i); ok; ok = this.configs.next(i))
00554:       begin
00555:          cfg = this.configs[i];
00556:      		
00557:          if (cfg.trig_mode == ON_OFF) begin
00558:             cfg.the_event_bit = 0;
00559:             ->cfg.the_event;
00560:          end
00561: 
00562:          if (cfg.watch != null)
00563:          begin
00564:             ->cfg.reset;
00565:             if (rst_typ == HARD)
00566:             begin
00567:      	  ->cfg.abort;
00568:      	  cfg.watch = null;
00569:             end
00570:          end
00571: 
00572:          if (rst_typ == HARD)
00573:          begin
00574:             cfg.stamp  = 0;
00575:             cfg.status = null;
00576:             cfg.n_waiting_for = 0;
00577:          end
00578:       end
00579:       return;
00580:    end
00581: 
00582:    if (!this.configs.exists(notification_id))
00583:    begin
00584:       if (this.log == null) begin
00585:          $write("vmm_notify::FATAL: Reseting undefined notification #%0d\n",
00586:                 notification_id);
00587:          $finish();
00588:       end
00589:       else if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::FATAL_SEV))
00590:       begin
00591:          string txt;
00592:          $sformat(txt, "Reseting undefined notification #%0d", notification_id);
00593:          void'(this.log.text(txt));
00594:          this.log.end_msg();
00595:       end
00596:       return;
00597:    end
00598: 
00599:    cfg = this.configs[notification_id];
00600:    ->cfg.the_event;
00601:    cfg.the_event_bit = 0;
00602:    if (cfg.watch != null)
00603:    begin
00604:       ->cfg.reset;
00605:       if (rst_typ == HARD)
00606:       begin
00607:          ->cfg.abort;
00608:          cfg.watch = null;
00609:       end
00610:    end
00611: 
00612:    if (rst_typ == HARD)
00613:    begin
00614:       cfg.stamp = 0;
00615:       cfg.status = null;
00616:       cfg.n_waiting_for = 0;
00617:    end
00618: endfunction: reset
00619: 
00620: 
00621: function void vmm_notify::append_callback(int                  notification_id,
00622:                                           vmm_notify_callbacks cbs);
00623:    if (!this.configs.exists(notification_id))
00624:    begin
00625:       if (log == null) begin
00626:          $write("vmm_notify::ERROR: Unknown notification #%0d to append callback to.\n",
00627:                 notification_id);
00628:       end
00629:       else if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV))
00630:       begin
00631:          string txt;
00632:          $sformat(txt, "Unkown notification #%0d to append callback to.",
00633:                   notification_id);
00634:          this.log.text(txt);
00635:          this.log.end_msg();
00636:       end
00637:       return;
00638:    end
00639: 
00640:    // Append new callback
00641:    this.configs[notification_id].cbs.push_back(cbs);
00642: 
00643: endfunction: append_callback
00644: 
00645: 
00646: function void vmm_notify::unregister_callback(int                  notification_id,
00647:                                               vmm_notify_callbacks cbs);
00648:    if (!this.configs.exists(notification_id))
00649:    begin
00650:       if (log == null) begin
00651:          $write("vmm_notify::ERROR: Unknown notification #%0d to remove callback from.\n",
00652:                 notification_id);
00653:       end
00654:       else if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV))
00655:       begin
00656:          string txt;
00657:          $sformat(txt, "Unkown notification #%0d to remove callback from.",
00658:                   notification_id);
00659:          this.log.text(txt);
00660:          this.log.end_msg();
00661:       end
00662:       return;
00663:    end
00664: 
00665:    begin
00666:       vmm_notification_config cfg = this.configs[notification_id];
00667:       foreach(cfg.cbs[i]) begin
00668:          if (cfg.cbs[i] == cbs) begin
00669:             // Unregister it
00670:             cfg.cbs.delete(i);
00671:             return;
00672:          end
00673:       end
00674:    end
00675: 
00676:    if (log == null) begin
00677:       $write("vmm_notify::WARNING: Callback was not registered with notification #%0d.\n",
00678:              notification_id);
00679:    end
00680:    else if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::WARNING_SEV))
00681:    begin
00682:       string txt;
00683:       $sformat(txt, "Callback was not registered with notification #%0d.",
00684:                notification_id);
00685:       this.log.text(txt);
00686:       this.log.end_msg();
00687:    end
00688: endfunction: unregister_callback
00689: 
00690: 
00691:   
00692: 
00693: 
00694: