00001 // 00002 // ------------------------------------------------------------- 00003 // Copyright 2004-2008 Synopsys, Inc. 00004 // All Rights Reserved Worldwide 00005 // 00006 // Licensed under the Apache License, Version 2.0 (the 00007 // "License"); you may not use this file except in 00008 // compliance with the License. You may obtain a copy of 00009 // the License at 00010 // 00011 // http://www.apache.org/licenses/LICENSE-2.0 00012 // 00013 // Unless required by applicable law or agreed to in 00014 // writing, software distributed under the License is 00015 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 00016 // CONDITIONS OF ANY KIND, either express or implied. See 00017 // the License for the specific language governing 00018 // permissions and limitations under the License. 00019 // ------------------------------------------------------------- 00020 // 00021 00022 00023 class vmm_ral_block extends vmm_ral_block_or_sys; 00024 local vmm_ral_reg regs[$]; 00025 local vmm_ral_vreg vregs[$]; 00026 local vmm_ral_mem mems[$]; 00027 00028 extern function new(vmm_ral_sys parent, 00029 string name, 00030 string typename, 00031 int unsigned n_bytes, 00032 vmm_ral::endianness_e endian, 00033 bit [`VMM_RAL_ADDR_WIDTH-1:0] base_addr, 00034 string domain = "", 00035 bit cover_on = 1); 00036 00037 /*local*/ extern virtual function void Xlock_modelX(); 00038 /*local*/ extern function void register_reg(vmm_ral_reg register); 00039 /*local*/ extern function void register_vreg(vmm_ral_vreg register); 00040 /*local*/ extern function void register_mem(vmm_ral_mem memory); 00041 /*local*/ extern virtual function void Xregister_ral_accessX(vmm_ral_access access); 00042 00043 extern virtual function string psdisplay(string prefix = "", 00044 string domain = ""); 00045 00046 extern virtual function void get_fields(ref vmm_ral_field fields[], 00047 input string domain = ""); 00048 extern virtual function void get_virtual_fields(ref vmm_ral_vfield fields[], 00049 input string domain = ""); 00050 extern virtual function vmm_ral_field get_field_by_name(string name); 00051 extern virtual function vmm_ral_vfield get_virtual_field_by_name(string name); 00052 00053 extern virtual function void get_registers(ref vmm_ral_reg regs[], 00054 input string domain = ""); 00055 extern virtual function void get_virtual_registers(ref vmm_ral_vreg vregs[], 00056 input string domain = ""); 00057 extern virtual function vmm_ral_reg get_reg_by_name(string name); 00058 extern virtual function vmm_ral_vreg get_vreg_by_name(string name); 00059 extern virtual function vmm_ral_reg get_reg_by_offset(bit [`VMM_RAL_ADDR_WIDTH-1:0] offset, 00060 string domain = ""); 00061 00062 extern virtual function void get_memories(ref vmm_ral_mem mems[], 00063 input string domain = ""); 00064 extern virtual function vmm_ral_mem get_mem_by_name(string name); 00065 extern virtual function vmm_ral_mem get_mem_by_offset(bit [`VMM_RAL_ADDR_WIDTH-1:0] offset, 00066 string domain = ""); 00067 00068 extern virtual function void get_constraints(ref string names[]); 00069 00070 extern virtual function bit set_cover(bit is_on); 00071 00072 extern virtual function void reset(string domain = "", 00073 vmm_ral::reset_e kind = vmm_ral::HARD); 00074 extern virtual function bit needs_update(); 00075 00076 extern virtual task update(output vmm_rw::status_e status, 00077 input vmm_ral::path_e path = vmm_ral::DEFAULT); 00078 extern virtual task mirror(output vmm_rw::status_e status, 00079 input vmm_ral::check_e check = vmm_ral:: QUIET, 00080 input vmm_ral::path_e path = vmm_ral::DEFAULT); 00081 00082 extern virtual task readmemh(string filename); 00083 extern virtual task writememh(string filename); 00084 00085 //protect 00086 extern virtual /*local*/ function void XsampleX(bit [`VMM_RAL_ADDR_WIDTH-1:0] addr, 00087 int domain); 00088 extern protected virtual function void sample(bit [`VMM_RAL_ADDR_WIDTH-1:0] addr, 00089 int domain); 00090 //endprotect 00091 endclass: vmm_ral_block 00092 00093 00094 function vmm_ral_block::new(vmm_ral_sys parent, 00095 string name, 00096 string typename, 00097 int unsigned n_bytes, 00098 vmm_ral::endianness_e endian, 00099 bit [`VMM_RAL_ADDR_WIDTH-1:0] base_addr, 00100 string domain, 00101 bit cover_on); 00102 super.new(parent, "RAL Block", name, typename, 00103 n_bytes, endian, base_addr, domain, 00104 cover_on); 00105 endfunction: new 00106 00107 00108 function void vmm_ral_block::Xlock_modelX(); 00109 if (this.Xis_lockedX()) return; 00110 00111 super.Xlock_modelX(); 00112 foreach (this.regs[i]) begin 00113 this.regs[i].Xlock_modelX(); 00114 end 00115 foreach (this.mems[i]) begin 00116 this.mems[i].Xlock_modelX(); 00117 end 00118 endfunction: Xlock_modelX 00119 00120 00121 function void vmm_ral_block::register_reg(vmm_ral_reg register); 00122 if (this.Xis_lockedX()) begin 00123 `vmm_error(this.log, "Cannot add register to locked block model"); 00124 return; 00125 end 00126 00127 // Check if this register has already been registered with this block 00128 foreach (this.regs[i]) begin 00129 if (this.regs[i] == register) begin 00130 `vmm_error(this.log, $psprintf("Register \"%s\" has already been registered with block \"%s\".\n", 00131 register.get_name(), this.get_name())); 00132 return; 00133 end 00134 end 00135 this.regs.push_back(register); 00136 endfunction: register_reg 00137 00138 function void vmm_ral_block::register_vreg(vmm_ral_vreg register); 00139 if (this.Xis_lockedX()) begin 00140 `vmm_error(this.log, "Cannot add virtual register to locked block model"); 00141 return; 00142 end 00143 00144 // Check if this register has already been registered with this block 00145 foreach (this.vregs[i]) begin 00146 if (this.vregs[i] == register) begin 00147 `vmm_error(this.log, $psprintf("Virtual register \"%s\" has already been registered with block \"%s\".\n", 00148 register.get_name(), this.get_name())); 00149 return; 00150 end 00151 end 00152 this.vregs.push_back(register); 00153 endfunction: register_vreg 00154 00155 function void vmm_ral_block::register_mem(vmm_ral_mem memory); 00156 if (this.Xis_lockedX()) begin 00157 `vmm_error(this.log, "Cannot add memory to locked block model"); 00158 return; 00159 end 00160 00161 // Check if this memory has already been registered with this block 00162 foreach (this.mems[i]) begin 00163 if (this.mems[i] == memory) begin 00164 `vmm_error(this.log, $psprintf("Memory \"%s\" has already been registered with block \"%s\".\n", 00165 memory.get_name(), this.get_name())); 00166 return; 00167 end 00168 end 00169 this.mems.push_back(memory); 00170 endfunction: register_mem 00171 00172 00173 function void vmm_ral_block::Xregister_ral_accessX(vmm_ral_access access); 00174 // There can only be one RAL Access on a RAL model 00175 if (this.ral_access != null && this.ral_access != access) begin 00176 `vmm_fatal(this.log, $psprintf("Block %s is already used by another RAL access instance", this.get_fullname())); 00177 end 00178 this.ral_access = access; 00179 00180 // Register all sub-elements 00181 begin 00182 vmm_ral_reg regs[]; 00183 vmm_ral_mem mems[]; 00184 00185 this.get_registers(regs); 00186 foreach (regs[i]) begin 00187 regs[i].Xregister_ral_accessX(access); 00188 end 00189 00190 this.get_memories(mems); 00191 foreach (mems[i]) begin 00192 mems[i].Xregister_ral_accessX(access); 00193 end 00194 end 00195 endfunction: Xregister_ral_accessX 00196 00197 00198 function string vmm_ral_block::psdisplay(string prefix, 00199 string domain); 00200 string domains[]; 00201 vmm_ral_reg regs[]; 00202 vmm_ral_vreg vregs[]; 00203 vmm_ral_mem mems[]; 00204 bit single_domain; 00205 vmm_ral::endianness_e endian; 00206 00207 single_domain = 1; 00208 if (domain == "") begin 00209 this.get_domains(domains); 00210 if (domains.size() > 1) single_domain = 0; 00211 end 00212 if (single_domain) begin 00213 $sformat(psdisplay, "%sBlock %s", prefix, this.get_fullname()); 00214 if (domain != "") $sformat(psdisplay, "%s.%s", psdisplay, domain); 00215 endian = this.get_endian(domain); 00216 $sformat(psdisplay, "%s -- %0d bytes (%s)", psdisplay, 00217 this.get_n_bytes(domain), endian.name()); 00218 this.get_registers(regs, domain); 00219 foreach (regs[j]) begin 00220 $sformat(psdisplay, "%s\n%s", psdisplay, 00221 regs[j].psdisplay({prefix, " "}, domain)); 00222 end 00223 this.get_virtual_registers(vregs, domain); 00224 foreach (vregs[j]) begin 00225 $sformat(psdisplay, "%s\n%s", psdisplay, 00226 vregs[j].psdisplay({prefix, " "}, domain)); 00227 end 00228 this.get_memories(mems, domain); 00229 foreach (mems[j]) begin 00230 $sformat(psdisplay, "%s\n%s", psdisplay, 00231 mems[j].psdisplay({prefix, " "}, domain)); 00232 end 00233 end 00234 else begin 00235 $sformat(psdisplay, "%sBlock %s", prefix, this.get_fullname()); 00236 foreach (domains[i]) begin 00237 endian = this.get_endian(domains[i]); 00238 $sformat(psdisplay, "%s\n%s Domain \"%s\" -- %0d bytes (%s)", 00239 psdisplay, prefix, domains[i], 00240 this.get_n_bytes(domains[i]), endian.name()); 00241 this.get_registers(regs, domains[i]); 00242 foreach (regs[j]) begin 00243 $sformat(psdisplay, "%s\n%s", psdisplay, 00244 regs[j].psdisplay({prefix, " "}, 00245 domains[i])); 00246 end 00247 this.get_virtual_registers(vregs, domains[i]); 00248 foreach (vregs[j]) begin 00249 $sformat(psdisplay, "%s\n%s", psdisplay, 00250 vregs[j].psdisplay({prefix, " "}, 00251 domains[i])); 00252 end 00253 this.get_memories(mems, domains[i]); 00254 foreach (mems[j]) begin 00255 $sformat(psdisplay, "%s\n%s", psdisplay, 00256 mems[j].psdisplay({prefix, " "}, domains[i])); 00257 end 00258 end 00259 end 00260 endfunction: psdisplay 00261 00262 00263 function void vmm_ral_block::get_fields(ref vmm_ral_field fields[], 00264 input string domain); 00265 int n; 00266 vmm_ral_reg r[]; 00267 vmm_ral_field f[]; 00268 00269 fields = new [0]; 00270 this.get_registers(r, domain); 00271 foreach (r[i]) begin 00272 r[i].get_fields(f); 00273 n = fields.size(); 00274 fields = new [n + f.size()] (fields); 00275 00276 foreach (f[j]) begin 00277 fields[n++] = f[j]; 00278 end 00279 end 00280 endfunction: get_fields 00281 00282 function void vmm_ral_block::get_virtual_fields(ref vmm_ral_vfield fields[], 00283 input string domain); 00284 int n; 00285 vmm_ral_vreg r[]; 00286 vmm_ral_vfield f[]; 00287 00288 fields = new [0]; 00289 this.get_virtual_registers(r, domain); 00290 foreach (r[i]) begin 00291 r[i].get_fields(f); 00292 n = fields.size(); 00293 fields = new [n + f.size()] (fields); 00294 00295 foreach (f[j]) begin 00296 fields[n++] = f[j]; 00297 end 00298 end 00299 endfunction: get_virtual_fields 00300 00301 function vmm_ral_field vmm_ral_block::get_field_by_name(string name); 00302 // Search the registers to find the first field of the specified name 00303 foreach (this.regs[i]) begin 00304 vmm_ral_field fields[]; 00305 this.regs[i].get_fields(fields); 00306 foreach (fields[j]) begin 00307 if (fields[j].get_name() == name) begin 00308 return fields[j]; 00309 end 00310 end 00311 end 00312 `vmm_warning(this.log, $psprintf("Unable to locate field \"%s\" in block \"%s\".", 00313 name, this.get_fullname())); 00314 get_field_by_name = null; 00315 endfunction: get_field_by_name 00316 00317 function vmm_ral_vfield vmm_ral_block::get_virtual_field_by_name(string name); 00318 // Search the registers to find the first field of the specified name 00319 foreach (this.vregs[i]) begin 00320 vmm_ral_vfield fields[]; 00321 this.vregs[i].get_fields(fields); 00322 foreach (fields[j]) begin 00323 if (fields[j].get_name() == name) begin 00324 return fields[j]; 00325 end 00326 end 00327 end 00328 `vmm_warning(this.log, $psprintf("Unable to locate virtual field \"%s\" in block \"%s\".", 00329 name, this.get_fullname())); 00330 get_virtual_field_by_name = null; 00331 endfunction: get_virtual_field_by_name 00332 00333 00334 function void vmm_ral_block::get_registers(ref vmm_ral_reg regs[], 00335 input string domain); 00336 if (domain == "") begin 00337 regs = new [this.regs.size()]; 00338 foreach(this.regs[i]) begin 00339 regs[i] = this.regs[i]; 00340 end 00341 end 00342 else begin 00343 int n = 0; 00344 regs = new [this.regs.size()]; 00345 foreach(this.regs[i]) begin 00346 // Is the register in the specified domain? 00347 string domains[]; 00348 this.regs[i].get_domains(domains); 00349 foreach(domains[j]) begin 00350 if (domains[j] == domain) begin 00351 regs[n++] = this.regs[i]; 00352 break; 00353 end 00354 end 00355 end 00356 regs = new [n] (regs); 00357 end 00358 endfunction: get_registers 00359 00360 function void vmm_ral_block::get_virtual_registers(ref vmm_ral_vreg vregs[], 00361 input string domain); 00362 if (domain == "") begin 00363 vregs = new [this.vregs.size()]; 00364 foreach(this.vregs[i]) begin 00365 vregs[i] = this.vregs[i]; 00366 end 00367 end 00368 else begin 00369 int n = 0; 00370 vregs = new [this.vregs.size()]; 00371 foreach(this.vregs[i]) begin 00372 // Is the register in the specified domain? 00373 string domains[]; 00374 this.vregs[i].get_domains(domains); 00375 foreach(domains[j]) begin 00376 if (domains[j] == domain) begin 00377 vregs[n++] = this.vregs[i]; 00378 break; 00379 end 00380 end 00381 end 00382 vregs = new [n] (vregs); 00383 end 00384 endfunction: get_virtual_registers 00385 00386 function vmm_ral_reg vmm_ral_block::get_reg_by_name(string name); 00387 foreach (this.regs[i]) begin 00388 if (this.regs[i].get_name() == name) begin 00389 return this.regs[i]; 00390 end 00391 end 00392 `vmm_warning(this.log, $psprintf("Unable to locate register \"%s\" in block \"%s\".", 00393 name, this.get_fullname())); 00394 get_reg_by_name = null; 00395 endfunction: get_reg_by_name 00396 00397 function vmm_ral_vreg vmm_ral_block::get_vreg_by_name(string name); 00398 foreach (this.vregs[i]) begin 00399 if (this.vregs[i].get_name() == name) begin 00400 return this.vregs[i]; 00401 end 00402 end 00403 `vmm_warning(this.log, $psprintf("Unable to locate virtual register \"%s\" in block \"%s\".", 00404 name, this.get_fullname())); 00405 get_vreg_by_name = null; 00406 endfunction: get_vreg_by_name 00407 00408 function vmm_ral_reg vmm_ral_block::get_reg_by_offset(bit [`VMM_RAL_ADDR_WIDTH-1:0] offset, 00409 string domain); 00410 foreach (this.regs[i]) begin 00411 if (this.regs[i].get_offset_in_block(domain) == offset) begin 00412 return this.regs[i]; 00413 end 00414 end 00415 `vmm_warning(this.log, $psprintf("Unable to locate register at offset 0x%h %0sin block \"%s\".", 00416 offset, ((domain == "") ? "" : $psprintf("in domain \"%s\" ", 00417 domain)), 00418 this.get_fullname())); 00419 get_reg_by_offset = null; 00420 endfunction: get_reg_by_offset 00421 00422 00423 function void vmm_ral_block::get_memories(ref vmm_ral_mem mems[], 00424 input string domain); 00425 if (domain == "") begin 00426 mems = new [this.mems.size()]; 00427 foreach(this.mems[i]) begin 00428 mems[i] = this.mems[i]; 00429 end 00430 end 00431 else begin 00432 int n = 0; 00433 mems = new [this.mems.size()]; 00434 foreach(this.mems[i]) begin 00435 // Is the memory in the specified domain? 00436 string domains[]; 00437 this.mems[i].get_domains(domains); 00438 foreach(domains[j]) begin 00439 if (domains[j] == domain) begin 00440 mems[n++] = this.mems[i]; 00441 break; 00442 end 00443 end 00444 end 00445 mems = new [n] (mems); 00446 end 00447 endfunction: get_memories 00448 00449 00450 function vmm_ral_mem vmm_ral_block::get_mem_by_name(string name); 00451 foreach (this.mems[i]) begin 00452 if (this.mems[i].get_name() == name) begin 00453 return this.mems[i]; 00454 end 00455 end 00456 `vmm_warning(this.log, $psprintf("Unable to locate memory \"%s\" in block \"%s\".", 00457 name, this.get_fullname())); 00458 get_mem_by_name = null; 00459 endfunction: get_mem_by_name 00460 00461 00462 function vmm_ral_mem vmm_ral_block::get_mem_by_offset(bit [`VMM_RAL_ADDR_WIDTH-1:0] offset, 00463 string domain); 00464 //get_mem_by_offset = this.mems.first() with index: (this.mems[index].offset_in_block == offset); 00465 endfunction: get_mem_by_offset 00466 00467 00468 function void vmm_ral_block::get_constraints(ref string names[]); 00469 endfunction: get_constraints 00470 00471 00472 function bit vmm_ral_block::set_cover(bit is_on); 00473 set_cover = super.set_cover(is_on); 00474 00475 if (is_on && !super.is_cover_on()) return set_cover; 00476 00477 foreach (this.regs[i]) begin 00478 this.regs[i].set_cover(is_on); 00479 end 00480 foreach (this.mems[i]) begin 00481 this.mems[i].set_cover(is_on); 00482 end 00483 endfunction: set_cover 00484 00485 00486 function void vmm_ral_block::reset(string domain, 00487 vmm_ral::reset_e kind); 00488 vmm_ral_reg regs[]; 00489 vmm_ral_mem mems[]; 00490 00491 this.get_registers(regs, domain); 00492 foreach (regs[i]) begin 00493 regs[i].reset(kind); 00494 end 00495 00496 this.get_memories(mems, domain); 00497 foreach (mems[i]) begin 00498 vmm_ral_vreg vregs[]; 00499 mems[i].get_virtual_registers(vregs); 00500 foreach (vregs[j]) begin 00501 vregs[j].reset(kind); 00502 end 00503 end 00504 endfunction: reset 00505 00506 00507 function bit vmm_ral_block::needs_update(); 00508 needs_update = 0; 00509 foreach (this.regs[i]) begin 00510 if (this.regs[i].needs_update()) begin 00511 return 1; 00512 end 00513 end 00514 endfunction: needs_update 00515 00516 00517 task vmm_ral_block::update(output vmm_rw::status_e status, 00518 input vmm_ral::path_e path); 00519 string domains[]; 00520 bit updated; 00521 00522 status = vmm_rw::IS_OK; 00523 foreach (this.regs[i]) begin 00524 if (!this.regs[i].needs_update()) continue; 00525 00526 if (path == vmm_ral::BACKDOOR) begin 00527 this.regs[i].update(status, path); 00528 if (status != vmm_rw::IS_OK) return; 00529 continue; 00530 end 00531 00532 // Find the first writeable domain to 00533 // perform the update through 00534 this.regs[i].get_domains(domains); 00535 updated = 0; 00536 foreach (domains[j]) begin 00537 if (this.regs[i].get_rights(domains[j]) != vmm_ral::RO) begin 00538 this.regs[i].update(status, path, domains[j]); 00539 if (status == vmm_rw::IS_OK) begin 00540 updated = 1; 00541 break; 00542 end 00543 end 00544 end 00545 if (!updated) begin 00546 `vmm_error(this.log, $psprintf("Register \"%s\" could not be updated", 00547 regs[i].get_fullname())); 00548 if (status == vmm_rw::IS_OK) status = vmm_rw::ERROR; 00549 return; 00550 end 00551 end 00552 endtask: update 00553 00554 00555 task vmm_ral_block::mirror(output vmm_rw::status_e status, 00556 input vmm_ral::check_e check, 00557 input vmm_ral::path_e path); 00558 string domains[]; 00559 bit mirrored; 00560 00561 status = vmm_rw::IS_OK; 00562 foreach (this.regs[i]) begin 00563 00564 if (path == vmm_ral::BACKDOOR) begin 00565 this.regs[i].mirror(status, check, path); 00566 if (status != vmm_rw::IS_OK) return; 00567 continue; 00568 end 00569 00570 // Find the first readable domain to 00571 // perform the update through 00572 this.regs[i].get_domains(domains); 00573 mirrored = 0; 00574 foreach (domains[j]) begin 00575 if (this.regs[i].get_rights(domains[j]) != vmm_ral::WO) begin 00576 this.regs[i].mirror(status, check, path, domains[0]); 00577 if (status == vmm_rw::IS_OK) begin 00578 mirrored = 1; 00579 break; 00580 end 00581 end 00582 end 00583 if (!mirrored) begin 00584 `vmm_error(this.log, $psprintf("Register \"%s\" could not be mirrored", 00585 regs[i].get_fullname())); 00586 if (status == vmm_rw::IS_OK) status = vmm_rw::ERROR; 00587 return; 00588 end 00589 end 00590 endtask: mirror 00591 00592 00593 task vmm_ral_block::readmemh(string filename); 00594 endtask: readmemh 00595 00596 00597 task vmm_ral_block::writememh(string filename); 00598 endtask: writememh 00599 00600 00601 function void vmm_ral_block::XsampleX(bit [`VMM_RAL_ADDR_WIDTH-1:0] addr, 00602 int domain); 00603 this.sample(addr, domain); 00604 endfunction 00605 00606 00607 function void vmm_ral_block::sample(bit [`VMM_RAL_ADDR_WIDTH-1:0] addr, 00608 int domain); 00609 // Nothing to do in this base class 00610 endfunction
![]() 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 Version: 1.5.6 Sat Oct 18 11:38:21 2008 |