forked from Github_Repos/cvw
Merge branch 'main' of https://github.com/davidharrishmc/riscv-wally into main
This commit is contained in:
commit
d386929c0e
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
68
wally-pipelined/linux-testgen/combineGDBs.py
Executable file
68
wally-pipelined/linux-testgen/combineGDBs.py
Executable file
@ -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()
|
2
wally-pipelined/linux-testgen/find_csr.sh
Executable file
2
wally-pipelined/linux-testgen/find_csr.sh
Executable file
@ -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, -
|
9
wally-pipelined/linux-testgen/fix_mem.py
Executable file
9
wally-pipelined/linux-testgen/fix_mem.py
Executable file
@ -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')
|
15
wally-pipelined/linux-testgen/gdbinit
Executable file
15
wally-pipelined/linux-testgen/gdbinit
Executable file
@ -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
|
23
wally-pipelined/linux-testgen/gdbinit_mem
Executable file
23
wally-pipelined/linux-testgen/gdbinit_mem
Executable file
@ -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
|
10
wally-pipelined/linux-testgen/gdbinit_qemulog
Executable file
10
wally-pipelined/linux-testgen/gdbinit_qemulog
Executable file
@ -0,0 +1,10 @@
|
||||
set pagination off
|
||||
target extended-remote :1234
|
||||
b *0xffffffe00020144e
|
||||
c
|
||||
c
|
||||
c
|
||||
c
|
||||
set confirm off
|
||||
kill
|
||||
q
|
9
wally-pipelined/linux-testgen/gdbinit_qemulog_debug
Executable file
9
wally-pipelined/linux-testgen/gdbinit_qemulog_debug
Executable file
@ -0,0 +1,9 @@
|
||||
set pagination off
|
||||
target extended-remote :1234
|
||||
b *0x000000008020103c
|
||||
c
|
||||
del 1
|
||||
stepi 100
|
||||
set confirm off
|
||||
kill
|
||||
q
|
26
wally-pipelined/linux-testgen/logAllBuildroot.sh
Executable file
26
wally-pipelined/linux-testgen/logAllBuildroot.sh
Executable file
@ -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
|
4
wally-pipelined/linux-testgen/logBuildrootMem.sh
Executable file
4
wally-pipelined/linux-testgen/logBuildrootMem.sh
Executable file
@ -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"
|
1
wally-pipelined/linux-testgen/parseAllBusybear.sh
Executable file
1
wally-pipelined/linux-testgen/parseAllBusybear.sh
Executable file
@ -0,0 +1 @@
|
||||
./combineGDBs.py && cat gdbcombined.txt | ./parse_gdb_output.py "/courses/e190ax/busybear_boot_new/"
|
164
wally-pipelined/linux-testgen/parse_gdb_output.py
Executable file
164
wally-pipelined/linux-testgen/parse_gdb_output.py
Executable file
@ -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')
|
||||
|
107
wally-pipelined/linux-testgen/parse_qemu.py
Executable file
107
wally-pipelined/linux-testgen/parse_qemu.py
Executable file
@ -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)
|
7
wally-pipelined/linux-testgen/setup_OVP.sh
Executable file
7
wally-pipelined/linux-testgen/setup_OVP.sh
Executable file
@ -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
|
2
wally-pipelined/linux-testgen/start_OVP.sh
Executable file
2
wally-pipelined/linux-testgen/start_OVP.sh
Executable file
@ -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
|
@ -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
|
||||
|
||||
|
@ -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 [7:0] TXHR, nexttxdata;
|
||||
@ -107,7 +107,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;
|
||||
|
||||
///////////////////////////////////////////
|
||||
@ -147,13 +149,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
|
||||
|
||||
@ -163,7 +167,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)
|
||||
@ -200,7 +203,6 @@ module uartPC16550D(
|
||||
///////////////////////////////////////////
|
||||
// receive timing and control
|
||||
///////////////////////////////////////////
|
||||
|
||||
always_ff @(posedge HCLK, negedge HRESETn)
|
||||
if (~HRESETn) begin
|
||||
rxoversampledcnt <= #1 0;
|
||||
@ -261,7 +263,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;
|
||||
@ -290,14 +292,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)
|
||||
@ -344,7 +346,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
|
||||
@ -425,20 +426,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;
|
||||
@ -446,9 +449,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==3'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==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);
|
||||
|
||||
///////////////////////////////////////////
|
||||
// modem control logic
|
||||
|
Loading…
Reference in New Issue
Block a user