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

Implement disassembler and instruction fetch cycle #25

Merged
merged 11 commits into from
Jul 18, 2024
Merged

Conversation

Scott-Guest
Copy link
Contributor

@Scott-Guest Scott-Guest commented Jul 8, 2024

Implements everything needed to execute our first instructions 🥳

  • Define basic configuration with
    • Map{Int, Int} mapping address to the initialized data at those ranges
    • PC register value
    • Map{Int, Int} mapping register numbers to their values
      • The Int value is the register's value interpreted as an XLEN-bit two's complement signed integer
      • x0, which is always hardcoded to be 0, isn't directly stored and instead handled by readReg/writeReg
  • Disassembler
  • Instruction fetch cycle
  • Logic to halt at a given address defined by a specified symbol in the ELF file
    • RISC-V has no built-in means to halt, and instead passes this responsibility off to the surrounding OS / execution environment. Halting at a particular symbol is just the easiest solution I could come up with for testing.
    • The conformance tests and other simulators use a more involved tohost / fromhost format, which we should also implement eventually
  • ADDI and LUI instructions

@Scott-Guest Scott-Guest force-pushed the simple-instrs branch 3 times, most recently from 8a8238d to 93d8a93 Compare July 15, 2024 01:44
@Scott-Guest Scott-Guest marked this pull request as ready for review July 15, 2024 05:06
@Scott-Guest Scott-Guest self-assigned this Jul 15, 2024
@Scott-Guest
Copy link
Contributor Author

After further discussion, a RangeMap{Int, Bytes} is not the right data structure for memory. We were essentially trying to use the RangeMap as an Map{Int, Int}, but using ranges to pack together the data of consecutively defined addresses into a single Bytes value as a space saving optimization.

However, there are a few issues with this:

  • In practice, we won't actually save much space:
    • The only large ranges are the initial one or two ELF segments, which will hold the instruction memory and possibly some static data. Neither of these ranges should be that large.
    • All operations are done at the single byte level, so all dynamically created ranges will only be 1-byte long, degrading the space performance back to the same as a Map
  • RangeMap's range coalescing is undesirable:
    • Conceptually, [start, end) r|-> data was supposed to mean that the byte at address start <= addr < end has value data[addr - start], thus length(data) == end - start
    • However, coalescing breaks this invariant:
      • [0, 2) |-> b"\x12\x34", [2, 4) |-> b"\x12\x34" coalesces to [0, 4) |-> b"\x12\x34"
      • What do we do if we want to store to address 3?
  • RangeMaps don't have symbolic reasoning support, and working around the coalescing + manually doing coalescing with concatenation will make this even more difficult.

For the time being, I'll switch to just a Map{Int, Int} instead then, but hidden behind the loadBytes function so it's easy to swap out later. If there are performance issues, we should steal the SparseBytes data structure from the WASM semantics.

@rv-jenkins rv-jenkins merged commit f6c0156 into master Jul 18, 2024
3 checks passed
@rv-jenkins rv-jenkins deleted the simple-instrs branch July 18, 2024 21:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants