mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
Implement support for superpages
This commit is contained in:
parent
7888eacc3f
commit
e807f5d771
@ -26,6 +26,8 @@
|
||||
///////////////////////////////////////////
|
||||
|
||||
// Virtual Memory Constants (sv39)
|
||||
`define VPN_SEGMENT_BITS 9
|
||||
`define VPN_BITS 27
|
||||
`define PPN_BITS 44
|
||||
`define PPN_HIGH_SEGMENT_BITS 26
|
||||
`define PA_BITS 56
|
||||
|
@ -26,6 +26,8 @@
|
||||
///////////////////////////////////////////
|
||||
|
||||
// Virtual Memory Constants (sv39)
|
||||
`define VPN_SEGMENT_BITS 9
|
||||
`define VPN_BITS 27
|
||||
`define PPN_BITS 44
|
||||
`define PPN_HIGH_SEGMENT_BITS 26
|
||||
`define PA_BITS 56
|
||||
|
@ -26,6 +26,8 @@
|
||||
///////////////////////////////////////////
|
||||
|
||||
// Virtual Memory Constants (sv39)
|
||||
`define VPN_SEGMENT_BITS 9
|
||||
`define VPN_BITS 27
|
||||
`define PPN_BITS 44
|
||||
`define PPN_HIGH_SEGMENT_BITS 26
|
||||
`define PA_BITS 56
|
||||
|
@ -26,6 +26,8 @@
|
||||
///////////////////////////////////////////
|
||||
|
||||
// Virtual Memory Constants (sv32)
|
||||
`define VPN_SEGMENT_BITS 10
|
||||
`define VPN_BITS 20
|
||||
`define PPN_BITS 22
|
||||
`define PPN_HIGH_SEGMENT_BITS 12
|
||||
`define PA_BITS 34
|
||||
|
@ -25,11 +25,9 @@
|
||||
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
///////////////////////////////////////////
|
||||
|
||||
// Interrupt configuration
|
||||
`define PLIC_NUM_SRC 53
|
||||
`define PLIC_UART_ID 4
|
||||
|
||||
// Virtual Memory Constants (sv39)
|
||||
`define VPN_SEGMENT_BITS 9
|
||||
`define VPN_BITS 27
|
||||
`define PPN_BITS 44
|
||||
`define PPN_HIGH_SEGMENT_BITS 26
|
||||
`define PA_BITS 56
|
||||
|
@ -26,6 +26,8 @@
|
||||
///////////////////////////////////////////
|
||||
|
||||
// Virtual Memory Constants (sv39)
|
||||
`define VPN_SEGMENT_BITS 9
|
||||
`define VPN_BITS 27
|
||||
`define PPN_BITS 44
|
||||
`define PPN_HIGH_SEGMENT_BITS 26
|
||||
`define PA_BITS 56
|
||||
|
@ -26,6 +26,8 @@
|
||||
///////////////////////////////////////////
|
||||
|
||||
// Virtual Memory Constants (sv39)
|
||||
`define VPN_SEGMENT_BITS 9
|
||||
`define VPN_BITS 27
|
||||
`define PPN_BITS 44
|
||||
`define PPN_HIGH_SEGMENT_BITS 26
|
||||
`define PA_BITS 56
|
||||
|
@ -52,20 +52,23 @@ module dmem (
|
||||
// TLB management
|
||||
input logic [1:0] PrivilegeModeW,
|
||||
input logic [`XLEN-1:0] PageTableEntryM,
|
||||
input logic [1:0] PageTypeM,
|
||||
input logic [`XLEN-1:0] SATP_REGW,
|
||||
input logic DTLBWriteM, // DTLBFlushM,
|
||||
input logic DTLBWriteM, DTLBFlushM,
|
||||
output logic DTLBMissM, DTLBHitM
|
||||
);
|
||||
|
||||
logic MemAccessM; // Whether memory needs to be accessed
|
||||
logic SquashSCM;
|
||||
// *** needs to be sent to trap unit
|
||||
logic DTLBPageFaultM;
|
||||
|
||||
// *** temporary hack until walker is hooked up -- Thomas F
|
||||
// logic [`XLEN-1:0] PageTableEntryM = '0;
|
||||
logic DTLBFlushM = '0;
|
||||
// logic DTLBWriteM = '0;
|
||||
tlb #(3) dtlb(clk, reset, SATP_REGW, PrivilegeModeW, MemAccessM, MemAdrM, PageTableEntryM, DTLBWriteM,
|
||||
DTLBFlushM, MemPAdrM, DTLBMissM, DTLBHitM);
|
||||
tlb #(3) dtlb(.TLBAccess(MemAccessM), .VirtualAddress(MemAdrM),
|
||||
.PageTableEntryWrite(PageTableEntryM), .PageTypeWrite(PageTypeM),
|
||||
.TLBWrite(DTLBWriteM), .TLBFlush(DTLBFlushM),
|
||||
.PhysicalAddress(MemPAdrM), .TLBMiss(DTLBMissM),
|
||||
.TLBHit(DTLBHitM), .TLBPageFault(DTLBPageFaultM),
|
||||
.*);
|
||||
|
||||
// Determine if an Unaligned access is taking place
|
||||
always_comb
|
||||
|
@ -48,6 +48,7 @@ module pagetablewalker (
|
||||
|
||||
// Outputs to the TLBs (PTEs to write)
|
||||
output logic [`XLEN-1:0] PageTableEntryF, PageTableEntryM,
|
||||
output logic [1:0] PageTypeF, PageTypeM,
|
||||
output logic ITLBWriteF, DTLBWriteM,
|
||||
|
||||
// Signals from ahblite (PTEs from memory)
|
||||
@ -78,6 +79,10 @@ module pagetablewalker (
|
||||
// PTE descriptions
|
||||
logic ValidPTE, AccessAlert, MegapageMisaligned, BadMegapage, LeafPTE;
|
||||
|
||||
// Outputs of walker
|
||||
logic [`XLEN-1:0] PageTableEntry;
|
||||
logic [1:0] PageType;
|
||||
|
||||
// Signals for direct, fake translations. Not part of the final Wally version.
|
||||
logic [`XLEN-1:0] DirectInstrPTE, DirectMemPTE;
|
||||
logic [9:0] DirectPTEFlags = {2'b0, 8'b00001111};
|
||||
@ -122,6 +127,12 @@ module pagetablewalker (
|
||||
assign ValidPTE = Valid && ~(Writable && ~Readable);
|
||||
assign AccessAlert = ~Accessed || (MemStore && ~Dirty);
|
||||
|
||||
// Assign specific outputs to general outputs
|
||||
assign PageTableEntryF = PageTableEntry;
|
||||
assign PageTableEntryM = PageTableEntry;
|
||||
assign PageTypeF = PageType;
|
||||
assign PageTypeM = PageType;
|
||||
|
||||
generate
|
||||
if (`XLEN == 32) begin
|
||||
logic [9:0] VPN1, VPN0;
|
||||
@ -169,8 +180,8 @@ module pagetablewalker (
|
||||
always_comb begin
|
||||
// default values
|
||||
assign TranslationPAdr = '0;
|
||||
assign PageTableEntryF = '0;
|
||||
assign PageTableEntryM = '0;
|
||||
assign PageTableEntry = '0;
|
||||
assign PageType ='0;
|
||||
assign MMUTranslationComplete = '0;
|
||||
assign DTLBWriteM = '0;
|
||||
assign ITLBWriteF = '0;
|
||||
@ -188,8 +199,8 @@ module pagetablewalker (
|
||||
LEAF: begin
|
||||
// Keep physical address alive to prevent HADDR dropping to 0
|
||||
assign TranslationPAdr = {CurrentPPN, VPN0, 2'b00};
|
||||
assign PageTableEntryF = CurrentPTE;
|
||||
assign PageTableEntryM = CurrentPTE;
|
||||
assign PageTableEntry = CurrentPTE;
|
||||
assign PageType = (WalkerState == LEVEL1) ? 2'b01 : 2'b00;
|
||||
assign MMUTranslationComplete = '1;
|
||||
assign DTLBWriteM = DTLBMissM;
|
||||
assign ITLBWriteF = ~DTLBMissM; // Prefer data over instructions
|
||||
@ -204,8 +215,6 @@ module pagetablewalker (
|
||||
endcase
|
||||
end
|
||||
|
||||
|
||||
|
||||
// Capture page table entry from ahblite
|
||||
flopenr #(32) ptereg(HCLK, ~HRESETn, MMUReady, MMUReadPTE, SavedPTE);
|
||||
mux2 #(32) ptemux(SavedPTE, MMUReadPTE, MMUReady, CurrentPTE);
|
||||
@ -271,8 +280,8 @@ module pagetablewalker (
|
||||
always_comb begin
|
||||
// default values
|
||||
assign TranslationPAdr = '0;
|
||||
assign PageTableEntryF = '0;
|
||||
assign PageTableEntryM = '0;
|
||||
assign PageTableEntry = '0;
|
||||
assign PageType = '0;
|
||||
assign MMUTranslationComplete = '0;
|
||||
assign DTLBWriteM = '0;
|
||||
assign ITLBWriteF = '0;
|
||||
@ -293,8 +302,9 @@ module pagetablewalker (
|
||||
LEAF: begin
|
||||
// Keep physical address alive to prevent HADDR dropping to 0
|
||||
assign TranslationPAdr = {CurrentPPN, VPN0, 3'b000};
|
||||
assign PageTableEntryF = CurrentPTE;
|
||||
assign PageTableEntryM = CurrentPTE;
|
||||
assign PageTableEntry = CurrentPTE;
|
||||
assign PageType = (WalkerState == LEVEL2) ? 2'b11 :
|
||||
((WalkerState == LEVEL1) ? 2'b01 : 2'b00);
|
||||
assign MMUTranslationComplete = '1;
|
||||
assign DTLBWriteM = DTLBMissM;
|
||||
assign ITLBWriteF = ~DTLBMissM; // Prefer data over instructions
|
||||
|
@ -60,6 +60,7 @@ module ifu (
|
||||
// TLB management
|
||||
input logic [1:0] PrivilegeModeW,
|
||||
input logic [`XLEN-1:0] PageTableEntryF,
|
||||
input logic [1:0] PageTypeF,
|
||||
input logic [`XLEN-1:0] SATP_REGW,
|
||||
input logic ITLBWriteF, ITLBFlushF,
|
||||
output logic ITLBMissF, ITLBHitF
|
||||
@ -74,9 +75,15 @@ module ifu (
|
||||
logic [31:0] InstrRawD, InstrE, InstrW;
|
||||
logic [31:0] nop = 32'h00000013; // instruction for NOP
|
||||
logic [`XLEN-1:0] ITLBInstrPAdrF, ICacheInstrPAdrF;
|
||||
// *** send this to the trap unit
|
||||
logic ITLBPageFaultF;
|
||||
|
||||
tlb #(3) itlb(clk, reset, SATP_REGW, PrivilegeModeW, 1'b1, PCF, PageTableEntryF, ITLBWriteF, ITLBFlushF,
|
||||
ITLBInstrPAdrF, ITLBMissF, ITLBHitF);
|
||||
tlb #(3) itlb(.TLBAccess(1'b1), .VirtualAddress(PCF),
|
||||
.PageTableEntryWrite(PageTableEntryF), .PageTypeWrite(PageTypeF),
|
||||
.TLBWrite(ITLBWriteF), .TLBFlush(ITLBFlushF),
|
||||
.PhysicalAddress(ITLBInstrPAdrF), .TLBMiss(ITLBMissF),
|
||||
.TLBHit(ITLBHitF), .TLBPageFault(ITLBPageFaultF),
|
||||
.*);
|
||||
|
||||
// branch predictor signals
|
||||
logic SelBPPredF;
|
||||
|
79
wally-pipelined/src/mmu/cam_line.sv
Normal file
79
wally-pipelined/src/mmu/cam_line.sv
Normal file
@ -0,0 +1,79 @@
|
||||
///////////////////////////////////////////
|
||||
// cam_line.sv
|
||||
//
|
||||
// Written: tfleming@hmc.edu & jtorrey@hmc.edu 6 April 2021
|
||||
// Modified:
|
||||
//
|
||||
// Purpose: CAM line for the translation lookaside buffer (TLB)
|
||||
// Determines whether a virtual address matches the stored key.
|
||||
//
|
||||
// A component of the Wally configurable RISC-V project.
|
||||
//
|
||||
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
|
||||
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
|
||||
// is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
|
||||
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
///////////////////////////////////////////
|
||||
|
||||
`include "wally-config.vh"
|
||||
`include "wally-constants.vh"
|
||||
|
||||
module cam_line #(parameter KEY_BITS = 20,
|
||||
parameter HIGH_SEGMENT_BITS = 10) (
|
||||
input clk, reset,
|
||||
|
||||
// The requested page number to compare against the key
|
||||
input [KEY_BITS-1:0] VirtualPageNumber,
|
||||
|
||||
// Signals to write a new entry to this line
|
||||
input CAMLineWrite,
|
||||
input [1:0] PageTypeWrite,
|
||||
|
||||
// Flush this line (set valid to 0)
|
||||
input TLBFlush,
|
||||
|
||||
// This entry is a key for a giga, mega, or kilopage.
|
||||
// PageType == 2'b00 --> kilopage
|
||||
// PageType == 2'b01 --> megapage
|
||||
// PageType == 2'b11 --> gigapage
|
||||
output [1:0] PageType, // *** should this be the stored version or the always updated one?
|
||||
output Match
|
||||
);
|
||||
|
||||
// This entry has KEY_BITS for the key plus one valid bit.
|
||||
logic Valid;
|
||||
logic [KEY_BITS-1:0] Key;
|
||||
|
||||
// When determining a match for a superpage, we might use only a portion of
|
||||
// the input VirtualPageNumber. Unused parts of the VirtualPageNumber are
|
||||
// zeroed in VirtualPageNumberQuery to better match with Key.
|
||||
logic [KEY_BITS-1:0] VirtualPageNumberQuery;
|
||||
|
||||
// On a write, update the type of the page referred to by this line.
|
||||
flopenr #(2) pagetypeflop(clk, reset, CAMLineWrite, PageTypeWrite, PageType);
|
||||
//mux2 #(2) pagetypemux(StoredPageType, PageTypeWrite, CAMLineWrite, PageType);
|
||||
|
||||
// On a write, set the valid bit high and update the stored key.
|
||||
// On a flush, zero the valid bit and leave the key unchanged.
|
||||
// *** Might we want to update stored key right away to output match on the
|
||||
// write cycle? (using a mux)
|
||||
flopenrc #(1) validbitflop(clk, reset, TLBFlush, CAMLineWrite, 1'b1, Valid);
|
||||
flopenr #(KEY_BITS) keyflop(clk, reset, CAMLineWrite, VirtualPageNumber, Key);
|
||||
|
||||
// Calculate the actual query key based on the input key and the page type.
|
||||
// For example, a megapage in sv39 only cares about VPN2 and VPN1, so VPN0
|
||||
// should automatically match.
|
||||
page_number_mixer #(KEY_BITS, HIGH_SEGMENT_BITS) mixer(VirtualPageNumber, Key, PageType, VirtualPageNumberQuery);
|
||||
|
||||
assign Match = ({1'b1, VirtualPageNumberQuery} == Key);
|
||||
|
||||
endmodule
|
36
wally-pipelined/src/mmu/decoder.sv
Normal file
36
wally-pipelined/src/mmu/decoder.sv
Normal file
@ -0,0 +1,36 @@
|
||||
///////////////////////////////////////////
|
||||
// decoder.sv
|
||||
//
|
||||
// Written: tfleming@hmc.edu & jtorrey@hmc.edu 7 April 2021
|
||||
// Modified:
|
||||
//
|
||||
// Purpose: Binary encoding to one-hot decoder
|
||||
//
|
||||
// A component of the Wally configurable RISC-V project.
|
||||
//
|
||||
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
|
||||
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
|
||||
// is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
|
||||
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
///////////////////////////////////////////
|
||||
|
||||
`include "wally-config.vh"
|
||||
|
||||
module decoder #(parameter BINARY_BITS = 3) (
|
||||
input [BINARY_BITS-1:0] binary,
|
||||
output [(2**BINARY_BITS)-1:0] one_hot
|
||||
);
|
||||
|
||||
// *** Double check whether this synthesizes as expected
|
||||
assign one_hot = 1 << binary;
|
||||
|
||||
endmodule
|
85
wally-pipelined/src/mmu/page_number_mixer.sv
Normal file
85
wally-pipelined/src/mmu/page_number_mixer.sv
Normal file
@ -0,0 +1,85 @@
|
||||
///////////////////////////////////////////
|
||||
// page_number_mixer.sv
|
||||
//
|
||||
// Written: tfleming@hmc.edu & jtorrey@hmc.edu 6 April 2021
|
||||
// Modified:
|
||||
//
|
||||
// Purpose: Takes two page numbers and replaces segments of the first page
|
||||
// number with segments from the second, based on the page type.
|
||||
//
|
||||
// A component of the Wally configurable RISC-V project.
|
||||
//
|
||||
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
|
||||
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
|
||||
// is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
|
||||
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
///////////////////////////////////////////
|
||||
|
||||
`include "wally-config.vh"
|
||||
|
||||
module page_number_mixer #(parameter BITS = 20,
|
||||
parameter HIGH_SEGMENT_BITS = 10) (
|
||||
input [BITS-1:0] PageNumber,
|
||||
input [BITS-1:0] MixPageNumber,
|
||||
input [1:0] PageType,
|
||||
output [BITS-1:0] PageNumberCombined
|
||||
);
|
||||
|
||||
generate
|
||||
// *** Just checking XLEN is not enough to support sv39 AND sv48.
|
||||
if (`XLEN == 32) begin
|
||||
// The upper segment might have a different width than the lower segments.
|
||||
// For example, an sv39 PTE has 26 bits for PPN2 and 9 bits for the other
|
||||
// segments.
|
||||
localparam LOW_SEGMENT_BITS = (BITS - HIGH_SEGMENT_BITS);
|
||||
|
||||
logic [HIGH_SEGMENT_BITS-1:0] Segment1, MixSegment1, Segment1Combined;
|
||||
logic [LOW_SEGMENT_BITS-1:0] Segment0, MixSegment0, Segment0Combined;
|
||||
|
||||
// Unswizzle segments of the input page numbers
|
||||
assign {Segment1, Segment0} = PageNumber;
|
||||
assign {MixSegment1, MixSegment0} = MixPageNumber;
|
||||
|
||||
// Pass through the high segment
|
||||
assign Segment1Combined = Segment1;
|
||||
|
||||
// Either pass through or zero out segment 0
|
||||
mux2 #(LOW_SEGMENT_BITS) segment0mux(Segment0, MixSegment0, PageType[0], Segment0Combined);
|
||||
|
||||
// Reswizzle segments of the combined page number
|
||||
assign PageNumberCombined = {Segment1Combined, Segment0Combined};
|
||||
end else begin
|
||||
// The upper segment might have a different width than the lower segments.
|
||||
// For example, an sv39 PTE has 26 bits for PPN2 and 9 bits for the other
|
||||
// segments.
|
||||
localparam LOW_SEGMENT_BITS = (BITS - HIGH_SEGMENT_BITS) / 2;
|
||||
|
||||
logic [HIGH_SEGMENT_BITS-1:0] Segment2, MixSegment2, Segment2Combined;
|
||||
logic [LOW_SEGMENT_BITS-1:0] Segment1, MixSegment1, Segment1Combined;
|
||||
logic [LOW_SEGMENT_BITS-1:0] Segment0, MixSegment0, Segment0Combined;
|
||||
|
||||
// Unswizzle segments of the input page number
|
||||
assign {Segment2, Segment1, Segment0} = PageNumber;
|
||||
assign {MixSegment2, MixSegment1, MixSegment0} = MixPageNumber;
|
||||
|
||||
// Pass through the high segment
|
||||
assign Segment2Combined = Segment2;
|
||||
|
||||
// Either pass through or zero out segments 1 and 0 based on the page type
|
||||
mux2 #(LOW_SEGMENT_BITS) segment1mux(Segment1, MixSegment1, PageType[1], Segment1Combined);
|
||||
mux2 #(LOW_SEGMENT_BITS) segment0mux(Segment0, MixSegment0, PageType[0], Segment0Combined);
|
||||
|
||||
// Reswizzle segments of the combined page number
|
||||
assign PageNumberCombined = {Segment2Combined, Segment1Combined, Segment0Combined};
|
||||
end
|
||||
endgenerate
|
||||
endmodule
|
48
wally-pipelined/src/mmu/priority_encoder.sv
Normal file
48
wally-pipelined/src/mmu/priority_encoder.sv
Normal file
@ -0,0 +1,48 @@
|
||||
///////////////////////////////////////////
|
||||
// priority_encoder.sv
|
||||
//
|
||||
// Written: tfleming@hmc.edu & jtorrey@hmc.edu 7 April 2021
|
||||
// Modified:
|
||||
//
|
||||
// Purpose: One-hot encoding to binary encoder
|
||||
//
|
||||
// A component of the Wally configurable RISC-V project.
|
||||
//
|
||||
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
|
||||
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
|
||||
// is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
|
||||
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
///////////////////////////////////////////
|
||||
|
||||
`include "wally-config.vh"
|
||||
|
||||
// *** We should look for a better parameterized priority encoder. This has a
|
||||
// bad code smell and might not synthesize
|
||||
module priority_encoder #(parameter BINARY_BITS = 3) (
|
||||
input [(2**BINARY_BITS)-1:0] one_hot,
|
||||
output [BINARY_BITS-1:0] binary
|
||||
);
|
||||
|
||||
localparam ONE_HOT_BITS = 2**BINARY_BITS;
|
||||
|
||||
genvar i, j;
|
||||
generate
|
||||
for (i = 0; i < ONE_HOT_BITS; i++) begin
|
||||
for (j = 0; j < BINARY_BITS; j++) begin
|
||||
if (i[j]) begin
|
||||
assign binary[j] = one_hot[i];
|
||||
end
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
|
||||
endmodule
|
@ -71,6 +71,7 @@ module tlb #(parameter ENTRY_BITS = 3) (
|
||||
|
||||
// Controls for writing a new entry to the TLB
|
||||
input [`XLEN-1:0] PageTableEntryWrite,
|
||||
input [1:0] PageTypeWrite,
|
||||
input TLBWrite,
|
||||
|
||||
// Invalidate all TLB entries
|
||||
@ -79,7 +80,10 @@ module tlb #(parameter ENTRY_BITS = 3) (
|
||||
// Physical address outputs
|
||||
output [`XLEN-1:0] PhysicalAddress,
|
||||
output TLBMiss,
|
||||
output TLBHit
|
||||
output TLBHit,
|
||||
|
||||
// Faults
|
||||
output TLBPageFault
|
||||
);
|
||||
|
||||
logic SvMode;
|
||||
@ -108,19 +112,18 @@ module tlb #(parameter ENTRY_BITS = 3) (
|
||||
|
||||
// Sections of the virtual and physical addresses
|
||||
logic [`VPN_BITS-1:0] VirtualPageNumber;
|
||||
logic [`PPN_BITS-1:0] PhysicalPageNumber;
|
||||
logic [`PPN_BITS-1:0] PhysicalPageNumber, PhysicalPageNumberMixed;
|
||||
logic [7:0] PTEAccessBits;
|
||||
logic [11:0] PageOffset;
|
||||
logic [`PA_BITS-1:0] PhysicalAddressFull;
|
||||
|
||||
// Pattern and pattern location in the CAM
|
||||
// Pattern location in the CAM and type of page hit
|
||||
logic [ENTRY_BITS-1:0] VPNIndex;
|
||||
logic [1:0] HitPageType;
|
||||
|
||||
// RAM access location
|
||||
logic [ENTRY_BITS-1:0] EntryIndex;
|
||||
|
||||
// Page table entry matching the virtual address
|
||||
logic [`XLEN-1:0] PageTableEntry;
|
||||
|
||||
logic CAMHit;
|
||||
|
||||
assign VirtualPageNumber = VirtualAddress[`VPN_BITS+11:12];
|
||||
@ -130,9 +133,21 @@ module tlb #(parameter ENTRY_BITS = 3) (
|
||||
tlb_rand rdm(.*);
|
||||
|
||||
tlb_ram #(ENTRY_BITS) ram(.*);
|
||||
tlb_cam #(ENTRY_BITS, `VPN_BITS) cam(.*);
|
||||
tlb_cam #(ENTRY_BITS, `VPN_BITS, `VPN_SEGMENT_BITS) cam(.*);
|
||||
|
||||
assign PhysicalAddressFull = (TLBHit) ? {PhysicalPageNumber, PageOffset} : '0;
|
||||
// *** check whether access is allowed, otherwise fault
|
||||
assign TLBPageFault = 0; // *** temporary
|
||||
|
||||
localparam EXTRA_PHYSICAL_BITS = `PPN_HIGH_SEGMENT_BITS - `VPN_SEGMENT_BITS;
|
||||
|
||||
page_number_mixer #(`PPN_BITS, `PPN_HIGH_SEGMENT_BITS)
|
||||
physical_mixer(PhysicalPageNumber,
|
||||
{{EXTRA_PHYSICAL_BITS{1'b0}}, VirtualPageNumber},
|
||||
HitPageType,
|
||||
PhysicalPageNumberMixed);
|
||||
|
||||
assign PhysicalAddressFull = (TLBHit) ?
|
||||
{PhysicalPageNumberMixed, PageOffset} : '0;
|
||||
|
||||
generate
|
||||
if (`XLEN == 32) begin
|
||||
@ -154,18 +169,22 @@ module tlb_ram #(parameter ENTRY_BITS = 3) (
|
||||
input [`XLEN-1:0] PageTableEntryWrite,
|
||||
input TLBWrite,
|
||||
|
||||
output [`XLEN-1:0] PageTableEntry
|
||||
output [`PPN_BITS-1:0] PhysicalPageNumber,
|
||||
output [7:0] PTEAccessBits
|
||||
);
|
||||
|
||||
localparam NENTRIES = 2**ENTRY_BITS;
|
||||
|
||||
logic [`XLEN-1:0] ram [0:NENTRIES-1];
|
||||
logic [`XLEN-1:0] PageTableEntry;
|
||||
always @(posedge clk) begin
|
||||
if (TLBWrite) ram[WriteIndex] <= PageTableEntryWrite;
|
||||
end
|
||||
|
||||
assign PageTableEntry = ram[VPNIndex];
|
||||
|
||||
assign PTEAccessBits = PageTableEntry[7:0];
|
||||
assign PhysicalPageNumber = PageTableEntry[`PPN_BITS+9:10];
|
||||
|
||||
initial begin
|
||||
for (int i = 0; i < NENTRIES; i++)
|
||||
ram[i] = `XLEN'b0;
|
||||
@ -174,54 +193,49 @@ module tlb_ram #(parameter ENTRY_BITS = 3) (
|
||||
endmodule
|
||||
|
||||
module tlb_cam #(parameter ENTRY_BITS = 3,
|
||||
parameter KEY_BITS = 20) (
|
||||
parameter KEY_BITS = 20,
|
||||
parameter HIGH_SEGMENT_BITS = 10) (
|
||||
input clk, reset,
|
||||
input [KEY_BITS-1:0] VirtualPageNumber,
|
||||
input [1:0] PageTypeWrite,
|
||||
input [ENTRY_BITS-1:0] WriteIndex,
|
||||
input TLBWrite,
|
||||
input TLBFlush,
|
||||
output [ENTRY_BITS-1:0] VPNIndex,
|
||||
output [1:0] HitPageType,
|
||||
output CAMHit
|
||||
);
|
||||
|
||||
localparam NENTRIES = 2**ENTRY_BITS;
|
||||
|
||||
// Each entry of this memory has KEY_BITS for the key plus one valid bit.
|
||||
logic [KEY_BITS:0] ram [0:NENTRIES-1];
|
||||
logic [NENTRIES-1:0] CAMLineWrite;
|
||||
logic [1:0] PageTypeList [0:NENTRIES-1];
|
||||
logic [NENTRIES-1:0] Matches;
|
||||
|
||||
logic [ENTRY_BITS-1:0] matched_address_comb;
|
||||
logic match_found_comb;
|
||||
// Determine which CAM line should be written, based on a binary index
|
||||
decoder #(ENTRY_BITS) decoder(WriteIndex, CAMLineWrite);
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (TLBWrite) ram[WriteIndex] <= {1'b1,VirtualPageNumber};
|
||||
if (TLBFlush) begin
|
||||
for (int i = 0; i < NENTRIES; i++)
|
||||
ram[i][KEY_BITS] = 1'b0; // Zero out msb (valid bit) of all entries
|
||||
// Create NENTRIES CAM lines, each of which will independently consider
|
||||
// whether the requested virtual address is a match. Each line stores the
|
||||
// original virtual page number from when the address was written, regardless
|
||||
// of page type. However, matches are determined based on a subset of the
|
||||
// page number segments.
|
||||
generate
|
||||
genvar i;
|
||||
for (i = 0; i < NENTRIES; i++) begin
|
||||
cam_line #(KEY_BITS, HIGH_SEGMENT_BITS) cam_line(
|
||||
.CAMLineWrite(CAMLineWrite[i] && TLBWrite),
|
||||
.PageType(PageTypeList[i]),
|
||||
.Match(Matches[i]),
|
||||
.*);
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
|
||||
// *** Check whether this for loop synthesizes correctly
|
||||
always_comb begin
|
||||
match_found_comb = 1'b0;
|
||||
matched_address_comb = '0;
|
||||
for (int i = 0; i < NENTRIES; i++) begin
|
||||
if (ram[i] == {1'b1,VirtualPageNumber} && !match_found_comb) begin
|
||||
matched_address_comb = i;
|
||||
match_found_comb = 1;
|
||||
end else begin
|
||||
matched_address_comb = matched_address_comb;
|
||||
match_found_comb = match_found_comb;
|
||||
end
|
||||
end
|
||||
end
|
||||
// In case there are multiple matches in the CAM, select only one
|
||||
priority_encoder #(ENTRY_BITS) match_priority(Matches, VPNIndex);
|
||||
|
||||
assign VPNIndex = matched_address_comb;
|
||||
assign CAMHit = match_found_comb & ~TLBFlush;
|
||||
|
||||
initial begin
|
||||
for (int i = 0; i < NENTRIES; i++)
|
||||
ram[i] = '0;
|
||||
end
|
||||
assign CAMHit = |Matches & ~TLBFlush;
|
||||
assign HitPageType = PageTypeList[VPNIndex];
|
||||
|
||||
endmodule
|
||||
|
||||
|
@ -105,6 +105,7 @@ module wallypipelinedhart (
|
||||
logic [1:0] PrivilegeModeW;
|
||||
|
||||
logic [`XLEN-1:0] PageTableEntryF, PageTableEntryM;
|
||||
logic [1:0] PageTypeF, PageTypeM;
|
||||
|
||||
// IMem stalls
|
||||
logic ICacheStallF;
|
||||
|
@ -369,7 +369,7 @@ string tests32i[] = {
|
||||
// if (`F_SUPPORTED) tests = {tests64f, tests};
|
||||
// if (`D_SUPPORTED) tests = {tests64d, tests};
|
||||
if (`A_SUPPORTED) tests = {tests, tests64a};
|
||||
//if (`MEM_VIRTMEM) tests = {tests, tests64mmu};
|
||||
if (`MEM_VIRTMEM) tests = {tests64mmu, tests};
|
||||
end
|
||||
// tests = {tests64a, tests};
|
||||
tests = {tests, tests64p};
|
||||
|
@ -198,7 +198,7 @@ rv32 = Architecture(32)
|
||||
rv64 = Architecture(64)
|
||||
|
||||
if __name__ == "__main__":
|
||||
arch = rv32
|
||||
arch = rv64
|
||||
pgdir = PageTable("page_directory", next_ppn(), arch)
|
||||
|
||||
# Directly map the first 20 pages of RAM
|
||||
|
Loading…
Reference in New Issue
Block a user