forked from Github_Repos/cvw
Works for misaligned instructions not on line boundaries
This commit is contained in:
parent
3b4f0141f4
commit
5f4feb0ff1
@ -45,7 +45,7 @@ module icache(
|
||||
// High if the icache is requesting a stall
|
||||
output logic ICacheStallF,
|
||||
// The raw (not decompressed) instruction that was requested
|
||||
// If the next instruction is compressed, the upper 16 bits may be anything
|
||||
// If this instruction is compressed, upper 16 bits may be the next 16 bits or may be zeros
|
||||
output logic [31:0] InstrRawD
|
||||
);
|
||||
|
||||
@ -125,23 +125,25 @@ module icachecontroller #(parameter LINESIZE = 256) (
|
||||
output logic InstrReadF
|
||||
);
|
||||
|
||||
// Happy path signals
|
||||
logic [31:0] AlignedInstrRawF, AlignedInstrRawD;
|
||||
logic FlushDLastCycleN;
|
||||
logic PCPMisalignedF;
|
||||
const logic [31:0] NOP = 32'h13;
|
||||
// Misaligned signals
|
||||
logic [`XLEN:0] MisalignedInstrRawF;
|
||||
logic MisalignedStall;
|
||||
// Cache fault signals
|
||||
logic FaultStall;
|
||||
|
||||
// Detect if the instruction is compressed
|
||||
assign CompressedF = AlignedInstrRawF[1:0] != 2'b11;
|
||||
|
||||
// Handle happy path (data in cache, reads aligned)
|
||||
always_comb begin
|
||||
assign ICacheMemReadLowerAdr = LowerPCF;
|
||||
assign ICacheMemReadUpperPAdr = UpperPCPF;
|
||||
end
|
||||
|
||||
generate
|
||||
if (`XLEN == 32) begin
|
||||
assign AlignedInstrRawF = LowerPCF[1] ? {16'b0, ICacheMemReadData[31:16]} : ICacheMemReadData;
|
||||
assign AlignedInstrRawF = LowerPCF[1] ? MisalignedInstrRawF : ICacheMemReadData;
|
||||
assign PCPMisalignedF = LowerPCF[1] && ~CompressedF;
|
||||
end else begin
|
||||
assign AlignedInstrRawF = LowerPCF[2]
|
||||
@ -160,54 +162,48 @@ module icachecontroller #(parameter LINESIZE = 256) (
|
||||
assign ICacheStallF = FaultStall | MisalignedStall;
|
||||
end
|
||||
|
||||
// Handle misaligned, noncompressed reads
|
||||
logic MisalignedState, NextMisalignedState;
|
||||
logic MisalignedStall;
|
||||
logic [15:0] MisalignedHalfInstrF;
|
||||
logic [`XLEN:0] MisalignedInstrRawF;
|
||||
|
||||
always_comb begin
|
||||
assign MisalignedInstrRawF = {16'b0, ICacheMemReadData[63:48]};
|
||||
end
|
||||
// Handle misaligned, noncompressed reads
|
||||
|
||||
logic MisalignedState, NextMisalignedState;
|
||||
logic [15:0] MisalignedHalfInstrF;
|
||||
logic [15:0] UpperHalfWord;
|
||||
|
||||
flopenr #(16) MisalignedHalfInstrFlop(clk, reset, ~FaultStall & (PCPMisalignedF & MisalignedState), AlignedInstrRawF[15:0], MisalignedHalfInstrF);
|
||||
flopenr #(1) MisalignedStateFlop(clk, reset, ~FaultStall, NextMisalignedState, MisalignedState);
|
||||
|
||||
// When doing a misaligned read, swizzle the bits correctly
|
||||
generate
|
||||
if (`XLEN == 32) begin
|
||||
assign UpperHalfWord = ICacheMemReadData[31:16];
|
||||
end else begin
|
||||
assign UpperHalfWord = ICacheMemReadData[63:48];
|
||||
end
|
||||
endgenerate
|
||||
always_comb begin
|
||||
if (MisalignedState) begin
|
||||
assign MisalignedInstrRawF = {16'b0, UpperHalfWord};
|
||||
end else begin
|
||||
assign MisalignedInstrRawF = {ICacheMemReadData[15:0], MisalignedHalfInstrF};
|
||||
end
|
||||
end
|
||||
|
||||
// Manage internal state and stall when necessary
|
||||
always_comb begin
|
||||
assign MisalignedStall = PCPMisalignedF & MisalignedState;
|
||||
assign NextMisalignedState = ~PCPMisalignedF | ~MisalignedState;
|
||||
end
|
||||
|
||||
// Pick the correct address to read
|
||||
always_comb begin
|
||||
if (~PCPMisalignedF) begin
|
||||
assign ICacheMemReadUpperPAdr = UpperPCPF;
|
||||
generate
|
||||
if (`XLEN == 32)
|
||||
assign ICacheMemReadLowerAdr = {LowerPCF[31:2], 2'b00};
|
||||
else
|
||||
assign ICacheMemReadLowerAdr = {LowerPCF[31:3], 2'b000};
|
||||
endgenerate
|
||||
generate
|
||||
if (`XLEN == 32) begin
|
||||
assign ICacheMemReadLowerAdr = {LowerPCF[11:2] + (PCPMisalignedF & ~MisalignedState), 2'b00};
|
||||
end else begin
|
||||
if (MisalignedState) begin
|
||||
assign ICacheMemReadUpperPAdr = UpperPCPF;
|
||||
generate
|
||||
if (`XLEN == 32)
|
||||
assign ICacheMemReadLowerAdr = {LowerPCF[31:2]+1, 2'b00};
|
||||
else
|
||||
assign ICacheMemReadLowerAdr = {LowerPCF[31:3]+1, 2'b000};
|
||||
endgenerate
|
||||
end else begin
|
||||
assign ICacheMemReadUpperPAdr = UpperPCPF;
|
||||
generate
|
||||
if (`XLEN == 32)
|
||||
assign ICacheMemReadLowerAdr = {LowerPCF[31:2], 2'b00};
|
||||
else
|
||||
assign ICacheMemReadLowerAdr = {LowerPCF[31:3], 2'b000};
|
||||
endgenerate
|
||||
end
|
||||
assign ICacheMemReadLowerAdr = {LowerPCF[11:3] + (PCPMisalignedF & ~MisalignedState), 3'b00};
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
assign ICacheMemReadUpperPAdr = UpperPCPF;
|
||||
|
||||
|
||||
// Handle cache faults
|
||||
|
||||
@ -216,7 +212,6 @@ module icachecontroller #(parameter LINESIZE = 256) (
|
||||
localparam integer OFFSETWIDTH = $clog2(LINESIZE/8);
|
||||
|
||||
logic FetchState, EndFetchState, BeginFetchState;
|
||||
logic FaultStall;
|
||||
logic [LOGWPL:0] FetchWordNum, NextFetchWordNum;
|
||||
logic [`XLEN-1:0] LineAlignedPCPF;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user