-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
difftest访存踩坑分享 #10
Comments
issue9里有我写的verilog代码,应该跟你是差不多的意思 |
谢谢!!! |
了解了!十分感谢! |
已发送,准备分享一下汇编的8进制txt转机器可读取的二进制文件的python小工具。如果有需要对汇编文件进行修改,可以用该程序转换为2进制文件。 import string
import os
import sys
import getopt
def read_file(filename):
with open(filename, 'r') as f:
lines = f.readlines()
return lines
def extract_num(lines, mode='hex', reverse=False):
if mode in ('hex','Hex','HEX'):
str_width = 2
int_widht = 16
elif mode in ('bin','Bin','BIN'):
str_width = 8
int_widht = 2
else:
return False
context = ""
for line in lines:
if ':' in line:
line = line[ line.index(':')+1 : ] # ignore the inst-addr
if '#' in line:
line = line[: line.index('#') ] # ignore the inst-note
context = context + line
context = context.replace(' ', '').replace('_', '').replace('\n', '').replace('\t', '')
list_nums = []
len_byte = int(len(context)/str_width) #计算字节的个数
for i in range(0, len_byte): #循环将解析出来的字节填充到list中
chs = context[str_width*i : str_width*i + str_width]
num = int(chs, int_widht)
list_nums.append(num)
if(reverse):
list_nums = order_reverse(list_nums)
data_bys = bytes(list_nums)
return data_bys, list_nums
def export_bin(filename, data_bys):
with open(filename, "wb") as f:
f.write(data_bys)
def export_txt(filename, data_export ):
with open(filename, "w") as f:
f.write(data_export)
def binary_str_gen(list_nums):
c = ""
for count, i in enumerate(list_nums):
temp = "{:0>8b}".format(i)
c = c + temp
if (count+1) % 4 == 0:
c = c + "\n"
else:
c = c + "_"
return c
def order_reverse(list_nums):
new_list = []
the_len = int(len(list_nums)/4)
for i in range(the_len):
for j in range(3,-1,-1):
new_list.append( list_nums[4*i+j] )
print("reverse the list")
return new_list
def judege_bool(the_str):
if the_str in ("True","true","TRUE","T","t"):
return True
else:
return False
def arg_handler():
# default-values
inputfile = "./czcpu/test.txt"
outputfile = "./czcpu/test.bin"
mode = "hex"
export = "False"
reverse = "False"
try:
argv = sys.argv[1:]
opts, args = getopt.getopt(argv,"hi:o:m:e:r:",["ifile=","ofile=","mode=","export=","reverse="])
# print(argv)
# print(opts)
except getopt.GetoptError:
print('BinGen.py -i <inputfile> -o <outputfile>')
sys.exit(2)
for opt, arg in opts:
if opt in ("-h", "--help"):
print('BinGen.py -i <inputfile> -o <outputfile> -m <mode>(hex or bin) -e -r')
print('-i input-file-path\n-o output-file-path\n-m input-data-mode(hex or bin)\n-e export?\n-r reverse the list?')
sys.exit()
elif opt in ("-i", "--ifile"):
inputfile = arg
elif opt in ("-o", "--ofile"):
outputfile = arg
elif opt in ("-m", "--mode"):
mode = arg
elif opt in ("-e", "--export"):
export = arg
elif opt in ("-r", "--reverse"):
reverse = arg
return inputfile, outputfile, mode, export, reverse
if __name__== '__main__':
# get the args
inputfile, outputfile, mode, export, reverse = arg_handler()
# print(inputfile, outputfile, mode, export, reverse)
export = judege_bool(export)
reverse = judege_bool(reverse)
if os.path.exists(inputfile) == False:
print("The input-file does not exist !!!")
sys.exit(2)
lines = read_file(inputfile)
data_bys, list_nums = extract_num(lines, mode=mode, reverse=reverse)
# print(data_bys)
if export :
data_export = binary_str_gen(list_nums)
export_txt(outputfile, data_export)
print("Extracting the bin from the hex is done !")
else:
export_bin(outputfile, data_bys)
print("Exporting the bin-file is done !") 标准格式的txt文件如下。
|
收到 十分感谢! |
老哥你在文章中说的 “通过分析可以发现理想的寄存器状态是0x0000000400000003,而读出的数据是0x0000000000000003。该pc对应的指令ld,即读取64位数据。那么基本可以判断是在对存储器进行读写时出现的问题。” 有查到是什么原因吗,我用ram_read_helper打印出来的访存数据,和bin文件里对应地址的数据不一样。0x0000000e00000006,读成了0x0000000000000006。 |
你好,这个应该是因为你在读写的时候没有添加掩码,可以参考上面我写的chisel代码或者我标注的另一个issue中的verilog代码。 |
错误描述
我在对lw和sw指令进行测试,按照学长提供的测试代码自己写了一段汇编并翻译成2进制进行测试。
我在ram.cpp里面加入了printf信号打印出存储器,看到写入和读出的数据是正确的。
但是difftest报错显示,这个读出的数据和理想的寄存器数据不同?
通过分析可以发现理想的寄存器状态是0x0000000400000003,而读出的数据是0x0000000000000003。该pc对应的指令ld,即读取64位数据。那么基本可以判断是在对存储器进行读写时出现的问题。
访存分析
大小端模式
RISCV的数据均为小端模式,即高位数据存储在存储器的大地址,低位数据存储在存储器的小地址。以下图为例,最高位字节是0x0A,最低位字节是0x0D。
Difftest的读出写入函数
打开
difftest/src/test/csrc/common/ram.cpp
文件,找到ram_write_helper和ram_inst_helper函数。在这里,我添加了两行printf(已注释)来打印写入或者读出数据,来辅助调试。分析代码可以发现,代码的读写都是以uint64_t进行的!!!所以在写入过程加入了一个64位的写入掩码wmask!!!
即,该存储器是按照64位的存储空间设置的,所以对应的rtl代码要做出相同的适配。
由于项目给出的例子中没有涉及到回写部分的操作,所以在这里我也是纠结了很久才修正了bug。
RTL访存代码(chisel)
我使用的是chisel,给出我的访存部分的代码;对于verilog选手,我也会给出chisel生成的verilog代码。
chisel代码——difftest接口
大体上和chisel接入difftest经验贴的接入部分一致。需要特别注意的是
( rvcore.io.mem_r_addr - "h80000000".U(64.W) ) >> 3.U
这里计算出来的地址要右移3位。主要原因在于存储器的每个存储地址对应的存储空间是64位的!!!最低的3位的地址是该存储地址内存储空间的索引。假设低4位的地址为
the_addr[3:0]
,存储器存储的64位数据为the_data[63:0]
。那么对于
lw
来说,the_addr[2]
就决定读取the_data
的高32位the_data[63:32]
还是低32位the_data[31:0]
。同样对于
lh
来说,the_addr[2:1]
就决定读取the_data
的高16位the_data[63:48]
或者是中间的the_data[47:32]
或the_data[31:16]
还是低16位the_data[15:0]
。同样对于
lb
来说,the_addr[2:0]
就决定读取the_data
的哪8位数据。对于写入,也是相同的情况。
chisel代码——访存阶段(Mem_Stage)
代码写的比较烂,没有进行优化。核心的思想就是,写入或者读出时,按照读写指令的类型和具体的地址,对数据进行移位,配合读写掩码得到正确的结果。
verilog代码——访存
chisel自动生成的代码,可读性比较差
The text was updated successfully, but these errors were encountered: