vmm_ral_block.sv

Go to the documentation of this file.
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    local vmm_ral_reg  regs[$];
00025    local vmm_ral_vreg vregs[$];
00026    local vmm_ral_mem  mems[$];
00027 
00028    extern function new(vmm_ral_sys                   parent,
00029                        string                        name,
00030                        string                        typename,
00031                        int unsigned                  n_bytes,
00032                        vmm_ral::endianness_e         endian,
00033                        bit [`VMM_RAL_ADDR_WIDTH-1:0] base_addr,
00034                        string                        domain   = "",
00035                        bit                           cover_on = 1);
00036 
00037    /*local*/ extern virtual function void Xlock_modelX();
00038    /*local*/ extern function void register_reg(vmm_ral_reg register);
00039    /*local*/ extern function void register_vreg(vmm_ral_vreg register);
00040    /*local*/ extern function void register_mem(vmm_ral_mem memory);
00041    /*local*/ extern virtual function void Xregister_ral_accessX(vmm_ral_access access);
00042 
00043    extern virtual function string psdisplay(string prefix = "",
00044                                             string domain = "");
00045 
00046    extern virtual function void get_fields(ref vmm_ral_field fields[],
00047                                            input string      domain = ""); 
00048    extern virtual function void get_virtual_fields(ref vmm_ral_vfield fields[],
00049                                                    input string      domain = ""); 
00050    extern virtual function vmm_ral_field get_field_by_name(string name);
00051    extern virtual function vmm_ral_vfield get_virtual_field_by_name(string name);
00052 
00053    extern virtual function void get_registers(ref vmm_ral_reg regs[],
00054                                               input string    domain = "");
00055    extern virtual function void get_virtual_registers(ref vmm_ral_vreg vregs[],
00056                                                       input string    domain = "");
00057    extern virtual function vmm_ral_reg get_reg_by_name(string name);
00058    extern virtual function vmm_ral_vreg get_vreg_by_name(string name);
00059    extern virtual function vmm_ral_reg get_reg_by_offset(bit [`VMM_RAL_ADDR_WIDTH-1:0] offset,
00060                                                          string                        domain = "");
00061 
00062    extern virtual function void get_memories(ref vmm_ral_mem mems[],
00063                                              input string    domain = "");
00064    extern virtual function vmm_ral_mem get_mem_by_name(string name);
00065    extern virtual function vmm_ral_mem get_mem_by_offset(bit [`VMM_RAL_ADDR_WIDTH-1:0] offset,
00066                                                          string                        domain = "");
00067 
00068    extern virtual function void get_constraints(ref string names[]);
00069 
00070    extern virtual function bit set_cover(bit is_on);
00071 
00072    extern virtual function void reset(string           domain = "",
00073                                       vmm_ral::reset_e kind   = vmm_ral::HARD);
00074    extern virtual function bit needs_update();
00075 
00076    extern virtual task update(output vmm_rw::status_e status,
00077                               input  vmm_ral::path_e  path = vmm_ral::DEFAULT);
00078    extern virtual task mirror(output vmm_rw::status_e status,
00079                               input  vmm_ral::check_e check = vmm_ral:: QUIET,
00080                               input  vmm_ral::path_e  path  = vmm_ral::DEFAULT);
00081    
00082    extern virtual task readmemh(string filename);
00083    extern virtual task writememh(string filename);
00084 
00085 //protect
00086    extern virtual /*local*/ function void XsampleX(bit [`VMM_RAL_ADDR_WIDTH-1:0] addr,
00087                                                    int                           domain);
00088    extern protected virtual function void sample(bit [`VMM_RAL_ADDR_WIDTH-1:0] addr,
00089                                                  int                           domain);
00090 //endprotect
00091 endclass: vmm_ral_block
00092    
00093 
00094 function vmm_ral_block::new(vmm_ral_sys                   parent,
00095                             string                        name,
00096                             string                        typename,
00097                             int unsigned                  n_bytes,
00098                             vmm_ral::endianness_e         endian,
00099                             bit [`VMM_RAL_ADDR_WIDTH-1:0] base_addr,
00100                             string                        domain,
00101                             bit                           cover_on);
00102    super.new(parent, "RAL Block", name, typename,
00103              n_bytes, endian, base_addr, domain,
00104              cover_on);
00105 endfunction: new
00106 
00107 
00108 function void vmm_ral_block::Xlock_modelX();
00109    if (this.Xis_lockedX()) return;
00110 
00111    super.Xlock_modelX();
00112    foreach (this.regs[i]) begin
00113       this.regs[i].Xlock_modelX();
00114    end
00115    foreach (this.mems[i]) begin
00116       this.mems[i].Xlock_modelX();
00117    end
00118 endfunction: Xlock_modelX
00119 
00120 
00121 function void vmm_ral_block::register_reg(vmm_ral_reg register);
00122    if (this.Xis_lockedX()) begin
00123       `vmm_error(this.log, "Cannot add register to locked block model");
00124       return;
00125    end
00126 
00127    // Check if this register has already been registered with this block
00128    foreach (this.regs[i]) begin
00129       if (this.regs[i] == register) begin
00130          `vmm_error(this.log, $psprintf("Register \"%s\" has already been registered with block \"%s\".\n",
00131                                        register.get_name(), this.get_name()));
00132          return;
00133       end
00134    end
00135    this.regs.push_back(register);
00136 endfunction: register_reg
00137 
00138 function void vmm_ral_block::register_vreg(vmm_ral_vreg register);
00139    if (this.Xis_lockedX()) begin
00140       `vmm_error(this.log, "Cannot add virtual register to locked block model");
00141       return;
00142    end
00143 
00144    // Check if this register has already been registered with this block
00145    foreach (this.vregs[i]) begin
00146       if (this.vregs[i] == register) begin
00147          `vmm_error(this.log, $psprintf("Virtual register \"%s\" has already been registered with block \"%s\".\n",
00148                                        register.get_name(), this.get_name()));
00149          return;
00150       end
00151    end
00152    this.vregs.push_back(register);
00153 endfunction: register_vreg
00154 
00155 function void vmm_ral_block::register_mem(vmm_ral_mem memory);
00156    if (this.Xis_lockedX()) begin
00157       `vmm_error(this.log, "Cannot add memory to locked block model");
00158       return;
00159    end
00160 
00161    // Check if this memory has already been registered with this block
00162    foreach (this.mems[i]) begin
00163       if (this.mems[i] == memory) begin
00164          `vmm_error(this.log, $psprintf("Memory \"%s\" has already been registered with block \"%s\".\n",
00165                                        memory.get_name(), this.get_name()));
00166          return;
00167       end
00168    end
00169    this.mems.push_back(memory);
00170 endfunction: register_mem
00171 
00172 
00173 function void vmm_ral_block::Xregister_ral_accessX(vmm_ral_access access);
00174    // There can only be one RAL Access on a RAL model
00175    if (this.ral_access != null && this.ral_access != access) begin
00176       `vmm_fatal(this.log, $psprintf("Block %s is already used by another RAL access instance", this.get_fullname()));
00177    end
00178    this.ral_access = access;
00179 
00180    // Register all sub-elements
00181    begin
00182       vmm_ral_reg  regs[];
00183       vmm_ral_mem  mems[];
00184 
00185       this.get_registers(regs);
00186       foreach (regs[i]) begin
00187          regs[i].Xregister_ral_accessX(access);
00188       end
00189 
00190       this.get_memories(mems);
00191       foreach (mems[i]) begin
00192          mems[i].Xregister_ral_accessX(access);
00193       end
00194    end
00195 endfunction: Xregister_ral_accessX
00196 
00197 
00198 function string vmm_ral_block::psdisplay(string prefix,
00199                                          string domain);
00200    string       domains[];
00201    vmm_ral_reg  regs[];
00202    vmm_ral_vreg vregs[];
00203    vmm_ral_mem  mems[];
00204    bit          single_domain;
00205    vmm_ral::endianness_e endian;
00206 
00207    single_domain = 1;
00208    if (domain == "") begin
00209       this.get_domains(domains);
00210       if (domains.size() > 1) single_domain = 0;
00211    end
00212    if (single_domain) begin
00213       $sformat(psdisplay, "%sBlock %s", prefix, this.get_fullname());
00214       if (domain != "") $sformat(psdisplay, "%s.%s", psdisplay, domain);
00215       endian = this.get_endian(domain);
00216       $sformat(psdisplay, "%s -- %0d bytes (%s)", psdisplay,
00217                this.get_n_bytes(domain), endian.name());
00218       this.get_registers(regs, domain);
00219       foreach (regs[j]) begin
00220          $sformat(psdisplay, "%s\n%s", psdisplay,
00221                   regs[j].psdisplay({prefix, "   "}, domain));
00222       end
00223       this.get_virtual_registers(vregs, domain);
00224       foreach (vregs[j]) begin
00225          $sformat(psdisplay, "%s\n%s", psdisplay,
00226                   vregs[j].psdisplay({prefix, "   "}, domain));
00227       end
00228       this.get_memories(mems, domain);
00229       foreach (mems[j]) begin
00230          $sformat(psdisplay, "%s\n%s", psdisplay,
00231                   mems[j].psdisplay({prefix, "   "}, domain));
00232       end
00233    end
00234    else begin
00235       $sformat(psdisplay, "%sBlock %s", prefix, this.get_fullname());
00236       foreach (domains[i]) begin
00237          endian = this.get_endian(domains[i]);
00238          $sformat(psdisplay, "%s\n%s   Domain \"%s\" -- %0d bytes (%s)",
00239                   psdisplay, prefix, domains[i],
00240                   this.get_n_bytes(domains[i]), endian.name());
00241          this.get_registers(regs, domains[i]);
00242          foreach (regs[j]) begin
00243             $sformat(psdisplay, "%s\n%s", psdisplay,
00244                      regs[j].psdisplay({prefix, "      "},
00245                                        domains[i]));
00246          end
00247          this.get_virtual_registers(vregs, domains[i]);
00248          foreach (vregs[j]) begin
00249             $sformat(psdisplay, "%s\n%s", psdisplay,
00250                      vregs[j].psdisplay({prefix, "      "},
00251                                        domains[i]));
00252          end
00253          this.get_memories(mems, domains[i]);
00254          foreach (mems[j]) begin
00255             $sformat(psdisplay, "%s\n%s", psdisplay,
00256                      mems[j].psdisplay({prefix, "      "}, domains[i]));
00257          end
00258       end
00259    end
00260 endfunction: psdisplay
00261 
00262 
00263 function void vmm_ral_block::get_fields(ref vmm_ral_field fields[],
00264                                         input string      domain);
00265    int n;
00266    vmm_ral_reg r[];
00267    vmm_ral_field f[];
00268 
00269    fields = new [0];
00270    this.get_registers(r, domain);
00271    foreach (r[i]) begin
00272       r[i].get_fields(f);
00273       n = fields.size();
00274       fields = new [n + f.size()] (fields);
00275 
00276       foreach (f[j]) begin
00277          fields[n++] = f[j];
00278       end
00279    end
00280 endfunction: get_fields
00281 
00282 function void vmm_ral_block::get_virtual_fields(ref vmm_ral_vfield fields[],
00283                                                 input string      domain);
00284    int n;
00285    vmm_ral_vreg r[];
00286    vmm_ral_vfield f[];
00287 
00288    fields = new [0];
00289    this.get_virtual_registers(r, domain);
00290    foreach (r[i]) begin
00291       r[i].get_fields(f);
00292       n = fields.size();
00293       fields = new [n + f.size()] (fields);
00294 
00295       foreach (f[j]) begin
00296          fields[n++] = f[j];
00297       end
00298    end
00299 endfunction: get_virtual_fields
00300 
00301 function vmm_ral_field vmm_ral_block::get_field_by_name(string name);
00302    // Search the registers to find the first field of the specified name
00303    foreach (this.regs[i]) begin
00304       vmm_ral_field fields[];
00305       this.regs[i].get_fields(fields);
00306       foreach (fields[j]) begin
00307          if (fields[j].get_name() == name) begin
00308             return fields[j];
00309          end
00310       end
00311    end
00312    `vmm_warning(this.log, $psprintf("Unable to locate field \"%s\" in block \"%s\".",
00313                                     name, this.get_fullname()));
00314    get_field_by_name = null;
00315 endfunction: get_field_by_name
00316 
00317 function vmm_ral_vfield vmm_ral_block::get_virtual_field_by_name(string name);
00318    // Search the registers to find the first field of the specified name
00319    foreach (this.vregs[i]) begin
00320       vmm_ral_vfield fields[];
00321       this.vregs[i].get_fields(fields);
00322       foreach (fields[j]) begin
00323          if (fields[j].get_name() == name) begin
00324             return fields[j];
00325          end
00326       end
00327    end
00328    `vmm_warning(this.log, $psprintf("Unable to locate virtual field \"%s\" in block \"%s\".",
00329                                     name, this.get_fullname()));
00330    get_virtual_field_by_name = null;
00331 endfunction: get_virtual_field_by_name
00332 
00333 
00334 function void vmm_ral_block::get_registers(ref vmm_ral_reg regs[],
00335                                            input string    domain);
00336    if (domain == "") begin
00337       regs = new [this.regs.size()];
00338       foreach(this.regs[i]) begin
00339          regs[i] = this.regs[i];
00340       end
00341    end
00342    else begin
00343       int n = 0;
00344       regs = new [this.regs.size()];
00345       foreach(this.regs[i]) begin
00346          // Is the register in the specified domain?
00347          string domains[];
00348          this.regs[i].get_domains(domains);
00349          foreach(domains[j]) begin
00350             if (domains[j] == domain) begin
00351                regs[n++] = this.regs[i];
00352                break;
00353             end
00354          end
00355       end
00356       regs = new [n] (regs);
00357    end
00358 endfunction: get_registers
00359 
00360 function void vmm_ral_block::get_virtual_registers(ref vmm_ral_vreg vregs[],
00361                                                    input string    domain);
00362    if (domain == "") begin
00363       vregs = new [this.vregs.size()];
00364       foreach(this.vregs[i]) begin
00365          vregs[i] = this.vregs[i];
00366       end
00367    end
00368    else begin
00369       int n = 0;
00370       vregs = new [this.vregs.size()];
00371       foreach(this.vregs[i]) begin
00372          // Is the register in the specified domain?
00373          string domains[];
00374          this.vregs[i].get_domains(domains);
00375          foreach(domains[j]) begin
00376             if (domains[j] == domain) begin
00377                vregs[n++] = this.vregs[i];
00378                break;
00379             end
00380          end
00381       end
00382       vregs = new [n] (vregs);
00383    end
00384 endfunction: get_virtual_registers
00385 
00386 function vmm_ral_reg vmm_ral_block::get_reg_by_name(string name);
00387    foreach (this.regs[i]) begin
00388       if (this.regs[i].get_name() == name) begin
00389          return this.regs[i];
00390       end
00391    end
00392    `vmm_warning(this.log, $psprintf("Unable to locate register \"%s\" in block \"%s\".",
00393                                     name, this.get_fullname()));
00394    get_reg_by_name = null;
00395 endfunction: get_reg_by_name
00396 
00397 function vmm_ral_vreg vmm_ral_block::get_vreg_by_name(string name);
00398    foreach (this.vregs[i]) begin
00399       if (this.vregs[i].get_name() == name) begin
00400          return this.vregs[i];
00401       end
00402    end
00403    `vmm_warning(this.log, $psprintf("Unable to locate virtual register \"%s\" in block \"%s\".",
00404                                     name, this.get_fullname()));
00405    get_vreg_by_name = null;
00406 endfunction: get_vreg_by_name
00407 
00408 function vmm_ral_reg vmm_ral_block::get_reg_by_offset(bit [`VMM_RAL_ADDR_WIDTH-1:0] offset,
00409                                                       string                        domain);
00410    foreach (this.regs[i]) begin
00411       if (this.regs[i].get_offset_in_block(domain) == offset) begin
00412          return this.regs[i];
00413       end
00414    end
00415    `vmm_warning(this.log, $psprintf("Unable to locate register at offset 0x%h %0sin block \"%s\".",
00416                                     offset, ((domain == "") ? "" : $psprintf("in domain \"%s\" ",
00417                                                                              domain)),
00418                                     this.get_fullname()));
00419    get_reg_by_offset = null;
00420 endfunction: get_reg_by_offset
00421 
00422 
00423 function void vmm_ral_block::get_memories(ref vmm_ral_mem mems[],
00424                                           input string    domain);
00425    if (domain == "") begin
00426       mems = new [this.mems.size()];
00427       foreach(this.mems[i]) begin
00428          mems[i] = this.mems[i];
00429       end
00430    end
00431    else begin
00432       int n = 0;
00433       mems = new [this.mems.size()];
00434       foreach(this.mems[i]) begin
00435          // Is the memory in the specified domain?
00436          string domains[];
00437          this.mems[i].get_domains(domains);
00438          foreach(domains[j]) begin
00439             if (domains[j] == domain) begin
00440                mems[n++] = this.mems[i];
00441                break;
00442             end
00443          end
00444       end
00445       mems = new [n] (mems);
00446    end
00447 endfunction: get_memories
00448 
00449 
00450 function vmm_ral_mem vmm_ral_block::get_mem_by_name(string name);
00451    foreach (this.mems[i]) begin
00452       if (this.mems[i].get_name() == name) begin
00453          return this.mems[i];
00454       end
00455    end
00456    `vmm_warning(this.log, $psprintf("Unable to locate memory \"%s\" in block \"%s\".",
00457                                     name, this.get_fullname()));
00458    get_mem_by_name = null;
00459 endfunction: get_mem_by_name
00460 
00461 
00462 function vmm_ral_mem vmm_ral_block::get_mem_by_offset(bit [`VMM_RAL_ADDR_WIDTH-1:0] offset,
00463                                                       string                        domain);
00464    //get_mem_by_offset = this.mems.first() with index: (this.mems[index].offset_in_block == offset);
00465 endfunction: get_mem_by_offset
00466 
00467 
00468 function void vmm_ral_block::get_constraints(ref string names[]);
00469 endfunction: get_constraints
00470 
00471 
00472 function bit vmm_ral_block::set_cover(bit is_on);
00473    set_cover = super.set_cover(is_on);
00474 
00475    if (is_on && !super.is_cover_on()) return set_cover;
00476 
00477    foreach (this.regs[i]) begin
00478       this.regs[i].set_cover(is_on);
00479    end
00480    foreach (this.mems[i]) begin
00481       this.mems[i].set_cover(is_on);
00482    end
00483 endfunction: set_cover
00484 
00485 
00486 function void vmm_ral_block::reset(string           domain,
00487                                    vmm_ral::reset_e kind);
00488    vmm_ral_reg regs[];
00489    vmm_ral_mem mems[];
00490 
00491    this.get_registers(regs, domain);
00492    foreach (regs[i]) begin
00493       regs[i].reset(kind);
00494    end
00495 
00496    this.get_memories(mems, domain);
00497    foreach (mems[i]) begin
00498       vmm_ral_vreg vregs[];
00499       mems[i].get_virtual_registers(vregs);
00500       foreach (vregs[j]) begin
00501          vregs[j].reset(kind);
00502       end
00503    end
00504 endfunction: reset
00505 
00506 
00507 function bit vmm_ral_block::needs_update();
00508    needs_update = 0;
00509    foreach (this.regs[i]) begin
00510       if (this.regs[i].needs_update()) begin
00511          return 1;
00512       end
00513    end
00514 endfunction: needs_update
00515 
00516 
00517 task vmm_ral_block::update(output vmm_rw::status_e status,
00518                            input  vmm_ral::path_e  path);
00519    string domains[];
00520    bit    updated;
00521 
00522    status = vmm_rw::IS_OK;
00523    foreach (this.regs[i]) begin
00524       if (!this.regs[i].needs_update()) continue;
00525 
00526       if (path == vmm_ral::BACKDOOR) begin
00527          this.regs[i].update(status, path);
00528          if (status != vmm_rw::IS_OK) return;
00529          continue;
00530       end
00531 
00532       // Find the first writeable domain to
00533       // perform the update through
00534       this.regs[i].get_domains(domains);
00535       updated = 0;
00536       foreach (domains[j]) begin
00537          if (this.regs[i].get_rights(domains[j]) != vmm_ral::RO) begin
00538             this.regs[i].update(status, path, domains[j]);
00539             if (status == vmm_rw::IS_OK) begin
00540                updated = 1;
00541                break;
00542             end
00543          end
00544       end
00545       if (!updated) begin
00546          `vmm_error(this.log, $psprintf("Register \"%s\" could not be updated",
00547                                         regs[i].get_fullname()));
00548          if (status == vmm_rw::IS_OK) status = vmm_rw::ERROR;
00549          return;
00550       end
00551    end
00552 endtask: update
00553 
00554 
00555 task vmm_ral_block::mirror(output vmm_rw::status_e status,
00556                            input  vmm_ral::check_e check,
00557                            input  vmm_ral::path_e  path);
00558    string domains[];
00559    bit mirrored;
00560 
00561    status = vmm_rw::IS_OK;
00562    foreach (this.regs[i]) begin
00563 
00564       if (path == vmm_ral::BACKDOOR) begin
00565          this.regs[i].mirror(status, check, path);
00566          if (status != vmm_rw::IS_OK) return;
00567          continue;
00568       end
00569 
00570       // Find the first readable domain to
00571       // perform the update through
00572       this.regs[i].get_domains(domains);
00573       mirrored = 0;
00574       foreach (domains[j]) begin
00575          if (this.regs[i].get_rights(domains[j]) != vmm_ral::WO) begin
00576             this.regs[i].mirror(status, check, path, domains[0]);
00577             if (status == vmm_rw::IS_OK) begin
00578                mirrored = 1;
00579                break;
00580             end
00581          end
00582       end
00583       if (!mirrored) begin
00584          `vmm_error(this.log, $psprintf("Register \"%s\" could not be mirrored",
00585                                         regs[i].get_fullname()));
00586          if (status == vmm_rw::IS_OK) status = vmm_rw::ERROR;
00587          return;
00588       end
00589    end
00590 endtask: mirror
00591 
00592 
00593 task vmm_ral_block::readmemh(string filename);
00594 endtask: readmemh
00595 
00596 
00597 task vmm_ral_block::writememh(string filename);
00598 endtask: writememh
00599 
00600 
00601 function void vmm_ral_block::XsampleX(bit [`VMM_RAL_ADDR_WIDTH-1:0] addr,
00602                                       int                           domain);
00603    this.sample(addr, domain);
00604 endfunction
00605 
00606 
00607 function void vmm_ral_block::sample(bit [`VMM_RAL_ADDR_WIDTH-1:0] addr,
00608                                     int                           domain);
00609    // Nothing to do in this base class
00610 endfunction

Intelligent Design Verification
Intelligent Design Verification
Project: VMM, Revision: 1.0.0
Copyright (c) 2008 Intelligent Design Verification.
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
A copy of the license is included here:
http://www.intelligentdv.com/licenses/fdl.txt
doxygen
Doxygen Version: 1.5.6
Sat Oct 18 11:38:21 2008
Find a documentation bug? Report bugs to: bugs.intelligentdv.com Project: DoxygenFilterSV