-
Notifications
You must be signed in to change notification settings - Fork 147
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
sequential mtspr calls fail #122
Comments
Find the test newlib binaries and vcd files attached. The file |
Issue openrisc#122 Writing to the tlb rams was dependent on the spr_bus_ack as a means to only write during the first cycle after a spr_bus_stb_i. This works fine for a single write, but if we have a write to itlb_match_spr followed by itlb_trans_spr the spr_bus_ack never goes low so the write to itlb_trans_spr is skipped. Fix this by using the itlb_match_spr_cs_r and itlb_trans_spr_cs_r signals to control the "first cycle after spr_bus_stb_i" condition. This way writes can happen independently. Note, there may still be issues with a write to itlb_match followed by another write to itlb_match. Fixing that requires changing the "first cycle after spr_bus_stb_i" policy, which is similar to dmmu.
Issue openrisc#122 Writing to the tlb rams was dependent on the spr_bus_ack as a means to only write during the first cycle after a spr_bus_stb_i. This works fine for a single write, but if we have a write to itlb_match_spr followed by itlb_trans_spr the spr_bus_ack never goes low so the write to itlb_trans_spr is skipped. Fix this by using the itlb_match_spr_cs_r and itlb_trans_spr_cs_r signals to control the "first cycle after spr_bus_stb_i" condition. This way writes can happen independently. Note, there may still be issues with a write to itlb_match followed by another write to itlb_match. Fixing that requires changing the "first cycle after spr_bus_stb_i" policy, which is similar to dmmu.
I was able to fix case 2 with patch stffrdhrn@8d7b044 The test still fails due to case 1. Case 2 - mtspr / mtspr succeedsWe can see Case 1 - store still failsWe can see that after the invalidate the |
To test this I am using
Then running fusesoc: The |
The investigation so far:
|
Issue openrisc#122 This fixes case 1 from issue 122 where writes are missed after invalidate state. The change to invalidate_ack to to allow the invalidate_ack to be asserted after the invalidate happens not before. For writes we allow forwarding to WRITE state directly from invalidate at this point pending_write will still be high and we can use that to initialiate the write. When we have delays the cpu_req_i may be low when we get to the write state.
Issue openrisc#122 An additional fix for back to back spr writes. I was seeing that during back to back writes the busy_o signal would go low after the first spr write complete. This caused the fetch to proceed and present bad data to the bus caused by the second in-progress write. This is because ack goes high during the first write and stays high as long as we are writing. Introducing a busy tracker based on what writes are in progress seems to fix this issue.
Issue openrisc#122 An additional fix for back to back spr writes. I was seeing that during back to back writes the busy_o signal would go low after the first spr write complete. This caused the fetch to proceed and present bad data to the bus caused by the second in-progress write. This is because ack goes high during the first write and stays high as long as we are writing. Introducing a busy tracker based on the assuming that spr transactions take 2 clocks to complete.
Issue openrisc#122 Writing to the tlb rams was dependent on the spr_bus_ack as a means to only write during the first cycle after a spr_bus_stb_i. This works fine for a single write, but if we have a write to itlb_match_spr followed by itlb_trans_spr the spr_bus_ack never goes low so the write to itlb_trans_spr is skipped. Fix this by using the itlb_match_spr_cs_r and itlb_trans_spr_cs_r signals to control the "first cycle after spr_bus_stb_i" condition. This way writes can happen independently. Note, there may still be issues with a write to itlb_match followed by another write to itlb_match. Fixing that requires changing the "first cycle after spr_bus_stb_i" policy, which is similar to dmmu.
Issue openrisc#122 This fixes case 1 from issue 122 where writes are missed after invalidate state. The change to invalidate_ack to to allow the invalidate_ack to be asserted after the invalidate happens not before. For writes we allow forwarding to WRITE state directly from invalidate at this point pending_write will still be high and we can use that to initialiate the write. When we have delays the cpu_req_i may be low when we get to the write state.
Issue openrisc#122 An additional fix for back to back spr writes. I was seeing that during back to back writes the busy_o signal would go low after the first spr write complete. This caused the fetch to proceed and present bad data to the bus caused by the second in-progress write. This is because ack goes high during the first write and stays high as long as we are writing. Introducing a busy tracker based on the assuming that spr transactions take 2 clocks to complete.
Issue #122 Writing to the tlb rams was dependent on the spr_bus_ack as a means to only write during the first cycle after a spr_bus_stb_i. This works fine for a single write, but if we have a write to itlb_match_spr followed by itlb_trans_spr the spr_bus_ack never goes low so the write to itlb_trans_spr is skipped. Fix this by using the itlb_match_spr_cs_r and itlb_trans_spr_cs_r signals to control the "first cycle after spr_bus_stb_i" condition. This way writes can happen independently. Note, there may still be issues with a write to itlb_match followed by another write to itlb_match. Fixing that requires changing the "first cycle after spr_bus_stb_i" policy, which is similar to dmmu.
Issue #122 This fixes case 1 from issue 122 where writes are missed after invalidate state. The change to invalidate_ack to to allow the invalidate_ack to be asserted after the invalidate happens not before. For writes we allow forwarding to WRITE state directly from invalidate at this point pending_write will still be high and we can use that to initialiate the write. When we have delays the cpu_req_i may be low when we get to the write state.
Issue #122 An additional fix for back to back spr writes. I was seeing that during back to back writes the busy_o signal would go low after the first spr write complete. This caused the fetch to proceed and present bad data to the bus caused by the second in-progress write. This is because ack goes high during the first write and stays high as long as we are writing. Introducing a busy tracker based on the assuming that spr transactions take 2 clocks to complete.
This again fixes: openrisc#122 Testing to see how it helps with: openrisc#146 However, this time I hope it is more stable as formal now caught this bug and now asserts that the formal properties pass. The fix is slightly different than the original as now we only change the state machine to allow going directly from INVALIDATE to WRITE with write having higher priority over invalidate as per comment.
This again fixes: openrisc#122 Testing to see how it helps with: openrisc#146 However, this time I hope it is more stable as formal now caught this bug and now asserts that the formal properties pass. The fix is slightly different than the original as now we only change the state machine to allow going directly from INVALIDATE to WRITE with write having higher priority over invalidate as per comment.
This again fixes: openrisc#122 Testing to see how it helps with: openrisc#146 However, this time I hope it is more stable as formal now caught this bug and now asserts that the formal properties pass. The fix is slightly different than the original as now we only change the state machine to allow going directly from INVALIDATE to WRITE with write having higher priority over invalidate as per comment.
I have converted to or1k-tests to use inline calls to
mtspr()
andmfspr()
. This causes failures in the following cases inor1k-mmu
.See: openrisc/or1k-tests@32f0ba2
Case 1 - this happens when 1 nop after mtspr.
The first case is where we have
mtspr
following by al.sw
, this causes an invalidate to be sent to the dcache. At the same time as the write operation. The write fails.Case 2 - this happens with 0 nop after mtspr.
The mtspr followed by mtspr causes the second write to OR1K_SPR_IMMU_ITLBW_TR_ADDR to be lost.
Workaround
Adding 2
l.nop
s aftermtspr
fixes the issue. Below in case 1 thel.sw
came before thel.nop
due to some optimizations from gcc, to fix it theasm
forl.mtspr
contains the nop inline i.e.l.mtspr %0, %1, 0; l.nop; l.nop
. But the below is without the fix exposing the CPU issue, but it should still work.Trace case1 - dcache spr mix with l.sw fails
Trace case2 - immu spr fails
When we have a l.mtspr writing to the IMMU followed by another l.mtspr writing to the IMMU the second spr write may fail.
The text was updated successfully, but these errors were encountered: