📄 bit_bash.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 bit_bash;vmm_log log = new("Bit Bash", "Test");`RAL_TB_ENV env = new;initialbegin vmm_ral_block_or_sys ral_model; vmm_ral_reg regs[]; 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(); // Iterate over all registers, trying to modify read-only bits // and making sure read-write bits can be set and cleared ral_model.get_registers(regs); foreach (regs[i]) begin vmm_ral_field fields[]; vmm_ral::access_e mode[`VMM_RAL_DATA_WIDTH]; string domains[]; bit [`VMM_RAL_DATA_WIDTH-1:0] wo_mask; bit [`VMM_RAL_DATA_WIDTH-1:0] reset_val; int n_bits; n_bits = regs[i].get_n_bytes() * 8; // Let's see what kind of bits we have... regs[i].get_fields(fields); // Registers may be accessible from multiple physical interfaces (domains) regs[i].get_domains(domains); // Bash the bits in the register via each domain foreach (domains[j]) begin vmm_rw::status_e status; bit [`VMM_RAL_DATA_WIDTH-1:0] val, exp, v, other; int next_lsb; next_lsb = 0; wo_mask = '1; foreach (fields[k]) begin int lsb, w; lsb = fields[k].get_lsb_pos_in_register(); w = fields[k].get_n_bits(); // Any unused bits on the right side of the LSB? while (next_lsb < lsb) begin mode[next_lsb++] = vmm_ral::RO; end repeat (w) begin mode[next_lsb] = fields[k].get_access(domains[j]); if (mode[next_lsb] == vmm_ral::WO) wo_mask[next_lsb] = 1'b0; next_lsb++; end end // Any unused bits on the left side of the MSB? while (next_lsb < 64) begin mode[next_lsb++] = vmm_ral::RO; end `vmm_note(log, $psprintf("Verifying bits in register %s in domain \"%s\"...", regs[i].get_fullname(), domains[j])); // The mirror still contains initial value reset_val = regs[i].get(); // But the mirrored value of any WO bits will read back // as all zeroes via the frontdoor... reset_val &= wo_mask; regs[i].read(status, val, vmm_ral::BFM, domains[j]); if (status != vmm_rw::IS_OK) begin `vmm_error(log, $psprintf("Status was %s when reading register \"%s\" through domain \"%s\".", status, regs[i].get_fullname(), domains[j])); end if (val !== reset_val) begin `vmm_error(log, $psprintf("Initial value of register \"%s\" ('h%h) not %s ('h%h)", regs[i].get_fullname(), val, (j == 0) ? "reset value" : "as expected", reset_val)); end // Bash the kth bit other = 0; for (int k = 0; k < n_bits; k++) begin // Cannot test unpredictable bit behavior if (mode[k] >= vmm_ral::DC) begin other[k] = 1; continue; end bash_kth_bit(regs[i], k, mode[k], domains[j], wo_mask); end // Write the complement of the reset value // Except in the "OTHER" and "USERx" bits val = reset_val ^ ~other; regs[i].write(status, val, vmm_ral::BFM, domains[j]); if (status != vmm_rw::IS_OK) begin `vmm_error(log, $psprintf("Status was %s when writing to register \"%s\" through domain \"%s\".", status, regs[i].get_fullname(), domains[j])); end exp = regs[i].get() & wo_mask; regs[i].read(status, v, vmm_ral::BFM, domains[j]); if (status != vmm_rw::IS_OK) begin `vmm_error(log, $psprintf("Status was %s when reading register \"%s\" through domain \"%s\".", status, regs[i].get_fullname(), domains[j])); end if (v !== exp) begin `vmm_error(log, $psprintf("Writing 'h%h to register \"%s\" with initial value 'h%h yielded 'h%h instead of 'h%h", val, regs[i].get_fullname(), reset_val, v, exp)); end end end // Apply reset then verify all reset values env.hw_reset(); ral_model.reset(); foreach (regs[i]) begin string domains[]; // Registers may be accessible from multiple physical interfaces (domains) regs[i].get_domains(domains); // Verify the reset value in each domain foreach (domains[j]) begin vmm_rw::status_e status; bit [`VMM_RAL_DATA_WIDTH-1:0] v; `vmm_note(log, $psprintf("Verifying reset value of register %s in domain \"%s\"...", regs[i].get_fullname(), domains[j])); regs[i].mirror(status, vmm_ral::VERB, vmm_ral::BFM, domains[j]); if (status != vmm_rw::IS_OK) begin `vmm_error(log, $psprintf("Status was %s when reading reset value of register \"%s\" through domain \"%s\".", status, regs[i].get_fullname(), domains[j])); end end end env.log.report();endtask bash_kth_bit(input vmm_ral_reg regs, input int k, input vmm_ral::access_e mode, input string domain, input bit [`VMM_RAL_DATA_WIDTH-1:0] wo_mask); vmm_rw::status_e status; bit [`VMM_RAL_DATA_WIDTH-1:0] val, exp, v; bit bit_val; `vmm_note(log, $psprintf("...Bashing %s bit #%0d", mode.name(), k)); repeat (2) begin val = regs.get(); v = val; exp = val; val[k] = ~val[k]; bit_val = val[k]; regs.write(status, val, vmm_ral::BFM, domain); if (status != vmm_rw::IS_OK) begin `vmm_error(log, $psprintf("Status was %s when writing to register \"%s\" through domain \"%s\".", status, regs.get_fullname(), domain)); end exp = regs.get() & wo_mask; regs.read(status, val, vmm_ral::BFM, domain); if (status != vmm_rw::IS_OK) begin `vmm_error(log, $psprintf("Status was %s when reading register \"%s\" through domain \"%s\".", status, regs.get_fullname(), domain)); end if (val !== exp) begin `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", bit_val, k, regs.get_fullname(), v, val, exp)); end end // If this is a write-once bit, apply reset and make sure it // can be written again. if (mode == vmm_ral::W1) begin env.hw_reset(); regs.reset(); val = regs.get(); val[k] = ~val[k]; regs.write(status, val, vmm_ral::BFM, domain); if (status != vmm_rw::IS_OK) begin `vmm_error(log, $psprintf("Status was %s when writing to register \"%s\" through domain \"%s\".", status, regs.get_fullname(), domain)); end exp = regs.get() & wo_mask; regs.read(status, val, vmm_ral::BFM, domain); if (status != vmm_rw::IS_OK) begin `vmm_error(log, $psprintf("Status was %s when reading register \"%s\" through domain \"%s\".", status, regs.get_fullname(), domain)); end if (val !== exp) begin `vmm_error(log, $psprintf("Writing a %b in W1 bit #%0d of register \"%s\" after reset yielded 'h%h instead of 'h%h", bit_val, k, regs.get_fullname(), val, exp)); end endendtask: bash_kth_bitendprogram: bit_bash
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -