2017ZYNQ加速編譯
A. zynq linux 移植過程中編譯u-boot出現問題
明顯是提示沒有庫文件吧。 libmpfr.so.1: cannot open shared object file: No such file or directory
B. linux編譯u-boot時顯示[arch/arm/dts/zynq-zc702.dtb]錯誤
在編譯uboot的時候,會出現出錯,因此我們要首先做 make disclean. 將原來的一些中間文件清理干凈。
因此在編譯Uboot依次執行 1.make disclean
2.make smdk2440_config
3. make
就可以編譯通過了
C. zynq7000術語詳解,不懂啥是pl,ps,apu,scu
摘要:本文介紹與XILINX的EPP平台成員, ZYNQ晶元相關的縮寫術語和含義. 與簡單翻譯術語不同,本文對每個縮寫在本行業其他公司的展開含義也略作介紹, 避免混淆. 對術語的技術功能也作簡單介紹.
8月份學校放暑假, 大學計劃這邊緊急的事不多, 因此通常是俺的充電和學習時間.
本月的學習任務嘛, 當然是ZYNQ. 資料不多,一個是今年3月份出來的UG804, 是一個簡介性質的東東, 24頁, 另一個是UG585, 技術手冊,目前有1804頁. 目前都還是保密的, 合作夥伴需要簽NDA才能看到.
去年ZYNQ剛出來的時候,文檔還沒有,俺只有對著僅有的一個框圖,對其中的縮寫瞎猜了一番. 當時還寫了博客. 信馬由韁-XILINX的ARM晶元初探(之一). 看到UG804,終於有機會驗證俺當時猜的縮寫展開到底對不對.
看了之後才發現, 框圖中那點看不懂的縮寫, 比起UG804中引入的各種縮寫, 簡直是小巫見大巫. 為了給你一個概念, 假設你3年後碰到一個用過ZYNQ的工程師, 和你說了下面一句話, 你能聽懂多少:
經理啊, 我的PS啟動了,可是PL還沒載入, 這時,APU復位檢查了沒問題, MIO連得好好的, EMIO看上去也工作正常,你說我該查GIC呢, 還是AFI呢 ?
坑爹啊!比火星文還火星文的話聽了傷不起啊~~~.下面,開始逐個解釋新出現的,或者冷僻的縮寫,繼續看文檔時看見了,才能反映上來是啥意思.
假設你3年後碰到一個用過ZYNQ的工程師, 和你說了下面一句話, 你能聽懂多少:
經理啊, 我的PS啟動了,可是PL還沒載入, 這時,APU復位檢查了沒問題, MIO連得好好的, EMIO看上去也工作正常,你說我該查GIC呢, 還是AFI呢 ?
PS: 處理系統 (Processing System) , 就是與FPGA無關的ARM的SOC的部分。
PL: 可編程邏輯 (Progarmmable Logic), 就是FPGA部分。 之所以叫PL,而不是叫FPGA,我想,原因主要是考慮到讓搞軟體的兔子們不要看了以後望而生畏。 邏輯嘛,搞軟體的也要講邏輯是不?可編程,軟體就是編程是不?
ZYNQ,往大里說,就是兩大功能塊,PS 部分和 PL部分, 說白了,就是ARM的SOC部分,和FPGA部分。
下一個層級, APU部分:
APU: 應用處理器單元(Application Processor Unit). 位於PS裡面的中心位置。 這個名字起的,就有點學問了。
APU這三個字,AMD公司曾經用過,特指全稱是「Accelerated Processing Units」,加速處理器,它是融聚了CPU與GPU功能的產品,電腦上兩個最重要的處理器融合,相互補足,發揮最大性能。XILINX 的APU與AMD的APU在縮寫上就是截然不同的兩個詞, 不能混淆了。
APU 這個詞,在Xilinx內部的術語中,也是撞車了的。 在XILINX 的 PowerPC體系中, 有一個輔助處理單元「Auxiliary Processing Unit」 的概念,指的是在PowerPC硬核外掛的浮點協處理器之類的單元。
在這個位置上的處理器, 還有各種其他的叫法, 有MCU (微控制器處理單元Microcontroller Unit), MPU (微處理器單元Microprocessor Unit),等等。 MCU這個叫法,暗示了處理器功能不強,只能搞搞輸入輸出控制啊,寫個小狀態機啊, 一般都是8位機。 MPU呢,就更先進了一些,成prcessor了,這意味著處理器通常是32位的, 能幹點計算的事。 但是, 有一個micro詞根在裡面, 說明乾的是小活, 通常沒有正式的和全尺寸的操作系統, 通常沒有內存管理單元MMU。 ARM 的Cortex-M系列是干這類活的。
APU, 帶了Application這個詞, 意味著在上面可以跑應用程序, 暗示著這個系統是需要全尺寸的操作系統的, 和現在炙手可熱的應用商店app store 遙相呼應。
APU裡面具體包含的內容嘛,就是雙ARM-CortexA9核,加上高速緩沖,DMA,定時器,中斷控制,浮點和NEON協處理,硬體加速器一致性控制器ACP神馬的。 也就是,處理器核心部分。
套用時下越來越流行的詞彙,「嵌入式計算」, "embedded computing", 可以這么說, 用MCU,MPU搭出來的東東,通常叫嵌入式系統。 而APU搭出來的東東, 就夠格叫嵌入式計算系統了。
TTC, 這個詞,當年猜了半天也拿不準,看了文檔,發現,是Triple Time Counter的意思。 就是這個計數器裡面有3個獨立通道, 可以獨立計數。 掛在APB上,為系統或外設提供定時或計數服務的。
WDT, 看門狗定時器,有兩個, 分別監視ARM-Cortex A9用的。 如果軟體跑飛,無法清定時器,一段時間後,看門狗就復位。
SWDT,系統級看門狗定時器, 這個看門狗的時鍾和復位信號,都可以來自於晶元外部, 這樣,即使系統有嚴重故障,比如時鍾頻率本身都有問題了, 仍然可以通過與系統無關的外部信號計數,計數滿就復位。
SCU, Snoop Control Unit, 用來保持雙核之間的數據Cache的一致性。 也就是是說,第一個A9
處理器寫存儲時,只是寫在了緩存里,沒有進主存, 如果第二個A9讀操作,涉及到第一個寫臟了的數據段, SCU要保證第二個A9的緩存里是最新的數據。 如果第二個A9寫同樣數據段的數據,需要在第一個中體現出寫的內容。 SCU的存在,才使得兩個核成互相聯系的「雙核」,才能成為MPsoc。 在原先XILINX的雙PowerPC的晶元中, 是木有這個東東的。 不少學校的老師拿XILINX的雙powerpc練手和教學,從頭搭一個Snoop協議在裸的雙PowerPC中,倒也不錯。
D. 如何在VIVADO中編譯模擬庫
1、選擇vivado菜單「Tools」——>「Compile Simulation Libraries...」命令。
2、在彈出的對話框中設置器件庫編譯參數,模擬工具「Simulator」選為ModelSim,語言「Language」、庫「Library」、器件家族「Family」都為默認設置All(當然也可以根據自己的需求進行設置),然後在「Compiled library location」欄設置編譯器件庫的存放路徑,這里選擇新建的vivado2014_lib文件夾,此外在「Simulator executable path」欄設置Modelsim執行文件的路徑,其他參數默認。
3、設置好參數後點擊「Compile」按鈕開始器件庫的編譯。
4、器件庫編譯結束後給出編譯報告,從報告中看出0個警告和0個錯誤。
5、打開vivado2014_lib文件夾,便可以看到已經產生了器件庫。
E. 沒硬體怎麼玩zynq7000
官網提供的可執行文件是基於64位Linux的:zynq_linux.tar.gz.
對於32位的系統,需要自己編譯,解決方案如下:
1) 下載代碼:git clone git://git.xilinx.com/qemu-xarm.git
2) 配置工程:
cd qemu-xarm
./configure --target-list=arm-softmmu --disable-werror --disable-kvm
3) 編譯: make
4) 編譯結果:
[walt@zynq7k qemu-xarm]$ ls -l arm-softmmu/qemu-system-arm
-rwxrwxr-x. 1 walt walt 18428427 Nov 6 15:27 arm-softmmu/qemu-system-arm
5) 檢測環境是否OK,測試如下:
[walt@zynq7k qemu-xarm]$ ./arm-softmmu/qemu-system-arm -h
QEMU emulator version 1.0.50, Copyright (c) 2003-2008 Fabrice Bellard
usage: qemu-system-arm [options] [disk_image]
『disk_image』 is a raw hard disk image for IDE hard disk 0
Standard options:
-h or -help display this help and exit
-version display version information and exit
-machine [type=]name[,prop[=value][,...]]
selects emulated machine (-machine ? for list)
property accel=accel1[:accel2[:...]] selects accelerator
supported accelerators are kvm, xen, tcg (default: tcg)
-cpu cpu select CPU (-cpu ? for list)
…… ……
註: 若無法執行,請按http://wiki.xilinx.com/zynq-qemu提示安裝缺失的動態庫。
替換官方下載的壓縮包中的文件為新編譯的qemu-system-arm,測試執行如下:
[walt@zynq7k zynq_linux]# ./start_qemu.sh
ram size=40000000
error reading QSPI block device
error no mtd drive for nand flash
a0mpcore_priv: smp_priv_base f8f00000
error no sd drive for sdhci controller (0)
error no sd drive for sdhci controller (1)
Number of configured NICs 0×1
ram_size 40000000, board_id d32, loader_start 0
Uncompressing Linux… done, booting the kernel.
Booting Linux on physical CPU 0
Linux version 3.3.0-14.2-build1 (relman@xcobldal824) (gcc version 4.6.1 (Sourcery CodeBench Lite 2011.09-50) ) #1 SMP PREEMPT Thu Jul 12 09:04:32 MDT 2012
CPU: ARMv7 Processor [410fc090] revision 0 (ARMv7), cr=10c5387d
CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
Machine: Xilinx Zynq Platform, model: Xilinx Zynq ZC702
bootconsole [earlycon0] enabled
Memory policy: ECC disabled, Data cache writealloc
PERCPU: Embedded 7 pages/cpu @c190b000 s5696 r8192 d14784 u32768
Built 1 zonelists in Zone order, mobility grouping on. Total pages: 255744
Kernel command line: console=ttyPS0,115200 root=/dev/ram rw initrd=0×800000,8M ip=:::::eth0:dhcp earlyprintk
PID hash table entries: 4096 (order: 2, 16384 bytes)
Dentry cache hash table entries: 131072 (order: 7, 524288 bytes)
Inode-cache hash table entries: 65536 (order: 6, 262144 bytes)
Memory: 240MB 768MB = 1008MB total
Memory: 1009280k/1009280k available, 39296k reserved, 270336K highmem
Virtual kernel memory layout:
vector : 0xffff0000 – 0xffff1000 ( 4 kB)
fixmap : 0xfff00000 – 0xfffe0000 ( 896 kB)
vmalloc : 0xf0000000 – 0xff000000 ( 240 MB)
lowmem : 0xc0000000 – 0xef800000 ( 760 MB)
pkmap : 0xbfe00000 – 0xc0000000 ( 2 MB)
moles : 0xbf000000 – 0xbfe00000 ( 14 MB)
.text : 0xc0008000 – 0xc040bdb0 (4112 kB)
.init : 0xc040c000 – 0xc0430640 ( 146 kB)
.data : 0xc0432000 – 0xc045fd20 ( 184 kB)
.bss : 0xc045fd44 – 0xc0479f5c ( 105 kB)
Preemptible hierarchical RCU implementation.
Verbose stalled-CPUs detection is disabled.
NR_IRQS:128
xlnx,ps7-ttc-1.00.a #0 at 0xf0000000, irq=43
Console: colour mmy device 80×30
Calibrating delay loop… 147.35 BogoMIPS (lpj=736768)
pid_max: default: 32768 minimum: 301
Mount-cache hash table entries: 512
CPU: Testing write buffer coherency: ok
CPU0: thread -1, cpu 0, socket 0, mpidr 80000000
smp_twd: clock not found: -2
Calibrating local timer… 84.48MHz.
hw perfevents: enabled with ARMv7 Cortex-A9 PMU driver, 1 counters available
Setting up static identity map for 0x2f3000 – 0x2f3034
CPU1: Booted secondary processor
CPU1: thread -1, cpu 1, socket 0, mpidr 80000001
Brought up 2 CPUs
SMP: Total of 2 processors activated (271.66 BogoMIPS).
devtmpfs: initialized
NET: Registered protocol family 16
L2x0 series cache controller enabled
l2x0: 8 ways, CACHE_ID 0×00000000, AUX_CTRL 0×72060000, Cache size: 524288 B
registering platform device 『pl330′ id 0
registering platform device 『arm-pmu』 id 0
hw-breakpoint: debug architecture 0×0 unsupported.
xslcr xslcr.0: at 0xF8000000 mapped to 0xF0008000
bio: create slab at 0
gpiochip_add: registered GPIOs 0 to 245 on device: xgpiops
xgpiops e000a000.gpio: gpio at 0xe000a000 mapped to 0xf000a000
SCSI subsystem initialized
usbcore: registered new interface driver usbfs
usbcore: registered new interface driver hub
usbcore: registered new device driver usb
Switching to clocksource xttcpss_timer1
NET: Registered protocol family 2
IP route cache hash table entries: 32768 (order: 5, 131072 bytes)
TCP established hash table entries: 131072 (order: 8, 1048576 bytes)
TCP bind hash table entries: 65536 (order: 7, 786432 bytes)
TCP: Hash tables configured (established 131072 bind 65536)
TCP reno registered
UDP hash table entries: 512 (order: 2, 16384 bytes)
UDP-Lite hash table entries: 512 (order: 2, 16384 bytes)
NET: Registered protocol family 1
RPC: Registered named UNIX socket transport mole.
RPC: Registered udp transport mole.
RPC: Registered tcp transport mole.
RPC: Registered tcp NFSv4.1 backchannel transport mole.
Trying to unpack rootfs image as initramfs…
rootfs image is not initramfs (junk in compressed archive); looks like an initrd
Freeing initrd memory: 8192K
xscugtimer xscugtimer.0: ioremap fe00c200 to f000c200 with size 400
pl330 dev 0 probe success
highmem bounce pool size: 64 pages
JFFS2 version 2.2. (NAND) (SUMMARY) © 2001-2006 Red Hat, Inc.
msgmni has been set to 1459
io scheler noop registered
io scheler deadline registered
io scheler cfq registered (default)
e0001000.uart: ttyPS0 at MMIO 0xe0001000 (irq = 82) is a xuartps
console [ttyPS0] enabled, bootconsole disabled
console [ttyPS0] enabled, bootconsole disabled
e0000000.uart: ttyPS1 at MMIO 0xe0000000 (irq = 59) is a xuartps
xdevcfg f8007000.devcfg: ioremap f8007000 to f0060000 with size 100
brd: mole loaded
loop: mole loaded
GEM: BASEADDRESS hw: e000b000 virt: f0062000
XEMACPS mii bus: probed
xemacps e000b000.eth: invalid address, use assigned
MAC updated d2:c4:43:31:6b:d0
eth0, pdev->id -1, baseaddr 0xe000b000, irq 54
ehci_hcd: USB 2.0 『Enhanced』 Host Controller (EHCI) Driver
xusbps-ehci xusbps-ehci.0: Xilinx PS USB EHCI Host Controller
xusbps-ehci xusbps-ehci.0: new USB bus registered, assigned bus number 1
xusbps-ehci xusbps-ehci.0: irq 53, io mem 0×00000000
xusbps-ehci xusbps-ehci.0: USB 2.0 started, EHCI 0.00
hub 1-0:1.0: USB hub found
hub 1-0:1.0: 0 ports detected
Initializing USB Mass Storage driver…
usbcore: registered new interface driver usb-storage
USB Mass Storage support registered.
Xilinx PS USB Device Controller driver (Apr 01, 2011)
mousedev: PS/2 mouse device common for all mice
i2c /dev entries driver
Linux video capture interface: v2.00
gspca_main: v2.14.0 registered
uvcvideo: Unable to create debugfs directory
usbcore: registered new interface driver uvcvideo
USB Video Class driver (1.1.1)
WDT OF probe
xwdtps f8005000.swdt: Xilinx Watchdog Timer at 0xf0066000 with timeout 10 seconds
sdhci: Secure Digital Host Controller Interface driver
sdhci: Copyright(c) Pierre Ossman
sdhci-pltfm: SDHCI platform and OF driver helper
mmc0: SDHCI controller on e0100000.sdhci [e0100000.sdhci] using ADMA
usbcore: registered new interface driver usbhid
usbhid: USB HID core driver
TCP cubic registered
NET: Registered protocol family 17
VFP support v0.3: implementor 41 architecture 3 part 40 variant 0 rev 0
Registering SWP/SWPB emulation handler
drivers/rtc/hctosys.c: unable to open rtc device (rtc0)
GEM: lp->tx_bd ffdfb000 lp->tx_bd_dma 2f2b2000 lp->tx_skb ee9199c0
GEM: lp->rx_bd ffdfc000 lp->rx_bd_dma 2f2b1000 lp->rx_skb ee9198c0
GEM: MAC 0x3143c4d2, 0x0000d06b, d2:c4:43:31:6b:d0
GEM: phydev ee90ec00, phydev->phy_id 0x1410cc2, phydev->addr 0×17
eth0, phy_addr 0×17, phy_id 0x01410cc2
eth0, attach [Marvell 88E1111] phy driver
Sending DHCP requests ., OK
IP-Config: Got DHCP answer from 10.0.2.2, my address is 10.0.2.15
IP-Config: Complete:
device=eth0, addr=10.0.2.15, mask=255.255.255.0, gw=10.0.2.2,
host=10.0.2.15, domain=, nis-domain=(none),
bootserver=10.0.2.2, rootserver=10.0.2.2, rootpath=
RAMDISK: ext2 filesystem found at block 0
RAMDISK: Loading 8192KiB [1 disk] into ram disk… done.
VFS: Mounted root (ext2 filesystem) on device 1:0.
devtmpfs: mounted
Freeing init memory: 144K
Starting rcS…
++ Mounting filesystem
++ Setting up mdev
eth0: link up (1000/FULL)
++ Starting telnet daemon
++ Starting http daemon
++ Starting ftp daemon
++ Starting dropbear (ssh) daemon
rcS Complete
zynq> uname -v
#1 SMP PREEMPT Thu Jul 12 09:04:32 MDT 2012
zynq> df
Filesystem 1K-blocks Used Available Use% Mounted on
none 508808 0 508808 0% /tmp
zynq>
F. 如何使用oprofile對軟體做profiling
關於Xilinx Zynq-7000帶來的新的系統設計思路,以及Profiling的對象libjpeg,前文已經描述過了,再此不再贅述。
一. Oprofile簡介
Profiling是對不同性能特徵的數據的形式化總結或分析,它通常以圖形和表的形式出現。它提供為特定的處理器事件收集的采樣百分數或數 量,比如cache miss rate、TLB miss rate等等。一般來說,主要目的是為了找出軟體中的性能瓶頸,然後有針對性的優化以提升軟體的整體性能。
Oprofile 是用於 Linux 的若干種評測和性能監控工具中的一種。它可以工作在不同的體系結構上,包括ARM, PowerPC, MIPS, IA32, IA64 和 AMD Athlon等等。它的開銷很小,從Linux 2.6 版起,它被包含進了Linux內核中。
Oprofile可以收集有關處理器事件的信息,幫助用戶識別諸如循環的展開、cache的使用率低、低效的類型轉換和冗餘操作、錯誤預測轉移 等問題。Oprofile是一種細粒度的工具,可以為指令集或者為函數、系統調用或中斷處理常式收集采樣。Oprofile 通過取樣來工作。使用收集到的評測數據,用戶可以很容易地找出性能問題。
通過監察CPU的hardware events,oprofile可以在運行狀態下對整個Linux系統進行profiling。Profiling的對象可以是Linux kernel (包括moles和interrupt handlers), shared libraries或者應用程序。
從0.9.8版本開始,oprofile支持Perf_events profiling mode模式。應用程序operf被用來控制profiling過程;而在legacy mode下,是通過opcontrol腳本和oprofiled daemon來完成的。Operf不再象legacy mode那樣需要OProfile kernel driver,它直接和Linux Kernel Performance Events Subsystem打交道。使用operf,就可以用普通用戶的身份來profiling用戶的應用程序了,當然如果需要對整個系統來profiling 的時候還是需要root許可權的。
如果硬體不支持OProfile使用performance counters,OProfile就只能工作在Timer Mode下了。Timer Mode只能在legacy profiling mode下使用,即只能通過opcontrol腳本來控制。
Oprofile的website為:http://oprofile.sourceforge.net/
可以支持的處理器的hardware event類型:http://oprofile.sourceforge.net/docs/
對於Zynq-7000來說,http://oprofile.sourceforge.net/docs/armv7-ca9- events.php 列出了ARM Cortex-A9內核PMU(Performance Monitor Unit)所支持的所有hardware event種類,可以看出oprofile可以支持很多深入處理器內部的分析。
http://oprofile.sourceforge.net/examples/ 提供了一些oprofile生成的結果,可以方便開發者在開始使用之前了解oprofile能夠做到哪些事情。
Oprofile的詳細使用文檔:http://oprofile.sourceforge.net/doc/index.html
Oprofile的優勢:
? 比較低的運行開銷
? 對被profiling的對象影響很小
? 可以profiling中斷服務程序(interrupt handlers)
? 可以profiling應用程序和shared libraries
? 可以profiling dynamically compiled (JIT) code
? 可以對整個系統做profiling
? 可以觀察CPU內部的細節,例如cache miss rate
? 可以多源代碼做annotation
? 可以支持instruction-level的profiling
? 可以生成call-graph profiles
不過OProfile也不是萬能的,它也有自己的局限性:
? 只能在x86, ARM, 和PowerPC架構上生成call graph profiles
? 不支持100%精確的instruction-level profiling
? 對dynamically compiled (JIT) code profiling的支持還不完善。
無論如何,Oprofile的功能都比gprof要強很多,代價是配置起來會比較麻煩。
二. 編譯Oprofile
首先最好在Linux kernel裡面選中Oprofile driver,以獲得全面的支持。
下載Linux kernel Source:從https://github.com/Xilinx/linux-xlnx 可以下載到Xilinx提供的驗證好的內核。如果不方便使用Linux下的git工具,可以單擊頁面上的releases找到相應的版本下載tar ball。下載的時候最好選tar.gz格式的,而不是zip格式的,因為後者在處理symbol link的時候有可能會出問題。
因為筆者使用的是Xilinx Linux pre-built 14.7,所以這里下載的是linux-xlnx-xilinx-v14.7.tar.gz
解壓縮後,用以下命令調出Linux kernel的配置界面:
export ARCH=arm
export CROSS_COMPILE=arm-xilinx-linux-gnueabi-
make xilinx_zynq_defconfig
make xconfig 或者make menuconfig
在配置界面上將以下兩項勾上:
General setup --->
[*] Profiling support
<*> OProfile system profiling
然後make uImage即可生成新的uImage,用來替換Xilinx Linux pre-built 14.7中的Linux kernel image。同時我們也需要vmlinux來檢查profiling的結果。
Oprofile需要popt, bfd, liberty庫,要在嵌入式單板上使用這些庫,需要手工完成交叉編譯。
針對popt 1.7,用以下命令完成編譯:
./configure --prefix=/home/wave/xilinx/oprofileprj/rootfs --host=arm-xilinx-linux-gnueabi --with-kernel-support --disable-nls && make && make install
針對binutils 2.24,用以下命令完成編譯:
./configure --host=arm-xilinx-linux-gnueabi --prefix=/home/wave/xilinx/oprofileprj/rootfs --enable-install-libbfd --enable-install-libiberty --enable-shared && make && make install
不過--enable-install-libiberty沒有效果,所以需要手工把libiberty.a和libiberty.h拷貝到相應的位置。
針對oprofile 0.9.9,用以下命令完成編譯:
./configure --host=arm-xilinx-linux-gnueabi --prefix=/home/wave/xilinx/oprofileprj/rootfs --with-kernel-support --with-binutils=/home/wave/xilinx/oprofileprj/rootfs && make && make install
配置過程結束後可能會有以下提示,因為沒有打算用GUI和profile JITed code,所以直接忽視之。
config.status: executing libtool commands
Warning: QT version 3 was requested but not found. No GUI will be built.
Warning: The user account 'oprofile:oprofile' does not exist on the system.
To profile JITed code, this special user account must exist.
Please ask your system administrator to add the following user and group:
user name : 'oprofile'
group name: 'oprofile'
The 'oprofile' group must be the default group for the 'oprofile' user.
將編譯完成的uImage,vmlinux,oprofile binary,重新編譯的沒有-pg的libjpeg binary以及tool chain的libc打包放到SD卡中,准備在ZC706開發板上嘗試profile djpeg。
三. 運行Oprofile
正常啟動嵌入式Linux後,在開發板的console上一次輸入以下命令:
mount /dev/mmcblk0p1 /mnt
mkdir -p /home/root/work
cd /home/root/work
tar zxvf /mnt/jpeg-bin-nopg.tar.gz
cd jpeg-bin/bin
cp /mnt/park-2880x1800.jpg .
export LD_LIBRARY_PATH=/home/root/work/jpeg-bin/lib
cd /home/root/work
tar zxvf /mnt/rootfs.tar.gz
cd rootfs
chown root:root -R *
cp -R bin/* /usr/bin
cp -R lib/* /lib
cp /bin/which /usr/bin
cp /bin/dirname /usr/bin
mkdir -p /home/wave/xilinx/oprofileprj/rootfs/share
cp -R ./rootfs/* /home/wave/xilinx/oprofileprj/rootfs
cd /home/root/work
tar zxvf /mnt/libc.tar.gz
cp ./lib/libstdc*.* /lib
mkdir -p /home/wave/xilinx/libjpeg
cd /home/wave/xilinx/libjpeg
tar zxvf /mnt/jpeg-9.tar.gz
cp /mnt/vmlinux /home/root/work
cd /home/root/work/jpeg-bin/bin
opcontrol --init
opcontrol --vmlinux=/home/root/work/vmlinux
opcontrol --setup --event=CPU_CYCLES:100000::0:1 --session-dir=/home/root/
operf --vmlinux /home/root/work/vmlinux ./djpeg -bmp park-2880x1800.jpg > result.bmp
opreport -l ./djpeg
完成這一步後,我們就可以看到profiling的結果了,在筆者的平台上看到的內容的主要部分如下:
root@zynq:~/work/jpeg-bin/bin# opreport -l ./djpeg
Using /home/root/work/jpeg-bin/bin/oprofile_data/samples/ for samples directory.
CPU: ARM Cortex-A9, speed 666667 MHz (estimated)
Counted CPU_CYCLES events (CPU cycle) with a unit mask of 0x00 (No unit mask) count 100000
samples % image name symbol name
15293 58.6253 libc-2.17.so /lib/libc-2.17.so
2044 7.8356 libjpeg.so.9.0.0 ycc_rgb_convert
1964 7.5289 libjpeg.so.9.0.0 jpeg_idct_16x16
1918 7.3526 libjpeg.so.9.0.0 decode_mcu
1570 6.0186 libjpeg.so.9.0.0 jpeg_idct_islow
1567 6.0071 djpeg finish_output_bmp
528 2.0241 libjpeg.so.9.0.0 jpeg_fill_bit_buffer
397 1.5219 djpeg put_pixel_rows
73 0.2798 vmlinux ___from_user
70 0.2683 libjpeg.so.9.0.0 decompress_onepass
65 0.2492 libjpeg.so.9.0.0 jpeg_huff_decode
56 0.2147 vmlinux get_page_from_freelist
50 0.1917 vmlinux __memzero
45 0.1725 vmlinux ___to_user_std
41 0.1572 vmlinux _raw_spin_unlock_irqrestore
15 0.0575 vmlinux do_page_fault
14 0.0537 vmlinux __generic_file_aio_write
13 0.0498 vmlinux _raw_spin_unlock_irq
11 0.0422 vmlinux free_hot_cold_page
11 0.0422 vmlinux vector_swi
10 0.0383 vmlinux handle_pte_fault
從結果中我們可以看到libjpeg.so.9.0.0, djpeg和vmlinux中的symbol name已經可以被正確的解析出來了,和gprof的結果基本一致。相比gprof,oprofile可以在更大的范圍內完成profiling。
我們還可以用以下命令觀察源代碼中特定行的執行時間,進一步縮小優化的范圍,達到事半功倍的效果。
opannotate --source ./djpeg > opannotate.txt
四. 小結
通過實驗,我們可以看到Oprofile可以提供更豐富的profiling結果,可以更好的幫助開發者找到瓶頸,通過有針對性的優化提升軟體 性能;profiling的結果也可以幫助開發者將性能瓶頸代碼通過Xilinx HLS工具用硬體加速器來實現,從而為進一步提升整個嵌入式系統的性能打開了大門。