mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-03 10:15:19 +00:00
Merge branch 'main' of github.com:davidharrishmc/riscv-wally into main
This commit is contained in:
commit
a9b4f9b1e7
1
.gitignore
vendored
1
.gitignore
vendored
@ -51,4 +51,5 @@ fpga/generator/*.jou
|
||||
examples/asm/sumtest/sumtest
|
||||
examples/asm/example/example
|
||||
examples/C/sum/sum
|
||||
examples/C/fir/fir
|
||||
|
||||
|
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -17,9 +17,6 @@
|
||||
[submodule "addins/embench-iot"]
|
||||
path = addins/embench-iot
|
||||
url = https://github.com/embench/embench-iot
|
||||
[submodule "addins/book_flow"]
|
||||
path = addins/book_flow
|
||||
url = https://github.com/stineje/book_flow
|
||||
[submodule "addins/sky130_osu_sc_t18"]
|
||||
path = addins/sky130_osu_sc_t18
|
||||
url = https://foss-eda-tools.googlesource.com/skywater-pdk/libs/sky130_osu_sc_t18
|
||||
|
@ -1 +0,0 @@
|
||||
Subproject commit 5ef17d725e472ef414e5581bf25805236e6a60ca
|
@ -5,7 +5,7 @@ $(TARGET).objdump: $(TARGET)
|
||||
spike $(TARGET)
|
||||
|
||||
$(TARGET): $(TARGET).c Makefile
|
||||
riscv64-unknown-elf-gcc -o $(TARGET) -g -O\
|
||||
riscv64-unknown-elf-gcc -o $(TARGET) -g -O2\
|
||||
-march=rv64gc -mabi=lp64d -mcmodel=medany \
|
||||
-nostdlib -static -lm -fno-tree-loop-distribute-patterns \
|
||||
-T../common/test.ld -I../common \
|
||||
|
Binary file not shown.
@ -3,6 +3,7 @@
|
||||
// Finite Impulse Response Filter
|
||||
|
||||
#include <stdio.h> // supports printf
|
||||
#include <math.h> // supports fabs
|
||||
#include "util.h" // supports verify
|
||||
|
||||
void fir(int N, int M, double X[], double c[], double Y[]) {
|
||||
|
@ -86,10 +86,10 @@
|
||||
// Range should be a thermometer code with 0's in the upper bits and 1s in the lower bits
|
||||
`define BOOTROM_SUPPORTED 1'b1
|
||||
`define BOOTROM_BASE 34'h00001000
|
||||
`define BOOTROM_RANGE 34'h00000FFF
|
||||
`define BOOTROM_RANGE 34'h000000FF
|
||||
`define RAM_SUPPORTED 1'b1
|
||||
`define RAM_BASE 34'h80000000
|
||||
`define RAM_RANGE 34'h0000FFFF
|
||||
`define RAM_RANGE 34'h000003FF
|
||||
`define EXT_MEM_SUPPORTED 1'b0
|
||||
`define EXT_MEM_BASE 34'h80000000
|
||||
`define EXT_MEM_RANGE 34'h07FFFFFF
|
||||
@ -129,6 +129,6 @@
|
||||
|
||||
`define TWO_BIT_PRELOAD "../config/rv32ic/twoBitPredictor.txt"
|
||||
`define BTB_PRELOAD "../config/rv32ic/BTBPredictor.txt"
|
||||
`define BPRED_ENABLED 1
|
||||
`define BPRED_ENABLED 0
|
||||
`define BPTYPE "BPGSHARE" // BPLOCALPAg or BPGLOBAL or BPTWOBIT or BPGSHARE
|
||||
`define TESTSBP 0
|
||||
|
@ -129,11 +129,11 @@ assign FmtE = 1'b1;
|
||||
|
||||
assign BiasE = 13'h3ff;
|
||||
|
||||
assign wnan = FmtE ? &FMAResM[`FLEN-2:`NF] && |FMAResM[`NF-1:0] : &FMAResM[30:23] && |FMAResM[22:0];
|
||||
// assign XNaNE = FmtE ? &X[62:52] && |X[51:0] : &X[62:55] && |X[54:32];
|
||||
// assign YNaNE = FmtE ? &Y[62:52] && |Y[51:0] : &Y[62:55] && |Y[54:32];
|
||||
// assign ZNaNE = FmtE ? &Z[62:52] && |Z[51:0] : &Z[62:55] && |Z[54:32];
|
||||
assign ansnan = FmtE ? &ans[`FLEN-2:`NF] && |ans[`NF-1:0] : &ans[30:23] && |ans[22:0];
|
||||
assign wnan = FmtE ? &FMAResM[`FLEN-2:`NF] & |FMAResM[`NF-1:0] : &FMAResM[30:23] & |FMAResM[22:0];
|
||||
// assign XNaNE = FmtE ? &X[62:52] & |X[51:0] : &X[62:55] & |X[54:32];
|
||||
// assign YNaNE = FmtE ? &Y[62:52] & |Y[51:0] : &Y[62:55] & |Y[54:32];
|
||||
// assign ZNaNE = FmtE ? &Z[62:52] & |Z[51:0] : &Z[62:55] & |Z[54:32];
|
||||
assign ansnan = FmtE ? &ans[`FLEN-2:`NF] & |ans[`NF-1:0] : &ans[30:23] & |ans[22:0];
|
||||
// instantiate device under test
|
||||
|
||||
logic [3*`NF+5:0] SumE, SumM;
|
||||
@ -179,9 +179,9 @@ always @(posedge clk)
|
||||
// check results on falling edge of clk
|
||||
always @(negedge clk) begin
|
||||
|
||||
if((FmtE==1'b1) & (FMAFlgM != flags[4:0] || (!wnan && (FMAResM != ans)) || (wnan && ansnan && ~((XNaNE && (FMAResM[`FLEN-2:0] == {XExpE,1'b1,X[`NF-2:0]})) || (YNaNE && (FMAResM[`FLEN-2:0] == {YExpE,1'b1,Y[`NF-2:0]})) || (ZNaNE && (FMAResM[`FLEN-2:0] == {ZExpE,1'b1,Z[`NF-2:0]})) || (FMAResM[`FLEN-2:0] == ans[`FLEN-2:0]))))) begin
|
||||
if((FmtE==1'b1) & (FMAFlgM != flags[4:0] | (!wnan & (FMAResM != ans)) | (wnan & ansnan & ~((XNaNE & (FMAResM[`FLEN-2:0] == {XExpE,1'b1,X[`NF-2:0]})) | (YNaNE & (FMAResM[`FLEN-2:0] == {YExpE,1'b1,Y[`NF-2:0]})) | (ZNaNE & (FMAResM[`FLEN-2:0] == {ZExpE,1'b1,Z[`NF-2:0]})) | (FMAResM[`FLEN-2:0] == ans[`FLEN-2:0]))))) begin
|
||||
// fp = $fopen("/home/kparry/riscv-wally/pipelined/src/fpu/FMA/tbgen/results.dat","w");
|
||||
// if((FmtE==1'b1) & (FMAFlgM != flags[4:0] || (FMAResM != ans))) begin
|
||||
// if((FmtE==1'b1) & (FMAFlgM != flags[4:0] | (FMAResM != ans))) begin
|
||||
$display( "%h %h %h %h %h %h %h Wrong ",X,Y, Z, FMAResM, ans, FMAFlgM, flags);
|
||||
if(FMAResM == 64'h8000000000000000) $display( "FMAResM=-zero ");
|
||||
if(XDenormE) $display( "xdenorm ");
|
||||
@ -190,35 +190,35 @@ always @(posedge clk)
|
||||
if(FMAFlgM[4] != 0) $display( "invld ");
|
||||
if(FMAFlgM[2] != 0) $display( "ovrflw ");
|
||||
if(FMAFlgM[1] != 0) $display( "unflw ");
|
||||
if(FMAResM[`FLEN] && FMAResM[`FLEN-2:`NF] == {`NE{1'b1}} && FMAResM[`NF-1:0] == 0) $display( "FMAResM=-inf ");
|
||||
if(~FMAResM[`FLEN] && FMAResM[`FLEN-2:`NF] == {`NE{1'b1}} && FMAResM[`NF-1:0] == 0) $display( "FMAResM=+inf ");
|
||||
if(FMAResM[`FLEN-2:`NF] == {`NE{1'b1}} && FMAResM[`NF-1:0] != 0 && ~FMAResM[`NF-1]) $display( "FMAResM=sigNaN ");
|
||||
if(FMAResM[`FLEN-2:`NF] == {`NE{1'b1}} && FMAResM[`NF-1:0] != 0 && FMAResM[`NF-1]) $display( "FMAResM=qutNaN ");
|
||||
if(ans[`FLEN] && ans[`FLEN-2:`NF] == {`NE{1'b1}} && ans[`NF-1:0] == 0) $display( "ans=-inf ");
|
||||
if(~ans[`FLEN] && ans[`FLEN-2:`NF] == {`NE{1'b1}} && ans[`NF-1:0] == 0) $display( "ans=+inf ");
|
||||
if(ans[`FLEN-2:`NF] == {`NE{1'b1}} && ans[`NF-1:0] != 0 && ~ans[`NF-1]) $display( "ans=sigNaN ");
|
||||
if(ans[`FLEN-2:`NF] == {`NE{1'b1}} && ans[`NF-1:0] != 0 && ans[`NF-1]) $display( "ans=qutNaN ");
|
||||
if(FMAResM[`FLEN] & FMAResM[`FLEN-2:`NF] == {`NE{1'b1}} & FMAResM[`NF-1:0] == 0) $display( "FMAResM=-inf ");
|
||||
if(~FMAResM[`FLEN] & FMAResM[`FLEN-2:`NF] == {`NE{1'b1}} & FMAResM[`NF-1:0] == 0) $display( "FMAResM=+inf ");
|
||||
if(FMAResM[`FLEN-2:`NF] == {`NE{1'b1}} & FMAResM[`NF-1:0] != 0 & ~FMAResM[`NF-1]) $display( "FMAResM=sigNaN ");
|
||||
if(FMAResM[`FLEN-2:`NF] == {`NE{1'b1}} & FMAResM[`NF-1:0] != 0 & FMAResM[`NF-1]) $display( "FMAResM=qutNaN ");
|
||||
if(ans[`FLEN] & ans[`FLEN-2:`NF] == {`NE{1'b1}} & ans[`NF-1:0] == 0) $display( "ans=-inf ");
|
||||
if(~ans[`FLEN] & ans[`FLEN-2:`NF] == {`NE{1'b1}} & ans[`NF-1:0] == 0) $display( "ans=+inf ");
|
||||
if(ans[`FLEN-2:`NF] == {`NE{1'b1}} & ans[`NF-1:0] != 0 & ~ans[`NF-1]) $display( "ans=sigNaN ");
|
||||
if(ans[`FLEN-2:`NF] == {`NE{1'b1}} & ans[`NF-1:0] != 0 & ans[`NF-1]) $display( "ans=qutNaN ");
|
||||
errors = errors + 1;
|
||||
//if (errors == 10)
|
||||
$stop;
|
||||
end
|
||||
if((FmtE==1'b0)&(FMAFlgM != flags[4:0] || (!wnan && (FMAResM != ans)) || (wnan && ansnan && ~(((XNaNE && (FMAResM[30:0] == {X[30:23],1'b1,X[21:0]})) || (YNaNE && (FMAResM[30:0] == {Y[30:23],1'b1,Y[21:0]})) || (ZNaNE && (FMAResM[30:0] == {Z[30:23],1'b1,Z[21:0]})) || (FMAResM[30:0] == ans[30:0]))) ))) begin
|
||||
if((FmtE==1'b0)&(FMAFlgM != flags[4:0] | (!wnan & (FMAResM != ans)) | (wnan & ansnan & ~(((XNaNE & (FMAResM[30:0] == {X[30:23],1'b1,X[21:0]})) | (YNaNE & (FMAResM[30:0] == {Y[30:23],1'b1,Y[21:0]})) | (ZNaNE & (FMAResM[30:0] == {Z[30:23],1'b1,Z[21:0]})) | (FMAResM[30:0] == ans[30:0]))) ))) begin
|
||||
$display( "%h %h %h %h %h %h %h Wrong ",X,Y, Z, FMAResM, ans, FMAFlgM, flags);
|
||||
if(FMAResM == 64'h8000000000000000) $display( "FMAResM=-zero ");
|
||||
if(~(|X[30:23]) && |X[22:0]) $display( "xdenorm ");
|
||||
if(~(|Y[30:23]) && |Y[22:0]) $display( "ydenorm ");
|
||||
if(~(|Z[30:23]) && |Z[22:0]) $display( "zdenorm ");
|
||||
if(~(|X[30:23]) & |X[22:0]) $display( "xdenorm ");
|
||||
if(~(|Y[30:23]) & |Y[22:0]) $display( "ydenorm ");
|
||||
if(~(|Z[30:23]) & |Z[22:0]) $display( "zdenorm ");
|
||||
if(FMAFlgM[4] != 0) $display( "invld ");
|
||||
if(FMAFlgM[2] != 0) $display( "ovrflw ");
|
||||
if(FMAFlgM[1] != 0) $display( "unflw ");
|
||||
if(FMAResM == 64'hFF80000000000000) $display( "FMAResM=-inf ");
|
||||
if(FMAResM == 64'h7F80000000000000) $display( "FMAResM=+inf ");
|
||||
if(&FMAResM[30:23] && |FMAResM[22:0] && ~FMAResM[22]) $display( "FMAResM=sigNaN ");
|
||||
if(&FMAResM[30:23] && |FMAResM[22:0] && FMAResM[22] ) $display( "FMAResM=qutNaN ");
|
||||
if(&FMAResM[30:23] & |FMAResM[22:0] & ~FMAResM[22]) $display( "FMAResM=sigNaN ");
|
||||
if(&FMAResM[30:23] & |FMAResM[22:0] & FMAResM[22] ) $display( "FMAResM=qutNaN ");
|
||||
if(ans == 64'hFF80000000000000) $display( "ans=-inf ");
|
||||
if(ans == 64'h7F80000000000000) $display( "ans=+inf ");
|
||||
if(&ans[30:23] && |ans[22:0] && ~ans[22] ) $display( "ans=sigNaN ");
|
||||
if(&ans[30:23] && |ans[22:0] && ans[22]) $display( "ans=qutNaN ");
|
||||
if(&ans[30:23] & |ans[22:0] & ~ans[22] ) $display( "ans=sigNaN ");
|
||||
if(&ans[30:23] & |ans[22:0] & ans[22]) $display( "ans=qutNaN ");
|
||||
errors = errors + 1;
|
||||
if (errors == 10)
|
||||
$stop;
|
||||
|
@ -98,7 +98,7 @@ add wave -noupdate -group Bpred -expand -group {bp wrong} /testbench/dut/wallypi
|
||||
add wave -noupdate -group Bpred -expand -group {bp wrong} /testbench/dut/wallypipelinedsoc/core/ifu/bpred/bpred/BPPredWrongE
|
||||
add wave -noupdate -group Bpred /testbench/dut/wallypipelinedsoc/core/ifu/bpred/bpred/BPPredWrongE
|
||||
add wave -noupdate -group {instruction pipeline} /testbench/InstrFName
|
||||
add wave -noupdate -group {instruction pipeline} /testbench/dut/wallypipelinedsoc/core/ifu/icache/FinalInstrRawF
|
||||
add wave -noupdate -group {instruction pipeline} /testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/FinalInstrRawF
|
||||
add wave -noupdate -group {instruction pipeline} /testbench/dut/wallypipelinedsoc/core/ifu/InstrD
|
||||
add wave -noupdate -group {instruction pipeline} /testbench/dut/wallypipelinedsoc/core/ifu/InstrE
|
||||
add wave -noupdate -group {instruction pipeline} /testbench/dut/wallypipelinedsoc/core/ifu/InstrM
|
||||
@ -172,86 +172,86 @@ add wave -noupdate -group muldiv /testbench/dut/wallypipelinedsoc/core/mdu/Flush
|
||||
add wave -noupdate -group muldiv /testbench/dut/wallypipelinedsoc/core/mdu/FlushW
|
||||
add wave -noupdate -group muldiv /testbench/dut/wallypipelinedsoc/core/mdu/MulDivResultW
|
||||
add wave -noupdate -group muldiv /testbench/dut/wallypipelinedsoc/core/mdu/DivBusyE
|
||||
add wave -noupdate -group icache -color Gold /testbench/dut/wallypipelinedsoc/core/ifu/icache/controller/CurrState
|
||||
add wave -noupdate -group icache /testbench/dut/wallypipelinedsoc/core/ifu/icache/BasePAdrF
|
||||
add wave -noupdate -group icache /testbench/dut/wallypipelinedsoc/core/ifu/icache/WayHit
|
||||
add wave -noupdate -group icache /testbench/dut/wallypipelinedsoc/core/ifu/icache/genblk1/cachereplacementpolicy/BlockReplacementBits
|
||||
add wave -noupdate -group icache /testbench/dut/wallypipelinedsoc/core/ifu/icache/genblk1/cachereplacementpolicy/EncVicWay
|
||||
add wave -noupdate -group icache /testbench/dut/wallypipelinedsoc/core/ifu/icache/VictimWay
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way0 {/testbench/dut/wallypipelinedsoc/core/ifu/icache/MemWay[0]/WriteEnable}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way0 {/testbench/dut/wallypipelinedsoc/core/ifu/icache/MemWay[0]/SetValid}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way0 -label TAG {/testbench/dut/wallypipelinedsoc/core/ifu/icache/MemWay[0]/CacheTagMem/StoredData}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way0 {/testbench/dut/wallypipelinedsoc/core/ifu/icache/MemWay[0]/ValidBits}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way0 -expand -group Way0Word0 {/testbench/dut/wallypipelinedsoc/core/ifu/icache/MemWay[0]/word[0]/CacheDataMem/StoredData}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way0 -expand -group Way0Word0 {/testbench/dut/wallypipelinedsoc/core/ifu/icache/MemWay[0]/word[0]/CacheDataMem/WriteEnable}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way0 -group Way0Word1 {/testbench/dut/wallypipelinedsoc/core/ifu/icache/MemWay[0]/word[1]/CacheDataMem/StoredData}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way0 -group Way0Word1 {/testbench/dut/wallypipelinedsoc/core/ifu/icache/MemWay[0]/word[1]/CacheDataMem/WriteEnable}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way0 -group Way0Word2 {/testbench/dut/wallypipelinedsoc/core/ifu/icache/MemWay[0]/word[2]/CacheDataMem/WriteEnable}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way0 -group Way0Word2 {/testbench/dut/wallypipelinedsoc/core/ifu/icache/MemWay[0]/word[2]/CacheDataMem/StoredData}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way0 -group Way0Word3 {/testbench/dut/wallypipelinedsoc/core/ifu/icache/MemWay[0]/word[3]/CacheDataMem/WriteEnable}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way0 -group Way0Word3 {/testbench/dut/wallypipelinedsoc/core/ifu/icache/MemWay[0]/word[3]/CacheDataMem/StoredData}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way1 {/testbench/dut/wallypipelinedsoc/core/ifu/icache/MemWay[1]/WriteEnable}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way1 {/testbench/dut/wallypipelinedsoc/core/ifu/icache/MemWay[1]/WriteWordEnable}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way1 -label TAG {/testbench/dut/wallypipelinedsoc/core/ifu/icache/MemWay[1]/CacheTagMem/StoredData}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way1 {/testbench/dut/wallypipelinedsoc/core/ifu/icache/MemWay[1]/ValidBits}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way1 -expand -group Way1Word0 {/testbench/dut/wallypipelinedsoc/core/ifu/icache/MemWay[1]/word[0]/CacheDataMem/WriteEnable}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way1 -expand -group Way1Word0 {/testbench/dut/wallypipelinedsoc/core/ifu/icache/MemWay[1]/word[0]/CacheDataMem/StoredData}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way1 -group Way1Word1 {/testbench/dut/wallypipelinedsoc/core/ifu/icache/MemWay[1]/word[1]/CacheDataMem/WriteEnable}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way1 -group Way1Word1 {/testbench/dut/wallypipelinedsoc/core/ifu/icache/MemWay[1]/word[1]/CacheDataMem/StoredData}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way1 -group Way1Word2 {/testbench/dut/wallypipelinedsoc/core/ifu/icache/MemWay[1]/word[2]/CacheDataMem/WriteEnable}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way1 -group Way1Word2 {/testbench/dut/wallypipelinedsoc/core/ifu/icache/MemWay[1]/word[2]/CacheDataMem/StoredData}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way1 -group Way1Word3 {/testbench/dut/wallypipelinedsoc/core/ifu/icache/MemWay[1]/word[3]/CacheDataMem/WriteEnable}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way1 -group Way1Word3 {/testbench/dut/wallypipelinedsoc/core/ifu/icache/MemWay[1]/word[3]/CacheDataMem/StoredData}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way2 {/testbench/dut/wallypipelinedsoc/core/ifu/icache/MemWay[2]/WriteEnable}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way2 {/testbench/dut/wallypipelinedsoc/core/ifu/icache/MemWay[2]/SetValid}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way2 -label TAG {/testbench/dut/wallypipelinedsoc/core/ifu/icache/MemWay[2]/CacheTagMem/StoredData}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way2 {/testbench/dut/wallypipelinedsoc/core/ifu/icache/MemWay[2]/ValidBits}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way2 -expand -group Way2Word0 {/testbench/dut/wallypipelinedsoc/core/ifu/icache/MemWay[2]/word[0]/CacheDataMem/StoredData}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way2 -expand -group Way2Word0 {/testbench/dut/wallypipelinedsoc/core/ifu/icache/MemWay[2]/word[0]/CacheDataMem/WriteEnable}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way2 -group Way2Word1 {/testbench/dut/wallypipelinedsoc/core/ifu/icache/MemWay[2]/word[1]/CacheDataMem/StoredData}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way2 -group Way2Word1 {/testbench/dut/wallypipelinedsoc/core/ifu/icache/MemWay[2]/word[1]/CacheDataMem/WriteEnable}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way2 -group Way2Word2 {/testbench/dut/wallypipelinedsoc/core/ifu/icache/MemWay[2]/word[2]/CacheDataMem/WriteEnable}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way2 -group Way2Word2 {/testbench/dut/wallypipelinedsoc/core/ifu/icache/MemWay[2]/word[2]/CacheDataMem/StoredData}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way2 -group Way2Word3 {/testbench/dut/wallypipelinedsoc/core/ifu/icache/MemWay[2]/word[3]/CacheDataMem/WriteEnable}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way2 -group Way2Word3 {/testbench/dut/wallypipelinedsoc/core/ifu/icache/MemWay[2]/word[3]/CacheDataMem/StoredData}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -expand -group way3 {/testbench/dut/wallypipelinedsoc/core/ifu/icache/MemWay[3]/WriteEnable}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -expand -group way3 {/testbench/dut/wallypipelinedsoc/core/ifu/icache/MemWay[3]/SetValid}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -expand -group way3 -label TAG {/testbench/dut/wallypipelinedsoc/core/ifu/icache/MemWay[3]/CacheTagMem/StoredData}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -expand -group way3 {/testbench/dut/wallypipelinedsoc/core/ifu/icache/MemWay[3]/DirtyBits}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -expand -group way3 {/testbench/dut/wallypipelinedsoc/core/ifu/icache/MemWay[3]/ValidBits}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -expand -group way3 -expand -group Way3Word0 {/testbench/dut/wallypipelinedsoc/core/ifu/icache/MemWay[3]/word[0]/CacheDataMem/StoredData}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -expand -group way3 -expand -group Way3Word0 {/testbench/dut/wallypipelinedsoc/core/ifu/icache/MemWay[3]/word[0]/CacheDataMem/WriteEnable}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -expand -group way3 -group Way3Word1 {/testbench/dut/wallypipelinedsoc/core/ifu/icache/MemWay[3]/word[1]/CacheDataMem/StoredData}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -expand -group way3 -group Way3Word1 {/testbench/dut/wallypipelinedsoc/core/ifu/icache/MemWay[3]/word[1]/CacheDataMem/WriteEnable}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -expand -group way3 -group Way3Word2 {/testbench/dut/wallypipelinedsoc/core/ifu/icache/MemWay[3]/word[2]/CacheDataMem/WriteEnable}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -expand -group way3 -group Way3Word2 {/testbench/dut/wallypipelinedsoc/core/ifu/icache/MemWay[3]/word[2]/CacheDataMem/StoredData}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -expand -group way3 -group Way3Word3 {/testbench/dut/wallypipelinedsoc/core/ifu/icache/MemWay[3]/word[3]/CacheDataMem/WriteEnable}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -expand -group way3 -group Way3Word3 {/testbench/dut/wallypipelinedsoc/core/ifu/icache/MemWay[3]/word[3]/CacheDataMem/StoredData}
|
||||
add wave -noupdate -group icache /testbench/dut/wallypipelinedsoc/core/ifu/icache/controller/NextState
|
||||
add wave -noupdate -group icache -color Gold /testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/controller/CurrState
|
||||
add wave -noupdate -group icache /testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/BasePAdrF
|
||||
add wave -noupdate -group icache /testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/WayHit
|
||||
add wave -noupdate -group icache /testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/genblk1/cachereplacementpolicy/BlockReplacementBits
|
||||
add wave -noupdate -group icache /testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/genblk1/cachereplacementpolicy/EncVicWay
|
||||
add wave -noupdate -group icache /testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/VictimWay
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way0 {/testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/MemWay[0]/WriteEnable}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way0 {/testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/MemWay[0]/SetValid}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way0 -label TAG {/testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/MemWay[0]/CacheTagMem/StoredData}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way0 {/testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/MemWay[0]/ValidBits}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way0 -expand -group Way0Word0 {/testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/MemWay[0]/word[0]/CacheDataMem/StoredData}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way0 -expand -group Way0Word0 {/testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/MemWay[0]/word[0]/CacheDataMem/WriteEnable}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way0 -group Way0Word1 {/testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/MemWay[0]/word[1]/CacheDataMem/StoredData}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way0 -group Way0Word1 {/testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/MemWay[0]/word[1]/CacheDataMem/WriteEnable}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way0 -group Way0Word2 {/testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/MemWay[0]/word[2]/CacheDataMem/WriteEnable}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way0 -group Way0Word2 {/testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/MemWay[0]/word[2]/CacheDataMem/StoredData}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way0 -group Way0Word3 {/testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/MemWay[0]/word[3]/CacheDataMem/WriteEnable}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way0 -group Way0Word3 {/testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/MemWay[0]/word[3]/CacheDataMem/StoredData}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way1 {/testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/MemWay[1]/WriteEnable}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way1 {/testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/MemWay[1]/WriteWordEnable}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way1 -label TAG {/testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/MemWay[1]/CacheTagMem/StoredData}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way1 {/testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/MemWay[1]/ValidBits}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way1 -expand -group Way1Word0 {/testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/MemWay[1]/word[0]/CacheDataMem/WriteEnable}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way1 -expand -group Way1Word0 {/testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/MemWay[1]/word[0]/CacheDataMem/StoredData}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way1 -group Way1Word1 {/testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/MemWay[1]/word[1]/CacheDataMem/WriteEnable}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way1 -group Way1Word1 {/testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/MemWay[1]/word[1]/CacheDataMem/StoredData}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way1 -group Way1Word2 {/testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/MemWay[1]/word[2]/CacheDataMem/WriteEnable}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way1 -group Way1Word2 {/testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/MemWay[1]/word[2]/CacheDataMem/StoredData}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way1 -group Way1Word3 {/testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/MemWay[1]/word[3]/CacheDataMem/WriteEnable}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way1 -group Way1Word3 {/testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/MemWay[1]/word[3]/CacheDataMem/StoredData}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way2 {/testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/MemWay[2]/WriteEnable}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way2 {/testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/MemWay[2]/SetValid}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way2 -label TAG {/testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/MemWay[2]/CacheTagMem/StoredData}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way2 {/testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/MemWay[2]/ValidBits}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way2 -expand -group Way2Word0 {/testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/MemWay[2]/word[0]/CacheDataMem/StoredData}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way2 -expand -group Way2Word0 {/testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/MemWay[2]/word[0]/CacheDataMem/WriteEnable}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way2 -group Way2Word1 {/testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/MemWay[2]/word[1]/CacheDataMem/StoredData}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way2 -group Way2Word1 {/testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/MemWay[2]/word[1]/CacheDataMem/WriteEnable}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way2 -group Way2Word2 {/testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/MemWay[2]/word[2]/CacheDataMem/WriteEnable}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way2 -group Way2Word2 {/testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/MemWay[2]/word[2]/CacheDataMem/StoredData}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way2 -group Way2Word3 {/testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/MemWay[2]/word[3]/CacheDataMem/WriteEnable}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -group way2 -group Way2Word3 {/testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/MemWay[2]/word[3]/CacheDataMem/StoredData}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -expand -group way3 {/testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/MemWay[3]/WriteEnable}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -expand -group way3 {/testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/MemWay[3]/SetValid}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -expand -group way3 -label TAG {/testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/MemWay[3]/CacheTagMem/StoredData}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -expand -group way3 {/testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/MemWay[3]/DirtyBits}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -expand -group way3 {/testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/MemWay[3]/ValidBits}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -expand -group way3 -expand -group Way3Word0 {/testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/MemWay[3]/word[0]/CacheDataMem/StoredData}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -expand -group way3 -expand -group Way3Word0 {/testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/MemWay[3]/word[0]/CacheDataMem/WriteEnable}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -expand -group way3 -group Way3Word1 {/testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/MemWay[3]/word[1]/CacheDataMem/StoredData}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -expand -group way3 -group Way3Word1 {/testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/MemWay[3]/word[1]/CacheDataMem/WriteEnable}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -expand -group way3 -group Way3Word2 {/testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/MemWay[3]/word[2]/CacheDataMem/WriteEnable}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -expand -group way3 -group Way3Word2 {/testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/MemWay[3]/word[2]/CacheDataMem/StoredData}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -expand -group way3 -group Way3Word3 {/testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/MemWay[3]/word[3]/CacheDataMem/WriteEnable}
|
||||
add wave -noupdate -group icache -group {Cache SRAM writes} -expand -group way3 -group Way3Word3 {/testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/MemWay[3]/word[3]/CacheDataMem/StoredData}
|
||||
add wave -noupdate -group icache /testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/controller/NextState
|
||||
add wave -noupdate -group icache /testbench/dut/wallypipelinedsoc/core/ifu/ITLBMissF
|
||||
add wave -noupdate -group icache /testbench/dut/wallypipelinedsoc/core/ifu/icache/ITLBWriteF
|
||||
add wave -noupdate -group icache /testbench/dut/wallypipelinedsoc/core/ifu/icache/ReadLineF
|
||||
add wave -noupdate -group icache /testbench/dut/wallypipelinedsoc/core/ifu/icache/PCNextIndexF
|
||||
add wave -noupdate -group icache /testbench/dut/wallypipelinedsoc/core/ifu/icache/ReadLineF
|
||||
add wave -noupdate -group icache /testbench/dut/wallypipelinedsoc/core/ifu/icache/BasePAdrF
|
||||
add wave -noupdate -group icache -group {fsm out and control} /testbench/dut/wallypipelinedsoc/core/ifu/icache/controller/hit
|
||||
add wave -noupdate -group icache -group {fsm out and control} /testbench/dut/wallypipelinedsoc/core/ifu/icache/controller/spill
|
||||
add wave -noupdate -group icache -group {fsm out and control} /testbench/dut/wallypipelinedsoc/core/ifu/icache/controller/ICacheStallF
|
||||
add wave -noupdate -group icache -group {fsm out and control} /testbench/dut/wallypipelinedsoc/core/ifu/icache/controller/SavePC
|
||||
add wave -noupdate -group icache -group {fsm out and control} /testbench/dut/wallypipelinedsoc/core/ifu/icache/controller/spillSave
|
||||
add wave -noupdate -group icache -group {fsm out and control} /testbench/dut/wallypipelinedsoc/core/ifu/icache/controller/UnalignedSelect
|
||||
add wave -noupdate -group icache -group {fsm out and control} /testbench/dut/wallypipelinedsoc/core/ifu/icache/controller/spillSave
|
||||
add wave -noupdate -group icache -group {fsm out and control} /testbench/dut/wallypipelinedsoc/core/ifu/icache/controller/CntReset
|
||||
add wave -noupdate -group icache -group {fsm out and control} /testbench/dut/wallypipelinedsoc/core/ifu/icache/controller/PreCntEn
|
||||
add wave -noupdate -group icache -group {fsm out and control} /testbench/dut/wallypipelinedsoc/core/ifu/icache/controller/CntEn
|
||||
add wave -noupdate -group icache -expand -group memory /testbench/dut/wallypipelinedsoc/core/ifu/icache/InstrPAdrF
|
||||
add wave -noupdate -group icache -expand -group memory /testbench/dut/wallypipelinedsoc/core/ifu/icache/InstrInF
|
||||
add wave -noupdate -group icache -expand -group memory /testbench/dut/wallypipelinedsoc/core/ifu/icache/controller/FetchCountFlag
|
||||
add wave -noupdate -group icache -expand -group memory /testbench/dut/wallypipelinedsoc/core/ifu/icache/FetchCount
|
||||
add wave -noupdate -group icache -expand -group memory /testbench/dut/wallypipelinedsoc/core/ifu/icache/controller/InstrReadF
|
||||
add wave -noupdate -group icache -expand -group memory /testbench/dut/wallypipelinedsoc/core/ifu/icache/controller/InstrAckF
|
||||
add wave -noupdate -group icache -expand -group memory /testbench/dut/wallypipelinedsoc/core/ifu/icache/controller/ICacheMemWriteEnable
|
||||
add wave -noupdate -group icache -expand -group memory /testbench/dut/wallypipelinedsoc/core/ifu/icache/ICacheMemWriteData
|
||||
add wave -noupdate -group icache /testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/ITLBWriteF
|
||||
add wave -noupdate -group icache /testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/ReadLineF
|
||||
add wave -noupdate -group icache /testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/PCNextIndexF
|
||||
add wave -noupdate -group icache /testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/ReadLineF
|
||||
add wave -noupdate -group icache /testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/BasePAdrF
|
||||
add wave -noupdate -group icache -group {fsm out and control} /testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/controller/hit
|
||||
add wave -noupdate -group icache -group {fsm out and control} /testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/controller/spill
|
||||
add wave -noupdate -group icache -group {fsm out and control} /testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/controller/ICacheStallF
|
||||
add wave -noupdate -group icache -group {fsm out and control} /testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/controller/SavePC
|
||||
add wave -noupdate -group icache -group {fsm out and control} /testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/controller/spillSave
|
||||
add wave -noupdate -group icache -group {fsm out and control} /testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/controller/UnalignedSelect
|
||||
add wave -noupdate -group icache -group {fsm out and control} /testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/controller/spillSave
|
||||
add wave -noupdate -group icache -group {fsm out and control} /testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/controller/CntReset
|
||||
add wave -noupdate -group icache -group {fsm out and control} /testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/controller/PreCntEn
|
||||
add wave -noupdate -group icache -group {fsm out and control} /testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/controller/CntEn
|
||||
add wave -noupdate -group icache -expand -group memory /testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/InstrPAdrF
|
||||
add wave -noupdate -group icache -expand -group memory /testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/InstrInF
|
||||
add wave -noupdate -group icache -expand -group memory /testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/controller/FetchCountFlag
|
||||
add wave -noupdate -group icache -expand -group memory /testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/FetchCount
|
||||
add wave -noupdate -group icache -expand -group memory /testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/controller/InstrReadF
|
||||
add wave -noupdate -group icache -expand -group memory /testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/controller/InstrAckF
|
||||
add wave -noupdate -group icache -expand -group memory /testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/controller/ICacheMemWriteEnable
|
||||
add wave -noupdate -group icache -expand -group memory /testbench/dut/wallypipelinedsoc/core/ifu/bus/icache/ICacheMemWriteData
|
||||
add wave -noupdate -group AHB -color Gold /testbench/dut/wallypipelinedsoc/core/ebu/BusState
|
||||
add wave -noupdate -group AHB /testbench/dut/wallypipelinedsoc/core/ebu/NextBusState
|
||||
add wave -noupdate -group AHB -expand -group {input requests} /testbench/dut/wallypipelinedsoc/core/ebu/AtomicMaskedM
|
||||
|
@ -23,7 +23,7 @@ add wave -noupdate -group HDU -expand -group traps /testbench/dut/core/priv/priv
|
||||
add wave -noupdate -group HDU -expand -group traps /testbench/dut/core/priv/priv/trap/StoreAmoMisalignedFaultM
|
||||
add wave -noupdate -group HDU -expand -group traps /testbench/dut/core/priv/priv/trap/InstrPageFaultM
|
||||
add wave -noupdate -group HDU -expand -group traps /testbench/dut/core/priv/priv/trap/LoadPageFaultM
|
||||
add wave -noupdate -group HDU -expand -group traps /testbench/dut/core/priv/priv/trap/StorePageFaultM
|
||||
add wave -noupdate -group HDU -expand -group traps /testbench/dut/core/priv/priv/trap/StoreAmoPageFaultM
|
||||
add wave -noupdate -group HDU -expand -group traps /testbench/dut/core/priv/priv/trap/BreakpointFaultM
|
||||
add wave -noupdate -group HDU -expand -group traps /testbench/dut/core/priv/priv/trap/EcallFaultM
|
||||
add wave -noupdate -group HDU -expand -group traps /testbench/dut/core/priv/priv/trap/LoadMisalignedFaultM
|
||||
@ -168,15 +168,15 @@ add wave -noupdate -group {alu execution stage} /testbench/dut/core/ieu/dp/Write
|
||||
add wave -noupdate -group {alu execution stage} /testbench/dut/core/ieu/dp/ALUResultE
|
||||
add wave -noupdate -group {alu execution stage} /testbench/dut/core/ieu/dp/SrcAE
|
||||
add wave -noupdate -group {alu execution stage} /testbench/dut/core/ieu/dp/SrcBE
|
||||
add wave -noupdate -group icache -color Gold /testbench/dut/core/ifu/icache/icache/cachefsm/CurrState
|
||||
add wave -noupdate -group icache /testbench/dut/core/ifu/icache/icache/ReadDataWord
|
||||
add wave -noupdate -group icache /testbench/dut/core/ifu/icache/icache/SelAdr
|
||||
add wave -noupdate -group icache /testbench/dut/core/ifu/icache/icache/RAdr
|
||||
add wave -noupdate -group icache -expand -group {fsm out and control} /testbench/dut/core/ifu/icache/icache/CacheHit
|
||||
add wave -noupdate -group icache -expand -group {fsm out and control} /testbench/dut/core/ifu/icache/icache/CacheStall
|
||||
add wave -noupdate -group icache -expand -group {fsm out and control} /testbench/dut/core/ifu/icache/icache/ReadDataLineSets
|
||||
add wave -noupdate -group icache -expand -group memory /testbench/dut/core/ifu/icache/icache/CacheMemWriteData
|
||||
add wave -noupdate -group icache /testbench/dut/core/ifu/SpillSupport/SpillDataLine0
|
||||
add wave -noupdate -group icache -color Gold /testbench/dut/core/ifu/bus/icache/icache/cachefsm/CurrState
|
||||
add wave -noupdate -group icache /testbench/dut/core/ifu/bus/icache/icache/ReadDataWord
|
||||
add wave -noupdate -group icache /testbench/dut/core/ifu/bus/icache/icache/SelAdr
|
||||
add wave -noupdate -group icache /testbench/dut/core/ifu/bus/icache/icache/RAdr
|
||||
add wave -noupdate -group icache -expand -group {fsm out and control} /testbench/dut/core/ifu/bus/icache/icache/CacheHit
|
||||
add wave -noupdate -group icache -expand -group {fsm out and control} /testbench/dut/core/ifu/bus/icache/icache/CacheStall
|
||||
add wave -noupdate -group icache -expand -group {fsm out and control} /testbench/dut/core/ifu/bus/icache/icache/ReadDataLineSets
|
||||
add wave -noupdate -group icache -expand -group memory /testbench/dut/core/ifu/bus/icache/icache/CacheMemWriteData
|
||||
add wave -noupdate -group icache /testbench/dut/core/ifu/SpillSupport/spillsupport/SpillDataLine0
|
||||
add wave -noupdate -group AHB -color Gold /testbench/dut/core/ebu/BusState
|
||||
add wave -noupdate -group AHB /testbench/dut/core/ebu/NextBusState
|
||||
add wave -noupdate -group AHB -expand -group {input requests} /testbench/dut/core/ebu/AtomicMaskedM
|
||||
@ -196,12 +196,12 @@ add wave -noupdate -group AHB /testbench/dut/core/ebu/HMASTLOCK
|
||||
add wave -noupdate -group AHB /testbench/dut/core/ebu/HADDRD
|
||||
add wave -noupdate -group AHB /testbench/dut/core/ebu/HSIZED
|
||||
add wave -noupdate -group AHB /testbench/dut/core/ebu/HWRITED
|
||||
add wave -noupdate -group AMO_ALU /testbench/dut/core/lsu/amo/amoalu/funct
|
||||
add wave -noupdate -group AMO_ALU /testbench/dut/core/lsu/amo/amoalu/result
|
||||
add wave -noupdate -group AMO_ALU /testbench/dut/core/lsu/amo/amoalu/srca
|
||||
add wave -noupdate -group AMO_ALU /testbench/dut/core/lsu/amo/amoalu/srcb
|
||||
add wave -noupdate -group AMO_ALU /testbench/dut/core/lsu/amo/amoalu/width
|
||||
add wave -noupdate -expand -group lsu -color Gold /testbench/dut/core/lsu/MEM_VIRTMEM/interlockfsm/InterlockCurrState
|
||||
add wave -noupdate -group AMO_ALU /testbench/dut/core/lsu/atomic/atomic/amoalu/funct
|
||||
add wave -noupdate -group AMO_ALU /testbench/dut/core/lsu/atomic/atomic/amoalu/result
|
||||
add wave -noupdate -group AMO_ALU /testbench/dut/core/lsu/atomic/atomic/amoalu/srca
|
||||
add wave -noupdate -group AMO_ALU /testbench/dut/core/lsu/atomic/atomic/amoalu/srcb
|
||||
add wave -noupdate -group AMO_ALU /testbench/dut/core/lsu/atomic/atomic/amoalu/width
|
||||
add wave -noupdate -expand -group lsu -color Gold /testbench/dut/core/lsu/MEM_VIRTMEM/lsuvirtmem/interlockfsm/InterlockCurrState
|
||||
add wave -noupdate -expand -group lsu /testbench/dut/core/lsu/SelHPTW
|
||||
add wave -noupdate -expand -group lsu /testbench/dut/core/lsu/InterlockStall
|
||||
add wave -noupdate -expand -group lsu /testbench/dut/core/lsu/LSUStallM
|
||||
@ -212,7 +212,7 @@ add wave -noupdate -expand -group lsu -expand -group dcache /testbench/dut/core/
|
||||
add wave -noupdate -expand -group lsu -expand -group dcache /testbench/dut/core/lsu.bus.dcache/dcache/SRAMWayWriteEnable
|
||||
add wave -noupdate -expand -group lsu -expand -group dcache /testbench/dut/core/lsu.bus.dcache/dcache/SRAMWordEnable
|
||||
add wave -noupdate -expand -group lsu -expand -group dcache /testbench/dut/core/lsu.bus.dcache/dcache/SelAdr
|
||||
add wave -noupdate -expand -group lsu -expand -group dcache /testbench/dut/core/lsu/MEM_VIRTMEM/SelReplayCPURequest
|
||||
add wave -noupdate -expand -group lsu -expand -group dcache /testbench/dut/core/lsu/MEM_VIRTMEM/lsuvirtmem/SelReplayCPURequest
|
||||
add wave -noupdate -expand -group lsu -expand -group dcache /testbench/dut/core/lsu/IEUAdrE
|
||||
add wave -noupdate -expand -group lsu -expand -group dcache /testbench/dut/core/lsu/IEUAdrM
|
||||
add wave -noupdate -expand -group lsu -expand -group dcache /testbench/dut/core/lsu.bus.dcache/dcache/RAdr
|
||||
@ -220,8 +220,8 @@ add wave -noupdate -expand -group lsu -expand -group dcache -expand -group flush
|
||||
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group flush /testbench/dut/core/lsu.bus.dcache/dcache/VictimDirtyWay
|
||||
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group flush /testbench/dut/core/lsu.bus.dcache/dcache/VictimTag
|
||||
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group flush /testbench/dut/core/lsu.bus.dcache/dcache/CacheBusAdr
|
||||
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group flush /testbench/dut/core/lsu/WordCount
|
||||
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group flush /testbench/dut/core/lsu.bus.dcache/dcache/FlushAdr
|
||||
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group flush /testbench/dut/core/lsu/bus/busdp/WordCount
|
||||
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group flush /testbench/dut/core/lsu/bus/dcache/dcache/FlushAdr
|
||||
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group flush /testbench/dut/core/lsu.bus.dcache/dcache/FlushWay
|
||||
add wave -noupdate -expand -group lsu -expand -group dcache /testbench/dut/core/lsu.bus.dcache/dcache/CacheMemWriteData
|
||||
add wave -noupdate -expand -group lsu -expand -group dcache /testbench/dut/core/lsu.bus.dcache/dcache/WayHit
|
||||
@ -319,7 +319,7 @@ add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {CPU
|
||||
add wave -noupdate -expand -group lsu -expand -group dcache -expand -group {CPU side} /testbench/dut/core/lsu.bus.dcache/dcache/CacheStall
|
||||
add wave -noupdate -expand -group lsu -expand -group dcache -group status /testbench/dut/core/lsu.bus.dcache/dcache/WayHit
|
||||
add wave -noupdate -expand -group lsu -expand -group dcache -group status -color {Medium Orchid} /testbench/dut/core/lsu.bus.dcache/dcache/CacheHit
|
||||
add wave -noupdate -expand -group lsu -expand -group dcache -group status /testbench/dut/core/lsu/WordCount
|
||||
add wave -noupdate -expand -group lsu -expand -group dcache -group status /testbench/dut/core/lsu/bus/busdp/WordCount
|
||||
add wave -noupdate -expand -group lsu -expand -group dcache -group {Memory Side} /testbench/dut/core/lsu.bus.dcache/dcache/CacheBusAdr
|
||||
add wave -noupdate -expand -group lsu -expand -group dcache -group {Memory Side} /testbench/dut/core/lsu.bus.dcache/dcache/CacheFetchLine
|
||||
add wave -noupdate -expand -group lsu -expand -group dcache -group {Memory Side} /testbench/dut/core/lsu.bus.dcache/dcache/CacheWriteLine
|
||||
@ -360,20 +360,20 @@ add wave -noupdate -expand -group lsu -group pmp /testbench/dut/core/lsu/dmmu/dm
|
||||
add wave -noupdate -expand -group lsu -group pmp /testbench/dut/core/lsu/dmmu/dmmu/pmpchecker/pmpchecker/W
|
||||
add wave -noupdate -expand -group lsu -group pmp /testbench/dut/core/lsu/dmmu/dmmu/pmpchecker/pmpchecker/X
|
||||
add wave -noupdate -expand -group lsu -group pmp /testbench/dut/core/lsu/dmmu/dmmu/pmpchecker/pmpchecker/L
|
||||
add wave -noupdate -expand -group lsu -group ptwalker -color Gold /testbench/dut/core/lsu/MEM_VIRTMEM/hptw/WalkerState
|
||||
add wave -noupdate -expand -group lsu -group ptwalker /testbench/dut/core/lsu/MEM_VIRTMEM/hptw/PCF
|
||||
add wave -noupdate -expand -group lsu -group ptwalker /testbench/dut/core/lsu/MEM_VIRTMEM/hptw/HPTWAdr
|
||||
add wave -noupdate -expand -group lsu -group ptwalker /testbench/dut/core/lsu/MEM_VIRTMEM/hptw/HPTWReadPTE
|
||||
add wave -noupdate -expand -group lsu -group ptwalker /testbench/dut/core/lsu/MEM_VIRTMEM/hptw/HPTWAdr
|
||||
add wave -noupdate -expand -group lsu -group ptwalker /testbench/dut/core/lsu/MEM_VIRTMEM/hptw/PTE
|
||||
add wave -noupdate -expand -group lsu -group ptwalker -expand -group types /testbench/dut/core/lsu/MEM_VIRTMEM/hptw/ITLBMissF
|
||||
add wave -noupdate -expand -group lsu -group ptwalker -expand -group types /testbench/dut/core/lsu/MEM_VIRTMEM/hptw/DTLBMissM
|
||||
add wave -noupdate -expand -group lsu -group ptwalker -expand -group types /testbench/dut/core/lsu/MEM_VIRTMEM/hptw/ITLBWriteF
|
||||
add wave -noupdate -expand -group lsu -group ptwalker -expand -group types /testbench/dut/core/lsu/MEM_VIRTMEM/hptw/DTLBWriteM
|
||||
add wave -noupdate -group itlb /testbench/dut/core/ifu/immu/TLBWrite
|
||||
add wave -noupdate -expand -group lsu -group ptwalker -color Gold /testbench/dut/core/lsu/MEM_VIRTMEM/lsuvirtmem/hptw/WalkerState
|
||||
add wave -noupdate -expand -group lsu -group ptwalker /testbench/dut/core/lsu/MEM_VIRTMEM/lsuvirtmem/hptw/PCF
|
||||
add wave -noupdate -expand -group lsu -group ptwalker /testbench/dut/core/lsu/MEM_VIRTMEM/lsuvirtmem/hptw/HPTWAdr
|
||||
add wave -noupdate -expand -group lsu -group ptwalker /testbench/dut/core/lsu/MEM_VIRTMEM/lsuvirtmem/hptw/HPTWReadPTE
|
||||
add wave -noupdate -expand -group lsu -group ptwalker /testbench/dut/core/lsu/MEM_VIRTMEM/lsuvirtmem/hptw/HPTWAdr
|
||||
add wave -noupdate -expand -group lsu -group ptwalker /testbench/dut/core/lsu/MEM_VIRTMEM/lsuvirtmem/hptw/PTE
|
||||
add wave -noupdate -expand -group lsu -group ptwalker -expand -group types /testbench/dut/core/lsu/MEM_VIRTMEM/lsuvirtmem/hptw/ITLBMissF
|
||||
add wave -noupdate -expand -group lsu -group ptwalker -expand -group types /testbench/dut/core/lsu/MEM_VIRTMEM/lsuvirtmem/hptw/DTLBMissM
|
||||
add wave -noupdate -expand -group lsu -group ptwalker -expand -group types /testbench/dut/core/lsu/MEM_VIRTMEM/lsuvirtmem/hptw/ITLBWriteF
|
||||
add wave -noupdate -expand -group lsu -group ptwalker -expand -group types /testbench/dut/core/lsu/MEM_VIRTMEM/lsuvirtmem/hptw/DTLBWriteM
|
||||
add wave -noupdate -group itlb /testbench/dut/core/ifu/immu/immu//TLBWrite
|
||||
add wave -noupdate -group itlb /testbench/dut/core/ifu/ITLBMissF
|
||||
add wave -noupdate -group itlb /testbench/dut/core/ifu/immu/PhysicalAddress
|
||||
add wave -noupdate -group itlb /testbench/dut/core/ifu/immu/PMAInstrAccessFaultF
|
||||
add wave -noupdate -group itlb /testbench/dut/core/ifu/immu/immu/PhysicalAddress
|
||||
add wave -noupdate -group itlb /testbench/dut/core/ifu/immu/immu/PMAInstrAccessFaultF
|
||||
add wave -noupdate -group plic /testbench/dut/uncore/plic/plic/HCLK
|
||||
add wave -noupdate -group plic /testbench/dut/uncore/plic/plic/HSELPLIC
|
||||
add wave -noupdate -group plic /testbench/dut/uncore/plic/plic/HADDR
|
||||
@ -470,10 +470,10 @@ add wave -noupdate /testbench/dut/core/ifu/BPPredWrongM
|
||||
add wave -noupdate /testbench/dut/core/ifu/InvalidateICacheM
|
||||
add wave -noupdate -expand -group ifu /testbench/dut/core/ifu/PCF
|
||||
add wave -noupdate -expand -group ifu /testbench/dut/core/ifu/PostSpillInstrRawF
|
||||
add wave -noupdate -expand -group ifu -expand -group {Bus FSM} -color Gold /testbench/dut/core/ifu/busfsm/BusCurrState
|
||||
add wave -noupdate -expand -group ifu -expand -group {Bus FSM} -color Gold /testbench/dut/core/ifu/bus/busfsm/BusCurrState
|
||||
add wave -noupdate -expand -group ifu -expand -group {Bus FSM} /testbench/dut/core/ifu/BusStall
|
||||
add wave -noupdate -expand -group ifu -expand -group Spills /testbench/dut/core/ifu/SpillSupport/Spill
|
||||
add wave -noupdate -expand -group ifu -expand -group Spills -color Gold /testbench/dut/core/ifu/SpillSupport/CurrState
|
||||
add wave -noupdate -expand -group ifu -expand -group Spills /testbench/dut/core/ifu/SpillSupport/spillsupport/SpillF
|
||||
add wave -noupdate -expand -group ifu -expand -group Spills -color Gold /testbench/dut/core/ifu/SpillSupport/spillsupport/CurrState
|
||||
add wave -noupdate /testbench/dut/core/lsu.bus.dcache/dcache/VictimTag
|
||||
TreeUpdate [SetDefaultTree]
|
||||
WaveRestoreCursors {{Cursor 6} {5187387 ns} 1} {{Cursor 5} {88705641 ns} 0}
|
||||
|
@ -98,7 +98,7 @@ add wave -noupdate -group Bpred -expand -group {bp wrong} /testbench/dut/core/if
|
||||
add wave -noupdate -group Bpred -expand -group {bp wrong} /testbench/dut/core/ifu/bpred/bpred/BPPredWrongE
|
||||
add wave -noupdate -group Bpred /testbench/dut/core/ifu/bpred/bpred/BPPredWrongE
|
||||
add wave -noupdate -group {instruction pipeline} /testbench/InstrFName
|
||||
add wave -noupdate -group {instruction pipeline} /testbench/dut/core/ifu/icache/FinalInstrRawF
|
||||
add wave -noupdate -group {instruction pipeline} /testbench/dut/core/ifu/bus/icache/FinalInstrRawF
|
||||
add wave -noupdate -group {instruction pipeline} /testbench/dut/core/ifu/InstrD
|
||||
add wave -noupdate -group {instruction pipeline} /testbench/dut/core/ifu/InstrE
|
||||
add wave -noupdate -group {instruction pipeline} /testbench/dut/core/ifu/InstrM
|
||||
@ -174,44 +174,44 @@ add wave -noupdate -group muldiv /testbench/dut/core/mdu/FlushM
|
||||
add wave -noupdate -group muldiv /testbench/dut/core/mdu/FlushW
|
||||
add wave -noupdate -group muldiv /testbench/dut/core/mdu/MulDivResultW
|
||||
add wave -noupdate -group muldiv /testbench/dut/core/mdu/DivBusyE
|
||||
add wave -noupdate -group icache -color Gold /testbench/dut/core/ifu/icache/controller/CurrState
|
||||
add wave -noupdate -group icache /testbench/dut/core/ifu/icache/BasePAdrF
|
||||
add wave -noupdate -group icache /testbench/dut/core/ifu/icache/WayHit
|
||||
add wave -noupdate -group icache /testbench/dut/core/ifu/icache/VictimWay
|
||||
add wave -noupdate -group icache -expand -group {Cache SRAM writes} -group way0 {/testbench/dut/core/ifu/icache/MemWay[0]/WriteEnable}
|
||||
add wave -noupdate -group icache -expand -group {Cache SRAM writes} -group way0 {/testbench/dut/core/ifu/icache/MemWay[0]/SetValid}
|
||||
add wave -noupdate -group icache -expand -group {Cache SRAM writes} -group way0 -label TAG {/testbench/dut/core/ifu/icache/MemWay[0]/CacheTagMem/StoredData}
|
||||
add wave -noupdate -group icache -expand -group {Cache SRAM writes} -group way0 {/testbench/dut/core/ifu/icache/MemWay[0]/ValidBits}
|
||||
add wave -noupdate -group icache -expand -group {Cache SRAM writes} -group way0 -expand -group Way0Word0 {/testbench/dut/core/ifu/icache/MemWay[0]/word[0]/CacheDataMem/StoredData}
|
||||
add wave -noupdate -group icache -expand -group {Cache SRAM writes} -group way0 -expand -group Way0Word0 {/testbench/dut/core/ifu/icache/MemWay[0]/word[0]/CacheDataMem/WriteEnable}
|
||||
add wave -noupdate -group icache -expand -group {Cache SRAM writes} -group way0 -group Way0Word1 {/testbench/dut/core/ifu/icache/MemWay[0]/word[1]/CacheDataMem/StoredData}
|
||||
add wave -noupdate -group icache -expand -group {Cache SRAM writes} -group way0 -group Way0Word1 {/testbench/dut/core/ifu/icache/MemWay[0]/word[1]/CacheDataMem/WriteEnable}
|
||||
add wave -noupdate -group icache -expand -group {Cache SRAM writes} -group way0 -group Way0Word2 {/testbench/dut/core/ifu/icache/MemWay[0]/word[2]/CacheDataMem/WriteEnable}
|
||||
add wave -noupdate -group icache -expand -group {Cache SRAM writes} -group way0 -group Way0Word2 {/testbench/dut/core/ifu/icache/MemWay[0]/word[2]/CacheDataMem/StoredData}
|
||||
add wave -noupdate -group icache -expand -group {Cache SRAM writes} -group way0 -group Way0Word3 {/testbench/dut/core/ifu/icache/MemWay[0]/word[3]/CacheDataMem/WriteEnable}
|
||||
add wave -noupdate -group icache -expand -group {Cache SRAM writes} -group way0 -group Way0Word3 {/testbench/dut/core/ifu/icache/MemWay[0]/word[3]/CacheDataMem/StoredData}
|
||||
add wave -noupdate -group icache /testbench/dut/core/ifu/icache/controller/NextState
|
||||
add wave -noupdate -group icache -color Gold /testbench/dut/core/ifu/bus/icache/controller/CurrState
|
||||
add wave -noupdate -group icache /testbench/dut/core/ifu/bus/icache/BasePAdrF
|
||||
add wave -noupdate -group icache /testbench/dut/core/ifu/bus/icache/WayHit
|
||||
add wave -noupdate -group icache /testbench/dut/core/ifu/bus/icache/VictimWay
|
||||
add wave -noupdate -group icache -expand -group {Cache SRAM writes} -group way0 {/testbench/dut/core/ifu/bus/icache/MemWay[0]/WriteEnable}
|
||||
add wave -noupdate -group icache -expand -group {Cache SRAM writes} -group way0 {/testbench/dut/core/ifu/bus/icache/MemWay[0]/SetValid}
|
||||
add wave -noupdate -group icache -expand -group {Cache SRAM writes} -group way0 -label TAG {/testbench/dut/core/ifu/bus/icache/MemWay[0]/CacheTagMem/StoredData}
|
||||
add wave -noupdate -group icache -expand -group {Cache SRAM writes} -group way0 {/testbench/dut/core/ifu/bus/icache/MemWay[0]/ValidBits}
|
||||
add wave -noupdate -group icache -expand -group {Cache SRAM writes} -group way0 -expand -group Way0Word0 {/testbench/dut/core/ifu/bus/icache/MemWay[0]/word[0]/CacheDataMem/StoredData}
|
||||
add wave -noupdate -group icache -expand -group {Cache SRAM writes} -group way0 -expand -group Way0Word0 {/testbench/dut/core/ifu/bus/icache/MemWay[0]/word[0]/CacheDataMem/WriteEnable}
|
||||
add wave -noupdate -group icache -expand -group {Cache SRAM writes} -group way0 -group Way0Word1 {/testbench/dut/core/ifu/bus/icache/MemWay[0]/word[1]/CacheDataMem/StoredData}
|
||||
add wave -noupdate -group icache -expand -group {Cache SRAM writes} -group way0 -group Way0Word1 {/testbench/dut/core/ifu/bus/icache/MemWay[0]/word[1]/CacheDataMem/WriteEnable}
|
||||
add wave -noupdate -group icache -expand -group {Cache SRAM writes} -group way0 -group Way0Word2 {/testbench/dut/core/ifu/bus/icache/MemWay[0]/word[2]/CacheDataMem/WriteEnable}
|
||||
add wave -noupdate -group icache -expand -group {Cache SRAM writes} -group way0 -group Way0Word2 {/testbench/dut/core/ifu/bus/icache/MemWay[0]/word[2]/CacheDataMem/StoredData}
|
||||
add wave -noupdate -group icache -expand -group {Cache SRAM writes} -group way0 -group Way0Word3 {/testbench/dut/core/ifu/bus/icache/MemWay[0]/word[3]/CacheDataMem/WriteEnable}
|
||||
add wave -noupdate -group icache -expand -group {Cache SRAM writes} -group way0 -group Way0Word3 {/testbench/dut/core/ifu/bus/icache/MemWay[0]/word[3]/CacheDataMem/StoredData}
|
||||
add wave -noupdate -group icache /testbench/dut/core/ifu/bus/icache/controller/NextState
|
||||
add wave -noupdate -group icache /testbench/dut/core/ifu/ITLBMissF
|
||||
add wave -noupdate -group icache /testbench/dut/core/ifu/icache/ITLBWriteF
|
||||
add wave -noupdate -group icache /testbench/dut/core/ifu/icache/ReadLineF
|
||||
add wave -noupdate -group icache /testbench/dut/core/ifu/icache/ReadLineF
|
||||
add wave -noupdate -group icache /testbench/dut/core/ifu/icache/BasePAdrF
|
||||
add wave -noupdate -group icache -expand -group {fsm out and control} /testbench/dut/core/ifu/icache/controller/hit
|
||||
add wave -noupdate -group icache -expand -group {fsm out and control} /testbench/dut/core/ifu/icache/controller/spill
|
||||
add wave -noupdate -group icache -expand -group {fsm out and control} /testbench/dut/core/ifu/icache/controller/ICacheStallF
|
||||
add wave -noupdate -group icache -expand -group {fsm out and control} /testbench/dut/core/ifu/icache/controller/spillSave
|
||||
add wave -noupdate -group icache -expand -group {fsm out and control} /testbench/dut/core/ifu/icache/controller/spillSave
|
||||
add wave -noupdate -group icache -expand -group {fsm out and control} /testbench/dut/core/ifu/icache/controller/CntReset
|
||||
add wave -noupdate -group icache -expand -group {fsm out and control} /testbench/dut/core/ifu/icache/controller/PreCntEn
|
||||
add wave -noupdate -group icache -expand -group {fsm out and control} /testbench/dut/core/ifu/icache/controller/CntEn
|
||||
add wave -noupdate -group icache -expand -group memory /testbench/dut/core/ifu/icache/InstrPAdrF
|
||||
add wave -noupdate -group icache -expand -group memory /testbench/dut/core/ifu/icache/InstrInF
|
||||
add wave -noupdate -group icache -expand -group memory /testbench/dut/core/ifu/icache/controller/FetchCountFlag
|
||||
add wave -noupdate -group icache -expand -group memory /testbench/dut/core/ifu/icache/FetchCount
|
||||
add wave -noupdate -group icache -expand -group memory /testbench/dut/core/ifu/icache/controller/InstrReadF
|
||||
add wave -noupdate -group icache -expand -group memory /testbench/dut/core/ifu/icache/controller/InstrAckF
|
||||
add wave -noupdate -group icache -expand -group memory /testbench/dut/core/ifu/icache/controller/ICacheMemWriteEnable
|
||||
add wave -noupdate -group icache -expand -group memory /testbench/dut/core/ifu/icache/ICacheMemWriteData
|
||||
add wave -noupdate -group icache /testbench/dut/core/ifu/bus/icache/ITLBWriteF
|
||||
add wave -noupdate -group icache /testbench/dut/core/ifu/bus/icache/ReadLineF
|
||||
add wave -noupdate -group icache /testbench/dut/core/ifu/bus/icache/ReadLineF
|
||||
add wave -noupdate -group icache /testbench/dut/core/ifu/bus/icache/BasePAdrF
|
||||
add wave -noupdate -group icache -expand -group {fsm out and control} /testbench/dut/core/ifu/bus/icache/controller/hit
|
||||
add wave -noupdate -group icache -expand -group {fsm out and control} /testbench/dut/core/ifu/bus/icache/controller/spill
|
||||
add wave -noupdate -group icache -expand -group {fsm out and control} /testbench/dut/core/ifu/bus/icache/controller/ICacheStallF
|
||||
add wave -noupdate -group icache -expand -group {fsm out and control} /testbench/dut/core/ifu/bus/icache/controller/spillSave
|
||||
add wave -noupdate -group icache -expand -group {fsm out and control} /testbench/dut/core/ifu/bus/icache/controller/spillSave
|
||||
add wave -noupdate -group icache -expand -group {fsm out and control} /testbench/dut/core/ifu/bus/icache/controller/CntReset
|
||||
add wave -noupdate -group icache -expand -group {fsm out and control} /testbench/dut/core/ifu/bus/icache/controller/PreCntEn
|
||||
add wave -noupdate -group icache -expand -group {fsm out and control} /testbench/dut/core/ifu/bus/icache/controller/CntEn
|
||||
add wave -noupdate -group icache -expand -group memory /testbench/dut/core/ifu/bus/icache/InstrPAdrF
|
||||
add wave -noupdate -group icache -expand -group memory /testbench/dut/core/ifu/bus/icache/InstrInF
|
||||
add wave -noupdate -group icache -expand -group memory /testbench/dut/core/ifu/bus/icache/controller/FetchCountFlag
|
||||
add wave -noupdate -group icache -expand -group memory /testbench/dut/core/ifu/bus/icache/FetchCount
|
||||
add wave -noupdate -group icache -expand -group memory /testbench/dut/core/ifu/bus/icache/controller/InstrReadF
|
||||
add wave -noupdate -group icache -expand -group memory /testbench/dut/core/ifu/bus/icache/controller/InstrAckF
|
||||
add wave -noupdate -group icache -expand -group memory /testbench/dut/core/ifu/bus/icache/controller/ICacheMemWriteEnable
|
||||
add wave -noupdate -group icache -expand -group memory /testbench/dut/core/ifu/bus/icache/ICacheMemWriteData
|
||||
add wave -noupdate -group AHB -color Gold /testbench/dut/core/ebu/BusState
|
||||
add wave -noupdate -group AHB /testbench/dut/core/ebu/NextBusState
|
||||
add wave -noupdate -group AHB -expand -group {input requests} /testbench/dut/core/ebu/AtomicMaskedM
|
||||
|
File diff suppressed because one or more lines are too long
@ -40,7 +40,7 @@ module cvtfp (
|
||||
logic [8:0] i,NormCnt;
|
||||
always_comb begin
|
||||
i = 0;
|
||||
while (~XManE[52-i] && i <= 52) i = i+1; // search for leading one
|
||||
while (~XManE[52-i] & i <= 52) i = i+1; // search for leading one
|
||||
NormCnt = i;
|
||||
end
|
||||
|
||||
|
@ -187,12 +187,12 @@ module fpuaddcvt1 (
|
||||
logic [8:0] j;
|
||||
always_comb begin
|
||||
i = 0;
|
||||
while (~mantissaA[52-i] && $unsigned(i) <= $unsigned(52)) i = i+1; // search for leading one
|
||||
while (~mantissaA[52-i] & $unsigned(i) <= $unsigned(52)) i = i+1; // search for leading one
|
||||
ZP_mantissaA = i;
|
||||
end
|
||||
always_comb begin
|
||||
j = 0;
|
||||
while (~mantissaB[52-j] && $unsigned(j) <= $unsigned(52)) j = j+1; // search for leading one
|
||||
while (~mantissaB[52-j] & $unsigned(j) <= $unsigned(52)) j = j+1; // search for leading one
|
||||
ZP_mantissaB = j;
|
||||
end
|
||||
|
||||
|
@ -85,7 +85,7 @@ module fcvt (
|
||||
logic [8:0] i;
|
||||
always_comb begin
|
||||
i = 0;
|
||||
while (~PosInt[64-1-i] && i < `XLEN) i = i+1; // search for leading one
|
||||
while (~PosInt[64-1-i] & i < `XLEN) i = i+1; // search for leading one
|
||||
LZResP = i[5:0]+1; // compute shift count
|
||||
end
|
||||
|
||||
|
@ -396,7 +396,7 @@ module lzc(
|
||||
logic [8:0] i;
|
||||
always_comb begin
|
||||
i = 0;
|
||||
while (~f[3*`NF+6-i] && $unsigned(i) <= $unsigned(9'd3*9'd`NF+9'd6)) i = i+1; // search for leading one
|
||||
while (~f[3*`NF+6-i] & $unsigned(i) <= $unsigned(9'd3*9'd`NF+9'd6)) i = i+1; // search for leading one
|
||||
NormCntE = i;
|
||||
end
|
||||
endmodule
|
||||
@ -768,7 +768,7 @@ module fmaflags(
|
||||
// 3) 0 * Inf
|
||||
|
||||
assign SigNaN = XSNaNM | YSNaNM | ZSNaNM;
|
||||
assign Invalid = SigNaN | ((XInfM || YInfM) & ZInfM & (PSgnM ^ ZSgnEffM) & ~XNaNM & ~YNaNM) | (XZeroM & YInfM) | (YZeroM & XInfM);
|
||||
assign Invalid = SigNaN | ((XInfM | YInfM) & ZInfM & (PSgnM ^ ZSgnEffM) & ~XNaNM & ~YNaNM) | (XZeroM & YInfM) | (YZeroM & XInfM);
|
||||
|
||||
// Set Overflow flag if the number is too big to be represented
|
||||
// - Don't set the overflow flag if an overflowed result isn't outputed
|
||||
|
@ -129,7 +129,7 @@ module fsm_fpdiv_pipe (
|
||||
end // if (start==1'b0)
|
||||
S65:
|
||||
begin
|
||||
if (op_type==1'b0 && P==1'b0)
|
||||
if (op_type==1'b0 & P==1'b0)
|
||||
begin
|
||||
done = 1'b0;
|
||||
divBusy = 1'b1;
|
||||
@ -146,7 +146,7 @@ module fsm_fpdiv_pipe (
|
||||
sel_muxr = 1'b0;
|
||||
next_state = S1;
|
||||
end
|
||||
else if (op_type==1'b0 && P==1'b1)
|
||||
else if (op_type==1'b0 & P==1'b1)
|
||||
begin
|
||||
done = 1'b0;
|
||||
divBusy = 1'b1;
|
||||
@ -163,7 +163,7 @@ module fsm_fpdiv_pipe (
|
||||
sel_muxr = 1'b0;
|
||||
next_state = S36;
|
||||
end
|
||||
else if (op_type==1'b1 && P==1'b0)
|
||||
else if (op_type==1'b1 & P==1'b0)
|
||||
begin
|
||||
done = 1'b0;
|
||||
divBusy = 1'b1;
|
||||
@ -180,7 +180,7 @@ module fsm_fpdiv_pipe (
|
||||
sel_muxr = 1'b0;
|
||||
next_state = S15;
|
||||
end
|
||||
else if (op_type==1'b1 && P==1'b1)
|
||||
else if (op_type==1'b1 & P==1'b1)
|
||||
begin
|
||||
done = 1'b0;
|
||||
divBusy = 1'b1;
|
||||
|
@ -85,13 +85,15 @@ module ifu (
|
||||
);
|
||||
|
||||
(* mark_debug = "true" *) logic [`XLEN-1:0] PCCorrectE, UnalignedPCNextF, PCNextF;
|
||||
logic misaligned, BranchMisalignedFaultE, BranchMisalignedFaultM, TrapMisalignedFaultM;
|
||||
logic BranchMisalignedFaultE;
|
||||
logic PrivilegedChangePCM;
|
||||
logic IllegalCompInstrD;
|
||||
logic [`XLEN-1:0] PCPlus2or4F, PCLinkD;
|
||||
logic [`XLEN-3:0] PCPlusUpperF;
|
||||
logic CompressedF;
|
||||
logic [31:0] InstrRawD, FinalInstrRawF, InstrRawF;
|
||||
logic [31:0] InstrRawD, InstrRawF;
|
||||
logic [`XLEN-1:0] FinalInstrRawF;
|
||||
|
||||
logic [31:0] InstrE;
|
||||
logic [`XLEN-1:0] PCD;
|
||||
|
||||
@ -114,202 +116,127 @@ module ifu (
|
||||
logic CPUBusy;
|
||||
(* mark_debug = "true" *) logic [31:0] PostSpillInstrRawF;
|
||||
|
||||
localparam integer SPILLTHRESHOLD = `MEM_ICACHE ? `ICACHE_LINELENINBITS/32 : 1;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Spill Support *** add other banners
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
if(`C_SUPPORTED) begin : SpillSupport
|
||||
logic [`XLEN-1:0] PCPlus2F;
|
||||
logic TakeSpillF;
|
||||
logic SpillF;
|
||||
logic SelSpillF, SpillSaveF;
|
||||
logic [15:0] SpillDataLine0;
|
||||
|
||||
// *** PLACE ALL THIS IN A MODULE
|
||||
// this exists only if there are compressed instructions.
|
||||
// reuse PC+2/4 circuitry to avoid needing a second CPA to add 2
|
||||
mux2 #(`XLEN) pcplus2mux(.d0({PCF[`XLEN-1:2], 2'b10}), .d1({PCPlusUpperF, 2'b00}), .s(PCF[1]), .y(PCPlus2F));
|
||||
mux2 #(`XLEN) pcnextspillmux(.d0(PCNextF), .d1(PCPlus2F), .s(SelNextSpillF), .y(PCNextFSpill));
|
||||
mux2 #(`XLEN) pcspillmux(.d0(PCF), .d1(PCPlus2F), .s(SelSpillF), .y(PCFSpill));
|
||||
|
||||
assign SpillF = &PCF[$clog2(SPILLTHRESHOLD)+1:1];
|
||||
|
||||
typedef enum {STATE_SPILL_READY, STATE_SPILL_SPILL} statetype;
|
||||
(* mark_debug = "true" *) statetype CurrState, NextState;
|
||||
|
||||
always_ff @(posedge clk)
|
||||
if (reset) CurrState <= #1 STATE_SPILL_READY;
|
||||
else CurrState <= #1 NextState;
|
||||
|
||||
assign TakeSpillF = SpillF & ~IFUCacheBusStallF;
|
||||
|
||||
always_comb begin
|
||||
case (CurrState)
|
||||
STATE_SPILL_READY: if (TakeSpillF) NextState = STATE_SPILL_SPILL;
|
||||
else NextState = STATE_SPILL_READY;
|
||||
STATE_SPILL_SPILL: if(IFUCacheBusStallF | StallF) NextState = STATE_SPILL_SPILL;
|
||||
else NextState = STATE_SPILL_READY;
|
||||
default: NextState = STATE_SPILL_READY;
|
||||
endcase
|
||||
end
|
||||
|
||||
assign SelSpillF = (CurrState == STATE_SPILL_SPILL);
|
||||
assign SelNextSpillF = (CurrState == STATE_SPILL_READY & TakeSpillF) |
|
||||
(CurrState == STATE_SPILL_SPILL & IFUCacheBusStallF);
|
||||
assign SpillSaveF = (CurrState == STATE_SPILL_READY) & TakeSpillF;
|
||||
|
||||
flopenr #(16) SpillInstrReg(.clk(clk),
|
||||
.en(SpillSaveF),
|
||||
.reset(reset),
|
||||
.d(`MEM_ICACHE ? InstrRawF[15:0] : InstrRawF[31:16]),
|
||||
.q(SpillDataLine0));
|
||||
|
||||
assign PostSpillInstrRawF = SpillF ? {InstrRawF[15:0], SpillDataLine0} : InstrRawF;
|
||||
assign CompressedF = PostSpillInstrRawF[1:0] != 2'b11;
|
||||
|
||||
// end of spill support
|
||||
end else begin : NoSpillSupport // line: SpillSupport
|
||||
assign PCNextFSpill = PCNextF;
|
||||
assign PCFSpill = PCF;
|
||||
assign SelNextSpillF = 0;
|
||||
assign PostSpillInstrRawF = InstrRawF;
|
||||
end
|
||||
|
||||
|
||||
assign PCFExt = {2'b00, PCFSpill};
|
||||
|
||||
mmu #(.TLB_ENTRIES(`ITLB_ENTRIES), .IMMU(1))
|
||||
immu(.PAdr(PCFExt[`PA_BITS-1:0]),
|
||||
.VAdr(PCFSpill),
|
||||
.Size(2'b10),
|
||||
.PTE(PTE),
|
||||
.PageTypeWriteVal(PageType),
|
||||
.TLBWrite(ITLBWriteF),
|
||||
.TLBFlush(ITLBFlushF),
|
||||
.PhysicalAddress(PCPF),
|
||||
.TLBMiss(ITLBMissF),
|
||||
.InstrPageFaultF,
|
||||
.ExecuteAccessF(1'b1),
|
||||
.AtomicAccessM(1'b0),
|
||||
.ReadAccessM(1'b0),
|
||||
.WriteAccessM(1'b0),
|
||||
.LoadAccessFaultM(),
|
||||
.StoreAmoAccessFaultM(),
|
||||
.LoadPageFaultM(), .StoreAmoPageFaultM(),
|
||||
.LoadMisalignedFaultM(), .StoreAmoMisalignedFaultM(),
|
||||
.DisableTranslation(1'b0), // *** is there a better name
|
||||
.Cacheable(CacheableF), .Idempotent(), .AtomicAllowed(),
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Spill Support *** add other banners
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
.clk, .reset,
|
||||
.SATP_REGW,
|
||||
.STATUS_MXR, .STATUS_SUM, .STATUS_MPRV,
|
||||
.STATUS_MPP,
|
||||
.PrivilegeModeW,
|
||||
.InstrAccessFaultF,
|
||||
.PMPCFG_ARRAY_REGW,
|
||||
.PMPADDR_ARRAY_REGW
|
||||
);
|
||||
if(`C_SUPPORTED) begin : SpillSupport
|
||||
|
||||
// conditional
|
||||
// 1. ram // controlled by `MEM_IROM
|
||||
// 2. cache // `MEM_ICACHE
|
||||
// 3. wire pass-through
|
||||
spillsupport spillsupport(.clk, .reset, .StallF, .PCF, .PCPlusUpperF, .PCNextF, .InstrRawF,
|
||||
.IFUCacheBusStallF, .PCNextFSpill, .PCFSpill, .SelNextSpillF,
|
||||
.PostSpillInstrRawF, .CompressedF);
|
||||
end else begin : NoSpillSupport
|
||||
assign PCNextFSpill = PCNextF;
|
||||
assign PCFSpill = PCF;
|
||||
assign PostSpillInstrRawF = InstrRawF;
|
||||
assign {SelNextSpillF, CompressedF} = 0;
|
||||
end
|
||||
|
||||
// If we have `MEM_IROM we don't have the bus controller
|
||||
// otherwise we have the bus controller and either a cache or a passthrough.
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Memory management
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
if(`ZICSR_SUPPORTED == 1) begin : immu
|
||||
mmu #(.TLB_ENTRIES(`ITLB_ENTRIES), .IMMU(1))
|
||||
immu(.clk, .reset, .SATP_REGW, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP,
|
||||
.PrivilegeModeW, .DisableTranslation(1'b0),
|
||||
.PAdr(PCFExt[`PA_BITS-1:0]),
|
||||
.VAdr(PCFSpill),
|
||||
.Size(2'b10),
|
||||
.PTE(PTE),
|
||||
.PageTypeWriteVal(PageType),
|
||||
.TLBWrite(ITLBWriteF),
|
||||
.TLBFlush(ITLBFlushF),
|
||||
.PhysicalAddress(PCPF),
|
||||
.TLBMiss(ITLBMissF),
|
||||
.Cacheable(CacheableF), .Idempotent(), .AtomicAllowed(),
|
||||
.InstrAccessFaultF, .LoadAccessFaultM(), .StoreAmoAccessFaultM(),
|
||||
.InstrPageFaultF, .LoadPageFaultM(), .StoreAmoPageFaultM(),
|
||||
.LoadMisalignedFaultM(), .StoreAmoMisalignedFaultM(),
|
||||
.AtomicAccessM(1'b0),.ExecuteAccessF(1'b1), .WriteAccessM(1'b0), .ReadAccessM(1'b0),
|
||||
.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW);
|
||||
|
||||
// *** make this area look like LSU, including moving I$. Hide localparams in submodules when feasible
|
||||
end else begin
|
||||
assign {ITLBMissF, InstrAccessFaultF} = '0;
|
||||
assign InstrPageFaultF = '0;
|
||||
assign PCPF = PCF;
|
||||
assign CacheableF = '1;
|
||||
end
|
||||
|
||||
localparam integer WORDSPERLINE = `MEM_ICACHE ? `ICACHE_LINELENINBITS/`XLEN : 1;
|
||||
localparam integer LOGWPL = `MEM_ICACHE ? $clog2(WORDSPERLINE) : 1;
|
||||
localparam integer LINELEN = `MEM_ICACHE ? `ICACHE_LINELENINBITS : `XLEN;
|
||||
localparam integer WordCountThreshold = `MEM_ICACHE ? WORDSPERLINE - 1 : 0;
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Memory
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
localparam integer LINEBYTELEN = LINELEN/8;
|
||||
localparam integer OFFSETLEN = $clog2(LINEBYTELEN);
|
||||
logic [`XLEN-1:0] AllInstrRawF;
|
||||
assign InstrRawF = AllInstrRawF[31:0];
|
||||
|
||||
logic [LOGWPL-1:0] WordCount;
|
||||
logic [LINELEN-1:0] ICacheMemWriteData;
|
||||
logic ICacheBusAck;
|
||||
logic [`PA_BITS-1:0] LocalIFUBusAdr;
|
||||
logic [`PA_BITS-1:0] ICacheBusAdr;
|
||||
logic SelUncachedAdr;
|
||||
|
||||
if (`MEM_IROM) begin : irom
|
||||
logic [`XLEN-1:0] FinalInstrRawF_FIXME;
|
||||
|
||||
simpleram #(
|
||||
.BASE(`RAM_BASE), .RANGE(`RAM_RANGE)) ram (
|
||||
.clk,
|
||||
.a(CPUBusy | reset ? PCPF[31:0] : PCNextFSpill[31:0]), // mux is also inside $, have to replay address if CPU is stalled.
|
||||
.we(1'b0),
|
||||
.wd(0), .rd(FinalInstrRawF_FIXME));
|
||||
assign FinalInstrRawF = FinalInstrRawF_FIXME[31:0];
|
||||
assign BusStall = 0;
|
||||
assign IFUBusRead = 0;
|
||||
assign ICacheBusAck = 0;
|
||||
assign SelUncachedAdr = 0;
|
||||
assign IFUBusAdr = 0;
|
||||
dtim irom(.clk, .reset, .CPUBusy, .LSURWM(2'b10), .IEUAdrM(PCPF), .IEUAdrE(PCNextFSpill),
|
||||
.TrapM(1'b0), .FinalWriteDataM(),
|
||||
.ReadDataWordM(AllInstrRawF), .BusStall, .LSUBusWrite(), .LSUBusRead(IFUBusRead),
|
||||
.BusCommittedM(), .ReadDataWordMuxM(), .DCacheStallM(ICacheStallF),
|
||||
.DCacheCommittedM(), .DCacheMiss(ICacheMiss), .DCacheAccess(ICacheAccess));
|
||||
|
||||
end else begin : bus
|
||||
genvar index;
|
||||
for (index = 0; index < WORDSPERLINE; index++) begin:fetchbuffer
|
||||
flopen #(`XLEN) fb(.clk(clk),
|
||||
.en(IFUBusAck & IFUBusRead & (index == WordCount)),
|
||||
.d(IFUBusHRDATA),
|
||||
.q(ICacheMemWriteData[(index+1)*`XLEN-1:index*`XLEN]));
|
||||
end
|
||||
localparam integer WORDSPERLINE = `MEM_ICACHE ? `ICACHE_LINELENINBITS/`XLEN : 1;
|
||||
localparam integer LOGWPL = `MEM_ICACHE ? $clog2(WORDSPERLINE) : 1;
|
||||
localparam integer LINELEN = `MEM_ICACHE ? `ICACHE_LINELENINBITS : `XLEN;
|
||||
localparam integer WordCountThreshold = `MEM_ICACHE ? WORDSPERLINE - 1 : 0;
|
||||
|
||||
assign LocalIFUBusAdr = SelUncachedAdr ? PCPF : ICacheBusAdr;
|
||||
assign IFUBusAdr = ({{`PA_BITS-LOGWPL{1'b0}}, WordCount} << $clog2(`XLEN/8)) + LocalIFUBusAdr;
|
||||
localparam integer LINEBYTELEN = LINELEN/8;
|
||||
localparam integer OFFSETLEN = $clog2(LINEBYTELEN);
|
||||
|
||||
busfsm #(WordCountThreshold, LOGWPL, `MEM_ICACHE)
|
||||
busfsm(.clk, .reset, .IgnoreRequest(ITLBMissF),
|
||||
.LSURWM(2'b10), .DCacheFetchLine(ICacheFetchLine), .DCacheWriteLine(1'b0),
|
||||
.LSUBusAck(IFUBusAck),
|
||||
.CPUBusy, .CacheableM(CacheableF),
|
||||
.BusStall, .LSUBusWrite(), .LSUBusRead(IFUBusRead), .DCacheBusAck(ICacheBusAck),
|
||||
.BusCommittedM(), .SelUncachedAdr(SelUncachedAdr), .WordCount);
|
||||
logic [LOGWPL-1:0] WordCount;
|
||||
logic SelUncachedAdr;
|
||||
logic [LINELEN-1:0] ICacheMemWriteData;
|
||||
logic [`PA_BITS-1:0] LocalIFUBusAdr;
|
||||
logic [`PA_BITS-1:0] ICacheBusAdr;
|
||||
logic ICacheBusAck;
|
||||
|
||||
genvar index;
|
||||
|
||||
|
||||
busdp #(WORDSPERLINE, LINELEN)
|
||||
busdp(.clk, .reset,
|
||||
.LSUBusHRDATA(IFUBusHRDATA), .LSUBusAck(IFUBusAck), .LSUBusWrite(),
|
||||
.LSUBusRead(IFUBusRead), .LSUBusHWDATA(), .LSUBusSize(),
|
||||
.LSUFunct3M(3'b010), .LSUBusAdr(IFUBusAdr), .DCacheBusAdr(ICacheBusAdr),
|
||||
.ReadDataLineSetsM(), .DCacheFetchLine(ICacheFetchLine),
|
||||
.DCacheWriteLine(1'b0), .DCacheBusAck(ICacheBusAck),
|
||||
.DCacheMemWriteData(ICacheMemWriteData), .LSUPAdrM(PCPF),
|
||||
.FinalAMOWriteDataM(), .ReadDataWordM(FinalInstrRawF), .ReadDataWordMuxM(AllInstrRawF),
|
||||
.IgnoreRequest(ITLBMissF), .LSURWM(2'b10), .CPUBusy, .CacheableM(CacheableF),
|
||||
.BusStall, .BusCommittedM());
|
||||
|
||||
if(`MEM_ICACHE) begin : icache
|
||||
logic [1:0] IFURWF;
|
||||
assign IFURWF = CacheableF ? 2'b10 : 2'b00;
|
||||
|
||||
cache #(.LINELEN(`ICACHE_LINELENINBITS),
|
||||
.NUMLINES(`ICACHE_WAYSIZEINBYTES*8/`ICACHE_LINELENINBITS),
|
||||
.NUMWAYS(`ICACHE_NUMWAYS), .DCACHE(0))
|
||||
icache(.clk, .reset, .CPUBusy, .IgnoreRequest(ITLBMissF),
|
||||
.CacheMemWriteData(ICacheMemWriteData), .CacheBusAck(ICacheBusAck),
|
||||
.CacheBusAdr(ICacheBusAdr), .CacheStall(ICacheStallF),
|
||||
.ReadDataWord(FinalInstrRawF), .CacheFetchLine(ICacheFetchLine),
|
||||
.CacheWriteLine(), .ReadDataLineSets(),
|
||||
.CacheMiss(ICacheMiss), .CacheAccess(ICacheAccess),
|
||||
.FinalWriteData('0),
|
||||
.RW(IFURWF),
|
||||
.Atomic(2'b00), .FlushCache(1'b0),
|
||||
.NextAdr(PCNextFSpill[11:0]),
|
||||
.PAdr(PCPF),
|
||||
.CacheCommitted(), .InvalidateCacheM(InvalidateICacheM));
|
||||
|
||||
end else begin : passthrough
|
||||
assign {ICacheFetchLine, ICacheBusAdr, ICacheStallF, FinalInstrRawF} = '0;
|
||||
assign ICacheAccess = CacheableF; assign ICacheMiss = CacheableF;
|
||||
end
|
||||
end
|
||||
|
||||
// *** in same generate with bus
|
||||
if(`MEM_ICACHE) begin : icache
|
||||
logic [1:0] IFURWF;
|
||||
assign IFURWF = CacheableF ? 2'b10 : 2'b00;
|
||||
|
||||
logic [`XLEN-1:0] FinalInstrRawF_FIXME;
|
||||
|
||||
cache #(.LINELEN(`ICACHE_LINELENINBITS),
|
||||
.NUMLINES(`ICACHE_WAYSIZEINBYTES*8/`ICACHE_LINELENINBITS),
|
||||
.NUMWAYS(`ICACHE_NUMWAYS), .DCACHE(0))
|
||||
icache(.clk, .reset, .CPUBusy, .IgnoreRequest(ITLBMissF), .CacheMemWriteData(ICacheMemWriteData) , .CacheBusAck(ICacheBusAck),
|
||||
.CacheBusAdr(ICacheBusAdr), .CacheStall(ICacheStallF), .ReadDataWord(FinalInstrRawF_FIXME),
|
||||
.CacheFetchLine(ICacheFetchLine),
|
||||
.CacheWriteLine(),
|
||||
.ReadDataLineSets(),
|
||||
.CacheMiss(ICacheMiss),
|
||||
.CacheAccess(ICacheAccess),
|
||||
.FinalWriteData('0),
|
||||
.RW(IFURWF),
|
||||
.Atomic(2'b00),
|
||||
.FlushCache(1'b0),
|
||||
.NextAdr(PCNextFSpill[11:0]),
|
||||
.PAdr(PCPF),
|
||||
.CacheCommitted(),
|
||||
.InvalidateCacheM(InvalidateICacheM));
|
||||
|
||||
assign FinalInstrRawF = FinalInstrRawF_FIXME[31:0];
|
||||
end else begin
|
||||
assign ICacheFetchLine = 0;
|
||||
assign ICacheBusAdr = 0;
|
||||
assign ICacheStallF = 0;
|
||||
if(!`MEM_IROM) assign FinalInstrRawF = 0; // *** move
|
||||
assign ICacheAccess = CacheableF;
|
||||
assign ICacheMiss = CacheableF;
|
||||
end
|
||||
|
||||
// branch predictor signal
|
||||
logic SelBPPredF;
|
||||
@ -317,9 +244,6 @@ module ifu (
|
||||
logic [4:0] InstrClassD, InstrClassE;
|
||||
|
||||
|
||||
// select between dcache and direct from the BUS. Always selected if no dcache.
|
||||
// handled in the busfsm.
|
||||
mux2 #(32) UnCachedInstrMux(.d0(FinalInstrRawF), .d1(ICacheMemWriteData[31:0]), .s(SelUncachedAdr), .y(InstrRawF));
|
||||
|
||||
assign IFUCacheBusStallF = ICacheStallF | BusStall;
|
||||
assign IFUStallF = IFUCacheBusStallF | SelNextSpillF;
|
||||
@ -401,22 +325,19 @@ module ifu (
|
||||
|
||||
|
||||
// Misaligned PC logic
|
||||
// Instruction address misalignement only from br/jal(r) instructions.
|
||||
// instruction address misalignment is generated by the target of control flow instructions, not
|
||||
// the fetch itself.
|
||||
assign misaligned = PCNextF[0] | (PCNextF[1] & ~`C_SUPPORTED);
|
||||
// do we really need to have check if the instruction is control flow? Yes
|
||||
// Branches are updated in the execution stage but traps are updated in the memory stage.
|
||||
|
||||
// pipeline misaligned faults to M stage
|
||||
assign BranchMisalignedFaultE = misaligned & PCSrcE; // E-stage (Branch/Jump) misaligned
|
||||
flopenr #(1) InstrMisalginedReg(clk, reset, ~StallM, BranchMisalignedFaultE, BranchMisalignedFaultM);
|
||||
// xret and Traps both cannot produce instruction misaligned.
|
||||
// xret: mepc is an MXLEN-bit read/write register formatted as shown in Figure 3.21.
|
||||
// The low bit of mepc (mepc[0]) is always zero. On implementations that support
|
||||
// only IALIGN=32, the two low bits (mepc[1:0]) are always zero.
|
||||
// Spec 3.1.14
|
||||
// Traps: Can’t happen. The bottom two bits of MTVEC are ignored so the trap always is to a multiple of 4. See 3.1.7 of the privileged spec.
|
||||
assign BranchMisalignedFaultE = (IEUAdrE[1] & ~`C_SUPPORTED) & PCSrcE;
|
||||
flopenr #(1) InstrMisalginedReg(clk, reset, ~StallM, BranchMisalignedFaultE, InstrMisalignedFaultM);
|
||||
// *** Ross Thompson. Check InstrMisalignedAdrM as I believe it is the same as PCF. Should be able to remove.
|
||||
flopenr #(`XLEN) InstrMisalignedAdrReg(clk, reset, ~StallM, PCNextF, InstrMisalignedAdrM);
|
||||
assign TrapMisalignedFaultM = misaligned & PrivilegedChangePCM;
|
||||
assign InstrMisalignedFaultM = BranchMisalignedFaultM; // | TrapMisalignedFaultM; *** put this back in without causing a cyclic path
|
||||
// *** likely leave TrapMisalignedFaultM out of here. Don't implement full spec because
|
||||
// *** it seems silly to have a misaligned trap handler and it adds to the critical path.
|
||||
// ***later revisit more detail
|
||||
|
||||
// Instruction and PC/PCLink pipeline registers
|
||||
flopenr #(32) InstrEReg(clk, reset, ~StallE, FlushE ? nop : InstrD, InstrE);
|
||||
|
100
pipelined/src/ifu/spillsupport.sv
Normal file
100
pipelined/src/ifu/spillsupport.sv
Normal file
@ -0,0 +1,100 @@
|
||||
///////////////////////////////////////////
|
||||
// spillsupport.sv
|
||||
//
|
||||
// Written: Ross Thompson ross1728@gmail.com January 28, 2022
|
||||
// Modified:
|
||||
//
|
||||
// Purpose: allows the IFU to make extra memory request if instruction address crosses
|
||||
// cache line boundaries or if instruction address without a cache crosses
|
||||
// XLEN/8 boundary.
|
||||
//
|
||||
// A component of the Wally configurable RISC-V project.
|
||||
//
|
||||
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
|
||||
//
|
||||
// MIT LICENSE
|
||||
// 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 spillsupport (
|
||||
input logic clk,
|
||||
input logic reset,
|
||||
input logic StallF,
|
||||
input logic [`XLEN-1:0] PCF,
|
||||
input logic [`XLEN-3:0] PCPlusUpperF,
|
||||
input logic [`XLEN-1:0] PCNextF,
|
||||
logic [31:0] InstrRawF,
|
||||
input logic IFUCacheBusStallF,
|
||||
output logic [`XLEN-1:0] PCNextFSpill,
|
||||
output logic [`XLEN-1:0] PCFSpill,
|
||||
output logic SelNextSpillF,
|
||||
output logic [31:0] PostSpillInstrRawF,
|
||||
output logic CompressedF);
|
||||
|
||||
|
||||
localparam integer SPILLTHRESHOLD = `MEM_ICACHE ? `ICACHE_LINELENINBITS/32 : 1;
|
||||
logic [`XLEN-1:0] PCPlus2F;
|
||||
logic TakeSpillF;
|
||||
logic SpillF;
|
||||
logic SelSpillF, SpillSaveF;
|
||||
logic [15:0] SpillDataLine0;
|
||||
|
||||
// *** PLACE ALL THIS IN A MODULE
|
||||
// this exists only if there are compressed instructions.
|
||||
// reuse PC+2/4 circuitry to avoid needing a second CPA to add 2
|
||||
mux2 #(`XLEN) pcplus2mux(.d0({PCF[`XLEN-1:2], 2'b10}), .d1({PCPlusUpperF, 2'b00}), .s(PCF[1]), .y(PCPlus2F));
|
||||
mux2 #(`XLEN) pcnextspillmux(.d0(PCNextF), .d1(PCPlus2F), .s(SelNextSpillF), .y(PCNextFSpill));
|
||||
mux2 #(`XLEN) pcspillmux(.d0(PCF), .d1(PCPlus2F), .s(SelSpillF), .y(PCFSpill));
|
||||
|
||||
assign SpillF = &PCF[$clog2(SPILLTHRESHOLD)+1:1];
|
||||
|
||||
typedef enum {STATE_SPILL_READY, STATE_SPILL_SPILL} statetype;
|
||||
(* mark_debug = "true" *) statetype CurrState, NextState;
|
||||
|
||||
always_ff @(posedge clk)
|
||||
if (reset) CurrState <= #1 STATE_SPILL_READY;
|
||||
else CurrState <= #1 NextState;
|
||||
|
||||
assign TakeSpillF = SpillF & ~IFUCacheBusStallF;
|
||||
|
||||
always_comb begin
|
||||
case (CurrState)
|
||||
STATE_SPILL_READY: if (TakeSpillF) NextState = STATE_SPILL_SPILL;
|
||||
else NextState = STATE_SPILL_READY;
|
||||
STATE_SPILL_SPILL: if(IFUCacheBusStallF | StallF) NextState = STATE_SPILL_SPILL;
|
||||
else NextState = STATE_SPILL_READY;
|
||||
default: NextState = STATE_SPILL_READY;
|
||||
endcase
|
||||
end
|
||||
|
||||
assign SelSpillF = (CurrState == STATE_SPILL_SPILL);
|
||||
assign SelNextSpillF = (CurrState == STATE_SPILL_READY & TakeSpillF) |
|
||||
(CurrState == STATE_SPILL_SPILL & IFUCacheBusStallF);
|
||||
assign SpillSaveF = (CurrState == STATE_SPILL_READY) & TakeSpillF;
|
||||
|
||||
flopenr #(16) SpillInstrReg(.clk(clk),
|
||||
.en(SpillSaveF),
|
||||
.reset(reset),
|
||||
.d(`MEM_ICACHE ? InstrRawF[15:0] : InstrRawF[31:16]),
|
||||
.q(SpillDataLine0));
|
||||
|
||||
assign PostSpillInstrRawF = SpillF ? {InstrRawF[15:0], SpillDataLine0} : InstrRawF;
|
||||
assign CompressedF = PostSpillInstrRawF[1:0] != 2'b11;
|
||||
|
||||
endmodule
|
59
pipelined/src/lsu/atomic.sv
Normal file
59
pipelined/src/lsu/atomic.sv
Normal file
@ -0,0 +1,59 @@
|
||||
///////////////////////////////////////////
|
||||
// atomic.sv
|
||||
//
|
||||
// Written: Ross Thompson ross1728@gmail.com January 31, 2022
|
||||
// Modified:
|
||||
//
|
||||
// Purpose: atomic data path.
|
||||
//
|
||||
// A component of the Wally configurable RISC-V project.
|
||||
//
|
||||
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
|
||||
//
|
||||
// MIT LICENSE
|
||||
// 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 atomic (
|
||||
input logic clk,
|
||||
input logic reset, FlushW, CPUBusy,
|
||||
input logic [`XLEN-1:0] ReadDataM,
|
||||
input logic [`XLEN-1:0] WriteDataM,
|
||||
input logic [`PA_BITS-1:0] LSUPAdrM,
|
||||
input logic [6:0] LSUFunct7M,
|
||||
input logic [2:0] LSUFunct3M,
|
||||
input logic [1:0] LSUAtomicM,
|
||||
input logic [1:0] PreLSURWM,
|
||||
input logic IgnoreRequest,
|
||||
input logic DTLBMissM,
|
||||
output logic [`XLEN-1:0] FinalAMOWriteDataM,
|
||||
output logic SquashSCW,
|
||||
output logic [1:0] LSURWM);
|
||||
|
||||
logic [`XLEN-1:0] AMOResult;
|
||||
logic MemReadM;
|
||||
|
||||
amoalu amoalu(.srca(ReadDataM), .srcb(WriteDataM), .funct(LSUFunct7M), .width(LSUFunct3M[1:0]),
|
||||
.result(AMOResult));
|
||||
mux2 #(`XLEN) wdmux(WriteDataM, AMOResult, LSUAtomicM[1], FinalAMOWriteDataM);
|
||||
assign MemReadM = PreLSURWM[1] & ~(IgnoreRequest) & ~DTLBMissM;
|
||||
lrsc lrsc(.clk, .reset, .FlushW, .CPUBusy, .MemReadM, .PreLSURWM, .LSUAtomicM, .LSUPAdrM,
|
||||
.SquashSCW, .LSURWM);
|
||||
|
||||
endmodule
|
101
pipelined/src/lsu/busdp.sv
Normal file
101
pipelined/src/lsu/busdp.sv
Normal file
@ -0,0 +1,101 @@
|
||||
///////////////////////////////////////////
|
||||
// busdp.sv
|
||||
//
|
||||
// Written: Ross Thompson ross1728@gmail.com January 30, 2022
|
||||
// Modified:
|
||||
//
|
||||
// Purpose: Bus data path.
|
||||
// Bus Side logic
|
||||
// register the fetch data from the next level of memory.
|
||||
// This register should be necessary for timing. There is no register in the uncore or
|
||||
// ahblite controller between the memories and this cache.
|
||||
//
|
||||
// A component of the Wally configurable RISC-V project.
|
||||
//
|
||||
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
|
||||
//
|
||||
// MIT LICENSE
|
||||
// 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 busdp #(parameter WORDSPERLINE, parameter LINELEN)
|
||||
(
|
||||
input logic clk, reset,
|
||||
// bus interface
|
||||
input logic [`XLEN-1:0] LSUBusHRDATA,
|
||||
input logic LSUBusAck,
|
||||
output logic LSUBusWrite,
|
||||
output logic LSUBusRead,
|
||||
output logic [`XLEN-1:0] LSUBusHWDATA,
|
||||
output logic [2:0] LSUBusSize,
|
||||
input logic [2:0] LSUFunct3M,
|
||||
output logic [`PA_BITS-1:0] LSUBusAdr,
|
||||
|
||||
// cache interface.
|
||||
input logic [`PA_BITS-1:0] DCacheBusAdr,
|
||||
input var logic [`XLEN-1:0] ReadDataLineSetsM [WORDSPERLINE-1:0],
|
||||
input logic DCacheFetchLine,
|
||||
input logic DCacheWriteLine,
|
||||
output logic DCacheBusAck,
|
||||
output logic [LINELEN-1:0] DCacheMemWriteData,
|
||||
|
||||
// lsu interface
|
||||
input logic [`PA_BITS-1:0] LSUPAdrM,
|
||||
input logic [`XLEN-1:0] FinalAMOWriteDataM,
|
||||
input logic [`XLEN-1:0] ReadDataWordM,
|
||||
output logic [`XLEN-1:0] ReadDataWordMuxM,
|
||||
input logic IgnoreRequest,
|
||||
input logic [1:0] LSURWM,
|
||||
input logic CPUBusy,
|
||||
input logic CacheableM,
|
||||
output logic BusStall,
|
||||
output logic BusCommittedM);
|
||||
|
||||
|
||||
localparam integer WordCountThreshold = `MEM_DCACHE ? WORDSPERLINE - 1 : 0;
|
||||
localparam integer LOGWPL = `MEM_DCACHE ? $clog2(WORDSPERLINE) : 1;
|
||||
|
||||
logic SelUncachedAdr;
|
||||
logic [`XLEN-1:0] PreLSUBusHWDATA;
|
||||
logic [`PA_BITS-1:0] LocalLSUBusAdr;
|
||||
logic [LOGWPL-1:0] WordCount;
|
||||
genvar index;
|
||||
|
||||
for (index = 0; index < WORDSPERLINE; index++) begin:fetchbuffer
|
||||
flopen #(`XLEN) fb(.clk, .en(LSUBusAck & LSUBusRead & (index == WordCount)),
|
||||
.d(LSUBusHRDATA), .q(DCacheMemWriteData[(index+1)*`XLEN-1:index*`XLEN]));
|
||||
end
|
||||
|
||||
|
||||
mux2 #(`PA_BITS) localadrmux(DCacheBusAdr, LSUPAdrM, SelUncachedAdr, LocalLSUBusAdr);
|
||||
assign LSUBusAdr = ({{`PA_BITS-LOGWPL{1'b0}}, WordCount} << $clog2(`XLEN/8)) + LocalLSUBusAdr;
|
||||
assign PreLSUBusHWDATA = ReadDataLineSetsM[WordCount]; // only in lsu, not ifu
|
||||
mux2 #(`XLEN) lsubushwdatamux(.d0(PreLSUBusHWDATA), .d1(FinalAMOWriteDataM),
|
||||
.s(SelUncachedAdr), .y(LSUBusHWDATA));
|
||||
mux2 #(3) lsubussizemux(.d0(`XLEN == 32 ? 3'b010 : 3'b011), .d1(LSUFunct3M),
|
||||
.s(SelUncachedAdr), .y(LSUBusSize));
|
||||
mux2 #(`XLEN) UnCachedDataMux(.d0(ReadDataWordM), .d1(DCacheMemWriteData[`XLEN-1:0]),
|
||||
.s(SelUncachedAdr), .y(ReadDataWordMuxM));
|
||||
|
||||
busfsm #(WordCountThreshold, LOGWPL, `MEM_DCACHE)
|
||||
busfsm(.clk, .reset, .IgnoreRequest, .LSURWM, .DCacheFetchLine, .DCacheWriteLine,
|
||||
.LSUBusAck, .CPUBusy, .CacheableM, .BusStall, .LSUBusWrite, .LSUBusRead,
|
||||
.DCacheBusAck, .BusCommittedM, .SelUncachedAdr, .WordCount);
|
||||
|
||||
endmodule
|
@ -33,23 +33,23 @@
|
||||
|
||||
module busfsm #(parameter integer WordCountThreshold,
|
||||
parameter integer LOGWPL, parameter logic CacheEnabled )
|
||||
(input logic clk,
|
||||
input logic reset,
|
||||
(input logic clk,
|
||||
input logic reset,
|
||||
|
||||
input logic IgnoreRequest,
|
||||
input logic [1:0] LSURWM,
|
||||
input logic DCacheFetchLine,
|
||||
input logic DCacheWriteLine,
|
||||
input logic LSUBusAck,
|
||||
input logic CPUBusy,
|
||||
input logic CacheableM,
|
||||
input logic IgnoreRequest,
|
||||
input logic [1:0] LSURWM,
|
||||
input logic DCacheFetchLine,
|
||||
input logic DCacheWriteLine,
|
||||
input logic LSUBusAck,
|
||||
input logic CPUBusy,
|
||||
input logic CacheableM,
|
||||
|
||||
output logic BusStall,
|
||||
output logic LSUBusWrite,
|
||||
output logic LSUBusRead,
|
||||
output logic DCacheBusAck,
|
||||
output logic BusCommittedM,
|
||||
output logic SelUncachedAdr,
|
||||
output logic BusStall,
|
||||
output logic LSUBusWrite,
|
||||
output logic LSUBusRead,
|
||||
output logic DCacheBusAck,
|
||||
output logic BusCommittedM,
|
||||
output logic SelUncachedAdr,
|
||||
output logic [LOGWPL-1:0] WordCount);
|
||||
|
||||
|
||||
|
65
pipelined/src/lsu/dtim.sv
Normal file
65
pipelined/src/lsu/dtim.sv
Normal file
@ -0,0 +1,65 @@
|
||||
///////////////////////////////////////////
|
||||
// dtim.sv
|
||||
//
|
||||
// Written: Ross Thompson ross1728@gmail.com January 30, 2022
|
||||
// Modified:
|
||||
//
|
||||
// Purpose: simple memory with bus or cache.
|
||||
// A component of the Wally configurable RISC-V project.
|
||||
//
|
||||
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
|
||||
//
|
||||
// MIT LICENSE
|
||||
// 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 dtim(
|
||||
input logic clk, reset,
|
||||
input logic CPUBusy,
|
||||
input logic [1:0] LSURWM,
|
||||
input logic [`XLEN-1:0] IEUAdrM,
|
||||
input logic [`XLEN-1:0] IEUAdrE,
|
||||
input logic TrapM,
|
||||
input logic [`XLEN-1:0] FinalWriteDataM,
|
||||
output logic [`XLEN-1:0] ReadDataWordM,
|
||||
output logic BusStall,
|
||||
output logic LSUBusWrite,
|
||||
output logic LSUBusRead,
|
||||
output logic BusCommittedM,
|
||||
output logic [`XLEN-1:0] ReadDataWordMuxM,
|
||||
output logic DCacheStallM,
|
||||
output logic DCacheCommittedM,
|
||||
output logic DCacheMiss,
|
||||
output logic DCacheAccess);
|
||||
|
||||
simpleram #(.BASE(`RAM_BASE), .RANGE(`RAM_RANGE)) ram (
|
||||
.clk,
|
||||
.a(CPUBusy | LSURWM[0] | reset ? IEUAdrM[31:0] : IEUAdrE[31:0]),
|
||||
.we(LSURWM[0] & ~TrapM), // have to ignore write if Trap.
|
||||
.wd(FinalWriteDataM), .rd(ReadDataWordM));
|
||||
|
||||
// since we have a local memory the bus connections are all disabled.
|
||||
// There are no peripherals supported.
|
||||
assign {BusStall, LSUBusWrite, LSUBusRead, BusCommittedM} = '0;
|
||||
assign ReadDataWordMuxM = ReadDataWordM;
|
||||
assign {DCacheStallM, DCacheCommittedM} = '0;
|
||||
assign {DCacheMiss, DCacheAccess} = '0;
|
||||
|
||||
endmodule
|
||||
|
@ -33,129 +33,99 @@
|
||||
`include "wally-config.vh"
|
||||
|
||||
module lsu (
|
||||
input logic clk, reset,
|
||||
input logic StallM, FlushM, StallW, FlushW,
|
||||
output logic LSUStallM,
|
||||
input logic clk, reset,
|
||||
input logic StallM, FlushM, StallW, FlushW,
|
||||
output logic LSUStallM,
|
||||
// connected to cpu (controls)
|
||||
input logic [1:0] MemRWM,
|
||||
input logic [2:0] Funct3M,
|
||||
input logic [6:0] Funct7M,
|
||||
input logic [1:0] AtomicM,
|
||||
input logic TrapM,
|
||||
input logic FlushDCacheM,
|
||||
output logic CommittedM,
|
||||
output logic SquashSCW,
|
||||
output logic DCacheMiss,
|
||||
output logic DCacheAccess,
|
||||
input logic [1:0] MemRWM,
|
||||
input logic [2:0] Funct3M,
|
||||
input logic [6:0] Funct7M,
|
||||
input logic [1:0] AtomicM,
|
||||
input logic TrapM,
|
||||
input logic FlushDCacheM,
|
||||
output logic CommittedM,
|
||||
output logic SquashSCW,
|
||||
output logic DCacheMiss,
|
||||
output logic DCacheAccess,
|
||||
// address and write data
|
||||
input logic [`XLEN-1:0] IEUAdrE,
|
||||
(* mark_debug = "true" *)output logic [`XLEN-1:0] IEUAdrM,
|
||||
input logic [`XLEN-1:0] WriteDataM,
|
||||
output logic [`XLEN-1:0] ReadDataM,
|
||||
input logic [`XLEN-1:0] IEUAdrE,
|
||||
(* mark_debug = "true" *)output logic [`XLEN-1:0] IEUAdrM,
|
||||
input logic [`XLEN-1:0] WriteDataM,
|
||||
output logic [`XLEN-1:0] ReadDataM,
|
||||
// cpu privilege
|
||||
input logic [1:0] PrivilegeModeW,
|
||||
input logic DTLBFlushM,
|
||||
input logic [1:0] PrivilegeModeW,
|
||||
input logic DTLBFlushM,
|
||||
// faults
|
||||
output logic LoadPageFaultM, StoreAmoPageFaultM,
|
||||
output logic LoadMisalignedFaultM, LoadAccessFaultM,
|
||||
output logic LoadPageFaultM, StoreAmoPageFaultM,
|
||||
output logic LoadMisalignedFaultM, LoadAccessFaultM,
|
||||
// cpu hazard unit (trap)
|
||||
output logic StoreAmoMisalignedFaultM, StoreAmoAccessFaultM,
|
||||
// connect to ahb
|
||||
(* mark_debug = "true" *) output logic [`PA_BITS-1:0] LSUBusAdr,
|
||||
(* mark_debug = "true" *) output logic LSUBusRead,
|
||||
(* mark_debug = "true" *) output logic LSUBusWrite,
|
||||
(* mark_debug = "true" *) input logic LSUBusAck,
|
||||
(* mark_debug = "true" *) input logic [`XLEN-1:0] LSUBusHRDATA,
|
||||
(* mark_debug = "true" *) output logic [`XLEN-1:0] LSUBusHWDATA,
|
||||
(* mark_debug = "true" *) output logic [2:0] LSUBusSize,
|
||||
// page table walker
|
||||
input logic [`XLEN-1:0] SATP_REGW, // from csr
|
||||
input logic STATUS_MXR, STATUS_SUM, STATUS_MPRV,
|
||||
input logic [1:0] STATUS_MPP,
|
||||
input logic [`XLEN-1:0] PCF,
|
||||
input logic ITLBMissF,
|
||||
output logic [`XLEN-1:0] PTE,
|
||||
output logic [1:0] PageType,
|
||||
output logic ITLBWriteF,
|
||||
input var logic [7:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES-1:0],
|
||||
input var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW[`PMP_ENTRIES-1:0] // *** this one especially has a large note attached to it in pmpchecker.
|
||||
output logic StoreAmoMisalignedFaultM, StoreAmoAccessFaultM,
|
||||
// connect to ahb
|
||||
(* mark_debug = "true" *) output logic [`PA_BITS-1:0] LSUBusAdr,
|
||||
(* mark_debug = "true" *) output logic LSUBusRead,
|
||||
(* mark_debug = "true" *) output logic LSUBusWrite,
|
||||
(* mark_debug = "true" *) input logic LSUBusAck,
|
||||
(* mark_debug = "true" *) input logic [`XLEN-1:0] LSUBusHRDATA,
|
||||
(* mark_debug = "true" *) output logic [`XLEN-1:0] LSUBusHWDATA,
|
||||
(* mark_debug = "true" *) output logic [2:0] LSUBusSize,
|
||||
// page table walker
|
||||
input logic [`XLEN-1:0] SATP_REGW, // from csr
|
||||
input logic STATUS_MXR, STATUS_SUM, STATUS_MPRV,
|
||||
input logic [1:0] STATUS_MPP,
|
||||
input logic [`XLEN-1:0] PCF,
|
||||
input logic ITLBMissF,
|
||||
output logic [`XLEN-1:0] PTE,
|
||||
output logic [1:0] PageType,
|
||||
output logic ITLBWriteF,
|
||||
input var logic [7:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES-1:0],
|
||||
input var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW[`PMP_ENTRIES-1:0] // *** this one especially has a large note attached to it in pmpchecker.
|
||||
);
|
||||
|
||||
logic [`PA_BITS-1:0] LSUPAdrM; // from mmu to dcache
|
||||
logic [`XLEN+1:0] IEUAdrExtM;
|
||||
logic DTLBMissM;
|
||||
logic DTLBWriteM;
|
||||
logic [1:0] LSURWM;
|
||||
logic [1:0] PreLSURWM;
|
||||
logic [2:0] LSUFunct3M;
|
||||
logic [6:0] LSUFunct7M;
|
||||
logic [1:0] LSUAtomicM;
|
||||
(* mark_debug = "true" *) logic [`PA_BITS-1:0] PreLSUPAdrM, LocalLSUBusAdr;
|
||||
logic [11:0] PreLSUAdrE, LSUAdrE;
|
||||
logic CPUBusy;
|
||||
logic MemReadM;
|
||||
logic DCacheStallM;
|
||||
logic CacheableM;
|
||||
logic SelHPTW;
|
||||
logic BusStall;
|
||||
logic InterlockStall;
|
||||
logic IgnoreRequest;
|
||||
logic BusCommittedM, DCacheCommittedM;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// HPTW and Interlock FSM (only needed if VM supported)
|
||||
// MMU include PMP and is needed if any privileged supported
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
logic [`XLEN+1:0] IEUAdrExtM;
|
||||
logic [`PA_BITS-1:0] LSUPAdrM;
|
||||
logic DTLBMissM;
|
||||
logic DTLBWriteM;
|
||||
logic [1:0] LSURWM;
|
||||
logic [1:0] PreLSURWM;
|
||||
logic [2:0] LSUFunct3M;
|
||||
logic [6:0] LSUFunct7M;
|
||||
logic [1:0] LSUAtomicM;
|
||||
(* mark_debug = "true" *) logic [`PA_BITS-1:0] PreLSUPAdrM;
|
||||
logic [11:0] PreLSUAdrE, LSUAdrE;
|
||||
logic CPUBusy;
|
||||
logic DCacheStallM;
|
||||
logic CacheableM;
|
||||
logic SelHPTW;
|
||||
logic BusStall;
|
||||
logic InterlockStall;
|
||||
logic IgnoreRequest;
|
||||
logic BusCommittedM, DCacheCommittedM;
|
||||
|
||||
flopenrc #(`XLEN) AddressMReg(clk, reset, FlushM, ~StallM, IEUAdrE, IEUAdrM);
|
||||
assign IEUAdrExtM = {2'b00, IEUAdrM};
|
||||
|
||||
assign LSUStallM = DCacheStallM | InterlockStall | BusStall;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// HPTW and Interlock FSM (only needed if VM supported)
|
||||
// MMU include PMP and is needed if any privileged supported
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
if(`MEM_VIRTMEM) begin : MEM_VIRTMEM
|
||||
// *** encapsulate as lsuvirtmem
|
||||
logic AnyCPUReqM;
|
||||
logic [`PA_BITS-1:0] HPTWAdr;
|
||||
logic HPTWRead;
|
||||
logic [2:0] HPTWSize;
|
||||
logic SelReplayCPURequest;
|
||||
lsuvirtmem lsuvirtmem(.clk, .reset, .StallW, .MemRWM, .AtomicM, .ITLBMissF, .ITLBWriteF,
|
||||
.DTLBMissM, .DTLBWriteM, .TrapM, .DCacheStallM, .SATP_REGW, .PCF,
|
||||
.ReadDataM, .Funct3M, .LSUFunct3M, .Funct7M, .LSUFunct7M, .IEUAdrM,
|
||||
.IEUAdrExtM, .PTE, .PageType, .PreLSURWM, .LSUAtomicM, .IEUAdrE,
|
||||
.LSUAdrE, .PreLSUPAdrM, .CPUBusy, .InterlockStall, .SelHPTW,
|
||||
.IgnoreRequest);
|
||||
|
||||
assign AnyCPUReqM = (|MemRWM) | (|AtomicM);
|
||||
|
||||
interlockfsm interlockfsm (.clk, .reset, .AnyCPUReqM, .ITLBMissF, .ITLBWriteF,
|
||||
.DTLBMissM, .DTLBWriteM, .TrapM, .DCacheStallM,
|
||||
.InterlockStall, .SelReplayCPURequest, .SelHPTW,
|
||||
.IgnoreRequest);
|
||||
|
||||
hptw hptw(.clk, .reset, .SATP_REGW, .PCF, .IEUAdrM,
|
||||
.ITLBMissF(ITLBMissF & ~TrapM),
|
||||
.DTLBMissM(DTLBMissM & ~TrapM),
|
||||
.PTE, .PageType, .ITLBWriteF, .DTLBWriteM,
|
||||
.HPTWReadPTE(ReadDataM),
|
||||
.DCacheStallM, .HPTWAdr, .HPTWRead, .HPTWSize);
|
||||
|
||||
// arbiter between IEU and hptw
|
||||
|
||||
// multiplex the outputs to LSU
|
||||
mux2 #(2) rwmux(MemRWM, {HPTWRead, 1'b0}, SelHPTW, PreLSURWM);
|
||||
mux2 #(3) sizemux(Funct3M, HPTWSize, SelHPTW, LSUFunct3M);
|
||||
mux2 #(7) funct7mux(Funct7M, 7'b0, SelHPTW, LSUFunct7M);
|
||||
mux2 #(2) atomicmux(AtomicM, 2'b00, SelHPTW, LSUAtomicM);
|
||||
mux2 #(12) adremux(IEUAdrE[11:0], HPTWAdr[11:0], SelHPTW, PreLSUAdrE);
|
||||
mux2 #(12) replaymux(PreLSUAdrE, IEUAdrM[11:0], SelReplayCPURequest, LSUAdrE); // replay cpu request after hptw.
|
||||
mux2 #(`PA_BITS) lsupadrmux(IEUAdrExtM[`PA_BITS-1:0], HPTWAdr, SelHPTW, PreLSUPAdrM);
|
||||
|
||||
// always block interrupts when using the hardware page table walker.
|
||||
assign CPUBusy = StallW & ~SelHPTW;
|
||||
|
||||
end // if (`MEM_VIRTMEM)
|
||||
else begin
|
||||
end else begin
|
||||
assign {InterlockStall, SelHPTW, PTE, PageType, DTLBWriteM, ITLBWriteF} = '0;
|
||||
assign IgnoreRequest = TrapM;
|
||||
assign CPUBusy = StallW;
|
||||
assign LSUAdrE = PreLSUAdrE; assign LSUFunct3M = Funct3M; assign LSUFunct7M = Funct7M; assign LSUAtomicM = AtomicM;
|
||||
assign PreLSURWM = MemRWM; assign PreLSUAdrE = IEUAdrE[11:0]; assign PreLSUPAdrM = IEUAdrExtM;
|
||||
assign IgnoreRequest = TrapM; assign CPUBusy = StallW; assign PreLSURWM = MemRWM;
|
||||
assign LSUAdrE = PreLSUAdrE; assign PreLSUAdrE = IEUAdrE[11:0];
|
||||
assign PreLSUPAdrM = IEUAdrExtM[`PA_BITS-1:0];
|
||||
assign LSUFunct3M = Funct3M; assign LSUFunct7M = Funct7M; assign LSUAtomicM = AtomicM;
|
||||
end
|
||||
|
||||
|
||||
// **** look into this confusing signal.
|
||||
// This signal is confusing. CommittedM tells the CPU's trap unit the current instruction
|
||||
// in the memory stage is a memory operaton and that memory operation is either completed
|
||||
@ -181,168 +151,91 @@ module lsu (
|
||||
.TLBFlush(DTLBFlushM),
|
||||
.PhysicalAddress(LSUPAdrM),
|
||||
.TLBMiss(DTLBMissM),
|
||||
.Cacheable(CacheableM),
|
||||
.Idempotent(), .AtomicAllowed(),
|
||||
.Cacheable(CacheableM), .Idempotent(), .AtomicAllowed(),
|
||||
.InstrAccessFaultF(), .LoadAccessFaultM, .StoreAmoAccessFaultM,
|
||||
.InstrPageFaultF(),.LoadPageFaultM, .StoreAmoPageFaultM,
|
||||
.LoadMisalignedFaultM, .StoreAmoMisalignedFaultM,
|
||||
.AtomicAccessM(|LSUAtomicM), .ExecuteAccessF(1'b0), // **** change this to just use PreLSURWM
|
||||
.WriteAccessM(PreLSURWM[0]), .ReadAccessM(PreLSURWM[1]),
|
||||
.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW
|
||||
);
|
||||
|
||||
// *** lsumisaligned lsumisaligned(Funct3M, IEUAdrM, MemRW, LoadMisalignedFaultM, StoreAmoMisalignedFaultM);
|
||||
// *** lump into lsumislaigned module
|
||||
// Determine if an Unaligned access is taking place
|
||||
// hptw guarantees alignment, only check inputs from IEU.
|
||||
|
||||
// *** modify MMU to put out LoadMisalignedFault and StoreMisalignedFault rather than DataMisalignedM
|
||||
|
||||
.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW);
|
||||
|
||||
end else begin
|
||||
assign {DTLBMissM, LoadAccessFaultM, StoreAmoAccessFaultM, LoadMisalignedFaultM, StoreAmoMisalignedFaultM} = '0;
|
||||
assign LSUPAdrM = PreLSUPAdrM;
|
||||
assign CacheableM = 1;
|
||||
assign {LoadPageFaultM, StoreAmoPageFaultM} = '0;
|
||||
assign LSUPAdrM = PreLSUPAdrM;
|
||||
assign CacheableM = '1;
|
||||
end
|
||||
assign LSUStallM = DCacheStallM | InterlockStall | BusStall;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Hart Memory System
|
||||
// Either Data Cache or Data Tightly Integrated Memory or just bus interface
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
localparam integer WORDSPERLINE = `MEM_DCACHE ? `DCACHE_LINELENINBITS/`XLEN : 1;
|
||||
localparam integer LOGWPL = `MEM_DCACHE ? $clog2(WORDSPERLINE) : 1;
|
||||
localparam integer LINELEN = `MEM_DCACHE ? `DCACHE_LINELENINBITS : `XLEN;
|
||||
localparam integer WordCountThreshold = `MEM_DCACHE ? WORDSPERLINE - 1 : 0;
|
||||
|
||||
localparam integer LINEBYTELEN = LINELEN/8;
|
||||
localparam integer OFFSETLEN = $clog2(LINEBYTELEN);
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
logic [`XLEN-1:0] FinalAMOWriteDataM, FinalWriteDataM;
|
||||
(* mark_debug = "true" *) logic [`XLEN-1:0] PreLSUBusHWDATA;
|
||||
logic [`XLEN-1:0] ReadDataWordM;
|
||||
logic [LINELEN-1:0] DCacheMemWriteData;
|
||||
logic [`XLEN-1:0] ReadDataWordMuxM;
|
||||
logic [`PA_BITS-1:0] DCacheBusAdr;
|
||||
logic [`XLEN-1:0] ReadDataLineSetsM [WORDSPERLINE-1:0];
|
||||
logic DCacheWriteLine;
|
||||
logic DCacheFetchLine;
|
||||
logic DCacheBusAck;
|
||||
logic SelUncachedAdr;
|
||||
|
||||
if (`MEM_DTIM) begin : dtim
|
||||
/* Consider restructuring with higher level blocks. Try drawing block diagrams with several pages of schematics,
|
||||
one for top level, one for each sublevel, alternate with either dtim or bus. If this looks more satisfactory,
|
||||
restructure code accordingly.
|
||||
dtim dtim(.clk, .reset, .CPUBusy, .LSURWM, .IEUAdrM, .IEUAdrE, .TrapM, .FinalWriteDataM,
|
||||
.ReadDataWordM, .BusStall, .LSUBusWrite,.LSUBusRead, .BusCommittedM,
|
||||
.ReadDataWordMuxM, .DCacheStallM, .DCacheCommittedM,
|
||||
.DCacheMiss, .DCacheAccess);
|
||||
|
||||
dtim dtim (.clk, .CPUBusy, .LSURWM, .IEUAdrM, .IEUAdrE, .TrapM, .FinalWriteDataM, .ReadDataWordM,
|
||||
.BusStallM, .LSUBusWrite, .LSUBusRead, .DCacheBusAck, .BusCommittedM, .SelUncachedAdr,
|
||||
.ReadDataWordMuxM, .DCacheStallM, .DCacheCommittedM, .DCacheWriteLine, .DCacheFetchLine, .DCacheBusAdr,
|
||||
.ReadDataLineSetsM, .DCacheMiss, .DCacheAccess); */
|
||||
|
||||
// *** adjust interface so write address doesn't need delaying; switch to standard RAM?
|
||||
simpleram #(.BASE(`RAM_BASE), .RANGE(`RAM_RANGE)) ram (
|
||||
.clk,
|
||||
.a(CPUBusy | LSURWM[0] ? IEUAdrM[31:0] : IEUAdrE[31:0]),
|
||||
.we(LSURWM[0] & ~TrapM), // have to ignore write if Trap.
|
||||
.wd(FinalWriteDataM), .rd(ReadDataWordM));
|
||||
|
||||
// since we have a local memory the bus connections are all disabled.
|
||||
// There are no peripherals supported.
|
||||
assign {BusStall, LSUBusWrite, LSUBusRead, DCacheBusAck, BusCommittedM, SelUncachedAdr} = '0;
|
||||
assign ReadDataWordMuxM = ReadDataWordM;
|
||||
assign {DCacheStallM, DCacheCommittedM, DCacheWriteLine, DCacheFetchLine, DCacheBusAdr} = '0;
|
||||
assign ReadDataLineSetsM[0] = 0;
|
||||
assign DCacheMiss = 1'b0; assign DCacheAccess = 1'b0;
|
||||
end else begin : bus
|
||||
// replace from here up to if (`MEM_DCACHE) with busdp ***
|
||||
// Bus Side logic
|
||||
// register the fetch data from the next level of memory.
|
||||
// This register should be necessary for timing. There is no register in the uncore or
|
||||
// ahblite controller between the memories and this cache.
|
||||
logic [LOGWPL-1:0] WordCount;
|
||||
|
||||
genvar index;
|
||||
for (index = 0; index < WORDSPERLINE; index++) begin:fetchbuffer
|
||||
flopen #(`XLEN) fb(.clk, .en(LSUBusAck & LSUBusRead & (index == WordCount)),
|
||||
.d(LSUBusHRDATA), .q(DCacheMemWriteData[(index+1)*`XLEN-1:index*`XLEN]));
|
||||
end
|
||||
|
||||
assign LocalLSUBusAdr = SelUncachedAdr ? LSUPAdrM : DCacheBusAdr ;
|
||||
assign LSUBusAdr = ({{`PA_BITS-LOGWPL{1'b0}}, WordCount} << $clog2(`XLEN/8)) + LocalLSUBusAdr;
|
||||
assign PreLSUBusHWDATA = ReadDataLineSetsM[WordCount];
|
||||
// exclude the subword write for uncached. We don't read the data first so we cannot
|
||||
// select the subword by masking. Subword write also exists inside the uncore to
|
||||
// suport subword masking for i/o. I'm not sure if this is necessary.
|
||||
assign LSUBusHWDATA = SelUncachedAdr ? FinalAMOWriteDataM : PreLSUBusHWDATA;
|
||||
|
||||
assign LSUBusSize = SelUncachedAdr ? LSUFunct3M : (`XLEN == 32 ? 3'b010 : 3'b011);
|
||||
|
||||
// select between dcache and direct from the BUS. Always selected if no dcache.
|
||||
mux2 #(`XLEN) UnCachedDataMux(.d0(ReadDataWordM),
|
||||
.d1(DCacheMemWriteData[`XLEN-1:0]),
|
||||
.s(SelUncachedAdr),
|
||||
.y(ReadDataWordMuxM));
|
||||
|
||||
busfsm #(WordCountThreshold, LOGWPL, `MEM_DCACHE)
|
||||
busfsm(.clk, .reset, .IgnoreRequest, .LSURWM, .DCacheFetchLine, .DCacheWriteLine,
|
||||
.LSUBusAck, .CPUBusy, .CacheableM, .BusStall, .LSUBusWrite, .LSUBusRead,
|
||||
.DCacheBusAck, .BusCommittedM, .SelUncachedAdr, .WordCount);
|
||||
localparam integer WORDSPERLINE = `MEM_DCACHE ? `DCACHE_LINELENINBITS/`XLEN : 1;
|
||||
localparam integer LINELEN = `MEM_DCACHE ? `DCACHE_LINELENINBITS : `XLEN;
|
||||
logic [`XLEN-1:0] ReadDataLineSetsM [WORDSPERLINE-1:0];
|
||||
logic [LINELEN-1:0] DCacheMemWriteData;
|
||||
logic [`PA_BITS-1:0] DCacheBusAdr;
|
||||
logic DCacheWriteLine;
|
||||
logic DCacheFetchLine;
|
||||
logic DCacheBusAck;
|
||||
|
||||
busdp #(WORDSPERLINE, LINELEN)
|
||||
busdp(.clk, .reset,
|
||||
.LSUBusHRDATA, .LSUBusAck, .LSUBusWrite, .LSUBusRead, .LSUBusHWDATA, .LSUBusSize,
|
||||
.LSUFunct3M, .LSUBusAdr, .DCacheBusAdr, .ReadDataLineSetsM, .DCacheFetchLine,
|
||||
.DCacheWriteLine, .DCacheBusAck, .DCacheMemWriteData, .LSUPAdrM, .FinalAMOWriteDataM,
|
||||
.ReadDataWordM, .ReadDataWordMuxM, .IgnoreRequest, .LSURWM, .CPUBusy, .CacheableM,
|
||||
.BusStall, .BusCommittedM);
|
||||
|
||||
if(`MEM_DCACHE) begin : dcache
|
||||
cache #(.LINELEN(`DCACHE_LINELENINBITS), .NUMLINES(`DCACHE_WAYSIZEINBYTES*8/LINELEN),
|
||||
.NUMWAYS(`DCACHE_NUMWAYS), .DCACHE(1))
|
||||
.NUMWAYS(`DCACHE_NUMWAYS), .DCACHE(1))
|
||||
dcache(.clk, .reset, .CPUBusy,
|
||||
.RW(CacheableM ? LSURWM : 2'b00), .FlushCache(FlushDCacheM), .Atomic(CacheableM ? LSUAtomicM : 2'b00),
|
||||
.NextAdr(LSUAdrE), .PAdr(LSUPAdrM),
|
||||
.FinalWriteData(FinalWriteDataM), .ReadDataWord(ReadDataWordM), .CacheStall(DCacheStallM),
|
||||
.CacheMiss(DCacheMiss), .CacheAccess(DCacheAccess),
|
||||
.IgnoreRequest, .CacheCommitted(DCacheCommittedM),
|
||||
.CacheBusAdr(DCacheBusAdr), .ReadDataLineSets(ReadDataLineSetsM), .CacheMemWriteData(DCacheMemWriteData),
|
||||
.CacheFetchLine(DCacheFetchLine), .CacheWriteLine(DCacheWriteLine), .CacheBusAck(DCacheBusAck), .InvalidateCacheM(1'b0));
|
||||
.RW(CacheableM ? LSURWM : 2'b00), .FlushCache(FlushDCacheM),
|
||||
.Atomic(CacheableM ? LSUAtomicM : 2'b00), .NextAdr(LSUAdrE), .PAdr(LSUPAdrM),
|
||||
.FinalWriteData(FinalWriteDataM), .ReadDataWord(ReadDataWordM),
|
||||
.CacheStall(DCacheStallM), .CacheMiss(DCacheMiss), .CacheAccess(DCacheAccess),
|
||||
.IgnoreRequest, .CacheCommitted(DCacheCommittedM), .CacheBusAdr(DCacheBusAdr),
|
||||
.ReadDataLineSets(ReadDataLineSetsM), .CacheMemWriteData(DCacheMemWriteData),
|
||||
.CacheFetchLine(DCacheFetchLine), .CacheWriteLine(DCacheWriteLine),
|
||||
.CacheBusAck(DCacheBusAck), .InvalidateCacheM(1'b0));
|
||||
|
||||
end else begin : passthrough
|
||||
assign {ReadDataWordM, DCacheStallM, DCacheCommittedM, DCacheWriteLine, DCacheFetchLine, DCacheBusAdr} = '0;
|
||||
assign ReadDataLineSetsM[0] = 0;
|
||||
assign {ReadDataWordM, DCacheStallM, DCacheCommittedM, DCacheFetchLine, DCacheWriteLine} = '0;
|
||||
assign DCacheMiss = CacheableM; assign DCacheAccess = CacheableM;
|
||||
end
|
||||
end
|
||||
|
||||
// sub word selection for read and writes and optional amo alu.
|
||||
subwordread subwordread(.ReadDataWordMuxM,
|
||||
.LSUPAdrM(LSUPAdrM[2:0]),
|
||||
.Funct3M(LSUFunct3M),
|
||||
.ReadDataM);
|
||||
subwordread subwordread(.ReadDataWordMuxM, .LSUPAdrM(LSUPAdrM[2:0]),
|
||||
.Funct3M(LSUFunct3M), .ReadDataM);
|
||||
|
||||
// this might only get instantiated if there is a dcache or dtim.
|
||||
// There is a copy in the ebu. *** is it needed there, or can data come in from ebu, get muxed here and sent back out
|
||||
// Explore changing feedback path from output of AMOALU to subword write ***
|
||||
subwordwrite subwordwrite(.HRDATA(ReadDataWordM),
|
||||
.HADDRD(LSUPAdrM[2:0]),
|
||||
subwordwrite subwordwrite(.HRDATA(ReadDataWordM), .HADDRD(LSUPAdrM[2:0]),
|
||||
.HSIZED({LSUFunct3M[2], 1'b0, LSUFunct3M[1:0]}),
|
||||
.HWDATAIN(FinalAMOWriteDataM),
|
||||
.HWDATA(FinalWriteDataM));
|
||||
.HWDATAIN(FinalAMOWriteDataM), .HWDATA(FinalWriteDataM));
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Atomic operations
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
if (`A_SUPPORTED) begin:lrsc
|
||||
/*atomic atomic(.clk, .reset, .FlushW, .CPUBusy, .MemRead, .PreLSURWM, .LSUAtomicM, .LSUPAdrM,
|
||||
.SquashSCM, .LSURWM, ... ); *** */
|
||||
logic [`XLEN-1:0] AMOResult;
|
||||
amoalu amoalu(.srca(ReadDataM), .srcb(WriteDataM), .funct(LSUFunct7M), .width(LSUFunct3M[1:0]),
|
||||
.result(AMOResult));
|
||||
mux2 #(`XLEN) wdmux(WriteDataM, AMOResult, LSUAtomicM[1], FinalAMOWriteDataM);
|
||||
assign MemReadM = PreLSURWM[1] & ~(IgnoreRequest) & ~DTLBMissM;
|
||||
lrsc lrsc(.clk, .reset, .FlushW, .CPUBusy, .MemReadM, .PreLSURWM, .LSUAtomicM, .LSUPAdrM,
|
||||
.SquashSCW, .LSURWM);
|
||||
if (`A_SUPPORTED) begin:atomic
|
||||
atomic atomic(.clk, .reset, .FlushW, .CPUBusy, .ReadDataM, .WriteDataM, .LSUPAdrM,
|
||||
.LSUFunct7M, .LSUFunct3M, .LSUAtomicM, .PreLSURWM, .IgnoreRequest,
|
||||
.DTLBMissM, .FinalAMOWriteDataM, .SquashSCW, .LSURWM);
|
||||
end else begin:lrsc
|
||||
assign SquashSCW = 0;
|
||||
assign LSURWM = PreLSURWM;
|
||||
assign FinalAMOWriteDataM = WriteDataM;
|
||||
assign SquashSCW = 0; assign LSURWM = PreLSURWM; assign FinalAMOWriteDataM = WriteDataM;
|
||||
end
|
||||
endmodule
|
||||
|
||||
|
102
pipelined/src/lsu/lsuvirtmen.sv
Normal file
102
pipelined/src/lsu/lsuvirtmen.sv
Normal file
@ -0,0 +1,102 @@
|
||||
///////////////////////////////////////////
|
||||
// lsuvirtmem.sv
|
||||
//
|
||||
// Written: Ross Thompson ross1728@gmail.com January 30, 2022
|
||||
// Modified:
|
||||
//
|
||||
// Purpose: Encapsulates the hptw and muxes required to support virtual memory.
|
||||
// A component of the Wally configurable RISC-V project.
|
||||
//
|
||||
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
|
||||
//
|
||||
// MIT LICENSE
|
||||
// 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 lsuvirtmem(
|
||||
input logic clk, reset, StallW,
|
||||
input logic [1:0] MemRWM,
|
||||
input logic [1:0] AtomicM,
|
||||
input logic ITLBMissF,
|
||||
output logic ITLBWriteF,
|
||||
input logic DTLBMissM,
|
||||
output logic DTLBWriteM,
|
||||
input logic TrapM,
|
||||
input logic DCacheStallM,
|
||||
input logic [`XLEN-1:0] SATP_REGW, // from csr
|
||||
input logic [`XLEN-1:0] PCF,
|
||||
input logic [`XLEN-1:0] ReadDataM,
|
||||
input logic [2:0] Funct3M,
|
||||
output logic [2:0] LSUFunct3M,
|
||||
input logic [6:0] Funct7M,
|
||||
output logic [6:0] LSUFunct7M,
|
||||
input logic [`XLEN-1:0] IEUAdrE,
|
||||
input logic [`XLEN-1:0] IEUAdrM,
|
||||
output logic [`XLEN-1:0] PTE,
|
||||
output logic [1:0] PageType,
|
||||
output logic [1:0] PreLSURWM,
|
||||
output logic [1:0] LSUAtomicM,
|
||||
output logic [11:0] LSUAdrE,
|
||||
output logic [`PA_BITS-1:0] PreLSUPAdrM,
|
||||
input logic [`XLEN+1:0] IEUAdrExtM,
|
||||
|
||||
output logic InterlockStall,
|
||||
output logic CPUBusy,
|
||||
output logic SelHPTW,
|
||||
output logic IgnoreRequest);
|
||||
|
||||
|
||||
logic AnyCPUReqM;
|
||||
logic [`PA_BITS-1:0] HPTWAdr;
|
||||
logic HPTWRead;
|
||||
logic [2:0] HPTWSize;
|
||||
logic SelReplayCPURequest;
|
||||
logic [11:0] PreLSUAdrE;
|
||||
|
||||
|
||||
|
||||
assign AnyCPUReqM = (|MemRWM) | (|AtomicM);
|
||||
|
||||
interlockfsm interlockfsm (.clk, .reset, .AnyCPUReqM, .ITLBMissF, .ITLBWriteF,
|
||||
.DTLBMissM, .DTLBWriteM, .TrapM, .DCacheStallM,
|
||||
.InterlockStall, .SelReplayCPURequest, .SelHPTW,
|
||||
.IgnoreRequest);
|
||||
|
||||
hptw hptw(.clk, .reset, .SATP_REGW, .PCF, .IEUAdrM,
|
||||
.ITLBMissF(ITLBMissF & ~TrapM),
|
||||
.DTLBMissM(DTLBMissM & ~TrapM),
|
||||
.PTE, .PageType, .ITLBWriteF, .DTLBWriteM,
|
||||
.HPTWReadPTE(ReadDataM),
|
||||
.DCacheStallM, .HPTWAdr, .HPTWRead, .HPTWSize);
|
||||
|
||||
// arbiter between IEU and hptw
|
||||
|
||||
// multiplex the outputs to LSU
|
||||
mux2 #(2) rwmux(MemRWM, {HPTWRead, 1'b0}, SelHPTW, PreLSURWM);
|
||||
mux2 #(3) sizemux(Funct3M, HPTWSize, SelHPTW, LSUFunct3M);
|
||||
mux2 #(7) funct7mux(Funct7M, 7'b0, SelHPTW, LSUFunct7M);
|
||||
mux2 #(2) atomicmux(AtomicM, 2'b00, SelHPTW, LSUAtomicM);
|
||||
mux2 #(12) adremux(IEUAdrE[11:0], HPTWAdr[11:0], SelHPTW, PreLSUAdrE);
|
||||
mux2 #(12) replaymux(PreLSUAdrE, IEUAdrM[11:0], SelReplayCPURequest, LSUAdrE); // replay cpu request after hptw.
|
||||
mux2 #(`PA_BITS) lsupadrmux(IEUAdrExtM[`PA_BITS-1:0], HPTWAdr, SelHPTW, PreLSUPAdrM);
|
||||
|
||||
// always block interrupts when using the hardware page table walker.
|
||||
assign CPUBusy = StallW & ~SelHPTW;
|
||||
|
||||
endmodule; // lsuvirtmem
|
@ -86,7 +86,7 @@ module csrc #(parameter
|
||||
|
||||
// Determine when to increment each counter
|
||||
assign CounterEvent[0] = 1'b1; // MCYCLE always increments
|
||||
assign CounterEvent[1] = 1'b0; // Counter 0 doesn't exist
|
||||
assign CounterEvent[1] = 1'b0; // Counter 1 doesn't exist
|
||||
assign CounterEvent[2] = InstrValidNotFlushedM;
|
||||
if(`QEMU) begin: cevent // No other performance counters in QEMU
|
||||
assign CounterEvent[`COUNTERS-1:3] = 0;
|
||||
|
@ -72,25 +72,16 @@ module trap (
|
||||
assign PendingIntsM = ((MIP_REGW & MIE_REGW) & ({12{MIntGlobalEnM}} & 12'h888)) | ((SIP_REGW & SIE_REGW) & ({12{SIntGlobalEnM}} & 12'h222));
|
||||
assign PendingInterruptM = (|PendingIntsM) & InstrValidM;
|
||||
assign InterruptM = PendingInterruptM & ~(CommittedM); // *** RT. temporary hack to prevent integer division from having an interrupt during divide.
|
||||
// ideally this should be disabled for all but the first cycle. However I'm not familar with the internals of the integer divider. This should (could) be an issue for
|
||||
// floating point and integer multiply.
|
||||
//assign ExceptionM = TrapM;
|
||||
assign ExceptionM = Exception1M;
|
||||
// *** as of 7/17/21, the system passes with this definition of ExceptionM as being all traps and fails if ExceptionM = Exception1M
|
||||
// with no interrupts. However, Ross intended the datacache to use Exception without interrupts, so there is something subtle
|
||||
// to sort out here.
|
||||
// *** as of 8/13/21, switching to Exception1M does not seem to cause any failures. It's possible the bug was
|
||||
// fixed inadvertantly as the dcache was debugged.
|
||||
|
||||
|
||||
// Trigger Traps and RET
|
||||
// According to RISC-V Spec Section 1.6, exceptions are caused by instructions. Interrupts are external asynchronous.
|
||||
// Traps are the union of exceptions and interrupts.
|
||||
assign Exception1M = InstrMisalignedFaultM | InstrAccessFaultM | IllegalInstrFaultM |
|
||||
assign ExceptionM = InstrMisalignedFaultM | InstrAccessFaultM | IllegalInstrFaultM |
|
||||
LoadMisalignedFaultM | StoreAmoMisalignedFaultM |
|
||||
InstrPageFaultM | LoadPageFaultM | StoreAmoPageFaultM |
|
||||
BreakpointFaultM | EcallFaultM |
|
||||
LoadAccessFaultM | StoreAmoAccessFaultM;
|
||||
assign TrapM = Exception1M | InterruptM; // *** clean this up later DH
|
||||
assign TrapM = ExceptionM | InterruptM; // *** clean this up later DH
|
||||
assign MTrapM = TrapM & (NextPrivilegeModeM == `M_MODE);
|
||||
assign STrapM = TrapM & (NextPrivilegeModeM == `S_MODE) & `S_SUPPORTED;
|
||||
assign UTrapM = TrapM & (NextPrivilegeModeM == `U_MODE) & `N_SUPPORTED;
|
||||
|
@ -361,7 +361,7 @@ module sdModel
|
||||
next_state = READ_CMD;
|
||||
end
|
||||
ANALYZE_CMD: begin
|
||||
if ((ValidCmd ) && (outDelayCnt >= `outDelay )) // outDelayCnt >= 4 (NCR)
|
||||
if ((ValidCmd ) & (outDelayCnt >= `outDelay )) // outDelayCnt >= 4 (NCR)
|
||||
next_state = SEND_CMD;
|
||||
else if (inValidCmd)
|
||||
next_state = IDLE;
|
||||
@ -387,7 +387,7 @@ module sdModel
|
||||
DATA_IDLE: begin
|
||||
if ((CardStatus[12:9]==`RCV) | (mult_write == 1'b1) )
|
||||
next_datastate = READ_WAITS;
|
||||
else if ((CardStatus[12:9]==`DATAS )|| (mult_read == 1'b1) )
|
||||
else if ((CardStatus[12:9]==`DATAS )| (mult_read == 1'b1) )
|
||||
next_datastate = WRITE_DATA;
|
||||
else
|
||||
next_datastate = DATA_IDLE;
|
||||
@ -551,7 +551,7 @@ module sdModel
|
||||
ResetCard;
|
||||
end
|
||||
2 : begin //ALL_SEND_CARD_ID (CID)
|
||||
if (lastCMD != 41 && outDelayCnt==0) begin
|
||||
if (lastCMD != 41 & outDelayCnt==0) begin
|
||||
$fdisplay(sdModel_file_desc, "**Error in sequence, ACMD 41 should precede 2 in Start-up state") ;
|
||||
//$display(sdModel_file_desc, "**Error in sequence, ACMD 41 should precede 2 in Start-up state") ;
|
||||
CardStatus[3]<=1; // AKE_SEQ_ERROR = ERROR in sequence of authentication process
|
||||
@ -561,7 +561,7 @@ module sdModel
|
||||
CardStatus[12:9] <=2;
|
||||
end
|
||||
3 : begin //SEND_RELATIVE_CARD_ADDRESS (RCA)
|
||||
if (lastCMD != 2 && outDelayCnt==0 ) begin
|
||||
if (lastCMD != 2 & outDelayCnt==0 ) begin
|
||||
$fdisplay(sdModel_file_desc, "**Error in sequence, CMD 2 should precede 3 in Start-up state") ;
|
||||
//$display(sdModel_file_desc, "**Error in sequence, CMD 2 should precede 3 in Start-up state") ;
|
||||
CardStatus[3]<=1; // AKE_SEQ_ERROR = ERROR in sequence of authentication process
|
||||
@ -573,7 +573,7 @@ module sdModel
|
||||
cardIdentificationState<=0;
|
||||
end
|
||||
6 : begin
|
||||
if (lastCMD == 55 && outDelayCnt==0) begin //ACMD6 - SET_BUS_WIDTH
|
||||
if (lastCMD == 55 & outDelayCnt==0) begin //ACMD6 - SET_BUS_WIDTH
|
||||
if (inCmd[9:8] == 2'b10) begin
|
||||
BusWidth <=4;
|
||||
$display(sdModel_file_desc, "**BUS WIDTH 4 ") ;
|
||||
@ -627,7 +627,7 @@ module sdModel
|
||||
end
|
||||
|
||||
9 : begin // SEND_CARD_SPECIFIC_DATA (CSD)
|
||||
if (lastCMD != 41 && outDelayCnt==0) begin
|
||||
if (lastCMD != 41 & outDelayCnt==0) begin
|
||||
$fdisplay(sdModel_file_desc, "**Error in sequence, ACMD 41 should precede 9 in Start-up state") ;
|
||||
//$display(sdModel_file_desc, "**Error in sequence, ACMD 41 should precede 9 in Start-up state") ;
|
||||
CardStatus[3]<=1; // AKE_SEQ_ERROR = ERROR in sequence of authentication process
|
||||
@ -743,7 +743,7 @@ module sdModel
|
||||
41 : // CMD41 - SD_SEND_OCR
|
||||
begin
|
||||
if (cardIdentificationState) begin
|
||||
if (lastCMD != 55 && outDelayCnt==0) begin // CMD41 - Reserved/Invalid
|
||||
if (lastCMD != 55 & outDelayCnt==0) begin // CMD41 - Reserved/Invalid
|
||||
$fdisplay(sdModel_file_desc, "**Error in sequence, CMD 55 should precede 41 in Start-up state") ;
|
||||
$display( "**Error in sequence, CMD 55 should precede 41 in Start-up state") ;
|
||||
CardStatus[3]<=1; // AKE_SEQ_ERROR = ERROR in sequence of authentication process
|
||||
@ -755,7 +755,7 @@ module sdModel
|
||||
CardStatus[5] <=0; // not expecting next command to be ACMD
|
||||
if (Busy==1)
|
||||
CardStatus[12:9] <=1; // READY
|
||||
end // else: !if(lastCMD != 55 && outDelayCnt==0)
|
||||
end // else: !if(lastCMD != 55 & outDelayCnt==0)
|
||||
end // if (cardIdentificationState)
|
||||
end // case: 41
|
||||
endcase // case (inCmd[45:40])
|
||||
@ -799,7 +799,7 @@ module sdModel
|
||||
else
|
||||
cmdOut<=1;
|
||||
|
||||
if ((cmdWrite>0) && (cmdWrite < response_S-8)) begin
|
||||
if ((cmdWrite>0) & (cmdWrite < response_S-8)) begin
|
||||
cmdOut<=response_CMD[135-cmdWrite];
|
||||
crcIn<=response_CMD[134-cmdWrite];
|
||||
if (cmdWrite >= response_S-9)
|
||||
@ -948,7 +948,7 @@ module sdModel
|
||||
data_send_index<=1; // Next nibble is lower nibble
|
||||
end
|
||||
|
||||
else if ( (transf_cnt>=2) && (transf_cnt<=BLOCK_WIDTH -`CRC_OFF )) begin // if (2 <= transf_cnt <= 1025)
|
||||
else if ( (transf_cnt>=2) & (transf_cnt<=BLOCK_WIDTH -`CRC_OFF )) begin // if (2 <= transf_cnt <= 1025)
|
||||
data_send_index<=~data_send_index; //toggle
|
||||
if (!data_send_index) begin //upper nibble
|
||||
if (BLOCK_WIDTH == 11'd1044) begin
|
||||
@ -987,7 +987,7 @@ module sdModel
|
||||
if ( transf_cnt >=BLOCK_WIDTH-`CRC_OFF ) begin // if (trans_cnt >= 1025)
|
||||
crcDat_en<=0; // Disable CRC16 Generators
|
||||
end
|
||||
end // if ( (transf_cnt>=2) && (transf_cnt<=`BIT_BLOCK-`CRC_OFF ))
|
||||
end // if ( (transf_cnt>=2) & (transf_cnt<=`BIT_BLOCK-`CRC_OFF ))
|
||||
|
||||
else if (transf_cnt>BLOCK_WIDTH-`CRC_OFF & crc_c!=0) begin // if ((transf_cnt > 1025) and (crc_c /= 0))
|
||||
datOut<= last_din; // if sent all data bitsbut not crc16 bits yet
|
||||
@ -1004,7 +1004,7 @@ module sdModel
|
||||
else if (transf_cnt==BLOCK_WIDTH-2) begin // if (transf_cnt = 1042) Last CRC16 bit is 1041
|
||||
datOut<=4'b1111; // send end bits
|
||||
end
|
||||
else if ((transf_cnt !=0) && (crc_c == 0 ))begin // if sent data bits and crc_c points past last bit of CRC
|
||||
else if ((transf_cnt !=0) & (crc_c == 0 ))begin // if sent data bits and crc_c points past last bit of CRC
|
||||
oeDat<=0; // disable output on DAT bus
|
||||
CardStatus[12:9] <= `TRAN; // put card in transfer state
|
||||
end
|
||||
@ -1026,14 +1026,14 @@ module sdModel
|
||||
else if(flash_write_cnt == 2)
|
||||
datOut[0]<=0;
|
||||
|
||||
else if ((flash_write_cnt > 2) && (flash_write_cnt < 7)) begin
|
||||
else if ((flash_write_cnt > 2) & (flash_write_cnt < 7)) begin
|
||||
if (crc_ok)
|
||||
datOut[0] <=okcrctoken[6-flash_write_cnt];
|
||||
else
|
||||
datOut[0] <= invalidcrctoken[6-flash_write_cnt];
|
||||
|
||||
end
|
||||
else if ((flash_write_cnt >= 7) && (flash_write_cnt < 264)) begin
|
||||
else if ((flash_write_cnt >= 7) & (flash_write_cnt < 264)) begin
|
||||
datOut[0]<=0;
|
||||
|
||||
flash_blockwrite_cnt<=flash_blockwrite_cnt+2;
|
||||
@ -1045,7 +1045,7 @@ module sdModel
|
||||
datOut<=1;
|
||||
InbuffStatus<=0;
|
||||
CardStatus[12:9] <= `TRAN;
|
||||
end // else: !if((flash_write_cnt >= 7) && (flash_write_cnt < 264))
|
||||
end // else: !if((flash_write_cnt >= 7) & (flash_write_cnt < 264))
|
||||
end // case: WRITE_FLASH
|
||||
endcase // case (dataState)
|
||||
end // always @ (negedge sdClk)
|
||||
|
@ -82,7 +82,7 @@ module testbench;
|
||||
.HRDATAEXT, .HREADYEXT, .HREADY, .HSELEXT, .HRESPEXT, .HCLK,
|
||||
.HRESETn, .HADDR, .HWDATA, .HWRITE, .HSIZE, .HBURST, .HPROT,
|
||||
.HTRANS, .HMASTLOCK,
|
||||
.TIMECLK(0), .GPIOPinsIn, .GPIOPinsOut, .GPIOPinsEn,
|
||||
.TIMECLK('0), .GPIOPinsIn, .GPIOPinsOut, .GPIOPinsEn,
|
||||
.UARTSin, .UARTSout,
|
||||
.SDCCLK, .SDCCmdIn, .SDCCmdOut, .SDCCmdOE, .SDCDatIn);
|
||||
|
||||
@ -379,7 +379,7 @@ module testbench;
|
||||
//$display("len = %d", line``STAGE.len()); \
|
||||
for(index``STAGE = 0; index``STAGE < line``STAGE.len(); index``STAGE++) begin \
|
||||
//$display("char = %s", line``STAGE[index]); \
|
||||
if (line``STAGE[index``STAGE] == " " || line``STAGE[index``STAGE] == "\n") begin \
|
||||
if (line``STAGE[index``STAGE] == " " | line``STAGE[index``STAGE] == "\n") begin \
|
||||
EndIndex``STAGE = index``STAGE; \
|
||||
ExpectedTokens``STAGE[TokenIndex``STAGE] = line``STAGE.substr(StartIndex``STAGE, EndIndex``STAGE-1); \
|
||||
//$display("In Tokenizer %s", line``STAGE.substr(StartIndex, EndIndex-1)); \
|
||||
@ -412,7 +412,7 @@ module testbench;
|
||||
// parse CSRs, because there are 1 or more CSRs after the CSR token \
|
||||
// we check if the CSR token or the number of CSRs is greater than 0. \
|
||||
// if so then we want to parse for a CSR. \
|
||||
end else if(ExpectedTokens``STAGE[MarkerIndex``STAGE] == "CSR" || NumCSR``STAGE > 0) begin \
|
||||
end else if(ExpectedTokens``STAGE[MarkerIndex``STAGE] == "CSR" | NumCSR``STAGE > 0) begin \
|
||||
if(ExpectedTokens``STAGE[MarkerIndex``STAGE] == "CSR") begin \
|
||||
// all additional CSR's won't have this token. \
|
||||
MarkerIndex``STAGE++; \
|
||||
@ -467,7 +467,7 @@ module testbench;
|
||||
// $display("%tns: ExpectedPCM %x",$time,ExpectedPCM);
|
||||
// $display("%tns: ExpectedPCE %x",$time,ExpectedPCE);
|
||||
// $display("%tns: ExpectedPCW %x",$time,ExpectedPCW);
|
||||
if((ExpectedPCE != MepcExpected) & ((MepcExpected - ExpectedPCE) * (MepcExpected - ExpectedPCE) <= 200) || ~dut.core.ieu.c.InstrValidM) begin
|
||||
if((ExpectedPCE != MepcExpected) & ((MepcExpected - ExpectedPCE) * (MepcExpected - ExpectedPCE) <= 200) | ~dut.core.ieu.c.InstrValidM) begin
|
||||
RequestDelayedMIP <= 1;
|
||||
$display("%tns: Requesting Delayed MIP. Current MEPC value is %x",$time,MepcExpected);
|
||||
end else begin // update MIP immediately
|
||||
@ -584,10 +584,10 @@ module testbench;
|
||||
if (MemOpW.substr(0,2) == "Mem") begin
|
||||
if(`DEBUG_TRACE >= 4) $display("\tIEUAdrW: %016x ? expected: %016x", IEUAdrW, ExpectedIEUAdrW);
|
||||
`checkEQ("IEUAdrW",IEUAdrW,ExpectedIEUAdrW)
|
||||
if(MemOpW == "MemR" || MemOpW == "MemRW") begin
|
||||
if(MemOpW == "MemR" | MemOpW == "MemRW") begin
|
||||
if(`DEBUG_TRACE >= 4) $display("\tReadDataW: %016x ? expected: %016x", dut.core.ieu.dp.ReadDataW, ExpectedMemReadDataW);
|
||||
`checkEQ("ReadDataW",dut.core.ieu.dp.ReadDataW,ExpectedMemReadDataW)
|
||||
end else if(MemOpW == "MemW" || MemOpW == "MemRW") begin
|
||||
end else if(MemOpW == "MemW" | MemOpW == "MemRW") begin
|
||||
if(`DEBUG_TRACE >= 4) $display("\tWriteDataW: %016x ? expected: %016x", WriteDataW, ExpectedMemWriteDataW);
|
||||
`checkEQ("WriteDataW",ExpectedMemWriteDataW,ExpectedMemWriteDataW)
|
||||
end
|
||||
@ -636,7 +636,7 @@ module testbench;
|
||||
// For waveview convenience
|
||||
string InstrFName, InstrDName, InstrEName, InstrMName, InstrWName;
|
||||
instrTrackerTB it(clk, reset, dut.core.ieu.dp.FlushE,
|
||||
dut.core.ifu.FinalInstrRawF,
|
||||
dut.core.ifu.FinalInstrRawF[31:0],
|
||||
dut.core.ifu.InstrD, dut.core.ifu.InstrE,
|
||||
dut.core.ifu.InstrM, InstrW,
|
||||
InstrFName, InstrDName, InstrEName, InstrMName, InstrWName);
|
||||
@ -680,7 +680,7 @@ module testbench;
|
||||
PTE = dut.uncore.ram.ram.RAM[PAdr >> 3];
|
||||
PTE_R = PTE[1];
|
||||
PTE_X = PTE[3];
|
||||
if (PTE_R || PTE_X) begin
|
||||
if (PTE_R | PTE_X) begin
|
||||
// Leaf page found
|
||||
break;
|
||||
end else begin
|
||||
|
@ -196,7 +196,7 @@ logic [3:0] dummy;
|
||||
else pathname = tvpaths[1]; */
|
||||
memfilename = {pathname, tests[test], ".elf.memfile"};
|
||||
//$readmemh(memfilename, dut.uncore.ram.ram.RAM);
|
||||
$readmemh(memfilename, dut.core.lsu.dtim.ram.RAM);
|
||||
$readmemh(memfilename, dut.core.lsu.dtim.dtim.ram.RAM);
|
||||
// if(`MEM_DTIM == 1) $readmemh(memfilename, dut.core.lsu.dtim.ram.RAM);
|
||||
//`ifdef `MEM_IROM
|
||||
// $display("here!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
|
||||
@ -204,7 +204,7 @@ logic [3:0] dummy;
|
||||
//`endif
|
||||
// if(`MEM_IROM == 1) begin
|
||||
// $display("here!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
|
||||
$readmemh(memfilename, dut.core.ifu.irom.ram.RAM);
|
||||
$readmemh(memfilename, dut.core.ifu.irom.irom.ram.RAM);
|
||||
// end
|
||||
ProgramAddrMapFile = {pathname, tests[test], ".elf.objdump.addr"};
|
||||
ProgramLabelMapFile = {pathname, tests[test], ".elf.objdump.lab"};
|
||||
@ -258,7 +258,7 @@ logic [3:0] dummy;
|
||||
while (signature[i] !== 'bx) begin
|
||||
//$display("signature[%h] = %h", i, signature[i]);
|
||||
// *** have to figure out how to exclude shadowram when not using a dcache.
|
||||
if (signature[i] !== dut.core.lsu.dtim.ram.RAM[testadr+i] &
|
||||
if (signature[i] !== dut.core.lsu.dtim.dtim.ram.RAM[testadr+i] &
|
||||
(signature[i] !== DCacheFlushFSM.ShadowRAM[testadr+i])) begin
|
||||
if (signature[i+4] !== 'bx | signature[i] !== 32'hFFFFFFFF) begin
|
||||
// report errors unless they are garbage at the end of the sim
|
||||
@ -266,7 +266,7 @@ logic [3:0] dummy;
|
||||
errors = errors+1;
|
||||
$display(" Error on test %s result %d: adr = %h sim (D$) %h sim (TIM) = %h, signature = %h",
|
||||
//tests[test], i, (testadr+i)*(`XLEN/8), DCacheFlushFSM.ShadowRAM[testadr+i], dut.uncore.ram.ram.RAM[testadr+i], signature[i]);
|
||||
tests[test], i, (testadr+i)*(`XLEN/8), DCacheFlushFSM.ShadowRAM[testadr+i], dut.core.lsu.dtim.ram.RAM[testadr+i], signature[i]);
|
||||
tests[test], i, (testadr+i)*(`XLEN/8), DCacheFlushFSM.ShadowRAM[testadr+i], dut.core.lsu.dtim.dtim.ram.RAM[testadr+i], signature[i]);
|
||||
$stop;//***debug
|
||||
end
|
||||
end
|
||||
@ -290,7 +290,7 @@ logic [3:0] dummy;
|
||||
//pathname = tvpaths[tests[0]];
|
||||
memfilename = {pathname, tests[test], ".elf.memfile"};
|
||||
//$readmemh(memfilename, dut.uncore.ram.ram.RAM);
|
||||
$readmemh(memfilename, dut.core.lsu.dtim.ram.RAM);
|
||||
$readmemh(memfilename, dut.core.lsu.dtim.dtim.ram.RAM);
|
||||
//if(`MEM_DTIM == 1) $readmemh(memfilename, dut.core.lsu.dtim.ram.RAM);
|
||||
/* -----\/----- EXCLUDED -----\/-----
|
||||
`ifdef `MEM_IROM
|
||||
@ -298,7 +298,7 @@ logic [3:0] dummy;
|
||||
$readmemh(memfilename, dut.core.ifu.irom.ram.RAM);
|
||||
`endif
|
||||
-----/\----- EXCLUDED -----/\----- */
|
||||
$readmemh(memfilename, dut.core.ifu.irom.ram.RAM);
|
||||
$readmemh(memfilename, dut.core.ifu.irom.irom.ram.RAM);
|
||||
//if(`MEM_IROM == 1) $readmemh(memfilename, dut.core.ifu.irom.ram.RAM);
|
||||
ProgramAddrMapFile = {pathname, tests[test], ".elf.objdump.addr"};
|
||||
ProgramLabelMapFile = {pathname, tests[test], ".elf.objdump.lab"};
|
||||
|
@ -1479,7 +1479,8 @@ string imperas32f[] = '{
|
||||
"rv64i_m/privilege/WALLY-MMU-SV39", "30A0",
|
||||
"rv64i_m/privilege/WALLY-MMU-SV48", "30A0",
|
||||
"rv64i_m/privilege/WALLY-PMP", "30A0",
|
||||
"rv64i_m/privilege/WALLY-PMA", "30A0"
|
||||
"rv64i_m/privilege/WALLY-PMA", "30A0",
|
||||
"rv64i_m/privilege/WALLY-minfo-01", "30A0"
|
||||
};
|
||||
|
||||
string wally64periph[] = '{
|
||||
|
78
synthDC/.synopsys_dc.setup
Executable file
78
synthDC/.synopsys_dc.setup
Executable file
@ -0,0 +1,78 @@
|
||||
|
||||
# Search Paths
|
||||
set CURRENT_DIR [exec pwd]
|
||||
set search_path [list "./" ]
|
||||
|
||||
set s8lib ../addins/sky130_osu_sc_t18/18T_ms/lib
|
||||
lappend search_path $s8lib
|
||||
|
||||
# Synthetic libraries
|
||||
set synthetic_library [list dw_foundation.sldb]
|
||||
|
||||
# Set OKSTATE standard cell libraries
|
||||
set target_library [list]
|
||||
|
||||
lappend target_library sky130_osu_sc_18T_ms_TT_1P8_25C.ccs.db
|
||||
|
||||
# Set Link Library
|
||||
set link_library "$target_library $synthetic_library"
|
||||
|
||||
# Set up DesignWare cache read and write directories to speed up compile.
|
||||
set cache_write ~
|
||||
set cache_read $cache_write
|
||||
|
||||
# Tell DC where to look for files
|
||||
lappend search_path ./scripts
|
||||
lappend search_path ./hdl
|
||||
lappend search_path ./mapped
|
||||
|
||||
# Set up User Information
|
||||
set company "Oklahoma State University"
|
||||
set user "James E. Stine"
|
||||
|
||||
# Alias
|
||||
alias ra report_area
|
||||
alias rt report_timing
|
||||
alias rc {report_constraint -all_violators}
|
||||
|
||||
alias sf set_flatten
|
||||
alias ss set_structure
|
||||
alias rco report_compile_options
|
||||
alias cs compile -scan
|
||||
alias csi compile -scan -incr -map high
|
||||
|
||||
alias h history
|
||||
history keep 100
|
||||
alias all_gone {remove_design -designs}
|
||||
|
||||
alias page_on {set sh_enable_page_mode true}
|
||||
alias page_off {set sh_enable_page_mode false}
|
||||
|
||||
# specify directory for intermediate files from analyze
|
||||
define_design_lib DEFAULT -path ./analyzed
|
||||
|
||||
# suppress Driving cell warning
|
||||
suppress_message {UID-401}
|
||||
|
||||
########### Source Useful Tcl Procedures ###########
|
||||
|
||||
foreach _file [glob -nocomplain ./tcl_procs/*.tcl] {
|
||||
source $_file
|
||||
}
|
||||
|
||||
############# Enable line editing in 2004.12 ###########
|
||||
|
||||
set sh_enable_line_editing true
|
||||
|
||||
############# Setup the view utility ###########
|
||||
|
||||
proc view {args} {
|
||||
redirect tmpfile1212 {uplevel $args}
|
||||
# Without redirect, exec echos the PID of the new process to the screen
|
||||
redirect /dev/null {exec ./tcl_procs/view.tk tmpfile1212 "$args" &}
|
||||
}
|
||||
|
||||
alias vrt {view report_timing -nosplit}
|
||||
alias vrtm {view report_timing -nosplit -delay min}
|
||||
alias vman {view man}
|
||||
|
34
synthDC/Makefile
Executable file
34
synthDC/Makefile
Executable file
@ -0,0 +1,34 @@
|
||||
#
|
||||
# Makefile for synthesis
|
||||
#
|
||||
NAME := synth
|
||||
|
||||
VARIANT := 18T_ms
|
||||
|
||||
default:
|
||||
@echo "Basic synthesis procedure for OSU/HMC/UNLV:"
|
||||
@echo " adapt Makefile to your liking..."
|
||||
@echo
|
||||
|
||||
synth:
|
||||
@sed -i 's/18T_ms/${VARIANT}/g' scripts/synth.tcl
|
||||
@sed -i 's/18T_ms/${VARIANT}/g' .synopsys_dc.setup
|
||||
@echo "DC Synthesis"
|
||||
@mkdir -p reports
|
||||
@mkdir -p mapped
|
||||
dc_shell-xg-t -64bit -f scripts/$(NAME).tcl | tee $(NAME).out
|
||||
# @cp mapped/*.sdc ../../outputs/
|
||||
# @cp mapped/*.vh ../../outputs/
|
||||
# @sed -i 's/${VARIANT}/18T_ms/g' scripts/synth.tcl
|
||||
# @sed -i 's/${VARIANT}/18T_ms/g' .synopsys_dc.setup
|
||||
|
||||
clean:
|
||||
rm -rf alib-52 WORK mapped unmapped reports analyzed $(NAME).out
|
||||
mkdir mapped unmapped reports
|
||||
rm -f hdl/*
|
||||
rm -f default.svf
|
||||
rm -f command.log
|
||||
rm -f filenames*.log
|
||||
|
||||
|
||||
|
34
synthDC/README.md
Normal file
34
synthDC/README.md
Normal file
@ -0,0 +1,34 @@
|
||||
This subdirectory contains synthesis scripts for use with Synopsys
|
||||
Design Compiler (DC). The scripts are separated into two distinct
|
||||
sections: user and technology setups. The technology setup is found
|
||||
in .synopsys_dc.setup file. Key items within this technology setup
|
||||
are the location of the PDK and standard cell libraries.
|
||||
|
||||
We are using the Skywater Technology 130nm process for the synthesis.
|
||||
The Oklahoma State University standard-cell libraries for this process
|
||||
are located via the target_library keyword. There are currently three
|
||||
versions of the standard-cell libraries available (see
|
||||
http://stineje.github.io) for dowload locations. Currently, the TT 18
|
||||
track OSU standard-cell library is utilized.
|
||||
|
||||
There are other useful elements within the technology setup file, as
|
||||
well. These include user information as well as search path
|
||||
information. Good tool flows usually rely on finding the right files
|
||||
correctly and having a search path set correctly is importantly.
|
||||
|
||||
The user setup is found in two main areas. The scripts/ and hdl/
|
||||
directories. The scripts directory contains a basic DC synthesis Tcl
|
||||
script that is involved when synthesis is run. Please modify this
|
||||
synth.tcl file to add information about PPA and information about your
|
||||
design (e.g., top-level name, SV files). The SV is found within the
|
||||
hdl/ subdirectory. Just put all your synthesis-friendly files in this
|
||||
directory or allude to the correct location in the synthesis Tcl
|
||||
script.
|
||||
|
||||
After synthesis completes, always check your synthesis log file that
|
||||
will be called synth.log. Good tool flow starts and ends with
|
||||
understanding what is happening during a specific part of the flow.
|
||||
This can only be done through interpreting what the Electronic Design
|
||||
Automation (EDA) tool is doing. So, always check this file for any
|
||||
possible warnings or errors after completion. All output of synthesis
|
||||
is found in the reports/ subdirectory.
|
184
synthDC/scripts/synth.tcl
Executable file
184
synthDC/scripts/synth.tcl
Executable file
@ -0,0 +1,184 @@
|
||||
#
|
||||
# Main Synopsys Flow
|
||||
# james.stine@okstate.edu 26 Jan 2022
|
||||
#
|
||||
|
||||
# Config
|
||||
set hdl_src "../pipelined/src"
|
||||
|
||||
eval file copy ${hdl_src}/../config/rv64gc/wally-config.vh {hdl/}
|
||||
eval file copy ${hdl_src}/../config/rv64gc/wally-config.vh {reports/}
|
||||
eval file copy [glob ${hdl_src}/../config/shared/*.vh] {hdl/}
|
||||
eval file copy [glob ${hdl_src}/*/*.sv] {hdl/}
|
||||
eval file copy [glob ${hdl_src}/*/flop/*.sv] {hdl/}
|
||||
|
||||
# Verilog files
|
||||
set my_verilog_files [glob hdl/*]
|
||||
|
||||
# Set toplevel
|
||||
set my_toplevel wallypipelinedcore
|
||||
|
||||
# Set number of significant digits
|
||||
set report_default_significant_digits 6
|
||||
|
||||
# V(HDL) Unconnectoed Pins Output
|
||||
set verilogout_show_unconnected_pins "true"
|
||||
set vhdlout_show_unconnected_pins "true"
|
||||
|
||||
#
|
||||
# Due to parameterized Verilog must use analyze/elaborate and not
|
||||
# read_verilog/vhdl (change to pull in Verilog and/or VHDL)
|
||||
#
|
||||
define_design_lib WORK -path ./WORK
|
||||
analyze -f sverilog -lib WORK $my_verilog_files
|
||||
|
||||
#
|
||||
# Added if you had any VHDL
|
||||
# analyze -f vhdl -lib WORK $my_vhdl_files
|
||||
#
|
||||
elaborate $my_toplevel -lib WORK
|
||||
|
||||
# Set the current_design
|
||||
current_design $my_toplevel
|
||||
link
|
||||
|
||||
# Reset all constraints
|
||||
reset_design
|
||||
|
||||
# Set Frequency in [MHz] or [ps]
|
||||
set my_clock_pin clk
|
||||
set my_clk_freq_MHz 10
|
||||
set my_period [expr 1000 / $my_clk_freq_MHz]
|
||||
set my_uncertainty [expr .1 * $my_period]
|
||||
|
||||
# Create clock object
|
||||
set find_clock [ find port [list $my_clock_pin] ]
|
||||
if { $find_clock != [list] } {
|
||||
echo "Found clock!"
|
||||
set my_clk $my_clock_pin
|
||||
create_clock -period $my_period $my_clk
|
||||
set_clock_uncertainty $my_uncertainty [get_clocks $my_clk]
|
||||
} else {
|
||||
echo "Did not find clock! Design is probably combinational!"
|
||||
set my_clk vclk
|
||||
create_clock -period $my_period -name $my_clk
|
||||
}
|
||||
|
||||
# Partitioning - flatten or hierarchically synthesize
|
||||
#ungroup -flatten -simple_names { dp* }
|
||||
#ungroup -flatten -simple_names { c* }
|
||||
#ungroup -all -flatten -simple_names
|
||||
|
||||
# Set input pins except clock
|
||||
set all_in_ex_clk [remove_from_collection [all_inputs] [get_ports $my_clk]]
|
||||
|
||||
# Specifies delays be propagated through the clock network
|
||||
set_propagated_clock [get_clocks $my_clk]
|
||||
|
||||
# Setting constraints on input ports
|
||||
set_driving_cell -lib_cell sky130_osu_sc_18T_ms__dff_1 -pin Q $all_in_ex_clk
|
||||
|
||||
# Set input/output delay
|
||||
set_input_delay 0.0 -max -clock $my_clk $all_in_ex_clk
|
||||
set_output_delay 0.0 -max -clock $my_clk [all_outputs]
|
||||
|
||||
# Setting load constraint on output ports
|
||||
set_load [expr [load_of sky130_osu_sc_18T_ms_TT_1P8_25C.ccs/sky130_osu_sc_18T_ms__dff_1/D] * 1] [all_outputs]
|
||||
|
||||
# Set the wire load model
|
||||
set_wire_load_mode "top"
|
||||
|
||||
# Attempt Area Recovery - if looking for minimal area
|
||||
# set_max_area 2000
|
||||
|
||||
# Set fanout
|
||||
set_max_fanout 6 $all_in_ex_clk
|
||||
|
||||
# Fix hold time violations
|
||||
set_fix_hold [all_clocks]
|
||||
|
||||
# Deal with constants and buffers to isolate ports
|
||||
set_fix_multiple_port_nets -all -buffer_constants
|
||||
|
||||
# setting up the group paths to find out the required timings
|
||||
#group_path -name OUTPUTS -to [all_outputs]
|
||||
#group_path -name INPUTS -from [all_inputs]
|
||||
#group_path -name COMBO -from [all_inputs] -to [all_outputs]
|
||||
|
||||
# Save Unmapped Design
|
||||
set filename [format "%s%s%s" "unmapped/" $my_toplevel ".ddc"]
|
||||
write_file -format ddc -hierarchy -o $filename
|
||||
|
||||
# Compile statements - either compile or compile_ultra
|
||||
# compile -scan -incr -map_effort low
|
||||
# compile_ultra -no_seq_output_inversion -no_boundary_optimization
|
||||
|
||||
# Eliminate need for assign statements (yuck!)
|
||||
set verilogout_no_tri true
|
||||
set verilogout_equation false
|
||||
|
||||
# setting to generate output files
|
||||
set write_v 1 ;# generates structual netlist
|
||||
set write_sdc 1 ;# generates synopsys design constraint file for p&r
|
||||
set write_ddc 1 ;# compiler file in ddc format
|
||||
set write_sdf 1 ;# sdf file for backannotated timing sim
|
||||
set write_pow 1 ;# genrates estimated power report
|
||||
set write_rep 1 ;# generates estimated area and timing report
|
||||
set write_cst 1 ;# generate report of constraints
|
||||
set write_hier 1 ;# generate hierarchy report
|
||||
|
||||
# Report Constraint Violators
|
||||
set filename [format "%s%s%s" "reports/" $my_toplevel "_constraint_all_violators.rpt"]
|
||||
redirect $filename {report_constraint -all_violators}
|
||||
|
||||
# Check design
|
||||
redirect reports/check_design.rpt { check_design }
|
||||
|
||||
# Report Final Netlist (Hierarchical)
|
||||
set filename [format "%s%s%s" "mapped/" $my_toplevel ".vh"]
|
||||
write_file -f verilog -hierarchy -output $filename
|
||||
|
||||
set filename [format "%s%s%s" "mapped/" $my_toplevel ".sdc"]
|
||||
write_sdc $filename
|
||||
|
||||
set filename [format "%s%s%s" "mapped/" $my_toplevel ".ddc"]
|
||||
write_file -format ddc -hierarchy -o $filename
|
||||
|
||||
set filename [format "%s%s%s" "mapped/" $my_toplevel ".sdf"]
|
||||
write_sdf $filename
|
||||
|
||||
# QoR
|
||||
set filename [format "%s%s%s" "reports/" $my_toplevel "_qor.rep"]
|
||||
redirect $filename { report_qor }
|
||||
|
||||
# Report Timing
|
||||
set filename [format "%s%s%s" "reports/" $my_toplevel "_reportpath.rep"]
|
||||
redirect $filename { report_path_group }
|
||||
|
||||
set filename [format "%s%s%s" "reports/" $my_toplevel "_report_clock.rep"]
|
||||
redirect $filename { report_clock }
|
||||
|
||||
set filename [format "%s%s%s" "reports/" $my_toplevel "_timing.rep"]
|
||||
redirect $filename { report_timing -capacitance -transition_time -nets -nworst 1 }
|
||||
|
||||
set filename [format "%s%s%s" "reports/" $my_toplevel "_min_timing.rep"]
|
||||
redirect $filename { report_timing -delay min }
|
||||
|
||||
set filename [format "%s%s%s" "reports/" $my_toplevel "_area.rep"]
|
||||
redirect $filename { report_area -hierarchy -nosplit -physical -designware}
|
||||
|
||||
set filename [format "%s%s%s" "reports/" $my_toplevel "_cell.rep"]
|
||||
redirect $filename { report_cell [get_cells -hier *] }
|
||||
|
||||
set filename [format "%s%s%s" "reports/" $my_toplevel "_power.rep"]
|
||||
redirect $filename { report_power }
|
||||
|
||||
set filename [format "%s%s%s" "reports/" $my_toplevel "_constraint.rep"]
|
||||
redirect $filename { report_constraint }
|
||||
|
||||
set filename [format "%s%s%s" "reports/" $my_toplevel "_hier.rep"]
|
||||
redirect $filename { report_hierarchy }
|
||||
|
||||
# Quit
|
||||
quit
|
||||
|
@ -21,7 +21,7 @@
|
||||
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
///////////////////////////////////////////
|
||||
|
||||
#include "WALLY-TEST-LIB-32.S"
|
||||
#include "WALLY-TEST-LIB-32.h"
|
||||
// Test library includes and handler for each type of test, a trap handler, imperas compliance instructions
|
||||
// Ideally this should mean that a test can be written by simply adding .8byte statements as below.
|
||||
|
||||
@ -44,52 +44,52 @@
|
||||
# test 12.3.1.1.1 write page tables / entries to phyiscal memory
|
||||
# sv32 Page table (See Figure 12.12***):
|
||||
# Level 1 page table, situated at 0x8000D000
|
||||
.4byte 0x8000D000, 0x20004C01, 0x0 # points to level 0 page table A
|
||||
.4byte 0x8000D004, 0x200000CB, 0x0 # Vaddr 0x400000 Paddr 0x80000000: aligned megapage, W=0, used for execute tests
|
||||
.4byte 0x8000D008, 0x20005401, 0x0 # points to level 0 page table B
|
||||
.4byte 0x8000D00C, 0x000800C7, 0x0 # Vaddr 0xC00000: misaligned megapage
|
||||
.4byte 0x8000D800, 0x200000CF, 0x0 # Vaddr 0x80000000 Paddr 0x80000000: aligned megapage (program and data memory)
|
||||
.4byte 0x8000D804, 0x200000DF, 0x0 # Vaddr 0x80400000 Paddr 0x80000000: aligned megapage, U=1 (aliased with program and data memory)
|
||||
.4byte 0x8000D000, 0x20004C01, write32_test # points to level 0 page table A
|
||||
.4byte 0x8000D004, 0x200000CB, write32_test # Vaddr 0x400000 Paddr 0x80000000: aligned megapage, W=0, used for execute tests
|
||||
.4byte 0x8000D008, 0x20005401, write32_test # points to level 0 page table B
|
||||
.4byte 0x8000D00C, 0x000800C7, write32_test # Vaddr 0xC00000: misaligned megapage
|
||||
.4byte 0x8000D800, 0x200000CF, write32_test # Vaddr 0x80000000 Paddr 0x80000000: aligned megapage (program and data memory)
|
||||
.4byte 0x8000D804, 0x200000DF, write32_test # Vaddr 0x80400000 Paddr 0x80000000: aligned megapage, U=1 (aliased with program and data memory)
|
||||
# Level 0 page table A
|
||||
.4byte 0x80013000, 0x20007001, 0x0 # Vaddr 0x0000: bad PTE points to level -1 table
|
||||
.4byte 0x80013004, 0x202000DF, 0x0 # Vaddr 0x1000 Paddr 0x80800000: aligned kilopage, U=1
|
||||
.4byte 0x80013008, 0x202010D5, 0x0 # Vaddr 0x2000: pad PTE has W but not R
|
||||
.4byte 0x8001300C, 0x20200817, 0x0 # Vaddr 0x3000: A=0, should cause read fault
|
||||
.4byte 0x80013010, 0x20200C57, 0x0 # Vaddr 0x4000: D=0, should cause write fault
|
||||
.4byte 0x80013014, 0x202014C9, 0x0 # Vaddr 0x5000 Paddr 80805000: aligned kilopage, W=R=0
|
||||
.4byte 0x80013018, 0x0, 0x0 # Vaddr 0x6000: invalid page
|
||||
.4byte 0x80013000, 0x20007001, write32_test # Vaddr 0x0000: bad PTE points to level -1 table
|
||||
.4byte 0x80013004, 0x202000DF, write32_test # Vaddr 0x1000 Paddr 0x80800000: aligned kilopage, U=1
|
||||
.4byte 0x80013008, 0x202010D5, write32_test # Vaddr 0x2000: pad PTE has W but not R
|
||||
.4byte 0x8001300C, 0x20200817, write32_test # Vaddr 0x3000: A=0, should cause read fault
|
||||
.4byte 0x80013010, 0x20200C57, write32_test # Vaddr 0x4000: D=0, should cause write fault
|
||||
.4byte 0x80013014, 0x202014C9, write32_test # Vaddr 0x5000 Paddr 80805000: aligned kilopage, W=R=0
|
||||
.4byte 0x80013018, 0x0, write32_test # Vaddr 0x6000: invalid page
|
||||
# Level 0 page table B
|
||||
.4byte 0x80015FFC, 0x202004C7, 0x0 # Vaddr 0xBFF000 Paddr 0x80801000: aligned kilopage with X=0, U=0
|
||||
.4byte 0x80015FFC, 0x202004C7, write32_test # Vaddr 0xBFF000 Paddr 0x80801000: aligned kilopage with X=0, U=0
|
||||
|
||||
|
||||
# test 12.3.1.1.2 write values to Paddrs in each page
|
||||
# each of these values is used for 12.3.1.1.3 and some other tests, specified in the comments.
|
||||
# when a test is supposed to fault, nothing is written into where it'll be reading/executing since it should fault before getting there.
|
||||
.4byte 0x800AAAA8, 0xBEEF0055, 0x0 # 12.3.1.1.4 megapage
|
||||
.4byte 0x800FFAC0, 0xBEEF0033, 0x0 # 12.3.1.3.2
|
||||
.4byte 0x800E3130, 0xBEEF0077, 0x0 # 12.3.1.3.2
|
||||
.4byte 0x808017E0, 0xBEEF0099, 0x0 # 12.3.1.1.4 kilopage
|
||||
.4byte 0x80805EA0, 0xBEEF0440, 0x0 # 12.3.1.3.3
|
||||
.4byte 0x80803AA0, 0xBEEF0BB0, 0x0 # 12.3.1.3.7
|
||||
.4byte 0x8000FFA0, 0x11100393, 0x0 # write executable code for "li x7, 0x111; ret" to executable region.
|
||||
.4byte 0x8000FFA4, 0x00008067, 0x0 # Used for 12.3.1.3.1, 12.3.1.3.2
|
||||
.4byte 0x800AAAA8, 0xBEEF0055, write32_test # 12.3.1.1.4 megapage
|
||||
.4byte 0x800FFAC0, 0xBEEF0033, write32_test # 12.3.1.3.2
|
||||
.4byte 0x800E3130, 0xBEEF0077, write32_test # 12.3.1.3.2
|
||||
.4byte 0x808017E0, 0xBEEF0099, write32_test # 12.3.1.1.4 kilopage
|
||||
.4byte 0x80805EA0, 0xBEEF0440, write32_test # 12.3.1.3.3
|
||||
.4byte 0x80803AA0, 0xBEEF0BB0, write32_test # 12.3.1.3.7
|
||||
.4byte 0x8000FFA0, 0x11100393, write32_test # write executable code for "li x7, 0x111; ret" to executable region.
|
||||
.4byte 0x8000FFA4, 0x00008067, write32_test # Used for 12.3.1.3.1, 12.3.1.3.2
|
||||
|
||||
# test 12.3.1.1.3 read values back from Paddrs without translation (this also verifies the previous test)
|
||||
.4byte 0x0, 0x0, 0x4 # satp.MODE = baremetal / no translation.
|
||||
.4byte 0x0, 0x0, 0x9 # change to S mode, 0xb written to output
|
||||
.4byte 0x800AAAA8, 0xBEEF0055, 0x1
|
||||
.4byte 0x800FFAC0, 0xBEEF0033, 0x1
|
||||
.4byte 0x800E3130, 0xBEEF0077, 0x1
|
||||
.4byte 0x808017E0, 0xBEEF0099, 0x1
|
||||
.4byte 0x80805EA0, 0xBEEF0440, 0x1
|
||||
.4byte 0x80803AA0, 0xBEEF0BB0, 0x1
|
||||
.4byte 0x8000FFA0, 0x11100393, 0x1
|
||||
.4byte 0x8000FFA4, 0x00008067, 0x1
|
||||
.4byte 0x0, 0x0, goto_baremetal # satp.MODE = baremetal / no translation.
|
||||
.4byte 0x0, 0x0, goto_s_mode # change to S mode, 0xb written to output
|
||||
.4byte 0x800AAAA8, 0xBEEF0055, read32_test
|
||||
.4byte 0x800FFAC0, 0xBEEF0033, read32_test
|
||||
.4byte 0x800E3130, 0xBEEF0077, read32_test
|
||||
.4byte 0x808017E0, 0xBEEF0099, read32_test
|
||||
.4byte 0x80805EA0, 0xBEEF0440, read32_test
|
||||
.4byte 0x80803AA0, 0xBEEF0BB0, read32_test
|
||||
.4byte 0x8000FFA0, 0x11100393, read32_test
|
||||
.4byte 0x8000FFA4, 0x00008067, read32_test
|
||||
|
||||
# test 12.3.1.1.4 check translation works in sv48, read the same values from previous tests, this time with Vaddrs
|
||||
.4byte 0x0, 0x0, 0x5 # satp.MODE = sv32, Nothing written to output
|
||||
.4byte 0x4AAAA8, 0xBEEF0055, 0x1 # megapage at Vaddr 0x400000, Paddr 0x80000000
|
||||
.4byte 0xBFF7E0, 0xBEEF0099, 0x1 # kilopage at Vaddr 0xBFF000, Paddr 0x80201000
|
||||
.4byte 0x0, 0x0, goto_sv32 # satp.MODE = sv32, Nothing written to output
|
||||
.4byte 0x4AAAA8, 0xBEEF0055, read32_test # megapage at Vaddr 0x400000, Paddr 0x80000000
|
||||
.4byte 0xBFF7E0, 0xBEEF0099, read32_test # kilopage at Vaddr 0xBFF000, Paddr 0x80201000
|
||||
|
||||
# =========== test 12.3.1.2 page fault tests ===========
|
||||
|
||||
@ -97,59 +97,59 @@
|
||||
# Not tested in rv32/sv32
|
||||
|
||||
# test 12.3.1.2.2 load page fault when reading an address where the valid flag is zero
|
||||
.4byte 0x6000, 0x0, 0x1
|
||||
.4byte 0x6000, 0x0, read32_test
|
||||
|
||||
# test 12.3.1.2.3 store page fault if PTE has W and ~R flags set
|
||||
.4byte 0x2000, 0x0, 0x0
|
||||
.4byte 0x2000, 0x0, write32_test
|
||||
|
||||
# test 12.3.1.2.4 Fault if last level PTE is a pointer
|
||||
.4byte 0x0200, 0x0, 0x1
|
||||
.4byte 0x0200, 0x0, read32_test
|
||||
|
||||
# test 12.3.1.2.5 load page fault on misaligned pages
|
||||
.4byte 0xC00000, 0x0, 0x1 # misaligned megapage
|
||||
.4byte 0xC00000, 0x0, read32_test # misaligned megapage
|
||||
|
||||
# =========== test 12.3.1.3 PTE Protection flags ===========
|
||||
|
||||
# test 12.3.1.3.1 User flag == 0
|
||||
# *** reads on pages with U=0 already tested in 12.3.1.1.4
|
||||
.4byte 0x40FFA0, 0x111, 0x2 # fetch success when U=0, priv=S
|
||||
.4byte 0x80400000, 0x1, 0xA # go to U mode, return to VPN 0x80400000 where PTE.U = 1. 0x9 written to output
|
||||
.4byte 0xBFFC80, 0xBEEF0550, 0x1 # load page fault when U=0, priv=U
|
||||
.4byte 0x40FFA0, 0xbad, 0x2 # instr page fault when U=0, priv=U
|
||||
.4byte 0x40FFA0, 0x111, executable_test # fetch success when U=0, priv=S
|
||||
.4byte 0x80400000, 0x1, goto_u_mode # go to U mode, return to VPN 0x80400000 where PTE.U = 1. 0x9 written to output
|
||||
.4byte 0xBFFC80, 0xBEEF0550, read32_test # load page fault when U=0, priv=U
|
||||
.4byte 0x40FFA0, 0xbad, executable_test # instr page fault when U=0, priv=U
|
||||
|
||||
# test 12.3.1.3.2 User flag == 1
|
||||
.4byte 0x804FFAC0, 0xBEEF0033, 0x1 # read success when U=1, priv=U
|
||||
.4byte 0x80000000, 0x1, 0x9 # go back to S mode, return to VPN 0x80000000 where PTE.U = 0. 0x8 written to output
|
||||
.4byte 0x0, 0x3, 0x7 # set sstatus.[MXR, SUM] = 11
|
||||
.4byte 0x804E3130, 0xBEEF0077, 0x1 # read success when U=1, priv=S, sstatus.SUM=1
|
||||
.4byte 0x8040FFA0, 0xbad, 0x2 # instr page fault when U=1, priv=S (with any sstatus.SUM)
|
||||
.4byte 0x0, 0x2, 0x7 # set sstatus.[MXR, SUM] = 10.
|
||||
.4byte 0x804FFAC0, 0xBEEF0033, 0x1 # load page fault when U-1, priv=S, sstatus.SUM=0
|
||||
.4byte 0x804FFAC0, 0xBEEF0033, read32_test # read success when U=1, priv=U
|
||||
.4byte 0x80000000, 0x1, goto_s_mode # go back to S mode, return to VPN 0x80000000 where PTE.U = 0. 0x8 written to output
|
||||
.4byte 0x0, 0x3, write_mxr_sum # set sstatus.[MXR, SUM] = 11
|
||||
.4byte 0x804E3130, 0xBEEF0077, read32_test # read success when U=1, priv=S, sstatus.SUM=1
|
||||
.4byte 0x8040FFA0, 0xbad, executable_test # instr page fault when U=1, priv=S (with any sstatus.SUM)
|
||||
.4byte 0x0, 0x2, write_mxr_sum # set sstatus.[MXR, SUM] = 10.
|
||||
.4byte 0x804FFAC0, 0xBEEF0033, read32_test # load page fault when U-1, priv=S, sstatus.SUM=0
|
||||
|
||||
# test 12.3.1.3.3 Read flag
|
||||
# *** reads on pages with R=1 already tested in 12.3.1.1.4
|
||||
.4byte 0x0, 0x1, 0x7 # set sstatus.[MXR, SUM] = 01.
|
||||
.4byte 0x5EA0, 0xBEEF0440, 0x1 # load page fault when R=0, sstatus.MXR=0
|
||||
.4byte 0x0, 0x3, 0x7 # set sstatus.[MXR, SUM] = 11.
|
||||
.4byte 0x5EA0, 0xBEEF0440, 0x1 # read success when R=0, MXR=1, X=1
|
||||
.4byte 0x0, 0x1, write_mxr_sum # set sstatus.[MXR, SUM] = 01.
|
||||
.4byte 0x5EA0, 0xBEEF0440, read32_test # load page fault when R=0, sstatus.MXR=0
|
||||
.4byte 0x0, 0x3, write_mxr_sum # set sstatus.[MXR, SUM] = 11.
|
||||
.4byte 0x5EA0, 0xBEEF0440, read32_test # read success when R=0, MXR=1, X=1
|
||||
|
||||
# test 12.3.1.3.4 Write flag
|
||||
.4byte 0xBFF290, 0xBEEF0110, 0x0 # write success when W=1
|
||||
.4byte 0xBFF290, 0xBEEF0110, 0x1 # check write success by reading
|
||||
.4byte 0x5B78, 0xBEEF0CC0, 0x0 # store page fault when W=0
|
||||
.4byte 0xBFF290, 0xBEEF0110, write32_test # write success when W=1
|
||||
.4byte 0xBFF290, 0xBEEF0110, read32_test # check write success by reading
|
||||
.4byte 0x5B78, 0xBEEF0CC0, write32_test # store page fault when W=0
|
||||
|
||||
# test 12.3.1.3.5 eXecute flag
|
||||
# *** fetches on pages with X = 1 already tested in 12.3.1.3.1
|
||||
.4byte 0xBFFDE0, 0xbad, 0x2 # instr page fault when X=0
|
||||
.4byte 0xBFFDE0, 0xbad, executable_test # instr page fault when X=0
|
||||
|
||||
# test 12.3.1.3.6 Accessed flag == 0
|
||||
.4byte 0x3020, 0xBEEF0770, 0x0 # store page fault when A=0
|
||||
.4byte 0x3808, 0xBEEF0990, 0x1 # load page fault when A=0
|
||||
.4byte 0x3020, 0xBEEF0770, write32_test # store page fault when A=0
|
||||
.4byte 0x3808, 0xBEEF0990, read32_test # load page fault when A=0
|
||||
|
||||
# test 12.3.1.3.7 Dirty flag == 0
|
||||
.4byte 0x4658, 0xBEEF0AA0, 0x0 # store page fault when D=0
|
||||
.4byte 0x4AA0, 0xBEEF0BB0, 0x1 # read success when D=0
|
||||
.4byte 0x4658, 0xBEEF0AA0, write32_test # store page fault when D=0
|
||||
.4byte 0x4AA0, 0xBEEF0BB0, read32_test # read success when D=0
|
||||
|
||||
# terminate tests
|
||||
.4byte 0x0, 0x0, 0x3 # brings us back into machine mode with a final ecall, writing 0x9 to the output.
|
||||
.4byte 0x0, 0x0, terminate_test # brings us back into machine mode with a final ecall, writing 0x9 to the output.
|
||||
|
||||
|
@ -34,7 +34,7 @@
|
||||
#define PLIC_BASE 0x0C000000
|
||||
#define PLIC_RANGE 0x03FFFFFF
|
||||
|
||||
#include "WALLY-TEST-LIB-32.S"
|
||||
#include "WALLY-TEST-LIB-32.h"
|
||||
// Test library includes and handler for each type of test, a trap handler, imperas compliance instructions
|
||||
// Ideally this should mean that a test can be written by simply adding .4byte statements as below.
|
||||
|
||||
@ -71,49 +71,49 @@
|
||||
# ----------------- CLINT ---------------------
|
||||
|
||||
# Use timecmp register as readable and writable section of the CLINT
|
||||
.4byte CLINT_BASE + 0x4000, 0xBEEF00B5, 0x0 # 32-bit write: success
|
||||
.4byte CLINT_BASE + 0x4000, 0xBEEF00B5, 0x1 # 32-bit read: success
|
||||
.4byte CLINT_BASE + 0x4000, 0xBEEF00B6, 0x12 # 16-bit write: success
|
||||
.4byte CLINT_BASE + 0x4000, 0xBEEF00B6, 0x15 # 16-bit read: success
|
||||
.4byte CLINT_BASE + 0x4000, 0xBEEF00B7, 0x13 # 08-bit write: success
|
||||
.4byte CLINT_BASE + 0x4000, 0xBEEF00B7, 0x16 # 08-bit read: success
|
||||
.4byte CLINT_BASE + 0x4000, 0xBEEF00B5, write32_test # 32-bit write: success
|
||||
.4byte CLINT_BASE + 0x4000, 0xBEEF00B5, read32_test # 32-bit read: success
|
||||
.4byte CLINT_BASE + 0x4000, 0xBEEF00B6, write16_test# 16-bit write: success
|
||||
.4byte CLINT_BASE + 0x4000, 0xBEEF00B6, read16_test# 16-bit read: success
|
||||
.4byte CLINT_BASE + 0x4000, 0xBEEF00B7, write08_test# 08-bit write: success
|
||||
.4byte CLINT_BASE + 0x4000, 0xBEEF00B7, read08_test# 08-bit read: success
|
||||
|
||||
.4byte CLINT_BASE, 0xbad, 0x2 # execute: instruction access fault
|
||||
.4byte CLINT_BASE, 0xbad, executable_test# execute: instruction access fault
|
||||
|
||||
# ----------------- PLIC ---------------------
|
||||
|
||||
# Write 0x2 instead of wider value to plic address because the register width might change.
|
||||
.4byte PLIC_BASE + 0x2000, 0x2, 0x0 # 32-bit write: success
|
||||
.4byte PLIC_BASE + 0x2000, 0x2, 0x1 # 32-bit read: success
|
||||
.4byte PLIC_BASE, 0xBEEF00BA, 0x12 # 16-bit write: store access fault
|
||||
.4byte PLIC_BASE, 0xBEEF00BA, 0x15 # 16-bit read: load access fault
|
||||
.4byte PLIC_BASE, 0xBEEF00BB, 0x13 # 08-bit write: store access fault
|
||||
.4byte PLIC_BASE, 0xBEEF00BB, 0x16 # 08-bit read: load access fault
|
||||
.4byte PLIC_BASE + 0x2000, 0x2, write32_test # 32-bit write: success
|
||||
.4byte PLIC_BASE + 0x2000, 0x2, read32_test # 32-bit read: success
|
||||
.4byte PLIC_BASE, 0xBEEF00BA, write16_test # 16-bit write: store access fault
|
||||
.4byte PLIC_BASE, 0xBEEF00BA, read16_test # 16-bit read: load access fault
|
||||
.4byte PLIC_BASE, 0xBEEF00BB, write08_test # 08-bit write: store access fault
|
||||
.4byte PLIC_BASE, 0xBEEF00BB, read08_test # 08-bit read: load access fault
|
||||
|
||||
.4byte PLIC_BASE, 0xbad, 0x2 # execute: instruction access fault
|
||||
.4byte PLIC_BASE, 0xbad, executable_test# execute: instruction access fault
|
||||
|
||||
# ----------------- UART0 ---------------------
|
||||
|
||||
.4byte UART_BASE, 0xBEEF00BD, 0x0 # 32-bit write: store access fault
|
||||
.4byte UART_BASE, 0xBEEF00BD, 0x1 # 32-bit read: load access fault
|
||||
.4byte UART_BASE, 0xBEEF00BE, 0x12 # 16-bit write: store access fault
|
||||
.4byte UART_BASE, 0xBEEF00BE, 0x15 # 16-bit read: load access fault
|
||||
.4byte UART_BASE, 0xBEEF00BD, write32_test # 32-bit write: store access fault
|
||||
.4byte UART_BASE, 0xBEEF00BD, read32_test # 32-bit read: load access fault
|
||||
.4byte UART_BASE, 0xBEEF00BE, write16_test# 16-bit write: store access fault
|
||||
.4byte UART_BASE, 0xBEEF00BE, read16_test# 16-bit read: load access fault
|
||||
# Different address for this test so that we write into a writable register in the uart.
|
||||
.4byte UART_BASE + 0x3, 0xBEEF00BF, 0x13 # 08-bit write: success
|
||||
.4byte UART_BASE + 0x3, 0xBEEF00BF, 0x16 # 08-bit read: success
|
||||
.4byte UART_BASE + 0x3, 0xBEEF00BF, write08_test# 08-bit write: success
|
||||
.4byte UART_BASE + 0x3, 0xBEEF00BF, read08_test# 08-bit read: success
|
||||
|
||||
.4byte UART_BASE, 0xbad, 0x2 # execute: instruction access fault
|
||||
.4byte UART_BASE, 0xbad, executable_test# execute: instruction access fault
|
||||
|
||||
# ----------------- GPIO ---------------------
|
||||
|
||||
.4byte GPIO_BASE + 0x8, 0xBEEF00C1, 0x0 # 32-bit write: success
|
||||
.4byte GPIO_BASE + 0x8, 0xBEEF00C1, 0x1 # 32-bit read: success
|
||||
.4byte GPIO_BASE, 0xBEEF00C2, 0x12 # 16-bit write: store access fault
|
||||
.4byte GPIO_BASE, 0xBEEF00C2, 0x15 # 16-bit read: load access fault
|
||||
.4byte GPIO_BASE, 0xBEEF00C3, 0x13 # 08-bit write: store access fault
|
||||
.4byte GPIO_BASE, 0xBEEF00C3, 0x16 # 08-bit read: load access fault
|
||||
.4byte GPIO_BASE + 0x8, 0xBEEF00C1, write32_test # 32-bit write: success
|
||||
.4byte GPIO_BASE + 0x8, 0xBEEF00C1, read32_test# 32-bit read: success
|
||||
.4byte GPIO_BASE, 0xBEEF00C2, write16_test # 16-bit write: store access fault
|
||||
.4byte GPIO_BASE, 0xBEEF00C2, read16_test # 16-bit read: load access fault
|
||||
.4byte GPIO_BASE, 0xBEEF00C3, write08_test # 08-bit write: store access fault
|
||||
.4byte GPIO_BASE, 0xBEEF00C3, read08_test # 08-bit read: load access fault
|
||||
|
||||
.4byte GPIO_BASE, 0xbad, 0x2 # execute: instruction access fault
|
||||
.4byte GPIO_BASE, 0xbad, executable_test# execute: instruction access fault
|
||||
|
||||
|
||||
# ----------------- Inaccessible ---------------------
|
||||
@ -121,32 +121,32 @@
|
||||
# show that load, store, and jalr cause faults in a region not defined by PMAs.
|
||||
|
||||
# Tests 'random' place in unimplemented memory
|
||||
.4byte 0x40000000, 0xBEEF00C7, 0x0 # 32-bit write: store access fault
|
||||
.4byte 0x40000000, 0xBEEF00C7, 0x1 # 32-bit read: load access fault
|
||||
.4byte 0x40000000, 0x111, 0x2 # execute: instruction access fault
|
||||
.4byte 0x40000000, 0xBEEF00C7, write32_test # 32-bit write: store access fault
|
||||
.4byte 0x40000000, 0xBEEF00C7, read32_test # 32-bit read: load access fault
|
||||
.4byte 0x40000000, 0x111, executable_test # execute: instruction access fault
|
||||
|
||||
# Tests just past the end of each peripheral
|
||||
.4byte (BOOTROM_BASE+BOOTROM_RANGE+1), 0xBEEF00C8, 0x0 # 32-bit write: store access fault
|
||||
.4byte (BOOTROM_BASE+BOOTROM_RANGE+1), 0xBEEF00C8, 0x1 # 32-bit read: load access fault
|
||||
.4byte (BOOTROM_BASE+BOOTROM_RANGE+1), 0x111, 0x2 # execute: instruction access fault
|
||||
.4byte (BOOTROM_BASE+BOOTROM_RANGE+1), 0xBEEF00C8, write32_test # 32-bit write: store access fault
|
||||
.4byte (BOOTROM_BASE+BOOTROM_RANGE+1), 0xBEEF00C8, read32_test # 32-bit read: load access fault
|
||||
.4byte (BOOTROM_BASE+BOOTROM_RANGE+1), 0x111, executable_test # execute: instruction access fault
|
||||
|
||||
.4byte (CLINT_BASE+CLINT_RANGE+1), 0xBEEF00C9, 0x0 # 32-bit write: store access fault
|
||||
.4byte (CLINT_BASE+CLINT_RANGE+1), 0xBEEF00C9, 0x1 # 32-bit read: load access fault
|
||||
.4byte (CLINT_BASE+CLINT_RANGE+1), 0x111, 0x2 # execute: instruction access fault
|
||||
.4byte (CLINT_BASE+CLINT_RANGE+1), 0xBEEF00C9, write32_test # 32-bit write: store access fault
|
||||
.4byte (CLINT_BASE+CLINT_RANGE+1), 0xBEEF00C9, read32_test # 32-bit read: load access fault
|
||||
.4byte (CLINT_BASE+CLINT_RANGE+1), 0x111, executable_test # execute: instruction access fault
|
||||
|
||||
.4byte (PLIC_BASE+PLIC_RANGE+1), 0xBEEF00CA, 0x0 # 32-bit write: store access fault
|
||||
.4byte (PLIC_BASE+PLIC_RANGE+1), 0xBEEF00CA, 0x1 # 32-bit read: load access fault
|
||||
.4byte (PLIC_BASE+PLIC_RANGE+1), 0x111, 0x2 # execute: instruction access fault
|
||||
.4byte (PLIC_BASE+PLIC_RANGE+1), 0xBEEF00CA, write32_test # 32-bit write: store access fault
|
||||
.4byte (PLIC_BASE+PLIC_RANGE+1), 0xBEEF00CA, read32_test # 32-bit read: load access fault
|
||||
.4byte (PLIC_BASE+PLIC_RANGE+1), 0x111, executable_test # execute: instruction access fault
|
||||
|
||||
.4byte (UART_BASE+UART_RANGE+1), 0xBEEF00CB, 0x13 # 08-bit write: store access fault
|
||||
.4byte (UART_BASE+UART_RANGE+1), 0xBEEF00CB, 0x16 # 08-bit read: load access fault
|
||||
.4byte (UART_BASE+UART_RANGE+1), 0x111, 0x2 # execute: instruction access fault
|
||||
.4byte (UART_BASE+UART_RANGE+1), 0xBEEF00CB, write08_test # 08-bit write: store access fault
|
||||
.4byte (UART_BASE+UART_RANGE+1), 0xBEEF00CB, read08_test # 08-bit read: load access fault
|
||||
.4byte (UART_BASE+UART_RANGE+1), 0x111, executable_test # execute: instruction access fault
|
||||
|
||||
.4byte (GPIO_BASE+GPIO_RANGE+1), 0xBEEF00CC, 0x0 # 32-bit write: store access fault
|
||||
.4byte (GPIO_BASE+GPIO_RANGE+1), 0xBEEF00CC, 0x1 # 32-bit read: load access fault
|
||||
.4byte (GPIO_BASE+GPIO_RANGE+1), 0x111, 0x2 # execute: instruction access fault
|
||||
.4byte (GPIO_BASE+GPIO_RANGE+1), 0xBEEF00CC, write32_test # 32-bit write: store access fault
|
||||
.4byte (GPIO_BASE+GPIO_RANGE+1), 0xBEEF00CC, read32_test # 32-bit read: load access fault
|
||||
.4byte (GPIO_BASE+GPIO_RANGE+1), 0x111, executable_test # execute: instruction access fault
|
||||
|
||||
.4byte 0x0, 0x0, 0x3 # terminate tests
|
||||
.4byte 0x0, 0x0, terminate_test # terminate tests
|
||||
|
||||
|
||||
|
||||
|
@ -21,7 +21,7 @@
|
||||
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
///////////////////////////////////////////
|
||||
|
||||
#include "WALLY-TEST-LIB-32.S"
|
||||
#include "WALLY-TEST-LIB-32.h"
|
||||
// Test library includes and handler for each type of test, a trap handler, imperas compliance instructions
|
||||
// Ideally this should mean that a test can be written by simply adding .4byte statements as below.
|
||||
|
||||
@ -45,70 +45,70 @@
|
||||
# Test 12.3.2.2.1 Config: Write known values and set PMP config according to table 12.4 in the *** riscv book, copied below
|
||||
|
||||
# write pmpaddr regs
|
||||
# | Reg | pmpaddr | pmpcfg | L | A | X | W | R | Comments |
|
||||
.4byte 0x0, 0x0FFFFFFF, 0xE # | 0 | 0x0FFFFFFF | 1F | 0 | NAPOT | 0 | 1 | 1 | I/O 00000000-7FFFFFFF RW |
|
||||
.4byte 0x1, 0x20040000, 0xE # | 1 | 0x20040000 | 00 | 0 | OFF | 0 | 0 | 0 | |
|
||||
.4byte 0x2, 0x2004003F, 0xE # | 2 | 0x2004003F | 09 | 0 | TOR | 0 | 0 | 1 | 80100000-801000FF R |
|
||||
.4byte 0x3, 0x20040080, 0xE # | 3 | 0x20040080 | 00 | 0 | OFF | 0 | 0 | 0 | |
|
||||
.4byte 0x4, 0x20040084, 0xE # | 4 | 0x20040084 | 0C | 0 | TOR | 1 | 0 | 0 | 80100200-80100210 X |
|
||||
.4byte 0x5, 0x200400C0, 0xE # | 5 | 0x200400C0 | 90 | 1 | NA4 | 0 | 0 | 0 | 80100300-80100303 locked out |
|
||||
.4byte 0x6, 0x2004013F, 0xE # | 6 | 0x2004013F | 18 | 0 | NAPOT | 0 | 0 | 0 | 80100400-801004FF no access |
|
||||
# | Reg | pmpaddr | pmpcfg | L | A | X | W | R | Comments |
|
||||
.4byte 0x0, 0x0FFFFFFF, write_pmpaddr_0 # | 0 | 0x0FFFFFFF | 1F | 0 | NAPOT | 0 | 1 | 1 | I/O 00000000-7FFFFFFF RW |
|
||||
.4byte 0x1, 0x20040000, write_pmpaddr_0 # | 1 | 0x20040000 | 00 | 0 | OFF | 0 | 0 | 0 | |
|
||||
.4byte 0x2, 0x2004003F, write_pmpaddr_0 # | 2 | 0x2004003F | 09 | 0 | TOR | 0 | 0 | 1 | 80100000-801000FF R |
|
||||
.4byte 0x3, 0x20040080, write_pmpaddr_0 # | 3 | 0x20040080 | 00 | 0 | OFF | 0 | 0 | 0 | |
|
||||
.4byte 0x4, 0x20040084, write_pmpaddr_0 # | 4 | 0x20040084 | 0C | 0 | TOR | 1 | 0 | 0 | 80100200-80100210 X |
|
||||
.4byte 0x5, 0x200400C0, write_pmpaddr_0 # | 5 | 0x200400C0 | 90 | 1 | NA4 | 0 | 0 | 0 | 80100300-80100303 locked out |
|
||||
.4byte 0x6, 0x2004013F, write_pmpaddr_0 # | 6 | 0x2004013F | 18 | 0 | NAPOT | 0 | 0 | 0 | 80100400-801004FF no access |
|
||||
# Pmpaddr 7-14 are all zeroed out in this test, so they don't need writes.
|
||||
.4byte 0xF, 0x2FFFFFFF, 0xE # | 15 | 0x2FFFFFFF | 1F | 0 | NAPOT | 1 | 1 | 1 | Main mem 80000000-FFFFFFFF RWX|
|
||||
.4byte 0xF, 0x2FFFFFFF, write_pmpaddr_0 # | 15 | 0x2FFFFFFF | 1F | 0 | NAPOT | 1 | 1 | 1 | Main mem 80000000-FFFFFFFF RWX|
|
||||
|
||||
# write pmpcfg regs with the information in the table above. this should also write the value of these registers to the output.
|
||||
.4byte 0x0, 0x0009001F, 0xD # write pmpcfg0, output 0x0009001F
|
||||
.4byte 0x1, 0x0018900C, 0xD # write pmpcfg1, output 0x0018900C
|
||||
.4byte 0x0, 0x0009001F, write_pmpcfg_0 # write pmpcfg0, output 0x0009001F
|
||||
.4byte 0x1, 0x0018900C, write_pmpcfg_0 # write pmpcfg1, output 0x0018900C
|
||||
# pmpcfg2 is zeroed out, so it doesn't need a write
|
||||
.4byte 0x3, 0x1F000000, 0xD # write pmpcfg3, output 0x1F000000
|
||||
.4byte 0x3, 0x1F000000, write_pmpcfg_0 # write pmpcfg3, output 0x1F000000
|
||||
|
||||
# write known values to memory where W=0. This should be possible since we're in machine mode.
|
||||
.4byte 0x80100010, 0x600DAA, 0x0 # write to pmpaddr 1-2 range
|
||||
.4byte 0x80100400, 0x600DBB, 0x0 # write to pmpaddr 6 range
|
||||
.4byte 0x80100010, 0x600DAA, write32_test # write to pmpaddr 1-2 range
|
||||
.4byte 0x80100400, 0x600DBB, write32_test # write to pmpaddr 6 range
|
||||
|
||||
# Write executable code to regions where X = 0, 1 in main memory
|
||||
.4byte 0x80100200, 0x11100393, 0x0 # write executable code for "li x7, 0x111; ret" to region with X=1 (PMP4)
|
||||
.4byte 0x80100204, 0x00008067, 0x0
|
||||
.4byte 0x80100020, 0x11100393, 0x0 # write same executable code to region with X=0 (PMP2)
|
||||
.4byte 0x80100024, 0x00008067, 0x0
|
||||
.4byte 0x80100200, 0x11100393, write32_test # write executable code for "li x7, 0x111; ret" to region with X=1 (PMP4)
|
||||
.4byte 0x80100204, 0x00008067, write32_test
|
||||
.4byte 0x80100020, 0x11100393, write32_test # write same executable code to region with X=0 (PMP2)
|
||||
.4byte 0x80100024, 0x00008067, write32_test
|
||||
|
||||
|
||||
# attempt to write to pmpaddr5 and pmp5cfg after lockout
|
||||
.4byte 0x1, 0x0018FF0C, 0xD # attempt to edit only pmp5cfg (pmpcfg1[8:15]) after lockout.
|
||||
.4byte 0x1, 0x0018FF0C, write_pmpcfg_0 # attempt to edit only pmp5cfg (pmpcfg1[8:15]) after lockout.
|
||||
# instruction ignored, output is 0x0018900C, NOT 0x0018FF0C
|
||||
.4byte 0x5, 0xFFFFFFFF, 0xE # attempt to edit pmpaddr5 after lockout.
|
||||
.4byte 0x5, 0xFFFFFFFF, write_pmpaddr_0 # attempt to edit pmpaddr5 after lockout.
|
||||
# instruction ignored, output is 0x200400C0, NOT 0xFFFFFFFF
|
||||
|
||||
# Test 12.3.2.2.2 Machine mode access
|
||||
|
||||
.4byte 0x80100300, 0x0, 0x1 # access fault to region with L=1, R=0. This one writes 0x5 as the mcause, not 0xd.
|
||||
.4byte 0x80100400, 0x0, 0x1 # successful access to region with L=X=W=R=0
|
||||
.4byte 0x80100300, 0x0, read32_test # access fault to region with L=1, R=0. This one writes 0x5 as the mcause, not 0xd.
|
||||
.4byte 0x80100400, 0x0, read32_test # successful access to region with L=X=W=R=0
|
||||
|
||||
# Test 12.3.2.2.3 System mode access
|
||||
|
||||
.4byte 0x0, 0x0, 0x9 # go to S mode. 0xb written to output
|
||||
.4byte 0x0, 0x0, goto_s_mode # go to S mode. 0xb written to output
|
||||
# test a write followed by a read to each region with R=W=1
|
||||
.4byte 0x80200000, 0x600D15, 0x0 # Write "good value" to RW range (PMP15)
|
||||
.4byte 0x80200000, 0x600D15, 0x1 # confirm write with read
|
||||
.4byte 0x80200000, 0x600D15, write32_test # Write "good value" to RW range (PMP15)
|
||||
.4byte 0x80200000, 0x600D15, read32_test # confirm write with read
|
||||
|
||||
# test a write followed by a read on the edges of a read-only range
|
||||
.4byte 0x800FFFF8, 0x600D02, 0x0 # Write "good value" just below read-only range (PMP2)
|
||||
.4byte 0x800FFFF8, 0x600D02, 0x1 # confirm write with read
|
||||
.4byte 0x80100100, 0x600D12, 0x0 # Write "good value" just above read-only range (PMP2)
|
||||
.4byte 0x80100100, 0x600D12, 0x1 # confirm write with read
|
||||
.4byte 0x800FFFF8, 0x600D02, write32_test # Write "good value" just below read-only range (PMP2)
|
||||
.4byte 0x800FFFF8, 0x600D02, read32_test # confirm write with read
|
||||
.4byte 0x80100100, 0x600D12, write32_test # Write "good value" just above read-only range (PMP2)
|
||||
.4byte 0x80100100, 0x600D12, read32_test # confirm write with read
|
||||
|
||||
# test a read from each read only range verify a write causes an access fault
|
||||
.4byte 0x80100010, 0xBAD, 0x0 # Write fault in read-only range (PMP2)
|
||||
.4byte 0x80100010, 0x600DAA, 0x1 # read correct value out
|
||||
.4byte 0x80100010, 0xBAD, write32_test # Write fault in read-only range (PMP2)
|
||||
.4byte 0x80100010, 0x600DAA, read32_test # read correct value out
|
||||
|
||||
# test read and write fault on region with no access
|
||||
.4byte 0x80100208, 0x600D15, 0x0 # Write fault on no-access range (PMP6)
|
||||
.4byte 0x80100208, 0x600D15, 0x1 # read fault on no-access range (PMP6)
|
||||
.4byte 0x80100208, 0x600D15, write32_test # Write fault on no-access range (PMP6)
|
||||
.4byte 0x80100208, 0x600D15, read32_test # read fault on no-access range (PMP6)
|
||||
|
||||
# test jalr to region with X=0 causes access fault
|
||||
.4byte 0x80100020, 0xbad, 0x2 # execute fault on no-execute range (PMP2)
|
||||
.4byte 0x80100020, 0xbad, executable_test # execute fault on no-execute range (PMP2)
|
||||
|
||||
# test jalr to region with X=1 returns successfully
|
||||
.4byte 0x80100200, 0x111, 0x2 # execute success when X=1
|
||||
.4byte 0x80100200, 0x111, executable_test # execute success when X=1
|
||||
|
||||
.4byte 0x0, 0x0, 0x3 // terminate tests
|
||||
.4byte 0x0, 0x0, terminate_test // terminate tests
|
||||
|
@ -1,609 +0,0 @@
|
||||
///////////////////////////////////////////
|
||||
//
|
||||
// WALLY-TEST-LIB-32.S
|
||||
//
|
||||
// Author: Kip Macsai-Goren <kmacsaigoren@g.hmc.edu>
|
||||
//
|
||||
// Created 2021-07-20
|
||||
//
|
||||
// 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 "model_test.h"
|
||||
#include "arch_test.h"
|
||||
RVTEST_ISA("RV32I")
|
||||
|
||||
.section .text.init
|
||||
.globl rvtest_entry_point
|
||||
rvtest_entry_point:
|
||||
RVMODEL_BOOT
|
||||
RVTEST_CODE_BEGIN
|
||||
|
||||
# ---------------------------------------------------------------------------------------------
|
||||
# Initialization Overview:
|
||||
#
|
||||
# Initialize x6 as a virtual pointer to the test results
|
||||
# Initialize x16 as a physical pointer to the test results
|
||||
# Set up stack pointer (sp = x2)
|
||||
# Set up the exception Handler, keeping the original handler in x4.
|
||||
#
|
||||
# ---------------------------------------------------------------------------------------------
|
||||
|
||||
# address for test results
|
||||
la x6, test_1_res
|
||||
la x16, test_1_res # x16 reserved for the physical address equivalent of x6 to be used in trap handlers
|
||||
# any time either is used, both must be updated.
|
||||
|
||||
# address for stack
|
||||
la sp, top_of_stack
|
||||
|
||||
# trap handler setup
|
||||
la x1, machine_trap_handler
|
||||
csrrw x4, mtvec, x1 # x4 reserved for "default" trap handler address that needs to be restored before halting this test.
|
||||
li a0, 0
|
||||
li a1, 0
|
||||
li a2, 0 # reset trap handler inputs to zero
|
||||
|
||||
# go to first test!
|
||||
j test_setup
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------------------------
|
||||
# General traps Handler
|
||||
#
|
||||
# Handles traps by branching to different behaviors based on mcause.
|
||||
#
|
||||
# Note that allowing the exception handler to change mode for a program is a huge security
|
||||
# hole, but this is an expedient way of writing tests that need different modes
|
||||
#
|
||||
# input parameters:
|
||||
#
|
||||
# a0 (x10):
|
||||
# 0: halt program with no failures
|
||||
# 1: halt program with failure in x11 = a1
|
||||
# 2: go to machine mode
|
||||
# 3: go to supervisor mode
|
||||
# 4: go to user mode
|
||||
# others: do nothing
|
||||
#
|
||||
# a1 (x11):
|
||||
# VPN for return address after changing privilege mode.
|
||||
# This should be the base VPN with no offset.
|
||||
# 0x0 : defaults to next instruction on the same page the trap was called on.
|
||||
#
|
||||
# a2 (x12):
|
||||
# Pagetype of the current address VPN before changing privilge mode
|
||||
# Used so that we can know how many bits of the adress are the offset.
|
||||
# Ignored if a1 == 0x0
|
||||
# 0: Kilopage
|
||||
# 1: Megapage
|
||||
#
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
machine_trap_handler:
|
||||
# The processor is always in machine mode when a trap takes us here
|
||||
# save registers on stack before using
|
||||
sw x1, -4(sp)
|
||||
sw x5, -8(sp)
|
||||
|
||||
# Record trap
|
||||
csrr x1, mcause # record the mcause
|
||||
sw x1, 0(x16)
|
||||
addi x6, x6, 4
|
||||
addi x16, x16, 4 # update pointers for logging results
|
||||
|
||||
# Respond to trap based on cause
|
||||
# All interrupts should return after being logged
|
||||
li x5, 0x8000000000000000 # if msb is set, it is an interrupt
|
||||
and x5, x5, x1
|
||||
bnez x5, trapreturn # return from interrupt
|
||||
# Other trap handling is specified in the vector Table
|
||||
slli x1, x1, 2 # multiply cause by 4 to get offset in vector Table
|
||||
la x5, trap_handler_vector_table
|
||||
add x5, x5, x1 # compute address of vector in Table
|
||||
lw x5, 0(x5) # fectch address of handler from vector Table
|
||||
jr x5 # and jump to the handler
|
||||
|
||||
segfault:
|
||||
lw x5, -8(sp) # restore registers from stack before faulting
|
||||
lw x1, -4(sp)
|
||||
j terminate_test # halt program.
|
||||
|
||||
trapreturn:
|
||||
# look at the instruction to figure out whether to add 2 or 4 bytes to PC, or go to address specified in a1
|
||||
csrr x1, mepc # get the mepc
|
||||
addi x1, x1, 4 # *** should be 2 for compressed instructions, see note.
|
||||
|
||||
|
||||
# ****** KMG: the following is no longer as easy to determine. mepc gets the virtual address of the trapped instruction,
|
||||
# ******** but in the handler, we work in M mode with physical addresses
|
||||
# This means the address in mepc is suddenly pointing somewhere else.
|
||||
# to get this to work, We could either retranslate the vaddr back into a paddr (probably on the scale of difficult to intractible)
|
||||
# or we could come up with some other ingenious way to stay in M mode and see if the instruction was compressed.
|
||||
|
||||
# lw x5, 0(x1) # read the faulting instruction
|
||||
# li x1, 3 # check bottom 2 bits of instruction to see if compressed
|
||||
# and x5, x5, x1 # mask the other bits
|
||||
# beq x5, x1, trapreturn_uncompressed # if 11, the instruction is return_uncompressed
|
||||
|
||||
# trapreturn_compressed:
|
||||
# csrr x1, mepc # get the mepc again
|
||||
# addi x1, x1, 2 # add 2 to find the next instruction
|
||||
# j trapreturn_specified # and return
|
||||
|
||||
# trapreturn_uncompressed:
|
||||
# csrr x1, mepc # get the mepc again
|
||||
# addi x1, x1, 4 # add 4 to find the next instruction
|
||||
|
||||
trapreturn_specified:
|
||||
# reset the necessary pointers and registers (x1, x5, x6, and the return address going to mepc)
|
||||
# so that when we return to a new virtual address, they're all in the right spot as well.
|
||||
|
||||
beqz a1, trapreturn_finished # either update values, of go to default return address.
|
||||
|
||||
la x5, trap_return_pagetype_table
|
||||
slli a2, a2, 2
|
||||
add x5, x5, a2
|
||||
lw a2, 0(x5) # a2 = number of offset bits in current page type
|
||||
|
||||
li x5, 1
|
||||
sll x5, x5, a2
|
||||
addi x5, x5, -1 # x5 = mask bits for offset into current pagetype
|
||||
|
||||
# reset the top of the stack, x1
|
||||
lw x7, -4(sp)
|
||||
and x7, x5, x7 # x7 = offset for x1
|
||||
add x7, x7, a1 # x7 = new address for x1
|
||||
sw x7, -4(sp)
|
||||
|
||||
# reset the second spot in the stack, x5
|
||||
lw x7, -8(sp)
|
||||
and x7, x5, x7 # x7 = offset for x5
|
||||
add x7, x7, a1 # x7 = new address for x5
|
||||
sw x7, -8(sp)
|
||||
|
||||
# reset x6, the pointer for the virtual address of the output of the tests
|
||||
and x7, x5, x6 # x7 = offset for x6
|
||||
add x6, x7, a1 # x6 = new address for the result pointer
|
||||
|
||||
# set return address, stored temporarily in x1, to the next instruction, but in the new virtual page.
|
||||
and x1, x5, x1 # x1 = offset for the return address
|
||||
add x1, x1, a1 # x1 = new return address.
|
||||
|
||||
li a1, 0
|
||||
li a2, 0 # reset trapreturn inputs to the trap handler
|
||||
|
||||
trapreturn_finished:
|
||||
csrw mepc, x1 # update the mepc with address of next instruction
|
||||
lw x5, -8(sp) # restore registers from stack before returning
|
||||
lw x1, -4(sp)
|
||||
mret # return from trap
|
||||
|
||||
ecallhandler:
|
||||
# Check input parameter a0. encoding above.
|
||||
# *** ASSUMES: that this trap is being handled in machine mode. in other words, that nothing odd has been written to the medeleg or mideleg csrs.
|
||||
li x5, 2 # case 2: change to machine mode
|
||||
beq a0, x5, ecallhandler_changetomachinemode
|
||||
li x5, 3 # case 3: change to supervisor mode
|
||||
beq a0, x5, ecallhandler_changetosupervisormode
|
||||
li x5, 4 # case 4: change to user mode
|
||||
beq a0, x5, ecallhandler_changetousermode
|
||||
# unsupported ecalls should segfault
|
||||
j segfault
|
||||
|
||||
ecallhandler_changetomachinemode:
|
||||
# Force mstatus.MPP (bits 12:11) to 11 to enter machine mode after mret
|
||||
li x1, 0b1100000000000
|
||||
csrs mstatus, x1
|
||||
j trapreturn
|
||||
|
||||
ecallhandler_changetosupervisormode:
|
||||
# Force mstatus.MPP (bits 12:11) to 01 to enter supervisor mode after mret
|
||||
li x1, 0b1100000000000
|
||||
csrc mstatus, x1
|
||||
li x1, 0b0100000000000
|
||||
csrs mstatus, x1
|
||||
j trapreturn
|
||||
|
||||
ecallhandler_changetousermode:
|
||||
# Force mstatus.MPP (bits 12:11) to 00 to enter user mode after mret
|
||||
li x1, 0b1100000000000
|
||||
csrc mstatus, x1
|
||||
j trapreturn
|
||||
|
||||
instrfault:
|
||||
lw x1, -4(sp) # load return address int x1 (the address after the jal into faulting page)
|
||||
j trapreturn_finished # puts x1 into mepc, restores stack and returns to program (outside of faulting page)
|
||||
|
||||
accessfault:
|
||||
# *** What do I have to do here?
|
||||
j trapreturn
|
||||
# Table of trap behavior
|
||||
# lists what to do on each exception (not interrupts)
|
||||
# unexpected exceptions should cause segfaults for easy detection
|
||||
# Expected exceptions should increment the EPC to the next instruction and return
|
||||
|
||||
.align 2 # aligns this data table to an 4 byte boundary
|
||||
trap_handler_vector_table:
|
||||
.4byte segfault # 0: instruction address misaligned
|
||||
.4byte instrfault # 1: instruction access fault
|
||||
.4byte segfault # 2: illegal instruction
|
||||
.4byte segfault # 3: breakpoint
|
||||
.4byte segfault # 4: load address misaligned
|
||||
.4byte accessfault # 5: load access fault
|
||||
.4byte segfault # 6: store address misaligned
|
||||
.4byte accessfault # 7: store access fault
|
||||
.4byte ecallhandler # 8: ecall from U-mode
|
||||
.4byte ecallhandler # 9: ecall from S-mode
|
||||
.4byte segfault # 10: reserved
|
||||
.4byte ecallhandler # 11: ecall from M-mode
|
||||
.4byte instrfault # 12: instruction page fault
|
||||
.4byte trapreturn # 13: load page fault
|
||||
.4byte segfault # 14: reserved
|
||||
.4byte trapreturn # 15: store page fault
|
||||
|
||||
.align 2
|
||||
trap_return_pagetype_table:
|
||||
.4byte 0xC # 0: kilopage has 12 offset bits
|
||||
.4byte 0x16 # 1: megapage has 22 offset bits
|
||||
|
||||
# ---------------------------------------------------------------------------------------------
|
||||
# Test Handler
|
||||
#
|
||||
# This test handler works in a similar wy to the trap handler. It takes in a few things by reading from a table in memory
|
||||
# (see test_cases) and performing certain behavior based on them.
|
||||
#
|
||||
# Input parameters:
|
||||
#
|
||||
# x28:
|
||||
# Address input for the test taking place (think address to read/write, new address to return to, etc...)
|
||||
#
|
||||
# x29:
|
||||
# Value input for the test taking place (think value to write, any other extra info needed)
|
||||
#
|
||||
# x30:
|
||||
# Test type input that determines which kind of test will take place. Encoding for this input is in the table/case statements below
|
||||
#
|
||||
# ------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
test_setup:
|
||||
la x5, test_cases
|
||||
|
||||
test_loop:
|
||||
lw x28, 0(x5) # fetch test case address
|
||||
lw x29, 4(x5) # fetch test case value
|
||||
lw x30, 8(x5) # fetch test case flag
|
||||
addi x5, x5, 12 # set x5 to next test case
|
||||
|
||||
slli x30, x30, 2 # multiply test type by 4 to index into jump table
|
||||
la x7, test_jump_table # load base address of jump table
|
||||
add x7, x7, x30 # get address of jump table entry
|
||||
jr x7 # jump to relevant test
|
||||
|
||||
test_jump_table:
|
||||
# x30 Value : Function : Fault output value : Normal output values
|
||||
# ----------:---------------------------------------:------------------------:------------------------------------------------------
|
||||
j write32_test # 0x0 : Write 32 bits to address : 0xf : None
|
||||
j read32_test # 0x1 : Read 32 bits from address : 0xd, 0xbad : readvalue in hex
|
||||
j executable_test # 0x2 : test executable at address : 0xc, 0xbad : leading 12 bits of the li instr written to address. In general this is 0x111. (be sure to also write a return instruction)
|
||||
j terminate_test # 0x3 : terminate tests : mcause value for fault : from M 0xb, from S 0x9, from U 0x8
|
||||
j goto_baremetal # 0x4 : satp.MODE = bare metal : None : None
|
||||
j goto_sv32 # 0x5 : satp.MODE = sv32 : None : None
|
||||
j segfault # 0x6 : Segfault, undefined test
|
||||
j write_mxr_sum # 0x7 : write sstatus.[19:18] = MXR, SUM bits : None : None
|
||||
j goto_m_mode # 0x8 : go to mahcine mode : mcause value for fault : from M 0xb, from S 0x9, from U 0x8
|
||||
j goto_s_mode # 0x9 : go to supervisor mode : mcause value for fault : from M 0xb, from S 0x9, from U 0x8
|
||||
j goto_u_mode # 0xA : go to user mode : mcause value for fault : from M 0xb, from S 0x9, from U 0x8
|
||||
j segfault # 0xB : Segfault, undefined test
|
||||
j segfault # 0xC : Segfault, undefined test
|
||||
j write_pmpcfg_0 # 0xD : Write one of the pmpcfg csr's : mstatuses?, 0xD : readback of pmpcfg value
|
||||
j write_pmpaddr_0 # 0xE : Write one of the pmpaddr csr's : None : readback of pmpaddr value
|
||||
j segfault # 0xF : Segfault, undefined test
|
||||
j segfault # 0x10 : Segfault, undefined test
|
||||
j segfault # 0x11 : Segfault, undefined test
|
||||
j write16_test # 0x12 : Write 16 bits to address : 0xf : None
|
||||
j write08_test # 0x13 : Write 8 bits to address : 0xf : None
|
||||
j segfault # 0x14 : Segfault, undefined test
|
||||
j read16_test # 0x15 : Read 16 bits from address : 0xd, 0xbad : readvalue in hex
|
||||
j read08_test # 0x16 : Read 8 bits from address : 0xd, 0xbad : readvalue in hex
|
||||
|
||||
write32_test:
|
||||
# address to write in x28, word value in x29
|
||||
sw x29, 0(x28)
|
||||
j test_loop # go to next test case
|
||||
|
||||
write16_test:
|
||||
# address to write in x28, halfword value in x29
|
||||
sh x29, 0(x28)
|
||||
j test_loop # go to next test case
|
||||
|
||||
write08_test:
|
||||
# address to write in x28, value in x29
|
||||
sb x29, 0(x28)
|
||||
j test_loop # go to next test case
|
||||
|
||||
read32_test:
|
||||
# address to read in x28, expected 32 bit value in x29 (unused, but there for your perusal).
|
||||
li x7, 0xBAD # bad value that will be overwritten on good reads.
|
||||
lw x7, 0(x28)
|
||||
sw x7, 0(x6)
|
||||
addi x6, x6, 4
|
||||
addi x16, x16, 4
|
||||
j test_loop # go to next test case
|
||||
|
||||
read16_test:
|
||||
# address to read in x28, expected 16 bit value in x29 (unused, but there for your perusal).
|
||||
li x7, 0xBAD # bad value that will be overwritten on good reads.
|
||||
lh x7, 0(x28)
|
||||
sw x7, 0(x6)
|
||||
addi x6, x6, 4
|
||||
addi x16, x16, 4
|
||||
j test_loop # go to next test case
|
||||
|
||||
read08_test:
|
||||
# address to read in x28, expected 8 bit value in x29 (unused, but there for your perusal).
|
||||
li x7, 0xBAD # bad value that will be overwritten on good reads.
|
||||
lb x7, 0(x28)
|
||||
sw x7, 0(x6)
|
||||
addi x6, x6, 4
|
||||
addi x16, x16, 4
|
||||
j test_loop # go to next test case
|
||||
|
||||
|
||||
goto_s_mode:
|
||||
li a0, 3 # Trap handler behavior (go to machine mode)
|
||||
mv a1, x28 # return VPN
|
||||
mv a2, x29 # return page types
|
||||
ecall # writes mcause to the output.
|
||||
# now in S mode
|
||||
j test_loop
|
||||
|
||||
goto_m_mode:
|
||||
li a0, 2 # Trap handler behavior (go to machine mode)
|
||||
mv a1, x28 # return VPN
|
||||
mv a2, x29 # return page types
|
||||
ecall # writes mcause to the output.
|
||||
j test_loop
|
||||
|
||||
goto_u_mode:
|
||||
li a0, 4 # Trap handler behavior (go to user mode)
|
||||
mv a1, x28 # return VPN
|
||||
mv a2, x29 # return page types
|
||||
ecall # writes mcause to the output.
|
||||
j test_loop
|
||||
|
||||
goto_baremetal:
|
||||
# Turn translation off
|
||||
li x7, 0 # satp.MODE value for bare metal (0)
|
||||
slli x7, x7, 31
|
||||
li x28, 0x8000D # Base Pagetable physical page number, satp.PPN field.
|
||||
add x7, x7, x28
|
||||
csrw satp, x7
|
||||
sfence.vma x0, x0 # *** flushes global pte's as well. Be careful
|
||||
j test_loop # go to next test case
|
||||
|
||||
goto_sv32:
|
||||
li x7, 1 # satp.MODE value for Sv39 (1)
|
||||
slli x7, x7, 31
|
||||
li x28, 0x8000D # Base Pagetable physical page number, satp.PPN field.
|
||||
add x7, x7, x28
|
||||
csrw satp, x7
|
||||
sfence.vma x0, x0 # *** flushes global pte's as well. Be careful
|
||||
j test_loop # go to next test case
|
||||
|
||||
write_mxr_sum:
|
||||
# writes sstatus.[mxr, sum] with the (assumed to be) 2 bit value in x29. also assumes we're in S. M mode
|
||||
li x30, 0xC0000 # mask bits for MXR, SUM
|
||||
not x7, x29
|
||||
slli x7, x7, 18
|
||||
and x7, x7, x30
|
||||
slli x29, x29, 18
|
||||
csrc sstatus, x7
|
||||
csrs sstatus, x29
|
||||
j test_loop
|
||||
|
||||
write_pmpcfg_0:
|
||||
# writes the value in x29 to the pmpcfg register specified in x28.
|
||||
li x7, 0x0
|
||||
bne x7, x28, write_pmpcfg_1
|
||||
csrw pmpcfg0, x29
|
||||
csrr x30, pmpcfg0
|
||||
write_pmpcfg_1:
|
||||
li x7, 0x1
|
||||
bne x7, x28, write_pmpcfg_2
|
||||
csrw pmpcfg1, x29
|
||||
csrr x30, pmpcfg1
|
||||
write_pmpcfg_2:
|
||||
li x7, 0x2
|
||||
bne x7, x28, write_pmpcfg_3
|
||||
csrw pmpcfg2, x29
|
||||
csrr x30, pmpcfg2
|
||||
write_pmpcfg_3:
|
||||
li x7, 0x3
|
||||
bne x7, x28, write_pmpcfg_end
|
||||
csrw pmpcfg3, x29
|
||||
csrr x30, pmpcfg3
|
||||
write_pmpcfg_end:
|
||||
sw x30, 0(x6)
|
||||
addi x6, x6, 4
|
||||
addi x16, x16, 4
|
||||
j test_loop
|
||||
|
||||
write_pmpaddr_0:
|
||||
# writes the value in x29 to the pmpaddr register specified in x28.
|
||||
# then writes the final value of pmpaddrX to the output.
|
||||
li x7, 0x0
|
||||
bne x7, x28, write_pmpaddr_1
|
||||
csrw pmpaddr0, x29
|
||||
csrr x30, pmpaddr0
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_1:
|
||||
li x7, 0x1
|
||||
bne x7, x28, write_pmpaddr_2
|
||||
csrw pmpaddr1, x29
|
||||
csrr x30, pmpaddr1
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_2:
|
||||
li x7, 0x2
|
||||
bne x7, x28, write_pmpaddr_3
|
||||
csrw pmpaddr2, x29
|
||||
csrr x30, pmpaddr2
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_3:
|
||||
li x7, 0x3
|
||||
bne x7, x28, write_pmpaddr_4
|
||||
csrw pmpaddr3, x29
|
||||
csrr x30, pmpaddr3
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_4:
|
||||
li x7, 0x4
|
||||
bne x7, x28, write_pmpaddr_5
|
||||
csrw pmpaddr4, x29
|
||||
csrr x30, pmpaddr4
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_5:
|
||||
li x7, 0x5
|
||||
bne x7, x28, write_pmpaddr_6
|
||||
csrw pmpaddr5, x29
|
||||
csrr x30, pmpaddr5
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_6:
|
||||
li x7, 0x6
|
||||
bne x7, x28, write_pmpaddr_7
|
||||
csrw pmpaddr6, x29
|
||||
csrr x30, pmpaddr6
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_7:
|
||||
li x7, 0x7
|
||||
bne x7, x28, write_pmpaddr_8
|
||||
csrw pmpaddr7, x29
|
||||
csrr x30, pmpaddr7
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_8:
|
||||
li x7, 0x8
|
||||
bne x7, x28, write_pmpaddr_9
|
||||
csrw pmpaddr8, x29
|
||||
csrr x30, pmpaddr8
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_9:
|
||||
li x7, 0x9
|
||||
bne x7, x28, write_pmpaddr_10
|
||||
csrw pmpaddr9, x29
|
||||
csrr x30, pmpaddr9
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_10:
|
||||
li x7, 0xA
|
||||
bne x7, x28, write_pmpaddr_11
|
||||
csrw pmpaddr10, x29
|
||||
csrr x30, pmpaddr10
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_11:
|
||||
li x7, 0xB
|
||||
bne x7, x28, write_pmpaddr_12
|
||||
csrw pmpaddr11, x29
|
||||
csrr x30, pmpaddr11
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_12:
|
||||
li x7, 0xC
|
||||
bne x7, x28, write_pmpaddr_13
|
||||
csrw pmpaddr12, x29
|
||||
csrr x30, pmpaddr12
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_13:
|
||||
li x7, 0xD
|
||||
bne x7, x28, write_pmpaddr_14
|
||||
csrw pmpaddr13, x29
|
||||
csrr x30, pmpaddr13
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_14:
|
||||
li x7, 0xE
|
||||
bne x7, x28, write_pmpaddr_15
|
||||
csrw pmpaddr14, x29
|
||||
csrr x30, pmpaddr14
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_15:
|
||||
li x7, 0xF
|
||||
bne x7, x28, write_pmpaddr_end
|
||||
csrw pmpaddr15, x29
|
||||
csrr x30, pmpaddr15
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_end:
|
||||
sw x30, 0(x6)
|
||||
addi x6, x6, 4
|
||||
addi x16, x16, 4
|
||||
j test_loop
|
||||
|
||||
executable_test:
|
||||
# Execute the code at the address in x28, returning the value in x7.
|
||||
# Assumes the code modifies x7, to become the value stored in x29 for this test.
|
||||
fence.i # forces cache and main memory to sync so execution code written by the program can run.
|
||||
li x7, 0xBAD
|
||||
jalr x28
|
||||
sw x7, 0(x6)
|
||||
addi x6, x6, 4
|
||||
addi x16, x16, 4
|
||||
j test_loop
|
||||
|
||||
|
||||
|
||||
terminate_test:
|
||||
|
||||
li a0, 2 # Trap handler behavior (go to machine mode)
|
||||
ecall # writes mcause to the output.
|
||||
csrw mtvec, x4 # restore original trap handler to halt program
|
||||
|
||||
|
||||
RVTEST_CODE_END
|
||||
RVMODEL_HALT
|
||||
|
||||
RVTEST_DATA_BEGIN
|
||||
.align 4
|
||||
rvtest_data:
|
||||
.word 0xbabecafe
|
||||
RVTEST_DATA_END
|
||||
|
||||
.align 2 # align stack to 4 byte boundary
|
||||
bottom_of_stack:
|
||||
.fill 1024, 4, 0xdeadbeef
|
||||
top_of_stack:
|
||||
|
||||
|
||||
|
||||
RVMODEL_DATA_BEGIN
|
||||
|
||||
// next lines through test cases copied over from old framework
|
||||
test_1_res:
|
||||
.fill 1024, 4, 0xdeadbeef
|
||||
|
||||
RVMODEL_DATA_END
|
||||
|
||||
#ifdef rvtest_mtrap_routine
|
||||
|
||||
mtrap_sigptr:
|
||||
.fill 64*(XLEN/32),4,0xdeadbeef
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef rvtest_gpr_save
|
||||
|
||||
gpr_save:
|
||||
.fill 32*(XLEN/32),4,0xdeadbeef
|
||||
|
||||
#endif
|
||||
|
||||
.align 2
|
||||
test_cases:
|
||||
|
@ -0,0 +1,607 @@
|
||||
///////////////////////////////////////////
|
||||
//
|
||||
// WALLY-TEST-LIB-32.S
|
||||
//
|
||||
// Author: Kip Macsai-Goren <kmacsaigoren@g.hmc.edu>
|
||||
//
|
||||
// Created 2021-07-20
|
||||
//
|
||||
// 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 "model_test.h"
|
||||
#include "arch_test.h"
|
||||
RVTEST_ISA("RV32I")
|
||||
|
||||
.section .text.init
|
||||
.globl rvtest_entry_point
|
||||
rvtest_entry_point:
|
||||
RVMODEL_BOOT
|
||||
RVTEST_CODE_BEGIN
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
// Initialization Overview:
|
||||
//
|
||||
// Initialize x6 as a virtual pointer to the test results
|
||||
// Initialize x16 as a physical pointer to the test results
|
||||
// Set up stack pointer (sp = x2)
|
||||
// Set up the exception Handler, keeping the original handler in x4.
|
||||
//
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
|
||||
// address for test results
|
||||
la x6, test_1_res
|
||||
la x16, test_1_res // x16 reserved for the physical address equivalent of x6 to be used in trap handlers
|
||||
// any time either is used, both must be updated.
|
||||
|
||||
// address for stack
|
||||
la sp, top_of_stack
|
||||
|
||||
// trap handler setup
|
||||
la x1, machine_trap_handler
|
||||
csrrw x4, mtvec, x1 // x4 reserved for "default" trap handler address that needs to be restored before halting this test.
|
||||
li a0, 0
|
||||
li a1, 0
|
||||
li a2, 0 // reset trap handler inputs to zero
|
||||
|
||||
// go to first test!
|
||||
j test_setup
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
// General traps Handler
|
||||
//
|
||||
// Handles traps by branching to different behaviors based on mcause.
|
||||
//
|
||||
// Note that allowing the exception handler to change mode for a program is a huge security
|
||||
// hole, but this is an expedient way of writing tests that need different modes
|
||||
//
|
||||
// input parameters:
|
||||
//
|
||||
// a0 (x10):
|
||||
// 0: halt program with no failures
|
||||
// 1: halt program with failure in x11 = a1
|
||||
// 2: go to machine mode
|
||||
// 3: go to supervisor mode
|
||||
// 4: go to user mode
|
||||
// others: do nothing
|
||||
//
|
||||
// a1 (x11):
|
||||
// VPN for return address after changing privilege mode.
|
||||
// This should be the base VPN with no offset.
|
||||
// 0x0 : defaults to next instruction on the same page the trap was called on.
|
||||
//
|
||||
// a2 (x12):
|
||||
// Pagetype of the current address VPN before changing privilge mode
|
||||
// Used so that we can know how many bits of the adress are the offset.
|
||||
// Ignored if a1 == 0x0
|
||||
// 0: Kilopage
|
||||
// 1: Megapage
|
||||
//
|
||||
// --------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
machine_trap_handler:
|
||||
// The processor is always in machine mode when a trap takes us here
|
||||
// save registers on stack before using
|
||||
sw x1, -4(sp)
|
||||
sw x5, -8(sp)
|
||||
|
||||
// Record trap
|
||||
csrr x1, mcause // record the mcause
|
||||
sw x1, 0(x16)
|
||||
addi x6, x6, 4
|
||||
addi x16, x16, 4 // update pointers for logging results
|
||||
|
||||
// Respond to trap based on cause
|
||||
// All interrupts should return after being logged
|
||||
li x5, 0x8000000000000000 // if msb is set, it is an interrupt
|
||||
and x5, x5, x1
|
||||
bnez x5, trapreturn // return from interrupt
|
||||
// Other trap handling is specified in the vector Table
|
||||
slli x1, x1, 2 // multiply cause by 4 to get offset in vector Table
|
||||
la x5, trap_handler_vector_table
|
||||
add x5, x5, x1 // compute address of vector in Table
|
||||
lw x5, 0(x5) // fectch address of handler from vector Table
|
||||
jr x5 // and jump to the handler
|
||||
|
||||
segfault:
|
||||
lw x5, -8(sp) // restore registers from stack before faulting
|
||||
lw x1, -4(sp)
|
||||
j terminate_test // halt program.
|
||||
|
||||
trapreturn:
|
||||
// look at the instruction to figure out whether to add 2 or 4 bytes to PC, or go to address specified in a1
|
||||
csrr x1, mepc // get the mepc
|
||||
addi x1, x1, 4 // *** should be 2 for compressed instructions, see note.
|
||||
|
||||
|
||||
// ****** KMG: the following is no longer as easy to determine. mepc gets the virtual address of the trapped instruction,
|
||||
// ******** but in the handler, we work in M mode with physical addresses
|
||||
// This means the address in mepc is suddenly pointing somewhere else.
|
||||
// to get this to work, We could either retranslate the vaddr back into a paddr (probably on the scale of difficult to intractible)
|
||||
// or we could come up with some other ingenious way to stay in M mode and see if the instruction was compressed.
|
||||
|
||||
// lw x5, 0(x1) // read the faulting instruction
|
||||
// li x1, 3 // check bottom 2 bits of instruction to see if compressed
|
||||
// and x5, x5, x1 // mask the other bits
|
||||
// beq x5, x1, trapreturn_uncompressed // if 11, the instruction is return_uncompressed
|
||||
|
||||
// trapreturn_compressed:
|
||||
// csrr x1, mepc // get the mepc again
|
||||
// addi x1, x1, 2 // add 2 to find the next instruction
|
||||
// j trapreturn_specified // and return
|
||||
|
||||
// trapreturn_uncompressed:
|
||||
// csrr x1, mepc // get the mepc again
|
||||
// addi x1, x1, 4 // add 4 to find the next instruction
|
||||
|
||||
trapreturn_specified:
|
||||
// reset the necessary pointers and registers (x1, x5, x6, and the return address going to mepc)
|
||||
// so that when we return to a new virtual address, they're all in the right spot as well.
|
||||
|
||||
beqz a1, trapreturn_finished // either update values, of go to default return address.
|
||||
|
||||
la x5, trap_return_pagetype_table
|
||||
slli a2, a2, 2
|
||||
add x5, x5, a2
|
||||
lw a2, 0(x5) // a2 = number of offset bits in current page type
|
||||
|
||||
li x5, 1
|
||||
sll x5, x5, a2
|
||||
addi x5, x5, -1 // x5 = mask bits for offset into current pagetype
|
||||
|
||||
// reset the top of the stack, x1
|
||||
lw x7, -4(sp)
|
||||
and x7, x5, x7 // x7 = offset for x1
|
||||
add x7, x7, a1 // x7 = new address for x1
|
||||
sw x7, -4(sp)
|
||||
|
||||
// reset the second spot in the stack, x5
|
||||
lw x7, -8(sp)
|
||||
and x7, x5, x7 // x7 = offset for x5
|
||||
add x7, x7, a1 // x7 = new address for x5
|
||||
sw x7, -8(sp)
|
||||
|
||||
// reset x6, the pointer for the virtual address of the output of the tests
|
||||
and x7, x5, x6 // x7 = offset for x6
|
||||
add x6, x7, a1 // x6 = new address for the result pointer
|
||||
|
||||
// set return address, stored temporarily in x1, to the next instruction, but in the new virtual page.
|
||||
and x1, x5, x1 // x1 = offset for the return address
|
||||
add x1, x1, a1 // x1 = new return address.
|
||||
|
||||
li a1, 0
|
||||
li a2, 0 // reset trapreturn inputs to the trap handler
|
||||
|
||||
trapreturn_finished:
|
||||
csrw mepc, x1 // update the mepc with address of next instruction
|
||||
lw x5, -8(sp) // restore registers from stack before returning
|
||||
lw x1, -4(sp)
|
||||
mret // return from trap
|
||||
|
||||
ecallhandler:
|
||||
// Check input parameter a0. encoding above.
|
||||
// *** ASSUMES: that this trap is being handled in machine mode. in other words, that nothing odd has been written to the medeleg or mideleg csrs.
|
||||
li x5, 2 // case 2: change to machine mode
|
||||
beq a0, x5, ecallhandler_changetomachinemode
|
||||
li x5, 3 // case 3: change to supervisor mode
|
||||
beq a0, x5, ecallhandler_changetosupervisormode
|
||||
li x5, 4 // case 4: change to user mode
|
||||
beq a0, x5, ecallhandler_changetousermode
|
||||
// unsupported ecalls should segfault
|
||||
j segfault
|
||||
|
||||
ecallhandler_changetomachinemode:
|
||||
// Force mstatus.MPP (bits 12:11) to 11 to enter machine mode after mret
|
||||
li x1, 0b1100000000000
|
||||
csrs mstatus, x1
|
||||
j trapreturn
|
||||
|
||||
ecallhandler_changetosupervisormode:
|
||||
// Force mstatus.MPP (bits 12:11) to 01 to enter supervisor mode after mret
|
||||
li x1, 0b1100000000000
|
||||
csrc mstatus, x1
|
||||
li x1, 0b0100000000000
|
||||
csrs mstatus, x1
|
||||
j trapreturn
|
||||
|
||||
ecallhandler_changetousermode:
|
||||
// Force mstatus.MPP (bits 12:11) to 00 to enter user mode after mret
|
||||
li x1, 0b1100000000000
|
||||
csrc mstatus, x1
|
||||
j trapreturn
|
||||
|
||||
instrfault:
|
||||
lw x1, -4(sp) // load return address int x1 (the address after the jal into faulting page)
|
||||
j trapreturn_finished // puts x1 into mepc, restores stack and returns to program (outside of faulting page)
|
||||
|
||||
accessfault:
|
||||
// *** What do I have to do here?
|
||||
j trapreturn
|
||||
// Table of trap behavior
|
||||
// lists what to do on each exception (not interrupts)
|
||||
// unexpected exceptions should cause segfaults for easy detection
|
||||
// Expected exceptions should increment the EPC to the next instruction and return
|
||||
|
||||
.align 2 // aligns this data table to an 4 byte boundary
|
||||
trap_handler_vector_table:
|
||||
.4byte segfault // 0: instruction address misaligned
|
||||
.4byte instrfault // 1: instruction access fault
|
||||
.4byte segfault // 2: illegal instruction
|
||||
.4byte segfault // 3: breakpoint
|
||||
.4byte segfault // 4: load address misaligned
|
||||
.4byte accessfault // 5: load access fault
|
||||
.4byte segfault // 6: store address misaligned
|
||||
.4byte accessfault // 7: store access fault
|
||||
.4byte ecallhandler // 8: ecall from U-mode
|
||||
.4byte ecallhandler // 9: ecall from S-mode
|
||||
.4byte segfault // 10: reserved
|
||||
.4byte ecallhandler // 11: ecall from M-mode
|
||||
.4byte instrfault // 12: instruction page fault
|
||||
.4byte trapreturn // 13: load page fault
|
||||
.4byte segfault // 14: reserved
|
||||
.4byte trapreturn // 15: store page fault
|
||||
|
||||
.align 2
|
||||
trap_return_pagetype_table:
|
||||
.4byte 0xC // 0: kilopage has 12 offset bits
|
||||
.4byte 0x16 // 1: megapage has 22 offset bits
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
// Test Handler
|
||||
//
|
||||
// This test handler works in a similar wy to the trap handler. It takes in a few things by reading from a table in memory
|
||||
// (see test_cases) and performing certain behavior based on them.
|
||||
//
|
||||
// Input parameters:
|
||||
//
|
||||
// x28:
|
||||
// Address input for the test taking place (think address to read/write, new address to return to, etc...)
|
||||
//
|
||||
// x29:
|
||||
// Value input for the test taking place (think value to write, any other extra info needed)
|
||||
//
|
||||
// x30:
|
||||
// Test type input that determines which kind of test will take place. Encoding for this input is in the table/case statements below
|
||||
//
|
||||
// ------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
test_setup:
|
||||
la x5, test_cases
|
||||
|
||||
test_loop:
|
||||
lw x28, 0(x5) // fetch test case address
|
||||
lw x29, 4(x5) // fetch test case value
|
||||
lw x30, 8(x5) // fetch test case flag
|
||||
addi x5, x5, 12 // set x5 to next test case
|
||||
|
||||
// x5 has the symbol for a test's location in the assembly
|
||||
li x7, 0x3FFFFF
|
||||
and x30, x30, x7 // This program is always on at least a megapage, so this masks out the megapage offset.
|
||||
auipc x7, 0x0
|
||||
srli x7, x7, 22
|
||||
slli x7, x7, 22 // zero out the bottom 22 bits so the megapage offset of the symbol can be placed there
|
||||
or x30, x7, x30 // x30 = virtual address of the symbol for this type of test.
|
||||
|
||||
jr x30
|
||||
|
||||
// Test Name : Description : Fault output value : Normal output values
|
||||
// ----------------------:---------------------------------------:------------------------:------------------------------------------------------
|
||||
// write32_test : Write 32 bits to address : 0xf : None
|
||||
// write16_test : Write 16 bits to address : 0xf : None
|
||||
// write08_test : Write 8 bits to address : 0xf : None
|
||||
// read32_test : Read 32 bits from address : 0xd, 0xbad : readvalue in hex
|
||||
// read16_test : Read 16 bits from address : 0xd, 0xbad : readvalue in hex
|
||||
// read08_test : Read 8 bits from address : 0xd, 0xbad : readvalue in hex
|
||||
// executable_test : test executable at address : 0xc, 0xbad : leading 12 bits of the li instr written to address. In general this is 0x111. (be sure to also write a return instruction)
|
||||
// terminate_test : terminate tests : mcause value for fault : from M 0xb, from S 0x9, from U 0x8
|
||||
// goto_baremetal : satp.MODE = bare metal : None : None
|
||||
// goto_sv32 : satp.MODE = sv32 : None : None
|
||||
// write_mxr_sum : write sstatus.[19:18] = MXR, SUM bits : None : None
|
||||
// goto_m_mode : go to mahcine mode : mcause value for fault : from M 0xb, from S 0x9, from U 0x8
|
||||
// goto_s_mode : go to supervisor mode : mcause value for fault : from M 0xb, from S 0x9, from U 0x8
|
||||
// goto_u_mode : go to user mode : mcause value for fault : from M 0xb, from S 0x9, from U 0x8
|
||||
// write_pmpcfg_x : Write one of the pmpcfg csr's : mstatuses?, 0xD : readback of pmpcfg value
|
||||
// write_pmpaddr_x : Write one of the pmpaddr csr's : None : readback of pmpaddr value
|
||||
|
||||
|
||||
write32_test:
|
||||
// address to write in x28, word value in x29
|
||||
sw x29, 0(x28)
|
||||
j test_loop // go to next test case
|
||||
|
||||
write16_test:
|
||||
// address to write in x28, halfword value in x29
|
||||
sh x29, 0(x28)
|
||||
j test_loop // go to next test case
|
||||
|
||||
write08_test:
|
||||
// address to write in x28, value in x29
|
||||
sb x29, 0(x28)
|
||||
j test_loop // go to next test case
|
||||
|
||||
read32_test:
|
||||
// address to read in x28, expected 32 bit value in x29 (unused, but there for your perusal).
|
||||
li x7, 0xBAD // bad value that will be overwritten on good reads.
|
||||
lw x7, 0(x28)
|
||||
sw x7, 0(x6)
|
||||
addi x6, x6, 4
|
||||
addi x16, x16, 4
|
||||
j test_loop // go to next test case
|
||||
|
||||
read16_test:
|
||||
// address to read in x28, expected 16 bit value in x29 (unused, but there for your perusal).
|
||||
li x7, 0xBAD // bad value that will be overwritten on good reads.
|
||||
lh x7, 0(x28)
|
||||
sw x7, 0(x6)
|
||||
addi x6, x6, 4
|
||||
addi x16, x16, 4
|
||||
j test_loop // go to next test case
|
||||
|
||||
read08_test:
|
||||
// address to read in x28, expected 8 bit value in x29 (unused, but there for your perusal).
|
||||
li x7, 0xBAD // bad value that will be overwritten on good reads.
|
||||
lb x7, 0(x28)
|
||||
sw x7, 0(x6)
|
||||
addi x6, x6, 4
|
||||
addi x16, x16, 4
|
||||
j test_loop // go to next test case
|
||||
|
||||
|
||||
goto_s_mode:
|
||||
li a0, 3 // Trap handler behavior (go to machine mode)
|
||||
mv a1, x28 // return VPN
|
||||
mv a2, x29 // return page types
|
||||
ecall // writes mcause to the output.
|
||||
// now in S mode
|
||||
j test_loop
|
||||
|
||||
goto_m_mode:
|
||||
li a0, 2 // Trap handler behavior (go to machine mode)
|
||||
mv a1, x28 // return VPN
|
||||
mv a2, x29 // return page types
|
||||
ecall // writes mcause to the output.
|
||||
j test_loop
|
||||
|
||||
goto_u_mode:
|
||||
li a0, 4 // Trap handler behavior (go to user mode)
|
||||
mv a1, x28 // return VPN
|
||||
mv a2, x29 // return page types
|
||||
ecall // writes mcause to the output.
|
||||
j test_loop
|
||||
|
||||
goto_baremetal:
|
||||
// Turn translation off
|
||||
li x7, 0 // satp.MODE value for bare metal (0)
|
||||
slli x7, x7, 31
|
||||
li x28, 0x8000D // Base Pagetable physical page number, satp.PPN field.
|
||||
add x7, x7, x28
|
||||
csrw satp, x7
|
||||
sfence.vma x0, x0 // *** flushes global pte's as well. Be careful
|
||||
j test_loop // go to next test case
|
||||
|
||||
goto_sv32:
|
||||
li x7, 1 // satp.MODE value for Sv39 (1)
|
||||
slli x7, x7, 31
|
||||
li x28, 0x8000D // Base Pagetable physical page number, satp.PPN field.
|
||||
add x7, x7, x28
|
||||
csrw satp, x7
|
||||
sfence.vma x0, x0 // *** flushes global pte's as well. Be careful
|
||||
j test_loop // go to next test case
|
||||
|
||||
write_mxr_sum:
|
||||
// writes sstatus.[mxr, sum] with the (assumed to be) 2 bit value in x29. also assumes we're in S. M mode
|
||||
li x30, 0xC0000 // mask bits for MXR, SUM
|
||||
not x7, x29
|
||||
slli x7, x7, 18
|
||||
and x7, x7, x30
|
||||
slli x29, x29, 18
|
||||
csrc sstatus, x7
|
||||
csrs sstatus, x29
|
||||
j test_loop
|
||||
|
||||
write_pmpcfg_0:
|
||||
// writes the value in x29 to the pmpcfg register specified in x28.
|
||||
li x7, 0x0
|
||||
bne x7, x28, write_pmpcfg_1
|
||||
csrw pmpcfg0, x29
|
||||
csrr x30, pmpcfg0
|
||||
write_pmpcfg_1:
|
||||
li x7, 0x1
|
||||
bne x7, x28, write_pmpcfg_2
|
||||
csrw pmpcfg1, x29
|
||||
csrr x30, pmpcfg1
|
||||
write_pmpcfg_2:
|
||||
li x7, 0x2
|
||||
bne x7, x28, write_pmpcfg_3
|
||||
csrw pmpcfg2, x29
|
||||
csrr x30, pmpcfg2
|
||||
write_pmpcfg_3:
|
||||
li x7, 0x3
|
||||
bne x7, x28, write_pmpcfg_end
|
||||
csrw pmpcfg3, x29
|
||||
csrr x30, pmpcfg3
|
||||
write_pmpcfg_end:
|
||||
sw x30, 0(x6)
|
||||
addi x6, x6, 4
|
||||
addi x16, x16, 4
|
||||
j test_loop
|
||||
|
||||
write_pmpaddr_0:
|
||||
// writes the value in x29 to the pmpaddr register specified in x28.
|
||||
// then writes the final value of pmpaddrX to the output.
|
||||
li x7, 0x0
|
||||
bne x7, x28, write_pmpaddr_1
|
||||
csrw pmpaddr0, x29
|
||||
csrr x30, pmpaddr0
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_1:
|
||||
li x7, 0x1
|
||||
bne x7, x28, write_pmpaddr_2
|
||||
csrw pmpaddr1, x29
|
||||
csrr x30, pmpaddr1
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_2:
|
||||
li x7, 0x2
|
||||
bne x7, x28, write_pmpaddr_3
|
||||
csrw pmpaddr2, x29
|
||||
csrr x30, pmpaddr2
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_3:
|
||||
li x7, 0x3
|
||||
bne x7, x28, write_pmpaddr_4
|
||||
csrw pmpaddr3, x29
|
||||
csrr x30, pmpaddr3
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_4:
|
||||
li x7, 0x4
|
||||
bne x7, x28, write_pmpaddr_5
|
||||
csrw pmpaddr4, x29
|
||||
csrr x30, pmpaddr4
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_5:
|
||||
li x7, 0x5
|
||||
bne x7, x28, write_pmpaddr_6
|
||||
csrw pmpaddr5, x29
|
||||
csrr x30, pmpaddr5
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_6:
|
||||
li x7, 0x6
|
||||
bne x7, x28, write_pmpaddr_7
|
||||
csrw pmpaddr6, x29
|
||||
csrr x30, pmpaddr6
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_7:
|
||||
li x7, 0x7
|
||||
bne x7, x28, write_pmpaddr_8
|
||||
csrw pmpaddr7, x29
|
||||
csrr x30, pmpaddr7
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_8:
|
||||
li x7, 0x8
|
||||
bne x7, x28, write_pmpaddr_9
|
||||
csrw pmpaddr8, x29
|
||||
csrr x30, pmpaddr8
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_9:
|
||||
li x7, 0x9
|
||||
bne x7, x28, write_pmpaddr_10
|
||||
csrw pmpaddr9, x29
|
||||
csrr x30, pmpaddr9
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_10:
|
||||
li x7, 0xA
|
||||
bne x7, x28, write_pmpaddr_11
|
||||
csrw pmpaddr10, x29
|
||||
csrr x30, pmpaddr10
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_11:
|
||||
li x7, 0xB
|
||||
bne x7, x28, write_pmpaddr_12
|
||||
csrw pmpaddr11, x29
|
||||
csrr x30, pmpaddr11
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_12:
|
||||
li x7, 0xC
|
||||
bne x7, x28, write_pmpaddr_13
|
||||
csrw pmpaddr12, x29
|
||||
csrr x30, pmpaddr12
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_13:
|
||||
li x7, 0xD
|
||||
bne x7, x28, write_pmpaddr_14
|
||||
csrw pmpaddr13, x29
|
||||
csrr x30, pmpaddr13
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_14:
|
||||
li x7, 0xE
|
||||
bne x7, x28, write_pmpaddr_15
|
||||
csrw pmpaddr14, x29
|
||||
csrr x30, pmpaddr14
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_15:
|
||||
li x7, 0xF
|
||||
bne x7, x28, write_pmpaddr_end
|
||||
csrw pmpaddr15, x29
|
||||
csrr x30, pmpaddr15
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_end:
|
||||
sw x30, 0(x6)
|
||||
addi x6, x6, 4
|
||||
addi x16, x16, 4
|
||||
j test_loop
|
||||
|
||||
executable_test:
|
||||
// Execute the code at the address in x28, returning the value in x7.
|
||||
// Assumes the code modifies x7, to become the value stored in x29 for this test.
|
||||
fence.i // forces cache and main memory to sync so execution code written by the program can run.
|
||||
li x7, 0xBAD
|
||||
jalr x28
|
||||
sw x7, 0(x6)
|
||||
addi x6, x6, 4
|
||||
addi x16, x16, 4
|
||||
j test_loop
|
||||
|
||||
|
||||
|
||||
terminate_test:
|
||||
|
||||
li a0, 2 // Trap handler behavior (go to machine mode)
|
||||
ecall // writes mcause to the output.
|
||||
csrw mtvec, x4 // restore original trap handler to halt program
|
||||
|
||||
|
||||
RVTEST_CODE_END
|
||||
RVMODEL_HALT
|
||||
|
||||
RVTEST_DATA_BEGIN
|
||||
.align 4
|
||||
rvtest_data:
|
||||
.word 0xbabecafe
|
||||
RVTEST_DATA_END
|
||||
|
||||
.align 2 // align stack to 4 byte boundary
|
||||
bottom_of_stack:
|
||||
.fill 1024, 4, 0xdeadbeef
|
||||
top_of_stack:
|
||||
|
||||
|
||||
|
||||
RVMODEL_DATA_BEGIN
|
||||
|
||||
// next lines through test cases copied over from old framework
|
||||
test_1_res:
|
||||
.fill 1024, 4, 0xdeadbeef
|
||||
|
||||
RVMODEL_DATA_END
|
||||
|
||||
#ifdef rvtest_mtrap_routine
|
||||
|
||||
mtrap_sigptr:
|
||||
.fill 64*(XLEN/32),4,0xdeadbeef
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef rvtest_gpr_save
|
||||
|
||||
gpr_save:
|
||||
.fill 32*(XLEN/32),4,0xdeadbeef
|
||||
|
||||
#endif
|
||||
|
||||
.align 2
|
||||
test_cases:
|
||||
|
@ -30,7 +30,8 @@
|
||||
rv64i_sc_tests = \
|
||||
WALLY-MMU-SV39 \
|
||||
WALLY-MMU-SV48 \
|
||||
WALLY-PMP
|
||||
WALLY-PMP \
|
||||
WALLY-minfo-01
|
||||
|
||||
target_tests_nosim = WALLY-PMA \
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -21,7 +21,7 @@
|
||||
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
///////////////////////////////////////////
|
||||
|
||||
#include "WALLY-TEST-LIB-64.S"
|
||||
#include "WALLY-TEST-LIB-64.h"
|
||||
// Test library includes and handler for each type of test, a trap handler, imperas compliance instructions
|
||||
// Ideally this should mean that a test can be written by simply adding .8byte statements as below.
|
||||
|
||||
@ -44,126 +44,126 @@
|
||||
# test 12.3.1.1.1 write page tables / entries to phyiscal memory
|
||||
# sv39 page table (See Figure 12.12***):
|
||||
# Level 2 page table, situated at 0x8000D000
|
||||
.8byte 0x000000008000D000, 0x0000000020004C01, 0x0 # points to level 1 page table A
|
||||
.8byte 0x000000008000D008, 0x0000000020005001, 0x0 # points to level 1 page table B #*** replacing all the pointers DAU bits with 0.
|
||||
.8byte 0x000000008000D010, 0x00000000200000CF, 0x0 # Vaddr 0x8000_0000, Paddr 0x80000000: aligned gigapage (program and data memory)
|
||||
.8byte 0x000000008000D018, 0x00004000004000C7, 0x0 # Vaddr 0xC000_0000: misaligned gigapage
|
||||
.8byte 0x000000008000DFF8, 0x0000000020005401, 0x0 # points to level 1 page table C
|
||||
.8byte 0x000000008000D000, 0x0000000020004C01, write64_test# points to level 1 page table A
|
||||
.8byte 0x000000008000D008, 0x0000000020005001, write64_test# points to level 1 page table B #*** replacing all the pointers DAU bits with 0.
|
||||
.8byte 0x000000008000D010, 0x00000000200000CF, write64_test# Vaddr 0x8000_0000, Paddr 0x80000000: aligned gigapage (program and data memory)
|
||||
.8byte 0x000000008000D018, 0x00004000004000C7, write64_test# Vaddr 0xC000_0000: misaligned gigapage
|
||||
.8byte 0x000000008000DFF8, 0x0000000020005401, write64_test # points to level 1 page table C
|
||||
|
||||
# Level 1 page table A
|
||||
.8byte 0x0000000080013000, 0x0000000020006001, 0x0 # points to level 0 page table A
|
||||
.8byte 0x0000000080013000, 0x0000000020006001, write64_test# points to level 0 page table A
|
||||
|
||||
# Level 1 page table B
|
||||
.8byte 0x0000000080014000, 0x00000000200000CB, 0x0 # Vaddr 0x4000_0000, Paddr 0x80000000: aligned megapage, W=0, used for execution tests
|
||||
.8byte 0x0000000080014008, 0x00000400000080C3, 0x0 # Vaddr 0x4020_0000: misaligned megapage
|
||||
.8byte 0x0000000080014010, 0x00000000200000DF, 0x0 # Vaddr 0x4040_0000, Paddr 0x80000000: aligned megapage, aliased with program, U=1
|
||||
.8byte 0x0000000080014018, 0x00000000210800C9, 0x0 # Vaddr 0x4060_0000, Paddr 0x84200000: R=0, reads should fault
|
||||
.8byte 0x0000000080014000, 0x00000000200000CB, write64_test# Vaddr 0x4000_0000, Paddr 0x80000000: aligned megapage, W=0, used for execution tests
|
||||
.8byte 0x0000000080014008, 0x00000400000080C3, write64_test# Vaddr 0x4020_0000: misaligned megapage
|
||||
.8byte 0x0000000080014010, 0x00000000200000DF, write64_test# Vaddr 0x4040_0000, Paddr 0x80000000: aligned megapage, aliased with program, U=1
|
||||
.8byte 0x0000000080014018, 0x00000000210800C9, write64_test# Vaddr 0x4060_0000, Paddr 0x84200000: R=0, reads should fault
|
||||
# Level 1 page table C
|
||||
.8byte 0x0000000080015FF8, 0x0000000020005801, 0x0 # points to level 0 page table B
|
||||
.8byte 0x0000000080015FF8, 0x0000000020005801, write64_test# points to level 0 page table B
|
||||
|
||||
# Level 0 page table A
|
||||
.8byte 0x0000000080018000, 0x00000000200070D1, 0x0 # Vaddr 0x0000: bad PTE points to level -1 table
|
||||
.8byte 0x0000000080018008, 0x00000000200800DF, 0x0 # Vaddr 0x1000, Paddr = 0x80200000: aligned kilopage
|
||||
.8byte 0x0000000080018010, 0x00000000200810D5, 0x0 # Vaddr 0x2000: bad PTE has W but not R
|
||||
.8byte 0x0000000080018018, 0x0000000020080817, 0x0 # Vaddr 0x3000 Paddr 0x80202000: A=0, should cause read fault
|
||||
.8byte 0x0000000080018020, 0x0000000020080C57, 0x0 # Vaddr 0x4000 Paddr 0x80203000: D=0, should cause write fault
|
||||
.8byte 0x0000000080018028, 0x00000000200814C7, 0x0 # Vaddr 0x5000 Paddr 0x80205000: X=0, fetches should fault
|
||||
.8byte 0x0000000080018030, 0x00000000200814C0, 0x0 # Vaddr 0x6000: invalid page
|
||||
.8byte 0x0000000080018000, 0x00000000200070D1, write64_test# Vaddr 0x0000: bad PTE points to level -1 table
|
||||
.8byte 0x0000000080018008, 0x00000000200800DF, write64_test# Vaddr 0x1000, Paddr = 0x80200000: aligned kilopage
|
||||
.8byte 0x0000000080018010, 0x00000000200810D5, write64_test# Vaddr 0x2000: bad PTE has W but not R
|
||||
.8byte 0x0000000080018018, 0x0000000020080817, write64_test# Vaddr 0x3000 Paddr 0x80202000: A=0, should cause read fault
|
||||
.8byte 0x0000000080018020, 0x0000000020080C57, write64_test# Vaddr 0x4000 Paddr 0x80203000: D=0, should cause write fault
|
||||
.8byte 0x0000000080018028, 0x00000000200814C7, write64_test# Vaddr 0x5000 Paddr 0x80205000: X=0, fetches should fault
|
||||
.8byte 0x0000000080018030, 0x00000000200814C0, write64_test# Vaddr 0x6000: invalid page
|
||||
# Level 0 page table B
|
||||
.8byte 0x0000000080016FF8, 0x00000000200804CF, 0x0 # Vaddr 0xFFFFFFFFFFFFF000, Paddr 0x80201000 aligned kilopage
|
||||
.8byte 0x0000000080016FF8, 0x00000000200804CF, write64_test# Vaddr 0xFFFFFFFFFFFFF000, Paddr 0x80201000 aligned kilopage
|
||||
|
||||
# test 12.3.1.1.2 write values to Paddrs in each page
|
||||
# each of these values is used for 12.3.1.1.3 and some other tests, specified in the comments.
|
||||
# when a test is supposed to fault, nothing is written into where it'll be reading/executing since it shuold fault before getting there.
|
||||
.8byte 0x80200AB0, 0x0000DEADBEEF0000, 0x0 # 12.3.1.1.4
|
||||
.8byte 0x800FFAB8, 0x0880DEADBEEF0055, 0x0 # 12.3.1.1.4
|
||||
.8byte 0x80200AC0, 0x0990DEADBEEF0033, 0x0 # 12.3.1.3.2
|
||||
.8byte 0x80203130, 0x0110DEADBEEF0077, 0x0 # 12.3.1.3.2
|
||||
.8byte 0x80099000, 0x0000806711100393, 0x0 # 12.3.1.3.1 and 12.3.1.3.2 write executable code for "li x7, 0x111; ret"
|
||||
.8byte 0x80205AA0, 0x0000806711100393, 0x0 # 12.3.1.3.5 write same executable code
|
||||
.8byte 0x80201888, 0x0220DEADBEEF0099, 0x0 # 12.3.1.1.4
|
||||
.8byte 0x84212348, 0x0330DEADBEEF0440, 0x0 # 12.3.1.3.3
|
||||
.8byte 0x80203AA0, 0x0440DEADBEEF0BB0, 0x0 # 12.3.1.3.7
|
||||
.8byte 0x80200AB0, 0x0000DEADBEEF0000, write64_test# 12.3.1.1.4
|
||||
.8byte 0x800FFAB8, 0x0880DEADBEEF0055, write64_test# 12.3.1.1.4
|
||||
.8byte 0x80200AC0, 0x0990DEADBEEF0033, write64_test# 12.3.1.3.2
|
||||
.8byte 0x80203130, 0x0110DEADBEEF0077, write64_test# 12.3.1.3.2
|
||||
.8byte 0x80099000, 0x0000806711100393, write64_test# 12.3.1.3.1 and 12.3.1.3.2 write executable code for "li x7, 0x111; ret"
|
||||
.8byte 0x80205AA0, 0x0000806711100393, write64_test# 12.3.1.3.5 write same executable code
|
||||
.8byte 0x80201888, 0x0220DEADBEEF0099, write64_test# 12.3.1.1.4
|
||||
.8byte 0x84212348, 0x0330DEADBEEF0440, write64_test# 12.3.1.3.3
|
||||
.8byte 0x80203AA0, 0x0440DEADBEEF0BB0, write64_test# 12.3.1.3.7
|
||||
|
||||
# test 12.3.1.1.3 read values back from Paddrs without translation (this also verifies the previous test)
|
||||
.8byte 0x0, 0x0, 0x4 # satp.MODE = baremetal / no translation.
|
||||
.8byte 0x0, 0x0, 0x9 # change to S mode, 0xb written to output
|
||||
.8byte 0x80200AB0, 0x0000DEADBEEF0000, 0x1
|
||||
.8byte 0x800FFAB8, 0x0880DEADBEEF0055, 0x1
|
||||
.8byte 0x80200AC0, 0x0990DEADBEEF0033, 0x1
|
||||
.8byte 0x80203130, 0x0110DEADBEEF0077, 0x1
|
||||
.8byte 0x80201888, 0x0220DEADBEEF0099, 0x1
|
||||
.8byte 0x84212348, 0x0330DEADBEEF0440, 0x1
|
||||
.8byte 0x80203AA0, 0x0440DEADBEEF0BB0, 0x1
|
||||
.8byte 0x0, 0x0, goto_baremetal# satp.MODE = baremetal / no translation.
|
||||
.8byte 0x0, 0x0, goto_s_mode # change to S mode, 0xb written to output
|
||||
.8byte 0x80200AB0, 0x0000DEADBEEF0000, read64_test
|
||||
.8byte 0x800FFAB8, 0x0880DEADBEEF0055, read64_test
|
||||
.8byte 0x80200AC0, 0x0990DEADBEEF0033, read64_test
|
||||
.8byte 0x80203130, 0x0110DEADBEEF0077, read64_test
|
||||
.8byte 0x80201888, 0x0220DEADBEEF0099, read64_test
|
||||
.8byte 0x84212348, 0x0330DEADBEEF0440, read64_test
|
||||
.8byte 0x80203AA0, 0x0440DEADBEEF0BB0, read64_test
|
||||
|
||||
# test 12.3.1.1.4 check translation works in sv39, read the same values from previous tests, this time with Vaddrs
|
||||
.8byte 0x0, 0x0, 0x5 # satp.MODE = sv39, current VPN: gigapage at 0x80000000. Nothing written to output
|
||||
.8byte 0x80200AB0, 0x0000DEADBEEF0000, 0x1 # gigapage at Vaddr 0x80000000, Paddr 0x80000000
|
||||
.8byte 0x400FFAB8, 0x0880DEADBEEF0055, 0x1 # megapage at Vaddr 0x40400000, Paddr 0x80000000
|
||||
.8byte 0xFFFFFFFFFFFFF888, 0x0220DEADBEEF0099, 0x1 # kilopage at Vaddr 0xFFFFFFFFFFFFF000, Paddr 0x80201000
|
||||
.8byte 0x0, 0x0, goto_sv39 # satp.MODE = sv39, current VPN: gigapage at 0x80000000. Nothing written to output
|
||||
.8byte 0x80200AB0, 0x0000DEADBEEF0000, read64_test # gigapage at Vaddr 0x80000000, Paddr 0x80000000
|
||||
.8byte 0x400FFAB8, 0x0880DEADBEEF0055, read64_test # megapage at Vaddr 0x40400000, Paddr 0x80000000
|
||||
.8byte 0xFFFFFFFFFFFFF888, 0x0220DEADBEEF0099, read64_test # kilopage at Vaddr 0xFFFFFFFFFFFFF000, Paddr 0x80201000
|
||||
|
||||
# =========== test 12.3.1.2 page fault tests ===========
|
||||
|
||||
# test 12.3.1.2.1 load page fault if upper bits of Vaddr are not the same
|
||||
.8byte 0x0010000080000AB0, 0x0, 0x1 # gigapage at Vaddr 0x80000000, Paddr 0x80000000, bad 1 in upper bits
|
||||
.8byte 0xFF0FFFFFFFFFF888, 0x0, 0x1 # kilopage at Vaddr 0xFFFFFFFFFFFFF000, Paddr 0x80201000, bad 0000 in upper bits
|
||||
.8byte 0x0010000080000AB0, 0x0, read64_test# gigapage at Vaddr 0x80000000, Paddr 0x80000000, bad 1 in upper bits
|
||||
.8byte 0xFF0FFFFFFFFFF888, 0x0, read64_test# kilopage at Vaddr 0xFFFFFFFFFFFFF000, Paddr 0x80201000, bad 0000 in upper bits
|
||||
|
||||
# test 12.3.1.2.2 load page fault when reading an address where the valid flag is zero
|
||||
.8byte 0x6000, 0x0, 0x1
|
||||
.8byte 0x6000, 0x0, read64_test
|
||||
|
||||
# test 12.3.1.2.3 store page fault if PTE has W and ~R flags set
|
||||
.8byte 0x2000, 0x0, 0x0
|
||||
.8byte 0x2000, 0x0, write64_test
|
||||
|
||||
# test 12.3.1.2.4 Fault if last level PTE is a pointer
|
||||
.8byte 0x0020, 0x0, 0x1
|
||||
.8byte 0x0020, 0x0, read64_test
|
||||
|
||||
# test 12.3.1.2.5 load page fault on misaligned pages
|
||||
.8byte 0xC0000000, 0x0, 0x1 # misaligned gigapage
|
||||
.8byte 0x40200000, 0x0, 0x1 # misaligned megapage
|
||||
.8byte 0xC0000000, 0x0, read64_test# misaligned gigapage
|
||||
.8byte 0x40200000, 0x0, read64_test# misaligned megapage
|
||||
|
||||
# =========== test 12.3.1.3 PTE Protection flags ===========
|
||||
|
||||
|
||||
# test 12.3.1.3.1 User flag == 0
|
||||
# *** reads on pages with U=0 already tested in 12.3.1.1.4
|
||||
.8byte 0x40099000, 0x111, 0x2 # execute success when U=0, priv=S
|
||||
.8byte 0x40400000, 0x2, 0xA # go to U mode, return to megapage at 0x40400000 where U = 1. 0x9 written to output
|
||||
.8byte 0xFFFFFFFFFFFFFC80, 0x0880DEADBEEF0550, 0x1 # load page fault when U=0, priv=U
|
||||
.8byte 0x40099000, 0xbad, 0x2 # execute fault when U=0, priv=U
|
||||
.8byte 0x40099000, 0x111, executable_test # execute success when U=0, priv=S
|
||||
.8byte 0x40400000, 0x2, goto_u_mode # go to U mode, return to megapage at 0x40400000 where U = 1. 0x9 written to output
|
||||
.8byte 0xFFFFFFFFFFFFFC80, 0x0880DEADBEEF0550, read64_test # load page fault when U=0, priv=U
|
||||
.8byte 0x40099000, 0xbad, executable_test # execute fault when U=0, priv=U
|
||||
|
||||
# test 12.3.1.3.2 User flag == 1
|
||||
.8byte 0x1AC0, 0x0990DEADBEEF0033, 0x1 # read success when U=1, priv=U
|
||||
.8byte 0x80000000, 0x1, 0x9 # go back to S mode, return to gigapage at 0x80000000 where U = 0. 0x8 written to output
|
||||
.8byte 0x0, 0x3, 0x7 # set sstatus.[MXR, SUM] = 11
|
||||
.8byte 0x4130, 0x0110DEADBEEF0077, 0x1 # read success when U=1, priv=S, sstatus.SUM=1
|
||||
.8byte 0x40499000, 0xbad, 0x2 # instr page fault when U=1, priv=S (with any sstatus.SUM)
|
||||
.8byte 0x0, 0x2, 0x7 # set sstatus.[MXR, SUM] = 10.
|
||||
.8byte 0x1AC0, 0x0990DEADBEEF0033, 0x1 # load page fault when U-1, priv=S, sstatus.SUM=0
|
||||
.8byte 0x1AC0, 0x0990DEADBEEF0033, read64_test # read success when U=1, priv=U
|
||||
.8byte 0x80000000, 0x1, goto_s_mode # go back to S mode, return to gigapage at 0x80000000 where U = 0. 0x8 written to output
|
||||
.8byte 0x0, 0x3, write_mxr_sum # set sstatus.[MXR, SUM] = 11
|
||||
.8byte 0x4130, 0x0110DEADBEEF0077, read64_test # read success when U=1, priv=S, sstatus.SUM=1
|
||||
.8byte 0x40499000, 0xbad, executable_test # instr page fault when U=1, priv=S (with any sstatus.SUM)
|
||||
.8byte 0x0, 0x2, write_mxr_sum # set sstatus.[MXR, SUM] = 10.
|
||||
.8byte 0x1AC0, 0x0990DEADBEEF0033, read64_test # load page fault when U-1, priv=S, sstatus.SUM=0
|
||||
|
||||
# test 12.3.1.3.3 Read flag
|
||||
# *** reads on pages with R=1 already tested in 12.3.1.1.4
|
||||
.8byte 0x0, 0x1, 0x7 # set sstatus.[MXR, SUM] = 01.
|
||||
.8byte 0x40612348, 0x0330DEADBEEF0440, 0x1 # load page fault when R=0, sstatus.MXR=0
|
||||
.8byte 0x0, 0x3, 0x7 # set sstatus.[MXR, SUM] = 11.
|
||||
.8byte 0x40612348, 0x0330DEADBEEF0440, 0x1 # read success when MXR=1, X=1
|
||||
.8byte 0x0, 0x1, write_mxr_sum # set sstatus.[MXR, SUM] = 01.
|
||||
.8byte 0x40612348, 0x0330DEADBEEF0440, read64_test # load page fault when R=0, sstatus.MXR=0
|
||||
.8byte 0x0, 0x3, write_mxr_sum # set sstatus.[MXR, SUM] = 11.
|
||||
.8byte 0x40612348, 0x0330DEADBEEF0440, read64_test # read success when MXR=1, X=1
|
||||
|
||||
# test 12.3.1.3.4 Write flag
|
||||
.8byte 0x80AAAAA0, 0x0440DEADBEEF0110, 0x0 # write success when W=1
|
||||
.8byte 0x80AAAAA0, 0x0440DEADBEEF0110, 0x1 # check write success by reading the same address
|
||||
.8byte 0x40000000, 0x0220DEADBEEF0BB0, 0x0 # store page fault when W=0
|
||||
.8byte 0x80AAAAA0, 0x0440DEADBEEF0110, write64_test# write success when W=1
|
||||
.8byte 0x80AAAAA0, 0x0440DEADBEEF0110, read64_test# check write success by reading the same address
|
||||
.8byte 0x40000000, 0x0220DEADBEEF0BB0, write64_test# store page fault when W=0
|
||||
|
||||
# test 12.3.1.3.5 eXecute flag
|
||||
# *** fetches on pages with X = 1 already tested in 12.3.1.3.1
|
||||
.8byte 0x5AA0, 0x1, 0x2 # instr page fault when X=0
|
||||
.8byte 0x5AA0, 0x1, executable_test # instr page fault when X=0
|
||||
|
||||
# test 12.3.1.3.6 Accessed flag == 0
|
||||
.8byte 0x36D0, 0x0990DEADBEEF0770, 0x0 # store page fault when A=0
|
||||
.8byte 0x3AB8, 0x0990DEADBEEF0990, 0x1 # load page fault when A=0
|
||||
.8byte 0x36D0, 0x0990DEADBEEF0770, write64_test# store page fault when A=0
|
||||
.8byte 0x3AB8, 0x0990DEADBEEF0990, read64_test# load page fault when A=0
|
||||
|
||||
# test 12.3.1.3.7 Dirty flag == 0
|
||||
.8byte 0x4658, 0x0440DEADBEEF0AA0, 0x0 # store page fault when D=0
|
||||
.8byte 0x4AA0, 0x0440DEADBEEF0BB0, 0x1 # read success when D=0
|
||||
.8byte 0x4658, 0x0440DEADBEEF0AA0, write64_test# store page fault when D=0
|
||||
.8byte 0x4AA0, 0x0440DEADBEEF0BB0, read64_test# read success when D=0
|
||||
|
||||
# terminate tests
|
||||
.8byte 0x0, 0x0, 0x3 # brings us back into machine mode with a final ecall, writing 0x9 to the output.
|
||||
.8byte 0x0, 0x0, terminate_test # brings us back into machine mode with a final ecall, writing 0x9 to the output.
|
||||
|
||||
|
@ -21,7 +21,7 @@
|
||||
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
///////////////////////////////////////////
|
||||
|
||||
#include "WALLY-TEST-LIB-64.S"
|
||||
#include "WALLY-TEST-LIB-64.h"
|
||||
// Test library includes and handler for each type of test, a trap handler, imperas compliance instructions
|
||||
// Ideally this should mean that a test can be written by simply adding .8byte statements as below.
|
||||
|
||||
@ -46,136 +46,136 @@
|
||||
# test 12.3.1.1.1 write page tables / entries to phyiscal memory
|
||||
# sv48 page table (See Figure 12.12***):
|
||||
# Level 3 page table, situated at 0x8000D000
|
||||
.8byte 0x000000008000D000, 0x0000000020004C01, 0x0 # points to level 2 page table A
|
||||
.8byte 0x000000008000D008, 0x0000000020005001, 0x0 # points to level 2 page table B # Changing DAU bits of each pointer to zero
|
||||
.8byte 0x000000008000D010, 0x00000000000000C7, 0x0 # Vaddr 0x010000000000, Paddr 0x00000000: aligned terapage
|
||||
.8byte 0x000000008000D018, 0x00004000004000C7, 0x0 # Vaddr 0x018000000000, misaligned terapage
|
||||
.8byte 0x000000008000DFF8, 0x0000000020005401, 0x0 # points to level 2 page table C
|
||||
.8byte 0x000000008000D000, 0x0000000020004C01, write64_test # points to level 2 page table A
|
||||
.8byte 0x000000008000D008, 0x0000000020005001, write64_test # points to level 2 page table B # Changing DAU bits of each pointer to zero
|
||||
.8byte 0x000000008000D010, 0x00000000000000C7, write64_test # Vaddr 0x010000000000, Paddr 0x00000000: aligned terapage
|
||||
.8byte 0x000000008000D018, 0x00004000004000C7, write64_test # Vaddr 0x018000000000, misaligned terapage
|
||||
.8byte 0x000000008000DFF8, 0x0000000020005401, write64_test # points to level 2 page table C
|
||||
|
||||
# Level 2 page table A
|
||||
.8byte 0x0000000080013010, 0x0000000020006001, 0x0 # points to level 1 page table A
|
||||
.8byte 0x0000000080013010, 0x0000000020006001, write64_test # points to level 1 page table A
|
||||
|
||||
# Level 2 page table B
|
||||
.8byte 0x0000000080014000, 0x00000000200000CB, 0x0 # Vaddr 0x008000000000, Paddr 0x80000000: aligned gigapage used for execution tests
|
||||
.8byte 0x0000000080014008, 0x00000000200000DF, 0x0 # Vaddr 0x008040000000, Paddr 0x80000000: aligned gigapage (aliased with data and instr memory) U bit set.
|
||||
.8byte 0x0000000080014010, 0x00000400080000C3, 0x0 # Vaddr 0x008080000000, misaligned gigapage
|
||||
.8byte 0x0000000080014000, 0x00000000200000CB, write64_test # Vaddr 0x008000000000, Paddr 0x80000000: aligned gigapage used for execution tests
|
||||
.8byte 0x0000000080014008, 0x00000000200000DF, write64_test # Vaddr 0x008040000000, Paddr 0x80000000: aligned gigapage (aliased with data and instr memory) U bit set.
|
||||
.8byte 0x0000000080014010, 0x00000400080000C3, write64_test # Vaddr 0x008080000000, misaligned gigapage
|
||||
# Level 2 page table C
|
||||
.8byte 0x0000000080015FF8, 0x0000000020005801, 0x0 # points to level 1 page table B
|
||||
.8byte 0x0000000080015FF8, 0x0000000020005801, write64_test # points to level 1 page table B
|
||||
|
||||
# Level 1 page table A
|
||||
.8byte 0x0000000080018000, 0x00000000200000CF, 0x0 # Vaddr 0x80000000, Paddr 0x80000000: aligned megapage (data and instr memory)
|
||||
.8byte 0x0000000080018008, 0x0000000020006401, 0x0 # points to level 0 page table A
|
||||
.8byte 0x0000000080018010, 0x000000C0000400CF, 0x0 # Vaddr 0x80400000, misaligned megapage
|
||||
.8byte 0x0000000080018018, 0x00000000214800C9, 0x0 # Vaddr 0x80600000, Paddr 0x85200000: aligned megapage, R=0
|
||||
.8byte 0x0000000080018000, 0x00000000200000CF, write64_test # Vaddr 0x80000000, Paddr 0x80000000: aligned megapage (data and instr memory)
|
||||
.8byte 0x0000000080018008, 0x0000000020006401, write64_test # points to level 0 page table A
|
||||
.8byte 0x0000000080018010, 0x000000C0000400CF, write64_test # Vaddr 0x80400000, misaligned megapage
|
||||
.8byte 0x0000000080018018, 0x00000000214800C9, write64_test # Vaddr 0x80600000, Paddr 0x85200000: aligned megapage, R=0
|
||||
# Level 1 page table B
|
||||
.8byte 0x0000000080016FF8, 0x0000000020006801, 0x0 # points to level 0 page table B
|
||||
.8byte 0x0000000080016FF8, 0x0000000020006801, write64_test # points to level 0 page table B
|
||||
|
||||
# Level 0 page table A
|
||||
.8byte 0x0000000080019000, 0x00000000200070D1, 0x0 # Vaddr 0x80200000, Paddr 0x8001C000: bad PTE points to level -1 table
|
||||
.8byte 0x0000000080019008, 0x00000000200800DF, 0x0 # Vaddr 0x80201000, Paddr 0x80200000: aligned kilopage
|
||||
.8byte 0x0000000080019010, 0x00000000200810DF, 0x0 # Vaddr 0x80202000, Paddr 0x80204000: bad PTE has W but not R
|
||||
.8byte 0x0000000080019018, 0x0000000020080817, 0x0 # Vaddr 0x80203000, Paddr 0x80202000: A=0, should cause read fault
|
||||
.8byte 0x0000000080019020, 0x0000000020080C57, 0x0 # Vaddr 0x80204000, Paddr 0x80203000: D=0, should cause write fault
|
||||
.8byte 0x0000000080019028, 0x0000000020333000, 0x0 # Vaddr 0x80205000, Paddr 0x80CCC000, invalid page.
|
||||
.8byte 0x0000000080019000, 0x00000000200070D1, write64_test # Vaddr 0x80200000, Paddr 0x8001C000: bad PTE points to level -1 table
|
||||
.8byte 0x0000000080019008, 0x00000000200800DF, write64_test # Vaddr 0x80201000, Paddr 0x80200000: aligned kilopage
|
||||
.8byte 0x0000000080019010, 0x00000000200810DF, write64_test # Vaddr 0x80202000, Paddr 0x80204000: bad PTE has W but not R
|
||||
.8byte 0x0000000080019018, 0x0000000020080817, write64_test # Vaddr 0x80203000, Paddr 0x80202000: A=0, should cause read fault
|
||||
.8byte 0x0000000080019020, 0x0000000020080C57, write64_test # Vaddr 0x80204000, Paddr 0x80203000: D=0, should cause write fault
|
||||
.8byte 0x0000000080019028, 0x0000000020333000, write64_test # Vaddr 0x80205000, Paddr 0x80CCC000, invalid page.
|
||||
# Level 0 page table B
|
||||
.8byte 0x000000008001AFF8, 0x00000000200804CF, 0x0 # Vaddr 0xFFFFFFFFF000, Paddr 0x80201000: aligned kilopage
|
||||
.8byte 0x000000008001AFF8, 0x00000000200804CF, write64_test # Vaddr 0xFFFFFFFFF000, Paddr 0x80201000: aligned kilopage
|
||||
|
||||
# test 12.3.1.1.2 write values to Paddrs in each page
|
||||
# each of these values is used for 12.3.1.1.3 and some other tests, specified in the comments.
|
||||
# when a test is supposed to fault, nothing is written into where it'll be reading/executing since it should fault before getting there.
|
||||
.8byte 0x82777778, 0x0EE0DEADBEEF0CC0, 0x0 # 12.3.1.1.4 terapage
|
||||
.8byte 0x85BC0AB0, 0x0000DEADBEEF0000, 0x0 # 12.3.1.1.4 gigapage
|
||||
.8byte 0x800F0AB8, 0x0880DEADBEEF0055, 0x0 # 12.3.1.1.4 megapage
|
||||
.8byte 0x80201888, 0x0220DEADBEEF0099, 0x0 # 12.3.1.1.4 kilopage
|
||||
.8byte 0x80099000, 0x0000806711100393, 0x0 # 12.3.1.3.1 write executable code for "li x7, 0x111; ret"
|
||||
.8byte 0x80200400, 0x0000806711100393, 0x0 # 12.3.1.3.2 write same executable code
|
||||
.8byte 0x80200AC0, 0x0990DEADBEEF0033, 0x0 # 12.3.1.3.2
|
||||
.8byte 0x80200130, 0x0110DEADBEEF0077, 0x0 # 12.3.1.3.2
|
||||
.8byte 0x85212348, 0x0330DEADBEEF0440, 0x0 # 12.3.1.3.3
|
||||
.8byte 0x88888000, 0x0000806711100393, 0x0 # 12.3.1.3.5 write same executable code
|
||||
.8byte 0x80203AA0, 0x0440DEADBEEF0BB0, 0x0 # 12.3.1.3.7
|
||||
.8byte 0x82777778, 0x0EE0DEADBEEF0CC0, write64_test # 12.3.1.1.4 terapage
|
||||
.8byte 0x85BC0AB0, 0x0000DEADBEEF0000, write64_test # 12.3.1.1.4 gigapage
|
||||
.8byte 0x800F0AB8, 0x0880DEADBEEF0055, write64_test # 12.3.1.1.4 megapage
|
||||
.8byte 0x80201888, 0x0220DEADBEEF0099, write64_test # 12.3.1.1.4 kilopage
|
||||
.8byte 0x80099000, 0x0000806711100393, write64_test # 12.3.1.3.1 write executable code for "li x7, 0x111; ret"
|
||||
.8byte 0x80200400, 0x0000806711100393, write64_test # 12.3.1.3.2 write same executable code
|
||||
.8byte 0x80200AC0, 0x0990DEADBEEF0033, write64_test # 12.3.1.3.2
|
||||
.8byte 0x80200130, 0x0110DEADBEEF0077, write64_test # 12.3.1.3.2
|
||||
.8byte 0x85212348, 0x0330DEADBEEF0440, write64_test # 12.3.1.3.3
|
||||
.8byte 0x88888000, 0x0000806711100393, write64_test # 12.3.1.3.5 write same executable code
|
||||
.8byte 0x80203AA0, 0x0440DEADBEEF0BB0, write64_test # 12.3.1.3.7
|
||||
|
||||
# test 12.3.1.1.3 read values back from Paddrs without translation (this also verifies the previous test)
|
||||
.8byte 0x0, 0x0, 0x4 # satp.MODE = baremetal / no translation.
|
||||
.8byte 0x0, 0x0, 0x9 # change to S mode, 0xb written to output
|
||||
.8byte 0x82777778, 0x0EE0DEADBEEF0CC0, 0x1
|
||||
.8byte 0x85BC0AB0, 0x0000DEADBEEF0000, 0x1
|
||||
.8byte 0x800F0AB8, 0x0880DEADBEEF0055, 0x1
|
||||
.8byte 0x80200AC0, 0x0990DEADBEEF0033, 0x1
|
||||
.8byte 0x80200130, 0x0110DEADBEEF0077, 0x1
|
||||
.8byte 0x80201888, 0x0220DEADBEEF0099, 0x1
|
||||
.8byte 0x85212348, 0x0330DEADBEEF0440, 0x1
|
||||
.8byte 0x80203AA0, 0x0440DEADBEEF0BB0, 0x1
|
||||
.8byte 0x0, 0x0, goto_baremetal # satp.MODE = baremetal / no translation.
|
||||
.8byte 0x0, 0x0, goto_s_mode # change to S mode, 0xb written to output
|
||||
.8byte 0x82777778, 0x0EE0DEADBEEF0CC0, read64_test
|
||||
.8byte 0x85BC0AB0, 0x0000DEADBEEF0000, read64_test
|
||||
.8byte 0x800F0AB8, 0x0880DEADBEEF0055, read64_test
|
||||
.8byte 0x80200AC0, 0x0990DEADBEEF0033, read64_test
|
||||
.8byte 0x80200130, 0x0110DEADBEEF0077, read64_test
|
||||
.8byte 0x80201888, 0x0220DEADBEEF0099, read64_test
|
||||
.8byte 0x85212348, 0x0330DEADBEEF0440, read64_test
|
||||
.8byte 0x80203AA0, 0x0440DEADBEEF0BB0, read64_test
|
||||
|
||||
# test 12.3.1.1.4 check translation works in sv48, read the same values from previous tests, this time with Vaddrs
|
||||
.8byte 0x0, 0x0, 0x6 # satp.MODE = sv48, current VPN: megapage at 0x80000000. Nothing written to output
|
||||
.8byte 0x10082777778, 0x0EE0DEADBEEF0CC0, 0x1 # terapage at Vaddr 0x010000000000, Paddr 0x0
|
||||
.8byte 0x8005BC0AB0, 0x0000DEADBEEF0000, 0x1 # gigapage at Vaddr 0x008000000000, Paddr 0x80000000
|
||||
.8byte 0x800F0AB8, 0x0880DEADBEEF0055, 0x1 # megapage at Vaddr 0x80000000, Paddr 0x80000000
|
||||
.8byte 0xFFFFFFFFFFFFF888, 0x0220DEADBEEF0099, 0x1 # kilopage at Vaddr 0xFFFFFFFFFFFFF000, Paddr 0x80201000
|
||||
.8byte 0x0, 0x0, goto_sv48 # satp.MODE = sv48, current VPN: megapage at 0x80000000. Nothing written to output
|
||||
.8byte 0x10082777778, 0x0EE0DEADBEEF0CC0, read64_test # terapage at Vaddr 0x010000000000, Paddr 0x0
|
||||
.8byte 0x8005BC0AB0, 0x0000DEADBEEF0000, read64_test # gigapage at Vaddr 0x008000000000, Paddr 0x80000000
|
||||
.8byte 0x800F0AB8, 0x0880DEADBEEF0055, read64_test # megapage at Vaddr 0x80000000, Paddr 0x80000000
|
||||
.8byte 0xFFFFFFFFFFFFF888, 0x0220DEADBEEF0099, read64_test # kilopage at Vaddr 0xFFFFFFFFFFFFF000, Paddr 0x80201000
|
||||
|
||||
# =========== test 12.3.1.2 page fault tests ===========
|
||||
|
||||
# test 12.3.1.2.1 page fault if upper bits of Vaddr are not the same
|
||||
.8byte 0x001000800ABC0AB0, 0x0, 0x1 # gigapage at Vaddr 0x008000000000, Paddr 0x80000000, bad 1 in upper bits
|
||||
.8byte 0xFF0FFFFFFFFFF888, 0x0, 0x1 # kilopage at Vaddr 0xFFFFFFFFFFFFF000, Paddr 0x80201000, bad 0000 in upper bits
|
||||
.8byte 0x001000800ABC0AB0, 0x0, read64_test# gigapage at Vaddr 0x008000000000, Paddr 0x80000000, bad 1 in upper bits
|
||||
.8byte 0xFF0FFFFFFFFFF888, 0x0, read64_test# kilopage at Vaddr 0xFFFFFFFFFFFFF000, Paddr 0x80201000, bad 0000 in upper bits
|
||||
|
||||
# test 12.3.1.2.2 read fault when reading an address where the valid flag is zero
|
||||
.8byte 0x80205000, 0x0, 0x1
|
||||
.8byte 0x80205000, 0x0, read64_test
|
||||
|
||||
# test 12.3.1.2.3 write fault if PTE has W and ~R flags set
|
||||
.8byte 0x80202000, 0x0, 0x0
|
||||
.8byte 0x80202000, 0x0, write64_test
|
||||
|
||||
# test 12.3.1.2.4 Fault if last level PTE is a pointer
|
||||
.8byte 0x80200000, 0x0, 0x1
|
||||
.8byte 0x80200000, 0x0, read64_test
|
||||
|
||||
# test 12.3.1.2.5 read fault on misaligned pages
|
||||
.8byte 0x18000000000, 0x0, 0x1 # misaligned terapage
|
||||
.8byte 0x8080000000, 0x0, 0x1 # misaligned gigapage
|
||||
.8byte 0x80400000, 0x0, 0x1 # misaligned megapage
|
||||
.8byte 0x18000000000, 0x0, read64_test # misaligned terapage
|
||||
.8byte 0x8080000000, 0x0, read64_test # misaligned gigapage
|
||||
.8byte 0x80400000, 0x0, read64_test # misaligned megapage
|
||||
|
||||
# =========== test 12.3.1.3 PTE Protection flags ===========
|
||||
|
||||
# test 12.3.1.3.1 User flag == 0
|
||||
# reads on pages with U=0 already tested in 12.3.1.1.4
|
||||
.8byte 0x008000099000, 0x111, 0x2 # execute success when U=0, priv=S
|
||||
.8byte 0x008040000000, 0x1, 0xA # go to U mode, return to gigapage at 0x008040000000 where PTE.U = 1. 0x9 written to output
|
||||
.8byte 0xFFFFFFFFFFFFFC80, 0x0880DEADBEEF0550, 0x1 # read fault when U=0, priv=U
|
||||
.8byte 0x008000099000, 0xbad, 0x2 # execute fault when U=0, priv=U
|
||||
.8byte 0x008000099000, 0x111, executable_test # execute success when U=0, priv=S
|
||||
.8byte 0x008040000000, 0x1, goto_u_mode # go to U mode, return to gigapage at 0x008040000000 where PTE.U = 1. 0x9 written to output
|
||||
.8byte 0xFFFFFFFFFFFFFC80, 0x0880DEADBEEF0550, read64_test # read fault when U=0, priv=U
|
||||
.8byte 0x008000099000, 0xbad, executable_test # execute fault when U=0, priv=U
|
||||
|
||||
# test 12.3.1.3.2 User flag == 1
|
||||
.8byte 0x80201AC0, 0x0990DEADBEEF0033, 0x1 # read success when U=1, priv=U
|
||||
.8byte 0x80000000, 0x2, 0x9 # go back to S mode, return to megapage at 0x80000000 where PTE.U = 0. 0x8 written to output
|
||||
.8byte 0x0, 0x3, 0x7 # set sstatus.[MXR, SUM] = 11
|
||||
.8byte 0x80201130, 0x0110DEADBEEF0077, 0x1 # read success when U=1, priv=S, sstatus.SUM=1
|
||||
.8byte 0x80201400, 0xbad, 0x2 # execute fault when U=1, priv=S (with any sstatus.SUM)
|
||||
.8byte 0x0, 0x2, 0x7 # set sstatus.[MXR, SUM] = 10.
|
||||
.8byte 0x80201AC0, 0x0990DEADBEEF0033, 0x1 # read fault when U=1, priv=S, sstatus.SUM=0
|
||||
.8byte 0x80201AC0, 0x0990DEADBEEF0033, read64_test # read success when U=1, priv=U
|
||||
.8byte 0x80000000, 0x2, goto_s_mode
|
||||
.8byte 0x0, 0x3, write_mxr_sum # set sstatus.[MXR, SUM] = 11
|
||||
.8byte 0x80201130, 0x0110DEADBEEF0077, read64_test # read success when U=1, priv=S, sstatus.SUM=1
|
||||
.8byte 0x80201400, 0xbad, executable_test # execute fault when U=1, priv=S (with any sstatus.SUM)
|
||||
.8byte 0x0, 0x2, write_mxr_sum # set sstatus.[MXR, SUM] = 10.
|
||||
.8byte 0x80201AC0, 0x0990DEADBEEF0033, read64_test # read fault when U=1, priv=S, sstatus.SUM=0
|
||||
|
||||
# test 12.3.1.3.3 Read flag
|
||||
# reads on pages with R=1 already tested in 12.3.1.1.4
|
||||
.8byte 0x0, 0x1, 0x7 # set sstatus.[MXR, SUM] = 01.
|
||||
.8byte 0x80612348, 0x0330DEADBEEF0440, 0x1 # read fault when R=0, sstatus.MXR=0
|
||||
.8byte 0x0, 0x3, 0x7 # set sstatus.[MXR, SUM] = 11.
|
||||
.8byte 0x80612348, 0x0330DEADBEEF0440, 0x1 # read success when MXR=1, X=1
|
||||
.8byte 0x0, 0x1, write_mxr_sum # set sstatus.[MXR, SUM] = 01.
|
||||
.8byte 0x80612348, 0x0330DEADBEEF0440, read64_test # read fault when R=0, sstatus.MXR=0
|
||||
.8byte 0x0, 0x3, write_mxr_sum # set sstatus.[MXR, SUM] = 11.
|
||||
.8byte 0x80612348, 0x0330DEADBEEF0440, read64_test # read success when MXR=1, X=1
|
||||
|
||||
# test 12.3.1.3.4 Write flag
|
||||
.8byte 0x10080BCDED8, 0x0440DEADBEEF0110, 0x0 # write success when W=1 (corresponding Paddr = 0x80BCDED8)
|
||||
.8byte 0x10080BCDED8, 0x0440DEADBEEF0110, 0x1 # check write success by reading value back
|
||||
.8byte 0x8000009E88, 0x0220DEADBEEF0BB0, 0x0 # write fault when W=0
|
||||
.8byte 0x10080BCDED8, 0x0440DEADBEEF0110, write64_test # write success when W=1 (corresponding Paddr = 0x80BCDED8)
|
||||
.8byte 0x10080BCDED8, 0x0440DEADBEEF0110, read64_test # check write success by reading value back
|
||||
.8byte 0x8000009E88, 0x0220DEADBEEF0BB0, write64_test # write fault when W=0
|
||||
|
||||
# test 12.3.1.3.5 eXecute flag
|
||||
# executes on pages with X = 1 already tested in 12.3.1.3.1
|
||||
.8byte 0x010088888000, 0x2, 0x2 # execute fault when X=0
|
||||
.8byte 0x010088888000, 0x2, executable_test # execute fault when X=0
|
||||
|
||||
# test 12.3.1.3.6 Accessed flag == 0
|
||||
.8byte 0x802036D0, 0x0990DEADBEEF0770, 0x0 # write fault when A=0
|
||||
.8byte 0x80203AB8, 0x0990DEADBEEF0990, 0x1 # read fault when A=0
|
||||
.8byte 0x802036D0, 0x0990DEADBEEF0770, write64_test # write fault when A=0
|
||||
.8byte 0x80203AB8, 0x0990DEADBEEF0990, read64_test# read fault when A=0
|
||||
|
||||
# test 12.3.1.3.7 Dirty flag == 0
|
||||
.8byte 0x80204658, 0x0440DEADBEEF0AA0, 0x0 # write fault when D=0
|
||||
.8byte 0x80204AA0, 0x0440DEADBEEF0BB0, 0x1 # read success when D=0
|
||||
.8byte 0x80204658, 0x0440DEADBEEF0AA0, write64_test # write fault when D=0
|
||||
.8byte 0x80204AA0, 0x0440DEADBEEF0BB0, read64_test# read success when D=0
|
||||
|
||||
# terminate tests
|
||||
.8byte 0x0, 0x0, 0x3 # brings us back into machine mode with a final ecall, writing 0x9 to the output.
|
||||
.8byte 0x0, 0x0, terminate_test # brings us back into machine mode with a final ecall, writing 0x9 to the output.
|
||||
|
||||
|
@ -34,7 +34,7 @@
|
||||
#define PLIC_BASE 0x0C000000
|
||||
#define PLIC_RANGE 0x03FFFFFF
|
||||
|
||||
#include "WALLY-TEST-LIB-64.S"
|
||||
#include "WALLY-TEST-LIB-64.h"
|
||||
// Test library includes and handler for each type of test, a trap handler, imperas compliance instructions
|
||||
// Ideally this should mean that a test can be written by simply adding .8byte statements as below.
|
||||
|
||||
@ -71,89 +71,89 @@
|
||||
# ----------------- CLINT ---------------------
|
||||
|
||||
# Use timecmp register as readable and writable section of the CLINT
|
||||
.8byte CLINT_BASE + 0x4000, 0x0000DEADBEEF00B4, 0x0 # 64-bit write: success
|
||||
.8byte CLINT_BASE + 0x4000, 0x0000DEADBEEF00B4, 0x1 # 64-bit read: success
|
||||
.8byte CLINT_BASE + 0x4000, 0x0000DEADBEEF00B5, 0x11 # 32-bit write: success
|
||||
.8byte CLINT_BASE + 0x4000, 0x0000DEADBEEF00B5, 0x14 # 32-bit read: success
|
||||
.8byte CLINT_BASE + 0x4000, 0x0000DEADBEEF00B6, 0x12 # 16-bit write: success
|
||||
.8byte CLINT_BASE + 0x4000, 0x0000DEADBEEF00B6, 0x15 # 16-bit read: success
|
||||
.8byte CLINT_BASE + 0x4000, 0x0000DEADBEEF00B7, 0x13 # 08-bit write: success
|
||||
.8byte CLINT_BASE + 0x4000, 0x0000DEADBEEF00B7, 0x16 # 08-bit read: success
|
||||
.8byte CLINT_BASE + 0x4000, 0x0000DEADBEEF00B4, write64_test # 64-bit write: success
|
||||
.8byte CLINT_BASE + 0x4000, 0x0000DEADBEEF00B4, read64_test # 64-bit read: success
|
||||
.8byte CLINT_BASE + 0x4000, 0x0000DEADBEEF00B5, write32_test # 32-bit write: success
|
||||
.8byte CLINT_BASE + 0x4000, 0x0000DEADBEEF00B5, read32_test # 32-bit read: success
|
||||
.8byte CLINT_BASE + 0x4000, 0x0000DEADBEEF00B6, write16_test # 16-bit write: success
|
||||
.8byte CLINT_BASE + 0x4000, 0x0000DEADBEEF00B6, read16_test # 16-bit read: success
|
||||
.8byte CLINT_BASE + 0x4000, 0x0000DEADBEEF00B7, write08_test # 08-bit write: success
|
||||
.8byte CLINT_BASE + 0x4000, 0x0000DEADBEEF00B7, read08_test # 08-bit read: success
|
||||
|
||||
.8byte CLINT_BASE, 0xbad, 0x2 # execute: instruction access fault
|
||||
.8byte CLINT_BASE, 0xbad, executable_test# execute: instruction access fault
|
||||
|
||||
# ----------------- PLIC ---------------------
|
||||
|
||||
.8byte PLIC_BASE, 0x0000DEADBEEF00B8, 0x0 # 64-bit write: store access fault
|
||||
.8byte PLIC_BASE, 0x0000DEADBEEF00B8, 0x1 # 64-bit read: load access fault
|
||||
.8byte PLIC_BASE, 0x0000DEADBEEF00B8, write64_test # 64-bit write: store access fault
|
||||
.8byte PLIC_BASE, 0x0000DEADBEEF00B8, read64_test # 64-bit read: load access fault
|
||||
# Write 0x2 instead of wider value to plic address because the register width might change.
|
||||
.8byte PLIC_BASE + 0x2000, 0x2, 0x11 # 32-bit write: success
|
||||
.8byte PLIC_BASE + 0x2000, 0x2, 0x14 # 32-bit read: success
|
||||
.8byte PLIC_BASE, 0x0000DEADBEEF00BA, 0x12 # 16-bit write: store access fault
|
||||
.8byte PLIC_BASE, 0x0000DEADBEEF00BA, 0x15 # 16-bit read: load access fault
|
||||
.8byte PLIC_BASE, 0x0000DEADBEEF00BB, 0x13 # 08-bit write: store access fault
|
||||
.8byte PLIC_BASE, 0x0000DEADBEEF00BB, 0x16 # 08-bit read: load access fault
|
||||
.8byte PLIC_BASE + 0x2000, 0x2, write32_test # 32-bit write: success
|
||||
.8byte PLIC_BASE + 0x2000, 0x2, read32_test # 32-bit read: success
|
||||
.8byte PLIC_BASE, 0x0000DEADBEEF00BA, write16_test # 16-bit write: store access fault
|
||||
.8byte PLIC_BASE, 0x0000DEADBEEF00BA, read16_test # 16-bit read: load access fault
|
||||
.8byte PLIC_BASE, 0x0000DEADBEEF00BB, write08_test # 08-bit write: store access fault
|
||||
.8byte PLIC_BASE, 0x0000DEADBEEF00BB, read08_test # 08-bit read: load access fault
|
||||
|
||||
.8byte PLIC_BASE, 0xbad, 0x2 # execute: instruction access fault
|
||||
.8byte PLIC_BASE, 0xbad, executable_test# execute: instruction access fault
|
||||
|
||||
# ----------------- UART0 ---------------------
|
||||
|
||||
.8byte UART_BASE, 0x0000DEADBEEF00BC, 0x0 # 64-bit write: store access fault
|
||||
.8byte UART_BASE, 0x0000DEADBEEF00BC, 0x1 # 64-bit read: load access fault
|
||||
.8byte UART_BASE, 0x0000DEADBEEF00BD, 0x11 # 32-bit write: store access fault
|
||||
.8byte UART_BASE, 0x0000DEADBEEF00BD, 0x14 # 32-bit read: load access fault
|
||||
.8byte UART_BASE, 0x0000DEADBEEF00BE, 0x12 # 16-bit write: store access fault
|
||||
.8byte UART_BASE, 0x0000DEADBEEF00BE, 0x15 # 16-bit read: load access fault
|
||||
.8byte UART_BASE, 0x0000DEADBEEF00BC, write64_test # 64-bit write: store access fault
|
||||
.8byte UART_BASE, 0x0000DEADBEEF00BC, read64_test # 64-bit read: load access fault
|
||||
.8byte UART_BASE, 0x0000DEADBEEF00BD, write32_test # 32-bit write: store access fault
|
||||
.8byte UART_BASE, 0x0000DEADBEEF00BD, read32_test # 32-bit read: load access fault
|
||||
.8byte UART_BASE, 0x0000DEADBEEF00BE, write16_test # 16-bit write: store access fault
|
||||
.8byte UART_BASE, 0x0000DEADBEEF00BE, read16_test # 16-bit read: load access fault
|
||||
# Different address for this test so that we write into a writable register in the uart.
|
||||
.8byte UART_BASE + 0x3, 0x0000DEADBEEF00BF, 0x13 # 08-bit write: success
|
||||
.8byte UART_BASE + 0x3, 0x0000DEADBEEF00BF, 0x16 # 08-bit read: success
|
||||
.8byte UART_BASE + 0x3, 0x0000DEADBEEF00BF, write08_test # 08-bit write: success
|
||||
.8byte UART_BASE + 0x3, 0x0000DEADBEEF00BF, read08_test # 08-bit read: success
|
||||
|
||||
.8byte UART_BASE, 0xbad, 0x2 # execute: instruction access fault
|
||||
.8byte UART_BASE, 0xbad, executable_test# execute: instruction access fault
|
||||
|
||||
# ----------------- GPIO ---------------------
|
||||
|
||||
.8byte GPIO_BASE, 0x0000DEADBEEF00C0, 0x0 # 64-bit write: store access fault
|
||||
.8byte GPIO_BASE, 0x0000DEADBEEF00C0, 0x1 # 64-bit read: load access fault
|
||||
.8byte GPIO_BASE + 0x8, 0x0000DEADBEEF00C1, 0x11 # 32-bit write: success
|
||||
.8byte GPIO_BASE + 0x8, 0x0000DEADBEEF00C1, 0x14 # 32-bit read: success
|
||||
.8byte GPIO_BASE, 0x0000DEADBEEF00C2, 0x12 # 16-bit write: store access fault
|
||||
.8byte GPIO_BASE, 0x0000DEADBEEF00C2, 0x15 # 16-bit read: load access fault
|
||||
.8byte GPIO_BASE, 0x0000DEADBEEF00C3, 0x13 # 08-bit write: store access fault
|
||||
.8byte GPIO_BASE, 0x0000DEADBEEF00C3, 0x16 # 08-bit read: load access fault
|
||||
.8byte GPIO_BASE, 0x0000DEADBEEF00C0, write64_test # 64-bit write: store access fault
|
||||
.8byte GPIO_BASE, 0x0000DEADBEEF00C0, read64_test # 64-bit read: load access fault
|
||||
.8byte GPIO_BASE + 0x8, 0x0000DEADBEEF00C1, write32_test # 32-bit write: success
|
||||
.8byte GPIO_BASE + 0x8, 0x0000DEADBEEF00C1, read32_test # 32-bit read: success
|
||||
.8byte GPIO_BASE, 0x0000DEADBEEF00C2, write16_test # 16-bit write: store access fault
|
||||
.8byte GPIO_BASE, 0x0000DEADBEEF00C2, read16_test # 16-bit read: load access fault
|
||||
.8byte GPIO_BASE, 0x0000DEADBEEF00C3, write08_test # 08-bit write: store access fault
|
||||
.8byte GPIO_BASE, 0x0000DEADBEEF00C3, read08_test # 08-bit read: load access fault
|
||||
|
||||
.8byte GPIO_BASE, 0xbad, 0x2 # execute: instruction access fault
|
||||
.8byte GPIO_BASE, 0xbad, executable_test# execute: instruction access fault
|
||||
|
||||
# ----------------- Inaccessible ---------------------
|
||||
|
||||
# show that load, store, and jalr cause faults in regions not defined by PMAs.
|
||||
|
||||
# Tests 'random' place in unimplemented memory
|
||||
.8byte 0x40000000, 0x0000DEADBEEF00C7, 0x0 # 64-bit write: store access fault
|
||||
.8byte 0x40000000, 0x0000DEADBEEF00C7, 0x1 # 64-bit read: load access fault
|
||||
.8byte 0x40000000, 0x111, 0x2 # execute: instruction access fault
|
||||
.8byte 0x40000000, 0x0000DEADBEEF00C7, write64_test # 64-bit write: store access fault
|
||||
.8byte 0x40000000, 0x0000DEADBEEF00C7, read64_test # 64-bit read: load access fault
|
||||
.8byte 0x40000000, 0x111, executable_test # execute: instruction access fault
|
||||
|
||||
# Tests just past the end of each peripheral
|
||||
.8byte (BOOTROM_BASE+BOOTROM_RANGE+1), 0x0000DEADBEEF00C8, 0x0 # 64-bit write: store access fault
|
||||
.8byte (BOOTROM_BASE+BOOTROM_RANGE+1), 0x0000DEADBEEF00C8, 0x1 # 64-bit read: load access fault
|
||||
.8byte (BOOTROM_BASE+BOOTROM_RANGE+1), 0x111, 0x2 # execute: instruction access fault
|
||||
.8byte (BOOTROM_BASE+BOOTROM_RANGE+1), 0x0000DEADBEEF00C8, write64_test # 64-bit write: store access fault
|
||||
.8byte (BOOTROM_BASE+BOOTROM_RANGE+1), 0x0000DEADBEEF00C8, read64_test # 64-bit read: load access fault
|
||||
.8byte (BOOTROM_BASE+BOOTROM_RANGE+1), 0x111, executable_test # execute: instruction access fault
|
||||
|
||||
.8byte (CLINT_BASE+CLINT_RANGE+1), 0x0000DEADBEEF00C9, 0x0 # 64-bit write: store access fault
|
||||
.8byte (CLINT_BASE+CLINT_RANGE+1), 0x0000DEADBEEF00C9, 0x1 # 64-bit read: load access fault
|
||||
.8byte (CLINT_BASE+CLINT_RANGE+1), 0x111, 0x2 # execute: instruction access fault
|
||||
.8byte (CLINT_BASE+CLINT_RANGE+1), 0x0000DEADBEEF00C9, write64_test # 64-bit write: store access fault
|
||||
.8byte (CLINT_BASE+CLINT_RANGE+1), 0x0000DEADBEEF00C9, read64_test # 64-bit read: load access fault
|
||||
.8byte (CLINT_BASE+CLINT_RANGE+1), 0x111, executable_test # execute: instruction access fault
|
||||
|
||||
.8byte (PLIC_BASE+PLIC_RANGE+1), 0x0000DEADBEEF00CA, 0x11 # 32-bit write: store access fault
|
||||
.8byte (PLIC_BASE+PLIC_RANGE+1), 0x0000DEADBEEF00CA, 0x14 # 32-bit read: load access fault
|
||||
.8byte (PLIC_BASE+PLIC_RANGE+1), 0x111, 0x2 # execute: instruction access fault
|
||||
.8byte (PLIC_BASE+PLIC_RANGE+1), 0x0000DEADBEEF00CA, write32_test # 32-bit write: store access fault
|
||||
.8byte (PLIC_BASE+PLIC_RANGE+1), 0x0000DEADBEEF00CA, read32_test # 32-bit read: load access fault
|
||||
.8byte (PLIC_BASE+PLIC_RANGE+1), 0x111, executable_test # execute: instruction access fault
|
||||
|
||||
.8byte (UART_BASE+UART_RANGE+1), 0x0000DEADBEEF00CB, 0x13 # 08-bit write: store access fault
|
||||
.8byte (UART_BASE+UART_RANGE+1), 0x0000DEADBEEF00CB, 0x16 # 08-bit read: load access fault
|
||||
.8byte (UART_BASE+UART_RANGE+1), 0x111, 0x2 # execute: instruction access fault
|
||||
.8byte (UART_BASE+UART_RANGE+1), 0x0000DEADBEEF00CB, write08_test # 08-bit write: store access fault
|
||||
.8byte (UART_BASE+UART_RANGE+1), 0x0000DEADBEEF00CB, read08_test # 08-bit read: load access fault
|
||||
.8byte (UART_BASE+UART_RANGE+1), 0x111, executable_test # execute: instruction access fault
|
||||
|
||||
.8byte (GPIO_BASE+GPIO_RANGE+1), 0x0000DEADBEEF00CC, 0x11 # 32-bit write: store access fault
|
||||
.8byte (GPIO_BASE+GPIO_RANGE+1), 0x0000DEADBEEF00CC, 0x14 # 32-bit read: load access fault
|
||||
.8byte (GPIO_BASE+GPIO_RANGE+1), 0x111, 0x2 # execute: instruction access fault
|
||||
.8byte (GPIO_BASE+GPIO_RANGE+1), 0x0000DEADBEEF00CC, write32_test # 32-bit write: store access fault
|
||||
.8byte (GPIO_BASE+GPIO_RANGE+1), 0x0000DEADBEEF00CC, read32_test # 32-bit read: load access fault
|
||||
.8byte (GPIO_BASE+GPIO_RANGE+1), 0x111, executable_test # execute: instruction access fault
|
||||
|
||||
.8byte 0x0, 0x0, 0x3 # terminate tests
|
||||
.8byte 0x0, 0x0, terminate_test# terminate tests
|
||||
|
||||
|
||||
|
||||
|
@ -21,7 +21,7 @@
|
||||
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
///////////////////////////////////////////
|
||||
|
||||
#include "WALLY-TEST-LIB-64.S"
|
||||
#include "WALLY-TEST-LIB-64.h"
|
||||
// Test library includes and handler for each type of test, a trap handler, imperas compliance instructions
|
||||
// Ideally this should mean that a test can be written by simply adding .8byte statements as below.
|
||||
|
||||
@ -45,65 +45,65 @@
|
||||
# Test 12.3.2.2.1 Config: Write known values and set PMP config according to table 12.4 in the *** riscv book, copied below
|
||||
|
||||
# write pmpaddr regs. Each of these should output the value of the pmpaddr after being written.
|
||||
# | Reg | pmpaddr | pmpcfg | L | A | X | W | R | Comments |
|
||||
.8byte 0x0, 0x0FFFFFFF, 0xE # | 0 | 0x0FFFFFFF | 1F | 0 | NAPOT | 0 | 1 | 1 | I/O 00000000-7FFFFFFF RW |
|
||||
.8byte 0x1, 0x20040000, 0xE # | 1 | 0x20040000 | 00 | 0 | OFF | 0 | 0 | 0 | |
|
||||
.8byte 0x2, 0x2004003F, 0xE # | 2 | 0x2004003F | 09 | 0 | TOR | 0 | 0 | 1 | 80100000-801000FF R |
|
||||
.8byte 0x3, 0x20040080, 0xE # | 3 | 0x20040080 | 00 | 0 | OFF | 0 | 0 | 0 | |
|
||||
.8byte 0x4, 0x20040084, 0xE # | 4 | 0x20040084 | 0C | 0 | TOR | 1 | 0 | 0 | 80100200-80100210 X |
|
||||
.8byte 0x5, 0x200400C0, 0xE # | 5 | 0x200400C0 | 90 | 1 | NA4 | 0 | 0 | 0 | 80100300-80100303 locked out |
|
||||
.8byte 0x6, 0x2004013F, 0xE # | 6 | 0x2004013F | 18 | 0 | NAPOT | 0 | 0 | 0 | 80100400-801004FF no access |
|
||||
# *** change the pmpcfg and addr commands to the right number # | Reg | pmpaddr | pmpcfg | L | A | X | W | R | Comments |
|
||||
.8byte 0x0, 0x0FFFFFFF, write_pmpaddr_0 # | 0 | 0x0FFFFFFF | 1F | 0 | NAPOT | 0 | 1 | 1 | I/O 00000000-7FFFFFFF RW |
|
||||
.8byte 0x1, 0x20040000, write_pmpaddr_1 # | 1 | 0x20040000 | 00 | 0 | OFF | 0 | 0 | 0 | |
|
||||
.8byte 0x2, 0x2004003F, write_pmpaddr_2 # | 2 | 0x2004003F | 09 | 0 | TOR | 0 | 0 | 1 | 80100000-801000FF R |
|
||||
.8byte 0x3, 0x20040080, write_pmpaddr_3 # | 3 | 0x20040080 | 00 | 0 | OFF | 0 | 0 | 0 | |
|
||||
.8byte 0x4, 0x20040084, write_pmpaddr_4 # | 4 | 0x20040084 | 0C | 0 | TOR | 1 | 0 | 0 | 80100200-80100210 X |
|
||||
.8byte 0x5, 0x200400C0, write_pmpaddr_5 # | 5 | 0x200400C0 | 90 | 1 | NA4 | 0 | 0 | 0 | 80100300-80100303 locked out |
|
||||
.8byte 0x6, 0x2004013F, write_pmpaddr_6 # | 6 | 0x2004013F | 18 | 0 | NAPOT | 0 | 0 | 0 | 80100400-801004FF no access |
|
||||
# Pmpaddr 7-14 are all zeroed out in this test, so they don't need writes.
|
||||
.8byte 0xF, 0x2FFFFFFF, 0xE # | 15 | 0x2FFFFFFF | 1F | 0 | NAPOT | 1 | 1 | 1 | Main mem 80000000-FFFFFFFF RWX|
|
||||
.8byte 0xF, 0x2FFFFFFF, write_pmpaddr_15 # | 15 | 0x2FFFFFFF | 1F | 0 | NAPOT | 1 | 1 | 1 | Main mem 80000000-FFFFFFFF RWX|
|
||||
|
||||
# write pmpcfg regs with the information in the table above. this should also write the value of these registers to the output.
|
||||
.8byte 0x0, 0x0018900C0009001F, 0xD # write pmpcfg0, output 0x0018900C0009001F
|
||||
.8byte 0x2, 0x1F00000000000000, 0xD # write pmpcfg2, output 0x1F00000000000000
|
||||
.8byte 0x0, 0x0018900C0009001F, write_pmpcfg_0 # write pmpcfg0, output 0x0018900C0009001F
|
||||
.8byte 0x2, 0x1F00000000000000, write_pmpcfg_2 # write pmpcfg2, output 0x1F00000000000000
|
||||
|
||||
# write known values to memory where W=0. This should be possible since we're in machine mode.
|
||||
.8byte 0x80100010, 0x600DAA, 0x0 # write to pmpaddr 1-2 range
|
||||
.8byte 0x80100400, 0x600DBB, 0x0 # write to pmpaddr 6 range
|
||||
.8byte 0x80100010, 0x600DAA, write64_test # write to pmpaddr 1-2 range
|
||||
.8byte 0x80100400, 0x600DBB, write64_test # write to pmpaddr 6 range
|
||||
|
||||
# Write executable code to regions where X = 0, 1 in main memory
|
||||
.8byte 0x80100200, 0x0000806711100393, 0x0 # write executable code for "li x7, 0x111; ret" to region with X=1 (PMP4)
|
||||
.8byte 0x80100020, 0x0000806711100393, 0x0 # Write same executable code to region with X=0 (PMP2)
|
||||
.8byte 0x80100200, 0x0000806711100393, write64_test # write executable code for "li x7, 0x111; ret" to region with X=1 (PMP4)
|
||||
.8byte 0x80100020, 0x0000806711100393, write64_test # Write same executable code to region with X=0 (PMP2)
|
||||
|
||||
# attempt to write to pmpaddr5 and pmp5cfg after lockout
|
||||
.8byte 0x0, 0x0018FF0C0009001F, 0xD # attempt to edit only pmp5cfg (pmpcfg0[47:40]) after lockout.
|
||||
.8byte 0x0, 0x0018FF0C0009001F, write_pmpcfg_0 # attempt to edit only pmp5cfg (pmpcfg0[47:40]) after lockout.
|
||||
# instruction ignored, output is 0x0018900C0009001F, NOT 0x0018FF0C0009001F
|
||||
.8byte 0x5, 0xFFFFFFFF, 0xE # attempt to edit pmpaddr5 after lockout.
|
||||
.8byte 0x5, 0xFFFFFFFF, write_pmpaddr_5 # attempt to edit pmpaddr5 after lockout.
|
||||
# instruction ignored, output is 0x80100300, NOT 0xFFFFFFFF
|
||||
|
||||
# Test 12.3.2.2.2 Machine mode access
|
||||
|
||||
.8byte 0x80100300, 0x0, 0x1 # access fault to region with L=1, R=0
|
||||
.8byte 0x80100400, 0x0, 0x1 # successful access to region with L=X=W=R=0
|
||||
.8byte 0x80100300, 0x0, read64_test # access fault to region with L=1, R=0
|
||||
.8byte 0x80100400, 0x0, read64_test # successful access to region with L=X=W=R=0
|
||||
|
||||
# Test 12.3.2.2.3 System mode access
|
||||
|
||||
.8byte 0x0, 0x0, 0x9 # go to S mode. 0xb written to output
|
||||
.8byte 0x0, 0x0, goto_s_mode # go to S mode. 0xb written to output
|
||||
# test a write followed by a read to each region with R=W=1
|
||||
.8byte 0x80200000, 0x600D15, 0x0 # Write "good value" to RW range (PMP15)
|
||||
.8byte 0x80200000, 0x600D15, 0x1 # confirm write with read
|
||||
.8byte 0x80200000, 0x600D15, write64_test # Write "good value" to RW range (PMP15)
|
||||
.8byte 0x80200000, 0x600D15, read64_test # confirm write with read
|
||||
|
||||
# test a write followed by a read on the edges of a read-only range
|
||||
.8byte 0x800FFFF8, 0x600D02, 0x0 # Write "good value" just below read-only range (PMP2)
|
||||
.8byte 0x800FFFF8, 0x600D02, 0x1 # confirm write with read
|
||||
.8byte 0x80100100, 0x600D12, 0x0 # Write "good value" just above read-only range (PMP2)
|
||||
.8byte 0x80100100, 0x600D12, 0x1 # confirm write with read
|
||||
.8byte 0x800FFFF8, 0x600D02, write64_test # Write "good value" just below read-only range (PMP2)
|
||||
.8byte 0x800FFFF8, 0x600D02, read64_test # confirm write with read
|
||||
.8byte 0x80100100, 0x600D12, write64_test # Write "good value" just above read-only range (PMP2)
|
||||
.8byte 0x80100100, 0x600D12, read64_test # confirm write with read
|
||||
|
||||
# test a read from each read only range verify a write causes an access fault
|
||||
.8byte 0x80100010, 0xBAD, 0x0 # Write fault in read-only range (PMP2)
|
||||
.8byte 0x80100010, 0x600DAA, 0x1 # read correct value out
|
||||
.8byte 0x80100010, 0xBAD, write64_test # Write fault in read-only range (PMP2)
|
||||
.8byte 0x80100010, 0x600DAA, read64_test # read correct value out
|
||||
|
||||
# test read and write fault on region with no access
|
||||
.8byte 0x80100208, 0x600D15, 0x0 # Write fault on no-access range (PMP6)
|
||||
.8byte 0x80100208, 0x600D15, 0x1 # read fault on no-access range (PMP6)
|
||||
.8byte 0x80100208, 0x600D15, write64_test # Write fault on no-access range (PMP6)
|
||||
.8byte 0x80100208, 0x600D15, read64_test # read fault on no-access range (PMP6)
|
||||
|
||||
# test jalr to region with X=0 causes access fault
|
||||
.8byte 0x80100020, 0xbad, 0x2 # execute fault on no-execute range (PMP2)
|
||||
.8byte 0x80100020, 0xbad, executable_test # execute fault on no-execute range (PMP2)
|
||||
|
||||
# test jalr to region with X=1 returns successfully
|
||||
.8byte 0x80100200, 0x111, 0x2 # execute success when X=1
|
||||
.8byte 0x80100200, 0x111, executable_test # execute success when X=1
|
||||
|
||||
.8byte 0x0, 0x0, 0x3 // terminate tests
|
||||
.8byte 0x0, 0x0, terminate_test // terminate tests
|
||||
|
@ -1,623 +0,0 @@
|
||||
///////////////////////////////////////////
|
||||
//
|
||||
// WALLY-TEST-LIB-64.S
|
||||
//
|
||||
// Author: Kip Macsai-Goren <kmacsaigoren@g.hmc.edu>
|
||||
//
|
||||
// Created 2021-07-19
|
||||
//
|
||||
// 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 "model_test.h"
|
||||
#include "arch_test.h"
|
||||
RVTEST_ISA("RV64I")
|
||||
|
||||
.section .text.init
|
||||
.globl rvtest_entry_point
|
||||
rvtest_entry_point:
|
||||
RVMODEL_BOOT
|
||||
RVTEST_CODE_BEGIN
|
||||
|
||||
# ---------------------------------------------------------------------------------------------
|
||||
# Initialization Overview:
|
||||
#
|
||||
# Initialize x6 as a virtual pointer to the test results
|
||||
# Initialize x16 as a physical pointer to the test results
|
||||
# Set up stack pointer (sp = x2)
|
||||
# Set up the exception Handler, keeping the original handler in x4.
|
||||
#
|
||||
# ---------------------------------------------------------------------------------------------
|
||||
|
||||
# address for test results
|
||||
la x6, test_1_res
|
||||
la x16, test_1_res # x16 reserved for the physical address equivalent of x6 to be used in trap handlers
|
||||
# any time either is used, both must be updated.
|
||||
|
||||
# address for stack
|
||||
la sp, top_of_stack
|
||||
|
||||
# trap handler setup
|
||||
la x1, machine_trap_handler
|
||||
csrrw x4, mtvec, x1 # x4 reserved for "default" trap handler address that needs to be restored before halting this test.
|
||||
li a0, 0
|
||||
li a1, 0
|
||||
li a2, 0 # reset trap handler inputs to zero
|
||||
|
||||
# go to first test!
|
||||
j test_setup
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------------------------
|
||||
# General traps Handler
|
||||
#
|
||||
# Handles traps by branching to different behaviors based on mcause.
|
||||
#
|
||||
# Note that allowing the exception handler to change mode for a program is a huge security
|
||||
# hole, but this is an expedient way of writing tests that need different modes
|
||||
#
|
||||
# input parameters:
|
||||
#
|
||||
# a0 (x10):
|
||||
# 0: halt program with no failures
|
||||
# 1: halt program with failure in x11 = a1
|
||||
# 2: go to machine mode
|
||||
# 3: go to supervisor mode
|
||||
# 4: go to user mode
|
||||
# others: do nothing
|
||||
#
|
||||
# a1 (x11):
|
||||
# VPN for return address after changing privilege mode.
|
||||
# This should be the base VPN with no offset.
|
||||
# 0x0 : defaults to next instruction on the same page the trap was called on.
|
||||
#
|
||||
# a2 (x12):
|
||||
# Pagetype of the current address VPN before changing privilge mode
|
||||
# Used so that we can know how many bits of the adress are the offset.
|
||||
# Ignored if a1 == 0x0
|
||||
# 0: Kilopage
|
||||
# 1: Megapage
|
||||
# 2: Gigapage
|
||||
# 3: Terapage
|
||||
#
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
machine_trap_handler:
|
||||
# The processor is always in machine mode when a trap takes us here
|
||||
# save registers on stack before using
|
||||
sd x1, -8(sp)
|
||||
sd x5, -16(sp)
|
||||
|
||||
# Record trap
|
||||
csrr x1, mcause # record the mcause
|
||||
sd x1, 0(x16)
|
||||
addi x6, x6, 8
|
||||
addi x16, x16, 8 # update pointers for logging results
|
||||
|
||||
# Respond to trap based on cause
|
||||
# All interrupts should return after being logged
|
||||
li x5, 0x8000000000000000 # if msb is set, it is an interrupt
|
||||
and x5, x5, x1
|
||||
bnez x5, trapreturn # return from interrupt
|
||||
# Other trap handling is specified in the vector Table
|
||||
slli x1, x1, 3 # multiply cause by 8 to get offset in vector Table
|
||||
la x5, trap_handler_vector_table
|
||||
add x5, x5, x1 # compute address of vector in Table
|
||||
ld x5, 0(x5) # fectch address of handler from vector Table
|
||||
jr x5 # and jump to the handler
|
||||
|
||||
segfault:
|
||||
ld x5, -16(sp) # restore registers from stack before faulting
|
||||
ld x1, -8(sp)
|
||||
j terminate_test # halt program.
|
||||
|
||||
trapreturn:
|
||||
# look at the instruction to figure out whether to add 2 or 4 bytes to PC, or go to address specified in a1
|
||||
csrr x1, mepc # get the mepc
|
||||
addi x1, x1, 4 # *** should be 2 for compressed instructions, see note.
|
||||
|
||||
|
||||
# ****** KMG: the following is no longer as easy to determine. mepc gets the virtual address of the trapped instruction,
|
||||
# ******** but in the handler, we work in M mode with physical addresses
|
||||
# This means the address in mepc is suddenly pointing somewhere else.
|
||||
# to get this to work, We could either retranslate the vaddr back into a paddr (probably on the scale of difficult to intractible)
|
||||
# or we could come up with some other ingenious way to stay in M mode and see if the instruction was compressed.
|
||||
|
||||
# lw x5, 0(x1) # read the faulting instruction
|
||||
# li x1, 3 # check bottom 2 bits of instruction to see if compressed
|
||||
# and x5, x5, x1 # mask the other bits
|
||||
# beq x5, x1, trapreturn_uncompressed # if 11, the instruction is return_uncompressed
|
||||
|
||||
# trapreturn_compressed:
|
||||
# csrr x1, mepc # get the mepc again
|
||||
# addi x1, x1, 2 # add 2 to find the next instruction
|
||||
# j trapreturn_specified # and return
|
||||
|
||||
# trapreturn_uncompressed:
|
||||
# csrr x1, mepc # get the mepc again
|
||||
# addi x1, x1, 4 # add 4 to find the next instruction
|
||||
|
||||
trapreturn_specified:
|
||||
# reset the necessary pointers and registers (x1, x5, x6, and the return address going to mepc)
|
||||
# so that when we return to a new virtual address, they're all in the right spot as well.
|
||||
|
||||
beqz a1, trapreturn_finished # either update values, of go to default return address.
|
||||
|
||||
la x5, trap_return_pagetype_table
|
||||
slli a2, a2, 3
|
||||
add x5, x5, a2
|
||||
ld a2, 0(x5) # a2 = number of offset bits in current page type
|
||||
|
||||
li x5, 1
|
||||
sll x5, x5, a2
|
||||
addi x5, x5, -1 # x5 = mask bits for offset into current pagetype
|
||||
|
||||
# reset the top of the stack, x1
|
||||
ld x7, -8(sp)
|
||||
and x7, x5, x7 # x7 = offset for x1
|
||||
add x7, x7, a1 # x7 = new address for x1
|
||||
sd x7, -8(sp)
|
||||
|
||||
# reset the second spot in the stack, x5
|
||||
ld x7, -16(sp)
|
||||
and x7, x5, x7 # x7 = offset for x5
|
||||
add x7, x7, a1 # x7 = new address for x5
|
||||
sd x7, -16(sp)
|
||||
|
||||
# reset x6, the pointer for the virtual address of the output of the tests
|
||||
and x7, x5, x6 # x7 = offset for x6
|
||||
add x6, x7, a1 # x6 = new address for the result pointer
|
||||
|
||||
# set return address, stored temporarily in x1, to the next instruction, but in the new virtual page.
|
||||
and x1, x5, x1 # x1 = offset for the return address
|
||||
add x1, x1, a1 # x1 = new return address.
|
||||
|
||||
li a1, 0
|
||||
li a2, 0 # reset trapreturn inputs to the trap handler
|
||||
|
||||
trapreturn_finished:
|
||||
csrw mepc, x1 # update the mepc with address of next instruction
|
||||
ld x5, -16(sp) # restore registers from stack before returning
|
||||
ld x1, -8(sp)
|
||||
mret # return from trap
|
||||
|
||||
ecallhandler:
|
||||
# Check input parameter a0. encoding above.
|
||||
# *** ASSUMES: that this trap is being handled in machine mode. in other words, that nothing odd has been written to the medeleg or mideleg csrs.
|
||||
li x5, 2 # case 2: change to machine mode
|
||||
beq a0, x5, ecallhandler_changetomachinemode
|
||||
li x5, 3 # case 3: change to supervisor mode
|
||||
beq a0, x5, ecallhandler_changetosupervisormode
|
||||
li x5, 4 # case 4: change to user mode
|
||||
beq a0, x5, ecallhandler_changetousermode
|
||||
# unsupported ecalls should segfault
|
||||
j segfault
|
||||
|
||||
ecallhandler_changetomachinemode:
|
||||
# Force mstatus.MPP (bits 12:11) to 11 to enter machine mode after mret
|
||||
li x1, 0b1100000000000
|
||||
csrs mstatus, x1
|
||||
j trapreturn
|
||||
|
||||
ecallhandler_changetosupervisormode:
|
||||
# Force mstatus.MPP (bits 12:11) to 01 to enter supervisor mode after mret
|
||||
li x1, 0b1100000000000
|
||||
csrc mstatus, x1
|
||||
li x1, 0b0100000000000
|
||||
csrs mstatus, x1
|
||||
j trapreturn
|
||||
|
||||
ecallhandler_changetousermode:
|
||||
# Force mstatus.MPP (bits 12:11) to 00 to enter user mode after mret
|
||||
li x1, 0b1100000000000
|
||||
csrc mstatus, x1
|
||||
j trapreturn
|
||||
|
||||
instrfault:
|
||||
ld x1, -8(sp) # load return address int x1 (the address AFTER the jal into faulting page)
|
||||
j trapreturn_finished # puts x1 into mepc, restores stack and returns to program (outside of faulting page)
|
||||
|
||||
accessfault:
|
||||
# *** What do I have to do here?
|
||||
j trapreturn
|
||||
|
||||
# Table of trap behavior
|
||||
# lists what to do on each exception (not interrupts)
|
||||
# unexpected exceptions should cause segfaults for easy detection
|
||||
# Expected exceptions should increment the EPC to the next instruction and return
|
||||
|
||||
.align 3 # aligns this data table to an 8 byte boundary
|
||||
trap_handler_vector_table:
|
||||
.8byte segfault # 0: instruction address misaligned
|
||||
.8byte instrfault # 1: instruction access fault
|
||||
.8byte segfault # 2: illegal instruction
|
||||
.8byte segfault # 3: breakpoint
|
||||
.8byte segfault # 4: load address misaligned
|
||||
.8byte accessfault # 5: load access fault
|
||||
.8byte segfault # 6: store address misaligned
|
||||
.8byte accessfault # 7: store access fault
|
||||
.8byte ecallhandler # 8: ecall from U-mode
|
||||
.8byte ecallhandler # 9: ecall from S-mode
|
||||
.8byte segfault # 10: reserved
|
||||
.8byte ecallhandler # 11: ecall from M-mode
|
||||
.8byte instrfault # 12: instruction page fault
|
||||
.8byte trapreturn # 13: load page fault
|
||||
.8byte segfault # 14: reserved
|
||||
.8byte trapreturn # 15: store page fault
|
||||
|
||||
.align 3
|
||||
trap_return_pagetype_table:
|
||||
.8byte 0xC # 0: kilopage has 12 offset bits
|
||||
.8byte 0x15 # 1: megapage has 21 offset bits
|
||||
.8byte 0x1E # 2: gigapage has 30 offset bits
|
||||
.8byte 0x27 # 3: terapage has 39 offset bits
|
||||
|
||||
# ---------------------------------------------------------------------------------------------
|
||||
# Test Handler
|
||||
#
|
||||
# This test handler works in a similar wy to the trap handler. It takes in a few things by reading from a table in memory
|
||||
# (see test_cases) and performing certain behavior based on them.
|
||||
#
|
||||
# Input parameters:
|
||||
#
|
||||
# x28:
|
||||
# Address input for the test taking place (think address to read/write, new address to return to, etc...)
|
||||
#
|
||||
# x29:
|
||||
# Value input for the test taking place (think value to write, any other extra info needed)
|
||||
#
|
||||
# x30:
|
||||
# Test type input that determines which kind of test will take place. Encoding for this input is in the table/case statements below
|
||||
#
|
||||
# ------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
test_setup:
|
||||
la x5, test_cases
|
||||
|
||||
test_loop:
|
||||
ld x28, 0(x5) # fetch test case address
|
||||
ld x29, 8(x5) # fetch test case value
|
||||
ld x30, 16(x5) # fetch test case flag
|
||||
addi x5, x5, 24 # set x5 to next test case
|
||||
|
||||
slli x30, x30, 2 # multiply test type by 4 to index into jump table
|
||||
la x7, test_jump_table # load base address of jump table
|
||||
add x7, x7, x30 # get address of jump table entry
|
||||
jr x7 # jump to relevant test
|
||||
|
||||
test_jump_table:
|
||||
# x30 Value : Function : Fault output value : Normal output values
|
||||
# ----------:---------------------------------------:------------------------:------------------------------------------------------
|
||||
j write64_test # 0x0 : Write 64 bits to address : 0xf : None
|
||||
j read64_test # 0x1 : Read 64 bits from address : 0xd, 0xbad : readvalue in hex
|
||||
j executable_test # 0x2 : test executable on virtual page : 0xc, 0xbad : value of x7 modified by exectuion code (usually 0x111)
|
||||
j terminate_test # 0x3 : terminate tests : mcause value for fault : from M 0xb, from S 0x9, from U 0x8
|
||||
j goto_baremetal # 0x4 : satp.MODE = bare metal : None : None
|
||||
j goto_sv39 # 0x5 : satp.MODE = sv39 : None : None
|
||||
j goto_sv48 # 0x6 : satp.MODE = sv48 : None : None
|
||||
j write_mxr_sum # 0x7 : write sstatus.[19:18] = MXR, SUM bits : None : None
|
||||
j goto_m_mode # 0x8 : go to mahcine mode : mcause value for fault : from M 0xb, from S 0x9, from U 0x8
|
||||
j goto_s_mode # 0x9 : go to supervisor mode : mcause value for fault : from M 0xb, from S 0x9, from U 0x8
|
||||
j goto_u_mode # 0xA : go to user mode : mcause value for fault : from M 0xb, from S 0x9, from U 0x8
|
||||
j segfault # 0xB : Segfault, undefined test
|
||||
j segfault # 0xC : Segfault, undefined test
|
||||
j write_pmpcfg_0 # 0xD : Write one of the pmpcfg csr's : mstatuses?, 0xD : readback of pmpcfg value
|
||||
j write_pmpaddr_0 # 0xE : Write one of the pmpaddr csr's : None : None
|
||||
j segfault # 0xF : Segfault, undefined test
|
||||
j segfault # 0x10 : Segfault, undefined test
|
||||
j write32_test # 0x11 : Write 32 bits to address : 0xf : None
|
||||
j write16_test # 0x12 : Write 16 bits to address : 0xf : None
|
||||
j write08_test # 0x13 : Write 8 bits to address : 0xf : None
|
||||
j read32_test # 0x14 : Read 32 bitsfrom address : 0xd, 0xbad : readvalue in hex
|
||||
j read16_test # 0x15 : Read 16 bitsfrom address : 0xd, 0xbad : readvalue in hex
|
||||
j read08_test # 0x16 : Read 8 bitsfrom address : 0xd, 0xbad : readvalue in hex
|
||||
|
||||
write64_test:
|
||||
# address to write in x28, double value in x29
|
||||
sd x29, 0(x28)
|
||||
j test_loop # go to next test case
|
||||
|
||||
write32_test:
|
||||
# address to write in x28, word value in x29
|
||||
sw x29, 0(x28)
|
||||
j test_loop # go to next test case
|
||||
|
||||
write16_test:
|
||||
# address to write in x28, halfword value in x29
|
||||
sh x29, 0(x28)
|
||||
j test_loop # go to next test case
|
||||
|
||||
write08_test:
|
||||
# address to write in x28, value in x29
|
||||
sb x29, 0(x28)
|
||||
j test_loop # go to next test case
|
||||
|
||||
read64_test:
|
||||
# address to read in x28, expected 64 bit value in x29 (unused, but there for your perusal).
|
||||
li x7, 0xBAD # bad value that will be overwritten on good reads.
|
||||
ld x7, 0(x28)
|
||||
sd x7, 0(x6)
|
||||
addi x6, x6, 8
|
||||
addi x16, x16, 8
|
||||
j test_loop # go to next test case
|
||||
|
||||
read32_test:
|
||||
# address to read in x28, expected 32 bit value in x29 (unused, but there for your perusal).
|
||||
li x7, 0xBAD # bad value that will be overwritten on good reads.
|
||||
lw x7, 0(x28)
|
||||
sd x7, 0(x6)
|
||||
addi x6, x6, 8
|
||||
addi x16, x16, 8
|
||||
j test_loop # go to next test case
|
||||
|
||||
read16_test:
|
||||
# address to read in x28, expected 16 bit value in x29 (unused, but there for your perusal).
|
||||
li x7, 0xBAD # bad value that will be overwritten on good reads.
|
||||
lh x7, 0(x28)
|
||||
sd x7, 0(x6)
|
||||
addi x6, x6, 8
|
||||
addi x16, x16, 8
|
||||
j test_loop # go to next test case
|
||||
|
||||
read08_test:
|
||||
# address to read in x28, expected 8 bit value in x29 (unused, but there for your perusal).
|
||||
li x7, 0xBAD # bad value that will be overwritten on good reads.
|
||||
lb x7, 0(x28)
|
||||
sd x7, 0(x6)
|
||||
addi x6, x6, 8
|
||||
addi x16, x16, 8
|
||||
j test_loop # go to next test case
|
||||
|
||||
goto_s_mode:
|
||||
# return to address in x28,
|
||||
li a0, 3 # Trap handler behavior (go to supervisor mode)
|
||||
mv a1, x28 # return VPN
|
||||
mv a2, x29 # return page types
|
||||
ecall # writes mcause to the output.
|
||||
# now in S mode
|
||||
j test_loop
|
||||
|
||||
goto_m_mode:
|
||||
li a0, 2 # Trap handler behavior (go to machine mode)
|
||||
mv a1, x28 # return VPN
|
||||
mv a2, x29 # return page types
|
||||
ecall # writes mcause to the output.
|
||||
j test_loop
|
||||
|
||||
goto_u_mode:
|
||||
li a0, 4 # Trap handler behavior (go to user mode)
|
||||
mv a1, x28 # return VPN
|
||||
mv a2, x29 # return page types
|
||||
ecall # writes mcause to the output.
|
||||
j test_loop
|
||||
|
||||
goto_baremetal:
|
||||
# Turn translation off
|
||||
li x7, 0 # satp.MODE value for bare metal (0)
|
||||
slli x7, x7, 60
|
||||
li x28, 0x8000D # Base Pagetable physical page number, satp.PPN field.
|
||||
add x7, x7, x28
|
||||
csrw satp, x7
|
||||
sfence.vma x0, x0 # *** flushes global pte's as well
|
||||
j test_loop # go to next test case
|
||||
|
||||
goto_sv39:
|
||||
li x7, 8 # satp.MODE value for Sv39 (8)
|
||||
slli x7, x7, 60
|
||||
li x28, 0x8000D # Base Pagetable physical page number, satp.PPN field.
|
||||
add x7, x7, x28
|
||||
csrw satp, x7
|
||||
sfence.vma x0, x0 # *** flushes global pte's as well
|
||||
j test_loop # go to next test case
|
||||
|
||||
goto_sv48:
|
||||
li x7, 9 # satp.MODE value for Sv48
|
||||
slli x7, x7, 60
|
||||
li x28, 0x8000D # Base Pagetable physical page number, satp.PPN field.
|
||||
add x7, x7, x28
|
||||
csrw satp, x7
|
||||
sfence.vma x0, x0 # *** flushes global pte's as well
|
||||
j test_loop # go to next test case
|
||||
|
||||
write_mxr_sum:
|
||||
# writes sstatus.[mxr, sum] with the (assumed to be) 2 bit value in x29. also assumes we're in S. M mode
|
||||
li x30, 0xC0000 # mask bits for MXR, SUM
|
||||
not x7, x29
|
||||
slli x7, x7, 18
|
||||
and x7, x7, x30
|
||||
slli x29, x29, 18
|
||||
csrc sstatus, x7
|
||||
csrs sstatus, x29
|
||||
j test_loop
|
||||
|
||||
write_pmpcfg_0:
|
||||
# writes the value in x29 to the pmpcfg register specified in x28.
|
||||
# then writes the final value of pmpcfgX to the output.
|
||||
li x7, 0x0
|
||||
bne x7, x28, write_pmpcfg_2
|
||||
csrw pmpcfg0, x29
|
||||
csrr x30, pmpcfg0
|
||||
write_pmpcfg_2:
|
||||
li x7, 0x2
|
||||
bne x7, x28, write_pmpcfg_end
|
||||
csrw pmpcfg2, x29
|
||||
csrr x30, pmpcfg2 # I would use csrrw but we need the value AFTER the csr has been written
|
||||
write_pmpcfg_end:
|
||||
sd x30, 0(x6)
|
||||
addi x6, x6, 8
|
||||
addi x16, x16, 8
|
||||
j test_loop
|
||||
|
||||
write_pmpaddr_0:
|
||||
# writes the value in x29 to the pmpaddr register specified in x28.
|
||||
# then writes the final value of pmpaddrX to the output.
|
||||
li x7, 0x0
|
||||
bne x7, x28, write_pmpaddr_1
|
||||
csrw pmpaddr0, x29
|
||||
csrr x30, pmpaddr0
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_1:
|
||||
li x7, 0x1
|
||||
bne x7, x28, write_pmpaddr_2
|
||||
csrw pmpaddr1, x29
|
||||
csrr x30, pmpaddr1
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_2:
|
||||
li x7, 0x2
|
||||
bne x7, x28, write_pmpaddr_3
|
||||
csrw pmpaddr2, x29
|
||||
csrr x30, pmpaddr2
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_3:
|
||||
li x7, 0x3
|
||||
bne x7, x28, write_pmpaddr_4
|
||||
csrw pmpaddr3, x29
|
||||
csrr x30, pmpaddr3
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_4:
|
||||
li x7, 0x4
|
||||
bne x7, x28, write_pmpaddr_5
|
||||
csrw pmpaddr4, x29
|
||||
csrr x30, pmpaddr4
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_5:
|
||||
li x7, 0x5
|
||||
bne x7, x28, write_pmpaddr_6
|
||||
csrw pmpaddr5, x29
|
||||
csrr x30, pmpaddr5
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_6:
|
||||
li x7, 0x6
|
||||
bne x7, x28, write_pmpaddr_7
|
||||
csrw pmpaddr6, x29
|
||||
csrr x30, pmpaddr6
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_7:
|
||||
li x7, 0x7
|
||||
bne x7, x28, write_pmpaddr_8
|
||||
csrw pmpaddr7, x29
|
||||
csrr x30, pmpaddr7
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_8:
|
||||
li x7, 0x8
|
||||
bne x7, x28, write_pmpaddr_9
|
||||
csrw pmpaddr8, x29
|
||||
csrr x30, pmpaddr8
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_9:
|
||||
li x7, 0x9
|
||||
bne x7, x28, write_pmpaddr_10
|
||||
csrw pmpaddr9, x29
|
||||
csrr x30, pmpaddr9
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_10:
|
||||
li x7, 0xA
|
||||
bne x7, x28, write_pmpaddr_11
|
||||
csrw pmpaddr10, x29
|
||||
csrr x30, pmpaddr10
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_11:
|
||||
li x7, 0xB
|
||||
bne x7, x28, write_pmpaddr_12
|
||||
csrw pmpaddr11, x29
|
||||
csrr x30, pmpaddr11
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_12:
|
||||
li x7, 0xC
|
||||
bne x7, x28, write_pmpaddr_13
|
||||
csrw pmpaddr12, x29
|
||||
csrr x30, pmpaddr12
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_13:
|
||||
li x7, 0xD
|
||||
bne x7, x28, write_pmpaddr_14
|
||||
csrw pmpaddr13, x29
|
||||
csrr x30, pmpaddr13
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_14:
|
||||
li x7, 0xE
|
||||
bne x7, x28, write_pmpaddr_15
|
||||
csrw pmpaddr14, x29
|
||||
csrr x30, pmpaddr14
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_15:
|
||||
li x7, 0xF
|
||||
bne x7, x28, write_pmpaddr_end
|
||||
csrw pmpaddr15, x29
|
||||
csrr x30, pmpaddr15
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_end:
|
||||
sd x30, 0(x6)
|
||||
addi x6, x6, 8
|
||||
addi x16, x16, 8
|
||||
j test_loop
|
||||
|
||||
executable_test:
|
||||
# Execute the code at the address in x28, returning the value in x7.
|
||||
# Assumes the code modifies x7, to become the value stored in x29 for this test.
|
||||
fence.i # forces cache and main memory to sync so execution code written by the program can run.
|
||||
li x7, 0xBAD
|
||||
jalr x28
|
||||
sd x7, 0(x6)
|
||||
addi x6, x6, 8
|
||||
addi x16, x16, 8
|
||||
j test_loop
|
||||
|
||||
terminate_test:
|
||||
|
||||
li a0, 2 # Trap handler behavior (go to machine mode)
|
||||
ecall # writes mcause to the output.
|
||||
csrw mtvec, x4 # restore original trap handler to halt program
|
||||
|
||||
RVTEST_CODE_END
|
||||
RVMODEL_HALT
|
||||
|
||||
RVTEST_DATA_BEGIN
|
||||
.align 4
|
||||
rvtest_data:
|
||||
.word 0xbabecafe
|
||||
RVTEST_DATA_END
|
||||
|
||||
.align 3 # align stack to 8 byte boundary
|
||||
bottom_of_stack:
|
||||
.fill 1024, 4, 0xdeadbeef
|
||||
top_of_stack:
|
||||
|
||||
|
||||
RVMODEL_DATA_BEGIN
|
||||
|
||||
test_1_res:
|
||||
.fill 1024, 4, 0xdeadbeef
|
||||
|
||||
RVMODEL_DATA_END
|
||||
|
||||
#ifdef rvtest_mtrap_routine
|
||||
|
||||
mtrap_sigptr:
|
||||
.fill 64*(XLEN/32),4,0xdeadbeef
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef rvtest_gpr_save
|
||||
|
||||
gpr_save:
|
||||
.fill 32*(XLEN/32),4,0xdeadbeef
|
||||
|
||||
#endif
|
||||
|
||||
.align 3
|
||||
test_cases:
|
||||
|
@ -0,0 +1,624 @@
|
||||
///////////////////////////////////////////
|
||||
//
|
||||
// WALLY-TEST-LIB-64.S
|
||||
//
|
||||
// Author: Kip Macsai-Goren <kmacsaigoren@g.hmc.edu>
|
||||
//
|
||||
// Created 2021-07-19
|
||||
//
|
||||
// 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 "model_test.h"
|
||||
#include "arch_test.h"
|
||||
RVTEST_ISA("RV64I")
|
||||
|
||||
.section .text.init
|
||||
.globl rvtest_entry_point
|
||||
rvtest_entry_point:
|
||||
RVMODEL_BOOT
|
||||
RVTEST_CODE_BEGIN
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
// Initialization Overview:
|
||||
//
|
||||
// Initialize x6 as a virtual pointer to the test results
|
||||
// Initialize x16 as a physical pointer to the test results
|
||||
// Set up stack pointer (sp = x2)
|
||||
// Set up the exception Handler, keeping the original handler in x4.
|
||||
//
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
|
||||
// address for test results
|
||||
la x6, test_1_res
|
||||
la x16, test_1_res // x16 reserved for the physical address equivalent of x6 to be used in trap handlers
|
||||
// any time either is used, both must be updated.
|
||||
|
||||
// address for stack
|
||||
la sp, top_of_stack
|
||||
|
||||
// trap handler setup
|
||||
la x1, machine_trap_handler
|
||||
csrrw x4, mtvec, x1 // x4 reserved for "default" trap handler address that needs to be restored before halting this test.
|
||||
li a0, 0
|
||||
li a1, 0
|
||||
li a2, 0 // reset trap handler inputs to zero
|
||||
|
||||
// go to first test!
|
||||
j test_setup
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
// General traps Handler
|
||||
//
|
||||
// Handles traps by branching to different behaviors based on mcause.
|
||||
//
|
||||
// Note that allowing the exception handler to change mode for a program is a huge security
|
||||
// hole, but this is an expedient way of writing tests that need different modes
|
||||
//
|
||||
// input parameters:
|
||||
//
|
||||
// a0 (x10):
|
||||
// 0: halt program with no failures
|
||||
// 1: halt program with failure in x11 = a1
|
||||
// 2: go to machine mode
|
||||
// 3: go to supervisor mode
|
||||
// 4: go to user mode
|
||||
// others: do nothing
|
||||
//
|
||||
// a1 (x11):
|
||||
// VPN for return address after changing privilege mode.
|
||||
// This should be the base VPN with no offset.
|
||||
// 0x0 : defaults to next instruction on the same page the trap was called on.
|
||||
//
|
||||
// a2 (x12):
|
||||
// Pagetype of the current address VPN before changing privilge mode
|
||||
// Used so that we can know how many bits of the adress are the offset.
|
||||
// Ignored if a1 == 0x0
|
||||
// 0: Kilopage
|
||||
// 1: Megapage
|
||||
// 2: Gigapage
|
||||
// 3: Terapage
|
||||
//
|
||||
// --------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
machine_trap_handler:
|
||||
// The processor is always in machine mode when a trap takes us here
|
||||
// save registers on stack before using
|
||||
sd x1, -8(sp)
|
||||
sd x5, -16(sp)
|
||||
|
||||
// Record trap
|
||||
csrr x1, mcause // record the mcause
|
||||
sd x1, 0(x16)
|
||||
addi x6, x6, 8
|
||||
addi x16, x16, 8 // update pointers for logging results
|
||||
|
||||
// Respond to trap based on cause
|
||||
// All interrupts should return after being logged
|
||||
li x5, 0x8000000000000000 // if msb is set, it is an interrupt
|
||||
and x5, x5, x1
|
||||
bnez x5, trapreturn // return from interrupt
|
||||
// Other trap handling is specified in the vector Table
|
||||
slli x1, x1, 3 // multiply cause by 8 to get offset in vector Table
|
||||
la x5, trap_handler_vector_table
|
||||
add x5, x5, x1 // compute address of vector in Table
|
||||
ld x5, 0(x5) // fectch address of handler from vector Table
|
||||
jr x5 // and jump to the handler
|
||||
|
||||
segfault:
|
||||
ld x5, -16(sp) // restore registers from stack before faulting
|
||||
ld x1, -8(sp)
|
||||
j terminate_test // halt program.
|
||||
|
||||
trapreturn:
|
||||
// look at the instruction to figure out whether to add 2 or 4 bytes to PC, or go to address specified in a1
|
||||
csrr x1, mepc // get the mepc
|
||||
addi x1, x1, 4 // *** should be 2 for compressed instructions, see note.
|
||||
|
||||
|
||||
// ****** KMG: the following is no longer as easy to determine. mepc gets the virtual address of the trapped instruction,
|
||||
// ******** but in the handler, we work in M mode with physical addresses
|
||||
// This means the address in mepc is suddenly pointing somewhere else.
|
||||
// to get this to work, We could either retranslate the vaddr back into a paddr (probably on the scale of difficult to intractible)
|
||||
// or we could come up with some other ingenious way to stay in M mode and see if the instruction was compressed.
|
||||
|
||||
// lw x5, 0(x1) // read the faulting instruction
|
||||
// li x1, 3 // check bottom 2 bits of instruction to see if compressed
|
||||
// and x5, x5, x1 // mask the other bits
|
||||
// beq x5, x1, trapreturn_uncompressed // if 11, the instruction is return_uncompressed
|
||||
|
||||
// trapreturn_compressed:
|
||||
// csrr x1, mepc // get the mepc again
|
||||
// addi x1, x1, 2 // add 2 to find the next instruction
|
||||
// j trapreturn_specified // and return
|
||||
|
||||
// trapreturn_uncompressed:
|
||||
// csrr x1, mepc // get the mepc again
|
||||
// addi x1, x1, 4 // add 4 to find the next instruction
|
||||
|
||||
trapreturn_specified:
|
||||
// reset the necessary pointers and registers (x1, x5, x6, and the return address going to mepc)
|
||||
// so that when we return to a new virtual address, they're all in the right spot as well.
|
||||
|
||||
beqz a1, trapreturn_finished // either update values, of go to default return address.
|
||||
|
||||
la x5, trap_return_pagetype_table
|
||||
slli a2, a2, 3
|
||||
add x5, x5, a2
|
||||
ld a2, 0(x5) // a2 = number of offset bits in current page type
|
||||
|
||||
li x5, 1
|
||||
sll x5, x5, a2
|
||||
addi x5, x5, -1 // x5 = mask bits for offset into current pagetype
|
||||
|
||||
// reset the top of the stack, x1
|
||||
ld x7, -8(sp)
|
||||
and x7, x5, x7 // x7 = offset for x1
|
||||
add x7, x7, a1 // x7 = new address for x1
|
||||
sd x7, -8(sp)
|
||||
|
||||
// reset the second spot in the stack, x5
|
||||
ld x7, -16(sp)
|
||||
and x7, x5, x7 // x7 = offset for x5
|
||||
add x7, x7, a1 // x7 = new address for x5
|
||||
sd x7, -16(sp)
|
||||
|
||||
// reset x6, the pointer for the virtual address of the output of the tests
|
||||
and x7, x5, x6 // x7 = offset for x6
|
||||
add x6, x7, a1 // x6 = new address for the result pointer
|
||||
|
||||
// set return address, stored temporarily in x1, to the next instruction, but in the new virtual page.
|
||||
and x1, x5, x1 // x1 = offset for the return address
|
||||
add x1, x1, a1 // x1 = new return address.
|
||||
|
||||
li a1, 0
|
||||
li a2, 0 // reset trapreturn inputs to the trap handler
|
||||
|
||||
trapreturn_finished:
|
||||
csrw mepc, x1 // update the mepc with address of next instruction
|
||||
ld x5, -16(sp) // restore registers from stack before returning
|
||||
ld x1, -8(sp)
|
||||
mret // return from trap
|
||||
|
||||
ecallhandler:
|
||||
// Check input parameter a0. encoding above.
|
||||
// *** ASSUMES: that this trap is being handled in machine mode. in other words, that nothing odd has been written to the medeleg or mideleg csrs.
|
||||
li x5, 2 // case 2: change to machine mode
|
||||
beq a0, x5, ecallhandler_changetomachinemode
|
||||
li x5, 3 // case 3: change to supervisor mode
|
||||
beq a0, x5, ecallhandler_changetosupervisormode
|
||||
li x5, 4 // case 4: change to user mode
|
||||
beq a0, x5, ecallhandler_changetousermode
|
||||
// unsupported ecalls should segfault
|
||||
j segfault
|
||||
|
||||
ecallhandler_changetomachinemode:
|
||||
// Force mstatus.MPP (bits 12:11) to 11 to enter machine mode after mret
|
||||
li x1, 0b1100000000000
|
||||
csrs mstatus, x1
|
||||
j trapreturn
|
||||
|
||||
ecallhandler_changetosupervisormode:
|
||||
// Force mstatus.MPP (bits 12:11) to 01 to enter supervisor mode after mret
|
||||
li x1, 0b1100000000000
|
||||
csrc mstatus, x1
|
||||
li x1, 0b0100000000000
|
||||
csrs mstatus, x1
|
||||
j trapreturn
|
||||
|
||||
ecallhandler_changetousermode:
|
||||
// Force mstatus.MPP (bits 12:11) to 00 to enter user mode after mret
|
||||
li x1, 0b1100000000000
|
||||
csrc mstatus, x1
|
||||
j trapreturn
|
||||
|
||||
instrfault:
|
||||
ld x1, -8(sp) // load return address int x1 (the address AFTER the jal into faulting page)
|
||||
j trapreturn_finished // puts x1 into mepc, restores stack and returns to program (outside of faulting page)
|
||||
|
||||
accessfault:
|
||||
// *** What do I have to do here?
|
||||
j trapreturn
|
||||
|
||||
// Table of trap behavior
|
||||
// lists what to do on each exception (not interrupts)
|
||||
// unexpected exceptions should cause segfaults for easy detection
|
||||
// Expected exceptions should increment the EPC to the next instruction and return
|
||||
|
||||
.align 3 // aligns this data table to an 8 byte boundary
|
||||
trap_handler_vector_table:
|
||||
.8byte segfault // 0: instruction address misaligned
|
||||
.8byte instrfault // 1: instruction access fault
|
||||
.8byte segfault // 2: illegal instruction
|
||||
.8byte segfault // 3: breakpoint
|
||||
.8byte segfault // 4: load address misaligned
|
||||
.8byte accessfault // 5: load access fault
|
||||
.8byte segfault // 6: store address misaligned
|
||||
.8byte accessfault // 7: store access fault
|
||||
.8byte ecallhandler // 8: ecall from U-mode
|
||||
.8byte ecallhandler // 9: ecall from S-mode
|
||||
.8byte segfault // 10: reserved
|
||||
.8byte ecallhandler // 11: ecall from M-mode
|
||||
.8byte instrfault // 12: instruction page fault
|
||||
.8byte trapreturn // 13: load page fault
|
||||
.8byte segfault // 14: reserved
|
||||
.8byte trapreturn // 15: store page fault
|
||||
|
||||
.align 3
|
||||
trap_return_pagetype_table:
|
||||
.8byte 0xC // 0: kilopage has 12 offset bits
|
||||
.8byte 0x15 // 1: megapage has 21 offset bits
|
||||
.8byte 0x1E // 2: gigapage has 30 offset bits
|
||||
.8byte 0x27 // 3: terapage has 39 offset bits
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
// Test Handler
|
||||
//
|
||||
// This test handler works in a similar wy to the trap handler. It takes in a few things by reading from a table in memory
|
||||
// (see test_cases) and performing certain behavior based on them.
|
||||
//
|
||||
// Input parameters:
|
||||
//
|
||||
// x28:
|
||||
// Address input for the test taking place (think address to read/write, new address to return to, etc...)
|
||||
//
|
||||
// x29:
|
||||
// Value input for the test taking place (think value to write, any other extra info needed)
|
||||
//
|
||||
// x30:
|
||||
// Test type input that determines which kind of test will take place. Encoding for this input is in the table/case statements below
|
||||
//
|
||||
// ------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
test_setup:
|
||||
la x5, test_cases
|
||||
|
||||
test_loop:
|
||||
ld x28, 0(x5) // fetch test case address
|
||||
ld x29, 8(x5) // fetch test case value
|
||||
ld x30, 16(x5) // fetch test case flag
|
||||
addi x5, x5, 24 // set x5 to next test case
|
||||
|
||||
// x5 has the symbol for a test's location in the assembly
|
||||
li x7, 0x1FFFFF
|
||||
and x30, x30, x7 // This program is always on at least a megapage, so this masks out the megapage offset.
|
||||
auipc x7, 0x0
|
||||
srli x7, x7, 21
|
||||
slli x7, x7, 21 // zero out the bottom 21 bits so the megapage offset of the symbol can be placed there
|
||||
or x30, x7, x30 // x30 = virtual address of the symbol for this type of test.
|
||||
|
||||
jr x30
|
||||
|
||||
// Test Name : Description : Fault output value : Normal output values
|
||||
// ----------------------:-------------------------------------------:------------------------:------------------------------------------------------
|
||||
// write64_test : Write 64 bits to address : 0xf : None
|
||||
// write32_test : Write 32 bits to address : 0xf : None
|
||||
// write16_test : Write 16 bits to address : 0xf : None
|
||||
// write08_test : Write 8 bits to address : 0xf : None
|
||||
// read64_test : Read 64 bits from address : 0xd, 0xbad : readvalue in hex
|
||||
// read32_test : Read 32 bitsfrom address : 0xd, 0xbad : readvalue in hex
|
||||
// read16_test : Read 16 bitsfrom address : 0xd, 0xbad : readvalue in hex
|
||||
// read08_test : Read 8 bitsfrom address : 0xd, 0xbad : readvalue in hex
|
||||
// executable_test : test executable on virtual page : 0xc, 0xbad : value of x7 modified by exectuion code (usually 0x111)
|
||||
// terminate_test : terminate tests : mcause value for fault : from M 0xb, from S 0x9, from U 0x8
|
||||
// goto_baremetal : satp.MODE = bare metal : None : None
|
||||
// goto_sv39 : satp.MODE = sv39 : None : None
|
||||
// goto_sv48 : satp.MODE = sv48 : None : None
|
||||
// write_mxr_sum : write sstatus.[19:18] = MXR, SUM bits : None : None
|
||||
// goto_m_mode : go to mahcine mode : mcause value for fault : from M 0xb, from S 0x9, from U 0x8
|
||||
// goto_s_mode : go to supervisor mode : mcause value for fault : from M 0xb, from S 0x9, from U 0x8
|
||||
// goto_u_mode : go to user mode : mcause value for fault : from M 0xb, from S 0x9, from U 0x8
|
||||
// write_pmpcfg_x : Write one of the pmpcfg csr's : mstatuses?, 0xD : readback of pmpcfg value
|
||||
// write_pmpaddr_x : Write one of the pmpaddr csr's : None : readback of pmpaddr value
|
||||
|
||||
|
||||
write64_test:
|
||||
// address to write in x28, double value in x29
|
||||
sd x29, 0(x28)
|
||||
j test_loop // go to next test case
|
||||
|
||||
write32_test:
|
||||
// address to write in x28, word value in x29
|
||||
sw x29, 0(x28)
|
||||
j test_loop // go to next test case
|
||||
|
||||
write16_test:
|
||||
// address to write in x28, halfword value in x29
|
||||
sh x29, 0(x28)
|
||||
j test_loop // go to next test case
|
||||
|
||||
write08_test:
|
||||
// address to write in x28, value in x29
|
||||
sb x29, 0(x28)
|
||||
j test_loop // go to next test case
|
||||
|
||||
read64_test:
|
||||
// address to read in x28, expected 64 bit value in x29 (unused, but there for your perusal).
|
||||
li x7, 0xBAD // bad value that will be overwritten on good reads.
|
||||
ld x7, 0(x28)
|
||||
sd x7, 0(x6)
|
||||
addi x6, x6, 8
|
||||
addi x16, x16, 8
|
||||
j test_loop // go to next test case
|
||||
|
||||
read32_test:
|
||||
// address to read in x28, expected 32 bit value in x29 (unused, but there for your perusal).
|
||||
li x7, 0xBAD // bad value that will be overwritten on good reads.
|
||||
lw x7, 0(x28)
|
||||
sd x7, 0(x6)
|
||||
addi x6, x6, 8
|
||||
addi x16, x16, 8
|
||||
j test_loop // go to next test case
|
||||
|
||||
read16_test:
|
||||
// address to read in x28, expected 16 bit value in x29 (unused, but there for your perusal).
|
||||
li x7, 0xBAD // bad value that will be overwritten on good reads.
|
||||
lh x7, 0(x28)
|
||||
sd x7, 0(x6)
|
||||
addi x6, x6, 8
|
||||
addi x16, x16, 8
|
||||
j test_loop // go to next test case
|
||||
|
||||
read08_test:
|
||||
// address to read in x28, expected 8 bit value in x29 (unused, but there for your perusal).
|
||||
li x7, 0xBAD // bad value that will be overwritten on good reads.
|
||||
lb x7, 0(x28)
|
||||
sd x7, 0(x6)
|
||||
addi x6, x6, 8
|
||||
addi x16, x16, 8
|
||||
j test_loop // go to next test case
|
||||
|
||||
goto_s_mode:
|
||||
// return to address in x28,
|
||||
li a0, 3 // Trap handler behavior (go to supervisor mode)
|
||||
mv a1, x28 // return VPN
|
||||
mv a2, x29 // return page types
|
||||
ecall // writes mcause to the output.
|
||||
// now in S mode
|
||||
j test_loop
|
||||
|
||||
goto_m_mode:
|
||||
li a0, 2 // Trap handler behavior (go to machine mode)
|
||||
mv a1, x28 // return VPN
|
||||
mv a2, x29 // return page types
|
||||
ecall // writes mcause to the output.
|
||||
j test_loop
|
||||
|
||||
goto_u_mode:
|
||||
li a0, 4 // Trap handler behavior (go to user mode)
|
||||
mv a1, x28 // return VPN
|
||||
mv a2, x29 // return page types
|
||||
ecall // writes mcause to the output.
|
||||
j test_loop
|
||||
|
||||
goto_baremetal:
|
||||
// Turn translation off
|
||||
li x7, 0 // satp.MODE value for bare metal (0)
|
||||
slli x7, x7, 60
|
||||
li x28, 0x8000D // Base Pagetable physical page number, satp.PPN field.
|
||||
add x7, x7, x28
|
||||
csrw satp, x7
|
||||
sfence.vma x0, x0 // *** flushes global pte's as well
|
||||
j test_loop // go to next test case
|
||||
|
||||
goto_sv39:
|
||||
li x7, 8 // satp.MODE value for Sv39 (8)
|
||||
slli x7, x7, 60
|
||||
li x28, 0x8000D // Base Pagetable physical page number, satp.PPN field.
|
||||
add x7, x7, x28
|
||||
csrw satp, x7
|
||||
sfence.vma x0, x0 // *** flushes global pte's as well
|
||||
j test_loop // go to next test case
|
||||
|
||||
goto_sv48:
|
||||
li x7, 9 // satp.MODE value for Sv48
|
||||
slli x7, x7, 60
|
||||
li x28, 0x8000D // Base Pagetable physical page number, satp.PPN field.
|
||||
add x7, x7, x28
|
||||
csrw satp, x7
|
||||
sfence.vma x0, x0 // *** flushes global pte's as well
|
||||
j test_loop // go to next test case
|
||||
|
||||
write_mxr_sum:
|
||||
// writes sstatus.[mxr, sum] with the (assumed to be) 2 bit value in x29. also assumes we're in S. M mode
|
||||
li x30, 0xC0000 // mask bits for MXR, SUM
|
||||
not x7, x29
|
||||
slli x7, x7, 18
|
||||
and x7, x7, x30
|
||||
slli x29, x29, 18
|
||||
csrc sstatus, x7
|
||||
csrs sstatus, x29
|
||||
j test_loop
|
||||
|
||||
write_pmpcfg_0:
|
||||
// writes the value in x29 to the pmpcfg register specified in x28.
|
||||
// then writes the final value of pmpcfgX to the output.
|
||||
li x7, 0x0
|
||||
bne x7, x28, write_pmpcfg_2
|
||||
csrw pmpcfg0, x29
|
||||
csrr x30, pmpcfg0
|
||||
write_pmpcfg_2:
|
||||
li x7, 0x2
|
||||
bne x7, x28, write_pmpcfg_end
|
||||
csrw pmpcfg2, x29
|
||||
csrr x30, pmpcfg2 // I would use csrrw but we need the value AFTER the csr has been written
|
||||
write_pmpcfg_end:
|
||||
sd x30, 0(x6)
|
||||
addi x6, x6, 8
|
||||
addi x16, x16, 8
|
||||
j test_loop
|
||||
|
||||
write_pmpaddr_0:
|
||||
// writes the value in x29 to the pmpaddr register specified in x28.
|
||||
// then writes the final value of pmpaddrX to the output.
|
||||
li x7, 0x0
|
||||
bne x7, x28, write_pmpaddr_1
|
||||
csrw pmpaddr0, x29
|
||||
csrr x30, pmpaddr0
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_1:
|
||||
li x7, 0x1
|
||||
bne x7, x28, write_pmpaddr_2
|
||||
csrw pmpaddr1, x29
|
||||
csrr x30, pmpaddr1
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_2:
|
||||
li x7, 0x2
|
||||
bne x7, x28, write_pmpaddr_3
|
||||
csrw pmpaddr2, x29
|
||||
csrr x30, pmpaddr2
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_3:
|
||||
li x7, 0x3
|
||||
bne x7, x28, write_pmpaddr_4
|
||||
csrw pmpaddr3, x29
|
||||
csrr x30, pmpaddr3
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_4:
|
||||
li x7, 0x4
|
||||
bne x7, x28, write_pmpaddr_5
|
||||
csrw pmpaddr4, x29
|
||||
csrr x30, pmpaddr4
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_5:
|
||||
li x7, 0x5
|
||||
bne x7, x28, write_pmpaddr_6
|
||||
csrw pmpaddr5, x29
|
||||
csrr x30, pmpaddr5
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_6:
|
||||
li x7, 0x6
|
||||
bne x7, x28, write_pmpaddr_7
|
||||
csrw pmpaddr6, x29
|
||||
csrr x30, pmpaddr6
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_7:
|
||||
li x7, 0x7
|
||||
bne x7, x28, write_pmpaddr_8
|
||||
csrw pmpaddr7, x29
|
||||
csrr x30, pmpaddr7
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_8:
|
||||
li x7, 0x8
|
||||
bne x7, x28, write_pmpaddr_9
|
||||
csrw pmpaddr8, x29
|
||||
csrr x30, pmpaddr8
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_9:
|
||||
li x7, 0x9
|
||||
bne x7, x28, write_pmpaddr_10
|
||||
csrw pmpaddr9, x29
|
||||
csrr x30, pmpaddr9
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_10:
|
||||
li x7, 0xA
|
||||
bne x7, x28, write_pmpaddr_11
|
||||
csrw pmpaddr10, x29
|
||||
csrr x30, pmpaddr10
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_11:
|
||||
li x7, 0xB
|
||||
bne x7, x28, write_pmpaddr_12
|
||||
csrw pmpaddr11, x29
|
||||
csrr x30, pmpaddr11
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_12:
|
||||
li x7, 0xC
|
||||
bne x7, x28, write_pmpaddr_13
|
||||
csrw pmpaddr12, x29
|
||||
csrr x30, pmpaddr12
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_13:
|
||||
li x7, 0xD
|
||||
bne x7, x28, write_pmpaddr_14
|
||||
csrw pmpaddr13, x29
|
||||
csrr x30, pmpaddr13
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_14:
|
||||
li x7, 0xE
|
||||
bne x7, x28, write_pmpaddr_15
|
||||
csrw pmpaddr14, x29
|
||||
csrr x30, pmpaddr14
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_15:
|
||||
li x7, 0xF
|
||||
bne x7, x28, write_pmpaddr_end
|
||||
csrw pmpaddr15, x29
|
||||
csrr x30, pmpaddr15
|
||||
j write_pmpaddr_end
|
||||
write_pmpaddr_end:
|
||||
sd x30, 0(x6)
|
||||
addi x6, x6, 8
|
||||
addi x16, x16, 8
|
||||
j test_loop
|
||||
|
||||
executable_test:
|
||||
// Execute the code at the address in x28, returning the value in x7.
|
||||
// Assumes the code modifies x7, to become the value stored in x29 for this test.
|
||||
fence.i // forces cache and main memory to sync so execution code written by the program can run.
|
||||
li x7, 0xBAD
|
||||
jalr x28
|
||||
sd x7, 0(x6)
|
||||
addi x6, x6, 8
|
||||
addi x16, x16, 8
|
||||
j test_loop
|
||||
|
||||
terminate_test:
|
||||
|
||||
li a0, 2 // Trap handler behavior (go to machine mode)
|
||||
ecall // writes mcause to the output.
|
||||
csrw mtvec, x4 // restore original trap handler to halt program
|
||||
|
||||
RVTEST_CODE_END
|
||||
RVMODEL_HALT
|
||||
|
||||
RVTEST_DATA_BEGIN
|
||||
.align 4
|
||||
rvtest_data:
|
||||
.word 0xbabecafe
|
||||
RVTEST_DATA_END
|
||||
|
||||
.align 3 // align stack to 8 byte boundary
|
||||
bottom_of_stack:
|
||||
.fill 1024, 4, 0xdeadbeef
|
||||
top_of_stack:
|
||||
|
||||
|
||||
RVMODEL_DATA_BEGIN
|
||||
|
||||
test_1_res:
|
||||
.fill 1024, 4, 0xdeadbeef
|
||||
|
||||
RVMODEL_DATA_END
|
||||
|
||||
#ifdef rvtest_mtrap_routine
|
||||
|
||||
mtrap_sigptr:
|
||||
.fill 64*(XLEN/32),4,0xdeadbeef
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef rvtest_gpr_save
|
||||
|
||||
gpr_save:
|
||||
.fill 32*(XLEN/32),4,0xdeadbeef
|
||||
|
||||
#endif
|
||||
|
||||
.align 3
|
||||
test_cases:
|
||||
|
@ -0,0 +1,560 @@
|
||||
///////////////////////////////////////////
|
||||
//
|
||||
// WALLY-TEST-LIB-64.h
|
||||
//
|
||||
// Author: Kip Macsai-Goren <kmacsaigoren@g.hmc.edu>
|
||||
//
|
||||
// Created 2022-01-30
|
||||
//
|
||||
// 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.
|
||||
///////////////////////////////////////////
|
||||
|
||||
|
||||
.macro INIT_TESTS
|
||||
|
||||
#include "model_test.h"
|
||||
#include "arch_test.h"
|
||||
RVTEST_ISA("RV64I")
|
||||
|
||||
.section .text.init
|
||||
.globl rvtest_entry_point
|
||||
rvtest_entry_point:
|
||||
RVMODEL_BOOT
|
||||
RVTEST_CODE_BEGIN
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
// Initialization Overview:
|
||||
//
|
||||
// Initialize x6 as a virtual pointer to the test results
|
||||
// Initialize x16 as a physical pointer to the test results
|
||||
// Set up stack pointer (sp = x2)
|
||||
// Set up the exception Handler, keeping the original handler in x4.
|
||||
//
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
|
||||
// address for test results
|
||||
la x6, test_1_res
|
||||
la x16, test_1_res // x16 reserved for the physical address equivalent of x6 to be used in trap handlers
|
||||
// any time either is used, both must be updated.
|
||||
|
||||
// address for stack
|
||||
la sp, top_of_stack
|
||||
|
||||
// trap handler setup
|
||||
la x1, machine_trap_handler
|
||||
csrrw x4, mtvec, x1 // x4 reserved for "default" trap handler address that needs to be restored before halting this test.
|
||||
li a0, 0
|
||||
li a1, 0
|
||||
li a2, 0 // reset trap handler inputs to zero
|
||||
|
||||
// go to first test!
|
||||
j begin_test
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
// General traps Handler
|
||||
//
|
||||
// Handles traps by branching to different behaviors based on mcause.
|
||||
//
|
||||
// Note that allowing the exception handler to change mode for a program is a huge security
|
||||
// hole, but this is an expedient way of writing tests that need different modes
|
||||
//
|
||||
// input parameters:
|
||||
//
|
||||
// a0 (x10):
|
||||
// 0: halt program with no failures
|
||||
// 1: halt program with failure in x11 = a1
|
||||
// 2: go to machine mode
|
||||
// 3: go to supervisor mode
|
||||
// 4: go to user mode
|
||||
// others: do nothing
|
||||
//
|
||||
// a1 (x11):
|
||||
// VPN for return address after changing privilege mode.
|
||||
// This should be the base VPN with no offset.
|
||||
// 0x0 : defaults to next instruction on the same page the trap was called on.
|
||||
//
|
||||
// a2 (x12):
|
||||
// Pagetype of the current address VPN before changing privilge mode
|
||||
// Used so that we can know how many bits of the adress are the offset.
|
||||
// Ignored if a1 == 0x0
|
||||
// 0: Kilopage
|
||||
// 1: Megapage
|
||||
// 2: Gigapage
|
||||
// 3: Terapage
|
||||
//
|
||||
// --------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
machine_trap_handler:
|
||||
// The processor is always in machine mode when a trap takes us here
|
||||
// save registers on stack before using
|
||||
sd x1, -8(sp)
|
||||
sd x5, -16(sp)
|
||||
|
||||
// Record trap
|
||||
csrr x1, mcause // record the mcause
|
||||
sd x1, 0(x16)
|
||||
addi x6, x6, 8
|
||||
addi x16, x16, 8 // update pointers for logging results
|
||||
|
||||
// Respond to trap based on cause
|
||||
// All interrupts should return after being logged
|
||||
li x5, 0x8000000000000000 // if msb is set, it is an interrupt
|
||||
and x5, x5, x1
|
||||
bnez x5, trapreturn // return from interrupt
|
||||
// Other trap handling is specified in the vector Table
|
||||
slli x1, x1, 3 // multiply cause by 8 to get offset in vector Table
|
||||
la x5, trap_handler_vector_table
|
||||
add x5, x5, x1 // compute address of vector in Table
|
||||
ld x5, 0(x5) // fectch address of handler from vector Table
|
||||
jr x5 // and jump to the handler
|
||||
|
||||
segfault:
|
||||
ld x5, -16(sp) // restore registers from stack before faulting
|
||||
ld x1, -8(sp)
|
||||
j terminate_test // halt program.
|
||||
|
||||
trapreturn:
|
||||
// look at the instruction to figure out whether to add 2 or 4 bytes to PC, or go to address specified in a1
|
||||
csrr x1, mepc // get the mepc
|
||||
addi x1, x1, 4 // *** should be 2 for compressed instructions, see note.
|
||||
|
||||
|
||||
// ****** KMG: the following is no longer as easy to determine. mepc gets the virtual address of the trapped instruction,
|
||||
// ******** but in the handler, we work in M mode with physical addresses
|
||||
// This means the address in mepc is suddenly pointing somewhere else.
|
||||
// to get this to work, We could either retranslate the vaddr back into a paddr (probably on the scale of difficult to intractible)
|
||||
// or we could come up with some other ingenious way to stay in M mode and see if the instruction was compressed.
|
||||
|
||||
// lw x5, 0(x1) // read the faulting instruction
|
||||
// li x1, 3 // check bottom 2 bits of instruction to see if compressed
|
||||
// and x5, x5, x1 // mask the other bits
|
||||
// beq x5, x1, trapreturn_uncompressed // if 11, the instruction is return_uncompressed
|
||||
|
||||
// trapreturn_compressed:
|
||||
// csrr x1, mepc // get the mepc again
|
||||
// addi x1, x1, 2 // add 2 to find the next instruction
|
||||
// j trapreturn_specified // and return
|
||||
|
||||
// trapreturn_uncompressed:
|
||||
// csrr x1, mepc // get the mepc again
|
||||
// addi x1, x1, 4 // add 4 to find the next instruction
|
||||
|
||||
trapreturn_specified:
|
||||
// reset the necessary pointers and registers (x1, x5, x6, and the return address going to mepc)
|
||||
// so that when we return to a new virtual address, they're all in the right spot as well.
|
||||
|
||||
beqz a1, trapreturn_finished // either update values, of go to default return address.
|
||||
|
||||
la x5, trap_return_pagetype_table
|
||||
slli a2, a2, 3
|
||||
add x5, x5, a2
|
||||
ld a2, 0(x5) // a2 = number of offset bits in current page type
|
||||
|
||||
li x5, 1
|
||||
sll x5, x5, a2
|
||||
addi x5, x5, -1 // x5 = mask bits for offset into current pagetype
|
||||
|
||||
// reset the top of the stack, x1
|
||||
ld x7, -8(sp)
|
||||
and x7, x5, x7 // x7 = offset for x1
|
||||
add x7, x7, a1 // x7 = new address for x1
|
||||
sd x7, -8(sp)
|
||||
|
||||
// reset the second spot in the stack, x5
|
||||
ld x7, -16(sp)
|
||||
and x7, x5, x7 // x7 = offset for x5
|
||||
add x7, x7, a1 // x7 = new address for x5
|
||||
sd x7, -16(sp)
|
||||
|
||||
// reset x6, the pointer for the virtual address of the output of the tests
|
||||
and x7, x5, x6 // x7 = offset for x6
|
||||
add x6, x7, a1 // x6 = new address for the result pointer
|
||||
|
||||
// set return address, stored temporarily in x1, to the next instruction, but in the new virtual page.
|
||||
and x1, x5, x1 // x1 = offset for the return address
|
||||
add x1, x1, a1 // x1 = new return address.
|
||||
|
||||
li a1, 0
|
||||
li a2, 0 // reset trapreturn inputs to the trap handler
|
||||
|
||||
trapreturn_finished:
|
||||
csrw mepc, x1 // update the mepc with address of next instruction
|
||||
ld x5, -16(sp) // restore registers from stack before returning
|
||||
ld x1, -8(sp)
|
||||
mret // return from trap
|
||||
|
||||
ecallhandler:
|
||||
// Check input parameter a0. encoding above.
|
||||
// *** ASSUMES: that this trap is being handled in machine mode. in other words, that nothing odd has been written to the medeleg or mideleg csrs.
|
||||
li x5, 2 // case 2: change to machine mode
|
||||
beq a0, x5, ecallhandler_changetomachinemode
|
||||
li x5, 3 // case 3: change to supervisor mode
|
||||
beq a0, x5, ecallhandler_changetosupervisormode
|
||||
li x5, 4 // case 4: change to user mode
|
||||
beq a0, x5, ecallhandler_changetousermode
|
||||
// unsupported ecalls should segfault
|
||||
j segfault
|
||||
|
||||
ecallhandler_changetomachinemode:
|
||||
// Force mstatus.MPP (bits 12:11) to 11 to enter machine mode after mret
|
||||
li x1, 0b1100000000000
|
||||
csrs mstatus, x1
|
||||
j trapreturn
|
||||
|
||||
ecallhandler_changetosupervisormode:
|
||||
// Force mstatus.MPP (bits 12:11) to 01 to enter supervisor mode after mret
|
||||
li x1, 0b1100000000000
|
||||
csrc mstatus, x1
|
||||
li x1, 0b0100000000000
|
||||
csrs mstatus, x1
|
||||
j trapreturn
|
||||
|
||||
ecallhandler_changetousermode:
|
||||
// Force mstatus.MPP (bits 12:11) to 00 to enter user mode after mret
|
||||
li x1, 0b1100000000000
|
||||
csrc mstatus, x1
|
||||
j trapreturn
|
||||
|
||||
instrfault:
|
||||
ld x1, -8(sp) // load return address int x1 (the address AFTER the jal into faulting page)
|
||||
j trapreturn_finished // puts x1 into mepc, restores stack and returns to program (outside of faulting page)
|
||||
|
||||
illegalinstr:
|
||||
j trapreturn // return to the code after recording the mcause
|
||||
|
||||
accessfault:
|
||||
// *** What do I have to do here?
|
||||
j trapreturn
|
||||
|
||||
// Table of trap behavior
|
||||
// lists what to do on each exception (not interrupts)
|
||||
// unexpected exceptions should cause segfaults for easy detection
|
||||
// Expected exceptions should increment the EPC to the next instruction and return
|
||||
|
||||
.align 3 // aligns this data table to an 8 byte boundary
|
||||
trap_handler_vector_table:
|
||||
.8byte segfault // 0: instruction address misaligned
|
||||
.8byte instrfault // 1: instruction access fault
|
||||
.8byte illegalinstr // 2: illegal instruction
|
||||
.8byte segfault // 3: breakpoint
|
||||
.8byte segfault // 4: load address misaligned
|
||||
.8byte accessfault // 5: load access fault
|
||||
.8byte segfault // 6: store address misaligned
|
||||
.8byte accessfault // 7: store access fault
|
||||
.8byte ecallhandler // 8: ecall from U-mode
|
||||
.8byte ecallhandler // 9: ecall from S-mode
|
||||
.8byte segfault // 10: reserved
|
||||
.8byte ecallhandler // 11: ecall from M-mode
|
||||
.8byte instrfault // 12: instruction page fault
|
||||
.8byte trapreturn // 13: load page fault
|
||||
.8byte segfault // 14: reserved
|
||||
.8byte trapreturn // 15: store page fault
|
||||
|
||||
.align 3
|
||||
trap_return_pagetype_table:
|
||||
.8byte 0xC // 0: kilopage has 12 offset bits
|
||||
.8byte 0x15 // 1: megapage has 21 offset bits
|
||||
.8byte 0x1E // 2: gigapage has 30 offset bits
|
||||
.8byte 0x27 // 3: terapage has 39 offset bits
|
||||
|
||||
begin_test: // label here to jump to so we dont go through the trap handler before starting the test
|
||||
|
||||
.endm // Ends the initialization macro that set up the begginnning of the tests and the trap handler.
|
||||
|
||||
|
||||
// Test Summary table!
|
||||
|
||||
// Test Name : Description : Fault output value : Normal output values
|
||||
// ---------------------:-------------------------------------------:-------------------------------:------------------------------------------------------
|
||||
// write64_test : Write 64 bits to address : 0x6, 0x7, or 0xf : None
|
||||
// write32_test : Write 32 bits to address : 0x6, 0x7, or 0xf : None
|
||||
// write16_test : Write 16 bits to address : 0x6, 0x7, or 0xf : None
|
||||
// write08_test : Write 8 bits to address : 0x6, 0x7, or 0xf : None
|
||||
// read64_test : Read 64 bits from address : 0x4, 0x5, or 0xd, then 0xbad : readvalue in hex
|
||||
// read32_test : Read 32 bitsfrom address : 0x4, 0x5, or 0xd, then 0xbad : readvalue in hex
|
||||
// read16_test : Read 16 bitsfrom address : 0x4, 0x5, or 0xd, then 0xbad : readvalue in hex
|
||||
// read08_test : Read 8 bitsfrom address : 0x4, 0x5, or 0xd, then 0xbad : readvalue in hex
|
||||
// executable_test : test executable on virtual page : 0x0, 0x1, or 0xc, then 0xbad : value of x7 modified by exectuion code (usually 0x111)
|
||||
// terminate_test : terminate tests : mcause value for fault : from M 0xb, from S 0x9, from U 0x8
|
||||
// goto_baremetal : satp.MODE = bare metal : None : None
|
||||
// goto_sv39 : satp.MODE = sv39 : None : None
|
||||
// goto_sv48 : satp.MODE = sv48 : None : None
|
||||
// goto_m_mode : go to mahcine mode : mcause value for fault : from M 0xb, from S 0x9, from U 0x8
|
||||
// goto_s_mode : go to supervisor mode : mcause value for fault : from M 0xb, from S 0x9, from U 0x8
|
||||
// goto_u_mode : go to user mode : mcause value for fault : from M 0xb, from S 0x9, from U 0x8
|
||||
// write_csr : write to specified CSR : CSR value before test attempt : value written to CSR
|
||||
// read_csr : read from specified CSR : *** None? Mcause or fault? : value read back from CSR
|
||||
|
||||
|
||||
// *** TESTS TO ADD: execute inline, read unknown value out, read CSR unknown value
|
||||
|
||||
.macro write64_test ADDR VAL
|
||||
// attempt to write VAL to ADDR
|
||||
// Success outputs:
|
||||
// None
|
||||
// Fault outputs:
|
||||
// 0x6: misaligned address
|
||||
// 0x7: access fault
|
||||
// 0xf: page fault
|
||||
li x29, \VAL
|
||||
li x30, \ADDR
|
||||
sd x29, 0(x30)
|
||||
.endm
|
||||
|
||||
.macro write32_test ADDR VAL
|
||||
// all write tests have the same description/outputs as write64
|
||||
li x29, \VAL
|
||||
li x30, \ADDR
|
||||
sw x29, 0(x30)
|
||||
.endm
|
||||
|
||||
.macro write16_test ADDR VAL
|
||||
// all write tests have the same description/outputs as write64
|
||||
li x29, \VAL
|
||||
li x30, \ADDR
|
||||
sh x29, 0(x30)
|
||||
.endm
|
||||
|
||||
.macro write08_test ADDR VAL
|
||||
// all write tests have the same description/outputs as write64
|
||||
li x29, \VAL
|
||||
li x30, \ADDR
|
||||
sb x29, 0(x30)
|
||||
.endm
|
||||
|
||||
.macro read64_test ADDR
|
||||
// Attempt read at ADDR. Write the value read out to the output *** Consider adding specific test for reading a non known value
|
||||
// Success outputs:
|
||||
// value read out from ADDR
|
||||
// Fault outputs:
|
||||
// One of the following followed by 0xBAD
|
||||
// 0x4: misaligned address
|
||||
// 0x5: access fault
|
||||
// 0xD: page fault
|
||||
li x7, 0xBAD // bad value that will be overwritten on good reads.
|
||||
li x29, \ADDR
|
||||
ld x7, 0(x29)
|
||||
sd x7, 0(x6)
|
||||
addi x6, x6, 8
|
||||
addi x16, x16, 8
|
||||
.endm
|
||||
|
||||
.macro read32_test ADDR
|
||||
// All reads have the same description/outputs as read64.
|
||||
// They will store the sign extended value of what was read out at ADDR
|
||||
li x7, 0xBAD // bad value that will be overwritten on good reads.
|
||||
li x29, \ADDR
|
||||
lw x7, 0(x29)
|
||||
sd x7, 0(x6)
|
||||
addi x6, x6, 8
|
||||
addi x16, x16, 8
|
||||
.endm
|
||||
|
||||
.macro read16_test ADDR
|
||||
// All reads have the same description/outputs as read64.
|
||||
// They will store the sign extended value of what was read out at ADDR
|
||||
li x7, 0xBAD // bad value that will be overwritten on good reads.
|
||||
li x29, \ADDR
|
||||
lh x7, 0(x29)
|
||||
sd x7, 0(x6)
|
||||
addi x6, x6, 8
|
||||
addi x16, x16, 8
|
||||
.endm
|
||||
|
||||
.macro read08_test ADDR
|
||||
// All reads have the same description/outputs as read64.
|
||||
// They will store the sign extended value of what was read out at ADDR
|
||||
li x7, 0xBAD // bad value that will be overwritten on good reads.
|
||||
li x29, \ADDR
|
||||
lb x7, 0(x29)
|
||||
sd x7, 0(x6)
|
||||
addi x6, x6, 8
|
||||
addi x16, x16, 8
|
||||
.endm
|
||||
|
||||
// These goto_x_mode tests all involve invoking the trap handler,
|
||||
// So their outputs are inevitably:
|
||||
// 0x8: test called from U mode
|
||||
// 0x9: test called from S mode
|
||||
// 0xB: test called from M mode
|
||||
// they generally do not fault or cause issues as long as these modes are enabled
|
||||
// *** add functionality to check if modes are enabled before jumping? maybe cause a fault if not?
|
||||
|
||||
.macro goto_m_mode RETURN_VPN RETURN_PAGETYPE
|
||||
li a0, 2 // determine trap handler behavior (go to supervisor mode)
|
||||
li a1, \RETURN_VPN // return VPN
|
||||
li a2, \RETURN_PAGETYPE // return page types
|
||||
ecall // writes mcause to the output.
|
||||
// now in S mode
|
||||
.endm
|
||||
|
||||
.macro goto_s_mode RETURN_VPN RETURN_PAGETYPE
|
||||
li a0, 3 // determine trap handler behavior (go to supervisor mode)
|
||||
li a1, \RETURN_VPN // return VPN
|
||||
li a2, \RETURN_PAGETYPE // return page types
|
||||
ecall // writes mcause to the output.
|
||||
// now in S mode
|
||||
.endm
|
||||
|
||||
.macro goto_u_mode RETURN_VPN RETURN_PAGETYPE
|
||||
li a0, 4 // determine trap handler behavior (go to supervisor mode)
|
||||
li a1, \RETURN_VPN // return VPN
|
||||
li a2, \RETURN_PAGETYPE // return page types
|
||||
ecall // writes mcause to the output.
|
||||
// now in S mode
|
||||
.endm
|
||||
|
||||
// These tests change virtual memory settings, turning it on/off and changing between types.
|
||||
// They don't have outputs as any error with turning on virtual memory should reveal itself in the tests *** Consider changing this policy?
|
||||
|
||||
.macro goto_baremetal
|
||||
// Turn translation off
|
||||
li x7, 0 // satp.MODE value for bare metal (0)
|
||||
slli x7, x7, 60
|
||||
li x28, 0x8000D // Base Pagetable physical page number, satp.PPN field. *** add option for different pagetable location
|
||||
add x7, x7, x28
|
||||
csrw satp, x7
|
||||
sfence.vma x0, x0 // *** flushes global pte's as well
|
||||
.endm
|
||||
|
||||
.macro goto_sv39
|
||||
// Turn on sv39 virtual memory
|
||||
li x7, 8 // satp.MODE value for Sv39 (8)
|
||||
slli x7, x7, 60
|
||||
li x28, 0x8000D // Base Pagetable physical page number, satp.PPN field. *** add option for different pagetable location
|
||||
add x7, x7, x28
|
||||
csrw satp, x7
|
||||
sfence.vma x0, x0 // *** flushes global pte's as well
|
||||
.endm
|
||||
|
||||
.macro goto_sv48
|
||||
// Turn on sv48 virtual memory
|
||||
li x7, 9 // satp.MODE value for Sv39 (8)
|
||||
slli x7, x7, 60
|
||||
li x28, 0x8000D // Base Pagetable physical page number, satp.PPN field. *** add option for different pagetable location
|
||||
add x7, x7, x28
|
||||
csrw satp, x7
|
||||
sfence.vma x0, x0 // *** flushes global pte's as well
|
||||
.endm
|
||||
|
||||
.macro write_csr CSR VAL
|
||||
// attempt to write CSR with VAL *** ASSUMES RW access to CSR in whatever privilege mode is running
|
||||
// Success outputs:
|
||||
// value read back out from CSR after writing
|
||||
// Fault outputs:
|
||||
// The previous CSR value before write attempt
|
||||
// *** Is there an associated mstatus? maybe 0x2???
|
||||
li x29, \VAL
|
||||
csrw \CSR\(), x29
|
||||
csrr x30, \CSR
|
||||
sd x30, 0(x6)
|
||||
addi x6, x6, 8
|
||||
addi x16, x16, 8
|
||||
.endm
|
||||
|
||||
.macro csr_r_access CSR
|
||||
// verify that a csr is accessible to read but not to write
|
||||
// Success outputs:
|
||||
// 0x2, then
|
||||
// 0x11 *** consider changing to something more meaningful
|
||||
// Fault outputs:
|
||||
// 0xBAD *** consider changing this one as well. in general, do we need the branching if it hould cause an illegal instruction fault?
|
||||
csrr x29, \CSR
|
||||
csrwi \CSR\(), 0xA // Attempt to write a 'random' value to the CSR
|
||||
csrr x30, \CSR
|
||||
bne x30, x29, 1f // 1f represents write_access
|
||||
li x30, 0x11 // Write succeeded, violating read only permissions.
|
||||
j 2f // j r_access_end
|
||||
1: // w_access (test failed)
|
||||
li x30, 0xBAD
|
||||
2: // r_access end
|
||||
sd x30, 0(x6)
|
||||
addi x6, x6, 8
|
||||
addi x16, x16, 8
|
||||
.endm
|
||||
|
||||
.macro execute_at_address ADDR
|
||||
// Execute the code already written to ADDR, returning the value in x7.
|
||||
// *** Note: this test itself doesn't write the code to ADDR because it might be callled at a point where we dont have write access to ADDR
|
||||
// Assumes the code modifies x7, usually to become 0x111.
|
||||
// Sample code: 0x11100393 (li x7, 0x111), 0x00008067 (ret)
|
||||
// Success outputs:
|
||||
// modified value of x7. (0x111 if you use the sample code)
|
||||
// Fault outputs:
|
||||
// One of the following followed by 0xBAD
|
||||
// 0x0: misaligned address
|
||||
// 0x1: access fault
|
||||
// 0xC: page fault
|
||||
fence.i // forces caches and main memory to sync so execution code written to ADDR can run.
|
||||
li x7, 0xBAD
|
||||
li x28, \ADDR
|
||||
jalr x28 // jump to executable test code
|
||||
sd x7, 0(x6)
|
||||
addi x6, x6, 8
|
||||
addi x16, x16, 8
|
||||
.endm
|
||||
|
||||
.macro END_TESTS
|
||||
// invokes one final ecall to return to machine mode then terminates this program, so the output is
|
||||
// 0x8: termination called from U mode
|
||||
// 0x9: termination called from S mode
|
||||
// 0xB: termination called from M mode
|
||||
|
||||
terminate_test:
|
||||
|
||||
li a0, 2 // Trap handler behavior (go to machine mode)
|
||||
ecall // writes mcause to the output.
|
||||
csrw mtvec, x4 // restore original trap handler to halt program
|
||||
|
||||
RVTEST_CODE_END
|
||||
RVMODEL_HALT
|
||||
|
||||
RVTEST_DATA_BEGIN
|
||||
.align 4
|
||||
rvtest_data:
|
||||
.word 0xbabecafe
|
||||
RVTEST_DATA_END
|
||||
|
||||
.align 3 // align stack to 8 byte boundary
|
||||
bottom_of_stack:
|
||||
.fill 1024, 4, 0xdeadbeef
|
||||
top_of_stack:
|
||||
|
||||
|
||||
RVMODEL_DATA_BEGIN
|
||||
|
||||
test_1_res:
|
||||
.fill 1024, 4, 0xdeadbeef
|
||||
|
||||
RVMODEL_DATA_END
|
||||
|
||||
#ifdef rvtest_mtrap_routine
|
||||
|
||||
mtrap_sigptr:
|
||||
.fill 64*(XLEN/32),4,0xdeadbeef
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef rvtest_gpr_save
|
||||
|
||||
gpr_save:
|
||||
.fill 32*(XLEN/32),4,0xdeadbeef
|
||||
|
||||
#endif
|
||||
|
||||
.endm // ends the macro that terminates this test program.
|
@ -0,0 +1,37 @@
|
||||
///////////////////////////////////////////
|
||||
//
|
||||
// WALLY-MMU
|
||||
//
|
||||
// Author: Kip Macsai-Goren <kmacsaigoren@g.hmc.edu>
|
||||
//
|
||||
// Created 2022-01-25
|
||||
//
|
||||
// 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-TEST-MACROS-64.h"
|
||||
|
||||
INIT_TESTS
|
||||
|
||||
// Test 5.2.3.1: tersting Read-only access to Machine info CSRs
|
||||
|
||||
csr_r_access mvendorid
|
||||
csr_r_access marchid
|
||||
csr_r_access mimpid
|
||||
csr_r_access mhartid
|
||||
# csr_r_access mconfigptr # Unimplemented in spike as of 31 Jan 22
|
||||
|
||||
|
||||
END_TESTS
|
Loading…
Reference in New Issue
Block a user