Skip to content

Conversation

nemecad
Copy link

@nemecad nemecad commented Aug 1, 2025

This PR implements basic virtual memory support:

  • Set-associative TLB (machine::TLB): Implements a set-associative Translation Lookaside Buffer (TLB) frontend over physical memory, handling virtual to physical translation, flush, and replacement policy.
  • Pluggable Replacement Policies (machine::TLBPolicy): Abstract TLB replacement policy interface & implementations (RAND, LRU, LFU, PLRU) for set-associative tables.
  • SV32 Page-Table Walker (machine::PageTableWalker): Performs multi-level page-table walks (SV32) in memory to resolve a virtual address to a physical one.
  • Sv32Pte Bitfield Helpers (sv32.h): SV32-specific definitions: page-table entry (PTE) bitfields, shifts/masks, and PTE to physical address helpers.
  • VirtualAddress (virtual_address.h): Lightweight VirtualAddress wrapper offering raw access, alignment checks, arithmetic, and comparisons.
  • Page Fault Handling (machine::PageFaultHandler): Catches page-fault exceptions, invokes page allocation, and recovers execution.
  • Qt “BigSlider” Widget (BigSlider): Qt widget subclass exposing 64-bit slider range/value designed for selecting a base virtual memory address from 0x0000_0000 up to 0xFFFF_F000.

UI Components:

  • Configuration Dialog:
Snímek obrazovky 2025-08-01 154839
  • Memory window: “Show virtual” checkbox to toggle between physical and virtual address spaces.
Snímek obrazovky 2025-08-01 154908 Snímek obrazovky 2025-08-01 154858

Copy link
Collaborator

@jdupak jdupak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall this is pretty good work! Thank you

Most of my comments are style nits, so don't worry to much :) Btw, please make sure the the code is properly formated by clangformat that with config that is in the root of the project.

There are some cases I think we should move the components around to make this better encapslated.

There is one major decision that we need to make regarding the use of virtual memory. I think the current compomise is not great.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please delete the accidentally committed files.

Comment on lines +19 to +20
/cmake-build-debug-wsl/
/cmake-build-release-wsl/
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The way I do this on my machine is that I configure the files to be build/Debug and build/Release. You can also ignore thise files localy. It should not be here.

@@ -79,6 +80,7 @@ class SimpleAsm : public QObject {
private:
QStringList include_stack;
machine::FrontendMemory *mem {};
machine::MachineConfig config {};
machine::RelocExpressionList reloc;
};
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be a pointer - it feels weirt to have multiple copies of machine config in the program.

@@ -286,7 +288,12 @@ bool SimpleAsm::process_line(
if (error_ptr != nullptr) { *error_ptr = error; }
return false;
}
address = machine::Address(value);
qint64 offset = qint64(value);
qint64 base = 0;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: please prefer standard cpp types over qt ones whenever possible.

if (config.get_vm_enabled() && config.get_vm_mode() == machine::MachineConfig::VM_SV32) {
base = config.get_kernel_virt_base();
}
address = machine::Address(base + offset);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now looking at this, wouldn't it be simpler to just pass the base to the assembler constructor and keep this logic outside?

aclint::AclintSswi *aclint_sswi = nullptr;
std::optional<TLB> tlb_program;
std::optional<TLB> tlb_data;
FrontendMemory *instr_if_;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will require a deeper design decision @ppisa

I see 2 ways to go here:

  • We go all in on virtual addresses. We say that the CPU always operates with virtual memory. For CPU without MMU we make the mapping 1:1. This means that the memory interface will always be an instance of TLB (possibly trivial).
  • We give up on virtuall addresses, we just make TLB just another instance of FrontendMemory. We use the same type for both virtual and physical address.

This code is somewhere in the middle which IMO does not bring any benefit of special type but brings all the cons. This one is on me, I should have explained it better.

return false;
}

void PageFaultHandler::perform_page_allocation(const VirtualAddress &va, uint32_t raw_satp) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ppisa I am wondering if this should rather be in osemu.

Comment on lines 22 to +23
if (machine == nullptr) { return nullptr; }
if (machine->memory_data_bus() != nullptr) { return machine->memory_data_bus(); }
return machine->instr_frontend();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is wrong, thos never used to point to cache.

this->machine = machine;
if (machine && machine->config().get_vm_enabled()
&& machine->config().get_vm_mode() == machine::MachineConfig::VM_SV32) {
index0_offset = machine::Address(machine->config().get_va_base_addr());
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this place is a really good ilustration why separate virtual memory type will increase clarity a lot.

Comment on lines -71 to -72
if (mem == nullptr) { return QString(""); }
if ((access_through_cache > 0) && (machine->cache_data() != nullptr)) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might need this for proper startup/reset,

@jdupak
Copy link
Collaborator

jdupak commented Aug 16, 2025

Also, please consider that the next person reading this code will not be an expert on MMU like you, so try to add comments and use less cryptic names whenever possible (don't be afraid of long names too much).

@ppisa
Copy link
Member

ppisa commented Aug 17, 2025

I did send direct e-mail to @nemecad and @jdupak at 2025-08-08. It has been mainly about generated content in the commits and some remarks for clarification etc. I hope that you have received it. I plan ti provide review there when the technical/format problems are resolved and updated series is posted.

@jdupak
Copy link
Collaborator

jdupak commented Aug 18, 2025

I did send direct e-mail to @nemecad and @jdupak at 2025-08-08. It has been mainly about generated content in the commits and some remarks for clarification etc. I hope that you have received it. I plan ti provide review there when the technical/format problems are resolved and updated series is posted.

I did get it, but the generated files did not cause too much trouble for me to review this.

@petr-stepan
Copy link

Nice work, I have problem to cmake this project. I had to change CMakeList.txt in machine directory (remove memory and some others tests). Then in cli main.cpp, there is TODO at line 500, than was necessary to comment.
Finally, I run qtrvsim_gui and started virtual memory. In dialog number of sets should be only power of 2. The virtual memory base address input is not working. If I tried to insert concrete number, then there was error.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants