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_tests;
00024
00025 extern `VMM_STATIC_M task hw_reset(vmm_ral_block blk,
00026 string domain,
00027 vmm_log log);
00028
00029 extern `VMM_STATIC_M task bit_bash(vmm_ral_block blk,
00030 string domain,
00031 vmm_log log);
00032
00033 extern `VMM_STATIC_M task mem_walk(vmm_ral_block blk,
00034 string domain,
00035 vmm_log log);
00036
00037 extern `VMM_STATIC_M task reg_access(vmm_ral_block blk,
00038 vmm_log log);
00039
00040 extern `VMM_STATIC_M task mem_access(vmm_ral_block blk,
00041 vmm_log log);
00042
00043 extern `VMM_STATIC_M task shared_access(vmm_ral_block blk,
00044 vmm_log log);
00045
00046
00047 extern local `VMM_STATIC_M task bash_kth_bit(vmm_log log,
00048 vmm_ral_reg regs,
00049 int k,
00050 vmm_ral::access_e mode,
00051 string domain,
00052 bit [`VMM_RAL_DATA_WIDTH-1:0] wo_mask);
00053 endclass: vmm_ral_tests
00054
00055
00056 task vmm_ral_tests::hw_reset(vmm_ral_block blk,
00057 string domain,
00058 vmm_log log);
00059 vmm_ral_reg regs[];
00060
00061 // Iterate over all registers, checking the reset values
00062 blk.get_registers(regs, domain);
00063 foreach (regs[i]) begin
00064 string domains[];
00065
00066 // Registers with some attributes are not to be tested
00067 if (regs[i].get_attribute("NO_RAL_TESTS") != "" ||
00068 regs[i].get_attribute("NO_HW_RESET_TEST") != "") continue;
00069
00070 // Registers may be accessible from multiple physical interfaces (domains)
00071 regs[i].get_domains(domains);
00072
00073 // Verify the initial (reset) value in each domain
00074 foreach (domains[j]) begin
00075 vmm_rw::status_e status;
00076 bit [`VMM_RAL_DATA_WIDTH-1:0] v;
00077
00078 `vmm_note(log, $psprintf("Verifying reset value of register %s in domain \"%s\"...",
00079 regs[i].get_fullname(), domains[j]));
00080
00081 regs[i].mirror(status, vmm_ral::VERB, vmm_ral::BFM, domains[j]);
00082 if (status != vmm_rw::IS_OK) begin
00083 `vmm_error(log, $psprintf("Status was %s when reading reset value of register \"%s\" through domain \"%s\".",
00084 status.name(), regs[i].get_fullname(), domains[j]));
00085 end
00086 end
00087 end
00088 endtask: hw_reset
00089
00090
00091
00092 task vmm_ral_tests::bit_bash(vmm_ral_block blk,
00093 string domain,
00094 vmm_log log);
00095 vmm_ral_reg regs[];
00096
00097 // Iterate over all registers, trying to modify read-only bits
00098 // and making sure read-write bits can be set and cleared
00099 blk.get_registers(regs, domain);
00100 foreach (regs[i]) begin
00101 vmm_ral_field fields[];
00102 vmm_ral::access_e mode[`VMM_RAL_DATA_WIDTH];
00103 string domains[];
00104 bit [`VMM_RAL_DATA_WIDTH-1:0] wo_mask;
00105 bit [`VMM_RAL_DATA_WIDTH-1:0] reset_val;
00106 int n_bits;
00107
00108 // Registers with some attributes are not to be tested
00109 if (regs[i].get_attribute("NO_RAL_TESTS") != "" ||
00110 regs[i].get_attribute("NO_BIT_BASH_TEST") != "") continue;
00111
00112 n_bits = regs[i].get_n_bytes() * 8;
00113
00114 // Let's see what kind of bits we have...
00115 regs[i].get_fields(fields);
00116
00117 // Registers may be accessible from multiple physical interfaces (domains)
00118 regs[i].get_domains(domains);
00119
00120 // Bash the bits in the register via each domain
00121 foreach (domains[j]) begin
00122 vmm_rw::status_e status;
00123 bit [`VMM_RAL_DATA_WIDTH-1:0] val, exp, v, other;
00124 int next_lsb;
00125
00126 next_lsb = 0;
00127 wo_mask = '1;
00128 foreach (fields[k]) begin
00129 int lsb, w;
00130
00131 lsb = fields[k].get_lsb_pos_in_register();
00132 w = fields[k].get_n_bits();
00133
00134 // Any unused bits on the right side of the LSB?
00135 while (next_lsb < lsb) begin
00136 mode[next_lsb++] = vmm_ral::RO;
00137 end
00138
00139 repeat (w) begin
00140 mode[next_lsb] = fields[k].get_access(domains[j]);
00141 if (mode[next_lsb] == vmm_ral::WO) wo_mask[next_lsb] = 1'b0;
00142 next_lsb++;
00143 end
00144 end
00145 // Any unused bits on the left side of the MSB?
00146 while (next_lsb < 64) begin
00147 mode[next_lsb++] = vmm_ral::RO;
00148 end
00149
00150 `vmm_note(log, $psprintf("Verifying bits in register %s in domain \"%s\"...",
00151 regs[i].get_fullname(), domains[j]));
00152
00153 // The mirror still contains initial value
00154 reset_val = regs[i].get();
00155
00156 // But the mirrored value of any WO bits will read back
00157 // as all zeroes via the frontdoor...
00158 reset_val &= wo_mask;
00159
00160 regs[i].read(status, val, vmm_ral::BFM, domains[j]);
00161 if (status != vmm_rw::IS_OK) begin
00162 `vmm_error(log, $psprintf("Status was %s when reading register \"%s\" through domain \"%s\".",
00163 status, regs[i].get_fullname(), domains[j]));
00164 end
00165
00166 if (val !== reset_val) begin
00167 `vmm_error(log, $psprintf("Initial value of register \"%s\" ('h%h) not %s ('h%h)",
00168 regs[i].get_fullname(), val,
00169 (j == 0) ? "reset value" : "as expected",
00170 reset_val));
00171 end
00172
00173 // Bash the kth bit
00174 other = 0;
00175 for (int k = 0; k < n_bits; k++) begin
00176
00177 // Cannot test unpredictable bit behavior
00178 if (mode[k] >= vmm_ral::DC) begin
00179 other[k] = 1;
00180 continue;
00181 end
00182
00183 bash_kth_bit(log, regs[i], k, mode[k], domains[j], wo_mask);
00184 end
00185
00186 // Write the complement of the reset value
00187 // Except in the "OTHER" and "USERx" bits
00188 val = reset_val ^ ~other;
00189
00190 regs[i].write(status, val, vmm_ral::BFM, domains[j]);
00191 if (status != vmm_rw::IS_OK) begin
00192 `vmm_error(log, $psprintf("Status was %s when writing to register \"%s\" through domain \"%s\".",
00193 status, regs[i].get_fullname(), domains[j]));
00194 end
00195
00196 exp = regs[i].get() & wo_mask;
00197 regs[i].read(status, v, vmm_ral::BFM, domains[j]);
00198 if (status != vmm_rw::IS_OK) begin
00199 `vmm_error(log, $psprintf("Status was %s when reading register \"%s\" through domain \"%s\".",
00200 status, regs[i].get_fullname(), domains[j]));
00201 end
00202
00203 if (v !== exp) begin
00204 `vmm_error(log, $psprintf("Writing 'h%h to register \"%s\" with initial value 'h%h yielded 'h%h instead of 'h%h",
00205 val, regs[i].get_fullname(), reset_val, v, exp));
00206 end
00207 end
00208 end
00209 endtask: bit_bash
00210
00211
00212 task vmm_ral_tests::bash_kth_bit(vmm_log log,
00213 vmm_ral_reg regs,
00214 int k,
00215 vmm_ral::access_e mode,
00216 string domain,
00217 bit [`VMM_RAL_DATA_WIDTH-1:0] wo_mask);
00218 vmm_rw::status_e status;
00219 bit [`VMM_RAL_DATA_WIDTH-1:0] val, exp, v;
00220 bit bit_val;
00221
00222 `vmm_note(log, $psprintf("...Bashing %s bit #%0d", mode.name(), k));
00223
00224 repeat (2) begin
00225 val = regs.get();
00226 v = val;
00227 exp = val;
00228 val[k] = ~val[k];
00229 bit_val = val[k];
00230
00231 regs.write(status, val, vmm_ral::BFM, domain);
00232 if (status != vmm_rw::IS_OK) begin
00233 `vmm_error(log, $psprintf("Status was %s when writing to register \"%s\" through domain \"%s\".",
00234 status, regs.get_fullname(), domain));
00235 end
00236
00237 exp = regs.get() & wo_mask;
00238 regs.read(status, val, vmm_ral::BFM, domain);
00239 if (status != vmm_rw::IS_OK) begin
00240 `vmm_error(log, $psprintf("Status was %s when reading register \"%s\" through domain \"%s\".",
00241 status, regs.get_fullname(), domain));
00242 end
00243
00244 if (val !== exp) begin
00245 `vmm_error(log, $psprintf("Writing a %b in bit #%0d of register \"%s\" with initial value 'h%h yielded 'h%h instead of 'h%h",
00246 bit_val, k, regs.get_fullname(), v, val, exp));
00247 end
00248 end
00249 endtask: bash_kth_bit
00250
00251
00252 task vmm_ral_tests::mem_walk(vmm_ral_block blk,
00253 string domain,
00254 vmm_log log);
00255 vmm_ral_mem mems[];
00256
00257 // Walk over all RW memories
00258 blk.get_memories(mems, domain);
00259 foreach (mems[i]) begin
00260 vmm_ral::access_e mode;
00261 string domains[];
00262 int n_bits;
00263
00264 // Memories with some attributes are not to be tested
00265 if (mems[i].get_attribute("NO_RAL_TESTS") != "" ||
00266 mems[i].get_attribute("NO_MEM_WALK_TEST") != "") continue;
00267
00268 n_bits = mems[i].get_n_bits();
00269
00270 // Memories may be accessible from multiple physical interfaces (domains)
00271 mems[i].get_domains(domains);
00272
00273 // Walk the memory via each domain
00274 foreach (domains[j]) begin
00275 vmm_rw::status_e status;
00276 bit [`VMM_RAL_DATA_WIDTH-1:0] val, exp, v;
00277
00278 // Only deal with RW memories
00279 if (mems[i].get_access(domains[j]) != vmm_ral::RW) continue;
00280
00281 `vmm_note(log, $psprintf("Walking memory %s in domain \"%s\"...",
00282 mems[i].get_fullname(), domains[j]));
00283
00284 // The walking process is, for address k:
00285 // - Write ~k
00286 // - Read k-1 and expect ~(k-1) if k > 0
00287 // - Write k-1 at k-1
00288 // - Read k and expect ~k if k == last address
00289 for (int k = 0; k < mems[i].get_size(); k++) begin
00290 mems[i].write(status, k, ~k, vmm_ral::BFM, domains[j]);
00291 if (status != vmm_rw::IS_OK) begin
00292 `vmm_error(log, $psprintf("Status was %s when writing \"%s[%0d]\" through domain \"%s\".",
00293 status.name(), mems[i].get_fullname(), k, domains[j]));
00294 end
00295
00296 if (k > 0) begin
00297 mems[i].read(status, k-1, val, vmm_ral::BFM, domains[j]);
00298 if (status != vmm_rw::IS_OK) begin
00299 `vmm_error(log, $psprintf("Status was %s when reading \"%s[%0d]\" through domain \"%s\".",
00300 status.name(), mems[i].get_fullname(), k, domains[j]));
00301 end
00302 else begin
00303 exp = ~(k-1) & ((1'b1<<n_bits)-1);
00304 if (val !== exp) begin
00305 `vmm_error(log, $psprintf("\"%s[%0d-1]\" read back as 'h%h instead of 'h%h.",
00306 mems[i].get_fullname(), k, val, exp));
00307
00308 end
00309 end
00310
00311 mems[i].write(status, k-1, k-1, vmm_ral::BFM, domains[j]);
00312 if (status != vmm_rw::IS_OK) begin
00313 `vmm_error(log, $psprintf("Status was %s when writing \"%s[%0d-1]\" through domain \"%s\".",
00314 status.name(), mems[i].get_fullname(), k, domains[j]));
00315 end
00316 end
00317
00318 if (k == mems[i].get_size() - 1) begin
00319 mems[i].read(status, k, val, vmm_ral::BFM, domains[j]);
00320 if (status != vmm_rw::IS_OK) begin
00321 `vmm_error(log, $psprintf("Status was %s when reading \"%s[%0d]\" through domain \"%s\".",
00322 status.name(), mems[i].get_fullname(), k, domains[j]));
00323 end
00324 else begin
00325 exp = ~(k) & ((1'b1<<n_bits)-1);
00326 if (val !== exp) begin
00327 `vmm_error(log, $psprintf("\"%s[%0d]\" read back as 'h%h instead of 'h%h.",
00328 mems[i].get_fullname(), k, val, exp));
00329
00330 end
00331 end
00332 end
00333 end
00334 end
00335 end
00336 endtask: mem_walk
00337
00338
00339 task vmm_ral_tests::reg_access(vmm_ral_block blk,
00340 vmm_log log);
00341 vmm_ral_reg regs[];
00342 bit skip_reg = 0;
00343
00344 // Iterate over all registers, checking accesses
00345 blk.get_registers(regs);
00346 foreach (regs[i]) begin
00347 string domains[];
00348
00349 // Registers with some attributes are not to be tested
00350 if (regs[i].get_attribute("NO_RAL_TESTS") != "" ||
00351 regs[i].get_attribute("NO_REG_ACCESS_TEST") != "") continue;
00352
00353 // Can only deal with registers with backdoor access
00354 if (regs[i].get_backdoor() == null) begin
00355 `vmm_warning(log, $psprintf("Register \"%s\" does not have a backdoor mechanism available",
00356 regs[i].get_fullname()));
00357 continue;
00358 end
00359
00360 // Registers may be accessible from multiple physical interfaces (domains)
00361 regs[i].get_domains(domains);
00362
00363 // Cannot test access if register contains RO or OTHER fields
00364 begin
00365 vmm_ral_field fields[];
00366 regs[i].get_fields(fields);
00367 foreach (fields[j]) begin
00368 foreach (domains[k]) begin
00369 if (fields[j].get_access(domains[k]) == vmm_ral::RO) begin
00370 `vmm_warning(log, $psprintf("Register \"%s\" has RO bits",
00371 regs[i].get_fullname()));
00372 skip_reg = 1; break;
00373 end
00374 if (fields[j].get_access(domains[k]) >= vmm_ral::OTHER) begin
00375 `vmm_warning(log, $psprintf("Register \"%s\" has OTHER or USER bits",
00376 regs[i].get_fullname()));
00377 skip_reg = 1; break;
00378 end
00379 end
00380 if (skip_reg == 1) break;
00381 end
00382 if (skip_reg == 1) begin
00383 skip_reg = 0;
00384 continue;
00385 end
00386 end
00387
00388 // Access each register:
00389 // - Write complement of reset value via front door
00390 // - Read value via backdoor and compare against mirror
00391 // - Write reset value via backdoor
00392 // - Read via front door and compare against mirror
00393 foreach (domains[j]) begin
00394 vmm_rw::status_e status;
00395 bit [`VMM_RAL_DATA_WIDTH-1:0] v, exp;
00396
00397 `vmm_note(log, $psprintf("Verifying access of register %s in domain \"%s\"...",
00398 regs[i].get_fullname(), domains[j]));
00399
00400 v = regs[i].get();
00401
00402 regs[i].write(status, ~v, vmm_ral::BFM, domains[j]);
00403 if (status != vmm_rw::IS_OK) begin
00404 `vmm_error(log, $psprintf("Status was %s when writing \"%s\" through domain \"%s\".",
00405 status.name(), regs[i].get_fullname(), domains[j]));
00406 end
00407
00408 regs[i].mirror(status, vmm_ral::VERB, vmm_ral::BACKDOOR);
00409 if (status != vmm_rw::IS_OK) begin
00410 `vmm_error(log, $psprintf("Status was %s when reading reset value of register \"%s\" through backdoor.",
00411 status.name(), regs[i].get_fullname()));
00412 end
00413
00414 regs[i].write(status, v, vmm_ral::BACKDOOR, domains[j]);
00415 if (status != vmm_rw::IS_OK) begin
00416 `vmm_error(log, $psprintf("Status was %s when writing \"%s\" through backdoor.",
00417 status.name(), regs[i].get_fullname()));
00418 end
00419
00420 regs[i].mirror(status, vmm_ral::VERB, vmm_ral::BFM, domains[j]);
00421 if (status != vmm_rw::IS_OK) begin
00422 `vmm_error(log, $psprintf("Status was %s when reading reset value of register \"%s\" through domain \"%s\".",
00423 status.name(), regs[i].get_fullname(), domains[j]));
00424 end
00425 end
00426 end
00427 endtask: reg_access
00428
00429
00430 task vmm_ral_tests::mem_access(vmm_ral_block blk,
00431 vmm_log log);
00432 vmm_ral_mem mems[];
00433
00434 // Access each location in all memories
00435 blk.get_memories(mems);
00436 foreach (mems[i]) begin
00437 vmm_ral::access_e mode;
00438 string domains[];
00439 int n_bits;
00440
00441 // Memories with some attributes are not to be tested
00442 if (mems[i].get_attribute("NO_RAL_TESTS") != "" ||
00443 mems[i].get_attribute("NO_MEM_ACCESS_TEST") != "") continue;
00444
00445 // Can only deal with memories with backdoor access
00446 if (mems[i].get_backdoor() == null) begin
00447 `vmm_warning(log, $psprintf("Memory \"%s\" does not have a backdoor mechanism available",
00448 mems[i].get_fullname()));
00449 continue;
00450 end
00451
00452 n_bits = mems[i].get_n_bits();
00453
00454 // Memories may be accessible from multiple physical interfaces (domains)
00455 mems[i].get_domains(domains);
00456
00457 // Walk the memory via each domain
00458 foreach (domains[j]) begin
00459 vmm_rw::status_e status;
00460 bit [`VMM_RAL_DATA_WIDTH-1:0] val, exp, v;
00461
00462 `vmm_note(log, $psprintf("Accessing memory %s in domain \"%s\"...\n",
00463 mems[i].get_fullname(), domains[j]));
00464
00465 mode = mems[i].get_access(domains[j]);
00466
00467 // The access process is, for address k:
00468 // - Write random value via front door
00469 // - Read via backdoor and expect same random value if RW
00470 // - Write complement of random value via back door
00471 // - Read via front door and expect inverted random value
00472 for (int k = 0; k < mems[i].get_size(); k++) begin
00473 val = $random & ((1'b1<<n_bits)-1);
00474 if (mode == vmm_ral::RO) begin
00475 mems[i].peek(status, k, exp);
00476 if (status != vmm_rw::IS_OK) begin
00477 `vmm_error(log, $psprintf("Status was %s when reading \"%s[%0d]\" through backdoor.",
00478 status.name(), mems[i].get_fullname(), k));
00479 end
00480 end
00481 else exp = val;
00482
00483 mems[i].write(status, k, val, vmm_ral::BFM, domains[j]);
00484 if (status != vmm_rw::IS_OK) begin
00485 `vmm_error(log, $psprintf("Status was %s when writing \"%s[%0d]\" through domain \"%s\".",
00486 status.name(), mems[i].get_fullname(), k, domains[j]));
00487 end
00488
00489 val = 'x;
00490 mems[i].peek(status, k, val);
00491 if (status != vmm_rw::IS_OK) begin
00492 `vmm_error(log, $psprintf("Status was %s when reading \"%s[%0d]\" through backdoor.",
00493 status.name(), mems[i].get_fullname(), k));
00494 end
00495 else begin
00496 if (val !== exp) begin
00497 `vmm_error(log, $psprintf("Backdoor \"%s[%0d]\" read back as 'h%h instead of 'h%h.",
00498 mems[i].get_fullname(), k, val, exp));
00499 end
00500 end
00501
00502 exp = ~exp & ((1'b1<<n_bits)-1);
00503 mems[i].poke(status, k, exp);
00504 if (status != vmm_rw::IS_OK) begin
00505 `vmm_error(log, $psprintf("Status was %s when writing \"%s[%0d-1]\" through backdoor.",
00506 status.name(), mems[i].get_fullname(), k));
00507 end
00508
00509 mems[i].read(status, k, val, vmm_ral::BFM, domains[j]);
00510 if (status != vmm_rw::IS_OK) begin
00511 `vmm_error(log, $psprintf("Status was %s when reading \"%s[%0d]\" through domain \"%s\".",
00512 status.name(), mems[i].get_fullname(), k, domains[j]));
00513 end
00514 else begin
00515 if (mode == vmm_ral::WO) begin
00516 if (val !== '0) begin
00517 `vmm_error(log, $psprintf("Front door \"%s[%0d]\" read back as 'h%h instead of 'h%h.",
00518 mems[i].get_fullname(), k, val, 0));
00519 end
00520 end
00521 else begin
00522 if (val !== exp) begin
00523 `vmm_error(log, $psprintf("Front door \"%s[%0d]\" read back as 'h%h instead of 'h%h.",
00524 mems[i].get_fullname(), k, val, exp));
00525 end
00526 end
00527 end
00528 end
00529 end
00530 end
00531 endtask: mem_access
00532
00533
00534 task vmm_ral_tests::shared_access(vmm_ral_block blk,
00535 vmm_log log);
00536 vmm_ral_reg regs[];
00537 vmm_ral_mem mems[];
00538
00539 // Iterate over all registers, looking for shared registers
00540 blk.get_registers(regs);
00541 foreach (regs[i]) begin
00542 string domains[];
00543 vmm_ral_field fields[];
00544 bit [`VMM_RAL_DATA_WIDTH-1:0] other_mask;
00545 bit [`VMM_RAL_DATA_WIDTH-1:0] wo_mask[];
00546
00547 // Registers with some attributes are not to be tested
00548 if (regs[i].get_attribute("NO_RAL_TESTS") != "" ||
00549 regs[i].get_attribute("NO_SHARED_ACCESS_TEST") != "") continue;
00550
00551 // Only look at shared registers
00552 if (regs[i].get_n_domains() < 2) continue;
00553 regs[i].get_domains(domains);
00554
00555 // Let's see what kind of bits we have...
00556 regs[i].get_fields(fields);
00557
00558 // Identify unpredictable bits and the ones we shouldn't change
00559 other_mask = 0;
00560 foreach (fields[k]) begin
00561 int lsb, w;
00562
00563 lsb = fields[k].get_lsb_pos_in_register();
00564 w = fields[k].get_n_bits();
00565
00566 if (fields[k].get_access(domains[0]) >= vmm_ral::OTHER) begin
00567 repeat (w) begin
00568 other_mask[lsb++] = 1'b1;
00569 end
00570 end
00571 end
00572
00573 // WO bits will always readback as 0's but the mirror
00574 // with return what is supposed to have been written
00575 // so we cannot use the mirror-check function
00576 wo_mask = new [domains.size()];
00577 foreach (domains[j]) begin
00578 bit [`VMM_RAL_DATA_WIDTH-1:0] wo;
00579 wo = 0;
00580 foreach (fields[k]) begin
00581 int lsb, w;
00582
00583 lsb = fields[k].get_lsb_pos_in_register();
00584 w = fields[k].get_n_bits();
00585
00586 if (fields[k].get_access(domains[j]) == vmm_ral::WO) begin
00587 repeat (w) begin
00588 wo[lsb++] = 1'b1;
00589 end
00590 end
00591 end
00592 wo_mask[j] = wo;
00593 end
00594
00595 // Try to write through each domain
00596 foreach (domains[j]) begin
00597 vmm_rw::status_e status;
00598 bit [`VMM_RAL_DATA_WIDTH-1:0] prev, v;
00599
00600 // The mirror should contain the initial value
00601 prev = regs[i].get();
00602
00603 // Write a random value, except in those "don't touch" fields
00604 v = ({$random, $random} & ~other_mask) | (prev & other_mask);
00605
00606 `vmm_note(log, $psprintf("Writing register %s via domain \"%s\"...",
00607 regs[i].get_fullname(), domains[j]));
00608
00609 `vmm_debug(log, $psprintf("Writing 'h%h over 'h%h", v, prev));
00610
00611 regs[i].write(status, v, vmm_ral::BFM, domains[j]);
00612 if (status != vmm_rw::IS_OK) begin
00613 `vmm_error(log, $psprintf("Status was %s when writing register \"%s\" through domain \"%s\".",
00614 status.name(), regs[i].get_fullname(), domains[j]));
00615 end
00616
00617 foreach (domains[k]) begin
00618 bit [`VMM_RAL_DATA_WIDTH-1:0] actual, exp;
00619
00620 `vmm_note(log, $psprintf("Reading register %s via domain \"%s\"...",
00621 regs[i].get_fullname(), domains[k]));
00622
00623 // Was it what we expected?
00624 exp = regs[i].get() & ~wo_mask[k];
00625
00626 regs[i].read(status, actual, vmm_ral::BFM, domains[k]);
00627 if (status != vmm_rw::IS_OK) begin
00628 `vmm_error(log, $psprintf("Status was %s when reading register \"%s\" through domain \"%s\".",
00629 status.name(), regs[i].get_fullname(), domains[k]));
00630 end
00631
00632 `vmm_debug(log, $psprintf("Read 'h%h, expecting 'h%h",
00633 actual, exp));
00634
00635 if (actual !== exp) begin
00636 `vmm_error(log, $psprintf("Register \"%s\" through domain \"%s\" is 'h%h instead of 'h%h after writing 'h%h via domain \"%s\" over 'h%h.",
00637 regs[i].get_fullname(), domains[k],
00638 actual, exp, v, domains[j], prev));
00639 end
00640 end
00641 end
00642 end
00643
00644 // Iterate over all memories, looking for shared ones
00645 blk.get_memories(mems);
00646 foreach (mems[i]) begin
00647 string domains[];
00648 int read_from = -1;
00649
00650 // Memories with some attributes are not to be tested
00651 if (mems[i].get_attribute("NO_RAL_TESTS") != "" ||
00652 mems[i].get_attribute("NO_SHARED_ACCESS_TEST") != "") continue;
00653
00654 // Only look at shared memories
00655 if (mems[i].get_n_domains() < 2) continue;
00656 mems[i].get_domains(domains);
00657
00658 // We need at least a backdoor or a domain that can read
00659 // the shared memory
00660 if (mems[i].get_backdoor() == null) begin
00661 foreach (domains[j]) begin
00662 vmm_ral::access_e right;
00663 right = mems[i].get_access(domains[j]);
00664 if (right == vmm_ral::RW ||
00665 right == vmm_ral::RO) begin
00666 read_from = j;
00667 break;
00668 end
00669 end
00670 if (read_from < 0) begin
00671 `vmm_warning(mems[i].log, "Memory cannot be read from any domains or backdoor. Shared access not verified.");
00672 continue;
00673 end
00674 end
00675
00676 // Try to write through each domain
00677 foreach (domains[j]) begin
00678
00679 `vmm_note(log, $psprintf("Writing shared memory \"%s\" via domain \"%s\".",
00680 mems[i].get_fullname(), domains[j]));
00681
00682 // All addresses
00683 for (int offset = 0; offset < mems[i].get_size(); offset++) begin
00684 vmm_rw::status_e status;
00685 bit [`VMM_RAL_DATA_WIDTH-1:0] prev, v;
00686
00687 // Read the initial value
00688 if (mems[i].get_backdoor() != null) begin
00689 mems[i].peek(status, offset, prev);
00690 if (status != vmm_rw::IS_OK) begin
00691 `vmm_error(log, $psprintf("Status was %s when reading initial value of \"%s\"[%0d] through backdoor.",
00692 status.name(), mems[i].get_fullname(), offset));
00693 end
00694 end
00695 else begin
00696 mems[i].read(status, offset, prev, vmm_ral::BFM, domains[read_from]);
00697 if (status != vmm_rw::IS_OK) begin
00698 `vmm_error(log, $psprintf("Status was %s when reading initial value of \"%s\"[%0d] through domain \"%s\".",
00699 status.name(), mems[i].get_fullname(),
00700 offset, domains[read_from]));
00701 end
00702 end
00703
00704
00705 // Write a random value,
00706 v = {$random, $random};
00707
00708 mems[i].write(status, offset, v, vmm_ral::BFM, domains[j]);
00709 if (status != vmm_rw::IS_OK) begin
00710 `vmm_error(log, $psprintf("Status was %s when writing \"%s\"[%0d] through domain \"%s\".",
00711 status.name(), mems[i].get_fullname(), offset, domains[j]));
00712 end
00713
00714 // Read back from all other domains
00715 foreach (domains[k]) begin
00716 bit [`VMM_RAL_DATA_WIDTH-1:0] actual, exp;
00717
00718 mems[i].read(status, offset, actual, vmm_ral::BFM, domains[k]);
00719 if (status != vmm_rw::IS_OK) begin
00720 `vmm_error(log, $psprintf("Status was %s when reading %s[%0d] through domain \"%s\".",
00721 status.name(), mems[i].get_fullname(), offset, domains[k]));
00722 end
00723
00724 // Was it what we expected?
00725 exp = v;
00726 if (mems[i].get_access(domains[j]) == vmm_ral::RO) begin
00727 exp = prev;
00728 end
00729 if (mems[i].get_access(domains[k]) == vmm_ral::WO) begin
00730 exp = 0;
00731 end
00732 // Trim to number of bits
00733 exp &= (1 << mems[i].get_n_bits()) - 1;
00734 if (actual !== exp) begin
00735 `vmm_error(log, $psprintf("%s[%0d] through domain \"%s\" is 'h%h instead of 'h%h after writing 'h%h via domain \"%s\" over 'h%h.",
00736 mems[i].get_fullname(), offset, domains[k],
00737 actual, exp, v, domains[j], prev));
00738 end
00739 end
00740 end
00741 end
00742 end
00743 endtask: shared_access