Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
M0stafaRady committed Nov 21, 2023
2 parents b0d9bfd + 21577e6 commit 8c04538
Show file tree
Hide file tree
Showing 30 changed files with 167 additions and 210 deletions.
6 changes: 5 additions & 1 deletion .github/workflows/caravel_cocotb.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,11 @@ jobs:
python3 -m pip install --upgrade pip
pip install -r requirements.txt
python3 -m pip install --upgrade --no-cache-dir volare
pip install flake8
- name: Run Flake8
run: flake8 $GITHUB_WORKSPACE/cocotb --config $GITHUB_WORKSPACE/cocotb/.flake8

- name: Install caravel_cocotb
run: |
cd $GITHUB_WORKSPACE/cocotb
Expand Down
2 changes: 2 additions & 0 deletions cocotb/.flake8
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[flake8]
ignore = E203,E266,E302,E501,W503,E731
23 changes: 23 additions & 0 deletions cocotb/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
PACKAGE_NAME = caravel_cocotb

.PHONY: clean test lint dist upload release

clean:
rm -rf dist build *.egg-info
rm -rf caravel mgmt_core pdk_root user_project_root

test:
pip install .
python3 caravel_cocotb/CI/main.py

lint:
flake8

dist: clean
python3 setup.py sdist bdist_wheel

upload: dist
twine upload dist/*

release: lint test dist upload

2 changes: 1 addition & 1 deletion cocotb/caravel_cocotb/CI/base_class.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ def configure_logger(self):
formatter = logging.Formatter("%(levelname)s@%(asctime)s: [%(name)s] %(message)s")
console_handler = logging.StreamHandler()
console_handler.setFormatter(formatter)
self.logger.addHandler(console_handler)
self.logger.addHandler(console_handler)
14 changes: 7 additions & 7 deletions cocotb/caravel_cocotb/CI/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,15 @@ def get_expected_tests_dir(self):
else:
sims = self.command.sim.split()
expected_tests = list()
# to get tests run by -t
# to get tests run by -t
if self.command.test is None:
self.logger.debug("Test is None")
tests = None
else:
tests = self.command.test.split()
for sim_type in sims:
for test_name in tests:
if sim_type != "GL_SDF":
if sim_type != "GL_SDF":
expected_tests.append(f"{sim_type}-{test_name}")
else:
expected_tests.append(f"{sim_type}-{test_name}-{'nom-t' if self.command.corner is None else self.command.corner}")
Expand All @@ -52,12 +52,12 @@ def get_expected_tests_dir(self):
for test in tests:
test_name = test.get("name")
sim_type = test.get("sim")
if sim_type != "GL_SDF":
if sim_type != "GL_SDF":
expected_tests.append(f"{sim_type}-{test_name}")
else:
expected_tests.append(f"{sim_type}-{test_name}-{'nom-t' if self.command.corner is None else self.command.corner}")
self.tag_path = f"{self.command.run_location if self.command.sim_path is None else self.command.sim_path}/sim/{self.command.tag}/"
full_tests_paths = [self.tag_path+expected_test for expected_test in expected_tests]
full_tests_paths = [self.tag_path + expected_test for expected_test in expected_tests]
self.logger.info(f"[get_expected_tests_dir] Expected tests: {full_tests_paths}")
return full_tests_paths

Expand All @@ -76,7 +76,7 @@ def check_exist_pass(self, all_tests_paths):
raise ValueError(f"[check_exist_pass] Test {test_path} failed")
return False
return True

def check_configs(self):
# read design_info.yaml
design_info_path = self.command.design_info if self.command.design_info is not None else f"{self.command.run_location}/design_info.yaml"
Expand All @@ -85,7 +85,7 @@ def check_configs(self):
design_info = yaml.safe_load(yaml_data)
caravel_root_exp = design_info.get("CARAVEL_ROOT")
mgmt_core_exp = design_info.get("MCW_ROOT")
pdk_root_exp = design_info.get("PDK_ROOT")+"/"+design_info.get("PDK")
pdk_root_exp = design_info.get("PDK_ROOT") + "/" + design_info.get("PDK")
pdk_exp = design_info.get("PDK")[:-1]
clk_exp = self.command.clk if self.command.clk is not None else design_info.get("clk")
max_err_exp = int(self.command.max_error) if self.command.max_error is not None else 3
Expand All @@ -107,7 +107,7 @@ def check_configs(self):
raise ValueError(f"[check_configs] PDK root mismatch: {pdk_root_exp} != {configs.get('PDK_ROOT')}")
if pdk_exp != configs.get("PDK"):
raise ValueError(f"[check_configs] PDK mismatch: {pdk_exp} != {configs.get('PDK')}")

def check_seed(self, all_tests_paths):
if self.command.seed is not None:
for test_path in all_tests_paths:
Expand Down
7 changes: 3 additions & 4 deletions cocotb/caravel_cocotb/CI/gen_run_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ def all_switches_chooser(self):
self.test_list_chooser = RandomChooser([f"{self.cocotb_path}/test_io10/test_io10.yaml", f"{self.cocotb_path}/test_mgmt_gpio/test_mgmt_gpio.yaml"])
self.design_infos_chooser = RandomChooser([None, f"{self.cocotb_path}/design_info.yaml"])
self.sims_chooser = RandomChooser([None, 'RTL', "GL", "GL_SDF", "RTL GL", "GL RTL"])
self.tags_chooser = RandomChooser([''.join(random.choice(string.ascii_lowercase) for _ in range(i)) for i in range(5,10)]) # change string length to make sure tag is unique
self.tags_chooser = RandomChooser([''.join(random.choice(string.ascii_lowercase) for _ in range(i)) for i in range(5, 10)]) # change string length to make sure tag is unique
self.max_errors_chooser = RandomChooser([None, "7", "5", "100"])
self.corners_chooser = RandomChooser([None, "nom-t", "nom-f", "nom-s", "max-t", "max-f", "max-s", "min-t", "min-f", "min-s"])
self.seed_chooser = RandomChooser([None] + [random.randint(0, 100000) for _ in range(5)])
Expand Down Expand Up @@ -152,13 +152,12 @@ def generate_command_str(self, command):
verbosity = f" -verbosity {command.verbosity} " if command.verbosity is not None else ""
compile = " -compile" if command.compile is not None else ""
CI = " --CI" if command.CI is not None else ""
check_commits = " -check_commits" if command.check_commits is not None else ""
# check_commits = " -check_commits" if command.check_commits is not None else ""
# TODO for now remove using {check_commits}
command = f"cd {command.run_location} && caravel_cocotb {test}{design_info}{sim}{max_error}{corner}{seed}{no_wave}{clk}{macro}{sim_path}{verbosity}{compile}{CI} -tag {command.tag}"
return command



class RandomChooser:
def __init__(self, items):
self.items = items.copy()
Expand All @@ -176,4 +175,4 @@ def choose_next(self):
self.reset()
chosen_item = self.shuffled_items[self.index]
self.index += 1
return chosen_item
return chosen_item
1 change: 0 additions & 1 deletion cocotb/caravel_cocotb/CI/setup_env.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,3 @@ def clone_repo(self, repo_url, target_dir, branch=None, commit=None, depth=None)

def checkout_commit(self, repo_dir, commit):
subprocess.run(["git", "checkout", commit], cwd=repo_dir, check=True)

2 changes: 1 addition & 1 deletion cocotb/caravel_cocotb/VIP/register_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,4 +162,4 @@ def write(self, data, select):
if sel == "1":
byte = data >> (index * 8) & 0xFF
self.value[index] = byte
cocotb.log.debug(f"[Register][write] value={[hex(hex_val) for hex_val in self.value]}, select={bin(select)[2:][::-1]} data={hex(data)} value[0]={self.value[0]}")
cocotb.log.debug(f"[Register][write] value={[hex(hex_val) for hex_val in self.value]}, select={bin(select)[2:][::-1]} data={hex(data)} value[0]={self.value[0]}")
12 changes: 6 additions & 6 deletions cocotb/caravel_cocotb/VIP/wishbone.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import cocotb
import cocotb
from cocotb.triggers import RisingEdge


Expand Down Expand Up @@ -35,12 +35,12 @@ async def valid_cycle(self):
self.registers.reset()
continue

# wait check for valid cycle
# wait check for valid cycle
if self.wishbone_in["cyc"].get_val() == 0 or self.wishbone_in["stb"].get_val() == 0:
self.wishbone_out["ack"].set_val(0)
continue

# check for valid address
# check for valid address
if not self.registers.is_valid_address(self.wishbone_in["addr"].get_val()):
self.wishbone_out["ack"].set_val(0)
cocotb.log.error(f"[WishboneInterface][valid_cycle] trying to access invalid address {hex(self.wishbone_in['addr'].get_val())} the firmware will stuck waiting for ack that will never be sent")
Expand All @@ -55,7 +55,7 @@ async def read_write_op(self):
await self.valid_cycle()
self.wishbone_out["ack"].set_val(1)

# read operation
# read operation
if self.wishbone_in["we"].get_val() == 0:
cocotb.log.debug(f"[WishboneInterface][read_write_op] start reading address {hex(self.wishbone_in['addr'].get_val())}")
data = self.registers.read(self.wishbone_in["addr"].get_val(), self.wishbone_in["sel"].get_val())
Expand Down Expand Up @@ -85,6 +85,6 @@ def __init__(self, hdl):

def set_val(self, val):
self.hdl.value = val

def get_hdl(self):
return self.hdl
return self.hdl
18 changes: 8 additions & 10 deletions cocotb/caravel_cocotb/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# -*- coding: utf-8 -*-
from caravel_cocotb.scripts.verify_cocotb.RunFlow import RunFLow, CocotbArgs
import argparse
from caravel_cocotb.version import __version__


def main():
Expand All @@ -23,8 +24,7 @@ def main():
help="Simulation type RTL,GL & GL_SDF provided only when run -test<takes list as input>",
)
parser.add_argument("-testlist", "-tl", nargs="+",
help="path of testlist to be run"
)
help="path of testlist to be run")
parser.add_argument(
"-tag",
help="provide tag of the run default would be regression name and if no regression is provided would be run_<random float>_<timestamp>_"
Expand Down Expand Up @@ -87,14 +87,11 @@ def main():
action="store_true",
help='force recompilation',
)
parser.add_argument("--run_defaults", action="store_true", help=argparse.SUPPRESS) # this used to run the default tests the flag is hidden because it just used with caravel verification flow
parser.add_argument("--CI", action="store_true", help=argparse.SUPPRESS) #used only for CI to run docker in non interactive mode
parser.add_argument("-no_gen_defaults", action="store_true", help="don't run gen_gpio_defaults script")
parser.add_argument(
"-verilator",
action="store_true",
help='use verilator to compile',
)
parser.add_argument("--run_defaults", action="store_true", help=argparse.SUPPRESS) # this used to run the default tests the flag is hidden because it just used with caravel verification flow
parser.add_argument("--CI", action="store_true", help=argparse.SUPPRESS) # used only for CI to run docker in non interactive mode
parser.add_argument("-no_gen_defaults", action="store_true", help="don't run gen_gpio_defaults script")
# Add a --version option
parser.add_argument('--version', action='version', version='%(prog)s ' + __version__)
args = parser.parse_args()
# Arguments = namedtuple("Arguments","regression test sim corner testlist tag maxerr vcs cov checker_en caravan emailto seed no_wave clk lint arm sdf_setup")
# arg = Arguments(args.regression ,args.test ,args.sim ,args.corner ,args.testlist ,args.tag ,args.maxerr ,args.vcs ,args.cov ,args.checkers_en ,args.caravan ,args.emailto ,args.seed ,args.no_wave ,args.clk ,args.lint ,args.arm ,args.sdf_setup)
Expand All @@ -106,6 +103,7 @@ def main():
cocotb_args.argparse_to_CocotbArgs(args)
RunFLow(cocotb_args)


if __name__ == "__main__":
# Call the main function
main()
Expand Down
13 changes: 6 additions & 7 deletions cocotb/caravel_cocotb/caravel_interfaces.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from caravel_cocotb.interfaces.caravel import Caravel_env
from caravel_cocotb.interfaces.SPI import SPI
from caravel_cocotb.interfaces.UART import UART
from caravel_cocotb.interfaces.common_functions.test_functions import test_configure
from caravel_cocotb.interfaces.common_functions.test_functions import report_test
from caravel_cocotb.interfaces.common import GPIO_MODE

from caravel_cocotb.interfaces.caravel import Caravel_env # noqa: F401
from caravel_cocotb.interfaces.SPI import SPI # noqa: F401
from caravel_cocotb.interfaces.UART import UART # noqa: F401
from caravel_cocotb.interfaces.common_functions.test_functions import test_configure # noqa: F401
from caravel_cocotb.interfaces.common_functions.test_functions import report_test # noqa: F401
from caravel_cocotb.interfaces.common import GPIO_MODE # noqa: F401
4 changes: 2 additions & 2 deletions cocotb/caravel_cocotb/docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@
#
import os
import sys
## add C code XML
import subprocess

sys.path.insert(0, os.path.abspath("../.."))
sys.path.insert(0, os.path.abspath("../../tests/common_functions"))

## add C code XML
import subprocess

# subprocess.call('make clean', shell=True)
subprocess.call("cd ../Doxgen ; doxygen sample_text.conf", shell=True)
Expand Down
24 changes: 11 additions & 13 deletions cocotb/caravel_cocotb/interfaces/SPI.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def __init__(self, caravelEnv: Caravel_env, clk_period=None, spi_pins={"CSB": 3,
self.caravelEnv = caravelEnv
self.spi_pins = spi_pins
# if clock period is not given, use caravel clock * 3
self.clk_period = clk_period if clk_period is not None else self.caravelEnv.get_clock_obj().period*3 / 1000
self.clk_period = clk_period if clk_period is not None else self.caravelEnv.get_clock_obj().period * 3 / 1000
self.caravelEnv.drive_gpio_in(self.spi_pins["SDO"], 0)
# self._setup_spi_clk()

Expand Down Expand Up @@ -98,18 +98,18 @@ async def _hk_write_read_byte(self, data):
def _get_cycle_number(self):

current_time = cocotb.utils.get_sim_time("ns")
cycle_num = (current_time - self.start_time)/self.clk_period
cycle_num = (current_time - self.start_time) / self.clk_period
return cycle_num

async def disable_csb(self):
"""
Disables the housekeeping SPI transmission by driving the CSB line high.
**Note:** The function waits for 2 clock cycles before disabling to ensure that the previous writing command has been applied.
**Note:** The function waits for 2 clock cycles before disabling to ensure that the previous writing command has been applied.
It then drives the CSB line high and kills the SPI clock.Finally, the function waits for some time to ensure that the disable has taken effect.
"""
cocotb.log.info("[SPI][disable_csb] disable housekeeping SPI transmission")
# should wait for 2 clock cycles before disabling
# should wait for 2 clock cycles before disabling
# to wait until writing command got applied
await Timer(self.clk_period, "ns")
await Timer(self.clk_period, "ns")
Expand All @@ -131,7 +131,7 @@ async def enable_csb(self):
# must wait for some time for the disable get affected
await Timer(self.clk_period, "ns")
self._setup_spi_clk()
await Timer(self.clk_period*0.5, "ns")
await Timer(self.clk_period * 0.5, "ns")
self.caravelEnv.drive_gpio_in(self.spi_pins["CSB"], 0)

async def write_reg_spi(self, address, data, disable_csb: bool = True):
Expand Down Expand Up @@ -159,7 +159,6 @@ async def read_reg_spi(self, address, disable_csb: bool = True):
"""
Reads a byte from a register at the given address over the housekeeping SPI interface.
:param address: The address of the register to read from.
:type address: int
:param disable_csb: Whether to disable the chip select line after reading the byte. Defaults to True.
Expand Down Expand Up @@ -206,7 +205,7 @@ async def read_write_reg_spi(self, address, data, disable_csb: bool = True):
if disable_csb:
await self.disable_csb()
return data

async def write_reg_spi_nbytes(self, address, data, n_bytes, disable_csb: bool = True):
"""
Writes to `n_bytes` bytes starting from the register at `address` over the housekeeping SPI.
Expand Down Expand Up @@ -284,7 +283,7 @@ async def read_write_reg_nbytes(self, address, data_in, n_bytes, disable_csb: bo
async def reg_spi_user_pass_thru(self, send_data: list, read_byte_num: int = 0, disable_csb: bool = True):
"""
Sends SPI data to a housekeeping SPI using user pass-thru command.
:param send_data: A list of data to be sent includeing the commands and addresses.
:type send_data: list
:param read_byte_num: expected number of bytes to be read defaults to 0.
Expand Down Expand Up @@ -312,13 +311,13 @@ async def reg_spi_user_pass_thru(self, send_data: list, read_byte_num: int = 0,
async def reg_spi_mgmt_pass_thru_read(self, address: int, read_byte_num: int = 1, disable_csb: bool = True):
"""
Sends SPI read data command to a housekeeping SPI using managment pass-thru command.
:param address: The address of the register to read.
:type address: int
:param read_byte_num: expected number of bytes to be read defaults to 1.
:type read_byte_num: int
:param disable_csb: Whether to disable CSB after the transaction defaults to True.
:type disable_csb: bool
:type disable_csb: bool
"""
cocotb.log.debug(f"[SPI][reg_spi_mgmt_pass_thru_read] read addr {hex(address)}")
await self.enable_csb()
Expand All @@ -330,7 +329,7 @@ async def reg_spi_mgmt_pass_thru_read(self, address: int, read_byte_num: int = 1
addr_bits = bin(address)[2:].zfill(24)
cocotb.log.debug(f"[SPI][reg_spi_mgmt_pass_thru_read] send addr {addr_bits}")
for i in range(3):
address_byte = int(addr_bits[i*8:(i+1)*8], 2)
address_byte = int(addr_bits[i * 8:(i + 1) * 8], 2)
cocotb.log.debug(f"[SPI][reg_spi_mgmt_pass_thru_read] send addr {hex(address_byte)} i = {i}")
await self._hk_write_byte(address_byte)
# READ
Expand All @@ -343,7 +342,7 @@ async def reg_spi_mgmt_pass_thru_read(self, address: int, read_byte_num: int = 1
await self.disable_csb()
return data

# use for configure in mgmt pass thru or user pass thru or any other command that doesn't have a function
# use for configure in mgmt pass thru or user pass thru or any other command that doesn't have a function
async def reg_spi_op(self, command, address, disable_csb: bool = True):
"""
Perform a register SPI operation.
Expand Down Expand Up @@ -381,4 +380,3 @@ class SPI_COMMAND(IntEnum):
WRITE_READ = 0xC0
USER_PASS_THRU = 0x02
MGMT_PATH_THRU = 0xC4

2 changes: 1 addition & 1 deletion cocotb/caravel_cocotb/interfaces/UART.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ async def start_of_tx(self):
if self.caravelEnv.dut._id(f"gpio{self.uart_pins['tx']}_monitor", False).value == 1:
continue # to skip latches
await Timer(self.bit_time_ns - 2, units="ns")
await Timer(int(self.bit_time_ns/2), units="ns") # read the bit from the middle
await Timer(int(self.bit_time_ns / 2), units="ns") # read the bit from the middle
break

async def uart_send_char(self, char):
Expand Down
2 changes: 1 addition & 1 deletion cocotb/caravel_cocotb/interfaces/caravel.py
Original file line number Diff line number Diff line change
Expand Up @@ -571,7 +571,7 @@ def setup_clock(self, period, unit="ns") -> cocotb.clock.Clock:
def get_clock_obj(self) -> cocotb.clock.Clock:
"""return the used clock object of cocotb.clock.Clock used mostly to get info about simulation time or clock period info"""
return self.clock_obj

def get_clock_period(self) -> int:
"""return the used clock period in ns"""
return self.clock_obj.period / 1000
Loading

0 comments on commit 8c04538

Please sign in to comment.