Skip to content

Commit

Permalink
Add example UVM testbench for Verilator
Browse files Browse the repository at this point in the history
  • Loading branch information
mkurc-ant authored and kbieganski committed Nov 8, 2023
1 parent 61739fe commit e161f59
Show file tree
Hide file tree
Showing 14 changed files with 852 additions and 0 deletions.
5 changes: 5 additions & 0 deletions testbench/uvm/mem/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
*-sim
snapshots
*.vcd
*.fst
uvm
106 changes: 106 additions & 0 deletions testbench/uvm/mem/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
all: simulate

# -------------------------------------
# Testbench setup
# -------------------------------------
# Check for RV_ROOT
ifeq (,$(wildcard ${RV_ROOT}/configs/veer.config))
$(error env var RV_ROOT does not point to a valid dir! Exiting!)
endif

VERILATOR ?= verilator
ifdef VERILATOR_ROOT
VERILATOR := $(VERILATOR_ROOT)/bin/verilator
endif

# Check for Verilator
ifeq ($(shell which $(VERILATOR)),)
$(error Verilator not found! Exiting!)
endif
ifneq ($(shell $(VERILATOR) --version),Verilator 5.019 devel rev v5.018-14-gdf36e9ca2)
$(warning Using $(shell $(VERILATOR) --version))
$(warning It is recommended to use Verilator revision: https://github.com/antmicro/verilator-1/commit/df36e9ca2)
endif

UVM_ROOT ?= uvm
UVM_TEST ?= mem_wr_rd_test
SNAPSHOT = verilator-uvm

VERILOG_DEFINE_FILES = \
${UVM_ROOT}/src/uvm.sv \
${RV_ROOT}/snapshots/$(SNAPSHOT)/common_defines.vh \
${RV_ROOT}/design/include/el2_def.sv \
${RV_ROOT}/snapshots/$(SNAPSHOT)/el2_pdef.vh

VERILOG_INCLUDE_DIRS = \
hdl \
${UVM_ROOT}/src \
${RV_ROOT}/design/include \
${RV_ROOT}/snapshots/$(SNAPSHOT)

VERILOG_SOURCES = \
${RV_ROOT}/design/lib/beh_lib.sv \
${RV_ROOT}/design/lib/mem_lib.sv \
$(SIM_DIR)/el2_lsu_dccm_mem.sv \
hdl/tbench_top.sv

# -------------------------------------
# Compilation/simulation configuration
# -------------------------------------
SIM_NAME ?= mem_tb
SIM_DIR := $(SIM_NAME)-sim
COMPILE_ARGS += --top-module tbench_top
COMPILE_ARGS += -DUVM_NO_DPI
COMPILE_ARGS += --prefix $(SIM_NAME) -o $(SIM_NAME)
COMPILE_ARGS += $(addprefix +incdir+, $(VERILOG_INCLUDE_DIRS))
EXTRA_ARGS += --timescale 1ns/1ps --error-limit 100 --trace --trace-structs
WARNING_ARGS += -Wno-lint \
-Wno-style \
-Wno-SYMRSVDWORD \
-Wno-IGNOREDRETURN \
-Wno-CONSTRAINTIGN \
-Wno-ZERODLY

# -------------------------------------
# Fetch UVM
# -------------------------------------
$(UVM_ROOT):
git clone https://github.com/antmicro/uvm-verilator -b current-patches $(UVM_ROOT)

# -------------------------------------
# Configure VeeR EL-2
# -------------------------------------
$(RV_ROOT)/snapshots/$(SNAPSHOT)/el2_param.vh:
$(RV_ROOT)/configs/veer.config -snapshot=$(SNAPSHOT) -fpga_optimize=0

# FIXME: Patch source to disable "ifdef VERILATOR". Can't undef it as it has to be set for UVM sources.
$(SIM_DIR)/el2_lsu_dccm_mem.sv:
mkdir -p $(SIM_DIR)
sed 's/ifdef VERILATOR/ifdef XXXX/g' $(RV_ROOT)/design/lsu/el2_lsu_dccm_mem.sv > $(SIM_DIR)/el2_lsu_dccm_mem.sv

# -------------------------------------
# Make UVM test with Verilator
# -------------------------------------
$(SIM_DIR)/$(SIM_NAME).mk: ${UVM_ROOT} $(RV_ROOT)/snapshots/$(SNAPSHOT)/el2_param.vh $(VERILOG_SOURCES) $(wildcard hdl/*.sv)
$(VERILATOR) --cc --exe --main --timing -Mdir $(SIM_DIR) \
${COMPILE_ARGS} ${EXTRA_ARGS} \
${VERILOG_DEFINE_FILES} \
${VERILOG_SOURCES} \
${WARNING_ARGS}

$(SIM_DIR)/$(SIM_NAME): $(SIM_DIR)/$(SIM_NAME).mk
$(MAKE) -C $(SIM_DIR) $(BUILD_ARGS) -f $(SIM_NAME).mk

simulate: $(SIM_DIR)/$(SIM_NAME).mk $(SIM_DIR)/$(SIM_NAME)
$(SIM_DIR)/$(SIM_NAME) +UVM_TESTNAME=$(UVM_TEST)

clean:
rm -rf snapshots
rm -rf simv*.daidir csrc
rm -rf csrc* simv*
rm -rf *.vcd *.fst
rm -rf $(SIM_DIR)
rm -rf $(UVM_DIR)


.PHONY: simulate clean
53 changes: 53 additions & 0 deletions testbench/uvm/mem/hdl/mem_agent.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
//-------------------------------------------------------------------------
// mem_agent - www.verificationguide.com
//-------------------------------------------------------------------------

`include "mem_seq_item.sv"
`include "mem_sequencer.sv"
`include "mem_sequence.sv"
`include "mem_driver.sv"
`include "mem_monitor.sv"

class mem_agent extends uvm_agent;

//---------------------------------------
// component instances
//---------------------------------------
mem_driver driver;
mem_sequencer sequencer;
mem_monitor monitor;

`uvm_component_utils(mem_agent)

//---------------------------------------
// constructor
//---------------------------------------
function new (string name, uvm_component parent);
super.new(name, parent);
endfunction : new

//---------------------------------------
// build_phase
//---------------------------------------
function void build_phase(uvm_phase phase);
super.build_phase(phase);

monitor = mem_monitor::type_id::create("monitor", this);

//creating driver and sequencer only for ACTIVE agent
if(get_is_active() == UVM_ACTIVE) begin
driver = mem_driver::type_id::create("driver", this);
sequencer = mem_sequencer::type_id::create("sequencer", this);
end
endfunction : build_phase

//---------------------------------------
// connect_phase - connecting the driver and sequencer port
//---------------------------------------
function void connect_phase(uvm_phase phase);
if(get_is_active() == UVM_ACTIVE) begin
driver.seq_item_port.connect(sequencer.seq_item_export);
end
endfunction : connect_phase

endclass : mem_agent
60 changes: 60 additions & 0 deletions testbench/uvm/mem/hdl/mem_base_test.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
//-------------------------------------------------------------------------
// mem_test - www.verificationguide.com
//-------------------------------------------------------------------------

`include "mem_env.sv"
class mem_model_base_test extends uvm_test;

`uvm_component_utils(mem_model_base_test)

//---------------------------------------
// env instance
//---------------------------------------
mem_model_env env;

//---------------------------------------
// constructor
//---------------------------------------
function new(string name = "mem_model_base_test",uvm_component parent=null);
super.new(name,parent);
endfunction : new

//---------------------------------------
// build_phase
//---------------------------------------
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);

// Create the env
env = mem_model_env::type_id::create("env", this);
endfunction : build_phase

//---------------------------------------
// end_of_elobaration phase
//---------------------------------------
virtual function void end_of_elaboration();
//print's the topology
print();
endfunction

//---------------------------------------
// end_of_elobaration phase
//---------------------------------------
function void report_phase(uvm_phase phase);
uvm_report_server svr;
super.report_phase(phase);

svr = uvm_report_server::get_server();
if(svr.get_severity_count(UVM_FATAL)+svr.get_severity_count(UVM_ERROR)>0) begin
`uvm_info(get_type_name(), "---------------------------------------", UVM_NONE)
`uvm_info(get_type_name(), "---- TEST FAIL ----", UVM_NONE)
`uvm_info(get_type_name(), "---------------------------------------", UVM_NONE)
end
else begin
`uvm_info(get_type_name(), "---------------------------------------", UVM_NONE)
`uvm_info(get_type_name(), "---- TEST PASS ----", UVM_NONE)
`uvm_info(get_type_name(), "---------------------------------------", UVM_NONE)
end
endfunction

endclass : mem_model_base_test
69 changes: 69 additions & 0 deletions testbench/uvm/mem/hdl/mem_driver.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
//-------------------------------------------------------------------------
// mem_driver - www.verificationguide.com
//-------------------------------------------------------------------------

`define DRIV_IF vif

class mem_driver extends uvm_driver #(mem_seq_item);

//---------------------------------------
// Virtual Interface
//---------------------------------------
virtual mem_if vif;
`uvm_component_utils(mem_driver)

//---------------------------------------
// Constructor
//---------------------------------------
function new (string name, uvm_component parent);
super.new(name, parent);
endfunction : new

//---------------------------------------
// build phase
//---------------------------------------
function void build_phase(uvm_phase phase);
super.build_phase(phase);
if(!uvm_config_db#(virtual mem_if)::get(this, "", "vif", vif))
`uvm_fatal("NO_VIF",{"virtual interface must be set for: ",get_full_name(),".vif"});
endfunction: build_phase

//---------------------------------------
// run phase
//---------------------------------------
virtual task run_phase(uvm_phase phase);
forever begin
seq_item_port.get_next_item(req);
drive();
seq_item_port.item_done();
end
endtask : run_phase

//---------------------------------------
// drive - transaction level to signal level
// drives the value's from seq_item to interface signals
//---------------------------------------
virtual task drive();
`DRIV_IF.wr_en <= 0;
`DRIV_IF.rd_en <= 0;
@(posedge vif.clk);

`DRIV_IF.addr <= req.addr;

if(req.wr_en) begin // write operation
`uvm_info(get_type_name(), $sformatf("WR: 0x%08X <= 0x%08X", req.addr, req.wdata), UVM_LOW)
`DRIV_IF.wr_en <= 1'b1;//req.wr_en;
`DRIV_IF.wdata <= req.wdata;
@(posedge vif.clk);
end
else if(req.rd_en) begin //read operation
`DRIV_IF.rd_en <= 1'b1;//req.rd_en;
@(posedge vif.clk);
`DRIV_IF.rd_en <= 0;
@(posedge vif.clk);
req.rdata = `DRIV_IF.rdata;
`uvm_info(get_type_name(), $sformatf("RD: 0x%08X => 0x%08X", req.addr, req.rdata), UVM_LOW)
end

endtask : drive
endclass : mem_driver
42 changes: 42 additions & 0 deletions testbench/uvm/mem/hdl/mem_env.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
//-------------------------------------------------------------------------
// mem_env - www.verificationguide.com
//-------------------------------------------------------------------------

`include "mem_agent.sv"
`include "mem_scoreboard.sv"

class mem_model_env extends uvm_env;

//---------------------------------------
// agent and scoreboard instance
//---------------------------------------
mem_agent mem_agnt;
mem_scoreboard mem_scb;

`uvm_component_utils(mem_model_env)

//---------------------------------------
// constructor
//---------------------------------------
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction : new

//---------------------------------------
// build_phase - crate the components
//---------------------------------------
function void build_phase(uvm_phase phase);
super.build_phase(phase);

mem_agnt = mem_agent::type_id::create("mem_agnt", this);
mem_scb = mem_scoreboard::type_id::create("mem_scb", this);
endfunction : build_phase

//---------------------------------------
// connect_phase - connecting monitor and scoreboard port
//---------------------------------------
function void connect_phase(uvm_phase phase);
mem_agnt.monitor.item_collected_port.connect(mem_scb.item_collected_export);
endfunction : connect_phase

endclass : mem_model_env
18 changes: 18 additions & 0 deletions testbench/uvm/mem/hdl/mem_interface.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//-------------------------------------------------------------------------
// mem_interface - www.verificationguide.com
//-------------------------------------------------------------------------

interface mem_if (input logic clk,reset);

`include "el2_param.vh" ;

//---------------------------------------
//declaring the signals
//---------------------------------------
logic [pt.DCCM_BITS-1:0] addr;
logic wr_en;
logic rd_en;
logic [pt.DCCM_FDATA_WIDTH-1:0] wdata;
logic [pt.DCCM_FDATA_WIDTH-1:0] rdata;

endinterface
Loading

0 comments on commit e161f59

Please sign in to comment.