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_sys_domain;
00024 vmm_ral_block blocks[$];
00025 string blk_domains[$];
00026 vmm_ral_sys subsys[$];
00027 string sys_domains[$];
00028 endclass
00029
00030
00031 class vmm_ral_sys extends vmm_ral_block_or_sys;
00032 local vmm_ral_sys_domain domains[];
00033
00034 extern function new(
00035 vmm_ral_sys parent = null,
00036 string name,
00037 string typename,
00038 int unsigned n_bytes,
00039 vmm_ral::endianness_e endian,
00040 bit [`VMM_RAL_ADDR_WIDTH-1:0] base_addr = 0,
00041 string domain = "",
00042 int cover_on = vmm_ral::NO_COVERAGE,
00043 int has_cover = vmm_ral::NO_COVERAGE);
00044
00045 /*local*/ extern virtual function void Xlock_modelX();
00046 /*local*/ extern virtual function void add_domain(int unsigned n_bytes,
00047 vmm_ral::endianness_e endian,
00048 string domain);
00049 /*local*/ extern function void register_block(vmm_ral_block block,
00050 string domain = "",
00051 string in_domain = "",
00052 bit [`VMM_RAL_ADDR_WIDTH-1:0] base_addr);
00053 /*local*/ extern function void register_subsys(vmm_ral_sys subsys,
00054 string domain = "",
00055 string in_domain = "",
00056 bit [`VMM_RAL_ADDR_WIDTH-1:0]base_addr);
00057 /*local*/ extern virtual function void Xregister_ral_accessX(vmm_ral_access access);
00058
00059 extern virtual function string psdisplay(string prefix = "",
00060 string domain = "");
00061
00062 extern virtual function void get_fields(ref vmm_ral_field fields[],
00063 input string domain = "");
00064 extern virtual function void get_virtual_fields(ref vmm_ral_vfield fields[],
00065 input string domain = "");
00066 extern virtual function vmm_ral_field get_field_by_name(string name);
00067 extern virtual function vmm_ral_vfield get_virtual_field_by_name(string name);
00068
00069 extern virtual function void get_registers(ref vmm_ral_reg regs[],
00070 input string domain = "");
00071 extern virtual function void get_virtual_registers(ref vmm_ral_vreg vregs[],
00072 input string domain = "");
00073 extern virtual function vmm_ral_reg get_reg_by_name(string name);
00074 extern virtual function vmm_ral_vreg get_vreg_by_name(string name);
00075
00076 extern local function vmm_ral_reg Xget_reg_by_offsetX(bit [`VMM_RAL_ADDR_WIDTH-1:0] offset,
00077 string domain = "");
00078
00079 extern virtual function vmm_ral_reg get_reg_by_offset(bit [`VMM_RAL_ADDR_WIDTH-1:0] offset,
00080 string domain = "");
00081 extern virtual function vmm_ral_vreg get_vreg_by_offset(bit [`VMM_RAL_ADDR_WIDTH-1:0] offset,
00082 string domain = "");
00083
00084 extern virtual function void get_memories(ref vmm_ral_mem mems[],
00085 input string domain = "");
00086 extern virtual function vmm_ral_mem get_mem_by_name(string name);
00087 extern virtual function vmm_ral_mem get_mem_by_offset(bit [`VMM_RAL_ADDR_WIDTH-1:0] offset,
00088 string domain = "");
00089
00090 extern virtual function void get_blocks(ref vmm_ral_block blocks[],
00091 ref string domains[],
00092 input string domain = "");
00093 extern virtual function void get_all_blocks(ref vmm_ral_block blocks[],
00094 ref string domains[],
00095 input string domain = "");
00096 extern virtual function vmm_ral_block get_block_by_name(string name);
00097 extern virtual function vmm_ral_block get_block_by_offset(bit [`VMM_RAL_ADDR_WIDTH-1:0] offset,
00098 string domain = "");
00099
00100 extern virtual function void get_subsys(ref vmm_ral_sys subsys[],
00101 ref string domains[],
00102 input string domain = "");
00103 extern virtual function void get_all_subsys(ref vmm_ral_sys subsys[],
00104 ref string domains[],
00105 input string domain = "");
00106 extern virtual function vmm_ral_sys get_subsys_by_name(string name);
00107 extern virtual function vmm_ral_sys get_subsys_by_offset(bit [`VMM_RAL_ADDR_WIDTH-1:0] offset,
00108 string domain = "");
00109
00110 extern virtual function void power_down(bit retain = 0);
00111 extern virtual function void power_up(string power_domains = "");
00112
00113 extern function int set_cover(int is_on);
00114
00115 extern virtual function void reset(string domain = "",
00116 vmm_ral::reset_e kind = vmm_ral::HARD);
00117 extern virtual function bit needs_update();
00118
00119 extern virtual task update(output vmm_rw::status_e status,
00120 input vmm_ral::path_e path = vmm_ral::DEFAULT);
00121 extern virtual task mirror(output vmm_rw::status_e status,
00122 input vmm_ral::check_e check = vmm_ral:: QUIET,
00123 input vmm_ral::path_e path = vmm_ral::DEFAULT);
00124
00125 extern virtual task readmemh(string filename);
00126 extern virtual task writememh(string filename);
00127
00128 extern function int unsigned get_sys_ID();
00129
00130 extern virtual function int unsigned get_block_or_sys_size(string domain = "");
00131
00132 extern virtual function bit set_offset(bit [`VMM_RAL_ADDR_WIDTH-1:0] offset,
00133 string domain = "");
00134
00135
00136 extern virtual function bit Xcheck_child_overlapX(int unsigned my_offset,
00137 int unsigned my_size,
00138 string domain = "",
00139 vmm_ral_block blk,
00140 vmm_ral_sys sys);
00141
00142
00143
00144 endclass: vmm_ral_sys
00145
00146
00147 function vmm_ral_sys::new(vmm_ral_sys parent = null,
00148 string name,
00149 string typename,
00150 int unsigned n_bytes,
00151 vmm_ral::endianness_e endian,
00152 bit [`VMM_RAL_ADDR_WIDTH-1:0] base_addr = 0,
00153 string domain = "",
00154 int cover_on = vmm_ral::NO_COVERAGE,
00155 int has_cover = vmm_ral::NO_COVERAGE);
00156 super.new(parent, "RAL System", name, typename,
00157 n_bytes, endian, base_addr, domain,
00158 cover_on, has_cover);
00159
00160 this.domains = new [1];
00161 this.domains[0] = new;
00162 endfunction: new
00163
00164
00165 function void vmm_ral_sys::Xlock_modelX();
00166 if (this.Xis_lockedX()) return;
00167
00168 super.Xlock_modelX();
00169 foreach (this.domains[i]) begin
00170 foreach (this.domains[i].blocks[j]) begin
00171 this.domains[i].blocks[j].Xlock_modelX();
00172 end
00173 foreach (this.domains[i].subsys[j]) begin
00174 this.domains[i].subsys[j].Xlock_modelX();
00175 end
00176 end
00177 endfunction: Xlock_modelX
00178
00179
00180 function void vmm_ral_sys::add_domain(int unsigned n_bytes,
00181 vmm_ral::endianness_e endian,
00182 string domain);
00183 int n;
00184
00185 super.add_domain(n_bytes, endian, domain);
00186
00187 n = this.domains.size();
00188 this.domains = new [n+1] (this.domains);
00189 this.domains[n] = new;
00190 endfunction: add_domain
00191
00192
00193 function void vmm_ral_sys::register_block(vmm_ral_block block,
00194 string domain = "",
00195 string in_domain = "",
00196 bit [`VMM_RAL_ADDR_WIDTH-1:0] base_addr);
00197 string doms[];
00198 vmm_ral_sys_domain dom;
00199
00200 if (this.Xis_lockedX()) begin
00201 `vmm_error(this.log, "Cannot add block to locked system model");
00202 return;
00203 end
00204
00205 block.get_domains(doms);
00206 foreach (doms[i]) begin
00207 if (doms[i] == domain) begin
00208 int j = this.get_domain_index(in_domain);
00209 if (j < 0) return;
00210
00211 dom = this.domains[j];
00212 dom.blocks.push_back(block);
00213 dom.blk_domains.push_back(domain);
00214
00215 begin
00216 int k;
00217 j = this.get_n_bytes(in_domain);
00218 k = block.get_n_bytes(domain);
00219 if (k > j) begin
00220 `vmm_warning(this.log, $psprintf("%0d-byte block %s.%s instantiated in %0d-byte system %s.%s",
00221 k, block.get_name(), domain,
00222 j, this.get_name(), in_domain));
00223 end
00224 end
00225
00226 block.map_domain(domain, in_domain, base_addr);
00227
00228 return;
00229 end
00230 end
00231
00232 `vmm_error(this.log, $psprintf("Domain \"%s\" not found in block \"%s\".",
00233 domain, block.get_name()));
00234 endfunction: register_block
00235
00236
00237
00238 function void vmm_ral_sys::register_subsys(vmm_ral_sys subsys,
00239 string domain = "",
00240 string in_domain = "",
00241 bit [`VMM_RAL_ADDR_WIDTH-1:0] base_addr);
00242 string doms[];
00243 vmm_ral_sys_domain dom;
00244 int i;
00245
00246 if (this.Xis_lockedX()) begin
00247 `vmm_error(this.log, "Cannot add subsystem to locked system model");
00248 return;
00249 end
00250
00251 subsys.get_domains(doms);
00252 foreach (doms[i]) begin
00253 if (doms[i] == domain) begin
00254 int j = this.get_domain_index(in_domain);
00255 if (j < 0) return;
00256
00257 dom = this.domains[j];
00258 dom.subsys.push_back(subsys);
00259 dom.sys_domains.push_back(domain);
00260
00261 begin
00262 int k;
00263 j = this.get_n_bytes(in_domain);
00264 k = subsys.get_n_bytes(domain);
00265 if (k > j) begin
00266 `vmm_warning(this.log, $psprintf("%0d-byte system %s.%s instantiated in %0d-byte system %s.%s",
00267 k, subsys.get_name(), domain,
00268 j, this.get_name(), in_domain));
00269 end
00270 end
00271
00272 subsys.map_domain(domain, in_domain, base_addr);
00273
00274 return;
00275 end
00276 end
00277
00278 `vmm_error(this.log, $psprintf("Domain \"%s\" not found in system \"%s\".",
00279 domain, subsys.get_fullname()));
00280 endfunction: register_subsys
00281
00282
00283 function void vmm_ral_sys::Xregister_ral_accessX(vmm_ral_access access);
00284 // There can only be one RAL Access on a RAL model
00285 if (this.ral_access != null && this.ral_access != access) begin
00286 `vmm_fatal(this.log, $psprintf("System %s is already used by another RAL access instance", this.get_fullname()));
00287 end
00288 this.ral_access = access;
00289
00290 // Register all sub-elements
00291 begin
00292 vmm_ral_sys sys[];
00293 vmm_ral_block blks[];
00294 string domains[];
00295
00296 this.get_subsys(sys, domains);
00297 foreach (sys[i]) begin
00298 sys[i].Xregister_ral_accessX(access);
00299 end
00300
00301 this.get_blocks(blks, domains);
00302 foreach (blks[i]) begin
00303 blks[i].Xregister_ral_accessX(access);
00304 end
00305 end
00306 endfunction: Xregister_ral_accessX
00307
00308
00309 function string vmm_ral_sys::psdisplay(string prefix = "",
00310 string domain = "");
00311 string image;
00312 string domains[];
00313 string blk_domains[];
00314 vmm_ral_sys sys[];
00315 vmm_ral_block blks[];
00316 bit single_domain;
00317 vmm_ral::endianness_e endian;
00318
00319 single_domain = 1;
00320 if (domain == "") begin
00321 this.get_domains(domains);
00322 if (domains.size() > 1) single_domain = 0;
00323 end
00324
00325 if (single_domain) begin
00326 $sformat(image, "%sSystem %s", prefix, this.get_fullname());
00327 if (domain != "") $sformat(image, "%s.%s", image, domain);
00328 endian = this.get_endian(domain);
00329 $sformat(image, "%s -- %0d bytes (%s)", image,
00330 this.get_n_bytes(domain), endian.name());
00331
00332 this.get_blocks(blks, blk_domains, domain);
00333 foreach (blks[i]) begin
00334 string img;
00335 img = blks[i].psdisplay({prefix, " "}, blk_domains[i]);
00336 image = {image, "\n", img};
00337 end
00338
00339 this.get_subsys(sys, blk_domains, domain);
00340 foreach (sys[i]) begin
00341 string img;
00342 img = sys[i].psdisplay({prefix, " "}, blk_domains[i]);
00343 image = {image, "\n", img};
00344 end
00345 end
00346 else begin
00347 $sformat(image, "%sSystem %s", prefix, this.get_fullname());
00348 foreach (domains[i]) begin
00349 string img;
00350 endian = this.get_endian(domains[i]);
00351 $sformat(img, "%s Domain \"%s\" -- %0d bytes (%s)",
00352 prefix, domains[i],
00353 this.get_n_bytes(domains[i]), endian.name());
00354 image = {image, "\n", img};
00355
00356 this.get_blocks(blks, blk_domains, domains[i]);
00357 foreach (blks[j]) begin
00358 img = blks[j].psdisplay({prefix, " "},
00359 blk_domains[j]);
00360 image = {image, "\n", img};
00361 end
00362
00363 this.get_subsys(sys, blk_domains, domains[i]);
00364 foreach (sys[j]) begin
00365 img = sys[j].psdisplay({prefix, " "},
00366 blk_domains[j]);
00367 image = {image, "\n", img};
00368 end
00369 end
00370 end
00371 return image;
00372 endfunction: psdisplay
00373
00374
00375 function void vmm_ral_sys::get_fields(ref vmm_ral_field fields[],
00376 input string domain = "");
00377 int n;
00378 vmm_ral_block b[];
00379 string d[];
00380 vmm_ral_field f[];
00381
00382 this.get_all_blocks(b, d, domain);
00383 fields = new [0];
00384 foreach (b[i]) begin
00385 b[i].get_fields(f, d[i]);
00386 n = fields.size();
00387 fields = new [n + f.size()] (fields);
00388
00389 foreach (f[j]) begin
00390 fields[n++] = f[j];
00391 end
00392 end
00393 endfunction: get_fields
00394
00395 function void vmm_ral_sys::get_virtual_fields(ref vmm_ral_vfield fields[],
00396 input string domain = "");
00397 int n;
00398 vmm_ral_block b[];
00399 string d[];
00400 vmm_ral_vfield f[];
00401
00402 this.get_all_blocks(b, d, domain);
00403 fields = new [0];
00404 foreach (b[i]) begin
00405 b[i].get_virtual_fields(f, d[i]);
00406 n = fields.size();
00407 fields = new [n + f.size()] (fields);
00408
00409 foreach (f[j]) begin
00410 fields[n++] = f[j];
00411 end
00412 end
00413 endfunction: get_virtual_fields
00414
00415 function vmm_ral_field vmm_ral_sys::get_field_by_name(string name);
00416 // Search the registers to find the first field of the specified name
00417 vmm_ral_reg r[];
00418
00419 this.get_registers(r);
00420 foreach (r[i]) begin
00421 vmm_ral_field fields[];
00422 r[i].get_fields(fields);
00423 foreach (fields[j]) begin
00424 if (fields[j].get_name() == name) begin
00425 return fields[j];
00426 end
00427 end
00428 end
00429 `vmm_warning(this.log, $psprintf("Unable to locate field \"%s\" in system \"%s\".",
00430 name, this.get_fullname()));
00431 get_field_by_name = null;
00432 endfunction: get_field_by_name
00433
00434 function vmm_ral_vfield vmm_ral_sys::get_virtual_field_by_name(string name);
00435 // Search the registers to find the first field of the specified name
00436 vmm_ral_vreg r[];
00437
00438 this.get_virtual_registers(r);
00439 foreach (r[i]) begin
00440 vmm_ral_vfield fields[];
00441 r[i].get_fields(fields);
00442 foreach (fields[j]) begin
00443 if (fields[j].get_name() == name) begin
00444 return fields[j];
00445 end
00446 end
00447 end
00448 `vmm_warning(this.log, $psprintf("Unable to locate virtual field \"%s\" in system \"%s\".",
00449 name, this.get_fullname()));
00450 get_virtual_field_by_name = null;
00451 endfunction: get_virtual_field_by_name
00452
00453 function void vmm_ral_sys::get_registers(ref vmm_ral_reg regs[],
00454 input string domain = "");
00455 vmm_ral_block blks[];
00456 string d[];
00457
00458 regs = new [0];
00459
00460 this.get_all_blocks(blks, d, domain);
00461 foreach (blks[i]) begin
00462 int n = regs.size();
00463 vmm_ral_reg rg[];
00464
00465 blks[i].get_registers(rg, d[i]);
00466 regs = new [n + rg.size()] (regs);
00467
00468 foreach (rg[j]) begin
00469 regs[n+j] = rg[j];
00470 end
00471 end
00472 endfunction: get_registers
00473
00474 function void vmm_ral_sys::get_virtual_registers(ref vmm_ral_vreg vregs[],
00475 input string domain = "");
00476 vmm_ral_block blks[];
00477 string d[];
00478
00479 vregs = new [0];
00480
00481 this.get_all_blocks(blks, d, domain);
00482 foreach (blks[i]) begin
00483 int n = vregs.size();
00484 vmm_ral_vreg rg[];
00485
00486 blks[i].get_virtual_registers(rg, d[i]);
00487 vregs = new [n + rg.size()] (vregs);
00488
00489 foreach (rg[j]) begin
00490 vregs[n+j] = rg[j];
00491 end
00492 end
00493 endfunction: get_virtual_registers
00494
00495 function vmm_ral_reg vmm_ral_sys::get_reg_by_name(string name);
00496 // Search the registers to find the first of the specified name
00497 vmm_ral_reg r[];
00498
00499 this.get_registers(r);
00500 foreach (r[i]) begin
00501 if (r[i].get_name() == name) begin
00502 return r[i];
00503 end
00504 end
00505 `vmm_warning(this.log, $psprintf("Unable to locate register \"%s\" in system \"%s\".",
00506 name, this.get_fullname()));
00507 get_reg_by_name = null;
00508 endfunction: get_reg_by_name
00509
00510 function vmm_ral_vreg vmm_ral_sys::get_vreg_by_name(string name);
00511 // Search the registers to find the first of the specified name
00512 vmm_ral_vreg r[];
00513
00514 this.get_virtual_registers(r);
00515 foreach (r[i]) begin
00516 if (r[i].get_name() == name) begin
00517 return r[i];
00518 end
00519 end
00520 `vmm_warning(this.log, $psprintf("Unable to locate virtual register \"%s\" in system \"%s\".",
00521 name, this.get_fullname()));
00522 get_vreg_by_name = null;
00523 endfunction: get_vreg_by_name
00524
00525
00526 function vmm_ral_reg vmm_ral_sys::Xget_reg_by_offsetX(bit [`VMM_RAL_ADDR_WIDTH-1:0] offset,
00527 string domain = "");
00528 vmm_ral_sys_domain dom; int unsigned my_n_bytes;
00529 int j = this.get_domain_index(domain);
00530 if (j < 0) begin
00531 `vmm_warning(this.log, $psprintf("Unable to locate domain \"%s\" in System \"%s\".",
00532 domain, this.get_fullname()));
00533 return null;
00534 end
00535 my_n_bytes = this.get_n_bytes(domain);
00536 dom = this.domains[j];
00537
00538 // Look inside all blocks...
00539 foreach (dom.blocks[i]) begin
00540 bit [`VMM_RAL_ADDR_WIDTH-1:0] tmp_offset = dom.blocks[i].get_base_addr(dom.blk_domains[i]);
00541 if (tmp_offset <= offset) begin
00542 `ifdef VMM_RAL_FAST_SRCH
00543 int unsigned blk_n_bytes = dom.blocks[i].get_n_bytes(dom.blk_domains[i]);
00544 bit [`VMM_RAL_ADDR_WIDTH-1:0] reg_offset = offset - tmp_offset;
00545 int unsigned multiplier = (((blk_n_bytes-1)/my_n_bytes)+1);
00546
00547 if ((reg_offset % multiplier) == 0) begin
00548 vmm_ral_reg_by_offset_map reg_map = dom.blocks[i].Xget_reg_by_offset_mapX(dom.blk_domains[i]);
00549 bit [`VMM_RAL_ADDR_WIDTH-1:0] reg_offset_in_blk = reg_offset / multiplier;
00550 if (reg_map.reg_by_offset.exists(reg_offset_in_blk))
00551 return reg_map.reg_by_offset[reg_offset_in_blk];
00552 end
00553 `else
00554 vmm_ral_reg regs[];
00555 int unsigned blk_n_bytes = dom.blocks[i].get_n_bytes(dom.blk_domains[i]);
00556 bit [`VMM_RAL_ADDR_WIDTH-1:0] reg_offset = offset - tmp_offset;
00557 dom.blocks[i].get_registers(regs, dom.blk_domains[i]);
00558 foreach (regs[k]) begin
00559 if ((regs[k].get_offset_in_block(dom.blk_domains[i]) *
00560 (((blk_n_bytes-1)/my_n_bytes)+1)) == reg_offset)
00561 return regs[k];
00562 end
00563 `endif
00564 end
00565 end
00566
00567 // Look inside all sub-systems...
00568 foreach (dom.subsys[i]) begin
00569 bit [`VMM_RAL_ADDR_WIDTH-1:0] tmp_offset = dom.subsys[i].get_base_addr(dom.sys_domains[i]);
00570 if (tmp_offset <= offset) begin
00571 vmm_ral_reg rg;
00572 bit [`VMM_RAL_ADDR_WIDTH-1:0] reg_offset = offset - tmp_offset;
00573 int unsigned sys_n_bytes = dom.subsys[i].get_n_bytes(dom.sys_domains[i]);
00574 if (sys_n_bytes > my_n_bytes) begin
00575 reg_offset = reg_offset / (((sys_n_bytes-1)/my_n_bytes)+1);
00576 end
00577 rg = dom.subsys[i].Xget_reg_by_offsetX(reg_offset, dom.sys_domains[i]);
00578 if (rg) return rg;
00579 end
00580 end
00581
00582 Xget_reg_by_offsetX = null;
00583 endfunction: Xget_reg_by_offsetX
00584
00585
00586 function vmm_ral_reg vmm_ral_sys::get_reg_by_offset(bit [`VMM_RAL_ADDR_WIDTH-1:0] offset,
00587 string domain = "");
00588 vmm_ral_reg rg = this.Xget_reg_by_offsetX(offset, domain);
00589
00590 if (rg) return rg;
00591
00592 `vmm_warning(this.log, $psprintf("Unable to locate register at offset 0x%h %0sin system \"%s\".",
00593 offset, ((domain == "") ? "" : $psprintf("in domain \"%s\" ",
00594 domain)), this.get_fullname()));
00595 get_reg_by_offset = null;
00596 endfunction: get_reg_by_offset
00597
00598
00599 function vmm_ral_vreg vmm_ral_sys::get_vreg_by_offset(bit [`VMM_RAL_ADDR_WIDTH-1:0] offset,
00600 string domain = "");
00601 return null;
00602 endfunction: get_vreg_by_offset
00603
00604 function void vmm_ral_sys::get_memories(ref vmm_ral_mem mems[],
00605 input string domain = "");
00606 vmm_ral_block blks[];
00607 string d[];
00608
00609 mems = new [0];
00610
00611 this.get_all_blocks(blks, d, domain);
00612 foreach (blks[i]) begin
00613 integer n = mems.size();
00614 vmm_ral_mem mm[];
00615
00616 blks[i].get_memories(mm, domain);
00617 mems = new [n + mm.size()] (mems);
00618
00619 foreach (mm[j]) begin
00620 mems[n+j] = mm[j];
00621 end
00622 end
00623 endfunction: get_memories
00624
00625
00626 function vmm_ral_mem vmm_ral_sys::get_mem_by_name(string name);
00627 // Search the memories to find the first of the specified name
00628 vmm_ral_mem m[];
00629
00630 this.get_memories(m);
00631 foreach (m[i]) begin
00632 if (m[i].get_name() == name) begin
00633 return m[i];
00634 end
00635 end
00636 `vmm_warning(this.log, $psprintf("Unable to locate memory \"%s\" in system \"%s\".",
00637 name, this.get_fullname()));
00638 get_mem_by_name = null;
00639 endfunction: get_mem_by_name
00640
00641
00642 function vmm_ral_mem vmm_ral_sys::get_mem_by_offset(bit [`VMM_RAL_ADDR_WIDTH-1:0] offset,
00643 string domain = "");
00644 return null;
00645 endfunction: get_mem_by_offset
00646
00647
00648 function void vmm_ral_sys::get_blocks(ref vmm_ral_block blocks[],
00649 ref string domains[],
00650 input string domain = "");
00651 if (domain == "" && this.domains.size() > 1) begin
00652 blocks = new [0];
00653 domains = new [0];
00654
00655 foreach (this.domains[i]) begin
00656 int n = blocks.size();
00657
00658 blocks = new [n + this.domains[i].blocks.size()] (blocks);
00659 domains = new [n + this.domains[i].blocks.size()] (domains);
00660
00661 foreach (this.domains[i].blocks[j]) begin
00662 blocks[n+j] = this.domains[i].blocks[j];
00663 domains[n+j] = this.domains[i].blk_domains[j];
00664 end
00665 end
00666 end
00667 else begin
00668 vmm_ral_sys_domain dom;
00669 int i;
00670
00671 i = this.get_domain_index(domain);
00672 if (i < 0) return;
00673
00674 dom = this.domains[i];
00675 blocks = new [dom.blocks.size()];
00676 domains = new [dom.blocks.size()];
00677
00678 foreach (dom.blocks[j]) begin
00679 blocks[j] = dom.blocks[j];
00680 domains[j] = dom.blk_domains[j];
00681 end
00682 end
00683 endfunction: get_blocks
00684
00685
00686 function void vmm_ral_sys::get_all_blocks(ref vmm_ral_block blocks[],
00687 ref string domains[],
00688 input string domain = "");
00689 vmm_ral_block blks[];
00690 vmm_ral_sys sys[];
00691 string doms[];
00692 string subdoms[];
00693
00694 this.get_blocks(blocks, domains, domain);
00695
00696 this.get_all_subsys(sys, subdoms, domain);
00697 foreach (sys[i]) begin
00698 int n = blocks.size();
00699
00700 sys[i].get_blocks(blks, doms, subdoms[i]);
00701 blocks = new [n + blks.size()] (blocks);
00702 domains = new [n + blks.size()] (domains);
00703
00704 foreach (blks[j]) begin
00705 blocks[n+j] = blks[j];
00706 domains[n+j] = doms[j];
00707 end
00708 end
00709 endfunction: get_all_blocks
00710
00711
00712 function vmm_ral_block vmm_ral_sys::get_block_by_name(string name);
00713 vmm_ral_block blks[];
00714 string d[];
00715
00716 this.get_all_blocks(blks, d);
00717 foreach (blks[i]) begin
00718 if (blks[i].get_name() == name) begin
00719 return blks[i];
00720 end
00721 end
00722 `vmm_warning(this.log, $psprintf("Unable to locate block \"%s\" in system \"%s\".",
00723 name, this.get_fullname()));
00724 get_block_by_name = null;
00725 endfunction: get_block_by_name
00726
00727
00728 function vmm_ral_block vmm_ral_sys::get_block_by_offset(bit [`VMM_RAL_ADDR_WIDTH-1:0] offset,
00729 string domain = "");
00730 return null;
00731 endfunction: get_block_by_offset
00732
00733
00734 function void vmm_ral_sys::get_subsys(ref vmm_ral_sys subsys[],
00735 ref string domains[],
00736 input string domain = "");
00737 if (domain == "" && this.domains.size() > 1) begin
00738 subsys = new [0];
00739 domains = new [0];
00740
00741 foreach (this.domains[i]) begin
00742 int n = subsys.size();
00743
00744 subsys = new [n + this.domains[i].subsys.size()] (subsys);
00745 domains = new [n + this.domains[i].subsys.size()] (domains);
00746
00747 foreach (this.domains[i].subsys[j]) begin
00748 subsys[n+j] = this.domains[i].subsys[j];
00749 domains[n+j] = this.domains[i].sys_domains[j];
00750 end
00751 end
00752 end
00753 else begin
00754 vmm_ral_sys_domain dom;
00755 int i;
00756
00757 i = this.get_domain_index(domain);
00758 if (i < 0) return;
00759
00760 dom = this.domains[i];
00761 subsys = new [dom.subsys.size()];
00762 domains = new [dom.subsys.size()];
00763
00764 foreach (dom.subsys[j]) begin
00765 subsys[j] = dom.subsys[j];
00766 domains[j] = dom.sys_domains[j];
00767 end
00768 end
00769 endfunction: get_subsys
00770
00771
00772 function void vmm_ral_sys::get_all_subsys(ref vmm_ral_sys subsys[],
00773 ref string domains[],
00774 input string domain = "");
00775 vmm_ral_sys sys[];
00776 string subdoms[];
00777 vmm_ral_sys ss[];
00778 string doms[];
00779
00780 subsys = new [0];
00781 domains = new[0];
00782
00783 this.get_subsys(sys, subdoms, domain);
00784
00785 foreach (sys[i]) begin
00786 int n = subsys.size() + 1;
00787
00788 sys[i].get_all_subsys(ss, doms, subdoms[i]);
00789 subsys = new [n + ss.size()] (subsys);
00790 domains = new [n + ss.size()] (domains);
00791
00792 subsys[n-1] = sys[i];
00793 domains[n-1] = subdoms[i];
00794
00795 foreach (ss[j]) begin
00796 subsys[n+j] = ss[j];
00797 domains[n+j] = doms[j];
00798 end
00799 end
00800 endfunction: get_all_subsys
00801
00802
00803 function vmm_ral_sys vmm_ral_sys::get_subsys_by_name(string name);
00804 vmm_ral_sys subsys[];
00805 string d[];
00806
00807 this.get_all_subsys(subsys, d);
00808 foreach (subsys[i]) begin
00809 if (subsys[i].get_name() == name) begin
00810 return subsys[i];
00811 end
00812 end
00813 `vmm_warning(this.log, $psprintf("Unable to locate subsystem \"%s\" in system \"%s\".",
00814 name, this.get_fullname()));
00815 get_subsys_by_name = null;
00816 endfunction: get_subsys_by_name
00817
00818
00819 function vmm_ral_sys vmm_ral_sys::get_subsys_by_offset(bit [`VMM_RAL_ADDR_WIDTH-1:0] offset,
00820 string domain = "");
00821 return null;
00822 endfunction: get_subsys_by_offset
00823
00824
00825 function void vmm_ral_sys::power_down(bit retain = 0);
00826 vmm_ral_block blks[];
00827 string domains[];
00828
00829 // Power down all blocks
00830 this.get_blocks(blks, domains);
00831 foreach (blks[i]) begin
00832 blks[i].power_down(retain);
00833 end
00834 endfunction: power_down
00835
00836
00837 function void vmm_ral_sys::power_up(string power_domains = "");
00838 vmm_ral_block blks[];
00839 string domains[];
00840 string pwr_domain;
00841
00842 if (power_domains != "") begin
00843 pwr_domain = this.get_attribute("POWER_DOMAIN");
00844 if (!`vmm_str_match(pwr_domain, power_domains)) return;
00845 end
00846
00847 // Power up blocks in the specified power domains
00848 this.get_blocks(blks, domains);
00849 foreach (blks[i]) begin
00850 if (power_domains != "") begin
00851 pwr_domain = blks[i].get_attribute("POWER_DOMAIN");
00852 if (!`vmm_str_match(pwr_domain, power_domains)) continue;
00853 end
00854 blks[i].power_up(power_domains);
00855 end
00856 endfunction: power_up
00857
00858
00859 function int vmm_ral_sys::set_cover(int is_on);
00860 int can_cvr;
00861
00862 set_cover = super.set_cover(is_on);
00863 can_cvr = is_on & set_cover;
00864 if (can_cvr == 0) return set_cover;
00865
00866 foreach (this.domains[i]) begin
00867 foreach (this.domains[i].blocks[j]) begin
00868 void'(this.domains[i].blocks[j].set_cover(can_cvr));
00869 end
00870 foreach (this.domains[i].subsys[j]) begin
00871 void'(this.domains[i].subsys[j].set_cover(can_cvr));
00872 end
00873 end
00874 endfunction: set_cover
00875
00876
00877 function void vmm_ral_sys::reset(string domain = "",
00878 vmm_ral::reset_e kind = vmm_ral::HARD);
00879 if (domain == "" && this.domains.size() > 1) begin
00880 foreach (this.domains[i]) begin
00881 foreach (this.domains[i].blocks[j]) begin
00882 this.domains[i].blocks[j].reset(this.domains[i].blk_domains[j],
00883 kind);
00884 end
00885 foreach (this.domains[i].subsys[j]) begin
00886 this.domains[i].subsys[j].reset(this.domains[i].sys_domains[j],
00887 kind);
00888 end
00889 end
00890 end
00891 else begin
00892 int i;
00893
00894 i = this.get_domain_index(domain);
00895 if (i < 0) return;
00896
00897 foreach (this.domains[i].blocks[j]) begin
00898 this.domains[i].blocks[j].reset(this.domains[i].blk_domains[j],
00899 kind);
00900 end
00901 foreach (this.domains[i].subsys[j]) begin
00902 this.domains[i].subsys[j].reset(this.domains[i].sys_domains[j],
00903 kind);
00904 end
00905 end
00906 endfunction: reset
00907
00908
00909 function bit vmm_ral_sys::needs_update();
00910 needs_update = 0;
00911 foreach (this.domains[i]) begin
00912 foreach (this.domains[i].blocks[j]) begin
00913 if (this.domains[i].blocks[j].needs_update()) begin
00914 return 1;
00915 end
00916 end
00917 foreach (this.domains[i].subsys[j]) begin
00918 if (this.domains[i].subsys[j].needs_update()) begin
00919 return 1;
00920 end
00921 end
00922 end
00923 return 0;
00924 endfunction: needs_update
00925
00926
00927 task vmm_ral_sys::update(output vmm_rw::status_e status,
00928 input vmm_ral::path_e path = vmm_ral::DEFAULT);
00929 status = vmm_rw::IS_OK;
00930 foreach (this.domains[i]) begin
00931 foreach (this.domains[i].blocks[j]) begin
00932 this.domains[i].blocks[j].update(status, path);
00933 if (status != vmm_rw::IS_OK) return;
00934 end
00935 foreach (this.domains[i].subsys[j]) begin
00936 this.domains[i].subsys[j].update(status, path);
00937 if (status != vmm_rw::IS_OK) return;
00938 end
00939 end
00940 endtask: update
00941
00942
00943 task vmm_ral_sys::mirror(output vmm_rw::status_e status,
00944 input vmm_ral::check_e check = vmm_ral::QUIET,
00945 input vmm_ral::path_e path = vmm_ral::DEFAULT);
00946 status = vmm_rw::IS_OK;
00947 foreach (this.domains[i]) begin
00948 foreach (this.domains[i].blocks[j]) begin
00949 this.domains[i].blocks[j].mirror(status, check, path);
00950 if (status != vmm_rw::IS_OK) return;
00951 end
00952 foreach (this.domains[i].subsys[j]) begin
00953 this.domains[i].subsys[j].mirror(status, check, path);
00954 if (status != vmm_rw::IS_OK) return;
00955 end
00956 end
00957 endtask: mirror
00958
00959
00960 task vmm_ral_sys::readmemh(string filename);
00961 endtask: readmemh
00962
00963
00964 task vmm_ral_sys::writememh(string filename);
00965 endtask: writememh
00966
00967
00968 function int unsigned vmm_ral_sys::get_sys_ID();
00969 get_sys_ID = this.get_block_or_sys_ID();
00970 endfunction
00971
00972 function int unsigned vmm_ral_sys::get_block_or_sys_size(string domain = "");
00973
00974 vmm_ral_sys subsys[];
00975 vmm_ral_block blks[];
00976 string dm[];
00977 int j;
00978 int unsigned max_addr = 0;
00979 int unsigned size = 1;
00980
00981 j = this.get_domain_index(domain);
00982 if (j < 0)
00983 begin
00984 `vmm_warning(this.log, $psprintf("Unable to locate domain \"%s\" in system \"%s\".",
00985 domain, this.get_fullname()));
00986 get_block_or_sys_size = 0;
00987 return 0;
00988 end
00989
00990 j =0;
00991 this.get_subsys(subsys,dm,domain);
00992 foreach(subsys[j])
00993 begin
00994 int unsigned offset_sys;
00995 offset_sys = subsys[j].get_base_addr(dm[j]);
00996 if(offset_sys >= max_addr)
00997 begin
00998 max_addr = offset_sys +
00999 ((subsys[j].get_block_or_sys_size(dm[j]) *
01000 ((((subsys[j].get_n_bytes(dm[j]) - 1)/this.get_n_bytes(domain))+1)))
01001 ) - 1;
01002 end
01003 end
01004
01005 j =0;
01006 this.get_blocks(blks,dm,domain);
01007 foreach(blks[j])
01008 begin
01009 int unsigned offset_blk;
01010 offset_blk = blks[j].get_base_addr(dm[j]);
01011 if(offset_blk >= max_addr)
01012 begin
01013 max_addr = offset_blk +
01014 ((blks[j].get_block_or_sys_size(dm[j]) *
01015 ((((blks[j].get_n_bytes(dm[j]) - 1)/this.get_n_bytes(domain))+1)))
01016 ) - 1;
01017 end
01018 end
01019
01020 get_block_or_sys_size = max_addr + 1;
01021
01022 endfunction:get_block_or_sys_size
01023
01024 function bit vmm_ral_sys::set_offset(bit [`VMM_RAL_ADDR_WIDTH-1:0] offset,
01025 string domain = "");
01026
01027 int j;
01028 vmm_ral_sys parent_sys;
01029 string parent_domain;
01030
01031 set_offset = 0;
01032 j = this.get_domain_index(domain);
01033 if (j < 0)
01034 begin
01035 `vmm_warning(this.log, $psprintf("Unable to locate domain \"%s\" in Block \"%s\".",
01036 domain, this.get_fullname()));
01037 return 0;
01038 end
01039
01040 if(this.get_parent() != null)
01041 begin
01042 parent_sys = this.get_parent();
01043 parent_domain = this.get_parent_domain(domain);
01044 if(!parent_sys.Xcheck_child_overlapX(offset,this.get_block_or_sys_size(domain),parent_domain,null,this))
01045 begin
01046 `vmm_error(this.log,$psprintf("set_offset for %s failed",this.get_fullname()));
01047 return 0;
01048 end
01049 return this.Xset_base_addrX(offset,domain);
01050 end
01051
01052 if (offset != 0) begin
01053 `vmm_error(this.log, $psprintf("Cannot set offset for top-level system \"%s\": must always be 0.", this.get_fullname()));
01054 end
01055
01056 return 0;
01057 endfunction
01058
01059
01060 function bit vmm_ral_sys::Xcheck_child_overlapX(int unsigned my_offset,
01061 int unsigned my_size,
01062 string domain = "",
01063 vmm_ral_block blk,
01064 vmm_ral_sys sys);
01065
01066 vmm_ral_sys subsys[];
01067 vmm_ral_block blks[];
01068 int unsigned str_addr[];
01069 int unsigned end_addr[];
01070 int unsigned my_end_addr;
01071 int size;
01072 string dm[];
01073 vmm_ral_sys parent_sys;
01074 string parent_domain;
01075 int j;
01076
01077 Xcheck_child_overlapX = 0;
01078 j = this.get_domain_index(domain);
01079 if (j < 0)
01080 begin
01081 `vmm_warning(this.log, $psprintf("Unable to locate domain \"%s\" in system \"%s\".",
01082 domain, this.get_fullname()));
01083 return 0;
01084 end
01085
01086 j =0;
01087 this.get_subsys(subsys,dm,domain);
01088 foreach(subsys[j])
01089 begin
01090 if((sys != null) && (subsys[j] == sys))
01091 begin
01092 size = my_offset - sys.get_base_addr(dm[j]);
01093 my_end_addr = my_offset + (my_size * (((sys.get_n_bytes(dm[j]) - 1)/this.get_n_bytes(domain))+1)) - 1;
01094 end
01095 else
01096 begin
01097 str_addr = new[str_addr.size + 1] (str_addr);
01098 str_addr[str_addr.size-1] = subsys[j].get_base_addr(dm[j]);
01099 end_addr = new[end_addr.size + 1] (end_addr);
01100 end_addr[end_addr.size-1] = str_addr[str_addr.size-1] +
01101 (subsys[j].get_block_or_sys_size(dm[j]) *
01102 (((subsys[j].get_n_bytes(dm[j]) - 1)/this.get_n_bytes(domain))+1)) -1;
01103 end
01104
01105 end
01106
01107 j =0;
01108 this.get_blocks(blks,dm,domain);
01109 foreach(blks[j])
01110 begin
01111 if((blk != null) && (blks[j] == blk))
01112 begin
01113 size = my_offset - blk.get_base_addr(dm[j]);
01114 my_end_addr = my_offset + (my_size * (((blk.get_n_bytes(dm[j]) - 1)/this.get_n_bytes(domain))+1)) - 1;
01115 end
01116 else
01117 begin
01118 str_addr = new[str_addr.size + 1] (str_addr);
01119 str_addr[str_addr.size-1] = blks[j].get_base_addr(dm[j]);
01120 end_addr = new[end_addr.size + 1] (end_addr);
01121 end_addr[end_addr.size-1] = str_addr[str_addr.size-1] +
01122 (blks[j].get_block_or_sys_size(dm[j]) *
01123 (((blks[j].get_n_bytes(dm[j]) - 1)/this.get_n_bytes(domain))+1)) - 1;
01124 end
01125
01126 end
01127
01128 j = 0;
01129 foreach(str_addr[j])
01130 begin
01131 if((my_offset == end_addr[j]) ||
01132 (my_end_addr == str_addr[j]) ||
01133 (my_offset == str_addr[j]) ||
01134 (my_end_addr == end_addr[j]))
01135 begin
01136 `vmm_warning(this.log,$psprintf("System %s has found address range conflict inbetween its child subsystems/blocks",this.get_fullname));
01137 return 0;
01138 end
01139 else if(my_offset < str_addr[j])
01140 begin
01141 if(my_end_addr > str_addr[j])
01142 begin
01143 `vmm_warning(this.log,$psprintf("System %s has found address range conflict inbetween its child subsystems/blocks",this.get_fullname));
01144 return 0;
01145 end
01146 end
01147 else
01148 begin
01149 if(my_offset < end_addr[j])
01150 begin
01151 `vmm_warning(this.log,$psprintf("System %s has found address range conflict inbetween its child subsystems/blocks",this.get_fullname));
01152 return 0;
01153 end
01154 end
01155 end
01156 Xcheck_child_overlapX = 1;
01157
01158 //check if parent present for this system
01159 if(this.get_parent() != null)
01160 begin
01161 if(my_offset >= this.get_block_or_sys_size(domain))
01162 size += this.get_block_or_sys_size(domain);
01163 else
01164 size = this.get_block_or_sys_size(domain);
01165
01166 parent_sys = this.get_parent();
01167 parent_domain = this.get_parent_domain(domain);
01168 Xcheck_child_overlapX =
01169 parent_sys.Xcheck_child_overlapX(this.get_base_addr(domain),size,parent_domain,null,this);
01170 end
01171
01172 endfunction
01173
01174
01175 function vmm_ral_sys vmm_ral_get_sys_by_ID(int unsigned id);
01176 vmm_ral_sys sys;
01177 vmm_ral_block_or_sys blk_or_sys;
01178
01179 blk_or_sys = vmm_ral_get_block_or_sys_by_ID(id);
01180 if ($cast(sys, blk_or_sys)) vmm_ral_get_sys_by_ID = sys;
01181 else vmm_ral_get_sys_by_ID = null;
01182 endfunction
01183