VMM - (expanded) RAL/vmm_ral_reg.sv

Expanded versions of source files are the output of the preprocessor. Lines subject to conditional compilation are not shown and all compiler pragmas have been stripped. Macros have been completely expanded.

RAL/vmm_ral_reg.sv unexpanded 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 [64-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 [64-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 [64-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 [64-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 [64-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 [64-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 [64-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 [64-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[64-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[64-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 [64-1:0] get_offset_in_block(string domain = ""); 
00148:    extern virtual function bit [64-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 [64-1:0] value,
00165:                                               vmm_ral::path_e               path,
00166:                                               string                        domain);
00167:    extern local virtual function void XwroteX(bit [64-1:0] value,
00168:                                               vmm_ral::path_e               path,
00169:                                               string                        domain);
00170:    extern virtual function void set(bit [64-1:0] value);
00171:    extern virtual function bit predict(bit [64-1:0] value);
00172:    extern virtual function bit[64-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[64-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[64-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[64-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[64-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 [64-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 [64-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:       
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("Register \"%s\" cannot have 0 bits", this.get_name()))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00248:       n_bits = 1;
00249:    end
00250:    if (n_bits > 64) begin
00251:       
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("Register \"%s\" cannot have more than %0d bits (%0d)", this.get_name(), 64, n_bits))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00252:       n_bits = 64;
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 [64-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:       
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text("Cannot add domain to locked register model")); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
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:
00299: 
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("Register \"%s\" has no access rights in domain \"%s\"",
     :                             this.get_name(), domain))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
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
00324: 
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("Domain \"%s\" not found in parent block %s of register \"%s\"",
     :                                   domain, this.parent.get_name(), this.get_name()))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
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:       
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text("Cannot add field to locked register model")); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00334:       return;
00335:    end
00336: 
00337:    if (field == null) 
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::FATAL_SEV)) begin 
     :       void'(this.log.text("Attempting to register NULL field")); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
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
00361: 
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("Fields use more bits (%0d) than available in register \"%s\" (%0d)",
     :                                      this.n_used_bits, this.get_name(), this.n_bits))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
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
00370: 
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("Field %s overlaps field %s in register \"%s\"",
     :                                         this.fields[idx-1].get_name(),
     :                                         field.get_name(), this.get_name()))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
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
00380: 
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("Field %s overlaps field %s in register \"%s\"",
     :                                         field.get_name(),
     :                                         this.fields[idx+1].get_name(),
     : 
     :                                       this.get_name()))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
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:       
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::FATAL_SEV)) begin 
     :       void'(this.log.text($psprintf("Register \"%s\" is already used by another RAL access instance", this.get_name()))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
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:       
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text("Cannot add constraints to locked register model")); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
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
00407: 
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::WARNING_SEV)) begin 
     :       void'(this.log.text($psprintf("Constraint \"%s\" already added",
     :                                           name))); 
     :       this.log.end_msg(); 
     :    end 
     : while(0);
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 [64-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:             
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::WARNING_SEV)) begin 
     :       void'(this.log.text($psprintf("Register \"%s\" is unmapped in domain \"%s\".", this.get_name(), domain))); 
     :       this.log.end_msg(); 
     :    end 
     : while(0);
00483:             return '0;
00484:          end
00485:          
00486:          return this.offset_in_block[i];
00487:       end
00488:    end
00490: 
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::WARNING_SEV)) begin 
     :       void'(this.log.text($psprintf("Unable to find offset within domain \"%s\" in register \"%s\".",
     :                                     domain, this.get_name()))); 
     :       this.log.end_msg(); 
     :    end 
     : while(0);
00491:    get_offset_in_block = '1;
00492: endfunction: get_offset_in_block
00493: 
00494: 
00495: function bit [64-1:0] vmm_ral_reg::get_address_in_system(string domain);
00496:    bit [64-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
00503: 
     : do 
     :    if (this.parent.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::FATAL_SEV)) begin 
     :       void'(this.parent.log.text("RAL model is not associated with an access transactor")); 
     :       this.parent.log.end_msg(); 
     :    end 
     : while (0);
00504:       return 0;
00505:    end
00506:          
00507:    if (this.offset_in_block[i] === 'x) begin
00508:       
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("Register \"%s\" is unmapped in domain \"%s\".", this.get_name(), this.domains[i]))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
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
00574: 
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::WARNING_SEV)) begin 
     :       void'(this.log.text($psprintf("Unable to locate field \"%s\" in register \"%s\".",
     :                                     name, this.get_name()))); 
     :       this.log.end_msg(); 
     :    end 
     : while(0);
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:       
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::WARNING_SEV)) begin 
     :       void'(this.log.text($psprintf("Cannot turn cover ON if not constructed with corresponding coverage model in register \"%s\"", this.get_name()))); 
     :       this.log.end_msg(); 
     :    end 
     : while(0);
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 [64-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 [64-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 [64-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 [64-1:0] value);
00645:    if (this.Xis_busyX) begin
00647: 
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::WARNING_SEV)) begin 
     :       void'(this.log.text($psprintf("Trying to predict value of register \"%s\" while it is being accessed",
     :                                        this.get_fullname()))); 
     :       this.log.end_msg(); 
     :    end 
     : while(0);
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[64-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 [64-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[64-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[64-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:       
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("Register \"%s\" not associated with RAL access object", this.get_name()))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00745:       return;
00746:    end
00747:    
00748:    if (path == vmm_ral::DEFAULT) path = this.parent.get_default_access();
00749: 
00750:    begin
00751:       bit [64-1:0] tmp;
00752:       bit [64-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
00773: 
     : 
     : do foreach (this.callbacks[vmm_i]) begin 
     :    vmm_ral_reg_callbacks cb; 
     :    if (!$cast(cb, this.callbacks[vmm_i])) continue; 
     :  
     :    cb.pre_write(this, value, path, domain); 
     : end while (0);
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:       
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::WARNING_SEV)) begin 
     :       void'(this.log.text($psprintf("No backdoor access available for register \"%s\". Using frontdoor instead.", this.get_name()))); 
     :       this.log.end_msg(); 
     :    end 
     : while(0);
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 [64-1:0] addr[];
00797:             int w, j;
00798:             int n_bits;
00799: 
00800:             if (this.offset_in_block[di] === 'x) begin
00803: 
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("Register \"%s\" unmapped in domain \"%s\" does not have a user-defined frontdoor",
     :                                               this.get_name(),
     :                                               this.domains[di]))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
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 [64-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 [64-1:0] reg_val;
00839:          bit [64-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 [64-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 [64-1:0] tmp;
00868:       bit [64-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: 
00892: 
     : do 
     :    if (this.log.start_msg(vmm_log::DEBUG_TYP, vmm_log::TRACE_SEV)) begin 
     :       void'(this.log.text($psprintf("Wrote register \"%s\" via %s with: 'h%h",
     :                                   this.get_fullname(),
     :                                   (path == vmm_ral::BFM) ? "frontdoor" : "backdoor",
     :                                   value))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00893: 
00895: 
     : 
     : do foreach (this.callbacks[vmm_i]) begin 
     :    vmm_ral_reg_callbacks cb; 
     :    if (!$cast(cb, this.callbacks[vmm_i])) continue; 
     :  
     :    cb.post_write(this, value, path, domain, status); 
     : end while (0);
00896: endtask: XwriteX
00897: 
00898: 
00899: task vmm_ral_reg::read(output vmm_rw::status_e             status,
00900:                        output bit[64-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[64-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:       
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("Register \"%s\" not associated with RAL access object", this.get_name()))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
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
00938: 
     : 
     : do foreach (this.callbacks[vmm_i]) begin 
     :    vmm_ral_reg_callbacks cb; 
     :    if (!$cast(cb, this.callbacks[vmm_i])) continue; 
     :  
     :    cb.pre_read(this, path, domain); 
     : end while (0);
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:       
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::WARNING_SEV)) begin 
     :       void'(this.log.text($psprintf("No backdoor access available for register \"%s\". Using frontdoor instead.", this.get_name()))); 
     :       this.log.end_msg(); 
     :    end 
     : while(0);
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 [64-1:0] addr[];
00962:             int w, j;
00963:             int n_bits;
00964:          
00965:             if (this.offset_in_block[di] === 'x) begin
00968: 
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("Register \"%s\" unmapped in domain \"%s\" does not have a user-defined frontdoor",
     :                                               this.get_name(),
     :                                               this.domains[di]))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
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 [64-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 [64-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 [64-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 [64-1:0] tmp;
01037:       bit [64-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: 
01061: 
     : do 
     :    if (this.log.start_msg(vmm_log::DEBUG_TYP, vmm_log::TRACE_SEV)) begin 
     :       void'(this.log.text($psprintf("Read register \"%s\" via %s: 'h%h",
     :                                   this.get_fullname(),
     :                                   (path == vmm_ral::BFM) ? "frontdoor" : "backdoor",
     :                                   value))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
01062: 
01064: 
     : 
     : do foreach (this.callbacks[vmm_i]) begin 
     :    vmm_ral_reg_callbacks cb; 
     :    if (!$cast(cb, this.callbacks[vmm_i])) continue; 
     :  
     :    cb.post_read(this, value, path, domain, status); 
     : end while (0);
01065: endtask: XreadX
01066: 
01067: 
01068: task vmm_ral_reg::poke(output vmm_rw::status_e             status,
01069:                        input  bit[64-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:       
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("No backdoor access available to poke register \"%s\"", this.get_name()))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
01077:       status = vmm_rw::ERROR;
01078:       return;
01079:    end
01080: 
01081:    this.backdoor.write(status, value, data_id, scenario_id, stream_id);
01082: 
01084: 
     : do 
     :    if (this.log.start_msg(vmm_log::DEBUG_TYP, vmm_log::TRACE_SEV)) begin 
     :       void'(this.log.text($psprintf("Poked register \"%s\" with: 'h%h",
     :                                   this.get_fullname(), value))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
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[64-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:       
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("No backdoor access available peek register \"%s\"", this.get_name()))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
01099:       status = vmm_rw::ERROR;
01100:       return;
01101:    end
01102:    this.backdoor.read(status, value, data_id, scenario_id, stream_id);
01103: 
01105: 
     : do 
     :    if (this.log.start_msg(vmm_log::DEBUG_TYP, vmm_log::TRACE_SEV)) begin 
     :       void'(this.log.text($psprintf("Peeked register \"%s\": 'h%h",
     :                                   this.get_fullname(), value))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
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 [64-1:0] v;
01118:    bit [64-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 [64-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
01167: 
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("Register \"%s\" value read from DUT (0x%h) does not match mirrored value (0x%h)",
     :                                         this.get_name(), v, (exp ^ ('x & dc))))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
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:    
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("Domain \"%s\" not found in register %s", domain, this.get_fullname()))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
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:    
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("Domain \"%s\" not found in register %s", domain, this.get_fullname()))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
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:          
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::WARNING_SEV)) begin 
     :       void'(this.log.text($psprintf("Callback has already been registered with register \"%s\"", this.get_name()))); 
     :       this.log.end_msg(); 
     :    end 
     : while(0);
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:          
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::WARNING_SEV)) begin 
     :       void'(this.log.text($psprintf("Callback has already been registered with register \"%s\"", this.get_name()))); 
     :       this.log.end_msg(); 
     :    end 
     : while(0);
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:    
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::WARNING_SEV)) begin 
     :       void'(this.log.text($psprintf("Callback was not registered with register \"%s\"", this.get_name()))); 
     :       this.log.end_msg(); 
     :    end 
     : while(0);
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:    
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::WARNING_SEV)) begin 
     :       void'(this.log.text($psprintf("Unknown domain name \"%s\" in register \"%s\".", domain, this.get_name()))); 
     :       this.log.end_msg(); 
     :    end 
     : while(0);
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 [64-1:0] data,
01263:                                   input  int                           data_id,
01264:                                   input  int                           scenario_id,
01265:                                   input  int                           stream_id);
01266:    
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::FATAL_SEV)) begin 
     :       void'(this.log.text("vmm_ral_reg_frontdoor::write() method has not been overloaded")); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
01267: endtask: write
01268: 
01269: 
01270: task vmm_ral_reg_frontdoor::read(output vmm_rw::status_e              status,
01271:                                  output bit [64-1:0] data,
01272:                                  input  int                           data_id,
01273:                                  input  int                           scenario_id,
01274:                                  input  int                           stream_id);
01275:    
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::FATAL_SEV)) begin 
     :       void'(this.log.text("vmm_ral_reg_frontdoor::read() method has not been overloaded")); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
01276: endtask: read
01277: 
01278: 
01279: function void vmm_ral_reg::sample(bit [64-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