// // ------------------------------------------------------------- // Copyright 2004-2009 Synopsys, Inc. // Copyright 2010 Mentor Graphics Corporation // Copyright 2010 Cadence Design 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. // ------------------------------------------------------------- // typedef class uvm_reg; typedef class uvm_mem; typedef class uvm_reg_backdoor; //------------------------------------------------------------------------------ // Title: Register Callbacks // // This section defines the base class used for all register callback // extensions. It also includes pre-defined callback extensions for use on // read-only and write-only registers. //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ // Class: uvm_reg_cbs // // Facade class for field, register, memory and backdoor // access callback methods. //------------------------------------------------------------------------------ virtual class uvm_reg_cbs extends uvm_callback; function new(string name = "uvm_reg_cbs"); super.new(name); endfunction // Task: pre_write // // Called before a write operation. // // All registered ~pre_write~ callback methods are invoked after the // invocation of the ~pre_write~ method of associated object (, // , , or ). If the element being // written is a , all ~pre_write~ callback methods are invoked // before the contained . // // Backdoor - , // cbs for backdoor. // // Register - , // cbs for reg, // then foreach field: // , // cbs for field // // RegField - , // cbs for field // // Memory - , // cbs for mem // // The ~rw~ argument holds information about the operation. // // - Modifying the ~value~ modifies the actual value written. // // - For memories, modifying the ~offset~ modifies the offset // used in the operation. // // - For non-backdoor operations, modifying the access ~path~ or // address ~map~ modifies the actual path or map used in the // operation. // // If the ~rw.status~ is modified to anything other than , // the operation is aborted. // // See for details on ~rw~ information. // virtual task pre_write(uvm_reg_item rw); endtask // Task: post_write // // Called after a write operation. // // All registered ~post_write~ callback methods are invoked before the // invocation of the ~post_write~ method of the associated object (, // , , or ). If the element being // written is a , all ~post_write~ callback methods are invoked // before the contained . // // Summary of callback order: // // Backdoor - cbs for backdoor, // // // Register - cbs for reg, // , // then foreach field: // cbs for field, // // // RegField - cbs for field, // // // Memory - cbs for mem, // // // The ~rw~ argument holds information about the operation. // // - Modifying the ~status~ member modifies the returned status. // // - Modiying the ~value~ or ~offset~ members has no effect, as // the operation has already completed. // // See for details on ~rw~ information. // virtual task post_write(uvm_reg_item rw); endtask // Task: pre_read // // Callback called before a read operation. // // All registered ~pre_read~ callback methods are invoked after the // invocation of the ~pre_read~ method of associated object (, // , , or ). If the element being // read is a , all ~pre_read~ callback methods are invoked before // the contained . // // Backdoor - , // cbs for backdoor // // Register - , // cbs for reg, // then foreach field: // , // cbs for field // // RegField - , // cbs for field // // Memory - , // cbs for mem // // The ~rw~ argument holds information about the operation. // // - The ~value~ member of ~rw~ is not used has no effect if modified. // // - For memories, modifying the ~offset~ modifies the offset // used in the operation. // // - For non-backdoor operations, modifying the access ~path~ or // address ~map~ modifies the actual path or map used in the // operation. // // If the ~rw.status~ is modified to anything other than , // the operation is aborted. // // See for details on ~rw~ information. // virtual task pre_read(uvm_reg_item rw); endtask // Task: post_read // // Callback called after a read operation. // // All registered ~post_read~ callback methods are invoked before the // invocation of the ~post_read~ method of the associated object (, // , , or ). If the element being read // is a , all ~post_read~ callback methods are invoked before the // contained . // // Backdoor - cbs for backdoor, // // // Register - cbs for reg, // , // then foreach field: // cbs for field, // // // RegField - cbs for field, // // // Memory - cbs for mem, // // // The ~rw~ argument holds information about the operation. // // - Modifying the readback ~value~ or ~status~ modifies the actual // returned value and status. // // - Modiying the ~value~ or ~offset~ members has no effect, as // the operation has already completed. // // See for details on ~rw~ information. // virtual task post_read(uvm_reg_item rw); endtask // Task: post_predict // // Called by the method // after a successful UVM_PREDICT_READ or UVM_PREDICT_WRITE prediction. // // ~previous~ is the previous value in the mirror and // ~value~ is the latest predicted value. Any change to ~value~ will // modify the predicted mirror value. // virtual function void post_predict(input uvm_reg_field fld, input uvm_reg_data_t previous, inout uvm_reg_data_t value, input uvm_predict_e kind, input uvm_path_e path, input uvm_reg_map map); endfunction // Function: encode // // Data encoder // // The registered callback methods are invoked in order of registration // after all the ~pre_write~ methods have been called. // The encoded data is passed through each invocation in sequence. // This allows the ~pre_write~ methods to deal with clear-text data. // // By default, the data is not modified. // virtual function void encode(ref uvm_reg_data_t data[]); endfunction // Function: decode // // Data decode // // The registered callback methods are invoked in ~reverse order~ // of registration before all the ~post_read~ methods are called. // The decoded data is passed through each invocation in sequence. // This allows the ~post_read~ methods to deal with clear-text data. // // The reversal of the invocation order is to allow the decoding // of the data to be performed in the opposite order of the encoding // with both operations specified in the same callback extension. // // By default, the data is not modified. // virtual function void decode(ref uvm_reg_data_t data[]); endfunction endclass //------------------ // Section: Typedefs //------------------ // Type: uvm_reg_cb // // Convenience callback type declaration for registers // // Use this declaration to register register callbacks rather than // the more verbose parameterized class // typedef uvm_callbacks#(uvm_reg, uvm_reg_cbs) uvm_reg_cb; // Type: uvm_reg_cb_iter // // Convenience callback iterator type declaration for registers // // Use this declaration to iterate over registered register callbacks // rather than the more verbose parameterized class // typedef uvm_callback_iter#(uvm_reg, uvm_reg_cbs) uvm_reg_cb_iter; // Type: uvm_reg_bd_cb // // Convenience callback type declaration for backdoor // // Use this declaration to register register backdoor callbacks rather than // the more verbose parameterized class // typedef uvm_callbacks#(uvm_reg_backdoor, uvm_reg_cbs) uvm_reg_bd_cb; // Type: uvm_reg_bd_cb_iter // Convenience callback iterator type declaration for backdoor // // Use this declaration to iterate over registered register backdoor callbacks // rather than the more verbose parameterized class // typedef uvm_callback_iter#(uvm_reg_backdoor, uvm_reg_cbs) uvm_reg_bd_cb_iter; // Type: uvm_mem_cb // // Convenience callback type declaration for memories // // Use this declaration to register memory callbacks rather than // the more verbose parameterized class // typedef uvm_callbacks#(uvm_mem, uvm_reg_cbs) uvm_mem_cb; // Type: uvm_mem_cb_iter // // Convenience callback iterator type declaration for memories // // Use this declaration to iterate over registered memory callbacks // rather than the more verbose parameterized class // typedef uvm_callback_iter#(uvm_mem, uvm_reg_cbs) uvm_mem_cb_iter; // Type: uvm_reg_field_cb // // Convenience callback type declaration for fields // // Use this declaration to register field callbacks rather than // the more verbose parameterized class // typedef uvm_callbacks#(uvm_reg_field, uvm_reg_cbs) uvm_reg_field_cb; // Type: uvm_reg_field_cb_iter // // Convenience callback iterator type declaration for fields // // Use this declaration to iterate over registered field callbacks // rather than the more verbose parameterized class // typedef uvm_callback_iter#(uvm_reg_field, uvm_reg_cbs) uvm_reg_field_cb_iter; //----------------------------- // Group: Predefined Extensions //----------------------------- //------------------------------------------------------------------------------ // Class: uvm_reg_read_only_cbs // // Pre-defined register callback method for read-only registers // that will issue an error if a write() operation is attempted. // //------------------------------------------------------------------------------ class uvm_reg_read_only_cbs extends uvm_reg_cbs; function new(string name = "uvm_reg_read_only_cbs"); super.new(name); endfunction `uvm_object_utils(uvm_reg_read_only_cbs) // Function: pre_write // // Produces an error message and sets status to . // virtual task pre_write(uvm_reg_item rw); string name = rw.element.get_full_name(); if (rw.status != UVM_IS_OK) return; if (rw.element_kind == UVM_FIELD) begin uvm_reg_field fld; uvm_reg rg; $cast(fld, rw.element); rg = fld.get_parent(); name = rg.get_full_name(); end `uvm_error("UVM/REG/READONLY", {name, " is read-only. Cannot call write() method."}); rw.status = UVM_NOT_OK; endtask local static uvm_reg_read_only_cbs m_me; local static function uvm_reg_read_only_cbs get(); if (m_me == null) m_me = new; return m_me; endfunction // Function: add // // Add this callback to the specified register and its contained fields. // static function void add(uvm_reg rg); uvm_reg_field flds[$]; uvm_reg_cb::add(rg, get()); rg.get_fields(flds); foreach (flds[i]) begin uvm_reg_field_cb::add(flds[i], get()); end endfunction // Function: remove // // Remove this callback from the specified register and its contained fields. // static function void remove(uvm_reg rg); uvm_reg_cb_iter cbs = new(rg); uvm_reg_field flds[$]; void'(cbs.first()); while (cbs.get_cb() != get()) begin if (cbs.get_cb() == null) return; void'(cbs.next()); end uvm_reg_cb::delete(rg, get()); rg.get_fields(flds); foreach (flds[i]) begin uvm_reg_field_cb::delete(flds[i], get()); end endfunction endclass //------------------------------------------------------------------------------ // Class: uvm_reg_write_only_cbs // // Pre-defined register callback method for write-only registers // that will issue an error if a read() operation is attempted. // //------------------------------------------------------------------------------ class uvm_reg_write_only_cbs extends uvm_reg_cbs; function new(string name = "uvm_reg_write_only_cbs"); super.new(name); endfunction `uvm_object_utils(uvm_reg_write_only_cbs) // Function: pre_read // // Produces an error message and sets status to . // virtual task pre_read(uvm_reg_item rw); string name = rw.element.get_full_name(); if (rw.status != UVM_IS_OK) return; if (rw.element_kind == UVM_FIELD) begin uvm_reg_field fld; uvm_reg rg; $cast(fld, rw.element); rg = fld.get_parent(); name = rg.get_full_name(); end `uvm_error("UVM/REG/WRTEONLY", {name, " is write-only. Cannot call read() method."}); rw.status = UVM_NOT_OK; endtask local static uvm_reg_write_only_cbs m_me; local static function uvm_reg_write_only_cbs get(); if (m_me == null) m_me = new; return m_me; endfunction // Function: add // // Add this callback to the specified register and its contained fields. // static function void add(uvm_reg rg); uvm_reg_field flds[$]; uvm_reg_cb::add(rg, get()); rg.get_fields(flds); foreach (flds[i]) begin uvm_reg_field_cb::add(flds[i], get()); end endfunction // Function: remove // // Remove this callback from the specified register and its contained fields. // static function void remove(uvm_reg rg); uvm_reg_cb_iter cbs = new(rg); uvm_reg_field flds[$]; void'(cbs.first()); while (cbs.get_cb() != get()) begin if (cbs.get_cb() == null) return; void'(cbs.next()); end uvm_reg_cb::delete(rg, get()); rg.get_fields(flds); foreach (flds[i]) begin uvm_reg_field_cb::delete(flds[i], get()); end endfunction endclass