Skip to content

Commit

Permalink
Deduplicated code, isolated common sequence definitions
Browse files Browse the repository at this point in the history
Signed-off-by: Maciej Kurc <[email protected]>
  • Loading branch information
mkurc-ant committed Sep 21, 2023
1 parent c0a76e9 commit 89305b9
Show file tree
Hide file tree
Showing 9 changed files with 303 additions and 552 deletions.
253 changes: 253 additions & 0 deletions verification/block/dma/sequences.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,253 @@
# Copyright (c) 2023 Antmicro <www.antmicro.com>
# SPDX-License-Identifier: Apache-2.0

import random
import struct

from cocotb.triggers import ClockCycles
from pyuvm import *
from testbench import (
BaseEnv,
BaseTest,
BusReadItem,
BusWriteItem,
DebugReadItem,
DebugWriteItem,
MemReadItem,
MemWriteItem,
)

# =============================================================================


class MemWriteSequence(uvm_sequence):
"""
A sequence of random memory writes
"""

def __init__(self, name, mem, dwidth=32):
super().__init__(name)
self.mem = mem
self.dwidth = dwidth

async def body(self):
mem_base = ConfigDB().get(None, "", self.mem + "_BASE")
mem_size = ConfigDB().get(None, "", self.mem + "_SIZE")

align = ConfigDB().get(None, "", "ADDR_ALIGN")

count = ConfigDB().get(None, "", "TEST_ITERATIONS")
burst = ConfigDB().get(None, "", "TEST_BURST_LEN")
gap = ConfigDB().get(None, "", "TEST_BURST_GAP")

for j in range(count):
for i in range(burst):
addr = mem_base + random.randrange(0, mem_size)
addr = (addr // align) * align

# Determine how to pack data to bytes
if self.dwidth == 32:
fmt = "<I"
elif self.dwidth == 64:
fmt = "<Q"
else:
assert False, self.dwidth

data = random.randrange(0, (1 << self.dwidth) - 1)
item = BusWriteItem(addr, struct.pack(fmt, data))

await self.start_item(item)
await self.finish_item(item)

await ClockCycles(cocotb.top.clk, gap)


class AnyMemWriteSequence(uvm_sequence):
"""
A sequence of random ICCM or DCCM writes
"""

def __init__(self, name, dwidth=32):
super().__init__(name)
self.dwidth = dwidth

async def body(self):
iccm_base = ConfigDB().get(None, "", "ICCM_BASE")
iccm_size = ConfigDB().get(None, "", "ICCM_SIZE")

dccm_base = ConfigDB().get(None, "", "DCCM_BASE")
dccm_size = ConfigDB().get(None, "", "DCCM_SIZE")

align = ConfigDB().get(None, "", "ADDR_ALIGN")

count = ConfigDB().get(None, "", "TEST_ITERATIONS")
burst = ConfigDB().get(None, "", "TEST_BURST_LEN")
gap = ConfigDB().get(None, "", "TEST_BURST_GAP")

for j in range(count):
for i in range(burst):
mem_base, mem_size = random.choice(
[
(iccm_base, iccm_size),
(dccm_base, dccm_size),
]
)

addr = mem_base + random.randrange(0, mem_size)
addr = (addr // align) * align

# Determine how to pack data to bytes
if self.dwidth == 32:
fmt = "<I"
elif self.dwidth == 64:
fmt = "<Q"
else:
assert False, self.dwidth

data = random.randrange(0, (1 << self.dwidth) - 1)
item = BusWriteItem(addr, struct.pack(fmt, data))

await self.start_item(item)
await self.finish_item(item)

await ClockCycles(cocotb.top.clk, gap)


# =============================================================================


class MemReadSequence(uvm_sequence):
"""
A sequence of random memory reads
"""

def __init__(self, name, mem):
super().__init__(name)
self.mem = mem

async def body(self):
mem_base = ConfigDB().get(None, "", self.mem + "_BASE")
mem_size = ConfigDB().get(None, "", self.mem + "_SIZE")

align = ConfigDB().get(None, "", "ADDR_ALIGN")

count = ConfigDB().get(None, "", "TEST_ITERATIONS")
burst = ConfigDB().get(None, "", "TEST_BURST_LEN")
gap = ConfigDB().get(None, "", "TEST_BURST_GAP")

for j in range(count):
for i in range(burst):
addr = mem_base + random.randrange(0, mem_size)
addr = (addr // align) * align

item = BusReadItem(addr)
await self.start_item(item)
await self.finish_item(item)

await ClockCycles(cocotb.top.clk, gap)


class AnyMemReadSequence(uvm_sequence):
"""
A sequence of random ICCM or DCCM reads
"""

def __init__(self, name):
super().__init__(name)

async def body(self):
iccm_base = ConfigDB().get(None, "", "ICCM_BASE")
iccm_size = ConfigDB().get(None, "", "ICCM_SIZE")

dccm_base = ConfigDB().get(None, "", "DCCM_BASE")
dccm_size = ConfigDB().get(None, "", "DCCM_SIZE")

align = ConfigDB().get(None, "", "ADDR_ALIGN")

count = ConfigDB().get(None, "", "TEST_ITERATIONS")
burst = ConfigDB().get(None, "", "TEST_BURST_LEN")
gap = ConfigDB().get(None, "", "TEST_BURST_GAP")

for j in range(count):
for i in range(burst):
mem_base, mem_size = random.choice(
[
(iccm_base, iccm_size),
(dccm_base, dccm_size),
]
)

addr = mem_base + random.randrange(0, mem_size)
addr = (addr // align) * align

item = BusReadItem(addr)
await self.start_item(item)
await self.finish_item(item)

await ClockCycles(cocotb.top.clk, gap)


# =============================================================================


class InvalidAddressSequence(uvm_sequence):
"""
A sequence of random bus read/write requests to addresses
outside the range accepted by the DMA module
"""

def __init__(self, name, dwidth=32):
super().__init__(name)
self.dwidth = dwidth

async def body(self):
iccm_base = ConfigDB().get(None, "", "ICCM_BASE")
iccm_size = ConfigDB().get(None, "", "ICCM_SIZE")

dccm_base = ConfigDB().get(None, "", "DCCM_BASE")
dccm_size = ConfigDB().get(None, "", "DCCM_SIZE")

pic_base = ConfigDB().get(None, "", "PIC_BASE")
pic_size = ConfigDB().get(None, "", "PIC_SIZE")

align = ConfigDB().get(None, "", "ADDR_ALIGN")

count = ConfigDB().get(None, "", "TEST_ITERATIONS")
burst = ConfigDB().get(None, "", "TEST_BURST_LEN")
gap = ConfigDB().get(None, "", "TEST_BURST_GAP")

for j in range(count):
for i in range(burst):
# Crude address randomizer
while True:
addr = random.randrange(0, (1 << 32) - 1)
addr = (addr // align) * align

if addr >= iccm_base and addr < iccm_base + iccm_size:
continue
if addr >= dccm_base and addr < dccm_base + dccm_size:
continue
if addr >= pic_base and addr < pic_base + pic_size:
continue

break

# Randomize read/write
if random.random() >= 0.5:
item = BusReadItem(addr)
else:
# Determine how to pack data to bytes
if self.dwidth == 32:
fmt = "<I"
elif self.dwidth == 64:
fmt = "<Q"
else:
assert False, self.dwidth

data = random.randrange(0, (1 << self.dwidth) - 1)
item = BusWriteItem(addr, struct.pack(fmt, data))

await self.start_item(item)
await self.finish_item(item)

await ClockCycles(cocotb.top.clk, gap)
58 changes: 3 additions & 55 deletions verification/block/dma/test_address.py
Original file line number Diff line number Diff line change
@@ -1,64 +1,12 @@
# Copyright (c) 2023 Antmicro <www.antmicro.com>
# SPDX-License-Identifier: Apache-2.0

import random
import struct

import pyuvm
from cocotb.triggers import ClockCycles
from pyuvm import *
from scoreboards import AccessScoreboard
from testbench import BaseEnv, BaseTest, BusReadItem, BusWriteItem

# =============================================================================


class TestSequenceRange(uvm_sequence):
"""
A sequencer that generates random bus read/write requests to addresses
outside the range accepted by the DMA module
"""

def __init__(self, name):
super().__init__(name)

async def body(self):
iccm_base = ConfigDB().get(None, "", "ICCM_BASE")
iccm_size = ConfigDB().get(None, "", "ICCM_SIZE")

dccm_base = ConfigDB().get(None, "", "DCCM_BASE")
dccm_size = ConfigDB().get(None, "", "DCCM_SIZE")

pic_base = ConfigDB().get(None, "", "PIC_BASE")
pic_size = ConfigDB().get(None, "", "PIC_SIZE")

align = ConfigDB().get(None, "", "ADDR_ALIGN")

for j in range(50):
# Crude address randomizer
while True:
addr = random.randrange(0, (1 << 32) - 1)
addr = (addr // align) * align

if addr >= iccm_base and addr < iccm_base + iccm_size:
continue
if addr >= dccm_base and addr < dccm_base + dccm_size:
continue
if addr >= pic_base and addr < pic_base + pic_size:
continue

break

# Randomize read/write
if random.random() >= 0.5:
item = BusReadItem(addr)
else:
data = random.randrange(0, (1 << 64) - 1)
item = BusWriteItem(addr, struct.pack("<Q", data))

await self.start_item(item)
await self.finish_item(item)

from sequences import InvalidAddressSequence
from testbench import BaseEnv, BaseTest

# =============================================================================

Expand Down Expand Up @@ -92,7 +40,7 @@ def __init__(self, name, parent):

def end_of_elaboration_phase(self):
super().end_of_elaboration_phase()
self.seq = TestSequenceRange.create("stimulus")
self.seq = InvalidAddressSequence("stimulus", dwidth=self.env.axi_bfm.dwidth)

async def run(self):
await self.seq.start(self.env.axi_seqr)
Loading

0 comments on commit 89305b9

Please sign in to comment.