One Compile to Rule them All:An elegant solution for
OVM/UVM Testbench Topologies
byGalen Blake
SMTS
andSteve Chappell
Solutions Architect
Sponsored By:
2 of 21
System Verilog Topology
• Hey, you got software in my hardware.
• No, you got hardware in my software.
• How are we going to mix all this stuff together and configure the topology?
• If you never saw this advertisement, visit
http://www.youtube.com/watch?v=DJLDF6qZUX0
Sponsored By:
3 of 21
SystemVerilog Topology
• Design• HW• Modules• Static
– Fixed at Elab time
• Testbench• SW• Classes• Dynamic
– Created at Run time
Software(HVL)
Hardware(HDL)
Sponsored By:
4 of 21
SOC Topology Challenge
MPU
Memory Controller
Periph
SwitchFabric
Periph
Periph
Periph
Periph
Periph
Periph
Periph
Periph
Periph
Periph
Periph
Periph
Periph
Periph
Periph
Periph
Periph
• Traditional SOC Design:
• Many peripherals.• Not enough pins.• Users must choose
some combination of peripherals to keep.
• Each combination is effectively a new DUT.
• Each new DUT needs a new testbench.
Sponsored By:
5 of 21
OOP (SV) Topology Challenge
• Polymorphic VIP’s create more topology options.
• A polymorphic VIP could– Be held inactive– Monitor an internal
bus– Drive an internal
bus• The desired form of a
polymorphic VIP must be selected.
• Other topology controls are needed for driving an internal bus.
MPU
Memory Controll
er
SwitchFabric
Driver
Driver
Driver
Monitor or Driver
Driver
Sponsored By:
6 of 21
SOC on FPGA Topology Challenge• 1000s of nets added
to 100s of pins.• Many more virtual
pins connecting the SOC to the FPGA fabric.
• Many more possible peripheral combinations.
• Many more new DUTs and testbench topologies.
SOC
Memory I-F
Memory Controller
CORE
Sponsored By:
7 of 21
Testbench Aceleration Challenge• Testbench acceleration
requires us to split up our OVM/UVM agents.
• Time consuming tasks must be located in HDL context.
• So we place our drivers and monitors into SV Interfaces.
driver
monitor
sequencer
analysis
Editorial:• SystemVerilog should not allow us to “mix our metaphors.”• We should not be putting hardware (HDL-TCTs) in our software (HVL-Classes).• Perhaps a topic for a future paper…
HVL HDL
Sponsored By:
8 of 21
Invasion of SW Test Writers
• Need to simplify view of HW and HW flows
• One shared known-good pre-compiled database is crucial
Sponsored By:
9 of 21
Faster Turnaround timeSmaller Diskspace requirements
Sponsored By:
10 of 21
Testbench Topology Development• Normal topology development strategy.• It evolves slowly.• Many different developers and their ideas all get
mixed together.• A single cohesive strategy is often lacking.
Sponsored By:
11 of 21
Approach #1: “Many netlists”
Pros:• Easy.
Cons:• How many do we need?• Maintenance.• Copy-paste errors.• Re-use?
module hdl_top_pci_tests();
wire tx,rx,…;
emac_vip_if emac_vip_if0(.tx(tx),.rx(rx),…);
`include “dut_inst.svh”
endmodule
module hdl_top_nic_tests();
reg tx = 0; wire rx;
`include “dut_inst.svh”
endmodule.
module hdl_top_hat_tests();
wire tx,rx,…;
emac_vip_if emac_vip_if0(.tx(tx),.rx(rx),…);
`include “dut_inst.svh”
endmodule
module hdl_top_nic_tests();
reg tx = 0; wire rx;
`include “dut_inst.svh”
endmodule.
module hdl_top_ddr_tests();
wire tx,rx,…;
emac_vip_if emac_vip_if0(.tx(tx),.rx(rx),…);
`include “dut_inst.svh”
endmodule
module hdl_top_nic_tests();
reg tx = 0; wire rx;
`include “dut_inst.svh”
endmodule.
module hdl_top_foo_tests();
wire tx,rx,…;
emac_vip_if emac_vip_if0(.tx(tx),.rx(rx),…);
`include “dut_inst.svh”
endmodule
module hdl_top_nic_tests();
reg tx = 0; wire rx;
`include “dut_inst.svh”
endmodule.
module hdl_top_uart_tests();
wire tx,rx,…;
emac_vip_if emac_vip_if0(.tx(tx),.rx(rx),…);
`include “dut_inst.svh”
endmodule
module hdl_top_nic_tests();
reg tx = 0; wire rx;
`include “dut_inst.svh”
endmodule.
module hdl_top_usb_tests();
wire tx,rx,…;
emac_vip_if emac_vip_if0(.tx(tx),.rx(rx),…);
`include “dut_inst.svh”
endmodule
module hdl_top_nic_tests();
reg tx = 0; wire rx;
`include “dut_inst.svh”
endmodule.
module hdl_top_emac_tests();
wire tx,rx,…;
emac_vip_if emac_vip_if0(.tx(tx),.rx(rx),…);
`include “dut_inst.svh”
endmodule
module hdl_top_nic_tests();
reg tx = 0; wire rx;
`include “dut_inst.svh”
endmodule.
Sponsored By:
12 of 21
Approach #2: Macros (`ifdefs)
Pros:• Easy.
Cons:• Expanded pre-compile• Scope? (Name collisions)• Debug• Nested readability
module hdl_top ();`ifdef USE_EMAC0 wire tx,rx,…; emac_vip_if emac_vip_if0(.tx(tx),.rx(rx),…);`else reg tx = 0; wire rx;`endif dut dut(….);endmodule class my_env extends uvm_env; function void build_phase( uvm_phase phase); `ifdef USE_EMAC0 emac0_agent = new(…); // or create from factory `endif ….
module hdl_top_emac_tests();
wire tx,rx,…;
emac_vip_if emac_vip_if0(.tx(tx),.rx(rx),…);
`include “dut_inst.svh”
endmodule
module hdl_top_nic_tests();
reg tx = 0; wire rx;
`include “dut_inst.svh”
endmodule.
Sponsored By:
13 of 21
Approach #3: Parameters
Pros:• Set at elaboration time• Well-defined scope
Cons:• Type specializations• UVM factory considerations
module hdl_top (); parameter USE_EMAC0 = 1; if (USE_EMAC0 == 1) begin wire tx,rx,…; emac_vip_if emac_vip_if0(.tx(tx),.rx(rx),…);end else begin reg tx = 0; wire rx;end dut dut(….);endmodule class my_env #(int USE_EMAC0=1) extends uvm_env; `uvm_component_param_utils(my_env); function void build_phase( uvm_phase phase); if (USE_EMAC0) emac0_agent = new(…); // or create from factory ….
HDL
HVL
module hdl_top ();`ifdef USE_EMAC0 wire tx,rx,…; emac_vip_if emac_vip_if0(.tx(tx),.rx(rx),…);`else reg tx = 0; wire rx;`endif dut dut(….);endmodule class my_env extends uvm_env; function void build_phase( uvm_phase phase); `ifdef USE_EMAC0 emac0_agent = new(…); // or create from factory `endif ….
Sponsored By:
14 of 21
Approach #4: +plusargs
Pros:• Runtime• UVM cmdline processor• Register encapsulation
Cons:• Too late for HDL
interface config_regs ();
reg [`MAX_CFGS-1:0] tb_cfg;
initial begin
tb_cfg = `DEFAULT_TB_CFG;
if ( $value$plusargs("USE_EMAC0=%d", use_e0 ) )
tb_cfg[`USE_EMAC0] = use_e0;
end
endinterface
Sponsored By:
15 of 21
The Elegant Topology Solution. • Any solution for dealing with the configuring the
topology of the testbench must consider both contexts:– HDL (module)– HVL (class).
• HVL topology must match HDL topology.• One set of controls is best.• Parameters are good in HDL.• But how do we configure HVL?
Sponsored By:
16 of 21
Parameter Transport
• Parameters used to configure HDL are transported to HVL.
• Parameters are tranported using a SV Interface to any HVL class object.
• Hundreds of topology parameters are available without the burden of putting parameters in a class.
Parameters
Software(HVL)
Hardware(HDL)
Sponsored By:
17 of 21
HDL ExampleFROM THE HDL CONTEXT: . . . parameter USE_L3_ACP_AXI_VIP = 0;. . . // This interface is used to store and distribute parameter settings // for which TB components and parameters to use. config_tb_if cfg_tb(); assign cfg_tb.use_l3_acp_axi_vip = USE_L3_ACP_AXI_VIP;. . . //// AXI Tranactor (replaces peripheral connections for testing). generate if (USE_L3_ACP_AXI_VIP) begin : inst_acp_axi_vip_mst axi_monitor_module #( .ADDR_WIDTH (`ACP_ADDR_WIDTH), .RDATA_WIDTH (`ACP_RDATA_WIDTH), .WDATA_WIDTH (`ACP_WDATA_WIDTH), .ID_WIDTH (`ACP_ID_WIDTH), .LEN_WIDTH (4), .AXI_ID ( "acp_axi_monitor" ) ) acp_axi_monitor (.mif(acp_axi_vip_mst)); end endgenerate
Sponsored By:
18 of 21
HVL ExampleFROM THE HVL CONTEXT: . . . virtual config_tb_if cfg_tb; . . . if ( cfg_tb.use_l3_acp_axi_vip) begin ovm_report_info("build: ", "ACP_AXI_VIP agent will be enabled ..."); l3_acp_axi_a = axi_agent #(ACP_axi_p)::type_id::create("l3_acp_axi_a", this); l3_acp_axi_a.set_config_id("master_acp", axi_pkg::MASTER_MONITOR); l3_acp_axi_a.register_agent(TBMB_PERIF_ACP_ID); end. . .
Sponsored By:
19 of 21
The Code (from paper)module hdl_top ();
parameter USE_L3_ACP_AXI_VIP = 0;…generate if (USE_L3_ACP_AXI_VIP) begin : i_acp_axi_vip axi_monitor_vip #( .ADDR_WIDTH (`ACP_ADDR_WIDTH), .RDATA_WIDTH (`ACP_RDATA_WIDTH), … .AXI_ID ( "acp_axi_monitor" ) ) acp_axi_monitor (.mif(acp_axi_vip_mst)); end endgenerate…endmodule
interface config_tb_if();
bit use_l3_acp_axi_vip;
…
endinterface
module hdl_top ();
parameter USE_L3_ACP_AXI_VIP = 0;… config_tb_if cfg_tb(); assign cfg_tb.use_l3_acp_axi_vip =
USE_L3_ACP_AXI_VIP; initial uvm_config_db #( virtual config_tb_if )::set( …);…endmodule
class my_env extends uvm_env;
`uvm_component_utils(my_env);
virtual config_tb_if cfg_tb;
function void build_phase( uvm_phase phase);
cfg_tb = uvm_config_db #( virtual config_tb_if )::get(.. );
if ( cfg_tb.use_l3_acp_axi_vip) begin
l3_acp_axi_a = axi_agent
#(ACP_axi_p)::type_id::create("l3_acp_axi_a", this);
end
. . .
Sponsored By:
20 of 21
Comparison Chart
Topology control
Maintain HDLContext
HVLContext
Lockdown Phase
Many netlists
Bad Fair Fair Elab
Text Macros Poor Fair Fair Compile
Parameters Good Good Poor Elab
Plus args Fair Bad Good Runtime
Parameter transport
Good Good Good Elab
Sponsored By:
21 of 21
Conclusion
• Sprawling complexity and inconsistent hybrid solutions for defining the testbench topology create serious maintenance issues making it difficult to develop or enhance tests for HVL and complex SOC designs.
• Consolidating topology definition of both HDL net-lists and HVL object hierarchies to a single point source simplifies maintenance while preserving significant flexibility with a very large variety of topologies available.