cvw/wally-pipelined/src/cache/dmapped.sv

235 lines
9.1 KiB
Systemverilog
Raw Normal View History

2021-03-23 21:03:02 +00:00
///////////////////////////////////////////
// dmapped.sv
//
// Written: jaallen@g.hmc.edu 2021-03-23
// Modified:
//
2021-04-16 01:13:56 +00:00
// Purpose: An implementation of a direct-mapped cache memory, with read-only and write-through versions
2021-03-23 21:03:02 +00:00
//
// 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"
2021-04-16 01:13:56 +00:00
// Read-only direct-mapped memory
2021-04-01 17:55:21 +00:00
module rodirectmappedmem #(parameter NUMLINES=512, parameter LINESIZE = 256, parameter WORDSIZE = `XLEN) (
2021-03-23 21:03:02 +00:00
// Pipeline stuff
input logic clk,
input logic reset,
2021-04-13 05:06:57 +00:00
input logic stall,
2021-03-23 21:03:02 +00:00
// If flush is high, invalidate the entire cache
input logic flush,
// Select which address to read (broken for efficiency's sake)
input logic [`XLEN-1:12] ReadUpperPAdr,
input logic [11:0] ReadLowerAdr,
2021-03-23 21:03:02 +00:00
// Write new data to the cache
input logic WriteEnable,
input logic [LINESIZE-1:0] WriteLine,
input logic [`XLEN-1:0] WritePAdr,
// Output the word, as well as if it is valid
output logic [WORDSIZE-1:0] DataWord,
output logic DataValid
);
2021-04-01 17:55:21 +00:00
// Various compile-time constants
2021-04-13 05:06:57 +00:00
localparam integer WORDWIDTH = $clog2(WORDSIZE/8);
localparam integer OFFSETWIDTH = $clog2(LINESIZE/WORDSIZE);
2021-04-01 17:55:21 +00:00
localparam integer SETWIDTH = $clog2(NUMLINES);
2021-04-13 05:06:57 +00:00
localparam integer TAGWIDTH = `XLEN - OFFSETWIDTH - SETWIDTH - WORDWIDTH;
localparam integer OFFSETBEGIN = WORDWIDTH;
localparam integer OFFSETEND = OFFSETBEGIN+OFFSETWIDTH-1;
localparam integer SETBEGIN = OFFSETEND+1;
localparam integer SETEND = SETBEGIN + SETWIDTH - 1;
localparam integer TAGBEGIN = SETEND + 1;
localparam integer TAGEND = TAGBEGIN + TAGWIDTH - 1;
2021-03-23 21:03:02 +00:00
2021-04-01 17:55:21 +00:00
// Machinery to read from and write to the correct addresses in memory
logic [`XLEN-1:0] ReadPAdr;
2021-04-13 05:06:57 +00:00
logic [`XLEN-1:0] OldReadPAdr;
2021-04-01 17:55:21 +00:00
logic [OFFSETWIDTH-1:0] ReadOffset, WriteOffset;
logic [SETWIDTH-1:0] ReadSet, WriteSet;
logic [TAGWIDTH-1:0] ReadTag, WriteTag;
2021-04-13 05:06:57 +00:00
logic [LINESIZE-1:0] ReadLine;
logic [LINESIZE/WORDSIZE-1:0][WORDSIZE-1:0] ReadLineTransformed;
2021-03-23 21:03:02 +00:00
2021-04-01 17:55:21 +00:00
// Machinery to check if a given read is valid and is the desired value
logic [TAGWIDTH-1:0] DataTag;
2021-04-13 05:06:57 +00:00
logic [NUMLINES-1:0] ValidOut;
2021-04-14 23:03:33 +00:00
logic DataValidBit;
2021-04-13 05:06:57 +00:00
flopenr #(`XLEN) ReadPAdrFlop(clk, reset, ~stall, ReadPAdr, OldReadPAdr);
2021-04-01 17:55:21 +00:00
// Assign the read and write addresses in cache memory
2021-03-23 21:03:02 +00:00
always_comb begin
ReadOffset = OldReadPAdr[OFFSETEND:OFFSETBEGIN];
ReadPAdr = {ReadUpperPAdr, ReadLowerAdr};
ReadSet = ReadPAdr[SETEND:SETBEGIN];
ReadTag = OldReadPAdr[TAGEND:TAGBEGIN];
2021-04-01 17:55:21 +00:00
WriteOffset = WritePAdr[OFFSETEND:OFFSETBEGIN];
WriteSet = WritePAdr[SETEND:SETBEGIN];
WriteTag = WritePAdr[TAGEND:TAGBEGIN];
2021-03-23 21:03:02 +00:00
end
2021-04-13 05:06:57 +00:00
// Depth is number of bits in one "word" of the memory, width is number of such words
Sram1Read1Write #(.DEPTH(LINESIZE), .WIDTH(NUMLINES)) cachemem (
2021-04-01 17:55:21 +00:00
.*,
2021-04-13 05:06:57 +00:00
.ReadAddr(ReadSet),
.ReadData(ReadLine),
.WriteAddr(WriteSet),
.WriteData(WriteLine)
);
Sram1Read1Write #(.DEPTH(TAGWIDTH), .WIDTH(NUMLINES)) cachetags (
.*,
.ReadAddr(ReadSet),
.ReadData(DataTag),
.WriteAddr(WriteSet),
.WriteData(WriteTag)
);
// Pick the right bits coming out the read line
assign DataWord = ReadLineTransformed[ReadOffset];
genvar i;
generate
for (i=0; i < LINESIZE/WORDSIZE; i++) begin:readline
assign ReadLineTransformed[i] = ReadLine[(i+1)*WORDSIZE-1:i*WORDSIZE];
end
endgenerate
// Correctly handle the valid bits
always_ff @(posedge clk, posedge reset) begin
if (reset || flush) begin
ValidOut <= {NUMLINES{1'b0}};
end else begin
if (WriteEnable) begin
ValidOut[WriteSet] <= 1;
end
end
DataValidBit <= ValidOut[ReadSet];
end
assign DataValid = DataValidBit && (DataTag == ReadTag);
endmodule
2021-04-16 01:13:56 +00:00
// Write-through direct-mapped memory
module wtdirectmappedmem #(parameter NUMLINES=512, parameter LINESIZE = 256, parameter WORDSIZE = `XLEN) (
// Pipeline stuff
input logic clk,
input logic reset,
input logic stall,
// If flush is high, invalidate the entire cache
input logic flush,
// Select which address to read (broken for efficiency's sake)
input logic [`XLEN-1:12] ReadUpperPAdr,
input logic [11:0] ReadLowerAdr,
// Load new data into the cache (from main memory)
input logic LoadEnable,
input logic [LINESIZE-1:0] LoadLine,
input logic [`XLEN-1:0] LoadPAdr,
// Write data to the cache (like from a store instruction)
input logic WriteEnable,
input logic [WORDSIZE-1:0] WriteWord,
input logic [`XLEN-1:0] WritePAdr,
input logic [1:0] WriteSize, // Specify size of the write (non-written bits should be preserved)
// Output the word, as well as if it is valid
output logic [WORDSIZE-1:0] DataWord,
output logic DataValid
);
// Various compile-time constants
localparam integer WORDWIDTH = $clog2(WORDSIZE/8);
localparam integer OFFSETWIDTH = $clog2(LINESIZE/WORDSIZE);
localparam integer SETWIDTH = $clog2(NUMLINES);
localparam integer TAGWIDTH = `XLEN - OFFSETWIDTH - SETWIDTH - WORDWIDTH;
localparam integer OFFSETBEGIN = WORDWIDTH;
localparam integer OFFSETEND = OFFSETBEGIN+OFFSETWIDTH-1;
localparam integer SETBEGIN = OFFSETEND+1;
localparam integer SETEND = SETBEGIN + SETWIDTH - 1;
localparam integer TAGBEGIN = SETEND + 1;
localparam integer TAGEND = TAGBEGIN + TAGWIDTH - 1;
// Machinery to read from and write to the correct addresses in memory
logic [`XLEN-1:0] ReadPAdr;
logic [`XLEN-1:0] OldReadPAdr;
logic [OFFSETWIDTH-1:0] ReadOffset, LoadOffset;
logic [SETWIDTH-1:0] ReadSet, LoadSet;
logic [TAGWIDTH-1:0] ReadTag, LoadTag;
logic [LINESIZE-1:0] ReadLine;
logic [LINESIZE/WORDSIZE-1:0][WORDSIZE-1:0] ReadLineTransformed;
// Machinery to check if a given read is valid and is the desired value
logic [TAGWIDTH-1:0] DataTag;
logic [NUMLINES-1:0] ValidOut;
logic DataValidBit;
flopenr #(`XLEN) ReadPAdrFlop(clk, reset, ~stall, ReadPAdr, OldReadPAdr);
// Assign the read and write addresses in cache memory
always_comb begin
ReadOffset = OldReadPAdr[OFFSETEND:OFFSETBEGIN];
ReadPAdr = {ReadUpperPAdr, ReadLowerAdr};
ReadSet = ReadPAdr[SETEND:SETBEGIN];
ReadTag = OldReadPAdr[TAGEND:TAGBEGIN];
LoadOffset = LoadPAdr[OFFSETEND:OFFSETBEGIN];
LoadSet = LoadPAdr[SETEND:SETBEGIN];
LoadTag = LoadPAdr[TAGEND:TAGBEGIN];
end
// Depth is number of bits in one "word" of the memory, width is number of such words
Sram1Read1Write #(.DEPTH(LINESIZE), .WIDTH(NUMLINES)) cachemem (
.*,
.ReadAddr(ReadSet),
.ReadData(ReadLine),
.WriteAddr(LoadSet),
.WriteData(LoadLine),
.WriteEnable(LoadEnable)
);
Sram1Read1Write #(.DEPTH(TAGWIDTH), .WIDTH(NUMLINES)) cachetags (
.*,
.ReadAddr(ReadSet),
.ReadData(DataTag),
.WriteAddr(LoadSet),
.WriteData(LoadTag),
.WriteEnable(LoadEnable)
);
// Pick the right bits coming out the read line
assign DataWord = ReadLineTransformed[ReadOffset];
genvar i;
generate
for (i=0; i < LINESIZE/WORDSIZE; i++) begin:readline
2021-04-16 01:13:56 +00:00
assign ReadLineTransformed[i] = ReadLine[(i+1)*WORDSIZE-1:i*WORDSIZE];
end
endgenerate
// Correctly handle the valid bits
always_ff @(posedge clk, posedge reset) begin
if (reset || flush) begin
ValidOut <= {NUMLINES{1'b0}};
end else begin
if (LoadEnable) begin
ValidOut[LoadSet] <= 1;
end
end
DataValidBit <= ValidOut[ReadSet];
end
assign DataValid = DataValidBit && (DataTag == ReadTag);
endmodule