步进代码

时间:2018-03-28 13:55:16

标签: performance caching arm

我正在使用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

感谢您的时间,感谢您的帮助。

0 个答案:

没有答案