#
#------------------------------------------------------------------------------
# Copyright 2007-2011 Mentor Graphics Corporation
# Copyright 2007-2010 Cadence Design Systems, Inc.
# Copyright 2010 Synopsys, Inc.
# 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.
#------------------------------------------------------------------------------
"""
Title: TLM FIFO Classes
This section defines TLM-based FIFO classes.
"""
from .uvm_tlm_fifo_base import UVMTLMFIFOBase
from ..base.uvm_mailbox import UVMMailbox
from ..macros.uvm_message_defines import uvm_error
from .uvm_analysis_port import UVMAnalysisImp
from typing import List, Any
[docs]class UVMTLMFIFO(UVMTLMFIFOBase):
"""
Class: UVMTLMFIFO
This class provides storage of transactions between two independently running
processes. Transactions are put into the FIFO via the `UVMTLMFIFOBase.put_export`.
transactions are fetched from the FIFO in the order they arrived via the
`get_peek_export`. The `UVMTLMFIFOBase.put_export` and `UVMTLMFIFOBase.get_peek_export`
are inherited from
the `UVMTLMFIFOBase` super class, and the interface methods provided by
these exports are defined by the `TLMIFBaseClass` class.
"""
type_name = "uvm_tlm_fifo #(T)"
def __init__(self, name, parent=None, size=1):
"""
The `name` and `parent` are the normal uvm_component constructor arguments.
The `parent` should be `null` if the <uvm_tlm_fifo#(T)> is going to be used in a
statically elaborated construct (e.g., a module). The `size` indicates the
maximum size of the FIFO; a value of zero indicates no upper bound.
Args:
name: Name of the component
parent: Parent of the component
size (int): Size of the TLM FIFO.
"""
UVMTLMFIFOBase.__init__(self, name, parent)
self.m = UVMMailbox(size)
self.m_size = size
self.m_pending_blocked_gets = 0
[docs] def get_type_name(self):
return UVMTLMFIFO.type_name
[docs] def size(self):
"""
Returns the capacity of the FIFO, the number of entries
the FIFO is capable of holding. A return value of 0 indicates the
FIFO capacity has no limit.
Returns:
int: Capacity of the FIFO
"""
return self.m_size
[docs] def used(self):
"""
Function: used
Returns the number of entries put into the FIFO.
Returns:
int: Number of entries in the FIFO.
"""
return self.m.num()
[docs] def is_empty(self):
"""
Returns 1 when there are no entries in the FIFO, 0 otherwise.
Returns:
"""
return self.m.num() == 0
[docs] def is_full(self):
"""
Returns 1 when the number of entries in the FIFO is equal to its <size>,
0 otherwise.
Returns:
"""
return (self.m_size != 0) and (self.m.num() == self.m_size)
[docs] async def put(self, t) -> None:
await self.m.put(t)
self.put_ap.write(t)
[docs] async def get(self, t=None) -> Any:
self.m_pending_blocked_gets += 1
res = await self.m.get()
self.m_pending_blocked_gets -= 1
self.get_ap.write(res)
if t is not None:
t.append(res)
return res
[docs] async def peek(self, t=None) -> Any:
res = await self.m.peek(t)
if t is not None:
t.append(res)
return res
[docs] def try_get(self, t) -> bool:
if not self.m.try_get(t):
return False
self.get_ap.write(t[0])
return True
[docs] def try_peek(self, t) -> bool:
return self.m.try_peek(t)
[docs] def try_put(self, t) -> bool:
if not self.m.try_put(t):
return False
self.put_ap.write(t)
return True
[docs] def can_put(self) -> bool:
return self.m_size == 0 or self.m.num() < self.m_size
[docs] def can_get(self) -> bool:
return self.m.num() > 0 and self.m_pending_blocked_gets == 0
[docs] def can_peek(self) -> bool:
return self.m.num() > 0
[docs] def flush(self) -> None:
"""
Removes all entries from the FIFO, after which `used` returns 0
and `is_empty` returns 1.
"""
trans = []
res = 1
while res:
res = self.try_get(trans)
if self.m.num() > 0 and self.m_pending_blocked_gets != 0:
uvm_error("flush failed",
"there are blocked gets preventing the flush")
[docs]class UVMTLMAnalysisFIFO(UVMTLMFIFO):
"""
Class: UVMTLMAnalysisFIFO
An analysis_fifo is a `UVMTLMFIFO` with an unbounded size and a write interface.
It can be used any place a `UVMAnalysisImp` is used. Typical usage is
as a buffer between a <uvm_analysis_port> in an initiator component
and TLM1 target component.
"""
type_name = "uvm_tlm_analysis_fifo #(T)"
def __init__(self, name, parent=None):
"""
This is the standard `UVMComponent` constructor. `name` is the local name
of this component. The `parent` should be left unspecified when this
component is instantiated in statically elaborated constructs and must be
specified when this component is a child of another UVM component.
Args:
name (str): Name of the component
parent (UVMComponent): Parent of the component
"""
UVMTLMFIFO.__init__(self, name, parent, 0) # analysis fifo must be unbounded
# // Port: analysis_export #(T)
# //
# // The analysis_export provides the write method to all connected analysis
# // ports and parent exports:
# //
# //| def write(self, t)
# //
# // Access via ports bound to this export is the normal mechanism for writing
# // to an analysis FIFO.
# // See write method of <uvm_tlm_if_base #(T1,T2)> for more information.
self.analysis_export = UVMAnalysisImp("analysis_export", self)
[docs] def get_type_name(self):
return UVMTLMAnalysisFIFO.type_name
[docs] def write(self, t) -> None:
self.try_put(t) # unbounded => must succeed