VMM OpenSource - sv/RAL/vmm_ral_block.sv

sv/RAL/vmm_ral_block.sv expanded 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_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