-
Notifications
You must be signed in to change notification settings - Fork 856
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
[RFC] make XLENs changable #1167
base: master
Are you sure you want to change the base?
Conversation
I think we should take a step back and determine whether Spike really needs to support this feature. It adds a lot of complexity, but it isn’t clearly of high value. More generally, we should look at the roadmap of RISC-V features and decide what Spike needs to support and what can be omitted. |
This seems to be a very interesting feature supported by RISC-V. As spike is the golden model, I think adding some complexity to support this feature seems acceptable. It introduces minor change to the main stream of simulation. Most of the additional complexity is for CSRs access. |
f186dea
to
81639ec
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.
Commit a4f6efe does way more than what its commit message claims.
Don't make XLEN fields writable before everything else is fixed. We don't want Spike to be broken at any commit point. You should be able to change all the CSRs to support dynamic XLEN first (one at a time!), and everything should still work with fixed XLEN. The last step is to enable writable XLEN fields.
No tests == doesn't work.
I concur with @aswaterman that this might not be desirable to have. Is there any demand for this support? I'm not aware of any RISC-V implementation that supports this capability.
riscv/csrs.cc
Outdated
basic_csr_t(proc, addr, 0) { | ||
cause_csr_t::cause_csr_t(processor_t* const proc, const reg_t addr, uint8_t prv_index): | ||
basic_csr_t(proc, addr, 0), | ||
prv_index(prv_index) { | ||
} | ||
|
||
reg_t cause_csr_t::read() const noexcept { | ||
reg_t val = basic_csr_t::read(); | ||
// When reading, the interrupt bit needs to adjust to xlen. Spike does | ||
// not generally support dynamic xlen, but this code was (partly) |
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.
Comment is now out of date
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'll modify it.
riscv/csrs.cc
Outdated
} | ||
|
||
reg_t cause_csr_t::read() const noexcept { | ||
reg_t val = basic_csr_t::read(); | ||
// When reading, the interrupt bit needs to adjust to xlen. Spike does | ||
// not generally support dynamic xlen, but this code was (partly) | ||
// there since at least 2015 (ea58df8 and c4350ef). | ||
if (proc->get_isa().get_max_xlen() > proc->get_xlen()) // Move interrupt bit to top of xlen | ||
return val | ((val >> (proc->get_isa().get_max_xlen()-1)) << (proc->get_xlen()-1)); | ||
unsigned xlen = proc->get_xlen(prv_index & 3, prv_index & 4); |
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.
Don't use bit fields when C++ has much better data structures. Make a new struct and pass that to get_xlen()
.
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'll adjust it.
riscv/csrs.cc
Outdated
@@ -500,19 +545,51 @@ bool mstatus_csr_t::unlogged_write(const reg_t val) noexcept { | |||
|
|||
const reg_t requested_mpp = proc->legalize_privilege(get_field(val, MSTATUS_MPP)); | |||
const reg_t adjusted_val = set_field(val, MSTATUS_MPP, requested_mpp); | |||
const reg_t new_mstatus = (read() & ~mask) | (adjusted_val & mask); | |||
reg_t new_mstatus = (this->val & ~mask) | (adjusted_val & mask); |
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.
Why can't this still be const
? I don't see it being modified below...
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.
Yeah. It's not necessary currently. I'll restore it.
riscv/csrs.cc
Outdated
int orig_uxl = get_field(new_mstatus, MSTATUS_UXL); | ||
int new_uxl = legalize_xl(get_field(val, MSTATUS_UXL), orig_uxl); | ||
int orig_sxl = get_field(new_mstatus, MSTATUS_SXL); | ||
int new_sxl = legalize_xl(get_field(val, MSTATUS_SXL), orig_sxl); |
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.
Why can't you do these adjustments up above where all the other fields (e.g. MPP) are legalized? Then write this->val
only once with the final value in the end.
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.
In current implementation, update_sxl may modify uxl field of mstatus. Maybe I can add this to the legalize_xl function.
riscv/csrs.cc
Outdated
@@ -1239,7 +1239,7 @@ bool hgatp_csr_t::unlogged_write(const reg_t val) noexcept { | |||
proc->get_mmu()->flush_tlb(); | |||
|
|||
reg_t mask; | |||
if (proc->get_const_xlen() == 32) { | |||
if (proc->get_xlen(PRV_S) == 32) { |
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.
Not a safe change, since this CSR's implementation still assumes a const xlen. (Because it doesn't dynamically adjust its shape when xlen changes.)
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.
Why the CSR's implementation is const xlen? Hgatp is stated as HSXLEN bits in spec . So I think its length is changable.
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.
If I do CSRW when HSXLEN=64 and then read it back when HSXLEN=32 what happens?
I'm not even sure what's supposed to happen in that case, since the MODE field changes interpretation. But at least the VMID field needs to move. And there's no code to do that in this implementation.
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.
The fields for HSXLEN=64 cannot totally map to fields for HSXLEN=32, even though they have the same field names. I think this may be the work of software.
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, what's supposed to happen here when XLEN changes doesn't seem to be well-specified. But at least we could make some effort not to leave total garbage in there -- move VMID, reset Mode, etc?
I think you're pioneering a lot of architectural work here, and there will be many more questions like this that we don't have good answers for.
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.
“Complete garbage” might be what’s required by the CSR width modulation section in chapter 2. I think it requires a bitwise copy of the whole register, even if bits end up in the wrong fields.
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.
The current implementation is to use bitwise copy for most CSRs, by leaving them alone, and truncating their length to their related XLEN when read and write.
However, the CSR value may be unchanged if their XLEN is back-to-back changed(64->32->64). This seems a little different from the description from the CSR width modulation section in chapter 2:
“If the new width is wider than the previous width, the temporary register is zero-extended to the wider width”
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.
“Complete garbage” might be what’s required by the CSR width modulation section in chapter 2. I think it requires a bitwise copy of the whole register, even if bits end up in the wrong fields.
The opening paragraph there says: "fields and bits of the new-width CSR are, unless specified otherwise, determined..."
I think the two different figures for hgatp
for HSXLEN of 32/64 count as "specified otherwise." VMID and MODE move and it wouldn't be correct to jam the upper bits of PPN into the VMID field when switching from 64 to 32.
This kind of per-field relocation might not be well explained in the spec, but is necessary in order for changing misa.MXL
back and forth between 2 (xlen=64) and 1 (xlen=32) to work.
But it's because of architectural questions like this that I am very leery of this being the right time & place to pioneer this feature.
riscv/csrs.cc
Outdated
} | ||
|
||
bool vsstatus_csr_t::unlogged_write(const reg_t val) noexcept { | ||
const reg_t newval = (this->val & ~sstatus_write_mask) | (val & sstatus_write_mask); | ||
unsigned vslen = proc->get_xlen(PRV_S, true); |
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.
Use consistent names. In the previous method this was vsxlen
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'll modify it.
f8e1509 does not compile |
Historically, other architectures had the feature to change XLEN to facilitate an ISA transition. When x86-64 processors were deployed, IA-32 software was still the norm, and so the processors wouldn’t have been commercially successful without the ability to run IA-32 code. RISC-V is not in the same boat: RV32 and RV64 were created simultaneously, and so there was no such transition. RV64 is already the norm for applications-class processors. For this reason, I suspect few vendors will choose to implement this feature, and so there probably won’t be much demand to support it in Spike. If I’m proven wrong about the demand, then obviously I’d change my opinion and would support adding this feature to Spike. I imagine RV128 processors might need this feature (but RV128 support will be a major feature for other reasons). |
Thanks for your comments.
OK. I'll reorganized the commits.
Yeah. I'll try to adjust the riscv-tests to test it(any other seggestion?). The main reason I sent this RFC is to discuss whether there are problems in my understanding of how XLENs work.
I search the RISC-V implementations, and find Xuantie C908 seems to support partial of this feature: |
Yeah. I didn't find an implementation to support all of this feature. Xuantie C908 seems to support partial of it.
I have a question of RV128: there is description about the xlen changing from 32 to wider, how about 64 to 128? |
RV128 isn’t defined yet, so this isn’t fully defined, either. The presumption is that this feature will support RV128 in the obvious way. |
Yeah, this isn’t compelling evidence of demand (especially since it sounds like a nonconforming implementation). |
Sorry, I don't know how much it supports currently. Why I said 'partial' is that it doesn't support 'H' extension which means VSXLEN/VUXLEN will not work. |
rv64_rv32_low_csr_t is used in the next commit. |
If it doesn't compile, that's a problem. Here's the beginning of the giant list of errors that I get when doing a clean compile from f8e1509:
|
OK, there is bug in the code(Maybe not the unused rv64_rv32_low_csr_t). I'll fix it later. |
aa47842
to
3ecb188
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.
ee8c63f is way too big and does way too much at once. It also changes behavior of csrw minstret
, changing the value written to the CSR by 1. It also changes logging of mstatush
sometimes, though that behavior is then reverted back by ffe656a.
dbfbc9f somehow changes the values in mstatush
bits MBE
and SBE
.
Though I still don't think this is the right time for this feature.
OK. I'll reorganize them later.
Sorry. I didn't find the way to change
OK. Maybe we can keep it in development here. |
My test is proprietary (sorry) but here's all it does with
... some time later ...
Before dbfbc9f, that last It would help if you broke up dbfbc9f into several steps: first keep sxl/uxl fixed, but move the computation of those fields into |
Yeah. This is the UXL and SXL fields problem. I didn't clear it when MXLEN = 32. I'll fix it later. |
Right. My mistake, that wasn't MBE/SBE bits. |
…ll be checked by their verify_permissions) Add rv64_rv32_low_csr_t class for 64bits CSRs in RV64 that are also low half CSRs in RV32
Remove unsed xlen_to_uxl function
Remove unused get_const_xlen function
3ecb188
to
977381d
Compare
This patchset add the support for changable XLENs:
Tests for changable XLENs are lacked currently.