Skip to content

Comments

Implement callbacks for state-changing events#494

Merged
Timmmm merged 1 commit intoriscv:masterfrom
kseniadobrovolskaya:Callbacks_for_state-changing_events
May 6, 2025
Merged

Implement callbacks for state-changing events#494
Timmmm merged 1 commit intoriscv:masterfrom
kseniadobrovolskaya:Callbacks_for_state-changing_events

Conversation

@kseniadobrovolskaya
Copy link
Contributor

@kseniadobrovolskaya kseniadobrovolskaya commented Jun 11, 2024

Add a callback API for register, PC and CSR updates, memory writes and traps. This is used for logging and RVFI instead of embedding that code in the model itself.

Copy link
Collaborator

@Timmmm Timmmm left a comment

Choose a reason for hiding this comment

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

This looks along the lines I was thinking, though I think we will still need to have RVFI support in the C emulator, so you still need the flags. It will just need to be implemented via the callbacks.

I probably wouldn't use __attribute__((weak)). If anyone is modifying the callbacks they'll have their own fork of the emulator anyway and can just delete the default ones. That's what we (Codasip) will do.

I'll get you some code to read lbits.

@Timmmm
Copy link
Collaborator

Timmmm commented Jun 11, 2024

It's something like this in C++ (adapted from our code, so this exact code isn't tested).

std::vector<uint8_t> readLbits(lbits val) {
    std::vector<uint8_t> data(val.len);

    // We should really double check the length of `val.bits` to ensure it
    // isn't actually greated than `val.len`, otherwise we are at risk of
    // a buffer overflow.
    // I think you can maybe use (mpz_sizeinbase(val.bits, 2) + 7) / 8.

    // Export the lbits. Note this doesn't pad with zeros but that's ok
    // because data is prefilled with zeros.
    mpz_export(
        // Destination buffer.
        data.data(),
        // Where to write the output size (we ignore this).
        nullptr,
        // Endianness of words (-1 = little).
        -1,
        // Size of words in bytes.
        1,
        // Endianness *within* words (0 = native). Doesn't matter in this case.
        0,
        // Number of "nail" bits (upper bits to clear in each word).
        0,
        // The GMP value. Note the sign is ignored but it should always be positive.
        val.bits);

    return data;
}

In crappy C you will have to deal with malloc manually rather than using vector.

if i == 0 then { ext_handle_data_check_error(e); return RETIRE_FAIL }
else {
vl = to_bits(sizeof(xlen), i);
if rv_enable_callbacks then csr_update_callback("vl", vl);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Having to add these manually is rather error prone and makes the code less readable. Can we do some fancy sail overloading tricks to automatically call these functions for CSR writes (e.g. something like CSR(vl) = ... ?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Various CSRs have a set_foo() function. We could put it in there. Though that doesn't significantly reduce the risk because people can always forget to use the setter.

I ran into a similar issue recently - trying to memoize/cache a value. Difficult to guarantee that all the code will use setter that updates the cache without some support for private.

IMO there are few enough of these that we can probably ignore this issue for the moment, though I agree it's not ideal.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Perhaps it would be better to get Sail to generate the callbacks automatically?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yeah we discussed this before. Might be nice, but I'm not 100% sure it would do exactly what you want, e.g. you probably want distinct callbacks for writes to sstatus and mstatus, but under the hood they write to the same register. Also there are very few places this callback is needed so the manual burden is not that high, and I suspect Alasdair has enough on his plate already!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I added the ext_notification_write_CSR (and ext_notification_read_CSR) function. It helps to simplify writing to a CSR with a call to a callback.

@Timmmm
Copy link
Collaborator

Timmmm commented Jun 11, 2024

mpz_sizeinbase(val.bits, 2) + 7) / 8

Actually reading this back, I wonder if mpz_sizeinbase(val.bits, 256) would work (and not be really slow).

@kseniadobrovolskaya
Copy link
Contributor Author

I would like to point out that the callback functions are annotated as pure. But in reality we have no way to guarantee that users will not actually change the state of the model in these functions. Should we really keep this attribute or should we remove it so that we don't fool anyone?

@Timmmm
Copy link
Collaborator

Timmmm commented Jun 13, 2024

I would like to point out that the callback functions are annotated as pure. But in reality we have no way to guarantee that users will not actually change the state of the model in these functions. Should we really keep this attribute or should we remove it so that we don't fool anyone?

I would say if someone edits the code and changes the callback to be impure then it's up to them to also change the Sail code to mark them as impure.

Copy link
Collaborator

@arichardson arichardson left a comment

Choose a reason for hiding this comment

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

Could you keep the RVFI-DII code around? Alternatively, a good demonstrator of the callbacks would be to implement the RVFI-DII socket interface using those callbacks?

@Timmmm
Copy link
Collaborator

Timmmm commented Jun 13, 2024

Yeah to be clear I don't think these callbacks should be user defined. We should have hard-coded callbacks that support RVFI, logging, etc.

@kseniadobrovolskaya kseniadobrovolskaya force-pushed the Callbacks_for_state-changing_events branch 3 times, most recently from 10ae49b to 6e0f187 Compare July 1, 2024 12:55
@kseniadobrovolskaya
Copy link
Contributor Author

@arichardson, @Timmmm, what do you think of the current version?

Copy link
Collaborator

@Timmmm Timmmm left a comment

Choose a reason for hiding this comment

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

Yeah this is pretty much exactly what I was thinking. I put some minor comments but I it looks like the right direction to me.

Copy link
Collaborator

@arichardson arichardson left a comment

Choose a reason for hiding this comment

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

Overall I think this approach looks good, but I'd push all the rv_enable_callbacks into the callee to simplify the code. Since the variable is not a compile-time constant it shouldn't matter whether it's checked in the C code or sail code. It might be easier to keep this as an internal flag to the C/Ocaml emulators.

@kseniadobrovolskaya kseniadobrovolskaya force-pushed the Callbacks_for_state-changing_events branch 3 times, most recently from 09acccc to be696b8 Compare July 26, 2024 08:51
@kseniadobrovolskaya kseniadobrovolskaya force-pushed the Callbacks_for_state-changing_events branch 2 times, most recently from 98f3973 to 7dcbd56 Compare October 10, 2024 12:26
Copy link
Collaborator

@arichardson arichardson left a comment

Choose a reason for hiding this comment

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

Not reviewed this in detail, but overall the new approach looks sensible to me.

@kseniadobrovolskaya kseniadobrovolskaya force-pushed the Callbacks_for_state-changing_events branch 2 times, most recently from 779fbf7 to 232e5bd Compare October 17, 2024 10:54
@kseniadobrovolskaya
Copy link
Contributor Author

@arichardson, @Timmmm, what do you think of the current version?

@Timmmm
Copy link
Collaborator

Timmmm commented Nov 29, 2024

Hi, sorry for not getting around to this. Just wanted to say it's still on my todo list and I will get to it!

Copy link
Collaborator

@Timmmm Timmmm left a comment

Choose a reason for hiding this comment

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

Finally got around to this again - sorry for the delay!

I think it's pretty close - the main thing is merging riscv_rvfi_callbacks.c into riscv_default_callbacks.c.

You could also rename it to just riscv_callbacks.c.

Copy link
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.

A nice improvement, moving most of RVFI handling out of the main Sail model.

@jordancarlin jordancarlin force-pushed the Callbacks_for_state-changing_events branch from 756baa5 to cd62eef Compare May 1, 2025 02:38
@jordancarlin jordancarlin requested a review from pmundkur May 1, 2025 02:48
@jordancarlin jordancarlin force-pushed the Callbacks_for_state-changing_events branch 3 times, most recently from 48ede59 to b70da8f Compare May 1, 2025 06:09
Copy link
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.

Other than the c-preserve and pc_write_callback, looks great!

@jordancarlin jordancarlin force-pushed the Callbacks_for_state-changing_events branch from b70da8f to 8022eea Compare May 1, 2025 16:04
@jordancarlin jordancarlin force-pushed the Callbacks_for_state-changing_events branch from 8022eea to 9812b22 Compare May 1, 2025 16:11
@jordancarlin jordancarlin requested a review from pmundkur May 1, 2025 16:11
Copy link
Collaborator

@Timmmm Timmmm left a comment

Choose a reason for hiding this comment

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

LGTM. Just a couple of minor things and I think we should add some comments to either riscv_callbacks.h or riscv_callbacks.sail to say exactly what all the callbacks mean, because there are some subtleties. E.g. when exactly is trap_callback() called? Are addresses physical or virtual? How is mstatush etc. handled?

There are probably some other minor things we can improve but I think this is already a huge improvement so lets get it in!

@jordancarlin jordancarlin force-pushed the Callbacks_for_state-changing_events branch from 9812b22 to 294f469 Compare May 5, 2025 16:07
@jordancarlin jordancarlin requested a review from Timmmm May 5, 2025 16:08
Copy link
Collaborator

@Timmmm Timmmm left a comment

Choose a reason for hiding this comment

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

LGTM. We can add the comments later. I imagine the exact API may change slightly when we try to use it in anger anyway.

@Timmmm
Copy link
Collaborator

Timmmm commented May 5, 2025

Oh you missed a paddr though...

1. Added callback functions for XRegs, FRegs, VRegs, PC, CSR and memory writes, and CSR and memory reads.
2. Added RVFI and standard trace logging implementation of callbacks.

Co-authored-by: Tim Hutt <timothy.hutt@codasip.com>
@jordancarlin jordancarlin force-pushed the Callbacks_for_state-changing_events branch from 294f469 to ef2b1d1 Compare May 5, 2025 19:48
@jordancarlin
Copy link
Collaborator

Oops. Fixed. I added some comments to riscv_callbacks.h.

@jordancarlin jordancarlin added the will be merged Scheduled to be merged soon if nobody objects label May 6, 2025
@Timmmm Timmmm changed the title Implementing callbacks in sail-riscv for state-changing events Implement callbacks for state-changing events May 6, 2025
@Timmmm Timmmm added this pull request to the merge queue May 6, 2025
@Timmmm
Copy link
Collaborator

Timmmm commented May 6, 2025

Nice work everyone!

Merged via the queue into riscv:master with commit 3bdcf27 May 6, 2025
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

will be merged Scheduled to be merged soon if nobody objects

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants