This file defines the following OVM consumer components.
OVM Consumers | |
This file defines the following OVM consumer components. | |
ovm_consumer | A generic OVM driver/consumer component that can get transactions from a blocking get port or receive transactions via is blocking put export. |
blocking_get_port | When connected, a consumer process will continually get from the port and call put with the received transaction. |
analysis_port | The put method will also write the transaction to this port for coverage, scoreboarding or other analysis. |
blockling_put_export | Transactions put to this export will be forwarded to the put method, where the received transaction is executed. |
run | If the blocking_get_port is connected, a the run task will continually get from the port and put the transaction for immediate execution. |
put | Called via the <blocking_put_port> or run process, this process “executes” the transaction by printing a message and waiting a bit of time. |
ovm_driver_req | This consumer’s run task will continually retrieve and execute transaction items from this port in one of two ways, chosen randomly ofr -- either using get_next_item/item_done or peek/get. |
seq_item_port | Transactions are fetched from this port. |
ap | Processed requests are published to this port. |
ovm_driver_rsp | This consumer’s run task will continually retrieve, execute, and send back a response in one of three ways, chosen randomly-- either using peek/get, get/delay/put, or get_next_item/item_done. |
seq_item_port | When connected, a consumer process will continually get from the port and call put with the response. |
ovm_subscribe | This consumer receives transactions via the ovm_analysis_export inherited from its ovm_subscriber base class. |
analysis_export | Transactions are received via this inherited analysis export. |
A generic OVM driver/consumer component that can get transactions from a blocking get port or receive transactions via is blocking put export. If the blocking_get_port has been connected, this consumer will continually get and execute transactions from that port. Transactions coming in from the <blocking_get_export> will also be executed. A semaphore is used to arbitrate these two potential sources of transactions.
class ovm_consumer #(type T=int) extends ovm_component; typedef ovm_consumer #(T) this_type; `ovm_component_param_utils(this_type) // Port: blocking_get_port // // When connected, a consumer process will continually get from // the port and call <put> with the received transaction. This // port may be left unconnected. ovm_blocking_get_port #(T) blocking_get_port; // Port: analysis_port // // The <put> method will also write the transaction to this port // for coverage, scoreboarding or other analysis. This port may // be left unconnected. ovm_analysis_port #(T) analysis_port; // Port: blockling_put_export // // Transactions put to this export will be forwarded to the <put> // method, where the received transaction is executed. (In this // case, we merely print the fact a transaction was received.) // A semaphore is used to govern access by both this port and the // active process that putting transaction that were gotten from // the blocking_get_port. ovm_blocking_put_imp #(T,this_type) blocking_put_export; function new(string name, ovm_component parent=null); super.new(name,parent); blocking_put_export = new("blocking_put_export",this); blocking_get_port = new("blocking_get_port",this,0); analysis_port = new("analysis_port",this); endfunction const string type_name = {"ovm_consumer #(",T::type_name,")"}; virtual function string get_type_name(); return type_name; endfunction int num_trans=0; local semaphore lock = new(1); // Task: run // // If the <blocking_get_port> is connected, a the run task will // continually get from the port and <put> the transaction for // immediate execution. If <put> is busy with a transaction // recevied from the blocking_put_export, this process will block // until the transaction is complete. task run(); T tr; if (blocking_get_port.size()<=0) return; forever begin blocking_get_port.get(tr); put(tr); end endtask // Task: put // // Called via the <blocking_put_port> or <run> process, this // process "executes" the transaction by printing a message // and waiting a bit of time. It uses a semaphore to prevent // multiple callers from colliding. task put (T tr); lock.get(); num_trans++; ovm_report_info("recevied", tr.convert2string()); analysis_port.write(tr); #100; lock.put(); endtask endclass
When connected, a consumer process will continually get from the port and call put with the received transaction. This port may be left unconnected.
The put method will also write the transaction to this port for coverage, scoreboarding or other analysis. This port may be left unconnected.
Transactions put to this export will be forwarded to the put method, where the received transaction is executed. (In this case, we merely print the fact a transaction was received.) A semaphore is used to govern access by both this port and the active process that putting transaction that were gotten from the blocking_get_port.
task run()
If the blocking_get_port is connected, a the run task will continually get from the port and put the transaction for immediate execution. If put is busy with a transaction recevied from the blocking_put_export, this process will block until the transaction is complete.
This consumer’s run task will continually retrieve and execute transaction items from this port in one of two ways, chosen randomly ofr -- either using get_next_item/item_done or peek/get.
class ovm_driver_req extends ovm_component; `ovm_component_utils(ovm_driver_req) // Port: seq_item_port // // Transactions are fetched from this port. Although this port is bidirectional, // this component will not return responses. ovm_seq_item_pull_port #(ovm_apb_rw) seq_item_port; // Port: ap // // Processed requests are published to this port. ovm_analysis_port #(ovm_apb_rw) ap; function new(string name, ovm_component parent=null); super.new(name,parent); seq_item_port = new("seq_item_port",this); ap = new("ap",this); endfunction int max_trans = 100; int num_trans = 0; local integer unsigned m[int]; function void mem_model(ref ovm_apb_rw tr); if(tr.cmd == ovm_apb_rw::WR) m[tr.addr] = tr.data; else begin if (m.exists(tr.addr)) tr.data = m[tr.addr]; else tr.data = 'hx; end endfunction task run(); ovm_apb_rw req; ovm_apb_rw pop; while (num_trans < max_trans) begin randcase // get_next_item/item_done 1: begin seq_item_port.get_next_item(req); mem_model(req); #10; seq_item_port.item_done(); ovm_report_info("OVM Consumer", {"via GET_NEXT_ITEM/ITEM_DONE - ", req.convert2string()}); end // peek/get 1: begin seq_item_port.peek(req); mem_model(req); #10; seq_item_port.get(pop); ovm_report_info("OVM Consumer", {"via PEEK/GET - ", req.convert2string()}); end endcase ap.write(req); num_trans++; end endtask endclass
Transactions are fetched from this port. Although this port is bidirectional, this component will not return responses.
Processed requests are published to this port.
This consumer’s run task will continually retrieve, execute, and send back a response in one of three ways, chosen randomly-- either using peek/get, get/delay/put, or get_next_item/item_done.
class ovm_driver_rsp extends ovm_component; `ovm_component_param_utils(ovm_driver_rsp) // Port: seq_item_port // // When connected, a consumer process will continually get from // the port and call <put> with the response. ovm_seq_item_pull_port #(ovm_apb_rw) seq_item_port; function new(string name, ovm_component parent=null); super.new(name,parent); seq_item_port = new("seq_item_port",this); endfunction int max_trans=100; int num_trans=0; local integer unsigned m[int]; function ovm_apb_rw mem_model(ref ovm_apb_rw tr); ovm_apb_rw rsp; $cast(rsp,tr.clone()); if(tr.cmd == ovm_apb_rw::WR) begin m[tr.addr] = tr.data; end else begin if (m.exists(tr.addr)) rsp.data = m[tr.addr]; else rsp.data = 'hx; end rsp.set_id_info(tr); return rsp; endfunction // mem_model task run(); ovm_apb_rw req; ovm_apb_rw rsp; while (num_trans < max_trans) begin randcase // peek/get 1: begin ovm_report_info("OVM Consumer","Using peek/get"); seq_item_port.peek(req); rsp = mem_model(req); seq_item_port.get(req); #10; seq_item_port.put_response(rsp); ovm_report_info("OVM Consumer", { " via PEEK/GET - ", "req=",req.convert2string(), " rsp=", rsp.convert2string() }); end // get-delay-put 1: begin ovm_report_info("OVM Consumer","Using get-delay-put"); seq_item_port.get(req); rsp = mem_model(req); #10 seq_item_port.put_response(rsp); ovm_report_info("OVM Consumer", { " via GET/DELAY/PUT - ", "req=",req.convert2string(), " rsp=", rsp.convert2string() }); end // get_next_item/item_done 1: begin ovm_report_info("OVM Consumer","Using get_next_item/item_done"); seq_item_port.get_next_item(req); rsp = mem_model(req); seq_item_port.item_done(); #10; seq_item_port.put_response(rsp); ovm_report_info("OVM Consumer", { " via GET_NEXT_ITEM/ITEM_DONE/PUT_RESPONSE - ", "req=",req.convert2string(), " rsp=", rsp.convert2string() }); end endcase end endtask endclass
When connected, a consumer process will continually get from the port and call put with the response.
This consumer receives transactions via the ovm_analysis_export inherited from its ovm_subscriber base class.
class ovm_subscribe #(type T=int) extends ovm_subscriber #(T); // Port: analysis_export // // Transactions are received via this inherited analysis export. ovm_analysis_port #(T) ap; function new(string name, ovm_component parent=null); super.new(name, parent); ap = new("ap",this); endfunction virtual function void write(T t); ovm_transaction o_tr; vmm_data v_tr; if ($cast(o_tr,t)) begin ovm_report_info("received_ovm",o_tr.convert2string()); ap.write(t); end else if ($cast(v_tr,t)) ovm_report_info("received_vmm",v_tr.psdisplay()); endfunction endclass
Transactions are received via this inherited analysis export.
Called via the blocking_put_port or run process, this process “executes” the transaction by printing a message and waiting a bit of time.
task put ( T tr )
If the blocking_get_port is connected, a the run task will continually get from the port and put the transaction for immediate execution.
task run()