# C6Run

_C6Run_, TI tarafından, çift çekirdekli (ARM+DSP) heterojen işlemcileri için geliştirilmiş bir projedir. _ARM Linux_ ve _C6000 DSP_ çekirdeği içeren sistemler hedeflenmektedir.

Projenin 2011 yılı itibariyle geliştirilmesi sonlanmasına karşın, proje indirilebilmekte ve kullanılabilmektedir.

_C6Run_, _DSP_ ile ilgili birçok detayı gizlediğinden ve burada _DSP_ kullanımı hakkında genel bir fikir vermeyi amaçladığımızdan bu projeyi kullanacağız.

Bu bölümde ilk olarak, projeye ilişkin araçları sistemimize nasıl kuracağımıza, sonrasında _DSP_ hedefli kodu nasıl üretebileceğimize bakacağız.

## C6Run Kurulumu

Kurulum işlemine ilk olarak küçük bir başlangıç paketi indirerek başlayacağız. Projenin diğer bağımlılıklarını, bir tanesi hariç, bu paket üzerinden sağlayacağız. Ayrıca derlenmiş bir _kernel_ dizinine de ihtiyacımız olacak. Başlangıç paketini aşağıdaki gibi indirebilirsiniz.

```
wget -c https://gforge.ti.com/gf/download/frsrelease/535/4556/%43%36%52%75%6e%5f%30%5f%39%37%5f%30%33%5f%30%33%2e%74%61%72%2e%67%7a
```

> **Uyarı:** İndirdiğimiz paketin, **0.98** numaralı bir üst versiyonu bulunmasına veya **SVN** üzerinden son halinin indirilebilmesine karşın, sonrasında birçok probleme neden olmakta o yüzden **0.97** numaralı bu versiyonu kullanmanızı öneriyoruz.

Paketi açıp, _DSP_ derleyicisi hariç diğer bağımlılıkları aşağıdaki gibi sisteminize yükleyip kurabilirsiniz. Bu amaçla ana dizin içindeki _Makefile_ dosyasında _get\_component_ isimli bir hedef bulunmaktadır.

```
tar xf C6Run_0_98_03_03.tar.gz
cd C6Run_0_98_03_03
make get_components
```

_DSP_'ye ilişkin araçları ise sistemimize elle kurmalıyız. Bu araçlara ilişkin kurulum dosyasını aşağıdaki bağlantıdan indirebilirsiniz. **7.2.2** versiyonunu seçiniz.

```
http://software-dl.ti.com/codegen/non-esd/downloads/download.htm
```

> **Not:** Bu işlem öncesinde TI üyeliği gerektirmektedir, TI'ın sitesinden ücretsiz olarak üye olabilirsiniz.

İndirme işlemi sonucunda elde ettiğiniz _ti\_cgt\_c6000\_7.2.2\_setup\_linux\_x86.bin_ kurulum dosyası ile _DSP_'ye ilişkin araçları _home_ dizinin altında oluşturacağınız _toolchains/TI\_CGT\_C6000\_7.2.2_ isimli bir dizin altına kurabilirsiniz. Neden böyle bir dizin yolu seçtiğimize birazdan bakacağız.

Gerekli bağımlılıkları edindikten sonra, ana dizindeki _Rules.mak_ ve _platforms/hawkboard/platform.mak_ dosyalarındaki bazı değişkenere uygun değerleri geçirmeliyiz.

_Rules.mak_ dosyasında, _DSP_ ve _ARM_ araçlarının öngörülen yol ve önek ifadeleri aşağıdaki gibidir.

```
CODEGEN_INSTALL_DIR     ?= $(HOME)/toolchains/TI_CGT_C6000_7.2.2
ARM_TOOLCHAIN_PATH      ?= $(HOME)/toolchains/arm-2009q1
ARM_TOOLCHAIN_PREFIX    ?= arm-none-linux-gnueabi-
```

_DSP_ veya _ARM_ derleyicinizi başka bir yere kurduysanız veya başka bir çapraz derleyici kullanıyorsanız, bu değişkenlere uygun değerleri vermelisiniz.

_platforms/hawkboard/platform.mak_ dosyasında ise derlenmiş çekirdek dizinini göstermeliyiz, öngörülen değeri aşağıdaki gibidir.

```
LINUXKERNEL_INSTALL_DIR     ?= $(HOME)/workdir/hawkboard/kernel/
```

Kendi sisteminize uygun olarak bu değişkenleri değiştirebilirsiniz.

> **Not:** Board Recovery bölümünde, Hawkboard için çekirdeği nasıl derleyebileceğiniz bulunmaktadır.

Bu aşamadan sonra, projeyi _Hawkboard_ hedefli konfigür edebilir ve gerekli araçları aşağıdaki gibi derleyebiliriz.

```
make hawkboard_config
make everything
```

Bu süreç sonunda sisteminizde gerekli kütüphaneler kurulmuş olmalıdır. Bu aşamadan sonra proje dizinindeki örnekleri derleyip, örneklerle beraber gerekli modülleri bir dizinde sakalayabiliriz. Öncesinde _C6Run_ ana dizindeki _bin_ dizinini _PATH_ çevre değişkenine eklemeliyiz.

```
export PATH=$PATH:$(pwd)/bin
make examples
make INSTALL_DIR=/tmp/hawkdps install_programs
```

Hedef platform için derlenmiş örneklerle beraber, gerekli çekirdek modülleri ve betiklerler aşağıdaki gibi olacaktır.

```
# ls /tmp/hawkdps/
cmemk.ko  dsplinkk.ko  examples  loadmodules.sh  test  unloadmodules.sh
```

Son olarak, DSP modülünü kullanan kendi uygulamalarımızı nasıl derleyebileceğimize bakalım.

## DSP Hedefli Uygulamaların Derlenmesi

C6Run araçları ile, DSP modülünü farklı şekilde kullanan, 2 tür uygulama oluşturmak mümkündür. Birinci durumda uygulamanın tamamı DSP modülünde çalışırken, ikinci durumda yalnız istenilen kritik bir kodu DSP tarafında çalıştırmak mümkündür. Her iki durumda da uygulama doğal bir ARM uygulaması olarak gözükmekte, DSP modülünün başlatılması ve program kodunun yüklenmesi içsel olarak yapılmaktadır. Tüm giriş/çıkış işlemleri ise DSP modülünden ARM tarafına yönlendirilmektedir.

Uygulamalarımızı derlemek için kullanacağımız önyüz araçları projenin ana dizini altındaki _bin_ dizininde yer almaktadır. Kullanacağımız araçlar aşağıdaki gibidir:

* c6runapp-cc &#x20;
* c6runlib-cc
* c6runlib-ar &#x20;

_Bash_ betiği olarak yazılmış bu önyüz araçları, arka planda TI C6000 derleyicisi _cl6x_'i, çapraz ARM derleyicisini, diğer gerekli araçları kullamakta ve bize _gcc_ derleyicisine oldukça benzer bir arayüz sunmaktadır.

Şimdi sırasıyla, uygulamanın tümünün ya da yalnız bir kısmının DSP tarafında çalıştırılacağı uygulamaları nasıl derleyebileceğimize bakalım.

## Tüm Uygulamanın DSP Hedefli Derlenmesi

Aşağıdaki örnek uygulamayı _measure.c_ adıyla saklayıp derleyebilirsiniz.

```c
#include <stdio.h>
#include <time.h>
#include <math.h>

#if defined(_TMS320C6X)
#elif defined(__GNUC__)
    #include <sys/time.h>
#endif

#define N 1000000

typedef unsigned long long timestamp_t;

int i;
timestamp_t t0, t1;
float secs;
double d;

static timestamp_t get_timestamp () {
#if defined(_TMS320C6X)
      return (timestamp_t) clock();
#elif defined(__GNUC__)
    struct timeval now;
    gettimeofday (&now, NULL);
    return  now.tv_usec + (timestamp_t)now.tv_sec * 1000000;
#endif
}

void bench() {
    t0 = get_timestamp();
    for (i = 0; i < N; ++i) {
        d = sin(i) * cos(i);
    }
    t1 = get_timestamp();
    secs = (t1 - t0) / 1000000.0L;
    printf("%d times sin(i) * cos(i)   sec: %f\n", N, secs);
}

int main() {
    bench();
    return 0;
}
```

```
c6runapp-cc -omeasure_dsp measure.c
```

Aynı uygulamayı ayrıca ARM hedefli derleyerek, _bench_ fonskiyonunda geçen süreleri karşılaştırabilirsiniz. Kullandığımız çapraz derleyici için derleme işlemi aşağıdaki gibi olacaktır.

```
arm-none-linux-gnueabi-gcc -omeasure_arm measure.c -lm
```

> **Not:** ARM ve DSP modüllerinde sistem zamanının farklı şekilde alındığına ve kodda bu bölümlerin `_TMS320C6X` ve `__GNUC__` makrolarıyla birbirinden ayrıldığına dikkat ediniz.

## Kritik Kodun DSP Hedefli Derlenmesi

DSP tarafında çalışacak kod, ilk önce C6000 obje koduna, ardından linklenebilecek ARM hedefli bir kütüphaneye dönüştürülmelidir. Sırasıyla bu işlemler için _c6runlib-cc_ ve _c6runlib-ar_ araçlarını kullanacağız.

Bir önceki örneğimizdeki _bench_ fonksiyonunu bir kütüphane fonksiyonu olarak derleyelim. Aşağıdaki örnek kodları sırasıyla _libmeasure.c_ ve _main.c_ olarak kaydedebilirsiniz.

```c
#include <stdio.h>
#include <time.h>
#include <math.h>

#if defined(_TMS320C6X)
#elif defined(__GNUC__)
    #include <sys/time.h>
#endif

#define N 1000000

typedef unsigned long long timestamp_t;

int i;
timestamp_t t0, t1;
float secs;
double d;

static timestamp_t get_timestamp () {
#if defined(_TMS320C6X)
      return (timestamp_t) clock();
#elif defined(__GNUC__)
    struct timeval now;
    gettimeofday (&now, NULL);
    return  now.tv_usec + (timestamp_t)now.tv_sec * 1000000;
#endif
}

void bench() {
    t0 = get_timestamp();
    for (i = 0; i < N; ++i) {
        d = sin(i) * cos(i);
    }
    t1 = get_timestamp();
    secs = (t1 - t0) / 1000000.0L;
    printf("%d times sin(i) * cos(i)   sec: %f\n", N, secs);
}
```

```c
void bench();

int main() {
    bench();
    return 0;
}
```

_bench_ kodunun bulunduğu kaynak kodu, aşağıdaki gibi bir statik kütüphaneye dönüştürdükten sonra uygulamamıza linkleyebiliriz.

```
c6runlib-cc -c -olibmeasure.o libmeasure.c
c6runlib-ar rcs libmeasure.a libmeasure.o
arm-none-linux-gnueabi-gcc -c main.c 
arm-none-linux-gnueabi-gcc -omeasure_dsp main.o libmeasure.a
```
