Skip to content

Commit f8ec9c7

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 4d73982 commit f8ec9c7

File tree

2 files changed

+51
-4
lines changed

2 files changed

+51
-4
lines changed

.github/workflows/ci-formal.yml

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
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+
workflow_call:
11+
inputs:
12+
max-mem:
13+
description: 'Maximum memory available for use in GB. Maximum on Pomona is ~220GB, which has ~40 min proof time. Halving memory approximately doubles proof time. '
14+
required: false
15+
default: '256'
16+
17+
jobs:
18+
fv:
19+
name: Run the Open-Source FV flow
20+
runs-on: nixos
21+
steps:
22+
- uses: actions/checkout@v4
23+
24+
- name: Setup env
25+
run: |
26+
echo "NIX_CONFIG=accept-flake-config = true" >> $GITHUB_ENV
27+
28+
- name: Install Nix
29+
uses: cachix/install-nix-action@v27
30+
with:
31+
extra_nix_config: |
32+
substituters = https://nix-cache.lowrisc.org/public/ https://cache.nixos.org/
33+
trusted-public-keys = nix-cache.lowrisc.org-public-1:O6JLD0yXzaJDPiQW1meVu32JIDViuaPtGDfjlOopU7o= cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=
34+
35+
- name: Run OSS Env
36+
run: |
37+
source <(nix print-dev-env .#oss-dev)
38+
39+
cd dv/formal
40+
make build/aig-manip
41+
make build/all.aig SHELL=bash
42+
python3 conductor.py prove --check-complete --max-mem $INPUT_MAX_MEM
43+

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)