uvm_sequence_base¶
- class uvm.seq.uvm_sequence_base.UVMSequenceBase(name='uvm_sequence')[source]¶
Bases:
UVMSequenceItem
CLASS: UVMSequenceBase
The UVMSequenceBase class provides the interfaces needed to create streams of sequence items and/or other sequences.
A sequence is executed by calling its <start> method, either directly or invocation of any of the `uvm_do_* macros.
Executing sequences via <start>:
A sequence’s <start> method has a ~parent_sequence~ argument that controls whether <pre_do>, <mid_do>, and <post_do> are called in the parent sequence. It also has a ~call_pre_post~ argument that controls whether its <pre_body> and <post_body> methods are called. In all cases, its <pre_start> and <post_start> methods are always called.
When <start> is called directly, you can provide the appropriate arguments according to your application.
The sequence execution flow looks like this
User code:
sub_seq.randomize(...) # optional await sub_seq.start(seqr, parent_seq, priority, call_pre_post)
The following methods are called, in order:
sub_seq.pre_start() (async) sub_seq.pre_body() (async) if call_pre_post==1 parent_seq.pre_do(0) (async) if parent_sequence!=None parent_seq.mid_do(this) (func) if parent_sequence!=None sub_seq.body (async) YOUR STIMULUS CODE parent_seq.post_do(this) (func) if parent_sequence!=None sub_seq.post_body() (async) if call_pre_post==1 sub_seq.post_start() (async)
Executing sub-sequences via `uvm_do macros:
A sequence can also be indirectly started as a child in the <body> of a parent sequence. The child sequence’s <start> method is called indirectly by invoking any of the uvm_do functions in
uvm_sequence_defines.py
. In these cases, <start> is called with ~call_pre_post~ set to 0, preventing the started sequence’s <pre_body> and <post_body> methods from being called. During execution of the child sequence, the parent’s <pre_do>, <mid_do>, and <post_do> methods are called.The sub-sequence execution flow looks like:
await uvm_do_with_prior(self, seq_seq, { constraints }, priority)
The following methods are called, in order:
sub_seq.pre_start() (async) parent_seq.pre_do(0) (async) parent_req.mid_do(sub_seq) (func) sub_seq.body() (async) parent_seq.post_do(sub_seq) (func) sub_seq.post_start() (async)
Remember, it is the parent sequence’s pre|mid|post_do that are called, not the sequence being executed.
Executing sequence items via
start_item
/finish_item
or uvm_do functions:Items are started in the
body
of a parent sequence via calls tostart_item
/finish_item
or invocations of any of the `uvm_do macros. The <pre_do>, <mid_do>, and <post_do> methods of the parent sequence will be called as the item is executed.The sequence-item execution flow looks like
User code:
await parent_seq.start_item(item, priority) item.randomize[_with({constraints})] await parent_seq.finish_item(item)
or:
await uvm_do_with_prior(self, item, constraints, priority)
The following methods are called, in order:
sequencer.wait_for_grant(prior) (task) \ start_item parent_seq.pre_do(1) (task) / uvm_do* functions parent_seq.mid_do(item) (func) \ / sequencer.send_request(item) (func)
- inish_item /
sequencer.wait_for_item_done() (task) / parent_seq.post_do(item) (func) /
Attempting to execute a sequence via
start_item
/finish_item
will produce a run-time error.
- type_name = 'uvm_sequence_base'¶
- is_item() bool [source]¶
Function: is_item
Returns 1 on items and 0 on sequences. As this object is a sequence,
is_item
will always return 0.Returns:
- get_sequence_state()[source]¶
Function: get_sequence_state
Returns the sequence state as an enumerated value. Can use to wait on the sequence reaching or changing from one or more states.
| wait(get_sequence_state() & (UVM_STOPPED|UVM_FINISHED))
Returns:
- async wait_for_sequence_state(state_mask)[source]¶
Waits until the sequence reaches one of the given
state
. If the sequence is already in one of the state, this method returns immediately.await wait_for_sequence_state(UVM_STOPPED|UVM_FINISHED)
- Parameters
state_mask –
Raises:
- get_tr_handle()[source]¶
Returns the integral recording transaction handle for this sequence. Can be used to associate sub-sequences and sequence items as child transactions when calling <uvm_component::begin_child_tr>.
Returns:
- async start(sequencer, parent_sequence=None, this_priority=-1, call_pre_post=1)[source]¶
Task: start
Executes this sequence, returning when the sequence has completed.
The
sequencer
argument specifies the sequencer on which to run this sequence. The sequencer must be compatible with the sequence.If
parent_sequence
isNone
, then this sequence is a root parent, otherwise it is a child ofparent_sequence
. Theparent_sequence
’s pre_do, mid_do, and post_do methods will be called during the execution of this sequence.By default, the
priority
of a sequence is the priority of its parent sequence. If it is a root sequence, its default priority is 100. A different priority may be specified bythis_priority
. Higher numbers indicate higher priority.If
call_pre_post
is set to 1 (default), then thepre_body
andpost_body
tasks will be called before and after the sequencebody
is called.- async def start(self, uvm_sequencer_base sequencer,
uvm_sequence_base parent_sequence = None, int this_priority = -1, bit call_pre_post = 1)
- Parameters
sequencer –
parent_sequence –
this_priority –
call_pre_post –
- async pre_start()[source]¶
Task: pre_start
This task is a user-definable callback that is called before the optional execution of
pre_body
. This method should not be called directly by the user.virtual task pre_start()
- async pre_body()[source]¶
Task: pre_body
This task is a user-definable callback that is called before the execution of
body
only
when the sequence is started withstart
. Ifstart
is called withcall_pre_post
set to 0,pre_body
is not called. This method should not be called directly by the user.
- pre_do(is_item)[source]¶
Task: pre_do
This task is a user-definable callback task that is called ~on the parent sequence~, if any sequence has issued a wait_for_grant() call and after the sequencer has selected this sequence, and before the item is randomized.
Although pre_do is a task, consuming simulation cycles may result in unexpected behavior on the driver.
This method should not be called directly by the user.
- Parameters
is_item –
- mid_do(this_item)[source]¶
Function: mid_do
This function is a user-definable callback function that is called after the sequence item has been randomized, and just before the item is sent to the driver. This method should not be called directly by the user.
- Parameters
this_item –
- async body()[source]¶
Task: body
This is the user-defined task where the main sequence code resides. This method should not be called directly by the user.
- post_do(this_item)[source]¶
Function: post_do
This function is a user-definable callback function that is called after the driver has indicated that it has completed the item, using either this item_done or put methods. This method should not be called directly by the user.
- Parameters
this_item –
- async post_body()[source]¶
Task: post_body
This task is a user-definable callback task that is called after the execution of
body
only
when the sequence is started withstart
. Ifstart
is called withcall_pre_post
set to 0,post_body
is not called. This task is a user-definable callback task that is called after the execution of the body, unless the sequence is started with call_pre_post=0. This method should not be called directly by the user.
- async post_start()[source]¶
Task: post_start
This task is a user-definable callback that is called after the optional execution of
post_body
. This method should not be called directly by the user.
- m_init_phase_daps(create)[source]¶
Function- m_init_phase_daps Either creates or renames DAPS
- Parameters
create –
- get_starting_phase()[source]¶
Function: get_starting_phase Returns the ‘starting phase’.
If non-
None
, the starting phase specifies the phase in which this sequence was started. The starting phase is set automatically when this sequence is started as the default sequence on a sequencer. See <uvm_sequencer_base::start_phase_sequence> for more information.Internally, the uvm_sequence_base uses an
uvm_get_to_lock_dap
to protect the starting phase value from being modified after the reference has been read. Once the sequence has ended its execution (either via natural termination, or being killed), then the starting phase value can be modified again.Returns:
- set_starting_phase(phase)[source]¶
Function: set_starting_phase Sets the ‘starting phase’.
Internally, the uvm_sequence_base uses a
uvm_get_to_lock_dap
to protect the starting phase value from being modified after the reference has been read. Once the sequence has ended its execution (either via natural termination, or being killed), then the starting phase value can be modified again.- Parameters
phase –
- set_automatic_phase_objection(value)[source]¶
Function: set_automatic_phase_objection Sets the ‘automatically object to starting phase’ bit.
The most common interaction with the starting phase within a sequence is to simply
The raise statement
the phase’s objection prior to executing the sequence, anddrop
the objection after ending the sequence (either naturally, or via a call tokill
). In order to simplify this interaction for the user, the UVM provides the ability to perform this functionality automatically.For example:
| function my_sequence::new(string name="unnamed") | super.new(name) | set_automatic_phase_objection(1) | endfunction : new From a timeline point of view, the automatic phase objection looks like:
| start() is executed | --! Objection is raised !-- | pre_start() is executed | pre_body() is optionally executed | body() is executed | post_body() is optionally executed | post_start() is executed | --! Objection is dropped !-- | start() unblocks This functionality can also be enabled in sequences which were not written with UVM Run-Time Phasing in mind:
| my_legacy_seq_type seq = new("seq") | seq.set_automatic_phase_objection(1) | seq.start(my_sequencer) Internally, the `uvm_sequence_base` uses a `uvm_get_to_lock_dap` to protect the `automatic_phase_objection` value from being modified after the reference has been read. Once the sequence has ended its execution (either via natural termination, or being killed), then the `automatic_phase_objection` value can be modified again. NEVER set the automatic phase objection bit to 1 if your sequence runs with a forever loop inside of the body, as the objection will never get dropped!
- Parameters
value –
- get_automatic_phase_objection()[source]¶
Function: get_automatic_phase_objection Returns (and locks) the value of the ‘automatically object to starting phase’ bit.
If 1, then the sequence will automatically raise an objection to the starting phase (if the starting phase is not
None
) immediately prior topre_start
being called. The objection will be dropped afterpost_start
has executed, orkill
has been called.Returns:
- m_safe_raise_starting_phase(description='', count=1)[source]¶
m_safe_raise_starting_phase
- function void m_safe_raise_starting_phase(string description = “”,
int count = 1)
- Parameters
description –
count –
- m_safe_drop_starting_phase(description='', count=1)[source]¶
m_safe_drop_starting_phase
- function void m_safe_drop_starting_phase(string description = “”,
int count = 1)
- Parameters
description –
count –
- set_priority(value)[source]¶
Function: set_priority
The priority of a sequence may be changed at any point in time. When the priority of a sequence is changed, the new priority will be used by the sequencer the next time that it arbitrates between sequences.
The default priority value for a sequence is 100. Higher values result in higher priorities.
- Parameters
value –
- get_priority()[source]¶
Function: get_priority
This function returns the current priority of the sequence.
Returns:
- is_relevant()[source]¶
Function: is_relevant
The default is_relevant implementation returns 1, indicating that the sequence is always relevant.
Users may choose to override with their own virtual function to indicate to the sequencer that the sequence is not currently relevant after a request has been made.
When the sequencer arbitrates, it will call is_relevant on each requesting, unblocked sequence to see if it is relevant. If a 0 is returned, then the sequence will not be chosen.
If all requesting sequences are not relevant, then the sequencer will call wait_for_relevant on all sequences and re-arbitrate upon its return.
Any sequence that implements is_relevant must also implement wait_for_relevant so that the sequencer has a way to wait for a sequence to become relevant.
Returns:
- async wait_for_relevant()[source]¶
Task: wait_for_relevant
This method is called by the sequencer when all available sequences are not relevant. When wait_for_relevant returns the sequencer attempt to re-arbitrate.
Returning from this call does not guarantee a sequence is relevant, although that would be the ideal. The method provide some delay to prevent an infinite loop.
If a sequence defines is_relevant so that it is not always relevant (by default, a sequence is always relevant), then the sequence must also supply a wait_for_relevant method.
- is_blocked()[source]¶
Function: is_blocked
Returns a bit indicating whether this sequence is currently prevented from running due to another lock or grab. A 1 is returned if the sequence is currently blocked. A 0 is returned if no lock or grab prevents this sequence from executing. Note that even if a sequence is not blocked, it is possible for another sequence to issue a lock or grab before this sequence can issue a request.
Returns:
- has_lock()[source]¶
Function: has_lock
Returns 1 if this sequence has a lock, 0 otherwise.
Note that even if this sequence has a lock, a child sequence may also have a lock, in which case the sequence is still blocked from issuing operations on the sequencer.
Returns:
- do_kill()[source]¶
Function: do_kill
This function is a user hook that is called whenever a sequence is terminated by using either sequence.kill() or sequencer.stop_sequences() (which effectively calls sequence.kill()).
- create_item(type_var, l_sequencer, name)[source]¶
Function: create_item
Create_item will create and initialize a sequence_item or sequence using the factory. The sequence_item or sequence will be initialized to communicate with the specified sequencer.
- protected function uvm_sequence_item create_item(uvm_object_wrapper type_var,
uvm_sequencer_base l_sequencer, string name)
- Parameters
type_var –
l_sequencer –
name –
Returns:
- async start_item(item, set_priority=-1, sequencer=None)[source]¶
start_item
andfinish_item
together will initiate operation of a sequence item. If the item has not already been initialized using create_item, then it will be initialized here to use the default sequencer specified by self.m_sequencer. Randomization may be done between start_item and finish_item to ensure late generation- virtual task start_item (uvm_sequence_item item,
int set_priority = -1, uvm_sequencer_base sequencer=None)
- Parameters
item –
set_priority –
sequencer –
- async finish_item(item, set_priority=-1)[source]¶
finish_item, together with start_item together will initiate operation of a sequence_item. Finish_item must be called after start_item with no delays or delta-cycles. Randomization, or other functions may be called between the start_item and finish_item calls.
- virtual task finish_item (uvm_sequence_item item,
int set_priority = -1)
- Parameters
item (UVMSequenceItem) – Item that was started with start_item().
set_priority (int) – Priority for the item.
- use_response_handler(enable)[source]¶
Function: use_response_handler
When called with enable set to 1, responses will be sent to the response handler. Otherwise, responses must be retrieved using get_response.
By default, responses from the driver are retrieved in the sequence by calling get_response.
An alternative method is for the sequencer to call the response_handler function with each response.
- Parameters
enable –
- get_use_response_handler()[source]¶
Function: get_use_response_handler
Returns the state of the use_response_handler bit.
Returns:
- response_handler(response)[source]¶
Function: response_handler
When the use_response_handler bit is set to 1, this virtual task is called by the sequencer for each response that arrives for this sequence.
- Parameters
response –
- set_response_queue_error_report_disabled(value)[source]¶
Function: set_response_queue_error_report_disabled
By default, if the self.response_queue overflows, an error is reported. The self.response_queue will overflow if more responses are sent to this sequence from the driver than get_response calls are made. Setting value to 0 disables these errors, while setting it to 1 enables them.
- Parameters
value –
- get_response_queue_error_report_disabled()[source]¶
Function: get_response_queue_error_report_disabled
When this bit is 0 (default value), error reports are generated when the response queue overflows. When this bit is 1, no such error reports are generated.
Returns:
- set_response_queue_depth(value)[source]¶
Function: set_response_queue_depth
The default maximum depth of the response queue is 8. These method is used to examine or change the maximum depth of the response queue.
Setting the response_queue_depth to -1 indicates an arbitrarily deep response queue. No checking is done.
- Parameters
value –
- get_response_queue_depth()[source]¶
Function: get_response_queue_depth
Returns the current depth setting for the response queue.
Returns:
- clear_response_queue()[source]¶
Function: clear_response_queue
Empties the response queue for this sequence.
- put_base_response(response)[source]¶
virtual function void put_base_response(input uvm_sequence_item response)
- Parameters
response –
- put_response(response_item)[source]¶
Function- put_response
Internal method.
virtual function void put_response (uvm_sequence_item response_item)
- Parameters
response_item –
- async get_base_response(response: UVMQueue[UVMSequenceItem], transaction_id=-1)[source]¶
Function- get_base_response
virtual task get_base_response(output uvm_sequence_item response, input int transaction_id = -1)
- Parameters
response –
transaction_id –