Source code for uvm.reg.sequences.uvm_mem_access_seq

#//
#// -------------------------------------------------------------
#//    Copyright 2004-2008 Synopsys, Inc.
#//    Copyright 2010 Mentor Graphics Corporation
#//    Copyright 2019-2020 Tuomas Poikela (tpoikela)
#//    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.
#// -------------------------------------------------------------
#//

import cocotb
from cocotb.triggers import Timer

from ..uvm_reg_sequence import UVMRegSequence
from ..uvm_reg_model import *
from ...macros import uvm_error, uvm_object_utils, uvm_info, uvm_warning
from ...base import sv, UVM_LOW


#//
#// TITLE: Memory Access Test Sequence
#//


#//
#// class: UVMMemSingleAccessSeq
#//
#// Verify the accessibility of a memory
#// by writing through its default address map
#// then reading it via the backdoor, then reversing the process,
#// making sure that the resulting value matches the written value.
#//
#// If bit-type resource named
#// "NO_REG_TESTS", "NO_MEM_TESTS", or "NO_MEM_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);
#//
#// Memories without an available backdoor
#// cannot be tested.
#//
#// The DUT should be idle and not modify the memory during this test.
#//


[docs]class UVMMemSingleAccessSeq(UVMRegSequence): # (uvm_sequence #(uvm_reg_item)) def __init__(self, name="uam_mem_single_access_seq"): super().__init__(name) # // Variable: mem # // # // The memory to be tested # // self.mem = None
[docs] async def body(self): mem = self.mem mode = "" maps = [] # uvm_reg_map[$] n_bits = 0 if mem is None: uvm_error("UVMMemAccessSeq", "No register specified to run sequence on") return # Memories with some attributes are not to be tested if reg_test_off(mem, ["NO_REG_TESTS", "NO_MEM_TESTS", "NO_MEM_ACCESS_TEST"]): return # Can only deal with memories with backdoor access if (mem.get_backdoor() is None and not mem.has_hdl_path()): uvm_error("UVMMemAccessSeq", "Memory '" + mem.get_full_name() + "' does not have a backdoor mechanism available") return n_bits = mem.get_n_bits() # Memories may be accessible from multiple physical interfaces (maps) mem.get_maps(maps) # Walk the memory via each map for j in range(len(maps)): status = 0 val = 0 exp = 0 v = 0 uvm_info("UVMMemAccessSeq", "Verifying access of memory '" + mem.get_full_name() + "' in map '" + maps[j].get_full_name() + "' ...", UVM_LOW) mode = mem.get_access(maps[j]) # The access process is, for address k: # - Write random value via front door # - Read via backdoor and expect same random value if RW # - Write complement of random value via back door # - Read via front door and expect inverted random value for k in range(mem.get_size()): val = sv.random() & (1 << n_bits) - 1 # cast to 'uvm_reg_data_t' removed if n_bits > 32: val = (val << 32) | sv.random() if mode == "RO": status = [] await mem.peek(status, k, exp) status = status[0] if status != UVM_IS_OK: uvm_error("UVMMemAccessSeq", sv.sformatf( "Status was %s when reading \"%s[%0d]\" through backdoor.", status.name(), mem.get_full_name(), k)) else: exp = val status = [] await mem.write(status, k, val, UVM_FRONTDOOR, maps[j], self) status = status[0] if status != UVM_IS_OK: uvm_error("UVMMemAccessSeq", sv.sformatf( "Status was %s when writing '%s[%0d]' through map '%s'.", status.name(), mem.get_full_name(), k, maps[j].get_full_name())) await Timer(1, "NS") val = [] status = [] #yield mem.peek(status, k, val) mem.peek(status, k, val) status = status[0] if status != UVM_IS_OK: uvm_error("UVMMemAccessSeq", sv.sformatf( "Status was %s when reading '%s[%0d]' through backdoor.", str(status), mem.get_full_name(), k)) else: val = val[0] if val != exp: uvm_error("UVMMemAccessSeq", sv.sformatf( "Backdoor '%s[%0d]' read back as 'h%h instead of 'h%h.", mem.get_full_name(), k, val, exp)) exp = ~exp & ((1 << n_bits)-1) status = [] #yield mem.poke(status, k, exp) mem.poke(status, k, exp) status = status[0] if status != UVM_IS_OK: uvm_error("UVMMemAccessSeq", sv.sformatf( "Status was %s when writing '%s[%0d-1]' through backdoor.", str(status), mem.get_full_name(), k)) status = [] val = [] await mem.read(status, k, val, UVM_FRONTDOOR, maps[j], self) status = status[0] val = val[0] if status != UVM_IS_OK: uvm_error("UVMMemAccessSeq", sv.sformatf( "Status was %s when reading \"%s[%0d]\" through map \"%s\".", status.name(), mem.get_full_name(), k, maps[j].get_full_name())) else: if mode == "WO": if val != 0: uvm_error("UVMMemAccessSeq", sv.sformatf( "Front door \"%s[%0d]\" read back as 'h%h instead of 'h%h.", mem.get_full_name(), k, val, 0)) else: if val != exp: uvm_error("UVMMemAccessSeq", sv.sformatf( "Front door \"%s[%0d]\" read back as 'h%h instead of 'h%h.", mem.get_full_name(), k, val, exp))
#endclass: UVMMemSingleAccessSeq uvm_object_utils(UVMMemSingleAccessSeq) #// #// class: UVMMemAccessSeq #// #// Verify the accessibility of all memories in a block #// by executing the <UVMMemSingleAccessSeq> sequence on #// every memory within it. #// #// If bit-type resource named #// "NO_REG_TESTS", "NO_MEM_TESTS", or "NO_MEM_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_MEM_TESTS", 1, this); #//
[docs]class UVMMemAccessSeq(UVMRegSequence): # (uvm_sequence #(uvm_reg_item)) def __init__(self, name="UVMMemAccessSeq"): super().__init__(name) # // Variable: mem_seq # // # // The sequence used to test one memory # // self.mem_seq = None # // Task: body # // # // Execute the Memory Access sequence. # // Do not call directly. Use seq.start() instead. # //
[docs] async def body(self): model = self.model if model is None: uvm_error("UVMMemAccessSeq", "No register model specified to run sequence on") return uvm_info("STARTING_SEQ", "\n\nStarting " + self.get_name() + " sequence...\n", UVM_LOW) self.mem_seq = UVMMemSingleAccessSeq.type_id.create("single_mem_access_seq") await self.reset_blk(model) model.reset() await self.do_block(model)
# // Task: do_block # // # // Test all of the memories in a given ~block~ # //
[docs] async def do_block(self, blk): if reg_test_off(blk, ["NO_REG_TESTS", "NO_MEM_TESTS", "NO_MEM_ACCESS_TEST"]): return # Iterate over all memories, checking accesses mems = [] # uvm_mem[$] blk.get_memories(mems, UVM_NO_HIER) for i in range(len(mems)): # Registers with some attributes are not to be tested if reg_test_off(mems[i], ["NO_REG_TESTS", "NO_MEM_TESTS", "NO_MEM_ACCESS_TEST"]): continue # Can only deal with memories with backdoor access if (mems[i].get_backdoor() is None and not mems[i].has_hdl_path()): uvm_warning("UVMMemAccessSeq", sv.sformatf( "Memory \"%s\" does not have a backdoor mechanism available", mems[i].get_full_name())) continue self.mem_seq.mem = mems[i] await self.mem_seq.start(None, self) blks = [] # uvm_reg_block[$] blk.get_blocks(blks) for i in range(len(blks)): await self.do_block(blks[i])
# // 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. # //
[docs] async def reset_blk(self, blk): await Timer(1, "NS")
#endclass: UVMMemAccessSeq uvm_object_utils(UVMMemAccessSeq)