blob: 6aeefb9ab43098f464e77569fe1deb11c43f7915 [file] [log] [blame]
//
//-----------------------------------------------------------------------------
// Copyright 2007-2014 Mentor Graphics Corporation
// Copyright 2015 Analog Devices, Inc.
// Copyright 2007-2018 Cadence Design Systems, Inc.
// Copyright 2013-2015 NVIDIA Corporation
// Copyright 2017 Cisco Systems, 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.
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
// File -- NODOCS -- Transaction Recording Streams
//
// class- m_uvm_tr_stream_cfg
// Undocumented helper class for storing stream
// initialization values.
class m_uvm_tr_stream_cfg;
uvm_tr_database db;
string scope;
string stream_type_name;
endclass : m_uvm_tr_stream_cfg
typedef class uvm_set_before_get_dap;
typedef class uvm_text_recorder;
// @uvm-ieee 1800.2-2017 auto 7.2.1
virtual class uvm_tr_stream extends uvm_object;
// Variable- m_cfg_dap
// Data access protected reference to the DB
local uvm_set_before_get_dap#(m_uvm_tr_stream_cfg) m_cfg_dap;
// Variable- m_records
// Active records in the stream (active == open or closed)
local bit m_records[uvm_recorder];
// Variable- m_warn_null_cfg
// Used to limit the number of warnings
local bit m_warn_null_cfg;
// Variable- m_is_opened
// Used to indicate stream is open
local bit m_is_opened;
// Variable- m_is_closed
// Used to indicate stream is closed
local bit m_is_closed;
// !m_is_opened && !m_is_closed == m_is_freed
// @uvm-ieee 1800.2-2017 auto 7.2.2
function new(string name="unnamed-uvm_tr_stream");
super.new(name);
m_cfg_dap = new("cfg_dap");
endfunction : new
// Variable- m_ids_by_stream
// An associative array of int, indexed by uvm_tr_streams. This
// provides a unique 'id' or 'handle' for each stream, which can be
// used to identify the stream.
//
// By default, neither ~m_ids_by_stream~ or ~m_streams_by_id~ are
// used. Streams are only placed in the arrays when the user
// attempts to determine the id for a stream.
local static int m_ids_by_stream[uvm_tr_stream];
// Group -- NODOCS -- Configuration API
// @uvm-ieee 1800.2-2017 auto 7.2.3.1
function uvm_tr_database get_db();
m_uvm_tr_stream_cfg m_cfg;
if (!m_cfg_dap.try_get(m_cfg)) begin
if (m_warn_null_cfg == 1)
`uvm_warning("UVM/REC_STR/NO_CFG",
$sformatf("attempt to retrieve DB from '%s' before it was set!",
get_name()))
m_warn_null_cfg = 0;
return null;
end
return m_cfg.db;
endfunction : get_db
// @uvm-ieee 1800.2-2017 auto 7.2.3.2
function string get_scope();
m_uvm_tr_stream_cfg m_cfg;
if (!m_cfg_dap.try_get(m_cfg)) begin
if (m_warn_null_cfg == 1)
`uvm_warning("UVM/REC_STR/NO_CFG",
$sformatf("attempt to retrieve scope from '%s' before it was set!",
get_name()))
m_warn_null_cfg = 0;
return "";
end
return m_cfg.scope;
endfunction : get_scope
// @uvm-ieee 1800.2-2017 auto 7.2.3.3
function string get_stream_type_name();
m_uvm_tr_stream_cfg m_cfg;
if (!m_cfg_dap.try_get(m_cfg)) begin
if (m_warn_null_cfg == 1)
`uvm_warning("UVM/REC_STR/NO_CFG",
$sformatf("attempt to retrieve STREAM_TYPE_NAME from '%s' before it was set!",
get_name()))
m_warn_null_cfg = 0;
return "";
end
return m_cfg.stream_type_name;
endfunction : get_stream_type_name
// Group -- NODOCS -- Stream API
//
// Once a stream has been opened via <uvm_tr_database::open_stream>, the user
// can ~close~ the stream.
//
// Due to the fact that many database implementations will require crossing
// a language boundary, an additional step of ~freeing~ the stream is required.
//
// A ~link~ can be established within the database any time between "Open" and
// "Free", however it is illegal to establish a link after "Freeing" the stream.
//
// @uvm-ieee 1800.2-2017 auto 7.2.4.1
function void close();
if (!is_open())
return;
do_close();
foreach (m_records[idx])
if (idx.is_open())
idx.close();
m_is_opened = 0;
m_is_closed = 1;
endfunction : close
// @uvm-ieee 1800.2-2017 auto 7.2.4.2
function void free();
process p;
string s;
uvm_tr_database db;
if (!is_open() && !is_closed())
return;
if (is_open())
close();
do_free();
foreach (m_records[idx])
idx.free();
// Clear out internal state
db = get_db();
m_is_closed = 0;
p = process::self();
if(p != null)
s = p.get_randstate();
m_cfg_dap = new("cfg_dap");
if(p != null)
p.set_randstate(s);
m_warn_null_cfg = 1;
if (m_ids_by_stream.exists(this))
m_free_id(m_ids_by_stream[this]);
// Clear out DB state
if (db != null)
db.m_free_stream(this);
endfunction : free
// Function- m_do_open
// Initializes the state of the stream
//
// Parameters-
// db - Database which the stream belongs to
// scope - Optional scope
// stream_type_name - Optional type name for the stream
//
// This method will trigger a <do_open> call.
//
// An error will be asserted if-
// - m_do_open is called more than once without the stream
// being ~freed~ between.
// - m_do_open is passed a ~null~ db
function void m_do_open(uvm_tr_database db,
string scope="",
string stream_type_name="");
m_uvm_tr_stream_cfg m_cfg;
uvm_tr_database m_db;
if (db == null) begin
`uvm_error("UVM/REC_STR/NULL_DB",
$sformatf("Illegal attempt to set DB for '%s' to '<null>'",
this.get_full_name()))
return;
end
if (m_cfg_dap.try_get(m_cfg)) begin
`uvm_error("UVM/REC_STR/RE_CFG",
$sformatf("Illegal attempt to re-open '%s'",
this.get_full_name()))
end
else begin
// Never set before
m_cfg = new();
m_cfg.db = db;
m_cfg.scope = scope;
m_cfg.stream_type_name = stream_type_name;
m_cfg_dap.set(m_cfg);
m_is_opened = 1;
do_open(db, scope, stream_type_name);
end
endfunction : m_do_open
// @uvm-ieee 1800.2-2017 auto 7.2.4.3
function bit is_open();
return m_is_opened;
endfunction : is_open
// @uvm-ieee 1800.2-2017 auto 7.2.4.4
function bit is_closed();
return m_is_closed;
endfunction : is_closed
// Group -- NODOCS -- Transaction Recorder API
//
// New recorders can be opened prior to the stream being ~closed~.
//
// Once a stream has been closed, requests to open a new recorder
// will be ignored (<open_recorder> will return ~null~).
//
// @uvm-ieee 1800.2-2017 auto 7.2.5.1
function uvm_recorder open_recorder(string name,
time open_time = 0,
string type_name="");
time m_time = (open_time == 0) ? $time : open_time;
// Check to make sure we're open
if (!is_open())
return null;
else begin
process p = process::self();
string s;
if (p != null)
s = p.get_randstate();
open_recorder = do_open_recorder(name,
m_time,
type_name);
if (open_recorder != null) begin
m_records[open_recorder] = 1;
open_recorder.m_do_open(this, m_time, type_name);
end
if (p != null)
p.set_randstate(s);
end
endfunction : open_recorder
// Function- m_free_recorder
// Removes recorder from the internal array
function void m_free_recorder(uvm_recorder recorder);
if (m_records.exists(recorder))
m_records.delete(recorder);
endfunction : m_free_recorder
// @uvm-ieee 1800.2-2017 auto 7.2.5.2
function unsigned get_recorders(ref uvm_recorder q[$]);
// Clear out the queue first...
q.delete();
// Fill in the values
foreach (m_records[idx])
q.push_back(idx);
// Finally return the size of the queue
return q.size();
endfunction : get_recorders
// Group -- NODOCS -- Handles
// Variable- m_streams_by_id
// A corollary to ~m_ids_by_stream~, this indexes the streams by their
// unique ids.
local static uvm_tr_stream m_streams_by_id[int];
// @uvm-ieee 1800.2-2017 auto 7.2.6.1
function int get_handle();
if (!is_open() && !is_closed()) begin
return 0;
end
else begin
int handle = get_inst_id();
// Check for the weird case where our handle changed.
if (m_ids_by_stream.exists(this) && m_ids_by_stream[this] != handle)
m_streams_by_id.delete(m_ids_by_stream[this]);
m_streams_by_id[handle] = this;
m_ids_by_stream[this] = handle;
return handle;
end
endfunction : get_handle
// @uvm-ieee 1800.2-2017 auto 7.2.6.2
static function uvm_tr_stream get_stream_from_handle(int id);
if (id == 0)
return null;
if ($isunknown(id) || !m_streams_by_id.exists(id))
return null;
return m_streams_by_id[id];
endfunction : get_stream_from_handle
// Function- m_free_id
// Frees the id/stream link (memory cleanup)
//
static function void m_free_id(int id);
uvm_tr_stream stream;
if (!$isunknown(id) && m_streams_by_id.exists(id))
stream = m_streams_by_id[id];
if (stream != null) begin
m_streams_by_id.delete(id);
m_ids_by_stream.delete(stream);
end
endfunction : m_free_id
// Group -- NODOCS -- Implementation Agnostic API
//
// @uvm-ieee 1800.2-2017 auto 7.2.7.1
protected virtual function void do_open(uvm_tr_database db,
string scope,
string stream_type_name);
endfunction : do_open
// @uvm-ieee 1800.2-2017 auto 7.2.7.2
protected virtual function void do_close();
endfunction : do_close
// @uvm-ieee 1800.2-2017 auto 7.2.7.3
protected virtual function void do_free();
endfunction : do_free
// @uvm-ieee 1800.2-2017 auto 7.2.7.4
protected virtual function uvm_recorder do_open_recorder(string name,
time open_time,
string type_name);
return null;
endfunction : do_open_recorder
endclass : uvm_tr_stream