ovm_scenario_controller.svh

Go to the documentation of this file.
00001 //----------------------------------------------------------------------
00002 //   Copyright 2007-2008 Mentor Graphics Corporation
00003 //   Copyright 2007-2008 Cadence Design Systems, 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 typedef enum {TYPE_REQ, TYPE_LOCK} REQ_TYPE;
00022 typedef enum {FIFO, WEIGHTED, RANDOM} ARBITRATION_TYPE;
00023 
00024 typedef class ovm_scenario_base;
00025 typedef class ovm_scenario_driver_base;
00026 
00027 class ovm_scenario_controller_base extends ovm_threaded_component;
00028 
00029   protected REQ_TYPE            arb_req_q[$];
00030   protected ovm_scenario_base  arb_scen_q[$];
00031   protected ovm_scenario_base  lock_list[$];
00032   local     ovm_scenario_controller_base m_push_if;
00033 
00034 // Weighted Priority
00035   local ARBITRATION_TYPE   arbitration = FIFO;
00036 
00038 
00039 function new (string name, ovm_component parent, ovm_scenario_controller_base push_if = null);
00040     super.new(name, parent);
00041     m_push_if = push_if;
00042 endfunction // new
00043 
00045 //
00046 // Local functions
00047 //
00049 
00050 local function string display_queues();
00051     string s;
00052 
00053     $sformat(s, "  -- arb i/type/id: ");
00054     foreach (arb_scen_q[i]) begin
00055       $sformat(s, "%s %0d/%s/%0d ", s, i, arb_req_q[i], arb_scen_q[i].get_id());
00056     end
00057     $sformat(s, "%s\n  -- lock i/id: ", s);
00058     foreach (lock_list[i]) begin
00059       $sformat(s, "%s %0d/%0d ", s, i, lock_list[i].get_id());
00060     end
00061     return(s);
00062 endfunction
00063 
00064 
00066 //
00067 // arb_lock_grant()
00068 //    Find all queued lock requests and grant them if
00069 //    possible
00071 
00072 local function void arb_lock_grant();
00073     int i, temp;
00074     
00075     for (i = 0; i < arb_scen_q.size(); i++) begin
00076 
00077       // If this is a lock request, and the lock is available,
00078       // then grant the lock
00079 
00080       temp = 0;
00081       if (i < arb_scen_q.size()) begin
00082    if (arb_req_q[i] == TYPE_LOCK) begin
00083      temp = is_blocked(arb_scen_q[i]) == 0;
00084    end
00085       end
00086       
00087       
00088       while (temp) begin
00089         lock_list.push_back(arb_scen_q[i]);
00090         arb_scen_q[i].grant(null);
00091         arb_req_q.delete(i);
00092         arb_scen_q.delete(i);
00093    
00094    temp = 0;
00095    if (i < arb_scen_q.size())
00096      if (arb_req_q[i] == TYPE_LOCK)
00097        temp = is_blocked(arb_scen_q[i]) == 0;
00098       end
00099     end // for (i = 0; i < arb_scen_q.size(); i++)
00100 endfunction // arb_lock_grant
00101 
00103 //
00104 // choose_next_request
00105 //    When a driver requests an operation, this funciton
00106 //    must find the next available, unlocked, relevant scenario
00108 
00109 local function int choose_next_request();
00110     int i, temp;
00111     int avail_scen_count;
00112     int sum_priority_val;
00113     int avail_scenarios[$];
00114 
00115     avail_scen_count = 0;
00116     for (i = 0; i < arb_scen_q.size(); i++) begin
00117       // If this is a lock request, and the lock is available,
00118       // then grant the lock
00119       
00120       temp = 0;
00121       if (i < arb_scen_q.size()) begin
00122    if (arb_req_q[i] == TYPE_LOCK) begin
00123      temp = is_blocked(arb_scen_q[i]) == 0;
00124    end
00125       end
00126       while (temp) begin
00127         lock_list.push_back(arb_scen_q[i]);
00128         arb_scen_q[i].grant(null);
00129         arb_req_q.delete(i);
00130         arb_scen_q.delete(i);
00131 
00132    temp = 0;
00133    if (i < arb_scen_q.size()) begin
00134      if (arb_req_q[i] == TYPE_LOCK) begin
00135        temp = is_blocked(arb_scen_q[i]) == 0;
00136      end
00137    end
00138       end
00139       
00140       // choose the first i that is ready and is a request
00141       if (i < arb_scen_q.size())
00142    if (arb_req_q[i] == TYPE_REQ)
00143           if (is_blocked(arb_scen_q[i]) == 0)
00144             if (arb_scen_q[i].is_relevant() == 1) begin
00145          if (arbitration == FIFO) return (i);
00146               else avail_scenarios.push_back(i);
00147        end
00148     end // for (i = 0; i < arb_scen_q.size(); i++)
00149     
00150     // Return immediately if there are 0 or 1 available scenarios
00151     if (arbitration == FIFO) return (-1);
00152     if (avail_scenarios.size() < 1)  return (-1);
00153     if (avail_scenarios.size() == 1) return (avail_scenarios[0]);
00154     
00155     // If any locks are in place, then the available queue must
00156     // be checked to see if a lock prevents any scenario from proceeding
00157     if (lock_list.size() > 0) begin
00158       for (i = 0; i < avail_scenarios.size(); i++) begin
00159    if (is_blocked(arb_scen_q[avail_scenarios[i]]) != 0) begin
00160      avail_scenarios.delete(i);
00161      i--;
00162    end
00163       end
00164       if (avail_scenarios.size() < 1) return (-1);
00165       if (avail_scenarios.size() == 1) return (avail_scenarios[0]);
00166     end
00167     
00169     //  Weighted Priority Distribution
00171     if (arbitration == WEIGHTED) begin
00172       sum_priority_val = 0;
00173       for (i = 0; i < avail_scenarios.size(); i++) begin
00174    sum_priority_val += arb_scen_q[avail_scenarios[i]].get_weighted_priority();
00175       end
00176       
00177       // Pick an available scenario based on weighted priorities of available scenarios
00178       temp = $urandom_range(sum_priority_val-1, 0);
00179       sum_priority_val = 0;
00180       for (i = 0; i < avail_scenarios.size(); i++) begin
00181    if ((arb_scen_q[avail_scenarios[i]].get_weighted_priority() + 
00182         sum_priority_val) > temp) begin
00183      return (avail_scenarios[i]);
00184    end
00185    sum_priority_val += arb_scen_q[avail_scenarios[i]].get_weighted_priority();
00186       end
00187     end // if (arbitration == WEIGHTED)
00188     
00190     //  Random Distribution
00192     if (arbitration == RANDOM) begin
00193       i = $urandom_range(avail_scenarios.size()-1, 0);
00194       return (avail_scenarios[i]);
00195       return avail_scenarios[i];
00196     end
00197     ovm_report_fatal("Scenario controller", "Internal error: Failed to choose scenario");
00198 endfunction 
00199 
00200 function void set_arbitration(ARBITRATION_TYPE val);
00201     arbitration = val;
00202 endfunction // void
00203 
00205 //
00206 // is_child
00207 //    Determine if a scenario is a child of a parent
00209 
00210 function bit is_child (ovm_scenario_base parent, ovm_scenario_base child);
00211     ovm_scenario_base scenario_ptr;
00212 
00213     scenario_ptr = child.get_parent_scenario();
00214     while (scenario_ptr != null) begin
00215       if (scenario_ptr.get_id() == (parent.get_id())) begin
00216         return (1);
00217       end
00218       scenario_ptr = scenario_ptr.get_parent_scenario();
00219     end
00220     return (0);
00221 endfunction // bit
00222 
00224 //
00225 // is_blocked
00226 //    Determine if a scenario is locked out
00228   
00229 function bit is_blocked(ovm_scenario_base scenario_ptr);
00230 
00231     if (scenario_ptr == null)
00232       ovm_report_fatal("ovm_scenario_controller", "is_blocked passed null scenario_ptr");
00233     
00234     if (m_push_if == null) begin
00235       foreach (lock_list[i]) begin
00236         if ((lock_list[i].get_id() != scenario_ptr.get_id()) &&
00237             (is_child(lock_list[i], scenario_ptr) == 0)) begin
00238           return (1);
00239         end
00240       end 
00241       return (0);
00242     end else begin
00243       return (m_push_if.is_blocked(scenario_ptr));
00244     end 
00245 endfunction // is_locked
00246 
00248 //
00249 // lock_req
00250 //    Called by a scenario to request a lock.  Puts
00251 //    the lock request onto the arbitration queue
00253   
00254 function void lock_req(ovm_scenario_base scenario_ptr);
00255     if (scenario_ptr == null)
00256       ovm_report_fatal("ovm_scenario_controller", "lock_req passed null scenario_ptr");
00257 
00258     if (m_push_if == null) begin
00259       arb_scen_q.push_back(scenario_ptr);
00260       arb_req_q.push_back(TYPE_LOCK);
00261     end else begin
00262       m_push_if.lock_req(scenario_ptr);
00263     end
00264 endfunction    
00265     
00267 //
00268 // unlock_req
00269 //    Called by a scenario to request an unlock.  This
00270 //    will remove a lock for this scenario if it exists
00272   
00273 function void unlock_req(ovm_scenario_base scenario_ptr);
00274     if (scenario_ptr == null)
00275       ovm_report_fatal("ovm_scenario_controller", "unlock_req passed null scenario_ptr");
00276     if (m_push_if == null) begin
00277       foreach (lock_list[i]) begin
00278         if (lock_list[i].get_id() == scenario_ptr.get_id()) begin
00279           lock_list.delete(i);
00280           return;
00281         end
00282       end
00283     end else begin
00284       m_push_if.unlock_req(scenario_ptr);
00285     end 
00286 endfunction
00287 
00289 //
00290 // request
00291 //    Called by a scenario to request a ovm_transaction
00292 //    to be executed by the driver
00294   
00295 function void request(ovm_scenario_base scenario_ptr);
00296     if (scenario_ptr == null)
00297       ovm_report_fatal("ovm_scenario_controller", "request passed null scenario_ptr");
00298 
00299     if (m_push_if == null) begin
00300       arb_scen_q.push_back(scenario_ptr);
00301       arb_req_q.push_back(TYPE_REQ);
00302     end else begin
00303       m_push_if.request(scenario_ptr);
00304     end // else: !if(lock_list[i].get_id() == scenario_ptr.get_id())
00305 endfunction
00306 
00308 //
00309 // Driver request
00310 //    Called by a driver to request a ovm_transaction
00312   
00313 task driver_request (input ovm_scenario_driver_base driver_ptr, 
00314            output ovm_scenario_base chosen_scen, input bit non_blocking = 0 );
00315     ovm_scenario_base scenario_ptr;
00316     int select_num, req_size;
00317 
00318     if (driver_ptr == null)
00319       ovm_report_fatal("ovm_scenario_controller", "driver_request passed null driver ptr");
00320 
00321     #0; //Allow scenario requests in before arbitrating.  Needed for weighted distribution
00322     select_num = choose_next_request();
00323 
00324     // Non-blocking logic - if no item availabe, and a non-blocking
00325     // request was made, then return a null
00326     if ((select_num < 0) && (non_blocking == 1)) begin
00327       chosen_scen = null;
00328       return;
00329     end
00330     
00331     while (select_num < 0) begin
00332       // If we just granted a lock, allow the scenario
00333       // to put a request in the queue
00334       req_size = arb_scen_q.size();
00335       wait (arb_scen_q.size() != req_size);
00336       select_num = choose_next_request();
00337     end
00338 
00339     // If no scenario was chosen, then return null
00340     if (select_num < 0) begin
00341       chosen_scen = null;
00342       return;
00343     end
00344       
00345     scenario_ptr = arb_scen_q[select_num];
00346     arb_scen_q.delete(select_num);
00347     arb_req_q.delete(select_num);
00348     
00349     // return the driver pointer when granting the scenario
00350     scenario_ptr.grant(driver_ptr);
00351     // return the scenario pointer to the driver
00352     chosen_scen = scenario_ptr;
00353 endtask // driver_request
00354 
00355 virtual task run();
00356   return;
00357 endtask // run
00358 
00359 endclass
00360 
00361   
00362 class ovm_scenario_controller #(type REQ = ovm_transaction,
00363             type RSP = ovm_transaction) extends ovm_scenario_controller_base;
00364 
00365 // For driver ports to connect to the request_driver
00366 ovm_blocking_get_export #(REQ) get_req_export;
00367 ovm_blocking_put_export #(RSP) put_rsp_export;
00368 
00369 // For stimulus generators to connect to the stimulus scenario
00370 ovm_blocking_put_export #(REQ) put_req_export;
00371 
00372 request_driver #(REQ, RSP) req_driver;
00373 ovm_stimulus_scenario #(REQ) stimulus_scenario;
00374 
00375 function new (string name, ovm_component parent, ovm_scenario_controller_base push_if = null);
00376     super.new(name, parent, push_if);
00377     req_driver = new("nscenr_drv", this);
00378     req_driver.set_scenario_controller(this);
00379     stimulus_scenario = new("scenario_stim", this);
00380     get_req_export = new("reqdrv_req_export", this);
00381     put_rsp_export = new("reqdrv_rsp_export", this);
00382     put_req_export = new("stimscen_req_export", this);
00383 endfunction // new
00384 
00385 function void connect();
00386     get_req_export.connect(req_driver.get_req_export);
00387     put_rsp_export.connect(req_driver.put_rsp_export);
00388     put_req_export.connect(stimulus_scenario.put_req_export);
00389 endfunction
00390 
00391 task run();
00392     stimulus_scenario.start(this, null);
00393 endtask // run
00394   
00395 endclass
00396 

Intelligent Design Verification
Intelligent Design Verification
Project: OVM, Revision: 1.1.0
Copyright (c) 2008 Intelligent Design Verification.
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
A copy of the license is included here:
http://www.intelligentdv.com/licenses/fdl.txt
doxygen
Doxygen Version: 1.4.6
Mon Sep 29 14:20:12 2008
Find a documentation bug? Report bugs to: bugs.intelligentdv.com Project: DoxygenFilterSV