//
//------------------------------------------------------------------------------
// Copyright 2007-2011 Mentor Graphics Corporation
// Copyright 2007-2011 Cadence Design Systems, Inc.
// Copyright 2010-2011 Synopsys, Inc.
// Copyright 2013 NVIDIA 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.
//------------------------------------------------------------------------------
// Class: uvm_set_before_get_dap
// Provides a 'Set Before Get' Data Access Policy.
//
// The 'Set Before Get' Data Access Policy enforces that the value must
// be written at ~least~ once before it is read. This DAP can be used to
// pass shared information to multiple components during standard configuration,
// even if that information hasn't yet been determined.
//
// Such DAP objects can be useful for passing a 'placeholder' reference, before
// the information is actually available. A good example of this would be
// the virtual sequencer:
//
//| typedef uvm_set_before_get_dap#(uvm_sequencer_base) seqr_dap_t;
//| virtual_seqeuncer_type virtual_sequencer;
//| agent_type my_agent;
//| seqr_dap_t seqr_dap;
//|
//| function void my_env::build_phase(uvm_phase phase);
//| seqr_dap = seqr_dap_t::type_id::create("seqr_dap");
//| // Pass the DAP, because we don't have a reference to the
//| // real sequencer yet...
//| uvm_config_db#(seqr_dap_t)::set(this, "virtual_sequencer", "seqr_dap", seqr_dap);
//|
//| // Create the virtual sequencer
//| virtual_sequencer = virtual_sequencer_type::type_id::create("virtual_sequencer", this);
//|
//| // Create the agent
//| agent = agent_type::type_id::create("agent", this);
//| endfunction
//|
//| function void my_env::connect_phase(uvm_phase phase);
//| // Now that we know the value is good, we can set it
//| seqr_dap.set(agent.sequencer);
//| endfunction
//
// In the example above, the environment didn't have a reference to the
// agent's sequencer yet, because the agent hadn't executed its ~build_phase~.
// The environment needed to give the virtual sequencer a "Set before get" DAP
// so that the virtual sequencer (and any sequences one it), could ~eventually~
// see the agent's sequencer, when the reference was finally available. If
// the virtual sequencer (or any sequences on it) attempted to 'get' the
// reference to the agent's sequencer ~prior~ to the environment assigning it,
// an error would have been reported.
class [docs]uvm_set_before_get_dap#(type T=int) extends uvm_set_get_dap_base#(T);
// Used for self-references
typedef uvm_set_before_get_dap#(T) this_type;
// Parameterized Utils
`uvm_object_param_utils(uvm_set_before_get_dap#(T))
// Stored data
local T m_value;
// Set state
local bit m_set;
// Function: new
// Constructor
function [docs]new(string name="unnamed-uvm_set_before_get_dap#(T)");
super.new(name);
m_set = 0;
endfunction : new
// Group: Set/Get Interface
// Function: set
// Updates the value stored within the DAP.
//
virtual function void [docs]set(T value);
m_set = 1;
m_value = value;
endfunction : set
// Function: try_set
// Attempts to update the value stored within the DAP.
//
// ~try_set~ will always return a 1.
virtual function bit [docs]try_set(T value);
set(value);
return 1;
endfunction : try_set
// Function: get
// Returns the current value stored within the DAP.
//
// If 'get' is called before a call to <set> or <try_set>, then
// an error will be reported.
virtual function T [docs]get();
if (!m_set) begin
`uvm_error("UVM/SET_BEFORE_GET_DAP/NO_SET",
$sformatf("Attempt to get value on '%s', but the data access policy forbits calling 'get' prior to calling 'set' or 'try_set'!",
get_full_name()))
end
return m_value;
endfunction : get
// Function: try_get
// Attempts to retrieve the current value stored within the DAP
//
// If the value has not been 'set', then try_get will return a 0,
// otherwise it will return a 1, and set ~value~ to the current
// value stored within the DAP.
virtual function bit [docs]try_get(output T value);
if (!m_set) begin
return 0;
end
else begin
value = m_value;
return 1;
end
endfunction : try_get
// Group: Introspection
//
// The ~uvm_set_before_get_dap~ cannot support the standard UVM
// instrumentation methods (~copy~, ~clone~, ~pack~ and
// ~unpack~), due to the fact that they would potentially
// violate the access policy.
//
// A call to any of these methods will result in an error.
virtual function void [docs]do_copy(uvm_object rhs);
`uvm_error("UVM/SET_BEFORE_GET_DAP/CPY",
"'copy()' is not supported for 'uvm_set_before_get_dap#(T)'")
endfunction : do_copy
virtual function void [docs]do_pack(uvm_packer packer);
`uvm_error("UVM/SET_BEFORE_GET_DAP/PCK",
"'pack()' is not supported for 'uvm_set_before_get_dap#(T)'")
endfunction : do_pack
virtual function void [docs]do_unpack(uvm_packer packer);
`uvm_error("UVM/SET_BEFORE_GET_DAP/UPK",
"'unpack()' is not supported for 'uvm_set_before_get_dap#(T)'")
endfunction : do_unpack
// Group- Reporting
// Function- convert2string
virtual function string [docs]convert2string();
if (m_set)
return $sformatf("(%s) %0p [SET]", `uvm_typename(m_value), m_value);
else
return $sformatf("(%s) %0p [UNSET]", `uvm_typename(m_value), m_value);
endfunction : convert2string
// Function- do_print
virtual function void [docs]do_print(uvm_printer printer);
super.do_print(printer);
printer.print_field_int("set_state", m_set, $bits(m_set));
printer.print_generic("value",
`uvm_typename(m_value),
0,
$sformatf("%0p", m_value));
endfunction : do_print
endclass // uvm_set_before_get_dap