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_scheduler.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_scheduler::new(string name, 00024: string inst, 00025: vmm_channel destination, 00026: int instance_id 00027: ); 00028: super.new(name, inst, instance_id ); 00029: 00030: if (destination == null) begin 00031: if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::FATAL_SEV)) begin 00032: this.log.text("Cannot create vmm_scheduler instance with a NULL destination channel reference"); 00033: this.log.end_msg(); 00034: end 00035: return; 00036: end 00037: this.out_chan = destination; 00038: this.log.is_above(this.out_chan.log); 00039: 00040: this.randomized_sched = new; 00041: 00042: this.instance_id = instance_id; 00043: this.election_count = 0; 00044: endfunction : new 00045: 00046: 00047: function int vmm_scheduler::new_source(vmm_channel channel); 00048: if (channel == null) begin 00049: if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::WARNING_SEV)) begin 00050: this.log.text("Attempting to add a NULL source channel"); 00051: this.log.end_msg(); 00052: end 00053: return -1; 00054: end 00055: 00056: new_source = this.sources.size(); 00057: 00058: this.sources.push_back(channel); 00059: this.is_on.push_back(1); 00060: if (channel.level() > 0) begin 00061: -> this.next_cycle; 00062: end 00063: 00064: // Watch for new additions to the newly added source 00065: // to potentially trigger new scheduling cycles 00066: fork 00067: while (1) begin 00068: // The input channel may have been filled 00069: // before the forked thread has had a chance 00070: // to wait on the PUT indication 00071: if (channel.level() > 0) begin 00072: -> this.next_cycle; 00073: end 00074: channel.notify.wait_for(vmm_channel::PUT); 00075: -> this.next_cycle; 00076: end 00077: join_none 00078: 00079: endfunction : new_source 00080: 00081: 00082: task vmm_scheduler::sched_from_input(int channel_id, 00083: int on_off); 00084: if (channel_id < 0 || channel_id >= this.sources.size()) begin 00085: if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::WARNING_SEV)) begin 00086: string msg; 00087: $sformat(msg, "Invalid source channel ID specified in vmm_scheduler::sched_from_input(): %0d", channel_id); 00088: this.log.text(msg); 00089: this.log.end_msg(); 00090: end 00091: return; 00092: end 00093: 00094: this.is_on[channel_id] = on_off; 00095: 00096: if (this.log.start_msg(vmm_log::INTERNAL_TYP, vmm_log::TRACE_SEV)) begin 00097: string msg; 00098: $sformat(msg, "Scheduling from channel #%0d turned %s", channel_id, 00099: (on_off) ? "ON" : "OFF"); 00100: this.log.text(msg); 00101: this.log.end_msg(); 00102: end 00103: 00104: if (on_off && this.sources[channel_id].level() > 0) begin 00105: -> this.next_cycle; 00106: end 00107: endtask : sched_from_input 00108: 00109: 00110: task vmm_scheduler::schedule(output vmm_data obj, 00111: input vmm_channel sources[$], 00112: input int unsigned input_ids[$]); 00113: int id; 00114: 00115: this.randomized_sched.instance_id = this.instance_id; 00116: this.randomized_sched.election_id = this.election_count++; 00117: this.randomized_sched.n_sources = sources.size(); 00118: this.randomized_sched.sources = sources; 00119: this.randomized_sched.ids = input_ids; 00120: 00121: // Round-robin scheduler 00122: this.randomized_sched.next_idx = 0; 00123: if (this.randomized_sched.id_history.size() > 0) begin 00124: int last_id; 00125: // Find the next ID that follows (numerically) the last one 00126: // that was picked or use the first ID in the list of IDs. 00127: // Note: IDs will be stored in increasing numerical values. 00128: last_id = this.randomized_sched.id_history[$]; 00129: foreach (input_ids[i]) begin 00130: if (input_ids[i] > last_id) begin 00131: this.randomized_sched.next_idx = i; 00132: break; 00133: end 00134: end 00135: end 00136: 00137: obj = null; 00138: if (!this.randomized_sched.randomize()) begin 00139: if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::FATAL_SEV)) begin 00140: this.log.text("Unable to randomize vmm_scheduler::randomized_sched"); 00141: this.log.end_msg(); 00142: end 00143: return; 00144: end 00145: if (this.randomized_sched.source_idx < 0) return; 00146: 00147: if (this.randomized_sched.source_idx >= input_ids.size()) begin 00148: if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::FATAL_SEV)) begin 00149: this.log.text("vmm_scheduler::randomized_sched randomized to an invalid choice"); 00150: this.log.end_msg(); 00151: end 00152: return; 00153: end 00154: 00155: id = input_ids[this.randomized_sched.source_idx]; 00156: 00157: if (this.log.start_msg(vmm_log::INTERNAL_TYP, vmm_log::TRACE_SEV)) begin 00158: string msg; 00159: $sformat(msg, "Scheduled data from source #%0d, offset %0d", 00160: id, this.randomized_sched.obj_offset); 00161: this.log.text(msg); 00162: this.log.end_msg(); 00163: end 00164: 00165: begin 00166: vmm_channel src = this.sources[id]; 00167: if (src == null || src.level() == 0 || 00168: src.level() <= this.randomized_sched.obj_offset) begin 00169: if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::FATAL_SEV)) begin 00170: this.log.text("vmm_scheduler::randomized_sched randomized to an invalid source"); 00171: this.log.end_msg(); 00172: end 00173: return; 00174: end 00175: this.get_object(obj, src, id, this.randomized_sched.obj_offset); 00176: end 00177: 00178: this.randomized_sched.id_history.push_back(id); 00179: this.randomized_sched.obj_history.push_back(obj); 00180: if (this.randomized_sched.id_history.size() > 10) begin 00181: this.randomized_sched.id_history.pop_front(); 00182: this.randomized_sched.obj_history.pop_front(); 00183: end 00184: endtask : schedule 00185: 00186: 00187: task vmm_scheduler::get_object(output vmm_data obj, 00188: input vmm_channel source, 00189: input int unsigned input_id, 00190: input int offset); 00191: obj = null; 00192: 00193: if (source == null) begin 00194: if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::FATAL_SEV)) begin 00195: this.log.text("vmm_scheduler::get_object called with invalid source"); 00196: this.log.end_msg(); 00197: end 00198: return; 00199: end 00200: 00201: if (offset >= source.level()) begin 00202: if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::FATAL_SEV)) begin 00203: this.log.text("vmm_scheduler::get_object called with invalid offset"); 00204: this.log.end_msg(); 00205: end 00206: return; 00207: end 00208: 00209: source.get( obj, offset); 00210: endtask : get_object 00211: 00212: 00213: function void vmm_scheduler::start_xactor(); 00214: super.start_xactor(); 00215: // This MAY cause a new scheduling cycle 00216: -> this.next_cycle; 00217: endfunction : start_xactor 00218: 00219: 00220: function void vmm_scheduler::stop_xactor(); 00221: super.stop_xactor(); 00222: endfunction : stop_xactor 00223: 00224: 00225: function void vmm_scheduler::reset_xactor(vmm_xactor::reset_e rst_typ); 00226: super.reset_xactor(rst_typ); 00227: 00228: this.out_chan.flush(); 00229: foreach (sources[i]) begin 00230: this.sources[i].flush(); 00231: end 00232: 00233: this.instance_id = instance_id; 00234: this.election_count = 0; 00235: 00236: if (rst_typ == HARD_RST ) begin 00237: this.randomized_sched = new; 00238: end 00239: endfunction 00240: 00241: 00242: task vmm_scheduler::main(); 00243: fork 00244: super.main(); 00245: this.schedule_cycle(); 00246: join_none 00247: endtask 00248: 00249: 00250: task vmm_scheduler::schedule_cycle(); 00251: vmm_data data; 00252: vmm_channel srcs[$]; 00253: int unsigned ids[$]; 00254: 00255: while (1) begin 00262: // Works in VCS2008.03 00263: srcs = '{}; 00264: ids = '{}; 00266: 00267: super.wait_if_stopped(); 00268: 00269: // Identify all non-empty, active sources 00270: foreach (this.sources[i]) begin 00271: if (this.is_on[i] && this.sources[i] != null && 00272: this.sources[i].level() > 0) begin 00273: srcs.push_back(this.sources[i]); 00274: ids.push_back(i); 00275: end 00276: end 00277: if (srcs.size() == 0) data = null; 00278: else this.schedule(data, srcs, ids); 00279: 00280: if (data == null) begin 00281: // Delay the next scheduling cycle until 00282: // A new channel is added, new data is put into 00283: // a channel, a channel is turned on or the scheduler 00284: // is restarted 00285: : do : if (this.log.start_msg(vmm_log::DEBUG_TYP, vmm_log::TRACE_SEV)) begin : void'(this.log.text("Waiting for next scheduling cycle...")); : this.log.end_msg(); : end : while (0); 00286: @ ( this.next_cycle); 00287: continue; 00288: end 00289: this.out_chan.put(data); 00290: end 00291: endtask 00292: