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