Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tests: Improve GitHub CI action #2144

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
138 changes: 118 additions & 20 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,75 +2,173 @@ name: ci

on: [push, pull_request]


env:
GHDL_VERSION: "v4.1.0"
VERILATOR_VERSION: "v5.030"
CT_NG_VERSION: "32f288e61fee8528931bcd55bf106cf0cfb4e2a1"

jobs:
build:
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
strategy:
matrix:
python-version: ["3.8", "3.12"]
steps:
# Checkout Repository
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: Setup CCache
uses: hendrikmuhs/[email protected]
with:
create-symlink: true

# Install Tools
- name: Install Tools
run: |
sudo apt-get install wget build-essential ninja-build
sudo apt-get install wget build-essential ninja-build libtool libtool-bin
sudo apt-get install libevent-dev libjson-c-dev flex bison
sudo apt-get install libfl-dev libfl2 zlib1g-dev
sudo apt-get install libfl-dev libfl2 zlib1g-dev libncurses5-dev
sudo apt-get install llvm gnat help2man mold clang lld

- name: Set up SBT
uses: sbt/setup-sbt@v1

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: "3.9"
python-version: ${{ matrix.python-version }}
cache: "pip"
cache-dependency-path: "setup.py"

- name: Install Python dependencies
run: |
python3 -m pip install setuptools requests pexpect meson

# Install (n)Migen / LiteX / Cores
- name: Install LiteX
run: |
python3 litex_setup.py --config=full --init --install --user --dev

# Install GCC Toolchains
- name: Install GCC Toolchains
run: |
sudo python3 litex_setup.py --gcc=riscv
sudo python3 litex_setup.py --gcc=openrisc
sudo python3 litex_setup.py --gcc=powerpc

# Build / Install crosstool-ng
- name: Cache crosstool-ng
id: cache-crosstool-ng
uses: actions/cache@v3
with:
path: crosstool-ng
key: crosstool-ng-${{ env.CT_NG_VERSION }}-${{ runner.os }}

- name: Checkout crosstool-ng
if: steps.cache-crosstool-ng.outputs.cache-hit != 'true'
uses: actions/checkout@v4
with:
repository: crosstool-ng/crosstool-ng
ref: ${{ env.CT_NG_VERSION }}
path: crosstool-ng

- name: Build crosstool-ng
if: steps.cache-crosstool-ng.outputs.cache-hit != 'true'
run: |
cd crosstool-ng
./bootstrap
./configure
make -j$(nproc)

- name: Install crosstool-ng
run: |
cd crosstool-ng
sudo make install

- name: Cache x-tools
id: cache-x-tools
uses: actions/cache@v3
with:
path: x-tools
key: x-tools-${{ runner.os }}

- name: Build lm32 toolchain
if: steps.cache-x-tools.outputs.cache-hit != 'true'
run: |
unset LD_LIBRARY_PATH
ct-ng lm32-unknown-elf
sed -i -e '/CT_LOG_PROGRESS_BAR/s/y$/n/' .config
sed -i -e '/CT_LOCAL_TARBALLS_DIR/s/HOME/CT_TOP_DIR/' .config
sed -i -e '/CT_PREFIX_DIR/s/HOME/CT_TOP_DIR/' .config
ct-ng build

- name: Add toolchains to PATH
run: |
for d in $(pwd)/x-tools/*/bin; do echo "$d" >> $GITHUB_PATH; done

# Build / Install GHDL
- name: Cache GHDL
id: cache-ghdl
uses: actions/cache@v3
with:
path: ghdl
key: ghdl-${{ env.GHDL_VERSION }}-${{ runner.os }}

- name: Checkout GHDL
if: steps.cache-ghdl.outputs.cache-hit != 'true'
uses: actions/checkout@v4
with:
repository: ghdl/ghdl
ref: ${{ env.GHDL_VERSION }}
path: ghdl

- name: Build GHDL
if: steps.cache-ghdl.outputs.cache-hit != 'true'
run: |
sudo apt-get install gnat llvm
git clone https://github.com/ghdl/ghdl.git
cd ghdl
./configure --with-llvm-config
make
make -j$(nproc)

- name: Install GHDL
run: |
cd ghdl
sudo make install

# Build / Install Verilator
- name: Cache Verilator
id: cache-verilator
uses: actions/cache@v3
with:
path: verilator
key: verilator-${{ env.VERILATOR_VERSION }}-${{ runner.os }}

- name: Checkout Verilator
if: steps.cache-verilator.outputs.cache-hit != 'true'
uses: actions/checkout@v4
with:
repository: verilator/verilator
ref: ${{ env.VERILATOR_VERSION }}
path: verilator

- name: Build Verilator
if: steps.cache-verilator.outputs.cache-hit != 'true'
run: |
sudo apt-get install help2man
export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH"
git clone https://github.com/verilator/verilator
cd verilator
git checkout 7d2d32420a630befa4097170ecbf227e04e32522
autoconf
./configure
./configure CC=clang CXX=clang++
make -j$(nproc)

- name: Install Verilator
run: |
cd verilator
sudo make install

# Install (n)Migen / LiteX / Cores
- name: Install LiteX
run: |
python3 litex_setup.py --config=full --init --install --user --dev

# Install Project
- name: Install Project
run: python3 setup.py develop --user

# Test
- name: Run Tests
run: |
python3 setup.py test
run: python3 -m unittest discover -v
4 changes: 2 additions & 2 deletions litex/soc/cores/cpu/cv32e40p/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,9 @@ def add_manifest_sources(platform, manifest):
basedir = get_data_mod("cpu", "cv32e40p").data_location
with open(os.path.join(basedir, manifest), 'r') as f:
for l in f:
res = re.search('\$\{DESIGN_RTL_DIR\}/(.+)', l)
res = re.search(r'\$\{DESIGN_RTL_DIR\}/(.+)', l)
if res and not re.match('//', l):
if re.match('\+incdir\+', l):
if re.match(r'\+incdir\+', l):
platform.add_verilog_include_path(os.path.join(basedir, 'rtl', res.group(1)))
else:
platform.add_source(os.path.join(basedir, 'rtl', res.group(1)))
Expand Down
4 changes: 2 additions & 2 deletions litex/soc/cores/cpu/cv32e41p/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,9 @@ def add_manifest_sources(platform, manifest):
basedir = get_data_mod("cpu", "cv32e41p").data_location
with open(os.path.join(basedir, manifest), 'r') as f:
for l in f:
res = re.search('\$\{DESIGN_RTL_DIR\}/(.+)', l)
res = re.search(r'\$\{DESIGN_RTL_DIR\}/(.+)', l)
if res and not re.match('//', l):
if re.match('\+incdir\+', l):
if re.match(r'\+incdir\+', l):
platform.add_verilog_include_path(os.path.join(basedir, 'rtl', res.group(1)))
else:
platform.add_source(os.path.join(basedir, 'rtl', res.group(1)))
Expand Down
4 changes: 2 additions & 2 deletions litex/soc/cores/cpu/cva6/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,13 @@ def add_manifest_sources(platform, manifest):
lx_core_dir = os.path.abspath(os.path.dirname(__file__))
with open(os.path.join(manifest), 'r') as f:
for l in f:
res = re.search('\$\{(CVA6_REPO_DIR|LX_CVA6_CORE_DIR)\}/(.+)', l)
res = re.search(r'\$\{(CVA6_REPO_DIR|LX_CVA6_CORE_DIR)\}/(.+)', l)
if res and not re.match('//', l):
if res.group(1) == "LX_CVA6_CORE_DIR":
basedir = lx_core_dir
else:
basedir = cva6_dir
if re.match('\+incdir\+', l):
if re.match(r'\+incdir\+', l):
platform.add_verilog_include_path(os.path.join(basedir, res.group(2)))
else:
filename = res.group(2)
Expand Down
2 changes: 1 addition & 1 deletion litex/soc/cores/cpu/lm32/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class LM32(CPU):
variants = CPU_VARIANTS
data_width = 32
endianness = "big"
gcc_triple = "lm32-elf"
gcc_triple = ("lm32-elf", "lm32-unknown-elf")
linker_output_format = "elf32-lm32"
nop = "nop"
io_regions = {0x8000_0000: 0x8000_0000} # origin, length
Expand Down
6 changes: 3 additions & 3 deletions litex/soc/cores/cpu/openc906/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,9 @@ def add_manifest_sources(platform, manifest):
basedir = os.path.join(os.environ["OPENC906_DIR"], "C906_RTL_FACTORY")
with open(os.path.join(basedir, manifest), 'r') as f:
for l in f:
res = re.search('\$\{CODE_BASE_PATH\}/(.+)', l)
if res and not re.match('//', l):
if re.match('\+incdir\+', l):
res = re.search(r'\$\{CODE_BASE_PATH\}/(.+)', l)
if res and not re.match(r'//', l):
if re.match(r'\+incdir\+', l):
platform.add_verilog_include_path(os.path.join(basedir, res.group(1)))
else:
platform.add_source(os.path.join(basedir, res.group(1)))
Expand Down
2 changes: 1 addition & 1 deletion litex/soc/integration/export.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ def get_binutils_version():
for i, l in enumerate(os.popen(selected_triple + "-ar -V")):
# Version is last float reported in first line.
if i == 0:
version = float(re.findall("\d+\.\d+", l)[-1])
version = float(re.findall(r"\d+\.\d+", l)[-1])
return version

def apply_riscv_zicsr_march_workaround(flags):
Expand Down
35 changes: 11 additions & 24 deletions test/test_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
import tempfile
import itertools

from litex.soc.cores.cpu import CPUS

class TestIntegration(unittest.TestCase):
def boot_test(self, cpu_type="vexriscv", cpu_variant="standard", args=""):
cmd = f'litex_sim --cpu-type={cpu_type} --cpu-variant={cpu_variant} {args} --opt-level=O0 --jobs {os.cpu_count()}'
Expand Down Expand Up @@ -42,39 +44,24 @@ def boot_test(self, cpu_type="vexriscv", cpu_variant="standard", args=""):
return is_success

def test_cpu(self):
tested_cpus = [
#"cv32e40p", # (riscv / softcore)
"femtorv", # (riscv / softcore)
"firev", # (riscv / softcore)
"marocchino", # (or1k / softcore)
"naxriscv", # (riscv / softcore)
"serv", # (riscv / softcore)
"vexriscv", # (riscv / softcore)
"vexriscv_smp", # (riscv / softcore)
#"microwatt", # (ppc64 / softcore)
"neorv32", # (riscv / softcore)
]
untested_cpus = [
"blackparrot", # (riscv / softcore) -> Broken install?
"cortex_m1", # (arm / softcore) -> Proprietary code.
"cortex_m3", # (arm / softcore) -> Proprieraty code.
"cv32e41p", # (riscv / softcore) -> Broken?
"cva5", # (riscv / softcore) -> Needs to be tested.
"cva6", # (riscv / softcore) -> Needs to be tested.
"eos_s3", # (arm / hardcore) -> Hardcore.
"gowin_emcu", # (arm / hardcore) -> Hardcore.
"ibex", # (riscv / softcore) -> Broken since 2022.11.12.
"lm32", # (lm32 / softcore) -> Requires LM32 toolchain.
"minerva", # (riscv / softcore) -> Broken install? (Amaranth?)
"mor1kx", # (or1k / softcore) -> Verilator compilation issue.
"picorv32", # (riscv / softcore) -> Verilator compilation issue.
"microwatt", # (powerpc / softcore) -> GHDL?
"openc906", # (riscv / softcore) -> Missing source.
"rocket", # (riscv / softcore) -> Not enough RAM in CI.
"zynq7000", # (arm / hardcore) -> Hardcore.
"zynqmp", # (aarch64 / hardcore) -> Hardcore.
"vexiiriscv", # (riscv / softcore) -> Broken?
]

for cpu in tested_cpus:
with self.subTest(target=cpu):
for cpu in CPUS.keys():
if cpu == "None" or CPUS[cpu].category != "softcore":
continue
if cpu in untested_cpus:
continue
with self.subTest(target=cpu):
self.assertTrue(self.boot_test(cpu))

def test_buses(self):
Expand Down