Вы находитесь на странице: 1из 5

//------------------------------------------------------------------------------

// Copyright 2007-2010 Mentor Graphics Corporation


// Copyright 2007-2010 Cadence Design Systems, Inc.
// Copyright 2010 Synopsys, 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.
//------------------------------------------------------------------------------

`include "uvm_macros.svh"

//------------------------------------------------------------------------------
// Title: Typical Callback Application
//
// This example demonstrates callback usage. The component developer defines a
// driver and driver-specific callback class. The callback class defines the
// hooks available for users to override. The component using the callbacks
// (i.e. calling the callback methods) also defines corresponding virtual
// methods for each callback hook. The developer implements each virtual methods
// to call the corresponding callback method in all registered callback objects
// using default algorithm. The end-user may then define either a callback or
// driver subtype to extend driver behavior.
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
//
// Group: Component Developer Use Model
//
//------------------------------------------------------------------------------
// Component developers defines transaction, driver, and callback classes.
//------------------------------------------------------------------------------

package bus_driver_pkg;

import uvm_pkg::*;

typedef class bus_driver;


typedef class bus_driver_cb;
typedef uvm_callbacks #(bus_driver,bus_driver_cb) bus_driver_cbs_t;

//------------------------------------------------------------------------------
//
// CLASS: bus_tr
//
// A basic bus transaction.
//------------------------------------------------------------------------------

class bus_tr extends uvm_transaction;


rand int addr;
rand int data;
virtual function string convert2string();
convert2string = $sformatf("addr=%0h data=%0h",addr,data);
endfunction
endclass

//------------------------------------------------------------------------------
//
// CLASS: bus_driver_cb
//
//------------------------------------------------------------------------------
// The callback class defines an interface consisting of one or more function
// or task prototypes. The signatures of each method have no restrictions.
// The component developer knows best the intended semantic of multiple
// registered callbacks. Thus the algorithm for traversal the callback queue
// should reside in the callback class itself. We could provide convenience
// macros that implement the most common traversal methods, such as sequential
// in-order execution.
//------------------------------------------------------------------------------

virtual class bus_driver_cb extends uvm_callback;

virtual function bit trans_received(bus_driver driver, bus_tr tr);


return 0;
endfunction

virtual task trans_executed(bus_driver driver, bus_tr tr);


endtask

function new(string name="bus_driver_cb_inst");


super.new(name);
endfunction

static string type_name = "bus_driver_cb";

virtual function string get_type_name();


return type_name;
endfunction

endclass

//------------------------------------------------------------------------------
//
// CLASS: bus_driver
//
//------------------------------------------------------------------------------
// With the following implementation of bus_driver, users can implement
// the callback "hooks" by either...
//
// - extending bus_driver and overriding one or more of the virtual
// methods, trans_received or trans_executed. Then, configure the
// factory to use the new type via a type or instance override.
//
// - extending bus_driver_cb and overriding one or more of the virtual
// methods, trans_received or trans_executed. Then, register an
// instance of the new callback type with an instance of bus_driver.
// This requires access to the handle of the bus_driver.
//------------------------------------------------------------------------------

class bus_driver extends uvm_component;

uvm_blocking_put_imp #(bus_tr,bus_driver) in;

`uvm_register_cb(bus_driver, bus_driver_cb)

function new (string name, uvm_component parent=null);


super.new(name,parent);
in = new("in",this);
endfunction

static string type_name = "bus_driver";

virtual function string get_type_name();


return type_name;
endfunction

virtual function bit trans_received(bus_tr tr);


`uvm_do_callbacks_exit_on(bus_driver,bus_driver_cb,trans_received(this,tr),1)
endfunction

virtual task trans_executed(bus_tr tr);


`uvm_do_callbacks(bus_driver,bus_driver_cb,trans_executed(this,tr))
endtask

virtual task put(bus_tr t);


uvm_report_info("bus_tr received",t.convert2string());
if (!trans_received(t)) begin
uvm_report_info("bus_tr dropped",
"user callback indicated DROPPED\n");
return;
end
#100;
trans_executed(t);
uvm_report_info("bus_tr executed",{t.convert2string(),"\n"});
endtask

endclass

endpackage // bus_driver_pkg

//------------------------------------------------------------------------------
//
// Group: End-User Use Model
//
//------------------------------------------------------------------------------
// The end-user simply needs to extend the callback base class, overriding any or
// all of the prototypes provided in the developer-supplied callback interface.
// Then, register an instance of the callback class with any object designed to
// use the base callback type.
//------------------------------------------------------------------------------

import uvm_pkg::*;
import bus_driver_pkg::*;
//------------------------------------------------------------------------------
//
// CLASS: my_bus_driver_cb
//
//------------------------------------------------------------------------------
// This class defines a subtype of the driver developer's base callback class.
// In this case, both available driver callback methods are defined. The
// ~trans_received~ method randomly chooses whether to return 0 or 1. When 1,
// the driver will "drop" the received transaction.
//------------------------------------------------------------------------------

class my_bus_driver_cb extends bus_driver_cb;

function new(string name="bus_driver_cb_inst");


super.new(name);
endfunction

virtual function bit trans_received(bus_driver driver, bus_tr tr);


static bit drop = 0;
driver.uvm_report_info("trans_received_cb",
{" bus_driver=",driver.get_full_name()," tr=",tr.convert2string()});
drop = 1 - drop;
return drop;
endfunction

virtual task trans_executed(bus_driver driver, bus_tr tr);


driver.uvm_report_info("trans_executed_cb",
{" bus_driver=",driver.get_full_name()," tr=",tr.convert2string()});
endtask

virtual function string get_type_name();


return "my_bus_driver_cb";
endfunction

endclass

//------------------------------------------------------------------------------
//
// CLASS: my_bus_driver_cb2
//
//------------------------------------------------------------------------------
// This class defines a subtype of the driver developer's base callback class.
// In this case, only one of the two available methods are defined.
//------------------------------------------------------------------------------

class my_bus_driver_cb2 extends bus_driver_cb;

function new(string name="bus_driver_cb_inst");


super.new(name);
endfunction

virtual task trans_executed(bus_driver driver, bus_tr tr);


driver.uvm_report_info("trans_executed_cb2",
{" bus_driver=",driver.get_full_name()," tr=",tr.convert2string()});
endtask

virtual function string get_type_name();


return "my_bus_driver_cb2";
endfunction

endclass

//------------------------------------------------------------------------------
//
// MODULE: top
//
//------------------------------------------------------------------------------
// In this simple example, we don't build a complete environment, but this does
// not detract from the example's purpose. In the top module, we instantiate
// the bus_driver, and one instance each of our custom callback classes.
// To register the callbacks with the driver, we get the global callback pool
// that is typed to our specific driver-callback combination. We associate
// (register) the callback objects with driver using the callback pool's
// ~add_cb~ method. After calling ~display~ just to show that the
// registration was successful, we push several transactions into the driver.
// Our custom callbacks get called as the driver receives each transaction.
//------------------------------------------------------------------------------

module top;
import uvm_pkg::*;
import bus_driver_pkg::*;

bus_tr tr = new;
bus_driver driver = new("driver");
my_bus_driver_cb cb1 = new("cb1");
my_bus_driver_cb2 cb2 = new("cb2");

initial begin
bus_driver_cbs_t::add(driver,cb1);
bus_driver_cbs_t::add(driver,cb2);
bus_driver_cbs_t::display();
for (int i=1; i<=5; i++) begin
tr.addr = i;
tr.data = 6-i;
driver.in.put(tr);
end
begin
uvm_report_server svr;
svr = uvm_report_server::get_server();
svr.summarize();
end
end

endmodule

Вам также может понравиться