Commit d0759cb2 authored by Kento HASEGAWA's avatar Kento HASEGAWA

Change character codec

parent 1fc5e482
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
using namespace std; using namespace std;
// テストデータ (文字列形式) // テストデータ (文字列形式)
// NL_Q00.txt // NL_Q00.txt
//char boardstr[BOARDSTR_SIZE] = "X10Y05Z3L0000107041L0004107002L0102102021L0900100003"; //char boardstr[BOARDSTR_SIZE] = "X10Y05Z3L0000107041L0004107002L0102102021L0900100003";
// NL_Q06.txt // NL_Q06.txt
...@@ -29,9 +29,9 @@ int main(int argc, char *argv[]) { ...@@ -29,9 +29,9 @@ int main(int argc, char *argv[]) {
// NL_Q08.txt // NL_Q08.txt
//char boardstr[BOARDSTR_SIZE] = "X17Y20Z2L0000103022L1603115052L0916107032L0302108012L1104111042L1002100002L0919116162L1616113182L1001115012L0500201182L1603213152L0600210022"; //char boardstr[BOARDSTR_SIZE] = "X17Y20Z2L0000103022L1603115052L0916107032L0302108012L1104111042L1002100002L0919116162L1616113182L1001115012L0500201182L1603213152L0600210022";
// 指定されてればコマンドラインから問題文字列を読み込む // 指定されてればコマンドラインから問題文字列を読み込む
if (1 < argc) { if (1 < argc) {
//先頭がXではないならば標準入力から読み込む //先頭がXではないならば標準入力から読み込む
if(argv[1][0]!='X') if(argv[1][0]!='X')
{ {
char* c_p=fgets(boardstr, BOARDSTR_SIZE, stdin); char* c_p=fgets(boardstr, BOARDSTR_SIZE, stdin);
...@@ -44,7 +44,7 @@ int main(int argc, char *argv[]) { ...@@ -44,7 +44,7 @@ int main(int argc, char *argv[]) {
} }
} }
// 指定されてればシード値を読み込む // 指定されてればシード値を読み込む
int seed = 12345; int seed = 12345;
if (2 < argc) { if (2 < argc) {
seed = atoi(argv[2]); seed = atoi(argv[2]);
...@@ -54,7 +54,7 @@ int main(int argc, char *argv[]) { ...@@ -54,7 +54,7 @@ int main(int argc, char *argv[]) {
int size_y = (boardstr[4] - '0') * 10 + (boardstr[5] - '0'); int size_y = (boardstr[4] - '0') * 10 + (boardstr[5] - '0');
int size_z = (boardstr[7] - '0'); int size_z = (boardstr[7] - '0');
// ソルバ実行 // ソルバ実行
ap_int<32> status; ap_int<32> status;
clock_t clock_start, clock_done; clock_t clock_start, clock_done;
clock_start = clock(); clock_start = clock();
...@@ -68,7 +68,7 @@ int main(int argc, char *argv[]) { ...@@ -68,7 +68,7 @@ int main(int argc, char *argv[]) {
cout << "status = " << (int)status << endl; cout << "status = " << (int)status << endl;
cout << "elapsed = " << ((double)(clock_done - clock_start) / CLOCKS_PER_SEC) << endl << endl; cout << "elapsed = " << ((double)(clock_done - clock_start) / CLOCKS_PER_SEC) << endl << endl;
// 解表示 // 解表示
cout << "SOLUTION" << endl; cout << "SOLUTION" << endl;
cout << "========" << endl; cout << "========" << endl;
cout << "SIZE " << size_x << "X" << size_y << "X" << size_z << endl; cout << "SIZE " << size_x << "X" << size_y << "X" << size_z << endl;
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
// LFST // LFST
// ================================ // // ================================ //
// 参考 https://highlevel-synthesis.com/2017/02/10/lfsr-in-hls/ // 参考 https://highlevel-synthesis.com/2017/02/10/lfsr-in-hls/
static ap_uint<32> lfsr; static ap_uint<32> lfsr;
void lfsr_random_init(ap_uint<32> seed) { void lfsr_random_init(ap_uint<32> seed) {
...@@ -38,15 +38,15 @@ ap_uint<32> lfsr_random() { ...@@ -38,15 +38,15 @@ ap_uint<32> lfsr_random() {
return lfsr.to_uint(); return lfsr.to_uint();
} }
// AからBの範囲 (AとBを含む) の整数の乱数が欲しいとき // AからBの範囲 (AとBを含む) の整数の乱数が欲しいとき
// 参考 http://www.sat.t.u-tokyo.ac.jp/~omi/random_variables_generation.html // 参考 http://www.sat.t.u-tokyo.ac.jp/~omi/random_variables_generation.html
/*ap_uint<32> lfsr_random_uint32(ap_uint<32> a, ap_uint<32> b) { /*ap_uint<32> lfsr_random_uint32(ap_uint<32> a, ap_uint<32> b) {
#pragma HLS INLINE #pragma HLS INLINE
return lfsr_random() % (b - a + 1) + a; return lfsr_random() % (b - a + 1) + a;
}*/ }*/
// 0からBの範囲 (AとBを含む) の整数の乱数が欲しいとき // 0からBの範囲 (AとBを含む) の整数の乱数が欲しいとき
// 参考 http://www.sat.t.u-tokyo.ac.jp/~omi/random_variables_generation.html // 参考 http://www.sat.t.u-tokyo.ac.jp/~omi/random_variables_generation.html
/*ap_uint<32> lfsr_random_uint32_0(ap_uint<32> b) { /*ap_uint<32> lfsr_random_uint32_0(ap_uint<32> b) {
#pragma HLS INLINE #pragma HLS INLINE
return lfsr_random() % (b + 1); return lfsr_random() % (b + 1);
...@@ -54,21 +54,21 @@ ap_uint<32> lfsr_random() { ...@@ -54,21 +54,21 @@ ap_uint<32> lfsr_random() {
// ================================ // // ================================ //
// メインモジュール // メインモジュール
// ================================ // // ================================ //
// 重みの更新 // 重みの更新
// TODO 調整 // TODO 調整
// min_uint8(r, MAX_WEIGHT) と同じ // min_uint8(r, MAX_WEIGHT) と同じ
ap_uint<8> new_weight(ap_uint<16> x) { ap_uint<8> new_weight(ap_uint<16> x) {
#pragma HLS INLINE #pragma HLS INLINE
#if 1 #if 1
// 下位8ビット (最大 255) を抜き出して、1/8 をかけて最大 31 (32) にする // 下位8ビット (最大 255) を抜き出して、1/8 をかけて最大 31 (32) にする
ap_uint<8> y = x & 255; ap_uint<8> y = x & 255;
return (ap_uint<8>)(y / 8 + 1); return (ap_uint<8>)(y / 8 + 1);
#endif #endif
#if 0 #if 0
// 下位10ビット (最大 1023) を抜き出して、1/32 をかけて最大 31 (32) にする // 下位10ビット (最大 1023) を抜き出して、1/32 をかけて最大 31 (32) にする
ap_uint<10> y = x & 1023; ap_uint<10> y = x & 1023;
return (ap_uint<8>)(y / 32 + 1); return (ap_uint<8>)(y / 32 + 1);
#endif #endif
...@@ -79,23 +79,23 @@ ap_uint<8> new_weight(ap_uint<16> x) { ...@@ -79,23 +79,23 @@ ap_uint<8> new_weight(ap_uint<16> x) {
#endif #endif
} }
// ボードに関する変数 // ボードに関する変数
static ap_uint<7> size_x; // ボードの X サイズ static ap_uint<7> size_x; // ボードの X サイズ
static ap_uint<7> size_y; // ボードの Y サイズ static ap_uint<7> size_y; // ボードの Y サイズ
static ap_uint<4> size_z; // ボードの Z サイズ static ap_uint<4> size_z; // ボードの Z サイズ
static ap_uint<7> line_num = 0; // ラインの総数 static ap_uint<7> line_num = 0; // ラインの総数
// グローバル変数で定義する // グローバル変数で定義する
#ifdef GLOBALVARS #ifdef GLOBALVARS
ap_uint<16> starts[MAX_LINES]; // ラインのスタートリスト ap_uint<16> starts[MAX_LINES]; // ラインのスタートリスト
ap_uint<16> goals[MAX_LINES]; // ラインのゴールリスト ap_uint<16> goals[MAX_LINES]; // ラインのゴールリスト
ap_uint<8> weights[MAX_CELLS]; // セルの重み ap_uint<8> weights[MAX_CELLS]; // セルの重み
ap_uint<8> paths_size[MAX_LINES]; // ラインが対応するセルIDのサイズ ap_uint<8> paths_size[MAX_LINES]; // ラインが対応するセルIDのサイズ
ap_uint<16> paths[MAX_LINES][MAX_PATH]; // ラインが対応するセルIDの集合 (スタートとゴールは除く) ap_uint<16> paths[MAX_LINES][MAX_PATH]; // ラインが対応するセルIDの集合 (スタートとゴールは除く)
bool adjacents[MAX_LINES]; // スタートとゴールが隣接しているライン bool adjacents[MAX_LINES]; // スタートとゴールが隣接しているライン
#endif #endif
bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *status) { bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *status) {
...@@ -106,30 +106,30 @@ bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *stat ...@@ -106,30 +106,30 @@ bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *stat
*status = -1; *status = -1;
// グローバル変数では定義しない // グローバル変数では定義しない
#ifndef GLOBALVARS #ifndef GLOBALVARS
ap_uint<16> starts[MAX_LINES]; // ラインのスタートリスト ap_uint<16> starts[MAX_LINES]; // ラインのスタートリスト
#pragma HLS ARRAY_PARTITION variable=starts complete dim=1 #pragma HLS ARRAY_PARTITION variable=starts complete dim=1
ap_uint<16> goals[MAX_LINES]; // ラインのゴールリスト ap_uint<16> goals[MAX_LINES]; // ラインのゴールリスト
#pragma HLS ARRAY_PARTITION variable=goals complete dim=1 #pragma HLS ARRAY_PARTITION variable=goals complete dim=1
ap_uint<8> weights[MAX_CELLS]; // セルの重み ap_uint<8> weights[MAX_CELLS]; // セルの重み
//#pragma HLS ARRAY_PARTITION variable=weights cyclic factor=8 dim=1 partition //#pragma HLS ARRAY_PARTITION variable=weights cyclic factor=8 dim=1 partition
// Note: weights は様々な順番でアクセスされるからパーティションしても全然効果ない // Note: weights は様々な順番でアクセスされるからパーティションしても全然効果ない
ap_uint<8> paths_size[MAX_LINES]; // ラインが対応するセルIDのサイズ ap_uint<8> paths_size[MAX_LINES]; // ラインが対応するセルIDのサイズ
//#pragma HLS ARRAY_PARTITION variable=paths_size complete dim=1 //#pragma HLS ARRAY_PARTITION variable=paths_size complete dim=1
ap_uint<16> paths[MAX_LINES][MAX_PATH]; // ラインが対応するセルIDの集合 (スタートとゴールは除く) ap_uint<16> paths[MAX_LINES][MAX_PATH]; // ラインが対応するセルIDの集合 (スタートとゴールは除く)
//#pragma HLS ARRAY_PARTITION variable=paths cyclic factor=16 dim=2 partition //#pragma HLS ARRAY_PARTITION variable=paths cyclic factor=16 dim=2 partition
bool adjacents[MAX_LINES]; // スタートとゴールが隣接しているライン bool adjacents[MAX_LINES]; // スタートとゴールが隣接しているライン
//#pragma HLS ARRAY_PARTITION variable=adjacents complete dim=1 //#pragma HLS ARRAY_PARTITION variable=adjacents complete dim=1
#endif #endif
// ================================ // ================================
// 初期化 BEGIN // 初期化 BEGIN
// ================================ // ================================
// ループカウンタは1ビット余分に用意しないと終了判定できない // ループカウンタは1ビット余分に用意しないと終了判定できない
INIT_ADJACENTS: INIT_ADJACENTS:
for (ap_uint<8> i = 0; i < (ap_uint<8>)(MAX_LINES); i++) { for (ap_uint<8> i = 0; i < (ap_uint<8>)(MAX_LINES); i++) {
adjacents[i] = false; adjacents[i] = false;
...@@ -142,7 +142,7 @@ bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *stat ...@@ -142,7 +142,7 @@ bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *stat
weights[i] = 1; weights[i] = 1;
} }
// ボードストリングの解釈 // ボードストリングの解釈
size_x = (boardstr[1] - '0') * 10 + (boardstr[2] - '0'); size_x = (boardstr[1] - '0') * 10 + (boardstr[2] - '0');
size_y = (boardstr[4] - '0') * 10 + (boardstr[5] - '0'); size_y = (boardstr[4] - '0') * 10 + (boardstr[5] - '0');
...@@ -152,7 +152,7 @@ bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *stat ...@@ -152,7 +152,7 @@ bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *stat
for (ap_uint<16> idx = 8; idx < BOARDSTR_SIZE; idx+=11) { for (ap_uint<16> idx = 8; idx < BOARDSTR_SIZE; idx+=11) {
//#pragma HLS LOOP_TRIPCOUNT min=100 max=32768 avg=1000 //#pragma HLS LOOP_TRIPCOUNT min=100 max=32768 avg=1000
// 終端 (null) 文字 // 終端 (null) 文字
if (boardstr[idx] == 0) { if (boardstr[idx] == 0) {
break; break;
} }
...@@ -166,16 +166,16 @@ bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *stat ...@@ -166,16 +166,16 @@ bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *stat
//cout << "L " << line_num << ": (" << s_x << ", " << s_y << ", " << s_z << ") " //cout << "L " << line_num << ": (" << s_x << ", " << s_y << ", " << s_z << ") "
// "(" << g_x << ", " << g_y << ", " << g_z << ")" << endl; // "(" << g_x << ", " << g_y << ", " << g_z << ")" << endl;
// スタートとゴール // スタートとゴール
ap_uint<16> start_id = (((ap_uint<16>)s_x * MAX_WIDTH + (ap_uint<16>)s_y) << BITWIDTH_Z) | (ap_uint<16>)s_z; ap_uint<16> start_id = (((ap_uint<16>)s_x * MAX_WIDTH + (ap_uint<16>)s_y) << BITWIDTH_Z) | (ap_uint<16>)s_z;
ap_uint<16> goal_id = (((ap_uint<16>)g_x * MAX_WIDTH + (ap_uint<16>)g_y) << BITWIDTH_Z) | (ap_uint<16>)g_z; ap_uint<16> goal_id = (((ap_uint<16>)g_x * MAX_WIDTH + (ap_uint<16>)g_y) << BITWIDTH_Z) | (ap_uint<16>)g_z;
starts[line_num] = start_id; starts[line_num] = start_id;
goals[line_num] = goal_id; goals[line_num] = goal_id;
// 初期状態で数字が隣接しているか判断 // 初期状態で数字が隣接しているか判断
ap_int<8> dx = (ap_int<8>)g_x - (ap_int<8>)s_x; // 最小-71 最大71 (-> 符号付き8ビット) ap_int<8> dx = (ap_int<8>)g_x - (ap_int<8>)s_x; // 最小-71 最大71 (-> 符号付き8ビット)
ap_int<8> dy = (ap_int<8>)g_y - (ap_int<8>)s_y; // 最小-71 最大71 (-> 符号付き8ビット) ap_int<8> dy = (ap_int<8>)g_y - (ap_int<8>)s_y; // 最小-71 最大71 (-> 符号付き8ビット)
ap_int<4> dz = (ap_int<4>)g_z - (ap_int<4>)s_z; // 最小-7 最大7 (-> 符号付き4ビット) ap_int<4> dz = (ap_int<4>)g_z - (ap_int<4>)s_z; // 最小-7 最大7 (-> 符号付き4ビット)
if ((dx == 0 && dy == 0 && (dz == 1 || dz == -1)) || (dx == 0 && (dy == 1 || dy == -1) && dz == 0) || ((dx == 1 || dx == -1) && dy == 0 && dz == 0)) { if ((dx == 0 && dy == 0 && (dz == 1 || dz == -1)) || (dx == 0 && (dy == 1 || dy == -1) && dz == 0) || ((dx == 1 || dx == -1) && dy == 0 && dz == 0)) {
adjacents[line_num] = true; adjacents[line_num] = true;
paths_size[line_num] = 0; paths_size[line_num] = 0;
...@@ -191,21 +191,21 @@ bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *stat ...@@ -191,21 +191,21 @@ bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *stat
} }
//cout << size_x << " " << size_y << " " << size_z << endl; //cout << size_x << " " << size_y << " " << size_z << endl;
// 乱数の初期化 // 乱数の初期化
lfsr_random_init(seed); lfsr_random_init(seed);
// TODO // TODO
// すべてのラインが隣接してたらソルバを終わりにする // すべてのラインが隣接してたらソルバを終わりにする
// ================================ // ================================
// 初期化 END // 初期化 END
// ================================ // ================================
// ================================ // ================================
// ルーティング BEGIN // ルーティング BEGIN
// ================================ // ================================
// [Step 1] 初期ルーティング // [Step 1] 初期ルーティング
cout << "Initial Routing" << endl; cout << "Initial Routing" << endl;
FIRST_ROUTING: FIRST_ROUTING:
for (ap_uint<8> i = 0; i < (ap_uint<8>)(line_num); i++) { for (ap_uint<8> i = 0; i < (ap_uint<8>)(line_num); i++) {
...@@ -213,10 +213,10 @@ bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *stat ...@@ -213,10 +213,10 @@ bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *stat
//#pragma HLS PIPELINE //#pragma HLS PIPELINE
//#pragma HLS UNROLL factor=2 //#pragma HLS UNROLL factor=2
// 数字が隣接する場合スキップ、そうでない場合は実行 // 数字が隣接する場合スキップ、そうでない場合は実行
if (adjacents[i] == false) { if (adjacents[i] == false) {
// 経路探索 // 経路探索
#ifdef DEBUG_PRINT #ifdef DEBUG_PRINT
cout << "LINE #" << (int)(i + 1) << endl; cout << "LINE #" << (int)(i + 1) << endl;
#endif #endif
...@@ -230,7 +230,7 @@ bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *stat ...@@ -230,7 +230,7 @@ bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *stat
bool has_overlap = false; bool has_overlap = false;
#ifndef USE_MOD_CALC #ifndef USE_MOD_CALC
// line_num_2: line_num 以上で最小の2のべき乗数 // line_num_2: line_num 以上で最小の2のべき乗数
ap_uint<8> line_num_2; ap_uint<8> line_num_2;
CALC_LINE_NUM_2: CALC_LINE_NUM_2:
for (line_num_2 = 1; line_num_2 < (ap_uint<8>)line_num; line_num_2 *= 2) { for (line_num_2 = 1; line_num_2 < (ap_uint<8>)line_num; line_num_2 *= 2) {
...@@ -243,7 +243,7 @@ bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *stat ...@@ -243,7 +243,7 @@ bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *stat
ap_uint<8> last_target = 255; ap_uint<8> last_target = 255;
// [Step 2] Rip-up 再ルーティング // [Step 2] Rip-up 再ルーティング
ROUTING: ROUTING:
for (ap_uint<16> round = 1; round <= 32768 /* = (2048 * 16) */; round++) { for (ap_uint<16> round = 1; round <= 32768 /* = (2048 * 16) */; round++) {
#pragma HLS LOOP_TRIPCOUNT min=1 max=4000 avg=50 #pragma HLS LOOP_TRIPCOUNT min=1 max=4000 avg=50
...@@ -252,12 +252,12 @@ bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *stat ...@@ -252,12 +252,12 @@ bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *stat
//cout << "ITERATION " << round; //cout << "ITERATION " << round;
//#endif //#endif
// 対象ラインを選択 // 対象ラインを選択
#ifdef USE_MOD_CALC #ifdef USE_MOD_CALC
// (1) 剰余演算を用いる方法 // (1) 剰余演算を用いる方法
ap_uint<8> target = lfsr_random() % line_num; // i.e., lfsr_random_uint32(0, line_num - 1); ap_uint<8> target = lfsr_random() % line_num; // i.e., lfsr_random_uint32(0, line_num - 1);
#else #else
// (2) 剰余演算を用いない方法 // (2) 剰余演算を用いない方法
ap_uint<8> target = lfsr_random() & (line_num_2 - 1); ap_uint<8> target = lfsr_random() & (line_num_2 - 1);
if (line_num <= target) { if (line_num <= target) {
//cout << endl; //cout << endl;
...@@ -265,36 +265,36 @@ bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *stat ...@@ -265,36 +265,36 @@ bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *stat
} }
#endif #endif
// 数字が隣接する場合スキップ、そうでない場合は実行 // 数字が隣接する場合スキップ、そうでない場合は実行
if (adjacents[target] == true) { if (adjacents[target] == true) {
//cout << endl; //cout << endl;
continue; continue;
} }
// 直前のイテレーション (ラウンド) と同じ対象ラインだったらルーティングスキップする // 直前のイテレーション (ラウンド) と同じ対象ラインだったらルーティングスキップする
if (target == last_target) { if (target == last_target) {
//cout << endl; //cout << endl;
continue; continue;
} }
last_target = target; last_target = target;
// (1) 引きはがすラインの重みをリセット // (1) 引きはがすラインの重みをリセット
ROUTING_RESET: ROUTING_RESET:
for (ap_uint<9> j = 0; j < (ap_uint<9>)(paths_size[target]); j++) { for (ap_uint<9> j = 0; j < (ap_uint<9>)(paths_size[target]); j++) {
#pragma HLS LOOP_TRIPCOUNT min=1 max=255 avg=50 #pragma HLS LOOP_TRIPCOUNT min=1 max=255 avg=50
weights[paths[target][j]] = 1; weights[paths[target][j]] = 1;
} }
// 対象ラインのスタートの重みも一旦リセット あとで (*) で戻す // 対象ラインのスタートの重みも一旦リセット あとで (*) で戻す
weights[starts[target]] = 1; weights[starts[target]] = 1;
// (2) 重みを更新 // (2) 重みを更新
ap_uint<8> current_round_weight = new_weight(round); ap_uint<8> current_round_weight = new_weight(round);
//cout << " weight " << current_round_weight << endl; //cout << " weight " << current_round_weight << endl;
ROUTING_UPDATE: ROUTING_UPDATE:
for (ap_uint<8> i = 0; i < (ap_uint<8>)(line_num); i++) { for (ap_uint<8> i = 0; i < (ap_uint<8>)(line_num); i++) {
#pragma HLS LOOP_TRIPCOUNT min=2 max=127 avg=50 #pragma HLS LOOP_TRIPCOUNT min=2 max=127 avg=50
// 数字が隣接する場合スキップ、そうでない場合は実行 // 数字が隣接する場合スキップ、そうでない場合は実行
if (adjacents[i] == false && i != target) { if (adjacents[i] == false && i != target) {
ROUTING_UPDATE_PATH: ROUTING_UPDATE_PATH:
for (ap_uint<9> j = 0; j < (ap_uint<9>)(paths_size[i]); j++) { for (ap_uint<9> j = 0; j < (ap_uint<9>)(paths_size[i]); j++) {
...@@ -304,17 +304,17 @@ bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *stat ...@@ -304,17 +304,17 @@ bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *stat
} }
} }
// 経路探索 // 経路探索
#ifdef DEBUG_PRINT #ifdef DEBUG_PRINT
cout << "LINE #" << (int)(target + 1) << endl; cout << "LINE #" << (int)(target + 1) << endl;
#endif #endif
search(&(paths_size[target]), paths[target], starts[target], goals[target], weights); search(&(paths_size[target]), paths[target], starts[target], goals[target], weights);
// (*) 対象ラインのスタートの重みを戻す // (*) 対象ラインのスタートの重みを戻す
weights[starts[target]] = MAX_WEIGHT; weights[starts[target]] = MAX_WEIGHT;
// ルーティング後 // ルーティング後
// オーバーラップのチェック // オーバーラップのチェック
has_overlap = false; has_overlap = false;
OVERLAP_RESET: OVERLAP_RESET:
for (ap_uint<16> i = 0; i < (ap_uint<16>)(MAX_CELLS); i++) { for (ap_uint<16> i = 0; i < (ap_uint<16>)(MAX_CELLS); i++) {
...@@ -328,7 +328,7 @@ bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *stat ...@@ -328,7 +328,7 @@ bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *stat
overlap_checks[starts[i]] = 1; overlap_checks[starts[i]] = 1;
overlap_checks[goals[i]] = 1; overlap_checks[goals[i]] = 1;
// 数字が隣接する場合スキップ、そうでない場合は実行 // 数字が隣接する場合スキップ、そうでない場合は実行
//if (adjacents[i] == false) { //if (adjacents[i] == false) {
OVERLAP_CHECK_PATH: OVERLAP_CHECK_PATH:
...@@ -346,35 +346,35 @@ bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *stat ...@@ -346,35 +346,35 @@ bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *stat
} }
//} //}
} }
// オーバーラップなければ探索終了 // オーバーラップなければ探索終了
if (has_overlap == false) { if (has_overlap == false) {
break; break;
} }
} }
// 解導出できなかった場合 // 解導出できなかった場合
if (has_overlap == true) { if (has_overlap == true) {
*status = 1; *status = 1;
return false; return false;
} }
// ================================ // ================================
// ルーティング END // ルーティング END
// ================================ // ================================
// ================================ // ================================
// 解生成 BEGIN // 解生成 BEGIN
// ================================ // ================================
// 空白 // 空白
OUTPUT_INIT: OUTPUT_INIT:
for (ap_uint<16> i = 0; i < (ap_uint<16>)(MAX_CELLS); i++) { for (ap_uint<16> i = 0; i < (ap_uint<16>)(MAX_CELLS); i++) {
boardstr[i] = 0; boardstr[i] = 0;
} }
// ライン // ライン
// このソルバでのラインIDを+1して表示する // このソルバでのラインIDを+1して表示する
// なぜなら空白を 0 で表すことにするからラインIDは 1 以上にしたい // なぜなら空白を 0 で表すことにするからラインIDは 1 以上にしたい
OUTPUT_LINE: OUTPUT_LINE:
for (ap_uint<8> i = 0; i < (ap_uint<8>)(line_num); i++) { for (ap_uint<8> i = 0; i < (ap_uint<8>)(line_num); i++) {
#pragma HLS LOOP_TRIPCOUNT min=2 max=127 avg=50 #pragma HLS LOOP_TRIPCOUNT min=2 max=127 avg=50
...@@ -388,7 +388,7 @@ bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *stat ...@@ -388,7 +388,7 @@ bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *stat
} }
// ================================ // ================================
// 解生成 END // 解生成 END
// ================================ // ================================
*status = 0; *status = 0;
...@@ -397,18 +397,18 @@ bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *stat ...@@ -397,18 +397,18 @@ bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *stat
// ================================ // // ================================ //
// 探索 // 探索
// ================================ // // ================================ //
#ifdef USE_ASTAR #ifdef USE_ASTAR
// A* ヒューリスティック用 // A* ヒューリスティック用
// 最大71 最小0 // 最大71 最小0
ap_uint<7> abs_uint7(ap_uint<7> a, ap_uint<7> b) { ap_uint<7> abs_uint7(ap_uint<7> a, ap_uint<7> b) {
#pragma HLS INLINE #pragma HLS INLINE
if (a < b) { return b - a; } if (a < b) { return b - a; }
else { return a - b; } else { return a - b; }
} }
// 最大7 最小0 // 最大7 最小0
ap_uint<3> abs_uint3(ap_uint<3> a, ap_uint<3> b) { ap_uint<3> abs_uint3(ap_uint<3> a, ap_uint<3> b) {
#pragma HLS INLINE #pragma HLS INLINE
if (a < b) { return b - a; } if (a < b) { return b - a; }
...@@ -416,20 +416,20 @@ ap_uint<3> abs_uint3(ap_uint<3> a, ap_uint<3> b) { ...@@ -416,20 +416,20 @@ ap_uint<3> abs_uint3(ap_uint<3> a, ap_uint<3> b) {
} }
#endif #endif
// * Pythonでダイクストラアルゴリズムを実装した - フツーって言うなぁ! // * Pythonでダイクストラアルゴリズムを実装した - フツーって言うなぁ!
// http://lethe2211.hatenablog.com/entry/2014/12/30/011030 // http://lethe2211.hatenablog.com/entry/2014/12/30/011030
// * Implementation of A* // * Implementation of A*
// http://www.redblobgames.com/pathfinding/a-star/implementation.html // http://www.redblobgames.com/pathfinding/a-star/implementation.html
// をベース // をベース
void search(ap_uint<8> *path_size, ap_uint<16> path[MAX_PATH], ap_uint<16> start, ap_uint<16> goal, ap_uint<8> w[MAX_CELLS]) { void search(ap_uint<8> *path_size, ap_uint<16> path[MAX_PATH], ap_uint<16> start, ap_uint<16> goal, ap_uint<8> w[MAX_CELLS]) {
//#pragma HLS INLINE // search関数はインラインすると遅くなるしBRAM足りなくなる //#pragma HLS INLINE // search関数はインラインすると遅くなるしBRAM足りなくなる
//#pragma HLS FUNCTION_INSTANTIATE variable=start //#pragma HLS FUNCTION_INSTANTIATE variable=start
//#pragma HLS FUNCTION_INSTANTIATE variable=goal //#pragma HLS FUNCTION_INSTANTIATE variable=goal
ap_uint<16> dist[MAX_CELLS]; // 始点から各頂点までの最短距離を格納する ap_uint<16> dist[MAX_CELLS]; // 始点から各頂点までの最短距離を格納する
#pragma HLS ARRAY_PARTITION variable=dist cyclic factor=64 dim=1 partition #pragma HLS ARRAY_PARTITION variable=dist cyclic factor=64 dim=1 partition
// Note: dist のパーティションの factor は 128 にするとBRAMが足りなくなる // Note: dist のパーティションの factor は 128 にするとBRAMが足りなくなる
ap_uint<16> prev[MAX_CELLS]; // 最短経路における,その頂点の前の頂点のIDを格納する ap_uint<16> prev[MAX_CELLS]; // 最短経路における,その頂点の前の頂点のIDを格納する
SEARCH_INIT_DIST: SEARCH_INIT_DIST:
for (ap_uint<16> i = 0; i < MAX_CELLS; i++) { for (ap_uint<16> i = 0; i < MAX_CELLS; i++) {
...@@ -437,19 +437,19 @@ void search(ap_uint<8> *path_size, ap_uint<16> path[MAX_PATH], ap_uint<16> start ...@@ -437,19 +437,19 @@ void search(ap_uint<8> *path_size, ap_uint<16> path[MAX_PATH], ap_uint<16> start
dist[i] = 65535; // = (2^16 - 1) dist[i] = 65535; // = (2^16 - 1)
} }
// プライオリティ・キュー // プライオリティ・キュー
ap_uint<12> pq_len = 0; ap_uint<12> pq_len = 0;
ap_uint<32> pq_nodes[MAX_PQ]; ap_uint<32> pq_nodes[MAX_PQ];
//#pragma HLS ARRAY_PARTITION variable=pq_nodes complete dim=1 //#pragma HLS ARRAY_PARTITION variable=pq_nodes complete dim=1
//#pragma HLS ARRAY_PARTITION variable=pq_nodes cyclic factor=2 dim=1 partition //#pragma HLS ARRAY_PARTITION variable=pq_nodes cyclic factor=2 dim=1 partition
#ifdef DEBUG_PRINT #ifdef DEBUG_PRINT
// キューの最大長さチェック用 // キューの最大長さチェック用
ap_uint<12> max_pq_len = 0; ap_uint<12> max_pq_len = 0;
#endif #endif
#ifdef USE_ASTAR #ifdef USE_ASTAR
// ゴールの座標 // ゴールの座標
ap_uint<13> goal_xy = (ap_uint<13>)(goal >> BITWIDTH_Z); ap_uint<13> goal_xy = (ap_uint<13>)(goal >> BITWIDTH_Z);
ap_uint<7> goal_x = (ap_uint<7>)(goal_xy / MAX_WIDTH); ap_uint<7> goal_x = (ap_uint<7>)(goal_xy / MAX_WIDTH);
ap_uint<7> goal_y = (ap_uint<7>)(goal_xy - goal_x * MAX_WIDTH); ap_uint<7> goal_y = (ap_uint<7>)(goal_xy - goal_x * MAX_WIDTH);
...@@ -457,7 +457,7 @@ void search(ap_uint<8> *path_size, ap_uint<16> path[MAX_PATH], ap_uint<16> start ...@@ -457,7 +457,7 @@ void search(ap_uint<8> *path_size, ap_uint<16> path[MAX_PATH], ap_uint<16> start
#endif #endif
dist[start] = 0; dist[start] = 0;
pq_push(0, start, &pq_len, pq_nodes); // 始点をpush pq_push(0, start, &pq_len, pq_nodes); // 始点をpush
#ifdef DEBUG_PRINT #ifdef DEBUG_PRINT
if (max_pq_len < pq_len) { max_pq_len = pq_len; } if (max_pq_len < pq_len) { max_pq_len = pq_len; }
#endif #endif
...@@ -480,86 +480,86 @@ void search(ap_uint<8> *path_size, ap_uint<16> path[MAX_PATH], ap_uint<16> start ...@@ -480,86 +480,86 @@ void search(ap_uint<8> *path_size, ap_uint<16> path[MAX_PATH], ap_uint<16> start
ap_uint<16> dist_src = dist[src]; ap_uint<16> dist_src = dist[src];
#ifndef USE_ASTAR #ifndef USE_ASTAR
// プライオリティキューに格納されている最短距離が,現在計算できている最短距離より大きければ,distの更新をする必要はない // プライオリティキューに格納されている最短距離が,現在計算できている最短距離より大きければ,distの更新をする必要はない
if (dist_src < prov_cost) { if (dist_src < prov_cost) {
continue; continue;
} }
#endif #endif
// PQの先頭がゴールの場合にPQがまだ空じゃなくても探索終わらせしまう // PQの先頭がゴールの場合にPQがまだ空じゃなくても探索終わらせしまう
if (src == goal) { if (src == goal) {
break; break;
} }
// 隣接する他の頂点の探索 // 隣接する他の頂点の探索
// (0) コスト // (0) コスト
ap_uint<8> cost = w[src]; ap_uint<8> cost = w[src];
// (1) ノードIDから3次元座標をマスクして抜き出す // (1) ノードIDから3次元座標をマスクして抜き出す
ap_uint<13> src_xy = (ap_uint<13>)(src >> BITWIDTH_Z); ap_uint<13> src_xy = (ap_uint<13>)(src >> BITWIDTH_Z);
ap_uint<7> src_x = (ap_uint<7>)(src_xy / MAX_WIDTH); ap_uint<7> src_x = (ap_uint<7>)(src_xy / MAX_WIDTH);
ap_uint<7> src_y = (ap_uint<7>)(src_xy - src_x * MAX_WIDTH); ap_uint<7> src_y = (ap_uint<7>)(src_xy - src_x * MAX_WIDTH);
ap_uint<3> src_z = (ap_uint<3>)(src & BITMASK_Z); ap_uint<3> src_z = (ap_uint<3>)(src & BITMASK_Z);
//cout << src << " " << src_x << " " << src_y << " " << src_z << endl; //cout << src << " " << src_x << " " << src_y << " " << src_z << endl;
// (2) 3次元座標で隣接するノード (6個) を調べる // 手動ループ展開 // (2) 3次元座標で隣接するノード (6個) を調べる // 手動ループ展開
/*********************************************************** /***********************************************************
if (src_x > 0) { // x-を調査 if (src_x > 0) { // x-を調査
ap_uint<16> dest = (((ap_uint<16>)(src_x-1) * MAX_WIDTH + (ap_uint<16>)(src_y)) << BITWIDTH_Z) | (ap_uint<16>)(src_z); ap_uint<16> dest = (((ap_uint<16>)(src_x-1) * MAX_WIDTH + (ap_uint<16>)(src_y)) << BITWIDTH_Z) | (ap_uint<16>)(src_z);
ap_uint<16> dist_new = dist_src + cost; ap_uint<16> dist_new = dist_src + cost;
if (dist[dest] > dist_new) { if (dist[dest] > dist_new) {
dist[dest] = dist_new; // distの更新 dist[dest] = dist_new; // distの更新
prev[dest] = src; // 前の頂点を記録 prev[dest] = src; // 前の頂点を記録
dist_new += abs_uint7(src_x-1, goal_x) + abs_uint7(src_y, goal_y) + abs_uint3(src_z, goal_z); // A* ヒューリスティック dist_new += abs_uint7(src_x-1, goal_x) + abs_uint7(src_y, goal_y) + abs_uint3(src_z, goal_z); // A* ヒューリスティック
pq_push(dist_new, dest, &pq_len, pq_nodes); // キューに新たな仮の距離の情報をpush pq_push(dist_new, dest, &pq_len, pq_nodes); // キューに新たな仮の距離の情報をpush
} }
} }
if (src_x < (size_x-1)) { // x+を調査 if (src_x < (size_x-1)) { // x+を調査
ap_uint<16> dest = (((ap_uint<16>)(src_x+1) * MAX_WIDTH + (ap_uint<16>)(src_y)) << BITWIDTH_Z) | (ap_uint<16>)(src_z); ap_uint<16> dest = (((ap_uint<16>)(src_x+1) * MAX_WIDTH + (ap_uint<16>)(src_y)) << BITWIDTH_Z) | (ap_uint<16>)(src_z);
ap_uint<16> dist_new = dist_src + cost; ap_uint<16> dist_new = dist_src + cost;
if (dist[dest] > dist_new) { if (dist[dest] > dist_new) {
dist[dest] = dist_new; // distの更新 dist[dest] = dist_new; // distの更新
prev[dest] = src; // 前の頂点を記録 prev[dest] = src; // 前の頂点を記録
dist_new += abs_uint7(src_x+1, goal_x) + abs_uint7(src_y, goal_y) + abs_uint3(src_z, goal_z); // A* ヒューリスティック dist_new += abs_uint7(src_x+1, goal_x) + abs_uint7(src_y, goal_y) + abs_uint3(src_z, goal_z); // A* ヒューリスティック
pq_push(dist_new, dest, &pq_len, pq_nodes); // キューに新たな仮の距離の情報をpush pq_push(dist_new, dest, &pq_len, pq_nodes); // キューに新たな仮の距離の情報をpush
} }
} }
if (src_y > 0) { // y-を調査 if (src_y > 0) { // y-を調査
ap_uint<16> dest = (((ap_uint<16>)(src_x) * MAX_WIDTH + (ap_uint<16>)(src_y-1)) << BITWIDTH_Z) | (ap_uint<16>)(src_z); ap_uint<16> dest = (((ap_uint<16>)(src_x) * MAX_WIDTH + (ap_uint<16>)(src_y-1)) << BITWIDTH_Z) | (ap_uint<16>)(src_z);
ap_uint<16> dist_new = dist_src + cost; ap_uint<16> dist_new = dist_src + cost;
if (dist[dest] > dist_new) { if (dist[dest] > dist_new) {
dist[dest] = dist_new; // distの更新 dist[dest] = dist_new; // distの更新
prev[dest] = src; // 前の頂点を記録 prev[dest] = src; // 前の頂点を記録
dist_new += abs_uint7(src_x, goal_x) + abs_uint7(src_y-1, goal_y) + abs_uint3(src_z, goal_z); // A* ヒューリスティック dist_new += abs_uint7(src_x, goal_x) + abs_uint7(src_y-1, goal_y) + abs_uint3(src_z, goal_z); // A* ヒューリスティック
pq_push(dist_new, dest, &pq_len, pq_nodes); // キューに新たな仮の距離の情報をpush pq_push(dist_new, dest, &pq_len, pq_nodes); // キューに新たな仮の距離の情報をpush
} }
} }
if (src_y < (size_y-1)) { // y+を調査 if (src_y < (size_y-1)) { // y+を調査
ap_uint<16> dest = (((ap_uint<16>)(src_x) * MAX_WIDTH + (ap_uint<16>)(src_y+1)) << BITWIDTH_Z) | (ap_uint<16>)(src_z); ap_uint<16> dest = (((ap_uint<16>)(src_x) * MAX_WIDTH + (ap_uint<16>)(src_y+1)) << BITWIDTH_Z) | (ap_uint<16>)(src_z);
ap_uint<16> dist_new = dist_src + cost; ap_uint<16> dist_new = dist_src + cost;
if (dist[dest] > dist_new) { if (dist[dest] > dist_new) {
dist[dest] = dist_new; // distの更新 dist[dest] = dist_new; // distの更新
prev[dest] = src; // 前の頂点を記録 prev[dest] = src; // 前の頂点を記録
dist_new += abs_uint7(src_x, goal_x) + abs_uint7(src_y+1, goal_y) + abs_uint3(src_z, goal_z); // A* ヒューリスティック dist_new += abs_uint7(src_x, goal_x) + abs_uint7(src_y+1, goal_y) + abs_uint3(src_z, goal_z); // A* ヒューリスティック
pq_push(dist_new, dest, &pq_len, pq_nodes); // キューに新たな仮の距離の情報をpush pq_push(dist_new, dest, &pq_len, pq_nodes); // キューに新たな仮の距離の情報をpush
} }
} }
if (src_z > 0) { // z-を調査 if (src_z > 0) { // z-を調査
ap_uint<16> dest = (((ap_uint<16>)(src_x) * MAX_WIDTH + (ap_uint<16>)(src_y)) << BITWIDTH_Z) | (ap_uint<16>)(src_z-1); ap_uint<16> dest = (((ap_uint<16>)(src_x) * MAX_WIDTH + (ap_uint<16>)(src_y)) << BITWIDTH_Z) | (ap_uint<16>)(src_z-1);
ap_uint<16> dist_new = dist_src + cost; ap_uint<16> dist_new = dist_src + cost;
if (dist[dest] > dist_new) { if (dist[dest] > dist_new) {
dist[dest] = dist_new; // distの更新 dist[dest] = dist_new; // distの更新
prev[dest] = src; // 前の頂点を記録 prev[dest] = src; // 前の頂点を記録
dist_new += abs_uint7(src_x, goal_x) + abs_uint7(src_y, goal_y) + abs_uint3(src_z-1, goal_z); // A* ヒューリスティック dist_new += abs_uint7(src_x, goal_x) + abs_uint7(src_y, goal_y) + abs_uint3(src_z-1, goal_z); // A* ヒューリスティック
pq_push(dist_new, dest, &pq_len, pq_nodes); // キューに新たな仮の距離の情報をpush pq_push(dist_new, dest, &pq_len, pq_nodes); // キューに新たな仮の距離の情報をpush
} }
} }
if (src_z < (size_z-1)) { // y+を調査 if (src_z < (size_z-1)) { // y+を調査
ap_uint<16> dest = (((ap_uint<16>)(src_x) * MAX_WIDTH + (ap_uint<16>)(src_y)) << BITWIDTH_Z) | (ap_uint<16>)(src_z+1); ap_uint<16> dest = (((ap_uint<16>)(src_x) * MAX_WIDTH + (ap_uint<16>)(src_y)) << BITWIDTH_Z) | (ap_uint<16>)(src_z+1);
ap_uint<16> dist_new = dist_src + cost; ap_uint<16> dist_new = dist_src + cost;
if (dist[dest] > dist_new) { if (dist[dest] > dist_new) {
dist[dest] = dist_new; // distの更新 dist[dest] = dist_new; // distの更新
prev[dest] = src; // 前の頂点を記録 prev[dest] = src; // 前の頂点を記録
dist_new += abs_uint7(src_x, goal_x) + abs_uint7(src_y, goal_y) + abs_uint3(src_z+1, goal_z); // A* ヒューリスティック dist_new += abs_uint7(src_x, goal_x) + abs_uint7(src_y, goal_y) + abs_uint3(src_z+1, goal_z); // A* ヒューリスティック
pq_push(dist_new, dest, &pq_len, pq_nodes); // キューに新たな仮の距離の情報をpush pq_push(dist_new, dest, &pq_len, pq_nodes); // キューに新たな仮の距離の情報をpush
} }
} }
***********************************************************/ ***********************************************************/
...@@ -568,9 +568,9 @@ void search(ap_uint<8> *path_size, ap_uint<16> path[MAX_PATH], ap_uint<16> start ...@@ -568,9 +568,9 @@ void search(ap_uint<8> *path_size, ap_uint<16> path[MAX_PATH], ap_uint<16> start
for (ap_uint<3> a = 0; a < 6; a++) { for (ap_uint<3> a = 0; a < 6; a++) {
//#pragma HLS PIPELINE //#pragma HLS PIPELINE
//#pragma HLS UNROLL factor=2 //#pragma HLS UNROLL factor=2
ap_int<8> dest_x = (ap_int<8>)src_x; // 最小-1 最大72 (->符号付き8ビット) ap_int<8> dest_x = (ap_int<8>)src_x; // 最小-1 最大72 (->符号付き8ビット)
ap_int<8> dest_y = (ap_int<8>)src_y; // 最小-1 最大72 (->符号付き8ビット) ap_int<8> dest_y = (ap_int<8>)src_y; // 最小-1 最大72 (->符号付き8ビット)
ap_int<5> dest_z = (ap_int<5>)src_z; // 最小-1 最大8 (->符号付き5ビット) ap_int<5> dest_z = (ap_int<5>)src_z; // 最小-1 最大8 (->符号付き5ビット)
if (a == 0) { dest_x -= 1; } if (a == 0) { dest_x -= 1; }
if (a == 1) { dest_x += 1; } if (a == 1) { dest_x += 1; }
if (a == 2) { dest_y -= 1; } if (a == 2) { dest_y -= 1; }
...@@ -585,12 +585,12 @@ void search(ap_uint<8> *path_size, ap_uint<16> path[MAX_PATH], ap_uint<16> start ...@@ -585,12 +585,12 @@ void search(ap_uint<8> *path_size, ap_uint<16> path[MAX_PATH], ap_uint<16> start
//cout << " adjacent " << (int)dest << " (" << (int)dest_x << "," << (int)dest_y << "," << (int)dest_z << ") dist_new=" << (int)dist_new; //cout << " adjacent " << (int)dest << " (" << (int)dest_x << "," << (int)dest_y << "," << (int)dest_z << ") dist_new=" << (int)dist_new;
#endif #endif
if (dist[dest] > dist_new) { if (dist[dest] > dist_new) {
dist[dest] = dist_new; // distの更新 dist[dest] = dist_new; // distの更新
prev[dest] = src; // 前の頂点を記録 prev[dest] = src; // 前の頂点を記録
#ifdef USE_ASTAR #ifdef USE_ASTAR
dist_new += abs_uint7(dest_x, goal_x) + abs_uint7(dest_y, goal_y) + abs_uint3(dest_z, goal_z); // A* ヒューリスティック dist_new += abs_uint7(dest_x, goal_x) + abs_uint7(dest_y, goal_y) + abs_uint3(dest_z, goal_z); // A* ヒューリスティック
#endif #endif
pq_push(dist_new, dest, &pq_len, pq_nodes); // キューに新たな仮の距離の情報をpush pq_push(dist_new, dest, &pq_len, pq_nodes); // キューに新たな仮の距離の情報をpush
#ifdef DEBUG_PRINT #ifdef DEBUG_PRINT
//cout << " h=" << (int)(abs_uint7(dest_x, goal_x) + abs_uint7(dest_y, goal_y) + abs_uint3(dest_z, goal_z)) << endl; //cout << " h=" << (int)(abs_uint7(dest_x, goal_x) + abs_uint7(dest_y, goal_y) + abs_uint3(dest_z, goal_z)) << endl;
//cout << (int)dest_x << " " << (int)goal_x << " " << (int)abs_uint7(dest_x, goal_x) << endl; //cout << (int)dest_x << " " << (int)goal_x << " " << (int)abs_uint7(dest_x, goal_x) << endl;
...@@ -606,8 +606,8 @@ void search(ap_uint<8> *path_size, ap_uint<16> path[MAX_PATH], ap_uint<16> start ...@@ -606,8 +606,8 @@ void search(ap_uint<8> *path_size, ap_uint<16> path[MAX_PATH], ap_uint<16> start
} }
} }
// 経路を出力 // 経路を出力
// ゴールからスタートへの順番で表示される (ゴールとスタートは含まれない) // ゴールからスタートへの順番で表示される (ゴールとスタートは含まれない)
ap_uint<16> t = prev[goal]; ap_uint<16> t = prev[goal];
#ifdef DEBUG_PRINT #ifdef DEBUG_PRINT
...@@ -625,7 +625,7 @@ void search(ap_uint<8> *path_size, ap_uint<16> path[MAX_PATH], ap_uint<16> start ...@@ -625,7 +625,7 @@ void search(ap_uint<8> *path_size, ap_uint<16> path[MAX_PATH], ap_uint<16> start
<< "(" << dbg_goal_x << ", " << dbg_goal_y << ", " << dbg_goal_z << ") #" << goal << endl; << "(" << dbg_goal_x << ", " << dbg_goal_y << ", " << dbg_goal_z << ") #" << goal << endl;
#endif #endif
// バックトラック // バックトラック
ap_uint<8> p = 0; ap_uint<8> p = 0;
SEARCH_BACKTRACK: SEARCH_BACKTRACK:
while (t != start) { while (t != start) {
...@@ -640,10 +640,10 @@ void search(ap_uint<8> *path_size, ap_uint<16> path[MAX_PATH], ap_uint<16> start ...@@ -640,10 +640,10 @@ void search(ap_uint<8> *path_size, ap_uint<16> path[MAX_PATH], ap_uint<16> start
cout << " via " << "(" << t_x << ", " << t_y << ", " << t_z << ") #" << prev[t] << " dist=" << dist[t] << endl; cout << " via " << "(" << t_x << ", " << t_y << ", " << t_z << ") #" << prev[t] << " dist=" << dist[t] << endl;
#endif #endif
path[p] = t; // 記録 path[p] = t; // 記録
p++; p++;
t = prev[t]; // 次に移動 t = prev[t]; // 次に移動
} }
*path_size = p; *path_size = p;
...@@ -654,29 +654,29 @@ void search(ap_uint<8> *path_size, ap_uint<16> path[MAX_PATH], ap_uint<16> start ...@@ -654,29 +654,29 @@ void search(ap_uint<8> *path_size, ap_uint<16> path[MAX_PATH], ap_uint<16> start
} }
// プライオリティ・キュー (ヒープで実装) // プライオリティ・キュー (ヒープで実装)
// 優先度の最小値がヒープのルートに来る // 優先度の最小値がヒープのルートに来る
// 参考 // 参考
// * ヒープ - Wikipedia https://ja.wikipedia.org/wiki/%E3%83%92%E3%83%BC%E3%83%97 // * ヒープ - Wikipedia https://ja.wikipedia.org/wiki/%E3%83%92%E3%83%BC%E3%83%97
// * 二分ヒープ - Wikipedia https://ja.wikipedia.org/wiki/%E4%BA%8C%E5%88%86%E3%83%92%E3%83%BC%E3%83%97 // * 二分ヒープ - Wikipedia https://ja.wikipedia.org/wiki/%E4%BA%8C%E5%88%86%E3%83%92%E3%83%BC%E3%83%97
// * ヒープの正体 - http://www.maroontress.com/Heap/ // * ヒープの正体 - http://www.maroontress.com/Heap/
// * Priority queue - Rosetta Code https://rosettacode.org/wiki/Priority_queue#C // * Priority queue - Rosetta Code https://rosettacode.org/wiki/Priority_queue#C
// Note // Note
// インデックスが0から始まるとき (0-origin index) // インデックスが0から始まるとき (0-origin index)
// --> 親: (n-1)/2, 左の子: 2n+1, 右の子: 2n+2 // --> 親: (n-1)/2, 左の子: 2n+1, 右の子: 2n+2
// インデックスが1から始まるとき (1-origin index) // インデックスが1から始まるとき (1-origin index)
// --> 親: n/2, 左の子: 2n, 右の子: 2n+1 // --> 親: n/2, 左の子: 2n, 右の子: 2n+1
// FPGA的にはどちらも遅延は同じだけど 1-origin の方がLUTリソース少なくて済む (ただし配列の0要素が無駄になる) // FPGA的にはどちらも遅延は同じだけど 1-origin の方がLUTリソース少なくて済む (ただし配列の0要素が無駄になる)
// ノードの挿入は,末尾に追加してから優先度が正しい高さの位置までノードを上げていく // ノードの挿入は,末尾に追加してから優先度が正しい高さの位置までノードを上げていく
// 探索の都合上,同じ優先度では後から入れた方を先に出したいから, // 探索の都合上,同じ優先度では後から入れた方を先に出したいから,
// ループの終了条件は挿入ノードの優先度が比較対象の優先度よりも小さくなったとき // ループの終了条件は挿入ノードの優先度が比較対象の優先度よりも小さくなったとき
void pq_push(ap_uint<16> priority, ap_uint<16> data, ap_uint<12> *pq_len, ap_uint<32> pq_nodes[MAX_PQ]) { void pq_push(ap_uint<16> priority, ap_uint<16> data, ap_uint<12> *pq_len, ap_uint<32> pq_nodes[MAX_PQ]) {
#pragma HLS INLINE #pragma HLS INLINE
(*pq_len)++; (*pq_len)++;
ap_uint<12> i = (*pq_len); // target ap_uint<12> i = (*pq_len); // target
ap_uint<12> p = (*pq_len) >> 1; // i.e., (*pq_len) / 2; // ap_uint<12> p = (*pq_len) >> 1; // i.e., (*pq_len) / 2; //
PQ_PUSH_LOOP: PQ_PUSH_LOOP:
while (i > 1 && (ap_uint<16>)(pq_nodes[p] & PQ_PRIORITY_MASK) >= priority) { while (i > 1 && (ap_uint<16>)(pq_nodes[p] & PQ_PRIORITY_MASK) >= priority) {
#pragma HLS LOOP_TRIPCOUNT min=1 max=8 avg=4 #pragma HLS LOOP_TRIPCOUNT min=1 max=8 avg=4
...@@ -684,16 +684,16 @@ void pq_push(ap_uint<16> priority, ap_uint<16> data, ap_uint<12> *pq_len, ap_uin ...@@ -684,16 +684,16 @@ void pq_push(ap_uint<16> priority, ap_uint<16> data, ap_uint<12> *pq_len, ap_uin
//#pragma HLS UNROLL factor=2 //#pragma HLS UNROLL factor=2
pq_nodes[i] = pq_nodes[p]; pq_nodes[i] = pq_nodes[p];
i = p; i = p;
p = p >> 1; // i.e., p / 2; // p = p >> 1; // i.e., p / 2; //
} }
pq_nodes[i] = ((ap_uint<32>)data << 16) | (ap_uint<32>)priority; pq_nodes[i] = ((ap_uint<32>)data << 16) | (ap_uint<32>)priority;
} }
// ノードの取り出しは,ルートを取ってくるだけ // ノードの取り出しは,ルートを取ってくるだけ
// 次に最小の優先度をもつノードをルートに移動させるために, // 次に最小の優先度をもつノードをルートに移動させるために,
// まず,末尾のノードをルートに移動する // まず,末尾のノードをルートに移動する
// 両方の子で優先度が小さい方を上にもっていく (ルートを適切な高さまで下げる) // 両方の子で優先度が小さい方を上にもっていく (ルートを適切な高さまで下げる)
// これを再帰的に繰り返す // これを再帰的に繰り返す
void pq_pop(ap_uint<16> *ret_priority, ap_uint<16> *ret_data, ap_uint<12> *pq_len, ap_uint<32> pq_nodes[MAX_PQ]) { void pq_pop(ap_uint<16> *ret_priority, ap_uint<16> *ret_data, ap_uint<12> *pq_len, ap_uint<32> pq_nodes[MAX_PQ]) {
#pragma HLS INLINE #pragma HLS INLINE
...@@ -701,18 +701,18 @@ void pq_pop(ap_uint<16> *ret_priority, ap_uint<16> *ret_data, ap_uint<12> *pq_le ...@@ -701,18 +701,18 @@ void pq_pop(ap_uint<16> *ret_priority, ap_uint<16> *ret_data, ap_uint<12> *pq_le
*ret_data = (ap_uint<16>)(pq_nodes[1] >> PQ_PRIORITY_WIDTH); *ret_data = (ap_uint<16>)(pq_nodes[1] >> PQ_PRIORITY_WIDTH);
//pq_nodes[1] = pq_nodes[*pq_len]; //pq_nodes[1] = pq_nodes[*pq_len];
ap_uint<12> i = 1; // 親ノード ap_uint<12> i = 1; // 親ノード
//ap_uint<12> t = 1; // 交換対象ノード //ap_uint<12> t = 1; // 交換対象ノード
ap_uint<16> last_priority = (ap_uint<16>)(pq_nodes[*pq_len] & PQ_PRIORITY_MASK); // 末尾ノードの優先度 ap_uint<16> last_priority = (ap_uint<16>)(pq_nodes[*pq_len] & PQ_PRIORITY_MASK); // 末尾ノードの優先度
PQ_POP_LOOP: PQ_POP_LOOP:
while (1) { while (1) {
#pragma HLS LOOP_TRIPCOUNT min=1 max=8 avg=4 #pragma HLS LOOP_TRIPCOUNT min=1 max=8 avg=4
//#pragma HLS PIPELINE //#pragma HLS PIPELINE
//#pragma HLS UNROLL factor=2 //#pragma HLS UNROLL factor=2
ap_uint<12> c1 = i << 1; // i.e., 2 * i; // 左の子 ap_uint<12> c1 = i << 1; // i.e., 2 * i; // 左の子
ap_uint<12> c2 = c1 + 1; // i.e., 2 * i + 1; // 右の子 ap_uint<12> c2 = c1 + 1; // i.e., 2 * i + 1; // 右の子
if (c1 < *pq_len && (ap_uint<16>)(pq_nodes[c1] & PQ_PRIORITY_MASK) <= last_priority) { if (c1 < *pq_len && (ap_uint<16>)(pq_nodes[c1] & PQ_PRIORITY_MASK) <= last_priority) {
if (c2 < *pq_len && (ap_uint<16>)(pq_nodes[c2] & PQ_PRIORITY_MASK) <= (ap_uint<16>)(pq_nodes[c1] & PQ_PRIORITY_MASK)) { if (c2 < *pq_len && (ap_uint<16>)(pq_nodes[c2] & PQ_PRIORITY_MASK) <= (ap_uint<16>)(pq_nodes[c1] & PQ_PRIORITY_MASK)) {
pq_nodes[i] = pq_nodes[c2]; pq_nodes[i] = pq_nodes[c2];
......
...@@ -13,33 +13,33 @@ ...@@ -13,33 +13,33 @@
#include <ap_int.h> #include <ap_int.h>
#endif #endif
//#define DEBUG_PRINT // いろいろ表示する //#define DEBUG_PRINT // いろいろ表示する
#define USE_ASTAR // A* 探索を使う #define USE_ASTAR // A* 探索を使う
#define USE_MOD_CALC // ターゲットラインの選択に剰余演算を用いる #define USE_MOD_CALC // ターゲットラインの選択に剰余演算を用いる
using namespace std; using namespace std;
// 各種設定値 // 各種設定値
#define MAX_WIDTH 72 // X, Y の最大値 (7ビットで収まる) #define MAX_WIDTH 72 // X, Y の最大値 (7ビットで収まる)
#define BITWIDTH_XY 13 #define BITWIDTH_XY 13
#define BITMASK_XY 65528 // 1111 1111 1111 1000 #define BITMASK_XY 65528 // 1111 1111 1111 1000
#define MAX_LAYER 8 // Z の最大値 (3ビット) #define MAX_LAYER 8 // Z の最大値 (3ビット)
#define BITWIDTH_Z 3 #define BITWIDTH_Z 3
#define BITMASK_Z 7 // 0000 0000 0000 0111 #define BITMASK_Z 7 // 0000 0000 0000 0111
#define MAX_CELLS 41472 // セルの総数 =72*72*8 (16ビットで収まる) #define MAX_CELLS 41472 // セルの総数 =72*72*8 (16ビットで収まる)
#define MAX_LINES 128 // ライン数の最大値 (7ビット) #define MAX_LINES 128 // ライン数の最大値 (7ビット)
#define MAX_PATH 256 // 1つのラインが対応するセル数の最大値 (8ビット) #define MAX_PATH 256 // 1つのラインが対応するセル数の最大値 (8ビット)
#define MAX_PQ 4096 // 探索時のプライオリティ・キューの最大サイズ (12ビット) 足りないかも? #define MAX_PQ 4096 // 探索時のプライオリティ・キューの最大サイズ (12ビット) 足りないかも?
#define PQ_PRIORITY_WIDTH 16 #define PQ_PRIORITY_WIDTH 16
#define PQ_PRIORITY_MASK 65535 // 0000 0000 0000 0000 1111 1111 1111 1111 #define PQ_PRIORITY_MASK 65535 // 0000 0000 0000 0000 1111 1111 1111 1111
#define PQ_DATA_WIDTH 16 #define PQ_DATA_WIDTH 16
#define PQ_DATA_MASK 4294901760 // 1111 1111 1111 1111 0000 0000 0000 0000 #define PQ_DATA_MASK 4294901760 // 1111 1111 1111 1111 0000 0000 0000 0000
#define MAX_WEIGHT 255 // 重みの最大値 (8ビットで収まる) #define MAX_WEIGHT 255 // 重みの最大値 (8ビットで収まる)
#define BOARDSTR_SIZE 41472 // ボードストリングの最大文字数 (セル数 72*72*8 あれば良い) #define BOARDSTR_SIZE 41472 // ボードストリングの最大文字数 (セル数 72*72*8 あれば良い)
void lfsr_random_init(ap_uint<32> seed); void lfsr_random_init(ap_uint<32> seed);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment