Hey, Michael Walle asked me to publish a documentation of Milkymist MMU in order for him to study the feasibility of implementing a model for this MMU in QEmu. Documenting is always something one needs to do at some point, so here it is, written very quickly in a small text file.
I hope it is clear enough, if you have any question: do not hesitate to ask me :) This is not a complete documentation, it does not say anything about generated exceptions/TLB miss/page fault etc. Cheers ! -- Yann Sionneau
Milkymist MMU documentation Page size : 4 kB page offset : addr[11:0] page frame number : addr[31:12] *TLB size : 1024 entries => TLB index == addr[21:12] TLB contains 10 bits vaddr[31:22] tag + 10 bits paddr[31:22] + 1 valid bit To control ITLB or DTLB you should write to TLBCTRL csr. let "csr_write_data[31:0]" be the value written to TLBCTRL csr. The lowest bit is used to chose which TLB you want to control : - csr_write_data[0] == 1'b1 : DTLB is controlled - csr_write_data[0] == 1'b0 : ITLB is controlled The remaining bits of csr_write_data are the command ID. They select which action is done on the selected TLB. If the action involves a virtual address, the latter has to be written first to the TLBVADDR csr register. If the action involves a physical address, the latter has to be written first to the TLBPADDR csr register. TLB actions sorted by csr_write_data[5:1] : - 5'h1 : FLUSH the entire TLB - 5'h2 : UPDATE the selected TLB line - 5'h4 : Switch to kernel mode (for debugging and developpment purposes only, will be removed later on) - 5'h8 : Switch to user mode (for debugging and developpment purposes only, will be removed later on) - 5'h10 : INVALIDATE the selected TLB line Note : The TLBPADDR and TLBVADDR csr registers internally are exclusive to each *TLB. If you intend to INVALIDATE a DTLB line, you should therefore write the DTLB index of the line you want to invalidate inside the TLBVADDR csr reg *OF THE DTLB*. You select the *TLB when you write to TLBVADDR with the lowest bit - as before. TLBPADDR and TLBVADDR are used to select which line of the TLB is concerned by the following TLBCTRL command and which physical address is concerned (for an UPDATE) The concerned TLB line index should be written in TLBVADDR at the position it would occupy in a real world memory address => TLBVADDR[21:12]. This allows you to directly write your virtual address (with lowest bit set according to which TLB you want to control) to TLBVADDR. The same thing applies for TLBPADDR. Other bits than [21:12] and [0] of TLBPADDR and TLBVADDR are reserved for future use. They will be needed to add access control feature (READ, WRITE, EXECUTE), DIRTY bit and maybe more. Examples : 1°) Flush the DTLB : mvi r1, 0x3 wcsr tlbctrl, r1 0x3 means 2'b11 ||-> means you select DTLB |--> means command 5'h1 => FLUSH entirely selected TLB 2°) Update DTLB with mapping vpfn (virtual page frame number) 0x44001 to ppfn (physical pfn) 0x44002 This actually means updating index 0x1 of the DTLB to contain the physical pfn 0x2 because TLB index is only 10 bits wide the 0x44 prefix is dropped. You can write the prefix anyway, only the necessary bits will be used. mvhi r1, 0x4400 ori r1, r1, 0x1001 wcsr tlbvaddr, r1 mvi r1, 0x4400 ori r1, r1, 0x2001 wcsr tlbpaddr, r1 xor r1, r1, r1 mvi r1, 0x5 wcsr tlbctrl, r1 The first three lines write the virtual address to the TLBVADDR csr reg of the DTLB system (DTLB ? yes, because the address ends with lowest bit '1') The next three lines write the physical address to the TLBPADDR csr reg of the DTLB system (same reason, DTLB because of the address ending with lowest bit '1') The last three lines trigger the actual update of the DTLB line. 0x5 means 3'b101 |||-> This bit selects the DTLB || `|--> Those two bits select command 2'b10 => 5'h2 which means UPDATE the selected TLB. 3°) FLUSH/INVALIDATE ITLB line number 5 xor r1, r1, r1 mvi r1, 0x5000 wcsr tlbvaddr, r1 mvi r1, 0x20 wcsr tlbctrl, r1
_______________________________________________ http://lists.milkymist.org/listinfo.cgi/devel-milkymist.org IRC: #milkymist@Freenode