Skip to content
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

Untangle ISA-specific information from the assembler framework. #303

Open
mortbopet opened this issue Sep 24, 2023 · 0 comments
Open

Untangle ISA-specific information from the assembler framework. #303

mortbopet opened this issue Sep 24, 2023 · 0 comments

Comments

@mortbopet
Copy link
Owner

Currently, defining an ISA and defining the assembler for said ISA is done in two different places, e.g.:

Ideally, all information regarding operations themselves - such as opcodes, fields, registers, etc.. would not be inherently tied to the assembler, but instead part of the ISA information. The assembler framework would then query the operations of a given instruction set, and generate the assembler based on said information. This is almost what's already done, but with the assembler being too strongly coupled with the instruction definitions.

If we manage to move instruction definitions to ISA files, meaning that the ISA files will contain all information about the ISA, we can start to query this more reliably in various different places in Ripes. One improvement that this refactor would allow is to avoid duplicating ISA information in the processor model decoders: https://github.com/mortbopet/Ripes/blob/master/src/processors/RISC-V/rv_decode.h - which instead should reference the ISA files.

Currrently, instructions are defined dynamically (e.g. https://github.com/mortbopet/Ripes/blob/master/src/assembler/rv_c_ext.h#L319C11-L323), meaning that all information that we specify when defining an instruction must lookup some runtime object to acquire the values of interest (opcode bitfields etc..). However, from the point of view of writing e.g. the RISC-V decoder model, we only need static information - hence there would be quite a bit of overhead in performing a bunch of dynamic, runtime lookups. As such, solving this issue should also consider whether there is a way to make instruction information (specifically bitfields) available at compile time.

mortbopet pushed a commit that referenced this issue Nov 9, 2023
Changed ISA code structure to use template classes for instruction information. This information is now defined at compile-time, instead of dynamically at runtime. In this change, all information about an instruction (opcode parts, fields, bit ranges, etc.) is initialized using template parameters.

## Issues Solved

This almost fully solves #306 by using template parameters to define instruction set information at compile-time instead of runtime. The only remaining thing to do here is group up instruction sets at compile-time instead of dynamically. As of this change, instruction sets are created at runtime in the `enableInstructions()` function depending on which extensions are enabled. To solve this, each ISA extension could have a struct that uses template parameters to define the extension's enabled instructions at compile-time. These structs can then be combined at run-time depending on which extensions are enabled. I have not tested this yet, but I think it would work and be an improvement over defining the enabled instructions in the `enableInstructions()` function.

This almost solves #303. ISA-specific information such as instruction encodings, register information, and other details have all been moved to the ISA library. The only remaining ISA-specific information are the RV32 and RV64 assembler classes and RISC-V relocation functions. The assembler classes are mostly boilerplate code that enables certain instructions based on which extensions are enabled. These assemblers should be replaced by a single assembler class that takes an ISA ID as input. The extensions should be detected (and instructions enabled) only in the ISA library. The relocation functions are short and should be moved to the ISA library as well.

Similarly, this almost solves #307. The main problem here is decoupling the ISA/assembler libraries from VSRTL and QT. VSRTL has only a few coupled functions, but there are many dependencies on QT classes. These problems need to be solved before the ISA/assembler libraries can be extracted.

#311 has been solved. It is true that register widths do not need to be scattered throughout many template parameters and that removing them cleans up the code base without affecting performance. This change moves register widths into 2 locations; a function called `bits()` in all `ISAInfo` sub-classes (of which there is one per ISA), and the `N` template parameter in the `BitRange` class. Although `N` keeps the register width as a template parameter, it is not as scattered throughout the code base because each ISA uses their own default parameter for `N` equal to the ISA's register width. For example, in the RISC-V C extension file:

```c++
template <unsigned start, unsigned stop>
using BitRange = Ripes::BitRange<start, stop, 16>;
```

## Future Changes

There are also a few other improvements that can be made after this change.

One is in the `RegInfoBase` class that (as of this change) defines information about all of the registers for an ISA. Although it didn't make it in time for this commit, I've been working on changing this class so that it defines a single register file of an ISA. There will then be a `RegInfoSet` class that holds all of the currently enabled register files for an ISA. This will allow indexing into registers from either a specific register file or all enabled register files as a whole.

Another improvement is adding more compile-time instruction verifications. When instructions are combined into a struct at compile-time, as described above, it can be verified at compile-time that there are no duplicate instructions or instruction mnemonics. Other similar verifications could be added to further ensure that ISA implementations are correct.

Finally, I think that the implementation for pseudo-instructions could be improved by defining the instructions that they expand into at compile-time. Currently, the `PseudoInstruction` method `expander()` defines what the pseudo-instruction expands to, at runtime. Although I have not tested it yet, I think that this could be improved by changing the `expander()` function into a struct containing the expanded instructions (defined at compile-time).
raccog added a commit to raccog/Ripes that referenced this issue Dec 5, 2023
mortbopet pushed a commit that referenced this issue Dec 6, 2023
* Move instruction set vector from Assembler to ISAInfo

* Fix clang-format

* Add back runtime errors to assembler initializations

* Change ISA-specific assemblers into a single template class

This change should complete #303.

* Throw runtime error in `constructAssemblerDynamic()`

Also added doc comment.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant