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_block extends vmm_ral_block_or_sys;
00024
00025 local vmm_ral_reg regs[$];
00026 local vmm_ral_vreg vregs[$];
00027 local vmm_ral_mem mems[$];
00028
00029 extern function new(vmm_ral_sys parent,
00030 string name,
00031 string typename,
00032 int unsigned n_bytes,
00033 vmm_ral::endianness_e endian,
00034 bit [`VMM_RAL_ADDR_WIDTH-1:0] base_addr,
00035 string domain = "",
00036 int cover_on = vmm_ral::NO_COVERAGE,
00037 int has_cover = vmm_ral::NO_COVERAGE);
00038
00039 /*local*/ extern virtual function void Xlock_modelX();
00040 /*local*/ extern function void register_reg(vmm_ral_reg register);
00041 /*local*/ extern function void register_vreg(vmm_ral_vreg register);
00042 /*local*/ extern function void register_mem(vmm_ral_mem memory);
00043 /*local*/ extern virtual function void Xregister_ral_accessX(vmm_ral_access access);
00044
00045 `ifdef VMM_RAL_FAST_SRCH
00046 extern local function void Xinit_reg_by_offset_mapX();
00047 vmm_ral_reg_by_offset_map reg_map_by_domain[*];
00048 extern /*local*/ function vmm_ral_reg_by_offset_map Xget_reg_by_offset_mapX(string domain);
00049 `endif
00050
00051 extern virtual function string psdisplay(string prefix = "",
00052 string domain = "");
00053
00054 extern virtual function void get_fields(ref vmm_ral_field fields[],
00055 input string domain = "");
00056 extern virtual function void get_virtual_fields(ref vmm_ral_vfield fields[],
00057 input string domain = "");
00058 extern virtual function vmm_ral_field get_field_by_name(string name);
00059 extern virtual function vmm_ral_vfield get_virtual_field_by_name(string name);
00060
00061 extern virtual function void get_registers(ref vmm_ral_reg regs[],
00062 input string domain = "");
00063 extern virtual function void get_virtual_registers(ref vmm_ral_vreg vregs[],
00064 input string domain = "");
00065 extern virtual function vmm_ral_reg get_reg_by_name(string name);
00066 extern virtual function vmm_ral_vreg get_vreg_by_name(string name);
00067 extern virtual function vmm_ral_reg get_reg_by_offset(bit [`VMM_RAL_ADDR_WIDTH-1:0] offset,
00068 string domain = "");
00069
00070 extern virtual function void get_memories(ref vmm_ral_mem mems[],
00071 input string domain = "");
00072 extern virtual function vmm_ral_mem get_mem_by_name(string name);
00073 extern virtual function vmm_ral_mem get_mem_by_offset(bit [`VMM_RAL_ADDR_WIDTH-1:0] offset,
00074 string domain = "");
00075
00076 extern virtual function void get_constraints(ref string names[]);
00077
00078 extern virtual function void power_down(bit retain = 0);
00079 extern virtual function void power_up(string power_domains = "");
00080 /*local*/ bit Xis_powered_downX;
00081 local bit is_powered_down_with_retention;
00082
00083 extern virtual function int set_cover(int is_on);
00084
00085 extern virtual function void reset(string domain = "",
00086 vmm_ral::reset_e kind = vmm_ral::HARD);
00087 extern virtual function bit needs_update();
00088
00089 extern virtual task update(output vmm_rw::status_e status,
00090 input vmm_ral::path_e path = vmm_ral::DEFAULT);
00091 extern virtual task mirror(output vmm_rw::status_e status,
00092 input vmm_ral::check_e check = vmm_ral::QUIET,
00093 input vmm_ral::path_e path = vmm_ral::DEFAULT);
00094
00095 extern virtual task readmemh(string filename);
00096 extern virtual task writememh(string filename);
00097
00098 extern virtual /*local*/ function void XsampleX(bit [`VMM_RAL_ADDR_WIDTH-1:0] addr,
00099 int domain);
00100 extern protected virtual function void sample(bit [`VMM_RAL_ADDR_WIDTH-1:0] addr,
00101 int domain);
00102
00103 extern function int unsigned get_block_ID();
00104
00105 extern virtual function int unsigned get_block_or_sys_size(string domain = "");
00106
00107 extern virtual function bit set_offset(bit [`VMM_RAL_ADDR_WIDTH-1:0] offset,
00108 string domain = "");
00109
00110
00111 endclass: vmm_ral_block
00112
00113
00114 function vmm_ral_block::new(vmm_ral_sys parent,
00115 string name,
00116 string typename,
00117 int unsigned n_bytes,
00118 vmm_ral::endianness_e endian,
00119 bit [`VMM_RAL_ADDR_WIDTH-1:0] base_addr,
00120 string domain = "",
00121 int cover_on = vmm_ral::NO_COVERAGE,
00122 int has_cover = vmm_ral::NO_COVERAGE);
00123 super.new(parent, "RAL Block", name, typename,
00124 n_bytes, endian, base_addr, domain,
00125 cover_on, has_cover);
00126 this.Xis_powered_downX = 0;
00127 endfunction: new
00128
00129
00130 function void vmm_ral_block::Xlock_modelX();
00131 if (this.Xis_lockedX()) return;
00132
00133 super.Xlock_modelX();
00134 foreach (this.regs[i]) begin
00135 this.regs[i].Xlock_modelX();
00136 end
00137 foreach (this.mems[i]) begin
00138 this.mems[i].Xlock_modelX();
00139 end
00140
00141 `ifdef VMM_RAL_FAST_SRCH
00142 this.Xinit_reg_by_offset_mapX();
00143 `endif
00144 endfunction: Xlock_modelX
00145
00146
00147 `ifdef VMM_RAL_FAST_SRCH
00148 function void vmm_ral_block::Xinit_reg_by_offset_mapX();
00149 string domains[];
00150 this.get_domains(domains);
00151 foreach (domains[i]) begin
00152 vmm_ral_reg regs[];
00153 this.reg_map_by_domain[i] = new;
00154
00155 this.get_registers(regs, domains[i]);
00156 foreach (regs[l]) begin
00157 bit [`VMM_RAL_ADDR_WIDTH-1:0] offset_in_blk
00158 = regs[l].get_offset_in_block(domains[i]);
00159 this.reg_map_by_domain[i].reg_by_offset[offset_in_blk] = regs[l];
00160 end
00161 end
00162 endfunction
00163
00164
00165 function vmm_ral_reg_by_offset_map vmm_ral_block::Xget_reg_by_offset_mapX(string domain);
00166 int j = this.get_domain_index(domain);
00167 if (j < 0) begin
00168 `vmm_warning(this.log, $psprintf("Unable to locate domain \"%s\" in Block \"%s\".",
00169 domain, this.get_fullname()));
00170 return null;
00171 end
00172 if (this.reg_map_by_domain.exists(j)) return this.reg_map_by_domain[j];
00173 `vmm_warning(this.log, $psprintf("Unable to locate 'reg_by_offset_map' in domain \"%s\" of Block \"%s\".",
00174 domain, this.get_fullname()));
00175 return null;
00176 endfunction
00177 `endif
00178
00179
00180 function void vmm_ral_block::register_reg(vmm_ral_reg register);
00181 if (this.Xis_lockedX()) begin
00182 `vmm_error(this.log, "Cannot add register to locked block model");
00183 return;
00184 end
00185
00186 // Check if this register has already been registered with this block
00187 foreach (this.regs[i]) begin
00188 if (this.regs[i] == register) begin
00189 `vmm_error(this.log, $psprintf("Register \"%s\" has already been registered with block \"%s\".\n",
00190 register.get_name(), this.get_name()));
00191 return;
00192 end
00193 end
00194 this.regs.push_back(register);
00195 endfunction: register_reg
00196
00197 function void vmm_ral_block::register_vreg(vmm_ral_vreg register);
00198 if (this.Xis_lockedX()) begin
00199 `vmm_error(this.log, "Cannot add virtual register to locked block model");
00200 return;
00201 end
00202
00203 // Check if this register has already been registered with this block
00204 foreach (this.vregs[i]) begin
00205 if (this.vregs[i] == register) begin
00206 `vmm_error(this.log, $psprintf("Virtual register \"%s\" has already been registered with block \"%s\".\n",
00207 register.get_name(), this.get_name()));
00208 return;
00209 end
00210 end
00211 this.vregs.push_back(register);
00212 endfunction: register_vreg
00213
00214 function void vmm_ral_block::register_mem(vmm_ral_mem memory);
00215 if (this.Xis_lockedX()) begin
00216 `vmm_error(this.log, "Cannot add memory to locked block model");
00217 return;
00218 end
00219
00220 // Check if this memory has already been registered with this block
00221 foreach (this.mems[i]) begin
00222 if (this.mems[i] == memory) begin
00223 `vmm_error(this.log, $psprintf("Memory \"%s\" has already been registered with block \"%s\".\n",
00224 memory.get_name(), this.get_name()));
00225 return;
00226 end
00227 end
00228 this.mems.push_back(memory);
00229 endfunction: register_mem
00230
00231
00232 function void vmm_ral_block::Xregister_ral_accessX(vmm_ral_access access);
00233 // There can only be one RAL Access on a RAL model
00234 if (this.ral_access != null && this.ral_access != access) begin
00235 `vmm_fatal(this.log, $psprintf("Block %s is already used by another RAL access instance", this.get_fullname()));
00236 end
00237 this.ral_access = access;
00238
00239 // Register all sub-elements
00240 begin
00241 vmm_ral_reg regs[];
00242 vmm_ral_mem mems[];
00243
00244 this.get_registers(regs);
00245 foreach (regs[i]) begin
00246 regs[i].Xregister_ral_accessX(access);
00247 end
00248
00249 this.get_memories(mems);
00250 foreach (mems[i]) begin
00251 mems[i].Xregister_ral_accessX(access);
00252 end
00253 end
00254 endfunction: Xregister_ral_accessX
00255
00256
00257 function string vmm_ral_block::psdisplay(string prefix = "",
00258 string domain = "");
00259 string domains[];
00260 vmm_ral_reg regs[];
00261 vmm_ral_vreg vregs[];
00262 vmm_ral_mem mems[];
00263 bit single_domain;
00264 vmm_ral::endianness_e endian;
00265
00266 single_domain = 1;
00267 if (domain == "") begin
00268 this.get_domains(domains);
00269 if (domains.size() > 1) single_domain = 0;
00270 end
00271 if (single_domain) begin
00272 $sformat(psdisplay, "%sBlock %s", prefix, this.get_fullname());
00273 if (domain != "") $sformat(psdisplay, "%s.%s", psdisplay, domain);
00274 endian = this.get_endian(domain);
00275 $sformat(psdisplay, "%s -- %0d bytes (%s)", psdisplay,
00276 this.get_n_bytes(domain), endian.name());
00277 this.get_registers(regs, domain);
00278 foreach (regs[j]) begin
00279 $sformat(psdisplay, "%s\n%s", psdisplay,
00280 regs[j].psdisplay({prefix, " "}, domain));
00281 end
00282 this.get_virtual_registers(vregs, domain);
00283 foreach (vregs[j]) begin
00284 $sformat(psdisplay, "%s\n%s", psdisplay,
00285 vregs[j].psdisplay({prefix, " "}, domain));
00286 end
00287 this.get_memories(mems, domain);
00288 foreach (mems[j]) begin
00289 $sformat(psdisplay, "%s\n%s", psdisplay,
00290 mems[j].psdisplay({prefix, " "}, domain));
00291 end
00292 end
00293 else begin
00294 $sformat(psdisplay, "%sBlock %s", prefix, this.get_fullname());
00295 foreach (domains[i]) begin
00296 endian = this.get_endian(domains[i]);
00297 $sformat(psdisplay, "%s\n%s Domain \"%s\" -- %0d bytes (%s)",
00298 psdisplay, prefix, domains[i],
00299 this.get_n_bytes(domains[i]), endian.name());
00300 this.get_registers(regs, domains[i]);
00301 foreach (regs[j]) begin
00302 $sformat(psdisplay, "%s\n%s", psdisplay,
00303 regs[j].psdisplay({prefix, " "},
00304 domains[i]));
00305 end
00306 this.get_virtual_registers(vregs, domains[i]);
00307 foreach (vregs[j]) begin
00308 $sformat(psdisplay, "%s\n%s", psdisplay,
00309 vregs[j].psdisplay({prefix, " "},
00310 domains[i]));
00311 end
00312 this.get_memories(mems, domains[i]);
00313 foreach (mems[j]) begin
00314 $sformat(psdisplay, "%s\n%s", psdisplay,
00315 mems[j].psdisplay({prefix, " "}, domains[i]));
00316 end
00317 end
00318 end
00319 endfunction: psdisplay
00320
00321
00322 function void vmm_ral_block::get_fields(ref vmm_ral_field fields[],
00323 input string domain = "");
00324 int n;
00325 vmm_ral_reg r[];
00326 vmm_ral_field f[];
00327
00328 fields = new [0];
00329 this.get_registers(r, domain);
00330 foreach (r[i]) begin
00331 r[i].get_fields(f);
00332 n = fields.size();
00333 fields = new [n + f.size()] (fields);
00334
00335 foreach (f[j]) begin
00336 fields[n++] = f[j];
00337 end
00338 end
00339 endfunction: get_fields
00340
00341 function void vmm_ral_block::get_virtual_fields(ref vmm_ral_vfield fields[],
00342 input string domain = "");
00343 int n;
00344 vmm_ral_vreg r[];
00345 vmm_ral_vfield f[];
00346
00347 fields = new [0];
00348 this.get_virtual_registers(r, domain);
00349 foreach (r[i]) begin
00350 r[i].get_fields(f);
00351 n = fields.size();
00352 fields = new [n + f.size()] (fields);
00353
00354 foreach (f[j]) begin
00355 fields[n++] = f[j];
00356 end
00357 end
00358 endfunction: get_virtual_fields
00359
00360 function vmm_ral_field vmm_ral_block::get_field_by_name(string name);
00361 // Search the registers to find the first field of the specified name
00362 foreach (this.regs[i]) begin
00363 vmm_ral_field fields[];
00364 this.regs[i].get_fields(fields);
00365 foreach (fields[j]) begin
00366 if (fields[j].get_name() == name) begin
00367 return fields[j];
00368 end
00369 end
00370 end
00371 `vmm_warning(this.log, $psprintf("Unable to locate field \"%s\" in block \"%s\".",
00372 name, this.get_fullname()));
00373 get_field_by_name = null;
00374 endfunction: get_field_by_name
00375
00376 function vmm_ral_vfield vmm_ral_block::get_virtual_field_by_name(string name);
00377 // Search the registers to find the first field of the specified name
00378 foreach (this.vregs[i]) begin
00379 vmm_ral_vfield fields[];
00380 this.vregs[i].get_fields(fields);
00381 foreach (fields[j]) begin
00382 if (fields[j].get_name() == name) begin
00383 return fields[j];
00384 end
00385 end
00386 end
00387 `vmm_warning(this.log, $psprintf("Unable to locate virtual field \"%s\" in block \"%s\".",
00388 name, this.get_fullname()));
00389 get_virtual_field_by_name = null;
00390 endfunction: get_virtual_field_by_name
00391
00392
00393 function void vmm_ral_block::get_registers(ref vmm_ral_reg regs[],
00394 input string domain = "");
00395 if (domain == "") begin
00396 regs = new [this.regs.size()];
00397 foreach(this.regs[i]) begin
00398 regs[i] = this.regs[i];
00399 end
00400 end
00401 else begin
00402 int n = 0;
00403 regs = new [this.regs.size()];
00404 foreach(this.regs[i]) begin
00405 // Is the register in the specified domain?
00406 string domains[];
00407 this.regs[i].get_domains(domains);
00408 foreach(domains[j]) begin
00409 if (domains[j] == domain) begin
00410 regs[n++] = this.regs[i];
00411 break;
00412 end
00413 end
00414 end
00415 regs = new [n] (regs);
00416 end
00417 endfunction: get_registers
00418
00419 function void vmm_ral_block::get_virtual_registers(ref vmm_ral_vreg vregs[],
00420 input string domain = "");
00421 if (domain == "") begin
00422 vregs = new [this.vregs.size()];
00423 foreach(this.vregs[i]) begin
00424 vregs[i] = this.vregs[i];
00425 end
00426 end
00427 else begin
00428 int n = 0;
00429 vregs = new [this.vregs.size()];
00430 foreach(this.vregs[i]) begin
00431 // Is the register in the specified domain?
00432 string domains[];
00433 if(this.vregs[i].get_memory() != null)
00434 begin
00435 this.vregs[i].get_domains(domains);
00436 foreach(domains[j]) begin
00437 if (domains[j] == domain) begin
00438 vregs[n++] = this.vregs[i];
00439 break;
00440 end
00441 end
00442 end
00443 end
00444 vregs = new [n] (vregs);
00445 end
00446 endfunction: get_virtual_registers
00447
00448 function vmm_ral_reg vmm_ral_block::get_reg_by_name(string name);
00449 foreach (this.regs[i]) begin
00450 if (this.regs[i].get_name() == name) begin
00451 return this.regs[i];
00452 end
00453 end
00454 `vmm_warning(this.log, $psprintf("Unable to locate register \"%s\" in block \"%s\".",
00455 name, this.get_fullname()));
00456 get_reg_by_name = null;
00457 endfunction: get_reg_by_name
00458
00459 function vmm_ral_vreg vmm_ral_block::get_vreg_by_name(string name);
00460 foreach (this.vregs[i]) begin
00461 if (this.vregs[i].get_name() == name) begin
00462 return this.vregs[i];
00463 end
00464 end
00465 `vmm_warning(this.log, $psprintf("Unable to locate virtual register \"%s\" in block \"%s\".",
00466 name, this.get_fullname()));
00467 get_vreg_by_name = null;
00468 endfunction: get_vreg_by_name
00469
00470 function vmm_ral_reg vmm_ral_block::get_reg_by_offset(bit [`VMM_RAL_ADDR_WIDTH-1:0] offset,
00471 string domain = "");
00472 vmm_ral_reg regs[];
00473
00474 this.get_registers(regs, domain);
00475 foreach (regs[i]) begin
00476 if (regs[i].get_offset_in_block(domain) == offset) begin
00477 return regs[i];
00478 end
00479 end
00480 `vmm_warning(this.log, $psprintf("Unable to locate register at offset 0x%h %0sin block \"%s\".",
00481 offset, ((domain == "") ? "" : $psprintf("in domain \"%s\" ",
00482 domain)),
00483 this.get_fullname()));
00484 get_reg_by_offset = null;
00485 endfunction: get_reg_by_offset
00486
00487
00488 function void vmm_ral_block::get_memories(ref vmm_ral_mem mems[],
00489 input string domain = "");
00490 if (domain == "") begin
00491 mems = new [this.mems.size()];
00492 foreach(this.mems[i]) begin
00493 mems[i] = this.mems[i];
00494 end
00495 end
00496 else begin
00497 int n = 0;
00498 mems = new [this.mems.size()];
00499 foreach(this.mems[i]) begin
00500 // Is the memory in the specified domain?
00501 string domains[];
00502 this.mems[i].get_domains(domains);
00503 foreach(domains[j]) begin
00504 if (domains[j] == domain) begin
00505 mems[n++] = this.mems[i];
00506 break;
00507 end
00508 end
00509 end
00510 mems = new [n] (mems);
00511 end
00512 endfunction: get_memories
00513
00514
00515 function vmm_ral_mem vmm_ral_block::get_mem_by_name(string name);
00516 foreach (this.mems[i]) begin
00517 if (this.mems[i].get_name() == name) begin
00518 return this.mems[i];
00519 end
00520 end
00521 `vmm_warning(this.log, $psprintf("Unable to locate memory \"%s\" in block \"%s\".",
00522 name, this.get_fullname()));
00523 get_mem_by_name = null;
00524 endfunction: get_mem_by_name
00525
00526
00527 function vmm_ral_mem vmm_ral_block::get_mem_by_offset(bit [`VMM_RAL_ADDR_WIDTH-1:0] offset,
00528 string domain ="");
00529 //get_mem_by_offset = this.mems.first() with index: (this.mems[index].offset_in_block == offset);
00530 endfunction: get_mem_by_offset
00531
00532
00533 function void vmm_ral_block::get_constraints(ref string names[]);
00534 endfunction: get_constraints
00535
00536
00537 function void vmm_ral_block::power_down(bit retain = 0);
00538 vmm_ral_mem mems[];
00539
00540 if (this.Xis_powered_downX) begin
00541 // It's OK to insist that the block is powered down, but
00542 // you can't get state retention if it was previously powered down without it
00543 if (!this.is_powered_down_with_retention && retain) begin
00544 `vmm_error(this.log, $psprintf("Cannot power-down memory \"%s\" with retention because is has already been powered down without retention",
00545 this.get_fullname()));
00546 return;
00547 end
00548 end
00549
00550 // Power down all memories
00551 this.get_memories(mems);
00552 foreach (mems[i]) begin
00553 mems[i].power_down();
00554 end
00555
00556 this.Xis_powered_downX = 1;
00557 this.is_powered_down_with_retention = retain;
00558 endfunction: power_down
00559
00560
00561 function void vmm_ral_block::power_up(string power_domains = "");
00562 vmm_ral_reg regs[];
00563 vmm_ral_mem mems[];
00564 string pwr_domain;
00565
00566 if (power_domains != "") begin
00567 pwr_domain = this.get_attribute("POWER_DOMAIN");
00568 if (!`vmm_str_match(pwr_domain, power_domains)) return;
00569 end
00570
00571 // Initialize registers based on powered-down retention
00572 this.get_registers(regs);
00573 foreach (regs[i]) begin
00574 if (!this.is_powered_down_with_retention) regs[i].reset();
00575 else begin
00576 string retain_attrib = regs[i].get_attribute("RETAIN");
00577 if (retain_attrib == "" ||
00578 retain_attrib == "0") regs[i].reset();
00579 end
00580 end
00581
00582 // Power up memories in the specified power domains
00583 this.get_memories(mems);
00584 foreach (mems[i]) begin
00585 if (power_domains != "") begin
00586 pwr_domain = mems[i].get_attribute("POWER_DOMAIN");
00587 if (!`vmm_str_match(pwr_domain, power_domains)) continue;
00588 end
00589 mems[i].power_up();
00590 end
00591
00592 this.Xis_powered_downX = 0;
00593 endfunction: power_up
00594
00595
00596 function int vmm_ral_block::set_cover(int is_on);
00597 int can_cvr;
00598
00599 set_cover = super.set_cover(is_on);
00600 can_cvr = is_on & set_cover;
00601 if (can_cvr == 0) return set_cover;
00602
00603 foreach (this.regs[i]) begin
00604 void'(this.regs[i].set_cover(can_cvr));
00605 end
00606 foreach (this.mems[i]) begin
00607 void'(this.mems[i].set_cover(can_cvr));
00608 end
00609 endfunction: set_cover
00610
00611
00612 function void vmm_ral_block::reset(string domain = "",
00613 vmm_ral::reset_e kind = vmm_ral::HARD);
00614 vmm_ral_reg regs[];
00615 vmm_ral_mem mems[];
00616
00617 this.get_registers(regs, domain);
00618 foreach (regs[i]) begin
00619 regs[i].reset(kind);
00620 end
00621
00622 this.get_memories(mems, domain);
00623 foreach (mems[i]) begin
00624 vmm_ral_vreg vregs[];
00625 mems[i].get_virtual_registers(vregs);
00626 foreach (vregs[j]) begin
00627 vregs[j].reset(kind);
00628 end
00629 end
00630 endfunction: reset
00631
00632
00633 function bit vmm_ral_block::needs_update();
00634 needs_update = 0;
00635 foreach (this.regs[i]) begin
00636 if (this.regs[i].needs_update()) begin
00637 return 1;
00638 end
00639 end
00640 endfunction: needs_update
00641
00642
00643 task vmm_ral_block::update(output vmm_rw::status_e status,
00644 input vmm_ral::path_e path = vmm_ral::DEFAULT);
00645 string domains[];
00646 bit updated;
00647
00648 status = vmm_rw::IS_OK;
00649 foreach (this.regs[i]) begin
00650 if (!this.regs[i].needs_update()) continue;
00651
00652 if (path == vmm_ral::BACKDOOR) begin
00653 this.regs[i].update(status, path);
00654 if (status == vmm_rw::IS_OK) continue;
00655 `vmm_error(this.log, $psprintf("Register \"%s\" could not be updated",
00656 regs[i].get_fullname()));
00657 return;
00658 end
00659
00660 // Find the first writeable domain to
00661 // perform the update through
00662 this.regs[i].get_domains(domains);
00663 updated = 0;
00664 foreach (domains[j]) begin
00665 if (this.regs[i].get_rights(domains[j]) != vmm_ral::RO) begin
00666 this.regs[i].update(status, path, domains[j]);
00667 if (status == vmm_rw::IS_OK) begin
00668 updated = 1;
00669 break;
00670 end
00671 end
00672 end
00673 if (!updated) begin
00674 `vmm_error(this.log, $psprintf("Register \"%s\" could not be updated",
00675 regs[i].get_fullname()));
00676 if (status == vmm_rw::IS_OK) status = vmm_rw::ERROR;
00677 return;
00678 end
00679 end
00680 endtask: update
00681
00682
00683 task vmm_ral_block::mirror(output vmm_rw::status_e status,
00684 input vmm_ral::check_e check = vmm_ral::QUIET,
00685 input vmm_ral::path_e path = vmm_ral::DEFAULT);
00686 string domains[];
00687 bit mirrored;
00688
00689 status = vmm_rw::IS_OK;
00690 foreach (this.regs[i]) begin
00691
00692 if (path == vmm_ral::BACKDOOR) begin
00693 this.regs[i].mirror(status, check, path);
00694 if (status != vmm_rw::IS_OK) return;
00695 continue;
00696 end
00697
00698 // Find the first readable domain to
00699 // perform the update through
00700 this.regs[i].get_domains(domains);
00701 mirrored = 0;
00702 foreach (domains[j]) begin
00703 if (this.regs[i].get_rights(domains[j]) != vmm_ral::WO) begin
00704 this.regs[i].mirror(status, check, path, domains[0]);
00705 if (status == vmm_rw::IS_OK) begin
00706 mirrored = 1;
00707 break;
00708 end
00709 end
00710 end
00711 if (!mirrored) begin
00712 `vmm_error(this.log, $psprintf("Register \"%s\" could not be mirrored",
00713 regs[i].get_fullname()));
00714 if (status == vmm_rw::IS_OK) status = vmm_rw::ERROR;
00715 return;
00716 end
00717 end
00718 endtask: mirror
00719
00720
00721 task vmm_ral_block::readmemh(string filename);
00722 endtask: readmemh
00723
00724
00725 task vmm_ral_block::writememh(string filename);
00726 endtask: writememh
00727
00728
00729 function void vmm_ral_block::XsampleX(bit [`VMM_RAL_ADDR_WIDTH-1:0] addr,
00730 int domain);
00731 this.sample(addr, domain);
00732 endfunction
00733
00734
00735 function void vmm_ral_block::sample(bit [`VMM_RAL_ADDR_WIDTH-1:0] addr,
00736 int domain);
00737 // Nothing to do in this base class
00738 endfunction
00739
00740
00741 function bit vmm_ral_block::set_offset(bit [`VMM_RAL_ADDR_WIDTH-1:0] offset,
00742 string domain = "");
00743 int j;
00744 vmm_ral_sys parent_sys;
00745 string parent_domain;
00746
00747 set_offset = 0;
00748 j = this.get_domain_index(domain);
00749 if (j < 0)
00750 begin
00751 `vmm_warning(this.log, $psprintf("Unable to locate domain \"%s\" in Block \"%s\".",
00752 domain, this.get_fullname()));
00753 return 0;
00754 end
00755
00756 if(this.get_parent() != null)
00757 begin
00758 parent_sys = this.get_parent();
00759 parent_domain = this.get_parent_domain(domain);
00760 if(!parent_sys.Xcheck_child_overlapX(offset,this.get_block_or_sys_size(domain),parent_domain,this,null))
00761 begin
00762 `vmm_error(this.log,$psprintf("set_offset for %s failed",this.get_fullname()));
00763 return 0;
00764 end
00765 return this.Xset_base_addrX(offset,domain);
00766 end
00767
00768 if (offset != 0) begin
00769 `vmm_error(this.log, $psprintf("Cannot set offset for top-level block \"%s\": must always be 0.",
00770 this.get_fullname()));
00771 end
00772
00773 return 0;
00774 endfunction
00775
00776
00777 function int unsigned vmm_ral_block::get_block_or_sys_size(string domain = "");
00778
00779 vmm_ral_reg regs[];
00780 vmm_ral_mem mems[];
00781 int j;
00782 int unsigned max_addr = 0;
00783 int unsigned size = 1;
00784
00785 j = this.get_domain_index(domain);
00786 if (j < 0)
00787 begin
00788 `vmm_warning(this.log, $psprintf("Unable to locate domain \"%s\" in Block \"%s\".",
00789 domain, this.get_fullname()));
00790 get_block_or_sys_size = 0;
00791 return 0;
00792 end
00793
00794
00795 this.get_registers(regs,domain);
00796 this.get_memories(mems,domain);
00797
00798 foreach (regs[i])
00799 begin
00800 int unsigned offset_blk;
00801 offset_blk = regs[i].get_offset_in_block(domain);
00802 if (offset_blk > max_addr)
00803 begin
00804 max_addr = offset_blk + ((regs[i].get_n_bytes()-1)/this.get_n_bytes(domain));
00805 end
00806 end
00807
00808 foreach (mems[i])
00809 begin
00810 int unsigned offset_blk;
00811 offset_blk = mems[i].get_offset_in_block(0,domain);
00812 if (offset_blk > max_addr)
00813 begin
00814 max_addr = offset_blk + (mems[i].get_size() * (((mems[i].get_n_bytes()-1)/this.get_n_bytes(domain))+1)) -1;
00815 end
00816 end
00817
00818 get_block_or_sys_size = max_addr + 1;
00819
00820 endfunction : get_block_or_sys_size
00821
00822 function int unsigned vmm_ral_block::get_block_ID();
00823 get_block_ID = this.get_block_or_sys_ID();
00824 endfunction
00825
00826 function vmm_ral_block vmm_ral_get_block_by_ID(int unsigned id);
00827 vmm_ral_block blk;
00828 vmm_ral_block_or_sys blk_or_sys;
00829
00830 blk_or_sys = vmm_ral_get_block_or_sys_by_ID(id);
00831 if ($cast(blk, blk_or_sys)) vmm_ral_get_block_by_ID = blk;
00832 else vmm_ral_get_block_by_ID = null;
00833 endfunction
00834