●クロックの設定

●消費電力と実行時間の評価に使ったCPUプログラム

#include <stdint.h>
#include <stdbool.h>
#include "bsp.h"
#include "prescaler.h"
#include "timer.h"
#include "userTimerDemo.h"
#include "riscv.h"
#include "plic.h"
#include "gpio.h"

volatile uint32_t counter = 0;       // 割り込みで更新されるカウンタ
volatile uint32_t calculation_result = 0; // 計算結果を保存
volatile bool interrupt_flag = false;    // 割り込みフラグ

#define TIMER_PRESCALER_CTRL            (TIMER_CTRL + 0x00)
#define TIMER_0_CTRL                    (TIMER_CTRL +  0x40)
#define TIMER_CONFIG_WITH_PRESCALER     0x2
#define TIMER_CONFIG_WITHOUT_PRESCALER  0x1
#define TIMER_CONFIG_SELF_RESTART       0x10000

#define GPIO0       SYSTEM_GPIO_0_IO_CTRL

void init();
void main();
void trap();
void crash();
void trap_entry();
void timerInterrupt();
void externalInterrupt();
void initTimer();

#define ARRAY_SIZE 100
#define SEARCH_KEY 42

// 配列の初期化関数
void initialize_array(uint32_t array[], uint32_t size, bool use_random) {
    if (use_random) {
        // 疑似乱数を用いた初期化
        uint32_t seed = 12345;  // 固定されたシード
        for (uint32_t i = 0; i < size; i++) {
            seed = (1103515245 * seed + 12345) & 0x7FFFFFFF; // 線形合同法
            array[i] = seed % 1000;  // 0~999の値で初期化
        }
    } else {
        // 固定値による初期化
        for (uint32_t i = 0; i < size; i++) {
            array[i] = size - i;  // 降順に初期化
        }
    }
}

// 配列のシャッフル関数
void shuffle_array(uint32_t array[], uint32_t size) {
    uint32_t seed = 12345;  // 固定されたシードで乱数生成
    for (uint32_t i = size - 1; i > 0; i--) {
        seed = (1103515245 * seed + 12345) & 0x7FFFFFFF; // 線形合同法
        uint32_t j = seed % (i + 1); // 0 ~ i の範囲でランダムなインデックス
        // 要素を交換
        uint32_t temp = array[i];
        array[i] = array[j];
        array[j] = temp;
    }
}

// 配列ソート(バブルソート)
void bubble_sort(uint32_t array[], uint32_t size) {
    for (uint32_t i = 0; i < size - 1; i++) {
        for (uint32_t j = 0; j < size - i - 1; j++) {
            if (array[j] > array[j + 1]) {
                uint32_t temp = array[j];
                array[j] = array[j + 1];
                array[j + 1] = temp;
            }
        }
    }
}

// 配列探索(線形探索)
int linear_search(uint32_t array[], uint32_t size, uint32_t key) {
    for (uint32_t i = 0; i < size; i++) {
        if (array[i] == key) {
            return i;
        }
    }
    return -1; // 見つからなかった場合
}

// 割り込みハンドラ
void timerInterrupt() {
    counter++;                // 割り込みでカウンタを更新
    interrupt_flag = true;    // 割り込み発生を通知
}

// 割り込み処理
void externalInterrupt() {
    uint32_t claim;
    while ((claim = plic_claim(BSP_PLIC, BSP_PLIC_CPU_0))) {
        switch (claim) {
        case SYSTEM_PLIC_TIMER_INTERRUPTS_0:
            timerInterrupt();
            break;
        default:
            crash();
            break;
        }
        plic_release(BSP_PLIC, BSP_PLIC_CPU_0, claim);
    }
}

// トラップ(例外/割り込み)エントリ
void trap() {
    int32_t mcause = csr_read(mcause); // 割り込み/例外の原因を取得
    int32_t interrupt = mcause < 0;   // 割り込みの場合はtrue
    int32_t cause = mcause & 0xF;     // 原因コード
    if (interrupt) {
        switch (cause) {
        case CAUSE_MACHINE_EXTERNAL:
            externalInterrupt();
            break;
        default:
            crash();
            break;
        }
    } else {
        crash();
    }
}

// システム停止(クラッシュ処理)
void crash() {
    bsp_printf("\r\n*** CRASH ***\r\n");
    while (1); // 無限ループで停止
}

// タイマ初期化
void initTimer() {
    prescaler_setValue(TIMER_CTRL, 124);         // RISC-V 21.09 MHz の場合は 210 に変更
    timer_setConfig(TIMER_CTRL, 0x1 | 0x10000);
    timer_setLimit(TIMER_CTRL, 4);
}

// 初期化処理
void init() {
    initTimer();
    plic_set_threshold(BSP_PLIC, BSP_PLIC_CPU_0, 0);
    plic_set_enable(BSP_PLIC, BSP_PLIC_CPU_0, SYSTEM_PLIC_TIMER_INTERRUPTS_0, 1);
    plic_set_priority(BSP_PLIC, SYSTEM_PLIC_TIMER_INTERRUPTS_0, 1);
    csr_write(mtvec, trap_entry); // トラップエントリ設定
    csr_set(mie, MIE_MEIE);
    csr_write(mstatus, csr_read(mstatus) | MSTATUS_MPP | MSTATUS_MIE);
}

// メインプログラム
void main() {
    gpio_setOutput(SYSTEM_GPIO_0_IO_CTRL, 0x00);
    bsp_uDelay(1000000);
    gpio_setOutput(SYSTEM_GPIO_0_IO_CTRL, 0xFF);   // 処理開始 : GPIO = High

    init();

    volatile uint32_t data = 1, temp1 = 0, temp2 = 0, temp3 = 0;
    uint32_t array[ARRAY_SIZE];
    uint32_t search_result = 0;

    // 配列の初期化(固定値)
    initialize_array(array, ARRAY_SIZE, false);

    for (uint32_t i = 0; i < 1000; i++) {
        // 配列をバブルソート
        bubble_sort(array, ARRAY_SIZE);

        // 配列探索(線形探索)
        search_result = linear_search(array, ARRAY_SIZE, SEARCH_KEY);

        // 複雑なデータ依存計算
        temp1 = data * 2 + search_result;
        temp2 = temp1 / 3 + counter;
        temp3 = temp2 * temp1 - counter;
        calculation_result = temp3 + array[0];

        // 配列をシャッフルして再び未ソート状態に
        shuffle_array(array, ARRAY_SIZE);

        // 割り込みフラグの確認
        if (interrupt_flag) {
            interrupt_flag = false;
            calculation_result += counter; // 割り込みでカウンタの値を利用
        }
    }

    gpio_setOutput(SYSTEM_GPIO_0_IO_CTRL, 0x00);  // 処理完了 : GPIO = Low
}

コメントを残す