Can we use ports in driver, inside driver callback method driver's handle?

Hi,

I have requirement of sending a packet from driver class to another component in environment via analysis port. The code looks like

class my_driver extends uvm_driver#(my_packet);

uvm_component_utils(my_driver) uvm_register_cb(my_driver, my_driver_cb)

uvm_analysis_port #(my_packet) my_ap;

new ()

task main_phase(uvm_phase phase);
-----
-----//this task has my_packet handle drv_pkt
`uvm_do_callbacks(my_driver, my_driver_cb, put_pkt(this, drv_pkt));
----
endtask

endclass

class my_driver_cb extends uvm_callback;

new()

task put_packet (uvm_driver driver, my_packet pkt);
driver.my_ap.write(pkt);
endtask

endclass

I am getting an error when executing above code. The error is
No field named my_ap

Is this implementation valid in UVM? If yes, then what could be the reason of failure?

Is there a specific reason you are trying to use a callback to accomplish what you are trying to do? Why don’t you just write each packet out of the analysis port within the driver? The use of callbacks goes against the recommended TLM approach for UVM.

I agree with Chuck that you don’t need the callback.
The specific problem is that your put_packet method had the driver argument of type ‘uvm_driver’ which doesn’t have an analysis_port. The argument type needs to be ‘my_driver’ for your scheme to work.
Now, on to the other problems:
Writing out to an analysis_port from a driver is a trivial exercise that does NOT require callbacks.


task my_driver::run_phase(uvm_phase phase);
  ...
  seq_item_port.get(trans);
  ap.write(trans);
  send_trans_to_bus(trans);
  seq_item_port.item_done();
endtask  

The only value to callbacks is if you want to create some bizarre action to be taken when something happens, and you don’t want to make that part of the component’s original declaration. But callbacks are expensive, cumbersome and complicated, and there’s almost always another way of handling the operation. In your particular case, the callback gives you flexibility in that, if you choose not to register the callback with the driver, then it won’t actually write out the transaction. If you need that flexibility, it’s always easier to use the config_db to tell the driver whether to write to the analysis port or not:


task my_driver::run_phase(uvm_phase phase);
  ...
  uvm_config_db#(driver_cfg_obj)::get(this,"","cfg",cfg);
  seq_item_port.get(trans);
  if(cfg.write_to_ap == 1)
    ap.write(trans);
  send_trans_to_bus(trans);
  seq_item_port.item_done();
endtask  

Also note that I’m showing the driver executing the run_phase, not main_phase. This is because drivers and monitors should only execute the run_phase because throughout the simulation, they are always doing the same operation: getting a transaction and executing it on the bus. If you really want to use main_phase and the other run-time phases (which you never really need to do and we don’t recommend), you should only use them in your test to control which sequences execute at what times - but that’s ultimately what a virtual sequence is for.
Hope this helps,
-Tom

Hi,

Thanks Tom for clarification. (even on the usage of run_phase and main_phase).

My comments:

  1. I agree that UVM TLM does not recommend the use of writing to analysis port in callbacks. However I purposefully do not want to keep ap.write() in the driver. Hence wanted to use callback.

  2. Also an argument callback method is uvm_driver. For this I am typecasting an argument with my_driver type before actually using using it to access my_ap. This has now removed the error.

Further I am seeing a problem that the transaction item is not put in the analysis port. Is it because access of an TLM port is not allowed in callback?? I think callback is just a class and we should be able to access ports in any callback method.

Your comments.

Thanks,
Dipali

  1. Not sure why you think the `uvm_do_callbacks call is preferable to the conditional ap.write I suggested. Callbacks have much more overhead, and you’ve already lost several days trying to get them to work. ;-)
  2. Glad the upcasting helped. There is no restriction to referring to a TLM port in a callback, as long as you have things set up correctly.
    Perhaps you could try turning on +UVM_CB_TRACE_ON as discussed in the Cookbook.

Yeah Tom!
Meanwhile I am going ahead by doing ap.write in my driver class itself. And this is working anyways.

However, this does not fulfill my requirement. I tried turning on +UVM_CB_TRACE_ON, but couldn’t see any messages in the log. I still wonder why the packet is not written into an analysis port!!

What exactly is your requirement? It sounds like you want to conditionally write a packet to the driver’s analysis_port. Is there something more?
By the way, if your requirement is to use a callback in the driver, then I’d respectfully suggest that it’s an overly-specified requirement and you may want to rethink it.

In reply to tfitz:

Sure, I will give a thought on this.

Thanks.