Skip to content

Commit

Permalink
Add supoort to verify ahb
Browse files Browse the repository at this point in the history
  • Loading branch information
M0stafaRady committed Feb 28, 2024
1 parent 230420d commit 01594d0
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 72 deletions.
15 changes: 12 additions & 3 deletions verify/uvm-python/Makefile
Original file line number Diff line number Diff line change
@@ -1,15 +1,24 @@
PLUSARGS += "+UVM_VERBOSITY=UVM_HIGH"
TOPLEVEL := top
MODULE ?= top_module
VERILOG_SOURCES ?= $(PWD)/top.v $(PWD)/IP_Utilities/rtl/aucohl_lib.v $(PWD)/IP_Utilities/rtl/aucohl_rtl.vh $(PWD)/../../hdl/rtl/bus_wrappers/EF_UART_APB.pp.v $(PWD)/../../hdl/rtl/EF_UART.v
RTL_MACROS ?= ""
VERILOG_INCLUDE_DIRS = $(PWD)/IP_Utilities/rtl $(PWD)/../../hdl/rtl $(PWD)/../../hdl/rtl/bus_wrappers
VERILOG_SOURCES ?= $(PWD)/top.v $(PWD)/IP_Utilities/rtl/aucohl_lib.v $(PWD)/IP_Utilities/rtl/aucohl_rtl.vh $(PWD)/../../hdl/rtl/bus_wrappers/EF_UART_AHBL.pp.v $(PWD)/../../hdl/rtl/bus_wrappers/EF_UART_APB.pp.v $(PWD)/../../hdl/rtl/EF_UART.v
RTL_MACROS += ""
BUS_TYPE ?= APB
ifeq ($(BUS_TYPE),APB)
RTL_MACROS += -DBUS_TYPE_APB
else ifeq ($(BUS_TYPE),AHB)
RTL_MACROS += -DBUS_TYPE_AHB
else ifeq ($(BUS_TYPE),WISHBONE)
RTL_MACROS += -DBUS_TYPE_WISHBONE
endif
# RTL_MACROS ?= "-DSKIP_WAVE_DUMP"
YAML_FILE = $(PWD)/../../EF_UART.yaml
MAKEFLAGS += --no-print-directory

# List of tests
TESTS := TX_StressTest RX_StressTest LoopbackTest PrescalarStressTest LengthParityTXStressTest LengthParityRXStressTest WriteReadRegsTest
# TESTS := WriteReadRegsTest
# TESTS := TX_StressTest

# Variable for tag - set this as required
SIM_TAG ?= default_tag
Expand Down
37 changes: 28 additions & 9 deletions verify/uvm-python/test_lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from uvm.base.uvm_globals import run_test
from EF_UVM.top_env import top_env
from uart_interface.uart_if import uart_if
from EF_UVM.wrapper_env.wrapper_interface.wrapper_if import wrapper_bus_if, wrapper_irq_if
from EF_UVM.wrapper_env.wrapper_interface.wrapper_if import wrapper_apb_if, wrapper_irq_if, wrapper_ahb_if
from cocotb_coverage.coverage import coverage_db
from cocotb.triggers import Event, First
from EF_UVM.wrapper_env.wrapper_regs import wrapper_regs
Expand Down Expand Up @@ -40,19 +40,34 @@
from EF_UVM.ip_env.ip_logger.ip_logger import ip_logger
from uart_logger.uart_logger import uart_logger

# import cProfile
# import pstats
#
from EF_UVM.wrapper_env.wrapper_agent.wrapper_ahb_driver import wrapper_ahb_driver
from EF_UVM.wrapper_env.wrapper_agent.wrapper_apb_driver import wrapper_apb_driver
from EF_UVM.wrapper_env.wrapper_agent.wrapper_ahb_monitor import wrapper_ahb_monitor
from EF_UVM.wrapper_env.wrapper_agent.wrapper_apb_monitor import wrapper_apb_monitor



@cocotb.test()
async def module_top(dut):
# profiler = cProfile.Profile()
# profiler.enable()

arr = []
# sv.value_plusargs('BUS_TYPE',arr)
BUS_TYPE = cocotb.plusargs['BUS_TYPE']
print(f"plusr agr value = {BUS_TYPE}")
pif = uart_if(dut)
w_if = wrapper_bus_if(dut)
if BUS_TYPE == "APB":
w_if = wrapper_apb_if(dut)
elif BUS_TYPE == "AHB":
w_if = wrapper_ahb_if(dut)
elif BUS_TYPE == "WISHBONE":
w_if = wrapper_wishbone_if(dut)
else:
uvm_fatal("module_top", f"unknown bus type {BUS_TYPE}")
w_irq_if = wrapper_irq_if(dut)
UVMConfigDb.set(None, "*", "ip_if", pif)
UVMConfigDb.set(None, "*", "wrapper_bus_if", w_if)
UVMConfigDb.set(None, "*", "wrapper_if", w_if)
UVMConfigDb.set(None, "*", "wrapper_irq_if", w_irq_if)
UVMConfigDb.set(None, "*", "json_file", "/home/rady/work/uvm_unit/EF_UART/EF_UART.json")
yaml_file = []
Expand Down Expand Up @@ -92,6 +107,10 @@ def build_phase(self, phase):
self.set_type_override_by_type(scoreboard.get_type(), uart_scoreboard.get_type())
self.set_type_override_by_type(ip_coverage.get_type(), uart_coverage.get_type())
self.set_type_override_by_type(ip_logger.get_type(), uart_logger.get_type())
BUS_TYPE = cocotb.plusargs['BUS_TYPE']
if BUS_TYPE == "AHB":
self.set_type_override_by_type(wrapper_apb_driver.get_type(), wrapper_ahb_driver.get_type())
self.set_type_override_by_type(wrapper_apb_monitor.get_type(), wrapper_ahb_monitor.get_type())
# self.set_type_override_by_type(ip_item.get_type(),uart_item.get_type())
# Enable transaction recording for everything
UVMConfigDb.set(self, "*", "recording_detail", UVM_FULL)
Expand All @@ -107,10 +126,10 @@ def build_phase(self, phase):
else:
uvm_fatal("NOVIF", "Could not get ip_if from config DB")

if UVMConfigDb.get(None, "*", "wrapper_bus_if", arr) is True:
UVMConfigDb.set(self, "*", "wrapper_bus_if", arr[0])
if UVMConfigDb.get(None, "*", "wrapper_if", arr) is True:
UVMConfigDb.set(self, "*", "wrapper_if", arr[0])
else:
uvm_fatal("NOVIF", "Could not get wrapper_bus_if from config DB")
uvm_fatal("NOVIF", "Could not get wrapper_if from config DB")
# set max number of uvm errors
server = UVMReportServer()
server.set_max_quit_count(3)
Expand Down
50 changes: 31 additions & 19 deletions verify/uvm-python/top.v
Original file line number Diff line number Diff line change
@@ -1,31 +1,43 @@
`timescale 1ns/1ps

module top();
wire x=0;
wire y=1;
wire z;
assign z = x+y;
wire RX;
wire TX;
reg PCLK = 0;
wire PRESETn = 1;
wire [31:0] PADDR;
wire PWRITE;
wire PSEL;
wire PENABLE;
wire [31:0] PWDATA;
wire [31:0] PRDATA;
wire PREADY;
wire irq;
// monitor inside signals
reg CLK = 0;
wire RESETn = 1;
`ifdef BUS_TYPE_APB
wire RX;
wire TX;

wire [31:0] PADDR;
wire PWRITE;
wire PSEL;
wire PENABLE;
wire [31:0] PWDATA;
wire [31:0] PRDATA;
wire PREADY;
wire irq;
EF_UART_APB dut(.rx(RX), .tx(TX), .PCLK(CLK), .PRESETn(RESETn), .PADDR(PADDR), .PWRITE(PWRITE), .PSEL(PSEL), .PENABLE(PENABLE), .PWDATA(PWDATA), .PRDATA(PRDATA), .PREADY(PREADY), .IRQ(irq));
`endif
`ifdef BUS_TYPE_AHB
wire [31:0] HADDR;
wire HWRITE;
wire HSEL = 0;
wire HREADYOUT;
wire [1:0] HTRANS=0;
wire [31:0] HWDATA;
wire [31:0] HRDATA;
wire HREADY;
wire irq;
EF_UART_AHBL dut(.rx(RX), .tx(TX), .HCLK(CLK), .HRESETn(RESETn), .HADDR(HADDR), .HWRITE(HWRITE), .HSEL(HSEL), .HTRANS(HTRANS), .HWDATA(HWDATA), .HRDATA(HRDATA), .HREADY(HREADY),.HREADYOUT(HREADYOUT), .IRQ(irq));
`endif
// monitor inside signals
wire tx_done = dut.instance_to_wrap.tx_done;
wire rx_done = dut.instance_to_wrap.rx_done;
EF_UART_APB dut(.rx(RX), .tx(TX), .PCLK(PCLK), .PRESETn(PRESETn), .PADDR(PADDR), .PWRITE(PWRITE), .PSEL(PSEL), .PENABLE(PENABLE), .PWDATA(PWDATA), .PRDATA(PRDATA), .PREADY(PREADY), .IRQ(irq));

`ifndef SKIP_WAVE_DUMP
initial begin
$dumpfile ({"waves.vcd"});
$dumpvars(0, top);
end
`endif
always #10 PCLK = !PCLK; // clk generator
always #10 CLK = !CLK; // clk generator
endmodule
92 changes: 52 additions & 40 deletions verify/uvm-python/uart_agent/uart_driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from uvm.base.uvm_config_db import UVMConfigDb
from uvm.base.uvm_object_globals import UVM_HIGH, UVM_LOW, UVM_MEDIUM
from uart_item.uart_item import uart_item
from cocotb.triggers import Timer, ClockCycles, FallingEdge, Event, RisingEdge
from cocotb.triggers import Timer, ClockCycles, FallingEdge, Event, RisingEdge, First
import cocotb
import random

Expand All @@ -19,13 +19,13 @@ def build_phase(self, phase):
if (not UVMConfigDb.get(self, "", "ip_if", arr)):
uvm_fatal(self.tag, "No interface specified for self driver instance")
else:
self.sigs = arr[0]
self.vif = arr[0]
regs_arr = []
if (not UVMConfigDb.get(self, "", "wrapper_regs", regs_arr)):
uvm_fatal(self.tag, "No json file wrapper regs")
else:
self.regs = regs_arr[0]
self.sigs = arr[0]
self.vif = arr[0]
glitches_arr = []
if (not UVMConfigDb.get(self, "", "insert_glitches", glitches_arr)):
self.insert_glitches = False
Expand All @@ -35,76 +35,88 @@ def build_phase(self, phase):
async def run_phase(self, phase):
uvm_info(self.tag, "run_phase started", UVM_LOW)
await self.reset()
# assert glitches
# assert glitches
while True:
tr = []
await self.seq_item_port.get_next_item(tr)
tr = tr[0]
if tr.direction == uart_item.RX:
uvm_info(self.tag, "Driving trans into IP: " + tr.convert2string(), UVM_MEDIUM)
await self.start_of_rx()
if self.insert_glitches:
await cocotb.start(self.add_glitches()) # assert glitches
await self.send_byte(tr.char)
uvm_info(self.tag, "finish send byte", UVM_MEDIUM)
await self.send_parity(tr)
uvm_info(self.tag, "finish send parity", UVM_MEDIUM)
await self.send_stop_bit()
uvm_info(self.tag, "finish send bit1", UVM_MEDIUM)
await self.end_of_rx(1)
uvm_info(self.tag, "finish send bit0", UVM_MEDIUM)
# add breakline 2% of the times
# if random.random() < 0.02:
# uvm_info(self.tag, "Adding breakline", UVM_MEDIUM)
# await self.break_line()
send_item_thread = await cocotb.start(self.send_item_rx(tr))
reset_thread = await cocotb.start(self.wait_reset())
await First(send_item_thread, reset_thread)
self.vif.RX.value = 1
reset_thread.kill()
send_item_thread.kill()
else:
uvm_warning(self.tag, f"invalid direction {tr.direction} send to driver", UVM_HIGH)
self.seq_item_port.item_done()


async def wait_reset(self):
await FallingEdge(self.vif.PRESETn)

async def send_item_rx(self, tr):
await self.start_of_rx()
if self.insert_glitches:
await cocotb.start(self.add_glitches()) # assert glitches
await self.send_byte(tr.char)
uvm_info(self.tag, "finish send byte", UVM_HIGH)
await self.send_parity(tr)
uvm_info(self.tag, "finish send parity", UVM_HIGH)
await self.send_stop_bit()
uvm_info(self.tag, "finish send bit1", UVM_HIGH)
await self.end_of_rx(1)
uvm_info(self.tag, "finish send bit0", UVM_HIGH)
# add breakline 2% of the times
# if random.random() < 0.02:
# uvm_info(self.tag, "Adding breakline", UVM_MEDIUM)
# await self.break_line()

async def break_line(self):
self.sigs.RX.value = 0
await ClockCycles(self.sigs.PCLK, self.num_cyc_bit * random.randint(12, 20))
self.sigs.RX.value = 1
await ClockCycles(self.sigs.PCLK, self.num_cyc_bit)
self.vif.RX.value = 0
await ClockCycles(self.vif.PCLK, self.num_cyc_bit * random.randint(12, 20))
self.vif.RX.value = 1
await ClockCycles(self.vif.PCLK, self.num_cyc_bit)

async def start_of_rx(self):
self.sigs.RX.value = 0
self.vif.RX.value = 0
self.num_cyc_bit = self.get_bit_n_cyc()
self.word_length = self.get_n_bits()
uvm_info(self.tag, "starting of start bit", UVM_HIGH)
await ClockCycles(self.sigs.PCLK, self.num_cyc_bit)
await ClockCycles(self.vif.PCLK, self.num_cyc_bit)
uvm_info(self.tag, "finifhing of start bit", UVM_HIGH)

async def send_byte(self, byte):
for i in range(self.word_length):
self.sigs.RX.value = (byte >> i) & 1
self.vif.RX.value = (byte >> i) & 1
uvm_info(self.tag, f"driving byte[{i}] = {(byte >> i) & 1}", UVM_HIGH)
await ClockCycles(self.sigs.PCLK, self.num_cyc_bit)
await ClockCycles(self.vif.PCLK, self.num_cyc_bit)

async def send_parity(self, tr):
parity_type = (self.regs.read_reg_value("CFG") >> 5) & 0x7
tr.calculate_parity(parity_type)
if tr.parity == "None":
return
self.sigs.RX.value = int(tr.parity)
self.vif.RX.value = int(tr.parity)
uvm_info(self.tag, f"driving parity = {tr.parity}", UVM_HIGH)
await ClockCycles(self.sigs.PCLK, self.num_cyc_bit)
await ClockCycles(self.vif.PCLK, self.num_cyc_bit)

async def send_stop_bit(self):
stop_bit = (self.regs.read_reg_value("CFG") >> 4) & 0x1
if stop_bit:
self.sigs.RX.value = 1
self.vif.RX.value = 1
uvm_info(self.tag, f"driving extra stop bit", UVM_HIGH)
await ClockCycles(self.sigs.PCLK, self.num_cyc_bit)
await ClockCycles(self.vif.PCLK, self.num_cyc_bit)
return

async def end_of_rx(self, extra_stop_bit=0):
self.sigs.RX.value = 1
self.vif.RX.value = 1
uvm_info(self.tag, f"start ending of RX", UVM_HIGH)
await ClockCycles(self.sigs.PCLK, self.num_cyc_bit)
await ClockCycles(self.vif.PCLK, self.num_cyc_bit)
uvm_info(self.tag, f"finished ending of RX", UVM_HIGH)
for _ in range(extra_stop_bit):
await ClockCycles(self.sigs.PCLK, self.num_cyc_bit)
await ClockCycles(self.vif.PCLK, self.num_cyc_bit)

def get_bit_n_cyc(self):
prescale = self.regs.read_reg_value("PR")
Expand All @@ -117,17 +129,17 @@ def get_n_bits(self):
return word_length

async def reset(self, num_cycles=3):
self.sigs.RX.value = 1
await ClockCycles(self.sigs.PCLK, num_cycles)
self.vif.RX.value = 1
await ClockCycles(self.vif.PCLK, num_cycles)

async def add_glitches(self):
await ClockCycles(self.sigs.PCLK, random.randint(self.num_cyc_bit, self.num_cyc_bit * 7))
await ClockCycles(self.vif.PCLK, random.randint(self.num_cyc_bit, self.num_cyc_bit * 7))
await Timer(random.randint(1, 100), units="ns")
old_val = self.sigs.RX.value.integer
self.sigs.RX.value = old_val-1
old_val = self.vif.RX.value.integer
self.vif.RX.value = old_val-1
uvm_info(self.tag, "Asserting glitch", UVM_MEDIUM)
await Timer(random.randint(1, 10), units="ns")
self.sigs.RX.value = old_val
self.vif.RX.value = old_val
# wait long before checking again

uvm_component_utils(uart_driver)
2 changes: 1 addition & 1 deletion verify/uvm-python/uart_interface/uart_if.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ class uart_if(sv_if):
# wire TX;

def __init__(self, dut):
bus_map = {"PCLK": "PCLK", "RX": "RX", "TX": "TX", "tx_done": "tx_done", "rx_done": "rx_done"}
bus_map = {"PCLK": "CLK", "PRESETn": "RESETn", "RX": "RX", "TX": "TX", "tx_done": "tx_done", "rx_done": "rx_done"}
super().__init__(dut, "", bus_map)

0 comments on commit 01594d0

Please sign in to comment.