From 79e798a6417f4730ef5030680007ecf2b79270ac Mon Sep 17 00:00:00 2001 From: bbracker Date: Thu, 10 Jun 2021 09:53:48 -0400 Subject: [PATCH 1/4] UART improved and added more reg read side effects --- wally-pipelined/src/uncore/uartPC16550D.sv | 56 +++++++++++++--------- 1 file changed, 33 insertions(+), 23 deletions(-) diff --git a/wally-pipelined/src/uncore/uartPC16550D.sv b/wally-pipelined/src/uncore/uartPC16550D.sv index 0f539512..9261848c 100644 --- a/wally-pipelined/src/uncore/uartPC16550D.sv +++ b/wally-pipelined/src/uncore/uartPC16550D.sv @@ -94,7 +94,7 @@ module uartPC16550D( logic rxfifodmaready; logic [8:0] rxdata9; logic [7:0] rxdata; - logic [15:0] rxerrbit, rxfullbit; + logic [15:0] RXerrbit, rxfullbit; // transmit data logic [11:0] TXHR, txdata, nexttxdata, txsr; @@ -106,7 +106,9 @@ module uartPC16550D( logic fifoenabled, fifodmamodesel, evenparitysel; // interrupts - logic rxlinestatusintr, rxdataavailintr, modemstatusintr, intrpending, THRE, suppressTHREbecauseIIR, suppressTHREbecauseIIRtrig; + logic RXerr, RXerrIP, squashRXerrIP, prevSquashRXerrIP, setSquashRXerrIP, resetSquashRXerrIP; + logic THRE, THRE_IP, squashTHRE_IP, prevSquashTHRE_IP, setSquashTHRE_IP, resetSquashTHRE_IP; + logic rxdataavailintr, modemstatusintr, intrpending; logic [2:0] intrID; /////////////////////////////////////////// @@ -146,13 +148,15 @@ module uartPC16550D( 3'b111: SCR <= #1 Din; endcase end + // Line Status Register (8.6.3) + // Ben 6/9/21 I don't like how this is a register. A lot of the individual bits have clocked components, so this just adds unecessary delay. LSR[0] <= #1 rxdataready; // Data ready - if (RXBR[10]) LSR[1] <= #1 1; // overrun error - if (RXBR[9]) LSR[2] <= #1 1; // parity error - if (RXBR[8]) LSR[3] <= #1 1; // framing error - if (rxbreak) LSR[4] <= #1 1; // break indicator - LSR[5] <= #1 THRE & ~(suppressTHREbecauseIIR | suppressTHREbecauseIIRtrig); // THRE (suppress trigger included to avoid 2-cycle delay) + LSR[1] <= #1 (LSR[1] | RXBR[10]) & ~squashRXerrIP;; // overrun error + LSR[2] <= #1 (LSR[2] | RXBR[9]) & ~squashRXerrIP; // parity error + LSR[3] <= #1 (LSR[3] | RXBR[8]) & ~squashRXerrIP; // framing error + LSR[4] <= #1 (LSR[4] | rxbreak) & ~squashRXerrIP; // break indicator + LSR[5] <= #1 THRE; // THRE LSR[6] <= #1 ~txsrfull & THRE; // TEMT if (rxfifohaserr) LSR[7] <= #1 1; // any bits in FIFO have error @@ -162,7 +166,6 @@ module uartPC16550D( MSR[2] <= #1 MSR[2] | (~RIb2 & RIbsync); // Trailing Edge of Ring Indicator MSR[3] <= #1 MSR[3] | DCDb2 ^ DCDbsync; // Delta Data Carrier Detect end - always_comb if (~MEMRb) case (A) @@ -199,7 +202,6 @@ module uartPC16550D( /////////////////////////////////////////// // receive timing and control /////////////////////////////////////////// - always_ff @(posedge HCLK, negedge HRESETn) if (~HRESETn) begin rxoversampledcnt <= #1 0; @@ -260,7 +262,7 @@ module uartPC16550D( if (rxstate == UART_DONE) begin RXBR <= #1 {rxoverrunerr, rxparityerr, rxframingerr, rxdata}; // load recevive buffer register if (fifoenabled) begin - rxfifo[rxfifohead] <= #1 {rxoverrunerr, rxparityerr, rxframingerr, rxdata}; + rxfifo[rxfifohead] <= #1 {rxoverrunerr, rxparityerr, rxframingerr, rxdata}; rxfifohead <= #1 rxfifohead + 1; end rxdataready <= #1 1; @@ -287,14 +289,14 @@ module uartPC16550D( generate genvar i; for (i=0; i<16; i++) begin - assign rxerrbit[i] = |rxfifo[i][10:8]; // are any of the error conditions set? + assign RXerrbit[i] = |rxfifo[i][10:8]; // are any of the error conditions set? if (i > 0) assign rxfullbit[i] = ((rxfifohead==i) | rxfullbit[i-1]) & (rxfifotail != i); else assign rxfullbit[0] = ((rxfifohead==i) | rxfullbit[15]) & (rxfifotail != i); end endgenerate - assign rxfifohaserr = |(rxerrbit & rxfullbit); + assign rxfifohaserr = |(RXerrbit & rxfullbit); // receive buffer register and ready bit always_ff @(posedge HCLK, negedge HRESETn) // track rxrdy for DMA mode (FCR3 = FCR0 = 1) @@ -341,7 +343,6 @@ module uartPC16550D( /////////////////////////////////////////// // transmit holding register, shift register, FIFO /////////////////////////////////////////// - always_comb begin // compute value for parity and tx holding register nexttxdata = fifoenabled ? txfifo[txfifotail] : TXHR; // pick from FIFO or holding register case (LCR[1:0]) // compute parity from appropriate number of bits @@ -420,20 +421,22 @@ module uartPC16550D( /////////////////////////////////////////// // interrupts /////////////////////////////////////////// - assign rxlinestatusintr = |LSR[4:1]; // LS interrupt if any of the flags are true + assign RXerr = |LSR[4:1]; // LS interrupt if any of the flags are true + assign RXerrIP = RXerr & ~squashRXerrIP; // intr squashed upon reading LSR assign rxdataavailintr = fifoenabled ? rxfifotriggered : rxdataready; - assign THRE = fifoenabled ? txfifoempty : ~txhrfull; + assign THRE = fifoenabled ? txfifoempty : ~txhrfull; + assign THRE_IP = THRE & ~squashTHRE_IP; // THRE_IP squashed upon reading IIR assign modemstatusintr = |MSR[3:0]; // set interrupt when modem pins change // IIR: interrupt priority (Table 5) // set intrID based on highest priority pending interrupt source; otherwise, no interrupt is pending always_comb begin intrpending = 1; - if (rxlinestatusintr & IER[2]) intrID = 3'b011; - else if (rxdataavailintr & IER[0]) intrID = 3'b010; - else if (rxfifotimeout & fifoenabled & IER[0]) intrID = 3'b110; - else if (THRE & IER[1] & ~suppressTHREbecauseIIR) intrID = 3'b001; - else if (modemstatusintr & IER[3]) intrID = 3'b000; + if (RXerrIP & IER[2]) intrID = 3'b011; + else if (rxdataavailintr & IER[0]) intrID = 3'b010; + else if (rxfifotimeout & fifoenabled & IER[0]) intrID = 3'b110; + else if (THRE_IP & IER[1]) intrID = 3'b001; + else if (modemstatusintr & IER[3]) intrID = 3'b000; else begin intrID = 3'b000; intrpending = 0; @@ -441,9 +444,16 @@ module uartPC16550D( end always @(posedge HCLK) INTR <= #1 intrpending; // prevent glitches on interrupt pin - // Side effect of reading IIR is lowering THRE if most significant intr - assign suppressTHREbecauseIIRtrig = ~MEMRb & (A==3'b010) & (intrID==2'h1); - flopr #(1) suppressTHREreg(HCLK, (~HRESETn | (fifoenabled ? ~txfifoempty : txhrfull)), (suppressTHREbecauseIIRtrig | suppressTHREbecauseIIR), suppressTHREbecauseIIR); + // Side effect of reading LSR is lowering overrun, parity, framing, break intr's + assign setSquashRXerrIP = ~MEMRb & (A==3'b101); + assign resetSquashRXerrIP = (rxstate == UART_DONE); + assign squashRXerrIP = (prevSquashRXerrIP | setSquashRXerrIP) & ~resetSquashRXerrIP; + flopr #(1) squashRXerrIPreg(HCLK, ~HRESETn, squashRXerrIP, prevSquashRXerrIP); + // Side effect of reading IIR is lowering THRE_IP if most significant intr + assign setSquashTHRE_IP = ~MEMRb & (A==3'b010) & (intrID==2'h1); // there's a 1-cycle delay on set squash so that THRE_IP doesn't change during the process of reading IIR (otherwise combinational loop) + assign resetSquashTHRE_IP = ~THRE; + assign squashTHRE_IP = prevSquashTHRE_IP & ~resetSquashTHRE_IP; + flopr #(1) squashTHRE_IPreg(HCLK, ~HRESETn, squashTHRE_IP | setSquashTHRE_IP, prevSquashTHRE_IP); /////////////////////////////////////////// // modem control logic From d9022551c20df4063c397f5a4526e1001e495901 Mon Sep 17 00:00:00 2001 From: bbracker Date: Thu, 10 Jun 2021 09:58:20 -0400 Subject: [PATCH 2/4] buildroot progress -- able to mimic GDB output --- wally-pipelined/linux-testgen/combineGDBs.py | 68 ++++++++ wally-pipelined/linux-testgen/find_csr.sh | 2 + wally-pipelined/linux-testgen/fix_mem.py | 9 + wally-pipelined/linux-testgen/gdbinit | 15 ++ wally-pipelined/linux-testgen/gdbinit_mem | 23 +++ wally-pipelined/linux-testgen/gdbinit_qemulog | 10 ++ .../linux-testgen/gdbinit_qemulog_debug | 9 + .../linux-testgen/logAllBuildroot.sh | 26 +++ .../linux-testgen/logBuildrootMem.sh | 4 + .../linux-testgen/parseAllBusybear.sh | 1 + .../linux-testgen/parse_gdb_output.py | 164 ++++++++++++++++++ wally-pipelined/linux-testgen/parse_qemu.py | 107 ++++++++++++ wally-pipelined/linux-testgen/setup_OVP.sh | 7 + wally-pipelined/linux-testgen/start_OVP.sh | 2 + 14 files changed, 447 insertions(+) create mode 100755 wally-pipelined/linux-testgen/combineGDBs.py create mode 100755 wally-pipelined/linux-testgen/find_csr.sh create mode 100755 wally-pipelined/linux-testgen/fix_mem.py create mode 100755 wally-pipelined/linux-testgen/gdbinit create mode 100755 wally-pipelined/linux-testgen/gdbinit_mem create mode 100755 wally-pipelined/linux-testgen/gdbinit_qemulog create mode 100755 wally-pipelined/linux-testgen/gdbinit_qemulog_debug create mode 100755 wally-pipelined/linux-testgen/logAllBuildroot.sh create mode 100755 wally-pipelined/linux-testgen/logBuildrootMem.sh create mode 100755 wally-pipelined/linux-testgen/parseAllBusybear.sh create mode 100755 wally-pipelined/linux-testgen/parse_gdb_output.py create mode 100755 wally-pipelined/linux-testgen/parse_qemu.py create mode 100755 wally-pipelined/linux-testgen/setup_OVP.sh create mode 100755 wally-pipelined/linux-testgen/start_OVP.sh diff --git a/wally-pipelined/linux-testgen/combineGDBs.py b/wally-pipelined/linux-testgen/combineGDBs.py new file mode 100755 index 00000000..5fe0b197 --- /dev/null +++ b/wally-pipelined/linux-testgen/combineGDBs.py @@ -0,0 +1,68 @@ +#! /usr/bin/python3 + +instrs = 0 +def readBlock(f, start, end): + l = f.readline() + if not l: + quit() + while not (l.startswith(start) and 'in ' not in l): + l = f.readline() + if not l: + quit() + ret = l + while not l.startswith(end): + l = f.readline() + if not l: + quit() + ret += l + return ret.split('\n'), f.readline() + +with open('gdbcombined.txt', 'w') as out: + with open('/mnt/scratch/riscv_gp/riscv_gp.txt', 'r') as gp: + with open('/mnt/scratch/riscv_sp1/riscv_sp1.txt', 'r') as sp1: + with open('/mnt/scratch/riscv_sp2/riscv_sp2.txt', 'r') as sp2: + with open('/mnt/scratch/riscv_sp3/riscv_sp3.txt', 'r') as sp3: + with open('/mnt/scratch/riscv_decodepc_threads/riscv_decodepc.txt.disassembly', 'r') as inst: + inst.readline() + while(True): + instrs += 1 + g, i1 = readBlock(gp, 'ra', 't6') + p1, i2 = readBlock(sp1, 'mie', 'scounteren') + p2, i3 = readBlock(sp2, '0x', 'mideleg') + p3, i4 = readBlock(sp3, 'mcause', 'stvec') + instr = inst.readline() + if not instr: + quit() + while '...' in instr: + instr = inst.readline() + if not instr: + quit() + if i1 != i2 or i2 != i3 or i3 != i4 or int(p2[0].split()[0].split(':')[0], 16) != int(instr.split()[0].split(':')[0], 16): + print("error: PC was not the same") + print("instruction {}".format(instrs)) + print(i1) + print(i2) + print(i3) + print(i4) + print(p2[0]) + print(instr) + quit() + if "unimp" in instr: + instrs -= 1 + continue + out.write('=> {}'.format(instr.split(':')[2][1:].replace(' ', ':\t', 1))) + out.write(p2[0] + '\n') + out.write("zero 0x0 0\n") + out.write("\n".join(g)) + pc = p2[0].split()[0] + if pc.endswith(':'): + pc = pc[:-1] + out.write("pc {} {}\n".format(pc, pc)) + out.write("\n".join(p1)) + out.write("\n".join(p3)) + out.write("\n".join(p2[2:])) + out.write("-----\n") + if instrs % 10000 == 0: + print(instrs) + #if instrs >= 1000010: + # quit() diff --git a/wally-pipelined/linux-testgen/find_csr.sh b/wally-pipelined/linux-testgen/find_csr.sh new file mode 100755 index 00000000..89d0f098 --- /dev/null +++ b/wally-pipelined/linux-testgen/find_csr.sh @@ -0,0 +1,2 @@ +#grep '=>.*csr' $1 | rev | cut -d' ' -f1 | rev | tee >(cut -d',' -f1) | cut -d',' -f2 | grep -Ev 'a[0-7]|t[0-6]|zero|[0-8]' | sort | uniq | paste -s -d, - +grep 'csr' /mnt/scratch/riscv_decodepc_threads/riscv_decodepc.txt.disassembly | rev | cut -d' ' -f1 | rev | tee >(cut -d',' -f1 | sort -u) >(cut -d',' -f2 | sort -u) | (cut -d',' -f3 | sort -u) | sort -u | paste -s -d, - diff --git a/wally-pipelined/linux-testgen/fix_mem.py b/wally-pipelined/linux-testgen/fix_mem.py new file mode 100755 index 00000000..ca5fda08 --- /dev/null +++ b/wally-pipelined/linux-testgen/fix_mem.py @@ -0,0 +1,9 @@ +#! /usr/bin/python3 +test_dir = '/courses/e190ax/buildroot_boot/' +infiles = ['bootmemGDB.txt', 'ramGDB.txt'] +outfiles = ['bootmem.txt', 'ram.txt'] +for i in range(len(infiles)): + with open(f'{test_dir}{infiles[i]}', 'r') as f: + with open(f'{test_dir}{outfiles[i]}', 'w') as w: + for l in f: + w.write(f'{"".join([x[2:] for x in l.split()[:0:-1]])}\n') diff --git a/wally-pipelined/linux-testgen/gdbinit b/wally-pipelined/linux-testgen/gdbinit new file mode 100755 index 00000000..f41e2398 --- /dev/null +++ b/wally-pipelined/linux-testgen/gdbinit @@ -0,0 +1,15 @@ +set pagination off +set logging overwrite on +set logging redirect on +set logging file /mnt/scratch/riscv_testbench/riscv_boot_regs.txt +set logging on +x/i $pc +x/x $pc +info all-registers +while ($pc != 0xffffffe000018fa4) + si + x/i $pc + x/x $pc + info all-registers +end +set logging off diff --git a/wally-pipelined/linux-testgen/gdbinit_mem b/wally-pipelined/linux-testgen/gdbinit_mem new file mode 100755 index 00000000..1a05f4af --- /dev/null +++ b/wally-pipelined/linux-testgen/gdbinit_mem @@ -0,0 +1,23 @@ +set pagination off +target extended-remote :1234 +set logging overwrite on +set logging redirect on +printf "Creating bootmemGDB.txt\n" +set logging file /courses/e190ax/buildroot_boot/bootmemGDB.txt +set logging on +x/4096xb 0x1000 +set logging off +printf "Creating bootmem_untrimmed_GDB.txt\n" +printf "Warning - please verify that the second half of bootmem_untrimmed_GDB.txt is all 0s\n" +set logging file /courses/e190ax/buildroot_boot/bootmem_untrimmed_GDB.txt +set logging on +x/8192xb 0x1000 +set logging off +printf "Creating ramGDB.txt\n" +set logging file /courses/e190ax/buildroot_boot/ramGDB.txt +set logging on +x/134217728xb 0x80000000 +set logging off +set confirm off +kill +q diff --git a/wally-pipelined/linux-testgen/gdbinit_qemulog b/wally-pipelined/linux-testgen/gdbinit_qemulog new file mode 100755 index 00000000..ad9d9351 --- /dev/null +++ b/wally-pipelined/linux-testgen/gdbinit_qemulog @@ -0,0 +1,10 @@ +set pagination off +target extended-remote :1234 +b *0xffffffe00020144e +c +c +c +c +set confirm off +kill +q diff --git a/wally-pipelined/linux-testgen/gdbinit_qemulog_debug b/wally-pipelined/linux-testgen/gdbinit_qemulog_debug new file mode 100755 index 00000000..f1202500 --- /dev/null +++ b/wally-pipelined/linux-testgen/gdbinit_qemulog_debug @@ -0,0 +1,9 @@ +set pagination off +target extended-remote :1234 +b *0x000000008020103c +c +del 1 +stepi 100 +set confirm off +kill +q diff --git a/wally-pipelined/linux-testgen/logAllBuildroot.sh b/wally-pipelined/linux-testgen/logAllBuildroot.sh new file mode 100755 index 00000000..dfb5205a --- /dev/null +++ b/wally-pipelined/linux-testgen/logAllBuildroot.sh @@ -0,0 +1,26 @@ +# =========== Debug the Process ========== +# Uncomment this version for GDB/QEMU debugging +# - Opens up GDB interactively +# - Logs raw QEMU output to qemu_output.txt +#(qemu-system-riscv64 -M virt -nographic -bios /courses/e190ax/qemu_sim/rv64_initrd/buildroot_experimental/output/images/fw_jump.elf -kernel /courses/e190ax/qemu_sim/rv64_initrd/buildroot_experimental/output/images/Image -append "root=/dev/vda ro" -initrd /courses/e190ax/qemu_sim/rv64_initrd/buildroot_experimental/output/images/rootfs.cpio -d nochain,cpu,in_asm -serial /dev/null -singlestep -s -S 2> /mnt/scratch/wally_linux_output/qemu_output.txt) & riscv64-unknown-elf-gdb + +# Uncomment this version to generate qemu_output.txt +# - Uses GDB script +# - Logs raw QEMU output to qemu_output.txt +#(qemu-system-riscv64 -M virt -nographic -bios /courses/e190ax/qemu_sim/rv64_initrd/buildroot_experimental/output/images/fw_jump.elf -kernel /courses/e190ax/qemu_sim/rv64_initrd/buildroot_experimental/output/images/Image -append "root=/dev/vda ro" -initrd /courses/e190ax/qemu_sim/rv64_initrd/buildroot_experimental/output/images/rootfs.cpio -d nochain,cpu,in_asm -serial /dev/null -singlestep -s -S 2>/mnt/scratch/wally_linux_output/qemu_output.txt) & riscv64-unknown-elf-gdb -x gdbinit_qemulog + +# Uncomment this version for parse_qemu.py debugging +# - Uses qemu_output.txt +# - Makes qemu_in_gdb_format.txt +# - Logs parse_qemu.py's simulated gdb output to qemu_in_gdb_format.txt +#cat /mnt/scratch/wally_linux_output/qemu_output.txt | ./parse_qemu.py >/mnt/scratch/wally_linux_output/qemu_in_gdb_format.txt + +# Uncomment this version for parse_gdb_output.py debugging +# - Uses qemu_in_gdb_format.txt +# - Logs info needed by buildroot testbench +cat /mnt/scratch/wally_linux_output/qemu_in_gdb_format.txt | ./parse_gdb_output.py "/courses/e190ax/buildroot_boot/" + +# =========== Just Do the Thing ========== +# Uncomment this version for the whole thing (if it works ha ha_ +# - Logs info needed by buildroot testbench +#(qemu-system-riscv64 -M virt -nographic -bios /courses/e190ax/qemu_sim/rv64_initrd/buildroot_experimental/output/images/fw_jump.elf -kernel /courses/e190ax/qemu_sim/rv64_initrd/buildroot_experimental/output/images/Image -append "root=/dev/vda ro" -initrd /courses/e190ax/qemu_sim/rv64_initrd/buildroot_experimental/output/images/rootfs.cpio -d nochain,cpu,in_asm -serial /dev/null -singlestep -s -S 2>&1 >/dev/null | pv -l | ./parse_qemu.py | ./parse_gdb_output.py "/courses/e190ax/buildroot_boot/") & riscv64-unknown-elf-gdb -x gdbinit_qemulog diff --git a/wally-pipelined/linux-testgen/logBuildrootMem.sh b/wally-pipelined/linux-testgen/logBuildrootMem.sh new file mode 100755 index 00000000..d41d85d0 --- /dev/null +++ b/wally-pipelined/linux-testgen/logBuildrootMem.sh @@ -0,0 +1,4 @@ +(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>/dev/null >/dev/null ) & +riscv64-unknown-elf-gdb -x gdbinit_mem +#sed -i '$d' $file +echo "Done" diff --git a/wally-pipelined/linux-testgen/parseAllBusybear.sh b/wally-pipelined/linux-testgen/parseAllBusybear.sh new file mode 100755 index 00000000..bee05019 --- /dev/null +++ b/wally-pipelined/linux-testgen/parseAllBusybear.sh @@ -0,0 +1 @@ +./combineGDBs.py && cat gdbcombined.txt | ./parse_gdb_output.py "/courses/e190ax/busybear_boot_new/" diff --git a/wally-pipelined/linux-testgen/parse_gdb_output.py b/wally-pipelined/linux-testgen/parse_gdb_output.py new file mode 100755 index 00000000..5ae62b32 --- /dev/null +++ b/wally-pipelined/linux-testgen/parse_gdb_output.py @@ -0,0 +1,164 @@ +#! /usr/bin/python3 +import sys, fileinput + +sys.stderr.write("reminder: this script takes input from stdin\n") + +csrs = ['fcsr','mcause','mcounteren','medeleg','mepc','mhartid','mideleg','mie','mip','misa','mscratch','mstatus','mtval','mtvec','pmpaddr0','pmpcfg0','satp','scause','scounteren','sepc','sie','sscratch','sstatus','stval','stvec'] + +# just for now, since these CSRs aren't yet ready to be checked in testbench-linux +list(map(csrs.remove, ['fcsr','mhartid','pmpcfg0','pmpaddr0','mip'])) +#output_path = '/courses/e190ax/busybear_boot_new/' +#output_path = '/courses/e190ax/buildroot_boot/' +output_path = sys.argv[1] +print(f'output dir: {output_path}') +instrs = -1 +try: + with open('{}parsedPC.txt'.format(output_path), 'w') as wPC: + with open('{}parsedRegs.txt'.format(output_path), 'w') as wReg: + with open('{}parsedMemRead.txt'.format(output_path), 'w') as wMem: + with open('{}parsedMemWrite.txt'.format(output_path), 'w') as wMemW: + with open('{}parsedCSRs.txt'.format(output_path), 'w') as wCSRs: + firstCSR = True + curCSRs = {} + lastRead = '' + currentRead = '' + readOffset = '' + lastReadLoc = '' + readType = '' + lastReadType = '' + readLoc = '' + instrStart = -1 + lastRegs = '' + curRegs = '' + storeReg = '' + storeOffset = '' + storeLoc = '' + storeAMO = '' + lastAMO = '' + lastStoreReg = '' + lastStoreLoc = '' + for l in fileinput.input('-'): + l = l.split("#")[0].rstrip() + if l.startswith('=>'): + instrs += 1 + storeAMO = '' + if instrs % 10000 == 0: + print(instrs) + wPC.write('{} ***\n'.format(' '.join(l.split(':')[1].split()[0:2]))) + if '\tld' in l or '\tlw' in l or '\tlh' in l or '\tlb' in l: + currentRead = l.split()[-1].split(',')[0] + if len(l.split()[-1].split(',')) < 2: + print(l) + readOffset = l.split()[-1].split(',')[1].split('(')[0] + readLoc = l.split()[-1].split(',')[1].split('(')[1][:-1] + readType = l.split()[-2] + if 'amo' in l: + #print(l) + currentRead = l.split()[-1].split(',')[0] + readOffset = "0" + readLoc = l.split()[-1].split('(')[1][:-1] + readType = l.split()[-2] + storeOffset = "0" + storeLoc = readLoc + storeReg = l.split()[-1].split(',')[1] + storeAMO = l.split()[-2] + if '\tsd' in l or '\tsw' in l or '\tsh' in l or '\tsb' in l: + #print(l) + s = l.split('#')[0].split()[-1] + storeReg = s.split(',')[0] + if len(s.split(',')) < 2: + print(s) + print(l) + if len(s.split(',')[1].split('(')) < 1: + print(s) + print(l) + storeOffset = s.split(',')[1].split('(')[0] + storeLoc = s.split(',')[1].split('(')[1][:-1] + instrStart = 0 + elif instrStart != -1: + instrStart += 1 + if instrStart == 1: + wPC.write('{}\n'.format(l.split()[-1][2:])) + elif instrStart < 34: + if lastRead == l.split()[0]: + readData = int(l.split()[1][2:], 16) + readData <<= (8 * (lastReadLoc % 8)) + #if(lastReadLoc % 8 != 0 and ('lw' in lastReadType or 'lb' in lastReadType)): + # readData <<= 32 + wMem.write('{:x}\n'.format(readData)) + if readLoc == l.split()[0]: + readLoc = l.split()[1][2:] + if storeReg == l.split()[0]: + storeReg = l.split()[1] + if storeLoc == l.split()[0]: + storeLoc = l.split()[1][2:] + if instrStart > 2: + #print(l) + #print(instrStart) + curRegs += '{}\n'.format(l.split()[1][2:]) + elif instrStart < 35: + #print("----------") + #print(l.split()[1][2:]) + wPC.write('{}\n'.format(l.split()[1][2:])) + #print(l.split()[1][2:]) + if any([c == l.split()[0] for c in csrs]): + if l.split()[0] in curCSRs: + if curCSRs[l.split()[0]] != l.split()[1]: + if firstCSR: + wCSRs.write('---\n') + firstCSR = False + wCSRs.write('{}\n{}\n'.format(l.split()[0], l.split()[1][2:])) + else: + wCSRs.write('{}\n{}\n'.format(l.split()[0], l.split()[1][2:])) + curCSRs[l.split()[0]] = l.split()[1] + if '-----' in l: # end of each cycle + if curRegs != lastRegs: + if lastRegs == '': + wReg.write(curRegs) + else: + for i in range(32): + if curRegs.split('\n')[i] != lastRegs.split('\n')[i]: + wReg.write('{}\n'.format(i+1)) + wReg.write('{}\n'.format(curRegs.split('\n')[i])) + break + lastRegs = curRegs + if lastAMO != '': + if 'amoadd' in lastAMO: + lastStoreReg = hex(int(lastStoreReg[2:], 16) + readData)[2:] + elif 'amoand' in lastAMO: + lastStoreReg = hex(int(lastStoreReg[2:], 16) & readData)[2:] + elif 'amoor' in lastAMO: + lastStoreReg = hex(int(lastStoreReg[2:], 16) | readData)[2:] + elif 'amoswap' in lastAMO: + lastStoreReg = hex(int(lastStoreReg[2:], 16))[2:] + else: + print(lastAMO) + exit() + wMemW.write('{}\n'.format(lastStoreReg)) + wMemW.write('{:x}\n'.format(int(lastStoreLoc, 16))) + if storeReg != '' and storeOffset != '' and storeLoc != '' and storeAMO == '': + storeLocOffset = int(storeOffset,10) + int(storeLoc, 16) + #wMemW.write('{:x}\n'.format(int(storeReg, 16) << (8 * (storeLocOffset % 8)))) + wMemW.write('{}\n'.format(storeReg[2:])) + wMemW.write('{:x}\n'.format(storeLocOffset)) + if readOffset != '' and readLoc != '': + wMem.write('{:x}\n'.format(int(readOffset,10) + int(readLoc, 16))) + lastReadLoc = int(readOffset,10) + int(readLoc, 16) + lastReadType = readType + readOffset = '' + readLoc = '' + curRegs = '' + instrStart = -1 + lastRead = currentRead + currentRead = '' + lastStoreReg = storeReg + lastStoreLoc = storeLoc + storeReg = '' + storeOffset = '' + storeLoc = '' + lastAMO = storeAMO + + +except (FileNotFoundError): + print('please give gdb output file as argument') + diff --git a/wally-pipelined/linux-testgen/parse_qemu.py b/wally-pipelined/linux-testgen/parse_qemu.py new file mode 100755 index 00000000..91d45800 --- /dev/null +++ b/wally-pipelined/linux-testgen/parse_qemu.py @@ -0,0 +1,107 @@ +#! /usr/bin/python3 +import fileinput, sys + +sys.stderr.write("reminder: this script takes input from stdin\n") +parseState = "idle" +inPageFault = 0 +CSRs = {} +pageFaultCSRs = {} +regs = {} +pageFaultRegs = {} +instrs = {} + +def printPC(l): + global parseState, inPageFault, CSRs, pageFaultCSRs, regs, pageFaultCSRs, instrs + if not inPageFault: + inst = l.split() + if len(inst) > 3: + print(f'=> {inst[1]}:\t{inst[2]} {inst[3]}') + else: + print(f'=> {inst[1]}:\t{inst[2]}') + print(f'{inst[0]} 0x{inst[1]}') + +def printCSRs(): + global parseState, inPageFault, CSRs, pageFaultCSRs, regs, pageFaultCSRs, instrs + if not inPageFault: + for (csr,val) in CSRs.items(): + print('{}{}{:#x} {}'.format(csr, ' '*(15-len(csr)), val, val)) + print('-----') + +def parseCSRs(l): + global parseState, inPageFault, CSRs, pageFaultCSRs, regs, pageFaultCSRs, instrs + if l.strip() and (not l.startswith("Disassembler")) and (not l.startswith("Please")): + if l.startswith(' x0/zero'): + parseState = "regFile" + instr = instrs[CSRs["pc"]] + printPC(instr) + parseRegs(l) + else: + csr = l.split()[0] + val = int(l.split()[1],16) + if inPageFault: + if l.startswith("mstatus") or l.startswith("mepc") or l.startswith("mcause") or l.startswith("mtval") or l.startswith("sepc") or l.startswith("scause") or l.startswith("stval"): + # We do update some CSRs + CSRs[csr] = val + else: + # Others we preserve until changed later + pageFaultCSRs[csr] = val + elif pageFaultCSRs and (csr in pageFaultCSRs): + if (val != pageFaultCSRs[csr]): + del pageFaultCSRs[csr] + CSRs[csr] = val + else: + CSRs[csr] = val + +def parseRegs(l): + global parseState, inPageFault, CSRs, pageFaultCSRs, regs, pageFaultCSRs, instrs + if "mcounteren" in l: + printCSRs() + # New non-disassembled instruction + parseState = "CSRs" + parseCSRs(l) + elif l.startswith('--------'): + # End of disassembled instruction + printCSRs() + parseState = "idle" + else: + s = l.split() + for i in range(0,len(s),2): + if '/' in s[i]: + reg = s[i].split('/')[1] + val = int(s[i+1], 16) + if inPageFault: + pageFaultRegs[reg] = val + else: + if pageFaultRegs and (reg in pageFaultRegs): + if (val != pageFaultRegs[reg]): + del pageFaultRegs[reg] + regs[reg] = val + else: + regs[reg] = val + val = regs[reg] + print('{}{}{:#x} {}'.format(reg, ' '*(15-len(reg)), val, val)) + else: + sys.stderr.write("Whoops. Expected a list of reg file regs; got:\n"+l) + +############# +# Main Code # +############# +for l in fileinput.input(): + if l.startswith('qemu-system-riscv64: QEMU: Terminated via GDBstub'): + break + elif l.startswith('IN:'): + # New disassembled instr + parseState = "instr" + elif (parseState == "instr") and l.startswith('0x'): + if "out of bounds" in l: + sys.stderr.write("Detected QEMU page fault error\n") + inPageFault = 1 + else: + inPageFault = 0 + adr = int(l.split()[0][2:-1], 16) + instrs[adr] = l + parseState = "CSRs" + elif parseState == "CSRs": + parseCSRs(l) + elif parseState == "regFile": + parseRegs(l) diff --git a/wally-pipelined/linux-testgen/setup_OVP.sh b/wally-pipelined/linux-testgen/setup_OVP.sh new file mode 100755 index 00000000..66cd899d --- /dev/null +++ b/wally-pipelined/linux-testgen/setup_OVP.sh @@ -0,0 +1,7 @@ +#!/bin/bash +source /cad/riscv/OVP/Imperas.20200630/bin/setup.sh +setupImperas /cad/riscv/OVP/Imperas.20200630 -m32 +source /cad/riscv/OVP/Imperas.20200630/bin/switchRuntime.sh 2>/dev/null +echo 1 | switchRuntimeImperas +source /cad/riscv/OVP/Imperas.20200630/bin/switchISS.sh 2>/dev/null +echo 1 | switchISSImperas diff --git a/wally-pipelined/linux-testgen/start_OVP.sh b/wally-pipelined/linux-testgen/start_OVP.sh new file mode 100755 index 00000000..7d2815c1 --- /dev/null +++ b/wally-pipelined/linux-testgen/start_OVP.sh @@ -0,0 +1,2 @@ +#!/bin/bash +sh /cad/riscv/OVP/Imperas.20200630/Demo/Platforms/riscv_RV64GC_Virtio_Linux/harness/RUN_Virtio_Linux.sh --gdbconsole --gdbinit /mnt/scratch/riscv_testbench/gdbinit From 0321d74562cfc7f73e2f9d6438b0819797dc9cc9 Mon Sep 17 00:00:00 2001 From: bbracker Date: Thu, 10 Jun 2021 09:59:26 -0400 Subject: [PATCH 3/4] attempt to fix regression by adding PMP_ENTRIES to configs --- wally-pipelined/config/buildroot/wally-config.vh | 3 +++ wally-pipelined/config/busybear/wally-config.vh | 3 +++ 2 files changed, 6 insertions(+) diff --git a/wally-pipelined/config/buildroot/wally-config.vh b/wally-pipelined/config/buildroot/wally-config.vh index 398c46dc..8e8ec1ca 100644 --- a/wally-pipelined/config/buildroot/wally-config.vh +++ b/wally-pipelined/config/buildroot/wally-config.vh @@ -52,6 +52,9 @@ `define ITLB_ENTRY_BITS 5 `define DTLB_ENTRY_BITS 5 +// Legal number of PMP entries are 0, 16, or 64 +`define PMP_ENTRIES 16 + // Address space `define RESET_VECTOR 64'h0000000000001000 diff --git a/wally-pipelined/config/busybear/wally-config.vh b/wally-pipelined/config/busybear/wally-config.vh index 269f3ae2..aa122e7e 100644 --- a/wally-pipelined/config/busybear/wally-config.vh +++ b/wally-pipelined/config/busybear/wally-config.vh @@ -52,6 +52,9 @@ `define ITLB_ENTRY_BITS 5 `define DTLB_ENTRY_BITS 5 +// Legal number of PMP entries are 0, 16, or 64 +`define PMP_ENTRIES 16 + // Address space `define RESET_VECTOR 64'h0000000000001000 From f272cd46d8845358057c202b27f4fb4b882f20f4 Mon Sep 17 00:00:00 2001 From: bbracker Date: Thu, 10 Jun 2021 10:19:10 -0400 Subject: [PATCH 4/4] peripheral lint fixes --- wally-pipelined/src/uncore/plic.sv | 12 ++++++------ wally-pipelined/src/uncore/uartPC16550D.sv | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/wally-pipelined/src/uncore/plic.sv b/wally-pipelined/src/uncore/plic.sv index db25c241..dc50eb4f 100644 --- a/wally-pipelined/src/uncore/plic.sv +++ b/wally-pipelined/src/uncore/plic.sv @@ -118,12 +118,12 @@ module plic ( 24'h002004: intEn[N:32] <= #1 Din[31:0]; `endif 24'h200000: intThreshold[2:0] <= #1 Din[2:0]; - 24'h200004: intInProgress <= #1 intInProgress & ~(1'b1 << (Din[5:0]-1)); // lower "InProgress" to signify completion + 24'h200004: intInProgress <= #1 intInProgress & ~(4'b1 << (Din[5:0]-1)); // lower "InProgress" to signify completion endcase // reading if (memread) casez(entry) - 24'h0000??: Dout <= #1 {{(`XLEN-3){1'b0}},intPriority[entry[7:2]]}; + 24'h0000??: Dout <= #1 {29'b0,intPriority[entry[7:2]]}; `ifdef PLIC_NUM_SRC_LT_32 24'h001000: Dout <= #1 {{(31-N){1'b0}},intPending[N:1],1'b0}; 24'h002000: Dout <= #1 {{(31-N){1'b0}},intEn[N:1],1'b0}; @@ -137,7 +137,7 @@ module plic ( 24'h200000: Dout <= #1 {29'b0,intThreshold[2:0]}; 24'h200004: begin Dout <= #1 {26'b0,intClaim}; - intInProgress <= #1 intInProgress | (1'b1 << (intClaim-1)); // claimed requests are currently in progress of being serviced until they are completed + intInProgress <= #1 intInProgress | (4'b1 << (intClaim-1)); // claimed requests are currently in progress of being serviced until they are completed end default: Dout <= #1 32'hdeadbeef; // invalid access endcase @@ -159,8 +159,8 @@ module plic ( // pending updates // *** verify that this matches the expectations of the things that make requests (in terms of timing, edge-triggered vs level-triggered) - assign nextIntPending = (intPending | (requests & ~intInProgress)) // requests should raise intPending except when their service routine is already in progress - & ~(((entry == 24'h200004) && memread) << (intClaim-1)); // clear pending bit when claim register is read + assign nextIntPending = (intPending | (requests & ~intInProgress)) & // requests should raise intPending except when their service routine is already in progress + ~({4{((entry == 24'h200004) & memread)}} << (intClaim-1)); // clear pending bit when claim register is read flopr #(N) intPendingFlop(HCLK,~HRESETn,nextIntPending,intPending); // pending array - indexed by priority_lvl x source_ID @@ -207,7 +207,7 @@ module plic ( always_comb begin intClaim = 6'b0; for(j=N; j>0; j=j-1) begin - if(pendingRequestsAtMaxP[j]) intClaim = j; + if(pendingRequestsAtMaxP[j]) intClaim = j[5:0]; end end diff --git a/wally-pipelined/src/uncore/uartPC16550D.sv b/wally-pipelined/src/uncore/uartPC16550D.sv index 057c92ba..4ead3f67 100644 --- a/wally-pipelined/src/uncore/uartPC16550D.sv +++ b/wally-pipelined/src/uncore/uartPC16550D.sv @@ -455,7 +455,7 @@ module uartPC16550D( assign squashRXerrIP = (prevSquashRXerrIP | setSquashRXerrIP) & ~resetSquashRXerrIP; flopr #(1) squashRXerrIPreg(HCLK, ~HRESETn, squashRXerrIP, prevSquashRXerrIP); // Side effect of reading IIR is lowering THRE_IP if most significant intr - assign setSquashTHRE_IP = ~MEMRb & (A==3'b010) & (intrID==2'h1); // there's a 1-cycle delay on set squash so that THRE_IP doesn't change during the process of reading IIR (otherwise combinational loop) + assign setSquashTHRE_IP = ~MEMRb & (A==3'b010) & (intrID==3'h1); // there's a 1-cycle delay on set squash so that THRE_IP doesn't change during the process of reading IIR (otherwise combinational loop) assign resetSquashTHRE_IP = ~THRE; assign squashTHRE_IP = prevSquashTHRE_IP & ~resetSquashTHRE_IP; flopr #(1) squashTHRE_IPreg(HCLK, ~HRESETn, squashTHRE_IP | setSquashTHRE_IP, prevSquashTHRE_IP);