Basic Difference b/w TLM Interface & TLM Channel! People do post al u had learnt!

Hello All,

Sort down the basic diff b/w TLM interface & TLM channel!!!

Many people including me have some fundamental doubts on the TLM Interface and TLM channel!!

Its pretty tough to get through the complete library of ovm_reference which put people into confusion,…

– People kindly post your experience using this TLM interface n channel, please share your practical usage of these, post short code, errors you had come across etc which would be useful to needy ones…

Thanks in adv…
Desperado → Getting catch up with OVM :D

Desperado,

Maybe you better start with the AVM. The AVM cookbook is still on our website, and the libraries are still supported by Questa. It’s a great way to learn the basics of TLM in SystemVerilog. Everything you learn can be applied to the OVM (with the exception of starting and stoping your test - do_test() is depricated in the OVM).

Dave

Hey Dave,

I thought that the TLM section in the OVM User guide, that “we” wrote, was pretty good :). There are enough subtle differences in TLM terminology and implementation between OVM and AVM which will make it more confusing for Desperado. You can see from the code below, which Desperado posted a couple of days ago, that he’s already confused between TLM analysis and TLM get, TLM port vs export vs imp.

// SB code from Desperado
class ctl_score extends ovm_scoreboard;

   logic [7:0] m_me[15];

   ovm_<font color=Red>analysis</font>_export #(ctl_item) <font color=Blue>on_itd_export</font>;
   ovm_<font color=Red>analysis</font>_export #(ctl_item) <font color=Blue>on_ofd_export</font>;

`ovm_component_utils(ctl_scoreboard)
   ...
  task ver_data(input ctl_item mon1, mon2);
   forever
    begin
<font color=Blue>on_itd_export</font>.<font color=Red>get</font>(mon1); // This gets info from first 
....
      end
     else if(mon1.m_ctl_opr0 == RQQ)
      begin
       <font color=Blue>on_ofd_export</font>.<font color=Red>get</font>(mon2); // This gets info from 2nd monit (i.e output
                                           // from dut
       if(m_me[mon2.addr] == mon2.rd_data)
       begin
         //................ MATCH
       end
     else
       begin
         //................MISMATCH
       end
    end
  end
 endtask
endclass

Desperado, I strongly recommend that you study the OVM User guide (NOT the reference guide, which is not intended for that purpose), it will clear up many of your confusions. Another avenue is to talk to you application engineer, he or she might be able to sign you up for a free OVM class.

PS: “we” = Cadence and Mentor (or Mentor and Cadence :) )

Hi phuynh,

– Thank you for your kind words and ways, i read through the user guide and understood that, the necessity of ovm_analysis_port is only when we require to put transaction from one to many user i.e. from monitor(i.e 1st user) to scoreboard , coverage (i.e two users),

– And its enough to use tlm_fifo when we try to put information from two monitor to a single scoreboard or coverage!!

– But have a problem, with its usage of write funcion inside the scoreboard
– Sample code i wrote after reading the information given in threads,

// Connection inside scoreboard using ovm_analysis_imp

`ovm_analysis_imp_decl(_mon1)
`ovm_analysis_imp_decl(_mon2)

class ctl_scoreboard extends ovm_scoreboard;

 virtual ctl_if ctl_if0;

 logic [7:0] m_mem_expected [50];

 ovm_analysis_imp_mon1 #(ctl_item, ctl_scoreboard) on_itd_export;
 ovm_analysis_imp_mon2 #(ctl_item, ctl_scoreboard) on_ofd_export;

`ovm_component_utils(ctl_scoreboard)

 function new(string name, ovm_component parent);
  super.new(name,parent);
 endfunction

 function void assign_vi(virtual interface ctl_if ctl_if0);
  this.ctl_if0 = ctl_if0;
 endfunction: assign_vi

 function void build();
  on_itd_export = new("on_itd_export", this);
  on_ofd_export = new("on_ofd_export", this);
 endfunction

 virtual function write_mon1(ctl_item  on1_item);
  write_mem(on1_item);
 endfunction: write_mon1

 virtual function write_mon2(ctl_item  on2_item);
  read_mem(on2_item);
 endfunction: write_mon2
// connections made inside the environment  (ovm_env)    

ctl_mon_itd0.mitd_port.connect(ctl_scoreboard0.on_itd_export);
ctl_mon_ofd0.mofd_port.connect(ctl_scoreboard0.on_ofd_export);

The problme is :

  • The monitor1, monitor informations input to DUT sends the information to write1, which inturn writes to a temporary memory inside scoreboard.

  • The monitor2, monitors informations output from DUT sends the information to write2, which inturn reads from the temporary memory inside the scoreboard which is been written using the write1 function.

  • Since we shouldnt use any dealy concepts inside the functions, things are not happening in synchronization with the clock…

  • Are there any other way where in can make the scoreboard operate in synch with global clock…

  • Kindly correct me if i am worng any where, dont mistake me…

Thanks a lot again for your encouraging words,

Desperado → In learning phase… :o

One of the things not covered in the OVM User’s guide is ovm_analysis_fifo.

Instead of implementing your own write method, which is a non-blocking function, use the ovm_analysis_fifo’s write method, and then use a blocking get() at the other end of the fifo to synchronize responses from the two analysis ports.

class ctl_scoreboard extends ovm_scoreboard;

  virtual ctl_if ctl_if0;

 logic [7:0] m_mem_expected [50];

 
ovm_analysis_export #(ctl_item) on_itd_export;
ovm_analysis_export #(ctl_item) on_ofd_export;
ovm_analysis_fifo #(ctl_item) on_itd_fifo;
ovm_analysis_fifo #(ctl_item) on_ofd_fifo;

 function void build();
  on_itd_export = new("on_itd_export", this);
  on_ofd_export = new("on_ofd_export", this);
  on_itd_fifo   = new("on_itd_fifo", this);
  on_ofd_fifo   = new("on_ofd_fifo", this);
 endfunction

function void connect;
  on_itd_export,connect(on_itd_fifo.analysis_export);
  on_otd_export,connect(on_otd_fifo.analysis_export);
endfunction

task run;

ctl_item in_h, out_h;
for(;;;) begin // whatever loop is needed
   fork// assuming these come in pairs
      on_itd_fifo.get(in_h);
      on_otd_fifo.get(out_h);
   join
   // now you have both, do what you need to check
...
end
endtask :run

endclass

The example in chapter 8/9 of the AVM cookbook shows the use of an analysis fifo. The AVM cookbook also shows usage of the reporting mechanisms, none of which is in the OVM user guide, and other than the naming prefixes, none of it has changed.

Dave

Hi Dave,
Thanks for identifying the missing info in the OVM user guide. I will file a request for enhancement to the OVM user guide for the Cadence side. Could you please do the same on the Mentor side. This way we will ensure that the missing info that you have identified will be in the next release of the OVM user guide. Thanks.

Already did - back in September '08.

Hello Dave,

Thank you so much for your fruitful comments, i tried the procedure you said with ovm_analysis_fifo, when tried running it wasn’t working and checked the ovm-2.0.1 library and there wasn’t any information related to ovm_analysis_fifo,

But when i changed it to tlm_analysis_fifo it was working fine with ovm_analysis_port at the monitor side… Is it a right usage??

Thanks for your helps…
Desperado → In a swing ;)

Yes, I meant tlm_analysis_fifo.

[LEFT]Hello Sir Dave,

Thank you for your fruitful and patience replies.!!!

Can you please help me out for questions in the post i had given, the link is given below

http://ovmworld.org/forums/showthread.php?t=857

Thanks,
Desperado → Thank Full to all my OVM Gurus :o
[/LEFT]

Hi all,

There weren’t info’s relating connecting ovm_monitor with ovm_scoreboard. Things I learned about TLM Connections for connecting ovm_monitor to ovm_scoreboard, giving below.

1. For connecting OVM Monitor to OVM Scoreboard :
Type1:
- Using ovm_put_port in ovm_monitor.
- Using ovm_get_port in ovm_scoreboard.
- Using tlm_fifo inside ovm_env to connect the ovm_monitor
****and ovm_scoreboard.

// Declaration In monitor1
ovm_put_port #(xactn_item) mon1_port;
// Code to put the transaction into fifo in monitor1
mon1_port.put(xactn_item);
// Declaration In monitor2
ovm_put_port #(xactn_item) mon2_port;
// Code to put the transaction into fifo in monitor2
mon2_port.put(xactn_item);
//Declarations in Scoreboard to get the transactions
ovm_get_port #(xactn_item) score1_export;
ovm_get_port #(xactn_item) score2_export;
//Connection inside environment
//Declare two fifo’s to connect two differenct ovm_monitor to
//ovm_scoreboard
tlm_fifo #(xactn_item) fifo1 = new(“fifo1”,null);
tlm_fifo #(xactn_item) fifo2 = new(“fifo2”,null);
//Connect the ovm_monitor with ovm_scoreboard inside connect function
function void connect();
ctl_mon_itd0.mon1_port.connect(fifo1.put_export);
ctl_scoreboard0.score1_export.connect(fifo1.get_export);
ctl_mon_ofd0.mon2_port.connect(fifo2.put_export);
ctl_scoreboard0.score2_export.connect(fifo2.get_export);
endfunction: connect

2. For connecting OVM Monitor to OVM Scoreboard

Type2:
- Using ovm_analysis_port in ovm_monitor.
- Using ovm_analysis_imp inside ovm_scoreboard
.
- Write functions inside the ovm_scoreboard to get the
transactions from two different ovm_monitor.

//Declaration inside monitor1
ovm_analysis_port #(xactn_item) mon1_port;
//Code to put the transaction into fifo in monitor1
mon1_port.write(xactn_item);
//Declaration inside monitor2
ovm_analysis_port #(xactn_item) mon2_port;
//Code to put the transaction into fifo in monitor2
mon2_port.write(xactn_item);
//Declaring macros outside ovm_scoreboard class to define N number of
//write function as per requirment
ovm_analysis_imp_decl(_mon1) ovm_analysis_imp_decl(_mon2)
//Declaring two ports to get transactions from two different monitors
ovm_analysis_imp_mon1 #(xactn_item, ctl_scoreboard) mon1_export;
ovm_analysis_imp_mon2 #(xactn_item, ctl_scoreboard) mon2_export;
//Define two separate write functions to get the transactions from
//two different monitors
protected function void write_memory(input xactn_item mon1_item);
endfunction: write_memory
protected function void read_memory(input xactn_item mon2_item);
endfunction: read_memory
//Connections inside ovm_environment in connect() function
function void connect();
ctl_mon_1.mon1_port.connect(ctl_scoreboard0.mon1_export);
ctl_mon_2.mon2_port.connect(ctl_scoreboard0.mon2_export);
endfunction: connect
NOTE:

  • Since we are using ovm_analysis_imp, we got to define write functions
    inside ovm_scoreboard to get the transactions from the ovm_moniter
  • As we use write functions inside scoreboard, we cant use any delay
    informations inside it and we cant do any synching with the ovm_monitor
  • To solve this we go for Type 3 Connection as given below.

3. For connecting OVM Monitor to OVM Scoreboard

Type3:
- Using ovm_analysis_port in ovm_monitor to put transaction.
- Using ovm_analysis_export inside ovm_scoreboard to get
transaction.
- Define tlm_analysis_fifo inside ovm_scoreboard, connect it
to ovm_analysis_export to get the transactions.

//Declaration inside monitor1
ovm_analysis_port #(xactn_item) mon1_port;
//Code to put the transaction into fifo in monitor1
mon1_port.write(xactn_item);
//Declaration inside monitor2
ovm_analysis_port #(xactn_item) mon2_port;
//Code to put the transaction into fifo in monitor2
mon2_port.write(xactn_item);
//Declarations inside ovm_scoreboard
//Declare two ovm_analysis_export to receive transactions from
//two different monitors
ovm_analysis_export #(xactn_item) mon1_export;
ovm_analysis_export #(xactn_item) mon2_export;
//Declare two tlm_analysis_fifo to connect to ovm_analysis_export to
//get the transactions
tlm_analysis_fifo #(xactn_item) mon1_fifo;
tlm_analysis_fifo #(xactn_item) mon2_fifo;
//Connect ovm_analysis_export and tlm_analysis_fifo using connect
//function inside ovm_scoreboard
function void connect;
mon1_export.connect(mon1_fifo.analysis_export);
mon2_export.connect(mon2_fifo.analysis_export);
endfunction: connect
//Define the task run to get the transaction using get method
task run;
begin
@(ctl_if0.mon_cb);
chk_data();
end
endtask: run
task chk_data();
xactn_item mon1, mon2;
forever begin
mon1_fifo.get(mon1);
if(mon1.opr == OPRA)
begin end
else if(mon1.opr == OPRB)
begin
mon2_fifo.get(mon2);
end
endtask: chk_data
// Connections inside the environment
// Now connecting the two differenct ovm_monitor with the
// ovm_scoreboard using the connect function
function void connect();
ctl_mon_1.mon1_port.connect(ctl_scoreboard0.mon1_export);
ctl_mon_2.mon2_port.connect(ctl_scoreboard0.mon2_export);
endfunction: connect
Note: In Type 2 connections we used ovm_analysis_imp, so we got to use write function inside the ovm_scoreboard to get the transactions and doesnt help in synching with the ovm_monitor as we cant use any delay inside function. But here in this Type 3 we connected tlm_analysis_fifo to ovm_analysis_export to get the transactions from the two different monitor and by doing so we can use “task” inside the ovm_scoreboard to get the transactions and hence you can use any delays informations inside the task, and helps in synching with the ovm_monitor.

The above given information’s are things which I learned from user guide and other threads, If i had made any mistake on it kindly forgive and please post the suggestions.

Thanks,
Desperado → Coming for help with things i know ;)

In reply to desperado:

Hi,
i have one doubt regarding ovm_analysis imp.
Cam we use ovm_analysis_imp instead of ovm_analysis_export for type 3 example? Please can you clarify my doubt?. If we are using tlm_analysis fifo, we must use ovm_analysis_export. Am i correct? how we can impelement socreboard(for type 3) using ovm_anlysis_imp with tlm_analysis_fifo?

In reply to sudheer:

Hi,
Can you please tell what is the depth of tlm_fifo? is it one? or else can we explicitly mention?

thanks & regards,
Sudheer

In reply to sudheer:

Yes, default size is 1, you can change it during construction. The prototype is:

function tlm_fifo::new(	string 	name,	  	
	ovm_component 	parent	 = 	null,
	int 	size	 = 	1	);

When you create an instance you can do:

tlm_fifo #(my_xactn) my_tlm_fifo;

  //..
  this.my_tlm_fifo = new (.name ("my_tlm_fifo"),
                          .parent(this),
                          .size(10));

HTH,
Ajeetha, CVC