我正在使用OpenOCD在带有ARM Cortex-A9的嵌入式主板上运行程序(Zynq-7010;我使用的是运行裸机程序的单核)。
我希望能够弄清楚每次内存访问是否导致缓存命中或缓存未命中。 L2高速缓存控制器,L2C-310,提供了两个计数器,我已将其配置为计数数据读取命中数和数据读取查找数(导致命中或未命中)。
问题是,当我执行程序而不停止时,与执行程序和逐行执行程序相比,我得到的结果不同。我的具体问题是:为什么会出现差异,是否可以使输出均匀?更一般地说:是否可以确定特定的汇编线是否导致缓存命中?
我使用python脚本控制OpenOCD。我正在禁用L1缓存(未显示),关闭预取,以及(我认为)关闭预加载引擎。这是我在不停止执行程序时运行的代码:
# A this point, the program has be loaded, and allowed to execute up until the start of the code section I am measuring
telnet = Telnet('127.0.0.1', 4444, 300)
end_addr = 0x100930 # End of code section I am measuing
### 1) Pre-Fetch / Pre-Load stuff ####################
# Turning off the pre-fetch option. Should read, change mask, then write
print('\tSetting pre-fetch option to off\n')
telnet.write('arm mcr 15 0 1 0 1\n')
response = telnet.read_until('arm mcr 15 0 1 0 1\r\n')
response = telnet.read_until('\r>')
print('Response: %s' % (response))
actlr = int(response[:-2])
print('actlr: %d' % (actlr))
actlr = actlr & (~(1 << 2)) # Disable L1 Pre-fetch
actlr = actlr & (~(1)) # Disable TLB / Cache maintenance fwd
print('actlr: %d' % (actlr))
# write to telnet
telnet.write('arm mrc 15 0 1 0 1 ' + str(actlr) + '\n')
telnet.write('arm mcr 15 0 1 0 1\n')
response = telnet.read_until('arm mcr 15 0 1 0 1\r\n')
response = telnet.read_until('\r>')
print('Response: %s' % (response))
print('attempting to pause pre-load engine:')
telnet.write('arm mrc 15 0 11 3 0 0\n')
######################################################
### 2) Enable L2CC counters ##########################
telnet.write('mww 0xF8F02200 0x1\n') # enable counting
# confirm enabled
telnet.write('mdw 0xF8F02200\n')
response = telnet.read_until('mdw 0xF8F02200\r\n')
response = telnet.read_until('\r>')
print('Response should be 1: %s' % (response))
# Counter 0: 0011 to set source to Data Lookup, 01 for increment
telnet.write('mww 0xF8F02208 0xD\n')
# confirm counter 0 settings
telnet.write('mdw 0xF8F02208\n')
response = telnet.read_until('mdw 0xF8F02208\r\n')
response = telnet.read_until('\r>')
print('Response should be 0xD: %s' % (response))
# Counter 1: 0010 to set source to Data Read Hit, 01 for increment
telnet.write('mww 0xF8F02204 0x9\n')
# confirm counter 1 settings
telnet.write('mdw 0xF8F02204\n')
response = telnet.read_until('mdw 0xF8F02204\r\n')
response = telnet.read_until('\r>')
print('Response should be 0x9: %s' % (response))
######################################################
### 3) Different from step mode ######################
print("Setting end tag to 0x%x" % (end_addr))
# Set breakpoint to end of section
telnet.write('bp ' + str(end_addr) + ' 1 hw\n')
telnet.write('resume\n')
response = telnet.read_until('resume\r\n', 1)
response = telnet.read_until('>', 1)
# Allow program to execute
sleep(10)
######################################################
### 4) Check L2CC counters ###########################
# Counter 0: number of data lookups
telnet.write('mdw 0xF8F02210\n')
response = telnet.read_until('mdw 0xF8F02210\r\n')
response = telnet.read_until('\r>')
print('Data Lookups: %s' % (response))
# Counter 1: check number of data read hits
telnet.write('mdw 0xF8F0220C\n')
response = telnet.read_until('mdw 0xF8F0220C\r\n')
response = telnet.read_until('\r>')
print('Data Read Hits: %s' % (response))
system('exit')
结果如下:
Data Lookups: 0xf8f02210: 00000660
Data Read Hits: 0xf8f0220c: 000004c2
当我通过逐步执行每条指令来运行代码时,数据查找的数量最终与读取命中的数量相同......那么这些缓存未命中的位置是什么?
这是更改的代码(块号3):
### 3) Different from continuous mode ##############
print("Setting end tag to 0x%x" % (end_addr))
cur_addr = step()
# Run until the end tag
while cur_addr != end_addr:
cur_addr = step()
step()
函数:
# Commands OpenOCD to step the processor forward
# Returns the new pc address
# Sorry for the messy error checking!
def step():
telnet.write('step\n')
response = telnet.read_until('step\r\n', 1)
# print('Step: %s ****' % (response))
# Skip line of output
response = telnet.read_until('\n', 1)
# print('Step: %s ****' % (response))
# 2nd line has the pc, 4th column
response = telnet.read_until('\n', 1)
# print('Step: %s ****' % (response))
try:
cur_addr = int(response.strip().split()[3], 16)
except (ValueError, IndexError) as e:
print("Error step() on line: ", response)
print("\tException: ", e)
countdown = 20
error = True
while (countdown > 0):
countdown = countdown - 1
response = telnet.read_until('\n', 1)
#print("Retry on line: ", response)
if ('cpsr' in response): # TODO: Maybe just read until this anyways?
print("Found a match.\n")
cur_addr = int(response.strip().split()[3], 16)
countdown = 0
error = False
if error:
# try sending again?
telnet.write('step\n')
response = telnet.read_until('step\r\n', 1)
print('Step: %s ****' % (response))
# Skip line of output
response = telnet.read_until('\n', 1)
print('Step: %s ****' % (response))
# 2nd line has the pc, 4th column
response = telnet.read_until('\n', 1)
print("Failed to recover from error? Retried:", response)
cur_addr = int(response.strip().split()[3], 16) # This line should fail
response = telnet.read_until('>', 1) # skip remaining
return cur_addr
输出:
Data Lookups: 0xf8f02210: 000004c2
Data Read Hits: 0xf8f0220c: 000004c2
感谢您的时间,感谢您的帮助。