PDA

View Full Version : tlm_fifo misbehavior ?



elmar
03-05-2008, 11:41 AM
Hi

We observe a strange behavior of the OVM application below on IUS 06.20-s004.
It implements two independent transaction level comunications using tlm_fifo:
1) pre_source --> driver
2) monitor --> sink

Running the code exactly as it is below everything is o.k.
However, erasing the line marked "********* initial delay offset *************"
the two comunications get mixed up.

Is this my programming error or a OVM error or a IUS error ?

Elmar

module tb;
`include "ovm.svh"

class packet extends ovm_transaction;
rand int i;
constraint i_range {
i > 0;
i < 16;
}
endclass


class pre_source extends ovm_threaded_component;
ovm_put_port #(packet) data_out;
function new(string name, ovm_component parent);
super.new(name,parent);
data_out = new("data_out", this);
endfunction
task run();
packet p;
while(1) begin
p = new();
assert(p.randomize());
$display("source %0t: put %0d", $time, p.i);
data_out.put(p);
end
endtask
endclass

class driver extends ovm_threaded_component;
ovm_get_port #(packet) data_in;
function new(string name, ovm_component parent);
super.new(name,parent);
data_in = new("data_in", this);
endfunction
task run();
packet p;
while(1) begin
#10;
data_in.get(p);
$display("driver %0t: rec %0d", $time, p.i);
p = null;
end
endtask
endclass

class monitor extends ovm_threaded_component;
ovm_put_port #(packet) data_out;
function new(string name, ovm_component parent);
super.new(name,parent);
data_out = new("data_out", this);
endfunction
task run();
packet p;
#1; // ********* initial delay offset *************
while(1) begin
#10;
p = new();
assert(p.randomize());
$display(" monitor %0t: put %0d", $time, p.i);
data_out.put(p);
end
endtask
endclass

class sink extends ovm_threaded_component;
ovm_get_port #(packet) tr_in;
function new(string name, ovm_component parent);
super.new(name,parent);
tr_in = new("tr_in", this);
endfunction
task run();
packet tr;
while(1) begin
tr_in.get(tr);
$display(" sink %0t: rec %0d", $time, tr.i);
tr = null;
end
endtask
endclass

class env extends ovm_env;
pre_source sou;
driver dri;
monitor mon;
sink sin;

tlm_fifo #(packet) source_driver;
tlm_fifo #(packet) monitor_checker;

function new(string name = "env");
sou = new("sou", this);
dri = new("dri", this);
mon = new("mon", this);
sin = new("sin", this);

source_driver = new("source_driver", this, 1);
monitor_checker = new("monitor_checker", this, 1);
endfunction

function void connect();
mon.data_out.connect(monitor_checker.put_export);
sin.tr_in.connect(monitor_checker.get_export);
sou.data_out.connect(source_driver.put_export);
dri.data_in.connect(source_driver.get_export);
endfunction

task run();
#100;
endtask

endclass

env e;

initial begin
e = new();
e.do_test();
$finish;
end

endmodule



Output with initial delay offset of 1 for monitor-sink transactions (everything o.k.)
================================================== =================
source 0: put 5
source 0: put 11
driver 10: rec 5
source 10: put 3
monitor 11: put 11
sink 11: rec 11
driver 20: rec 11
source 20: put 11
monitor 21: put 12
sink 21: rec 12
driver 30: rec 3
source 30: put 10
monitor 31: put 11
sink 31: rec 11
driver 40: rec 11
source 40: put 6
monitor 41: put 2
sink 41: rec 2
driver 50: rec 10
source 50: put 4
monitor 51: put 14
sink 51: rec 14
driver 60: rec 6
source 60: put 1
monitor 61: put 1
sink 61: rec 1
driver 70: rec 4
source 70: put 3
monitor 71: put 15
sink 71: rec 15
driver 80: rec 1
source 80: put 5
monitor 81: put 3
sink 81: rec 3
driver 90: rec 3
source 90: put 1
monitor 91: put 9
sink 91: rec 9
driver 100: rec 5


Output for simultaneous transactions (BAD: sink receives transaction from source instead from monitor)
====================================
source 0: put 5
source 0: put 11
monitor 10: put 11
driver 10: rec 5
sink 10: rec 5
source 10: put 3
monitor 20: put 12
driver 20: rec 11
sink 20: rec 11
source 20: put 11
monitor 30: put 11
driver 30: rec 3
sink 30: rec 3
source 30: put 10
monitor 40: put 2
driver 40: rec 11
sink 40: rec 11
source 40: put 6
monitor 50: put 14
driver 50: rec 10
sink 50: rec 10
source 50: put 4
monitor 60: put 1
driver 60: rec 6
sink 60: rec 6
source 60: put 1
monitor 70: put 15
driver 70: rec 4
sink 70: rec 4
source 70: put 3
monitor 80: put 3
driver 80: rec 1
sink 80: rec 1
source 80: put 5
monitor 90: put 9
driver 90: rec 3
sink 90: rec 3
source 90: put 1
monitor 100: put 14
driver 100: rec 5

Nigele
03-06-2008, 03:41 AM
It appears to run in Questa ok

With #1 delay



# vsim -c opt
# // QuestaSim 6.3e Feb 2 2008
# //
# // Copyright 1991-2008 Mentor Graphics Corporation
# // All Rights Reserved.
# //
# // THIS WORK CONTAINS TRADE SECRET AND
# // PROPRIETARY INFORMATION WHICH IS THE PROPERTY
# // OF MENTOR GRAPHICS CORPORATION OR ITS LICENSORS
# // AND IS SUBJECT TO LICENSE TERMS.
# //
# Loading sv_std.std
# Loading work.ovm_pkg(fast)
# Loading work.tb(fast)
# ----------------------------------------------------------------
# OVM-1.0.1
# (C) 2007-2008 Mentor Graphics Corporation
# (C) 2007-2008 Cadence Design Systems, Inc.
# ----------------------------------------------------------------
# source 0: put 10
# source 0: put 11
# driver 10: rec 10
# source 10: put 9
# monitor 11: put 5
# sink 11: rec 5
# driver 20: rec 11
# source 20: put 10
# monitor 21: put 2
# sink 21: rec 2
# driver 30: rec 9
# source 30: put 13
# monitor 31: put 6
# sink 31: rec 6
# driver 40: rec 10
# source 40: put 3
# monitor 41: put 10
# sink 41: rec 10
# driver 50: rec 13
# source 50: put 9
# monitor 51: put 1
# sink 51: rec 1
# driver 60: rec 3
# source 60: put 4
# monitor 61: put 1
# sink 61: rec 1
# driver 70: rec 9
# source 70: put 13
# monitor 71: put 10
# sink 71: rec 10
# driver 80: rec 4
# source 80: put 6
# monitor 81: put 11
# sink 81: rec 11
# driver 90: rec 13
# source 90: put 10
# monitor 91: put 1
# sink 91: rec 1
#
# --- OVM Report Summary ---
#
# ** Report counts by severity
# OVM_INFO : 0
# OVM_WARNING : 0
# OVM_ERROR : 0
# OVM_FATAL : 0
# ** Report counts by id
# ** Note: $finish : orig.sv(120)
# Time: 100 ns Iteration: 10 Instance: /tb



Without #1 delay




# vsim -c opt
# // QuestaSim 6.3e Feb 2 2008
# //
# // Copyright 1991-2008 Mentor Graphics Corporation
# // All Rights Reserved.
# //
# // THIS WORK CONTAINS TRADE SECRET AND
# // PROPRIETARY INFORMATION WHICH IS THE PROPERTY
# // OF MENTOR GRAPHICS CORPORATION OR ITS LICENSORS
# // AND IS SUBJECT TO LICENSE TERMS.
# //
# Loading sv_std.std
# Loading work.ovm_pkg(fast)
# Loading work.tb(fast)
# ----------------------------------------------------------------
# OVM-1.0.1
# (C) 2007-2008 Mentor Graphics Corporation
# (C) 2007-2008 Cadence Design Systems, Inc.
# ----------------------------------------------------------------
# source 0: put 10
# source 0: put 11
# monitor 10: put 5
# sink 10: rec 5
# driver 10: rec 10
# source 10: put 9
# monitor 20: put 2
# sink 20: rec 2
# driver 20: rec 11
# source 20: put 10
# monitor 30: put 6
# sink 30: rec 6
# driver 30: rec 9
# source 30: put 13
# monitor 40: put 10
# sink 40: rec 10
# driver 40: rec 10
# source 40: put 3
# monitor 50: put 1
# sink 50: rec 1
# driver 50: rec 13
# source 50: put 9
# monitor 60: put 1
# sink 60: rec 1
# driver 60: rec 3
# source 60: put 4
# monitor 70: put 10
# sink 70: rec 10
# driver 70: rec 9
# source 70: put 13
# monitor 80: put 11
# sink 80: rec 11
# driver 80: rec 4
# source 80: put 6
# monitor 90: put 1
# sink 90: rec 1
# driver 90: rec 13
# source 90: put 10
#
# --- OVM Report Summary ---
#
# ** Report counts by severity
# OVM_INFO : 0
# OVM_WARNING : 0
# OVM_ERROR : 0
# OVM_FATAL : 0
# ** Report counts by id
# ** Note: $finish : orig.sv(120)
# Time: 100 ns Iteration: 10 Instance: /tb

sasan
03-09-2008, 12:37 PM
I can't say for sure if this is a bug in either IUS or OVM, but you can fix it with the following work-around:

Either prepend all calls to get() with a "#0;" For example, change this:

"data_in.get(p);"

to:

"#0; data_in.get(p);"


Alternatively, if you're brave enough to touch the OVM source code, you can do the following:

In file src/tlm/tlm_fifos.svh line 70, change:

"m.get( tmp );"

To

"#0; m.get( tmp );"

The best thing of course would be to wait for Cadence folks to tell us what to do about this.

Sasan

jlrose
03-11-2008, 11:11 AM
This is an OVM bug, and I hate to admit that it is my fault. Sasan's work around will work in some specific cases, but it still suffers from the fundamental issue that the tlm_fifo::get and tlm_fifo::peek tasks are not thread safe.

The temporary static variable is used to work around a current IUS limitation. However, this is not really the right way to work around the issue (it is fine for a function, at least in most cases, but for a task it is pretty dangerous).

The right thing to do is to move the static variable out of the task and make it a local variable of the tlm_fifo class and then add a semaphore to protect access to the variable. The get method then looks like:

local T m_tmp_data; //make a local class variable
local semaphore m_get_sem = new(1); //add a mutex
task get( output T t );
m_pending_blocked_gets++;
m_get_sem.get(); //protect the shared variable
m.get( m_tmp_data );
t = m_tmp_data;
m_pending_blocked_gets--;
m_get_sem.post(); //release the lock
get_ap.write( t );
endtask

I will fix this for the next release (end of this month).

john

elmar
03-12-2008, 11:44 AM
Hi John,

I tried to modify tlm/tlm_fifos.svh according to Your instructions but got this:

file: ./INCA_libs/irun.lnx86.06.20.nc/svpplib/tb.sv
m_get_sem.post(); //release the lock
|
ncvlog: *E,QAANBI (./INCA_libs/irun.lnx86.06.20.nc/svpplib/specials/tlm_fifo_packet.svi,78|17): This is not a valid built in method name for this object. [SystemVerilog].

Without really knowing what I am doing I tried
m_get_sem.put(); //release the lock
and it seamed to work.
Is this o.k. ?

Elmar

jlrose
03-12-2008, 12:05 PM
Right, it should be put, not post. Sorry, I sometimes get myself confused between systemc and systemverilog. I apologize for the confusion.

john