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_consensus.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: 00024: `define VMM_CONSENSUS__SV 00025: 00026: 00027: function vmm_consensus::new(string name, 00028: string inst); 00032: 00033: this.log = new(name, inst); 00034: 00035: this.n_dissenters = 0; 00036: this.n_forcing = 0; 00037: endfunction: new 00038: 00039: 00040: function vmm_voter vmm_consensus::register_voter(string name); 00041: vmm_voter voter = new(name, this); 00042: 00043: // Voters object by default 00044: this.n_dissenters++; 00045: 00046: this.voters.push_back(voter); 00047: 00048: return voter; 00049: endfunction: register_voter 00050: 00051: 00052: function void vmm_consensus::unregister_voter(vmm_voter voter); 00053: foreach (this.voters[i]) begin 00054: if (this.voters[i] == voter) begin 00055: if (!voter.get_vote()) voter.consent("Dead voter consents by default"); 00056: voter.kill_voter(); 00057: this.voters.delete(i); 00058: return; 00059: end 00060: end 00061: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.log.text({voter.get_name(), " is not a registered voter"})); : this.log.end_msg(); : end : while (0); 00062: endfunction: unregister_voter 00063: 00064: 00065: function void vmm_consensus::register_xactor(vmm_xactor xact); 00066: vmm_voter voter = this.register_voter({"Transactor ", xact.get_name(), 00067: "(", xact.get_instance(), ")"}); 00068: voter.xactor(xact); 00069: endfunction: register_xactor 00070: 00071: 00072: function void vmm_consensus::unregister_xactor(vmm_xactor xact); 00073: foreach (this.voters[i]) begin 00074: vmm_voter voter = this.voters[i]; 00075: if (voter.get_xactor() == xact) begin 00076: if (!voter.get_vote()) voter.consent("Dead voter consents by default"); 00077: voter.kill_voter(); 00078: this.voters.delete(i); 00079: return; 00080: end 00081: end 00083: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.log.text({"Transactor ", xact.get_name(), "(", : xact.get_instance(), ") is not a registered voter"})); : this.log.end_msg(); : end : while (0); 00084: endfunction: unregister_xactor 00085: 00086: 00087: function void vmm_consensus::register_channel(vmm_channel chan); 00088: vmm_voter voter = this.register_voter({"Channel ", 00089: chan.log.get_name(), "(", 00090: chan.log.get_instance(), ")"}); 00091: voter.channel(chan); 00092: endfunction: register_channel 00093: 00094: 00095: function void vmm_consensus::unregister_channel(vmm_channel chan); 00096: foreach (this.voters[i]) begin 00097: vmm_voter voter = this.voters[i]; 00098: if (voter.get_channel() == chan) begin 00099: if (!voter.get_vote()) voter.consent("Dead voter consents by default"); 00100: voter.kill_voter(); 00101: this.voters.delete(i); 00102: return; 00103: end 00104: end 00107: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.log.text({"Channel ", chan.log.get_name(), "(", : chan.log.get_instance(), : ") is not a registered voter"})); : this.log.end_msg(); : end : while (0); 00108: endfunction: unregister_channel 00109: 00110: 00111: function void vmm_consensus::register_notification(vmm_notify notify, 00112: int notification); 00113: 00114: vmm_voter voter; 00115: string name; 00116: int mode; 00117: 00118: if (notify == null) begin 00119: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.log.text("Cannot register NULL vmm_notify reference")); : this.log.end_msg(); : end : while (0); 00120: return; 00121: end 00122: 00123: mode = notify.is_configured(notification); 00124: if (!mode) begin 00125: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.log.text("Cannot register unconfigured notification")); : this.log.end_msg(); : end : while (0); 00126: return; 00127: end 00128: if (mode != vmm_notify::ON_OFF) begin 00129: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.log.text("Can only register ON_OFF notification")); : this.log.end_msg(); : end : while (0); 00130: return; 00131: end 00132: 00133: $sformat(name, "Notification #%0d %s(%s)", 00134: notification, notify.log.get_name(), 00135: notify.log.get_instance()); 00136: voter = this.register_voter(name); 00137: voter.notify(notify, notification, 1); 00138: endfunction: register_notification 00139: 00140: 00141: function void vmm_consensus::register_no_notification(vmm_notify notify, 00142: int notification); 00143: 00144: vmm_voter voter; 00145: string name; 00146: int mode; 00147: 00148: if (notify == null) begin 00149: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.log.text("Cannot register NULL vmm_notify reference")); : this.log.end_msg(); : end : while (0); 00150: return; 00151: end 00152: 00153: mode = notify.is_configured(notification); 00154: if (!mode) begin 00155: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.log.text("Cannot register unconfigured notification")); : this.log.end_msg(); : end : while (0); 00156: return; 00157: end 00158: if (mode != vmm_notify::ON_OFF) begin 00159: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.log.text("Can only register ON_OFF notification")); : this.log.end_msg(); : end : while (0); 00160: return; 00161: end 00162: 00163: $sformat(name, "Notification #%0d %s(%s)", 00164: notification, notify.log.get_name(), 00165: notify.log.get_instance()); 00166: voter = this.register_voter(name); 00167: voter.notify(notify, notification, 0); 00168: endfunction: register_no_notification 00169: 00170: 00171: function void vmm_consensus::unregister_notification(vmm_notify notify, 00172: int notification); 00173: foreach (this.voters[i]) begin 00174: vmm_voter voter = this.voters[i]; 00175: if (voter.get_notify() == notify && 00176: voter.get_notification() == notification) begin 00177: if (!voter.get_vote()) voter.consent("Dead voter consents by default"); 00178: voter.kill_voter(); 00179: this.voters.delete(i); 00180: return; 00181: end 00182: end 00183: begin 00184: string msg; 00185: $sformat(msg, "Notification #%0d %s(%s)", 00186: notification, notify.log.get_name(), 00187: notify.log.get_instance()); 00188: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.log.text(msg)); : this.log.end_msg(); : end : while (0); 00189: end 00190: endfunction: unregister_notification 00191: 00192: 00193: function void vmm_consensus::register_consensus(vmm_consensus vote, 00194: bit force_through); 00195: vmm_voter voter = this.register_voter({"Consensus ", 00196: vote.log.get_instance()}); 00197: voter.sub_consensus(vote, force_through); 00198: endfunction: register_consensus 00199: 00200: 00201: function void vmm_consensus::unregister_consensus(vmm_consensus vote); 00202: foreach (this.voters[i]) begin 00203: vmm_voter voter = this.voters[i]; 00204: if (voter.get_consensus() == vote) begin 00205: if (!voter.get_vote()) voter.consent("Dead voter consents by default"); 00206: voter.kill_voter(); 00207: this.voters.delete(i); 00208: return; 00209: end 00210: end 00212: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.log.text({"Consensus ", vote.log.get_instance(), : " is not a registered voter"})); : this.log.end_msg(); : end : while (0); 00213: endfunction: unregister_consensus 00214: 00215: 00216: task vmm_consensus::wait_for_consensus(); 00217: wait (this.n_forcing > 0 || this.n_dissenters == 0); 00218: endtask: wait_for_consensus 00219: 00220: 00221: task vmm_consensus::wait_for_no_consensus(); 00222: wait (this.n_forcing == 0 && this.n_dissenters != 0); 00223: endtask: wait_for_no_consensus 00224: 00225: 00226: function bit vmm_consensus::is_reached(); 00227: return this.n_forcing > 0 || this.n_dissenters == 0; 00228: endfunction: is_reached 00229: 00230: 00231: function bit vmm_consensus::is_forced(); 00232: return this.n_forcing > 0; 00233: endfunction: is_forced 00234: 00235: 00236: function string vmm_consensus::psdisplay(string prefix); 00237: $sformat(psdisplay, "%sConsensus %s(%s) is %0s", prefix, 00238: this.log.get_name(), this.log.get_instance(), 00239: (this.is_reached() ? (this.is_forced() ? "forced" : "reached") 00240: : "NOT reached")); 00241: if (this.voters.size() == 0) begin 00242: psdisplay = {psdisplay, " by default"}; 00243: end 00244: else begin 00245: foreach (this.voters[i]) begin 00246: vmm_consensus subvote; 00247: $sformat(psdisplay, "%s\n%s %s %0s because %s", psdisplay, prefix, 00248: this.voters[i].get_name(), 00249: (this.voters[i].get_vote() ? 00250: (this.voters[i].get_forced() ? "forces" : "consents") 00251: : "opposes"), 00252: this.voters[i].get_reason()); 00253: subvote = this.voters[i].get_consensus(); 00254: if (subvote != null) begin 00255: psdisplay = {psdisplay, "\n", subvote.psdisplay({prefix, " "})}; 00256: end 00257: end 00258: end 00259: endfunction: psdisplay 00260: 00261: 00262: function void vmm_consensus::yeas(ref string who[], 00263: ref string why[]); 00264: int n = 0; 00265: 00266: foreach (this.voters[i]) begin 00267: if (this.voters[i].get_vote()) n++; 00268: end 00269: 00270: who = new [n]; 00271: why = new [n]; 00272: 00273: n = 0; 00274: foreach (this.voters[i]) begin 00275: if (this.voters[i].get_vote()) begin 00276: who[n] = this.voters[i].get_name(); 00277: why[n] = this.voters[i].get_reason(); 00278: n++; 00279: end 00280: end 00281: endfunction: yeas 00282: 00283: 00284: function void vmm_consensus::nays(ref string who[], 00285: ref string why[]); 00286: int n = 0; 00287: 00288: foreach (this.voters[i]) begin 00289: if (!this.voters[i].get_vote()) n++; 00290: end 00291: 00292: who = new [n]; 00293: why = new [n]; 00294: 00295: n = 0; 00296: foreach (this.voters[i]) begin 00297: if (!this.voters[i].get_vote()) begin 00298: who[n] = this.voters[i].get_name(); 00299: why[n] = this.voters[i].get_reason(); 00300: n++; 00301: end 00302: end 00303: endfunction: nays 00304: 00305: 00306: function void vmm_consensus::forcing(ref string who[], 00307: ref string why[]); 00308: int n = 0; 00309: 00310: foreach (this.voters[i]) begin 00311: if (this.voters[i].get_vote() && 00312: this.voters[i].get_forced()) n++; 00313: end 00314: 00315: who = new [n]; 00316: why = new [n]; 00317: 00318: n = 0; 00319: foreach (this.voters[i]) begin 00320: if (this.voters[i].get_vote() && 00321: this.voters[i].get_forced()) begin 00322: who[n] = this.voters[i].get_name(); 00323: why[n] = this.voters[i].get_reason(); 00324: n++; 00325: end 00326: end 00327: endfunction: forcing 00328: 00329: 00330: function void vmm_consensus::XvoteX(bit was_agree, 00331: bit agree, 00332: bit was_forced, 00333: bit forced); 00334: if (agree && !was_agree) begin 00335: this.n_dissenters--; 00336: if (this.n_dissenters == 0) ->this.new_results; 00337: end 00338: else if (!agree && was_agree) begin 00339: if (this.n_dissenters == 0) ->this.new_results; 00340: this.n_dissenters++; 00341: end 00342: 00343: if (forced && !was_forced) begin 00344: if (this.n_forcing == 0) ->this.new_results; 00345: this.n_forcing++; 00346: end 00347: else if (!forced && was_forced) begin 00348: this.n_forcing--; 00349: if (this.n_forcing == 0) ->this.new_results; 00350: end 00351: 00352: endfunction: XvoteX 00353: 00354: 00355: function vmm_voter::new(string name, 00356: vmm_consensus vote); 00357: this.name = name; 00358: this.consensus = vote; 00359: 00360: this.vote = 0; 00361: this.is_forced = 0; 00362: this.why = "Opposes by default"; 00363: 00364: this.xactor_voter = null; 00365: this.channel_voter = null; 00366: this.sub_vote = null; 00367: endfunction: new 00368: 00369: 00370: function void vmm_voter::oppose(string why); 00371: if (this.consensus != null) begin 00372: this.consensus.XvoteX(this.vote, 0, this.is_forced, 0); 00373: end 00374: this.vote = 0; 00375: this.is_forced = 0; 00376: this.why = why; 00377: endfunction: oppose 00378: 00379: 00380: function void vmm_voter::consent(string why); 00381: if (this.consensus != null) begin 00382: this.consensus.XvoteX(this.vote, 1, this.is_forced, 0); 00383: end 00384: this.vote = 1; 00385: this.is_forced = 0; 00386: this.why = why; 00387: endfunction: consent 00388: 00389: 00390: function void vmm_voter::forced(string why); 00391: if (this.consensus != null) begin 00392: this.consensus.XvoteX(this.vote, 1, this.is_forced, 1); 00393: end 00394: this.vote = 1; 00395: this.is_forced = 1; 00396: this.why = why; 00397: endfunction: forced 00398: 00399: 00400: function string vmm_voter::get_name(); 00401: return this.name; 00402: endfunction: get_name 00403: 00404: 00405: function bit vmm_voter::get_vote(); 00406: return this.vote; 00407: endfunction: get_vote 00408: 00409: 00410: function bit vmm_voter::get_forced(); 00411: return this.is_forced; 00412: endfunction: get_forced 00413: 00414: 00415: function string vmm_voter::get_reason(); 00416: return this.why; 00417: endfunction: get_reason 00418: 00419: 00420: function void vmm_voter::xactor(vmm_xactor xact); 00421: this.xactor_voter = xact; 00422: if (xact.notify.is_on(vmm_xactor::XACTOR_BUSY)) begin 00423: this.oppose("Transactor is BUSY"); 00424: end 00425: else this.consent("Transactor is IDLE"); 00426: fork 00427: begin 00428: fork 00429: begin 00430: // The transactor might have become busy while 00431: // the forked thread was getting started... 00432: if (xact.notify.is_on(vmm_xactor::XACTOR_BUSY)) begin 00433: this.oppose("Transactor is BUSY"); 00434: end 00435: forever begin 00436: // Wait for transactor to be IDLE 00437: xact.notify.wait_for(vmm_xactor::XACTOR_IDLE); 00438: this.consent("Transactor is IDLE"); 00439: // Prevent an infinite loop 00440: if (xact.notify.is_on(vmm_xactor::XACTOR_BUSY)) begin 00442: : do : if (this.xactor_voter.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::FATAL_SEV)) begin : void'(this.xactor_voter.log.text("Transactor is indicating both IDLE and BUSY")); : this.xactor_voter.log.end_msg(); : end : while (0); 00443: end 00444: // Wait for transactor to be BUSY 00445: xact.notify.wait_for(vmm_xactor::XACTOR_BUSY); 00446: this.oppose("Transactor is BUSY"); 00447: // Prevent an infinite loop 00448: if (xact.notify.is_on(vmm_xactor::XACTOR_IDLE)) begin 00450: : do : if (this.xactor_voter.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::FATAL_SEV)) begin : void'(this.xactor_voter.log.text("Transactor is indicating both IDLE and BUSY")); : this.xactor_voter.log.end_msg(); : end : while (0); 00451: end 00452: end 00453: end 00454: join_none 00455: 00456: @(this.killme); 00457: disable fork; 00458: end 00459: join_none 00460: endfunction: xactor 00461: 00462: 00463: function void vmm_voter::channel(vmm_channel chan); 00464: this.channel_voter = chan; 00465: if (!chan.notify.is_on(vmm_channel::EMPTY)) begin 00466: this.oppose("Channel is not empty"); 00467: end 00468: else this.consent("Channel is empty"); 00469: fork 00470: begin 00471: fork 00472: forever begin 00473: // Wait for channel to be empty 00474: chan.notify.wait_for(vmm_channel::EMPTY); 00475: this.consent("Channel is empty"); 00476: // Wait for channel to be not empty 00477: chan.notify.wait_for_off(vmm_channel::EMPTY); 00478: this.oppose("Channel is not empty"); 00479: end 00480: join_none 00481: 00482: @(this.killme); 00483: disable fork; 00484: end 00485: join_none 00486: endfunction: channel 00487: 00488: 00489: function void vmm_voter::notify(vmm_notify ntfy, 00490: int notification, 00491: bit is_on); 00492: this.notify_voter = ntfy; 00493: if (is_on) begin 00494: if (!ntfy.is_on(notification)) begin 00495: this.oppose("Notification is not indicated"); 00496: end 00497: else this.consent("Notification is indicated"); 00498: end 00499: else begin 00500: if (ntfy.is_on(notification)) begin 00501: this.oppose("Notification is indicated"); 00502: end 00503: else this.consent("Notification is not indicated"); 00504: end 00505: fork 00506: begin 00507: fork 00508: if (is_on) forever begin 00509: // Wait for indication 00510: ntfy.wait_for(notification); 00511: this.consent("Notification is indicated"); 00512: // Wait for indication to be reset 00513: ntfy.wait_for_off(notification); 00514: this.oppose("Notification is not indicated"); 00515: end 00516: if (!is_on) forever begin 00517: // Wait for indication 00518: ntfy.wait_for_off(notification); 00519: this.consent("Notification is not indicated"); 00520: // Wait for indication to be reset 00521: ntfy.wait_for(notification); 00522: this.oppose("Notification is indicated"); 00523: end 00524: join_none 00525: 00526: @(this.killme); 00527: disable fork; 00528: end 00529: join_none 00530: endfunction: notify 00531: 00532: 00533: function void vmm_voter::sub_consensus(vmm_consensus vote, 00534: bit force_through); 00535: this.sub_vote = vote; 00536: if (!vote.is_reached()) begin 00537: this.oppose("Sub-consensus is not reached"); 00538: end 00539: else this.consent("Sub-consensus is reached"); 00540: 00541: fork 00542: begin 00543: fork 00544: forever begin 00545: if (vote.is_forced() && force_through) begin 00546: this.forced("Sub-consensus forces"); 00547: end 00548: else if (vote.is_reached()) this.consent("Sub-consensus consents"); 00549: else this.oppose("Sub-consensus opposes"); 00550: // Wait for sub-consensus to reach new results 00551: @vote.new_results; 00552: end 00553: join_none 00554: 00555: @(this.killme); 00556: disable fork; 00557: end 00558: join_none 00559: endfunction: sub_consensus 00560: 00561: 00562: function void vmm_voter::kill_voter(); 00563: ->this.killme; 00564: this.consensus = null; 00565: endfunction: kill_voter 00566: 00567: 00568: function vmm_xactor vmm_voter::get_xactor(); 00569: return this.xactor_voter; 00570: endfunction: get_xactor 00571: 00572: 00573: function vmm_channel vmm_voter::get_channel(); 00574: return this.channel_voter; 00575: endfunction: get_channel 00576: 00577: 00578: function vmm_notify vmm_voter::get_notify(); 00579: return this.notify_voter; 00580: endfunction: get_notify 00581: 00582: 00583: function int vmm_voter::get_notification(); 00584: return this.notification; 00585: endfunction: get_notification 00586: 00587: 00588: function vmm_consensus vmm_voter::get_consensus(); 00589: return this.sub_vote; 00590: endfunction: get_consensus 00591: 00592: