URL
https://opencores.org/ocsvn/uart2bus_testbench/uart2bus_testbench/trunk
Subversion Repositories uart2bus_testbench
[/] [uart2bus_testbench/] [trunk/] [tb/] [uvm_src/] [reg/] [sequences/] [uvm_reg_mem_shared_access_seq.svh] - Rev 16
Compare with Previous | Blame | View Log
//// -------------------------------------------------------------// Copyright 2004-2008 Synopsys, Inc.// Copyright 2010 Mentor Graphics Corporation// 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.// -------------------------------------------------------------////------------------------------------------------------------------------------// Title: Shared Register and Memory Access Test Sequences//------------------------------------------------------------------------------// This section defines sequences for testing registers and memories that are// shared between two or more physical interfaces, i.e. are associated with// more than one <uvm_reg_map> instance.//------------------------------------------------------------------------------//------------------------------------------------------------------------------// Class: uvm_reg_shared_access_seq//// Verify the accessibility of a shared register// by writing through each address map// then reading it via every other address maps// in which the register is readable and the backdoor,// making sure that the resulting value matches the mirrored value.//// If bit-type resource named// "NO_REG_TESTS" or "NO_REG_SHARED_ACCESS_TEST"// in the "REG::" namespace// matches the full name of the register,// the register is not tested.////| uvm_resource_db#(bit)::set({"REG::",regmodel.blk.r0.get_full_name()},//| "NO_REG_TESTS", 1, this);//// Registers that contain fields with unknown access policies// cannot be tested.//// The DUT should be idle and not modify any register during this test.////------------------------------------------------------------------------------class uvm_reg_shared_access_seq extends uvm_reg_sequence #(uvm_sequence #(uvm_reg_item));// Variable: rg// The register to be testeduvm_reg rg;`uvm_object_utils(uvm_reg_shared_access_seq)function new(string name="uvm_reg_shared_access_seq");super.new(name);endfunctionvirtual task body();uvm_reg_data_t other_mask;uvm_reg_data_t wo_mask[$];uvm_reg_field fields[$];uvm_reg_map maps[$];if (rg == null) begin`uvm_error("uvm_reg_shared_access_seq", "No register specified to run sequence on");return;end// Registers with some attributes are not to be testedif (uvm_resource_db#(bit)::get_by_name({"REG::",rg.get_full_name()},"NO_REG_TESTS", 0) != null ||uvm_resource_db#(bit)::get_by_name({"REG::",rg.get_full_name()},"NO_REG_SHARED_ACCESS_TEST", 0) != null )return;// Only look at shared registersif (rg.get_n_maps() < 2) return;rg.get_maps(maps);// Let's see what kind of bits we have...rg.get_fields(fields);// Identify unpredictable bits and the ones we shouldn't changeother_mask = 0;foreach (fields[k]) beginint lsb, w;lsb = fields[k].get_lsb_pos();w = fields[k].get_n_bits();if (!fields[k].is_known_access(maps[0])) beginrepeat (w) beginother_mask[lsb++] = 1'b1;endendend// 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 functionforeach (maps[j]) beginuvm_reg_data_t wo;wo = 0;foreach (fields[k]) beginint lsb, w;lsb = fields[k].get_lsb_pos();w = fields[k].get_n_bits();if (fields[k].get_access(maps[j]) == "WO") beginrepeat (w) beginwo[lsb++] = 1'b1;endendendwo_mask[j] = wo;end// Try to write through each mapforeach (maps[j]) beginuvm_status_e status;uvm_reg_data_t prev, v;// The mirror should contain the initial valueprev = rg.get();// Write a random value, except in those "don't touch" fieldsv = ({$random, $random} & ~other_mask) | (prev & other_mask);`uvm_info("uvm_reg_shared_access_seq", $sformatf("Writing register %s via map \"%s\"...",rg.get_full_name(), maps[j].get_full_name), UVM_LOW);`uvm_info("uvm_reg_shared_access_seq", $sformatf("Writing 'h%h over 'h%h", v, prev),UVM_DEBUG);rg.write(status, v, UVM_FRONTDOOR, maps[j], this);if (status != UVM_IS_OK) begin`uvm_error("uvm_reg_shared_access_seq", $sformatf("Status was %s when writing register \"%s\" through map \"%s\".",status.name(), rg.get_full_name(), maps[j].get_full_name()));endforeach (maps[k]) beginuvm_reg_data_t actual, exp;`uvm_info("uvm_reg_shared_access_seq", $sformatf("Reading register %s via map \"%s\"...",rg.get_full_name(), maps[k].get_full_name()), UVM_LOW);// Was it what we expected?exp = rg.get() & ~wo_mask[k];rg.read(status, actual, UVM_FRONTDOOR, maps[k], this);if (status != UVM_IS_OK) begin`uvm_error("uvm_reg_shared_access_seq", $sformatf("Status was %s when reading register \"%s\" through map \"%s\".",status.name(), rg.get_full_name(), maps[k].get_full_name()));end`uvm_info("uvm_reg_shared_access_seq", $sformatf("Read 'h%h, expecting 'h%h",actual, exp),UVM_DEBUG);if (actual !== exp) begin`uvm_error("uvm_reg_shared_access_seq", $sformatf("Register \"%s\" through map \"%s\" is 'h%h instead of 'h%h after writing 'h%h via map \"%s\" over 'h%h.",rg.get_full_name(), maps[k].get_full_name(),actual, exp, v, maps[j].get_full_name(), prev));endendendendtask: bodyendclass: uvm_reg_shared_access_seq//------------------------------------------------------------------------------// Class: uvm_mem_shared_access_seq//------------------------------------------------------------------------------//// Verify the accessibility of a shared memory// by writing through each address map// then reading it via every other address maps// in which the memory is readable and the backdoor,// making sure that the resulting value matches the written value.//// If bit-type resource named// "NO_REG_TESTS", "NO_MEM_TESTS",// "NO_REG_SHARED_ACCESS_TEST" or "NO_MEM_SHARED_ACCESS_TEST"// in the "REG::" namespace// matches the full name of the memory,// the memory is not tested.////| uvm_resource_db#(bit)::set({"REG::",regmodel.blk.mem0.get_full_name()},//| "NO_MEM_TESTS", 1, this);//// The DUT should be idle and not modify the memory during this test.////------------------------------------------------------------------------------class uvm_mem_shared_access_seq extends uvm_reg_sequence #(uvm_sequence #(uvm_reg_item));// variable: mem// The memory to be testeduvm_mem mem;`uvm_object_utils(uvm_mem_shared_access_seq)function new(string name="uvm_mem_shared_access_seq");super.new(name);endfunctionvirtual task body();int read_from;uvm_reg_map maps[$];if (mem == null) begin`uvm_error("uvm_mem_shared_access_seq", "No memory specified to run sequence on");return;end// Memories with some attributes are not to be testedif (uvm_resource_db#(bit)::get_by_name({"REG::",mem.get_full_name()},"NO_REG_TESTS", 0) != null ||uvm_resource_db#(bit)::get_by_name({"REG::",mem.get_full_name()},"NO_MEM_TESTS", 0) != null ||uvm_resource_db#(bit)::get_by_name({"REG::",mem.get_full_name()},"NO_REG_SHARED_ACCESS_TEST", 0) != null ||uvm_resource_db#(bit)::get_by_name({"REG::",mem.get_full_name()},"NO_MEM_SHARED_ACCESS_TEST", 0) != null )return;// Only look at shared memoriesif (mem.get_n_maps() < 2) return;mem.get_maps(maps);// We need at least a backdoor or a map that can read// the shared memoryread_from = -1;if (mem.get_backdoor() == null) beginforeach (maps[j]) beginstring right;right = mem.get_access(maps[j]);if (right == "RW" ||right == "RO") beginread_from = j;break;endendif (read_from < 0) begin`uvm_warning("uvm_mem_shared_access_seq", $sformatf("Memory \"%s\" cannot be read from any maps or backdoor. Shared access not verified.", mem.get_full_name()));return;endend// Try to write through each mapforeach (maps[j]) begin`uvm_info("uvm_mem_shared_access_seq", $sformatf("Writing shared memory \"%s\" via map \"%s\".",mem.get_full_name(), maps[j].get_full_name()), UVM_LOW);// All addressesfor (int offset = 0; offset < mem.get_size(); offset++) beginuvm_status_e status;uvm_reg_data_t prev, v;// Read the initial valueif (mem.get_backdoor() != null) beginmem.peek(status, offset, prev);if (status != UVM_IS_OK) begin`uvm_error("uvm_mem_shared_access_seq", $sformatf("Status was %s when reading initial value of \"%s\"[%0d] through backdoor.",status.name(), mem.get_full_name(), offset));endendelse beginmem.read(status, offset, prev, UVM_FRONTDOOR, maps[read_from], this);if (status != UVM_IS_OK) begin`uvm_error("uvm_mem_shared_access_seq", $sformatf("Status was %s when reading initial value of \"%s\"[%0d] through map \"%s\".",status.name(), mem.get_full_name(),offset, maps[read_from].get_full_name()));endend// Write a random value,v = {$random, $random};mem.write(status, offset, v, UVM_FRONTDOOR, maps[j], this);if (status != UVM_IS_OK) begin`uvm_error("uvm_mem_shared_access_seq", $sformatf("Status was %s when writing \"%s\"[%0d] through map \"%s\".",status.name(), mem.get_full_name(), offset, maps[j].get_full_name()));end// Read back from all other mapsforeach (maps[k]) beginuvm_reg_data_t actual, exp;mem.read(status, offset, actual, UVM_FRONTDOOR, maps[k], this);if (status != UVM_IS_OK) begin`uvm_error("uvm_mem_shared_access_seq", $sformatf("Status was %s when reading %s[%0d] through map \"%s\".",status.name(), mem.get_full_name(), offset, maps[k].get_full_name()));end// Was it what we expected?exp = v;if (mem.get_access(maps[j]) == "RO") beginexp = prev;endif (mem.get_access(maps[k]) == "WO") beginexp = 0;end// Trim to number of bitsexp &= (1 << mem.get_n_bits()) - 1;if (actual !== exp) begin`uvm_error("uvm_mem_shared_access_seq", $sformatf("%s[%0d] through map \"%s\" is 'h%h instead of 'h%h after writing 'h%h via map \"%s\" over 'h%h.",mem.get_full_name(), offset, maps[k].get_full_name(),actual, exp, v, maps[j].get_full_name(), prev));endendendendendtask: bodyendclass: uvm_mem_shared_access_seq//------------------------------------------------------------------------------// Class: uvm_reg_mem_shared_access_seq//------------------------------------------------------------------------------//// Verify the accessibility of all shared registers// and memories in a block// by executing the <uvm_reg_shared_access_seq>// and <uvm_mem_shared_access_seq>// sequence respectively on every register and memory within it.//// If bit-type resource named// "NO_REG_TESTS", "NO_MEM_TESTS",// "NO_REG_SHARED_ACCESS_TEST" or "NO_MEM_SHARED_ACCESS_TEST"// in the "REG::" namespace// matches the full name of the block,// the block is not tested.////| uvm_resource_db#(bit)::set({"REG::",regmodel.blk.get_full_name(),".*"},//| "NO_REG_TESTS", 1, this);////------------------------------------------------------------------------------class uvm_reg_mem_shared_access_seq extends uvm_reg_sequence #(uvm_sequence #(uvm_reg_item));// Variable: model//// The block to be tested////| uvm_reg_block model;// Variable: reg_seq//// The sequence used to test one register//protected uvm_reg_shared_access_seq reg_seq;// Variable: mem_seq//// The sequence used to test one memory//protected uvm_mem_shared_access_seq mem_seq;`uvm_object_utils(uvm_reg_mem_shared_access_seq)function new(string name="uvm_reg_mem_shared_access_seq");super.new(name);endfunction// Task: body//// Executes the Shared Register and Memory sequence//virtual task body();if (model == null) begin`uvm_error("uvm_reg_mem_shared_access_seq", "No register model specified to run sequence on");return;enduvm_report_info("STARTING_SEQ",{"\n\nStarting ",get_name()," sequence...\n"},UVM_LOW);reg_seq = uvm_reg_shared_access_seq::type_id::create("reg_shared_access_seq");mem_seq = uvm_mem_shared_access_seq::type_id::create("reg_shared_access_seq");this.reset_blk(model);model.reset();do_block(model);endtask: body// Task: do_block//// Test all of the registers and memories in a block//protected virtual task do_block(uvm_reg_block blk);uvm_reg regs[$];uvm_mem mems[$];if (uvm_resource_db#(bit)::get_by_name({"REG::",blk.get_full_name()},"NO_REG_TESTS", 0) != null ||uvm_resource_db#(bit)::get_by_name({"REG::",blk.get_full_name()},"NO_MEM_TESTS", 0) != null ||uvm_resource_db#(bit)::get_by_name({"REG::",blk.get_full_name()},"NO_REG_SHARED_ACCESS_TEST", 0) != null ||uvm_resource_db#(bit)::get_by_name({"REG::",blk.get_full_name()},"NO_MEM_SHARED_ACCESS_TEST", 0) != null )return;this.reset_blk(model);model.reset();// Iterate over all registers, checking accessesblk.get_registers(regs, UVM_NO_HIER);foreach (regs[i]) begin// Registers with some attributes are not to be testedif (uvm_resource_db#(bit)::get_by_name({"REG::",regs[i].get_full_name()},"NO_REG_TESTS", 0) != null ||uvm_resource_db#(bit)::get_by_name({"REG::",regs[i].get_full_name()},"NO_REG_SHARED_ACCESS_TEST", 0) != null )continue;reg_seq.rg = regs[i];reg_seq.start(this.get_sequencer(), this);end// Iterate over all memories, checking accessesblk.get_memories(mems, UVM_NO_HIER);foreach (mems[i]) begin// Registers with some attributes are not to be testedif (uvm_resource_db#(bit)::get_by_name({"REG::",mems[i].get_full_name()},"NO_REG_TESTS", 0) != null ||uvm_resource_db#(bit)::get_by_name({"REG::",mems[i].get_full_name()},"NO_MEM_TESTS", 0) != null ||uvm_resource_db#(bit)::get_by_name({"REG::",mems[i].get_full_name()},"NO_REG_SHARED_ACCESS_TEST", 0) != null ||uvm_resource_db#(bit)::get_by_name({"REG::",mems[i].get_full_name()},"NO_MEM_SHARED_ACCESS_TEST", 0) != null )continue;mem_seq.mem = mems[i];mem_seq.start(this.get_sequencer(), this);endbeginuvm_reg_block blks[$];blk.get_blocks(blks);foreach (blks[i]) begindo_block(blks[i]);endendendtask: do_block//// task: reset_blk// Reset the DUT that corresponds to the specified block abstraction class.//// Currently empty.// Will rollback the environment's phase to the ~reset~// phase once the new phasing is available.//// In the meantime, the DUT should be reset before executing this// test sequence or this method should be implemented// in an extension to reset the DUT.//virtual task reset_blk(uvm_reg_block blk);endtaskendclass: uvm_reg_mem_shared_access_seq
