VMM OpenSource - sv/RAL/vmm_ral_sys.sv

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