mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
Broken icache. Design is done. Time to debug.
This commit is contained in:
parent
59b340dac9
commit
649589ee2c
@ -26,7 +26,6 @@ add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/CSR
|
||||
add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/RetM
|
||||
add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/TrapM
|
||||
add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/LoadStallD
|
||||
add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/InstrStall
|
||||
add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/DataStall
|
||||
add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/MulDivStallD
|
||||
add wave -noupdate -expand -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/hzu/FlushF
|
||||
@ -39,11 +38,6 @@ add wave -noupdate -expand -group HDU -expand -group Stall -color Orange /testbe
|
||||
add wave -noupdate -expand -group HDU -expand -group Stall -color Orange /testbench/dut/hart/StallE
|
||||
add wave -noupdate -expand -group HDU -expand -group Stall -color Orange /testbench/dut/hart/StallM
|
||||
add wave -noupdate -expand -group HDU -expand -group Stall -color Orange /testbench/dut/hart/StallW
|
||||
add wave -noupdate /testbench/dut/hart/hzu/StallFCause_Q
|
||||
add wave -noupdate /testbench/dut/hart/hzu/StallDCause_Q
|
||||
add wave -noupdate /testbench/dut/hart/hzu/StallECause_Q
|
||||
add wave -noupdate /testbench/dut/hart/hzu/StallMCause_Q
|
||||
add wave -noupdate /testbench/dut/hart/hzu/StallWCause_Q
|
||||
add wave -noupdate -group Bpred -expand -group direction -divider Update
|
||||
add wave -noupdate -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/UpdatePC
|
||||
add wave -noupdate -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/UpdateEN
|
||||
@ -80,36 +74,36 @@ add wave -noupdate -group {Decode Stage} /testbench/dut/hart/ieu/c/RegWriteD
|
||||
add wave -noupdate -group {Decode Stage} /testbench/dut/hart/ieu/dp/RdD
|
||||
add wave -noupdate -group {Decode Stage} /testbench/dut/hart/ieu/dp/Rs1D
|
||||
add wave -noupdate -group {Decode Stage} /testbench/dut/hart/ieu/dp/Rs2D
|
||||
add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/rf
|
||||
add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/a1
|
||||
add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/a2
|
||||
add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/a3
|
||||
add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/rd1
|
||||
add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/rd2
|
||||
add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/we3
|
||||
add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/wd3
|
||||
add wave -noupdate -expand -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ALUResultW
|
||||
add wave -noupdate -expand -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ReadDataW
|
||||
add wave -noupdate -expand -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/CSRReadValW
|
||||
add wave -noupdate -expand -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ResultSrcW
|
||||
add wave -noupdate -expand -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ResultW
|
||||
add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/a
|
||||
add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/b
|
||||
add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/alucontrol
|
||||
add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/result
|
||||
add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/flags
|
||||
add wave -noupdate -expand -group alu -divider internals
|
||||
add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/overflow
|
||||
add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/carry
|
||||
add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/zero
|
||||
add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/neg
|
||||
add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/lt
|
||||
add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/ltu
|
||||
add wave -noupdate -group RegFile /testbench/dut/hart/ieu/dp/regf/rf
|
||||
add wave -noupdate -group RegFile /testbench/dut/hart/ieu/dp/regf/a1
|
||||
add wave -noupdate -group RegFile /testbench/dut/hart/ieu/dp/regf/a2
|
||||
add wave -noupdate -group RegFile /testbench/dut/hart/ieu/dp/regf/a3
|
||||
add wave -noupdate -group RegFile /testbench/dut/hart/ieu/dp/regf/rd1
|
||||
add wave -noupdate -group RegFile /testbench/dut/hart/ieu/dp/regf/rd2
|
||||
add wave -noupdate -group RegFile /testbench/dut/hart/ieu/dp/regf/we3
|
||||
add wave -noupdate -group RegFile /testbench/dut/hart/ieu/dp/regf/wd3
|
||||
add wave -noupdate -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ALUResultW
|
||||
add wave -noupdate -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ReadDataW
|
||||
add wave -noupdate -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/CSRReadValW
|
||||
add wave -noupdate -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ResultSrcW
|
||||
add wave -noupdate -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ResultW
|
||||
add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/a
|
||||
add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/b
|
||||
add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/alucontrol
|
||||
add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/result
|
||||
add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/flags
|
||||
add wave -noupdate -group alu -divider internals
|
||||
add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/overflow
|
||||
add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/carry
|
||||
add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/zero
|
||||
add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/neg
|
||||
add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/lt
|
||||
add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/ltu
|
||||
add wave -noupdate /testbench/InstrFName
|
||||
add wave -noupdate -expand -group dcache /testbench/dut/hart/MemAdrM
|
||||
add wave -noupdate -expand -group dcache /testbench/dut/hart/MemPAdrM
|
||||
add wave -noupdate -expand -group dcache /testbench/dut/hart/WriteDataM
|
||||
add wave -noupdate -expand -group dcache /testbench/dut/hart/dmem/MemRWM
|
||||
add wave -noupdate -group dcache /testbench/dut/hart/MemAdrM
|
||||
add wave -noupdate -group dcache /testbench/dut/hart/MemPAdrM
|
||||
add wave -noupdate -group dcache /testbench/dut/hart/WriteDataM
|
||||
add wave -noupdate -group dcache /testbench/dut/hart/dmem/MemRWM
|
||||
add wave -noupdate -group Forward /testbench/dut/hart/ieu/fw/Rs1D
|
||||
add wave -noupdate -group Forward /testbench/dut/hart/ieu/fw/Rs2D
|
||||
add wave -noupdate -group Forward /testbench/dut/hart/ieu/fw/Rs1E
|
||||
@ -148,32 +142,64 @@ add wave -noupdate -group {function radix debug} /testbench/functionRadix/functi
|
||||
add wave -noupdate -group {function radix debug} /testbench/functionRadix/function_radix/FunctionAddr
|
||||
add wave -noupdate -group {function radix debug} /testbench/functionRadix/function_radix/ProgramAddrIndex
|
||||
add wave -noupdate -group {function radix debug} /testbench/functionRadix/function_radix/FunctionName
|
||||
add wave -noupdate -expand -group muldiv /testbench/dut/hart/mdu/InstrD
|
||||
add wave -noupdate -expand -group muldiv /testbench/dut/hart/mdu/SrcAE
|
||||
add wave -noupdate -expand -group muldiv /testbench/dut/hart/mdu/SrcBE
|
||||
add wave -noupdate -expand -group muldiv /testbench/dut/hart/mdu/Funct3E
|
||||
add wave -noupdate -expand -group muldiv /testbench/dut/hart/mdu/MulDivE
|
||||
add wave -noupdate -expand -group muldiv /testbench/dut/hart/mdu/W64E
|
||||
add wave -noupdate -expand -group muldiv /testbench/dut/hart/mdu/StallM
|
||||
add wave -noupdate -expand -group muldiv /testbench/dut/hart/mdu/StallW
|
||||
add wave -noupdate -expand -group muldiv /testbench/dut/hart/mdu/FlushM
|
||||
add wave -noupdate -expand -group muldiv /testbench/dut/hart/mdu/FlushW
|
||||
add wave -noupdate -expand -group muldiv /testbench/dut/hart/mdu/MulDivResultW
|
||||
add wave -noupdate -expand -group muldiv /testbench/dut/hart/mdu/genblk1/div/start
|
||||
add wave -noupdate -expand -group muldiv /testbench/dut/hart/mdu/DivDoneE
|
||||
add wave -noupdate -expand -group muldiv /testbench/dut/hart/mdu/DivBusyE
|
||||
add wave -noupdate /testbench/dut/hart/mdu/genblk1/gclk
|
||||
add wave -noupdate -expand -group divider /testbench/dut/hart/mdu/genblk1/div/fsm1/CURRENT_STATE
|
||||
add wave -noupdate -expand -group divider /testbench/dut/hart/mdu/genblk1/div/N
|
||||
add wave -noupdate -expand -group divider /testbench/dut/hart/mdu/genblk1/div/D
|
||||
add wave -noupdate -expand -group divider /testbench/dut/hart/mdu/genblk1/div/Q
|
||||
add wave -noupdate -expand -group divider /testbench/dut/hart/mdu/genblk1/div/rem0
|
||||
add wave -noupdate /testbench/dut/hart/MulDivResultW
|
||||
add wave -noupdate /testbench/dut/hart/mdu/genblk1/PrelimResultE
|
||||
add wave -noupdate /testbench/dut/hart/mdu/Funct3E
|
||||
add wave -noupdate /testbench/dut/hart/mdu/genblk1/QuotE
|
||||
add wave -noupdate -group muldiv /testbench/dut/hart/mdu/InstrD
|
||||
add wave -noupdate -group muldiv /testbench/dut/hart/mdu/SrcAE
|
||||
add wave -noupdate -group muldiv /testbench/dut/hart/mdu/SrcBE
|
||||
add wave -noupdate -group muldiv /testbench/dut/hart/mdu/Funct3E
|
||||
add wave -noupdate -group muldiv /testbench/dut/hart/mdu/MulDivE
|
||||
add wave -noupdate -group muldiv /testbench/dut/hart/mdu/W64E
|
||||
add wave -noupdate -group muldiv /testbench/dut/hart/mdu/StallM
|
||||
add wave -noupdate -group muldiv /testbench/dut/hart/mdu/StallW
|
||||
add wave -noupdate -group muldiv /testbench/dut/hart/mdu/FlushM
|
||||
add wave -noupdate -group muldiv /testbench/dut/hart/mdu/FlushW
|
||||
add wave -noupdate -group muldiv /testbench/dut/hart/mdu/MulDivResultW
|
||||
add wave -noupdate -group muldiv /testbench/dut/hart/mdu/genblk1/div/start
|
||||
add wave -noupdate -group muldiv /testbench/dut/hart/mdu/DivDoneE
|
||||
add wave -noupdate -group muldiv /testbench/dut/hart/mdu/DivBusyE
|
||||
add wave -noupdate -group divider /testbench/dut/hart/mdu/genblk1/div/fsm1/CURRENT_STATE
|
||||
add wave -noupdate -group divider /testbench/dut/hart/mdu/genblk1/div/N
|
||||
add wave -noupdate -group divider /testbench/dut/hart/mdu/genblk1/div/D
|
||||
add wave -noupdate -group divider /testbench/dut/hart/mdu/genblk1/div/Q
|
||||
add wave -noupdate -group divider /testbench/dut/hart/mdu/genblk1/div/rem0
|
||||
add wave -noupdate -expand -group parameters /testbench/dut/hart/ifu/icache/controller/AHBByteLength
|
||||
add wave -noupdate -expand -group parameters /testbench/dut/hart/ifu/icache/controller/AHBOFFETWIDTH
|
||||
add wave -noupdate -expand -group parameters /testbench/dut/hart/ifu/icache/controller/BlockByteLength
|
||||
add wave -noupdate -expand -group parameters /testbench/dut/hart/ifu/icache/controller/OFFSETWIDTH
|
||||
add wave -noupdate -expand -group parameters /testbench/dut/hart/ifu/icache/controller/WORDSPERLINE
|
||||
add wave -noupdate -expand -group parameters /testbench/dut/hart/ifu/icache/controller/LOGWPL
|
||||
add wave -noupdate -expand -group parameters /testbench/dut/hart/ifu/icache/controller/LINESIZE
|
||||
add wave -noupdate /testbench/dut/hart/ifu/icache/controller/CurrState
|
||||
add wave -noupdate -expand -group memory /testbench/dut/hart/ifu/icache/controller/InstrPAdrF
|
||||
add wave -noupdate -expand -group memory /testbench/dut/hart/ifu/icache/controller/FetchCountFlag
|
||||
add wave -noupdate -expand -group memory /testbench/dut/hart/ifu/icache/controller/FetchCount
|
||||
add wave -noupdate -expand -group memory /testbench/dut/hart/ifu/icache/controller/InstrReadF
|
||||
add wave -noupdate -expand -group memory /testbench/dut/hart/ifu/icache/controller/InstrAckF
|
||||
add wave -noupdate -expand -group memory /testbench/dut/hart/ifu/icache/controller/ICacheMemWriteEnable
|
||||
add wave -noupdate -expand -group memory /testbench/dut/hart/ifu/icache/controller/ICacheMemWriteData
|
||||
add wave -noupdate -expand -group memory /testbench/dut/hart/ifu/icache/controller/ICacheMemWritePAdr
|
||||
add wave -noupdate /testbench/dut/hart/ifu/icache/controller/PCPF
|
||||
add wave -noupdate /testbench/dut/hart/ifu/icache/controller/PCPreFinalF
|
||||
add wave -noupdate -expand -group {instr to cpu} /testbench/dut/hart/ifu/icache/controller/FinalInstrRawF
|
||||
add wave -noupdate -expand -group {instr to cpu} /testbench/dut/hart/ifu/icache/controller/AlignedInstrRawD
|
||||
add wave -noupdate -expand -group {instr to cpu} /testbench/dut/hart/ifu/icache/controller/InstrRawD
|
||||
add wave -noupdate /testbench/dut/hart/ifu/icache/controller/hit
|
||||
add wave -noupdate /testbench/dut/hart/ifu/icache/controller/spill
|
||||
add wave -noupdate /testbench/dut/hart/ifu/icache/controller/spillSave
|
||||
add wave -noupdate /testbench/dut/hart/ifu/icache/controller/UnalignedSelect
|
||||
add wave -noupdate /testbench/dut/hart/ifu/icache/controller/PCMux
|
||||
add wave -noupdate /testbench/dut/hart/ifu/icache/controller/PCPFinalF
|
||||
add wave -noupdate /testbench/dut/hart/ifu/icache/cachemem/DataValidBit
|
||||
add wave -noupdate /testbench/dut/hart/ifu/icache/cachemem/DataValid
|
||||
add wave -noupdate /testbench/dut/hart/ifu/icache/cachemem/ReadTag
|
||||
add wave -noupdate /testbench/dut/hart/ifu/icache/cachemem/DataTag
|
||||
add wave -noupdate /testbench/dut/hart/ifu/icache/cachemem/WriteEnable
|
||||
add wave -noupdate /testbench/dut/hart/ifu/icache/cachemem/WriteLine
|
||||
add wave -noupdate /testbench/dut/hart/ifu/icache/cachemem/WritePAdr
|
||||
add wave -noupdate /testbench/dut/hart/ifu/icache/cachemem/WriteSet
|
||||
add wave -noupdate /testbench/dut/hart/ifu/icache/cachemem/WriteTag
|
||||
add wave -noupdate /testbench/dut/hart/ifu/icache/cachemem/cachetags/StoredData
|
||||
TreeUpdate [SetDefaultTree]
|
||||
WaveRestoreCursors {{Cursor 2} {128433 ns} 0}
|
||||
WaveRestoreCursors {{Cursor 2} {237 ns} 0}
|
||||
quietly wave cursor active 1
|
||||
configure wave -namecolwidth 250
|
||||
configure wave -valuecolwidth 229
|
||||
@ -189,4 +215,4 @@ configure wave -griddelta 40
|
||||
configure wave -timeline 0
|
||||
configure wave -timelineunits ns
|
||||
update
|
||||
WaveRestoreZoom {128007 ns} {128663 ns}
|
||||
WaveRestoreZoom {96 ns} {400 ns}
|
||||
|
@ -129,57 +129,141 @@ 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;
|
||||
logic [`XLEN-1:0] PCPF;
|
||||
// Misaligned signals
|
||||
logic [`XLEN:0] MisalignedInstrRawF;
|
||||
logic MisalignedStall;
|
||||
// Cache fault signals
|
||||
logic FaultStall;
|
||||
// FSM states
|
||||
localparam STATE_READY = 0;
|
||||
localparam STATE_HIT_SPILL = 1; // spill, block 0 hit
|
||||
localparam STATE_HIT_SPILL_MISS_FETCH_WDV = 2; // block 1 miss, issue read to AHB and wait data.
|
||||
localparam STATE_HIT_SPILL_MISS_FETCH_DONE = 3; // write data into SRAM/LUT
|
||||
localparam STATE_HIT_SPILL_MERGE = 4; // Read block 0 of CPU access, should be able to optimize into STATE_HIT_SPILL.
|
||||
|
||||
localparam STATE_MISS_FETCH_WDV = 5; // aligned miss, issue read to AHB and wait for data.
|
||||
localparam STATE_MISS_FETCH_DONE = 6; // write data into SRAM/LUT
|
||||
localparam STATE_MISS_READ = 7; // read block 1 from SRAM/LUT
|
||||
|
||||
localparam STATE_MISS_SPILL_FETCH_WDV = 8; // spill, miss on block 0, issue read to AHB and wait
|
||||
localparam STATE_MISS_SPILL_FETCH_DONE = 9; // write data into SRAM/LUT
|
||||
localparam STATE_MISS_SPILL_READ1 = 10; // read block 0 from SRAM/LUT
|
||||
localparam STATE_MISS_SPILL_2 = 11; // return to ready if hit or do second block update.
|
||||
localparam STATE_MISS_SPILL_MISS_FETCH_WDV = 12; // miss on block 1, issue read to AHB and wait
|
||||
localparam STATE_MISS_SPILL_MISS_FETCH_DONE = 13; // write data to SRAM/LUT
|
||||
localparam STATE_MISS_SPILL_MERGE = 14; // read block 0 of CPU access,
|
||||
|
||||
localparam STATE_INVALIDATE = 15; // *** not sure if invalidate or evict? invalidate by cache block or address?
|
||||
|
||||
localparam AHBByteLength = `XLEN / 8;
|
||||
localparam AHBOFFETWIDTH = $clog2(AHBByteLength);
|
||||
|
||||
|
||||
localparam BlockByteLength = LINESIZE / 8;
|
||||
localparam OFFSETWIDTH = $clog2(BlockByteLength);
|
||||
|
||||
localparam WORDSPERLINE = LINESIZE/`XLEN;
|
||||
localparam LOGWPL = $clog2(WORDSPERLINE);
|
||||
|
||||
logic [3:0] CurrState, NextState;
|
||||
logic hit, spill;
|
||||
logic SavePC;
|
||||
logic [1:0] PCMux;
|
||||
logic CntReset;
|
||||
logic PreCntEn, CntEn;
|
||||
logic spillSave;
|
||||
logic UnalignedSelect;
|
||||
logic FetchCountFlag;
|
||||
localparam FetchCountThreshold = WORDSPERLINE - 1;
|
||||
|
||||
logic [LOGWPL:0] FetchCount, NextFetchCount;
|
||||
|
||||
logic [`XLEN-1:0] PCPreFinalF, PCPFinalF, PCSpillF;
|
||||
logic [`XLEN-1:OFFSETWIDTH] PCPTrunkF;
|
||||
|
||||
|
||||
logic [31:0] FinalInstrRawF;
|
||||
|
||||
logic [15:0] SpillDataBlock0;
|
||||
|
||||
|
||||
|
||||
// Happy path signals
|
||||
logic [31:0] AlignedInstrRawD;
|
||||
|
||||
//logic [31:0] AlignedInstrRawF, AlignedInstrRawD;
|
||||
//logic FlushDLastCycleN;
|
||||
//logic PCPMisalignedF;
|
||||
const logic [31:0] NOP = 32'h13;
|
||||
logic [`XLEN-1:0] PCPF;
|
||||
|
||||
logic reset_q;
|
||||
|
||||
// Misaligned signals
|
||||
//logic [`XLEN:0] MisalignedInstrRawF;
|
||||
//logic MisalignedStall;
|
||||
// Cache fault signals
|
||||
//logic FaultStall;
|
||||
|
||||
|
||||
flopenr #(`XLEN) PCPFFlop(clk, reset, SavePC, {UpperPCNextPF, LowerPCNextF}, PCPF);
|
||||
// on spill we want to get the first 2 bytes of the next cache block.
|
||||
// the spill only occurs if the PCPF mod BlockByteLength == -2. Therefore we can
|
||||
// simply add 2 to land on the next cache block.
|
||||
assign PCSpillF = PCPF + 2'b10;
|
||||
|
||||
// now we have to select between these three PCs
|
||||
assign PCPreFinalF = PCMux[0] ? PCPF : {UpperPCNextPF, LowerPCNextF};
|
||||
assign PCPFinalF = PCMux[1] ? PCSpillF : PCPreFinalF;
|
||||
|
||||
|
||||
|
||||
// truncate the offset from PCPF for memory address generation
|
||||
assign PCPTrunkF = PCPFinalF[`XLEN-1:OFFSETWIDTH];
|
||||
|
||||
// Detect if the instruction is compressed
|
||||
assign CompressedF = AlignedInstrRawF[1:0] != 2'b11;
|
||||
assign CompressedF = FinalInstrRawF[1:0] != 2'b11;
|
||||
|
||||
|
||||
// Handle happy path (data in cache, reads aligned)
|
||||
/* -----\/----- EXCLUDED -----\/-----
|
||||
|
||||
generate
|
||||
if (`XLEN == 32) begin
|
||||
assign AlignedInstrRawF = PCPF[1] ? MisalignedInstrRawF : ICacheMemReadData;
|
||||
assign PCPMisalignedF = PCPF[1] && ~CompressedF;
|
||||
//assign PCPMisalignedF = PCPF[1] && ~CompressedF;
|
||||
end else begin
|
||||
assign AlignedInstrRawF = PCPF[2]
|
||||
? (PCPF[1] ? MisalignedInstrRawF : ICacheMemReadData[63:32])
|
||||
: (PCPF[1] ? ICacheMemReadData[47:16] : ICacheMemReadData[31:0]);
|
||||
assign PCPMisalignedF = PCPF[2] && PCPF[1] && ~CompressedF;
|
||||
//assign PCPMisalignedF = PCPF[2] && PCPF[1] && ~CompressedF;
|
||||
end
|
||||
endgenerate
|
||||
-----/\----- EXCLUDED -----/\----- */
|
||||
|
||||
flopenr #(32) AlignedInstrRawDFlop(clk, reset, ~StallD, AlignedInstrRawF, AlignedInstrRawD);
|
||||
flopr #(1) FlushDLastCycleFlop(clk, reset, ~FlushD & (FlushDLastCycleN | ~StallF), FlushDLastCycleN);
|
||||
flopenr #(`XLEN) PCPFFlop(clk, reset, ~StallF, {UpperPCNextPF, LowerPCNextF}, PCPF);
|
||||
mux2 #(32) InstrRawDMux(AlignedInstrRawD, NOP, ~FlushDLastCycleN, InstrRawD);
|
||||
//flopenr #(32) AlignedInstrRawDFlop(clk, reset, ~StallD, AlignedInstrRawF, AlignedInstrRawD);
|
||||
//flopr #(1) FlushDLastCycleFlop(clk, reset, ~FlushD & (FlushDLastCycleN | ~StallF), FlushDLastCycleN);
|
||||
|
||||
//mux2 #(32) InstrRawDMux(AlignedInstrRawD, NOP, ~FlushDLastCycleN, InstrRawD);
|
||||
|
||||
// Stall for faults or misaligned reads
|
||||
/* -----\/----- EXCLUDED -----\/-----
|
||||
always_comb begin
|
||||
assign ICacheStallF = FaultStall | MisalignedStall;
|
||||
end
|
||||
-----/\----- EXCLUDED -----/\----- */
|
||||
|
||||
|
||||
// Handle misaligned, noncompressed reads
|
||||
|
||||
/* -----\/----- EXCLUDED -----\/-----
|
||||
logic MisalignedState, NextMisalignedState;
|
||||
logic [15:0] MisalignedHalfInstrF;
|
||||
logic [15:0] UpperHalfWord;
|
||||
-----/\----- EXCLUDED -----/\----- */
|
||||
|
||||
/* -----\/----- EXCLUDED -----\/-----
|
||||
flopenr #(16) MisalignedHalfInstrFlop(clk, reset, ~FaultStall & (PCPMisalignedF & MisalignedState), AlignedInstrRawF[15:0], MisalignedHalfInstrF);
|
||||
flopenr #(1) MisalignedStateFlop(clk, reset, ~FaultStall, NextMisalignedState, MisalignedState);
|
||||
-----/\----- EXCLUDED -----/\----- */
|
||||
|
||||
// When doing a misaligned read, swizzle the bits correctly
|
||||
/* -----\/----- EXCLUDED -----\/-----
|
||||
generate
|
||||
if (`XLEN == 32) begin
|
||||
assign UpperHalfWord = ICacheMemReadData[31:16];
|
||||
@ -194,14 +278,18 @@ module icachecontroller #(parameter LINESIZE = 256) (
|
||||
assign MisalignedInstrRawF = {ICacheMemReadData[15:0], MisalignedHalfInstrF};
|
||||
end
|
||||
end
|
||||
-----/\----- EXCLUDED -----/\----- */
|
||||
|
||||
// Manage internal state and stall when necessary
|
||||
/* -----\/----- EXCLUDED -----\/-----
|
||||
always_comb begin
|
||||
assign MisalignedStall = PCPMisalignedF & MisalignedState;
|
||||
assign NextMisalignedState = ~PCPMisalignedF | ~MisalignedState;
|
||||
end
|
||||
-----/\----- EXCLUDED -----/\----- */
|
||||
|
||||
// Pick the correct address to read
|
||||
/* -----\/----- EXCLUDED -----\/-----
|
||||
generate
|
||||
if (`XLEN == 32) begin
|
||||
assign ICacheMemReadLowerAdr = {LowerPCNextF[11:2] + (PCPMisalignedF & ~MisalignedState), 2'b00};
|
||||
@ -209,16 +297,15 @@ module icachecontroller #(parameter LINESIZE = 256) (
|
||||
assign ICacheMemReadLowerAdr = {LowerPCNextF[11:3] + (PCPMisalignedF & ~MisalignedState), 3'b00};
|
||||
end
|
||||
endgenerate
|
||||
-----/\----- EXCLUDED -----/\----- */
|
||||
// TODO Handle reading instructions that cross page boundaries
|
||||
assign ICacheMemReadUpperPAdr = UpperPCNextPF;
|
||||
//assign ICacheMemReadUpperPAdr = UpperPCNextPF;
|
||||
|
||||
|
||||
// Handle cache faults
|
||||
|
||||
localparam integer WORDSPERLINE = LINESIZE/`XLEN;
|
||||
localparam integer LOGWPL = $clog2(WORDSPERLINE);
|
||||
localparam integer OFFSETWIDTH = $clog2(LINESIZE/8);
|
||||
|
||||
/* -----\/----- EXCLUDED -----\/-----
|
||||
logic FetchState, BeginFetchState;
|
||||
logic [LOGWPL:0] FetchWordNum, NextFetchWordNum;
|
||||
logic [`XLEN-1:0] LineAlignedPCPF;
|
||||
@ -226,12 +313,6 @@ module icachecontroller #(parameter LINESIZE = 256) (
|
||||
flopr #(1) FetchStateFlop(clk, reset, BeginFetchState | (FetchState & ~EndFetchState), FetchState);
|
||||
flopr #(LOGWPL+1) FetchWordNumFlop(clk, reset, NextFetchWordNum, FetchWordNum);
|
||||
|
||||
genvar i;
|
||||
generate
|
||||
for (i=0; i < WORDSPERLINE; i++) begin
|
||||
flopenr #(`XLEN) flop(clk, reset, FetchState & (i == FetchWordNum), InstrInF, ICacheMemWriteData[(i+1)*`XLEN-1:i*`XLEN]);
|
||||
end
|
||||
endgenerate
|
||||
|
||||
// Enter the fetch state when we hit a cache fault
|
||||
always_comb begin
|
||||
@ -242,10 +323,10 @@ module icachecontroller #(parameter LINESIZE = 256) (
|
||||
|
||||
// Machinery to request the correct addresses from main memory
|
||||
always_comb begin
|
||||
InstrReadF = FetchState & ~EndFetchState & ~ICacheMemWriteEnable;
|
||||
LineAlignedPCPF = {ICacheMemReadUpperPAdr, ICacheMemReadLowerAdr[11:OFFSETWIDTH], {OFFSETWIDTH{1'b0}}};
|
||||
InstrPAdrF = LineAlignedPCPF + FetchWordNum*(`XLEN/8);
|
||||
NextFetchWordNum = FetchState ? FetchWordNum+InstrAckF : {LOGWPL+1{1'b0}};
|
||||
InstrReadF = FetchState & ~EndFetchState & ~ICacheMemWriteEnable; // next stage logic
|
||||
LineAlignedPCPF = {ICacheMemReadUpperPAdr, ICacheMemReadLowerAdr[11:OFFSETWIDTH], {OFFSETWIDTH{1'b0}}}; // the fetch address for abh?
|
||||
InstrPAdrF = LineAlignedPCPF + FetchWordNum*(`XLEN/8); // ?
|
||||
NextFetchWordNum = FetchState ? FetchWordNum+InstrAckF : {LOGWPL+1{1'b0}}; // convert to enable
|
||||
end
|
||||
|
||||
// Write to cache memory when we have the line here
|
||||
@ -258,4 +339,255 @@ module icachecontroller #(parameter LINESIZE = 256) (
|
||||
always_comb begin
|
||||
FaultStall = FetchState | ~ICacheMemReadValid;
|
||||
end
|
||||
-----/\----- EXCLUDED -----/\----- */
|
||||
|
||||
// the FSM is always runing, do not stall.
|
||||
flopr #(4) stateReg(.clk(clk),
|
||||
.reset(reset),
|
||||
.d(NextState),
|
||||
.q(CurrState));
|
||||
|
||||
assign spill = PCPF[5:1] == 5'b1_1111 ? 1'b1 : 1'b0;
|
||||
assign hit = ICacheMemReadValid; // note ICacheMemReadValid is hit.
|
||||
assign FetchCountFlag = FetchCount == FetchCountThreshold;
|
||||
|
||||
// Next state logic
|
||||
always_comb begin
|
||||
UnalignedSelect = 1'b0;
|
||||
CntReset = 1'b0;
|
||||
PreCntEn = 1'b0;
|
||||
InstrReadF = 1'b0;
|
||||
ICacheMemWriteEnable = 1'b0;
|
||||
spillSave = 1'b0;
|
||||
PCMux = 2'b00;
|
||||
|
||||
case (CurrState)
|
||||
|
||||
STATE_READY: begin
|
||||
PCMux = 2'b00;
|
||||
if (hit & ~spill) begin
|
||||
NextState = STATE_READY;
|
||||
end else if (hit & spill) begin
|
||||
spillSave = 1'b1;
|
||||
NextState = STATE_HIT_SPILL;
|
||||
end else if (~hit & ~spill) begin
|
||||
CntReset = 1'b1;
|
||||
NextState = STATE_MISS_FETCH_WDV;
|
||||
end else if (~hit & spill) begin
|
||||
CntReset = 1'b1;
|
||||
NextState = STATE_MISS_SPILL_FETCH_WDV;
|
||||
end else begin
|
||||
NextState = STATE_READY;
|
||||
end
|
||||
end
|
||||
|
||||
// branch 1, hit spill and 2, miss spill hit
|
||||
STATE_HIT_SPILL: begin
|
||||
PCMux = 2'b10;
|
||||
UnalignedSelect = 1'b1;
|
||||
if (hit) begin
|
||||
NextState = STATE_READY;
|
||||
end else
|
||||
CntReset = 1'b1;
|
||||
NextState = STATE_HIT_SPILL_MISS_FETCH_WDV;
|
||||
end
|
||||
STATE_HIT_SPILL_MISS_FETCH_WDV: begin
|
||||
PCMux = 2'b10;
|
||||
InstrReadF = 1'b1;
|
||||
PreCntEn = 1'b1;
|
||||
if (FetchCountFlag & InstrAckF) begin
|
||||
NextState = STATE_HIT_SPILL_MISS_FETCH_DONE;
|
||||
end else begin
|
||||
NextState = STATE_HIT_SPILL_MISS_FETCH_WDV;
|
||||
end
|
||||
end
|
||||
STATE_HIT_SPILL_MISS_FETCH_DONE: begin
|
||||
PCMux = 2'b10;
|
||||
ICacheMemWriteEnable = 1'b1;
|
||||
NextState = STATE_HIT_SPILL_MERGE;
|
||||
end
|
||||
STATE_HIT_SPILL_MERGE: begin
|
||||
PCMux = 2'b10;
|
||||
UnalignedSelect = 1'b1;
|
||||
NextState = STATE_READY;
|
||||
end
|
||||
|
||||
// branch 3 miss no spill
|
||||
STATE_MISS_FETCH_WDV: begin
|
||||
PCMux = 2'b01;
|
||||
InstrReadF = 1'b1;
|
||||
PreCntEn = 1'b1;
|
||||
if (FetchCountFlag & InstrAckF) begin
|
||||
NextState = STATE_MISS_FETCH_DONE;
|
||||
end else begin
|
||||
NextState = STATE_MISS_FETCH_WDV;
|
||||
end
|
||||
end
|
||||
STATE_MISS_FETCH_DONE: begin
|
||||
PCMux = 2'b01;
|
||||
ICacheMemWriteEnable = 1'b1;
|
||||
NextState = STATE_MISS_READ;
|
||||
end
|
||||
STATE_MISS_READ: begin
|
||||
PCMux = 2'b01;
|
||||
NextState = STATE_READY;
|
||||
end
|
||||
|
||||
// branch 4 miss spill hit, and 5 miss spill miss
|
||||
STATE_MISS_SPILL_FETCH_WDV: begin
|
||||
PCMux = 2'b01;
|
||||
PreCntEn = 1'b1;
|
||||
InstrReadF = 1'b1;
|
||||
if (FetchCountFlag & InstrAckF) begin
|
||||
NextState = STATE_MISS_SPILL_FETCH_DONE;
|
||||
end else begin
|
||||
NextState = STATE_MISS_SPILL_FETCH_WDV;
|
||||
end
|
||||
end
|
||||
STATE_MISS_SPILL_FETCH_DONE: begin
|
||||
PCMux = 2'b01;
|
||||
ICacheMemWriteEnable = 1'b1;
|
||||
NextState = STATE_MISS_SPILL_READ1;
|
||||
end
|
||||
STATE_MISS_SPILL_READ1: begin // always be a hit as we just wrote that cache block.
|
||||
PCMux = 2'b10; // there is a 1 cycle delay after setting the address before the date arrives.
|
||||
spillSave = 1'b1; /// *** Could pipeline these to make it clearer in the fsm.
|
||||
NextState = STATE_MISS_SPILL_2;
|
||||
end
|
||||
STATE_MISS_SPILL_2: begin
|
||||
PCMux = 2'b10;
|
||||
UnalignedSelect = 1'b1;
|
||||
if (~hit) begin
|
||||
CntReset = 1'b1;
|
||||
NextState = STATE_MISS_SPILL_MISS_FETCH_WDV;
|
||||
end else begin
|
||||
NextState = STATE_READY;
|
||||
end
|
||||
end
|
||||
STATE_MISS_SPILL_MISS_FETCH_WDV: begin
|
||||
PCMux = 2'b10;
|
||||
PreCntEn = 1'b1;
|
||||
InstrReadF = 1'b1;
|
||||
if (FetchCountFlag & InstrAckF) begin
|
||||
NextState = STATE_MISS_SPILL_MISS_FETCH_DONE;
|
||||
end else begin
|
||||
NextState = STATE_MISS_SPILL_MISS_FETCH_WDV;
|
||||
end
|
||||
end
|
||||
STATE_MISS_SPILL_MISS_FETCH_DONE: begin
|
||||
PCMux = 2'b10;
|
||||
ICacheMemWriteEnable = 1'b1;
|
||||
NextState = STATE_MISS_SPILL_MERGE;
|
||||
end
|
||||
STATE_MISS_SPILL_MERGE: begin
|
||||
PCMux = 2'b10;
|
||||
UnalignedSelect = 1'b1;
|
||||
NextState = STATE_READY;
|
||||
end
|
||||
default: begin
|
||||
PCMux = 2'b01;
|
||||
NextState = STATE_READY;
|
||||
end
|
||||
// *** add in error handling and invalidate/evict
|
||||
endcase
|
||||
end
|
||||
|
||||
// fsm outputs
|
||||
// stall CPU any time we are not in the ready state. any other state means the
|
||||
// cache is either requesting data from the memory interface or handling a
|
||||
// spill over two cycles.
|
||||
assign ICacheStallF = (CurrState != STATE_READY) | reset_q ? 1'b1 : 1'b0;
|
||||
// save the PC anytime we are in the ready state. The saved value will be used as the PC may not be stable.
|
||||
assign SavePC = CurrState == STATE_READY ? 1'b1 : 1'b0;
|
||||
assign CntEn = PreCntEn & InstrAckF;
|
||||
|
||||
// to compute the fetch address we need to add the bit shifted
|
||||
// counter output to the address.
|
||||
|
||||
flopenr #(LOGWPL+1)
|
||||
FetchCountReg(.clk(clk),
|
||||
.reset(reset | CntReset),
|
||||
.en(CntEn),
|
||||
.d(NextFetchCount),
|
||||
.q(FetchCount));
|
||||
|
||||
assign NextFetchCount = FetchCount + 1'b1;
|
||||
|
||||
// This part is confusing.
|
||||
// we need to remove the offset bits (PCPTrunkF). Because the AHB interface is XLEN wide
|
||||
// we need to address on that number of bits so the PC is extended to the right by AHBByteLength with zeros.
|
||||
// fetch count is already aligned to AHBByteLength, but we need to extend back to the full address width with
|
||||
// more zeros after the addition. This will be the number of offset bits less the AHBByteLength.
|
||||
assign InstrPAdrF = {{PCPTrunkF, {{LOGWPL}{1'b0}}} + FetchCount, {{OFFSETWIDTH-LOGWPL}{1'b0}}};
|
||||
|
||||
|
||||
// store read data from memory interface before writing into SRAM.
|
||||
genvar i;
|
||||
generate
|
||||
for (i = 0; i < AHBByteLength; i++) begin
|
||||
flopenr #(`XLEN) flop(.clk(clk),
|
||||
.reset(reset),
|
||||
.en(InstrAckF & (i == FetchCount)),
|
||||
.d(InstrInF),
|
||||
.q(ICacheMemWriteData[(i+1)*`XLEN-1:i*`XLEN]));
|
||||
end
|
||||
endgenerate
|
||||
|
||||
// what address is used to write the SRAM?
|
||||
|
||||
|
||||
// spills require storing the first cache block so it can merged
|
||||
// with the second
|
||||
// can optimize size, for now just make it the size of the data
|
||||
// leaving the cache memory.
|
||||
flopenr #(16) SpillInstrReg(.clk(clk),
|
||||
.en(spillSave),
|
||||
.reset(reset),
|
||||
.d(ICacheMemReadData[15:0]),
|
||||
.q(SpillDataBlock0));
|
||||
|
||||
// use the not quite final PC to do the final selection.
|
||||
generate
|
||||
if( `XLEN == 32) begin
|
||||
logic [1:1] PCPreFinalF_q;
|
||||
flop #(1) PCFReg(.clk(clk),
|
||||
.d(PCPreFinalF[1]),
|
||||
.q(PCPreFinalF_q[1]));
|
||||
assign FinalInstrRawF = PCPreFinalF[1] ? {SpillDataBlock0, ICacheMemReadData[31:16]} : ICacheMemReadData;
|
||||
end else begin
|
||||
logic [2:1] PCPreFinalF_q;
|
||||
flop #(2) PCFReg(.clk(clk),
|
||||
.d(PCPreFinalF[2:1]),
|
||||
.q(PCPreFinalF_q[2:1]));
|
||||
mux4 #(32) AlignmentMux(.d0(ICacheMemReadData[31:0]),
|
||||
.d1(ICacheMemReadData[47:16]),
|
||||
.d2(ICacheMemReadData[63:32]),
|
||||
.d3({SpillDataBlock0, ICacheMemReadData[63:48]}),
|
||||
.s(PCPreFinalF[2:1]),
|
||||
.y(FinalInstrRawF));
|
||||
end
|
||||
endgenerate
|
||||
|
||||
// There is a frustrating issue on the first access.
|
||||
// The cache will not contain any valid data but will contain x's on
|
||||
// reset. This makes FinalInstrRawF invalid. On the first cycle out of
|
||||
// reset this register will pickup this x and it will propagate throughout
|
||||
// the cpu causing simulation failure, most likely a trap for invalid instruction.
|
||||
// Reset must be held 1 cycle longer to prevent this issue. additionally the
|
||||
// reset should be to a NOP rather than 0.
|
||||
|
||||
// register reset
|
||||
flop #(1) resetReg (.clk(clk),
|
||||
.d(reset),
|
||||
.q(reset_q));
|
||||
|
||||
flopenl #(32) AlignedInstrRawDFlop(clk, reset | reset_q, ~StallD, FinalInstrRawF, NOP, AlignedInstrRawD);
|
||||
mux2 #(32) InstrRawDMux(AlignedInstrRawD, NOP, FlushD, InstrRawD);
|
||||
|
||||
assign {ICacheMemReadUpperPAdr, ICacheMemReadLowerAdr} = PCPFinalF;
|
||||
|
||||
assign ICacheMemWritePAdr = PCPFinalF;
|
||||
|
||||
|
||||
|
||||
endmodule
|
||||
|
@ -77,6 +77,8 @@ module ifu (
|
||||
logic [31:0] nop = 32'h00000013; // instruction for NOP
|
||||
// *** send this to the trap unit
|
||||
logic ITLBPageFaultF;
|
||||
logic reset_q; // *** look at this later.
|
||||
|
||||
|
||||
tlb #(3) itlb(.TLBAccess(1'b1), .VirtualAddress(PCF),
|
||||
.PageTableEntryWrite(PageTableEntryF), .PageTypeWrite(PageTypeF),
|
||||
@ -87,7 +89,7 @@ module ifu (
|
||||
|
||||
// branch predictor signals
|
||||
logic SelBPPredF;
|
||||
logic [`XLEN-1:0] BPPredPCF, PCCorrectE, PCNext0F, PCNext1F;
|
||||
logic [`XLEN-1:0] BPPredPCF, PCCorrectE, PCNext0F, PCNext1F, PCNext2F;
|
||||
logic [3:0] InstrClassD, InstrClassE;
|
||||
|
||||
|
||||
@ -98,10 +100,10 @@ module ifu (
|
||||
|
||||
// jarred 2021-03-14 Add instrution cache block to remove rd2
|
||||
assign PCNextPF = PCNextF; // Temporary workaround until iTLB is live
|
||||
icache ic(
|
||||
icache icache(
|
||||
.*,
|
||||
.UpperPCPF(PCPF[`XLEN-1:12]),
|
||||
.LowerPCF(PCF[11:0])
|
||||
.UpperPCNextPF(PCNextPF[`XLEN-1:12]),
|
||||
.LowerPCNextF(PCNextPF[11:0])
|
||||
);
|
||||
|
||||
assign PrivilegedChangePCM = RetM | TrapM;
|
||||
@ -120,7 +122,17 @@ module ifu (
|
||||
mux2 #(`XLEN) pcmux2(.d0(PCNext1F),
|
||||
.d1(PrivilegedNextPCM),
|
||||
.s(PrivilegedChangePCM),
|
||||
.y(PCNext2F));
|
||||
|
||||
mux2 #(`XLEN) pcmux3(.d0(PCNext2F),
|
||||
.d1(`RESET_VECTOR),
|
||||
.s(reset_q),
|
||||
.y(UnalignedPCNextF));
|
||||
|
||||
flop #(1) resetReg (.clk(clk),
|
||||
.d(reset),
|
||||
.q(reset_q));
|
||||
|
||||
|
||||
assign PCNextF = {UnalignedPCNextF[`XLEN-1:1], 1'b0}; // hart-SPEC p. 21 about 16-bit alignment
|
||||
flopenl #(`XLEN) pcreg(clk, reset, ~StallF & ~ICacheStallF, PCNextF, `RESET_VECTOR, PCF);
|
||||
|
@ -447,7 +447,7 @@ module testbench();
|
||||
|
||||
// Track names of instructions
|
||||
instrTrackerTB it(clk, reset, dut.hart.ieu.dp.FlushE,
|
||||
dut.hart.ifu.ic.controller.AlignedInstrRawF,
|
||||
dut.hart.ifu.icache.controller.FinalInstrRawF,
|
||||
dut.hart.ifu.InstrD, dut.hart.ifu.InstrE,
|
||||
dut.hart.ifu.InstrM, dut.hart.ifu.InstrW,
|
||||
InstrFName, InstrDName, InstrEName, InstrMName, InstrWName);
|
||||
|
Loading…
Reference in New Issue
Block a user