ARM 시뮬레이터인 ARMSIM 의 소개와 사용법에 대해서 설명한다.
ARMSIM 은 서울대에서 이재진 교수님 연구실에서 만든 것으로서, arm 으로 컴파일된 프로그램(kernel 포함)을 x86 머신에서 실행할 수 있게 해준다.
여기서 사용하는 vpos 는 기존의 gcc-2.95.3 기반의 vpos 소스 라는 것을 기억하기 바란다.
준비운동 하기
redhat 9 을 기준으로 설명한다. armsim 을 컴파일하기 위해서는 pmake 가 필요하다. pmake-1.45-10.i386.rpm 를 설치한다.
그 외 필요한 파일들은 armsim_vpos.tar.gz 에서 다운받는다.
이 파일들은 내가 기존의 stong 서버에 있던 원본 파일을 나의 개발서버(redhat 9) 에 맞게 수정한 것이다.
압축을 풀면, 디렉토리 구조는 다음과 같다.
#tar xzf armsim_vpos.tar.gz #cd armsim_vpos #ls -al drwxr-xr-x 4 502 502 4096 Aug 10 23:14 armsim // ARMSIM 소스 파일 -rw-r--r-- 1 502 502 14482 Aug 4 23:08 armsim.config // ARMSIM 설정 파일 -rwxr-xr-x 1 root root 10279871 Aug 10 23:14 armsim_p // ARMSIM 실행파일 -rw-r--r-- 1 502 502 1310100 Aug 10 23:16 dis.txt // 메모리 dump 파일 drwxr-xr-x 2 502 502 4096 Aug 4 23:07 image // vpos 실행 이미지(elf) drwxr-xr-x 11 root root 4096 Aug 4 23:13 mpos_armsim // vpos 소스 파일
vpos 수정사항
앞에서 다운로드 받은 경우에는 따로 수정없이 사용하면 되지만, 기존의 vpos 에 경우, ARMSIM 상에서 실행하기 위해서는 수정이 필요하다.
ARMSIM 은 부트로더를 수행하지 않고, 바로 커널을 수행한다. 기존의 vpos 는 링커(ld) 에 의해서 0x30000000 로 엔트리포인트(entry point) 가 잡힌다. 하지만 ARMSIM 은 가장 먼저 수행되는 커널의 엔트리포인트(entry point) 가 0x0 로 잡혀야 정상적으로 동작한다.
그러므로 링커 스크립트(hal/cpu/vpos_kernel-ld-script)를 수정해야 한다.
... SECTIONS { . = 0x00000000; # 수정 . = ALIGN(4); ...
이 외에도, 세미 호스팅(uart 출력을 콘솔 출력으로 바꾸기 위한)과 관련한 부분을 수정해야 한다.
컴파일 및 실행
먼저 ARMSIM 을 컴파일한다.
#cd armsim #make clean; make #cd ..
에러없이 컴파일 되었다면, 상위 디렉토리에 'armsim_p' 파일이 생성된다.
이제 ARMSIM 에 사용할 VPOS 를 컴파일 한다.
#cd mpos_armsim #make clean; make
컴파일 후에 생성되는 이미지 파일은 자동으로 image 디렉토리로 복사된다. 후에 ARMSIM 에서는 image 디렉토리에 있는 vpos_kernel-elf32_master 파일을 로딩한다.
이제 ARMSIM 을 이용해서 vpos 를 실행해보자.
#./armsim_p +++++yyparse ===== core_freqency : TK_NUMBER +++++yyparse ===== core_type : ARM9E ... +++++yyparse ===== core_type_list : core_type +++++yyparse ===== core_type : ARM9E ... +++++yyparse ===== core_type : ARM9E ... +++++yyparse ===== core_type : ARM9E ... +++++yyparse ===== core_sepc : TK_CORE ... +++++yyparse ===== shared_bus_spec : BUS_SHARED ... +++++yyparse ===== mem_region_spec : SDRAM ... +++++yyparse ===== mem_region_spec_list : mem_region_spec +++++yyparse ===== ipb_spec : IPREFETCH_BUFFER ... +++++yyparse ===== mmu_spec : MMU ... +++++yyparse ===== iutlb_spec : IMICROTLB ... +++++yyparse ===== dutlb_spec : DMICROTLB ... +++++yyparse ===== tlb_spec : TLB ... +++++yyparse ===== icache_spec : ICACHE ... +++++yyparse ===== dcache_spec : DCACHE ... +++++yyparse ===== itcm_spec : ITCM ... +++++yyparse ===== dtcm_spec : DTCM ... +++++yyparse ===== mem_subsystem_spec : MEM_SUBSYSTEM { ... } +++++yyparse ===== mem_subsystem_list : mem_subsystem_list mem_subsystem +++++yyparse ===== local_bus_spec : BUS_LOCAL ... +++++yyparse ===== mem_region_spec : SDRAM ... +++++yyparse ===== mem_region_spec_list : mem_region_spec +++++yyparse ===== mem_local_spec : TK_MEMORY_LOCAL ... +++++yyparse ===== ipb_spec : IPREFETCH_BUFFER ... +++++yyparse ===== mmu_spec : MMU ... +++++yyparse ===== iutlb_spec : IMICROTLB ... +++++yyparse ===== dutlb_spec : DMICROTLB ... +++++yyparse ===== tlb_spec : TLB ... +++++yyparse ===== icache_spec : ICACHE ... +++++yyparse ===== dcache_spec : DCACHE ... +++++yyparse ===== itcm_spec : ITCM ... +++++yyparse ===== dtcm_spec : DTCM ... +++++yyparse ===== mem_subsystem_spec : MEM_SUBSYSTEM { ... } +++++yyparse ===== mem_subsystem_list : mem_subsystem_list mem_subsystem +++++yyparse ===== local_bus_spec : BUS_LOCAL ... +++++yyparse ===== mem_region_spec : SDRAM ... +++++yyparse ===== mem_region_spec_list : mem_region_spec +++++yyparse ===== mem_local_spec : TK_MEMORY_LOCAL ... +++++yyparse ===== ipb_spec : IPREFETCH_BUFFER ... +++++yyparse ===== mmu_spec : MMU ... +++++yyparse ===== iutlb_spec : IMICROTLB ... +++++yyparse ===== dutlb_spec : DMICROTLB ... +++++yyparse ===== tlb_spec : TLB ... +++++yyparse ===== icache_spec : ICACHE ... +++++yyparse ===== dcache_spec : DCACHE ... +++++yyparse ===== itcm_spec : ITCM ... +++++yyparse ===== dtcm_spec : DTCM ... +++++yyparse ===== mem_subsystem_spec : MEM_SUBSYSTEM { ... } +++++yyparse ===== mem_subsystem_list : mem_subsystem_list mem_subsystem +++++yyparse ===== mem_subsystem_spec : mem_subsystem_list +++++yyparse ===== trace : TK_TRACE: ... TK_FILE_NAME +++++yyparse ===== trace : TK_SPECIAL_TRACE: ... +++++yyparse ===== timer_spec : TK_TIMER: ... +++++yyparse ===== imagefiles : TK_IMAGEFILES: ... +++++yyparse ===== config : core_spec bus_spec mem_subsystem_spec ======================================================================= System Configuration ==================================================================== Number of Cores = 4 Core0: ARM926E, 200 MHz ---------------------------------------------------------- IPB = on, IuTLB = off, DuTLB = off, TLB = off, MMU = off ICache = on, DCache = off, ITCM = off, DTCM = off Core1: ARM926E, 200 MHz ---------------------------------------------------------- IPB = on, IuTLB = off, DuTLB = off, TLB = off, MMU = off ICache = on, DCache = off, ITCM = off, DTCM = off Core2: ARM926E, 200 MHz ---------------------------------------------------------- IPB = on, IuTLB = off, DuTLB = off, TLB = off, MMU = off ICache = on, DCache = off, ITCM = off, DTCM = off Core3: ARM926E, 200 MHz ---------------------------------------------------------- IPB = on, IuTLB = off, DuTLB = off, TLB = off, MMU = off ICache = on, DCache = off, ITCM = off, DTCM = off ==================================================================== Bus: AHB, 66 MHz (core/bus = 3) ==================================================================== IMAGE: ./image/vpos_kernel-elf32_master Loading ( ./image/vpos_kernel-elf32_master )with the entrypoint at [0x00000000]... p_vaddr: 0 p_paddr: 0 p_offset: 8000 p_filesz: 39bd4 p_memsz: 164694 IMAGE: ./image/vpos_kernel-elf32_slave1 Loading ( ./image/vpos_kernel-elf32_slave1 )with the entrypoint at [0x00000000]... p_vaddr: 0 p_paddr: 0 p_offset: 8000 p_filesz: 32c4c p_memsz: 15d5d4 IMAGE: ./image/vpos_kernel-elf32_slave2 Loading ( ./image/vpos_kernel-elf32_slave2 )with the entrypoint at [0x00000000]... p_vaddr: 0 p_paddr: 0 p_offset: 8000 p_filesz: 32c4c p_memsz: 15d5d4 IMAGE: Image Loading Completed (snack-armsim>> g # 명령어 입력(go 를 입력해도 됨) ********************************************************************************* * MPOS version 1.0 xx/12/2006 * * Developed by Minyeol Seo, Jichan Maeng, Haseok Kim, Junhee Lee * * Released by Real-Time Computing and Communications Lab., Hanyang University * * http://rtcc.hanyang.ac.kr (myseo@rtcc.hanyang.ac.kr) * ********************************************************************************* VPSH> ls # 명령어 입력 *******************Command_List******************* - help - ls - msg_Q_example - cond_example - barrier_example - pthread_create_example - pthread_join_example - semaphore_example - mutex_example - no_mutex_example - stub_mutex - device_driver_example - mem_test <start_addr> <size> <flag> - mem_read <start_addr> <size> - mem_write <start_addr> <value> <size> <b|w> - comm_api - divx ************************************************** VPSH>
마치 vpos 를 타겟보드에서 돌리는 것과 같은 실행결과를 보여준다.
지금까지 실행방법에 대해서 설명했다. 이제는 설정 파일들에 대해서 설명하겠다.
armsim.config
ARMSIM 이 실행할 때, 자동으로 읽어들이는 파일이다.
여러가지 설정을 바꿀 수 있는데, 중요한 것들만 설명하겠다.
... IMAGEFILES: { ./image/vpos_kernel-elf32_master, ./image/vpos_kernel-elf32_slave1, ./image/vpos_kernel-elf32_slave2 } ...
시뮬레이터를 실행할 이미지 파일을 지정하는 부분이다. 총 3 개의 이미지 파일을 읽어들인다.
문제점
테스트를 하면서 발견된 문제점들을 정리했다. 시뮬레이터이기 때문에, 아무래도 타겟보드 상에서 실행하는 것에 비해 제한이 많다.
exception handler 를 수행할 수 없음
타겟보드에서는 발생해야할 exception 이 발생하지 않았다. 발생하더라도, ARMSIM 자체에서 core dump 를 출력하면서 죽어버리기 때문에, exception handler 를 실행할 수 없다.
time 에 대해 critical 하지 못함
ARMSIM 은 코드가 수행되는 상태에서만 타이머 인터럽트를 발생시킨다. 코드 수행과 상관없이 주기적으로 타이머 인터럽트가 발생하는 타겟보드 환경과 비교하자면, 큰 차이점이다. 그래서 만일 getc() 를 사용해서 사용자의 명령어 입력을 기다리는 시점에서는 타이머 인터럽트가 발생하지 않는다.
이러한 점 때문에, 실제로 세미포어와 뮤텍스, cond_example 에서 printf 문이나, NULL 루프(아무 일도 하지 않는 루프) 의 추가나 삭제에 따라서 결과값이 달라지는 현상이 나타났다.
그 외 설명할 없는 문제
같은 프로그램을 수행하는 데, 처음에는 제대로 동작을 하다가도, 두번째, 세번째에 가면 이상한 결과를 출력하거나, 전혀 엉뚱한 값을 출력하는 문제가 발생했다. 또한 vpos 소스파일의 이름을 수정에 따라서, 제대로 동작하거나 그렇지 않은 문제가 발생했다.
결론
지금 현재로서는 ARMSIM 을 100 % 신뢰할 수 있는 상태가 아니기 때문에, 문제가 발생했을 때 vpos 가 원인인지 ARMSIM 이 원인인지 명확히 알아내기가 쉽지않다. 또한 ARMSIM 에서 수행되는 코드의 출력 결과와 실제 타겟보드에서 수행되는 코드의 결과가 일치하지 않는다.
하지만, 간단한 예제들을 테스트하는 경우에는 문제없이 동작했다.
추가 되어야 할 것들
ARMSIM 에 대한 분석을 통해서, 앞에서 언급된 문제점들을 차후에 해결해야 할 것이다.