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