uvm_report_info("TEST", "I am in the top-level test", UVM_NONE);
UVM_INFO @ 0: reporter [TEST] I am in the top-level test
`uvm_info("TEST", "I am in the top-level test", UVM_NONE)
UVM_INFO ex_messages.sv(13) @ 0: reporter [TEST] I am in the top-level test
2011年6月4日 星期六
UVM Factory Usage in set_type_override_by_type
Cadence example
`include "uvm_pkg.sv"
module uvm_type_override;
// Import the UVM Package and include the UVM macros
import uvm_pkg::*;
`include "uvm_macros.svh"
class state extends uvm_component;
`uvm_component_utils(state)
function new(string name="state", uvm_component parent);
super.new(name, parent);
endfunction : new
function void end_of_elaboration();
this.print();
endfunction : end_of_elaboration
endclass : state
class florida extends state;
`uvm_component_utils(florida)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction : new
endclass : florida
class new_york extends state;
`uvm_component_utils(new_york)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction : new
endclass : new_york
state my_state1, my_state2;
initial begin
my_state1 = state::type_id::create("my_state1", null);
`uvm_info("INFO1", {"my_state1.type=", my_state1.get_type_name()}, UVM_LOW);
factory.set_type_override_by_type(state::get_type(), new_york::get_type());
my_state2 = state::type_id::create("my_state2", null);
`uvm_info("INFO2", {"my_state2.type=", my_state2.get_type_name()}, UVM_LOW);
#100 $finish;
end
endmodule : uvm_type_override
simulation result:
UVM_INFO ex4-16_uvm_factory2.sv(41) @ 0: reporter [INFO1] my_state1.type=state
UVM_INFO ex4-16_uvm_factory2.sv(44) @ 0: reporter [INFO2] my_state2.type=new_york
`include "uvm_pkg.sv"
module uvm_type_override;
// Import the UVM Package and include the UVM macros
import uvm_pkg::*;
`include "uvm_macros.svh"
class state extends uvm_component;
`uvm_component_utils(state)
function new(string name="state", uvm_component parent);
super.new(name, parent);
endfunction : new
function void end_of_elaboration();
this.print();
endfunction : end_of_elaboration
endclass : state
class florida extends state;
`uvm_component_utils(florida)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction : new
endclass : florida
class new_york extends state;
`uvm_component_utils(new_york)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction : new
endclass : new_york
state my_state1, my_state2;
initial begin
my_state1 = state::type_id::create("my_state1", null);
`uvm_info("INFO1", {"my_state1.type=", my_state1.get_type_name()}, UVM_LOW);
factory.set_type_override_by_type(state::get_type(), new_york::get_type());
my_state2 = state::type_id::create("my_state2", null);
`uvm_info("INFO2", {"my_state2.type=", my_state2.get_type_name()}, UVM_LOW);
#100 $finish;
end
endmodule : uvm_type_override
simulation result:
UVM_INFO ex4-16_uvm_factory2.sv(41) @ 0: reporter [INFO1] my_state1.type=state
UVM_INFO ex4-16_uvm_factory2.sv(44) @ 0: reporter [INFO2] my_state2.type=new_york
2011年6月3日 星期五
Connecting a Child Export to a Parent Export
Cadence example
此例的連接性
producer.put_port->consumer.put_export->child_consumer.put_export
`include "uvm_pkg.sv"
module test;
import uvm_pkg::*;
`include "uvm_macros.svh"
`include "simple_packet.sv"
typedef class consumer;
class parent_consumer extends uvm_component;
uvm_blocking_put_export #(simple_packet) put_export;
consumer child_consumer_inst;
`uvm_component_utils(parent_consumer)
function new(string name, uvm_component parent);
super.new(name, parent);
put_export = new("put_export", this);
child_consumer_inst= new("child_consumer_inst", this);
endfunction
virtual function void connect();
put_export.connect(child_consumer_inst.put_export);
endfunction : connect
endclass : parent_consumer
class producer extends uvm_component;
uvm_blocking_put_port #(simple_packet) put_port;
`uvm_component_utils_begin(producer)
`uvm_component_utils_end
function new(string name, uvm_component parent);
super.new(name, parent);
put_port = new("put_port", this);
endfunction : new
virtual task run();
simple_packet p;
p = simple_packet::type_id::create("p");
void'(p.randomize());
put_port.put(p);
endtask : run
endclass : producer
class consumer extends uvm_component;
uvm_blocking_put_imp #(simple_packet, consumer) put_export;
`uvm_component_utils(consumer)
function new(string name, uvm_component parent);
super.new(name, parent);
put_export = new("put_export", this);
endfunction : new
task put(simple_packet p);
p.print();
endtask : put
endclass : consumer
class parent_comp extends uvm_component;
producer producer_inst;
parent_consumer consumer_inst;
`uvm_component_utils(parent_comp)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction : new
function void build();
super.build();
producer_inst = producer::type_id::create("producer_inst", null);
consumer_inst = parent_consumer::type_id::create("consumer_inst", null);
endfunction : build
function void connect();
super.connect();
producer_inst.put_port.connect(consumer_inst.put_export);
endfunction : connect
function void end_of_elaboration();
super.end_of_elaboration();
this.print();
endfunction : end_of_elaboration
endclass : parent_comp
parent_comp pc = parent_comp::type_id::create("pc", null);
initial begin
fork
run_test();
#100 global_stop_request();
join
end
endmodule : test
此例的連接性
producer.put_port->consumer.put_export->child_consumer.put_export
`include "uvm_pkg.sv"
module test;
import uvm_pkg::*;
`include "uvm_macros.svh"
`include "simple_packet.sv"
typedef class consumer;
class parent_consumer extends uvm_component;
uvm_blocking_put_export #(simple_packet) put_export;
consumer child_consumer_inst;
`uvm_component_utils(parent_consumer)
function new(string name, uvm_component parent);
super.new(name, parent);
put_export = new("put_export", this);
child_consumer_inst= new("child_consumer_inst", this);
endfunction
virtual function void connect();
put_export.connect(child_consumer_inst.put_export);
endfunction : connect
endclass : parent_consumer
class producer extends uvm_component;
uvm_blocking_put_port #(simple_packet) put_port;
`uvm_component_utils_begin(producer)
`uvm_component_utils_end
function new(string name, uvm_component parent);
super.new(name, parent);
put_port = new("put_port", this);
endfunction : new
virtual task run();
simple_packet p;
p = simple_packet::type_id::create("p");
void'(p.randomize());
put_port.put(p);
endtask : run
endclass : producer
class consumer extends uvm_component;
uvm_blocking_put_imp #(simple_packet, consumer) put_export;
`uvm_component_utils(consumer)
function new(string name, uvm_component parent);
super.new(name, parent);
put_export = new("put_export", this);
endfunction : new
task put(simple_packet p);
p.print();
endtask : put
endclass : consumer
class parent_comp extends uvm_component;
producer producer_inst;
parent_consumer consumer_inst;
`uvm_component_utils(parent_comp)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction : new
function void build();
super.build();
producer_inst = producer::type_id::create("producer_inst", null);
consumer_inst = parent_consumer::type_id::create("consumer_inst", null);
endfunction : build
function void connect();
super.connect();
producer_inst.put_port.connect(consumer_inst.put_export);
endfunction : connect
function void end_of_elaboration();
super.end_of_elaboration();
this.print();
endfunction : end_of_elaboration
endclass : parent_comp
parent_comp pc = parent_comp::type_id::create("pc", null);
initial begin
fork
run_test();
#100 global_stop_request();
join
end
endmodule : test
Connecting a Child Port to a Parent Port
Cadence example
此例的連接性
child_producer.put_port->parent_producer.put_port->consumer.put_export.
`include "uvm_pkg.sv"
module test;
import uvm_pkg::*;
`include "uvm_macros.svh"
`include "simple_packet.sv"
typedef class producer;
class parent_producer extends uvm_component;
uvm_blocking_put_port #(simple_packet) put_port;
producer child_producer_inst;
`uvm_component_utils(parent_producer)
function new(string name, uvm_component parent);
super.new(name, parent);
put_port = new("put_port", this);
child_producer_inst = new("child_producer_inst", this);
endfunction : new
function void connect();
super.connect();
child_producer_inst.put_port.connect(put_port);
endfunction : connect
endclass : parent_producer
class producer extends uvm_component;
uvm_blocking_put_port #(simple_packet) put_port;
`uvm_component_utils_begin(producer)
`uvm_component_utils_end
function new(string name, uvm_component parent);
super.new(name, parent);
put_port = new("put_port", this);
endfunction : new
virtual task run();
simple_packet p;
p = simple_packet::type_id::create("p");
void'(p.randomize());
put_port.put(p);
endtask : run
endclass : producer
class consumer extends uvm_component;
uvm_blocking_put_imp #(simple_packet, consumer) put_export;
`uvm_component_utils(consumer)
function new(string name, uvm_component parent);
super.new(name, parent);
put_export = new("put_export", this);
endfunction : new
task put(simple_packet p);
p.print();
endtask : put
endclass : consumer
class parent_comp extends uvm_component;
parent_producer producer_inst;
consumer consumer_inst;
`uvm_component_utils(parent_comp)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction : new
function void build();
super.build();
producer_inst = parent_producer::type_id::create("producer_inst", null);
consumer_inst = consumer::type_id::create("consumer_inst", null);
endfunction : build
function void connect();
super.connect();
producer_inst.put_port.connect(consumer_inst.put_export);
endfunction : connect
function void end_of_elaboration();
super.end_of_elaboration();
this.print();
endfunction : end_of_elaboration
endclass : parent_comp
parent_comp pc = parent_comp::type_id::create("pc", null);
initial begin
fork
run_test();
#100 global_stop_request();
join
end
endmodule : test
class simple_packet extends uvm_sequence_item;
rand bit [1:0] addr;
rand bit [5:0] length;
rand bit [7:0] payload [];
// Constraints
constraint c_payload { payload.size == length; }
constraint c_length { length >0; length <= 63; }
`uvm_object_utils_begin(simple_packet)
`uvm_field_int(addr, UVM_DEFAULT)
`uvm_field_int(length, UVM_DEFAULT)
`uvm_field_array_int(payload, UVM_DEFAULT)
`uvm_object_utils_end
function new(string name="simple_packet");
super.new(name);
endfunction : new
endclass : simple_packet
此例的連接性
child_producer.put_port->parent_producer.put_port->consumer.put_export.
`include "uvm_pkg.sv"
module test;
import uvm_pkg::*;
`include "uvm_macros.svh"
`include "simple_packet.sv"
typedef class producer;
class parent_producer extends uvm_component;
uvm_blocking_put_port #(simple_packet) put_port;
producer child_producer_inst;
`uvm_component_utils(parent_producer)
function new(string name, uvm_component parent);
super.new(name, parent);
put_port = new("put_port", this);
child_producer_inst = new("child_producer_inst", this);
endfunction : new
function void connect();
super.connect();
child_producer_inst.put_port.connect(put_port);
endfunction : connect
endclass : parent_producer
class producer extends uvm_component;
uvm_blocking_put_port #(simple_packet) put_port;
`uvm_component_utils_begin(producer)
`uvm_component_utils_end
function new(string name, uvm_component parent);
super.new(name, parent);
put_port = new("put_port", this);
endfunction : new
virtual task run();
simple_packet p;
p = simple_packet::type_id::create("p");
void'(p.randomize());
put_port.put(p);
endtask : run
endclass : producer
class consumer extends uvm_component;
uvm_blocking_put_imp #(simple_packet, consumer) put_export;
`uvm_component_utils(consumer)
function new(string name, uvm_component parent);
super.new(name, parent);
put_export = new("put_export", this);
endfunction : new
task put(simple_packet p);
p.print();
endtask : put
endclass : consumer
class parent_comp extends uvm_component;
parent_producer producer_inst;
consumer consumer_inst;
`uvm_component_utils(parent_comp)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction : new
function void build();
super.build();
producer_inst = parent_producer::type_id::create("producer_inst", null);
consumer_inst = consumer::type_id::create("consumer_inst", null);
endfunction : build
function void connect();
super.connect();
producer_inst.put_port.connect(consumer_inst.put_export);
endfunction : connect
function void end_of_elaboration();
super.end_of_elaboration();
this.print();
endfunction : end_of_elaboration
endclass : parent_comp
parent_comp pc = parent_comp::type_id::create("pc", null);
initial begin
fork
run_test();
#100 global_stop_request();
join
end
endmodule : test
class simple_packet extends uvm_sequence_item;
rand bit [1:0] addr;
rand bit [5:0] length;
rand bit [7:0] payload [];
// Constraints
constraint c_payload { payload.size == length; }
constraint c_length { length >0; length <= 63; }
`uvm_object_utils_begin(simple_packet)
`uvm_field_int(addr, UVM_DEFAULT)
`uvm_field_int(length, UVM_DEFAULT)
`uvm_field_array_int(payload, UVM_DEFAULT)
`uvm_object_utils_end
function new(string name="simple_packet");
super.new(name);
endfunction : new
endclass : simple_packet
2011年6月2日 星期四
Configuration Mechanism for Coverage
Cadence example
`include "uvm_pkg.sv"
module test;
import uvm_pkg::*;
`include "uvm_macros.svh"
typedef enum bit [2:0] {FLORIDA, NEW_YORK, GEORGIA, CALIFORNIA, MICHIGAN,
TEXAS, MARYLAND, CONNECTICUT} state_name_enum;
class state extends uvm_component;
bit coverage_enable = 1;
state_name_enum state_name = FLORIDA;
`uvm_component_utils_begin(state)
`uvm_field_enum(state_name_enum, state_name, UVM_DEFAULT )
`uvm_field_int(coverage_enable, UVM_DEFAULT | UVM_READONLY )
`uvm_component_utils_end
covergroup state_cg;
coverpoint state_name;
endgroup : state_cg
function new(string name="state", uvm_component parent);
super.new(name, parent);
void'(get_config_int("coverage_enable", coverage_enable));
if (coverage_enable) begin
state_cg = new();
end
endfunction : new
function void end_of_elaboration();
if (coverage_enable)
state_cg.sample();
this.print();
endfunction : end_of_elaboration
endclass : state
state my_state;
initial begin
set_config_int("my_state", "state_name", NEW_YORK);
set_config_int("my_state", "coverage_enable", 0);
my_state = state::type_id::create("my_state", null);
fork
run_test();
#100 $finish;
join
end
endmodule : test
`include "uvm_pkg.sv"
module test;
import uvm_pkg::*;
`include "uvm_macros.svh"
typedef enum bit [2:0] {FLORIDA, NEW_YORK, GEORGIA, CALIFORNIA, MICHIGAN,
TEXAS, MARYLAND, CONNECTICUT} state_name_enum;
class state extends uvm_component;
bit coverage_enable = 1;
state_name_enum state_name = FLORIDA;
`uvm_component_utils_begin(state)
`uvm_field_enum(state_name_enum, state_name, UVM_DEFAULT )
`uvm_field_int(coverage_enable, UVM_DEFAULT | UVM_READONLY )
`uvm_component_utils_end
covergroup state_cg;
coverpoint state_name;
endgroup : state_cg
function new(string name="state", uvm_component parent);
super.new(name, parent);
void'(get_config_int("coverage_enable", coverage_enable));
if (coverage_enable) begin
state_cg = new();
end
endfunction : new
function void end_of_elaboration();
if (coverage_enable)
state_cg.sample();
this.print();
endfunction : end_of_elaboration
endclass : state
state my_state;
initial begin
set_config_int("my_state", "state_name", NEW_YORK);
set_config_int("my_state", "coverage_enable", 0);
my_state = state::type_id::create("my_state", null);
fork
run_test();
#100 $finish;
join
end
endmodule : test
uvm_component Simulation Phases and Hierarchy Methods
Cadence example
`include "uvm_pkg.sv"
module test;
import uvm_pkg::*;
`include "uvm_macros.svh"
class street extends uvm_component;
`uvm_component_utils(street)
function new(string name="street", uvm_component parent);
super.new(name, parent);
endfunction : new
task run ();
`uvm_info("INFO1", "I vacationed here in 2010", UVM_LOW)
endtask : run
endclass : street
class city extends uvm_component;
street Main_St;
`uvm_component_utils(city)
function new(string name="city", uvm_component parent);
super.new(name, parent);
endfunction : new
function void build();
super.build();
Main_St = street::type_id::create("Main_St", this);
endfunction : build
task run ();
uvm_component child, parent;
string pr, ch;
child=get_child("Main_St");
parent=get_parent();
pr = parent.get_full_name();
ch = child.get_name();
`uvm_info(get_type_name(), $psprintf("Parent:%s Child:%s", pr, ch), UVM_LOW)
endtask : run
endclass : city
class state extends uvm_component;
city Capital_city;
`uvm_component_utils(state)
function new(string name="state", uvm_component parent);
super.new(name, parent);
endfunction : new
function void build();
super.build();
Capital_city = city::type_id::create("Capital_city", this);
endfunction : build
function void end_of_elaboration();
this.print();
endfunction : end_of_elaboration
endclass : state
state Florida = state::type_id::create("Florida", null);
state New_York = state::type_id::create("New_York", null);
// Start UVM Phases
initial run_test();
initial #100 global_stop_request();
endmodule : test
`include "uvm_pkg.sv"
module test;
import uvm_pkg::*;
`include "uvm_macros.svh"
class street extends uvm_component;
`uvm_component_utils(street)
function new(string name="street", uvm_component parent);
super.new(name, parent);
endfunction : new
task run ();
`uvm_info("INFO1", "I vacationed here in 2010", UVM_LOW)
endtask : run
endclass : street
class city extends uvm_component;
street Main_St;
`uvm_component_utils(city)
function new(string name="city", uvm_component parent);
super.new(name, parent);
endfunction : new
function void build();
super.build();
Main_St = street::type_id::create("Main_St", this);
endfunction : build
task run ();
uvm_component child, parent;
string pr, ch;
child=get_child("Main_St");
parent=get_parent();
pr = parent.get_full_name();
ch = child.get_name();
`uvm_info(get_type_name(), $psprintf("Parent:%s Child:%s", pr, ch), UVM_LOW)
endtask : run
endclass : city
class state extends uvm_component;
city Capital_city;
`uvm_component_utils(state)
function new(string name="state", uvm_component parent);
super.new(name, parent);
endfunction : new
function void build();
super.build();
Capital_city = city::type_id::create("Capital_city", this);
endfunction : build
function void end_of_elaboration();
this.print();
endfunction : end_of_elaboration
endclass : state
state Florida = state::type_id::create("Florida", null);
state New_York = state::type_id::create("New_York", null);
// Start UVM Phases
initial run_test();
initial #100 global_stop_request();
endmodule : test
2011年6月1日 星期三
object automation
Cadence example
uvm_default_tree_printer
要參考Class Reference
還有其它的printer方式
`include "uvm_pkg.sv"
module automation_example;
import uvm_pkg::*;
`include "uvm_macros.svh"
// Include the APB transfer class
`include "apb_transfer.sv"
apb_transfer my_xfer, tx1, tx2, tx3;
initial begin
my_xfer = apb_transfer::type_id::create("my_xfer");
if (!my_xfer.randomize())
`uvm_fatal("RANDFAIL", "can not randomize my_xfer")
tx1 = my_xfer; // tx1 and my_xfer share the same memory
tx2 = apb_transfer::type_id::create("tx2");
tx2.copy(tx1); // copies fields from tx1 to tx2
$cast(tx3, tx1.clone()); // creates a new apb_transfer and copy all
// fields from tx1 to tx3
if (!tx3.compare(tx2))
`uvm_error("CompareFailed", "The comparison failed")
my_xfer.print(); // Prints my_xfer in a table format
my_xfer.print(uvm_default_tree_printer); // Prints in "tree" format
tx2.print(); // Prints tx2 in a table format
tx2.print(uvm_default_tree_printer); // Prints in "tree" format
$display ("\n\ntx3 == my_xfer\n\n");
tx3.print(); // Prints tx3 in a table format
tx3.print(uvm_default_tree_printer); // Prints in "tree" format
end
endmodule : automation_example
typedef enum bit {APB_READ, APB_WRITE} apb_direction_enum;
class apb_transfer extends uvm_sequence_item;
rand bit [31:0] addr;
rand bit [31:0] data;
rand apb_direction_enum direction;
// Control field - does not translate into signal data
rand int unsigned transmit_delay;
// Constraint
constraint c_transmit_delay { transmit_delay inside {[0:15]}; }
// UVM automation macros for data items
`uvm_object_utils_begin(apb_transfer)
`uvm_field_int(addr, UVM_DEFAULT)
`uvm_field_int(data, UVM_DEFAULT)
`uvm_field_enum(apb_direction_enum, direction, UVM_DEFAULT)
`uvm_field_int(transmit_delay, UVM_DEFAULT | UVM_NOCOMPARE)
`uvm_object_utils_end
// Constructor - required UVM syntax
function new (string name = "apb_transfer");
super.new(name);
endfunction
endclass : apb_transfer
uvm_default_tree_printer
要參考Class Reference
還有其它的printer方式
`include "uvm_pkg.sv"
module automation_example;
import uvm_pkg::*;
`include "uvm_macros.svh"
// Include the APB transfer class
`include "apb_transfer.sv"
apb_transfer my_xfer, tx1, tx2, tx3;
initial begin
my_xfer = apb_transfer::type_id::create("my_xfer");
if (!my_xfer.randomize())
`uvm_fatal("RANDFAIL", "can not randomize my_xfer")
tx1 = my_xfer; // tx1 and my_xfer share the same memory
tx2 = apb_transfer::type_id::create("tx2");
tx2.copy(tx1); // copies fields from tx1 to tx2
$cast(tx3, tx1.clone()); // creates a new apb_transfer and copy all
// fields from tx1 to tx3
if (!tx3.compare(tx2))
`uvm_error("CompareFailed", "The comparison failed")
my_xfer.print(); // Prints my_xfer in a table format
my_xfer.print(uvm_default_tree_printer); // Prints in "tree" format
tx2.print(); // Prints tx2 in a table format
tx2.print(uvm_default_tree_printer); // Prints in "tree" format
$display ("\n\ntx3 == my_xfer\n\n");
tx3.print(); // Prints tx3 in a table format
tx3.print(uvm_default_tree_printer); // Prints in "tree" format
end
endmodule : automation_example
typedef enum bit {APB_READ, APB_WRITE} apb_direction_enum;
class apb_transfer extends uvm_sequence_item;
rand bit [31:0] addr;
rand bit [31:0] data;
rand apb_direction_enum direction;
// Control field - does not translate into signal data
rand int unsigned transmit_delay;
// Constraint
constraint c_transmit_delay { transmit_delay inside {[0:15]}; }
// UVM automation macros for data items
`uvm_object_utils_begin(apb_transfer)
`uvm_field_int(addr, UVM_DEFAULT)
`uvm_field_int(data, UVM_DEFAULT)
`uvm_field_enum(apb_direction_enum, direction, UVM_DEFAULT)
`uvm_field_int(transmit_delay, UVM_DEFAULT | UVM_NOCOMPARE)
`uvm_object_utils_end
// Constructor - required UVM syntax
function new (string name = "apb_transfer");
super.new(name);
endfunction
endclass : apb_transfer
field automation macros
Cadence example
//------------------------------------------------------------------------------
// CLASS: packet_header - length, addr
//------------------------------------------------------------------------------
class packet_header extends uvm_sequence_item;
rand bit [2:0] length;
rand bit [1:0] addr;
// UVM macros for built-in automation - These declarations enable automation
// of the data_item fields and implement create() and get_type_name()
`uvm_object_utils_begin(packet_header)
`uvm_field_int(length, UVM_ALL_ON)
`uvm_field_int(addr, UVM_ALL_ON)
`uvm_object_utils_end
// Constructor - required syntax for UVM automation and utilities
function new (string name="packet_header");
super.new(name);
endfunction
endclass : packet_header
//------------------------------------------------------------------------------
typedef enum bit { BAD_PARITY, GOOD_PARITY } parity_e;
//------------------------------------------------------------------------------
// CLASS: yapp_packet
//------------------------------------------------------------------------------
class yapp_packet extends uvm_sequence_item;
// Physical Data
rand packet_header header; // packet headder class contains addr, length
rand bit [7:0] payload []; // dynamic array
bit [7:0] parity; // calculated in post_randomize()
// Control Knobs
rand parity_e parity_type;
rand int packet_delay;
// Default Constraints
constraint c_default_length { header.length > 0; header.length < 8; }
constraint c_payload_size { header.length == payload.size(); }
constraint c_packet_delay { packet_delay inside {[0:10]}; }
// UVM macros for built-in automation - These declarations enable automation
// of the data_item fields and implement create() and get_type_name()
`uvm_object_utils_begin(yapp_packet)
`uvm_field_object(header, UVM_ALL_ON)
`uvm_field_array_int(payload, UVM_ALL_ON)
`uvm_field_int(parity, UVM_ALL_ON)
`uvm_field_enum(parity_e, parity_type, UVM_ALL_ON)
`uvm_field_int(packet_delay, UVM_ALL_ON | UVM_DEC | UVM_NOCOMPARE)
`uvm_object_utils_end
function new (string name = "yapp_packet");
super.new(name);
header = packet_header::type_id::create("header"); // allocation
endfunction : new
// This method calculates the parity over the header and payload
function bit [7:0] calc_parity();
calc_parity = {header.length, header.addr};
for (int i=0; i<header.length; i++)
calc_parity = calc_parity ^ payload[i];
endfunction : calc_parity
// post_randomize() - calculates parity
function void post_randomize();
if (parity_type == GOOD_PARITY)
parity = calc_parity();
else do
parity = $urandom;
while( parity == calc_parity());
endfunction : post_randomize
endclass : yapp_packet
module test;
yapp_packet packet;
initial begin
packet = new();
repeat (3) begin
void'(packet.randomize());
if (packet.packet_delay >0) begin
for (int i=0;i
#1;
end
end
packet.print();
$display("time = %t", $time);
end
end
endmodule : test
//------------------------------------------------------------------------------
// CLASS: packet_header - length, addr
//------------------------------------------------------------------------------
class packet_header extends uvm_sequence_item;
rand bit [2:0] length;
rand bit [1:0] addr;
// UVM macros for built-in automation - These declarations enable automation
// of the data_item fields and implement create() and get_type_name()
`uvm_object_utils_begin(packet_header)
`uvm_field_int(length, UVM_ALL_ON)
`uvm_field_int(addr, UVM_ALL_ON)
`uvm_object_utils_end
// Constructor - required syntax for UVM automation and utilities
function new (string name="packet_header");
super.new(name);
endfunction
endclass : packet_header
//------------------------------------------------------------------------------
typedef enum bit { BAD_PARITY, GOOD_PARITY } parity_e;
//------------------------------------------------------------------------------
// CLASS: yapp_packet
//------------------------------------------------------------------------------
class yapp_packet extends uvm_sequence_item;
// Physical Data
rand packet_header header; // packet headder class contains addr, length
rand bit [7:0] payload []; // dynamic array
bit [7:0] parity; // calculated in post_randomize()
// Control Knobs
rand parity_e parity_type;
rand int packet_delay;
// Default Constraints
constraint c_default_length { header.length > 0; header.length < 8; }
constraint c_payload_size { header.length == payload.size(); }
constraint c_packet_delay { packet_delay inside {[0:10]}; }
// UVM macros for built-in automation - These declarations enable automation
// of the data_item fields and implement create() and get_type_name()
`uvm_object_utils_begin(yapp_packet)
`uvm_field_object(header, UVM_ALL_ON)
`uvm_field_array_int(payload, UVM_ALL_ON)
`uvm_field_int(parity, UVM_ALL_ON)
`uvm_field_enum(parity_e, parity_type, UVM_ALL_ON)
`uvm_field_int(packet_delay, UVM_ALL_ON | UVM_DEC | UVM_NOCOMPARE)
`uvm_object_utils_end
function new (string name = "yapp_packet");
super.new(name);
header = packet_header::type_id::create("header"); // allocation
endfunction : new
// This method calculates the parity over the header and payload
function bit [7:0] calc_parity();
calc_parity = {header.length, header.addr};
for (int i=0; i<header.length; i++)
calc_parity = calc_parity ^ payload[i];
endfunction : calc_parity
// post_randomize() - calculates parity
function void post_randomize();
if (parity_type == GOOD_PARITY)
parity = calc_parity();
else do
parity = $urandom;
while( parity == calc_parity());
endfunction : post_randomize
endclass : yapp_packet
module test;
yapp_packet packet;
initial begin
packet = new();
repeat (3) begin
void'(packet.randomize());
if (packet.packet_delay >0) begin
for (int i=0;i
#1;
end
end
packet.print();
$display("time = %t", $time);
end
end
endmodule : test
2011年5月31日 星期二
一個使用UVM的最簡單Class
From Cadence
`include "uvm_pkg.sv"
`include "uvm_macros.svh"
import uvm_pkg::*;
//------------------------------------------------------------------------------
// CLASS: apb_transfer
//------------------------------------------------------------------------------
typedef enum bit {APB_READ, APB_WRITE} apb_direction_enum;
class apb_transfer extends uvm_sequence_item;
rand bit [31:0] addr;
rand bit [31:0] data;
rand apb_direction_enum direction;
// Control field - does not translate into signal data
rand int unsigned transmit_delay;
// UVM automation macros for data items
`uvm_object_utils_begin(apb_transfer)
`uvm_field_int(addr, UVM_DEFAULT)
`uvm_field_int(data, UVM_DEFAULT)
`uvm_field_enum(apb_direction_enum, direction, UVM_DEFAULT)
`uvm_field_int(transmit_delay, UVM_DEFAULT | UVM_NOCOMPARE)
`uvm_object_utils_end
// Constructor - required UVM syntax
function new (string name = "apb_transfer");
super.new(name);
endfunction
endclass : apb_transfer
module test;
apb_transfer transfer;
initial begin
transfer = new();
repeat (3) begin
void'(transfer.randomize());
transfer.print();
end
end
endmodule : test
`include "uvm_pkg.sv"
`include "uvm_macros.svh"
import uvm_pkg::*;
//------------------------------------------------------------------------------
// CLASS: apb_transfer
//------------------------------------------------------------------------------
typedef enum bit {APB_READ, APB_WRITE} apb_direction_enum;
class apb_transfer extends uvm_sequence_item;
rand bit [31:0] addr;
rand bit [31:0] data;
rand apb_direction_enum direction;
// Control field - does not translate into signal data
rand int unsigned transmit_delay;
// UVM automation macros for data items
`uvm_object_utils_begin(apb_transfer)
`uvm_field_int(addr, UVM_DEFAULT)
`uvm_field_int(data, UVM_DEFAULT)
`uvm_field_enum(apb_direction_enum, direction, UVM_DEFAULT)
`uvm_field_int(transmit_delay, UVM_DEFAULT | UVM_NOCOMPARE)
`uvm_object_utils_end
// Constructor - required UVM syntax
function new (string name = "apb_transfer");
super.new(name);
endfunction
endclass : apb_transfer
module test;
apb_transfer transfer;
initial begin
transfer = new();
repeat (3) begin
void'(transfer.randomize());
transfer.print();
end
end
endmodule : test
沒有使用UVM的Class
Cadence's example
//------------------------------------------------------------------------------
// CLASS: apb_transfer
//------------------------------------------------------------------------------
typedef enum bit {APB_READ, APB_WRITE} apb_direction_enum;
class apb_transfer;
rand bit [31:0] addr;
rand bit [31:0] data;
rand apb_direction_enum direction;
function void print();
$display("%s transfer: addr=%h data=%h", direction.name(), addr, data);
endfunction : print
endclass : apb_transfer
module test;
apb_transfer transfer;
initial begin
transfer = new();
repeat (3) begin
void'(transfer.randomize());
transfer.print();
end
end
endmodule : test
//------------------------------------------------------------------------------
// CLASS: apb_transfer
//------------------------------------------------------------------------------
typedef enum bit {APB_READ, APB_WRITE} apb_direction_enum;
class apb_transfer;
rand bit [31:0] addr;
rand bit [31:0] data;
rand apb_direction_enum direction;
function void print();
$display("%s transfer: addr=%h data=%h", direction.name(), addr, data);
endfunction : print
endclass : apb_transfer
module test;
apb_transfer transfer;
initial begin
transfer = new();
repeat (3) begin
void'(transfer.randomize());
transfer.print();
end
end
endmodule : test
import package
Cadence's example
package branda_pkg;
typedef enum {RED, BLUE, BLACK, WHITE} color_t;
class sports_car; // note that car is a virtual class
rand color_t color;
virtual function void print();
$display("I'm a %s branda sports car", color.name());
endfunction : print
endclass : sports_car
class m5 extends sports_car;
endclass : m5
endpackage : branda_pkg
package brandz_pkg;
typedef enum {SILVER, GOLD, WHITE} color_t;
class sports_car; // note that car is a virtual class
rand color_t color;
virtual function void print();
$display("I'm a %s brandz sports car", color.name());
endfunction : print
endclass : sports_car
class convertible extends sports_car;
endclass : convertible
endpackage : brandz_pkg
module race;
// 當使用import 之後,裡面的class就好像被include 進來一樣
// 但是,繼承的class或其它變數只能用到同一個package內部的
import branda_pkg::*;
import brandz_pkg::*;
m5 my_m5;
convertible my_convertible;
initial begin
my_m5 = new();
void'(my_m5.randomize());
my_m5.print();
my_convertible = new();
void'(my_convertible.randomize());
my_convertible.print();
end
endmodule : race
package branda_pkg;
typedef enum {RED, BLUE, BLACK, WHITE} color_t;
class sports_car; // note that car is a virtual class
rand color_t color;
virtual function void print();
$display("I'm a %s branda sports car", color.name());
endfunction : print
endclass : sports_car
class m5 extends sports_car;
endclass : m5
endpackage : branda_pkg
package brandz_pkg;
typedef enum {SILVER, GOLD, WHITE} color_t;
class sports_car; // note that car is a virtual class
rand color_t color;
virtual function void print();
$display("I'm a %s brandz sports car", color.name());
endfunction : print
endclass : sports_car
class convertible extends sports_car;
endclass : convertible
endpackage : brandz_pkg
module race;
// 當使用import 之後,裡面的class就好像被include 進來一樣
// 但是,繼承的class或其它變數只能用到同一個package內部的
import branda_pkg::*;
import brandz_pkg::*;
m5 my_m5;
convertible my_convertible;
initial begin
my_m5 = new();
void'(my_m5.randomize());
my_m5.print();
my_convertible = new();
void'(my_convertible.randomize());
my_convertible.print();
end
endmodule : race
2011年5月30日 星期一
class in package
Cadence's example
package branda_pkg;
typedef enum {RED, BLUE, BLACK, WHITE} color_t;
class sports_car; // note that car is a virtual class
rand color_t color;
virtual function void print();
$display("I'm a %s branda sports car", color.name());
endfunction : print
endclass : sports_car
endpackage : branda_pkg
package brandz_pkg;
typedef enum {SILVER, GOLD, WHITE} color_t;
class sports_car; // note that car is a virtual class
rand color_t color;
virtual function void print();
$display("I'm a %s brandz sports car", color.name());
endfunction : print
endclass : sports_car
endpackage : brandz_pkg
module top;
branda_pkg::sports_car my_m5; // use class
brandz_pkg::sports_car my_convertible; // use class
initial begin
my_m5 = new();
void'(my_m5.randomize());
my_m5.print();
my_convertible = new();
void'(my_convertible.randomize());
my_convertible.print();
end
endmodule : top
package branda_pkg;
typedef enum {RED, BLUE, BLACK, WHITE} color_t;
class sports_car; // note that car is a virtual class
rand color_t color;
virtual function void print();
$display("I'm a %s branda sports car", color.name());
endfunction : print
endclass : sports_car
endpackage : branda_pkg
package brandz_pkg;
typedef enum {SILVER, GOLD, WHITE} color_t;
class sports_car; // note that car is a virtual class
rand color_t color;
virtual function void print();
$display("I'm a %s brandz sports car", color.name());
endfunction : print
endclass : sports_car
endpackage : brandz_pkg
module top;
branda_pkg::sports_car my_m5; // use class
brandz_pkg::sports_car my_convertible; // use class
initial begin
my_m5 = new();
void'(my_m5.randomize());
my_m5.print();
my_convertible = new();
void'(my_convertible.randomize());
my_convertible.print();
end
endmodule : top
Parameterized Classes
Cadence 的例子
module top;
class stack #(type T = int); // parameterized class syntax
local T items[$]; //使用Queues
task push( T a );
items.push_front(a); //Systemverilog queues function, inserts the given element at the front of the queue.
endtask
task pop (ref T a);
a = items.pop_back(); //Systemverilog queues function, inserts the given element at the end of the queue.
endtask
endclass
stack int_stack; // default: stack of ints
stack #(bit[9:0]) bit_stack; // stack of 10-bit vectors
stack #(real) real_stack; // stack of reals
int int_value;
bit[9:0] bit_value;
real real_value;
initial begin
int_stack=new(); bit_stack=new(); real_stack=new();
int_stack.push(400);
bit_stack.push('h200);
real_stack.push(40.5);
int_stack.pop(int_value);
bit_stack.pop(bit_value);
real_stack.pop(real_value);
$display("int:%0d bit:%0h real:%g", int_value, bit_value, real_value);
end
endmodule : top
module top;
class stack #(type T = int); // parameterized class syntax
local T items[$]; //使用Queues
task push( T a );
items.push_front(a); //Systemverilog queues function, inserts the given element at the front of the queue.
endtask
task pop (ref T a);
a = items.pop_back(); //Systemverilog queues function, inserts the given element at the end of the queue.
endtask
endclass
stack int_stack; // default: stack of ints
stack #(bit[9:0]) bit_stack; // stack of 10-bit vectors
stack #(real) real_stack; // stack of reals
int int_value;
bit[9:0] bit_value;
real real_value;
initial begin
int_stack=new(); bit_stack=new(); real_stack=new();
int_stack.push(400);
bit_stack.push('h200);
real_stack.push(40.5);
int_stack.pop(int_value);
bit_stack.pop(bit_value);
real_stack.pop(real_value);
$display("int:%0d bit:%0h real:%g", int_value, bit_value, real_value);
end
endmodule : top
2011年5月29日 星期日
static methods in class
Cadence的例子
module top;
typedef enum {RED, BLUE, BLACK, WHITE} color_t;
virtual class car;
static int counter = 0; // shared by all instances
int car_id;
static local function void increment_counter();
counter++;
$display("creating item %0d ...", counter);
endfunction : increment_counter
function new();
increment_counter(); // increment on construction to a new class
car_id = counter;
endfunction : new
endclass : car
virtual class sports_car extends car; // note that car is a virtual class
rand color_t color;
virtual function void print();
$display("Car #%0d: I'm a %s sports car", car_id, color.name());
endfunction : print
endclass : sports_car
class plorsche extends sports_car;
virtual function void print();
$display("Car #%0d: I'm a %s plorsche", car_id, color.name());
endfunction : print
endclass : plorsche
class flerrari extends sports_car;
virtual function void print();
$display("Car #%0d: I'm a %s flerrari", car_id, color.name());
endfunction : print
endclass : flerrari
sports_car cars[];
plorsche p1, p2;
flerrari f1, f2;
initial begin
cars = new[4];
p1 = new(); p2 = new();
void'(p1.randomize());
void'(p2.randomize());
f1 = new(); f2 = new();
void'(f1.randomize());
void'(f2.randomize());
$cast(cars[0], p1);
$cast(cars[1], f1);
$cast(cars[2], p2);
$cast(cars[3], f2);
print_all(cars);
end
task print_all(sports_car cars[]);
for (int i=0; i cars[i].print();
endtask : print_all
endmodule : top
module top;
typedef enum {RED, BLUE, BLACK, WHITE} color_t;
virtual class car;
static int counter = 0; // shared by all instances
int car_id;
static local function void increment_counter();
counter++;
$display("creating item %0d ...", counter);
endfunction : increment_counter
function new();
increment_counter(); // increment on construction to a new class
car_id = counter;
endfunction : new
endclass : car
virtual class sports_car extends car; // note that car is a virtual class
rand color_t color;
virtual function void print();
$display("Car #%0d: I'm a %s sports car", car_id, color.name());
endfunction : print
endclass : sports_car
class plorsche extends sports_car;
virtual function void print();
$display("Car #%0d: I'm a %s plorsche", car_id, color.name());
endfunction : print
endclass : plorsche
class flerrari extends sports_car;
virtual function void print();
$display("Car #%0d: I'm a %s flerrari", car_id, color.name());
endfunction : print
endclass : flerrari
sports_car cars[];
plorsche p1, p2;
flerrari f1, f2;
initial begin
cars = new[4];
p1 = new(); p2 = new();
void'(p1.randomize());
void'(p2.randomize());
f1 = new(); f2 = new();
void'(f1.randomize());
void'(f2.randomize());
$cast(cars[0], p1);
$cast(cars[1], f1);
$cast(cars[2], p2);
$cast(cars[3], f2);
print_all(cars);
end
task print_all(sports_car cars[]);
for (int i=0; i
endtask : print_all
endmodule : top
關於uvm_analysis_port
Analysis Ports:
The uvm_analysis_port is a specialized TLM port whose interface consists of a single function, write().
The analysis port contains a list of analysis_exports that are connected to it.
When the component calls analysis_port.write(), the analysis_port cycles through the list and calls the write() method of each connected export.

Analysis Exports
The implementation is write() via an analysis_export.
The uvm_subscriber base component can be used to simplify this operation,
class sub1 #(type T = simple_trans) extends uvm_subscriber #(T);
...
function void write(T t);
// Record coverage information of t.
endfunction
endclass
對比的UVM example 如下
/*
Walk through the test:
A thread *gen* will use an uvm_blocking_put_port to put a transaction.
A *conv* thread will use an uvm_blocking_put_port to put a transaction,an uvm_blocking_get_port to get a transactions, and an uvm_analysis_ port to a writte a transaction through it.
Another thread *bfm* will use an uvm_blocking_get_port to only get the transactions that has been sent by the other threads.
A *listener* will extends the uvm_subscriber, to implement the analysis port write function.
A *producer* component will use uvm_blocking_put_port and uvm_analysis_port and a uvm_tlm_fifo, to connect the *gen* and *conv* put, get and analysis ports through the fifo exports.
A *consumer* component will use uvm_blocking_put export and connect it directly to a fifo export, also will connect the *bfm* get port to the fifo export
At *top* env, the *producer*, *consumer*, and the the *listener* will be connected
*/
`include "uvm_macros.svh"
module test;
import uvm_pkg::*;
//----------------------------------------------------------------------
// class transaction
//----------------------------------------------------------------------
class transaction extends uvm_transaction;
rand int data;
rand int addr;
function string convert2string();
string s;
$sformat(s, "[ addr = %x, data = %x ]", addr, data);
return s;
endfunction
endclass
//----------------------------------------------------------------------
// component gen
//----------------------------------------------------------------------
class gen extends uvm_component;
uvm_blocking_put_port #(transaction) put_port;
function new(string name, uvm_component parent);
super.new(name, parent);
put_port = new("put_port", this);
endfunction
task run;
transaction t;
string msg;
for(int i=0; i < 20; i++) begin
t = new();
///assert(t.randomize());
/// 此處改成類似DMA的傳輸
t.addr = 32+i*2;
t.data = i*1024;
`uvm_info("gen", $sformatf("sending : %s", t.convert2string()), UVM_MEDIUM)
put_port.put(t);
end
endtask
endclass
//----------------------------------------------------------------------
// componenet conv
//----------------------------------------------------------------------
class conv extends uvm_component;
uvm_blocking_put_port #(transaction) put_port;
uvm_blocking_get_port #(transaction) get_port;
uvm_analysis_port #(transaction) cap;
function new(string name, uvm_component parent);
super.new(name, parent);
put_port = new("put_port", this);
get_port = new("get_port", this);
cap = new("analysis_port", this);
endfunction
task run;
transaction t;
forever begin
get_port.get(t);
cap.write(t); // uvm_analysis_port 呼叫write function,但這個write() is void
put_port.put(t);
end
endtask
endclass
//----------------------------------------------------------------------
// componenet bfm
//----------------------------------------------------------------------
class bfm extends uvm_component;
uvm_blocking_get_port #(transaction) get_port;
function new(string name, uvm_component parent);
super.new(name, parent);
get_port = new("get_port", this);
endfunction
task run;
transaction t;
forever begin
get_port.get(t);
`uvm_info("bfm", $sformatf("receiving: %s", t.convert2string()),UVM_MEDIUM)
end
endtask
endclass
class listener extends uvm_subscriber #(transaction);
function new(string name, uvm_component parent);
super.new(name,parent);
endfunction // new
// 真正的uvm_analysis_port所用到的write()是在此
function void write(input transaction t);
`uvm_info(m_name, $sformatf("Received: %s", t.convert2string()), UVM_MEDIUM)
endfunction // write
endclass // listener
//----------------------------------------------------------------------
// componenet producer
//----------------------------------------------------------------------
// begin codeblock producer
class producer extends uvm_component;
uvm_blocking_put_port #(transaction) put_port;
uvm_analysis_port #(transaction) pap;
gen g;
conv c;
uvm_tlm_fifo #(transaction) f;
function new(string name, uvm_component parent);
super.new(name, parent);
put_port = new("put_port", this);
pap = new("analysis_port", this);
g = new("gen", this);
c = new("conv", this);
f = new("fifo", this);
endfunction
function void connect();
g.put_port.connect(f.blocking_put_export); // A
c.get_port.connect(f.blocking_get_export); // B
c.put_port.connect(put_port); // C
c.cap.connect(pap); //第一次analysis_port連結,此時為port對port
endfunction
endclass
//----------------------------------------------------------------------
// componenet consumer
//----------------------------------------------------------------------
class consumer extends uvm_component;
uvm_blocking_put_export #(transaction) put_export;
bfm b;
uvm_tlm_fifo #(transaction) f;
function new(string name, uvm_component parent);
super.new(name, parent);
put_export = new("put_export", this);
f = new("fifo", this);
b = new("bfm", this);
endfunction
function void connect();
put_export.connect(f.blocking_put_export);
b.get_port.connect(f.blocking_get_export);
endfunction
endclass
//----------------------------------------------------------------------
// componenet top
//----------------------------------------------------------------------
class top extends uvm_env;
producer p;
consumer c;
listener l;
function new(string name, uvm_component parent);
super.new(name, parent);
p = new("producer", this);
c = new("consumer", this);
l = new("listener", this);
// Connections may also be done in the constructor, if you wish
p.put_port.connect(c.put_export);
p.pap.connect(l.analysis_export); //這是第二次的analysis_port連結,此時連結到了uvm_subscriber
endfunction
task run;
begin
end
endtask
endclass
//----------------------------------------------------------------------
// environment env
//----------------------------------------------------------------------
class env extends uvm_env;
top t;
function new(string name = "env");
super.new(name);
t = new("top", this);
endfunction
task run;
#1000;
global_stop_request();
endtask
endclass
//----------------------------------------------------------------------
// module test
//----------------------------------------------------------------------
env e;
initial begin
e = new("e");
run_test();
end
endmodule // test
The uvm_analysis_port is a specialized TLM port whose interface consists of a single function, write().
The analysis port contains a list of analysis_exports that are connected to it.
When the component calls analysis_port.write(), the analysis_port cycles through the list and calls the write() method of each connected export.

Analysis Exports
The implementation is write() via an analysis_export.
The uvm_subscriber base component can be used to simplify this operation,
class sub1 #(type T = simple_trans) extends uvm_subscriber #(T);
...
function void write(T t);
// Record coverage information of t.
endfunction
endclass
對比的UVM example 如下
/*
Walk through the test:
A thread *gen* will use an uvm_blocking_put_port to put a transaction.
A *conv* thread will use an uvm_blocking_put_port to put a transaction,an uvm_blocking_get_port to get a transactions, and an uvm_analysis_ port to a writte a transaction through it.
Another thread *bfm* will use an uvm_blocking_get_port to only get the transactions that has been sent by the other threads.
A *listener* will extends the uvm_subscriber, to implement the analysis port write function.
A *producer* component will use uvm_blocking_put_port and uvm_analysis_port and a uvm_tlm_fifo, to connect the *gen* and *conv* put, get and analysis ports through the fifo exports.
A *consumer* component will use uvm_blocking_put export and connect it directly to a fifo export, also will connect the *bfm* get port to the fifo export
At *top* env, the *producer*, *consumer*, and the the *listener* will be connected
*/
`include "uvm_macros.svh"
module test;
import uvm_pkg::*;
//----------------------------------------------------------------------
// class transaction
//----------------------------------------------------------------------
class transaction extends uvm_transaction;
rand int data;
rand int addr;
function string convert2string();
string s;
$sformat(s, "[ addr = %x, data = %x ]", addr, data);
return s;
endfunction
endclass
//----------------------------------------------------------------------
// component gen
//----------------------------------------------------------------------
class gen extends uvm_component;
uvm_blocking_put_port #(transaction) put_port;
function new(string name, uvm_component parent);
super.new(name, parent);
put_port = new("put_port", this);
endfunction
task run;
transaction t;
string msg;
for(int i=0; i < 20; i++) begin
t = new();
///assert(t.randomize());
/// 此處改成類似DMA的傳輸
t.addr = 32+i*2;
t.data = i*1024;
`uvm_info("gen", $sformatf("sending : %s", t.convert2string()), UVM_MEDIUM)
put_port.put(t);
end
endtask
endclass
//----------------------------------------------------------------------
// componenet conv
//----------------------------------------------------------------------
class conv extends uvm_component;
uvm_blocking_put_port #(transaction) put_port;
uvm_blocking_get_port #(transaction) get_port;
uvm_analysis_port #(transaction) cap;
function new(string name, uvm_component parent);
super.new(name, parent);
put_port = new("put_port", this);
get_port = new("get_port", this);
cap = new("analysis_port", this);
endfunction
task run;
transaction t;
forever begin
get_port.get(t);
cap.write(t); // uvm_analysis_port 呼叫write function,但這個write() is void
put_port.put(t);
end
endtask
endclass
//----------------------------------------------------------------------
// componenet bfm
//----------------------------------------------------------------------
class bfm extends uvm_component;
uvm_blocking_get_port #(transaction) get_port;
function new(string name, uvm_component parent);
super.new(name, parent);
get_port = new("get_port", this);
endfunction
task run;
transaction t;
forever begin
get_port.get(t);
`uvm_info("bfm", $sformatf("receiving: %s", t.convert2string()),UVM_MEDIUM)
end
endtask
endclass
class listener extends uvm_subscriber #(transaction);
function new(string name, uvm_component parent);
super.new(name,parent);
endfunction // new
// 真正的uvm_analysis_port所用到的write()是在此
function void write(input transaction t);
`uvm_info(m_name, $sformatf("Received: %s", t.convert2string()), UVM_MEDIUM)
endfunction // write
endclass // listener
//----------------------------------------------------------------------
// componenet producer
//----------------------------------------------------------------------
// begin codeblock producer
class producer extends uvm_component;
uvm_blocking_put_port #(transaction) put_port;
uvm_analysis_port #(transaction) pap;
gen g;
conv c;
uvm_tlm_fifo #(transaction) f;
function new(string name, uvm_component parent);
super.new(name, parent);
put_port = new("put_port", this);
pap = new("analysis_port", this);
g = new("gen", this);
c = new("conv", this);
f = new("fifo", this);
endfunction
function void connect();
g.put_port.connect(f.blocking_put_export); // A
c.get_port.connect(f.blocking_get_export); // B
c.put_port.connect(put_port); // C
c.cap.connect(pap); //第一次analysis_port連結,此時為port對port
endfunction
endclass
//----------------------------------------------------------------------
// componenet consumer
//----------------------------------------------------------------------
class consumer extends uvm_component;
uvm_blocking_put_export #(transaction) put_export;
bfm b;
uvm_tlm_fifo #(transaction) f;
function new(string name, uvm_component parent);
super.new(name, parent);
put_export = new("put_export", this);
f = new("fifo", this);
b = new("bfm", this);
endfunction
function void connect();
put_export.connect(f.blocking_put_export);
b.get_port.connect(f.blocking_get_export);
endfunction
endclass
//----------------------------------------------------------------------
// componenet top
//----------------------------------------------------------------------
class top extends uvm_env;
producer p;
consumer c;
listener l;
function new(string name, uvm_component parent);
super.new(name, parent);
p = new("producer", this);
c = new("consumer", this);
l = new("listener", this);
// Connections may also be done in the constructor, if you wish
p.put_port.connect(c.put_export);
p.pap.connect(l.analysis_export); //這是第二次的analysis_port連結,此時連結到了uvm_subscriber
endfunction
task run;
begin
end
endtask
endclass
//----------------------------------------------------------------------
// environment env
//----------------------------------------------------------------------
class env extends uvm_env;
top t;
function new(string name = "env");
super.new(name);
t = new("top", this);
endfunction
task run;
#1000;
global_stop_request();
endtask
endclass
//----------------------------------------------------------------------
// module test
//----------------------------------------------------------------------
env e;
initial begin
e = new("e");
run_test();
end
endmodule // test
訂閱:
文章 (Atom)