●クロックの設定
●消費電力と実行時間の評価に使った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
}