Skip to content

Lean emulator#1541

Open
Ptival wants to merge 3 commits intoriscv:masterfrom
GaloisInc:lean_emulator_ci
Open

Lean emulator#1541
Ptival wants to merge 3 commits intoriscv:masterfrom
GaloisInc:lean_emulator_ci

Conversation

@Ptival
Copy link
Copy Markdown
Contributor

@Ptival Ptival commented Feb 10, 2026

Opening this pull request for discussion about what it would take to integrate these changes upstream.

This PR contains:

  • a frontend to start an emulator based on Lean extracted from SAIL RISC-V,
  • a CI job that builds said emulator, and tests it on some ELF files.

There are, however, a couple of things that ought to be discussed:

  1. In order to parse ELF files, this adds a dependency to ELFSage. Well, almost, the project is purposefully kept compatible with an old version of Lean (see here), so we forked and modernized it. This is a new dependency. I have found it fairly easy to maintain, but I wanted to be upfront about it.
  2. Our "main" is not the cleanest, I might do a tiny bit of refactoring, but please let us know whether it would require significant changes to merge.
  3. I have extended the Lean workflow to test the extracted emulator. Unfortunately, we have to re-extract the Lean code with a smaller set of modules to get less prohibitive compilation times, and then also extract the ELF files. There might be nicer ways of achieving this without all the redundancy here, but I'm neither an expert at CMake or CI, so I'm open to ideas.

Putting this as a draft request for now.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Feb 10, 2026

Test Results

2 314 tests  ±0   2 314 ✅ ±0   31m 24s ⏱️ +4s
    1 suites ±0       0 💤 ±0 
    1 files   ±0       0 ❌ ±0 

Results for commit 1a4ce49. ± Comparison against base commit c4d3140.

♻️ This comment has been updated with latest results.

Copy link
Copy Markdown
Collaborator

@pmundkur pmundkur left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is really great!

@Timmmm
Copy link
Copy Markdown
Collaborator

Timmmm commented Feb 10, 2026

I agree this is great! I don't see any issue with merging it except potentially that not many of us really know Lean. Would you be willing to maintain it. Also what are you using it for, just out of curiosity?

(And on the other hand, learning Lean has been on my todo list for ages so maybe this is a good excuse to finally get around to it!)

@jprider63
Copy link
Copy Markdown
Contributor

I agree this is great! I don't see any issue with merging it except potentially that not many of us really know Lean. Would you be willing to maintain it. Also what are you using it for, just out of curiosity?

(And on the other hand, learning Lean has been on my todo list for ages so maybe this is a good excuse to finally get around to it!)

There's a group of us at Galois and Cambridge who have been working on Sail's Lean backend so we can help if things break.

@Ptival
Copy link
Copy Markdown
Contributor Author

Ptival commented Feb 23, 2026

Alright, I have made a lot of changes, and it's back to being reviewable:

  • I have moved the whole logic of building and running the Lean emulator in CMake. Now the CI only calls the appropriate CMake target, much nicer.
  • In order to support printing out the logging of the emulator run, I needed to pass -D PRINT_EFFECTS to sail. But there was no way to do so from the current CMake setup, so I added an option PRINT_EFFECTS that, when set, adds -D PRINT_EFFECTS to sail invocations.
  • I wanted to use the status code of the emulator run as the status code of the process, so that a failing emulator run would be a failing run for CI. Unfortunately, the original loop did not return the result. If this is okay with everyone, I'm suggesting a change where loop returns the exit code of the code being looped. I have updated one use that doesn't care about it to throw it away, and I'm demonstrating in the emulator main function its use.
  • As part of having loop return a status code, I reorganized its control flow to have a clearer single exit point, rather than the current state where the handling of the exit state happens mid-loop.

EDIT: The CI is currently failing because of this limitation:
rems-project/sail#1624

Copy link
Copy Markdown
Collaborator

@pmundkur pmundkur left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs a pre-commit fix for CI.

Does the Lean emulator need an unusual amount of CPU/memory resources to build? It's been building for quite a while on my desktop.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file needs to pass pre-commit checks. See

We recommend installing pre-commit hooks that ensure certain basic coding

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will look at the pre-commit fix.

As for the resources, I have been building it on a powerful laptop so I'm not sure.
Anecdotally, on our Github CI, the Lean emulator build seems to take ~8 minutes.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I fixed the pre-commit problem. As for the slowness of it, I'm open to suggestions, in particular:

  • maybe this could be run daily rather than per commit?
  • we could definitely trim the list of ELF files to test, it's somewhat arbitrary.

@Ptival Ptival marked this pull request as ready for review February 25, 2026 21:10
}

function loop () : unit -> unit = {
function loop () : unit -> int = {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
function loop () : unit -> int = {
function loop () : unit -> nat = {

Presumably?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, in fact I'm not sure what a Sail int is, so maybe we should be careful.

It seems we start with a htif_exit_code, with declared type bits(64), so I guess this is a sign-agnostic view of it.

I wrote int because I had in mind the typical C status codes, e.g. return -1;, where they are typically considered signed. But this is likey inconsistent with the call to unsigned at:

let exit_val = unsigned(htif_exit_code);

So the question is, either:

  • we want to view exit codes as signed, in which case we would leave int but replace unsigned(...) with signed(...), or,
  • we want to view exit codes as unsigned, in which case we would replace int with nat.

Do you have more knowledge on the reasonable thing to do here?

)
foreach(file IN LISTS LEAN_EMULATOR_TEST_ELFS)
message(STATUS "Testing Lean emulator on file ${file}")
execute_process(
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't it make more sense to add lake build ... as a normal CMake target, and then add these as CTest tests? I can sketch out the code if you don't want to learn CMake (which would be very very understandable!)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please do! I am indeed not used to CMake and have been teaching myself in order to produce what you're currently seeing.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @Timmmm , just checking on whether you have bandwidth to look into this, or if I should figure it out.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants