VMM - (expanded) RAL/vmm_ral_vreg.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_vreg.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: typedef class vmm_mam_region;
00024: typedef class vmm_mam;
00025: 
00026: 
00027: class vmm_ral_vreg_callbacks extends vmm_ral_callbacks;
00028: 
00029:    virtual task pre_write(vmm_ral_vreg                      rg,
00030:                           longint unsigned                  idx,
00031:                           ref bit [64-1:0] wdat,
00032:                           ref vmm_ral::path_e               path,
00033:                           ref string                        domain);
00034:    endtask: pre_write
00035: 
00036:    virtual task post_write(vmm_ral_vreg                  rg,
00037:                            longint unsigned              idx,
00038:                            bit [64-1:0] wdat,
00039:                            vmm_ral::path_e               path,
00040:                            string                        domain,
00041:                            ref vmm_rw::status_e          status);
00042:    endtask: post_write
00043: 
00044:    virtual task pre_read(vmm_ral_vreg         rg,
00045:                          longint unsigned     idx,
00046:                          ref vmm_ral::path_e  path,
00047:                          ref string           domain);
00048:    endtask: pre_read
00049: 
00050:    virtual task post_read(vmm_ral_vreg                      rg,
00051:                           longint unsigned                  idx,
00052:                           ref bit [64-1:0] rdat,
00053:                           input vmm_ral::path_e             path,
00054:                           input string                      domain,
00055:                           ref vmm_rw::status_e              status);
00056:    endtask: post_read
00057: endclass: vmm_ral_vreg_callbacks
00058: 
00059: 
00060: class vmm_ral_vreg;
00061:    static vmm_log log = new("RAL", "virtual register");
00062: 
00063:    local bit locked;
00064:    local vmm_ral_block parent;
00065:    local string name;
00066:    local int unsigned  n_bits;
00067:    local int unsigned  n_used_bits;
00068: 
00069:    local vmm_ral_vfield fields[$];   // Fields in LSB to MSB order
00070: 
00071:    local vmm_ral_vreg_callbacks callbacks[$];
00072: 
00073:    local vmm_ral_mem                   mem;     // Where is it implemented?
00074:    local bit [64-1:0] offset;  // Start of vreg[0]
00075:    local int unsigned                  incr;    // From start to start of next
00076:    local longint unsigned              size;    //number of vregs
00077:    local bit                           is_static;
00078: 
00079:    local vmm_mam_region   region;    // Not NULL if implemented via MAM
00080:   
00081:    local semaphore atomic;   // Field RMW operations must be atomic
00082: 
00083:    extern /*local*/ function new(vmm_ral_block                 parent,
00084:                                  string                        name,
00085:                                  int unsigned                  n_bits,
00086:                                  bit [64-1:0] offset = 0,
00087:                                  vmm_ral_mem                   mem    = null,
00088:                                  longint unsigned              size   = 0,
00089:                                  int unsigned                  incr   = 0);
00090: 
00091:    /*local*/ extern function void Xlock_modelX();
00092:    
00093:    /*local*/ extern function void register_field(vmm_ral_vfield field);
00094:    /*local*/ extern task XatomicX(bit on);
00095:    
00096:    extern function void reset(vmm_ral::reset_e kind = vmm_ral::HARD);
00097: 
00098:    extern virtual function string get_name();
00099:    extern virtual function string get_fullname();
00100:    extern virtual function vmm_ral_block get_block();
00101: 
00102:    extern virtual function bit implement(longint unsigned              n,
00103:                                          vmm_ral_mem                   mem    = null,
00104:                                          bit [64-1:0] offset = 0,
00105:                                          int unsigned                  incr   = 0);
00106:    extern virtual function vmm_mam_region allocate(longint unsigned n,
00107:                                                    vmm_mam          mam);
00108:    extern virtual function vmm_mam_region get_region();
00109:    extern virtual function void release_region();
00110: 
00111:    extern virtual function vmm_ral_mem get_memory();
00112:    extern virtual function int get_n_domains();
00113:    extern virtual function void get_domains(ref string domains[]);
00114:    extern virtual function vmm_ral::access_e get_access(string domain = "");
00115:    extern virtual function vmm_ral::access_e get_rights(string domain = "");
00116:    extern virtual function bit [64-1:0] get_offset_in_memory(longint unsigned idx);
00117: 
00118:    extern virtual function bit [64-1:0] get_address_in_system(longint unsigned idx,
00119:                                                                                string domain = "");
00120: 
00121:    extern virtual function int unsigned get_size();
00122:    extern virtual function int unsigned get_n_bytes();
00123:    extern virtual function int unsigned get_n_memlocs();
00124:    extern virtual function int unsigned get_incr();
00125: 
00126:    extern virtual function void display(string prefix = "",
00127:                                         string domain = "");
00128:    extern virtual function string psdisplay(string prefix = "",
00129:                                             string domain = "");
00130: 
00131:    extern virtual function void get_fields(ref vmm_ral_vfield fields[]);
00132:    extern virtual function vmm_ral_vfield get_field_by_name(string name);
00133: 
00134:    extern virtual task write(input  longint unsigned             idx,
00135:                              output vmm_rw::status_e             status,
00136:                              input  bit[64-1:0] value,
00137:                              input  vmm_ral::path_e              path = vmm_ral::DEFAULT,
00138:                              input  string                       domain = "",
00139:                              input  int                          data_id = -1,
00140:                              input  int                          scenario_id = -1,
00141:                              input  int                          stream_id = -1);
00142:    extern virtual task read(input  longint unsigned             idx,
00143:                             output vmm_rw::status_e             status,
00144:                             output bit[64-1:0] value,
00145:                             input  vmm_ral::path_e              path = vmm_ral::DEFAULT,
00146:                             input  string                       domain = "",
00147:                             input  int                          data_id = -1,
00148:                             input  int                          scenario_id = -1,
00149:                             input  int                          stream_id = -1);
00150:    extern virtual task poke(input  longint unsigned             idx,
00151:                             output vmm_rw::status_e             status,
00152:                             input  bit[64-1:0] value,
00153:                             input  int                          data_id = -1,
00154:                             input  int                          scenario_id = -1,
00155:                             input  int                          stream_id = -1);
00156:    extern virtual task peek(input  longint unsigned             idx,
00157:                             output vmm_rw::status_e             status,
00158:                             output bit[64-1:0] value,
00159:                             input  int                          data_id = -1,
00160:                             input  int                          scenario_id = -1,
00161:                             input  int                          stream_id = -1);
00162:   
00163:    extern function void prepend_callback(vmm_ral_vreg_callbacks cb);
00164:    extern function void append_callback(vmm_ral_vreg_callbacks cb);
00165:    extern function void unregister_callback(vmm_ral_vreg_callbacks cb);
00166: endclass: vmm_ral_vreg
00167: 
00168: 
00169: function vmm_ral_vreg::new(vmm_ral_block                 parent,
00170:                            string                        name,
00171:                            int unsigned                  n_bits,
00172:                            bit [64-1:0] offset,
00173:                            vmm_ral_mem                   mem,
00174:                            longint unsigned              size,
00175:                            int unsigned                  incr);
00176:    this.locked    = 0;
00177: 
00178:    this.parent = parent;
00179:    this.parent.register_vreg(this);
00180:    this.name = name;
00181: 
00182:    if (n_bits == 0) begin
00183:       
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("Virtual register \"%s\" cannot have 0 bits", this.get_fullname()))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00184:       n_bits = 1;
00185:    end
00186:    if (n_bits > 64) begin
00187:       
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("Virtual register \"%s\" cannot have more than %0d bits (%0d)", this.get_fullname(), 64, n_bits))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00188:       n_bits = 64;
00189:    end
00190:    this.n_bits = n_bits;
00191:    this.n_used_bits = 0;
00192: 
00193:    if (mem != null) begin
00194:       this.implement(size, mem, offset, incr);
00195:       this.is_static = 1;
00196:    end
00197:    else begin
00198:       this.mem = null;
00199:       this.is_static = 0;
00200:    end
00201: 
00202:    this.atomic = new(1);
00203: endfunction: new
00204: 
00205: 
00206: function void vmm_ral_vreg::Xlock_modelX();
00207:    if (this.locked) return;
00208: 
00209:    this.locked = 1;
00210: endfunction: Xlock_modelX
00211: 
00212: 
00213: function void vmm_ral_vreg::register_field(vmm_ral_vfield field);
00214:    int offset;
00215:    int idx;
00216:    
00217:    if (this.locked) begin
00218:       
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text("Cannot add virtual field to locked virtual register model")); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00219:       return;
00220:    end
00221: 
00222:    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 virtual field")); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00223: 
00224:    // Store fields in LSB to MSB order
00225:    offset = field.get_lsb_pos_in_register();
00226: 
00227:    idx = -1;
00228:    foreach (this.fields[i]) begin
00229:       if (offset < this.fields[i].get_lsb_pos_in_register()) begin
00230:          int j = i;
00231:          this.fields.insert(j, field);
00232:          idx = i;
00233:          break;
00234:       end
00235:    end
00236:    if (idx < 0) begin
00237:       this.fields.push_back(field);
00238:       idx = this.fields.size()-1;
00239:    end
00240: 
00241:    this.n_used_bits += field.get_n_bits();
00242:    
00243:    // Check if there are too many fields in the register
00244:    if (this.n_used_bits > this.n_bits) begin
00246: 
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("Virtual fields use more bits (%0d) than available in virtual register \"%s\" (%0d)",
     :                                      this.n_used_bits, this.get_fullname(), this.n_bits))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00247:    end
00248: 
00249:    // Check if there are overlapping fields
00250:    if (idx > 0) begin
00251:       if (this.fields[idx-1].get_lsb_pos_in_register() +
00252:           this.fields[idx-1].get_n_bits() > offset) begin
00256: 
     : 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 virtual register \"%s\"",
     :                                         this.fields[idx-1].get_name(),
     :                                         field.get_name(),
     :                                         this.get_fullname()))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00257:       end
00258:    end
00259:    if (idx < this.fields.size()-1) begin
00260:       if (offset + field.get_n_bits() >
00261:           this.fields[idx+1].get_lsb_pos_in_register()) begin
00266: 
     : 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 virtual register \"%s\"",
     :                                         field.get_name(),
     :                                         this.fields[idx+1].get_name(),
     : 
     :                                         this.get_fullname()))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00267:       end
00268:    end
00269: endfunction: register_field
00270: 
00271: 
00272: task vmm_ral_vreg::XatomicX(bit on);
00273:    if (on) this.atomic.get(1);
00274:    else begin
00275:       // Maybe a key was put back in by a spurious call to reset()
00276:       this.atomic.try_get(1);
00277:       this.atomic.put(1);
00278:    end
00279: endtask: XatomicX
00280: 
00281: 
00282: function void vmm_ral_vreg::reset(vmm_ral::reset_e kind);
00283:    // Put back a key in the semaphore if it is checked out
00284:    // in case a thread was killed during an operation
00285:    this.atomic.try_get(1);
00286:    this.atomic.put(1);
00287: endfunction: reset
00288: 
00289: 
00290: function string vmm_ral_vreg::get_name();
00291:    return this.name;
00292: endfunction: get_name
00293: 
00294: 
00295: function string vmm_ral_vreg::get_fullname();
00296:    vmm_ral_block blk;
00297: 
00298:    get_fullname = this.get_name();
00299: 
00300:    // Do not include top-level name in full name
00301:    blk = this.get_block();
00302:    if (blk == null) return get_fullname;
00303:    if (blk.get_parent() == null) return get_fullname;
00304: 
00305:    get_fullname = {this.parent.get_fullname(), ".", get_fullname};
00306: endfunction: get_fullname
00307: 
00308: 
00309: function vmm_ral_block vmm_ral_vreg::get_block();
00310:    get_block = this.parent;
00311: endfunction: get_block
00312: 
00313: 
00314: function bit vmm_ral_vreg::implement(longint unsigned              n,
00315:                                      vmm_ral_mem                   mem,
00316:                                      bit [64-1:0] offset,
00317:                                      int unsigned                  incr);
00318:    if (mem == null) begin
00319:       
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("Attempting to implement virtual register \"%s\" using a NULL vmm_ral_mem reference", this.get_fullname()))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00320:       return 0;
00321:    end
00322: 
00323:    if (this.is_static) begin
00324:       
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("Virtual register \"%s\" is static and cannot be dynamically implemented", this.get_fullname()))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00325:       return 0;
00326:    end
00327: 
00328:    if (mem.get_block() != this.parent) begin
00331: 
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("Attempting to implement virtual register \"%s\" on memory \"%s\" in a different block",
     :                                      this.get_fullname(),
     :                                      mem.get_fullname()))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00332:       return 0;
00333:    end
00334: 
00335:    begin
00336:       int min_incr = (this.get_n_bytes()-1) / mem.get_n_bytes() + 1;
00337:       if (incr == 0) incr = min_incr;
00338:       if (min_incr > incr) begin
00341: 
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("Virtual register \"%s\" increment is too small (%0d): Each virtual register requires at least %0d locations in memory \"%s\".",
     :                                         this.get_fullname(), incr,
     :                                         min_incr, mem.get_fullname()))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00342:          return 0;
00343:       end
00344:    end
00345: 
00346:    // Is the memory big enough for ya?
00347:    if (offset + (n * incr) > mem.get_size()) begin
00348:       
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("Virtual register \"%s[%0d]\" is too big for memory %s@'h%0h", this.get_fullname(), n, mem.get_fullname(), offset))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00349:       return 0;
00350:    end
00351: 
00352:    if (this.mem != null) begin
00357: 
     : do 
     :    if (this.log.start_msg(vmm_log::DEBUG_TYP, vmm_log::TRACE_SEV)) begin 
     :       void'(this.log.text($psprintf("Virtual register \"%s\" is being moved re-implemented from %s@'h%0h to %s@'h%0h",
     :                                      this.get_fullname(),
     :                                      this.mem.get_fullname(),
     :                                      this.offset,
     :                                      mem.get_fullname(), offset))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00358:       this.release_region();
00359:    end
00360: 
00361:    this.mem    = mem;
00362:    this.size   = n;
00363:    this.offset = offset;
00364:    this.incr   = incr;
00365:    this.mem.XvregsX.push_back(this);
00366: 
00367:    return 1;
00368: endfunction: implement
00369: 
00370: 
00371: function vmm_mam_region vmm_ral_vreg::allocate(longint unsigned n,
00372:                                                vmm_mam          mam);
00373: 
00374:    vmm_ral_mem mem;
00375: 
00376:    if (mam == null) begin
00377:       
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("Attempting to implement virtual register \"%s\" using a NULL vmm_mam reference", this.get_fullname()))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00378:       return null;
00379:    end
00380: 
00381:    if (this.is_static) begin
00382:       
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("Virtual register \"%s\" is static and cannot be dynamically allocated", this.get_fullname()))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00383:       return null;
00384:    end
00385: 
00386:    mem = mam.get_memory();
00387:    if (mem.get_block() != this.parent) begin
00390: 
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("Attempting to allocate virtual register \"%s\" on memory \"%s\" in a different block",
     :                                      this.get_fullname(),
     :                                      mem.get_fullname()))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00391:       return null;
00392:    end
00393: 
00394:    begin
00395:       int min_incr = (this.get_n_bytes()-1) / mem.get_n_bytes() + 1;
00396:       if (incr == 0) incr = min_incr;
00397:       if (min_incr < incr) begin
00400: 
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("Virtual register \"%s\" increment is too small (%0d): Each virtual register requires at least %0d locations in memory \"%s\".",
     :                                         this.get_fullname(), incr,
     :                                         min_incr, mem.get_fullname()))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00401:          return null;
00402:       end
00403:    end
00404: 
00405:    // Need memory at least of size num_vregs*sizeof(vreg) in bytes.
00406:    allocate = mam.request_region(n*incr*mem.get_n_bytes());
00407:    if (allocate == null) begin
00408:       
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("Could not allocate a memory region for virtual register \"%s\"", this.get_fullname()))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00409:       return null;
00410:    end
00411: 
00412:    if (this.mem != null) begin
00418: 
     : do 
     :    if (this.log.start_msg(vmm_log::DEBUG_TYP, vmm_log::TRACE_SEV)) begin 
     :       void'(this.log.text($psprintf("Virtual register \"%s\" is being moved re-allocated from %s@'h%0h to %s@'h%0h",
     :                                      this.get_fullname(),
     :                                      this.mem.get_fullname(),
     :                                      this.offset,
     :                                      mem.get_fullname(),
     :                                      allocate.get_start_offset()))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00419: 
00420:       this.release_region();
00421:    end
00422: 
00423:    this.region = allocate;
00424: 
00425:    this.mem    = mam.get_memory();
00426:    this.offset = allocate.get_start_offset();
00427:    this.size   = n;
00428:    this.incr   = incr;
00429: 
00430:    this.mem.XvregsX.push_back(this);
00431: endfunction: allocate
00432: 
00433: 
00434: function vmm_mam_region vmm_ral_vreg::get_region();
00435:    return this.region;
00436: endfunction: get_region
00437: 
00438: 
00439: function void vmm_ral_vreg::release_region();
00440:    if (this.is_static) begin
00441:       
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("Virtual register \"%s\" is static and cannot be dynamically released", this.get_fullname()))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00442:       return;
00443:    end
00444: 
00445:    if (this.mem != null) begin
00446:       foreach (this.mem.XvregsX[i]) begin
00447:          if (this.mem.XvregsX[i] == this) begin
00448:             this.mem.XvregsX.delete(i);
00449:             break;
00450:          end
00451:       end
00452:    end 
00453:    if (this.region != null) begin
00454:       this.region.release_region();
00455:    end
00456: 
00457:    this.region = null;
00458:    this.mem    = null;
00459:    this.size   = 0;
00460:    this.offset = 0;
00461: 
00462:    this.reset();
00463: endfunction: release_region
00464: 
00465: 
00466: function vmm_ral_mem vmm_ral_vreg::get_memory();
00467:    return this.mem;
00468: endfunction: get_memory
00469: 
00470: 
00471: function bit [64-1:0] vmm_ral_vreg::get_offset_in_memory(longint unsigned idx);
00472:    if (this.mem == null) begin
00474: 
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("Cannot call vmm_ral_vreg::get_offset_in_memory() on unimplemented virtual register \"%s\"",
     :                                      this.get_fullname()))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00475:       return 0;
00476:    end
00477: 
00478:    return this.offset + idx * this.incr;
00479: endfunction
00480: 
00481: 
00482: function bit [64-1:0] vmm_ral_vreg::get_address_in_system(longint unsigned idx,
00483:                                                                            string domain);
00484:    if (this.mem == null) begin
00485:       
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("Cannot get address of of unimplemented virtual register \"%s\".", this.get_fullname()))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00486:       return 0;
00487:    end
00488: 
00489:    return this.mem.get_address_in_system(this.get_offset_in_memory(idx),
00490:                                          domain);
00491: endfunction: get_address_in_system
00492: 
00493: 
00494: function int unsigned vmm_ral_vreg::get_size();
00495:    if (this.size == 0) begin
00497: 
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("Cannot call vmm_ral_vreg::get_size() on unimplemented virtual register \"%s\"",
     :                                      this.get_fullname()))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00498:       return 0;
00499:    end
00500: 
00501:    return this.size;
00502: endfunction: get_size
00503: 
00504: 
00505: function int unsigned vmm_ral_vreg::get_n_bytes();
00506:    return ((this.n_bits-1) / 8) + 1;
00507: endfunction: get_n_bytes
00508: 
00509: 
00510: function int unsigned vmm_ral_vreg::get_n_memlocs();
00511:    if (this.mem == null) begin
00513: 
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("Cannot call vmm_ral_vreg::get_n_memlocs() on unimplemented virtual register \"%s\"",
     :                                      this.get_fullname()))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00514:       return 0;
00515:    end
00516: 
00517:    return (this.get_n_bytes()-1) / this.mem.get_n_bytes() + 1;
00518: endfunction: get_n_memlocs
00519: 
00520: 
00521: function int unsigned vmm_ral_vreg::get_incr();
00522:    if (this.incr == 0) begin
00524: 
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("Cannot call vmm_ral_vreg::get_incr() on unimplemented virtual register \"%s\"",
     :                                      this.get_fullname()))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00525:       return 0;
00526:    end
00527: 
00528:    return this.incr;
00529: endfunction: get_incr
00530: 
00531: 
00532: function int vmm_ral_vreg::get_n_domains();
00533:    if (this.mem == null) begin
00535: 
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("Cannot call vmm_ral_vreg::get_n_domains() on unimplemented virtual register \"%s\"",
     :                                      this.get_fullname()))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00536:       return 0;
00537:    end
00538: 
00539:    get_n_domains = this.mem.get_n_domains();
00540: endfunction: get_n_domains
00541: 
00542: 
00543: function void vmm_ral_vreg::get_domains(ref string domains[]);
00544:    if (this.mem == null) begin
00546: 
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("Cannot call vmm_ral_vreg::get_domains() on unimplemented virtual register \"%s\"",
     :                                      this.get_fullname()))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00547:       return;
00548:    end
00549: 
00550:    this.mem.get_domains(domains);
00551: endfunction: get_domains
00552: 
00553: 
00554: function vmm_ral::access_e vmm_ral_vreg::get_access(string domain);
00555:    if (this.mem == null) begin
00557: 
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("Cannot call vmm_ral_vreg::get_rights() on unimplemented virtual register \"%s\"",
     :                                      this.get_fullname()))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00558:       return vmm_ral::RW;
00559:    end
00560: 
00561:    get_access = this.mem.get_access(domain);
00562: endfunction: get_access
00563: 
00564: 
00565: function vmm_ral::access_e vmm_ral_vreg::get_rights(string domain);
00566:    if (this.mem == null) begin
00568: 
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("Cannot call vmm_ral_vreg::get_rights() on unimplemented virtual register \"%s\"",
     :                                      this.get_fullname()))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00569:       return vmm_ral::RW;
00570:    end
00571: 
00572:    get_rights = this.mem.get_rights(domain);
00573: endfunction: get_rights
00574: 
00575: 
00576: function void vmm_ral_vreg::display(string prefix,
00577:                                     string domain);
00578:    $write("%s\n", this.psdisplay(prefix, domain));
00579: endfunction: display
00580: 
00581: 
00582: function string vmm_ral_vreg::psdisplay(string prefix,
00583:                                        string domain);
00584:    $sformat(psdisplay, "%sVirtual register %s -- ", prefix,
00585:             this.get_fullname());
00586:    if (this.size == 0) $sformat(psdisplay, "%sunimplemented", psdisplay);
00587:    else begin
00588:       bit [64-1:0] addr0;
00589: 
00590:       addr0 = this.get_address_in_system(0, domain);
00591: 
00592:       $sformat(psdisplay, "%s[%0d] in %0s['h%0h+'h%0h] @'h%h+'h%h", psdisplay,
00593:                this.size, this.mem.get_fullname(), this.offset, this.incr, 
00594:                addr0, this.get_address_in_system(1, domain) - addr0);
00595:   end
00596:    foreach(this.fields[i]) begin
00597:       $sformat(psdisplay, "%s\n%s", psdisplay,
00598:                this.fields[i].psdisplay({prefix, "   "}));
00599:    end
00600: endfunction: psdisplay
00601: 
00602: 
00603: function void vmm_ral_vreg::get_fields(ref vmm_ral_vfield fields[]);
00604:    fields = new [this.fields.size()];
00605:    foreach(this.fields[i]) begin
00606:       fields[i] = this.fields[i];
00607:    end
00608: endfunction: get_fields
00609: 
00610: 
00611: function vmm_ral_vfield vmm_ral_vreg::get_field_by_name(string name);
00612:    foreach (this.fields[i]) begin
00613:       if (this.fields[i].get_name() == name) begin
00614:          return this.fields[i];
00615:       end
00616:    end
00618: 
     : 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 virtual register \"%s\".",
     :                                     name, this.get_fullname()))); 
     :       this.log.end_msg(); 
     :    end 
     : while(0);
00619:    get_field_by_name = null;
00620: endfunction: get_field_by_name
00621: 
00622: 
00623: task vmm_ral_vreg::write(input  longint unsigned             idx,
00624:                          output vmm_rw::status_e             status,
00625:                          input  bit[64-1:0] value,
00626:                          input  vmm_ral::path_e              path,
00627:                          input  string                       domain,
00628:                          input  int                          data_id,
00629:                          input  int                          scenario_id,
00630:                          input  int                          stream_id);
00631: 
00632:    bit [64-1:0] addr;
00633:    bit [64-1:0] tmp;
00634:    bit [64-1:0] msk;
00635:    int lsb;
00636: 
00637:    if (this.mem == null) begin
00638:       
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("Cannot write to unimplemented virtual register \"%s\".", this.get_fullname()))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00639:       status = vmm_rw::ERROR;
00640:       return;
00641:    end
00642: 
00643:    if (path == vmm_ral::DEFAULT) path = this.parent.get_default_access();
00644: 
00645:    foreach (fields[i]) begin
00646:       vmm_ral_vfield f = fields[i];
00647:       
00648:       lsb = f.get_lsb_pos_in_register();
00649:       msk = ((1<<f.get_n_bits())-1) << lsb;
00650:       tmp = (value & msk) >> lsb;
00651:       foreach (f.XcbsX[j]) begin
00652:          vmm_ral_vfield_callbacks cb;
00653:          if (!$cast(cb, f.XcbsX[j])) continue;
00654:          cb.pre_write(f, idx, tmp, path, domain);
00655:       end
00656:       value = (value & ~msk) | (tmp << lsb);
00657:    end
00659: 
     : 
     : do foreach (this.callbacks[vmm_i]) begin 
     :    vmm_ral_vreg_callbacks cb; 
     :    if (!$cast(cb, this.callbacks[vmm_i])) continue; 
     :  
     :    cb.pre_write(this, idx, value, path, domain); 
     : end while (0);
00660: 
00661:    addr = this.offset + (idx * this.incr);
00662: 
00663:    lsb = 0;
00664:    status = vmm_rw::IS_OK;
00665:    for (int i = 0; i < this.get_n_memlocs(); i++) begin
00666:       vmm_rw::status_e s;
00667: 
00668:       msk = ((1<<(this.mem.get_n_bytes()*8))-1) << lsb;
00669:       tmp = (value & msk) >> lsb;
00670:       this.mem.write(s, addr + i, tmp,
00671:                      path, domain ,
00672:                      data_id, scenario_id, stream_id);
00673:       if (s != vmm_rw::IS_OK) status = s;
00674:       lsb += this.mem.get_n_bytes() * 8;
00675:    end
00676: 
00677:    foreach (fields[i]) begin
00678:       vmm_ral_vfield f = fields[i];
00679:       
00680:       lsb = f.get_lsb_pos_in_register();
00681:       msk = ((1<<f.get_n_bits())-1) << lsb;
00682:       tmp = (value & msk) >> lsb;
00683:       foreach (f.XcbsX[j]) begin
00684:          vmm_ral_vfield_callbacks cb;
00685:          if (!$cast(cb, f.XcbsX[j])) continue;
00686:          cb.post_write(f, idx, tmp, path, domain, status);
00687:       end
00688:       value = (value & ~msk) | (tmp << lsb);
00689:    end
00691: 
     : 
     : do foreach (this.callbacks[vmm_i]) begin 
     :    vmm_ral_vreg_callbacks cb; 
     :    if (!$cast(cb, this.callbacks[vmm_i])) continue; 
     :  
     :    cb.post_write(this, idx, value, path, domain, status); 
     : end while (0);
00692: 
00696: 
     : do 
     :    if (this.log.start_msg(vmm_log::DEBUG_TYP, vmm_log::TRACE_SEV)) begin 
     :       void'(this.log.text($psprintf("Wrote virtual register \"%s\"[%0d] via %s with: 'h%h",
     :                                   this.get_fullname(), idx,
     :                                   (path == vmm_ral::BFM) ? "frontdoor" : "backdoor",
     :                                   value))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00697: 
00698: endtask: write
00699: 
00700: 
00701: task vmm_ral_vreg::read(input  longint unsigned             idx,
00702:                         output vmm_rw::status_e             status,
00703:                         output bit[64-1:0] value,
00704:                         input  vmm_ral::path_e              path,
00705:                         input  string                       domain,
00706:                         input  int                          data_id,
00707:                         input  int                          scenario_id,
00708:                         input  int                          stream_id);
00709:    bit [64-1:0] addr;
00710:    bit [64-1:0] tmp;
00711:    bit [64-1:0] msk;
00712:    int lsb;
00713: 
00714:    if (this.mem == null) begin
00715:       
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("Cannot read from unimplemented virtual register \"%s\".", this.get_fullname()))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00716:       status = vmm_rw::ERROR;
00717:       return;
00718:    end
00719: 
00720:    if (path == vmm_ral::DEFAULT) path = this.parent.get_default_access();
00721: 
00722:    foreach (fields[i]) begin
00723:       vmm_ral_vfield f = fields[i];
00724:       foreach (f.XcbsX[j]) begin
00725:          vmm_ral_vfield_callbacks cb;
00726:          if (!$cast(cb, f.XcbsX[j])) continue;
00727:          cb.pre_read(f, idx, path, domain);
00728:       end
00729:    end
00731: 
     : 
     : do foreach (this.callbacks[vmm_i]) begin 
     :    vmm_ral_vreg_callbacks cb; 
     :    if (!$cast(cb, this.callbacks[vmm_i])) continue; 
     :  
     :    cb.pre_read(this, idx, path, domain); 
     : end while (0);
00732: 
00733:    addr = this.offset + (idx * this.incr);
00734: 
00735:    lsb = 0;
00736:    value = 0;
00737:    status = vmm_rw::IS_OK;
00738:    for (int i = 0; i < this.get_n_memlocs(); i++) begin
00739:       vmm_rw::status_e s;
00740: 
00741:       this.mem.read(s, addr + i, tmp,
00742:                      path, domain ,
00743:                      data_id, scenario_id, stream_id);
00744:       if (s != vmm_rw::IS_OK) status = s;
00745: 
00746:       value |= tmp << lsb;
00747:       lsb += this.mem.get_n_bytes() * 8;
00748:    end
00749: 
00750:    foreach (fields[i]) begin
00751:       vmm_ral_vfield f = fields[i];
00752: 
00753:       lsb = f.get_lsb_pos_in_register();
00754: 
00755:       msk = ((1<<f.get_n_bits())-1) << lsb;
00756:       tmp = (value & msk) >> lsb;
00757: 
00758:       foreach (f.XcbsX[j]) begin
00759:          vmm_ral_vfield_callbacks cb;
00760:          if (!$cast(cb, f.XcbsX[j])) continue;
00761:          cb.post_read(f, idx, tmp, path, domain, status);
00762:       end
00763: 
00764:       value = (value & ~msk) | (tmp << lsb);
00765:    end
00767: 
     : 
     : do foreach (this.callbacks[vmm_i]) begin 
     :    vmm_ral_vreg_callbacks cb; 
     :    if (!$cast(cb, this.callbacks[vmm_i])) continue; 
     :  
     :    cb.post_read(this, idx, value, path, domain, status); 
     : end while (0);
00768: 
00772: 
     : do 
     :    if (this.log.start_msg(vmm_log::DEBUG_TYP, vmm_log::TRACE_SEV)) begin 
     :       void'(this.log.text($psprintf("Read virtual register \"%s\"[%0d] via %s: 'h%h",
     :                                   this.get_fullname(), idx,
     :                                   (path == vmm_ral::BFM) ? "frontdoor" : "backdoor",
     :                                   value))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00773: endtask: read
00774: 
00775: 
00776: task vmm_ral_vreg::poke(input longint unsigned              idx,
00777:                         output vmm_rw::status_e             status,
00778:                         input  bit[64-1:0] value,
00779:                         input  int                          data_id,
00780:                         input  int                          scenario_id,
00781:                         input  int                          stream_id);
00782:    bit [64-1:0] addr;
00783:    bit [64-1:0] tmp;
00784:    bit [64-1:0] msk;
00785:    int lsb;
00786: 
00787:    if (this.mem == null) begin
00788:       
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("Cannot poke in unimplemented virtual register \"%s\".", this.get_fullname()))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00789:       status = vmm_rw::ERROR;
00790:       return;
00791:    end
00792: 
00793:    addr = this.offset + (idx * this.incr);
00794: 
00795:    lsb = 0;
00796:    status = vmm_rw::IS_OK;
00797:    for (int i = 0; i < this.get_n_memlocs(); i++) begin
00798:       vmm_rw::status_e s;
00799: 
00800:       msk = ((1<<(this.mem.get_n_bytes() * 8))-1) << lsb;
00801:       tmp = (value & msk) >> lsb;
00802: 
00803:       this.mem.poke(status, addr + i, tmp,
00804:                     data_id, scenario_id, stream_id);
00805:       if (s != vmm_rw::IS_OK) status = s;
00806: 
00807:       lsb += this.mem.get_n_bytes() * 8;
00808:    end
00809: 
00811: 
     : do 
     :    if (this.log.start_msg(vmm_log::DEBUG_TYP, vmm_log::TRACE_SEV)) begin 
     :       void'(this.log.text($psprintf("Poked virtual register \"%s\"[%0d] with: 'h%h",
     :                                   this.get_fullname(), idx, value))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00812: 
00813: endtask: poke
00814: 
00815: 
00816: task vmm_ral_vreg::peek(input longint unsigned              idx,
00817:                         output vmm_rw::status_e             status,
00818:                         output bit[64-1:0] value,
00819:                         input  int                          data_id,
00820:                         input  int                          scenario_id,
00821:                         input  int                          stream_id);
00822:    bit [64-1:0] addr;
00823:    bit [64-1:0] tmp;
00824:    bit [64-1:0] msk;
00825:    int lsb;
00826: 
00827:    if (this.mem == null) begin
00828:       
     : do 
     :    if (this.log.start_msg(vmm_log::FAILURE_TYP, vmm_log::ERROR_SEV)) begin 
     :       void'(this.log.text($psprintf("Cannot peek in from unimplemented virtual register \"%s\".", this.get_fullname()))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00829:       status = vmm_rw::ERROR;
00830:       return;
00831:    end
00832: 
00833:    addr = this.offset + (idx * this.incr);
00834: 
00835:    lsb = 0;
00836:    value = 0;
00837:    status = vmm_rw::IS_OK;
00838:    for (int i = 0; i < this.get_n_memlocs(); i++) begin
00839:       vmm_rw::status_e s;
00840: 
00841:       this.mem.peek(status, addr + i, tmp,
00842:                     data_id, scenario_id, stream_id);
00843:       if (s != vmm_rw::IS_OK) status = s;
00844: 
00845:       value |= tmp << lsb;
00846:       lsb += this.mem.get_n_bytes() * 8;
00847:    end
00848: 
00850: 
     : do 
     :    if (this.log.start_msg(vmm_log::DEBUG_TYP, vmm_log::TRACE_SEV)) begin 
     :       void'(this.log.text($psprintf("Peeked virtual register \"%s\"[%0d]: 'h%h",
     :                                   this.get_fullname(), idx, value))); 
     :       this.log.end_msg(); 
     :    end 
     : while (0);
00851: 
00852: endtask: peek
00853: 
00854: 
00855: function void vmm_ral_vreg::prepend_callback(vmm_ral_vreg_callbacks cb);
00856:    foreach (this.callbacks[i]) begin
00857:       if (this.callbacks[i] == cb) begin
00858:          
     : 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 virtual register \"%s\"", this.get_fullname()))); 
     :       this.log.end_msg(); 
     :    end 
     : while(0);
00859:          return;
00860:       end
00861:    end
00862:    
00863:    // Prepend new callback
00864:    this.callbacks.push_front(cb);
00865: endfunction: prepend_callback
00866: 
00867: 
00868: function void vmm_ral_vreg::append_callback(vmm_ral_vreg_callbacks cb);
00869:    foreach (this.callbacks[i]) begin
00870:       if (this.callbacks[i] == cb) begin
00871:          
     : 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 virtual register \"%s\"", this.get_fullname()))); 
     :       this.log.end_msg(); 
     :    end 
     : while(0);
00872:          return;
00873:       end
00874:    end
00875:    
00876:    // Append new callback
00877:    this.callbacks.push_back(cb);
00878: endfunction: append_callback
00879: 
00880: 
00881: function void vmm_ral_vreg::unregister_callback(vmm_ral_vreg_callbacks cb);
00882:    foreach (this.callbacks[i]) begin
00883:       if (this.callbacks[i] == cb) begin
00884:          int j = i;
00885:          // Unregister it
00886:          this.callbacks.delete(j);
00887:          return;
00888:       end
00889:    end
00890: 
00891:    
     : 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 virtual register \"%s\"", this.get_fullname()))); 
     :       this.log.end_msg(); 
     :    end 
     : while(0);
00892: endfunction: unregister_callback