This commit is contained in:
bracker 2021-06-18 20:41:01 -05:00
commit cd7d403f92
47 changed files with 2122 additions and 1277 deletions

4
.gitignore vendored
View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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!",

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View 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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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