📄 shared_access.sv
字号:
// // -------------------------------------------------------------// Copyright 2004-2008 Synopsys, Inc.// All Rights Reserved Worldwide// // Licensed under the Apache License, Version 2.0 (the// "License"); you may not use this file except in// compliance with the License. You may obtain a copy of// the License at// // http://www.apache.org/licenses/LICENSE-2.0// // Unless required by applicable law or agreed to in// writing, software distributed under the License is// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR// CONDITIONS OF ANY KIND, either express or implied. See// the License for the specific language governing// permissions and limitations under the License.// -------------------------------------------------------------// `include "ral_env.svh"`ifndef RAL_TB_ENV`define RAL_TB_ENV tb_env`endifprogram shared_access;vmm_log log = new("Shared Access", "Test");`RAL_TB_ENV env = new;initialbegin vmm_ral_block_or_sys ral_model; vmm_ral_reg regs[]; vmm_ral_mem mems[]; ral_model = env.ral.get_model(); if (ral_model == null) begin `vmm_fatal(log, "No RAL abstraction model was specified"); end env.reset_dut(); ral_model.reset(); //log.set_verbosity(vmm_log::DEBUG_SEV); //env.ral.log.set_verbosity(vmm_log::TRACE_SEV); // Iterate over all registers, looking for shared registers ral_model.get_registers(regs); foreach (regs[i]) begin string domains[]; vmm_ral_field fields[]; bit [`VMM_RAL_DATA_WIDTH-1:0] other_mask; bit [`VMM_RAL_DATA_WIDTH-1:0] wo_mask[]; // Only look at shared registers if (regs[i].get_n_domains() < 2) continue; regs[i].get_domains(domains); // Let's see what kind of bits we have... regs[i].get_fields(fields); // Identify unpredictable bits and the ones we shouldn't change other_mask = 0; foreach (fields[k]) begin int lsb, w; lsb = fields[k].get_lsb_pos_in_register(); w = fields[k].get_n_bits(); if (fields[k].get_access(domains[0]) >= vmm_ral::OTHER) begin repeat (w) begin other_mask[lsb++] = 1'b1; end end end // WO bits will always readback as 0's but the mirror // with return what is supposed to have been written // so we cannot use the mirror-check function wo_mask = new [domains.size()]; foreach (domains[j]) begin bit [`VMM_RAL_DATA_WIDTH-1:0] wo; wo = 0; foreach (fields[k]) begin int lsb, w; lsb = fields[k].get_lsb_pos_in_register(); w = fields[k].get_n_bits(); if (fields[k].get_access(domains[j]) == vmm_ral::WO) begin repeat (w) begin wo[lsb++] = 1'b1; end end end wo_mask[j] = wo; end // Try to write through each domain foreach (domains[j]) begin vmm_rw::status_e status; bit [`VMM_RAL_DATA_WIDTH-1:0] prev, v; // The mirror should contain the initial value prev = regs[i].get(); // Write a random value, except in those "don't touch" fields v = ({$random, $random} & ~other_mask) | (prev & other_mask); `vmm_note(log, $psprintf("Writing register %s via domain \"%s\"...", regs[i].get_fullname(), domains[j])); `vmm_debug(log, $psprintf("Writing 'h%h over 'h%h", v, prev)); regs[i].write(status, v, vmm_ral::BFM, domains[j]); if (status != vmm_rw::IS_OK) begin `vmm_error(log, $psprintf("Status was %s when writing register \"%s\" through domain \"%s\".", status.name(), regs[i].get_fullname(), domains[j])); end foreach (domains[k]) begin bit [`VMM_RAL_DATA_WIDTH-1:0] actual, exp; `vmm_note(log, $psprintf("Reading register %s via domain \"%s\"...", regs[i].get_fullname(), domains[k])); // Was it what we expected? exp = regs[i].get() & ~wo_mask[k]; regs[i].read(status, actual, vmm_ral::BFM, domains[k]); if (status != vmm_rw::IS_OK) begin `vmm_error(log, $psprintf("Status was %s when reading register \"%s\" through domain \"%s\".", status.name(), regs[i].get_fullname(), domains[k])); end `vmm_debug(log, $psprintf("Read 'h%h, expecting 'h%h", actual, exp)); if (actual !== exp) begin `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.", regs[i].get_fullname(), domains[k], actual, exp, v, domains[j], prev)); end end end end // Iterate over all memories, looking for shared ones ral_model.get_memories(mems); foreach (mems[i]) begin string domains[]; int read_from = -1; // Only look at shared memories if (mems[i].get_n_domains() < 2) continue; mems[i].get_domains(domains); // We need at least a backdoor or a domain that can read // the shared memory if (mems[i].get_backdoor() == null) begin foreach (domains[j]) begin vmm_ral::access_e right; right = mems[i].get_access(domains[j]); if (right == vmm_ral::RW || right == vmm_ral::RO) begin read_from = j; break; end end if (read_from < 0) begin `vmm_warning(mems[i].log, "Memory cannot be read from any domains or backdoor. Shared access not verified."); continue; end end // Try to write through each domain foreach (domains[j]) begin `vmm_note(log, $psprintf("Writing shared memory \"%s\" via domain \"%s\".", mems[i].get_fullname(), domains[j])); // All addresses for (int offset = 0; offset < mems[i].get_size(); offset++) begin vmm_rw::status_e status; bit [`VMM_RAL_DATA_WIDTH-1:0] prev, v; // Read the initial value if (mems[i].get_backdoor() != null) begin mems[i].peek(status, offset, prev); if (status != vmm_rw::IS_OK) begin `vmm_error(log, $psprintf("Status was %s when reading initial value of \"%s\"[%0d] through backdoor.", status.name(), mems[i].get_fullname(), offset)); end end else begin mems[i].read(status, offset, prev, vmm_ral::BFM, domains[read_from]); if (status != vmm_rw::IS_OK) begin `vmm_error(log, $psprintf("Status was %s when reading initial value of \"%s\"[%0d] through domain \"%s\".", status.name(), mems[i].get_fullname(), offset, domains[read_from])); end end // Write a random value, v = {$random, $random}; mems[i].write(status, offset, v, vmm_ral::BFM, domains[j]); if (status != vmm_rw::IS_OK) begin `vmm_error(log, $psprintf("Status was %s when writing \"%s\"[%0d] through domain \"%s\".", status.name(), mems[i].get_fullname(), offset, domains[j])); end // Read back from all other domains foreach (domains[k]) begin bit [`VMM_RAL_DATA_WIDTH-1:0] actual, exp; mems[i].read(status, offset, actual, vmm_ral::BFM, domains[k]); if (status != vmm_rw::IS_OK) begin `vmm_error(log, $psprintf("Status was %s when reading %s[%0d] through domain \"%s\".", status.name(), mems[i].get_fullname(), offset, domains[k])); end // Was it what we expected? exp = v; if (mems[i].get_access(domains[j]) == vmm_ral::RO) begin exp = prev; end if (mems[i].get_access(domains[k]) == vmm_ral::WO) begin exp = 0; end // Trim to number of bits exp &= (1 << mems[i].get_n_bits()) - 1; if (actual !== exp) begin `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.", mems[i].get_fullname(), offset, domains[k], actual, exp, v, domains[j], prev)); end end end end end env.log.report();endendprogram: shared_access
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -