Analysis Layer
- Scoreboard / Subscriber / Monitor / Predictor
- Watch / Observe
- Recognize transactions
- Place the transactions to the analysis ports
- Coverage
- Reporting
- Simulation
- Tests/Transactions -> Drivr -> DUT -> Responder -> TLM models
- Can connect to multiple objects (unlike uvm_put_port)
- Analysis Ports, Exports, Imps
- Port, Export and Imp
Example of Monitor Class
class monitor extends interface_base;
`uvm_component_utils(monitor)
uvm_analysis_port #(mem_data) rspa;
uvm_analysis_port #(mem_req) reqa;
function new (string name = "driver",
uvm_component parent = null);
super.new (name, parent);
endfunction : new
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
reqa = new ("reqa", this);
rspa = new ("rspa", this);
endfunction: build_phase
task run_phase(uvm_phase phase);
mem_req req = new(), c_req;
mem_data rsp = new(), c_rsp;
forever begin : monitor_loop
@(posedge mif.clk);
#UNIT_DELAY;
req.load_data (mif.addr, mif.data, nop);
rsp.load_data (mif.addr, mif.data);
if (mif.wr) req.op = write;
if (mif.rd) req.op = read;
if (req.op != nop) begin
$cast(c_req, req.clone());
reqa.write (c_req);
end
if (mif.rd) begin
$cast (c_rap, rsp.clone());
rspa.write (c_rsp);
end
end : monitor_loop
endtask
endclass : monitor
Create a Subscriber
- Instantiate a "uvm_tlm_analysis_fifo"
- Connect to the analysis_port at the top level
- Use get() to block and take data out of the analysis fifo
Create a Predictor
- It gets a request from the analysis_port connected to the monitor.
- It predicts what response transaction will appear.
class predictor extends uvm_agent;
`uvm_component_utils (predictor)
logic [15:0] mem [2**16-1 : 0];
uvm_tlm_analysis_fifo #(mem_req) reqfifo;
uvm_put_port #(mem_data) rsp_p; // to connect to comparator
mem_data rsp = new();
function new (string name, uvm_component parent);
super.new (name, parent);
endfunction: new
virtual function void build_phase (uvm_phase phase);
super.build_phase(phase);
req_fifo = new("req_fifl", this);
rsp_p = new ("rsp_po", this);
endfunction : build_phase
task run_phase (uvm_phase phase);
mem_data cln;
mem_req req_txn;
forever begin : run_loop
req_fifo.get (req_tx);
case (req_tx.op)
write : mem[req_tx.addr] = req_tx.data;
read : begin : read_op
rsp.load_data (req_tx.addr, mem[req_tx.addr]);
$case (cln, rsp.clong());
rsp_p.put(cln);
end : read_op
endcase
end : run_loop
endtask : run_phase
endclass : predictor
Create a Comparator and a Printer to Report
- It gets a response transaction from the monitor.
- It compares the actual response transaction to the predicted response transaction.
class comparator extends uvm_agent;
`uvm_component_utils (comparator)
uvm_tlm_analysis_fifo #(mem_data) actual_f;
uvm_get_port #(mem_data) predicted_p;
mem_data actual_rsp, predicted_rsp;
function new ...
virtual function void build_phase (uvm_phase phase);
super.build_phase (phase);
actual_f = new ("actual_f", this);
predicted_p = new ("predicted_p", this);
endfunction : build_phase
task run_phase (uvm_phase phase);
forever begin : run_loop
actual_f.get (actual_rsp);
predicted_p.get (predicted_rsp);
if (actual_rsp.comp(predicted_rsp))
uvm_report_info ("run",
$psprintf ("passed: %s",
actual_rsp.convert2string()) );
else
uvm_report_info ("run",
$psprintf ("ERROR: expected: %s does not match actual: %s",
predicted_rsp.convert2string(),
actual_rsp.convert2string()) );
end : run_loop
endtask : run_phase
endclass : comparator
class printer #(type T = mem_data) extends uvm_agent;
`uvm_component_utils (printer#(T))
uvm_tlm_analysis_fifo #(T) a_fifo;
function new ...
virtual function void build_phase (uvm_phase phase);
super.build_phase (phase);
a_fifo = new ("a_fifo", this);
endfunction : build_phase
task run_phase (uvm_phase phase);
forever begin
T data;
a_fifo.get(data);
uvm_report_info ("run", data.convert2string());
end
endtask : run_phase
endclass : printer
class mem_data extends uvm_transaction;
`uvm_object_utils (mem_data)
rand logic [15:0] data;
rand lobic [15:0] addr;
virtual function bit comp (uvm_object rhs);
mem_data RHS;
$cast (RHS, rhs);
return ((RHS.addr == addr) && (RHS.data == data));
endfunction : comp
endclass : mem_data
class mem_req extends mem_data;
...
endclass : mem_req
Top Leven Test Environment
class test_env extends uvm_env;
`uvm_component_utils (test_env)
tester tst;
driver drv;
uvm_tlm_fifo #(mem_req) tester2driv;
printer #(mem_req) req_prt;
printer #(mem_data) rsp_prt;
monitor mon;
predictor pred;
comparator cmp;
uvm_tlm_fifo #(mem_data) pred2cmp;
function new (string name = "tester_env",
uvm_component parent = null );
super.new (name, parent);
endfunction : new
virtual function void build_phase (uvm_phase phase);
super.build_phase (phase);
tst = tester::type_id::create ("tst", this);
drv = driver::type_id::create ("drv", this);
tester2drv = new ("tester2drv");
req_prt = printer#(mem_req)::type_id::create("req_prt", this);
rsp_prt = printer#(mem_data)::type_id::create("rsp_prt", this);
mon = monitor::type_id::create ("mon", this);
pred = predictor::type_id::create ("pred", this);
cmp = comparator;:type_id::create ("cmp", this);
pred2cmp = new("pred2cmp"< this);
endfunction : build_phase
virtual function void connect_phase (uvm_phase phase);
super.connect_phase(phase);
tst.tb_port.connect (tester2drv.put_export);
drv.req_f.connect (tester2drv.get_export);
cmp.predicted_p.connect (pred2cmp.get_export);
pred.rsp_p.connect(pred2cmp.put_export);
mon.req_a.connect (pred.req_fifo.analysis_export);
mon.rsp_a.connect (cmp.req_fifo.analysis_export);
mon.req_a.connect (req_prt.a_fifo.analysis_export);
mon.rsp_a.connect (rsp_prt.a_fifo.analysis_export);
endfunction : connect_phase
endclass : test_env
class bucket #(type T = mem_data) extends printer #(T);
typedef bit_bucket#(T) thistype;
`uvm_component_param_utils (thistype)
function new ...
task run_phase (uvm_phase phase);
forever begin
T data;
a_fifo.get(data);
end
endtask : run_phase
endclass : bucket
class qtest extends uvm_test;
`uvm_component_utils (qtest)
test_env t_env;
function new ...
virtual function void build_phase (uvm_phase phase);
super.build_phase (phase);
printer#(mem_data)::type_id::set_type_override
(bucket#(mem_data)::get_type());
printer#(mem_req)::type_id::set_type_override
(bucket#(mem_data)::get_type());
t_env = test_env::type_id::create ("t_env", this);
endfunction : build_phase
endclass : qtest
No comments:
Post a Comment