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_access.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: class vmm_ral_access extends vmm_xactor; 00024: vmm_ral::path_e default_path = vmm_ral::BFM; // Cannot be "DEFAULT" 00025: 00026: protected vmm_ral_block_or_sys model; 00027: 00028: protected vmm_rw_xactor rw_exec[string]; // One per domain 00029: 00030: extern function new(); 00031: 00032: extern function void set_model(vmm_ral_block_or_sys model); 00033: extern function vmm_ral_block_or_sys get_model(); 00034: extern function void add_xactor(vmm_rw_xactor xact, 00035: string domain = ""); 00036: 00037: extern task write(output vmm_rw::status_e status, 00038: input bit [64-1:0] addr, 00039: input bit [64-1:0] data, 00040: input int n_bits = 64, 00041: input string domain = "", 00042: input int data_id = -1, 00043: input int scenario_id = -1, 00044: input int stream_id = -1); 00045: 00046: extern task read(output vmm_rw::status_e status, 00047: input bit [64-1:0] addr, 00048: output bit [64-1:0] data, 00049: input int n_bits = 64, 00050: input string domain = "", 00051: input int data_id = -1, 00052: input int scenario_id = -1, 00053: input int stream_id = -1); 00054: 00055: extern task burst_write(output vmm_rw::status_e status, 00056: input bit [64-1:0] start, 00057: input bit [64-1:0] incr, 00058: input bit [64-1:0] max, 00059: input bit [64-1:0] data[], 00060: input vmm_data user = null, 00061: input int n_bits = 64, 00062: input string domain = "", 00063: input int data_id = -1, 00064: input int scenario_id = -1, 00065: input int stream_id = -1); 00066: 00067: extern task burst_read(output vmm_rw::status_e status, 00068: input bit [64-1:0] start, 00069: input bit [64-1:0] incr, 00070: input bit [64-1:0] max, 00071: input int n_beats, 00072: output bit [64-1:0] data[], 00073: input vmm_data user = null, 00074: input int n_bits = 64, 00075: input string domain = "", 00076: input int data_id = -1, 00077: input int scenario_id = -1, 00078: input int stream_id = -1); 00079: 00080: extern virtual function bit set_by_name(input string name, 00081: input bit [64-1:0] value); 00082: extern virtual function bit get_by_name(input string name, 00083: output bit [64-1:0] value); 00084: 00085: extern task write_by_name(output vmm_rw::status_e status, 00086: input string name, 00087: input bit [64-1:0] data, 00088: input vmm_ral::path_e path = vmm_ral::DEFAULT, 00089: input string domain = "", 00090: input int data_id = -1, 00091: input int scenario_id = -1, 00092: input int stream_id = -1); 00093: 00094: extern task read_by_name(output vmm_rw::status_e status, 00095: input string name, 00096: output bit [64-1:0] data, 00097: input vmm_ral::path_e path = vmm_ral::DEFAULT, 00098: input string domain = "", 00099: input int data_id = -1, 00100: input int scenario_id = -1, 00101: input int stream_id = -1); 00102: 00103: extern task write_mem_by_name(output vmm_rw::status_e status, 00104: input string name, 00105: input bit [64-1:0] offset, 00106: input bit [64-1:0] data, 00107: input vmm_ral::path_e path = vmm_ral::DEFAULT, 00108: input string domain = "", 00109: input int data_id = -1, 00110: input int scenario_id = -1, 00111: input int stream_id = -1); 00112: 00113: extern task read_mem_by_name(output vmm_rw::status_e status, 00114: input string name, 00115: input bit [64-1:0] offset, 00116: output bit [64-1:0] data, 00117: input vmm_ral::path_e path = vmm_ral::DEFAULT, 00118: input string domain = "", 00119: input int data_id = -1, 00120: input int scenario_id = -1, 00121: input int stream_id = -1); 00122: 00123: /*local*/ extern function int 00124: Xget_physical_addressesX(bit [64-1:0] base_addr, 00125: bit [64-1:0] mem_offset, 00126: int unsigned n_bytes, 00127: vmm_ral_block_or_sys in_block, 00128: string domain, 00129: ref bit [64-1:0] addr[]); 00130: endclass: vmm_ral_access 00131: 00132: 00133: function vmm_ral_access::new(); 00134: super.new("RVM RAL Access", "Main"); 00135: endfunction: new 00136: 00137: 00138: function void vmm_ral_access::set_model(vmm_ral_block_or_sys model); 00139: if (this.model != null) begin 00140: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.log.text("A RAL abstraction model has already been associated with this RAL access interface")); : this.log.end_msg(); : end : while (0); 00141: return; 00142: end 00143: 00144: this.model = model; 00145: 00146: // Register this RAL access object with the RAL model 00147: model.Xregister_ral_accessX(this); 00148: endfunction: set_model 00149: 00150: 00151: function vmm_ral_block_or_sys vmm_ral_access::get_model(); 00152: get_model = this.model; 00153: endfunction: get_model 00154: 00155: 00156: function void vmm_ral_access::add_xactor(vmm_rw_xactor xact, 00157: string domain); 00158: if (this.model == null) begin 00159: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.log.text("A RAL abstraction model has not yet been associated with this RAL access interface")); : this.log.end_msg(); : end : while (0); 00160: return; 00161: end 00162: 00163: // Check if the specified domain matches a domain in the model 00164: begin 00165: string domains[]; 00166: bit found = 0; 00167: 00168: model.get_domains(domains); 00169: foreach (domains[i]) begin 00170: if (domains[i] == domain) begin 00171: found = 1; 00172: break; 00173: end 00174: end 00175: if (!found) begin 00177: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.log.text($psprintf("Domain \"%s\" does not exist in RAL model", : domain))); : this.log.end_msg(); : end : while (0); 00178: if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 00179: string msg; 00180: this.log.text($psprintf("Domain \"%s\" does not exist in RAL model \"%s\"", 00181: domain, this.model.get_name())); 00182: msg = "Available domains are:"; 00183: foreach (domains[i]) begin 00184: $sformat(msg, "%s \"%s\"", msg, domains[i]); 00185: end 00186: this.log.text(msg); 00187: this.log.end_msg(); 00188: end 00189: return; 00190: end 00191: end 00192: 00193: if (this.rw_exec.exists(domain)) begin 00195: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.log.text($psprintf("Transactor for domain \"%s\" already exists", : domain))); : this.log.end_msg(); : end : while (0); 00196: end 00197: else begin 00198: this.rw_exec[domain] = xact; 00199: 00200: // Make sure transactor is started 00201: xact.start_xactor(); 00202: end 00203: endfunction: add_xactor 00204: 00205: 00206: task vmm_ral_access::write(output vmm_rw::status_e status, 00207: input bit [64-1:0] addr, 00208: input bit [64-1:0] data, 00209: input int n_bits, 00210: input string domain, 00211: input int data_id, 00212: input int scenario_id, 00213: input int stream_id); 00214: status = vmm_rw::ERROR; 00215: 00216: if (!this.rw_exec.exists(domain)) begin 00218: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.log.text($psprintf("No transactor available to physically access domain \"%s\".", : domain))); : this.log.end_msg(); : end : while (0); 00219: return; 00220: end 00221: 00223: : do : if (this.log.start_msg(vmm_log::DEBUG_TYP, vmm_log::TRACE_SEV)) begin : void'(this.log.text($psprintf("Writing 'h%h at 'h%h via domain \"%s\"...", : data, addr, domain))); : this.log.end_msg(); : end : while (0); 00224: 00225: begin 00226: vmm_rw_access rw = new; 00227: 00228: rw.data_id = data_id; 00229: rw.scenario_id = scenario_id; 00230: rw.stream_id = stream_id; 00231: 00232: rw.kind = vmm_rw::WRITE; 00233: rw.addr = addr; 00234: rw.data = data; 00235: rw.n_bits = n_bits; 00236: this.rw_exec[domain].exec_chan.put(rw); 00237: 00238: status = rw.status; 00239: end 00240: endtask: write 00241: 00242: 00243: task vmm_ral_access::read(output vmm_rw::status_e status, 00244: input bit [64-1:0] addr, 00245: output bit [64-1:0] data, 00246: input int n_bits, 00247: input string domain, 00248: input int data_id, 00249: input int scenario_id, 00250: input int stream_id); 00251: status = vmm_rw::ERROR; 00252: 00253: if (!this.rw_exec.exists(domain)) begin 00255: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.log.text($psprintf("No transactor available to physically access domain \"%s\".", : domain))); : this.log.end_msg(); : end : while (0); 00256: return; 00257: end 00258: 00259: begin 00260: vmm_rw_access rw = new; 00261: 00262: rw.data_id = data_id; 00263: rw.scenario_id = scenario_id; 00264: rw.stream_id = stream_id; 00265: 00266: rw.kind = vmm_rw::READ; 00267: rw.addr = addr; 00268: rw.n_bits = n_bits; 00269: this.rw_exec[domain].exec_chan.put(rw); 00270: 00271: data = rw.data; 00272: status = rw.status; 00273: end 00274: 00276: : do : if (this.log.start_msg(vmm_log::DEBUG_TYP, vmm_log::TRACE_SEV)) begin : void'(this.log.text($psprintf("Read 'h%h from 'h%h via domain \"%s\"...", : data, addr, domain))); : this.log.end_msg(); : end : while (0); 00277: 00278: endtask: read 00279: 00280: 00281: task vmm_ral_access::burst_write(output vmm_rw::status_e status, 00282: input bit [64-1:0] start, 00283: input bit [64-1:0] incr, 00284: input bit [64-1:0] max, 00285: input bit [64-1:0] data[], 00286: input vmm_data user, 00287: input int n_bits, 00288: input string domain, 00289: input int data_id, 00290: input int scenario_id, 00291: input int stream_id); 00292: status = vmm_rw::ERROR; 00293: 00294: if (!this.rw_exec.exists(domain)) begin 00296: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.log.text($psprintf("No transactor available to physically access domain \"%s\".", : domain))); : this.log.end_msg(); : end : while (0); 00297: return; 00298: end 00299: 00300: begin 00301: vmm_rw_burst rw = new; 00302: 00303: rw.data_id = data_id; 00304: rw.scenario_id = scenario_id; 00305: rw.stream_id = stream_id; 00306: 00307: rw.kind = vmm_rw::WRITE; 00308: rw.addr = start; 00309: rw.incr_addr = incr; 00310: rw.max_addr = max; 00311: rw.n_beats = data.size(); 00312: rw.n_bits = n_bits; 00313: rw.user_data = user; 00314: 00315: rw.data = new [rw.n_beats]; 00316: foreach (data[i]) rw.data[i] = data[i]; 00317: 00318: this.rw_exec[domain].exec_chan.put(rw); 00319: 00320: status = rw.status; 00321: end 00322: 00324: : do : if (this.log.start_msg(vmm_log::DEBUG_TYP, vmm_log::TRACE_SEV)) begin : void'(this.log.text($psprintf("Burst-wrote %0d data from ['h%h+'h%h %%'h%h] via domain \"%s\"...", : data.size(), start, incr, max, domain))); : this.log.end_msg(); : end : while (0); 00325: 00326: endtask: burst_write 00327: 00328: 00329: task vmm_ral_access::burst_read(output vmm_rw::status_e status, 00330: input bit [64-1:0] start, 00331: input bit [64-1:0] incr, 00332: input bit [64-1:0] max, 00333: input int n_beats, 00334: output bit [64-1:0] data[], 00335: input vmm_data user, 00336: input int n_bits, 00337: input string domain, 00338: input int data_id, 00339: input int scenario_id, 00340: input int stream_id); 00341: status = vmm_rw::ERROR; 00342: 00343: if (!this.rw_exec.exists(domain)) begin 00345: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.log.text($psprintf("No transactor available to physically access domain \"%s\".", : domain))); : this.log.end_msg(); : end : while (0); 00346: return; 00347: end 00348: 00349: begin 00350: vmm_rw_burst rw = new; 00351: 00352: rw.data_id = data_id; 00353: rw.scenario_id = scenario_id; 00354: rw.stream_id = stream_id; 00355: 00356: rw.kind = vmm_rw::READ; 00357: rw.addr = start; 00358: rw.incr_addr = incr; 00359: rw.max_addr = max; 00360: rw.n_beats = n_beats; 00361: rw.n_bits = n_bits; 00362: rw.user_data = user; 00363: 00364: this.rw_exec[domain].exec_chan.put(rw); 00365: 00366: data = new [rw.data.size()]; 00367: foreach (data[i]) data[i] = rw.data[i]; 00368: status = rw.status; 00369: end 00370: 00372: : do : if (this.log.start_msg(vmm_log::DEBUG_TYP, vmm_log::TRACE_SEV)) begin : void'(this.log.text($psprintf("Burst-read %0d data from ['h%h+'h%h %%'h%h] via domain \"%s\"...", : data.size(), start, incr, max, domain))); : this.log.end_msg(); : end : while (0); 00373: 00374: endtask: burst_read 00375: 00376: 00377: function bit vmm_ral_access::set_by_name(string name, 00378: bit [64-1:0] value); 00379: vmm_ral_reg rg; 00380: 00381: set_by_name = 0; 00382: rg = this.model.get_reg_by_name(name); 00383: if (rg == null) return 0; 00384: 00385: rg.set(value); 00386: set_by_name = 1; 00387: endfunction: set_by_name 00388: 00389: 00390: function bit vmm_ral_access::get_by_name(input string name, 00391: output bit [64-1:0] value); 00392: vmm_ral_reg rg; 00393: 00394: get_by_name = 0; 00395: rg = this.model.get_reg_by_name(name); 00396: if (rg == null) return 0; 00397: 00398: value = rg.get(); 00399: get_by_name = 1; 00400: endfunction: get_by_name 00401: 00402: 00403: task vmm_ral_access::write_by_name(output vmm_rw::status_e status, 00404: input string name, 00405: input bit [64-1:0] data, 00406: input vmm_ral::path_e path, 00407: input string domain, 00408: input int data_id, 00409: input int scenario_id, 00410: input int stream_id); 00411: vmm_ral_reg rg; 00412: 00413: status = vmm_rw::ERROR; 00414: rg = this.model.get_reg_by_name(name); 00415: if (rg == null) return; 00416: 00417: rg.write(status, data, path, domain, data_id, scenario_id, stream_id); 00418: endtask: write_by_name 00419: 00420: 00421: task vmm_ral_access::read_by_name(output vmm_rw::status_e status, 00422: input string name, 00423: output bit [64-1:0] data, 00424: input vmm_ral::path_e path, 00425: input string domain, 00426: input int data_id, 00427: input int scenario_id, 00428: input int stream_id); 00429: vmm_ral_reg rg; 00430: 00431: status = vmm_rw::ERROR; 00432: rg = this.model.get_reg_by_name(name); 00433: if (rg == null) return; 00434: 00435: rg.read(status, data, path, domain, data_id, scenario_id, stream_id); 00436: endtask: read_by_name 00437: 00438: 00439: task vmm_ral_access::write_mem_by_name(output vmm_rw::status_e status, 00440: input string name, 00441: input bit [64-1:0] offset, 00442: input bit [64-1:0] data, 00443: input vmm_ral::path_e path, 00444: input string domain, 00445: input int data_id, 00446: input int scenario_id, 00447: input int stream_id); 00448: vmm_ral_mem mem; 00449: 00450: status = vmm_rw::ERROR; 00451: mem = this.model.get_mem_by_name(name); 00452: if (mem == null) return; 00453: 00454: mem.write(status, offset, data, path, domain, data_id, scenario_id, stream_id); 00455: endtask: write_mem_by_name 00456: 00457: 00458: task vmm_ral_access::read_mem_by_name(output vmm_rw::status_e status, 00459: input string name, 00460: input bit [64-1:0] offset, 00461: output bit [64-1:0] data, 00462: input vmm_ral::path_e path, 00463: input string domain, 00464: input int data_id, 00465: input int scenario_id, 00466: input int stream_id); 00467: vmm_ral_mem mem; 00468: 00469: status = vmm_rw::ERROR; 00470: mem = this.model.get_mem_by_name(name); 00471: if (mem == null) return; 00472: 00473: mem.read(status, offset, data, path, domain, data_id, scenario_id, stream_id); 00474: endtask: read_mem_by_name 00475: 00476: 00477: // 00478: // Identify the sequence of addresses that must be accessed physically 00479: // to access the specified number of bytes at the specified address 00480: // within the specified block or system. Returns the number of bytes 00481: // of valid data in each access. 00482: // 00483: // Returns a list of address in little endian order, with the granularity 00484: // of the top-level system 00485: // 00486: // A register is specified as a base address with mem_indx == 0. 00487: // A location within a memory is specified as an index from a base address. 00488: // 00489: function int vmm_ral_access::Xget_physical_addressesX(bit [64-1:0] base_addr, 00490: bit [64-1:0] mem_offset, 00491: int unsigned n_bytes, 00492: vmm_ral_block_or_sys in_block, 00493: string domain, 00494: ref bit [64-1:0] addr[]); 00495: int bus_width = in_block.get_n_bytes(domain); 00496: bit [64-1:0] local_addr[]; 00497: vmm_ral_block_or_sys parent = in_block.get_parent(); 00498: 00499: addr = new [0]; 00500: 00501: if (n_bytes <= 0) begin 00503: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::FATAL_SEV)) begin : void'(this.log.text($psprintf("Cannot access %0d bytes. Must be greater than 0", : n_bytes))); : this.log.end_msg(); : end : while (0); 00504: return 0; 00505: end 00506: 00507: // First, identify the addresses within the block/system 00508: if (n_bytes <= bus_width) begin 00509: local_addr = new [1]; 00510: local_addr[0] = base_addr + mem_offset; 00511: end else begin 00512: int n; 00513: 00514: n = ((n_bytes-1) / bus_width) + 1; 00515: local_addr = new [n]; 00516: 00517: base_addr = base_addr + mem_offset * n; 00518: 00519: case (in_block.get_endian(domain)) 00520: vmm_ral::LITTLE_ENDIAN: begin 00521: foreach (local_addr[i]) begin 00522: local_addr[i] = base_addr + i; 00523: end 00524: end 00525: vmm_ral::BIG_ENDIAN: begin 00526: foreach (local_addr[i]) begin 00527: n--; 00528: local_addr[i] = base_addr + n; 00529: end 00530: end 00531: vmm_ral::LITTLE_FIFO: begin 00532: foreach (local_addr[i]) begin 00533: local_addr[i] = base_addr; 00534: end 00535: end 00536: vmm_ral::BIG_FIFO: begin 00537: foreach (local_addr[i]) begin 00538: local_addr[i] = base_addr; 00539: end 00540: end 00541: default: begin 00543: : do : if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin : void'(this.log.text($psprintf("Block has no specified endianness. Cannot access %0d bytes register via its %0d byte \"%s\" interface", : n_bytes, in_block.get_n_bytes(domain), domain))); : this.log.end_msg(); : end : while (0); 00544: end 00545: endcase 00546: end 00547: 00548: 00549: // Then translate these addresses in the parent's space 00550: if (parent == null) begin 00551: // This is the top-most system/block! 00552: addr = new [local_addr.size()] (local_addr); 00553: end else begin 00554: bit [64-1:0] sys_addr[]; 00555: bit [64-1:0] base_addr; 00556: string up_domain; 00557: int w, k; 00558: 00559: up_domain = in_block.get_parent_domain(domain); 00560: 00561: // Scale the consecutive local address in the system's granularity 00562: if (bus_width < parent.get_n_bytes(up_domain)) k = 1; 00563: else k = ((bus_width-1) / parent.get_n_bytes(up_domain)) + 1; 00564: 00565: base_addr = in_block.get_base_addr(domain); 00566: foreach (local_addr[i]) begin 00567: int n = addr.size(); 00568: 00569: w = this.Xget_physical_addressesX(base_addr + local_addr[i] * k, 0, 00570: bus_width, parent, up_domain, 00571: sys_addr); 00572: 00573: addr = new [n + sys_addr.size()] (addr); 00574: foreach (sys_addr[j]) begin 00575: addr[n+j] = sys_addr[j]; 00576: end 00577: end 00578: // The width of each access is the minimum of this block or the system's width 00579: if (w < bus_width) bus_width = w; 00580: end 00581: 00582: Xget_physical_addressesX = bus_width; 00583: endfunction: Xget_physical_addressesX