diff --git a/wally-pipelined/config/buildroot/wally-config.vh b/wally-pipelined/config/buildroot/wally-config.vh index e1e4f300..a535abff 100644 --- a/wally-pipelined/config/buildroot/wally-config.vh +++ b/wally-pipelined/config/buildroot/wally-config.vh @@ -62,10 +62,8 @@ // 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 56'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 56'h00003FFF -//`define BOOTTIM_BASE 56'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 56'h00000FFF +`define BOOTTIM_BASE 56'h00001000 +`define BOOTTIM_RANGE 56'h00000FFF `define TIM_SUPPORTED 1'b1 `define TIM_BASE 56'h80000000 `define TIM_RANGE 56'h07FFFFFF diff --git a/wally-pipelined/config/busybear/wally-config.vh b/wally-pipelined/config/busybear/wally-config.vh index 58c1c8a0..44729449 100644 --- a/wally-pipelined/config/busybear/wally-config.vh +++ b/wally-pipelined/config/busybear/wally-config.vh @@ -64,10 +64,10 @@ // 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 56'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 56'h00003FFF -//`define BOOTTIM_BASE 56'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 56'h00000FFF +//`define BOOTTIM_BASE 56'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 56'h00003FFF +`define BOOTTIM_BASE 56'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 56'h00000FFF `define TIM_SUPPORTED 1'b1 `define TIM_BASE 56'h80000000 `define TIM_RANGE 56'h07FFFFFF diff --git a/wally-pipelined/config/coremark-64i/wally-config.vh b/wally-pipelined/config/coremark-64i/wally-config.vh index f72b4f61..ae3100c6 100644 --- a/wally-pipelined/config/coremark-64i/wally-config.vh +++ b/wally-pipelined/config/coremark-64i/wally-config.vh @@ -55,25 +55,23 @@ // 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 BOOTTIM_BASE 56'h00001000 +`define BOOTTIM_RANGE 56'h00000FFF `define TIM_SUPPORTED 1'b1 -`define TIM_BASE 32'h80000000 -`define TIM_RANGE 32'h07FFFFFF +`define TIM_BASE 56'h80000000 +`define TIM_RANGE 56'h07FFFFFF `define CLINT_SUPPORTED 1'b1 -`define CLINT_BASE 32'h02000000 -`define CLINT_RANGE 32'h0000FFFF +`define CLINT_BASE 56'h02000000 +`define CLINT_RANGE 56'h0000FFFF `define GPIO_SUPPORTED 1'b1 -`define GPIO_BASE 32'h10012000 -`define GPIO_RANGE 32'h000000FF +`define GPIO_BASE 56'h10012000 +`define GPIO_RANGE 56'h000000FF `define UART_SUPPORTED 1'b1 -`define UART_BASE 32'h10000000 -`define UART_RANGE 32'h00000007 +`define UART_BASE 56'h10000000 +`define UART_RANGE 56'h00000007 `define PLIC_SUPPORTED 1'b1 -`define PLIC_BASE 32'h0C000000 -`define PLIC_RANGE 32'h03FFFFFF +`define PLIC_BASE 56'h0C000000 +`define PLIC_RANGE 56'h03FFFFFF // Test modes diff --git a/wally-pipelined/config/coremark/wally-config.vh b/wally-pipelined/config/coremark/wally-config.vh index ccf0a64b..7bfdc882 100644 --- a/wally-pipelined/config/coremark/wally-config.vh +++ b/wally-pipelined/config/coremark/wally-config.vh @@ -63,25 +63,23 @@ // 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 BOOTTIM_BASE 34'h00001000 +`define BOOTTIM_RANGE 34'h00000FFF `define TIM_SUPPORTED 1'b1 -`define TIM_BASE 32'h80000000 -`define TIM_RANGE 32'h07FFFFFF +`define TIM_BASE 34'h80000000 +`define TIM_RANGE 34'h07FFFFFF `define CLINT_SUPPORTED 1'b1 -`define CLINT_BASE 32'h02000000 -`define CLINT_RANGE 32'h0000FFFF +`define CLINT_BASE 34'h02000000 +`define CLINT_RANGE 34'h0000FFFF `define GPIO_SUPPORTED 1'b1 -`define GPIO_BASE 32'h10012000 -`define GPIO_RANGE 32'h000000FF +`define GPIO_BASE 34'h10012000 +`define GPIO_RANGE 34'h000000FF `define UART_SUPPORTED 1'b1 -`define UART_BASE 32'h10000000 -`define UART_RANGE 32'h00000007 +`define UART_BASE 34'h10000000 +`define UART_RANGE 34'h00000007 `define PLIC_SUPPORTED 1'b1 -`define PLIC_BASE 32'h0C000000 -`define PLIC_RANGE 32'h03FFFFFF +`define PLIC_BASE 34'h0C000000 +`define PLIC_RANGE 34'h03FFFFFF // Test modes diff --git a/wally-pipelined/config/coremark_bare/wally-config.vh b/wally-pipelined/config/coremark_bare/wally-config.vh index d55200b4..fb4bee34 100644 --- a/wally-pipelined/config/coremark_bare/wally-config.vh +++ b/wally-pipelined/config/coremark_bare/wally-config.vh @@ -66,25 +66,23 @@ // 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 BOOTTIM_BASE 34'h00001000 +`define BOOTTIM_RANGE 34'h00000FFF `define TIM_SUPPORTED 1'b1 -`define TIM_BASE 32'h80000000 -`define TIM_RANGE 32'h07FFFFFF +`define TIM_BASE 34'h80000000 +`define TIM_RANGE 34'h07FFFFFF `define CLINT_SUPPORTED 1'b1 -`define CLINT_BASE 32'h02000000 -`define CLINT_RANGE 32'h0000FFFF +`define CLINT_BASE 34'h02000000 +`define CLINT_RANGE 34'h0000FFFF `define GPIO_SUPPORTED 1'b1 -`define GPIO_BASE 32'h10012000 -`define GPIO_RANGE 32'h000000FF +`define GPIO_BASE 34'h10012000 +`define GPIO_RANGE 34'h000000FF `define UART_SUPPORTED 1'b1 -`define UART_BASE 32'h10000000 -`define UART_RANGE 32'h00000007 +`define UART_BASE 34'h10000000 +`define UART_RANGE 34'h00000007 `define PLIC_SUPPORTED 1'b1 -`define PLIC_BASE 32'h0C000000 -`define PLIC_RANGE 32'h03FFFFFF +`define PLIC_BASE 34'h0C000000 +`define PLIC_RANGE 34'h03FFFFFF // Test modes diff --git a/wally-pipelined/config/rv32ic/wally-config.vh b/wally-pipelined/config/rv32ic/wally-config.vh index 29cd973a..1933a2e7 100644 --- a/wally-pipelined/config/rv32ic/wally-config.vh +++ b/wally-pipelined/config/rv32ic/wally-config.vh @@ -63,10 +63,8 @@ // *** each of these is `PA_BITS wide. is this paramaterizable INSIDE the config file? `define BOOTTIM_SUPPORTED 1'b1 -`define BOOTTIM_BASE 34'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 34'h00003FFF -//`define BOOTTIM_BASE 34'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 34'h00000FFF +`define BOOTTIM_BASE 34'h00001000 +`define BOOTTIM_RANGE 34'h00000FFF `define TIM_SUPPORTED 1'b1 `define TIM_BASE 34'h80000000 `define TIM_RANGE 34'h07FFFFFF diff --git a/wally-pipelined/config/rv64BP/wally-config.vh b/wally-pipelined/config/rv64BP/wally-config.vh index 2e5eaf37..335f2d87 100644 --- a/wally-pipelined/config/rv64BP/wally-config.vh +++ b/wally-pipelined/config/rv64BP/wally-config.vh @@ -64,25 +64,23 @@ // 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 BOOTTIM_BASE 56'h00001000 +`define BOOTTIM_RANGE 56'h00000FFF `define TIM_SUPPORTED 1'b1 -`define TIM_BASE 32'h80000000 -`define TIM_RANGE 32'h07FFFFFF +`define TIM_BASE 56'h80000000 +`define TIM_RANGE 56'h07FFFFFF `define CLINT_SUPPORTED 1'b1 -`define CLINT_BASE 32'h02000000 -`define CLINT_RANGE 32'h0000FFFF +`define CLINT_BASE 56'h02000000 +`define CLINT_RANGE 56'h0000FFFF `define GPIO_SUPPORTED 1'b1 -`define GPIO_BASE 32'h10012000 -`define GPIO_RANGE 32'h000000FF +`define GPIO_BASE 56'h10012000 +`define GPIO_RANGE 56'h000000FF `define UART_SUPPORTED 1'b1 -`define UART_BASE 32'h10000000 -`define UART_RANGE 32'h00000007 +`define UART_BASE 56'h10000000 +`define UART_RANGE 56'h00000007 `define PLIC_SUPPORTED 1'b1 -`define PLIC_BASE 32'h0C000000 -`define PLIC_RANGE 32'h03FFFFFF +`define PLIC_BASE 56'h0C000000 +`define PLIC_RANGE 56'h03FFFFFF // Test modes diff --git a/wally-pipelined/config/rv64ic/wally-config.vh b/wally-pipelined/config/rv64ic/wally-config.vh index a15ef18b..ad97d446 100644 --- a/wally-pipelined/config/rv64ic/wally-config.vh +++ b/wally-pipelined/config/rv64ic/wally-config.vh @@ -67,10 +67,10 @@ // *** each of these is `PA_BITS wide. is this paramaterizable INSIDE the config file? `define BOOTTIM_SUPPORTED 1'b1 -`define BOOTTIM_RANGE 56'h00003FFF -`define BOOTTIM_BASE 56'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_BASE 56'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 56'h00000FFF +//`define BOOTTIM_RANGE 56'h00003FFF +//`define BOOTTIM_BASE 56'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_BASE 56'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 56'h00000FFF `define TIM_SUPPORTED 1'b1 `define TIM_BASE 56'h80000000 `define TIM_RANGE 56'h07FFFFFF diff --git a/wally-pipelined/config/rv64icfd/wally-config.vh b/wally-pipelined/config/rv64icfd/wally-config.vh index 29322210..e645f014 100644 --- a/wally-pipelined/config/rv64icfd/wally-config.vh +++ b/wally-pipelined/config/rv64icfd/wally-config.vh @@ -66,25 +66,23 @@ // 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 BOOTTIM_BASE 56'h00001000 +`define BOOTTIM_RANGE 56'h00000FFF `define TIM_SUPPORTED 1'b1 -`define TIM_BASE 32'h80000000 -`define TIM_RANGE 32'h07FFFFFF +`define TIM_BASE 56'h80000000 +`define TIM_RANGE 56'h07FFFFFF `define CLINT_SUPPORTED 1'b1 -`define CLINT_BASE 32'h02000000 -`define CLINT_RANGE 32'h0000FFFF +`define CLINT_BASE 56'h02000000 +`define CLINT_RANGE 56'h0000FFFF `define GPIO_SUPPORTED 1'b1 -`define GPIO_BASE 32'h10012000 -`define GPIO_RANGE 32'h000000FF +`define GPIO_BASE 56'h10012000 +`define GPIO_RANGE 56'h000000FF `define UART_SUPPORTED 1'b1 -`define UART_BASE 32'h10000000 -`define UART_RANGE 32'h00000007 +`define UART_BASE 56'h10000000 +`define UART_RANGE 56'h00000007 `define PLIC_SUPPORTED 1'b1 -`define PLIC_BASE 32'h0C000000 -`define PLIC_RANGE 32'h03FFFFFF +`define PLIC_BASE 56'h0C000000 +`define PLIC_RANGE 56'h03FFFFFF // Test modes diff --git a/wally-pipelined/config/rv64imc/wally-config.vh b/wally-pipelined/config/rv64imc/wally-config.vh index 5ecb9bef..885a519d 100644 --- a/wally-pipelined/config/rv64imc/wally-config.vh +++ b/wally-pipelined/config/rv64imc/wally-config.vh @@ -62,25 +62,23 @@ // 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 BOOTTIM_BASE 56'h00001000 +`define BOOTTIM_RANGE 56'h00000FFF `define TIM_SUPPORTED 1'b1 -`define TIM_BASE 32'h80000000 -`define TIM_RANGE 32'h07FFFFFF +`define TIM_BASE 56'h80000000 +`define TIM_RANGE 56'h07FFFFFF `define CLINT_SUPPORTED 1'b1 -`define CLINT_BASE 32'h02000000 -`define CLINT_RANGE 32'h0000FFFF +`define CLINT_BASE 56'h02000000 +`define CLINT_RANGE 56'h0000FFFF `define GPIO_SUPPORTED 1'b1 -`define GPIO_BASE 32'h10012000 -`define GPIO_RANGE 32'h000000FF +`define GPIO_BASE 56'h10012000 +`define GPIO_RANGE 56'h000000FF `define UART_SUPPORTED 1'b1 -`define UART_BASE 32'h10000000 -`define UART_RANGE 32'h00000007 +`define UART_BASE 56'h10000000 +`define UART_RANGE 56'h00000007 `define PLIC_SUPPORTED 1'b1 -`define PLIC_BASE 32'h0C000000 -`define PLIC_RANGE 32'h03FFFFFF +`define PLIC_BASE 56'h0C000000 +`define PLIC_RANGE 56'h03FFFFFF // Test modes diff --git a/wally-pipelined/linux-testgen/logAllBuildroot.sh b/wally-pipelined/linux-testgen/logAllBuildroot.sh index 740fa8c4..86bba6af 100755 --- a/wally-pipelined/linux-testgen/logAllBuildroot.sh +++ b/wally-pipelined/linux-testgen/logAllBuildroot.sh @@ -21,11 +21,12 @@ # - Logs parse_qemu.py's simulated gdb output to 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 in case you just want to have qemu_in_gdb_format.txt around # It is often helpful for general debugging -#(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 | ./parse_qemu.py >qemu_in_gdb_format.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>&1 >/dev/null | ./parse_qemu.py >/courses/e190ax/buildroot_boot/qemu_in_gdb_format.txt) & riscv64-unknown-elf-gdb -x gdbinit_qemulog # Split qemu_in_gdb_format.txt into chunks of 100,000 instructions for easier inspection +#cd /courses/e190ax/buildroot_boot #split -d -l 5600000 qemu_in_gdb_format.txt --verbose # Uncomment this version for parse_gdb_output.py debugging @@ -36,4 +37,4 @@ # =========== Just Do the Thing ========== # 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 | ./parse_qemu.py | ./parse_gdb_output.py "/courses/e190ax/buildroot_boot_new/") & 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 | ./parse_qemu.py | ./parse_gdb_output.py "/courses/e190ax/buildroot_boot_new/") & riscv64-unknown-elf-gdb -x gdbinit_qemulog diff --git a/wally-pipelined/linux-testgen/parse_qemu.py b/wally-pipelined/linux-testgen/parse_qemu.py index ac5d95f0..4da168ab 100755 --- a/wally-pipelined/linux-testgen/parse_qemu.py +++ b/wally-pipelined/linux-testgen/parse_qemu.py @@ -9,9 +9,10 @@ pageFaultCSRs = {} regs = {} pageFaultRegs = {} instrs = {} +instrCount = 0 def printPC(l): - global parseState, inPageFault, CSRs, pageFaultCSRs, regs, pageFaultCSRs, instrs + global parseState, inPageFault, CSRs, pageFaultCSRs, regs, pageFaultCSRs, instrs, instrCount if not inPageFault: inst = l.split() if len(inst) > 3: @@ -19,6 +20,9 @@ def printPC(l): else: print(f'=> {inst[1]}:\t{inst[2]}') print(f'{inst[0]} 0x{inst[1]}') + instrCount += 1 + if ((instrCount % 100000) == 0): + sys.stderr.write("QEMU parser reached "+str(instrCount)+" instrs\n") def printCSRs(): global parseState, inPageFault, CSRs, pageFaultCSRs, regs, pageFaultCSRs, instrs diff --git a/wally-pipelined/regression/wally-busybear-batch.do b/wally-pipelined/regression/wally-busybear-batch.do index a4a80eb7..e2817dfa 100644 --- a/wally-pipelined/regression/wally-busybear-batch.do +++ b/wally-pipelined/regression/wally-busybear-batch.do @@ -35,5 +35,6 @@ vopt work_busybear.testbench -o workopt_busybear vsim workopt_busybear -suppress 8852,12070 +run -all run -all quit diff --git a/wally-pipelined/regression/wally-busybear.do b/wally-pipelined/regression/wally-busybear.do index 11876dde..204d1c4e 100644 --- a/wally-pipelined/regression/wally-busybear.do +++ b/wally-pipelined/regression/wally-busybear.do @@ -35,9 +35,10 @@ vopt +acc work.testbench -o workopt vsim workopt -suppress 8852,12070 -do ./wave-dos/linux-waves.do #-- Run the Simulation run -all +do ./wave-dos/linux-waves.do +run -all ##quit diff --git a/wally-pipelined/regression/wave-dos/linux-waves.do b/wally-pipelined/regression/wave-dos/linux-waves.do index 63623891..843ed274 100644 --- a/wally-pipelined/regression/wave-dos/linux-waves.do +++ b/wally-pipelined/regression/wave-dos/linux-waves.do @@ -122,8 +122,7 @@ add wave -hex sim:/testbench/dut/hart/priv/csr/genblk1/csrn/UEPC_REGW add wave -hex sim:/testbench/dut/hart/priv/csr/genblk1/csrn/UTVEC_REGW add wave -hex sim:/testbench/dut/hart/priv/csr/genblk1/csrn/UIP_REGW add wave -hex sim:/testbench/dut/hart/priv/csr/genblk1/csrn/UIE_REGW -add wave -hex sim:/testbench/dut/hart/priv/csr/genblk1/csrm/PMPCFG01_REGW -add wave -hex sim:/testbench/dut/hart/priv/csr/genblk1/csrm/PMPCFG23_REGW +add wave -hex sim:/testbench/dut/hart/priv/csr/genblk1/csrm/PMPCFG_ARRAY_REGW add wave -hex sim:/testbench/dut/hart/priv/csr/genblk1/csrm/PMPADDR_ARRAY_REGW add wave -hex sim:/testbench/dut/hart/priv/csr/genblk1/csrm/MISA_REGW add wave -hex sim:/testbench/dut/hart/priv/csr/genblk1/csru/FRM_REGW diff --git a/wally-pipelined/src/cache/ICacheCntrl.sv b/wally-pipelined/src/cache/ICacheCntrl.sv index ea52130c..748b3f5e 100644 --- a/wally-pipelined/src/cache/ICacheCntrl.sv +++ b/wally-pipelined/src/cache/ICacheCntrl.sv @@ -71,11 +71,11 @@ module ICacheCntrl #(parameter BLOCKLEN = 256) ); // FSM states - localparam STATE_READY = 0; - localparam STATE_HIT_SPILL = 1; // spill, block 0 hit - localparam STATE_HIT_SPILL_MISS_FETCH_WDV = 2; // block 1 miss, issue read to AHB and wait data. - localparam STATE_HIT_SPILL_MISS_FETCH_DONE = 3; // write data into SRAM/LUT - localparam STATE_HIT_SPILL_MERGE = 4; // Read block 0 of CPU access, should be able to optimize into STATE_HIT_SPILL. + localparam STATE_READY = 'h0; + localparam STATE_HIT_SPILL = 'h1; // spill, block 0 hit + localparam STATE_HIT_SPILL_MISS_FETCH_WDV = 'h2; // block 1 miss, issue read to AHB and wait data. + localparam STATE_HIT_SPILL_MISS_FETCH_DONE = 'h3; // write data into SRAM/LUT + localparam STATE_HIT_SPILL_MERGE = 'h4; // Read block 0 of CPU access, should be able to optimize into STATE_HIT_SPILL. // a challenge is the spill signal gets us out of the ready state and moves us to // 1 of the 2 spill branches. However the original fsm design had us return to @@ -91,30 +91,30 @@ module ICacheCntrl #(parameter BLOCKLEN = 256) // between CPU stalling and that register. // Picking option 1. - localparam STATE_HIT_SPILL_FINAL = 5; // this state replicates STATE_READY's replay of the + localparam STATE_HIT_SPILL_FINAL = 'h5; // this state replicates STATE_READY's replay of the // spill access but does nto consider spill. It also does not do another operation. - localparam STATE_MISS_FETCH_WDV = 6; // aligned miss, issue read to AHB and wait for data. - localparam STATE_MISS_FETCH_DONE = 7; // write data into SRAM/LUT - localparam STATE_MISS_READ = 8; // read block 1 from SRAM/LUT + localparam STATE_MISS_FETCH_WDV = 'h6; // aligned miss, issue read to AHB and wait for data. + localparam STATE_MISS_FETCH_DONE = 'h7; // write data into SRAM/LUT + localparam STATE_MISS_READ = 'h8; // read block 1 from SRAM/LUT - localparam STATE_MISS_SPILL_FETCH_WDV = 9; // spill, miss on block 0, issue read to AHB and wait - localparam STATE_MISS_SPILL_FETCH_DONE = 10; // write data into SRAM/LUT - localparam STATE_MISS_SPILL_READ1 = 11; // read block 0 from SRAM/LUT - localparam STATE_MISS_SPILL_2 = 12; // return to ready if hit or do second block update. - localparam STATE_MISS_SPILL_2_START = 13; // return to ready if hit or do second block update. - localparam STATE_MISS_SPILL_MISS_FETCH_WDV = 14; // miss on block 1, issue read to AHB and wait - localparam STATE_MISS_SPILL_MISS_FETCH_DONE = 15; // write data to SRAM/LUT - localparam STATE_MISS_SPILL_MERGE = 16; // read block 0 of CPU access, + localparam STATE_MISS_SPILL_FETCH_WDV = 'h9; // spill, miss on block 0, issue read to AHB and wait + localparam STATE_MISS_SPILL_FETCH_DONE = 'ha; // write data into SRAM/LUT + localparam STATE_MISS_SPILL_READ1 = 'hb; // read block 0 from SRAM/LUT + localparam STATE_MISS_SPILL_2 = 'hc; // return to ready if hit or do second block update. + localparam STATE_MISS_SPILL_2_START = 'hd; // return to ready if hit or do second block update. + localparam STATE_MISS_SPILL_MISS_FETCH_WDV = 'he; // miss on block 1, issue read to AHB and wait + localparam STATE_MISS_SPILL_MISS_FETCH_DONE = 'hf; // write data to SRAM/LUT + localparam STATE_MISS_SPILL_MERGE = 'h10; // read block 0 of CPU access, - localparam STATE_MISS_SPILL_FINAL = 17; // this state replicates STATE_READY's replay of the + localparam STATE_MISS_SPILL_FINAL = 'h11; // this state replicates STATE_READY's replay of the // spill access but does nto consider spill. It also does not do another operation. - localparam STATE_INVALIDATE = 18; // *** not sure if invalidate or evict? invalidate by cache block or address? - localparam STATE_TLB_MISS = 19; - localparam STATE_TLB_MISS_DONE = 20; + localparam STATE_INVALIDATE = 'h12; // *** not sure if invalidate or evict? invalidate by cache block or address? + localparam STATE_TLB_MISS = 'h13; + localparam STATE_TLB_MISS_DONE = 'h14; @@ -213,179 +213,175 @@ module ICacheCntrl #(parameter BLOCKLEN = 256) ICacheStallF = 1'b1; case (CurrState) - STATE_READY: begin - PCMux = 2'b00; - ICacheReadEn = 1'b1; - if (ITLBMissF) begin - NextState = STATE_TLB_MISS; - end else if (hit & ~spill) begin - SavePC = 1'b1; - ICacheStallF = 1'b0; - NextState = STATE_READY; - end else if (hit & spill) begin - spillSave = 1'b1; - PCMux = 2'b10; - NextState = STATE_HIT_SPILL; - end else if (~hit & ~spill) begin - CntReset = 1'b1; - NextState = STATE_MISS_FETCH_WDV; - end else if (~hit & spill) begin - CntReset = 1'b1; - PCMux = 2'b01; - NextState = STATE_MISS_SPILL_FETCH_WDV; - end else begin + PCMux = 2'b00; + ICacheReadEn = 1'b1; + if (ITLBMissF) begin + NextState = STATE_TLB_MISS; + end else if (hit & ~spill) begin + SavePC = 1'b1; + ICacheStallF = 1'b0; NextState = STATE_READY; - end + end else if (hit & spill) begin + spillSave = 1'b1; + PCMux = 2'b10; + NextState = STATE_HIT_SPILL; + end else if (~hit & ~spill) begin + CntReset = 1'b1; + NextState = STATE_MISS_FETCH_WDV; + end else if (~hit & spill) begin + CntReset = 1'b1; + PCMux = 2'b01; + NextState = STATE_MISS_SPILL_FETCH_WDV; + end else begin + NextState = STATE_READY; + end end - // branch 1, hit spill and 2, miss spill hit STATE_HIT_SPILL: begin - PCMux = 2'b10; - UnalignedSelect = 1'b1; - ICacheReadEn = 1'b1; - if (hit) begin + PCMux = 2'b10; + UnalignedSelect = 1'b1; + ICacheReadEn = 1'b1; + if (hit) begin NextState = STATE_HIT_SPILL_FINAL; - end else begin - CntReset = 1'b1; + end else begin + CntReset = 1'b1; NextState = STATE_HIT_SPILL_MISS_FETCH_WDV; - end + end end STATE_HIT_SPILL_MISS_FETCH_WDV: begin - PCMux = 2'b10; - //InstrReadF = 1'b1; - PreCntEn = 1'b1; - if (FetchCountFlag & InstrAckF) begin - NextState = STATE_HIT_SPILL_MISS_FETCH_DONE; - end else begin - NextState = STATE_HIT_SPILL_MISS_FETCH_WDV; - end + PCMux = 2'b10; + //InstrReadF = 1'b1; + PreCntEn = 1'b1; + if (FetchCountFlag & InstrAckF) begin + NextState = STATE_HIT_SPILL_MISS_FETCH_DONE; + end else begin + NextState = STATE_HIT_SPILL_MISS_FETCH_WDV; + end end STATE_HIT_SPILL_MISS_FETCH_DONE: begin - PCMux = 2'b10; - ICacheMemWriteEnable = 1'b1; + PCMux = 2'b10; + ICacheMemWriteEnable = 1'b1; NextState = STATE_HIT_SPILL_MERGE; end STATE_HIT_SPILL_MERGE: begin - PCMux = 2'b10; - UnalignedSelect = 1'b1; - ICacheReadEn = 1'b1; + PCMux = 2'b10; + UnalignedSelect = 1'b1; + ICacheReadEn = 1'b1; NextState = STATE_HIT_SPILL_FINAL; end STATE_HIT_SPILL_FINAL: begin - ICacheReadEn = 1'b1; - PCMux = 2'b00; - UnalignedSelect = 1'b1; - SavePC = 1'b1; - NextState = STATE_READY; - ICacheStallF = 1'b0; + ICacheReadEn = 1'b1; + PCMux = 2'b00; + UnalignedSelect = 1'b1; + SavePC = 1'b1; + NextState = STATE_READY; + ICacheStallF = 1'b0; end - // branch 3 miss no spill STATE_MISS_FETCH_WDV: begin - PCMux = 2'b01; - //InstrReadF = 1'b1; - PreCntEn = 1'b1; - if (FetchCountFlag & InstrAckF) begin - NextState = STATE_MISS_FETCH_DONE; - end else begin - NextState = STATE_MISS_FETCH_WDV; - end + PCMux = 2'b01; + //InstrReadF = 1'b1; + PreCntEn = 1'b1; + if (FetchCountFlag & InstrAckF) begin + NextState = STATE_MISS_FETCH_DONE; + end else begin + NextState = STATE_MISS_FETCH_WDV; + end end STATE_MISS_FETCH_DONE: begin - PCMux = 2'b01; - ICacheMemWriteEnable = 1'b1; + PCMux = 2'b01; + ICacheMemWriteEnable = 1'b1; NextState = STATE_MISS_READ; end STATE_MISS_READ: begin - PCMux = 2'b01; - ICacheReadEn = 1'b1; - NextState = STATE_READY; + PCMux = 2'b01; + ICacheReadEn = 1'b1; + NextState = STATE_READY; end - // branch 4 miss spill hit, and 5 miss spill miss STATE_MISS_SPILL_FETCH_WDV: begin - PCMux = 2'b01; - PreCntEn = 1'b1; - //InstrReadF = 1'b1; - if (FetchCountFlag & InstrAckF) begin - NextState = STATE_MISS_SPILL_FETCH_DONE; - end else begin - NextState = STATE_MISS_SPILL_FETCH_WDV; - end + PCMux = 2'b01; + PreCntEn = 1'b1; + //InstrReadF = 1'b1; + if (FetchCountFlag & InstrAckF) begin + NextState = STATE_MISS_SPILL_FETCH_DONE; + end else begin + NextState = STATE_MISS_SPILL_FETCH_WDV; + end end STATE_MISS_SPILL_FETCH_DONE: begin - PCMux = 2'b01; - ICacheMemWriteEnable = 1'b1; - NextState = STATE_MISS_SPILL_READ1; + PCMux = 2'b01; + ICacheMemWriteEnable = 1'b1; + NextState = STATE_MISS_SPILL_READ1; end STATE_MISS_SPILL_READ1: begin // always be a hit as we just wrote that cache block. - PCMux = 2'b01; // there is a 1 cycle delay after setting the address before the date arrives. - ICacheReadEn = 1'b1; - NextState = STATE_MISS_SPILL_2; + PCMux = 2'b01; // there is a 1 cycle delay after setting the address before the date arrives. + ICacheReadEn = 1'b1; + NextState = STATE_MISS_SPILL_2; end STATE_MISS_SPILL_2: begin - PCMux = 2'b10; - UnalignedSelect = 1'b1; - spillSave = 1'b1; /// *** Could pipeline these to make it clearer in the fsm. - ICacheReadEn = 1'b1; - NextState = STATE_MISS_SPILL_2_START; + PCMux = 2'b10; + UnalignedSelect = 1'b1; + spillSave = 1'b1; /// *** Could pipeline these to make it clearer in the fsm. + ICacheReadEn = 1'b1; + NextState = STATE_MISS_SPILL_2_START; end STATE_MISS_SPILL_2_START: begin - if (~hit) begin - CntReset = 1'b1; - NextState = STATE_MISS_SPILL_MISS_FETCH_WDV; - end else begin - NextState = STATE_READY; - ICacheReadEn = 1'b1; - PCMux = 2'b00; - UnalignedSelect = 1'b1; - SavePC = 1'b1; - ICacheStallF = 1'b0; - end + if (~hit) begin + CntReset = 1'b1; + NextState = STATE_MISS_SPILL_MISS_FETCH_WDV; + end else begin + NextState = STATE_READY; + ICacheReadEn = 1'b1; + PCMux = 2'b00; + UnalignedSelect = 1'b1; + SavePC = 1'b1; + ICacheStallF = 1'b0; + end end STATE_MISS_SPILL_MISS_FETCH_WDV: begin - PCMux = 2'b10; - PreCntEn = 1'b1; - //InstrReadF = 1'b1; - if (FetchCountFlag & InstrAckF) begin - NextState = STATE_MISS_SPILL_MISS_FETCH_DONE; - end else begin - NextState = STATE_MISS_SPILL_MISS_FETCH_WDV; - end + PCMux = 2'b10; + PreCntEn = 1'b1; + //InstrReadF = 1'b1; + if (FetchCountFlag & InstrAckF) begin + NextState = STATE_MISS_SPILL_MISS_FETCH_DONE; + end else begin + NextState = STATE_MISS_SPILL_MISS_FETCH_WDV; + end end STATE_MISS_SPILL_MISS_FETCH_DONE: begin - PCMux = 2'b10; - ICacheMemWriteEnable = 1'b1; - NextState = STATE_MISS_SPILL_MERGE; + PCMux = 2'b10; + ICacheMemWriteEnable = 1'b1; + NextState = STATE_MISS_SPILL_MERGE; end STATE_MISS_SPILL_MERGE: begin - PCMux = 2'b10; - UnalignedSelect = 1'b1; - ICacheReadEn = 1'b1; + PCMux = 2'b10; + UnalignedSelect = 1'b1; + ICacheReadEn = 1'b1; NextState = STATE_MISS_SPILL_FINAL; end STATE_MISS_SPILL_FINAL: begin - ICacheReadEn = 1'b1; - PCMux = 2'b00; - UnalignedSelect = 1'b1; - SavePC = 1'b1; - ICacheStallF = 1'b0; - NextState = STATE_READY; + ICacheReadEn = 1'b1; + PCMux = 2'b00; + UnalignedSelect = 1'b1; + SavePC = 1'b1; + ICacheStallF = 1'b0; + NextState = STATE_READY; end STATE_TLB_MISS: begin - if (ITLBWriteF | WalkerInstrPageFaultF) begin - NextState = STATE_TLB_MISS_DONE; - end else begin - NextState = STATE_TLB_MISS; - end + if (ITLBWriteF | WalkerInstrPageFaultF) begin + NextState = STATE_TLB_MISS_DONE; + end else begin + NextState = STATE_TLB_MISS; + end end STATE_TLB_MISS_DONE : begin - NextState = STATE_READY; + NextState = STATE_READY; end default: begin - PCMux = 2'b01; - NextState = STATE_READY; + PCMux = 2'b01; + NextState = STATE_READY; end // *** add in error handling and invalidate/evict endcase diff --git a/wally-pipelined/src/ebu/ahblite.sv b/wally-pipelined/src/ebu/ahblite.sv index 09e5799c..b0c6f033 100644 --- a/wally-pipelined/src/ebu/ahblite.sv +++ b/wally-pipelined/src/ebu/ahblite.sv @@ -139,6 +139,7 @@ module ahblite ( // (ProposedNextBusState == MMUTRANSLATE); // The PMA and PMP checkers can decide to squash the access + // *** this probably needs to be controlled by the caches rather than EBU dh 7/2/11 assign NextBusState = (DSquashBusAccessM || ISquashBusAccessF) ? IDLE : ProposedNextBusState; // stall signals diff --git a/wally-pipelined/src/fpu/mult_R4_64_64_cs.sv b/wally-pipelined/src/fpu/mult_R4_64_64_cs.sv index 7b4d3f64..eca5fadf 100644 --- a/wally-pipelined/src/fpu/mult_R4_64_64_cs.sv +++ b/wally-pipelined/src/fpu/mult_R4_64_64_cs.sv @@ -2,6 +2,7 @@ // It is unsigned and uses Radix-4 Booth encoding. // This file was automatically generated by tdm.pl. +/* module mult64 (x, y, P); input [63:0] x; @@ -18,7 +19,8 @@ module mult64 (x, y, P); //assign P = Pt[127:0]; ldf128 cpa (cout, P, Sum, Carry, 1'b0); -endmodule // mult64 +endmodule // mult64 +*/ module multiplier( y, x, Sum, Carry ); @@ -11612,7 +11614,7 @@ module r4be(x0,x1,x2,sing,doub,neg); endmodule // r4be - +/* // Use maj and two xor2's, with cin being late module fullAdd_xc(cout, s, a, b, cin); @@ -11629,7 +11631,7 @@ module fullAdd_xc(cout, s, a, b, cin); maj MAJ_0_112(cout,a,b,cin); endmodule // fullAdd_xc - +*/ module maj(y, a, b, c); @@ -11645,6 +11647,7 @@ module maj(y, a, b, c); endmodule // maj +/* // 4:2 Weinberger compressor module fourtwo_x(t, S, C, X, Y, Z, W, t_1); @@ -11664,6 +11667,7 @@ module fourtwo_x(t, S, C, X, Y, Z, W, t_1); fullAdd_xc secondCSA_0_160(C,S,W,t_1,intermediate); endmodule // fourtwo_x +*/ module inverter(egress, in); @@ -11767,6 +11771,7 @@ module fullAdd_x(cout,sum,a,b,c); endmodule // fullAdd_x +/* module nand2(egress,in1,in2); output egress; @@ -11800,7 +11805,7 @@ module and3(y,a,b,c); assign y = a&b&c; endmodule // and3 - +*/ module and2(y,a,b); output y; @@ -11810,7 +11815,7 @@ module and2(y,a,b); assign y = a&b; endmodule // and2 - +/* module nor2(egress,in1,in2); output egress; @@ -11902,6 +11907,7 @@ module oai(egress,in1,in2,in3); assign egress = ~(in3 & (in1|in2)); endmodule // oai +*/ module aoi(egress,in1,in2,in3); @@ -11949,7 +11955,7 @@ module fullAdd_i(cout_b,sum_b,a,b,c); sum_b sum_0_32(sum_b,a,b,c,cout_b); endmodule // fullAdd_i - +/* module fullAdd(cout,s,a,b,c); output cout; @@ -11979,7 +11985,7 @@ module blackCell(g_i_j, p_i_j, g_i_k, p_i_k, g_kneg1_j, p_kneg1_j); and2 and_0_48(p_i_j, p_i_k, p_kneg1_j); endmodule // blackCell - +*/ module grayCell(g_i_j, g_i_k, p_i_k, g_kneg1_j); output g_i_j; diff --git a/wally-pipelined/src/fpu/shifter_denorm.sv b/wally-pipelined/src/fpu/shifter_denorm.sv index ed208381..e56b0072 100755 --- a/wally-pipelined/src/fpu/shifter_denorm.sv +++ b/wally-pipelined/src/fpu/shifter_denorm.sv @@ -118,6 +118,7 @@ module barrel_shifter_r57 (Z, Sticky, A, Shift); endmodule // barrel_shifter_r57 +/* module barrel_shifter_r64 (Z, Sticky, A, Shift); input [63:0] A; @@ -160,3 +161,4 @@ module barrel_shifter_r64 (Z, Sticky, A, Shift); assign Sticky = (S != sixtythreezeros); endmodule // barrel_shifter_r64 +*/ \ No newline at end of file diff --git a/wally-pipelined/src/generic/flop.sv b/wally-pipelined/src/generic/flop.sv index a5636c6f..cb583de2 100644 --- a/wally-pipelined/src/generic/flop.sv +++ b/wally-pipelined/src/generic/flop.sv @@ -77,7 +77,7 @@ module flopenr #(parameter WIDTH = 8) ( output logic [WIDTH-1:0] q); always_ff @(posedge clk, posedge reset) - if (reset) q <= #1 0; + if (reset) q <= #1 0; else if (en) q <= #1 d; endmodule diff --git a/wally-pipelined/src/ifu/ifu.sv b/wally-pipelined/src/ifu/ifu.sv index 04110d9a..65f8a9b8 100644 --- a/wally-pipelined/src/ifu/ifu.sv +++ b/wally-pipelined/src/ifu/ifu.sv @@ -70,15 +70,16 @@ module ifu ( input logic [`XLEN-1:0] PageTableEntryF, input logic [1:0] PageTypeF, input logic [`XLEN-1:0] SATP_REGW, - input logic STATUS_MXR, STATUS_SUM, + input logic STATUS_MXR, STATUS_SUM, STATUS_MPRV, + input logic [1:0] STATUS_MPP, input logic ITLBWriteF, ITLBFlushF, input logic WalkerInstrPageFaultF, output logic ITLBMissF, ITLBHitF, // pmp/pma (inside mmu) signals. *** temporarily from AHB bus but eventually replace with internal versions pre H - input var logic [63:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES/8-1:0], - input var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW [`PMP_ENTRIES-1:0], + input var logic [7:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES-1:0], + input var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW[`PMP_ENTRIES-1:0], output logic PMPInstrAccessFaultF, PMAInstrAccessFaultF, output logic ISquashBusAccessF @@ -127,7 +128,7 @@ module ifu ( .TLBMiss(ITLBMissF), .TLBHit(ITLBHitF), .TLBPageFault(ITLBInstrPageFaultF), - .ExecuteAccessF(InstrReadF), /// *** Ross Thompson this is definitely wrong. InstrReadF changed to icache read to memory. + .ExecuteAccessF(1'b1), // ***dh -- this should eventually change to only true if an instruction fetch is occurring .AtomicAccessM(1'b0), .ReadAccessM(1'b0), .WriteAccessM(1'b0), diff --git a/wally-pipelined/src/lsu/lsu.sv b/wally-pipelined/src/lsu/lsu.sv index 45fdf9e0..f44f0a50 100644 --- a/wally-pipelined/src/lsu/lsu.sv +++ b/wally-pipelined/src/lsu/lsu.sv @@ -72,7 +72,8 @@ module lsu ( // page table walker input logic [`XLEN-1:0] SATP_REGW, // from csr - input logic STATUS_MXR, STATUS_SUM, // from csr + input logic STATUS_MXR, STATUS_SUM, STATUS_MPRV, + input logic [1:0] STATUS_MPP, input logic [`XLEN-1:0] PCF, input logic ITLBMissF, @@ -86,14 +87,14 @@ module lsu ( output logic DTLBHitM, // not connected // PMA/PMP (inside mmu) signals - input logic [31:0] HADDR, // *** replace all of these H inputs with physical adress once pma checkers have been edited to use paddr as well. - input logic [2:0] HSIZE, HBURST, - input logic HWRITE, - input var logic [63:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES/8-1:0], - input var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW [`PMP_ENTRIES-1:0], // *** this one especially has a large note attached to it in pmpchecker. + input logic [31:0] HADDR, // *** replace all of these H inputs with physical adress once pma checkers have been edited to use paddr as well. + input logic [2:0] HSIZE, HBURST, + input logic HWRITE, + input var logic [7:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES-1:0], + input var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW[`PMP_ENTRIES-1:0], // *** this one especially has a large note attached to it in pmpchecker. - output logic PMALoadAccessFaultM, PMAStoreAccessFaultM, - output logic PMPLoadAccessFaultM, PMPStoreAccessFaultM, // *** can these be parameterized? we dont need the m stage ones for the immu and vice versa. + output logic PMALoadAccessFaultM, PMAStoreAccessFaultM, + output logic PMPLoadAccessFaultM, PMPStoreAccessFaultM, // *** can these be parameterized? we dont need the m stage ones for the immu and vice versa. output logic DSquashBusAccessM // output logic [5:0] DHSELRegionsM diff --git a/wally-pipelined/src/mmu/adrdecs.sv b/wally-pipelined/src/mmu/adrdecs.sv index 8585a4ee..94951aad 100644 --- a/wally-pipelined/src/mmu/adrdecs.sv +++ b/wally-pipelined/src/mmu/adrdecs.sv @@ -24,12 +24,13 @@ /////////////////////////////////////////// `include "wally-config.vh" + // verilator lint_off UNOPTFLAT module adrdecs ( input logic [`PA_BITS-1:0] PhysicalAddress, input logic AccessRW, AccessRX, AccessRWX, input logic [1:0] Size, - output logic [5:0] SelRegions + output logic [6:0] SelRegions ); // Determine which region of physical memory (if any) is being accessed @@ -41,5 +42,8 @@ module adrdecs ( adrdec uartdec(PhysicalAddress, `UART_BASE, `UART_RANGE, `UART_SUPPORTED, AccessRW, Size, 4'b0001, SelRegions[1]); adrdec plicdec(PhysicalAddress, `PLIC_BASE, `PLIC_RANGE, `PLIC_SUPPORTED, AccessRW, Size, 4'b0100, SelRegions[0]); + assign SelRegions[6] = ~|(SelRegions[5:0]); + endmodule + // verilator lint_on UNOPTFLAT diff --git a/wally-pipelined/src/mmu/mmu.sv b/wally-pipelined/src/mmu/mmu.sv index 8082d01a..e28db2e7 100644 --- a/wally-pipelined/src/mmu/mmu.sv +++ b/wally-pipelined/src/mmu/mmu.sv @@ -34,7 +34,8 @@ module mmu #(parameter ENTRY_BITS = 3, input logic clk, reset, // Current value of satp CSR (from privileged unit) input logic [`XLEN-1:0] SATP_REGW, - input logic STATUS_MXR, STATUS_SUM, + input logic STATUS_MXR, STATUS_SUM, STATUS_MPRV, + input logic [1:0] STATUS_MPP, // Current privilege level of the processeor input logic [1:0] PrivilegeModeW, @@ -68,7 +69,7 @@ module mmu #(parameter ENTRY_BITS = 3, // PMA checker signals input logic AtomicAccessM, ExecuteAccessF, WriteAccessM, ReadAccessM, - input var logic [63:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES/8-1:0], + input var logic [7:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES-1:0], input var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW [`PMP_ENTRIES-1:0], output logic SquashBusAccess, // *** send to privileged unit diff --git a/wally-pipelined/src/mmu/pmachecker.sv b/wally-pipelined/src/mmu/pmachecker.sv index 8d31f3ae..86abcb3f 100644 --- a/wally-pipelined/src/mmu/pmachecker.sv +++ b/wally-pipelined/src/mmu/pmachecker.sv @@ -32,9 +32,6 @@ module pmachecker ( input logic [`PA_BITS-1:0] PhysicalAddress, input logic [1:0] Size, -// input logic [31:0] HADDR, -// input logic [2:0] HSIZE, -// input logic [2:0] HBURST, // *** in AHBlite, HBURST is hardwired to zero for single bursts only allowed. consider removing from this module if unused. input logic AtomicAccessM, ExecuteAccessF, WriteAccessM, ReadAccessM, // *** atomicaccessM is unused but might want to stay in for future use. @@ -46,10 +43,9 @@ module pmachecker ( output logic PMAStoreAccessFaultM ); - // logic BootTim, Tim, CLINT, GPIO, UART, PLIC; logic PMAAccessFault; logic AccessRW, AccessRWX, AccessRX; - logic [5:0] SelRegions; + logic [6:0] SelRegions; // Determine what type of access is being made assign AccessRW = ReadAccessM | WriteAccessM; diff --git a/wally-pipelined/src/mmu/pmpadrdec.sv b/wally-pipelined/src/mmu/pmpadrdec.sv index 3286368f..50d399ae 100644 --- a/wally-pipelined/src/mmu/pmpadrdec.sv +++ b/wally-pipelined/src/mmu/pmpadrdec.sv @@ -31,35 +31,42 @@ module pmpadrdec ( input logic [`PA_BITS-1:0] PhysicalAddress, -// input logic [31:0] HADDR, // *** replace with PAdr - input logic [1:0] AdrMode, - input logic [`XLEN-1:0] CurrentPMPAdr, - input logic AdrAtLeastPreviousPMP, - output logic AdrAtLeastCurrentPMP, - output logic Match + input logic [7:0] PMPCfg, + input logic [`XLEN-1:0] PMPAdr, + input logic PAgePMPAdrIn, + input logic NoLowerMatchIn, + output logic PAgePMPAdrOut, + output logic NoLowerMatchOut, + output logic Match, Active, + output logic L, X, W, R ); + localparam TOR = 2'b01; localparam NA4 = 2'b10; localparam NAPOT = 2'b11; logic TORMatch, NAMatch; - logic AdrBelowCurrentPMP; + logic PAltPMPAdr; + logic FirstMatch; logic [`PA_BITS-1:0] CurrentAdrFull; -// logic [`PA_BITS-1:0] FakePhysAdr; + logic [1:0] AdrMode; - // ***replace this when the true physical address from MMU is available -// assign FakePhysAdr = {{(`PA_BITS-32){1'b0}}, HADDR}; + + assign AdrMode = PMPCfg[4:3]; + + // The two lsb of the physical address don't matter for this checking. + // The following code includes them, but hardwires the PMP checker lsbs to 00 + // and masks them later. Logic synthesis should optimize away these bottom bits. // Top-of-range (TOR) // Append two implicit trailing 0's to PMPAdr value - assign CurrentAdrFull = {CurrentPMPAdr[`PA_BITS-3:0], 2'b00}; - assign AdrBelowCurrentPMP = PhysicalAddress < CurrentAdrFull; // *** make sure unsigned comparison works correctly - assign AdrAtLeastCurrentPMP = ~AdrBelowCurrentPMP; - assign TORMatch = AdrAtLeastPreviousPMP && AdrBelowCurrentPMP; + assign CurrentAdrFull = {PMPAdr[`PA_BITS-3:0], 2'b00}; + assign PAltPMPAdr = {1'b0, PhysicalAddress} < {1'b0, CurrentAdrFull}; // unsigned comparison + assign PAgePMPAdrOut = ~PAltPMPAdr; + assign TORMatch = PAgePMPAdrIn && PAltPMPAdr; // Naturally aligned regions - // *** should be able to optimize away bottom 2 bits // verilator lint_off UNOPTFLAT logic [`PA_BITS-1:0] Mask; @@ -70,69 +77,22 @@ module pmpadrdec ( assign Mask[1:0] = 2'b11; assign Mask[2] = (AdrMode == NAPOT); // mask has 0s in upper bis for NA4 region for (i=3; i < `PA_BITS; i=i+1) - assign Mask[i] = Mask[i-1] & CurrentPMPAdr[i-3]; // NAPOT mask: 1's indicate bits to ignore + assign Mask[i] = Mask[i-1] & PMPAdr[i-3]; // NAPOT mask: 1's indicate bits to ignore endgenerate // verilator lint_on UNOPTFLAT assign NAMatch = &((PhysicalAddress ~^ CurrentAdrFull) | Mask); - /* generate - if (`XLEN == 32 || `XLEN == 64) begin // ***redo for various sizes - // priority encoder to translate address to range - // *** We'd like to replace this with a better priority encoder - // *** We should not be truncating 64 bit physical addresses to 32 bits... - // *** there is an easy combinatinoal way to do this with a cascade of AND gates O(32) rather than O(32^2) dh - always_comb - if (AdrMode == NA4) Range = (2**2) - 1; - else casez (CurrentPMPAdr[31:0]) // NAPOT regions - 32'b???????????????????????????????0: Range = (2**3) - 1; - 32'b??????????????????????????????01: Range = (2**4) - 1; - 32'b?????????????????????????????011: Range = (2**5) - 1; - 32'b????????????????????????????0111: Range = (2**6) - 1; - 32'b???????????????????????????01111: Range = (2**7) - 1; - 32'b??????????????????????????011111: Range = (2**8) - 1; - 32'b?????????????????????????0111111: Range = (2**9) - 1; - 32'b????????????????????????01111111: Range = (2**10) - 1; - 32'b???????????????????????011111111: Range = (2**11) - 1; - 32'b??????????????????????0111111111: Range = (2**12) - 1; - 32'b?????????????????????01111111111: Range = (2**13) - 1; - 32'b????????????????????011111111111: Range = (2**14) - 1; - 32'b???????????????????0111111111111: Range = (2**15) - 1; - 32'b??????????????????01111111111111: Range = (2**16) - 1; - 32'b?????????????????011111111111111: Range = (2**17) - 1; - 32'b????????????????0111111111111111: Range = (2**18) - 1; - 32'b???????????????01111111111111111: Range = (2**19) - 1; - 32'b??????????????011111111111111111: Range = (2**20) - 1; - 32'b?????????????0111111111111111111: Range = (2**21) - 1; - 32'b????????????01111111111111111111: Range = (2**22) - 1; - 32'b???????????011111111111111111111: Range = (2**23) - 1; - 32'b??????????0111111111111111111111: Range = (2**24) - 1; - 32'b?????????01111111111111111111111: Range = (2**25) - 1; - 32'b????????011111111111111111111111: Range = (2**26) - 1; - 32'b???????0111111111111111111111111: Range = (2**27) - 1; - 32'b??????01111111111111111111111111: Range = (2**28) - 1; - 32'b?????011111111111111111111111111: Range = (2**29) - 1; - 32'b????0111111111111111111111111111: Range = (2**30) - 1; - 32'b???01111111111111111111111111111: Range = (2**31) - 1; - 32'b??011111111111111111111111111111: Range = (2**32) - 1; - 32'b?0111111111111111111111111111111: Range = (2**33) - 1; - 32'b01111111111111111111111111111111: Range = (2**34) - 1; - 32'b11111111111111111111111111111111: Range = (2**35) - 1; - default: Range = '0; - endcase - end else begin - assign Range = '0; - end - endgenerate - - // *** Range should not be truncated... but our physical address space is - // currently only 32 bits wide. - // with a bit of combining of range selection, this could be shared with NA4Match *** - assign NAMatch = &((HADDR ~^ CurrentAdrFull) | Range[31:0]);*/ - assign Match = (AdrMode == TOR) ? TORMatch : (AdrMode == NA4 || AdrMode == NAPOT) ? NAMatch : 0; -endmodule + assign FirstMatch = NoLowerMatchIn & Match; + assign NoLowerMatchOut = NoLowerMatchIn & ~Match; + assign L = PMPCfg[7] & FirstMatch; + assign X = PMPCfg[2] & FirstMatch; + assign W = PMPCfg[1] & FirstMatch; + assign R = PMPCfg[0] & FirstMatch; + assign Active = |PMPCfg[4:3]; + endmodule diff --git a/wally-pipelined/src/mmu/pmpchecker.sv b/wally-pipelined/src/mmu/pmpchecker.sv index 409e2ccb..ee4b261d 100644 --- a/wally-pipelined/src/mmu/pmpchecker.sv +++ b/wally-pipelined/src/mmu/pmpchecker.sv @@ -29,12 +29,8 @@ `include "wally-config.vh" module pmpchecker ( -// input logic clk, reset, //*** it seems like clk, reset is also not needed here? input logic [`PA_BITS-1:0] PhysicalAddress, -// input logic [31:0] HADDR, - - input logic [1:0] PrivilegeModeW, - + input logic [1:0] PrivilegeModeW, // *** ModelSim has a switch -svinputport which controls whether input ports // are nets (wires) or vars by default. The default setting of this switch is @@ -43,11 +39,7 @@ module pmpchecker ( // this will be understood as a var. However, if we don't supply the `var` // keyword, the compiler warns us that it's interpreting the signal as a var, // which we might not intend. - // However, it's still bad form to pass 512 or 1024 signals across a module - // boundary. It would be better to store the PMP address registers in a module - // somewhere in the CSR hierarchy and do PMP checking _within_ that module, so - // we don't have to pass around 16 whole registers. - input var logic [63:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES/8-1:0], + input var logic [7:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES-1:0], input var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW [`PMP_ENTRIES-1:0], input logic ExecuteAccessF, WriteAccessM, ReadAccessM, @@ -59,111 +51,42 @@ module pmpchecker ( output logic PMPStoreAccessFaultM ); + // Bit i is high when the address falls in PMP region i - logic [`PMP_ENTRIES-1:0] Regions, FirstMatch; - //logic [3:0] MatchedRegion; - logic EnforcePMP; - - logic [7:0] PMPCFG [`PMP_ENTRIES-1:0]; - - // Bit i is high when the address is greater than or equal to PMPADR[i] - // Used for determining whether TOR PMP regions match - logic [`PMP_ENTRIES-1:0] AboveRegion; - - // Bit i is high if PMP register i is non-null - logic [`PMP_ENTRIES-1:0] ActiveRegion; - - logic [`PMP_ENTRIES-1:0] L_Bits, X_Bits, W_Bits, R_Bits; - //logic InvalidExecute, InvalidWrite, InvalidRead; - - genvar i,j; - - pmpadrdec pmpadrdec(.PhysicalAddress(PhysicalAddress), - .AdrMode(PMPCFG[0][4:3]), - .CurrentPMPAdr(PMPADDR_ARRAY_REGW[0]), - .AdrAtLeastPreviousPMP(1'b1), - .AdrAtLeastCurrentPMP(AboveRegion[0]), - .Match(Regions[0])); - - assign ActiveRegion[0] = |PMPCFG[0][4:3]; - - generate // *** only for PMP_ENTRIES > 0 - for (i = 1; i < `PMP_ENTRIES; i++) begin - pmpadrdec pmpadrdec(.PhysicalAddress(PhysicalAddress), - .AdrMode(PMPCFG[i][4:3]), - .CurrentPMPAdr(PMPADDR_ARRAY_REGW[i]), - .AdrAtLeastPreviousPMP(AboveRegion[i-1]), - .AdrAtLeastCurrentPMP(AboveRegion[i]), - .Match(Regions[i])); - - assign ActiveRegion[i] = |PMPCFG[i][4:3]; - end - endgenerate - - //assign Match = |Regions; - + logic EnforcePMP; + logic [7:0] PMPCfg[`PMP_ENTRIES-1:0]; + logic [`PMP_ENTRIES-1:0] Match; // PMP Entry matches + logic [`PMP_ENTRIES-1:0] Active; // PMP register i is non-null + logic [`PMP_ENTRIES-1:0] L, X, W, R; // PMP matches and has flag set // verilator lint_off UNOPTFLAT - logic [`PMP_ENTRIES-1:0] NoLowerMatch; -// assign NoLowerMatch[0] = 1; - generate - // verilator lint_off WIDTH - for (j=0; j<`PMP_ENTRIES; j = j+8) begin - assign {PMPCFG[j+7], PMPCFG[j+6], PMPCFG[j+5], PMPCFG[j+4], - PMPCFG[j+3], PMPCFG[j+2], PMPCFG[j+1], PMPCFG[j]} = PMPCFG_ARRAY_REGW[j/8]; - end - // verilator lint_on WIDTH - for (i=0; i<`PMP_ENTRIES; i++) begin - if (i==0) begin - assign FirstMatch[i] = Regions[i]; - assign NoLowerMatch[i] = ~Regions[i]; - end else begin - assign FirstMatch[i] = Regions[i] & NoLowerMatch[i]; - assign NoLowerMatch[i] = NoLowerMatch[i-1] & ~Regions[i]; - end - assign L_Bits[i] = PMPCFG[i][7] & FirstMatch[i]; - assign X_Bits[i] = PMPCFG[i][2] & FirstMatch[i]; - assign W_Bits[i] = PMPCFG[i][1] & FirstMatch[i]; - assign R_Bits[i] = PMPCFG[i][0] & FirstMatch[i]; - end - // verilator lint_on UNOPTFLAT - endgenerate -/* // *** extend to up to 64, fold bit extraction to avoid need for binary encoding of region - always_comb - casez (Regions) - 16'b???????????????1: MatchedRegion = 0; - 16'b??????????????10: MatchedRegion = 1; - 16'b?????????????100: MatchedRegion = 2; - 16'b????????????1000: MatchedRegion = 3; - 16'b???????????10000: MatchedRegion = 4; - 16'b??????????100000: MatchedRegion = 5; - 16'b?????????1000000: MatchedRegion = 6; - 16'b????????10000000: MatchedRegion = 7; - 16'b???????100000000: MatchedRegion = 8; - 16'b??????1000000000: MatchedRegion = 9; - 16'b?????10000000000: MatchedRegion = 10; - 16'b????100000000000: MatchedRegion = 11; - 16'b???1000000000000: MatchedRegion = 12; - 16'b??10000000000000: MatchedRegion = 13; - 16'b?100000000000000: MatchedRegion = 14; - 16'b1000000000000000: MatchedRegion = 15; - default: MatchedRegion = 0; // Should only occur if there is no match - endcase + logic [`PMP_ENTRIES-1:0] NoLowerMatch; // None of the lower PMP entries match + // verilator lint_on UNOPTFLAT + logic [`PMP_ENTRIES-1:0] PAgePMPAdr; // for TOR PMP matching, PhysicalAddress > PMPAdr[i] + genvar i,j; + /* + generate // extract 8-bit chunks from PMPCFG array + for (j=0; j<`PMP_ENTRIES; j = j+8) + assign {PMPCfg[j+7], PMPCfg[j+6], PMPCfg[j+5], PMPCfg[j+4], + PMPCfg[j+3], PMPCfg[j+2], PMPCfg[j+1], PMPCfg[j]} = PMPCFG_ARRAY_REGW[j/8]; + endgenerate */ - assign L_Bit = PMPCFG[MatchedRegion][7] && Match; - assign X_Bit = PMPCFG[MatchedRegion][2] && Match; - assign W_Bit = PMPCFG[MatchedRegion][1] && Match; - assign R_Bit = PMPCFG[MatchedRegion][0] && Match; + pmpadrdec pmpadrdecs[`PMP_ENTRIES-1:0]( + .PhysicalAddress, + .PMPCfg(PMPCFG_ARRAY_REGW), + .PMPAdr(PMPADDR_ARRAY_REGW), + .PAgePMPAdrIn({PAgePMPAdr[`PMP_ENTRIES-2:0], 1'b1}), + .PAgePMPAdrOut(PAgePMPAdr), + .NoLowerMatchIn({NoLowerMatch[`PMP_ENTRIES-2:0], 1'b1}), + .NoLowerMatchOut(NoLowerMatch), + .Match, .Active, .L, .X, .W, .R); - assign InvalidExecute = ExecuteAccessF && ~X_Bit; - assign InvalidWrite = WriteAccessM && ~W_Bit; - assign InvalidRead = ReadAccessM && ~R_Bit;*/ // Only enforce PMP checking for S and U modes when at least one PMP is active or in Machine mode when L bit is set in selected region - assign EnforcePMP = (PrivilegeModeW == `M_MODE) ? |L_Bits : |ActiveRegion; + assign EnforcePMP = (PrivilegeModeW == `M_MODE) ? |L : |Active; - assign PMPInstrAccessFaultF = EnforcePMP && ExecuteAccessF && ~|X_Bits; - assign PMPStoreAccessFaultM = EnforcePMP && WriteAccessM && ~|W_Bits; - assign PMPLoadAccessFaultM = EnforcePMP && ReadAccessM && ~|R_Bits; + assign PMPInstrAccessFaultF = EnforcePMP && ExecuteAccessF && ~|X; + assign PMPStoreAccessFaultM = EnforcePMP && WriteAccessM && ~|W; + assign PMPLoadAccessFaultM = EnforcePMP && ReadAccessM && ~|R; assign PMPSquashBusAccess = PMPInstrAccessFaultF | PMPLoadAccessFaultM | PMPStoreAccessFaultM; diff --git a/wally-pipelined/src/mmu/tlb.sv b/wally-pipelined/src/mmu/tlb.sv index 1cf63906..2741f958 100644 --- a/wally-pipelined/src/mmu/tlb.sv +++ b/wally-pipelined/src/mmu/tlb.sv @@ -55,7 +55,8 @@ module tlb #(parameter ENTRY_BITS = 3, // Current value of satp CSR (from privileged unit) input logic [`XLEN-1:0] SATP_REGW, - input logic STATUS_MXR, STATUS_SUM, + input logic STATUS_MXR, STATUS_SUM, STATUS_MPRV, + input logic [1:0] STATUS_MPP, // Current privilege level of the processeor input logic [1:0] PrivilegeModeW, @@ -87,20 +88,23 @@ module tlb #(parameter ENTRY_BITS = 3, output logic TLBPageFault ); + localparam NENTRIES = 2**ENTRY_BITS; + logic Translate; logic TLBAccess, ReadAccess, WriteAccess; // Store current virtual memory mode (SV32, SV39, SV48, ect...) logic [`SVMODE_BITS-1:0] SvMode; + logic [1:0] EffectivePrivilegeMode; // privilege mode, possibly modified by MPRV - // Index (currently random) to write the next TLB entry - logic [ENTRY_BITS-1:0] WriteIndex; - logic [(2**ENTRY_BITS)-1:0] WriteLines; // used as the one-hot encoding of WriteIndex + //logic [ENTRY_BITS-1:0] WriteIndex; + logic [NENTRIES-1:0] ReadLines, WriteLines, WriteEnables; // used as the one-hot encoding of WriteIndex // Sections of the virtual and physical addresses logic [`VPN_BITS-1:0] VirtualPageNumber; logic [`PPN_BITS-1:0] PhysicalPageNumber, PhysicalPageNumberMixed; logic [`PA_BITS-1:0] PhysicalAddressFull; + logic [`XLEN+1:0] VAExt; // Sections of the page table entry logic [7:0] PTEAccessBits; @@ -110,17 +114,20 @@ module tlb #(parameter ENTRY_BITS = 3, logic PTE_U, PTE_X, PTE_W, PTE_R; // Pattern location in the CAM and type of page hit - logic [ENTRY_BITS-1:0] VPNIndex; + //ogic [ENTRY_BITS-1:0] VPNIndex; logic [1:0] HitPageType; // Whether the virtual address has a match in the CAM logic CAMHit; - // Grab the sv mode from SATP + // Grab the sv mode from SATP and determine whether translation should occur assign SvMode = SATP_REGW[`XLEN-1:`XLEN-`SVMODE_BITS]; + assign EffectivePrivilegeMode = (ITLB == 1) ? PrivilegeModeW : (STATUS_MPRV ? STATUS_MPP : PrivilegeModeW); // DTLB uses MPP mode when MPRV is 1 + assign Translate = (SvMode != `NO_TRANSLATE) & (EffectivePrivilegeMode != `M_MODE) & ~ DisableTranslation; // Decode the integer encoded WriteIndex into the one-hot encoded WriteLines - decoder #(ENTRY_BITS) writedecoder(WriteIndex, WriteLines); + //decoder #(ENTRY_BITS) writedecoder(WriteIndex, WriteLines); + assign WriteEnables = WriteLines & {(2**ENTRY_BITS){TLBWrite}}; // The bus width is always the largest it could be for that XLEN. For example, vpn will be 36 bits wide in rv64 // this, even though it could be 27 bits (SV39) or 36 bits (SV48) wide. When the value of VPN is narrower, @@ -135,79 +142,64 @@ module tlb #(parameter ENTRY_BITS = 3, end endgenerate - // Whether translation should occur - assign Translate = (SvMode != `NO_TRANSLATE) & (PrivilegeModeW != `M_MODE) & ~ DisableTranslation; - + // Determine how the TLB is currently being used // Note that we use ReadAccess for both loads and instruction fetches assign ReadAccess = TLBAccessType[1]; assign WriteAccess = TLBAccessType[0]; assign TLBAccess = ReadAccess || WriteAccess; - - assign PageOffset = VirtualAddress[11:0]; // TLB entries are evicted according to the LRU algorithm tlblru #(ENTRY_BITS) lru(.*); + // TLB memory tlbram #(ENTRY_BITS) tlbram(.*); tlbcam #(ENTRY_BITS, `VPN_BITS, `VPN_SEGMENT_BITS) tlbcam(.*); - // unswizzle useful PTE bits - assign PTE_U = PTEAccessBits[4]; - assign PTE_X = PTEAccessBits[3]; - assign PTE_W = PTEAccessBits[2]; - assign PTE_R = PTEAccessBits[1]; + // Replace segments of the virtual page number with segments of the physical + // page number. For 4 KB pages, the entire virtual page number is replaced. + // For superpages, some segments are considered offsets into a larger page. + tlbphysicalpagemask PageMask(VirtualPageNumber, PhysicalPageNumber, HitPageType, PhysicalPageNumberMixed); + // unswizzle useful PTE bits + assign {PTE_U, PTE_X, PTE_W, PTE_R} = PTEAccessBits[4:1]; + // Check whether the access is allowed, page faulting if not. - // *** We might not have S mode. generate if (ITLB == 1) begin logic ImproperPrivilege; // User mode may only execute user mode pages, and supervisor mode may // only execute non-user mode pages. - assign ImproperPrivilege = ((PrivilegeModeW == `U_MODE) && ~PTE_U) || - ((PrivilegeModeW == `S_MODE) && PTE_U); + assign ImproperPrivilege = ((EffectivePrivilegeMode == `U_MODE) && ~PTE_U) || + ((EffectivePrivilegeMode == `S_MODE) && PTE_U); assign TLBPageFault = Translate && TLBHit && (ImproperPrivilege || ~PTE_X); end else begin logic ImproperPrivilege, InvalidRead, InvalidWrite; // User mode may only load/store from user mode pages, and supervisor mode // may only access user mode pages when STATUS_SUM is low. - assign ImproperPrivilege = ((PrivilegeModeW == `U_MODE) && ~PTE_U) || - ((PrivilegeModeW == `S_MODE) && PTE_U && ~STATUS_SUM); + assign ImproperPrivilege = ((EffectivePrivilegeMode == `U_MODE) && ~PTE_U) || + ((EffectivePrivilegeMode == `S_MODE) && PTE_U && ~STATUS_SUM); // Check for read error. Reads are invalid when the page is not readable // (and executable pages are not readable) or when the page is neither // readable nor executable (and executable pages are readable). - assign InvalidRead = ReadAccess && - ((~STATUS_MXR && ~PTE_R) || (STATUS_MXR && ~PTE_R && PTE_X)); + assign InvalidRead = ReadAccess && ~PTE_R && (~STATUS_MXR | ~PTE_X); // Check for write error. Writes are invalid when the page's write bit is // low. assign InvalidWrite = WriteAccess && ~PTE_W; - assign TLBPageFault = Translate && TLBHit && - (ImproperPrivilege || InvalidRead || InvalidWrite); + assign TLBPageFault = Translate && TLBHit && (ImproperPrivilege || InvalidRead || InvalidWrite); end endgenerate - // Replace segments of the virtual page number with segments of the physical - // page number. For 4 KB pages, the entire virtual page number is replaced. - // For superpages, some segments are considered offsets into a larger page. - physicalpagemask PageNumberMixer(VirtualPageNumber, PhysicalPageNumber, HitPageType, PhysicalPageNumberMixed); - - // Provide physical address only on TLBHits to cause catastrophic errors if - // garbage address is used. - assign PhysicalAddressFull = (TLBHit) ? - {PhysicalPageNumberMixed, PageOffset} : '0; // Output the hit physical address if translation is currently on. - generate - if (`XLEN == 32) begin - mux2 #(`PA_BITS) addressmux({2'b0, VirtualAddress}, PhysicalAddressFull, Translate, PhysicalAddress); - end else begin - mux2 #(`PA_BITS) addressmux(VirtualAddress[`PA_BITS-1:0], PhysicalAddressFull, Translate, PhysicalAddress); - end - endgenerate + // Provide physical address of zero if not TLBHits, to cause segmentation error if miss somehow percolated through signal + assign VAExt = {2'b00, VirtualAddress}; // extend length of virtual address if necessary for RV32 + assign PageOffset = VirtualAddress[11:0]; + assign PhysicalAddressFull = TLBHit ? {PhysicalPageNumberMixed, PageOffset} : '0; + mux2 #(`PA_BITS) addressmux(VAExt[`PA_BITS-1:0], PhysicalAddressFull, Translate, PhysicalAddress); assign TLBHit = CAMHit & TLBAccess; assign TLBMiss = ~TLBHit & ~TLBFlush & Translate & TLBAccess; diff --git a/wally-pipelined/src/mmu/tlbcam.sv b/wally-pipelined/src/mmu/tlbcam.sv index bd64afea..ef64e0d6 100644 --- a/wally-pipelined/src/mmu/tlbcam.sv +++ b/wally-pipelined/src/mmu/tlbcam.sv @@ -34,20 +34,18 @@ module tlbcam #(parameter ENTRY_BITS = 3, input logic clk, reset, input logic [KEY_BITS-1:0] VirtualPageNumber, input logic [1:0] PageTypeWriteVal, -// input logic [`SVMODE_BITS-1:0] SvMode, // *** may not need to be used. - input logic TLBWrite, input logic TLBFlush, - input logic [2**ENTRY_BITS-1:0] WriteLines, + input logic [2**ENTRY_BITS-1:0] WriteEnables, - output logic [ENTRY_BITS-1:0] VPNIndex, + //output logic [ENTRY_BITS-1:0] VPNIndex, + output logic [2**ENTRY_BITS-1:0] ReadLines, output logic [1:0] HitPageType, output logic CAMHit ); localparam NENTRIES = 2**ENTRY_BITS; - - logic [1:0] PageTypeList [NENTRIES-1:0]; + logic [1:0] PageTypeRead [NENTRIES-1:0]; logic [NENTRIES-1:0] Matches; // Create NENTRIES CAM lines, each of which will independently consider @@ -55,23 +53,19 @@ module tlbcam #(parameter ENTRY_BITS = 3, // original virtual page number from when the address was written, regardless // of page type. However, matches are determined based on a subset of the // page number segments. - generate - genvar i; - for (i = 0; i < NENTRIES; i++) begin - camline #(KEY_BITS, SEGMENT_BITS) camline( - .CAMLineWrite(WriteLines[i] && TLBWrite), - .PageType(PageTypeList[i]), - .Match(Matches[i]), - .*); - end - endgenerate + + tlbcamline #(KEY_BITS, SEGMENT_BITS) camlines[NENTRIES-1:0]( + .WriteEnable(WriteEnables), + .PageTypeRead, // *** change name to agree + .Match(ReadLines), // *** change name to agree + .*); // In case there are multiple matches in the CAM, select only one // *** it might be guaranteed that the CAM will never have multiple matches. // If so, this is just an encoder - priorityencoder #(ENTRY_BITS) matchencoder(Matches, VPNIndex); + //priorityencoder #(ENTRY_BITS) matchencoder(Matches, VPNIndex); - assign CAMHit = |Matches & ~TLBFlush; - assign HitPageType = PageTypeList[VPNIndex]; + assign CAMHit = |ReadLines & ~TLBFlush; + assign HitPageType = PageTypeRead.or; // applies OR to elements of the (NENTRIES x 2) array to get 2-bit result endmodule diff --git a/wally-pipelined/src/mmu/camline.sv b/wally-pipelined/src/mmu/tlbcamline.sv similarity index 83% rename from wally-pipelined/src/mmu/camline.sv rename to wally-pipelined/src/mmu/tlbcamline.sv index 6e3f705c..605d8f30 100644 --- a/wally-pipelined/src/mmu/camline.sv +++ b/wally-pipelined/src/mmu/tlbcamline.sv @@ -1,5 +1,5 @@ /////////////////////////////////////////// -// camline.sv +// tlbcamline.sv // // Written: tfleming@hmc.edu & jtorrey@hmc.edu 6 April 2021 // Modified: kmacsaigoren@hmc.edu 1 June 2021 @@ -28,7 +28,7 @@ `include "wally-config.vh" -module camline #(parameter KEY_BITS = 20, +module tlbcamline #(parameter KEY_BITS = 20, parameter SEGMENT_BITS = 10) ( input logic clk, reset, @@ -39,7 +39,7 @@ module camline #(parameter KEY_BITS = 20, input logic [KEY_BITS-1:0] VirtualPageNumber, // Signals to write a new entry to this line - input logic CAMLineWrite, + input logic WriteEnable, input logic [1:0] PageTypeWriteVal, // Flush this line (set valid to 0) @@ -50,19 +50,21 @@ module camline #(parameter KEY_BITS = 20, // PageType == 2'b01 --> megapage // PageType == 2'b10 --> gigapage // PageType == 2'b11 --> terapage - output logic [1:0] PageType, // *** should this be the stored version or the always updated one? + output logic [1:0] PageTypeRead, // *** should this be the stored version or the always updated one? output logic Match ); // This entry has KEY_BITS for the key plus one valid bit. logic Valid; logic [KEY_BITS-1:0] Key; + logic [1:0] PageType; - // Split up key and query into sections for each page table level. logic [SEGMENT_BITS-1:0] Key0, Key1, Query0, Query1; logic Match0, Match1; + // *** need to add ASID and G bit support + generate if (`XLEN == 32) begin @@ -85,26 +87,26 @@ module camline #(parameter KEY_BITS = 20, assign {Key3, Key2, Key1, Key0} = Key; // Calculate the actual match value based on the input vpn and the page type. - // For example, a gigapage in SV only cares about VPN[2], so VPN[0] and VPN[1] + // For example, a gigapage in SV39 only cares about VPN[2], so VPN[0] and VPN[1] // should automatically match. assign Match0 = (Query0 == Key0) || (PageType > 2'd0); // least signifcant section assign Match1 = (Query1 == Key1) || (PageType > 2'd1); assign Match2 = (Query2 == Key2) || (PageType > 2'd2); - assign Match3 = (Query3 == Key3); // *** this should always match in sv39 since both vPN3 and key3 are zeroed by the pagetable walker before getting to the cam + assign Match3 = (Query3 == Key3); // this should always match in sv39 since both vPN3 and key3 are zeroed by the pagetable walker before getting to the cam assign Match = Match0 & Match1 & Match2 & Match3 & Valid; end endgenerate // On a write, update the type of the page referred to by this line. - flopenr #(2) pagetypeflop(clk, reset, CAMLineWrite, PageTypeWriteVal, PageType); - //mux2 #(2) pagetypemux(StoredPageType, PageTypeWrite, CAMLineWrite, PageType); + flopenr #(2) pagetypeflop(clk, reset, WriteEnable, PageTypeWriteVal, PageType); + assign PageTypeRead = PageType & {2{Match}}; // On a write, set the valid bit high and update the stored key. // On a flush, zero the valid bit and leave the key unchanged. // *** Might we want to update stored key right away to output match on the // write cycle? (using a mux) - flopenrc #(1) validbitflop(clk, reset, TLBFlush, CAMLineWrite, 1'b1, Valid); - flopenr #(KEY_BITS) keyflop(clk, reset, CAMLineWrite, VirtualPageNumber, Key); + flopenrc #(1) validbitflop(clk, reset, TLBFlush, WriteEnable, 1'b1, Valid); + flopenr #(KEY_BITS) keyflop(clk, reset, WriteEnable, VirtualPageNumber, Key); endmodule diff --git a/wally-pipelined/src/mmu/tlblru.sv b/wally-pipelined/src/mmu/tlblru.sv index e86598f7..5dc1f846 100644 --- a/wally-pipelined/src/mmu/tlblru.sv +++ b/wally-pipelined/src/mmu/tlblru.sv @@ -28,11 +28,9 @@ module tlblru #(parameter ENTRY_BITS = 3) ( input logic clk, reset, input logic TLBWrite, input logic TLBFlush, - input logic [ENTRY_BITS-1:0] VPNIndex, + input logic [2**ENTRY_BITS-1:0] ReadLines, input logic CAMHit, - input logic [2**ENTRY_BITS-1:0] WriteLines, - - output logic [ENTRY_BITS-1:0] WriteIndex + output logic [2**ENTRY_BITS-1:0] WriteLines ); localparam NENTRIES = 2**ENTRY_BITS; @@ -41,29 +39,19 @@ module tlblru #(parameter ENTRY_BITS = 3) ( logic [NENTRIES-1:0] RUBits, RUBitsNext, RUBitsAccessed; // One-hot encodings of which line is being accessed - logic [NENTRIES-1:0] ReadLineOneHot, AccessLineOneHot; + logic [NENTRIES-1:0] AccessLines; // High if the next access causes all RU bits to be 1 logic AllUsed; - // Convert indices to one-hot encodings - decoder #(ENTRY_BITS) readdecoder(VPNIndex, ReadLineOneHot); - // Find the first line not recently used - priorityencoder #(ENTRY_BITS) firstnru(~RUBits, WriteIndex); + tlbpriority #(NENTRIES) nru(~RUBits, WriteLines); - // Access either the hit line or written line - assign AccessLineOneHot = (TLBWrite) ? WriteLines : ReadLineOneHot; - - // Raise the bit of the recently accessed line - assign RUBitsAccessed = AccessLineOneHot | RUBits; - - // Determine whether we need to reset the RU bits to all zeroes - assign AllUsed = &(RUBitsAccessed); - assign RUBitsNext = (AllUsed) ? AccessLineOneHot : RUBitsAccessed; - - // Update LRU state on any TLB hit or write - flopenrc #(NENTRIES) lrustate(clk, reset, TLBFlush, (CAMHit || TLBWrite), - RUBitsNext, RUBits); + // Track recently used lines, updating on a CAM Hit or TLB write + assign AccessLines = TLBWrite ? WriteLines : ReadLines; + assign RUBitsAccessed = AccessLines | RUBits; + assign AllUsed = &RUBitsAccessed; // if all recently used, then clear to none + assign RUBitsNext = AllUsed ? 0 : RUBitsAccessed; + flopenrc #(NENTRIES) lrustate(clk, reset, TLBFlush, (CAMHit || TLBWrite), RUBitsNext, RUBits); endmodule diff --git a/wally-pipelined/src/mmu/physicalpagemask.sv b/wally-pipelined/src/mmu/tlbphysicalpagemask.sv similarity index 92% rename from wally-pipelined/src/mmu/physicalpagemask.sv rename to wally-pipelined/src/mmu/tlbphysicalpagemask.sv index b1f77e2d..dd791e48 100644 --- a/wally-pipelined/src/mmu/physicalpagemask.sv +++ b/wally-pipelined/src/mmu/tlbphysicalpagemask.sv @@ -1,5 +1,5 @@ /////////////////////////////////////////// -// physicalpagemask.sv +// tlbphysicalpagemask.sv // // Written: David Harris and kmacsaigoren@hmc.edu 7 June 2021 // Modified: @@ -28,7 +28,7 @@ `include "wally-config.vh" -module physicalpagemask ( +module tlbphysicalpagemask ( input logic [`VPN_BITS-1:0] VPN, input logic [`PPN_BITS-1:0] PPN, input logic [1:0] PageType, @@ -40,13 +40,11 @@ module physicalpagemask ( logic [`PPN_BITS-1:0] ZeroExtendedVPN; logic [`PPN_BITS-1:0] PageNumberMask; - assign ZeroExtendedVPN = {{EXTRA_BITS{1'b0}}, VPN}; // forces the VPN to be the same width as PPN. - generate if (`XLEN == 32) begin always_comb case (PageType[0]) - // *** the widths of these constansts are hardocded here to match `PPN_BITS in the wally-constants file. + // the widths of these constansts are hardocded here to match `PPN_BITS in the wally-constants file. 0: PageNumberMask = 22'h3FFFFF; // kilopage: 22 bits of PPN, 0 bits of VPN 1: PageNumberMask = 22'h3FFC00; // megapage: 12 bits of PPN, 10 bits of VPN endcase @@ -57,7 +55,7 @@ module physicalpagemask ( 1: PageNumberMask = 44'hFFFFFFFFE00; // megapage: 35 bits of PPN, 9 bits of VPN 2: PageNumberMask = 44'hFFFFFFC0000; // gigapage: 26 bits of PPN, 18 bits of VPN 3: PageNumberMask = 44'hFFFF8000000; // terapage: 17 bits of PPN, 27 bits of VPN - // *** make sure that this doesnt break when using sv39. In that case, all of these + // Bus widths accomodate SV48. In SV39, all of these // busses are the widths for sv48, but extra bits should be zeroed out by the mux // in the tlb when it generates VPN from the full virtualadress. endcase @@ -65,6 +63,7 @@ module physicalpagemask ( endgenerate // merge low segments of VPN with high segments of PPN decided by the pagetype. + assign ZeroExtendedVPN = {{EXTRA_BITS{1'b0}}, VPN}; // forces the VPN to be the same width as PPN. assign MixedPageNumber = (ZeroExtendedVPN & ~PageNumberMask) | (PPN & PageNumberMask); endmodule diff --git a/wally-pipelined/src/mmu/priorityencoder.sv b/wally-pipelined/src/mmu/tlbpriority.sv similarity index 62% rename from wally-pipelined/src/mmu/priorityencoder.sv rename to wally-pipelined/src/mmu/tlbpriority.sv index d56da3d6..a061f622 100644 --- a/wally-pipelined/src/mmu/priorityencoder.sv +++ b/wally-pipelined/src/mmu/tlbpriority.sv @@ -1,16 +1,15 @@ /////////////////////////////////////////// -// priorityencoder.sv +// tlbpriority.sv // // Written: tfleming@hmc.edu & jtorrey@hmc.edu 7 April 2021 -// Based on implementation from https://www.allaboutcircuits.com/ip-cores/communication-controller/priority-encoder/ -// *** Give proper LGPL attribution for above source // Modified: Teo Ene 15 Apr 2021: // Temporarily removed paramterized priority encoder for non-parameterized one // To get synthesis working quickly // Kmacsaigoren@hmc.edu 28 May 2021: // Added working version of parameterized priority encoder. +// David_Harris@Hmc.edu switched to one-hot output // -// Purpose: One-hot encoding to binary encoder +// Purpose: Priority circuit to choose most significant one-hot output // // A component of the Wally configurable RISC-V project. // @@ -31,35 +30,20 @@ `include "wally-config.vh" -module priorityencoder #(parameter BINARY_BITS = 3) ( - input logic [2**BINARY_BITS - 1:0] onehot, - output logic [BINARY_BITS - 1:0] binary +module tlbpriority #(parameter ENTRIES = 8) ( + input logic [ENTRIES-1:0] a, + output logic [ENTRIES-1:0] y ); + // verilator lint_off UNOPTFLAT + logic [ENTRIES-1:0] nolower; - integer i; - always_comb begin - binary = 0; - for (i = 0; i < 2**BINARY_BITS; i++) begin - // verilator lint_off WIDTH - if (onehot[i]) binary = i; // prioritizes the most significant bit - // verilator lint_on WIDTH - end - end - // *** triple check synthesizability here - - // Ideally this mimics the following: - /* - always_comb begin - casex (one_hot) - 1xx ... x: binary = BINARY_BITS - 1; - 01x ... x: binary = BINARY_BITS - 2; - 001 ... x: binary = BINARY_BITS - 3; - - {...} - - 00 ... 1xx: binary = 2; - 00 ... 01x: binary = 1; - 00 ... 001: binary = 0; - end - */ + // generate thermometer code mask + genvar i; + generate + assign nolower[0] = 1; + for (i=1; i= PMPADDR0 && CSRAdrM < PMPADDR0 + `PMP_ENTRIES) // reading a PMP entry CSRMReadValM = PMPADDR_ARRAY_REGW[CSRAdrM - PMPADDR0]; - else if (CSRAdrM >= PMPCFG0 && CSRAdrM < PMPCFG0 + `PMP_ENTRIES/8) begin - if (~CSRAdrM[0]) CSRMReadValM = PMPCFG_ARRAY_REGW[CSRAdrM - PMPCFG0][`XLEN-1:0]; - else CSRMReadValM = {{(`XLEN-32){1'b0}}, PMPCFG_ARRAY_REGW[CSRAdrM - PMPCFG0][63:32]}; + else if (CSRAdrM >= PMPCFG0 && CSRAdrM < PMPCFG0 + `PMP_ENTRIES/4) begin + if (`XLEN==64) begin + entry = ({CSRAdrM[11:1], 1'b0} - PMPCFG0)*4; // disregard odd entries in RV64 + CSRMReadValM = {PMPCFG_ARRAY_REGW[entry+7],PMPCFG_ARRAY_REGW[entry+6],PMPCFG_ARRAY_REGW[entry+5],PMPCFG_ARRAY_REGW[entry+4], + PMPCFG_ARRAY_REGW[entry+3],PMPCFG_ARRAY_REGW[entry+2],PMPCFG_ARRAY_REGW[entry+1],PMPCFG_ARRAY_REGW[entry]}; + end else begin + entry = (CSRAdrM - PMPCFG0)*4; + CSRMReadValM = {PMPCFG_ARRAY_REGW[entry+3],PMPCFG_ARRAY_REGW[entry+2],PMPCFG_ARRAY_REGW[entry+1],PMPCFG_ARRAY_REGW[entry]}; + end + + /* + if (~CSRAdrM[0]) CSRMReadValM = {PMPCFG_ARRAY_REGW[]}; + else CSRMReadValM = {{(`XLEN-32){1'b0}}, PMPCFG_ARRAY_REGW[(CSRAdrM - PMPCFG0-1)/2][63:32]};*/ end else case (CSRAdrM) MISA_ADR: CSRMReadValM = MISA_REGW; @@ -212,26 +210,7 @@ module csrm #(parameter MTVAL: CSRMReadValM = MTVAL_REGW; MCOUNTEREN:CSRMReadValM = {{(`XLEN-32){1'b0}}, MCOUNTEREN_REGW}; MCOUNTINHIBIT:CSRMReadValM = {{(`XLEN-32){1'b0}}, MCOUNTINHIBIT_REGW}; -/* PMPCFG0: CSRMReadValM = PMPCFG01_REGW[`XLEN-1:0]; - PMPCFG1: CSRMReadValM = {{(`XLEN-32){1'b0}}, PMPCFG01_REGW[63:32]}; - PMPCFG2: CSRMReadValM = PMPCFG23_REGW[`XLEN-1:0]; - PMPCFG3: CSRMReadValM = {{(`XLEN-32){1'b0}}, PMPCFG23_REGW[63:32]}; - PMPADDR0: CSRMReadValM = PMPADDR_ARRAY_REGW[0]; // *** make configurable - PMPADDR1: CSRMReadValM = PMPADDR_ARRAY_REGW[1]; - PMPADDR2: CSRMReadValM = PMPADDR_ARRAY_REGW[2]; - PMPADDR3: CSRMReadValM = PMPADDR_ARRAY_REGW[3]; - PMPADDR4: CSRMReadValM = PMPADDR_ARRAY_REGW[4]; - PMPADDR5: CSRMReadValM = PMPADDR_ARRAY_REGW[5]; - PMPADDR6: CSRMReadValM = PMPADDR_ARRAY_REGW[6]; - PMPADDR7: CSRMReadValM = PMPADDR_ARRAY_REGW[7]; - PMPADDR8: CSRMReadValM = PMPADDR_ARRAY_REGW[8]; - PMPADDR9: CSRMReadValM = PMPADDR_ARRAY_REGW[9]; - PMPADDR10: CSRMReadValM = PMPADDR_ARRAY_REGW[10]; - PMPADDR11: CSRMReadValM = PMPADDR_ARRAY_REGW[11]; - PMPADDR12: CSRMReadValM = PMPADDR_ARRAY_REGW[12]; - PMPADDR13: CSRMReadValM = PMPADDR_ARRAY_REGW[13]; - PMPADDR14: CSRMReadValM = PMPADDR_ARRAY_REGW[14]; - PMPADDR15: CSRMReadValM = PMPADDR_ARRAY_REGW[15]; */ + default: begin CSRMReadValM = 0; IllegalCSRMAccessM = 1; diff --git a/wally-pipelined/src/privileged/privdec.sv b/wally-pipelined/src/privileged/privdec.sv index 1330a62b..621ef9a2 100644 --- a/wally-pipelined/src/privileged/privdec.sv +++ b/wally-pipelined/src/privileged/privdec.sv @@ -38,9 +38,9 @@ module privdec ( // xRET defined in Privileged Spect 3.2.2 assign uretM = PrivilegedM & (InstrM[31:20] == 12'b000000000010) & `N_SUPPORTED; - assign sretM = PrivilegedM & (InstrM[31:20] == 12'b000100000010) & `S_SUPPORTED && + assign sretM = PrivilegedM & (InstrM[31:20] == 12'b000100000010) & `S_SUPPORTED & PrivilegeModeW[0] & ~STATUS_TSR; - assign mretM = PrivilegedM & (InstrM[31:20] == 12'b001100000010) && (PrivilegeModeW == `M_MODE); + assign mretM = PrivilegedM & (InstrM[31:20] == 12'b001100000010) & (PrivilegeModeW == `M_MODE); assign ecallM = PrivilegedM & (InstrM[31:20] == 12'b000000000000); assign ebreakM = PrivilegedM & (InstrM[31:20] == 12'b000000000001); diff --git a/wally-pipelined/src/privileged/privileged.sv b/wally-pipelined/src/privileged/privileged.sv index 5ed8c880..90830137 100644 --- a/wally-pipelined/src/privileged/privileged.sv +++ b/wally-pipelined/src/privileged/privileged.sv @@ -64,11 +64,12 @@ module privileged ( input logic PMALoadAccessFaultM, PMPLoadAccessFaultM, input logic PMAStoreAccessFaultM, PMPStoreAccessFaultM, - output logic IllegalFPUInstrE, + output logic IllegalFPUInstrE, output logic [1:0] PrivilegeModeW, output logic [`XLEN-1:0] SATP_REGW, - output logic STATUS_MXR, STATUS_SUM, - output var logic [63:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES/8-1:0], + output logic STATUS_MXR, STATUS_SUM, STATUS_MPRV, + output logic [1:0] STATUS_MPP, + output var logic [7:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES-1:0], output var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW [`PMP_ENTRIES-1:0], output logic [2:0] FRM_REGW ); @@ -94,8 +95,7 @@ module privileged ( logic MTrapM, STrapM, UTrapM; logic InterruptM; - 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_SPP, STATUS_TSR; logic STATUS_MIE, STATUS_SIE; logic [11:0] MIP_REGW, MIE_REGW, SIP_REGW, SIE_REGW; logic md, sd; diff --git a/wally-pipelined/src/uncore/clint.sv b/wally-pipelined/src/uncore/clint.sv index d2014468..80cb28a1 100644 --- a/wally-pipelined/src/uncore/clint.sv +++ b/wally-pipelined/src/uncore/clint.sv @@ -94,7 +94,7 @@ module clint ( if (~HRESETn) begin MTIME <= 0; // MTIMECMP is not reset - end else if (memwrite && entryd == 16'hBFF8) begin + end else if (memwrite & entryd == 16'hBFF8) begin // MTIME Counter. Eventually change this to run off separate clock. Synchronization then needed MTIME <= HWDATA; end else MTIME <= MTIME + 1; @@ -125,9 +125,9 @@ module clint ( if (~HRESETn) begin MTIME <= 0; // MTIMECMP is not reset - end else if (memwrite && (entryd == 16'hBFF8)) begin + end else if (memwrite & (entryd == 16'hBFF8)) begin MTIME[31:0] <= HWDATA; - end else if (memwrite && (entryd == 16'hBFFC)) begin + end else if (memwrite & (entryd == 16'hBFFC)) begin // MTIME Counter. Eventually change this to run off separate clock. Synchronization then needed MTIME[63:32]<= HWDATA; end else MTIME <= MTIME + 1; diff --git a/wally-pipelined/src/uncore/dtim.sv b/wally-pipelined/src/uncore/dtim.sv index 40864567..c195c551 100644 --- a/wally-pipelined/src/uncore/dtim.sv +++ b/wally-pipelined/src/uncore/dtim.sv @@ -102,13 +102,13 @@ module dtim #(parameter BASE=0, RANGE = 65535) ( always_ff @(posedge HCLK) begin HWADDR <= #1 A; HREADTim0 <= #1 RAM[A[31:3]]; - if (memwrite && risingHREADYTim) RAM[HWADDR[31:3]] <= #1 HWDATA; + if (memwrite & risingHREADYTim) RAM[HWADDR[31:3]] <= #1 HWDATA; end end else begin always_ff @(posedge HCLK) begin HWADDR <= #1 A; HREADTim0 <= #1 RAM[A[31:2]]; - if (memwrite && risingHREADYTim) RAM[HWADDR[31:2]] <= #1 HWDATA; + if (memwrite & risingHREADYTim) RAM[HWADDR[31:2]] <= #1 HWDATA; end end endgenerate diff --git a/wally-pipelined/src/uncore/gpio.sv b/wally-pipelined/src/uncore/gpio.sv index bddec8e6..cde55b7a 100644 --- a/wally-pipelined/src/uncore/gpio.sv +++ b/wally-pipelined/src/uncore/gpio.sv @@ -131,19 +131,19 @@ module gpio ( default: Dout <= #1 0; endcase // interrupts - if (memwrite && (entryd == 8'h1C)) + if (memwrite & (entryd == 8'h1C)) rise_ip <= rise_ip & ~Din | (input2d & ~input3d); else rise_ip <= rise_ip | (input2d & ~input3d); - if (memwrite && (entryd == 8'h24)) + if (memwrite & (entryd == 8'h24)) fall_ip <= fall_ip & ~Din | (~input2d & input3d); else fall_ip <= fall_ip | (~input2d & input3d); - if (memwrite && (entryd == 8'h2C)) + if (memwrite & (entryd == 8'h2C)) high_ip <= high_ip & ~Din | input3d; else high_ip <= high_ip | input3d; - if (memwrite && (entryd == 8'h34)) + if (memwrite & (entryd == 8'h34)) low_ip <= low_ip & ~Din | ~input3d; else low_ip <= low_ip | ~input3d; @@ -157,7 +157,6 @@ module gpio ( else assign input0d = GPIOPinsIn & input_en; endgenerate - // *** this costs lots of flops; I suspect they don't need to be resettable, do they? flop #(32) sync1(HCLK,input0d,input1d); flop #(32) sync2(HCLK,input1d,input2d); flop #(32) sync3(HCLK,input2d,input3d); diff --git a/wally-pipelined/src/uncore/imem.sv b/wally-pipelined/src/uncore/imem.sv deleted file mode 100644 index 85362edf..00000000 --- a/wally-pipelined/src/uncore/imem.sv +++ /dev/null @@ -1,71 +0,0 @@ -/////////////////////////////////////////// -// imem.sv -// -// Written: David_Harris@hmc.edu 9 January 2021 -// Modified: -// -// Purpose: -// -// 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 imem ( - input logic [`XLEN-1:1] AdrF, - output logic [31:0] InstrF, - output logic [15:0] rd2, // bogus, delete when real multicycle fetch works - output logic InstrAccessFaultF); - - /* verilator lint_off UNDRIVEN */ - 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; -// logic [15:0] rd2; - - generate - if (`XLEN==32) assign adrbits = AdrF[31:2]; - else assign adrbits = AdrF[31:3]; - endgenerate - - 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 < (`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 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} ~^ `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} ~^ `TIM_BASE | `TIM_RANGE)) & (|AdrF[`XLEN-1:32] | ~&({AdrF[31:1],1'b0} ~^ `BOOTTIM_BASE | `BOOTTIM_RANGE)); - end - endgenerate -endmodule - diff --git a/wally-pipelined/src/uncore/uartPC16550D.sv b/wally-pipelined/src/uncore/uartPC16550D.sv index 4ead3f67..62c8ea00 100644 --- a/wally-pipelined/src/uncore/uartPC16550D.sv +++ b/wally-pipelined/src/uncore/uartPC16550D.sv @@ -224,11 +224,11 @@ module uartPC16550D( else rxstate <= #1 UART_IDLE; end // timeout counting - if (~MEMRb && A == 3'b000 && ~DLAB) rxtimeoutcnt <= #1 0; // reset timeout on read + if (~MEMRb & A == 3'b000 & ~DLAB) rxtimeoutcnt <= #1 0; // reset timeout on read else if (fifoenabled & ~rxfifoempty & rxbaudpulse & ~rxfifotimeout) rxtimeoutcnt <= #1 rxtimeoutcnt+1; // *** not right end - assign rxcentered = rxbaudpulse && (rxoversampledcnt == 4'b1000); // implies rxstate = UART_ACTIVE + assign rxcentered = rxbaudpulse & (rxoversampledcnt == 4'b1000); // implies rxstate = UART_ACTIVE assign rxbitsexpected = 4'd1 + (4'd5 + {2'b00, LCR[1:0]}) + {3'b000, LCR[3]} + 4'd1; // start bit + data bits + (parity bit) + stop bit /////////////////////////////////////////// @@ -267,12 +267,12 @@ module uartPC16550D( rxfifohead <= #1 rxfifohead + 1; end rxdataready <= #1 1; - end else if (~MEMRb && A == 3'b000 && ~DLAB) begin // reading RBR updates ready / pops fifo + end else if (~MEMRb & A == 3'b000 & ~DLAB) begin // reading RBR updates ready / pops fifo if (fifoenabled) begin rxfifotail <= #1 rxfifotail + 1; if (rxfifohead == rxfifotail +1) rxdataready <= #1 0; end else rxdataready <= #1 0; - end else if (~MEMWb && A == 3'b010) // writes to FIFO Control Register + end else if (~MEMWb & A == 3'b010) // writes to FIFO Control Register if (Din[1] | ~Din[0]) begin // rx FIFO reset or FIFO disable clears FIFO contents rxfifohead <= #1 0; rxfifotail <= #1 0; end @@ -326,7 +326,7 @@ module uartPC16550D( txoversampledcnt <= #1 0; txstate <= #1 UART_IDLE; txbitssent <= #1 0; - end else if ((txstate == UART_IDLE) && txsrfull) begin // start transmitting + end else if ((txstate == UART_IDLE) & txsrfull) begin // start transmitting txstate <= #1 UART_ACTIVE; txoversampledcnt <= #1 1; txbitssent <= #1 0; @@ -341,7 +341,7 @@ module uartPC16550D( end assign txbitsexpected = 4'd1 + (4'd5 + {2'b00, LCR[1:0]}) + {3'b000, LCR[3]} + 4'd1 + {3'b000, LCR[2]} - 4'd1; // start bit + data bits + (parity bit) + stop bit(s) - assign txnextbit = txbaudpulse && (txoversampledcnt == 4'b0000); // implies txstate = UART_ACTIVE + assign txnextbit = txbaudpulse & (txoversampledcnt == 4'b0000); // implies txstate = UART_ACTIVE /////////////////////////////////////////// // transmit holding register, shift register, FIFO @@ -372,7 +372,7 @@ module uartPC16550D( if (~HRESETn) begin txfifohead <= #1 0; txfifotail <= #1 0; txhrfull <= #1 0; txsrfull <= #1 0; TXHR <= #1 0; txsr <= #1 12'hfff; end else begin - if (~MEMWb && A == 3'b000 && ~DLAB) begin // writing transmit holding register or fifo + if (~MEMWb & A == 3'b000 & ~DLAB) begin // writing transmit holding register or fifo if (fifoenabled) begin txfifo[txfifohead] <= #1 Din; txfifohead <= #1 txfifohead + 1; @@ -395,8 +395,8 @@ module uartPC16550D( txsrfull <= #1 1; end end else if (txstate == UART_DONE) txsrfull <= #1 0; // done transmitting shift register - else if (txstate == UART_ACTIVE && txnextbit) txsr <= #1 {txsr[10:0], 1'b1}; // shift txhr - if (!MEMWb && A == 3'b010) // writes to FIFO control register + else if (txstate == UART_ACTIVE & txnextbit) txsr <= #1 {txsr[10:0], 1'b1}; // shift txhr + if (!MEMWb & A == 3'b010) // writes to FIFO control register if (Din[2] | ~Din[0]) begin // tx FIFO reste or FIFO disable clears FIFO contents txfifohead <= #1 0; txfifotail <= #1 0; end diff --git a/wally-pipelined/src/uncore/uncore.sv b/wally-pipelined/src/uncore/uncore.sv index 91aee66b..e5f5fdd7 100644 --- a/wally-pipelined/src/uncore/uncore.sv +++ b/wally-pipelined/src/uncore/uncore.sv @@ -62,22 +62,24 @@ module uncore ( logic [`XLEN-1:0] HWDATA; logic [`XLEN-1:0] HREADTim, HREADCLINT, HREADPLIC, HREADGPIO, HREADUART; - logic [5:0] HSELRegions; + logic [6:0] HSELRegions; logic HSELTim, HSELCLINT, HSELPLIC, HSELGPIO, PreHSELUART, HSELUART; logic HSELTimD, HSELCLINTD, HSELPLICD, HSELGPIOD, HSELUARTD; logic HRESPTim, HRESPCLINT, HRESPPLIC, HRESPGPIO, HRESPUART; logic HREADYTim, HREADYCLINT, HREADYPLIC, HREADYGPIO, HREADYUART; logic [`XLEN-1:0] HREADBootTim; logic HSELBootTim, HSELBootTimD, HRESPBootTim, HREADYBootTim; + logic HSELNoneD; logic [1:0] MemRWboottim; logic UARTIntr,GPIOIntr; // Determine which region of physical memory (if any) is being accessed // Use a trimmed down portion of the PMA checker - only the address decoders + // Set access types to all 1 as don't cares because the MMU has already done access checking adrdecs adrdecs({{(`PA_BITS-32){1'b0}}, HADDR}, 1'b1, 1'b1, 1'b1, HSIZE[1:0], HSELRegions); // unswizzle HSEL signals - assign {HSELBootTim, HSELTim, HSELCLINT, HSELGPIO, HSELUART, HSELPLIC} = HSELRegions; + assign {HSELBootTim, HSELTim, HSELCLINT, HSELGPIO, HSELUART, HSELPLIC} = HSELRegions[5:0]; // subword accesses: converts HWDATAIN to HWDATA subwordwrite sww(.*); @@ -133,19 +135,10 @@ module uncore ( HSELPLICD & HREADYPLIC | HSELGPIOD & HREADYGPIO | HSELBootTimD & HREADYBootTim | - HSELUARTD & HREADYUART; - - /* PMA checker now handles access faults. *** This can be deleted - // Faults - assign DataAccessFaultM = ~(HSELTimD | HSELCLINTD | HSELPLICD | HSELGPIOD | HSELBootTimD | HSELUARTD); - */ + HSELUARTD & HREADYUART | + HSELNoneD; // don't lock up the bus if no region is being accessed // Address Decoder Delay (figure 4-2 in spec) - flopr #(1) hseltimreg(HCLK, ~HRESETn, HSELTim, HSELTimD); - flopr #(1) hselclintreg(HCLK, ~HRESETn, HSELCLINT, HSELCLINTD); - flopr #(1) hselplicreg(HCLK, ~HRESETn, HSELPLIC, HSELPLICD); - flopr #(1) hselgpioreg(HCLK, ~HRESETn, HSELGPIO, HSELGPIOD); - flopr #(1) hseluartreg(HCLK, ~HRESETn, HSELUART, HSELUARTD); - flopr #(1) hselboottimreg(HCLK, ~HRESETn, HSELBootTim, HSELBootTimD); + flopr #(7) hseldelayreg(HCLK, ~HRESETn, HSELRegions, {HSELNoneD, HSELBootTimD, HSELTimD, HSELCLINTD, HSELGPIOD, HSELUARTD, HSELPLICD}); endmodule diff --git a/wally-pipelined/src/wally/wallypipelinedhart.sv b/wally-pipelined/src/wally/wallypipelinedhart.sv index 89486d8b..1c44565f 100644 --- a/wally-pipelined/src/wally/wallypipelinedhart.sv +++ b/wally-pipelined/src/wally/wallypipelinedhart.sv @@ -112,7 +112,8 @@ module wallypipelinedhart logic ITLBMissF, ITLBHitF; logic DTLBMissM, DTLBHitM; logic [`XLEN-1:0] SATP_REGW; - logic STATUS_MXR, STATUS_SUM; + logic STATUS_MXR, STATUS_SUM, STATUS_MPRV; + logic [1:0] STATUS_MPP; logic [1:0] PrivilegeModeW; logic [`XLEN-1:0] PageTableEntryF, PageTableEntryM; logic [1:0] PageTypeF, PageTypeM; @@ -122,8 +123,8 @@ module wallypipelinedhart logic PMPInstrAccessFaultF, PMPLoadAccessFaultM, PMPStoreAccessFaultM; logic PMAInstrAccessFaultF, PMALoadAccessFaultM, PMAStoreAccessFaultM; logic DSquashBusAccessM, ISquashBusAccessF; - var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW [`PMP_ENTRIES-1:0]; - var logic [63:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES/8-1:0]; + var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW [`PMP_ENTRIES-1:0]; + var logic [7:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES-1:0]; // IMem stalls logic ICacheStallF; @@ -223,6 +224,8 @@ module wallypipelinedhart .SATP_REGW(SATP_REGW), // from csr .STATUS_MXR(STATUS_MXR), // from csr .STATUS_SUM(STATUS_SUM), // from csr + .STATUS_MPRV(STATUS_MPRV), // from csr + .STATUS_MPP(STATUS_MPP), // from csr .DTLBFlushM(DTLBFlushM), // connects to privilege .NonBusTrapM(NonBusTrapM), // connects to privilege diff --git a/wally-pipelined/testbench/testbench-imperas.sv b/wally-pipelined/testbench/testbench-imperas.sv index 11b8e562..8c3e28c3 100644 --- a/wally-pipelined/testbench/testbench-imperas.sv +++ b/wally-pipelined/testbench/testbench-imperas.sv @@ -520,6 +520,7 @@ string tests32f[] = '{ // check assertions for a legal configuration riscvassertions riscvassertions(); + logging logging(clk, reset, dut.uncore.HADDR, dut.uncore.HTRANS); // pick tests based on modes supported initial begin @@ -722,6 +723,7 @@ module riscvassertions(); // Legal number of PMP entries are 0, 16, or 64 initial begin assert (`PMP_ENTRIES == 0 || `PMP_ENTRIES==16 || `PMP_ENTRIES==64) else $error("Illegal number of PMP entries"); + assert (`F_SUPPORTED || ~`D_SUPPORTED) else $error("Can't support double without supporting float"); end endmodule @@ -949,3 +951,13 @@ module instrNameDecTB( default: name = "ILLEGAL"; endcase endmodule + +module logging( + input logic clk, reset, + input logic [31:0] HADDR, + input logic [1:0] HTRANS); + + always @(posedge clk) + if (HTRANS != 2'b00 && HADDR == 0) + $display("Warning: access to memory address 0\n"); +endmodule diff --git a/wally-pipelined/testbench/testbench-linux.sv b/wally-pipelined/testbench/testbench-linux.sv index 6676d1a7..18ef74ff 100644 --- a/wally-pipelined/testbench/testbench-linux.sv +++ b/wally-pipelined/testbench/testbench-linux.sv @@ -27,8 +27,8 @@ module testbench(); - parameter waveOnICount = 2657000; // # of instructions at which to turn on waves in graphical sim - + parameter waveOnICount = `BUSYBEAR*140000 + `BUILDROOT*2400000; // # of instructions at which to turn on waves in graphical sim + parameter stopICount = `BUSYBEAR*143898 + `BUILDROOT*0000000; // # instructions at which to halt sim completely (set to 0 to let it run as far as it can) /////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////// DUT ///////////////////////////////////// @@ -248,6 +248,9 @@ module testbench(); if (instrs == waveOnICount) begin $display("turning on waves at %0d instructions", instrs); $stop; + end else if (instrs == stopICount && stopICount != 0) begin + $display("Ending sim at %0d instructions (set stopICount to 0 to let the sim go on)", instrs); + $stop; end // Check if PCD is going to be flushed due to a branch or jump @@ -331,6 +334,8 @@ module testbench(); `SCAN_PC(data_file_PCM, scan_file_PCM, trashString, trashString, InstrMExpected, PCMexpected); end + logging logging(clk, reset, dut.uncore.HADDR, dut.uncore.HTRANS); + // ------------------- // Additional Hardware // ------------------- @@ -715,6 +720,16 @@ module testbench(); endfunction endmodule +module logging( + input logic clk, reset, + input logic [31:0] HADDR, + input logic [1:0] HTRANS); + + always @(posedge clk) + if (HTRANS != 2'b00 && HADDR == 0) + $display("Warning: access to memory address 0\n"); +endmodule + module instrTrackerTB( input logic clk, reset,