Open ColsonZhang opened 3 years ago
issue9里有我写的verilog代码,应该跟你是差不多的意思
issue9里有我写的verilog代码,应该跟你是差不多的意思
谢谢!!! 我之前没有注意到,在这里给大家指个路。 点击右方链接有verilog版本的访存代码-> https://github.com/OSCPU/ysyx/issues/9#issuecomment-891889850
请问是重新写了ram.v吗?我看默认的ramhelper只能提交一个读取数据的地址,为什么你的程序既可以提交指令的地址又能提交读取内存的地址呢? 还有请问测试访存的.bin文件能共享一下吗? 多谢!!!
请问是重新写了ram.v吗?我看默认的ramhelper只能提交一个读取数据的地址,为什么你的程序既可以提交指令的地址又能提交读取内存的地址呢? 还有请问测试访存的.bin文件能共享一下吗? 多谢!!!
这里我重写了双端口的ram,如下图所示。 测试访存的bin文件cpu-test里面有一个load-store.c,也可以进行访存的测试。如果实在需要这个.bin可以留个邮箱。
这里我重写了双端口的ram,如下图所示。
了解了!十分感谢! 麻烦发我一下吧!liusyic@gmail.com 多谢!
这里我重写了双端口的ram,如下图所示。
了解了!十分感谢! 麻烦发我一下吧!liusyic@gmail.com 多谢!
已发送,准备分享一下汇编的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文件如下。
00: 0010029b # addiw t0,zero,1
04: 01f29293 # slli t0,t0,0x1f
08: 00100213 # li tp,1
0c: 0042a423 # sw tp,8(t0)
10: 00120213 # addi tp,tp,1 # 0x1
14: 0042a623 # sw tp,12(t0)
18: 00120213 # addi tp,tp,1 # 0x1
1c: 0042a823 # sw tp,16(t0)
20: 00120213 # addi tp,tp,1 # 0x1
24: 0042aa23 # sw tp,20(t0)
28: 0082a303 # lw t1,8(t0)
2c: 00c2a383 # lw t2,12(t0)
30: 0102a403 # lw s0,16(t0)
34: 0142a483 # lw s1,20(t0)
35: 0000006b # shut down
收到 十分感谢!
老哥你在文章中说的
“通过分析可以发现理想的寄存器状态是0x0000000400000003,而读出的数据是0x0000000000000003。该pc对应的指令ld,即读取64位数据。那么基本可以判断是在对存储器进行读写时出现的问题。”
有查到是什么原因吗,我用ram_read_helper打印出来的访存数据,和bin文件里对应地址的数据不一样。0x0000000e00000006,读成了0x0000000000000006。
老哥你在文章中说的
“通过分析可以发现理想的寄存器状态是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自动生成的代码,可读性比较差