VMM OpenSource - sv/RAL/vmm_ral_reg.sv

sv/RAL/vmm_ral_reg.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_reg_callbacks extends vmm_ral_callbacks;
00024 
00025    virtual task pre_write(vmm_ral_reg                       rg,
00026                           ref bit [`VMM_RAL_DATA_WIDTH-1:0] wdat,
00027                           ref vmm_ral::path_e               path,
00028                           ref string                        domain);
00029    endtask: pre_write
00030 
00031    virtual task post_write(vmm_ral_reg                   rg,
00032                            bit [`VMM_RAL_DATA_WIDTH-1:0] wdat,
00033                            vmm_ral::path_e               path,
00034                            string                        domain,
00035                            ref vmm_rw::status_e          status);
00036    endtask: post_write
00037 
00038    virtual task pre_read(vmm_ral_reg          rg,
00039                          ref vmm_ral::path_e  path,
00040                          ref string           domain);
00041    endtask: pre_read
00042 
00043    virtual task post_read(vmm_ral_reg                       rg,
00044                           ref bit [`VMM_RAL_DATA_WIDTH-1:0] rdat,
00045                           input vmm_ral::path_e             path,
00046                           input string                      domain,
00047                           ref vmm_rw::status_e              status);
00048    endtask: post_read
00049 endclass: vmm_ral_reg_callbacks
00050 
00051 
00052 virtual class vmm_ral_reg_frontdoor;
00053    static vmm_log log = new("vmm_ral_reg_frontdoor", "class");
00054    
00055    extern virtual task write(output vmm_rw::status_e              status,
00056                              input  bit [`VMM_RAL_DATA_WIDTH-1:0] data,
00057                              input  int                           data_id = -1,
00058                              input  int                           scenario_id = -1,
00059                              input  int                           stream_id = -1);
00060    extern virtual task read(output vmm_rw::status_e              status,
00061                             output bit [`VMM_RAL_DATA_WIDTH-1:0] data,
00062                             input  int                           data_id = -1,
00063                             input  int                           scenario_id = -1,
00064                             input  int                           stream_id = -1);
00065 endclass: vmm_ral_reg_frontdoor
00066 
00067 
00068 
00069 class vmm_ral_reg;
00070    static vmm_log log = new("RAL", "register");
00071 
00072    static vmm_ral_reg all_regs[`VMM_AA_INT]; // Keeps track of all registers in the RAL Model
00073    static local int unsigned reg_id_factory = 0;
00074    local int unsigned reg_id = 0;
00075    local bit locked;
00076    local vmm_ral_block parent;
00077    local string name;
00078    local int unsigned  n_bits;
00079    local int unsigned  n_used_bits;
00080 
00081    local logic [`VMM_RAL_ADDR_WIDTH-1:0] offset_in_block[];
00082    local string                          domains[];
00083    local vmm_ral::access_e               rights[];
00084 
00085    local vmm_ral_field fields[$];   // Fields in LSB to MSB order
00086    local string        constr[];
00087    local event         value_change;
00088 
00089    local vmm_ral_access        ral_access;
00090    local vmm_ral_reg_frontdoor frontdoor[];
00091    local vmm_ral_reg_backdoor  backdoor;
00092 
00093    local vmm_ral_reg_callbacks callbacks[$];
00094 
00095    local string attributes[string];
00096 
00097    local int has_cover;
00098    local int cover_on;
00099 
00100    local semaphore atomic;
00101 
00102    /*local*/ bit Xis_busyX;
00103    /*local*/ bit Xis_locked_by_fieldX;
00104 
00105    extern function new(vmm_ral_block                 parent,
00106                        string                        name,
00107                        int unsigned                  n_bits,
00108                        bit [`VMM_RAL_ADDR_WIDTH-1:0] offset,
00109                        string                        domain = "",
00110                        int                           cover_on = vmm_ral::NO_COVERAGE,
00111                        bit [1:0]                     rights = 2'b11,
00112                        bit                           unmapped = 0,
00113                        int                           has_cover = vmm_ral::NO_COVERAGE);
00114 
00115    /*local*/ extern function void Xlock_modelX();
00116    /*local*/ extern function void add_domain(bit [`VMM_RAL_ADDR_WIDTH-1:0] offset,
00117                                              string                        domain,
00118                                              bit [1:0]                     rights,
00119                                              bit                           unmapped = 0);
00120    
00121    local virtual function void domain_coverage(string domain,
00122                                                bit    rights,
00123                                                int    idx);
00124    endfunction
00125    
00126    /*local*/ extern function void register_field(vmm_ral_field field);
00127    /*local*/ extern function void Xregister_ral_accessX(vmm_ral_access access);
00128    /*local*/ extern function void Xadd_constraintsX(string name);
00129    /*local*/ extern task XatomicX(bit on);
00130    /*local*/ extern task XwriteX(output vmm_rw::status_e             status,
00131                                  input  bit[`VMM_RAL_DATA_WIDTH-1:0] value,
00132                                  input  vmm_ral::path_e              path,
00133                                  input  string                       domain,
00134                                  input  int                          data_id,
00135                                  input  int                          scenario_id,
00136                                  input  int                          stream_id);
00137    /*local*/ extern task XreadX(output vmm_rw::status_e             status,
00138                                 output bit[`VMM_RAL_DATA_WIDTH-1:0] value,
00139                                 input  vmm_ral::path_e              path,
00140                                 input  string                       domain,
00141                                 input  int                          data_id,
00142                                 input  int                          scenario_id,
00143                                 input  int                          stream_id);
00144    
00145    extern virtual function string get_name();
00146    extern virtual function string get_fullname();
00147    extern virtual function int get_n_domains();
00148    extern virtual function void get_domains(ref string domains[]);
00149    extern virtual function vmm_ral::access_e get_rights(string domain = "");
00150    extern virtual function vmm_ral_block get_block();
00151    extern virtual function bit [`VMM_RAL_ADDR_WIDTH-1:0] get_offset_in_block(string domain = ""); 
00152    extern virtual function bit [`VMM_RAL_ADDR_WIDTH-1:0] get_address_in_system(string domain = "");
00153    extern virtual function int unsigned get_n_bytes();
00154    extern virtual function void get_constraints(ref string names[]);
00155 
00156    extern virtual function void display(string prefix = "",
00157                                         string domain = "");
00158    extern virtual function string psdisplay(string prefix = "",
00159                                             string domain = "");
00160 
00161    extern virtual function void get_fields(ref vmm_ral_field fields[]);
00162    extern virtual function vmm_ral_field get_field_by_name(string name);
00163 
00164    extern virtual function void set_attribute(string name,
00165                                               string value);
00166    extern virtual function string get_attribute(string name,
00167                                                 bit inherited = 1);
00168    extern virtual function void get_all_attributes(ref string names[],
00169                                                    input bit inherited = 1);
00170 
00171    extern virtual function bit can_cover(int models);
00172    extern virtual function int set_cover(int is_on);
00173    extern virtual function bit is_cover_on(int is_on);
00174 
00175    extern local virtual function void XforceX(bit [`VMM_RAL_DATA_WIDTH-1:0] value,
00176                                               vmm_ral::path_e               path,
00177                                               string                        domain);
00178    extern local virtual function void XwroteX(bit [`VMM_RAL_DATA_WIDTH-1:0] value,
00179                                               vmm_ral::path_e               path,
00180                                               string                        domain);
00181    extern virtual function void set(bit [`VMM_RAL_DATA_WIDTH-1:0] value);
00182    extern virtual function bit predict(bit [`VMM_RAL_DATA_WIDTH-1:0] value);
00183    extern virtual function bit[`VMM_RAL_DATA_WIDTH-1:0] get();
00184    extern virtual function void reset(vmm_ral::reset_e kind = vmm_ral::HARD);
00185    extern virtual function logic [`VMM_RAL_DATA_WIDTH-1:0]
00186                     get_reset(vmm_ral::reset_e kind = vmm_ral::HARD);
00187    extern virtual function bit needs_update(); 
00188  
00189    extern virtual task update(output vmm_rw::status_e status,
00190                               input  vmm_ral::path_e  path = vmm_ral::DEFAULT,
00191                               input  string           domain = "");
00192    extern virtual task write(output vmm_rw::status_e             status,
00193                              input  bit[`VMM_RAL_DATA_WIDTH-1:0] value,
00194                              input  vmm_ral::path_e              path = vmm_ral::DEFAULT,
00195                              input  string                       domain = "",
00196                              input  int                          data_id = -1,
00197                              input  int                          scenario_id = -1,
00198                              input  int                          stream_id = -1);
00199    extern virtual task read(output vmm_rw::status_e             status,
00200                             output bit[`VMM_RAL_DATA_WIDTH-1:0] value,
00201                             input  vmm_ral::path_e              path = vmm_ral::DEFAULT,
00202                             input  string                       domain = "",
00203                             input  int                          data_id = -1,
00204                             input  int                          scenario_id = -1,
00205                             input  int                          stream_id = -1);
00206    extern virtual task poke(output vmm_rw::status_e             status,
00207                             input  bit[`VMM_RAL_DATA_WIDTH-1:0] value,
00208                             input  int                          data_id = -1,
00209                             input  int                          scenario_id = -1,
00210                             input  int                          stream_id = -1);
00211    extern virtual task peek(output vmm_rw::status_e             status,
00212                             output bit[`VMM_RAL_DATA_WIDTH-1:0] value,
00213                             input  int                          data_id = -1,
00214                             input  int                          scenario_id = -1,
00215                             input  int                          stream_id = -1);
00216    extern virtual task mirror(output vmm_rw::status_e status,
00217                               input vmm_ral::check_e  check  = vmm_ral::QUIET,
00218                               input vmm_ral::path_e   path = vmm_ral::DEFAULT,
00219                               input string            domain = "");
00220   
00221    extern function void set_frontdoor(vmm_ral_reg_frontdoor ftdr,
00222                                       string                domain = "");
00223    extern function vmm_ral_reg_frontdoor get_frontdoor(string domain = "");
00224    extern function void set_backdoor(vmm_ral_reg_backdoor bkdr);
00225    extern function vmm_ral_reg_backdoor get_backdoor();
00226 
00227    extern function void prepend_callback(vmm_ral_reg_callbacks cb);
00228    extern function void append_callback(vmm_ral_reg_callbacks cb);
00229    extern function void unregister_callback(vmm_ral_reg_callbacks cb);
00230 
00231    extern local function int get_domain_index(string domain);
00232    extern virtual local function void sample(bit [`VMM_RAL_DATA_WIDTH-1:0] data,
00233                                              bit                           is_read,
00234                                              int                           domain);
00235 
00236    extern function int unsigned get_reg_ID();
00237 endclass: vmm_ral_reg
00238 
00239 
00240 function vmm_ral_reg::new(vmm_ral_block                 parent,
00241                           string                        name,
00242                           int unsigned                  n_bits,
00243                           bit [`VMM_RAL_ADDR_WIDTH-1:0] offset,
00244                           string                        domain = "",
00245                           int                           cover_on = vmm_ral::NO_COVERAGE,
00246                           bit [1:0]                     rights = 2'b11,
00247                           bit                           unmapped = 0,
00248                           int                           has_cover = vmm_ral::NO_COVERAGE);
00249    this.locked = 0;
00250 
00251    this.parent = parent;
00252    this.parent.register_reg(this);
00253 
00254    this.name = name;
00255    this.has_cover = has_cover;
00256    this.cover_on = vmm_ral::NO_COVERAGE;
00257    void'(this.set_cover(cover_on));
00258 
00259    if (n_bits == 0) begin
00260       `vmm_error(this.log, $psprintf("Register \"%s\" cannot have 0 bits", this.get_name()));
00261       n_bits = 1;
00262    end
00263    if (n_bits > `VMM_RAL_DATA_WIDTH) begin
00264       `vmm_error(this.log, $psprintf("Register \"%s\" cannot have more than %0d bits (%0d)", this.get_name(), `VMM_RAL_DATA_WIDTH, n_bits));
00265       n_bits = `VMM_RAL_DATA_WIDTH;
00266    end
00267    this.n_bits = n_bits;
00268    this.n_used_bits = 0;
00269    this.add_domain(offset, domain, rights, unmapped);
00270 
00271    this.atomic = new(1);
00272 
00273    this.Xis_busyX = 0;
00274    this.Xis_locked_by_fieldX = 1'b0;
00275    // Initialize Register ID
00276    this.reg_id = ++this.reg_id_factory;
00277    all_regs[this.reg_id] = this;
00278 endfunction: new
00279 
00280 
00281 function void vmm_ral_reg::Xlock_modelX();
00282    int idx;
00283    string fullname;
00284 
00285    if (this.locked) return;
00286 
00287    this.locked = 1;
00288 
00289 endfunction: Xlock_modelX
00290 
00291 
00292 function void vmm_ral_reg::add_domain(bit [`VMM_RAL_ADDR_WIDTH-1:0] offset,
00293                                       string                        domain,
00294                                       bit [1:0]                     rights,
00295                                       bit                           unmapped = 0);
00296    // Verify that this is a valid domain in the block
00297    string domains[];
00298    vmm_ral::access_e acc;
00299 
00300    if (this.locked) begin
00301       `vmm_error(this.log, "Cannot add domain to locked register model");
00302       return;
00303    end
00304 
00305    case (rights)
00306      2'b11: acc = vmm_ral::RW;
00307      2'b10: acc = vmm_ral::RO;
00308      2'b01: acc = vmm_ral::WO;
00309      default:
00310        `vmm_error(this.log,
00311                   $psprintf("Register \"%s\" has no access rights in domain \"%s\"",
00312                             this.get_name(), domain));
00313    endcase
00314 
00315    this.parent.get_domains(domains);
00316    foreach(domains[i]) begin
00317       if (domains[i] == domain) begin
00318          automatic int n = this.offset_in_block.size();
00319    
00320          this.offset_in_block = new [n + 1] (this.offset_in_block);
00321          this.offset_in_block[n] = (unmapped) ? 'x : offset;
00322     
00323          this.domains = new [n + 1] (this.domains);
00324          this.domains[n] = domain;
00325 
00326          this.rights = new [n + 1] (this.rights);
00327          this.rights[n] = acc;
00328 
00329          this.frontdoor = new [n + 1] (this.frontdoor);
00330          this.frontdoor[n] = null;
00331 
00332          this.domain_coverage(domain, rights, n);
00333          return;
00334       end
00335    end
00336    `vmm_error(this.log, $psprintf("Domain \"%s\" not found in parent block %s of register \"%s\"",
00337                                   domain, this.parent.get_name(), this.get_name()));
00338 endfunction: add_domain
00339 
00340 
00341 function void vmm_ral_reg::register_field(vmm_ral_field field);
00342    int offset;
00343    int idx;
00344    
00345    if (this.locked) begin
00346       `vmm_error(this.log, "Cannot add field to locked register model");
00347       return;
00348    end
00349 
00350    if (field == null) `vmm_fatal(this.log, "Attempting to register NULL field");
00351 
00352    // Store fields in LSB to MSB order
00353    offset = field.get_lsb_pos_in_register();
00354 
00355    idx = -1;
00356    foreach (this.fields[i]) begin
00357       if (offset < this.fields[i].get_lsb_pos_in_register()) begin
00358          int j = i;
00359          this.fields.insert(j, field);
00360          idx = i;
00361          break;
00362       end
00363    end
00364    if (idx < 0) begin
00365       this.fields.push_back(field);
00366       idx = this.fields.size()-1;
00367    end
00368 
00369    this.n_used_bits += field.get_n_bits();
00370    
00371    // Check if there are too many fields in the register
00372    if (this.n_used_bits > this.n_bits) begin
00373       `vmm_error(this.log, $psprintf("Fields use more bits (%0d) than available in register \"%s\" (%0d)",
00374                                      this.n_used_bits, this.get_name(), this.n_bits));
00375    end
00376 
00377    // Check if there are overlapping fields
00378    if (idx > 0) begin
00379       if (this.fields[idx-1].get_lsb_pos_in_register() +
00380           this.fields[idx-1].get_n_bits() > offset) begin
00381          `vmm_error(this.log, $psprintf("Field %s overlaps field %s in register \"%s\"",
00382                                         this.fields[idx-1].get_name(),
00383                                         field.get_name(), this.get_name()));
00384       end
00385    end
00386    if (idx < this.fields.size()-1) begin
00387       if (offset + field.get_n_bits() >
00388           this.fields[idx+1].get_lsb_pos_in_register()) begin
00389          `vmm_error(this.log, $psprintf("Field %s overlaps field %s in register \"%s\"",
00390                                         field.get_name(),
00391                                         this.fields[idx+1].get_name(),
00392 
00393                                       this.get_name()));
00394       end
00395    end
00396 endfunction: register_field
00397 
00398 
00399 function void vmm_ral_reg::Xregister_ral_accessX(vmm_ral_access access);
00400    // There can only be one RAL Access on a RAL model
00401    if (this.ral_access != null && this.ral_access != access) begin
00402       `vmm_fatal(this.log, $psprintf("Register \"%s\" is already used by another RAL access instance", this.get_name()));
00403    end
00404    this.ral_access = access;
00405 endfunction: Xregister_ral_accessX
00406 
00407 
00408 function void vmm_ral_reg::Xadd_constraintsX(string name);
00409    int n;
00410 
00411    if (this.locked) begin
00412       `vmm_error(this.log, "Cannot add constraints to locked register model");
00413       return;
00414    end
00415 
00416    // Check if the constraint block already exists
00417    foreach (this.constr[i]) begin
00418       if (this.constr[i] == name) begin
00419          `vmm_warning(this.log, $psprintf("Constraint \"%s\" already added",
00420                                           name));
00421          return;
00422       end
00423    end
00424 
00425    // Append the constraint name to the list
00426    n = this.constr.size();
00427    this.constr = new [n+1] (this.constr);
00428    this.constr[n] = name;
00429 endfunction: Xadd_constraintsX
00430 
00431 
00432 task vmm_ral_reg::XatomicX(bit on);
00433    if (on) this.atomic.get(1);
00434    else begin
00435       // Maybe a key was put back in by a spurious call to reset()
00436       void'(this.atomic.try_get(1));
00437       this.atomic.put(1);
00438    end
00439 endtask: XatomicX
00440 
00441 
00442 function string vmm_ral_reg::get_name();
00443    get_name = this.name;
00444 endfunction: get_name
00445 
00446 
00447 function string vmm_ral_reg::get_fullname();
00448    vmm_ral_block blk;
00449 
00450    get_fullname = this.get_name();
00451 
00452    // Do not include top-level name in full name
00453    blk = this.get_block();
00454    if (blk == null) return get_fullname;
00455    if (blk.get_parent() == null) return get_fullname;
00456 
00457    get_fullname = {this.parent.get_fullname(), ".", get_fullname};
00458 endfunction: get_fullname
00459 
00460 
00461 function int vmm_ral_reg::get_n_domains();
00462    get_n_domains = this.domains.size();
00463 endfunction: get_n_domains
00464 
00465 
00466 function void vmm_ral_reg::get_domains(ref string domains[]);
00467    domains = new [this.domains.size()] (this.domains);
00468 endfunction: get_domains
00469 
00470 
00471 function vmm_ral::access_e vmm_ral_reg::get_rights(string domain = "");
00472    int i;
00473 
00474    // No right restrictions if not shared
00475    if (this.domains.size() == 1) begin
00476       return vmm_ral::RW;
00477    end
00478 
00479    i = this.get_domain_index(domain);
00480    if (i < 0) return vmm_ral::RW;
00481 
00482    get_rights = this.rights[i];
00483 endfunction: get_rights
00484 
00485 
00486 function vmm_ral_block vmm_ral_reg::get_block();
00487    get_block = this.parent;
00488 endfunction: get_block
00489 
00490 
00491 function bit [`VMM_RAL_ADDR_WIDTH-1:0] vmm_ral_reg::get_offset_in_block(string domain = "");
00492    foreach (this.domains[i]) begin
00493       if (this.domains[i] == domain) begin
00494          if (this.offset_in_block[i] === 'x) begin
00495             `vmm_warning(this.log, $psprintf("Register \"%s\" is unmapped in domain \"%s\".", this.get_name(), domain));
00496             return '0;
00497          end
00498          
00499          return this.offset_in_block[i];
00500       end
00501    end
00502    `vmm_warning(this.log, $psprintf("Unable to find offset within domain \"%s\" in register \"%s\".",
00503                                     domain, this.get_name()));
00504    get_offset_in_block = '1;
00505 endfunction: get_offset_in_block
00506 
00507 
00508 function bit [`VMM_RAL_ADDR_WIDTH-1:0] vmm_ral_reg::get_address_in_system(string domain = "");
00509    bit [`VMM_RAL_ADDR_WIDTH-1:0] addr[];
00510          
00511    int i = this.get_domain_index(domain);
00512    if (i < 0) return 0;
00513 
00514    if (this.ral_access == null) begin
00515       `vmm_fatal(this.parent.log,
00516                  "RAL model is not associated with an access transactor");
00517       return 0;
00518    end
00519          
00520    if (this.offset_in_block[i] === 'x) begin
00521       `vmm_error(this.log, $psprintf("Register \"%s\" is unmapped in domain \"%s\".", this.get_name(), this.domains[i]));
00522       return '1;
00523    end
00524          
00525    void'(this.ral_access.Xget_physical_addressesX(this.offset_in_block[i],
00526                                                   0, this.get_n_bytes(),
00527                                                   this.parent, this.domains[i],
00528                                                   addr));
00529 
00530    get_address_in_system = addr[addr.size()-1];
00531 
00532    // Make sure to return the lower address as Xget_physical_addressesX()
00533    // returns the address in little-endian sequence.
00534    if (addr[0] < get_address_in_system) get_address_in_system = addr[0];
00535 endfunction: get_address_in_system
00536 
00537 
00538 function int unsigned vmm_ral_reg::get_n_bytes();
00539    get_n_bytes = ((this.n_bits-1) / 8) + 1;
00540 endfunction: get_n_bytes
00541 
00542 
00543 function void vmm_ral_reg::display(string prefix = "",
00544                                    string domain = "");
00545    $write("%s\n", this.psdisplay(prefix, domain));
00546 endfunction: display
00547 
00548 
00549 function string vmm_ral_reg::psdisplay(string prefix = "",
00550                                        string domain = "");
00551    $sformat(psdisplay, "%sRegister %s -- %0d bytes @", prefix,
00552             this.get_fullname(), this.get_n_bytes());
00553    foreach (this.domains[i]) begin
00554       if (this.domains[i] == domain) begin
00555          if (this.offset_in_block[i] === 'x) begin
00556             psdisplay = {psdisplay, "none"};
00557          end
00558          else begin
00559             $sformat(psdisplay, "%s'h%h", psdisplay,
00560                      this.get_address_in_system(domain));
00561          end
00562          break;
00563       end
00564    end
00565    if (this.attributes.num() > 0) begin
00566       string name;
00567       this.attributes.first(name);
00568       psdisplay = {psdisplay, "\n", prefix, "Attributes:"};
00569       do begin
00570          $sformat(psdisplay, " %s=\"%s\"", name, this.attributes[name]);
00571       end while (this.attributes.next(name));
00572    end
00573    foreach(this.fields[i]) begin
00574       $sformat(psdisplay, "%s\n%s", psdisplay,
00575                this.fields[i].psdisplay({prefix, "   "}));
00576    end
00577 endfunction: psdisplay
00578 
00579 
00580 function void vmm_ral_reg::get_fields(ref vmm_ral_field fields[]);
00581    fields = new [this.fields.size()];
00582    foreach(this.fields[i]) begin
00583       fields[i] = this.fields[i];
00584    end
00585 endfunction: get_fields
00586 
00587 
00588 function vmm_ral_field vmm_ral_reg::get_field_by_name(string name);
00589    foreach (this.fields[i]) begin
00590       if (this.fields[i].get_name() == name) begin
00591          return this.fields[i];
00592       end
00593    end
00594    `vmm_warning(this.log, $psprintf("Unable to locate field \"%s\" in register \"%s\".",
00595                                     name, this.get_name()));
00596    get_field_by_name = null;
00597 endfunction: get_field_by_name
00598 
00599 
00600 function void vmm_ral_reg::get_constraints(ref string names[]);
00601    names = new [this.constr.size()] (this.constr);
00602 endfunction: get_constraints
00603 
00604 
00605 function void vmm_ral_reg::set_attribute(string name,
00606                                          string value);
00607    if (name == "") begin
00608       `vmm_error(this.log, $psprintf("Cannot set anonymous attribute \"\" in register \"%s\". Please specify an attribute name.",
00609                                        name, this.get_fullname()));
00610       return;
00611    end
00612 
00613    if (this.attributes.exists(name)) begin
00614       if (value != "") begin
00615          `vmm_warning(this.log, $psprintf("Redefining attributed \"%s\" in register \"%s\" to \"%s\".",
00616                                           name, this.get_fullname(), value));
00617          this.attributes[name] = value;
00618       end
00619       else begin
00620          this.attributes.delete(name);
00621       end
00622       return;
00623    end
00624 
00625    if (value == "") begin
00626       `vmm_warning(this.log, $psprintf("Attempting to delete non-existent attribute \"%s\" in register \"%s\".",
00627                                        name, this.get_fullname()));
00628       return;
00629    end
00630 
00631    this.attributes[name] = value;
00632 endfunction: set_attribute
00633 
00634 
00635 function string vmm_ral_reg::get_attribute(string name,
00636                                            bit inherited = 1);
00637    if (this.attributes.exists(name)) begin
00638       return this.attributes[name];
00639    end
00640 
00641    if (inherited) return this.parent.get_attribute(name);
00642 
00643    return "";
00644 endfunction: get_attribute
00645 
00646 
00647 function void vmm_ral_reg::get_all_attributes(ref string names[],
00648                                               input bit inherited = 1);
00649    string tmp[];
00650    string name;
00651    bit    ok;
00652    int    i;
00653 
00654    if (inherited) this.parent.get_all_attributes(tmp);
00655 
00656    i = tmp.size();
00657    tmp = new [tmp.size() + this.attributes.num()] (tmp);
00658 
00659    ok = this.attributes.first(name);
00660    while (ok) begin
00661       int found = 0;
00662       foreach (tmp[j]) begin
00663          if (tmp[j] == name) begin
00664             found = 1;
00665             break;
00666          end
00667       end
00668       if (!found) tmp[i++] = name;
00669       ok = this.attributes.next(name);
00670    end
00671    names = new [i] (tmp);
00672 endfunction: get_all_attributes
00673 
00674 
00675 function bit vmm_ral_reg::can_cover(int models);
00676    return ((this.has_cover & models) == models);
00677 endfunction: can_cover
00678 
00679 
00680 function int vmm_ral_reg::set_cover(int is_on);
00681    if (is_on == vmm_ral::NO_COVERAGE) begin
00682       this.cover_on = is_on;
00683       return this.cover_on;
00684    end
00685 
00686    if ((this.has_cover & is_on) == 0) begin
00687       `vmm_warning(this.log, $psprintf("Register \"%s\" - Cannot turn ON any coverage becasue the corresponding coverage model was not generated.", this.get_fullname()));
00688       return this.cover_on;
00689    end
00690 
00691    if (is_on & vmm_ral::REG_BITS) begin
00692       if (this.has_cover & vmm_ral::REG_BITS) begin
00693           this.cover_on |= vmm_ral::REG_BITS;
00694       end else begin
00695           `vmm_warning(this.log, $psprintf("Register \"%s\" - Cannot turn ON Register Bit coverage becasue the corresponding coverage model was not generated.", this.get_fullname()));
00696       end
00697    end
00698 
00699    if (is_on & vmm_ral::FIELD_VALS) begin
00700       if (this.has_cover & vmm_ral::FIELD_VALS) begin
00701           this.cover_on |= vmm_ral::FIELD_VALS;
00702       end else begin
00703           `vmm_warning(this.log, $psprintf("Register \"%s\" - Cannot turn ON Field Value coverage becasue the corresponding coverage model was not generated.", this.get_fullname()));
00704       end
00705    end
00706 
00707    if (is_on & vmm_ral::ADDR_MAP) begin
00708       if (this.has_cover & vmm_ral::ADDR_MAP) begin
00709           this.cover_on |= vmm_ral::ADDR_MAP;
00710       end else begin
00711           `vmm_warning(this.log, $psprintf("Register \"%s\" - Cannot turn ON Address Map coverage becasue the corresponding coverage model was not generated.", this.get_fullname()));
00712       end
00713    end
00714 
00715    set_cover = this.cover_on;
00716 endfunction: set_cover
00717 
00718 
00719 function bit vmm_ral_reg::is_cover_on(int is_on);
00720    if (this.can_cover(is_on) == 0) return 0;
00721    return ((this.cover_on & is_on) == is_on);
00722 endfunction: is_cover_on
00723 
00724 
00725 function void vmm_ral_reg::XforceX(bit [`VMM_RAL_DATA_WIDTH-1:0] value,
00726                                    vmm_ral::path_e               path,
00727                                    string                        domain);
00728    // Fields are stored in LSB or MSB order
00729    foreach (this.fields[i]) begin
00730       this.fields[i].XforceX(value >> this.fields[i].get_lsb_pos_in_register(),
00731                              path, domain);
00732    end
00733 endfunction: XforceX
00734 
00735 
00736 function void vmm_ral_reg::XwroteX(bit [`VMM_RAL_DATA_WIDTH-1:0] value,
00737                                    vmm_ral::path_e               path,
00738                                    string                        domain);
00739    int j, w;
00740 
00741    // Fields are stored in LSB or MSB order
00742    foreach (this.fields[i]) begin
00743       j = this.fields[i].get_lsb_pos_in_register();
00744       w = this.fields[i].get_n_bits();
00745       this.fields[i].XwroteX((value >> j) & ((1 << w) - 1), path, domain);
00746    end
00747 endfunction: XwroteX
00748 
00749 
00750 function void vmm_ral_reg::set(bit [`VMM_RAL_DATA_WIDTH-1:0] value);
00751    // Split the value into the individual fields
00752    int j, w;
00753 
00754    // Fields are stored in LSB or MSB order
00755    foreach (this.fields[i]) begin
00756       j = this.fields[i].get_lsb_pos_in_register();
00757       w = this.fields[i].get_n_bits();
00758       this.fields[i].set((value >> j) & ((1 << w) - 1));
00759    end
00760 endfunction: set
00761 
00762 
00763 function bit vmm_ral_reg::predict(bit [`VMM_RAL_DATA_WIDTH-1:0] value);
00764    if (this.Xis_busyX) begin
00765       `vmm_warning(this.log, $psprintf("Trying to predict value of register \"%s\" while it is being accessed",
00766                                        this.get_fullname()));
00767       return 0;
00768    end
00769    
00770    predict = 1;
00771    
00772    // Fields are stored in LSB or MSB order
00773    foreach (this.fields[i]) begin
00774       predict &= this.fields[i].predict(value >> this.fields[i].get_lsb_pos_in_register());
00775    end
00776 endfunction: predict
00777 
00778 
00779 function bit[`VMM_RAL_DATA_WIDTH-1:0] vmm_ral_reg::get();
00780    // Concatenate the value of the individual fields
00781    // to form the register value
00782    int j, w;
00783 
00784    get = 0;
00785    
00786    // Fields are stored in LSB or MSB order
00787    foreach (this.fields[i]) begin
00788       j = this.fields[i].get_lsb_pos_in_register();
00789       get |= this.fields[i].get() << j;
00790    end
00791 endfunction: get
00792 
00793 
00794 function logic [`VMM_RAL_DATA_WIDTH-1:0]
00795    vmm_ral_reg::get_reset(vmm_ral::reset_e kind = vmm_ral::HARD);
00796    // Concatenate the value of the individual fields
00797    // to form the register value
00798    int j, w;
00799 
00800    get_reset = 0;
00801    
00802    // Fields are stored in LSB or MSB order
00803    foreach (this.fields[i]) begin
00804       j = this.fields[i].get_lsb_pos_in_register();
00805       get_reset |= this.fields[i].get_reset(kind) << j;
00806    end
00807 endfunction: get_reset
00808 
00809 
00810 function void vmm_ral_reg::reset(vmm_ral::reset_e kind = vmm_ral::HARD);
00811    foreach (this.fields[i]) begin
00812       this.fields[i].reset(kind);
00813    end
00814    // Put back a key in the semaphore if it is checked out
00815    // in case a thread was killed during an operation
00816    void'(this.atomic.try_get(1));
00817    this.atomic.put(1);
00818 endfunction: reset
00819 
00820 
00821 function bit vmm_ral_reg::needs_update();
00822    needs_update = 0;
00823    foreach (this.fields[i]) begin
00824       if (this.fields[i].needs_update()) begin
00825          return 1;
00826       end
00827    end
00828 endfunction: needs_update
00829 
00830 
00831 task vmm_ral_reg::update(output vmm_rw::status_e status,
00832                          input  vmm_ral::path_e  path = vmm_ral::DEFAULT,
00833                          input  string           domain = "");
00834    bit [`VMM_RAL_DATA_WIDTH-1:0] upd;
00835    int j;
00836 
00837    if (this.parent.Xis_powered_downX) begin
00838       `vmm_error(this.log, $psprintf("Register %s cannot be accessed when its parent block is powered down", this.get_fullname()));
00839       return;
00840    end
00841 
00842    status = vmm_rw::IS_OK;
00843    if (!this.needs_update()) return;
00844 
00845    this.XatomicX(1);
00846 
00847    // Concatenate the write-to-update values from each field
00848    // Fields are stored in LSB or MSB order
00849    upd = 0;
00850    foreach (this.fields[i]) begin
00851       j = this.fields[i].get_lsb_pos_in_register();
00852       upd |= this.fields[i].XupdX() << j;
00853    end
00854 
00855    this.XwriteX(status, upd, path, domain, -1, -1, -1);
00856 
00857    this.XatomicX(0);
00858 endtask: update
00859 
00860 
00861 task vmm_ral_reg::write(output vmm_rw::status_e             status,
00862                         input  bit[`VMM_RAL_DATA_WIDTH-1:0] value,
00863                         input  vmm_ral::path_e              path = vmm_ral::DEFAULT,
00864                         input  string                       domain = "",
00865                         input  int                          data_id = -1,
00866                         input  int                          scenario_id = -1,
00867                         input  int                          stream_id = -1);
00868    if (this.parent.Xis_powered_downX) begin
00869       `vmm_error(this.log, $psprintf("Register %s cannot be accessed when its parent block is powered down", this.get_fullname()));
00870       return;
00871    end
00872 
00873    this.XatomicX(1);
00874    this.XwriteX(status, value, path, domain, data_id, scenario_id, stream_id);
00875    this.XatomicX(0);
00876 endtask: write
00877 
00878 
00879 task vmm_ral_reg::XwriteX(output vmm_rw::status_e             status,
00880                           input  bit[`VMM_RAL_DATA_WIDTH-1:0] value,
00881                           input  vmm_ral::path_e              path,
00882                           input  string                       domain,
00883                           input  int                          data_id,
00884                           input  int                          scenario_id,
00885                           input  int                          stream_id);
00886    status = vmm_rw::ERROR;
00887    
00888    if (this.ral_access == null) begin
00889       `vmm_error(this.log, $psprintf("Register \"%s\" not associated with RAL access object", this.get_name()));
00890       return;
00891    end
00892    
00893    if (path == vmm_ral::DEFAULT) path = this.parent.get_default_access();
00894 
00895    begin
00896       bit [`VMM_RAL_DATA_WIDTH-1:0] tmp;
00897       bit [`VMM_RAL_DATA_WIDTH-1:0] msk;
00898       int lsb;
00899 
00900       foreach (fields[i]) begin
00901          vmm_ral_field f = fields[i];
00902 
00903          lsb = f.get_lsb_pos_in_register();
00904 
00905          msk = ((1<<f.get_n_bits())-1) << lsb;
00906          tmp = (value & msk) >> lsb;
00907 
00908          foreach (f.XcbsX[j]) begin
00909             vmm_ral_field_callbacks cb;
00910             if (!$cast(cb, f.XcbsX[j])) continue;
00911             cb.pre_write(f, tmp, path, domain);
00912          end
00913 
00914          value = (value & ~msk) | (tmp << lsb);
00915       end
00916    end
00917    `vmm_callback(vmm_ral_reg_callbacks,
00918               pre_write(this, value, path, domain));
00919 
00920    if (path == vmm_ral::DEFAULT) path = this.parent.get_default_access();
00921 
00922    if (path == vmm_ral::BACKDOOR &&
00923        this.backdoor == null) begin
00924       `vmm_warning(this.log, $psprintf("No backdoor access available for register \"%s\". Using frontdoor instead.", this.get_name()));
00925       path = vmm_ral::BFM;
00926    end
00927 
00928    case (path)
00929       
00930       vmm_ral::BFM: begin
00931          int di = this.get_domain_index(domain);
00932          if (di < 0) return;
00933          
00934          this.Xis_busyX = 1;
00935 
00936          if (this.frontdoor[di] != null) begin
00937             this.frontdoor[di].write(status, value,
00938                                      data_id, scenario_id, stream_id);
00939          end
00940          else begin
00941             bit [`VMM_RAL_ADDR_WIDTH-1:0] addr[];
00942             int w, j;
00943             int n_bits;
00944 
00945             if (this.offset_in_block[di] === 'x) begin
00946                `vmm_error(this.log, $psprintf("Register \"%s\" unmapped in domain \"%s\" does not have a user-defined frontdoor",
00947                                               this.get_name(),
00948                                               this.domains[di]));
00949                return;
00950             end
00951 
00952             w = this.ral_access.Xget_physical_addressesX(this.offset_in_block[di],
00953                                                          0, this.get_n_bytes(),
00954                                                          this.parent,
00955                                                          this.domains[di],
00956                                                          addr);
00957             j = 0;
00958             n_bits = this.get_n_bytes() * 8;
00959             foreach (addr[i]) begin
00960                bit [`VMM_RAL_DATA_WIDTH-1:0] data;
00961                data = value >> (j*8);
00962                this.ral_access.write(status, addr[i], data,
00963                                      (n_bits > w*8) ? w*8 : n_bits,
00964                                      this.parent.get_external_domain(this.domains[di]),
00965                                      data_id, scenario_id, stream_id);
00966                if (status != vmm_rw::IS_OK) return;
00967                j += w;
00968                n_bits -= w * 8;
00969             end
00970          end
00971 
00972          if (this.cover_on) begin
00973             this.sample(value, 0, di);
00974             this.parent.XsampleX(this.offset_in_block[di], di);
00975          end
00976 
00977          this.Xis_busyX = 0;
00978 
00979          this.XwroteX(value, path, domain);
00980       end
00981       
00982       vmm_ral::BACKDOOR: begin
00983          bit [`VMM_RAL_DATA_WIDTH-1:0] reg_val;
00984          bit [`VMM_RAL_DATA_WIDTH-1:0] final_val;
00985 
00986          // Mimick the final value after a physical read
00987          this.backdoor.read(status, reg_val,
00988                             data_id, scenario_id, stream_id);
00989          if (status != vmm_rw::IS_OK) return;
00990 
00991          begin
00992             int j, w;
00993 
00994             // Fields are stored in LSB or MSB order
00995             final_val = '0;
00996             foreach (this.fields[i]) begin
00997                bit [`VMM_RAL_DATA_WIDTH-1:0] field_val;
00998                j = this.fields[i].get_lsb_pos_in_register();
00999                w = this.fields[i].get_n_bits();
01000                field_val = this.fields[i].XpredictX((reg_val >> j) & ((1 << w) - 1),
01001                                                     (value >> j) & ((1 << w) - 1),
01002                                                     domain);
01003                final_val |= field_val << j;
01004             end
01005          end
01006          this.backdoor.write(status, final_val, data_id, scenario_id, stream_id);
01007          this.XwroteX(final_val, path, "-");
01008       end
01009    endcase
01010 
01011    begin
01012       bit [`VMM_RAL_DATA_WIDTH-1:0] tmp;
01013       bit [`VMM_RAL_DATA_WIDTH-1:0] msk;
01014       int lsb;
01015 
01016       value = this.get();
01017 
01018       foreach (fields[i]) begin
01019          vmm_ral_field f = fields[i];
01020 
01021          lsb = f.get_lsb_pos_in_register();
01022 
01023          msk = ((1<<f.get_n_bits())-1) << lsb;
01024          tmp = (value & msk) >> lsb;
01025 
01026          foreach (f.XcbsX[j]) begin
01027             vmm_ral_field_callbacks cb;
01028             if (!$cast(cb, f.XcbsX[j])) continue;
01029             cb.post_write(f, tmp, path, domain, status);
01030          end
01031       end
01032    end
01033 
01034    `vmm_trace(this.log, $psprintf("Wrote register \"%s\" via %s with: 'h%h",
01035                                   this.get_fullname(),
01036                                   (path == vmm_ral::BFM) ? "frontdoor" : "backdoor",
01037                                   value));
01038 
01039    `vmm_callback(vmm_ral_reg_callbacks,
01040                  post_write(this, value, path, domain, status));
01041 endtask: XwriteX
01042 
01043 
01044 task vmm_ral_reg::read(output vmm_rw::status_e             status,
01045                        output bit[`VMM_RAL_DATA_WIDTH-1:0] value,
01046                        input  vmm_ral::path_e              path = vmm_ral::DEFAULT,
01047                        input  string                       domain = "",
01048                        input  int                          data_id = -1,
01049                        input  int                          scenario_id = -1,
01050                        input  int                          stream_id = -1);
01051    if (this.parent.Xis_powered_downX) begin
01052       `vmm_error(this.log, $psprintf("Register %s cannot be accessed when its parent block is powered down", this.get_fullname()));
01053       return;
01054    end
01055 
01056    this.XatomicX(1);
01057    this.XreadX(status, value, path, domain, data_id, scenario_id, stream_id);
01058    this.XatomicX(0);
01059 endtask: read
01060 
01061 
01062 task vmm_ral_reg::XreadX(output vmm_rw::status_e             status,
01063                          output bit[`VMM_RAL_DATA_WIDTH-1:0] value,
01064                          input  vmm_ral::path_e              path,
01065                          input  string                       domain,
01066                          input  int                          data_id,
01067                          input  int                          scenario_id,
01068                          input  int                          stream_id);
01069    status = vmm_rw::ERROR;
01070    
01071    if (this.ral_access == null) begin
01072       `vmm_error(this.log, $psprintf("Register \"%s\" not associated with RAL access object", this.get_name()));
01073       return;
01074    end
01075    
01076    if (path == vmm_ral::DEFAULT) path = this.parent.get_default_access();
01077 
01078    foreach (fields[i]) begin
01079       vmm_ral_field f = fields[i];
01080 
01081       foreach (f.XcbsX[j]) begin
01082          vmm_ral_field_callbacks cb;
01083          if (!$cast(cb, f.XcbsX[j])) continue;
01084          cb.pre_read(f, path, domain);
01085       end
01086    end
01087    `vmm_callback(vmm_ral_reg_callbacks,
01088                  pre_read(this, path, domain));
01089 
01090    if (path == vmm_ral::DEFAULT) path = this.parent.get_default_access();
01091 
01092    if (path == vmm_ral::BACKDOOR &&
01093        this.backdoor == null) begin
01094       `vmm_warning(this.log, $psprintf("No backdoor access available for register \"%s\". Using frontdoor instead.", this.get_name()));
01095       path = vmm_ral::BFM;
01096    end
01097 
01098    case (path)
01099       
01100       vmm_ral::BFM: begin
01101          int di = this.get_domain_index(domain);
01102          if (di < 0) return;
01103          
01104          this.Xis_busyX = 1;
01105 
01106          if (this.frontdoor[di] != null) begin
01107             this.frontdoor[di].read(status, value,
01108                                    data_id, scenario_id, stream_id);
01109          end
01110          else begin
01111             bit [`VMM_RAL_ADDR_WIDTH-1:0] addr[];
01112             int w, j;
01113             int n_bits;
01114          
01115             if (this.offset_in_block[di] === 'x) begin
01116                `vmm_error(this.log, $psprintf("Register \"%s\" unmapped in domain \"%s\" does not have a user-defined frontdoor",
01117                                               this.get_name(),
01118                                               this.domains[di]));
01119                return;
01120             end
01121          
01122             w = this.ral_access.Xget_physical_addressesX(this.offset_in_block[di],
01123                                                          0, this.get_n_bytes(),
01124                                                          this.parent,
01125                                                          this.domains[di],
01126                                                          addr);
01127             j = 0;
01128             n_bits = this.get_n_bytes() * 8;
01129             value = 0;
01130             foreach (addr[i]) begin
01131                bit [`VMM_RAL_DATA_WIDTH-1:0] data;
01132                this.ral_access.read(status, addr[i], data,
01133                                     (n_bits > w*8) ? w*8 : n_bits,
01134                                     this.parent.get_external_domain(this.domains[di]),
01135                                     data_id, scenario_id, stream_id);
01136                if (status != vmm_rw::IS_OK) return;
01137                value |= (data & ((1 << (w*8)) - 1)) << (j*8);
01138                j += w;
01139                n_bits -= w * 8;
01140             end
01141          end
01142 
01143          if (this.cover_on) begin
01144             this.sample(value, 1, di);
01145             this.parent.XsampleX(this.offset_in_block[di], di);
01146          end
01147 
01148          this.Xis_busyX = 0;
01149 
01150          this.XforceX(value, path, domain);
01151       end
01152       
01153       vmm_ral::BACKDOOR: begin
01154          bit [`VMM_RAL_DATA_WIDTH-1:0] final_val;
01155 
01156          this.backdoor.read(status, value, data_id, scenario_id, stream_id);
01157          final_val = value;
01158 
01159          // Need to clear RC fields and mask WO fields
01160          if (status == vmm_rw::IS_OK) begin
01161             bit [`VMM_RAL_DATA_WIDTH-1:0] wo_mask = 0;
01162 
01163             foreach (this.fields[i]) begin
01164                vmm_ral::access_e acc = this.fields[i].get_access("BaCkDoOr");
01165                if (acc == vmm_ral::RC) begin
01166                   final_val &= ~(((1<<this.fields[i].get_n_bits())-1) << this.fields[i].get_lsb_pos_in_register());
01167                end
01168                else if (acc == vmm_ral::WO) begin
01169                   wo_mask |= ((1<<this.fields[i].get_n_bits())-1) << this.fields[i].get_lsb_pos_in_register();
01170                end
01171             end
01172 
01173             if (final_val != value) begin
01174                this.backdoor.write(status, final_val,
01175                                    data_id, scenario_id, stream_id);
01176             end
01177 
01178             value &= ~wo_mask;
01179             this.XforceX(final_val, path, "-");
01180          end
01181       end
01182    endcase
01183 
01184 
01185    begin
01186       bit [`VMM_RAL_DATA_WIDTH-1:0] tmp;
01187       bit [`VMM_RAL_DATA_WIDTH-1:0] msk;
01188       int lsb;
01189 
01190       foreach (fields[i]) begin
01191          vmm_ral_field f = fields[i];
01192 
01193          lsb = f.get_lsb_pos_in_register();
01194 
01195          msk = ((1<<f.get_n_bits())-1) << lsb;
01196          tmp = (value & msk) >> lsb;
01197 
01198          foreach (f.XcbsX[j]) begin
01199             vmm_ral_field_callbacks cb;
01200             if (!$cast(cb, f.XcbsX[j])) continue;
01201             cb.post_read(f, tmp, path, domain, status);
01202          end
01203 
01204          value = (value & ~msk) | (tmp << lsb);
01205       end
01206    end
01207 
01208    `vmm_trace(this.log, $psprintf("Read register \"%s\" via %s: 'h%h",
01209                                   this.get_fullname(),
01210                                   (path == vmm_ral::BFM) ? "frontdoor" : "backdoor",
01211                                   value));
01212 
01213    `vmm_callback(vmm_ral_reg_callbacks,
01214                  post_read(this, value, path, domain, status));
01215 endtask: XreadX
01216 
01217 
01218 task vmm_ral_reg::poke(output vmm_rw::status_e             status,
01219                        input  bit[`VMM_RAL_DATA_WIDTH-1:0] value,
01220                        input  int                          data_id = -1,
01221                        input  int                          scenario_id = -1,
01222                        input  int                          stream_id = -1);
01223    if (this.parent.Xis_powered_downX) begin
01224       `vmm_error(this.log, $psprintf("Register %s cannot be accessed when its parent block is powered down", this.get_fullname()));
01225       return;
01226    end
01227 
01228    if(!this.Xis_locked_by_fieldX)
01229      this.XatomicX(1);
01230 
01231    if (this.backdoor == null) begin
01232       `vmm_error(this.log, $psprintf("No backdoor access available to poke register \"%s\"", this.get_name()));
01233       status = vmm_rw::ERROR;
01234       if(!this.Xis_locked_by_fieldX)
01235         this.XatomicX(0);
01236       return;
01237    end
01238 
01239    this.backdoor.write(status, value, data_id, scenario_id, stream_id);
01240 
01241    `vmm_trace(this.log, $psprintf("Poked register \"%s\" with: 'h%h",
01242                                   this.get_fullname(), value));
01243 
01244    this.XforceX(value, vmm_ral::BACKDOOR, "-");
01245    if(!this.Xis_locked_by_fieldX)
01246      this.XatomicX(0);
01247 endtask: poke
01248 
01249 
01250 task vmm_ral_reg::peek(output vmm_rw::status_e             status,
01251                        output bit[`VMM_RAL_DATA_WIDTH-1:0] value,
01252                        input  int                          data_id = -1,
01253                        input  int                          scenario_id = -1,
01254                        input  int                          stream_id = -1);
01255    if (this.parent.Xis_powered_downX) begin
01256       `vmm_error(this.log, $psprintf("Register %s cannot be accessed when its parent block is powered down", this.get_fullname()));
01257       return;
01258    end
01259 
01260    if(!this.Xis_locked_by_fieldX)
01261      this.XatomicX(1);
01262    if (this.backdoor == null) begin
01263       `vmm_error(this.log, $psprintf("No backdoor access available peek register \"%s\"", this.get_name()));
01264       status = vmm_rw::ERROR;
01265       if(!this.Xis_locked_by_fieldX)
01266         this.XatomicX(0);
01267       return;
01268    end
01269    this.backdoor.read(status, value, data_id, scenario_id, stream_id);
01270 
01271    `vmm_trace(this.log, $psprintf("Peeked register \"%s\": 'h%h",
01272                                   this.get_fullname(), value));
01273 
01274    this.XforceX(value, vmm_ral::BACKDOOR, "-");
01275 
01276    if(!this.Xis_locked_by_fieldX)
01277      this.XatomicX(0);
01278 endtask: peek
01279 
01280 
01281 task vmm_ral_reg::mirror(output vmm_rw::status_e  status,
01282                          input  vmm_ral::check_e  check = vmm_ral::QUIET,
01283                          input  vmm_ral::path_e   path = vmm_ral::DEFAULT,
01284                          input  string            domain = "");
01285    bit [`VMM_RAL_DATA_WIDTH-1:0] v;
01286    bit [`VMM_RAL_DATA_WIDTH-1:0] exp;
01287 
01288    if (this.parent.Xis_powered_downX) begin
01289       `vmm_error(this.log, $psprintf("Register %s cannot be accessed when its parent block is powered down", this.get_fullname()));
01290       return;
01291    end
01292 
01293    if (path == vmm_ral::DEFAULT) path = this.parent.get_default_access();
01294 
01295    this.XatomicX(1);
01296 
01297    if (path == vmm_ral::BACKDOOR && this.backdoor != null) begin
01298       domain = "BaCkDoOr";
01299    end
01300 
01301    // Remember what we think the value is before it gets updated
01302    if (check == vmm_ral::VERB) begin
01303       exp = this.get();
01304       // Any WO field will readback as 0's
01305       foreach(this.fields[i]) begin
01306          if (this.fields[i].get_access(domain) == vmm_ral::WO) begin
01307             exp &= ~(((1 << this.fields[i].get_n_bits())-1)
01308                      << this.fields[i].get_lsb_pos_in_register());
01309          end
01310       end
01311    end
01312 
01313    this.XreadX(status, v, path, domain, -1, -1, -1);
01314 
01315    if (status != vmm_rw::IS_OK) begin
01316       this.XatomicX(0);
01317       return;
01318    end
01319 
01320    if (check == vmm_ral::VERB) begin
01321       // Check that our idea of the register value matches
01322       // what we just read from the DUT, minus the don't care fields
01323       bit [`VMM_RAL_DATA_WIDTH-1:0] dc = 0;
01324 
01325       foreach(this.fields[i]) begin
01326          vmm_ral::access_e acc = this.fields[i].get_access(domain);
01327          if (acc == vmm_ral::DC) begin
01328             dc |= ((1 << this.fields[i].get_n_bits())-1)
01329                   << this.fields[i].get_lsb_pos_in_register();
01330          end
01331          else if (acc == vmm_ral::WO) begin
01332             // WO fields will always read-back as 0
01333             exp &= ~(((1 << this.fields[i].get_n_bits())-1)
01334                      << this.fields[i].get_lsb_pos_in_register());
01335          end
01336       end
01337 
01338       if ((v|dc) !== (exp|dc)) begin
01339          `vmm_error(this.log, $psprintf("Register \"%s\" value read from DUT (0x%h) does not match mirrored value (0x%h)",
01340                                         this.get_name(), v, (exp ^ ('x & dc))));
01341       end
01342    end
01343 
01344    this.XatomicX(0);
01345 endtask: mirror
01346 
01347 
01348 function void vmm_ral_reg::set_frontdoor(vmm_ral_reg_frontdoor ftdr,
01349                                          string                domain = "");
01350    foreach(this.domains[i]) begin
01351       if (this.domains[i] == domain) begin
01352          this.frontdoor[i] = ftdr;
01353          return;
01354       end
01355    end
01356    `vmm_error(this.log, $psprintf("Domain \"%s\" not found in register %s", domain, this.get_fullname()));
01357 endfunction: set_frontdoor
01358 
01359 
01360 function vmm_ral_reg_frontdoor vmm_ral_reg::get_frontdoor(string domain = "");
01361    foreach(this.domains[i]) begin
01362       if (this.domains[i] == domain) begin
01363          return this.frontdoor[i];
01364       end
01365    end
01366    `vmm_error(this.log, $psprintf("Domain \"%s\" not found in register %s", domain, this.get_fullname()));
01367 endfunction: get_frontdoor
01368 
01369 
01370 function void vmm_ral_reg::set_backdoor(vmm_ral_reg_backdoor bkdr);
01371    this.backdoor = bkdr;
01372 endfunction: set_backdoor
01373 
01374 
01375 function vmm_ral_reg_backdoor vmm_ral_reg::get_backdoor();
01376    get_backdoor = this.backdoor;
01377 endfunction: get_backdoor
01378 
01379 
01380 function void vmm_ral_reg::prepend_callback(vmm_ral_reg_callbacks cb);
01381    foreach (this.callbacks[i]) begin
01382       if (this.callbacks[i] == cb) begin
01383          `vmm_warning(this.log, $psprintf("Callback has already been registered with register \"%s\"", this.get_name()));
01384          return;
01385       end
01386    end
01387    
01388    // Prepend new callback
01389    this.callbacks.push_front(cb);
01390 endfunction: prepend_callback
01391 
01392 
01393 function void vmm_ral_reg::append_callback(vmm_ral_reg_callbacks cb);
01394    foreach (this.callbacks[i]) begin
01395       if (this.callbacks[i] == cb) begin
01396          `vmm_warning(this.log, $psprintf("Callback has already been registered with register \"%s\"", this.get_name()));
01397          return;
01398       end
01399    end
01400    
01401    // Append new callback
01402    this.callbacks.push_back(cb);
01403 endfunction: append_callback
01404 
01405 
01406 function void vmm_ral_reg::unregister_callback(vmm_ral_reg_callbacks cb);
01407    foreach (this.callbacks[i]) begin
01408       if (this.callbacks[i] == cb) begin
01409          int j = i;
01410          // Unregister it
01411          this.callbacks.delete(j);
01412          return;
01413       end
01414    end
01415 
01416    `vmm_warning(this.log, $psprintf("Callback was not registered with register \"%s\"", this.get_name()));
01417 endfunction: unregister_callback
01418 
01419 
01420 function int vmm_ral_reg::get_domain_index(string domain);
01421    // If the domain is "" and there is only one domain,
01422    // assume it is the one domain available to avoid
01423    // having to always have to specify domains
01424    if (domain == "" && this.domains.size() == 1) return 0;
01425 
01426    foreach (this.domains[i]) begin
01427       if (this.domains[i] == domain) return i;
01428    end
01429    `vmm_warning(this.log, $psprintf("Unknown domain name \"%s\" in register \"%s\".", domain, this.get_name()));
01430    return -1;
01431 endfunction: get_domain_index
01432 
01433 
01434 task vmm_ral_reg_frontdoor::write(output vmm_rw::status_e              status,
01435                                   input  bit [`VMM_RAL_DATA_WIDTH-1:0] data,
01436                                   input  int                           data_id,
01437                                   input  int                           scenario_id,
01438                                   input  int                           stream_id);
01439    `vmm_fatal(this.log, "vmm_ral_reg_frontdoor::write() method has not been overloaded");
01440 endtask: write
01441 
01442 
01443 task vmm_ral_reg_frontdoor::read(output vmm_rw::status_e              status,
01444                                  output bit [`VMM_RAL_DATA_WIDTH-1:0] data,
01445                                  input  int                           data_id,
01446                                  input  int                           scenario_id,
01447                                  input  int                           stream_id);
01448    `vmm_fatal(this.log, "vmm_ral_reg_frontdoor::read() method has not been overloaded");
01449 endtask: read
01450 
01451 
01452 function void vmm_ral_reg::sample(bit [`VMM_RAL_DATA_WIDTH-1:0] data,
01453                                   bit                           is_read,
01454                                   int                           domain);
01455    // Nothing to do in this base class
01456 endfunction
01457 
01458 
01459 function int unsigned vmm_ral_reg::get_reg_ID();
01460    get_reg_ID =  this.reg_id;
01461 endfunction
01462 
01463 function vmm_ral_reg vmm_ral_get_reg_by_ID(int unsigned id);
01464    vmm_ral_reg rg;
01465    if (rg.all_regs.exists(id)) 
01466       vmm_ral_get_reg_by_ID = rg.all_regs[id];
01467    else vmm_ral_get_reg_by_ID = null;
01468 endfunction
01469