-
Notifications
You must be signed in to change notification settings - Fork 169
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
Handle additional memory requests made by RCOMBBASE
#1229
Conversation
5f36479
to
df15de8
Compare
a54ba5a
to
50f9395
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you! Looks good! I rebased the PR from the latest code and left a few comments inline.
let factor1 = alphas[0] | ||
+ alphas[1].mul_base(Felt::from(op_label)) | ||
+ alphas[2].mul_base(ctx) | ||
+ alphas[3].mul_base(z_ptr) | ||
+ alphas[4].mul_base(clk) | ||
+ alphas[5].mul_base(tz0) | ||
+ alphas[6].mul_base(tz1) | ||
+ alphas[7].mul_base(tzg0) | ||
+ alphas[8].mul_base(tzg1); | ||
|
||
let factor2 = alphas[0] | ||
+ alphas[1].mul_base(Felt::from(op_label)) | ||
+ alphas[2].mul_base(ctx) | ||
+ alphas[3].mul_base(a_ptr) | ||
+ alphas[4].mul_base(clk) | ||
+ alphas[5].mul_base(a0) | ||
+ alphas[6].mul_base(a1) | ||
+ alphas[7].mul_base(ZERO) | ||
+ alphas[8].mul_base(ZERO); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These two computations are very similar - I wonder if we should have a separate function for computing memory request values. For example, something like:
fn compute_memory_read_request(alphas: &[E], ctx: Felt, clk: Felt, addr: Felt, value: Word) -> E
(or maybe ctx
and clk
could be replaced with self
if we put this function on MainTrace
).
This will make the intent of the code a bit more clear. Also, such a function may be useful in other contexts too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed! I have now added the proposed method to MainTrace
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left a change proposal. Would love to hear your thoughts!
air/src/trace/main_trace.rs
Outdated
pub fn helper_2(&self, i: usize) -> Felt { | ||
self.columns.get_column(DECODER_TRACE_OFFSET + USER_OP_HELPERS_OFFSET + 2)[i] | ||
/// The i-th decoder helper register at `row`. | ||
pub fn helper(&self, i: usize, row: usize) -> Felt { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would rename to helper_register()
- it wasn't clear to me what main_trace.helper()
was
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, makes sense. Renamed
air/src/trace/main_trace.rs
Outdated
@@ -367,6 +357,30 @@ impl MainTrace { | |||
self.columns.get_column(MEMORY_V_COL_RANGE.start + 3)[i] | |||
} | |||
|
|||
/// Computes a memory read request at `row` given randomness `alphas`, memory address `addr` | |||
/// and value `value`. | |||
pub fn compute_memory_read_request<E: FieldElement<BaseField = Felt>>( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With this new function, we have 2 functions in the system that build a memory read request: this one, and processor::chiplets::aux_trace::build_mem_request()
. We should have only one.
A few thoughts:
- I think
MainTrace
should only have dumb accessors. It shouldn't be computing complex functions of the trace columns. - A memory read (for words) is always a random linear combination of
[op_label, ctx, addr, clk, VALUE]
. The issue we have is thatMLOAD*
andMSTORE*
don't take these values from the same locations in the trace asRCOMBBASE
. The solution IMO is to havebuild_mem_request
take the values it needs as input, and caller can supply them by reading from the correct trace location. - I would split
build_mem_request()
into 2: one that builds a memory access for aFelt
(e.g.build_mem_element_request()
), and another for aWord
(e.g.build_mem_word_request()
). This would help us think of them as separate requests, because they are (i.e. the virtual columns that they collapse into 1 are different).
In other words, we currently think of a memory request (as defined by build_mem_request()
) as coming from MLOAD*
or MSTORE*
. This change would help us think of a memory request as a random linear combination of specific columns (depending on whether we're reading a Felt
or Word
), which can come from any operation (current and/or future ones).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With this new function, we have 2 functions in the system that build a memory read request: this one, and
processor::chiplets::aux_trace::build_mem_request()
.
Ah - good point! I forgot about this one. We actually also have build_mstream_request()
which does something similar. I'd love to consolidate them to use the same logic for computing the random linear combination.
I think
MainTrace
should only have dumb accessors. It shouldn't be computing complex functions of the trace columns.
I agree with this. I wanted to have a more "convenient" location for the function - but separation of concerns is probably more important here.
As mentioned above, I still think that it would be good to have the function that computes the random linear combination for the request - but this function could probably live in the aux_trace
module. Than, this function could be used from build_mem_request()
, build_mstream_request()
, build_rcomb_base_request()
and others in the future.
I would split
build_mem_request()
into 2: one that builds a memory access for aFelt
(e.g.build_mem_element_request()
), and another for aWord
(e.g.build_mem_word_request()
). This would help us think of them as separate requests, because they are (i.e. the virtual columns that they collapse into 1 are different).
If we have the above-mentioned function as a helper, I think splitting up build_mem_request()
would make sense.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with points 1 and 2. Regarding point 3, it is indeed helpful (especially for the future) to make the code reflect the separation between requests (and by transitivity virtual columns). The issue is that this can be in conflict with reducing the size of the code in some places. Nevertheless, I have split the build_mem_request()
and we can discuss the other cases, if any, on a case-by-case basis
let factor1 = main_trace.compute_memory_read_request(alphas, i, z_ptr, [tz0, tz1, tzg0, tzg1]); | ||
let factor2 = main_trace.compute_memory_read_request(alphas, i, a_ptr, [a0, a1, ZERO, ZERO]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given previous comment, this would call the new build_mem_word_request()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense, changed!
air/src/trace/main_trace.rs
Outdated
let ctx = self.ctx(row); | ||
let clk = self.clk(row); | ||
|
||
alphas[0] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
main_trace.helper_register(2, row), | ||
main_trace.helper_register(1, row), | ||
main_trace.helper_register(0, row), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is stored in these helper registers, and why is it included as part of the request computation? Can we add a comment that explains it?
This would help understand the value
argument to compute_memory_request()
, which is currently unclear to me (since it's not always "the word that was read or written" EDIT - or is it?).
And based on this new understanding, I might rename build_mem_request_{element, word}()
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I infer from build_memory_chiplet_response()
that the helper registers must hold the remaining 3 elements that were read/written.
I would
- make that clear in a comment here
- In
compute_memory_request()
's docstring, I would add a sentence to say thatvalue
is the memory value that was read/written - rename
build_mem_request_element()
->build_loadstore_request()
- rename
build_mem_request_word()
->build_loadstorew_request()
I suggest renaming build_mem_request_{element, word}()
yet again because I had something else in mind when I suggested it. I thought we would have these 2 basic functions that everything else would depend on (which is now compute_memory_request()
). Now these 2 are associated exclusively with the MLOAD/STORE{W}
instructions, and so I would rename them so as to capture that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the naming is fine as it stands given the totality of the discussions above.
a5bf6a1
to
19df843
Compare
3d06daa
to
4c963d2
Compare
19df843
to
b56558e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good! Thank you! I left one comment for the future inline.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good :)
Describe your changes
Updates the bus to handle the two memory requests made by
RCOMBBASE
and updates docs.Checklist before requesting a review
next
according to naming convention.