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.
RAL/vmm_ral_mem.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_ral_mem::new(vmm_ral_block parent, 00024: string name, 00025: vmm_ral::access_e access, 00026: longint unsigned size, 00027: int unsigned n_bits, 00028: bit [64-1:0] base_addr, 00029: string domain, 00030: bit cover_on, 00031: bit [1:0] rights, 00032: bit unmapped); 00033: 00034: this.name = name; 00035: this.locked = 0; 00036: 00037: if (n_bits == 0) begin 00038: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.log.text($psprintf("Memory \"%s\" cannot have 0 bits", this.get_fullname()))); : this.log.end_msg(); : end : while (0); 00039: n_bits = 1; 00040: end 00041: if (n_bits > 64) begin 00042: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.log.text($psprintf("Memory \"%s\" cannot have more than %0d bits (%0d)", this.get_fullname(), 64, n_bits))); : this.log.end_msg(); : end : while (0); 00043: n_bits = 64; 00044: end 00045: if (access != vmm_ral::RW && access != vmm_ral::RO) begin 00047: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.log.text($psprintf("Memory %s can only be RW or RO", : this.get_fullname()))); : this.log.end_msg(); : end : while (0); 00048: access = vmm_ral::RW; 00049: end 00050: 00051: this.parent = parent; 00052: this.size = size; 00053: this.access = access; 00054: this.n_bits = n_bits; 00055: this.backdoor = null; 00056: 00057: this.parent.register_mem(this); 00058: this.add_domain(base_addr, domain, rights, unmapped); 00059: 00060: this.cover_on = cover_on; 00061: this.no_cover = !cover_on; 00062: 00063: begin 00064: vmm_mam_cfg cfg = new; 00065: 00066: cfg.n_bytes = ((n_bits-1) / 8) + 1; 00067: cfg.start_offset = 0; 00068: cfg.end_offset = size-1; 00069: 00070: cfg.mode = vmm_mam::GREEDY; 00071: cfg.locality = vmm_mam::BROAD; 00072: 00073: this.mam = new(this.get_fullname(), cfg, this); 00074: end 00075: 00076: // Initialize Memory ID 00077: this.__vmm_mem_id = ++this.__vmm_mem_id_factory; 00078: __vmm_all_mems[this.__vmm_mem_id] = this; 00079: endfunction: new 00080: 00081: 00082: function void vmm_ral_mem::Xlock_modelX(); 00083: this.locked = 1; 00084: endfunction: Xlock_modelX 00085: 00086: 00087: function void vmm_ral_mem::add_domain(bit [64-1:0] base_addr, 00088: string domain, 00089: bit [1:0] rights, 00090: bit unmapped); 00091: vmm_ral::access_e acc; 00092: 00093: // Verify that this is a valid domain in the block 00094: string domains[]; 00095: 00096: if (this.locked) begin 00097: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.log.text($psprintf("Cannot add domain to locked memory %s", this.get_fullname()))); : this.log.end_msg(); : end : while (0); 00098: return; 00099: end 00100: 00101: case (rights) 00102: 2'b11: acc = vmm_ral::RW; 00103: 2'b10: acc = vmm_ral::RO; 00104: 2'b01: acc = vmm_ral::WO; 00105: default: 00108: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.log.text($psprintf("Memory %s has no access rights in domain \"%s\"", : this.get_fullname(), domain))); : this.log.end_msg(); : end : while (0); 00109: endcase 00110: 00111: this.parent.get_domains(domains); 00112: foreach(domains[i]) begin 00113: if (domains[i] == domain) begin 00114: automatic int n = this.offset_in_block.size(); 00115: 00116: this.offset_in_block = new [n + 1] (this.offset_in_block); 00117: this.offset_in_block[n] = (unmapped) ? 'X : base_addr; 00118: 00119: this.domains = new [n + 1] (this.domains); 00120: this.domains[n] = domain; 00121: 00122: this.rights = new [n + 1] (this.rights); 00123: this.rights[n] = acc; 00124: 00125: this.frontdoor = new [n + 1] (this.frontdoor); 00126: this.frontdoor[n] = null; 00127: return; 00128: end 00129: end 00131: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.log.text($psprintf("Domain \"%s\" not found in parent block %s of memory %s", : domain, this.parent.get_name(), this.get_fullname()))); : this.log.end_msg(); : end : while (0); 00132: endfunction: add_domain 00133: 00134: 00135: function void vmm_ral_mem::Xregister_ral_accessX(vmm_ral_access access); 00136: // There can only be one RAL Access on a RAL model 00137: if (this.ral_access != null && this.ral_access != access) begin 00138: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::FATAL_SEV)) begin : void'(this.log.text($psprintf("Memory %s is already used by another RAL access instance", this.get_fullname()))); : this.log.end_msg(); : end : while (0); 00139: end 00140: this.ral_access = access; 00141: endfunction: Xregister_ral_accessX 00142: 00143: 00144: function string vmm_ral_mem::get_name(); 00145: get_name = this.name; 00146: endfunction: get_name 00147: 00148: 00149: function string vmm_ral_mem::get_fullname(); 00150: vmm_ral_block blk; 00151: 00152: get_fullname = this.get_name(); 00153: 00154: // Do not include top-level name in full name 00155: blk = this.get_block(); 00156: if (blk == null) return get_fullname; 00157: if (blk.get_parent() == null) return get_fullname; 00158: 00159: get_fullname = {this.parent.get_fullname(), ".", get_fullname}; 00160: endfunction: get_fullname 00161: 00162: 00163: function int vmm_ral_mem::get_n_domains(); 00164: get_n_domains = this.domains.size(); 00165: endfunction: get_n_domains 00166: 00167: 00168: function void vmm_ral_mem::get_domains(ref string domains[]); 00169: domains = new [this.domains.size()] (this.domains); 00170: endfunction: get_domains 00171: 00172: 00173: function vmm_ral::access_e vmm_ral_mem::get_access(string domain); 00174: get_access = this.access; 00175: if (this.get_n_domains() == 1) return get_access; 00176: 00177: // Is the memory restricted in this domain? 00178: case (this.get_rights(domain)) 00179: vmm_ral::RW: 00180: // No restrictions 00181: return get_access; 00182: 00183: vmm_ral::RO: 00184: case (get_access) 00185: vmm_ral::RW, 00186: vmm_ral::RO: get_access = vmm_ral::RO; 00187: 00188: vmm_ral::WO: begin 00191: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.log.text($psprintf("WO memory %s restricted to RO in domain \"%s\"", : this.get_fullname(), domain))); : this.log.end_msg(); : end : while (0); 00192: end 00193: 00194: default: 00197: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.log.text($psprintf("Invalid memory %s access mode \"%s\"", : this.get_fullname(), get_access.name()))); : this.log.end_msg(); : end : while (0); 00198: endcase 00199: 00200: vmm_ral::WO: 00201: case (get_access) 00202: vmm_ral::RW, 00203: vmm_ral::WO: get_access = vmm_ral::WO; 00204: 00205: vmm_ral::RO: begin 00208: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.log.text($psprintf("RO memory %s restricted to WO in domain \"%s\"", : this.get_fullname(), get_access.name(), domain))); : this.log.end_msg(); : end : while (0); 00209: end 00210: 00211: default: 00214: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.log.text($psprintf("Invalid memory %s access mode \"%s\"", : this.get_fullname(), get_access.name()))); : this.log.end_msg(); : end : while (0); 00215: endcase 00216: 00217: default: 00220: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.log.text($psprintf("Shared memory \"%s\" is not shared in domain \"%s\"", : this.get_fullname(), domain))); : this.log.end_msg(); : end : while (0); 00221: endcase 00222: endfunction: get_access 00223: 00224: 00225: function vmm_ral::access_e vmm_ral_mem::get_rights(string domain); 00226: int i; 00227: 00228: // No right restrictions if not shared 00229: if (this.domains.size() == 1) begin 00230: return vmm_ral::RW; 00231: end 00232: 00233: i = this.get_domain_index(domain); 00234: if (i < 0) return vmm_ral::RW; 00235: 00236: get_rights = this.rights[i]; 00237: endfunction: get_rights 00238: 00239: 00240: function void vmm_ral_mem::get_virtual_fields(ref vmm_ral_vfield fields[]); 00241: vmm_ral_vfield vfields[]; 00242: 00243: fields = new[0]; 00244: foreach (this.XvregsX[i]) begin 00245: int n = fields.size(); 00246: this.XvregsX[i].get_fields(vfields); 00247: fields = new[n + vfields.size()] (fields); 00248: foreach(vfields[j]) begin 00249: fields[n+j] = vfields[j]; 00250: end 00251: end 00252: endfunction: get_virtual_fields 00253: 00254: 00255: // Return first occurrence of vfield matching name 00256: function vmm_ral_vfield vmm_ral_mem::get_virtual_field_by_name(string name); 00257: vmm_ral_vfield vfields[]; 00258: 00259: this.get_virtual_fields(vfields); 00260: foreach (vfields[i]) begin 00261: if (vfields[i].get_name() == name) return vfields[i]; 00262: end 00265: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::WARNING_SEV)) begin : void'(this.log.text($psprintf("Unable to find virtual field \"%s\" in memory %s.", : name, this.get_fullname()))); : this.log.end_msg(); : end : while(0); 00266: return null; 00267: endfunction: get_virtual_field_by_name 00268: 00269: 00270: function void vmm_ral_mem::get_virtual_registers(ref vmm_ral_vreg regs[]); 00271: regs = new[this.XvregsX.size()]; 00272: foreach (this.XvregsX[i]) begin 00273: regs[i] = this.XvregsX[i]; 00274: end 00275: endfunction: get_virtual_registers 00276: 00277: 00278: function vmm_ral_vreg vmm_ral_mem::get_vreg_by_name(string name); 00279: foreach (this.XvregsX[i]) begin 00280: if (this.XvregsX[i].get_name() == name) return this.XvregsX[i]; 00281: end 00284: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::WARNING_SEV)) begin : void'(this.log.text($psprintf("Unable to find virtual register \"%s\" in memory %s.", : name, this.get_fullname()))); : this.log.end_msg(); : end : while(0); 00285: 00286: endfunction: get_vreg_by_name 00287: 00288: 00289: function vmm_ral_vreg vmm_ral_mem::get_vreg_by_offset(bit [63:0] offset, 00290: string domain); 00291: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.log.text("vmm_ral_mem::get_vreg_by_offset() not yet implemented")); : this.log.end_msg(); : end : while (0); 00292: return null; 00293: endfunction: get_vreg_by_offset 00294: 00295: 00296: function vmm_ral_block vmm_ral_mem::get_block(); 00297: get_block = this.parent; 00298: endfunction: get_block 00299: 00300: 00301: function bit [64-1:0] vmm_ral_mem::get_offset_in_block(bit [64-1:0] mem_addr, 00302: string domain); 00303: foreach (this.domains[i]) begin 00304: if (this.domains[i] == domain) begin 00305: if (this.offset_in_block[i] === 'x) begin 00306: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::WARNING_SEV)) begin : void'(this.log.text($psprintf("Memory \"%s\" is unmapped in domain \"%s\".", this.get_name(), domain))); : this.log.end_msg(); : end : while(0); 00307: return '0; 00308: end 00309: 00310: return this.offset_in_block[i]; 00311: end 00312: end 00314: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::WARNING_SEV)) begin : void'(this.log.text($psprintf("Unable to find offset within domain \"%s\" in memory %s.", : domain, this.get_fullname()))); : this.log.end_msg(); : end : while(0); 00315: get_offset_in_block = '1; 00316: endfunction: get_offset_in_block 00317: 00318: 00319: function bit [64-1:0] vmm_ral_mem::get_address_in_system(bit [64-1:0] mem_addr, 00320: string domain); 00321: bit [64-1:0] addr[]; 00322: 00323: int i = this.get_domain_index(domain); 00324: if (i < 0) return 0; 00325: 00326: if (this.ral_access == null) begin 00328: : do : if (this.parent.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::FATAL_SEV)) begin : void'(this.parent.log.text("RAL model is not associated with an access transactor")); : this.parent.log.end_msg(); : end : while (0); 00329: return 0; 00330: end 00331: 00332: if (this.offset_in_block[i] === 'x) begin 00333: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.log.text($psprintf("Memory \"%s\" is unmapped in domain \"%s\".", this.get_name(), this.domains[i]))); : this.log.end_msg(); : end : while (0); 00334: return '1; 00335: end 00336: 00337: this.ral_access.Xget_physical_addressesX(this.offset_in_block[i], 00338: mem_addr, this.get_n_bytes(), 00339: this.parent, 00340: this.domains[i], 00341: addr); 00342: 00343: get_address_in_system = addr[0]; 00344: endfunction: get_address_in_system 00345: 00346: 00347: function longint unsigned vmm_ral_mem::get_size(); 00348: get_size = this.size; 00349: endfunction: get_size 00350: 00351: 00352: function int unsigned vmm_ral_mem::get_n_bits(); 00353: get_n_bits = this.n_bits; 00354: endfunction: get_n_bits 00355: 00356: 00357: function int unsigned vmm_ral_mem::get_n_bytes(); 00358: get_n_bytes = (this.n_bits - 1) / 8 + 1; 00359: endfunction: get_n_bytes 00360: 00361: 00362: function void vmm_ral_mem::display(string prefix, 00363: string domain); 00364: $write("%s\n", this.psdisplay(prefix, domain)); 00365: endfunction: display 00366: 00367: 00368: function string vmm_ral_mem::psdisplay(string prefix, 00369: string domain); 00370: $sformat(psdisplay, "%sMemory %s -- %0dx%0d bits @", prefix, 00371: this.get_fullname(), this.get_size(), this.get_n_bits()); 00372: foreach (this.domains[i]) begin 00373: if (this.domains[i] == domain) begin 00374: if (this.offset_in_block[i] === 'x) begin 00375: psdisplay = {psdisplay, "none"}; 00376: end 00377: else begin 00378: $sformat(psdisplay, "%s'h%h", psdisplay, 00379: this.get_address_in_system(0, domain)); 00380: end 00381: break; 00382: end 00383: end 00384: endfunction: psdisplay 00385: 00386: 00387: function bit vmm_ral_mem::set_cover(bit is_on); 00388: set_cover = this.cover_on; 00389: 00390: if (this.no_cover && is_on) begin 00391: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::WARNING_SEV)) begin : void'(this.log.text($psprintf("Cannot turn cover ON if constructed with coverage disabled in memory %s", this.get_fullname()))); : this.log.end_msg(); : end : while(0); 00392: return 0; 00393: end 00394: 00395: this.cover_on = is_on; 00396: endfunction: set_cover 00397: 00398: 00399: function bit vmm_ral_mem::is_cover_on(); 00400: is_cover_on = this.cover_on; 00401: endfunction: is_cover_on 00402: 00403: 00404: task vmm_ral_mem::init(output bit is_ok, 00405: input init_e pattern, 00406: input bit [64-1:0] data); 00407: int incr; 00408: is_ok = 0; 00409: 00410: if (this.backdoor == null) begin 00411: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.log.text($psprintf("No backdoor available to initialize memory %s", this.get_fullname()))); : this.log.end_msg(); : end : while (0); 00412: return; 00413: end 00414: 00415: case (pattern) 00416: UNKNOWNS: 00417: begin 00418: data = 'x; 00419: incr = 0; 00420: end 00421: 00422: ZEROES: 00423: begin 00424: data = '0; 00425: incr = 0; 00426: end 00427: 00428: ONES: 00429: begin 00430: data = '1; 00431: incr = 0; 00432: end 00433: 00434: VALUE: 00435: begin 00436: incr = 0; 00437: end 00438: 00439: INCR: 00440: begin 00441: incr = 1; 00442: end 00443: 00444: DECR: 00445: begin 00446: incr = -1; 00447: end 00448: endcase 00449: 00450: // ToDo... 00451: endtask:init 00452: 00453: 00454: task vmm_ral_mem::write(output vmm_rw::status_e status, 00455: input bit [64-1:0] mem_addr, 00456: input bit [64-1:0] value, 00457: input vmm_ral::path_e path, 00458: input string domain, 00459: input int data_id, 00460: input int scenario_id, 00461: input int stream_id); 00462: status = vmm_rw::ERROR; 00463: 00464: if (this.ral_access == null) begin 00465: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.log.text($psprintf("Memory %s not associated with RAL access object", this.get_fullname()))); : this.log.end_msg(); : end : while (0); 00466: return; 00467: end 00468: 00469: if (path == vmm_ral::DEFAULT) path = this.parent.get_default_access(); 00470: 00472: : : do foreach (this.callbacks[vmm_i]) begin : vmm_ral_mem_callbacks cb; : if (!$cast(cb, this.callbacks[vmm_i])) continue; : : cb.pre_write(this, mem_addr, value, path, domain); : end while (0); 00473: 00474: if (path == vmm_ral::DEFAULT) path = this.parent.get_default_access(); 00475: 00476: if (path == vmm_ral::BACKDOOR && 00477: this.backdoor == null) begin 00478: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::WARNING_SEV)) begin : void'(this.log.text($psprintf("No backdoor access available for memory \"%s\". Using frontdoor instead.", this.get_name()))); : this.log.end_msg(); : end : while(0); 00479: path = vmm_ral::BFM; 00480: end 00481: 00482: case (path) 00483: 00484: vmm_ral::BFM: begin 00485: int di = this.get_domain_index(domain); 00486: if (di < 0) return; 00487: 00488: if (this.frontdoor[di] != null) begin 00489: this.frontdoor[di].write(status, mem_addr, value, 00490: data_id, scenario_id, stream_id); 00491: end 00492: else begin 00493: bit [64-1:0] addr[]; 00494: int w, j; 00495: int n_bits; 00496: 00497: if (this.offset_in_block[di] === 'x) begin 00500: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.log.text($psprintf("Memory \"%s\" unmapped in domain \"%s\" does not have a user-defined frontdoor", : this.get_name(), : this.domains[di]))); : this.log.end_msg(); : end : while (0); 00501: return; 00502: end 00503: 00504: w = this.ral_access.Xget_physical_addressesX(this.offset_in_block[di], 00505: mem_addr, 00506: this.get_n_bytes(), 00507: this.parent, 00508: this.domains[di], 00509: addr); 00510: j = 0; 00511: n_bits = this.get_n_bits; 00512: foreach (addr[i]) begin 00513: bit [64-1:0] data; 00514: data = value >> (j*8); 00515: this.ral_access.write(status, addr[i], data, 00516: (n_bits > w*8) ? w*8 : n_bits, 00517: this.parent.get_external_domain(this.domains[di]), 00518: data_id, scenario_id, stream_id); 00519: if (status != vmm_rw::IS_OK) break; 00520: j += w; 00521: n_bits -= w * 8; 00522: end 00523: end 00524: 00525: if (this.cover_on) this.parent.XsampleX(this.offset_in_block[di], di); 00526: end 00527: 00528: vmm_ral::BACKDOOR: begin 00529: // Mimick front door access: Do not write read-only memories 00530: if (this.get_access(domain) == vmm_ral::RW) begin 00531: this.poke(status, mem_addr, value, 00532: data_id, scenario_id, stream_id); 00533: end else status = vmm_rw::IS_OK; 00534: end 00535: endcase 00536: 00538: : : do foreach (this.callbacks[vmm_i]) begin : vmm_ral_mem_callbacks cb; : if (!$cast(cb, this.callbacks[vmm_i])) continue; : : cb.post_write(this, mem_addr, value, path, domain, status); : end while (0); 00539: 00543: : do : if (this.log.start_msg(vmm_log::DEBUG_TYP, vmm_log::TRACE_SEV)) begin : void'(this.log.text($psprintf("Wrote memory \"%s\"[%0d] via %s: with 'h%h", : this.get_fullname(), mem_addr, : (path == vmm_ral::BFM) ? "frontdoor" : "backdoor", : value))); : this.log.end_msg(); : end : while (0); 00544: endtask: write 00545: 00546: 00547: task vmm_ral_mem::read(output vmm_rw::status_e status, 00548: input bit [64-1:0] mem_addr, 00549: output bit [64-1:0] value, 00550: input vmm_ral::path_e path, 00551: input string domain, 00552: input int data_id, 00553: input int scenario_id, 00554: input int stream_id); 00555: status = vmm_rw::ERROR; 00556: 00557: if (this.ral_access == null) begin 00558: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.log.text($psprintf("Memory %s not associated with RAL access object", this.get_fullname()))); : this.log.end_msg(); : end : while (0); 00559: return; 00560: end 00561: 00562: if (path == vmm_ral::DEFAULT) path = this.parent.get_default_access(); 00563: 00565: : : do foreach (this.callbacks[vmm_i]) begin : vmm_ral_mem_callbacks cb; : if (!$cast(cb, this.callbacks[vmm_i])) continue; : : cb.pre_read(this, mem_addr, path, domain); : end while (0); 00566: 00567: if (path == vmm_ral::DEFAULT) path = this.parent.get_default_access(); 00568: 00569: if (path == vmm_ral::BACKDOOR && 00570: this.backdoor == null) begin 00571: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::WARNING_SEV)) begin : void'(this.log.text($psprintf("No backdoor access available for memory \"%s\". Using frontdoor instead.", this.get_name()))); : this.log.end_msg(); : end : while(0); 00572: path = vmm_ral::BFM; 00573: end 00574: 00575: case (path) 00576: 00577: vmm_ral::BFM: begin 00578: int di = this.get_domain_index(domain); 00579: if (di < 0) return; 00580: 00581: if (this.frontdoor[di] != null) begin 00582: this.frontdoor[di].read(status, mem_addr, value, 00583: data_id, scenario_id, stream_id); 00584: end 00585: else begin 00586: bit [64-1:0] addr[]; 00587: int w, j; 00588: int n_bits; 00589: 00590: if (this.offset_in_block[di] === 'x) begin 00593: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.log.text($psprintf("Memory \"%s\" unmapped in domain \"%s\" does not have a user-defined frontdoor", : this.get_name(), : this.domains[di]))); : this.log.end_msg(); : end : while (0); 00594: return; 00595: end 00596: 00597: w = this.ral_access.Xget_physical_addressesX(this.offset_in_block[di], 00598: mem_addr, 00599: this.get_n_bytes(), 00600: this.parent, 00601: this.domains[di], 00602: addr); 00603: j = 0; 00604: n_bits = this.get_n_bits(); 00605: value = 0; 00606: foreach (addr[i]) begin 00607: bit [64-1:0] data; 00608: this.ral_access.read(status, addr[i], data, 00609: (n_bits > w*8) ? w*8 : n_bits, 00610: this.parent.get_external_domain(this.domains[di]), 00611: data_id, scenario_id, stream_id); 00612: if (status != vmm_rw::IS_OK) break; 00613: value |= (data & ((1 << (w*8)) - 1)) << (j*8); 00614: j += w; 00615: n_bits -= w * 8; 00616: end 00617: end 00618: 00619: if (this.cover_on) this.parent.XsampleX(this.offset_in_block[di], di); 00620: end 00621: 00622: vmm_ral::BACKDOOR: begin 00623: this.peek(status, mem_addr, value, 00624: data_id, scenario_id, stream_id); 00625: end 00626: endcase 00627: 00629: : : do foreach (this.callbacks[vmm_i]) begin : vmm_ral_mem_callbacks cb; : if (!$cast(cb, this.callbacks[vmm_i])) continue; : : cb.post_read(this, mem_addr, value, path, domain, status); : end while (0); 00630: 00634: : do : if (this.log.start_msg(vmm_log::DEBUG_TYP, vmm_log::TRACE_SEV)) begin : void'(this.log.text($psprintf("Read memory \"%s\"[%0d] via %s: 'h%h", : this.get_fullname(), mem_addr, : (path == vmm_ral::BFM) ? "frontdoor" : "backdoor", : value))); : this.log.end_msg(); : end : while (0); 00635: endtask: read 00636: 00637: 00638: function bit vmm_ral_mem::validate_burst(vmm_ral_mem_burst burst); 00639: if (burst.start_offset >= this.get_size()) begin 00641: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.log.text($psprintf("Starting burst offset 'h%0h is greater than number of memory locations ('h%0h)", : burst.start_offset, this.get_size()))); : this.log.end_msg(); : end : while (0); 00642: return 0; 00643: end 00644: 00645: if (burst.max_offset >= this.get_size()) begin 00647: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.log.text($psprintf("Maximum burst offset 'h%0h is greater than number of memory locations ('h%0h)", : burst.max_offset, this.get_size()))); : this.log.end_msg(); : end : while (0); 00648: return 0; 00649: end 00650: 00651: if (burst.n_beats == 0) begin 00652: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.log.text("Zero-length burst")); : this.log.end_msg(); : end : while (0); 00653: return 0; 00654: end 00655: 00656: if (burst.start_offset > burst.max_offset) begin 00658: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.log.text($psprintf("Starting burst offset ('h%0h) greater than maximum burst offset ('h%0h)", : burst.start_offset, burst.max_offset))); : this.log.end_msg(); : end : while (0); 00659: return 0; 00660: end 00661: 00662: if (burst.n_beats > 1 && 00663: burst.start_offset + burst.incr_offset >= burst.max_offset) begin 00666: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.log.text($psprintf("First burst offset increment 'h%0h+%0h is greater than maximum burst offset ('h%0h)", : burst.start_offset, burst.incr_offset, : burst.max_offset))); : this.log.end_msg(); : end : while (0); 00667: return 0; 00668: end 00669: 00670: return 1; 00671: endfunction: validate_burst 00672: 00673: 00674: task vmm_ral_mem::burst_write(output vmm_rw::status_e status, 00675: input vmm_ral_mem_burst burst, 00676: input bit [64-1:0] value[], 00677: input vmm_ral::path_e path, 00678: input string domain, 00679: input int data_id, 00680: input int scenario_id, 00681: input int stream_id); 00682: status = vmm_rw::ERROR; 00683: 00684: if (this.ral_access == null) begin 00685: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.log.text($psprintf("Memory %s not associated with RAL access object", this.get_fullname()))); : this.log.end_msg(); : end : while (0); 00686: return; 00687: end 00688: 00689: if (path == vmm_ral::DEFAULT) path = this.parent.get_default_access(); 00690: 00692: : : do foreach (this.callbacks[vmm_i]) begin : vmm_ral_mem_callbacks cb; : if (!$cast(cb, this.callbacks[vmm_i])) continue; : : cb.pre_burst(this, vmm_rw::WRITE, burst, value, path, domain); : end while (0); 00693: 00694: if (!this.validate_burst(burst)) return; 00695: 00696: if (path == vmm_ral::DEFAULT) path = this.parent.get_default_access(); 00697: 00698: case (path) 00699: 00700: vmm_ral::BFM: begin 00701: int di = this.get_domain_index(domain); 00702: if (di < 0) return; 00703: 00704: if (this.frontdoor[di] != null) begin 00705: this.frontdoor[di].burst_write(status, burst, value, 00706: data_id, scenario_id, stream_id); 00707: end 00708: else begin 00709: bit [64-1:0] addr[]; 00710: int w; 00711: int n_bits; 00712: 00713: if (this.offset_in_block[di] === 'x) begin 00716: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.log.text($psprintf("Memory \"%s\" unmapped in domain \"%s\" does not have a user-defined frontdoor", : this.get_name(), : this.domains[di]))); : this.log.end_msg(); : end : while (0); 00717: return; 00718: end 00719: 00720: w = this.ral_access.Xget_physical_addressesX(this.offset_in_block[di], 00721: burst.start_offset, 00722: this.get_n_bytes(), 00723: this.parent, 00724: this.domains[di], 00725: addr); 00726: n_bits = this.get_n_bits; 00727: // Cannot burst memory through a narrower datapath 00728: if (n_bits > w*8) begin 00730: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.log.text($psprintf("Cannot burst-write a %0d-bit memory through a narrower data path (%0d bytes)", : n_bits, w))); : this.log.end_msg(); : end : while (0); 00731: return; 00732: end 00733: // Translate offsets into addresses 00734: begin 00735: bit [64-1:0] start, incr, max; 00736: 00737: start = addr[0]; 00738: 00739: w = this.ral_access.Xget_physical_addressesX(this.offset_in_block[di], 00740: burst.start_offset + burst.incr_offset, 00741: this.get_n_bytes(), 00742: this.parent, 00743: this.domains[di], 00744: addr); 00745: incr = addr[0] - start; 00746: 00747: w = this.ral_access.Xget_physical_addressesX(this.offset_in_block[di], 00748: burst.max_offset, 00749: this.get_n_bytes(), 00750: this.parent, 00751: this.domains[di], 00752: addr); 00753: 00754: max = addr[addr.size()-1]; 00755: 00756: this.ral_access.burst_write(status, start, incr, max, value, 00757: burst.user_data, n_bits, 00758: this.parent.get_external_domain(this.domains[di]), 00759: data_id, scenario_id, stream_id); 00760: end 00761: end 00762: 00763: if (this.cover_on) begin 00764: bit [64-1:0] addr; 00765: for (addr = burst.start_offset; 00766: addr <= burst.max_offset; 00767: addr += burst.incr_offset) begin 00768: this.parent.XsampleX(this.offset_in_block[di] + addr, di); 00769: end 00770: end 00771: end 00772: 00773: vmm_ral::BACKDOOR: begin 00774: // Mimick front door access: Do not write read-only memories 00775: if (this.get_access(domain) == vmm_ral::RW) begin 00776: bit [64-1:0] addr; 00777: addr = burst.start_offset; 00778: foreach (value[i]) begin 00779: this.poke(status, addr, value[i], 00780: data_id, scenario_id, stream_id); 00781: if (status != vmm_rw::IS_OK) return; 00782: addr += burst.incr_offset; 00783: if (addr > burst.max_offset) begin 00784: addr -= (burst.max_offset - burst.start_offset - 1); 00785: end 00786: end 00787: end 00788: else status = vmm_rw::IS_OK; 00789: end 00790: endcase 00791: 00794: : : do foreach (this.callbacks[vmm_i]) begin : vmm_ral_mem_callbacks cb; : if (!$cast(cb, this.callbacks[vmm_i])) continue; : : cb.post_burst(this, vmm_rw::WRITE, burst, value, : path, domain, status); : end while (0); 00795: endtask: burst_write 00796: 00797: 00798: task vmm_ral_mem::burst_read(output vmm_rw::status_e status, 00799: input vmm_ral_mem_burst burst, 00800: output bit [64-1:0] value[], 00801: input vmm_ral::path_e path, 00802: input string domain, 00803: input int data_id, 00804: input int scenario_id, 00805: input int stream_id); 00806: status = vmm_rw::ERROR; 00807: 00808: if (this.ral_access == null) begin 00809: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.log.text($psprintf("Memory %s not associated with RAL access object", this.get_fullname()))); : this.log.end_msg(); : end : while (0); 00810: return; 00811: end 00812: 00813: if (path == vmm_ral::DEFAULT) path = this.parent.get_default_access(); 00814: 00815: begin 00816: bit [64-1:0] junk[]; 00817: 00819: : : do foreach (this.callbacks[vmm_i]) begin : vmm_ral_mem_callbacks cb; : if (!$cast(cb, this.callbacks[vmm_i])) continue; : : cb.pre_burst(this, vmm_rw::READ, burst, junk, path, domain); : end while (0); 00820: end 00821: 00822: if (!this.validate_burst(burst)) return; 00823: 00824: if (path == vmm_ral::DEFAULT) path = this.parent.get_default_access(); 00825: 00826: case (path) 00827: 00828: vmm_ral::BFM: begin 00829: int di = this.get_domain_index(domain); 00830: if (di < 0) return; 00831: 00832: if (this.frontdoor[di] != null) begin 00833: this.frontdoor[di].burst_read(status, burst, value, 00834: data_id, scenario_id, stream_id); 00835: end 00836: else begin 00837: bit [64-1:0] addr[]; 00838: int n_bits, w; 00839: 00840: if (this.offset_in_block[di] === 'x) begin 00843: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.log.text($psprintf("Memory \"%s\" unmapped in domain \"%s\" does not have a user-defined frontdoor", : this.get_name(), : this.domains[di]))); : this.log.end_msg(); : end : while (0); 00844: return; 00845: end 00846: 00847: w = this.ral_access.Xget_physical_addressesX(this.offset_in_block[di], 00848: burst.start_offset, 00849: this.get_n_bytes(), 00850: this.parent, 00851: this.domains[di], 00852: addr); 00853: n_bits = this.get_n_bits(); 00854: // Cannot burst memory through a narrower datapath 00855: if (n_bits > w*8) begin 00857: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.log.text($psprintf("Cannot burst-write a %0d-bit memory through a narrower data path (%0d bytes)", : n_bits, w))); : this.log.end_msg(); : end : while (0); 00858: return; 00859: end 00860: // Translate the offset-based burst into address-based burst 00861: begin 00862: bit [64-1:0] start, incr, max; 00863: 00864: start = addr[0]; 00865: 00866: w = this.ral_access.Xget_physical_addressesX(this.offset_in_block[di], 00867: burst.start_offset + burst.incr_offset, 00868: this.get_n_bytes(), 00869: this.parent, 00870: this.domains[di], 00871: addr); 00872: incr = addr[0] - start; 00873: 00874: w = this.ral_access.Xget_physical_addressesX(this.offset_in_block[di], 00875: burst.max_offset, 00876: this.get_n_bytes(), 00877: this.parent, 00878: this.domains[di], 00879: addr); 00880: 00881: max = addr[addr.size()-1]; 00882: 00883: this.ral_access.burst_read(status, start, incr, max, 00884: burst.n_beats, value, 00885: burst.user_data, n_bits, 00886: this.parent.get_external_domain(this.domains[di]), 00887: data_id, scenario_id, stream_id); 00888: end 00889: end 00890: 00891: if (this.cover_on) begin 00892: bit [64-1:0] addr; 00893: for (addr = burst.start_offset; 00894: addr <= burst.max_offset; 00895: addr += burst.incr_offset) begin 00896: this.parent.XsampleX(this.offset_in_block[di] + addr, di); 00897: end 00898: end 00899: end 00900: 00901: vmm_ral::BACKDOOR: begin 00902: bit [64-1:0] addr; 00903: value = new [burst.n_beats]; 00904: addr = burst.start_offset; 00905: foreach (value[i]) begin 00906: this.peek(status, addr, value[i], 00907: data_id, scenario_id, stream_id); 00908: if (status != vmm_rw::IS_OK) return; 00909: addr += burst.incr_offset; 00910: if (addr > burst.max_offset) begin 00911: addr -= (burst.max_offset - burst.start_offset - 1); 00912: end 00913: end 00914: end 00915: endcase 00916: 00919: : : do foreach (this.callbacks[vmm_i]) begin : vmm_ral_mem_callbacks cb; : if (!$cast(cb, this.callbacks[vmm_i])) continue; : : cb.post_burst(this, vmm_rw::READ, burst, value, : path, domain, status); : end while (0); 00920: endtask: burst_read 00921: 00922: 00923: task vmm_ral_mem::poke(output vmm_rw::status_e status, 00924: input bit [64-1:0] mem_addr, 00925: input bit [64-1:0] value, 00926: input int data_id, 00927: input int scenario_id, 00928: input int stream_id); 00929: if (this.backdoor == null) begin 00930: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.log.text($psprintf("No backdoor access available in memory %s", this.get_fullname()))); : this.log.end_msg(); : end : while (0); 00931: status = vmm_rw::ERROR; 00932: return; 00933: end 00934: this.backdoor.write(status, mem_addr, value, data_id, scenario_id, stream_id); 00935: 00937: : do : if (this.log.start_msg(vmm_log::DEBUG_TYP, vmm_log::TRACE_SEV)) begin : void'(this.log.text($psprintf("Poked memory \"%s\"[%0d] with: 'h%h", : this.get_fullname(), mem_addr, value))); : this.log.end_msg(); : end : while (0); 00938: endtask: poke 00939: 00940: 00941: task vmm_ral_mem::peek(output vmm_rw::status_e status, 00942: input bit [64-1:0] mem_addr, 00943: output bit [64-1:0] value, 00944: input int data_id, 00945: input int scenario_id, 00946: input int stream_id); 00947: if (this.backdoor == null) begin 00948: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.log.text($psprintf("No backdoor access available in memory %s", this.get_fullname()))); : this.log.end_msg(); : end : while (0); 00949: status = vmm_rw::ERROR; 00950: return; 00951: end 00952: this.backdoor.read(status, mem_addr, value, data_id, scenario_id, stream_id); 00953: 00955: : do : if (this.log.start_msg(vmm_log::DEBUG_TYP, vmm_log::TRACE_SEV)) begin : void'(this.log.text($psprintf("Peeked memory \"%s\"[%0d]: 'h%h", : this.get_fullname(), mem_addr, value))); : this.log.end_msg(); : end : while (0); 00956: endtask: peek 00957: 00958: 00959: task vmm_ral_mem::readmemh(string filename); 00960: endtask: readmemh 00961: 00962: 00963: task vmm_ral_mem::writememh(string filename); 00964: endtask: writememh 00965: 00966: 00967: function void vmm_ral_mem::set_frontdoor(vmm_ral_mem_frontdoor ftdr, 00968: string domain); 00969: foreach(this.domains[i]) begin 00970: if (this.domains[i] == domain) begin 00971: this.frontdoor[i] = ftdr; 00972: return; 00973: end 00974: end 00975: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.log.text($psprintf("Domain \"%s\" not found in memory %s", domain, this.get_fullname()))); : this.log.end_msg(); : end : while (0); 00976: endfunction: set_frontdoor 00977: 00978: 00979: function vmm_ral_mem_frontdoor vmm_ral_mem::get_frontdoor(string domain); 00980: foreach(this.domains[i]) begin 00981: if (this.domains[i] == domain) begin 00982: return this.frontdoor[i]; 00983: end 00984: end 00985: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.log.text($psprintf("Domain \"%s\" not found in memory %s", domain, this.get_fullname()))); : this.log.end_msg(); : end : while (0); 00986: endfunction: get_frontdoor 00987: 00988: 00989: function void vmm_ral_mem::set_backdoor(vmm_ral_mem_backdoor bkdr); 00990: this.backdoor = bkdr; 00991: endfunction: set_backdoor 00992: 00993: 00994: function vmm_ral_mem_backdoor vmm_ral_mem::get_backdoor(); 00995: get_backdoor = this.backdoor; 00996: endfunction: get_backdoor 00997: 00998: 00999: function void vmm_ral_mem::prepend_callback(vmm_ral_mem_callbacks cb); 01000: foreach (this.callbacks[i]) begin 01001: if (this.callbacks[i] == cb) begin 01002: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::WARNING_SEV)) begin : void'(this.log.text($psprintf("Callback has already been registered with memory %s", this.get_fullname()))); : this.log.end_msg(); : end : while(0); 01003: return; 01004: end 01005: end 01006: 01007: // Prepend new callback 01008: this.callbacks.push_front(cb); 01009: endfunction: prepend_callback 01010: 01011: 01012: function void vmm_ral_mem::append_callback(vmm_ral_mem_callbacks cb); 01013: foreach (this.callbacks[i]) begin 01014: if (this.callbacks[i] == cb) begin 01015: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::WARNING_SEV)) begin : void'(this.log.text($psprintf("Callback has already been registered with memory %s", this.get_fullname()))); : this.log.end_msg(); : end : while(0); 01016: return; 01017: end 01018: end 01019: 01020: // Append new callback 01021: this.callbacks.push_back(cb); 01022: endfunction: append_callback 01023: 01024: 01025: function void vmm_ral_mem::unregister_callback(vmm_ral_mem_callbacks cb); 01026: foreach (this.callbacks[i]) begin 01027: if (this.callbacks[i] == cb) begin 01028: int j = i; 01029: // Unregister it 01030: this.callbacks.delete(j); 01031: return; 01032: end 01033: end 01034: 01035: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::WARNING_SEV)) begin : void'(this.log.text($psprintf("Callback was not registered with memory %s", this.get_fullname()))); : this.log.end_msg(); : end : while(0); 01036: endfunction: unregister_callback 01037: 01038: 01039: function int vmm_ral_mem::get_domain_index(string domain); 01040: // If the domain is "" and there is only one domain, 01041: // assume it is the one domain available to avoid 01042: // having to always have to specify domains 01043: if (domain == "" && this.domains.size() == 1) return 0; 01044: 01045: foreach (this.domains[i]) begin 01046: if (this.domains[i] == domain) return i; 01047: end 01048: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::WARNING_SEV)) begin : void'(this.log.text($psprintf("Unknown domain name \"%s\" in memory %s.", domain, this.get_fullname()))); : this.log.end_msg(); : end : while(0); 01049: return -1; 01050: endfunction: get_domain_index 01051: 01052: 01053: task vmm_ral_mem_frontdoor::write(output vmm_rw::status_e status, 01054: input bit [64-1:0] offset, 01055: input bit [64-1:0] data, 01056: input int data_id, 01057: input int scenario_id, 01058: input int stream_id); 01059: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::FATAL_SEV)) begin : void'(this.log.text("vmm_ral_mem_frontdoor::write() method has not been overloaded")); : this.log.end_msg(); : end : while (0); 01060: endtask: write 01061: 01062: 01063: task vmm_ral_mem_frontdoor::read(output vmm_rw::status_e status, 01064: input bit [64-1:0] offset, 01065: output bit [64-1:0] data, 01066: input int data_id, 01067: input int scenario_id, 01068: input int stream_id); 01069: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::FATAL_SEV)) begin : void'(this.log.text("vmm_ral_mem_frontdoor::read() method has not been overloaded")); : this.log.end_msg(); : end : while (0); 01070: endtask: read 01071: 01072: 01073: function int unsigned vmm_ral_mem::get_mem_ID(); 01074: get_mem_ID = this.__vmm_mem_id; 01075: endfunction 01076: 01077: function vmm_ral_mem vmm_ral_mem::get_mem_by_ID(int unsigned id); 01078: if (__vmm_all_mems.exists(id)) get_mem_by_ID = __vmm_all_mems[id]; 01079: else get_mem_by_ID = null; 01080: endfunction