Skip to content

Commit b4efd28

Browse files
committed
[ci] Have an OSS-Formal CI Pass
This commit introduces a new ci job which invokes the OS formal flow. It uses the nix flake, which contains all the necessary dependencies. With everything already in cache this takes less than an hour on pomona. An input (max-mem) is provided to limit memory usage.
1 parent 72e1848 commit b4efd28

File tree

2 files changed

+55
-4
lines changed

2 files changed

+55
-4
lines changed

.github/workflows/ci-formal.yml

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Copyright lowRISC contributors.
2+
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
3+
# SPDX-License-Identifier: Apache-2.0
4+
5+
# GitHub Actions CI build configuration
6+
7+
name: Ibex OSS Formal CI
8+
9+
on:
10+
pull_request:
11+
branches:
12+
- '*'
13+
14+
jobs:
15+
fv:
16+
name: Run the Open-Source FV flow
17+
runs-on: nixos
18+
concurrency:
19+
group: oss-fv
20+
cancel-in-progress: false # Only do one oss-fv job at a time, since we will use a huge amount of memory
21+
steps:
22+
- name: Notify about queued execution
23+
run: |
24+
echo "Warning: This job will block other oss-fv jobs until it finishes, since it uses a lot of memory."
25+
26+
- uses: actions/checkout@v4
27+
28+
- name: Setup env
29+
run: |
30+
echo "NIX_CONFIG=accept-flake-config = true" >> $GITHUB_ENV
31+
32+
- name: Install Nix
33+
uses: cachix/install-nix-action@v27
34+
with:
35+
extra_nix_config: |
36+
substituters = https://nix-cache.lowrisc.org/public/ https://cache.nixos.org/
37+
trusted-public-keys = nix-cache.lowrisc.org-public-1:O6JLD0yXzaJDPiQW1meVu32JIDViuaPtGDfjlOopU7o= cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=
38+
39+
- name: Run OSS Env
40+
run: |
41+
source <(nix print-dev-env .#oss-dev)
42+
43+
cd dv/formal
44+
make build/aig-manip
45+
make build/all.aig SHELL=bash
46+
python3 conductor.py prove --check-complete
47+

dv/formal/conductor.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -225,13 +225,13 @@ class ProcessRunner:
225225
MAX_RUNNING = (psutil.cpu_count() or 8) - 2 # Number of CPUs, with a couple spares
226226

227227
def __init__(self):
228-
log(f"Process runner will have a maximum of {ProcessRunner.MAX_RUNNING} processes, and currently sees {global_memory_free():.3f}GB free.")
229-
230228
self.pending = []
231229
self.running = []
232230
self.first_start = time.time()
233231
self.debug_count = 0
234232

233+
log(f"Process runner will have a maximum of {ProcessRunner.MAX_RUNNING} processes, and currently sees {self.mem_avail():.3f}GB free.")
234+
235235
def append(self, proc):
236236
self.pending.insert(0, proc)
237237

@@ -244,7 +244,7 @@ def children_used_mem(self):
244244
def mem_avail(self):
245245
if args.max_mem == 0:
246246
return global_memory_free()
247-
return max(args.max_mem - self.children_used_mem(), 0)
247+
return min(global_memory_free(), max(args.max_mem - self.children_used_mem(), 0))
248248

249249
def poll(self):
250250
# Kill recently started processes until memory is OK, unless there is just one, then there's no point(?)
@@ -279,9 +279,10 @@ def poll(self):
279279

280280
asyncio.get_running_loop().call_later(ProcessRunner.POLL_DELAY, lambda: self.poll())
281281

282-
process_runner = ProcessRunner()
282+
process_runner: ProcessRunner | None = None
283283
'''Run a shell command in the global process runner'''
284284
async def shell(cmd, expected_memory = 0.0, timeout = None, debug_slow = None):
285+
assert process_runner is not None
285286
proc = Process(cmd, expected_memory=expected_memory, timeout=timeout, debug_slow=debug_slow)
286287
process_runner.append(proc)
287288
return await proc.future
@@ -720,6 +721,8 @@ async def explore_mode(by_step: list[list[str]]):
720721
log(f"Skipping proof run for step {step}, since it has just one step", c=white)
721722

722723
async def main():
724+
global process_runner
725+
723726
def preproc_name(name: str) -> tuple[int, str]:
724727
first = name.split("$")[1][5:]
725728
assert first.startswith("Step")
@@ -738,6 +741,7 @@ def group_by_step(names: list[tuple[int, str]], max=None) -> list[list[str]]:
738741
by_step.append([])
739742
return by_step
740743

744+
process_runner = ProcessRunner()
741745
process_runner.start_loop()
742746

743747
log("Reading property list", c=white)

0 commit comments

Comments
 (0)