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