In reply to Tudor Timi:
By UVM harness I am referring to something based on: http://www.synapse-da.com/Uploads/PDFFiles/03_UVM-Harness.pdf, a method of connecting the uvm environment and the dut that uses interfaces and binds with the module-side.
Let's define the environment terms first:
1.) top_dut = design under test w/ submod_1 and submod_2 having signals corresponding to my_if_1 and my_if_2
2.) my_env = uvm environment
3.) my_cfg = environment config contains virtual interfaces; agent_1 and agent_2 have corresponding cfg_1 and cfg_2
4.) my_if_1 = interface set 1 connects w/ agent_1
5.) my_if_2 = interface set 2 connects w/ agent_2
6.) my_harness = uvm harness that connects submod_1 and submod_2 to my_if_1 and my_if_2 respectively
7.) top_tb = for testbench top
The source code looks like this:
1.) top_dut
module modcore;
wire clk1;
wire valid1;
wire ready1;
wire clk2;
wire addr2;
wire byten2;
submod_1 u_submod_1 (.submod_1_clk(clk1),
.submod_1_valid(valid1),
.submod_1_ready(ready1));
submod_2 u_submod_2 (.submod_2_clk(clk2),
.submod_2_addr(addr2),
.submod_2_byten(byten2));
endmodule
module top_dut;
wire clk1;
wire clk2;
wire valid1;
wire ready1;
wire addr2;
wire byten2;
modcore u_modcore(.clk1(clk1),
.clk2(clk2),
.valid1(valid1),
.ready1(ready1),
.addr2(addr2),
.byten2(byten2)
);
endmodule
2.) my_env
class my_env extends uvm_env;
`uvm_component_utils(my_env)
my_agent1 u_agent1;
my_agent2 u_agent2;
my_cfg u_cfg;
function void build_phase(uvm_phase phase);
// Agent 1
if(this.u_agent1 == null) begin
this.u_agent1 = my_agent1::type_id::create("u_agent1",this);
uvm_config_db#(agent1_cfg)::set(
.cntxt (this),
.inst_name ("u_agent1*"),
.field_name ("agent1_cfg"),
.value (this.cfg.u_cfg_1)
);
end
// Agent 2
if(this.u_agent2 == null) begin
this.u_agent2 = my_agent2::type_id::create("u_agent2",this);
uvm_config_db#(agent2_cfg)::set(
.cntxt (this),
.inst_name ("u_agent2*"),
.field_name ("agent2_cfg"),
.value (this.cfg.u_cfg_2)
);
end
endfunction : build_phase
endclass : my_env
3.) my_cfg
class my_cfg extends uvm_object;
`uvm_object_utils(my_cfg)
cfg_1 u_cfg_1;
cfg_2 u_cfg_2;
function void build();
if (u_cfg_1 == null) begin
this.u_cfg_1 = cfg1::type_id::create("u_cfg_1");
end
if (u_cfg_2 == null) begin
this.u_cfg_2 = cfg2::type_id::create("u_cfg_2");
end
endfunction : build
endclass : my_cfg
4.) my_if_1
interface my_if_1 ();
wire clk;
wire my_if_1_valid;
wire my_if_1_ready;
clocking my_if_1_cb @(posedge clk);
input my_if_1_valid;
output ready;
endclocking
modport my_if_1_mp (clocking my_if_1_cb,
input clk);
endinterface : my_if_1
`define my_if_1_bind(VIF, PATH, CLK, VALID, READY)\
alias VIF.clk = PATH.CLK; \
alias VIF.my_if_1_valid = PATH.VALID; \
alias VIF.my_if_1_ready = PATH.READY;
5.) my_if_2
interface my_if_2 ();
wire clk;
wire my_if_2_addr; // don't mind the bit widths
wire my_if_2_byten;
clocking my_if_2_cb @(posedge clk);
input my_if_2_addr;
output my_if_2_byten;
endclocking
modport my_if_2_mp (clocking my_if_2_cb,
input clk);
endinterface : my_if_2
`define my_if_2_bind(VIF, PATH, CLK, ADDR, BYTEN)\
alias VIF.clk = PATH.CLK; \
alias VIF.my_if_2_addr = PATH.ADDR; \
alias VIF.my_if_2_byten = PATH.BYTEN;
6.) my_harness
`include "my_if_1.sv"
`include "my_if_2.sv"
interface my_harness ();
my_if_1 u_if_1 ();
my_if_2 u_if_2 ();
`my_if_1_bind(u_if_1, u_modcore.u_submod_1, clk1, valid1, ready1)
`my_if_2_bind(u_if_2, u_modcore.u_submod_2, clk2, addr2, byten2)
endinterface
bind u_modcore my_harness harness();
7.) top_tb
import uvm_pkg::*;
`include "my_harness.sv"
module top_tb;
initial begin
uvm_config_db#(virtual my_harness)::set(
.cntxt (null),
.inst_name ("uvm_test_top"),
.field_name ("my_harness"),
.value (top_dut.u_modcore.harness)
);
end
endmodule
Let me change the error as follows to correspond with the signal names:
**Error: /some_path/my_harness.sv(100): (vlog-LRM-2230) Expression 'my_if.my_if_1_valid' is not allowed in alias statement.
Thanks,
Martin