class uart_driver extends uvm_driver #(uart_transaction);
uvm_analysis_port #(uart_transaction) drv2sb_port;
endclass
class uvm_analysis_port # (type T = int)
extends uvm_port_base # (uvm_tlm_if_base #(T,T));
endclass
virtual class uvm_port_base #(type IF=uvm_void) extends IF;
endclass
2) Use macro uvm_analysis_imp_decl(SFX) to define a new uvm_analysis_imp class in scoreboard and then create an object of the class in the scoreboard. uvm_analysis_imp extends the class uvm_port_base.
`uvm_analysis_imp_decl(_rcvd_uart)
class uart_scoreboard extends uvm_scoreboard;
uvm_analysis_imp_sent_uart #(uart_transaction, uart_scoreboard) drv2sb_port;
endclass
`define uvm_analysis_imp_decl(SFX) \
class uvm_analysis_imp``SFX #(type T=int, type IMP=int) \
extends uvm_port_base #(uvm_tlm_if_base #(T,T)); \
...\
\
endclass
3) In the uvm_env, connect the driver uvm_analysis_port with scoreboard uvm_analysis_imp port.
In uvm_analysis_port, which is inherited from uvm_port_base, function resolve_bindings will automatically be called just before the start of the end_of_elaboration phase, which will add the scoreboard port in the list m_imp_list.
class uart_env extends uvm_env;
uart_agent uart_agt;
uart_scoreboard uart_sb;
uart_scoreboard uart_sb;
function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
uart_agt.uart_drv.drv2sb_port.connect(uart_sb.drv2sb_port);
endfunction endclass
virtual class uvm_port_base #(type IF=uvm_void) extends IF;
virtual function void connect (this_type provider);
...
m_provided_by[provider.get_full_name()] = provider;
provider.m_provided_to[get_full_name()] = this;
endfunction
local function void m_add_list (this_type provider);
string sz;
this_type imp;
for (int i = 0; i < provider.size(); i++) begin
imp = provider.get_if(i);
if (!m_imp_list.exists(imp.get_full_name()))
m_imp_list[imp.get_full_name()] = imp;
end
endfunction
virtual function void resolve_bindings();
if (m_resolved) // don't repeat ourselves
return;
if (is_imp()) begin
m_imp_list[get_full_name()] = this;
end
else begin
foreach (m_provided_by[nm]) begin
this_type port;
port = m_provided_by[nm];
port.resolve_bindings();
m_add_list(port);
end
end
...
endfunction
endclass
super.connect_phase(phase);
uart_agt.uart_drv.drv2sb_port.connect(uart_sb.drv2sb_port);
endfunction endclass
virtual class uvm_port_base #(type IF=uvm_void) extends IF;
virtual function void connect (this_type provider);
...
m_provided_by[provider.get_full_name()] = provider;
provider.m_provided_to[get_full_name()] = this;
endfunction
local function void m_add_list (this_type provider);
string sz;
this_type imp;
for (int i = 0; i < provider.size(); i++) begin
imp = provider.get_if(i);
if (!m_imp_list.exists(imp.get_full_name()))
m_imp_list[imp.get_full_name()] = imp;
end
endfunction
virtual function void resolve_bindings();
if (m_resolved) // don't repeat ourselves
return;
if (is_imp()) begin
m_imp_list[get_full_name()] = this;
end
else begin
foreach (m_provided_by[nm]) begin
this_type port;
port = m_provided_by[nm];
port.resolve_bindings();
m_add_list(port);
end
end
...
endfunction
endclass
4) In the running phase, when driver call the write function of the uvm_analysis_port, it will go through all it's connected ports when connected in uvm_env and call the write function of the uvm_analysis_imp``SFX, which will call the m_imp.write``SFX( t) function in the scoreboard. In the example below m_imp.write``SFX( t) is write_sent_uart function.
class uart_driver extends uvm_driver #(uart_transaction);
forever begin
uart_transaction uart_tr;
seq_item_port.get_next_item(uart_tr); drv2sb_port.write(uart_tr);
end
endtask
endclass
class uvm_analysis_port # (type T = int)
extends uvm_port_base # (uvm_tlm_if_base #(T,T));
...
function void write (input T t);
uvm_tlm_if_base # (T, T) tif;
for (int i = 0; i < this.size(); i++) begin
tif = this.get_if (i);
if ( tif == null )
uvm_report_fatal ("NTCONN", {"No uvm_tlm interface is connected to ", get_full_name(), " for executing write()"}, UVM_NONE);
tif.write (t);
end
endfunction
endclass
virtual class uvm_port_base #(type IF=uvm_void) extends IF;
function int size ();
return m_imp_list.num();
endfunction
function uvm_port_base #(IF) get_if(int index=0);
string s;
if (size()==0) begin
m_comp.uvm_report_warning("get_if",
"Port size is zero; cannot get interface at any index", UVM_NONE);
return null;
end
if (index < 0 || index >= size()) begin
$sformat(s, "Index %0d out of range [0,%0d]", index, size()-1);
m_comp.uvm_report_warning(s_connection_error_id, s, UVM_NONE);
return null;
end
foreach (m_imp_list[nm]) begin
if (index == 0)
return m_imp_list[nm];
index--;
end
endfunction
endclass
`define uvm_analysis_imp_decl(SFX) class uvm_analysis_imp``SFX #(type T=int, type IMP=int) \
extends uvm_port_base #(uvm_tlm_if_base #(T,T)); \ `UVM_IMP_COMMON(`UVM_TLM_ANALYSIS_MASK,`"uvm_analysis_imp``SFX`",IMP) \
function void write( input T t); \
m_imp.write``SFX( t); \
endfunction \
\
endclass
`define uvm_analysis_imp_decl(SFX) class uvm_analysis_imp``SFX #(type T=int, type IMP=int) \
extends uvm_port_base #(uvm_tlm_if_base #(T,T)); \ `UVM_IMP_COMMON(`UVM_TLM_ANALYSIS_MASK,`"uvm_analysis_imp``SFX`",IMP) \
function void write( input T t); \
m_imp.write``SFX( t); \
endfunction \
\
endclass
`uvm_analysis_imp_decl(_rcvd_uart) class uart_scoreboard extends uvm_scoreboard; uvm_analysis_imp_sent_uart #(uart_transaction, uart_scoreboard) drv2sb_port; $cast(cb_uart_tr, uart_tr.clone()); endfunction virtual function void write_sent_uart(input uart_transaction uart_tr); endclass
No comments:
Post a Comment