Merge branch 'main' of github.com:davidharrishmc/riscv-wally into main

This commit is contained in:
Ross Thompson 2022-02-01 10:50:38 -06:00
commit a9b4f9b1e7
50 changed files with 4520 additions and 2339 deletions

1
.gitignore vendored
View File

@ -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
View File

@ -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

View File

@ -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.

View File

@ -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[]) {

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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: Cant 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);

View 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

View 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
View 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

View File

@ -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
View 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

View File

@ -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

View 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

View File

@ -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;

View File

@ -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;

View File

@ -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)

View File

@ -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

View File

@ -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"};

View File

@ -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
View 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
View 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
View 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
View 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

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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:

View File

@ -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:

View File

@ -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 \

View File

@ -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.

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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:

View File

@ -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:

View File

@ -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.

View File

@ -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