2009-10-04

【C語言】左移&右移巨集

恩...就左移與右移巨集函數

#include <stdio.h>

#define ROTATE_LEFT(NUM,BIT) ( \
(NUM<<BIT) | (NUM>>( (sizeof(unsigned)<<3)-BIT) ) \
)

#define ROTATE_RIGHT(NUM,BIT) ( \
(NUM>>BIT) | (NUM<<( (sizeof(unsigned)<<3)-BIT) ) \
)

int main() {
unsigned int x = 0xff000000 ;
printf("0x%8X\t0x%08X\n", x, ROTATE_RIGHT(x,4)) ;
printf("0x%8X\t0x%08X\n", x, ROTATE_LEFT(x,4)) ;
system("pause") ;
return 0 ;
}

2009-07-25

Simplescalar/ARM模擬器安裝與測試

裝這模擬器純粹是老闆要我安裝給他跑而已...
本人對這模擬器沒說很瞭
有任何問題請留言討論,但別期待能幫上什麼忙...

  1. 下載Simplescalar/ARM
    網址: http://www.simplescalar.com/v4test.html
    直接下載網址: http://www.eecs.umich.edu/~taustin/code/arm/simplesim-arm-0.2.tar.gz
  2. 下載Mibench ARM
    網址: http://www.eecs.umich.edu/mibench/
    直接下載網址: http://www.eecs.umich.edu/%7Ejringenb/mibench/mibench_arm_binaries.tar.gz
  3. 解壓縮simplesim-arm-0.2.tar.gz
    $ tar zxvf simplesim-arm-0.2.tar.gz
  4. 進入解壓縮後的目錄
    $ cd simplesim-arm

    PS. 官網上的安裝使用說明文件: http://www.eecs.umich.edu/~taustin/code/arm/ANNOUNCE.ARM

  5. 照上面的說明文件只要兩步驟,一個是設定環境、另一個是make
    $ make config-arm
    $ make
  6. 沒意外的話應該會發生點錯誤,不然也不用寫這篇文章了...
    在最後面應該會看到提示字元 => make: *** [sim-safe.o] Error 1
    往前捲動一下會看到真正錯誤的來源 => machine.h:349: 錯誤: 陣列元素的類型不完全
    其他的錯誤都只是一些副效應 => machine.h:349: 錯誤: 陣列元素的類型不完全
    觀察一下349行附近的敘述
    $ gedit machine.h &
    發現敘述內容為 => extern enum md_opcode md_mask2op[];
    往下面幾行會看到上面用到的列舉型別md_opcode,宣告在354-363行間,敘述如下
    /* global opcode names, these are returned by the decoder (MD_OP_ENUM()) */
    enum md_opcode {
    OP_NA = 0, /* NA */
    #define DEFINST(OP,MSK,NAME,OPFORM,RES,FLAGS,O1,O2,O3,I1,I2,I3,I4) OP,
    #define DEFUOP(OP,NAME,OPFORM,RES,FLAGS,O1,O2,O3,I1,I2,I3,I4) OP,
    #define DEFLINK(OP,MSK,NAME,MASK,SHIFT) OP,
    #define CONNECT(OP)
    #include "machine.def"
    OP_MAX /* number of opcodes + NA */
    };
    把354-363敘述搬到列舉宣告前就可以了,修改完後存檔在重新make一次。
    $ make
  7. 過一會肯定又是眉頭一皺,事情果然並不單純...出現以下錯誤
    /usr/bin/ld: errno: TLS definition in /lib/libc.so.6 section .tbss mismatches non-TLS reference in eval.o
    /lib/libc.so.6: could not read symbols: Bad value
    collect2: ld 回傳 1
    make: *** [sim-safe] Error 1

    查看eval.c檔案
    $ gedit eval.c &
    發現83-85行的敘述
    #if defined(__CYGWIN32__)
    #include
    #endif
    但仔細查看Makefile或其他*.h檔案中都沒定義這巨集變數__CYGWIN32__,自然errno.h會被忽略,但程式碼中用到錯誤常數需要此標頭檔定義,所以把83跟85刪掉即可。
    再重新編譯
    $ make
  8. 肯定想飆髒話了,出現以下錯誤
    /usr/bin/ld: errno: TLS definition in /lib/libc.so.6 section .tbss mismatches non-TLS reference in range.o
    /lib/libc.so.6: could not read symbols: Bad value
    collect2: ld 回傳 1
    make: *** [sim-safe] Error 1

    此時請查看range.c檔案
    $ gedit range.c &
    找到81-83行的敘述,跟前一個eval.c的問題一樣,把兩行假指令刪掉即可
  9. 在重新編譯
    $ make
    這次可跑比較久了,心中肯定暗爽結束了結束了,就快要編好了,結果伸個懶腰回神一看,下面訊息...
    make: *** [sim-outorder.o] Error 1
    心中肯定充滿無限#@^%&(*&^%#
    想捶牆壁又怕手會痛,實在很無力...
  10. 其實就剩下gcc版本問題了
    查看一下自身gcc版本會發現是4.X
    $ gcc -v
    裝一個3.X版的gcc就可以了
    $ sudo apt-get install gcc-3.4
    如果上述指令安裝失敗請先安裝
    $ sudo apt-get install gcc-3.4-base
  11. 安裝完畢後修改Makefile,設定CC使用gcc-3.4即可
    $ gedit Makefile &
    應該在177行敘述為CC = gcc
    改成CC = gcc-3.4即可
    這次應該就OK了,下make去編譯吧
    $ make
  12. 編完後測試一下,先回到上層目錄
    $ cd ..
    解壓縮mibench_arm_binaries.tar.gz檔案
    $ tar zxvf mibench_arm_binaries.tar.gz
  13. 先把剛剛編譯完的模擬器(這裡示範用sim-outorder,每個模擬器之間的不同請參考官網上的說明)複製到mibench目錄下
    $ cp simplesim-arm/sim-outorder mibench_arm_binaries
  14. 進到mibench的目錄下進行模擬測試
    $ cd mibench_arm_binaries/
    $ ./sim-outorder bitcount/bitcnts.arm 150000
  15. 應該會看到類似下面訊息
    sim: ** simulation statistics **
    sim_num_insn 99409825 # total number of instructions committed
    sim_num_uops 149104246 # total number of UOPs executed
    sim_avg_flowlen 1.4999 # uops per instruction
    sim_num_refs 24470769 # total number of loads and stores committed
    sim_num_loads 14563043 # total number of loads committed
    sim_num_stores 9907726.0000 # total number of stores committed
    這些就是模擬的數據結果,再依據所需觀察各個數值吧

2009-06-20

尋找格蘭菲迪

在ptt上看到網友推薦的活動,好奇心驅使之下就給他參加了
外盒包裝,格蘭菲迪商標很清楚的印在上面!推開外包裝,裡面是一個很有質感的黑色盒子
打開盒子,上面紙張背面印有活動的序號
恩...內包裝的樣子
真是超迷你的迷你酒瓶
品酒準備~贈送的迷你酒+贈送的酒杯+自己準備的冰水
第一步,色澤的觀察
恩...中間品酒步驟跳過
這樣的行銷很棒,有免費的酒可以品嘗還贈送酒杯真是太有心了
巧的是格蘭菲迪12年是我人生購買的第一支威士忌
跟這山羊牌威士忌還真是有緣份
接下來就等15年的品酪禮盒寄來了
最後是18年...雖然送的迷你酒容量只有50ml
品酒而已嘛~這樣很夠了

PS. 品茗酒香,基本上分為三個步驟
首先,距離瓶口不用太近,先讓鼻子熟悉酒精的刺激
接著兩步驟才是真正去感受威士忌釀造時所帶入的花果香味

2008-09-03

【LP】程式讀取參數列

  在Linux下寫程式要讀取參數列的參數(值),最直覺的作法莫過於直接使用main()中的argc與argv變數,不過要自己在程式中處理參數列並且想要提供使用者靈活的參數組合,恐怕會是一個叫人頭痛的"超級任務"。
  以ls程式為例,其參數項目就已經玲瑯滿目(如:-l、-a...等),參數項豐富頂多就是在程式中的switch...case敘述多寫一點,但是再加上沒有參數值的參數項可以合併在一個破折號後面(如:-la),這就很麻煩了。
  在Linux下可使用getopt()函數來幫我們處理參數列的問題,其prototype如下:

int getopt(int argc, char *argv[], const char * optstring) ;
extern char *optarg ;
extern int optind, opterr, optopt ;
  使用上很簡單,getopt函數前兩個參數就將main函數宣告的參數項(argc與argv)填入就是了,重點在於optstring,直接用例子來說明:
#include <stdio.h>
#include
<unistd.h>

int main(int argc, char *argv[]) {
int opt ;


while( (opt=getopt(argc, argv, "x:yz")) != -1 ) {
switch(opt) {
case 'x':
printf("option: %c argument: %s\n", opt, optarg) ;
break ;
case 'y':
case 'z':
printf("option: %c\n", opt) ;
break ;
case '?':
printf("unknow option\n") ;
}
}


return 0 ;
}
  將此範例存檔為lab_arg.c並編譯成lab_arg:gcc -o lab_arg lab_arg.c
  此程式可接受參數x、y、z,並且參數x其後會接著一個參數值,可以先執行看看其效果。在optstring部分範例中用了"x:yz",其表示此程式接受參數有x、y、z,而在x後面加一個冒號(:)說明x參數將會帶一個參數值。
  getopt會依序解析使用者傳入的參數項,若符合optstring規則的參數會回傳對應的參數字元,當getopt函數解析完餐數個數後,會傳回-1表示結束,因此使用一個while迴圈將之包附並檢查傳回值是否為-1。
  使用getopt()我們僅需關注程式中對於各個參數項的對應行為即可,而不需費盡心思自己在程式中解析複雜的參數組合可能。
  更詳細的getopt()函數說明請參閱:http://fair.athost.net/main/linux_c/function/16.html#linuxc293

2008-08-26

建立Toolchain

  當我們在編譯某些Library或是open source的程式時,會遇到target board廠商所提供的toolchain版本過舊/新而產生版本差異引發的錯誤,此時可以藉由自己建構特定版本的toolchain來解決此類的問題。
  那究竟如何建構自己的toolchain呢?其實也不難,跟在一般的PC上建構編譯環境是一樣的,只是我們是要跨平台的編譯環境而已,因此不外乎就是安裝binutils、gcc、glibc和header這些編譯需要的元件。
  如果覺得很陌生也無所謂,網路上已經有高手寫好自動安裝編譯的script了,我們只需要取得該script檔案並且選擇想要的gcc版本跟glibc版本之後,就可以讓電腦自動完成安裝,接下來我們所需要做的事就是好好品味一下咖啡的香!

  1. 下載crosstool的build script
    開啟http://kegel.com/crosstool/連結,進入download頁面下載crosstool-0.43.tar.gz,記得一定要選擇0.43版本,0.42版在gcc版本驗證的正規表示式限制住只能安裝3.x版本。
  2. 將檔案解壓縮並進入該目錄
    # tar zxvf crosstool-0.43.tar.gz
    # cd crosstool-0.43
  3. 然後依據target的機器選擇script檔,在此選擇demo-arm.sh:
    1 TARBALLS_DIR=$HOME/downloads
    2 RESULT_TOP=/opt/crosstool
    3 export TARBALLS_DIR RESULT_TOP
    4 GCC_LANGUAGES="c,c++"
    ……
    5 eval `cat arm.dat gcc-4.1.0-glibc-2.3.2-tls.dat` sh all.sh --notest
    1 安裝過程中會下載需要的tarball檔,選擇暫存這些檔案的目錄,預設為家目錄下的downloads。
    2 選擇toolchain的安裝根目錄,預設會裝在/opt/crosstool目錄下。
    3 只是把剛剛定義定變數暫時丟給環境變數,方便其他shell取用而已。
    4 這裡可以把需要的編譯語言加進去,比如java等。
    5 你會在這個script檔中看到很多行類似的敘述,這就依需要的版本做選擇就可以了,前面有加井號(#)的表是不採用,沒有加井號的就是我們選擇的版本,因此千萬記住只能有一行是沒有加井號!
  4. 接著建立安裝目錄,並且更改目錄的擁有者為目前登入的帳號:
    # sudo mkdir /opt/crosstool
    # sudo chown $USER /opt/crosstool
  5. 上述基本動作都做完後,下最後一道指令就可以去喝咖啡了!
    # sh demo-arm.sh
  6. 咖啡喝完回來發現:什麼還在跑!sorry剛剛忘了說要多吃一塊pizza,出去再回來後應該就差不多啦,當你看到DONE.提示字串,那就恭喜老爺賀喜老爺:是個活跳跳的toolchain。現在可以透過命令:
    #/opt/crosstool/gcc-4.1.0-glibc-2.3.2/arm-unknown-linux-gnu/bin/arm-unknown-linux-gnu-gcc
  7. 用這樣一長串命令來進行編譯了,每次編譯都打這一長串,只要是人一定會受不了的,因此我們將此路徑加入預設路徑(建議就把這路徑寫入~/bashrc這樣就不用每次登入都要設定路徑):
    # export PATH=$PATH: /opt/crosstool/gcc-4.1.0-glibc-2.3.2/arm-unknown-linux-gnu/bin/arm-unknown-linux-gnu-gcc
【關鍵字:toolchain、cross compiler、ARM、跨平台編譯器】