forked from Github_Repos/cvw
Merge branch 'main' of https://github.com/davidharrishmc/riscv-wally into main
This commit is contained in:
commit
cd7d403f92
4
.gitignore
vendored
4
.gitignore
vendored
@ -16,8 +16,8 @@ wlft*
|
||||
/imperas-riscv-tests/FunctionRadix.addr
|
||||
/imperas-riscv-tests/ProgramMap.txt
|
||||
/imperas-riscv-tests/logs
|
||||
/wally-pipelined/busybear-testgen/gdbcombined.txt
|
||||
/wally-pipelined/busybear-testgen/first10.txt
|
||||
/wally-pipelined/linux-testgen/qemu_output.txt
|
||||
/wally-pipelined/linux-testgen/qemu_in_gdb_format.txt
|
||||
*.o
|
||||
*.d
|
||||
testsBP/*/*/*.elf*
|
||||
|
@ -286,17 +286,17 @@ MAIN_RETURN_TYPE main(int argc, char *argv[]) {
|
||||
results[i].err=0;
|
||||
if ((results[i].execs & ID_LIST) &&
|
||||
(results[i].crclist!=list_known_crc[known_id])) {
|
||||
ee_printf("[%u]ERROR! list crc 0x%04x - should be 0x%04x\n,i,results[i].crclist,list_known_crc[known_id]");
|
||||
ee_printf("[%u]ERROR! list crc 0x%04x - should be 0x%04x\n",i,results[i].crclist,list_known_crc[known_id]);
|
||||
results[i].err++;
|
||||
}
|
||||
if ((results[i].execs & ID_MATRIX) &&
|
||||
(results[i].crcmatrix!=matrix_known_crc[known_id])) {
|
||||
ee_printf("[%u]ERROR! matrix crc 0x%04x - should be 0x%04x\n,i,results[i].crcmatrix,matrix_known_crc[known_id]");
|
||||
ee_printf("[%u]ERROR! matrix crc 0x%04x - should be 0x%04x\n",i,results[i].crcmatrix,matrix_known_crc[known_id]);
|
||||
results[i].err++;
|
||||
}
|
||||
if ((results[i].execs & ID_STATE) &&
|
||||
(results[i].crcstate!=state_known_crc[known_id])) {
|
||||
ee_printf("[%u]ERROR! state crc 0x%04x - should be 0x%04x\n,i,results[i].crcstate,state_known_crc[known_id]");
|
||||
ee_printf("[%u]ERROR! state crc 0x%04x - should be 0x%04x\n",i,results[i].crcstate,state_known_crc[known_id]);
|
||||
results[i].err++;
|
||||
}
|
||||
total_errors+=results[i].err;
|
||||
@ -305,55 +305,55 @@ MAIN_RETURN_TYPE main(int argc, char *argv[]) {
|
||||
total_errors+=check_data_types();
|
||||
/* and report results */
|
||||
//ee_printf("CoreMark Size : %lu\n", (long unsigned) results[0].size);
|
||||
ee_printf("CoreMark Size : %lu\n, (long unsigned) results[0].size");
|
||||
ee_printf("Total ticks : %lu\n, (long unsigned) total_time");
|
||||
ee_printf("CoreMark Size : %lu\n", (long unsigned) results[0].size);
|
||||
ee_printf("Total ticks : %lu\n", (long unsigned) total_time);
|
||||
#if HAS_FLOAT
|
||||
ee_printf("Total time (secs): %f\n,time_in_secs(total_time)");
|
||||
ee_printf("Total time (secs): %f\n",time_in_secs(total_time));
|
||||
if (time_in_secs(total_time) > 0)
|
||||
ee_printf("Iterations/Sec : %f\n,default_num_contexts*results[0].iterations/time_in_secs(total_time)");
|
||||
ee_printf("Iterations/Sec : %f\n",default_num_contexts*results[0].iterations/time_in_secs(total_time));
|
||||
#else
|
||||
ee_printf("Total time (secs): %d\n,time_in_secs(total_time)");
|
||||
if (time_in_secs(total_time) > 0)
|
||||
ee_printf("Iterations/Sec : %d\n,default_num_contexts*results[0].iterations/time_in_secs(total_time)");
|
||||
ee_printf("Iterations/Sec : %d\n",default_num_contexts*results[0].iterations/time_in_secs(total_time));
|
||||
#endif
|
||||
if (time_in_secs(total_time) < 10) {
|
||||
ee_printf("ERROR! Must execute for at least 10 secs for a valid result!\n");
|
||||
total_errors++;
|
||||
}
|
||||
|
||||
ee_printf("Iterations : %lu\n, (long unsigned) default_num_contexts*results[0].iterations");
|
||||
ee_printf("Compiler version : %s\n,COMPILER_VERSION");
|
||||
ee_printf("Compiler flags : %s\n,COMPILER_FLAGS");
|
||||
ee_printf("Iterations : %lu\n", (long unsigned) default_num_contexts*results[0].iterations);
|
||||
ee_printf("Compiler version : %s\n",COMPILER_VERSION);
|
||||
ee_printf("Compiler flags : %s\n",COMPILER_FLAGS);
|
||||
#if (MULTITHREAD>1)
|
||||
ee_printf("Parallel %s : %d\n,PARALLEL_METHOD,default_num_contexts");
|
||||
ee_printf("Parallel %s : %d\n",PARALLEL_METHOD,default_num_contexts);
|
||||
#endif
|
||||
ee_printf("Memory location : %s\n,MEM_LOCATION");
|
||||
ee_printf("Memory location : %s\n",MEM_LOCATION);
|
||||
/* output for verification */
|
||||
ee_printf("seedcrc : 0x%04x\n,seedcrc");
|
||||
ee_printf("seedcrc : 0x%04x\n",seedcrc);
|
||||
if (results[0].execs & ID_LIST)
|
||||
for (i=0 ; i<default_num_contexts; i++)
|
||||
ee_printf("[%d]crclist : 0x%04x\n,i,results[i].crclist");
|
||||
ee_printf("[%d]crclist : 0x%04x\n",i,results[i].crclist);
|
||||
if (results[0].execs & ID_MATRIX)
|
||||
for (i=0 ; i<default_num_contexts; i++)
|
||||
ee_printf("[%d]crcmatrix : 0x%04x\n,i,results[i].crcmatrix");
|
||||
ee_printf("[%d]crcmatrix : 0x%04x\n",i,results[i].crcmatrix);
|
||||
if (results[0].execs & ID_STATE)
|
||||
for (i=0 ; i<default_num_contexts; i++)
|
||||
ee_printf("[%d]crcstate : 0x%04x\n,i,results[i].crcstate");
|
||||
ee_printf("[%d]crcstate : 0x%04x\n",i,results[i].crcstate);
|
||||
for (i=0 ; i<default_num_contexts; i++)
|
||||
ee_printf("[%d]crcfinal : 0x%04x\n,i,results[i].crc");
|
||||
ee_printf("[%d]crcfinal : 0x%04x\"n",i,results[i].crc);
|
||||
if (total_errors==0) {
|
||||
ee_printf("Correct operation validated. See README.md for run and reporting rules.\n");
|
||||
#if HAS_FLOAT
|
||||
if (known_id==3) {
|
||||
ee_printf("CoreMark 1.0 : %f / %s %s,default_num_contexts*results[0].iterations/time_in_secs(total_time),COMPILER_VERSION,COMPILER_FLAGS");
|
||||
ee_printf("CoreMark 1.0 : %f / %s %s",default_num_contexts*results[0].iterations/time_in_secs(total_time),COMPILER_VERSION,COMPILER_FLAGS);
|
||||
#if defined(MEM_LOCATION) && !defined(MEM_LOCATION_UNSPEC)
|
||||
ee_printf(" / %s,MEM_LOCATION");
|
||||
ee_printf(" / %s",MEM_LOCATION);
|
||||
#else
|
||||
ee_printf(" / %s,mem_name[MEM_METHOD]");
|
||||
ee_printf(" / %s",mem_name[MEM_METHOD]);
|
||||
#endif
|
||||
|
||||
#if (MULTITHREAD>1)
|
||||
ee_printf(" / %d:%s,default_num_contexts,PARALLEL_METHOD");
|
||||
ee_printf(" / %d:%s",default_num_contexts,PARALLEL_METHOD);
|
||||
#endif
|
||||
ee_printf("\n");
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
//////////////////////////////////////////
|
||||
// busybear-config.vh
|
||||
// wally-config.vh
|
||||
//
|
||||
// Written: David_Harris@hmc.edu 4 January 2021
|
||||
// Modified:
|
||||
@ -61,22 +61,27 @@
|
||||
// Peripheral Addresses
|
||||
// Peripheral memory space extends from BASE to BASE+RANGE
|
||||
// Range should be a thermometer code with 0's in the upper bits and 1s in the lower bits
|
||||
`define BOOTTIM_SUPPORTED 1'b1
|
||||
`define BOOTTIM_BASE 32'h00000000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder
|
||||
`define BOOTTIM_RANGE 32'h00003FFF
|
||||
//`define BOOTTIM_BASE 32'h00001000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder
|
||||
//`define BOOTTIM_RANGE 32'h00000FFF
|
||||
`define TIM_SUPPORTED 1'b1
|
||||
`define TIM_BASE 32'h80000000
|
||||
`define TIM_RANGE 32'h07FFFFFF
|
||||
`define CLINT_SUPPORTED 1'b1
|
||||
`define CLINT_BASE 32'h02000000
|
||||
`define CLINT_RANGE 32'h0000FFFF
|
||||
`define GPIO_SUPPORTED 1'b1
|
||||
`define GPIO_BASE 32'h10012000
|
||||
`define GPIO_RANGE 32'h000000FF
|
||||
`define UART_SUPPORTED 1'b1
|
||||
`define UART_BASE 32'h10000000
|
||||
`define UART_RANGE 32'h00000007
|
||||
`define PLIC_SUPPORTED 1'b1
|
||||
`define PLIC_BASE 32'h0C000000
|
||||
`define PLIC_RANGE 32'h03FFFFFF
|
||||
|
||||
`define BOOTTIMBASE 32'h00000000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder
|
||||
`define BOOTTIMRANGE 32'h00003FFF
|
||||
`define CLINTBASE 32'h02000000
|
||||
`define CLINTRANGE 32'h0000FFFF
|
||||
`define PLICBASE 32'h0C000000
|
||||
`define PLICRANGE 32'h03FFFFFF
|
||||
`define UARTBASE 32'h10000000
|
||||
`define UARTRANGE 32'h00000007
|
||||
`define VBD0BASE 32'h10001000
|
||||
`define VBD0RANGE 32'h000001FF
|
||||
// differing from Imperas' OVPSim by not having a VND0
|
||||
`define GPIOBASE 32'h20000000
|
||||
`define GPIORANGE 32'h000000FF
|
||||
`define TIMBASE 32'h80000000
|
||||
`define TIMRANGE 32'h07FFFFFF
|
||||
// Bus Interface width
|
||||
`define AHBW 64
|
||||
|
||||
|
@ -62,21 +62,27 @@
|
||||
// Peripheral memory space extends from BASE to BASE+RANGE
|
||||
// Range should be a thermometer code with 0's in the upper bits and 1s in the lower bits
|
||||
|
||||
`define BOOTTIMBASE 32'h00000000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder
|
||||
`define BOOTTIMRANGE 32'h00003FFF
|
||||
`define CLINTBASE 32'h02000000
|
||||
`define CLINTRANGE 32'h0000FFFF
|
||||
`define PLICBASE 32'h0C000000
|
||||
`define PLICRANGE 32'h03FFFFFF
|
||||
`define UARTBASE 32'h10000000
|
||||
`define UARTRANGE 32'h00000007
|
||||
`define VBD0BASE 32'h10001000
|
||||
`define VBD0RANGE 32'h000001FF
|
||||
// differing from Imperas' OVPSim by not having a VND0
|
||||
`define GPIOBASE 32'h20000000
|
||||
`define GPIORANGE 32'h000000FF
|
||||
`define TIMBASE 32'h80000000
|
||||
`define TIMRANGE 32'h07FFFFFF
|
||||
`define BOOTTIM_SUPPORTED 1'b1
|
||||
`define BOOTTIM_BASE 32'h00000000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder
|
||||
`define BOOTTIM_RANGE 32'h00003FFF
|
||||
//`define BOOTTIM_BASE 32'h00001000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder
|
||||
//`define BOOTTIM_RANGE 32'h00000FFF
|
||||
`define TIM_SUPPORTED 1'b1
|
||||
`define TIM_BASE 32'h80000000
|
||||
`define TIM_RANGE 32'h07FFFFFF
|
||||
`define CLINT_SUPPORTED 1'b1
|
||||
`define CLINT_BASE 32'h02000000
|
||||
`define CLINT_RANGE 32'h0000FFFF
|
||||
`define GPIO_SUPPORTED 1'b1
|
||||
`define GPIO_BASE 32'h10012000
|
||||
`define GPIO_RANGE 32'h000000FF
|
||||
`define UART_SUPPORTED 1'b1
|
||||
`define UART_BASE 32'h10000000
|
||||
`define UART_RANGE 32'h00000007
|
||||
`define PLIC_SUPPORTED 1'b1
|
||||
`define PLIC_BASE 32'h0C000000
|
||||
`define PLIC_RANGE 32'h03FFFFFF
|
||||
|
||||
// Bus Interface width
|
||||
`define AHBW 64
|
||||
|
||||
|
@ -54,14 +54,26 @@
|
||||
// Peripheral memory space extends from BASE to BASE+RANGE
|
||||
// Range should be a thermometer code with 0's in the upper bits and 1s in the lower bits
|
||||
|
||||
`define TIMBASE 32'h80000000
|
||||
`define TIMRANGE 32'h0007FFFF
|
||||
`define CLINTBASE 32'h02000000
|
||||
`define CLINTRANGE 32'h0000FFFF
|
||||
`define GPIOBASE 32'h10012000
|
||||
`define GPIORANGE 32'h000000FF
|
||||
`define UARTBASE 32'h10000000
|
||||
`define UARTRANGE 32'h00000007
|
||||
`define BOOTTIM_SUPPORTED 1'b1
|
||||
`define BOOTTIM_BASE 32'h00000000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder
|
||||
`define BOOTTIM_RANGE 32'h00003FFF
|
||||
//`define BOOTTIM_BASE 32'h00001000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder
|
||||
//`define BOOTTIM_RANGE 32'h00000FFF
|
||||
`define TIM_SUPPORTED 1'b1
|
||||
`define TIM_BASE 32'h80000000
|
||||
`define TIM_RANGE 32'h07FFFFFF
|
||||
`define CLINT_SUPPORTED 1'b1
|
||||
`define CLINT_BASE 32'h02000000
|
||||
`define CLINT_RANGE 32'h0000FFFF
|
||||
`define GPIO_SUPPORTED 1'b1
|
||||
`define GPIO_BASE 32'h10012000
|
||||
`define GPIO_RANGE 32'h000000FF
|
||||
`define UART_SUPPORTED 1'b1
|
||||
`define UART_BASE 32'h10000000
|
||||
`define UART_RANGE 32'h00000007
|
||||
`define PLIC_SUPPORTED 1'b1
|
||||
`define PLIC_BASE 32'h0C000000
|
||||
`define PLIC_RANGE 32'h03FFFFFF
|
||||
|
||||
// Test modes
|
||||
|
||||
|
@ -62,18 +62,26 @@
|
||||
// Peripheral memory space extends from BASE to BASE+RANGE
|
||||
// Range should be a thermometer code with 0's in the upper bits and 1s in the lower bits
|
||||
|
||||
`define BOOTTIMBASE 32'h00000000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder
|
||||
`define BOOTTIMRANGE 32'h00003FFF
|
||||
`define TIMBASE 32'h00000000
|
||||
`define TIMRANGE 32'hFFFFFFFF
|
||||
`define CLINTBASE 32'h02000000
|
||||
`define CLINTRANGE 32'h0000FFFF
|
||||
`define GPIOBASE 32'h10012000
|
||||
`define GPIORANGE 32'h000000FF
|
||||
`define UARTBASE 32'h10000000
|
||||
`define UARTRANGE 32'h00000007
|
||||
`define PLICBASE 32'h0C000000
|
||||
`define PLICRANGE 32'h03FFFFFF
|
||||
`define BOOTTIM_SUPPORTED 1'b1
|
||||
`define BOOTTIM_BASE 32'h00000000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder
|
||||
`define BOOTTIM_RANGE 32'h00003FFF
|
||||
//`define BOOTTIM_BASE 32'h00001000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder
|
||||
//`define BOOTTIM_RANGE 32'h00000FFF
|
||||
`define TIM_SUPPORTED 1'b1
|
||||
`define TIM_BASE 32'h80000000
|
||||
`define TIM_RANGE 32'h07FFFFFF
|
||||
`define CLINT_SUPPORTED 1'b1
|
||||
`define CLINT_BASE 32'h02000000
|
||||
`define CLINT_RANGE 32'h0000FFFF
|
||||
`define GPIO_SUPPORTED 1'b1
|
||||
`define GPIO_BASE 32'h10012000
|
||||
`define GPIO_RANGE 32'h000000FF
|
||||
`define UART_SUPPORTED 1'b1
|
||||
`define UART_BASE 32'h10000000
|
||||
`define UART_RANGE 32'h00000007
|
||||
`define PLIC_SUPPORTED 1'b1
|
||||
`define PLIC_BASE 32'h0C000000
|
||||
`define PLIC_RANGE 32'h03FFFFFF
|
||||
|
||||
// Test modes
|
||||
|
||||
|
@ -52,6 +52,9 @@
|
||||
`define ITLB_ENTRY_BITS 5
|
||||
`define DTLB_ENTRY_BITS 5
|
||||
|
||||
// Legal number of PMP entries are 0, 16, or 64
|
||||
`define PMP_ENTRIES 16
|
||||
|
||||
// Address space
|
||||
`define RESET_VECTOR 64'h0000000080000000
|
||||
|
||||
@ -62,18 +65,26 @@
|
||||
// Peripheral memory space extends from BASE to BASE+RANGE
|
||||
// Range should be a thermometer code with 0's in the upper bits and 1s in the lower bits
|
||||
|
||||
`define BOOTTIMBASE 32'h00000000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder
|
||||
`define BOOTTIMRANGE 32'h00003FFF
|
||||
`define TIMBASE 32'h80000000
|
||||
`define TIMRANGE 32'h000FFFFF
|
||||
`define CLINTBASE 32'h02000000
|
||||
`define CLINTRANGE 32'h0000FFFF
|
||||
`define GPIOBASE 32'h10012000
|
||||
`define GPIORANGE 32'h000000FF
|
||||
`define UARTBASE 32'h10000000
|
||||
`define UARTRANGE 32'h00000007
|
||||
`define PLICBASE 32'h0C000000
|
||||
`define PLICRANGE 32'h03FFFFFF
|
||||
`define BOOTTIM_SUPPORTED 1'b1
|
||||
`define BOOTTIM_BASE 32'h00000000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder
|
||||
`define BOOTTIM_RANGE 32'h00003FFF
|
||||
//`define BOOTTIM_BASE 32'h00001000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder
|
||||
//`define BOOTTIM_RANGE 32'h00000FFF
|
||||
`define TIM_SUPPORTED 1'b1
|
||||
`define TIM_BASE 32'h80000000
|
||||
`define TIM_RANGE 32'h07FFFFFF
|
||||
`define CLINT_SUPPORTED 1'b1
|
||||
`define CLINT_BASE 32'h02000000
|
||||
`define CLINT_RANGE 32'h0000FFFF
|
||||
`define GPIO_SUPPORTED 1'b1
|
||||
`define GPIO_BASE 32'h10012000
|
||||
`define GPIO_RANGE 32'h000000FF
|
||||
`define UART_SUPPORTED 1'b1
|
||||
`define UART_BASE 32'h10000000
|
||||
`define UART_RANGE 32'h00000007
|
||||
`define PLIC_SUPPORTED 1'b1
|
||||
`define PLIC_BASE 32'h0C000000
|
||||
`define PLIC_RANGE 32'h03FFFFFF
|
||||
|
||||
// Test modes
|
||||
|
||||
@ -93,7 +104,7 @@
|
||||
`define PLIC_GPIO_ID 3
|
||||
`define PLIC_UART_ID 4
|
||||
|
||||
/`define TWO_BIT_PRELOAD "../config/coremark_bare/twoBitPredictor.txt"
|
||||
`define TWO_BIT_PRELOAD "../config/coremark_bare/twoBitPredictor.txt"
|
||||
`define BTB_PRELOAD "../config/coremark_bare/BTBPredictor.txt"
|
||||
`define BPRED_ENABLED 1
|
||||
`define BPTYPE "BPGSHARE"//comments
|
||||
|
@ -61,18 +61,26 @@
|
||||
// Peripheral memory space extends from BASE to BASE+RANGE
|
||||
// Range should be a thermometer code with 0's in the upper bits and 1s in the lower bits
|
||||
|
||||
`define BOOTTIMBASE 32'h00000000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder
|
||||
`define BOOTTIMRANGE 32'h00003FFF
|
||||
`define TIMBASE 32'h80000000
|
||||
`define TIMRANGE 32'h07FFFFFF
|
||||
`define CLINTBASE 32'h02000000
|
||||
`define CLINTRANGE 32'h0000FFFF
|
||||
`define GPIOBASE 32'h10012000
|
||||
`define GPIORANGE 32'h000000FF
|
||||
`define UARTBASE 32'h10000000
|
||||
`define UARTRANGE 32'h00000007
|
||||
`define PLICBASE 32'h0C000000
|
||||
`define PLICRANGE 32'h03FFFFFF
|
||||
`define BOOTTIM_SUPPORTED 1'b1
|
||||
`define BOOTTIM_BASE 32'h00000000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder
|
||||
`define BOOTTIM_RANGE 32'h00003FFF
|
||||
//`define BOOTTIM_BASE 32'h00001000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder
|
||||
//`define BOOTTIM_RANGE 32'h00000FFF
|
||||
`define TIM_SUPPORTED 1'b1
|
||||
`define TIM_BASE 32'h80000000
|
||||
`define TIM_RANGE 32'h07FFFFFF
|
||||
`define CLINT_SUPPORTED 1'b1
|
||||
`define CLINT_BASE 32'h02000000
|
||||
`define CLINT_RANGE 32'h0000FFFF
|
||||
`define GPIO_SUPPORTED 1'b1
|
||||
`define GPIO_BASE 32'h10012000
|
||||
`define GPIO_RANGE 32'h000000FF
|
||||
`define UART_SUPPORTED 1'b1
|
||||
`define UART_BASE 32'h10000000
|
||||
`define UART_RANGE 32'h00000007
|
||||
`define PLIC_SUPPORTED 1'b1
|
||||
`define PLIC_BASE 32'h0C000000
|
||||
`define PLIC_RANGE 32'h03FFFFFF
|
||||
|
||||
// Bus Interface width
|
||||
`define AHBW 32
|
||||
|
@ -63,18 +63,26 @@
|
||||
// Peripheral memory space extends from BASE to BASE+RANGE
|
||||
// Range should be a thermometer code with 0's in the upper bits and 1s in the lower bits
|
||||
|
||||
`define BOOTTIMBASE 32'h00000000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder
|
||||
`define BOOTTIMRANGE 32'h00003FFF
|
||||
`define TIMBASE 32'h00000000
|
||||
`define TIMRANGE 32'h07FFFFFF
|
||||
`define CLINTBASE 32'h02000000
|
||||
`define CLINTRANGE 32'h0000FFFF
|
||||
`define GPIOBASE 32'h10012000
|
||||
`define GPIORANGE 32'h000000FF
|
||||
`define UARTBASE 32'h10000000
|
||||
`define UARTRANGE 32'h00000007
|
||||
`define PLICBASE 32'h0C000000
|
||||
`define PLICRANGE 32'h03FFFFFF
|
||||
`define BOOTTIM_SUPPORTED 1'b1
|
||||
`define BOOTTIM_BASE 32'h00000000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder
|
||||
`define BOOTTIM_RANGE 32'h00003FFF
|
||||
//`define BOOTTIM_BASE 32'h00001000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder
|
||||
//`define BOOTTIM_RANGE 32'h00000FFF
|
||||
`define TIM_SUPPORTED 1'b1
|
||||
`define TIM_BASE 32'h80000000
|
||||
`define TIM_RANGE 32'h07FFFFFF
|
||||
`define CLINT_SUPPORTED 1'b1
|
||||
`define CLINT_BASE 32'h02000000
|
||||
`define CLINT_RANGE 32'h0000FFFF
|
||||
`define GPIO_SUPPORTED 1'b1
|
||||
`define GPIO_BASE 32'h10012000
|
||||
`define GPIO_RANGE 32'h000000FF
|
||||
`define UART_SUPPORTED 1'b1
|
||||
`define UART_BASE 32'h10000000
|
||||
`define UART_RANGE 32'h00000007
|
||||
`define PLIC_SUPPORTED 1'b1
|
||||
`define PLIC_BASE 32'h0C000000
|
||||
`define PLIC_RANGE 32'h03FFFFFF
|
||||
|
||||
// Test modes
|
||||
|
||||
|
@ -65,20 +65,26 @@
|
||||
// Peripheral memory space extends from BASE to BASE+RANGE
|
||||
// Range should be a thermometer code with 0's in the upper bits and 1s in the lower bits
|
||||
|
||||
`define BOOTTIMBASE 32'h00000000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder
|
||||
`define BOOTTIMRANGE 32'h00003FFF
|
||||
//`define BOOTTIMBASE 32'h00001000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder
|
||||
//`define BOOTTIMRANGE 32'h00000FFF
|
||||
`define TIMBASE 32'h80000000
|
||||
`define TIMRANGE 32'h07FFFFFF
|
||||
`define CLINTBASE 32'h02000000
|
||||
`define CLINTRANGE 32'h0000FFFF
|
||||
`define GPIOBASE 32'h10012000
|
||||
`define GPIORANGE 32'h000000FF
|
||||
`define UARTBASE 32'h10000000
|
||||
`define UARTRANGE 32'h00000007
|
||||
`define PLICBASE 32'h0C000000
|
||||
`define PLICRANGE 32'h03FFFFFF
|
||||
`define BOOTTIM_SUPPORTED 1'b1
|
||||
`define BOOTTIM_BASE 32'h00000000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder
|
||||
`define BOOTTIM_RANGE 32'h00003FFF
|
||||
//`define BOOTTIM_BASE 32'h00001000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder
|
||||
//`define BOOTTIM_RANGE 32'h00000FFF
|
||||
`define TIM_SUPPORTED 1'b1
|
||||
`define TIM_BASE 32'h80000000
|
||||
`define TIM_RANGE 32'h07FFFFFF
|
||||
`define CLINT_SUPPORTED 1'b1
|
||||
`define CLINT_BASE 32'h02000000
|
||||
`define CLINT_RANGE 32'h0000FFFF
|
||||
`define GPIO_SUPPORTED 1'b1
|
||||
`define GPIO_BASE 32'h10012000
|
||||
`define GPIO_RANGE 32'h000000FF
|
||||
`define UART_SUPPORTED 1'b1
|
||||
`define UART_BASE 32'h10000000
|
||||
`define UART_RANGE 32'h00000007
|
||||
`define PLIC_SUPPORTED 1'b1
|
||||
`define PLIC_BASE 32'h0C000000
|
||||
`define PLIC_RANGE 32'h03FFFFFF
|
||||
|
||||
// Test modes
|
||||
|
||||
|
@ -65,19 +65,26 @@
|
||||
// Peripheral memory space extends from BASE to BASE+RANGE
|
||||
// Range should be a thermometer code with 0's in the upper bits and 1s in the lower bits
|
||||
|
||||
`define BOOTTIMBASE 32'h00000000
|
||||
`define BOOTTIMRANGE 32'h00003FFF
|
||||
`define TIMBASE 32'h80000000
|
||||
// `define TIMRANGE 32'h0007FFFF
|
||||
`define TIMRANGE 32'h07FFFFFF
|
||||
`define CLINTBASE 32'h02000000
|
||||
`define CLINTRANGE 32'h0000FFFF
|
||||
`define GPIOBASE 32'h10012000
|
||||
`define GPIORANGE 32'h000000FF
|
||||
`define UARTBASE 32'h10000000
|
||||
`define UARTRANGE 32'h00000007
|
||||
`define PLICBASE 32'h0C000000
|
||||
`define PLICRANGE 32'h03FFFFFF
|
||||
`define BOOTTIM_SUPPORTED 1'b1
|
||||
`define BOOTTIM_BASE 32'h00000000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder
|
||||
`define BOOTTIM_RANGE 32'h00003FFF
|
||||
//`define BOOTTIM_BASE 32'h00001000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder
|
||||
//`define BOOTTIM_RANGE 32'h00000FFF
|
||||
`define TIM_SUPPORTED 1'b1
|
||||
`define TIM_BASE 32'h80000000
|
||||
`define TIM_RANGE 32'h07FFFFFF
|
||||
`define CLINT_SUPPORTED 1'b1
|
||||
`define CLINT_BASE 32'h02000000
|
||||
`define CLINT_RANGE 32'h0000FFFF
|
||||
`define GPIO_SUPPORTED 1'b1
|
||||
`define GPIO_BASE 32'h10012000
|
||||
`define GPIO_RANGE 32'h000000FF
|
||||
`define UART_SUPPORTED 1'b1
|
||||
`define UART_BASE 32'h10000000
|
||||
`define UART_RANGE 32'h00000007
|
||||
`define PLIC_SUPPORTED 1'b1
|
||||
`define PLIC_BASE 32'h0C000000
|
||||
`define PLIC_RANGE 32'h03FFFFFF
|
||||
|
||||
// Test modes
|
||||
|
||||
|
@ -61,18 +61,26 @@
|
||||
// Peripheral memory space extends from BASE to BASE+RANGE
|
||||
// Range should be a thermometer code with 0's in the upper bits and 1s in the lower bits
|
||||
|
||||
`define BOOTTIMBASE 32'h00000000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder
|
||||
`define BOOTTIMRANGE 32'h00003FFF
|
||||
`define TIMBASE 32'h80000000
|
||||
`define TIMRANGE 32'h0007FFFF
|
||||
`define CLINTBASE 32'h02000000
|
||||
`define CLINTRANGE 32'h0000FFFF
|
||||
`define GPIOBASE 32'h10012000
|
||||
`define GPIORANGE 32'h000000FF
|
||||
`define UARTBASE 32'h10000000
|
||||
`define UARTRANGE 32'h00000007
|
||||
`define PLICBASE 32'h0C000000
|
||||
`define PLICRANGE 32'h03FFFFFF
|
||||
`define BOOTTIM_SUPPORTED 1'b1
|
||||
`define BOOTTIM_BASE 32'h00000000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder
|
||||
`define BOOTTIM_RANGE 32'h00003FFF
|
||||
//`define BOOTTIM_BASE 32'h00001000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder
|
||||
//`define BOOTTIM_RANGE 32'h00000FFF
|
||||
`define TIM_SUPPORTED 1'b1
|
||||
`define TIM_BASE 32'h80000000
|
||||
`define TIM_RANGE 32'h07FFFFFF
|
||||
`define CLINT_SUPPORTED 1'b1
|
||||
`define CLINT_BASE 32'h02000000
|
||||
`define CLINT_RANGE 32'h0000FFFF
|
||||
`define GPIO_SUPPORTED 1'b1
|
||||
`define GPIO_BASE 32'h10012000
|
||||
`define GPIO_RANGE 32'h000000FF
|
||||
`define UART_SUPPORTED 1'b1
|
||||
`define UART_BASE 32'h10000000
|
||||
`define UART_RANGE 32'h00000007
|
||||
`define PLIC_SUPPORTED 1'b1
|
||||
`define PLIC_BASE 32'h0C000000
|
||||
`define PLIC_RANGE 32'h03FFFFFF
|
||||
|
||||
// Test modes
|
||||
|
||||
|
@ -2,25 +2,26 @@
|
||||
# Uncomment this version for GDB/QEMU debugging
|
||||
# - Opens up GDB interactively
|
||||
# - Logs raw QEMU output to qemu_output.txt
|
||||
#(qemu-system-riscv64 -M virt -nographic -bios /courses/e190ax/qemu_sim/rv64_initrd/buildroot_experimental/output/images/fw_jump.elf -kernel /courses/e190ax/qemu_sim/rv64_initrd/buildroot_experimental/output/images/Image -append "root=/dev/vda ro" -initrd /courses/e190ax/qemu_sim/rv64_initrd/buildroot_experimental/output/images/rootfs.cpio -d nochain,cpu,in_asm -serial /dev/null -singlestep -s -S 2> /mnt/scratch/wally_linux_output/qemu_output.txt) & riscv64-unknown-elf-gdb
|
||||
#(qemu-system-riscv64 -M virt -nographic -bios /courses/e190ax/qemu_sim/rv64_initrd/buildroot_experimental/output/images/fw_jump.elf -kernel /courses/e190ax/qemu_sim/rv64_initrd/buildroot_experimental/output/images/Image -append "root=/dev/vda ro" -initrd /courses/e190ax/qemu_sim/rv64_initrd/buildroot_experimental/output/images/rootfs.cpio -d nochain,cpu,in_asm -serial /dev/null -singlestep -s -S 2> qemu_output.txt) & riscv64-unknown-elf-gdb
|
||||
|
||||
# Uncomment this version to generate qemu_output.txt
|
||||
# - Uses GDB script
|
||||
# - Logs raw QEMU output to qemu_output.txt
|
||||
#(qemu-system-riscv64 -M virt -nographic -bios /courses/e190ax/qemu_sim/rv64_initrd/buildroot_experimental/output/images/fw_jump.elf -kernel /courses/e190ax/qemu_sim/rv64_initrd/buildroot_experimental/output/images/Image -append "root=/dev/vda ro" -initrd /courses/e190ax/qemu_sim/rv64_initrd/buildroot_experimental/output/images/rootfs.cpio -d nochain,cpu,in_asm -serial /dev/null -singlestep -s -S 2>/mnt/scratch/wally_linux_output/qemu_output.txt) & riscv64-unknown-elf-gdb -x gdbinit_qemulog
|
||||
#(qemu-system-riscv64 -M virt -nographic -bios /courses/e190ax/qemu_sim/rv64_initrd/buildroot_experimental/output/images/fw_jump.elf -kernel /courses/e190ax/qemu_sim/rv64_initrd/buildroot_experimental/output/images/Image -append "root=/dev/vda ro" -initrd /courses/e190ax/qemu_sim/rv64_initrd/buildroot_experimental/output/images/rootfs.cpio -d nochain,cpu,in_asm -serial /dev/null -singlestep -s -S 2>qemu_output.txt) & riscv64-unknown-elf-gdb -x gdbinit_qemulog_debug
|
||||
|
||||
# Uncomment this version for parse_qemu.py debugging
|
||||
# - Uses qemu_output.txt
|
||||
# - Makes qemu_in_gdb_format.txt
|
||||
# - Logs parse_qemu.py's simulated gdb output to qemu_in_gdb_format.txt
|
||||
#cat /mnt/scratch/wally_linux_output/qemu_output.txt | ./parse_qemu.py >/mnt/scratch/wally_linux_output/qemu_in_gdb_format.txt
|
||||
#cat qemu_output.txt | ./parse_qemu.py >qemu_in_gdb_format.txt
|
||||
#cat qemu_output.txt | ./parse_qemu.py | ./parse_gdb_output.py "/courses/e190ax/buildroot_boot/"
|
||||
|
||||
# Uncomment this version for parse_gdb_output.py debugging
|
||||
# - Uses qemu_in_gdb_format.txt
|
||||
# - Logs info needed by buildroot testbench
|
||||
cat /mnt/scratch/wally_linux_output/qemu_in_gdb_format.txt | ./parse_gdb_output.py "/courses/e190ax/buildroot_boot/"
|
||||
#cat qemu_in_gdb_format.txt | ./parse_gdb_output.py "/courses/e190ax/buildroot_boot/"
|
||||
|
||||
# =========== Just Do the Thing ==========
|
||||
# Uncomment this version for the whole thing (if it works ha ha_
|
||||
# Uncomment this version for the whole thing
|
||||
# - Logs info needed by buildroot testbench
|
||||
#(qemu-system-riscv64 -M virt -nographic -bios /courses/e190ax/qemu_sim/rv64_initrd/buildroot_experimental/output/images/fw_jump.elf -kernel /courses/e190ax/qemu_sim/rv64_initrd/buildroot_experimental/output/images/Image -append "root=/dev/vda ro" -initrd /courses/e190ax/qemu_sim/rv64_initrd/buildroot_experimental/output/images/rootfs.cpio -d nochain,cpu,in_asm -serial /dev/null -singlestep -s -S 2>&1 >/dev/null | pv -l | ./parse_qemu.py | ./parse_gdb_output.py "/courses/e190ax/buildroot_boot/") & riscv64-unknown-elf-gdb -x gdbinit_qemulog
|
||||
(qemu-system-riscv64 -M virt -nographic -bios /courses/e190ax/qemu_sim/rv64_initrd/buildroot_experimental/output/images/fw_jump.elf -kernel /courses/e190ax/qemu_sim/rv64_initrd/buildroot_experimental/output/images/Image -append "root=/dev/vda ro" -initrd /courses/e190ax/qemu_sim/rv64_initrd/buildroot_experimental/output/images/rootfs.cpio -d nochain,cpu,in_asm -serial /dev/null -singlestep -s -S 2>&1 >/dev/null | pv -l | ./parse_qemu.py | ./parse_gdb_output.py "/courses/e190ax/buildroot_boot/") & riscv64-unknown-elf-gdb -x gdbinit_qemulog
|
||||
|
@ -27,7 +27,7 @@ try:
|
||||
readType = ''
|
||||
lastReadType = ''
|
||||
readLoc = ''
|
||||
instrStart = -1
|
||||
lineOffset = -1
|
||||
lastRegs = ''
|
||||
curRegs = ''
|
||||
storeReg = ''
|
||||
@ -40,10 +40,12 @@ try:
|
||||
for l in fileinput.input('-'):
|
||||
l = l.split("#")[0].rstrip()
|
||||
if l.startswith('=>'):
|
||||
# Begin new instruction
|
||||
instrs += 1
|
||||
storeAMO = ''
|
||||
if instrs % 10000 == 0:
|
||||
print(instrs)
|
||||
# Instr in human assembly
|
||||
wPC.write('{} ***\n'.format(' '.join(l.split(':')[1].split()[0:2])))
|
||||
if '\tld' in l or '\tlw' in l or '\tlh' in l or '\tlb' in l:
|
||||
currentRead = l.split()[-1].split(',')[0]
|
||||
@ -53,7 +55,6 @@ try:
|
||||
readLoc = l.split()[-1].split(',')[1].split('(')[1][:-1]
|
||||
readType = l.split()[-2]
|
||||
if 'amo' in l:
|
||||
#print(l)
|
||||
currentRead = l.split()[-1].split(',')[0]
|
||||
readOffset = "0"
|
||||
readLoc = l.split()[-1].split('(')[1][:-1]
|
||||
@ -63,7 +64,6 @@ try:
|
||||
storeReg = l.split()[-1].split(',')[1]
|
||||
storeAMO = l.split()[-2]
|
||||
if '\tsd' in l or '\tsw' in l or '\tsh' in l or '\tsb' in l:
|
||||
#print(l)
|
||||
s = l.split('#')[0].split()[-1]
|
||||
storeReg = s.split(',')[0]
|
||||
if len(s.split(',')) < 2:
|
||||
@ -74,17 +74,19 @@ try:
|
||||
print(l)
|
||||
storeOffset = s.split(',')[1].split('(')[0]
|
||||
storeLoc = s.split(',')[1].split('(')[1][:-1]
|
||||
instrStart = 0
|
||||
elif instrStart != -1:
|
||||
instrStart += 1
|
||||
if instrStart == 1:
|
||||
lineOffset = 0
|
||||
elif lineOffset != -1:
|
||||
lineOffset += 1
|
||||
if lineOffset == 1:
|
||||
# Instr in hex comes one line after the instruction
|
||||
wPC.write('{}\n'.format(l.split()[-1][2:]))
|
||||
elif instrStart < 34:
|
||||
# As well as instr address
|
||||
wPC.write('{}\n'.format(l.split()[0][2:].strip(":")))
|
||||
elif lineOffset <= (1+32):
|
||||
# Next 32 lines are the Register File
|
||||
if lastRead == l.split()[0]:
|
||||
readData = int(l.split()[1][2:], 16)
|
||||
readData <<= (8 * (lastReadLoc % 8))
|
||||
#if(lastReadLoc % 8 != 0 and ('lw' in lastReadType or 'lb' in lastReadType)):
|
||||
# readData <<= 32
|
||||
wMem.write('{:x}\n'.format(readData))
|
||||
if readLoc == l.split()[0]:
|
||||
readLoc = l.split()[1][2:]
|
||||
@ -92,16 +94,12 @@ try:
|
||||
storeReg = l.split()[1]
|
||||
if storeLoc == l.split()[0]:
|
||||
storeLoc = l.split()[1][2:]
|
||||
if instrStart > 2:
|
||||
#print(l)
|
||||
#print(instrStart)
|
||||
if lineOffset > (1+1):
|
||||
# Start logging x1 onwards (we don't care about x0)
|
||||
curRegs += '{}\n'.format(l.split()[1][2:])
|
||||
elif instrStart < 35:
|
||||
#print("----------")
|
||||
#print(l.split()[1][2:])
|
||||
wPC.write('{}\n'.format(l.split()[1][2:]))
|
||||
#print(l.split()[1][2:])
|
||||
if any([c == l.split()[0] for c in csrs]):
|
||||
#elif "pc" in l:
|
||||
# wPC.write('{}\n'.format(l.split()[1][2:]))
|
||||
if any([csr == l.split()[0] for csr in csrs]):
|
||||
if l.split()[0] in curCSRs:
|
||||
if curCSRs[l.split()[0]] != l.split()[1]:
|
||||
if firstCSR:
|
||||
@ -112,51 +110,53 @@ try:
|
||||
wCSRs.write('{}\n{}\n'.format(l.split()[0], l.split()[1][2:]))
|
||||
curCSRs[l.split()[0]] = l.split()[1]
|
||||
if '-----' in l: # end of each cycle
|
||||
if curRegs != lastRegs:
|
||||
if lastRegs == '':
|
||||
wReg.write(curRegs)
|
||||
else:
|
||||
for i in range(32):
|
||||
if curRegs.split('\n')[i] != lastRegs.split('\n')[i]:
|
||||
wReg.write('{}\n'.format(i+1))
|
||||
wReg.write('{}\n'.format(curRegs.split('\n')[i]))
|
||||
break
|
||||
lastRegs = curRegs
|
||||
if lastAMO != '':
|
||||
if 'amoadd' in lastAMO:
|
||||
lastStoreReg = hex(int(lastStoreReg[2:], 16) + readData)[2:]
|
||||
elif 'amoand' in lastAMO:
|
||||
lastStoreReg = hex(int(lastStoreReg[2:], 16) & readData)[2:]
|
||||
elif 'amoor' in lastAMO:
|
||||
lastStoreReg = hex(int(lastStoreReg[2:], 16) | readData)[2:]
|
||||
elif 'amoswap' in lastAMO:
|
||||
lastStoreReg = hex(int(lastStoreReg[2:], 16))[2:]
|
||||
else:
|
||||
print(lastAMO)
|
||||
exit()
|
||||
wMemW.write('{}\n'.format(lastStoreReg))
|
||||
wMemW.write('{:x}\n'.format(int(lastStoreLoc, 16)))
|
||||
if storeReg != '' and storeOffset != '' and storeLoc != '' and storeAMO == '':
|
||||
storeLocOffset = int(storeOffset,10) + int(storeLoc, 16)
|
||||
#wMemW.write('{:x}\n'.format(int(storeReg, 16) << (8 * (storeLocOffset % 8))))
|
||||
wMemW.write('{}\n'.format(storeReg[2:]))
|
||||
wMemW.write('{:x}\n'.format(storeLocOffset))
|
||||
if readOffset != '' and readLoc != '':
|
||||
wMem.write('{:x}\n'.format(int(readOffset,10) + int(readLoc, 16)))
|
||||
lastReadLoc = int(readOffset,10) + int(readLoc, 16)
|
||||
lastReadType = readType
|
||||
readOffset = ''
|
||||
readLoc = ''
|
||||
curRegs = ''
|
||||
instrStart = -1
|
||||
lastRead = currentRead
|
||||
currentRead = ''
|
||||
lastStoreReg = storeReg
|
||||
lastStoreLoc = storeLoc
|
||||
storeReg = ''
|
||||
storeOffset = ''
|
||||
storeLoc = ''
|
||||
lastAMO = storeAMO
|
||||
if curRegs != lastRegs:
|
||||
if lastRegs == '':
|
||||
wReg.write(curRegs)
|
||||
else:
|
||||
for i in range(32):
|
||||
if curRegs.split('\n')[i] != lastRegs.split('\n')[i]:
|
||||
wReg.write('{}\n'.format(i+1))
|
||||
wReg.write('{}\n'.format(curRegs.split('\n')[i]))
|
||||
break
|
||||
lastRegs = curRegs
|
||||
if lastAMO != '':
|
||||
if 'amoadd' in lastAMO:
|
||||
lastStoreReg = hex(int(lastStoreReg[2:], 16) + readData)[2:]
|
||||
elif 'amoand' in lastAMO:
|
||||
lastStoreReg = hex(int(lastStoreReg[2:], 16) & readData)[2:]
|
||||
elif 'amoor' in lastAMO:
|
||||
lastStoreReg = hex(int(lastStoreReg[2:], 16) | readData)[2:]
|
||||
elif 'amoswap' in lastAMO:
|
||||
lastStoreReg = hex(int(lastStoreReg[2:], 16))[2:]
|
||||
else:
|
||||
print(lastAMO)
|
||||
exit()
|
||||
#print('lastStoreReg {}\n'.format(lastStoreReg))
|
||||
#print('lastStoreLoc '+str(lastStoreLoc))
|
||||
wMemW.write('{}\n'.format(lastStoreReg))
|
||||
wMemW.write('{:x}\n'.format(int(lastStoreLoc, 16)))
|
||||
if storeReg != '' and storeOffset != '' and storeLoc != '' and storeAMO == '':
|
||||
storeLocOffset = int(storeOffset,10) + int(storeLoc, 16)
|
||||
#wMemW.write('{:x}\n'.format(int(storeReg, 16) << (8 * (storeLocOffset % 8))))
|
||||
wMemW.write('{}\n'.format(storeReg[2:]))
|
||||
wMemW.write('{:x}\n'.format(storeLocOffset))
|
||||
if readOffset != '' and readLoc != '':
|
||||
wMem.write('{:x}\n'.format(int(readOffset,10) + int(readLoc, 16)))
|
||||
lastReadLoc = int(readOffset,10) + int(readLoc, 16)
|
||||
lastReadType = readType
|
||||
readOffset = ''
|
||||
readLoc = ''
|
||||
curRegs = ''
|
||||
lineOffset = -1
|
||||
lastRead = currentRead
|
||||
currentRead = ''
|
||||
lastStoreReg = storeReg
|
||||
lastStoreLoc = storeLoc
|
||||
storeReg = ''
|
||||
storeOffset = ''
|
||||
storeLoc = ''
|
||||
lastAMO = storeAMO
|
||||
|
||||
|
||||
except (FileNotFoundError):
|
||||
|
@ -39,12 +39,14 @@ def parseCSRs(l):
|
||||
csr = l.split()[0]
|
||||
val = int(l.split()[1],16)
|
||||
if inPageFault:
|
||||
if l.startswith("mstatus") or l.startswith("mepc") or l.startswith("mcause") or l.startswith("mtval") or l.startswith("sepc") or l.startswith("scause") or l.startswith("stval"):
|
||||
# We do update some CSRs
|
||||
CSRs[csr] = val
|
||||
else:
|
||||
# Others we preserve until changed later
|
||||
pageFaultCSRs[csr] = val
|
||||
# Not sure if these CSRs should be updated or not during page fault.
|
||||
#if l.startswith("mstatus") or l.startswith("mepc") or l.startswith("mcause") or l.startswith("mtval") or l.startswith("sepc") or l.startswith("scause") or l.startswith("stval"):
|
||||
# # We do update some CSRs
|
||||
# CSRs[csr] = val
|
||||
#else:
|
||||
# # Others we preserve until changed later
|
||||
# pageFaultCSRs[csr] = val
|
||||
pageFaultCSRs[csr] = val
|
||||
elif pageFaultCSRs and (csr in pageFaultCSRs):
|
||||
if (val != pageFaultCSRs[csr]):
|
||||
del pageFaultCSRs[csr]
|
||||
|
@ -28,11 +28,11 @@ configs = [
|
||||
cmd="vsim -do wally-busybear-batch.do -c > {}",
|
||||
grepstr="# loaded 100000 instructions"
|
||||
),
|
||||
# TestCase(
|
||||
# name="buildroot",
|
||||
# cmd="vsim -do wally-buildroot-batch.do -c > {}",
|
||||
# grepstr="# loaded 100000 instructions"
|
||||
# ),
|
||||
TestCase(
|
||||
name="buildroot",
|
||||
cmd="vsim -do wally-buildroot-batch.do -c > {}",
|
||||
grepstr="# loaded 600000 instructions"
|
||||
),
|
||||
TestCase(
|
||||
name="rv32ic",
|
||||
cmd="vsim > {} -c <<!\ndo wally-pipelined-batch.do ../config/rv32ic rv32ic\n!",
|
||||
|
1534
wally-pipelined/regression/vsim_stacktrace.vstf
Normal file
1534
wally-pipelined/regression/vsim_stacktrace.vstf
Normal file
File diff suppressed because it is too large
Load Diff
@ -35,7 +35,7 @@ vopt +acc work.testbench -o workopt
|
||||
|
||||
vsim workopt -suppress 8852,12070
|
||||
|
||||
do ./wave-dos/busybear-waves.do
|
||||
do ./wave-dos/linux-waves.do
|
||||
|
||||
#-- Run the Simulation
|
||||
run -all
|
||||
|
@ -35,7 +35,7 @@ vopt +acc work.testbench -o workopt
|
||||
|
||||
vsim workopt -suppress 8852,12070
|
||||
|
||||
do ./wave-dos/bens-busybear-waves.do
|
||||
do ./wave-dos/linux-waves.do
|
||||
|
||||
|
||||
#-- Run the Simulation
|
||||
|
@ -1,64 +0,0 @@
|
||||
# busybear-waves.do
|
||||
restart -f
|
||||
delete wave /*
|
||||
view wave
|
||||
|
||||
add wave /testbench/dut/hart/DataStall
|
||||
add wave /testbench/dut/hart/ICacheStallF
|
||||
add wave /testbench/dut/hart/StallF
|
||||
add wave /testbench/dut/hart/StallD
|
||||
add wave /testbench/dut/hart/StallE
|
||||
add wave /testbench/dut/hart/StallM
|
||||
add wave /testbench/dut/hart/StallW
|
||||
add wave /testbench/dut/hart/FlushD
|
||||
add wave /testbench/dut/hart/FlushE
|
||||
add wave /testbench/dut/hart/FlushM
|
||||
add wave /testbench/dut/hart/FlushW
|
||||
add wave -divider
|
||||
|
||||
add wave /testbench/clk
|
||||
add wave /testbench/reset
|
||||
add wave -divider
|
||||
|
||||
add wave -hex /testbench/dut/hart/ifu/PCF
|
||||
add wave -hex /testbench/PCtext
|
||||
add wave -hex /testbench/pcExpected
|
||||
add wave -hex /testbench/dut/hart/ifu/PCD
|
||||
add wave -hex /testbench/dut/hart/ifu/InstrD
|
||||
add wave /testbench/InstrDName
|
||||
add wave -divider
|
||||
add wave -hex /testbench/dut/hart/ifu/PCE
|
||||
add wave -hex /testbench/dut/hart/ifu/InstrE
|
||||
add wave /testbench/InstrEName
|
||||
add wave -hex /testbench/dut/hart/ieu/dp/SrcAE
|
||||
add wave -hex /testbench/dut/hart/ieu/dp/SrcBE
|
||||
add wave -hex /testbench/dut/hart/ieu/dp/ALUResultE
|
||||
#add wave /testbench/dut/hart/ieu/dp/PCSrcE
|
||||
add wave -divider
|
||||
add wave -hex /testbench/dut/hart/ifu/PCM
|
||||
add wave -hex /testbench/dut/hart/ifu/InstrM
|
||||
add wave /testbench/InstrMName
|
||||
add wave /testbench/dut/uncore/dtim/memwrite
|
||||
add wave -hex /testbench/dut/uncore/HADDR
|
||||
add wave -hex /testbench/dut/uncore/HWDATA
|
||||
add wave -divider
|
||||
add wave -hex /testbench/PCW
|
||||
add wave -hex /testbench/InstrW
|
||||
add wave /testbench/InstrWName
|
||||
add wave /testbench/dut/hart/ieu/dp/RegWriteW
|
||||
add wave -hex /testbench/dut/hart/ieu/dp/ResultW
|
||||
add wave -hex /testbench/dut/hart/ieu/dp/RdW
|
||||
add wave -divider
|
||||
|
||||
# appearance
|
||||
TreeUpdate [SetDefaultTree]
|
||||
WaveRestoreZoom {0 ps} {100 ps}
|
||||
configure wave -namecolwidth 250
|
||||
configure wave -valuecolwidth 150
|
||||
configure wave -justifyvalue left
|
||||
configure wave -signalnamewidth 0
|
||||
configure wave -snapdistance 10
|
||||
configure wave -datasetprefix 0
|
||||
configure wave -rowmargin 4
|
||||
configure wave -childrowmargin 2
|
||||
set DefaultRadix hexadecimal
|
@ -1,58 +1,66 @@
|
||||
# busybear-waves.do
|
||||
|
||||
# linux-waves.do
|
||||
restart -f
|
||||
delete wave /*
|
||||
view wave
|
||||
|
||||
-- display input and output signals as hexidecimal values
|
||||
# Diplays All Signals recursively
|
||||
add wave -divider
|
||||
add wave /testbench/clk
|
||||
add wave /testbench/reset
|
||||
add wave -divider
|
||||
add wave -hex /testbench/PCtext
|
||||
|
||||
add wave -divider Stalls_and_Flushes
|
||||
add wave /testbench/dut/hart/StallF
|
||||
add wave /testbench/dut/hart/StallD
|
||||
add wave /testbench/dut/hart/StallE
|
||||
add wave /testbench/dut/hart/StallM
|
||||
add wave /testbench/dut/hart/StallW
|
||||
add wave -group stall_srcs /testbench/dut/hart/DataStall
|
||||
add wave -group stall_srcs /testbench/dut/hart/ICacheStallF
|
||||
add wave /testbench/dut/hart/FlushD
|
||||
add wave /testbench/dut/hart/FlushE
|
||||
add wave /testbench/dut/hart/FlushM
|
||||
add wave /testbench/dut/hart/FlushW
|
||||
|
||||
add wave -divider F
|
||||
add wave -hex /testbench/dut/hart/ifu/PCF
|
||||
add wave -divider D
|
||||
add wave -hex /testbench/pcExpected
|
||||
add wave -hex /testbench/dut/hart/ifu/PCD
|
||||
add wave -hex /testbench/PCtextD
|
||||
add wave /testbench/InstrDName
|
||||
add wave -hex /testbench/dut/hart/ifu/InstrD
|
||||
add wave -hex /testbench/dut/hart/ifu/StallD
|
||||
add wave -hex /testbench/dut/hart/ifu/FlushD
|
||||
add wave -hex /testbench/dut/hart/ifu/StallE
|
||||
add wave -hex /testbench/dut/hart/ifu/FlushE
|
||||
add wave -hex /testbench/dut/hart/ifu/InstrRawD
|
||||
add wave /testbench/CheckInstrD
|
||||
add wave /testbench/lastCheckInstrD
|
||||
add wave /testbench/speculative
|
||||
add wave /testbench/lastPC2
|
||||
add wave -divider
|
||||
add wave -divider
|
||||
add wave /testbench/dut/uncore/HSELBootTim
|
||||
add wave /testbench/dut/uncore/HSELTim
|
||||
add wave /testbench/dut/uncore/HREADTim
|
||||
add wave /testbench/dut/uncore/dtim/HREADTim0
|
||||
add wave /testbench/dut/uncore/HREADYTim
|
||||
add wave -divider
|
||||
add wave /testbench/dut/uncore/HREADBootTim
|
||||
add wave /testbench/dut/uncore/bootdtim/HREADTim0
|
||||
add wave /testbench/dut/uncore/HREADYBootTim
|
||||
add wave /testbench/dut/uncore/HADDR
|
||||
add wave /testbench/dut/uncore/HRESP
|
||||
add wave /testbench/dut/uncore/HREADY
|
||||
add wave /testbench/dut/uncore/HRDATA
|
||||
#add wave -hex /testbench/dut/hart/priv/csr/MTVEC_REG
|
||||
#add wave -hex /testbench/dut/hart/priv/csr/MSTATUS_REG
|
||||
#add wave -hex /testbench/dut/hart/priv/csr/SCOUNTEREN_REG
|
||||
#add wave -hex /testbench/dut/hart/priv/csr/MIE_REG
|
||||
#add wave -hex /testbench/dut/hart/priv/csr/MIDELEG_REG
|
||||
#add wave -hex /testbench/dut/hart/priv/csr/MEDELEG_REG
|
||||
add wave -divider
|
||||
# registers!
|
||||
add wave -hex /testbench/dut/hart/ieu/c/InstrValidD
|
||||
add wave -divider E
|
||||
add wave -hex /testbench/dut/hart/ifu/PCE
|
||||
add wave -hex /testbench/PCtextE
|
||||
add wave /testbench/InstrEName
|
||||
add wave -hex /testbench/dut/hart/ifu/InstrE
|
||||
add wave -hex /testbench/dut/hart/ieu/c/InstrValidE
|
||||
add wave -hex /testbench/dut/hart/ieu/dp/SrcAE
|
||||
add wave -hex /testbench/dut/hart/ieu/dp/SrcBE
|
||||
add wave -hex /testbench/dut/hart/ieu/dp/ALUResultE
|
||||
add wave -divider M
|
||||
add wave -hex /testbench/dut/hart/ifu/PCM
|
||||
add wave -hex /testbench/PCtextM
|
||||
add wave /testbench/InstrMName
|
||||
add wave -hex /testbench/dut/hart/ifu/InstrM
|
||||
add wave -hex /testbench/dut/hart/ieu/c/InstrValidM
|
||||
add wave /testbench/dut/uncore/dtim/memwrite
|
||||
add wave -hex /testbench/dut/uncore/HADDR
|
||||
add wave -hex /testbench/HWRITE
|
||||
add wave -hex /testbench/dut/uncore/HWDATA
|
||||
add wave -hex /testbench/HRDATA
|
||||
add wave -hex /testbench/readAdrExpected
|
||||
add wave -divider W
|
||||
add wave -hex /testbench/PCW
|
||||
add wave -hex /testbench/PCtextW
|
||||
add wave -hex /testbench/dut/hart/ieu/c/InstrValidW
|
||||
add wave /testbench/dut/hart/ieu/dp/RegWriteW
|
||||
add wave -hex /testbench/dut/hart/ieu/dp/ResultW
|
||||
add wave -hex /testbench/dut/hart/ieu/dp/RdW
|
||||
|
||||
add wave -divider RegFile
|
||||
add wave -hex /testbench/regExpected
|
||||
add wave -hex /testbench/regNumExpected
|
||||
add wave -hex /testbench/HWRITE
|
||||
add wave -hex /testbench/dut/hart/MemRWM[1]
|
||||
add wave -hex /testbench/HWDATA
|
||||
add wave -hex /testbench/HRDATA
|
||||
add wave -hex /testbench/HADDR
|
||||
add wave -hex /testbench/readAdrExpected
|
||||
add wave -hex /testbench/dut/hart/ieu/dp/regf/rf[1]
|
||||
add wave -hex /testbench/dut/hart/ieu/dp/regf/rf[2]
|
||||
add wave -hex /testbench/dut/hart/ieu/dp/regf/rf[3]
|
||||
@ -84,36 +92,10 @@ add wave -hex /testbench/dut/hart/ieu/dp/regf/rf[28]
|
||||
add wave -hex /testbench/dut/hart/ieu/dp/regf/rf[29]
|
||||
add wave -hex /testbench/dut/hart/ieu/dp/regf/rf[30]
|
||||
add wave -hex /testbench/dut/hart/ieu/dp/regf/rf[31]
|
||||
add wave /testbench/InstrFName
|
||||
add wave -hex /testbench/dut/hart/ifu/PCD
|
||||
#add wave -hex /testbench/dut/hart/ifu/InstrD
|
||||
add wave /testbench/InstrDName
|
||||
#add wave -divider
|
||||
add wave -hex /testbench/dut/hart/ifu/PCE
|
||||
##add wave -hex /testbench/dut/hart/ifu/InstrE
|
||||
add wave /testbench/InstrEName
|
||||
#add wave -hex /testbench/dut/hart/ieu/dp/SrcAE
|
||||
#add wave -hex /testbench/dut/hart/ieu/dp/SrcBE
|
||||
add wave -hex /testbench/dut/hart/ieu/dp/ALUResultE
|
||||
#add wave /testbench/dut/hart/ieu/dp/PCSrcE
|
||||
#add wave -divider
|
||||
add wave -hex /testbench/dut/hart/ifu/PCM
|
||||
##add wave -hex /testbench/dut/hart/ifu/InstrM
|
||||
add wave /testbench/InstrMName
|
||||
#add wave /testbench/dut/hart/dmem/dtim/memwrite
|
||||
#add wave -hex /testbench/dut/hart/dmem/AdrM
|
||||
#add wave -hex /testbench/dut/hart/dmem/WriteDataM
|
||||
#add wave -divider
|
||||
add wave -hex /testbench/PCW
|
||||
##add wave -hex /testbench/dut/hart/ifu/InstrW
|
||||
add wave /testbench/InstrWName
|
||||
#add wave /testbench/dut/hart/ieu/dp/RegWriteW
|
||||
#add wave -hex /testbench/dut/hart/ieu/dp/ResultW
|
||||
#add wave -hex /testbench/dut/hart/ieu/dp/RdW
|
||||
#add wave -divider
|
||||
##add ww
|
||||
|
||||
add wave -divider
|
||||
add wave -hex -r /testbench/*
|
||||
#
|
||||
|
||||
# appearance
|
||||
TreeUpdate [SetDefaultTree]
|
||||
WaveRestoreZoom {0 ps} {100 ps}
|
23
wally-pipelined/src/cache/ICacheCntrl.sv
vendored
23
wally-pipelined/src/cache/ICacheCntrl.sv
vendored
@ -33,15 +33,15 @@ module ICacheCntrl #(parameter BLOCKLEN = 256) (
|
||||
|
||||
// Input the address to read
|
||||
// The upper bits of the physical pc
|
||||
input logic [`XLEN-1:0] PCNextF,
|
||||
input logic [`XLEN-1:0] PCPF,
|
||||
input logic [`PA_BITS-1:0] PCNextF,
|
||||
input logic [`PA_BITS-1:0] PCPF,
|
||||
// Signals to/from cache memory
|
||||
// The read coming out of it
|
||||
input logic [31:0] ICacheMemReadData,
|
||||
input logic ICacheMemReadValid,
|
||||
// The address at which we want to search the cache memory
|
||||
output logic [`XLEN-1:0] PCTagF,
|
||||
output logic [`XLEN-1:0] PCNextIndexF,
|
||||
output logic [`PA_BITS-1:0] PCTagF,
|
||||
output logic [`PA_BITS-1:0] PCNextIndexF,
|
||||
output logic ICacheReadEn,
|
||||
// Load data into the cache
|
||||
output logic ICacheMemWriteEnable,
|
||||
@ -133,8 +133,8 @@ module ICacheCntrl #(parameter BLOCKLEN = 256) (
|
||||
|
||||
logic [LOGWPL:0] FetchCount, NextFetchCount;
|
||||
|
||||
logic [`XLEN-1:0] PCPreFinalF, PCPFinalF, PCSpillF;
|
||||
logic [`XLEN-1:OFFSETWIDTH] PCPTrunkF;
|
||||
logic [`PA_BITS-1:0] PCPreFinalF, PCPSpillF;
|
||||
logic [`PA_BITS-1:OFFSETWIDTH] PCPTrunkF;
|
||||
|
||||
|
||||
logic [31:0] FinalInstrRawF;
|
||||
@ -156,11 +156,11 @@ module ICacheCntrl #(parameter BLOCKLEN = 256) (
|
||||
// on spill we want to get the first 2 bytes of the next cache block.
|
||||
// the spill only occurs if the PCPF mod BlockByteLength == -2. Therefore we can
|
||||
// simply add 2 to land on the next cache block.
|
||||
assign PCSpillF = PCPF + `XLEN'b10;
|
||||
assign PCPSpillF = PCPF + 2'b10; // *** modelsim does not allow the use of PA_BITS for literal width.
|
||||
|
||||
// now we have to select between these three PCs
|
||||
assign PCPreFinalF = PCMux[0] | StallF ? PCPF : PCNextF; // *** don't like the stallf, but it is necessary
|
||||
assign PCPFinalF = PCMux[1] ? PCSpillF : PCPreFinalF;
|
||||
assign PCNextIndexF = PCMux[1] ? PCPSpillF : PCPreFinalF;
|
||||
|
||||
// this mux needs to be delayed 1 cycle as it occurs 1 pipeline stage later.
|
||||
// *** read enable may not be necessary.
|
||||
@ -170,11 +170,10 @@ module ICacheCntrl #(parameter BLOCKLEN = 256) (
|
||||
.d(PCMux),
|
||||
.q(PCMux_q));
|
||||
|
||||
assign PCTagF = PCMux_q[1] ? PCSpillF : PCPF;
|
||||
assign PCNextIndexF = PCPFinalF;
|
||||
assign PCTagF = PCMux_q[1] ? PCPSpillF : PCPF;
|
||||
|
||||
// truncate the offset from PCPF for memory address generation
|
||||
assign PCPTrunkF = PCTagF[`XLEN-1:OFFSETWIDTH];
|
||||
assign PCPTrunkF = PCTagF[`PA_BITS-1:OFFSETWIDTH];
|
||||
|
||||
// Detect if the instruction is compressed
|
||||
assign CompressedF = FinalInstrRawF[1:0] != 2'b11;
|
||||
@ -395,7 +394,7 @@ module ICacheCntrl #(parameter BLOCKLEN = 256) (
|
||||
// we need to address on that number of bits so the PC is extended to the right by AHBByteLength with zeros.
|
||||
// fetch count is already aligned to AHBByteLength, but we need to extend back to the full address width with
|
||||
// more zeros after the addition. This will be the number of offset bits less the AHBByteLength.
|
||||
logic [`XLEN-1:OFFSETWIDTH-LOGWPL] PCPTrunkExtF, InstrPAdrTrunkF ;
|
||||
logic [`PA_BITS-1:OFFSETWIDTH-LOGWPL] PCPTrunkExtF, InstrPAdrTrunkF ;
|
||||
|
||||
assign PCPTrunkExtF = {PCPTrunkF, {{LOGWPL}{1'b0}}};
|
||||
// verilator lint_off WIDTH
|
||||
|
10
wally-pipelined/src/cache/ICacheMem.sv
vendored
10
wally-pipelined/src/cache/ICacheMem.sv
vendored
@ -8,8 +8,8 @@ module ICacheMem #(parameter NUMLINES=512, parameter BLOCKLEN = 256)
|
||||
// If flush is high, invalidate the entire cache
|
||||
input logic flush,
|
||||
|
||||
input logic [`XLEN-1:0] PCTagF, // physical address
|
||||
input logic [`XLEN-1:0] PCNextIndexF, // virtual address
|
||||
input logic [`PA_BITS-1:0] PCTagF, // physical address
|
||||
input logic [`PA_BITS-1:0] PCNextIndexF, // virtual address
|
||||
input logic WriteEnable,
|
||||
input logic [BLOCKLEN-1:0] WriteLine,
|
||||
output logic [BLOCKLEN-1:0] ReadLineF,
|
||||
@ -21,7 +21,7 @@ module ICacheMem #(parameter NUMLINES=512, parameter BLOCKLEN = 256)
|
||||
localparam OFFSETLEN = $clog2(BLOCKBYTELEN);
|
||||
localparam INDEXLEN = $clog2(NUMLINES);
|
||||
// *** BUG. `XLEN needs to be replaced with the virtual address width, S32, S39, or S48
|
||||
localparam TAGLEN = `XLEN - OFFSETLEN - INDEXLEN;
|
||||
localparam TAGLEN = `PA_BITS - OFFSETLEN - INDEXLEN;
|
||||
|
||||
logic [TAGLEN-1:0] LookupTag;
|
||||
logic [NUMLINES-1:0] ValidOut;
|
||||
@ -39,7 +39,7 @@ module ICacheMem #(parameter NUMLINES=512, parameter BLOCKLEN = 256)
|
||||
cachetags (.*,
|
||||
.Addr(PCNextIndexF[INDEXLEN+OFFSETLEN-1:OFFSETLEN]),
|
||||
.ReadData(LookupTag),
|
||||
.WriteData(PCTagF[`XLEN-1:INDEXLEN+OFFSETLEN])
|
||||
.WriteData(PCTagF[`PA_BITS-1:INDEXLEN+OFFSETLEN])
|
||||
);
|
||||
|
||||
// Correctly handle the valid bits
|
||||
@ -55,5 +55,5 @@ module ICacheMem #(parameter NUMLINES=512, parameter BLOCKLEN = 256)
|
||||
end
|
||||
DataValidBit <= ValidOut[PCNextIndexF[INDEXLEN+OFFSETLEN-1:OFFSETLEN]];
|
||||
end
|
||||
assign HitF = DataValidBit && (LookupTag == PCTagF[`XLEN-1:INDEXLEN+OFFSETLEN]);
|
||||
assign HitF = DataValidBit && (LookupTag == PCTagF[`PA_BITS-1:INDEXLEN+OFFSETLEN]);
|
||||
endmodule
|
||||
|
6
wally-pipelined/src/cache/icache.sv
vendored
6
wally-pipelined/src/cache/icache.sv
vendored
@ -31,8 +31,8 @@ module icache
|
||||
input logic clk, reset,
|
||||
input logic StallF, StallD,
|
||||
input logic FlushD,
|
||||
input logic [`XLEN-1:0] PCNextF,
|
||||
input logic [`XLEN-1:0] PCPF,
|
||||
input logic [`PA_BITS-1:0] PCNextF,
|
||||
input logic [`PA_BITS-1:0] PCPF,
|
||||
// Data read in from the ebu unit
|
||||
input logic [`XLEN-1:0] InstrInF,
|
||||
input logic InstrAckF,
|
||||
@ -58,7 +58,7 @@ module icache
|
||||
logic ICacheMemWriteEnable;
|
||||
logic [BLOCKLEN-1:0] ICacheMemWriteData;
|
||||
logic EndFetchState;
|
||||
logic [`XLEN-1:0] PCTagF, PCNextIndexF;
|
||||
logic [`PA_BITS-1:0] PCTagF, PCNextIndexF;
|
||||
// Output signals from cache memory
|
||||
logic [31:0] ICacheMemReadData;
|
||||
logic ICacheMemReadValid;
|
||||
|
@ -31,7 +31,7 @@ module dcache(
|
||||
input logic StallW,
|
||||
input logic FlushW,
|
||||
// Upper bits of physical address
|
||||
input logic [`XLEN-1:12] UpperPAdrM,
|
||||
input logic [`PA_BITS-1:12] UpperPAdrM,
|
||||
// Lower 12 bits of virtual address, since it's faster this way
|
||||
input logic [11:0] LowerVAdrM,
|
||||
// Write to the dcache
|
||||
@ -41,7 +41,7 @@ module dcache(
|
||||
input logic [`XLEN-1:0] ReadDataW,
|
||||
input logic MemAckW,
|
||||
// Access requested from the ebu unit
|
||||
output logic [`XLEN-1:0] MemPAdrM,
|
||||
output logic [`PA_BITS-1:0] MemPAdrM,
|
||||
output logic MemReadM, MemWriteM,
|
||||
// High if the dcache is requesting a stall
|
||||
output logic DCacheStallW,
|
||||
@ -56,7 +56,7 @@ module dcache(
|
||||
|
||||
// Input signals to cache memory
|
||||
logic FlushMem;
|
||||
logic [`XLEN-1:12] DCacheMemUpperPAdr;
|
||||
logic [`PA_BITS-1:12] DCacheMemUpperPAdr;
|
||||
logic [11:0] DCacheMemLowerAdr;
|
||||
logic DCacheMemWriteEnable;
|
||||
logic [DCACHELINESIZE-1:0] DCacheMemWriteData;
|
||||
@ -98,7 +98,7 @@ module dcachecontroller #(parameter LINESIZE = 256) (
|
||||
|
||||
// Input the address to read
|
||||
// The upper bits of the physical pc
|
||||
input logic [`XLEN-1:12] DCacheMemUpperPAdr,
|
||||
input logic [`PA_BITS-1:12] DCacheMemUpperPAdr,
|
||||
// The lower bits of the virtual pc
|
||||
input logic [11:0] DCacheMemLowerAdr,
|
||||
|
||||
@ -122,7 +122,7 @@ module dcachecontroller #(parameter LINESIZE = 256) (
|
||||
input logic [`XLEN-1:0] ReadDataW,
|
||||
input logic MemAckW,
|
||||
// The read we request from main memory
|
||||
output logic [`XLEN-1:0] MemPAdrM,
|
||||
output logic [`PA_BITS-1:0] MemPAdrM,
|
||||
output logic MemReadM, MemWriteM
|
||||
);
|
||||
|
||||
@ -144,7 +144,7 @@ module dcachecontroller #(parameter LINESIZE = 256) (
|
||||
|
||||
logic FetchState, BeginFetchState;
|
||||
logic [LOGWPL:0] FetchWordNum, NextFetchWordNum;
|
||||
logic [`XLEN-1:0] LineAlignedPCPF;
|
||||
logic [`PA_BITS-1:0] LineAlignedPCPF;
|
||||
|
||||
flopr #(1) FetchStateFlop(clk, reset, BeginFetchState | (FetchState & ~EndFetchState), FetchState);
|
||||
flopr #(LOGWPL+1) FetchWordNumFlop(clk, reset, NextFetchWordNum, FetchWordNum);
|
||||
|
@ -40,7 +40,7 @@ module dmem (
|
||||
input logic [`XLEN-1:0] WriteDataM,
|
||||
input logic [1:0] AtomicM,
|
||||
input logic CommitM,
|
||||
output logic [`XLEN-1:0] MemPAdrM,
|
||||
output logic [`PA_BITS-1:0] MemPAdrM,
|
||||
output logic MemReadM, MemWriteM,
|
||||
output logic [1:0] AtomicMaskedM,
|
||||
output logic DataMisalignedM,
|
||||
@ -142,20 +142,20 @@ module dmem (
|
||||
// Handle atomic load reserved / store conditional
|
||||
generate
|
||||
if (`A_SUPPORTED) begin // atomic instructions supported
|
||||
logic [`XLEN-1:2] ReservationPAdrW;
|
||||
logic [`PA_BITS-1:2] ReservationPAdrW;
|
||||
logic ReservationValidM, ReservationValidW;
|
||||
logic lrM, scM, WriteAdrMatchM;
|
||||
|
||||
assign lrM = MemReadM && AtomicM[0];
|
||||
assign scM = MemRWM[0] && AtomicM[0];
|
||||
assign WriteAdrMatchM = MemRWM[0] && (MemPAdrM[`XLEN-1:2] == ReservationPAdrW) && ReservationValidW;
|
||||
assign WriteAdrMatchM = MemRWM[0] && (MemPAdrM[`PA_BITS-1:2] == ReservationPAdrW) && ReservationValidW;
|
||||
assign SquashSCM = scM && ~WriteAdrMatchM;
|
||||
always_comb begin // ReservationValidM (next value of valid reservation)
|
||||
if (lrM) ReservationValidM = 1; // set valid on load reserve
|
||||
else if (scM || WriteAdrMatchM) ReservationValidM = 0; // clear valid on store to same address or any sc
|
||||
else ReservationValidM = ReservationValidW; // otherwise don't change valid
|
||||
end
|
||||
flopenrc #(`XLEN-2) resadrreg(clk, reset, FlushW, lrM, MemPAdrM[`XLEN-1:2], ReservationPAdrW); // could drop clear on this one but not valid
|
||||
flopenrc #(`PA_BITS-2) resadrreg(clk, reset, FlushW, lrM, MemPAdrM[`PA_BITS-1:2], ReservationPAdrW); // could drop clear on this one but not valid
|
||||
flopenrc #(1) resvldreg(clk, reset, FlushW, lrM, ReservationValidM, ReservationValidW);
|
||||
flopenrc #(1) squashreg(clk, reset, FlushW, ~StallW, SquashSCM, SquashSCW);
|
||||
end else begin // Atomic operations not supported
|
||||
|
@ -47,7 +47,7 @@ module ahblite (
|
||||
output logic [`XLEN-1:0] InstrRData,
|
||||
output logic InstrAckF,
|
||||
// Signals from Data Cache
|
||||
input logic [`XLEN-1:0] MemPAdrM,
|
||||
input logic [`PA_BITS-1:0] MemPAdrM,
|
||||
input logic MemReadM, MemWriteM,
|
||||
input logic [`XLEN-1:0] WriteDataM,
|
||||
input logic [1:0] MemSizeM,
|
||||
|
@ -105,10 +105,19 @@ module ifu (
|
||||
logic PMPLoadAccessFaultM, PMPStoreAccessFaultM; // *** these are just so that the mmu has somewhere to put these outputs, they're unused in this stage
|
||||
// if you're allowed to parameterize outputs/ inputs existence, these are an easy delete.
|
||||
|
||||
logic [`PA_BITS-1:0] PCPFmmu;
|
||||
|
||||
generate
|
||||
if (`XLEN==32)
|
||||
assign PCPF = PCPFmmu[31:0];
|
||||
else
|
||||
assign PCPF = {8'b0, PCPFmmu};
|
||||
endgenerate
|
||||
|
||||
mmu #(.ENTRY_BITS(`ITLB_ENTRY_BITS), .IMMU(1)) itlb(.TLBAccessType(2'b10), .VirtualAddress(PCF),
|
||||
.PTEWriteVal(PageTableEntryF), .PageTypeWriteVal(PageTypeF),
|
||||
.TLBWrite(ITLBWriteF), .TLBFlush(ITLBFlushF),
|
||||
.PhysicalAddress(PCPF), .TLBMiss(ITLBMissF),
|
||||
.PhysicalAddress(PCPFmmu), .TLBMiss(ITLBMissF),
|
||||
.TLBHit(ITLBHitF), .TLBPageFault(ITLBInstrPageFaultF),
|
||||
|
||||
.AtomicAccessM(1'b0), .WriteAccessM(1'b0), .ReadAccessM(1'b0), // *** is this the right way force these bits constant? should they be someething else?
|
||||
@ -129,7 +138,9 @@ module ifu (
|
||||
|
||||
// jarred 2021-03-14 Add instrution cache block to remove rd2
|
||||
assign PCNextPF = PCNextF; // Temporary workaround until iTLB is live
|
||||
icache icache(.*);
|
||||
icache icache(.*,
|
||||
.PCNextF(PCNextF[`PA_BITS-1:0]),
|
||||
.PCPF(PCPFmmu));
|
||||
|
||||
|
||||
|
||||
|
@ -57,7 +57,7 @@ module mmu #(parameter ENTRY_BITS = 3,
|
||||
input logic TLBFlush,
|
||||
|
||||
// Physical address outputs
|
||||
output logic [`XLEN-1:0] PhysicalAddress,
|
||||
output logic [`PA_BITS-1:0] PhysicalAddress,
|
||||
output logic TLBMiss,
|
||||
output logic TLBHit,
|
||||
|
||||
|
52
wally-pipelined/src/mmu/pmaadrdec.sv
Normal file
52
wally-pipelined/src/mmu/pmaadrdec.sv
Normal file
@ -0,0 +1,52 @@
|
||||
///////////////////////////////////////////
|
||||
// pmaadrdec.sv
|
||||
//
|
||||
// Written: David_Harris@hmc.edu 29 January 2021
|
||||
// Modified:
|
||||
//
|
||||
// Purpose: Address decoder
|
||||
//
|
||||
// A component of the Wally configurable RISC-V project.
|
||||
//
|
||||
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
|
||||
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
|
||||
// is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
|
||||
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
///////////////////////////////////////////
|
||||
|
||||
`include "wally-config.vh"
|
||||
|
||||
module pmaadrdec (
|
||||
input logic [31:0] HADDR,
|
||||
input logic [31:0] Base, Range,
|
||||
input logic Supported,
|
||||
input logic AccessValid,
|
||||
input logic [2:0] Size,
|
||||
input logic [3:0] SizeMask,
|
||||
output logic HSEL
|
||||
);
|
||||
|
||||
logic Match;
|
||||
logic SizeValid;
|
||||
|
||||
// determine if an address is in a range starting at the base
|
||||
// for example, if Base = 0x04002000 and range = 0x00000FFF,
|
||||
// then anything address between 0x04002000 and 0x04002FFF should match (HSEL=1)
|
||||
assign Match = &((HADDR ~^ Base) | Range);
|
||||
|
||||
// determine if legal size of access is being made (byte, halfword, word, doubleword)
|
||||
assign SizeValid = SizeMask[Size[1:0]];
|
||||
|
||||
assign HSEL = Match && Supported && AccessValid && SizeValid;
|
||||
|
||||
endmodule
|
||||
|
@ -46,85 +46,33 @@ module pmachecker (
|
||||
output logic PMAStoreAccessFaultM
|
||||
);
|
||||
|
||||
// Signals are high if the memory access is within the given region
|
||||
logic BootTim, Tim, CLINT, GPIO, UART, PLIC;
|
||||
logic [5:0] Regions;
|
||||
// logic BootTim, Tim, CLINT, GPIO, UART, PLIC;
|
||||
logic PMAAccessFault;
|
||||
logic AccessRW, AccessRWX, AccessRX;
|
||||
|
||||
// Actual HSEL signals sent to uncore
|
||||
logic HSELBootTim, HSELTim, HSELCLINT, HSELGPIO, HSELUART, HSELPLIC;
|
||||
logic ValidBootTim, ValidTim, ValidCLINT, ValidGPIO, ValidUART, ValidPLIC;
|
||||
|
||||
// Attributes of memory region accessed
|
||||
logic Executable, Readable, Writable;
|
||||
|
||||
logic Fault;
|
||||
|
||||
attributes attributes(.Address(HADDR), .*);
|
||||
|
||||
// Unswizzle region bits
|
||||
assign {BootTim, Tim, CLINT, GPIO, UART, PLIC} = Regions;
|
||||
|
||||
assign ValidBootTim = '1;
|
||||
assign ValidTim = '1;
|
||||
assign ValidCLINT = ~ExecuteAccessF && ((HSIZE == 3'b011 && `XLEN==64) || (HSIZE == 3'b010 && `XLEN==32));
|
||||
assign ValidGPIO = ~ExecuteAccessF && (HSIZE == 3'b010);
|
||||
assign ValidUART = ~ExecuteAccessF && (HSIZE == 3'b000);
|
||||
assign ValidPLIC = ~ExecuteAccessF && (HSIZE == 3'b010);
|
||||
|
||||
assign HSELBootTim = BootTim && ValidBootTim;
|
||||
assign HSELTim = Tim && ValidTim;
|
||||
assign HSELCLINT = CLINT && ValidCLINT;
|
||||
assign HSELGPIO = GPIO && ValidGPIO;
|
||||
assign HSELUART = UART && ValidUART; // only byte writes to UART are supported
|
||||
assign HSELPLIC = PLIC && ValidPLIC;
|
||||
|
||||
// Swizzle region bits
|
||||
assign HSELRegions = {HSELBootTim, HSELTim, HSELCLINT, HSELGPIO, HSELUART, HSELPLIC};
|
||||
|
||||
assign Fault = ~|HSELRegions;
|
||||
|
||||
assign PMAInstrAccessFaultF = ExecuteAccessF && Fault;
|
||||
assign PMALoadAccessFaultM = ReadAccessM && Fault;
|
||||
assign PMAStoreAccessFaultM = WriteAccessM && Fault;
|
||||
|
||||
assign PMASquashBusAccess = PMAInstrAccessFaultF || PMALoadAccessFaultM || PMAStoreAccessFaultM;
|
||||
|
||||
endmodule
|
||||
|
||||
module attributes (
|
||||
// input logic clk, reset, // *** unused in this module and all sub modules.
|
||||
|
||||
input logic [31:0] Address,
|
||||
|
||||
output logic [5:0] Regions,
|
||||
|
||||
output logic Cacheable, Idempotent, AtomicAllowed,
|
||||
output logic Executable, Readable, Writable
|
||||
);
|
||||
|
||||
// Signals are high if the memory access is within the given region
|
||||
logic BootTim, Tim, CLINT, GPIO, UART, PLIC;
|
||||
// Determine what type of access is being made
|
||||
assign AccessRW = ReadAccessM | WriteAccessM;
|
||||
assign AccessRWX = ReadAccessM | WriteAccessM | ExecuteAccessF;
|
||||
assign AccessRX = ReadAccessM | ExecuteAccessF;
|
||||
|
||||
// Determine which region of physical memory (if any) is being accessed
|
||||
adrdec boottimdec(Address, `BOOTTIMBASE, `BOOTTIMRANGE, BootTim);
|
||||
adrdec timdec(Address, `TIMBASE, `TIMRANGE, Tim);
|
||||
adrdec clintdec(Address, `CLINTBASE, `CLINTRANGE, CLINT);
|
||||
adrdec gpiodec(Address, `GPIOBASE, `GPIORANGE, GPIO);
|
||||
adrdec uartdec(Address, `UARTBASE, `UARTRANGE, UART);
|
||||
adrdec plicdec(Address, `PLICBASE, `PLICRANGE, PLIC);
|
||||
|
||||
// Swizzle region bits
|
||||
assign Regions = {BootTim, Tim, CLINT, GPIO, UART, PLIC};
|
||||
// *** linux tests fail early when Access is anything other than 1b1
|
||||
pmaadrdec boottimdec(HADDR, `BOOTTIM_BASE, `BOOTTIM_RANGE, `BOOTTIM_SUPPORTED, 1'b1/*AccessRX*/, HSIZE, 4'b1111, HSELRegions[5]);
|
||||
pmaadrdec timdec(HADDR, `TIM_BASE, `TIM_RANGE, `TIM_SUPPORTED, 1'b1/*AccessRWX*/, HSIZE, 4'b1111, HSELRegions[4]);
|
||||
pmaadrdec clintdec(HADDR, `CLINT_BASE, `CLINT_RANGE, `CLINT_SUPPORTED, AccessRW, HSIZE, 4'b1111, HSELRegions[3]);
|
||||
pmaadrdec gpiodec(HADDR, `GPIO_BASE, `GPIO_RANGE, `GPIO_SUPPORTED, AccessRW, HSIZE, 4'b0100, HSELRegions[2]);
|
||||
pmaadrdec uartdec(HADDR, `UART_BASE, `UART_RANGE, `UART_SUPPORTED, AccessRW, HSIZE, 4'b0001, HSELRegions[1]);
|
||||
pmaadrdec plicdec(HADDR, `PLIC_BASE, `PLIC_RANGE, `PLIC_SUPPORTED, AccessRW, HSIZE, 4'b0100, HSELRegions[0]);
|
||||
|
||||
// Only RAM memory regions are cacheable
|
||||
assign Cacheable = BootTim | Tim;
|
||||
|
||||
assign Idempotent = BootTim | Tim;
|
||||
|
||||
assign AtomicAllowed = BootTim | Tim;
|
||||
|
||||
assign Executable = BootTim | Tim;
|
||||
assign Readable = BootTim | Tim | CLINT | GPIO | UART | PLIC;
|
||||
assign Writable = BootTim | Tim | CLINT | GPIO | UART | PLIC;
|
||||
assign Cacheable = HSELRegions[5] | HSELRegions[4];
|
||||
assign Idempotent = HSELRegions[4];
|
||||
assign AtomicAllowed = HSELRegions[4];
|
||||
|
||||
// Detect access faults
|
||||
assign PMAAccessFault = (~|HSELRegions) && AccessRWX;
|
||||
assign PMAInstrAccessFaultF = ExecuteAccessF && PMAAccessFault;
|
||||
assign PMALoadAccessFaultM = ReadAccessM && PMAAccessFault;
|
||||
assign PMAStoreAccessFaultM = WriteAccessM && PMAAccessFault;
|
||||
assign PMASquashBusAccess = PMAAccessFault;
|
||||
endmodule
|
||||
|
@ -78,7 +78,7 @@ module tlb #(parameter ENTRY_BITS = 3,
|
||||
input logic TLBFlush,
|
||||
|
||||
// Physical address outputs
|
||||
output logic [`XLEN-1:0] PhysicalAddress,
|
||||
output logic [`PA_BITS-1:0] PhysicalAddress,
|
||||
output logic TLBMiss,
|
||||
output logic TLBHit,
|
||||
|
||||
@ -202,11 +202,9 @@ module tlb #(parameter ENTRY_BITS = 3,
|
||||
// Output the hit physical address if translation is currently on.
|
||||
generate
|
||||
if (`XLEN == 32) begin
|
||||
// *** If we want rv32 to use the full 34 bit physical address space, this
|
||||
// must be changed
|
||||
mux2 #(`XLEN) addressmux(VirtualAddress, PhysicalAddressFull[31:0], Translate, PhysicalAddress);
|
||||
mux2 #(`PA_BITS) addressmux({2'b0, VirtualAddress}, PhysicalAddressFull, Translate, PhysicalAddress);
|
||||
end else begin
|
||||
mux2 #(`XLEN) addressmux(VirtualAddress, {8'b0, PhysicalAddressFull}, Translate, PhysicalAddress);
|
||||
mux2 #(`PA_BITS) addressmux(VirtualAddress[`PA_BITS-1:0], PhysicalAddressFull, Translate, PhysicalAddress);
|
||||
end
|
||||
endgenerate
|
||||
|
||||
|
@ -39,6 +39,7 @@ module csr #(parameter
|
||||
input logic InterruptM,
|
||||
input logic CSRReadM, CSRWriteM, TrapM, MTrapM, STrapM, UTrapM, mretM, sretM, uretM,
|
||||
input logic TimerIntM, ExtIntM, SwIntM,
|
||||
input logic [63:0] MTIME_CLINT, MTIMECMP_CLINT,
|
||||
input logic InstrValidW, FloatRegWriteW, LoadStallD,
|
||||
input logic BPPredDirWrongM,
|
||||
input logic BTBPredPCWrongM,
|
||||
@ -55,7 +56,7 @@ module csr #(parameter
|
||||
output logic [`XLEN-1:0] MEPC_REGW, SEPC_REGW, UEPC_REGW, UTVEC_REGW, STVEC_REGW, MTVEC_REGW,
|
||||
output logic [`XLEN-1:0] MEDELEG_REGW, MIDELEG_REGW, SEDELEG_REGW, SIDELEG_REGW,
|
||||
output logic [`XLEN-1:0] SATP_REGW,
|
||||
output logic [11:0] MIP_REGW, MIE_REGW,
|
||||
output logic [11:0] MIP_REGW, MIE_REGW, SIP_REGW, SIE_REGW,
|
||||
output logic STATUS_MIE, STATUS_SIE,
|
||||
output logic STATUS_MXR, STATUS_SUM,
|
||||
output logic STATUS_MPRV,
|
||||
@ -80,7 +81,6 @@ module csr #(parameter
|
||||
logic [`XLEN-1:0] UnalignedNextEPCM, NextEPCM, NextCauseM, NextMtvalM;
|
||||
|
||||
logic [11:0] CSRAdrM;
|
||||
logic [11:0] SIP_REGW, SIE_REGW;
|
||||
//logic [11:0] UIP_REGW, UIE_REGW = 0; // N user-mode exceptions not supported
|
||||
logic IllegalCSRCAccessM, IllegalCSRMAccessM, IllegalCSRSAccessM, IllegalCSRUAccessM, IllegalCSRNAccessM, InsufficientCSRPrivilegeM;
|
||||
logic IllegalCSRMWriteReadonlyM;
|
||||
|
@ -27,11 +27,11 @@
|
||||
///////////////////////////////////////////
|
||||
|
||||
`include "wally-config.vh"
|
||||
|
||||
// Ben 06/17/21: I brought in MTIME, MTIMECMP from CLINT. *** this probably isn't perfect though because it doesn't yet provide the ability to change these through CSR writes; overall this whole thing might need some rethinking
|
||||
module csrc #(parameter
|
||||
MCYCLE = 12'hB00,
|
||||
// MTIME = 12'hB01, // address not specified in privileged spec. Consider moving to CLINT to match SiFive
|
||||
// MTIMECMP = 12'hB21, // not specified in privileged spec. Move to CLINT
|
||||
MTIME = 12'hB01, // address not specified in privileged spec. Consider moving to CLINT to match SiFive
|
||||
MTIMECMP = 12'hB21, // not specified in privileged spec. Move to CLINT
|
||||
MINSTRET = 12'hB02,
|
||||
MHPMCOUNTERBASE = 12'hB00,
|
||||
//MHPMCOUNTER3 = 12'hB03,
|
||||
@ -39,8 +39,8 @@ module csrc #(parameter
|
||||
// ... more counters
|
||||
//MHPMCOUNTER31 = 12'hB1F,
|
||||
MCYCLEH = 12'hB80,
|
||||
// MTIMEH = 12'hB81, // address not specified in privileged spec. Consider moving to CLINT to match SiFive
|
||||
// MTIMECMPH = 12'hBA1, // not specified in privileged spec. Move to CLINT
|
||||
MTIMEH = 12'hB81, // address not specified in privileged spec. Consider moving to CLINT to match SiFive
|
||||
MTIMECMPH = 12'hBA1, // not specified in privileged spec. Move to CLINT
|
||||
MINSTRETH = 12'hB82,
|
||||
MHPMCOUNTERHBASE = 12'hB80,
|
||||
//MHPMCOUNTER3H = 12'hB83,
|
||||
@ -54,7 +54,7 @@ module csrc #(parameter
|
||||
// ... more counters
|
||||
//MHPMEVENT31 = 12'h33F,
|
||||
CYCLE = 12'hC00,
|
||||
// TIME = 12'hC01, // not specified
|
||||
TIME = 12'hC01,
|
||||
INSTRET = 12'hC02,
|
||||
HPMCOUNTERBASE = 12'hC00,
|
||||
//HPMCOUNTER3 = 12'hC03,
|
||||
@ -62,7 +62,7 @@ module csrc #(parameter
|
||||
// ...more counters
|
||||
//HPMCOUNTER31 = 12'hC1F,
|
||||
CYCLEH = 12'hC80,
|
||||
// TIMEH = 12'hC81, // not specified
|
||||
TIMEH = 12'hC81, // not specified
|
||||
INSTRETH = 12'hC82,
|
||||
HPMCOUNTERHBASE = 12'hC80
|
||||
//HPMCOUNTER3H = 12'hC83,
|
||||
@ -71,17 +71,18 @@ module csrc #(parameter
|
||||
//HPMCOUNTER31H = 12'hC9F
|
||||
) (
|
||||
input logic clk, reset,
|
||||
input logic StallD, StallE, StallM, StallW,
|
||||
input logic StallD, StallE, StallM, StallW,
|
||||
input logic InstrValidW, LoadStallD, CSRMWriteM,
|
||||
input logic BPPredDirWrongM,
|
||||
input logic BTBPredPCWrongM,
|
||||
input logic RASPredPCWrongM,
|
||||
input logic BPPredClassNonCFIWrongM,
|
||||
input logic [4:0] InstrClassM,
|
||||
input logic BPPredDirWrongM,
|
||||
input logic BTBPredPCWrongM,
|
||||
input logic RASPredPCWrongM,
|
||||
input logic BPPredClassNonCFIWrongM,
|
||||
input logic [4:0] InstrClassM,
|
||||
input logic [11:0] CSRAdrM,
|
||||
input logic [1:0] PrivilegeModeW,
|
||||
input logic [`XLEN-1:0] CSRWriteValM,
|
||||
input logic [31:0] MCOUNTINHIBIT_REGW, MCOUNTEREN_REGW, SCOUNTEREN_REGW,
|
||||
input logic [63:0] MTIME_CLINT, MTIMECMP_CLINT,
|
||||
output logic [`XLEN-1:0] CSRCReadValM,
|
||||
output logic IllegalCSRCAccessM
|
||||
);
|
||||
@ -112,12 +113,12 @@ module csrc #(parameter
|
||||
|
||||
// Counter adders with inhibits for power savings
|
||||
assign CYCLEPlusM = CYCLE_REGW + {63'b0, ~MCOUNTINHIBIT_REGW[0]};
|
||||
// assign TIMEPlusM = TIME_REGW + 1; // can't be inhibited
|
||||
//assign TIMEPlusM = TIME_REGW + 1; // can't be inhibited
|
||||
assign INSTRETPlusM = INSTRET_REGW + {63'b0, InstrValidW & ~MCOUNTINHIBIT_REGW[2]};
|
||||
//assign HPMCOUNTER3PlusM = HPMCOUNTER3_REGW + {63'b0, LoadStallD & ~MCOUNTINHIBIT_REGW[3]}; // count load stalls
|
||||
///assign HPMCOUNTER4PlusM = HPMCOUNTER4_REGW + {63'b0, 1'b0 & ~MCOUNTINHIBIT_REGW[4]}; // change to count signals
|
||||
//assign HPMCOUNTER4PlusM = HPMCOUNTER4_REGW + {63'b0, 1'b0 & ~MCOUNTINHIBIT_REGW[4]}; // change to count signals
|
||||
assign NextCYCLEM = WriteCYCLEM ? CSRWriteValM : CYCLEPlusM[`XLEN-1:0];
|
||||
// assign NextTIMEM = WriteTIMEM ? CSRWriteValM : TIMEPlusM[`XLEN-1:0];
|
||||
//assign NextTIMEM = WriteTIMEM ? CSRWriteValM : TIMEPlusM[`XLEN-1:0];
|
||||
assign NextINSTRETM = WriteINSTRETM ? CSRWriteValM : INSTRETPlusM[`XLEN-1:0];
|
||||
//assign NextHPMCOUNTER3M = WriteHPMCOUNTER3M ? CSRWriteValM : HPMCOUNTER3PlusM[`XLEN-1:0];
|
||||
//assign NextHPMCOUNTER4M = WriteHPMCOUNTER4M ? CSRWriteValM : HPMCOUNTER4PlusM[`XLEN-1:0];
|
||||
@ -211,7 +212,7 @@ module csrc #(parameter
|
||||
//flopr #(32) HPMCOUNTER4Hreg(clk, reset, NextHPMCOUNTER4HM, HPMCOUNTER4_REGW[63:32]);
|
||||
end
|
||||
|
||||
// eventually move TIME and TIMECMP to the CLINT
|
||||
// eventually move TIME and TIMECMP to the CLINT -- Ben 06/17/21: sure let's give that a shot!
|
||||
// run TIME off asynchronous reference clock
|
||||
// synchronize write enable to TIME
|
||||
// four phase handshake to synchronize reads from TIME
|
||||
@ -229,13 +230,13 @@ module csrc #(parameter
|
||||
if (CSRAdrM >= MHPMCOUNTERBASE+3 && CSRAdrM < MHPMCOUNTERBASE+`COUNTERS) CSRCReadValM = HPMCOUNTER_REGW[CSRAdrM-MHPMCOUNTERBASE];
|
||||
else if (CSRAdrM >= HPMCOUNTERBASE+3 && CSRAdrM < HPMCOUNTERBASE+`COUNTERS) CSRCReadValM = HPMCOUNTER_REGW[CSRAdrM-HPMCOUNTERBASE];
|
||||
else case (CSRAdrM)
|
||||
// MTIME: CSRCReadValM = TIME_REGW;
|
||||
// MTIMECMP: CSRCReadValM = TIMECMP_REGW;
|
||||
MTIME: CSRCReadValM = MTIME_CLINT;
|
||||
MTIMECMP: CSRCReadValM = MTIMECMP_CLINT;
|
||||
MCYCLE: CSRCReadValM = CYCLE_REGW;
|
||||
MINSTRET: CSRCReadValM = INSTRET_REGW;
|
||||
//MHPMCOUNTER3: CSRCReadValM = HPMCOUNTER3_REGW;
|
||||
//MHPMCOUNTER4: CSRCReadValM = HPMCOUNTER4_REGW;
|
||||
// TIME: CSRCReadValM = TIME_REGW;
|
||||
TIME: CSRCReadValM = MTIME_CLINT;
|
||||
CYCLE: CSRCReadValM = CYCLE_REGW;
|
||||
INSTRET: CSRCReadValM = INSTRET_REGW;
|
||||
//HPMCOUNTER3: CSRCReadValM = HPMCOUNTER3_REGW;
|
||||
@ -258,24 +259,24 @@ module csrc #(parameter
|
||||
else if (CSRAdrM >= MHPMCOUNTERHBASE+3 && CSRAdrM < MHPMCOUNTERHBASE+`COUNTERS) CSRCReadValM = HPMCOUNTERH_REGW[CSRAdrM-MHPMCOUNTERHBASE];
|
||||
else if (CSRAdrM >= HPMCOUNTERHBASE+3 && CSRAdrM < HPMCOUNTERHBASE+`COUNTERS) CSRCReadValM = HPMCOUNTERH_REGW[CSRAdrM-HPMCOUNTERHBASE];
|
||||
else case (CSRAdrM)
|
||||
// MTIME: CSRCReadValM = TIME_REGW[31:0];
|
||||
// MTIMECMP: CSRCReadValM = TIMECMP_REGW[31:0];
|
||||
MTIME: CSRCReadValM = MTIME_CLINT[31:0];
|
||||
MTIMECMP: CSRCReadValM = MTIMECMP_CLINT[31:0];
|
||||
MCYCLE: CSRCReadValM = CYCLE_REGW[31:0];
|
||||
MINSTRET: CSRCReadValM = INSTRET_REGW[31:0];
|
||||
//MHPMCOUNTER3: CSRCReadValM = HPMCOUNTER3_REGW[31:0];
|
||||
//MHPMCOUNTER4: CSRCReadValM = HPMCOUNTER4_REGW[31:0];
|
||||
// TIME: CSRCReadValM = TIME_REGW[31:0];
|
||||
TIME: CSRCReadValM = MTIME_CLINT[31:0];
|
||||
CYCLE: CSRCReadValM = CYCLE_REGW[31:0];
|
||||
INSTRET: CSRCReadValM = INSTRET_REGW[31:0];
|
||||
//HPMCOUNTER3: CSRCReadValM = HPMCOUNTER3_REGW[31:0];
|
||||
//HPMCOUNTER4: CSRCReadValM = HPMCOUNTER4_REGW[31:0];
|
||||
// MTIMEH: CSRCReadValM = TIME_REGW[63:32];
|
||||
// MTIMECMPH: CSRCReadValM = TIMECMP_REGW[63:32];
|
||||
MTIMEH: CSRCReadValM = MTIME_CLINT[63:32];
|
||||
MTIMECMPH: CSRCReadValM = MTIMECMP_CLINT[63:32];
|
||||
MCYCLEH: CSRCReadValM = CYCLE_REGW[63:32];
|
||||
MINSTRETH: CSRCReadValM = INSTRET_REGW[63:32];
|
||||
//MHPMCOUNTER3H: CSRCReadValM = HPMCOUNTER3_REGW[63:32];
|
||||
//MHPMCOUNTER4H: CSRCReadValM = HPMCOUNTER4_REGW[63:32];
|
||||
// TIMEH: CSRCReadValM = TIME_REGW[63:32];
|
||||
TIMEH: CSRCReadValM = MTIME_CLINT[63:32];
|
||||
CYCLEH: CSRCReadValM = CYCLE_REGW[63:32];
|
||||
INSTRETH: CSRCReadValM = INSTRET_REGW[63:32];
|
||||
//HPMCOUNTER3H: CSRCReadValM = HPMCOUNTER3_REGW[63:32];
|
||||
|
@ -172,7 +172,7 @@ module csrm #(parameter
|
||||
// There are PMP_ENTRIES = 0, 16, or 64 PMPADDR registers, each of which has its own flop
|
||||
generate
|
||||
genvar i;
|
||||
for (i = 0; i < `PMP_ENTRIES-1; i++) begin: pmp_flop
|
||||
for (i = 0; i < `PMP_ENTRIES; i++) begin: pmp_flop
|
||||
flopenr #(`XLEN) PMPADDRreg(clk, reset, WritePMPADDRM[i], CSRWriteValM, PMPADDR_ARRAY_REGW[i]);
|
||||
end
|
||||
endgenerate
|
||||
|
@ -52,6 +52,7 @@ module privileged (
|
||||
input logic LoadMisalignedFaultM,
|
||||
input logic StoreMisalignedFaultM,
|
||||
input logic TimerIntM, ExtIntM, SwIntM,
|
||||
input logic [63:0] MTIME_CLINT, MTIMECMP_CLINT,
|
||||
input logic [`XLEN-1:0] InstrMisalignedAdrM, MemAdrM,
|
||||
input logic [4:0] SetFflagsM,
|
||||
|
||||
@ -96,7 +97,7 @@ module privileged (
|
||||
logic [1:0] STATUS_MPP;
|
||||
logic STATUS_SPP, STATUS_TSR, STATUS_MPRV; // **** status mprv is unused outside of the csr module as of 4 June 2021. should it be deleted alltogether from the module, or should I leav the pin here in case someone needs it?
|
||||
logic STATUS_MIE, STATUS_SIE;
|
||||
logic [11:0] MIP_REGW, MIE_REGW;
|
||||
logic [11:0] MIP_REGW, MIE_REGW, SIP_REGW, SIE_REGW;
|
||||
logic md, sd;
|
||||
|
||||
|
||||
|
@ -35,7 +35,7 @@ module trap (
|
||||
input logic mretM, sretM, uretM,
|
||||
input logic [1:0] PrivilegeModeW, NextPrivilegeModeM,
|
||||
input logic [`XLEN-1:0] MEPC_REGW, SEPC_REGW, UEPC_REGW, UTVEC_REGW, STVEC_REGW, MTVEC_REGW,
|
||||
input logic [11:0] MIP_REGW, MIE_REGW,
|
||||
input logic [11:0] MIP_REGW, MIE_REGW, SIP_REGW, SIE_REGW,
|
||||
input logic STATUS_MIE, STATUS_SIE,
|
||||
input logic [`XLEN-1:0] PCM,
|
||||
input logic [`XLEN-1:0] InstrMisalignedAdrM, MemAdrM,
|
||||
@ -58,7 +58,7 @@ module trap (
|
||||
// Determine pending enabled interrupts
|
||||
assign MIntGlobalEnM = (PrivilegeModeW != `M_MODE) || STATUS_MIE; // if M ints enabled or lower priv 3.1.9
|
||||
assign SIntGlobalEnM = (PrivilegeModeW == `U_MODE) || STATUS_SIE; // if S ints enabled or lower priv 3.1.9
|
||||
assign PendingIntsM = (MIP_REGW & MIE_REGW) & ({12{MIntGlobalEnM}} & 12'h888) | ({12{SIntGlobalEnM}} & 12'h222);
|
||||
assign PendingIntsM = ((MIP_REGW & MIE_REGW) & ({12{MIntGlobalEnM}} & 12'h888)) | ((SIP_REGW & SIE_REGW) & ({12{SIntGlobalEnM}} & 12'h222));
|
||||
assign InterruptM = (|PendingIntsM) & InstrValidM & ~CommittedM;
|
||||
// interrupt if any sources are pending
|
||||
// & with a M stage valid bit to avoid interrupts from interrupt a nonexistent flushed instruction (in the M stage)
|
||||
|
@ -27,22 +27,22 @@
|
||||
`include "wally-config.vh"
|
||||
|
||||
module clint (
|
||||
input logic HCLK, HRESETn,
|
||||
input logic HSELCLINT,
|
||||
input logic [15:0] HADDR,
|
||||
input logic HWRITE,
|
||||
input logic [`XLEN-1:0] HWDATA,
|
||||
output logic [`XLEN-1:0] HREADCLINT,
|
||||
output logic HRESPCLINT, HREADYCLINT,
|
||||
input logic HCLK, HRESETn,
|
||||
input logic HSELCLINT,
|
||||
input logic [15:0] HADDR,
|
||||
input logic HWRITE,
|
||||
input logic [`XLEN-1:0] HWDATA,
|
||||
input logic HREADY,
|
||||
input logic [1:0] HTRANS,
|
||||
output logic TimerIntM, SwIntM);
|
||||
input logic [1:0] HTRANS,
|
||||
output logic [`XLEN-1:0] HREADCLINT,
|
||||
output logic HRESPCLINT, HREADYCLINT,
|
||||
output logic [63:0] MTIME, MTIMECMP,
|
||||
output logic TimerIntM, SwIntM);
|
||||
|
||||
logic [63:0] MTIMECMP, MTIME;
|
||||
logic MSIP;
|
||||
|
||||
logic [15:0] entry, entryd;
|
||||
logic memread, memwrite;
|
||||
logic memread, memwrite;
|
||||
logic initTrans;
|
||||
|
||||
assign initTrans = HREADY & HSELCLINT & (HTRANS != 2'b00);
|
||||
|
@ -32,8 +32,8 @@ module imem (
|
||||
output logic InstrAccessFaultF);
|
||||
|
||||
/* verilator lint_off UNDRIVEN */
|
||||
logic [`XLEN-1:0] RAM[`TIMBASE>>(1+`XLEN/32):(`TIMRANGE+`TIMBASE)>>(1+`XLEN/32)];
|
||||
logic [`XLEN-1:0] bootram[`BOOTTIMBASE>>(1+`XLEN/32):(`BOOTTIMRANGE+`BOOTTIMBASE)>>(1+`XLEN/32)];
|
||||
logic [`XLEN-1:0] RAM[`TIM_BASE>>(1+`XLEN/32):(`TIM_RANGE+`TIM_BASE)>>(1+`XLEN/32)];
|
||||
logic [`XLEN-1:0] bootram[`BOOTTIM_BASE>>(1+`XLEN/32):(`BOOTTIM_RANGE+`BOOTTIM_BASE)>>(1+`XLEN/32)];
|
||||
/* verilator lint_on UNDRIVEN */
|
||||
logic [31:0] adrbits; // needs to be 32 bits to index RAM
|
||||
logic [`XLEN-1:0] rd;
|
||||
@ -44,27 +44,27 @@ module imem (
|
||||
else assign adrbits = AdrF[31:3];
|
||||
endgenerate
|
||||
|
||||
assign #2 rd = (AdrF < (`TIMBASE >> 1)) ? bootram[adrbits] : RAM[adrbits]; // busybear: 2 memory options
|
||||
assign #2 rd = (AdrF < (`TIM_BASE >> 1)) ? bootram[adrbits] : RAM[adrbits]; // busybear: 2 memory options
|
||||
|
||||
// hack right now for unaligned 32-bit instructions
|
||||
// eventually this will need to cause a stall like a cache miss
|
||||
// when the instruction wraps around a cache line
|
||||
// could be optimized to only stall when the instruction wrapping is 32 bits
|
||||
assign #2 rd2 = (AdrF < (`TIMBASE >> 1)) ? bootram[adrbits+1][15:0] : RAM[adrbits+1][15:0]; //busybear: 2 memory options
|
||||
assign #2 rd2 = (AdrF < (`TIM_BASE >> 1)) ? bootram[adrbits+1][15:0] : RAM[adrbits+1][15:0]; //busybear: 2 memory options
|
||||
generate
|
||||
if (`XLEN==32) begin
|
||||
assign InstrF = AdrF[1] ? {rd2[15:0], rd[31:16]} : rd;
|
||||
// First, AdrF needs to get its last bit appended back onto it
|
||||
// Then not-XORing it with TIMBASE checks if it matches TIMBASE exactly
|
||||
// Then ORing it with TIMRANGE introduces some leeway into the previous check, by allowing the lower bits to be either high or low
|
||||
// Then not-XORing it with TIM_BASE checks if it matches TIM_BASE exactly
|
||||
// Then ORing it with TIM_RANGE introduces some leeway into the previous check, by allowing the lower bits to be either high or low
|
||||
|
||||
assign InstrAccessFaultF = (~&(({AdrF,1'b0} ~^ `TIMBASE) | `TIMRANGE)) & (~&(({AdrF,1'b0} ~^ `BOOTTIMBASE) | `BOOTTIMRANGE));
|
||||
assign InstrAccessFaultF = (~&(({AdrF,1'b0} ~^ `TIM_BASE) | `TIM_RANGE)) & (~&(({AdrF,1'b0} ~^ `BOOTTIM_BASE) | `BOOTTIM_RANGE));
|
||||
|
||||
end else begin
|
||||
assign InstrF = AdrF[2] ? (AdrF[1] ? {rd2[15:0], rd[63:48]} : rd[63:32])
|
||||
: (AdrF[1] ? rd[47:16] : rd[31:0]);
|
||||
//
|
||||
assign InstrAccessFaultF = (|AdrF[`XLEN-1:32] | ~&({AdrF[31:1],1'b0} ~^ `TIMBASE | `TIMRANGE)) & (|AdrF[`XLEN-1:32] | ~&({AdrF[31:1],1'b0} ~^ `BOOTTIMBASE | `BOOTTIMRANGE));
|
||||
assign InstrAccessFaultF = (|AdrF[`XLEN-1:32] | ~&({AdrF[31:1],1'b0} ~^ `TIM_BASE | `TIM_RANGE)) & (|AdrF[`XLEN-1:32] | ~&({AdrF[31:1],1'b0} ~^ `BOOTTIM_BASE | `BOOTTIM_RANGE));
|
||||
end
|
||||
endgenerate
|
||||
endmodule
|
||||
|
@ -57,7 +57,8 @@ module uncore (
|
||||
input logic [31:0] GPIOPinsIn,
|
||||
output logic [31:0] GPIOPinsOut, GPIOPinsEn,
|
||||
input logic UARTSin,
|
||||
output logic UARTSout
|
||||
output logic UARTSout,
|
||||
output logic [63:0] MTIME_CLINT, MTIMECMP_CLINT
|
||||
);
|
||||
|
||||
logic [`XLEN-1:0] HWDATA;
|
||||
@ -75,26 +76,15 @@ module uncore (
|
||||
// unswizzle HSEL signals
|
||||
assign {HSELBootTim, HSELTim, HSELCLINT, HSELGPIO, HSELUART, HSELPLIC} = HSELRegions;
|
||||
|
||||
/* PMA checker now handles decoding addresses. *** This can be deleted.
|
||||
// AHB Address decoder
|
||||
adrdec timdec(HADDR, `TIMBASE, `TIMRANGE, HSELTim);
|
||||
adrdec boottimdec(HADDR, `BOOTTIMBASE, `BOOTTIMRANGE, HSELBootTim);
|
||||
adrdec clintdec(HADDR, `CLINTBASE, `CLINTRANGE, HSELCLINT);
|
||||
adrdec plicdec(HADDR, `PLICBASE, `PLICRANGE, HSELPLIC);
|
||||
adrdec gpiodec(HADDR, `GPIOBASE, `GPIORANGE, HSELGPIO);
|
||||
adrdec uartdec(HADDR, `UARTBASE, `UARTRANGE, PreHSELUART);
|
||||
assign HSELUART = PreHSELUART && (HSIZE == 3'b000); // only byte writes to UART are supported
|
||||
*/
|
||||
|
||||
// subword accesses: converts HWDATAIN to HWDATA
|
||||
subwordwrite sww(.*);
|
||||
|
||||
// tightly integrated memory
|
||||
dtim #(.BASE(`TIMBASE), .RANGE(`TIMRANGE)) dtim (.*);
|
||||
dtim #(.BASE(`BOOTTIMBASE), .RANGE(`BOOTTIMRANGE)) bootdtim(.HSELTim(HSELBootTim), .HREADTim(HREADBootTim), .HRESPTim(HRESPBootTim), .HREADYTim(HREADYBootTim), .*);
|
||||
dtim #(.BASE(`TIM_BASE), .RANGE(`TIM_RANGE)) dtim (.*);
|
||||
dtim #(.BASE(`BOOTTIM_BASE), .RANGE(`BOOTTIM_RANGE)) bootdtim(.HSELTim(HSELBootTim), .HREADTim(HREADBootTim), .HRESPTim(HRESPBootTim), .HREADYTim(HREADYBootTim), .*);
|
||||
|
||||
// memory-mapped I/O peripherals
|
||||
clint clint(.HADDR(HADDR[15:0]), .*);
|
||||
clint clint(.HADDR(HADDR[15:0]), .MTIME(MTIME_CLINT), .MTIMECMP(MTIMECMP_CLINT), .*);
|
||||
plic plic(.HADDR(HADDR[27:0]), .*);
|
||||
gpio gpio(.HADDR(HADDR[7:0]), .*); // *** may want to add GPIO interrupts
|
||||
uart uart(.HADDR(HADDR[2:0]), .TXRDYb(), .RXRDYb(), .INTR(UARTIntr), .SIN(UARTSin), .SOUT(UARTSout),
|
||||
|
@ -34,6 +34,7 @@ module wallypipelinedhart (
|
||||
input logic TimerIntM, ExtIntM, SwIntM,
|
||||
input logic InstrAccessFaultF,
|
||||
input logic DataAccessFaultM,
|
||||
input logic [63:0] MTIME_CLINT, MTIMECMP_CLINT,
|
||||
// Bus Interface
|
||||
input logic [15:0] rd2, // bogus, delete when real multicycle fetch works
|
||||
input logic [`AHBW-1:0] HRDATA,
|
||||
@ -134,7 +135,8 @@ module wallypipelinedhart (
|
||||
logic MemReadM, MemWriteM;
|
||||
logic [1:0] AtomicMaskedM;
|
||||
logic [2:0] Funct3M;
|
||||
logic [`XLEN-1:0] MemAdrM, MemPAdrM, WriteDataM;
|
||||
logic [`XLEN-1:0] MemAdrM, WriteDataM;
|
||||
logic [`PA_BITS-1:0] MemPAdrM;
|
||||
logic [`XLEN-1:0] ReadDataW;
|
||||
logic [`XLEN-1:0] InstrPAdrF;
|
||||
logic [`XLEN-1:0] InstrRData;
|
||||
|
@ -63,6 +63,7 @@ module wallypipelinedsoc (
|
||||
logic [5:0] HSELRegions;
|
||||
logic InstrAccessFaultF, DataAccessFaultM;
|
||||
logic TimerIntM, SwIntM; // from CLINT
|
||||
logic [63:0] MTIME_CLINT, MTIMECMP_CLINT; // from CLINT to CSRs
|
||||
logic ExtIntM; // from PLIC
|
||||
logic [2:0] HADDRD;
|
||||
logic [3:0] HSIZED;
|
||||
|
@ -1,711 +0,0 @@
|
||||
`include "wally-config.vh"
|
||||
|
||||
|
||||
module testbench();
|
||||
logic clk, reset;
|
||||
logic [31:0] GPIOPinsIn;
|
||||
logic [31:0] GPIOPinsOut, GPIOPinsEn;
|
||||
|
||||
// instantiate device to be tested
|
||||
logic [31:0] CheckInstrD;
|
||||
|
||||
logic [`AHBW-1:0] HRDATA;
|
||||
logic [31:0] HADDR;
|
||||
logic [`AHBW-1:0] HWDATA;
|
||||
logic HWRITE;
|
||||
logic [2:0] HSIZE;
|
||||
logic [2:0] HBURST;
|
||||
logic [3:0] HPROT;
|
||||
logic [1:0] HTRANS;
|
||||
logic HMASTLOCK;
|
||||
logic HCLK, HRESETn;
|
||||
logic [`AHBW-1:0] HRDATAEXT;
|
||||
logic HREADYEXT, HRESPEXT;
|
||||
logic UARTSout;
|
||||
|
||||
assign GPIOPinsIn = 0;
|
||||
assign UARTSin = 1;
|
||||
|
||||
// instantiate processor and memories
|
||||
wallypipelinedsoc dut(.*);
|
||||
|
||||
/**
|
||||
* Walk the page table stored in dtim according to sv39 logic and translate a
|
||||
* virtual address to a physical address.
|
||||
*
|
||||
* See section 4.3.2 of the RISC-V Privileged specification for a full
|
||||
* explanation of the below algorithm.
|
||||
*/
|
||||
function logic [`XLEN-1:0] adrTranslator(
|
||||
input logic [`XLEN-1:0] adrIn);
|
||||
begin
|
||||
logic SvMode, PTE_R, PTE_X;
|
||||
logic [`XLEN-1:0] SATP, PTE;
|
||||
logic [55:0] BaseAdr, PAdr;
|
||||
logic [8:0] VPN [0:2];
|
||||
logic [11:0] Offset;
|
||||
|
||||
int i;
|
||||
|
||||
// Grab the SATP register from privileged unit
|
||||
SATP = dut.hart.priv.csr.SATP_REGW;
|
||||
|
||||
// Split the virtual address into page number segments and offset
|
||||
VPN[2] = adrIn[38:30];
|
||||
VPN[1] = adrIn[29:21];
|
||||
VPN[0] = adrIn[20:12];
|
||||
Offset = adrIn[11:0];
|
||||
|
||||
// We do not support sv48; only sv39
|
||||
SvMode = SATP[63];
|
||||
|
||||
// Only perform translation if translation is on and the processor is not
|
||||
// in machine mode
|
||||
if (SvMode && (dut.hart.priv.PrivilegeModeW != `M_MODE)) begin
|
||||
BaseAdr = SATP[43:0] << 12;
|
||||
|
||||
for (i = 2; i >= 0; i--) begin
|
||||
PAdr = BaseAdr + (VPN[i] << 3);
|
||||
|
||||
// dtim.RAM is 64-bit addressed. PAdr specifies a byte. We right shift
|
||||
// by 3 (the PTE size) to get the requested 64-bit PTE.
|
||||
PTE = dut.uncore.dtim.RAM[PAdr >> 3];
|
||||
PTE_R = PTE[1];
|
||||
PTE_X = PTE[3];
|
||||
if (PTE_R || PTE_X) begin
|
||||
// Leaf page found
|
||||
break;
|
||||
end else begin
|
||||
// Go to next level of table
|
||||
BaseAdr = PTE[53:10] << 12;
|
||||
end
|
||||
end
|
||||
|
||||
// Determine which parts of the PTE page number to use based on the
|
||||
// level of the page table we reached.
|
||||
if (i == 2) begin
|
||||
// Gigapage
|
||||
assign adrTranslator = {8'b0, PTE[53:28], VPN[1], VPN[0], Offset};
|
||||
end else if (i == 1) begin
|
||||
// Megapage
|
||||
assign adrTranslator = {8'b0, PTE[53:19], VPN[0], Offset};
|
||||
end else begin
|
||||
// Kilopage
|
||||
assign adrTranslator = {8'b0, PTE[53:10], Offset};
|
||||
end
|
||||
end else begin
|
||||
// Direct translation if address translation is not on
|
||||
assign adrTranslator = adrIn;
|
||||
end
|
||||
end
|
||||
endfunction
|
||||
|
||||
// initialize test
|
||||
initial
|
||||
begin
|
||||
reset <= 1; # 22; reset <= 0;
|
||||
end
|
||||
|
||||
// read pc trace file
|
||||
integer data_file_PC, scan_file_PC;
|
||||
initial begin
|
||||
data_file_PC = $fopen({`LINUX_TEST_VECTORS,"parsedPC.txt"}, "r");
|
||||
if (data_file_PC == 0) begin
|
||||
$display("file couldn't be opened");
|
||||
$stop;
|
||||
end
|
||||
end
|
||||
|
||||
integer data_file_PCW, scan_file_PCW;
|
||||
initial begin
|
||||
data_file_PCW = $fopen({`LINUX_TEST_VECTORS,"parsedPC.txt"}, "r");
|
||||
if (data_file_PCW == 0) begin
|
||||
$display("file couldn't be opened");
|
||||
$stop;
|
||||
end
|
||||
end
|
||||
|
||||
// read register trace file
|
||||
integer data_file_rf, scan_file_rf;
|
||||
initial begin
|
||||
data_file_rf = $fopen({`LINUX_TEST_VECTORS,"parsedRegs.txt"}, "r");
|
||||
if (data_file_rf == 0) begin
|
||||
$display("file couldn't be opened");
|
||||
$stop;
|
||||
end
|
||||
end
|
||||
|
||||
// read CSR trace file
|
||||
integer data_file_csr, scan_file_csr;
|
||||
initial begin
|
||||
data_file_csr = $fopen({`LINUX_TEST_VECTORS,"parsedCSRs2.txt"}, "r");
|
||||
if (data_file_csr == 0) begin
|
||||
$display("file couldn't be opened");
|
||||
$stop;
|
||||
end
|
||||
end
|
||||
|
||||
// read memreads trace file
|
||||
integer data_file_memR, scan_file_memR;
|
||||
initial begin
|
||||
data_file_memR = $fopen({`LINUX_TEST_VECTORS,"parsedMemRead.txt"}, "r");
|
||||
if (data_file_memR == 0) begin
|
||||
$display("file couldn't be opened");
|
||||
$stop;
|
||||
end
|
||||
end
|
||||
|
||||
// read memwrite trace file
|
||||
integer data_file_memW, scan_file_memW;
|
||||
initial begin
|
||||
data_file_memW = $fopen({`LINUX_TEST_VECTORS,"parsedMemWrite.txt"}, "r");
|
||||
if (data_file_memW == 0) begin
|
||||
$display("file couldn't be opened");
|
||||
$stop;
|
||||
end
|
||||
end
|
||||
|
||||
// initial loading of memories
|
||||
initial begin
|
||||
$readmemh({`LINUX_TEST_VECTORS,"bootmem.txt"}, dut.uncore.bootdtim.RAM, 'h1000 >> 3); // load at address 0x1000, start of boot TIM
|
||||
$readmemh({`LINUX_TEST_VECTORS,"ram.txt"}, dut.uncore.dtim.RAM);
|
||||
$readmemb(`TWO_BIT_PRELOAD, dut.hart.ifu.bpred.bpred.Predictor.DirPredictor.PHT.memory);
|
||||
$readmemb(`BTB_PRELOAD, dut.hart.ifu.bpred.bpred.TargetPredictor.memory.memory);
|
||||
end
|
||||
|
||||
integer warningCount = 0;
|
||||
integer instrs;
|
||||
|
||||
//logic[63:0] adrTranslation[4:0];
|
||||
//string translationType[4:0] = {"rf", "writeAdr", "PCW", "PC", "readAdr"};
|
||||
//initial begin
|
||||
// for(int i=0; i<5; i++) begin
|
||||
// adrTranslation[i] = 64'b0;
|
||||
// end
|
||||
//end
|
||||
|
||||
//function logic equal(logic[63:0] adr, logic[63:0] adrExpected, integer func);
|
||||
// if (adr[11:0] !== adrExpected[11:0]) begin
|
||||
// equal = 1'b0;
|
||||
// end else begin
|
||||
// equal = 1'b1;
|
||||
// if ((adr+adrTranslation[func]) !== adrExpected) begin
|
||||
// adrTranslation[func] = adrExpected - adr;
|
||||
// $display("warning: probably new address translation %x for %s at instr %0d", adrTranslation[func], translationType[func], instrs);
|
||||
// warningCount += 1;
|
||||
// end
|
||||
// end
|
||||
//endfunction
|
||||
|
||||
// pretty sure this isn't necessary anymore, but keeping this for now since its easier
|
||||
function logic equal(logic[63:0] adr, logic[63:0] adrExpected, integer func);
|
||||
equal = adr === adrExpected;
|
||||
endfunction
|
||||
|
||||
|
||||
`define ERROR \
|
||||
#10; \
|
||||
$display("processed %0d instructions with %0d warnings", instrs, warningCount); \
|
||||
$stop;
|
||||
|
||||
logic [63:0] pcExpected;
|
||||
logic [63:0] regExpected;
|
||||
integer regNumExpected;
|
||||
logic [`XLEN-1:0] PCW;
|
||||
|
||||
flopenr #(`XLEN) PCWReg(clk, reset, ~dut.hart.ieu.dp.StallW, dut.hart.ifu.PCM, PCW);
|
||||
|
||||
genvar i;
|
||||
generate
|
||||
for(i=1; i<32; i++) begin
|
||||
always @(dut.hart.ieu.dp.regf.rf[i]) begin
|
||||
if ($time == 0) begin
|
||||
scan_file_rf = $fscanf(data_file_rf, "%x\n", regExpected);
|
||||
if (dut.hart.ieu.dp.regf.rf[i] != regExpected) begin
|
||||
$display("%0t ps, instr %0d: rf[%0d] does not equal rf expected: %x, %x", $time, instrs, i, dut.hart.ieu.dp.regf.rf[i], regExpected);
|
||||
`ERROR
|
||||
end
|
||||
end else begin
|
||||
scan_file_rf = $fscanf(data_file_rf, "%d\n", regNumExpected);
|
||||
scan_file_rf = $fscanf(data_file_rf, "%x\n", regExpected);
|
||||
if (i != regNumExpected) begin
|
||||
$display("%0t ps, instr %0d: wrong register changed: %0d, %0d expected to switch to %x from %x", $time, instrs, i, regNumExpected, regExpected, dut.hart.ieu.dp.regf.rf[regNumExpected]);
|
||||
`ERROR
|
||||
end
|
||||
if (~equal(dut.hart.ieu.dp.regf.rf[i],regExpected, 0)) begin
|
||||
$display("%0t ps, instr %0d: rf[%0d] does not equal rf expected: %x, %x", $time, instrs, i, dut.hart.ieu.dp.regf.rf[i], regExpected);
|
||||
`ERROR
|
||||
end
|
||||
//if (dut.hart.ieu.dp.regf.rf[i] !== regExpected) begin
|
||||
// force dut.hart.ieu.dp.regf.rf[i] = regExpected;
|
||||
// release dut.hart.ieu.dp.regf.rf[i];
|
||||
//end
|
||||
end
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
|
||||
// RAM and bootram are addressed in 64-bit blocks - this logic handles R/W
|
||||
// including subwords. Brief explanation on signals:
|
||||
//
|
||||
// readMask: bitmask of bits to read / write, left-shifted to align with
|
||||
// nearest 64-bit boundary - examples
|
||||
// HSIZE = 0 -> readMask = 11111111
|
||||
// HSIZE = 1 -> readMask = 1111111111111111
|
||||
//
|
||||
// In the linux boot, the processor spends the first ~5 instructions in
|
||||
// bootram, before jr jumps to main RAM
|
||||
|
||||
logic [63:0] readMask;
|
||||
assign readMask = ((1 << (8*(1 << HSIZE))) - 1) << 8 * HADDR[2:0];
|
||||
|
||||
logic [`XLEN-1:0] readAdrExpected, readAdrTranslated;
|
||||
|
||||
always @(dut.HRDATA) begin
|
||||
#2;
|
||||
if (dut.hart.MemRWM[1]
|
||||
&& (dut.hart.ebu.CaptureDataM)
|
||||
&& dut.HRDATA !== {64{1'bx}}) begin
|
||||
//$display("%0t", $time);
|
||||
if($feof(data_file_memR)) begin
|
||||
$display("no more memR data to read");
|
||||
`ERROR
|
||||
end
|
||||
scan_file_memR = $fscanf(data_file_memR, "%x\n", readAdrExpected);
|
||||
scan_file_memR = $fscanf(data_file_memR, "%x\n", HRDATA);
|
||||
assign readAdrTranslated = adrTranslator(readAdrExpected);
|
||||
if (~equal(HADDR,readAdrTranslated,4)) begin
|
||||
$display("%0t ps, instr %0d: HADDR does not equal readAdrExpected: %x, %x", $time, instrs, HADDR, readAdrTranslated);
|
||||
`ERROR
|
||||
end
|
||||
if ((readMask & HRDATA) !== (readMask & dut.HRDATA)) begin
|
||||
if (HADDR inside `LINUX_FIX_READ) begin
|
||||
//$display("warning %0t ps, instr %0d, adr %0d: forcing HRDATA to expected: %x, %x", $time, instrs, HADDR, HRDATA, dut.HRDATA);
|
||||
force dut.uncore.HRDATA = HRDATA;
|
||||
#9;
|
||||
release dut.uncore.HRDATA;
|
||||
warningCount += 1;
|
||||
end else begin
|
||||
$display("%0t ps, instr %0d: ExpectedHRDATA does not equal dut.HRDATA: %x, %x from address %x, %x", $time, instrs, HRDATA, dut.HRDATA, HADDR, HSIZE);
|
||||
`ERROR
|
||||
end
|
||||
end
|
||||
//end else if(dut.hart.MemRWM[1]) begin
|
||||
// $display("%x, %x, %x, %t", HADDR, dut.PCF, dut.HRDATA, $time);
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
logic [`XLEN-1:0] writeDataExpected, writeAdrExpected, writeAdrTranslated;
|
||||
|
||||
// this might need to change
|
||||
//always @(HWDATA or HADDR or HSIZE or HWRITE) begin
|
||||
always @(negedge HWRITE) begin
|
||||
//#1;
|
||||
if ($time != 0) begin
|
||||
if($feof(data_file_memW)) begin
|
||||
$display("no more memW data to read");
|
||||
`ERROR
|
||||
end
|
||||
scan_file_memW = $fscanf(data_file_memW, "%x\n", writeDataExpected);
|
||||
scan_file_memW = $fscanf(data_file_memW, "%x\n", writeAdrExpected);
|
||||
assign writeAdrTranslated = adrTranslator(writeAdrExpected);
|
||||
|
||||
if (writeDataExpected != HWDATA && ~dut.uncore.HSELPLICD) begin
|
||||
$display("%0t ps, instr %0d: HWDATA does not equal writeDataExpected: %x, %x", $time, instrs, HWDATA, writeDataExpected);
|
||||
`ERROR
|
||||
end
|
||||
if (~equal(writeAdrTranslated,HADDR,1) && ~dut.uncore.HSELPLICD) begin
|
||||
$display("%0t ps, instr %0d: HADDR does not equal writeAdrExpected: %x, %x", $time, instrs, HADDR, writeAdrTranslated);
|
||||
`ERROR
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
integer totalCSR = 0;
|
||||
logic [99:0] StartCSRexpected[63:0];
|
||||
string StartCSRname[99:0];
|
||||
initial begin
|
||||
while(1) begin
|
||||
scan_file_csr = $fscanf(data_file_csr, "%s\n", StartCSRname[totalCSR]);
|
||||
if(StartCSRname[totalCSR] == "---") begin
|
||||
break;
|
||||
end
|
||||
scan_file_csr = $fscanf(data_file_csr, "%x\n", StartCSRexpected[totalCSR]);
|
||||
totalCSR = totalCSR + 1;
|
||||
end
|
||||
end
|
||||
|
||||
always @(dut.hart.priv.csr.genblk1.csrm.MCAUSE_REGW) begin
|
||||
if (dut.hart.priv.csr.genblk1.csrm.MCAUSE_REGW == 2 && instrs > 1) begin
|
||||
$display("!!!!!! illegal instruction !!!!!!!!!!");
|
||||
$display("(as a reminder, MCAUSE and MEPC are set by this)");
|
||||
$display("at %0t ps, instr %0d, HADDR %x", $time, instrs, HADDR);
|
||||
`ERROR
|
||||
end
|
||||
if (dut.hart.priv.csr.genblk1.csrm.MCAUSE_REGW == 5 && instrs != 0) begin
|
||||
$display("!!!!!! illegal (physical) memory access !!!!!!!!!!");
|
||||
$display("(as a reminder, MCAUSE and MEPC are set by this)");
|
||||
$display("at %0t ps, instr %0d, HADDR %x", $time, instrs, HADDR);
|
||||
`ERROR
|
||||
end
|
||||
end
|
||||
|
||||
`define CHECK_CSR2(CSR, PATH) \
|
||||
string CSR; \
|
||||
logic [63:0] expected``CSR``; \
|
||||
//CSR checking \
|
||||
always @(``PATH``.``CSR``_REGW) begin \
|
||||
if ($time > 1) begin \
|
||||
if ("SEPC" == `"CSR`") begin #1; end \
|
||||
if ("SCAUSE" == `"CSR`") begin #2; end \
|
||||
if ("SSTATUS" == `"CSR`") begin #3; end \
|
||||
scan_file_csr = $fscanf(data_file_csr, "%s\n", CSR); \
|
||||
scan_file_csr = $fscanf(data_file_csr, "%x\n", expected``CSR``); \
|
||||
if(CSR.icompare(`"CSR`")) begin \
|
||||
$display("%0t ps, instr %0d: %s changed, expected %s", $time, instrs, `"CSR`", CSR); \
|
||||
end \
|
||||
if(``PATH``.``CSR``_REGW != ``expected``CSR) begin \
|
||||
$display("%0t ps, instr %0d: %s does not equal %s expected: %x, %x", $time, instrs, `"CSR`", CSR, ``PATH``.``CSR``_REGW, ``expected``CSR); \
|
||||
`ERROR \
|
||||
end \
|
||||
end else begin \
|
||||
if (!(`BUILDROOT == 1 && "MSTATUS" == `"CSR`")) begin \
|
||||
for(integer j=0; j<totalCSR; j++) begin \
|
||||
if(!StartCSRname[j].icompare(`"CSR`")) begin \
|
||||
if(``PATH``.``CSR``_REGW != StartCSRexpected[j]) begin \
|
||||
$display("%0t ps, instr %0d: %s does not equal %s expected: %x, %x", $time, instrs, `"CSR`", StartCSRname[j], ``PATH``.``CSR``_REGW, StartCSRexpected[j]); \
|
||||
`ERROR \
|
||||
end \
|
||||
end \
|
||||
end \
|
||||
end \
|
||||
end \
|
||||
end
|
||||
`define CHECK_CSR(CSR) \
|
||||
`CHECK_CSR2(CSR, dut.hart.priv.csr)
|
||||
`define CSRM dut.hart.priv.csr.genblk1.csrm
|
||||
`define CSRS dut.hart.priv.csr.genblk1.csrs.genblk1
|
||||
|
||||
|
||||
//`CHECK_CSR(FCSR)
|
||||
`CHECK_CSR2(MCAUSE, `CSRM)
|
||||
`CHECK_CSR(MCOUNTEREN)
|
||||
`CHECK_CSR(MEDELEG)
|
||||
`CHECK_CSR(MEPC)
|
||||
//`CHECK_CSR(MHARTID)
|
||||
`CHECK_CSR(MIDELEG)
|
||||
`CHECK_CSR(MIE)
|
||||
//`CHECK_CSR(MIP)
|
||||
`CHECK_CSR2(MISA, `CSRM)
|
||||
`CHECK_CSR2(MSCRATCH, `CSRM)
|
||||
`CHECK_CSR(MSTATUS)
|
||||
`CHECK_CSR2(MTVAL, `CSRM)
|
||||
`CHECK_CSR(MTVEC)
|
||||
//`CHECK_CSR2(PMPADDR0, `CSRM)
|
||||
//`CHECK_CSR2(PMdut.PCFG0, `CSRM)
|
||||
`CHECK_CSR(SATP)
|
||||
`CHECK_CSR2(SCAUSE, `CSRS)
|
||||
`CHECK_CSR(SCOUNTEREN)
|
||||
`CHECK_CSR(SEPC)
|
||||
`CHECK_CSR(SIE)
|
||||
`CHECK_CSR2(SSCRATCH, `CSRS)
|
||||
`CHECK_CSR(SSTATUS)
|
||||
`CHECK_CSR2(STVAL, `CSRS)
|
||||
`CHECK_CSR(STVEC)
|
||||
|
||||
logic speculative;
|
||||
initial begin
|
||||
speculative = 0;
|
||||
end
|
||||
logic [63:0] lastCheckInstrD, lastPC, lastPC2;
|
||||
|
||||
string PCtextW, PCtext2W;
|
||||
logic [31:0] InstrWExpected;
|
||||
logic [63:0] PCWExpected;
|
||||
always @(PCW or dut.hart.ieu.InstrValidW) begin
|
||||
if(dut.hart.ieu.InstrValidW && PCW != 0) begin
|
||||
if($feof(data_file_PCW)) begin
|
||||
$display("no more PC data to read");
|
||||
`ERROR
|
||||
end
|
||||
scan_file_PCW = $fscanf(data_file_PCW, "%s\n", PCtextW);
|
||||
PCtext2W = "";
|
||||
while (PCtext2W != "***") begin
|
||||
PCtextW = {PCtextW, " ", PCtext2W};
|
||||
scan_file_PC = $fscanf(data_file_PCW, "%s\n", PCtext2W);
|
||||
end
|
||||
scan_file_PCW = $fscanf(data_file_PCW, "%x\n", InstrWExpected);
|
||||
// then expected PC value
|
||||
scan_file_PCW = $fscanf(data_file_PCW, "%x\n", PCWExpected);
|
||||
if(~equal(PCW,PCWExpected,2)) begin
|
||||
$display("%0t ps, instr %0d: PCW does not equal PCW expected: %x, %x", $time, instrs, PCW, PCWExpected);
|
||||
`ERROR
|
||||
end
|
||||
//if(it.InstrW != InstrWExpected) begin
|
||||
// $display("%0t ps, instr %0d: InstrW does not equal InstrW expected: %x, %x", $time, instrs, it.InstrW, InstrWExpected);
|
||||
//end
|
||||
end
|
||||
end
|
||||
|
||||
string PCtext, PCtext2;
|
||||
initial begin
|
||||
instrs = 0;
|
||||
end
|
||||
logic [31:0] InstrMask;
|
||||
logic forcedInstr;
|
||||
logic [63:0] lastPCD;
|
||||
always @(dut.hart.ifu.PCD or dut.hart.ifu.InstrRawD or reset or negedge dut.hart.ifu.StallE) begin
|
||||
if(~HWRITE) begin
|
||||
#2;
|
||||
if (~reset && dut.hart.ifu.InstrRawD[15:0] !== {16{1'bx}} && dut.hart.ifu.PCD !== 64'h0 && ~dut.hart.ifu.StallE) begin
|
||||
if (dut.hart.ifu.PCD !== lastPCD) begin
|
||||
lastCheckInstrD = CheckInstrD;
|
||||
lastPC <= dut.hart.ifu.PCD;
|
||||
lastPC2 <= lastPC;
|
||||
if (speculative && (lastPC != pcExpected)) begin
|
||||
speculative = ~equal(dut.hart.ifu.PCD,pcExpected,3);
|
||||
if(dut.hart.ifu.PCD===pcExpected) begin
|
||||
if((dut.hart.ifu.InstrRawD[6:0] == 7'b1010011) || // for now, NOP out any float instrs
|
||||
(dut.hart.ifu.PCD == 32'h80001dc6) || // as well as stores to PLIC
|
||||
(dut.hart.ifu.PCD == 32'h80001de0) ||
|
||||
(dut.hart.ifu.PCD == 32'h80001de2)) begin
|
||||
$display("warning: NOPing out %s at PC=%0x, instr %0d, time %0t", PCtext, dut.hart.ifu.PCD, instrs, $time);
|
||||
force CheckInstrD = 32'b0010011;
|
||||
force dut.hart.ifu.InstrRawD = 32'b0010011;
|
||||
while (clk != 0) #1;
|
||||
while (clk != 1) #1;
|
||||
release dut.hart.ifu.InstrRawD;
|
||||
release CheckInstrD;
|
||||
warningCount += 1;
|
||||
forcedInstr = 1;
|
||||
end
|
||||
else begin
|
||||
forcedInstr = 0;
|
||||
end
|
||||
end
|
||||
end
|
||||
else begin
|
||||
if($feof(data_file_PC)) begin
|
||||
$display("no more PC data to read");
|
||||
`ERROR
|
||||
end
|
||||
scan_file_PC = $fscanf(data_file_PC, "%s\n", PCtext);
|
||||
PCtext2 = "";
|
||||
while (PCtext2 != "***") begin
|
||||
PCtext = {PCtext, " ", PCtext2};
|
||||
scan_file_PC = $fscanf(data_file_PC, "%s\n", PCtext2);
|
||||
end
|
||||
scan_file_PC = $fscanf(data_file_PC, "%x\n", CheckInstrD);
|
||||
if(dut.hart.ifu.PCD === pcExpected) begin
|
||||
if((dut.hart.ifu.InstrRawD[6:0] == 7'b1010011) || // for now, NOP out any float instrs
|
||||
(dut.hart.ifu.PCD == 32'h80001dc6) || // as well as stores to PLIC
|
||||
(dut.hart.ifu.PCD == 32'h80001de0) ||
|
||||
(dut.hart.ifu.PCD == 32'h80001de2)) begin
|
||||
$display("warning: NOPing out %s at PC=%0x, instr %0d, time %0t", PCtext, dut.hart.ifu.PCD, instrs, $time);
|
||||
force CheckInstrD = 32'b0010011;
|
||||
force dut.hart.ifu.InstrRawD = 32'b0010011;
|
||||
while (clk != 0) #1;
|
||||
while (clk != 1) #1;
|
||||
release dut.hart.ifu.InstrRawD;
|
||||
release CheckInstrD;
|
||||
warningCount += 1;
|
||||
forcedInstr = 1;
|
||||
end
|
||||
else begin
|
||||
forcedInstr = 0;
|
||||
end
|
||||
end
|
||||
// then expected PC value
|
||||
scan_file_PC = $fscanf(data_file_PC, "%x\n", pcExpected);
|
||||
if (instrs <= 10 || (instrs <= 100 && instrs % 10 == 0) ||
|
||||
(instrs <= 1000 && instrs % 100 == 0) || (instrs <= 10000 && instrs % 1000 == 0) ||
|
||||
(instrs <= 100000 && instrs % 10000 == 0) || (instrs <= 1000000 && instrs % 100000 == 0)) begin
|
||||
$display("loaded %0d instructions", instrs);
|
||||
end
|
||||
instrs += 1;
|
||||
// are we at a branch/jump?
|
||||
if (`BPRED_ENABLED) begin
|
||||
speculative = dut.hart.ifu.bpred.bpred.BPPredWrongE;
|
||||
end else begin
|
||||
casex (lastCheckInstrD[31:0])
|
||||
32'b00000000001000000000000001110011, // URET
|
||||
32'b00010000001000000000000001110011, // SRET
|
||||
32'b00110000001000000000000001110011, // MRET
|
||||
32'bXXXXXXXXXXXXXXXXXXXXXXXXX1101111, // JAL
|
||||
32'bXXXXXXXXXXXXXXXXXXXXXXXXX1100111, // JALR
|
||||
32'bXXXXXXXXXXXXXXXXXXXXXXXXX1100011, // B
|
||||
32'bXXXXXXXXXXXXXXXX110XXXXXXXXXXX01, // C.BEQZ
|
||||
32'bXXXXXXXXXXXXXXXX111XXXXXXXXXXX01, // C.BNEZ
|
||||
32'bXXXXXXXXXXXXXXXX101XXXXXXXXXXX01: // C.J
|
||||
speculative = 1;
|
||||
32'bXXXXXXXXXXXXXXXX1001000000000010, // C.EBREAK:
|
||||
32'bXXXXXXXXXXXXXXXXX000XXXXX1110011: // Something that's not CSRR*
|
||||
speculative = 0; // tbh don't really know what should happen here
|
||||
32'b000110000000XXXXXXXXXXXXX1110011, // CSR* SATP, *
|
||||
32'bXXXXXXXXXXXXXXXX1000XXXXX0000010, // C.JR
|
||||
32'bXXXXXXXXXXXXXXXX1001XXXXX0000010: // C.JALR //this is RV64 only so no C.JAL
|
||||
speculative = 1;
|
||||
default:
|
||||
speculative = 0;
|
||||
endcase
|
||||
end
|
||||
|
||||
//check things!
|
||||
if ((~speculative) && (~equal(dut.hart.ifu.PCD,pcExpected,3))) begin
|
||||
$display("%0t ps, instr %0d: PC does not equal PC expected: %x, %x", $time, instrs, dut.hart.ifu.PCD, pcExpected);
|
||||
`ERROR
|
||||
end
|
||||
InstrMask = CheckInstrD[1:0] == 2'b11 ? 32'hFFFFFFFF : 32'h0000FFFF;
|
||||
if ((~forcedInstr) && (~speculative) && ((InstrMask & dut.hart.ifu.InstrRawD) !== (InstrMask & CheckInstrD))) begin
|
||||
$display("%0t ps, instr %0d: InstrD does not equal CheckInstrD: %x, %x, PC: %x", $time, instrs, dut.hart.ifu.InstrRawD, CheckInstrD, dut.hart.ifu.PCD);
|
||||
`ERROR
|
||||
end
|
||||
end
|
||||
end
|
||||
lastPCD = dut.hart.ifu.PCD;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// Track names of instructions
|
||||
string InstrFName, InstrDName, InstrEName, InstrMName, InstrWName;
|
||||
logic [31:0] InstrW;
|
||||
instrTrackerTB it(clk, reset,
|
||||
dut.hart.ifu.icache.controller.FinalInstrRawF,
|
||||
dut.hart.ifu.InstrD, dut.hart.ifu.InstrE,
|
||||
dut.hart.ifu.InstrM, dut.hart.ifu.InstrW,
|
||||
InstrFName, InstrDName, InstrEName, InstrMName, InstrWName);
|
||||
|
||||
// generate clock to sequence tests
|
||||
always
|
||||
begin
|
||||
clk <= 1; # 5; clk <= 0; # 5;
|
||||
end
|
||||
|
||||
endmodule
|
||||
module instrTrackerTB(
|
||||
input logic clk, reset,
|
||||
input logic [31:0] InstrF,InstrD,InstrE,InstrM,InstrW,
|
||||
output string InstrFName, InstrDName, InstrEName, InstrMName, InstrWName);
|
||||
|
||||
// stage Instr to Writeback for visualization
|
||||
//flopr #(32) InstrWReg(clk, reset, InstrM, InstrW);
|
||||
|
||||
instrNameDecTB fdec(InstrF, InstrFName);
|
||||
instrNameDecTB ddec(InstrD, InstrDName);
|
||||
instrNameDecTB edec(InstrE, InstrEName);
|
||||
instrNameDecTB mdec(InstrM, InstrMName);
|
||||
instrNameDecTB wdec(InstrW, InstrWName);
|
||||
endmodule
|
||||
|
||||
// decode the instruction name, to help the test bench
|
||||
module instrNameDecTB(
|
||||
input logic [31:0] instr,
|
||||
output string name);
|
||||
|
||||
logic [6:0] op;
|
||||
logic [2:0] funct3;
|
||||
logic [6:0] funct7;
|
||||
logic [11:0] imm;
|
||||
|
||||
assign op = instr[6:0];
|
||||
assign funct3 = instr[14:12];
|
||||
assign funct7 = instr[31:25];
|
||||
assign imm = instr[31:20];
|
||||
|
||||
// it would be nice to add the operands to the name
|
||||
// create another variable called decoded
|
||||
|
||||
always_comb
|
||||
casez({op, funct3})
|
||||
10'b0000000_000: name = "BAD";
|
||||
10'b0000011_000: name = "LB";
|
||||
10'b0000011_001: name = "LH";
|
||||
10'b0000011_010: name = "LW";
|
||||
10'b0000011_011: name = "LD";
|
||||
10'b0000011_100: name = "LBU";
|
||||
10'b0000011_101: name = "LHU";
|
||||
10'b0000011_110: name = "LWU";
|
||||
10'b0010011_000: if (instr[31:15] == 0 && instr[11:7] ==0) name = "NOP/FLUSH";
|
||||
else name = "ADDI";
|
||||
10'b0010011_001: if (funct7[6:1] == 6'b000000) name = "SLLI";
|
||||
else name = "ILLEGAL";
|
||||
10'b0010011_010: name = "SLTI";
|
||||
10'b0010011_011: name = "SLTIU";
|
||||
10'b0010011_100: name = "XORI";
|
||||
10'b0010011_101: if (funct7[6:1] == 6'b000000) name = "SRLI";
|
||||
else if (funct7[6:1] == 6'b010000) name = "SRAI";
|
||||
else name = "ILLEGAL";
|
||||
10'b0010011_110: name = "ORI";
|
||||
10'b0010011_111: name = "ANDI";
|
||||
10'b0010111_???: name = "AUIPC";
|
||||
10'b0100011_000: name = "SB";
|
||||
10'b0100011_001: name = "SH";
|
||||
10'b0100011_010: name = "SW";
|
||||
10'b0100011_011: name = "SD";
|
||||
10'b0011011_000: name = "ADDIW";
|
||||
10'b0011011_001: name = "SLLIW";
|
||||
10'b0011011_101: if (funct7 == 7'b0000000) name = "SRLIW";
|
||||
else if (funct7 == 7'b0100000) name = "SRAIW";
|
||||
else name = "ILLEGAL";
|
||||
10'b0111011_000: if (funct7 == 7'b0000000) name = "ADDW";
|
||||
else if (funct7 == 7'b0100000) name = "SUBW";
|
||||
else name = "ILLEGAL";
|
||||
10'b0111011_001: name = "SLLW";
|
||||
10'b0111011_101: if (funct7 == 7'b0000000) name = "SRLW";
|
||||
else if (funct7 == 7'b0100000) name = "SRAW";
|
||||
else name = "ILLEGAL";
|
||||
10'b0110011_000: if (funct7 == 7'b0000000) name = "ADD";
|
||||
else if (funct7 == 7'b0000001) name = "MUL";
|
||||
else if (funct7 == 7'b0100000) name = "SUB";
|
||||
else name = "ILLEGAL";
|
||||
10'b0110011_001: if (funct7 == 7'b0000000) name = "SLL";
|
||||
else if (funct7 == 7'b0000001) name = "MULH";
|
||||
else name = "ILLEGAL";
|
||||
10'b0110011_010: if (funct7 == 7'b0000000) name = "SLT";
|
||||
else if (funct7 == 7'b0000001) name = "MULHSU";
|
||||
else name = "ILLEGAL";
|
||||
10'b0110011_011: if (funct7 == 7'b0000000) name = "SLTU";
|
||||
else if (funct7 == 7'b0000001) name = "DIV";
|
||||
else name = "ILLEGAL";
|
||||
10'b0110011_100: if (funct7 == 7'b0000000) name = "XOR";
|
||||
else if (funct7 == 7'b0000001) name = "MUL";
|
||||
else name = "ILLEGAL";
|
||||
10'b0110011_101: if (funct7 == 7'b0000000) name = "SRL";
|
||||
else if (funct7 == 7'b0000001) name = "DIVU";
|
||||
else if (funct7 == 7'b0100000) name = "SRA";
|
||||
else name = "ILLEGAL";
|
||||
10'b0110011_110: if (funct7 == 7'b0000000) name = "OR";
|
||||
else if (funct7 == 7'b0000001) name = "REM";
|
||||
else name = "ILLEGAL";
|
||||
10'b0110011_111: if (funct7 == 7'b0000000) name = "AND";
|
||||
else if (funct7 == 7'b0000001) name = "REMU";
|
||||
else name = "ILLEGAL";
|
||||
10'b0110111_???: name = "LUI";
|
||||
10'b1100011_000: name = "BEQ";
|
||||
10'b1100011_001: name = "BNE";
|
||||
10'b1100011_100: name = "BLT";
|
||||
10'b1100011_101: name = "BGE";
|
||||
10'b1100011_110: name = "BLTU";
|
||||
10'b1100011_111: name = "BGEU";
|
||||
10'b1100111_000: name = "JALR";
|
||||
10'b1101111_???: name = "JAL";
|
||||
10'b1110011_000: if (imm == 0) name = "ECALL";
|
||||
else if (imm == 1) name = "EBREAK";
|
||||
else if (imm == 2) name = "URET";
|
||||
else if (imm == 258) name = "SRET";
|
||||
else if (imm == 770) name = "MRET";
|
||||
else name = "ILLEGAL";
|
||||
10'b1110011_001: name = "CSRRW";
|
||||
10'b1110011_010: name = "CSRRS";
|
||||
10'b1110011_011: name = "CSRRC";
|
||||
10'b1110011_101: name = "CSRRWI";
|
||||
10'b1110011_110: name = "CSRRSI";
|
||||
10'b1110011_111: name = "CSRRCI";
|
||||
10'b0001111_???: name = "FENCE";
|
||||
default: name = "ILLEGAL";
|
||||
endcase
|
||||
endmodule
|
||||
|
@ -582,8 +582,8 @@ string tests32f[] = '{
|
||||
InstrFName, InstrDName, InstrEName, InstrMName, InstrWName);
|
||||
|
||||
// initialize tests
|
||||
localparam integer MemStartAddr = `TIMBASE>>(1+`XLEN/32);
|
||||
localparam integer MemEndAddr = (`TIMRANGE+`TIMBASE)>>1+(`XLEN/32);
|
||||
localparam integer MemStartAddr = `TIM_BASE>>(1+`XLEN/32);
|
||||
localparam integer MemEndAddr = (`TIM_RANGE+`TIM_BASE)>>1+(`XLEN/32);
|
||||
|
||||
initial
|
||||
begin
|
||||
@ -655,9 +655,9 @@ string tests32f[] = '{
|
||||
errors = (i == SIGNATURESIZE+1); // error if file is empty
|
||||
i = 0;
|
||||
if (`XLEN == 32)
|
||||
testadr = (`TIMBASE+tests[test+1].atohex())/4;
|
||||
testadr = (`TIM_BASE+tests[test+1].atohex())/4;
|
||||
else
|
||||
testadr = (`TIMBASE+tests[test+1].atohex())/8;
|
||||
testadr = (`TIM_BASE+tests[test+1].atohex())/8;
|
||||
/* verilator lint_off INFINITELOOP */
|
||||
while (signature[i] !== 'bx) begin
|
||||
//$display("signature[%h] = %h", i, signature[i]);
|
||||
|
@ -162,7 +162,7 @@ module testbench();
|
||||
// read CSR trace file
|
||||
integer data_file_csr, scan_file_csr;
|
||||
initial begin
|
||||
data_file_csr = $fopen({`LINUX_TEST_VECTORS,"parsedCSRs2.txt"}, "r");
|
||||
data_file_csr = $fopen({`LINUX_TEST_VECTORS,"parsedCSRs.txt"}, "r");
|
||||
if (data_file_csr == 0) begin
|
||||
$display("file couldn't be opened");
|
||||
$stop;
|
||||
@ -473,13 +473,28 @@ module testbench();
|
||||
end
|
||||
end
|
||||
|
||||
string PCtext, PCtext2;
|
||||
string PCtextD,PCtextE,PCtextM,PCtext2;
|
||||
always_ff @(posedge clk, posedge reset)
|
||||
if (reset) begin
|
||||
PCtextE = "(reset)";
|
||||
PCtextM = "(reset)";
|
||||
end else begin
|
||||
if (~dut.hart.StallM)
|
||||
if (dut.hart.FlushM) PCtextM = "(flushed)";
|
||||
else PCtextM = PCtextE;
|
||||
if (~dut.hart.StallE)
|
||||
if (dut.hart.FlushE) PCtextE = "(flushed)";
|
||||
else PCtextE = PCtextD;
|
||||
end
|
||||
|
||||
|
||||
initial begin
|
||||
instrs = 0;
|
||||
end
|
||||
logic [31:0] InstrMask;
|
||||
logic forcedInstr;
|
||||
logic [63:0] lastPCD;
|
||||
|
||||
always @(dut.hart.ifu.PCD or dut.hart.ifu.InstrRawD or reset or negedge dut.hart.ifu.StallE) begin
|
||||
if(~HWRITE) begin
|
||||
#2;
|
||||
@ -495,7 +510,7 @@ module testbench();
|
||||
(dut.hart.ifu.PCD == 32'h80001dc6) || // as well as stores to PLIC
|
||||
(dut.hart.ifu.PCD == 32'h80001de0) ||
|
||||
(dut.hart.ifu.PCD == 32'h80001de2)) begin
|
||||
$display("warning: NOPing out %s at PC=%0x, instr %0d, time %0t", PCtext, dut.hart.ifu.PCD, instrs, $time);
|
||||
$display("warning: NOPing out %s at PC=%0x, instr %0d, time %0t", PCtextD, dut.hart.ifu.PCD, instrs, $time);
|
||||
force CheckInstrD = 32'b0010011;
|
||||
force dut.hart.ifu.InstrRawD = 32'b0010011;
|
||||
while (clk != 0) #1;
|
||||
@ -515,10 +530,10 @@ module testbench();
|
||||
$display("no more PC data to read");
|
||||
`ERROR
|
||||
end
|
||||
scan_file_PC = $fscanf(data_file_PC, "%s\n", PCtext);
|
||||
scan_file_PC = $fscanf(data_file_PC, "%s\n", PCtextD);
|
||||
PCtext2 = "";
|
||||
while (PCtext2 != "***") begin
|
||||
PCtext = {PCtext, " ", PCtext2};
|
||||
PCtextD = {PCtextD, " ", PCtext2};
|
||||
scan_file_PC = $fscanf(data_file_PC, "%s\n", PCtext2);
|
||||
end
|
||||
scan_file_PC = $fscanf(data_file_PC, "%x\n", CheckInstrD);
|
||||
@ -527,7 +542,7 @@ module testbench();
|
||||
(dut.hart.ifu.PCD == 32'h80001dc6) || // as well as stores to PLIC
|
||||
(dut.hart.ifu.PCD == 32'h80001de0) ||
|
||||
(dut.hart.ifu.PCD == 32'h80001de2)) begin
|
||||
$display("warning: NOPing out %s at PC=%0x, instr %0d, time %0t", PCtext, dut.hart.ifu.PCD, instrs, $time);
|
||||
$display("warning: NOPing out %s at PC=%0x, instr %0d, time %0t", PCtextD, dut.hart.ifu.PCD, instrs, $time);
|
||||
force CheckInstrD = 32'b0010011;
|
||||
force dut.hart.ifu.InstrRawD = 32'b0010011;
|
||||
while (clk != 0) #1;
|
||||
@ -593,6 +608,7 @@ module testbench();
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
// Track names of instructions
|
||||
string InstrFName, InstrDName, InstrEName, InstrMName, InstrWName;
|
||||
logic [31:0] InstrW;
|
||||
|
@ -159,9 +159,9 @@ module testbench();
|
||||
i = 0;
|
||||
errors = 0;
|
||||
if (`XLEN == 32)
|
||||
testadr = (`TIMBASE+tests[test+1].atohex())/4;
|
||||
testadr = (`TIM_BASE+tests[test+1].atohex())/4;
|
||||
else
|
||||
testadr = (`TIMBASE+tests[test+1].atohex())/8;
|
||||
testadr = (`TIM_BASE+tests[test+1].atohex())/8;
|
||||
/* verilator lint_off INFINITELOOP */
|
||||
while (signature[i] !== 'bx) begin
|
||||
//$display("signature[%h] = %h", i, signature[i]);
|
||||
|
@ -53,7 +53,7 @@ def writeVectors(storecmd, returningInstruction):
|
||||
csrrs x0, {fromMode}status, x1
|
||||
|
||||
la x18, {clintAddr}
|
||||
lw x11, 0(x18)
|
||||
{loadcmd} x11, 0(x18)
|
||||
li x1, 0x3fffffffffffffff
|
||||
{storecmd} x1, 0(x18)
|
||||
|
||||
@ -69,7 +69,8 @@ def writeVectors(storecmd, returningInstruction):
|
||||
csrrc x0, {fromMode}status, x1
|
||||
|
||||
la x18, {clintAddr}
|
||||
{storecmd} x0, 0(x18)
|
||||
li x1, -1
|
||||
{storecmd} x1, 0(x18)
|
||||
""")
|
||||
|
||||
# Page 6 of unpriviledged spec
|
||||
@ -309,9 +310,11 @@ for xlen in xlens:
|
||||
formatrefstr = "{:08x}" # format as xlen-bit hexadecimal number with no leading 0x
|
||||
if (xlen == 32):
|
||||
storecmd = "sw"
|
||||
loadcmd = "lw"
|
||||
wordsize = 4
|
||||
else:
|
||||
storecmd = "sd"
|
||||
loadcmd = "ld"
|
||||
wordsize = 8
|
||||
|
||||
# testMode can be m, s, and u. User mode traps are deprecated, so this should likely just be ["m", "s"]
|
||||
|
Loading…
Reference in New Issue
Block a user