diff --git a/CMakeLists.txt b/CMakeLists.txt index 2a7f45e3..d4bc8676 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,7 +15,7 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0 -g -fsanitize=address -fno-inline -D # "-fsanitize=address" flag was used to check the stack smashing with Google Address Sanitizer. Use this flag with CLang and # run the program to check. -set(DP_HLS_HOME "/home/centos/workspace/DP-HLS") +set(DP_HLS_HOME "/home/centos/workspace/banding/DP-HLS") set(EXECUTABLE_TARGETS baseline_local_linear diff --git a/include/PE.h b/include/PE.h index 9e270166..b7ef46ce 100644 --- a/include/PE.h +++ b/include/PE.h @@ -65,8 +65,6 @@ namespace PE const dp_mem_block_t dp_mem, const input_char_block_t qry, const input_char_block_t ref, - const bool entering, const bool exiting, - const idx_t entering_pe, const idx_t exiting_pe, const Penalties penalties, wavefront_scores_inf_t &score, tbp_vec_t &tbp); diff --git a/include/align.h b/include/align.h index 69acbc27..f871d187 100644 --- a/include/align.h +++ b/include/align.h @@ -349,9 +349,9 @@ namespace Align const chunk_col_scores_inf_t &init_col_scr, score_vec_t (&init_row_scr)[MAX_REFERENCE_LENGTH], idx_t p_cols, const idx_t ck_idx, - const idx_t (&local_l_lim)[PE_NUM], const idx_t (&local_u_lim)[PE_NUM], + idx_t &l_lim_reg, idx_t &u_lim_reg, const bool (&col_pred)[PE_NUM], - const idx_t global_query_length, const idx_t reference_length, + const idx_t global_query_length, const idx_t local_query_length, const idx_t reference_length, const Penalties &penalties, ScorePack (&max)[PE_NUM], // write out so must pass by reference tbp_t (&chunk_tbp_out)[PE_NUM][TBMEM_SIZE] @@ -401,10 +401,8 @@ namespace Align void PrepareLocals( const char_t (&query)[MAX_QUERY_LENGTH_], const score_vec_t (&init_col_scr)[MAX_QUERY_LENGTH_], - const idx_t (&l_lim)[MAX_QUERY_LENGTH_], const idx_t (&u_lim)[MAX_QUERY_LENGTH_], char_t (&local_query)[PE_NUM_], chunk_col_scores_inf_t &init_col_scr_local, - idx_t (&local_l_lim)[PE_NUM_], idx_t (&local_u_lim)[PE_NUM_], bool (&col_pred)[PE_NUM_], const idx_t local_query_len, const idx_t idx) { @@ -415,8 +413,6 @@ namespace Align init_col_scr_local[i + 1] = init_col_scr[idx + i]; local_query[i] = query[idx + i]; col_pred[i] = i < local_query_len; - local_l_lim[i] = l_lim[idx + i]; - local_u_lim[i] = u_lim[idx + i]; } } } diff --git a/include/debug.h b/include/debug.h index 4acdd2f5..d013e2dd 100644 --- a/include/debug.h +++ b/include/debug.h @@ -9,6 +9,7 @@ #include #include // #include +#include #include #include #include @@ -36,6 +37,27 @@ class Container { array, MAX_QUERY_LENGTH> tb_mat_kernel; array, MAX_QUERY_LENGTH> tb_mat_cpp; // this need to be translated + std::map, std::array, PE_NUM+1>, 2>> wf_dp_mem; + std::map, std::array> wf_predicates; + + struct score_info { + float up[N_LAYERS]; + float left[N_LAYERS]; + float diag[N_LAYERS]; + float write[N_LAYERS]; + bool pred; + bool exiting; + bool entering; + int entering_pe; + int exiting_pe; + }; + + /** + * @brief Record the information of scores, with their coordinate as the index + * + */ + std::map, score_info> scores_infos; + Container() {}; void cast_scores(); @@ -45,6 +67,78 @@ class Container { void set_score(int chunk_row_offset, int chunk_col_offset, int pe_num, int wavefront, score_vec_t vals, bool pred); void set_scores_wf(int chunk_row_offset, int chunk_col_offset, int wavefront, score_vec_t vals[PE_NUM], bool predicates[PE_NUM]); + + template + void set_wf_dp_mem(IDX_T ck_idx, IDX_T wf_idx, dp_mem_block_t dp_mem){ + array, PE_NUM+1>, 2> store_dp_mem; + for (int i = 0; i < PE_NUM+1; i++){ + for (int j = 0; j < 2; j++){ + for (int k = 0; k < N_LAYERS; k++){ + store_dp_mem[j][i][k] = dp_mem[i][j][k]; + } + } + } + wf_dp_mem[std::make_pair(ck_idx, wf_idx)] = store_dp_mem; + } + + template + void set_score_info_dependency(IDX_T chunk_offset, IDX_T wf_idx, dp_mem_block_t dp_mem){ + for (int i = 0; i < PE_NUM; i++){ + score_info curr_info; + scores_infos[std::make_pair(chunk_offset + i, wf_idx - i)] = curr_info; + for (int k = 0; k < N_LAYERS; k++){ + scores_infos[std::make_pair(chunk_offset + i, wf_idx - i)].up[k] = dp_mem[i][0][k]; + scores_infos[std::make_pair(chunk_offset + i, wf_idx - i)].left[k] = dp_mem[i+1][0][k]; + scores_infos[std::make_pair(chunk_offset + i, wf_idx - i)].diag[k] = dp_mem[i][1][k]; + } + + } + } + + template + void set_score_info_entering_exiting(IDX_T chunk_offset, IDX_T wf_idx, bool entering, bool exiting, int entering_pe, int exiting_pe){ + for (int i = 0; i < PE_NUM; i++){ + scores_infos[std::make_pair(chunk_offset + i, wf_idx - i)].entering = entering; + scores_infos[std::make_pair(chunk_offset + i, wf_idx - i)].exiting = exiting; + scores_infos[std::make_pair(chunk_offset + i, wf_idx - i)].entering_pe = entering_pe; + scores_infos[std::make_pair(chunk_offset + i, wf_idx - i)].exiting_pe = exiting_pe; + } + } + + // function that dump scores infos to a debug file + template + void dump_scores_infos(ofstream &file){ + // dump scores, one cell per line + file << "Scores: " << endl; + for (const auto& kv : this->scores_infos) { + const std::pair& key = kv.first; + const score_info& value = kv.second; + for (int i = 0; i < N_LAYERS_; i++){ + file << "Coordinate: (" << key.first << ", " << key.second << "), Layer: " << i << + ", Up: " << value.up[i] << ", Left: " << value.left[i] << ", Diag: " << value.diag[i] << ", Pred: " << value.pred << ", "; + if (value.entering){ + file << "Entering PE: " << value.entering_pe << ", "; + } + if (value.exiting){ + file << "Exiting PE: " << value.exiting_pe << ", "; + } + file << endl; + } + } + +} + // set score info predicate + template + void set_score_info_predicates(IDX_T ck_offset, IDX_T wf_idx, bool preds[PE_NUM]){ + for (int i = 0; i < PE_NUM; i++){ + this->scores_infos[std::make_pair(ck_offset + i, wf_idx-i)].pred = preds[i]; + } + } + + // template + // void dump_tb_info(ofstream &file){ + + // } void compare_scores(array, MAX_QUERY_LENGTH>, N_LAYERS> scores_sol, int query_len, int ref_len); diff --git a/include/solutions.h b/include/solutions.h index 33f1442d..349e9308 100644 --- a/include/solutions.h +++ b/include/solutions.h @@ -341,8 +341,8 @@ void fixed_banding_global_linear_solution(std::string query, std::string referen int llim[SOL_MAX_QUERY_LENGTH], ulim[SOL_MAX_QUERY_LENGTH]; for (int i = 0; i < SOL_MAX_QUERY_LENGTH; i++) { - llim[i] = max(0, i - SOL_BANDWIDTH); - ulim[i] = min(SOL_MAX_REFERENCE_LENGTH - 1, i + SOL_BANDWIDTH - 1); + llim[i] = i - SOL_BANDWIDTH; + ulim[i] = i + SOL_BANDWIDTH - 1; } // print ulim @@ -2636,7 +2636,7 @@ void fprint_matrix(ofstream &file, array, M> &mat, string name) template void fprint_matrix(ofstream &file, array, M> &mat, string query, string reference, string name) { - int width = 2; + int width = 3; file << name << endl; file << std::right << std::setw(width) << " "; file << std::right << std::setw(width) << " "; diff --git a/include/traceback.h b/include/traceback.h index 9f049332..c57cb3f0 100644 --- a/include/traceback.h +++ b/include/traceback.h @@ -115,6 +115,14 @@ namespace Traceback int ck_idx, int pe_idx, int col_idx, int v_row, int v_col) { +#ifdef CMAKEDEBUG + // set the initial state of the traceback to be AL_END + for (int i = 0; i < MAX_QUERY_LENGTH + MAX_REFERENCE_LENGTH; i++) + { + traceback_out[i] = AL_END; + } +#endif + #pragma HLS bind_storage variable = traceback_out type = fifo impl = uram int pe = pe_idx; // row index, but in tbmat int col = col_idx; @@ -126,6 +134,26 @@ namespace Traceback TB_STATE state; ALIGN_TYPE::Traceback::StateInit(tbmat[pe][col], state); +#ifdef CMAKEDEBUG + // print the content fo tbmat + // Please print it with certain width for the first row, which is the index + + for (int j = 0; j < TBMEM_SIZE; j++) + { + std::cout << std::setw(3) << j << " "; + } + std::cout << std::endl; + for (int i = 0; i < PE_NUM; i++) + { + for (int j = 0; j < TBMEM_SIZE; j++) + { + std::cout << std::setw(3) << tbmat[i][j].to_int() << " "; + } + std::cout << std::endl; + } + std::cout << std::endl; +#endif + traceback_loop: while (navigation != AL_END) // Now solely this flag determines whether to stop the traceback. { diff --git a/kernels/banding_global_linear/kernel_banding_global_linear.cpp b/kernels/banding_global_linear/kernel_banding_global_linear.cpp index 59830d1e..8d6763c3 100644 --- a/kernels/banding_global_linear/kernel_banding_global_linear.cpp +++ b/kernels/banding_global_linear/kernel_banding_global_linear.cpp @@ -77,19 +77,19 @@ void BandingGlobalLinear::UpdatePEMaximum( const bool (&predicate)[PE_NUM], const idx_t query_len, const idx_t ref_len) { - for (int i = 0; i < PE_NUM; i++) - { -#pragma HLS unroll - if (predicate[i] && chunk_row_offset + i == query_len - 1 && wavefront - i == ref_len - 1) - { - if (max[i].score < scores[i + 1][0]) - { - max[i].score = scores[i + 1][0]; - max[i].p_col = p_cols; - max[i].ck = ck_idx; - } - } - } +// for (int i = 0; i < PE_NUM; i++) +// { +// #pragma HLS unroll +// if (predicate[i] && chunk_row_offset + i == query_len - 1 && wavefront - i == ref_len - 1) +// { +// if (max[i].score < scores[i + 1][0]) +// { +// max[i].score = scores[i + 1][0]; +// max[i].p_col = p_cols; +// max[i].ck = ck_idx; +// } +// } +// } } void BandingGlobalLinear::InitializeMaxScores(ScorePack (&max)[PE_NUM], idx_t qry_len, idx_t ref_len) @@ -102,11 +102,16 @@ void BandingGlobalLinear::InitializeMaxScores(ScorePack (&max)[PE_NUM], idx_t qr max[i].ck = 0; } - // idx_t max_pe = (qry_len - 1) % PE_NUM; - // idx_t max_ck = (qry_len - 1) / PE_NUM; - // max[max_pe].score = INF; - // max[max_pe].p_col = max_ck * (2 * BANDWIDTH + PE_NUM - 1 + PE_NUM - 1) + max_pe + ref_len - 1; - // max[max_pe].ck = max_ck; + idx_t max_pe = (qry_len - 1) % PE_NUM; + idx_t max_ck = (qry_len - 1) / PE_NUM; + max[max_pe].score = INF; + std::cout << "Magic Number: " << ( max_ck * PE_NUM - BANDWIDTH ) << std::endl; + max[max_pe].p_col = max_ck * (TB_CHUNK_WIDTH) + max_pe + ref_len - ( max_ck * PE_NUM - BANDWIDTH ) - 1; // FIXME: Problemmatic, the problem is that the last chunk doesn't have length ref_len. + max[max_pe].ck = max_ck; +#ifdef CMAKEDEBUG + std::cout << "Physical Column" << max[max_pe].p_col << std::endl; + +#endif } void BandingGlobalLinear::Traceback::StateInit(tbp_t tbp, TB_STATE &state) diff --git a/kernels/banding_global_linear/params.h b/kernels/banding_global_linear/params.h index 3b13890d..1b56af9e 100644 --- a/kernels/banding_global_linear/params.h +++ b/kernels/banding_global_linear/params.h @@ -4,13 +4,18 @@ #include #include -#define MAX_QUERY_LENGTH 32 -#define MAX_REFERENCE_LENGTH 32 +#define MAX_QUERY_LENGTH 256 +#define MAX_REFERENCE_LENGTH 256 + + +#define INPUT_QUERY_LENGTH 256 +#define INPUT_REFERENCE_LENGTH 256 + #define ALIGN_TYPE BandingGlobalLinear #define N_BLOCKS 1 #define N_LAYERS 1 -const int PE_NUM = 8; +const int PE_NUM = 16; #define LAYER_MAXIMIUM 0 // We need to indicate from which layer (main matrix) is the maximum score stored. #define BANDING FIXED @@ -19,7 +24,7 @@ const int PE_NUM = 8; // Primitive Types typedef ap_uint<2> char_t; // Sequence Alphabet typedef ap_fixed<16, 12> type_t; // Scores Type -typedef short idx_t; // Indexing Type, could be much less than 32. ap_uint<8> +typedef int idx_t; // Indexing Type, could be much less than 32. ap_uint<8> typedef ap_uint<2> tbp_t; // Traceback Pointer Type // Define Zero Value @@ -35,8 +40,7 @@ typedef ap_uint<2> tbp_t; // Traceback Pointer Type #define TB_DIAG (tbp_t) 0b10 #define TB_UP (tbp_t) 0b11 -// Legacy Debugger Configuration -#define DEBUG_OUTPUT_FILE "/home/centos/workspace/DP-HLS/banding_global_linear_out.txt" +#define DEBUG_OUTPUT_FILE "/home/centos/workspace/banding/DP-HLS/banding_global_linear_out.txt" struct Penalties { type_t mismatch; diff --git a/src/align.cpp b/src/align.cpp index d62578da..c348f0e3 100644 --- a/src/align.cpp +++ b/src/align.cpp @@ -279,7 +279,7 @@ void Align::ArrangeTBP( for (int i = 0; i < PE_NUM; i++) { #pragma HLS unroll - chunk_tbp_out[i][p_col_offset] = tbp_in[i]; + if (predicate[i]) chunk_tbp_out[i][p_col_offset] = tbp_in[i]; } } @@ -533,13 +533,6 @@ void Align::Fixed::AlignStatic( #pragma HLS array_partition variable = tbp_matrix type = cyclic factor = PRAGMA_PE_NUM dim = 1 - idx_t l_lims[MAX_QUERY_LENGTH], u_lims[MAX_QUERY_LENGTH]; -#pragma HLS bind_storage variable = l_lims type = ram_1p impl = bram -#pragma HLS bind_storage variable = u_lims type = ram_1p impl = bram - - Align::Fixed::PrecomputeLowerLimits(l_lims); - Align::Fixed::PrecomputeUpperLimits(u_lims, reference_length); - #ifdef CMAKEDEBUG // print l_lims and u_lims // std::cout << "Lower limits: "; @@ -563,9 +556,10 @@ void Align::Fixed::AlignStatic( char_t local_query[PE_NUM]; chunk_col_scores_inf_t local_init_col_score; local_init_col_score[PE_NUM] = score_vec_t(0); // Always initialize the upper left cornor to 0 - idx_t local_l_lim[PE_NUM]; - idx_t local_u_lim[PE_NUM]; + bool col_pred[PE_NUM]; + idx_t l_lim_reg = -BANDWIDTH; + idx_t u_lim_reg = BANDWIDTH - 1; // we don't need to - 1 because the cell score is 0 only when it's out of the band #pragma HLS array_partition variable = local_query type = complete #pragma HLS array_partition variable = col_pred type = complete @@ -580,15 +574,13 @@ void Align::Fixed::AlignStatic( idx_t local_query_length = ((idx_t)PE_NUM < query_length - i) ? (idx_t)PE_NUM : (idx_t)(query_length - i); p_col = p_cols_internal_offset + p_col_offset; - p_cols_internal_offset = p_cols_internal_offset - PE_NUM > 0 ? p_cols_internal_offset - PE_NUM : 0; + p_cols_internal_offset = p_cols_internal_offset > (idx_t) PE_NUM ? p_cols_internal_offset - PE_NUM : 0; Align::Fixed::PrepareLocals( query, init_col_score, - l_lims, u_lims, local_query, local_init_col_score, - local_l_lim, local_u_lim, col_pred, local_query_length, i @@ -601,8 +593,9 @@ void Align::Fixed::AlignStatic( local_init_col_score, init_row_score, p_col, ic, - local_l_lim, local_u_lim, col_pred, - query_length, reference_length, + l_lim_reg, u_lim_reg, + col_pred, + query_length, local_query_length, reference_length, penalties, local_max, tbp_matrix @@ -621,12 +614,13 @@ void Align::Fixed::AlignStatic( // >>> Traceback >>> tb_i = maximum.ck * PE_NUM + max_pe; - tb_j = maximum.p_col - (maximum.ck) * TB_CHUNK_WIDTH - max_pe + l_lims[maximum.ck * PE_NUM]; + tb_j = maximum.p_col - (maximum.ck) * TB_CHUNK_WIDTH - max_pe + (PE_NUM * maximum.ck - BANDWIDTH); #ifdef CMAKEDEBUG // print tracevack start idx std::cout << "Traceback start idx: " << maximum.ck << " "<< tb_i << " " << tb_j << endl; std::cout << "Traceback start idx physical: " << max_pe << " " << maximum.p_col << endl; + std::cout << "First TBP: " << tbp_matrix[max_pe][maximum.p_col] << std::endl; #endif Traceback::TracebackFixedSize<2 * BANDWIDTH - 1>(tbp_matrix, tb_out, maximum.ck, max_pe, maximum.p_col, tb_i, tb_j); @@ -642,9 +636,9 @@ void Align::Fixed::ChunkCompute( const chunk_col_scores_inf_t &init_col_scr, score_vec_t (&init_row_scr)[MAX_REFERENCE_LENGTH], idx_t p_cols, const idx_t ck_idx, - const idx_t (&local_l_lim)[PE_NUM], const idx_t (&local_u_lim)[PE_NUM], + idx_t &l_lim_reg, idx_t &u_lim_reg, const bool (&col_pred)[PE_NUM], - const idx_t global_query_length, const idx_t reference_length, + const idx_t global_query_length, const idx_t local_query_length, const idx_t reference_length, const Penalties &penalties, ScorePack (&max)[PE_NUM], // write out so must pass by reference tbp_t (&chunk_tbp_out)[PE_NUM][TBMEM_SIZE] @@ -683,9 +677,8 @@ void Align::Fixed::ChunkCompute( #pragma HLS array_partition variable = tbp_out type = complete #pragma HLS array_partition variable = score_buff type = complete - const idx_t chunk_start_col = local_l_lim[0]; - const idx_t chunk_end_col = local_u_lim[PE_NUM - 1]; - + const idx_t chunk_start_col = l_lim_reg > 0 ? l_lim_reg : (idx_t) 0; + const idx_t chunk_end_col = u_lim_reg + PE_NUM - 1 <= reference_length - 1 ? u_lim_reg + PE_NUM - 1: reference_length - 1; idx_t entering_pe = 0; idx_t exiting_pe = 0; bool entering = false; @@ -698,10 +691,10 @@ void Align::Fixed::ChunkCompute( Utils::Init::ArrSet(exiting_shift, true); // Set the upper left corner cell of the chunk, depending whether it's the first chunk. - dp_mem[0][0] = local_l_lim[0] > 0 ? init_row_scr[chunk_start_col-1] : init_col_scr[0]; + dp_mem[0][0] = l_lim_reg > 0 ? init_row_scr[chunk_start_col-1] : init_col_scr[0]; Iterating_Wavefronts: - for (int i = chunk_start_col; i < chunk_end_col + PE_NUM; i++) + for (idx_t i = chunk_start_col; i < chunk_end_col + local_query_length; i++) { #pragma HLS pipeline II = 1 #pragma HLS dependence variable = init_row_scr type = inter direction = RAW false @@ -715,11 +708,11 @@ void Align::Fixed::ChunkCompute( init_row_scr_f.push_back((float) init_row_scr[j][0]); } #endif - - entering = (entering_pe < PE_NUM && local_l_lim[entering_pe] == i - entering_pe); - exiting = (exiting_pe < PE_NUM && local_u_lim[exiting_pe] == i - 1 - exiting_pe); + + entering = (entering_pe < PE_NUM && (l_lim_reg > 0 ? l_lim_reg : (idx_t) 0) == i - entering_pe); + exiting = (exiting_pe < PE_NUM && (u_lim_reg < reference_length ? u_lim_reg : reference_length) == i - exiting_pe); if (entering) Utils::Array::ShiftRight(entering_shift, true); - if (exiting) Utils::Array::ShiftRight(exiting_shift, false); + for (int j = 0; j < PE_NUM; j++) { @@ -727,20 +720,28 @@ void Align::Fixed::ChunkCompute( predicate[j] = col_pred[j] && entering_shift[j] && exiting_shift[j]; } - // if (entering) predicate[entering_pe] = true; - // if (exiting) predicate[exiting_pe] = false; - Utils::Array::ShiftRight(local_reference, i < MAX_REFERENCE_LENGTH ? reference[i] : ZERO_CHAR); Align::PrepareScoreBuffer(score_buff, i, init_col_scr, init_row_scr); + if (exiting) { + score_buff[exiting_pe] = score_vec_t(NINF); + } + if (entering) score_buff[entering_pe + 1] = l_lim_reg <= 0 ? init_col_scr[entering_pe + 1] : score_vec_t(NINF); + Align::UpdateDPMemSep(dp_mem, score_buff); + +#ifdef CMAKEDEBUG + debugger.set_wf_dp_mem(ck_idx, i, dp_mem); + debugger.set_score_info_dependency(chunk_row_offset, i, dp_mem); + debugger.set_score_info_predicates(chunk_row_offset, i, predicate); + debugger.set_score_info_entering_exiting(chunk_row_offset, i, entering, exiting, entering_pe, exiting_pe); +#endif + PE::PEUnrollFixedSep( dp_mem, local_query, local_reference, - entering, exiting, - entering_pe, exiting_pe, penalties, score_buff, tbp_out); @@ -765,10 +766,16 @@ void Align::Fixed::ChunkCompute( ALIGN_TYPE::UpdatePEMaximum(score_buff, max, chunk_row_offset, i, p_cols, ck_idx, predicate, global_query_length, reference_length); - p_cols++; - if (entering) entering_pe++; - if (exiting) exiting_pe++; + if (entering) { + entering_pe++; + l_lim_reg++; + } + if (exiting) { + Utils::Array::ShiftRight(exiting_shift, false); + exiting_pe++; + u_lim_reg++; + } } } diff --git a/src/debug.cpp b/src/debug.cpp index 79920680..dbd916bf 100644 --- a/src/debug.cpp +++ b/src/debug.cpp @@ -55,7 +55,7 @@ void Container::set_score(int chunk_row_offset, int chunk_col_offset, int pe_num // } int row = chunk_row_offset + pe_num; int col = chunk_col_offset + wavefront - pe_num; - if (0 <= row < MAX_QUERY_LENGTH && 0 <= col < MAX_REFERENCE_LENGTH && pred){ + if (0 <= row && row < MAX_QUERY_LENGTH && 0 <= col && col < MAX_REFERENCE_LENGTH && pred){ this->scores_kernel[row][col] = vals; } } @@ -166,6 +166,7 @@ std::vector> DebugUtils::translate_scores(hls::vector>> scores) { printf("%s\n", name); @@ -203,7 +204,6 @@ void DebugUtils::Translate::print_2d(const char * name, std::vector scores) diff --git a/src/pe.cpp b/src/pe.cpp index 461630bb..d010f09b 100644 --- a/src/pe.cpp +++ b/src/pe.cpp @@ -73,8 +73,6 @@ void PE::PEUnrollFixedSep( const dp_mem_block_t dp_mem, const input_char_block_t qry, const input_char_block_t ref, - const bool entering, const bool exiting, - const idx_t entering_pe, const idx_t exiting_pe, const Penalties penalties, wavefront_scores_inf_t &score, tbp_vec_t &tbp){ @@ -90,9 +88,9 @@ void PE::PEUnrollFixedSep( ALIGN_TYPE::PE::Compute( qry[i], ref[i], - i == exiting_pe && exiting ? score_vec_t(NINF) : dp_mem[i][0], + dp_mem[i][0], dp_mem[i][1], - i == entering_pe && entering ? score_vec_t(NINF) : dp_mem[i+1][0], + dp_mem[i+1][0], penalties, score[i+1], tbp[i]); diff --git a/testbench/test_csim_banding_global_linear.cpp b/testbench/test_csim_banding_global_linear.cpp index c5b6db07..21009c13 100644 --- a/testbench/test_csim_banding_global_linear.cpp +++ b/testbench/test_csim_banding_global_linear.cpp @@ -10,9 +10,7 @@ #include "dp_hls_common.h" #include "solutions.h" #include "debug.h" - -#define INPUT_QUERY_LENGTH 32 -#define INPUT_REFERENCE_LENGTH 32 +#include using namespace std; @@ -57,6 +55,8 @@ int main(){ // Create debug file ofstream debug_file(DEBUG_OUTPUT_FILE); + cout << "TB Chunk Size: " << TB_CHUNK_WIDTH << endl; + // std::string query_string = "TACAGAC"; // CCGTAGACCCGAACTTCGCGGTACACCTTCTGAAACCGTCCCTAATCCGACGAGCGCCTTGAGAACG"; // std::string reference_string = "TGCTATTC"; // TGAGAACGTAGTCTAGGCGAATCGGCCCTTGTATATCGGGGCCGTAGACCCGAACTTCGCGGTACAC"; char alphabet[4] = {'A', 'T', 'G', 'C'}; @@ -148,6 +148,9 @@ int main(){ debug_file << "Kernel call done" << endl; + // create a json file and dump the data + + // print the original traceback to file for (int b = 0; b < N_BLOCKS; b++) { @@ -210,5 +213,15 @@ int main(){ // print traceback pointer matrices fprint_matrix(debug_file, sol_tb_mat, "Solution Traceback Matrix, Layer: " + std::to_string(0)); #endif + // print traceback pointers for block 0 + debug_file << "Block 0 Traceback Pointers: "; + for (int i = 0; i < MAX_QUERY_LENGTH + MAX_REFERENCE_LENGTH; i++){ + debug_file << tbp_to_char(tb_streams_d[i][0]); + } + debug_file << endl; + + debuggers[0].dump_scores_infos(debug_file); + + return 0; } \ No newline at end of file diff --git a/tmp.txt b/tmp.txt new file mode 100644 index 00000000..c2e4b98e --- /dev/null +++ b/tmp.txt @@ -0,0 +1,52 @@ +0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 2 1 2 1 2 2 2 2 2 2 2 2 1 2 1 1 1 1 2 1 2 1 1 1 1 1 1 1 1 1 3 3 3 2 3 2 3 2 1 3 2 2 2 2 2 3 2 2 2 2 1 2 1 1 2 2 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 1 2 2 2 2 2 2 2 2 2 2 1 1 2 2 2 2 2 2 2 2 2 1 1 1 1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 3 2 3 2 2 2 2 2 2 2 2 1 1 2 2 2 1 1 3 2 2 2 2 3 3 3 3 3 3 3 3 3 3 3 3 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 3 1 2 2 2 2 1 1 1 1 2 3 2 1 1 2 2 2 2 2 3 2 3 2 2 1 2 1 2 1 2 1 2 2 2 2 2 2 2 2 3 1 2 1 2 3 2 2 3 2 2 2 2 2 3 2 3 2 2 1 2 1 2 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 1 3 2 2 2 1 2 2 2 1 1 2 1 3 2 2 1 2 2 2 2 1 2 1 2 1 2 1 1 1 1 1 2 1 1 1 1 1 1 1 1 3 2 2 2 1 2 3 2 3 2 2 2 2 2 2 2 2 2 3 2 2 2 1 2 1 1 3 2 2 2 3 3 3 3 3 3 3 3 3 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 3 2 3 2 2 2 2 2 2 2 2 2 2 1 1 2 2 2 1 2 2 2 1 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 3 2 3 2 2 2 2 1 3 2 3 2 2 2 2 2 2 2 2 2 3 2 2 2 2 2 2 2 1 2 2 2 3 3 3 3 3 3 3 3 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 3 3 2 3 2 2 3 2 2 1 1 2 2 3 2 2 1 1 2 2 1 2 2 2 2 2 3 2 1 2 1 2 1 2 1 2 2 2 2 2 2 1 1 3 2 2 3 1 2 1 2 2 2 2 2 2 2 1 2 1 2 1 2 1 1 2 3 2 2 1 1 2 2 3 3 3 3 3 3 3 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 1 3 3 3 3 2 2 2 3 2 2 2 1 1 2 2 3 2 2 1 2 2 1 2 1 2 1 2 3 2 1 2 2 2 2 2 1 2 2 2 3 3 2 2 3 2 2 2 2 2 1 1 3 2 3 2 2 2 2 1 2 1 2 3 2 2 1 2 2 3 2 2 1 2 3 3 3 3 3 3 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 2 1 1 1 1 3 2 2 3 3 2 2 3 2 2 1 2 1 2 3 2 2 2 2 1 2 1 2 1 1 3 2 2 1 2 1 1 2 2 2 2 3 3 2 2 3 2 2 3 2 1 2 2 1 2 2 2 2 2 1 2 1 2 1 2 2 3 2 2 2 2 2 2 2 3 3 3 3 3 3 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 3 3 2 2 2 2 3 2 2 2 3 2 2 2 2 3 2 1 1 1 2 2 2 2 2 2 1 2 1 2 1 2 2 3 2 2 2 2 1 1 3 3 3 3 2 2 3 2 2 2 3 1 2 2 2 1 3 3 2 2 2 1 2 1 2 2 2 2 2 2 1 1 2 2 2 3 3 3 3 3 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 1 1 1 2 1 1 1 1 1 2 3 3 2 2 3 2 2 3 2 1 1 1 1 1 2 2 2 2 1 2 1 1 1 1 2 2 2 1 1 2 1 1 1 3 3 2 2 3 2 2 2 3 1 2 2 2 2 1 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 3 3 3 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 3 2 2 2 3 2 2 2 2 2 2 1 3 2 2 1 2 1 3 3 2 2 1 2 1 1 1 1 1 2 1 2 2 2 2 2 2 3 2 2 3 2 2 2 3 3 2 2 3 2 2 3 2 2 2 2 2 1 2 1 2 2 1 2 1 2 1 2 1 1 2 3 2 2 1 1 1 3 3 3 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 3 3 1 1 2 1 1 1 2 2 2 3 2 2 2 1 2 3 2 3 3 2 1 2 2 2 2 2 2 2 2 2 1 2 1 2 1 2 1 2 3 3 2 2 2 3 3 2 2 3 2 2 2 3 2 1 1 1 2 2 2 1 2 2 1 2 1 2 2 2 2 1 2 2 3 2 2 2 3 3 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 2 3 3 2 2 3 1 2 2 3 2 2 2 3 3 3 2 2 3 2 1 2 3 2 2 2 2 2 2 2 2 1 2 1 1 2 2 2 1 2 2 3 3 2 2 2 3 3 2 2 3 2 2 2 3 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 2 2 2 1 1 2 2 2 3 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 1 1 1 1 2 2 3 2 2 2 3 2 2 2 1 3 3 2 1 2 3 2 3 3 2 1 2 1 1 1 1 1 2 2 2 2 1 2 3 2 1 1 1 1 2 2 2 3 3 2 2 2 2 1 1 3 3 1 2 2 2 2 2 2 2 1 2 3 2 2 1 2 1 2 1 2 1 2 2 2 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 3 2 2 2 2 2 2 3 2 2 2 3 2 2 3 2 1 3 3 2 1 1 2 1 3 3 2 1 2 2 2 2 1 2 1 2 1 2 1 3 3 1 2 2 2 3 2 2 3 3 3 2 2 3 2 2 1 2 2 2 2 2 2 2 2 2 2 1 2 2 3 2 2 2 1 2 1 2 2 2 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 2 3 2 2 2 1 1 1 1 2 1 1 1 1 1 3 3 2 2 3 3 2 2 1 2 1 3 3 2 2 2 2 2 2 1 2 1 1 1 1 2 3 2 1 2 2 2 1 1 3 3 2 2 2 2 1 3 2 3 2 1 1 1 1 1 1 1 1 2 1 2 2 2 2 1 2 1 2 1 2 0 0 0 0 0 0 0 0 0 0 + + +0 0 0 0 0 0 0 0 0 0 2 2 1 1 2 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 2 1 3 3 2 1 1 2 3 3 2 2 2 2 2 1 2 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 2 1 2 2 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 2 3 2 3 2 2 2 3 2 2 2 2 3 2 2 2 2 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 3 2 3 2 2 2 3 2 2 2 2 3 2 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 3 3 2 1 2 1 3 2 2 2 1 2 2 1 1 2 3 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 2 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 2 3 2 2 2 3 2 3 2 2 2 1 2 1 1 1 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 2 2 1 2 2 2 1 2 2 1 1 1 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 2 2 2 1 1 2 2 2 1 2 2 1 2 2 2 2 2 3 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 2 1 2 2 1 1 2 2 2 2 1 1 1 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 2 3 2 2 2 3 3 2 2 1 2 1 1 1 1 1 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 3 2 1 1 2 2 1 2 2 1 2 2 2 1 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 3 2 2 1 2 2 2 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 3 3 2 2 2 1 2 1 1 1 2 1 1 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 2 2 2 3 3 2 2 1 2 1 1 1 1 1 2 1 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 3 2 2 2 3 2 1 2 2 1 1 1 2 1 2 1 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 3 3 2 2 2 2 2 2 2 2 2 2 1 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 3 2 2 2 3 2 2 2 2 1 1 1 2 1 2 1 2 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 1 1 3 3 3 2 3 2 1 2 2 2 1 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 3 2 1 1 3 2 3 3 2 2 2 1 2 1 1 1 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 3 2 2 2 2 3 2 2 2 2 2 1 2 2 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 3 2 2 2 2 2 2 2 2 3 2 1 2 1 2 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 3 2 2 2 2 3 2 2 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 2 2 2 2 2 2 2 2 3 2 2 2 1 2 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 2 2 2 2 3 2 2 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 2 3 2 2 2 2 2 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 3 2 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 3 2 3 3 2 1 1 3 2 3 2 1 2 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 + 0 0 0 0 0 0 0 0 0 0 2 2 1 1 2 1 2 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 3 3 2 2 2 2 2 2 2 3 2 2 1 2 2 2 2 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 1 2 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 3 2 2 2 2 2 2 3 2 2 3 2 2 2 1 1 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 2 3 2 1 1 2 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 2 2 2 2 2 2 2 3 2 2 3 2 2 2 2 1 2 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 2 3 2 2 2 2 2 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 3 2 2 3 2 2 2 2 2 2 1 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 3 2 2 2 2 2 2 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 1 2 1 1 3 2 1 3 2 2 2 1 2 1 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 3 2 2 1 2 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 3 2 2 2 2 1 2 3 2 2 2 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 1 3 2 1 2 2 2 2 2 1 1 2 1 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 1 3 2 1 3 2 2 2 1 2 1 1 2 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 2 1 3 2 1 2 1 2 2 2 2 2 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 1 2 3 3 2 3 2 2 3 2 3 2 1 1 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 3 2 3 3 2 1 1 1 1 2 2 1 2 1 1 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 2 2 2 3 2 3 2 2 1 2 1 3 2 2 3 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 3 2 1 3 3 2 2 2 2 2 2 2 2 2 2 2 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 1 3 2 2 2 1 2 3 2 3 2 1 1 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 2 3 2 2 3 2 1 1 1 1 1 1 1 1 2 1 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 3 2 2 2 2 2 3 2 3 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 3 2 1 3 3 2 2 2 1 1 2 1 2 1 1 1 1 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 1 3 3 2 2 1 2 2 3 3 2 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 2 2 3 3 2 2 2 1 1 2 1 2 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 3 3 2 3 2 2 2 2 3 2 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 2 3 3 3 3 2 2 2 2 2 2 2 2 1 1 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 3 2 3 2 2 2 2 3 2 2 2 2 1 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 1 2 3 3 2 2 2 2 2 2 2 1 2 2 1 1 1 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 2 3 2 2 2 2 3 2 2 2 2 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 3 3 3 2 2 2 2 2 2 3 2 1 1 2 2 2 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 \ No newline at end of file