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_broadcast.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_broadcast::new(string name, 00024: string inst, 00025: vmm_channel source, 00026: bit use_references, 00027: int mode 00028: ); 00029: super.new(name, inst, -1 ); 00030: 00031: if (source == null) begin 00032: if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::FATAL_SEV)) begin 00033: this.log.text("Cannot create vmm_broadcast instance with a NULL source channel reference"); 00034: this.log.end_msg(); 00035: end 00036: end 00037: 00038: this.in_chan = source; 00039: this.log.is_above(this.in_chan.log); 00040: this.dflt_use_refs = use_references; 00041: this.mode = mode; 00042: 00043: this.n_out_chans = 0; 00044: endfunction : new 00045: 00046: 00047: task vmm_broadcast::broadcast_mode(bcast_mode_e mode); 00048: if (mode != AFAP && mode != ALAP) begin 00049: if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::FATAL_SEV)) begin 00050: this.log.text($psprintf("Invalid broadcast mode %0d", mode)); 00051: this.log.end_msg(); 00052: end 00053: return; 00054: end 00055: 00056: this.mode = mode; 00057: // This MAY create the opportunity for a new broadcast cycle... 00058: -> this.new_cycle; 00059: endtask : broadcast_mode 00060: 00061: 00062: function int vmm_broadcast::new_output(vmm_channel channel, 00063: logic use_references); 00064: int chan_id = this.n_out_chans++; 00065: 00066: 00067: this.out_chans.push_back(channel); 00068: this.is_on.push_back(1); 00069: this.use_refs.push_back((use_references === 1'bx) ? 00070: this.dflt_use_refs : use_references); 00071: 00072: 00073: // Trigger a new broadcasting cycle whenever the channel becomes 00074: // empty while it is ON 00075: fork 00076: while (1) begin 00077: // A new (presumably empty) channel is added creates 00078: // a broadcast opportunity 00079: if (this.is_on[chan_id]) -> this.new_cycle; 00080: channel.notify.wait_for(vmm_channel::GOT); 00081: end 00082: join_none 00083: 00084: new_output = chan_id; 00085: endfunction : new_output 00086: 00087: 00088: function void vmm_broadcast::bcast_on(int unsigned output_id); 00089: this.bcast_on_off(output_id, 1); 00090: endfunction: bcast_on 00091: 00092: 00093: function void vmm_broadcast::bcast_off(int unsigned output_id); 00094: this.bcast_on_off(output_id, 0); 00095: endfunction: bcast_off 00096: 00097: 00098: function void vmm_broadcast::bcast_on_off(int channel_id, 00099: int on_off); 00100: if (channel_id < 0 || channel_id >= this.n_out_chans) begin 00101: if (this.log.start_msg(vmm_log::FAILURE_TYP)) begin 00102: string txt; 00103: $sformat(txt, "Invalid output channel ID %0d", channel_id); 00104: this.log.text(txt); 00105: this.log.end_msg(); 00106: end 00107: return; 00108: end 00109: 00110: this.is_on[channel_id] = on_off; 00111: 00112: // If a non-full channel is turned back on, this triggers a 00113: // new broadcasting cycle 00114: if (on_off && !this.out_chans[channel_id].is_full()) begin 00115: -> this.new_cycle; 00116: end 00117: 00118: // If a full channel is turned off, this triggers a 00119: // new broadcasting cycle 00120: if (!on_off && this.out_chans[channel_id].is_full()) begin 00121: -> this.new_cycle; 00122: end 00123: 00124: // Flush a channel that has been turned off 00125: if (!on_off) begin 00126: this.out_chans[channel_id].flush(); 00127: end 00128: endfunction: bcast_on_off 00129: 00130: 00131: task vmm_broadcast::bcast_to_output(int channel_id, 00132: int on_off); 00133: this.bcast_on_off(channel_id, on_off); 00134: endtask : bcast_to_output 00135: 00136: 00137: function bit vmm_broadcast::add_to_output(int unsigned decision_id, 00138: int unsigned output_id, 00139: vmm_channel channel, 00140: vmm_data obj); 00141: add_to_output = 1; 00142: endfunction : add_to_output 00143: 00144: 00145: function void vmm_broadcast::start_xactor(); 00146: super.start_xactor(); 00147: endfunction : start_xactor 00148: 00149: 00150: function void vmm_broadcast::stop_xactor(); 00151: super.stop_xactor(); 00152: endfunction : stop_xactor 00153: 00154: 00155: function void vmm_broadcast::reset_xactor(vmm_xactor::reset_e rst_typ); 00156: super.reset_xactor(rst_typ); 00157: 00158: this.in_chan.flush(); 00159: foreach (out_chans[i]) begin 00160: this.out_chans[i].flush(); 00161: end 00162: endfunction : reset_xactor 00163: 00164: 00165: task vmm_broadcast::main(); 00166: fork 00167: super.main(); 00168: this.broadcast(); 00169: this.sink_if_outs(); 00170: join_none 00171: endtask : main 00172: 00173: 00174: task vmm_broadcast::broadcast(); 00175: bit run_once = 1; 00176: 00177: while (1) begin 00178: int decision_id = 0; 00179: int i; 00180: int go; 00181: 00182: vmm_data data, cpy; 00183: vmm_data obj; 00184: 00185: if (this.log.start_msg(vmm_log::INTERNAL_TYP, vmm_log::TRACE_SEV)) begin 00186: this.log.text("Waiting for next broadcasting cycle..."); 00187: this.log.end_msg(); 00188: end 00189: if (!run_once) @ this.new_cycle; 00190: run_once = 0; 00191: this.wait_if_stopped(); 00192: 00193: // OK to broadcast? 00194: case (this.mode) 00195: 00196: AFAP: begin 00197: // OK to broadcast if just one active output channel 00198: // is not full 00199: int i; 00200: 00201: go = 0; 00202: for (i = 0; i < this.n_out_chans; i++) begin 00203: if (this.is_on[i] && !this.out_chans[i].is_full()) begin 00204: go = 1; 00205: break; 00206: end 00207: end 00208: end 00209: 00210: ALAP: begin 00211: // OK to broadcast only if ALL active output channel 00212: // are not full 00213: int i; 00214: 00215: go = 1; 00216: for (i = 0; i < this.n_out_chans; i++) begin 00217: if (this.is_on[i] && this.out_chans[i].is_full()) begin 00218: go = 0; 00219: break; 00220: end 00221: end 00222: end 00223: 00224: default: begin 00225: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.log.text($psprintf("Internal Error: Invalid broadcasting mode %0d!", this.mode))); : this.log.end_msg(); : end : while (0); 00226: continue; 00227: end 00228: endcase 00229: // No go! 00230: if (!go) continue; 00231: 00232: this.wait_if_stopped(); 00233: this.in_chan.get(data); 00234: this.wait_if_stopped(); 00235: 00246: 00247: for (i = 0; i < this.n_out_chans; i++) begin 00248: if (this.is_on[i]) begin 00249: 00250: // Copy or reference? 00251: if (this.use_refs[i]) begin 00252: obj = data; 00253: end 00254: else begin 00255: // Minimize the number of copies made 00256: if (cpy == null) cpy = data.copy(); 00257: obj = cpy; 00258: end 00259: 00260: if (this.add_to_output(decision_id++, i, this.out_chans[i], obj)) begin 00261: this.out_chans[i].sneak(obj); 00275: // Mark the copy as having been used. 00276: if (!this.use_refs[i]) cpy = null; 00277: end 00278: end 00279: end 00280: end 00281: endtask : broadcast 00282: 00283: 00284: task vmm_broadcast::sink_if_outs(); 00285: bit sink; 00286: vmm_data unused_data; 00287: 00288: vmm_data temp_obj; 00289: // Sink the data from the source channel 00290: // if there are no active output channels 00291: while (1) begin 00292: int i; 00293: 00294: // Wait for something to be in the source channel 00295: vmm_data peeked; 00296: this.in_chan.peek(peeked); 00297: 00298: // Can it go anywhere?? 00299: sink = 1; 00300: for (i = 0; i < this.n_out_chans; i++) begin 00301: if (this.is_on[i]) begin 00302: sink = 0; 00303: break; 00304: end 00305: end 00306: 00307: // Sink it if there is nowhere to go and it has not 00308: // been removed by some other thread. 00309: this.in_chan.peek( temp_obj); 00310: if (sink && this.in_chan.level() > 0 && 00311: temp_obj == peeked ) begin 00312: this.in_chan.get( unused_data); 00313: end 00314: 00315: if (in_chan.level() > 0) begin 00316: in_chan.notify.wait_for(vmm_channel::GOT); 00317: end 00318: end 00319: endtask : sink_if_outs