Skip to content

Commit

Permalink
Merge pull request #131 from antmicro/verilator-uvm-testbench
Browse files Browse the repository at this point in the history
Add LSU DCCM UVM testbench for Verilator
  • Loading branch information
kgugala authored Nov 9, 2023
2 parents 61739fe + 4a8e19d commit 0faacff
Show file tree
Hide file tree
Showing 16 changed files with 644 additions and 3 deletions.
17 changes: 14 additions & 3 deletions .github/workflows/build-verilator.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,20 @@ jobs:
verilator:
name: Build Verilator
runs-on: ubuntu-latest
strategy:
matrix:
include:
- version: v5.010
repo: verilator/verilator
commit: v5.010
- version: uvm
repo: antmicro/verilator-1
commit: df36e9ca2597aebe4b92c72461d945745b36c3e0
env:
TOOL_NAME: verilator
TOOL_VERSION: v5.010
TOOL_VERSION: ${{ matrix.version }}
TOOL_REPO: ${{ matrix.repo }}
TOOL_COMMIT: ${{ matrix.commit }}
DEBIAN_FRONTEND: "noninteractive"

steps:
Expand Down Expand Up @@ -56,9 +67,9 @@ jobs:
run: |
export CCACHE_DIR=/opt/verilator/.cache
ccache --show-config | grep cache_dir
git clone https://github.com/verilator/verilator
git clone https://github.com/${{ env.TOOL_REPO }} verilator
pushd verilator
git checkout ${{ env.TOOL_VERSION }}
git checkout ${{ env.TOOL_COMMIT }}
autoconf
./configure --prefix=/opt/verilator
make -j `nproc`
Expand Down
5 changes: 5 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ jobs:
needs: [Build-Verilator, Build-Spike]
uses: ./.github/workflows/test-riscof.yml

Test-UVM:
name: Test-UVM
needs: [Build-Verilator]
uses: ./.github/workflows/test-uvm.yml

Report-Coverage:
name: Report-Coverage
needs: [Test-Regression, Test-Verification, Test-RISCV-DV, Test-RISCOF]
Expand Down
84 changes: 84 additions & 0 deletions .github/workflows/test-uvm.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
name: VeeR-EL2 verification

on:
workflow_call:

jobs:
tests:
name: UVM tests
runs-on: ubuntu-latest
env:
CCACHE_DIR: "/opt/uvm/.cache/"
VERILATOR_VERSION: uvm
DEBIAN_FRONTEND: "noninteractive"
steps:
- name: Setup repository
uses: actions/checkout@v3
with:
submodules: recursive

- name: Setup Cache Metadata
id: cache_metadata
run: |
date=$(date +"%Y_%m_%d")
time=$(date +"%Y%m%d_%H%M%S_%N")
cache_verilator_restore_key=cache_verilator_
cache_verilator_key=${cache_verilator_restore_key}${{ env.VERILATOR_VERSION }}
cache_test_restore_key=${{ matrix.test }}_${{ matrix.coverage }}_
cache_test_key=${cache_test_restore_key}${time}
echo "date=$date" | tee -a "$GITHUB_ENV"
echo "time=$time" | tee -a "$GITHUB_ENV"
echo "cache_verilator_restore_key=$cache_verilator_restore_key" | tee -a "$GITHUB_ENV"
echo "cache_verilator_key=$cache_verilator_key" | tee -a "$GITHUB_ENV"
echo "cache_test_restore_key=$cache_test_restore_key" | tee -a "$GITHUB_ENV"
echo "cache_test_key=$cache_test_key" | tee -a "$GITHUB_ENV"
- name: Restore verilator cache
id: cache-verilator-restore
uses: actions/cache/restore@v3
with:
path: |
/opt/verilator
/opt/verilator/.cache
key: ${{ env.cache_verilator_key }}
restore-keys: ${{ env.cache_verilator_restore_key }}

- name: Setup tests cache
uses: actions/cache@v3
id: cache-test-setup
with:
path: |
${{ env.CCACHE_DIR }}
key: ${{ env.cache_test_key }}
restore-keys: ${{ env.cache_test_restore_key }}

- name: Install prerequisities
run: |
sudo apt -qqy update && sudo apt -qqy --no-install-recommends install \
git build-essential cpanminus ccache
sudo cpanm Bit::Vector
- name: Setup environment
run: |
echo "/opt/verilator/bin" >> $GITHUB_PATH
RV_ROOT=`pwd`
echo "RV_ROOT=$RV_ROOT" >> $GITHUB_ENV
PYTHONUNBUFFERED=1
echo "PYTHONUNBUFFERED=$PYTHONUNBUFFERED" >> $GITHUB_ENV
- name: Build UVM testbench
run: |
make -C testbench/uvm/mem build -j$(nproc)
- name: Run UVM testbench
run: |
make -C testbench/uvm/mem simulate | tee test.out
- name: Upload test output
if: always()
uses: actions/upload-artifact@v3
with:
name: uvm_test_output
path: test.out
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
110 changes: 110 additions & 0 deletions testbench/uvm/mem/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
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

# Check Verilator version
VERILATOR_VERSION := $(shell $(VERILATOR) --version)
VERILATOR_RECOMMENDED_COMMIT := df36e9ca2
ifeq ($(findstring $(VERILATOR_RECOMMENDED_COMMIT),$(VERILATOR_VERSION)),)
$(warning Using $(VERILATOR_VERSION))
$(warning It is recommended to use Verilator revision: https://github.com/antmicro/verilator-1/commit/$(VERILATOR_RECOMMENDED_COMMIT))
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
# -------------------------------------
verilate: ${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}

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

simulate: build
$(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: verilate build simulate clean
36 changes: 36 additions & 0 deletions testbench/uvm/mem/hdl/dccm_agent.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
`include "dccm_transaction_sequence_item.sv"
`include "dccm_sequencer.sv"
`include "dccm_sequence.sv"
`include "dccm_driver.sv"
`include "dccm_monitor.sv"

class dccm_agent extends uvm_agent;

dccm_driver driver;
dccm_sequencer sequencer;
dccm_monitor monitor;

`uvm_component_utils(dccm_agent)

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

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

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

if (get_is_active() == UVM_ACTIVE) begin
driver = dccm_driver::type_id::create("driver", this);
sequencer = dccm_sequencer::type_id::create("sequencer", this);
end
endfunction : build_phase

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 : dccm_agent
40 changes: 40 additions & 0 deletions testbench/uvm/mem/hdl/dccm_base_test.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
`include "dccm_agent.sv"
`include "dccm_scoreboard.sv"
class mem_model_base_test extends uvm_test;

`uvm_component_utils(mem_model_base_test)

dccm_agent agent;
dccm_scoreboard scoreboard;

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

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

agent = dccm_agent::type_id::create("agent", this);
scoreboard = dccm_scoreboard::type_id::create("scoreboard", this);
endfunction : build_phase

function void connect_phase(uvm_phase phase);
agent.monitor.transaction_analisys_port.connect(scoreboard.item_collected_export);
endfunction : connect_phase

function void report_phase(uvm_phase phase);
uvm_report_server svr;
int errors;
super.report_phase(phase);

svr = uvm_report_server::get_server();
errors = svr.get_severity_count(UVM_FATAL) + svr.get_severity_count(UVM_ERROR);
if (errors > 0) begin
`uvm_info(get_type_name(), "DCCM TEST FAILED!!", UVM_NONE)
`uvm_info(get_type_name(), $sformatf("Found %d errors", errors), UVM_NONE)
end else begin
`uvm_info(get_type_name(), "DCCM TEST PASSED!!", UVM_NONE)
end
endfunction

endclass : mem_model_base_test
46 changes: 46 additions & 0 deletions testbench/uvm/mem/hdl/dccm_driver.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
class dccm_driver extends uvm_driver #(dccm_transaction_sequence_item);

virtual dccm_interface memory_vif;
`uvm_component_utils(dccm_driver)

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

function void build_phase(uvm_phase phase);
super.build_phase(phase);
if (!uvm_config_db#(virtual dccm_interface)::get(this, "", "memory_vif", memory_vif))
`uvm_fatal("NO_VIF", {"virtual interface must be set for: ", get_full_name(), ".memory_vif"});
endfunction : build_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

virtual task drive();
memory_vif.wr_en <= 0;
memory_vif.rd_en <= 0;
@(posedge memory_vif.clk);

memory_vif.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)
memory_vif.wr_en <= 1'b1; //req.wr_en;
memory_vif.wdata <= req.wdata;
@(posedge memory_vif.clk);
end else if (req.rd_en) begin //read operation
memory_vif.rd_en <= 1'b1; //req.rd_en;
@(posedge memory_vif.clk);
memory_vif.rd_en <= 0;
@(posedge memory_vif.clk);
req.rdata = memory_vif.rdata;
`uvm_info(get_type_name(), $sformatf("RD: 0x%08X => 0x%08X", req.addr, req.rdata), UVM_LOW)
end

endtask : drive
endclass : dccm_driver
15 changes: 15 additions & 0 deletions testbench/uvm/mem/hdl/dccm_interface.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
interface dccm_interface (
input logic clk,
reset
);

`include "el2_param.vh"
;

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 0faacff

Please sign in to comment.