vmm_ral_mem.sv

Go to the documentation of this file.
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 function vmm_ral_mem::new(vmm_ral_block                 parent,
00024                           string                        name,
00025                           vmm_ral::access_e             access,
00026                           longint unsigned              size,
00027                           int unsigned                  n_bits,
00028                           bit [`VMM_RAL_ADDR_WIDTH-1:0] base_addr,
00029                           string                        domain,
00030                           bit                           cover_on,
00031                           bit [1:0]                     rights,
00032                           bit                           unmapped);
00033 
00034    this.name = name;
00035    this.locked = 0;
00036 
00037    if (n_bits == 0) begin
00038       `vmm_error(this.log, $psprintf("Memory \"%s\" cannot have 0 bits", this.get_fullname()));
00039       n_bits = 1;
00040    end
00041    if (n_bits > `VMM_RAL_DATA_WIDTH) begin
00042       `vmm_error(this.log, $psprintf("Memory \"%s\" cannot have more than %0d bits (%0d)", this.get_fullname(), `VMM_RAL_DATA_WIDTH, n_bits));
00043       n_bits = `VMM_RAL_DATA_WIDTH;
00044    end
00045    if (access != vmm_ral::RW && access != vmm_ral::RO) begin
00046       `vmm_error(this.log, $psprintf("Memory %s can only be RW or RO",
00047                                      this.get_fullname()));
00048       access = vmm_ral::RW;
00049    end
00050 
00051    this.parent   = parent;
00052    this.size     = size;
00053    this.access   = access;
00054    this.n_bits   = n_bits;
00055    this.backdoor  = null;
00056 
00057    this.parent.register_mem(this);
00058    this.add_domain(base_addr, domain, rights, unmapped);
00059 
00060    this.cover_on = cover_on;
00061    this.no_cover = !cover_on;
00062 
00063    begin
00064       vmm_mam_cfg cfg = new;
00065 
00066       cfg.n_bytes      = ((n_bits-1) / 8) + 1;
00067       cfg.start_offset = 0;
00068       cfg.end_offset   = size-1;
00069 
00070       cfg.mode     = vmm_mam::GREEDY;
00071       cfg.locality = vmm_mam::BROAD;
00072 
00073       this.mam = new(this.get_fullname(), cfg, this);
00074    end
00075 endfunction: new
00076 
00077 
00078 function void vmm_ral_mem::Xlock_modelX();
00079    this.locked = 1;
00080 endfunction: Xlock_modelX
00081 
00082 
00083 function void vmm_ral_mem::add_domain(bit [`VMM_RAL_ADDR_WIDTH-1:0] base_addr,
00084                                       string                        domain,
00085                                       bit [1:0]                     rights,
00086                                       bit                           unmapped);
00087    vmm_ral::access_e acc;
00088 
00089    // Verify that this is a valid domain in the block
00090    string domains[];
00091 
00092    if (this.locked) begin
00093       `vmm_error(this.log, $psprintf("Cannot add domain to locked memory %s", this.get_fullname()));
00094       return;
00095    end
00096 
00097    case (rights)
00098      2'b11: acc = vmm_ral::RW;
00099      2'b10: acc = vmm_ral::RO;
00100      2'b01: acc = vmm_ral::WO;
00101      default:
00102        `vmm_error(this.log,
00103                   $psprintf("Memory %s has no access rights in domain \"%s\"",
00104                             this.get_fullname(), domain));
00105    endcase
00106 
00107    this.parent.get_domains(domains);
00108    foreach(domains[i]) begin
00109       if (domains[i] == domain) begin
00110          automatic int n = this.offset_in_block.size();
00111    
00112          this.offset_in_block = new [n + 1] (this.offset_in_block);
00113          this.offset_in_block[n] = (unmapped) ? 'X : base_addr;
00114     
00115          this.domains = new [n + 1] (this.domains);
00116          this.domains[n] = domain;
00117 
00118          this.rights = new [n + 1] (this.rights);
00119          this.rights[n] = acc;
00120 
00121          this.frontdoor = new [n + 1] (this.frontdoor);
00122          this.frontdoor[n] = null;
00123          return;
00124       end
00125    end
00126    `vmm_error(this.log, $psprintf("Domain \"%s\" not found in parent block %s of memory %s",
00127                                   domain, this.parent.get_name(), this.get_fullname()));
00128 endfunction: add_domain
00129 
00130 
00131 function void vmm_ral_mem::Xregister_ral_accessX(vmm_ral_access access);
00132    // There can only be one RAL Access on a RAL model
00133    if (this.ral_access != null && this.ral_access != access) begin
00134       `vmm_fatal(this.log, $psprintf("Memory %s is already used by another RAL access instance", this.get_fullname()));
00135    end
00136    this.ral_access = access;
00137 endfunction: Xregister_ral_accessX
00138 
00139 
00140 function string vmm_ral_mem::get_name();
00141    get_name = this.name;
00142 endfunction: get_name
00143 
00144 
00145 function string vmm_ral_mem::get_fullname();
00146    vmm_ral_block blk;
00147 
00148    get_fullname = this.get_name();
00149 
00150    // Do not include top-level name in full name
00151    blk = this.get_block();
00152    if (blk == null) return get_fullname;
00153    if (blk.get_parent() == null) return get_fullname;
00154 
00155    get_fullname = {this.parent.get_fullname(), ".", get_fullname};
00156 endfunction: get_fullname
00157 
00158 
00159 function int vmm_ral_mem::get_n_domains();
00160    get_n_domains = this.domains.size();
00161 endfunction: get_n_domains
00162 
00163 
00164 function void vmm_ral_mem::get_domains(ref string domains[]);
00165    domains = new [this.domains.size()] (this.domains);
00166 endfunction: get_domains
00167 
00168 
00169 function vmm_ral::access_e vmm_ral_mem::get_access(string domain);
00170    get_access = this.access;
00171    if (this.get_n_domains() == 1) return get_access;
00172 
00173    // Is the memory restricted in this domain?
00174    case (this.get_rights(domain))
00175      vmm_ral::RW:
00176        // No restrictions
00177        return get_access;
00178 
00179      vmm_ral::RO:
00180        case (get_access)
00181          vmm_ral::RW,
00182          vmm_ral::RO: get_access = vmm_ral::RO;
00183 
00184          vmm_ral::WO: begin
00185             `vmm_error(this.log,
00186                        $psprintf("WO memory %s restricted to RO in domain \"%s\"",
00187                                  this.get_fullname(), domain));
00188          end
00189 
00190          default:
00191            `vmm_error(this.log,
00192                       $psprintf("Invalid memory %s access mode \"%s\"",
00193                                 this.get_fullname(), get_access.name()));
00194        endcase
00195 
00196      vmm_ral::WO:
00197        case (get_access)
00198          vmm_ral::RW,
00199          vmm_ral::WO: get_access = vmm_ral::WO;
00200 
00201          vmm_ral::RO: begin
00202             `vmm_error(this.log,
00203                        $psprintf("RO memory %s restricted to WO in domain \"%s\"",
00204                                  this.get_fullname(), get_access.name(), domain));
00205          end
00206 
00207          default:
00208            `vmm_error(this.log,
00209                       $psprintf("Invalid memory %s access mode \"%s\"",
00210                                 this.get_fullname(), get_access.name()));
00211        endcase
00212 
00213      default:
00214        `vmm_error(this.log,
00215                   $psprintf("Shared memory \"%s\" is not shared in domain \"%s\"",
00216                             this.get_fullname(), domain));
00217    endcase
00218 endfunction: get_access
00219 
00220 
00221 function vmm_ral::access_e vmm_ral_mem::get_rights(string domain);
00222    int i;
00223 
00224    // No right restrictions if not shared
00225    if (this.domains.size() == 1) begin
00226       return vmm_ral::RW;
00227    end
00228 
00229    i = this.get_domain_index(domain);
00230    if (i < 0) return vmm_ral::RW;
00231 
00232    get_rights = this.rights[i];
00233 endfunction: get_rights
00234 
00235 
00236 function void vmm_ral_mem::get_virtual_fields(ref vmm_ral_vfield fields[]);
00237   vmm_ral_vfield vfields[];
00238 
00239   fields = new[0];
00240   foreach (this.XvregsX[i]) begin
00241     int n = fields.size();
00242     this.XvregsX[i].get_fields(vfields);
00243     fields = new[n + vfields.size()] (fields);
00244     foreach(vfields[j]) begin
00245       fields[n+j] = vfields[j];
00246     end
00247   end
00248 endfunction: get_virtual_fields
00249 
00250 
00251 // Return first occurrence of vfield matching name
00252 function vmm_ral_vfield vmm_ral_mem::get_virtual_field_by_name(string name);
00253   vmm_ral_vfield vfields[];
00254 
00255   this.get_virtual_fields(vfields);
00256   foreach (vfields[i]) begin
00257     if (vfields[i].get_name() == name) return vfields[i];
00258   end
00259   `vmm_warning(this.log,
00260                $psprintf("Unable to find virtual field \"%s\" in memory %s.",
00261                          name, this.get_fullname()));
00262    return null;
00263 endfunction: get_virtual_field_by_name
00264 
00265 
00266 function void vmm_ral_mem::get_virtual_registers(ref vmm_ral_vreg regs[]);
00267   regs = new[this.XvregsX.size()];
00268   foreach (this.XvregsX[i]) begin
00269      regs[i] = this.XvregsX[i];
00270   end
00271 endfunction: get_virtual_registers
00272 
00273 
00274 function vmm_ral_vreg vmm_ral_mem::get_vreg_by_name(string name);
00275   foreach (this.XvregsX[i]) begin
00276     if (this.XvregsX[i].get_name() == name) return this.XvregsX[i];
00277   end
00278   `vmm_warning(this.log,
00279                $psprintf("Unable to find virtual register \"%s\" in memory %s.",
00280                          name, this.get_fullname()));
00281 
00282 endfunction: get_vreg_by_name
00283 
00284 
00285 function vmm_ral_vreg vmm_ral_mem::get_vreg_by_offset(bit [63:0] offset,
00286                                                       string domain);
00287    `vmm_error(this.log, "vmm_ral_mem::get_vreg_by_offset() not yet implemented");
00288    return null;
00289 endfunction: get_vreg_by_offset
00290 
00291 
00292 function vmm_ral_block vmm_ral_mem::get_block();
00293    get_block = this.parent;
00294 endfunction: get_block
00295 
00296 
00297 function bit [`VMM_RAL_ADDR_WIDTH-1:0] vmm_ral_mem::get_offset_in_block(bit [`VMM_RAL_ADDR_WIDTH-1:0] mem_addr,
00298                                                                         string                        domain);
00299    foreach (this.domains[i]) begin
00300       if (this.domains[i] == domain) begin
00301          if (this.offset_in_block[i] === 'x) begin
00302             `vmm_warning(this.log, $psprintf("Memory \"%s\" is unmapped in domain \"%s\".", this.get_name(), domain));
00303             return '0;
00304          end
00305          
00306          return this.offset_in_block[i];
00307       end
00308    end
00309    `vmm_warning(this.log, $psprintf("Unable to find offset within domain \"%s\" in memory %s.",
00310                                     domain, this.get_fullname()));
00311    get_offset_in_block = '1;
00312 endfunction: get_offset_in_block
00313 
00314 
00315 function bit [`VMM_RAL_ADDR_WIDTH-1:0] vmm_ral_mem::get_address_in_system(bit [`VMM_RAL_ADDR_WIDTH-1:0] mem_addr,
00316                                                        string                                           domain);
00317    bit [`VMM_RAL_ADDR_WIDTH-1:0] addr[];
00318          
00319    int i = this.get_domain_index(domain);
00320    if (i < 0) return 0;
00321          
00322    if (this.ral_access == null) begin
00323       `vmm_fatal(this.parent.log,
00324                  "RAL model is not associated with an access transactor");
00325       return 0;
00326    end
00327          
00328    if (this.offset_in_block[i] === 'x) begin
00329       `vmm_error(this.log, $psprintf("Memory \"%s\" is unmapped in domain \"%s\".", this.get_name(), this.domains[i]));
00330       return '1;
00331    end
00332          
00333    this.ral_access.Xget_physical_addressesX(this.offset_in_block[i],
00334                                             mem_addr, this.get_n_bytes(),
00335                                             this.parent,
00336                                             this.domains[i],
00337                                             addr);
00338 
00339    get_address_in_system = addr[0];
00340 endfunction: get_address_in_system
00341 
00342 
00343 function longint unsigned vmm_ral_mem::get_size();
00344    get_size = this.size;
00345 endfunction: get_size
00346 
00347 
00348 function int unsigned vmm_ral_mem::get_n_bits();
00349    get_n_bits = this.n_bits;
00350 endfunction: get_n_bits
00351 
00352 
00353 function int unsigned vmm_ral_mem::get_n_bytes();
00354    get_n_bytes = (this.n_bits - 1) / 8 + 1;
00355 endfunction: get_n_bytes
00356 
00357 
00358 function void vmm_ral_mem::display(string prefix,
00359                                    string domain);
00360    $write("%s\n", this.psdisplay(prefix, domain));
00361 endfunction: display
00362 
00363 
00364 function string vmm_ral_mem::psdisplay(string prefix,
00365                                        string domain);
00366    $sformat(psdisplay, "%sMemory %s -- %0dx%0d bits @", prefix,
00367             this.get_fullname(), this.get_size(), this.get_n_bits());
00368    foreach (this.domains[i]) begin
00369       if (this.domains[i] == domain) begin
00370          if (this.offset_in_block[i] === 'x) begin
00371             psdisplay = {psdisplay, "none"};
00372          end
00373          else begin
00374             $sformat(psdisplay, "%s'h%h", psdisplay,
00375                      this.get_address_in_system(0, domain));
00376          end
00377          break;
00378       end
00379    end
00380 endfunction: psdisplay
00381 
00382 
00383 function bit vmm_ral_mem::set_cover(bit is_on);
00384    set_cover = this.cover_on;
00385 
00386    if (this.no_cover && is_on) begin
00387       `vmm_warning(this.log, $psprintf("Cannot turn cover ON if constructed with coverage disabled in memory %s", this.get_fullname()));
00388       return 0;
00389    end
00390 
00391    this.cover_on = is_on;
00392 endfunction: set_cover
00393 
00394 
00395 function bit vmm_ral_mem::is_cover_on();
00396    is_cover_on = this.cover_on;
00397 endfunction: is_cover_on
00398 
00399 
00400 task vmm_ral_mem::init(output bit                           is_ok,
00401                        input  init_e                        pattern,
00402                        input  bit [`VMM_RAL_DATA_WIDTH-1:0] data);
00403    int incr;
00404    is_ok = 0;
00405 
00406    if (this.backdoor == null) begin
00407       `vmm_error(this.log, $psprintf("No backdoor available to initialize memory %s", this.get_fullname()));
00408       return;
00409    end
00410 
00411    case (pattern)
00412    UNKNOWNS:
00413      begin
00414         data = 'x;
00415         incr = 0;
00416      end
00417 
00418    ZEROES:
00419      begin
00420         data = '0;
00421         incr = 0;
00422      end
00423 
00424    ONES:
00425      begin
00426         data = '1;
00427         incr = 0;
00428      end
00429 
00430    VALUE:
00431      begin
00432         incr = 0;
00433      end
00434 
00435    INCR:
00436      begin
00437         incr = 1;
00438      end
00439 
00440    DECR:
00441      begin
00442         incr = -1;
00443      end
00444    endcase
00445 
00446    // ToDo...
00447 endtask:init
00448 
00449 
00450 task vmm_ral_mem::write(output vmm_rw::status_e              status,
00451                         input  bit [`VMM_RAL_ADDR_WIDTH-1:0] mem_addr,
00452                         input  bit [`VMM_RAL_DATA_WIDTH-1:0] value,
00453                         input  vmm_ral::path_e               path,
00454                         input  string                        domain,
00455                         input  int                           data_id,
00456                         input  int                           scenario_id,
00457                         input  int                           stream_id);
00458    status = vmm_rw::ERROR;
00459    
00460    if (this.ral_access == null) begin
00461       `vmm_error(this.log, $psprintf("Memory %s not associated with RAL access object", this.get_fullname()));
00462       return;
00463    end
00464    
00465    if (path == vmm_ral::DEFAULT) path = this.parent.get_default_access();
00466 
00467    `vmm_callback(vmm_ral_mem_callbacks,
00468                  pre_write(this, mem_addr, value, path, domain));
00469 
00470    if (path == vmm_ral::DEFAULT) path = this.parent.get_default_access();
00471 
00472    if (path == vmm_ral::BACKDOOR &&
00473        this.backdoor == null) begin
00474       `vmm_warning(this.log, $psprintf("No backdoor access available for memory \"%s\". Using frontdoor instead.", this.get_name()));
00475       path = vmm_ral::BFM;
00476    end
00477 
00478    case (path)
00479       
00480       vmm_ral::BFM: begin
00481          int di = this.get_domain_index(domain);
00482          if (di < 0) return;
00483 
00484          if (this.frontdoor[di] != null) begin
00485             this.frontdoor[di].write(status, mem_addr, value,
00486                                      data_id, scenario_id, stream_id);
00487          end
00488          else begin
00489             bit [`VMM_RAL_ADDR_WIDTH-1:0] addr[];
00490             int w, j;
00491             int n_bits;
00492          
00493             if (this.offset_in_block[di] === 'x) begin
00494                `vmm_error(this.log, $psprintf("Memory \"%s\" unmapped in domain \"%s\" does not have a user-defined frontdoor",
00495                                               this.get_name(),
00496                                               this.domains[di]));
00497                return;
00498             end
00499          
00500             w = this.ral_access.Xget_physical_addressesX(this.offset_in_block[di],
00501                                                          mem_addr,
00502                                                          this.get_n_bytes(),
00503                                                          this.parent,
00504                                                          this.domains[di],
00505                                                          addr);
00506             j = 0;
00507             n_bits = this.get_n_bits;
00508             foreach (addr[i]) begin
00509                bit [`VMM_RAL_DATA_WIDTH-1:0] data;
00510                data = value >> (j*8);
00511                this.ral_access.write(status, addr[i], data,
00512                                      (n_bits > w*8) ? w*8 : n_bits,
00513                                      this.parent.get_external_domain(this.domains[di]),
00514                                      data_id, scenario_id, stream_id);
00515                if (status != vmm_rw::IS_OK) break;
00516                j += w;
00517                n_bits -= w * 8;
00518             end
00519          end
00520 
00521          if (this.cover_on) this.parent.XsampleX(this.offset_in_block[di], di);
00522       end
00523       
00524       vmm_ral::BACKDOOR: begin
00525          // Mimick front door access: Do not write read-only memories
00526          if (this.get_access(domain) == vmm_ral::RW) begin
00527             this.poke(status, mem_addr, value,
00528                       data_id, scenario_id, stream_id);
00529          end else status = vmm_rw::IS_OK;
00530       end
00531    endcase
00532 
00533    `vmm_callback(vmm_ral_mem_callbacks,
00534                  post_write(this, mem_addr, value, path, domain, status));
00535 
00536    `vmm_trace(this.log, $psprintf("Wrote memory \"%s\"[%0d] via %s: with 'h%h",
00537                                   this.get_fullname(), mem_addr,
00538                                   (path == vmm_ral::BFM) ? "frontdoor" : "backdoor",
00539                                   value));
00540 endtask: write
00541 
00542 
00543 task vmm_ral_mem::read(output vmm_rw::status_e              status,
00544                        input  bit [`VMM_RAL_ADDR_WIDTH-1:0] mem_addr,
00545                        output bit [`VMM_RAL_DATA_WIDTH-1:0] value,
00546                        input  vmm_ral::path_e               path,
00547                        input  string                        domain,
00548                        input  int                           data_id,
00549                        input  int                           scenario_id,
00550                        input  int                           stream_id);
00551    status = vmm_rw::ERROR;
00552    
00553    if (this.ral_access == null) begin
00554       `vmm_error(this.log, $psprintf("Memory %s not associated with RAL access object", this.get_fullname()));
00555       return;
00556    end
00557    
00558    if (path == vmm_ral::DEFAULT) path = this.parent.get_default_access();
00559 
00560    `vmm_callback(vmm_ral_mem_callbacks,
00561                  pre_read(this, mem_addr, path, domain));
00562 
00563    if (path == vmm_ral::DEFAULT) path = this.parent.get_default_access();
00564 
00565    if (path == vmm_ral::BACKDOOR &&
00566        this.backdoor == null) begin
00567       `vmm_warning(this.log, $psprintf("No backdoor access available for memory \"%s\". Using frontdoor instead.", this.get_name()));
00568       path = vmm_ral::BFM;
00569    end
00570 
00571    case (path)
00572       
00573       vmm_ral::BFM: begin
00574          int di = this.get_domain_index(domain);
00575          if (di < 0) return;
00576          
00577          if (this.frontdoor[di] != null) begin
00578             this.frontdoor[di].read(status, mem_addr, value,
00579                                    data_id, scenario_id, stream_id);
00580          end
00581          else begin
00582             bit [`VMM_RAL_ADDR_WIDTH-1:0] addr[];
00583             int w, j;
00584             int n_bits;
00585          
00586             if (this.offset_in_block[di] === 'x) begin
00587                `vmm_error(this.log, $psprintf("Memory \"%s\" unmapped in domain \"%s\" does not have a user-defined frontdoor",
00588                                               this.get_name(),
00589                                               this.domains[di]));
00590                return;
00591             end
00592          
00593             w = this.ral_access.Xget_physical_addressesX(this.offset_in_block[di],
00594                                                          mem_addr,
00595                                                          this.get_n_bytes(),
00596                                                          this.parent,
00597                                                          this.domains[di],
00598                                                          addr);
00599             j = 0;
00600             n_bits = this.get_n_bits();
00601             value = 0;
00602             foreach (addr[i]) begin
00603                bit [`VMM_RAL_DATA_WIDTH-1:0] data;
00604                this.ral_access.read(status, addr[i], data,
00605                                     (n_bits > w*8) ? w*8 : n_bits,
00606                                     this.parent.get_external_domain(this.domains[di]),
00607                                     data_id, scenario_id, stream_id);
00608                if (status != vmm_rw::IS_OK) break;
00609                value |= (data & ((1 << (w*8)) - 1)) << (j*8);
00610                j += w;
00611                n_bits -= w * 8;
00612             end
00613          end
00614 
00615          if (this.cover_on) this.parent.XsampleX(this.offset_in_block[di], di);
00616       end
00617       
00618       vmm_ral::BACKDOOR: begin
00619          this.peek(status, mem_addr, value,
00620                    data_id, scenario_id, stream_id);
00621       end
00622    endcase
00623 
00624    `vmm_callback(vmm_ral_mem_callbacks,
00625                  post_read(this, mem_addr, value, path, domain, status));
00626 
00627    `vmm_trace(this.log, $psprintf("Read memory \"%s\"[%0d] via %s: 'h%h",
00628                                   this.get_fullname(), mem_addr,
00629                                   (path == vmm_ral::BFM) ? "frontdoor" : "backdoor",
00630                                   value));
00631 endtask: read
00632 
00633 
00634 function bit vmm_ral_mem::validate_burst(vmm_ral_mem_burst burst);
00635    if (burst.start_offset >= this.get_size()) begin
00636       `vmm_error(this.log, $psprintf("Starting burst offset 'h%0h is greater than number of memory locations ('h%0h)",
00637                                      burst.start_offset, this.get_size()));
00638       return 0;
00639    end
00640 
00641    if (burst.max_offset >= this.get_size()) begin
00642       `vmm_error(this.log, $psprintf("Maximum burst offset 'h%0h is greater than number of memory locations ('h%0h)",
00643                                      burst.max_offset, this.get_size()));
00644       return 0;
00645    end
00646 
00647    if (burst.n_beats == 0) begin
00648       `vmm_error(this.log, "Zero-length burst");
00649       return 0;
00650    end
00651 
00652    if (burst.start_offset > burst.max_offset) begin
00653       `vmm_error(this.log, $psprintf("Starting burst offset ('h%0h) greater than maximum burst offset ('h%0h)",
00654                                      burst.start_offset, burst.max_offset));
00655       return 0;
00656    end
00657 
00658    if (burst.n_beats > 1 &&
00659        burst.start_offset + burst.incr_offset >= burst.max_offset) begin
00660       `vmm_error(this.log, $psprintf("First burst offset increment 'h%0h+%0h is greater than maximum burst offset ('h%0h)",
00661                                      burst.start_offset, burst.incr_offset,
00662                                      burst.max_offset));
00663       return 0;
00664    end
00665 
00666    return 1;
00667 endfunction: validate_burst
00668 
00669 
00670 task vmm_ral_mem::burst_write(output vmm_rw::status_e              status,
00671                               input  vmm_ral_mem_burst             burst,
00672                               input  bit [`VMM_RAL_DATA_WIDTH-1:0] value[],
00673                               input  vmm_ral::path_e               path,
00674                               input  string                        domain,
00675                               input  int                           data_id,
00676                               input  int                           scenario_id,
00677                               input  int                           stream_id);
00678    status = vmm_rw::ERROR;
00679 
00680    if (this.ral_access == null) begin
00681       `vmm_error(this.log, $psprintf("Memory %s not associated with RAL access object", this.get_fullname()));
00682       return;
00683    end
00684    
00685    if (path == vmm_ral::DEFAULT) path = this.parent.get_default_access();
00686 
00687    `vmm_callback(vmm_ral_mem_callbacks,
00688                  pre_burst(this, vmm_rw::WRITE, burst, value, path, domain));
00689 
00690    if (!this.validate_burst(burst)) return;
00691 
00692    if (path == vmm_ral::DEFAULT) path = this.parent.get_default_access();
00693 
00694    case (path)
00695       
00696       vmm_ral::BFM: begin
00697          int di = this.get_domain_index(domain);
00698          if (di < 0) return;
00699 
00700          if (this.frontdoor[di] != null) begin
00701             this.frontdoor[di].burst_write(status, burst, value,
00702                                            data_id, scenario_id, stream_id);
00703          end
00704          else begin
00705             bit [`VMM_RAL_ADDR_WIDTH-1:0] addr[];
00706             int w;
00707             int n_bits;
00708          
00709             if (this.offset_in_block[di] === 'x) begin
00710                `vmm_error(this.log, $psprintf("Memory \"%s\" unmapped in domain \"%s\" does not have a user-defined frontdoor",
00711                                               this.get_name(),
00712                                               this.domains[di]));
00713                return;
00714             end
00715          
00716             w = this.ral_access.Xget_physical_addressesX(this.offset_in_block[di],
00717                                                          burst.start_offset,
00718                                                          this.get_n_bytes(),
00719                                                          this.parent,
00720                                                          this.domains[di],
00721                                                          addr);
00722             n_bits = this.get_n_bits;
00723             // Cannot burst memory through a narrower datapath
00724             if (n_bits > w*8) begin
00725                `vmm_error(this.log, $psprintf("Cannot burst-write a %0d-bit memory through a narrower data path (%0d bytes)",
00726                                               n_bits, w));
00727                return;
00728             end
00729             // Translate offsets into addresses
00730             begin
00731                bit [`VMM_RAL_ADDR_WIDTH-1:0] start, incr, max;
00732 
00733                start = addr[0];
00734 
00735                w = this.ral_access.Xget_physical_addressesX(this.offset_in_block[di],
00736                                                             burst.start_offset + burst.incr_offset,
00737                                                             this.get_n_bytes(),
00738                                                             this.parent,
00739                                                             this.domains[di],
00740                                                             addr);
00741                incr = addr[0] - start;
00742 
00743                w = this.ral_access.Xget_physical_addressesX(this.offset_in_block[di],
00744                                                             burst.max_offset,
00745                                                             this.get_n_bytes(),
00746                                                             this.parent,
00747                                                             this.domains[di],
00748                                                             addr);
00749 
00750                max = addr[addr.size()-1];
00751 
00752                this.ral_access.burst_write(status, start, incr, max, value,
00753                                            burst.user_data, n_bits,
00754                                            this.parent.get_external_domain(this.domains[di]),
00755                                            data_id, scenario_id, stream_id);
00756             end
00757          end
00758 
00759          if (this.cover_on) begin
00760             bit [`VMM_RAL_ADDR_WIDTH-1:0] addr;
00761             for (addr = burst.start_offset;
00762                  addr <= burst.max_offset;
00763                  addr += burst.incr_offset) begin
00764                this.parent.XsampleX(this.offset_in_block[di] + addr, di);
00765             end
00766          end
00767       end
00768       
00769       vmm_ral::BACKDOOR: begin
00770          // Mimick front door access: Do not write read-only memories
00771          if (this.get_access(domain) == vmm_ral::RW) begin
00772             bit [`VMM_RAL_ADDR_WIDTH-1:0] addr;
00773             addr = burst.start_offset;
00774             foreach (value[i]) begin
00775                this.poke(status, addr, value[i],
00776                          data_id, scenario_id, stream_id);
00777                if (status != vmm_rw::IS_OK) return;
00778                addr += burst.incr_offset;
00779                if (addr > burst.max_offset) begin
00780                   addr -= (burst.max_offset - burst.start_offset - 1);
00781                end
00782             end
00783          end
00784          else status = vmm_rw::IS_OK;
00785       end
00786    endcase
00787 
00788    `vmm_callback(vmm_ral_mem_callbacks,
00789                  post_burst(this, vmm_rw::WRITE, burst, value,
00790                             path, domain, status));
00791 endtask: burst_write
00792 
00793 
00794 task vmm_ral_mem::burst_read(output vmm_rw::status_e              status,
00795                              input  vmm_ral_mem_burst             burst,
00796                              output bit [`VMM_RAL_DATA_WIDTH-1:0] value[],
00797                              input  vmm_ral::path_e               path,
00798                              input  string                        domain,
00799                              input  int                           data_id,
00800                              input  int                           scenario_id,
00801                              input  int                           stream_id);
00802    status = vmm_rw::ERROR;
00803 
00804    if (this.ral_access == null) begin
00805       `vmm_error(this.log, $psprintf("Memory %s not associated with RAL access object", this.get_fullname()));
00806       return;
00807    end
00808    
00809    if (path == vmm_ral::DEFAULT) path = this.parent.get_default_access();
00810 
00811    begin
00812       bit [`VMM_RAL_DATA_WIDTH-1:0] junk[];
00813 
00814       `vmm_callback(vmm_ral_mem_callbacks,
00815                     pre_burst(this, vmm_rw::READ, burst, junk, path, domain));
00816    end
00817 
00818    if (!this.validate_burst(burst)) return;
00819 
00820    if (path == vmm_ral::DEFAULT) path = this.parent.get_default_access();
00821 
00822    case (path)
00823       
00824       vmm_ral::BFM: begin
00825          int di = this.get_domain_index(domain);
00826          if (di < 0) return;
00827          
00828          if (this.frontdoor[di] != null) begin
00829             this.frontdoor[di].burst_read(status, burst, value,
00830                                           data_id, scenario_id, stream_id);
00831          end
00832          else begin
00833             bit [`VMM_RAL_ADDR_WIDTH-1:0] addr[];
00834             int n_bits, w;
00835          
00836             if (this.offset_in_block[di] === 'x) begin
00837                `vmm_error(this.log, $psprintf("Memory \"%s\" unmapped in domain \"%s\" does not have a user-defined frontdoor",
00838                                               this.get_name(),
00839                                               this.domains[di]));
00840                return;
00841             end
00842          
00843             w = this.ral_access.Xget_physical_addressesX(this.offset_in_block[di],
00844                                                          burst.start_offset,
00845                                                          this.get_n_bytes(),
00846                                                          this.parent,
00847                                                          this.domains[di],
00848                                                          addr);
00849             n_bits = this.get_n_bits();
00850             // Cannot burst memory through a narrower datapath
00851             if (n_bits > w*8) begin
00852                `vmm_error(this.log, $psprintf("Cannot burst-write a %0d-bit memory through a narrower data path (%0d bytes)",
00853                                               n_bits, w));
00854                return;
00855             end
00856             // Translate the offset-based burst into address-based burst
00857             begin
00858                bit [`VMM_RAL_ADDR_WIDTH-1:0] start, incr, max;
00859 
00860                start = addr[0];
00861 
00862                w = this.ral_access.Xget_physical_addressesX(this.offset_in_block[di],
00863                                                             burst.start_offset + burst.incr_offset,
00864                                                             this.get_n_bytes(),
00865                                                             this.parent,
00866                                                             this.domains[di],
00867                                                             addr);
00868                incr = addr[0] - start;
00869 
00870                w = this.ral_access.Xget_physical_addressesX(this.offset_in_block[di],
00871                                                             burst.max_offset,
00872                                                             this.get_n_bytes(),
00873                                                             this.parent,
00874                                                             this.domains[di],
00875                                                             addr);
00876 
00877                max = addr[addr.size()-1];
00878 
00879                this.ral_access.burst_read(status, start, incr, max,
00880                                           burst.n_beats, value,
00881                                           burst.user_data, n_bits,
00882                                           this.parent.get_external_domain(this.domains[di]),
00883                                           data_id, scenario_id, stream_id);
00884             end
00885          end
00886 
00887          if (this.cover_on) begin
00888             bit [`VMM_RAL_ADDR_WIDTH-1:0] addr;
00889             for (addr = burst.start_offset;
00890                  addr <= burst.max_offset;
00891                  addr += burst.incr_offset) begin
00892                this.parent.XsampleX(this.offset_in_block[di] + addr, di);
00893             end
00894          end
00895       end
00896       
00897       vmm_ral::BACKDOOR: begin
00898          bit [`VMM_RAL_ADDR_WIDTH-1:0] addr;
00899          value = new [burst.n_beats];
00900          addr = burst.start_offset;
00901          foreach (value[i]) begin
00902             this.peek(status, addr, value[i],
00903                       data_id, scenario_id, stream_id);
00904             if (status != vmm_rw::IS_OK) return;
00905             addr += burst.incr_offset;
00906             if (addr > burst.max_offset) begin
00907                addr -= (burst.max_offset - burst.start_offset - 1);
00908             end
00909          end
00910       end
00911    endcase
00912 
00913    `vmm_callback(vmm_ral_mem_callbacks,
00914                  post_burst(this, vmm_rw::READ, burst, value,
00915                             path, domain, status));
00916 endtask: burst_read
00917 
00918 
00919 task vmm_ral_mem::poke(output vmm_rw::status_e              status,
00920                        input  bit [`VMM_RAL_ADDR_WIDTH-1:0] mem_addr,
00921                        input  bit [`VMM_RAL_DATA_WIDTH-1:0] value,
00922                        input  int                           data_id,
00923                        input  int                           scenario_id,
00924                        input  int                           stream_id);
00925    if (this.backdoor == null) begin
00926       `vmm_error(this.log, $psprintf("No backdoor access available in memory %s", this.get_fullname()));
00927       status = vmm_rw::ERROR;
00928       return;
00929    end
00930    this.backdoor.write(status, mem_addr, value, data_id, scenario_id, stream_id);
00931 
00932    `vmm_trace(this.log, $psprintf("Poked memory \"%s\"[%0d] with: 'h%h",
00933                                   this.get_fullname(), mem_addr, value));
00934 endtask: poke
00935 
00936 
00937 task vmm_ral_mem::peek(output vmm_rw::status_e              status,
00938                        input  bit [`VMM_RAL_ADDR_WIDTH-1:0] mem_addr,
00939                        output bit [`VMM_RAL_DATA_WIDTH-1:0] value,
00940                        input  int                           data_id,
00941                        input  int                           scenario_id,
00942                        input  int                           stream_id);
00943    if (this.backdoor == null) begin
00944       `vmm_error(this.log, $psprintf("No backdoor access available in memory %s", this.get_fullname()));
00945       status = vmm_rw::ERROR;
00946       return;
00947    end
00948    this.backdoor.read(status, mem_addr, value, data_id, scenario_id, stream_id);
00949 
00950    `vmm_trace(this.log, $psprintf("Peeked memory \"%s\"[%0d]: 'h%h",
00951                                   this.get_fullname(), mem_addr, value));
00952 endtask: peek
00953 
00954 
00955 task vmm_ral_mem::readmemh(string filename);
00956 endtask: readmemh
00957 
00958 
00959 task vmm_ral_mem::writememh(string filename);
00960 endtask: writememh
00961 
00962 
00963 function void vmm_ral_mem::set_frontdoor(vmm_ral_mem_frontdoor ftdr,
00964                                          string                domain);
00965    foreach(this.domains[i]) begin
00966       if (this.domains[i] == domain) begin
00967          this.frontdoor[i] = ftdr;
00968          return;
00969       end
00970    end
00971    `vmm_error(this.log, $psprintf("Domain \"%s\" not found in memory %s", domain, this.get_fullname()));
00972 endfunction: set_frontdoor
00973 
00974 
00975 function vmm_ral_mem_frontdoor vmm_ral_mem::get_frontdoor(string domain);
00976    foreach(this.domains[i]) begin
00977       if (this.domains[i] == domain) begin
00978          return this.frontdoor[i];
00979       end
00980    end
00981    `vmm_error(this.log, $psprintf("Domain \"%s\" not found in memory %s", domain, this.get_fullname()));
00982 endfunction: get_frontdoor
00983 
00984 
00985 function void vmm_ral_mem::set_backdoor(vmm_ral_mem_backdoor bkdr);
00986    this.backdoor = bkdr;
00987 endfunction: set_backdoor
00988 
00989 
00990 function vmm_ral_mem_backdoor vmm_ral_mem::get_backdoor();
00991    get_backdoor = this.backdoor;
00992 endfunction: get_backdoor
00993 
00994 
00995 function void vmm_ral_mem::prepend_callback(vmm_ral_mem_callbacks cb);
00996    foreach (this.callbacks[i]) begin
00997       if (this.callbacks[i] == cb) begin
00998          `vmm_warning(this.log, $psprintf("Callback has already been registered with memory %s", this.get_fullname()));
00999          return;
01000       end
01001    end
01002    
01003    // Prepend new callback
01004    this.callbacks.push_front(cb);
01005 endfunction: prepend_callback
01006 
01007 
01008 function void vmm_ral_mem::append_callback(vmm_ral_mem_callbacks cb);
01009    foreach (this.callbacks[i]) begin
01010       if (this.callbacks[i] == cb) begin
01011          `vmm_warning(this.log, $psprintf("Callback has already been registered with memory %s", this.get_fullname()));
01012          return;
01013       end
01014    end
01015    
01016    // Append new callback
01017    this.callbacks.push_back(cb);
01018 endfunction: append_callback
01019 
01020 
01021 function void vmm_ral_mem::unregister_callback(vmm_ral_mem_callbacks cb);
01022    foreach (this.callbacks[i]) begin
01023       if (this.callbacks[i] == cb) begin
01024          int j = i;
01025          // Unregister it
01026          this.callbacks.delete(j);
01027          return;
01028       end
01029    end
01030 
01031 `vmm_warning(this.log, $psprintf("Callback was not registered with memory %s", this.get_fullname()));
01032 endfunction: unregister_callback
01033 
01034 
01035 function int vmm_ral_mem::get_domain_index(string domain);
01036    // If the domain is "" and there is only one domain,
01037    // assume it is the one domain available to avoid
01038    // having to always have to specify domains
01039    if (domain == "" && this.domains.size() == 1) return 0;
01040 
01041    foreach (this.domains[i]) begin
01042       if (this.domains[i] == domain) return i;
01043    end
01044    `vmm_warning(this.log, $psprintf("Unknown domain name \"%s\" in memory %s.", domain, this.get_fullname()));
01045    return -1;
01046 endfunction: get_domain_index
01047 
01048 
01049 task vmm_ral_mem_frontdoor::write(output vmm_rw::status_e              status,
01050                                   input  bit [`VMM_RAL_ADDR_WIDTH-1:0] offset,
01051                                   input  bit [`VMM_RAL_DATA_WIDTH-1:0] data,
01052                                   input  int                           data_id,
01053                                   input  int                           scenario_id,
01054                                   input  int                           stream_id);
01055    `vmm_fatal(this.log, "vmm_ral_mem_frontdoor::write() method has not been overloaded");
01056 endtask: write
01057 
01058 
01059 task vmm_ral_mem_frontdoor::read(output vmm_rw::status_e              status,
01060                                  input  bit [`VMM_RAL_ADDR_WIDTH-1:0] offset,
01061                                  output bit [`VMM_RAL_DATA_WIDTH-1:0] data,
01062                                  input  int                           data_id,
01063                                  input  int                           scenario_id,
01064                                  input  int                           stream_id);
01065    `vmm_fatal(this.log, "vmm_ral_mem_frontdoor::read() method has not been overloaded");
01066 endtask: read

Intelligent Design Verification
Intelligent Design Verification
Project: VMM, Revision: 1.0.0
Copyright (c) 2008 Intelligent Design Verification.
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
A copy of the license is included here:
http://www.intelligentdv.com/licenses/fdl.txt
doxygen
Doxygen Version: 1.5.6
Sat Oct 18 11:38:21 2008
Find a documentation bug? Report bugs to: bugs.intelligentdv.com Project: DoxygenFilterSV