|
|
|
|
@ -4,7 +4,7 @@ import os
|
|
|
|
|
random.seed(0)
|
|
|
|
|
|
|
|
|
|
reg = [f"x{i}" for i in range(32)]
|
|
|
|
|
# 定义R型运算类指令
|
|
|
|
|
# Define R-type arithmetic instructions
|
|
|
|
|
inst_reg = [
|
|
|
|
|
"add",
|
|
|
|
|
"sub",
|
|
|
|
|
@ -62,15 +62,13 @@ file_name = "test"
|
|
|
|
|
mem_start = 0x80200000
|
|
|
|
|
mem_end = 0x80210000
|
|
|
|
|
|
|
|
|
|
# 自动生成R型指令测试样例1000个输出到file_name文件中
|
|
|
|
|
# 新建build文件夹存放生成的文件
|
|
|
|
|
# 初始化寄存器状态,0表示可用
|
|
|
|
|
# Initialize register status: 0 means available.
|
|
|
|
|
reg_status = {r: 0 for r in reg}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_available_reg(reg, reg_status):
|
|
|
|
|
available_regs = [r for r, status in reg_status.items() if status == 0]
|
|
|
|
|
if not available_regs: # 如果没有可用的寄存器,则返回x0
|
|
|
|
|
if not available_regs: # If no register available, return x0.
|
|
|
|
|
return reg[0]
|
|
|
|
|
return random.choice(available_regs)
|
|
|
|
|
|
|
|
|
|
@ -78,7 +76,7 @@ def get_available_reg(reg, reg_status):
|
|
|
|
|
def update_reg_status(reg_status):
|
|
|
|
|
for r in reg_status:
|
|
|
|
|
if reg_status[r] > 0:
|
|
|
|
|
reg_status[r] -= 1 # 减少计数,向可用状态靠近
|
|
|
|
|
reg_status[r] -= 1 # Countdown to register availability
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_reg_inst(insts=inst_reg):
|
|
|
|
|
@ -87,8 +85,8 @@ def test_reg_inst(insts=inst_reg):
|
|
|
|
|
rs1 = get_available_reg(reg, reg_status)
|
|
|
|
|
rs2 = get_available_reg(reg, reg_status)
|
|
|
|
|
f.write(f"\t{inst} {rd}, {rs1}, {rs2}\n")
|
|
|
|
|
reg_status[rd] = 4 # 解决数据冲突
|
|
|
|
|
update_reg_status(reg_status) # 更新寄存器状态
|
|
|
|
|
reg_status[rd] = 4 # Delay to avoid data hazard
|
|
|
|
|
update_reg_status(reg_status)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_imm_inst():
|
|
|
|
|
@ -102,8 +100,8 @@ def test_imm_inst():
|
|
|
|
|
else:
|
|
|
|
|
imm = random.randint(-(2**11), 2**11 - 1)
|
|
|
|
|
f.write(f"\t{inst} {rd}, {rs1}, {imm}\n")
|
|
|
|
|
reg_status[rd] = 4 # 解决数据冲突
|
|
|
|
|
update_reg_status(reg_status) # 更新寄存器状态
|
|
|
|
|
reg_status[rd] = 4
|
|
|
|
|
update_reg_status(reg_status)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_lui_inst():
|
|
|
|
|
@ -111,8 +109,8 @@ def test_lui_inst():
|
|
|
|
|
rd = get_available_reg(reg, reg_status)
|
|
|
|
|
imm = random.randint(0, 2**20 - 1)
|
|
|
|
|
f.write(f"\t{inst} {rd}, {imm}\n")
|
|
|
|
|
reg_status[rd] = 4 # 解决数据冲突
|
|
|
|
|
update_reg_status(reg_status) # 更新寄存器状态
|
|
|
|
|
reg_status[rd] = 4
|
|
|
|
|
update_reg_status(reg_status)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def wait_gpr(index):
|
|
|
|
|
@ -130,7 +128,7 @@ def insert_nop(n=3):
|
|
|
|
|
def test_lb():
|
|
|
|
|
f.write("\taddiw x1, x0, 1025\n")
|
|
|
|
|
insert_nop()
|
|
|
|
|
f.write("\tslli x1, x1, 0x15\n") # x1=0x80200000
|
|
|
|
|
f.write("\tslli x1, x1, 0x15\n") # x1 = 0x80200000
|
|
|
|
|
insert_nop()
|
|
|
|
|
rd = get_available_reg(reg, reg_status)
|
|
|
|
|
while rd == "x1":
|
|
|
|
|
@ -139,82 +137,183 @@ def test_lb():
|
|
|
|
|
imm = random.randint(-(2**11), 2**11 - 1)
|
|
|
|
|
f.write(f"\tsb {rd}, {imm}({rs1})\n")
|
|
|
|
|
f.write(f"\tlb {rd}, {imm}({rs1})\n")
|
|
|
|
|
reg_status[rd] = 4 # 解决数据冲突
|
|
|
|
|
update_reg_status(reg_status) # 更新寄存器状态
|
|
|
|
|
reg_status[rd] = 4
|
|
|
|
|
update_reg_status(reg_status)
|
|
|
|
|
rd = get_available_reg(reg, reg_status)
|
|
|
|
|
while rd == "x1":
|
|
|
|
|
rd = get_available_reg(reg, reg_status)
|
|
|
|
|
f.write(f"\tlbu {rd}, {imm}({rs1})\n")
|
|
|
|
|
reg_status[rd] = 4 # 解决数据冲突
|
|
|
|
|
update_reg_status(reg_status) # 更新寄存器状态
|
|
|
|
|
reg_status[rd] = 4
|
|
|
|
|
update_reg_status(reg_status)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_lh():
|
|
|
|
|
f.write("\taddiw x1, x0, 1025\n")
|
|
|
|
|
insert_nop()
|
|
|
|
|
f.write("\tslli x1, x1, 0x15\n") # x1=0x80200000
|
|
|
|
|
f.write("\tslli x1, x1, 0x15\n") # x1 = 0x80200000
|
|
|
|
|
insert_nop()
|
|
|
|
|
rd = get_available_reg(reg, reg_status)
|
|
|
|
|
while rd == "x1":
|
|
|
|
|
rd = get_available_reg(reg, reg_status)
|
|
|
|
|
rs1 = "x1"
|
|
|
|
|
# Align immediate for halfword access (even address)
|
|
|
|
|
imm = random.randint(-(2**11), 2**11 - 1) & 0xFFFFFFFFFFFFFFFE
|
|
|
|
|
f.write(f"\tsh {rd}, {imm}({rs1})\n")
|
|
|
|
|
f.write(f"\tlh {rd}, {imm}({rs1})\n")
|
|
|
|
|
reg_status[rd] = 4 # 解决数据冲突
|
|
|
|
|
update_reg_status(reg_status) # 更新寄存器状态
|
|
|
|
|
reg_status[rd] = 4
|
|
|
|
|
update_reg_status(reg_status)
|
|
|
|
|
rd = get_available_reg(reg, reg_status)
|
|
|
|
|
while rd == "x1":
|
|
|
|
|
rd = get_available_reg(reg, reg_status)
|
|
|
|
|
f.write(f"\tlhu {rd}, {imm}({rs1})\n")
|
|
|
|
|
reg_status[rd] = 4 # 解决数据冲突
|
|
|
|
|
update_reg_status(reg_status) # 更新寄存器状态
|
|
|
|
|
reg_status[rd] = 4
|
|
|
|
|
update_reg_status(reg_status)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_lw():
|
|
|
|
|
f.write("\taddiw x1, x0, 1025\n")
|
|
|
|
|
insert_nop()
|
|
|
|
|
f.write("\tslli x1, x1, 0x15\n") # x1=0x80200000
|
|
|
|
|
f.write("\tslli x1, x1, 0x15\n") # x1 = 0x80200000
|
|
|
|
|
insert_nop()
|
|
|
|
|
rd = get_available_reg(reg, reg_status)
|
|
|
|
|
while rd == "x1":
|
|
|
|
|
rd = get_available_reg(reg, reg_status)
|
|
|
|
|
rs1 = "x1"
|
|
|
|
|
# Align immediate for word access (multiple of 4)
|
|
|
|
|
imm = random.randint(-(2**11), 2**11 - 1) & 0xFFFFFFFFFFFFFFFC
|
|
|
|
|
f.write(f"\tsw {rd}, {imm}({rs1})\n")
|
|
|
|
|
f.write(f"\tlw {rd}, {imm}({rs1})\n")
|
|
|
|
|
reg_status[rd] = 4 # 解决数据冲突
|
|
|
|
|
update_reg_status(reg_status) # 更新寄存器状态
|
|
|
|
|
reg_status[rd] = 4
|
|
|
|
|
update_reg_status(reg_status)
|
|
|
|
|
rd = get_available_reg(reg, reg_status)
|
|
|
|
|
while rd == "x1":
|
|
|
|
|
rd = get_available_reg(reg, reg_status)
|
|
|
|
|
f.write(f"\tlwu {rd}, {imm}({rs1})\n")
|
|
|
|
|
reg_status[rd] = 4 # 解决数据冲突
|
|
|
|
|
update_reg_status(reg_status) # 更新寄存器状态
|
|
|
|
|
reg_status[rd] = 4
|
|
|
|
|
update_reg_status(reg_status)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_ld():
|
|
|
|
|
f.write("\taddiw x1, x0, 1025\n")
|
|
|
|
|
insert_nop()
|
|
|
|
|
f.write("\tslli x1, x1, 0x15\n") # x1=0x80200000
|
|
|
|
|
f.write("\tslli x1, x1, 0x15\n") # x1 = 0x80200000
|
|
|
|
|
insert_nop()
|
|
|
|
|
rd = get_available_reg(reg, reg_status)
|
|
|
|
|
while rd == "x1":
|
|
|
|
|
rd = get_available_reg(reg, reg_status)
|
|
|
|
|
rs1 = "x1"
|
|
|
|
|
# Align immediate for doubleword access (multiple of 8)
|
|
|
|
|
imm = random.randint(-(2**11), 2**11 - 1) & 0xFFFFFFFFFFFFFFF8
|
|
|
|
|
f.write(f"\tsd {rd}, {imm}({rs1})\n")
|
|
|
|
|
f.write(f"\tld {rd}, {imm}({rs1})\n")
|
|
|
|
|
reg_status[rd] = 4 # 解决数据冲突
|
|
|
|
|
update_reg_status(reg_status) # 更新寄存器状态
|
|
|
|
|
reg_status[rd] = 4
|
|
|
|
|
update_reg_status(reg_status)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_store_load_cycle():
|
|
|
|
|
"""
|
|
|
|
|
This function stores several registers into memory using store instructions
|
|
|
|
|
with properly aligned immediates, then overwrites those memory addresses,
|
|
|
|
|
and finally loads the values back using the corresponding load instructions.
|
|
|
|
|
"""
|
|
|
|
|
# Set up x1 as the memory base address (0x80200000)
|
|
|
|
|
f.write("\taddiw x1, x0, 1025\n")
|
|
|
|
|
insert_nop()
|
|
|
|
|
f.write("\tslli x1, x1, 0x15\n")
|
|
|
|
|
insert_nop()
|
|
|
|
|
|
|
|
|
|
cycle_count = 5 # Number of store instructions in each cycle.
|
|
|
|
|
store_entries = []
|
|
|
|
|
|
|
|
|
|
# First, store values using a randomly chosen store instruction.
|
|
|
|
|
for _ in range(cycle_count):
|
|
|
|
|
rd = get_available_reg(reg, reg_status)
|
|
|
|
|
while rd == "x1":
|
|
|
|
|
rd = get_available_reg(reg, reg_status)
|
|
|
|
|
|
|
|
|
|
store_inst = random.choice(inst_store)
|
|
|
|
|
if store_inst == "sb":
|
|
|
|
|
imm = random.randint(-(2**11), 2**11 - 1)
|
|
|
|
|
elif store_inst == "sh":
|
|
|
|
|
# Align immediate to an even address.
|
|
|
|
|
imm = random.randint(-(2**11), 2**11 - 1) & 0xFFFFFFFFFFFFFFFE
|
|
|
|
|
elif store_inst == "sw":
|
|
|
|
|
# Align immediate to a multiple of 4.
|
|
|
|
|
imm = random.randint(-(2**11), 2**11 - 1) & 0xFFFFFFFFFFFFFFFC
|
|
|
|
|
elif store_inst == "sd":
|
|
|
|
|
# Align immediate to a multiple of 8.
|
|
|
|
|
imm = random.randint(-(2**11), 2**11 - 1) & 0xFFFFFFFFFFFFFFF8
|
|
|
|
|
f.write(f"\t{store_inst} {rd}, {imm}(x1)\n")
|
|
|
|
|
store_entries.append((store_inst, imm, rd))
|
|
|
|
|
reg_status[rd] = 4
|
|
|
|
|
update_reg_status(reg_status)
|
|
|
|
|
|
|
|
|
|
# Overwrite the previously stored addresses with new values.
|
|
|
|
|
overwrite_entries = []
|
|
|
|
|
for _ in range(cycle_count):
|
|
|
|
|
rd = get_available_reg(reg, reg_status)
|
|
|
|
|
while rd == "x1":
|
|
|
|
|
rd = get_available_reg(reg, reg_status)
|
|
|
|
|
|
|
|
|
|
store_inst = random.choice(inst_store)
|
|
|
|
|
if store_inst == "sb":
|
|
|
|
|
imm = random.randint(-(2**11), 2**11 - 1)
|
|
|
|
|
elif store_inst == "sh":
|
|
|
|
|
imm = random.randint(-(2**11), 2**11 - 1) & 0xFFFFFFFFFFFFFFFE
|
|
|
|
|
elif store_inst == "sw":
|
|
|
|
|
imm = random.randint(-(2**11), 2**11 - 1) & 0xFFFFFFFFFFFFFFFC
|
|
|
|
|
elif store_inst == "sd":
|
|
|
|
|
imm = random.randint(-(2**11), 2**11 - 1) & 0xFFFFFFFFFFFFFFF8
|
|
|
|
|
f.write(f"\t{store_inst} {rd}, {imm}(x1)\n")
|
|
|
|
|
overwrite_entries.append((store_inst, imm, rd))
|
|
|
|
|
reg_status[rd] = 4
|
|
|
|
|
update_reg_status(reg_status)
|
|
|
|
|
|
|
|
|
|
# Now, load back the values stored in the first cycle.
|
|
|
|
|
for store_inst, imm, reg_written in store_entries:
|
|
|
|
|
rd = get_available_reg(reg, reg_status)
|
|
|
|
|
while rd == "x1":
|
|
|
|
|
rd = get_available_reg(reg, reg_status)
|
|
|
|
|
# Choose an appropriate load instruction corresponding to the store type.
|
|
|
|
|
if store_inst == "sb":
|
|
|
|
|
load_inst = random.choice(["lb", "lbu"])
|
|
|
|
|
elif store_inst == "sh":
|
|
|
|
|
load_inst = random.choice(["lh", "lhu"])
|
|
|
|
|
elif store_inst == "sw":
|
|
|
|
|
load_inst = random.choice(["lw", "lwu"])
|
|
|
|
|
elif store_inst == "sd":
|
|
|
|
|
load_inst = "ld"
|
|
|
|
|
f.write(f"\t{load_inst} {rd}, {imm}(x1)\n")
|
|
|
|
|
reg_status[rd] = 4
|
|
|
|
|
update_reg_status(reg_status)
|
|
|
|
|
|
|
|
|
|
# Similarly, load back the values from the overwrite cycle.
|
|
|
|
|
for store_inst, imm, reg_written in overwrite_entries:
|
|
|
|
|
rd = get_available_reg(reg, reg_status)
|
|
|
|
|
while rd == "x1":
|
|
|
|
|
rd = get_available_reg(reg, reg_status)
|
|
|
|
|
if store_inst == "sb":
|
|
|
|
|
load_inst = random.choice(["lb", "lbu"])
|
|
|
|
|
elif store_inst == "sh":
|
|
|
|
|
load_inst = random.choice(["lh", "lhu"])
|
|
|
|
|
elif store_inst == "sw":
|
|
|
|
|
load_inst = random.choice(["lw", "lwu"])
|
|
|
|
|
elif store_inst == "sd":
|
|
|
|
|
load_inst = "ld"
|
|
|
|
|
f.write(f"\t{load_inst} {rd}, {imm}(x1)\n")
|
|
|
|
|
reg_status[rd] = 4
|
|
|
|
|
update_reg_status(reg_status)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Create the build directory if it doesn't exist.
|
|
|
|
|
if not os.path.exists("build"):
|
|
|
|
|
os.mkdir("build")
|
|
|
|
|
|
|
|
|
|
with open("./build/{}.s".format(file_name), "w") as f:
|
|
|
|
|
f.write(".text\n")
|
|
|
|
|
f.write(".global _start\n")
|
|
|
|
|
f.write("_start:\n")
|
|
|
|
|
# Generate some immediate and LUI instructions.
|
|
|
|
|
for i in range(100):
|
|
|
|
|
test_imm_inst()
|
|
|
|
|
test_lui_inst()
|
|
|
|
|
@ -223,7 +322,7 @@ with open("./build/{}.s".format(file_name), "w") as f:
|
|
|
|
|
test_reg_inst()
|
|
|
|
|
random.choice([test_imm_inst, test_lui_inst, test_reg_inst])()
|
|
|
|
|
random.choice(instructions)()
|
|
|
|
|
# 结束程序
|
|
|
|
|
# End the program.
|
|
|
|
|
wait_gpr(3)
|
|
|
|
|
f.write("\tli x3, 1\n")
|
|
|
|
|
wait_gpr(17)
|
|
|
|
|
|