-
Notifications
You must be signed in to change notification settings - Fork 335
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
target/riscv: cache requests to trigger configuration #928
Conversation
180d934
to
ddc5f78
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.
I love this improvement. It's going to help a lot, as you explained.
Why did you choose to use a linked list for the data structure? It looks like you're always allocating the whole thing. I think using an array would simplify the code significantly, but perhaps I'm missing some downside.
When caching tdata2 data, each new call is written to the top of the list (or moved if such a call has already been made), thus making it easier to find the data. And for tdata1 a list to make code uniform. |
src/target/riscv/riscv.c
Outdated
|
||
struct tdata1_cache *tdata1_cache = find_tdata1(&(r->wp_triggers_cache[idx]), tdata1); | ||
if (tdata1_cache == NULL) { | ||
tdata1_cache = create_new_tdata1_cache(&(r->wp_triggers_cache[idx]), tdata1); |
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.
Are you making a new cache per trigger index here? I don't understand that. There can only be one tdata1 value per trigger at a time.
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.
We can use one trigger to set wp of different types (eq, napot, ge, lt). And in this implementation, all this information is cached. This is necessary if we installed wp on a certain trigger, then deleted it and want to reinstall it.
ddc5f78
to
22567be
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.
OK, I think I got it now. Overall looks good. I have a lot of naming/comment suggestions that would have made this code more obvious to me, but nothing really about the structure of the code.
src/target/riscv/riscv.c
Outdated
@@ -700,6 +732,99 @@ static void log_trigger_request_info(struct trigger_request_info trig_info) | |||
trig_info.tdata1, trig_info.tdata2, trig_info.tdata1_ignore_mask); | |||
}; | |||
|
|||
static struct tdata1_cache *create_new_tdata1_cache(struct list_head *tdata1_cache_head, riscv_reg_t tdata1) |
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.
Following the example of e.g. riscv_batch_alloc, let's call this:
static struct tdata1_cache *create_new_tdata1_cache(struct list_head *tdata1_cache_head, riscv_reg_t tdata1) | |
static struct tdata1_cache *tdata1_cache_alloc(struct list_head *tdata1_cache_head, riscv_reg_t tdata1) |
(How does this square with e.g. riscv_free_registers()? It's a bit messy and inconsistent, but at least when there's a simple struct then using _alloc() seems more consistent.)
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.
Addressed.
src/target/riscv/riscv.c
Outdated
return elem; | ||
} | ||
|
||
static void create_new_tdata2_cache(struct list_head *tdata2_cache_head, riscv_reg_t tdata2) |
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.
static void create_new_tdata2_cache(struct list_head *tdata2_cache_head, riscv_reg_t tdata2) | |
static void tdata2_cache_alloc(struct list_head *tdata2_cache_head, riscv_reg_t tdata2) |
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.
Addressed.
src/target/riscv/riscv.c
Outdated
list_add(&elem->elem_tdata2, tdata2_cache_head); | ||
} | ||
|
||
struct tdata2_cache *find_call_in_tdata2_cache(struct list_head *tdata2_cache_head, riscv_reg_t find_tdata2) |
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 "call" in this context? Isn't this simply tdata2_cache_search
?
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.
Addressed.
src/target/riscv/riscv.c
Outdated
return NULL; | ||
} | ||
|
||
struct tdata1_cache *find_tdata1(struct list_head *tdata1_cache_head, riscv_reg_t find_tdata1) |
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.
struct tdata1_cache *find_tdata1(struct list_head *tdata1_cache_head, riscv_reg_t find_tdata1) | |
struct tdata1_cache *tdata1_cache_search(struct list_head *tdata1_cache_head, riscv_reg_t find_tdata1) |
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.
Addressed.
src/target/riscv/riscv.c
Outdated
static bool is_use_wp_trigger_in_cache(struct target *target, unsigned int idx, | ||
riscv_reg_t tdata1, riscv_reg_t tdata2) |
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.
static bool is_use_wp_trigger_in_cache(struct target *target, unsigned int idx, | |
riscv_reg_t tdata1, riscv_reg_t tdata2) | |
static bool wp_triggers_cache_search(struct target *target, unsigned int idx, | |
riscv_reg_t tdata1, riscv_reg_t tdata2) |
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.
Alternate suggestion for your consideration:
is_known_unsupported_trigger(...)
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.
Addressed.
src/target/riscv/riscv.c
Outdated
static bool is_use_wp_trigger_in_cache(struct target *target, unsigned int idx, | ||
riscv_reg_t tdata1, riscv_reg_t tdata2) |
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.
Alternate suggestion for your consideration:
is_known_unsupported_trigger(...)
22567be
to
b5e3b3c
Compare
b5e3b3c
to
02e41a5
Compare
@timsifive All issues were addressed. Could you please take a look? |
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.
There seem to be two unaddressed (overlooked?) items:
- target/riscv: cache requests to trigger configuration #928 (comment)
- target/riscv: cache requests to trigger configuration #928 (comment)
Other than that, the code looks all right.
02e41a5
to
6c43689
Compare
@timsifive this commit has an unexpected (to me test failure) that I haven't observed locally. That being said - I used relatively old riscv-tests to check my changes (riscv-tests ed0a63ea4f , which is from around Jul 10, 2023). Looks like I'll need to re-test my changes with an updated riscv-tests. |
@AnastasiyaChernikova , @timsifive, @JanMatCodasip actually, I've tried to update |
and just for the reference (I think this should be mentioned). This attempt to update was in repository that has few additional patches applied on top of riscv-openocd (minor fixes that were backported from https://sourceforge.net/p/openocd/ . And I used a relatively old version of spike (around 2 months old) |
If I build everything (without the changes in this PR) from scratch from the latest sources (toolchain, Spike, RISC-V OpenOCD) then the If I copy in the modified |
UnavailableHaltedTest seems to fail intermittently in the github action. I haven't seen it fail this way when I run it locally. :-( Hopefully I'll have some time to investigate more next week. |
I've restarted this test run several times, and it fails UnavailableHaltedTest consistently. Is it simply based on older code? |
Depending on configuration, the existing implementation of watchpoints is rather inefficient for certain scenarios. Consider HW that: 1. triggers 0-3 can be used as instruction breakpoints 2. triggers 4-7 can be used as data breakpoints (watchpoints) 3. NAPOT triggers are not supported. Now, consider that we have a pending watchpoint. And we perform a "step" operation. According to the current implementation: * OpenOCD will disable watchpoints * Perform a single-step * Will try to restore the original watchpoints. It will need 12 attempts to find a suitable trigger: (8 attempts to try NAPOT, and another 4 to try GE+LE). This patch introduces a dedicated cache for requests to triggers. It significantly speeds things up, since we cache failed attempts and no additional interactions with HW is necessary. Change-Id: Ic272895eaa763a7ae84d14f7633790afd015ca9d Signed-off-by: Anastasiya Chernikova <[email protected]>
fea20e2
6c43689
to
fea20e2
Compare
For some reason, in this branch only, UnavailableHaltedTest consistently fails. I have no idea why. It doesn't make any sense with this change and what that test does. I cannot reproduce the failure on my machine either. :-( I'm weary merging this change, though, because I don't want all testing to suddenly start failing. Is this blocking other work for you? |
I can actually. However, the issue is reproducible even without this patch on my machine. This may be related to python version or some weird timing issues. Sometimes OpenOCD log file contain non-printable characters (like ^H and stuff). It seems that this sometimes messes up matching algorithms used in testing infrastructure. There are 2 types of issues I observe:
|
I think I've found the root cause. It's a timing/parsing issue. I've filed riscv-software-src/riscv-tests#520 against riscv-tests. |
Depending on configuration, the existing implementation of watchpoints is rather inefficient for certain scenarios. Consider HW that:
Now, consider that we have a pending watchpoint. And we perform a "step" operation. According to the current implementation:
This patch introduces a dedicated cache for requests to triggers. It significantly speeds things up, since we cache failed attempts and no additional interactions with HW is necessary.