VMM OpenSource - sv/RAL/vmm_ral_field.sv

sv/RAL/vmm_ral_field.sv expanded source

00001 // 
00002 // -------------------------------------------------------------
00003 //    Copyright 2004-2008 Synopsys, Inc.
00004 //    All Rights Reserved Worldwide
00005 // 
00006 //    Licensed under the Apache License, Version 2.0 (the
00007 //    "License"); you may not use this file except in
00008 //    compliance with the License.  You may obtain a copy of
00009 //    the License at
00010 // 
00011 //        http://www.apache.org/licenses/LICENSE-2.0
00012 // 
00013 //    Unless required by applicable law or agreed to in
00014 //    writing, software distributed under the License is
00015 //    distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
00016 //    CONDITIONS OF ANY KIND, either express or implied.  See
00017 //    the License for the specific language governing
00018 //    permissions and limitations under the License.
00019 // -------------------------------------------------------------
00020 // 
00021 
00022 
00023 typedef class vmm_ral_field;
00024 class vmm_ral_field_callbacks extends vmm_ral_callbacks;
00025 
00026    virtual task pre_write(vmm_ral_field                     field,
00027                           ref bit [`VMM_RAL_DATA_WIDTH-1:0] wdat,
00028                           ref vmm_ral::path_e               path,
00029                           ref string                        domain);
00030    endtask: pre_write
00031 
00032    virtual task post_write(vmm_ral_field                 field,
00033                            bit [`VMM_RAL_DATA_WIDTH-1:0] wdat,
00034                            vmm_ral::path_e               path,
00035                            string                        domain,
00036                            ref vmm_rw::status_e          status);
00037    endtask: post_write
00038 
00039    virtual task pre_read(vmm_ral_field         field,
00040                          ref vmm_ral::path_e   path,
00041                          ref string            domain);
00042    endtask: pre_read
00043 
00044    virtual task post_read(vmm_ral_field                     field,
00045                           ref bit [`VMM_RAL_DATA_WIDTH-1:0] rdat,
00046                           vmm_ral::path_e                   path,
00047                           string                            domain,
00048                           ref vmm_rw::status_e              status);
00049    endtask: post_read
00050 endclass: vmm_ral_field_callbacks
00051 
00052 
00053 class vmm_ral_field;
00054    static vmm_log log = new("RAL", "field");
00055 
00056    local string name;
00057    local vmm_ral::access_e access;
00058    local vmm_ral_reg parent;
00059    local int unsigned lsb;
00060    local int unsigned size;
00061    local bit [`VMM_RAL_DATA_WIDTH-1:0] mirrored; // What we think is in the HW
00062    local bit [`VMM_RAL_DATA_WIDTH-1:0] desired;  // Mirrored after set()
00063    rand  bit [`VMM_RAL_DATA_WIDTH-1:0] value;    // Mirrored after randomize()
00064    local bit [`VMM_RAL_DATA_WIDTH-1:0] reset_value;
00065    local logic [`VMM_RAL_DATA_WIDTH-1:0] soft_reset_value;
00066    local bit written;
00067 
00068    vmm_ral_field_callbacks XcbsX[$];
00069 
00070    constraint vmm_ral_field_valid {
00071       if (`VMM_RAL_DATA_WIDTH > size) {
00072          value < (`VMM_RAL_DATA_WIDTH'h1 << size);
00073       }
00074    }
00075 
00076    extern function new(vmm_ral_reg                   parent,
00077                        string                        name,
00078                        int unsigned                  size,
00079                        vmm_ral::access_e             access,
00080                        bit [`VMM_RAL_DATA_WIDTH-1:0] reset,
00081                        logic [`VMM_RAL_DATA_WIDTH-1:0] soft_reset,
00082                        int unsigned                  lsb_pos,
00083                        bit                           is_rand = 0,
00084                        bit                           cover_on = vmm_ral::NO_COVERAGE); 
00085                                                              // Ignoring cover_on - It is not yet used/supported 
00086                                                              // in the field level.
00087 
00088    extern virtual function string get_name();
00089    extern virtual function string get_fullname();
00090    extern virtual function vmm_ral_reg get_register();
00091    extern virtual function int unsigned get_lsb_pos_in_register();
00092    extern virtual function int unsigned get_n_bits();
00093    extern virtual function vmm_ral::access_e get_access(string domain = "");
00094    extern virtual function vmm_ral::access_e set_access(vmm_ral::access_e mode);
00095 
00096    extern virtual function void display(string prefix = "");
00097    extern virtual function string psdisplay(string prefix = "");
00098 
00099 
00100    /*local*/ extern virtual function bit [`VMM_RAL_DATA_WIDTH-1:0] XpredictX(bit [`VMM_RAL_DATA_WIDTH-1:0] cur_val,
00101                                                                              bit [`VMM_RAL_DATA_WIDTH-1:0] wr_val,
00102                                                                              string                        domain);
00103 
00104    /*local*/ extern virtual function void XforceX(bit [`VMM_RAL_DATA_WIDTH-1:0] value,
00105                                                   vmm_ral::path_e               path,
00106                                                   string                        domain);
00107    /*local*/ extern virtual function void XwroteX(bit [`VMM_RAL_DATA_WIDTH-1:0] value,
00108                                                   vmm_ral::path_e               path,
00109                                                   string                        domain);
00110    /*local*/ extern virtual function bit[`VMM_RAL_DATA_WIDTH-1:0] XupdX();
00111 
00112    extern virtual function void set(bit[`VMM_RAL_DATA_WIDTH-1:0] value);
00113    extern virtual function bit predict(bit [`VMM_RAL_DATA_WIDTH-1:0] value);
00114    extern virtual function bit[`VMM_RAL_DATA_WIDTH-1:0] get();
00115    extern virtual function void reset(vmm_ral::reset_e kind = vmm_ral::HARD);
00116    extern virtual function logic [`VMM_RAL_DATA_WIDTH-1:0]
00117                     get_reset(vmm_ral::reset_e kind = vmm_ral::HARD);
00118    extern virtual function logic [`VMM_RAL_DATA_WIDTH-1:0]
00119                     set_reset(logic [`VMM_RAL_DATA_WIDTH-1:0] value,
00120                               vmm_ral::reset_e                kind = vmm_ral::HARD);
00121    extern virtual function bit needs_update();
00122 
00123    extern virtual task write(output vmm_rw::status_e              status,
00124                              input  bit [`VMM_RAL_DATA_WIDTH-1:0] value,
00125                              input  vmm_ral::path_e               path = vmm_ral::DEFAULT,
00126                              input  string                        domain = "",
00127                              input  int                           data_id = -1,
00128                              input  int                           scenario_id =- 1,
00129                              input  int                           stream_id = -1);
00130    extern virtual task read(output vmm_rw::status_e             status,
00131                             output bit[`VMM_RAL_DATA_WIDTH-1:0] value,
00132                             input  vmm_ral::path_e              path = vmm_ral::DEFAULT,
00133                             input  string                       domain = "",
00134                             input  int                          data_id = -1,
00135                             input  int                          scenario_id = -1,
00136                             input  int                          stream_id = -1);
00137                
00138    extern virtual task poke(output vmm_rw::status_e              status,
00139                             input  bit [`VMM_RAL_DATA_WIDTH-1:0] value,
00140                             input  int                           data_id = -1,
00141                             input  int                           scenario_id =- 1,
00142                             input  int                           stream_id = -1);
00143    extern virtual task peek(output vmm_rw::status_e             status,
00144                             output bit[`VMM_RAL_DATA_WIDTH-1:0] value,
00145                             input  int                          data_id = -1,
00146                             input  int                          scenario_id = -1,
00147                             input  int                          stream_id = -1);
00148                
00149    extern virtual task mirror(output vmm_rw::status_e status,
00150                               input  vmm_ral::check_e check = vmm_ral::QUIET,
00151                               input  vmm_ral::path_e  path = vmm_ral::DEFAULT,
00152                               input  string           domain = "");
00153 
00154    extern function void prepend_callback(vmm_ral_field_callbacks cb);
00155    extern function void append_callback(vmm_ral_field_callbacks cb);
00156    extern function void unregister_callback(vmm_ral_field_callbacks cb);
00157 
00158    extern function void pre_randomize();
00159    extern function void post_randomize();
00160 endclass: vmm_ral_field
00161 
00162 
00163 function vmm_ral_field::new(vmm_ral_reg                   parent,
00164                             string                        name,
00165                             int unsigned                  size,
00166                             vmm_ral::access_e             access,
00167                             bit [`VMM_RAL_DATA_WIDTH-1:0] reset,
00168                             logic [`VMM_RAL_DATA_WIDTH-1:0] soft_reset,
00169                             int unsigned                  lsb_pos,
00170                             bit                           is_rand = 0,
00171                             bit                           cover_on = vmm_ral::NO_COVERAGE);
00172                                                              // Ignoring cover_on - It is not yet used/supported 
00173                                                              // in the field level.
00174    this.parent = parent;
00175    this.name   = name;
00176 
00177    if (size == 0) begin
00178       `vmm_error(this.log, $psprintf("Field \"%s\" cannot have 0 bits", name));
00179       size = 1;
00180    end
00181    if (size > `VMM_RAL_DATA_WIDTH) begin
00182       `vmm_error(this.log, $psprintf("Field \"%s\" cannot have more than %0d bits",
00183                                      name, `VMM_RAL_DATA_WIDTH));
00184       size = `VMM_RAL_DATA_WIDTH;
00185    end
00186    this.size   = size;
00187 
00188    this.access = access;
00189    this.reset_value = reset;
00190    this.soft_reset_value = soft_reset;
00191    this.lsb    = lsb_pos;
00192    this.parent.register_field(this);
00193    if (!is_rand) this.value.rand_mode(0);
00194 
00195    this.written = 0;
00196 
00197 endfunction: new
00198 
00199 
00200 function string vmm_ral_field::get_name();
00201    get_name = this.name;
00202 endfunction: get_name
00203 
00204 
00205 function string vmm_ral_field::get_fullname();
00206    get_fullname = {this.parent.get_fullname(), ".", this.name};
00207 endfunction: get_fullname
00208 
00209 
00210 function vmm_ral_reg vmm_ral_field::get_register();
00211    get_register = this.parent;
00212 endfunction: get_register
00213 
00214 
00215 function int unsigned vmm_ral_field::get_lsb_pos_in_register();
00216    get_lsb_pos_in_register = this.lsb;
00217 endfunction: get_lsb_pos_in_register
00218 
00219 
00220 function int unsigned vmm_ral_field::get_n_bits();
00221    get_n_bits = this.size;
00222 endfunction: get_n_bits
00223 
00224 
00225 function vmm_ral::access_e vmm_ral_field::get_access(string domain = "");
00226    get_access = this.access;
00227    if (parent.get_n_domains() == 1 || domain == "BaCkDoOr") return get_access;
00228 
00229    // Is the register restricted in this domain?
00230    case (this.parent.get_rights(domain))
00231      vmm_ral::RW:
00232        // No restrictions
00233        return get_access;
00234 
00235      vmm_ral::RO:
00236        case (get_access)
00237          vmm_ral::RW,
00238          vmm_ral::RO,
00239          vmm_ral::W1,
00240          vmm_ral::W1C: get_access = vmm_ral::RO;
00241 
00242          vmm_ral::RU,
00243          vmm_ral::A0,
00244          vmm_ral::A1: get_access = vmm_ral::RU;
00245 
00246          vmm_ral::WO: begin
00247             `vmm_error(this.log,
00248                        $psprintf("WO field \"%s\" restricted to RO in domain \"%s\"",
00249                                  this.get_name(), domain));
00250          end
00251 
00252          // No change for the other modes (OTHER, USERx)
00253        endcase
00254 
00255      vmm_ral::WO:
00256        case (get_access)
00257          vmm_ral::RW,
00258          vmm_ral::WO: get_access = vmm_ral::WO;
00259 
00260          vmm_ral::RO,
00261          vmm_ral::RU,
00262          vmm_ral::W1C,
00263          vmm_ral::A0,
00264          vmm_ral::A1: begin
00265             `vmm_error(this.log,
00266                        $psprintf("%s field \"%s\" restricted to WO in domain \"%s\"",
00267                                  get_access.name(), this.get_name(), domain));
00268          end
00269 
00270          // No change for the other modes (W1, OTHER, USERx)
00271        endcase
00272 
00273      default:
00274        `vmm_error(this.log,
00275                   $psprintf("Shared register \"%s\" containing field \"%s\" is not shared in domain \"%s\"",
00276                             this.parent.get_name(), this.get_name(), domain));
00277    endcase
00278 endfunction: get_access
00279 
00280 
00281 function vmm_ral::access_e vmm_ral_field::set_access(vmm_ral::access_e mode);
00282    set_access = this.access;
00283    this.access = mode;
00284 endfunction: set_access
00285 
00286 
00287 function void vmm_ral_field::display(string prefix = "");
00288    $write("%s\n", this.psdisplay(prefix));
00289 endfunction: display
00290 
00291 
00292 function string vmm_ral_field::psdisplay(string prefix = "");
00293    string fmt;
00294    $sformat(fmt, "%0d'h%%%0dh", this.get_n_bits(),
00295             (this.get_n_bits()-1)/4 + 1);
00296    $sformat(psdisplay, {"%s%s[%0d-%0d] = ",fmt,"%s"}, prefix,
00297             this.get_name(),
00298             this.get_lsb_pos_in_register() + this.get_n_bits() - 1,
00299             this.get_lsb_pos_in_register(), this.desired,
00300             (this.desired != this.mirrored) ? $psprintf({" (Mirror: ",fmt,")"}, this.mirrored) : "");
00301 endfunction: psdisplay
00302 
00303 
00304 
00305 function bit [`VMM_RAL_DATA_WIDTH-1:0] vmm_ral_field::XpredictX(bit [`VMM_RAL_DATA_WIDTH-1:0] cur_val,
00306                                                                 bit [`VMM_RAL_DATA_WIDTH-1:0] wr_val,
00307                                                                 string                        domain);
00308 
00309    case (this.get_access(domain))
00310      vmm_ral::RW:    return wr_val;
00311      vmm_ral::RO:    return cur_val;
00312      vmm_ral::WO:    return wr_val;
00313      vmm_ral::W1:    return (this.written) ? cur_val : wr_val;
00314      vmm_ral::RU:    return cur_val;
00315      vmm_ral::RC:    return cur_val;
00316      vmm_ral::W1C:   return cur_val & (~wr_val);
00317      vmm_ral::A0:    return cur_val | wr_val;
00318      vmm_ral::A1:    return cur_val & wr_val;
00319      vmm_ral::DC:    return wr_val;
00320      vmm_ral::OTHER,
00321      vmm_ral::USER0,
00322      vmm_ral::USER1,
00323      vmm_ral::USER2,
00324      vmm_ral::USER3: return wr_val;
00325    endcase
00326 
00327    `vmm_fatal(log, "vmm_ral_field::XpredictX(): Internal error");
00328    return 0;
00329 endfunction: XpredictX
00330 
00331 
00332 function void vmm_ral_field::XforceX(bit[`VMM_RAL_DATA_WIDTH-1:0] value,
00333                                      vmm_ral::path_e              path,
00334                                      string                       domain);
00335    value &= ('b1 << this.size)-1;
00336 
00337    // If the value was obtained via a front-door access
00338    // then a RC field will have been cleared
00339    if (path == vmm_ral::BFM && this.get_access(domain) == vmm_ral::RC) begin
00340       value = 0;
00341    end
00342 
00343    // If the value of a WO field was obtained via a front-door access
00344    // it will always read back as 0 and the value of the field
00345    // cannot be inferred from it
00346    if (path == vmm_ral::BFM && this.get_access(domain) == vmm_ral::WO) return;
00347 
00348    this.mirrored = value;
00349    this.desired = value;
00350    this.value   = value;
00351 endfunction: XforceX
00352 
00353 
00354 function void vmm_ral_field::XwroteX(bit[`VMM_RAL_DATA_WIDTH-1:0] value,
00355                                      vmm_ral::path_e              path,
00356                                      string                       domain);
00357    if (value >> this.size) begin
00358       `vmm_warning(this.log, $psprintf("Specified value (0x%h) greater than field \"%s\" size (%0d bits)",
00359                                        value, this.get_name(), this.size));
00360       value &= ('b1 << this.size)-1;
00361    end
00362 
00363    if (path == vmm_ral::BFM) begin
00364       this.mirrored = this.XpredictX(this.mirrored, value, domain);
00365    end
00366    else this.mirrored = value;
00367 
00368    this.desired = this.mirrored;
00369    this.value   = this.mirrored;
00370 
00371    this.written = 1;
00372 endfunction: XwroteX
00373 
00374 
00375 function bit [`VMM_RAL_DATA_WIDTH-1:0] vmm_ral_field::XupdX();
00376    // Figure out which value must be written to get the desired value
00377    // given what we think is the current value in the hardware
00378    XupdX = 0;
00379 
00380    case (this.access)
00381       vmm_ral::RW:    XupdX = this.desired;
00382       vmm_ral::RO:    XupdX = this.desired;
00383       vmm_ral::WO:    XupdX = this.desired;
00384       vmm_ral::W1:    XupdX = this.desired;
00385       vmm_ral::RU:    XupdX = this.desired;
00386       vmm_ral::RC:    XupdX = this.desired;
00387       vmm_ral::W1C:   XupdX = ~this.desired;
00388       vmm_ral::A0:    XupdX = this.desired;
00389       vmm_ral::A1:    XupdX = this.desired;
00390       vmm_ral::DC,
00391       vmm_ral::OTHER,
00392       vmm_ral::USER0,
00393       vmm_ral::USER1,
00394       vmm_ral::USER2,
00395       vmm_ral::USER3: XupdX = this.desired;
00396    endcase
00397 endfunction: XupdX
00398 
00399 
00400 function void vmm_ral_field::set(bit[`VMM_RAL_DATA_WIDTH-1:0] value);
00401    if (value >> this.size) begin
00402       `vmm_warning(this.log, $psprintf("Specified value (0x%h) greater than field \"%s\" size (%0d bits)",
00403                                        value, this.get_name(), this.size));
00404       value &= ('b1 << this.size)-1;
00405    end
00406 
00407    case (this.access)
00408       vmm_ral::RW:    this.desired = value;
00409       vmm_ral::RO:    this.desired = this.desired;
00410       vmm_ral::WO:    this.desired = value;
00411       vmm_ral::W1:    this.desired = (this.written) ? this.desired : value;
00412       vmm_ral::RU:    this.desired = this.desired;
00413       vmm_ral::RC:    this.desired = this.desired;
00414       vmm_ral::W1C:   this.desired &= (~value);
00415       vmm_ral::A0:    this.desired |= value;
00416       vmm_ral::A1:    this.desired &= value;
00417       vmm_ral::DC,
00418       vmm_ral::OTHER,
00419       vmm_ral::USER0,
00420       vmm_ral::USER1,
00421       vmm_ral::USER2,
00422       vmm_ral::USER3: this.desired = value;
00423    endcase
00424    this.value = this.desired;
00425 endfunction: set
00426 
00427  
00428 function bit vmm_ral_field::predict(bit[`VMM_RAL_DATA_WIDTH-1:0] value);
00429    if (this.parent.Xis_busyX) begin
00430       `vmm_warning(this.log, $psprintf("Trying to predict value of field \"%s\" while register \"%s\" is being accessed",
00431                                        this.get_name(),
00432                                        this.parent.get_fullname()));
00433       return 0;
00434    end
00435    
00436    value &= ('b1 << this.size)-1;
00437    this.mirrored = value;
00438    this.desired = value;
00439    this.value   = value;
00440 
00441    return 1;
00442 endfunction: predict
00443 
00444 
00445 function bit[`VMM_RAL_DATA_WIDTH-1:0] vmm_ral_field::get();
00446    get = this.desired;
00447 endfunction: get
00448 
00449 
00450 function void vmm_ral_field::reset(vmm_ral::reset_e kind = vmm_ral::HARD);
00451    case (kind)
00452      vmm_ral::HARD: begin
00453         this.mirrored = reset_value;
00454         this.desired  = reset_value;
00455         this.written  = 0;
00456      end
00457      vmm_ral::SOFT: begin
00458         if (soft_reset_value !== 'x) begin
00459            this.mirrored = soft_reset_value;
00460            this.desired  = soft_reset_value;
00461         end
00462      end
00463    endcase
00464    this.value = this.desired;
00465 endfunction: reset
00466 
00467 
00468 function logic [`VMM_RAL_DATA_WIDTH-1:0]
00469    vmm_ral_field::get_reset(vmm_ral::reset_e kind = vmm_ral::HARD);
00470 
00471    if (kind == vmm_ral::SOFT) return this.soft_reset_value;
00472 
00473    return this.reset_value;
00474 endfunction: get_reset
00475 
00476 
00477 function logic [`VMM_RAL_DATA_WIDTH-1:0]
00478    vmm_ral_field::set_reset(logic [`VMM_RAL_DATA_WIDTH-1:0] value,
00479                             vmm_ral::reset_e kind = vmm_ral::HARD);
00480    case (kind)
00481      vmm_ral::HARD: begin
00482         set_reset = this.reset_value;
00483         this.reset_value = value;
00484      end
00485      vmm_ral::SOFT: begin
00486         set_reset = this.soft_reset_value;
00487         this.soft_reset_value = value;
00488      end
00489    endcase
00490 endfunction: set_reset
00491 
00492 
00493 function bit vmm_ral_field::needs_update();
00494    needs_update = (this.mirrored != this.desired);
00495 endfunction: needs_update
00496 
00497 
00498 task vmm_ral_field::write(output vmm_rw::status_e              status,
00499                           input  bit [`VMM_RAL_DATA_WIDTH-1:0] value,
00500                           input  vmm_ral::path_e               path = vmm_ral::DEFAULT,
00501                           input  string                        domain = "",
00502                           input  int                           data_id = -1,
00503                           input  int                           scenario_id = -1,
00504                           input  int                           stream_id = -1);
00505    bit [`VMM_RAL_DATA_WIDTH-1:0] tmp;
00506    vmm_ral_field fields[];
00507 
00508    this.parent.XatomicX(1);
00509 
00510    if (value >> this.size) begin
00511       `vmm_warning(log, $psprintf("vmm_ral_field::write(): Value greater than field \"%s\" size", this.get_name()));
00512       value &= value & ((1<<this.size)-1);
00513    end
00514 
00515    tmp = 0;
00516    // What values are written for the other fields???
00517    this.parent.get_fields(fields);
00518    foreach (fields[i]) begin
00519       if (fields[i] == this) begin
00520          tmp |= value << this.lsb;
00521          continue;
00522       end
00523 
00524       // It depends on what kind of bits they are made of...
00525       case (fields[i].get_access(domain))
00526         // These...
00527         vmm_ral::RW,
00528         vmm_ral::RO,
00529         vmm_ral::WO,
00530         vmm_ral::W1,
00531         vmm_ral::RU,
00532         vmm_ral::DC,
00533         vmm_ral::OTHER,
00534         vmm_ral::USER0,
00535         vmm_ral::USER1,
00536         vmm_ral::USER2,
00537         vmm_ral::USER3:
00538           // Use their mirrored value
00539           tmp |= fields[i].get() << fields[i].get_lsb_pos_in_register();
00540 
00541         // These...
00542         vmm_ral::RC,
00543         vmm_ral::W1C,
00544         vmm_ral::A0:
00545           // Use all 0's
00546           tmp |= 0;
00547 
00548         // These...
00549         vmm_ral::A1:
00550           // Use all 1's
00551           tmp |= ((1<<fields[i].get_n_bits())-1) << fields[i].get_lsb_pos_in_register();
00552 
00553         default:
00554           `vmm_fatal(log, "Internal error: write() does not handle field access mode");
00555       endcase
00556    end
00557 
00558    this.parent.XwriteX(status, tmp, path, domain, data_id, scenario_id, stream_id);
00559 
00560    this.parent.XatomicX(0);
00561 endtask: write
00562 
00563 
00564 task vmm_ral_field::read(output vmm_rw::status_e             status,
00565                          output bit[`VMM_RAL_DATA_WIDTH-1:0] value,
00566                          input  vmm_ral::path_e              path = vmm_ral::DEFAULT,
00567                          input  string                       domain = "",
00568                          input  int                          data_id = -1,
00569                          input  int                          scenario_id = -1,
00570                          input  int                          stream_id = -1);
00571    bit[`VMM_RAL_DATA_WIDTH-1:0] reg_value;
00572 
00573    this.parent.read(status, reg_value, path, domain, data_id, scenario_id, stream_id);
00574    value = (reg_value >> lsb) & ((1<<size))-1;
00575 endtask: read
00576                
00577 
00578 task vmm_ral_field::poke(output vmm_rw::status_e              status,
00579                          input  bit [`VMM_RAL_DATA_WIDTH-1:0] value,
00580                          input  int                           data_id = -1,
00581                          input  int                           scenario_id = -1,
00582                          input  int                           stream_id = -1);
00583    bit [`VMM_RAL_DATA_WIDTH-1:0] tmp;
00584 
00585    this.parent.XatomicX(1);
00586    this.parent.Xis_locked_by_fieldX = 1'b1;
00587 
00588    if (value >> this.size) begin
00589       `vmm_warning(log, $psprintf("vmm_ral_field::poke(): Value greater than field \"%s\" size", this.get_name()));
00590       value &= value & ((1<<this.size)-1);
00591    end
00592 
00593    tmp = 0;
00594    // What is the current values of the other fields???
00595    this.parent.peek(status, tmp, data_id, scenario_id, stream_id);
00596    if (status != vmm_rw::IS_OK) begin
00597       `vmm_error(log, $psprintf("vmm_ral_field::poke(): Peeking register \"%s\" returned status %s", this.parent.get_fullname(), status.name()));
00598       this.parent.XatomicX(0);
00599       this.parent.Xis_locked_by_fieldX = 1'b0;
00600       return;
00601    end
00602 
00603    // Force the value for this field then poke the resulting value
00604    tmp &= ~(((1<<this.size)-1) << this.lsb);
00605    tmp |= value << this.lsb;
00606    this.parent.poke(status, tmp, data_id, scenario_id, stream_id);
00607 
00608    this.parent.XatomicX(0);
00609    this.parent.Xis_locked_by_fieldX = 1'b0;
00610 endtask: poke
00611 
00612 
00613 task vmm_ral_field::peek(output vmm_rw::status_e             status,
00614                          output bit[`VMM_RAL_DATA_WIDTH-1:0] value,
00615                          input  int                          data_id = -1,
00616                          input  int                          scenario_id = -1,
00617                          input  int                          stream_id = -1);
00618    bit[`VMM_RAL_DATA_WIDTH-1:0] reg_value;
00619 
00620    this.parent.peek(status, reg_value, data_id, scenario_id, stream_id);
00621    value = (reg_value >> lsb) & ((1<<size))-1;
00622 endtask: peek
00623                
00624 
00625 task vmm_ral_field::mirror(output vmm_rw::status_e status,
00626                            input  vmm_ral::check_e check = vmm_ral::QUIET,
00627                            input  vmm_ral::path_e  path = vmm_ral::DEFAULT,
00628                            string                  domain = "");
00629    this.parent.mirror(status, check, path, domain);
00630 endtask: mirror
00631 
00632 
00633 function void vmm_ral_field::prepend_callback(vmm_ral_field_callbacks cb);
00634    foreach (this.XcbsX[i]) begin
00635       if (this.XcbsX[i] == cb) begin
00636          `vmm_warning(this.log, $psprintf("Callback has already been registered with field \"%s\"", this.get_name()));
00637          return;
00638       end
00639    end
00640    
00641    // Prepend new callback
00642    this.XcbsX.push_front(cb);
00643 endfunction: prepend_callback
00644 
00645 
00646 function void vmm_ral_field::append_callback(vmm_ral_field_callbacks cb);
00647    foreach (this.XcbsX[i]) begin
00648       if (this.XcbsX[i] == cb) begin
00649          `vmm_warning(this.log, $psprintf("Callback has already been registered with field \"%s\"", this.get_name()));
00650          return;
00651       end
00652    end
00653    
00654    // Append new callback
00655    this.XcbsX.push_back(cb);
00656 endfunction: append_callback
00657 
00658 
00659 function void vmm_ral_field::unregister_callback(vmm_ral_field_callbacks cb);
00660    foreach (this.XcbsX[i]) begin
00661       if (this.XcbsX[i] == cb) begin
00662          int j = i;
00663          // Unregister it
00664          this.XcbsX.delete(j);
00665          return;
00666       end
00667    end
00668 
00669    `vmm_warning(this.log, $psprintf("Callback was not registered with field \"%s\"", this.get_name()));
00670 endfunction: unregister_callback
00671 
00672 
00673 function void vmm_ral_field::pre_randomize();
00674    // Update the only publicly known property with the current
00675    // desired value so it can be used as a state variable should
00676    // the rand_mode of the field be turned off.
00677    this.value = this.desired;
00678 endfunction: pre_randomize
00679 
00680 
00681 function void vmm_ral_field::post_randomize();
00682    this.desired = this.value;
00683 endfunction: post_randomize