From 98afc37f19cdcca61f77e78c369081d987b6aefe Mon Sep 17 00:00:00 2001 From: Kazushi Kawamura Date: Fri, 24 Aug 2018 17:29:21 +0900 Subject: [PATCH 01/30] Add files --- hls_2018/router_01/router.cpp | 499 ++++++++++++++++++++++++++++++ hls_2018/router_01/router.hpp | 56 ++++ hls_2018/router_02/router.cpp | 557 ++++++++++++++++++++++++++++++++++ hls_2018/router_02/router.hpp | 59 ++++ hls_2018/router_03/router.cpp | 513 +++++++++++++++++++++++++++++++ hls_2018/router_03/router.hpp | 56 ++++ hls_2018/router_04/router.cpp | 513 +++++++++++++++++++++++++++++++ hls_2018/router_04/router.hpp | 56 ++++ 8 files changed, 2309 insertions(+) create mode 100755 hls_2018/router_01/router.cpp create mode 100755 hls_2018/router_01/router.hpp create mode 100755 hls_2018/router_02/router.cpp create mode 100755 hls_2018/router_02/router.hpp create mode 100755 hls_2018/router_03/router.cpp create mode 100755 hls_2018/router_03/router.hpp create mode 100755 hls_2018/router_04/router.cpp create mode 100755 hls_2018/router_04/router.hpp diff --git a/hls_2018/router_01/router.cpp b/hls_2018/router_01/router.cpp new file mode 100755 index 0000000..de396f1 --- /dev/null +++ b/hls_2018/router_01/router.cpp @@ -0,0 +1,499 @@ +/** + * router.cpp + * + * for Vivado HLS + */ + +#ifdef SOFTWARE +#include "ap_int.h" +#else +#include +#endif + +#include "./router.hpp" + +// Set weight +ap_uint<8> new_weight(ap_uint<16> x) { +#pragma HLS INLINE + // K. Terada: y = 1~32 (8bit) + ap_uint<8> y; + y = ((x & 255) >> 3) + 1; + return y; +} + + +// Global values +static ap_uint<7> size_x; // X +static ap_uint<7> size_y; // Y +static ap_uint<4> size_z; // Z + +static ap_uint line_num = 0; // #Lines + +#ifdef DEBUG_PRINT +int max_queue_length; // Max length of priority queue +int max_search_count; // Max count of queue pop +int max_buffer_length; // Max length of line buffer +#endif + + +bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *status) { +#pragma HLS INTERFACE s_axilite port=boardstr bundle=AXI4LS +#pragma HLS INTERFACE s_axilite port=seed bundle=AXI4LS +#pragma HLS INTERFACE s_axilite port=status bundle=AXI4LS +#pragma HLS INTERFACE s_axilite port=return bundle=AXI4LS + + // status(0:Solved, 1:Not solved) + *status = -1; + + // For all lines + ap_uint paths[MAX_BUFFER]; // Line buffer + + // For each line + // Note: Should not partition completely + bool adjacents[MAX_LINES]; // Line has adjacent terminals? + ap_uint starts[MAX_LINES]; // Start list + ap_uint goals[MAX_LINES]; // Goal list + ap_uint s_idx[MAX_LINES]; // Start point on line buffer + + ap_uint<8> weights[MAX_CELLS]; // Weight of each cell + // Note: Should not partition weight array + // since each element will be accessed in "random" order + + + // ================================ + // (Step.0) Initialization (BEGIN) + // ================================ + + // Note: Loop counter -> need an extra bit (for condition determination) + + INIT_WEIGHTS: + for (ap_uint i = 0; i < (ap_uint)(MAX_CELLS); i++) { + weights[i] = 1; + } + + /// Parse /// + size_x = (boardstr[1] - '0') * 10 + (boardstr[2] - '0'); + size_y = (boardstr[4] - '0') * 10 + (boardstr[5] - '0'); + size_z = (boardstr[7] - '0'); + + INIT_BOARDS: + for (ap_uint idx = 8; idx < (ap_uint)(BOARDSTR_SIZE); idx+=11) { + + // NULL-terminated + if (boardstr[idx] == 0) break; + + // Start & Goal of each line + ap_uint<7> s_x = (boardstr[idx+1] - '0') * 10 + (boardstr[idx+2] - '0'); + ap_uint<7> s_y = (boardstr[idx+3] - '0') * 10 + (boardstr[idx+4] - '0'); + ap_uint<3> s_z = (boardstr[idx+5] - '0') - 1; + ap_uint<7> g_x = (boardstr[idx+6] - '0') * 10 + (boardstr[idx+7] - '0'); + ap_uint<7> g_y = (boardstr[idx+8] - '0') * 10 + (boardstr[idx+9] - '0'); + ap_uint<3> g_z = (boardstr[idx+10] - '0') - 1; + + ap_uint start_id = (((ap_uint)s_x * MAX_WIDTH + (ap_uint)s_y) << BITWIDTH_Z) | (ap_uint)s_z; + ap_uint goal_id = (((ap_uint)g_x * MAX_WIDTH + (ap_uint)g_y) << BITWIDTH_Z) | (ap_uint)g_z; + starts[line_num] = start_id; + goals[line_num] = goal_id; + weights[start_id] = MAX_WEIGHT; + weights[goal_id] = MAX_WEIGHT; + + // Line has adjacent terminals? + adjacents[line_num] = false; + ap_int<8> dx = (ap_int<8>)g_x - (ap_int<8>)s_x; // Min: -71, Max: 71 (Signed 8bit) + ap_int<8> dy = (ap_int<8>)g_y - (ap_int<8>)s_y; // Min: -71, Max: 71 (Signed 8bit) + ap_int<4> dz = (ap_int<4>)g_z - (ap_int<4>)s_z; // Min: -7, Max: 7 (Signed 4bit) + 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; + } + + line_num++; + } + + // ================================ + // (Step.0) Initialization (END) + // ================================ + +#ifdef DEBUG_PRINT + max_queue_length = 0; + max_search_count = 0; + max_buffer_length = 0; +#endif + + ap_uint pointer = 0; // Pointer for line buffer + + // ================================ + // (Step.1) Initial Routing (BEGIN) + // ================================ + +#ifdef DEBUG_PRINT + cout << "Initial Routing ..." << endl; +#endif + + FIRST_ROUTING: + for (ap_uint i = 0; i < (ap_uint)(line_num); i++) { +#pragma HLS LOOP_TRIPCOUNT min=2 max=999 + + s_idx[i] = pointer; + + if (adjacents[i] == true) continue; // Skip routing + +#ifdef DEBUG_PRINT + //cout << "LINE #" << (int)(i + 1) << endl; +#endif + // Routing + pointer = search(s_idx[i], paths, starts[i], goals[i], weights); + } + + // ================================ + // (Step.1) Initial Routing (END) + // ================================ + + + // Memories for Overlap Check + ap_uint<1> overlap_checks[MAX_CELLS]; + bool has_overlap = false; + + // ================================ + // (Step.2) Rip-up Routing (BEGIN) + // ================================ + +#ifdef DEBUG_PRINT + cout << "Rip-up Routing ..." << endl; +#endif + + ROUTING: + for (ap_uint<16> round = 0; round < 32768 /* = (2048 * 16) */; round++) { +#pragma HLS LOOP_TRIPCOUNT min=1 max=32768 + + // Target line + ap_uint target = round % line_num; + ap_uint next_target = target + 1; + if (next_target == line_num) next_target = 0; + +#ifdef DEBUG_PRINT + //cout << "(round " << round << ") LINE #" << (int)(target + 1); + //cout << " -> " << pointer << endl; +#endif +#ifdef DEBUG_PRINT + int buffer_length = pointer - s_idx[target]; + if (max_buffer_length < buffer_length) { max_buffer_length = buffer_length; } +#endif + + // Skip routing + if (adjacents[target] == true) { + s_idx[target] = pointer; continue; + } + + + // (Step.2-1) Reset weights of target line + WEIGHT_RESET: + for (ap_uint j = s_idx[target]; j != s_idx[next_target]; j++) { +#pragma HLS LOOP_TRIPCOUNT min=1 max=256 + weights[paths[j]] = 1; + } + + // (Step.2-2) Set weights of non-target lines and terminals + ap_uint<8> current_round_weight = new_weight(round); + WEIGHT_PATH: + for (ap_uint j = s_idx[next_target]; j != pointer; j++) { +#pragma HLS LOOP_TRIPCOUNT min=1 max=8192 + weights[paths[j]] = current_round_weight; + } + WEIGHT_TERMINAL: + for (ap_uint i = 0; i < (ap_uint)(line_num); i++) { +#pragma HLS LOOP_TRIPCOUNT min=2 max=999 + weights[starts[i]] = MAX_WEIGHT; + weights[goals[i]] = MAX_WEIGHT; + } + // Reset weight of start terminal of target line (bug avoiding) + // Restore original settings in (*) + weights[starts[target]] = 1; + + // (Step.2-3) Routing + s_idx[target] = pointer; + pointer = search(s_idx[target], paths, starts[target], goals[target], weights); + + // (*) + weights[starts[target]] = MAX_WEIGHT; + +#ifdef DEBUG_PRINT + bool ng = false; + for (ap_uint i = 0; i < (ap_uint)(line_num); i++) { + if (weights[starts[i]] != 255 || weights[goals[i]] != 255) { + cout << i << " "; ng = true; + } + } + if(ng) { cout << endl; } +#endif + + // (Step.2-4) Overlap check + has_overlap = false; + OVERLAP_RESET: + for (ap_uint i = 0; i < (ap_uint)(MAX_CELLS); i++) { + overlap_checks[i] = 0; + } + OVERLAP_CHECK_LINE: + for (ap_uint i = 0; i < (ap_uint)(line_num); i++) { +#pragma HLS LOOP_TRIPCOUNT min=2 max=999 + overlap_checks[starts[i]] = 1; + overlap_checks[goals[i]] = 1; + } + OVERLAP_CHECK_PATH: + for (ap_uint j = s_idx[next_target]; j != pointer; j++) { +#pragma HLS LOOP_TRIPCOUNT min=1 max=8192 + ap_uint cell_id = paths[j]; + if (overlap_checks[cell_id]) { + has_overlap = true; break; + } + overlap_checks[cell_id] = 1; + } +#ifdef DEBUG_PRINT + if(!has_overlap){ cout << "ROUND: " << round << endl; } +#endif + if (!has_overlap) break; // Finish routing? + } + +#ifdef DEBUG_PRINT + cout << "MAX PQ LENGTH: " << max_queue_length << endl; + cout << "MAX SEARCH COUNT: " << max_search_count << endl; + cout << "MAX BUFFER: " << max_buffer_length << endl; +#endif + + // Not solved + if (has_overlap) { + *status = 1; return false; + } + + // ================================ + // (Step.2) Rip-up Routing (END) + // ================================ + + + // ================================ + // (Step.3) Output (BEGIN) + // ================================ + +#ifdef DEBUG_PRINT + cout << "Output ..." << endl; +#endif + + // Init: Blank = 0 + OUTPUT_INIT: + for (ap_uint i = 0; i < (ap_uint)(MAX_CELLS); i++) { + boardstr[i] = 0; + } + // Line + OUTPUT_LINE: + for (ap_uint i = 0; i < (ap_uint)(line_num); i++) { +#pragma HLS LOOP_TRIPCOUNT min=2 max=999 + boardstr[starts[i]] = (i + 1); + boardstr[goals[i]] = (i + 1); + + ap_uint p1; // p1: s_idx of target + ap_uint p2; // p2: s_idx of next target + p1 = s_idx[i]; + if (i == (ap_uint)(line_num-1)) { + p2 = s_idx[0]; + } + else { + p2 = s_idx[i+1]; + } + if ((ap_uint)(p2 - p1) > 8192){ + p2 = pointer; + } + OUTPUT_LINE_PATH: + for (ap_uint j = p1; j != p2; j++) { +#pragma HLS LOOP_TRIPCOUNT min=1 max=256 + boardstr[paths[j]] = (i + 1); + } + } + + // ================================ + // (Step.3) Output (END) + // ================================ + + *status = 0; return true; +} + + +// ================================ // +// For Routing +// ================================ // + +// Max: 71, Min: 0 (7bit) +ap_uint<7> abs_uint7(ap_uint<7> a, ap_uint<7> b) { +#pragma HLS INLINE + if (a < b) { return b - a; } + else { return a - b; } +} +// Max: 7, Min: 0 (3bit) +ap_uint<3> abs_uint3(ap_uint<3> a, ap_uint<3> b) { +#pragma HLS INLINE + if (a < b) { return b - a; } + else { return a - b; } +} + +// Reference codes: +// http://lethe2211.hatenablog.com/entry/2014/12/30/011030 +// http://www.redblobgames.com/pathfinding/a-star/implementation.html +// Need to modify "array partition factor" +ap_uint search(ap_uint idx, ap_uint paths[MAX_BUFFER], ap_uint start, ap_uint goal, ap_uint<8> w[MAX_CELLS]) { + + ap_uint dist[MAX_CELLS]; + ap_uint prev[MAX_CELLS]; + + SEARCH_INIT_DIST: + for (ap_uint i = 0; i < (ap_uint)(MAX_CELLS); i++) { + dist[i] = 65535; // = (2^16 - 1) + } + + // Priority queue (Circular list) + ap_uint top = 1, bottom = 0; + bool is_empty = true; + ap_uint<32> pq_nodes[MAX_PQ]; + +#ifdef DEBUG_PRINT + int queue_length = 0; + int search_count = 0; +#endif + + // Point of goal terminal + 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_y = (ap_uint<7>)(goal_xy - goal_x * MAX_WIDTH); + ap_uint<3> goal_z = (ap_uint<3>)(goal & BITMASK_Z); + + dist[start] = 0; + pq_push(pq_nodes, 0, start, &top, &bottom, &is_empty); // push start terminal + + SEARCH_PQ: + while (!is_empty) { +#pragma HLS LOOP_TRIPCOUNT min=1 max=1000 +#pragma HLS LOOP_FLATTEN off + + ap_uint<16> prev_cost; + ap_uint<16> src; // target cell + pq_pop(pq_nodes, &prev_cost, &src, &top, &bottom, &is_empty); +#ifdef DEBUG_PRINT + search_count++; +#endif + + + // End routing + if (src == goal) break; + + + // Target cell + ap_uint<16> dist_src = dist[src]; + ap_uint<8> cost = w[src]; + // Point of target cell + 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_y = (ap_uint<7>)(src_xy - src_x * MAX_WIDTH); + ap_uint<3> src_z = (ap_uint<3>)(src & BITMASK_Z); + + // Search adjacent cells + SEARCH_ADJACENTS: + for (ap_uint<3> a = 0; a < 6; a++) { + ap_int<8> dest_x = (ap_int<8>)src_x; // Min: -1, Max: 72 (Signed 8bit) + ap_int<8> dest_y = (ap_int<8>)src_y; // Min: -1, Max: 72 (Signed 8bit) + ap_int<5> dest_z = (ap_int<5>)src_z; // Min: -1, Max: 8 (Signed 5bit) + if (a == 0) { dest_x -= 1; } + if (a == 1) { dest_x += 1; } + if (a == 2) { dest_y -= 1; } + if (a == 3) { dest_y += 1; } + if (a == 4) { dest_z -= 1; } + if (a == 5) { dest_z += 1; } + + // Inside the board ? // + if (0 <= dest_x && dest_x < (ap_int<8>)size_x && 0 <= dest_y && dest_y < (ap_int<8>)size_y && 0 <= dest_z && dest_z < (ap_int<5>)size_z) { + // Adjacent cell + ap_uint<16> dest = (((ap_uint<16>)dest_x * MAX_WIDTH + (ap_uint<16>)dest_y) << BITWIDTH_Z) | (ap_uint<16>)dest_z; + ap_uint<16> dist_new = dist_src + cost; + + if (dist[dest] > dist_new) { + dist[dest] = dist_new; // Update dist + prev[dest] = src; // Recode previous cell + dist_new += abs_uint7(dest_x, goal_x) + abs_uint7(dest_y, goal_y) + abs_uint3(dest_z, goal_z); // A* heuristic + pq_push(pq_nodes, dist_new, dest, &top, &bottom, &is_empty); // push adjacent cell + } + } + } +#ifdef DEBUG_PRINT + if (queue_length < (bottom-top+1)) { queue_length = (bottom-top+1); } +#endif + } + + // Output target path + // Note: Do not include start & goal terminals + ap_uint<16> t = prev[goal]; + + // Backtracking + ap_uint p = idx; // buffer-idx + SEARCH_BACKTRACK: + while (t != start) { +#pragma HLS LOOP_TRIPCOUNT min=1 max=256 + paths[p] = t; + p++; + t = prev[t]; + } + +#ifdef DEBUG_PRINT + if (max_queue_length < queue_length) { max_queue_length = queue_length; } + if (max_search_count < search_count) { max_search_count = search_count; } +#endif + + return p; +} + +// Queue push (Enqueue) +// Need to modify "trip count" (2) +void pq_push(ap_uint<32> pq_nodes[MAX_PQ], ap_uint<16> priority, ap_uint<16> data, ap_uint *top, ap_uint *bottom, bool *is_empty) { +#pragma HLS INLINE + + (*bottom)++; + if ((*bottom) == (*top) && !(*is_empty)) { (*bottom)--; } // Queue is full -> Last element is automatically removed + + // Binary search for circular list + ap_uint t = (*top); + ap_uint b = (*bottom); + ap_uint h = ((ap_uint)(b - t) / 2) + t; + // Note: "h = (t + b) / 2" causes a bug! + PQ_PUSH_BINARY: + while (t != b) { +#pragma HLS LOOP_TRIPCOUNT min=0 max=13 +/** Set!: min=0 max=PQ_BIT **/ + if ((ap_uint<16>)(pq_nodes[h] & PQ_PRIORITY_MASK) >= priority) { + b = h; + } + else { + t = h + 1; + } + h = ((ap_uint)(b - t) / 2) + t; + } + + // Shifting + ap_uint shift_count = (*bottom) - t; // # of shifting + + ap_uint p0 = (*bottom), p1; + PQ_PUSH_SHIFT: + for (ap_uint j = 0; j < (ap_uint)(shift_count); j++) { +#pragma HLS LOOP_TRIPCOUNT min=0 max=8191 +/** Set!: min=0 max=MAX_PQ-1 **/ + p0 = p0 - 1; + p1 = p0 + 1; + pq_nodes[p1] = pq_nodes[p0]; + } + pq_nodes[p0] = ((ap_uint<32>)data << PQ_PRIORITY_WIDTH) | (ap_uint<32>)priority; + *is_empty = false; +} + +// Queue pop (Dequeue) +void pq_pop(ap_uint<32> pq_nodes[MAX_PQ], ap_uint<16> *ret_priority, ap_uint<16> *ret_data, ap_uint *top, ap_uint *bottom, bool *is_empty) { +#pragma HLS INLINE + + *ret_priority = (ap_uint<16>)(pq_nodes[(*top)] & PQ_PRIORITY_MASK); + *ret_data = (ap_uint<16>)(pq_nodes[(*top)] >> PQ_PRIORITY_WIDTH); + (*top)++; + if (((*bottom)-(*top)+1) == 0) { *is_empty = true; } +} diff --git a/hls_2018/router_01/router.hpp b/hls_2018/router_01/router.hpp new file mode 100755 index 0000000..3455260 --- /dev/null +++ b/hls_2018/router_01/router.hpp @@ -0,0 +1,56 @@ +/** + * router.hpp + * + * for Vivado HLS + */ + +#ifndef __ROUTER_HPP__ +#define __ROUTER_HPP__ + +#ifdef SOFTWARE +#include "ap_int.h" +#else +#include +#endif + +//#define DEBUG_PRINT // for debug + +#ifdef DEBUG_PRINT +using namespace std; +#endif + +// Parameters +#define MAX_WIDTH 72 // Max of X, Y +#define BITWIDTH_XY 13 +#define BITMASK_XY 65528 // 1111 1111 1111 1000 +#define MAX_LAYER 8 // Max of Z +#define BITWIDTH_Z 3 +#define BITMASK_Z 7 // 0000 0000 0000 0111 + +#define MAX_CELLS 41472 // Max #cells (16bit) +#define MAX_LINES 1024 // Max #lines (10bit) +#define MAX_PQ 8192 // Queue size (13bit) +#define MAX_BUFFER 16384 // Line buffer size (14bit) +#define CELL_BIT 16 +#define LINE_BIT 10 +#define PQ_BIT 13 +#define BUFF_BIT 14 + +#define PQ_PRIORITY_WIDTH 16 +#define PQ_PRIORITY_MASK 65535 // 0000 0000 0000 0000 1111 1111 1111 1111 +#define PQ_DATA_WIDTH 16 +#define PQ_DATA_MASK 4294901760 // 1111 1111 1111 1111 0000 0000 0000 0000 + +#define MAX_WEIGHT 255 // Max weight +#define BOARDSTR_SIZE 41472 // Size of I/O + +ap_uint<8> new_weight(ap_uint<16> x); +bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *status); + +ap_uint<7> abs_uint7(ap_uint<7> a, ap_uint<7> b); +ap_uint<3> abs_uint3(ap_uint<3> a, ap_uint<3> b); +ap_uint search(ap_uint idx, ap_uint paths[MAX_BUFFER], ap_uint start, ap_uint goal, ap_uint<8> w[MAX_WEIGHT]); +void pq_push(ap_uint<32> pq_nodes[MAX_PQ], ap_uint<16> priority, ap_uint<16> data, ap_uint *top, ap_uint *bottom, bool *is_empty); +void pq_pop(ap_uint<32> pq_nodes[MAX_PQ], ap_uint<16> *ret_priority, ap_uint<16> *ret_data, ap_uint *top, ap_uint *bottom, bool *is_empty); + +#endif /* __ROUTER_HPP__ */ diff --git a/hls_2018/router_02/router.cpp b/hls_2018/router_02/router.cpp new file mode 100755 index 0000000..cf50624 --- /dev/null +++ b/hls_2018/router_02/router.cpp @@ -0,0 +1,557 @@ +/** + * router.cpp + * + * for Vivado HLS + */ + +#ifdef SOFTWARE +#include "ap_int.h" +#else +#include +#endif + +#include "./router.hpp" + +// Set weight +ap_uint<8> new_weight(ap_uint<16> x) { +#pragma HLS INLINE + // K. Terada: y = 1~32 (8bit) + ap_uint<8> y; + y = ((x & 255) >> 3) + 1; + return y; +} + + +// Global values +static ap_uint<7> size_x; // X +static ap_uint<7> size_y; // Y +static ap_uint<4> size_z; // Z + +static ap_uint line_num = 0; // #Lines + +#ifdef DEBUG_PRINT +int max_queue_length; // Max length of priority queue +int max_search_count; // Max count of queue pop +int max_buffer_length; // Max length of line buffer +#endif + + +bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *status) { +#pragma HLS INTERFACE s_axilite port=boardstr bundle=AXI4LS +#pragma HLS INTERFACE s_axilite port=seed bundle=AXI4LS +#pragma HLS INTERFACE s_axilite port=status bundle=AXI4LS +#pragma HLS INTERFACE s_axilite port=return bundle=AXI4LS + + // status(0:Solved, 1:Not solved) + *status = -1; + + // For all lines + ap_uint paths[MAX_BUFFER]; // Line buffer + + // For each line + // Note: Should not partition completely + bool adjacents[MAX_LINES]; // Line has adjacent terminals? + ap_uint starts[MAX_LINES]; // Start list + ap_uint goals[MAX_LINES]; // Goal list + ap_uint s_idx[MAX_LINES]; // Start point on line buffer + + ap_uint<8> weights[MAX_CELLS]; // Weight of each cell + // Note: Should not partition weight array + // since each element will be accessed in "random" order + + + // ================================ + // (Step.0) Initialization (BEGIN) + // ================================ + + // Note: Loop counter -> need an extra bit (for condition determination) + + INIT_WEIGHTS: + for (ap_uint i = 0; i < (ap_uint)(MAX_CELLS); i++) { + weights[i] = 1; + } + + /// Parse /// + size_x = (boardstr[1] - '0') * 10 + (boardstr[2] - '0'); + size_y = (boardstr[4] - '0') * 10 + (boardstr[5] - '0'); + size_z = (boardstr[7] - '0'); + + INIT_BOARDS: + for (ap_uint idx = 8; idx < (ap_uint)(BOARDSTR_SIZE); idx+=11) { + + // NULL-terminated + if (boardstr[idx] == 0) break; + + // Start & Goal of each line + ap_uint<7> s_x = (boardstr[idx+1] - '0') * 10 + (boardstr[idx+2] - '0'); + ap_uint<7> s_y = (boardstr[idx+3] - '0') * 10 + (boardstr[idx+4] - '0'); + ap_uint<3> s_z = (boardstr[idx+5] - '0') - 1; + ap_uint<7> g_x = (boardstr[idx+6] - '0') * 10 + (boardstr[idx+7] - '0'); + ap_uint<7> g_y = (boardstr[idx+8] - '0') * 10 + (boardstr[idx+9] - '0'); + ap_uint<3> g_z = (boardstr[idx+10] - '0') - 1; + + ap_uint start_id = (((ap_uint)s_x * MAX_WIDTH + (ap_uint)s_y) << BITWIDTH_Z) | (ap_uint)s_z; + ap_uint goal_id = (((ap_uint)g_x * MAX_WIDTH + (ap_uint)g_y) << BITWIDTH_Z) | (ap_uint)g_z; + starts[line_num] = start_id; + goals[line_num] = goal_id; + weights[start_id] = MAX_WEIGHT; + weights[goal_id] = MAX_WEIGHT; + + // Line has adjacent terminals? + adjacents[line_num] = false; + ap_int<8> dx = (ap_int<8>)g_x - (ap_int<8>)s_x; // Min: -71, Max: 71 (Signed 8bit) + ap_int<8> dy = (ap_int<8>)g_y - (ap_int<8>)s_y; // Min: -71, Max: 71 (Signed 8bit) + ap_int<4> dz = (ap_int<4>)g_z - (ap_int<4>)s_z; // Min: -7, Max: 7 (Signed 4bit) + 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; + } + + line_num++; + } + + // ================================ + // (Step.0) Initialization (END) + // ================================ + +#ifdef DEBUG_PRINT + max_queue_length = 0; + max_search_count = 0; + max_buffer_length = 0; +#endif + + ap_uint pointer = 0; // Pointer for line buffer + + // ================================ + // (Step.1) Initial Routing (BEGIN) + // ================================ + +#ifdef DEBUG_PRINT + cout << "Initial Routing ..." << endl; +#endif + + FIRST_ROUTING: + for (ap_uint i = 0; i < (ap_uint)(line_num); i++) { +#pragma HLS LOOP_TRIPCOUNT min=2 max=999 + + s_idx[i] = pointer; + + if (adjacents[i] == true) continue; // Skip routing + +#ifdef DEBUG_PRINT + //cout << "LINE #" << (int)(i + 1) << endl; +#endif + // Routing + pointer = search(s_idx[i], paths, starts[i], goals[i], weights); + } + + // ================================ + // (Step.1) Initial Routing (END) + // ================================ + + + // Memories for Overlap Check + ap_uint<1> overlap_checks[MAX_CELLS]; + bool has_overlap = false; + + // ================================ + // (Step.2) Rip-up Routing (BEGIN) + // ================================ + +#ifdef DEBUG_PRINT + cout << "Rip-up Routing ..." << endl; +#endif + + ROUTING: + for (ap_uint<16> round = 0; round < 32768 /* = (2048 * 16) */; round++) { +#pragma HLS LOOP_TRIPCOUNT min=1 max=32768 + + // Target line + ap_uint target = round % line_num; + ap_uint next_target = target + 1; + if (next_target == line_num) next_target = 0; + +#ifdef DEBUG_PRINT + //cout << "(round " << round << ") LINE #" << (int)(target + 1); + //cout << " -> " << pointer << endl; +#endif +#ifdef DEBUG_PRINT + int buffer_length = pointer - s_idx[target]; + if (max_buffer_length < buffer_length) { max_buffer_length = buffer_length; } +#endif + + // Skip routing + if (adjacents[target] == true) { + s_idx[target] = pointer; continue; + } + + + // (Step.2-1) Reset weights of target line + WEIGHT_RESET: + for (ap_uint j = s_idx[target]; j != s_idx[next_target]; j++) { +#pragma HLS LOOP_TRIPCOUNT min=1 max=256 + weights[paths[j]] = 1; + } + + // (Step.2-2) Set weights of non-target lines and terminals + ap_uint<8> current_round_weight = new_weight(round); + WEIGHT_PATH: + for (ap_uint j = s_idx[next_target]; j != pointer; j++) { +#pragma HLS LOOP_TRIPCOUNT min=1 max=8192 + weights[paths[j]] = current_round_weight; + } + WEIGHT_TERMINAL: + for (ap_uint i = 0; i < (ap_uint)(line_num); i++) { +#pragma HLS LOOP_TRIPCOUNT min=2 max=999 + weights[starts[i]] = MAX_WEIGHT; + weights[goals[i]] = MAX_WEIGHT; + } + // Reset weight of start terminal of target line (bug avoiding) + // Restore original settings in (*) + weights[starts[target]] = 1; + + // (Step.2-3) Routing + s_idx[target] = pointer; + pointer = search(s_idx[target], paths, starts[target], goals[target], weights); + + // (*) + weights[starts[target]] = MAX_WEIGHT; + +#ifdef DEBUG_PRINT + bool ng = false; + for (ap_uint i = 0; i < (ap_uint)(line_num); i++) { + if (weights[starts[i]] != 255 || weights[goals[i]] != 255) { + cout << i << " "; ng = true; + } + } + if(ng) { cout << endl; } +#endif + + // (Step.2-4) Overlap check + has_overlap = false; + OVERLAP_RESET: + for (ap_uint i = 0; i < (ap_uint)(MAX_CELLS); i++) { + overlap_checks[i] = 0; + } + OVERLAP_CHECK_LINE: + for (ap_uint i = 0; i < (ap_uint)(line_num); i++) { +#pragma HLS LOOP_TRIPCOUNT min=2 max=999 + overlap_checks[starts[i]] = 1; + overlap_checks[goals[i]] = 1; + } + OVERLAP_CHECK_PATH: + for (ap_uint j = s_idx[next_target]; j != pointer; j++) { +#pragma HLS LOOP_TRIPCOUNT min=1 max=8192 + ap_uint cell_id = paths[j]; + if (overlap_checks[cell_id]) { + has_overlap = true; break; + } + overlap_checks[cell_id] = 1; + } +#ifdef DEBUG_PRINT + if(!has_overlap){ cout << "ROUND: " << round << endl; } +#endif + if (!has_overlap) break; // Finish routing? + } + +#ifdef DEBUG_PRINT + cout << "MAX PQ LENGTH: " << max_queue_length << endl; + cout << "MAX SEARCH COUNT: " << max_search_count << endl; + cout << "MAX BUFFER: " << max_buffer_length << endl; +#endif + + // Not solved + if (has_overlap) { + *status = 1; return false; + } + + // ================================ + // (Step.2) Rip-up Routing (END) + // ================================ + + + // ================================ + // (Step.3) Output (BEGIN) + // ================================ + +#ifdef DEBUG_PRINT + cout << "Output ..." << endl; +#endif + + // Init: Blank = 0 + OUTPUT_INIT: + for (ap_uint i = 0; i < (ap_uint)(MAX_CELLS); i++) { + boardstr[i] = 0; + } + // Line + OUTPUT_LINE: + for (ap_uint i = 0; i < (ap_uint)(line_num); i++) { +#pragma HLS LOOP_TRIPCOUNT min=2 max=999 + boardstr[starts[i]] = (i + 1); + boardstr[goals[i]] = (i + 1); + + ap_uint p1; // p1: s_idx of target + ap_uint p2; // p2: s_idx of next target + p1 = s_idx[i]; + if (i == (ap_uint)(line_num-1)) { + p2 = s_idx[0]; + } + else { + p2 = s_idx[i+1]; + } + if ((ap_uint)(p2 - p1) > 8192){ + p2 = pointer; + } + OUTPUT_LINE_PATH: + for (ap_uint j = p1; j != p2; j++) { +#pragma HLS LOOP_TRIPCOUNT min=1 max=256 + boardstr[paths[j]] = (i + 1); + } + } + + // ================================ + // (Step.3) Output (END) + // ================================ + + *status = 0; return true; +} + + +// ================================ // +// For Routing +// ================================ // + +// Max: 71, Min: 0 (7bit) +ap_uint<7> abs_uint7(ap_uint<7> a, ap_uint<7> b) { +#pragma HLS INLINE + if (a < b) { return b - a; } + else { return a - b; } +} +// Max: 7, Min: 0 (3bit) +ap_uint<3> abs_uint3(ap_uint<3> a, ap_uint<3> b) { +#pragma HLS INLINE + if (a < b) { return b - a; } + else { return a - b; } +} + +// Reference codes: +// http://lethe2211.hatenablog.com/entry/2014/12/30/011030 +// http://www.redblobgames.com/pathfinding/a-star/implementation.html +// Need to modify "array partition factor" +ap_uint search(ap_uint idx, ap_uint paths[MAX_BUFFER], ap_uint start, ap_uint goal, ap_uint<8> w[MAX_CELLS]) { + + ap_uint dist[MAX_CELLS]; + ap_uint prev[MAX_CELLS]; + + SEARCH_INIT_DIST: + for (ap_uint i = 0; i < (ap_uint)(MAX_CELLS); i++) { + dist[i] = 65535; // = (2^16 - 1) + } + + // Priority queue (Circular list) + ap_uint top = 1, bottom = 0; + bool is_empty = true; + ap_uint<32> pq_nodes[MAX_PQ]; +#pragma HLS ARRAY_PARTITION variable=pq_nodes cyclic factor=32 dim=1 +/** Set!: factor=PP **/ + +#ifdef DEBUG_PRINT + int queue_length = 0; + int search_count = 0; +#endif + + // Point of goal terminal + 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_y = (ap_uint<7>)(goal_xy - goal_x * MAX_WIDTH); + ap_uint<3> goal_z = (ap_uint<3>)(goal & BITMASK_Z); + + dist[start] = 0; + pq_push(pq_nodes, 0, start, &top, &bottom, &is_empty); // push start terminal + + SEARCH_PQ: + while (!is_empty) { +#pragma HLS LOOP_TRIPCOUNT min=1 max=1000 +#pragma HLS LOOP_FLATTEN off + + ap_uint<16> prev_cost; + ap_uint<16> src; // target cell + pq_pop(pq_nodes, &prev_cost, &src, &top, &bottom, &is_empty); +#ifdef DEBUG_PRINT + search_count++; +#endif + + + // End routing + if (src == goal) break; + + + // Target cell + ap_uint<16> dist_src = dist[src]; + ap_uint<8> cost = w[src]; + // Point of target cell + 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_y = (ap_uint<7>)(src_xy - src_x * MAX_WIDTH); + ap_uint<3> src_z = (ap_uint<3>)(src & BITMASK_Z); + + // Search adjacent cells + SEARCH_ADJACENTS: + for (ap_uint<3> a = 0; a < 6; a++) { + ap_int<8> dest_x = (ap_int<8>)src_x; // Min: -1, Max: 72 (Signed 8bit) + ap_int<8> dest_y = (ap_int<8>)src_y; // Min: -1, Max: 72 (Signed 8bit) + ap_int<5> dest_z = (ap_int<5>)src_z; // Min: -1, Max: 8 (Signed 5bit) + if (a == 0) { dest_x -= 1; } + if (a == 1) { dest_x += 1; } + if (a == 2) { dest_y -= 1; } + if (a == 3) { dest_y += 1; } + if (a == 4) { dest_z -= 1; } + if (a == 5) { dest_z += 1; } + + // Inside the board ? // + if (0 <= dest_x && dest_x < (ap_int<8>)size_x && 0 <= dest_y && dest_y < (ap_int<8>)size_y && 0 <= dest_z && dest_z < (ap_int<5>)size_z) { + // Adjacent cell + ap_uint<16> dest = (((ap_uint<16>)dest_x * MAX_WIDTH + (ap_uint<16>)dest_y) << BITWIDTH_Z) | (ap_uint<16>)dest_z; + ap_uint<16> dist_new = dist_src + cost; + + if (dist[dest] > dist_new) { + dist[dest] = dist_new; // Update dist + prev[dest] = src; // Recode previous cell + dist_new += abs_uint7(dest_x, goal_x) + abs_uint7(dest_y, goal_y) + abs_uint3(dest_z, goal_z); // A* heuristic + pq_push(pq_nodes, dist_new, dest, &top, &bottom, &is_empty); // push adjacent cell + } + } + } +#ifdef DEBUG_PRINT + if (queue_length < (bottom-top+1)) { queue_length = (bottom-top+1); } +#endif + } + + // Output target path + // Note: Do not include start & goal terminals + ap_uint<16> t = prev[goal]; + + // Backtracking + ap_uint p = idx; // buffer-idx + SEARCH_BACKTRACK: + while (t != start) { +#pragma HLS LOOP_TRIPCOUNT min=1 max=256 + paths[p] = t; + p++; + t = prev[t]; + } + +#ifdef DEBUG_PRINT + if (max_queue_length < queue_length) { max_queue_length = queue_length; } + if (max_search_count < search_count) { max_search_count = search_count; } +#endif + + return p; +} + +// Queue push (Enqueue) +// Need to modify "trip count" (5) +void pq_push(ap_uint<32> pq_nodes[MAX_PQ], ap_uint<16> priority, ap_uint<16> data, ap_uint *top, ap_uint *bottom, bool *is_empty) { +#pragma HLS INLINE + + (*bottom)++; + if ((*bottom) == (*top) && !(*is_empty)) { (*bottom)--; } // Queue is full -> Last element is automatically removed + + // Binary search for circular list + ap_uint t = (*top); + ap_uint b = (*bottom); + ap_uint h = ((ap_uint)(b - t) / 2) + t; + // Note: "h = (t + b) / 2" causes a bug! + PQ_PUSH_BINARY: + while (t != b) { +#pragma HLS LOOP_TRIPCOUNT min=0 max=13 +/** Set!: min=0 max=PQ_BIT **/ + if ((ap_uint<16>)(pq_nodes[h] & PQ_PRIORITY_MASK) >= priority) { + b = h; + } + else { + t = h + 1; + } + h = ((ap_uint)(b - t) / 2) + t; + } + + // Parallel shifting (PP parallel) + ap_uint shift_count = (*bottom) - t; // # of shifting + + ap_uint bottom_H = (*bottom) / PP; // High-order bits of (*bottom) + ap_uint bottom_L = (*bottom) % PP; // Low-order bits of (*bottom) + ap_uint p0 = (*bottom), p1; + if (shift_count > (ap_uint)(bottom_L)) { + // bottom_L bit shift + PQ_PUSH_SHIFT_H_1: + for (ap_uint k = 0; k < (ap_uint)(bottom_L); k++) { +#pragma HLS LOOP_TRIPCOUNT min=0 max=31 +/** Set!: min=0 max=PP-1 **/ + p0 = p0 - 1; // source + p1 = p0 + 1; // destination + pq_nodes[p1] = pq_nodes[p0]; + } + shift_count = shift_count - bottom_L; + } + else { + // shift_count bit shift + PQ_PUSH_SHIFT_H_2: + for (ap_uint k = 0; k < (ap_uint)(shift_count); k++) { +#pragma HLS LOOP_TRIPCOUNT min=0 max=31 +/** Set!: min=0 max=PP-1 **/ + p0 = p0 - 1; // source + p1 = p0 + 1; // destination + pq_nodes[p1] = pq_nodes[p0]; + } + pq_nodes[p0] = ((ap_uint<32>)data << PQ_PRIORITY_WIDTH) | (ap_uint<32>)priority; + *is_empty = false; return; + } + + ap_uint shift_count_i = shift_count >> LOG_PP; + ap_uint shift_count_j = shift_count - (shift_count_i << LOG_PP); + // Note: Bit adjustment is necessary + // when the values of PP & LOG_PP have been changed. + + ap_uint p[PP+1]; +#pragma HLS ARRAY_PARTITION variable=p complete dim=1 + p[0] = bottom_H * PP; + ap_uint<32> tmp[PP]; +#pragma HLS ARRAY_PARTITION variable=tmp complete dim=1 + PQ_PUSH_SHIFT_I: + for (ap_uint i = 0; i < (ap_uint)(shift_count_i); i++) { +#pragma HLS LOOP_TRIPCOUNT min=0 max=255 +/** Set!: min=0 max=(MAX_PQ)/(PP)-1 **/ + p[0] = p[0] - PP; + for (ap_uint k = 1; k <= (ap_uint)(PP); k++) { +#pragma HLS UNROLL + p[k] = p[0] + k; + } + for (ap_uint k = 1; k <= (ap_uint)(PP); k++) { +#pragma HLS UNROLL + tmp[k-1] = pq_nodes[p[k-1]]; + } + for (ap_uint k = 1; k <= (ap_uint)(PP); k++) { +#pragma HLS UNROLL + pq_nodes[p[k]] = tmp[k-1]; + } + } + PQ_PUSH_SHIFT_J: + for (ap_uint j = 0; j < (ap_uint)(shift_count_j); j++) { +#pragma HLS LOOP_TRIPCOUNT min=0 max=31 +/** Set!: min=0 max=PP-1 **/ + p[0] = p[0] - 1; + p[1] = p[0] + 1; + pq_nodes[p[1]] = pq_nodes[p[0]]; + } + pq_nodes[p[0]] = ((ap_uint<32>)data << PQ_PRIORITY_WIDTH) | (ap_uint<32>)priority; + *is_empty = false; +} + +// Queue pop (Dequeue) +void pq_pop(ap_uint<32> pq_nodes[MAX_PQ], ap_uint<16> *ret_priority, ap_uint<16> *ret_data, ap_uint *top, ap_uint *bottom, bool *is_empty) { +#pragma HLS INLINE + + *ret_priority = (ap_uint<16>)(pq_nodes[(*top)] & PQ_PRIORITY_MASK); + *ret_data = (ap_uint<16>)(pq_nodes[(*top)] >> PQ_PRIORITY_WIDTH); + (*top)++; + if (((*bottom)-(*top)+1) == 0) { *is_empty = true; } +} diff --git a/hls_2018/router_02/router.hpp b/hls_2018/router_02/router.hpp new file mode 100755 index 0000000..7a5b241 --- /dev/null +++ b/hls_2018/router_02/router.hpp @@ -0,0 +1,59 @@ +/** + * router.hpp + * + * for Vivado HLS + */ + +#ifndef __ROUTER_HPP__ +#define __ROUTER_HPP__ + +#ifdef SOFTWARE +#include "ap_int.h" +#else +#include +#endif + +//#define DEBUG_PRINT // for debug + +#ifdef DEBUG_PRINT +using namespace std; +#endif + +// Parameters +#define MAX_WIDTH 72 // Max of X, Y +#define BITWIDTH_XY 13 +#define BITMASK_XY 65528 // 1111 1111 1111 1000 +#define MAX_LAYER 8 // Max of Z +#define BITWIDTH_Z 3 +#define BITMASK_Z 7 // 0000 0000 0000 0111 + +#define MAX_CELLS 41472 // Max #cells (16bit) +#define MAX_LINES 1024 // Max #lines (10bit) +#define MAX_PQ 8192 // Queue size (13bit) +#define MAX_BUFFER 16384 // Line buffer size (14bit) +#define CELL_BIT 16 +#define LINE_BIT 10 +#define PQ_BIT 13 +#define BUFF_BIT 14 + +#define PQ_PRIORITY_WIDTH 16 +#define PQ_PRIORITY_MASK 65535 // 0000 0000 0000 0000 1111 1111 1111 1111 +#define PQ_DATA_WIDTH 16 +#define PQ_DATA_MASK 4294901760 // 1111 1111 1111 1111 0000 0000 0000 0000 + +#define MAX_WEIGHT 255 // Max weight +#define BOARDSTR_SIZE 41472 // Size of I/O + +#define PP 32 // Parameter for Parallel shifting in queue push +#define LOG_PP 5 // LOG_PP is log2(PP) + +ap_uint<8> new_weight(ap_uint<16> x); +bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *status); + +ap_uint<7> abs_uint7(ap_uint<7> a, ap_uint<7> b); +ap_uint<3> abs_uint3(ap_uint<3> a, ap_uint<3> b); +ap_uint search(ap_uint idx, ap_uint paths[MAX_BUFFER], ap_uint start, ap_uint goal, ap_uint<8> w[MAX_WEIGHT]); +void pq_push(ap_uint<32> pq_nodes[MAX_PQ], ap_uint<16> priority, ap_uint<16> data, ap_uint *top, ap_uint *bottom, bool *is_empty); +void pq_pop(ap_uint<32> pq_nodes[MAX_PQ], ap_uint<16> *ret_priority, ap_uint<16> *ret_data, ap_uint *top, ap_uint *bottom, bool *is_empty); + +#endif /* __ROUTER_HPP__ */ diff --git a/hls_2018/router_03/router.cpp b/hls_2018/router_03/router.cpp new file mode 100755 index 0000000..a2e01cb --- /dev/null +++ b/hls_2018/router_03/router.cpp @@ -0,0 +1,513 @@ +/** + * router.cpp + * + * for Vivado HLS + */ + +#ifdef SOFTWARE +#include "ap_int.h" +#else +#include +#endif + +#include "./router.hpp" + +// Set weight +ap_uint<8> new_weight(ap_uint<16> x) { +#pragma HLS INLINE + // K. Terada: y = 1~32 (8bit) + ap_uint<8> y; + y = ((x & 255) >> 3) + 1; + return y; +} + + +// Global values +static ap_uint<7> size_x; // X +static ap_uint<7> size_y; // Y +static ap_uint<4> size_z; // Z + +static ap_uint line_num = 0; // #Lines + +#ifdef DEBUG_PRINT +int max_queue_length; // Max length of priority queue +int max_search_count; // Max count of queue pop +int max_buffer_length; // Max length of line buffer +#endif + + +bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *status) { +#pragma HLS INTERFACE s_axilite port=boardstr bundle=AXI4LS +#pragma HLS INTERFACE s_axilite port=seed bundle=AXI4LS +#pragma HLS INTERFACE s_axilite port=status bundle=AXI4LS +#pragma HLS INTERFACE s_axilite port=return bundle=AXI4LS + + // status(0:Solved, 1:Not solved) + *status = -1; + + // For all lines + ap_uint paths[MAX_BUFFER]; // Line buffer + + // For each line + // Note: Should not partition completely + bool adjacents[MAX_LINES]; // Line has adjacent terminals? + ap_uint starts[MAX_LINES]; // Start list + ap_uint goals[MAX_LINES]; // Goal list + ap_uint s_idx[MAX_LINES]; // Start point on line buffer + + ap_uint<8> weights[MAX_CELLS]; // Weight of each cell + // Note: Should not partition weight array + // since each element will be accessed in "random" order + + + // ================================ + // (Step.0) Initialization (BEGIN) + // ================================ + + // Note: Loop counter -> need an extra bit (for condition determination) + + INIT_WEIGHTS: + for (ap_uint i = 0; i < (ap_uint)(MAX_CELLS); i++) { + weights[i] = 1; + } + + /// Parse /// + size_x = (boardstr[1] - '0') * 10 + (boardstr[2] - '0'); + size_y = (boardstr[4] - '0') * 10 + (boardstr[5] - '0'); + size_z = (boardstr[7] - '0'); + + INIT_BOARDS: + for (ap_uint idx = 8; idx < (ap_uint)(BOARDSTR_SIZE); idx+=11) { + + // NULL-terminated + if (boardstr[idx] == 0) break; + + // Start & Goal of each line + ap_uint<7> s_x = (boardstr[idx+1] - '0') * 10 + (boardstr[idx+2] - '0'); + ap_uint<7> s_y = (boardstr[idx+3] - '0') * 10 + (boardstr[idx+4] - '0'); + ap_uint<3> s_z = (boardstr[idx+5] - '0') - 1; + ap_uint<7> g_x = (boardstr[idx+6] - '0') * 10 + (boardstr[idx+7] - '0'); + ap_uint<7> g_y = (boardstr[idx+8] - '0') * 10 + (boardstr[idx+9] - '0'); + ap_uint<3> g_z = (boardstr[idx+10] - '0') - 1; + + ap_uint start_id = (((ap_uint)s_x * MAX_WIDTH + (ap_uint)s_y) << BITWIDTH_Z) | (ap_uint)s_z; + ap_uint goal_id = (((ap_uint)g_x * MAX_WIDTH + (ap_uint)g_y) << BITWIDTH_Z) | (ap_uint)g_z; + starts[line_num] = start_id; + goals[line_num] = goal_id; + weights[start_id] = MAX_WEIGHT; + weights[goal_id] = MAX_WEIGHT; + + // Line has adjacent terminals? + adjacents[line_num] = false; + ap_int<8> dx = (ap_int<8>)g_x - (ap_int<8>)s_x; // Min: -71, Max: 71 (Signed 8bit) + ap_int<8> dy = (ap_int<8>)g_y - (ap_int<8>)s_y; // Min: -71, Max: 71 (Signed 8bit) + ap_int<4> dz = (ap_int<4>)g_z - (ap_int<4>)s_z; // Min: -7, Max: 7 (Signed 4bit) + 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; + } + + line_num++; + } + + // ================================ + // (Step.0) Initialization (END) + // ================================ + +#ifdef DEBUG_PRINT + max_queue_length = 0; + max_search_count = 0; + max_buffer_length = 0; +#endif + + ap_uint pointer = 0; // Pointer for line buffer + + // ================================ + // (Step.1) Initial Routing (BEGIN) + // ================================ + +#ifdef DEBUG_PRINT + cout << "Initial Routing ..." << endl; +#endif + + FIRST_ROUTING: + for (ap_uint i = 0; i < (ap_uint)(line_num); i++) { +#pragma HLS LOOP_TRIPCOUNT min=2 max=999 + + s_idx[i] = pointer; + + if (adjacents[i] == true) continue; // Skip routing + +#ifdef DEBUG_PRINT + //cout << "LINE #" << (int)(i + 1) << endl; +#endif + // Routing + pointer = search(s_idx[i], paths, starts[i], goals[i], weights); + } + + // ================================ + // (Step.1) Initial Routing (END) + // ================================ + + + // Memories for Overlap Check + ap_uint<1> overlap_checks[MAX_CELLS]; + bool has_overlap = false; + + // ================================ + // (Step.2) Rip-up Routing (BEGIN) + // ================================ + +#ifdef DEBUG_PRINT + cout << "Rip-up Routing ..." << endl; +#endif + + ROUTING: + for (ap_uint<16> round = 0; round < 32768 /* = (2048 * 16) */; round++) { +#pragma HLS LOOP_TRIPCOUNT min=1 max=32768 + + // Target line + ap_uint target = round % line_num; + ap_uint next_target = target + 1; + if (next_target == line_num) next_target = 0; + +#ifdef DEBUG_PRINT + cout << "(round " << round << ") LINE #" << (int)(target + 1); + cout << " -> " << pointer << endl; +#endif +#ifdef DEBUG_PRINT + int buffer_length = pointer - s_idx[target]; + if (max_buffer_length < buffer_length) { max_buffer_length = buffer_length; } +#endif + + // Skip routing + if (adjacents[target] == true) { + s_idx[target] = pointer; continue; + } + + + // (Step.2-1) Reset weights of target line + WEIGHT_RESET: + for (ap_uint j = s_idx[target]; j != s_idx[next_target]; j++) { +#pragma HLS LOOP_TRIPCOUNT min=1 max=256 + weights[paths[j]] = 1; + } + + // (Step.2-2) Set weights of non-target lines and terminals + ap_uint<8> current_round_weight = new_weight(round); + WEIGHT_PATH: + for (ap_uint j = s_idx[next_target]; j != pointer; j++) { +#pragma HLS LOOP_TRIPCOUNT min=1 max=8192 + weights[paths[j]] = current_round_weight; + } + WEIGHT_TERMINAL: + for (ap_uint i = 0; i < (ap_uint)(line_num); i++) { +#pragma HLS LOOP_TRIPCOUNT min=2 max=999 + weights[starts[i]] = MAX_WEIGHT; + weights[goals[i]] = MAX_WEIGHT; + } + // Reset weight of start terminal of target line (bug avoiding) + // Restore original settings in (*) + weights[starts[target]] = 1; + + // (Step.2-3) Routing + s_idx[target] = pointer; + pointer = search(s_idx[target], paths, starts[target], goals[target], weights); + + // (*) + weights[starts[target]] = MAX_WEIGHT; + +#ifdef DEBUG_PRINT + bool ng = false; + for (ap_uint i = 0; i < (ap_uint)(line_num); i++) { + if (weights[starts[i]] != 255 || weights[goals[i]] != 255) { + cout << i << " "; ng = true; + } + } + if(ng) { cout << endl; } +#endif + + // (Step.2-4) Overlap check + has_overlap = false; + OVERLAP_RESET: + for (ap_uint i = 0; i < (ap_uint)(MAX_CELLS); i++) { + overlap_checks[i] = 0; + } + OVERLAP_CHECK_LINE: + for (ap_uint i = 0; i < (ap_uint)(line_num); i++) { +#pragma HLS LOOP_TRIPCOUNT min=2 max=999 + overlap_checks[starts[i]] = 1; + overlap_checks[goals[i]] = 1; + } + OVERLAP_CHECK_PATH: + for (ap_uint j = s_idx[next_target]; j != pointer; j++) { +#pragma HLS LOOP_TRIPCOUNT min=1 max=8192 + ap_uint cell_id = paths[j]; + if (overlap_checks[cell_id]) { + has_overlap = true; break; + } + overlap_checks[cell_id] = 1; + } +#ifdef DEBUG_PRINT + if(!has_overlap){ cout << "ROUND: " << round << endl; } +#endif + if (!has_overlap) break; // Finish routing? + } + +#ifdef DEBUG_PRINT + cout << "MAX PQ LENGTH: " << max_queue_length << endl; + cout << "MAX SEARCH COUNT: " << max_search_count << endl; + cout << "MAX BUFFER: " << max_buffer_length << endl; +#endif + + // Not solved + if (has_overlap) { + *status = 1; return false; + } + + // ================================ + // (Step.2) Rip-up Routing (END) + // ================================ + + + // ================================ + // (Step.3) Output (BEGIN) + // ================================ + +#ifdef DEBUG_PRINT + cout << "Output ..." << endl; +#endif + + // Init: Blank = 0 + OUTPUT_INIT: + for (ap_uint i = 0; i < (ap_uint)(MAX_CELLS); i++) { + boardstr[i] = 0; + } + // Line + OUTPUT_LINE: + for (ap_uint i = 0; i < (ap_uint)(line_num); i++) { +#pragma HLS LOOP_TRIPCOUNT min=2 max=999 + boardstr[starts[i]] = (i + 1); + boardstr[goals[i]] = (i + 1); + + ap_uint p1; // p1: s_idx of target + ap_uint p2; // p2: s_idx of next target + p1 = s_idx[i]; + if (i == (ap_uint)(line_num-1)) { + p2 = s_idx[0]; + } + else { + p2 = s_idx[i+1]; + } + if ((ap_uint)(p2 - p1) > 8192){ + p2 = pointer; + } + OUTPUT_LINE_PATH: + for (ap_uint j = p1; j != p2; j++) { +#pragma HLS LOOP_TRIPCOUNT min=1 max=256 + boardstr[paths[j]] = (i + 1); + } + } + + // ================================ + // (Step.3) Output (END) + // ================================ + + *status = 0; return true; +} + + +// ================================ // +// For Routing +// ================================ // + +// Max: 71, Min: 0 (7bit) +ap_uint<7> abs_uint7(ap_uint<7> a, ap_uint<7> b) { +#pragma HLS INLINE + if (a < b) { return b - a; } + else { return a - b; } +} +// Max: 7, Min: 0 (3bit) +ap_uint<3> abs_uint3(ap_uint<3> a, ap_uint<3> b) { +#pragma HLS INLINE + if (a < b) { return b - a; } + else { return a - b; } +} + +// Reference codes: +// http://lethe2211.hatenablog.com/entry/2014/12/30/011030 +// http://www.redblobgames.com/pathfinding/a-star/implementation.html +// Need to modify "array partition factor" +ap_uint search(ap_uint idx, ap_uint paths[MAX_BUFFER], ap_uint start, ap_uint goal, ap_uint<8> w[MAX_CELLS]) { + + ap_uint dist[MAX_CELLS]; + ap_uint prev[MAX_CELLS]; + + SEARCH_INIT_DIST: + for (ap_uint i = 0; i < (ap_uint)(MAX_CELLS); i++) { + dist[i] = 65535; // = (2^16 - 1) + } + + // Priority queue (Heap) + ap_uint pq_len = 0; + bool is_empty = true; + ap_uint<32> pq_nodes[MAX_PQ]; + +#ifdef DEBUG_PRINT + int queue_length = 0; + int search_count = 0; +#endif + + // Point of goal terminal + 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_y = (ap_uint<7>)(goal_xy - goal_x * MAX_WIDTH); + ap_uint<3> goal_z = (ap_uint<3>)(goal & BITMASK_Z); + + dist[start] = 0; + pq_push(pq_nodes, 0, start, &pq_len, &is_empty); // push start terminal + + SEARCH_PQ: + while (!is_empty) { +#pragma HLS LOOP_TRIPCOUNT min=1 max=1000 +#pragma HLS LOOP_FLATTEN off + + ap_uint<16> prev_cost; + ap_uint<16> src; // target cell + pq_pop(pq_nodes, &prev_cost, &src, &pq_len, &is_empty); +#ifdef DEBUG_PRINT + search_count++; +#endif + + + // End routing + if (src == goal) break; + + + // Target cell + ap_uint<16> dist_src = dist[src]; + ap_uint<8> cost = w[src]; + // Point of target cell + 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_y = (ap_uint<7>)(src_xy - src_x * MAX_WIDTH); + ap_uint<3> src_z = (ap_uint<3>)(src & BITMASK_Z); + + // Search adjacent cells + SEARCH_ADJACENTS: + for (ap_uint<3> a = 0; a < 6; a++) { + ap_int<8> dest_x = (ap_int<8>)src_x; // Min: -1, Max: 72 (Signed 8bit) + ap_int<8> dest_y = (ap_int<8>)src_y; // Min: -1, Max: 72 (Signed 8bit) + ap_int<5> dest_z = (ap_int<5>)src_z; // Min: -1, Max: 8 (Signed 5bit) + if (a == 0) { dest_x -= 1; } + if (a == 1) { dest_x += 1; } + if (a == 2) { dest_y -= 1; } + if (a == 3) { dest_y += 1; } + if (a == 4) { dest_z -= 1; } + if (a == 5) { dest_z += 1; } + + // Inside the board ? // + if (0 <= dest_x && dest_x < (ap_int<8>)size_x && 0 <= dest_y && dest_y < (ap_int<8>)size_y && 0 <= dest_z && dest_z < (ap_int<5>)size_z) { + // Adjacent cell + ap_uint<16> dest = (((ap_uint<16>)dest_x * MAX_WIDTH + (ap_uint<16>)dest_y) << BITWIDTH_Z) | (ap_uint<16>)dest_z; + ap_uint<16> dist_new = dist_src + cost; + + if (dist[dest] > dist_new) { + dist[dest] = dist_new; // Update dist + prev[dest] = src; // Recode previous cell + dist_new += abs_uint7(dest_x, goal_x) + abs_uint7(dest_y, goal_y) + abs_uint3(dest_z, goal_z); // A* heuristic + pq_push(pq_nodes, dist_new, dest, &pq_len, &is_empty); // push adjacent cell + } + } + } +#ifdef DEBUG_PRINT + if (queue_length < pq_len) { queue_length = pq_len; } +#endif + } + + // Output target path + // Note: Do not include start & goal terminals + ap_uint<16> t = prev[goal]; + + // Backtracking + ap_uint p = idx; // buffer-idx + SEARCH_BACKTRACK: + while (t != start) { +#pragma HLS LOOP_TRIPCOUNT min=1 max=256 + paths[p] = t; + p++; + t = prev[t]; + } + +#ifdef DEBUG_PRINT + if (max_queue_length < queue_length) { max_queue_length = queue_length; } + if (max_search_count < search_count) { max_search_count = search_count; } +#endif + + return p; +} + +// Queue push (Enqueue) +// Need to modify "trip count" (1) +void pq_push(ap_uint<32> pq_nodes[MAX_PQ], ap_uint<16> priority, ap_uint<16> data, ap_uint *pq_len, bool *is_empty) { +#pragma HLS INLINE + + (*pq_len)++; + if ((*pq_len) == 0) { (*pq_len)--; } // Queue is full -> Last element is automatically removed + + // Binary search for circular list + ap_uint i = (*pq_len); + ap_uint p = (*pq_len) >> 1; // parent node + PQ_PUSH_LOOP: + while (i > 1 && (ap_uint<16>)(pq_nodes[p] & PQ_PRIORITY_MASK) >= priority) { +#pragma HLS LOOP_TRIPCOUNT min=0 max=16 +/** Set!: min=0 max=PQ_BIT **/ + pq_nodes[i] = pq_nodes[p]; + i = p; + p = p >> 1; // parent node + } + pq_nodes[i] = ((ap_uint<32>)data << PQ_PRIORITY_WIDTH) | (ap_uint<32>)priority; + *is_empty = false; +} + +// Queue pop (Dequeue) +// Need to modify "trip count" (1) +void pq_pop(ap_uint<32> pq_nodes[MAX_PQ], ap_uint<16> *ret_priority, ap_uint<16> *ret_data, ap_uint *pq_len, bool *is_empty) { +#pragma HLS INLINE + + *ret_priority = (ap_uint<16>)(pq_nodes[1] & PQ_PRIORITY_MASK); + *ret_data = (ap_uint<16>)(pq_nodes[1] >> PQ_PRIORITY_WIDTH); + + ap_uint i = 1; // root node + ap_uint last_priority = (ap_uint<16>)(pq_nodes[*pq_len] & PQ_PRIORITY_MASK); // Priority of last element + + PQ_POP_LOOP: + while (1) { +#pragma HLS LOOP_TRIPCOUNT min=1 max=16 +/** Set!: min=0 max=PQ_BIT **/ + ap_uint c1 = i << 1; // child node(left) + ap_uint c2 = c1 + 1; // child node(right) + 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)) { + pq_nodes[i] = pq_nodes[c2]; + i = c2; + } + else { + pq_nodes[i] = pq_nodes[c1]; + i = c1; + } + } + else { + if (c2 < *pq_len && (ap_uint<16>)(pq_nodes[c2] & PQ_PRIORITY_MASK) <= last_priority) { + pq_nodes[i] = pq_nodes[c2]; + i = c2; + } + else { + break; + } + } + } + pq_nodes[i] = pq_nodes[*pq_len]; + (*pq_len)--; + if ((*pq_len) == 0) { *is_empty = true; } +} + diff --git a/hls_2018/router_03/router.hpp b/hls_2018/router_03/router.hpp new file mode 100755 index 0000000..0f523d4 --- /dev/null +++ b/hls_2018/router_03/router.hpp @@ -0,0 +1,56 @@ +/** + * router.hpp + * + * for Vivado HLS + */ + +#ifndef __ROUTER_HPP__ +#define __ROUTER_HPP__ + +#ifdef SOFTWARE +#include "ap_int.h" +#else +#include +#endif + +//#define DEBUG_PRINT // for debug + +#ifdef DEBUG_PRINT +using namespace std; +#endif + +// Parameters +#define MAX_WIDTH 72 // Max of X, Y +#define BITWIDTH_XY 13 +#define BITMASK_XY 65528 // 1111 1111 1111 1000 +#define MAX_LAYER 8 // Max of Z +#define BITWIDTH_Z 3 +#define BITMASK_Z 7 // 0000 0000 0000 0111 + +#define MAX_CELLS 41472 // Max #cells (16bit) +#define MAX_LINES 1024 // Max #lines (10bit) +#define MAX_PQ 32768 // Queue size (15bit) +#define MAX_BUFFER 16384 // Line buffer size (14bit) +#define CELL_BIT 16 +#define LINE_BIT 10 +#define PQ_BIT 15 +#define BUFF_BIT 14 + +#define PQ_PRIORITY_WIDTH 16 +#define PQ_PRIORITY_MASK 65535 // 0000 0000 0000 0000 1111 1111 1111 1111 +#define PQ_DATA_WIDTH 16 +#define PQ_DATA_MASK 4294901760 // 1111 1111 1111 1111 0000 0000 0000 0000 + +#define MAX_WEIGHT 255 // Max weight +#define BOARDSTR_SIZE 41472 // Size of I/O + +ap_uint<8> new_weight(ap_uint<16> x); +bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *status); + +ap_uint<7> abs_uint7(ap_uint<7> a, ap_uint<7> b); +ap_uint<3> abs_uint3(ap_uint<3> a, ap_uint<3> b); +ap_uint search(ap_uint idx, ap_uint paths[MAX_BUFFER], ap_uint start, ap_uint goal, ap_uint<8> w[MAX_WEIGHT]); +void pq_push(ap_uint<32> pq_nodes[MAX_PQ], ap_uint<16> priority, ap_uint<16> data, ap_uint *pq_len, bool *is_empty); +void pq_pop(ap_uint<32> pq_nodes[MAX_PQ], ap_uint<16> *ret_priority, ap_uint<16> *ret_data, ap_uint *pq_len, bool *is_empty); + +#endif /* __ROUTER_HPP__ */ diff --git a/hls_2018/router_04/router.cpp b/hls_2018/router_04/router.cpp new file mode 100755 index 0000000..a2e01cb --- /dev/null +++ b/hls_2018/router_04/router.cpp @@ -0,0 +1,513 @@ +/** + * router.cpp + * + * for Vivado HLS + */ + +#ifdef SOFTWARE +#include "ap_int.h" +#else +#include +#endif + +#include "./router.hpp" + +// Set weight +ap_uint<8> new_weight(ap_uint<16> x) { +#pragma HLS INLINE + // K. Terada: y = 1~32 (8bit) + ap_uint<8> y; + y = ((x & 255) >> 3) + 1; + return y; +} + + +// Global values +static ap_uint<7> size_x; // X +static ap_uint<7> size_y; // Y +static ap_uint<4> size_z; // Z + +static ap_uint line_num = 0; // #Lines + +#ifdef DEBUG_PRINT +int max_queue_length; // Max length of priority queue +int max_search_count; // Max count of queue pop +int max_buffer_length; // Max length of line buffer +#endif + + +bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *status) { +#pragma HLS INTERFACE s_axilite port=boardstr bundle=AXI4LS +#pragma HLS INTERFACE s_axilite port=seed bundle=AXI4LS +#pragma HLS INTERFACE s_axilite port=status bundle=AXI4LS +#pragma HLS INTERFACE s_axilite port=return bundle=AXI4LS + + // status(0:Solved, 1:Not solved) + *status = -1; + + // For all lines + ap_uint paths[MAX_BUFFER]; // Line buffer + + // For each line + // Note: Should not partition completely + bool adjacents[MAX_LINES]; // Line has adjacent terminals? + ap_uint starts[MAX_LINES]; // Start list + ap_uint goals[MAX_LINES]; // Goal list + ap_uint s_idx[MAX_LINES]; // Start point on line buffer + + ap_uint<8> weights[MAX_CELLS]; // Weight of each cell + // Note: Should not partition weight array + // since each element will be accessed in "random" order + + + // ================================ + // (Step.0) Initialization (BEGIN) + // ================================ + + // Note: Loop counter -> need an extra bit (for condition determination) + + INIT_WEIGHTS: + for (ap_uint i = 0; i < (ap_uint)(MAX_CELLS); i++) { + weights[i] = 1; + } + + /// Parse /// + size_x = (boardstr[1] - '0') * 10 + (boardstr[2] - '0'); + size_y = (boardstr[4] - '0') * 10 + (boardstr[5] - '0'); + size_z = (boardstr[7] - '0'); + + INIT_BOARDS: + for (ap_uint idx = 8; idx < (ap_uint)(BOARDSTR_SIZE); idx+=11) { + + // NULL-terminated + if (boardstr[idx] == 0) break; + + // Start & Goal of each line + ap_uint<7> s_x = (boardstr[idx+1] - '0') * 10 + (boardstr[idx+2] - '0'); + ap_uint<7> s_y = (boardstr[idx+3] - '0') * 10 + (boardstr[idx+4] - '0'); + ap_uint<3> s_z = (boardstr[idx+5] - '0') - 1; + ap_uint<7> g_x = (boardstr[idx+6] - '0') * 10 + (boardstr[idx+7] - '0'); + ap_uint<7> g_y = (boardstr[idx+8] - '0') * 10 + (boardstr[idx+9] - '0'); + ap_uint<3> g_z = (boardstr[idx+10] - '0') - 1; + + ap_uint start_id = (((ap_uint)s_x * MAX_WIDTH + (ap_uint)s_y) << BITWIDTH_Z) | (ap_uint)s_z; + ap_uint goal_id = (((ap_uint)g_x * MAX_WIDTH + (ap_uint)g_y) << BITWIDTH_Z) | (ap_uint)g_z; + starts[line_num] = start_id; + goals[line_num] = goal_id; + weights[start_id] = MAX_WEIGHT; + weights[goal_id] = MAX_WEIGHT; + + // Line has adjacent terminals? + adjacents[line_num] = false; + ap_int<8> dx = (ap_int<8>)g_x - (ap_int<8>)s_x; // Min: -71, Max: 71 (Signed 8bit) + ap_int<8> dy = (ap_int<8>)g_y - (ap_int<8>)s_y; // Min: -71, Max: 71 (Signed 8bit) + ap_int<4> dz = (ap_int<4>)g_z - (ap_int<4>)s_z; // Min: -7, Max: 7 (Signed 4bit) + 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; + } + + line_num++; + } + + // ================================ + // (Step.0) Initialization (END) + // ================================ + +#ifdef DEBUG_PRINT + max_queue_length = 0; + max_search_count = 0; + max_buffer_length = 0; +#endif + + ap_uint pointer = 0; // Pointer for line buffer + + // ================================ + // (Step.1) Initial Routing (BEGIN) + // ================================ + +#ifdef DEBUG_PRINT + cout << "Initial Routing ..." << endl; +#endif + + FIRST_ROUTING: + for (ap_uint i = 0; i < (ap_uint)(line_num); i++) { +#pragma HLS LOOP_TRIPCOUNT min=2 max=999 + + s_idx[i] = pointer; + + if (adjacents[i] == true) continue; // Skip routing + +#ifdef DEBUG_PRINT + //cout << "LINE #" << (int)(i + 1) << endl; +#endif + // Routing + pointer = search(s_idx[i], paths, starts[i], goals[i], weights); + } + + // ================================ + // (Step.1) Initial Routing (END) + // ================================ + + + // Memories for Overlap Check + ap_uint<1> overlap_checks[MAX_CELLS]; + bool has_overlap = false; + + // ================================ + // (Step.2) Rip-up Routing (BEGIN) + // ================================ + +#ifdef DEBUG_PRINT + cout << "Rip-up Routing ..." << endl; +#endif + + ROUTING: + for (ap_uint<16> round = 0; round < 32768 /* = (2048 * 16) */; round++) { +#pragma HLS LOOP_TRIPCOUNT min=1 max=32768 + + // Target line + ap_uint target = round % line_num; + ap_uint next_target = target + 1; + if (next_target == line_num) next_target = 0; + +#ifdef DEBUG_PRINT + cout << "(round " << round << ") LINE #" << (int)(target + 1); + cout << " -> " << pointer << endl; +#endif +#ifdef DEBUG_PRINT + int buffer_length = pointer - s_idx[target]; + if (max_buffer_length < buffer_length) { max_buffer_length = buffer_length; } +#endif + + // Skip routing + if (adjacents[target] == true) { + s_idx[target] = pointer; continue; + } + + + // (Step.2-1) Reset weights of target line + WEIGHT_RESET: + for (ap_uint j = s_idx[target]; j != s_idx[next_target]; j++) { +#pragma HLS LOOP_TRIPCOUNT min=1 max=256 + weights[paths[j]] = 1; + } + + // (Step.2-2) Set weights of non-target lines and terminals + ap_uint<8> current_round_weight = new_weight(round); + WEIGHT_PATH: + for (ap_uint j = s_idx[next_target]; j != pointer; j++) { +#pragma HLS LOOP_TRIPCOUNT min=1 max=8192 + weights[paths[j]] = current_round_weight; + } + WEIGHT_TERMINAL: + for (ap_uint i = 0; i < (ap_uint)(line_num); i++) { +#pragma HLS LOOP_TRIPCOUNT min=2 max=999 + weights[starts[i]] = MAX_WEIGHT; + weights[goals[i]] = MAX_WEIGHT; + } + // Reset weight of start terminal of target line (bug avoiding) + // Restore original settings in (*) + weights[starts[target]] = 1; + + // (Step.2-3) Routing + s_idx[target] = pointer; + pointer = search(s_idx[target], paths, starts[target], goals[target], weights); + + // (*) + weights[starts[target]] = MAX_WEIGHT; + +#ifdef DEBUG_PRINT + bool ng = false; + for (ap_uint i = 0; i < (ap_uint)(line_num); i++) { + if (weights[starts[i]] != 255 || weights[goals[i]] != 255) { + cout << i << " "; ng = true; + } + } + if(ng) { cout << endl; } +#endif + + // (Step.2-4) Overlap check + has_overlap = false; + OVERLAP_RESET: + for (ap_uint i = 0; i < (ap_uint)(MAX_CELLS); i++) { + overlap_checks[i] = 0; + } + OVERLAP_CHECK_LINE: + for (ap_uint i = 0; i < (ap_uint)(line_num); i++) { +#pragma HLS LOOP_TRIPCOUNT min=2 max=999 + overlap_checks[starts[i]] = 1; + overlap_checks[goals[i]] = 1; + } + OVERLAP_CHECK_PATH: + for (ap_uint j = s_idx[next_target]; j != pointer; j++) { +#pragma HLS LOOP_TRIPCOUNT min=1 max=8192 + ap_uint cell_id = paths[j]; + if (overlap_checks[cell_id]) { + has_overlap = true; break; + } + overlap_checks[cell_id] = 1; + } +#ifdef DEBUG_PRINT + if(!has_overlap){ cout << "ROUND: " << round << endl; } +#endif + if (!has_overlap) break; // Finish routing? + } + +#ifdef DEBUG_PRINT + cout << "MAX PQ LENGTH: " << max_queue_length << endl; + cout << "MAX SEARCH COUNT: " << max_search_count << endl; + cout << "MAX BUFFER: " << max_buffer_length << endl; +#endif + + // Not solved + if (has_overlap) { + *status = 1; return false; + } + + // ================================ + // (Step.2) Rip-up Routing (END) + // ================================ + + + // ================================ + // (Step.3) Output (BEGIN) + // ================================ + +#ifdef DEBUG_PRINT + cout << "Output ..." << endl; +#endif + + // Init: Blank = 0 + OUTPUT_INIT: + for (ap_uint i = 0; i < (ap_uint)(MAX_CELLS); i++) { + boardstr[i] = 0; + } + // Line + OUTPUT_LINE: + for (ap_uint i = 0; i < (ap_uint)(line_num); i++) { +#pragma HLS LOOP_TRIPCOUNT min=2 max=999 + boardstr[starts[i]] = (i + 1); + boardstr[goals[i]] = (i + 1); + + ap_uint p1; // p1: s_idx of target + ap_uint p2; // p2: s_idx of next target + p1 = s_idx[i]; + if (i == (ap_uint)(line_num-1)) { + p2 = s_idx[0]; + } + else { + p2 = s_idx[i+1]; + } + if ((ap_uint)(p2 - p1) > 8192){ + p2 = pointer; + } + OUTPUT_LINE_PATH: + for (ap_uint j = p1; j != p2; j++) { +#pragma HLS LOOP_TRIPCOUNT min=1 max=256 + boardstr[paths[j]] = (i + 1); + } + } + + // ================================ + // (Step.3) Output (END) + // ================================ + + *status = 0; return true; +} + + +// ================================ // +// For Routing +// ================================ // + +// Max: 71, Min: 0 (7bit) +ap_uint<7> abs_uint7(ap_uint<7> a, ap_uint<7> b) { +#pragma HLS INLINE + if (a < b) { return b - a; } + else { return a - b; } +} +// Max: 7, Min: 0 (3bit) +ap_uint<3> abs_uint3(ap_uint<3> a, ap_uint<3> b) { +#pragma HLS INLINE + if (a < b) { return b - a; } + else { return a - b; } +} + +// Reference codes: +// http://lethe2211.hatenablog.com/entry/2014/12/30/011030 +// http://www.redblobgames.com/pathfinding/a-star/implementation.html +// Need to modify "array partition factor" +ap_uint search(ap_uint idx, ap_uint paths[MAX_BUFFER], ap_uint start, ap_uint goal, ap_uint<8> w[MAX_CELLS]) { + + ap_uint dist[MAX_CELLS]; + ap_uint prev[MAX_CELLS]; + + SEARCH_INIT_DIST: + for (ap_uint i = 0; i < (ap_uint)(MAX_CELLS); i++) { + dist[i] = 65535; // = (2^16 - 1) + } + + // Priority queue (Heap) + ap_uint pq_len = 0; + bool is_empty = true; + ap_uint<32> pq_nodes[MAX_PQ]; + +#ifdef DEBUG_PRINT + int queue_length = 0; + int search_count = 0; +#endif + + // Point of goal terminal + 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_y = (ap_uint<7>)(goal_xy - goal_x * MAX_WIDTH); + ap_uint<3> goal_z = (ap_uint<3>)(goal & BITMASK_Z); + + dist[start] = 0; + pq_push(pq_nodes, 0, start, &pq_len, &is_empty); // push start terminal + + SEARCH_PQ: + while (!is_empty) { +#pragma HLS LOOP_TRIPCOUNT min=1 max=1000 +#pragma HLS LOOP_FLATTEN off + + ap_uint<16> prev_cost; + ap_uint<16> src; // target cell + pq_pop(pq_nodes, &prev_cost, &src, &pq_len, &is_empty); +#ifdef DEBUG_PRINT + search_count++; +#endif + + + // End routing + if (src == goal) break; + + + // Target cell + ap_uint<16> dist_src = dist[src]; + ap_uint<8> cost = w[src]; + // Point of target cell + 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_y = (ap_uint<7>)(src_xy - src_x * MAX_WIDTH); + ap_uint<3> src_z = (ap_uint<3>)(src & BITMASK_Z); + + // Search adjacent cells + SEARCH_ADJACENTS: + for (ap_uint<3> a = 0; a < 6; a++) { + ap_int<8> dest_x = (ap_int<8>)src_x; // Min: -1, Max: 72 (Signed 8bit) + ap_int<8> dest_y = (ap_int<8>)src_y; // Min: -1, Max: 72 (Signed 8bit) + ap_int<5> dest_z = (ap_int<5>)src_z; // Min: -1, Max: 8 (Signed 5bit) + if (a == 0) { dest_x -= 1; } + if (a == 1) { dest_x += 1; } + if (a == 2) { dest_y -= 1; } + if (a == 3) { dest_y += 1; } + if (a == 4) { dest_z -= 1; } + if (a == 5) { dest_z += 1; } + + // Inside the board ? // + if (0 <= dest_x && dest_x < (ap_int<8>)size_x && 0 <= dest_y && dest_y < (ap_int<8>)size_y && 0 <= dest_z && dest_z < (ap_int<5>)size_z) { + // Adjacent cell + ap_uint<16> dest = (((ap_uint<16>)dest_x * MAX_WIDTH + (ap_uint<16>)dest_y) << BITWIDTH_Z) | (ap_uint<16>)dest_z; + ap_uint<16> dist_new = dist_src + cost; + + if (dist[dest] > dist_new) { + dist[dest] = dist_new; // Update dist + prev[dest] = src; // Recode previous cell + dist_new += abs_uint7(dest_x, goal_x) + abs_uint7(dest_y, goal_y) + abs_uint3(dest_z, goal_z); // A* heuristic + pq_push(pq_nodes, dist_new, dest, &pq_len, &is_empty); // push adjacent cell + } + } + } +#ifdef DEBUG_PRINT + if (queue_length < pq_len) { queue_length = pq_len; } +#endif + } + + // Output target path + // Note: Do not include start & goal terminals + ap_uint<16> t = prev[goal]; + + // Backtracking + ap_uint p = idx; // buffer-idx + SEARCH_BACKTRACK: + while (t != start) { +#pragma HLS LOOP_TRIPCOUNT min=1 max=256 + paths[p] = t; + p++; + t = prev[t]; + } + +#ifdef DEBUG_PRINT + if (max_queue_length < queue_length) { max_queue_length = queue_length; } + if (max_search_count < search_count) { max_search_count = search_count; } +#endif + + return p; +} + +// Queue push (Enqueue) +// Need to modify "trip count" (1) +void pq_push(ap_uint<32> pq_nodes[MAX_PQ], ap_uint<16> priority, ap_uint<16> data, ap_uint *pq_len, bool *is_empty) { +#pragma HLS INLINE + + (*pq_len)++; + if ((*pq_len) == 0) { (*pq_len)--; } // Queue is full -> Last element is automatically removed + + // Binary search for circular list + ap_uint i = (*pq_len); + ap_uint p = (*pq_len) >> 1; // parent node + PQ_PUSH_LOOP: + while (i > 1 && (ap_uint<16>)(pq_nodes[p] & PQ_PRIORITY_MASK) >= priority) { +#pragma HLS LOOP_TRIPCOUNT min=0 max=16 +/** Set!: min=0 max=PQ_BIT **/ + pq_nodes[i] = pq_nodes[p]; + i = p; + p = p >> 1; // parent node + } + pq_nodes[i] = ((ap_uint<32>)data << PQ_PRIORITY_WIDTH) | (ap_uint<32>)priority; + *is_empty = false; +} + +// Queue pop (Dequeue) +// Need to modify "trip count" (1) +void pq_pop(ap_uint<32> pq_nodes[MAX_PQ], ap_uint<16> *ret_priority, ap_uint<16> *ret_data, ap_uint *pq_len, bool *is_empty) { +#pragma HLS INLINE + + *ret_priority = (ap_uint<16>)(pq_nodes[1] & PQ_PRIORITY_MASK); + *ret_data = (ap_uint<16>)(pq_nodes[1] >> PQ_PRIORITY_WIDTH); + + ap_uint i = 1; // root node + ap_uint last_priority = (ap_uint<16>)(pq_nodes[*pq_len] & PQ_PRIORITY_MASK); // Priority of last element + + PQ_POP_LOOP: + while (1) { +#pragma HLS LOOP_TRIPCOUNT min=1 max=16 +/** Set!: min=0 max=PQ_BIT **/ + ap_uint c1 = i << 1; // child node(left) + ap_uint c2 = c1 + 1; // child node(right) + 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)) { + pq_nodes[i] = pq_nodes[c2]; + i = c2; + } + else { + pq_nodes[i] = pq_nodes[c1]; + i = c1; + } + } + else { + if (c2 < *pq_len && (ap_uint<16>)(pq_nodes[c2] & PQ_PRIORITY_MASK) <= last_priority) { + pq_nodes[i] = pq_nodes[c2]; + i = c2; + } + else { + break; + } + } + } + pq_nodes[i] = pq_nodes[*pq_len]; + (*pq_len)--; + if ((*pq_len) == 0) { *is_empty = true; } +} + diff --git a/hls_2018/router_04/router.hpp b/hls_2018/router_04/router.hpp new file mode 100755 index 0000000..0f523d4 --- /dev/null +++ b/hls_2018/router_04/router.hpp @@ -0,0 +1,56 @@ +/** + * router.hpp + * + * for Vivado HLS + */ + +#ifndef __ROUTER_HPP__ +#define __ROUTER_HPP__ + +#ifdef SOFTWARE +#include "ap_int.h" +#else +#include +#endif + +//#define DEBUG_PRINT // for debug + +#ifdef DEBUG_PRINT +using namespace std; +#endif + +// Parameters +#define MAX_WIDTH 72 // Max of X, Y +#define BITWIDTH_XY 13 +#define BITMASK_XY 65528 // 1111 1111 1111 1000 +#define MAX_LAYER 8 // Max of Z +#define BITWIDTH_Z 3 +#define BITMASK_Z 7 // 0000 0000 0000 0111 + +#define MAX_CELLS 41472 // Max #cells (16bit) +#define MAX_LINES 1024 // Max #lines (10bit) +#define MAX_PQ 32768 // Queue size (15bit) +#define MAX_BUFFER 16384 // Line buffer size (14bit) +#define CELL_BIT 16 +#define LINE_BIT 10 +#define PQ_BIT 15 +#define BUFF_BIT 14 + +#define PQ_PRIORITY_WIDTH 16 +#define PQ_PRIORITY_MASK 65535 // 0000 0000 0000 0000 1111 1111 1111 1111 +#define PQ_DATA_WIDTH 16 +#define PQ_DATA_MASK 4294901760 // 1111 1111 1111 1111 0000 0000 0000 0000 + +#define MAX_WEIGHT 255 // Max weight +#define BOARDSTR_SIZE 41472 // Size of I/O + +ap_uint<8> new_weight(ap_uint<16> x); +bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *status); + +ap_uint<7> abs_uint7(ap_uint<7> a, ap_uint<7> b); +ap_uint<3> abs_uint3(ap_uint<3> a, ap_uint<3> b); +ap_uint search(ap_uint idx, ap_uint paths[MAX_BUFFER], ap_uint start, ap_uint goal, ap_uint<8> w[MAX_WEIGHT]); +void pq_push(ap_uint<32> pq_nodes[MAX_PQ], ap_uint<16> priority, ap_uint<16> data, ap_uint *pq_len, bool *is_empty); +void pq_pop(ap_uint<32> pq_nodes[MAX_PQ], ap_uint<16> *ret_priority, ap_uint<16> *ret_data, ap_uint *pq_len, bool *is_empty); + +#endif /* __ROUTER_HPP__ */ -- 2.22.0 From b8153fb64e8bf67dcb559412465b2b6b49751b66 Mon Sep 17 00:00:00 2001 From: Kazushi Kawamura Date: Fri, 24 Aug 2018 18:12:21 +0900 Subject: [PATCH 02/30] Add README.md --- hls_2018/README.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 hls_2018/README.md diff --git a/hls_2018/README.md b/hls_2018/README.md new file mode 100644 index 0000000..bb8612e --- /dev/null +++ b/hls_2018/README.md @@ -0,0 +1,28 @@ +# pynq-router (sw) + +PYNQ-router for Vivado-HLS (2018 ver.) + +## Types of router + +|Name|Operation name|Description| +|:---|:---|:---| +|01|TBD|Line-number-free router for PYNQ-Z1. Priority queue is implemented with circular array(non-parallel)| +|02|TBD|Line-number-free router for PYNQ-Z1. Priority queue is implemented with circular array(parallel)| +|03|TBD|Line-number-free router for PYNQ-Z1. Priority queue is implemented with heap(size:2^15)| +|04|TBD|Line-number-free router for AVNET-Ultra96. Priority queue is implemented with heap(size:2^16)| + +## Memo + +* Vivado HLS 2018.2 +* Vivado 2018.2 + +Options: +* Part: xc7z020clg400-1 (PYNQ-Z1), xczu3eg-sbva484-1-i (AVNET-Ultra96) +* Clock Period: 10.0 ns +* Clock Uncertainty: 3.0 ns +* Synthesis strategy: Vivado Synthesis Defaults +* Implementation strategy: Vivado Implementation Defaults + +## I/O +* Input/Output: boardstr, seed, &status, return + -- 2.22.0 From 4a343721499e81da7c568abdf155e2946f498102 Mon Sep 17 00:00:00 2001 From: Kazushi Kawamura Date: Fri, 24 Aug 2018 18:34:43 +0900 Subject: [PATCH 03/30] Modify README.md --- hls_2018/README.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/hls_2018/README.md b/hls_2018/README.md index bb8612e..3994d6f 100644 --- a/hls_2018/README.md +++ b/hls_2018/README.md @@ -6,10 +6,10 @@ PYNQ-router for Vivado-HLS (2018 ver.) |Name|Operation name|Description| |:---|:---|:---| -|01|TBD|Line-number-free router for PYNQ-Z1. Priority queue is implemented with circular array(non-parallel)| -|02|TBD|Line-number-free router for PYNQ-Z1. Priority queue is implemented with circular array(parallel)| -|03|TBD|Line-number-free router for PYNQ-Z1. Priority queue is implemented with heap(size:2^15)| -|04|TBD|Line-number-free router for AVNET-Ultra96. Priority queue is implemented with heap(size:2^16)| +|01|TBD|*Line-number-free* router for "PYNQ-Z1". Priority queue is implemented with circular array(non-parallel)| +|02|TBD|*Line-number-free* router for "PYNQ-Z1". Priority queue is implemented with circular array(parallel)| +|03|TBD|*Line-number-free* router for "PYNQ-Z1". Priority queue is implemented with heap(size:$`2^{15}`$)| +|04|TBD|*Line-number-free* router for "AVNET-Ultra96". Priority queue is implemented with heap(size:$`2^{16}`$)| ## Memo @@ -24,5 +24,8 @@ Options: * Implementation strategy: Vivado Implementation Defaults ## I/O -* Input/Output: boardstr, seed, &status, return +* Input/Output: boardstr(8bit\*41472), seed(32bit), &status(32bit), return(1bit) + +## Results +TODO -- 2.22.0 From df65dc85db6cb270a60c887ddfd31eca10fe2c59 Mon Sep 17 00:00:00 2001 From: Kazushi Kawamura Date: Fri, 24 Aug 2018 19:50:36 +0900 Subject: [PATCH 04/30] Upload files --- hls_2018/router_01/Makefile | 20 + hls_2018/router_01/Makefile.cygwin | 14 + hls_2018/router_01/ap_int.h | 521 +++ hls_2018/router_01/etc/ap_fixed_sim.h | 2451 +++++++++++ hls_2018/router_01/etc/ap_int_sim.h | 1629 +++++++ hls_2018/router_01/etc/ap_private.h | 5858 +++++++++++++++++++++++++ hls_2018/router_01/main.cpp | 97 + hls_2018/router_02/Makefile | 20 + hls_2018/router_02/Makefile.cygwin | 14 + hls_2018/router_02/ap_int.h | 521 +++ hls_2018/router_02/etc/ap_fixed_sim.h | 2451 +++++++++++ hls_2018/router_02/etc/ap_int_sim.h | 1629 +++++++ hls_2018/router_02/etc/ap_private.h | 5858 +++++++++++++++++++++++++ hls_2018/router_02/main.cpp | 97 + hls_2018/router_03/Makefile | 20 + hls_2018/router_03/Makefile.cygwin | 14 + hls_2018/router_03/ap_int.h | 521 +++ hls_2018/router_03/etc/ap_fixed_sim.h | 2451 +++++++++++ hls_2018/router_03/etc/ap_int_sim.h | 1629 +++++++ hls_2018/router_03/etc/ap_private.h | 5858 +++++++++++++++++++++++++ hls_2018/router_03/main.cpp | 97 + hls_2018/router_03/router.cpp | 4 +- hls_2018/router_04/Makefile | 20 + hls_2018/router_04/Makefile.cygwin | 14 + hls_2018/router_04/ap_int.h | 521 +++ hls_2018/router_04/etc/ap_fixed_sim.h | 2451 +++++++++++ hls_2018/router_04/etc/ap_int_sim.h | 1629 +++++++ hls_2018/router_04/etc/ap_private.h | 5858 +++++++++++++++++++++++++ hls_2018/router_04/main.cpp | 97 + hls_2018/router_04/router.cpp | 4 +- hls_2018/router_04/router.hpp | 4 +- 31 files changed, 42366 insertions(+), 6 deletions(-) create mode 100755 hls_2018/router_01/Makefile create mode 100755 hls_2018/router_01/Makefile.cygwin create mode 100755 hls_2018/router_01/ap_int.h create mode 100755 hls_2018/router_01/etc/ap_fixed_sim.h create mode 100755 hls_2018/router_01/etc/ap_int_sim.h create mode 100755 hls_2018/router_01/etc/ap_private.h create mode 100755 hls_2018/router_01/main.cpp create mode 100755 hls_2018/router_02/Makefile create mode 100755 hls_2018/router_02/Makefile.cygwin create mode 100755 hls_2018/router_02/ap_int.h create mode 100755 hls_2018/router_02/etc/ap_fixed_sim.h create mode 100755 hls_2018/router_02/etc/ap_int_sim.h create mode 100755 hls_2018/router_02/etc/ap_private.h create mode 100755 hls_2018/router_02/main.cpp create mode 100755 hls_2018/router_03/Makefile create mode 100755 hls_2018/router_03/Makefile.cygwin create mode 100755 hls_2018/router_03/ap_int.h create mode 100755 hls_2018/router_03/etc/ap_fixed_sim.h create mode 100755 hls_2018/router_03/etc/ap_int_sim.h create mode 100755 hls_2018/router_03/etc/ap_private.h create mode 100755 hls_2018/router_03/main.cpp create mode 100755 hls_2018/router_04/Makefile create mode 100755 hls_2018/router_04/Makefile.cygwin create mode 100755 hls_2018/router_04/ap_int.h create mode 100755 hls_2018/router_04/etc/ap_fixed_sim.h create mode 100755 hls_2018/router_04/etc/ap_int_sim.h create mode 100755 hls_2018/router_04/etc/ap_private.h create mode 100755 hls_2018/router_04/main.cpp diff --git a/hls_2018/router_01/Makefile b/hls_2018/router_01/Makefile new file mode 100755 index 0000000..8f79e7a --- /dev/null +++ b/hls_2018/router_01/Makefile @@ -0,0 +1,20 @@ +TARGET = sim +OBJS = $(CPPS:.cpp=.o) +CPPS = $(wildcard *.cpp) +CXX = g++ +CXXFLAGS = -O3 -Wall -Wno-unknown-pragmas -Wno-unused-label -DSOFTWARE -DCALCTIME + +all: $(TARGET) + +$(TARGET): $(OBJS) + $(CXX) -O3 -o $@ $(OBJS) + +run: + python3 ../NLGenerator.py -x 20 -y 20 -z 6 -l 100;\ + python3 ./gen_boardstr.py Q-20x20x5_100_10.txt |\ + ./$(TARGET) - + + +clean: + rm *.o + rm $(TARGET) diff --git a/hls_2018/router_01/Makefile.cygwin b/hls_2018/router_01/Makefile.cygwin new file mode 100755 index 0000000..866fdcd --- /dev/null +++ b/hls_2018/router_01/Makefile.cygwin @@ -0,0 +1,14 @@ +TARGET = sim +OBJS = $(CPPS:.cpp=.o) +CPPS = $(wildcard *.cpp) +CXX = g++ +CXXFLAGS = -O3 -Wall -Wno-unknown-pragmas -Wno-unused-label -DSOFTWARE -DCALCTIME + +all: $(TARGET) + +$(TARGET): $(OBJS) + $(CXX) -O3 -Wl,--stack,33554432 -o $@ $(OBJS) + +clean: + rm *.o + rm $(TARGET) diff --git a/hls_2018/router_01/ap_int.h b/hls_2018/router_01/ap_int.h new file mode 100755 index 0000000..b8d9fdc --- /dev/null +++ b/hls_2018/router_01/ap_int.h @@ -0,0 +1,521 @@ +/* + * Copyright 2012 Xilinx, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __AESL_AP_SIM_H__ +#define __AESL_AP_SIM_H__ + +#ifndef __cplusplus +#error C++ is required to include this header file +#else + +#include "etc/ap_int_sim.h" +#include "etc/ap_fixed_sim.h" + +//Forward declaration +template class ap_fixed; +template class ap_ufixed; +template class ap_int; +template class ap_uint; + +//AP_INT +//-------------------------------------------------------- +template +class ap_int : public ap_private<_AP_W, true> { +#ifdef _MSC_VER +#pragma warning(disable: 4521 4522) +#endif /* #ifdef _MSC_VER */ +public: + typedef ap_private<_AP_W, true> Base; + + //Constructor + INLINE ap_int(): Base() {} + template + INLINE ap_int(const volatile ap_int<_AP_W2> &op):Base((const ap_private<_AP_W2,true> &)(op)) {} + + template + INLINE ap_int(const ap_int<_AP_W2> &op):Base((const ap_private<_AP_W2,true> &)(op)) {} + + template + INLINE ap_int(const ap_uint<_AP_W2> &op):Base((const ap_private<_AP_W2,false> &)(op)) {} + + template + INLINE ap_int(const volatile ap_uint<_AP_W2> &op):Base((const ap_private<_AP_W2,false> &)(op)) {} + + template + INLINE ap_int(const ap_range_ref<_AP_W2, _AP_S2>& ref):Base(ref) {} + + template + INLINE ap_int(const ap_bit_ref<_AP_W2, _AP_S2>& ref):Base(ref) {} + + template + INLINE ap_int(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& ref):Base(ref) {} + + template + INLINE ap_int(const ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op.to_ap_private()) {} + + template + INLINE ap_int(const ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op.to_ap_private()) {} + + template + INLINE ap_int(const volatile ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op.to_ap_private()) {} + + template + INLINE ap_int(const volatile ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op.to_ap_private()) {} + + template + INLINE ap_int(const ap_private<_AP_W2, _AP_S2>& op):Base(op) {} + + template + INLINE ap_int(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, + _AP_N2>& op):Base(op) {} + + template + INLINE ap_int(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, + _AP_N2>& op):Base(op) {} + + template + INLINE ap_int(const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& op):Base(op.to_ap_private()) {} + +#define CTOR(TYPE) \ + INLINE ap_int(TYPE v):Base(v) {} + CTOR(bool) + CTOR(signed char) + CTOR(unsigned char) + CTOR(short) + CTOR(unsigned short) + CTOR(int) + CTOR(unsigned int) + CTOR(long) + CTOR(unsigned long) + CTOR(unsigned long long) + CTOR(long long) + CTOR(float) + CTOR(double) + CTOR(const char*) + CTOR(const std::string&) +#undef CTOR + INLINE ap_int(const char* str, signed char rd):Base(str, rd) {} + //Assignment + //Another form of "write" + INLINE void operator = (const ap_int<_AP_W>& op2) volatile { + const_cast(this)->operator = (op2); + } + + INLINE void operator = (const volatile ap_int<_AP_W>& op2) volatile { + const_cast(this)->operator = (op2); + } + + INLINE ap_int<_AP_W>& operator = (const volatile ap_int<_AP_W>& op2) { + Base::operator = (const_cast& >(op2)); + return *this; + } + + INLINE ap_int<_AP_W>& operator = (const ap_int<_AP_W>& op2) { + Base::operator = ((const ap_private<_AP_W, true>&)op2); + return *this; + } +}; + +//AP_UINT +//--------------------------------------------------------------- +template +class ap_uint: public ap_private<_AP_W, false> { +#ifdef _MSC_VER +#pragma warning( disable : 4521 4522 ) +#endif +public: + typedef ap_private<_AP_W, false> Base; + //Constructor + INLINE ap_uint(): Base() {} + INLINE ap_uint(const ap_uint<_AP_W>& op) :Base(dynamic_cast&>(op)) {} + INLINE ap_uint(const volatile ap_uint<_AP_W>& op):Base(dynamic_cast&>(op)){} + template + INLINE ap_uint(const volatile ap_uint<_AP_W2> &op):Base((const ap_private<_AP_W2, false>&)(op)) {} + + template + INLINE ap_uint(const ap_uint<_AP_W2> &op) : Base((const ap_private<_AP_W2, false>&)(op)){} + + template + INLINE ap_uint(const ap_int<_AP_W2> &op) : Base((const ap_private<_AP_W2, true>&)(op)) {} + + template + INLINE ap_uint(const volatile ap_int<_AP_W2> &op) : Base((const ap_private<_AP_W2, false>&)(op)) {} + + template + INLINE ap_uint(const ap_range_ref<_AP_W2, _AP_S2>& ref):Base(ref) {} + + template + INLINE ap_uint(const ap_bit_ref<_AP_W2, _AP_S2>& ref):Base(ref) {} + + template + INLINE ap_uint(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& ref):Base(ref) {} + + template + INLINE ap_uint(const ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op.to_ap_private()) {} + + template + INLINE ap_uint(const ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op.to_ap_private()) {} + + template + INLINE ap_uint(const volatile ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op.to_ap_private()) {} + + template + INLINE ap_uint(const volatile ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op) {} + + template + INLINE ap_uint(const ap_private<_AP_W2, _AP_S2>& op):Base(op) {} + + template + INLINE ap_uint(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, + _AP_N2>& op):Base(op) {} + + template + INLINE ap_uint(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, + _AP_N2>& op):Base(op) {} + + template + INLINE ap_uint(const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& op):Base(op.to_ap_private()) {} + +#define CTOR(TYPE) \ + INLINE ap_uint(TYPE v):Base(v) {} + CTOR(bool) + CTOR(signed char) + CTOR(unsigned char) + CTOR(short) + CTOR(unsigned short) + CTOR(int) + CTOR(unsigned int) + CTOR(long) + CTOR(unsigned long) + CTOR(unsigned long long) + CTOR(long long) + CTOR(float) + CTOR(double) + CTOR(const char*) + CTOR(const std::string&) +#undef CTOR + INLINE ap_uint(const char* str, signed char rd):Base(str, rd) {} + //Assignment + //Another form of "write" + INLINE void operator = (const ap_uint<_AP_W>& op2) volatile { + Base::operator = (op2); + } + + INLINE void operator = (const volatile ap_uint<_AP_W>& op2) volatile { + Base::operator = (op2); + } + + INLINE ap_uint<_AP_W>& operator = (const volatile ap_uint<_AP_W>& op2) { + Base::operator = (op2); + return *this; + } + + INLINE ap_uint<_AP_W>& operator = (const ap_uint<_AP_W>& op2) { + Base::operator = ((const ap_private<_AP_W, false>&)(op2)); + return *this; + } +}; + +#define ap_bigint ap_int +#define ap_biguint ap_uint + +//AP_FIXED +//--------------------------------------------------------------------- +template +class ap_fixed: public ap_fixed_base<_AP_W, _AP_I, true, _AP_Q, _AP_O, _AP_N> { +#ifdef _MSC_VER +#pragma warning( disable : 4521 4522 ) +#endif +public: + typedef ap_fixed_base<_AP_W, _AP_I, true, _AP_Q, _AP_O, _AP_N> Base; + //Constructor + INLINE ap_fixed():Base() {} + + template + INLINE ap_fixed(const ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, + _AP_N2>& op): Base(op) {} + + template + INLINE ap_fixed(const ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, + _AP_N2>& op): Base(ap_fixed_base<_AP_W2, _AP_I2, + false, _AP_Q2, _AP_O2, _AP_N2>(op)) {} + + template + INLINE ap_fixed(const ap_int<_AP_W2>& op): + Base(ap_private<_AP_W2, true>(op)) {} + + template + INLINE ap_fixed(const ap_uint<_AP_W2>& op):Base(ap_private<_AP_W2, false>(op)) {} + + template + INLINE ap_fixed(const volatile ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, + _AP_N2>& op): Base(ap_fixed_base<_AP_W2, _AP_I2, + true, _AP_Q2, _AP_O2, _AP_N2>(op)) {} + + template + INLINE ap_fixed(const volatile ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, + _AP_N2>& op): Base(ap_fixed_base<_AP_W2, _AP_I2, + false, _AP_Q2, _AP_O2, _AP_N2>(op)) {} + + template + INLINE ap_fixed(const volatile ap_int<_AP_W2>& op): + Base(ap_private<_AP_W2, true>(op)) {} + + template + INLINE ap_fixed(const volatile ap_uint<_AP_W2>& op):Base(op) {} + + template + INLINE ap_fixed(const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& op):Base(op) {} + + template + INLINE ap_fixed(const ap_bit_ref<_AP_W2, _AP_S2>& op): + Base(op) {} + + template + INLINE ap_fixed(const ap_range_ref<_AP_W2, _AP_S2>& op): + Base(op) {} + + template + INLINE ap_fixed(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& op): + Base(op) {} + + template + INLINE ap_fixed(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& op): Base(op) {} + + template + INLINE ap_fixed(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& op): Base(op) {} + + template + INLINE ap_fixed(const ap_private<_AP_W2, _AP_S2>& op):Base(op) {} + + #define CTOR(TYPE) \ + INLINE ap_fixed(TYPE v):Base(v) {} + CTOR(bool) + CTOR(signed char) + CTOR(unsigned char) + CTOR(short) + CTOR(unsigned short) + CTOR(int) + CTOR(unsigned int) + CTOR(long) + CTOR(unsigned long) + CTOR(unsigned long long) + CTOR(long long) + CTOR(float) + CTOR(double) + CTOR(const char*) + CTOR(const std::string&) +#undef CTOR + INLINE ap_fixed(const char* str, signed char rd):Base(str, rd) {} + + //Assignment + INLINE ap_fixed& operator = (const ap_fixed<_AP_W, _AP_I, + _AP_Q, _AP_O, _AP_N>& op) { + Base::operator = (op); + return *this; + } + + INLINE ap_fixed& operator = (const volatile ap_fixed<_AP_W, _AP_I, + _AP_Q, _AP_O, _AP_N>& op) { + Base::operator = (op); + return *this; + } +}; + +//AP_ UFIXED +//--- ---------------------------------------------------------------- +template +class ap_ufixed : public ap_fixed_base<_AP_W, _AP_I, false, _AP_Q, _AP_O, _AP_N> { +#ifdef _MSC_VER +#pragma warning(disable: 4521 4522) +#endif /* #ifdef _MSC_VER */ +public: + typedef ap_fixed_base<_AP_W, _AP_I, false, _AP_Q, _AP_O, _AP_N> Base; + + //Constructor + INLINE ap_ufixed():Base() {} + + template + INLINE ap_ufixed(const ap_fixed<_AP_W2, _AP_I2, _AP_Q2, + _AP_O2, _AP_N2>& op) : Base(ap_fixed_base<_AP_W2, + _AP_I2, true, _AP_Q2, _AP_O2, _AP_N2>(op)) {} + + template + INLINE ap_ufixed(const ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, + _AP_O2, _AP_N2>& op): Base(ap_fixed_base<_AP_W2, _AP_I2, + false, _AP_Q2, _AP_O2, _AP_N2>(op)) {} + + template + INLINE ap_ufixed(const ap_int<_AP_W2>& op): + Base((const ap_private<_AP_W2, true>&)(op)) {} + + template + INLINE ap_ufixed(const ap_uint<_AP_W2>& op): + Base((const ap_private<_AP_W2, false>&)(op)) {} + + template + INLINE ap_ufixed(const volatile ap_fixed<_AP_W2, _AP_I2, _AP_Q2, + _AP_O2, _AP_N2>& op) : Base(ap_fixed_base<_AP_W2, + _AP_I2, true, _AP_Q2, _AP_O2, _AP_N2>(op)) {} + + template + INLINE ap_ufixed(const volatile ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, + _AP_O2, _AP_N2>& op): Base(ap_fixed_base<_AP_W2, _AP_I2, + false, _AP_Q2, _AP_O2, _AP_N2>(op)) {} + + template + INLINE ap_ufixed(const volatile ap_int<_AP_W2>& op): + Base(ap_private<_AP_W2, true>(op)) {} + + template + INLINE ap_ufixed(const volatile ap_uint<_AP_W2>& op): + Base(ap_private<_AP_W2, false>(op)) {} + + template + INLINE ap_ufixed(const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2>& op):Base(op) {} + + template + INLINE ap_ufixed(const ap_bit_ref<_AP_W2, _AP_S2>& op): + Base(op) {} + + template + INLINE ap_ufixed(const ap_range_ref<_AP_W2, _AP_S2>& op): + Base(op) {} + + template + INLINE ap_ufixed(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& op): + Base(op) {} + + template + INLINE ap_ufixed(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& op): Base(op) {} + + template + INLINE ap_ufixed(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& op): Base(op) {} + + template + INLINE ap_ufixed(const ap_private<_AP_W2, _AP_S2>& op):Base(op) {} + + #define CTOR(TYPE) \ + INLINE ap_ufixed(TYPE v):Base(v) {} + CTOR(bool) + CTOR(signed char) + CTOR(unsigned char) + CTOR(short) + CTOR(unsigned short) + CTOR(int) + CTOR(unsigned int) + CTOR(long) + CTOR(unsigned long) + CTOR(unsigned long long) + CTOR(long long) + CTOR(float) + CTOR(double) + CTOR(const char*) + CTOR(const std::string&) +#undef CTOR + INLINE ap_ufixed(const char* str, signed char rd):Base(str, rd) {} + + //Assignment + INLINE ap_ufixed& operator = (const ap_ufixed<_AP_W, _AP_I, + _AP_Q, _AP_O, _AP_N>& op) { + Base::operator = (op); + return *this; + } + + INLINE ap_ufixed& operator = (const volatile ap_ufixed<_AP_W, _AP_I, + _AP_Q, _AP_O, _AP_N>& op) { + Base::V = const_cast(op); + return *this; + } +}; + +#if defined(SYSTEMC_H) || defined(SYSTEMC_INCLUDED) +template +INLINE void sc_trace(sc_core::sc_trace_file *tf, const ap_int<_AP_W> &op, + const std::string &name) { + if (tf) + tf->trace(sc_dt::sc_lv<_AP_W>(op.to_string(2).c_str()), name); +} + +template +INLINE void sc_trace(sc_core::sc_trace_file *tf, const ap_uint<_AP_W> &op, + const std::string &name) { + if (tf) + tf->trace(sc_dt::sc_lv<_AP_W>(op.to_string(2).c_str()), name); +} + +template +INLINE void sc_trace(sc_core::sc_trace_file *tf, const ap_fixed<_AP_W, _AP_I, _AP_Q, _AP_O, _AP_N >&op, const std::string &name) { + tf->trace(sc_dt::sc_lv<_AP_W>(op.to_string(2).c_str()), name); +} + +template +INLINE void sc_trace(sc_core::sc_trace_file *tf, const ap_ufixed<_AP_W, _AP_I, _AP_Q, _AP_O, _AP_N >&op, const std::string &name) { + tf->trace(sc_dt::sc_lv<_AP_W>(op.to_string(2).c_str()), name); +} +#endif /* #if defined(SYSTEMC_H) || defined(SYSTEMC_INCLUDED) */ +#endif /* #ifndef __cplusplus */ +#endif /* #ifndef __AESL_AP_SIM_H__ */ \ No newline at end of file diff --git a/hls_2018/router_01/etc/ap_fixed_sim.h b/hls_2018/router_01/etc/ap_fixed_sim.h new file mode 100755 index 0000000..5be571d --- /dev/null +++ b/hls_2018/router_01/etc/ap_fixed_sim.h @@ -0,0 +1,2451 @@ +/* + * Copyright 2012 Xilinx, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __AESL_GCC_AP_FIXED_H__ +#define __AESL_GCC_AP_FIXED_H__ + +#ifndef __cplusplus + #error C++ is required to include this header file +#endif /* #ifndef __cplusplus */ + + +#include +#ifndef __AESL_APDT_IN_SCFLOW__ + #include "etc/ap_int_sim.h" +#else + #include "../etc/ap_private.h" +#endif /* #ifndef __AESL_APDT_IN_SCFLOW__ */ + +#define FLOAT_MAN 23 +#define FLOAT_EXP 8 +#define DOUBLE_MAN 52 +#define DOUBLE_EXP 11 +// #define DOUBLE_MAN_MASK (~0ULL >> (64-DOUBLE_MAN-2)) +#define DOUBLE_MAN_MASK 0x3fffffffffffffULL +#define BIAS(e) ((1ULL<<(e-1))-1) +#define FLOAT_BIAS BIAS(FLOAT_EXP) +#define DOUBLE_BIAS BIAS(DOUBLE_EXP) + +/// Forward declaration. +template struct ap_fixed_base; + +///Proxy class, which allows bit selection to be used as both rvalue(for reading) and +//lvalue(for writing) +template +struct af_bit_ref { +#ifdef _MSC_VER + #pragma warning(disable: 4521 4522) +#endif /* #ifdef _MSC_VER */ + ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& d_bv; + int d_index; +public: + INLINE af_bit_ref(const af_bit_ref<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& ref): + d_bv(ref.d_bv), d_index(ref.d_index) {} + + INLINE af_bit_ref(ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>* bv, int index=0): + d_bv(*bv),d_index(index) {} + + INLINE operator bool() const { + return d_bv.V[d_index]; + } + + INLINE af_bit_ref& operator=(unsigned long long val) { + if (val) + d_bv.V.set(d_index); + else + d_bv.V.clear(d_index); + return *this; + } + + template + INLINE af_bit_ref& operator =(const ap_private<_AP_W2,_AP_S2>& val) { + return operator=(val!=0); + } + + INLINE af_bit_ref& operator =(const af_bit_ref<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& val) { + return operator=((unsigned long long)(bool)val); + } + + template + INLINE af_bit_ref operator=(const af_bit_ref<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& val) { + return operator=((unsigned long long)(bool)val); + } + + template + INLINE af_bit_ref& operator = ( const ap_bit_ref<_AP_W2, _AP_S2> &val) { + return operator =((unsigned long long) (bool) val); + } + + template + INLINE af_bit_ref& operator = ( const ap_range_ref<_AP_W2,_AP_S2>& val) { + return operator =((const ap_private<_AP_W2, false>) val); + } + + template + INLINE af_bit_ref& operator= (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& val) { + return operator=((const ap_private<_AP_W2, false>)(val)); + } + + template + INLINE af_bit_ref& operator= (const ap_concat_ref<_AP_W2, _AP_T3, _AP_W3, _AP_T3>& val) { + return operator=((const ap_private<_AP_W2 + _AP_W3, false>)(val)); + } + + template + INLINE ap_concat_ref<1, af_bit_ref, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (ap_private<_AP_W2, _AP_S2>& op) { + return ap_concat_ref<1, af_bit_ref, _AP_W2, + ap_private<_AP_W2, _AP_S2> >(*this, op); + } + + template + INLINE ap_concat_ref<1, af_bit_ref, 1, ap_bit_ref<_AP_W2, _AP_S2> > + operator, (const ap_bit_ref<_AP_W2, _AP_S2> &op) { + return ap_concat_ref<1, af_bit_ref, 1, + ap_bit_ref<_AP_W2, _AP_S2> >(*this, + const_cast& >(op)); + } + + template + INLINE ap_concat_ref<1, af_bit_ref, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > + operator, (const ap_range_ref<_AP_W2, _AP_S2> &op) { + return ap_concat_ref<1, af_bit_ref, _AP_W2, + ap_range_ref<_AP_W2, _AP_S2> >(*this, + const_cast& >(op)); + } + + template + INLINE ap_concat_ref<1, af_bit_ref, _AP_W2 + _AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > + operator, (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &op) { + return ap_concat_ref<1, af_bit_ref, _AP_W2 + _AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(*this, + const_cast& >(op)); + } + + template + INLINE ap_concat_ref<1, af_bit_ref, _AP_W2, + af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &op) { + return ap_concat_ref<1, af_bit_ref, _AP_W2, + af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, + _AP_N2> >(*this, const_cast& >(op)); + } + + template + INLINE ap_concat_ref<1, af_bit_ref, 1, + af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &op) { + return ap_concat_ref<1, af_bit_ref, 1, + af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, + const_cast& >(op)); + } + + template + INLINE bool operator == (const af_bit_ref<_AP_W2, _AP_I2, + _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) { + return get() == op.get(); + } + + template + INLINE bool operator != (const af_bit_ref<_AP_W2, _AP_I2, + _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) { + return get() != op.get(); + } + + INLINE bool operator ~ () const { + bool bit = (d_bv.V)[d_index]; + return bit ? false : true; + } + + INLINE int length() const { + return 1; + } + + INLINE bool get() { + return d_bv.V[d_index]; + } + + INLINE bool get() const { + return d_bv.V[d_index]; + } + + INLINE std::string to_string() const { + return d_bv.V[d_index] ? "1" : "0"; + } +}; + +///Range(slice) reference +//------------------------------------------------------------ +template +struct af_range_ref { +#ifdef _MSC_VER + #pragma warning(disable: 4521 4522) +#endif /* #ifdef _MSC_VER */ + ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &d_bv; + int l_index; + int h_index; + +public: + INLINE af_range_ref(const af_range_ref<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& ref): + d_bv(ref.d_bv), l_index(ref.l_index), h_index(ref.h_index) {} + + INLINE af_range_ref(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>* bv, int h, int l): + d_bv(*bv),l_index(l),h_index(h) { + //if (h < l) + // fprintf(stderr, + //"Warning! The bits selected will be returned in reverse order\n"); + } + + INLINE operator ap_private<_AP_W, false> () const { + if (h_index >= l_index) { + ap_private<_AP_W, false> val(d_bv.V); + ap_private<_AP_W,false> mask(-1); + mask>>=_AP_W-(h_index-l_index+1); + val>>=l_index; + return val&=mask; + } else { + ap_private<_AP_W, false> val = 0; + for (int i=0, j=l_index;j>=0&&j>=h_index;j--,i++) + if ((d_bv.V)[j]) val.set(i); + return val; + } + } + + INLINE operator unsigned long long() const { + return get().to_uint64(); + } + + template + INLINE af_range_ref& operator =(const ap_private<_AP_W2,_AP_S2>& val) { + ap_private<_AP_W, false> vval= ap_private<_AP_W, false>(val); + if (l_index > h_index) { + for (int i=0, j=l_index;j>=0&&j>=h_index;j--,i++) + vval[i]? d_bv.V.set(j):d_bv.V.clear(j); + } else { + ap_private<_AP_W,false> mask(-1); + if (l_index>0) { + mask<<=l_index; + vval<<=l_index; + } + if (h_index<_AP_W-1) { + ap_private<_AP_W,false> mask2(-1); + mask2>>=_AP_W-h_index-1; + mask&=mask2; + vval&=mask2; + } + mask.flip(); + d_bv.V &= mask; + d_bv.V |= vval; + } + return *this; + } + + INLINE af_range_ref& operator = (unsigned long long val) { + const ap_private<_AP_W, false> tmpVal(val); + return operator = (tmpVal); + } + + template + INLINE af_range_ref& operator = + (const ap_concat_ref <_AP_W3, _AP_T3, _AP_W4, _AP_T4>& val) { + const ap_private<_AP_W, false> tmpVal(val); + return operator = (tmpVal); + } + + template + INLINE af_range_ref& operator =(const ap_bit_ref<_AP_W3, _AP_S3>& val) { + const ap_private<_AP_W, false> tmpVal(val); + return operator = (tmpVal); + } + + template + INLINE af_range_ref& operator =(const ap_range_ref<_AP_W3,_AP_S3>& val) { + const ap_private<_AP_W, false> tmpVal(val); + return operator =(tmpVal); + } + + template + INLINE af_range_ref& operator= (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& val) { + const ap_private<_AP_W2, false> tmp= val.get(); + return operator = (tmp); + } + + INLINE af_range_ref& operator= (const af_range_ref<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& val) { + const ap_private<_AP_W, false> tmp= val.get(); + return operator = (tmp); + } + + template + INLINE af_range_ref& operator= (const ap_fixed_base<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& val) { + return operator=(val.to_ap_private()); + } + + template + INLINE bool operator == (const ap_range_ref<_AP_W2, _AP_S2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs==rhs; + } + + template + INLINE bool operator != (const ap_range_ref<_AP_W2, _AP_S2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs!=rhs; + } + + template + INLINE bool operator > (const ap_range_ref<_AP_W2, _AP_S2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs>rhs; + } + + template + INLINE bool operator >= (const ap_range_ref<_AP_W2, _AP_S2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs>=rhs; + } + + template + INLINE bool operator < (const ap_range_ref<_AP_W2, _AP_S2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs + INLINE bool operator <= (const ap_range_ref<_AP_W2, _AP_S2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs<=rhs; + } + + template + INLINE bool operator == (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs==rhs; + } + + template + INLINE bool operator != (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs!=rhs; + } + + template + INLINE bool operator > (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs>rhs; + } + + template + INLINE bool operator >= (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs>=rhs; + } + + template + INLINE bool operator < (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs + INLINE bool operator <= (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs<=rhs; + } + + template + INLINE void set(const ap_private<_AP_W2,false>& val) { + ap_private<_AP_W,_AP_S> vval=val; + if (l_index>h_index) { + for (int i=0, j=l_index;j>=0&&j>=h_index;j--,i++) + vval[i]? d_bv.V.set(j):d_bv.V.clear(j); + } else { + ap_private<_AP_W,_AP_S> mask(-1); + if (l_index>0) { + ap_private<_AP_W,false> mask1(-1); + mask1>>=_AP_W-l_index; + mask1.flip(); + mask=mask1; + //vval&=mask1; + vval<<=l_index; + } + if (h_index<_AP_W-1) { + ap_private<_AP_W,false> mask2(-1); + mask2<<=h_index+1; + mask2.flip(); + mask&=mask2; + vval&=mask2; + } + mask.flip(); + d_bv&=mask; + d_bv|=vval; + } + + } + + INLINE ap_private<_AP_W,false> get() const { + if (h_index val(0); + for (int i=0, j=l_index;j>=0&&j>=h_index;j--,i++) + if ((d_bv.V)[j]) val.set(i); + return val; + } else { + ap_private<_AP_W, false> val = ap_private<_AP_W,false>(d_bv.V); + val>>= l_index; + if (h_index<_AP_W-1) + { + ap_private<_AP_W,false> mask(-1); + mask>>=_AP_W-(h_index-l_index+1); + val&=mask; + } + return val; + } + } + + template + INLINE ap_concat_ref<_AP_W, af_range_ref, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (ap_private<_AP_W2, _AP_S2>& op) { + return ap_concat_ref<_AP_W, af_range_ref, _AP_W2, + ap_private<_AP_W2, _AP_S2> >(*this, op); + } + + template + INLINE ap_concat_ref<_AP_W, af_range_ref, 1, ap_bit_ref<_AP_W2, _AP_S2> > + operator, (const ap_bit_ref<_AP_W2, _AP_S2> &op) { + return ap_concat_ref<_AP_W, af_range_ref, 1, + ap_bit_ref<_AP_W2, _AP_S2> >(*this, + const_cast& >(op)); + } + + template + INLINE ap_concat_ref<_AP_W, af_range_ref, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > + operator, (const ap_range_ref<_AP_W2, _AP_S2> &op) { + return ap_concat_ref<_AP_W, af_range_ref, _AP_W2, + ap_range_ref<_AP_W2, _AP_S2> >(*this, + const_cast& >(op)); + } + + template + INLINE ap_concat_ref<_AP_W, af_range_ref, _AP_W2 + _AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > + operator, (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &op) { + return ap_concat_ref<_AP_W, af_range_ref, _AP_W2 + _AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(*this, + const_cast& >(op)); + } + + template + INLINE ap_concat_ref<_AP_W, af_range_ref, _AP_W2, + af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &op) { + return ap_concat_ref<_AP_W, af_range_ref, _AP_W2, + af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, + const_cast& > (op)); + } + + template + INLINE ap_concat_ref<_AP_W, af_range_ref, 1, + af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &op) { + return ap_concat_ref<_AP_W, af_range_ref, 1, + af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, + const_cast& >(op)); + } + + INLINE int length() const { + return h_index>=l_index?h_index-l_index+1:l_index-h_index+1; + } + + INLINE int to_int() const { + ap_private<_AP_W,false> val=get(); + return val.to_int(); + } + + INLINE unsigned int to_uint() const { + ap_private<_AP_W,false> val=get(); + return val.to_uint(); + } + + INLINE long to_long() const { + ap_private<_AP_W,false> val=get(); + return val.to_long(); + } + + INLINE unsigned long to_ulong() const { + ap_private<_AP_W,false> val=get(); + return val.to_ulong(); + } + + INLINE ap_slong to_int64() const { + ap_private<_AP_W,false> val=get(); + return val.to_int64(); + } + + INLINE ap_ulong to_uint64() const { + ap_private<_AP_W,false> val=get(); + return val.to_uint64(); + } + + INLINE std::string to_string(uint8_t radix) const { + return get().to_string(radix); + } + +}; + +//----------------------------------------------------------------------------- +///ap_fixed_base: AutoPilot fixed point +//----------------------------------------------------------------------------- +template +struct ap_fixed_base { +#ifdef _MSC_VER + #pragma warning(disable: 4521 4522) +#endif /* #ifdef _MSC_VER */ +public: + template friend struct +ap_fixed_base; + template friend struct +af_bit_ref; + + INLINE void overflow_adjust(bool underflow, bool overflow, + bool lD, bool sign) { + if (!overflow && !underflow) return; + switch (_AP_O) { + case AP_WRAP: + if (_AP_N == 0) + return; + if (_AP_S) { + //signed SC_WRAP + //n_bits == 1; + if (_AP_N > 1) { + ap_private<_AP_W, _AP_S> mask(-1); + if (_AP_N >= _AP_W) mask = 0; + else mask.lshr(_AP_N); + if (sign) + V &= mask; + else + V |= ~mask; + } + sign ? V.set(_AP_W - 1) : V.clear(_AP_W - 1); + } else { + //unsigned SC_WRAP + ap_private<_AP_W, _AP_S> mask(-1); + if (_AP_N >= _AP_W) mask = 0; + else mask.lshr(_AP_N); + mask.flip(); + V |= mask; + } + break; + case AP_SAT_ZERO: + V.clear(); + break; + case AP_WRAP_SM: + { + bool Ro = ap_private_ops::get<_AP_W, _AP_S, _AP_W -1>(V); // V[_AP_W -1]; + if (_AP_N == 0) { + if (lD != Ro) { + V.flip(); + lD ? ap_private_ops::set<_AP_W, _AP_S, _AP_W - 1>(V) : + ap_private_ops::clear<_AP_W, _AP_S, _AP_W - 1>(V); + } + } else { + if (_AP_N == 1 && sign != Ro) { + V.flip(); + } else if (_AP_N > 1) { + bool lNo = ap_private_ops::get<_AP_W, _AP_S, _AP_W - _AP_N> (V); // V[_AP_W - _AP_N]; + if (lNo == sign) + V.flip(); + ap_private<_AP_W, false> mask(-1); + if (_AP_N >= _AP_W) mask = 0; + else mask.lshr(_AP_N); + if (sign) + V &= mask; + else + V |= mask.flip(); + sign ? ap_private_ops::set<_AP_W, _AP_S, _AP_W - 1>(V) : ap_private_ops::clear<_AP_W, _AP_S, _AP_W - 1>(V); + } + } + } + break; + default: + if (_AP_S) { + if (overflow) { + V.set(); ap_private_ops::clear<_AP_W, _AP_S, _AP_W-1>(V); + } else if (underflow) { + V.clear(); + ap_private_ops::set<_AP_W, _AP_S, _AP_W-1>(V); + if (_AP_O == AP_SAT_SYM) + ap_private_ops::set<_AP_W, _AP_S, 0>(V); + } + } else { + if (overflow) + V.set(); + else if (underflow) + V.clear(); + } + } + } + + INLINE bool quantization_adjust(bool qb, bool r, bool s) { + bool carry=ap_private_ops::get<_AP_W, _AP_S, _AP_W-1>(V); + switch (_AP_Q) { + case AP_TRN: + return false; + case AP_RND_ZERO: + qb &= s || r; + break; + case AP_RND_MIN_INF: + qb &= r; + break; + case AP_RND_INF: + qb &= !s || r; + break; + case AP_RND_CONV: + qb &= ap_private_ops::get<_AP_W, _AP_S, 0>(V) || r; + break; + case AP_TRN_ZERO: + qb = s && ( qb || r ); + break; + default:; + + } + if (qb) ++V; + //only when old V[_AP_W-1]==1 && new V[_AP_W-1]==0 + return carry && !(ap_private_ops::get<_AP_W, _AP_S, _AP_W-1>(V)); //(!V[_AP_W-1]); + } + + template + struct RType { + enum { + _AP_F=_AP_W-_AP_I, + F2=_AP_W2-_AP_I2, + mult_w = _AP_W+_AP_W2, + mult_i = _AP_I+_AP_I2, + mult_s = _AP_S||_AP_S2, + plus_w = AP_MAX(_AP_I+(_AP_S2&&!_AP_S),_AP_I2+(_AP_S&&!_AP_S2))+1+AP_MAX(_AP_F,F2), + plus_i = AP_MAX(_AP_I+(_AP_S2&&!_AP_S),_AP_I2+(_AP_S&&!_AP_S2))+1, + plus_s = _AP_S||_AP_S2, + minus_w = AP_MAX(_AP_I+(_AP_S2&&!_AP_S),_AP_I2+(_AP_S&&!_AP_S2))+1+AP_MAX(_AP_F,F2), + minus_i = AP_MAX(_AP_I+(_AP_S2&&!_AP_S),_AP_I2+(_AP_S&&!_AP_S2))+1, + minus_s = true, +#ifndef __SC_COMPATIBLE__ + div_w = _AP_W + AP_MAX(_AP_W2 - _AP_I2, 0) + _AP_S2, +#else + div_w = _AP_W + AP_MAX(_AP_W2 - _AP_I2, 0) + _AP_S2 + AP_MAX(_AP_I2, 0), +#endif /* #ifndef __SC_COMPATIBLE__ */ + div_i = _AP_I + (_AP_W2-_AP_I2) + _AP_S2, + div_s = _AP_S||_AP_S2, + logic_w = AP_MAX(_AP_I+(_AP_S2&&!_AP_S),_AP_I2+(_AP_S&&!_AP_S2))+AP_MAX(_AP_F,F2), + logic_i = AP_MAX(_AP_I+(_AP_S2&&!_AP_S),_AP_I2+(_AP_S&&!_AP_S2)), + logic_s = _AP_S||_AP_S2 + }; + + typedef ap_fixed_base mult; + typedef ap_fixed_base plus; + typedef ap_fixed_base minus; + typedef ap_fixed_base logic; + typedef ap_fixed_base div; + typedef ap_fixed_base<_AP_W, _AP_I, _AP_S> arg1; + }; + INLINE void report() { +#if 0 + if (_AP_W > 1024 && _AP_W <= 4096) { + fprintf(stderr, "[W] W=%d is out of bound (1<=W<=1024):" + " for synthesis, please define macro AP_INT_TYPE_EXT(N) to" + " extend the valid range.\n", _AP_W); + } else +#endif /* #if 0 */ + if (_AP_W > MAX_MODE(AP_INT_MAX_W) * 1024) { + fprintf(stderr, "[E] ap_%sfixed<%d, ...>: Bitwidth exceeds the " + "default max value %d. Please use macro " + "AP_INT_MAX_W to set a larger max value.\n", + _AP_S?"":"u", _AP_W, + MAX_MODE(AP_INT_MAX_W) * 1024); + exit(1); + } + } + + /// Constructors. + // ------------------------------------------------------------------------- +#if 0 + #ifdef __SC_COMPATIBLE__ + INLINE ap_fixed_base():V(uint32_t(_AP_W), uint64_t(0)) {} + #else + INLINE ap_fixed_base():V(uint32_t(_AP_W)) {} + #endif /* #ifdef __SC_COMPATIBLE__ */ +#else + INLINE ap_fixed_base():V(0) {} +#endif /* #if 0 */ + // INLINE ap_fixed_base():V() {} + // INLINE explicit ap_fixed_base(const ap_private<_AP_W+_AP_I, _AP_S>& _V):V(_V) {} + INLINE ap_fixed_base(const ap_fixed_base& op):V(op.V) {} + template + INLINE ap_fixed_base(const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op):V(0) { + enum {N2=_AP_W2,_AP_F=_AP_W-_AP_I,F2=_AP_W2-_AP_I2,QUAN_INC=F2>_AP_F && !(_AP_Q==AP_TRN || + (_AP_Q==AP_TRN_ZERO && !_AP_S2))}; + if (!op) return; + bool carry=false; + //handle quantization + enum { sh_amt =(F2>_AP_F)?F2-_AP_F:_AP_F-F2}; + const ap_private<_AP_W2, _AP_S2>& val = op.V; + bool neg_src=val.isNegative(); + if (F2==_AP_F) + V=val; + + else if (F2>_AP_F) { + if (sh_amt >= _AP_W2) + V = neg_src ? -1 : 0; + else + V = _AP_S2?val.ashr(sh_amt):val.lshr(sh_amt); + if (_AP_Q!=AP_TRN && !(_AP_Q==AP_TRN_ZERO && !_AP_S2)) { + bool qb = false; + if (F2-_AP_F>_AP_W2) + qb = neg_src; + else + qb = ap_private_ops::get<_AP_W2, _AP_S2, F2-_AP_F-1>(val); + + bool r=false; + enum { pos3 = F2-_AP_F-2}; + if (pos3>=_AP_W2-1) + r=val!=0; + else if (pos3>=0) + r = (val<<(_AP_W2-1-pos3))!=0; + carry = quantization_adjust(qb,r,neg_src); + } + } else { //no quantization + if (sh_amt < _AP_W) { + V=val; + V <<= sh_amt; + } + } + //hanle overflow/underflow + if ((_AP_O!=AP_WRAP || _AP_N != 0) && + ((!_AP_S && _AP_S2) || _AP_I-_AP_S < + _AP_I2 - _AP_S2 + (QUAN_INC|| (_AP_S2 && + _AP_O==AP_SAT_SYM)))) {//saturation + bool deleted_zeros = _AP_S2?true:!carry, + deleted_ones = true; + bool lD=(_AP_I2>_AP_I && _AP_W2-_AP_I2+_AP_I>=0) && + ap_private_ops::get<_AP_W2, _AP_S2, _AP_W2-_AP_I2+_AP_I>(val); + enum { pos1=F2-_AP_F+_AP_W, pos2=F2-_AP_F+_AP_W+1}; + if (pos1 < _AP_W2) { + bool Range1_all_ones= true; + bool Range1_all_zeros= true; + if (pos1 >= 0) { + enum { __W = (_AP_W2-pos1) > 0 ? (_AP_W2-pos1) : 1 }; + const ap_private<__W, _AP_S2> Range1=ap_private<__W, _AP_S2>(val.lshr(pos1)); + Range1_all_ones=Range1.isAllOnesValue(); + Range1_all_zeros=Range1.isMinValue(); + } else { + Range1_all_ones=false; + Range1_all_zeros=val.isMinValue(); + } + bool Range2_all_ones=true; + if (pos2<_AP_W2 && pos2>=0) { + enum { __W = (_AP_W2-pos2)>0 ? (_AP_W2-pos2) : 1}; + ap_private<__W, true> Range2=ap_private<__W, true>(val.lshr(pos2)); + Range2_all_ones=Range2.isAllOnesValue(); + } else if (pos2<0) + Range2_all_ones=false; + + deleted_zeros=deleted_zeros && (carry?Range1_all_ones:Range1_all_zeros); + deleted_ones=carry?Range2_all_ones&&(F2-_AP_F+_AP_W<0||!lD) + :Range1_all_ones; + neg_src= neg_src&&!(carry && Range1_all_ones); + } else + neg_src = neg_src && V[_AP_W-1]; + + bool neg_trg= V.isNegative(); + bool overflow=(neg_trg||!deleted_zeros) && !val.isNegative(); + bool underflow=(!neg_trg||!deleted_ones)&&neg_src; + //printf("neg_src = %d, neg_trg = %d, deleted_zeros = %d, + // deleted_ones = %d, overflow = %d, underflow = %d\n", + // neg_src, neg_trg, deleted_zeros, deleted_ones, + // overflow, underflow); + if (_AP_O==AP_SAT_SYM && _AP_S2 && _AP_S) + underflow |= neg_src && (_AP_W>1?V.isMinSignedValue():true); + overflow_adjust(underflow, overflow, lD, neg_src); + } + report(); + } + + template + INLINE ap_fixed_base(const volatile ap_fixed_base<_AP_W2,_AP_I2, + _AP_S2,_AP_Q2,_AP_O2, _AP_N2> &op) : V(op.V) { + *this = const_cast&>(op); + } + + template + INLINE ap_fixed_base(const ap_private<_AP_W2,_AP_S2>& op) { + ap_fixed_base<_AP_W2,_AP_W2,_AP_S2> f_op; + f_op.V=op; + *this = f_op; + } + + INLINE ap_fixed_base(bool b) { + *this=(ap_private<1,false>)b; + report(); + } + + INLINE ap_fixed_base(char b) { + *this=(ap_private<8,false>)b; + report(); + } + + INLINE ap_fixed_base(signed char b) { + *this=(ap_private<8,true>)b; + report(); + } + + INLINE ap_fixed_base(unsigned char b) { + *this=(ap_private<8,false>)b; + report(); + } + + INLINE ap_fixed_base(signed short b) { + *this=(ap_private<16,true>)b; + report(); + } + + INLINE ap_fixed_base(unsigned short b) { + *this=(ap_private<16,false>)b; + report(); + } + + INLINE ap_fixed_base(signed int b) { + *this=(ap_private<32,true>)b; + report(); + } + + INLINE ap_fixed_base(unsigned int b) { + *this=(ap_private<32,false>)b; + report(); + } +# if defined __x86_64__ + INLINE ap_fixed_base(signed long b) { + *this=(ap_private<64,true>)b; + report(); + } + + INLINE ap_fixed_base(unsigned long b) { + *this=(ap_private<64,false>)b; + report(); + } +# else + INLINE ap_fixed_base(signed long b) { + *this=(ap_private<32,true>)b; + report(); + } + + INLINE ap_fixed_base(unsigned long b) { + *this=(ap_private<32,false>)b; + report(); + } +# endif + + INLINE ap_fixed_base(ap_slong b) { + *this=(ap_private<64,true>)b; + report(); + } + + INLINE ap_fixed_base(ap_ulong b) { + *this=(ap_private<64,false>)b; + report(); + } + +#if 1 + INLINE ap_fixed_base(const char* val):V(0) { + ap_private<_AP_W, _AP_S> Tmp(val); + V = Tmp; + } + + INLINE ap_fixed_base(const char* val, signed char rd): V(0) { + ap_private<_AP_W, _AP_S> Tmp(val, rd); + V = Tmp; + } + +#endif + + INLINE ap_fixed_base(const std::string& val) { + ap_private<_AP_W, _AP_S> Tmp(val, 2); + V = Tmp; + report(); + } + + template + INLINE ap_fixed_base(const ap_bit_ref<_AP_W2, _AP_S2>& op) { + *this = ((bool)op); + report(); + } + + template + INLINE ap_fixed_base(const ap_range_ref<_AP_W2, _AP_S2>& op) { + *this = ap_private<_AP_W2, _AP_S2>(op); + report(); + } + + template + INLINE ap_fixed_base(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& op) { + *this = ((const ap_private<_AP_W2 + _AP_W3, false>&)(op)); + report(); + } + + template + INLINE ap_fixed_base(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) { + *this = (bool(op)); + report(); + } + + template + INLINE ap_fixed_base(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) { + *this = (ap_private<_AP_W2, false>(op)); + report(); + } + + //helper function + INLINE unsigned long long doubleToRawBits(double pf)const { + union { + unsigned long long __L; + double __D; + }LD; + LD.__D=pf; + return LD.__L; + } + + + INLINE double rawBitsToDouble(unsigned long long pi) const { + union { + unsigned long long __L; + double __D; + }LD; + LD.__L=pi; + return LD.__D; + } + + INLINE float rawBitsToFloat(uint32_t pi) const { + union { + uint32_t __L; + float __D; + }LD; + LD.__L = pi; + return LD.__D; + } + + INLINE ap_fixed_base(double d):V(0) { + if (!d) return; + const bool isneg=d<0; + + const uint64_t ireg=doubleToRawBits(isneg?-d:d); + if ((ireg&0x7fffffffffffffffULL)!=0) { + const int32_t exp=(((ireg)>>DOUBLE_MAN)&0x07ff)-DOUBLE_BIAS; + ap_private man = ireg & DOUBLE_MAN_MASK; + man.clear(DOUBLE_MAN+1); + man.set(DOUBLE_MAN); + if (isneg) { + man.flip(); + man++; + } + + enum {_AP_S2=true, _AP_W2=DOUBLE_MAN+2,_AP_F=_AP_W -_AP_I }; + const int _AP_I2=exp+2; + const int F2=_AP_W2-_AP_I2; + const bool QUAN_INC=F2>_AP_F && !(_AP_Q==AP_TRN || (_AP_Q==AP_TRN_ZERO && + !_AP_S2)); + bool carry=false; + //handle quantization + const unsigned sh_amt=abs(F2-_AP_F); // sh_amt = F2>_AP_F ? F2 -_AP_F : _AP_F-F2; + if (F2==_AP_F ) + V=man; + else if (F2>_AP_F) { + if (sh_amt >= DOUBLE_MAN+2) + V=isneg?-1:0; + else + V=(man>>sh_amt) | ((man & 1ULL<<(DOUBLE_MAN+1)) ? (DOUBLE_MAN_MASK>>(DOUBLE_MAN+2-sh_amt) <<(DOUBLE_MAN+2-sh_amt)):0); + + if (_AP_Q!=AP_TRN && !(_AP_Q==AP_TRN_ZERO && !_AP_S2)) { + const bool qb=((F2-_AP_F > DOUBLE_MAN+2) ? isneg : (man & (1ULL<<(F2-_AP_F-1))) != 0); + const int pos3=F2-_AP_F-2; + const bool r = (pos3>= 0) ? (man << AP_MAX(0, _AP_W2-pos3-1)& DOUBLE_MAN_MASK)!=0 : false; + carry = quantization_adjust(qb,r,isneg); + } + } + else { //no quantization + // V=man; + if (sh_amt < _AP_W) { + V = man; + V <<= sh_amt; + } + } + //handle overflow/underflow + if ((_AP_O != AP_WRAP || _AP_N != 0) && + ((!_AP_S && _AP_S2) || _AP_I-_AP_S < + _AP_I2-_AP_S2+(QUAN_INC|| (_AP_S2 && + _AP_O==AP_SAT_SYM)) )) {// saturation + bool deleted_zeros = _AP_S2?true:!carry, + deleted_ones = true; + bool neg_src; + const bool lD=(_AP_I2>_AP_I) && (_AP_W2-_AP_I2+_AP_I>=0) && (man & (1ULL <<(DOUBLE_MAN+2-_AP_I2+_AP_I))); + int pos1=F2+_AP_W-_AP_F; + if (pos1 < _AP_W2) { + int pos2=pos1+1; + bool Range1_all_ones=true; + bool Range1_all_zeros=true; + if (pos1>=0) { + ap_private<_AP_W,_AP_S> Range1= + ap_private<_AP_W,_AP_S>((man >> pos1) | ((1ULL<<(DOUBLE_MAN+1)&man) ? (DOUBLE_MAN_MASK >> (DOUBLE_MAN+2-pos1) <<(DOUBLE_MAN+2-pos1)):0)); + Range1_all_ones = Range1.isAllOnesValue(); // Range1.isAllOnesValue(); + Range1_all_zeros = Range1.isMinValue(); // Range1.isMinValue(); + } else { + Range1_all_ones=false; + Range1_all_zeros = man==0; // man.isMinValue(); + } + bool Range2_all_ones=true; + if (pos2<_AP_W2 && pos2>=0) { + ap_private<_AP_W, _AP_S> Range2= + ap_private<_AP_W, _AP_S>((man >> pos2) | ((1ULL<<(DOUBLE_MAN+1)&man) ? (DOUBLE_MAN_MASK >> (DOUBLE_MAN+2-pos2) <<(DOUBLE_MAN+2-pos2)):0)); + Range2_all_ones=Range2.isAllOnesValue(); // Range2.isAllOnesValue(); + } else if (pos2<0) + Range2_all_ones=false; + deleted_zeros=deleted_zeros && (carry?Range1_all_ones:Range1_all_zeros); + deleted_ones=carry?Range2_all_ones&&(F2-_AP_F+_AP_W<0||!lD) : Range1_all_ones; + neg_src=isneg&&!(carry&Range1_all_ones); + } else + neg_src = isneg && V[_AP_W -1]; + + const bool neg_trg=V.isNegative(); + const bool overflow=(neg_trg||!deleted_zeros) && !isneg; + bool underflow=(!neg_trg||!deleted_ones)&&neg_src; + //printf("neg_src = %d, neg_trg = %d, deleted_zeros = %d, + // deleted_ones = %d, overflow = %d, underflow = %d\n", + // neg_src, neg_trg, deleted_zeros, deleted_ones, + // overflow, underflow); + if (_AP_O==AP_SAT_SYM && _AP_S2 && _AP_S) + underflow |= neg_src && (_AP_W>1?V.isMinSignedValue():true); + overflow_adjust(underflow,overflow,lD, neg_src); + } + } + report(); + } + + + ///assign operators + //------------------------------------------------------------------------- + + INLINE volatile ap_fixed_base& operator=(const ap_fixed_base<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& op) volatile { + V = op.V; + return *this; + } + + INLINE ap_fixed_base& operator=(const ap_fixed_base<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& op) { + V = op.V; + return *this; + } + + INLINE volatile ap_fixed_base& operator=(const volatile ap_fixed_base<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& op) volatile { + V = op.V; + return *this; + } + + INLINE ap_fixed_base& operator=(const volatile ap_fixed_base<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& op) { + V = op.V; + return *this; + } + + // Set this ap_fixed_base with a bits string. That means the ssdm_int::V + // inside this ap_fixed_base is assigned by bv. + // Note the input parameter should be a fixed-point formatted bit string. + INLINE ap_fixed_base& setBits(unsigned long long bv) { + V=bv; + return *this; + } + + // Return a ap_fixed_base object whose ssdm_int::V is assigned by bv. + // Note the input parameter should be a fixed-point formatted bit string. + static INLINE ap_fixed_base bitsToFixed(unsigned long long bv) { + ap_fixed_base Tmp=bv; + return Tmp; + } + + // Explicit conversion functions to ap_private that captures + // all integer bits (bits are truncated) + INLINE ap_private + to_ap_private(bool Cnative = true) const { + ap_private ret = ap_private ((_AP_I >= 1) ? (_AP_S==true ? V.ashr(AP_MAX(0,_AP_W - _AP_I)) : V.lshr(AP_MAX(0,_AP_W - _AP_I))) : ap_private<_AP_W, _AP_S>(0)); + + if (Cnative) { + bool r = false; + if (_AP_I < _AP_W) { + if (_AP_I > 0) r = !(V.getLoBits(_AP_W - _AP_I).isMinValue()); + else r = !(V.isMinValue()); + } + if (r && V.isNegative()) { // if this is negative integer + ++ret;//ap_private(1,_AP_S); + } + } else { + //Follow OSCI library, conversion from sc_fixed to sc_int + } + return ret; + } + + template + INLINE operator ap_private<_AP_W2,_AP_S2> () const { + return (ap_private<_AP_W2,_AP_S2>)to_ap_private(); + } + + template + INLINE operator ap_private<_AP_W2,_AP_S2,_AP_N2> () const { + return (ap_private<_AP_W2,_AP_S2,_AP_N2>)to_ap_private(); + } + + //Explict conversion function to C built-in integral type + INLINE int to_int() const { + return to_ap_private().to_int(); + } + + INLINE int to_uint() const { + return to_ap_private().to_uint(); + } + + INLINE ap_slong to_int64() const { + return to_ap_private().to_int64(); + } + + INLINE ap_ulong to_uint64() const { + return to_ap_private().to_uint64(); + } + + INLINE double to_double() const { + if (!V) + return 0; + if (_AP_W>64 || (_AP_W - _AP_I) > 0) { + bool isneg = _AP_S && V[_AP_W-1]; + uint64_t res = isneg ? 0x8000000000000000ULL : 0; + ap_private<_AP_W, false> tmp = V; + if (isneg) tmp = -tmp; + int i = _AP_W -1 - tmp.countLeadingZeros(); + int exp = _AP_I-(_AP_W-i); + res|=((uint64_t)(exp+DOUBLE_BIAS))<DOUBLE_MAN)?tmp.lshr(i-DOUBLE_MAN):tmp).to_uint64() & DOUBLE_MAN_MASK; + res |= i 0) { + /* This specialization is disabled. It is giving wrong results in some cases. + bool isneg=V.isNegative(); + double dp = V.get(); + dp /= (1<< (_AP_W - _AP_I)); + return dp;*/ + } else + return double(to_int64()); + } + + INLINE float to_float() const { + uint32_t res=0; + if (V==0) + return 0; + bool isneg=V.isNegative(); + ap_private<_AP_W, _AP_S> tmp=V; + if (isneg) tmp = -tmp; + if (_AP_W-_AP_I>0||_AP_W>64) { + if (isneg) + res=0x80000000; + int i=_AP_W-1; + i-=tmp.countLeadingZeros(); + int exp=_AP_I-(_AP_W-i); + res|=(exp+FLOAT_BIAS)< man = 0; + if (i!=0) { + tmp.clear(i); + if (i>FLOAT_MAN) + man=tmp.lshr(i-FLOAT_MAN); + else + man=tmp; + res |= i < FLOAT_MAN?man.getZExtValue()<<(FLOAT_MAN-i):man.getZExtValue(); + } + } else { + return float(to_int64()); + } + float dp=rawBitsToFloat(res); + return dp; + } + + INLINE operator double () const { + return to_double(); + } +#ifndef __SC_COMPATIBLE__ + INLINE operator float () const { + return to_float(); + } + + INLINE operator char () const { + return (char) to_int(); + } + + INLINE operator unsigned char () const { + return (unsigned char) to_uint(); + } + + INLINE operator short () const { + return (short) to_int(); + } + + INLINE operator unsigned short () const { + return (unsigned short) to_uint(); + } + + INLINE operator int () const { + return to_int(); + } + + INLINE operator unsigned int () const { + return to_uint(); + } +#if 1 +#ifdef __x86_64__ + INLINE operator long () const { + return (long)to_int64(); + } + + INLINE operator unsigned long () const { + return (unsigned long) to_uint64(); + } +#else + INLINE operator long () const { + return to_int64(); + } + + INLINE operator unsigned long () const { + return to_uint64(); + } + +#endif +#endif + INLINE operator unsigned long long () const { + return to_uint64(); + } + + INLINE operator long long () const { + return to_int64(); + } +#endif + + INLINE std::string to_string(uint8_t radix=2, bool sign=false) const; + + INLINE ap_slong bits_to_int64() const { + ap_private res(V); + return (ap_slong) res; + } + + INLINE ap_ulong bits_to_uint64() const { + ap_private res(V); + return (ap_ulong) res; + } + + INLINE int length() const {return _AP_W;} + + // Count the number of zeros from the most significant bit + // to the first one bit. Note this is only for ap_fixed_base whose + // _AP_W <= 64, otherwise will incur assertion. + INLINE int countLeadingZeros() { + return V.countLeadingZeros(); + } + + ///Arithmetic:Binary + //------------------------------------------------------------------------- + template + INLINE typename RType<_AP_W2,_AP_I2,_AP_S2>::mult + operator * (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + typename RType<_AP_W2,_AP_I2,_AP_S2>::mult r; + r.V = V * op2.V; + return r; + } + + template + static INLINE ap_fixed_base multiply(const ap_fixed_base<_AP_W1,_AP_I1,_AP_S1>& op1, const + ap_fixed_base<_AP_W2,_AP_I2,_AP_S2>& op2) { + ap_private<_AP_W+_AP_W2, _AP_S> OP1=op1.V; + ap_private<_AP_W2,_AP_S2> OP2=op2.V; + return OP1*OP2; + } + + template + INLINE typename RType<_AP_W2,_AP_I2,_AP_S2>::div + operator / (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + enum {F2 = _AP_W2-_AP_I2, _W1=AP_MAX(_AP_W + AP_MAX(F2, 0), _AP_W2), + _W2=AP_MAX(_AP_W2,AP_MAX(_AP_W + AP_MAX(F2, 0), _AP_W2))}; + ap_private<_W1, _AP_S> dividend = (ap_private<_W1, _AP_S>(V)) << ((_W1>_AP_W)?F2:0); + ap_private<_W1, _AP_S2> divisior = ap_private<_W2, _AP_S2>(op2.V); + ap_private<_W1, _AP_S> ret = ap_private<_W1,_AP_S> ((_AP_S||_AP_S2) ? dividend.sdiv(divisior): dividend.udiv(divisior)); + typename RType<_AP_W2, _AP_I2, _AP_S2>::div r; + r.V = ret; + return r; + } +#define OP_BIN_AF(Sym, Rty, Width, Sign, Fun) \ + template \ + INLINE typename RType<_AP_W2,_AP_I2,_AP_S2>::Rty \ + operator Sym (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const \ + { \ + enum {_AP_F=_AP_W-_AP_I, F2=_AP_W2-_AP_I2}; \ + typename RType<_AP_W2,_AP_I2,_AP_S2>::Rty r, lhs(*this), rhs(op2); \ + r.V = lhs.V.Fun(rhs.V); \ + return r; \ + } \ + INLINE typename RType<_AP_W,_AP_I,_AP_S>::Rty \ + operator Sym (const ap_fixed_base& op2) const \ + { \ + typename RType<_AP_W,_AP_I,_AP_S>::Rty r; \ + r.V = V Sym op2.V; \ + return r; \ + } \ + + OP_BIN_AF(+, plus, plus_w, plus_s, Add) + OP_BIN_AF(-, minus, minus_w, minus_s, Sub) + +#define OP_LOGIC_BIN_AF(Sym, Rty, Width, Sign) \ + template \ + INLINE typename RType<_AP_W2,_AP_I2,_AP_S2>::Rty \ + operator Sym (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const \ + { \ + typename RType<_AP_W2,_AP_I2,_AP_S2>::Rty r, lhs(*this), rhs(op2); \ + r.V=lhs.V Sym rhs.V; \ + return r; \ + } \ + INLINE typename RType<_AP_W,_AP_I,_AP_S>::Rty \ + operator Sym (const ap_fixed_base& op2) const \ + { \ + typename RType<_AP_W,_AP_I,_AP_S>::Rty r; \ + r.V = V Sym op2.V; \ + return r; \ + } \ + INLINE typename RType<_AP_W,_AP_I,_AP_S>::Rty operator Sym(int op2) const \ + { \ + return V Sym (op2<<(_AP_W - _AP_I)); \ + } + OP_LOGIC_BIN_AF(&, logic, logic_w, logic_s) + OP_LOGIC_BIN_AF(|, logic, logic_w, logic_s) + OP_LOGIC_BIN_AF(^, logic, logic_w, logic_s) + + ///Arithmic : assign + //------------------------------------------------------------------------- +#define OP_ASSIGN_AF(Sym) \ + template \ + INLINE ap_fixed_base& operator Sym##= (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) \ + { \ + *this=operator Sym (op2) ; \ + return *this; \ + } + + OP_ASSIGN_AF(+) + OP_ASSIGN_AF(-) + OP_ASSIGN_AF(&) + OP_ASSIGN_AF(|) + OP_ASSIGN_AF(^) + OP_ASSIGN_AF(*) + OP_ASSIGN_AF(/) + + ///Prefix increment, decrement + //------------------------------------------------------------------------- + INLINE ap_fixed_base& operator ++() { + operator+=(ap_fixed_base<1,1,false>(1)); //SystemC's semantics + return *this; + } + + INLINE ap_fixed_base& operator --() { + operator-=(ap_fixed_base<1,1,false>(1)); //SystemC's semantics + return *this; + } + + //Postfix increment, decrement + //------------------------------------------------------------------------- + INLINE const ap_fixed_base operator ++(int) { + ap_fixed_base t(*this); + operator++(); + return t; + } + + INLINE const ap_fixed_base operator --(int) { + ap_fixed_base t = *this; + operator--(); + return t; + } + + ///Unary arithmetic + //------------------------------------------------------------------------- + INLINE ap_fixed_base operator +() {return *this;} + + INLINE ap_fixed_base<_AP_W + 1, _AP_I + 1, true> operator -() const { + ap_fixed_base<_AP_W + 1, _AP_I + 1, true> Tmp(*this); + Tmp.V = - Tmp.V; + return Tmp; + } + + INLINE ap_fixed_base<_AP_W,_AP_I,true,_AP_Q,_AP_O, _AP_N> getNeg() { + ap_fixed_base<_AP_W,_AP_I,true,_AP_Q,_AP_O, _AP_N> Tmp(*this); + Tmp.V=-Tmp.V; + return Tmp; + } + + ///Not (!) + //------------------------------------------------------------------------- + INLINE bool operator !() const { + return !V; + } + + ///Bitwise complement + //------------------------------------------------------------------------- + INLINE ap_fixed_base<_AP_W, _AP_I, _AP_S> + operator ~() const { + ap_fixed_base<_AP_W, _AP_I, _AP_S> res(*this); + res.V.flip(); + return res; + } + + ///Shift + ///template argument as shift value + template + INLINE ap_fixed_base<_AP_W, _AP_I + _AP_SHIFT, _AP_S> lshift () const { + ap_fixed_base<_AP_W, _AP_I + _AP_SHIFT, _AP_S> r; + r.V = V; + return r; + } + + template + INLINE ap_fixed_base<_AP_W, _AP_I - _AP_SHIFT, _AP_S> rshift () const { + ap_fixed_base<_AP_W, _AP_I - _AP_SHIFT, _AP_S> r; + r.V = V; + return r; + } + + //Because the return type is the type of the the first operand, shift assign + //operators do not carry out any quantization or overflow + //While systemc, shift assigns for sc_fixed/sc_ufixed will result in + //quantization or overflow (depending on the mode of the first operand) + //------------------------------------------------------------------------- + INLINE ap_fixed_base operator << (int sh) const { + ap_fixed_base r; + bool isNeg=(sh&0x80000000) != 0; + sh=isNeg?-sh:sh; + bool shiftoverflow = sh >= _AP_W; + bool NegSrc = V.isNegative(); + if (isNeg) { + if (shiftoverflow) + NegSrc?r.V.set():r.V.clear(); + else + r.V=_AP_S?V.ashr(sh):V.lshr(sh); + } else { + if (shiftoverflow) + r.V.clear(); + else + r.V=V< 1 && sh <= _AP_W) + rb = (V << (_AP_W - sh + 1 )) != 0; + else if (sh > _AP_W) + rb = V != 0; + r.quantization_adjust(qb, rb, NegSrc); + } else if (isNeg == false && _AP_O != AP_WRAP) { + bool allones, allzeros; + if (sh < _AP_W ) { + ap_private<_AP_W, _AP_S > range1 = V.lshr(_AP_W - sh - 1); + allones = range1.isAllOnesValue(); + allzeros = range1.isMinValue(); + } else { + allones = false; + allzeros = V.isMinValue(); + } + bool overflow = !allzeros && !NegSrc; + bool underflow = !allones && NegSrc; + if (_AP_O == AP_SAT_SYM && _AP_S) + underflow |= NegSrc && (_AP_W > 1 ? r.V.isMinSignedValue():true); + bool lD = false; + if ( sh < _AP_W ) lD = V[_AP_W - sh - 1]; + r.overflow_adjust(underflow, overflow, lD, NegSrc); + } +#endif + return r; + } + + template + INLINE ap_fixed_base operator<<(const ap_private<_AP_W2,true>& op2) const { + int sh = op2.to_int(); + return operator << (sh); + } + + INLINE ap_fixed_base operator << (unsigned int sh ) const { + ap_fixed_base r; + bool shiftoverflow = sh >= _AP_W; + r.V = shiftoverflow ? ap_private<_AP_W, _AP_S >(0) : V << sh; + if (sh == 0) return r; +#ifdef __SC_COMPATIBLE__ + bool NegSrc = V.isNegative(); + if (_AP_O != AP_WRAP) { + bool allones, allzeros; + if (sh < _AP_W ) { + ap_private<_AP_W, _AP_S > range1 = V.lshr(_AP_W - sh -1); + allones = range1.isAllOnesValue(); + allzeros = range1.isMinValue(); + } else { + allones = false; + allzeros = V.isMinValue(); + } + bool overflow = !allzeros && !NegSrc; + bool underflow = !allones && NegSrc; + if (_AP_O == AP_SAT_SYM && _AP_S) + underflow |= NegSrc && (_AP_W > 1 ? r.V.isMinSignedValue():true); + bool lD = false; + if ( sh < _AP_W ) lD = V[_AP_W - sh - 1]; + r.overflow_adjust(underflow, overflow, lD, NegSrc); + } +#endif + return r; + } + + template + INLINE ap_fixed_base operator << (const ap_private<_AP_W2,false>& op2) const { + unsigned int sh = op2.to_uint(); + return operator << (sh); + } + + INLINE ap_fixed_base operator >> (int sh) const { + ap_fixed_base r; + bool isNeg=(sh&0x80000000) != 0; + bool NegSrc = V.isNegative(); + sh=isNeg?-sh:sh; + bool shiftoverflow = sh >= _AP_W; + if (isNeg && !shiftoverflow) r.V=V< 1 && sh <= _AP_W) + rb = (V << (_AP_W - sh + 1 )) != 0; + else if (sh > _AP_W) + rb = V != 0; + r.quantization_adjust(qb, rb, NegSrc); + } else if (isNeg == true && _AP_O != AP_WRAP) { + bool allones, allzeros; + if (sh < _AP_W ) { + ap_private<_AP_W, _AP_S > range1 = V.lshr(_AP_W - sh - 1); + allones = range1.isAllOnesValue(); + allzeros = range1.isMinValue(); + } else { + allones = false; + allzeros = V.isMinValue(); + } + bool overflow = !allzeros && !NegSrc; + bool underflow = !allones && NegSrc; + if (_AP_O == AP_SAT_SYM && _AP_S) + underflow |= NegSrc && (_AP_W > 1 ? r.V.isMinSignedValue():true); + bool lD = false; + if ( sh < _AP_W ) lD = V[_AP_W - sh - 1]; + r.overflow_adjust(underflow, overflow, lD, NegSrc); + } +#endif + return r; + } + + template + INLINE ap_fixed_base operator >> (const ap_private<_AP_W2,true>& op2) const { + int sh = op2.to_int(); + return operator >> (sh); + } + + INLINE ap_fixed_base operator >> (unsigned int sh) const { + ap_fixed_base r; + bool NegSrc = V.isNegative(); + bool shiftoverflow = sh >= _AP_W; + if (shiftoverflow) + NegSrc?r.V.set():r.V.clear(); + else + r.V=_AP_S?V.ashr(sh):V.lshr(sh); +#ifdef __SC_COMPATIBLE__ + if (sh == 0) return r; + if (_AP_Q != AP_TRN) { + bool qb = false; + if (sh <= _AP_W) qb = V[sh - 1]; + bool rb = false; + if (sh > 1 && sh <= _AP_W) + rb = (V << (_AP_W - sh + 1 )) != 0; + else if (sh > _AP_W) + rb = V != 0; + r.quantization_adjust(qb, rb, NegSrc); + } +#endif + return r; + } + + template + INLINE ap_fixed_base operator >> (const ap_private<_AP_W2,false>& op2) const { + unsigned int sh = op2.to_uint(); + return operator >> (sh); + } + + ///shift assign + //------------------------------------------------------------------------- +#define OP_AP_SHIFT_AP_ASSIGN_AF(Sym) \ + template \ + INLINE ap_fixed_base& operator Sym##=(const ap_private<_AP_W2,_AP_S2>& op2) \ + { \ + *this=operator Sym (op2); \ + return *this; \ + } + + OP_AP_SHIFT_AP_ASSIGN_AF(<<) + OP_AP_SHIFT_AP_ASSIGN_AF(>>) + + ///Support shift(ap_fixed_base) +#define OP_AP_SHIFT_AF(Sym) \ + template \ + INLINE ap_fixed_base operator Sym (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const \ + { \ + return operator Sym (op2.to_ap_private()); \ + } \ + template \ + INLINE ap_fixed_base& operator Sym##= (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) \ + { \ + *this=operator Sym (op2); \ + return *this; \ + } + + OP_AP_SHIFT_AF(<<) + OP_AP_SHIFT_AF(>>) + + INLINE ap_fixed_base& operator >>= (unsigned int sh) { + *this = operator >> (sh); + return *this; + } + + INLINE ap_fixed_base& operator <<= (unsigned int sh) { + *this = operator << (sh); + return *this; + } + + INLINE ap_fixed_base& operator >>= (int sh) { + *this = operator >> (sh); + return *this; + } + + INLINE ap_fixed_base& operator <<= (int sh) { + *this = operator << (sh); + return *this; + } + + ///Comparisons + //------------------------------------------------------------------------- + template + INLINE bool operator == (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + enum {_AP_F=_AP_W-_AP_I,F2=_AP_W2-_AP_I2, shAmt1 = AP_MAX(F2-_AP_F, 0), shAmt2 = AP_MAX(_AP_F-F2,0), _AP_W3 = (_AP_F==F2) ? AP_MAX(_AP_W,_AP_W2) : AP_MAX(_AP_W+shAmt1, _AP_W2+shAmt2)}; + ap_private<_AP_W3, _AP_S > OP1= ap_private<_AP_W3, _AP_S >(V)< OP2=ap_private<_AP_W3,_AP_S2 >(op2.V)< + INLINE bool operator != (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + return !(*this==op2); + } + + template + INLINE bool operator > (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + enum {_AP_F=_AP_W-_AP_I,F2=_AP_W2-_AP_I2, shAmt1 = AP_MAX(F2-_AP_F, 0), shAmt2 = AP_MAX(_AP_F-F2,0), _AP_W3 = (_AP_F==F2) ? AP_MAX(_AP_W,_AP_W2) : AP_MAX(_AP_W+shAmt1, _AP_W2+shAmt2)}; + ap_private<_AP_W3, _AP_S > OP1= ap_private<_AP_W3, _AP_S >(V)< OP2=ap_private<_AP_W3,_AP_S2 >(op2.V)< + INLINE bool operator <= (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + return !(*this>op2); + } + + template + INLINE bool operator < (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + enum {_AP_F=_AP_W-_AP_I,F2=_AP_W2-_AP_I2, shAmt1 = AP_MAX(F2-_AP_F, 0), shAmt2 = AP_MAX(_AP_F-F2,0), _AP_W3 = (_AP_F==F2) ? AP_MAX(_AP_W,_AP_W2) : AP_MAX(_AP_W+shAmt1, _AP_W2+shAmt2)}; + ap_private<_AP_W3, _AP_S > OP1= ap_private<_AP_W3, _AP_S >(V)< OP2=ap_private<_AP_W3,_AP_S2 >(op2.V)< + INLINE bool operator >= (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + return !(*this) + DOUBLE_CMP_AF(>=) + DOUBLE_CMP_AF(<) + DOUBLE_CMP_AF(<=) + + // Bit and Slice Select + INLINE af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N> operator [] (unsigned int index) { + assert(index<_AP_W&&"Attemping to read bit beyond MSB"); + return af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>(this, index); + } + + INLINE af_bit_ref<_AP_W, _AP_I,_AP_S,_AP_Q,_AP_O, _AP_N> bit(unsigned int index) { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>(this, index); + } + + template + INLINE af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N> bit (const ap_private<_AP_W2,_AP_S2>& index) { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>(this, index.to_int()); + } + + INLINE bool bit (unsigned int index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return V[index]; + } + + INLINE bool operator [] (unsigned int index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return V[index]; + } + + template + INLINE bool bit (const ap_private<_AP_W2, _AP_S2>& index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return V[index.to_uint()]; + } + + template + INLINE bool operator [] (const ap_private<_AP_W2, _AP_S2>& index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return V[index.to_uint()]; + } + + INLINE af_bit_ref<_AP_W, _AP_I,_AP_S,_AP_Q,_AP_O, _AP_N> get_bit(int index) { + assert(index < _AP_I && "Attempting to read bit beyond MSB"); + assert(index >= _AP_I - _AP_W&& "Attempting to read bit beyond MSB"); + return af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>(this, index + _AP_W - _AP_I); + } + + template + INLINE af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N> get_bit (const ap_private<_AP_W2, true>& index) { + assert(index >= _AP_I - _AP_W && "Attempting to read bit with negative index"); + assert(index < _AP_I && "Attempting to read bit beyond MSB"); + return af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>(this, index.to_int() + _AP_W - _AP_I); + } + + INLINE bool get_bit (int index) const { + assert(index >= _AP_I - _AP_W && "Attempting to read bit with negative index"); + assert(index < _AP_I && "Attempting to read bit beyond MSB"); + return V[index + _AP_W - _AP_I]; + } + + template + INLINE bool get_bit (const ap_private<_AP_W2, true>& index) const { + assert(index >= _AP_I - _AP_W && "Attempting to read bit with negative index"); + assert(index < _AP_I && "Attempting to read bit beyond MSB"); + return V[index.to_int() + _AP_W - _AP_I]; + } + + INLINE af_range_ref<_AP_W,_AP_I,_AP_S, _AP_Q, _AP_O, _AP_N> + range(int Hi, int Lo) { + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>(this, Hi, Lo); + } + + INLINE af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> + operator () (int Hi, int Lo) { + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>(this, Hi, Lo); + } + + INLINE af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> + range(int Hi, int Lo) const { + assert((Hi < _AP_W) && (Lo < _AP_W) &&"Out of bounds in range()"); + return af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>(const_cast(this), Hi, Lo); + } + + INLINE af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> + operator () (int Hi, int Lo) const { + return this->range(Hi, Lo); + } + + template + INLINE af_range_ref<_AP_W,_AP_I,_AP_S, _AP_Q, _AP_O, _AP_N> + range(const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>(this, Hi, Lo); + } + + template + INLINE af_range_ref<_AP_W,_AP_I,_AP_S, _AP_Q, _AP_O, _AP_N> + operator () (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>(this, Hi, Lo); + } + + template + INLINE af_range_ref<_AP_W,_AP_I,_AP_S, _AP_Q, _AP_O, _AP_N> + range(const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) const { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>(const_cast< + ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>*>(this), + Hi, Lo); + } + + template + INLINE af_range_ref<_AP_W,_AP_I,_AP_S, _AP_Q, _AP_O, _AP_N> + operator () (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) const { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + return this->range(Hi, Lo); + } + + INLINE af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> + range() { + return this->range(_AP_W - 1, 0); + } + + INLINE af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> + range() const { + return this->range(_AP_W - 1, 0); + } + + INLINE bool is_zero () const { + return V.isMinValue(); + } + + INLINE bool is_neg () const { + if (V.isNegative()) + return true; + return false; + } + + INLINE int wl () const { + return _AP_W; + } + + INLINE int iwl () const { + return _AP_I; + } + + INLINE ap_q_mode q_mode () const { + return _AP_Q; + } + + INLINE ap_o_mode o_mode () const { + return _AP_O; + } + + INLINE int n_bits () const { + return 0; + } + + //private: +public: + ap_private<_AP_W, _AP_S> V; +}; + +template +std::string ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>::to_string( + uint8_t radix, bool sign) const { + std::string str; + str.clear(); + char step; + std::string prefix; + switch (radix) { + case 2 : prefix = "0b"; step = 1; break; + case 8 : prefix = "0o"; step = 3; break; + case 16 : prefix = "0x"; step = 4; break; + default : break; + } + if (_AP_W <= _AP_I) + str = this->to_ap_private().to_string(radix, + radix == 10 ? _AP_S : sign); + else { + if (radix == 10) { + bool isNeg = _AP_S && V.isNegative(); + if (_AP_I > 0) { + ap_private int_part(0); + int_part = this->to_ap_private(); + str += int_part.to_string(radix, false); + } else { + if (isNeg) str += '-'; + } + ap_fixed_base<_AP_W, _AP_I, _AP_S> tmp(*this); + if (isNeg && _AP_I <= 0) tmp = -tmp; + ap_fixed_base<_AP_W - AP_MIN(_AP_I, 0), 0, false> frac_part = tmp; + if (frac_part == 0) return str; + str += "."; + while (frac_part != 0) { + char digit = (frac_part * radix).to_ap_private(); + str += static_cast(digit + '0'); + frac_part *= radix; + } + } else { + if (_AP_I > 0) { + for (signed i = _AP_W - _AP_I; i < _AP_W; i += step) { + + char digit = (char)(this->range(AP_MIN(i + step - 1, _AP_W - 1), i)); + str = (digit < 10 ? static_cast(digit + '0') : + static_cast(digit - 10 + 'a')) + str; + } + } + str += '.'; + ap_fixed_base tmp(*this); + for (signed i = _AP_W - _AP_I - 1; i >= 0; i -= step) { + char digit = (char)(tmp.range(i, AP_MAX(0, i - step + 1))); + str += digit < 10 ? static_cast(digit + '0') : + static_cast(digit - 10 + 'a'); + } + } + } + str = prefix + str; + return str; +} + +template +INLINE void b_not(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op) { + ret.V = op.V; + ret.V.flip(); +} + +template +INLINE void b_and(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op1, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op2) { + ret.V = op1.V & op2.V; +} + +template +INLINE void b_or(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op1, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op2) { + ret.V = op1.V | op2.V; +} + +template +INLINE void b_xor(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op1, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op2) { + ret.V = op1.V ^ op2.V; +} + +template +INLINE void neg(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) { + ap_fixed_base<_AP_W2+!_AP_S2, _AP_I2+!_AP_S2, true, _AP_Q2, _AP_O2, _AP_N2> Tmp; + Tmp.V = - op.V; + ret = Tmp; +} + +template +INLINE void neg(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op) { + ret.V = -op.V; +} + +template +INLINE void lshift(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op, + int i) { + ap_fixed_base<_AP_W2 - _AP_I2 + AP_MAX(_AP_I, _AP_I2), AP_MAX(_AP_I, _AP_I2), _AP_S2, _AP_Q2, _AP_O2, _AP_N2> Tmp; + Tmp = op; + Tmp.V <<= i; + ret = Tmp; +} + +template +INLINE void lshift(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op, + int i) { + ret.V = op.V << i; +} + +template +INLINE void rshift(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op, + int i) { + ap_fixed_base<_AP_I2 + AP_MAX(_AP_W - _AP_I, _AP_W2 - _AP_I2), _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> Tmp; + Tmp = op; + Tmp.V = _AP_S2 ? Tmp.V.ashr(i): Tmp.V.lshr(i); + ret = Tmp; +} + +template +INLINE void rshift(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op, + int i) { + ret.V = _AP_S ? op.V.ashr(i): op.V.lshr(i); +} + +#define AF_CTOR_SPEC_BASE(_AP_W,_AP_S,C_TYPE) \ + template<> INLINE ap_fixed_base<_AP_W,_AP_W,_AP_S,AP_TRN,AP_WRAP>::ap_fixed_base(C_TYPE i_op):V(i_op) \ + { \ + } + +#define AF_CTOR_SPEC(__W,C_TYPE) \ + AF_CTOR_SPEC_BASE(__W,true,C_TYPE) \ + AF_CTOR_SPEC_BASE(__W,false,C_TYPE) + +AF_CTOR_SPEC(1,bool) +AF_CTOR_SPEC(8, signed char) +AF_CTOR_SPEC(8, unsigned char) +AF_CTOR_SPEC(16, signed short) +AF_CTOR_SPEC(16, unsigned short) +AF_CTOR_SPEC(32, signed int) +AF_CTOR_SPEC(32, unsigned int) +AF_CTOR_SPEC(64, ap_slong) +AF_CTOR_SPEC(64, ap_ulong) + +///Output streaming +//----------------------------------------------------------------------------- +template +INLINE std::ostream& +operator <<(std::ostream& os, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& x) { + os << x.to_double(); + return os; +} + +///Input streaming +//----------------------------------------------------------------------------- +template +INLINE std::istream& +operator >> (std::istream& os, ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& x) { + double d; + os >> d; + x = ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>(x); + return os; +} + +template +INLINE void print(const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& x) { + ap_private<_AP_W,_AP_S> data=x.V; + if (_AP_I>0) { + const ap_private<_AP_I,_AP_S> p1=data>>(_AP_W-_AP_I); + print(p1); + + } else + printf("0"); + printf("."); + if (_AP_I<_AP_W) { + const ap_private<_AP_W-_AP_I,false> p2=data; + print(p2,false); + } +} + +///Operators mixing Integers with ap_fixed_base +//----------------------------------------------------------------------------- +#if 1 +#define AF_BIN_OP_WITH_INT_SF(BIN_OP,C_TYPE,_AP_W2,_AP_S2,RTYPE) \ + template \ + INLINE typename ap_fixed_base<_AP_W,_AP_I,_AP_S>::template RType<_AP_W2,_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP (const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) \ + { \ + return op.operator BIN_OP(ap_private<_AP_W2,_AP_S2>(i_op)); \ + } +#define AF_BIN_OP_WITH_INT(BIN_OP, C_TYPE, _AP_W2,_AP_S2,RTYPE) \ + template \ + INLINE typename ap_fixed_base<_AP_W,_AP_I,_AP_S>::template RType<_AP_W2,_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP (const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) \ + { \ + return op.operator BIN_OP (ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op)); \ + } \ + \ + template \ + INLINE typename ap_fixed_base<_AP_W,_AP_I,_AP_S>::template RType<_AP_W2,_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP (C_TYPE i_op, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op) \ + { \ + return ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op).operator BIN_OP (op); \ + } + +#else +#define AF_BIN_OP_WITH_INT_SF(BIN_OP,C_TYPE,_AP_W2,_AP_S2,RTYPE) \ + template \ + INLINE typename ap_fixed_base<_AP_W,_AP_I,_AP_S>::template RType<_AP_W2,_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP (const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) \ + { \ + return op BIN_OP (i_op); \ + } +#define AF_BIN_OP_WITH_INT(BIN_OP, C_TYPE, _AP_W2,_AP_S2,RTYPE) \ + template \ + INLINE typename ap_fixed_base<_AP_W,_AP_I,_AP_S>::template RType<_AP_W2,_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP (const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) \ + { \ + return op.V BIN_OP (i_op<<(_AP_W-_AP_I)); \ + } \ + \ + \ + template \ + INLINE typename ap_fixed_base<_AP_W,_AP_I,_AP_S>::template RType<_AP_W2,_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP (C_TYPE i_op, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op) \ + { \ + return ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op).operator BIN_OP (op); \ + } + +#endif +#if 1 +#define AF_REL_OP_WITH_INT(REL_OP, C_TYPE, _AP_W2,_AP_S2) \ + template \ + INLINE bool operator REL_OP (const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) \ + { \ + return op.operator REL_OP (ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op)); \ + } \ + \ + \ + template \ + INLINE bool operator REL_OP (C_TYPE i_op, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op) \ + { \ + return ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op).operator REL_OP (op); \ + } +#else +#define AF_REL_OP_WITH_INT(REL_OP, C_TYPE, _AP_W2,_AP_S2) \ + template \ + INLINE bool operator REL_OP (const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) \ + { \ + return op.V.operator REL_OP (i_op<<(_AP_W-_AP_I)); \ + } \ + \ + \ + template \ + INLINE bool operator REL_OP (C_TYPE i_op, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op) \ + { \ + return (i_op<<(_AP_W-_AP_I)) REL_OP (op.V.VAL); \ + } +#endif +#if 1 +#define AF_ASSIGN_OP_WITH_INT(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& operator ASSIGN_OP ( ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) { \ + return op.operator ASSIGN_OP (ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op)); \ + } +#define AF_ASSIGN_OP_WITH_INT_SF(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& operator ASSIGN_OP ( ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) { \ + return op.operator ASSIGN_OP (ap_private<_AP_W2,_AP_S2>(i_op)); \ + } +#else +#define AF_ASSIGN_OP_WITH_INT(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& operator ASSIGN_OP ( ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) { \ + return op.V.operator ASSIGN_OP (i_op); \ + } +#define AF_ASSIGN_OP_WITH_INT_SF(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& operator ASSIGN_OP ( ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) { \ + return op.V.operator ASSIGN_OP (i_op); \ + } +#endif + +#define AF_OPS_WITH_INT(C_TYPE, WI, SI) \ + AF_BIN_OP_WITH_INT(+, C_TYPE, WI, SI, plus) \ + AF_BIN_OP_WITH_INT(-, C_TYPE, WI, SI, minus) \ + AF_BIN_OP_WITH_INT(*, C_TYPE, WI, SI, mult) \ + AF_BIN_OP_WITH_INT(/, C_TYPE, WI, SI, div) \ + AF_BIN_OP_WITH_INT_SF(>>, C_TYPE, WI, SI, arg1) \ + AF_BIN_OP_WITH_INT_SF(<<, C_TYPE, WI, SI, arg1) \ + AF_BIN_OP_WITH_INT(&, C_TYPE, WI, SI, logic) \ + AF_BIN_OP_WITH_INT(|, C_TYPE, WI, SI, logic) \ + AF_BIN_OP_WITH_INT(^, C_TYPE, WI, SI, logic) \ + \ + AF_REL_OP_WITH_INT(==, C_TYPE, WI, SI) \ + AF_REL_OP_WITH_INT(!=, C_TYPE, WI, SI) \ + AF_REL_OP_WITH_INT(>, C_TYPE, WI, SI) \ + AF_REL_OP_WITH_INT(>=, C_TYPE, WI, SI) \ + AF_REL_OP_WITH_INT(<, C_TYPE, WI, SI) \ + AF_REL_OP_WITH_INT(<=, C_TYPE, WI, SI) \ + \ + AF_ASSIGN_OP_WITH_INT(+=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT(-=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT(*=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT(/=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT_SF(>>=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT_SF(<<=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT(&=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT(|=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT(^=, C_TYPE, WI, SI) + +AF_OPS_WITH_INT(bool, 1, false) +AF_OPS_WITH_INT(char, 8, true) +AF_OPS_WITH_INT(signed char, 8, true) +AF_OPS_WITH_INT(unsigned char, 8, false) +AF_OPS_WITH_INT(short, 16, true) +AF_OPS_WITH_INT(unsigned short, 16, false) +AF_OPS_WITH_INT(int, 32, true) +AF_OPS_WITH_INT(unsigned int, 32, false) +# if defined __x86_64__ +AF_OPS_WITH_INT(long, 64, true) +AF_OPS_WITH_INT(unsigned long, 64, false) +# else +AF_OPS_WITH_INT(long, 32, true) +AF_OPS_WITH_INT(unsigned long, 32, false) +# endif +AF_OPS_WITH_INT(ap_slong, 64, true) +AF_OPS_WITH_INT(ap_ulong, 64, false) + +#define AF_BIN_OP_WITH_AP_INT(BIN_OP, RTYPE) \ + template \ + INLINE typename ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>::template RType<_AP_W,_AP_I,_AP_S>::RTYPE \ + operator BIN_OP ( const ap_private<_AP_W2,_AP_S2>& i_op, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op) { \ + return ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op).operator BIN_OP (op); \ + } \ + template \ + INLINE typename ap_fixed_base<_AP_W,_AP_I,_AP_S>::template RType<_AP_W2,_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP ( const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, const ap_private<_AP_W2,_AP_S2>& i_op) { \ + return op.operator BIN_OP (ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op)); \ + } + +#define AF_REL_OP_WITH_AP_INT(REL_OP) \ + template \ + INLINE bool operator REL_OP ( const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, const ap_private<_AP_W2,_AP_S2>& i_op) { \ + return op.operator REL_OP ( ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op)); \ + } \ + template \ + INLINE bool operator REL_OP ( const ap_private<_AP_W2,_AP_S2>& i_op, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op) { \ + return ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op).operator REL_OP (op); \ + } + +#define AF_ASSIGN_OP_WITH_AP_INT(ASSIGN_OP) \ + template \ + INLINE ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& operator ASSIGN_OP ( ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, const ap_private<_AP_W2,_AP_S2>& i_op) { \ + return op.operator ASSIGN_OP (ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op)); \ + } \ + template \ + INLINE ap_private<_AP_W2,_AP_S2>& operator ASSIGN_OP ( ap_private<_AP_W2,_AP_S2>& i_op, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op) { \ + return i_op.operator ASSIGN_OP (op.to_ap_private()); \ + } + +AF_BIN_OP_WITH_AP_INT(+, plus) +AF_BIN_OP_WITH_AP_INT(-, minus) +AF_BIN_OP_WITH_AP_INT(*, mult) +AF_BIN_OP_WITH_AP_INT(/, div) +AF_BIN_OP_WITH_AP_INT(&, logic) +AF_BIN_OP_WITH_AP_INT(|, logic) +AF_BIN_OP_WITH_AP_INT(^, logic) + +AF_REL_OP_WITH_AP_INT(==) +AF_REL_OP_WITH_AP_INT(!=) +AF_REL_OP_WITH_AP_INT(>) +AF_REL_OP_WITH_AP_INT(>=) +AF_REL_OP_WITH_AP_INT(<) +AF_REL_OP_WITH_AP_INT(<=) + +AF_ASSIGN_OP_WITH_AP_INT(+=) +AF_ASSIGN_OP_WITH_AP_INT(-=) +AF_ASSIGN_OP_WITH_AP_INT(*=) +AF_ASSIGN_OP_WITH_AP_INT(/=) +AF_ASSIGN_OP_WITH_AP_INT(&=) +AF_ASSIGN_OP_WITH_AP_INT(|=) +AF_ASSIGN_OP_WITH_AP_INT(^=) + +#define AF_REF_REL_OP_MIX_INT(REL_OP, C_TYPE, _AP_W2, _AP_S2) \ +template \ + INLINE bool operator REL_OP ( const af_range_ref<_AP_W,_AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op, C_TYPE op2) { \ + return (ap_private<_AP_W, false>(op)).operator REL_OP (ap_private<_AP_W2,_AP_S2>(op2)); \ + } \ +template \ + INLINE bool operator REL_OP ( C_TYPE op2, const af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op) { \ + return ap_private<_AP_W2,_AP_S2>(op2).operator REL_OP (ap_private<_AP_W, false>(op)); \ + } \ +template \ + INLINE bool operator REL_OP ( const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op, C_TYPE op2) { \ + return (bool(op)) REL_OP op2; \ + } \ +template \ + INLINE bool operator REL_OP ( C_TYPE op2, const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op) { \ + return op2 REL_OP (bool(op)); \ + } + +#define AF_REF_REL_MIX_INT(C_TYPE, _AP_WI, _AP_SI) \ +AF_REF_REL_OP_MIX_INT(>, C_TYPE, _AP_WI, _AP_SI) \ +AF_REF_REL_OP_MIX_INT(<, C_TYPE, _AP_WI, _AP_SI) \ +AF_REF_REL_OP_MIX_INT(>=, C_TYPE, _AP_WI, _AP_SI) \ +AF_REF_REL_OP_MIX_INT(<=, C_TYPE, _AP_WI, _AP_SI) \ +AF_REF_REL_OP_MIX_INT(==, C_TYPE, _AP_WI, _AP_SI) \ +AF_REF_REL_OP_MIX_INT(!=, C_TYPE, _AP_WI, _AP_SI) + +AF_REF_REL_MIX_INT(bool, 1, false) +AF_REF_REL_MIX_INT(char, 8, true) +AF_REF_REL_MIX_INT(signed char, 8, true) +AF_REF_REL_MIX_INT(unsigned char, 8, false) +AF_REF_REL_MIX_INT(short, 16, true) +AF_REF_REL_MIX_INT(unsigned short, 16, false) +AF_REF_REL_MIX_INT(int, 32, true) +AF_REF_REL_MIX_INT(unsigned int, 32, false) +# if defined __x86_64__ +AF_REF_REL_MIX_INT(long, 64, true) +AF_REF_REL_MIX_INT(unsigned long, 64, false) +# else +AF_REF_REL_MIX_INT(long, 32, true) +AF_REF_REL_MIX_INT(unsigned long, 32, false) +# endif +AF_REF_REL_MIX_INT(ap_slong, 64, true) +AF_REF_REL_MIX_INT(ap_ulong, 64, false) + +#define AF_REF_REL_OP_AP_INT(REL_OP) \ +template \ + INLINE bool operator REL_OP ( const af_range_ref<_AP_W,_AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op, const ap_private<_AP_W2, _AP_S> &op2) { \ + return (ap_private<_AP_W, false>(op)).operator REL_OP (op2); \ + } \ +template \ + INLINE bool operator REL_OP (const ap_private<_AP_W2, _AP_S2> &op2, const af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op) { \ + return op2.operator REL_OP (ap_private<_AP_W, false>(op)); \ + } \ +template \ + INLINE bool operator REL_OP ( const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op, const ap_private<_AP_W2, _AP_S2> &op2) { \ + return (ap_private<1, false>(op)).operator REL_OP (op2); \ + } \ +template \ + INLINE bool operator REL_OP ( const ap_private<_AP_W2, _AP_S2> &op2, const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op) { \ + return op2.operator REL_OP (ap_private<1,false>(op)); \ + } + +AF_REF_REL_OP_AP_INT(>) +AF_REF_REL_OP_AP_INT(<) +AF_REF_REL_OP_AP_INT(>=) +AF_REF_REL_OP_AP_INT(<=) +AF_REF_REL_OP_AP_INT(==) +AF_REF_REL_OP_AP_INT(!=) + +// Relational Operators with double +template +INLINE bool operator == ( double op1, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op2) { + return op2.operator == (op1); +} + +template +INLINE bool operator != ( double op1, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op2) { + return op2.operator != (op1); +} + +template +INLINE bool operator > ( double op1, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op2) { + return op2.operator < (op1); +} + +template +INLINE bool operator >= ( double op1, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op2) { + return op2.operator <= (op1); +} + +template +INLINE bool operator < ( double op1, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op2) { + return op2.operator > (op1); +} + +template +INLINE bool operator <= ( double op1, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op2) { + return op2.operator >= (op1); +} + +#endif /* #ifndef __AESL_GCC_AP_FIXED_H__ */ \ No newline at end of file diff --git a/hls_2018/router_01/etc/ap_int_sim.h b/hls_2018/router_01/etc/ap_int_sim.h new file mode 100755 index 0000000..887ccd8 --- /dev/null +++ b/hls_2018/router_01/etc/ap_int_sim.h @@ -0,0 +1,1629 @@ +/* + * Copyright 2012 Xilinx, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __AESL_GCC_AP_INT_H__ +#define __AESL_GCC_AP_INT_H__ + +#ifndef __cplusplus +#error C++ is required to include this header file +#endif /* #ifndef __cplusplus */ + +#undef _AP_DEBUG_ +#include +#include + +// for safety +#if (defined(_AP_N)|| defined(_AP_C)) +#error One or more of the following is defined: _AP_N, _AP_C. Definition conflicts with their usage as template parameters. +#endif /* #if (defined(_AP_N)|| defined(_AP_C)) */ + +// for safety +#if (defined(_AP_W) || defined(_AP_I) || defined(_AP_S) || defined(_AP_Q) || defined(_AP_O) || defined(_AP_W2) || defined(_AP_I2) || defined(_AP_S2) || defined(_AP_Q2) || defined(_AP_O2)) +#error One or more of the following is defined: _AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2. Definition conflicts with their usage as template parameters. +#endif /* #if (defined(_AP_W) || defined(_AP_I) || defined(_AP_S) || defined(_AP_Q) || defined(_AP_O) || defined(_AP_W2) || defined(_AP_I2) || defined(_AP_S2) || defined(_AP_Q2) || defined(_AP_O2)) */ + +//for safety +#if (defined(_AP_W3) || defined(_AP_S3) || defined(_AP_W4) || defined(_AP_S4)) +#error One or more of the following is defined: _AP_W3, _AP_S3, _AP_W4,_AP_S4. Definition conflicts with their usage as template parameters. +#endif /* #if (defined(_AP_W3) || defined(_AP_S3) || defined(_AP_W4) || defined(_AP_S4)) */ + +//for safety +#if (defined(_AP_W1) || defined(_AP_S1) || defined(_AP_I1) || defined(_AP_T) || defined(_AP_T1) || defined(_AP_T2) || defined(_AP_T3) || defined(_AP_T4)) +#error One or more of the following is defined: _AP_W1, _AP_S1, _AP_I1, _AP_T, _AP_T1, _AP_T2, _AP_T3, _AP_T4. Definition conflicts with their usage as template parameters. +#endif /* #if (defined(_AP_W1) || defined(_AP_S1) || defined(_AP_I1) || defined(_AP_T) || defined(_AP_T1) || defined(_AP_T2) || defined(_AP_T3) || defined(_AP_T4)) */ + +#define __AESL_APDT_IN_SCFLOW__ +#ifndef __AESL_APDT_IN_SCFLOW__ + #include "etc/ap_private.h" +#else + #include "../etc/ap_private.h" +#endif /* #ifndef __AESL_APDT_IN_SCFLOW__ */ + +#ifdef _AP_DEBUG_ + #define AP_DEBUG(s) s +#else + #define AP_DEBUG(s) +#endif /* #ifdef _AP_DEBUG_ */ + +#ifndef __SIMULATION__ + #define __SIMULATION__ +#endif /* #ifndef __SIMULATION__ */ + +#if !(defined SYSTEMC_H) && !(defined SYSTEMC_INCLUDED) + #ifndef SC_TRN + #define SC_TRN AP_TRN + #endif /* #ifndef SC_TRN */ + #ifndef SC_RND + #define SC_RND AP_RND + #endif /* #ifndef SC_RND */ + #ifndef SC_TRN_ZERO + #define SC_TRN_ZERO AP_TRN_ZERO + #endif /* #ifndef SC_TRN_ZERO */ + #ifndef SC_RND_ZERO + #define SC_RND_ZERO AP_RND_ZERO + #endif /* #ifndef SC_RND_ZERO */ + #ifndef SC_RND_INF + #define SC_RND_INF AP_RND_INF + #endif /* #ifndef SC_RND_INF */ + #ifndef SC_RND_MIN_INF + #define SC_RND_MIN_INF AP_RND_MIN_INF + #endif /* #ifndef SC_RND_MIN_INF */ + #ifndef SC_RND_CONV + #define SC_RND_CONV AP_RND_CONV + #endif /* #ifndef SC_RND_CONV */ + #ifndef SC_WRAP + #define SC_WRAP AP_WRAP + #endif /* #ifndef SC_WRAP */ + #ifndef SC_SAT + #define SC_SAT AP_SAT + #endif /* #ifndef SC_SAT */ + #ifndef SC_SAT_ZERO + #define SC_SAT_ZERO AP_SAT_ZERO + #endif /* #ifndef SC_SAT_ZERO */ + #ifndef SC_SAT_SYM + #define SC_SAT_SYM AP_SAT_SYM + #endif /* #ifndef SC_SAT_SYM */ + #ifndef SC_WRAP_SM + #define SC_WRAP_SM AP_WRAP_SM + #endif /* #ifndef SC_WRAP_SM */ + #ifndef SC_BIN + #define SC_BIN AP_BIN + #endif /* #ifndef SC_BIN */ + #ifndef SC_OCT + #define SC_OCT AP_OCT + #endif /* #ifndef SC_OCT */ + #ifndef SC_DEC + #define SC_DEC AP_DEC + #endif /* #ifndef SC_DEC */ + #ifndef SC_HEX + #define SC_HEX AP_HEX + #endif /* #ifndef SC_HEX */ +#endif /* #if !(defined SYSTEMC_H) && !(defined SYSTEMC_INCLUDED) */ +#ifndef AP_INT_MAX_W +#define AP_INT_MAX_W 1024 +#endif +#define BIT_WIDTH_UPPER_LIMIT (1 << 15) +#if AP_INT_MAX_W > BIT_WIDTH_UPPER_LIMIT +#error "Bitwidth exceeds 32768 (1 << 15), the maximum allowed value" +#endif +#define MAX_MODE(BITS) ((BITS + 1023) / 1024) + +///Forward declaration +template struct ap_range_ref; +template struct ap_bit_ref; + +template struct ap_fixed_base; +template struct af_range_ref; +template struct af_bit_ref; +template class ap_uint; + +enum { + AP_BIN = 2, + AP_OCT = 8, + AP_DEC = 10, + AP_HEX = 16 +}; + +///Why to use reference? +///Because we will operate the original object indirectly by operating the +///result object directly after concating or part selecting + +///Proxy class which allows concatination to be used as rvalue(for reading) and +//lvalue(for writing) + +/// Concatination reference. +// ---------------------------------------------------------------- +template +struct ap_concat_ref { +#ifdef _MSC_VER + #pragma warning(disable: 4521 4522) +#endif /* #ifdef _MSC_VER */ + enum {_AP_WR=_AP_W1+_AP_W2,}; + _AP_T1& mbv1; + _AP_T2& mbv2; + + INLINE ap_concat_ref(const ap_concat_ref<_AP_W1, _AP_T1, + _AP_W2, _AP_T2>& ref): + mbv1(ref.mbv1), mbv2(ref.mbv2) {} + + INLINE ap_concat_ref(_AP_T1& bv1, _AP_T2& bv2):mbv1(bv1),mbv2(bv2) {} + + template + INLINE ap_concat_ref& operator = (const ap_private<_AP_W3,_AP_S3>& val) { + ap_private<_AP_W1+_AP_W2, false> vval(val); + int W_ref1=mbv1.length(); + int W_ref2=mbv2.length(); + ap_private<_AP_W1,false> mask1(-1); + mask1>>=_AP_W1-W_ref1; + ap_private<_AP_W2,false> mask2(-1); + mask2>>=_AP_W2-W_ref2; + mbv1.set(ap_private<_AP_W1,false>((vval>>W_ref2)&mask1)); + mbv2.set(ap_private<_AP_W2,false>(vval&mask2)); + return *this; + } + + INLINE ap_concat_ref& operator = (unsigned long long val) { + ap_private<_AP_W1+_AP_W2, false> tmpVal(val); + return operator = (tmpVal); + } + + template + INLINE ap_concat_ref& operator = + (const ap_concat_ref <_AP_W3, _AP_T3, _AP_W4, _AP_T4>& val) { + ap_private<_AP_W1+_AP_W2, false> tmpVal(val); + return operator = (tmpVal); + } + + INLINE ap_concat_ref& operator = + (const ap_concat_ref <_AP_W1, _AP_T1, _AP_W2, _AP_T2>& val) { + ap_private<_AP_W1+_AP_W2, false> tmpVal(val); + return operator = (tmpVal); + } + + template + INLINE ap_concat_ref& operator =(const ap_bit_ref<_AP_W3, _AP_S3>& val) { + ap_private<_AP_W1+_AP_W2, false> tmpVal(val); + return operator = (tmpVal); + } + + template + INLINE ap_concat_ref& operator =(const ap_range_ref<_AP_W3,_AP_S3>& val) { + ap_private<_AP_W1+_AP_W2, false> tmpVal(val); + return operator =(tmpVal); + } + + template + INLINE ap_concat_ref& operator= (const af_range_ref<_AP_W3, _AP_I3, _AP_S3, + _AP_Q3, _AP_O3, _AP_N3>& val) { + return operator = ((const ap_private<_AP_W3, false>)(val)); + } + + template + INLINE ap_concat_ref& operator= (const ap_fixed_base<_AP_W3, _AP_I3, _AP_S3, + _AP_Q3, _AP_O3, _AP_N3>& val) { + return operator = (val.to_ap_private()); + } + + template + INLINE ap_concat_ref& operator= (const af_bit_ref<_AP_W3, _AP_I3, _AP_S3, + _AP_Q3, _AP_O3, _AP_N3>& val) { + return operator=((unsigned long long)(bool)(val)); + } + + + INLINE operator ap_private<_AP_WR, false> () const { + return get(); + } + + INLINE operator unsigned long long () const { + return get().to_uint64(); + } + + template + INLINE ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, ap_range_ref<_AP_W3, _AP_S3> > + operator, (const ap_range_ref<_AP_W3, _AP_S3> &a2) { + return ap_concat_ref<_AP_WR, ap_concat_ref, + _AP_W3, ap_range_ref<_AP_W3, _AP_S3> >(*this, + const_cast &>(a2)); + } + + template + INLINE ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, ap_private<_AP_W3, _AP_S3> > + operator, (ap_private<_AP_W3, _AP_S3> &a2) { + return ap_concat_ref<_AP_WR, ap_concat_ref, + _AP_W3, ap_private<_AP_W3, _AP_S3> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, ap_private<_AP_W3, _AP_S3> > + operator, (const ap_private<_AP_W3, _AP_S3> &a2) { + return ap_concat_ref<_AP_WR, ap_concat_ref, + _AP_W3, ap_private<_AP_W3, _AP_S3> >(*this, + const_cast&>(a2)); + } + + template + INLINE ap_concat_ref<_AP_WR, ap_concat_ref, 1, ap_bit_ref<_AP_W3, _AP_S3> > + operator, (const ap_bit_ref<_AP_W3, _AP_S3> &a2) { + return ap_concat_ref<_AP_WR, ap_concat_ref, + 1, ap_bit_ref<_AP_W3, _AP_S3> >(*this, + const_cast &>(a2)); + } + + template + INLINE ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3+_AP_W4, ap_concat_ref<_AP_W3,_AP_T3,_AP_W4,_AP_T4> > + operator, (const ap_concat_ref<_AP_W3,_AP_T3,_AP_W4,_AP_T4> &a2) + { + return ap_concat_ref<_AP_WR, ap_concat_ref, + _AP_W3+_AP_W4, ap_concat_ref<_AP_W3,_AP_T3,_AP_W4, + _AP_T4> >(*this, const_cast& >(a2)); + } + + template + INLINE + ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, af_range_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3> > + operator, (const af_range_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, + _AP_O3, _AP_N3> &a2) { + return ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, af_range_ref<_AP_W3, + _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3> >(*this, + const_cast& >(a2)); + } + + template + INLINE + ap_concat_ref<_AP_WR, ap_concat_ref, 1, af_bit_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3> > + operator, (const af_bit_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, + _AP_O3, _AP_N3> &a2) { + return ap_concat_ref<_AP_WR, ap_concat_ref, 1, af_bit_ref<_AP_W3, + _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3> >(*this, + const_cast& >(a2)); + } + + template + INLINE ap_private + operator & (const ap_private<_AP_W3,_AP_S3>& a2) { + return get() & a2; + } + + + template + INLINE ap_private + operator | (const ap_private<_AP_W3,_AP_S3>& a2) { + return get() | a2; + } + + + template + INLINE ap_private + operator ^ (const ap_private<_AP_W3,_AP_S3>& a2) { + return ap_private(get() ^ a2); + } + + INLINE const ap_private<_AP_WR, false> get() const + { + ap_private<_AP_W1+_AP_W2, false> tmpVal = ap_private<_AP_W1+_AP_W2, false> (mbv1.get()); + ap_private<_AP_W1+_AP_W2, false> tmpVal2 = ap_private<_AP_W1+_AP_W2, false> (mbv2.get()); + int W_ref2 = mbv2.length(); + tmpVal <<= W_ref2; + tmpVal |= tmpVal2; + return tmpVal; + } + + INLINE const ap_private<_AP_WR, false> get() { + ap_private<_AP_W1+_AP_W2, false> tmpVal = ap_private<_AP_W1+_AP_W2, false> ( mbv1.get()); + ap_private<_AP_W1+_AP_W2, false> tmpVal2 = ap_private<_AP_W1+_AP_W2, false> (mbv2.get()); + int W_ref2 = mbv2.length(); + tmpVal <<= W_ref2; + tmpVal |= tmpVal2; + return tmpVal; + } + + template + INLINE void set(const ap_private<_AP_W3,false> & val) { + ap_private<_AP_W1+_AP_W2, false> vval(val); + int W_ref1=mbv1.length(); + int W_ref2=mbv2.length(); + ap_private<_AP_W1,false> mask1(-1); + mask1>>=_AP_W1-W_ref1; + ap_private<_AP_W2,false> mask2(-1); + mask2>>=_AP_W2-W_ref2; + mbv1.set(ap_private<_AP_W1,false>((vval>>W_ref2)&mask1)); + mbv2.set(ap_private<_AP_W2,false>(vval&mask2)); + } + + INLINE int length() const { + return mbv1.length()+mbv2.length(); + } + + INLINE std::string to_string(uint8_t radix=2) const { + return get().to_string(radix); + } +}; + +///Proxy class, which allows part selection to be used as rvalue(for reading) and +//lvalue(for writing) + +///Range(slice) reference +//------------------------------------------------------------ +template +struct ap_range_ref { +#ifdef _MSC_VER + #pragma warning( disable : 4521 4522 ) +#endif /* #ifdef _MSC_VER */ + ap_private<_AP_W,_AP_S> &d_bv; + int l_index; + int h_index; + +public: + INLINE ap_range_ref(const ap_range_ref<_AP_W, _AP_S>& ref): + d_bv(ref.d_bv), l_index(ref.l_index), h_index(ref.h_index) {} + + INLINE ap_range_ref(ap_private<_AP_W,_AP_S>* bv, int h, int l): + d_bv(*bv),l_index(l),h_index(h) { + //if (h < l) + //fprintf(stderr, "Warning! The bits selected will be returned in reverse order\n"); + } + + INLINE operator ap_private<_AP_W, false> () const { + ap_private<_AP_W, false> val(0); + if(h_index>=l_index) { + if (_AP_W > 64) { + val=d_bv; + ap_private<_AP_W,false> mask(-1); + mask>>=_AP_W-(h_index-l_index+1); + val>>=l_index; + val&=mask; + } else { + const static uint64_t mask = (~0ULL>> (64>_AP_W ? (64-_AP_W):0)); + val = (d_bv >> l_index) & (mask >>(_AP_W-(h_index-l_index+1))); + } + } else { + for(int i=0, j=l_index;j>=0&&j>=h_index;j--,i++) + if((d_bv)[j]) val.set(i); + } + return val; + } + + INLINE operator unsigned long long () const { + return to_uint64(); + } + + template + INLINE ap_range_ref& operator =(const ap_private<_AP_W2,_AP_S2>& val) { + ap_private<_AP_W,false> vval=ap_private<_AP_W,false>(val); + if (l_index>h_index) { + for (int i=0, j=l_index;j>=0&&j>=h_index;j--,i++) + (vval)[i]? d_bv.set(j):d_bv.clear(j); + } else { + if (_AP_W > 64) { + ap_private<_AP_W,false> mask(-1); + if (l_index>0) { + mask<<=l_index; + vval<<=l_index; + } + if(h_index<_AP_W-1) + { + ap_private<_AP_W,false> mask2(-1); + mask2>>=_AP_W-h_index-1; + mask&=mask2; + vval&=mask2; + } + mask.flip(); + d_bv&=mask; + d_bv|=vval; + } else { + unsigned shift = 64-_AP_W; + uint64_t mask = ~0ULL>>(shift); + if(l_index>0) + { + vval = mask & vval << l_index; + mask = mask & mask << l_index; + } + if(h_index<_AP_W-1) + { + uint64_t mask2 = mask; + mask2 >>= (_AP_W-h_index-1); + mask&=mask2; + vval&=mask2; + } + mask = ~mask; + d_bv&=mask; + d_bv|=vval; + } + } + return *this; + } + + INLINE ap_range_ref& operator = (unsigned long long val) + { + const ap_private<_AP_W,_AP_S> vval=val; + return operator = (vval); + } + + + INLINE ap_range_ref& operator =(const ap_range_ref<_AP_W, _AP_S>& val) + { + const ap_private<_AP_W, false> tmpVal(val); + return operator =(tmpVal); + } + + + + template + INLINE ap_range_ref& operator = + (const ap_concat_ref <_AP_W3, _AP_T3, _AP_W4, _AP_T4>& val) + { + const ap_private<_AP_W, false> tmpVal(val); + return operator = (tmpVal); + } + + template + INLINE ap_range_ref& operator =(const ap_range_ref<_AP_W3,_AP_S3>& val) + { + const ap_private<_AP_W, false> tmpVal(val); + return operator =(tmpVal); + } + + template + INLINE ap_range_ref& operator= (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& val) { + return operator=((const ap_private<_AP_W2, _AP_S2>)(val)); + } + + template + INLINE ap_range_ref& operator= (const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& val) { + return operator=(val.to_ap_private()); + } + + template + INLINE ap_range_ref& operator= (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& val) { + return operator=((unsigned long long)(bool)(val)); + } + + template + INLINE ap_range_ref& operator= (const ap_bit_ref<_AP_W2, _AP_S2>& val) { + return operator=((unsigned long long)(bool)(val)); + } + + template + INLINE + ap_concat_ref<_AP_W,ap_range_ref,_AP_W2,ap_range_ref<_AP_W2,_AP_S2> > + operator, (const ap_range_ref<_AP_W2,_AP_S2> &a2) + { + return + ap_concat_ref<_AP_W, ap_range_ref, _AP_W2, + ap_range_ref<_AP_W2,_AP_S2> >(*this, + const_cast& >(a2)); + } + + + template + INLINE ap_concat_ref<_AP_W,ap_range_ref,_AP_W2,ap_private<_AP_W2,_AP_S2> > + operator , (ap_private<_AP_W2,_AP_S2>& a2) + { + return + ap_concat_ref<_AP_W, ap_range_ref, _AP_W2, ap_private<_AP_W2,_AP_S2> >(*this, a2); + } + + INLINE ap_concat_ref<_AP_W,ap_range_ref,_AP_W,ap_private<_AP_W,_AP_S> > + operator , (ap_private<_AP_W, _AP_S>& a2) + { + return + ap_concat_ref<_AP_W, ap_range_ref, _AP_W, + ap_private<_AP_W,_AP_S> >(*this, a2); + } + + + + template + INLINE + ap_concat_ref<_AP_W,ap_range_ref,1,ap_bit_ref<_AP_W2,_AP_S2> > + operator, (const ap_bit_ref<_AP_W2,_AP_S2> &a2) + { + return + ap_concat_ref<_AP_W, ap_range_ref, 1, + ap_bit_ref<_AP_W2,_AP_S2> >(*this, const_cast& >(a2)); + } + + + template + INLINE + ap_concat_ref<_AP_W, ap_range_ref, _AP_W2+_AP_W3, ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > + operator, (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) + { + return ap_concat_ref<_AP_W, ap_range_ref, _AP_W2+_AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(*this, + const_cast& >(a2)); + } + + template + INLINE + ap_concat_ref<_AP_W, ap_range_ref, _AP_W2, af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<_AP_W, ap_range_ref, _AP_W2, af_range_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, + const_cast& >(a2)); + } + + template + INLINE + ap_concat_ref<_AP_W, ap_range_ref, 1, af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<_AP_W, ap_range_ref, 1, af_bit_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, + const_cast& >(a2)); + } + + template + INLINE bool operator == (const ap_range_ref<_AP_W2, _AP_S2>& op2) + { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs==rhs; + } + + + template + INLINE bool operator != (const ap_range_ref<_AP_W2, _AP_S2>& op2) + { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs!=rhs; + } + + + template + INLINE bool operator > (const ap_range_ref<_AP_W2, _AP_S2>& op2) + { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs>rhs; + } + + + template + INLINE bool operator >= (const ap_range_ref<_AP_W2, _AP_S2>& op2) + { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs>=rhs; + } + + + template + INLINE bool operator < (const ap_range_ref<_AP_W2, _AP_S2>& op2) + { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs + INLINE bool operator <= (const ap_range_ref<_AP_W2, _AP_S2>& op2) + { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs<=rhs; + } + + + template + INLINE void set(const ap_private<_AP_W2,false>& val) + { + ap_private<_AP_W,_AP_S> vval=val; + if(l_index>h_index) + { + for(int i=0, j=l_index;j>=0&&j>=h_index;j--,i++) + (vval)[i]? d_bv.set(j):d_bv.clear(j); + } else { + if (_AP_W>64 ) { + ap_private<_AP_W,_AP_S> mask(-1); + if(l_index>0) + { + ap_private<_AP_W,false> mask1(-1); + mask1>>=_AP_W-l_index; + mask1.flip(); + mask=mask1; + //vval&=mask1; + vval<<=l_index; + } + if(h_index<_AP_W-1) + { + ap_private<_AP_W,false> mask2(-1); + mask2<<=h_index+1; + mask2.flip(); + mask&=mask2; + vval&=mask2; + } + mask.flip(); + d_bv&=mask; + d_bv|=vval; + } else { + uint64_t mask = ~0ULL >> (64-_AP_W); + if(l_index>0) + { + uint64_t mask1 = mask; + mask1=mask & (mask1>>(_AP_W-l_index)); + vval =mask&( vval <> (64-_AP_W); + mask2 = mask &(mask2<<(h_index+1)); + mask&=~mask2; + vval&=~mask2; + } + d_bv&=(~mask&(~0ULL >> (64-_AP_W))); + d_bv|=vval; + } + } + } + + + INLINE ap_private<_AP_W,false> get() const + { + ap_private<_AP_W,false> val(0); + if(h_index=0&&j>=h_index;j--,i++) + if((d_bv)[j]) val.set(i); + } else { + val=d_bv; + val>>=l_index; + if(h_index<_AP_W-1) + { + if (_AP_W <= 64) { + const static uint64_t mask = (~0ULL>> (64>_AP_W ? (64-_AP_W):0)); + val &= (mask>> (_AP_W-(h_index-l_index+1))); + } else { + ap_private<_AP_W,false> mask(-1); + mask>>=_AP_W-(h_index-l_index+1); + val&=mask; + } + } + } + return val; + } + + + INLINE ap_private<_AP_W,false> get() + { + ap_private<_AP_W,false> val(0); + if(h_index=0&&j>=h_index;j--,i++) + if((d_bv)[j]) val.set(i); + } else { + val=d_bv; + val>>=l_index; + if(h_index<_AP_W-1) + { + if (_AP_W <= 64 ) { + static const uint64_t mask = ~0ULL>> (64>_AP_W ? (64-_AP_W):0); + return val &= ( (mask) >> (_AP_W - (h_index-l_index+1))); + } else { + ap_private<_AP_W,false> mask(-1); + mask>>=_AP_W-(h_index-l_index+1); + val&=mask; + } + } + } + return val; + } + + + INLINE int length() const + { + return h_index>=l_index?h_index-l_index+1:l_index-h_index+1; + } + + + INLINE int to_int() const + { + ap_private<_AP_W,false> val=get(); + return val.to_int(); + } + + + INLINE unsigned int to_uint() const + { + ap_private<_AP_W,false> val=get(); + return val.to_uint(); + } + + + INLINE long to_long() const + { + ap_private<_AP_W,false> val=get(); + return val.to_long(); + } + + + INLINE unsigned long to_ulong() const + { + ap_private<_AP_W,false> val=get(); + return val.to_ulong(); + } + + + INLINE ap_slong to_int64() const + { + ap_private<_AP_W,false> val=get(); + return val.to_int64(); + } + + + INLINE ap_ulong to_uint64() const + { + ap_private<_AP_W,false> val=get(); + return val.to_uint64(); + } + + INLINE std::string to_string(uint8_t radix=2) const { + return get().to_string(radix); + } + +}; + +///Proxy class, which allows bit selection to be used as rvalue(for reading) and +//lvalue(for writing) + +///Bit reference +//-------------------------------------------------------------- +template +struct ap_bit_ref { +#ifdef _MSC_VER +#pragma warning( disable : 4521 4522 ) +#endif + ap_private<_AP_W,_AP_S>& d_bv; + int d_index; + +public: + INLINE ap_bit_ref(const ap_bit_ref<_AP_W, _AP_S>& ref): + d_bv(ref.d_bv), d_index(ref.d_index) {} + + INLINE ap_bit_ref(ap_private<_AP_W,_AP_S>& bv, int index=0): + d_bv(bv),d_index(index) + { +#ifdef _AP_DEBUG_ + assert(d_index<_AP_W&&"index out of bound"); +#endif + } + + + INLINE operator bool () const + { + return d_bv.get_bit(d_index); + } + + + INLINE bool to_bool() const + { + return operator bool (); + } + + + INLINE ap_bit_ref& operator = (unsigned long long val) + { + if(val) + d_bv.set(d_index); + else + d_bv.clear(d_index); + return *this; + } + + +#if 0 + INLINE ap_bit_ref& operator = (bool val) + { + if(val) + d_bv.set(d_index); + else + d_bv.clear(d_index); + return *this; + } +#endif + template + INLINE ap_bit_ref& operator =(const ap_private<_AP_W2,_AP_S2>& val) + { + return operator =((unsigned long long)(val != 0)); + } + + + template + INLINE ap_bit_ref& operator =(const ap_bit_ref<_AP_W2,_AP_S2>& val) + { + return operator =((unsigned long long)(bool)val); + } + + INLINE ap_bit_ref& operator =(const ap_bit_ref<_AP_W,_AP_S>& val) + { + return operator =((unsigned long long)(bool)val); + } + + template + INLINE ap_bit_ref& operator =(const ap_range_ref<_AP_W2,_AP_S2>& val) + { + return operator =((unsigned long long)(bool) val); + } + + + template + INLINE ap_bit_ref& operator= (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& val) { + return operator=((const ap_private<_AP_W2, false>)(val)); + } + + template + INLINE ap_bit_ref& operator= (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& val) { + return operator=((unsigned long long)(bool)(val)); + } + + template + INLINE ap_bit_ref& operator= (const ap_concat_ref<_AP_W2, _AP_T3, _AP_W3, _AP_T3>& val) { + return operator=((const ap_private<_AP_W2 + _AP_W3, false>)(val)); + } + + + + template + INLINE ap_concat_ref<1, ap_bit_ref, _AP_W2, ap_private<_AP_W2,_AP_S2> > + operator , (ap_private<_AP_W2, _AP_S2>& a2) + { + return ap_concat_ref<1, ap_bit_ref, _AP_W2, ap_private<_AP_W2,_AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<1, ap_bit_ref, _AP_W2, ap_range_ref<_AP_W2,_AP_S2> > + operator, (const ap_range_ref<_AP_W2, _AP_S2> &a2) + { + return + ap_concat_ref<1, ap_bit_ref, _AP_W2, ap_range_ref<_AP_W2,_AP_S2> >(*this, + const_cast &>(a2)); + } + + + template + INLINE ap_concat_ref<1, ap_bit_ref, 1, ap_bit_ref<_AP_W2,_AP_S2> > + operator, (const ap_bit_ref<_AP_W2, _AP_S2> &a2) + { + return + ap_concat_ref<1, ap_bit_ref, 1, ap_bit_ref<_AP_W2,_AP_S2> >(*this, + const_cast &>(a2)); + } + + + INLINE ap_concat_ref<1, ap_bit_ref, 1, ap_bit_ref > + operator, (const ap_bit_ref &a2) + { + return + ap_concat_ref<1, ap_bit_ref, 1, ap_bit_ref >(*this, + const_cast(a2)); + } + + + template + INLINE ap_concat_ref<1, ap_bit_ref, _AP_W2+_AP_W3, ap_concat_ref<_AP_W2,_AP_T2,_AP_W3,_AP_T3> > + operator, (const ap_concat_ref<_AP_W2,_AP_T2,_AP_W3,_AP_T3> &a2) + { + return + ap_concat_ref<1,ap_bit_ref,_AP_W2+_AP_W3, + ap_concat_ref<_AP_W2,_AP_T2,_AP_W3,_AP_T3> >(*this, + const_cast& >(a2)); + } + + template + INLINE + ap_concat_ref<1, ap_bit_ref, _AP_W2, af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<1, ap_bit_ref, _AP_W2, af_range_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, + const_cast& >(a2)); + } + + template + INLINE + ap_concat_ref<1, ap_bit_ref, 1, af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<1, ap_bit_ref, 1, af_bit_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, + const_cast& >(a2)); + } + + template + INLINE bool operator == (const ap_bit_ref<_AP_W2, _AP_S2>& op) { + return get() == op.get(); + } + + template + INLINE bool operator != (const ap_bit_ref<_AP_W2, _AP_S2>& op) { + return get() != op.get(); + } + + + INLINE bool get() const + { + return operator bool (); + } + + + INLINE bool get() + { + return operator bool (); + } + + + template + INLINE void set(const ap_private<_AP_W3, false>& val) + { + operator = (val); + } + + INLINE bool operator ~ () const { + bool bit = (d_bv)[d_index]; + return bit ? false : true; + } + + INLINE int length() const { return 1; } + + INLINE std::string to_string() const { + bool val = get(); + return val ? "1" : "0"; + } +}; + +/// Operators mixing Integers with AP_Int +// ---------------------------------------------------------------- +#if 1 +#define OP_BIN_MIX_INT(BIN_OP, C_TYPE, _AP_WI, _AP_SI, RTYPE) \ + template \ + INLINE typename ap_private<_AP_WI,_AP_SI>::template RType<_AP_W,_AP_S>::RTYPE \ + operator BIN_OP ( C_TYPE i_op, const ap_private<_AP_W,_AP_S> &op) { \ + return ap_private<_AP_WI,_AP_SI>(i_op).operator BIN_OP (op); \ + } \ + template \ + INLINE typename ap_private<_AP_W,_AP_S>::template RType<_AP_WI,_AP_SI>::RTYPE \ + operator BIN_OP ( const ap_private<_AP_W,_AP_S> &op, C_TYPE i_op) { \ + return op.operator BIN_OP (ap_private<_AP_WI,_AP_SI>(i_op)); \ + } +#else +#define OP_BIN_MIX_INT(BIN_OP, C_TYPE, _AP_WI, _AP_SI, RTYPE) \ + template \ + INLINE typename ap_private<_AP_WI,_AP_SI>::template RType<_AP_W,_AP_S>::RTYPE \ + operator BIN_OP ( C_TYPE i_op, const ap_private<_AP_W,_AP_S> &op) { \ + return ap_private<_AP_WI,_AP_SI>(i_op).operator BIN_OP (op); \ + } \ + template \ + INLINE typename ap_private<_AP_W,_AP_S>::template RType<_AP_WI,_AP_SI>::RTYPE \ + operator BIN_OP ( const ap_private<_AP_W,_AP_S> &op, C_TYPE i_op) { \ + return op.operator BIN_OP (ap_private<_AP_WI,_AP_SI>(i_op)); \ + } +#endif +#define OP_REL_MIX_INT(REL_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE bool operator REL_OP ( const ap_private<_AP_W,_AP_S> &op, C_TYPE op2) { \ + return op.operator REL_OP (ap_private<_AP_W2, _AP_S2>(op2)); \ + } \ + template \ + INLINE bool operator REL_OP ( C_TYPE op2, const ap_private<_AP_W,_AP_S> &op) { \ + return ap_private<_AP_W2,_AP_S2>(op2).operator REL_OP (op); \ + } +#define OP_ASSIGN_MIX_INT(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE ap_private<_AP_W,_AP_S> &operator ASSIGN_OP ( ap_private<_AP_W,_AP_S> &op, C_TYPE op2) { \ + return op.operator ASSIGN_OP (ap_private<_AP_W2,_AP_S2>(op2)); \ + } + +#define OP_BIN_SHIFT_INT(BIN_OP, C_TYPE, _AP_WI, _AP_SI, RTYPE) \ + template \ + C_TYPE operator BIN_OP ( C_TYPE i_op, const ap_private<_AP_W,_AP_S> &op) { \ + return i_op BIN_OP (op.getVal()); \ + } \ + template \ + INLINE typename ap_private<_AP_W,_AP_S>::template RType<_AP_WI,_AP_SI>::RTYPE \ + operator BIN_OP ( const ap_private<_AP_W,_AP_S> &op, C_TYPE i_op) { \ + return op.operator BIN_OP (i_op); \ + } +#define OP_ASSIGN_RSHIFT_INT(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE ap_private<_AP_W,_AP_S> &operator ASSIGN_OP ( ap_private<_AP_W,_AP_S> &op, C_TYPE op2) { \ + op = op.operator >> (op2); \ + return op; \ + } +#define OP_ASSIGN_LSHIFT_INT(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE ap_private<_AP_W,_AP_S> &operator ASSIGN_OP ( ap_private<_AP_W,_AP_S> &op, C_TYPE op2) { \ + op = op.operator << (op2); \ + return op; \ + } + +#define OPS_MIX_INT(C_TYPE, WI, SI) \ + OP_BIN_MIX_INT(*, C_TYPE, WI, SI, mult) \ + OP_BIN_MIX_INT(+, C_TYPE, WI, SI, plus) \ + OP_BIN_MIX_INT(-, C_TYPE, WI, SI, minus) \ + OP_BIN_MIX_INT(/, C_TYPE, WI, SI, div) \ + OP_BIN_MIX_INT(%, C_TYPE, WI, SI, mod) \ + OP_BIN_MIX_INT(&, C_TYPE, WI, SI, logic) \ + OP_BIN_MIX_INT(|, C_TYPE, WI, SI, logic) \ + OP_BIN_MIX_INT(^, C_TYPE, WI, SI, logic) \ + OP_BIN_SHIFT_INT(>>, C_TYPE, WI, SI, arg1) \ + OP_BIN_SHIFT_INT(<<, C_TYPE, WI, SI, arg1) \ + \ + OP_REL_MIX_INT(==, C_TYPE, WI, SI) \ + OP_REL_MIX_INT(!=, C_TYPE, WI, SI) \ + OP_REL_MIX_INT(>, C_TYPE, WI, SI) \ + OP_REL_MIX_INT(>=, C_TYPE, WI, SI) \ + OP_REL_MIX_INT(<, C_TYPE, WI, SI) \ + OP_REL_MIX_INT(<=, C_TYPE, WI, SI) \ + \ + OP_ASSIGN_MIX_INT(+=, C_TYPE, WI, SI) \ + OP_ASSIGN_MIX_INT(-=, C_TYPE, WI, SI) \ + OP_ASSIGN_MIX_INT(*=, C_TYPE, WI, SI) \ + OP_ASSIGN_MIX_INT(/=, C_TYPE, WI, SI) \ + OP_ASSIGN_MIX_INT(%=, C_TYPE, WI, SI) \ + OP_ASSIGN_MIX_INT(&=, C_TYPE, WI, SI) \ + OP_ASSIGN_MIX_INT(|=, C_TYPE, WI, SI) \ + OP_ASSIGN_MIX_INT(^=, C_TYPE, WI, SI) \ + OP_ASSIGN_RSHIFT_INT(>>=, C_TYPE, WI, SI) \ + OP_ASSIGN_LSHIFT_INT(<<=, C_TYPE, WI, SI) + + +OPS_MIX_INT(bool, 1, false) +OPS_MIX_INT(char, 8, true) +OPS_MIX_INT(signed char, 8, true) +OPS_MIX_INT(unsigned char, 8, false) +OPS_MIX_INT(short, 16, true) +OPS_MIX_INT(unsigned short, 16, false) +OPS_MIX_INT(int, 32, true) +OPS_MIX_INT(unsigned int, 32, false) +# if defined __x86_64__ +OPS_MIX_INT(long, 64, true) +OPS_MIX_INT(unsigned long, 64, false) +# else +OPS_MIX_INT(long, 32, true) +OPS_MIX_INT(unsigned long, 32, false) +# endif +OPS_MIX_INT(ap_slong, 64, true) +OPS_MIX_INT(ap_ulong, 64, false) + +#define OP_BIN_MIX_RANGE(BIN_OP, RTYPE) \ + template \ + INLINE typename ap_private<_AP_W1,_AP_S1>::template RType<_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP ( const ap_range_ref<_AP_W1,_AP_S1>& op1, const ap_private<_AP_W2,_AP_S2>& op2) { \ + return ap_private<_AP_W1, false>(op1).operator BIN_OP (op2); \ + } \ + template \ + INLINE typename ap_private<_AP_W1,_AP_S1>::template RType<_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP ( const ap_private<_AP_W1,_AP_S1>& op1, const ap_range_ref<_AP_W2,_AP_S2>& op2) { \ + return op1.operator BIN_OP (ap_private<_AP_W2, false>(op2)); \ + } + +#define OP_REL_MIX_RANGE(REL_OP) \ + template \ + INLINE bool operator REL_OP ( const ap_range_ref<_AP_W1,_AP_S1>& op1, const ap_private<_AP_W2,_AP_S2>& op2) { \ + return ap_private<_AP_W1,false>(op1).operator REL_OP (op2); \ + } \ + template \ + INLINE bool operator REL_OP ( const ap_private<_AP_W1,_AP_S1>& op1, const ap_range_ref<_AP_W2,_AP_S2>& op2) { \ + return op1.operator REL_OP (op2.operator ap_private<_AP_W2, false>()); \ + } + +#define OP_ASSIGN_MIX_RANGE(ASSIGN_OP) \ + template \ + INLINE ap_private<_AP_W1,_AP_S1>& operator ASSIGN_OP ( ap_private<_AP_W1,_AP_S1>& op1, const ap_range_ref<_AP_W2,_AP_S2>& op2) { \ + return op1.operator ASSIGN_OP (ap_private<_AP_W2, false>(op2)); \ + } \ + template \ + INLINE ap_range_ref<_AP_W1,_AP_S1>& operator ASSIGN_OP (ap_range_ref<_AP_W1,_AP_S1>& op1, ap_private<_AP_W2,_AP_S2>& op2) { \ + ap_private<_AP_W1, false> tmp(op1); \ + tmp.operator ASSIGN_OP (op2); \ + op1 = tmp; \ + return op1; \ + } + + +OP_ASSIGN_MIX_RANGE(+=) +OP_ASSIGN_MIX_RANGE(-=) +OP_ASSIGN_MIX_RANGE(*=) +OP_ASSIGN_MIX_RANGE(/=) +OP_ASSIGN_MIX_RANGE(%=) +OP_ASSIGN_MIX_RANGE(>>=) +OP_ASSIGN_MIX_RANGE(<<=) +OP_ASSIGN_MIX_RANGE(&=) +OP_ASSIGN_MIX_RANGE(|=) +OP_ASSIGN_MIX_RANGE(^=) + +OP_REL_MIX_RANGE(==) +OP_REL_MIX_RANGE(!=) +OP_REL_MIX_RANGE(>) +OP_REL_MIX_RANGE(>=) +OP_REL_MIX_RANGE(<) +OP_REL_MIX_RANGE(<=) + +OP_BIN_MIX_RANGE(+, plus) +OP_BIN_MIX_RANGE(-, minus) +OP_BIN_MIX_RANGE(*, mult) +OP_BIN_MIX_RANGE(/, div) +OP_BIN_MIX_RANGE(%, mod) +OP_BIN_MIX_RANGE(>>, arg1) +OP_BIN_MIX_RANGE(<<, arg1) +OP_BIN_MIX_RANGE(&, logic) +OP_BIN_MIX_RANGE(|, logic) +OP_BIN_MIX_RANGE(^, logic) + +#define OP_BIN_MIX_BIT(BIN_OP, RTYPE) \ + template \ + INLINE typename ap_private<1, false>::template RType<_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP ( const ap_bit_ref<_AP_W1,_AP_S1>& op1, const ap_private<_AP_W2,_AP_S2>& op2) { \ + return ap_private<1, false>(op1).operator BIN_OP (op2); \ + } \ + template \ + INLINE typename ap_private<_AP_W1,_AP_S1>::template RType<1,false>::RTYPE \ + operator BIN_OP ( const ap_private<_AP_W1,_AP_S1>& op1, const ap_bit_ref<_AP_W2,_AP_S2>& op2) { \ + return op1.operator BIN_OP (ap_private<1, false>(op2)); \ + } + +#define OP_REL_MIX_BIT(REL_OP) \ + template \ + INLINE bool operator REL_OP ( const ap_bit_ref<_AP_W1,_AP_S1>& op1, const ap_private<_AP_W2,_AP_S2>& op2) { \ + return ap_private<_AP_W1,false>(op1).operator REL_OP (op2); \ + } \ + template \ + INLINE bool operator REL_OP ( const ap_private<_AP_W1,_AP_S1>& op1, const ap_bit_ref<_AP_W2,_AP_S2>& op2) { \ + return op1.operator REL_OP (ap_private<1, false>(op2)); \ + } + +#define OP_ASSIGN_MIX_BIT(ASSIGN_OP) \ + template \ + INLINE ap_private<_AP_W1,_AP_S1>& operator ASSIGN_OP ( ap_private<_AP_W1,_AP_S1>& op1, ap_bit_ref<_AP_W2,_AP_S2>& op2) { \ + return op1.operator ASSIGN_OP (ap_private<1, false>(op2)); \ + } \ + template \ + INLINE ap_bit_ref<_AP_W1,_AP_S1>& operator ASSIGN_OP ( ap_bit_ref<_AP_W1,_AP_S1>& op1, ap_private<_AP_W2,_AP_S2>& op2) { \ + ap_private<1, false> tmp(op1); \ + tmp.operator ASSIGN_OP (op2); \ + op1 = tmp; \ + return op1; \ + } + + +OP_ASSIGN_MIX_BIT(+=) +OP_ASSIGN_MIX_BIT(-=) +OP_ASSIGN_MIX_BIT(*=) +OP_ASSIGN_MIX_BIT(/=) +OP_ASSIGN_MIX_BIT(%=) +OP_ASSIGN_MIX_BIT(>>=) +OP_ASSIGN_MIX_BIT(<<=) +OP_ASSIGN_MIX_BIT(&=) +OP_ASSIGN_MIX_BIT(|=) +OP_ASSIGN_MIX_BIT(^=) + +OP_REL_MIX_BIT(==) +OP_REL_MIX_BIT(!=) +OP_REL_MIX_BIT(>) +OP_REL_MIX_BIT(>=) +OP_REL_MIX_BIT(<) +OP_REL_MIX_BIT(<=) + +OP_BIN_MIX_BIT(+, plus) +OP_BIN_MIX_BIT(-, minus) +OP_BIN_MIX_BIT(*, mult) +OP_BIN_MIX_BIT(/, div) +OP_BIN_MIX_BIT(%, mod) +OP_BIN_MIX_BIT(>>, arg1) +OP_BIN_MIX_BIT(<<, arg1) +OP_BIN_MIX_BIT(&, logic) +OP_BIN_MIX_BIT(|, logic) +OP_BIN_MIX_BIT(^, logic) + +#define REF_REL_OP_MIX_INT(REL_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE bool operator REL_OP ( const ap_range_ref<_AP_W,_AP_S> &op, C_TYPE op2) { \ + return (ap_private<_AP_W, false>(op)).operator REL_OP (ap_private<_AP_W2,_AP_S2>(op2)); \ + } \ + template \ + INLINE bool operator REL_OP ( C_TYPE op2, const ap_range_ref<_AP_W,_AP_S> &op) { \ + return ap_private<_AP_W2,_AP_S2>(op2).operator REL_OP (ap_private<_AP_W, false>(op)); \ + } \ + template \ + INLINE bool operator REL_OP ( const ap_bit_ref<_AP_W,_AP_S> &op, C_TYPE op2) { \ + return (bool(op)) REL_OP op2; \ + } \ + template \ + INLINE bool operator REL_OP ( C_TYPE op2, const ap_bit_ref<_AP_W,_AP_S> &op) { \ + return op2 REL_OP (bool(op)); \ + } \ + template \ + INLINE bool operator REL_OP ( const ap_concat_ref<_AP_W,_AP_T, _AP_W1, _AP_T1> &op, C_TYPE op2) { \ + return (ap_private<_AP_W + _AP_W1, false>(op)).operator REL_OP (ap_private<_AP_W2,_AP_S2>(op2)); \ + } \ + template \ + INLINE bool operator REL_OP ( C_TYPE op2, const ap_concat_ref<_AP_W,_AP_T, _AP_W1, _AP_T1> &op) { \ + return ap_private<_AP_W2,_AP_S2>(op2).operator REL_OP (ap_private<_AP_W + _AP_W1, false>(op)); \ + } + +#define REF_REL_MIX_INT(C_TYPE, _AP_WI, _AP_SI) \ +REF_REL_OP_MIX_INT(>, C_TYPE, _AP_WI, _AP_SI) \ +REF_REL_OP_MIX_INT(<, C_TYPE, _AP_WI, _AP_SI) \ +REF_REL_OP_MIX_INT(>=, C_TYPE, _AP_WI, _AP_SI) \ +REF_REL_OP_MIX_INT(<=, C_TYPE, _AP_WI, _AP_SI) \ +REF_REL_OP_MIX_INT(==, C_TYPE, _AP_WI, _AP_SI) \ +REF_REL_OP_MIX_INT(!=, C_TYPE, _AP_WI, _AP_SI) + +REF_REL_MIX_INT(bool, 1, false) +REF_REL_MIX_INT(char, 8, true) +REF_REL_MIX_INT(signed char, 8, true) +REF_REL_MIX_INT(unsigned char, 8, false) +REF_REL_MIX_INT(short, 16, true) +REF_REL_MIX_INT(unsigned short, 16, false) +REF_REL_MIX_INT(int, 32, true) +REF_REL_MIX_INT(unsigned int, 32, false) +# if defined __x86_64__ +REF_REL_MIX_INT(long, 64, true) +REF_REL_MIX_INT(unsigned long, 64, false) +# else +REF_REL_MIX_INT(long, 32, true) +REF_REL_MIX_INT(unsigned long, 32, false) +# endif +REF_REL_MIX_INT(ap_slong, 64, true) +REF_REL_MIX_INT(ap_ulong, 64, false) + +#define REF_BIN_OP_MIX_INT(BIN_OP, RTYPE, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE typename ap_private<_AP_W, false>::template RType<_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP ( const ap_range_ref<_AP_W,_AP_S> &op, C_TYPE op2) { \ + return (ap_private<_AP_W, false>(op)).operator BIN_OP (ap_private<_AP_W2,_AP_S2>(op2)); \ + } \ + template \ + INLINE typename ap_private<_AP_W2, _AP_S2>::template RType<_AP_W,false>::RTYPE \ + operator BIN_OP ( C_TYPE op2, const ap_range_ref<_AP_W,_AP_S> &op) { \ + return ap_private<_AP_W2,_AP_S2>(op2).operator BIN_OP (ap_private<_AP_W, false>(op)); \ + } + +#define REF_BIN_MIX_INT(C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(+, plus, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(-, minus, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(*, mult, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(/, div, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(%, mod, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(>>, arg1, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(<<, arg1, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(&, logic, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(|, logic, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(^, logic, C_TYPE, _AP_WI, _AP_SI) + +REF_BIN_MIX_INT(bool, 1, false) +REF_BIN_MIX_INT(char, 8, true) +REF_BIN_MIX_INT(signed char, 8, true) +REF_BIN_MIX_INT(unsigned char, 8, false) +REF_BIN_MIX_INT(short, 16, true) +REF_BIN_MIX_INT(unsigned short, 16, false) +REF_BIN_MIX_INT(int, 32, true) +REF_BIN_MIX_INT(unsigned int, 32, false) +# if defined __x86_64__ +REF_BIN_MIX_INT(long, 64, true) +REF_BIN_MIX_INT(unsigned long, 64, false) +#else +REF_BIN_MIX_INT(long, 32, true) +REF_BIN_MIX_INT(unsigned long, 32, false) +#endif +REF_BIN_MIX_INT(ap_slong, 64, true) +REF_BIN_MIX_INT(ap_ulong, 64, false) + +#define REF_BIN_OP(BIN_OP, RTYPE) \ +template \ +INLINE typename ap_private<_AP_W, false>::template RType<_AP_W2, false>::RTYPE \ +operator BIN_OP (const ap_range_ref<_AP_W,_AP_S> &lhs, const ap_range_ref<_AP_W2,_AP_S2> &rhs) { \ + return ap_private<_AP_W,false>(lhs).operator BIN_OP (ap_private<_AP_W2, false>(rhs)); \ +} + +REF_BIN_OP(+, plus) +REF_BIN_OP(-, minus) +REF_BIN_OP(*, mult) +REF_BIN_OP(/, div) +REF_BIN_OP(%, mod) +REF_BIN_OP(>>, arg1) +REF_BIN_OP(<<, arg1) +REF_BIN_OP(&, logic) +REF_BIN_OP(|, logic) +REF_BIN_OP(^, logic) + +#if 1 +#define CONCAT_OP_MIX_INT(C_TYPE, _AP_WI, _AP_SI) \ +template \ +INLINE \ +ap_private< _AP_W + _AP_WI, false > \ + operator, (const ap_private<_AP_W, _AP_S> &op1, C_TYPE op2) { \ + ap_private<_AP_WI + _AP_W, false> val(op2); \ + ap_private<_AP_WI + _AP_W, false> ret(op1); \ + ret <<= _AP_WI; \ + if (_AP_SI) { \ + val <<= _AP_W; val >>= _AP_W; \ + }\ + ret |= val; \ + return ret;\ +} \ +template \ +INLINE \ +ap_private< _AP_W + _AP_WI, false > \ + operator, (C_TYPE op1, const ap_private<_AP_W, _AP_S>& op2) { \ + ap_private<_AP_WI + _AP_W, false> val(op1); \ + ap_private<_AP_WI + _AP_W, false> ret(op2); \ + if (_AP_S) { \ + ret <<= _AP_WI; ret >>= _AP_WI; \ + } \ + ret |= val << _AP_W; \ + return ret; \ +} \ +template \ +INLINE \ +ap_private< _AP_W + _AP_WI, false > \ + operator, (const ap_range_ref<_AP_W, _AP_S> &op1, C_TYPE op2) { \ + ap_private<_AP_WI + _AP_W, false> val(op2); \ + ap_private<_AP_WI + _AP_W, false> ret(op1); \ + ret <<= _AP_WI; \ + if (_AP_SI) { \ + val <<= _AP_W; val >>= _AP_W; \ + } \ + ret |= val; \ + return ret; \ +} \ +template \ +INLINE \ +ap_private< _AP_W + _AP_WI, false > \ + operator, (C_TYPE op1, const ap_range_ref<_AP_W, _AP_S> &op2) { \ + ap_private<_AP_WI + _AP_W, false> val(op1); \ + ap_private<_AP_WI + _AP_W, false> ret(op2); \ + int len = op2.length(); \ + val <<= len; \ + ret |= val; \ + return ret; \ +} \ +template \ +INLINE \ +ap_private<_AP_WI + 1, false > \ + operator, (const ap_bit_ref<_AP_W, _AP_S> &op1, C_TYPE op2) { \ + ap_private<_AP_WI + 1, false> val(op2); \ + val[_AP_WI] = op1; \ + return val; \ +} \ +template \ +INLINE \ +ap_private<_AP_WI + 1, false > \ + operator, (C_TYPE op1, const ap_bit_ref<_AP_W, _AP_S> &op2) { \ + ap_private<_AP_WI + 1, false> val(op1); \ + val <<= 1; \ + val[0] = op2; \ + return val; \ +} \ +template \ +INLINE \ +ap_private<_AP_W + _AP_W2 + _AP_WI, false > \ + operator, (const ap_concat_ref<_AP_W, _AP_T, _AP_W2, _AP_T2> &op1, C_TYPE op2) {\ + ap_private<_AP_WI + _AP_W + _AP_W2, _AP_SI> val(op2);\ + ap_private<_AP_WI + _AP_W + _AP_W2, _AP_SI> ret(op1);\ + if (_AP_SI) { \ + val <<= _AP_W + _AP_W2; val >>= _AP_W + _AP_W2; \ + } \ + ret <<= _AP_WI; \ + ret |= val; \ + return ret; \ +}\ +template \ +INLINE \ +ap_private<_AP_W + _AP_W2 + _AP_WI, false > \ + operator, (C_TYPE op1, const ap_concat_ref<_AP_W, _AP_T, _AP_W2, _AP_T2> &op2) {\ + ap_private<_AP_WI + _AP_W + _AP_W2, _AP_SI> val(op1);\ + ap_private<_AP_WI + _AP_W + _AP_W2, _AP_SI> ret(op2);\ + int len = op2.length(); \ + val <<= len; \ + ret |= val;\ + return ret; \ +}\ +template \ +INLINE \ +ap_private< _AP_W + _AP_WI, false > \ + operator, (const af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op1, C_TYPE op2) { \ + ap_private<_AP_WI + _AP_W, false> val(op2); \ + ap_private<_AP_WI + _AP_W, false> ret(op1); \ + if (_AP_SI) { \ + val <<= _AP_W; val >>= _AP_W; \ + }\ + ret <<= _AP_WI; \ + ret |= val; \ + return ret; \ +} \ +template \ +INLINE \ +ap_private< _AP_W + _AP_WI, false > \ + operator, (C_TYPE op1, const af_range_ref<_AP_W, _AP_I, _AP_S, \ + _AP_Q, _AP_O, _AP_N> &op2) { \ + ap_private<_AP_WI + _AP_W, false> val(op1); \ + ap_private<_AP_WI + _AP_W, false> ret(op2); \ + int len = op2.length(); \ + val <<= len; \ + ret |= val; \ + return ret; \ +} \ +template \ +INLINE \ +ap_private< 1 + _AP_WI, false> \ + operator, (const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, \ + _AP_N> &op1, C_TYPE op2) { \ + ap_private<_AP_WI + 1, _AP_SI> val(op2); \ + val[_AP_WI] = op1; \ + return val; \ +} \ +template \ +INLINE \ +ap_private< 1 + _AP_WI, false> \ + operator, (C_TYPE op1, const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q,\ + _AP_O, _AP_N> &op2) { \ + ap_private<_AP_WI + 1, _AP_SI> val(op1); \ + val <<= 1; \ + val[0] = op2; \ + return val; \ +} + +CONCAT_OP_MIX_INT(bool, 1, false) +CONCAT_OP_MIX_INT(char, 8, true) +CONCAT_OP_MIX_INT(signed char, 8, true) +CONCAT_OP_MIX_INT(unsigned char, 8, false) +CONCAT_OP_MIX_INT(short, 16, true) +CONCAT_OP_MIX_INT(unsigned short, 16, false) +CONCAT_OP_MIX_INT(int, 32, true) +CONCAT_OP_MIX_INT(unsigned int, 32, false) +# if defined __x86_64__ +CONCAT_OP_MIX_INT(long, 64, true) +CONCAT_OP_MIX_INT(unsigned long, 64, false) +# else +CONCAT_OP_MIX_INT(long, 32, true) +CONCAT_OP_MIX_INT(unsigned long, 32, false) +# endif +CONCAT_OP_MIX_INT(ap_slong, 64, true) +CONCAT_OP_MIX_INT(ap_ulong, 64, false) +#endif + +#if 1 +#define CONCAT_SHIFT_MIX_INT(C_TYPE, op) \ +template \ +INLINE ap_uint<_AP_W+_AP_W1> operator op (const ap_concat_ref<_AP_W, _AP_T, _AP_W1, _AP_T1> lhs, C_TYPE rhs) { \ + return ((ap_uint<_AP_W+_AP_W1>)lhs.get()) op ((int)rhs); \ +} + +CONCAT_SHIFT_MIX_INT(long, <<) +CONCAT_SHIFT_MIX_INT(unsigned long, <<) +CONCAT_SHIFT_MIX_INT(unsigned int, <<) +CONCAT_SHIFT_MIX_INT(ap_ulong, <<) +CONCAT_SHIFT_MIX_INT(ap_slong, <<) +CONCAT_SHIFT_MIX_INT(long, >>) +CONCAT_SHIFT_MIX_INT(unsigned long, >>) +CONCAT_SHIFT_MIX_INT(unsigned int, >>) +CONCAT_SHIFT_MIX_INT(ap_ulong, >>) +CONCAT_SHIFT_MIX_INT(ap_slong, >>) +#endif + +#if defined(SYSTEMC_H) || defined(SYSTEMC_INCLUDED) +template +INLINE void sc_trace(sc_core::sc_trace_file *tf, const ap_private<_AP_W, _AP_S> &op, + const std::string &name) { + if (tf) + tf->trace(sc_dt::sc_lv<_AP_W>(op.to_string(2).c_str()), name); +} +#endif + +template +INLINE std::ostream& operator<<(std::ostream& out, const ap_private<_AP_W,_AP_S> &op) +{ + ap_private<_AP_W, _AP_S> v=op; + const std::ios_base::fmtflags basefield = out.flags() & std::ios_base::basefield; + unsigned radix = (basefield == std::ios_base::hex) ? 16 : + ((basefield == std::ios_base::oct) ? 8 : 10); + std::string str=v.toString(radix,_AP_S); + out< +INLINE std::istream& operator >> (std::istream& in, ap_private<_AP_W,_AP_S> &op) +{ + std::string str; + in >> str; + op = ap_private<_AP_W, _AP_S>(str.c_str()); + return in; + +} + +template +INLINE std::ostream& operator<<(std::ostream& out, const ap_range_ref<_AP_W,_AP_S> &op) +{ + return operator<<(out, ap_private<_AP_W, _AP_S>(op)); +} + +template +INLINE std::istream& operator >> (std::istream& in, ap_range_ref<_AP_W,_AP_S> &op) +{ + return operator>>(in, ap_private<_AP_W, _AP_S>(op));; +} + +template +INLINE void print(const ap_private<_AP_W,_AP_S> &op, bool fill=true ) +{ + ap_private<_AP_W, _AP_S> v=op; + uint32_t ws=v.getNumWords(); + const uint64_t *ptr=v.getRawData(); + int i=ws-1; +#if 0 + if(fill) + printf("%016llx",*(ptr+i)); + else + printf("%llx",*(ptr+i)); +#else +//match SystemC output + if(_AP_W%64 != 0) { + uint32_t offset=_AP_W%64; + uint32_t count=(offset+3)/4; + int64_t data=*(ptr+i); + if(_AP_S) + data=(data<<(64-offset))>>(64-offset); + else + count=(offset+4)/4; + while(count-->0) + printf("%llx",(data>>(count*4))&0xf); + } else { + if(_AP_S==false) + printf("0"); + printf("%016llx",*(ptr+i)); + } +#endif + for(--i;i>=0;i--) + printf("%016llx",*(ptr+i)); + printf("\n"); + +} +#endif /* #ifndef __AESL_GCC_AP_INT_H__ */ \ No newline at end of file diff --git a/hls_2018/router_01/etc/ap_private.h b/hls_2018/router_01/etc/ap_private.h new file mode 100755 index 0000000..1a68a9e --- /dev/null +++ b/hls_2018/router_01/etc/ap_private.h @@ -0,0 +1,5858 @@ +/* + * Copyright 2012 Xilinx, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LLVM_SUPPORT_MATHEXTRAS_H +#define LLVM_SUPPORT_MATHEXTRAS_H + +#ifdef _MSC_VER +#if _MSC_VER <= 1500 +typedef __int8 int8_t; +typedef unsigned __int8 uint8_t; +typedef __int16 int16_t; +typedef unsigned __int16 uint16_t; +typedef __int32 int32_t; +typedef unsigned __int32 uint32_t; +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; +#else if +#include +#endif /* #if _MSC_VER <= 1500 */ +#else +#include +#endif /* #if _MSC_VER <= 1500 */ +#undef INLINE +#if 1 +#define INLINE inline +#else +//Enable to debug ap_int/ap_fixed +#define INLINE __attribute__((weak)) +#endif +#define AP_MAX(a,b) ((a) > (b) ? (a) : (b)) +#define AP_MIN(a,b) ((a) < (b) ? (a) : (b)) +#define AP_ABS(a) ((a)>=0 ? (a):-(a)) +#ifndef AP_INT_MAX_W +#define AP_INT_MAX_W 1024 +#endif +#define BIT_WIDTH_UPPER_LIMIT (1 << 15) +#if AP_INT_MAX_W > BIT_WIDTH_UPPER_LIMIT +#error "Bitwidth exceeds 32768 (1 << 15), the maximum allowed value" +#endif +#define MAX_MODE(BITS) ((BITS + 1023) / 1024) + +// NOTE: The following support functions use the _32/_64 extensions instead of +// type overloading so that signed and unsigned integers can be used without +// ambiguity. + +/// Hi_32 - This function returns the high 32 bits of a 64 bit value. +INLINE uint32_t Hi_32(uint64_t Value) { + return static_cast(Value >> 32); +} + +/// Lo_32 - This function returns the low 32 bits of a 64 bit value. +INLINE uint32_t Lo_32(uint64_t Value) { + return static_cast(Value); +} + +/// ByteSwap_16 - This function returns a byte-swapped representation of the +/// 16-bit argument, Value. +INLINE uint16_t ByteSwap_16(uint16_t Value) { +#if defined(_MSC_VER) && !defined(_DEBUG) + // The DLL version of the runtime lacks these functions (bug!?), but in a + // release build they're replaced with BSWAP instructions anyway. + return (uint16_t)(_byteswap_ushort(Value)); +#else + uint16_t Hi = (uint16_t)((Value) << 8); + uint16_t Lo = (uint16_t)((Value) >> 8); + return Hi | Lo; +#endif +} + +/// ByteSwap_32 - This function returns a byte-swapped representation of the +/// 32-bit argument, Value. +INLINE uint32_t ByteSwap_32(uint32_t Value) { + uint32_t Byte0 = Value & 0x000000FF; + uint32_t Byte1 = Value & 0x0000FF00; + uint32_t Byte2 = Value & 0x00FF0000; + uint32_t Byte3 = Value & 0xFF000000; + return ((Byte0) << 24) | ((Byte1) << 8) | ((Byte2) >> 8) | ((Byte3) >> 24); +} + +/// ByteSwap_64 - This function returns a byte-swapped representation of the +/// 64-bit argument, Value. +INLINE uint64_t ByteSwap_64(uint64_t Value) { + uint64_t Hi = ByteSwap_32(uint32_t(Value)); + uint32_t Lo = ByteSwap_32(uint32_t(Value >> 32)); + return ((Hi) << 32) | Lo; +} + +/// CountLeadingZeros_32 - this function performs the platform optimal form of +/// counting the number of zeros from the most significant bit to the first one +/// bit. Ex. CountLeadingZeros_32(0x00F000FF) == 8. +/// Returns 32 if the word is zero. +INLINE unsigned CountLeadingZeros_32(uint32_t Value) { + unsigned Count; // result +#if __GNUC__ >= 4 + // PowerPC is defined for __builtin_clz(0) +#if !defined(__ppc__) && !defined(__ppc64__) + if (Value == 0) return 32; +#endif + Count = __builtin_clz(Value); +#else + if (Value == 0) return 32; + Count = 0; + // bisecton method for count leading zeros + for (unsigned Shift = 32 >> 1; Shift; Shift >>= 1) { + uint32_t Tmp = (Value) >> (Shift); + if (Tmp) { + Value = Tmp; + } else { + Count |= Shift; + } + } +#endif + return Count; +} + +/// CountLeadingZeros_64 - This function performs the platform optimal form +/// of counting the number of zeros from the most significant bit to the first +/// one bit (64 bit edition.) +/// Returns 64 if the word is zero. +INLINE unsigned CountLeadingZeros_64(uint64_t Value) { + unsigned Count; // result +#if __GNUC__ >= 4 + // PowerPC is defined for __builtin_clzll(0) +#if !defined(__ppc__) && !defined(__ppc64__) + if (!Value) return 64; +#endif + Count = __builtin_clzll(Value); +#else + if (sizeof(long) == sizeof(int64_t)) { + if (!Value) return 64; + Count = 0; + // bisecton method for count leading zeros + for (unsigned Shift = 64 >> 1; Shift; Shift >>= 1) { + uint64_t Tmp = (Value) >> (Shift); + if (Tmp) { + Value = Tmp; + } else { + Count |= Shift; + } + } + } else { + // get hi portion + uint32_t Hi = Hi_32(Value); + + // if some bits in hi portion + if (Hi) { + // leading zeros in hi portion plus all bits in lo portion + Count = CountLeadingZeros_32(Hi); + } else { + // get lo portion + uint32_t Lo = Lo_32(Value); + // same as 32 bit value + Count = CountLeadingZeros_32(Lo)+32; + } + } +#endif + return Count; +} + +/// CountTrailingZeros_64 - This function performs the platform optimal form +/// of counting the number of zeros from the least significant bit to the first +/// one bit (64 bit edition.) +/// Returns 64 if the word is zero. +INLINE unsigned CountTrailingZeros_64(uint64_t Value) { +#if __GNUC__ >= 4 + return (Value != 0) ? __builtin_ctzll(Value) : 64; +#else + static const unsigned Mod67Position[] = { + 64, 0, 1, 39, 2, 15, 40, 23, 3, 12, 16, 59, 41, 19, 24, 54, + 4, 64, 13, 10, 17, 62, 60, 28, 42, 30, 20, 51, 25, 44, 55, + 47, 5, 32, 65, 38, 14, 22, 11, 58, 18, 53, 63, 9, 61, 27, + 29, 50, 43, 46, 31, 37, 21, 57, 52, 8, 26, 49, 45, 36, 56, + 7, 48, 35, 6, 34, 33, 0 + }; + return Mod67Position[(uint64_t)(-(int64_t)Value & (int64_t)Value) % 67]; +#endif +} + +/// CountPopulation_64 - this function counts the number of set bits in a value, +/// (64 bit edition.) +INLINE unsigned CountPopulation_64(uint64_t Value) { +#if __GNUC__ >= 4 + return __builtin_popcountll(Value); +#else + uint64_t v = Value - (((Value) >> 1) & 0x5555555555555555ULL); + v = (v & 0x3333333333333333ULL) + (((v) >> 2) & 0x3333333333333333ULL); + v = (v + ((v) >> 4)) & 0x0F0F0F0F0F0F0F0FULL; + return unsigned((uint64_t)(v * 0x0101010101010101ULL) >> 56); +#endif +} + +#endif // LLVM_SUPPORT_MATHEXTRAS_H + + +#ifndef AP_PRIVATE_H +#define AP_PRIVATE_H + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace AESL_std { + template + DataType INLINE min(DataType a, DataType b) { + // if (a >= b) return b; + // else return a; + return (a>=b) ? b : a; + } + + template + DataType INLINE max(DataType a, DataType b) { + // if (a >= b) return a; + // else return b; + return (a>=b) ? a : b; + } +} +enum ap_q_mode { + AP_RND, // rounding to plus infinity + AP_RND_ZERO,// rounding to zero + AP_RND_MIN_INF,// rounding to minus infinity + AP_RND_INF,// rounding to infinity + AP_RND_CONV, // convergent rounding + AP_TRN, // truncation + AP_TRN_ZERO // truncation to zero + +}; +enum ap_o_mode { + AP_SAT, // saturation + AP_SAT_ZERO, // saturation to zero + AP_SAT_SYM, // symmetrical saturation + AP_WRAP, // wrap-around (*) + AP_WRAP_SM // sign magnitude wrap-around (*) +}; + +template struct ap_fixed_base; +template struct af_range_ref; +template struct af_bit_ref; + +template struct ap_range_ref; +template struct ap_bit_ref; +template struct ap_concat_ref; +static bool InvalidDigit(const char* str, unsigned len, unsigned start, unsigned radix) { + unsigned i; + for (i = start; i < len; ++i) + if ((radix == 2 && (str[i] == '0' || str[i] == '1')) || + (radix == 8 && str[i] >= '0' && str[i] <= '7') || + (radix == 10 && str[i] >= '0' && str[i] <= '9') || + (radix == 16 && ((str[i] >= '0' && str[i] <= '9') || + (str[i] >= 'a' && str[i] <= 'f') || + (str[i] >= 'A' && str[i] <= 'F')))) + continue; + else + return true; + return false; +} + +static void ap_parse_sign(const char* str, uint32_t &base, bool &neg) { + if (str[0] == '+' || str[0] == '-') base = 1; + if (str[0] == '-') neg = true; + else neg = false; + return; +} + +static void ap_parse_prefix(const char* str, uint32_t &offset, uint32_t &radix) { + if (str[0] == '0') { + switch (str[1]) { + case 'b': + case 'B': offset = 2; radix = 2; break; + case 'x': + case 'X': offset = 2; radix = 16; break; + case 'd': + case 'D': offset = 2; radix = 10; break; + case 'o': + case 'O': offset = 2; radix = 8; break; + default: break; + } + } + if (offset == 0) + for (int i=0, len = strlen(str); i= 'a') || (str[i] <= 'F' && str[i] >= 'A')) { + radix = 16; + break; + } + return; +} + +/// sub_1 - This function subtracts a single "digit" (64-bit word), y, from +/// the multi-digit integer array, x[], propagating the borrowed 1 value until +/// no further borrowing is neeeded or it runs out of "digits" in x. The result +/// is 1 if "borrowing" exhausted the digits in x, or 0 if x was not exhausted. +/// In other words, if y > x then this function returns 1, otherwise 0. +/// @returns the borrow out of the subtraction +static bool sub_1(uint64_t x[], uint32_t len, uint64_t y) { + for (uint32_t i = 0; i < len; ++i) { + uint64_t __X = x[i]; + x[i] -= y; + if (y > __X) + y = 1; // We have to "borrow 1" from next "digit" + else { + y = 0; // No need to borrow + break; // Remaining digits are unchanged so exit early + } + } + return (y != 0); +} + + /// This enumeration just provides for internal constants used in this + /// translation unit. + enum { + MIN_INT_BITS = 1, ///< Minimum number of bits that can be specified + ///< Note that this must remain synchronized with IntegerType::MIN_INT_BITS + MAX_INT_BITS = (1<<23)-1 ///< Maximum number of bits that can be specified + ///< Note that this must remain synchronized with IntegerType::MAX_INT_BITS + }; + + /// A utility function for allocating memory and checking for allocation + /// failure. The content is not zeroed. + static uint64_t* getMemory(uint32_t numWords) { + return (uint64_t*) malloc(numWords*sizeof(uint64_t)); + } + + //===----------------------------------------------------------------------===// + // ap_private Class + //===----------------------------------------------------------------------===// + + /// ap_private - This class represents arbitrary precision constant integral values. + /// It is a functional replacement for common case unsigned integer type like + /// "unsigned", "unsigned long" or "uint64_t", but also allows non-byte-width + /// integer sizes and large integer value types such as 3-bits, 15-bits, or more + /// than 64-bits of precision. ap_private provides a variety of arithmetic operators + /// and methods to manipulate integer values of any bit-width. It supports both + /// the typical integer arithmetic and comparison operations as well as bitwise + /// manipulation. + /// + /// The class has several invariants worth noting: + /// * All bit, byte, and word positions are zero-based. + /// * Once the bit width is set, it doesn't change except by the Truncate, + /// SignExtend, or ZeroExtend operations. + /// * All binary operators must be on ap_private instances of the same bit width. + /// Attempting to use these operators on instances with different bit + /// widths will yield an assertion. + /// * The value is stored canonically as an unsigned value. For operations + /// where it makes a difference, there are both signed and unsigned variants + /// of the operation. For example, sdiv and udiv. However, because the bit + /// widths must be the same, operations such as Mul and Add produce the same + /// results regardless of whether the values are interpreted as signed or + /// not. + /// * In general, the class tries to follow the style of computation that LLVM + /// uses in its IR. This simplifies its use for LLVM. + /// + /// @brief Class for arbitrary precision integers. + template class ap_private; + namespace ap_private_ops{ + template + INLINE ap_private<_AP_W, _AP_S, _AP_N> lshr(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, uint32_t shiftAmt); + template + INLINE ap_private<_AP_W, _AP_S, _AP_N> shl(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, uint32_t shiftAmt); + } + +#if defined(_MSC_VER) +# if _MSC_VER < 1400 && !defined(for) +# define for if(0);else for +# endif + typedef unsigned __int64 ap_ulong; + typedef signed __int64 ap_slong; +#else + typedef unsigned long long ap_ulong; + typedef signed long long ap_slong; +#endif + template struct retval { + }; + template<> struct retval { + typedef ap_slong Type; + }; + template<> struct retval { + typedef ap_ulong Type; + }; + + template + class ap_private { +#ifdef _MSC_VER +#pragma warning( disable : 4521 4522 ) +#endif +public: + typedef typename retval<_AP_S>::Type ValType; + template friend struct ap_fixed_base; + ///return type of variety of operations + //---------------------------------------------------------- + template + struct RType { + enum { + mult_w = _AP_W+_AP_W2, + mult_s = _AP_S||_AP_S2, + plus_w = AP_MAX(_AP_W+(_AP_S2&&!_AP_S),_AP_W2+(_AP_S&&!_AP_S2))+1, + plus_s = _AP_S||_AP_S2, + minus_w = AP_MAX(_AP_W+(_AP_S2&&!_AP_S),_AP_W2+(_AP_S&&!_AP_S2))+1, + minus_s = true, + div_w = _AP_W+_AP_S2, + div_s = _AP_S||_AP_S2, + mod_w = AP_MIN(_AP_W,_AP_W2+(!_AP_S2&&_AP_S)), + mod_s = _AP_S, + logic_w = AP_MAX(_AP_W+(_AP_S2&&!_AP_S),_AP_W2+(_AP_S&&!_AP_S2)), + logic_s = _AP_S||_AP_S2 + }; + typedef ap_private mult; + typedef ap_private plus; + typedef ap_private minus; + typedef ap_private logic; + typedef ap_private div; + typedef ap_private mod; + typedef ap_private<_AP_W, _AP_S> arg1; + typedef bool reduce; + }; + + INLINE void report() { +#if 0 + if (_AP_W > 1024 && _AP_W <= 4096) { + fprintf(stderr, "[W] W=%d is out of bound (1<=W<=1024): for" + " synthesis: please define macro AP_INT_TYPE_EXT(N)" + " to extend the valid range.\n", _AP_W); + } else +#endif + if (_AP_W > MAX_MODE(AP_INT_MAX_W) * 1024) { + fprintf(stderr, "[E] ap_%sint<%d>: Bitwidth exceeds the " + "default max value %d. Please use macro " + "AP_INT_MAX_W to set a larger max value.\n", + _AP_S?"":"u", _AP_W, + MAX_MODE(AP_INT_MAX_W) * 1024); + exit(1); + } + } + + enum { BitWidth = _AP_W }; + /// This union is used to store the integer value. When the + /// integer bit-width <= 64, it uses VAL, otherwise it uses pVal. + + /// This enum is used to hold the constants we needed for ap_private. + uint64_t VAL; ///< Used to store the <= 64 bits integer value. + uint64_t pVal[_AP_N]; ///< Used to store the >64 bits integer value. + + /// This enum is used to hold the constants we needed for ap_private. + enum { + APINT_BITS_PER_WORD = sizeof(uint64_t) * 8, ///< Bits in a word + APINT_WORD_SIZE = sizeof(uint64_t) ///< Byte size of a word + }; + + enum { excess_bits = (_AP_W%APINT_BITS_PER_WORD) ? APINT_BITS_PER_WORD -(_AP_W%APINT_BITS_PER_WORD) : 0}; + static const uint64_t mask = ((uint64_t)~0ULL >> (excess_bits)); + + /// This constructor is used only internally for speed of construction of + /// temporaries. It is unsafe for general use so it is not public. + /* Constructors */ + + ap_private(const char* val) { + std::string str(val); + uint32_t strLen = str.length(); + const char *strp = str.c_str(); + uint32_t offset = 0; + uint32_t base = 0; + bool neg = false; + uint32_t radix = 16; + ap_parse_sign(strp, base, neg); + ap_parse_prefix(strp + base, offset, radix); + + if ((radix != 10 && neg) || + (strLen - base - offset <= 0) || + InvalidDigit(strp, strLen, base + offset, radix)) { + fprintf(stderr, "invalid character string %s !\n", val); + assert(0); + } + + ap_private ap_private_val(str.c_str(), strLen, radix, base, offset); + if (neg) + ap_private_val = -ap_private_val; + operator = (ap_private_val); + report(); + } + + ap_private(const char* val, int rd) { + std::string str(val); + uint32_t strLen = str.length(); + const char *strp = str.c_str(); + uint32_t offset = 0; + uint32_t base = 0; + uint32_t radix = rd; + bool neg = false; + ap_parse_sign(strp, base, neg); + ap_parse_prefix(strp + base, offset, radix); + + if ((radix != 10 && neg) || + (strLen - base - offset <= 0) || + InvalidDigit(strp, strLen, base + offset, radix)) { + fprintf(stderr, "invalid character string %s !\n", val); + assert(0); + } + + // uint32_t bitsNeeded = ap_private<_AP_W, _AP_S>::getBitsNeeded(strp, strLen, radix); + // ap_private<_AP_W, _AP_S> ap_private_val(bitsNeeded, strp , strLen, radix, base, offset); + ap_private ap_private_val(strp , strLen, radix, base, offset); + if (neg) + ap_private_val = -ap_private_val; + operator = (ap_private_val); + report(); + } + + /// Note that numWords can be smaller or larger than the corresponding bit + /// width but any extraneous bits will be dropped. + /// @param numBits the bit width of the constructed ap_private + /// @param numWords the number of words in bigVal + /// @param bigVal a sequence of words to form the initial value of the ap_private + /// @brief Construct an ap_private of numBits width, initialized as bigVal[]. + ap_private(uint32_t numWords, const uint64_t bigVal[]): VAL(0) { + assert(bigVal && "Null pointer detected!"); + { + // Get memory, cleared to 0 + memset(pVal, 0, _AP_N * sizeof(uint64_t)); + + // Calculate the number of words to copy + uint32_t words = AESL_std::min(numWords, _AP_N); + // Copy the words from bigVal to pVal + memcpy(pVal, bigVal, words * APINT_WORD_SIZE); + if (words >= _AP_W) + clearUnusedBits(); + // Make sure unused high bits are cleared + } + } + + /// This constructor interprets Val as a string in the given radix. The + /// interpretation stops when the first charater that is not suitable for the + /// radix is encountered. Acceptable radix values are 2, 8, 10 and 16. It is + /// an error for the value implied by the string to require more bits than + /// numBits. + /// @param numBits the bit width of the constructed ap_private + /// @param val the string to be interpreted + /// @param radix the radix of Val to use for the intepretation + /// @brief Construct an ap_private from a string representation. + ap_private(const std::string& val, uint8_t radix=2, int base=0, int offset=0): VAL(0) { + assert(!val.empty() && "The input string is empty."); + const char *c_str = val.c_str(); + fromString(c_str+base+offset, val.size()-base-offset, radix); + } + + /// This constructor interprets the slen characters starting at StrStart as + /// a string in the given radix. The interpretation stops when the first + /// character that is not suitable for the radix is encountered. Acceptable + /// radix values are 2, 8, 10 and 16. It is an error for the value implied by + /// the string to require more bits than numBits. + /// @param numBits the bit width of the constructed ap_private + /// @param strStart the start of the string to be interpreted + /// @param slen the maximum number of characters to interpret + /// @param radix the radix to use for the conversion + /// @brief Construct an ap_private from a string representation. + /// This method does not consider whether it is negative or not. + ap_private(const char strStart[], uint32_t slen, uint8_t radix, int base=0, int offset=0) : VAL(0) { + fromString(strStart+base+offset, slen-base-offset, radix); + } + + template + INLINE ap_private(const ap_range_ref<_AP_W2,_AP_S2>& ref) { + *this=ref.get(); + report(); + } + + template + INLINE ap_private(const ap_bit_ref<_AP_W2,_AP_S2>& ref) { + *this = ((uint64_t)(bool)ref); + report(); + } + + template + INLINE ap_private(const ap_concat_ref<_AP_W2, _AP_T2,_AP_W3, _AP_T3>& ref) { + *this=ref.get(); + report(); + } + + template + INLINE ap_private(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2> &val) { + *this = ((val.operator ap_private<_AP_W2, false> ())); + report(); + } + + template + INLINE ap_private(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2> &val) { + *this = (uint64_t)(bool)val; + report(); + } + + /// Simply makes *this a copy of that. + /// @brief Copy Constructor. + template + ap_private(const volatile ap_private<_AP_W1, _AP_S1, _AP_N1>& that): VAL(0) { + operator = (const_cast& >(that)); + } + + template + ap_private(const ap_private<_AP_W1, _AP_S1, _AP_N1>& that): VAL(0) { + operator = (that); + } + + template + explicit ap_private(const ap_private<_AP_W1, _AP_S1, 1>& that): VAL(0) { + static const uint64_t that_sign_ext_mask = (_AP_W1==APINT_BITS_PER_WORD)?0:~0ULL>>(_AP_W1%APINT_BITS_PER_WORD)<<(_AP_W1%APINT_BITS_PER_WORD); + if (that.isNegative()) { + pVal[0] = that.VAL|that_sign_ext_mask; + memset(pVal+1, ~0, sizeof(uint64_t)*(_AP_N-1)); + } else { + pVal[0] = that.VAL; + memset(pVal+1, 0, sizeof(uint64_t)*(_AP_N-1)); + } + clearUnusedBits(); + } + + ap_private(const ap_private& that): VAL(0) { + memcpy(pVal, that.pVal, _AP_N * APINT_WORD_SIZE); + clearUnusedBits(); + } + + /// @brief Destructor. + virtual ~ap_private() {} + + /// Default constructor that creates an uninitialized ap_private. This is useful + /// for object deserialization (pair this with the static method Read). + ap_private(){memset(pVal, 0, sizeof(uint64_t)*(_AP_N));} + + ap_private(uint64_t* val, uint32_t bits=_AP_W) {assert(0);} + ap_private(const uint64_t *const val, uint32_t bits) {assert(0);} + + /// @name Constructors + /// @{ + /// If isSigned is true then val is treated as if it were a signed value + /// (i.e. as an int64_t) and the appropriate sign extension to the bit width + /// will be done. Otherwise, no sign extension occurs (high order bits beyond + /// the range of val are zero filled). + /// @param numBits the bit width of the constructed ap_private + /// @param val the initial value of the ap_private + /// @param isSigned how to treat signedness of val + /// @brief Create a new ap_private of numBits width, initialized as val. +#define CTOR(TYPE, SIGNED) \ + ap_private(TYPE val, bool isSigned=SIGNED) { \ + pVal[0] = val; \ + if (isSigned && int64_t(pVal[0]) < 0) { \ + memset(pVal+1, ~0, sizeof(uint64_t)*(_AP_N-1)); \ + } else { \ + memset(pVal+1, 0, sizeof(uint64_t)*(_AP_N-1)); \ + } \ + clearUnusedBits(); \ + } +#if 1 + CTOR(int, true) + CTOR(bool, false) + CTOR(signed char, true) + CTOR(unsigned char, false) + CTOR(short, true) + CTOR(unsigned short, false) + CTOR(unsigned int, false) + CTOR(long, true) + CTOR(unsigned long, false) + CTOR(unsigned long long, false) + CTOR(long long, true) + CTOR(float, false) + CTOR(double, false) +#undef CTOR +#else + CTOR(uint64_t) +#undef CTOR +#endif + + + /// @returns true if the number of bits <= 64, false otherwise. + /// @brief Determine if this ap_private just has one word to store value. + INLINE bool isSingleWord() const { + return false; + } + + /// @returns the word position for the specified bit position. + /// @brief Determine which word a bit is in. + static uint32_t whichWord(uint32_t bitPosition) { + // return bitPosition / APINT_BITS_PER_WORD; + return (bitPosition) >> 6; + } + + /// @returns the bit position in a word for the specified bit position + /// in the ap_private. + /// @brief Determine which bit in a word a bit is in. + static uint32_t whichBit(uint32_t bitPosition) { + // return bitPosition % APINT_BITS_PER_WORD; + return bitPosition & 0x3f; + } + + /// bit at a specific bit position. This is used to mask the bit in the + /// corresponding word. + /// @returns a uint64_t with only bit at "whichBit(bitPosition)" set + /// @brief Get a single bit mask. + static uint64_t maskBit(uint32_t bitPosition) { + return 1ULL << (whichBit(bitPosition)); + } + + /// @returns the corresponding word for the specified bit position. + /// @brief Get the word corresponding to a bit position + INLINE uint64_t getWord(uint32_t bitPosition) const { + return isSingleWord() ? VAL : pVal[whichWord(bitPosition)]; + } + + /// This method is used internally to clear the to "N" bits in the high order + /// word that are not used by the ap_private. This is needed after the most + /// significant word is assigned a value to ensure that those bits are + /// zero'd out. + /// @brief Clear unused high order bits + INLINE void clearUnusedBits(void) { + pVal[_AP_N-1] = _AP_S ? ((((int64_t)pVal[_AP_N-1])<<(excess_bits))>> excess_bits) : (excess_bits ? ((pVal[_AP_N-1])<<(excess_bits))>>(excess_bits) : pVal[_AP_N-1]); + } + + INLINE void clearUnusedBitsToZero(void) { + pVal[_AP_N-1] &= mask; + } + + INLINE void clearUnusedBitsToOne(void) { + pVal[_AP_N-1] |= mask; + } + + /// This is used by the constructors that take string arguments. + /// @brief Convert a char array into an ap_private + INLINE void fromString(const char *strStart, uint32_t slen, + uint8_t radix) ; + + INLINE ap_private read() volatile { + return *this; + } + + INLINE void write(const ap_private& op2) volatile { + *this = (op2); + } + + //Explicit conversions to C interger types + //----------------------------------------------------------- + operator ValType() const { + return getVal(); + } + + INLINE ValType getVal() const{ + return *pVal; + } + + INLINE int to_int() const { + return int(*this); + } + + INLINE unsigned to_uint() const { + return (unsigned) getVal(); + } + + INLINE long to_long() const { + return (long) getVal(); + } + + INLINE unsigned long to_ulong() const { + return (unsigned long) getVal(); + } + + INLINE ap_slong to_int64() const { + return (ap_slong) getVal(); + } + + INLINE ap_ulong to_uint64() const { + return (ap_ulong) getVal(); + } + + INLINE double to_double() const { + if (isNegative()) + return roundToDouble(true); + else + return roundToDouble(false); + } + + INLINE unsigned length() const { return _AP_W; } + + /*Reverse the contents of ap_private instance. I.e. LSB becomes MSB and vise versa*/ + INLINE ap_private& reverse () { + for (int i = 0; i < _AP_W/2; ++i) { + bool tmp = operator[](i); + if (operator[](_AP_W - 1 - i)) + set(i); + else + clear(i); + if (tmp) + set(_AP_W - 1 - i); + else + clear(_AP_W - 1 - i); + } + clearUnusedBits(); + return *this; + } + + /*Return true if the value of ap_private instance is zero*/ + INLINE bool iszero () const { + return isMinValue(); + } + + /* x < 0 */ + INLINE bool sign () const { + if (isNegative()) + return true; + return false; + } + + /* x[i] = !x[i] */ + INLINE void invert (int i) { + assert( i >= 0 && "Attempting to read bit with negative index"); + assert( i < _AP_W && "Attempting to read bit beyond MSB"); + flip(i); + } + + /* x[i] */ + INLINE bool test (int i) const { + assert( i >= 0 && "Attempting to read bit with negative index"); + assert( i < _AP_W && "Attempting to read bit beyond MSB"); + return operator[](i); + } + + //Set the ith bit into v + INLINE void set (int i, bool v) { + assert( i >= 0 && "Attempting to write bit with negative index"); + assert( i < _AP_W && "Attempting to write bit beyond MSB"); + v ? set(i) : clear(i); + } + + //Set the ith bit into v + INLINE void set_bit (int i, bool v) { + assert( i >= 0 && "Attempting to write bit with negative index"); + assert( i < _AP_W && "Attempting to write bit beyond MSB"); + v ? set(i) : clear(i); + } + + INLINE ap_private& set(uint32_t bitPosition) { + pVal[whichWord(bitPosition)] |= maskBit(bitPosition); + clearUnusedBits(); + return *this; + } + + INLINE void set() { + for (uint32_t i = 0; i < _AP_N; ++i) + pVal[i] = ~0ULL; + clearUnusedBits(); + } + + //Get the value of ith bit + INLINE bool get (int i) const { + assert( i >= 0 && "Attempting to read bit with negative index"); + assert( i < _AP_W && "Attempting to read bit beyond MSB"); + return operator [](i); + } + + //Get the value of ith bit + INLINE bool get_bit (int i) const { + assert( i >= 0 && "Attempting to read bit with negative index"); + assert( i < _AP_W && "Attempting to read bit beyond MSB"); + return operator [](i); + } + + //This is used for sc_lv and sc_bv, which is implemented by sc_uint + //Rotate an ap_private object n places to the left + INLINE void lrotate(int n) { + assert( n >= 0 && "Attempting to shift negative index"); + assert( n < _AP_W && "Shift value larger than bit width"); + operator = (shl(n) | lshr(_AP_W - n)); + } + + //This is used for sc_lv and sc_bv, which is implemented by sc_uint + //Rotate an ap_private object n places to the right + INLINE void rrotate(int n) { + assert( n >= 0 && "Attempting to shift negative index"); + assert( n < _AP_W && "Shift value larger than bit width"); + operator = (lshr(n) | shl(_AP_W - n)); + } + + /// Set the given bit to 0 whose position is given as "bitPosition". + /// @brief Set a given bit to 0. + ap_private& clear(uint32_t bitPosition) { + pVal[whichWord(bitPosition)] &= ~maskBit(bitPosition); + clearUnusedBits(); + return *this; + } + + /// @brief Set every bit to 0. + void clear() { + memset(pVal, 0, _AP_N * APINT_WORD_SIZE); + } + + /// @brief Toggle every bit to its opposite value. + ap_private& flip() { + for (uint32_t i = 0; i < _AP_N; ++i) + pVal[i] ^= ~0ULL; + clearUnusedBits(); + return *this; + } + + /// Toggle a given bit to its opposite value whose position is given + /// as "bitPosition". + /// @brief Toggles a given bit to its opposite value. + ap_private& flip(uint32_t bitPosition) { + assert(bitPosition < BitWidth && "Out of the bit-width range!"); + if ((*this)[bitPosition]) clear(bitPosition); + else set(bitPosition); + return *this; + } + + //complements every bit + INLINE void b_not() { + flip(); + } + + ap_private getLoBits(uint32_t numBits) const { + return ap_private_ops::lshr(ap_private_ops::shl(*this, _AP_W - numBits), + _AP_W - numBits); + } + + ap_private getHiBits(uint32_t numBits) const { + return ap_private_ops::lshr(*this, _AP_W - numBits); + } + + //Binary Arithmetic + //----------------------------------------------------------- + + template + INLINE ap_private + operator & (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) { + return *this & a2.get(); + } + + template + INLINE ap_private + operator | (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) { + return *this | a2.get(); + } + + template + INLINE ap_private + operator ^ (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) { + return *this ^ a2.get(); + } + + + ///Arithmetic assign + //------------------------------------------------------------- + +#define OP_BIN_LOGIC_ASSIGN_AP(Sym) \ + template \ + INLINE ap_private& operator Sym(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { \ + uint32_t numWords = AESL_std::min(_AP_N, _AP_N1); \ + uint32_t i; \ + for (i = 0; i < numWords; ++i) \ + pVal[i] Sym RHS.pVal[i]; \ + if (_AP_N1 < _AP_N) { \ + uint64_t ext = RHS.isNegative()?~0ULL:0; \ + for (;i<_AP_N; i++) \ + pVal[i] Sym ext; \ + } \ + clearUnusedBits(); \ + return *this; \ + } + + OP_BIN_LOGIC_ASSIGN_AP(&=); + OP_BIN_LOGIC_ASSIGN_AP(|=); + OP_BIN_LOGIC_ASSIGN_AP(^=); +#undef OP_BIN_LOGIC_ASSIGN_AP + + /// Adds the RHS APint to this ap_private. + /// @returns this, after addition of RHS. + /// @brief Addition assignment operator. + template + INLINE ap_private& operator+=(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { + add(pVal, pVal, RHS.pVal, _AP_N, _AP_N, _AP_N1, _AP_S, _AP_S1); + clearUnusedBits(); + return *this; + } + + template + INLINE ap_private& operator-=(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { + sub(pVal, pVal, RHS.pVal, _AP_N, _AP_N, _AP_N1, _AP_S, _AP_S1); + clearUnusedBits(); + return *this; + } + + template + ap_private& operator*=(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { + // Get some bit facts about LHS and check for zero + uint32_t lhsBits = getActiveBits(); + uint32_t lhsWords = !lhsBits ? 0 : whichWord(lhsBits - 1) + 1; + if (!lhsWords) { + // 0 * X ===> 0 + return *this; + } + + ap_private dupRHS = RHS; + // Get some bit facts about RHS and check for zero + uint32_t rhsBits = dupRHS.getActiveBits(); + uint32_t rhsWords = !rhsBits ? 0 : whichWord(rhsBits - 1) + 1; + if (!rhsWords) { + // X * 0 ===> 0 + clear(); + return *this; + } + + // Allocate space for the result + uint32_t destWords = rhsWords + lhsWords; + uint64_t *dest = getMemory(destWords); + + // Perform the long multiply + mul(dest, pVal, lhsWords, dupRHS.pVal, rhsWords, destWords); + + // Copy result back into *this + clear(); + uint32_t wordsToCopy = destWords >= _AP_N ? _AP_N : destWords; + + memcpy(pVal, dest, wordsToCopy* APINT_WORD_SIZE); + + uint64_t ext = (isNegative() ^ RHS.isNegative()) ? ~0ULL : 0ULL; + for (int i=wordsToCopy; i<_AP_N; i++) + pVal[i]=ext; + clearUnusedBits(); + // delete dest array and return + free(dest); + return *this; + } + +#define OP_ASSIGN_AP(Sym) \ + template \ + INLINE ap_private& operator Sym##=(const ap_private<_AP_W2,_AP_S2>& op) \ + { \ + *this=operator Sym (op); \ + return *this; \ + } \ + + OP_ASSIGN_AP(/) + OP_ASSIGN_AP(%) +#undef OP_ASSIGN_AP + +#define OP_BIN_LOGIC_AP(Sym) \ + template \ + INLINE \ + typename RType<_AP_W1, _AP_S1>::logic \ + operator Sym (const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) const { \ + enum { numWords = (RType<_AP_W1, _AP_S1>::logic_w +APINT_BITS_PER_WORD-1)/APINT_BITS_PER_WORD}; \ + typename RType<_AP_W1, _AP_S1>::logic Result; \ + uint64_t *val = Result.pVal; \ + uint32_t i; \ + uint32_t min_N = std::min(_AP_N, _AP_N1); \ + uint32_t max_N = std::max(_AP_N, _AP_N1); \ + for (i = 0; i < min_N; ++i) \ + val[i] = pVal[i] Sym RHS.pVal[i]; \ + if (numWords > i) { \ + const uint64_t* tmpVal = (_AP_N>_AP_N1 ? pVal : RHS.pVal)+i; \ + uint64_t ext = ((_AP_N<_AP_N1 && isNegative() )||(_AP_N1 < _AP_N && RHS.isNegative())) ? ~0ULL : 0; \ + for (;i i) { \ + uint64_t ext2 = ((_AP_N>_AP_N1 && isNegative() )||(_AP_N1 > _AP_N && RHS.isNegative())) ? ~0ULL : 0; \ + val[i] = ext Sym ext2; \ + } \ + } \ + Result.clearUnusedBits(); \ + return Result; \ + } + + OP_BIN_LOGIC_AP(|); + OP_BIN_LOGIC_AP(&); + OP_BIN_LOGIC_AP(^); + +#undef OP_BIN_LOGIC_AP + + template + INLINE typename RType<_AP_W1,_AP_S1>::plus operator+(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) const { + // assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + typename RType<_AP_W1,_AP_S1>::plus Result; + bool carry = add(Result.pVal, this->pVal, RHS.pVal, (RType<_AP_W1,_AP_S1>::plus_w + 63) / 64, _AP_N, _AP_N1, _AP_S, _AP_S1); + if ((RType<_AP_W1,_AP_S1>::plus_w + 63) / 64> std::max(_AP_W, _AP_W1) ) + Result.pVal[(RType<_AP_W1,_AP_S1>::plus_w + 63)/64 - 1] = carry; + Result.clearUnusedBits(); + return Result; + } + + template + INLINE typename RType<_AP_W1,_AP_S1>::minus operator-(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) const { + typename RType<_AP_W1,_AP_S1>::minus Result; + bool borrow = sub(Result.pVal, this->pVal, RHS.pVal, (RType<_AP_W1,_AP_S1>::minus_w + 63) / 64, _AP_N, _AP_N1, _AP_S, _AP_S1); + if ((RType<_AP_W1,_AP_S1>::minus_w + 63) / 64 > AESL_std::max(_AP_W, _AP_W1) ) { + Result.pVal[(RType<_AP_W1,_AP_S1>::minus_w+63)/64 - 1] = borrow; + } + Result.clearUnusedBits(); + return Result; + } + + template + typename RType<_AP_W1, _AP_S1>::mult operator*(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) const { + + // Get some bit facts about LHS and check for zero + uint32_t lhsBits = getActiveBits(); + uint32_t lhsWords = !lhsBits ? 0 : whichWord(lhsBits - 1) + 1; + if (!lhsWords) + // 0 * X ===> 0 + return typename RType<_AP_W1, _AP_S1>::mult(); + + // Get some bit facts about RHS and check for zero + uint32_t rhsBits = RHS.getActiveBits(); + uint32_t rhsWords = !rhsBits ? 0 : whichWord(rhsBits - 1) + 1; + if (!rhsWords) { + // X * 0 ===> 0 + return typename RType<_AP_W1, _AP_S1>::mult(); + } + + //extend size to avoid result loss + typename RType<_AP_W1, _AP_S1>::mult dupLHS = *this; + typename RType<_AP_W1, _AP_S1>::mult dupRHS = RHS; + lhsBits = dupLHS.getActiveBits(); + lhsWords = !lhsBits ? 0 : whichWord(lhsBits - 1) + 1; + rhsBits = dupRHS.getActiveBits(); + rhsWords = !rhsBits ? 0 : whichWord(rhsBits - 1) + 1; + + // Allocate space for the result + enum { destWords =(RType<_AP_W1, _AP_S1>::mult_w+APINT_BITS_PER_WORD-1)/APINT_BITS_PER_WORD}; + int destw = destWords; + typename RType<_AP_W1, _AP_S1>::mult Result; + uint64_t *dest = Result.pVal; + uint64_t ext = (isNegative() ^ RHS.isNegative()) ? ~0ULL : 0; + + // Perform the long multiply + mul(dest, dupLHS.pVal, lhsWords, dupRHS.pVal, rhsWords, destWords); + + for (int i=lhsWords+rhsWords; i + INLINE typename RType<_AP_W2,_AP_S2>::div + operator / (const ap_private<_AP_W2,_AP_S2>& op) const { + ap_private lhs=ap_private(*this); + ap_private rhs=ap_private(op); + return typename RType<_AP_W2,_AP_S2>::div((_AP_S||_AP_S2)?lhs.sdiv(rhs):lhs.udiv(rhs)); + } + + template + INLINE typename RType<_AP_W2,_AP_S2>::mod + operator % (const ap_private<_AP_W2,_AP_S2>& op) const { + ap_private lhs=*this; + ap_private rhs= op; + typename RType<_AP_W2,_AP_S2>::mod res = typename RType<_AP_W2,_AP_S2>::mod(_AP_S?lhs.srem(rhs):lhs.urem(rhs)); + return res; + } + + template + INLINE ap_private + operator << (const ap_private<_AP_W2, _AP_S2>& op2) const { + uint32_t sh=op2.to_uint(); + return *this << sh; + } + + INLINE ap_private + operator << (uint32_t sh) const { + ap_private r(*this); + bool overflow=(sh>=length()); + if(overflow) + r.clear(); + else + r = ap_private(r.shl(sh)); + return r; + } + + template + INLINE ap_private + operator >> (const ap_private<_AP_W2, _AP_S2>& op2) const { + uint32_t sh = op2.to_uint(); + return *this >> sh; + } + + INLINE ap_private + operator >> (uint32_t sh) const { + ap_private r(*this); + bool overflow=(sh>=_AP_W); + bool neg_v=r.isNegative(); + if(_AP_S) { + if(overflow) + neg_v?r.set():r.clear(); + else + return r.ashr(sh); + } else { + if(overflow) + r.clear(); + else + return r.lshr(sh); + } + return r; + } + + ///Shift assign + //------------------------------------------------------------------ +#define OP_ASSIGN_AP(Sym) \ + template \ + INLINE ap_private& operator Sym##=(int op) \ + { \ + *this = operator Sym (op); \ + return *this; \ + } \ + INLINE ap_private& operator Sym##=(unsigned int op) \ + { \ + *this = operator Sym (op); \ + return *this; \ + } \ + template \ + INLINE ap_private& operator Sym##=(const ap_private<_AP_W2,_AP_S2>& op) \ + { \ + *this = operator Sym (op); \ + return *this; \ + } + OP_ASSIGN_AP(>>) + OP_ASSIGN_AP(<<) +#undef OP_ASSIGN_AP + ///Comparisons + //----------------------------------------------------------------- + bool operator==(const ap_private& RHS) const { + // Get some facts about the number of bits used in the two operands. + uint32_t n1 = getActiveBits(); + uint32_t n2 = RHS.getActiveBits(); + + // If the number of bits isn't the same, they aren't equal + if (n1 != n2) + return false; + + // If the number of bits fits in a word, we only need to compare the low word. + if (n1 <= APINT_BITS_PER_WORD) + return pVal[0] == RHS.pVal[0]; + + // Otherwise, compare everything + for (int i = whichWord(n1 - 1); i >= 0; --i) + if (pVal[i] != RHS.pVal[i]) + return false; + return true; + } + + template + INLINE bool operator == (const ap_private<_AP_W2, _AP_S2>& op) const { + enum { _AP_MAX_W = AP_MAX(_AP_W+(_AP_S||_AP_S2),_AP_W2+(_AP_S||_AP_S2))}; + ap_private<_AP_MAX_W, _AP_S|_AP_S2> lhs(*this); + ap_private<_AP_MAX_W, _AP_S|_AP_S2> rhs(op); + return lhs==rhs; + } + + bool operator==(uint64_t Val) const { + uint32_t n = getActiveBits(); + if (n <= APINT_BITS_PER_WORD) + return pVal[0] == Val; + else + return false; + } + + template + INLINE bool operator != (const ap_private<_AP_W2, _AP_S2>& op) const { + return !(*this==op); + } + + template + INLINE bool operator!=(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return !((*this) == RHS); + } + + INLINE bool operator!=(uint64_t Val) const { + return !((*this) == Val); + } + + + template + INLINE bool operator <= (const ap_private<_AP_W2,_AP_S2>& op) const { + return !(*this>op); + } + + INLINE bool operator <(const ap_private& op) const { + return _AP_S ? slt(op):ult(op); + } + + template + INLINE bool operator < (const ap_private<_AP_W2, _AP_S2>& op) const { + enum { _AP_MAX_W = AP_MAX(_AP_W+(_AP_S||_AP_S2),_AP_W2+(_AP_S||_AP_S2))}; + ap_private<_AP_MAX_W, _AP_S> lhs(*this); + ap_private<_AP_MAX_W, _AP_S2> rhs(op); + if (_AP_S == _AP_S2) + return _AP_S?lhs.slt(rhs):lhs.ult(rhs); + else + if (_AP_S) + if (_AP_W2 >= _AP_W) + return lhs.ult(rhs); + else + return lhs.slt(rhs); + else + if (_AP_W >= _AP_W2) + return lhs.ult(rhs); + else + return lhs.slt(rhs); + } + + template + INLINE bool operator >=(const ap_private<_AP_W2,_AP_S2>& op) const { + return !(*this + INLINE bool operator > (const ap_private<_AP_W2, _AP_S2>& op) const { + enum { _AP_MAX_W = AP_MAX(_AP_W+(_AP_S||_AP_S2),_AP_W2+(_AP_S||_AP_S2))}; + ap_private<_AP_MAX_W, _AP_S> lhs(*this); + ap_private<_AP_MAX_W, _AP_S2> rhs(op); + if (_AP_S == _AP_S2) + return _AP_S?lhs.sgt(rhs):lhs.ugt(rhs); + else + if (_AP_S) + if (_AP_W2 >= _AP_W) + return lhs.ugt(rhs); + else + return lhs.sgt(rhs); + else + if (_AP_W >= _AP_W2) + return lhs.ugt(rhs); + else + return lhs.sgt(rhs); + } + + ///Bit and Part Select + //-------------------------------------------------------------- + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (int Hi, int Lo) { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (int Hi, int Lo) const { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(const_cast*>(this), Hi, Lo); + } + + INLINE ap_range_ref<_AP_W,_AP_S> + range (int Hi, int Lo) const { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>((const_cast*> (this)), Hi, Lo); + } + + INLINE ap_range_ref<_AP_W,_AP_S> + range (int Hi, int Lo) { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + range (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + range (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) const { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(const_cast(this), Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) const { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + return this->range(Hi, Lo); + } + + INLINE ap_bit_ref<_AP_W,_AP_S> operator [] (uint32_t index) { + assert(index >= 0&&"Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S>( *this, index ); + } + + template + INLINE ap_bit_ref<_AP_W,_AP_S> operator [] (const ap_private<_AP_W2,_AP_S2> &index) { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S>( *this, index.to_int() ); + } + + template + INLINE bool operator [] (const ap_private<_AP_W2,_AP_S2>& index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + ap_bit_ref<_AP_W,_AP_S> br =operator [] (index); + return br.to_bool(); + } + + INLINE bool operator [](uint32_t bitPosition) const { + return (maskBit(bitPosition) & (pVal[whichWord(bitPosition)])) != 0; + } + + INLINE ap_bit_ref<_AP_W,_AP_S> bit (int index) { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S>( *this, index ); + } + + template + INLINE ap_bit_ref<_AP_W,_AP_S> bit (const ap_private<_AP_W2,_AP_S2> &index) { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W &&"Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S>( *this, index.to_int() ); + } + + INLINE bool bit (int index) const { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + ap_bit_ref<_AP_W,_AP_S> br(const_cast*>(this), index); + return br.to_bool(); + } + + template + INLINE bool bit (const ap_private<_AP_W2,_AP_S2>& index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + ap_bit_ref<_AP_W,_AP_S> br = bit(index); + return br.to_bool(); + } + + template + INLINE ap_concat_ref<_AP_W,ap_private<_AP_W, _AP_S>,_AP_W2,ap_private<_AP_W2,_AP_S2> > concat(ap_private<_AP_W2,_AP_S2>& a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_private<_AP_W2,_AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W,ap_private<_AP_W, _AP_S>,_AP_W2,ap_private<_AP_W2,_AP_S2> > concat(const ap_private<_AP_W2,_AP_S2>& a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_private<_AP_W2,_AP_S2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (ap_private<_AP_W2, _AP_S2>& a2) { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (ap_private<_AP_W2, _AP_S2>& a2) const { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(const_cast& >(*this), a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (const ap_private<_AP_W2, _AP_S2>& a2) { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(*this, const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (const ap_private<_AP_W2, _AP_S2>& a2) const { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(const_cast& >(*this), const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > + operator, (const ap_range_ref<_AP_W2, _AP_S2> &a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, + ap_range_ref<_AP_W2, _AP_S2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > + operator, (ap_range_ref<_AP_W2, _AP_S2> &a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, + ap_range_ref<_AP_W2, _AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, ap_bit_ref<_AP_W2, _AP_S2> > + operator, (const ap_bit_ref<_AP_W2, _AP_S2> &a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, + ap_bit_ref<_AP_W2, _AP_S2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, ap_bit_ref<_AP_W2, _AP_S2> > + operator, (ap_bit_ref<_AP_W2, _AP_S2> &a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, + ap_bit_ref<_AP_W2, _AP_S2> >(*this, a2); + } + + template + INLINE + ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > + operator, (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE + ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > + operator, (ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) const { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) const { + return ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, a2); + } + + INLINE ap_private<_AP_W,false> get() const { + ap_private<_AP_W,false> ret(*this); + return ret; + } + + template + INLINE void set(const ap_private<_AP_W3, false> & val) { + operator = (ap_private<_AP_W3, _AP_S>(val)); + } + + /// @} + /// @name Value Tests + /// @{ + /// This tests the high bit of this ap_private to determine if it is set. + /// @returns true if this ap_private is negative, false otherwise + /// @brief Determine sign of this ap_private. + INLINE bool isNegative() const { + //just for get rid of warnings + enum {shift = (_AP_W-APINT_BITS_PER_WORD*(_AP_N-1)-1)}; + static const uint64_t mask = 1ULL << (shift); + return _AP_S && (pVal[_AP_N-1]&mask); + } + + /// This tests the high bit of the ap_private to determine if it is unset. + /// @brief Determine if this ap_private Value is positive (not negative). + INLINE bool isPositive() const { + return !isNegative(); + } + + /// This tests if the value of this ap_private is strictly positive (> 0). + /// @returns true if this ap_private is Positive and not zero. + /// @brief Determine if this ap_private Value is strictly positive. + INLINE bool isStrictlyPositive() const { + return isPositive() && (*this) != 0; + } + + /// This checks to see if the value has all bits of the ap_private are set or not. + /// @brief Determine if all bits are set + INLINE bool isAllOnesValue() const { + return countPopulation() == _AP_W; + } + + /// This checks to see if the value of this ap_private is the maximum unsigned + /// value for the ap_private's bit width. + /// @brief Determine if this is the largest unsigned value. + INLINE bool isMaxValue() const { + return countPopulation() == _AP_W; + } + + /// This checks to see if the value of this ap_private is the maximum signed + /// value for the ap_private's bit width. + /// @brief Determine if this is the largest signed value. + INLINE bool isMaxSignedValue() const { + return BitWidth == 1 ? VAL == 0 : + !isNegative() && countPopulation() == _AP_W - 1; + } + + /// This checks to see if the value of this ap_private is the minimum unsigned + /// value for the ap_private's bit width. + /// @brief Determine if this is the smallest unsigned value. + INLINE bool isMinValue() const { + return countPopulation() == 0; + } + + /// This checks to see if the value of this ap_private is the minimum signed + /// value for the ap_private's bit width. + /// @brief Determine if this is the smallest signed value. + INLINE bool isMinSignedValue() const { + return BitWidth == 1 ? VAL == 1 : + isNegative() && countPopulation() == 1; + } + + /// This function returns a pointer to the internal storage of the ap_private. + /// This is useful for writing out the ap_private in binary form without any + /// conversions. + INLINE const uint64_t* getRawData() const { + if (isSingleWord()) + return &VAL; + return &pVal[0]; + } + + ap_private sqrt() const; + + /// @} + /// @Assignment Operators + /// @{ + /// @returns *this after assignment of RHS. + /// @brief Copy assignment operator. + INLINE ap_private& operator=(const ap_private& RHS) { + if (this != &RHS) + memcpy(pVal, RHS.pVal, _AP_N * APINT_WORD_SIZE); + return *this; + } + INLINE ap_private& operator=(const volatile ap_private& RHS) { + if (this != &RHS) + for (int i=0; i<_AP_N; ++i) + pVal[i] = RHS.pVal[i]; + return *this; + } + INLINE volatile ap_private& operator=(const ap_private& RHS) volatile { + if (this != &RHS) + for (int i=0; i<_AP_N; ++i) + pVal[i] = RHS.pVal[i]; + return *this; + } + INLINE volatile ap_private& operator=(const volatile ap_private& RHS) volatile { + if (this != &RHS) + for (int i=0; i<_AP_N; ++i) + pVal[i] = RHS.pVal[i]; + return *this; + } + + template + INLINE ap_private& operator=(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { + if (_AP_S1) + cpSextOrTrunc(RHS); + else + cpZextOrTrunc(RHS); + clearUnusedBits(); + return *this; + } + + template + INLINE ap_private& operator=(const volatile ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { + if (_AP_S1) + cpSextOrTrunc(RHS); + else + cpZextOrTrunc(RHS); + clearUnusedBits(); + return *this; + } + + template + INLINE ap_private& operator=(const ap_private<_AP_W1, _AP_S1, 1>& RHS) { + static const uint64_t that_sign_ext_mask = (_AP_W1==APINT_BITS_PER_WORD)?0:~0ULL>>(_AP_W1%APINT_BITS_PER_WORD)<<(_AP_W1%APINT_BITS_PER_WORD); + if (RHS.isNegative()) { + pVal[0] = RHS.VAL | that_sign_ext_mask; + memset(pVal+1,~0, APINT_WORD_SIZE*(_AP_N-1)); + } else { + pVal[0] = RHS.VAL; + memset(pVal+1, 0, APINT_WORD_SIZE*(_AP_N-1)); + } + clearUnusedBits(); + return *this; + } + + template + INLINE ap_private& operator=(const volatile ap_private<_AP_W1, _AP_S1, 1>& RHS) { + static const uint64_t that_sign_ext_mask = (_AP_W1==APINT_BITS_PER_WORD)?0:~0ULL>>(_AP_W1%APINT_BITS_PER_WORD)<<(_AP_W1%APINT_BITS_PER_WORD); + if (RHS.isNegative()) { + pVal[0] = RHS.VAL | that_sign_ext_mask; + memset(pVal+1,~0, APINT_WORD_SIZE*(_AP_N-1)); + } else { + pVal[0] = RHS.VAL; + memset(pVal+1, 0, APINT_WORD_SIZE*(_AP_N-1)); + } + clearUnusedBits(); + return *this; + } + + /// @} + /// @name Unary Operators + /// @{ + /// @returns a new ap_private value representing *this incremented by one + /// @brief Postfix increment operator. + INLINE const ap_private operator++(int) { + ap_private API(*this); + ++(*this); + return API; + } + + /// @returns *this incremented by one + /// @brief Prefix increment operator. + INLINE ap_private& operator++() { + add_1(pVal, pVal, _AP_N, 1); + clearUnusedBits(); + return *this; + } + + /// @returns a new ap_private representing *this decremented by one. + /// @brief Postfix decrement operator. + INLINE const ap_private operator--(int) { + ap_private API(*this); + --(*this); + return API; + } + + /// @returns *this decremented by one. + /// @brief Prefix decrement operator. + INLINE ap_private& operator--() { + sub_1(pVal, _AP_N, 1); + clearUnusedBits(); + return *this; + } + + /// Performs a bitwise complement operation on this ap_private. + /// @returns an ap_private that is the bitwise complement of *this + /// @brief Unary bitwise complement operator. + INLINE ap_private operator~() const { + ap_private Result(*this); + Result.flip(); + return Result; + } + + /// Negates *this using two's complement logic. + /// @returns An ap_private value representing the negation of *this. + /// @brief Unary negation operator + INLINE typename RType<1,false>::minus operator-() const { + return ap_private<1,false>(0) - (*this); + } + + /// Performs logical negation operation on this ap_private. + /// @returns true if *this is zero, false otherwise. + /// @brief Logical negation operator. + INLINE bool operator !() const { + for (uint32_t i = 0; i < _AP_N; ++i) + if (pVal[i]) + return false; + return true; + } + + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> And(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return this->operator&(RHS); + } + template + INLINE ap_private Or(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return this->operator|(RHS); + } + template + ap_private Xor(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return this->operator^(RHS); + } + + ap_private Mul(const ap_private& RHS) const { + ap_private Result(*this); + Result *= RHS; + return Result; + } + + ap_private Add(const ap_private& RHS) const { + ap_private Result(0); + bool carry = add(Result.pVal, this->pVal, RHS.pVal, _AP_N, _AP_N, _AP_N, _AP_S, _AP_S); + Result.clearUnusedBits(); + return Result; + } + + ap_private Sub(const ap_private& RHS) const { + ap_private Result(0); + sub(Result.pVal, this->pVal, RHS.pVal, _AP_N, _AP_N, _AP_N, _AP_S, _AP_S); + Result.clearUnusedBits(); + return Result; + } + + /// Arithmetic right-shift this ap_private by shiftAmt. + /// @brief Arithmetic right-shift function. + ap_private ashr(uint32_t shiftAmt) const { + assert(shiftAmt <= BitWidth && "Invalid shift amount, too big"); + // Handle a degenerate case + if (shiftAmt == 0) + return *this; + + // Handle single word shifts with built-in ashr + if (isSingleWord()) { + if (shiftAmt == BitWidth) + return ap_private(/*BitWidth, 0*/); // undefined + else { + uint32_t SignBit = APINT_BITS_PER_WORD - BitWidth; + return ap_private(/*BitWidth,*/ + (((int64_t(VAL) << (SignBit)) >> (SignBit)) >> (shiftAmt))); + } + } + + // If all the bits were shifted out, the result is, technically, undefined. + // We return -1 if it was negative, 0 otherwise. We check this early to avoid + // issues in the algorithm below. + if (shiftAmt == BitWidth) { + if (isNegative()) + return ap_private(-1); + else + return ap_private(0); + } + + // Create some space for the result. + ap_private Retval(0); + uint64_t * val = Retval.pVal; + + // Compute some values needed by the following shift algorithms + uint32_t wordShift = shiftAmt % APINT_BITS_PER_WORD; // bits to shift per word + uint32_t offset = shiftAmt / APINT_BITS_PER_WORD; // word offset for shift + uint32_t breakWord = _AP_N - 1 - offset; // last word affected + uint32_t bitsInWord = whichBit(BitWidth); // how many bits in last word? + if (bitsInWord == 0) + bitsInWord = APINT_BITS_PER_WORD; + + // If we are shifting whole words, just move whole words + if (wordShift == 0) { + // Move the words containing significant bits + for (uint32_t i = 0; i <= breakWord; ++i) + val[i] = pVal[i+offset]; // move whole word + + // Adjust the top significant word for sign bit fill, if negative + if (isNegative()) + if (bitsInWord < APINT_BITS_PER_WORD) + val[breakWord] |= ~0ULL << (bitsInWord); // set high bits + } else { + // Shift the low order words + for (uint32_t i = 0; i < breakWord; ++i) { + // This combines the shifted corresponding word with the low bits from + // the next word (shifted into this word's high bits). + val[i] = ((pVal[i+offset]) >> (wordShift)); + val[i] |= ((pVal[i+offset+1]) << (APINT_BITS_PER_WORD - wordShift)); + } + + // Shift the break word. In this case there are no bits from the next word + // to include in this word. + val[breakWord] = (pVal[breakWord+offset]) >> (wordShift); + + // Deal with sign extenstion in the break word, and possibly the word before + // it. + if (isNegative()) { + if (wordShift > bitsInWord) { + if (breakWord > 0) + val[breakWord-1] |= + ~0ULL << (APINT_BITS_PER_WORD - (wordShift - bitsInWord)); + val[breakWord] |= ~0ULL; + } else + val[breakWord] |= (~0ULL << (bitsInWord - wordShift)); + } + } + + // Remaining words are 0 or -1, just assign them. + uint64_t fillValue = (isNegative() ? ~0ULL : 0); + for (uint32_t i = breakWord+1; i < _AP_N; ++i) + val[i] = fillValue; + Retval.clearUnusedBits(); + return Retval; + } + + /// Logical right-shift this ap_private by shiftAmt. + /// @brief Logical right-shift function. + ap_private lshr(uint32_t shiftAmt) const { + if (isSingleWord()) { + if (shiftAmt == BitWidth) + return ap_private(0); + else + return ap_private((this->VAL) >> (shiftAmt)); + } + + // If all the bits were shifted out, the result is 0. This avoids issues + // with shifting by the size of the integer type, which produces undefined + // results. We define these "undefined results" to always be 0. + if (shiftAmt == BitWidth) + return ap_private(0); + + // If none of the bits are shifted out, the result is *this. This avoids + // issues with shifting byt he size of the integer type, which produces + // undefined results in the code below. This is also an optimization. + if (shiftAmt == 0) + return *this; + + // Create some space for the result. + ap_private Retval(0); + uint64_t * val = Retval.pVal; + + // If we are shifting less than a word, compute the shift with a simple carry + if (shiftAmt < APINT_BITS_PER_WORD) { + uint64_t carry = 0; + for (int i = _AP_N-1; i >= 0; --i) { + val[i] = ((pVal[i]) >> (shiftAmt)) | carry; + carry = (pVal[i]) << (APINT_BITS_PER_WORD - shiftAmt); + } + Retval.clearUnusedBits(); + return Retval; + } + + // Compute some values needed by the remaining shift algorithms + uint32_t wordShift = shiftAmt % APINT_BITS_PER_WORD; + uint32_t offset = shiftAmt / APINT_BITS_PER_WORD; + + // If we are shifting whole words, just move whole words + if (wordShift == 0) { + for (uint32_t i = 0; i < _AP_N - offset; ++i) + val[i] = pVal[i+offset]; + for (uint32_t i = _AP_N-offset; i < _AP_N; i++) + val[i] = 0; + Retval.clearUnusedBits(); + return Retval; + } + + // Shift the low order words + uint32_t breakWord = _AP_N - offset -1; + for (uint32_t i = 0; i < breakWord; ++i) + val[i] = ((pVal[i+offset]) >> (wordShift)) | + ((pVal[i+offset+1]) << (APINT_BITS_PER_WORD - wordShift)); + // Shift the break word. + val[breakWord] = (pVal[breakWord+offset]) >> (wordShift); + + // Remaining words are 0 + for (uint32_t i = breakWord+1; i < _AP_N; ++i) + val[i] = 0; + Retval.clearUnusedBits(); + return Retval; + } + + /// Left-shift this ap_private by shiftAmt. + /// @brief Left-shift function. + ap_private shl(uint32_t shiftAmt) const { + assert(shiftAmt <= BitWidth && "Invalid shift amount, too big"); + if (isSingleWord()) { + if (shiftAmt == BitWidth) + return ap_private(0); // avoid undefined shift results + return ap_private((VAL) << (shiftAmt)); + } + + // If all the bits were shifted out, the result is 0. This avoids issues + // with shifting by the size of the integer type, which produces undefined + // results. We define these "undefined results" to always be 0. + if (shiftAmt == BitWidth) + return ap_private(0); + + // If none of the bits are shifted out, the result is *this. This avoids a + // lshr by the words size in the loop below which can produce incorrect + // results. It also avoids the expensive computation below for a common case. + if (shiftAmt == 0) + return *this; + + // Create some space for the result. + ap_private Retval(0); + uint64_t* val = Retval.pVal; + // If we are shifting less than a word, do it the easy way + if (shiftAmt < APINT_BITS_PER_WORD) { + uint64_t carry = 0; + for (uint32_t i = 0; i < _AP_N; i++) { + val[i] = ((pVal[i]) << (shiftAmt)) | carry; + carry = (pVal[i]) >> (APINT_BITS_PER_WORD - shiftAmt); + } + Retval.clearUnusedBits(); + return Retval; + } + + // Compute some values needed by the remaining shift algorithms + uint32_t wordShift = shiftAmt % APINT_BITS_PER_WORD; + uint32_t offset = shiftAmt / APINT_BITS_PER_WORD; + + // If we are shifting whole words, just move whole words + if (wordShift == 0) { + for (uint32_t i = 0; i < offset; i++) + val[i] = 0; + for (uint32_t i = offset; i < _AP_N; i++) + val[i] = pVal[i-offset]; + Retval.clearUnusedBits(); + return Retval; + } + + // Copy whole words from this to Result. + uint32_t i = _AP_N - 1; + for (; i > offset; --i) + val[i] = (pVal[i-offset]) << (wordShift) | + (pVal[i-offset-1]) >> (APINT_BITS_PER_WORD - wordShift); + val[offset] = (pVal[0]) << (wordShift); + for (i = 0; i < offset; ++i) + val[i] = 0; + Retval.clearUnusedBits(); + return Retval; + } + + INLINE ap_private rotl(uint32_t rotateAmt) const { + if (rotateAmt == 0) + return *this; + // Don't get too fancy, just use existing shift/or facilities + ap_private hi(*this); + ap_private lo(*this); + hi.shl(rotateAmt); + lo.lshr(BitWidth - rotateAmt); + return hi | lo; + } + + INLINE ap_private rotr(uint32_t rotateAmt) const { + if (rotateAmt == 0) + return *this; + // Don't get too fancy, just use existing shift/or facilities + ap_private hi(*this); + ap_private lo(*this); + lo.lshr(rotateAmt); + hi.shl(BitWidth - rotateAmt); + return hi | lo; + } + + /// Perform an unsigned divide operation on this ap_private by RHS. Both this and + /// RHS are treated as unsigned quantities for purposes of this division. + /// @returns a new ap_private value containing the division result + /// @brief Unsigned division operation. + ap_private udiv(const ap_private& RHS) const { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + + // First, deal with the easy case + if (isSingleWord()) { + assert(RHS.VAL != 0 && "Divide by zero?"); + return ap_private(VAL / RHS.VAL); + } + + // Get some facts about the LHS and RHS number of bits and words + uint32_t rhsBits = RHS.getActiveBits(); + uint32_t rhsWords = !rhsBits ? 0 : (whichWord(rhsBits - 1) + 1); + assert(rhsWords && "Divided by zero???"); + uint32_t lhsBits = this->getActiveBits(); + uint32_t lhsWords = !lhsBits ? 0 : (whichWord(lhsBits - 1) + 1); + + // Deal with some degenerate cases + if (!lhsWords) + // 0 / X ===> 0 + return ap_private(0); + else if (lhsWords < rhsWords || this->ult(RHS)) { + // X / Y ===> 0, iff X < Y + return ap_private(0); + } else if (*this == RHS) { + // X / X ===> 1 + return ap_private(1); + } else if (lhsWords == 1 && rhsWords == 1) { + // All high words are zero, just use native divide + return ap_private(this->pVal[0] / RHS.pVal[0]); + } + + // We have to compute it the hard way. Invoke the Knuth divide algorithm. + ap_private Quotient(0); // to hold result. + divide(*this, lhsWords, RHS, rhsWords, &Quotient, (ap_private*)0); + return Quotient; + } + + /// Signed divide this ap_private by ap_private RHS. + /// @brief Signed division function for ap_private. + INLINE ap_private sdiv(const ap_private& RHS) const { + if (isNegative()) + if (RHS.isNegative()) + return (-(*this)).udiv(-RHS); + else + return -((-(*this)).udiv(RHS)); + else if (RHS.isNegative()) + return -(this->udiv(-RHS)); + return this->udiv(RHS); + } + + /// Perform an unsigned remainder operation on this ap_private with RHS being the + /// divisor. Both this and RHS are treated as unsigned quantities for purposes + /// of this operation. Note that this is a true remainder operation and not + /// a modulo operation because the sign follows the sign of the dividend + /// which is *this. + /// @returns a new ap_private value containing the remainder result + /// @brief Unsigned remainder operation. + ap_private urem(const ap_private& RHS) const { + if (isSingleWord()) { + assert(RHS.VAL != 0 && "Remainder by zero?"); + return ap_private(VAL % RHS.VAL); + } + + // Get some facts about the LHS + uint32_t lhsBits = getActiveBits(); + uint32_t lhsWords = !lhsBits ? 0 : (whichWord(lhsBits - 1) + 1); + + // Get some facts about the RHS + uint32_t rhsBits = RHS.getActiveBits(); + uint32_t rhsWords = !rhsBits ? 0 : (whichWord(rhsBits - 1) + 1); + assert(rhsWords && "Performing remainder operation by zero ???"); + + // Check the degenerate cases + if (lhsWords == 0) { + // 0 % Y ===> 0 + return ap_private(0); + } else if (lhsWords < rhsWords || this->ult(RHS)) { + // X % Y ===> X, iff X < Y + return *this; + } else if (*this == RHS) { + // X % X == 0; + return ap_private(0); + } else if (lhsWords == 1) { + // All high words are zero, just use native remainder + return ap_private(pVal[0] % RHS.pVal[0]); + } + + // We have to compute it the hard way. Invoke the Knuth divide algorithm. + ap_private Remainder(0); + divide(*this, lhsWords, RHS, rhsWords, (ap_private*)(0), &Remainder); + return Remainder; + } + + ap_private urem(uint64_t RHS) const { + // Get some facts about the LHS + uint32_t lhsBits = getActiveBits(); + uint32_t lhsWords = !lhsBits ? 0 : (whichWord(lhsBits - 1) + 1); + // Get some facts about the RHS + uint32_t rhsBits = 64 - CountLeadingZeros_64(RHS); // RHS.getActiveBits(); + uint32_t rhsWords = 1;//!rhsBits ? 0 : (ap_private<_AP_W, _AP_S, _AP_N>::whichWord(rhsBits - 1) + 1); + assert(rhsWords && "Performing remainder operation by zero ???"); + // Check the degenerate cases + if (lhsWords == 0) { + // 0 % Y ===> 0 + return ap_private(0); + } else if (lhsWords < rhsWords || this->ult(RHS)) { + // X % Y ===> X, iff X < Y + return *this; + } else if (*this == RHS) { + // X % X == 0; + return ap_private(0); + } else if (lhsWords == 1) { + // All high words are zero, just use native remainder + return ap_private(pVal[0] % RHS); + } + + // We have to compute it the hard way. Invoke the Knuth divide algorithm. + ap_private Remainder(0); + divide(*this, lhsWords, RHS, (ap_private*)(0), &Remainder); + return Remainder; + } + + /// Signed remainder operation on ap_private. + /// @brief Function for signed remainder operation. + INLINE ap_private srem(const ap_private& RHS) const { + if (isNegative()) { + ap_private lhs = -(*this); + if (RHS.isNegative()) { + ap_private rhs = -RHS; + return -(lhs.urem(rhs)); + } else + return -(lhs.urem(RHS)); + } else if (RHS.isNegative()) { + ap_private rhs = -RHS; + return this->urem(rhs); + } + return this->urem(RHS); + } + + /// Signed remainder operation on ap_private. + /// @brief Function for signed remainder operation. + INLINE ap_private srem(int64_t RHS) const { + if (isNegative()) + if (RHS<0) + return -((-(*this)).urem(-RHS)); + else + return -((-(*this)).urem(RHS)); + else if (RHS<0) + return this->urem(-RHS); + return this->urem(RHS); + } + + /// Sometimes it is convenient to divide two ap_private values and obtain both + /// the quotient and remainder. This function does both operations in the + /// same computation making it a little more efficient. + /// @brief Dual division/remainder interface. + static void udivrem(const ap_private& LHS, const ap_private& RHS, ap_private &Quotient, ap_private& Remainder) { + // Get some size facts about the dividend and divisor + uint32_t lhsBits = LHS.getActiveBits(); + uint32_t lhsWords = !lhsBits ? 0 : (ap_private::whichWord(lhsBits - 1) + 1); + uint32_t rhsBits = RHS.getActiveBits(); + uint32_t rhsWords = !rhsBits ? 0 : (ap_private::whichWord(rhsBits - 1) + 1); + + // Check the degenerate cases + if (lhsWords == 0) { + Quotient = 0; // 0 / Y ===> 0 + Remainder = 0; // 0 % Y ===> 0 + return; + } + + if (lhsWords < rhsWords || LHS.ult(RHS)) { + Quotient = 0; // X / Y ===> 0, iff X < Y + Remainder = LHS; // X % Y ===> X, iff X < Y + return; + } + + if (LHS == RHS) { + Quotient = 1; // X / X ===> 1 + Remainder = 0; // X % X ===> 0; + return; + } + + if (lhsWords == 1 && rhsWords == 1) { + // There is only one word to consider so use the native versions. + if (LHS.isSingleWord()) { + Quotient = ap_private(LHS.VAL / RHS.VAL); + Remainder = ap_private(LHS.VAL % RHS.VAL); + } else { + Quotient = ap_private(LHS.pVal[0] / RHS.pVal[0]); + Remainder = ap_private(LHS.pVal[0] % RHS.pVal[0]); + } + return; + } + + // Okay, lets do it the long way + divide(LHS, lhsWords, RHS, rhsWords, &Quotient, &Remainder); + } + + static void sdivrem(const ap_private &LHS, const ap_private &RHS, + ap_private &Quotient, ap_private &Remainder) { + if (LHS.isNegative()) { + if (RHS.isNegative()) + ap_private::udivrem(-LHS, -RHS, Quotient, Remainder); + else + ap_private::udivrem(-LHS, RHS, Quotient, Remainder); + Quotient = -Quotient; + Remainder = -Remainder; + } else if (RHS.isNegative()) { + ap_private::udivrem(LHS, -RHS, Quotient, Remainder); + Quotient = -Quotient; + } else { + ap_private::udivrem(LHS, RHS, Quotient, Remainder); + } + } + + /// Compares this ap_private with RHS for the validity of the equality + /// relationship. + /// @returns true if *this == Val + /// @brief Equality comparison. + template + INLINE bool eq(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return (*this) == RHS; + } + + /// Compares this ap_private with RHS for the validity of the inequality + /// relationship. + /// @returns true if *this != Val + /// @brief Inequality comparison + template + INLINE bool ne(const ap_private<_AP_W, _AP_S1, _AP_N> &RHS) const { + return !((*this) == RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// the validity of the less-than relationship. + /// @returns true if *this < RHS when both are considered unsigned. + /// @brief Unsigned less than comparison + template + INLINE bool ult(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + // Get active bit length of both operands + uint32_t n1 = getActiveBits(); + uint32_t n2 = RHS.getActiveBits(); + + // If magnitude of LHS is less than RHS, return true. + if (n1 < n2) + return true; + + // If magnitude of RHS is greather than LHS, return false. + if (n2 < n1) + return false; + + // If they bot fit in a word, just compare the low order word + if (n1 <= APINT_BITS_PER_WORD && n2 <= APINT_BITS_PER_WORD) + return pVal[0] < RHS.pVal[0]; + + // Otherwise, compare all words + uint32_t topWord = whichWord(AESL_std::max(n1,n2)-1); + for (int i = topWord; i >= 0; --i) { + if (pVal[i] > RHS.pVal[i]) + return false; + if (pVal[i] < RHS.pVal[i]) + return true; + } + return false; + } + + INLINE bool ult(uint64_t RHS) const { + // Get active bit length of both operands + uint32_t n1 = getActiveBits(); + uint32_t n2 = 64 - CountLeadingZeros_64(RHS); //RHS.getActiveBits(); + + // If magnitude of LHS is less than RHS, return true. + if (n1 < n2) + return true; + + // If magnitude of RHS is greather than LHS, return false. + if (n2 < n1) + return false; + + // If they bot fit in a word, just compare the low order word + if (n1 <= APINT_BITS_PER_WORD && n2 <= APINT_BITS_PER_WORD) + return pVal[0] < RHS; + assert(0); + } + + template + INLINE bool slt(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + ap_private lhs(*this); + ap_private<_AP_W, _AP_S1, _AP_N> rhs(RHS); + bool lhsNeg = isNegative(); + bool rhsNeg = rhs.isNegative(); + if (lhsNeg) { + // Sign bit is set so perform two's complement to make it positive + lhs.flip(); + lhs++; + } + if (rhsNeg) { + // Sign bit is set so perform two's complement to make it positive + rhs.flip(); + rhs++; + } + + // Now we have unsigned values to compare so do the comparison if necessary + // based on the negativeness of the values. + if (lhsNeg) + if (rhsNeg) + return lhs.ugt(rhs); + else + return true; + else if (rhsNeg) + return false; + else + return lhs.ult(rhs); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// validity of the less-or-equal relationship. + /// @returns true if *this <= RHS when both are considered unsigned. + /// @brief Unsigned less or equal comparison + template + INLINE bool ule(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return ult(RHS) || eq(RHS); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the less-or-equal relationship. + /// @returns true if *this <= RHS when both are considered signed. + /// @brief Signed less or equal comparison + template + INLINE bool sle(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return slt(RHS) || eq(RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// the validity of the greater-than relationship. + /// @returns true if *this > RHS when both are considered unsigned. + /// @brief Unsigned greather than comparison + template + INLINE bool ugt(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return !ult(RHS) && !eq(RHS); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// the validity of the greater-than relationship. + /// @returns true if *this > RHS when both are considered signed. + /// @brief Signed greather than comparison + template + INLINE bool sgt(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return !slt(RHS) && !eq(RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// validity of the greater-or-equal relationship. + /// @returns true if *this >= RHS when both are considered unsigned. + /// @brief Unsigned greater or equal comparison + template + INLINE bool uge(const ap_private<_AP_W, _AP_S, _AP_N>& RHS) const { + return !ult(RHS); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the greater-or-equal relationship. + /// @returns true if *this >= RHS when both are considered signed. + /// @brief Signed greather or equal comparison + template + INLINE bool sge(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return !slt(RHS); + } + + template + void cpTrunc(const ap_private<_AP_W1, _AP_S1, _AP_N1>& that) { + assert(_AP_W1 > BitWidth && "Invalid ap_private Truncate request"); + assert(_AP_W1 >= MIN_INT_BITS && "Can't truncate to 0 bits"); + memcpy(pVal, that.pVal, _AP_N*APINT_WORD_SIZE); + } + + // Sign extend to a new width. + template + void cpSext(const ap_private<_AP_W1, _AP_S1, _AP_N1>& that) { + assert(_AP_W1 < BitWidth && "Invalid ap_private SignExtend request"); + assert(_AP_W1 <= MAX_INT_BITS && "Too many bits"); + // If the sign bit isn't set, this is the same as zext. + if (!that.isNegative()) { + cpZext(that); + return; + } + + // The sign bit is set. First, get some facts + enum { wordBits = _AP_W1 % APINT_BITS_PER_WORD}; + + // Mask the high order word appropriately + if (_AP_N1 == _AP_N) { + enum { newWordBits = _AP_W % APINT_BITS_PER_WORD}; + // The extension is contained to the wordsBefore-1th word. + static const uint64_t mask = wordBits?(~0ULL<<(wordBits)):0ULL; + if (_AP_N1 == 1) { + assert(0); + } else { + for (uint32_t i = 0; i < _AP_N1; ++i) + pVal[i] = that.pVal[i]; + pVal[_AP_N1-1] |= mask; + return; + } + } + + if (_AP_N1 == 1) { + assert(0);// newVal[0] = VAL | mask; + } else { + enum { newWordBits = _AP_W % APINT_BITS_PER_WORD}; + // The extension is contained to the wordsBefore-1th word. + static const uint64_t mask = wordBits?(~0ULL<<(wordBits)):0ULL; + for (uint32_t i = 0; i < _AP_N1; ++i) + pVal[i] = that.pVal[i]; + pVal[_AP_N1-1] |= mask; + } + for (uint32_t i=_AP_N1; i < _AP_N-1; i++) + pVal[i] = ~0ULL; + pVal[_AP_N-1] = ~0ULL; + clearUnusedBits(); + return; + } + + // Zero extend to a new width. + template + void cpZext(const ap_private<_AP_W1, _AP_S1, _AP_N1>& that) { + assert(_AP_W1 < BitWidth && "Invalid ap_private ZeroExtend request"); + assert(_AP_W1 <= MAX_INT_BITS && "Too many bits"); + uint32_t wordsAfter = _AP_N; + if (wordsAfter==1) { + assert(0); // return ap_private<_AP_W1, _AP_S, _AP_N1> (_AP_W1, VAL, _AP_S); + } else { + if (_AP_N1 == 1) { + assert(0); + // newVal[0] = VAL; + } else { + uint32_t i = 0; + for (; i < _AP_N1; ++i) + pVal[i] = that.pVal[i]; + for (; i < _AP_N; ++i) + pVal[i] = 0; + } + } + clearUnusedBits(); + } + + template + void cpZextOrTrunc(const ap_private<_AP_W1, _AP_S1, _AP_N1>& that) { + if (BitWidth > _AP_W1) + cpZext(that); + else if (BitWidth < _AP_W1) + cpTrunc(that); + else { + for (int i=0; i<_AP_N1; ++i) + pVal[i]=that.pVal[i]; + clearUnusedBits(); + } + } + + template + void cpSextOrTrunc(const ap_private<_AP_W1, _AP_S1, _AP_N1>& that) { + if (BitWidth > _AP_W1) + cpSext(that); + else if (BitWidth < _AP_W1) + cpTrunc(that); + else { + for (int i=0; i<_AP_N1; ++i) + pVal[i] = that.pVal[i]; + clearUnusedBits(); + } + } + + /// @name Value Characterization Functions + /// @{ + + /// @returns the total number of bits. + INLINE uint32_t getBitWidth() const { + return BitWidth; + } + + /// Here one word's bitwidth equals to that of uint64_t. + /// @returns the number of words to hold the integer value of this ap_private. + /// @brief Get the number of words. + INLINE uint32_t getNumWords() const { + return (BitWidth + APINT_BITS_PER_WORD - 1) / APINT_BITS_PER_WORD; + } + + /// This function returns the number of active bits which is defined as the + /// bit width minus the number of leading zeros. This is used in several + /// computations to see how "wide" the value is. + /// @brief Compute the number of active bits in the value + INLINE uint32_t getActiveBits() const { + uint32_t bits=BitWidth - countLeadingZeros(); + return bits?bits:1; + } + + + /// This method attempts to return the value of this ap_private as a zero extended + /// uint64_t. The bitwidth must be <= 64 or the value must fit within a + /// uint64_t. Otherwise an assertion will result. + /// @brief Get zero extended value + INLINE uint64_t getZExtValue() const { + assert(getActiveBits() <= 64 && "Too many bits for uint64_t"); + return *pVal; + } + + /// This method attempts to return the value of this ap_private as a sign extended + /// int64_t. The bit width must be <= 64 or the value must fit within an + /// int64_t. Otherwise an assertion will result. + /// @brief Get sign extended value + INLINE int64_t getSExtValue() const { + assert(getActiveBits() <= 64 && "Too many bits for int64_t"); + return int64_t(pVal[0]); + } + + /// This method determines how many bits are required to hold the ap_private + /// equivalent of the string given by \p str of length \p slen. + /// @brief Get bits required for string value. + static uint32_t getBitsNeeded(const char* str, uint32_t slen, uint8_t radix); + + /// countLeadingZeros - This function is an ap_private version of the + /// countLeadingZeros_{32,64} functions in MathExtras.h. It counts the number + /// of zeros from the most significant bit to the first one bit. + /// @returns BitWidth if the value is zero. + /// @returns the number of zeros from the most significant bit to the first + /// one bits. + INLINE uint32_t countLeadingZeros() const ; + + /// countLeadingOnes - This function counts the number of contiguous 1 bits + /// in the high order bits. The count stops when the first 0 bit is reached. + /// @returns 0 if the high order bit is not set + /// @returns the number of 1 bits from the most significant to the least + /// @brief Count the number of leading one bits. + INLINE uint32_t countLeadingOnes() const ; + + /// countTrailingZeros - This function is an ap_private version of the + /// countTrailingZoers_{32,64} functions in MathExtras.h. It counts + /// the number of zeros from the least significant bit to the first set bit. + /// @returns BitWidth if the value is zero. + /// @returns the number of zeros from the least significant bit to the first + /// one bit. + /// @brief Count the number of trailing zero bits. + INLINE uint32_t countTrailingZeros() const ; + + /// countPopulation - This function is an ap_private version of the + /// countPopulation_{32,64} functions in MathExtras.h. It counts the number + /// of 1 bits in the ap_private value. + /// @returns 0 if the value is zero. + /// @returns the number of set bits. + /// @brief Count the number of bits set. + INLINE uint32_t countPopulation() const { + uint32_t Count = 0; + for (uint32_t i = 0; i<_AP_N-1 ; ++i) + Count += CountPopulation_64(pVal[i]); + Count += CountPopulation_64(pVal[_AP_N-1]&mask); + return Count; + } + + /// @} + /// @name Conversion Functions + /// @{ + + /// This is used internally to convert an ap_private to a string. + /// @brief Converts an ap_private to a std::string + INLINE std::string toString(uint8_t radix, bool wantSigned) const + ; + + /// Considers the ap_private to be unsigned and converts it into a string in the + /// radix given. The radix can be 2, 8, 10 or 16. + /// @returns a character interpretation of the ap_private + /// @brief Convert unsigned ap_private to string representation. + INLINE std::string toStringUnsigned(uint8_t radix = 10) const { + return toString(radix, false); + } + + /// Considers the ap_private to be unsigned and converts it into a string in the + /// radix given. The radix can be 2, 8, 10 or 16. + /// @returns a character interpretation of the ap_private + /// @brief Convert unsigned ap_private to string representation. + INLINE std::string toStringSigned(uint8_t radix = 10) const { + return toString(radix, true); + } + + /// @returns a byte-swapped representation of this ap_private Value. + INLINE ap_private byteSwap() const ; + + /// @brief Converts this ap_private to a double value. + INLINE double roundToDouble(bool isSigned) const ; + + /// @brief Converts this unsigned ap_private to a double value. + INLINE double roundToDouble() const { + return roundToDouble(false); + } + + /// @brief Converts this signed ap_private to a double value. + INLINE double signedRoundToDouble() const { + return roundToDouble(true); + } + + /// The conversion does not do a translation from integer to double, it just + /// re-interprets the bits as a double. Note that it is valid to do this on + /// any bit width. Exactly 64 bits will be translated. + /// @brief Converts ap_private bits to a double + INLINE double bitsToDouble() const { + union { + uint64_t __I; + double __D; + } __T; + __T.__I = pVal[0]; + return __T.__D; + } + + /// The conversion does not do a translation from integer to float, it just + /// re-interprets the bits as a float. Note that it is valid to do this on + /// any bit width. Exactly 32 bits will be translated. + /// @brief Converts ap_private bits to a double + INLINE float bitsToFloat() const { + union { + uint32_t __I; + float __F; + } __T; + __T.__I = uint32_t(pVal[0]); + return __T.__F; + } + + /// The conversion does not do a translation from double to integer, it just + /// re-interprets the bits of the double. Note that it is valid to do this on + /// any bit width but bits from V may get truncated. + /// @brief Converts a double to ap_private bits. + INLINE ap_private& doubleToBits(double __V) { + union { + uint64_t __I; + double __D; + } __T; + __T.__D = __V; + pVal[0] = __T.__I; + return *this; + } + + /// The conversion does not do a translation from float to integer, it just + /// re-interprets the bits of the float. Note that it is valid to do this on + /// any bit width but bits from V may get truncated. + /// @brief Converts a float to ap_private bits. + INLINE ap_private& floatToBits(float __V) { + union { + uint32_t __I; + float __F; + } __T; + __T.__F = __V; + pVal[0] = __T.__I; + } + + //Reduce operation + //----------------------------------------------------------- + INLINE bool and_reduce() const { + return isMaxValue(); + } + + INLINE bool nand_reduce() const { + return isMinValue(); + } + + INLINE bool or_reduce() const { + return (bool)countPopulation(); + } + + INLINE bool nor_reduce() const { + return countPopulation()==0; + } + + INLINE bool xor_reduce() const { + unsigned int i=countPopulation(); + return (i%2)?true:false; + } + + INLINE bool xnor_reduce() const { + unsigned int i=countPopulation(); + return (i%2)?false:true; + } + INLINE std::string to_string(uint8_t radix=16, bool sign=false) const { + return toString(radix, radix==10?_AP_S:sign); + } +}; + +template +INLINE bool operator==(uint64_t V1, const ap_private<_AP_W, _AP_S, _AP_N>& V2) { + return V2 == V1; +} + +template +INLINE bool operator!=(uint64_t V1, const ap_private<_AP_W, _AP_S, _AP_N>& V2) { + return V2 != V1; +} + +namespace ap_private_ops { + enum {APINT_BITS_PER_WORD=64}; + /// @brief Determine the smaller of two ap_privates considered to be signed. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> smin(const ap_private<_AP_W, _AP_S, _AP_N> &LHS, const ap_private<_AP_W, _AP_S1, _AP_N> &RHS) { + return LHS.slt(RHS) ? LHS : RHS; + } + + /// @brief Determine the larger of two ap_privates considered to be signed. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> smax(const ap_private<_AP_W, _AP_S, _AP_N> &LHS, const ap_private<_AP_W, _AP_S1, _AP_N> &RHS) { + return LHS.sgt(RHS) ? LHS : RHS; + } + + /// @brief Determine the smaller of two ap_privates considered to be signed. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> umin(const ap_private<_AP_W, _AP_S, _AP_N> &LHS, const ap_private<_AP_W, _AP_S1, _AP_N> &RHS) { + return LHS.ult(RHS) ? LHS : RHS; + } + + /// @brief Determine the larger of two ap_privates considered to be unsigned. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> umax(const ap_private<_AP_W, _AP_S, _AP_N> &LHS, const ap_private<_AP_W, _AP_S1, _AP_N> &RHS) { + return LHS.ugt(RHS) ? LHS : RHS; + } + + /// @brief Check if the specified ap_private has a N-bits integer value. + template + INLINE bool isIntN(uint32_t __N, const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.isIntN(__N); + } + + /// @returns true if the argument ap_private value is a sequence of ones + /// starting at the least significant bit with the remainder zero. + template + INLINE bool isMask(uint32_t numBits, const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.getBoolValue() && ((APIVal + ap_private<_AP_W, _AP_S, _AP_N>(numBits,1)) & APIVal) == 0; + } + + /// @returns true if the argument ap_private value contains a sequence of ones + /// with the remainder zero. + template + INLINE bool isShiftedMask(uint32_t numBits, const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return isMask(numBits, (APIVal - ap_private<_AP_W, _AP_S, _AP_N>(numBits,1)) | APIVal); + } + + /// @returns a byte-swapped representation of the specified ap_private Value. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> byteSwap(const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.byteSwap(); + } + + /// @returns the floor log base 2 of the specified ap_private value. + template INLINE uint32_t logBase2(const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.logBase2(); + } + + /// GreatestCommonDivisor - This function returns the greatest common + /// divisor of the two ap_private values using Enclid's algorithm. + /// @returns the greatest common divisor of Val1 and Val2 + /// @brief Compute GCD of two ap_private values. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> GreatestCommonDivisor(const ap_private<_AP_W, _AP_S, _AP_N>& Val1, const ap_private<_AP_W, _AP_S, _AP_N>& Val2) + ; + + /// Treats the ap_private as an unsigned value for conversion purposes. + /// @brief Converts the given ap_private to a double value. + template INLINE double Roundap_privateToDouble(const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.roundToDouble(); + } + + /// Treats the ap_private as a signed value for conversion purposes. + /// @brief Converts the given ap_private to a double value. + template INLINE double RoundSignedap_privateToDouble(const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.signedRoundToDouble(); + } + + /// @brief Converts the given ap_private to a float vlalue. + template INLINE float Roundap_privateToFloat(const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return float(Roundap_privateToDouble(APIVal)); + } + + /// Treast the ap_private as a signed value for conversion purposes. + /// @brief Converts the given ap_private to a float value. + template INLINE float RoundSignedap_privateToFloat(const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return float(APIVal.signedRoundToDouble()); + } + + /// RoundDoubleToap_private - This function convert a double value to an ap_private value. + /// @brief Converts the given double value into a ap_private. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> RoundDoubleToap_private(double Double, uint32_t width) ; + + /// RoundFloatToap_private - Converts a float value into an ap_private value. + /// @brief Converts a float value into a ap_private. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> RoundFloatToap_private(float Float, uint32_t width) { + return RoundDoubleToap_private<_AP_W, _AP_S, _AP_N>(double(Float), width); + } + + /// Arithmetic right-shift the ap_private by shiftAmt. + /// @brief Arithmetic right-shift function. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> ashr(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, uint32_t shiftAmt) { + return LHS.ashr(shiftAmt); + } + + /// Logical right-shift the ap_private by shiftAmt. + /// @brief Logical right-shift function. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> lshr(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, uint32_t shiftAmt) { + return LHS.lshr(shiftAmt); + } + + /// Left-shift the ap_private by shiftAmt. + /// @brief Left-shift function. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> shl(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, uint32_t shiftAmt) { + return LHS.shl(shiftAmt); + } + + /// Signed divide ap_private LHS by ap_private RHS. + /// @brief Signed division function for ap_private. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> sdiv(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS.sdiv(RHS); + } + + /// Unsigned divide ap_private LHS by ap_private RHS. + /// @brief Unsigned division function for ap_private. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> udiv(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS.udiv(RHS); + } + + /// Signed remainder operation on ap_private. + /// @brief Function for signed remainder operation. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> srem(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS.srem(RHS); + } + + /// Unsigned remainder operation on ap_private. + /// @brief Function for unsigned remainder operation. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> urem(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS.urem(RHS); + } + + /// Performs multiplication on ap_private values. + /// @brief Function for multiplication operation. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> mul(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS * RHS; + } + + /// Performs addition on ap_private values. + /// @brief Function for addition operation. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> add(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS + RHS; + } + + /// Performs subtraction on ap_private values. + /// @brief Function for subtraction operation. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> sub(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS - RHS; + } + + /// Performs bitwise AND operation on ap_private LHS and + /// ap_private RHS. + /// @brief Bitwise AND function for ap_private. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> And(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS & RHS; + } + + /// Performs bitwise OR operation on ap_private LHS and ap_private RHS. + /// @brief Bitwise OR function for ap_private. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> Or(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS | RHS; + } + + /// Performs bitwise XOR operation on ap_private. + /// @brief Bitwise XOR function for ap_private. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> Xor(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS ^ RHS; + } + + /// Performs a bitwise complement operation on ap_private. + /// @brief Bitwise complement function. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> Not(const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return ~APIVal; + } + + template void clearUnusedBits(uint64_t& msw) { + // Compute how many bits are used in the final word + // uint32_t wordBits = APIVal.getBitWidth() & 0x3f; + if (wordBits == 0) + // If all bits are used, we want to leave the value alone. This also + // avoids the undefined behavior of >> when the shfit is the same size as + // the word size (64). + return; + + // Mask out the hight bits. + uint64_t mask = ~uint64_t(0ULL) >> (64 /*ap_private::APINT_BITS_PER_WORD */- wordBits); + msw &= mask; + } + template <> INLINE void clearUnusedBits<1>(uint64_t& msw) { + uint64_t mask = ~uint64_t(0ULL) >> (64 /*ap_private::APINT_BITS_PER_WORD */- 1); + msw &= mask; + } + template void clearUnusedBits(int64_t& msw) { + // Compute how many bits are used in the final word + // uint32_t wordBits = APIVal.getBitWidth() & 0x3f; + if (wordBits == 0) + // If all bits are used, we want to leave the value alone. This also + // avoids the undefined behavior of >> when the shfit is the same size as + // the word size (64). + return; + + // Mask out the hight bits. + uint64_t mask = ~uint64_t(0ULL) >> (64 /*ap_private::APINT_BITS_PER_WORD */- wordBits); + msw &= mask; + } + template <> INLINE void clearUnusedBits<1>(int64_t& msw) { + uint64_t mask = ~uint64_t(0ULL) >> (64 /*ap_private::APINT_BITS_PER_WORD */- 1); + msw &= mask; + } + // template + template + INLINE ap_private<_AP_W, _AP_S> ashr(const ap_private<_AP_W, _AP_S>& a) { + return ashr(a, shiftAmt); + } + + template + INLINE ap_private<_AP_W, _AP_S> lshr(const ap_private<_AP_W, _AP_S>& a) { + return lshr(a, shiftAmt); + } + + template + INLINE ap_private<_AP_W, true> ashr(const ap_private<_AP_W, true, 1>& a) { + enum {APINT_BITS_PER_WORD=64, excess_bits=APINT_BITS_PER_WORD-_AP_W}; + static const uint64_t sign_bit = (1ULL<<(_AP_W-1)); + static const uint64_t sign_ext_mask = (_AP_W-shiftAmt>0)?~0ULL<<(APINT_BITS_PER_WORD-_AP_W+shiftAmt):~0ULL; + return ap_private<_AP_W, true>((((int64_t)a.VAL) >> (shiftAmt)) | (a.VAL & sign_bit? sign_ext_mask : 0ULL)); + } + + template + INLINE ap_private<_AP_W, false> ashr(const ap_private<_AP_W, false, 1>& a) { + return ap_private<_AP_W, false>((a.VAL) >> (shiftAmt)); + } + + template + INLINE ap_private<_AP_W, _AP_S> lshr(const ap_private<_AP_W, _AP_S, 1>& a) { + static const uint64_t mask = ~0ULL<<_AP_W; + return ap_private<_AP_W, _AP_S>((a.VAL&mask) >> (shiftAmt)); + } + + template + INLINE ap_private<_AP_W-shiftAmt, _AP_S> shr(const ap_private<_AP_W, _AP_S>& a) { + return ap_private<_AP_W-shiftAmt, _AP_S>((a.VAL) >> (shiftAmt)); + } + + template + INLINE ap_private<_AP_W+shiftAmt, _AP_S> shl(const ap_private<_AP_W, _AP_S>& a) { + return ap_private<_AP_W+shiftAmt, _AP_S>((a.VAL) << (shiftAmt)); + } + + template + INLINE bool get(const ap_private<_AP_W, _AP_S, 1>& a) { + unsigned shift = (index%APINT_BITS_PER_WORD); + static const uint64_t mask=1ULL << (shift); + return ((mask & a.VAL) != 0); + } + + template + INLINE bool get(const ap_private<_AP_W, _AP_S>& a) { + static const uint64_t mask=1ULL << (index&0x3f); + return ((mask & a.pVal[(index)>>6]) != 0); + } + + template + INLINE void set(ap_private<_AP_W, _AP_S, 1>& a) { + const uint64_t mask = ~0ULL >> (lsb) << (APINT_BITS_PER_WORD-msb+lsb-1)>>(APINT_BITS_PER_WORD-msb-1); + a.VAL |= mask; + } + + template + INLINE void clear(ap_private<_AP_W, _AP_S, 1>& a) { + static const uint64_t mask = ~(~0ULL >> (lsb) <<(APINT_BITS_PER_WORD-msb+lsb-1) >> (APINT_BITS_PER_WORD-msb-1)); + a.VAL &= mask; + } + + template + INLINE void set(ap_private<_AP_W, _AP_S>& a) { + enum { APINT_BITS_PER_WORD=64, + lsb_word = lsb_index /APINT_BITS_PER_WORD, + msb_word = msb_index / APINT_BITS_PER_WORD, + msb = msb_index % APINT_BITS_PER_WORD, + lsb=lsb_index % APINT_BITS_PER_WORD}; + if (msb_word==lsb_word) { + const uint64_t mask = ~0ULL >> (lsb) << (APINT_BITS_PER_WORD-msb+lsb-1)>>(APINT_BITS_PER_WORD-msb-1); + a.pVal[msb_word] |= mask; + } else { + const uint64_t lsb_mask = ~0ULL >> (lsb) << (lsb); + const uint64_t msb_mask = ~0ULL << (APINT_BITS_PER_WORD-msb-1)>>(APINT_BITS_PER_WORD-msb-1); + a.pVal[lsb_word] |=lsb_mask; + for (int i=lsb_word+1; i + INLINE void clear(ap_private<_AP_W, _AP_S>& a) { + enum { APINT_BITS_PER_WORD=64, + lsb_word = lsb_index /APINT_BITS_PER_WORD, + msb_word = msb_index / APINT_BITS_PER_WORD, + msb = msb_index % APINT_BITS_PER_WORD, + lsb=lsb_index % APINT_BITS_PER_WORD}; + if (msb_word == lsb_word) { + const uint64_t mask = ~(~0ULL >> (lsb) << (APINT_BITS_PER_WORD-msb+lsb-1)>>(APINT_BITS_PER_WORD-msb-1)); + a.pVal[msb_word] &= mask; + } else { + const uint64_t lsb_mask = ~(~0ULL >> (lsb) << (lsb)); + const uint64_t msb_mask = ~(~0ULL << (APINT_BITS_PER_WORD-msb-1)>>(APINT_BITS_PER_WORD-msb-1)); + a.pVal[lsb_word] &=lsb_mask; + for (int i=lsb_word+1; i + INLINE void set(ap_private<_AP_W, _AP_S, 1>& a) { + static const uint64_t mask=1ULL << (index); + a.VAL |= mask; + a.clearUnusedBits(); + } + + template + INLINE void clear(ap_private<_AP_W, _AP_S, 1>& a) { + static const uint64_t mask=~(1ULL << (index)); + a.VAL &= mask; + a.clearUnusedBits(); + } + + template + INLINE void set(ap_private<_AP_W, _AP_S>& a) { + enum { APINT_BITS_PER_WORD=64, word = index/APINT_BITS_PER_WORD}; + static const uint64_t mask=1ULL << (index%APINT_BITS_PER_WORD); + a.pVal[word] |= mask; + a.clearUnusedBits(); + } + + template + INLINE void clear(ap_private<_AP_W, _AP_S>& a) { + enum { APINT_BITS_PER_WORD=64, word = index/APINT_BITS_PER_WORD}; + static const uint64_t mask=~(1ULL << (index%APINT_BITS_PER_WORD)); + a.pVal[word] &= mask; + a.clearUnusedBits(); + } + + template + INLINE bool isNegative(const ap_private<_AP_W, false>& a) { + return false; + } + + template + INLINE bool isNegative(const ap_private<_AP_W, true, 1>& a) { + static const uint64_t sign_mask = (1ULL << (_AP_W-1)); + return ((sign_mask & a.VAL) != 0); + } + + template + INLINE bool isNegative(const ap_private<_AP_W, true>& a) { + enum {APINT_BITS_PER_WORD=64,_AP_N=(_AP_W+APINT_BITS_PER_WORD-1)/APINT_BITS_PER_WORD}; + static const uint64_t sign_mask = (1ULL << (_AP_W%APINT_BITS_PER_WORD-1)); + return sign_mask & a.pVal[_AP_N-1]; + } +} // End of ap_private_ops namespace + +/// @brief Check if the specified ap_private has a N-bits integer value. +template +INLINE bool isIntN(uint32_t __N, const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.isIntN(__N); +} + +/// @returns true if the argument ap_private value is a sequence of ones +/// starting at the least significant bit with the remainder zero. +template +INLINE bool isMask(uint32_t numBits, const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.getBoolValue() && ((APIVal + ap_private<_AP_W, _AP_S, _AP_N>(numBits,1)) & APIVal) == 0; +} + +/// @returns true if the argument ap_private value contains a sequence of ones +/// with the remainder zero. +template +INLINE bool isShiftedMask(uint32_t numBits, const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return isMask(numBits, (APIVal - ap_private<_AP_W, _AP_S, _AP_N>(numBits,1)) | APIVal); +} + +#if 0 +/// add_1 - This function adds a single "digit" integer, y, to the multiple +/// "digit" integer array, x[]. x[] is modified to reflect the addition and +/// 1 is returned if there is a carry out, otherwise 0 is returned. +/// @returns the carry of the addition. +static bool add_1(uint64_t dest[], uint64_t x[], uint32_t len, uint64_t y) { + for (uint32_t i = 0; i < len; ++i) { + dest[i] = y + x[i]; + if (dest[i] < y) + y = 1; // Carry one to next digit. + else { + y = 0; // No need to carry so exit early + break; + } + } + return (y != 0); +} +#endif + +#if 0 +/// add - This function adds the integer array x to the integer array Y and +/// places the result in dest. +/// @returns the carry out from the addition +/// @brief General addition of 64-bit integer arrays +static bool add(uint64_t *dest, const uint64_t *x, const uint64_t *y, + uint32_t destlen, uint32_t xlen, uint32_t ylen, bool xsigned, bool ysigned) { + bool carry = false; + uint32_t len = AESL_std::min(xlen, ylen); + uint32_t i; + for (i = 0; i< len && i < destlen; ++i) { + uint64_t limit = AESL_std::min(x[i],y[i]); // must come first in case dest == x + dest[i] = x[i] + y[i] + carry; + carry = dest[i] < limit || (carry && dest[i] == limit); + } + if (xlen > ylen) { + const uint64_t yext = xsigned && int64_t(y[ylen-1])<0 ? -1 : 0; + for (i=ylen; i< xlen && i < destlen; i++) { + uint64_t limit = AESL_std::min(x[i], yext); + dest[i] = x[i] + yext + carry; + carry = (dest[i] < limit)||(carry && dest[i] == x[i]); + } + } else if (ylen> xlen) { + const uint64_t xext = ysigned && int64_t(x[xlen-1])<0 ? -1 : 0; + for (i=xlen; i< ylen && i < destlen; i++) { + uint64_t limit = AESL_std::min(xext, y[i]); + dest[i] = xext + y[i] + carry; + carry = (dest[i] < limit)||(carry && dest[i] == y[i]); + } + } + return carry; +} +#endif + +#if 0 +/// @returns returns the borrow out. +/// @brief Generalized subtraction of 64-bit integer arrays. +static bool sub(uint64_t *dest, const uint64_t *x, const uint64_t *y, + uint32_t destlen, uint32_t xlen, uint32_t ylen, bool xsigned, bool ysigned) { + bool borrow = false; + uint32_t i; + uint32_t len = AESL_std::min(xlen, ylen); + for (i = 0; i < len && i < destlen; ++i) { + uint64_t x_tmp = borrow ? x[i] - 1 : x[i]; + borrow = y[i] > x_tmp || (borrow && x[i] == 0); + dest[i] = x_tmp - y[i]; + } + if (xlen > ylen) { + const uint64_t yext = ysigned && int64_t(y[ylen-1])<0 ? -1 : 0; + for (i=ylen; i< xlen && i < destlen; i++) { + uint64_t x_tmp = borrow ? x[i] - 1 : x[i]; + borrow = yext > x_tmp || (borrow && x[i] == 0); + dest[i] = x_tmp - yext; + } + } else if (ylen> xlen) { + const uint64_t xext = xsigned && int64_t(x[xlen-1])<0 ? -1 : 0; + for (i=xlen; i< ylen && i < destlen; i++) { + uint64_t x_tmp = borrow ? xext - 1 : xext; + borrow = y[i] > x_tmp || (borrow && xext==0); + dest[i] = x_tmp - y[i]; + } + } + return borrow; +} +#endif + +/// Subtracts the RHS ap_private from this ap_private +/// @returns this, after subtraction +/// @brief Subtraction assignment operator. + +#if 0 +/// Multiplies an integer array, x by a a uint64_t integer and places the result +/// into dest. +/// @returns the carry out of the multiplication. +/// @brief Multiply a multi-digit ap_private by a single digit (64-bit) integer. +static uint64_t mul_1(uint64_t dest[], const uint64_t x[], uint32_t len, uint64_t y) { + // Split y into high 32-bit part (hy) and low 32-bit part (ly) + uint64_t ly = y & 0xffffffffULL, hy = (y) >> 32; + uint64_t carry = 0; + static const uint64_t two_power_32 = 1ULL << 32; + // For each digit of x. + for (uint32_t i = 0; i < len; ++i) { + // Split x into high and low words + uint64_t lx = x[i] & 0xffffffffULL; + uint64_t hx = (x[i]) >> 32; + // hasCarry - A flag to indicate if there is a carry to the next digit. + // hasCarry == 0, no carry + // hasCarry == 1, has carry + // hasCarry == 2, no carry and the calculation result == 0. + uint8_t hasCarry = 0; + dest[i] = carry + lx * ly; + // Determine if the add above introduces carry. + hasCarry = (dest[i] < carry) ? 1 : 0; + carry = hx * ly + ((dest[i]) >> 32) + (hasCarry ? two_power_32 : 0); + // The upper limit of carry can be (2^32 - 1)(2^32 - 1) + + // (2^32 - 1) + 2^32 = 2^64. + hasCarry = (!carry && hasCarry) ? 1 : (!carry ? 2 : 0); + + carry += (lx * hy) & 0xffffffffULL; + dest[i] = ((carry) << 32) | (dest[i] & 0xffffffffULL); + carry = (((!carry && hasCarry != 2) || hasCarry == 1) ? two_power_32 : 0) + + ((carry) >> 32) + ((lx * hy) >> 32) + hx * hy; + } + return carry; +} +#endif + +#if 0 +/// Multiplies integer array x by integer array y and stores the result into +/// the integer array dest. Note that dest's size must be >= xlen + ylen. +/// @brief Generalized multiplicate of integer arrays. +static void mul(uint64_t dest[], const uint64_t x[], uint32_t xlen, const uint64_t y[], + uint32_t ylen, uint32_t destlen) { + dest[xlen] = mul_1(dest, x, xlen, y[0]); + for (uint32_t i = 1; i < ylen; ++i) { + uint64_t ly = y[i] & 0xffffffffULL, hy = (y[i]) >> 32; + uint64_t carry = 0, lx = 0, hx = 0; + for (uint32_t j = 0; j < xlen; ++j) { + lx = x[j] & 0xffffffffULL; + hx = (x[j]) >> 32; + // hasCarry - A flag to indicate if has carry. + // hasCarry == 0, no carry + // hasCarry == 1, has carry + // hasCarry == 2, no carry and the calculation result == 0. + uint8_t hasCarry = 0; + uint64_t resul = carry + lx * ly; + hasCarry = (resul < carry) ? 1 : 0; + carry = (hasCarry ? (1ULL << 32) : 0) + hx * ly + ((resul) >> 32); + hasCarry = (!carry && hasCarry) ? 1 : (!carry ? 2 : 0); + carry += (lx * hy) & 0xffffffffULL; + resul = ((carry) << 32) | (resul & 0xffffffffULL); + dest[i+j] += resul; + carry = (((!carry && hasCarry != 2) || hasCarry == 1) ? (1ULL << 32) : 0)+ + ((carry) >> 32) + (dest[i+j] < resul ? 1 : 0) + + ((lx * hy) >> 32) + hx * hy; + } + dest[i+xlen] = carry; + } +} +#endif + + + +template +uint32_t ap_private<_AP_W, _AP_S, _AP_N>::getBitsNeeded(const char* str, uint32_t slen, uint8_t radix) { + assert(str != 0 && "Invalid value string"); + assert(slen > 0 && "Invalid string length"); + + // Each computation below needs to know if its negative + uint32_t isNegative = str[0] == '-'; + if (isNegative) { + slen--; + str++; + } + // For radixes of power-of-two values, the bits required is accurately and + // easily computed + if (radix == 2) + return slen + isNegative; + if (radix == 8) + return slen * 3 + isNegative; + if (radix == 16) + return slen * 4 + isNegative; + + // Otherwise it must be radix == 10, the hard case + assert(radix == 10 && "Invalid radix"); + + // Convert to the actual binary value. + //ap_private<_AP_W, _AP_S, _AP_N> tmp(sufficient, str, slen, radix); + + // Compute how many bits are required. + //return isNegative + tmp.logBase2() + 1; + return isNegative + slen * 4; +} + +template +uint32_t ap_private<_AP_W, _AP_S, _AP_N>::countLeadingZeros() const { + enum { msw_bits = (BitWidth % APINT_BITS_PER_WORD)?(BitWidth % APINT_BITS_PER_WORD):APINT_BITS_PER_WORD, + excessBits = APINT_BITS_PER_WORD - msw_bits }; + uint32_t Count = CountLeadingZeros_64(pVal[_AP_N-1]); + if (Count>=excessBits) + Count -= excessBits; + if (!pVal[_AP_N-1]) { + for (uint32_t i = _AP_N-1 ; i ; --i) { + if (!pVal[i-1]) + Count += APINT_BITS_PER_WORD; + else { + Count += CountLeadingZeros_64(pVal[i-1]); + break; + } + } + } + return Count; +} + +static uint32_t countLeadingOnes_64(uint64_t __V, uint32_t skip) { + uint32_t Count = 0; + if (skip) + (__V) <<= (skip); + while (__V && (__V & (1ULL << 63))) { + Count++; + (__V) <<= 1; + } + return Count; +} + +template +uint32_t ap_private<_AP_W, _AP_S, _AP_N>::countLeadingOnes() const { + if (isSingleWord()) + return countLeadingOnes_64(VAL, APINT_BITS_PER_WORD - BitWidth); + + uint32_t highWordBits = BitWidth % APINT_BITS_PER_WORD; + uint32_t shift = (highWordBits == 0 ? 0 : APINT_BITS_PER_WORD - highWordBits); + int i = _AP_N - 1; + uint32_t Count = countLeadingOnes_64(pVal[i], shift); + if (Count == highWordBits) { + for (i--; i >= 0; --i) { + if (pVal[i] == ~0ULL) + Count += APINT_BITS_PER_WORD; + else { + Count += countLeadingOnes_64(pVal[i], 0); + break; + } + } + } + return Count; +} + +template +INLINE uint32_t ap_private<_AP_W, _AP_S, _AP_N>::countTrailingZeros() const { + if (isSingleWord()) + return AESL_std::min(uint32_t(CountTrailingZeros_64(VAL)), BitWidth); + uint32_t Count = 0; + uint32_t i = 0; + for (; i < _AP_N && pVal[i] == 0; ++i) + Count += APINT_BITS_PER_WORD; + if (i < _AP_N) + Count += CountTrailingZeros_64(pVal[i]); + return AESL_std::min(Count, BitWidth); +} + +template +ap_private<_AP_W, _AP_S, _AP_N> ap_private<_AP_W, _AP_S, _AP_N>::byteSwap() const { + assert(BitWidth >= 16 && BitWidth % 16 == 0 && "Cannot byteswap!"); + if (BitWidth == 16) + return ap_private<_AP_W, _AP_S, _AP_N>(/*BitWidth,*/ ByteSwap_16(uint16_t(VAL))); + else if (BitWidth == 32) + return ap_private<_AP_W, _AP_S, _AP_N>(/*BitWidth,*/ ByteSwap_32(uint32_t(VAL))); + else if (BitWidth == 48) { + uint32_t Tmp1 = uint32_t((VAL) >> 16); + Tmp1 = ByteSwap_32(Tmp1); + uint16_t Tmp2 = uint16_t(VAL); + Tmp2 = ByteSwap_16(Tmp2); + return ap_private<_AP_W, _AP_S, _AP_N>(/*BitWidth,*/ ((uint64_t(Tmp2)) << 32) | Tmp1); + } else if (BitWidth == 64) + return ap_private<_AP_W, _AP_S, _AP_N>(/*BitWidth,*/ ByteSwap_64(VAL)); + else { + ap_private<_AP_W, _AP_S, _AP_N> Result(0); + char *pByte = (char*)Result.pVal; + for (uint32_t i = 0; i < BitWidth / APINT_WORD_SIZE / 2; ++i) { + char Tmp = pByte[i]; + pByte[i] = pByte[BitWidth / APINT_WORD_SIZE - 1 - i]; + pByte[BitWidth / APINT_WORD_SIZE - i - 1] = Tmp; + } + return Result; + } +} + +template +ap_private<_AP_W, _AP_S, _AP_N> ap_private_ops::GreatestCommonDivisor(const ap_private<_AP_W, _AP_S, _AP_N>& API1, const ap_private<_AP_W, _AP_S, _AP_N>& API2) { + ap_private<_AP_W, _AP_S, _AP_N> __A = API1, __B = API2; + while (!!__B) { + ap_private<_AP_W, _AP_S, _AP_N> __T = __B; + __B = ap_private_ops::urem(__A, __B); + __A = __T; + } + return __A; +} + +template +ap_private<_AP_W, _AP_S, _AP_N> ap_private_ops::RoundDoubleToap_private(double Double, uint32_t width) { + union { + double __D; + uint64_t __I; + } __T; + __T.__D = Double; + + // Get the sign bit from the highest order bit + bool isNeg = (__T.__I) >> 63; + + // Get the 11-bit exponent and adjust for the 1023 bit bias + int64_t exp = (((__T.__I) >> 52) & 0x7ffULL) - 1023; + + // If the exponent is negative, the value is < 0 so just return 0. + if (exp < 0) + return ap_private<_AP_W, _AP_S, _AP_N>(width, 0u); + + // Extract the mantissa by clearing the top 12 bits (sign + exponent). + uint64_t mantissa = (__T.__I & (~0ULL >> 12)) | 1ULL << 52; + + // If the exponent doesn't shift all bits out of the mantissa + if (exp < 52) + return isNeg ? -ap_private<_AP_W, _AP_S, _AP_N>(width, (mantissa) >> (52 - exp)) : + ap_private<_AP_W, _AP_S, _AP_N>((mantissa) >> (52 - exp)); + + // If the client didn't provide enough bits for us to shift the mantissa into + // then the result is undefined, just return 0 + if (width <= exp - 52) + return ap_private<_AP_W, _AP_S, _AP_N>(width, 0); + + // Otherwise, we have to shift the mantissa bits up to the right location + ap_private<_AP_W, _AP_S, _AP_N> Tmp(width, mantissa); + Tmp = Tmp.shl(exp - 52); + return isNeg ? -Tmp : Tmp; +} + +/// RoundToDouble - This function convert this ap_private to a double. +/// The layout for double is as following (IEEE Standard 754): +/// -------------------------------------- +/// | Sign Exponent Fraction Bias | +/// |-------------------------------------- | +/// | 1[63] 11[62-52] 52[51-00] 1023 | +/// -------------------------------------- +template +double ap_private<_AP_W, _AP_S, _AP_N>::roundToDouble(bool isSigned) const { + + // Handle the simple case where the value is contained in one uint64_t. + if (isSingleWord() || getActiveBits() <= APINT_BITS_PER_WORD) { + uint64_t val; + if (isSingleWord()) val = VAL; + else val = pVal[0]; + if (isSigned) { + int64_t sext = ((int64_t(val)) << (64-BitWidth)) >> (64-BitWidth); + return double(sext); + } else + return double(val); + } + + // Determine if the value is negative. + bool isNeg = isSigned ? (*this)[BitWidth-1] : false; + + // Construct the absolute value if we're negative. + ap_private<_AP_W, _AP_S, _AP_N> Tmp(isNeg ? -(*this) : (*this)); + + // Figure out how many bits we're using. + uint32_t n = Tmp.getActiveBits(); + + // The exponent (without bias normalization) is just the number of bits + // we are using. Note that the sign bit is gone since we constructed the + // absolute value. + uint64_t exp = n; + + // Return infinity for exponent overflow + if (exp > 1023) { + if (!isSigned || !isNeg) + return std::numeric_limits::infinity(); + else + return -std::numeric_limits::infinity(); + } + exp += 1023; // Increment for 1023 bias + + // Number of bits in mantissa is 52. To obtain the mantissa value, we must + // extract the high 52 bits from the correct words in pVal. + uint64_t mantissa; + unsigned hiWord = whichWord(n-1); + if (hiWord == 0) { + mantissa = Tmp.pVal[0]; + if (n > 52) + (mantissa) >>= (n - 52); // shift down, we want the top 52 bits. + } else { + assert(hiWord > 0 && "High word is negative?"); + uint64_t hibits = (Tmp.pVal[hiWord]) << (52 - n % APINT_BITS_PER_WORD); + uint64_t lobits = (Tmp.pVal[hiWord-1]) >> (11 + n % APINT_BITS_PER_WORD); + mantissa = hibits | lobits; + } + + // The leading bit of mantissa is implicit, so get rid of it. + uint64_t sign = isNeg ? (1ULL << (APINT_BITS_PER_WORD - 1)) : 0; + union { + double __D; + uint64_t __I; + } __T; + __T.__I = sign | ((exp) << 52) | mantissa; + return __T.__D; +} + +// Square Root - this method computes and returns the square root of "this". +// Three mechanisms are used for computation. For small values (<= 5 bits), +// a table lookup is done. This gets some performance for common cases. For +// values using less than 52 bits, the value is converted to double and then +// the libc sqrt function is called. The result is rounded and then converted +// back to a uint64_t which is then used to construct the result. Finally, +// the Babylonian method for computing square roots is used. +template +ap_private<_AP_W, _AP_S, _AP_N> ap_private<_AP_W, _AP_S, _AP_N>::sqrt() const { + + // Determine the magnitude of the value. + uint32_t magnitude = getActiveBits(); + + // Use a fast table for some small values. This also gets rid of some + // rounding errors in libc sqrt for small values. + if (magnitude <= 5) { + static const uint8_t results[32] = { + /* 0 */ 0, + /* 1- 2 */ 1, 1, + /* 3- 6 */ 2, 2, 2, 2, + /* 7-12 */ 3, 3, 3, 3, 3, 3, + /* 13-20 */ 4, 4, 4, 4, 4, 4, 4, 4, + /* 21-30 */ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + /* 31 */ 6 + }; + return ap_private<_AP_W, _AP_S, _AP_N>(/*BitWidth,*/ results[ (isSingleWord() ? VAL : pVal[0]) ]); + } + + // If the magnitude of the value fits in less than 52 bits (the precision of + // an IEEE double precision floating point value), then we can use the + // libc sqrt function which will probably use a hardware sqrt computation. + // This should be faster than the algorithm below. + if (magnitude < 52) { +#ifdef _MSC_VER + // Amazingly, VC++ doesn't have round(). + return ap_private<_AP_W, _AP_S, _AP_N>(/*BitWidth,*/ + uint64_t(::sqrt(double(isSingleWord()?VAL:pVal[0]))) + 0.5); +#else + return ap_private<_AP_W, _AP_S, _AP_N>(/*BitWidth,*/ + uint64_t(::round(::sqrt(double(isSingleWord()?VAL:pVal[0]))))); +#endif + } + + // Okay, all the short cuts are exhausted. We must compute it. The following + // is a classical Babylonian method for computing the square root. This code + // was adapted to APINt from a wikipedia article on such computations. + // See http://www.wikipedia.org/ and go to the page named + // Calculate_an_integer_square_root. + uint32_t nbits = BitWidth, i = 4; + ap_private<_AP_W, _AP_S, _AP_N> testy(16); + ap_private<_AP_W, _AP_S, _AP_N> x_old(/*BitWidth,*/ 1); + ap_private<_AP_W, _AP_S, _AP_N> x_new(0); + ap_private<_AP_W, _AP_S, _AP_N> two(/*BitWidth,*/ 2); + + // Select a good starting value using binary logarithms. + for (;; i += 2, testy = testy.shl(2)) + if (i >= nbits || this->ule(testy)) { + x_old = x_old.shl(i / 2); + break; + } + + // Use the Babylonian method to arrive at the integer square root: + for (;;) { + x_new = (this->udiv(x_old) + x_old).udiv(two); + if (x_old.ule(x_new)) + break; + x_old = x_new; + } + + // Make sure we return the closest approximation + // NOTE: The rounding calculation below is correct. It will produce an + // off-by-one discrepancy with results from pari/gp. That discrepancy has been + // determined to be a rounding issue with pari/gp as it begins to use a + // floating point representation after 192 bits. There are no discrepancies + // between this algorithm and pari/gp for bit widths < 192 bits. + ap_private<_AP_W, _AP_S, _AP_N> square(x_old * x_old); + ap_private<_AP_W, _AP_S, _AP_N> nextSquare((x_old + 1) * (x_old +1)); + if (this->ult(square)) + return x_old; + else if (this->ule(nextSquare)) { + ap_private<_AP_W, _AP_S, _AP_N> midpoint((nextSquare - square).udiv(two)); + ap_private<_AP_W, _AP_S, _AP_N> offset(*this - square); + if (offset.ult(midpoint)) + return x_old; + else + return x_old + 1; + } else + assert(0 && "Error in ap_private<_AP_W, _AP_S, _AP_N>::sqrt computation"); + return x_old + 1; +} + +/// Implementation of Knuth's Algorithm D (Division of nonnegative integers) +/// from "Art of Computer Programming, Volume 2", section 4.3.1, p. 272. The +/// variables here have the same names as in the algorithm. Comments explain +/// the algorithm and any deviation from it. +static void KnuthDiv(uint32_t *u, uint32_t *v, uint32_t *q, uint32_t* r, + uint32_t m, uint32_t n) { + assert(u && "Must provide dividend"); + assert(v && "Must provide divisor"); + assert(q && "Must provide quotient"); + assert(u != v && u != q && v != q && "Must us different memory"); + assert(n>1 && "n must be > 1"); + + // Knuth uses the value b as the base of the number system. In our case b + // is 2^31 so we just set it to -1u. + uint64_t b = uint64_t(1) << 32; + + //DEBUG(cerr << "KnuthDiv: m=" << m << " n=" << n << '\n'); + //DEBUG(cerr << "KnuthDiv: original:"); + //DEBUG(for (int i = m+n; i >=0; i--) cerr << " " << std::setbase(16) << u[i]); + //DEBUG(cerr << " by"); + //DEBUG(for (int i = n; i >0; i--) cerr << " " << std::setbase(16) << v[i-1]); + //DEBUG(cerr << '\n'); + // D1. [Normalize.] Set d = b / (v[n-1] + 1) and multiply all the digits of + // u and v by d. Note that we have taken Knuth's advice here to use a power + // of 2 value for d such that d * v[n-1] >= b/2 (b is the base). A power of + // 2 allows us to shift instead of multiply and it is easy to determine the + // shift amount from the leading zeros. We are basically normalizing the u + // and v so that its high bits are shifted to the top of v's range without + // overflow. Note that this can require an extra word in u so that u must + // be of length m+n+1. + uint32_t shift = CountLeadingZeros_32(v[n-1]); + uint32_t v_carry = 0; + uint32_t u_carry = 0; + if (shift) { + for (uint32_t i = 0; i < m+n; ++i) { + uint32_t u_tmp = (u[i]) >> (32 - shift); + u[i] = ((u[i]) << (shift)) | u_carry; + u_carry = u_tmp; + } + for (uint32_t i = 0; i < n; ++i) { + uint32_t v_tmp = (v[i]) >> (32 - shift); + v[i] = ((v[i]) << (shift)) | v_carry; + v_carry = v_tmp; + } + } + u[m+n] = u_carry; + //DEBUG(cerr << "KnuthDiv: normal:"); + //DEBUG(for (int i = m+n; i >=0; i--) cerr << " " << std::setbase(16) << u[i]); + //DEBUG(cerr << " by"); + //DEBUG(for (int i = n; i >0; i--) cerr << " " << std::setbase(16) << v[i-1]); + //DEBUG(cerr << '\n'); + + // D2. [Initialize j.] Set j to m. This is the loop counter over the places. + int j = m; + do { + //DEBUG(cerr << "KnuthDiv: quotient digit #" << j << '\n'); + // D3. [Calculate q'.]. + // Set qp = (u[j+n]*b + u[j+n-1]) / v[n-1]. (qp=qprime=q') + // Set rp = (u[j+n]*b + u[j+n-1]) % v[n-1]. (rp=rprime=r') + // Now test if qp == b or qp*v[n-2] > b*rp + u[j+n-2]; if so, decrease + // qp by 1, inrease rp by v[n-1], and repeat this test if rp < b. The test + // on v[n-2] determines at high speed most of the cases in which the trial + // value qp is one too large, and it eliminates all cases where qp is two + // too large. + uint64_t dividend = ((uint64_t(u[j+n]) << 32) + u[j+n-1]); + //DEBUG(cerr << "KnuthDiv: dividend == " << dividend << '\n'); + uint64_t qp = dividend / v[n-1]; + uint64_t rp = dividend % v[n-1]; + if (qp == b || qp*v[n-2] > b*rp + u[j+n-2]) { + qp--; + rp += v[n-1]; + if (rp < b && (qp == b || qp*v[n-2] > b*rp + u[j+n-2])) + qp--; + } + //DEBUG(cerr << "KnuthDiv: qp == " << qp << ", rp == " << rp << '\n'); + + // D4. [Multiply and subtract.] Replace (u[j+n]u[j+n-1]...u[j]) with + // (u[j+n]u[j+n-1]..u[j]) - qp * (v[n-1]...v[1]v[0]). This computation + // consists of a simple multiplication by a one-place number, combined with + // a subtraction. + bool isNeg = false; + for (uint32_t i = 0; i < n; ++i) { + uint64_t u_tmp = uint64_t(u[j+i]) | ((uint64_t(u[j+i+1])) << 32); + uint64_t subtrahend = uint64_t(qp) * uint64_t(v[i]); + bool borrow = subtrahend > u_tmp; + /*DEBUG(cerr << "KnuthDiv: u_tmp == " << u_tmp + << ", subtrahend == " << subtrahend + << ", borrow = " << borrow << '\n');*/ + + uint64_t result = u_tmp - subtrahend; + uint32_t k = j + i; + u[k++] = (uint32_t)(result & (b-1)); // subtract low word + u[k++] = (uint32_t)((result) >> 32); // subtract high word + while (borrow && k <= m+n) { // deal with borrow to the left + borrow = u[k] == 0; + u[k]--; + k++; + } + isNeg |= borrow; + /*DEBUG(cerr << "KnuthDiv: u[j+i] == " << u[j+i] << ", u[j+i+1] == " << + u[j+i+1] << '\n');*/ + } + /*DEBUG(cerr << "KnuthDiv: after subtraction:"); + DEBUG(for (int i = m+n; i >=0; i--) cerr << " " << u[i]); + DEBUG(cerr << '\n');*/ + // The digits (u[j+n]...u[j]) should be kept positive; if the result of + // this step is actually negative, (u[j+n]...u[j]) should be left as the + // true value plus b**(n+1), namely as the b's complement of + // the true value, and a "borrow" to the left should be remembered. + // + if (isNeg) { + bool carry = true; // true because b's complement is "complement + 1" + for (uint32_t i = 0; i <= m+n; ++i) { + u[i] = ~u[i] + carry; // b's complement + carry = carry && u[i] == 0; + } + } + /*DEBUG(cerr << "KnuthDiv: after complement:"); + DEBUG(for (int i = m+n; i >=0; i--) cerr << " " << u[i]); + DEBUG(cerr << '\n');*/ + + // D5. [Test remainder.] Set q[j] = qp. If the result of step D4 was + // negative, go to step D6; otherwise go on to step D7. + q[j] = (uint32_t)qp; + if (isNeg) { + // D6. [Add back]. The probability that this step is necessary is very + // small, on the order of only 2/b. Make sure that test data accounts for + // this possibility. Decrease q[j] by 1 + q[j]--; + // and add (0v[n-1]...v[1]v[0]) to (u[j+n]u[j+n-1]...u[j+1]u[j]). + // A carry will occur to the left of u[j+n], and it should be ignored + // since it cancels with the borrow that occurred in D4. + bool carry = false; + for (uint32_t i = 0; i < n; i++) { + uint32_t limit = AESL_std::min(u[j+i],v[i]); + u[j+i] += v[i] + carry; + carry = u[j+i] < limit || (carry && u[j+i] == limit); + } + u[j+n] += carry; + } + /*DEBUG(cerr << "KnuthDiv: after correction:"); + DEBUG(for (int i = m+n; i >=0; i--) cerr <<" " << u[i]); + DEBUG(cerr << "\nKnuthDiv: digit result = " << q[j] << '\n');*/ + + // D7. [Loop on j.] Decrease j by one. Now if j >= 0, go back to D3. + } while (--j >= 0); + + /*DEBUG(cerr << "KnuthDiv: quotient:"); + DEBUG(for (int i = m; i >=0; i--) cerr <<" " << q[i]); + DEBUG(cerr << '\n');*/ + + // D8. [Unnormalize]. Now q[...] is the desired quotient, and the desired + // remainder may be obtained by dividing u[...] by d. If r is non-null we + // compute the remainder (urem uses this). + if (r) { + // The value d is expressed by the "shift" value above since we avoided + // multiplication by d by using a shift left. So, all we have to do is + // shift right here. In order to mak + if (shift) { + uint32_t carry = 0; + //DEBUG(cerr << "KnuthDiv: remainder:"); + for (int i = n-1; i >= 0; i--) { + r[i] = ((u[i]) >> (shift)) | carry; + carry = (u[i]) << (32 - shift); + //DEBUG(cerr << " " << r[i]); + } + } else { + for (int i = n-1; i >= 0; i--) { + r[i] = u[i]; + //DEBUG(cerr << " " << r[i]); + } + } + //DEBUG(cerr << '\n'); + } + //DEBUG(cerr << std::setbase(10) << '\n'); +} + +template +void divide(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, uint32_t lhsWords, + const ap_private<_AP_W, _AP_S, _AP_N>& RHS, uint32_t rhsWords, + ap_private<_AP_W, _AP_S, _AP_N> *Quotient, ap_private<_AP_W, _AP_S, _AP_N> *Remainder) { + assert(lhsWords >= rhsWords && "Fractional result"); + enum {APINT_BITS_PER_WORD=64}; + // First, compose the values into an array of 32-bit words instead of + // 64-bit words. This is a necessity of both the "short division" algorithm + // and the the Knuth "classical algorithm" which requires there to be native + // operations for +, -, and * on an m bit value with an m*2 bit result. We + // can't use 64-bit operands here because we don't have native results of + // 128-bits. Furthremore, casting the 64-bit values to 32-bit values won't + // work on large-endian machines. + uint64_t mask = ~0ull >> (sizeof(uint32_t)*8); + uint32_t n = rhsWords * 2; + uint32_t m = (lhsWords * 2) - n; + + // Allocate space for the temporary values we need either on the stack, if + // it will fit, or on the heap if it won't. + uint32_t SPACE[128]; + uint32_t *__U = 0; + uint32_t *__V = 0; + uint32_t *__Q = 0; + uint32_t *__R = 0; + if ((Remainder?4:3)*n+2*m+1 <= 128) { + __U = &SPACE[0]; + __V = &SPACE[m+n+1]; + __Q = &SPACE[(m+n+1) + n]; + if (Remainder) + __R = &SPACE[(m+n+1) + n + (m+n)]; + } else { + __U = new uint32_t[m + n + 1]; + __V = new uint32_t[n]; + __Q = new uint32_t[m+n]; + if (Remainder) + __R = new uint32_t[n]; + } + + // Initialize the dividend + memset(__U, 0, (m+n+1)*sizeof(uint32_t)); + for (unsigned i = 0; i < lhsWords; ++i) { + uint64_t tmp = (LHS.getNumWords() == 1 ? LHS.VAL : LHS.pVal[i]); + __U[i * 2] = (uint32_t)(tmp & mask); + __U[i * 2 + 1] = (tmp) >> (sizeof(uint32_t)*8); + } + __U[m+n] = 0; // this extra word is for "spill" in the Knuth algorithm. + + // Initialize the divisor + memset(__V, 0, (n)*sizeof(uint32_t)); + for (unsigned i = 0; i < rhsWords; ++i) { + uint64_t tmp = (RHS.getNumWords() == 1 ? RHS.VAL : RHS.pVal[i]); + __V[i * 2] = (uint32_t)(tmp & mask); + __V[i * 2 + 1] = (tmp) >> (sizeof(uint32_t)*8); + } + + // initialize the quotient and remainder + memset(__Q, 0, (m+n) * sizeof(uint32_t)); + if (Remainder) + memset(__R, 0, n * sizeof(uint32_t)); + + // Now, adjust m and n for the Knuth division. n is the number of words in + // the divisor. m is the number of words by which the dividend exceeds the + // divisor (i.e. m+n is the length of the dividend). These sizes must not + // contain any zero words or the Knuth algorithm fails. + for (unsigned i = n; i > 0 && __V[i-1] == 0; i--) { + n--; + m++; + } + for (unsigned i = m+n; i > 0 && __U[i-1] == 0; i--) + m--; + + // If we're left with only a single word for the divisor, Knuth doesn't work + // so we implement the short division algorithm here. This is much simpler + // and faster because we are certain that we can divide a 64-bit quantity + // by a 32-bit quantity at hardware speed and short division is simply a + // series of such operations. This is just like doing short division but we + // are using base 2^32 instead of base 10. + assert(n != 0 && "Divide by zero?"); + if (n == 1) { + uint32_t divisor = __V[0]; + uint32_t remainder = 0; + for (int i = m+n-1; i >= 0; i--) { + uint64_t partial_dividend = (uint64_t(remainder)) << 32 | __U[i]; + if (partial_dividend == 0) { + __Q[i] = 0; + remainder = 0; + } else if (partial_dividend < divisor) { + __Q[i] = 0; + remainder = (uint32_t)partial_dividend; + } else if (partial_dividend == divisor) { + __Q[i] = 1; + remainder = 0; + } else { + __Q[i] = (uint32_t)(partial_dividend / divisor); + remainder = (uint32_t)(partial_dividend - (__Q[i] * divisor)); + } + } + if (__R) + __R[0] = remainder; + } else { + // Now we're ready to invoke the Knuth classical divide algorithm. In this + // case n > 1. + KnuthDiv(__U, __V, __Q, __R, m, n); + } + + // If the caller wants the quotient + if (Quotient) { + // Set up the Quotient value's memory. + if (Quotient->BitWidth != LHS.BitWidth) { + if (Quotient->isSingleWord()) + Quotient->VAL = 0; + } else + Quotient->clear(); + + // The quotient is in Q. Reconstitute the quotient into Quotient's low + // order words. + if (lhsWords == 1) { + uint64_t tmp = + uint64_t(__Q[0]) | ((uint64_t(__Q[1])) << (APINT_BITS_PER_WORD / 2)); + if (Quotient->isSingleWord()) + Quotient->VAL = tmp; + else + Quotient->pVal[0] = tmp; + } else { + assert(!Quotient->isSingleWord() && "Quotient ap_private not large enough"); + for (unsigned i = 0; i < lhsWords; ++i) + Quotient->pVal[i] = + uint64_t(__Q[i*2]) | ((uint64_t(__Q[i*2+1])) << (APINT_BITS_PER_WORD / 2)); + } + Quotient->clearUnusedBits(); + } + + // If the caller wants the remainder + if (Remainder) { + // Set up the Remainder value's memory. + if (Remainder->BitWidth != RHS.BitWidth) { + if (Remainder->isSingleWord()) + Remainder->VAL = 0; + } else + Remainder->clear(); + + // The remainder is in R. Reconstitute the remainder into Remainder's low + // order words. + if (rhsWords == 1) { + uint64_t tmp = + uint64_t(__R[0]) | ((uint64_t(__R[1])) << (APINT_BITS_PER_WORD / 2)); + if (Remainder->isSingleWord()) + Remainder->VAL = tmp; + else + Remainder->pVal[0] = tmp; + } else { + assert(!Remainder->isSingleWord() && "Remainder ap_private not large enough"); + for (unsigned i = 0; i < rhsWords; ++i) + Remainder->pVal[i] = + uint64_t(__R[i*2]) | ((uint64_t(__R[i*2+1])) << (APINT_BITS_PER_WORD / 2)); + } + Remainder->clearUnusedBits(); + } + + // Clean up the memory we allocated. + if (__U != &SPACE[0]) { + delete [] __U; + delete [] __V; + delete [] __Q; + delete [] __R; + } +} + + +template +void ap_private<_AP_W, _AP_S, _AP_N>::fromString(const char *str, uint32_t slen, uint8_t radix) { + enum { numbits=_AP_W}; + // Check our assumptions here + assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) && + "Radix should be 2, 8, 10, or 16!"); + assert(str && "String is null?"); + bool isNeg = str[0] == '-'; + if (isNeg) + str++, slen--; + + //skip any leading zero + while(*str == '0' && *(str+1) != '\0') {str++; slen--;} + assert((slen <= numbits || radix != 2) && "Insufficient bit width"); + assert(((slen - 1)*3 <= numbits || radix != 8) && "Insufficient bit width"); + assert(((slen - 1)*4 <= numbits || radix != 16) && "Insufficient bit width"); + assert((((slen -1)*64)/22 <= numbits || radix != 10) && "Insufficient bit width"); + + memset(pVal, 0, _AP_N * sizeof(uint64_t)); + + // Figure out if we can shift instead of multiply + uint32_t shift = (radix == 16 ? 4 : radix == 8 ? 3 : radix == 2 ? 1 : 0); + + // Set up an ap_private for the digit to add outside the loop so we don't + // constantly construct/destruct it. + uint64_t bigVal[_AP_N]; + memset(bigVal, 0, _AP_N * sizeof(uint64_t)); + ap_private<_AP_W, _AP_S, _AP_N> apdigit(getBitWidth(), bigVal); + ap_private<_AP_W, _AP_S, _AP_N> apradix(radix); + + // Enter digit traversal loop + for (unsigned i = 0; i < slen; i++) { + // Get a digit + uint32_t digit = 0; + char cdigit = str[i]; + if (radix == 16) { +#define isxdigit(c) (((c) >= '0' && (c) <= '9') || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F')) +#define isdigit(c) ((c) >= '0' && (c) <= '9') + if (!isxdigit(cdigit)) + assert(0 && "Invalid hex digit in string"); + if (isdigit(cdigit)) + digit = cdigit - '0'; + else if (cdigit >= 'a') + digit = cdigit - 'a' + 10; + else if (cdigit >= 'A') + digit = cdigit - 'A' + 10; + else + assert(0 && "huh? we shouldn't get here"); + } else if (isdigit(cdigit)) { + digit = cdigit - '0'; + } else { + assert(0 && "Invalid character in digit string"); + } +#undef isxdigit +#undef isdigit + // Shift or multiply the value by the radix + if (shift) + *this <<= shift; + else + *this *= apradix; + + // Add in the digit we just interpreted + if (apdigit.isSingleWord()) + apdigit.VAL = digit; + else + apdigit.pVal[0] = digit; + *this += apdigit; + } + // If its negative, put it in two's complement form + if (isNeg) { + (*this)--; + this->flip(); + } + clearUnusedBits(); +} + +template +std::string ap_private<_AP_W, _AP_S, _AP_N>::toString(uint8_t radix, bool wantSigned) const { + assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) && + "Radix should be 2, 8, 10, or 16!"); + static const char *digits[] = { + "0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F" + }; + std::string result; + uint32_t bits_used = getActiveBits(); + + if (radix != 10) { + // For the 2, 8 and 16 bit cases, we can just shift instead of divide + // because the number of bits per digit (1,3 and 4 respectively) divides + // equaly. We just shift until there value is zero. + + // First, check for a zero value and just short circuit the logic below. + if (*this == (uint64_t)(0)) + result = "0"; + else { + ap_private<_AP_W, false, _AP_N> tmp(*this); + size_t insert_at = 0; + if (wantSigned && isNegative()) { + // They want to print the signed version and it is a negative value + // Flip the bits and add one to turn it into the equivalent positive + // value and put a '-' in the result. + tmp.flip(); + tmp++; + tmp.clearUnusedBitsToZero(); + result = "-"; + insert_at = 1; + } + // Just shift tmp right for each digit width until it becomes zero + uint32_t shift = (radix == 16 ? 4 : (radix == 8 ? 3 : 1)); + uint64_t mask = radix - 1; + ap_private<_AP_W, false, _AP_N> zero(0); + while (tmp.ne(zero)) { + unsigned digit = (tmp.isSingleWord() ? tmp.VAL : tmp.pVal[0]) & mask; + result.insert(insert_at, digits[digit]); + tmp = tmp.lshr(shift); + } + } + return result; + } + + ap_private<_AP_W, false, _AP_N> tmp(*this); + ap_private<_AP_W, false, _AP_N> divisor(radix); + ap_private<_AP_W, false, _AP_N> zero(0); + size_t insert_at = 0; + if (wantSigned && isNegative()) { + // They want to print the signed version and it is a negative value + // Flip the bits and add one to turn it into the equivalent positive + // value and put a '-' in the result. + tmp.flip(); + tmp++; + tmp.clearUnusedBitsToZero(); + result = "-"; + insert_at = 1; + } + if (tmp == ap_private<_AP_W, false, _AP_N>(0)) + result = "0"; + else while (tmp.ne(zero)) { + ap_private<_AP_W, false, _AP_N> APdigit(0); + ap_private<_AP_W, false, _AP_N> tmp2(0); + divide(tmp, tmp.getNumWords(), divisor, divisor.getNumWords(), &tmp2, + &APdigit); + uint32_t digit = APdigit.getZExtValue(); + assert(digit < radix && "divide failed"); + result.insert(insert_at,digits[digit]); + tmp = tmp2; + } + + return result; +} + +// This implements a variety of operations on a representation of +// arbitrary precision, two's-complement, bignum integer values. + +/* Assumed by lowHalf, highHalf, partMSB and partLSB. A fairly safe + and unrestricting assumption. */ + +/* Some handy functions local to this file. */ + +template +void divide(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, uint32_t lhsWords, + uint64_t RHS, + ap_private<_AP_W, _AP_S, _AP_N> *Quotient, ap_private<_AP_W, _AP_S, _AP_N> *Remainder) { + uint32_t rhsWords=1; + assert(lhsWords >= rhsWords && "Fractional result"); + enum {APINT_BITS_PER_WORD=64}; + // First, compose the values into an array of 32-bit words instead of + // 64-bit words. This is a necessity of both the "short division" algorithm + // and the the Knuth "classical algorithm" which requires there to be native + // operations for +, -, and * on an m bit value with an m*2 bit result. We + // can't use 64-bit operands here because we don't have native results of + // 128-bits. Furthremore, casting the 64-bit values to 32-bit values won't + // work on large-endian machines. + uint64_t mask = ~0ull >> (sizeof(uint32_t)*8); + uint32_t n = 2; + uint32_t m = (lhsWords * 2) - n; + + // Allocate space for the temporary values we need either on the stack, if + // it will fit, or on the heap if it won't. + uint32_t SPACE[128]; + uint32_t *__U = 0; + uint32_t *__V = 0; + uint32_t *__Q = 0; + uint32_t *__R = 0; + if ((Remainder?4:3)*n+2*m+1 <= 128) { + __U = &SPACE[0]; + __V = &SPACE[m+n+1]; + __Q = &SPACE[(m+n+1) + n]; + if (Remainder) + __R = &SPACE[(m+n+1) + n + (m+n)]; + } else { + __U = new uint32_t[m + n + 1]; + __V = new uint32_t[n]; + __Q = new uint32_t[m+n]; + if (Remainder) + __R = new uint32_t[n]; + } + + // Initialize the dividend + memset(__U, 0, (m+n+1)*sizeof(uint32_t)); + for (unsigned i = 0; i < lhsWords; ++i) { + uint64_t tmp = (LHS.getNumWords() == 1 ? LHS.VAL : LHS.pVal[i]); + __U[i * 2] = tmp & mask; + __U[i * 2 + 1] = (tmp) >> (sizeof(uint32_t)*8); + } + __U[m+n] = 0; // this extra word is for "spill" in the Knuth algorithm. + + // Initialize the divisor + memset(__V, 0, (n)*sizeof(uint32_t)); + __V[0] = RHS & mask; + __V[1] = (RHS) >> (sizeof(uint32_t)*8); + + // initialize the quotient and remainder + memset(__Q, 0, (m+n) * sizeof(uint32_t)); + if (Remainder) + memset(__R, 0, n * sizeof(uint32_t)); + + // Now, adjust m and n for the Knuth division. n is the number of words in + // the divisor. m is the number of words by which the dividend exceeds the + // divisor (i.e. m+n is the length of the dividend). These sizes must not + // contain any zero words or the Knuth algorithm fails. + for (unsigned i = n; i > 0 && __V[i-1] == 0; i--) { + n--; + m++; + } + for (unsigned i = m+n; i > 0 && __U[i-1] == 0; i--) + m--; + + // If we're left with only a single word for the divisor, Knuth doesn't work + // so we implement the short division algorithm here. This is much simpler + // and faster because we are certain that we can divide a 64-bit quantity + // by a 32-bit quantity at hardware speed and short division is simply a + // series of such operations. This is just like doing short division but we + // are using base 2^32 instead of base 10. + assert(n != 0 && "Divide by zero?"); + if (n == 1) { + uint32_t divisor = __V[0]; + uint32_t remainder = 0; + for (int i = m+n-1; i >= 0; i--) { + uint64_t partial_dividend = (uint64_t(remainder)) << 32 | __U[i]; + if (partial_dividend == 0) { + __Q[i] = 0; + remainder = 0; + } else if (partial_dividend < divisor) { + __Q[i] = 0; + remainder = partial_dividend; + } else if (partial_dividend == divisor) { + __Q[i] = 1; + remainder = 0; + } else { + __Q[i] = partial_dividend / divisor; + remainder = partial_dividend - (__Q[i] * divisor); + } + } + if (__R) + __R[0] = remainder; + } else { + // Now we're ready to invoke the Knuth classical divide algorithm. In this + // case n > 1. + KnuthDiv(__U, __V, __Q, __R, m, n); + } + + // If the caller wants the quotient + if (Quotient) { + // Set up the Quotient value's memory. + if (Quotient->BitWidth != LHS.BitWidth) { + if (Quotient->isSingleWord()) + Quotient->VAL = 0; + else + delete [] Quotient->pVal; + } else + Quotient->clear(); + + // The quotient is in Q. Reconstitute the quotient into Quotient's low + // order words. + if (lhsWords == 1) { + uint64_t tmp = + uint64_t(__Q[0]) | ((uint64_t(__Q[1])) << (APINT_BITS_PER_WORD / 2)); + if (Quotient->isSingleWord()) + Quotient->VAL = tmp; + else + Quotient->pVal[0] = tmp; + } else { + assert(!Quotient->isSingleWord() && "Quotient ap_private not large enough"); + for (unsigned i = 0; i < lhsWords; ++i) + Quotient->pVal[i] = + uint64_t(__Q[i*2]) | ((uint64_t(__Q[i*2+1])) << (APINT_BITS_PER_WORD / 2)); + } + Quotient->clearUnusedBits(); + } + + // If the caller wants the remainder + if (Remainder) { + // Set up the Remainder value's memory. + if (Remainder->BitWidth != 64 /* RHS.BitWidth */) { + if (Remainder->isSingleWord()) + Remainder->VAL = 0; + } else + Remainder->clear(); + + // The remainder is in __R. Reconstitute the remainder into Remainder's low + // order words. + if (rhsWords == 1) { + uint64_t tmp = + uint64_t(__R[0]) | ((uint64_t(__R[1])) << (APINT_BITS_PER_WORD / 2)); + if (Remainder->isSingleWord()) + Remainder->VAL = tmp; + else + Remainder->pVal[0] = tmp; + } else { + assert(!Remainder->isSingleWord() && "Remainder ap_private not large enough"); + for (unsigned i = 0; i < rhsWords; ++i) + Remainder->pVal[i] = + uint64_t(__R[i*2]) | ((uint64_t(__R[i*2+1])) << (APINT_BITS_PER_WORD / 2)); + } + Remainder->clearUnusedBits(); + } + + // Clean up the memory we allocated. + if (__U != &SPACE[0]) { + delete [] __U; + delete [] __V; + delete [] __Q; + delete [] __R; + } +} + +//When bitwidth < 64 +template class ap_private <_AP_W, _AP_S, 1> { +#ifdef _MSC_VER +#pragma warning( disable : 4521 4522 ) +#endif +public: + typedef typename retval<_AP_S>::Type ValType; + template + struct RType { + enum { + _AP_N =1, + mult_w = _AP_W+_AP_W2, + mult_s = _AP_S||_AP_S2, //?? why + plus_w = AP_MAX(_AP_W+(_AP_S2&&!_AP_S),_AP_W2+(_AP_S&&!_AP_S2))+1, //shouldn't it be AP_MAX(_AP_W,_AP_W2)+!(_AP_S^_AP_S2)+1 ???? + plus_s = _AP_S||_AP_S2, + minus_w = AP_MAX(_AP_W+(_AP_S2&&!_AP_S),_AP_W2+(_AP_S&&!_AP_S2))+1, + minus_s = true, + div_w = _AP_W+_AP_S2, + div_s = _AP_S||_AP_S2, + mod_w = AP_MIN(_AP_W,_AP_W2+(!_AP_S2&&_AP_S)), + mod_s = _AP_S, + logic_w = AP_MAX(_AP_W+(_AP_S2&&!_AP_S),_AP_W2+(_AP_S&&!_AP_S2)), + logic_s = _AP_S||_AP_S2 + }; + typedef ap_private mult; + typedef ap_private plus; + typedef ap_private minus; + typedef ap_private logic; + typedef ap_private div; + typedef ap_private mod; + typedef ap_private<_AP_W, _AP_S> arg1; + typedef bool reduce; + }; + enum { APINT_BITS_PER_WORD = 64}; + enum { excess_bits = (_AP_W%APINT_BITS_PER_WORD) ? APINT_BITS_PER_WORD -(_AP_W%APINT_BITS_PER_WORD) : 0}; + static const uint64_t mask = ((uint64_t)~0ULL >> (excess_bits)); + static const uint64_t not_mask = ~mask; + static const uint64_t sign_bit_mask = 1ULL << (APINT_BITS_PER_WORD-1); + template struct sign_ext_mask { static const uint64_t mask=~0ULL<<_AP_W1;}; + + enum { BitWidth=_AP_W}; + uint64_t VAL; ///< Used to store the <= 64 bits integer value. + const uint64_t *const pVal; + + INLINE uint32_t getBitWidth() const { + return BitWidth; + } + + template + ap_private<_AP_W, _AP_S, 1>& operator=(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { + VAL = RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + + template + ap_private<_AP_W, _AP_S, 1>& operator=(const volatile ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { + VAL = RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + + template + ap_private<_AP_W, _AP_S, 1>& operator=(const ap_private<_AP_W1, _AP_S1, 1>& RHS) { + VAL = RHS.VAL; + clearUnusedBits(); + return *this; + } + + template + ap_private<_AP_W, _AP_S, 1>& operator=(const volatile ap_private<_AP_W1, _AP_S1, 1>& RHS) { + VAL = RHS.VAL; + clearUnusedBits(); + return *this; + } + + volatile ap_private& operator=(const ap_private& RHS) volatile { + // Don't do anything for X = X + VAL = RHS.VAL; // No need to check because no harm done by copying. + return *this; + } + ap_private& operator=(const ap_private& RHS) { + // Don't do anything for X = X + VAL = RHS.VAL; // No need to check because no harm done by copying. + return *this; + } + + volatile ap_private& operator=(const volatile ap_private& RHS) volatile { + // Don't do anything for X = X + VAL = RHS.VAL; // No need to check because no harm done by copying. + return *this; + } + ap_private& operator=(const volatile ap_private& RHS) { + // Don't do anything for X = X + VAL = RHS.VAL; // No need to check because no harm done by copying. + return *this; + } + + template + INLINE ap_private& operator = (const ap_range_ref<_AP_W2, _AP_S2>& op2) { + *this = ap_private<_AP_W2, false>(op2); + return *this; + } + + explicit INLINE ap_private(uint64_t* val) : VAL(val[0]), pVal(&VAL){ + clearUnusedBits(); + } + + INLINE bool isSingleWord() const { return true; } + + INLINE void fromString(const char *strStart, uint32_t slen, + uint8_t radix, int offset=0) { + // Check our assumptions here + assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) && + "Radix should be 2, 8, 10, or 16!"); + assert(strStart && "String is null?"); + strStart+=offset; + switch(radix) { + case 2: + // sscanf(strStart,"%b",&VAL); + VAL = *strStart =='1' ? ~0ULL : 0; + for (;*strStart; ++strStart) { + assert((*strStart=='0'|| *strStart=='1')&&("Wrong binary number") ); + VAL <<=1; + VAL |= (*strStart-'0'); + } + break; + case 8: +#if __WIN32__ + sscanf(strStart,"%I64o",&VAL); +#else + +#if defined __x86_64__ + sscanf(strStart,"%lo",&VAL); +#else + sscanf(strStart,"%llo",&VAL); +#endif + +#endif + break; + case 10: +#if __WIN32__ + sscanf(strStart,"%I64u",&VAL); +#else + +#if defined __x86_64__ + sscanf(strStart,"%lu",&VAL); +#else + sscanf(strStart,"%llu",&VAL); +#endif + +#endif + break; + case 16: +#if __WIN32__ + sscanf(strStart,"%I64x",&VAL); +#else + +#if defined __x86_64__ + sscanf(strStart,"%lx",&VAL); +#else + sscanf(strStart,"%llx",&VAL); +#endif + +#endif + break; + default: + assert(true && "Unknown radix"); + // error + } + clearUnusedBits(); + } + + INLINE ap_private() : pVal(&VAL){VAL = 0ULL;} + +#define CTOR(TYPE) \ + INLINE ap_private(TYPE v) : VAL((uint64_t)v), pVal(&VAL) { \ + clearUnusedBits(); \ + } + CTOR(int) + CTOR(bool) + CTOR(signed char) + CTOR(unsigned char) + CTOR(short) + CTOR(unsigned short) + CTOR(unsigned int) + CTOR(long) + CTOR(unsigned long) + CTOR(unsigned long long) + CTOR(long long) + CTOR(float) + CTOR(double) +#undef CTOR + ap_private(uint32_t numWords, const uint64_t bigVal[]): VAL(bigVal[0]), pVal(&VAL) {clearUnusedBits();} + + ap_private(const std::string& val, uint8_t radix=2, int base=0, int offset=0): VAL(0), pVal(&VAL) { + assert(!val.empty() && "String empty?"); + fromString(val.c_str()+base, val.size()-base, radix); + } + + ap_private(const char strStart[], uint32_t slen, uint8_t radix, int base=0, int offset=0) : VAL(0), pVal(&VAL) { + fromString(strStart+base, slen-base, radix, offset); + } + + ap_private(const ap_private& that) : VAL(that.VAL), pVal(&VAL) { + clearUnusedBits(); + } + + template + ap_private(const ap_private<_AP_W1, _AP_S1, 1>& that) : VAL(that.VAL), pVal(&VAL) { + clearUnusedBits(); + } + + template + ap_private(const ap_private<_AP_W1, _AP_S1, _AP_N1>& that) : VAL(that.pVal[0]), pVal(&VAL) { + clearUnusedBits(); + } + + template + ap_private(const volatile ap_private<_AP_W1, _AP_S1, _AP_N1>& that) : VAL(that.pVal[0]), pVal(&VAL) { + clearUnusedBits(); + } + +#if 0 +template + explicit ap_private(const ap_private<_AP_W1, true, 1+_AP_W1/64>& that) + : VAL((_AP_W1>_AP_W) ? that.VAL & mask : ((1ULL<<(_AP_W1-1)&that.pVal[0]) ? sign_ext_mask<_AP_W1>::mask | that.VAL : that.pVal[0])), pVal(&VAL) {} + +template + explicit ap_private(const ap_private<_AP_W1, false, (_AP_W1+63)/64>& that) + : VAL(that.VAL & mask), pVal(&VAL) {} +#endif + + explicit ap_private(const char* val) : pVal(&VAL) { + std::string str(val); + uint32_t strLen = str.length(); + const char *strp = str.c_str(); + uint32_t offset = 0; + uint32_t base = 0; + bool neg = false; + uint32_t radix = 10; + ap_parse_sign(strp, base, neg); + ap_parse_prefix(strp + base, offset, radix); + + if ((radix != 10 && neg) || + (strLen - base - offset <= 0) || + InvalidDigit(strp, strLen, base + offset, radix)) { + fprintf(stderr, "invalid character string %s !\n", val); + assert(0); + } + + ap_private<_AP_W, _AP_S> ap_private_val(str.c_str(), strLen, radix, base, offset); + if (neg) + ap_private_val = -ap_private_val; + operator = (ap_private_val); + } + + ap_private(const char* val, signed char rd): pVal(&VAL) { + std::string str(val); + uint32_t strLen = str.length(); + const char *strp = str.c_str(); + uint32_t offset = 0; + uint32_t base = 0; + uint32_t radix = rd; + bool neg = false; + ap_parse_sign(strp, base, neg); + ap_parse_prefix(strp + base, offset, radix); + + if ((radix != 10 && neg) || + (strLen - base - offset <= 0) || + InvalidDigit(strp, strLen, base + offset, radix)) { + fprintf(stderr, "invalid character string %s !\n", val); + assert(0); + } + + uint32_t bitsNeeded = ap_private<_AP_W, _AP_S>::getBitsNeeded(strp, strLen, radix); + ap_private<_AP_W, _AP_S> ap_private_val(strp , strLen, radix, base, offset); + //ap_private<_AP_W, _AP_S> ap_private_val(bitsNeeded, strp , strLen, radix, base, offset); + if (strp[0] == '-') + ap_private_val = -ap_private_val; + operator = (ap_private_val); + } + + INLINE bool isNegative() const { + static const uint64_t sign_mask = 1ULL << (_AP_W-1); + return _AP_S && (sign_mask & VAL); + } + + INLINE bool isPositive() const { + return !isNegative(); + } + + INLINE bool isStrictlyPositive() const { + return !isNegative() && VAL!=0; + } + + INLINE bool isAllOnesValue() const { + return (mask & VAL) == mask; + } + + template + INLINE bool operator==(const ap_private<_AP_W1, _AP_S1, 1>& RHS) const { + return (VAL == RHS.VAL); + } + + INLINE bool operator==(const ap_private<_AP_W, _AP_S>& RHS) const { return VAL == RHS.VAL; } + INLINE bool operator==(const ap_private<_AP_W, !_AP_S>& RHS) const { return getVal() == RHS.getVal(); } + INLINE bool operator==(uint64_t Val) const { return (VAL == Val); } + INLINE bool operator!=(uint64_t Val) const { return (VAL != Val); } + INLINE bool operator!=(const ap_private<_AP_W, _AP_S>& RHS) const { return VAL != RHS.VAL; } + INLINE bool operator!=(const ap_private<_AP_W, !_AP_S>& RHS) const { return getVal() != RHS.getVal(); } + const ap_private operator++() { ++VAL; clearUnusedBits(); return *this; } + const ap_private operator--(int) { + ap_private orig(*this); + --VAL; clearUnusedBits(); + return orig; + } + const ap_private operator--() { --VAL; clearUnusedBits(); return *this;} + INLINE bool operator !() const { return !VAL;} + + const ap_private operator++(int) { + ap_private orig(*this); + VAL++; clearUnusedBits(); + return orig; + } + + const ap_private operator~() {return ap_private(~VAL);} + INLINE typename RType<1,false>::minus operator-() const { + return ap_private<1,false>(0) - (*this); + } + + INLINE std::string toString(uint8_t radix, bool wantSigned) const ; + INLINE std::string toStringUnsigned(uint8_t radix = 10) const { + return toString(radix, false); + } + INLINE std::string toStringSigned(uint8_t radix = 10) const { + return toString(radix, true); + } + INLINE void clear() { + VAL=0; + } + INLINE ap_private& clear(uint32_t bitPosition) { VAL &= ~(1ULL<<(bitPosition)); clearUnusedBits(); return *this;} + + INLINE ap_private ashr(uint32_t shiftAmt) const { + enum {excess_bits = APINT_BITS_PER_WORD - BitWidth}; + if (_AP_S) + return ap_private((shiftAmt == BitWidth) ? 0 : ((int64_t)VAL) >> (shiftAmt)); + else + return ap_private((shiftAmt == BitWidth) ? 0 : (VAL) >> (shiftAmt)); + } + + INLINE ap_private lshr(uint32_t shiftAmt) const { + return ap_private((shiftAmt == BitWidth) ? ap_private(0) : ap_private((VAL&mask) >> (shiftAmt))); + } + + INLINE ap_private shl(uint32_t shiftAmt) const { + if (shiftAmt > BitWidth) { + if (!isNegative()) + return ap_private(0); + else return ap_private(-1); + } + if (shiftAmt == BitWidth) return ap_private(0); + else return ap_private((VAL) << (shiftAmt)); + //return ap_private((shiftAmt == BitWidth) ? ap_private(0ULL) : ap_private(VAL << shiftAmt)); + } + + INLINE int64_t getSExtValue() const { + return VAL; + } + + INLINE uint64_t getZExtValue() const { + return VAL & mask; + } + + template + INLINE ap_private(const ap_range_ref<_AP_W2,_AP_S2>& ref) : pVal(&VAL) { + *this=ref.get(); + } + + template + INLINE ap_private(const ap_bit_ref<_AP_W2,_AP_S2>& ref) : pVal(&VAL) { + *this = ((uint64_t)(bool)ref); + } + + template + INLINE ap_private(const ap_concat_ref<_AP_W2, _AP_T2,_AP_W3, _AP_T3>& ref) : pVal(&VAL) { + *this=ref.get(); + } + + template + INLINE ap_private(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2> &val) : pVal(&VAL) { + *this = ((val.operator ap_private<_AP_W2, false> ())); + } + + template + INLINE ap_private(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2> &val) : pVal(&VAL) { + *this = (uint64_t)(bool)val; + } + + INLINE void write(const ap_private<_AP_W, _AP_S>& op2) volatile { + *this = (op2); + } + + //Explicit conversions to C interger types + //----------------------------------------------------------- + ValType getVal() const { + return VAL; + } + operator ValType () const { + return getVal(); + } + INLINE int to_int() const { + // ap_private<64 /* _AP_W */, _AP_S> res(V); + return (int) getVal(); + } + + INLINE unsigned to_uint() const { + return (unsigned) getVal(); + } + + INLINE long to_long() const { + return (long) getVal(); + } + + INLINE unsigned long to_ulong() const { + return (unsigned long) getVal(); + } + + INLINE ap_slong to_int64() const { + return (ap_slong) getVal(); + } + + INLINE ap_ulong to_uint64() const { + return (ap_ulong) getVal(); + } + + INLINE double to_double() const { + if (isNegative()) + return roundToDouble(true); + else + return roundToDouble(false); + } + + INLINE bool isMinValue() const { return VAL == 0;} + template INLINE ap_private& operator&=(const ap_private<_AP_W1, _AP_S1>& RHS) { + VAL = VAL&RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + + template INLINE ap_private& operator|=(const ap_private<_AP_W1, _AP_S1>& RHS) { + VAL = VAL|RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + + template INLINE ap_private& operator^=(const ap_private<_AP_W1, _AP_S1>& RHS){ + VAL = VAL^RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + + template INLINE ap_private& operator*=(const ap_private<_AP_W1, _AP_S1>& RHS){ + VAL = VAL*RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + + template INLINE ap_private& operator+=(const ap_private<_AP_W1, _AP_S1>& RHS){ + VAL = VAL+RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + + template INLINE ap_private& operator-=(const ap_private<_AP_W1, _AP_S1>& RHS){ + VAL = VAL-RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + INLINE const ap_private& operator<<=(uint32_t shiftAmt) { VAL<<=shiftAmt; clearUnusedBits(); return *this; } + + template INLINE typename RType<_AP_W1, _AP_S1>::logic operator&(const ap_private<_AP_W1, _AP_S1>& RHS) const { + if (RType<_AP_W1, _AP_S1>::logic_w <= 64) { + typename RType<_AP_W1, _AP_S1>::logic Ret(VAL & RHS.VAL); + return Ret; + } else { + typename RType<_AP_W1, _AP_S1>::logic Ret = *this; + return Ret & RHS; + } + } + + template INLINE typename RType<_AP_W1, _AP_S1>::logic operator^(const ap_private<_AP_W1, _AP_S1>& RHS) const { + if (RType<_AP_W1, _AP_S1>::logic_w <= 64) { + typename RType<_AP_W1, _AP_S1>::logic Ret(VAL ^ RHS.VAL); + return Ret; + } else { + typename RType<_AP_W1, _AP_S1>::logic Ret = *this; + return Ret ^ RHS; + } + } + + template INLINE typename RType<_AP_W1, _AP_S1>::logic operator|(const ap_private<_AP_W1, _AP_S1>& RHS) const { + if (RType<_AP_W1, _AP_S1>::logic_w <= 64) { + typename RType<_AP_W1, _AP_S1>::logic Ret(VAL | RHS.VAL); + return Ret; + } else { + typename RType<_AP_W1, _AP_S1>::logic Ret = *this; + return Ret | RHS; + } + } + + INLINE ap_private<_AP_W, _AP_S> And(const ap_private<_AP_W, _AP_S>& RHS) const { + return ap_private<_AP_W, _AP_S>(VAL & RHS.VAL); + } + + INLINE ap_private<_AP_W, _AP_S> Or(const ap_private<_AP_W, _AP_S>& RHS) const { + return ap_private<_AP_W, _AP_S>(VAL | RHS.VAL); + } + + INLINE ap_private<_AP_W, _AP_S> Xor(const ap_private<_AP_W, _AP_S>& RHS) const { + return ap_private<_AP_W, _AP_S>(VAL ^ RHS.VAL); + } +#if 1 + template + INLINE typename RType<_AP_W1, _AP_S1>::mult operator*(const ap_private<_AP_W1, _AP_S1>& RHS) const { + if (RType<_AP_W1, _AP_S1>::mult_w <= 64) { + typename RType<_AP_W1, _AP_S1>::mult Result(VAL * RHS.VAL); + return Result; + } else { + typename RType<_AP_W1, _AP_S1>::mult Result = typename RType<_AP_W1, _AP_S1>::mult(*this); + Result *= RHS; + return Result; + } + } +#endif + INLINE ap_private<_AP_W, _AP_S> Mul(const ap_private<_AP_W, _AP_S>& RHS) const { + return ap_private<_AP_W, _AP_S>(VAL * RHS.VAL); + } + + INLINE ap_private<_AP_W, _AP_S> Add(const ap_private<_AP_W, _AP_S>& RHS) const { + return ap_private<_AP_W, _AP_S>(VAL + RHS.VAL); + } + + INLINE ap_private<_AP_W, _AP_S> Sub(const ap_private<_AP_W, _AP_S>& RHS) const { + return ap_private<_AP_W, _AP_S>(VAL - RHS.VAL); + } + +#if 1 + INLINE ap_private& operator&=(uint64_t RHS) { VAL &= RHS; clearUnusedBits(); return *this;} + INLINE ap_private& operator|=(uint64_t RHS) { VAL |= RHS; clearUnusedBits(); return *this;} + INLINE ap_private& operator^=(uint64_t RHS){ VAL ^= RHS; clearUnusedBits(); return *this;} + INLINE ap_private& operator*=(uint64_t RHS){ VAL *= RHS; clearUnusedBits(); return *this; } + INLINE ap_private& operator+=(uint64_t RHS){ VAL += RHS; clearUnusedBits(); return *this;} + INLINE ap_private& operator-=(uint64_t RHS){ VAL -= RHS; clearUnusedBits(); return *this; } + INLINE ap_private operator&(uint64_t RHS) const { return ap_private(VAL & RHS); } + INLINE ap_private operator|(uint64_t RHS) const { return ap_private(VAL | RHS); } + INLINE ap_private operator^(uint64_t RHS) const { return ap_private(VAL ^ RHS); } + INLINE ap_private operator*(uint64_t RHS) const { return ap_private(VAL * RHS); } + INLINE ap_private operator/(uint64_t RHS) const { return ap_private(VAL / RHS); } + INLINE ap_private operator+(uint64_t RHS) const { return ap_private(VAL + RHS); } + INLINE ap_private operator-(uint64_t RHS) const { return ap_private(VAL - RHS); } +#endif + INLINE bool isMinSignedValue() const { + static const uint64_t min_mask = ~(~0ULL << (_AP_W-1)); + return BitWidth == 1 ? VAL == 1 : + (ap_private_ops::isNegative<_AP_W>(*this) && ((min_mask & VAL)==0)); + } + +#if 1 + + template INLINE + typename RType<_AP_W1,_AP_S1>::plus operator+(const ap_private<_AP_W1, _AP_S1>& RHS) const { + if (RType<_AP_W1,_AP_S1>::plus_w <=64) + return typename RType<_AP_W1,_AP_S1>::plus(RType<_AP_W1,_AP_S1>::plus_s ? int64_t(VAL+RHS.VAL):uint64_t(VAL+RHS.VAL)); + typename RType<_AP_W1,_AP_S1>::plus Result=RHS; + Result += VAL; + return Result; + } + + template INLINE + typename RType<_AP_W1,_AP_S1>::minus operator-(const ap_private<_AP_W1, _AP_S1>& RHS) const { + if (RType<_AP_W1,_AP_S1>::minus_w <=64) + return typename RType<_AP_W1,_AP_S1>::minus(int64_t(VAL-RHS.VAL)); + typename RType<_AP_W1,_AP_S1>::minus Result=*this; + Result -= RHS; + return Result; + } +#endif // #if 1 + + INLINE ap_private& flip() { + VAL = (~0ULL^VAL)&mask; + clearUnusedBits(); + return *this; + } + + uint32_t countPopulation() const { return CountPopulation_64(VAL);} + uint32_t countLeadingZeros() const { + int remainder = BitWidth % APINT_BITS_PER_WORD; + int excessBits = (APINT_BITS_PER_WORD - remainder) % APINT_BITS_PER_WORD; + //enum { remainder = BitWidth % APINT_BITS_PER_WORD, excessBits = APINT_BITS_PER_WORD - remainder}; + uint32_t Count = CountLeadingZeros_64(VAL); + if (Count) + Count-=excessBits; + return AESL_std::min(Count, (uint32_t)_AP_W); + } + + /// HiBits - This function returns the high "numBits" bits of this ap_private. + ap_private<_AP_W, _AP_S, 1> getHiBits(uint32_t numBits) const { + ap_private<_AP_W, _AP_S, 1> ret(*this); + ret = (ret)>>(BitWidth - numBits); + return ret; + } + + /// LoBits - This function returns the low "numBits" bits of this ap_private. + ap_private<_AP_W, _AP_S, 1> getLoBits(uint32_t numBits) const { + ap_private<_AP_W, _AP_S, 1> ret((VAL) << (BitWidth - numBits)); + ret = (ret)>>(BitWidth - numBits); + return ret; + //return ap_private(numBits, (VAL << (BitWidth - numBits))>> (BitWidth - numBits)); + } + + ap_private<_AP_W, _AP_S,1>& set(uint32_t bitPosition) { + VAL |= (1ULL << (bitPosition)); + clearUnusedBits(); + return *this; // clearUnusedBits(); + } + + void set() { + VAL = ~0ULL; + clearUnusedBits(); + } + + template + INLINE void set(const ap_private<_AP_W3, false> & val) { + operator = (ap_private<_AP_W3, _AP_S>(val)); + } + + INLINE void set(const ap_private & val) { + operator = (val); + } + + bool operator[](uint32_t bitPosition) const { + return (((1ULL << (bitPosition)) & VAL) != 0); + } + + INLINE void clearUnusedBits(void) { + enum { excess_bits = (_AP_W%APINT_BITS_PER_WORD) ? APINT_BITS_PER_WORD -_AP_W%APINT_BITS_PER_WORD : 0}; + VAL = _AP_S ? ((((int64_t)VAL)<<(excess_bits))>> (excess_bits)) : (excess_bits ? ((VAL)<<(excess_bits))>>(excess_bits) : VAL); + } + + INLINE void clearUnusedBitsToZero(void) { + enum { excess_bits = (_AP_W%APINT_BITS_PER_WORD) ? APINT_BITS_PER_WORD -_AP_W%APINT_BITS_PER_WORD : 0}; + static uint64_t mask = ~0ULL >> (excess_bits); + VAL &= mask; + } + + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1> udiv(const ap_private<_AP_W, _AP_S1>& RHS) const { + return ap_private<_AP_W, _AP_S||_AP_S1>(VAL / RHS.VAL); + } + + INLINE ap_private udiv(uint64_t RHS) const { + return ap_private(VAL / RHS); + } + + /// Signed divide this ap_private by ap_private RHS. + /// @brief Signed division function for ap_private. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1> sdiv(const ap_private<_AP_W, _AP_S1> & RHS) const { + if (isNegative()) + if (RHS.isNegative()) + return (-(*this)).udiv(-RHS); + else + return -((-(*this)).udiv(RHS)); + else if (RHS.isNegative()) + return -(this->udiv(-RHS)); + return this->udiv(RHS); + } + + /// Signed divide this ap_private by ap_private RHS. + /// @brief Signed division function for ap_private. + INLINE ap_private sdiv(int64_t RHS) const { + if (isNegative()) + if (RHS<0) + return (-(*this)).udiv(-RHS); + else + return -((-(*this)).udiv(RHS)); + else if (RHS<0) + return -(this->udiv(-RHS)); + return this->udiv(RHS); + } + + template + INLINE ap_private urem(const ap_private<_AP_W, _AP_S2>& RHS) const { + assert(RHS.VAL != 0 && "Divide by 0"); + return ap_private(VAL%RHS.VAL); + } + + INLINE ap_private urem(uint64_t RHS) const { + assert(RHS != 0 && "Divide by 0"); + return ap_private(VAL%RHS); + } + + /// Signed remainder operation on ap_private. + /// @brief Function for signed remainder operation. + template + INLINE ap_private srem(const ap_private<_AP_W, _AP_S2>& RHS) const { + if (isNegative()) { + ap_private lhs = -(*this); + if (RHS.isNegative()) { + ap_private rhs = -RHS; + return -(lhs.urem(rhs)); + } else + return -(lhs.urem(RHS)); + } else if (RHS.isNegative()) { + ap_private rhs = -RHS; + return this->urem(rhs); + } + return this->urem(RHS); + } + + /// Signed remainder operation on ap_private. + /// @brief Function for signed remainder operation. + INLINE ap_private srem(int64_t RHS) const { + if (isNegative()) + if (RHS<0) + return -((-(*this)).urem(-RHS)); + else + return -((-(*this)).urem(RHS)); + else if (RHS<0) + return this->urem(-RHS); + return this->urem(RHS); + } + + INLINE static void udivrem(const ap_private &LHS, const ap_private &RHS, + ap_private &Quotient, ap_private &Remainder){ + assert(RHS!=0 && "Divide by 0"); + Quotient = LHS.VAl/RHS.VAl; + Remainder = LHS.VAL % RHS.VAL; + } + + INLINE static void udivrem(const ap_private &LHS, uint64_t RHS, + ap_private &Quotient, ap_private &Remainder){ + assert(RHS!=0 && "Divide by 0"); + Quotient = LHS.VAl/RHS; + Remainder = LHS.VAL % RHS; + } + + INLINE static void sdivrem(const ap_private &LHS, const ap_private &RHS, + ap_private &Quotient, ap_private &Remainder) { + if (LHS.isNegative()) { + if (RHS.isNegative()) + ap_private::udivrem(-LHS, -RHS, Quotient, Remainder); + else + ap_private::udivrem(-LHS, RHS, Quotient, Remainder); + Quotient = -Quotient; + Remainder = -Remainder; + } else if (RHS.isNegative()) { + ap_private::udivrem(LHS, -RHS, Quotient, Remainder); + Quotient = -Quotient; + } else { + ap_private::udivrem(LHS, RHS, Quotient, Remainder); + } + } + + INLINE static void sdivrem(const ap_private &LHS, int64_t RHS, + ap_private &Quotient, ap_private &Remainder) { + if (LHS.isNegative()) { + if (RHS<0) + ap_private::udivrem(-LHS, -RHS, Quotient, Remainder); + else + ap_private::udivrem(-LHS, RHS, Quotient, Remainder); + Quotient = -Quotient; + Remainder = -Remainder; + } else if (RHS<0) { + ap_private::udivrem(LHS, -RHS, Quotient, Remainder); + Quotient = -Quotient; + } else { + ap_private::udivrem(LHS, RHS, Quotient, Remainder); + } + } + + template INLINE bool eq(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return (*this) == RHS; + } + + template INLINE bool ne(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return !((*this) == RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// the validity of the less-than relationship. + /// @returns true if *this < RHS when both are considered unsigned. + /// @brief Unsigned less than comparison + template INLINE bool ult(const ap_private<_AP_W1, _AP_S1, 1>& RHS) const { + uint64_t lhsZext = ((uint64_t(VAL)) << (64-_AP_W)) >> (64-_AP_W); + uint64_t rhsZext = ((uint64_t(RHS.VAL)) << (64-_AP_W1)) >> (64-_AP_W1); + return lhsZext < rhsZext; + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the less-than relationship. + /// @returns true if *this < RHS when both are considered signed. + /// @brief Signed less than comparison + template INLINE bool slt(const ap_private<_AP_W1, _AP_S1, 1>& RHS) const { + int64_t lhsSext = ((int64_t(VAL)) << (64-_AP_W)) >> (64-_AP_W); + int64_t rhsSext = ((int64_t(RHS.VAL)) << (64-_AP_W1)) >> (64-_AP_W1); + return lhsSext < rhsSext; + } + + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// validity of the less-or-equal relationship. + /// @returns true if *this <= RHS when both are considered unsigned. + /// @brief Unsigned less or equal comparison + template INLINE bool ule(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return ult(RHS) || eq(RHS); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the less-or-equal relationship. + /// @returns true if *this <= RHS when both are considered signed. + /// @brief Signed less or equal comparison + template INLINE bool sle(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return slt(RHS) || eq(RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// the validity of the greater-than relationship. + /// @returns true if *this > RHS when both are considered unsigned. + /// @brief Unsigned greather than comparison + template INLINE bool ugt(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return !ult(RHS) && !eq(RHS); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// the validity of the greater-than relationship. + /// @returns true if *this > RHS when both are considered signed. + /// @brief Signed greather than comparison + template INLINE bool sgt(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return !slt(RHS) && !eq(RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// validity of the greater-or-equal relationship. + /// @returns true if *this >= RHS when both are considered unsigned. + /// @brief Unsigned greater or equal comparison + template INLINE bool uge(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return !ult(RHS); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the greater-or-equal relationship. + /// @returns true if *this >= RHS when both are considered signed. + /// @brief Signed greather or equal comparison + template INLINE bool sge(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return !slt(RHS); + } + + INLINE ap_private abs() const { + if (isNegative()) + return -(*this); + return *this; + } + + ap_private<_AP_W, false> get() const { + ap_private<_AP_W,false> ret(*this); + return ret; + } + + INLINE static uint32_t getBitsNeeded(const char* str, uint32_t slen, uint8_t radix) { + return _AP_W; + } + + INLINE uint32_t getActiveBits() const { + uint32_t bits=_AP_W - countLeadingZeros(); + return bits?bits:1; + } + + INLINE double roundToDouble(bool isSigned=false) const { + const static uint64_t mask = ~0ULL << (APINT_BITS_PER_WORD - _AP_W); + return double(VAL); + } + + INLINE unsigned length() const { return _AP_W; } + + /*Reverse the contents of ap_private instance. I.e. LSB becomes MSB and vise versa*/ + INLINE ap_private& reverse () { + for (int i = 0; i < _AP_W/2; ++i) { + bool tmp = operator[](i); + if (operator[](_AP_W - 1 - i)) + set(i); + else + clear(i); + if (tmp) + set(_AP_W - 1 - i); + else + clear(_AP_W - 1 - i); + } + clearUnusedBits(); + return *this; + } + + /*Return true if the value of ap_private instance is zero*/ + INLINE bool iszero () const { + return isMinValue(); + } + + /* x < 0 */ + INLINE bool sign () const { + if (isNegative()) + return true; + return false; + } + + /* x[i] = !x[i] */ + INLINE void invert (int i) { + assert( i >= 0 && "Attempting to read bit with negative index"); + assert( i < _AP_W && "Attempting to read bit beyond MSB"); + flip(i); + } + + /* x[i] */ + INLINE bool test (int i) const { + assert( i >= 0 && "Attempting to read bit with negative index"); + assert( i < _AP_W && "Attempting to read bit beyond MSB"); + return operator[](i); + } + + //This is used for sc_lv and sc_bv, which is implemented by sc_uint + //Rotate an ap_private object n places to the left + INLINE void lrotate(int n) { + assert( n >= 0 && "Attempting to shift negative index"); + assert( n < _AP_W && "Shift value larger than bit width"); + operator = (shl(n) | lshr(_AP_W - n)); + } + + //This is used for sc_lv and sc_bv, which is implemented by sc_uint + //Rotate an ap_private object n places to the right + INLINE void rrotate(int n) { + assert( n >= 0 && "Attempting to shift negative index"); + assert( n < _AP_W && "Shift value larger than bit width"); + operator = (lshr(n) | shl(_AP_W - n)); + } + + //Set the ith bit into v + INLINE void set (int i, bool v) { + assert( i >= 0 && "Attempting to write bit with negative index"); + assert( i < _AP_W && "Attempting to write bit beyond MSB"); + v ? set(i) : clear(i); + } + + //Set the ith bit into v + INLINE void set_bit (int i, bool v) { + assert( i >= 0 && "Attempting to write bit with negative index"); + assert( i < _AP_W && "Attempting to write bit beyond MSB"); + v ? set(i) : clear(i); + } + + //Get the value of ith bit + INLINE bool get_bit (int i) const { + assert( i >= 0 && "Attempting to read bit with negative index"); + assert( i < _AP_W && "Attempting to read bit beyond MSB"); + return operator [](i); + } + + //complements every bit + INLINE void b_not() { + flip(); + } + + //Binary Arithmetic + //----------------------------------------------------------- +#define OP_BIN_AP(Sym,Rty, Fun) \ + template \ + INLINE \ + typename RType<_AP_W2,_AP_S2>::Rty \ + operator Sym (const ap_private<_AP_W2,_AP_S2>& op) const { \ + typename RType<_AP_W2,_AP_S2>::Rty lhs(*this); \ + typename RType<_AP_W2,_AP_S2>::Rty rhs(op); \ + return lhs.Fun(rhs); \ + } \ + + ///Bitwise and, or, xor + //OP_BIN_AP(&,logic, And) + //OP_BIN_AP(|,logic, Or) + //OP_BIN_AP(^,logic, Xor) + +#undef OP_BIN_AP + template + INLINE typename RType<_AP_W2,_AP_S2>::div + operator / (const ap_private<_AP_W2,_AP_S2>&op) const { + ap_private lhs=ap_private(*this); + ap_private rhs=ap_private(op); + return typename RType<_AP_W2,_AP_S2>::div((_AP_S||_AP_S2)?lhs.sdiv(rhs):lhs.udiv(rhs)); + } + + + template + INLINE typename RType<_AP_W2,_AP_S2>::mod + operator % (const ap_private<_AP_W2,_AP_S2>&op) const { + ap_private lhs=*this; + ap_private rhs=op; + typename RType<_AP_W2,_AP_S2>::mod res = typename RType<_AP_W2,_AP_S2>::mod (_AP_S?lhs.srem(rhs):lhs.urem(rhs)); + return res; + } + + +#define OP_ASSIGN_AP_2(Sym) \ + template \ + INLINE ap_private<_AP_W, _AP_S>& operator Sym##=(const ap_private<_AP_W2,_AP_S2>& op) \ + { \ + *this=operator Sym (op); \ + return *this; \ + } \ + + OP_ASSIGN_AP_2(/) + OP_ASSIGN_AP_2(%) +#undef OP_ASSIGN_AP_2 + + ///Bitwise assign: and, or, xor + //------------------------------------------------------------- + // OP_ASSIGN_AP(&) + // OP_ASSIGN_AP(^) + // OP_ASSIGN_AP(|) +#undef OP_ASSIGN_AP +#if 1 + + template + INLINE ap_private<_AP_W, _AP_S> + operator << (const ap_private<_AP_W2, _AP_S2>& op2) const { + uint32_t sh=op2.to_uint(); + return *this << sh; + } + + INLINE ap_private<_AP_W, _AP_S> + operator << (uint32_t sh) const { + return shl(sh); + } + +#endif + + template + INLINE ap_private<_AP_W, _AP_S> + operator >> (const ap_private<_AP_W2, _AP_S2>& op2) const { + uint32_t sh = op2.to_uint(); + return *this >> sh; + } + + INLINE ap_private<_AP_W, _AP_S> + operator >>(uint32_t sh) const { + ap_private<_AP_W, _AP_S> r(*this); + bool overflow=(sh>=_AP_W); + bool neg_v=r.isNegative(); + if(_AP_S) { + if(overflow) + neg_v?r.set():r.clear(); + else + return r.ashr(sh); + } else { + if(overflow) + r.clear(); + else + return r.lshr(sh); + } + return r; + } + + ///Shift assign + //------------------------------------------------------------------ +#define OP_ASSIGN_AP_3_SINGLE(Sym) \ + template \ + INLINE ap_private<_AP_W, _AP_S>& operator Sym##=(const ap_private<_AP_W2,_AP_S2>& op) \ + { \ + *this=operator Sym (op.getVal()); \ + return *this; \ + } + OP_ASSIGN_AP_3_SINGLE(>>) +#undef OP_ASSIGN_AP_3_SINGLE + + ///Comparisons + //----------------------------------------------------------------- + template + INLINE bool operator != (const ap_private<_AP_W2, _AP_S2, 1>& op) const { + return !(*this==op); + } + + template + INLINE bool operator > (const ap_private<_AP_W2, _AP_S2, 1>& op) const { + return op < *this; + } + + template + INLINE bool operator <= (const ap_private<_AP_W2, _AP_S2, 1>& op) const { + return !(*this>op); + } + + template + INLINE bool operator < (const ap_private<_AP_W2, _AP_S2, 1>& op) const { + enum { _AP_MAX_W = AP_MAX(_AP_W+(_AP_S||_AP_S2),_AP_W2+(_AP_S||_AP_S2))}; + ap_private<_AP_MAX_W, _AP_S> lhs(*this); + ap_private<_AP_MAX_W, _AP_S2> rhs(op); + if (_AP_S == _AP_S2) + return _AP_S?lhs.slt(rhs):lhs.ult(rhs); + else if (_AP_W < 32 && _AP_W2 < 32) + return lhs.slt(rhs); + else + if (_AP_S) + if (_AP_W2 >= _AP_W) + return lhs.ult(rhs); + else + return lhs.slt(rhs); + else + if (_AP_W >= _AP_W2) + return lhs.ult(rhs); + else + return lhs.slt(rhs); + } + + template + INLINE bool operator >=(const ap_private<_AP_W2, _AP_S2, 1>& op) const { + return !(*this + INLINE bool operator == (const ap_private<_AP_W2, _AP_S2, _AP_N2>& op) const { + return op == *this; + } + + template + INLINE bool operator != (const ap_private<_AP_W2, _AP_S2, _AP_N2>& op) const { + return !(op==*this); + } + + template + INLINE bool operator > (const ap_private<_AP_W2, _AP_S2, _AP_N2>& op) const { + return op < (*this); + } + + template + INLINE bool operator <= (const ap_private<_AP_W2, _AP_S2, _AP_N2>& op) const { + return op >= *this; + } + + template + INLINE bool operator <(const ap_private<_AP_W2, _AP_S2, _AP_N2>& op) const { + return op > *this; + } + + template + INLINE bool operator >=(const ap_private<_AP_W2,_AP_S2,_AP_N2>& op) const { + return op <= *this; + } + ///Bit and Part Select + //-------------------------------------------------------------- + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (int Hi, int Lo) { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (int Hi, int Lo) const { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(const_cast*>(this), Hi, Lo); + } + + INLINE ap_range_ref<_AP_W,_AP_S> + range (int Hi, int Lo) const { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>((const_cast*> (this)), Hi, Lo); + } + + INLINE ap_range_ref<_AP_W,_AP_S> + range (int Hi, int Lo) { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + range (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + range (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) const { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(const_cast(this), Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) const { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + return this->range(Hi, Lo); + } + + + INLINE ap_bit_ref<_AP_W,_AP_S> operator [] (uint32_t index) { + assert(index >= 0&&"Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S> (*this, (int)index); + } + + template + INLINE ap_bit_ref<_AP_W,_AP_S> operator [] (const ap_private<_AP_W2,_AP_S2> &index) { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S>( *this, index.to_int() ); + } + + template + INLINE bool operator [] (const ap_private<_AP_W2,_AP_S2>& index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + ap_bit_ref<_AP_W,_AP_S> br =operator [] (index); + return br.to_bool(); + } + + INLINE ap_bit_ref<_AP_W,_AP_S> bit (int index) { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S>( *this, index ); + } + + template + INLINE ap_bit_ref<_AP_W,_AP_S> bit (const ap_private<_AP_W2,_AP_S2> &index) { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W &&"Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S>( *this, index.to_int() ); + } + + INLINE bool bit (int index) const { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + ap_bit_ref<_AP_W,_AP_S> br(const_cast*>(this), index); + return br.to_bool(); + } + + template + INLINE bool bit (const ap_private<_AP_W2,_AP_S2>& index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + ap_bit_ref<_AP_W,_AP_S> br = bit(index); + return br.to_bool(); + } + + template + INLINE ap_concat_ref<_AP_W,ap_private<_AP_W, _AP_S>,_AP_W2,ap_private<_AP_W2,_AP_S2> > concat(const ap_private<_AP_W2,_AP_S2>& a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_private<_AP_W2,_AP_S2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W,ap_private<_AP_W, _AP_S>,_AP_W2,ap_private<_AP_W2,_AP_S2> > concat(ap_private<_AP_W2,_AP_S2>& a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_private<_AP_W2,_AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (const ap_private<_AP_W2, _AP_S2>& a2) const { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(const_cast& >(*this), const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (const ap_private<_AP_W2, _AP_S2>& a2) { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(*this, const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (ap_private<_AP_W2, _AP_S2>& a2) const { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(const_cast& >(*this), a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (ap_private<_AP_W2, _AP_S2>& a2) { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > + operator, (const ap_range_ref<_AP_W2, _AP_S2> &a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, + ap_range_ref<_AP_W2, _AP_S2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > + operator, (ap_range_ref<_AP_W2, _AP_S2> &a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, + ap_range_ref<_AP_W2, _AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, ap_bit_ref<_AP_W2, _AP_S2> > + operator, (const ap_bit_ref<_AP_W2, _AP_S2> &a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, + ap_bit_ref<_AP_W2, _AP_S2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, ap_bit_ref<_AP_W2, _AP_S2> > + operator, (ap_bit_ref<_AP_W2, _AP_S2> &a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, + ap_bit_ref<_AP_W2, _AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > + operator, (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > + operator, (ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) const { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) const { + return ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, a2); + } + + template + INLINE ap_private + operator & (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) { + return *this & a2.get(); + } + + template + INLINE ap_private + operator | (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) { + return *this | a2.get(); + } + + template + INLINE ap_private + operator ^ (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) { + return *this ^ a2.get(); + } + + + //Reduce operation + //----------------------------------------------------------- + INLINE bool and_reduce() const { + return (VAL & mask) == mask; + } + + INLINE bool nand_reduce() const { + return (VAL & mask) != mask; + } + + INLINE bool or_reduce() const { + return (bool)VAL; + } + + INLINE bool nor_reduce() const { + return VAL==0; + } + + INLINE bool xor_reduce() const { + unsigned int i=countPopulation(); + return (i%2)?true:false; + } + + INLINE bool xnor_reduce() const { + unsigned int i=countPopulation(); + return (i%2)?false:true; + } + + INLINE std::string to_string(uint8_t radix=2, bool sign=false) const { + return toString(radix, radix==10?_AP_S:sign); + } +}; +template +std::string ap_private<_AP_W, _AP_S, 1>::toString(uint8_t radix, bool wantSigned) const { + assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) && + "Radix should be 2, 8, 10, or 16!"); + static const char *digits[] = { + "0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f" + }; + std::string result; + if (radix != 10) { + // For the 2, 8 and 16 bit cases, we can just shift instead of divide + // because the number of bits per digit (1,3 and 4 respectively) divides + // equaly. We just shift until there value is zero. + + // First, check for a zero value and just short circuit the logic below. + if (*this == (uint64_t)(0)) + result = "0"; + else { + ap_private<_AP_W, false, 1> tmp(*this); + size_t insert_at = 0; + if (wantSigned && isNegative()) { + // They want to print the signed version and it is a negative value + // Flip the bits and add one to turn it into the equivalent positive + // value and put a '-' in the result. + tmp.flip(); + tmp++; + result = "-"; + insert_at = 1; + } + // Just shift tmp right for each digit width until it becomes zero + uint32_t shift = (radix == 16 ? 4 : (radix == 8 ? 3 : 1)); + uint64_t mask = radix - 1; + ap_private<_AP_W, false, 1> zero(0); + while (tmp.ne(zero)) { + unsigned digit = (unsigned)(tmp.VAL & mask); + result.insert(insert_at, digits[digit]); + tmp = tmp.lshr(shift); + } + } + return result; + } + + ap_private<_AP_W, false, 1> tmp(*this); + ap_private<6, false, 1> divisor(radix); + ap_private<_AP_W, _AP_S, 1> zero(0); + size_t insert_at = 0; + if (wantSigned && isNegative()) { + // They want to print the signed version and it is a negative value + // Flip the bits and add one to turn it into the equivalent positive + // value and put a '-' in the result. + tmp.flip(); + tmp++; + result = "-"; + insert_at = 1; + } + if (tmp == ap_private<_AP_W, false, 1>(0ULL)) + result = "0"; + else while (tmp.ne(zero)) { + ap_private<_AP_W, false, 1> APdigit = tmp%divisor; + ap_private<_AP_W, false, 1> tmp2 = tmp/divisor; + uint32_t digit = (uint32_t)(APdigit.getZExtValue()); + assert(digit < radix && "divide failed"); + result.insert(insert_at,digits[digit]); + tmp = tmp2; + } + return result; + +} + +#endif /* #ifndef LLVM_SUPPORT_MATHEXTRAS_H */ \ No newline at end of file diff --git a/hls_2018/router_01/main.cpp b/hls_2018/router_01/main.cpp new file mode 100755 index 0000000..2a4e7f5 --- /dev/null +++ b/hls_2018/router_01/main.cpp @@ -0,0 +1,97 @@ +/** + * main.cpp + * + * for Vivado HLS + */ + +#ifdef SOFTWARE +#include "ap_int.h" +#else +#include +#endif + +#ifdef CALCTIME +#include +#include +#endif + +#include "router.hpp" + +#define PRINT_SOLUTION + + +int main(int argc, char *argv[]) { + using namespace std; + + // Test data // + // NL_Q00.txt + //char boardstr[BOARDSTR_SIZE] = "X10Y05Z3L0000107041L0004107002L0102102021L0900100003"; + // NL_Q06.txt + char boardstr[BOARDSTR_SIZE] = "X10Y18Z2L0900109002L0901105012L0902103052L0903103062L0904100102L0905106012L0906109022L0717109102L0808109112L0017209172L0401200072L0912208152L0009201092L0709209092L0901206052L0309204092L0701209072L0101201022L0011202152L0016202162"; + // NL_Q08.txt + //char boardstr[BOARDSTR_SIZE] = "X17Y20Z2L0000103022L1603115052L0916107032L0302108012L1104111042L1002100002L0919116162L1616113182L1001115012L0500201182L1603213152L0600210022"; + + // Read boardstr from command line + if (1 < argc) { + // From stdin + if(argv[1][0]!='X') + { + char* c_p=fgets(boardstr, BOARDSTR_SIZE, stdin); + int length=strlen(c_p); + boardstr[length-1]=0; + } + else + { + strcpy(boardstr, argv[1]); + } + } + + // Seed value + int seed = 12345; + if (2 < argc) { + seed = atoi(argv[2]); + } + +#ifdef PRINT_SOLUTION + int size_x = (boardstr[1] - '0') * 10 + (boardstr[2] - '0'); + int size_y = (boardstr[4] - '0') * 10 + (boardstr[5] - '0'); + int size_z = (boardstr[7] - '0'); +#endif + + // Solver + ap_int<32> status; + clock_t clock_start, clock_done; + clock_start = clock(); + bool result = pynqrouter(boardstr, seed, &status); + clock_done = clock(); + if (result) { + cout << endl << "Test Passed!" << endl; + } else { + cout << endl << "Test Failed!" << endl; + } + cout << "status = " << (int)status << endl; + cout << "elapsed = " << ((double)(clock_done - clock_start) / CLOCKS_PER_SEC) << endl << endl; + +#ifdef PRINT_SOLUTION + cout << "SOLUTION" << endl; + cout << "========" << endl; + cout << "SIZE " << size_x << "X" << size_y << "X" << size_z << endl; + for (int z = 0; z < size_z; z++) { + cout << "LAYER " << (z + 1) << endl; + for (int y = 0; y < size_y; y++) { + for (int x = 0; x < size_x; x++) { + if (x != 0) { + cout << ","; + } + int i = ((x * MAX_WIDTH + y) << BITWIDTH_Z) | z; + cout << setfill('0') << setw(3) << right << (unsigned int)(unsigned char)(boardstr[i]); + //cout << (unsigned int)(unsigned char)(boardstr[i]); + } + cout << endl; + } + } +#endif + + return 0; +} + diff --git a/hls_2018/router_02/Makefile b/hls_2018/router_02/Makefile new file mode 100755 index 0000000..8f79e7a --- /dev/null +++ b/hls_2018/router_02/Makefile @@ -0,0 +1,20 @@ +TARGET = sim +OBJS = $(CPPS:.cpp=.o) +CPPS = $(wildcard *.cpp) +CXX = g++ +CXXFLAGS = -O3 -Wall -Wno-unknown-pragmas -Wno-unused-label -DSOFTWARE -DCALCTIME + +all: $(TARGET) + +$(TARGET): $(OBJS) + $(CXX) -O3 -o $@ $(OBJS) + +run: + python3 ../NLGenerator.py -x 20 -y 20 -z 6 -l 100;\ + python3 ./gen_boardstr.py Q-20x20x5_100_10.txt |\ + ./$(TARGET) - + + +clean: + rm *.o + rm $(TARGET) diff --git a/hls_2018/router_02/Makefile.cygwin b/hls_2018/router_02/Makefile.cygwin new file mode 100755 index 0000000..866fdcd --- /dev/null +++ b/hls_2018/router_02/Makefile.cygwin @@ -0,0 +1,14 @@ +TARGET = sim +OBJS = $(CPPS:.cpp=.o) +CPPS = $(wildcard *.cpp) +CXX = g++ +CXXFLAGS = -O3 -Wall -Wno-unknown-pragmas -Wno-unused-label -DSOFTWARE -DCALCTIME + +all: $(TARGET) + +$(TARGET): $(OBJS) + $(CXX) -O3 -Wl,--stack,33554432 -o $@ $(OBJS) + +clean: + rm *.o + rm $(TARGET) diff --git a/hls_2018/router_02/ap_int.h b/hls_2018/router_02/ap_int.h new file mode 100755 index 0000000..b8d9fdc --- /dev/null +++ b/hls_2018/router_02/ap_int.h @@ -0,0 +1,521 @@ +/* + * Copyright 2012 Xilinx, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __AESL_AP_SIM_H__ +#define __AESL_AP_SIM_H__ + +#ifndef __cplusplus +#error C++ is required to include this header file +#else + +#include "etc/ap_int_sim.h" +#include "etc/ap_fixed_sim.h" + +//Forward declaration +template class ap_fixed; +template class ap_ufixed; +template class ap_int; +template class ap_uint; + +//AP_INT +//-------------------------------------------------------- +template +class ap_int : public ap_private<_AP_W, true> { +#ifdef _MSC_VER +#pragma warning(disable: 4521 4522) +#endif /* #ifdef _MSC_VER */ +public: + typedef ap_private<_AP_W, true> Base; + + //Constructor + INLINE ap_int(): Base() {} + template + INLINE ap_int(const volatile ap_int<_AP_W2> &op):Base((const ap_private<_AP_W2,true> &)(op)) {} + + template + INLINE ap_int(const ap_int<_AP_W2> &op):Base((const ap_private<_AP_W2,true> &)(op)) {} + + template + INLINE ap_int(const ap_uint<_AP_W2> &op):Base((const ap_private<_AP_W2,false> &)(op)) {} + + template + INLINE ap_int(const volatile ap_uint<_AP_W2> &op):Base((const ap_private<_AP_W2,false> &)(op)) {} + + template + INLINE ap_int(const ap_range_ref<_AP_W2, _AP_S2>& ref):Base(ref) {} + + template + INLINE ap_int(const ap_bit_ref<_AP_W2, _AP_S2>& ref):Base(ref) {} + + template + INLINE ap_int(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& ref):Base(ref) {} + + template + INLINE ap_int(const ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op.to_ap_private()) {} + + template + INLINE ap_int(const ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op.to_ap_private()) {} + + template + INLINE ap_int(const volatile ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op.to_ap_private()) {} + + template + INLINE ap_int(const volatile ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op.to_ap_private()) {} + + template + INLINE ap_int(const ap_private<_AP_W2, _AP_S2>& op):Base(op) {} + + template + INLINE ap_int(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, + _AP_N2>& op):Base(op) {} + + template + INLINE ap_int(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, + _AP_N2>& op):Base(op) {} + + template + INLINE ap_int(const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& op):Base(op.to_ap_private()) {} + +#define CTOR(TYPE) \ + INLINE ap_int(TYPE v):Base(v) {} + CTOR(bool) + CTOR(signed char) + CTOR(unsigned char) + CTOR(short) + CTOR(unsigned short) + CTOR(int) + CTOR(unsigned int) + CTOR(long) + CTOR(unsigned long) + CTOR(unsigned long long) + CTOR(long long) + CTOR(float) + CTOR(double) + CTOR(const char*) + CTOR(const std::string&) +#undef CTOR + INLINE ap_int(const char* str, signed char rd):Base(str, rd) {} + //Assignment + //Another form of "write" + INLINE void operator = (const ap_int<_AP_W>& op2) volatile { + const_cast(this)->operator = (op2); + } + + INLINE void operator = (const volatile ap_int<_AP_W>& op2) volatile { + const_cast(this)->operator = (op2); + } + + INLINE ap_int<_AP_W>& operator = (const volatile ap_int<_AP_W>& op2) { + Base::operator = (const_cast& >(op2)); + return *this; + } + + INLINE ap_int<_AP_W>& operator = (const ap_int<_AP_W>& op2) { + Base::operator = ((const ap_private<_AP_W, true>&)op2); + return *this; + } +}; + +//AP_UINT +//--------------------------------------------------------------- +template +class ap_uint: public ap_private<_AP_W, false> { +#ifdef _MSC_VER +#pragma warning( disable : 4521 4522 ) +#endif +public: + typedef ap_private<_AP_W, false> Base; + //Constructor + INLINE ap_uint(): Base() {} + INLINE ap_uint(const ap_uint<_AP_W>& op) :Base(dynamic_cast&>(op)) {} + INLINE ap_uint(const volatile ap_uint<_AP_W>& op):Base(dynamic_cast&>(op)){} + template + INLINE ap_uint(const volatile ap_uint<_AP_W2> &op):Base((const ap_private<_AP_W2, false>&)(op)) {} + + template + INLINE ap_uint(const ap_uint<_AP_W2> &op) : Base((const ap_private<_AP_W2, false>&)(op)){} + + template + INLINE ap_uint(const ap_int<_AP_W2> &op) : Base((const ap_private<_AP_W2, true>&)(op)) {} + + template + INLINE ap_uint(const volatile ap_int<_AP_W2> &op) : Base((const ap_private<_AP_W2, false>&)(op)) {} + + template + INLINE ap_uint(const ap_range_ref<_AP_W2, _AP_S2>& ref):Base(ref) {} + + template + INLINE ap_uint(const ap_bit_ref<_AP_W2, _AP_S2>& ref):Base(ref) {} + + template + INLINE ap_uint(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& ref):Base(ref) {} + + template + INLINE ap_uint(const ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op.to_ap_private()) {} + + template + INLINE ap_uint(const ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op.to_ap_private()) {} + + template + INLINE ap_uint(const volatile ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op.to_ap_private()) {} + + template + INLINE ap_uint(const volatile ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op) {} + + template + INLINE ap_uint(const ap_private<_AP_W2, _AP_S2>& op):Base(op) {} + + template + INLINE ap_uint(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, + _AP_N2>& op):Base(op) {} + + template + INLINE ap_uint(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, + _AP_N2>& op):Base(op) {} + + template + INLINE ap_uint(const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& op):Base(op.to_ap_private()) {} + +#define CTOR(TYPE) \ + INLINE ap_uint(TYPE v):Base(v) {} + CTOR(bool) + CTOR(signed char) + CTOR(unsigned char) + CTOR(short) + CTOR(unsigned short) + CTOR(int) + CTOR(unsigned int) + CTOR(long) + CTOR(unsigned long) + CTOR(unsigned long long) + CTOR(long long) + CTOR(float) + CTOR(double) + CTOR(const char*) + CTOR(const std::string&) +#undef CTOR + INLINE ap_uint(const char* str, signed char rd):Base(str, rd) {} + //Assignment + //Another form of "write" + INLINE void operator = (const ap_uint<_AP_W>& op2) volatile { + Base::operator = (op2); + } + + INLINE void operator = (const volatile ap_uint<_AP_W>& op2) volatile { + Base::operator = (op2); + } + + INLINE ap_uint<_AP_W>& operator = (const volatile ap_uint<_AP_W>& op2) { + Base::operator = (op2); + return *this; + } + + INLINE ap_uint<_AP_W>& operator = (const ap_uint<_AP_W>& op2) { + Base::operator = ((const ap_private<_AP_W, false>&)(op2)); + return *this; + } +}; + +#define ap_bigint ap_int +#define ap_biguint ap_uint + +//AP_FIXED +//--------------------------------------------------------------------- +template +class ap_fixed: public ap_fixed_base<_AP_W, _AP_I, true, _AP_Q, _AP_O, _AP_N> { +#ifdef _MSC_VER +#pragma warning( disable : 4521 4522 ) +#endif +public: + typedef ap_fixed_base<_AP_W, _AP_I, true, _AP_Q, _AP_O, _AP_N> Base; + //Constructor + INLINE ap_fixed():Base() {} + + template + INLINE ap_fixed(const ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, + _AP_N2>& op): Base(op) {} + + template + INLINE ap_fixed(const ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, + _AP_N2>& op): Base(ap_fixed_base<_AP_W2, _AP_I2, + false, _AP_Q2, _AP_O2, _AP_N2>(op)) {} + + template + INLINE ap_fixed(const ap_int<_AP_W2>& op): + Base(ap_private<_AP_W2, true>(op)) {} + + template + INLINE ap_fixed(const ap_uint<_AP_W2>& op):Base(ap_private<_AP_W2, false>(op)) {} + + template + INLINE ap_fixed(const volatile ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, + _AP_N2>& op): Base(ap_fixed_base<_AP_W2, _AP_I2, + true, _AP_Q2, _AP_O2, _AP_N2>(op)) {} + + template + INLINE ap_fixed(const volatile ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, + _AP_N2>& op): Base(ap_fixed_base<_AP_W2, _AP_I2, + false, _AP_Q2, _AP_O2, _AP_N2>(op)) {} + + template + INLINE ap_fixed(const volatile ap_int<_AP_W2>& op): + Base(ap_private<_AP_W2, true>(op)) {} + + template + INLINE ap_fixed(const volatile ap_uint<_AP_W2>& op):Base(op) {} + + template + INLINE ap_fixed(const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& op):Base(op) {} + + template + INLINE ap_fixed(const ap_bit_ref<_AP_W2, _AP_S2>& op): + Base(op) {} + + template + INLINE ap_fixed(const ap_range_ref<_AP_W2, _AP_S2>& op): + Base(op) {} + + template + INLINE ap_fixed(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& op): + Base(op) {} + + template + INLINE ap_fixed(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& op): Base(op) {} + + template + INLINE ap_fixed(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& op): Base(op) {} + + template + INLINE ap_fixed(const ap_private<_AP_W2, _AP_S2>& op):Base(op) {} + + #define CTOR(TYPE) \ + INLINE ap_fixed(TYPE v):Base(v) {} + CTOR(bool) + CTOR(signed char) + CTOR(unsigned char) + CTOR(short) + CTOR(unsigned short) + CTOR(int) + CTOR(unsigned int) + CTOR(long) + CTOR(unsigned long) + CTOR(unsigned long long) + CTOR(long long) + CTOR(float) + CTOR(double) + CTOR(const char*) + CTOR(const std::string&) +#undef CTOR + INLINE ap_fixed(const char* str, signed char rd):Base(str, rd) {} + + //Assignment + INLINE ap_fixed& operator = (const ap_fixed<_AP_W, _AP_I, + _AP_Q, _AP_O, _AP_N>& op) { + Base::operator = (op); + return *this; + } + + INLINE ap_fixed& operator = (const volatile ap_fixed<_AP_W, _AP_I, + _AP_Q, _AP_O, _AP_N>& op) { + Base::operator = (op); + return *this; + } +}; + +//AP_ UFIXED +//--- ---------------------------------------------------------------- +template +class ap_ufixed : public ap_fixed_base<_AP_W, _AP_I, false, _AP_Q, _AP_O, _AP_N> { +#ifdef _MSC_VER +#pragma warning(disable: 4521 4522) +#endif /* #ifdef _MSC_VER */ +public: + typedef ap_fixed_base<_AP_W, _AP_I, false, _AP_Q, _AP_O, _AP_N> Base; + + //Constructor + INLINE ap_ufixed():Base() {} + + template + INLINE ap_ufixed(const ap_fixed<_AP_W2, _AP_I2, _AP_Q2, + _AP_O2, _AP_N2>& op) : Base(ap_fixed_base<_AP_W2, + _AP_I2, true, _AP_Q2, _AP_O2, _AP_N2>(op)) {} + + template + INLINE ap_ufixed(const ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, + _AP_O2, _AP_N2>& op): Base(ap_fixed_base<_AP_W2, _AP_I2, + false, _AP_Q2, _AP_O2, _AP_N2>(op)) {} + + template + INLINE ap_ufixed(const ap_int<_AP_W2>& op): + Base((const ap_private<_AP_W2, true>&)(op)) {} + + template + INLINE ap_ufixed(const ap_uint<_AP_W2>& op): + Base((const ap_private<_AP_W2, false>&)(op)) {} + + template + INLINE ap_ufixed(const volatile ap_fixed<_AP_W2, _AP_I2, _AP_Q2, + _AP_O2, _AP_N2>& op) : Base(ap_fixed_base<_AP_W2, + _AP_I2, true, _AP_Q2, _AP_O2, _AP_N2>(op)) {} + + template + INLINE ap_ufixed(const volatile ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, + _AP_O2, _AP_N2>& op): Base(ap_fixed_base<_AP_W2, _AP_I2, + false, _AP_Q2, _AP_O2, _AP_N2>(op)) {} + + template + INLINE ap_ufixed(const volatile ap_int<_AP_W2>& op): + Base(ap_private<_AP_W2, true>(op)) {} + + template + INLINE ap_ufixed(const volatile ap_uint<_AP_W2>& op): + Base(ap_private<_AP_W2, false>(op)) {} + + template + INLINE ap_ufixed(const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2>& op):Base(op) {} + + template + INLINE ap_ufixed(const ap_bit_ref<_AP_W2, _AP_S2>& op): + Base(op) {} + + template + INLINE ap_ufixed(const ap_range_ref<_AP_W2, _AP_S2>& op): + Base(op) {} + + template + INLINE ap_ufixed(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& op): + Base(op) {} + + template + INLINE ap_ufixed(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& op): Base(op) {} + + template + INLINE ap_ufixed(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& op): Base(op) {} + + template + INLINE ap_ufixed(const ap_private<_AP_W2, _AP_S2>& op):Base(op) {} + + #define CTOR(TYPE) \ + INLINE ap_ufixed(TYPE v):Base(v) {} + CTOR(bool) + CTOR(signed char) + CTOR(unsigned char) + CTOR(short) + CTOR(unsigned short) + CTOR(int) + CTOR(unsigned int) + CTOR(long) + CTOR(unsigned long) + CTOR(unsigned long long) + CTOR(long long) + CTOR(float) + CTOR(double) + CTOR(const char*) + CTOR(const std::string&) +#undef CTOR + INLINE ap_ufixed(const char* str, signed char rd):Base(str, rd) {} + + //Assignment + INLINE ap_ufixed& operator = (const ap_ufixed<_AP_W, _AP_I, + _AP_Q, _AP_O, _AP_N>& op) { + Base::operator = (op); + return *this; + } + + INLINE ap_ufixed& operator = (const volatile ap_ufixed<_AP_W, _AP_I, + _AP_Q, _AP_O, _AP_N>& op) { + Base::V = const_cast(op); + return *this; + } +}; + +#if defined(SYSTEMC_H) || defined(SYSTEMC_INCLUDED) +template +INLINE void sc_trace(sc_core::sc_trace_file *tf, const ap_int<_AP_W> &op, + const std::string &name) { + if (tf) + tf->trace(sc_dt::sc_lv<_AP_W>(op.to_string(2).c_str()), name); +} + +template +INLINE void sc_trace(sc_core::sc_trace_file *tf, const ap_uint<_AP_W> &op, + const std::string &name) { + if (tf) + tf->trace(sc_dt::sc_lv<_AP_W>(op.to_string(2).c_str()), name); +} + +template +INLINE void sc_trace(sc_core::sc_trace_file *tf, const ap_fixed<_AP_W, _AP_I, _AP_Q, _AP_O, _AP_N >&op, const std::string &name) { + tf->trace(sc_dt::sc_lv<_AP_W>(op.to_string(2).c_str()), name); +} + +template +INLINE void sc_trace(sc_core::sc_trace_file *tf, const ap_ufixed<_AP_W, _AP_I, _AP_Q, _AP_O, _AP_N >&op, const std::string &name) { + tf->trace(sc_dt::sc_lv<_AP_W>(op.to_string(2).c_str()), name); +} +#endif /* #if defined(SYSTEMC_H) || defined(SYSTEMC_INCLUDED) */ +#endif /* #ifndef __cplusplus */ +#endif /* #ifndef __AESL_AP_SIM_H__ */ \ No newline at end of file diff --git a/hls_2018/router_02/etc/ap_fixed_sim.h b/hls_2018/router_02/etc/ap_fixed_sim.h new file mode 100755 index 0000000..5be571d --- /dev/null +++ b/hls_2018/router_02/etc/ap_fixed_sim.h @@ -0,0 +1,2451 @@ +/* + * Copyright 2012 Xilinx, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __AESL_GCC_AP_FIXED_H__ +#define __AESL_GCC_AP_FIXED_H__ + +#ifndef __cplusplus + #error C++ is required to include this header file +#endif /* #ifndef __cplusplus */ + + +#include +#ifndef __AESL_APDT_IN_SCFLOW__ + #include "etc/ap_int_sim.h" +#else + #include "../etc/ap_private.h" +#endif /* #ifndef __AESL_APDT_IN_SCFLOW__ */ + +#define FLOAT_MAN 23 +#define FLOAT_EXP 8 +#define DOUBLE_MAN 52 +#define DOUBLE_EXP 11 +// #define DOUBLE_MAN_MASK (~0ULL >> (64-DOUBLE_MAN-2)) +#define DOUBLE_MAN_MASK 0x3fffffffffffffULL +#define BIAS(e) ((1ULL<<(e-1))-1) +#define FLOAT_BIAS BIAS(FLOAT_EXP) +#define DOUBLE_BIAS BIAS(DOUBLE_EXP) + +/// Forward declaration. +template struct ap_fixed_base; + +///Proxy class, which allows bit selection to be used as both rvalue(for reading) and +//lvalue(for writing) +template +struct af_bit_ref { +#ifdef _MSC_VER + #pragma warning(disable: 4521 4522) +#endif /* #ifdef _MSC_VER */ + ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& d_bv; + int d_index; +public: + INLINE af_bit_ref(const af_bit_ref<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& ref): + d_bv(ref.d_bv), d_index(ref.d_index) {} + + INLINE af_bit_ref(ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>* bv, int index=0): + d_bv(*bv),d_index(index) {} + + INLINE operator bool() const { + return d_bv.V[d_index]; + } + + INLINE af_bit_ref& operator=(unsigned long long val) { + if (val) + d_bv.V.set(d_index); + else + d_bv.V.clear(d_index); + return *this; + } + + template + INLINE af_bit_ref& operator =(const ap_private<_AP_W2,_AP_S2>& val) { + return operator=(val!=0); + } + + INLINE af_bit_ref& operator =(const af_bit_ref<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& val) { + return operator=((unsigned long long)(bool)val); + } + + template + INLINE af_bit_ref operator=(const af_bit_ref<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& val) { + return operator=((unsigned long long)(bool)val); + } + + template + INLINE af_bit_ref& operator = ( const ap_bit_ref<_AP_W2, _AP_S2> &val) { + return operator =((unsigned long long) (bool) val); + } + + template + INLINE af_bit_ref& operator = ( const ap_range_ref<_AP_W2,_AP_S2>& val) { + return operator =((const ap_private<_AP_W2, false>) val); + } + + template + INLINE af_bit_ref& operator= (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& val) { + return operator=((const ap_private<_AP_W2, false>)(val)); + } + + template + INLINE af_bit_ref& operator= (const ap_concat_ref<_AP_W2, _AP_T3, _AP_W3, _AP_T3>& val) { + return operator=((const ap_private<_AP_W2 + _AP_W3, false>)(val)); + } + + template + INLINE ap_concat_ref<1, af_bit_ref, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (ap_private<_AP_W2, _AP_S2>& op) { + return ap_concat_ref<1, af_bit_ref, _AP_W2, + ap_private<_AP_W2, _AP_S2> >(*this, op); + } + + template + INLINE ap_concat_ref<1, af_bit_ref, 1, ap_bit_ref<_AP_W2, _AP_S2> > + operator, (const ap_bit_ref<_AP_W2, _AP_S2> &op) { + return ap_concat_ref<1, af_bit_ref, 1, + ap_bit_ref<_AP_W2, _AP_S2> >(*this, + const_cast& >(op)); + } + + template + INLINE ap_concat_ref<1, af_bit_ref, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > + operator, (const ap_range_ref<_AP_W2, _AP_S2> &op) { + return ap_concat_ref<1, af_bit_ref, _AP_W2, + ap_range_ref<_AP_W2, _AP_S2> >(*this, + const_cast& >(op)); + } + + template + INLINE ap_concat_ref<1, af_bit_ref, _AP_W2 + _AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > + operator, (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &op) { + return ap_concat_ref<1, af_bit_ref, _AP_W2 + _AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(*this, + const_cast& >(op)); + } + + template + INLINE ap_concat_ref<1, af_bit_ref, _AP_W2, + af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &op) { + return ap_concat_ref<1, af_bit_ref, _AP_W2, + af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, + _AP_N2> >(*this, const_cast& >(op)); + } + + template + INLINE ap_concat_ref<1, af_bit_ref, 1, + af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &op) { + return ap_concat_ref<1, af_bit_ref, 1, + af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, + const_cast& >(op)); + } + + template + INLINE bool operator == (const af_bit_ref<_AP_W2, _AP_I2, + _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) { + return get() == op.get(); + } + + template + INLINE bool operator != (const af_bit_ref<_AP_W2, _AP_I2, + _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) { + return get() != op.get(); + } + + INLINE bool operator ~ () const { + bool bit = (d_bv.V)[d_index]; + return bit ? false : true; + } + + INLINE int length() const { + return 1; + } + + INLINE bool get() { + return d_bv.V[d_index]; + } + + INLINE bool get() const { + return d_bv.V[d_index]; + } + + INLINE std::string to_string() const { + return d_bv.V[d_index] ? "1" : "0"; + } +}; + +///Range(slice) reference +//------------------------------------------------------------ +template +struct af_range_ref { +#ifdef _MSC_VER + #pragma warning(disable: 4521 4522) +#endif /* #ifdef _MSC_VER */ + ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &d_bv; + int l_index; + int h_index; + +public: + INLINE af_range_ref(const af_range_ref<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& ref): + d_bv(ref.d_bv), l_index(ref.l_index), h_index(ref.h_index) {} + + INLINE af_range_ref(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>* bv, int h, int l): + d_bv(*bv),l_index(l),h_index(h) { + //if (h < l) + // fprintf(stderr, + //"Warning! The bits selected will be returned in reverse order\n"); + } + + INLINE operator ap_private<_AP_W, false> () const { + if (h_index >= l_index) { + ap_private<_AP_W, false> val(d_bv.V); + ap_private<_AP_W,false> mask(-1); + mask>>=_AP_W-(h_index-l_index+1); + val>>=l_index; + return val&=mask; + } else { + ap_private<_AP_W, false> val = 0; + for (int i=0, j=l_index;j>=0&&j>=h_index;j--,i++) + if ((d_bv.V)[j]) val.set(i); + return val; + } + } + + INLINE operator unsigned long long() const { + return get().to_uint64(); + } + + template + INLINE af_range_ref& operator =(const ap_private<_AP_W2,_AP_S2>& val) { + ap_private<_AP_W, false> vval= ap_private<_AP_W, false>(val); + if (l_index > h_index) { + for (int i=0, j=l_index;j>=0&&j>=h_index;j--,i++) + vval[i]? d_bv.V.set(j):d_bv.V.clear(j); + } else { + ap_private<_AP_W,false> mask(-1); + if (l_index>0) { + mask<<=l_index; + vval<<=l_index; + } + if (h_index<_AP_W-1) { + ap_private<_AP_W,false> mask2(-1); + mask2>>=_AP_W-h_index-1; + mask&=mask2; + vval&=mask2; + } + mask.flip(); + d_bv.V &= mask; + d_bv.V |= vval; + } + return *this; + } + + INLINE af_range_ref& operator = (unsigned long long val) { + const ap_private<_AP_W, false> tmpVal(val); + return operator = (tmpVal); + } + + template + INLINE af_range_ref& operator = + (const ap_concat_ref <_AP_W3, _AP_T3, _AP_W4, _AP_T4>& val) { + const ap_private<_AP_W, false> tmpVal(val); + return operator = (tmpVal); + } + + template + INLINE af_range_ref& operator =(const ap_bit_ref<_AP_W3, _AP_S3>& val) { + const ap_private<_AP_W, false> tmpVal(val); + return operator = (tmpVal); + } + + template + INLINE af_range_ref& operator =(const ap_range_ref<_AP_W3,_AP_S3>& val) { + const ap_private<_AP_W, false> tmpVal(val); + return operator =(tmpVal); + } + + template + INLINE af_range_ref& operator= (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& val) { + const ap_private<_AP_W2, false> tmp= val.get(); + return operator = (tmp); + } + + INLINE af_range_ref& operator= (const af_range_ref<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& val) { + const ap_private<_AP_W, false> tmp= val.get(); + return operator = (tmp); + } + + template + INLINE af_range_ref& operator= (const ap_fixed_base<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& val) { + return operator=(val.to_ap_private()); + } + + template + INLINE bool operator == (const ap_range_ref<_AP_W2, _AP_S2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs==rhs; + } + + template + INLINE bool operator != (const ap_range_ref<_AP_W2, _AP_S2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs!=rhs; + } + + template + INLINE bool operator > (const ap_range_ref<_AP_W2, _AP_S2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs>rhs; + } + + template + INLINE bool operator >= (const ap_range_ref<_AP_W2, _AP_S2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs>=rhs; + } + + template + INLINE bool operator < (const ap_range_ref<_AP_W2, _AP_S2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs + INLINE bool operator <= (const ap_range_ref<_AP_W2, _AP_S2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs<=rhs; + } + + template + INLINE bool operator == (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs==rhs; + } + + template + INLINE bool operator != (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs!=rhs; + } + + template + INLINE bool operator > (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs>rhs; + } + + template + INLINE bool operator >= (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs>=rhs; + } + + template + INLINE bool operator < (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs + INLINE bool operator <= (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs<=rhs; + } + + template + INLINE void set(const ap_private<_AP_W2,false>& val) { + ap_private<_AP_W,_AP_S> vval=val; + if (l_index>h_index) { + for (int i=0, j=l_index;j>=0&&j>=h_index;j--,i++) + vval[i]? d_bv.V.set(j):d_bv.V.clear(j); + } else { + ap_private<_AP_W,_AP_S> mask(-1); + if (l_index>0) { + ap_private<_AP_W,false> mask1(-1); + mask1>>=_AP_W-l_index; + mask1.flip(); + mask=mask1; + //vval&=mask1; + vval<<=l_index; + } + if (h_index<_AP_W-1) { + ap_private<_AP_W,false> mask2(-1); + mask2<<=h_index+1; + mask2.flip(); + mask&=mask2; + vval&=mask2; + } + mask.flip(); + d_bv&=mask; + d_bv|=vval; + } + + } + + INLINE ap_private<_AP_W,false> get() const { + if (h_index val(0); + for (int i=0, j=l_index;j>=0&&j>=h_index;j--,i++) + if ((d_bv.V)[j]) val.set(i); + return val; + } else { + ap_private<_AP_W, false> val = ap_private<_AP_W,false>(d_bv.V); + val>>= l_index; + if (h_index<_AP_W-1) + { + ap_private<_AP_W,false> mask(-1); + mask>>=_AP_W-(h_index-l_index+1); + val&=mask; + } + return val; + } + } + + template + INLINE ap_concat_ref<_AP_W, af_range_ref, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (ap_private<_AP_W2, _AP_S2>& op) { + return ap_concat_ref<_AP_W, af_range_ref, _AP_W2, + ap_private<_AP_W2, _AP_S2> >(*this, op); + } + + template + INLINE ap_concat_ref<_AP_W, af_range_ref, 1, ap_bit_ref<_AP_W2, _AP_S2> > + operator, (const ap_bit_ref<_AP_W2, _AP_S2> &op) { + return ap_concat_ref<_AP_W, af_range_ref, 1, + ap_bit_ref<_AP_W2, _AP_S2> >(*this, + const_cast& >(op)); + } + + template + INLINE ap_concat_ref<_AP_W, af_range_ref, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > + operator, (const ap_range_ref<_AP_W2, _AP_S2> &op) { + return ap_concat_ref<_AP_W, af_range_ref, _AP_W2, + ap_range_ref<_AP_W2, _AP_S2> >(*this, + const_cast& >(op)); + } + + template + INLINE ap_concat_ref<_AP_W, af_range_ref, _AP_W2 + _AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > + operator, (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &op) { + return ap_concat_ref<_AP_W, af_range_ref, _AP_W2 + _AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(*this, + const_cast& >(op)); + } + + template + INLINE ap_concat_ref<_AP_W, af_range_ref, _AP_W2, + af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &op) { + return ap_concat_ref<_AP_W, af_range_ref, _AP_W2, + af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, + const_cast& > (op)); + } + + template + INLINE ap_concat_ref<_AP_W, af_range_ref, 1, + af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &op) { + return ap_concat_ref<_AP_W, af_range_ref, 1, + af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, + const_cast& >(op)); + } + + INLINE int length() const { + return h_index>=l_index?h_index-l_index+1:l_index-h_index+1; + } + + INLINE int to_int() const { + ap_private<_AP_W,false> val=get(); + return val.to_int(); + } + + INLINE unsigned int to_uint() const { + ap_private<_AP_W,false> val=get(); + return val.to_uint(); + } + + INLINE long to_long() const { + ap_private<_AP_W,false> val=get(); + return val.to_long(); + } + + INLINE unsigned long to_ulong() const { + ap_private<_AP_W,false> val=get(); + return val.to_ulong(); + } + + INLINE ap_slong to_int64() const { + ap_private<_AP_W,false> val=get(); + return val.to_int64(); + } + + INLINE ap_ulong to_uint64() const { + ap_private<_AP_W,false> val=get(); + return val.to_uint64(); + } + + INLINE std::string to_string(uint8_t radix) const { + return get().to_string(radix); + } + +}; + +//----------------------------------------------------------------------------- +///ap_fixed_base: AutoPilot fixed point +//----------------------------------------------------------------------------- +template +struct ap_fixed_base { +#ifdef _MSC_VER + #pragma warning(disable: 4521 4522) +#endif /* #ifdef _MSC_VER */ +public: + template friend struct +ap_fixed_base; + template friend struct +af_bit_ref; + + INLINE void overflow_adjust(bool underflow, bool overflow, + bool lD, bool sign) { + if (!overflow && !underflow) return; + switch (_AP_O) { + case AP_WRAP: + if (_AP_N == 0) + return; + if (_AP_S) { + //signed SC_WRAP + //n_bits == 1; + if (_AP_N > 1) { + ap_private<_AP_W, _AP_S> mask(-1); + if (_AP_N >= _AP_W) mask = 0; + else mask.lshr(_AP_N); + if (sign) + V &= mask; + else + V |= ~mask; + } + sign ? V.set(_AP_W - 1) : V.clear(_AP_W - 1); + } else { + //unsigned SC_WRAP + ap_private<_AP_W, _AP_S> mask(-1); + if (_AP_N >= _AP_W) mask = 0; + else mask.lshr(_AP_N); + mask.flip(); + V |= mask; + } + break; + case AP_SAT_ZERO: + V.clear(); + break; + case AP_WRAP_SM: + { + bool Ro = ap_private_ops::get<_AP_W, _AP_S, _AP_W -1>(V); // V[_AP_W -1]; + if (_AP_N == 0) { + if (lD != Ro) { + V.flip(); + lD ? ap_private_ops::set<_AP_W, _AP_S, _AP_W - 1>(V) : + ap_private_ops::clear<_AP_W, _AP_S, _AP_W - 1>(V); + } + } else { + if (_AP_N == 1 && sign != Ro) { + V.flip(); + } else if (_AP_N > 1) { + bool lNo = ap_private_ops::get<_AP_W, _AP_S, _AP_W - _AP_N> (V); // V[_AP_W - _AP_N]; + if (lNo == sign) + V.flip(); + ap_private<_AP_W, false> mask(-1); + if (_AP_N >= _AP_W) mask = 0; + else mask.lshr(_AP_N); + if (sign) + V &= mask; + else + V |= mask.flip(); + sign ? ap_private_ops::set<_AP_W, _AP_S, _AP_W - 1>(V) : ap_private_ops::clear<_AP_W, _AP_S, _AP_W - 1>(V); + } + } + } + break; + default: + if (_AP_S) { + if (overflow) { + V.set(); ap_private_ops::clear<_AP_W, _AP_S, _AP_W-1>(V); + } else if (underflow) { + V.clear(); + ap_private_ops::set<_AP_W, _AP_S, _AP_W-1>(V); + if (_AP_O == AP_SAT_SYM) + ap_private_ops::set<_AP_W, _AP_S, 0>(V); + } + } else { + if (overflow) + V.set(); + else if (underflow) + V.clear(); + } + } + } + + INLINE bool quantization_adjust(bool qb, bool r, bool s) { + bool carry=ap_private_ops::get<_AP_W, _AP_S, _AP_W-1>(V); + switch (_AP_Q) { + case AP_TRN: + return false; + case AP_RND_ZERO: + qb &= s || r; + break; + case AP_RND_MIN_INF: + qb &= r; + break; + case AP_RND_INF: + qb &= !s || r; + break; + case AP_RND_CONV: + qb &= ap_private_ops::get<_AP_W, _AP_S, 0>(V) || r; + break; + case AP_TRN_ZERO: + qb = s && ( qb || r ); + break; + default:; + + } + if (qb) ++V; + //only when old V[_AP_W-1]==1 && new V[_AP_W-1]==0 + return carry && !(ap_private_ops::get<_AP_W, _AP_S, _AP_W-1>(V)); //(!V[_AP_W-1]); + } + + template + struct RType { + enum { + _AP_F=_AP_W-_AP_I, + F2=_AP_W2-_AP_I2, + mult_w = _AP_W+_AP_W2, + mult_i = _AP_I+_AP_I2, + mult_s = _AP_S||_AP_S2, + plus_w = AP_MAX(_AP_I+(_AP_S2&&!_AP_S),_AP_I2+(_AP_S&&!_AP_S2))+1+AP_MAX(_AP_F,F2), + plus_i = AP_MAX(_AP_I+(_AP_S2&&!_AP_S),_AP_I2+(_AP_S&&!_AP_S2))+1, + plus_s = _AP_S||_AP_S2, + minus_w = AP_MAX(_AP_I+(_AP_S2&&!_AP_S),_AP_I2+(_AP_S&&!_AP_S2))+1+AP_MAX(_AP_F,F2), + minus_i = AP_MAX(_AP_I+(_AP_S2&&!_AP_S),_AP_I2+(_AP_S&&!_AP_S2))+1, + minus_s = true, +#ifndef __SC_COMPATIBLE__ + div_w = _AP_W + AP_MAX(_AP_W2 - _AP_I2, 0) + _AP_S2, +#else + div_w = _AP_W + AP_MAX(_AP_W2 - _AP_I2, 0) + _AP_S2 + AP_MAX(_AP_I2, 0), +#endif /* #ifndef __SC_COMPATIBLE__ */ + div_i = _AP_I + (_AP_W2-_AP_I2) + _AP_S2, + div_s = _AP_S||_AP_S2, + logic_w = AP_MAX(_AP_I+(_AP_S2&&!_AP_S),_AP_I2+(_AP_S&&!_AP_S2))+AP_MAX(_AP_F,F2), + logic_i = AP_MAX(_AP_I+(_AP_S2&&!_AP_S),_AP_I2+(_AP_S&&!_AP_S2)), + logic_s = _AP_S||_AP_S2 + }; + + typedef ap_fixed_base mult; + typedef ap_fixed_base plus; + typedef ap_fixed_base minus; + typedef ap_fixed_base logic; + typedef ap_fixed_base div; + typedef ap_fixed_base<_AP_W, _AP_I, _AP_S> arg1; + }; + INLINE void report() { +#if 0 + if (_AP_W > 1024 && _AP_W <= 4096) { + fprintf(stderr, "[W] W=%d is out of bound (1<=W<=1024):" + " for synthesis, please define macro AP_INT_TYPE_EXT(N) to" + " extend the valid range.\n", _AP_W); + } else +#endif /* #if 0 */ + if (_AP_W > MAX_MODE(AP_INT_MAX_W) * 1024) { + fprintf(stderr, "[E] ap_%sfixed<%d, ...>: Bitwidth exceeds the " + "default max value %d. Please use macro " + "AP_INT_MAX_W to set a larger max value.\n", + _AP_S?"":"u", _AP_W, + MAX_MODE(AP_INT_MAX_W) * 1024); + exit(1); + } + } + + /// Constructors. + // ------------------------------------------------------------------------- +#if 0 + #ifdef __SC_COMPATIBLE__ + INLINE ap_fixed_base():V(uint32_t(_AP_W), uint64_t(0)) {} + #else + INLINE ap_fixed_base():V(uint32_t(_AP_W)) {} + #endif /* #ifdef __SC_COMPATIBLE__ */ +#else + INLINE ap_fixed_base():V(0) {} +#endif /* #if 0 */ + // INLINE ap_fixed_base():V() {} + // INLINE explicit ap_fixed_base(const ap_private<_AP_W+_AP_I, _AP_S>& _V):V(_V) {} + INLINE ap_fixed_base(const ap_fixed_base& op):V(op.V) {} + template + INLINE ap_fixed_base(const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op):V(0) { + enum {N2=_AP_W2,_AP_F=_AP_W-_AP_I,F2=_AP_W2-_AP_I2,QUAN_INC=F2>_AP_F && !(_AP_Q==AP_TRN || + (_AP_Q==AP_TRN_ZERO && !_AP_S2))}; + if (!op) return; + bool carry=false; + //handle quantization + enum { sh_amt =(F2>_AP_F)?F2-_AP_F:_AP_F-F2}; + const ap_private<_AP_W2, _AP_S2>& val = op.V; + bool neg_src=val.isNegative(); + if (F2==_AP_F) + V=val; + + else if (F2>_AP_F) { + if (sh_amt >= _AP_W2) + V = neg_src ? -1 : 0; + else + V = _AP_S2?val.ashr(sh_amt):val.lshr(sh_amt); + if (_AP_Q!=AP_TRN && !(_AP_Q==AP_TRN_ZERO && !_AP_S2)) { + bool qb = false; + if (F2-_AP_F>_AP_W2) + qb = neg_src; + else + qb = ap_private_ops::get<_AP_W2, _AP_S2, F2-_AP_F-1>(val); + + bool r=false; + enum { pos3 = F2-_AP_F-2}; + if (pos3>=_AP_W2-1) + r=val!=0; + else if (pos3>=0) + r = (val<<(_AP_W2-1-pos3))!=0; + carry = quantization_adjust(qb,r,neg_src); + } + } else { //no quantization + if (sh_amt < _AP_W) { + V=val; + V <<= sh_amt; + } + } + //hanle overflow/underflow + if ((_AP_O!=AP_WRAP || _AP_N != 0) && + ((!_AP_S && _AP_S2) || _AP_I-_AP_S < + _AP_I2 - _AP_S2 + (QUAN_INC|| (_AP_S2 && + _AP_O==AP_SAT_SYM)))) {//saturation + bool deleted_zeros = _AP_S2?true:!carry, + deleted_ones = true; + bool lD=(_AP_I2>_AP_I && _AP_W2-_AP_I2+_AP_I>=0) && + ap_private_ops::get<_AP_W2, _AP_S2, _AP_W2-_AP_I2+_AP_I>(val); + enum { pos1=F2-_AP_F+_AP_W, pos2=F2-_AP_F+_AP_W+1}; + if (pos1 < _AP_W2) { + bool Range1_all_ones= true; + bool Range1_all_zeros= true; + if (pos1 >= 0) { + enum { __W = (_AP_W2-pos1) > 0 ? (_AP_W2-pos1) : 1 }; + const ap_private<__W, _AP_S2> Range1=ap_private<__W, _AP_S2>(val.lshr(pos1)); + Range1_all_ones=Range1.isAllOnesValue(); + Range1_all_zeros=Range1.isMinValue(); + } else { + Range1_all_ones=false; + Range1_all_zeros=val.isMinValue(); + } + bool Range2_all_ones=true; + if (pos2<_AP_W2 && pos2>=0) { + enum { __W = (_AP_W2-pos2)>0 ? (_AP_W2-pos2) : 1}; + ap_private<__W, true> Range2=ap_private<__W, true>(val.lshr(pos2)); + Range2_all_ones=Range2.isAllOnesValue(); + } else if (pos2<0) + Range2_all_ones=false; + + deleted_zeros=deleted_zeros && (carry?Range1_all_ones:Range1_all_zeros); + deleted_ones=carry?Range2_all_ones&&(F2-_AP_F+_AP_W<0||!lD) + :Range1_all_ones; + neg_src= neg_src&&!(carry && Range1_all_ones); + } else + neg_src = neg_src && V[_AP_W-1]; + + bool neg_trg= V.isNegative(); + bool overflow=(neg_trg||!deleted_zeros) && !val.isNegative(); + bool underflow=(!neg_trg||!deleted_ones)&&neg_src; + //printf("neg_src = %d, neg_trg = %d, deleted_zeros = %d, + // deleted_ones = %d, overflow = %d, underflow = %d\n", + // neg_src, neg_trg, deleted_zeros, deleted_ones, + // overflow, underflow); + if (_AP_O==AP_SAT_SYM && _AP_S2 && _AP_S) + underflow |= neg_src && (_AP_W>1?V.isMinSignedValue():true); + overflow_adjust(underflow, overflow, lD, neg_src); + } + report(); + } + + template + INLINE ap_fixed_base(const volatile ap_fixed_base<_AP_W2,_AP_I2, + _AP_S2,_AP_Q2,_AP_O2, _AP_N2> &op) : V(op.V) { + *this = const_cast&>(op); + } + + template + INLINE ap_fixed_base(const ap_private<_AP_W2,_AP_S2>& op) { + ap_fixed_base<_AP_W2,_AP_W2,_AP_S2> f_op; + f_op.V=op; + *this = f_op; + } + + INLINE ap_fixed_base(bool b) { + *this=(ap_private<1,false>)b; + report(); + } + + INLINE ap_fixed_base(char b) { + *this=(ap_private<8,false>)b; + report(); + } + + INLINE ap_fixed_base(signed char b) { + *this=(ap_private<8,true>)b; + report(); + } + + INLINE ap_fixed_base(unsigned char b) { + *this=(ap_private<8,false>)b; + report(); + } + + INLINE ap_fixed_base(signed short b) { + *this=(ap_private<16,true>)b; + report(); + } + + INLINE ap_fixed_base(unsigned short b) { + *this=(ap_private<16,false>)b; + report(); + } + + INLINE ap_fixed_base(signed int b) { + *this=(ap_private<32,true>)b; + report(); + } + + INLINE ap_fixed_base(unsigned int b) { + *this=(ap_private<32,false>)b; + report(); + } +# if defined __x86_64__ + INLINE ap_fixed_base(signed long b) { + *this=(ap_private<64,true>)b; + report(); + } + + INLINE ap_fixed_base(unsigned long b) { + *this=(ap_private<64,false>)b; + report(); + } +# else + INLINE ap_fixed_base(signed long b) { + *this=(ap_private<32,true>)b; + report(); + } + + INLINE ap_fixed_base(unsigned long b) { + *this=(ap_private<32,false>)b; + report(); + } +# endif + + INLINE ap_fixed_base(ap_slong b) { + *this=(ap_private<64,true>)b; + report(); + } + + INLINE ap_fixed_base(ap_ulong b) { + *this=(ap_private<64,false>)b; + report(); + } + +#if 1 + INLINE ap_fixed_base(const char* val):V(0) { + ap_private<_AP_W, _AP_S> Tmp(val); + V = Tmp; + } + + INLINE ap_fixed_base(const char* val, signed char rd): V(0) { + ap_private<_AP_W, _AP_S> Tmp(val, rd); + V = Tmp; + } + +#endif + + INLINE ap_fixed_base(const std::string& val) { + ap_private<_AP_W, _AP_S> Tmp(val, 2); + V = Tmp; + report(); + } + + template + INLINE ap_fixed_base(const ap_bit_ref<_AP_W2, _AP_S2>& op) { + *this = ((bool)op); + report(); + } + + template + INLINE ap_fixed_base(const ap_range_ref<_AP_W2, _AP_S2>& op) { + *this = ap_private<_AP_W2, _AP_S2>(op); + report(); + } + + template + INLINE ap_fixed_base(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& op) { + *this = ((const ap_private<_AP_W2 + _AP_W3, false>&)(op)); + report(); + } + + template + INLINE ap_fixed_base(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) { + *this = (bool(op)); + report(); + } + + template + INLINE ap_fixed_base(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) { + *this = (ap_private<_AP_W2, false>(op)); + report(); + } + + //helper function + INLINE unsigned long long doubleToRawBits(double pf)const { + union { + unsigned long long __L; + double __D; + }LD; + LD.__D=pf; + return LD.__L; + } + + + INLINE double rawBitsToDouble(unsigned long long pi) const { + union { + unsigned long long __L; + double __D; + }LD; + LD.__L=pi; + return LD.__D; + } + + INLINE float rawBitsToFloat(uint32_t pi) const { + union { + uint32_t __L; + float __D; + }LD; + LD.__L = pi; + return LD.__D; + } + + INLINE ap_fixed_base(double d):V(0) { + if (!d) return; + const bool isneg=d<0; + + const uint64_t ireg=doubleToRawBits(isneg?-d:d); + if ((ireg&0x7fffffffffffffffULL)!=0) { + const int32_t exp=(((ireg)>>DOUBLE_MAN)&0x07ff)-DOUBLE_BIAS; + ap_private man = ireg & DOUBLE_MAN_MASK; + man.clear(DOUBLE_MAN+1); + man.set(DOUBLE_MAN); + if (isneg) { + man.flip(); + man++; + } + + enum {_AP_S2=true, _AP_W2=DOUBLE_MAN+2,_AP_F=_AP_W -_AP_I }; + const int _AP_I2=exp+2; + const int F2=_AP_W2-_AP_I2; + const bool QUAN_INC=F2>_AP_F && !(_AP_Q==AP_TRN || (_AP_Q==AP_TRN_ZERO && + !_AP_S2)); + bool carry=false; + //handle quantization + const unsigned sh_amt=abs(F2-_AP_F); // sh_amt = F2>_AP_F ? F2 -_AP_F : _AP_F-F2; + if (F2==_AP_F ) + V=man; + else if (F2>_AP_F) { + if (sh_amt >= DOUBLE_MAN+2) + V=isneg?-1:0; + else + V=(man>>sh_amt) | ((man & 1ULL<<(DOUBLE_MAN+1)) ? (DOUBLE_MAN_MASK>>(DOUBLE_MAN+2-sh_amt) <<(DOUBLE_MAN+2-sh_amt)):0); + + if (_AP_Q!=AP_TRN && !(_AP_Q==AP_TRN_ZERO && !_AP_S2)) { + const bool qb=((F2-_AP_F > DOUBLE_MAN+2) ? isneg : (man & (1ULL<<(F2-_AP_F-1))) != 0); + const int pos3=F2-_AP_F-2; + const bool r = (pos3>= 0) ? (man << AP_MAX(0, _AP_W2-pos3-1)& DOUBLE_MAN_MASK)!=0 : false; + carry = quantization_adjust(qb,r,isneg); + } + } + else { //no quantization + // V=man; + if (sh_amt < _AP_W) { + V = man; + V <<= sh_amt; + } + } + //handle overflow/underflow + if ((_AP_O != AP_WRAP || _AP_N != 0) && + ((!_AP_S && _AP_S2) || _AP_I-_AP_S < + _AP_I2-_AP_S2+(QUAN_INC|| (_AP_S2 && + _AP_O==AP_SAT_SYM)) )) {// saturation + bool deleted_zeros = _AP_S2?true:!carry, + deleted_ones = true; + bool neg_src; + const bool lD=(_AP_I2>_AP_I) && (_AP_W2-_AP_I2+_AP_I>=0) && (man & (1ULL <<(DOUBLE_MAN+2-_AP_I2+_AP_I))); + int pos1=F2+_AP_W-_AP_F; + if (pos1 < _AP_W2) { + int pos2=pos1+1; + bool Range1_all_ones=true; + bool Range1_all_zeros=true; + if (pos1>=0) { + ap_private<_AP_W,_AP_S> Range1= + ap_private<_AP_W,_AP_S>((man >> pos1) | ((1ULL<<(DOUBLE_MAN+1)&man) ? (DOUBLE_MAN_MASK >> (DOUBLE_MAN+2-pos1) <<(DOUBLE_MAN+2-pos1)):0)); + Range1_all_ones = Range1.isAllOnesValue(); // Range1.isAllOnesValue(); + Range1_all_zeros = Range1.isMinValue(); // Range1.isMinValue(); + } else { + Range1_all_ones=false; + Range1_all_zeros = man==0; // man.isMinValue(); + } + bool Range2_all_ones=true; + if (pos2<_AP_W2 && pos2>=0) { + ap_private<_AP_W, _AP_S> Range2= + ap_private<_AP_W, _AP_S>((man >> pos2) | ((1ULL<<(DOUBLE_MAN+1)&man) ? (DOUBLE_MAN_MASK >> (DOUBLE_MAN+2-pos2) <<(DOUBLE_MAN+2-pos2)):0)); + Range2_all_ones=Range2.isAllOnesValue(); // Range2.isAllOnesValue(); + } else if (pos2<0) + Range2_all_ones=false; + deleted_zeros=deleted_zeros && (carry?Range1_all_ones:Range1_all_zeros); + deleted_ones=carry?Range2_all_ones&&(F2-_AP_F+_AP_W<0||!lD) : Range1_all_ones; + neg_src=isneg&&!(carry&Range1_all_ones); + } else + neg_src = isneg && V[_AP_W -1]; + + const bool neg_trg=V.isNegative(); + const bool overflow=(neg_trg||!deleted_zeros) && !isneg; + bool underflow=(!neg_trg||!deleted_ones)&&neg_src; + //printf("neg_src = %d, neg_trg = %d, deleted_zeros = %d, + // deleted_ones = %d, overflow = %d, underflow = %d\n", + // neg_src, neg_trg, deleted_zeros, deleted_ones, + // overflow, underflow); + if (_AP_O==AP_SAT_SYM && _AP_S2 && _AP_S) + underflow |= neg_src && (_AP_W>1?V.isMinSignedValue():true); + overflow_adjust(underflow,overflow,lD, neg_src); + } + } + report(); + } + + + ///assign operators + //------------------------------------------------------------------------- + + INLINE volatile ap_fixed_base& operator=(const ap_fixed_base<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& op) volatile { + V = op.V; + return *this; + } + + INLINE ap_fixed_base& operator=(const ap_fixed_base<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& op) { + V = op.V; + return *this; + } + + INLINE volatile ap_fixed_base& operator=(const volatile ap_fixed_base<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& op) volatile { + V = op.V; + return *this; + } + + INLINE ap_fixed_base& operator=(const volatile ap_fixed_base<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& op) { + V = op.V; + return *this; + } + + // Set this ap_fixed_base with a bits string. That means the ssdm_int::V + // inside this ap_fixed_base is assigned by bv. + // Note the input parameter should be a fixed-point formatted bit string. + INLINE ap_fixed_base& setBits(unsigned long long bv) { + V=bv; + return *this; + } + + // Return a ap_fixed_base object whose ssdm_int::V is assigned by bv. + // Note the input parameter should be a fixed-point formatted bit string. + static INLINE ap_fixed_base bitsToFixed(unsigned long long bv) { + ap_fixed_base Tmp=bv; + return Tmp; + } + + // Explicit conversion functions to ap_private that captures + // all integer bits (bits are truncated) + INLINE ap_private + to_ap_private(bool Cnative = true) const { + ap_private ret = ap_private ((_AP_I >= 1) ? (_AP_S==true ? V.ashr(AP_MAX(0,_AP_W - _AP_I)) : V.lshr(AP_MAX(0,_AP_W - _AP_I))) : ap_private<_AP_W, _AP_S>(0)); + + if (Cnative) { + bool r = false; + if (_AP_I < _AP_W) { + if (_AP_I > 0) r = !(V.getLoBits(_AP_W - _AP_I).isMinValue()); + else r = !(V.isMinValue()); + } + if (r && V.isNegative()) { // if this is negative integer + ++ret;//ap_private(1,_AP_S); + } + } else { + //Follow OSCI library, conversion from sc_fixed to sc_int + } + return ret; + } + + template + INLINE operator ap_private<_AP_W2,_AP_S2> () const { + return (ap_private<_AP_W2,_AP_S2>)to_ap_private(); + } + + template + INLINE operator ap_private<_AP_W2,_AP_S2,_AP_N2> () const { + return (ap_private<_AP_W2,_AP_S2,_AP_N2>)to_ap_private(); + } + + //Explict conversion function to C built-in integral type + INLINE int to_int() const { + return to_ap_private().to_int(); + } + + INLINE int to_uint() const { + return to_ap_private().to_uint(); + } + + INLINE ap_slong to_int64() const { + return to_ap_private().to_int64(); + } + + INLINE ap_ulong to_uint64() const { + return to_ap_private().to_uint64(); + } + + INLINE double to_double() const { + if (!V) + return 0; + if (_AP_W>64 || (_AP_W - _AP_I) > 0) { + bool isneg = _AP_S && V[_AP_W-1]; + uint64_t res = isneg ? 0x8000000000000000ULL : 0; + ap_private<_AP_W, false> tmp = V; + if (isneg) tmp = -tmp; + int i = _AP_W -1 - tmp.countLeadingZeros(); + int exp = _AP_I-(_AP_W-i); + res|=((uint64_t)(exp+DOUBLE_BIAS))<DOUBLE_MAN)?tmp.lshr(i-DOUBLE_MAN):tmp).to_uint64() & DOUBLE_MAN_MASK; + res |= i 0) { + /* This specialization is disabled. It is giving wrong results in some cases. + bool isneg=V.isNegative(); + double dp = V.get(); + dp /= (1<< (_AP_W - _AP_I)); + return dp;*/ + } else + return double(to_int64()); + } + + INLINE float to_float() const { + uint32_t res=0; + if (V==0) + return 0; + bool isneg=V.isNegative(); + ap_private<_AP_W, _AP_S> tmp=V; + if (isneg) tmp = -tmp; + if (_AP_W-_AP_I>0||_AP_W>64) { + if (isneg) + res=0x80000000; + int i=_AP_W-1; + i-=tmp.countLeadingZeros(); + int exp=_AP_I-(_AP_W-i); + res|=(exp+FLOAT_BIAS)< man = 0; + if (i!=0) { + tmp.clear(i); + if (i>FLOAT_MAN) + man=tmp.lshr(i-FLOAT_MAN); + else + man=tmp; + res |= i < FLOAT_MAN?man.getZExtValue()<<(FLOAT_MAN-i):man.getZExtValue(); + } + } else { + return float(to_int64()); + } + float dp=rawBitsToFloat(res); + return dp; + } + + INLINE operator double () const { + return to_double(); + } +#ifndef __SC_COMPATIBLE__ + INLINE operator float () const { + return to_float(); + } + + INLINE operator char () const { + return (char) to_int(); + } + + INLINE operator unsigned char () const { + return (unsigned char) to_uint(); + } + + INLINE operator short () const { + return (short) to_int(); + } + + INLINE operator unsigned short () const { + return (unsigned short) to_uint(); + } + + INLINE operator int () const { + return to_int(); + } + + INLINE operator unsigned int () const { + return to_uint(); + } +#if 1 +#ifdef __x86_64__ + INLINE operator long () const { + return (long)to_int64(); + } + + INLINE operator unsigned long () const { + return (unsigned long) to_uint64(); + } +#else + INLINE operator long () const { + return to_int64(); + } + + INLINE operator unsigned long () const { + return to_uint64(); + } + +#endif +#endif + INLINE operator unsigned long long () const { + return to_uint64(); + } + + INLINE operator long long () const { + return to_int64(); + } +#endif + + INLINE std::string to_string(uint8_t radix=2, bool sign=false) const; + + INLINE ap_slong bits_to_int64() const { + ap_private res(V); + return (ap_slong) res; + } + + INLINE ap_ulong bits_to_uint64() const { + ap_private res(V); + return (ap_ulong) res; + } + + INLINE int length() const {return _AP_W;} + + // Count the number of zeros from the most significant bit + // to the first one bit. Note this is only for ap_fixed_base whose + // _AP_W <= 64, otherwise will incur assertion. + INLINE int countLeadingZeros() { + return V.countLeadingZeros(); + } + + ///Arithmetic:Binary + //------------------------------------------------------------------------- + template + INLINE typename RType<_AP_W2,_AP_I2,_AP_S2>::mult + operator * (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + typename RType<_AP_W2,_AP_I2,_AP_S2>::mult r; + r.V = V * op2.V; + return r; + } + + template + static INLINE ap_fixed_base multiply(const ap_fixed_base<_AP_W1,_AP_I1,_AP_S1>& op1, const + ap_fixed_base<_AP_W2,_AP_I2,_AP_S2>& op2) { + ap_private<_AP_W+_AP_W2, _AP_S> OP1=op1.V; + ap_private<_AP_W2,_AP_S2> OP2=op2.V; + return OP1*OP2; + } + + template + INLINE typename RType<_AP_W2,_AP_I2,_AP_S2>::div + operator / (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + enum {F2 = _AP_W2-_AP_I2, _W1=AP_MAX(_AP_W + AP_MAX(F2, 0), _AP_W2), + _W2=AP_MAX(_AP_W2,AP_MAX(_AP_W + AP_MAX(F2, 0), _AP_W2))}; + ap_private<_W1, _AP_S> dividend = (ap_private<_W1, _AP_S>(V)) << ((_W1>_AP_W)?F2:0); + ap_private<_W1, _AP_S2> divisior = ap_private<_W2, _AP_S2>(op2.V); + ap_private<_W1, _AP_S> ret = ap_private<_W1,_AP_S> ((_AP_S||_AP_S2) ? dividend.sdiv(divisior): dividend.udiv(divisior)); + typename RType<_AP_W2, _AP_I2, _AP_S2>::div r; + r.V = ret; + return r; + } +#define OP_BIN_AF(Sym, Rty, Width, Sign, Fun) \ + template \ + INLINE typename RType<_AP_W2,_AP_I2,_AP_S2>::Rty \ + operator Sym (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const \ + { \ + enum {_AP_F=_AP_W-_AP_I, F2=_AP_W2-_AP_I2}; \ + typename RType<_AP_W2,_AP_I2,_AP_S2>::Rty r, lhs(*this), rhs(op2); \ + r.V = lhs.V.Fun(rhs.V); \ + return r; \ + } \ + INLINE typename RType<_AP_W,_AP_I,_AP_S>::Rty \ + operator Sym (const ap_fixed_base& op2) const \ + { \ + typename RType<_AP_W,_AP_I,_AP_S>::Rty r; \ + r.V = V Sym op2.V; \ + return r; \ + } \ + + OP_BIN_AF(+, plus, plus_w, plus_s, Add) + OP_BIN_AF(-, minus, minus_w, minus_s, Sub) + +#define OP_LOGIC_BIN_AF(Sym, Rty, Width, Sign) \ + template \ + INLINE typename RType<_AP_W2,_AP_I2,_AP_S2>::Rty \ + operator Sym (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const \ + { \ + typename RType<_AP_W2,_AP_I2,_AP_S2>::Rty r, lhs(*this), rhs(op2); \ + r.V=lhs.V Sym rhs.V; \ + return r; \ + } \ + INLINE typename RType<_AP_W,_AP_I,_AP_S>::Rty \ + operator Sym (const ap_fixed_base& op2) const \ + { \ + typename RType<_AP_W,_AP_I,_AP_S>::Rty r; \ + r.V = V Sym op2.V; \ + return r; \ + } \ + INLINE typename RType<_AP_W,_AP_I,_AP_S>::Rty operator Sym(int op2) const \ + { \ + return V Sym (op2<<(_AP_W - _AP_I)); \ + } + OP_LOGIC_BIN_AF(&, logic, logic_w, logic_s) + OP_LOGIC_BIN_AF(|, logic, logic_w, logic_s) + OP_LOGIC_BIN_AF(^, logic, logic_w, logic_s) + + ///Arithmic : assign + //------------------------------------------------------------------------- +#define OP_ASSIGN_AF(Sym) \ + template \ + INLINE ap_fixed_base& operator Sym##= (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) \ + { \ + *this=operator Sym (op2) ; \ + return *this; \ + } + + OP_ASSIGN_AF(+) + OP_ASSIGN_AF(-) + OP_ASSIGN_AF(&) + OP_ASSIGN_AF(|) + OP_ASSIGN_AF(^) + OP_ASSIGN_AF(*) + OP_ASSIGN_AF(/) + + ///Prefix increment, decrement + //------------------------------------------------------------------------- + INLINE ap_fixed_base& operator ++() { + operator+=(ap_fixed_base<1,1,false>(1)); //SystemC's semantics + return *this; + } + + INLINE ap_fixed_base& operator --() { + operator-=(ap_fixed_base<1,1,false>(1)); //SystemC's semantics + return *this; + } + + //Postfix increment, decrement + //------------------------------------------------------------------------- + INLINE const ap_fixed_base operator ++(int) { + ap_fixed_base t(*this); + operator++(); + return t; + } + + INLINE const ap_fixed_base operator --(int) { + ap_fixed_base t = *this; + operator--(); + return t; + } + + ///Unary arithmetic + //------------------------------------------------------------------------- + INLINE ap_fixed_base operator +() {return *this;} + + INLINE ap_fixed_base<_AP_W + 1, _AP_I + 1, true> operator -() const { + ap_fixed_base<_AP_W + 1, _AP_I + 1, true> Tmp(*this); + Tmp.V = - Tmp.V; + return Tmp; + } + + INLINE ap_fixed_base<_AP_W,_AP_I,true,_AP_Q,_AP_O, _AP_N> getNeg() { + ap_fixed_base<_AP_W,_AP_I,true,_AP_Q,_AP_O, _AP_N> Tmp(*this); + Tmp.V=-Tmp.V; + return Tmp; + } + + ///Not (!) + //------------------------------------------------------------------------- + INLINE bool operator !() const { + return !V; + } + + ///Bitwise complement + //------------------------------------------------------------------------- + INLINE ap_fixed_base<_AP_W, _AP_I, _AP_S> + operator ~() const { + ap_fixed_base<_AP_W, _AP_I, _AP_S> res(*this); + res.V.flip(); + return res; + } + + ///Shift + ///template argument as shift value + template + INLINE ap_fixed_base<_AP_W, _AP_I + _AP_SHIFT, _AP_S> lshift () const { + ap_fixed_base<_AP_W, _AP_I + _AP_SHIFT, _AP_S> r; + r.V = V; + return r; + } + + template + INLINE ap_fixed_base<_AP_W, _AP_I - _AP_SHIFT, _AP_S> rshift () const { + ap_fixed_base<_AP_W, _AP_I - _AP_SHIFT, _AP_S> r; + r.V = V; + return r; + } + + //Because the return type is the type of the the first operand, shift assign + //operators do not carry out any quantization or overflow + //While systemc, shift assigns for sc_fixed/sc_ufixed will result in + //quantization or overflow (depending on the mode of the first operand) + //------------------------------------------------------------------------- + INLINE ap_fixed_base operator << (int sh) const { + ap_fixed_base r; + bool isNeg=(sh&0x80000000) != 0; + sh=isNeg?-sh:sh; + bool shiftoverflow = sh >= _AP_W; + bool NegSrc = V.isNegative(); + if (isNeg) { + if (shiftoverflow) + NegSrc?r.V.set():r.V.clear(); + else + r.V=_AP_S?V.ashr(sh):V.lshr(sh); + } else { + if (shiftoverflow) + r.V.clear(); + else + r.V=V< 1 && sh <= _AP_W) + rb = (V << (_AP_W - sh + 1 )) != 0; + else if (sh > _AP_W) + rb = V != 0; + r.quantization_adjust(qb, rb, NegSrc); + } else if (isNeg == false && _AP_O != AP_WRAP) { + bool allones, allzeros; + if (sh < _AP_W ) { + ap_private<_AP_W, _AP_S > range1 = V.lshr(_AP_W - sh - 1); + allones = range1.isAllOnesValue(); + allzeros = range1.isMinValue(); + } else { + allones = false; + allzeros = V.isMinValue(); + } + bool overflow = !allzeros && !NegSrc; + bool underflow = !allones && NegSrc; + if (_AP_O == AP_SAT_SYM && _AP_S) + underflow |= NegSrc && (_AP_W > 1 ? r.V.isMinSignedValue():true); + bool lD = false; + if ( sh < _AP_W ) lD = V[_AP_W - sh - 1]; + r.overflow_adjust(underflow, overflow, lD, NegSrc); + } +#endif + return r; + } + + template + INLINE ap_fixed_base operator<<(const ap_private<_AP_W2,true>& op2) const { + int sh = op2.to_int(); + return operator << (sh); + } + + INLINE ap_fixed_base operator << (unsigned int sh ) const { + ap_fixed_base r; + bool shiftoverflow = sh >= _AP_W; + r.V = shiftoverflow ? ap_private<_AP_W, _AP_S >(0) : V << sh; + if (sh == 0) return r; +#ifdef __SC_COMPATIBLE__ + bool NegSrc = V.isNegative(); + if (_AP_O != AP_WRAP) { + bool allones, allzeros; + if (sh < _AP_W ) { + ap_private<_AP_W, _AP_S > range1 = V.lshr(_AP_W - sh -1); + allones = range1.isAllOnesValue(); + allzeros = range1.isMinValue(); + } else { + allones = false; + allzeros = V.isMinValue(); + } + bool overflow = !allzeros && !NegSrc; + bool underflow = !allones && NegSrc; + if (_AP_O == AP_SAT_SYM && _AP_S) + underflow |= NegSrc && (_AP_W > 1 ? r.V.isMinSignedValue():true); + bool lD = false; + if ( sh < _AP_W ) lD = V[_AP_W - sh - 1]; + r.overflow_adjust(underflow, overflow, lD, NegSrc); + } +#endif + return r; + } + + template + INLINE ap_fixed_base operator << (const ap_private<_AP_W2,false>& op2) const { + unsigned int sh = op2.to_uint(); + return operator << (sh); + } + + INLINE ap_fixed_base operator >> (int sh) const { + ap_fixed_base r; + bool isNeg=(sh&0x80000000) != 0; + bool NegSrc = V.isNegative(); + sh=isNeg?-sh:sh; + bool shiftoverflow = sh >= _AP_W; + if (isNeg && !shiftoverflow) r.V=V< 1 && sh <= _AP_W) + rb = (V << (_AP_W - sh + 1 )) != 0; + else if (sh > _AP_W) + rb = V != 0; + r.quantization_adjust(qb, rb, NegSrc); + } else if (isNeg == true && _AP_O != AP_WRAP) { + bool allones, allzeros; + if (sh < _AP_W ) { + ap_private<_AP_W, _AP_S > range1 = V.lshr(_AP_W - sh - 1); + allones = range1.isAllOnesValue(); + allzeros = range1.isMinValue(); + } else { + allones = false; + allzeros = V.isMinValue(); + } + bool overflow = !allzeros && !NegSrc; + bool underflow = !allones && NegSrc; + if (_AP_O == AP_SAT_SYM && _AP_S) + underflow |= NegSrc && (_AP_W > 1 ? r.V.isMinSignedValue():true); + bool lD = false; + if ( sh < _AP_W ) lD = V[_AP_W - sh - 1]; + r.overflow_adjust(underflow, overflow, lD, NegSrc); + } +#endif + return r; + } + + template + INLINE ap_fixed_base operator >> (const ap_private<_AP_W2,true>& op2) const { + int sh = op2.to_int(); + return operator >> (sh); + } + + INLINE ap_fixed_base operator >> (unsigned int sh) const { + ap_fixed_base r; + bool NegSrc = V.isNegative(); + bool shiftoverflow = sh >= _AP_W; + if (shiftoverflow) + NegSrc?r.V.set():r.V.clear(); + else + r.V=_AP_S?V.ashr(sh):V.lshr(sh); +#ifdef __SC_COMPATIBLE__ + if (sh == 0) return r; + if (_AP_Q != AP_TRN) { + bool qb = false; + if (sh <= _AP_W) qb = V[sh - 1]; + bool rb = false; + if (sh > 1 && sh <= _AP_W) + rb = (V << (_AP_W - sh + 1 )) != 0; + else if (sh > _AP_W) + rb = V != 0; + r.quantization_adjust(qb, rb, NegSrc); + } +#endif + return r; + } + + template + INLINE ap_fixed_base operator >> (const ap_private<_AP_W2,false>& op2) const { + unsigned int sh = op2.to_uint(); + return operator >> (sh); + } + + ///shift assign + //------------------------------------------------------------------------- +#define OP_AP_SHIFT_AP_ASSIGN_AF(Sym) \ + template \ + INLINE ap_fixed_base& operator Sym##=(const ap_private<_AP_W2,_AP_S2>& op2) \ + { \ + *this=operator Sym (op2); \ + return *this; \ + } + + OP_AP_SHIFT_AP_ASSIGN_AF(<<) + OP_AP_SHIFT_AP_ASSIGN_AF(>>) + + ///Support shift(ap_fixed_base) +#define OP_AP_SHIFT_AF(Sym) \ + template \ + INLINE ap_fixed_base operator Sym (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const \ + { \ + return operator Sym (op2.to_ap_private()); \ + } \ + template \ + INLINE ap_fixed_base& operator Sym##= (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) \ + { \ + *this=operator Sym (op2); \ + return *this; \ + } + + OP_AP_SHIFT_AF(<<) + OP_AP_SHIFT_AF(>>) + + INLINE ap_fixed_base& operator >>= (unsigned int sh) { + *this = operator >> (sh); + return *this; + } + + INLINE ap_fixed_base& operator <<= (unsigned int sh) { + *this = operator << (sh); + return *this; + } + + INLINE ap_fixed_base& operator >>= (int sh) { + *this = operator >> (sh); + return *this; + } + + INLINE ap_fixed_base& operator <<= (int sh) { + *this = operator << (sh); + return *this; + } + + ///Comparisons + //------------------------------------------------------------------------- + template + INLINE bool operator == (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + enum {_AP_F=_AP_W-_AP_I,F2=_AP_W2-_AP_I2, shAmt1 = AP_MAX(F2-_AP_F, 0), shAmt2 = AP_MAX(_AP_F-F2,0), _AP_W3 = (_AP_F==F2) ? AP_MAX(_AP_W,_AP_W2) : AP_MAX(_AP_W+shAmt1, _AP_W2+shAmt2)}; + ap_private<_AP_W3, _AP_S > OP1= ap_private<_AP_W3, _AP_S >(V)< OP2=ap_private<_AP_W3,_AP_S2 >(op2.V)< + INLINE bool operator != (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + return !(*this==op2); + } + + template + INLINE bool operator > (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + enum {_AP_F=_AP_W-_AP_I,F2=_AP_W2-_AP_I2, shAmt1 = AP_MAX(F2-_AP_F, 0), shAmt2 = AP_MAX(_AP_F-F2,0), _AP_W3 = (_AP_F==F2) ? AP_MAX(_AP_W,_AP_W2) : AP_MAX(_AP_W+shAmt1, _AP_W2+shAmt2)}; + ap_private<_AP_W3, _AP_S > OP1= ap_private<_AP_W3, _AP_S >(V)< OP2=ap_private<_AP_W3,_AP_S2 >(op2.V)< + INLINE bool operator <= (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + return !(*this>op2); + } + + template + INLINE bool operator < (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + enum {_AP_F=_AP_W-_AP_I,F2=_AP_W2-_AP_I2, shAmt1 = AP_MAX(F2-_AP_F, 0), shAmt2 = AP_MAX(_AP_F-F2,0), _AP_W3 = (_AP_F==F2) ? AP_MAX(_AP_W,_AP_W2) : AP_MAX(_AP_W+shAmt1, _AP_W2+shAmt2)}; + ap_private<_AP_W3, _AP_S > OP1= ap_private<_AP_W3, _AP_S >(V)< OP2=ap_private<_AP_W3,_AP_S2 >(op2.V)< + INLINE bool operator >= (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + return !(*this) + DOUBLE_CMP_AF(>=) + DOUBLE_CMP_AF(<) + DOUBLE_CMP_AF(<=) + + // Bit and Slice Select + INLINE af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N> operator [] (unsigned int index) { + assert(index<_AP_W&&"Attemping to read bit beyond MSB"); + return af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>(this, index); + } + + INLINE af_bit_ref<_AP_W, _AP_I,_AP_S,_AP_Q,_AP_O, _AP_N> bit(unsigned int index) { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>(this, index); + } + + template + INLINE af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N> bit (const ap_private<_AP_W2,_AP_S2>& index) { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>(this, index.to_int()); + } + + INLINE bool bit (unsigned int index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return V[index]; + } + + INLINE bool operator [] (unsigned int index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return V[index]; + } + + template + INLINE bool bit (const ap_private<_AP_W2, _AP_S2>& index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return V[index.to_uint()]; + } + + template + INLINE bool operator [] (const ap_private<_AP_W2, _AP_S2>& index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return V[index.to_uint()]; + } + + INLINE af_bit_ref<_AP_W, _AP_I,_AP_S,_AP_Q,_AP_O, _AP_N> get_bit(int index) { + assert(index < _AP_I && "Attempting to read bit beyond MSB"); + assert(index >= _AP_I - _AP_W&& "Attempting to read bit beyond MSB"); + return af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>(this, index + _AP_W - _AP_I); + } + + template + INLINE af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N> get_bit (const ap_private<_AP_W2, true>& index) { + assert(index >= _AP_I - _AP_W && "Attempting to read bit with negative index"); + assert(index < _AP_I && "Attempting to read bit beyond MSB"); + return af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>(this, index.to_int() + _AP_W - _AP_I); + } + + INLINE bool get_bit (int index) const { + assert(index >= _AP_I - _AP_W && "Attempting to read bit with negative index"); + assert(index < _AP_I && "Attempting to read bit beyond MSB"); + return V[index + _AP_W - _AP_I]; + } + + template + INLINE bool get_bit (const ap_private<_AP_W2, true>& index) const { + assert(index >= _AP_I - _AP_W && "Attempting to read bit with negative index"); + assert(index < _AP_I && "Attempting to read bit beyond MSB"); + return V[index.to_int() + _AP_W - _AP_I]; + } + + INLINE af_range_ref<_AP_W,_AP_I,_AP_S, _AP_Q, _AP_O, _AP_N> + range(int Hi, int Lo) { + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>(this, Hi, Lo); + } + + INLINE af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> + operator () (int Hi, int Lo) { + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>(this, Hi, Lo); + } + + INLINE af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> + range(int Hi, int Lo) const { + assert((Hi < _AP_W) && (Lo < _AP_W) &&"Out of bounds in range()"); + return af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>(const_cast(this), Hi, Lo); + } + + INLINE af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> + operator () (int Hi, int Lo) const { + return this->range(Hi, Lo); + } + + template + INLINE af_range_ref<_AP_W,_AP_I,_AP_S, _AP_Q, _AP_O, _AP_N> + range(const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>(this, Hi, Lo); + } + + template + INLINE af_range_ref<_AP_W,_AP_I,_AP_S, _AP_Q, _AP_O, _AP_N> + operator () (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>(this, Hi, Lo); + } + + template + INLINE af_range_ref<_AP_W,_AP_I,_AP_S, _AP_Q, _AP_O, _AP_N> + range(const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) const { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>(const_cast< + ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>*>(this), + Hi, Lo); + } + + template + INLINE af_range_ref<_AP_W,_AP_I,_AP_S, _AP_Q, _AP_O, _AP_N> + operator () (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) const { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + return this->range(Hi, Lo); + } + + INLINE af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> + range() { + return this->range(_AP_W - 1, 0); + } + + INLINE af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> + range() const { + return this->range(_AP_W - 1, 0); + } + + INLINE bool is_zero () const { + return V.isMinValue(); + } + + INLINE bool is_neg () const { + if (V.isNegative()) + return true; + return false; + } + + INLINE int wl () const { + return _AP_W; + } + + INLINE int iwl () const { + return _AP_I; + } + + INLINE ap_q_mode q_mode () const { + return _AP_Q; + } + + INLINE ap_o_mode o_mode () const { + return _AP_O; + } + + INLINE int n_bits () const { + return 0; + } + + //private: +public: + ap_private<_AP_W, _AP_S> V; +}; + +template +std::string ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>::to_string( + uint8_t radix, bool sign) const { + std::string str; + str.clear(); + char step; + std::string prefix; + switch (radix) { + case 2 : prefix = "0b"; step = 1; break; + case 8 : prefix = "0o"; step = 3; break; + case 16 : prefix = "0x"; step = 4; break; + default : break; + } + if (_AP_W <= _AP_I) + str = this->to_ap_private().to_string(radix, + radix == 10 ? _AP_S : sign); + else { + if (radix == 10) { + bool isNeg = _AP_S && V.isNegative(); + if (_AP_I > 0) { + ap_private int_part(0); + int_part = this->to_ap_private(); + str += int_part.to_string(radix, false); + } else { + if (isNeg) str += '-'; + } + ap_fixed_base<_AP_W, _AP_I, _AP_S> tmp(*this); + if (isNeg && _AP_I <= 0) tmp = -tmp; + ap_fixed_base<_AP_W - AP_MIN(_AP_I, 0), 0, false> frac_part = tmp; + if (frac_part == 0) return str; + str += "."; + while (frac_part != 0) { + char digit = (frac_part * radix).to_ap_private(); + str += static_cast(digit + '0'); + frac_part *= radix; + } + } else { + if (_AP_I > 0) { + for (signed i = _AP_W - _AP_I; i < _AP_W; i += step) { + + char digit = (char)(this->range(AP_MIN(i + step - 1, _AP_W - 1), i)); + str = (digit < 10 ? static_cast(digit + '0') : + static_cast(digit - 10 + 'a')) + str; + } + } + str += '.'; + ap_fixed_base tmp(*this); + for (signed i = _AP_W - _AP_I - 1; i >= 0; i -= step) { + char digit = (char)(tmp.range(i, AP_MAX(0, i - step + 1))); + str += digit < 10 ? static_cast(digit + '0') : + static_cast(digit - 10 + 'a'); + } + } + } + str = prefix + str; + return str; +} + +template +INLINE void b_not(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op) { + ret.V = op.V; + ret.V.flip(); +} + +template +INLINE void b_and(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op1, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op2) { + ret.V = op1.V & op2.V; +} + +template +INLINE void b_or(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op1, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op2) { + ret.V = op1.V | op2.V; +} + +template +INLINE void b_xor(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op1, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op2) { + ret.V = op1.V ^ op2.V; +} + +template +INLINE void neg(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) { + ap_fixed_base<_AP_W2+!_AP_S2, _AP_I2+!_AP_S2, true, _AP_Q2, _AP_O2, _AP_N2> Tmp; + Tmp.V = - op.V; + ret = Tmp; +} + +template +INLINE void neg(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op) { + ret.V = -op.V; +} + +template +INLINE void lshift(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op, + int i) { + ap_fixed_base<_AP_W2 - _AP_I2 + AP_MAX(_AP_I, _AP_I2), AP_MAX(_AP_I, _AP_I2), _AP_S2, _AP_Q2, _AP_O2, _AP_N2> Tmp; + Tmp = op; + Tmp.V <<= i; + ret = Tmp; +} + +template +INLINE void lshift(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op, + int i) { + ret.V = op.V << i; +} + +template +INLINE void rshift(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op, + int i) { + ap_fixed_base<_AP_I2 + AP_MAX(_AP_W - _AP_I, _AP_W2 - _AP_I2), _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> Tmp; + Tmp = op; + Tmp.V = _AP_S2 ? Tmp.V.ashr(i): Tmp.V.lshr(i); + ret = Tmp; +} + +template +INLINE void rshift(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op, + int i) { + ret.V = _AP_S ? op.V.ashr(i): op.V.lshr(i); +} + +#define AF_CTOR_SPEC_BASE(_AP_W,_AP_S,C_TYPE) \ + template<> INLINE ap_fixed_base<_AP_W,_AP_W,_AP_S,AP_TRN,AP_WRAP>::ap_fixed_base(C_TYPE i_op):V(i_op) \ + { \ + } + +#define AF_CTOR_SPEC(__W,C_TYPE) \ + AF_CTOR_SPEC_BASE(__W,true,C_TYPE) \ + AF_CTOR_SPEC_BASE(__W,false,C_TYPE) + +AF_CTOR_SPEC(1,bool) +AF_CTOR_SPEC(8, signed char) +AF_CTOR_SPEC(8, unsigned char) +AF_CTOR_SPEC(16, signed short) +AF_CTOR_SPEC(16, unsigned short) +AF_CTOR_SPEC(32, signed int) +AF_CTOR_SPEC(32, unsigned int) +AF_CTOR_SPEC(64, ap_slong) +AF_CTOR_SPEC(64, ap_ulong) + +///Output streaming +//----------------------------------------------------------------------------- +template +INLINE std::ostream& +operator <<(std::ostream& os, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& x) { + os << x.to_double(); + return os; +} + +///Input streaming +//----------------------------------------------------------------------------- +template +INLINE std::istream& +operator >> (std::istream& os, ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& x) { + double d; + os >> d; + x = ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>(x); + return os; +} + +template +INLINE void print(const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& x) { + ap_private<_AP_W,_AP_S> data=x.V; + if (_AP_I>0) { + const ap_private<_AP_I,_AP_S> p1=data>>(_AP_W-_AP_I); + print(p1); + + } else + printf("0"); + printf("."); + if (_AP_I<_AP_W) { + const ap_private<_AP_W-_AP_I,false> p2=data; + print(p2,false); + } +} + +///Operators mixing Integers with ap_fixed_base +//----------------------------------------------------------------------------- +#if 1 +#define AF_BIN_OP_WITH_INT_SF(BIN_OP,C_TYPE,_AP_W2,_AP_S2,RTYPE) \ + template \ + INLINE typename ap_fixed_base<_AP_W,_AP_I,_AP_S>::template RType<_AP_W2,_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP (const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) \ + { \ + return op.operator BIN_OP(ap_private<_AP_W2,_AP_S2>(i_op)); \ + } +#define AF_BIN_OP_WITH_INT(BIN_OP, C_TYPE, _AP_W2,_AP_S2,RTYPE) \ + template \ + INLINE typename ap_fixed_base<_AP_W,_AP_I,_AP_S>::template RType<_AP_W2,_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP (const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) \ + { \ + return op.operator BIN_OP (ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op)); \ + } \ + \ + template \ + INLINE typename ap_fixed_base<_AP_W,_AP_I,_AP_S>::template RType<_AP_W2,_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP (C_TYPE i_op, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op) \ + { \ + return ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op).operator BIN_OP (op); \ + } + +#else +#define AF_BIN_OP_WITH_INT_SF(BIN_OP,C_TYPE,_AP_W2,_AP_S2,RTYPE) \ + template \ + INLINE typename ap_fixed_base<_AP_W,_AP_I,_AP_S>::template RType<_AP_W2,_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP (const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) \ + { \ + return op BIN_OP (i_op); \ + } +#define AF_BIN_OP_WITH_INT(BIN_OP, C_TYPE, _AP_W2,_AP_S2,RTYPE) \ + template \ + INLINE typename ap_fixed_base<_AP_W,_AP_I,_AP_S>::template RType<_AP_W2,_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP (const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) \ + { \ + return op.V BIN_OP (i_op<<(_AP_W-_AP_I)); \ + } \ + \ + \ + template \ + INLINE typename ap_fixed_base<_AP_W,_AP_I,_AP_S>::template RType<_AP_W2,_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP (C_TYPE i_op, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op) \ + { \ + return ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op).operator BIN_OP (op); \ + } + +#endif +#if 1 +#define AF_REL_OP_WITH_INT(REL_OP, C_TYPE, _AP_W2,_AP_S2) \ + template \ + INLINE bool operator REL_OP (const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) \ + { \ + return op.operator REL_OP (ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op)); \ + } \ + \ + \ + template \ + INLINE bool operator REL_OP (C_TYPE i_op, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op) \ + { \ + return ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op).operator REL_OP (op); \ + } +#else +#define AF_REL_OP_WITH_INT(REL_OP, C_TYPE, _AP_W2,_AP_S2) \ + template \ + INLINE bool operator REL_OP (const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) \ + { \ + return op.V.operator REL_OP (i_op<<(_AP_W-_AP_I)); \ + } \ + \ + \ + template \ + INLINE bool operator REL_OP (C_TYPE i_op, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op) \ + { \ + return (i_op<<(_AP_W-_AP_I)) REL_OP (op.V.VAL); \ + } +#endif +#if 1 +#define AF_ASSIGN_OP_WITH_INT(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& operator ASSIGN_OP ( ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) { \ + return op.operator ASSIGN_OP (ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op)); \ + } +#define AF_ASSIGN_OP_WITH_INT_SF(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& operator ASSIGN_OP ( ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) { \ + return op.operator ASSIGN_OP (ap_private<_AP_W2,_AP_S2>(i_op)); \ + } +#else +#define AF_ASSIGN_OP_WITH_INT(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& operator ASSIGN_OP ( ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) { \ + return op.V.operator ASSIGN_OP (i_op); \ + } +#define AF_ASSIGN_OP_WITH_INT_SF(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& operator ASSIGN_OP ( ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) { \ + return op.V.operator ASSIGN_OP (i_op); \ + } +#endif + +#define AF_OPS_WITH_INT(C_TYPE, WI, SI) \ + AF_BIN_OP_WITH_INT(+, C_TYPE, WI, SI, plus) \ + AF_BIN_OP_WITH_INT(-, C_TYPE, WI, SI, minus) \ + AF_BIN_OP_WITH_INT(*, C_TYPE, WI, SI, mult) \ + AF_BIN_OP_WITH_INT(/, C_TYPE, WI, SI, div) \ + AF_BIN_OP_WITH_INT_SF(>>, C_TYPE, WI, SI, arg1) \ + AF_BIN_OP_WITH_INT_SF(<<, C_TYPE, WI, SI, arg1) \ + AF_BIN_OP_WITH_INT(&, C_TYPE, WI, SI, logic) \ + AF_BIN_OP_WITH_INT(|, C_TYPE, WI, SI, logic) \ + AF_BIN_OP_WITH_INT(^, C_TYPE, WI, SI, logic) \ + \ + AF_REL_OP_WITH_INT(==, C_TYPE, WI, SI) \ + AF_REL_OP_WITH_INT(!=, C_TYPE, WI, SI) \ + AF_REL_OP_WITH_INT(>, C_TYPE, WI, SI) \ + AF_REL_OP_WITH_INT(>=, C_TYPE, WI, SI) \ + AF_REL_OP_WITH_INT(<, C_TYPE, WI, SI) \ + AF_REL_OP_WITH_INT(<=, C_TYPE, WI, SI) \ + \ + AF_ASSIGN_OP_WITH_INT(+=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT(-=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT(*=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT(/=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT_SF(>>=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT_SF(<<=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT(&=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT(|=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT(^=, C_TYPE, WI, SI) + +AF_OPS_WITH_INT(bool, 1, false) +AF_OPS_WITH_INT(char, 8, true) +AF_OPS_WITH_INT(signed char, 8, true) +AF_OPS_WITH_INT(unsigned char, 8, false) +AF_OPS_WITH_INT(short, 16, true) +AF_OPS_WITH_INT(unsigned short, 16, false) +AF_OPS_WITH_INT(int, 32, true) +AF_OPS_WITH_INT(unsigned int, 32, false) +# if defined __x86_64__ +AF_OPS_WITH_INT(long, 64, true) +AF_OPS_WITH_INT(unsigned long, 64, false) +# else +AF_OPS_WITH_INT(long, 32, true) +AF_OPS_WITH_INT(unsigned long, 32, false) +# endif +AF_OPS_WITH_INT(ap_slong, 64, true) +AF_OPS_WITH_INT(ap_ulong, 64, false) + +#define AF_BIN_OP_WITH_AP_INT(BIN_OP, RTYPE) \ + template \ + INLINE typename ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>::template RType<_AP_W,_AP_I,_AP_S>::RTYPE \ + operator BIN_OP ( const ap_private<_AP_W2,_AP_S2>& i_op, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op) { \ + return ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op).operator BIN_OP (op); \ + } \ + template \ + INLINE typename ap_fixed_base<_AP_W,_AP_I,_AP_S>::template RType<_AP_W2,_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP ( const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, const ap_private<_AP_W2,_AP_S2>& i_op) { \ + return op.operator BIN_OP (ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op)); \ + } + +#define AF_REL_OP_WITH_AP_INT(REL_OP) \ + template \ + INLINE bool operator REL_OP ( const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, const ap_private<_AP_W2,_AP_S2>& i_op) { \ + return op.operator REL_OP ( ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op)); \ + } \ + template \ + INLINE bool operator REL_OP ( const ap_private<_AP_W2,_AP_S2>& i_op, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op) { \ + return ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op).operator REL_OP (op); \ + } + +#define AF_ASSIGN_OP_WITH_AP_INT(ASSIGN_OP) \ + template \ + INLINE ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& operator ASSIGN_OP ( ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, const ap_private<_AP_W2,_AP_S2>& i_op) { \ + return op.operator ASSIGN_OP (ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op)); \ + } \ + template \ + INLINE ap_private<_AP_W2,_AP_S2>& operator ASSIGN_OP ( ap_private<_AP_W2,_AP_S2>& i_op, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op) { \ + return i_op.operator ASSIGN_OP (op.to_ap_private()); \ + } + +AF_BIN_OP_WITH_AP_INT(+, plus) +AF_BIN_OP_WITH_AP_INT(-, minus) +AF_BIN_OP_WITH_AP_INT(*, mult) +AF_BIN_OP_WITH_AP_INT(/, div) +AF_BIN_OP_WITH_AP_INT(&, logic) +AF_BIN_OP_WITH_AP_INT(|, logic) +AF_BIN_OP_WITH_AP_INT(^, logic) + +AF_REL_OP_WITH_AP_INT(==) +AF_REL_OP_WITH_AP_INT(!=) +AF_REL_OP_WITH_AP_INT(>) +AF_REL_OP_WITH_AP_INT(>=) +AF_REL_OP_WITH_AP_INT(<) +AF_REL_OP_WITH_AP_INT(<=) + +AF_ASSIGN_OP_WITH_AP_INT(+=) +AF_ASSIGN_OP_WITH_AP_INT(-=) +AF_ASSIGN_OP_WITH_AP_INT(*=) +AF_ASSIGN_OP_WITH_AP_INT(/=) +AF_ASSIGN_OP_WITH_AP_INT(&=) +AF_ASSIGN_OP_WITH_AP_INT(|=) +AF_ASSIGN_OP_WITH_AP_INT(^=) + +#define AF_REF_REL_OP_MIX_INT(REL_OP, C_TYPE, _AP_W2, _AP_S2) \ +template \ + INLINE bool operator REL_OP ( const af_range_ref<_AP_W,_AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op, C_TYPE op2) { \ + return (ap_private<_AP_W, false>(op)).operator REL_OP (ap_private<_AP_W2,_AP_S2>(op2)); \ + } \ +template \ + INLINE bool operator REL_OP ( C_TYPE op2, const af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op) { \ + return ap_private<_AP_W2,_AP_S2>(op2).operator REL_OP (ap_private<_AP_W, false>(op)); \ + } \ +template \ + INLINE bool operator REL_OP ( const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op, C_TYPE op2) { \ + return (bool(op)) REL_OP op2; \ + } \ +template \ + INLINE bool operator REL_OP ( C_TYPE op2, const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op) { \ + return op2 REL_OP (bool(op)); \ + } + +#define AF_REF_REL_MIX_INT(C_TYPE, _AP_WI, _AP_SI) \ +AF_REF_REL_OP_MIX_INT(>, C_TYPE, _AP_WI, _AP_SI) \ +AF_REF_REL_OP_MIX_INT(<, C_TYPE, _AP_WI, _AP_SI) \ +AF_REF_REL_OP_MIX_INT(>=, C_TYPE, _AP_WI, _AP_SI) \ +AF_REF_REL_OP_MIX_INT(<=, C_TYPE, _AP_WI, _AP_SI) \ +AF_REF_REL_OP_MIX_INT(==, C_TYPE, _AP_WI, _AP_SI) \ +AF_REF_REL_OP_MIX_INT(!=, C_TYPE, _AP_WI, _AP_SI) + +AF_REF_REL_MIX_INT(bool, 1, false) +AF_REF_REL_MIX_INT(char, 8, true) +AF_REF_REL_MIX_INT(signed char, 8, true) +AF_REF_REL_MIX_INT(unsigned char, 8, false) +AF_REF_REL_MIX_INT(short, 16, true) +AF_REF_REL_MIX_INT(unsigned short, 16, false) +AF_REF_REL_MIX_INT(int, 32, true) +AF_REF_REL_MIX_INT(unsigned int, 32, false) +# if defined __x86_64__ +AF_REF_REL_MIX_INT(long, 64, true) +AF_REF_REL_MIX_INT(unsigned long, 64, false) +# else +AF_REF_REL_MIX_INT(long, 32, true) +AF_REF_REL_MIX_INT(unsigned long, 32, false) +# endif +AF_REF_REL_MIX_INT(ap_slong, 64, true) +AF_REF_REL_MIX_INT(ap_ulong, 64, false) + +#define AF_REF_REL_OP_AP_INT(REL_OP) \ +template \ + INLINE bool operator REL_OP ( const af_range_ref<_AP_W,_AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op, const ap_private<_AP_W2, _AP_S> &op2) { \ + return (ap_private<_AP_W, false>(op)).operator REL_OP (op2); \ + } \ +template \ + INLINE bool operator REL_OP (const ap_private<_AP_W2, _AP_S2> &op2, const af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op) { \ + return op2.operator REL_OP (ap_private<_AP_W, false>(op)); \ + } \ +template \ + INLINE bool operator REL_OP ( const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op, const ap_private<_AP_W2, _AP_S2> &op2) { \ + return (ap_private<1, false>(op)).operator REL_OP (op2); \ + } \ +template \ + INLINE bool operator REL_OP ( const ap_private<_AP_W2, _AP_S2> &op2, const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op) { \ + return op2.operator REL_OP (ap_private<1,false>(op)); \ + } + +AF_REF_REL_OP_AP_INT(>) +AF_REF_REL_OP_AP_INT(<) +AF_REF_REL_OP_AP_INT(>=) +AF_REF_REL_OP_AP_INT(<=) +AF_REF_REL_OP_AP_INT(==) +AF_REF_REL_OP_AP_INT(!=) + +// Relational Operators with double +template +INLINE bool operator == ( double op1, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op2) { + return op2.operator == (op1); +} + +template +INLINE bool operator != ( double op1, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op2) { + return op2.operator != (op1); +} + +template +INLINE bool operator > ( double op1, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op2) { + return op2.operator < (op1); +} + +template +INLINE bool operator >= ( double op1, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op2) { + return op2.operator <= (op1); +} + +template +INLINE bool operator < ( double op1, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op2) { + return op2.operator > (op1); +} + +template +INLINE bool operator <= ( double op1, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op2) { + return op2.operator >= (op1); +} + +#endif /* #ifndef __AESL_GCC_AP_FIXED_H__ */ \ No newline at end of file diff --git a/hls_2018/router_02/etc/ap_int_sim.h b/hls_2018/router_02/etc/ap_int_sim.h new file mode 100755 index 0000000..887ccd8 --- /dev/null +++ b/hls_2018/router_02/etc/ap_int_sim.h @@ -0,0 +1,1629 @@ +/* + * Copyright 2012 Xilinx, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __AESL_GCC_AP_INT_H__ +#define __AESL_GCC_AP_INT_H__ + +#ifndef __cplusplus +#error C++ is required to include this header file +#endif /* #ifndef __cplusplus */ + +#undef _AP_DEBUG_ +#include +#include + +// for safety +#if (defined(_AP_N)|| defined(_AP_C)) +#error One or more of the following is defined: _AP_N, _AP_C. Definition conflicts with their usage as template parameters. +#endif /* #if (defined(_AP_N)|| defined(_AP_C)) */ + +// for safety +#if (defined(_AP_W) || defined(_AP_I) || defined(_AP_S) || defined(_AP_Q) || defined(_AP_O) || defined(_AP_W2) || defined(_AP_I2) || defined(_AP_S2) || defined(_AP_Q2) || defined(_AP_O2)) +#error One or more of the following is defined: _AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2. Definition conflicts with their usage as template parameters. +#endif /* #if (defined(_AP_W) || defined(_AP_I) || defined(_AP_S) || defined(_AP_Q) || defined(_AP_O) || defined(_AP_W2) || defined(_AP_I2) || defined(_AP_S2) || defined(_AP_Q2) || defined(_AP_O2)) */ + +//for safety +#if (defined(_AP_W3) || defined(_AP_S3) || defined(_AP_W4) || defined(_AP_S4)) +#error One or more of the following is defined: _AP_W3, _AP_S3, _AP_W4,_AP_S4. Definition conflicts with their usage as template parameters. +#endif /* #if (defined(_AP_W3) || defined(_AP_S3) || defined(_AP_W4) || defined(_AP_S4)) */ + +//for safety +#if (defined(_AP_W1) || defined(_AP_S1) || defined(_AP_I1) || defined(_AP_T) || defined(_AP_T1) || defined(_AP_T2) || defined(_AP_T3) || defined(_AP_T4)) +#error One or more of the following is defined: _AP_W1, _AP_S1, _AP_I1, _AP_T, _AP_T1, _AP_T2, _AP_T3, _AP_T4. Definition conflicts with their usage as template parameters. +#endif /* #if (defined(_AP_W1) || defined(_AP_S1) || defined(_AP_I1) || defined(_AP_T) || defined(_AP_T1) || defined(_AP_T2) || defined(_AP_T3) || defined(_AP_T4)) */ + +#define __AESL_APDT_IN_SCFLOW__ +#ifndef __AESL_APDT_IN_SCFLOW__ + #include "etc/ap_private.h" +#else + #include "../etc/ap_private.h" +#endif /* #ifndef __AESL_APDT_IN_SCFLOW__ */ + +#ifdef _AP_DEBUG_ + #define AP_DEBUG(s) s +#else + #define AP_DEBUG(s) +#endif /* #ifdef _AP_DEBUG_ */ + +#ifndef __SIMULATION__ + #define __SIMULATION__ +#endif /* #ifndef __SIMULATION__ */ + +#if !(defined SYSTEMC_H) && !(defined SYSTEMC_INCLUDED) + #ifndef SC_TRN + #define SC_TRN AP_TRN + #endif /* #ifndef SC_TRN */ + #ifndef SC_RND + #define SC_RND AP_RND + #endif /* #ifndef SC_RND */ + #ifndef SC_TRN_ZERO + #define SC_TRN_ZERO AP_TRN_ZERO + #endif /* #ifndef SC_TRN_ZERO */ + #ifndef SC_RND_ZERO + #define SC_RND_ZERO AP_RND_ZERO + #endif /* #ifndef SC_RND_ZERO */ + #ifndef SC_RND_INF + #define SC_RND_INF AP_RND_INF + #endif /* #ifndef SC_RND_INF */ + #ifndef SC_RND_MIN_INF + #define SC_RND_MIN_INF AP_RND_MIN_INF + #endif /* #ifndef SC_RND_MIN_INF */ + #ifndef SC_RND_CONV + #define SC_RND_CONV AP_RND_CONV + #endif /* #ifndef SC_RND_CONV */ + #ifndef SC_WRAP + #define SC_WRAP AP_WRAP + #endif /* #ifndef SC_WRAP */ + #ifndef SC_SAT + #define SC_SAT AP_SAT + #endif /* #ifndef SC_SAT */ + #ifndef SC_SAT_ZERO + #define SC_SAT_ZERO AP_SAT_ZERO + #endif /* #ifndef SC_SAT_ZERO */ + #ifndef SC_SAT_SYM + #define SC_SAT_SYM AP_SAT_SYM + #endif /* #ifndef SC_SAT_SYM */ + #ifndef SC_WRAP_SM + #define SC_WRAP_SM AP_WRAP_SM + #endif /* #ifndef SC_WRAP_SM */ + #ifndef SC_BIN + #define SC_BIN AP_BIN + #endif /* #ifndef SC_BIN */ + #ifndef SC_OCT + #define SC_OCT AP_OCT + #endif /* #ifndef SC_OCT */ + #ifndef SC_DEC + #define SC_DEC AP_DEC + #endif /* #ifndef SC_DEC */ + #ifndef SC_HEX + #define SC_HEX AP_HEX + #endif /* #ifndef SC_HEX */ +#endif /* #if !(defined SYSTEMC_H) && !(defined SYSTEMC_INCLUDED) */ +#ifndef AP_INT_MAX_W +#define AP_INT_MAX_W 1024 +#endif +#define BIT_WIDTH_UPPER_LIMIT (1 << 15) +#if AP_INT_MAX_W > BIT_WIDTH_UPPER_LIMIT +#error "Bitwidth exceeds 32768 (1 << 15), the maximum allowed value" +#endif +#define MAX_MODE(BITS) ((BITS + 1023) / 1024) + +///Forward declaration +template struct ap_range_ref; +template struct ap_bit_ref; + +template struct ap_fixed_base; +template struct af_range_ref; +template struct af_bit_ref; +template class ap_uint; + +enum { + AP_BIN = 2, + AP_OCT = 8, + AP_DEC = 10, + AP_HEX = 16 +}; + +///Why to use reference? +///Because we will operate the original object indirectly by operating the +///result object directly after concating or part selecting + +///Proxy class which allows concatination to be used as rvalue(for reading) and +//lvalue(for writing) + +/// Concatination reference. +// ---------------------------------------------------------------- +template +struct ap_concat_ref { +#ifdef _MSC_VER + #pragma warning(disable: 4521 4522) +#endif /* #ifdef _MSC_VER */ + enum {_AP_WR=_AP_W1+_AP_W2,}; + _AP_T1& mbv1; + _AP_T2& mbv2; + + INLINE ap_concat_ref(const ap_concat_ref<_AP_W1, _AP_T1, + _AP_W2, _AP_T2>& ref): + mbv1(ref.mbv1), mbv2(ref.mbv2) {} + + INLINE ap_concat_ref(_AP_T1& bv1, _AP_T2& bv2):mbv1(bv1),mbv2(bv2) {} + + template + INLINE ap_concat_ref& operator = (const ap_private<_AP_W3,_AP_S3>& val) { + ap_private<_AP_W1+_AP_W2, false> vval(val); + int W_ref1=mbv1.length(); + int W_ref2=mbv2.length(); + ap_private<_AP_W1,false> mask1(-1); + mask1>>=_AP_W1-W_ref1; + ap_private<_AP_W2,false> mask2(-1); + mask2>>=_AP_W2-W_ref2; + mbv1.set(ap_private<_AP_W1,false>((vval>>W_ref2)&mask1)); + mbv2.set(ap_private<_AP_W2,false>(vval&mask2)); + return *this; + } + + INLINE ap_concat_ref& operator = (unsigned long long val) { + ap_private<_AP_W1+_AP_W2, false> tmpVal(val); + return operator = (tmpVal); + } + + template + INLINE ap_concat_ref& operator = + (const ap_concat_ref <_AP_W3, _AP_T3, _AP_W4, _AP_T4>& val) { + ap_private<_AP_W1+_AP_W2, false> tmpVal(val); + return operator = (tmpVal); + } + + INLINE ap_concat_ref& operator = + (const ap_concat_ref <_AP_W1, _AP_T1, _AP_W2, _AP_T2>& val) { + ap_private<_AP_W1+_AP_W2, false> tmpVal(val); + return operator = (tmpVal); + } + + template + INLINE ap_concat_ref& operator =(const ap_bit_ref<_AP_W3, _AP_S3>& val) { + ap_private<_AP_W1+_AP_W2, false> tmpVal(val); + return operator = (tmpVal); + } + + template + INLINE ap_concat_ref& operator =(const ap_range_ref<_AP_W3,_AP_S3>& val) { + ap_private<_AP_W1+_AP_W2, false> tmpVal(val); + return operator =(tmpVal); + } + + template + INLINE ap_concat_ref& operator= (const af_range_ref<_AP_W3, _AP_I3, _AP_S3, + _AP_Q3, _AP_O3, _AP_N3>& val) { + return operator = ((const ap_private<_AP_W3, false>)(val)); + } + + template + INLINE ap_concat_ref& operator= (const ap_fixed_base<_AP_W3, _AP_I3, _AP_S3, + _AP_Q3, _AP_O3, _AP_N3>& val) { + return operator = (val.to_ap_private()); + } + + template + INLINE ap_concat_ref& operator= (const af_bit_ref<_AP_W3, _AP_I3, _AP_S3, + _AP_Q3, _AP_O3, _AP_N3>& val) { + return operator=((unsigned long long)(bool)(val)); + } + + + INLINE operator ap_private<_AP_WR, false> () const { + return get(); + } + + INLINE operator unsigned long long () const { + return get().to_uint64(); + } + + template + INLINE ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, ap_range_ref<_AP_W3, _AP_S3> > + operator, (const ap_range_ref<_AP_W3, _AP_S3> &a2) { + return ap_concat_ref<_AP_WR, ap_concat_ref, + _AP_W3, ap_range_ref<_AP_W3, _AP_S3> >(*this, + const_cast &>(a2)); + } + + template + INLINE ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, ap_private<_AP_W3, _AP_S3> > + operator, (ap_private<_AP_W3, _AP_S3> &a2) { + return ap_concat_ref<_AP_WR, ap_concat_ref, + _AP_W3, ap_private<_AP_W3, _AP_S3> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, ap_private<_AP_W3, _AP_S3> > + operator, (const ap_private<_AP_W3, _AP_S3> &a2) { + return ap_concat_ref<_AP_WR, ap_concat_ref, + _AP_W3, ap_private<_AP_W3, _AP_S3> >(*this, + const_cast&>(a2)); + } + + template + INLINE ap_concat_ref<_AP_WR, ap_concat_ref, 1, ap_bit_ref<_AP_W3, _AP_S3> > + operator, (const ap_bit_ref<_AP_W3, _AP_S3> &a2) { + return ap_concat_ref<_AP_WR, ap_concat_ref, + 1, ap_bit_ref<_AP_W3, _AP_S3> >(*this, + const_cast &>(a2)); + } + + template + INLINE ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3+_AP_W4, ap_concat_ref<_AP_W3,_AP_T3,_AP_W4,_AP_T4> > + operator, (const ap_concat_ref<_AP_W3,_AP_T3,_AP_W4,_AP_T4> &a2) + { + return ap_concat_ref<_AP_WR, ap_concat_ref, + _AP_W3+_AP_W4, ap_concat_ref<_AP_W3,_AP_T3,_AP_W4, + _AP_T4> >(*this, const_cast& >(a2)); + } + + template + INLINE + ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, af_range_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3> > + operator, (const af_range_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, + _AP_O3, _AP_N3> &a2) { + return ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, af_range_ref<_AP_W3, + _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3> >(*this, + const_cast& >(a2)); + } + + template + INLINE + ap_concat_ref<_AP_WR, ap_concat_ref, 1, af_bit_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3> > + operator, (const af_bit_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, + _AP_O3, _AP_N3> &a2) { + return ap_concat_ref<_AP_WR, ap_concat_ref, 1, af_bit_ref<_AP_W3, + _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3> >(*this, + const_cast& >(a2)); + } + + template + INLINE ap_private + operator & (const ap_private<_AP_W3,_AP_S3>& a2) { + return get() & a2; + } + + + template + INLINE ap_private + operator | (const ap_private<_AP_W3,_AP_S3>& a2) { + return get() | a2; + } + + + template + INLINE ap_private + operator ^ (const ap_private<_AP_W3,_AP_S3>& a2) { + return ap_private(get() ^ a2); + } + + INLINE const ap_private<_AP_WR, false> get() const + { + ap_private<_AP_W1+_AP_W2, false> tmpVal = ap_private<_AP_W1+_AP_W2, false> (mbv1.get()); + ap_private<_AP_W1+_AP_W2, false> tmpVal2 = ap_private<_AP_W1+_AP_W2, false> (mbv2.get()); + int W_ref2 = mbv2.length(); + tmpVal <<= W_ref2; + tmpVal |= tmpVal2; + return tmpVal; + } + + INLINE const ap_private<_AP_WR, false> get() { + ap_private<_AP_W1+_AP_W2, false> tmpVal = ap_private<_AP_W1+_AP_W2, false> ( mbv1.get()); + ap_private<_AP_W1+_AP_W2, false> tmpVal2 = ap_private<_AP_W1+_AP_W2, false> (mbv2.get()); + int W_ref2 = mbv2.length(); + tmpVal <<= W_ref2; + tmpVal |= tmpVal2; + return tmpVal; + } + + template + INLINE void set(const ap_private<_AP_W3,false> & val) { + ap_private<_AP_W1+_AP_W2, false> vval(val); + int W_ref1=mbv1.length(); + int W_ref2=mbv2.length(); + ap_private<_AP_W1,false> mask1(-1); + mask1>>=_AP_W1-W_ref1; + ap_private<_AP_W2,false> mask2(-1); + mask2>>=_AP_W2-W_ref2; + mbv1.set(ap_private<_AP_W1,false>((vval>>W_ref2)&mask1)); + mbv2.set(ap_private<_AP_W2,false>(vval&mask2)); + } + + INLINE int length() const { + return mbv1.length()+mbv2.length(); + } + + INLINE std::string to_string(uint8_t radix=2) const { + return get().to_string(radix); + } +}; + +///Proxy class, which allows part selection to be used as rvalue(for reading) and +//lvalue(for writing) + +///Range(slice) reference +//------------------------------------------------------------ +template +struct ap_range_ref { +#ifdef _MSC_VER + #pragma warning( disable : 4521 4522 ) +#endif /* #ifdef _MSC_VER */ + ap_private<_AP_W,_AP_S> &d_bv; + int l_index; + int h_index; + +public: + INLINE ap_range_ref(const ap_range_ref<_AP_W, _AP_S>& ref): + d_bv(ref.d_bv), l_index(ref.l_index), h_index(ref.h_index) {} + + INLINE ap_range_ref(ap_private<_AP_W,_AP_S>* bv, int h, int l): + d_bv(*bv),l_index(l),h_index(h) { + //if (h < l) + //fprintf(stderr, "Warning! The bits selected will be returned in reverse order\n"); + } + + INLINE operator ap_private<_AP_W, false> () const { + ap_private<_AP_W, false> val(0); + if(h_index>=l_index) { + if (_AP_W > 64) { + val=d_bv; + ap_private<_AP_W,false> mask(-1); + mask>>=_AP_W-(h_index-l_index+1); + val>>=l_index; + val&=mask; + } else { + const static uint64_t mask = (~0ULL>> (64>_AP_W ? (64-_AP_W):0)); + val = (d_bv >> l_index) & (mask >>(_AP_W-(h_index-l_index+1))); + } + } else { + for(int i=0, j=l_index;j>=0&&j>=h_index;j--,i++) + if((d_bv)[j]) val.set(i); + } + return val; + } + + INLINE operator unsigned long long () const { + return to_uint64(); + } + + template + INLINE ap_range_ref& operator =(const ap_private<_AP_W2,_AP_S2>& val) { + ap_private<_AP_W,false> vval=ap_private<_AP_W,false>(val); + if (l_index>h_index) { + for (int i=0, j=l_index;j>=0&&j>=h_index;j--,i++) + (vval)[i]? d_bv.set(j):d_bv.clear(j); + } else { + if (_AP_W > 64) { + ap_private<_AP_W,false> mask(-1); + if (l_index>0) { + mask<<=l_index; + vval<<=l_index; + } + if(h_index<_AP_W-1) + { + ap_private<_AP_W,false> mask2(-1); + mask2>>=_AP_W-h_index-1; + mask&=mask2; + vval&=mask2; + } + mask.flip(); + d_bv&=mask; + d_bv|=vval; + } else { + unsigned shift = 64-_AP_W; + uint64_t mask = ~0ULL>>(shift); + if(l_index>0) + { + vval = mask & vval << l_index; + mask = mask & mask << l_index; + } + if(h_index<_AP_W-1) + { + uint64_t mask2 = mask; + mask2 >>= (_AP_W-h_index-1); + mask&=mask2; + vval&=mask2; + } + mask = ~mask; + d_bv&=mask; + d_bv|=vval; + } + } + return *this; + } + + INLINE ap_range_ref& operator = (unsigned long long val) + { + const ap_private<_AP_W,_AP_S> vval=val; + return operator = (vval); + } + + + INLINE ap_range_ref& operator =(const ap_range_ref<_AP_W, _AP_S>& val) + { + const ap_private<_AP_W, false> tmpVal(val); + return operator =(tmpVal); + } + + + + template + INLINE ap_range_ref& operator = + (const ap_concat_ref <_AP_W3, _AP_T3, _AP_W4, _AP_T4>& val) + { + const ap_private<_AP_W, false> tmpVal(val); + return operator = (tmpVal); + } + + template + INLINE ap_range_ref& operator =(const ap_range_ref<_AP_W3,_AP_S3>& val) + { + const ap_private<_AP_W, false> tmpVal(val); + return operator =(tmpVal); + } + + template + INLINE ap_range_ref& operator= (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& val) { + return operator=((const ap_private<_AP_W2, _AP_S2>)(val)); + } + + template + INLINE ap_range_ref& operator= (const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& val) { + return operator=(val.to_ap_private()); + } + + template + INLINE ap_range_ref& operator= (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& val) { + return operator=((unsigned long long)(bool)(val)); + } + + template + INLINE ap_range_ref& operator= (const ap_bit_ref<_AP_W2, _AP_S2>& val) { + return operator=((unsigned long long)(bool)(val)); + } + + template + INLINE + ap_concat_ref<_AP_W,ap_range_ref,_AP_W2,ap_range_ref<_AP_W2,_AP_S2> > + operator, (const ap_range_ref<_AP_W2,_AP_S2> &a2) + { + return + ap_concat_ref<_AP_W, ap_range_ref, _AP_W2, + ap_range_ref<_AP_W2,_AP_S2> >(*this, + const_cast& >(a2)); + } + + + template + INLINE ap_concat_ref<_AP_W,ap_range_ref,_AP_W2,ap_private<_AP_W2,_AP_S2> > + operator , (ap_private<_AP_W2,_AP_S2>& a2) + { + return + ap_concat_ref<_AP_W, ap_range_ref, _AP_W2, ap_private<_AP_W2,_AP_S2> >(*this, a2); + } + + INLINE ap_concat_ref<_AP_W,ap_range_ref,_AP_W,ap_private<_AP_W,_AP_S> > + operator , (ap_private<_AP_W, _AP_S>& a2) + { + return + ap_concat_ref<_AP_W, ap_range_ref, _AP_W, + ap_private<_AP_W,_AP_S> >(*this, a2); + } + + + + template + INLINE + ap_concat_ref<_AP_W,ap_range_ref,1,ap_bit_ref<_AP_W2,_AP_S2> > + operator, (const ap_bit_ref<_AP_W2,_AP_S2> &a2) + { + return + ap_concat_ref<_AP_W, ap_range_ref, 1, + ap_bit_ref<_AP_W2,_AP_S2> >(*this, const_cast& >(a2)); + } + + + template + INLINE + ap_concat_ref<_AP_W, ap_range_ref, _AP_W2+_AP_W3, ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > + operator, (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) + { + return ap_concat_ref<_AP_W, ap_range_ref, _AP_W2+_AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(*this, + const_cast& >(a2)); + } + + template + INLINE + ap_concat_ref<_AP_W, ap_range_ref, _AP_W2, af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<_AP_W, ap_range_ref, _AP_W2, af_range_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, + const_cast& >(a2)); + } + + template + INLINE + ap_concat_ref<_AP_W, ap_range_ref, 1, af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<_AP_W, ap_range_ref, 1, af_bit_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, + const_cast& >(a2)); + } + + template + INLINE bool operator == (const ap_range_ref<_AP_W2, _AP_S2>& op2) + { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs==rhs; + } + + + template + INLINE bool operator != (const ap_range_ref<_AP_W2, _AP_S2>& op2) + { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs!=rhs; + } + + + template + INLINE bool operator > (const ap_range_ref<_AP_W2, _AP_S2>& op2) + { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs>rhs; + } + + + template + INLINE bool operator >= (const ap_range_ref<_AP_W2, _AP_S2>& op2) + { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs>=rhs; + } + + + template + INLINE bool operator < (const ap_range_ref<_AP_W2, _AP_S2>& op2) + { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs + INLINE bool operator <= (const ap_range_ref<_AP_W2, _AP_S2>& op2) + { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs<=rhs; + } + + + template + INLINE void set(const ap_private<_AP_W2,false>& val) + { + ap_private<_AP_W,_AP_S> vval=val; + if(l_index>h_index) + { + for(int i=0, j=l_index;j>=0&&j>=h_index;j--,i++) + (vval)[i]? d_bv.set(j):d_bv.clear(j); + } else { + if (_AP_W>64 ) { + ap_private<_AP_W,_AP_S> mask(-1); + if(l_index>0) + { + ap_private<_AP_W,false> mask1(-1); + mask1>>=_AP_W-l_index; + mask1.flip(); + mask=mask1; + //vval&=mask1; + vval<<=l_index; + } + if(h_index<_AP_W-1) + { + ap_private<_AP_W,false> mask2(-1); + mask2<<=h_index+1; + mask2.flip(); + mask&=mask2; + vval&=mask2; + } + mask.flip(); + d_bv&=mask; + d_bv|=vval; + } else { + uint64_t mask = ~0ULL >> (64-_AP_W); + if(l_index>0) + { + uint64_t mask1 = mask; + mask1=mask & (mask1>>(_AP_W-l_index)); + vval =mask&( vval <> (64-_AP_W); + mask2 = mask &(mask2<<(h_index+1)); + mask&=~mask2; + vval&=~mask2; + } + d_bv&=(~mask&(~0ULL >> (64-_AP_W))); + d_bv|=vval; + } + } + } + + + INLINE ap_private<_AP_W,false> get() const + { + ap_private<_AP_W,false> val(0); + if(h_index=0&&j>=h_index;j--,i++) + if((d_bv)[j]) val.set(i); + } else { + val=d_bv; + val>>=l_index; + if(h_index<_AP_W-1) + { + if (_AP_W <= 64) { + const static uint64_t mask = (~0ULL>> (64>_AP_W ? (64-_AP_W):0)); + val &= (mask>> (_AP_W-(h_index-l_index+1))); + } else { + ap_private<_AP_W,false> mask(-1); + mask>>=_AP_W-(h_index-l_index+1); + val&=mask; + } + } + } + return val; + } + + + INLINE ap_private<_AP_W,false> get() + { + ap_private<_AP_W,false> val(0); + if(h_index=0&&j>=h_index;j--,i++) + if((d_bv)[j]) val.set(i); + } else { + val=d_bv; + val>>=l_index; + if(h_index<_AP_W-1) + { + if (_AP_W <= 64 ) { + static const uint64_t mask = ~0ULL>> (64>_AP_W ? (64-_AP_W):0); + return val &= ( (mask) >> (_AP_W - (h_index-l_index+1))); + } else { + ap_private<_AP_W,false> mask(-1); + mask>>=_AP_W-(h_index-l_index+1); + val&=mask; + } + } + } + return val; + } + + + INLINE int length() const + { + return h_index>=l_index?h_index-l_index+1:l_index-h_index+1; + } + + + INLINE int to_int() const + { + ap_private<_AP_W,false> val=get(); + return val.to_int(); + } + + + INLINE unsigned int to_uint() const + { + ap_private<_AP_W,false> val=get(); + return val.to_uint(); + } + + + INLINE long to_long() const + { + ap_private<_AP_W,false> val=get(); + return val.to_long(); + } + + + INLINE unsigned long to_ulong() const + { + ap_private<_AP_W,false> val=get(); + return val.to_ulong(); + } + + + INLINE ap_slong to_int64() const + { + ap_private<_AP_W,false> val=get(); + return val.to_int64(); + } + + + INLINE ap_ulong to_uint64() const + { + ap_private<_AP_W,false> val=get(); + return val.to_uint64(); + } + + INLINE std::string to_string(uint8_t radix=2) const { + return get().to_string(radix); + } + +}; + +///Proxy class, which allows bit selection to be used as rvalue(for reading) and +//lvalue(for writing) + +///Bit reference +//-------------------------------------------------------------- +template +struct ap_bit_ref { +#ifdef _MSC_VER +#pragma warning( disable : 4521 4522 ) +#endif + ap_private<_AP_W,_AP_S>& d_bv; + int d_index; + +public: + INLINE ap_bit_ref(const ap_bit_ref<_AP_W, _AP_S>& ref): + d_bv(ref.d_bv), d_index(ref.d_index) {} + + INLINE ap_bit_ref(ap_private<_AP_W,_AP_S>& bv, int index=0): + d_bv(bv),d_index(index) + { +#ifdef _AP_DEBUG_ + assert(d_index<_AP_W&&"index out of bound"); +#endif + } + + + INLINE operator bool () const + { + return d_bv.get_bit(d_index); + } + + + INLINE bool to_bool() const + { + return operator bool (); + } + + + INLINE ap_bit_ref& operator = (unsigned long long val) + { + if(val) + d_bv.set(d_index); + else + d_bv.clear(d_index); + return *this; + } + + +#if 0 + INLINE ap_bit_ref& operator = (bool val) + { + if(val) + d_bv.set(d_index); + else + d_bv.clear(d_index); + return *this; + } +#endif + template + INLINE ap_bit_ref& operator =(const ap_private<_AP_W2,_AP_S2>& val) + { + return operator =((unsigned long long)(val != 0)); + } + + + template + INLINE ap_bit_ref& operator =(const ap_bit_ref<_AP_W2,_AP_S2>& val) + { + return operator =((unsigned long long)(bool)val); + } + + INLINE ap_bit_ref& operator =(const ap_bit_ref<_AP_W,_AP_S>& val) + { + return operator =((unsigned long long)(bool)val); + } + + template + INLINE ap_bit_ref& operator =(const ap_range_ref<_AP_W2,_AP_S2>& val) + { + return operator =((unsigned long long)(bool) val); + } + + + template + INLINE ap_bit_ref& operator= (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& val) { + return operator=((const ap_private<_AP_W2, false>)(val)); + } + + template + INLINE ap_bit_ref& operator= (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& val) { + return operator=((unsigned long long)(bool)(val)); + } + + template + INLINE ap_bit_ref& operator= (const ap_concat_ref<_AP_W2, _AP_T3, _AP_W3, _AP_T3>& val) { + return operator=((const ap_private<_AP_W2 + _AP_W3, false>)(val)); + } + + + + template + INLINE ap_concat_ref<1, ap_bit_ref, _AP_W2, ap_private<_AP_W2,_AP_S2> > + operator , (ap_private<_AP_W2, _AP_S2>& a2) + { + return ap_concat_ref<1, ap_bit_ref, _AP_W2, ap_private<_AP_W2,_AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<1, ap_bit_ref, _AP_W2, ap_range_ref<_AP_W2,_AP_S2> > + operator, (const ap_range_ref<_AP_W2, _AP_S2> &a2) + { + return + ap_concat_ref<1, ap_bit_ref, _AP_W2, ap_range_ref<_AP_W2,_AP_S2> >(*this, + const_cast &>(a2)); + } + + + template + INLINE ap_concat_ref<1, ap_bit_ref, 1, ap_bit_ref<_AP_W2,_AP_S2> > + operator, (const ap_bit_ref<_AP_W2, _AP_S2> &a2) + { + return + ap_concat_ref<1, ap_bit_ref, 1, ap_bit_ref<_AP_W2,_AP_S2> >(*this, + const_cast &>(a2)); + } + + + INLINE ap_concat_ref<1, ap_bit_ref, 1, ap_bit_ref > + operator, (const ap_bit_ref &a2) + { + return + ap_concat_ref<1, ap_bit_ref, 1, ap_bit_ref >(*this, + const_cast(a2)); + } + + + template + INLINE ap_concat_ref<1, ap_bit_ref, _AP_W2+_AP_W3, ap_concat_ref<_AP_W2,_AP_T2,_AP_W3,_AP_T3> > + operator, (const ap_concat_ref<_AP_W2,_AP_T2,_AP_W3,_AP_T3> &a2) + { + return + ap_concat_ref<1,ap_bit_ref,_AP_W2+_AP_W3, + ap_concat_ref<_AP_W2,_AP_T2,_AP_W3,_AP_T3> >(*this, + const_cast& >(a2)); + } + + template + INLINE + ap_concat_ref<1, ap_bit_ref, _AP_W2, af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<1, ap_bit_ref, _AP_W2, af_range_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, + const_cast& >(a2)); + } + + template + INLINE + ap_concat_ref<1, ap_bit_ref, 1, af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<1, ap_bit_ref, 1, af_bit_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, + const_cast& >(a2)); + } + + template + INLINE bool operator == (const ap_bit_ref<_AP_W2, _AP_S2>& op) { + return get() == op.get(); + } + + template + INLINE bool operator != (const ap_bit_ref<_AP_W2, _AP_S2>& op) { + return get() != op.get(); + } + + + INLINE bool get() const + { + return operator bool (); + } + + + INLINE bool get() + { + return operator bool (); + } + + + template + INLINE void set(const ap_private<_AP_W3, false>& val) + { + operator = (val); + } + + INLINE bool operator ~ () const { + bool bit = (d_bv)[d_index]; + return bit ? false : true; + } + + INLINE int length() const { return 1; } + + INLINE std::string to_string() const { + bool val = get(); + return val ? "1" : "0"; + } +}; + +/// Operators mixing Integers with AP_Int +// ---------------------------------------------------------------- +#if 1 +#define OP_BIN_MIX_INT(BIN_OP, C_TYPE, _AP_WI, _AP_SI, RTYPE) \ + template \ + INLINE typename ap_private<_AP_WI,_AP_SI>::template RType<_AP_W,_AP_S>::RTYPE \ + operator BIN_OP ( C_TYPE i_op, const ap_private<_AP_W,_AP_S> &op) { \ + return ap_private<_AP_WI,_AP_SI>(i_op).operator BIN_OP (op); \ + } \ + template \ + INLINE typename ap_private<_AP_W,_AP_S>::template RType<_AP_WI,_AP_SI>::RTYPE \ + operator BIN_OP ( const ap_private<_AP_W,_AP_S> &op, C_TYPE i_op) { \ + return op.operator BIN_OP (ap_private<_AP_WI,_AP_SI>(i_op)); \ + } +#else +#define OP_BIN_MIX_INT(BIN_OP, C_TYPE, _AP_WI, _AP_SI, RTYPE) \ + template \ + INLINE typename ap_private<_AP_WI,_AP_SI>::template RType<_AP_W,_AP_S>::RTYPE \ + operator BIN_OP ( C_TYPE i_op, const ap_private<_AP_W,_AP_S> &op) { \ + return ap_private<_AP_WI,_AP_SI>(i_op).operator BIN_OP (op); \ + } \ + template \ + INLINE typename ap_private<_AP_W,_AP_S>::template RType<_AP_WI,_AP_SI>::RTYPE \ + operator BIN_OP ( const ap_private<_AP_W,_AP_S> &op, C_TYPE i_op) { \ + return op.operator BIN_OP (ap_private<_AP_WI,_AP_SI>(i_op)); \ + } +#endif +#define OP_REL_MIX_INT(REL_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE bool operator REL_OP ( const ap_private<_AP_W,_AP_S> &op, C_TYPE op2) { \ + return op.operator REL_OP (ap_private<_AP_W2, _AP_S2>(op2)); \ + } \ + template \ + INLINE bool operator REL_OP ( C_TYPE op2, const ap_private<_AP_W,_AP_S> &op) { \ + return ap_private<_AP_W2,_AP_S2>(op2).operator REL_OP (op); \ + } +#define OP_ASSIGN_MIX_INT(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE ap_private<_AP_W,_AP_S> &operator ASSIGN_OP ( ap_private<_AP_W,_AP_S> &op, C_TYPE op2) { \ + return op.operator ASSIGN_OP (ap_private<_AP_W2,_AP_S2>(op2)); \ + } + +#define OP_BIN_SHIFT_INT(BIN_OP, C_TYPE, _AP_WI, _AP_SI, RTYPE) \ + template \ + C_TYPE operator BIN_OP ( C_TYPE i_op, const ap_private<_AP_W,_AP_S> &op) { \ + return i_op BIN_OP (op.getVal()); \ + } \ + template \ + INLINE typename ap_private<_AP_W,_AP_S>::template RType<_AP_WI,_AP_SI>::RTYPE \ + operator BIN_OP ( const ap_private<_AP_W,_AP_S> &op, C_TYPE i_op) { \ + return op.operator BIN_OP (i_op); \ + } +#define OP_ASSIGN_RSHIFT_INT(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE ap_private<_AP_W,_AP_S> &operator ASSIGN_OP ( ap_private<_AP_W,_AP_S> &op, C_TYPE op2) { \ + op = op.operator >> (op2); \ + return op; \ + } +#define OP_ASSIGN_LSHIFT_INT(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE ap_private<_AP_W,_AP_S> &operator ASSIGN_OP ( ap_private<_AP_W,_AP_S> &op, C_TYPE op2) { \ + op = op.operator << (op2); \ + return op; \ + } + +#define OPS_MIX_INT(C_TYPE, WI, SI) \ + OP_BIN_MIX_INT(*, C_TYPE, WI, SI, mult) \ + OP_BIN_MIX_INT(+, C_TYPE, WI, SI, plus) \ + OP_BIN_MIX_INT(-, C_TYPE, WI, SI, minus) \ + OP_BIN_MIX_INT(/, C_TYPE, WI, SI, div) \ + OP_BIN_MIX_INT(%, C_TYPE, WI, SI, mod) \ + OP_BIN_MIX_INT(&, C_TYPE, WI, SI, logic) \ + OP_BIN_MIX_INT(|, C_TYPE, WI, SI, logic) \ + OP_BIN_MIX_INT(^, C_TYPE, WI, SI, logic) \ + OP_BIN_SHIFT_INT(>>, C_TYPE, WI, SI, arg1) \ + OP_BIN_SHIFT_INT(<<, C_TYPE, WI, SI, arg1) \ + \ + OP_REL_MIX_INT(==, C_TYPE, WI, SI) \ + OP_REL_MIX_INT(!=, C_TYPE, WI, SI) \ + OP_REL_MIX_INT(>, C_TYPE, WI, SI) \ + OP_REL_MIX_INT(>=, C_TYPE, WI, SI) \ + OP_REL_MIX_INT(<, C_TYPE, WI, SI) \ + OP_REL_MIX_INT(<=, C_TYPE, WI, SI) \ + \ + OP_ASSIGN_MIX_INT(+=, C_TYPE, WI, SI) \ + OP_ASSIGN_MIX_INT(-=, C_TYPE, WI, SI) \ + OP_ASSIGN_MIX_INT(*=, C_TYPE, WI, SI) \ + OP_ASSIGN_MIX_INT(/=, C_TYPE, WI, SI) \ + OP_ASSIGN_MIX_INT(%=, C_TYPE, WI, SI) \ + OP_ASSIGN_MIX_INT(&=, C_TYPE, WI, SI) \ + OP_ASSIGN_MIX_INT(|=, C_TYPE, WI, SI) \ + OP_ASSIGN_MIX_INT(^=, C_TYPE, WI, SI) \ + OP_ASSIGN_RSHIFT_INT(>>=, C_TYPE, WI, SI) \ + OP_ASSIGN_LSHIFT_INT(<<=, C_TYPE, WI, SI) + + +OPS_MIX_INT(bool, 1, false) +OPS_MIX_INT(char, 8, true) +OPS_MIX_INT(signed char, 8, true) +OPS_MIX_INT(unsigned char, 8, false) +OPS_MIX_INT(short, 16, true) +OPS_MIX_INT(unsigned short, 16, false) +OPS_MIX_INT(int, 32, true) +OPS_MIX_INT(unsigned int, 32, false) +# if defined __x86_64__ +OPS_MIX_INT(long, 64, true) +OPS_MIX_INT(unsigned long, 64, false) +# else +OPS_MIX_INT(long, 32, true) +OPS_MIX_INT(unsigned long, 32, false) +# endif +OPS_MIX_INT(ap_slong, 64, true) +OPS_MIX_INT(ap_ulong, 64, false) + +#define OP_BIN_MIX_RANGE(BIN_OP, RTYPE) \ + template \ + INLINE typename ap_private<_AP_W1,_AP_S1>::template RType<_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP ( const ap_range_ref<_AP_W1,_AP_S1>& op1, const ap_private<_AP_W2,_AP_S2>& op2) { \ + return ap_private<_AP_W1, false>(op1).operator BIN_OP (op2); \ + } \ + template \ + INLINE typename ap_private<_AP_W1,_AP_S1>::template RType<_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP ( const ap_private<_AP_W1,_AP_S1>& op1, const ap_range_ref<_AP_W2,_AP_S2>& op2) { \ + return op1.operator BIN_OP (ap_private<_AP_W2, false>(op2)); \ + } + +#define OP_REL_MIX_RANGE(REL_OP) \ + template \ + INLINE bool operator REL_OP ( const ap_range_ref<_AP_W1,_AP_S1>& op1, const ap_private<_AP_W2,_AP_S2>& op2) { \ + return ap_private<_AP_W1,false>(op1).operator REL_OP (op2); \ + } \ + template \ + INLINE bool operator REL_OP ( const ap_private<_AP_W1,_AP_S1>& op1, const ap_range_ref<_AP_W2,_AP_S2>& op2) { \ + return op1.operator REL_OP (op2.operator ap_private<_AP_W2, false>()); \ + } + +#define OP_ASSIGN_MIX_RANGE(ASSIGN_OP) \ + template \ + INLINE ap_private<_AP_W1,_AP_S1>& operator ASSIGN_OP ( ap_private<_AP_W1,_AP_S1>& op1, const ap_range_ref<_AP_W2,_AP_S2>& op2) { \ + return op1.operator ASSIGN_OP (ap_private<_AP_W2, false>(op2)); \ + } \ + template \ + INLINE ap_range_ref<_AP_W1,_AP_S1>& operator ASSIGN_OP (ap_range_ref<_AP_W1,_AP_S1>& op1, ap_private<_AP_W2,_AP_S2>& op2) { \ + ap_private<_AP_W1, false> tmp(op1); \ + tmp.operator ASSIGN_OP (op2); \ + op1 = tmp; \ + return op1; \ + } + + +OP_ASSIGN_MIX_RANGE(+=) +OP_ASSIGN_MIX_RANGE(-=) +OP_ASSIGN_MIX_RANGE(*=) +OP_ASSIGN_MIX_RANGE(/=) +OP_ASSIGN_MIX_RANGE(%=) +OP_ASSIGN_MIX_RANGE(>>=) +OP_ASSIGN_MIX_RANGE(<<=) +OP_ASSIGN_MIX_RANGE(&=) +OP_ASSIGN_MIX_RANGE(|=) +OP_ASSIGN_MIX_RANGE(^=) + +OP_REL_MIX_RANGE(==) +OP_REL_MIX_RANGE(!=) +OP_REL_MIX_RANGE(>) +OP_REL_MIX_RANGE(>=) +OP_REL_MIX_RANGE(<) +OP_REL_MIX_RANGE(<=) + +OP_BIN_MIX_RANGE(+, plus) +OP_BIN_MIX_RANGE(-, minus) +OP_BIN_MIX_RANGE(*, mult) +OP_BIN_MIX_RANGE(/, div) +OP_BIN_MIX_RANGE(%, mod) +OP_BIN_MIX_RANGE(>>, arg1) +OP_BIN_MIX_RANGE(<<, arg1) +OP_BIN_MIX_RANGE(&, logic) +OP_BIN_MIX_RANGE(|, logic) +OP_BIN_MIX_RANGE(^, logic) + +#define OP_BIN_MIX_BIT(BIN_OP, RTYPE) \ + template \ + INLINE typename ap_private<1, false>::template RType<_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP ( const ap_bit_ref<_AP_W1,_AP_S1>& op1, const ap_private<_AP_W2,_AP_S2>& op2) { \ + return ap_private<1, false>(op1).operator BIN_OP (op2); \ + } \ + template \ + INLINE typename ap_private<_AP_W1,_AP_S1>::template RType<1,false>::RTYPE \ + operator BIN_OP ( const ap_private<_AP_W1,_AP_S1>& op1, const ap_bit_ref<_AP_W2,_AP_S2>& op2) { \ + return op1.operator BIN_OP (ap_private<1, false>(op2)); \ + } + +#define OP_REL_MIX_BIT(REL_OP) \ + template \ + INLINE bool operator REL_OP ( const ap_bit_ref<_AP_W1,_AP_S1>& op1, const ap_private<_AP_W2,_AP_S2>& op2) { \ + return ap_private<_AP_W1,false>(op1).operator REL_OP (op2); \ + } \ + template \ + INLINE bool operator REL_OP ( const ap_private<_AP_W1,_AP_S1>& op1, const ap_bit_ref<_AP_W2,_AP_S2>& op2) { \ + return op1.operator REL_OP (ap_private<1, false>(op2)); \ + } + +#define OP_ASSIGN_MIX_BIT(ASSIGN_OP) \ + template \ + INLINE ap_private<_AP_W1,_AP_S1>& operator ASSIGN_OP ( ap_private<_AP_W1,_AP_S1>& op1, ap_bit_ref<_AP_W2,_AP_S2>& op2) { \ + return op1.operator ASSIGN_OP (ap_private<1, false>(op2)); \ + } \ + template \ + INLINE ap_bit_ref<_AP_W1,_AP_S1>& operator ASSIGN_OP ( ap_bit_ref<_AP_W1,_AP_S1>& op1, ap_private<_AP_W2,_AP_S2>& op2) { \ + ap_private<1, false> tmp(op1); \ + tmp.operator ASSIGN_OP (op2); \ + op1 = tmp; \ + return op1; \ + } + + +OP_ASSIGN_MIX_BIT(+=) +OP_ASSIGN_MIX_BIT(-=) +OP_ASSIGN_MIX_BIT(*=) +OP_ASSIGN_MIX_BIT(/=) +OP_ASSIGN_MIX_BIT(%=) +OP_ASSIGN_MIX_BIT(>>=) +OP_ASSIGN_MIX_BIT(<<=) +OP_ASSIGN_MIX_BIT(&=) +OP_ASSIGN_MIX_BIT(|=) +OP_ASSIGN_MIX_BIT(^=) + +OP_REL_MIX_BIT(==) +OP_REL_MIX_BIT(!=) +OP_REL_MIX_BIT(>) +OP_REL_MIX_BIT(>=) +OP_REL_MIX_BIT(<) +OP_REL_MIX_BIT(<=) + +OP_BIN_MIX_BIT(+, plus) +OP_BIN_MIX_BIT(-, minus) +OP_BIN_MIX_BIT(*, mult) +OP_BIN_MIX_BIT(/, div) +OP_BIN_MIX_BIT(%, mod) +OP_BIN_MIX_BIT(>>, arg1) +OP_BIN_MIX_BIT(<<, arg1) +OP_BIN_MIX_BIT(&, logic) +OP_BIN_MIX_BIT(|, logic) +OP_BIN_MIX_BIT(^, logic) + +#define REF_REL_OP_MIX_INT(REL_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE bool operator REL_OP ( const ap_range_ref<_AP_W,_AP_S> &op, C_TYPE op2) { \ + return (ap_private<_AP_W, false>(op)).operator REL_OP (ap_private<_AP_W2,_AP_S2>(op2)); \ + } \ + template \ + INLINE bool operator REL_OP ( C_TYPE op2, const ap_range_ref<_AP_W,_AP_S> &op) { \ + return ap_private<_AP_W2,_AP_S2>(op2).operator REL_OP (ap_private<_AP_W, false>(op)); \ + } \ + template \ + INLINE bool operator REL_OP ( const ap_bit_ref<_AP_W,_AP_S> &op, C_TYPE op2) { \ + return (bool(op)) REL_OP op2; \ + } \ + template \ + INLINE bool operator REL_OP ( C_TYPE op2, const ap_bit_ref<_AP_W,_AP_S> &op) { \ + return op2 REL_OP (bool(op)); \ + } \ + template \ + INLINE bool operator REL_OP ( const ap_concat_ref<_AP_W,_AP_T, _AP_W1, _AP_T1> &op, C_TYPE op2) { \ + return (ap_private<_AP_W + _AP_W1, false>(op)).operator REL_OP (ap_private<_AP_W2,_AP_S2>(op2)); \ + } \ + template \ + INLINE bool operator REL_OP ( C_TYPE op2, const ap_concat_ref<_AP_W,_AP_T, _AP_W1, _AP_T1> &op) { \ + return ap_private<_AP_W2,_AP_S2>(op2).operator REL_OP (ap_private<_AP_W + _AP_W1, false>(op)); \ + } + +#define REF_REL_MIX_INT(C_TYPE, _AP_WI, _AP_SI) \ +REF_REL_OP_MIX_INT(>, C_TYPE, _AP_WI, _AP_SI) \ +REF_REL_OP_MIX_INT(<, C_TYPE, _AP_WI, _AP_SI) \ +REF_REL_OP_MIX_INT(>=, C_TYPE, _AP_WI, _AP_SI) \ +REF_REL_OP_MIX_INT(<=, C_TYPE, _AP_WI, _AP_SI) \ +REF_REL_OP_MIX_INT(==, C_TYPE, _AP_WI, _AP_SI) \ +REF_REL_OP_MIX_INT(!=, C_TYPE, _AP_WI, _AP_SI) + +REF_REL_MIX_INT(bool, 1, false) +REF_REL_MIX_INT(char, 8, true) +REF_REL_MIX_INT(signed char, 8, true) +REF_REL_MIX_INT(unsigned char, 8, false) +REF_REL_MIX_INT(short, 16, true) +REF_REL_MIX_INT(unsigned short, 16, false) +REF_REL_MIX_INT(int, 32, true) +REF_REL_MIX_INT(unsigned int, 32, false) +# if defined __x86_64__ +REF_REL_MIX_INT(long, 64, true) +REF_REL_MIX_INT(unsigned long, 64, false) +# else +REF_REL_MIX_INT(long, 32, true) +REF_REL_MIX_INT(unsigned long, 32, false) +# endif +REF_REL_MIX_INT(ap_slong, 64, true) +REF_REL_MIX_INT(ap_ulong, 64, false) + +#define REF_BIN_OP_MIX_INT(BIN_OP, RTYPE, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE typename ap_private<_AP_W, false>::template RType<_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP ( const ap_range_ref<_AP_W,_AP_S> &op, C_TYPE op2) { \ + return (ap_private<_AP_W, false>(op)).operator BIN_OP (ap_private<_AP_W2,_AP_S2>(op2)); \ + } \ + template \ + INLINE typename ap_private<_AP_W2, _AP_S2>::template RType<_AP_W,false>::RTYPE \ + operator BIN_OP ( C_TYPE op2, const ap_range_ref<_AP_W,_AP_S> &op) { \ + return ap_private<_AP_W2,_AP_S2>(op2).operator BIN_OP (ap_private<_AP_W, false>(op)); \ + } + +#define REF_BIN_MIX_INT(C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(+, plus, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(-, minus, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(*, mult, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(/, div, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(%, mod, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(>>, arg1, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(<<, arg1, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(&, logic, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(|, logic, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(^, logic, C_TYPE, _AP_WI, _AP_SI) + +REF_BIN_MIX_INT(bool, 1, false) +REF_BIN_MIX_INT(char, 8, true) +REF_BIN_MIX_INT(signed char, 8, true) +REF_BIN_MIX_INT(unsigned char, 8, false) +REF_BIN_MIX_INT(short, 16, true) +REF_BIN_MIX_INT(unsigned short, 16, false) +REF_BIN_MIX_INT(int, 32, true) +REF_BIN_MIX_INT(unsigned int, 32, false) +# if defined __x86_64__ +REF_BIN_MIX_INT(long, 64, true) +REF_BIN_MIX_INT(unsigned long, 64, false) +#else +REF_BIN_MIX_INT(long, 32, true) +REF_BIN_MIX_INT(unsigned long, 32, false) +#endif +REF_BIN_MIX_INT(ap_slong, 64, true) +REF_BIN_MIX_INT(ap_ulong, 64, false) + +#define REF_BIN_OP(BIN_OP, RTYPE) \ +template \ +INLINE typename ap_private<_AP_W, false>::template RType<_AP_W2, false>::RTYPE \ +operator BIN_OP (const ap_range_ref<_AP_W,_AP_S> &lhs, const ap_range_ref<_AP_W2,_AP_S2> &rhs) { \ + return ap_private<_AP_W,false>(lhs).operator BIN_OP (ap_private<_AP_W2, false>(rhs)); \ +} + +REF_BIN_OP(+, plus) +REF_BIN_OP(-, minus) +REF_BIN_OP(*, mult) +REF_BIN_OP(/, div) +REF_BIN_OP(%, mod) +REF_BIN_OP(>>, arg1) +REF_BIN_OP(<<, arg1) +REF_BIN_OP(&, logic) +REF_BIN_OP(|, logic) +REF_BIN_OP(^, logic) + +#if 1 +#define CONCAT_OP_MIX_INT(C_TYPE, _AP_WI, _AP_SI) \ +template \ +INLINE \ +ap_private< _AP_W + _AP_WI, false > \ + operator, (const ap_private<_AP_W, _AP_S> &op1, C_TYPE op2) { \ + ap_private<_AP_WI + _AP_W, false> val(op2); \ + ap_private<_AP_WI + _AP_W, false> ret(op1); \ + ret <<= _AP_WI; \ + if (_AP_SI) { \ + val <<= _AP_W; val >>= _AP_W; \ + }\ + ret |= val; \ + return ret;\ +} \ +template \ +INLINE \ +ap_private< _AP_W + _AP_WI, false > \ + operator, (C_TYPE op1, const ap_private<_AP_W, _AP_S>& op2) { \ + ap_private<_AP_WI + _AP_W, false> val(op1); \ + ap_private<_AP_WI + _AP_W, false> ret(op2); \ + if (_AP_S) { \ + ret <<= _AP_WI; ret >>= _AP_WI; \ + } \ + ret |= val << _AP_W; \ + return ret; \ +} \ +template \ +INLINE \ +ap_private< _AP_W + _AP_WI, false > \ + operator, (const ap_range_ref<_AP_W, _AP_S> &op1, C_TYPE op2) { \ + ap_private<_AP_WI + _AP_W, false> val(op2); \ + ap_private<_AP_WI + _AP_W, false> ret(op1); \ + ret <<= _AP_WI; \ + if (_AP_SI) { \ + val <<= _AP_W; val >>= _AP_W; \ + } \ + ret |= val; \ + return ret; \ +} \ +template \ +INLINE \ +ap_private< _AP_W + _AP_WI, false > \ + operator, (C_TYPE op1, const ap_range_ref<_AP_W, _AP_S> &op2) { \ + ap_private<_AP_WI + _AP_W, false> val(op1); \ + ap_private<_AP_WI + _AP_W, false> ret(op2); \ + int len = op2.length(); \ + val <<= len; \ + ret |= val; \ + return ret; \ +} \ +template \ +INLINE \ +ap_private<_AP_WI + 1, false > \ + operator, (const ap_bit_ref<_AP_W, _AP_S> &op1, C_TYPE op2) { \ + ap_private<_AP_WI + 1, false> val(op2); \ + val[_AP_WI] = op1; \ + return val; \ +} \ +template \ +INLINE \ +ap_private<_AP_WI + 1, false > \ + operator, (C_TYPE op1, const ap_bit_ref<_AP_W, _AP_S> &op2) { \ + ap_private<_AP_WI + 1, false> val(op1); \ + val <<= 1; \ + val[0] = op2; \ + return val; \ +} \ +template \ +INLINE \ +ap_private<_AP_W + _AP_W2 + _AP_WI, false > \ + operator, (const ap_concat_ref<_AP_W, _AP_T, _AP_W2, _AP_T2> &op1, C_TYPE op2) {\ + ap_private<_AP_WI + _AP_W + _AP_W2, _AP_SI> val(op2);\ + ap_private<_AP_WI + _AP_W + _AP_W2, _AP_SI> ret(op1);\ + if (_AP_SI) { \ + val <<= _AP_W + _AP_W2; val >>= _AP_W + _AP_W2; \ + } \ + ret <<= _AP_WI; \ + ret |= val; \ + return ret; \ +}\ +template \ +INLINE \ +ap_private<_AP_W + _AP_W2 + _AP_WI, false > \ + operator, (C_TYPE op1, const ap_concat_ref<_AP_W, _AP_T, _AP_W2, _AP_T2> &op2) {\ + ap_private<_AP_WI + _AP_W + _AP_W2, _AP_SI> val(op1);\ + ap_private<_AP_WI + _AP_W + _AP_W2, _AP_SI> ret(op2);\ + int len = op2.length(); \ + val <<= len; \ + ret |= val;\ + return ret; \ +}\ +template \ +INLINE \ +ap_private< _AP_W + _AP_WI, false > \ + operator, (const af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op1, C_TYPE op2) { \ + ap_private<_AP_WI + _AP_W, false> val(op2); \ + ap_private<_AP_WI + _AP_W, false> ret(op1); \ + if (_AP_SI) { \ + val <<= _AP_W; val >>= _AP_W; \ + }\ + ret <<= _AP_WI; \ + ret |= val; \ + return ret; \ +} \ +template \ +INLINE \ +ap_private< _AP_W + _AP_WI, false > \ + operator, (C_TYPE op1, const af_range_ref<_AP_W, _AP_I, _AP_S, \ + _AP_Q, _AP_O, _AP_N> &op2) { \ + ap_private<_AP_WI + _AP_W, false> val(op1); \ + ap_private<_AP_WI + _AP_W, false> ret(op2); \ + int len = op2.length(); \ + val <<= len; \ + ret |= val; \ + return ret; \ +} \ +template \ +INLINE \ +ap_private< 1 + _AP_WI, false> \ + operator, (const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, \ + _AP_N> &op1, C_TYPE op2) { \ + ap_private<_AP_WI + 1, _AP_SI> val(op2); \ + val[_AP_WI] = op1; \ + return val; \ +} \ +template \ +INLINE \ +ap_private< 1 + _AP_WI, false> \ + operator, (C_TYPE op1, const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q,\ + _AP_O, _AP_N> &op2) { \ + ap_private<_AP_WI + 1, _AP_SI> val(op1); \ + val <<= 1; \ + val[0] = op2; \ + return val; \ +} + +CONCAT_OP_MIX_INT(bool, 1, false) +CONCAT_OP_MIX_INT(char, 8, true) +CONCAT_OP_MIX_INT(signed char, 8, true) +CONCAT_OP_MIX_INT(unsigned char, 8, false) +CONCAT_OP_MIX_INT(short, 16, true) +CONCAT_OP_MIX_INT(unsigned short, 16, false) +CONCAT_OP_MIX_INT(int, 32, true) +CONCAT_OP_MIX_INT(unsigned int, 32, false) +# if defined __x86_64__ +CONCAT_OP_MIX_INT(long, 64, true) +CONCAT_OP_MIX_INT(unsigned long, 64, false) +# else +CONCAT_OP_MIX_INT(long, 32, true) +CONCAT_OP_MIX_INT(unsigned long, 32, false) +# endif +CONCAT_OP_MIX_INT(ap_slong, 64, true) +CONCAT_OP_MIX_INT(ap_ulong, 64, false) +#endif + +#if 1 +#define CONCAT_SHIFT_MIX_INT(C_TYPE, op) \ +template \ +INLINE ap_uint<_AP_W+_AP_W1> operator op (const ap_concat_ref<_AP_W, _AP_T, _AP_W1, _AP_T1> lhs, C_TYPE rhs) { \ + return ((ap_uint<_AP_W+_AP_W1>)lhs.get()) op ((int)rhs); \ +} + +CONCAT_SHIFT_MIX_INT(long, <<) +CONCAT_SHIFT_MIX_INT(unsigned long, <<) +CONCAT_SHIFT_MIX_INT(unsigned int, <<) +CONCAT_SHIFT_MIX_INT(ap_ulong, <<) +CONCAT_SHIFT_MIX_INT(ap_slong, <<) +CONCAT_SHIFT_MIX_INT(long, >>) +CONCAT_SHIFT_MIX_INT(unsigned long, >>) +CONCAT_SHIFT_MIX_INT(unsigned int, >>) +CONCAT_SHIFT_MIX_INT(ap_ulong, >>) +CONCAT_SHIFT_MIX_INT(ap_slong, >>) +#endif + +#if defined(SYSTEMC_H) || defined(SYSTEMC_INCLUDED) +template +INLINE void sc_trace(sc_core::sc_trace_file *tf, const ap_private<_AP_W, _AP_S> &op, + const std::string &name) { + if (tf) + tf->trace(sc_dt::sc_lv<_AP_W>(op.to_string(2).c_str()), name); +} +#endif + +template +INLINE std::ostream& operator<<(std::ostream& out, const ap_private<_AP_W,_AP_S> &op) +{ + ap_private<_AP_W, _AP_S> v=op; + const std::ios_base::fmtflags basefield = out.flags() & std::ios_base::basefield; + unsigned radix = (basefield == std::ios_base::hex) ? 16 : + ((basefield == std::ios_base::oct) ? 8 : 10); + std::string str=v.toString(radix,_AP_S); + out< +INLINE std::istream& operator >> (std::istream& in, ap_private<_AP_W,_AP_S> &op) +{ + std::string str; + in >> str; + op = ap_private<_AP_W, _AP_S>(str.c_str()); + return in; + +} + +template +INLINE std::ostream& operator<<(std::ostream& out, const ap_range_ref<_AP_W,_AP_S> &op) +{ + return operator<<(out, ap_private<_AP_W, _AP_S>(op)); +} + +template +INLINE std::istream& operator >> (std::istream& in, ap_range_ref<_AP_W,_AP_S> &op) +{ + return operator>>(in, ap_private<_AP_W, _AP_S>(op));; +} + +template +INLINE void print(const ap_private<_AP_W,_AP_S> &op, bool fill=true ) +{ + ap_private<_AP_W, _AP_S> v=op; + uint32_t ws=v.getNumWords(); + const uint64_t *ptr=v.getRawData(); + int i=ws-1; +#if 0 + if(fill) + printf("%016llx",*(ptr+i)); + else + printf("%llx",*(ptr+i)); +#else +//match SystemC output + if(_AP_W%64 != 0) { + uint32_t offset=_AP_W%64; + uint32_t count=(offset+3)/4; + int64_t data=*(ptr+i); + if(_AP_S) + data=(data<<(64-offset))>>(64-offset); + else + count=(offset+4)/4; + while(count-->0) + printf("%llx",(data>>(count*4))&0xf); + } else { + if(_AP_S==false) + printf("0"); + printf("%016llx",*(ptr+i)); + } +#endif + for(--i;i>=0;i--) + printf("%016llx",*(ptr+i)); + printf("\n"); + +} +#endif /* #ifndef __AESL_GCC_AP_INT_H__ */ \ No newline at end of file diff --git a/hls_2018/router_02/etc/ap_private.h b/hls_2018/router_02/etc/ap_private.h new file mode 100755 index 0000000..1a68a9e --- /dev/null +++ b/hls_2018/router_02/etc/ap_private.h @@ -0,0 +1,5858 @@ +/* + * Copyright 2012 Xilinx, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LLVM_SUPPORT_MATHEXTRAS_H +#define LLVM_SUPPORT_MATHEXTRAS_H + +#ifdef _MSC_VER +#if _MSC_VER <= 1500 +typedef __int8 int8_t; +typedef unsigned __int8 uint8_t; +typedef __int16 int16_t; +typedef unsigned __int16 uint16_t; +typedef __int32 int32_t; +typedef unsigned __int32 uint32_t; +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; +#else if +#include +#endif /* #if _MSC_VER <= 1500 */ +#else +#include +#endif /* #if _MSC_VER <= 1500 */ +#undef INLINE +#if 1 +#define INLINE inline +#else +//Enable to debug ap_int/ap_fixed +#define INLINE __attribute__((weak)) +#endif +#define AP_MAX(a,b) ((a) > (b) ? (a) : (b)) +#define AP_MIN(a,b) ((a) < (b) ? (a) : (b)) +#define AP_ABS(a) ((a)>=0 ? (a):-(a)) +#ifndef AP_INT_MAX_W +#define AP_INT_MAX_W 1024 +#endif +#define BIT_WIDTH_UPPER_LIMIT (1 << 15) +#if AP_INT_MAX_W > BIT_WIDTH_UPPER_LIMIT +#error "Bitwidth exceeds 32768 (1 << 15), the maximum allowed value" +#endif +#define MAX_MODE(BITS) ((BITS + 1023) / 1024) + +// NOTE: The following support functions use the _32/_64 extensions instead of +// type overloading so that signed and unsigned integers can be used without +// ambiguity. + +/// Hi_32 - This function returns the high 32 bits of a 64 bit value. +INLINE uint32_t Hi_32(uint64_t Value) { + return static_cast(Value >> 32); +} + +/// Lo_32 - This function returns the low 32 bits of a 64 bit value. +INLINE uint32_t Lo_32(uint64_t Value) { + return static_cast(Value); +} + +/// ByteSwap_16 - This function returns a byte-swapped representation of the +/// 16-bit argument, Value. +INLINE uint16_t ByteSwap_16(uint16_t Value) { +#if defined(_MSC_VER) && !defined(_DEBUG) + // The DLL version of the runtime lacks these functions (bug!?), but in a + // release build they're replaced with BSWAP instructions anyway. + return (uint16_t)(_byteswap_ushort(Value)); +#else + uint16_t Hi = (uint16_t)((Value) << 8); + uint16_t Lo = (uint16_t)((Value) >> 8); + return Hi | Lo; +#endif +} + +/// ByteSwap_32 - This function returns a byte-swapped representation of the +/// 32-bit argument, Value. +INLINE uint32_t ByteSwap_32(uint32_t Value) { + uint32_t Byte0 = Value & 0x000000FF; + uint32_t Byte1 = Value & 0x0000FF00; + uint32_t Byte2 = Value & 0x00FF0000; + uint32_t Byte3 = Value & 0xFF000000; + return ((Byte0) << 24) | ((Byte1) << 8) | ((Byte2) >> 8) | ((Byte3) >> 24); +} + +/// ByteSwap_64 - This function returns a byte-swapped representation of the +/// 64-bit argument, Value. +INLINE uint64_t ByteSwap_64(uint64_t Value) { + uint64_t Hi = ByteSwap_32(uint32_t(Value)); + uint32_t Lo = ByteSwap_32(uint32_t(Value >> 32)); + return ((Hi) << 32) | Lo; +} + +/// CountLeadingZeros_32 - this function performs the platform optimal form of +/// counting the number of zeros from the most significant bit to the first one +/// bit. Ex. CountLeadingZeros_32(0x00F000FF) == 8. +/// Returns 32 if the word is zero. +INLINE unsigned CountLeadingZeros_32(uint32_t Value) { + unsigned Count; // result +#if __GNUC__ >= 4 + // PowerPC is defined for __builtin_clz(0) +#if !defined(__ppc__) && !defined(__ppc64__) + if (Value == 0) return 32; +#endif + Count = __builtin_clz(Value); +#else + if (Value == 0) return 32; + Count = 0; + // bisecton method for count leading zeros + for (unsigned Shift = 32 >> 1; Shift; Shift >>= 1) { + uint32_t Tmp = (Value) >> (Shift); + if (Tmp) { + Value = Tmp; + } else { + Count |= Shift; + } + } +#endif + return Count; +} + +/// CountLeadingZeros_64 - This function performs the platform optimal form +/// of counting the number of zeros from the most significant bit to the first +/// one bit (64 bit edition.) +/// Returns 64 if the word is zero. +INLINE unsigned CountLeadingZeros_64(uint64_t Value) { + unsigned Count; // result +#if __GNUC__ >= 4 + // PowerPC is defined for __builtin_clzll(0) +#if !defined(__ppc__) && !defined(__ppc64__) + if (!Value) return 64; +#endif + Count = __builtin_clzll(Value); +#else + if (sizeof(long) == sizeof(int64_t)) { + if (!Value) return 64; + Count = 0; + // bisecton method for count leading zeros + for (unsigned Shift = 64 >> 1; Shift; Shift >>= 1) { + uint64_t Tmp = (Value) >> (Shift); + if (Tmp) { + Value = Tmp; + } else { + Count |= Shift; + } + } + } else { + // get hi portion + uint32_t Hi = Hi_32(Value); + + // if some bits in hi portion + if (Hi) { + // leading zeros in hi portion plus all bits in lo portion + Count = CountLeadingZeros_32(Hi); + } else { + // get lo portion + uint32_t Lo = Lo_32(Value); + // same as 32 bit value + Count = CountLeadingZeros_32(Lo)+32; + } + } +#endif + return Count; +} + +/// CountTrailingZeros_64 - This function performs the platform optimal form +/// of counting the number of zeros from the least significant bit to the first +/// one bit (64 bit edition.) +/// Returns 64 if the word is zero. +INLINE unsigned CountTrailingZeros_64(uint64_t Value) { +#if __GNUC__ >= 4 + return (Value != 0) ? __builtin_ctzll(Value) : 64; +#else + static const unsigned Mod67Position[] = { + 64, 0, 1, 39, 2, 15, 40, 23, 3, 12, 16, 59, 41, 19, 24, 54, + 4, 64, 13, 10, 17, 62, 60, 28, 42, 30, 20, 51, 25, 44, 55, + 47, 5, 32, 65, 38, 14, 22, 11, 58, 18, 53, 63, 9, 61, 27, + 29, 50, 43, 46, 31, 37, 21, 57, 52, 8, 26, 49, 45, 36, 56, + 7, 48, 35, 6, 34, 33, 0 + }; + return Mod67Position[(uint64_t)(-(int64_t)Value & (int64_t)Value) % 67]; +#endif +} + +/// CountPopulation_64 - this function counts the number of set bits in a value, +/// (64 bit edition.) +INLINE unsigned CountPopulation_64(uint64_t Value) { +#if __GNUC__ >= 4 + return __builtin_popcountll(Value); +#else + uint64_t v = Value - (((Value) >> 1) & 0x5555555555555555ULL); + v = (v & 0x3333333333333333ULL) + (((v) >> 2) & 0x3333333333333333ULL); + v = (v + ((v) >> 4)) & 0x0F0F0F0F0F0F0F0FULL; + return unsigned((uint64_t)(v * 0x0101010101010101ULL) >> 56); +#endif +} + +#endif // LLVM_SUPPORT_MATHEXTRAS_H + + +#ifndef AP_PRIVATE_H +#define AP_PRIVATE_H + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace AESL_std { + template + DataType INLINE min(DataType a, DataType b) { + // if (a >= b) return b; + // else return a; + return (a>=b) ? b : a; + } + + template + DataType INLINE max(DataType a, DataType b) { + // if (a >= b) return a; + // else return b; + return (a>=b) ? a : b; + } +} +enum ap_q_mode { + AP_RND, // rounding to plus infinity + AP_RND_ZERO,// rounding to zero + AP_RND_MIN_INF,// rounding to minus infinity + AP_RND_INF,// rounding to infinity + AP_RND_CONV, // convergent rounding + AP_TRN, // truncation + AP_TRN_ZERO // truncation to zero + +}; +enum ap_o_mode { + AP_SAT, // saturation + AP_SAT_ZERO, // saturation to zero + AP_SAT_SYM, // symmetrical saturation + AP_WRAP, // wrap-around (*) + AP_WRAP_SM // sign magnitude wrap-around (*) +}; + +template struct ap_fixed_base; +template struct af_range_ref; +template struct af_bit_ref; + +template struct ap_range_ref; +template struct ap_bit_ref; +template struct ap_concat_ref; +static bool InvalidDigit(const char* str, unsigned len, unsigned start, unsigned radix) { + unsigned i; + for (i = start; i < len; ++i) + if ((radix == 2 && (str[i] == '0' || str[i] == '1')) || + (radix == 8 && str[i] >= '0' && str[i] <= '7') || + (radix == 10 && str[i] >= '0' && str[i] <= '9') || + (radix == 16 && ((str[i] >= '0' && str[i] <= '9') || + (str[i] >= 'a' && str[i] <= 'f') || + (str[i] >= 'A' && str[i] <= 'F')))) + continue; + else + return true; + return false; +} + +static void ap_parse_sign(const char* str, uint32_t &base, bool &neg) { + if (str[0] == '+' || str[0] == '-') base = 1; + if (str[0] == '-') neg = true; + else neg = false; + return; +} + +static void ap_parse_prefix(const char* str, uint32_t &offset, uint32_t &radix) { + if (str[0] == '0') { + switch (str[1]) { + case 'b': + case 'B': offset = 2; radix = 2; break; + case 'x': + case 'X': offset = 2; radix = 16; break; + case 'd': + case 'D': offset = 2; radix = 10; break; + case 'o': + case 'O': offset = 2; radix = 8; break; + default: break; + } + } + if (offset == 0) + for (int i=0, len = strlen(str); i= 'a') || (str[i] <= 'F' && str[i] >= 'A')) { + radix = 16; + break; + } + return; +} + +/// sub_1 - This function subtracts a single "digit" (64-bit word), y, from +/// the multi-digit integer array, x[], propagating the borrowed 1 value until +/// no further borrowing is neeeded or it runs out of "digits" in x. The result +/// is 1 if "borrowing" exhausted the digits in x, or 0 if x was not exhausted. +/// In other words, if y > x then this function returns 1, otherwise 0. +/// @returns the borrow out of the subtraction +static bool sub_1(uint64_t x[], uint32_t len, uint64_t y) { + for (uint32_t i = 0; i < len; ++i) { + uint64_t __X = x[i]; + x[i] -= y; + if (y > __X) + y = 1; // We have to "borrow 1" from next "digit" + else { + y = 0; // No need to borrow + break; // Remaining digits are unchanged so exit early + } + } + return (y != 0); +} + + /// This enumeration just provides for internal constants used in this + /// translation unit. + enum { + MIN_INT_BITS = 1, ///< Minimum number of bits that can be specified + ///< Note that this must remain synchronized with IntegerType::MIN_INT_BITS + MAX_INT_BITS = (1<<23)-1 ///< Maximum number of bits that can be specified + ///< Note that this must remain synchronized with IntegerType::MAX_INT_BITS + }; + + /// A utility function for allocating memory and checking for allocation + /// failure. The content is not zeroed. + static uint64_t* getMemory(uint32_t numWords) { + return (uint64_t*) malloc(numWords*sizeof(uint64_t)); + } + + //===----------------------------------------------------------------------===// + // ap_private Class + //===----------------------------------------------------------------------===// + + /// ap_private - This class represents arbitrary precision constant integral values. + /// It is a functional replacement for common case unsigned integer type like + /// "unsigned", "unsigned long" or "uint64_t", but also allows non-byte-width + /// integer sizes and large integer value types such as 3-bits, 15-bits, or more + /// than 64-bits of precision. ap_private provides a variety of arithmetic operators + /// and methods to manipulate integer values of any bit-width. It supports both + /// the typical integer arithmetic and comparison operations as well as bitwise + /// manipulation. + /// + /// The class has several invariants worth noting: + /// * All bit, byte, and word positions are zero-based. + /// * Once the bit width is set, it doesn't change except by the Truncate, + /// SignExtend, or ZeroExtend operations. + /// * All binary operators must be on ap_private instances of the same bit width. + /// Attempting to use these operators on instances with different bit + /// widths will yield an assertion. + /// * The value is stored canonically as an unsigned value. For operations + /// where it makes a difference, there are both signed and unsigned variants + /// of the operation. For example, sdiv and udiv. However, because the bit + /// widths must be the same, operations such as Mul and Add produce the same + /// results regardless of whether the values are interpreted as signed or + /// not. + /// * In general, the class tries to follow the style of computation that LLVM + /// uses in its IR. This simplifies its use for LLVM. + /// + /// @brief Class for arbitrary precision integers. + template class ap_private; + namespace ap_private_ops{ + template + INLINE ap_private<_AP_W, _AP_S, _AP_N> lshr(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, uint32_t shiftAmt); + template + INLINE ap_private<_AP_W, _AP_S, _AP_N> shl(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, uint32_t shiftAmt); + } + +#if defined(_MSC_VER) +# if _MSC_VER < 1400 && !defined(for) +# define for if(0);else for +# endif + typedef unsigned __int64 ap_ulong; + typedef signed __int64 ap_slong; +#else + typedef unsigned long long ap_ulong; + typedef signed long long ap_slong; +#endif + template struct retval { + }; + template<> struct retval { + typedef ap_slong Type; + }; + template<> struct retval { + typedef ap_ulong Type; + }; + + template + class ap_private { +#ifdef _MSC_VER +#pragma warning( disable : 4521 4522 ) +#endif +public: + typedef typename retval<_AP_S>::Type ValType; + template friend struct ap_fixed_base; + ///return type of variety of operations + //---------------------------------------------------------- + template + struct RType { + enum { + mult_w = _AP_W+_AP_W2, + mult_s = _AP_S||_AP_S2, + plus_w = AP_MAX(_AP_W+(_AP_S2&&!_AP_S),_AP_W2+(_AP_S&&!_AP_S2))+1, + plus_s = _AP_S||_AP_S2, + minus_w = AP_MAX(_AP_W+(_AP_S2&&!_AP_S),_AP_W2+(_AP_S&&!_AP_S2))+1, + minus_s = true, + div_w = _AP_W+_AP_S2, + div_s = _AP_S||_AP_S2, + mod_w = AP_MIN(_AP_W,_AP_W2+(!_AP_S2&&_AP_S)), + mod_s = _AP_S, + logic_w = AP_MAX(_AP_W+(_AP_S2&&!_AP_S),_AP_W2+(_AP_S&&!_AP_S2)), + logic_s = _AP_S||_AP_S2 + }; + typedef ap_private mult; + typedef ap_private plus; + typedef ap_private minus; + typedef ap_private logic; + typedef ap_private div; + typedef ap_private mod; + typedef ap_private<_AP_W, _AP_S> arg1; + typedef bool reduce; + }; + + INLINE void report() { +#if 0 + if (_AP_W > 1024 && _AP_W <= 4096) { + fprintf(stderr, "[W] W=%d is out of bound (1<=W<=1024): for" + " synthesis: please define macro AP_INT_TYPE_EXT(N)" + " to extend the valid range.\n", _AP_W); + } else +#endif + if (_AP_W > MAX_MODE(AP_INT_MAX_W) * 1024) { + fprintf(stderr, "[E] ap_%sint<%d>: Bitwidth exceeds the " + "default max value %d. Please use macro " + "AP_INT_MAX_W to set a larger max value.\n", + _AP_S?"":"u", _AP_W, + MAX_MODE(AP_INT_MAX_W) * 1024); + exit(1); + } + } + + enum { BitWidth = _AP_W }; + /// This union is used to store the integer value. When the + /// integer bit-width <= 64, it uses VAL, otherwise it uses pVal. + + /// This enum is used to hold the constants we needed for ap_private. + uint64_t VAL; ///< Used to store the <= 64 bits integer value. + uint64_t pVal[_AP_N]; ///< Used to store the >64 bits integer value. + + /// This enum is used to hold the constants we needed for ap_private. + enum { + APINT_BITS_PER_WORD = sizeof(uint64_t) * 8, ///< Bits in a word + APINT_WORD_SIZE = sizeof(uint64_t) ///< Byte size of a word + }; + + enum { excess_bits = (_AP_W%APINT_BITS_PER_WORD) ? APINT_BITS_PER_WORD -(_AP_W%APINT_BITS_PER_WORD) : 0}; + static const uint64_t mask = ((uint64_t)~0ULL >> (excess_bits)); + + /// This constructor is used only internally for speed of construction of + /// temporaries. It is unsafe for general use so it is not public. + /* Constructors */ + + ap_private(const char* val) { + std::string str(val); + uint32_t strLen = str.length(); + const char *strp = str.c_str(); + uint32_t offset = 0; + uint32_t base = 0; + bool neg = false; + uint32_t radix = 16; + ap_parse_sign(strp, base, neg); + ap_parse_prefix(strp + base, offset, radix); + + if ((radix != 10 && neg) || + (strLen - base - offset <= 0) || + InvalidDigit(strp, strLen, base + offset, radix)) { + fprintf(stderr, "invalid character string %s !\n", val); + assert(0); + } + + ap_private ap_private_val(str.c_str(), strLen, radix, base, offset); + if (neg) + ap_private_val = -ap_private_val; + operator = (ap_private_val); + report(); + } + + ap_private(const char* val, int rd) { + std::string str(val); + uint32_t strLen = str.length(); + const char *strp = str.c_str(); + uint32_t offset = 0; + uint32_t base = 0; + uint32_t radix = rd; + bool neg = false; + ap_parse_sign(strp, base, neg); + ap_parse_prefix(strp + base, offset, radix); + + if ((radix != 10 && neg) || + (strLen - base - offset <= 0) || + InvalidDigit(strp, strLen, base + offset, radix)) { + fprintf(stderr, "invalid character string %s !\n", val); + assert(0); + } + + // uint32_t bitsNeeded = ap_private<_AP_W, _AP_S>::getBitsNeeded(strp, strLen, radix); + // ap_private<_AP_W, _AP_S> ap_private_val(bitsNeeded, strp , strLen, radix, base, offset); + ap_private ap_private_val(strp , strLen, radix, base, offset); + if (neg) + ap_private_val = -ap_private_val; + operator = (ap_private_val); + report(); + } + + /// Note that numWords can be smaller or larger than the corresponding bit + /// width but any extraneous bits will be dropped. + /// @param numBits the bit width of the constructed ap_private + /// @param numWords the number of words in bigVal + /// @param bigVal a sequence of words to form the initial value of the ap_private + /// @brief Construct an ap_private of numBits width, initialized as bigVal[]. + ap_private(uint32_t numWords, const uint64_t bigVal[]): VAL(0) { + assert(bigVal && "Null pointer detected!"); + { + // Get memory, cleared to 0 + memset(pVal, 0, _AP_N * sizeof(uint64_t)); + + // Calculate the number of words to copy + uint32_t words = AESL_std::min(numWords, _AP_N); + // Copy the words from bigVal to pVal + memcpy(pVal, bigVal, words * APINT_WORD_SIZE); + if (words >= _AP_W) + clearUnusedBits(); + // Make sure unused high bits are cleared + } + } + + /// This constructor interprets Val as a string in the given radix. The + /// interpretation stops when the first charater that is not suitable for the + /// radix is encountered. Acceptable radix values are 2, 8, 10 and 16. It is + /// an error for the value implied by the string to require more bits than + /// numBits. + /// @param numBits the bit width of the constructed ap_private + /// @param val the string to be interpreted + /// @param radix the radix of Val to use for the intepretation + /// @brief Construct an ap_private from a string representation. + ap_private(const std::string& val, uint8_t radix=2, int base=0, int offset=0): VAL(0) { + assert(!val.empty() && "The input string is empty."); + const char *c_str = val.c_str(); + fromString(c_str+base+offset, val.size()-base-offset, radix); + } + + /// This constructor interprets the slen characters starting at StrStart as + /// a string in the given radix. The interpretation stops when the first + /// character that is not suitable for the radix is encountered. Acceptable + /// radix values are 2, 8, 10 and 16. It is an error for the value implied by + /// the string to require more bits than numBits. + /// @param numBits the bit width of the constructed ap_private + /// @param strStart the start of the string to be interpreted + /// @param slen the maximum number of characters to interpret + /// @param radix the radix to use for the conversion + /// @brief Construct an ap_private from a string representation. + /// This method does not consider whether it is negative or not. + ap_private(const char strStart[], uint32_t slen, uint8_t radix, int base=0, int offset=0) : VAL(0) { + fromString(strStart+base+offset, slen-base-offset, radix); + } + + template + INLINE ap_private(const ap_range_ref<_AP_W2,_AP_S2>& ref) { + *this=ref.get(); + report(); + } + + template + INLINE ap_private(const ap_bit_ref<_AP_W2,_AP_S2>& ref) { + *this = ((uint64_t)(bool)ref); + report(); + } + + template + INLINE ap_private(const ap_concat_ref<_AP_W2, _AP_T2,_AP_W3, _AP_T3>& ref) { + *this=ref.get(); + report(); + } + + template + INLINE ap_private(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2> &val) { + *this = ((val.operator ap_private<_AP_W2, false> ())); + report(); + } + + template + INLINE ap_private(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2> &val) { + *this = (uint64_t)(bool)val; + report(); + } + + /// Simply makes *this a copy of that. + /// @brief Copy Constructor. + template + ap_private(const volatile ap_private<_AP_W1, _AP_S1, _AP_N1>& that): VAL(0) { + operator = (const_cast& >(that)); + } + + template + ap_private(const ap_private<_AP_W1, _AP_S1, _AP_N1>& that): VAL(0) { + operator = (that); + } + + template + explicit ap_private(const ap_private<_AP_W1, _AP_S1, 1>& that): VAL(0) { + static const uint64_t that_sign_ext_mask = (_AP_W1==APINT_BITS_PER_WORD)?0:~0ULL>>(_AP_W1%APINT_BITS_PER_WORD)<<(_AP_W1%APINT_BITS_PER_WORD); + if (that.isNegative()) { + pVal[0] = that.VAL|that_sign_ext_mask; + memset(pVal+1, ~0, sizeof(uint64_t)*(_AP_N-1)); + } else { + pVal[0] = that.VAL; + memset(pVal+1, 0, sizeof(uint64_t)*(_AP_N-1)); + } + clearUnusedBits(); + } + + ap_private(const ap_private& that): VAL(0) { + memcpy(pVal, that.pVal, _AP_N * APINT_WORD_SIZE); + clearUnusedBits(); + } + + /// @brief Destructor. + virtual ~ap_private() {} + + /// Default constructor that creates an uninitialized ap_private. This is useful + /// for object deserialization (pair this with the static method Read). + ap_private(){memset(pVal, 0, sizeof(uint64_t)*(_AP_N));} + + ap_private(uint64_t* val, uint32_t bits=_AP_W) {assert(0);} + ap_private(const uint64_t *const val, uint32_t bits) {assert(0);} + + /// @name Constructors + /// @{ + /// If isSigned is true then val is treated as if it were a signed value + /// (i.e. as an int64_t) and the appropriate sign extension to the bit width + /// will be done. Otherwise, no sign extension occurs (high order bits beyond + /// the range of val are zero filled). + /// @param numBits the bit width of the constructed ap_private + /// @param val the initial value of the ap_private + /// @param isSigned how to treat signedness of val + /// @brief Create a new ap_private of numBits width, initialized as val. +#define CTOR(TYPE, SIGNED) \ + ap_private(TYPE val, bool isSigned=SIGNED) { \ + pVal[0] = val; \ + if (isSigned && int64_t(pVal[0]) < 0) { \ + memset(pVal+1, ~0, sizeof(uint64_t)*(_AP_N-1)); \ + } else { \ + memset(pVal+1, 0, sizeof(uint64_t)*(_AP_N-1)); \ + } \ + clearUnusedBits(); \ + } +#if 1 + CTOR(int, true) + CTOR(bool, false) + CTOR(signed char, true) + CTOR(unsigned char, false) + CTOR(short, true) + CTOR(unsigned short, false) + CTOR(unsigned int, false) + CTOR(long, true) + CTOR(unsigned long, false) + CTOR(unsigned long long, false) + CTOR(long long, true) + CTOR(float, false) + CTOR(double, false) +#undef CTOR +#else + CTOR(uint64_t) +#undef CTOR +#endif + + + /// @returns true if the number of bits <= 64, false otherwise. + /// @brief Determine if this ap_private just has one word to store value. + INLINE bool isSingleWord() const { + return false; + } + + /// @returns the word position for the specified bit position. + /// @brief Determine which word a bit is in. + static uint32_t whichWord(uint32_t bitPosition) { + // return bitPosition / APINT_BITS_PER_WORD; + return (bitPosition) >> 6; + } + + /// @returns the bit position in a word for the specified bit position + /// in the ap_private. + /// @brief Determine which bit in a word a bit is in. + static uint32_t whichBit(uint32_t bitPosition) { + // return bitPosition % APINT_BITS_PER_WORD; + return bitPosition & 0x3f; + } + + /// bit at a specific bit position. This is used to mask the bit in the + /// corresponding word. + /// @returns a uint64_t with only bit at "whichBit(bitPosition)" set + /// @brief Get a single bit mask. + static uint64_t maskBit(uint32_t bitPosition) { + return 1ULL << (whichBit(bitPosition)); + } + + /// @returns the corresponding word for the specified bit position. + /// @brief Get the word corresponding to a bit position + INLINE uint64_t getWord(uint32_t bitPosition) const { + return isSingleWord() ? VAL : pVal[whichWord(bitPosition)]; + } + + /// This method is used internally to clear the to "N" bits in the high order + /// word that are not used by the ap_private. This is needed after the most + /// significant word is assigned a value to ensure that those bits are + /// zero'd out. + /// @brief Clear unused high order bits + INLINE void clearUnusedBits(void) { + pVal[_AP_N-1] = _AP_S ? ((((int64_t)pVal[_AP_N-1])<<(excess_bits))>> excess_bits) : (excess_bits ? ((pVal[_AP_N-1])<<(excess_bits))>>(excess_bits) : pVal[_AP_N-1]); + } + + INLINE void clearUnusedBitsToZero(void) { + pVal[_AP_N-1] &= mask; + } + + INLINE void clearUnusedBitsToOne(void) { + pVal[_AP_N-1] |= mask; + } + + /// This is used by the constructors that take string arguments. + /// @brief Convert a char array into an ap_private + INLINE void fromString(const char *strStart, uint32_t slen, + uint8_t radix) ; + + INLINE ap_private read() volatile { + return *this; + } + + INLINE void write(const ap_private& op2) volatile { + *this = (op2); + } + + //Explicit conversions to C interger types + //----------------------------------------------------------- + operator ValType() const { + return getVal(); + } + + INLINE ValType getVal() const{ + return *pVal; + } + + INLINE int to_int() const { + return int(*this); + } + + INLINE unsigned to_uint() const { + return (unsigned) getVal(); + } + + INLINE long to_long() const { + return (long) getVal(); + } + + INLINE unsigned long to_ulong() const { + return (unsigned long) getVal(); + } + + INLINE ap_slong to_int64() const { + return (ap_slong) getVal(); + } + + INLINE ap_ulong to_uint64() const { + return (ap_ulong) getVal(); + } + + INLINE double to_double() const { + if (isNegative()) + return roundToDouble(true); + else + return roundToDouble(false); + } + + INLINE unsigned length() const { return _AP_W; } + + /*Reverse the contents of ap_private instance. I.e. LSB becomes MSB and vise versa*/ + INLINE ap_private& reverse () { + for (int i = 0; i < _AP_W/2; ++i) { + bool tmp = operator[](i); + if (operator[](_AP_W - 1 - i)) + set(i); + else + clear(i); + if (tmp) + set(_AP_W - 1 - i); + else + clear(_AP_W - 1 - i); + } + clearUnusedBits(); + return *this; + } + + /*Return true if the value of ap_private instance is zero*/ + INLINE bool iszero () const { + return isMinValue(); + } + + /* x < 0 */ + INLINE bool sign () const { + if (isNegative()) + return true; + return false; + } + + /* x[i] = !x[i] */ + INLINE void invert (int i) { + assert( i >= 0 && "Attempting to read bit with negative index"); + assert( i < _AP_W && "Attempting to read bit beyond MSB"); + flip(i); + } + + /* x[i] */ + INLINE bool test (int i) const { + assert( i >= 0 && "Attempting to read bit with negative index"); + assert( i < _AP_W && "Attempting to read bit beyond MSB"); + return operator[](i); + } + + //Set the ith bit into v + INLINE void set (int i, bool v) { + assert( i >= 0 && "Attempting to write bit with negative index"); + assert( i < _AP_W && "Attempting to write bit beyond MSB"); + v ? set(i) : clear(i); + } + + //Set the ith bit into v + INLINE void set_bit (int i, bool v) { + assert( i >= 0 && "Attempting to write bit with negative index"); + assert( i < _AP_W && "Attempting to write bit beyond MSB"); + v ? set(i) : clear(i); + } + + INLINE ap_private& set(uint32_t bitPosition) { + pVal[whichWord(bitPosition)] |= maskBit(bitPosition); + clearUnusedBits(); + return *this; + } + + INLINE void set() { + for (uint32_t i = 0; i < _AP_N; ++i) + pVal[i] = ~0ULL; + clearUnusedBits(); + } + + //Get the value of ith bit + INLINE bool get (int i) const { + assert( i >= 0 && "Attempting to read bit with negative index"); + assert( i < _AP_W && "Attempting to read bit beyond MSB"); + return operator [](i); + } + + //Get the value of ith bit + INLINE bool get_bit (int i) const { + assert( i >= 0 && "Attempting to read bit with negative index"); + assert( i < _AP_W && "Attempting to read bit beyond MSB"); + return operator [](i); + } + + //This is used for sc_lv and sc_bv, which is implemented by sc_uint + //Rotate an ap_private object n places to the left + INLINE void lrotate(int n) { + assert( n >= 0 && "Attempting to shift negative index"); + assert( n < _AP_W && "Shift value larger than bit width"); + operator = (shl(n) | lshr(_AP_W - n)); + } + + //This is used for sc_lv and sc_bv, which is implemented by sc_uint + //Rotate an ap_private object n places to the right + INLINE void rrotate(int n) { + assert( n >= 0 && "Attempting to shift negative index"); + assert( n < _AP_W && "Shift value larger than bit width"); + operator = (lshr(n) | shl(_AP_W - n)); + } + + /// Set the given bit to 0 whose position is given as "bitPosition". + /// @brief Set a given bit to 0. + ap_private& clear(uint32_t bitPosition) { + pVal[whichWord(bitPosition)] &= ~maskBit(bitPosition); + clearUnusedBits(); + return *this; + } + + /// @brief Set every bit to 0. + void clear() { + memset(pVal, 0, _AP_N * APINT_WORD_SIZE); + } + + /// @brief Toggle every bit to its opposite value. + ap_private& flip() { + for (uint32_t i = 0; i < _AP_N; ++i) + pVal[i] ^= ~0ULL; + clearUnusedBits(); + return *this; + } + + /// Toggle a given bit to its opposite value whose position is given + /// as "bitPosition". + /// @brief Toggles a given bit to its opposite value. + ap_private& flip(uint32_t bitPosition) { + assert(bitPosition < BitWidth && "Out of the bit-width range!"); + if ((*this)[bitPosition]) clear(bitPosition); + else set(bitPosition); + return *this; + } + + //complements every bit + INLINE void b_not() { + flip(); + } + + ap_private getLoBits(uint32_t numBits) const { + return ap_private_ops::lshr(ap_private_ops::shl(*this, _AP_W - numBits), + _AP_W - numBits); + } + + ap_private getHiBits(uint32_t numBits) const { + return ap_private_ops::lshr(*this, _AP_W - numBits); + } + + //Binary Arithmetic + //----------------------------------------------------------- + + template + INLINE ap_private + operator & (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) { + return *this & a2.get(); + } + + template + INLINE ap_private + operator | (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) { + return *this | a2.get(); + } + + template + INLINE ap_private + operator ^ (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) { + return *this ^ a2.get(); + } + + + ///Arithmetic assign + //------------------------------------------------------------- + +#define OP_BIN_LOGIC_ASSIGN_AP(Sym) \ + template \ + INLINE ap_private& operator Sym(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { \ + uint32_t numWords = AESL_std::min(_AP_N, _AP_N1); \ + uint32_t i; \ + for (i = 0; i < numWords; ++i) \ + pVal[i] Sym RHS.pVal[i]; \ + if (_AP_N1 < _AP_N) { \ + uint64_t ext = RHS.isNegative()?~0ULL:0; \ + for (;i<_AP_N; i++) \ + pVal[i] Sym ext; \ + } \ + clearUnusedBits(); \ + return *this; \ + } + + OP_BIN_LOGIC_ASSIGN_AP(&=); + OP_BIN_LOGIC_ASSIGN_AP(|=); + OP_BIN_LOGIC_ASSIGN_AP(^=); +#undef OP_BIN_LOGIC_ASSIGN_AP + + /// Adds the RHS APint to this ap_private. + /// @returns this, after addition of RHS. + /// @brief Addition assignment operator. + template + INLINE ap_private& operator+=(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { + add(pVal, pVal, RHS.pVal, _AP_N, _AP_N, _AP_N1, _AP_S, _AP_S1); + clearUnusedBits(); + return *this; + } + + template + INLINE ap_private& operator-=(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { + sub(pVal, pVal, RHS.pVal, _AP_N, _AP_N, _AP_N1, _AP_S, _AP_S1); + clearUnusedBits(); + return *this; + } + + template + ap_private& operator*=(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { + // Get some bit facts about LHS and check for zero + uint32_t lhsBits = getActiveBits(); + uint32_t lhsWords = !lhsBits ? 0 : whichWord(lhsBits - 1) + 1; + if (!lhsWords) { + // 0 * X ===> 0 + return *this; + } + + ap_private dupRHS = RHS; + // Get some bit facts about RHS and check for zero + uint32_t rhsBits = dupRHS.getActiveBits(); + uint32_t rhsWords = !rhsBits ? 0 : whichWord(rhsBits - 1) + 1; + if (!rhsWords) { + // X * 0 ===> 0 + clear(); + return *this; + } + + // Allocate space for the result + uint32_t destWords = rhsWords + lhsWords; + uint64_t *dest = getMemory(destWords); + + // Perform the long multiply + mul(dest, pVal, lhsWords, dupRHS.pVal, rhsWords, destWords); + + // Copy result back into *this + clear(); + uint32_t wordsToCopy = destWords >= _AP_N ? _AP_N : destWords; + + memcpy(pVal, dest, wordsToCopy* APINT_WORD_SIZE); + + uint64_t ext = (isNegative() ^ RHS.isNegative()) ? ~0ULL : 0ULL; + for (int i=wordsToCopy; i<_AP_N; i++) + pVal[i]=ext; + clearUnusedBits(); + // delete dest array and return + free(dest); + return *this; + } + +#define OP_ASSIGN_AP(Sym) \ + template \ + INLINE ap_private& operator Sym##=(const ap_private<_AP_W2,_AP_S2>& op) \ + { \ + *this=operator Sym (op); \ + return *this; \ + } \ + + OP_ASSIGN_AP(/) + OP_ASSIGN_AP(%) +#undef OP_ASSIGN_AP + +#define OP_BIN_LOGIC_AP(Sym) \ + template \ + INLINE \ + typename RType<_AP_W1, _AP_S1>::logic \ + operator Sym (const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) const { \ + enum { numWords = (RType<_AP_W1, _AP_S1>::logic_w +APINT_BITS_PER_WORD-1)/APINT_BITS_PER_WORD}; \ + typename RType<_AP_W1, _AP_S1>::logic Result; \ + uint64_t *val = Result.pVal; \ + uint32_t i; \ + uint32_t min_N = std::min(_AP_N, _AP_N1); \ + uint32_t max_N = std::max(_AP_N, _AP_N1); \ + for (i = 0; i < min_N; ++i) \ + val[i] = pVal[i] Sym RHS.pVal[i]; \ + if (numWords > i) { \ + const uint64_t* tmpVal = (_AP_N>_AP_N1 ? pVal : RHS.pVal)+i; \ + uint64_t ext = ((_AP_N<_AP_N1 && isNegative() )||(_AP_N1 < _AP_N && RHS.isNegative())) ? ~0ULL : 0; \ + for (;i i) { \ + uint64_t ext2 = ((_AP_N>_AP_N1 && isNegative() )||(_AP_N1 > _AP_N && RHS.isNegative())) ? ~0ULL : 0; \ + val[i] = ext Sym ext2; \ + } \ + } \ + Result.clearUnusedBits(); \ + return Result; \ + } + + OP_BIN_LOGIC_AP(|); + OP_BIN_LOGIC_AP(&); + OP_BIN_LOGIC_AP(^); + +#undef OP_BIN_LOGIC_AP + + template + INLINE typename RType<_AP_W1,_AP_S1>::plus operator+(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) const { + // assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + typename RType<_AP_W1,_AP_S1>::plus Result; + bool carry = add(Result.pVal, this->pVal, RHS.pVal, (RType<_AP_W1,_AP_S1>::plus_w + 63) / 64, _AP_N, _AP_N1, _AP_S, _AP_S1); + if ((RType<_AP_W1,_AP_S1>::plus_w + 63) / 64> std::max(_AP_W, _AP_W1) ) + Result.pVal[(RType<_AP_W1,_AP_S1>::plus_w + 63)/64 - 1] = carry; + Result.clearUnusedBits(); + return Result; + } + + template + INLINE typename RType<_AP_W1,_AP_S1>::minus operator-(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) const { + typename RType<_AP_W1,_AP_S1>::minus Result; + bool borrow = sub(Result.pVal, this->pVal, RHS.pVal, (RType<_AP_W1,_AP_S1>::minus_w + 63) / 64, _AP_N, _AP_N1, _AP_S, _AP_S1); + if ((RType<_AP_W1,_AP_S1>::minus_w + 63) / 64 > AESL_std::max(_AP_W, _AP_W1) ) { + Result.pVal[(RType<_AP_W1,_AP_S1>::minus_w+63)/64 - 1] = borrow; + } + Result.clearUnusedBits(); + return Result; + } + + template + typename RType<_AP_W1, _AP_S1>::mult operator*(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) const { + + // Get some bit facts about LHS and check for zero + uint32_t lhsBits = getActiveBits(); + uint32_t lhsWords = !lhsBits ? 0 : whichWord(lhsBits - 1) + 1; + if (!lhsWords) + // 0 * X ===> 0 + return typename RType<_AP_W1, _AP_S1>::mult(); + + // Get some bit facts about RHS and check for zero + uint32_t rhsBits = RHS.getActiveBits(); + uint32_t rhsWords = !rhsBits ? 0 : whichWord(rhsBits - 1) + 1; + if (!rhsWords) { + // X * 0 ===> 0 + return typename RType<_AP_W1, _AP_S1>::mult(); + } + + //extend size to avoid result loss + typename RType<_AP_W1, _AP_S1>::mult dupLHS = *this; + typename RType<_AP_W1, _AP_S1>::mult dupRHS = RHS; + lhsBits = dupLHS.getActiveBits(); + lhsWords = !lhsBits ? 0 : whichWord(lhsBits - 1) + 1; + rhsBits = dupRHS.getActiveBits(); + rhsWords = !rhsBits ? 0 : whichWord(rhsBits - 1) + 1; + + // Allocate space for the result + enum { destWords =(RType<_AP_W1, _AP_S1>::mult_w+APINT_BITS_PER_WORD-1)/APINT_BITS_PER_WORD}; + int destw = destWords; + typename RType<_AP_W1, _AP_S1>::mult Result; + uint64_t *dest = Result.pVal; + uint64_t ext = (isNegative() ^ RHS.isNegative()) ? ~0ULL : 0; + + // Perform the long multiply + mul(dest, dupLHS.pVal, lhsWords, dupRHS.pVal, rhsWords, destWords); + + for (int i=lhsWords+rhsWords; i + INLINE typename RType<_AP_W2,_AP_S2>::div + operator / (const ap_private<_AP_W2,_AP_S2>& op) const { + ap_private lhs=ap_private(*this); + ap_private rhs=ap_private(op); + return typename RType<_AP_W2,_AP_S2>::div((_AP_S||_AP_S2)?lhs.sdiv(rhs):lhs.udiv(rhs)); + } + + template + INLINE typename RType<_AP_W2,_AP_S2>::mod + operator % (const ap_private<_AP_W2,_AP_S2>& op) const { + ap_private lhs=*this; + ap_private rhs= op; + typename RType<_AP_W2,_AP_S2>::mod res = typename RType<_AP_W2,_AP_S2>::mod(_AP_S?lhs.srem(rhs):lhs.urem(rhs)); + return res; + } + + template + INLINE ap_private + operator << (const ap_private<_AP_W2, _AP_S2>& op2) const { + uint32_t sh=op2.to_uint(); + return *this << sh; + } + + INLINE ap_private + operator << (uint32_t sh) const { + ap_private r(*this); + bool overflow=(sh>=length()); + if(overflow) + r.clear(); + else + r = ap_private(r.shl(sh)); + return r; + } + + template + INLINE ap_private + operator >> (const ap_private<_AP_W2, _AP_S2>& op2) const { + uint32_t sh = op2.to_uint(); + return *this >> sh; + } + + INLINE ap_private + operator >> (uint32_t sh) const { + ap_private r(*this); + bool overflow=(sh>=_AP_W); + bool neg_v=r.isNegative(); + if(_AP_S) { + if(overflow) + neg_v?r.set():r.clear(); + else + return r.ashr(sh); + } else { + if(overflow) + r.clear(); + else + return r.lshr(sh); + } + return r; + } + + ///Shift assign + //------------------------------------------------------------------ +#define OP_ASSIGN_AP(Sym) \ + template \ + INLINE ap_private& operator Sym##=(int op) \ + { \ + *this = operator Sym (op); \ + return *this; \ + } \ + INLINE ap_private& operator Sym##=(unsigned int op) \ + { \ + *this = operator Sym (op); \ + return *this; \ + } \ + template \ + INLINE ap_private& operator Sym##=(const ap_private<_AP_W2,_AP_S2>& op) \ + { \ + *this = operator Sym (op); \ + return *this; \ + } + OP_ASSIGN_AP(>>) + OP_ASSIGN_AP(<<) +#undef OP_ASSIGN_AP + ///Comparisons + //----------------------------------------------------------------- + bool operator==(const ap_private& RHS) const { + // Get some facts about the number of bits used in the two operands. + uint32_t n1 = getActiveBits(); + uint32_t n2 = RHS.getActiveBits(); + + // If the number of bits isn't the same, they aren't equal + if (n1 != n2) + return false; + + // If the number of bits fits in a word, we only need to compare the low word. + if (n1 <= APINT_BITS_PER_WORD) + return pVal[0] == RHS.pVal[0]; + + // Otherwise, compare everything + for (int i = whichWord(n1 - 1); i >= 0; --i) + if (pVal[i] != RHS.pVal[i]) + return false; + return true; + } + + template + INLINE bool operator == (const ap_private<_AP_W2, _AP_S2>& op) const { + enum { _AP_MAX_W = AP_MAX(_AP_W+(_AP_S||_AP_S2),_AP_W2+(_AP_S||_AP_S2))}; + ap_private<_AP_MAX_W, _AP_S|_AP_S2> lhs(*this); + ap_private<_AP_MAX_W, _AP_S|_AP_S2> rhs(op); + return lhs==rhs; + } + + bool operator==(uint64_t Val) const { + uint32_t n = getActiveBits(); + if (n <= APINT_BITS_PER_WORD) + return pVal[0] == Val; + else + return false; + } + + template + INLINE bool operator != (const ap_private<_AP_W2, _AP_S2>& op) const { + return !(*this==op); + } + + template + INLINE bool operator!=(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return !((*this) == RHS); + } + + INLINE bool operator!=(uint64_t Val) const { + return !((*this) == Val); + } + + + template + INLINE bool operator <= (const ap_private<_AP_W2,_AP_S2>& op) const { + return !(*this>op); + } + + INLINE bool operator <(const ap_private& op) const { + return _AP_S ? slt(op):ult(op); + } + + template + INLINE bool operator < (const ap_private<_AP_W2, _AP_S2>& op) const { + enum { _AP_MAX_W = AP_MAX(_AP_W+(_AP_S||_AP_S2),_AP_W2+(_AP_S||_AP_S2))}; + ap_private<_AP_MAX_W, _AP_S> lhs(*this); + ap_private<_AP_MAX_W, _AP_S2> rhs(op); + if (_AP_S == _AP_S2) + return _AP_S?lhs.slt(rhs):lhs.ult(rhs); + else + if (_AP_S) + if (_AP_W2 >= _AP_W) + return lhs.ult(rhs); + else + return lhs.slt(rhs); + else + if (_AP_W >= _AP_W2) + return lhs.ult(rhs); + else + return lhs.slt(rhs); + } + + template + INLINE bool operator >=(const ap_private<_AP_W2,_AP_S2>& op) const { + return !(*this + INLINE bool operator > (const ap_private<_AP_W2, _AP_S2>& op) const { + enum { _AP_MAX_W = AP_MAX(_AP_W+(_AP_S||_AP_S2),_AP_W2+(_AP_S||_AP_S2))}; + ap_private<_AP_MAX_W, _AP_S> lhs(*this); + ap_private<_AP_MAX_W, _AP_S2> rhs(op); + if (_AP_S == _AP_S2) + return _AP_S?lhs.sgt(rhs):lhs.ugt(rhs); + else + if (_AP_S) + if (_AP_W2 >= _AP_W) + return lhs.ugt(rhs); + else + return lhs.sgt(rhs); + else + if (_AP_W >= _AP_W2) + return lhs.ugt(rhs); + else + return lhs.sgt(rhs); + } + + ///Bit and Part Select + //-------------------------------------------------------------- + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (int Hi, int Lo) { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (int Hi, int Lo) const { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(const_cast*>(this), Hi, Lo); + } + + INLINE ap_range_ref<_AP_W,_AP_S> + range (int Hi, int Lo) const { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>((const_cast*> (this)), Hi, Lo); + } + + INLINE ap_range_ref<_AP_W,_AP_S> + range (int Hi, int Lo) { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + range (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + range (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) const { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(const_cast(this), Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) const { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + return this->range(Hi, Lo); + } + + INLINE ap_bit_ref<_AP_W,_AP_S> operator [] (uint32_t index) { + assert(index >= 0&&"Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S>( *this, index ); + } + + template + INLINE ap_bit_ref<_AP_W,_AP_S> operator [] (const ap_private<_AP_W2,_AP_S2> &index) { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S>( *this, index.to_int() ); + } + + template + INLINE bool operator [] (const ap_private<_AP_W2,_AP_S2>& index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + ap_bit_ref<_AP_W,_AP_S> br =operator [] (index); + return br.to_bool(); + } + + INLINE bool operator [](uint32_t bitPosition) const { + return (maskBit(bitPosition) & (pVal[whichWord(bitPosition)])) != 0; + } + + INLINE ap_bit_ref<_AP_W,_AP_S> bit (int index) { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S>( *this, index ); + } + + template + INLINE ap_bit_ref<_AP_W,_AP_S> bit (const ap_private<_AP_W2,_AP_S2> &index) { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W &&"Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S>( *this, index.to_int() ); + } + + INLINE bool bit (int index) const { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + ap_bit_ref<_AP_W,_AP_S> br(const_cast*>(this), index); + return br.to_bool(); + } + + template + INLINE bool bit (const ap_private<_AP_W2,_AP_S2>& index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + ap_bit_ref<_AP_W,_AP_S> br = bit(index); + return br.to_bool(); + } + + template + INLINE ap_concat_ref<_AP_W,ap_private<_AP_W, _AP_S>,_AP_W2,ap_private<_AP_W2,_AP_S2> > concat(ap_private<_AP_W2,_AP_S2>& a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_private<_AP_W2,_AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W,ap_private<_AP_W, _AP_S>,_AP_W2,ap_private<_AP_W2,_AP_S2> > concat(const ap_private<_AP_W2,_AP_S2>& a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_private<_AP_W2,_AP_S2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (ap_private<_AP_W2, _AP_S2>& a2) { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (ap_private<_AP_W2, _AP_S2>& a2) const { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(const_cast& >(*this), a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (const ap_private<_AP_W2, _AP_S2>& a2) { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(*this, const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (const ap_private<_AP_W2, _AP_S2>& a2) const { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(const_cast& >(*this), const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > + operator, (const ap_range_ref<_AP_W2, _AP_S2> &a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, + ap_range_ref<_AP_W2, _AP_S2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > + operator, (ap_range_ref<_AP_W2, _AP_S2> &a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, + ap_range_ref<_AP_W2, _AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, ap_bit_ref<_AP_W2, _AP_S2> > + operator, (const ap_bit_ref<_AP_W2, _AP_S2> &a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, + ap_bit_ref<_AP_W2, _AP_S2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, ap_bit_ref<_AP_W2, _AP_S2> > + operator, (ap_bit_ref<_AP_W2, _AP_S2> &a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, + ap_bit_ref<_AP_W2, _AP_S2> >(*this, a2); + } + + template + INLINE + ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > + operator, (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE + ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > + operator, (ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) const { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) const { + return ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, a2); + } + + INLINE ap_private<_AP_W,false> get() const { + ap_private<_AP_W,false> ret(*this); + return ret; + } + + template + INLINE void set(const ap_private<_AP_W3, false> & val) { + operator = (ap_private<_AP_W3, _AP_S>(val)); + } + + /// @} + /// @name Value Tests + /// @{ + /// This tests the high bit of this ap_private to determine if it is set. + /// @returns true if this ap_private is negative, false otherwise + /// @brief Determine sign of this ap_private. + INLINE bool isNegative() const { + //just for get rid of warnings + enum {shift = (_AP_W-APINT_BITS_PER_WORD*(_AP_N-1)-1)}; + static const uint64_t mask = 1ULL << (shift); + return _AP_S && (pVal[_AP_N-1]&mask); + } + + /// This tests the high bit of the ap_private to determine if it is unset. + /// @brief Determine if this ap_private Value is positive (not negative). + INLINE bool isPositive() const { + return !isNegative(); + } + + /// This tests if the value of this ap_private is strictly positive (> 0). + /// @returns true if this ap_private is Positive and not zero. + /// @brief Determine if this ap_private Value is strictly positive. + INLINE bool isStrictlyPositive() const { + return isPositive() && (*this) != 0; + } + + /// This checks to see if the value has all bits of the ap_private are set or not. + /// @brief Determine if all bits are set + INLINE bool isAllOnesValue() const { + return countPopulation() == _AP_W; + } + + /// This checks to see if the value of this ap_private is the maximum unsigned + /// value for the ap_private's bit width. + /// @brief Determine if this is the largest unsigned value. + INLINE bool isMaxValue() const { + return countPopulation() == _AP_W; + } + + /// This checks to see if the value of this ap_private is the maximum signed + /// value for the ap_private's bit width. + /// @brief Determine if this is the largest signed value. + INLINE bool isMaxSignedValue() const { + return BitWidth == 1 ? VAL == 0 : + !isNegative() && countPopulation() == _AP_W - 1; + } + + /// This checks to see if the value of this ap_private is the minimum unsigned + /// value for the ap_private's bit width. + /// @brief Determine if this is the smallest unsigned value. + INLINE bool isMinValue() const { + return countPopulation() == 0; + } + + /// This checks to see if the value of this ap_private is the minimum signed + /// value for the ap_private's bit width. + /// @brief Determine if this is the smallest signed value. + INLINE bool isMinSignedValue() const { + return BitWidth == 1 ? VAL == 1 : + isNegative() && countPopulation() == 1; + } + + /// This function returns a pointer to the internal storage of the ap_private. + /// This is useful for writing out the ap_private in binary form without any + /// conversions. + INLINE const uint64_t* getRawData() const { + if (isSingleWord()) + return &VAL; + return &pVal[0]; + } + + ap_private sqrt() const; + + /// @} + /// @Assignment Operators + /// @{ + /// @returns *this after assignment of RHS. + /// @brief Copy assignment operator. + INLINE ap_private& operator=(const ap_private& RHS) { + if (this != &RHS) + memcpy(pVal, RHS.pVal, _AP_N * APINT_WORD_SIZE); + return *this; + } + INLINE ap_private& operator=(const volatile ap_private& RHS) { + if (this != &RHS) + for (int i=0; i<_AP_N; ++i) + pVal[i] = RHS.pVal[i]; + return *this; + } + INLINE volatile ap_private& operator=(const ap_private& RHS) volatile { + if (this != &RHS) + for (int i=0; i<_AP_N; ++i) + pVal[i] = RHS.pVal[i]; + return *this; + } + INLINE volatile ap_private& operator=(const volatile ap_private& RHS) volatile { + if (this != &RHS) + for (int i=0; i<_AP_N; ++i) + pVal[i] = RHS.pVal[i]; + return *this; + } + + template + INLINE ap_private& operator=(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { + if (_AP_S1) + cpSextOrTrunc(RHS); + else + cpZextOrTrunc(RHS); + clearUnusedBits(); + return *this; + } + + template + INLINE ap_private& operator=(const volatile ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { + if (_AP_S1) + cpSextOrTrunc(RHS); + else + cpZextOrTrunc(RHS); + clearUnusedBits(); + return *this; + } + + template + INLINE ap_private& operator=(const ap_private<_AP_W1, _AP_S1, 1>& RHS) { + static const uint64_t that_sign_ext_mask = (_AP_W1==APINT_BITS_PER_WORD)?0:~0ULL>>(_AP_W1%APINT_BITS_PER_WORD)<<(_AP_W1%APINT_BITS_PER_WORD); + if (RHS.isNegative()) { + pVal[0] = RHS.VAL | that_sign_ext_mask; + memset(pVal+1,~0, APINT_WORD_SIZE*(_AP_N-1)); + } else { + pVal[0] = RHS.VAL; + memset(pVal+1, 0, APINT_WORD_SIZE*(_AP_N-1)); + } + clearUnusedBits(); + return *this; + } + + template + INLINE ap_private& operator=(const volatile ap_private<_AP_W1, _AP_S1, 1>& RHS) { + static const uint64_t that_sign_ext_mask = (_AP_W1==APINT_BITS_PER_WORD)?0:~0ULL>>(_AP_W1%APINT_BITS_PER_WORD)<<(_AP_W1%APINT_BITS_PER_WORD); + if (RHS.isNegative()) { + pVal[0] = RHS.VAL | that_sign_ext_mask; + memset(pVal+1,~0, APINT_WORD_SIZE*(_AP_N-1)); + } else { + pVal[0] = RHS.VAL; + memset(pVal+1, 0, APINT_WORD_SIZE*(_AP_N-1)); + } + clearUnusedBits(); + return *this; + } + + /// @} + /// @name Unary Operators + /// @{ + /// @returns a new ap_private value representing *this incremented by one + /// @brief Postfix increment operator. + INLINE const ap_private operator++(int) { + ap_private API(*this); + ++(*this); + return API; + } + + /// @returns *this incremented by one + /// @brief Prefix increment operator. + INLINE ap_private& operator++() { + add_1(pVal, pVal, _AP_N, 1); + clearUnusedBits(); + return *this; + } + + /// @returns a new ap_private representing *this decremented by one. + /// @brief Postfix decrement operator. + INLINE const ap_private operator--(int) { + ap_private API(*this); + --(*this); + return API; + } + + /// @returns *this decremented by one. + /// @brief Prefix decrement operator. + INLINE ap_private& operator--() { + sub_1(pVal, _AP_N, 1); + clearUnusedBits(); + return *this; + } + + /// Performs a bitwise complement operation on this ap_private. + /// @returns an ap_private that is the bitwise complement of *this + /// @brief Unary bitwise complement operator. + INLINE ap_private operator~() const { + ap_private Result(*this); + Result.flip(); + return Result; + } + + /// Negates *this using two's complement logic. + /// @returns An ap_private value representing the negation of *this. + /// @brief Unary negation operator + INLINE typename RType<1,false>::minus operator-() const { + return ap_private<1,false>(0) - (*this); + } + + /// Performs logical negation operation on this ap_private. + /// @returns true if *this is zero, false otherwise. + /// @brief Logical negation operator. + INLINE bool operator !() const { + for (uint32_t i = 0; i < _AP_N; ++i) + if (pVal[i]) + return false; + return true; + } + + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> And(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return this->operator&(RHS); + } + template + INLINE ap_private Or(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return this->operator|(RHS); + } + template + ap_private Xor(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return this->operator^(RHS); + } + + ap_private Mul(const ap_private& RHS) const { + ap_private Result(*this); + Result *= RHS; + return Result; + } + + ap_private Add(const ap_private& RHS) const { + ap_private Result(0); + bool carry = add(Result.pVal, this->pVal, RHS.pVal, _AP_N, _AP_N, _AP_N, _AP_S, _AP_S); + Result.clearUnusedBits(); + return Result; + } + + ap_private Sub(const ap_private& RHS) const { + ap_private Result(0); + sub(Result.pVal, this->pVal, RHS.pVal, _AP_N, _AP_N, _AP_N, _AP_S, _AP_S); + Result.clearUnusedBits(); + return Result; + } + + /// Arithmetic right-shift this ap_private by shiftAmt. + /// @brief Arithmetic right-shift function. + ap_private ashr(uint32_t shiftAmt) const { + assert(shiftAmt <= BitWidth && "Invalid shift amount, too big"); + // Handle a degenerate case + if (shiftAmt == 0) + return *this; + + // Handle single word shifts with built-in ashr + if (isSingleWord()) { + if (shiftAmt == BitWidth) + return ap_private(/*BitWidth, 0*/); // undefined + else { + uint32_t SignBit = APINT_BITS_PER_WORD - BitWidth; + return ap_private(/*BitWidth,*/ + (((int64_t(VAL) << (SignBit)) >> (SignBit)) >> (shiftAmt))); + } + } + + // If all the bits were shifted out, the result is, technically, undefined. + // We return -1 if it was negative, 0 otherwise. We check this early to avoid + // issues in the algorithm below. + if (shiftAmt == BitWidth) { + if (isNegative()) + return ap_private(-1); + else + return ap_private(0); + } + + // Create some space for the result. + ap_private Retval(0); + uint64_t * val = Retval.pVal; + + // Compute some values needed by the following shift algorithms + uint32_t wordShift = shiftAmt % APINT_BITS_PER_WORD; // bits to shift per word + uint32_t offset = shiftAmt / APINT_BITS_PER_WORD; // word offset for shift + uint32_t breakWord = _AP_N - 1 - offset; // last word affected + uint32_t bitsInWord = whichBit(BitWidth); // how many bits in last word? + if (bitsInWord == 0) + bitsInWord = APINT_BITS_PER_WORD; + + // If we are shifting whole words, just move whole words + if (wordShift == 0) { + // Move the words containing significant bits + for (uint32_t i = 0; i <= breakWord; ++i) + val[i] = pVal[i+offset]; // move whole word + + // Adjust the top significant word for sign bit fill, if negative + if (isNegative()) + if (bitsInWord < APINT_BITS_PER_WORD) + val[breakWord] |= ~0ULL << (bitsInWord); // set high bits + } else { + // Shift the low order words + for (uint32_t i = 0; i < breakWord; ++i) { + // This combines the shifted corresponding word with the low bits from + // the next word (shifted into this word's high bits). + val[i] = ((pVal[i+offset]) >> (wordShift)); + val[i] |= ((pVal[i+offset+1]) << (APINT_BITS_PER_WORD - wordShift)); + } + + // Shift the break word. In this case there are no bits from the next word + // to include in this word. + val[breakWord] = (pVal[breakWord+offset]) >> (wordShift); + + // Deal with sign extenstion in the break word, and possibly the word before + // it. + if (isNegative()) { + if (wordShift > bitsInWord) { + if (breakWord > 0) + val[breakWord-1] |= + ~0ULL << (APINT_BITS_PER_WORD - (wordShift - bitsInWord)); + val[breakWord] |= ~0ULL; + } else + val[breakWord] |= (~0ULL << (bitsInWord - wordShift)); + } + } + + // Remaining words are 0 or -1, just assign them. + uint64_t fillValue = (isNegative() ? ~0ULL : 0); + for (uint32_t i = breakWord+1; i < _AP_N; ++i) + val[i] = fillValue; + Retval.clearUnusedBits(); + return Retval; + } + + /// Logical right-shift this ap_private by shiftAmt. + /// @brief Logical right-shift function. + ap_private lshr(uint32_t shiftAmt) const { + if (isSingleWord()) { + if (shiftAmt == BitWidth) + return ap_private(0); + else + return ap_private((this->VAL) >> (shiftAmt)); + } + + // If all the bits were shifted out, the result is 0. This avoids issues + // with shifting by the size of the integer type, which produces undefined + // results. We define these "undefined results" to always be 0. + if (shiftAmt == BitWidth) + return ap_private(0); + + // If none of the bits are shifted out, the result is *this. This avoids + // issues with shifting byt he size of the integer type, which produces + // undefined results in the code below. This is also an optimization. + if (shiftAmt == 0) + return *this; + + // Create some space for the result. + ap_private Retval(0); + uint64_t * val = Retval.pVal; + + // If we are shifting less than a word, compute the shift with a simple carry + if (shiftAmt < APINT_BITS_PER_WORD) { + uint64_t carry = 0; + for (int i = _AP_N-1; i >= 0; --i) { + val[i] = ((pVal[i]) >> (shiftAmt)) | carry; + carry = (pVal[i]) << (APINT_BITS_PER_WORD - shiftAmt); + } + Retval.clearUnusedBits(); + return Retval; + } + + // Compute some values needed by the remaining shift algorithms + uint32_t wordShift = shiftAmt % APINT_BITS_PER_WORD; + uint32_t offset = shiftAmt / APINT_BITS_PER_WORD; + + // If we are shifting whole words, just move whole words + if (wordShift == 0) { + for (uint32_t i = 0; i < _AP_N - offset; ++i) + val[i] = pVal[i+offset]; + for (uint32_t i = _AP_N-offset; i < _AP_N; i++) + val[i] = 0; + Retval.clearUnusedBits(); + return Retval; + } + + // Shift the low order words + uint32_t breakWord = _AP_N - offset -1; + for (uint32_t i = 0; i < breakWord; ++i) + val[i] = ((pVal[i+offset]) >> (wordShift)) | + ((pVal[i+offset+1]) << (APINT_BITS_PER_WORD - wordShift)); + // Shift the break word. + val[breakWord] = (pVal[breakWord+offset]) >> (wordShift); + + // Remaining words are 0 + for (uint32_t i = breakWord+1; i < _AP_N; ++i) + val[i] = 0; + Retval.clearUnusedBits(); + return Retval; + } + + /// Left-shift this ap_private by shiftAmt. + /// @brief Left-shift function. + ap_private shl(uint32_t shiftAmt) const { + assert(shiftAmt <= BitWidth && "Invalid shift amount, too big"); + if (isSingleWord()) { + if (shiftAmt == BitWidth) + return ap_private(0); // avoid undefined shift results + return ap_private((VAL) << (shiftAmt)); + } + + // If all the bits were shifted out, the result is 0. This avoids issues + // with shifting by the size of the integer type, which produces undefined + // results. We define these "undefined results" to always be 0. + if (shiftAmt == BitWidth) + return ap_private(0); + + // If none of the bits are shifted out, the result is *this. This avoids a + // lshr by the words size in the loop below which can produce incorrect + // results. It also avoids the expensive computation below for a common case. + if (shiftAmt == 0) + return *this; + + // Create some space for the result. + ap_private Retval(0); + uint64_t* val = Retval.pVal; + // If we are shifting less than a word, do it the easy way + if (shiftAmt < APINT_BITS_PER_WORD) { + uint64_t carry = 0; + for (uint32_t i = 0; i < _AP_N; i++) { + val[i] = ((pVal[i]) << (shiftAmt)) | carry; + carry = (pVal[i]) >> (APINT_BITS_PER_WORD - shiftAmt); + } + Retval.clearUnusedBits(); + return Retval; + } + + // Compute some values needed by the remaining shift algorithms + uint32_t wordShift = shiftAmt % APINT_BITS_PER_WORD; + uint32_t offset = shiftAmt / APINT_BITS_PER_WORD; + + // If we are shifting whole words, just move whole words + if (wordShift == 0) { + for (uint32_t i = 0; i < offset; i++) + val[i] = 0; + for (uint32_t i = offset; i < _AP_N; i++) + val[i] = pVal[i-offset]; + Retval.clearUnusedBits(); + return Retval; + } + + // Copy whole words from this to Result. + uint32_t i = _AP_N - 1; + for (; i > offset; --i) + val[i] = (pVal[i-offset]) << (wordShift) | + (pVal[i-offset-1]) >> (APINT_BITS_PER_WORD - wordShift); + val[offset] = (pVal[0]) << (wordShift); + for (i = 0; i < offset; ++i) + val[i] = 0; + Retval.clearUnusedBits(); + return Retval; + } + + INLINE ap_private rotl(uint32_t rotateAmt) const { + if (rotateAmt == 0) + return *this; + // Don't get too fancy, just use existing shift/or facilities + ap_private hi(*this); + ap_private lo(*this); + hi.shl(rotateAmt); + lo.lshr(BitWidth - rotateAmt); + return hi | lo; + } + + INLINE ap_private rotr(uint32_t rotateAmt) const { + if (rotateAmt == 0) + return *this; + // Don't get too fancy, just use existing shift/or facilities + ap_private hi(*this); + ap_private lo(*this); + lo.lshr(rotateAmt); + hi.shl(BitWidth - rotateAmt); + return hi | lo; + } + + /// Perform an unsigned divide operation on this ap_private by RHS. Both this and + /// RHS are treated as unsigned quantities for purposes of this division. + /// @returns a new ap_private value containing the division result + /// @brief Unsigned division operation. + ap_private udiv(const ap_private& RHS) const { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + + // First, deal with the easy case + if (isSingleWord()) { + assert(RHS.VAL != 0 && "Divide by zero?"); + return ap_private(VAL / RHS.VAL); + } + + // Get some facts about the LHS and RHS number of bits and words + uint32_t rhsBits = RHS.getActiveBits(); + uint32_t rhsWords = !rhsBits ? 0 : (whichWord(rhsBits - 1) + 1); + assert(rhsWords && "Divided by zero???"); + uint32_t lhsBits = this->getActiveBits(); + uint32_t lhsWords = !lhsBits ? 0 : (whichWord(lhsBits - 1) + 1); + + // Deal with some degenerate cases + if (!lhsWords) + // 0 / X ===> 0 + return ap_private(0); + else if (lhsWords < rhsWords || this->ult(RHS)) { + // X / Y ===> 0, iff X < Y + return ap_private(0); + } else if (*this == RHS) { + // X / X ===> 1 + return ap_private(1); + } else if (lhsWords == 1 && rhsWords == 1) { + // All high words are zero, just use native divide + return ap_private(this->pVal[0] / RHS.pVal[0]); + } + + // We have to compute it the hard way. Invoke the Knuth divide algorithm. + ap_private Quotient(0); // to hold result. + divide(*this, lhsWords, RHS, rhsWords, &Quotient, (ap_private*)0); + return Quotient; + } + + /// Signed divide this ap_private by ap_private RHS. + /// @brief Signed division function for ap_private. + INLINE ap_private sdiv(const ap_private& RHS) const { + if (isNegative()) + if (RHS.isNegative()) + return (-(*this)).udiv(-RHS); + else + return -((-(*this)).udiv(RHS)); + else if (RHS.isNegative()) + return -(this->udiv(-RHS)); + return this->udiv(RHS); + } + + /// Perform an unsigned remainder operation on this ap_private with RHS being the + /// divisor. Both this and RHS are treated as unsigned quantities for purposes + /// of this operation. Note that this is a true remainder operation and not + /// a modulo operation because the sign follows the sign of the dividend + /// which is *this. + /// @returns a new ap_private value containing the remainder result + /// @brief Unsigned remainder operation. + ap_private urem(const ap_private& RHS) const { + if (isSingleWord()) { + assert(RHS.VAL != 0 && "Remainder by zero?"); + return ap_private(VAL % RHS.VAL); + } + + // Get some facts about the LHS + uint32_t lhsBits = getActiveBits(); + uint32_t lhsWords = !lhsBits ? 0 : (whichWord(lhsBits - 1) + 1); + + // Get some facts about the RHS + uint32_t rhsBits = RHS.getActiveBits(); + uint32_t rhsWords = !rhsBits ? 0 : (whichWord(rhsBits - 1) + 1); + assert(rhsWords && "Performing remainder operation by zero ???"); + + // Check the degenerate cases + if (lhsWords == 0) { + // 0 % Y ===> 0 + return ap_private(0); + } else if (lhsWords < rhsWords || this->ult(RHS)) { + // X % Y ===> X, iff X < Y + return *this; + } else if (*this == RHS) { + // X % X == 0; + return ap_private(0); + } else if (lhsWords == 1) { + // All high words are zero, just use native remainder + return ap_private(pVal[0] % RHS.pVal[0]); + } + + // We have to compute it the hard way. Invoke the Knuth divide algorithm. + ap_private Remainder(0); + divide(*this, lhsWords, RHS, rhsWords, (ap_private*)(0), &Remainder); + return Remainder; + } + + ap_private urem(uint64_t RHS) const { + // Get some facts about the LHS + uint32_t lhsBits = getActiveBits(); + uint32_t lhsWords = !lhsBits ? 0 : (whichWord(lhsBits - 1) + 1); + // Get some facts about the RHS + uint32_t rhsBits = 64 - CountLeadingZeros_64(RHS); // RHS.getActiveBits(); + uint32_t rhsWords = 1;//!rhsBits ? 0 : (ap_private<_AP_W, _AP_S, _AP_N>::whichWord(rhsBits - 1) + 1); + assert(rhsWords && "Performing remainder operation by zero ???"); + // Check the degenerate cases + if (lhsWords == 0) { + // 0 % Y ===> 0 + return ap_private(0); + } else if (lhsWords < rhsWords || this->ult(RHS)) { + // X % Y ===> X, iff X < Y + return *this; + } else if (*this == RHS) { + // X % X == 0; + return ap_private(0); + } else if (lhsWords == 1) { + // All high words are zero, just use native remainder + return ap_private(pVal[0] % RHS); + } + + // We have to compute it the hard way. Invoke the Knuth divide algorithm. + ap_private Remainder(0); + divide(*this, lhsWords, RHS, (ap_private*)(0), &Remainder); + return Remainder; + } + + /// Signed remainder operation on ap_private. + /// @brief Function for signed remainder operation. + INLINE ap_private srem(const ap_private& RHS) const { + if (isNegative()) { + ap_private lhs = -(*this); + if (RHS.isNegative()) { + ap_private rhs = -RHS; + return -(lhs.urem(rhs)); + } else + return -(lhs.urem(RHS)); + } else if (RHS.isNegative()) { + ap_private rhs = -RHS; + return this->urem(rhs); + } + return this->urem(RHS); + } + + /// Signed remainder operation on ap_private. + /// @brief Function for signed remainder operation. + INLINE ap_private srem(int64_t RHS) const { + if (isNegative()) + if (RHS<0) + return -((-(*this)).urem(-RHS)); + else + return -((-(*this)).urem(RHS)); + else if (RHS<0) + return this->urem(-RHS); + return this->urem(RHS); + } + + /// Sometimes it is convenient to divide two ap_private values and obtain both + /// the quotient and remainder. This function does both operations in the + /// same computation making it a little more efficient. + /// @brief Dual division/remainder interface. + static void udivrem(const ap_private& LHS, const ap_private& RHS, ap_private &Quotient, ap_private& Remainder) { + // Get some size facts about the dividend and divisor + uint32_t lhsBits = LHS.getActiveBits(); + uint32_t lhsWords = !lhsBits ? 0 : (ap_private::whichWord(lhsBits - 1) + 1); + uint32_t rhsBits = RHS.getActiveBits(); + uint32_t rhsWords = !rhsBits ? 0 : (ap_private::whichWord(rhsBits - 1) + 1); + + // Check the degenerate cases + if (lhsWords == 0) { + Quotient = 0; // 0 / Y ===> 0 + Remainder = 0; // 0 % Y ===> 0 + return; + } + + if (lhsWords < rhsWords || LHS.ult(RHS)) { + Quotient = 0; // X / Y ===> 0, iff X < Y + Remainder = LHS; // X % Y ===> X, iff X < Y + return; + } + + if (LHS == RHS) { + Quotient = 1; // X / X ===> 1 + Remainder = 0; // X % X ===> 0; + return; + } + + if (lhsWords == 1 && rhsWords == 1) { + // There is only one word to consider so use the native versions. + if (LHS.isSingleWord()) { + Quotient = ap_private(LHS.VAL / RHS.VAL); + Remainder = ap_private(LHS.VAL % RHS.VAL); + } else { + Quotient = ap_private(LHS.pVal[0] / RHS.pVal[0]); + Remainder = ap_private(LHS.pVal[0] % RHS.pVal[0]); + } + return; + } + + // Okay, lets do it the long way + divide(LHS, lhsWords, RHS, rhsWords, &Quotient, &Remainder); + } + + static void sdivrem(const ap_private &LHS, const ap_private &RHS, + ap_private &Quotient, ap_private &Remainder) { + if (LHS.isNegative()) { + if (RHS.isNegative()) + ap_private::udivrem(-LHS, -RHS, Quotient, Remainder); + else + ap_private::udivrem(-LHS, RHS, Quotient, Remainder); + Quotient = -Quotient; + Remainder = -Remainder; + } else if (RHS.isNegative()) { + ap_private::udivrem(LHS, -RHS, Quotient, Remainder); + Quotient = -Quotient; + } else { + ap_private::udivrem(LHS, RHS, Quotient, Remainder); + } + } + + /// Compares this ap_private with RHS for the validity of the equality + /// relationship. + /// @returns true if *this == Val + /// @brief Equality comparison. + template + INLINE bool eq(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return (*this) == RHS; + } + + /// Compares this ap_private with RHS for the validity of the inequality + /// relationship. + /// @returns true if *this != Val + /// @brief Inequality comparison + template + INLINE bool ne(const ap_private<_AP_W, _AP_S1, _AP_N> &RHS) const { + return !((*this) == RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// the validity of the less-than relationship. + /// @returns true if *this < RHS when both are considered unsigned. + /// @brief Unsigned less than comparison + template + INLINE bool ult(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + // Get active bit length of both operands + uint32_t n1 = getActiveBits(); + uint32_t n2 = RHS.getActiveBits(); + + // If magnitude of LHS is less than RHS, return true. + if (n1 < n2) + return true; + + // If magnitude of RHS is greather than LHS, return false. + if (n2 < n1) + return false; + + // If they bot fit in a word, just compare the low order word + if (n1 <= APINT_BITS_PER_WORD && n2 <= APINT_BITS_PER_WORD) + return pVal[0] < RHS.pVal[0]; + + // Otherwise, compare all words + uint32_t topWord = whichWord(AESL_std::max(n1,n2)-1); + for (int i = topWord; i >= 0; --i) { + if (pVal[i] > RHS.pVal[i]) + return false; + if (pVal[i] < RHS.pVal[i]) + return true; + } + return false; + } + + INLINE bool ult(uint64_t RHS) const { + // Get active bit length of both operands + uint32_t n1 = getActiveBits(); + uint32_t n2 = 64 - CountLeadingZeros_64(RHS); //RHS.getActiveBits(); + + // If magnitude of LHS is less than RHS, return true. + if (n1 < n2) + return true; + + // If magnitude of RHS is greather than LHS, return false. + if (n2 < n1) + return false; + + // If they bot fit in a word, just compare the low order word + if (n1 <= APINT_BITS_PER_WORD && n2 <= APINT_BITS_PER_WORD) + return pVal[0] < RHS; + assert(0); + } + + template + INLINE bool slt(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + ap_private lhs(*this); + ap_private<_AP_W, _AP_S1, _AP_N> rhs(RHS); + bool lhsNeg = isNegative(); + bool rhsNeg = rhs.isNegative(); + if (lhsNeg) { + // Sign bit is set so perform two's complement to make it positive + lhs.flip(); + lhs++; + } + if (rhsNeg) { + // Sign bit is set so perform two's complement to make it positive + rhs.flip(); + rhs++; + } + + // Now we have unsigned values to compare so do the comparison if necessary + // based on the negativeness of the values. + if (lhsNeg) + if (rhsNeg) + return lhs.ugt(rhs); + else + return true; + else if (rhsNeg) + return false; + else + return lhs.ult(rhs); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// validity of the less-or-equal relationship. + /// @returns true if *this <= RHS when both are considered unsigned. + /// @brief Unsigned less or equal comparison + template + INLINE bool ule(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return ult(RHS) || eq(RHS); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the less-or-equal relationship. + /// @returns true if *this <= RHS when both are considered signed. + /// @brief Signed less or equal comparison + template + INLINE bool sle(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return slt(RHS) || eq(RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// the validity of the greater-than relationship. + /// @returns true if *this > RHS when both are considered unsigned. + /// @brief Unsigned greather than comparison + template + INLINE bool ugt(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return !ult(RHS) && !eq(RHS); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// the validity of the greater-than relationship. + /// @returns true if *this > RHS when both are considered signed. + /// @brief Signed greather than comparison + template + INLINE bool sgt(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return !slt(RHS) && !eq(RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// validity of the greater-or-equal relationship. + /// @returns true if *this >= RHS when both are considered unsigned. + /// @brief Unsigned greater or equal comparison + template + INLINE bool uge(const ap_private<_AP_W, _AP_S, _AP_N>& RHS) const { + return !ult(RHS); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the greater-or-equal relationship. + /// @returns true if *this >= RHS when both are considered signed. + /// @brief Signed greather or equal comparison + template + INLINE bool sge(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return !slt(RHS); + } + + template + void cpTrunc(const ap_private<_AP_W1, _AP_S1, _AP_N1>& that) { + assert(_AP_W1 > BitWidth && "Invalid ap_private Truncate request"); + assert(_AP_W1 >= MIN_INT_BITS && "Can't truncate to 0 bits"); + memcpy(pVal, that.pVal, _AP_N*APINT_WORD_SIZE); + } + + // Sign extend to a new width. + template + void cpSext(const ap_private<_AP_W1, _AP_S1, _AP_N1>& that) { + assert(_AP_W1 < BitWidth && "Invalid ap_private SignExtend request"); + assert(_AP_W1 <= MAX_INT_BITS && "Too many bits"); + // If the sign bit isn't set, this is the same as zext. + if (!that.isNegative()) { + cpZext(that); + return; + } + + // The sign bit is set. First, get some facts + enum { wordBits = _AP_W1 % APINT_BITS_PER_WORD}; + + // Mask the high order word appropriately + if (_AP_N1 == _AP_N) { + enum { newWordBits = _AP_W % APINT_BITS_PER_WORD}; + // The extension is contained to the wordsBefore-1th word. + static const uint64_t mask = wordBits?(~0ULL<<(wordBits)):0ULL; + if (_AP_N1 == 1) { + assert(0); + } else { + for (uint32_t i = 0; i < _AP_N1; ++i) + pVal[i] = that.pVal[i]; + pVal[_AP_N1-1] |= mask; + return; + } + } + + if (_AP_N1 == 1) { + assert(0);// newVal[0] = VAL | mask; + } else { + enum { newWordBits = _AP_W % APINT_BITS_PER_WORD}; + // The extension is contained to the wordsBefore-1th word. + static const uint64_t mask = wordBits?(~0ULL<<(wordBits)):0ULL; + for (uint32_t i = 0; i < _AP_N1; ++i) + pVal[i] = that.pVal[i]; + pVal[_AP_N1-1] |= mask; + } + for (uint32_t i=_AP_N1; i < _AP_N-1; i++) + pVal[i] = ~0ULL; + pVal[_AP_N-1] = ~0ULL; + clearUnusedBits(); + return; + } + + // Zero extend to a new width. + template + void cpZext(const ap_private<_AP_W1, _AP_S1, _AP_N1>& that) { + assert(_AP_W1 < BitWidth && "Invalid ap_private ZeroExtend request"); + assert(_AP_W1 <= MAX_INT_BITS && "Too many bits"); + uint32_t wordsAfter = _AP_N; + if (wordsAfter==1) { + assert(0); // return ap_private<_AP_W1, _AP_S, _AP_N1> (_AP_W1, VAL, _AP_S); + } else { + if (_AP_N1 == 1) { + assert(0); + // newVal[0] = VAL; + } else { + uint32_t i = 0; + for (; i < _AP_N1; ++i) + pVal[i] = that.pVal[i]; + for (; i < _AP_N; ++i) + pVal[i] = 0; + } + } + clearUnusedBits(); + } + + template + void cpZextOrTrunc(const ap_private<_AP_W1, _AP_S1, _AP_N1>& that) { + if (BitWidth > _AP_W1) + cpZext(that); + else if (BitWidth < _AP_W1) + cpTrunc(that); + else { + for (int i=0; i<_AP_N1; ++i) + pVal[i]=that.pVal[i]; + clearUnusedBits(); + } + } + + template + void cpSextOrTrunc(const ap_private<_AP_W1, _AP_S1, _AP_N1>& that) { + if (BitWidth > _AP_W1) + cpSext(that); + else if (BitWidth < _AP_W1) + cpTrunc(that); + else { + for (int i=0; i<_AP_N1; ++i) + pVal[i] = that.pVal[i]; + clearUnusedBits(); + } + } + + /// @name Value Characterization Functions + /// @{ + + /// @returns the total number of bits. + INLINE uint32_t getBitWidth() const { + return BitWidth; + } + + /// Here one word's bitwidth equals to that of uint64_t. + /// @returns the number of words to hold the integer value of this ap_private. + /// @brief Get the number of words. + INLINE uint32_t getNumWords() const { + return (BitWidth + APINT_BITS_PER_WORD - 1) / APINT_BITS_PER_WORD; + } + + /// This function returns the number of active bits which is defined as the + /// bit width minus the number of leading zeros. This is used in several + /// computations to see how "wide" the value is. + /// @brief Compute the number of active bits in the value + INLINE uint32_t getActiveBits() const { + uint32_t bits=BitWidth - countLeadingZeros(); + return bits?bits:1; + } + + + /// This method attempts to return the value of this ap_private as a zero extended + /// uint64_t. The bitwidth must be <= 64 or the value must fit within a + /// uint64_t. Otherwise an assertion will result. + /// @brief Get zero extended value + INLINE uint64_t getZExtValue() const { + assert(getActiveBits() <= 64 && "Too many bits for uint64_t"); + return *pVal; + } + + /// This method attempts to return the value of this ap_private as a sign extended + /// int64_t. The bit width must be <= 64 or the value must fit within an + /// int64_t. Otherwise an assertion will result. + /// @brief Get sign extended value + INLINE int64_t getSExtValue() const { + assert(getActiveBits() <= 64 && "Too many bits for int64_t"); + return int64_t(pVal[0]); + } + + /// This method determines how many bits are required to hold the ap_private + /// equivalent of the string given by \p str of length \p slen. + /// @brief Get bits required for string value. + static uint32_t getBitsNeeded(const char* str, uint32_t slen, uint8_t radix); + + /// countLeadingZeros - This function is an ap_private version of the + /// countLeadingZeros_{32,64} functions in MathExtras.h. It counts the number + /// of zeros from the most significant bit to the first one bit. + /// @returns BitWidth if the value is zero. + /// @returns the number of zeros from the most significant bit to the first + /// one bits. + INLINE uint32_t countLeadingZeros() const ; + + /// countLeadingOnes - This function counts the number of contiguous 1 bits + /// in the high order bits. The count stops when the first 0 bit is reached. + /// @returns 0 if the high order bit is not set + /// @returns the number of 1 bits from the most significant to the least + /// @brief Count the number of leading one bits. + INLINE uint32_t countLeadingOnes() const ; + + /// countTrailingZeros - This function is an ap_private version of the + /// countTrailingZoers_{32,64} functions in MathExtras.h. It counts + /// the number of zeros from the least significant bit to the first set bit. + /// @returns BitWidth if the value is zero. + /// @returns the number of zeros from the least significant bit to the first + /// one bit. + /// @brief Count the number of trailing zero bits. + INLINE uint32_t countTrailingZeros() const ; + + /// countPopulation - This function is an ap_private version of the + /// countPopulation_{32,64} functions in MathExtras.h. It counts the number + /// of 1 bits in the ap_private value. + /// @returns 0 if the value is zero. + /// @returns the number of set bits. + /// @brief Count the number of bits set. + INLINE uint32_t countPopulation() const { + uint32_t Count = 0; + for (uint32_t i = 0; i<_AP_N-1 ; ++i) + Count += CountPopulation_64(pVal[i]); + Count += CountPopulation_64(pVal[_AP_N-1]&mask); + return Count; + } + + /// @} + /// @name Conversion Functions + /// @{ + + /// This is used internally to convert an ap_private to a string. + /// @brief Converts an ap_private to a std::string + INLINE std::string toString(uint8_t radix, bool wantSigned) const + ; + + /// Considers the ap_private to be unsigned and converts it into a string in the + /// radix given. The radix can be 2, 8, 10 or 16. + /// @returns a character interpretation of the ap_private + /// @brief Convert unsigned ap_private to string representation. + INLINE std::string toStringUnsigned(uint8_t radix = 10) const { + return toString(radix, false); + } + + /// Considers the ap_private to be unsigned and converts it into a string in the + /// radix given. The radix can be 2, 8, 10 or 16. + /// @returns a character interpretation of the ap_private + /// @brief Convert unsigned ap_private to string representation. + INLINE std::string toStringSigned(uint8_t radix = 10) const { + return toString(radix, true); + } + + /// @returns a byte-swapped representation of this ap_private Value. + INLINE ap_private byteSwap() const ; + + /// @brief Converts this ap_private to a double value. + INLINE double roundToDouble(bool isSigned) const ; + + /// @brief Converts this unsigned ap_private to a double value. + INLINE double roundToDouble() const { + return roundToDouble(false); + } + + /// @brief Converts this signed ap_private to a double value. + INLINE double signedRoundToDouble() const { + return roundToDouble(true); + } + + /// The conversion does not do a translation from integer to double, it just + /// re-interprets the bits as a double. Note that it is valid to do this on + /// any bit width. Exactly 64 bits will be translated. + /// @brief Converts ap_private bits to a double + INLINE double bitsToDouble() const { + union { + uint64_t __I; + double __D; + } __T; + __T.__I = pVal[0]; + return __T.__D; + } + + /// The conversion does not do a translation from integer to float, it just + /// re-interprets the bits as a float. Note that it is valid to do this on + /// any bit width. Exactly 32 bits will be translated. + /// @brief Converts ap_private bits to a double + INLINE float bitsToFloat() const { + union { + uint32_t __I; + float __F; + } __T; + __T.__I = uint32_t(pVal[0]); + return __T.__F; + } + + /// The conversion does not do a translation from double to integer, it just + /// re-interprets the bits of the double. Note that it is valid to do this on + /// any bit width but bits from V may get truncated. + /// @brief Converts a double to ap_private bits. + INLINE ap_private& doubleToBits(double __V) { + union { + uint64_t __I; + double __D; + } __T; + __T.__D = __V; + pVal[0] = __T.__I; + return *this; + } + + /// The conversion does not do a translation from float to integer, it just + /// re-interprets the bits of the float. Note that it is valid to do this on + /// any bit width but bits from V may get truncated. + /// @brief Converts a float to ap_private bits. + INLINE ap_private& floatToBits(float __V) { + union { + uint32_t __I; + float __F; + } __T; + __T.__F = __V; + pVal[0] = __T.__I; + } + + //Reduce operation + //----------------------------------------------------------- + INLINE bool and_reduce() const { + return isMaxValue(); + } + + INLINE bool nand_reduce() const { + return isMinValue(); + } + + INLINE bool or_reduce() const { + return (bool)countPopulation(); + } + + INLINE bool nor_reduce() const { + return countPopulation()==0; + } + + INLINE bool xor_reduce() const { + unsigned int i=countPopulation(); + return (i%2)?true:false; + } + + INLINE bool xnor_reduce() const { + unsigned int i=countPopulation(); + return (i%2)?false:true; + } + INLINE std::string to_string(uint8_t radix=16, bool sign=false) const { + return toString(radix, radix==10?_AP_S:sign); + } +}; + +template +INLINE bool operator==(uint64_t V1, const ap_private<_AP_W, _AP_S, _AP_N>& V2) { + return V2 == V1; +} + +template +INLINE bool operator!=(uint64_t V1, const ap_private<_AP_W, _AP_S, _AP_N>& V2) { + return V2 != V1; +} + +namespace ap_private_ops { + enum {APINT_BITS_PER_WORD=64}; + /// @brief Determine the smaller of two ap_privates considered to be signed. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> smin(const ap_private<_AP_W, _AP_S, _AP_N> &LHS, const ap_private<_AP_W, _AP_S1, _AP_N> &RHS) { + return LHS.slt(RHS) ? LHS : RHS; + } + + /// @brief Determine the larger of two ap_privates considered to be signed. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> smax(const ap_private<_AP_W, _AP_S, _AP_N> &LHS, const ap_private<_AP_W, _AP_S1, _AP_N> &RHS) { + return LHS.sgt(RHS) ? LHS : RHS; + } + + /// @brief Determine the smaller of two ap_privates considered to be signed. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> umin(const ap_private<_AP_W, _AP_S, _AP_N> &LHS, const ap_private<_AP_W, _AP_S1, _AP_N> &RHS) { + return LHS.ult(RHS) ? LHS : RHS; + } + + /// @brief Determine the larger of two ap_privates considered to be unsigned. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> umax(const ap_private<_AP_W, _AP_S, _AP_N> &LHS, const ap_private<_AP_W, _AP_S1, _AP_N> &RHS) { + return LHS.ugt(RHS) ? LHS : RHS; + } + + /// @brief Check if the specified ap_private has a N-bits integer value. + template + INLINE bool isIntN(uint32_t __N, const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.isIntN(__N); + } + + /// @returns true if the argument ap_private value is a sequence of ones + /// starting at the least significant bit with the remainder zero. + template + INLINE bool isMask(uint32_t numBits, const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.getBoolValue() && ((APIVal + ap_private<_AP_W, _AP_S, _AP_N>(numBits,1)) & APIVal) == 0; + } + + /// @returns true if the argument ap_private value contains a sequence of ones + /// with the remainder zero. + template + INLINE bool isShiftedMask(uint32_t numBits, const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return isMask(numBits, (APIVal - ap_private<_AP_W, _AP_S, _AP_N>(numBits,1)) | APIVal); + } + + /// @returns a byte-swapped representation of the specified ap_private Value. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> byteSwap(const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.byteSwap(); + } + + /// @returns the floor log base 2 of the specified ap_private value. + template INLINE uint32_t logBase2(const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.logBase2(); + } + + /// GreatestCommonDivisor - This function returns the greatest common + /// divisor of the two ap_private values using Enclid's algorithm. + /// @returns the greatest common divisor of Val1 and Val2 + /// @brief Compute GCD of two ap_private values. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> GreatestCommonDivisor(const ap_private<_AP_W, _AP_S, _AP_N>& Val1, const ap_private<_AP_W, _AP_S, _AP_N>& Val2) + ; + + /// Treats the ap_private as an unsigned value for conversion purposes. + /// @brief Converts the given ap_private to a double value. + template INLINE double Roundap_privateToDouble(const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.roundToDouble(); + } + + /// Treats the ap_private as a signed value for conversion purposes. + /// @brief Converts the given ap_private to a double value. + template INLINE double RoundSignedap_privateToDouble(const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.signedRoundToDouble(); + } + + /// @brief Converts the given ap_private to a float vlalue. + template INLINE float Roundap_privateToFloat(const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return float(Roundap_privateToDouble(APIVal)); + } + + /// Treast the ap_private as a signed value for conversion purposes. + /// @brief Converts the given ap_private to a float value. + template INLINE float RoundSignedap_privateToFloat(const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return float(APIVal.signedRoundToDouble()); + } + + /// RoundDoubleToap_private - This function convert a double value to an ap_private value. + /// @brief Converts the given double value into a ap_private. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> RoundDoubleToap_private(double Double, uint32_t width) ; + + /// RoundFloatToap_private - Converts a float value into an ap_private value. + /// @brief Converts a float value into a ap_private. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> RoundFloatToap_private(float Float, uint32_t width) { + return RoundDoubleToap_private<_AP_W, _AP_S, _AP_N>(double(Float), width); + } + + /// Arithmetic right-shift the ap_private by shiftAmt. + /// @brief Arithmetic right-shift function. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> ashr(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, uint32_t shiftAmt) { + return LHS.ashr(shiftAmt); + } + + /// Logical right-shift the ap_private by shiftAmt. + /// @brief Logical right-shift function. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> lshr(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, uint32_t shiftAmt) { + return LHS.lshr(shiftAmt); + } + + /// Left-shift the ap_private by shiftAmt. + /// @brief Left-shift function. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> shl(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, uint32_t shiftAmt) { + return LHS.shl(shiftAmt); + } + + /// Signed divide ap_private LHS by ap_private RHS. + /// @brief Signed division function for ap_private. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> sdiv(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS.sdiv(RHS); + } + + /// Unsigned divide ap_private LHS by ap_private RHS. + /// @brief Unsigned division function for ap_private. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> udiv(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS.udiv(RHS); + } + + /// Signed remainder operation on ap_private. + /// @brief Function for signed remainder operation. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> srem(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS.srem(RHS); + } + + /// Unsigned remainder operation on ap_private. + /// @brief Function for unsigned remainder operation. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> urem(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS.urem(RHS); + } + + /// Performs multiplication on ap_private values. + /// @brief Function for multiplication operation. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> mul(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS * RHS; + } + + /// Performs addition on ap_private values. + /// @brief Function for addition operation. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> add(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS + RHS; + } + + /// Performs subtraction on ap_private values. + /// @brief Function for subtraction operation. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> sub(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS - RHS; + } + + /// Performs bitwise AND operation on ap_private LHS and + /// ap_private RHS. + /// @brief Bitwise AND function for ap_private. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> And(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS & RHS; + } + + /// Performs bitwise OR operation on ap_private LHS and ap_private RHS. + /// @brief Bitwise OR function for ap_private. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> Or(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS | RHS; + } + + /// Performs bitwise XOR operation on ap_private. + /// @brief Bitwise XOR function for ap_private. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> Xor(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS ^ RHS; + } + + /// Performs a bitwise complement operation on ap_private. + /// @brief Bitwise complement function. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> Not(const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return ~APIVal; + } + + template void clearUnusedBits(uint64_t& msw) { + // Compute how many bits are used in the final word + // uint32_t wordBits = APIVal.getBitWidth() & 0x3f; + if (wordBits == 0) + // If all bits are used, we want to leave the value alone. This also + // avoids the undefined behavior of >> when the shfit is the same size as + // the word size (64). + return; + + // Mask out the hight bits. + uint64_t mask = ~uint64_t(0ULL) >> (64 /*ap_private::APINT_BITS_PER_WORD */- wordBits); + msw &= mask; + } + template <> INLINE void clearUnusedBits<1>(uint64_t& msw) { + uint64_t mask = ~uint64_t(0ULL) >> (64 /*ap_private::APINT_BITS_PER_WORD */- 1); + msw &= mask; + } + template void clearUnusedBits(int64_t& msw) { + // Compute how many bits are used in the final word + // uint32_t wordBits = APIVal.getBitWidth() & 0x3f; + if (wordBits == 0) + // If all bits are used, we want to leave the value alone. This also + // avoids the undefined behavior of >> when the shfit is the same size as + // the word size (64). + return; + + // Mask out the hight bits. + uint64_t mask = ~uint64_t(0ULL) >> (64 /*ap_private::APINT_BITS_PER_WORD */- wordBits); + msw &= mask; + } + template <> INLINE void clearUnusedBits<1>(int64_t& msw) { + uint64_t mask = ~uint64_t(0ULL) >> (64 /*ap_private::APINT_BITS_PER_WORD */- 1); + msw &= mask; + } + // template + template + INLINE ap_private<_AP_W, _AP_S> ashr(const ap_private<_AP_W, _AP_S>& a) { + return ashr(a, shiftAmt); + } + + template + INLINE ap_private<_AP_W, _AP_S> lshr(const ap_private<_AP_W, _AP_S>& a) { + return lshr(a, shiftAmt); + } + + template + INLINE ap_private<_AP_W, true> ashr(const ap_private<_AP_W, true, 1>& a) { + enum {APINT_BITS_PER_WORD=64, excess_bits=APINT_BITS_PER_WORD-_AP_W}; + static const uint64_t sign_bit = (1ULL<<(_AP_W-1)); + static const uint64_t sign_ext_mask = (_AP_W-shiftAmt>0)?~0ULL<<(APINT_BITS_PER_WORD-_AP_W+shiftAmt):~0ULL; + return ap_private<_AP_W, true>((((int64_t)a.VAL) >> (shiftAmt)) | (a.VAL & sign_bit? sign_ext_mask : 0ULL)); + } + + template + INLINE ap_private<_AP_W, false> ashr(const ap_private<_AP_W, false, 1>& a) { + return ap_private<_AP_W, false>((a.VAL) >> (shiftAmt)); + } + + template + INLINE ap_private<_AP_W, _AP_S> lshr(const ap_private<_AP_W, _AP_S, 1>& a) { + static const uint64_t mask = ~0ULL<<_AP_W; + return ap_private<_AP_W, _AP_S>((a.VAL&mask) >> (shiftAmt)); + } + + template + INLINE ap_private<_AP_W-shiftAmt, _AP_S> shr(const ap_private<_AP_W, _AP_S>& a) { + return ap_private<_AP_W-shiftAmt, _AP_S>((a.VAL) >> (shiftAmt)); + } + + template + INLINE ap_private<_AP_W+shiftAmt, _AP_S> shl(const ap_private<_AP_W, _AP_S>& a) { + return ap_private<_AP_W+shiftAmt, _AP_S>((a.VAL) << (shiftAmt)); + } + + template + INLINE bool get(const ap_private<_AP_W, _AP_S, 1>& a) { + unsigned shift = (index%APINT_BITS_PER_WORD); + static const uint64_t mask=1ULL << (shift); + return ((mask & a.VAL) != 0); + } + + template + INLINE bool get(const ap_private<_AP_W, _AP_S>& a) { + static const uint64_t mask=1ULL << (index&0x3f); + return ((mask & a.pVal[(index)>>6]) != 0); + } + + template + INLINE void set(ap_private<_AP_W, _AP_S, 1>& a) { + const uint64_t mask = ~0ULL >> (lsb) << (APINT_BITS_PER_WORD-msb+lsb-1)>>(APINT_BITS_PER_WORD-msb-1); + a.VAL |= mask; + } + + template + INLINE void clear(ap_private<_AP_W, _AP_S, 1>& a) { + static const uint64_t mask = ~(~0ULL >> (lsb) <<(APINT_BITS_PER_WORD-msb+lsb-1) >> (APINT_BITS_PER_WORD-msb-1)); + a.VAL &= mask; + } + + template + INLINE void set(ap_private<_AP_W, _AP_S>& a) { + enum { APINT_BITS_PER_WORD=64, + lsb_word = lsb_index /APINT_BITS_PER_WORD, + msb_word = msb_index / APINT_BITS_PER_WORD, + msb = msb_index % APINT_BITS_PER_WORD, + lsb=lsb_index % APINT_BITS_PER_WORD}; + if (msb_word==lsb_word) { + const uint64_t mask = ~0ULL >> (lsb) << (APINT_BITS_PER_WORD-msb+lsb-1)>>(APINT_BITS_PER_WORD-msb-1); + a.pVal[msb_word] |= mask; + } else { + const uint64_t lsb_mask = ~0ULL >> (lsb) << (lsb); + const uint64_t msb_mask = ~0ULL << (APINT_BITS_PER_WORD-msb-1)>>(APINT_BITS_PER_WORD-msb-1); + a.pVal[lsb_word] |=lsb_mask; + for (int i=lsb_word+1; i + INLINE void clear(ap_private<_AP_W, _AP_S>& a) { + enum { APINT_BITS_PER_WORD=64, + lsb_word = lsb_index /APINT_BITS_PER_WORD, + msb_word = msb_index / APINT_BITS_PER_WORD, + msb = msb_index % APINT_BITS_PER_WORD, + lsb=lsb_index % APINT_BITS_PER_WORD}; + if (msb_word == lsb_word) { + const uint64_t mask = ~(~0ULL >> (lsb) << (APINT_BITS_PER_WORD-msb+lsb-1)>>(APINT_BITS_PER_WORD-msb-1)); + a.pVal[msb_word] &= mask; + } else { + const uint64_t lsb_mask = ~(~0ULL >> (lsb) << (lsb)); + const uint64_t msb_mask = ~(~0ULL << (APINT_BITS_PER_WORD-msb-1)>>(APINT_BITS_PER_WORD-msb-1)); + a.pVal[lsb_word] &=lsb_mask; + for (int i=lsb_word+1; i + INLINE void set(ap_private<_AP_W, _AP_S, 1>& a) { + static const uint64_t mask=1ULL << (index); + a.VAL |= mask; + a.clearUnusedBits(); + } + + template + INLINE void clear(ap_private<_AP_W, _AP_S, 1>& a) { + static const uint64_t mask=~(1ULL << (index)); + a.VAL &= mask; + a.clearUnusedBits(); + } + + template + INLINE void set(ap_private<_AP_W, _AP_S>& a) { + enum { APINT_BITS_PER_WORD=64, word = index/APINT_BITS_PER_WORD}; + static const uint64_t mask=1ULL << (index%APINT_BITS_PER_WORD); + a.pVal[word] |= mask; + a.clearUnusedBits(); + } + + template + INLINE void clear(ap_private<_AP_W, _AP_S>& a) { + enum { APINT_BITS_PER_WORD=64, word = index/APINT_BITS_PER_WORD}; + static const uint64_t mask=~(1ULL << (index%APINT_BITS_PER_WORD)); + a.pVal[word] &= mask; + a.clearUnusedBits(); + } + + template + INLINE bool isNegative(const ap_private<_AP_W, false>& a) { + return false; + } + + template + INLINE bool isNegative(const ap_private<_AP_W, true, 1>& a) { + static const uint64_t sign_mask = (1ULL << (_AP_W-1)); + return ((sign_mask & a.VAL) != 0); + } + + template + INLINE bool isNegative(const ap_private<_AP_W, true>& a) { + enum {APINT_BITS_PER_WORD=64,_AP_N=(_AP_W+APINT_BITS_PER_WORD-1)/APINT_BITS_PER_WORD}; + static const uint64_t sign_mask = (1ULL << (_AP_W%APINT_BITS_PER_WORD-1)); + return sign_mask & a.pVal[_AP_N-1]; + } +} // End of ap_private_ops namespace + +/// @brief Check if the specified ap_private has a N-bits integer value. +template +INLINE bool isIntN(uint32_t __N, const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.isIntN(__N); +} + +/// @returns true if the argument ap_private value is a sequence of ones +/// starting at the least significant bit with the remainder zero. +template +INLINE bool isMask(uint32_t numBits, const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.getBoolValue() && ((APIVal + ap_private<_AP_W, _AP_S, _AP_N>(numBits,1)) & APIVal) == 0; +} + +/// @returns true if the argument ap_private value contains a sequence of ones +/// with the remainder zero. +template +INLINE bool isShiftedMask(uint32_t numBits, const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return isMask(numBits, (APIVal - ap_private<_AP_W, _AP_S, _AP_N>(numBits,1)) | APIVal); +} + +#if 0 +/// add_1 - This function adds a single "digit" integer, y, to the multiple +/// "digit" integer array, x[]. x[] is modified to reflect the addition and +/// 1 is returned if there is a carry out, otherwise 0 is returned. +/// @returns the carry of the addition. +static bool add_1(uint64_t dest[], uint64_t x[], uint32_t len, uint64_t y) { + for (uint32_t i = 0; i < len; ++i) { + dest[i] = y + x[i]; + if (dest[i] < y) + y = 1; // Carry one to next digit. + else { + y = 0; // No need to carry so exit early + break; + } + } + return (y != 0); +} +#endif + +#if 0 +/// add - This function adds the integer array x to the integer array Y and +/// places the result in dest. +/// @returns the carry out from the addition +/// @brief General addition of 64-bit integer arrays +static bool add(uint64_t *dest, const uint64_t *x, const uint64_t *y, + uint32_t destlen, uint32_t xlen, uint32_t ylen, bool xsigned, bool ysigned) { + bool carry = false; + uint32_t len = AESL_std::min(xlen, ylen); + uint32_t i; + for (i = 0; i< len && i < destlen; ++i) { + uint64_t limit = AESL_std::min(x[i],y[i]); // must come first in case dest == x + dest[i] = x[i] + y[i] + carry; + carry = dest[i] < limit || (carry && dest[i] == limit); + } + if (xlen > ylen) { + const uint64_t yext = xsigned && int64_t(y[ylen-1])<0 ? -1 : 0; + for (i=ylen; i< xlen && i < destlen; i++) { + uint64_t limit = AESL_std::min(x[i], yext); + dest[i] = x[i] + yext + carry; + carry = (dest[i] < limit)||(carry && dest[i] == x[i]); + } + } else if (ylen> xlen) { + const uint64_t xext = ysigned && int64_t(x[xlen-1])<0 ? -1 : 0; + for (i=xlen; i< ylen && i < destlen; i++) { + uint64_t limit = AESL_std::min(xext, y[i]); + dest[i] = xext + y[i] + carry; + carry = (dest[i] < limit)||(carry && dest[i] == y[i]); + } + } + return carry; +} +#endif + +#if 0 +/// @returns returns the borrow out. +/// @brief Generalized subtraction of 64-bit integer arrays. +static bool sub(uint64_t *dest, const uint64_t *x, const uint64_t *y, + uint32_t destlen, uint32_t xlen, uint32_t ylen, bool xsigned, bool ysigned) { + bool borrow = false; + uint32_t i; + uint32_t len = AESL_std::min(xlen, ylen); + for (i = 0; i < len && i < destlen; ++i) { + uint64_t x_tmp = borrow ? x[i] - 1 : x[i]; + borrow = y[i] > x_tmp || (borrow && x[i] == 0); + dest[i] = x_tmp - y[i]; + } + if (xlen > ylen) { + const uint64_t yext = ysigned && int64_t(y[ylen-1])<0 ? -1 : 0; + for (i=ylen; i< xlen && i < destlen; i++) { + uint64_t x_tmp = borrow ? x[i] - 1 : x[i]; + borrow = yext > x_tmp || (borrow && x[i] == 0); + dest[i] = x_tmp - yext; + } + } else if (ylen> xlen) { + const uint64_t xext = xsigned && int64_t(x[xlen-1])<0 ? -1 : 0; + for (i=xlen; i< ylen && i < destlen; i++) { + uint64_t x_tmp = borrow ? xext - 1 : xext; + borrow = y[i] > x_tmp || (borrow && xext==0); + dest[i] = x_tmp - y[i]; + } + } + return borrow; +} +#endif + +/// Subtracts the RHS ap_private from this ap_private +/// @returns this, after subtraction +/// @brief Subtraction assignment operator. + +#if 0 +/// Multiplies an integer array, x by a a uint64_t integer and places the result +/// into dest. +/// @returns the carry out of the multiplication. +/// @brief Multiply a multi-digit ap_private by a single digit (64-bit) integer. +static uint64_t mul_1(uint64_t dest[], const uint64_t x[], uint32_t len, uint64_t y) { + // Split y into high 32-bit part (hy) and low 32-bit part (ly) + uint64_t ly = y & 0xffffffffULL, hy = (y) >> 32; + uint64_t carry = 0; + static const uint64_t two_power_32 = 1ULL << 32; + // For each digit of x. + for (uint32_t i = 0; i < len; ++i) { + // Split x into high and low words + uint64_t lx = x[i] & 0xffffffffULL; + uint64_t hx = (x[i]) >> 32; + // hasCarry - A flag to indicate if there is a carry to the next digit. + // hasCarry == 0, no carry + // hasCarry == 1, has carry + // hasCarry == 2, no carry and the calculation result == 0. + uint8_t hasCarry = 0; + dest[i] = carry + lx * ly; + // Determine if the add above introduces carry. + hasCarry = (dest[i] < carry) ? 1 : 0; + carry = hx * ly + ((dest[i]) >> 32) + (hasCarry ? two_power_32 : 0); + // The upper limit of carry can be (2^32 - 1)(2^32 - 1) + + // (2^32 - 1) + 2^32 = 2^64. + hasCarry = (!carry && hasCarry) ? 1 : (!carry ? 2 : 0); + + carry += (lx * hy) & 0xffffffffULL; + dest[i] = ((carry) << 32) | (dest[i] & 0xffffffffULL); + carry = (((!carry && hasCarry != 2) || hasCarry == 1) ? two_power_32 : 0) + + ((carry) >> 32) + ((lx * hy) >> 32) + hx * hy; + } + return carry; +} +#endif + +#if 0 +/// Multiplies integer array x by integer array y and stores the result into +/// the integer array dest. Note that dest's size must be >= xlen + ylen. +/// @brief Generalized multiplicate of integer arrays. +static void mul(uint64_t dest[], const uint64_t x[], uint32_t xlen, const uint64_t y[], + uint32_t ylen, uint32_t destlen) { + dest[xlen] = mul_1(dest, x, xlen, y[0]); + for (uint32_t i = 1; i < ylen; ++i) { + uint64_t ly = y[i] & 0xffffffffULL, hy = (y[i]) >> 32; + uint64_t carry = 0, lx = 0, hx = 0; + for (uint32_t j = 0; j < xlen; ++j) { + lx = x[j] & 0xffffffffULL; + hx = (x[j]) >> 32; + // hasCarry - A flag to indicate if has carry. + // hasCarry == 0, no carry + // hasCarry == 1, has carry + // hasCarry == 2, no carry and the calculation result == 0. + uint8_t hasCarry = 0; + uint64_t resul = carry + lx * ly; + hasCarry = (resul < carry) ? 1 : 0; + carry = (hasCarry ? (1ULL << 32) : 0) + hx * ly + ((resul) >> 32); + hasCarry = (!carry && hasCarry) ? 1 : (!carry ? 2 : 0); + carry += (lx * hy) & 0xffffffffULL; + resul = ((carry) << 32) | (resul & 0xffffffffULL); + dest[i+j] += resul; + carry = (((!carry && hasCarry != 2) || hasCarry == 1) ? (1ULL << 32) : 0)+ + ((carry) >> 32) + (dest[i+j] < resul ? 1 : 0) + + ((lx * hy) >> 32) + hx * hy; + } + dest[i+xlen] = carry; + } +} +#endif + + + +template +uint32_t ap_private<_AP_W, _AP_S, _AP_N>::getBitsNeeded(const char* str, uint32_t slen, uint8_t radix) { + assert(str != 0 && "Invalid value string"); + assert(slen > 0 && "Invalid string length"); + + // Each computation below needs to know if its negative + uint32_t isNegative = str[0] == '-'; + if (isNegative) { + slen--; + str++; + } + // For radixes of power-of-two values, the bits required is accurately and + // easily computed + if (radix == 2) + return slen + isNegative; + if (radix == 8) + return slen * 3 + isNegative; + if (radix == 16) + return slen * 4 + isNegative; + + // Otherwise it must be radix == 10, the hard case + assert(radix == 10 && "Invalid radix"); + + // Convert to the actual binary value. + //ap_private<_AP_W, _AP_S, _AP_N> tmp(sufficient, str, slen, radix); + + // Compute how many bits are required. + //return isNegative + tmp.logBase2() + 1; + return isNegative + slen * 4; +} + +template +uint32_t ap_private<_AP_W, _AP_S, _AP_N>::countLeadingZeros() const { + enum { msw_bits = (BitWidth % APINT_BITS_PER_WORD)?(BitWidth % APINT_BITS_PER_WORD):APINT_BITS_PER_WORD, + excessBits = APINT_BITS_PER_WORD - msw_bits }; + uint32_t Count = CountLeadingZeros_64(pVal[_AP_N-1]); + if (Count>=excessBits) + Count -= excessBits; + if (!pVal[_AP_N-1]) { + for (uint32_t i = _AP_N-1 ; i ; --i) { + if (!pVal[i-1]) + Count += APINT_BITS_PER_WORD; + else { + Count += CountLeadingZeros_64(pVal[i-1]); + break; + } + } + } + return Count; +} + +static uint32_t countLeadingOnes_64(uint64_t __V, uint32_t skip) { + uint32_t Count = 0; + if (skip) + (__V) <<= (skip); + while (__V && (__V & (1ULL << 63))) { + Count++; + (__V) <<= 1; + } + return Count; +} + +template +uint32_t ap_private<_AP_W, _AP_S, _AP_N>::countLeadingOnes() const { + if (isSingleWord()) + return countLeadingOnes_64(VAL, APINT_BITS_PER_WORD - BitWidth); + + uint32_t highWordBits = BitWidth % APINT_BITS_PER_WORD; + uint32_t shift = (highWordBits == 0 ? 0 : APINT_BITS_PER_WORD - highWordBits); + int i = _AP_N - 1; + uint32_t Count = countLeadingOnes_64(pVal[i], shift); + if (Count == highWordBits) { + for (i--; i >= 0; --i) { + if (pVal[i] == ~0ULL) + Count += APINT_BITS_PER_WORD; + else { + Count += countLeadingOnes_64(pVal[i], 0); + break; + } + } + } + return Count; +} + +template +INLINE uint32_t ap_private<_AP_W, _AP_S, _AP_N>::countTrailingZeros() const { + if (isSingleWord()) + return AESL_std::min(uint32_t(CountTrailingZeros_64(VAL)), BitWidth); + uint32_t Count = 0; + uint32_t i = 0; + for (; i < _AP_N && pVal[i] == 0; ++i) + Count += APINT_BITS_PER_WORD; + if (i < _AP_N) + Count += CountTrailingZeros_64(pVal[i]); + return AESL_std::min(Count, BitWidth); +} + +template +ap_private<_AP_W, _AP_S, _AP_N> ap_private<_AP_W, _AP_S, _AP_N>::byteSwap() const { + assert(BitWidth >= 16 && BitWidth % 16 == 0 && "Cannot byteswap!"); + if (BitWidth == 16) + return ap_private<_AP_W, _AP_S, _AP_N>(/*BitWidth,*/ ByteSwap_16(uint16_t(VAL))); + else if (BitWidth == 32) + return ap_private<_AP_W, _AP_S, _AP_N>(/*BitWidth,*/ ByteSwap_32(uint32_t(VAL))); + else if (BitWidth == 48) { + uint32_t Tmp1 = uint32_t((VAL) >> 16); + Tmp1 = ByteSwap_32(Tmp1); + uint16_t Tmp2 = uint16_t(VAL); + Tmp2 = ByteSwap_16(Tmp2); + return ap_private<_AP_W, _AP_S, _AP_N>(/*BitWidth,*/ ((uint64_t(Tmp2)) << 32) | Tmp1); + } else if (BitWidth == 64) + return ap_private<_AP_W, _AP_S, _AP_N>(/*BitWidth,*/ ByteSwap_64(VAL)); + else { + ap_private<_AP_W, _AP_S, _AP_N> Result(0); + char *pByte = (char*)Result.pVal; + for (uint32_t i = 0; i < BitWidth / APINT_WORD_SIZE / 2; ++i) { + char Tmp = pByte[i]; + pByte[i] = pByte[BitWidth / APINT_WORD_SIZE - 1 - i]; + pByte[BitWidth / APINT_WORD_SIZE - i - 1] = Tmp; + } + return Result; + } +} + +template +ap_private<_AP_W, _AP_S, _AP_N> ap_private_ops::GreatestCommonDivisor(const ap_private<_AP_W, _AP_S, _AP_N>& API1, const ap_private<_AP_W, _AP_S, _AP_N>& API2) { + ap_private<_AP_W, _AP_S, _AP_N> __A = API1, __B = API2; + while (!!__B) { + ap_private<_AP_W, _AP_S, _AP_N> __T = __B; + __B = ap_private_ops::urem(__A, __B); + __A = __T; + } + return __A; +} + +template +ap_private<_AP_W, _AP_S, _AP_N> ap_private_ops::RoundDoubleToap_private(double Double, uint32_t width) { + union { + double __D; + uint64_t __I; + } __T; + __T.__D = Double; + + // Get the sign bit from the highest order bit + bool isNeg = (__T.__I) >> 63; + + // Get the 11-bit exponent and adjust for the 1023 bit bias + int64_t exp = (((__T.__I) >> 52) & 0x7ffULL) - 1023; + + // If the exponent is negative, the value is < 0 so just return 0. + if (exp < 0) + return ap_private<_AP_W, _AP_S, _AP_N>(width, 0u); + + // Extract the mantissa by clearing the top 12 bits (sign + exponent). + uint64_t mantissa = (__T.__I & (~0ULL >> 12)) | 1ULL << 52; + + // If the exponent doesn't shift all bits out of the mantissa + if (exp < 52) + return isNeg ? -ap_private<_AP_W, _AP_S, _AP_N>(width, (mantissa) >> (52 - exp)) : + ap_private<_AP_W, _AP_S, _AP_N>((mantissa) >> (52 - exp)); + + // If the client didn't provide enough bits for us to shift the mantissa into + // then the result is undefined, just return 0 + if (width <= exp - 52) + return ap_private<_AP_W, _AP_S, _AP_N>(width, 0); + + // Otherwise, we have to shift the mantissa bits up to the right location + ap_private<_AP_W, _AP_S, _AP_N> Tmp(width, mantissa); + Tmp = Tmp.shl(exp - 52); + return isNeg ? -Tmp : Tmp; +} + +/// RoundToDouble - This function convert this ap_private to a double. +/// The layout for double is as following (IEEE Standard 754): +/// -------------------------------------- +/// | Sign Exponent Fraction Bias | +/// |-------------------------------------- | +/// | 1[63] 11[62-52] 52[51-00] 1023 | +/// -------------------------------------- +template +double ap_private<_AP_W, _AP_S, _AP_N>::roundToDouble(bool isSigned) const { + + // Handle the simple case where the value is contained in one uint64_t. + if (isSingleWord() || getActiveBits() <= APINT_BITS_PER_WORD) { + uint64_t val; + if (isSingleWord()) val = VAL; + else val = pVal[0]; + if (isSigned) { + int64_t sext = ((int64_t(val)) << (64-BitWidth)) >> (64-BitWidth); + return double(sext); + } else + return double(val); + } + + // Determine if the value is negative. + bool isNeg = isSigned ? (*this)[BitWidth-1] : false; + + // Construct the absolute value if we're negative. + ap_private<_AP_W, _AP_S, _AP_N> Tmp(isNeg ? -(*this) : (*this)); + + // Figure out how many bits we're using. + uint32_t n = Tmp.getActiveBits(); + + // The exponent (without bias normalization) is just the number of bits + // we are using. Note that the sign bit is gone since we constructed the + // absolute value. + uint64_t exp = n; + + // Return infinity for exponent overflow + if (exp > 1023) { + if (!isSigned || !isNeg) + return std::numeric_limits::infinity(); + else + return -std::numeric_limits::infinity(); + } + exp += 1023; // Increment for 1023 bias + + // Number of bits in mantissa is 52. To obtain the mantissa value, we must + // extract the high 52 bits from the correct words in pVal. + uint64_t mantissa; + unsigned hiWord = whichWord(n-1); + if (hiWord == 0) { + mantissa = Tmp.pVal[0]; + if (n > 52) + (mantissa) >>= (n - 52); // shift down, we want the top 52 bits. + } else { + assert(hiWord > 0 && "High word is negative?"); + uint64_t hibits = (Tmp.pVal[hiWord]) << (52 - n % APINT_BITS_PER_WORD); + uint64_t lobits = (Tmp.pVal[hiWord-1]) >> (11 + n % APINT_BITS_PER_WORD); + mantissa = hibits | lobits; + } + + // The leading bit of mantissa is implicit, so get rid of it. + uint64_t sign = isNeg ? (1ULL << (APINT_BITS_PER_WORD - 1)) : 0; + union { + double __D; + uint64_t __I; + } __T; + __T.__I = sign | ((exp) << 52) | mantissa; + return __T.__D; +} + +// Square Root - this method computes and returns the square root of "this". +// Three mechanisms are used for computation. For small values (<= 5 bits), +// a table lookup is done. This gets some performance for common cases. For +// values using less than 52 bits, the value is converted to double and then +// the libc sqrt function is called. The result is rounded and then converted +// back to a uint64_t which is then used to construct the result. Finally, +// the Babylonian method for computing square roots is used. +template +ap_private<_AP_W, _AP_S, _AP_N> ap_private<_AP_W, _AP_S, _AP_N>::sqrt() const { + + // Determine the magnitude of the value. + uint32_t magnitude = getActiveBits(); + + // Use a fast table for some small values. This also gets rid of some + // rounding errors in libc sqrt for small values. + if (magnitude <= 5) { + static const uint8_t results[32] = { + /* 0 */ 0, + /* 1- 2 */ 1, 1, + /* 3- 6 */ 2, 2, 2, 2, + /* 7-12 */ 3, 3, 3, 3, 3, 3, + /* 13-20 */ 4, 4, 4, 4, 4, 4, 4, 4, + /* 21-30 */ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + /* 31 */ 6 + }; + return ap_private<_AP_W, _AP_S, _AP_N>(/*BitWidth,*/ results[ (isSingleWord() ? VAL : pVal[0]) ]); + } + + // If the magnitude of the value fits in less than 52 bits (the precision of + // an IEEE double precision floating point value), then we can use the + // libc sqrt function which will probably use a hardware sqrt computation. + // This should be faster than the algorithm below. + if (magnitude < 52) { +#ifdef _MSC_VER + // Amazingly, VC++ doesn't have round(). + return ap_private<_AP_W, _AP_S, _AP_N>(/*BitWidth,*/ + uint64_t(::sqrt(double(isSingleWord()?VAL:pVal[0]))) + 0.5); +#else + return ap_private<_AP_W, _AP_S, _AP_N>(/*BitWidth,*/ + uint64_t(::round(::sqrt(double(isSingleWord()?VAL:pVal[0]))))); +#endif + } + + // Okay, all the short cuts are exhausted. We must compute it. The following + // is a classical Babylonian method for computing the square root. This code + // was adapted to APINt from a wikipedia article on such computations. + // See http://www.wikipedia.org/ and go to the page named + // Calculate_an_integer_square_root. + uint32_t nbits = BitWidth, i = 4; + ap_private<_AP_W, _AP_S, _AP_N> testy(16); + ap_private<_AP_W, _AP_S, _AP_N> x_old(/*BitWidth,*/ 1); + ap_private<_AP_W, _AP_S, _AP_N> x_new(0); + ap_private<_AP_W, _AP_S, _AP_N> two(/*BitWidth,*/ 2); + + // Select a good starting value using binary logarithms. + for (;; i += 2, testy = testy.shl(2)) + if (i >= nbits || this->ule(testy)) { + x_old = x_old.shl(i / 2); + break; + } + + // Use the Babylonian method to arrive at the integer square root: + for (;;) { + x_new = (this->udiv(x_old) + x_old).udiv(two); + if (x_old.ule(x_new)) + break; + x_old = x_new; + } + + // Make sure we return the closest approximation + // NOTE: The rounding calculation below is correct. It will produce an + // off-by-one discrepancy with results from pari/gp. That discrepancy has been + // determined to be a rounding issue with pari/gp as it begins to use a + // floating point representation after 192 bits. There are no discrepancies + // between this algorithm and pari/gp for bit widths < 192 bits. + ap_private<_AP_W, _AP_S, _AP_N> square(x_old * x_old); + ap_private<_AP_W, _AP_S, _AP_N> nextSquare((x_old + 1) * (x_old +1)); + if (this->ult(square)) + return x_old; + else if (this->ule(nextSquare)) { + ap_private<_AP_W, _AP_S, _AP_N> midpoint((nextSquare - square).udiv(two)); + ap_private<_AP_W, _AP_S, _AP_N> offset(*this - square); + if (offset.ult(midpoint)) + return x_old; + else + return x_old + 1; + } else + assert(0 && "Error in ap_private<_AP_W, _AP_S, _AP_N>::sqrt computation"); + return x_old + 1; +} + +/// Implementation of Knuth's Algorithm D (Division of nonnegative integers) +/// from "Art of Computer Programming, Volume 2", section 4.3.1, p. 272. The +/// variables here have the same names as in the algorithm. Comments explain +/// the algorithm and any deviation from it. +static void KnuthDiv(uint32_t *u, uint32_t *v, uint32_t *q, uint32_t* r, + uint32_t m, uint32_t n) { + assert(u && "Must provide dividend"); + assert(v && "Must provide divisor"); + assert(q && "Must provide quotient"); + assert(u != v && u != q && v != q && "Must us different memory"); + assert(n>1 && "n must be > 1"); + + // Knuth uses the value b as the base of the number system. In our case b + // is 2^31 so we just set it to -1u. + uint64_t b = uint64_t(1) << 32; + + //DEBUG(cerr << "KnuthDiv: m=" << m << " n=" << n << '\n'); + //DEBUG(cerr << "KnuthDiv: original:"); + //DEBUG(for (int i = m+n; i >=0; i--) cerr << " " << std::setbase(16) << u[i]); + //DEBUG(cerr << " by"); + //DEBUG(for (int i = n; i >0; i--) cerr << " " << std::setbase(16) << v[i-1]); + //DEBUG(cerr << '\n'); + // D1. [Normalize.] Set d = b / (v[n-1] + 1) and multiply all the digits of + // u and v by d. Note that we have taken Knuth's advice here to use a power + // of 2 value for d such that d * v[n-1] >= b/2 (b is the base). A power of + // 2 allows us to shift instead of multiply and it is easy to determine the + // shift amount from the leading zeros. We are basically normalizing the u + // and v so that its high bits are shifted to the top of v's range without + // overflow. Note that this can require an extra word in u so that u must + // be of length m+n+1. + uint32_t shift = CountLeadingZeros_32(v[n-1]); + uint32_t v_carry = 0; + uint32_t u_carry = 0; + if (shift) { + for (uint32_t i = 0; i < m+n; ++i) { + uint32_t u_tmp = (u[i]) >> (32 - shift); + u[i] = ((u[i]) << (shift)) | u_carry; + u_carry = u_tmp; + } + for (uint32_t i = 0; i < n; ++i) { + uint32_t v_tmp = (v[i]) >> (32 - shift); + v[i] = ((v[i]) << (shift)) | v_carry; + v_carry = v_tmp; + } + } + u[m+n] = u_carry; + //DEBUG(cerr << "KnuthDiv: normal:"); + //DEBUG(for (int i = m+n; i >=0; i--) cerr << " " << std::setbase(16) << u[i]); + //DEBUG(cerr << " by"); + //DEBUG(for (int i = n; i >0; i--) cerr << " " << std::setbase(16) << v[i-1]); + //DEBUG(cerr << '\n'); + + // D2. [Initialize j.] Set j to m. This is the loop counter over the places. + int j = m; + do { + //DEBUG(cerr << "KnuthDiv: quotient digit #" << j << '\n'); + // D3. [Calculate q'.]. + // Set qp = (u[j+n]*b + u[j+n-1]) / v[n-1]. (qp=qprime=q') + // Set rp = (u[j+n]*b + u[j+n-1]) % v[n-1]. (rp=rprime=r') + // Now test if qp == b or qp*v[n-2] > b*rp + u[j+n-2]; if so, decrease + // qp by 1, inrease rp by v[n-1], and repeat this test if rp < b. The test + // on v[n-2] determines at high speed most of the cases in which the trial + // value qp is one too large, and it eliminates all cases where qp is two + // too large. + uint64_t dividend = ((uint64_t(u[j+n]) << 32) + u[j+n-1]); + //DEBUG(cerr << "KnuthDiv: dividend == " << dividend << '\n'); + uint64_t qp = dividend / v[n-1]; + uint64_t rp = dividend % v[n-1]; + if (qp == b || qp*v[n-2] > b*rp + u[j+n-2]) { + qp--; + rp += v[n-1]; + if (rp < b && (qp == b || qp*v[n-2] > b*rp + u[j+n-2])) + qp--; + } + //DEBUG(cerr << "KnuthDiv: qp == " << qp << ", rp == " << rp << '\n'); + + // D4. [Multiply and subtract.] Replace (u[j+n]u[j+n-1]...u[j]) with + // (u[j+n]u[j+n-1]..u[j]) - qp * (v[n-1]...v[1]v[0]). This computation + // consists of a simple multiplication by a one-place number, combined with + // a subtraction. + bool isNeg = false; + for (uint32_t i = 0; i < n; ++i) { + uint64_t u_tmp = uint64_t(u[j+i]) | ((uint64_t(u[j+i+1])) << 32); + uint64_t subtrahend = uint64_t(qp) * uint64_t(v[i]); + bool borrow = subtrahend > u_tmp; + /*DEBUG(cerr << "KnuthDiv: u_tmp == " << u_tmp + << ", subtrahend == " << subtrahend + << ", borrow = " << borrow << '\n');*/ + + uint64_t result = u_tmp - subtrahend; + uint32_t k = j + i; + u[k++] = (uint32_t)(result & (b-1)); // subtract low word + u[k++] = (uint32_t)((result) >> 32); // subtract high word + while (borrow && k <= m+n) { // deal with borrow to the left + borrow = u[k] == 0; + u[k]--; + k++; + } + isNeg |= borrow; + /*DEBUG(cerr << "KnuthDiv: u[j+i] == " << u[j+i] << ", u[j+i+1] == " << + u[j+i+1] << '\n');*/ + } + /*DEBUG(cerr << "KnuthDiv: after subtraction:"); + DEBUG(for (int i = m+n; i >=0; i--) cerr << " " << u[i]); + DEBUG(cerr << '\n');*/ + // The digits (u[j+n]...u[j]) should be kept positive; if the result of + // this step is actually negative, (u[j+n]...u[j]) should be left as the + // true value plus b**(n+1), namely as the b's complement of + // the true value, and a "borrow" to the left should be remembered. + // + if (isNeg) { + bool carry = true; // true because b's complement is "complement + 1" + for (uint32_t i = 0; i <= m+n; ++i) { + u[i] = ~u[i] + carry; // b's complement + carry = carry && u[i] == 0; + } + } + /*DEBUG(cerr << "KnuthDiv: after complement:"); + DEBUG(for (int i = m+n; i >=0; i--) cerr << " " << u[i]); + DEBUG(cerr << '\n');*/ + + // D5. [Test remainder.] Set q[j] = qp. If the result of step D4 was + // negative, go to step D6; otherwise go on to step D7. + q[j] = (uint32_t)qp; + if (isNeg) { + // D6. [Add back]. The probability that this step is necessary is very + // small, on the order of only 2/b. Make sure that test data accounts for + // this possibility. Decrease q[j] by 1 + q[j]--; + // and add (0v[n-1]...v[1]v[0]) to (u[j+n]u[j+n-1]...u[j+1]u[j]). + // A carry will occur to the left of u[j+n], and it should be ignored + // since it cancels with the borrow that occurred in D4. + bool carry = false; + for (uint32_t i = 0; i < n; i++) { + uint32_t limit = AESL_std::min(u[j+i],v[i]); + u[j+i] += v[i] + carry; + carry = u[j+i] < limit || (carry && u[j+i] == limit); + } + u[j+n] += carry; + } + /*DEBUG(cerr << "KnuthDiv: after correction:"); + DEBUG(for (int i = m+n; i >=0; i--) cerr <<" " << u[i]); + DEBUG(cerr << "\nKnuthDiv: digit result = " << q[j] << '\n');*/ + + // D7. [Loop on j.] Decrease j by one. Now if j >= 0, go back to D3. + } while (--j >= 0); + + /*DEBUG(cerr << "KnuthDiv: quotient:"); + DEBUG(for (int i = m; i >=0; i--) cerr <<" " << q[i]); + DEBUG(cerr << '\n');*/ + + // D8. [Unnormalize]. Now q[...] is the desired quotient, and the desired + // remainder may be obtained by dividing u[...] by d. If r is non-null we + // compute the remainder (urem uses this). + if (r) { + // The value d is expressed by the "shift" value above since we avoided + // multiplication by d by using a shift left. So, all we have to do is + // shift right here. In order to mak + if (shift) { + uint32_t carry = 0; + //DEBUG(cerr << "KnuthDiv: remainder:"); + for (int i = n-1; i >= 0; i--) { + r[i] = ((u[i]) >> (shift)) | carry; + carry = (u[i]) << (32 - shift); + //DEBUG(cerr << " " << r[i]); + } + } else { + for (int i = n-1; i >= 0; i--) { + r[i] = u[i]; + //DEBUG(cerr << " " << r[i]); + } + } + //DEBUG(cerr << '\n'); + } + //DEBUG(cerr << std::setbase(10) << '\n'); +} + +template +void divide(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, uint32_t lhsWords, + const ap_private<_AP_W, _AP_S, _AP_N>& RHS, uint32_t rhsWords, + ap_private<_AP_W, _AP_S, _AP_N> *Quotient, ap_private<_AP_W, _AP_S, _AP_N> *Remainder) { + assert(lhsWords >= rhsWords && "Fractional result"); + enum {APINT_BITS_PER_WORD=64}; + // First, compose the values into an array of 32-bit words instead of + // 64-bit words. This is a necessity of both the "short division" algorithm + // and the the Knuth "classical algorithm" which requires there to be native + // operations for +, -, and * on an m bit value with an m*2 bit result. We + // can't use 64-bit operands here because we don't have native results of + // 128-bits. Furthremore, casting the 64-bit values to 32-bit values won't + // work on large-endian machines. + uint64_t mask = ~0ull >> (sizeof(uint32_t)*8); + uint32_t n = rhsWords * 2; + uint32_t m = (lhsWords * 2) - n; + + // Allocate space for the temporary values we need either on the stack, if + // it will fit, or on the heap if it won't. + uint32_t SPACE[128]; + uint32_t *__U = 0; + uint32_t *__V = 0; + uint32_t *__Q = 0; + uint32_t *__R = 0; + if ((Remainder?4:3)*n+2*m+1 <= 128) { + __U = &SPACE[0]; + __V = &SPACE[m+n+1]; + __Q = &SPACE[(m+n+1) + n]; + if (Remainder) + __R = &SPACE[(m+n+1) + n + (m+n)]; + } else { + __U = new uint32_t[m + n + 1]; + __V = new uint32_t[n]; + __Q = new uint32_t[m+n]; + if (Remainder) + __R = new uint32_t[n]; + } + + // Initialize the dividend + memset(__U, 0, (m+n+1)*sizeof(uint32_t)); + for (unsigned i = 0; i < lhsWords; ++i) { + uint64_t tmp = (LHS.getNumWords() == 1 ? LHS.VAL : LHS.pVal[i]); + __U[i * 2] = (uint32_t)(tmp & mask); + __U[i * 2 + 1] = (tmp) >> (sizeof(uint32_t)*8); + } + __U[m+n] = 0; // this extra word is for "spill" in the Knuth algorithm. + + // Initialize the divisor + memset(__V, 0, (n)*sizeof(uint32_t)); + for (unsigned i = 0; i < rhsWords; ++i) { + uint64_t tmp = (RHS.getNumWords() == 1 ? RHS.VAL : RHS.pVal[i]); + __V[i * 2] = (uint32_t)(tmp & mask); + __V[i * 2 + 1] = (tmp) >> (sizeof(uint32_t)*8); + } + + // initialize the quotient and remainder + memset(__Q, 0, (m+n) * sizeof(uint32_t)); + if (Remainder) + memset(__R, 0, n * sizeof(uint32_t)); + + // Now, adjust m and n for the Knuth division. n is the number of words in + // the divisor. m is the number of words by which the dividend exceeds the + // divisor (i.e. m+n is the length of the dividend). These sizes must not + // contain any zero words or the Knuth algorithm fails. + for (unsigned i = n; i > 0 && __V[i-1] == 0; i--) { + n--; + m++; + } + for (unsigned i = m+n; i > 0 && __U[i-1] == 0; i--) + m--; + + // If we're left with only a single word for the divisor, Knuth doesn't work + // so we implement the short division algorithm here. This is much simpler + // and faster because we are certain that we can divide a 64-bit quantity + // by a 32-bit quantity at hardware speed and short division is simply a + // series of such operations. This is just like doing short division but we + // are using base 2^32 instead of base 10. + assert(n != 0 && "Divide by zero?"); + if (n == 1) { + uint32_t divisor = __V[0]; + uint32_t remainder = 0; + for (int i = m+n-1; i >= 0; i--) { + uint64_t partial_dividend = (uint64_t(remainder)) << 32 | __U[i]; + if (partial_dividend == 0) { + __Q[i] = 0; + remainder = 0; + } else if (partial_dividend < divisor) { + __Q[i] = 0; + remainder = (uint32_t)partial_dividend; + } else if (partial_dividend == divisor) { + __Q[i] = 1; + remainder = 0; + } else { + __Q[i] = (uint32_t)(partial_dividend / divisor); + remainder = (uint32_t)(partial_dividend - (__Q[i] * divisor)); + } + } + if (__R) + __R[0] = remainder; + } else { + // Now we're ready to invoke the Knuth classical divide algorithm. In this + // case n > 1. + KnuthDiv(__U, __V, __Q, __R, m, n); + } + + // If the caller wants the quotient + if (Quotient) { + // Set up the Quotient value's memory. + if (Quotient->BitWidth != LHS.BitWidth) { + if (Quotient->isSingleWord()) + Quotient->VAL = 0; + } else + Quotient->clear(); + + // The quotient is in Q. Reconstitute the quotient into Quotient's low + // order words. + if (lhsWords == 1) { + uint64_t tmp = + uint64_t(__Q[0]) | ((uint64_t(__Q[1])) << (APINT_BITS_PER_WORD / 2)); + if (Quotient->isSingleWord()) + Quotient->VAL = tmp; + else + Quotient->pVal[0] = tmp; + } else { + assert(!Quotient->isSingleWord() && "Quotient ap_private not large enough"); + for (unsigned i = 0; i < lhsWords; ++i) + Quotient->pVal[i] = + uint64_t(__Q[i*2]) | ((uint64_t(__Q[i*2+1])) << (APINT_BITS_PER_WORD / 2)); + } + Quotient->clearUnusedBits(); + } + + // If the caller wants the remainder + if (Remainder) { + // Set up the Remainder value's memory. + if (Remainder->BitWidth != RHS.BitWidth) { + if (Remainder->isSingleWord()) + Remainder->VAL = 0; + } else + Remainder->clear(); + + // The remainder is in R. Reconstitute the remainder into Remainder's low + // order words. + if (rhsWords == 1) { + uint64_t tmp = + uint64_t(__R[0]) | ((uint64_t(__R[1])) << (APINT_BITS_PER_WORD / 2)); + if (Remainder->isSingleWord()) + Remainder->VAL = tmp; + else + Remainder->pVal[0] = tmp; + } else { + assert(!Remainder->isSingleWord() && "Remainder ap_private not large enough"); + for (unsigned i = 0; i < rhsWords; ++i) + Remainder->pVal[i] = + uint64_t(__R[i*2]) | ((uint64_t(__R[i*2+1])) << (APINT_BITS_PER_WORD / 2)); + } + Remainder->clearUnusedBits(); + } + + // Clean up the memory we allocated. + if (__U != &SPACE[0]) { + delete [] __U; + delete [] __V; + delete [] __Q; + delete [] __R; + } +} + + +template +void ap_private<_AP_W, _AP_S, _AP_N>::fromString(const char *str, uint32_t slen, uint8_t radix) { + enum { numbits=_AP_W}; + // Check our assumptions here + assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) && + "Radix should be 2, 8, 10, or 16!"); + assert(str && "String is null?"); + bool isNeg = str[0] == '-'; + if (isNeg) + str++, slen--; + + //skip any leading zero + while(*str == '0' && *(str+1) != '\0') {str++; slen--;} + assert((slen <= numbits || radix != 2) && "Insufficient bit width"); + assert(((slen - 1)*3 <= numbits || radix != 8) && "Insufficient bit width"); + assert(((slen - 1)*4 <= numbits || radix != 16) && "Insufficient bit width"); + assert((((slen -1)*64)/22 <= numbits || radix != 10) && "Insufficient bit width"); + + memset(pVal, 0, _AP_N * sizeof(uint64_t)); + + // Figure out if we can shift instead of multiply + uint32_t shift = (radix == 16 ? 4 : radix == 8 ? 3 : radix == 2 ? 1 : 0); + + // Set up an ap_private for the digit to add outside the loop so we don't + // constantly construct/destruct it. + uint64_t bigVal[_AP_N]; + memset(bigVal, 0, _AP_N * sizeof(uint64_t)); + ap_private<_AP_W, _AP_S, _AP_N> apdigit(getBitWidth(), bigVal); + ap_private<_AP_W, _AP_S, _AP_N> apradix(radix); + + // Enter digit traversal loop + for (unsigned i = 0; i < slen; i++) { + // Get a digit + uint32_t digit = 0; + char cdigit = str[i]; + if (radix == 16) { +#define isxdigit(c) (((c) >= '0' && (c) <= '9') || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F')) +#define isdigit(c) ((c) >= '0' && (c) <= '9') + if (!isxdigit(cdigit)) + assert(0 && "Invalid hex digit in string"); + if (isdigit(cdigit)) + digit = cdigit - '0'; + else if (cdigit >= 'a') + digit = cdigit - 'a' + 10; + else if (cdigit >= 'A') + digit = cdigit - 'A' + 10; + else + assert(0 && "huh? we shouldn't get here"); + } else if (isdigit(cdigit)) { + digit = cdigit - '0'; + } else { + assert(0 && "Invalid character in digit string"); + } +#undef isxdigit +#undef isdigit + // Shift or multiply the value by the radix + if (shift) + *this <<= shift; + else + *this *= apradix; + + // Add in the digit we just interpreted + if (apdigit.isSingleWord()) + apdigit.VAL = digit; + else + apdigit.pVal[0] = digit; + *this += apdigit; + } + // If its negative, put it in two's complement form + if (isNeg) { + (*this)--; + this->flip(); + } + clearUnusedBits(); +} + +template +std::string ap_private<_AP_W, _AP_S, _AP_N>::toString(uint8_t radix, bool wantSigned) const { + assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) && + "Radix should be 2, 8, 10, or 16!"); + static const char *digits[] = { + "0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F" + }; + std::string result; + uint32_t bits_used = getActiveBits(); + + if (radix != 10) { + // For the 2, 8 and 16 bit cases, we can just shift instead of divide + // because the number of bits per digit (1,3 and 4 respectively) divides + // equaly. We just shift until there value is zero. + + // First, check for a zero value and just short circuit the logic below. + if (*this == (uint64_t)(0)) + result = "0"; + else { + ap_private<_AP_W, false, _AP_N> tmp(*this); + size_t insert_at = 0; + if (wantSigned && isNegative()) { + // They want to print the signed version and it is a negative value + // Flip the bits and add one to turn it into the equivalent positive + // value and put a '-' in the result. + tmp.flip(); + tmp++; + tmp.clearUnusedBitsToZero(); + result = "-"; + insert_at = 1; + } + // Just shift tmp right for each digit width until it becomes zero + uint32_t shift = (radix == 16 ? 4 : (radix == 8 ? 3 : 1)); + uint64_t mask = radix - 1; + ap_private<_AP_W, false, _AP_N> zero(0); + while (tmp.ne(zero)) { + unsigned digit = (tmp.isSingleWord() ? tmp.VAL : tmp.pVal[0]) & mask; + result.insert(insert_at, digits[digit]); + tmp = tmp.lshr(shift); + } + } + return result; + } + + ap_private<_AP_W, false, _AP_N> tmp(*this); + ap_private<_AP_W, false, _AP_N> divisor(radix); + ap_private<_AP_W, false, _AP_N> zero(0); + size_t insert_at = 0; + if (wantSigned && isNegative()) { + // They want to print the signed version and it is a negative value + // Flip the bits and add one to turn it into the equivalent positive + // value and put a '-' in the result. + tmp.flip(); + tmp++; + tmp.clearUnusedBitsToZero(); + result = "-"; + insert_at = 1; + } + if (tmp == ap_private<_AP_W, false, _AP_N>(0)) + result = "0"; + else while (tmp.ne(zero)) { + ap_private<_AP_W, false, _AP_N> APdigit(0); + ap_private<_AP_W, false, _AP_N> tmp2(0); + divide(tmp, tmp.getNumWords(), divisor, divisor.getNumWords(), &tmp2, + &APdigit); + uint32_t digit = APdigit.getZExtValue(); + assert(digit < radix && "divide failed"); + result.insert(insert_at,digits[digit]); + tmp = tmp2; + } + + return result; +} + +// This implements a variety of operations on a representation of +// arbitrary precision, two's-complement, bignum integer values. + +/* Assumed by lowHalf, highHalf, partMSB and partLSB. A fairly safe + and unrestricting assumption. */ + +/* Some handy functions local to this file. */ + +template +void divide(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, uint32_t lhsWords, + uint64_t RHS, + ap_private<_AP_W, _AP_S, _AP_N> *Quotient, ap_private<_AP_W, _AP_S, _AP_N> *Remainder) { + uint32_t rhsWords=1; + assert(lhsWords >= rhsWords && "Fractional result"); + enum {APINT_BITS_PER_WORD=64}; + // First, compose the values into an array of 32-bit words instead of + // 64-bit words. This is a necessity of both the "short division" algorithm + // and the the Knuth "classical algorithm" which requires there to be native + // operations for +, -, and * on an m bit value with an m*2 bit result. We + // can't use 64-bit operands here because we don't have native results of + // 128-bits. Furthremore, casting the 64-bit values to 32-bit values won't + // work on large-endian machines. + uint64_t mask = ~0ull >> (sizeof(uint32_t)*8); + uint32_t n = 2; + uint32_t m = (lhsWords * 2) - n; + + // Allocate space for the temporary values we need either on the stack, if + // it will fit, or on the heap if it won't. + uint32_t SPACE[128]; + uint32_t *__U = 0; + uint32_t *__V = 0; + uint32_t *__Q = 0; + uint32_t *__R = 0; + if ((Remainder?4:3)*n+2*m+1 <= 128) { + __U = &SPACE[0]; + __V = &SPACE[m+n+1]; + __Q = &SPACE[(m+n+1) + n]; + if (Remainder) + __R = &SPACE[(m+n+1) + n + (m+n)]; + } else { + __U = new uint32_t[m + n + 1]; + __V = new uint32_t[n]; + __Q = new uint32_t[m+n]; + if (Remainder) + __R = new uint32_t[n]; + } + + // Initialize the dividend + memset(__U, 0, (m+n+1)*sizeof(uint32_t)); + for (unsigned i = 0; i < lhsWords; ++i) { + uint64_t tmp = (LHS.getNumWords() == 1 ? LHS.VAL : LHS.pVal[i]); + __U[i * 2] = tmp & mask; + __U[i * 2 + 1] = (tmp) >> (sizeof(uint32_t)*8); + } + __U[m+n] = 0; // this extra word is for "spill" in the Knuth algorithm. + + // Initialize the divisor + memset(__V, 0, (n)*sizeof(uint32_t)); + __V[0] = RHS & mask; + __V[1] = (RHS) >> (sizeof(uint32_t)*8); + + // initialize the quotient and remainder + memset(__Q, 0, (m+n) * sizeof(uint32_t)); + if (Remainder) + memset(__R, 0, n * sizeof(uint32_t)); + + // Now, adjust m and n for the Knuth division. n is the number of words in + // the divisor. m is the number of words by which the dividend exceeds the + // divisor (i.e. m+n is the length of the dividend). These sizes must not + // contain any zero words or the Knuth algorithm fails. + for (unsigned i = n; i > 0 && __V[i-1] == 0; i--) { + n--; + m++; + } + for (unsigned i = m+n; i > 0 && __U[i-1] == 0; i--) + m--; + + // If we're left with only a single word for the divisor, Knuth doesn't work + // so we implement the short division algorithm here. This is much simpler + // and faster because we are certain that we can divide a 64-bit quantity + // by a 32-bit quantity at hardware speed and short division is simply a + // series of such operations. This is just like doing short division but we + // are using base 2^32 instead of base 10. + assert(n != 0 && "Divide by zero?"); + if (n == 1) { + uint32_t divisor = __V[0]; + uint32_t remainder = 0; + for (int i = m+n-1; i >= 0; i--) { + uint64_t partial_dividend = (uint64_t(remainder)) << 32 | __U[i]; + if (partial_dividend == 0) { + __Q[i] = 0; + remainder = 0; + } else if (partial_dividend < divisor) { + __Q[i] = 0; + remainder = partial_dividend; + } else if (partial_dividend == divisor) { + __Q[i] = 1; + remainder = 0; + } else { + __Q[i] = partial_dividend / divisor; + remainder = partial_dividend - (__Q[i] * divisor); + } + } + if (__R) + __R[0] = remainder; + } else { + // Now we're ready to invoke the Knuth classical divide algorithm. In this + // case n > 1. + KnuthDiv(__U, __V, __Q, __R, m, n); + } + + // If the caller wants the quotient + if (Quotient) { + // Set up the Quotient value's memory. + if (Quotient->BitWidth != LHS.BitWidth) { + if (Quotient->isSingleWord()) + Quotient->VAL = 0; + else + delete [] Quotient->pVal; + } else + Quotient->clear(); + + // The quotient is in Q. Reconstitute the quotient into Quotient's low + // order words. + if (lhsWords == 1) { + uint64_t tmp = + uint64_t(__Q[0]) | ((uint64_t(__Q[1])) << (APINT_BITS_PER_WORD / 2)); + if (Quotient->isSingleWord()) + Quotient->VAL = tmp; + else + Quotient->pVal[0] = tmp; + } else { + assert(!Quotient->isSingleWord() && "Quotient ap_private not large enough"); + for (unsigned i = 0; i < lhsWords; ++i) + Quotient->pVal[i] = + uint64_t(__Q[i*2]) | ((uint64_t(__Q[i*2+1])) << (APINT_BITS_PER_WORD / 2)); + } + Quotient->clearUnusedBits(); + } + + // If the caller wants the remainder + if (Remainder) { + // Set up the Remainder value's memory. + if (Remainder->BitWidth != 64 /* RHS.BitWidth */) { + if (Remainder->isSingleWord()) + Remainder->VAL = 0; + } else + Remainder->clear(); + + // The remainder is in __R. Reconstitute the remainder into Remainder's low + // order words. + if (rhsWords == 1) { + uint64_t tmp = + uint64_t(__R[0]) | ((uint64_t(__R[1])) << (APINT_BITS_PER_WORD / 2)); + if (Remainder->isSingleWord()) + Remainder->VAL = tmp; + else + Remainder->pVal[0] = tmp; + } else { + assert(!Remainder->isSingleWord() && "Remainder ap_private not large enough"); + for (unsigned i = 0; i < rhsWords; ++i) + Remainder->pVal[i] = + uint64_t(__R[i*2]) | ((uint64_t(__R[i*2+1])) << (APINT_BITS_PER_WORD / 2)); + } + Remainder->clearUnusedBits(); + } + + // Clean up the memory we allocated. + if (__U != &SPACE[0]) { + delete [] __U; + delete [] __V; + delete [] __Q; + delete [] __R; + } +} + +//When bitwidth < 64 +template class ap_private <_AP_W, _AP_S, 1> { +#ifdef _MSC_VER +#pragma warning( disable : 4521 4522 ) +#endif +public: + typedef typename retval<_AP_S>::Type ValType; + template + struct RType { + enum { + _AP_N =1, + mult_w = _AP_W+_AP_W2, + mult_s = _AP_S||_AP_S2, //?? why + plus_w = AP_MAX(_AP_W+(_AP_S2&&!_AP_S),_AP_W2+(_AP_S&&!_AP_S2))+1, //shouldn't it be AP_MAX(_AP_W,_AP_W2)+!(_AP_S^_AP_S2)+1 ???? + plus_s = _AP_S||_AP_S2, + minus_w = AP_MAX(_AP_W+(_AP_S2&&!_AP_S),_AP_W2+(_AP_S&&!_AP_S2))+1, + minus_s = true, + div_w = _AP_W+_AP_S2, + div_s = _AP_S||_AP_S2, + mod_w = AP_MIN(_AP_W,_AP_W2+(!_AP_S2&&_AP_S)), + mod_s = _AP_S, + logic_w = AP_MAX(_AP_W+(_AP_S2&&!_AP_S),_AP_W2+(_AP_S&&!_AP_S2)), + logic_s = _AP_S||_AP_S2 + }; + typedef ap_private mult; + typedef ap_private plus; + typedef ap_private minus; + typedef ap_private logic; + typedef ap_private div; + typedef ap_private mod; + typedef ap_private<_AP_W, _AP_S> arg1; + typedef bool reduce; + }; + enum { APINT_BITS_PER_WORD = 64}; + enum { excess_bits = (_AP_W%APINT_BITS_PER_WORD) ? APINT_BITS_PER_WORD -(_AP_W%APINT_BITS_PER_WORD) : 0}; + static const uint64_t mask = ((uint64_t)~0ULL >> (excess_bits)); + static const uint64_t not_mask = ~mask; + static const uint64_t sign_bit_mask = 1ULL << (APINT_BITS_PER_WORD-1); + template struct sign_ext_mask { static const uint64_t mask=~0ULL<<_AP_W1;}; + + enum { BitWidth=_AP_W}; + uint64_t VAL; ///< Used to store the <= 64 bits integer value. + const uint64_t *const pVal; + + INLINE uint32_t getBitWidth() const { + return BitWidth; + } + + template + ap_private<_AP_W, _AP_S, 1>& operator=(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { + VAL = RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + + template + ap_private<_AP_W, _AP_S, 1>& operator=(const volatile ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { + VAL = RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + + template + ap_private<_AP_W, _AP_S, 1>& operator=(const ap_private<_AP_W1, _AP_S1, 1>& RHS) { + VAL = RHS.VAL; + clearUnusedBits(); + return *this; + } + + template + ap_private<_AP_W, _AP_S, 1>& operator=(const volatile ap_private<_AP_W1, _AP_S1, 1>& RHS) { + VAL = RHS.VAL; + clearUnusedBits(); + return *this; + } + + volatile ap_private& operator=(const ap_private& RHS) volatile { + // Don't do anything for X = X + VAL = RHS.VAL; // No need to check because no harm done by copying. + return *this; + } + ap_private& operator=(const ap_private& RHS) { + // Don't do anything for X = X + VAL = RHS.VAL; // No need to check because no harm done by copying. + return *this; + } + + volatile ap_private& operator=(const volatile ap_private& RHS) volatile { + // Don't do anything for X = X + VAL = RHS.VAL; // No need to check because no harm done by copying. + return *this; + } + ap_private& operator=(const volatile ap_private& RHS) { + // Don't do anything for X = X + VAL = RHS.VAL; // No need to check because no harm done by copying. + return *this; + } + + template + INLINE ap_private& operator = (const ap_range_ref<_AP_W2, _AP_S2>& op2) { + *this = ap_private<_AP_W2, false>(op2); + return *this; + } + + explicit INLINE ap_private(uint64_t* val) : VAL(val[0]), pVal(&VAL){ + clearUnusedBits(); + } + + INLINE bool isSingleWord() const { return true; } + + INLINE void fromString(const char *strStart, uint32_t slen, + uint8_t radix, int offset=0) { + // Check our assumptions here + assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) && + "Radix should be 2, 8, 10, or 16!"); + assert(strStart && "String is null?"); + strStart+=offset; + switch(radix) { + case 2: + // sscanf(strStart,"%b",&VAL); + VAL = *strStart =='1' ? ~0ULL : 0; + for (;*strStart; ++strStart) { + assert((*strStart=='0'|| *strStart=='1')&&("Wrong binary number") ); + VAL <<=1; + VAL |= (*strStart-'0'); + } + break; + case 8: +#if __WIN32__ + sscanf(strStart,"%I64o",&VAL); +#else + +#if defined __x86_64__ + sscanf(strStart,"%lo",&VAL); +#else + sscanf(strStart,"%llo",&VAL); +#endif + +#endif + break; + case 10: +#if __WIN32__ + sscanf(strStart,"%I64u",&VAL); +#else + +#if defined __x86_64__ + sscanf(strStart,"%lu",&VAL); +#else + sscanf(strStart,"%llu",&VAL); +#endif + +#endif + break; + case 16: +#if __WIN32__ + sscanf(strStart,"%I64x",&VAL); +#else + +#if defined __x86_64__ + sscanf(strStart,"%lx",&VAL); +#else + sscanf(strStart,"%llx",&VAL); +#endif + +#endif + break; + default: + assert(true && "Unknown radix"); + // error + } + clearUnusedBits(); + } + + INLINE ap_private() : pVal(&VAL){VAL = 0ULL;} + +#define CTOR(TYPE) \ + INLINE ap_private(TYPE v) : VAL((uint64_t)v), pVal(&VAL) { \ + clearUnusedBits(); \ + } + CTOR(int) + CTOR(bool) + CTOR(signed char) + CTOR(unsigned char) + CTOR(short) + CTOR(unsigned short) + CTOR(unsigned int) + CTOR(long) + CTOR(unsigned long) + CTOR(unsigned long long) + CTOR(long long) + CTOR(float) + CTOR(double) +#undef CTOR + ap_private(uint32_t numWords, const uint64_t bigVal[]): VAL(bigVal[0]), pVal(&VAL) {clearUnusedBits();} + + ap_private(const std::string& val, uint8_t radix=2, int base=0, int offset=0): VAL(0), pVal(&VAL) { + assert(!val.empty() && "String empty?"); + fromString(val.c_str()+base, val.size()-base, radix); + } + + ap_private(const char strStart[], uint32_t slen, uint8_t radix, int base=0, int offset=0) : VAL(0), pVal(&VAL) { + fromString(strStart+base, slen-base, radix, offset); + } + + ap_private(const ap_private& that) : VAL(that.VAL), pVal(&VAL) { + clearUnusedBits(); + } + + template + ap_private(const ap_private<_AP_W1, _AP_S1, 1>& that) : VAL(that.VAL), pVal(&VAL) { + clearUnusedBits(); + } + + template + ap_private(const ap_private<_AP_W1, _AP_S1, _AP_N1>& that) : VAL(that.pVal[0]), pVal(&VAL) { + clearUnusedBits(); + } + + template + ap_private(const volatile ap_private<_AP_W1, _AP_S1, _AP_N1>& that) : VAL(that.pVal[0]), pVal(&VAL) { + clearUnusedBits(); + } + +#if 0 +template + explicit ap_private(const ap_private<_AP_W1, true, 1+_AP_W1/64>& that) + : VAL((_AP_W1>_AP_W) ? that.VAL & mask : ((1ULL<<(_AP_W1-1)&that.pVal[0]) ? sign_ext_mask<_AP_W1>::mask | that.VAL : that.pVal[0])), pVal(&VAL) {} + +template + explicit ap_private(const ap_private<_AP_W1, false, (_AP_W1+63)/64>& that) + : VAL(that.VAL & mask), pVal(&VAL) {} +#endif + + explicit ap_private(const char* val) : pVal(&VAL) { + std::string str(val); + uint32_t strLen = str.length(); + const char *strp = str.c_str(); + uint32_t offset = 0; + uint32_t base = 0; + bool neg = false; + uint32_t radix = 10; + ap_parse_sign(strp, base, neg); + ap_parse_prefix(strp + base, offset, radix); + + if ((radix != 10 && neg) || + (strLen - base - offset <= 0) || + InvalidDigit(strp, strLen, base + offset, radix)) { + fprintf(stderr, "invalid character string %s !\n", val); + assert(0); + } + + ap_private<_AP_W, _AP_S> ap_private_val(str.c_str(), strLen, radix, base, offset); + if (neg) + ap_private_val = -ap_private_val; + operator = (ap_private_val); + } + + ap_private(const char* val, signed char rd): pVal(&VAL) { + std::string str(val); + uint32_t strLen = str.length(); + const char *strp = str.c_str(); + uint32_t offset = 0; + uint32_t base = 0; + uint32_t radix = rd; + bool neg = false; + ap_parse_sign(strp, base, neg); + ap_parse_prefix(strp + base, offset, radix); + + if ((radix != 10 && neg) || + (strLen - base - offset <= 0) || + InvalidDigit(strp, strLen, base + offset, radix)) { + fprintf(stderr, "invalid character string %s !\n", val); + assert(0); + } + + uint32_t bitsNeeded = ap_private<_AP_W, _AP_S>::getBitsNeeded(strp, strLen, radix); + ap_private<_AP_W, _AP_S> ap_private_val(strp , strLen, radix, base, offset); + //ap_private<_AP_W, _AP_S> ap_private_val(bitsNeeded, strp , strLen, radix, base, offset); + if (strp[0] == '-') + ap_private_val = -ap_private_val; + operator = (ap_private_val); + } + + INLINE bool isNegative() const { + static const uint64_t sign_mask = 1ULL << (_AP_W-1); + return _AP_S && (sign_mask & VAL); + } + + INLINE bool isPositive() const { + return !isNegative(); + } + + INLINE bool isStrictlyPositive() const { + return !isNegative() && VAL!=0; + } + + INLINE bool isAllOnesValue() const { + return (mask & VAL) == mask; + } + + template + INLINE bool operator==(const ap_private<_AP_W1, _AP_S1, 1>& RHS) const { + return (VAL == RHS.VAL); + } + + INLINE bool operator==(const ap_private<_AP_W, _AP_S>& RHS) const { return VAL == RHS.VAL; } + INLINE bool operator==(const ap_private<_AP_W, !_AP_S>& RHS) const { return getVal() == RHS.getVal(); } + INLINE bool operator==(uint64_t Val) const { return (VAL == Val); } + INLINE bool operator!=(uint64_t Val) const { return (VAL != Val); } + INLINE bool operator!=(const ap_private<_AP_W, _AP_S>& RHS) const { return VAL != RHS.VAL; } + INLINE bool operator!=(const ap_private<_AP_W, !_AP_S>& RHS) const { return getVal() != RHS.getVal(); } + const ap_private operator++() { ++VAL; clearUnusedBits(); return *this; } + const ap_private operator--(int) { + ap_private orig(*this); + --VAL; clearUnusedBits(); + return orig; + } + const ap_private operator--() { --VAL; clearUnusedBits(); return *this;} + INLINE bool operator !() const { return !VAL;} + + const ap_private operator++(int) { + ap_private orig(*this); + VAL++; clearUnusedBits(); + return orig; + } + + const ap_private operator~() {return ap_private(~VAL);} + INLINE typename RType<1,false>::minus operator-() const { + return ap_private<1,false>(0) - (*this); + } + + INLINE std::string toString(uint8_t radix, bool wantSigned) const ; + INLINE std::string toStringUnsigned(uint8_t radix = 10) const { + return toString(radix, false); + } + INLINE std::string toStringSigned(uint8_t radix = 10) const { + return toString(radix, true); + } + INLINE void clear() { + VAL=0; + } + INLINE ap_private& clear(uint32_t bitPosition) { VAL &= ~(1ULL<<(bitPosition)); clearUnusedBits(); return *this;} + + INLINE ap_private ashr(uint32_t shiftAmt) const { + enum {excess_bits = APINT_BITS_PER_WORD - BitWidth}; + if (_AP_S) + return ap_private((shiftAmt == BitWidth) ? 0 : ((int64_t)VAL) >> (shiftAmt)); + else + return ap_private((shiftAmt == BitWidth) ? 0 : (VAL) >> (shiftAmt)); + } + + INLINE ap_private lshr(uint32_t shiftAmt) const { + return ap_private((shiftAmt == BitWidth) ? ap_private(0) : ap_private((VAL&mask) >> (shiftAmt))); + } + + INLINE ap_private shl(uint32_t shiftAmt) const { + if (shiftAmt > BitWidth) { + if (!isNegative()) + return ap_private(0); + else return ap_private(-1); + } + if (shiftAmt == BitWidth) return ap_private(0); + else return ap_private((VAL) << (shiftAmt)); + //return ap_private((shiftAmt == BitWidth) ? ap_private(0ULL) : ap_private(VAL << shiftAmt)); + } + + INLINE int64_t getSExtValue() const { + return VAL; + } + + INLINE uint64_t getZExtValue() const { + return VAL & mask; + } + + template + INLINE ap_private(const ap_range_ref<_AP_W2,_AP_S2>& ref) : pVal(&VAL) { + *this=ref.get(); + } + + template + INLINE ap_private(const ap_bit_ref<_AP_W2,_AP_S2>& ref) : pVal(&VAL) { + *this = ((uint64_t)(bool)ref); + } + + template + INLINE ap_private(const ap_concat_ref<_AP_W2, _AP_T2,_AP_W3, _AP_T3>& ref) : pVal(&VAL) { + *this=ref.get(); + } + + template + INLINE ap_private(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2> &val) : pVal(&VAL) { + *this = ((val.operator ap_private<_AP_W2, false> ())); + } + + template + INLINE ap_private(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2> &val) : pVal(&VAL) { + *this = (uint64_t)(bool)val; + } + + INLINE void write(const ap_private<_AP_W, _AP_S>& op2) volatile { + *this = (op2); + } + + //Explicit conversions to C interger types + //----------------------------------------------------------- + ValType getVal() const { + return VAL; + } + operator ValType () const { + return getVal(); + } + INLINE int to_int() const { + // ap_private<64 /* _AP_W */, _AP_S> res(V); + return (int) getVal(); + } + + INLINE unsigned to_uint() const { + return (unsigned) getVal(); + } + + INLINE long to_long() const { + return (long) getVal(); + } + + INLINE unsigned long to_ulong() const { + return (unsigned long) getVal(); + } + + INLINE ap_slong to_int64() const { + return (ap_slong) getVal(); + } + + INLINE ap_ulong to_uint64() const { + return (ap_ulong) getVal(); + } + + INLINE double to_double() const { + if (isNegative()) + return roundToDouble(true); + else + return roundToDouble(false); + } + + INLINE bool isMinValue() const { return VAL == 0;} + template INLINE ap_private& operator&=(const ap_private<_AP_W1, _AP_S1>& RHS) { + VAL = VAL&RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + + template INLINE ap_private& operator|=(const ap_private<_AP_W1, _AP_S1>& RHS) { + VAL = VAL|RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + + template INLINE ap_private& operator^=(const ap_private<_AP_W1, _AP_S1>& RHS){ + VAL = VAL^RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + + template INLINE ap_private& operator*=(const ap_private<_AP_W1, _AP_S1>& RHS){ + VAL = VAL*RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + + template INLINE ap_private& operator+=(const ap_private<_AP_W1, _AP_S1>& RHS){ + VAL = VAL+RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + + template INLINE ap_private& operator-=(const ap_private<_AP_W1, _AP_S1>& RHS){ + VAL = VAL-RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + INLINE const ap_private& operator<<=(uint32_t shiftAmt) { VAL<<=shiftAmt; clearUnusedBits(); return *this; } + + template INLINE typename RType<_AP_W1, _AP_S1>::logic operator&(const ap_private<_AP_W1, _AP_S1>& RHS) const { + if (RType<_AP_W1, _AP_S1>::logic_w <= 64) { + typename RType<_AP_W1, _AP_S1>::logic Ret(VAL & RHS.VAL); + return Ret; + } else { + typename RType<_AP_W1, _AP_S1>::logic Ret = *this; + return Ret & RHS; + } + } + + template INLINE typename RType<_AP_W1, _AP_S1>::logic operator^(const ap_private<_AP_W1, _AP_S1>& RHS) const { + if (RType<_AP_W1, _AP_S1>::logic_w <= 64) { + typename RType<_AP_W1, _AP_S1>::logic Ret(VAL ^ RHS.VAL); + return Ret; + } else { + typename RType<_AP_W1, _AP_S1>::logic Ret = *this; + return Ret ^ RHS; + } + } + + template INLINE typename RType<_AP_W1, _AP_S1>::logic operator|(const ap_private<_AP_W1, _AP_S1>& RHS) const { + if (RType<_AP_W1, _AP_S1>::logic_w <= 64) { + typename RType<_AP_W1, _AP_S1>::logic Ret(VAL | RHS.VAL); + return Ret; + } else { + typename RType<_AP_W1, _AP_S1>::logic Ret = *this; + return Ret | RHS; + } + } + + INLINE ap_private<_AP_W, _AP_S> And(const ap_private<_AP_W, _AP_S>& RHS) const { + return ap_private<_AP_W, _AP_S>(VAL & RHS.VAL); + } + + INLINE ap_private<_AP_W, _AP_S> Or(const ap_private<_AP_W, _AP_S>& RHS) const { + return ap_private<_AP_W, _AP_S>(VAL | RHS.VAL); + } + + INLINE ap_private<_AP_W, _AP_S> Xor(const ap_private<_AP_W, _AP_S>& RHS) const { + return ap_private<_AP_W, _AP_S>(VAL ^ RHS.VAL); + } +#if 1 + template + INLINE typename RType<_AP_W1, _AP_S1>::mult operator*(const ap_private<_AP_W1, _AP_S1>& RHS) const { + if (RType<_AP_W1, _AP_S1>::mult_w <= 64) { + typename RType<_AP_W1, _AP_S1>::mult Result(VAL * RHS.VAL); + return Result; + } else { + typename RType<_AP_W1, _AP_S1>::mult Result = typename RType<_AP_W1, _AP_S1>::mult(*this); + Result *= RHS; + return Result; + } + } +#endif + INLINE ap_private<_AP_W, _AP_S> Mul(const ap_private<_AP_W, _AP_S>& RHS) const { + return ap_private<_AP_W, _AP_S>(VAL * RHS.VAL); + } + + INLINE ap_private<_AP_W, _AP_S> Add(const ap_private<_AP_W, _AP_S>& RHS) const { + return ap_private<_AP_W, _AP_S>(VAL + RHS.VAL); + } + + INLINE ap_private<_AP_W, _AP_S> Sub(const ap_private<_AP_W, _AP_S>& RHS) const { + return ap_private<_AP_W, _AP_S>(VAL - RHS.VAL); + } + +#if 1 + INLINE ap_private& operator&=(uint64_t RHS) { VAL &= RHS; clearUnusedBits(); return *this;} + INLINE ap_private& operator|=(uint64_t RHS) { VAL |= RHS; clearUnusedBits(); return *this;} + INLINE ap_private& operator^=(uint64_t RHS){ VAL ^= RHS; clearUnusedBits(); return *this;} + INLINE ap_private& operator*=(uint64_t RHS){ VAL *= RHS; clearUnusedBits(); return *this; } + INLINE ap_private& operator+=(uint64_t RHS){ VAL += RHS; clearUnusedBits(); return *this;} + INLINE ap_private& operator-=(uint64_t RHS){ VAL -= RHS; clearUnusedBits(); return *this; } + INLINE ap_private operator&(uint64_t RHS) const { return ap_private(VAL & RHS); } + INLINE ap_private operator|(uint64_t RHS) const { return ap_private(VAL | RHS); } + INLINE ap_private operator^(uint64_t RHS) const { return ap_private(VAL ^ RHS); } + INLINE ap_private operator*(uint64_t RHS) const { return ap_private(VAL * RHS); } + INLINE ap_private operator/(uint64_t RHS) const { return ap_private(VAL / RHS); } + INLINE ap_private operator+(uint64_t RHS) const { return ap_private(VAL + RHS); } + INLINE ap_private operator-(uint64_t RHS) const { return ap_private(VAL - RHS); } +#endif + INLINE bool isMinSignedValue() const { + static const uint64_t min_mask = ~(~0ULL << (_AP_W-1)); + return BitWidth == 1 ? VAL == 1 : + (ap_private_ops::isNegative<_AP_W>(*this) && ((min_mask & VAL)==0)); + } + +#if 1 + + template INLINE + typename RType<_AP_W1,_AP_S1>::plus operator+(const ap_private<_AP_W1, _AP_S1>& RHS) const { + if (RType<_AP_W1,_AP_S1>::plus_w <=64) + return typename RType<_AP_W1,_AP_S1>::plus(RType<_AP_W1,_AP_S1>::plus_s ? int64_t(VAL+RHS.VAL):uint64_t(VAL+RHS.VAL)); + typename RType<_AP_W1,_AP_S1>::plus Result=RHS; + Result += VAL; + return Result; + } + + template INLINE + typename RType<_AP_W1,_AP_S1>::minus operator-(const ap_private<_AP_W1, _AP_S1>& RHS) const { + if (RType<_AP_W1,_AP_S1>::minus_w <=64) + return typename RType<_AP_W1,_AP_S1>::minus(int64_t(VAL-RHS.VAL)); + typename RType<_AP_W1,_AP_S1>::minus Result=*this; + Result -= RHS; + return Result; + } +#endif // #if 1 + + INLINE ap_private& flip() { + VAL = (~0ULL^VAL)&mask; + clearUnusedBits(); + return *this; + } + + uint32_t countPopulation() const { return CountPopulation_64(VAL);} + uint32_t countLeadingZeros() const { + int remainder = BitWidth % APINT_BITS_PER_WORD; + int excessBits = (APINT_BITS_PER_WORD - remainder) % APINT_BITS_PER_WORD; + //enum { remainder = BitWidth % APINT_BITS_PER_WORD, excessBits = APINT_BITS_PER_WORD - remainder}; + uint32_t Count = CountLeadingZeros_64(VAL); + if (Count) + Count-=excessBits; + return AESL_std::min(Count, (uint32_t)_AP_W); + } + + /// HiBits - This function returns the high "numBits" bits of this ap_private. + ap_private<_AP_W, _AP_S, 1> getHiBits(uint32_t numBits) const { + ap_private<_AP_W, _AP_S, 1> ret(*this); + ret = (ret)>>(BitWidth - numBits); + return ret; + } + + /// LoBits - This function returns the low "numBits" bits of this ap_private. + ap_private<_AP_W, _AP_S, 1> getLoBits(uint32_t numBits) const { + ap_private<_AP_W, _AP_S, 1> ret((VAL) << (BitWidth - numBits)); + ret = (ret)>>(BitWidth - numBits); + return ret; + //return ap_private(numBits, (VAL << (BitWidth - numBits))>> (BitWidth - numBits)); + } + + ap_private<_AP_W, _AP_S,1>& set(uint32_t bitPosition) { + VAL |= (1ULL << (bitPosition)); + clearUnusedBits(); + return *this; // clearUnusedBits(); + } + + void set() { + VAL = ~0ULL; + clearUnusedBits(); + } + + template + INLINE void set(const ap_private<_AP_W3, false> & val) { + operator = (ap_private<_AP_W3, _AP_S>(val)); + } + + INLINE void set(const ap_private & val) { + operator = (val); + } + + bool operator[](uint32_t bitPosition) const { + return (((1ULL << (bitPosition)) & VAL) != 0); + } + + INLINE void clearUnusedBits(void) { + enum { excess_bits = (_AP_W%APINT_BITS_PER_WORD) ? APINT_BITS_PER_WORD -_AP_W%APINT_BITS_PER_WORD : 0}; + VAL = _AP_S ? ((((int64_t)VAL)<<(excess_bits))>> (excess_bits)) : (excess_bits ? ((VAL)<<(excess_bits))>>(excess_bits) : VAL); + } + + INLINE void clearUnusedBitsToZero(void) { + enum { excess_bits = (_AP_W%APINT_BITS_PER_WORD) ? APINT_BITS_PER_WORD -_AP_W%APINT_BITS_PER_WORD : 0}; + static uint64_t mask = ~0ULL >> (excess_bits); + VAL &= mask; + } + + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1> udiv(const ap_private<_AP_W, _AP_S1>& RHS) const { + return ap_private<_AP_W, _AP_S||_AP_S1>(VAL / RHS.VAL); + } + + INLINE ap_private udiv(uint64_t RHS) const { + return ap_private(VAL / RHS); + } + + /// Signed divide this ap_private by ap_private RHS. + /// @brief Signed division function for ap_private. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1> sdiv(const ap_private<_AP_W, _AP_S1> & RHS) const { + if (isNegative()) + if (RHS.isNegative()) + return (-(*this)).udiv(-RHS); + else + return -((-(*this)).udiv(RHS)); + else if (RHS.isNegative()) + return -(this->udiv(-RHS)); + return this->udiv(RHS); + } + + /// Signed divide this ap_private by ap_private RHS. + /// @brief Signed division function for ap_private. + INLINE ap_private sdiv(int64_t RHS) const { + if (isNegative()) + if (RHS<0) + return (-(*this)).udiv(-RHS); + else + return -((-(*this)).udiv(RHS)); + else if (RHS<0) + return -(this->udiv(-RHS)); + return this->udiv(RHS); + } + + template + INLINE ap_private urem(const ap_private<_AP_W, _AP_S2>& RHS) const { + assert(RHS.VAL != 0 && "Divide by 0"); + return ap_private(VAL%RHS.VAL); + } + + INLINE ap_private urem(uint64_t RHS) const { + assert(RHS != 0 && "Divide by 0"); + return ap_private(VAL%RHS); + } + + /// Signed remainder operation on ap_private. + /// @brief Function for signed remainder operation. + template + INLINE ap_private srem(const ap_private<_AP_W, _AP_S2>& RHS) const { + if (isNegative()) { + ap_private lhs = -(*this); + if (RHS.isNegative()) { + ap_private rhs = -RHS; + return -(lhs.urem(rhs)); + } else + return -(lhs.urem(RHS)); + } else if (RHS.isNegative()) { + ap_private rhs = -RHS; + return this->urem(rhs); + } + return this->urem(RHS); + } + + /// Signed remainder operation on ap_private. + /// @brief Function for signed remainder operation. + INLINE ap_private srem(int64_t RHS) const { + if (isNegative()) + if (RHS<0) + return -((-(*this)).urem(-RHS)); + else + return -((-(*this)).urem(RHS)); + else if (RHS<0) + return this->urem(-RHS); + return this->urem(RHS); + } + + INLINE static void udivrem(const ap_private &LHS, const ap_private &RHS, + ap_private &Quotient, ap_private &Remainder){ + assert(RHS!=0 && "Divide by 0"); + Quotient = LHS.VAl/RHS.VAl; + Remainder = LHS.VAL % RHS.VAL; + } + + INLINE static void udivrem(const ap_private &LHS, uint64_t RHS, + ap_private &Quotient, ap_private &Remainder){ + assert(RHS!=0 && "Divide by 0"); + Quotient = LHS.VAl/RHS; + Remainder = LHS.VAL % RHS; + } + + INLINE static void sdivrem(const ap_private &LHS, const ap_private &RHS, + ap_private &Quotient, ap_private &Remainder) { + if (LHS.isNegative()) { + if (RHS.isNegative()) + ap_private::udivrem(-LHS, -RHS, Quotient, Remainder); + else + ap_private::udivrem(-LHS, RHS, Quotient, Remainder); + Quotient = -Quotient; + Remainder = -Remainder; + } else if (RHS.isNegative()) { + ap_private::udivrem(LHS, -RHS, Quotient, Remainder); + Quotient = -Quotient; + } else { + ap_private::udivrem(LHS, RHS, Quotient, Remainder); + } + } + + INLINE static void sdivrem(const ap_private &LHS, int64_t RHS, + ap_private &Quotient, ap_private &Remainder) { + if (LHS.isNegative()) { + if (RHS<0) + ap_private::udivrem(-LHS, -RHS, Quotient, Remainder); + else + ap_private::udivrem(-LHS, RHS, Quotient, Remainder); + Quotient = -Quotient; + Remainder = -Remainder; + } else if (RHS<0) { + ap_private::udivrem(LHS, -RHS, Quotient, Remainder); + Quotient = -Quotient; + } else { + ap_private::udivrem(LHS, RHS, Quotient, Remainder); + } + } + + template INLINE bool eq(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return (*this) == RHS; + } + + template INLINE bool ne(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return !((*this) == RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// the validity of the less-than relationship. + /// @returns true if *this < RHS when both are considered unsigned. + /// @brief Unsigned less than comparison + template INLINE bool ult(const ap_private<_AP_W1, _AP_S1, 1>& RHS) const { + uint64_t lhsZext = ((uint64_t(VAL)) << (64-_AP_W)) >> (64-_AP_W); + uint64_t rhsZext = ((uint64_t(RHS.VAL)) << (64-_AP_W1)) >> (64-_AP_W1); + return lhsZext < rhsZext; + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the less-than relationship. + /// @returns true if *this < RHS when both are considered signed. + /// @brief Signed less than comparison + template INLINE bool slt(const ap_private<_AP_W1, _AP_S1, 1>& RHS) const { + int64_t lhsSext = ((int64_t(VAL)) << (64-_AP_W)) >> (64-_AP_W); + int64_t rhsSext = ((int64_t(RHS.VAL)) << (64-_AP_W1)) >> (64-_AP_W1); + return lhsSext < rhsSext; + } + + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// validity of the less-or-equal relationship. + /// @returns true if *this <= RHS when both are considered unsigned. + /// @brief Unsigned less or equal comparison + template INLINE bool ule(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return ult(RHS) || eq(RHS); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the less-or-equal relationship. + /// @returns true if *this <= RHS when both are considered signed. + /// @brief Signed less or equal comparison + template INLINE bool sle(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return slt(RHS) || eq(RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// the validity of the greater-than relationship. + /// @returns true if *this > RHS when both are considered unsigned. + /// @brief Unsigned greather than comparison + template INLINE bool ugt(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return !ult(RHS) && !eq(RHS); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// the validity of the greater-than relationship. + /// @returns true if *this > RHS when both are considered signed. + /// @brief Signed greather than comparison + template INLINE bool sgt(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return !slt(RHS) && !eq(RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// validity of the greater-or-equal relationship. + /// @returns true if *this >= RHS when both are considered unsigned. + /// @brief Unsigned greater or equal comparison + template INLINE bool uge(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return !ult(RHS); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the greater-or-equal relationship. + /// @returns true if *this >= RHS when both are considered signed. + /// @brief Signed greather or equal comparison + template INLINE bool sge(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return !slt(RHS); + } + + INLINE ap_private abs() const { + if (isNegative()) + return -(*this); + return *this; + } + + ap_private<_AP_W, false> get() const { + ap_private<_AP_W,false> ret(*this); + return ret; + } + + INLINE static uint32_t getBitsNeeded(const char* str, uint32_t slen, uint8_t radix) { + return _AP_W; + } + + INLINE uint32_t getActiveBits() const { + uint32_t bits=_AP_W - countLeadingZeros(); + return bits?bits:1; + } + + INLINE double roundToDouble(bool isSigned=false) const { + const static uint64_t mask = ~0ULL << (APINT_BITS_PER_WORD - _AP_W); + return double(VAL); + } + + INLINE unsigned length() const { return _AP_W; } + + /*Reverse the contents of ap_private instance. I.e. LSB becomes MSB and vise versa*/ + INLINE ap_private& reverse () { + for (int i = 0; i < _AP_W/2; ++i) { + bool tmp = operator[](i); + if (operator[](_AP_W - 1 - i)) + set(i); + else + clear(i); + if (tmp) + set(_AP_W - 1 - i); + else + clear(_AP_W - 1 - i); + } + clearUnusedBits(); + return *this; + } + + /*Return true if the value of ap_private instance is zero*/ + INLINE bool iszero () const { + return isMinValue(); + } + + /* x < 0 */ + INLINE bool sign () const { + if (isNegative()) + return true; + return false; + } + + /* x[i] = !x[i] */ + INLINE void invert (int i) { + assert( i >= 0 && "Attempting to read bit with negative index"); + assert( i < _AP_W && "Attempting to read bit beyond MSB"); + flip(i); + } + + /* x[i] */ + INLINE bool test (int i) const { + assert( i >= 0 && "Attempting to read bit with negative index"); + assert( i < _AP_W && "Attempting to read bit beyond MSB"); + return operator[](i); + } + + //This is used for sc_lv and sc_bv, which is implemented by sc_uint + //Rotate an ap_private object n places to the left + INLINE void lrotate(int n) { + assert( n >= 0 && "Attempting to shift negative index"); + assert( n < _AP_W && "Shift value larger than bit width"); + operator = (shl(n) | lshr(_AP_W - n)); + } + + //This is used for sc_lv and sc_bv, which is implemented by sc_uint + //Rotate an ap_private object n places to the right + INLINE void rrotate(int n) { + assert( n >= 0 && "Attempting to shift negative index"); + assert( n < _AP_W && "Shift value larger than bit width"); + operator = (lshr(n) | shl(_AP_W - n)); + } + + //Set the ith bit into v + INLINE void set (int i, bool v) { + assert( i >= 0 && "Attempting to write bit with negative index"); + assert( i < _AP_W && "Attempting to write bit beyond MSB"); + v ? set(i) : clear(i); + } + + //Set the ith bit into v + INLINE void set_bit (int i, bool v) { + assert( i >= 0 && "Attempting to write bit with negative index"); + assert( i < _AP_W && "Attempting to write bit beyond MSB"); + v ? set(i) : clear(i); + } + + //Get the value of ith bit + INLINE bool get_bit (int i) const { + assert( i >= 0 && "Attempting to read bit with negative index"); + assert( i < _AP_W && "Attempting to read bit beyond MSB"); + return operator [](i); + } + + //complements every bit + INLINE void b_not() { + flip(); + } + + //Binary Arithmetic + //----------------------------------------------------------- +#define OP_BIN_AP(Sym,Rty, Fun) \ + template \ + INLINE \ + typename RType<_AP_W2,_AP_S2>::Rty \ + operator Sym (const ap_private<_AP_W2,_AP_S2>& op) const { \ + typename RType<_AP_W2,_AP_S2>::Rty lhs(*this); \ + typename RType<_AP_W2,_AP_S2>::Rty rhs(op); \ + return lhs.Fun(rhs); \ + } \ + + ///Bitwise and, or, xor + //OP_BIN_AP(&,logic, And) + //OP_BIN_AP(|,logic, Or) + //OP_BIN_AP(^,logic, Xor) + +#undef OP_BIN_AP + template + INLINE typename RType<_AP_W2,_AP_S2>::div + operator / (const ap_private<_AP_W2,_AP_S2>&op) const { + ap_private lhs=ap_private(*this); + ap_private rhs=ap_private(op); + return typename RType<_AP_W2,_AP_S2>::div((_AP_S||_AP_S2)?lhs.sdiv(rhs):lhs.udiv(rhs)); + } + + + template + INLINE typename RType<_AP_W2,_AP_S2>::mod + operator % (const ap_private<_AP_W2,_AP_S2>&op) const { + ap_private lhs=*this; + ap_private rhs=op; + typename RType<_AP_W2,_AP_S2>::mod res = typename RType<_AP_W2,_AP_S2>::mod (_AP_S?lhs.srem(rhs):lhs.urem(rhs)); + return res; + } + + +#define OP_ASSIGN_AP_2(Sym) \ + template \ + INLINE ap_private<_AP_W, _AP_S>& operator Sym##=(const ap_private<_AP_W2,_AP_S2>& op) \ + { \ + *this=operator Sym (op); \ + return *this; \ + } \ + + OP_ASSIGN_AP_2(/) + OP_ASSIGN_AP_2(%) +#undef OP_ASSIGN_AP_2 + + ///Bitwise assign: and, or, xor + //------------------------------------------------------------- + // OP_ASSIGN_AP(&) + // OP_ASSIGN_AP(^) + // OP_ASSIGN_AP(|) +#undef OP_ASSIGN_AP +#if 1 + + template + INLINE ap_private<_AP_W, _AP_S> + operator << (const ap_private<_AP_W2, _AP_S2>& op2) const { + uint32_t sh=op2.to_uint(); + return *this << sh; + } + + INLINE ap_private<_AP_W, _AP_S> + operator << (uint32_t sh) const { + return shl(sh); + } + +#endif + + template + INLINE ap_private<_AP_W, _AP_S> + operator >> (const ap_private<_AP_W2, _AP_S2>& op2) const { + uint32_t sh = op2.to_uint(); + return *this >> sh; + } + + INLINE ap_private<_AP_W, _AP_S> + operator >>(uint32_t sh) const { + ap_private<_AP_W, _AP_S> r(*this); + bool overflow=(sh>=_AP_W); + bool neg_v=r.isNegative(); + if(_AP_S) { + if(overflow) + neg_v?r.set():r.clear(); + else + return r.ashr(sh); + } else { + if(overflow) + r.clear(); + else + return r.lshr(sh); + } + return r; + } + + ///Shift assign + //------------------------------------------------------------------ +#define OP_ASSIGN_AP_3_SINGLE(Sym) \ + template \ + INLINE ap_private<_AP_W, _AP_S>& operator Sym##=(const ap_private<_AP_W2,_AP_S2>& op) \ + { \ + *this=operator Sym (op.getVal()); \ + return *this; \ + } + OP_ASSIGN_AP_3_SINGLE(>>) +#undef OP_ASSIGN_AP_3_SINGLE + + ///Comparisons + //----------------------------------------------------------------- + template + INLINE bool operator != (const ap_private<_AP_W2, _AP_S2, 1>& op) const { + return !(*this==op); + } + + template + INLINE bool operator > (const ap_private<_AP_W2, _AP_S2, 1>& op) const { + return op < *this; + } + + template + INLINE bool operator <= (const ap_private<_AP_W2, _AP_S2, 1>& op) const { + return !(*this>op); + } + + template + INLINE bool operator < (const ap_private<_AP_W2, _AP_S2, 1>& op) const { + enum { _AP_MAX_W = AP_MAX(_AP_W+(_AP_S||_AP_S2),_AP_W2+(_AP_S||_AP_S2))}; + ap_private<_AP_MAX_W, _AP_S> lhs(*this); + ap_private<_AP_MAX_W, _AP_S2> rhs(op); + if (_AP_S == _AP_S2) + return _AP_S?lhs.slt(rhs):lhs.ult(rhs); + else if (_AP_W < 32 && _AP_W2 < 32) + return lhs.slt(rhs); + else + if (_AP_S) + if (_AP_W2 >= _AP_W) + return lhs.ult(rhs); + else + return lhs.slt(rhs); + else + if (_AP_W >= _AP_W2) + return lhs.ult(rhs); + else + return lhs.slt(rhs); + } + + template + INLINE bool operator >=(const ap_private<_AP_W2, _AP_S2, 1>& op) const { + return !(*this + INLINE bool operator == (const ap_private<_AP_W2, _AP_S2, _AP_N2>& op) const { + return op == *this; + } + + template + INLINE bool operator != (const ap_private<_AP_W2, _AP_S2, _AP_N2>& op) const { + return !(op==*this); + } + + template + INLINE bool operator > (const ap_private<_AP_W2, _AP_S2, _AP_N2>& op) const { + return op < (*this); + } + + template + INLINE bool operator <= (const ap_private<_AP_W2, _AP_S2, _AP_N2>& op) const { + return op >= *this; + } + + template + INLINE bool operator <(const ap_private<_AP_W2, _AP_S2, _AP_N2>& op) const { + return op > *this; + } + + template + INLINE bool operator >=(const ap_private<_AP_W2,_AP_S2,_AP_N2>& op) const { + return op <= *this; + } + ///Bit and Part Select + //-------------------------------------------------------------- + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (int Hi, int Lo) { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (int Hi, int Lo) const { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(const_cast*>(this), Hi, Lo); + } + + INLINE ap_range_ref<_AP_W,_AP_S> + range (int Hi, int Lo) const { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>((const_cast*> (this)), Hi, Lo); + } + + INLINE ap_range_ref<_AP_W,_AP_S> + range (int Hi, int Lo) { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + range (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + range (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) const { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(const_cast(this), Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) const { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + return this->range(Hi, Lo); + } + + + INLINE ap_bit_ref<_AP_W,_AP_S> operator [] (uint32_t index) { + assert(index >= 0&&"Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S> (*this, (int)index); + } + + template + INLINE ap_bit_ref<_AP_W,_AP_S> operator [] (const ap_private<_AP_W2,_AP_S2> &index) { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S>( *this, index.to_int() ); + } + + template + INLINE bool operator [] (const ap_private<_AP_W2,_AP_S2>& index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + ap_bit_ref<_AP_W,_AP_S> br =operator [] (index); + return br.to_bool(); + } + + INLINE ap_bit_ref<_AP_W,_AP_S> bit (int index) { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S>( *this, index ); + } + + template + INLINE ap_bit_ref<_AP_W,_AP_S> bit (const ap_private<_AP_W2,_AP_S2> &index) { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W &&"Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S>( *this, index.to_int() ); + } + + INLINE bool bit (int index) const { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + ap_bit_ref<_AP_W,_AP_S> br(const_cast*>(this), index); + return br.to_bool(); + } + + template + INLINE bool bit (const ap_private<_AP_W2,_AP_S2>& index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + ap_bit_ref<_AP_W,_AP_S> br = bit(index); + return br.to_bool(); + } + + template + INLINE ap_concat_ref<_AP_W,ap_private<_AP_W, _AP_S>,_AP_W2,ap_private<_AP_W2,_AP_S2> > concat(const ap_private<_AP_W2,_AP_S2>& a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_private<_AP_W2,_AP_S2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W,ap_private<_AP_W, _AP_S>,_AP_W2,ap_private<_AP_W2,_AP_S2> > concat(ap_private<_AP_W2,_AP_S2>& a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_private<_AP_W2,_AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (const ap_private<_AP_W2, _AP_S2>& a2) const { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(const_cast& >(*this), const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (const ap_private<_AP_W2, _AP_S2>& a2) { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(*this, const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (ap_private<_AP_W2, _AP_S2>& a2) const { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(const_cast& >(*this), a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (ap_private<_AP_W2, _AP_S2>& a2) { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > + operator, (const ap_range_ref<_AP_W2, _AP_S2> &a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, + ap_range_ref<_AP_W2, _AP_S2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > + operator, (ap_range_ref<_AP_W2, _AP_S2> &a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, + ap_range_ref<_AP_W2, _AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, ap_bit_ref<_AP_W2, _AP_S2> > + operator, (const ap_bit_ref<_AP_W2, _AP_S2> &a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, + ap_bit_ref<_AP_W2, _AP_S2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, ap_bit_ref<_AP_W2, _AP_S2> > + operator, (ap_bit_ref<_AP_W2, _AP_S2> &a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, + ap_bit_ref<_AP_W2, _AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > + operator, (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > + operator, (ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) const { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) const { + return ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, a2); + } + + template + INLINE ap_private + operator & (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) { + return *this & a2.get(); + } + + template + INLINE ap_private + operator | (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) { + return *this | a2.get(); + } + + template + INLINE ap_private + operator ^ (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) { + return *this ^ a2.get(); + } + + + //Reduce operation + //----------------------------------------------------------- + INLINE bool and_reduce() const { + return (VAL & mask) == mask; + } + + INLINE bool nand_reduce() const { + return (VAL & mask) != mask; + } + + INLINE bool or_reduce() const { + return (bool)VAL; + } + + INLINE bool nor_reduce() const { + return VAL==0; + } + + INLINE bool xor_reduce() const { + unsigned int i=countPopulation(); + return (i%2)?true:false; + } + + INLINE bool xnor_reduce() const { + unsigned int i=countPopulation(); + return (i%2)?false:true; + } + + INLINE std::string to_string(uint8_t radix=2, bool sign=false) const { + return toString(radix, radix==10?_AP_S:sign); + } +}; +template +std::string ap_private<_AP_W, _AP_S, 1>::toString(uint8_t radix, bool wantSigned) const { + assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) && + "Radix should be 2, 8, 10, or 16!"); + static const char *digits[] = { + "0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f" + }; + std::string result; + if (radix != 10) { + // For the 2, 8 and 16 bit cases, we can just shift instead of divide + // because the number of bits per digit (1,3 and 4 respectively) divides + // equaly. We just shift until there value is zero. + + // First, check for a zero value and just short circuit the logic below. + if (*this == (uint64_t)(0)) + result = "0"; + else { + ap_private<_AP_W, false, 1> tmp(*this); + size_t insert_at = 0; + if (wantSigned && isNegative()) { + // They want to print the signed version and it is a negative value + // Flip the bits and add one to turn it into the equivalent positive + // value and put a '-' in the result. + tmp.flip(); + tmp++; + result = "-"; + insert_at = 1; + } + // Just shift tmp right for each digit width until it becomes zero + uint32_t shift = (radix == 16 ? 4 : (radix == 8 ? 3 : 1)); + uint64_t mask = radix - 1; + ap_private<_AP_W, false, 1> zero(0); + while (tmp.ne(zero)) { + unsigned digit = (unsigned)(tmp.VAL & mask); + result.insert(insert_at, digits[digit]); + tmp = tmp.lshr(shift); + } + } + return result; + } + + ap_private<_AP_W, false, 1> tmp(*this); + ap_private<6, false, 1> divisor(radix); + ap_private<_AP_W, _AP_S, 1> zero(0); + size_t insert_at = 0; + if (wantSigned && isNegative()) { + // They want to print the signed version and it is a negative value + // Flip the bits and add one to turn it into the equivalent positive + // value and put a '-' in the result. + tmp.flip(); + tmp++; + result = "-"; + insert_at = 1; + } + if (tmp == ap_private<_AP_W, false, 1>(0ULL)) + result = "0"; + else while (tmp.ne(zero)) { + ap_private<_AP_W, false, 1> APdigit = tmp%divisor; + ap_private<_AP_W, false, 1> tmp2 = tmp/divisor; + uint32_t digit = (uint32_t)(APdigit.getZExtValue()); + assert(digit < radix && "divide failed"); + result.insert(insert_at,digits[digit]); + tmp = tmp2; + } + return result; + +} + +#endif /* #ifndef LLVM_SUPPORT_MATHEXTRAS_H */ \ No newline at end of file diff --git a/hls_2018/router_02/main.cpp b/hls_2018/router_02/main.cpp new file mode 100755 index 0000000..2a4e7f5 --- /dev/null +++ b/hls_2018/router_02/main.cpp @@ -0,0 +1,97 @@ +/** + * main.cpp + * + * for Vivado HLS + */ + +#ifdef SOFTWARE +#include "ap_int.h" +#else +#include +#endif + +#ifdef CALCTIME +#include +#include +#endif + +#include "router.hpp" + +#define PRINT_SOLUTION + + +int main(int argc, char *argv[]) { + using namespace std; + + // Test data // + // NL_Q00.txt + //char boardstr[BOARDSTR_SIZE] = "X10Y05Z3L0000107041L0004107002L0102102021L0900100003"; + // NL_Q06.txt + char boardstr[BOARDSTR_SIZE] = "X10Y18Z2L0900109002L0901105012L0902103052L0903103062L0904100102L0905106012L0906109022L0717109102L0808109112L0017209172L0401200072L0912208152L0009201092L0709209092L0901206052L0309204092L0701209072L0101201022L0011202152L0016202162"; + // NL_Q08.txt + //char boardstr[BOARDSTR_SIZE] = "X17Y20Z2L0000103022L1603115052L0916107032L0302108012L1104111042L1002100002L0919116162L1616113182L1001115012L0500201182L1603213152L0600210022"; + + // Read boardstr from command line + if (1 < argc) { + // From stdin + if(argv[1][0]!='X') + { + char* c_p=fgets(boardstr, BOARDSTR_SIZE, stdin); + int length=strlen(c_p); + boardstr[length-1]=0; + } + else + { + strcpy(boardstr, argv[1]); + } + } + + // Seed value + int seed = 12345; + if (2 < argc) { + seed = atoi(argv[2]); + } + +#ifdef PRINT_SOLUTION + int size_x = (boardstr[1] - '0') * 10 + (boardstr[2] - '0'); + int size_y = (boardstr[4] - '0') * 10 + (boardstr[5] - '0'); + int size_z = (boardstr[7] - '0'); +#endif + + // Solver + ap_int<32> status; + clock_t clock_start, clock_done; + clock_start = clock(); + bool result = pynqrouter(boardstr, seed, &status); + clock_done = clock(); + if (result) { + cout << endl << "Test Passed!" << endl; + } else { + cout << endl << "Test Failed!" << endl; + } + cout << "status = " << (int)status << endl; + cout << "elapsed = " << ((double)(clock_done - clock_start) / CLOCKS_PER_SEC) << endl << endl; + +#ifdef PRINT_SOLUTION + cout << "SOLUTION" << endl; + cout << "========" << endl; + cout << "SIZE " << size_x << "X" << size_y << "X" << size_z << endl; + for (int z = 0; z < size_z; z++) { + cout << "LAYER " << (z + 1) << endl; + for (int y = 0; y < size_y; y++) { + for (int x = 0; x < size_x; x++) { + if (x != 0) { + cout << ","; + } + int i = ((x * MAX_WIDTH + y) << BITWIDTH_Z) | z; + cout << setfill('0') << setw(3) << right << (unsigned int)(unsigned char)(boardstr[i]); + //cout << (unsigned int)(unsigned char)(boardstr[i]); + } + cout << endl; + } + } +#endif + + return 0; +} + diff --git a/hls_2018/router_03/Makefile b/hls_2018/router_03/Makefile new file mode 100755 index 0000000..8f79e7a --- /dev/null +++ b/hls_2018/router_03/Makefile @@ -0,0 +1,20 @@ +TARGET = sim +OBJS = $(CPPS:.cpp=.o) +CPPS = $(wildcard *.cpp) +CXX = g++ +CXXFLAGS = -O3 -Wall -Wno-unknown-pragmas -Wno-unused-label -DSOFTWARE -DCALCTIME + +all: $(TARGET) + +$(TARGET): $(OBJS) + $(CXX) -O3 -o $@ $(OBJS) + +run: + python3 ../NLGenerator.py -x 20 -y 20 -z 6 -l 100;\ + python3 ./gen_boardstr.py Q-20x20x5_100_10.txt |\ + ./$(TARGET) - + + +clean: + rm *.o + rm $(TARGET) diff --git a/hls_2018/router_03/Makefile.cygwin b/hls_2018/router_03/Makefile.cygwin new file mode 100755 index 0000000..866fdcd --- /dev/null +++ b/hls_2018/router_03/Makefile.cygwin @@ -0,0 +1,14 @@ +TARGET = sim +OBJS = $(CPPS:.cpp=.o) +CPPS = $(wildcard *.cpp) +CXX = g++ +CXXFLAGS = -O3 -Wall -Wno-unknown-pragmas -Wno-unused-label -DSOFTWARE -DCALCTIME + +all: $(TARGET) + +$(TARGET): $(OBJS) + $(CXX) -O3 -Wl,--stack,33554432 -o $@ $(OBJS) + +clean: + rm *.o + rm $(TARGET) diff --git a/hls_2018/router_03/ap_int.h b/hls_2018/router_03/ap_int.h new file mode 100755 index 0000000..b8d9fdc --- /dev/null +++ b/hls_2018/router_03/ap_int.h @@ -0,0 +1,521 @@ +/* + * Copyright 2012 Xilinx, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __AESL_AP_SIM_H__ +#define __AESL_AP_SIM_H__ + +#ifndef __cplusplus +#error C++ is required to include this header file +#else + +#include "etc/ap_int_sim.h" +#include "etc/ap_fixed_sim.h" + +//Forward declaration +template class ap_fixed; +template class ap_ufixed; +template class ap_int; +template class ap_uint; + +//AP_INT +//-------------------------------------------------------- +template +class ap_int : public ap_private<_AP_W, true> { +#ifdef _MSC_VER +#pragma warning(disable: 4521 4522) +#endif /* #ifdef _MSC_VER */ +public: + typedef ap_private<_AP_W, true> Base; + + //Constructor + INLINE ap_int(): Base() {} + template + INLINE ap_int(const volatile ap_int<_AP_W2> &op):Base((const ap_private<_AP_W2,true> &)(op)) {} + + template + INLINE ap_int(const ap_int<_AP_W2> &op):Base((const ap_private<_AP_W2,true> &)(op)) {} + + template + INLINE ap_int(const ap_uint<_AP_W2> &op):Base((const ap_private<_AP_W2,false> &)(op)) {} + + template + INLINE ap_int(const volatile ap_uint<_AP_W2> &op):Base((const ap_private<_AP_W2,false> &)(op)) {} + + template + INLINE ap_int(const ap_range_ref<_AP_W2, _AP_S2>& ref):Base(ref) {} + + template + INLINE ap_int(const ap_bit_ref<_AP_W2, _AP_S2>& ref):Base(ref) {} + + template + INLINE ap_int(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& ref):Base(ref) {} + + template + INLINE ap_int(const ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op.to_ap_private()) {} + + template + INLINE ap_int(const ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op.to_ap_private()) {} + + template + INLINE ap_int(const volatile ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op.to_ap_private()) {} + + template + INLINE ap_int(const volatile ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op.to_ap_private()) {} + + template + INLINE ap_int(const ap_private<_AP_W2, _AP_S2>& op):Base(op) {} + + template + INLINE ap_int(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, + _AP_N2>& op):Base(op) {} + + template + INLINE ap_int(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, + _AP_N2>& op):Base(op) {} + + template + INLINE ap_int(const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& op):Base(op.to_ap_private()) {} + +#define CTOR(TYPE) \ + INLINE ap_int(TYPE v):Base(v) {} + CTOR(bool) + CTOR(signed char) + CTOR(unsigned char) + CTOR(short) + CTOR(unsigned short) + CTOR(int) + CTOR(unsigned int) + CTOR(long) + CTOR(unsigned long) + CTOR(unsigned long long) + CTOR(long long) + CTOR(float) + CTOR(double) + CTOR(const char*) + CTOR(const std::string&) +#undef CTOR + INLINE ap_int(const char* str, signed char rd):Base(str, rd) {} + //Assignment + //Another form of "write" + INLINE void operator = (const ap_int<_AP_W>& op2) volatile { + const_cast(this)->operator = (op2); + } + + INLINE void operator = (const volatile ap_int<_AP_W>& op2) volatile { + const_cast(this)->operator = (op2); + } + + INLINE ap_int<_AP_W>& operator = (const volatile ap_int<_AP_W>& op2) { + Base::operator = (const_cast& >(op2)); + return *this; + } + + INLINE ap_int<_AP_W>& operator = (const ap_int<_AP_W>& op2) { + Base::operator = ((const ap_private<_AP_W, true>&)op2); + return *this; + } +}; + +//AP_UINT +//--------------------------------------------------------------- +template +class ap_uint: public ap_private<_AP_W, false> { +#ifdef _MSC_VER +#pragma warning( disable : 4521 4522 ) +#endif +public: + typedef ap_private<_AP_W, false> Base; + //Constructor + INLINE ap_uint(): Base() {} + INLINE ap_uint(const ap_uint<_AP_W>& op) :Base(dynamic_cast&>(op)) {} + INLINE ap_uint(const volatile ap_uint<_AP_W>& op):Base(dynamic_cast&>(op)){} + template + INLINE ap_uint(const volatile ap_uint<_AP_W2> &op):Base((const ap_private<_AP_W2, false>&)(op)) {} + + template + INLINE ap_uint(const ap_uint<_AP_W2> &op) : Base((const ap_private<_AP_W2, false>&)(op)){} + + template + INLINE ap_uint(const ap_int<_AP_W2> &op) : Base((const ap_private<_AP_W2, true>&)(op)) {} + + template + INLINE ap_uint(const volatile ap_int<_AP_W2> &op) : Base((const ap_private<_AP_W2, false>&)(op)) {} + + template + INLINE ap_uint(const ap_range_ref<_AP_W2, _AP_S2>& ref):Base(ref) {} + + template + INLINE ap_uint(const ap_bit_ref<_AP_W2, _AP_S2>& ref):Base(ref) {} + + template + INLINE ap_uint(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& ref):Base(ref) {} + + template + INLINE ap_uint(const ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op.to_ap_private()) {} + + template + INLINE ap_uint(const ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op.to_ap_private()) {} + + template + INLINE ap_uint(const volatile ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op.to_ap_private()) {} + + template + INLINE ap_uint(const volatile ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op) {} + + template + INLINE ap_uint(const ap_private<_AP_W2, _AP_S2>& op):Base(op) {} + + template + INLINE ap_uint(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, + _AP_N2>& op):Base(op) {} + + template + INLINE ap_uint(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, + _AP_N2>& op):Base(op) {} + + template + INLINE ap_uint(const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& op):Base(op.to_ap_private()) {} + +#define CTOR(TYPE) \ + INLINE ap_uint(TYPE v):Base(v) {} + CTOR(bool) + CTOR(signed char) + CTOR(unsigned char) + CTOR(short) + CTOR(unsigned short) + CTOR(int) + CTOR(unsigned int) + CTOR(long) + CTOR(unsigned long) + CTOR(unsigned long long) + CTOR(long long) + CTOR(float) + CTOR(double) + CTOR(const char*) + CTOR(const std::string&) +#undef CTOR + INLINE ap_uint(const char* str, signed char rd):Base(str, rd) {} + //Assignment + //Another form of "write" + INLINE void operator = (const ap_uint<_AP_W>& op2) volatile { + Base::operator = (op2); + } + + INLINE void operator = (const volatile ap_uint<_AP_W>& op2) volatile { + Base::operator = (op2); + } + + INLINE ap_uint<_AP_W>& operator = (const volatile ap_uint<_AP_W>& op2) { + Base::operator = (op2); + return *this; + } + + INLINE ap_uint<_AP_W>& operator = (const ap_uint<_AP_W>& op2) { + Base::operator = ((const ap_private<_AP_W, false>&)(op2)); + return *this; + } +}; + +#define ap_bigint ap_int +#define ap_biguint ap_uint + +//AP_FIXED +//--------------------------------------------------------------------- +template +class ap_fixed: public ap_fixed_base<_AP_W, _AP_I, true, _AP_Q, _AP_O, _AP_N> { +#ifdef _MSC_VER +#pragma warning( disable : 4521 4522 ) +#endif +public: + typedef ap_fixed_base<_AP_W, _AP_I, true, _AP_Q, _AP_O, _AP_N> Base; + //Constructor + INLINE ap_fixed():Base() {} + + template + INLINE ap_fixed(const ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, + _AP_N2>& op): Base(op) {} + + template + INLINE ap_fixed(const ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, + _AP_N2>& op): Base(ap_fixed_base<_AP_W2, _AP_I2, + false, _AP_Q2, _AP_O2, _AP_N2>(op)) {} + + template + INLINE ap_fixed(const ap_int<_AP_W2>& op): + Base(ap_private<_AP_W2, true>(op)) {} + + template + INLINE ap_fixed(const ap_uint<_AP_W2>& op):Base(ap_private<_AP_W2, false>(op)) {} + + template + INLINE ap_fixed(const volatile ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, + _AP_N2>& op): Base(ap_fixed_base<_AP_W2, _AP_I2, + true, _AP_Q2, _AP_O2, _AP_N2>(op)) {} + + template + INLINE ap_fixed(const volatile ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, + _AP_N2>& op): Base(ap_fixed_base<_AP_W2, _AP_I2, + false, _AP_Q2, _AP_O2, _AP_N2>(op)) {} + + template + INLINE ap_fixed(const volatile ap_int<_AP_W2>& op): + Base(ap_private<_AP_W2, true>(op)) {} + + template + INLINE ap_fixed(const volatile ap_uint<_AP_W2>& op):Base(op) {} + + template + INLINE ap_fixed(const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& op):Base(op) {} + + template + INLINE ap_fixed(const ap_bit_ref<_AP_W2, _AP_S2>& op): + Base(op) {} + + template + INLINE ap_fixed(const ap_range_ref<_AP_W2, _AP_S2>& op): + Base(op) {} + + template + INLINE ap_fixed(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& op): + Base(op) {} + + template + INLINE ap_fixed(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& op): Base(op) {} + + template + INLINE ap_fixed(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& op): Base(op) {} + + template + INLINE ap_fixed(const ap_private<_AP_W2, _AP_S2>& op):Base(op) {} + + #define CTOR(TYPE) \ + INLINE ap_fixed(TYPE v):Base(v) {} + CTOR(bool) + CTOR(signed char) + CTOR(unsigned char) + CTOR(short) + CTOR(unsigned short) + CTOR(int) + CTOR(unsigned int) + CTOR(long) + CTOR(unsigned long) + CTOR(unsigned long long) + CTOR(long long) + CTOR(float) + CTOR(double) + CTOR(const char*) + CTOR(const std::string&) +#undef CTOR + INLINE ap_fixed(const char* str, signed char rd):Base(str, rd) {} + + //Assignment + INLINE ap_fixed& operator = (const ap_fixed<_AP_W, _AP_I, + _AP_Q, _AP_O, _AP_N>& op) { + Base::operator = (op); + return *this; + } + + INLINE ap_fixed& operator = (const volatile ap_fixed<_AP_W, _AP_I, + _AP_Q, _AP_O, _AP_N>& op) { + Base::operator = (op); + return *this; + } +}; + +//AP_ UFIXED +//--- ---------------------------------------------------------------- +template +class ap_ufixed : public ap_fixed_base<_AP_W, _AP_I, false, _AP_Q, _AP_O, _AP_N> { +#ifdef _MSC_VER +#pragma warning(disable: 4521 4522) +#endif /* #ifdef _MSC_VER */ +public: + typedef ap_fixed_base<_AP_W, _AP_I, false, _AP_Q, _AP_O, _AP_N> Base; + + //Constructor + INLINE ap_ufixed():Base() {} + + template + INLINE ap_ufixed(const ap_fixed<_AP_W2, _AP_I2, _AP_Q2, + _AP_O2, _AP_N2>& op) : Base(ap_fixed_base<_AP_W2, + _AP_I2, true, _AP_Q2, _AP_O2, _AP_N2>(op)) {} + + template + INLINE ap_ufixed(const ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, + _AP_O2, _AP_N2>& op): Base(ap_fixed_base<_AP_W2, _AP_I2, + false, _AP_Q2, _AP_O2, _AP_N2>(op)) {} + + template + INLINE ap_ufixed(const ap_int<_AP_W2>& op): + Base((const ap_private<_AP_W2, true>&)(op)) {} + + template + INLINE ap_ufixed(const ap_uint<_AP_W2>& op): + Base((const ap_private<_AP_W2, false>&)(op)) {} + + template + INLINE ap_ufixed(const volatile ap_fixed<_AP_W2, _AP_I2, _AP_Q2, + _AP_O2, _AP_N2>& op) : Base(ap_fixed_base<_AP_W2, + _AP_I2, true, _AP_Q2, _AP_O2, _AP_N2>(op)) {} + + template + INLINE ap_ufixed(const volatile ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, + _AP_O2, _AP_N2>& op): Base(ap_fixed_base<_AP_W2, _AP_I2, + false, _AP_Q2, _AP_O2, _AP_N2>(op)) {} + + template + INLINE ap_ufixed(const volatile ap_int<_AP_W2>& op): + Base(ap_private<_AP_W2, true>(op)) {} + + template + INLINE ap_ufixed(const volatile ap_uint<_AP_W2>& op): + Base(ap_private<_AP_W2, false>(op)) {} + + template + INLINE ap_ufixed(const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2>& op):Base(op) {} + + template + INLINE ap_ufixed(const ap_bit_ref<_AP_W2, _AP_S2>& op): + Base(op) {} + + template + INLINE ap_ufixed(const ap_range_ref<_AP_W2, _AP_S2>& op): + Base(op) {} + + template + INLINE ap_ufixed(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& op): + Base(op) {} + + template + INLINE ap_ufixed(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& op): Base(op) {} + + template + INLINE ap_ufixed(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& op): Base(op) {} + + template + INLINE ap_ufixed(const ap_private<_AP_W2, _AP_S2>& op):Base(op) {} + + #define CTOR(TYPE) \ + INLINE ap_ufixed(TYPE v):Base(v) {} + CTOR(bool) + CTOR(signed char) + CTOR(unsigned char) + CTOR(short) + CTOR(unsigned short) + CTOR(int) + CTOR(unsigned int) + CTOR(long) + CTOR(unsigned long) + CTOR(unsigned long long) + CTOR(long long) + CTOR(float) + CTOR(double) + CTOR(const char*) + CTOR(const std::string&) +#undef CTOR + INLINE ap_ufixed(const char* str, signed char rd):Base(str, rd) {} + + //Assignment + INLINE ap_ufixed& operator = (const ap_ufixed<_AP_W, _AP_I, + _AP_Q, _AP_O, _AP_N>& op) { + Base::operator = (op); + return *this; + } + + INLINE ap_ufixed& operator = (const volatile ap_ufixed<_AP_W, _AP_I, + _AP_Q, _AP_O, _AP_N>& op) { + Base::V = const_cast(op); + return *this; + } +}; + +#if defined(SYSTEMC_H) || defined(SYSTEMC_INCLUDED) +template +INLINE void sc_trace(sc_core::sc_trace_file *tf, const ap_int<_AP_W> &op, + const std::string &name) { + if (tf) + tf->trace(sc_dt::sc_lv<_AP_W>(op.to_string(2).c_str()), name); +} + +template +INLINE void sc_trace(sc_core::sc_trace_file *tf, const ap_uint<_AP_W> &op, + const std::string &name) { + if (tf) + tf->trace(sc_dt::sc_lv<_AP_W>(op.to_string(2).c_str()), name); +} + +template +INLINE void sc_trace(sc_core::sc_trace_file *tf, const ap_fixed<_AP_W, _AP_I, _AP_Q, _AP_O, _AP_N >&op, const std::string &name) { + tf->trace(sc_dt::sc_lv<_AP_W>(op.to_string(2).c_str()), name); +} + +template +INLINE void sc_trace(sc_core::sc_trace_file *tf, const ap_ufixed<_AP_W, _AP_I, _AP_Q, _AP_O, _AP_N >&op, const std::string &name) { + tf->trace(sc_dt::sc_lv<_AP_W>(op.to_string(2).c_str()), name); +} +#endif /* #if defined(SYSTEMC_H) || defined(SYSTEMC_INCLUDED) */ +#endif /* #ifndef __cplusplus */ +#endif /* #ifndef __AESL_AP_SIM_H__ */ \ No newline at end of file diff --git a/hls_2018/router_03/etc/ap_fixed_sim.h b/hls_2018/router_03/etc/ap_fixed_sim.h new file mode 100755 index 0000000..5be571d --- /dev/null +++ b/hls_2018/router_03/etc/ap_fixed_sim.h @@ -0,0 +1,2451 @@ +/* + * Copyright 2012 Xilinx, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __AESL_GCC_AP_FIXED_H__ +#define __AESL_GCC_AP_FIXED_H__ + +#ifndef __cplusplus + #error C++ is required to include this header file +#endif /* #ifndef __cplusplus */ + + +#include +#ifndef __AESL_APDT_IN_SCFLOW__ + #include "etc/ap_int_sim.h" +#else + #include "../etc/ap_private.h" +#endif /* #ifndef __AESL_APDT_IN_SCFLOW__ */ + +#define FLOAT_MAN 23 +#define FLOAT_EXP 8 +#define DOUBLE_MAN 52 +#define DOUBLE_EXP 11 +// #define DOUBLE_MAN_MASK (~0ULL >> (64-DOUBLE_MAN-2)) +#define DOUBLE_MAN_MASK 0x3fffffffffffffULL +#define BIAS(e) ((1ULL<<(e-1))-1) +#define FLOAT_BIAS BIAS(FLOAT_EXP) +#define DOUBLE_BIAS BIAS(DOUBLE_EXP) + +/// Forward declaration. +template struct ap_fixed_base; + +///Proxy class, which allows bit selection to be used as both rvalue(for reading) and +//lvalue(for writing) +template +struct af_bit_ref { +#ifdef _MSC_VER + #pragma warning(disable: 4521 4522) +#endif /* #ifdef _MSC_VER */ + ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& d_bv; + int d_index; +public: + INLINE af_bit_ref(const af_bit_ref<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& ref): + d_bv(ref.d_bv), d_index(ref.d_index) {} + + INLINE af_bit_ref(ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>* bv, int index=0): + d_bv(*bv),d_index(index) {} + + INLINE operator bool() const { + return d_bv.V[d_index]; + } + + INLINE af_bit_ref& operator=(unsigned long long val) { + if (val) + d_bv.V.set(d_index); + else + d_bv.V.clear(d_index); + return *this; + } + + template + INLINE af_bit_ref& operator =(const ap_private<_AP_W2,_AP_S2>& val) { + return operator=(val!=0); + } + + INLINE af_bit_ref& operator =(const af_bit_ref<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& val) { + return operator=((unsigned long long)(bool)val); + } + + template + INLINE af_bit_ref operator=(const af_bit_ref<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& val) { + return operator=((unsigned long long)(bool)val); + } + + template + INLINE af_bit_ref& operator = ( const ap_bit_ref<_AP_W2, _AP_S2> &val) { + return operator =((unsigned long long) (bool) val); + } + + template + INLINE af_bit_ref& operator = ( const ap_range_ref<_AP_W2,_AP_S2>& val) { + return operator =((const ap_private<_AP_W2, false>) val); + } + + template + INLINE af_bit_ref& operator= (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& val) { + return operator=((const ap_private<_AP_W2, false>)(val)); + } + + template + INLINE af_bit_ref& operator= (const ap_concat_ref<_AP_W2, _AP_T3, _AP_W3, _AP_T3>& val) { + return operator=((const ap_private<_AP_W2 + _AP_W3, false>)(val)); + } + + template + INLINE ap_concat_ref<1, af_bit_ref, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (ap_private<_AP_W2, _AP_S2>& op) { + return ap_concat_ref<1, af_bit_ref, _AP_W2, + ap_private<_AP_W2, _AP_S2> >(*this, op); + } + + template + INLINE ap_concat_ref<1, af_bit_ref, 1, ap_bit_ref<_AP_W2, _AP_S2> > + operator, (const ap_bit_ref<_AP_W2, _AP_S2> &op) { + return ap_concat_ref<1, af_bit_ref, 1, + ap_bit_ref<_AP_W2, _AP_S2> >(*this, + const_cast& >(op)); + } + + template + INLINE ap_concat_ref<1, af_bit_ref, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > + operator, (const ap_range_ref<_AP_W2, _AP_S2> &op) { + return ap_concat_ref<1, af_bit_ref, _AP_W2, + ap_range_ref<_AP_W2, _AP_S2> >(*this, + const_cast& >(op)); + } + + template + INLINE ap_concat_ref<1, af_bit_ref, _AP_W2 + _AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > + operator, (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &op) { + return ap_concat_ref<1, af_bit_ref, _AP_W2 + _AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(*this, + const_cast& >(op)); + } + + template + INLINE ap_concat_ref<1, af_bit_ref, _AP_W2, + af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &op) { + return ap_concat_ref<1, af_bit_ref, _AP_W2, + af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, + _AP_N2> >(*this, const_cast& >(op)); + } + + template + INLINE ap_concat_ref<1, af_bit_ref, 1, + af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &op) { + return ap_concat_ref<1, af_bit_ref, 1, + af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, + const_cast& >(op)); + } + + template + INLINE bool operator == (const af_bit_ref<_AP_W2, _AP_I2, + _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) { + return get() == op.get(); + } + + template + INLINE bool operator != (const af_bit_ref<_AP_W2, _AP_I2, + _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) { + return get() != op.get(); + } + + INLINE bool operator ~ () const { + bool bit = (d_bv.V)[d_index]; + return bit ? false : true; + } + + INLINE int length() const { + return 1; + } + + INLINE bool get() { + return d_bv.V[d_index]; + } + + INLINE bool get() const { + return d_bv.V[d_index]; + } + + INLINE std::string to_string() const { + return d_bv.V[d_index] ? "1" : "0"; + } +}; + +///Range(slice) reference +//------------------------------------------------------------ +template +struct af_range_ref { +#ifdef _MSC_VER + #pragma warning(disable: 4521 4522) +#endif /* #ifdef _MSC_VER */ + ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &d_bv; + int l_index; + int h_index; + +public: + INLINE af_range_ref(const af_range_ref<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& ref): + d_bv(ref.d_bv), l_index(ref.l_index), h_index(ref.h_index) {} + + INLINE af_range_ref(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>* bv, int h, int l): + d_bv(*bv),l_index(l),h_index(h) { + //if (h < l) + // fprintf(stderr, + //"Warning! The bits selected will be returned in reverse order\n"); + } + + INLINE operator ap_private<_AP_W, false> () const { + if (h_index >= l_index) { + ap_private<_AP_W, false> val(d_bv.V); + ap_private<_AP_W,false> mask(-1); + mask>>=_AP_W-(h_index-l_index+1); + val>>=l_index; + return val&=mask; + } else { + ap_private<_AP_W, false> val = 0; + for (int i=0, j=l_index;j>=0&&j>=h_index;j--,i++) + if ((d_bv.V)[j]) val.set(i); + return val; + } + } + + INLINE operator unsigned long long() const { + return get().to_uint64(); + } + + template + INLINE af_range_ref& operator =(const ap_private<_AP_W2,_AP_S2>& val) { + ap_private<_AP_W, false> vval= ap_private<_AP_W, false>(val); + if (l_index > h_index) { + for (int i=0, j=l_index;j>=0&&j>=h_index;j--,i++) + vval[i]? d_bv.V.set(j):d_bv.V.clear(j); + } else { + ap_private<_AP_W,false> mask(-1); + if (l_index>0) { + mask<<=l_index; + vval<<=l_index; + } + if (h_index<_AP_W-1) { + ap_private<_AP_W,false> mask2(-1); + mask2>>=_AP_W-h_index-1; + mask&=mask2; + vval&=mask2; + } + mask.flip(); + d_bv.V &= mask; + d_bv.V |= vval; + } + return *this; + } + + INLINE af_range_ref& operator = (unsigned long long val) { + const ap_private<_AP_W, false> tmpVal(val); + return operator = (tmpVal); + } + + template + INLINE af_range_ref& operator = + (const ap_concat_ref <_AP_W3, _AP_T3, _AP_W4, _AP_T4>& val) { + const ap_private<_AP_W, false> tmpVal(val); + return operator = (tmpVal); + } + + template + INLINE af_range_ref& operator =(const ap_bit_ref<_AP_W3, _AP_S3>& val) { + const ap_private<_AP_W, false> tmpVal(val); + return operator = (tmpVal); + } + + template + INLINE af_range_ref& operator =(const ap_range_ref<_AP_W3,_AP_S3>& val) { + const ap_private<_AP_W, false> tmpVal(val); + return operator =(tmpVal); + } + + template + INLINE af_range_ref& operator= (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& val) { + const ap_private<_AP_W2, false> tmp= val.get(); + return operator = (tmp); + } + + INLINE af_range_ref& operator= (const af_range_ref<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& val) { + const ap_private<_AP_W, false> tmp= val.get(); + return operator = (tmp); + } + + template + INLINE af_range_ref& operator= (const ap_fixed_base<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& val) { + return operator=(val.to_ap_private()); + } + + template + INLINE bool operator == (const ap_range_ref<_AP_W2, _AP_S2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs==rhs; + } + + template + INLINE bool operator != (const ap_range_ref<_AP_W2, _AP_S2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs!=rhs; + } + + template + INLINE bool operator > (const ap_range_ref<_AP_W2, _AP_S2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs>rhs; + } + + template + INLINE bool operator >= (const ap_range_ref<_AP_W2, _AP_S2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs>=rhs; + } + + template + INLINE bool operator < (const ap_range_ref<_AP_W2, _AP_S2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs + INLINE bool operator <= (const ap_range_ref<_AP_W2, _AP_S2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs<=rhs; + } + + template + INLINE bool operator == (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs==rhs; + } + + template + INLINE bool operator != (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs!=rhs; + } + + template + INLINE bool operator > (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs>rhs; + } + + template + INLINE bool operator >= (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs>=rhs; + } + + template + INLINE bool operator < (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs + INLINE bool operator <= (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs<=rhs; + } + + template + INLINE void set(const ap_private<_AP_W2,false>& val) { + ap_private<_AP_W,_AP_S> vval=val; + if (l_index>h_index) { + for (int i=0, j=l_index;j>=0&&j>=h_index;j--,i++) + vval[i]? d_bv.V.set(j):d_bv.V.clear(j); + } else { + ap_private<_AP_W,_AP_S> mask(-1); + if (l_index>0) { + ap_private<_AP_W,false> mask1(-1); + mask1>>=_AP_W-l_index; + mask1.flip(); + mask=mask1; + //vval&=mask1; + vval<<=l_index; + } + if (h_index<_AP_W-1) { + ap_private<_AP_W,false> mask2(-1); + mask2<<=h_index+1; + mask2.flip(); + mask&=mask2; + vval&=mask2; + } + mask.flip(); + d_bv&=mask; + d_bv|=vval; + } + + } + + INLINE ap_private<_AP_W,false> get() const { + if (h_index val(0); + for (int i=0, j=l_index;j>=0&&j>=h_index;j--,i++) + if ((d_bv.V)[j]) val.set(i); + return val; + } else { + ap_private<_AP_W, false> val = ap_private<_AP_W,false>(d_bv.V); + val>>= l_index; + if (h_index<_AP_W-1) + { + ap_private<_AP_W,false> mask(-1); + mask>>=_AP_W-(h_index-l_index+1); + val&=mask; + } + return val; + } + } + + template + INLINE ap_concat_ref<_AP_W, af_range_ref, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (ap_private<_AP_W2, _AP_S2>& op) { + return ap_concat_ref<_AP_W, af_range_ref, _AP_W2, + ap_private<_AP_W2, _AP_S2> >(*this, op); + } + + template + INLINE ap_concat_ref<_AP_W, af_range_ref, 1, ap_bit_ref<_AP_W2, _AP_S2> > + operator, (const ap_bit_ref<_AP_W2, _AP_S2> &op) { + return ap_concat_ref<_AP_W, af_range_ref, 1, + ap_bit_ref<_AP_W2, _AP_S2> >(*this, + const_cast& >(op)); + } + + template + INLINE ap_concat_ref<_AP_W, af_range_ref, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > + operator, (const ap_range_ref<_AP_W2, _AP_S2> &op) { + return ap_concat_ref<_AP_W, af_range_ref, _AP_W2, + ap_range_ref<_AP_W2, _AP_S2> >(*this, + const_cast& >(op)); + } + + template + INLINE ap_concat_ref<_AP_W, af_range_ref, _AP_W2 + _AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > + operator, (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &op) { + return ap_concat_ref<_AP_W, af_range_ref, _AP_W2 + _AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(*this, + const_cast& >(op)); + } + + template + INLINE ap_concat_ref<_AP_W, af_range_ref, _AP_W2, + af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &op) { + return ap_concat_ref<_AP_W, af_range_ref, _AP_W2, + af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, + const_cast& > (op)); + } + + template + INLINE ap_concat_ref<_AP_W, af_range_ref, 1, + af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &op) { + return ap_concat_ref<_AP_W, af_range_ref, 1, + af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, + const_cast& >(op)); + } + + INLINE int length() const { + return h_index>=l_index?h_index-l_index+1:l_index-h_index+1; + } + + INLINE int to_int() const { + ap_private<_AP_W,false> val=get(); + return val.to_int(); + } + + INLINE unsigned int to_uint() const { + ap_private<_AP_W,false> val=get(); + return val.to_uint(); + } + + INLINE long to_long() const { + ap_private<_AP_W,false> val=get(); + return val.to_long(); + } + + INLINE unsigned long to_ulong() const { + ap_private<_AP_W,false> val=get(); + return val.to_ulong(); + } + + INLINE ap_slong to_int64() const { + ap_private<_AP_W,false> val=get(); + return val.to_int64(); + } + + INLINE ap_ulong to_uint64() const { + ap_private<_AP_W,false> val=get(); + return val.to_uint64(); + } + + INLINE std::string to_string(uint8_t radix) const { + return get().to_string(radix); + } + +}; + +//----------------------------------------------------------------------------- +///ap_fixed_base: AutoPilot fixed point +//----------------------------------------------------------------------------- +template +struct ap_fixed_base { +#ifdef _MSC_VER + #pragma warning(disable: 4521 4522) +#endif /* #ifdef _MSC_VER */ +public: + template friend struct +ap_fixed_base; + template friend struct +af_bit_ref; + + INLINE void overflow_adjust(bool underflow, bool overflow, + bool lD, bool sign) { + if (!overflow && !underflow) return; + switch (_AP_O) { + case AP_WRAP: + if (_AP_N == 0) + return; + if (_AP_S) { + //signed SC_WRAP + //n_bits == 1; + if (_AP_N > 1) { + ap_private<_AP_W, _AP_S> mask(-1); + if (_AP_N >= _AP_W) mask = 0; + else mask.lshr(_AP_N); + if (sign) + V &= mask; + else + V |= ~mask; + } + sign ? V.set(_AP_W - 1) : V.clear(_AP_W - 1); + } else { + //unsigned SC_WRAP + ap_private<_AP_W, _AP_S> mask(-1); + if (_AP_N >= _AP_W) mask = 0; + else mask.lshr(_AP_N); + mask.flip(); + V |= mask; + } + break; + case AP_SAT_ZERO: + V.clear(); + break; + case AP_WRAP_SM: + { + bool Ro = ap_private_ops::get<_AP_W, _AP_S, _AP_W -1>(V); // V[_AP_W -1]; + if (_AP_N == 0) { + if (lD != Ro) { + V.flip(); + lD ? ap_private_ops::set<_AP_W, _AP_S, _AP_W - 1>(V) : + ap_private_ops::clear<_AP_W, _AP_S, _AP_W - 1>(V); + } + } else { + if (_AP_N == 1 && sign != Ro) { + V.flip(); + } else if (_AP_N > 1) { + bool lNo = ap_private_ops::get<_AP_W, _AP_S, _AP_W - _AP_N> (V); // V[_AP_W - _AP_N]; + if (lNo == sign) + V.flip(); + ap_private<_AP_W, false> mask(-1); + if (_AP_N >= _AP_W) mask = 0; + else mask.lshr(_AP_N); + if (sign) + V &= mask; + else + V |= mask.flip(); + sign ? ap_private_ops::set<_AP_W, _AP_S, _AP_W - 1>(V) : ap_private_ops::clear<_AP_W, _AP_S, _AP_W - 1>(V); + } + } + } + break; + default: + if (_AP_S) { + if (overflow) { + V.set(); ap_private_ops::clear<_AP_W, _AP_S, _AP_W-1>(V); + } else if (underflow) { + V.clear(); + ap_private_ops::set<_AP_W, _AP_S, _AP_W-1>(V); + if (_AP_O == AP_SAT_SYM) + ap_private_ops::set<_AP_W, _AP_S, 0>(V); + } + } else { + if (overflow) + V.set(); + else if (underflow) + V.clear(); + } + } + } + + INLINE bool quantization_adjust(bool qb, bool r, bool s) { + bool carry=ap_private_ops::get<_AP_W, _AP_S, _AP_W-1>(V); + switch (_AP_Q) { + case AP_TRN: + return false; + case AP_RND_ZERO: + qb &= s || r; + break; + case AP_RND_MIN_INF: + qb &= r; + break; + case AP_RND_INF: + qb &= !s || r; + break; + case AP_RND_CONV: + qb &= ap_private_ops::get<_AP_W, _AP_S, 0>(V) || r; + break; + case AP_TRN_ZERO: + qb = s && ( qb || r ); + break; + default:; + + } + if (qb) ++V; + //only when old V[_AP_W-1]==1 && new V[_AP_W-1]==0 + return carry && !(ap_private_ops::get<_AP_W, _AP_S, _AP_W-1>(V)); //(!V[_AP_W-1]); + } + + template + struct RType { + enum { + _AP_F=_AP_W-_AP_I, + F2=_AP_W2-_AP_I2, + mult_w = _AP_W+_AP_W2, + mult_i = _AP_I+_AP_I2, + mult_s = _AP_S||_AP_S2, + plus_w = AP_MAX(_AP_I+(_AP_S2&&!_AP_S),_AP_I2+(_AP_S&&!_AP_S2))+1+AP_MAX(_AP_F,F2), + plus_i = AP_MAX(_AP_I+(_AP_S2&&!_AP_S),_AP_I2+(_AP_S&&!_AP_S2))+1, + plus_s = _AP_S||_AP_S2, + minus_w = AP_MAX(_AP_I+(_AP_S2&&!_AP_S),_AP_I2+(_AP_S&&!_AP_S2))+1+AP_MAX(_AP_F,F2), + minus_i = AP_MAX(_AP_I+(_AP_S2&&!_AP_S),_AP_I2+(_AP_S&&!_AP_S2))+1, + minus_s = true, +#ifndef __SC_COMPATIBLE__ + div_w = _AP_W + AP_MAX(_AP_W2 - _AP_I2, 0) + _AP_S2, +#else + div_w = _AP_W + AP_MAX(_AP_W2 - _AP_I2, 0) + _AP_S2 + AP_MAX(_AP_I2, 0), +#endif /* #ifndef __SC_COMPATIBLE__ */ + div_i = _AP_I + (_AP_W2-_AP_I2) + _AP_S2, + div_s = _AP_S||_AP_S2, + logic_w = AP_MAX(_AP_I+(_AP_S2&&!_AP_S),_AP_I2+(_AP_S&&!_AP_S2))+AP_MAX(_AP_F,F2), + logic_i = AP_MAX(_AP_I+(_AP_S2&&!_AP_S),_AP_I2+(_AP_S&&!_AP_S2)), + logic_s = _AP_S||_AP_S2 + }; + + typedef ap_fixed_base mult; + typedef ap_fixed_base plus; + typedef ap_fixed_base minus; + typedef ap_fixed_base logic; + typedef ap_fixed_base div; + typedef ap_fixed_base<_AP_W, _AP_I, _AP_S> arg1; + }; + INLINE void report() { +#if 0 + if (_AP_W > 1024 && _AP_W <= 4096) { + fprintf(stderr, "[W] W=%d is out of bound (1<=W<=1024):" + " for synthesis, please define macro AP_INT_TYPE_EXT(N) to" + " extend the valid range.\n", _AP_W); + } else +#endif /* #if 0 */ + if (_AP_W > MAX_MODE(AP_INT_MAX_W) * 1024) { + fprintf(stderr, "[E] ap_%sfixed<%d, ...>: Bitwidth exceeds the " + "default max value %d. Please use macro " + "AP_INT_MAX_W to set a larger max value.\n", + _AP_S?"":"u", _AP_W, + MAX_MODE(AP_INT_MAX_W) * 1024); + exit(1); + } + } + + /// Constructors. + // ------------------------------------------------------------------------- +#if 0 + #ifdef __SC_COMPATIBLE__ + INLINE ap_fixed_base():V(uint32_t(_AP_W), uint64_t(0)) {} + #else + INLINE ap_fixed_base():V(uint32_t(_AP_W)) {} + #endif /* #ifdef __SC_COMPATIBLE__ */ +#else + INLINE ap_fixed_base():V(0) {} +#endif /* #if 0 */ + // INLINE ap_fixed_base():V() {} + // INLINE explicit ap_fixed_base(const ap_private<_AP_W+_AP_I, _AP_S>& _V):V(_V) {} + INLINE ap_fixed_base(const ap_fixed_base& op):V(op.V) {} + template + INLINE ap_fixed_base(const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op):V(0) { + enum {N2=_AP_W2,_AP_F=_AP_W-_AP_I,F2=_AP_W2-_AP_I2,QUAN_INC=F2>_AP_F && !(_AP_Q==AP_TRN || + (_AP_Q==AP_TRN_ZERO && !_AP_S2))}; + if (!op) return; + bool carry=false; + //handle quantization + enum { sh_amt =(F2>_AP_F)?F2-_AP_F:_AP_F-F2}; + const ap_private<_AP_W2, _AP_S2>& val = op.V; + bool neg_src=val.isNegative(); + if (F2==_AP_F) + V=val; + + else if (F2>_AP_F) { + if (sh_amt >= _AP_W2) + V = neg_src ? -1 : 0; + else + V = _AP_S2?val.ashr(sh_amt):val.lshr(sh_amt); + if (_AP_Q!=AP_TRN && !(_AP_Q==AP_TRN_ZERO && !_AP_S2)) { + bool qb = false; + if (F2-_AP_F>_AP_W2) + qb = neg_src; + else + qb = ap_private_ops::get<_AP_W2, _AP_S2, F2-_AP_F-1>(val); + + bool r=false; + enum { pos3 = F2-_AP_F-2}; + if (pos3>=_AP_W2-1) + r=val!=0; + else if (pos3>=0) + r = (val<<(_AP_W2-1-pos3))!=0; + carry = quantization_adjust(qb,r,neg_src); + } + } else { //no quantization + if (sh_amt < _AP_W) { + V=val; + V <<= sh_amt; + } + } + //hanle overflow/underflow + if ((_AP_O!=AP_WRAP || _AP_N != 0) && + ((!_AP_S && _AP_S2) || _AP_I-_AP_S < + _AP_I2 - _AP_S2 + (QUAN_INC|| (_AP_S2 && + _AP_O==AP_SAT_SYM)))) {//saturation + bool deleted_zeros = _AP_S2?true:!carry, + deleted_ones = true; + bool lD=(_AP_I2>_AP_I && _AP_W2-_AP_I2+_AP_I>=0) && + ap_private_ops::get<_AP_W2, _AP_S2, _AP_W2-_AP_I2+_AP_I>(val); + enum { pos1=F2-_AP_F+_AP_W, pos2=F2-_AP_F+_AP_W+1}; + if (pos1 < _AP_W2) { + bool Range1_all_ones= true; + bool Range1_all_zeros= true; + if (pos1 >= 0) { + enum { __W = (_AP_W2-pos1) > 0 ? (_AP_W2-pos1) : 1 }; + const ap_private<__W, _AP_S2> Range1=ap_private<__W, _AP_S2>(val.lshr(pos1)); + Range1_all_ones=Range1.isAllOnesValue(); + Range1_all_zeros=Range1.isMinValue(); + } else { + Range1_all_ones=false; + Range1_all_zeros=val.isMinValue(); + } + bool Range2_all_ones=true; + if (pos2<_AP_W2 && pos2>=0) { + enum { __W = (_AP_W2-pos2)>0 ? (_AP_W2-pos2) : 1}; + ap_private<__W, true> Range2=ap_private<__W, true>(val.lshr(pos2)); + Range2_all_ones=Range2.isAllOnesValue(); + } else if (pos2<0) + Range2_all_ones=false; + + deleted_zeros=deleted_zeros && (carry?Range1_all_ones:Range1_all_zeros); + deleted_ones=carry?Range2_all_ones&&(F2-_AP_F+_AP_W<0||!lD) + :Range1_all_ones; + neg_src= neg_src&&!(carry && Range1_all_ones); + } else + neg_src = neg_src && V[_AP_W-1]; + + bool neg_trg= V.isNegative(); + bool overflow=(neg_trg||!deleted_zeros) && !val.isNegative(); + bool underflow=(!neg_trg||!deleted_ones)&&neg_src; + //printf("neg_src = %d, neg_trg = %d, deleted_zeros = %d, + // deleted_ones = %d, overflow = %d, underflow = %d\n", + // neg_src, neg_trg, deleted_zeros, deleted_ones, + // overflow, underflow); + if (_AP_O==AP_SAT_SYM && _AP_S2 && _AP_S) + underflow |= neg_src && (_AP_W>1?V.isMinSignedValue():true); + overflow_adjust(underflow, overflow, lD, neg_src); + } + report(); + } + + template + INLINE ap_fixed_base(const volatile ap_fixed_base<_AP_W2,_AP_I2, + _AP_S2,_AP_Q2,_AP_O2, _AP_N2> &op) : V(op.V) { + *this = const_cast&>(op); + } + + template + INLINE ap_fixed_base(const ap_private<_AP_W2,_AP_S2>& op) { + ap_fixed_base<_AP_W2,_AP_W2,_AP_S2> f_op; + f_op.V=op; + *this = f_op; + } + + INLINE ap_fixed_base(bool b) { + *this=(ap_private<1,false>)b; + report(); + } + + INLINE ap_fixed_base(char b) { + *this=(ap_private<8,false>)b; + report(); + } + + INLINE ap_fixed_base(signed char b) { + *this=(ap_private<8,true>)b; + report(); + } + + INLINE ap_fixed_base(unsigned char b) { + *this=(ap_private<8,false>)b; + report(); + } + + INLINE ap_fixed_base(signed short b) { + *this=(ap_private<16,true>)b; + report(); + } + + INLINE ap_fixed_base(unsigned short b) { + *this=(ap_private<16,false>)b; + report(); + } + + INLINE ap_fixed_base(signed int b) { + *this=(ap_private<32,true>)b; + report(); + } + + INLINE ap_fixed_base(unsigned int b) { + *this=(ap_private<32,false>)b; + report(); + } +# if defined __x86_64__ + INLINE ap_fixed_base(signed long b) { + *this=(ap_private<64,true>)b; + report(); + } + + INLINE ap_fixed_base(unsigned long b) { + *this=(ap_private<64,false>)b; + report(); + } +# else + INLINE ap_fixed_base(signed long b) { + *this=(ap_private<32,true>)b; + report(); + } + + INLINE ap_fixed_base(unsigned long b) { + *this=(ap_private<32,false>)b; + report(); + } +# endif + + INLINE ap_fixed_base(ap_slong b) { + *this=(ap_private<64,true>)b; + report(); + } + + INLINE ap_fixed_base(ap_ulong b) { + *this=(ap_private<64,false>)b; + report(); + } + +#if 1 + INLINE ap_fixed_base(const char* val):V(0) { + ap_private<_AP_W, _AP_S> Tmp(val); + V = Tmp; + } + + INLINE ap_fixed_base(const char* val, signed char rd): V(0) { + ap_private<_AP_W, _AP_S> Tmp(val, rd); + V = Tmp; + } + +#endif + + INLINE ap_fixed_base(const std::string& val) { + ap_private<_AP_W, _AP_S> Tmp(val, 2); + V = Tmp; + report(); + } + + template + INLINE ap_fixed_base(const ap_bit_ref<_AP_W2, _AP_S2>& op) { + *this = ((bool)op); + report(); + } + + template + INLINE ap_fixed_base(const ap_range_ref<_AP_W2, _AP_S2>& op) { + *this = ap_private<_AP_W2, _AP_S2>(op); + report(); + } + + template + INLINE ap_fixed_base(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& op) { + *this = ((const ap_private<_AP_W2 + _AP_W3, false>&)(op)); + report(); + } + + template + INLINE ap_fixed_base(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) { + *this = (bool(op)); + report(); + } + + template + INLINE ap_fixed_base(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) { + *this = (ap_private<_AP_W2, false>(op)); + report(); + } + + //helper function + INLINE unsigned long long doubleToRawBits(double pf)const { + union { + unsigned long long __L; + double __D; + }LD; + LD.__D=pf; + return LD.__L; + } + + + INLINE double rawBitsToDouble(unsigned long long pi) const { + union { + unsigned long long __L; + double __D; + }LD; + LD.__L=pi; + return LD.__D; + } + + INLINE float rawBitsToFloat(uint32_t pi) const { + union { + uint32_t __L; + float __D; + }LD; + LD.__L = pi; + return LD.__D; + } + + INLINE ap_fixed_base(double d):V(0) { + if (!d) return; + const bool isneg=d<0; + + const uint64_t ireg=doubleToRawBits(isneg?-d:d); + if ((ireg&0x7fffffffffffffffULL)!=0) { + const int32_t exp=(((ireg)>>DOUBLE_MAN)&0x07ff)-DOUBLE_BIAS; + ap_private man = ireg & DOUBLE_MAN_MASK; + man.clear(DOUBLE_MAN+1); + man.set(DOUBLE_MAN); + if (isneg) { + man.flip(); + man++; + } + + enum {_AP_S2=true, _AP_W2=DOUBLE_MAN+2,_AP_F=_AP_W -_AP_I }; + const int _AP_I2=exp+2; + const int F2=_AP_W2-_AP_I2; + const bool QUAN_INC=F2>_AP_F && !(_AP_Q==AP_TRN || (_AP_Q==AP_TRN_ZERO && + !_AP_S2)); + bool carry=false; + //handle quantization + const unsigned sh_amt=abs(F2-_AP_F); // sh_amt = F2>_AP_F ? F2 -_AP_F : _AP_F-F2; + if (F2==_AP_F ) + V=man; + else if (F2>_AP_F) { + if (sh_amt >= DOUBLE_MAN+2) + V=isneg?-1:0; + else + V=(man>>sh_amt) | ((man & 1ULL<<(DOUBLE_MAN+1)) ? (DOUBLE_MAN_MASK>>(DOUBLE_MAN+2-sh_amt) <<(DOUBLE_MAN+2-sh_amt)):0); + + if (_AP_Q!=AP_TRN && !(_AP_Q==AP_TRN_ZERO && !_AP_S2)) { + const bool qb=((F2-_AP_F > DOUBLE_MAN+2) ? isneg : (man & (1ULL<<(F2-_AP_F-1))) != 0); + const int pos3=F2-_AP_F-2; + const bool r = (pos3>= 0) ? (man << AP_MAX(0, _AP_W2-pos3-1)& DOUBLE_MAN_MASK)!=0 : false; + carry = quantization_adjust(qb,r,isneg); + } + } + else { //no quantization + // V=man; + if (sh_amt < _AP_W) { + V = man; + V <<= sh_amt; + } + } + //handle overflow/underflow + if ((_AP_O != AP_WRAP || _AP_N != 0) && + ((!_AP_S && _AP_S2) || _AP_I-_AP_S < + _AP_I2-_AP_S2+(QUAN_INC|| (_AP_S2 && + _AP_O==AP_SAT_SYM)) )) {// saturation + bool deleted_zeros = _AP_S2?true:!carry, + deleted_ones = true; + bool neg_src; + const bool lD=(_AP_I2>_AP_I) && (_AP_W2-_AP_I2+_AP_I>=0) && (man & (1ULL <<(DOUBLE_MAN+2-_AP_I2+_AP_I))); + int pos1=F2+_AP_W-_AP_F; + if (pos1 < _AP_W2) { + int pos2=pos1+1; + bool Range1_all_ones=true; + bool Range1_all_zeros=true; + if (pos1>=0) { + ap_private<_AP_W,_AP_S> Range1= + ap_private<_AP_W,_AP_S>((man >> pos1) | ((1ULL<<(DOUBLE_MAN+1)&man) ? (DOUBLE_MAN_MASK >> (DOUBLE_MAN+2-pos1) <<(DOUBLE_MAN+2-pos1)):0)); + Range1_all_ones = Range1.isAllOnesValue(); // Range1.isAllOnesValue(); + Range1_all_zeros = Range1.isMinValue(); // Range1.isMinValue(); + } else { + Range1_all_ones=false; + Range1_all_zeros = man==0; // man.isMinValue(); + } + bool Range2_all_ones=true; + if (pos2<_AP_W2 && pos2>=0) { + ap_private<_AP_W, _AP_S> Range2= + ap_private<_AP_W, _AP_S>((man >> pos2) | ((1ULL<<(DOUBLE_MAN+1)&man) ? (DOUBLE_MAN_MASK >> (DOUBLE_MAN+2-pos2) <<(DOUBLE_MAN+2-pos2)):0)); + Range2_all_ones=Range2.isAllOnesValue(); // Range2.isAllOnesValue(); + } else if (pos2<0) + Range2_all_ones=false; + deleted_zeros=deleted_zeros && (carry?Range1_all_ones:Range1_all_zeros); + deleted_ones=carry?Range2_all_ones&&(F2-_AP_F+_AP_W<0||!lD) : Range1_all_ones; + neg_src=isneg&&!(carry&Range1_all_ones); + } else + neg_src = isneg && V[_AP_W -1]; + + const bool neg_trg=V.isNegative(); + const bool overflow=(neg_trg||!deleted_zeros) && !isneg; + bool underflow=(!neg_trg||!deleted_ones)&&neg_src; + //printf("neg_src = %d, neg_trg = %d, deleted_zeros = %d, + // deleted_ones = %d, overflow = %d, underflow = %d\n", + // neg_src, neg_trg, deleted_zeros, deleted_ones, + // overflow, underflow); + if (_AP_O==AP_SAT_SYM && _AP_S2 && _AP_S) + underflow |= neg_src && (_AP_W>1?V.isMinSignedValue():true); + overflow_adjust(underflow,overflow,lD, neg_src); + } + } + report(); + } + + + ///assign operators + //------------------------------------------------------------------------- + + INLINE volatile ap_fixed_base& operator=(const ap_fixed_base<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& op) volatile { + V = op.V; + return *this; + } + + INLINE ap_fixed_base& operator=(const ap_fixed_base<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& op) { + V = op.V; + return *this; + } + + INLINE volatile ap_fixed_base& operator=(const volatile ap_fixed_base<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& op) volatile { + V = op.V; + return *this; + } + + INLINE ap_fixed_base& operator=(const volatile ap_fixed_base<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& op) { + V = op.V; + return *this; + } + + // Set this ap_fixed_base with a bits string. That means the ssdm_int::V + // inside this ap_fixed_base is assigned by bv. + // Note the input parameter should be a fixed-point formatted bit string. + INLINE ap_fixed_base& setBits(unsigned long long bv) { + V=bv; + return *this; + } + + // Return a ap_fixed_base object whose ssdm_int::V is assigned by bv. + // Note the input parameter should be a fixed-point formatted bit string. + static INLINE ap_fixed_base bitsToFixed(unsigned long long bv) { + ap_fixed_base Tmp=bv; + return Tmp; + } + + // Explicit conversion functions to ap_private that captures + // all integer bits (bits are truncated) + INLINE ap_private + to_ap_private(bool Cnative = true) const { + ap_private ret = ap_private ((_AP_I >= 1) ? (_AP_S==true ? V.ashr(AP_MAX(0,_AP_W - _AP_I)) : V.lshr(AP_MAX(0,_AP_W - _AP_I))) : ap_private<_AP_W, _AP_S>(0)); + + if (Cnative) { + bool r = false; + if (_AP_I < _AP_W) { + if (_AP_I > 0) r = !(V.getLoBits(_AP_W - _AP_I).isMinValue()); + else r = !(V.isMinValue()); + } + if (r && V.isNegative()) { // if this is negative integer + ++ret;//ap_private(1,_AP_S); + } + } else { + //Follow OSCI library, conversion from sc_fixed to sc_int + } + return ret; + } + + template + INLINE operator ap_private<_AP_W2,_AP_S2> () const { + return (ap_private<_AP_W2,_AP_S2>)to_ap_private(); + } + + template + INLINE operator ap_private<_AP_W2,_AP_S2,_AP_N2> () const { + return (ap_private<_AP_W2,_AP_S2,_AP_N2>)to_ap_private(); + } + + //Explict conversion function to C built-in integral type + INLINE int to_int() const { + return to_ap_private().to_int(); + } + + INLINE int to_uint() const { + return to_ap_private().to_uint(); + } + + INLINE ap_slong to_int64() const { + return to_ap_private().to_int64(); + } + + INLINE ap_ulong to_uint64() const { + return to_ap_private().to_uint64(); + } + + INLINE double to_double() const { + if (!V) + return 0; + if (_AP_W>64 || (_AP_W - _AP_I) > 0) { + bool isneg = _AP_S && V[_AP_W-1]; + uint64_t res = isneg ? 0x8000000000000000ULL : 0; + ap_private<_AP_W, false> tmp = V; + if (isneg) tmp = -tmp; + int i = _AP_W -1 - tmp.countLeadingZeros(); + int exp = _AP_I-(_AP_W-i); + res|=((uint64_t)(exp+DOUBLE_BIAS))<DOUBLE_MAN)?tmp.lshr(i-DOUBLE_MAN):tmp).to_uint64() & DOUBLE_MAN_MASK; + res |= i 0) { + /* This specialization is disabled. It is giving wrong results in some cases. + bool isneg=V.isNegative(); + double dp = V.get(); + dp /= (1<< (_AP_W - _AP_I)); + return dp;*/ + } else + return double(to_int64()); + } + + INLINE float to_float() const { + uint32_t res=0; + if (V==0) + return 0; + bool isneg=V.isNegative(); + ap_private<_AP_W, _AP_S> tmp=V; + if (isneg) tmp = -tmp; + if (_AP_W-_AP_I>0||_AP_W>64) { + if (isneg) + res=0x80000000; + int i=_AP_W-1; + i-=tmp.countLeadingZeros(); + int exp=_AP_I-(_AP_W-i); + res|=(exp+FLOAT_BIAS)< man = 0; + if (i!=0) { + tmp.clear(i); + if (i>FLOAT_MAN) + man=tmp.lshr(i-FLOAT_MAN); + else + man=tmp; + res |= i < FLOAT_MAN?man.getZExtValue()<<(FLOAT_MAN-i):man.getZExtValue(); + } + } else { + return float(to_int64()); + } + float dp=rawBitsToFloat(res); + return dp; + } + + INLINE operator double () const { + return to_double(); + } +#ifndef __SC_COMPATIBLE__ + INLINE operator float () const { + return to_float(); + } + + INLINE operator char () const { + return (char) to_int(); + } + + INLINE operator unsigned char () const { + return (unsigned char) to_uint(); + } + + INLINE operator short () const { + return (short) to_int(); + } + + INLINE operator unsigned short () const { + return (unsigned short) to_uint(); + } + + INLINE operator int () const { + return to_int(); + } + + INLINE operator unsigned int () const { + return to_uint(); + } +#if 1 +#ifdef __x86_64__ + INLINE operator long () const { + return (long)to_int64(); + } + + INLINE operator unsigned long () const { + return (unsigned long) to_uint64(); + } +#else + INLINE operator long () const { + return to_int64(); + } + + INLINE operator unsigned long () const { + return to_uint64(); + } + +#endif +#endif + INLINE operator unsigned long long () const { + return to_uint64(); + } + + INLINE operator long long () const { + return to_int64(); + } +#endif + + INLINE std::string to_string(uint8_t radix=2, bool sign=false) const; + + INLINE ap_slong bits_to_int64() const { + ap_private res(V); + return (ap_slong) res; + } + + INLINE ap_ulong bits_to_uint64() const { + ap_private res(V); + return (ap_ulong) res; + } + + INLINE int length() const {return _AP_W;} + + // Count the number of zeros from the most significant bit + // to the first one bit. Note this is only for ap_fixed_base whose + // _AP_W <= 64, otherwise will incur assertion. + INLINE int countLeadingZeros() { + return V.countLeadingZeros(); + } + + ///Arithmetic:Binary + //------------------------------------------------------------------------- + template + INLINE typename RType<_AP_W2,_AP_I2,_AP_S2>::mult + operator * (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + typename RType<_AP_W2,_AP_I2,_AP_S2>::mult r; + r.V = V * op2.V; + return r; + } + + template + static INLINE ap_fixed_base multiply(const ap_fixed_base<_AP_W1,_AP_I1,_AP_S1>& op1, const + ap_fixed_base<_AP_W2,_AP_I2,_AP_S2>& op2) { + ap_private<_AP_W+_AP_W2, _AP_S> OP1=op1.V; + ap_private<_AP_W2,_AP_S2> OP2=op2.V; + return OP1*OP2; + } + + template + INLINE typename RType<_AP_W2,_AP_I2,_AP_S2>::div + operator / (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + enum {F2 = _AP_W2-_AP_I2, _W1=AP_MAX(_AP_W + AP_MAX(F2, 0), _AP_W2), + _W2=AP_MAX(_AP_W2,AP_MAX(_AP_W + AP_MAX(F2, 0), _AP_W2))}; + ap_private<_W1, _AP_S> dividend = (ap_private<_W1, _AP_S>(V)) << ((_W1>_AP_W)?F2:0); + ap_private<_W1, _AP_S2> divisior = ap_private<_W2, _AP_S2>(op2.V); + ap_private<_W1, _AP_S> ret = ap_private<_W1,_AP_S> ((_AP_S||_AP_S2) ? dividend.sdiv(divisior): dividend.udiv(divisior)); + typename RType<_AP_W2, _AP_I2, _AP_S2>::div r; + r.V = ret; + return r; + } +#define OP_BIN_AF(Sym, Rty, Width, Sign, Fun) \ + template \ + INLINE typename RType<_AP_W2,_AP_I2,_AP_S2>::Rty \ + operator Sym (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const \ + { \ + enum {_AP_F=_AP_W-_AP_I, F2=_AP_W2-_AP_I2}; \ + typename RType<_AP_W2,_AP_I2,_AP_S2>::Rty r, lhs(*this), rhs(op2); \ + r.V = lhs.V.Fun(rhs.V); \ + return r; \ + } \ + INLINE typename RType<_AP_W,_AP_I,_AP_S>::Rty \ + operator Sym (const ap_fixed_base& op2) const \ + { \ + typename RType<_AP_W,_AP_I,_AP_S>::Rty r; \ + r.V = V Sym op2.V; \ + return r; \ + } \ + + OP_BIN_AF(+, plus, plus_w, plus_s, Add) + OP_BIN_AF(-, minus, minus_w, minus_s, Sub) + +#define OP_LOGIC_BIN_AF(Sym, Rty, Width, Sign) \ + template \ + INLINE typename RType<_AP_W2,_AP_I2,_AP_S2>::Rty \ + operator Sym (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const \ + { \ + typename RType<_AP_W2,_AP_I2,_AP_S2>::Rty r, lhs(*this), rhs(op2); \ + r.V=lhs.V Sym rhs.V; \ + return r; \ + } \ + INLINE typename RType<_AP_W,_AP_I,_AP_S>::Rty \ + operator Sym (const ap_fixed_base& op2) const \ + { \ + typename RType<_AP_W,_AP_I,_AP_S>::Rty r; \ + r.V = V Sym op2.V; \ + return r; \ + } \ + INLINE typename RType<_AP_W,_AP_I,_AP_S>::Rty operator Sym(int op2) const \ + { \ + return V Sym (op2<<(_AP_W - _AP_I)); \ + } + OP_LOGIC_BIN_AF(&, logic, logic_w, logic_s) + OP_LOGIC_BIN_AF(|, logic, logic_w, logic_s) + OP_LOGIC_BIN_AF(^, logic, logic_w, logic_s) + + ///Arithmic : assign + //------------------------------------------------------------------------- +#define OP_ASSIGN_AF(Sym) \ + template \ + INLINE ap_fixed_base& operator Sym##= (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) \ + { \ + *this=operator Sym (op2) ; \ + return *this; \ + } + + OP_ASSIGN_AF(+) + OP_ASSIGN_AF(-) + OP_ASSIGN_AF(&) + OP_ASSIGN_AF(|) + OP_ASSIGN_AF(^) + OP_ASSIGN_AF(*) + OP_ASSIGN_AF(/) + + ///Prefix increment, decrement + //------------------------------------------------------------------------- + INLINE ap_fixed_base& operator ++() { + operator+=(ap_fixed_base<1,1,false>(1)); //SystemC's semantics + return *this; + } + + INLINE ap_fixed_base& operator --() { + operator-=(ap_fixed_base<1,1,false>(1)); //SystemC's semantics + return *this; + } + + //Postfix increment, decrement + //------------------------------------------------------------------------- + INLINE const ap_fixed_base operator ++(int) { + ap_fixed_base t(*this); + operator++(); + return t; + } + + INLINE const ap_fixed_base operator --(int) { + ap_fixed_base t = *this; + operator--(); + return t; + } + + ///Unary arithmetic + //------------------------------------------------------------------------- + INLINE ap_fixed_base operator +() {return *this;} + + INLINE ap_fixed_base<_AP_W + 1, _AP_I + 1, true> operator -() const { + ap_fixed_base<_AP_W + 1, _AP_I + 1, true> Tmp(*this); + Tmp.V = - Tmp.V; + return Tmp; + } + + INLINE ap_fixed_base<_AP_W,_AP_I,true,_AP_Q,_AP_O, _AP_N> getNeg() { + ap_fixed_base<_AP_W,_AP_I,true,_AP_Q,_AP_O, _AP_N> Tmp(*this); + Tmp.V=-Tmp.V; + return Tmp; + } + + ///Not (!) + //------------------------------------------------------------------------- + INLINE bool operator !() const { + return !V; + } + + ///Bitwise complement + //------------------------------------------------------------------------- + INLINE ap_fixed_base<_AP_W, _AP_I, _AP_S> + operator ~() const { + ap_fixed_base<_AP_W, _AP_I, _AP_S> res(*this); + res.V.flip(); + return res; + } + + ///Shift + ///template argument as shift value + template + INLINE ap_fixed_base<_AP_W, _AP_I + _AP_SHIFT, _AP_S> lshift () const { + ap_fixed_base<_AP_W, _AP_I + _AP_SHIFT, _AP_S> r; + r.V = V; + return r; + } + + template + INLINE ap_fixed_base<_AP_W, _AP_I - _AP_SHIFT, _AP_S> rshift () const { + ap_fixed_base<_AP_W, _AP_I - _AP_SHIFT, _AP_S> r; + r.V = V; + return r; + } + + //Because the return type is the type of the the first operand, shift assign + //operators do not carry out any quantization or overflow + //While systemc, shift assigns for sc_fixed/sc_ufixed will result in + //quantization or overflow (depending on the mode of the first operand) + //------------------------------------------------------------------------- + INLINE ap_fixed_base operator << (int sh) const { + ap_fixed_base r; + bool isNeg=(sh&0x80000000) != 0; + sh=isNeg?-sh:sh; + bool shiftoverflow = sh >= _AP_W; + bool NegSrc = V.isNegative(); + if (isNeg) { + if (shiftoverflow) + NegSrc?r.V.set():r.V.clear(); + else + r.V=_AP_S?V.ashr(sh):V.lshr(sh); + } else { + if (shiftoverflow) + r.V.clear(); + else + r.V=V< 1 && sh <= _AP_W) + rb = (V << (_AP_W - sh + 1 )) != 0; + else if (sh > _AP_W) + rb = V != 0; + r.quantization_adjust(qb, rb, NegSrc); + } else if (isNeg == false && _AP_O != AP_WRAP) { + bool allones, allzeros; + if (sh < _AP_W ) { + ap_private<_AP_W, _AP_S > range1 = V.lshr(_AP_W - sh - 1); + allones = range1.isAllOnesValue(); + allzeros = range1.isMinValue(); + } else { + allones = false; + allzeros = V.isMinValue(); + } + bool overflow = !allzeros && !NegSrc; + bool underflow = !allones && NegSrc; + if (_AP_O == AP_SAT_SYM && _AP_S) + underflow |= NegSrc && (_AP_W > 1 ? r.V.isMinSignedValue():true); + bool lD = false; + if ( sh < _AP_W ) lD = V[_AP_W - sh - 1]; + r.overflow_adjust(underflow, overflow, lD, NegSrc); + } +#endif + return r; + } + + template + INLINE ap_fixed_base operator<<(const ap_private<_AP_W2,true>& op2) const { + int sh = op2.to_int(); + return operator << (sh); + } + + INLINE ap_fixed_base operator << (unsigned int sh ) const { + ap_fixed_base r; + bool shiftoverflow = sh >= _AP_W; + r.V = shiftoverflow ? ap_private<_AP_W, _AP_S >(0) : V << sh; + if (sh == 0) return r; +#ifdef __SC_COMPATIBLE__ + bool NegSrc = V.isNegative(); + if (_AP_O != AP_WRAP) { + bool allones, allzeros; + if (sh < _AP_W ) { + ap_private<_AP_W, _AP_S > range1 = V.lshr(_AP_W - sh -1); + allones = range1.isAllOnesValue(); + allzeros = range1.isMinValue(); + } else { + allones = false; + allzeros = V.isMinValue(); + } + bool overflow = !allzeros && !NegSrc; + bool underflow = !allones && NegSrc; + if (_AP_O == AP_SAT_SYM && _AP_S) + underflow |= NegSrc && (_AP_W > 1 ? r.V.isMinSignedValue():true); + bool lD = false; + if ( sh < _AP_W ) lD = V[_AP_W - sh - 1]; + r.overflow_adjust(underflow, overflow, lD, NegSrc); + } +#endif + return r; + } + + template + INLINE ap_fixed_base operator << (const ap_private<_AP_W2,false>& op2) const { + unsigned int sh = op2.to_uint(); + return operator << (sh); + } + + INLINE ap_fixed_base operator >> (int sh) const { + ap_fixed_base r; + bool isNeg=(sh&0x80000000) != 0; + bool NegSrc = V.isNegative(); + sh=isNeg?-sh:sh; + bool shiftoverflow = sh >= _AP_W; + if (isNeg && !shiftoverflow) r.V=V< 1 && sh <= _AP_W) + rb = (V << (_AP_W - sh + 1 )) != 0; + else if (sh > _AP_W) + rb = V != 0; + r.quantization_adjust(qb, rb, NegSrc); + } else if (isNeg == true && _AP_O != AP_WRAP) { + bool allones, allzeros; + if (sh < _AP_W ) { + ap_private<_AP_W, _AP_S > range1 = V.lshr(_AP_W - sh - 1); + allones = range1.isAllOnesValue(); + allzeros = range1.isMinValue(); + } else { + allones = false; + allzeros = V.isMinValue(); + } + bool overflow = !allzeros && !NegSrc; + bool underflow = !allones && NegSrc; + if (_AP_O == AP_SAT_SYM && _AP_S) + underflow |= NegSrc && (_AP_W > 1 ? r.V.isMinSignedValue():true); + bool lD = false; + if ( sh < _AP_W ) lD = V[_AP_W - sh - 1]; + r.overflow_adjust(underflow, overflow, lD, NegSrc); + } +#endif + return r; + } + + template + INLINE ap_fixed_base operator >> (const ap_private<_AP_W2,true>& op2) const { + int sh = op2.to_int(); + return operator >> (sh); + } + + INLINE ap_fixed_base operator >> (unsigned int sh) const { + ap_fixed_base r; + bool NegSrc = V.isNegative(); + bool shiftoverflow = sh >= _AP_W; + if (shiftoverflow) + NegSrc?r.V.set():r.V.clear(); + else + r.V=_AP_S?V.ashr(sh):V.lshr(sh); +#ifdef __SC_COMPATIBLE__ + if (sh == 0) return r; + if (_AP_Q != AP_TRN) { + bool qb = false; + if (sh <= _AP_W) qb = V[sh - 1]; + bool rb = false; + if (sh > 1 && sh <= _AP_W) + rb = (V << (_AP_W - sh + 1 )) != 0; + else if (sh > _AP_W) + rb = V != 0; + r.quantization_adjust(qb, rb, NegSrc); + } +#endif + return r; + } + + template + INLINE ap_fixed_base operator >> (const ap_private<_AP_W2,false>& op2) const { + unsigned int sh = op2.to_uint(); + return operator >> (sh); + } + + ///shift assign + //------------------------------------------------------------------------- +#define OP_AP_SHIFT_AP_ASSIGN_AF(Sym) \ + template \ + INLINE ap_fixed_base& operator Sym##=(const ap_private<_AP_W2,_AP_S2>& op2) \ + { \ + *this=operator Sym (op2); \ + return *this; \ + } + + OP_AP_SHIFT_AP_ASSIGN_AF(<<) + OP_AP_SHIFT_AP_ASSIGN_AF(>>) + + ///Support shift(ap_fixed_base) +#define OP_AP_SHIFT_AF(Sym) \ + template \ + INLINE ap_fixed_base operator Sym (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const \ + { \ + return operator Sym (op2.to_ap_private()); \ + } \ + template \ + INLINE ap_fixed_base& operator Sym##= (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) \ + { \ + *this=operator Sym (op2); \ + return *this; \ + } + + OP_AP_SHIFT_AF(<<) + OP_AP_SHIFT_AF(>>) + + INLINE ap_fixed_base& operator >>= (unsigned int sh) { + *this = operator >> (sh); + return *this; + } + + INLINE ap_fixed_base& operator <<= (unsigned int sh) { + *this = operator << (sh); + return *this; + } + + INLINE ap_fixed_base& operator >>= (int sh) { + *this = operator >> (sh); + return *this; + } + + INLINE ap_fixed_base& operator <<= (int sh) { + *this = operator << (sh); + return *this; + } + + ///Comparisons + //------------------------------------------------------------------------- + template + INLINE bool operator == (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + enum {_AP_F=_AP_W-_AP_I,F2=_AP_W2-_AP_I2, shAmt1 = AP_MAX(F2-_AP_F, 0), shAmt2 = AP_MAX(_AP_F-F2,0), _AP_W3 = (_AP_F==F2) ? AP_MAX(_AP_W,_AP_W2) : AP_MAX(_AP_W+shAmt1, _AP_W2+shAmt2)}; + ap_private<_AP_W3, _AP_S > OP1= ap_private<_AP_W3, _AP_S >(V)< OP2=ap_private<_AP_W3,_AP_S2 >(op2.V)< + INLINE bool operator != (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + return !(*this==op2); + } + + template + INLINE bool operator > (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + enum {_AP_F=_AP_W-_AP_I,F2=_AP_W2-_AP_I2, shAmt1 = AP_MAX(F2-_AP_F, 0), shAmt2 = AP_MAX(_AP_F-F2,0), _AP_W3 = (_AP_F==F2) ? AP_MAX(_AP_W,_AP_W2) : AP_MAX(_AP_W+shAmt1, _AP_W2+shAmt2)}; + ap_private<_AP_W3, _AP_S > OP1= ap_private<_AP_W3, _AP_S >(V)< OP2=ap_private<_AP_W3,_AP_S2 >(op2.V)< + INLINE bool operator <= (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + return !(*this>op2); + } + + template + INLINE bool operator < (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + enum {_AP_F=_AP_W-_AP_I,F2=_AP_W2-_AP_I2, shAmt1 = AP_MAX(F2-_AP_F, 0), shAmt2 = AP_MAX(_AP_F-F2,0), _AP_W3 = (_AP_F==F2) ? AP_MAX(_AP_W,_AP_W2) : AP_MAX(_AP_W+shAmt1, _AP_W2+shAmt2)}; + ap_private<_AP_W3, _AP_S > OP1= ap_private<_AP_W3, _AP_S >(V)< OP2=ap_private<_AP_W3,_AP_S2 >(op2.V)< + INLINE bool operator >= (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + return !(*this) + DOUBLE_CMP_AF(>=) + DOUBLE_CMP_AF(<) + DOUBLE_CMP_AF(<=) + + // Bit and Slice Select + INLINE af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N> operator [] (unsigned int index) { + assert(index<_AP_W&&"Attemping to read bit beyond MSB"); + return af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>(this, index); + } + + INLINE af_bit_ref<_AP_W, _AP_I,_AP_S,_AP_Q,_AP_O, _AP_N> bit(unsigned int index) { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>(this, index); + } + + template + INLINE af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N> bit (const ap_private<_AP_W2,_AP_S2>& index) { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>(this, index.to_int()); + } + + INLINE bool bit (unsigned int index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return V[index]; + } + + INLINE bool operator [] (unsigned int index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return V[index]; + } + + template + INLINE bool bit (const ap_private<_AP_W2, _AP_S2>& index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return V[index.to_uint()]; + } + + template + INLINE bool operator [] (const ap_private<_AP_W2, _AP_S2>& index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return V[index.to_uint()]; + } + + INLINE af_bit_ref<_AP_W, _AP_I,_AP_S,_AP_Q,_AP_O, _AP_N> get_bit(int index) { + assert(index < _AP_I && "Attempting to read bit beyond MSB"); + assert(index >= _AP_I - _AP_W&& "Attempting to read bit beyond MSB"); + return af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>(this, index + _AP_W - _AP_I); + } + + template + INLINE af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N> get_bit (const ap_private<_AP_W2, true>& index) { + assert(index >= _AP_I - _AP_W && "Attempting to read bit with negative index"); + assert(index < _AP_I && "Attempting to read bit beyond MSB"); + return af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>(this, index.to_int() + _AP_W - _AP_I); + } + + INLINE bool get_bit (int index) const { + assert(index >= _AP_I - _AP_W && "Attempting to read bit with negative index"); + assert(index < _AP_I && "Attempting to read bit beyond MSB"); + return V[index + _AP_W - _AP_I]; + } + + template + INLINE bool get_bit (const ap_private<_AP_W2, true>& index) const { + assert(index >= _AP_I - _AP_W && "Attempting to read bit with negative index"); + assert(index < _AP_I && "Attempting to read bit beyond MSB"); + return V[index.to_int() + _AP_W - _AP_I]; + } + + INLINE af_range_ref<_AP_W,_AP_I,_AP_S, _AP_Q, _AP_O, _AP_N> + range(int Hi, int Lo) { + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>(this, Hi, Lo); + } + + INLINE af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> + operator () (int Hi, int Lo) { + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>(this, Hi, Lo); + } + + INLINE af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> + range(int Hi, int Lo) const { + assert((Hi < _AP_W) && (Lo < _AP_W) &&"Out of bounds in range()"); + return af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>(const_cast(this), Hi, Lo); + } + + INLINE af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> + operator () (int Hi, int Lo) const { + return this->range(Hi, Lo); + } + + template + INLINE af_range_ref<_AP_W,_AP_I,_AP_S, _AP_Q, _AP_O, _AP_N> + range(const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>(this, Hi, Lo); + } + + template + INLINE af_range_ref<_AP_W,_AP_I,_AP_S, _AP_Q, _AP_O, _AP_N> + operator () (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>(this, Hi, Lo); + } + + template + INLINE af_range_ref<_AP_W,_AP_I,_AP_S, _AP_Q, _AP_O, _AP_N> + range(const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) const { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>(const_cast< + ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>*>(this), + Hi, Lo); + } + + template + INLINE af_range_ref<_AP_W,_AP_I,_AP_S, _AP_Q, _AP_O, _AP_N> + operator () (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) const { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + return this->range(Hi, Lo); + } + + INLINE af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> + range() { + return this->range(_AP_W - 1, 0); + } + + INLINE af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> + range() const { + return this->range(_AP_W - 1, 0); + } + + INLINE bool is_zero () const { + return V.isMinValue(); + } + + INLINE bool is_neg () const { + if (V.isNegative()) + return true; + return false; + } + + INLINE int wl () const { + return _AP_W; + } + + INLINE int iwl () const { + return _AP_I; + } + + INLINE ap_q_mode q_mode () const { + return _AP_Q; + } + + INLINE ap_o_mode o_mode () const { + return _AP_O; + } + + INLINE int n_bits () const { + return 0; + } + + //private: +public: + ap_private<_AP_W, _AP_S> V; +}; + +template +std::string ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>::to_string( + uint8_t radix, bool sign) const { + std::string str; + str.clear(); + char step; + std::string prefix; + switch (radix) { + case 2 : prefix = "0b"; step = 1; break; + case 8 : prefix = "0o"; step = 3; break; + case 16 : prefix = "0x"; step = 4; break; + default : break; + } + if (_AP_W <= _AP_I) + str = this->to_ap_private().to_string(radix, + radix == 10 ? _AP_S : sign); + else { + if (radix == 10) { + bool isNeg = _AP_S && V.isNegative(); + if (_AP_I > 0) { + ap_private int_part(0); + int_part = this->to_ap_private(); + str += int_part.to_string(radix, false); + } else { + if (isNeg) str += '-'; + } + ap_fixed_base<_AP_W, _AP_I, _AP_S> tmp(*this); + if (isNeg && _AP_I <= 0) tmp = -tmp; + ap_fixed_base<_AP_W - AP_MIN(_AP_I, 0), 0, false> frac_part = tmp; + if (frac_part == 0) return str; + str += "."; + while (frac_part != 0) { + char digit = (frac_part * radix).to_ap_private(); + str += static_cast(digit + '0'); + frac_part *= radix; + } + } else { + if (_AP_I > 0) { + for (signed i = _AP_W - _AP_I; i < _AP_W; i += step) { + + char digit = (char)(this->range(AP_MIN(i + step - 1, _AP_W - 1), i)); + str = (digit < 10 ? static_cast(digit + '0') : + static_cast(digit - 10 + 'a')) + str; + } + } + str += '.'; + ap_fixed_base tmp(*this); + for (signed i = _AP_W - _AP_I - 1; i >= 0; i -= step) { + char digit = (char)(tmp.range(i, AP_MAX(0, i - step + 1))); + str += digit < 10 ? static_cast(digit + '0') : + static_cast(digit - 10 + 'a'); + } + } + } + str = prefix + str; + return str; +} + +template +INLINE void b_not(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op) { + ret.V = op.V; + ret.V.flip(); +} + +template +INLINE void b_and(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op1, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op2) { + ret.V = op1.V & op2.V; +} + +template +INLINE void b_or(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op1, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op2) { + ret.V = op1.V | op2.V; +} + +template +INLINE void b_xor(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op1, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op2) { + ret.V = op1.V ^ op2.V; +} + +template +INLINE void neg(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) { + ap_fixed_base<_AP_W2+!_AP_S2, _AP_I2+!_AP_S2, true, _AP_Q2, _AP_O2, _AP_N2> Tmp; + Tmp.V = - op.V; + ret = Tmp; +} + +template +INLINE void neg(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op) { + ret.V = -op.V; +} + +template +INLINE void lshift(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op, + int i) { + ap_fixed_base<_AP_W2 - _AP_I2 + AP_MAX(_AP_I, _AP_I2), AP_MAX(_AP_I, _AP_I2), _AP_S2, _AP_Q2, _AP_O2, _AP_N2> Tmp; + Tmp = op; + Tmp.V <<= i; + ret = Tmp; +} + +template +INLINE void lshift(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op, + int i) { + ret.V = op.V << i; +} + +template +INLINE void rshift(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op, + int i) { + ap_fixed_base<_AP_I2 + AP_MAX(_AP_W - _AP_I, _AP_W2 - _AP_I2), _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> Tmp; + Tmp = op; + Tmp.V = _AP_S2 ? Tmp.V.ashr(i): Tmp.V.lshr(i); + ret = Tmp; +} + +template +INLINE void rshift(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op, + int i) { + ret.V = _AP_S ? op.V.ashr(i): op.V.lshr(i); +} + +#define AF_CTOR_SPEC_BASE(_AP_W,_AP_S,C_TYPE) \ + template<> INLINE ap_fixed_base<_AP_W,_AP_W,_AP_S,AP_TRN,AP_WRAP>::ap_fixed_base(C_TYPE i_op):V(i_op) \ + { \ + } + +#define AF_CTOR_SPEC(__W,C_TYPE) \ + AF_CTOR_SPEC_BASE(__W,true,C_TYPE) \ + AF_CTOR_SPEC_BASE(__W,false,C_TYPE) + +AF_CTOR_SPEC(1,bool) +AF_CTOR_SPEC(8, signed char) +AF_CTOR_SPEC(8, unsigned char) +AF_CTOR_SPEC(16, signed short) +AF_CTOR_SPEC(16, unsigned short) +AF_CTOR_SPEC(32, signed int) +AF_CTOR_SPEC(32, unsigned int) +AF_CTOR_SPEC(64, ap_slong) +AF_CTOR_SPEC(64, ap_ulong) + +///Output streaming +//----------------------------------------------------------------------------- +template +INLINE std::ostream& +operator <<(std::ostream& os, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& x) { + os << x.to_double(); + return os; +} + +///Input streaming +//----------------------------------------------------------------------------- +template +INLINE std::istream& +operator >> (std::istream& os, ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& x) { + double d; + os >> d; + x = ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>(x); + return os; +} + +template +INLINE void print(const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& x) { + ap_private<_AP_W,_AP_S> data=x.V; + if (_AP_I>0) { + const ap_private<_AP_I,_AP_S> p1=data>>(_AP_W-_AP_I); + print(p1); + + } else + printf("0"); + printf("."); + if (_AP_I<_AP_W) { + const ap_private<_AP_W-_AP_I,false> p2=data; + print(p2,false); + } +} + +///Operators mixing Integers with ap_fixed_base +//----------------------------------------------------------------------------- +#if 1 +#define AF_BIN_OP_WITH_INT_SF(BIN_OP,C_TYPE,_AP_W2,_AP_S2,RTYPE) \ + template \ + INLINE typename ap_fixed_base<_AP_W,_AP_I,_AP_S>::template RType<_AP_W2,_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP (const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) \ + { \ + return op.operator BIN_OP(ap_private<_AP_W2,_AP_S2>(i_op)); \ + } +#define AF_BIN_OP_WITH_INT(BIN_OP, C_TYPE, _AP_W2,_AP_S2,RTYPE) \ + template \ + INLINE typename ap_fixed_base<_AP_W,_AP_I,_AP_S>::template RType<_AP_W2,_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP (const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) \ + { \ + return op.operator BIN_OP (ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op)); \ + } \ + \ + template \ + INLINE typename ap_fixed_base<_AP_W,_AP_I,_AP_S>::template RType<_AP_W2,_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP (C_TYPE i_op, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op) \ + { \ + return ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op).operator BIN_OP (op); \ + } + +#else +#define AF_BIN_OP_WITH_INT_SF(BIN_OP,C_TYPE,_AP_W2,_AP_S2,RTYPE) \ + template \ + INLINE typename ap_fixed_base<_AP_W,_AP_I,_AP_S>::template RType<_AP_W2,_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP (const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) \ + { \ + return op BIN_OP (i_op); \ + } +#define AF_BIN_OP_WITH_INT(BIN_OP, C_TYPE, _AP_W2,_AP_S2,RTYPE) \ + template \ + INLINE typename ap_fixed_base<_AP_W,_AP_I,_AP_S>::template RType<_AP_W2,_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP (const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) \ + { \ + return op.V BIN_OP (i_op<<(_AP_W-_AP_I)); \ + } \ + \ + \ + template \ + INLINE typename ap_fixed_base<_AP_W,_AP_I,_AP_S>::template RType<_AP_W2,_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP (C_TYPE i_op, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op) \ + { \ + return ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op).operator BIN_OP (op); \ + } + +#endif +#if 1 +#define AF_REL_OP_WITH_INT(REL_OP, C_TYPE, _AP_W2,_AP_S2) \ + template \ + INLINE bool operator REL_OP (const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) \ + { \ + return op.operator REL_OP (ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op)); \ + } \ + \ + \ + template \ + INLINE bool operator REL_OP (C_TYPE i_op, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op) \ + { \ + return ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op).operator REL_OP (op); \ + } +#else +#define AF_REL_OP_WITH_INT(REL_OP, C_TYPE, _AP_W2,_AP_S2) \ + template \ + INLINE bool operator REL_OP (const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) \ + { \ + return op.V.operator REL_OP (i_op<<(_AP_W-_AP_I)); \ + } \ + \ + \ + template \ + INLINE bool operator REL_OP (C_TYPE i_op, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op) \ + { \ + return (i_op<<(_AP_W-_AP_I)) REL_OP (op.V.VAL); \ + } +#endif +#if 1 +#define AF_ASSIGN_OP_WITH_INT(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& operator ASSIGN_OP ( ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) { \ + return op.operator ASSIGN_OP (ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op)); \ + } +#define AF_ASSIGN_OP_WITH_INT_SF(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& operator ASSIGN_OP ( ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) { \ + return op.operator ASSIGN_OP (ap_private<_AP_W2,_AP_S2>(i_op)); \ + } +#else +#define AF_ASSIGN_OP_WITH_INT(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& operator ASSIGN_OP ( ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) { \ + return op.V.operator ASSIGN_OP (i_op); \ + } +#define AF_ASSIGN_OP_WITH_INT_SF(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& operator ASSIGN_OP ( ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) { \ + return op.V.operator ASSIGN_OP (i_op); \ + } +#endif + +#define AF_OPS_WITH_INT(C_TYPE, WI, SI) \ + AF_BIN_OP_WITH_INT(+, C_TYPE, WI, SI, plus) \ + AF_BIN_OP_WITH_INT(-, C_TYPE, WI, SI, minus) \ + AF_BIN_OP_WITH_INT(*, C_TYPE, WI, SI, mult) \ + AF_BIN_OP_WITH_INT(/, C_TYPE, WI, SI, div) \ + AF_BIN_OP_WITH_INT_SF(>>, C_TYPE, WI, SI, arg1) \ + AF_BIN_OP_WITH_INT_SF(<<, C_TYPE, WI, SI, arg1) \ + AF_BIN_OP_WITH_INT(&, C_TYPE, WI, SI, logic) \ + AF_BIN_OP_WITH_INT(|, C_TYPE, WI, SI, logic) \ + AF_BIN_OP_WITH_INT(^, C_TYPE, WI, SI, logic) \ + \ + AF_REL_OP_WITH_INT(==, C_TYPE, WI, SI) \ + AF_REL_OP_WITH_INT(!=, C_TYPE, WI, SI) \ + AF_REL_OP_WITH_INT(>, C_TYPE, WI, SI) \ + AF_REL_OP_WITH_INT(>=, C_TYPE, WI, SI) \ + AF_REL_OP_WITH_INT(<, C_TYPE, WI, SI) \ + AF_REL_OP_WITH_INT(<=, C_TYPE, WI, SI) \ + \ + AF_ASSIGN_OP_WITH_INT(+=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT(-=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT(*=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT(/=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT_SF(>>=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT_SF(<<=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT(&=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT(|=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT(^=, C_TYPE, WI, SI) + +AF_OPS_WITH_INT(bool, 1, false) +AF_OPS_WITH_INT(char, 8, true) +AF_OPS_WITH_INT(signed char, 8, true) +AF_OPS_WITH_INT(unsigned char, 8, false) +AF_OPS_WITH_INT(short, 16, true) +AF_OPS_WITH_INT(unsigned short, 16, false) +AF_OPS_WITH_INT(int, 32, true) +AF_OPS_WITH_INT(unsigned int, 32, false) +# if defined __x86_64__ +AF_OPS_WITH_INT(long, 64, true) +AF_OPS_WITH_INT(unsigned long, 64, false) +# else +AF_OPS_WITH_INT(long, 32, true) +AF_OPS_WITH_INT(unsigned long, 32, false) +# endif +AF_OPS_WITH_INT(ap_slong, 64, true) +AF_OPS_WITH_INT(ap_ulong, 64, false) + +#define AF_BIN_OP_WITH_AP_INT(BIN_OP, RTYPE) \ + template \ + INLINE typename ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>::template RType<_AP_W,_AP_I,_AP_S>::RTYPE \ + operator BIN_OP ( const ap_private<_AP_W2,_AP_S2>& i_op, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op) { \ + return ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op).operator BIN_OP (op); \ + } \ + template \ + INLINE typename ap_fixed_base<_AP_W,_AP_I,_AP_S>::template RType<_AP_W2,_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP ( const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, const ap_private<_AP_W2,_AP_S2>& i_op) { \ + return op.operator BIN_OP (ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op)); \ + } + +#define AF_REL_OP_WITH_AP_INT(REL_OP) \ + template \ + INLINE bool operator REL_OP ( const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, const ap_private<_AP_W2,_AP_S2>& i_op) { \ + return op.operator REL_OP ( ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op)); \ + } \ + template \ + INLINE bool operator REL_OP ( const ap_private<_AP_W2,_AP_S2>& i_op, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op) { \ + return ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op).operator REL_OP (op); \ + } + +#define AF_ASSIGN_OP_WITH_AP_INT(ASSIGN_OP) \ + template \ + INLINE ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& operator ASSIGN_OP ( ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, const ap_private<_AP_W2,_AP_S2>& i_op) { \ + return op.operator ASSIGN_OP (ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op)); \ + } \ + template \ + INLINE ap_private<_AP_W2,_AP_S2>& operator ASSIGN_OP ( ap_private<_AP_W2,_AP_S2>& i_op, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op) { \ + return i_op.operator ASSIGN_OP (op.to_ap_private()); \ + } + +AF_BIN_OP_WITH_AP_INT(+, plus) +AF_BIN_OP_WITH_AP_INT(-, minus) +AF_BIN_OP_WITH_AP_INT(*, mult) +AF_BIN_OP_WITH_AP_INT(/, div) +AF_BIN_OP_WITH_AP_INT(&, logic) +AF_BIN_OP_WITH_AP_INT(|, logic) +AF_BIN_OP_WITH_AP_INT(^, logic) + +AF_REL_OP_WITH_AP_INT(==) +AF_REL_OP_WITH_AP_INT(!=) +AF_REL_OP_WITH_AP_INT(>) +AF_REL_OP_WITH_AP_INT(>=) +AF_REL_OP_WITH_AP_INT(<) +AF_REL_OP_WITH_AP_INT(<=) + +AF_ASSIGN_OP_WITH_AP_INT(+=) +AF_ASSIGN_OP_WITH_AP_INT(-=) +AF_ASSIGN_OP_WITH_AP_INT(*=) +AF_ASSIGN_OP_WITH_AP_INT(/=) +AF_ASSIGN_OP_WITH_AP_INT(&=) +AF_ASSIGN_OP_WITH_AP_INT(|=) +AF_ASSIGN_OP_WITH_AP_INT(^=) + +#define AF_REF_REL_OP_MIX_INT(REL_OP, C_TYPE, _AP_W2, _AP_S2) \ +template \ + INLINE bool operator REL_OP ( const af_range_ref<_AP_W,_AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op, C_TYPE op2) { \ + return (ap_private<_AP_W, false>(op)).operator REL_OP (ap_private<_AP_W2,_AP_S2>(op2)); \ + } \ +template \ + INLINE bool operator REL_OP ( C_TYPE op2, const af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op) { \ + return ap_private<_AP_W2,_AP_S2>(op2).operator REL_OP (ap_private<_AP_W, false>(op)); \ + } \ +template \ + INLINE bool operator REL_OP ( const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op, C_TYPE op2) { \ + return (bool(op)) REL_OP op2; \ + } \ +template \ + INLINE bool operator REL_OP ( C_TYPE op2, const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op) { \ + return op2 REL_OP (bool(op)); \ + } + +#define AF_REF_REL_MIX_INT(C_TYPE, _AP_WI, _AP_SI) \ +AF_REF_REL_OP_MIX_INT(>, C_TYPE, _AP_WI, _AP_SI) \ +AF_REF_REL_OP_MIX_INT(<, C_TYPE, _AP_WI, _AP_SI) \ +AF_REF_REL_OP_MIX_INT(>=, C_TYPE, _AP_WI, _AP_SI) \ +AF_REF_REL_OP_MIX_INT(<=, C_TYPE, _AP_WI, _AP_SI) \ +AF_REF_REL_OP_MIX_INT(==, C_TYPE, _AP_WI, _AP_SI) \ +AF_REF_REL_OP_MIX_INT(!=, C_TYPE, _AP_WI, _AP_SI) + +AF_REF_REL_MIX_INT(bool, 1, false) +AF_REF_REL_MIX_INT(char, 8, true) +AF_REF_REL_MIX_INT(signed char, 8, true) +AF_REF_REL_MIX_INT(unsigned char, 8, false) +AF_REF_REL_MIX_INT(short, 16, true) +AF_REF_REL_MIX_INT(unsigned short, 16, false) +AF_REF_REL_MIX_INT(int, 32, true) +AF_REF_REL_MIX_INT(unsigned int, 32, false) +# if defined __x86_64__ +AF_REF_REL_MIX_INT(long, 64, true) +AF_REF_REL_MIX_INT(unsigned long, 64, false) +# else +AF_REF_REL_MIX_INT(long, 32, true) +AF_REF_REL_MIX_INT(unsigned long, 32, false) +# endif +AF_REF_REL_MIX_INT(ap_slong, 64, true) +AF_REF_REL_MIX_INT(ap_ulong, 64, false) + +#define AF_REF_REL_OP_AP_INT(REL_OP) \ +template \ + INLINE bool operator REL_OP ( const af_range_ref<_AP_W,_AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op, const ap_private<_AP_W2, _AP_S> &op2) { \ + return (ap_private<_AP_W, false>(op)).operator REL_OP (op2); \ + } \ +template \ + INLINE bool operator REL_OP (const ap_private<_AP_W2, _AP_S2> &op2, const af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op) { \ + return op2.operator REL_OP (ap_private<_AP_W, false>(op)); \ + } \ +template \ + INLINE bool operator REL_OP ( const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op, const ap_private<_AP_W2, _AP_S2> &op2) { \ + return (ap_private<1, false>(op)).operator REL_OP (op2); \ + } \ +template \ + INLINE bool operator REL_OP ( const ap_private<_AP_W2, _AP_S2> &op2, const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op) { \ + return op2.operator REL_OP (ap_private<1,false>(op)); \ + } + +AF_REF_REL_OP_AP_INT(>) +AF_REF_REL_OP_AP_INT(<) +AF_REF_REL_OP_AP_INT(>=) +AF_REF_REL_OP_AP_INT(<=) +AF_REF_REL_OP_AP_INT(==) +AF_REF_REL_OP_AP_INT(!=) + +// Relational Operators with double +template +INLINE bool operator == ( double op1, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op2) { + return op2.operator == (op1); +} + +template +INLINE bool operator != ( double op1, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op2) { + return op2.operator != (op1); +} + +template +INLINE bool operator > ( double op1, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op2) { + return op2.operator < (op1); +} + +template +INLINE bool operator >= ( double op1, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op2) { + return op2.operator <= (op1); +} + +template +INLINE bool operator < ( double op1, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op2) { + return op2.operator > (op1); +} + +template +INLINE bool operator <= ( double op1, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op2) { + return op2.operator >= (op1); +} + +#endif /* #ifndef __AESL_GCC_AP_FIXED_H__ */ \ No newline at end of file diff --git a/hls_2018/router_03/etc/ap_int_sim.h b/hls_2018/router_03/etc/ap_int_sim.h new file mode 100755 index 0000000..887ccd8 --- /dev/null +++ b/hls_2018/router_03/etc/ap_int_sim.h @@ -0,0 +1,1629 @@ +/* + * Copyright 2012 Xilinx, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __AESL_GCC_AP_INT_H__ +#define __AESL_GCC_AP_INT_H__ + +#ifndef __cplusplus +#error C++ is required to include this header file +#endif /* #ifndef __cplusplus */ + +#undef _AP_DEBUG_ +#include +#include + +// for safety +#if (defined(_AP_N)|| defined(_AP_C)) +#error One or more of the following is defined: _AP_N, _AP_C. Definition conflicts with their usage as template parameters. +#endif /* #if (defined(_AP_N)|| defined(_AP_C)) */ + +// for safety +#if (defined(_AP_W) || defined(_AP_I) || defined(_AP_S) || defined(_AP_Q) || defined(_AP_O) || defined(_AP_W2) || defined(_AP_I2) || defined(_AP_S2) || defined(_AP_Q2) || defined(_AP_O2)) +#error One or more of the following is defined: _AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2. Definition conflicts with their usage as template parameters. +#endif /* #if (defined(_AP_W) || defined(_AP_I) || defined(_AP_S) || defined(_AP_Q) || defined(_AP_O) || defined(_AP_W2) || defined(_AP_I2) || defined(_AP_S2) || defined(_AP_Q2) || defined(_AP_O2)) */ + +//for safety +#if (defined(_AP_W3) || defined(_AP_S3) || defined(_AP_W4) || defined(_AP_S4)) +#error One or more of the following is defined: _AP_W3, _AP_S3, _AP_W4,_AP_S4. Definition conflicts with their usage as template parameters. +#endif /* #if (defined(_AP_W3) || defined(_AP_S3) || defined(_AP_W4) || defined(_AP_S4)) */ + +//for safety +#if (defined(_AP_W1) || defined(_AP_S1) || defined(_AP_I1) || defined(_AP_T) || defined(_AP_T1) || defined(_AP_T2) || defined(_AP_T3) || defined(_AP_T4)) +#error One or more of the following is defined: _AP_W1, _AP_S1, _AP_I1, _AP_T, _AP_T1, _AP_T2, _AP_T3, _AP_T4. Definition conflicts with their usage as template parameters. +#endif /* #if (defined(_AP_W1) || defined(_AP_S1) || defined(_AP_I1) || defined(_AP_T) || defined(_AP_T1) || defined(_AP_T2) || defined(_AP_T3) || defined(_AP_T4)) */ + +#define __AESL_APDT_IN_SCFLOW__ +#ifndef __AESL_APDT_IN_SCFLOW__ + #include "etc/ap_private.h" +#else + #include "../etc/ap_private.h" +#endif /* #ifndef __AESL_APDT_IN_SCFLOW__ */ + +#ifdef _AP_DEBUG_ + #define AP_DEBUG(s) s +#else + #define AP_DEBUG(s) +#endif /* #ifdef _AP_DEBUG_ */ + +#ifndef __SIMULATION__ + #define __SIMULATION__ +#endif /* #ifndef __SIMULATION__ */ + +#if !(defined SYSTEMC_H) && !(defined SYSTEMC_INCLUDED) + #ifndef SC_TRN + #define SC_TRN AP_TRN + #endif /* #ifndef SC_TRN */ + #ifndef SC_RND + #define SC_RND AP_RND + #endif /* #ifndef SC_RND */ + #ifndef SC_TRN_ZERO + #define SC_TRN_ZERO AP_TRN_ZERO + #endif /* #ifndef SC_TRN_ZERO */ + #ifndef SC_RND_ZERO + #define SC_RND_ZERO AP_RND_ZERO + #endif /* #ifndef SC_RND_ZERO */ + #ifndef SC_RND_INF + #define SC_RND_INF AP_RND_INF + #endif /* #ifndef SC_RND_INF */ + #ifndef SC_RND_MIN_INF + #define SC_RND_MIN_INF AP_RND_MIN_INF + #endif /* #ifndef SC_RND_MIN_INF */ + #ifndef SC_RND_CONV + #define SC_RND_CONV AP_RND_CONV + #endif /* #ifndef SC_RND_CONV */ + #ifndef SC_WRAP + #define SC_WRAP AP_WRAP + #endif /* #ifndef SC_WRAP */ + #ifndef SC_SAT + #define SC_SAT AP_SAT + #endif /* #ifndef SC_SAT */ + #ifndef SC_SAT_ZERO + #define SC_SAT_ZERO AP_SAT_ZERO + #endif /* #ifndef SC_SAT_ZERO */ + #ifndef SC_SAT_SYM + #define SC_SAT_SYM AP_SAT_SYM + #endif /* #ifndef SC_SAT_SYM */ + #ifndef SC_WRAP_SM + #define SC_WRAP_SM AP_WRAP_SM + #endif /* #ifndef SC_WRAP_SM */ + #ifndef SC_BIN + #define SC_BIN AP_BIN + #endif /* #ifndef SC_BIN */ + #ifndef SC_OCT + #define SC_OCT AP_OCT + #endif /* #ifndef SC_OCT */ + #ifndef SC_DEC + #define SC_DEC AP_DEC + #endif /* #ifndef SC_DEC */ + #ifndef SC_HEX + #define SC_HEX AP_HEX + #endif /* #ifndef SC_HEX */ +#endif /* #if !(defined SYSTEMC_H) && !(defined SYSTEMC_INCLUDED) */ +#ifndef AP_INT_MAX_W +#define AP_INT_MAX_W 1024 +#endif +#define BIT_WIDTH_UPPER_LIMIT (1 << 15) +#if AP_INT_MAX_W > BIT_WIDTH_UPPER_LIMIT +#error "Bitwidth exceeds 32768 (1 << 15), the maximum allowed value" +#endif +#define MAX_MODE(BITS) ((BITS + 1023) / 1024) + +///Forward declaration +template struct ap_range_ref; +template struct ap_bit_ref; + +template struct ap_fixed_base; +template struct af_range_ref; +template struct af_bit_ref; +template class ap_uint; + +enum { + AP_BIN = 2, + AP_OCT = 8, + AP_DEC = 10, + AP_HEX = 16 +}; + +///Why to use reference? +///Because we will operate the original object indirectly by operating the +///result object directly after concating or part selecting + +///Proxy class which allows concatination to be used as rvalue(for reading) and +//lvalue(for writing) + +/// Concatination reference. +// ---------------------------------------------------------------- +template +struct ap_concat_ref { +#ifdef _MSC_VER + #pragma warning(disable: 4521 4522) +#endif /* #ifdef _MSC_VER */ + enum {_AP_WR=_AP_W1+_AP_W2,}; + _AP_T1& mbv1; + _AP_T2& mbv2; + + INLINE ap_concat_ref(const ap_concat_ref<_AP_W1, _AP_T1, + _AP_W2, _AP_T2>& ref): + mbv1(ref.mbv1), mbv2(ref.mbv2) {} + + INLINE ap_concat_ref(_AP_T1& bv1, _AP_T2& bv2):mbv1(bv1),mbv2(bv2) {} + + template + INLINE ap_concat_ref& operator = (const ap_private<_AP_W3,_AP_S3>& val) { + ap_private<_AP_W1+_AP_W2, false> vval(val); + int W_ref1=mbv1.length(); + int W_ref2=mbv2.length(); + ap_private<_AP_W1,false> mask1(-1); + mask1>>=_AP_W1-W_ref1; + ap_private<_AP_W2,false> mask2(-1); + mask2>>=_AP_W2-W_ref2; + mbv1.set(ap_private<_AP_W1,false>((vval>>W_ref2)&mask1)); + mbv2.set(ap_private<_AP_W2,false>(vval&mask2)); + return *this; + } + + INLINE ap_concat_ref& operator = (unsigned long long val) { + ap_private<_AP_W1+_AP_W2, false> tmpVal(val); + return operator = (tmpVal); + } + + template + INLINE ap_concat_ref& operator = + (const ap_concat_ref <_AP_W3, _AP_T3, _AP_W4, _AP_T4>& val) { + ap_private<_AP_W1+_AP_W2, false> tmpVal(val); + return operator = (tmpVal); + } + + INLINE ap_concat_ref& operator = + (const ap_concat_ref <_AP_W1, _AP_T1, _AP_W2, _AP_T2>& val) { + ap_private<_AP_W1+_AP_W2, false> tmpVal(val); + return operator = (tmpVal); + } + + template + INLINE ap_concat_ref& operator =(const ap_bit_ref<_AP_W3, _AP_S3>& val) { + ap_private<_AP_W1+_AP_W2, false> tmpVal(val); + return operator = (tmpVal); + } + + template + INLINE ap_concat_ref& operator =(const ap_range_ref<_AP_W3,_AP_S3>& val) { + ap_private<_AP_W1+_AP_W2, false> tmpVal(val); + return operator =(tmpVal); + } + + template + INLINE ap_concat_ref& operator= (const af_range_ref<_AP_W3, _AP_I3, _AP_S3, + _AP_Q3, _AP_O3, _AP_N3>& val) { + return operator = ((const ap_private<_AP_W3, false>)(val)); + } + + template + INLINE ap_concat_ref& operator= (const ap_fixed_base<_AP_W3, _AP_I3, _AP_S3, + _AP_Q3, _AP_O3, _AP_N3>& val) { + return operator = (val.to_ap_private()); + } + + template + INLINE ap_concat_ref& operator= (const af_bit_ref<_AP_W3, _AP_I3, _AP_S3, + _AP_Q3, _AP_O3, _AP_N3>& val) { + return operator=((unsigned long long)(bool)(val)); + } + + + INLINE operator ap_private<_AP_WR, false> () const { + return get(); + } + + INLINE operator unsigned long long () const { + return get().to_uint64(); + } + + template + INLINE ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, ap_range_ref<_AP_W3, _AP_S3> > + operator, (const ap_range_ref<_AP_W3, _AP_S3> &a2) { + return ap_concat_ref<_AP_WR, ap_concat_ref, + _AP_W3, ap_range_ref<_AP_W3, _AP_S3> >(*this, + const_cast &>(a2)); + } + + template + INLINE ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, ap_private<_AP_W3, _AP_S3> > + operator, (ap_private<_AP_W3, _AP_S3> &a2) { + return ap_concat_ref<_AP_WR, ap_concat_ref, + _AP_W3, ap_private<_AP_W3, _AP_S3> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, ap_private<_AP_W3, _AP_S3> > + operator, (const ap_private<_AP_W3, _AP_S3> &a2) { + return ap_concat_ref<_AP_WR, ap_concat_ref, + _AP_W3, ap_private<_AP_W3, _AP_S3> >(*this, + const_cast&>(a2)); + } + + template + INLINE ap_concat_ref<_AP_WR, ap_concat_ref, 1, ap_bit_ref<_AP_W3, _AP_S3> > + operator, (const ap_bit_ref<_AP_W3, _AP_S3> &a2) { + return ap_concat_ref<_AP_WR, ap_concat_ref, + 1, ap_bit_ref<_AP_W3, _AP_S3> >(*this, + const_cast &>(a2)); + } + + template + INLINE ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3+_AP_W4, ap_concat_ref<_AP_W3,_AP_T3,_AP_W4,_AP_T4> > + operator, (const ap_concat_ref<_AP_W3,_AP_T3,_AP_W4,_AP_T4> &a2) + { + return ap_concat_ref<_AP_WR, ap_concat_ref, + _AP_W3+_AP_W4, ap_concat_ref<_AP_W3,_AP_T3,_AP_W4, + _AP_T4> >(*this, const_cast& >(a2)); + } + + template + INLINE + ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, af_range_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3> > + operator, (const af_range_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, + _AP_O3, _AP_N3> &a2) { + return ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, af_range_ref<_AP_W3, + _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3> >(*this, + const_cast& >(a2)); + } + + template + INLINE + ap_concat_ref<_AP_WR, ap_concat_ref, 1, af_bit_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3> > + operator, (const af_bit_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, + _AP_O3, _AP_N3> &a2) { + return ap_concat_ref<_AP_WR, ap_concat_ref, 1, af_bit_ref<_AP_W3, + _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3> >(*this, + const_cast& >(a2)); + } + + template + INLINE ap_private + operator & (const ap_private<_AP_W3,_AP_S3>& a2) { + return get() & a2; + } + + + template + INLINE ap_private + operator | (const ap_private<_AP_W3,_AP_S3>& a2) { + return get() | a2; + } + + + template + INLINE ap_private + operator ^ (const ap_private<_AP_W3,_AP_S3>& a2) { + return ap_private(get() ^ a2); + } + + INLINE const ap_private<_AP_WR, false> get() const + { + ap_private<_AP_W1+_AP_W2, false> tmpVal = ap_private<_AP_W1+_AP_W2, false> (mbv1.get()); + ap_private<_AP_W1+_AP_W2, false> tmpVal2 = ap_private<_AP_W1+_AP_W2, false> (mbv2.get()); + int W_ref2 = mbv2.length(); + tmpVal <<= W_ref2; + tmpVal |= tmpVal2; + return tmpVal; + } + + INLINE const ap_private<_AP_WR, false> get() { + ap_private<_AP_W1+_AP_W2, false> tmpVal = ap_private<_AP_W1+_AP_W2, false> ( mbv1.get()); + ap_private<_AP_W1+_AP_W2, false> tmpVal2 = ap_private<_AP_W1+_AP_W2, false> (mbv2.get()); + int W_ref2 = mbv2.length(); + tmpVal <<= W_ref2; + tmpVal |= tmpVal2; + return tmpVal; + } + + template + INLINE void set(const ap_private<_AP_W3,false> & val) { + ap_private<_AP_W1+_AP_W2, false> vval(val); + int W_ref1=mbv1.length(); + int W_ref2=mbv2.length(); + ap_private<_AP_W1,false> mask1(-1); + mask1>>=_AP_W1-W_ref1; + ap_private<_AP_W2,false> mask2(-1); + mask2>>=_AP_W2-W_ref2; + mbv1.set(ap_private<_AP_W1,false>((vval>>W_ref2)&mask1)); + mbv2.set(ap_private<_AP_W2,false>(vval&mask2)); + } + + INLINE int length() const { + return mbv1.length()+mbv2.length(); + } + + INLINE std::string to_string(uint8_t radix=2) const { + return get().to_string(radix); + } +}; + +///Proxy class, which allows part selection to be used as rvalue(for reading) and +//lvalue(for writing) + +///Range(slice) reference +//------------------------------------------------------------ +template +struct ap_range_ref { +#ifdef _MSC_VER + #pragma warning( disable : 4521 4522 ) +#endif /* #ifdef _MSC_VER */ + ap_private<_AP_W,_AP_S> &d_bv; + int l_index; + int h_index; + +public: + INLINE ap_range_ref(const ap_range_ref<_AP_W, _AP_S>& ref): + d_bv(ref.d_bv), l_index(ref.l_index), h_index(ref.h_index) {} + + INLINE ap_range_ref(ap_private<_AP_W,_AP_S>* bv, int h, int l): + d_bv(*bv),l_index(l),h_index(h) { + //if (h < l) + //fprintf(stderr, "Warning! The bits selected will be returned in reverse order\n"); + } + + INLINE operator ap_private<_AP_W, false> () const { + ap_private<_AP_W, false> val(0); + if(h_index>=l_index) { + if (_AP_W > 64) { + val=d_bv; + ap_private<_AP_W,false> mask(-1); + mask>>=_AP_W-(h_index-l_index+1); + val>>=l_index; + val&=mask; + } else { + const static uint64_t mask = (~0ULL>> (64>_AP_W ? (64-_AP_W):0)); + val = (d_bv >> l_index) & (mask >>(_AP_W-(h_index-l_index+1))); + } + } else { + for(int i=0, j=l_index;j>=0&&j>=h_index;j--,i++) + if((d_bv)[j]) val.set(i); + } + return val; + } + + INLINE operator unsigned long long () const { + return to_uint64(); + } + + template + INLINE ap_range_ref& operator =(const ap_private<_AP_W2,_AP_S2>& val) { + ap_private<_AP_W,false> vval=ap_private<_AP_W,false>(val); + if (l_index>h_index) { + for (int i=0, j=l_index;j>=0&&j>=h_index;j--,i++) + (vval)[i]? d_bv.set(j):d_bv.clear(j); + } else { + if (_AP_W > 64) { + ap_private<_AP_W,false> mask(-1); + if (l_index>0) { + mask<<=l_index; + vval<<=l_index; + } + if(h_index<_AP_W-1) + { + ap_private<_AP_W,false> mask2(-1); + mask2>>=_AP_W-h_index-1; + mask&=mask2; + vval&=mask2; + } + mask.flip(); + d_bv&=mask; + d_bv|=vval; + } else { + unsigned shift = 64-_AP_W; + uint64_t mask = ~0ULL>>(shift); + if(l_index>0) + { + vval = mask & vval << l_index; + mask = mask & mask << l_index; + } + if(h_index<_AP_W-1) + { + uint64_t mask2 = mask; + mask2 >>= (_AP_W-h_index-1); + mask&=mask2; + vval&=mask2; + } + mask = ~mask; + d_bv&=mask; + d_bv|=vval; + } + } + return *this; + } + + INLINE ap_range_ref& operator = (unsigned long long val) + { + const ap_private<_AP_W,_AP_S> vval=val; + return operator = (vval); + } + + + INLINE ap_range_ref& operator =(const ap_range_ref<_AP_W, _AP_S>& val) + { + const ap_private<_AP_W, false> tmpVal(val); + return operator =(tmpVal); + } + + + + template + INLINE ap_range_ref& operator = + (const ap_concat_ref <_AP_W3, _AP_T3, _AP_W4, _AP_T4>& val) + { + const ap_private<_AP_W, false> tmpVal(val); + return operator = (tmpVal); + } + + template + INLINE ap_range_ref& operator =(const ap_range_ref<_AP_W3,_AP_S3>& val) + { + const ap_private<_AP_W, false> tmpVal(val); + return operator =(tmpVal); + } + + template + INLINE ap_range_ref& operator= (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& val) { + return operator=((const ap_private<_AP_W2, _AP_S2>)(val)); + } + + template + INLINE ap_range_ref& operator= (const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& val) { + return operator=(val.to_ap_private()); + } + + template + INLINE ap_range_ref& operator= (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& val) { + return operator=((unsigned long long)(bool)(val)); + } + + template + INLINE ap_range_ref& operator= (const ap_bit_ref<_AP_W2, _AP_S2>& val) { + return operator=((unsigned long long)(bool)(val)); + } + + template + INLINE + ap_concat_ref<_AP_W,ap_range_ref,_AP_W2,ap_range_ref<_AP_W2,_AP_S2> > + operator, (const ap_range_ref<_AP_W2,_AP_S2> &a2) + { + return + ap_concat_ref<_AP_W, ap_range_ref, _AP_W2, + ap_range_ref<_AP_W2,_AP_S2> >(*this, + const_cast& >(a2)); + } + + + template + INLINE ap_concat_ref<_AP_W,ap_range_ref,_AP_W2,ap_private<_AP_W2,_AP_S2> > + operator , (ap_private<_AP_W2,_AP_S2>& a2) + { + return + ap_concat_ref<_AP_W, ap_range_ref, _AP_W2, ap_private<_AP_W2,_AP_S2> >(*this, a2); + } + + INLINE ap_concat_ref<_AP_W,ap_range_ref,_AP_W,ap_private<_AP_W,_AP_S> > + operator , (ap_private<_AP_W, _AP_S>& a2) + { + return + ap_concat_ref<_AP_W, ap_range_ref, _AP_W, + ap_private<_AP_W,_AP_S> >(*this, a2); + } + + + + template + INLINE + ap_concat_ref<_AP_W,ap_range_ref,1,ap_bit_ref<_AP_W2,_AP_S2> > + operator, (const ap_bit_ref<_AP_W2,_AP_S2> &a2) + { + return + ap_concat_ref<_AP_W, ap_range_ref, 1, + ap_bit_ref<_AP_W2,_AP_S2> >(*this, const_cast& >(a2)); + } + + + template + INLINE + ap_concat_ref<_AP_W, ap_range_ref, _AP_W2+_AP_W3, ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > + operator, (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) + { + return ap_concat_ref<_AP_W, ap_range_ref, _AP_W2+_AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(*this, + const_cast& >(a2)); + } + + template + INLINE + ap_concat_ref<_AP_W, ap_range_ref, _AP_W2, af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<_AP_W, ap_range_ref, _AP_W2, af_range_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, + const_cast& >(a2)); + } + + template + INLINE + ap_concat_ref<_AP_W, ap_range_ref, 1, af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<_AP_W, ap_range_ref, 1, af_bit_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, + const_cast& >(a2)); + } + + template + INLINE bool operator == (const ap_range_ref<_AP_W2, _AP_S2>& op2) + { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs==rhs; + } + + + template + INLINE bool operator != (const ap_range_ref<_AP_W2, _AP_S2>& op2) + { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs!=rhs; + } + + + template + INLINE bool operator > (const ap_range_ref<_AP_W2, _AP_S2>& op2) + { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs>rhs; + } + + + template + INLINE bool operator >= (const ap_range_ref<_AP_W2, _AP_S2>& op2) + { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs>=rhs; + } + + + template + INLINE bool operator < (const ap_range_ref<_AP_W2, _AP_S2>& op2) + { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs + INLINE bool operator <= (const ap_range_ref<_AP_W2, _AP_S2>& op2) + { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs<=rhs; + } + + + template + INLINE void set(const ap_private<_AP_W2,false>& val) + { + ap_private<_AP_W,_AP_S> vval=val; + if(l_index>h_index) + { + for(int i=0, j=l_index;j>=0&&j>=h_index;j--,i++) + (vval)[i]? d_bv.set(j):d_bv.clear(j); + } else { + if (_AP_W>64 ) { + ap_private<_AP_W,_AP_S> mask(-1); + if(l_index>0) + { + ap_private<_AP_W,false> mask1(-1); + mask1>>=_AP_W-l_index; + mask1.flip(); + mask=mask1; + //vval&=mask1; + vval<<=l_index; + } + if(h_index<_AP_W-1) + { + ap_private<_AP_W,false> mask2(-1); + mask2<<=h_index+1; + mask2.flip(); + mask&=mask2; + vval&=mask2; + } + mask.flip(); + d_bv&=mask; + d_bv|=vval; + } else { + uint64_t mask = ~0ULL >> (64-_AP_W); + if(l_index>0) + { + uint64_t mask1 = mask; + mask1=mask & (mask1>>(_AP_W-l_index)); + vval =mask&( vval <> (64-_AP_W); + mask2 = mask &(mask2<<(h_index+1)); + mask&=~mask2; + vval&=~mask2; + } + d_bv&=(~mask&(~0ULL >> (64-_AP_W))); + d_bv|=vval; + } + } + } + + + INLINE ap_private<_AP_W,false> get() const + { + ap_private<_AP_W,false> val(0); + if(h_index=0&&j>=h_index;j--,i++) + if((d_bv)[j]) val.set(i); + } else { + val=d_bv; + val>>=l_index; + if(h_index<_AP_W-1) + { + if (_AP_W <= 64) { + const static uint64_t mask = (~0ULL>> (64>_AP_W ? (64-_AP_W):0)); + val &= (mask>> (_AP_W-(h_index-l_index+1))); + } else { + ap_private<_AP_W,false> mask(-1); + mask>>=_AP_W-(h_index-l_index+1); + val&=mask; + } + } + } + return val; + } + + + INLINE ap_private<_AP_W,false> get() + { + ap_private<_AP_W,false> val(0); + if(h_index=0&&j>=h_index;j--,i++) + if((d_bv)[j]) val.set(i); + } else { + val=d_bv; + val>>=l_index; + if(h_index<_AP_W-1) + { + if (_AP_W <= 64 ) { + static const uint64_t mask = ~0ULL>> (64>_AP_W ? (64-_AP_W):0); + return val &= ( (mask) >> (_AP_W - (h_index-l_index+1))); + } else { + ap_private<_AP_W,false> mask(-1); + mask>>=_AP_W-(h_index-l_index+1); + val&=mask; + } + } + } + return val; + } + + + INLINE int length() const + { + return h_index>=l_index?h_index-l_index+1:l_index-h_index+1; + } + + + INLINE int to_int() const + { + ap_private<_AP_W,false> val=get(); + return val.to_int(); + } + + + INLINE unsigned int to_uint() const + { + ap_private<_AP_W,false> val=get(); + return val.to_uint(); + } + + + INLINE long to_long() const + { + ap_private<_AP_W,false> val=get(); + return val.to_long(); + } + + + INLINE unsigned long to_ulong() const + { + ap_private<_AP_W,false> val=get(); + return val.to_ulong(); + } + + + INLINE ap_slong to_int64() const + { + ap_private<_AP_W,false> val=get(); + return val.to_int64(); + } + + + INLINE ap_ulong to_uint64() const + { + ap_private<_AP_W,false> val=get(); + return val.to_uint64(); + } + + INLINE std::string to_string(uint8_t radix=2) const { + return get().to_string(radix); + } + +}; + +///Proxy class, which allows bit selection to be used as rvalue(for reading) and +//lvalue(for writing) + +///Bit reference +//-------------------------------------------------------------- +template +struct ap_bit_ref { +#ifdef _MSC_VER +#pragma warning( disable : 4521 4522 ) +#endif + ap_private<_AP_W,_AP_S>& d_bv; + int d_index; + +public: + INLINE ap_bit_ref(const ap_bit_ref<_AP_W, _AP_S>& ref): + d_bv(ref.d_bv), d_index(ref.d_index) {} + + INLINE ap_bit_ref(ap_private<_AP_W,_AP_S>& bv, int index=0): + d_bv(bv),d_index(index) + { +#ifdef _AP_DEBUG_ + assert(d_index<_AP_W&&"index out of bound"); +#endif + } + + + INLINE operator bool () const + { + return d_bv.get_bit(d_index); + } + + + INLINE bool to_bool() const + { + return operator bool (); + } + + + INLINE ap_bit_ref& operator = (unsigned long long val) + { + if(val) + d_bv.set(d_index); + else + d_bv.clear(d_index); + return *this; + } + + +#if 0 + INLINE ap_bit_ref& operator = (bool val) + { + if(val) + d_bv.set(d_index); + else + d_bv.clear(d_index); + return *this; + } +#endif + template + INLINE ap_bit_ref& operator =(const ap_private<_AP_W2,_AP_S2>& val) + { + return operator =((unsigned long long)(val != 0)); + } + + + template + INLINE ap_bit_ref& operator =(const ap_bit_ref<_AP_W2,_AP_S2>& val) + { + return operator =((unsigned long long)(bool)val); + } + + INLINE ap_bit_ref& operator =(const ap_bit_ref<_AP_W,_AP_S>& val) + { + return operator =((unsigned long long)(bool)val); + } + + template + INLINE ap_bit_ref& operator =(const ap_range_ref<_AP_W2,_AP_S2>& val) + { + return operator =((unsigned long long)(bool) val); + } + + + template + INLINE ap_bit_ref& operator= (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& val) { + return operator=((const ap_private<_AP_W2, false>)(val)); + } + + template + INLINE ap_bit_ref& operator= (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& val) { + return operator=((unsigned long long)(bool)(val)); + } + + template + INLINE ap_bit_ref& operator= (const ap_concat_ref<_AP_W2, _AP_T3, _AP_W3, _AP_T3>& val) { + return operator=((const ap_private<_AP_W2 + _AP_W3, false>)(val)); + } + + + + template + INLINE ap_concat_ref<1, ap_bit_ref, _AP_W2, ap_private<_AP_W2,_AP_S2> > + operator , (ap_private<_AP_W2, _AP_S2>& a2) + { + return ap_concat_ref<1, ap_bit_ref, _AP_W2, ap_private<_AP_W2,_AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<1, ap_bit_ref, _AP_W2, ap_range_ref<_AP_W2,_AP_S2> > + operator, (const ap_range_ref<_AP_W2, _AP_S2> &a2) + { + return + ap_concat_ref<1, ap_bit_ref, _AP_W2, ap_range_ref<_AP_W2,_AP_S2> >(*this, + const_cast &>(a2)); + } + + + template + INLINE ap_concat_ref<1, ap_bit_ref, 1, ap_bit_ref<_AP_W2,_AP_S2> > + operator, (const ap_bit_ref<_AP_W2, _AP_S2> &a2) + { + return + ap_concat_ref<1, ap_bit_ref, 1, ap_bit_ref<_AP_W2,_AP_S2> >(*this, + const_cast &>(a2)); + } + + + INLINE ap_concat_ref<1, ap_bit_ref, 1, ap_bit_ref > + operator, (const ap_bit_ref &a2) + { + return + ap_concat_ref<1, ap_bit_ref, 1, ap_bit_ref >(*this, + const_cast(a2)); + } + + + template + INLINE ap_concat_ref<1, ap_bit_ref, _AP_W2+_AP_W3, ap_concat_ref<_AP_W2,_AP_T2,_AP_W3,_AP_T3> > + operator, (const ap_concat_ref<_AP_W2,_AP_T2,_AP_W3,_AP_T3> &a2) + { + return + ap_concat_ref<1,ap_bit_ref,_AP_W2+_AP_W3, + ap_concat_ref<_AP_W2,_AP_T2,_AP_W3,_AP_T3> >(*this, + const_cast& >(a2)); + } + + template + INLINE + ap_concat_ref<1, ap_bit_ref, _AP_W2, af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<1, ap_bit_ref, _AP_W2, af_range_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, + const_cast& >(a2)); + } + + template + INLINE + ap_concat_ref<1, ap_bit_ref, 1, af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<1, ap_bit_ref, 1, af_bit_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, + const_cast& >(a2)); + } + + template + INLINE bool operator == (const ap_bit_ref<_AP_W2, _AP_S2>& op) { + return get() == op.get(); + } + + template + INLINE bool operator != (const ap_bit_ref<_AP_W2, _AP_S2>& op) { + return get() != op.get(); + } + + + INLINE bool get() const + { + return operator bool (); + } + + + INLINE bool get() + { + return operator bool (); + } + + + template + INLINE void set(const ap_private<_AP_W3, false>& val) + { + operator = (val); + } + + INLINE bool operator ~ () const { + bool bit = (d_bv)[d_index]; + return bit ? false : true; + } + + INLINE int length() const { return 1; } + + INLINE std::string to_string() const { + bool val = get(); + return val ? "1" : "0"; + } +}; + +/// Operators mixing Integers with AP_Int +// ---------------------------------------------------------------- +#if 1 +#define OP_BIN_MIX_INT(BIN_OP, C_TYPE, _AP_WI, _AP_SI, RTYPE) \ + template \ + INLINE typename ap_private<_AP_WI,_AP_SI>::template RType<_AP_W,_AP_S>::RTYPE \ + operator BIN_OP ( C_TYPE i_op, const ap_private<_AP_W,_AP_S> &op) { \ + return ap_private<_AP_WI,_AP_SI>(i_op).operator BIN_OP (op); \ + } \ + template \ + INLINE typename ap_private<_AP_W,_AP_S>::template RType<_AP_WI,_AP_SI>::RTYPE \ + operator BIN_OP ( const ap_private<_AP_W,_AP_S> &op, C_TYPE i_op) { \ + return op.operator BIN_OP (ap_private<_AP_WI,_AP_SI>(i_op)); \ + } +#else +#define OP_BIN_MIX_INT(BIN_OP, C_TYPE, _AP_WI, _AP_SI, RTYPE) \ + template \ + INLINE typename ap_private<_AP_WI,_AP_SI>::template RType<_AP_W,_AP_S>::RTYPE \ + operator BIN_OP ( C_TYPE i_op, const ap_private<_AP_W,_AP_S> &op) { \ + return ap_private<_AP_WI,_AP_SI>(i_op).operator BIN_OP (op); \ + } \ + template \ + INLINE typename ap_private<_AP_W,_AP_S>::template RType<_AP_WI,_AP_SI>::RTYPE \ + operator BIN_OP ( const ap_private<_AP_W,_AP_S> &op, C_TYPE i_op) { \ + return op.operator BIN_OP (ap_private<_AP_WI,_AP_SI>(i_op)); \ + } +#endif +#define OP_REL_MIX_INT(REL_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE bool operator REL_OP ( const ap_private<_AP_W,_AP_S> &op, C_TYPE op2) { \ + return op.operator REL_OP (ap_private<_AP_W2, _AP_S2>(op2)); \ + } \ + template \ + INLINE bool operator REL_OP ( C_TYPE op2, const ap_private<_AP_W,_AP_S> &op) { \ + return ap_private<_AP_W2,_AP_S2>(op2).operator REL_OP (op); \ + } +#define OP_ASSIGN_MIX_INT(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE ap_private<_AP_W,_AP_S> &operator ASSIGN_OP ( ap_private<_AP_W,_AP_S> &op, C_TYPE op2) { \ + return op.operator ASSIGN_OP (ap_private<_AP_W2,_AP_S2>(op2)); \ + } + +#define OP_BIN_SHIFT_INT(BIN_OP, C_TYPE, _AP_WI, _AP_SI, RTYPE) \ + template \ + C_TYPE operator BIN_OP ( C_TYPE i_op, const ap_private<_AP_W,_AP_S> &op) { \ + return i_op BIN_OP (op.getVal()); \ + } \ + template \ + INLINE typename ap_private<_AP_W,_AP_S>::template RType<_AP_WI,_AP_SI>::RTYPE \ + operator BIN_OP ( const ap_private<_AP_W,_AP_S> &op, C_TYPE i_op) { \ + return op.operator BIN_OP (i_op); \ + } +#define OP_ASSIGN_RSHIFT_INT(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE ap_private<_AP_W,_AP_S> &operator ASSIGN_OP ( ap_private<_AP_W,_AP_S> &op, C_TYPE op2) { \ + op = op.operator >> (op2); \ + return op; \ + } +#define OP_ASSIGN_LSHIFT_INT(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE ap_private<_AP_W,_AP_S> &operator ASSIGN_OP ( ap_private<_AP_W,_AP_S> &op, C_TYPE op2) { \ + op = op.operator << (op2); \ + return op; \ + } + +#define OPS_MIX_INT(C_TYPE, WI, SI) \ + OP_BIN_MIX_INT(*, C_TYPE, WI, SI, mult) \ + OP_BIN_MIX_INT(+, C_TYPE, WI, SI, plus) \ + OP_BIN_MIX_INT(-, C_TYPE, WI, SI, minus) \ + OP_BIN_MIX_INT(/, C_TYPE, WI, SI, div) \ + OP_BIN_MIX_INT(%, C_TYPE, WI, SI, mod) \ + OP_BIN_MIX_INT(&, C_TYPE, WI, SI, logic) \ + OP_BIN_MIX_INT(|, C_TYPE, WI, SI, logic) \ + OP_BIN_MIX_INT(^, C_TYPE, WI, SI, logic) \ + OP_BIN_SHIFT_INT(>>, C_TYPE, WI, SI, arg1) \ + OP_BIN_SHIFT_INT(<<, C_TYPE, WI, SI, arg1) \ + \ + OP_REL_MIX_INT(==, C_TYPE, WI, SI) \ + OP_REL_MIX_INT(!=, C_TYPE, WI, SI) \ + OP_REL_MIX_INT(>, C_TYPE, WI, SI) \ + OP_REL_MIX_INT(>=, C_TYPE, WI, SI) \ + OP_REL_MIX_INT(<, C_TYPE, WI, SI) \ + OP_REL_MIX_INT(<=, C_TYPE, WI, SI) \ + \ + OP_ASSIGN_MIX_INT(+=, C_TYPE, WI, SI) \ + OP_ASSIGN_MIX_INT(-=, C_TYPE, WI, SI) \ + OP_ASSIGN_MIX_INT(*=, C_TYPE, WI, SI) \ + OP_ASSIGN_MIX_INT(/=, C_TYPE, WI, SI) \ + OP_ASSIGN_MIX_INT(%=, C_TYPE, WI, SI) \ + OP_ASSIGN_MIX_INT(&=, C_TYPE, WI, SI) \ + OP_ASSIGN_MIX_INT(|=, C_TYPE, WI, SI) \ + OP_ASSIGN_MIX_INT(^=, C_TYPE, WI, SI) \ + OP_ASSIGN_RSHIFT_INT(>>=, C_TYPE, WI, SI) \ + OP_ASSIGN_LSHIFT_INT(<<=, C_TYPE, WI, SI) + + +OPS_MIX_INT(bool, 1, false) +OPS_MIX_INT(char, 8, true) +OPS_MIX_INT(signed char, 8, true) +OPS_MIX_INT(unsigned char, 8, false) +OPS_MIX_INT(short, 16, true) +OPS_MIX_INT(unsigned short, 16, false) +OPS_MIX_INT(int, 32, true) +OPS_MIX_INT(unsigned int, 32, false) +# if defined __x86_64__ +OPS_MIX_INT(long, 64, true) +OPS_MIX_INT(unsigned long, 64, false) +# else +OPS_MIX_INT(long, 32, true) +OPS_MIX_INT(unsigned long, 32, false) +# endif +OPS_MIX_INT(ap_slong, 64, true) +OPS_MIX_INT(ap_ulong, 64, false) + +#define OP_BIN_MIX_RANGE(BIN_OP, RTYPE) \ + template \ + INLINE typename ap_private<_AP_W1,_AP_S1>::template RType<_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP ( const ap_range_ref<_AP_W1,_AP_S1>& op1, const ap_private<_AP_W2,_AP_S2>& op2) { \ + return ap_private<_AP_W1, false>(op1).operator BIN_OP (op2); \ + } \ + template \ + INLINE typename ap_private<_AP_W1,_AP_S1>::template RType<_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP ( const ap_private<_AP_W1,_AP_S1>& op1, const ap_range_ref<_AP_W2,_AP_S2>& op2) { \ + return op1.operator BIN_OP (ap_private<_AP_W2, false>(op2)); \ + } + +#define OP_REL_MIX_RANGE(REL_OP) \ + template \ + INLINE bool operator REL_OP ( const ap_range_ref<_AP_W1,_AP_S1>& op1, const ap_private<_AP_W2,_AP_S2>& op2) { \ + return ap_private<_AP_W1,false>(op1).operator REL_OP (op2); \ + } \ + template \ + INLINE bool operator REL_OP ( const ap_private<_AP_W1,_AP_S1>& op1, const ap_range_ref<_AP_W2,_AP_S2>& op2) { \ + return op1.operator REL_OP (op2.operator ap_private<_AP_W2, false>()); \ + } + +#define OP_ASSIGN_MIX_RANGE(ASSIGN_OP) \ + template \ + INLINE ap_private<_AP_W1,_AP_S1>& operator ASSIGN_OP ( ap_private<_AP_W1,_AP_S1>& op1, const ap_range_ref<_AP_W2,_AP_S2>& op2) { \ + return op1.operator ASSIGN_OP (ap_private<_AP_W2, false>(op2)); \ + } \ + template \ + INLINE ap_range_ref<_AP_W1,_AP_S1>& operator ASSIGN_OP (ap_range_ref<_AP_W1,_AP_S1>& op1, ap_private<_AP_W2,_AP_S2>& op2) { \ + ap_private<_AP_W1, false> tmp(op1); \ + tmp.operator ASSIGN_OP (op2); \ + op1 = tmp; \ + return op1; \ + } + + +OP_ASSIGN_MIX_RANGE(+=) +OP_ASSIGN_MIX_RANGE(-=) +OP_ASSIGN_MIX_RANGE(*=) +OP_ASSIGN_MIX_RANGE(/=) +OP_ASSIGN_MIX_RANGE(%=) +OP_ASSIGN_MIX_RANGE(>>=) +OP_ASSIGN_MIX_RANGE(<<=) +OP_ASSIGN_MIX_RANGE(&=) +OP_ASSIGN_MIX_RANGE(|=) +OP_ASSIGN_MIX_RANGE(^=) + +OP_REL_MIX_RANGE(==) +OP_REL_MIX_RANGE(!=) +OP_REL_MIX_RANGE(>) +OP_REL_MIX_RANGE(>=) +OP_REL_MIX_RANGE(<) +OP_REL_MIX_RANGE(<=) + +OP_BIN_MIX_RANGE(+, plus) +OP_BIN_MIX_RANGE(-, minus) +OP_BIN_MIX_RANGE(*, mult) +OP_BIN_MIX_RANGE(/, div) +OP_BIN_MIX_RANGE(%, mod) +OP_BIN_MIX_RANGE(>>, arg1) +OP_BIN_MIX_RANGE(<<, arg1) +OP_BIN_MIX_RANGE(&, logic) +OP_BIN_MIX_RANGE(|, logic) +OP_BIN_MIX_RANGE(^, logic) + +#define OP_BIN_MIX_BIT(BIN_OP, RTYPE) \ + template \ + INLINE typename ap_private<1, false>::template RType<_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP ( const ap_bit_ref<_AP_W1,_AP_S1>& op1, const ap_private<_AP_W2,_AP_S2>& op2) { \ + return ap_private<1, false>(op1).operator BIN_OP (op2); \ + } \ + template \ + INLINE typename ap_private<_AP_W1,_AP_S1>::template RType<1,false>::RTYPE \ + operator BIN_OP ( const ap_private<_AP_W1,_AP_S1>& op1, const ap_bit_ref<_AP_W2,_AP_S2>& op2) { \ + return op1.operator BIN_OP (ap_private<1, false>(op2)); \ + } + +#define OP_REL_MIX_BIT(REL_OP) \ + template \ + INLINE bool operator REL_OP ( const ap_bit_ref<_AP_W1,_AP_S1>& op1, const ap_private<_AP_W2,_AP_S2>& op2) { \ + return ap_private<_AP_W1,false>(op1).operator REL_OP (op2); \ + } \ + template \ + INLINE bool operator REL_OP ( const ap_private<_AP_W1,_AP_S1>& op1, const ap_bit_ref<_AP_W2,_AP_S2>& op2) { \ + return op1.operator REL_OP (ap_private<1, false>(op2)); \ + } + +#define OP_ASSIGN_MIX_BIT(ASSIGN_OP) \ + template \ + INLINE ap_private<_AP_W1,_AP_S1>& operator ASSIGN_OP ( ap_private<_AP_W1,_AP_S1>& op1, ap_bit_ref<_AP_W2,_AP_S2>& op2) { \ + return op1.operator ASSIGN_OP (ap_private<1, false>(op2)); \ + } \ + template \ + INLINE ap_bit_ref<_AP_W1,_AP_S1>& operator ASSIGN_OP ( ap_bit_ref<_AP_W1,_AP_S1>& op1, ap_private<_AP_W2,_AP_S2>& op2) { \ + ap_private<1, false> tmp(op1); \ + tmp.operator ASSIGN_OP (op2); \ + op1 = tmp; \ + return op1; \ + } + + +OP_ASSIGN_MIX_BIT(+=) +OP_ASSIGN_MIX_BIT(-=) +OP_ASSIGN_MIX_BIT(*=) +OP_ASSIGN_MIX_BIT(/=) +OP_ASSIGN_MIX_BIT(%=) +OP_ASSIGN_MIX_BIT(>>=) +OP_ASSIGN_MIX_BIT(<<=) +OP_ASSIGN_MIX_BIT(&=) +OP_ASSIGN_MIX_BIT(|=) +OP_ASSIGN_MIX_BIT(^=) + +OP_REL_MIX_BIT(==) +OP_REL_MIX_BIT(!=) +OP_REL_MIX_BIT(>) +OP_REL_MIX_BIT(>=) +OP_REL_MIX_BIT(<) +OP_REL_MIX_BIT(<=) + +OP_BIN_MIX_BIT(+, plus) +OP_BIN_MIX_BIT(-, minus) +OP_BIN_MIX_BIT(*, mult) +OP_BIN_MIX_BIT(/, div) +OP_BIN_MIX_BIT(%, mod) +OP_BIN_MIX_BIT(>>, arg1) +OP_BIN_MIX_BIT(<<, arg1) +OP_BIN_MIX_BIT(&, logic) +OP_BIN_MIX_BIT(|, logic) +OP_BIN_MIX_BIT(^, logic) + +#define REF_REL_OP_MIX_INT(REL_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE bool operator REL_OP ( const ap_range_ref<_AP_W,_AP_S> &op, C_TYPE op2) { \ + return (ap_private<_AP_W, false>(op)).operator REL_OP (ap_private<_AP_W2,_AP_S2>(op2)); \ + } \ + template \ + INLINE bool operator REL_OP ( C_TYPE op2, const ap_range_ref<_AP_W,_AP_S> &op) { \ + return ap_private<_AP_W2,_AP_S2>(op2).operator REL_OP (ap_private<_AP_W, false>(op)); \ + } \ + template \ + INLINE bool operator REL_OP ( const ap_bit_ref<_AP_W,_AP_S> &op, C_TYPE op2) { \ + return (bool(op)) REL_OP op2; \ + } \ + template \ + INLINE bool operator REL_OP ( C_TYPE op2, const ap_bit_ref<_AP_W,_AP_S> &op) { \ + return op2 REL_OP (bool(op)); \ + } \ + template \ + INLINE bool operator REL_OP ( const ap_concat_ref<_AP_W,_AP_T, _AP_W1, _AP_T1> &op, C_TYPE op2) { \ + return (ap_private<_AP_W + _AP_W1, false>(op)).operator REL_OP (ap_private<_AP_W2,_AP_S2>(op2)); \ + } \ + template \ + INLINE bool operator REL_OP ( C_TYPE op2, const ap_concat_ref<_AP_W,_AP_T, _AP_W1, _AP_T1> &op) { \ + return ap_private<_AP_W2,_AP_S2>(op2).operator REL_OP (ap_private<_AP_W + _AP_W1, false>(op)); \ + } + +#define REF_REL_MIX_INT(C_TYPE, _AP_WI, _AP_SI) \ +REF_REL_OP_MIX_INT(>, C_TYPE, _AP_WI, _AP_SI) \ +REF_REL_OP_MIX_INT(<, C_TYPE, _AP_WI, _AP_SI) \ +REF_REL_OP_MIX_INT(>=, C_TYPE, _AP_WI, _AP_SI) \ +REF_REL_OP_MIX_INT(<=, C_TYPE, _AP_WI, _AP_SI) \ +REF_REL_OP_MIX_INT(==, C_TYPE, _AP_WI, _AP_SI) \ +REF_REL_OP_MIX_INT(!=, C_TYPE, _AP_WI, _AP_SI) + +REF_REL_MIX_INT(bool, 1, false) +REF_REL_MIX_INT(char, 8, true) +REF_REL_MIX_INT(signed char, 8, true) +REF_REL_MIX_INT(unsigned char, 8, false) +REF_REL_MIX_INT(short, 16, true) +REF_REL_MIX_INT(unsigned short, 16, false) +REF_REL_MIX_INT(int, 32, true) +REF_REL_MIX_INT(unsigned int, 32, false) +# if defined __x86_64__ +REF_REL_MIX_INT(long, 64, true) +REF_REL_MIX_INT(unsigned long, 64, false) +# else +REF_REL_MIX_INT(long, 32, true) +REF_REL_MIX_INT(unsigned long, 32, false) +# endif +REF_REL_MIX_INT(ap_slong, 64, true) +REF_REL_MIX_INT(ap_ulong, 64, false) + +#define REF_BIN_OP_MIX_INT(BIN_OP, RTYPE, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE typename ap_private<_AP_W, false>::template RType<_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP ( const ap_range_ref<_AP_W,_AP_S> &op, C_TYPE op2) { \ + return (ap_private<_AP_W, false>(op)).operator BIN_OP (ap_private<_AP_W2,_AP_S2>(op2)); \ + } \ + template \ + INLINE typename ap_private<_AP_W2, _AP_S2>::template RType<_AP_W,false>::RTYPE \ + operator BIN_OP ( C_TYPE op2, const ap_range_ref<_AP_W,_AP_S> &op) { \ + return ap_private<_AP_W2,_AP_S2>(op2).operator BIN_OP (ap_private<_AP_W, false>(op)); \ + } + +#define REF_BIN_MIX_INT(C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(+, plus, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(-, minus, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(*, mult, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(/, div, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(%, mod, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(>>, arg1, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(<<, arg1, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(&, logic, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(|, logic, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(^, logic, C_TYPE, _AP_WI, _AP_SI) + +REF_BIN_MIX_INT(bool, 1, false) +REF_BIN_MIX_INT(char, 8, true) +REF_BIN_MIX_INT(signed char, 8, true) +REF_BIN_MIX_INT(unsigned char, 8, false) +REF_BIN_MIX_INT(short, 16, true) +REF_BIN_MIX_INT(unsigned short, 16, false) +REF_BIN_MIX_INT(int, 32, true) +REF_BIN_MIX_INT(unsigned int, 32, false) +# if defined __x86_64__ +REF_BIN_MIX_INT(long, 64, true) +REF_BIN_MIX_INT(unsigned long, 64, false) +#else +REF_BIN_MIX_INT(long, 32, true) +REF_BIN_MIX_INT(unsigned long, 32, false) +#endif +REF_BIN_MIX_INT(ap_slong, 64, true) +REF_BIN_MIX_INT(ap_ulong, 64, false) + +#define REF_BIN_OP(BIN_OP, RTYPE) \ +template \ +INLINE typename ap_private<_AP_W, false>::template RType<_AP_W2, false>::RTYPE \ +operator BIN_OP (const ap_range_ref<_AP_W,_AP_S> &lhs, const ap_range_ref<_AP_W2,_AP_S2> &rhs) { \ + return ap_private<_AP_W,false>(lhs).operator BIN_OP (ap_private<_AP_W2, false>(rhs)); \ +} + +REF_BIN_OP(+, plus) +REF_BIN_OP(-, minus) +REF_BIN_OP(*, mult) +REF_BIN_OP(/, div) +REF_BIN_OP(%, mod) +REF_BIN_OP(>>, arg1) +REF_BIN_OP(<<, arg1) +REF_BIN_OP(&, logic) +REF_BIN_OP(|, logic) +REF_BIN_OP(^, logic) + +#if 1 +#define CONCAT_OP_MIX_INT(C_TYPE, _AP_WI, _AP_SI) \ +template \ +INLINE \ +ap_private< _AP_W + _AP_WI, false > \ + operator, (const ap_private<_AP_W, _AP_S> &op1, C_TYPE op2) { \ + ap_private<_AP_WI + _AP_W, false> val(op2); \ + ap_private<_AP_WI + _AP_W, false> ret(op1); \ + ret <<= _AP_WI; \ + if (_AP_SI) { \ + val <<= _AP_W; val >>= _AP_W; \ + }\ + ret |= val; \ + return ret;\ +} \ +template \ +INLINE \ +ap_private< _AP_W + _AP_WI, false > \ + operator, (C_TYPE op1, const ap_private<_AP_W, _AP_S>& op2) { \ + ap_private<_AP_WI + _AP_W, false> val(op1); \ + ap_private<_AP_WI + _AP_W, false> ret(op2); \ + if (_AP_S) { \ + ret <<= _AP_WI; ret >>= _AP_WI; \ + } \ + ret |= val << _AP_W; \ + return ret; \ +} \ +template \ +INLINE \ +ap_private< _AP_W + _AP_WI, false > \ + operator, (const ap_range_ref<_AP_W, _AP_S> &op1, C_TYPE op2) { \ + ap_private<_AP_WI + _AP_W, false> val(op2); \ + ap_private<_AP_WI + _AP_W, false> ret(op1); \ + ret <<= _AP_WI; \ + if (_AP_SI) { \ + val <<= _AP_W; val >>= _AP_W; \ + } \ + ret |= val; \ + return ret; \ +} \ +template \ +INLINE \ +ap_private< _AP_W + _AP_WI, false > \ + operator, (C_TYPE op1, const ap_range_ref<_AP_W, _AP_S> &op2) { \ + ap_private<_AP_WI + _AP_W, false> val(op1); \ + ap_private<_AP_WI + _AP_W, false> ret(op2); \ + int len = op2.length(); \ + val <<= len; \ + ret |= val; \ + return ret; \ +} \ +template \ +INLINE \ +ap_private<_AP_WI + 1, false > \ + operator, (const ap_bit_ref<_AP_W, _AP_S> &op1, C_TYPE op2) { \ + ap_private<_AP_WI + 1, false> val(op2); \ + val[_AP_WI] = op1; \ + return val; \ +} \ +template \ +INLINE \ +ap_private<_AP_WI + 1, false > \ + operator, (C_TYPE op1, const ap_bit_ref<_AP_W, _AP_S> &op2) { \ + ap_private<_AP_WI + 1, false> val(op1); \ + val <<= 1; \ + val[0] = op2; \ + return val; \ +} \ +template \ +INLINE \ +ap_private<_AP_W + _AP_W2 + _AP_WI, false > \ + operator, (const ap_concat_ref<_AP_W, _AP_T, _AP_W2, _AP_T2> &op1, C_TYPE op2) {\ + ap_private<_AP_WI + _AP_W + _AP_W2, _AP_SI> val(op2);\ + ap_private<_AP_WI + _AP_W + _AP_W2, _AP_SI> ret(op1);\ + if (_AP_SI) { \ + val <<= _AP_W + _AP_W2; val >>= _AP_W + _AP_W2; \ + } \ + ret <<= _AP_WI; \ + ret |= val; \ + return ret; \ +}\ +template \ +INLINE \ +ap_private<_AP_W + _AP_W2 + _AP_WI, false > \ + operator, (C_TYPE op1, const ap_concat_ref<_AP_W, _AP_T, _AP_W2, _AP_T2> &op2) {\ + ap_private<_AP_WI + _AP_W + _AP_W2, _AP_SI> val(op1);\ + ap_private<_AP_WI + _AP_W + _AP_W2, _AP_SI> ret(op2);\ + int len = op2.length(); \ + val <<= len; \ + ret |= val;\ + return ret; \ +}\ +template \ +INLINE \ +ap_private< _AP_W + _AP_WI, false > \ + operator, (const af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op1, C_TYPE op2) { \ + ap_private<_AP_WI + _AP_W, false> val(op2); \ + ap_private<_AP_WI + _AP_W, false> ret(op1); \ + if (_AP_SI) { \ + val <<= _AP_W; val >>= _AP_W; \ + }\ + ret <<= _AP_WI; \ + ret |= val; \ + return ret; \ +} \ +template \ +INLINE \ +ap_private< _AP_W + _AP_WI, false > \ + operator, (C_TYPE op1, const af_range_ref<_AP_W, _AP_I, _AP_S, \ + _AP_Q, _AP_O, _AP_N> &op2) { \ + ap_private<_AP_WI + _AP_W, false> val(op1); \ + ap_private<_AP_WI + _AP_W, false> ret(op2); \ + int len = op2.length(); \ + val <<= len; \ + ret |= val; \ + return ret; \ +} \ +template \ +INLINE \ +ap_private< 1 + _AP_WI, false> \ + operator, (const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, \ + _AP_N> &op1, C_TYPE op2) { \ + ap_private<_AP_WI + 1, _AP_SI> val(op2); \ + val[_AP_WI] = op1; \ + return val; \ +} \ +template \ +INLINE \ +ap_private< 1 + _AP_WI, false> \ + operator, (C_TYPE op1, const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q,\ + _AP_O, _AP_N> &op2) { \ + ap_private<_AP_WI + 1, _AP_SI> val(op1); \ + val <<= 1; \ + val[0] = op2; \ + return val; \ +} + +CONCAT_OP_MIX_INT(bool, 1, false) +CONCAT_OP_MIX_INT(char, 8, true) +CONCAT_OP_MIX_INT(signed char, 8, true) +CONCAT_OP_MIX_INT(unsigned char, 8, false) +CONCAT_OP_MIX_INT(short, 16, true) +CONCAT_OP_MIX_INT(unsigned short, 16, false) +CONCAT_OP_MIX_INT(int, 32, true) +CONCAT_OP_MIX_INT(unsigned int, 32, false) +# if defined __x86_64__ +CONCAT_OP_MIX_INT(long, 64, true) +CONCAT_OP_MIX_INT(unsigned long, 64, false) +# else +CONCAT_OP_MIX_INT(long, 32, true) +CONCAT_OP_MIX_INT(unsigned long, 32, false) +# endif +CONCAT_OP_MIX_INT(ap_slong, 64, true) +CONCAT_OP_MIX_INT(ap_ulong, 64, false) +#endif + +#if 1 +#define CONCAT_SHIFT_MIX_INT(C_TYPE, op) \ +template \ +INLINE ap_uint<_AP_W+_AP_W1> operator op (const ap_concat_ref<_AP_W, _AP_T, _AP_W1, _AP_T1> lhs, C_TYPE rhs) { \ + return ((ap_uint<_AP_W+_AP_W1>)lhs.get()) op ((int)rhs); \ +} + +CONCAT_SHIFT_MIX_INT(long, <<) +CONCAT_SHIFT_MIX_INT(unsigned long, <<) +CONCAT_SHIFT_MIX_INT(unsigned int, <<) +CONCAT_SHIFT_MIX_INT(ap_ulong, <<) +CONCAT_SHIFT_MIX_INT(ap_slong, <<) +CONCAT_SHIFT_MIX_INT(long, >>) +CONCAT_SHIFT_MIX_INT(unsigned long, >>) +CONCAT_SHIFT_MIX_INT(unsigned int, >>) +CONCAT_SHIFT_MIX_INT(ap_ulong, >>) +CONCAT_SHIFT_MIX_INT(ap_slong, >>) +#endif + +#if defined(SYSTEMC_H) || defined(SYSTEMC_INCLUDED) +template +INLINE void sc_trace(sc_core::sc_trace_file *tf, const ap_private<_AP_W, _AP_S> &op, + const std::string &name) { + if (tf) + tf->trace(sc_dt::sc_lv<_AP_W>(op.to_string(2).c_str()), name); +} +#endif + +template +INLINE std::ostream& operator<<(std::ostream& out, const ap_private<_AP_W,_AP_S> &op) +{ + ap_private<_AP_W, _AP_S> v=op; + const std::ios_base::fmtflags basefield = out.flags() & std::ios_base::basefield; + unsigned radix = (basefield == std::ios_base::hex) ? 16 : + ((basefield == std::ios_base::oct) ? 8 : 10); + std::string str=v.toString(radix,_AP_S); + out< +INLINE std::istream& operator >> (std::istream& in, ap_private<_AP_W,_AP_S> &op) +{ + std::string str; + in >> str; + op = ap_private<_AP_W, _AP_S>(str.c_str()); + return in; + +} + +template +INLINE std::ostream& operator<<(std::ostream& out, const ap_range_ref<_AP_W,_AP_S> &op) +{ + return operator<<(out, ap_private<_AP_W, _AP_S>(op)); +} + +template +INLINE std::istream& operator >> (std::istream& in, ap_range_ref<_AP_W,_AP_S> &op) +{ + return operator>>(in, ap_private<_AP_W, _AP_S>(op));; +} + +template +INLINE void print(const ap_private<_AP_W,_AP_S> &op, bool fill=true ) +{ + ap_private<_AP_W, _AP_S> v=op; + uint32_t ws=v.getNumWords(); + const uint64_t *ptr=v.getRawData(); + int i=ws-1; +#if 0 + if(fill) + printf("%016llx",*(ptr+i)); + else + printf("%llx",*(ptr+i)); +#else +//match SystemC output + if(_AP_W%64 != 0) { + uint32_t offset=_AP_W%64; + uint32_t count=(offset+3)/4; + int64_t data=*(ptr+i); + if(_AP_S) + data=(data<<(64-offset))>>(64-offset); + else + count=(offset+4)/4; + while(count-->0) + printf("%llx",(data>>(count*4))&0xf); + } else { + if(_AP_S==false) + printf("0"); + printf("%016llx",*(ptr+i)); + } +#endif + for(--i;i>=0;i--) + printf("%016llx",*(ptr+i)); + printf("\n"); + +} +#endif /* #ifndef __AESL_GCC_AP_INT_H__ */ \ No newline at end of file diff --git a/hls_2018/router_03/etc/ap_private.h b/hls_2018/router_03/etc/ap_private.h new file mode 100755 index 0000000..1a68a9e --- /dev/null +++ b/hls_2018/router_03/etc/ap_private.h @@ -0,0 +1,5858 @@ +/* + * Copyright 2012 Xilinx, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LLVM_SUPPORT_MATHEXTRAS_H +#define LLVM_SUPPORT_MATHEXTRAS_H + +#ifdef _MSC_VER +#if _MSC_VER <= 1500 +typedef __int8 int8_t; +typedef unsigned __int8 uint8_t; +typedef __int16 int16_t; +typedef unsigned __int16 uint16_t; +typedef __int32 int32_t; +typedef unsigned __int32 uint32_t; +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; +#else if +#include +#endif /* #if _MSC_VER <= 1500 */ +#else +#include +#endif /* #if _MSC_VER <= 1500 */ +#undef INLINE +#if 1 +#define INLINE inline +#else +//Enable to debug ap_int/ap_fixed +#define INLINE __attribute__((weak)) +#endif +#define AP_MAX(a,b) ((a) > (b) ? (a) : (b)) +#define AP_MIN(a,b) ((a) < (b) ? (a) : (b)) +#define AP_ABS(a) ((a)>=0 ? (a):-(a)) +#ifndef AP_INT_MAX_W +#define AP_INT_MAX_W 1024 +#endif +#define BIT_WIDTH_UPPER_LIMIT (1 << 15) +#if AP_INT_MAX_W > BIT_WIDTH_UPPER_LIMIT +#error "Bitwidth exceeds 32768 (1 << 15), the maximum allowed value" +#endif +#define MAX_MODE(BITS) ((BITS + 1023) / 1024) + +// NOTE: The following support functions use the _32/_64 extensions instead of +// type overloading so that signed and unsigned integers can be used without +// ambiguity. + +/// Hi_32 - This function returns the high 32 bits of a 64 bit value. +INLINE uint32_t Hi_32(uint64_t Value) { + return static_cast(Value >> 32); +} + +/// Lo_32 - This function returns the low 32 bits of a 64 bit value. +INLINE uint32_t Lo_32(uint64_t Value) { + return static_cast(Value); +} + +/// ByteSwap_16 - This function returns a byte-swapped representation of the +/// 16-bit argument, Value. +INLINE uint16_t ByteSwap_16(uint16_t Value) { +#if defined(_MSC_VER) && !defined(_DEBUG) + // The DLL version of the runtime lacks these functions (bug!?), but in a + // release build they're replaced with BSWAP instructions anyway. + return (uint16_t)(_byteswap_ushort(Value)); +#else + uint16_t Hi = (uint16_t)((Value) << 8); + uint16_t Lo = (uint16_t)((Value) >> 8); + return Hi | Lo; +#endif +} + +/// ByteSwap_32 - This function returns a byte-swapped representation of the +/// 32-bit argument, Value. +INLINE uint32_t ByteSwap_32(uint32_t Value) { + uint32_t Byte0 = Value & 0x000000FF; + uint32_t Byte1 = Value & 0x0000FF00; + uint32_t Byte2 = Value & 0x00FF0000; + uint32_t Byte3 = Value & 0xFF000000; + return ((Byte0) << 24) | ((Byte1) << 8) | ((Byte2) >> 8) | ((Byte3) >> 24); +} + +/// ByteSwap_64 - This function returns a byte-swapped representation of the +/// 64-bit argument, Value. +INLINE uint64_t ByteSwap_64(uint64_t Value) { + uint64_t Hi = ByteSwap_32(uint32_t(Value)); + uint32_t Lo = ByteSwap_32(uint32_t(Value >> 32)); + return ((Hi) << 32) | Lo; +} + +/// CountLeadingZeros_32 - this function performs the platform optimal form of +/// counting the number of zeros from the most significant bit to the first one +/// bit. Ex. CountLeadingZeros_32(0x00F000FF) == 8. +/// Returns 32 if the word is zero. +INLINE unsigned CountLeadingZeros_32(uint32_t Value) { + unsigned Count; // result +#if __GNUC__ >= 4 + // PowerPC is defined for __builtin_clz(0) +#if !defined(__ppc__) && !defined(__ppc64__) + if (Value == 0) return 32; +#endif + Count = __builtin_clz(Value); +#else + if (Value == 0) return 32; + Count = 0; + // bisecton method for count leading zeros + for (unsigned Shift = 32 >> 1; Shift; Shift >>= 1) { + uint32_t Tmp = (Value) >> (Shift); + if (Tmp) { + Value = Tmp; + } else { + Count |= Shift; + } + } +#endif + return Count; +} + +/// CountLeadingZeros_64 - This function performs the platform optimal form +/// of counting the number of zeros from the most significant bit to the first +/// one bit (64 bit edition.) +/// Returns 64 if the word is zero. +INLINE unsigned CountLeadingZeros_64(uint64_t Value) { + unsigned Count; // result +#if __GNUC__ >= 4 + // PowerPC is defined for __builtin_clzll(0) +#if !defined(__ppc__) && !defined(__ppc64__) + if (!Value) return 64; +#endif + Count = __builtin_clzll(Value); +#else + if (sizeof(long) == sizeof(int64_t)) { + if (!Value) return 64; + Count = 0; + // bisecton method for count leading zeros + for (unsigned Shift = 64 >> 1; Shift; Shift >>= 1) { + uint64_t Tmp = (Value) >> (Shift); + if (Tmp) { + Value = Tmp; + } else { + Count |= Shift; + } + } + } else { + // get hi portion + uint32_t Hi = Hi_32(Value); + + // if some bits in hi portion + if (Hi) { + // leading zeros in hi portion plus all bits in lo portion + Count = CountLeadingZeros_32(Hi); + } else { + // get lo portion + uint32_t Lo = Lo_32(Value); + // same as 32 bit value + Count = CountLeadingZeros_32(Lo)+32; + } + } +#endif + return Count; +} + +/// CountTrailingZeros_64 - This function performs the platform optimal form +/// of counting the number of zeros from the least significant bit to the first +/// one bit (64 bit edition.) +/// Returns 64 if the word is zero. +INLINE unsigned CountTrailingZeros_64(uint64_t Value) { +#if __GNUC__ >= 4 + return (Value != 0) ? __builtin_ctzll(Value) : 64; +#else + static const unsigned Mod67Position[] = { + 64, 0, 1, 39, 2, 15, 40, 23, 3, 12, 16, 59, 41, 19, 24, 54, + 4, 64, 13, 10, 17, 62, 60, 28, 42, 30, 20, 51, 25, 44, 55, + 47, 5, 32, 65, 38, 14, 22, 11, 58, 18, 53, 63, 9, 61, 27, + 29, 50, 43, 46, 31, 37, 21, 57, 52, 8, 26, 49, 45, 36, 56, + 7, 48, 35, 6, 34, 33, 0 + }; + return Mod67Position[(uint64_t)(-(int64_t)Value & (int64_t)Value) % 67]; +#endif +} + +/// CountPopulation_64 - this function counts the number of set bits in a value, +/// (64 bit edition.) +INLINE unsigned CountPopulation_64(uint64_t Value) { +#if __GNUC__ >= 4 + return __builtin_popcountll(Value); +#else + uint64_t v = Value - (((Value) >> 1) & 0x5555555555555555ULL); + v = (v & 0x3333333333333333ULL) + (((v) >> 2) & 0x3333333333333333ULL); + v = (v + ((v) >> 4)) & 0x0F0F0F0F0F0F0F0FULL; + return unsigned((uint64_t)(v * 0x0101010101010101ULL) >> 56); +#endif +} + +#endif // LLVM_SUPPORT_MATHEXTRAS_H + + +#ifndef AP_PRIVATE_H +#define AP_PRIVATE_H + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace AESL_std { + template + DataType INLINE min(DataType a, DataType b) { + // if (a >= b) return b; + // else return a; + return (a>=b) ? b : a; + } + + template + DataType INLINE max(DataType a, DataType b) { + // if (a >= b) return a; + // else return b; + return (a>=b) ? a : b; + } +} +enum ap_q_mode { + AP_RND, // rounding to plus infinity + AP_RND_ZERO,// rounding to zero + AP_RND_MIN_INF,// rounding to minus infinity + AP_RND_INF,// rounding to infinity + AP_RND_CONV, // convergent rounding + AP_TRN, // truncation + AP_TRN_ZERO // truncation to zero + +}; +enum ap_o_mode { + AP_SAT, // saturation + AP_SAT_ZERO, // saturation to zero + AP_SAT_SYM, // symmetrical saturation + AP_WRAP, // wrap-around (*) + AP_WRAP_SM // sign magnitude wrap-around (*) +}; + +template struct ap_fixed_base; +template struct af_range_ref; +template struct af_bit_ref; + +template struct ap_range_ref; +template struct ap_bit_ref; +template struct ap_concat_ref; +static bool InvalidDigit(const char* str, unsigned len, unsigned start, unsigned radix) { + unsigned i; + for (i = start; i < len; ++i) + if ((radix == 2 && (str[i] == '0' || str[i] == '1')) || + (radix == 8 && str[i] >= '0' && str[i] <= '7') || + (radix == 10 && str[i] >= '0' && str[i] <= '9') || + (radix == 16 && ((str[i] >= '0' && str[i] <= '9') || + (str[i] >= 'a' && str[i] <= 'f') || + (str[i] >= 'A' && str[i] <= 'F')))) + continue; + else + return true; + return false; +} + +static void ap_parse_sign(const char* str, uint32_t &base, bool &neg) { + if (str[0] == '+' || str[0] == '-') base = 1; + if (str[0] == '-') neg = true; + else neg = false; + return; +} + +static void ap_parse_prefix(const char* str, uint32_t &offset, uint32_t &radix) { + if (str[0] == '0') { + switch (str[1]) { + case 'b': + case 'B': offset = 2; radix = 2; break; + case 'x': + case 'X': offset = 2; radix = 16; break; + case 'd': + case 'D': offset = 2; radix = 10; break; + case 'o': + case 'O': offset = 2; radix = 8; break; + default: break; + } + } + if (offset == 0) + for (int i=0, len = strlen(str); i= 'a') || (str[i] <= 'F' && str[i] >= 'A')) { + radix = 16; + break; + } + return; +} + +/// sub_1 - This function subtracts a single "digit" (64-bit word), y, from +/// the multi-digit integer array, x[], propagating the borrowed 1 value until +/// no further borrowing is neeeded or it runs out of "digits" in x. The result +/// is 1 if "borrowing" exhausted the digits in x, or 0 if x was not exhausted. +/// In other words, if y > x then this function returns 1, otherwise 0. +/// @returns the borrow out of the subtraction +static bool sub_1(uint64_t x[], uint32_t len, uint64_t y) { + for (uint32_t i = 0; i < len; ++i) { + uint64_t __X = x[i]; + x[i] -= y; + if (y > __X) + y = 1; // We have to "borrow 1" from next "digit" + else { + y = 0; // No need to borrow + break; // Remaining digits are unchanged so exit early + } + } + return (y != 0); +} + + /// This enumeration just provides for internal constants used in this + /// translation unit. + enum { + MIN_INT_BITS = 1, ///< Minimum number of bits that can be specified + ///< Note that this must remain synchronized with IntegerType::MIN_INT_BITS + MAX_INT_BITS = (1<<23)-1 ///< Maximum number of bits that can be specified + ///< Note that this must remain synchronized with IntegerType::MAX_INT_BITS + }; + + /// A utility function for allocating memory and checking for allocation + /// failure. The content is not zeroed. + static uint64_t* getMemory(uint32_t numWords) { + return (uint64_t*) malloc(numWords*sizeof(uint64_t)); + } + + //===----------------------------------------------------------------------===// + // ap_private Class + //===----------------------------------------------------------------------===// + + /// ap_private - This class represents arbitrary precision constant integral values. + /// It is a functional replacement for common case unsigned integer type like + /// "unsigned", "unsigned long" or "uint64_t", but also allows non-byte-width + /// integer sizes and large integer value types such as 3-bits, 15-bits, or more + /// than 64-bits of precision. ap_private provides a variety of arithmetic operators + /// and methods to manipulate integer values of any bit-width. It supports both + /// the typical integer arithmetic and comparison operations as well as bitwise + /// manipulation. + /// + /// The class has several invariants worth noting: + /// * All bit, byte, and word positions are zero-based. + /// * Once the bit width is set, it doesn't change except by the Truncate, + /// SignExtend, or ZeroExtend operations. + /// * All binary operators must be on ap_private instances of the same bit width. + /// Attempting to use these operators on instances with different bit + /// widths will yield an assertion. + /// * The value is stored canonically as an unsigned value. For operations + /// where it makes a difference, there are both signed and unsigned variants + /// of the operation. For example, sdiv and udiv. However, because the bit + /// widths must be the same, operations such as Mul and Add produce the same + /// results regardless of whether the values are interpreted as signed or + /// not. + /// * In general, the class tries to follow the style of computation that LLVM + /// uses in its IR. This simplifies its use for LLVM. + /// + /// @brief Class for arbitrary precision integers. + template class ap_private; + namespace ap_private_ops{ + template + INLINE ap_private<_AP_W, _AP_S, _AP_N> lshr(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, uint32_t shiftAmt); + template + INLINE ap_private<_AP_W, _AP_S, _AP_N> shl(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, uint32_t shiftAmt); + } + +#if defined(_MSC_VER) +# if _MSC_VER < 1400 && !defined(for) +# define for if(0);else for +# endif + typedef unsigned __int64 ap_ulong; + typedef signed __int64 ap_slong; +#else + typedef unsigned long long ap_ulong; + typedef signed long long ap_slong; +#endif + template struct retval { + }; + template<> struct retval { + typedef ap_slong Type; + }; + template<> struct retval { + typedef ap_ulong Type; + }; + + template + class ap_private { +#ifdef _MSC_VER +#pragma warning( disable : 4521 4522 ) +#endif +public: + typedef typename retval<_AP_S>::Type ValType; + template friend struct ap_fixed_base; + ///return type of variety of operations + //---------------------------------------------------------- + template + struct RType { + enum { + mult_w = _AP_W+_AP_W2, + mult_s = _AP_S||_AP_S2, + plus_w = AP_MAX(_AP_W+(_AP_S2&&!_AP_S),_AP_W2+(_AP_S&&!_AP_S2))+1, + plus_s = _AP_S||_AP_S2, + minus_w = AP_MAX(_AP_W+(_AP_S2&&!_AP_S),_AP_W2+(_AP_S&&!_AP_S2))+1, + minus_s = true, + div_w = _AP_W+_AP_S2, + div_s = _AP_S||_AP_S2, + mod_w = AP_MIN(_AP_W,_AP_W2+(!_AP_S2&&_AP_S)), + mod_s = _AP_S, + logic_w = AP_MAX(_AP_W+(_AP_S2&&!_AP_S),_AP_W2+(_AP_S&&!_AP_S2)), + logic_s = _AP_S||_AP_S2 + }; + typedef ap_private mult; + typedef ap_private plus; + typedef ap_private minus; + typedef ap_private logic; + typedef ap_private div; + typedef ap_private mod; + typedef ap_private<_AP_W, _AP_S> arg1; + typedef bool reduce; + }; + + INLINE void report() { +#if 0 + if (_AP_W > 1024 && _AP_W <= 4096) { + fprintf(stderr, "[W] W=%d is out of bound (1<=W<=1024): for" + " synthesis: please define macro AP_INT_TYPE_EXT(N)" + " to extend the valid range.\n", _AP_W); + } else +#endif + if (_AP_W > MAX_MODE(AP_INT_MAX_W) * 1024) { + fprintf(stderr, "[E] ap_%sint<%d>: Bitwidth exceeds the " + "default max value %d. Please use macro " + "AP_INT_MAX_W to set a larger max value.\n", + _AP_S?"":"u", _AP_W, + MAX_MODE(AP_INT_MAX_W) * 1024); + exit(1); + } + } + + enum { BitWidth = _AP_W }; + /// This union is used to store the integer value. When the + /// integer bit-width <= 64, it uses VAL, otherwise it uses pVal. + + /// This enum is used to hold the constants we needed for ap_private. + uint64_t VAL; ///< Used to store the <= 64 bits integer value. + uint64_t pVal[_AP_N]; ///< Used to store the >64 bits integer value. + + /// This enum is used to hold the constants we needed for ap_private. + enum { + APINT_BITS_PER_WORD = sizeof(uint64_t) * 8, ///< Bits in a word + APINT_WORD_SIZE = sizeof(uint64_t) ///< Byte size of a word + }; + + enum { excess_bits = (_AP_W%APINT_BITS_PER_WORD) ? APINT_BITS_PER_WORD -(_AP_W%APINT_BITS_PER_WORD) : 0}; + static const uint64_t mask = ((uint64_t)~0ULL >> (excess_bits)); + + /// This constructor is used only internally for speed of construction of + /// temporaries. It is unsafe for general use so it is not public. + /* Constructors */ + + ap_private(const char* val) { + std::string str(val); + uint32_t strLen = str.length(); + const char *strp = str.c_str(); + uint32_t offset = 0; + uint32_t base = 0; + bool neg = false; + uint32_t radix = 16; + ap_parse_sign(strp, base, neg); + ap_parse_prefix(strp + base, offset, radix); + + if ((radix != 10 && neg) || + (strLen - base - offset <= 0) || + InvalidDigit(strp, strLen, base + offset, radix)) { + fprintf(stderr, "invalid character string %s !\n", val); + assert(0); + } + + ap_private ap_private_val(str.c_str(), strLen, radix, base, offset); + if (neg) + ap_private_val = -ap_private_val; + operator = (ap_private_val); + report(); + } + + ap_private(const char* val, int rd) { + std::string str(val); + uint32_t strLen = str.length(); + const char *strp = str.c_str(); + uint32_t offset = 0; + uint32_t base = 0; + uint32_t radix = rd; + bool neg = false; + ap_parse_sign(strp, base, neg); + ap_parse_prefix(strp + base, offset, radix); + + if ((radix != 10 && neg) || + (strLen - base - offset <= 0) || + InvalidDigit(strp, strLen, base + offset, radix)) { + fprintf(stderr, "invalid character string %s !\n", val); + assert(0); + } + + // uint32_t bitsNeeded = ap_private<_AP_W, _AP_S>::getBitsNeeded(strp, strLen, radix); + // ap_private<_AP_W, _AP_S> ap_private_val(bitsNeeded, strp , strLen, radix, base, offset); + ap_private ap_private_val(strp , strLen, radix, base, offset); + if (neg) + ap_private_val = -ap_private_val; + operator = (ap_private_val); + report(); + } + + /// Note that numWords can be smaller or larger than the corresponding bit + /// width but any extraneous bits will be dropped. + /// @param numBits the bit width of the constructed ap_private + /// @param numWords the number of words in bigVal + /// @param bigVal a sequence of words to form the initial value of the ap_private + /// @brief Construct an ap_private of numBits width, initialized as bigVal[]. + ap_private(uint32_t numWords, const uint64_t bigVal[]): VAL(0) { + assert(bigVal && "Null pointer detected!"); + { + // Get memory, cleared to 0 + memset(pVal, 0, _AP_N * sizeof(uint64_t)); + + // Calculate the number of words to copy + uint32_t words = AESL_std::min(numWords, _AP_N); + // Copy the words from bigVal to pVal + memcpy(pVal, bigVal, words * APINT_WORD_SIZE); + if (words >= _AP_W) + clearUnusedBits(); + // Make sure unused high bits are cleared + } + } + + /// This constructor interprets Val as a string in the given radix. The + /// interpretation stops when the first charater that is not suitable for the + /// radix is encountered. Acceptable radix values are 2, 8, 10 and 16. It is + /// an error for the value implied by the string to require more bits than + /// numBits. + /// @param numBits the bit width of the constructed ap_private + /// @param val the string to be interpreted + /// @param radix the radix of Val to use for the intepretation + /// @brief Construct an ap_private from a string representation. + ap_private(const std::string& val, uint8_t radix=2, int base=0, int offset=0): VAL(0) { + assert(!val.empty() && "The input string is empty."); + const char *c_str = val.c_str(); + fromString(c_str+base+offset, val.size()-base-offset, radix); + } + + /// This constructor interprets the slen characters starting at StrStart as + /// a string in the given radix. The interpretation stops when the first + /// character that is not suitable for the radix is encountered. Acceptable + /// radix values are 2, 8, 10 and 16. It is an error for the value implied by + /// the string to require more bits than numBits. + /// @param numBits the bit width of the constructed ap_private + /// @param strStart the start of the string to be interpreted + /// @param slen the maximum number of characters to interpret + /// @param radix the radix to use for the conversion + /// @brief Construct an ap_private from a string representation. + /// This method does not consider whether it is negative or not. + ap_private(const char strStart[], uint32_t slen, uint8_t radix, int base=0, int offset=0) : VAL(0) { + fromString(strStart+base+offset, slen-base-offset, radix); + } + + template + INLINE ap_private(const ap_range_ref<_AP_W2,_AP_S2>& ref) { + *this=ref.get(); + report(); + } + + template + INLINE ap_private(const ap_bit_ref<_AP_W2,_AP_S2>& ref) { + *this = ((uint64_t)(bool)ref); + report(); + } + + template + INLINE ap_private(const ap_concat_ref<_AP_W2, _AP_T2,_AP_W3, _AP_T3>& ref) { + *this=ref.get(); + report(); + } + + template + INLINE ap_private(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2> &val) { + *this = ((val.operator ap_private<_AP_W2, false> ())); + report(); + } + + template + INLINE ap_private(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2> &val) { + *this = (uint64_t)(bool)val; + report(); + } + + /// Simply makes *this a copy of that. + /// @brief Copy Constructor. + template + ap_private(const volatile ap_private<_AP_W1, _AP_S1, _AP_N1>& that): VAL(0) { + operator = (const_cast& >(that)); + } + + template + ap_private(const ap_private<_AP_W1, _AP_S1, _AP_N1>& that): VAL(0) { + operator = (that); + } + + template + explicit ap_private(const ap_private<_AP_W1, _AP_S1, 1>& that): VAL(0) { + static const uint64_t that_sign_ext_mask = (_AP_W1==APINT_BITS_PER_WORD)?0:~0ULL>>(_AP_W1%APINT_BITS_PER_WORD)<<(_AP_W1%APINT_BITS_PER_WORD); + if (that.isNegative()) { + pVal[0] = that.VAL|that_sign_ext_mask; + memset(pVal+1, ~0, sizeof(uint64_t)*(_AP_N-1)); + } else { + pVal[0] = that.VAL; + memset(pVal+1, 0, sizeof(uint64_t)*(_AP_N-1)); + } + clearUnusedBits(); + } + + ap_private(const ap_private& that): VAL(0) { + memcpy(pVal, that.pVal, _AP_N * APINT_WORD_SIZE); + clearUnusedBits(); + } + + /// @brief Destructor. + virtual ~ap_private() {} + + /// Default constructor that creates an uninitialized ap_private. This is useful + /// for object deserialization (pair this with the static method Read). + ap_private(){memset(pVal, 0, sizeof(uint64_t)*(_AP_N));} + + ap_private(uint64_t* val, uint32_t bits=_AP_W) {assert(0);} + ap_private(const uint64_t *const val, uint32_t bits) {assert(0);} + + /// @name Constructors + /// @{ + /// If isSigned is true then val is treated as if it were a signed value + /// (i.e. as an int64_t) and the appropriate sign extension to the bit width + /// will be done. Otherwise, no sign extension occurs (high order bits beyond + /// the range of val are zero filled). + /// @param numBits the bit width of the constructed ap_private + /// @param val the initial value of the ap_private + /// @param isSigned how to treat signedness of val + /// @brief Create a new ap_private of numBits width, initialized as val. +#define CTOR(TYPE, SIGNED) \ + ap_private(TYPE val, bool isSigned=SIGNED) { \ + pVal[0] = val; \ + if (isSigned && int64_t(pVal[0]) < 0) { \ + memset(pVal+1, ~0, sizeof(uint64_t)*(_AP_N-1)); \ + } else { \ + memset(pVal+1, 0, sizeof(uint64_t)*(_AP_N-1)); \ + } \ + clearUnusedBits(); \ + } +#if 1 + CTOR(int, true) + CTOR(bool, false) + CTOR(signed char, true) + CTOR(unsigned char, false) + CTOR(short, true) + CTOR(unsigned short, false) + CTOR(unsigned int, false) + CTOR(long, true) + CTOR(unsigned long, false) + CTOR(unsigned long long, false) + CTOR(long long, true) + CTOR(float, false) + CTOR(double, false) +#undef CTOR +#else + CTOR(uint64_t) +#undef CTOR +#endif + + + /// @returns true if the number of bits <= 64, false otherwise. + /// @brief Determine if this ap_private just has one word to store value. + INLINE bool isSingleWord() const { + return false; + } + + /// @returns the word position for the specified bit position. + /// @brief Determine which word a bit is in. + static uint32_t whichWord(uint32_t bitPosition) { + // return bitPosition / APINT_BITS_PER_WORD; + return (bitPosition) >> 6; + } + + /// @returns the bit position in a word for the specified bit position + /// in the ap_private. + /// @brief Determine which bit in a word a bit is in. + static uint32_t whichBit(uint32_t bitPosition) { + // return bitPosition % APINT_BITS_PER_WORD; + return bitPosition & 0x3f; + } + + /// bit at a specific bit position. This is used to mask the bit in the + /// corresponding word. + /// @returns a uint64_t with only bit at "whichBit(bitPosition)" set + /// @brief Get a single bit mask. + static uint64_t maskBit(uint32_t bitPosition) { + return 1ULL << (whichBit(bitPosition)); + } + + /// @returns the corresponding word for the specified bit position. + /// @brief Get the word corresponding to a bit position + INLINE uint64_t getWord(uint32_t bitPosition) const { + return isSingleWord() ? VAL : pVal[whichWord(bitPosition)]; + } + + /// This method is used internally to clear the to "N" bits in the high order + /// word that are not used by the ap_private. This is needed after the most + /// significant word is assigned a value to ensure that those bits are + /// zero'd out. + /// @brief Clear unused high order bits + INLINE void clearUnusedBits(void) { + pVal[_AP_N-1] = _AP_S ? ((((int64_t)pVal[_AP_N-1])<<(excess_bits))>> excess_bits) : (excess_bits ? ((pVal[_AP_N-1])<<(excess_bits))>>(excess_bits) : pVal[_AP_N-1]); + } + + INLINE void clearUnusedBitsToZero(void) { + pVal[_AP_N-1] &= mask; + } + + INLINE void clearUnusedBitsToOne(void) { + pVal[_AP_N-1] |= mask; + } + + /// This is used by the constructors that take string arguments. + /// @brief Convert a char array into an ap_private + INLINE void fromString(const char *strStart, uint32_t slen, + uint8_t radix) ; + + INLINE ap_private read() volatile { + return *this; + } + + INLINE void write(const ap_private& op2) volatile { + *this = (op2); + } + + //Explicit conversions to C interger types + //----------------------------------------------------------- + operator ValType() const { + return getVal(); + } + + INLINE ValType getVal() const{ + return *pVal; + } + + INLINE int to_int() const { + return int(*this); + } + + INLINE unsigned to_uint() const { + return (unsigned) getVal(); + } + + INLINE long to_long() const { + return (long) getVal(); + } + + INLINE unsigned long to_ulong() const { + return (unsigned long) getVal(); + } + + INLINE ap_slong to_int64() const { + return (ap_slong) getVal(); + } + + INLINE ap_ulong to_uint64() const { + return (ap_ulong) getVal(); + } + + INLINE double to_double() const { + if (isNegative()) + return roundToDouble(true); + else + return roundToDouble(false); + } + + INLINE unsigned length() const { return _AP_W; } + + /*Reverse the contents of ap_private instance. I.e. LSB becomes MSB and vise versa*/ + INLINE ap_private& reverse () { + for (int i = 0; i < _AP_W/2; ++i) { + bool tmp = operator[](i); + if (operator[](_AP_W - 1 - i)) + set(i); + else + clear(i); + if (tmp) + set(_AP_W - 1 - i); + else + clear(_AP_W - 1 - i); + } + clearUnusedBits(); + return *this; + } + + /*Return true if the value of ap_private instance is zero*/ + INLINE bool iszero () const { + return isMinValue(); + } + + /* x < 0 */ + INLINE bool sign () const { + if (isNegative()) + return true; + return false; + } + + /* x[i] = !x[i] */ + INLINE void invert (int i) { + assert( i >= 0 && "Attempting to read bit with negative index"); + assert( i < _AP_W && "Attempting to read bit beyond MSB"); + flip(i); + } + + /* x[i] */ + INLINE bool test (int i) const { + assert( i >= 0 && "Attempting to read bit with negative index"); + assert( i < _AP_W && "Attempting to read bit beyond MSB"); + return operator[](i); + } + + //Set the ith bit into v + INLINE void set (int i, bool v) { + assert( i >= 0 && "Attempting to write bit with negative index"); + assert( i < _AP_W && "Attempting to write bit beyond MSB"); + v ? set(i) : clear(i); + } + + //Set the ith bit into v + INLINE void set_bit (int i, bool v) { + assert( i >= 0 && "Attempting to write bit with negative index"); + assert( i < _AP_W && "Attempting to write bit beyond MSB"); + v ? set(i) : clear(i); + } + + INLINE ap_private& set(uint32_t bitPosition) { + pVal[whichWord(bitPosition)] |= maskBit(bitPosition); + clearUnusedBits(); + return *this; + } + + INLINE void set() { + for (uint32_t i = 0; i < _AP_N; ++i) + pVal[i] = ~0ULL; + clearUnusedBits(); + } + + //Get the value of ith bit + INLINE bool get (int i) const { + assert( i >= 0 && "Attempting to read bit with negative index"); + assert( i < _AP_W && "Attempting to read bit beyond MSB"); + return operator [](i); + } + + //Get the value of ith bit + INLINE bool get_bit (int i) const { + assert( i >= 0 && "Attempting to read bit with negative index"); + assert( i < _AP_W && "Attempting to read bit beyond MSB"); + return operator [](i); + } + + //This is used for sc_lv and sc_bv, which is implemented by sc_uint + //Rotate an ap_private object n places to the left + INLINE void lrotate(int n) { + assert( n >= 0 && "Attempting to shift negative index"); + assert( n < _AP_W && "Shift value larger than bit width"); + operator = (shl(n) | lshr(_AP_W - n)); + } + + //This is used for sc_lv and sc_bv, which is implemented by sc_uint + //Rotate an ap_private object n places to the right + INLINE void rrotate(int n) { + assert( n >= 0 && "Attempting to shift negative index"); + assert( n < _AP_W && "Shift value larger than bit width"); + operator = (lshr(n) | shl(_AP_W - n)); + } + + /// Set the given bit to 0 whose position is given as "bitPosition". + /// @brief Set a given bit to 0. + ap_private& clear(uint32_t bitPosition) { + pVal[whichWord(bitPosition)] &= ~maskBit(bitPosition); + clearUnusedBits(); + return *this; + } + + /// @brief Set every bit to 0. + void clear() { + memset(pVal, 0, _AP_N * APINT_WORD_SIZE); + } + + /// @brief Toggle every bit to its opposite value. + ap_private& flip() { + for (uint32_t i = 0; i < _AP_N; ++i) + pVal[i] ^= ~0ULL; + clearUnusedBits(); + return *this; + } + + /// Toggle a given bit to its opposite value whose position is given + /// as "bitPosition". + /// @brief Toggles a given bit to its opposite value. + ap_private& flip(uint32_t bitPosition) { + assert(bitPosition < BitWidth && "Out of the bit-width range!"); + if ((*this)[bitPosition]) clear(bitPosition); + else set(bitPosition); + return *this; + } + + //complements every bit + INLINE void b_not() { + flip(); + } + + ap_private getLoBits(uint32_t numBits) const { + return ap_private_ops::lshr(ap_private_ops::shl(*this, _AP_W - numBits), + _AP_W - numBits); + } + + ap_private getHiBits(uint32_t numBits) const { + return ap_private_ops::lshr(*this, _AP_W - numBits); + } + + //Binary Arithmetic + //----------------------------------------------------------- + + template + INLINE ap_private + operator & (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) { + return *this & a2.get(); + } + + template + INLINE ap_private + operator | (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) { + return *this | a2.get(); + } + + template + INLINE ap_private + operator ^ (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) { + return *this ^ a2.get(); + } + + + ///Arithmetic assign + //------------------------------------------------------------- + +#define OP_BIN_LOGIC_ASSIGN_AP(Sym) \ + template \ + INLINE ap_private& operator Sym(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { \ + uint32_t numWords = AESL_std::min(_AP_N, _AP_N1); \ + uint32_t i; \ + for (i = 0; i < numWords; ++i) \ + pVal[i] Sym RHS.pVal[i]; \ + if (_AP_N1 < _AP_N) { \ + uint64_t ext = RHS.isNegative()?~0ULL:0; \ + for (;i<_AP_N; i++) \ + pVal[i] Sym ext; \ + } \ + clearUnusedBits(); \ + return *this; \ + } + + OP_BIN_LOGIC_ASSIGN_AP(&=); + OP_BIN_LOGIC_ASSIGN_AP(|=); + OP_BIN_LOGIC_ASSIGN_AP(^=); +#undef OP_BIN_LOGIC_ASSIGN_AP + + /// Adds the RHS APint to this ap_private. + /// @returns this, after addition of RHS. + /// @brief Addition assignment operator. + template + INLINE ap_private& operator+=(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { + add(pVal, pVal, RHS.pVal, _AP_N, _AP_N, _AP_N1, _AP_S, _AP_S1); + clearUnusedBits(); + return *this; + } + + template + INLINE ap_private& operator-=(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { + sub(pVal, pVal, RHS.pVal, _AP_N, _AP_N, _AP_N1, _AP_S, _AP_S1); + clearUnusedBits(); + return *this; + } + + template + ap_private& operator*=(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { + // Get some bit facts about LHS and check for zero + uint32_t lhsBits = getActiveBits(); + uint32_t lhsWords = !lhsBits ? 0 : whichWord(lhsBits - 1) + 1; + if (!lhsWords) { + // 0 * X ===> 0 + return *this; + } + + ap_private dupRHS = RHS; + // Get some bit facts about RHS and check for zero + uint32_t rhsBits = dupRHS.getActiveBits(); + uint32_t rhsWords = !rhsBits ? 0 : whichWord(rhsBits - 1) + 1; + if (!rhsWords) { + // X * 0 ===> 0 + clear(); + return *this; + } + + // Allocate space for the result + uint32_t destWords = rhsWords + lhsWords; + uint64_t *dest = getMemory(destWords); + + // Perform the long multiply + mul(dest, pVal, lhsWords, dupRHS.pVal, rhsWords, destWords); + + // Copy result back into *this + clear(); + uint32_t wordsToCopy = destWords >= _AP_N ? _AP_N : destWords; + + memcpy(pVal, dest, wordsToCopy* APINT_WORD_SIZE); + + uint64_t ext = (isNegative() ^ RHS.isNegative()) ? ~0ULL : 0ULL; + for (int i=wordsToCopy; i<_AP_N; i++) + pVal[i]=ext; + clearUnusedBits(); + // delete dest array and return + free(dest); + return *this; + } + +#define OP_ASSIGN_AP(Sym) \ + template \ + INLINE ap_private& operator Sym##=(const ap_private<_AP_W2,_AP_S2>& op) \ + { \ + *this=operator Sym (op); \ + return *this; \ + } \ + + OP_ASSIGN_AP(/) + OP_ASSIGN_AP(%) +#undef OP_ASSIGN_AP + +#define OP_BIN_LOGIC_AP(Sym) \ + template \ + INLINE \ + typename RType<_AP_W1, _AP_S1>::logic \ + operator Sym (const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) const { \ + enum { numWords = (RType<_AP_W1, _AP_S1>::logic_w +APINT_BITS_PER_WORD-1)/APINT_BITS_PER_WORD}; \ + typename RType<_AP_W1, _AP_S1>::logic Result; \ + uint64_t *val = Result.pVal; \ + uint32_t i; \ + uint32_t min_N = std::min(_AP_N, _AP_N1); \ + uint32_t max_N = std::max(_AP_N, _AP_N1); \ + for (i = 0; i < min_N; ++i) \ + val[i] = pVal[i] Sym RHS.pVal[i]; \ + if (numWords > i) { \ + const uint64_t* tmpVal = (_AP_N>_AP_N1 ? pVal : RHS.pVal)+i; \ + uint64_t ext = ((_AP_N<_AP_N1 && isNegative() )||(_AP_N1 < _AP_N && RHS.isNegative())) ? ~0ULL : 0; \ + for (;i i) { \ + uint64_t ext2 = ((_AP_N>_AP_N1 && isNegative() )||(_AP_N1 > _AP_N && RHS.isNegative())) ? ~0ULL : 0; \ + val[i] = ext Sym ext2; \ + } \ + } \ + Result.clearUnusedBits(); \ + return Result; \ + } + + OP_BIN_LOGIC_AP(|); + OP_BIN_LOGIC_AP(&); + OP_BIN_LOGIC_AP(^); + +#undef OP_BIN_LOGIC_AP + + template + INLINE typename RType<_AP_W1,_AP_S1>::plus operator+(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) const { + // assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + typename RType<_AP_W1,_AP_S1>::plus Result; + bool carry = add(Result.pVal, this->pVal, RHS.pVal, (RType<_AP_W1,_AP_S1>::plus_w + 63) / 64, _AP_N, _AP_N1, _AP_S, _AP_S1); + if ((RType<_AP_W1,_AP_S1>::plus_w + 63) / 64> std::max(_AP_W, _AP_W1) ) + Result.pVal[(RType<_AP_W1,_AP_S1>::plus_w + 63)/64 - 1] = carry; + Result.clearUnusedBits(); + return Result; + } + + template + INLINE typename RType<_AP_W1,_AP_S1>::minus operator-(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) const { + typename RType<_AP_W1,_AP_S1>::minus Result; + bool borrow = sub(Result.pVal, this->pVal, RHS.pVal, (RType<_AP_W1,_AP_S1>::minus_w + 63) / 64, _AP_N, _AP_N1, _AP_S, _AP_S1); + if ((RType<_AP_W1,_AP_S1>::minus_w + 63) / 64 > AESL_std::max(_AP_W, _AP_W1) ) { + Result.pVal[(RType<_AP_W1,_AP_S1>::minus_w+63)/64 - 1] = borrow; + } + Result.clearUnusedBits(); + return Result; + } + + template + typename RType<_AP_W1, _AP_S1>::mult operator*(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) const { + + // Get some bit facts about LHS and check for zero + uint32_t lhsBits = getActiveBits(); + uint32_t lhsWords = !lhsBits ? 0 : whichWord(lhsBits - 1) + 1; + if (!lhsWords) + // 0 * X ===> 0 + return typename RType<_AP_W1, _AP_S1>::mult(); + + // Get some bit facts about RHS and check for zero + uint32_t rhsBits = RHS.getActiveBits(); + uint32_t rhsWords = !rhsBits ? 0 : whichWord(rhsBits - 1) + 1; + if (!rhsWords) { + // X * 0 ===> 0 + return typename RType<_AP_W1, _AP_S1>::mult(); + } + + //extend size to avoid result loss + typename RType<_AP_W1, _AP_S1>::mult dupLHS = *this; + typename RType<_AP_W1, _AP_S1>::mult dupRHS = RHS; + lhsBits = dupLHS.getActiveBits(); + lhsWords = !lhsBits ? 0 : whichWord(lhsBits - 1) + 1; + rhsBits = dupRHS.getActiveBits(); + rhsWords = !rhsBits ? 0 : whichWord(rhsBits - 1) + 1; + + // Allocate space for the result + enum { destWords =(RType<_AP_W1, _AP_S1>::mult_w+APINT_BITS_PER_WORD-1)/APINT_BITS_PER_WORD}; + int destw = destWords; + typename RType<_AP_W1, _AP_S1>::mult Result; + uint64_t *dest = Result.pVal; + uint64_t ext = (isNegative() ^ RHS.isNegative()) ? ~0ULL : 0; + + // Perform the long multiply + mul(dest, dupLHS.pVal, lhsWords, dupRHS.pVal, rhsWords, destWords); + + for (int i=lhsWords+rhsWords; i + INLINE typename RType<_AP_W2,_AP_S2>::div + operator / (const ap_private<_AP_W2,_AP_S2>& op) const { + ap_private lhs=ap_private(*this); + ap_private rhs=ap_private(op); + return typename RType<_AP_W2,_AP_S2>::div((_AP_S||_AP_S2)?lhs.sdiv(rhs):lhs.udiv(rhs)); + } + + template + INLINE typename RType<_AP_W2,_AP_S2>::mod + operator % (const ap_private<_AP_W2,_AP_S2>& op) const { + ap_private lhs=*this; + ap_private rhs= op; + typename RType<_AP_W2,_AP_S2>::mod res = typename RType<_AP_W2,_AP_S2>::mod(_AP_S?lhs.srem(rhs):lhs.urem(rhs)); + return res; + } + + template + INLINE ap_private + operator << (const ap_private<_AP_W2, _AP_S2>& op2) const { + uint32_t sh=op2.to_uint(); + return *this << sh; + } + + INLINE ap_private + operator << (uint32_t sh) const { + ap_private r(*this); + bool overflow=(sh>=length()); + if(overflow) + r.clear(); + else + r = ap_private(r.shl(sh)); + return r; + } + + template + INLINE ap_private + operator >> (const ap_private<_AP_W2, _AP_S2>& op2) const { + uint32_t sh = op2.to_uint(); + return *this >> sh; + } + + INLINE ap_private + operator >> (uint32_t sh) const { + ap_private r(*this); + bool overflow=(sh>=_AP_W); + bool neg_v=r.isNegative(); + if(_AP_S) { + if(overflow) + neg_v?r.set():r.clear(); + else + return r.ashr(sh); + } else { + if(overflow) + r.clear(); + else + return r.lshr(sh); + } + return r; + } + + ///Shift assign + //------------------------------------------------------------------ +#define OP_ASSIGN_AP(Sym) \ + template \ + INLINE ap_private& operator Sym##=(int op) \ + { \ + *this = operator Sym (op); \ + return *this; \ + } \ + INLINE ap_private& operator Sym##=(unsigned int op) \ + { \ + *this = operator Sym (op); \ + return *this; \ + } \ + template \ + INLINE ap_private& operator Sym##=(const ap_private<_AP_W2,_AP_S2>& op) \ + { \ + *this = operator Sym (op); \ + return *this; \ + } + OP_ASSIGN_AP(>>) + OP_ASSIGN_AP(<<) +#undef OP_ASSIGN_AP + ///Comparisons + //----------------------------------------------------------------- + bool operator==(const ap_private& RHS) const { + // Get some facts about the number of bits used in the two operands. + uint32_t n1 = getActiveBits(); + uint32_t n2 = RHS.getActiveBits(); + + // If the number of bits isn't the same, they aren't equal + if (n1 != n2) + return false; + + // If the number of bits fits in a word, we only need to compare the low word. + if (n1 <= APINT_BITS_PER_WORD) + return pVal[0] == RHS.pVal[0]; + + // Otherwise, compare everything + for (int i = whichWord(n1 - 1); i >= 0; --i) + if (pVal[i] != RHS.pVal[i]) + return false; + return true; + } + + template + INLINE bool operator == (const ap_private<_AP_W2, _AP_S2>& op) const { + enum { _AP_MAX_W = AP_MAX(_AP_W+(_AP_S||_AP_S2),_AP_W2+(_AP_S||_AP_S2))}; + ap_private<_AP_MAX_W, _AP_S|_AP_S2> lhs(*this); + ap_private<_AP_MAX_W, _AP_S|_AP_S2> rhs(op); + return lhs==rhs; + } + + bool operator==(uint64_t Val) const { + uint32_t n = getActiveBits(); + if (n <= APINT_BITS_PER_WORD) + return pVal[0] == Val; + else + return false; + } + + template + INLINE bool operator != (const ap_private<_AP_W2, _AP_S2>& op) const { + return !(*this==op); + } + + template + INLINE bool operator!=(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return !((*this) == RHS); + } + + INLINE bool operator!=(uint64_t Val) const { + return !((*this) == Val); + } + + + template + INLINE bool operator <= (const ap_private<_AP_W2,_AP_S2>& op) const { + return !(*this>op); + } + + INLINE bool operator <(const ap_private& op) const { + return _AP_S ? slt(op):ult(op); + } + + template + INLINE bool operator < (const ap_private<_AP_W2, _AP_S2>& op) const { + enum { _AP_MAX_W = AP_MAX(_AP_W+(_AP_S||_AP_S2),_AP_W2+(_AP_S||_AP_S2))}; + ap_private<_AP_MAX_W, _AP_S> lhs(*this); + ap_private<_AP_MAX_W, _AP_S2> rhs(op); + if (_AP_S == _AP_S2) + return _AP_S?lhs.slt(rhs):lhs.ult(rhs); + else + if (_AP_S) + if (_AP_W2 >= _AP_W) + return lhs.ult(rhs); + else + return lhs.slt(rhs); + else + if (_AP_W >= _AP_W2) + return lhs.ult(rhs); + else + return lhs.slt(rhs); + } + + template + INLINE bool operator >=(const ap_private<_AP_W2,_AP_S2>& op) const { + return !(*this + INLINE bool operator > (const ap_private<_AP_W2, _AP_S2>& op) const { + enum { _AP_MAX_W = AP_MAX(_AP_W+(_AP_S||_AP_S2),_AP_W2+(_AP_S||_AP_S2))}; + ap_private<_AP_MAX_W, _AP_S> lhs(*this); + ap_private<_AP_MAX_W, _AP_S2> rhs(op); + if (_AP_S == _AP_S2) + return _AP_S?lhs.sgt(rhs):lhs.ugt(rhs); + else + if (_AP_S) + if (_AP_W2 >= _AP_W) + return lhs.ugt(rhs); + else + return lhs.sgt(rhs); + else + if (_AP_W >= _AP_W2) + return lhs.ugt(rhs); + else + return lhs.sgt(rhs); + } + + ///Bit and Part Select + //-------------------------------------------------------------- + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (int Hi, int Lo) { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (int Hi, int Lo) const { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(const_cast*>(this), Hi, Lo); + } + + INLINE ap_range_ref<_AP_W,_AP_S> + range (int Hi, int Lo) const { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>((const_cast*> (this)), Hi, Lo); + } + + INLINE ap_range_ref<_AP_W,_AP_S> + range (int Hi, int Lo) { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + range (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + range (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) const { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(const_cast(this), Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) const { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + return this->range(Hi, Lo); + } + + INLINE ap_bit_ref<_AP_W,_AP_S> operator [] (uint32_t index) { + assert(index >= 0&&"Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S>( *this, index ); + } + + template + INLINE ap_bit_ref<_AP_W,_AP_S> operator [] (const ap_private<_AP_W2,_AP_S2> &index) { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S>( *this, index.to_int() ); + } + + template + INLINE bool operator [] (const ap_private<_AP_W2,_AP_S2>& index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + ap_bit_ref<_AP_W,_AP_S> br =operator [] (index); + return br.to_bool(); + } + + INLINE bool operator [](uint32_t bitPosition) const { + return (maskBit(bitPosition) & (pVal[whichWord(bitPosition)])) != 0; + } + + INLINE ap_bit_ref<_AP_W,_AP_S> bit (int index) { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S>( *this, index ); + } + + template + INLINE ap_bit_ref<_AP_W,_AP_S> bit (const ap_private<_AP_W2,_AP_S2> &index) { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W &&"Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S>( *this, index.to_int() ); + } + + INLINE bool bit (int index) const { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + ap_bit_ref<_AP_W,_AP_S> br(const_cast*>(this), index); + return br.to_bool(); + } + + template + INLINE bool bit (const ap_private<_AP_W2,_AP_S2>& index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + ap_bit_ref<_AP_W,_AP_S> br = bit(index); + return br.to_bool(); + } + + template + INLINE ap_concat_ref<_AP_W,ap_private<_AP_W, _AP_S>,_AP_W2,ap_private<_AP_W2,_AP_S2> > concat(ap_private<_AP_W2,_AP_S2>& a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_private<_AP_W2,_AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W,ap_private<_AP_W, _AP_S>,_AP_W2,ap_private<_AP_W2,_AP_S2> > concat(const ap_private<_AP_W2,_AP_S2>& a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_private<_AP_W2,_AP_S2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (ap_private<_AP_W2, _AP_S2>& a2) { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (ap_private<_AP_W2, _AP_S2>& a2) const { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(const_cast& >(*this), a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (const ap_private<_AP_W2, _AP_S2>& a2) { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(*this, const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (const ap_private<_AP_W2, _AP_S2>& a2) const { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(const_cast& >(*this), const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > + operator, (const ap_range_ref<_AP_W2, _AP_S2> &a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, + ap_range_ref<_AP_W2, _AP_S2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > + operator, (ap_range_ref<_AP_W2, _AP_S2> &a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, + ap_range_ref<_AP_W2, _AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, ap_bit_ref<_AP_W2, _AP_S2> > + operator, (const ap_bit_ref<_AP_W2, _AP_S2> &a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, + ap_bit_ref<_AP_W2, _AP_S2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, ap_bit_ref<_AP_W2, _AP_S2> > + operator, (ap_bit_ref<_AP_W2, _AP_S2> &a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, + ap_bit_ref<_AP_W2, _AP_S2> >(*this, a2); + } + + template + INLINE + ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > + operator, (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE + ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > + operator, (ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) const { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) const { + return ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, a2); + } + + INLINE ap_private<_AP_W,false> get() const { + ap_private<_AP_W,false> ret(*this); + return ret; + } + + template + INLINE void set(const ap_private<_AP_W3, false> & val) { + operator = (ap_private<_AP_W3, _AP_S>(val)); + } + + /// @} + /// @name Value Tests + /// @{ + /// This tests the high bit of this ap_private to determine if it is set. + /// @returns true if this ap_private is negative, false otherwise + /// @brief Determine sign of this ap_private. + INLINE bool isNegative() const { + //just for get rid of warnings + enum {shift = (_AP_W-APINT_BITS_PER_WORD*(_AP_N-1)-1)}; + static const uint64_t mask = 1ULL << (shift); + return _AP_S && (pVal[_AP_N-1]&mask); + } + + /// This tests the high bit of the ap_private to determine if it is unset. + /// @brief Determine if this ap_private Value is positive (not negative). + INLINE bool isPositive() const { + return !isNegative(); + } + + /// This tests if the value of this ap_private is strictly positive (> 0). + /// @returns true if this ap_private is Positive and not zero. + /// @brief Determine if this ap_private Value is strictly positive. + INLINE bool isStrictlyPositive() const { + return isPositive() && (*this) != 0; + } + + /// This checks to see if the value has all bits of the ap_private are set or not. + /// @brief Determine if all bits are set + INLINE bool isAllOnesValue() const { + return countPopulation() == _AP_W; + } + + /// This checks to see if the value of this ap_private is the maximum unsigned + /// value for the ap_private's bit width. + /// @brief Determine if this is the largest unsigned value. + INLINE bool isMaxValue() const { + return countPopulation() == _AP_W; + } + + /// This checks to see if the value of this ap_private is the maximum signed + /// value for the ap_private's bit width. + /// @brief Determine if this is the largest signed value. + INLINE bool isMaxSignedValue() const { + return BitWidth == 1 ? VAL == 0 : + !isNegative() && countPopulation() == _AP_W - 1; + } + + /// This checks to see if the value of this ap_private is the minimum unsigned + /// value for the ap_private's bit width. + /// @brief Determine if this is the smallest unsigned value. + INLINE bool isMinValue() const { + return countPopulation() == 0; + } + + /// This checks to see if the value of this ap_private is the minimum signed + /// value for the ap_private's bit width. + /// @brief Determine if this is the smallest signed value. + INLINE bool isMinSignedValue() const { + return BitWidth == 1 ? VAL == 1 : + isNegative() && countPopulation() == 1; + } + + /// This function returns a pointer to the internal storage of the ap_private. + /// This is useful for writing out the ap_private in binary form without any + /// conversions. + INLINE const uint64_t* getRawData() const { + if (isSingleWord()) + return &VAL; + return &pVal[0]; + } + + ap_private sqrt() const; + + /// @} + /// @Assignment Operators + /// @{ + /// @returns *this after assignment of RHS. + /// @brief Copy assignment operator. + INLINE ap_private& operator=(const ap_private& RHS) { + if (this != &RHS) + memcpy(pVal, RHS.pVal, _AP_N * APINT_WORD_SIZE); + return *this; + } + INLINE ap_private& operator=(const volatile ap_private& RHS) { + if (this != &RHS) + for (int i=0; i<_AP_N; ++i) + pVal[i] = RHS.pVal[i]; + return *this; + } + INLINE volatile ap_private& operator=(const ap_private& RHS) volatile { + if (this != &RHS) + for (int i=0; i<_AP_N; ++i) + pVal[i] = RHS.pVal[i]; + return *this; + } + INLINE volatile ap_private& operator=(const volatile ap_private& RHS) volatile { + if (this != &RHS) + for (int i=0; i<_AP_N; ++i) + pVal[i] = RHS.pVal[i]; + return *this; + } + + template + INLINE ap_private& operator=(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { + if (_AP_S1) + cpSextOrTrunc(RHS); + else + cpZextOrTrunc(RHS); + clearUnusedBits(); + return *this; + } + + template + INLINE ap_private& operator=(const volatile ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { + if (_AP_S1) + cpSextOrTrunc(RHS); + else + cpZextOrTrunc(RHS); + clearUnusedBits(); + return *this; + } + + template + INLINE ap_private& operator=(const ap_private<_AP_W1, _AP_S1, 1>& RHS) { + static const uint64_t that_sign_ext_mask = (_AP_W1==APINT_BITS_PER_WORD)?0:~0ULL>>(_AP_W1%APINT_BITS_PER_WORD)<<(_AP_W1%APINT_BITS_PER_WORD); + if (RHS.isNegative()) { + pVal[0] = RHS.VAL | that_sign_ext_mask; + memset(pVal+1,~0, APINT_WORD_SIZE*(_AP_N-1)); + } else { + pVal[0] = RHS.VAL; + memset(pVal+1, 0, APINT_WORD_SIZE*(_AP_N-1)); + } + clearUnusedBits(); + return *this; + } + + template + INLINE ap_private& operator=(const volatile ap_private<_AP_W1, _AP_S1, 1>& RHS) { + static const uint64_t that_sign_ext_mask = (_AP_W1==APINT_BITS_PER_WORD)?0:~0ULL>>(_AP_W1%APINT_BITS_PER_WORD)<<(_AP_W1%APINT_BITS_PER_WORD); + if (RHS.isNegative()) { + pVal[0] = RHS.VAL | that_sign_ext_mask; + memset(pVal+1,~0, APINT_WORD_SIZE*(_AP_N-1)); + } else { + pVal[0] = RHS.VAL; + memset(pVal+1, 0, APINT_WORD_SIZE*(_AP_N-1)); + } + clearUnusedBits(); + return *this; + } + + /// @} + /// @name Unary Operators + /// @{ + /// @returns a new ap_private value representing *this incremented by one + /// @brief Postfix increment operator. + INLINE const ap_private operator++(int) { + ap_private API(*this); + ++(*this); + return API; + } + + /// @returns *this incremented by one + /// @brief Prefix increment operator. + INLINE ap_private& operator++() { + add_1(pVal, pVal, _AP_N, 1); + clearUnusedBits(); + return *this; + } + + /// @returns a new ap_private representing *this decremented by one. + /// @brief Postfix decrement operator. + INLINE const ap_private operator--(int) { + ap_private API(*this); + --(*this); + return API; + } + + /// @returns *this decremented by one. + /// @brief Prefix decrement operator. + INLINE ap_private& operator--() { + sub_1(pVal, _AP_N, 1); + clearUnusedBits(); + return *this; + } + + /// Performs a bitwise complement operation on this ap_private. + /// @returns an ap_private that is the bitwise complement of *this + /// @brief Unary bitwise complement operator. + INLINE ap_private operator~() const { + ap_private Result(*this); + Result.flip(); + return Result; + } + + /// Negates *this using two's complement logic. + /// @returns An ap_private value representing the negation of *this. + /// @brief Unary negation operator + INLINE typename RType<1,false>::minus operator-() const { + return ap_private<1,false>(0) - (*this); + } + + /// Performs logical negation operation on this ap_private. + /// @returns true if *this is zero, false otherwise. + /// @brief Logical negation operator. + INLINE bool operator !() const { + for (uint32_t i = 0; i < _AP_N; ++i) + if (pVal[i]) + return false; + return true; + } + + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> And(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return this->operator&(RHS); + } + template + INLINE ap_private Or(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return this->operator|(RHS); + } + template + ap_private Xor(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return this->operator^(RHS); + } + + ap_private Mul(const ap_private& RHS) const { + ap_private Result(*this); + Result *= RHS; + return Result; + } + + ap_private Add(const ap_private& RHS) const { + ap_private Result(0); + bool carry = add(Result.pVal, this->pVal, RHS.pVal, _AP_N, _AP_N, _AP_N, _AP_S, _AP_S); + Result.clearUnusedBits(); + return Result; + } + + ap_private Sub(const ap_private& RHS) const { + ap_private Result(0); + sub(Result.pVal, this->pVal, RHS.pVal, _AP_N, _AP_N, _AP_N, _AP_S, _AP_S); + Result.clearUnusedBits(); + return Result; + } + + /// Arithmetic right-shift this ap_private by shiftAmt. + /// @brief Arithmetic right-shift function. + ap_private ashr(uint32_t shiftAmt) const { + assert(shiftAmt <= BitWidth && "Invalid shift amount, too big"); + // Handle a degenerate case + if (shiftAmt == 0) + return *this; + + // Handle single word shifts with built-in ashr + if (isSingleWord()) { + if (shiftAmt == BitWidth) + return ap_private(/*BitWidth, 0*/); // undefined + else { + uint32_t SignBit = APINT_BITS_PER_WORD - BitWidth; + return ap_private(/*BitWidth,*/ + (((int64_t(VAL) << (SignBit)) >> (SignBit)) >> (shiftAmt))); + } + } + + // If all the bits were shifted out, the result is, technically, undefined. + // We return -1 if it was negative, 0 otherwise. We check this early to avoid + // issues in the algorithm below. + if (shiftAmt == BitWidth) { + if (isNegative()) + return ap_private(-1); + else + return ap_private(0); + } + + // Create some space for the result. + ap_private Retval(0); + uint64_t * val = Retval.pVal; + + // Compute some values needed by the following shift algorithms + uint32_t wordShift = shiftAmt % APINT_BITS_PER_WORD; // bits to shift per word + uint32_t offset = shiftAmt / APINT_BITS_PER_WORD; // word offset for shift + uint32_t breakWord = _AP_N - 1 - offset; // last word affected + uint32_t bitsInWord = whichBit(BitWidth); // how many bits in last word? + if (bitsInWord == 0) + bitsInWord = APINT_BITS_PER_WORD; + + // If we are shifting whole words, just move whole words + if (wordShift == 0) { + // Move the words containing significant bits + for (uint32_t i = 0; i <= breakWord; ++i) + val[i] = pVal[i+offset]; // move whole word + + // Adjust the top significant word for sign bit fill, if negative + if (isNegative()) + if (bitsInWord < APINT_BITS_PER_WORD) + val[breakWord] |= ~0ULL << (bitsInWord); // set high bits + } else { + // Shift the low order words + for (uint32_t i = 0; i < breakWord; ++i) { + // This combines the shifted corresponding word with the low bits from + // the next word (shifted into this word's high bits). + val[i] = ((pVal[i+offset]) >> (wordShift)); + val[i] |= ((pVal[i+offset+1]) << (APINT_BITS_PER_WORD - wordShift)); + } + + // Shift the break word. In this case there are no bits from the next word + // to include in this word. + val[breakWord] = (pVal[breakWord+offset]) >> (wordShift); + + // Deal with sign extenstion in the break word, and possibly the word before + // it. + if (isNegative()) { + if (wordShift > bitsInWord) { + if (breakWord > 0) + val[breakWord-1] |= + ~0ULL << (APINT_BITS_PER_WORD - (wordShift - bitsInWord)); + val[breakWord] |= ~0ULL; + } else + val[breakWord] |= (~0ULL << (bitsInWord - wordShift)); + } + } + + // Remaining words are 0 or -1, just assign them. + uint64_t fillValue = (isNegative() ? ~0ULL : 0); + for (uint32_t i = breakWord+1; i < _AP_N; ++i) + val[i] = fillValue; + Retval.clearUnusedBits(); + return Retval; + } + + /// Logical right-shift this ap_private by shiftAmt. + /// @brief Logical right-shift function. + ap_private lshr(uint32_t shiftAmt) const { + if (isSingleWord()) { + if (shiftAmt == BitWidth) + return ap_private(0); + else + return ap_private((this->VAL) >> (shiftAmt)); + } + + // If all the bits were shifted out, the result is 0. This avoids issues + // with shifting by the size of the integer type, which produces undefined + // results. We define these "undefined results" to always be 0. + if (shiftAmt == BitWidth) + return ap_private(0); + + // If none of the bits are shifted out, the result is *this. This avoids + // issues with shifting byt he size of the integer type, which produces + // undefined results in the code below. This is also an optimization. + if (shiftAmt == 0) + return *this; + + // Create some space for the result. + ap_private Retval(0); + uint64_t * val = Retval.pVal; + + // If we are shifting less than a word, compute the shift with a simple carry + if (shiftAmt < APINT_BITS_PER_WORD) { + uint64_t carry = 0; + for (int i = _AP_N-1; i >= 0; --i) { + val[i] = ((pVal[i]) >> (shiftAmt)) | carry; + carry = (pVal[i]) << (APINT_BITS_PER_WORD - shiftAmt); + } + Retval.clearUnusedBits(); + return Retval; + } + + // Compute some values needed by the remaining shift algorithms + uint32_t wordShift = shiftAmt % APINT_BITS_PER_WORD; + uint32_t offset = shiftAmt / APINT_BITS_PER_WORD; + + // If we are shifting whole words, just move whole words + if (wordShift == 0) { + for (uint32_t i = 0; i < _AP_N - offset; ++i) + val[i] = pVal[i+offset]; + for (uint32_t i = _AP_N-offset; i < _AP_N; i++) + val[i] = 0; + Retval.clearUnusedBits(); + return Retval; + } + + // Shift the low order words + uint32_t breakWord = _AP_N - offset -1; + for (uint32_t i = 0; i < breakWord; ++i) + val[i] = ((pVal[i+offset]) >> (wordShift)) | + ((pVal[i+offset+1]) << (APINT_BITS_PER_WORD - wordShift)); + // Shift the break word. + val[breakWord] = (pVal[breakWord+offset]) >> (wordShift); + + // Remaining words are 0 + for (uint32_t i = breakWord+1; i < _AP_N; ++i) + val[i] = 0; + Retval.clearUnusedBits(); + return Retval; + } + + /// Left-shift this ap_private by shiftAmt. + /// @brief Left-shift function. + ap_private shl(uint32_t shiftAmt) const { + assert(shiftAmt <= BitWidth && "Invalid shift amount, too big"); + if (isSingleWord()) { + if (shiftAmt == BitWidth) + return ap_private(0); // avoid undefined shift results + return ap_private((VAL) << (shiftAmt)); + } + + // If all the bits were shifted out, the result is 0. This avoids issues + // with shifting by the size of the integer type, which produces undefined + // results. We define these "undefined results" to always be 0. + if (shiftAmt == BitWidth) + return ap_private(0); + + // If none of the bits are shifted out, the result is *this. This avoids a + // lshr by the words size in the loop below which can produce incorrect + // results. It also avoids the expensive computation below for a common case. + if (shiftAmt == 0) + return *this; + + // Create some space for the result. + ap_private Retval(0); + uint64_t* val = Retval.pVal; + // If we are shifting less than a word, do it the easy way + if (shiftAmt < APINT_BITS_PER_WORD) { + uint64_t carry = 0; + for (uint32_t i = 0; i < _AP_N; i++) { + val[i] = ((pVal[i]) << (shiftAmt)) | carry; + carry = (pVal[i]) >> (APINT_BITS_PER_WORD - shiftAmt); + } + Retval.clearUnusedBits(); + return Retval; + } + + // Compute some values needed by the remaining shift algorithms + uint32_t wordShift = shiftAmt % APINT_BITS_PER_WORD; + uint32_t offset = shiftAmt / APINT_BITS_PER_WORD; + + // If we are shifting whole words, just move whole words + if (wordShift == 0) { + for (uint32_t i = 0; i < offset; i++) + val[i] = 0; + for (uint32_t i = offset; i < _AP_N; i++) + val[i] = pVal[i-offset]; + Retval.clearUnusedBits(); + return Retval; + } + + // Copy whole words from this to Result. + uint32_t i = _AP_N - 1; + for (; i > offset; --i) + val[i] = (pVal[i-offset]) << (wordShift) | + (pVal[i-offset-1]) >> (APINT_BITS_PER_WORD - wordShift); + val[offset] = (pVal[0]) << (wordShift); + for (i = 0; i < offset; ++i) + val[i] = 0; + Retval.clearUnusedBits(); + return Retval; + } + + INLINE ap_private rotl(uint32_t rotateAmt) const { + if (rotateAmt == 0) + return *this; + // Don't get too fancy, just use existing shift/or facilities + ap_private hi(*this); + ap_private lo(*this); + hi.shl(rotateAmt); + lo.lshr(BitWidth - rotateAmt); + return hi | lo; + } + + INLINE ap_private rotr(uint32_t rotateAmt) const { + if (rotateAmt == 0) + return *this; + // Don't get too fancy, just use existing shift/or facilities + ap_private hi(*this); + ap_private lo(*this); + lo.lshr(rotateAmt); + hi.shl(BitWidth - rotateAmt); + return hi | lo; + } + + /// Perform an unsigned divide operation on this ap_private by RHS. Both this and + /// RHS are treated as unsigned quantities for purposes of this division. + /// @returns a new ap_private value containing the division result + /// @brief Unsigned division operation. + ap_private udiv(const ap_private& RHS) const { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + + // First, deal with the easy case + if (isSingleWord()) { + assert(RHS.VAL != 0 && "Divide by zero?"); + return ap_private(VAL / RHS.VAL); + } + + // Get some facts about the LHS and RHS number of bits and words + uint32_t rhsBits = RHS.getActiveBits(); + uint32_t rhsWords = !rhsBits ? 0 : (whichWord(rhsBits - 1) + 1); + assert(rhsWords && "Divided by zero???"); + uint32_t lhsBits = this->getActiveBits(); + uint32_t lhsWords = !lhsBits ? 0 : (whichWord(lhsBits - 1) + 1); + + // Deal with some degenerate cases + if (!lhsWords) + // 0 / X ===> 0 + return ap_private(0); + else if (lhsWords < rhsWords || this->ult(RHS)) { + // X / Y ===> 0, iff X < Y + return ap_private(0); + } else if (*this == RHS) { + // X / X ===> 1 + return ap_private(1); + } else if (lhsWords == 1 && rhsWords == 1) { + // All high words are zero, just use native divide + return ap_private(this->pVal[0] / RHS.pVal[0]); + } + + // We have to compute it the hard way. Invoke the Knuth divide algorithm. + ap_private Quotient(0); // to hold result. + divide(*this, lhsWords, RHS, rhsWords, &Quotient, (ap_private*)0); + return Quotient; + } + + /// Signed divide this ap_private by ap_private RHS. + /// @brief Signed division function for ap_private. + INLINE ap_private sdiv(const ap_private& RHS) const { + if (isNegative()) + if (RHS.isNegative()) + return (-(*this)).udiv(-RHS); + else + return -((-(*this)).udiv(RHS)); + else if (RHS.isNegative()) + return -(this->udiv(-RHS)); + return this->udiv(RHS); + } + + /// Perform an unsigned remainder operation on this ap_private with RHS being the + /// divisor. Both this and RHS are treated as unsigned quantities for purposes + /// of this operation. Note that this is a true remainder operation and not + /// a modulo operation because the sign follows the sign of the dividend + /// which is *this. + /// @returns a new ap_private value containing the remainder result + /// @brief Unsigned remainder operation. + ap_private urem(const ap_private& RHS) const { + if (isSingleWord()) { + assert(RHS.VAL != 0 && "Remainder by zero?"); + return ap_private(VAL % RHS.VAL); + } + + // Get some facts about the LHS + uint32_t lhsBits = getActiveBits(); + uint32_t lhsWords = !lhsBits ? 0 : (whichWord(lhsBits - 1) + 1); + + // Get some facts about the RHS + uint32_t rhsBits = RHS.getActiveBits(); + uint32_t rhsWords = !rhsBits ? 0 : (whichWord(rhsBits - 1) + 1); + assert(rhsWords && "Performing remainder operation by zero ???"); + + // Check the degenerate cases + if (lhsWords == 0) { + // 0 % Y ===> 0 + return ap_private(0); + } else if (lhsWords < rhsWords || this->ult(RHS)) { + // X % Y ===> X, iff X < Y + return *this; + } else if (*this == RHS) { + // X % X == 0; + return ap_private(0); + } else if (lhsWords == 1) { + // All high words are zero, just use native remainder + return ap_private(pVal[0] % RHS.pVal[0]); + } + + // We have to compute it the hard way. Invoke the Knuth divide algorithm. + ap_private Remainder(0); + divide(*this, lhsWords, RHS, rhsWords, (ap_private*)(0), &Remainder); + return Remainder; + } + + ap_private urem(uint64_t RHS) const { + // Get some facts about the LHS + uint32_t lhsBits = getActiveBits(); + uint32_t lhsWords = !lhsBits ? 0 : (whichWord(lhsBits - 1) + 1); + // Get some facts about the RHS + uint32_t rhsBits = 64 - CountLeadingZeros_64(RHS); // RHS.getActiveBits(); + uint32_t rhsWords = 1;//!rhsBits ? 0 : (ap_private<_AP_W, _AP_S, _AP_N>::whichWord(rhsBits - 1) + 1); + assert(rhsWords && "Performing remainder operation by zero ???"); + // Check the degenerate cases + if (lhsWords == 0) { + // 0 % Y ===> 0 + return ap_private(0); + } else if (lhsWords < rhsWords || this->ult(RHS)) { + // X % Y ===> X, iff X < Y + return *this; + } else if (*this == RHS) { + // X % X == 0; + return ap_private(0); + } else if (lhsWords == 1) { + // All high words are zero, just use native remainder + return ap_private(pVal[0] % RHS); + } + + // We have to compute it the hard way. Invoke the Knuth divide algorithm. + ap_private Remainder(0); + divide(*this, lhsWords, RHS, (ap_private*)(0), &Remainder); + return Remainder; + } + + /// Signed remainder operation on ap_private. + /// @brief Function for signed remainder operation. + INLINE ap_private srem(const ap_private& RHS) const { + if (isNegative()) { + ap_private lhs = -(*this); + if (RHS.isNegative()) { + ap_private rhs = -RHS; + return -(lhs.urem(rhs)); + } else + return -(lhs.urem(RHS)); + } else if (RHS.isNegative()) { + ap_private rhs = -RHS; + return this->urem(rhs); + } + return this->urem(RHS); + } + + /// Signed remainder operation on ap_private. + /// @brief Function for signed remainder operation. + INLINE ap_private srem(int64_t RHS) const { + if (isNegative()) + if (RHS<0) + return -((-(*this)).urem(-RHS)); + else + return -((-(*this)).urem(RHS)); + else if (RHS<0) + return this->urem(-RHS); + return this->urem(RHS); + } + + /// Sometimes it is convenient to divide two ap_private values and obtain both + /// the quotient and remainder. This function does both operations in the + /// same computation making it a little more efficient. + /// @brief Dual division/remainder interface. + static void udivrem(const ap_private& LHS, const ap_private& RHS, ap_private &Quotient, ap_private& Remainder) { + // Get some size facts about the dividend and divisor + uint32_t lhsBits = LHS.getActiveBits(); + uint32_t lhsWords = !lhsBits ? 0 : (ap_private::whichWord(lhsBits - 1) + 1); + uint32_t rhsBits = RHS.getActiveBits(); + uint32_t rhsWords = !rhsBits ? 0 : (ap_private::whichWord(rhsBits - 1) + 1); + + // Check the degenerate cases + if (lhsWords == 0) { + Quotient = 0; // 0 / Y ===> 0 + Remainder = 0; // 0 % Y ===> 0 + return; + } + + if (lhsWords < rhsWords || LHS.ult(RHS)) { + Quotient = 0; // X / Y ===> 0, iff X < Y + Remainder = LHS; // X % Y ===> X, iff X < Y + return; + } + + if (LHS == RHS) { + Quotient = 1; // X / X ===> 1 + Remainder = 0; // X % X ===> 0; + return; + } + + if (lhsWords == 1 && rhsWords == 1) { + // There is only one word to consider so use the native versions. + if (LHS.isSingleWord()) { + Quotient = ap_private(LHS.VAL / RHS.VAL); + Remainder = ap_private(LHS.VAL % RHS.VAL); + } else { + Quotient = ap_private(LHS.pVal[0] / RHS.pVal[0]); + Remainder = ap_private(LHS.pVal[0] % RHS.pVal[0]); + } + return; + } + + // Okay, lets do it the long way + divide(LHS, lhsWords, RHS, rhsWords, &Quotient, &Remainder); + } + + static void sdivrem(const ap_private &LHS, const ap_private &RHS, + ap_private &Quotient, ap_private &Remainder) { + if (LHS.isNegative()) { + if (RHS.isNegative()) + ap_private::udivrem(-LHS, -RHS, Quotient, Remainder); + else + ap_private::udivrem(-LHS, RHS, Quotient, Remainder); + Quotient = -Quotient; + Remainder = -Remainder; + } else if (RHS.isNegative()) { + ap_private::udivrem(LHS, -RHS, Quotient, Remainder); + Quotient = -Quotient; + } else { + ap_private::udivrem(LHS, RHS, Quotient, Remainder); + } + } + + /// Compares this ap_private with RHS for the validity of the equality + /// relationship. + /// @returns true if *this == Val + /// @brief Equality comparison. + template + INLINE bool eq(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return (*this) == RHS; + } + + /// Compares this ap_private with RHS for the validity of the inequality + /// relationship. + /// @returns true if *this != Val + /// @brief Inequality comparison + template + INLINE bool ne(const ap_private<_AP_W, _AP_S1, _AP_N> &RHS) const { + return !((*this) == RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// the validity of the less-than relationship. + /// @returns true if *this < RHS when both are considered unsigned. + /// @brief Unsigned less than comparison + template + INLINE bool ult(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + // Get active bit length of both operands + uint32_t n1 = getActiveBits(); + uint32_t n2 = RHS.getActiveBits(); + + // If magnitude of LHS is less than RHS, return true. + if (n1 < n2) + return true; + + // If magnitude of RHS is greather than LHS, return false. + if (n2 < n1) + return false; + + // If they bot fit in a word, just compare the low order word + if (n1 <= APINT_BITS_PER_WORD && n2 <= APINT_BITS_PER_WORD) + return pVal[0] < RHS.pVal[0]; + + // Otherwise, compare all words + uint32_t topWord = whichWord(AESL_std::max(n1,n2)-1); + for (int i = topWord; i >= 0; --i) { + if (pVal[i] > RHS.pVal[i]) + return false; + if (pVal[i] < RHS.pVal[i]) + return true; + } + return false; + } + + INLINE bool ult(uint64_t RHS) const { + // Get active bit length of both operands + uint32_t n1 = getActiveBits(); + uint32_t n2 = 64 - CountLeadingZeros_64(RHS); //RHS.getActiveBits(); + + // If magnitude of LHS is less than RHS, return true. + if (n1 < n2) + return true; + + // If magnitude of RHS is greather than LHS, return false. + if (n2 < n1) + return false; + + // If they bot fit in a word, just compare the low order word + if (n1 <= APINT_BITS_PER_WORD && n2 <= APINT_BITS_PER_WORD) + return pVal[0] < RHS; + assert(0); + } + + template + INLINE bool slt(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + ap_private lhs(*this); + ap_private<_AP_W, _AP_S1, _AP_N> rhs(RHS); + bool lhsNeg = isNegative(); + bool rhsNeg = rhs.isNegative(); + if (lhsNeg) { + // Sign bit is set so perform two's complement to make it positive + lhs.flip(); + lhs++; + } + if (rhsNeg) { + // Sign bit is set so perform two's complement to make it positive + rhs.flip(); + rhs++; + } + + // Now we have unsigned values to compare so do the comparison if necessary + // based on the negativeness of the values. + if (lhsNeg) + if (rhsNeg) + return lhs.ugt(rhs); + else + return true; + else if (rhsNeg) + return false; + else + return lhs.ult(rhs); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// validity of the less-or-equal relationship. + /// @returns true if *this <= RHS when both are considered unsigned. + /// @brief Unsigned less or equal comparison + template + INLINE bool ule(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return ult(RHS) || eq(RHS); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the less-or-equal relationship. + /// @returns true if *this <= RHS when both are considered signed. + /// @brief Signed less or equal comparison + template + INLINE bool sle(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return slt(RHS) || eq(RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// the validity of the greater-than relationship. + /// @returns true if *this > RHS when both are considered unsigned. + /// @brief Unsigned greather than comparison + template + INLINE bool ugt(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return !ult(RHS) && !eq(RHS); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// the validity of the greater-than relationship. + /// @returns true if *this > RHS when both are considered signed. + /// @brief Signed greather than comparison + template + INLINE bool sgt(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return !slt(RHS) && !eq(RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// validity of the greater-or-equal relationship. + /// @returns true if *this >= RHS when both are considered unsigned. + /// @brief Unsigned greater or equal comparison + template + INLINE bool uge(const ap_private<_AP_W, _AP_S, _AP_N>& RHS) const { + return !ult(RHS); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the greater-or-equal relationship. + /// @returns true if *this >= RHS when both are considered signed. + /// @brief Signed greather or equal comparison + template + INLINE bool sge(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return !slt(RHS); + } + + template + void cpTrunc(const ap_private<_AP_W1, _AP_S1, _AP_N1>& that) { + assert(_AP_W1 > BitWidth && "Invalid ap_private Truncate request"); + assert(_AP_W1 >= MIN_INT_BITS && "Can't truncate to 0 bits"); + memcpy(pVal, that.pVal, _AP_N*APINT_WORD_SIZE); + } + + // Sign extend to a new width. + template + void cpSext(const ap_private<_AP_W1, _AP_S1, _AP_N1>& that) { + assert(_AP_W1 < BitWidth && "Invalid ap_private SignExtend request"); + assert(_AP_W1 <= MAX_INT_BITS && "Too many bits"); + // If the sign bit isn't set, this is the same as zext. + if (!that.isNegative()) { + cpZext(that); + return; + } + + // The sign bit is set. First, get some facts + enum { wordBits = _AP_W1 % APINT_BITS_PER_WORD}; + + // Mask the high order word appropriately + if (_AP_N1 == _AP_N) { + enum { newWordBits = _AP_W % APINT_BITS_PER_WORD}; + // The extension is contained to the wordsBefore-1th word. + static const uint64_t mask = wordBits?(~0ULL<<(wordBits)):0ULL; + if (_AP_N1 == 1) { + assert(0); + } else { + for (uint32_t i = 0; i < _AP_N1; ++i) + pVal[i] = that.pVal[i]; + pVal[_AP_N1-1] |= mask; + return; + } + } + + if (_AP_N1 == 1) { + assert(0);// newVal[0] = VAL | mask; + } else { + enum { newWordBits = _AP_W % APINT_BITS_PER_WORD}; + // The extension is contained to the wordsBefore-1th word. + static const uint64_t mask = wordBits?(~0ULL<<(wordBits)):0ULL; + for (uint32_t i = 0; i < _AP_N1; ++i) + pVal[i] = that.pVal[i]; + pVal[_AP_N1-1] |= mask; + } + for (uint32_t i=_AP_N1; i < _AP_N-1; i++) + pVal[i] = ~0ULL; + pVal[_AP_N-1] = ~0ULL; + clearUnusedBits(); + return; + } + + // Zero extend to a new width. + template + void cpZext(const ap_private<_AP_W1, _AP_S1, _AP_N1>& that) { + assert(_AP_W1 < BitWidth && "Invalid ap_private ZeroExtend request"); + assert(_AP_W1 <= MAX_INT_BITS && "Too many bits"); + uint32_t wordsAfter = _AP_N; + if (wordsAfter==1) { + assert(0); // return ap_private<_AP_W1, _AP_S, _AP_N1> (_AP_W1, VAL, _AP_S); + } else { + if (_AP_N1 == 1) { + assert(0); + // newVal[0] = VAL; + } else { + uint32_t i = 0; + for (; i < _AP_N1; ++i) + pVal[i] = that.pVal[i]; + for (; i < _AP_N; ++i) + pVal[i] = 0; + } + } + clearUnusedBits(); + } + + template + void cpZextOrTrunc(const ap_private<_AP_W1, _AP_S1, _AP_N1>& that) { + if (BitWidth > _AP_W1) + cpZext(that); + else if (BitWidth < _AP_W1) + cpTrunc(that); + else { + for (int i=0; i<_AP_N1; ++i) + pVal[i]=that.pVal[i]; + clearUnusedBits(); + } + } + + template + void cpSextOrTrunc(const ap_private<_AP_W1, _AP_S1, _AP_N1>& that) { + if (BitWidth > _AP_W1) + cpSext(that); + else if (BitWidth < _AP_W1) + cpTrunc(that); + else { + for (int i=0; i<_AP_N1; ++i) + pVal[i] = that.pVal[i]; + clearUnusedBits(); + } + } + + /// @name Value Characterization Functions + /// @{ + + /// @returns the total number of bits. + INLINE uint32_t getBitWidth() const { + return BitWidth; + } + + /// Here one word's bitwidth equals to that of uint64_t. + /// @returns the number of words to hold the integer value of this ap_private. + /// @brief Get the number of words. + INLINE uint32_t getNumWords() const { + return (BitWidth + APINT_BITS_PER_WORD - 1) / APINT_BITS_PER_WORD; + } + + /// This function returns the number of active bits which is defined as the + /// bit width minus the number of leading zeros. This is used in several + /// computations to see how "wide" the value is. + /// @brief Compute the number of active bits in the value + INLINE uint32_t getActiveBits() const { + uint32_t bits=BitWidth - countLeadingZeros(); + return bits?bits:1; + } + + + /// This method attempts to return the value of this ap_private as a zero extended + /// uint64_t. The bitwidth must be <= 64 or the value must fit within a + /// uint64_t. Otherwise an assertion will result. + /// @brief Get zero extended value + INLINE uint64_t getZExtValue() const { + assert(getActiveBits() <= 64 && "Too many bits for uint64_t"); + return *pVal; + } + + /// This method attempts to return the value of this ap_private as a sign extended + /// int64_t. The bit width must be <= 64 or the value must fit within an + /// int64_t. Otherwise an assertion will result. + /// @brief Get sign extended value + INLINE int64_t getSExtValue() const { + assert(getActiveBits() <= 64 && "Too many bits for int64_t"); + return int64_t(pVal[0]); + } + + /// This method determines how many bits are required to hold the ap_private + /// equivalent of the string given by \p str of length \p slen. + /// @brief Get bits required for string value. + static uint32_t getBitsNeeded(const char* str, uint32_t slen, uint8_t radix); + + /// countLeadingZeros - This function is an ap_private version of the + /// countLeadingZeros_{32,64} functions in MathExtras.h. It counts the number + /// of zeros from the most significant bit to the first one bit. + /// @returns BitWidth if the value is zero. + /// @returns the number of zeros from the most significant bit to the first + /// one bits. + INLINE uint32_t countLeadingZeros() const ; + + /// countLeadingOnes - This function counts the number of contiguous 1 bits + /// in the high order bits. The count stops when the first 0 bit is reached. + /// @returns 0 if the high order bit is not set + /// @returns the number of 1 bits from the most significant to the least + /// @brief Count the number of leading one bits. + INLINE uint32_t countLeadingOnes() const ; + + /// countTrailingZeros - This function is an ap_private version of the + /// countTrailingZoers_{32,64} functions in MathExtras.h. It counts + /// the number of zeros from the least significant bit to the first set bit. + /// @returns BitWidth if the value is zero. + /// @returns the number of zeros from the least significant bit to the first + /// one bit. + /// @brief Count the number of trailing zero bits. + INLINE uint32_t countTrailingZeros() const ; + + /// countPopulation - This function is an ap_private version of the + /// countPopulation_{32,64} functions in MathExtras.h. It counts the number + /// of 1 bits in the ap_private value. + /// @returns 0 if the value is zero. + /// @returns the number of set bits. + /// @brief Count the number of bits set. + INLINE uint32_t countPopulation() const { + uint32_t Count = 0; + for (uint32_t i = 0; i<_AP_N-1 ; ++i) + Count += CountPopulation_64(pVal[i]); + Count += CountPopulation_64(pVal[_AP_N-1]&mask); + return Count; + } + + /// @} + /// @name Conversion Functions + /// @{ + + /// This is used internally to convert an ap_private to a string. + /// @brief Converts an ap_private to a std::string + INLINE std::string toString(uint8_t radix, bool wantSigned) const + ; + + /// Considers the ap_private to be unsigned and converts it into a string in the + /// radix given. The radix can be 2, 8, 10 or 16. + /// @returns a character interpretation of the ap_private + /// @brief Convert unsigned ap_private to string representation. + INLINE std::string toStringUnsigned(uint8_t radix = 10) const { + return toString(radix, false); + } + + /// Considers the ap_private to be unsigned and converts it into a string in the + /// radix given. The radix can be 2, 8, 10 or 16. + /// @returns a character interpretation of the ap_private + /// @brief Convert unsigned ap_private to string representation. + INLINE std::string toStringSigned(uint8_t radix = 10) const { + return toString(radix, true); + } + + /// @returns a byte-swapped representation of this ap_private Value. + INLINE ap_private byteSwap() const ; + + /// @brief Converts this ap_private to a double value. + INLINE double roundToDouble(bool isSigned) const ; + + /// @brief Converts this unsigned ap_private to a double value. + INLINE double roundToDouble() const { + return roundToDouble(false); + } + + /// @brief Converts this signed ap_private to a double value. + INLINE double signedRoundToDouble() const { + return roundToDouble(true); + } + + /// The conversion does not do a translation from integer to double, it just + /// re-interprets the bits as a double. Note that it is valid to do this on + /// any bit width. Exactly 64 bits will be translated. + /// @brief Converts ap_private bits to a double + INLINE double bitsToDouble() const { + union { + uint64_t __I; + double __D; + } __T; + __T.__I = pVal[0]; + return __T.__D; + } + + /// The conversion does not do a translation from integer to float, it just + /// re-interprets the bits as a float. Note that it is valid to do this on + /// any bit width. Exactly 32 bits will be translated. + /// @brief Converts ap_private bits to a double + INLINE float bitsToFloat() const { + union { + uint32_t __I; + float __F; + } __T; + __T.__I = uint32_t(pVal[0]); + return __T.__F; + } + + /// The conversion does not do a translation from double to integer, it just + /// re-interprets the bits of the double. Note that it is valid to do this on + /// any bit width but bits from V may get truncated. + /// @brief Converts a double to ap_private bits. + INLINE ap_private& doubleToBits(double __V) { + union { + uint64_t __I; + double __D; + } __T; + __T.__D = __V; + pVal[0] = __T.__I; + return *this; + } + + /// The conversion does not do a translation from float to integer, it just + /// re-interprets the bits of the float. Note that it is valid to do this on + /// any bit width but bits from V may get truncated. + /// @brief Converts a float to ap_private bits. + INLINE ap_private& floatToBits(float __V) { + union { + uint32_t __I; + float __F; + } __T; + __T.__F = __V; + pVal[0] = __T.__I; + } + + //Reduce operation + //----------------------------------------------------------- + INLINE bool and_reduce() const { + return isMaxValue(); + } + + INLINE bool nand_reduce() const { + return isMinValue(); + } + + INLINE bool or_reduce() const { + return (bool)countPopulation(); + } + + INLINE bool nor_reduce() const { + return countPopulation()==0; + } + + INLINE bool xor_reduce() const { + unsigned int i=countPopulation(); + return (i%2)?true:false; + } + + INLINE bool xnor_reduce() const { + unsigned int i=countPopulation(); + return (i%2)?false:true; + } + INLINE std::string to_string(uint8_t radix=16, bool sign=false) const { + return toString(radix, radix==10?_AP_S:sign); + } +}; + +template +INLINE bool operator==(uint64_t V1, const ap_private<_AP_W, _AP_S, _AP_N>& V2) { + return V2 == V1; +} + +template +INLINE bool operator!=(uint64_t V1, const ap_private<_AP_W, _AP_S, _AP_N>& V2) { + return V2 != V1; +} + +namespace ap_private_ops { + enum {APINT_BITS_PER_WORD=64}; + /// @brief Determine the smaller of two ap_privates considered to be signed. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> smin(const ap_private<_AP_W, _AP_S, _AP_N> &LHS, const ap_private<_AP_W, _AP_S1, _AP_N> &RHS) { + return LHS.slt(RHS) ? LHS : RHS; + } + + /// @brief Determine the larger of two ap_privates considered to be signed. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> smax(const ap_private<_AP_W, _AP_S, _AP_N> &LHS, const ap_private<_AP_W, _AP_S1, _AP_N> &RHS) { + return LHS.sgt(RHS) ? LHS : RHS; + } + + /// @brief Determine the smaller of two ap_privates considered to be signed. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> umin(const ap_private<_AP_W, _AP_S, _AP_N> &LHS, const ap_private<_AP_W, _AP_S1, _AP_N> &RHS) { + return LHS.ult(RHS) ? LHS : RHS; + } + + /// @brief Determine the larger of two ap_privates considered to be unsigned. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> umax(const ap_private<_AP_W, _AP_S, _AP_N> &LHS, const ap_private<_AP_W, _AP_S1, _AP_N> &RHS) { + return LHS.ugt(RHS) ? LHS : RHS; + } + + /// @brief Check if the specified ap_private has a N-bits integer value. + template + INLINE bool isIntN(uint32_t __N, const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.isIntN(__N); + } + + /// @returns true if the argument ap_private value is a sequence of ones + /// starting at the least significant bit with the remainder zero. + template + INLINE bool isMask(uint32_t numBits, const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.getBoolValue() && ((APIVal + ap_private<_AP_W, _AP_S, _AP_N>(numBits,1)) & APIVal) == 0; + } + + /// @returns true if the argument ap_private value contains a sequence of ones + /// with the remainder zero. + template + INLINE bool isShiftedMask(uint32_t numBits, const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return isMask(numBits, (APIVal - ap_private<_AP_W, _AP_S, _AP_N>(numBits,1)) | APIVal); + } + + /// @returns a byte-swapped representation of the specified ap_private Value. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> byteSwap(const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.byteSwap(); + } + + /// @returns the floor log base 2 of the specified ap_private value. + template INLINE uint32_t logBase2(const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.logBase2(); + } + + /// GreatestCommonDivisor - This function returns the greatest common + /// divisor of the two ap_private values using Enclid's algorithm. + /// @returns the greatest common divisor of Val1 and Val2 + /// @brief Compute GCD of two ap_private values. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> GreatestCommonDivisor(const ap_private<_AP_W, _AP_S, _AP_N>& Val1, const ap_private<_AP_W, _AP_S, _AP_N>& Val2) + ; + + /// Treats the ap_private as an unsigned value for conversion purposes. + /// @brief Converts the given ap_private to a double value. + template INLINE double Roundap_privateToDouble(const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.roundToDouble(); + } + + /// Treats the ap_private as a signed value for conversion purposes. + /// @brief Converts the given ap_private to a double value. + template INLINE double RoundSignedap_privateToDouble(const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.signedRoundToDouble(); + } + + /// @brief Converts the given ap_private to a float vlalue. + template INLINE float Roundap_privateToFloat(const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return float(Roundap_privateToDouble(APIVal)); + } + + /// Treast the ap_private as a signed value for conversion purposes. + /// @brief Converts the given ap_private to a float value. + template INLINE float RoundSignedap_privateToFloat(const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return float(APIVal.signedRoundToDouble()); + } + + /// RoundDoubleToap_private - This function convert a double value to an ap_private value. + /// @brief Converts the given double value into a ap_private. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> RoundDoubleToap_private(double Double, uint32_t width) ; + + /// RoundFloatToap_private - Converts a float value into an ap_private value. + /// @brief Converts a float value into a ap_private. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> RoundFloatToap_private(float Float, uint32_t width) { + return RoundDoubleToap_private<_AP_W, _AP_S, _AP_N>(double(Float), width); + } + + /// Arithmetic right-shift the ap_private by shiftAmt. + /// @brief Arithmetic right-shift function. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> ashr(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, uint32_t shiftAmt) { + return LHS.ashr(shiftAmt); + } + + /// Logical right-shift the ap_private by shiftAmt. + /// @brief Logical right-shift function. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> lshr(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, uint32_t shiftAmt) { + return LHS.lshr(shiftAmt); + } + + /// Left-shift the ap_private by shiftAmt. + /// @brief Left-shift function. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> shl(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, uint32_t shiftAmt) { + return LHS.shl(shiftAmt); + } + + /// Signed divide ap_private LHS by ap_private RHS. + /// @brief Signed division function for ap_private. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> sdiv(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS.sdiv(RHS); + } + + /// Unsigned divide ap_private LHS by ap_private RHS. + /// @brief Unsigned division function for ap_private. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> udiv(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS.udiv(RHS); + } + + /// Signed remainder operation on ap_private. + /// @brief Function for signed remainder operation. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> srem(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS.srem(RHS); + } + + /// Unsigned remainder operation on ap_private. + /// @brief Function for unsigned remainder operation. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> urem(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS.urem(RHS); + } + + /// Performs multiplication on ap_private values. + /// @brief Function for multiplication operation. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> mul(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS * RHS; + } + + /// Performs addition on ap_private values. + /// @brief Function for addition operation. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> add(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS + RHS; + } + + /// Performs subtraction on ap_private values. + /// @brief Function for subtraction operation. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> sub(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS - RHS; + } + + /// Performs bitwise AND operation on ap_private LHS and + /// ap_private RHS. + /// @brief Bitwise AND function for ap_private. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> And(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS & RHS; + } + + /// Performs bitwise OR operation on ap_private LHS and ap_private RHS. + /// @brief Bitwise OR function for ap_private. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> Or(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS | RHS; + } + + /// Performs bitwise XOR operation on ap_private. + /// @brief Bitwise XOR function for ap_private. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> Xor(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS ^ RHS; + } + + /// Performs a bitwise complement operation on ap_private. + /// @brief Bitwise complement function. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> Not(const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return ~APIVal; + } + + template void clearUnusedBits(uint64_t& msw) { + // Compute how many bits are used in the final word + // uint32_t wordBits = APIVal.getBitWidth() & 0x3f; + if (wordBits == 0) + // If all bits are used, we want to leave the value alone. This also + // avoids the undefined behavior of >> when the shfit is the same size as + // the word size (64). + return; + + // Mask out the hight bits. + uint64_t mask = ~uint64_t(0ULL) >> (64 /*ap_private::APINT_BITS_PER_WORD */- wordBits); + msw &= mask; + } + template <> INLINE void clearUnusedBits<1>(uint64_t& msw) { + uint64_t mask = ~uint64_t(0ULL) >> (64 /*ap_private::APINT_BITS_PER_WORD */- 1); + msw &= mask; + } + template void clearUnusedBits(int64_t& msw) { + // Compute how many bits are used in the final word + // uint32_t wordBits = APIVal.getBitWidth() & 0x3f; + if (wordBits == 0) + // If all bits are used, we want to leave the value alone. This also + // avoids the undefined behavior of >> when the shfit is the same size as + // the word size (64). + return; + + // Mask out the hight bits. + uint64_t mask = ~uint64_t(0ULL) >> (64 /*ap_private::APINT_BITS_PER_WORD */- wordBits); + msw &= mask; + } + template <> INLINE void clearUnusedBits<1>(int64_t& msw) { + uint64_t mask = ~uint64_t(0ULL) >> (64 /*ap_private::APINT_BITS_PER_WORD */- 1); + msw &= mask; + } + // template + template + INLINE ap_private<_AP_W, _AP_S> ashr(const ap_private<_AP_W, _AP_S>& a) { + return ashr(a, shiftAmt); + } + + template + INLINE ap_private<_AP_W, _AP_S> lshr(const ap_private<_AP_W, _AP_S>& a) { + return lshr(a, shiftAmt); + } + + template + INLINE ap_private<_AP_W, true> ashr(const ap_private<_AP_W, true, 1>& a) { + enum {APINT_BITS_PER_WORD=64, excess_bits=APINT_BITS_PER_WORD-_AP_W}; + static const uint64_t sign_bit = (1ULL<<(_AP_W-1)); + static const uint64_t sign_ext_mask = (_AP_W-shiftAmt>0)?~0ULL<<(APINT_BITS_PER_WORD-_AP_W+shiftAmt):~0ULL; + return ap_private<_AP_W, true>((((int64_t)a.VAL) >> (shiftAmt)) | (a.VAL & sign_bit? sign_ext_mask : 0ULL)); + } + + template + INLINE ap_private<_AP_W, false> ashr(const ap_private<_AP_W, false, 1>& a) { + return ap_private<_AP_W, false>((a.VAL) >> (shiftAmt)); + } + + template + INLINE ap_private<_AP_W, _AP_S> lshr(const ap_private<_AP_W, _AP_S, 1>& a) { + static const uint64_t mask = ~0ULL<<_AP_W; + return ap_private<_AP_W, _AP_S>((a.VAL&mask) >> (shiftAmt)); + } + + template + INLINE ap_private<_AP_W-shiftAmt, _AP_S> shr(const ap_private<_AP_W, _AP_S>& a) { + return ap_private<_AP_W-shiftAmt, _AP_S>((a.VAL) >> (shiftAmt)); + } + + template + INLINE ap_private<_AP_W+shiftAmt, _AP_S> shl(const ap_private<_AP_W, _AP_S>& a) { + return ap_private<_AP_W+shiftAmt, _AP_S>((a.VAL) << (shiftAmt)); + } + + template + INLINE bool get(const ap_private<_AP_W, _AP_S, 1>& a) { + unsigned shift = (index%APINT_BITS_PER_WORD); + static const uint64_t mask=1ULL << (shift); + return ((mask & a.VAL) != 0); + } + + template + INLINE bool get(const ap_private<_AP_W, _AP_S>& a) { + static const uint64_t mask=1ULL << (index&0x3f); + return ((mask & a.pVal[(index)>>6]) != 0); + } + + template + INLINE void set(ap_private<_AP_W, _AP_S, 1>& a) { + const uint64_t mask = ~0ULL >> (lsb) << (APINT_BITS_PER_WORD-msb+lsb-1)>>(APINT_BITS_PER_WORD-msb-1); + a.VAL |= mask; + } + + template + INLINE void clear(ap_private<_AP_W, _AP_S, 1>& a) { + static const uint64_t mask = ~(~0ULL >> (lsb) <<(APINT_BITS_PER_WORD-msb+lsb-1) >> (APINT_BITS_PER_WORD-msb-1)); + a.VAL &= mask; + } + + template + INLINE void set(ap_private<_AP_W, _AP_S>& a) { + enum { APINT_BITS_PER_WORD=64, + lsb_word = lsb_index /APINT_BITS_PER_WORD, + msb_word = msb_index / APINT_BITS_PER_WORD, + msb = msb_index % APINT_BITS_PER_WORD, + lsb=lsb_index % APINT_BITS_PER_WORD}; + if (msb_word==lsb_word) { + const uint64_t mask = ~0ULL >> (lsb) << (APINT_BITS_PER_WORD-msb+lsb-1)>>(APINT_BITS_PER_WORD-msb-1); + a.pVal[msb_word] |= mask; + } else { + const uint64_t lsb_mask = ~0ULL >> (lsb) << (lsb); + const uint64_t msb_mask = ~0ULL << (APINT_BITS_PER_WORD-msb-1)>>(APINT_BITS_PER_WORD-msb-1); + a.pVal[lsb_word] |=lsb_mask; + for (int i=lsb_word+1; i + INLINE void clear(ap_private<_AP_W, _AP_S>& a) { + enum { APINT_BITS_PER_WORD=64, + lsb_word = lsb_index /APINT_BITS_PER_WORD, + msb_word = msb_index / APINT_BITS_PER_WORD, + msb = msb_index % APINT_BITS_PER_WORD, + lsb=lsb_index % APINT_BITS_PER_WORD}; + if (msb_word == lsb_word) { + const uint64_t mask = ~(~0ULL >> (lsb) << (APINT_BITS_PER_WORD-msb+lsb-1)>>(APINT_BITS_PER_WORD-msb-1)); + a.pVal[msb_word] &= mask; + } else { + const uint64_t lsb_mask = ~(~0ULL >> (lsb) << (lsb)); + const uint64_t msb_mask = ~(~0ULL << (APINT_BITS_PER_WORD-msb-1)>>(APINT_BITS_PER_WORD-msb-1)); + a.pVal[lsb_word] &=lsb_mask; + for (int i=lsb_word+1; i + INLINE void set(ap_private<_AP_W, _AP_S, 1>& a) { + static const uint64_t mask=1ULL << (index); + a.VAL |= mask; + a.clearUnusedBits(); + } + + template + INLINE void clear(ap_private<_AP_W, _AP_S, 1>& a) { + static const uint64_t mask=~(1ULL << (index)); + a.VAL &= mask; + a.clearUnusedBits(); + } + + template + INLINE void set(ap_private<_AP_W, _AP_S>& a) { + enum { APINT_BITS_PER_WORD=64, word = index/APINT_BITS_PER_WORD}; + static const uint64_t mask=1ULL << (index%APINT_BITS_PER_WORD); + a.pVal[word] |= mask; + a.clearUnusedBits(); + } + + template + INLINE void clear(ap_private<_AP_W, _AP_S>& a) { + enum { APINT_BITS_PER_WORD=64, word = index/APINT_BITS_PER_WORD}; + static const uint64_t mask=~(1ULL << (index%APINT_BITS_PER_WORD)); + a.pVal[word] &= mask; + a.clearUnusedBits(); + } + + template + INLINE bool isNegative(const ap_private<_AP_W, false>& a) { + return false; + } + + template + INLINE bool isNegative(const ap_private<_AP_W, true, 1>& a) { + static const uint64_t sign_mask = (1ULL << (_AP_W-1)); + return ((sign_mask & a.VAL) != 0); + } + + template + INLINE bool isNegative(const ap_private<_AP_W, true>& a) { + enum {APINT_BITS_PER_WORD=64,_AP_N=(_AP_W+APINT_BITS_PER_WORD-1)/APINT_BITS_PER_WORD}; + static const uint64_t sign_mask = (1ULL << (_AP_W%APINT_BITS_PER_WORD-1)); + return sign_mask & a.pVal[_AP_N-1]; + } +} // End of ap_private_ops namespace + +/// @brief Check if the specified ap_private has a N-bits integer value. +template +INLINE bool isIntN(uint32_t __N, const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.isIntN(__N); +} + +/// @returns true if the argument ap_private value is a sequence of ones +/// starting at the least significant bit with the remainder zero. +template +INLINE bool isMask(uint32_t numBits, const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.getBoolValue() && ((APIVal + ap_private<_AP_W, _AP_S, _AP_N>(numBits,1)) & APIVal) == 0; +} + +/// @returns true if the argument ap_private value contains a sequence of ones +/// with the remainder zero. +template +INLINE bool isShiftedMask(uint32_t numBits, const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return isMask(numBits, (APIVal - ap_private<_AP_W, _AP_S, _AP_N>(numBits,1)) | APIVal); +} + +#if 0 +/// add_1 - This function adds a single "digit" integer, y, to the multiple +/// "digit" integer array, x[]. x[] is modified to reflect the addition and +/// 1 is returned if there is a carry out, otherwise 0 is returned. +/// @returns the carry of the addition. +static bool add_1(uint64_t dest[], uint64_t x[], uint32_t len, uint64_t y) { + for (uint32_t i = 0; i < len; ++i) { + dest[i] = y + x[i]; + if (dest[i] < y) + y = 1; // Carry one to next digit. + else { + y = 0; // No need to carry so exit early + break; + } + } + return (y != 0); +} +#endif + +#if 0 +/// add - This function adds the integer array x to the integer array Y and +/// places the result in dest. +/// @returns the carry out from the addition +/// @brief General addition of 64-bit integer arrays +static bool add(uint64_t *dest, const uint64_t *x, const uint64_t *y, + uint32_t destlen, uint32_t xlen, uint32_t ylen, bool xsigned, bool ysigned) { + bool carry = false; + uint32_t len = AESL_std::min(xlen, ylen); + uint32_t i; + for (i = 0; i< len && i < destlen; ++i) { + uint64_t limit = AESL_std::min(x[i],y[i]); // must come first in case dest == x + dest[i] = x[i] + y[i] + carry; + carry = dest[i] < limit || (carry && dest[i] == limit); + } + if (xlen > ylen) { + const uint64_t yext = xsigned && int64_t(y[ylen-1])<0 ? -1 : 0; + for (i=ylen; i< xlen && i < destlen; i++) { + uint64_t limit = AESL_std::min(x[i], yext); + dest[i] = x[i] + yext + carry; + carry = (dest[i] < limit)||(carry && dest[i] == x[i]); + } + } else if (ylen> xlen) { + const uint64_t xext = ysigned && int64_t(x[xlen-1])<0 ? -1 : 0; + for (i=xlen; i< ylen && i < destlen; i++) { + uint64_t limit = AESL_std::min(xext, y[i]); + dest[i] = xext + y[i] + carry; + carry = (dest[i] < limit)||(carry && dest[i] == y[i]); + } + } + return carry; +} +#endif + +#if 0 +/// @returns returns the borrow out. +/// @brief Generalized subtraction of 64-bit integer arrays. +static bool sub(uint64_t *dest, const uint64_t *x, const uint64_t *y, + uint32_t destlen, uint32_t xlen, uint32_t ylen, bool xsigned, bool ysigned) { + bool borrow = false; + uint32_t i; + uint32_t len = AESL_std::min(xlen, ylen); + for (i = 0; i < len && i < destlen; ++i) { + uint64_t x_tmp = borrow ? x[i] - 1 : x[i]; + borrow = y[i] > x_tmp || (borrow && x[i] == 0); + dest[i] = x_tmp - y[i]; + } + if (xlen > ylen) { + const uint64_t yext = ysigned && int64_t(y[ylen-1])<0 ? -1 : 0; + for (i=ylen; i< xlen && i < destlen; i++) { + uint64_t x_tmp = borrow ? x[i] - 1 : x[i]; + borrow = yext > x_tmp || (borrow && x[i] == 0); + dest[i] = x_tmp - yext; + } + } else if (ylen> xlen) { + const uint64_t xext = xsigned && int64_t(x[xlen-1])<0 ? -1 : 0; + for (i=xlen; i< ylen && i < destlen; i++) { + uint64_t x_tmp = borrow ? xext - 1 : xext; + borrow = y[i] > x_tmp || (borrow && xext==0); + dest[i] = x_tmp - y[i]; + } + } + return borrow; +} +#endif + +/// Subtracts the RHS ap_private from this ap_private +/// @returns this, after subtraction +/// @brief Subtraction assignment operator. + +#if 0 +/// Multiplies an integer array, x by a a uint64_t integer and places the result +/// into dest. +/// @returns the carry out of the multiplication. +/// @brief Multiply a multi-digit ap_private by a single digit (64-bit) integer. +static uint64_t mul_1(uint64_t dest[], const uint64_t x[], uint32_t len, uint64_t y) { + // Split y into high 32-bit part (hy) and low 32-bit part (ly) + uint64_t ly = y & 0xffffffffULL, hy = (y) >> 32; + uint64_t carry = 0; + static const uint64_t two_power_32 = 1ULL << 32; + // For each digit of x. + for (uint32_t i = 0; i < len; ++i) { + // Split x into high and low words + uint64_t lx = x[i] & 0xffffffffULL; + uint64_t hx = (x[i]) >> 32; + // hasCarry - A flag to indicate if there is a carry to the next digit. + // hasCarry == 0, no carry + // hasCarry == 1, has carry + // hasCarry == 2, no carry and the calculation result == 0. + uint8_t hasCarry = 0; + dest[i] = carry + lx * ly; + // Determine if the add above introduces carry. + hasCarry = (dest[i] < carry) ? 1 : 0; + carry = hx * ly + ((dest[i]) >> 32) + (hasCarry ? two_power_32 : 0); + // The upper limit of carry can be (2^32 - 1)(2^32 - 1) + + // (2^32 - 1) + 2^32 = 2^64. + hasCarry = (!carry && hasCarry) ? 1 : (!carry ? 2 : 0); + + carry += (lx * hy) & 0xffffffffULL; + dest[i] = ((carry) << 32) | (dest[i] & 0xffffffffULL); + carry = (((!carry && hasCarry != 2) || hasCarry == 1) ? two_power_32 : 0) + + ((carry) >> 32) + ((lx * hy) >> 32) + hx * hy; + } + return carry; +} +#endif + +#if 0 +/// Multiplies integer array x by integer array y and stores the result into +/// the integer array dest. Note that dest's size must be >= xlen + ylen. +/// @brief Generalized multiplicate of integer arrays. +static void mul(uint64_t dest[], const uint64_t x[], uint32_t xlen, const uint64_t y[], + uint32_t ylen, uint32_t destlen) { + dest[xlen] = mul_1(dest, x, xlen, y[0]); + for (uint32_t i = 1; i < ylen; ++i) { + uint64_t ly = y[i] & 0xffffffffULL, hy = (y[i]) >> 32; + uint64_t carry = 0, lx = 0, hx = 0; + for (uint32_t j = 0; j < xlen; ++j) { + lx = x[j] & 0xffffffffULL; + hx = (x[j]) >> 32; + // hasCarry - A flag to indicate if has carry. + // hasCarry == 0, no carry + // hasCarry == 1, has carry + // hasCarry == 2, no carry and the calculation result == 0. + uint8_t hasCarry = 0; + uint64_t resul = carry + lx * ly; + hasCarry = (resul < carry) ? 1 : 0; + carry = (hasCarry ? (1ULL << 32) : 0) + hx * ly + ((resul) >> 32); + hasCarry = (!carry && hasCarry) ? 1 : (!carry ? 2 : 0); + carry += (lx * hy) & 0xffffffffULL; + resul = ((carry) << 32) | (resul & 0xffffffffULL); + dest[i+j] += resul; + carry = (((!carry && hasCarry != 2) || hasCarry == 1) ? (1ULL << 32) : 0)+ + ((carry) >> 32) + (dest[i+j] < resul ? 1 : 0) + + ((lx * hy) >> 32) + hx * hy; + } + dest[i+xlen] = carry; + } +} +#endif + + + +template +uint32_t ap_private<_AP_W, _AP_S, _AP_N>::getBitsNeeded(const char* str, uint32_t slen, uint8_t radix) { + assert(str != 0 && "Invalid value string"); + assert(slen > 0 && "Invalid string length"); + + // Each computation below needs to know if its negative + uint32_t isNegative = str[0] == '-'; + if (isNegative) { + slen--; + str++; + } + // For radixes of power-of-two values, the bits required is accurately and + // easily computed + if (radix == 2) + return slen + isNegative; + if (radix == 8) + return slen * 3 + isNegative; + if (radix == 16) + return slen * 4 + isNegative; + + // Otherwise it must be radix == 10, the hard case + assert(radix == 10 && "Invalid radix"); + + // Convert to the actual binary value. + //ap_private<_AP_W, _AP_S, _AP_N> tmp(sufficient, str, slen, radix); + + // Compute how many bits are required. + //return isNegative + tmp.logBase2() + 1; + return isNegative + slen * 4; +} + +template +uint32_t ap_private<_AP_W, _AP_S, _AP_N>::countLeadingZeros() const { + enum { msw_bits = (BitWidth % APINT_BITS_PER_WORD)?(BitWidth % APINT_BITS_PER_WORD):APINT_BITS_PER_WORD, + excessBits = APINT_BITS_PER_WORD - msw_bits }; + uint32_t Count = CountLeadingZeros_64(pVal[_AP_N-1]); + if (Count>=excessBits) + Count -= excessBits; + if (!pVal[_AP_N-1]) { + for (uint32_t i = _AP_N-1 ; i ; --i) { + if (!pVal[i-1]) + Count += APINT_BITS_PER_WORD; + else { + Count += CountLeadingZeros_64(pVal[i-1]); + break; + } + } + } + return Count; +} + +static uint32_t countLeadingOnes_64(uint64_t __V, uint32_t skip) { + uint32_t Count = 0; + if (skip) + (__V) <<= (skip); + while (__V && (__V & (1ULL << 63))) { + Count++; + (__V) <<= 1; + } + return Count; +} + +template +uint32_t ap_private<_AP_W, _AP_S, _AP_N>::countLeadingOnes() const { + if (isSingleWord()) + return countLeadingOnes_64(VAL, APINT_BITS_PER_WORD - BitWidth); + + uint32_t highWordBits = BitWidth % APINT_BITS_PER_WORD; + uint32_t shift = (highWordBits == 0 ? 0 : APINT_BITS_PER_WORD - highWordBits); + int i = _AP_N - 1; + uint32_t Count = countLeadingOnes_64(pVal[i], shift); + if (Count == highWordBits) { + for (i--; i >= 0; --i) { + if (pVal[i] == ~0ULL) + Count += APINT_BITS_PER_WORD; + else { + Count += countLeadingOnes_64(pVal[i], 0); + break; + } + } + } + return Count; +} + +template +INLINE uint32_t ap_private<_AP_W, _AP_S, _AP_N>::countTrailingZeros() const { + if (isSingleWord()) + return AESL_std::min(uint32_t(CountTrailingZeros_64(VAL)), BitWidth); + uint32_t Count = 0; + uint32_t i = 0; + for (; i < _AP_N && pVal[i] == 0; ++i) + Count += APINT_BITS_PER_WORD; + if (i < _AP_N) + Count += CountTrailingZeros_64(pVal[i]); + return AESL_std::min(Count, BitWidth); +} + +template +ap_private<_AP_W, _AP_S, _AP_N> ap_private<_AP_W, _AP_S, _AP_N>::byteSwap() const { + assert(BitWidth >= 16 && BitWidth % 16 == 0 && "Cannot byteswap!"); + if (BitWidth == 16) + return ap_private<_AP_W, _AP_S, _AP_N>(/*BitWidth,*/ ByteSwap_16(uint16_t(VAL))); + else if (BitWidth == 32) + return ap_private<_AP_W, _AP_S, _AP_N>(/*BitWidth,*/ ByteSwap_32(uint32_t(VAL))); + else if (BitWidth == 48) { + uint32_t Tmp1 = uint32_t((VAL) >> 16); + Tmp1 = ByteSwap_32(Tmp1); + uint16_t Tmp2 = uint16_t(VAL); + Tmp2 = ByteSwap_16(Tmp2); + return ap_private<_AP_W, _AP_S, _AP_N>(/*BitWidth,*/ ((uint64_t(Tmp2)) << 32) | Tmp1); + } else if (BitWidth == 64) + return ap_private<_AP_W, _AP_S, _AP_N>(/*BitWidth,*/ ByteSwap_64(VAL)); + else { + ap_private<_AP_W, _AP_S, _AP_N> Result(0); + char *pByte = (char*)Result.pVal; + for (uint32_t i = 0; i < BitWidth / APINT_WORD_SIZE / 2; ++i) { + char Tmp = pByte[i]; + pByte[i] = pByte[BitWidth / APINT_WORD_SIZE - 1 - i]; + pByte[BitWidth / APINT_WORD_SIZE - i - 1] = Tmp; + } + return Result; + } +} + +template +ap_private<_AP_W, _AP_S, _AP_N> ap_private_ops::GreatestCommonDivisor(const ap_private<_AP_W, _AP_S, _AP_N>& API1, const ap_private<_AP_W, _AP_S, _AP_N>& API2) { + ap_private<_AP_W, _AP_S, _AP_N> __A = API1, __B = API2; + while (!!__B) { + ap_private<_AP_W, _AP_S, _AP_N> __T = __B; + __B = ap_private_ops::urem(__A, __B); + __A = __T; + } + return __A; +} + +template +ap_private<_AP_W, _AP_S, _AP_N> ap_private_ops::RoundDoubleToap_private(double Double, uint32_t width) { + union { + double __D; + uint64_t __I; + } __T; + __T.__D = Double; + + // Get the sign bit from the highest order bit + bool isNeg = (__T.__I) >> 63; + + // Get the 11-bit exponent and adjust for the 1023 bit bias + int64_t exp = (((__T.__I) >> 52) & 0x7ffULL) - 1023; + + // If the exponent is negative, the value is < 0 so just return 0. + if (exp < 0) + return ap_private<_AP_W, _AP_S, _AP_N>(width, 0u); + + // Extract the mantissa by clearing the top 12 bits (sign + exponent). + uint64_t mantissa = (__T.__I & (~0ULL >> 12)) | 1ULL << 52; + + // If the exponent doesn't shift all bits out of the mantissa + if (exp < 52) + return isNeg ? -ap_private<_AP_W, _AP_S, _AP_N>(width, (mantissa) >> (52 - exp)) : + ap_private<_AP_W, _AP_S, _AP_N>((mantissa) >> (52 - exp)); + + // If the client didn't provide enough bits for us to shift the mantissa into + // then the result is undefined, just return 0 + if (width <= exp - 52) + return ap_private<_AP_W, _AP_S, _AP_N>(width, 0); + + // Otherwise, we have to shift the mantissa bits up to the right location + ap_private<_AP_W, _AP_S, _AP_N> Tmp(width, mantissa); + Tmp = Tmp.shl(exp - 52); + return isNeg ? -Tmp : Tmp; +} + +/// RoundToDouble - This function convert this ap_private to a double. +/// The layout for double is as following (IEEE Standard 754): +/// -------------------------------------- +/// | Sign Exponent Fraction Bias | +/// |-------------------------------------- | +/// | 1[63] 11[62-52] 52[51-00] 1023 | +/// -------------------------------------- +template +double ap_private<_AP_W, _AP_S, _AP_N>::roundToDouble(bool isSigned) const { + + // Handle the simple case where the value is contained in one uint64_t. + if (isSingleWord() || getActiveBits() <= APINT_BITS_PER_WORD) { + uint64_t val; + if (isSingleWord()) val = VAL; + else val = pVal[0]; + if (isSigned) { + int64_t sext = ((int64_t(val)) << (64-BitWidth)) >> (64-BitWidth); + return double(sext); + } else + return double(val); + } + + // Determine if the value is negative. + bool isNeg = isSigned ? (*this)[BitWidth-1] : false; + + // Construct the absolute value if we're negative. + ap_private<_AP_W, _AP_S, _AP_N> Tmp(isNeg ? -(*this) : (*this)); + + // Figure out how many bits we're using. + uint32_t n = Tmp.getActiveBits(); + + // The exponent (without bias normalization) is just the number of bits + // we are using. Note that the sign bit is gone since we constructed the + // absolute value. + uint64_t exp = n; + + // Return infinity for exponent overflow + if (exp > 1023) { + if (!isSigned || !isNeg) + return std::numeric_limits::infinity(); + else + return -std::numeric_limits::infinity(); + } + exp += 1023; // Increment for 1023 bias + + // Number of bits in mantissa is 52. To obtain the mantissa value, we must + // extract the high 52 bits from the correct words in pVal. + uint64_t mantissa; + unsigned hiWord = whichWord(n-1); + if (hiWord == 0) { + mantissa = Tmp.pVal[0]; + if (n > 52) + (mantissa) >>= (n - 52); // shift down, we want the top 52 bits. + } else { + assert(hiWord > 0 && "High word is negative?"); + uint64_t hibits = (Tmp.pVal[hiWord]) << (52 - n % APINT_BITS_PER_WORD); + uint64_t lobits = (Tmp.pVal[hiWord-1]) >> (11 + n % APINT_BITS_PER_WORD); + mantissa = hibits | lobits; + } + + // The leading bit of mantissa is implicit, so get rid of it. + uint64_t sign = isNeg ? (1ULL << (APINT_BITS_PER_WORD - 1)) : 0; + union { + double __D; + uint64_t __I; + } __T; + __T.__I = sign | ((exp) << 52) | mantissa; + return __T.__D; +} + +// Square Root - this method computes and returns the square root of "this". +// Three mechanisms are used for computation. For small values (<= 5 bits), +// a table lookup is done. This gets some performance for common cases. For +// values using less than 52 bits, the value is converted to double and then +// the libc sqrt function is called. The result is rounded and then converted +// back to a uint64_t which is then used to construct the result. Finally, +// the Babylonian method for computing square roots is used. +template +ap_private<_AP_W, _AP_S, _AP_N> ap_private<_AP_W, _AP_S, _AP_N>::sqrt() const { + + // Determine the magnitude of the value. + uint32_t magnitude = getActiveBits(); + + // Use a fast table for some small values. This also gets rid of some + // rounding errors in libc sqrt for small values. + if (magnitude <= 5) { + static const uint8_t results[32] = { + /* 0 */ 0, + /* 1- 2 */ 1, 1, + /* 3- 6 */ 2, 2, 2, 2, + /* 7-12 */ 3, 3, 3, 3, 3, 3, + /* 13-20 */ 4, 4, 4, 4, 4, 4, 4, 4, + /* 21-30 */ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + /* 31 */ 6 + }; + return ap_private<_AP_W, _AP_S, _AP_N>(/*BitWidth,*/ results[ (isSingleWord() ? VAL : pVal[0]) ]); + } + + // If the magnitude of the value fits in less than 52 bits (the precision of + // an IEEE double precision floating point value), then we can use the + // libc sqrt function which will probably use a hardware sqrt computation. + // This should be faster than the algorithm below. + if (magnitude < 52) { +#ifdef _MSC_VER + // Amazingly, VC++ doesn't have round(). + return ap_private<_AP_W, _AP_S, _AP_N>(/*BitWidth,*/ + uint64_t(::sqrt(double(isSingleWord()?VAL:pVal[0]))) + 0.5); +#else + return ap_private<_AP_W, _AP_S, _AP_N>(/*BitWidth,*/ + uint64_t(::round(::sqrt(double(isSingleWord()?VAL:pVal[0]))))); +#endif + } + + // Okay, all the short cuts are exhausted. We must compute it. The following + // is a classical Babylonian method for computing the square root. This code + // was adapted to APINt from a wikipedia article on such computations. + // See http://www.wikipedia.org/ and go to the page named + // Calculate_an_integer_square_root. + uint32_t nbits = BitWidth, i = 4; + ap_private<_AP_W, _AP_S, _AP_N> testy(16); + ap_private<_AP_W, _AP_S, _AP_N> x_old(/*BitWidth,*/ 1); + ap_private<_AP_W, _AP_S, _AP_N> x_new(0); + ap_private<_AP_W, _AP_S, _AP_N> two(/*BitWidth,*/ 2); + + // Select a good starting value using binary logarithms. + for (;; i += 2, testy = testy.shl(2)) + if (i >= nbits || this->ule(testy)) { + x_old = x_old.shl(i / 2); + break; + } + + // Use the Babylonian method to arrive at the integer square root: + for (;;) { + x_new = (this->udiv(x_old) + x_old).udiv(two); + if (x_old.ule(x_new)) + break; + x_old = x_new; + } + + // Make sure we return the closest approximation + // NOTE: The rounding calculation below is correct. It will produce an + // off-by-one discrepancy with results from pari/gp. That discrepancy has been + // determined to be a rounding issue with pari/gp as it begins to use a + // floating point representation after 192 bits. There are no discrepancies + // between this algorithm and pari/gp for bit widths < 192 bits. + ap_private<_AP_W, _AP_S, _AP_N> square(x_old * x_old); + ap_private<_AP_W, _AP_S, _AP_N> nextSquare((x_old + 1) * (x_old +1)); + if (this->ult(square)) + return x_old; + else if (this->ule(nextSquare)) { + ap_private<_AP_W, _AP_S, _AP_N> midpoint((nextSquare - square).udiv(two)); + ap_private<_AP_W, _AP_S, _AP_N> offset(*this - square); + if (offset.ult(midpoint)) + return x_old; + else + return x_old + 1; + } else + assert(0 && "Error in ap_private<_AP_W, _AP_S, _AP_N>::sqrt computation"); + return x_old + 1; +} + +/// Implementation of Knuth's Algorithm D (Division of nonnegative integers) +/// from "Art of Computer Programming, Volume 2", section 4.3.1, p. 272. The +/// variables here have the same names as in the algorithm. Comments explain +/// the algorithm and any deviation from it. +static void KnuthDiv(uint32_t *u, uint32_t *v, uint32_t *q, uint32_t* r, + uint32_t m, uint32_t n) { + assert(u && "Must provide dividend"); + assert(v && "Must provide divisor"); + assert(q && "Must provide quotient"); + assert(u != v && u != q && v != q && "Must us different memory"); + assert(n>1 && "n must be > 1"); + + // Knuth uses the value b as the base of the number system. In our case b + // is 2^31 so we just set it to -1u. + uint64_t b = uint64_t(1) << 32; + + //DEBUG(cerr << "KnuthDiv: m=" << m << " n=" << n << '\n'); + //DEBUG(cerr << "KnuthDiv: original:"); + //DEBUG(for (int i = m+n; i >=0; i--) cerr << " " << std::setbase(16) << u[i]); + //DEBUG(cerr << " by"); + //DEBUG(for (int i = n; i >0; i--) cerr << " " << std::setbase(16) << v[i-1]); + //DEBUG(cerr << '\n'); + // D1. [Normalize.] Set d = b / (v[n-1] + 1) and multiply all the digits of + // u and v by d. Note that we have taken Knuth's advice here to use a power + // of 2 value for d such that d * v[n-1] >= b/2 (b is the base). A power of + // 2 allows us to shift instead of multiply and it is easy to determine the + // shift amount from the leading zeros. We are basically normalizing the u + // and v so that its high bits are shifted to the top of v's range without + // overflow. Note that this can require an extra word in u so that u must + // be of length m+n+1. + uint32_t shift = CountLeadingZeros_32(v[n-1]); + uint32_t v_carry = 0; + uint32_t u_carry = 0; + if (shift) { + for (uint32_t i = 0; i < m+n; ++i) { + uint32_t u_tmp = (u[i]) >> (32 - shift); + u[i] = ((u[i]) << (shift)) | u_carry; + u_carry = u_tmp; + } + for (uint32_t i = 0; i < n; ++i) { + uint32_t v_tmp = (v[i]) >> (32 - shift); + v[i] = ((v[i]) << (shift)) | v_carry; + v_carry = v_tmp; + } + } + u[m+n] = u_carry; + //DEBUG(cerr << "KnuthDiv: normal:"); + //DEBUG(for (int i = m+n; i >=0; i--) cerr << " " << std::setbase(16) << u[i]); + //DEBUG(cerr << " by"); + //DEBUG(for (int i = n; i >0; i--) cerr << " " << std::setbase(16) << v[i-1]); + //DEBUG(cerr << '\n'); + + // D2. [Initialize j.] Set j to m. This is the loop counter over the places. + int j = m; + do { + //DEBUG(cerr << "KnuthDiv: quotient digit #" << j << '\n'); + // D3. [Calculate q'.]. + // Set qp = (u[j+n]*b + u[j+n-1]) / v[n-1]. (qp=qprime=q') + // Set rp = (u[j+n]*b + u[j+n-1]) % v[n-1]. (rp=rprime=r') + // Now test if qp == b or qp*v[n-2] > b*rp + u[j+n-2]; if so, decrease + // qp by 1, inrease rp by v[n-1], and repeat this test if rp < b. The test + // on v[n-2] determines at high speed most of the cases in which the trial + // value qp is one too large, and it eliminates all cases where qp is two + // too large. + uint64_t dividend = ((uint64_t(u[j+n]) << 32) + u[j+n-1]); + //DEBUG(cerr << "KnuthDiv: dividend == " << dividend << '\n'); + uint64_t qp = dividend / v[n-1]; + uint64_t rp = dividend % v[n-1]; + if (qp == b || qp*v[n-2] > b*rp + u[j+n-2]) { + qp--; + rp += v[n-1]; + if (rp < b && (qp == b || qp*v[n-2] > b*rp + u[j+n-2])) + qp--; + } + //DEBUG(cerr << "KnuthDiv: qp == " << qp << ", rp == " << rp << '\n'); + + // D4. [Multiply and subtract.] Replace (u[j+n]u[j+n-1]...u[j]) with + // (u[j+n]u[j+n-1]..u[j]) - qp * (v[n-1]...v[1]v[0]). This computation + // consists of a simple multiplication by a one-place number, combined with + // a subtraction. + bool isNeg = false; + for (uint32_t i = 0; i < n; ++i) { + uint64_t u_tmp = uint64_t(u[j+i]) | ((uint64_t(u[j+i+1])) << 32); + uint64_t subtrahend = uint64_t(qp) * uint64_t(v[i]); + bool borrow = subtrahend > u_tmp; + /*DEBUG(cerr << "KnuthDiv: u_tmp == " << u_tmp + << ", subtrahend == " << subtrahend + << ", borrow = " << borrow << '\n');*/ + + uint64_t result = u_tmp - subtrahend; + uint32_t k = j + i; + u[k++] = (uint32_t)(result & (b-1)); // subtract low word + u[k++] = (uint32_t)((result) >> 32); // subtract high word + while (borrow && k <= m+n) { // deal with borrow to the left + borrow = u[k] == 0; + u[k]--; + k++; + } + isNeg |= borrow; + /*DEBUG(cerr << "KnuthDiv: u[j+i] == " << u[j+i] << ", u[j+i+1] == " << + u[j+i+1] << '\n');*/ + } + /*DEBUG(cerr << "KnuthDiv: after subtraction:"); + DEBUG(for (int i = m+n; i >=0; i--) cerr << " " << u[i]); + DEBUG(cerr << '\n');*/ + // The digits (u[j+n]...u[j]) should be kept positive; if the result of + // this step is actually negative, (u[j+n]...u[j]) should be left as the + // true value plus b**(n+1), namely as the b's complement of + // the true value, and a "borrow" to the left should be remembered. + // + if (isNeg) { + bool carry = true; // true because b's complement is "complement + 1" + for (uint32_t i = 0; i <= m+n; ++i) { + u[i] = ~u[i] + carry; // b's complement + carry = carry && u[i] == 0; + } + } + /*DEBUG(cerr << "KnuthDiv: after complement:"); + DEBUG(for (int i = m+n; i >=0; i--) cerr << " " << u[i]); + DEBUG(cerr << '\n');*/ + + // D5. [Test remainder.] Set q[j] = qp. If the result of step D4 was + // negative, go to step D6; otherwise go on to step D7. + q[j] = (uint32_t)qp; + if (isNeg) { + // D6. [Add back]. The probability that this step is necessary is very + // small, on the order of only 2/b. Make sure that test data accounts for + // this possibility. Decrease q[j] by 1 + q[j]--; + // and add (0v[n-1]...v[1]v[0]) to (u[j+n]u[j+n-1]...u[j+1]u[j]). + // A carry will occur to the left of u[j+n], and it should be ignored + // since it cancels with the borrow that occurred in D4. + bool carry = false; + for (uint32_t i = 0; i < n; i++) { + uint32_t limit = AESL_std::min(u[j+i],v[i]); + u[j+i] += v[i] + carry; + carry = u[j+i] < limit || (carry && u[j+i] == limit); + } + u[j+n] += carry; + } + /*DEBUG(cerr << "KnuthDiv: after correction:"); + DEBUG(for (int i = m+n; i >=0; i--) cerr <<" " << u[i]); + DEBUG(cerr << "\nKnuthDiv: digit result = " << q[j] << '\n');*/ + + // D7. [Loop on j.] Decrease j by one. Now if j >= 0, go back to D3. + } while (--j >= 0); + + /*DEBUG(cerr << "KnuthDiv: quotient:"); + DEBUG(for (int i = m; i >=0; i--) cerr <<" " << q[i]); + DEBUG(cerr << '\n');*/ + + // D8. [Unnormalize]. Now q[...] is the desired quotient, and the desired + // remainder may be obtained by dividing u[...] by d. If r is non-null we + // compute the remainder (urem uses this). + if (r) { + // The value d is expressed by the "shift" value above since we avoided + // multiplication by d by using a shift left. So, all we have to do is + // shift right here. In order to mak + if (shift) { + uint32_t carry = 0; + //DEBUG(cerr << "KnuthDiv: remainder:"); + for (int i = n-1; i >= 0; i--) { + r[i] = ((u[i]) >> (shift)) | carry; + carry = (u[i]) << (32 - shift); + //DEBUG(cerr << " " << r[i]); + } + } else { + for (int i = n-1; i >= 0; i--) { + r[i] = u[i]; + //DEBUG(cerr << " " << r[i]); + } + } + //DEBUG(cerr << '\n'); + } + //DEBUG(cerr << std::setbase(10) << '\n'); +} + +template +void divide(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, uint32_t lhsWords, + const ap_private<_AP_W, _AP_S, _AP_N>& RHS, uint32_t rhsWords, + ap_private<_AP_W, _AP_S, _AP_N> *Quotient, ap_private<_AP_W, _AP_S, _AP_N> *Remainder) { + assert(lhsWords >= rhsWords && "Fractional result"); + enum {APINT_BITS_PER_WORD=64}; + // First, compose the values into an array of 32-bit words instead of + // 64-bit words. This is a necessity of both the "short division" algorithm + // and the the Knuth "classical algorithm" which requires there to be native + // operations for +, -, and * on an m bit value with an m*2 bit result. We + // can't use 64-bit operands here because we don't have native results of + // 128-bits. Furthremore, casting the 64-bit values to 32-bit values won't + // work on large-endian machines. + uint64_t mask = ~0ull >> (sizeof(uint32_t)*8); + uint32_t n = rhsWords * 2; + uint32_t m = (lhsWords * 2) - n; + + // Allocate space for the temporary values we need either on the stack, if + // it will fit, or on the heap if it won't. + uint32_t SPACE[128]; + uint32_t *__U = 0; + uint32_t *__V = 0; + uint32_t *__Q = 0; + uint32_t *__R = 0; + if ((Remainder?4:3)*n+2*m+1 <= 128) { + __U = &SPACE[0]; + __V = &SPACE[m+n+1]; + __Q = &SPACE[(m+n+1) + n]; + if (Remainder) + __R = &SPACE[(m+n+1) + n + (m+n)]; + } else { + __U = new uint32_t[m + n + 1]; + __V = new uint32_t[n]; + __Q = new uint32_t[m+n]; + if (Remainder) + __R = new uint32_t[n]; + } + + // Initialize the dividend + memset(__U, 0, (m+n+1)*sizeof(uint32_t)); + for (unsigned i = 0; i < lhsWords; ++i) { + uint64_t tmp = (LHS.getNumWords() == 1 ? LHS.VAL : LHS.pVal[i]); + __U[i * 2] = (uint32_t)(tmp & mask); + __U[i * 2 + 1] = (tmp) >> (sizeof(uint32_t)*8); + } + __U[m+n] = 0; // this extra word is for "spill" in the Knuth algorithm. + + // Initialize the divisor + memset(__V, 0, (n)*sizeof(uint32_t)); + for (unsigned i = 0; i < rhsWords; ++i) { + uint64_t tmp = (RHS.getNumWords() == 1 ? RHS.VAL : RHS.pVal[i]); + __V[i * 2] = (uint32_t)(tmp & mask); + __V[i * 2 + 1] = (tmp) >> (sizeof(uint32_t)*8); + } + + // initialize the quotient and remainder + memset(__Q, 0, (m+n) * sizeof(uint32_t)); + if (Remainder) + memset(__R, 0, n * sizeof(uint32_t)); + + // Now, adjust m and n for the Knuth division. n is the number of words in + // the divisor. m is the number of words by which the dividend exceeds the + // divisor (i.e. m+n is the length of the dividend). These sizes must not + // contain any zero words or the Knuth algorithm fails. + for (unsigned i = n; i > 0 && __V[i-1] == 0; i--) { + n--; + m++; + } + for (unsigned i = m+n; i > 0 && __U[i-1] == 0; i--) + m--; + + // If we're left with only a single word for the divisor, Knuth doesn't work + // so we implement the short division algorithm here. This is much simpler + // and faster because we are certain that we can divide a 64-bit quantity + // by a 32-bit quantity at hardware speed and short division is simply a + // series of such operations. This is just like doing short division but we + // are using base 2^32 instead of base 10. + assert(n != 0 && "Divide by zero?"); + if (n == 1) { + uint32_t divisor = __V[0]; + uint32_t remainder = 0; + for (int i = m+n-1; i >= 0; i--) { + uint64_t partial_dividend = (uint64_t(remainder)) << 32 | __U[i]; + if (partial_dividend == 0) { + __Q[i] = 0; + remainder = 0; + } else if (partial_dividend < divisor) { + __Q[i] = 0; + remainder = (uint32_t)partial_dividend; + } else if (partial_dividend == divisor) { + __Q[i] = 1; + remainder = 0; + } else { + __Q[i] = (uint32_t)(partial_dividend / divisor); + remainder = (uint32_t)(partial_dividend - (__Q[i] * divisor)); + } + } + if (__R) + __R[0] = remainder; + } else { + // Now we're ready to invoke the Knuth classical divide algorithm. In this + // case n > 1. + KnuthDiv(__U, __V, __Q, __R, m, n); + } + + // If the caller wants the quotient + if (Quotient) { + // Set up the Quotient value's memory. + if (Quotient->BitWidth != LHS.BitWidth) { + if (Quotient->isSingleWord()) + Quotient->VAL = 0; + } else + Quotient->clear(); + + // The quotient is in Q. Reconstitute the quotient into Quotient's low + // order words. + if (lhsWords == 1) { + uint64_t tmp = + uint64_t(__Q[0]) | ((uint64_t(__Q[1])) << (APINT_BITS_PER_WORD / 2)); + if (Quotient->isSingleWord()) + Quotient->VAL = tmp; + else + Quotient->pVal[0] = tmp; + } else { + assert(!Quotient->isSingleWord() && "Quotient ap_private not large enough"); + for (unsigned i = 0; i < lhsWords; ++i) + Quotient->pVal[i] = + uint64_t(__Q[i*2]) | ((uint64_t(__Q[i*2+1])) << (APINT_BITS_PER_WORD / 2)); + } + Quotient->clearUnusedBits(); + } + + // If the caller wants the remainder + if (Remainder) { + // Set up the Remainder value's memory. + if (Remainder->BitWidth != RHS.BitWidth) { + if (Remainder->isSingleWord()) + Remainder->VAL = 0; + } else + Remainder->clear(); + + // The remainder is in R. Reconstitute the remainder into Remainder's low + // order words. + if (rhsWords == 1) { + uint64_t tmp = + uint64_t(__R[0]) | ((uint64_t(__R[1])) << (APINT_BITS_PER_WORD / 2)); + if (Remainder->isSingleWord()) + Remainder->VAL = tmp; + else + Remainder->pVal[0] = tmp; + } else { + assert(!Remainder->isSingleWord() && "Remainder ap_private not large enough"); + for (unsigned i = 0; i < rhsWords; ++i) + Remainder->pVal[i] = + uint64_t(__R[i*2]) | ((uint64_t(__R[i*2+1])) << (APINT_BITS_PER_WORD / 2)); + } + Remainder->clearUnusedBits(); + } + + // Clean up the memory we allocated. + if (__U != &SPACE[0]) { + delete [] __U; + delete [] __V; + delete [] __Q; + delete [] __R; + } +} + + +template +void ap_private<_AP_W, _AP_S, _AP_N>::fromString(const char *str, uint32_t slen, uint8_t radix) { + enum { numbits=_AP_W}; + // Check our assumptions here + assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) && + "Radix should be 2, 8, 10, or 16!"); + assert(str && "String is null?"); + bool isNeg = str[0] == '-'; + if (isNeg) + str++, slen--; + + //skip any leading zero + while(*str == '0' && *(str+1) != '\0') {str++; slen--;} + assert((slen <= numbits || radix != 2) && "Insufficient bit width"); + assert(((slen - 1)*3 <= numbits || radix != 8) && "Insufficient bit width"); + assert(((slen - 1)*4 <= numbits || radix != 16) && "Insufficient bit width"); + assert((((slen -1)*64)/22 <= numbits || radix != 10) && "Insufficient bit width"); + + memset(pVal, 0, _AP_N * sizeof(uint64_t)); + + // Figure out if we can shift instead of multiply + uint32_t shift = (radix == 16 ? 4 : radix == 8 ? 3 : radix == 2 ? 1 : 0); + + // Set up an ap_private for the digit to add outside the loop so we don't + // constantly construct/destruct it. + uint64_t bigVal[_AP_N]; + memset(bigVal, 0, _AP_N * sizeof(uint64_t)); + ap_private<_AP_W, _AP_S, _AP_N> apdigit(getBitWidth(), bigVal); + ap_private<_AP_W, _AP_S, _AP_N> apradix(radix); + + // Enter digit traversal loop + for (unsigned i = 0; i < slen; i++) { + // Get a digit + uint32_t digit = 0; + char cdigit = str[i]; + if (radix == 16) { +#define isxdigit(c) (((c) >= '0' && (c) <= '9') || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F')) +#define isdigit(c) ((c) >= '0' && (c) <= '9') + if (!isxdigit(cdigit)) + assert(0 && "Invalid hex digit in string"); + if (isdigit(cdigit)) + digit = cdigit - '0'; + else if (cdigit >= 'a') + digit = cdigit - 'a' + 10; + else if (cdigit >= 'A') + digit = cdigit - 'A' + 10; + else + assert(0 && "huh? we shouldn't get here"); + } else if (isdigit(cdigit)) { + digit = cdigit - '0'; + } else { + assert(0 && "Invalid character in digit string"); + } +#undef isxdigit +#undef isdigit + // Shift or multiply the value by the radix + if (shift) + *this <<= shift; + else + *this *= apradix; + + // Add in the digit we just interpreted + if (apdigit.isSingleWord()) + apdigit.VAL = digit; + else + apdigit.pVal[0] = digit; + *this += apdigit; + } + // If its negative, put it in two's complement form + if (isNeg) { + (*this)--; + this->flip(); + } + clearUnusedBits(); +} + +template +std::string ap_private<_AP_W, _AP_S, _AP_N>::toString(uint8_t radix, bool wantSigned) const { + assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) && + "Radix should be 2, 8, 10, or 16!"); + static const char *digits[] = { + "0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F" + }; + std::string result; + uint32_t bits_used = getActiveBits(); + + if (radix != 10) { + // For the 2, 8 and 16 bit cases, we can just shift instead of divide + // because the number of bits per digit (1,3 and 4 respectively) divides + // equaly. We just shift until there value is zero. + + // First, check for a zero value and just short circuit the logic below. + if (*this == (uint64_t)(0)) + result = "0"; + else { + ap_private<_AP_W, false, _AP_N> tmp(*this); + size_t insert_at = 0; + if (wantSigned && isNegative()) { + // They want to print the signed version and it is a negative value + // Flip the bits and add one to turn it into the equivalent positive + // value and put a '-' in the result. + tmp.flip(); + tmp++; + tmp.clearUnusedBitsToZero(); + result = "-"; + insert_at = 1; + } + // Just shift tmp right for each digit width until it becomes zero + uint32_t shift = (radix == 16 ? 4 : (radix == 8 ? 3 : 1)); + uint64_t mask = radix - 1; + ap_private<_AP_W, false, _AP_N> zero(0); + while (tmp.ne(zero)) { + unsigned digit = (tmp.isSingleWord() ? tmp.VAL : tmp.pVal[0]) & mask; + result.insert(insert_at, digits[digit]); + tmp = tmp.lshr(shift); + } + } + return result; + } + + ap_private<_AP_W, false, _AP_N> tmp(*this); + ap_private<_AP_W, false, _AP_N> divisor(radix); + ap_private<_AP_W, false, _AP_N> zero(0); + size_t insert_at = 0; + if (wantSigned && isNegative()) { + // They want to print the signed version and it is a negative value + // Flip the bits and add one to turn it into the equivalent positive + // value and put a '-' in the result. + tmp.flip(); + tmp++; + tmp.clearUnusedBitsToZero(); + result = "-"; + insert_at = 1; + } + if (tmp == ap_private<_AP_W, false, _AP_N>(0)) + result = "0"; + else while (tmp.ne(zero)) { + ap_private<_AP_W, false, _AP_N> APdigit(0); + ap_private<_AP_W, false, _AP_N> tmp2(0); + divide(tmp, tmp.getNumWords(), divisor, divisor.getNumWords(), &tmp2, + &APdigit); + uint32_t digit = APdigit.getZExtValue(); + assert(digit < radix && "divide failed"); + result.insert(insert_at,digits[digit]); + tmp = tmp2; + } + + return result; +} + +// This implements a variety of operations on a representation of +// arbitrary precision, two's-complement, bignum integer values. + +/* Assumed by lowHalf, highHalf, partMSB and partLSB. A fairly safe + and unrestricting assumption. */ + +/* Some handy functions local to this file. */ + +template +void divide(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, uint32_t lhsWords, + uint64_t RHS, + ap_private<_AP_W, _AP_S, _AP_N> *Quotient, ap_private<_AP_W, _AP_S, _AP_N> *Remainder) { + uint32_t rhsWords=1; + assert(lhsWords >= rhsWords && "Fractional result"); + enum {APINT_BITS_PER_WORD=64}; + // First, compose the values into an array of 32-bit words instead of + // 64-bit words. This is a necessity of both the "short division" algorithm + // and the the Knuth "classical algorithm" which requires there to be native + // operations for +, -, and * on an m bit value with an m*2 bit result. We + // can't use 64-bit operands here because we don't have native results of + // 128-bits. Furthremore, casting the 64-bit values to 32-bit values won't + // work on large-endian machines. + uint64_t mask = ~0ull >> (sizeof(uint32_t)*8); + uint32_t n = 2; + uint32_t m = (lhsWords * 2) - n; + + // Allocate space for the temporary values we need either on the stack, if + // it will fit, or on the heap if it won't. + uint32_t SPACE[128]; + uint32_t *__U = 0; + uint32_t *__V = 0; + uint32_t *__Q = 0; + uint32_t *__R = 0; + if ((Remainder?4:3)*n+2*m+1 <= 128) { + __U = &SPACE[0]; + __V = &SPACE[m+n+1]; + __Q = &SPACE[(m+n+1) + n]; + if (Remainder) + __R = &SPACE[(m+n+1) + n + (m+n)]; + } else { + __U = new uint32_t[m + n + 1]; + __V = new uint32_t[n]; + __Q = new uint32_t[m+n]; + if (Remainder) + __R = new uint32_t[n]; + } + + // Initialize the dividend + memset(__U, 0, (m+n+1)*sizeof(uint32_t)); + for (unsigned i = 0; i < lhsWords; ++i) { + uint64_t tmp = (LHS.getNumWords() == 1 ? LHS.VAL : LHS.pVal[i]); + __U[i * 2] = tmp & mask; + __U[i * 2 + 1] = (tmp) >> (sizeof(uint32_t)*8); + } + __U[m+n] = 0; // this extra word is for "spill" in the Knuth algorithm. + + // Initialize the divisor + memset(__V, 0, (n)*sizeof(uint32_t)); + __V[0] = RHS & mask; + __V[1] = (RHS) >> (sizeof(uint32_t)*8); + + // initialize the quotient and remainder + memset(__Q, 0, (m+n) * sizeof(uint32_t)); + if (Remainder) + memset(__R, 0, n * sizeof(uint32_t)); + + // Now, adjust m and n for the Knuth division. n is the number of words in + // the divisor. m is the number of words by which the dividend exceeds the + // divisor (i.e. m+n is the length of the dividend). These sizes must not + // contain any zero words or the Knuth algorithm fails. + for (unsigned i = n; i > 0 && __V[i-1] == 0; i--) { + n--; + m++; + } + for (unsigned i = m+n; i > 0 && __U[i-1] == 0; i--) + m--; + + // If we're left with only a single word for the divisor, Knuth doesn't work + // so we implement the short division algorithm here. This is much simpler + // and faster because we are certain that we can divide a 64-bit quantity + // by a 32-bit quantity at hardware speed and short division is simply a + // series of such operations. This is just like doing short division but we + // are using base 2^32 instead of base 10. + assert(n != 0 && "Divide by zero?"); + if (n == 1) { + uint32_t divisor = __V[0]; + uint32_t remainder = 0; + for (int i = m+n-1; i >= 0; i--) { + uint64_t partial_dividend = (uint64_t(remainder)) << 32 | __U[i]; + if (partial_dividend == 0) { + __Q[i] = 0; + remainder = 0; + } else if (partial_dividend < divisor) { + __Q[i] = 0; + remainder = partial_dividend; + } else if (partial_dividend == divisor) { + __Q[i] = 1; + remainder = 0; + } else { + __Q[i] = partial_dividend / divisor; + remainder = partial_dividend - (__Q[i] * divisor); + } + } + if (__R) + __R[0] = remainder; + } else { + // Now we're ready to invoke the Knuth classical divide algorithm. In this + // case n > 1. + KnuthDiv(__U, __V, __Q, __R, m, n); + } + + // If the caller wants the quotient + if (Quotient) { + // Set up the Quotient value's memory. + if (Quotient->BitWidth != LHS.BitWidth) { + if (Quotient->isSingleWord()) + Quotient->VAL = 0; + else + delete [] Quotient->pVal; + } else + Quotient->clear(); + + // The quotient is in Q. Reconstitute the quotient into Quotient's low + // order words. + if (lhsWords == 1) { + uint64_t tmp = + uint64_t(__Q[0]) | ((uint64_t(__Q[1])) << (APINT_BITS_PER_WORD / 2)); + if (Quotient->isSingleWord()) + Quotient->VAL = tmp; + else + Quotient->pVal[0] = tmp; + } else { + assert(!Quotient->isSingleWord() && "Quotient ap_private not large enough"); + for (unsigned i = 0; i < lhsWords; ++i) + Quotient->pVal[i] = + uint64_t(__Q[i*2]) | ((uint64_t(__Q[i*2+1])) << (APINT_BITS_PER_WORD / 2)); + } + Quotient->clearUnusedBits(); + } + + // If the caller wants the remainder + if (Remainder) { + // Set up the Remainder value's memory. + if (Remainder->BitWidth != 64 /* RHS.BitWidth */) { + if (Remainder->isSingleWord()) + Remainder->VAL = 0; + } else + Remainder->clear(); + + // The remainder is in __R. Reconstitute the remainder into Remainder's low + // order words. + if (rhsWords == 1) { + uint64_t tmp = + uint64_t(__R[0]) | ((uint64_t(__R[1])) << (APINT_BITS_PER_WORD / 2)); + if (Remainder->isSingleWord()) + Remainder->VAL = tmp; + else + Remainder->pVal[0] = tmp; + } else { + assert(!Remainder->isSingleWord() && "Remainder ap_private not large enough"); + for (unsigned i = 0; i < rhsWords; ++i) + Remainder->pVal[i] = + uint64_t(__R[i*2]) | ((uint64_t(__R[i*2+1])) << (APINT_BITS_PER_WORD / 2)); + } + Remainder->clearUnusedBits(); + } + + // Clean up the memory we allocated. + if (__U != &SPACE[0]) { + delete [] __U; + delete [] __V; + delete [] __Q; + delete [] __R; + } +} + +//When bitwidth < 64 +template class ap_private <_AP_W, _AP_S, 1> { +#ifdef _MSC_VER +#pragma warning( disable : 4521 4522 ) +#endif +public: + typedef typename retval<_AP_S>::Type ValType; + template + struct RType { + enum { + _AP_N =1, + mult_w = _AP_W+_AP_W2, + mult_s = _AP_S||_AP_S2, //?? why + plus_w = AP_MAX(_AP_W+(_AP_S2&&!_AP_S),_AP_W2+(_AP_S&&!_AP_S2))+1, //shouldn't it be AP_MAX(_AP_W,_AP_W2)+!(_AP_S^_AP_S2)+1 ???? + plus_s = _AP_S||_AP_S2, + minus_w = AP_MAX(_AP_W+(_AP_S2&&!_AP_S),_AP_W2+(_AP_S&&!_AP_S2))+1, + minus_s = true, + div_w = _AP_W+_AP_S2, + div_s = _AP_S||_AP_S2, + mod_w = AP_MIN(_AP_W,_AP_W2+(!_AP_S2&&_AP_S)), + mod_s = _AP_S, + logic_w = AP_MAX(_AP_W+(_AP_S2&&!_AP_S),_AP_W2+(_AP_S&&!_AP_S2)), + logic_s = _AP_S||_AP_S2 + }; + typedef ap_private mult; + typedef ap_private plus; + typedef ap_private minus; + typedef ap_private logic; + typedef ap_private div; + typedef ap_private mod; + typedef ap_private<_AP_W, _AP_S> arg1; + typedef bool reduce; + }; + enum { APINT_BITS_PER_WORD = 64}; + enum { excess_bits = (_AP_W%APINT_BITS_PER_WORD) ? APINT_BITS_PER_WORD -(_AP_W%APINT_BITS_PER_WORD) : 0}; + static const uint64_t mask = ((uint64_t)~0ULL >> (excess_bits)); + static const uint64_t not_mask = ~mask; + static const uint64_t sign_bit_mask = 1ULL << (APINT_BITS_PER_WORD-1); + template struct sign_ext_mask { static const uint64_t mask=~0ULL<<_AP_W1;}; + + enum { BitWidth=_AP_W}; + uint64_t VAL; ///< Used to store the <= 64 bits integer value. + const uint64_t *const pVal; + + INLINE uint32_t getBitWidth() const { + return BitWidth; + } + + template + ap_private<_AP_W, _AP_S, 1>& operator=(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { + VAL = RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + + template + ap_private<_AP_W, _AP_S, 1>& operator=(const volatile ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { + VAL = RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + + template + ap_private<_AP_W, _AP_S, 1>& operator=(const ap_private<_AP_W1, _AP_S1, 1>& RHS) { + VAL = RHS.VAL; + clearUnusedBits(); + return *this; + } + + template + ap_private<_AP_W, _AP_S, 1>& operator=(const volatile ap_private<_AP_W1, _AP_S1, 1>& RHS) { + VAL = RHS.VAL; + clearUnusedBits(); + return *this; + } + + volatile ap_private& operator=(const ap_private& RHS) volatile { + // Don't do anything for X = X + VAL = RHS.VAL; // No need to check because no harm done by copying. + return *this; + } + ap_private& operator=(const ap_private& RHS) { + // Don't do anything for X = X + VAL = RHS.VAL; // No need to check because no harm done by copying. + return *this; + } + + volatile ap_private& operator=(const volatile ap_private& RHS) volatile { + // Don't do anything for X = X + VAL = RHS.VAL; // No need to check because no harm done by copying. + return *this; + } + ap_private& operator=(const volatile ap_private& RHS) { + // Don't do anything for X = X + VAL = RHS.VAL; // No need to check because no harm done by copying. + return *this; + } + + template + INLINE ap_private& operator = (const ap_range_ref<_AP_W2, _AP_S2>& op2) { + *this = ap_private<_AP_W2, false>(op2); + return *this; + } + + explicit INLINE ap_private(uint64_t* val) : VAL(val[0]), pVal(&VAL){ + clearUnusedBits(); + } + + INLINE bool isSingleWord() const { return true; } + + INLINE void fromString(const char *strStart, uint32_t slen, + uint8_t radix, int offset=0) { + // Check our assumptions here + assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) && + "Radix should be 2, 8, 10, or 16!"); + assert(strStart && "String is null?"); + strStart+=offset; + switch(radix) { + case 2: + // sscanf(strStart,"%b",&VAL); + VAL = *strStart =='1' ? ~0ULL : 0; + for (;*strStart; ++strStart) { + assert((*strStart=='0'|| *strStart=='1')&&("Wrong binary number") ); + VAL <<=1; + VAL |= (*strStart-'0'); + } + break; + case 8: +#if __WIN32__ + sscanf(strStart,"%I64o",&VAL); +#else + +#if defined __x86_64__ + sscanf(strStart,"%lo",&VAL); +#else + sscanf(strStart,"%llo",&VAL); +#endif + +#endif + break; + case 10: +#if __WIN32__ + sscanf(strStart,"%I64u",&VAL); +#else + +#if defined __x86_64__ + sscanf(strStart,"%lu",&VAL); +#else + sscanf(strStart,"%llu",&VAL); +#endif + +#endif + break; + case 16: +#if __WIN32__ + sscanf(strStart,"%I64x",&VAL); +#else + +#if defined __x86_64__ + sscanf(strStart,"%lx",&VAL); +#else + sscanf(strStart,"%llx",&VAL); +#endif + +#endif + break; + default: + assert(true && "Unknown radix"); + // error + } + clearUnusedBits(); + } + + INLINE ap_private() : pVal(&VAL){VAL = 0ULL;} + +#define CTOR(TYPE) \ + INLINE ap_private(TYPE v) : VAL((uint64_t)v), pVal(&VAL) { \ + clearUnusedBits(); \ + } + CTOR(int) + CTOR(bool) + CTOR(signed char) + CTOR(unsigned char) + CTOR(short) + CTOR(unsigned short) + CTOR(unsigned int) + CTOR(long) + CTOR(unsigned long) + CTOR(unsigned long long) + CTOR(long long) + CTOR(float) + CTOR(double) +#undef CTOR + ap_private(uint32_t numWords, const uint64_t bigVal[]): VAL(bigVal[0]), pVal(&VAL) {clearUnusedBits();} + + ap_private(const std::string& val, uint8_t radix=2, int base=0, int offset=0): VAL(0), pVal(&VAL) { + assert(!val.empty() && "String empty?"); + fromString(val.c_str()+base, val.size()-base, radix); + } + + ap_private(const char strStart[], uint32_t slen, uint8_t radix, int base=0, int offset=0) : VAL(0), pVal(&VAL) { + fromString(strStart+base, slen-base, radix, offset); + } + + ap_private(const ap_private& that) : VAL(that.VAL), pVal(&VAL) { + clearUnusedBits(); + } + + template + ap_private(const ap_private<_AP_W1, _AP_S1, 1>& that) : VAL(that.VAL), pVal(&VAL) { + clearUnusedBits(); + } + + template + ap_private(const ap_private<_AP_W1, _AP_S1, _AP_N1>& that) : VAL(that.pVal[0]), pVal(&VAL) { + clearUnusedBits(); + } + + template + ap_private(const volatile ap_private<_AP_W1, _AP_S1, _AP_N1>& that) : VAL(that.pVal[0]), pVal(&VAL) { + clearUnusedBits(); + } + +#if 0 +template + explicit ap_private(const ap_private<_AP_W1, true, 1+_AP_W1/64>& that) + : VAL((_AP_W1>_AP_W) ? that.VAL & mask : ((1ULL<<(_AP_W1-1)&that.pVal[0]) ? sign_ext_mask<_AP_W1>::mask | that.VAL : that.pVal[0])), pVal(&VAL) {} + +template + explicit ap_private(const ap_private<_AP_W1, false, (_AP_W1+63)/64>& that) + : VAL(that.VAL & mask), pVal(&VAL) {} +#endif + + explicit ap_private(const char* val) : pVal(&VAL) { + std::string str(val); + uint32_t strLen = str.length(); + const char *strp = str.c_str(); + uint32_t offset = 0; + uint32_t base = 0; + bool neg = false; + uint32_t radix = 10; + ap_parse_sign(strp, base, neg); + ap_parse_prefix(strp + base, offset, radix); + + if ((radix != 10 && neg) || + (strLen - base - offset <= 0) || + InvalidDigit(strp, strLen, base + offset, radix)) { + fprintf(stderr, "invalid character string %s !\n", val); + assert(0); + } + + ap_private<_AP_W, _AP_S> ap_private_val(str.c_str(), strLen, radix, base, offset); + if (neg) + ap_private_val = -ap_private_val; + operator = (ap_private_val); + } + + ap_private(const char* val, signed char rd): pVal(&VAL) { + std::string str(val); + uint32_t strLen = str.length(); + const char *strp = str.c_str(); + uint32_t offset = 0; + uint32_t base = 0; + uint32_t radix = rd; + bool neg = false; + ap_parse_sign(strp, base, neg); + ap_parse_prefix(strp + base, offset, radix); + + if ((radix != 10 && neg) || + (strLen - base - offset <= 0) || + InvalidDigit(strp, strLen, base + offset, radix)) { + fprintf(stderr, "invalid character string %s !\n", val); + assert(0); + } + + uint32_t bitsNeeded = ap_private<_AP_W, _AP_S>::getBitsNeeded(strp, strLen, radix); + ap_private<_AP_W, _AP_S> ap_private_val(strp , strLen, radix, base, offset); + //ap_private<_AP_W, _AP_S> ap_private_val(bitsNeeded, strp , strLen, radix, base, offset); + if (strp[0] == '-') + ap_private_val = -ap_private_val; + operator = (ap_private_val); + } + + INLINE bool isNegative() const { + static const uint64_t sign_mask = 1ULL << (_AP_W-1); + return _AP_S && (sign_mask & VAL); + } + + INLINE bool isPositive() const { + return !isNegative(); + } + + INLINE bool isStrictlyPositive() const { + return !isNegative() && VAL!=0; + } + + INLINE bool isAllOnesValue() const { + return (mask & VAL) == mask; + } + + template + INLINE bool operator==(const ap_private<_AP_W1, _AP_S1, 1>& RHS) const { + return (VAL == RHS.VAL); + } + + INLINE bool operator==(const ap_private<_AP_W, _AP_S>& RHS) const { return VAL == RHS.VAL; } + INLINE bool operator==(const ap_private<_AP_W, !_AP_S>& RHS) const { return getVal() == RHS.getVal(); } + INLINE bool operator==(uint64_t Val) const { return (VAL == Val); } + INLINE bool operator!=(uint64_t Val) const { return (VAL != Val); } + INLINE bool operator!=(const ap_private<_AP_W, _AP_S>& RHS) const { return VAL != RHS.VAL; } + INLINE bool operator!=(const ap_private<_AP_W, !_AP_S>& RHS) const { return getVal() != RHS.getVal(); } + const ap_private operator++() { ++VAL; clearUnusedBits(); return *this; } + const ap_private operator--(int) { + ap_private orig(*this); + --VAL; clearUnusedBits(); + return orig; + } + const ap_private operator--() { --VAL; clearUnusedBits(); return *this;} + INLINE bool operator !() const { return !VAL;} + + const ap_private operator++(int) { + ap_private orig(*this); + VAL++; clearUnusedBits(); + return orig; + } + + const ap_private operator~() {return ap_private(~VAL);} + INLINE typename RType<1,false>::minus operator-() const { + return ap_private<1,false>(0) - (*this); + } + + INLINE std::string toString(uint8_t radix, bool wantSigned) const ; + INLINE std::string toStringUnsigned(uint8_t radix = 10) const { + return toString(radix, false); + } + INLINE std::string toStringSigned(uint8_t radix = 10) const { + return toString(radix, true); + } + INLINE void clear() { + VAL=0; + } + INLINE ap_private& clear(uint32_t bitPosition) { VAL &= ~(1ULL<<(bitPosition)); clearUnusedBits(); return *this;} + + INLINE ap_private ashr(uint32_t shiftAmt) const { + enum {excess_bits = APINT_BITS_PER_WORD - BitWidth}; + if (_AP_S) + return ap_private((shiftAmt == BitWidth) ? 0 : ((int64_t)VAL) >> (shiftAmt)); + else + return ap_private((shiftAmt == BitWidth) ? 0 : (VAL) >> (shiftAmt)); + } + + INLINE ap_private lshr(uint32_t shiftAmt) const { + return ap_private((shiftAmt == BitWidth) ? ap_private(0) : ap_private((VAL&mask) >> (shiftAmt))); + } + + INLINE ap_private shl(uint32_t shiftAmt) const { + if (shiftAmt > BitWidth) { + if (!isNegative()) + return ap_private(0); + else return ap_private(-1); + } + if (shiftAmt == BitWidth) return ap_private(0); + else return ap_private((VAL) << (shiftAmt)); + //return ap_private((shiftAmt == BitWidth) ? ap_private(0ULL) : ap_private(VAL << shiftAmt)); + } + + INLINE int64_t getSExtValue() const { + return VAL; + } + + INLINE uint64_t getZExtValue() const { + return VAL & mask; + } + + template + INLINE ap_private(const ap_range_ref<_AP_W2,_AP_S2>& ref) : pVal(&VAL) { + *this=ref.get(); + } + + template + INLINE ap_private(const ap_bit_ref<_AP_W2,_AP_S2>& ref) : pVal(&VAL) { + *this = ((uint64_t)(bool)ref); + } + + template + INLINE ap_private(const ap_concat_ref<_AP_W2, _AP_T2,_AP_W3, _AP_T3>& ref) : pVal(&VAL) { + *this=ref.get(); + } + + template + INLINE ap_private(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2> &val) : pVal(&VAL) { + *this = ((val.operator ap_private<_AP_W2, false> ())); + } + + template + INLINE ap_private(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2> &val) : pVal(&VAL) { + *this = (uint64_t)(bool)val; + } + + INLINE void write(const ap_private<_AP_W, _AP_S>& op2) volatile { + *this = (op2); + } + + //Explicit conversions to C interger types + //----------------------------------------------------------- + ValType getVal() const { + return VAL; + } + operator ValType () const { + return getVal(); + } + INLINE int to_int() const { + // ap_private<64 /* _AP_W */, _AP_S> res(V); + return (int) getVal(); + } + + INLINE unsigned to_uint() const { + return (unsigned) getVal(); + } + + INLINE long to_long() const { + return (long) getVal(); + } + + INLINE unsigned long to_ulong() const { + return (unsigned long) getVal(); + } + + INLINE ap_slong to_int64() const { + return (ap_slong) getVal(); + } + + INLINE ap_ulong to_uint64() const { + return (ap_ulong) getVal(); + } + + INLINE double to_double() const { + if (isNegative()) + return roundToDouble(true); + else + return roundToDouble(false); + } + + INLINE bool isMinValue() const { return VAL == 0;} + template INLINE ap_private& operator&=(const ap_private<_AP_W1, _AP_S1>& RHS) { + VAL = VAL&RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + + template INLINE ap_private& operator|=(const ap_private<_AP_W1, _AP_S1>& RHS) { + VAL = VAL|RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + + template INLINE ap_private& operator^=(const ap_private<_AP_W1, _AP_S1>& RHS){ + VAL = VAL^RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + + template INLINE ap_private& operator*=(const ap_private<_AP_W1, _AP_S1>& RHS){ + VAL = VAL*RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + + template INLINE ap_private& operator+=(const ap_private<_AP_W1, _AP_S1>& RHS){ + VAL = VAL+RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + + template INLINE ap_private& operator-=(const ap_private<_AP_W1, _AP_S1>& RHS){ + VAL = VAL-RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + INLINE const ap_private& operator<<=(uint32_t shiftAmt) { VAL<<=shiftAmt; clearUnusedBits(); return *this; } + + template INLINE typename RType<_AP_W1, _AP_S1>::logic operator&(const ap_private<_AP_W1, _AP_S1>& RHS) const { + if (RType<_AP_W1, _AP_S1>::logic_w <= 64) { + typename RType<_AP_W1, _AP_S1>::logic Ret(VAL & RHS.VAL); + return Ret; + } else { + typename RType<_AP_W1, _AP_S1>::logic Ret = *this; + return Ret & RHS; + } + } + + template INLINE typename RType<_AP_W1, _AP_S1>::logic operator^(const ap_private<_AP_W1, _AP_S1>& RHS) const { + if (RType<_AP_W1, _AP_S1>::logic_w <= 64) { + typename RType<_AP_W1, _AP_S1>::logic Ret(VAL ^ RHS.VAL); + return Ret; + } else { + typename RType<_AP_W1, _AP_S1>::logic Ret = *this; + return Ret ^ RHS; + } + } + + template INLINE typename RType<_AP_W1, _AP_S1>::logic operator|(const ap_private<_AP_W1, _AP_S1>& RHS) const { + if (RType<_AP_W1, _AP_S1>::logic_w <= 64) { + typename RType<_AP_W1, _AP_S1>::logic Ret(VAL | RHS.VAL); + return Ret; + } else { + typename RType<_AP_W1, _AP_S1>::logic Ret = *this; + return Ret | RHS; + } + } + + INLINE ap_private<_AP_W, _AP_S> And(const ap_private<_AP_W, _AP_S>& RHS) const { + return ap_private<_AP_W, _AP_S>(VAL & RHS.VAL); + } + + INLINE ap_private<_AP_W, _AP_S> Or(const ap_private<_AP_W, _AP_S>& RHS) const { + return ap_private<_AP_W, _AP_S>(VAL | RHS.VAL); + } + + INLINE ap_private<_AP_W, _AP_S> Xor(const ap_private<_AP_W, _AP_S>& RHS) const { + return ap_private<_AP_W, _AP_S>(VAL ^ RHS.VAL); + } +#if 1 + template + INLINE typename RType<_AP_W1, _AP_S1>::mult operator*(const ap_private<_AP_W1, _AP_S1>& RHS) const { + if (RType<_AP_W1, _AP_S1>::mult_w <= 64) { + typename RType<_AP_W1, _AP_S1>::mult Result(VAL * RHS.VAL); + return Result; + } else { + typename RType<_AP_W1, _AP_S1>::mult Result = typename RType<_AP_W1, _AP_S1>::mult(*this); + Result *= RHS; + return Result; + } + } +#endif + INLINE ap_private<_AP_W, _AP_S> Mul(const ap_private<_AP_W, _AP_S>& RHS) const { + return ap_private<_AP_W, _AP_S>(VAL * RHS.VAL); + } + + INLINE ap_private<_AP_W, _AP_S> Add(const ap_private<_AP_W, _AP_S>& RHS) const { + return ap_private<_AP_W, _AP_S>(VAL + RHS.VAL); + } + + INLINE ap_private<_AP_W, _AP_S> Sub(const ap_private<_AP_W, _AP_S>& RHS) const { + return ap_private<_AP_W, _AP_S>(VAL - RHS.VAL); + } + +#if 1 + INLINE ap_private& operator&=(uint64_t RHS) { VAL &= RHS; clearUnusedBits(); return *this;} + INLINE ap_private& operator|=(uint64_t RHS) { VAL |= RHS; clearUnusedBits(); return *this;} + INLINE ap_private& operator^=(uint64_t RHS){ VAL ^= RHS; clearUnusedBits(); return *this;} + INLINE ap_private& operator*=(uint64_t RHS){ VAL *= RHS; clearUnusedBits(); return *this; } + INLINE ap_private& operator+=(uint64_t RHS){ VAL += RHS; clearUnusedBits(); return *this;} + INLINE ap_private& operator-=(uint64_t RHS){ VAL -= RHS; clearUnusedBits(); return *this; } + INLINE ap_private operator&(uint64_t RHS) const { return ap_private(VAL & RHS); } + INLINE ap_private operator|(uint64_t RHS) const { return ap_private(VAL | RHS); } + INLINE ap_private operator^(uint64_t RHS) const { return ap_private(VAL ^ RHS); } + INLINE ap_private operator*(uint64_t RHS) const { return ap_private(VAL * RHS); } + INLINE ap_private operator/(uint64_t RHS) const { return ap_private(VAL / RHS); } + INLINE ap_private operator+(uint64_t RHS) const { return ap_private(VAL + RHS); } + INLINE ap_private operator-(uint64_t RHS) const { return ap_private(VAL - RHS); } +#endif + INLINE bool isMinSignedValue() const { + static const uint64_t min_mask = ~(~0ULL << (_AP_W-1)); + return BitWidth == 1 ? VAL == 1 : + (ap_private_ops::isNegative<_AP_W>(*this) && ((min_mask & VAL)==0)); + } + +#if 1 + + template INLINE + typename RType<_AP_W1,_AP_S1>::plus operator+(const ap_private<_AP_W1, _AP_S1>& RHS) const { + if (RType<_AP_W1,_AP_S1>::plus_w <=64) + return typename RType<_AP_W1,_AP_S1>::plus(RType<_AP_W1,_AP_S1>::plus_s ? int64_t(VAL+RHS.VAL):uint64_t(VAL+RHS.VAL)); + typename RType<_AP_W1,_AP_S1>::plus Result=RHS; + Result += VAL; + return Result; + } + + template INLINE + typename RType<_AP_W1,_AP_S1>::minus operator-(const ap_private<_AP_W1, _AP_S1>& RHS) const { + if (RType<_AP_W1,_AP_S1>::minus_w <=64) + return typename RType<_AP_W1,_AP_S1>::minus(int64_t(VAL-RHS.VAL)); + typename RType<_AP_W1,_AP_S1>::minus Result=*this; + Result -= RHS; + return Result; + } +#endif // #if 1 + + INLINE ap_private& flip() { + VAL = (~0ULL^VAL)&mask; + clearUnusedBits(); + return *this; + } + + uint32_t countPopulation() const { return CountPopulation_64(VAL);} + uint32_t countLeadingZeros() const { + int remainder = BitWidth % APINT_BITS_PER_WORD; + int excessBits = (APINT_BITS_PER_WORD - remainder) % APINT_BITS_PER_WORD; + //enum { remainder = BitWidth % APINT_BITS_PER_WORD, excessBits = APINT_BITS_PER_WORD - remainder}; + uint32_t Count = CountLeadingZeros_64(VAL); + if (Count) + Count-=excessBits; + return AESL_std::min(Count, (uint32_t)_AP_W); + } + + /// HiBits - This function returns the high "numBits" bits of this ap_private. + ap_private<_AP_W, _AP_S, 1> getHiBits(uint32_t numBits) const { + ap_private<_AP_W, _AP_S, 1> ret(*this); + ret = (ret)>>(BitWidth - numBits); + return ret; + } + + /// LoBits - This function returns the low "numBits" bits of this ap_private. + ap_private<_AP_W, _AP_S, 1> getLoBits(uint32_t numBits) const { + ap_private<_AP_W, _AP_S, 1> ret((VAL) << (BitWidth - numBits)); + ret = (ret)>>(BitWidth - numBits); + return ret; + //return ap_private(numBits, (VAL << (BitWidth - numBits))>> (BitWidth - numBits)); + } + + ap_private<_AP_W, _AP_S,1>& set(uint32_t bitPosition) { + VAL |= (1ULL << (bitPosition)); + clearUnusedBits(); + return *this; // clearUnusedBits(); + } + + void set() { + VAL = ~0ULL; + clearUnusedBits(); + } + + template + INLINE void set(const ap_private<_AP_W3, false> & val) { + operator = (ap_private<_AP_W3, _AP_S>(val)); + } + + INLINE void set(const ap_private & val) { + operator = (val); + } + + bool operator[](uint32_t bitPosition) const { + return (((1ULL << (bitPosition)) & VAL) != 0); + } + + INLINE void clearUnusedBits(void) { + enum { excess_bits = (_AP_W%APINT_BITS_PER_WORD) ? APINT_BITS_PER_WORD -_AP_W%APINT_BITS_PER_WORD : 0}; + VAL = _AP_S ? ((((int64_t)VAL)<<(excess_bits))>> (excess_bits)) : (excess_bits ? ((VAL)<<(excess_bits))>>(excess_bits) : VAL); + } + + INLINE void clearUnusedBitsToZero(void) { + enum { excess_bits = (_AP_W%APINT_BITS_PER_WORD) ? APINT_BITS_PER_WORD -_AP_W%APINT_BITS_PER_WORD : 0}; + static uint64_t mask = ~0ULL >> (excess_bits); + VAL &= mask; + } + + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1> udiv(const ap_private<_AP_W, _AP_S1>& RHS) const { + return ap_private<_AP_W, _AP_S||_AP_S1>(VAL / RHS.VAL); + } + + INLINE ap_private udiv(uint64_t RHS) const { + return ap_private(VAL / RHS); + } + + /// Signed divide this ap_private by ap_private RHS. + /// @brief Signed division function for ap_private. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1> sdiv(const ap_private<_AP_W, _AP_S1> & RHS) const { + if (isNegative()) + if (RHS.isNegative()) + return (-(*this)).udiv(-RHS); + else + return -((-(*this)).udiv(RHS)); + else if (RHS.isNegative()) + return -(this->udiv(-RHS)); + return this->udiv(RHS); + } + + /// Signed divide this ap_private by ap_private RHS. + /// @brief Signed division function for ap_private. + INLINE ap_private sdiv(int64_t RHS) const { + if (isNegative()) + if (RHS<0) + return (-(*this)).udiv(-RHS); + else + return -((-(*this)).udiv(RHS)); + else if (RHS<0) + return -(this->udiv(-RHS)); + return this->udiv(RHS); + } + + template + INLINE ap_private urem(const ap_private<_AP_W, _AP_S2>& RHS) const { + assert(RHS.VAL != 0 && "Divide by 0"); + return ap_private(VAL%RHS.VAL); + } + + INLINE ap_private urem(uint64_t RHS) const { + assert(RHS != 0 && "Divide by 0"); + return ap_private(VAL%RHS); + } + + /// Signed remainder operation on ap_private. + /// @brief Function for signed remainder operation. + template + INLINE ap_private srem(const ap_private<_AP_W, _AP_S2>& RHS) const { + if (isNegative()) { + ap_private lhs = -(*this); + if (RHS.isNegative()) { + ap_private rhs = -RHS; + return -(lhs.urem(rhs)); + } else + return -(lhs.urem(RHS)); + } else if (RHS.isNegative()) { + ap_private rhs = -RHS; + return this->urem(rhs); + } + return this->urem(RHS); + } + + /// Signed remainder operation on ap_private. + /// @brief Function for signed remainder operation. + INLINE ap_private srem(int64_t RHS) const { + if (isNegative()) + if (RHS<0) + return -((-(*this)).urem(-RHS)); + else + return -((-(*this)).urem(RHS)); + else if (RHS<0) + return this->urem(-RHS); + return this->urem(RHS); + } + + INLINE static void udivrem(const ap_private &LHS, const ap_private &RHS, + ap_private &Quotient, ap_private &Remainder){ + assert(RHS!=0 && "Divide by 0"); + Quotient = LHS.VAl/RHS.VAl; + Remainder = LHS.VAL % RHS.VAL; + } + + INLINE static void udivrem(const ap_private &LHS, uint64_t RHS, + ap_private &Quotient, ap_private &Remainder){ + assert(RHS!=0 && "Divide by 0"); + Quotient = LHS.VAl/RHS; + Remainder = LHS.VAL % RHS; + } + + INLINE static void sdivrem(const ap_private &LHS, const ap_private &RHS, + ap_private &Quotient, ap_private &Remainder) { + if (LHS.isNegative()) { + if (RHS.isNegative()) + ap_private::udivrem(-LHS, -RHS, Quotient, Remainder); + else + ap_private::udivrem(-LHS, RHS, Quotient, Remainder); + Quotient = -Quotient; + Remainder = -Remainder; + } else if (RHS.isNegative()) { + ap_private::udivrem(LHS, -RHS, Quotient, Remainder); + Quotient = -Quotient; + } else { + ap_private::udivrem(LHS, RHS, Quotient, Remainder); + } + } + + INLINE static void sdivrem(const ap_private &LHS, int64_t RHS, + ap_private &Quotient, ap_private &Remainder) { + if (LHS.isNegative()) { + if (RHS<0) + ap_private::udivrem(-LHS, -RHS, Quotient, Remainder); + else + ap_private::udivrem(-LHS, RHS, Quotient, Remainder); + Quotient = -Quotient; + Remainder = -Remainder; + } else if (RHS<0) { + ap_private::udivrem(LHS, -RHS, Quotient, Remainder); + Quotient = -Quotient; + } else { + ap_private::udivrem(LHS, RHS, Quotient, Remainder); + } + } + + template INLINE bool eq(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return (*this) == RHS; + } + + template INLINE bool ne(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return !((*this) == RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// the validity of the less-than relationship. + /// @returns true if *this < RHS when both are considered unsigned. + /// @brief Unsigned less than comparison + template INLINE bool ult(const ap_private<_AP_W1, _AP_S1, 1>& RHS) const { + uint64_t lhsZext = ((uint64_t(VAL)) << (64-_AP_W)) >> (64-_AP_W); + uint64_t rhsZext = ((uint64_t(RHS.VAL)) << (64-_AP_W1)) >> (64-_AP_W1); + return lhsZext < rhsZext; + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the less-than relationship. + /// @returns true if *this < RHS when both are considered signed. + /// @brief Signed less than comparison + template INLINE bool slt(const ap_private<_AP_W1, _AP_S1, 1>& RHS) const { + int64_t lhsSext = ((int64_t(VAL)) << (64-_AP_W)) >> (64-_AP_W); + int64_t rhsSext = ((int64_t(RHS.VAL)) << (64-_AP_W1)) >> (64-_AP_W1); + return lhsSext < rhsSext; + } + + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// validity of the less-or-equal relationship. + /// @returns true if *this <= RHS when both are considered unsigned. + /// @brief Unsigned less or equal comparison + template INLINE bool ule(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return ult(RHS) || eq(RHS); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the less-or-equal relationship. + /// @returns true if *this <= RHS when both are considered signed. + /// @brief Signed less or equal comparison + template INLINE bool sle(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return slt(RHS) || eq(RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// the validity of the greater-than relationship. + /// @returns true if *this > RHS when both are considered unsigned. + /// @brief Unsigned greather than comparison + template INLINE bool ugt(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return !ult(RHS) && !eq(RHS); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// the validity of the greater-than relationship. + /// @returns true if *this > RHS when both are considered signed. + /// @brief Signed greather than comparison + template INLINE bool sgt(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return !slt(RHS) && !eq(RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// validity of the greater-or-equal relationship. + /// @returns true if *this >= RHS when both are considered unsigned. + /// @brief Unsigned greater or equal comparison + template INLINE bool uge(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return !ult(RHS); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the greater-or-equal relationship. + /// @returns true if *this >= RHS when both are considered signed. + /// @brief Signed greather or equal comparison + template INLINE bool sge(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return !slt(RHS); + } + + INLINE ap_private abs() const { + if (isNegative()) + return -(*this); + return *this; + } + + ap_private<_AP_W, false> get() const { + ap_private<_AP_W,false> ret(*this); + return ret; + } + + INLINE static uint32_t getBitsNeeded(const char* str, uint32_t slen, uint8_t radix) { + return _AP_W; + } + + INLINE uint32_t getActiveBits() const { + uint32_t bits=_AP_W - countLeadingZeros(); + return bits?bits:1; + } + + INLINE double roundToDouble(bool isSigned=false) const { + const static uint64_t mask = ~0ULL << (APINT_BITS_PER_WORD - _AP_W); + return double(VAL); + } + + INLINE unsigned length() const { return _AP_W; } + + /*Reverse the contents of ap_private instance. I.e. LSB becomes MSB and vise versa*/ + INLINE ap_private& reverse () { + for (int i = 0; i < _AP_W/2; ++i) { + bool tmp = operator[](i); + if (operator[](_AP_W - 1 - i)) + set(i); + else + clear(i); + if (tmp) + set(_AP_W - 1 - i); + else + clear(_AP_W - 1 - i); + } + clearUnusedBits(); + return *this; + } + + /*Return true if the value of ap_private instance is zero*/ + INLINE bool iszero () const { + return isMinValue(); + } + + /* x < 0 */ + INLINE bool sign () const { + if (isNegative()) + return true; + return false; + } + + /* x[i] = !x[i] */ + INLINE void invert (int i) { + assert( i >= 0 && "Attempting to read bit with negative index"); + assert( i < _AP_W && "Attempting to read bit beyond MSB"); + flip(i); + } + + /* x[i] */ + INLINE bool test (int i) const { + assert( i >= 0 && "Attempting to read bit with negative index"); + assert( i < _AP_W && "Attempting to read bit beyond MSB"); + return operator[](i); + } + + //This is used for sc_lv and sc_bv, which is implemented by sc_uint + //Rotate an ap_private object n places to the left + INLINE void lrotate(int n) { + assert( n >= 0 && "Attempting to shift negative index"); + assert( n < _AP_W && "Shift value larger than bit width"); + operator = (shl(n) | lshr(_AP_W - n)); + } + + //This is used for sc_lv and sc_bv, which is implemented by sc_uint + //Rotate an ap_private object n places to the right + INLINE void rrotate(int n) { + assert( n >= 0 && "Attempting to shift negative index"); + assert( n < _AP_W && "Shift value larger than bit width"); + operator = (lshr(n) | shl(_AP_W - n)); + } + + //Set the ith bit into v + INLINE void set (int i, bool v) { + assert( i >= 0 && "Attempting to write bit with negative index"); + assert( i < _AP_W && "Attempting to write bit beyond MSB"); + v ? set(i) : clear(i); + } + + //Set the ith bit into v + INLINE void set_bit (int i, bool v) { + assert( i >= 0 && "Attempting to write bit with negative index"); + assert( i < _AP_W && "Attempting to write bit beyond MSB"); + v ? set(i) : clear(i); + } + + //Get the value of ith bit + INLINE bool get_bit (int i) const { + assert( i >= 0 && "Attempting to read bit with negative index"); + assert( i < _AP_W && "Attempting to read bit beyond MSB"); + return operator [](i); + } + + //complements every bit + INLINE void b_not() { + flip(); + } + + //Binary Arithmetic + //----------------------------------------------------------- +#define OP_BIN_AP(Sym,Rty, Fun) \ + template \ + INLINE \ + typename RType<_AP_W2,_AP_S2>::Rty \ + operator Sym (const ap_private<_AP_W2,_AP_S2>& op) const { \ + typename RType<_AP_W2,_AP_S2>::Rty lhs(*this); \ + typename RType<_AP_W2,_AP_S2>::Rty rhs(op); \ + return lhs.Fun(rhs); \ + } \ + + ///Bitwise and, or, xor + //OP_BIN_AP(&,logic, And) + //OP_BIN_AP(|,logic, Or) + //OP_BIN_AP(^,logic, Xor) + +#undef OP_BIN_AP + template + INLINE typename RType<_AP_W2,_AP_S2>::div + operator / (const ap_private<_AP_W2,_AP_S2>&op) const { + ap_private lhs=ap_private(*this); + ap_private rhs=ap_private(op); + return typename RType<_AP_W2,_AP_S2>::div((_AP_S||_AP_S2)?lhs.sdiv(rhs):lhs.udiv(rhs)); + } + + + template + INLINE typename RType<_AP_W2,_AP_S2>::mod + operator % (const ap_private<_AP_W2,_AP_S2>&op) const { + ap_private lhs=*this; + ap_private rhs=op; + typename RType<_AP_W2,_AP_S2>::mod res = typename RType<_AP_W2,_AP_S2>::mod (_AP_S?lhs.srem(rhs):lhs.urem(rhs)); + return res; + } + + +#define OP_ASSIGN_AP_2(Sym) \ + template \ + INLINE ap_private<_AP_W, _AP_S>& operator Sym##=(const ap_private<_AP_W2,_AP_S2>& op) \ + { \ + *this=operator Sym (op); \ + return *this; \ + } \ + + OP_ASSIGN_AP_2(/) + OP_ASSIGN_AP_2(%) +#undef OP_ASSIGN_AP_2 + + ///Bitwise assign: and, or, xor + //------------------------------------------------------------- + // OP_ASSIGN_AP(&) + // OP_ASSIGN_AP(^) + // OP_ASSIGN_AP(|) +#undef OP_ASSIGN_AP +#if 1 + + template + INLINE ap_private<_AP_W, _AP_S> + operator << (const ap_private<_AP_W2, _AP_S2>& op2) const { + uint32_t sh=op2.to_uint(); + return *this << sh; + } + + INLINE ap_private<_AP_W, _AP_S> + operator << (uint32_t sh) const { + return shl(sh); + } + +#endif + + template + INLINE ap_private<_AP_W, _AP_S> + operator >> (const ap_private<_AP_W2, _AP_S2>& op2) const { + uint32_t sh = op2.to_uint(); + return *this >> sh; + } + + INLINE ap_private<_AP_W, _AP_S> + operator >>(uint32_t sh) const { + ap_private<_AP_W, _AP_S> r(*this); + bool overflow=(sh>=_AP_W); + bool neg_v=r.isNegative(); + if(_AP_S) { + if(overflow) + neg_v?r.set():r.clear(); + else + return r.ashr(sh); + } else { + if(overflow) + r.clear(); + else + return r.lshr(sh); + } + return r; + } + + ///Shift assign + //------------------------------------------------------------------ +#define OP_ASSIGN_AP_3_SINGLE(Sym) \ + template \ + INLINE ap_private<_AP_W, _AP_S>& operator Sym##=(const ap_private<_AP_W2,_AP_S2>& op) \ + { \ + *this=operator Sym (op.getVal()); \ + return *this; \ + } + OP_ASSIGN_AP_3_SINGLE(>>) +#undef OP_ASSIGN_AP_3_SINGLE + + ///Comparisons + //----------------------------------------------------------------- + template + INLINE bool operator != (const ap_private<_AP_W2, _AP_S2, 1>& op) const { + return !(*this==op); + } + + template + INLINE bool operator > (const ap_private<_AP_W2, _AP_S2, 1>& op) const { + return op < *this; + } + + template + INLINE bool operator <= (const ap_private<_AP_W2, _AP_S2, 1>& op) const { + return !(*this>op); + } + + template + INLINE bool operator < (const ap_private<_AP_W2, _AP_S2, 1>& op) const { + enum { _AP_MAX_W = AP_MAX(_AP_W+(_AP_S||_AP_S2),_AP_W2+(_AP_S||_AP_S2))}; + ap_private<_AP_MAX_W, _AP_S> lhs(*this); + ap_private<_AP_MAX_W, _AP_S2> rhs(op); + if (_AP_S == _AP_S2) + return _AP_S?lhs.slt(rhs):lhs.ult(rhs); + else if (_AP_W < 32 && _AP_W2 < 32) + return lhs.slt(rhs); + else + if (_AP_S) + if (_AP_W2 >= _AP_W) + return lhs.ult(rhs); + else + return lhs.slt(rhs); + else + if (_AP_W >= _AP_W2) + return lhs.ult(rhs); + else + return lhs.slt(rhs); + } + + template + INLINE bool operator >=(const ap_private<_AP_W2, _AP_S2, 1>& op) const { + return !(*this + INLINE bool operator == (const ap_private<_AP_W2, _AP_S2, _AP_N2>& op) const { + return op == *this; + } + + template + INLINE bool operator != (const ap_private<_AP_W2, _AP_S2, _AP_N2>& op) const { + return !(op==*this); + } + + template + INLINE bool operator > (const ap_private<_AP_W2, _AP_S2, _AP_N2>& op) const { + return op < (*this); + } + + template + INLINE bool operator <= (const ap_private<_AP_W2, _AP_S2, _AP_N2>& op) const { + return op >= *this; + } + + template + INLINE bool operator <(const ap_private<_AP_W2, _AP_S2, _AP_N2>& op) const { + return op > *this; + } + + template + INLINE bool operator >=(const ap_private<_AP_W2,_AP_S2,_AP_N2>& op) const { + return op <= *this; + } + ///Bit and Part Select + //-------------------------------------------------------------- + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (int Hi, int Lo) { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (int Hi, int Lo) const { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(const_cast*>(this), Hi, Lo); + } + + INLINE ap_range_ref<_AP_W,_AP_S> + range (int Hi, int Lo) const { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>((const_cast*> (this)), Hi, Lo); + } + + INLINE ap_range_ref<_AP_W,_AP_S> + range (int Hi, int Lo) { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + range (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + range (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) const { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(const_cast(this), Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) const { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + return this->range(Hi, Lo); + } + + + INLINE ap_bit_ref<_AP_W,_AP_S> operator [] (uint32_t index) { + assert(index >= 0&&"Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S> (*this, (int)index); + } + + template + INLINE ap_bit_ref<_AP_W,_AP_S> operator [] (const ap_private<_AP_W2,_AP_S2> &index) { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S>( *this, index.to_int() ); + } + + template + INLINE bool operator [] (const ap_private<_AP_W2,_AP_S2>& index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + ap_bit_ref<_AP_W,_AP_S> br =operator [] (index); + return br.to_bool(); + } + + INLINE ap_bit_ref<_AP_W,_AP_S> bit (int index) { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S>( *this, index ); + } + + template + INLINE ap_bit_ref<_AP_W,_AP_S> bit (const ap_private<_AP_W2,_AP_S2> &index) { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W &&"Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S>( *this, index.to_int() ); + } + + INLINE bool bit (int index) const { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + ap_bit_ref<_AP_W,_AP_S> br(const_cast*>(this), index); + return br.to_bool(); + } + + template + INLINE bool bit (const ap_private<_AP_W2,_AP_S2>& index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + ap_bit_ref<_AP_W,_AP_S> br = bit(index); + return br.to_bool(); + } + + template + INLINE ap_concat_ref<_AP_W,ap_private<_AP_W, _AP_S>,_AP_W2,ap_private<_AP_W2,_AP_S2> > concat(const ap_private<_AP_W2,_AP_S2>& a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_private<_AP_W2,_AP_S2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W,ap_private<_AP_W, _AP_S>,_AP_W2,ap_private<_AP_W2,_AP_S2> > concat(ap_private<_AP_W2,_AP_S2>& a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_private<_AP_W2,_AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (const ap_private<_AP_W2, _AP_S2>& a2) const { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(const_cast& >(*this), const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (const ap_private<_AP_W2, _AP_S2>& a2) { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(*this, const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (ap_private<_AP_W2, _AP_S2>& a2) const { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(const_cast& >(*this), a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (ap_private<_AP_W2, _AP_S2>& a2) { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > + operator, (const ap_range_ref<_AP_W2, _AP_S2> &a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, + ap_range_ref<_AP_W2, _AP_S2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > + operator, (ap_range_ref<_AP_W2, _AP_S2> &a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, + ap_range_ref<_AP_W2, _AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, ap_bit_ref<_AP_W2, _AP_S2> > + operator, (const ap_bit_ref<_AP_W2, _AP_S2> &a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, + ap_bit_ref<_AP_W2, _AP_S2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, ap_bit_ref<_AP_W2, _AP_S2> > + operator, (ap_bit_ref<_AP_W2, _AP_S2> &a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, + ap_bit_ref<_AP_W2, _AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > + operator, (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > + operator, (ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) const { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) const { + return ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, a2); + } + + template + INLINE ap_private + operator & (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) { + return *this & a2.get(); + } + + template + INLINE ap_private + operator | (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) { + return *this | a2.get(); + } + + template + INLINE ap_private + operator ^ (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) { + return *this ^ a2.get(); + } + + + //Reduce operation + //----------------------------------------------------------- + INLINE bool and_reduce() const { + return (VAL & mask) == mask; + } + + INLINE bool nand_reduce() const { + return (VAL & mask) != mask; + } + + INLINE bool or_reduce() const { + return (bool)VAL; + } + + INLINE bool nor_reduce() const { + return VAL==0; + } + + INLINE bool xor_reduce() const { + unsigned int i=countPopulation(); + return (i%2)?true:false; + } + + INLINE bool xnor_reduce() const { + unsigned int i=countPopulation(); + return (i%2)?false:true; + } + + INLINE std::string to_string(uint8_t radix=2, bool sign=false) const { + return toString(radix, radix==10?_AP_S:sign); + } +}; +template +std::string ap_private<_AP_W, _AP_S, 1>::toString(uint8_t radix, bool wantSigned) const { + assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) && + "Radix should be 2, 8, 10, or 16!"); + static const char *digits[] = { + "0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f" + }; + std::string result; + if (radix != 10) { + // For the 2, 8 and 16 bit cases, we can just shift instead of divide + // because the number of bits per digit (1,3 and 4 respectively) divides + // equaly. We just shift until there value is zero. + + // First, check for a zero value and just short circuit the logic below. + if (*this == (uint64_t)(0)) + result = "0"; + else { + ap_private<_AP_W, false, 1> tmp(*this); + size_t insert_at = 0; + if (wantSigned && isNegative()) { + // They want to print the signed version and it is a negative value + // Flip the bits and add one to turn it into the equivalent positive + // value and put a '-' in the result. + tmp.flip(); + tmp++; + result = "-"; + insert_at = 1; + } + // Just shift tmp right for each digit width until it becomes zero + uint32_t shift = (radix == 16 ? 4 : (radix == 8 ? 3 : 1)); + uint64_t mask = radix - 1; + ap_private<_AP_W, false, 1> zero(0); + while (tmp.ne(zero)) { + unsigned digit = (unsigned)(tmp.VAL & mask); + result.insert(insert_at, digits[digit]); + tmp = tmp.lshr(shift); + } + } + return result; + } + + ap_private<_AP_W, false, 1> tmp(*this); + ap_private<6, false, 1> divisor(radix); + ap_private<_AP_W, _AP_S, 1> zero(0); + size_t insert_at = 0; + if (wantSigned && isNegative()) { + // They want to print the signed version and it is a negative value + // Flip the bits and add one to turn it into the equivalent positive + // value and put a '-' in the result. + tmp.flip(); + tmp++; + result = "-"; + insert_at = 1; + } + if (tmp == ap_private<_AP_W, false, 1>(0ULL)) + result = "0"; + else while (tmp.ne(zero)) { + ap_private<_AP_W, false, 1> APdigit = tmp%divisor; + ap_private<_AP_W, false, 1> tmp2 = tmp/divisor; + uint32_t digit = (uint32_t)(APdigit.getZExtValue()); + assert(digit < radix && "divide failed"); + result.insert(insert_at,digits[digit]); + tmp = tmp2; + } + return result; + +} + +#endif /* #ifndef LLVM_SUPPORT_MATHEXTRAS_H */ \ No newline at end of file diff --git a/hls_2018/router_03/main.cpp b/hls_2018/router_03/main.cpp new file mode 100755 index 0000000..2a4e7f5 --- /dev/null +++ b/hls_2018/router_03/main.cpp @@ -0,0 +1,97 @@ +/** + * main.cpp + * + * for Vivado HLS + */ + +#ifdef SOFTWARE +#include "ap_int.h" +#else +#include +#endif + +#ifdef CALCTIME +#include +#include +#endif + +#include "router.hpp" + +#define PRINT_SOLUTION + + +int main(int argc, char *argv[]) { + using namespace std; + + // Test data // + // NL_Q00.txt + //char boardstr[BOARDSTR_SIZE] = "X10Y05Z3L0000107041L0004107002L0102102021L0900100003"; + // NL_Q06.txt + char boardstr[BOARDSTR_SIZE] = "X10Y18Z2L0900109002L0901105012L0902103052L0903103062L0904100102L0905106012L0906109022L0717109102L0808109112L0017209172L0401200072L0912208152L0009201092L0709209092L0901206052L0309204092L0701209072L0101201022L0011202152L0016202162"; + // NL_Q08.txt + //char boardstr[BOARDSTR_SIZE] = "X17Y20Z2L0000103022L1603115052L0916107032L0302108012L1104111042L1002100002L0919116162L1616113182L1001115012L0500201182L1603213152L0600210022"; + + // Read boardstr from command line + if (1 < argc) { + // From stdin + if(argv[1][0]!='X') + { + char* c_p=fgets(boardstr, BOARDSTR_SIZE, stdin); + int length=strlen(c_p); + boardstr[length-1]=0; + } + else + { + strcpy(boardstr, argv[1]); + } + } + + // Seed value + int seed = 12345; + if (2 < argc) { + seed = atoi(argv[2]); + } + +#ifdef PRINT_SOLUTION + int size_x = (boardstr[1] - '0') * 10 + (boardstr[2] - '0'); + int size_y = (boardstr[4] - '0') * 10 + (boardstr[5] - '0'); + int size_z = (boardstr[7] - '0'); +#endif + + // Solver + ap_int<32> status; + clock_t clock_start, clock_done; + clock_start = clock(); + bool result = pynqrouter(boardstr, seed, &status); + clock_done = clock(); + if (result) { + cout << endl << "Test Passed!" << endl; + } else { + cout << endl << "Test Failed!" << endl; + } + cout << "status = " << (int)status << endl; + cout << "elapsed = " << ((double)(clock_done - clock_start) / CLOCKS_PER_SEC) << endl << endl; + +#ifdef PRINT_SOLUTION + cout << "SOLUTION" << endl; + cout << "========" << endl; + cout << "SIZE " << size_x << "X" << size_y << "X" << size_z << endl; + for (int z = 0; z < size_z; z++) { + cout << "LAYER " << (z + 1) << endl; + for (int y = 0; y < size_y; y++) { + for (int x = 0; x < size_x; x++) { + if (x != 0) { + cout << ","; + } + int i = ((x * MAX_WIDTH + y) << BITWIDTH_Z) | z; + cout << setfill('0') << setw(3) << right << (unsigned int)(unsigned char)(boardstr[i]); + //cout << (unsigned int)(unsigned char)(boardstr[i]); + } + cout << endl; + } + } +#endif + + return 0; +} + diff --git a/hls_2018/router_03/router.cpp b/hls_2018/router_03/router.cpp index a2e01cb..adf00df 100755 --- a/hls_2018/router_03/router.cpp +++ b/hls_2018/router_03/router.cpp @@ -459,7 +459,7 @@ void pq_push(ap_uint<32> pq_nodes[MAX_PQ], ap_uint<16> priority, ap_uint<16> dat ap_uint p = (*pq_len) >> 1; // parent node PQ_PUSH_LOOP: while (i > 1 && (ap_uint<16>)(pq_nodes[p] & PQ_PRIORITY_MASK) >= priority) { -#pragma HLS LOOP_TRIPCOUNT min=0 max=16 +#pragma HLS LOOP_TRIPCOUNT min=0 max=15 /** Set!: min=0 max=PQ_BIT **/ pq_nodes[i] = pq_nodes[p]; i = p; @@ -482,7 +482,7 @@ void pq_pop(ap_uint<32> pq_nodes[MAX_PQ], ap_uint<16> *ret_priority, ap_uint<16> PQ_POP_LOOP: while (1) { -#pragma HLS LOOP_TRIPCOUNT min=1 max=16 +#pragma HLS LOOP_TRIPCOUNT min=1 max=15 /** Set!: min=0 max=PQ_BIT **/ ap_uint c1 = i << 1; // child node(left) ap_uint c2 = c1 + 1; // child node(right) diff --git a/hls_2018/router_04/Makefile b/hls_2018/router_04/Makefile new file mode 100755 index 0000000..8f79e7a --- /dev/null +++ b/hls_2018/router_04/Makefile @@ -0,0 +1,20 @@ +TARGET = sim +OBJS = $(CPPS:.cpp=.o) +CPPS = $(wildcard *.cpp) +CXX = g++ +CXXFLAGS = -O3 -Wall -Wno-unknown-pragmas -Wno-unused-label -DSOFTWARE -DCALCTIME + +all: $(TARGET) + +$(TARGET): $(OBJS) + $(CXX) -O3 -o $@ $(OBJS) + +run: + python3 ../NLGenerator.py -x 20 -y 20 -z 6 -l 100;\ + python3 ./gen_boardstr.py Q-20x20x5_100_10.txt |\ + ./$(TARGET) - + + +clean: + rm *.o + rm $(TARGET) diff --git a/hls_2018/router_04/Makefile.cygwin b/hls_2018/router_04/Makefile.cygwin new file mode 100755 index 0000000..866fdcd --- /dev/null +++ b/hls_2018/router_04/Makefile.cygwin @@ -0,0 +1,14 @@ +TARGET = sim +OBJS = $(CPPS:.cpp=.o) +CPPS = $(wildcard *.cpp) +CXX = g++ +CXXFLAGS = -O3 -Wall -Wno-unknown-pragmas -Wno-unused-label -DSOFTWARE -DCALCTIME + +all: $(TARGET) + +$(TARGET): $(OBJS) + $(CXX) -O3 -Wl,--stack,33554432 -o $@ $(OBJS) + +clean: + rm *.o + rm $(TARGET) diff --git a/hls_2018/router_04/ap_int.h b/hls_2018/router_04/ap_int.h new file mode 100755 index 0000000..b8d9fdc --- /dev/null +++ b/hls_2018/router_04/ap_int.h @@ -0,0 +1,521 @@ +/* + * Copyright 2012 Xilinx, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __AESL_AP_SIM_H__ +#define __AESL_AP_SIM_H__ + +#ifndef __cplusplus +#error C++ is required to include this header file +#else + +#include "etc/ap_int_sim.h" +#include "etc/ap_fixed_sim.h" + +//Forward declaration +template class ap_fixed; +template class ap_ufixed; +template class ap_int; +template class ap_uint; + +//AP_INT +//-------------------------------------------------------- +template +class ap_int : public ap_private<_AP_W, true> { +#ifdef _MSC_VER +#pragma warning(disable: 4521 4522) +#endif /* #ifdef _MSC_VER */ +public: + typedef ap_private<_AP_W, true> Base; + + //Constructor + INLINE ap_int(): Base() {} + template + INLINE ap_int(const volatile ap_int<_AP_W2> &op):Base((const ap_private<_AP_W2,true> &)(op)) {} + + template + INLINE ap_int(const ap_int<_AP_W2> &op):Base((const ap_private<_AP_W2,true> &)(op)) {} + + template + INLINE ap_int(const ap_uint<_AP_W2> &op):Base((const ap_private<_AP_W2,false> &)(op)) {} + + template + INLINE ap_int(const volatile ap_uint<_AP_W2> &op):Base((const ap_private<_AP_W2,false> &)(op)) {} + + template + INLINE ap_int(const ap_range_ref<_AP_W2, _AP_S2>& ref):Base(ref) {} + + template + INLINE ap_int(const ap_bit_ref<_AP_W2, _AP_S2>& ref):Base(ref) {} + + template + INLINE ap_int(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& ref):Base(ref) {} + + template + INLINE ap_int(const ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op.to_ap_private()) {} + + template + INLINE ap_int(const ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op.to_ap_private()) {} + + template + INLINE ap_int(const volatile ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op.to_ap_private()) {} + + template + INLINE ap_int(const volatile ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op.to_ap_private()) {} + + template + INLINE ap_int(const ap_private<_AP_W2, _AP_S2>& op):Base(op) {} + + template + INLINE ap_int(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, + _AP_N2>& op):Base(op) {} + + template + INLINE ap_int(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, + _AP_N2>& op):Base(op) {} + + template + INLINE ap_int(const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& op):Base(op.to_ap_private()) {} + +#define CTOR(TYPE) \ + INLINE ap_int(TYPE v):Base(v) {} + CTOR(bool) + CTOR(signed char) + CTOR(unsigned char) + CTOR(short) + CTOR(unsigned short) + CTOR(int) + CTOR(unsigned int) + CTOR(long) + CTOR(unsigned long) + CTOR(unsigned long long) + CTOR(long long) + CTOR(float) + CTOR(double) + CTOR(const char*) + CTOR(const std::string&) +#undef CTOR + INLINE ap_int(const char* str, signed char rd):Base(str, rd) {} + //Assignment + //Another form of "write" + INLINE void operator = (const ap_int<_AP_W>& op2) volatile { + const_cast(this)->operator = (op2); + } + + INLINE void operator = (const volatile ap_int<_AP_W>& op2) volatile { + const_cast(this)->operator = (op2); + } + + INLINE ap_int<_AP_W>& operator = (const volatile ap_int<_AP_W>& op2) { + Base::operator = (const_cast& >(op2)); + return *this; + } + + INLINE ap_int<_AP_W>& operator = (const ap_int<_AP_W>& op2) { + Base::operator = ((const ap_private<_AP_W, true>&)op2); + return *this; + } +}; + +//AP_UINT +//--------------------------------------------------------------- +template +class ap_uint: public ap_private<_AP_W, false> { +#ifdef _MSC_VER +#pragma warning( disable : 4521 4522 ) +#endif +public: + typedef ap_private<_AP_W, false> Base; + //Constructor + INLINE ap_uint(): Base() {} + INLINE ap_uint(const ap_uint<_AP_W>& op) :Base(dynamic_cast&>(op)) {} + INLINE ap_uint(const volatile ap_uint<_AP_W>& op):Base(dynamic_cast&>(op)){} + template + INLINE ap_uint(const volatile ap_uint<_AP_W2> &op):Base((const ap_private<_AP_W2, false>&)(op)) {} + + template + INLINE ap_uint(const ap_uint<_AP_W2> &op) : Base((const ap_private<_AP_W2, false>&)(op)){} + + template + INLINE ap_uint(const ap_int<_AP_W2> &op) : Base((const ap_private<_AP_W2, true>&)(op)) {} + + template + INLINE ap_uint(const volatile ap_int<_AP_W2> &op) : Base((const ap_private<_AP_W2, false>&)(op)) {} + + template + INLINE ap_uint(const ap_range_ref<_AP_W2, _AP_S2>& ref):Base(ref) {} + + template + INLINE ap_uint(const ap_bit_ref<_AP_W2, _AP_S2>& ref):Base(ref) {} + + template + INLINE ap_uint(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& ref):Base(ref) {} + + template + INLINE ap_uint(const ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op.to_ap_private()) {} + + template + INLINE ap_uint(const ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op.to_ap_private()) {} + + template + INLINE ap_uint(const volatile ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op.to_ap_private()) {} + + template + INLINE ap_uint(const volatile ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op) {} + + template + INLINE ap_uint(const ap_private<_AP_W2, _AP_S2>& op):Base(op) {} + + template + INLINE ap_uint(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, + _AP_N2>& op):Base(op) {} + + template + INLINE ap_uint(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, + _AP_N2>& op):Base(op) {} + + template + INLINE ap_uint(const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& op):Base(op.to_ap_private()) {} + +#define CTOR(TYPE) \ + INLINE ap_uint(TYPE v):Base(v) {} + CTOR(bool) + CTOR(signed char) + CTOR(unsigned char) + CTOR(short) + CTOR(unsigned short) + CTOR(int) + CTOR(unsigned int) + CTOR(long) + CTOR(unsigned long) + CTOR(unsigned long long) + CTOR(long long) + CTOR(float) + CTOR(double) + CTOR(const char*) + CTOR(const std::string&) +#undef CTOR + INLINE ap_uint(const char* str, signed char rd):Base(str, rd) {} + //Assignment + //Another form of "write" + INLINE void operator = (const ap_uint<_AP_W>& op2) volatile { + Base::operator = (op2); + } + + INLINE void operator = (const volatile ap_uint<_AP_W>& op2) volatile { + Base::operator = (op2); + } + + INLINE ap_uint<_AP_W>& operator = (const volatile ap_uint<_AP_W>& op2) { + Base::operator = (op2); + return *this; + } + + INLINE ap_uint<_AP_W>& operator = (const ap_uint<_AP_W>& op2) { + Base::operator = ((const ap_private<_AP_W, false>&)(op2)); + return *this; + } +}; + +#define ap_bigint ap_int +#define ap_biguint ap_uint + +//AP_FIXED +//--------------------------------------------------------------------- +template +class ap_fixed: public ap_fixed_base<_AP_W, _AP_I, true, _AP_Q, _AP_O, _AP_N> { +#ifdef _MSC_VER +#pragma warning( disable : 4521 4522 ) +#endif +public: + typedef ap_fixed_base<_AP_W, _AP_I, true, _AP_Q, _AP_O, _AP_N> Base; + //Constructor + INLINE ap_fixed():Base() {} + + template + INLINE ap_fixed(const ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, + _AP_N2>& op): Base(op) {} + + template + INLINE ap_fixed(const ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, + _AP_N2>& op): Base(ap_fixed_base<_AP_W2, _AP_I2, + false, _AP_Q2, _AP_O2, _AP_N2>(op)) {} + + template + INLINE ap_fixed(const ap_int<_AP_W2>& op): + Base(ap_private<_AP_W2, true>(op)) {} + + template + INLINE ap_fixed(const ap_uint<_AP_W2>& op):Base(ap_private<_AP_W2, false>(op)) {} + + template + INLINE ap_fixed(const volatile ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, + _AP_N2>& op): Base(ap_fixed_base<_AP_W2, _AP_I2, + true, _AP_Q2, _AP_O2, _AP_N2>(op)) {} + + template + INLINE ap_fixed(const volatile ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, + _AP_N2>& op): Base(ap_fixed_base<_AP_W2, _AP_I2, + false, _AP_Q2, _AP_O2, _AP_N2>(op)) {} + + template + INLINE ap_fixed(const volatile ap_int<_AP_W2>& op): + Base(ap_private<_AP_W2, true>(op)) {} + + template + INLINE ap_fixed(const volatile ap_uint<_AP_W2>& op):Base(op) {} + + template + INLINE ap_fixed(const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& op):Base(op) {} + + template + INLINE ap_fixed(const ap_bit_ref<_AP_W2, _AP_S2>& op): + Base(op) {} + + template + INLINE ap_fixed(const ap_range_ref<_AP_W2, _AP_S2>& op): + Base(op) {} + + template + INLINE ap_fixed(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& op): + Base(op) {} + + template + INLINE ap_fixed(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& op): Base(op) {} + + template + INLINE ap_fixed(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& op): Base(op) {} + + template + INLINE ap_fixed(const ap_private<_AP_W2, _AP_S2>& op):Base(op) {} + + #define CTOR(TYPE) \ + INLINE ap_fixed(TYPE v):Base(v) {} + CTOR(bool) + CTOR(signed char) + CTOR(unsigned char) + CTOR(short) + CTOR(unsigned short) + CTOR(int) + CTOR(unsigned int) + CTOR(long) + CTOR(unsigned long) + CTOR(unsigned long long) + CTOR(long long) + CTOR(float) + CTOR(double) + CTOR(const char*) + CTOR(const std::string&) +#undef CTOR + INLINE ap_fixed(const char* str, signed char rd):Base(str, rd) {} + + //Assignment + INLINE ap_fixed& operator = (const ap_fixed<_AP_W, _AP_I, + _AP_Q, _AP_O, _AP_N>& op) { + Base::operator = (op); + return *this; + } + + INLINE ap_fixed& operator = (const volatile ap_fixed<_AP_W, _AP_I, + _AP_Q, _AP_O, _AP_N>& op) { + Base::operator = (op); + return *this; + } +}; + +//AP_ UFIXED +//--- ---------------------------------------------------------------- +template +class ap_ufixed : public ap_fixed_base<_AP_W, _AP_I, false, _AP_Q, _AP_O, _AP_N> { +#ifdef _MSC_VER +#pragma warning(disable: 4521 4522) +#endif /* #ifdef _MSC_VER */ +public: + typedef ap_fixed_base<_AP_W, _AP_I, false, _AP_Q, _AP_O, _AP_N> Base; + + //Constructor + INLINE ap_ufixed():Base() {} + + template + INLINE ap_ufixed(const ap_fixed<_AP_W2, _AP_I2, _AP_Q2, + _AP_O2, _AP_N2>& op) : Base(ap_fixed_base<_AP_W2, + _AP_I2, true, _AP_Q2, _AP_O2, _AP_N2>(op)) {} + + template + INLINE ap_ufixed(const ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, + _AP_O2, _AP_N2>& op): Base(ap_fixed_base<_AP_W2, _AP_I2, + false, _AP_Q2, _AP_O2, _AP_N2>(op)) {} + + template + INLINE ap_ufixed(const ap_int<_AP_W2>& op): + Base((const ap_private<_AP_W2, true>&)(op)) {} + + template + INLINE ap_ufixed(const ap_uint<_AP_W2>& op): + Base((const ap_private<_AP_W2, false>&)(op)) {} + + template + INLINE ap_ufixed(const volatile ap_fixed<_AP_W2, _AP_I2, _AP_Q2, + _AP_O2, _AP_N2>& op) : Base(ap_fixed_base<_AP_W2, + _AP_I2, true, _AP_Q2, _AP_O2, _AP_N2>(op)) {} + + template + INLINE ap_ufixed(const volatile ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, + _AP_O2, _AP_N2>& op): Base(ap_fixed_base<_AP_W2, _AP_I2, + false, _AP_Q2, _AP_O2, _AP_N2>(op)) {} + + template + INLINE ap_ufixed(const volatile ap_int<_AP_W2>& op): + Base(ap_private<_AP_W2, true>(op)) {} + + template + INLINE ap_ufixed(const volatile ap_uint<_AP_W2>& op): + Base(ap_private<_AP_W2, false>(op)) {} + + template + INLINE ap_ufixed(const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2>& op):Base(op) {} + + template + INLINE ap_ufixed(const ap_bit_ref<_AP_W2, _AP_S2>& op): + Base(op) {} + + template + INLINE ap_ufixed(const ap_range_ref<_AP_W2, _AP_S2>& op): + Base(op) {} + + template + INLINE ap_ufixed(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& op): + Base(op) {} + + template + INLINE ap_ufixed(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& op): Base(op) {} + + template + INLINE ap_ufixed(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& op): Base(op) {} + + template + INLINE ap_ufixed(const ap_private<_AP_W2, _AP_S2>& op):Base(op) {} + + #define CTOR(TYPE) \ + INLINE ap_ufixed(TYPE v):Base(v) {} + CTOR(bool) + CTOR(signed char) + CTOR(unsigned char) + CTOR(short) + CTOR(unsigned short) + CTOR(int) + CTOR(unsigned int) + CTOR(long) + CTOR(unsigned long) + CTOR(unsigned long long) + CTOR(long long) + CTOR(float) + CTOR(double) + CTOR(const char*) + CTOR(const std::string&) +#undef CTOR + INLINE ap_ufixed(const char* str, signed char rd):Base(str, rd) {} + + //Assignment + INLINE ap_ufixed& operator = (const ap_ufixed<_AP_W, _AP_I, + _AP_Q, _AP_O, _AP_N>& op) { + Base::operator = (op); + return *this; + } + + INLINE ap_ufixed& operator = (const volatile ap_ufixed<_AP_W, _AP_I, + _AP_Q, _AP_O, _AP_N>& op) { + Base::V = const_cast(op); + return *this; + } +}; + +#if defined(SYSTEMC_H) || defined(SYSTEMC_INCLUDED) +template +INLINE void sc_trace(sc_core::sc_trace_file *tf, const ap_int<_AP_W> &op, + const std::string &name) { + if (tf) + tf->trace(sc_dt::sc_lv<_AP_W>(op.to_string(2).c_str()), name); +} + +template +INLINE void sc_trace(sc_core::sc_trace_file *tf, const ap_uint<_AP_W> &op, + const std::string &name) { + if (tf) + tf->trace(sc_dt::sc_lv<_AP_W>(op.to_string(2).c_str()), name); +} + +template +INLINE void sc_trace(sc_core::sc_trace_file *tf, const ap_fixed<_AP_W, _AP_I, _AP_Q, _AP_O, _AP_N >&op, const std::string &name) { + tf->trace(sc_dt::sc_lv<_AP_W>(op.to_string(2).c_str()), name); +} + +template +INLINE void sc_trace(sc_core::sc_trace_file *tf, const ap_ufixed<_AP_W, _AP_I, _AP_Q, _AP_O, _AP_N >&op, const std::string &name) { + tf->trace(sc_dt::sc_lv<_AP_W>(op.to_string(2).c_str()), name); +} +#endif /* #if defined(SYSTEMC_H) || defined(SYSTEMC_INCLUDED) */ +#endif /* #ifndef __cplusplus */ +#endif /* #ifndef __AESL_AP_SIM_H__ */ \ No newline at end of file diff --git a/hls_2018/router_04/etc/ap_fixed_sim.h b/hls_2018/router_04/etc/ap_fixed_sim.h new file mode 100755 index 0000000..5be571d --- /dev/null +++ b/hls_2018/router_04/etc/ap_fixed_sim.h @@ -0,0 +1,2451 @@ +/* + * Copyright 2012 Xilinx, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __AESL_GCC_AP_FIXED_H__ +#define __AESL_GCC_AP_FIXED_H__ + +#ifndef __cplusplus + #error C++ is required to include this header file +#endif /* #ifndef __cplusplus */ + + +#include +#ifndef __AESL_APDT_IN_SCFLOW__ + #include "etc/ap_int_sim.h" +#else + #include "../etc/ap_private.h" +#endif /* #ifndef __AESL_APDT_IN_SCFLOW__ */ + +#define FLOAT_MAN 23 +#define FLOAT_EXP 8 +#define DOUBLE_MAN 52 +#define DOUBLE_EXP 11 +// #define DOUBLE_MAN_MASK (~0ULL >> (64-DOUBLE_MAN-2)) +#define DOUBLE_MAN_MASK 0x3fffffffffffffULL +#define BIAS(e) ((1ULL<<(e-1))-1) +#define FLOAT_BIAS BIAS(FLOAT_EXP) +#define DOUBLE_BIAS BIAS(DOUBLE_EXP) + +/// Forward declaration. +template struct ap_fixed_base; + +///Proxy class, which allows bit selection to be used as both rvalue(for reading) and +//lvalue(for writing) +template +struct af_bit_ref { +#ifdef _MSC_VER + #pragma warning(disable: 4521 4522) +#endif /* #ifdef _MSC_VER */ + ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& d_bv; + int d_index; +public: + INLINE af_bit_ref(const af_bit_ref<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& ref): + d_bv(ref.d_bv), d_index(ref.d_index) {} + + INLINE af_bit_ref(ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>* bv, int index=0): + d_bv(*bv),d_index(index) {} + + INLINE operator bool() const { + return d_bv.V[d_index]; + } + + INLINE af_bit_ref& operator=(unsigned long long val) { + if (val) + d_bv.V.set(d_index); + else + d_bv.V.clear(d_index); + return *this; + } + + template + INLINE af_bit_ref& operator =(const ap_private<_AP_W2,_AP_S2>& val) { + return operator=(val!=0); + } + + INLINE af_bit_ref& operator =(const af_bit_ref<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& val) { + return operator=((unsigned long long)(bool)val); + } + + template + INLINE af_bit_ref operator=(const af_bit_ref<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& val) { + return operator=((unsigned long long)(bool)val); + } + + template + INLINE af_bit_ref& operator = ( const ap_bit_ref<_AP_W2, _AP_S2> &val) { + return operator =((unsigned long long) (bool) val); + } + + template + INLINE af_bit_ref& operator = ( const ap_range_ref<_AP_W2,_AP_S2>& val) { + return operator =((const ap_private<_AP_W2, false>) val); + } + + template + INLINE af_bit_ref& operator= (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& val) { + return operator=((const ap_private<_AP_W2, false>)(val)); + } + + template + INLINE af_bit_ref& operator= (const ap_concat_ref<_AP_W2, _AP_T3, _AP_W3, _AP_T3>& val) { + return operator=((const ap_private<_AP_W2 + _AP_W3, false>)(val)); + } + + template + INLINE ap_concat_ref<1, af_bit_ref, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (ap_private<_AP_W2, _AP_S2>& op) { + return ap_concat_ref<1, af_bit_ref, _AP_W2, + ap_private<_AP_W2, _AP_S2> >(*this, op); + } + + template + INLINE ap_concat_ref<1, af_bit_ref, 1, ap_bit_ref<_AP_W2, _AP_S2> > + operator, (const ap_bit_ref<_AP_W2, _AP_S2> &op) { + return ap_concat_ref<1, af_bit_ref, 1, + ap_bit_ref<_AP_W2, _AP_S2> >(*this, + const_cast& >(op)); + } + + template + INLINE ap_concat_ref<1, af_bit_ref, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > + operator, (const ap_range_ref<_AP_W2, _AP_S2> &op) { + return ap_concat_ref<1, af_bit_ref, _AP_W2, + ap_range_ref<_AP_W2, _AP_S2> >(*this, + const_cast& >(op)); + } + + template + INLINE ap_concat_ref<1, af_bit_ref, _AP_W2 + _AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > + operator, (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &op) { + return ap_concat_ref<1, af_bit_ref, _AP_W2 + _AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(*this, + const_cast& >(op)); + } + + template + INLINE ap_concat_ref<1, af_bit_ref, _AP_W2, + af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &op) { + return ap_concat_ref<1, af_bit_ref, _AP_W2, + af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, + _AP_N2> >(*this, const_cast& >(op)); + } + + template + INLINE ap_concat_ref<1, af_bit_ref, 1, + af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &op) { + return ap_concat_ref<1, af_bit_ref, 1, + af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, + const_cast& >(op)); + } + + template + INLINE bool operator == (const af_bit_ref<_AP_W2, _AP_I2, + _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) { + return get() == op.get(); + } + + template + INLINE bool operator != (const af_bit_ref<_AP_W2, _AP_I2, + _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) { + return get() != op.get(); + } + + INLINE bool operator ~ () const { + bool bit = (d_bv.V)[d_index]; + return bit ? false : true; + } + + INLINE int length() const { + return 1; + } + + INLINE bool get() { + return d_bv.V[d_index]; + } + + INLINE bool get() const { + return d_bv.V[d_index]; + } + + INLINE std::string to_string() const { + return d_bv.V[d_index] ? "1" : "0"; + } +}; + +///Range(slice) reference +//------------------------------------------------------------ +template +struct af_range_ref { +#ifdef _MSC_VER + #pragma warning(disable: 4521 4522) +#endif /* #ifdef _MSC_VER */ + ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &d_bv; + int l_index; + int h_index; + +public: + INLINE af_range_ref(const af_range_ref<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& ref): + d_bv(ref.d_bv), l_index(ref.l_index), h_index(ref.h_index) {} + + INLINE af_range_ref(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>* bv, int h, int l): + d_bv(*bv),l_index(l),h_index(h) { + //if (h < l) + // fprintf(stderr, + //"Warning! The bits selected will be returned in reverse order\n"); + } + + INLINE operator ap_private<_AP_W, false> () const { + if (h_index >= l_index) { + ap_private<_AP_W, false> val(d_bv.V); + ap_private<_AP_W,false> mask(-1); + mask>>=_AP_W-(h_index-l_index+1); + val>>=l_index; + return val&=mask; + } else { + ap_private<_AP_W, false> val = 0; + for (int i=0, j=l_index;j>=0&&j>=h_index;j--,i++) + if ((d_bv.V)[j]) val.set(i); + return val; + } + } + + INLINE operator unsigned long long() const { + return get().to_uint64(); + } + + template + INLINE af_range_ref& operator =(const ap_private<_AP_W2,_AP_S2>& val) { + ap_private<_AP_W, false> vval= ap_private<_AP_W, false>(val); + if (l_index > h_index) { + for (int i=0, j=l_index;j>=0&&j>=h_index;j--,i++) + vval[i]? d_bv.V.set(j):d_bv.V.clear(j); + } else { + ap_private<_AP_W,false> mask(-1); + if (l_index>0) { + mask<<=l_index; + vval<<=l_index; + } + if (h_index<_AP_W-1) { + ap_private<_AP_W,false> mask2(-1); + mask2>>=_AP_W-h_index-1; + mask&=mask2; + vval&=mask2; + } + mask.flip(); + d_bv.V &= mask; + d_bv.V |= vval; + } + return *this; + } + + INLINE af_range_ref& operator = (unsigned long long val) { + const ap_private<_AP_W, false> tmpVal(val); + return operator = (tmpVal); + } + + template + INLINE af_range_ref& operator = + (const ap_concat_ref <_AP_W3, _AP_T3, _AP_W4, _AP_T4>& val) { + const ap_private<_AP_W, false> tmpVal(val); + return operator = (tmpVal); + } + + template + INLINE af_range_ref& operator =(const ap_bit_ref<_AP_W3, _AP_S3>& val) { + const ap_private<_AP_W, false> tmpVal(val); + return operator = (tmpVal); + } + + template + INLINE af_range_ref& operator =(const ap_range_ref<_AP_W3,_AP_S3>& val) { + const ap_private<_AP_W, false> tmpVal(val); + return operator =(tmpVal); + } + + template + INLINE af_range_ref& operator= (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& val) { + const ap_private<_AP_W2, false> tmp= val.get(); + return operator = (tmp); + } + + INLINE af_range_ref& operator= (const af_range_ref<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& val) { + const ap_private<_AP_W, false> tmp= val.get(); + return operator = (tmp); + } + + template + INLINE af_range_ref& operator= (const ap_fixed_base<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& val) { + return operator=(val.to_ap_private()); + } + + template + INLINE bool operator == (const ap_range_ref<_AP_W2, _AP_S2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs==rhs; + } + + template + INLINE bool operator != (const ap_range_ref<_AP_W2, _AP_S2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs!=rhs; + } + + template + INLINE bool operator > (const ap_range_ref<_AP_W2, _AP_S2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs>rhs; + } + + template + INLINE bool operator >= (const ap_range_ref<_AP_W2, _AP_S2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs>=rhs; + } + + template + INLINE bool operator < (const ap_range_ref<_AP_W2, _AP_S2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs + INLINE bool operator <= (const ap_range_ref<_AP_W2, _AP_S2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs<=rhs; + } + + template + INLINE bool operator == (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs==rhs; + } + + template + INLINE bool operator != (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs!=rhs; + } + + template + INLINE bool operator > (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs>rhs; + } + + template + INLINE bool operator >= (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs>=rhs; + } + + template + INLINE bool operator < (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs + INLINE bool operator <= (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs<=rhs; + } + + template + INLINE void set(const ap_private<_AP_W2,false>& val) { + ap_private<_AP_W,_AP_S> vval=val; + if (l_index>h_index) { + for (int i=0, j=l_index;j>=0&&j>=h_index;j--,i++) + vval[i]? d_bv.V.set(j):d_bv.V.clear(j); + } else { + ap_private<_AP_W,_AP_S> mask(-1); + if (l_index>0) { + ap_private<_AP_W,false> mask1(-1); + mask1>>=_AP_W-l_index; + mask1.flip(); + mask=mask1; + //vval&=mask1; + vval<<=l_index; + } + if (h_index<_AP_W-1) { + ap_private<_AP_W,false> mask2(-1); + mask2<<=h_index+1; + mask2.flip(); + mask&=mask2; + vval&=mask2; + } + mask.flip(); + d_bv&=mask; + d_bv|=vval; + } + + } + + INLINE ap_private<_AP_W,false> get() const { + if (h_index val(0); + for (int i=0, j=l_index;j>=0&&j>=h_index;j--,i++) + if ((d_bv.V)[j]) val.set(i); + return val; + } else { + ap_private<_AP_W, false> val = ap_private<_AP_W,false>(d_bv.V); + val>>= l_index; + if (h_index<_AP_W-1) + { + ap_private<_AP_W,false> mask(-1); + mask>>=_AP_W-(h_index-l_index+1); + val&=mask; + } + return val; + } + } + + template + INLINE ap_concat_ref<_AP_W, af_range_ref, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (ap_private<_AP_W2, _AP_S2>& op) { + return ap_concat_ref<_AP_W, af_range_ref, _AP_W2, + ap_private<_AP_W2, _AP_S2> >(*this, op); + } + + template + INLINE ap_concat_ref<_AP_W, af_range_ref, 1, ap_bit_ref<_AP_W2, _AP_S2> > + operator, (const ap_bit_ref<_AP_W2, _AP_S2> &op) { + return ap_concat_ref<_AP_W, af_range_ref, 1, + ap_bit_ref<_AP_W2, _AP_S2> >(*this, + const_cast& >(op)); + } + + template + INLINE ap_concat_ref<_AP_W, af_range_ref, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > + operator, (const ap_range_ref<_AP_W2, _AP_S2> &op) { + return ap_concat_ref<_AP_W, af_range_ref, _AP_W2, + ap_range_ref<_AP_W2, _AP_S2> >(*this, + const_cast& >(op)); + } + + template + INLINE ap_concat_ref<_AP_W, af_range_ref, _AP_W2 + _AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > + operator, (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &op) { + return ap_concat_ref<_AP_W, af_range_ref, _AP_W2 + _AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(*this, + const_cast& >(op)); + } + + template + INLINE ap_concat_ref<_AP_W, af_range_ref, _AP_W2, + af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &op) { + return ap_concat_ref<_AP_W, af_range_ref, _AP_W2, + af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, + const_cast& > (op)); + } + + template + INLINE ap_concat_ref<_AP_W, af_range_ref, 1, + af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &op) { + return ap_concat_ref<_AP_W, af_range_ref, 1, + af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, + const_cast& >(op)); + } + + INLINE int length() const { + return h_index>=l_index?h_index-l_index+1:l_index-h_index+1; + } + + INLINE int to_int() const { + ap_private<_AP_W,false> val=get(); + return val.to_int(); + } + + INLINE unsigned int to_uint() const { + ap_private<_AP_W,false> val=get(); + return val.to_uint(); + } + + INLINE long to_long() const { + ap_private<_AP_W,false> val=get(); + return val.to_long(); + } + + INLINE unsigned long to_ulong() const { + ap_private<_AP_W,false> val=get(); + return val.to_ulong(); + } + + INLINE ap_slong to_int64() const { + ap_private<_AP_W,false> val=get(); + return val.to_int64(); + } + + INLINE ap_ulong to_uint64() const { + ap_private<_AP_W,false> val=get(); + return val.to_uint64(); + } + + INLINE std::string to_string(uint8_t radix) const { + return get().to_string(radix); + } + +}; + +//----------------------------------------------------------------------------- +///ap_fixed_base: AutoPilot fixed point +//----------------------------------------------------------------------------- +template +struct ap_fixed_base { +#ifdef _MSC_VER + #pragma warning(disable: 4521 4522) +#endif /* #ifdef _MSC_VER */ +public: + template friend struct +ap_fixed_base; + template friend struct +af_bit_ref; + + INLINE void overflow_adjust(bool underflow, bool overflow, + bool lD, bool sign) { + if (!overflow && !underflow) return; + switch (_AP_O) { + case AP_WRAP: + if (_AP_N == 0) + return; + if (_AP_S) { + //signed SC_WRAP + //n_bits == 1; + if (_AP_N > 1) { + ap_private<_AP_W, _AP_S> mask(-1); + if (_AP_N >= _AP_W) mask = 0; + else mask.lshr(_AP_N); + if (sign) + V &= mask; + else + V |= ~mask; + } + sign ? V.set(_AP_W - 1) : V.clear(_AP_W - 1); + } else { + //unsigned SC_WRAP + ap_private<_AP_W, _AP_S> mask(-1); + if (_AP_N >= _AP_W) mask = 0; + else mask.lshr(_AP_N); + mask.flip(); + V |= mask; + } + break; + case AP_SAT_ZERO: + V.clear(); + break; + case AP_WRAP_SM: + { + bool Ro = ap_private_ops::get<_AP_W, _AP_S, _AP_W -1>(V); // V[_AP_W -1]; + if (_AP_N == 0) { + if (lD != Ro) { + V.flip(); + lD ? ap_private_ops::set<_AP_W, _AP_S, _AP_W - 1>(V) : + ap_private_ops::clear<_AP_W, _AP_S, _AP_W - 1>(V); + } + } else { + if (_AP_N == 1 && sign != Ro) { + V.flip(); + } else if (_AP_N > 1) { + bool lNo = ap_private_ops::get<_AP_W, _AP_S, _AP_W - _AP_N> (V); // V[_AP_W - _AP_N]; + if (lNo == sign) + V.flip(); + ap_private<_AP_W, false> mask(-1); + if (_AP_N >= _AP_W) mask = 0; + else mask.lshr(_AP_N); + if (sign) + V &= mask; + else + V |= mask.flip(); + sign ? ap_private_ops::set<_AP_W, _AP_S, _AP_W - 1>(V) : ap_private_ops::clear<_AP_W, _AP_S, _AP_W - 1>(V); + } + } + } + break; + default: + if (_AP_S) { + if (overflow) { + V.set(); ap_private_ops::clear<_AP_W, _AP_S, _AP_W-1>(V); + } else if (underflow) { + V.clear(); + ap_private_ops::set<_AP_W, _AP_S, _AP_W-1>(V); + if (_AP_O == AP_SAT_SYM) + ap_private_ops::set<_AP_W, _AP_S, 0>(V); + } + } else { + if (overflow) + V.set(); + else if (underflow) + V.clear(); + } + } + } + + INLINE bool quantization_adjust(bool qb, bool r, bool s) { + bool carry=ap_private_ops::get<_AP_W, _AP_S, _AP_W-1>(V); + switch (_AP_Q) { + case AP_TRN: + return false; + case AP_RND_ZERO: + qb &= s || r; + break; + case AP_RND_MIN_INF: + qb &= r; + break; + case AP_RND_INF: + qb &= !s || r; + break; + case AP_RND_CONV: + qb &= ap_private_ops::get<_AP_W, _AP_S, 0>(V) || r; + break; + case AP_TRN_ZERO: + qb = s && ( qb || r ); + break; + default:; + + } + if (qb) ++V; + //only when old V[_AP_W-1]==1 && new V[_AP_W-1]==0 + return carry && !(ap_private_ops::get<_AP_W, _AP_S, _AP_W-1>(V)); //(!V[_AP_W-1]); + } + + template + struct RType { + enum { + _AP_F=_AP_W-_AP_I, + F2=_AP_W2-_AP_I2, + mult_w = _AP_W+_AP_W2, + mult_i = _AP_I+_AP_I2, + mult_s = _AP_S||_AP_S2, + plus_w = AP_MAX(_AP_I+(_AP_S2&&!_AP_S),_AP_I2+(_AP_S&&!_AP_S2))+1+AP_MAX(_AP_F,F2), + plus_i = AP_MAX(_AP_I+(_AP_S2&&!_AP_S),_AP_I2+(_AP_S&&!_AP_S2))+1, + plus_s = _AP_S||_AP_S2, + minus_w = AP_MAX(_AP_I+(_AP_S2&&!_AP_S),_AP_I2+(_AP_S&&!_AP_S2))+1+AP_MAX(_AP_F,F2), + minus_i = AP_MAX(_AP_I+(_AP_S2&&!_AP_S),_AP_I2+(_AP_S&&!_AP_S2))+1, + minus_s = true, +#ifndef __SC_COMPATIBLE__ + div_w = _AP_W + AP_MAX(_AP_W2 - _AP_I2, 0) + _AP_S2, +#else + div_w = _AP_W + AP_MAX(_AP_W2 - _AP_I2, 0) + _AP_S2 + AP_MAX(_AP_I2, 0), +#endif /* #ifndef __SC_COMPATIBLE__ */ + div_i = _AP_I + (_AP_W2-_AP_I2) + _AP_S2, + div_s = _AP_S||_AP_S2, + logic_w = AP_MAX(_AP_I+(_AP_S2&&!_AP_S),_AP_I2+(_AP_S&&!_AP_S2))+AP_MAX(_AP_F,F2), + logic_i = AP_MAX(_AP_I+(_AP_S2&&!_AP_S),_AP_I2+(_AP_S&&!_AP_S2)), + logic_s = _AP_S||_AP_S2 + }; + + typedef ap_fixed_base mult; + typedef ap_fixed_base plus; + typedef ap_fixed_base minus; + typedef ap_fixed_base logic; + typedef ap_fixed_base div; + typedef ap_fixed_base<_AP_W, _AP_I, _AP_S> arg1; + }; + INLINE void report() { +#if 0 + if (_AP_W > 1024 && _AP_W <= 4096) { + fprintf(stderr, "[W] W=%d is out of bound (1<=W<=1024):" + " for synthesis, please define macro AP_INT_TYPE_EXT(N) to" + " extend the valid range.\n", _AP_W); + } else +#endif /* #if 0 */ + if (_AP_W > MAX_MODE(AP_INT_MAX_W) * 1024) { + fprintf(stderr, "[E] ap_%sfixed<%d, ...>: Bitwidth exceeds the " + "default max value %d. Please use macro " + "AP_INT_MAX_W to set a larger max value.\n", + _AP_S?"":"u", _AP_W, + MAX_MODE(AP_INT_MAX_W) * 1024); + exit(1); + } + } + + /// Constructors. + // ------------------------------------------------------------------------- +#if 0 + #ifdef __SC_COMPATIBLE__ + INLINE ap_fixed_base():V(uint32_t(_AP_W), uint64_t(0)) {} + #else + INLINE ap_fixed_base():V(uint32_t(_AP_W)) {} + #endif /* #ifdef __SC_COMPATIBLE__ */ +#else + INLINE ap_fixed_base():V(0) {} +#endif /* #if 0 */ + // INLINE ap_fixed_base():V() {} + // INLINE explicit ap_fixed_base(const ap_private<_AP_W+_AP_I, _AP_S>& _V):V(_V) {} + INLINE ap_fixed_base(const ap_fixed_base& op):V(op.V) {} + template + INLINE ap_fixed_base(const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op):V(0) { + enum {N2=_AP_W2,_AP_F=_AP_W-_AP_I,F2=_AP_W2-_AP_I2,QUAN_INC=F2>_AP_F && !(_AP_Q==AP_TRN || + (_AP_Q==AP_TRN_ZERO && !_AP_S2))}; + if (!op) return; + bool carry=false; + //handle quantization + enum { sh_amt =(F2>_AP_F)?F2-_AP_F:_AP_F-F2}; + const ap_private<_AP_W2, _AP_S2>& val = op.V; + bool neg_src=val.isNegative(); + if (F2==_AP_F) + V=val; + + else if (F2>_AP_F) { + if (sh_amt >= _AP_W2) + V = neg_src ? -1 : 0; + else + V = _AP_S2?val.ashr(sh_amt):val.lshr(sh_amt); + if (_AP_Q!=AP_TRN && !(_AP_Q==AP_TRN_ZERO && !_AP_S2)) { + bool qb = false; + if (F2-_AP_F>_AP_W2) + qb = neg_src; + else + qb = ap_private_ops::get<_AP_W2, _AP_S2, F2-_AP_F-1>(val); + + bool r=false; + enum { pos3 = F2-_AP_F-2}; + if (pos3>=_AP_W2-1) + r=val!=0; + else if (pos3>=0) + r = (val<<(_AP_W2-1-pos3))!=0; + carry = quantization_adjust(qb,r,neg_src); + } + } else { //no quantization + if (sh_amt < _AP_W) { + V=val; + V <<= sh_amt; + } + } + //hanle overflow/underflow + if ((_AP_O!=AP_WRAP || _AP_N != 0) && + ((!_AP_S && _AP_S2) || _AP_I-_AP_S < + _AP_I2 - _AP_S2 + (QUAN_INC|| (_AP_S2 && + _AP_O==AP_SAT_SYM)))) {//saturation + bool deleted_zeros = _AP_S2?true:!carry, + deleted_ones = true; + bool lD=(_AP_I2>_AP_I && _AP_W2-_AP_I2+_AP_I>=0) && + ap_private_ops::get<_AP_W2, _AP_S2, _AP_W2-_AP_I2+_AP_I>(val); + enum { pos1=F2-_AP_F+_AP_W, pos2=F2-_AP_F+_AP_W+1}; + if (pos1 < _AP_W2) { + bool Range1_all_ones= true; + bool Range1_all_zeros= true; + if (pos1 >= 0) { + enum { __W = (_AP_W2-pos1) > 0 ? (_AP_W2-pos1) : 1 }; + const ap_private<__W, _AP_S2> Range1=ap_private<__W, _AP_S2>(val.lshr(pos1)); + Range1_all_ones=Range1.isAllOnesValue(); + Range1_all_zeros=Range1.isMinValue(); + } else { + Range1_all_ones=false; + Range1_all_zeros=val.isMinValue(); + } + bool Range2_all_ones=true; + if (pos2<_AP_W2 && pos2>=0) { + enum { __W = (_AP_W2-pos2)>0 ? (_AP_W2-pos2) : 1}; + ap_private<__W, true> Range2=ap_private<__W, true>(val.lshr(pos2)); + Range2_all_ones=Range2.isAllOnesValue(); + } else if (pos2<0) + Range2_all_ones=false; + + deleted_zeros=deleted_zeros && (carry?Range1_all_ones:Range1_all_zeros); + deleted_ones=carry?Range2_all_ones&&(F2-_AP_F+_AP_W<0||!lD) + :Range1_all_ones; + neg_src= neg_src&&!(carry && Range1_all_ones); + } else + neg_src = neg_src && V[_AP_W-1]; + + bool neg_trg= V.isNegative(); + bool overflow=(neg_trg||!deleted_zeros) && !val.isNegative(); + bool underflow=(!neg_trg||!deleted_ones)&&neg_src; + //printf("neg_src = %d, neg_trg = %d, deleted_zeros = %d, + // deleted_ones = %d, overflow = %d, underflow = %d\n", + // neg_src, neg_trg, deleted_zeros, deleted_ones, + // overflow, underflow); + if (_AP_O==AP_SAT_SYM && _AP_S2 && _AP_S) + underflow |= neg_src && (_AP_W>1?V.isMinSignedValue():true); + overflow_adjust(underflow, overflow, lD, neg_src); + } + report(); + } + + template + INLINE ap_fixed_base(const volatile ap_fixed_base<_AP_W2,_AP_I2, + _AP_S2,_AP_Q2,_AP_O2, _AP_N2> &op) : V(op.V) { + *this = const_cast&>(op); + } + + template + INLINE ap_fixed_base(const ap_private<_AP_W2,_AP_S2>& op) { + ap_fixed_base<_AP_W2,_AP_W2,_AP_S2> f_op; + f_op.V=op; + *this = f_op; + } + + INLINE ap_fixed_base(bool b) { + *this=(ap_private<1,false>)b; + report(); + } + + INLINE ap_fixed_base(char b) { + *this=(ap_private<8,false>)b; + report(); + } + + INLINE ap_fixed_base(signed char b) { + *this=(ap_private<8,true>)b; + report(); + } + + INLINE ap_fixed_base(unsigned char b) { + *this=(ap_private<8,false>)b; + report(); + } + + INLINE ap_fixed_base(signed short b) { + *this=(ap_private<16,true>)b; + report(); + } + + INLINE ap_fixed_base(unsigned short b) { + *this=(ap_private<16,false>)b; + report(); + } + + INLINE ap_fixed_base(signed int b) { + *this=(ap_private<32,true>)b; + report(); + } + + INLINE ap_fixed_base(unsigned int b) { + *this=(ap_private<32,false>)b; + report(); + } +# if defined __x86_64__ + INLINE ap_fixed_base(signed long b) { + *this=(ap_private<64,true>)b; + report(); + } + + INLINE ap_fixed_base(unsigned long b) { + *this=(ap_private<64,false>)b; + report(); + } +# else + INLINE ap_fixed_base(signed long b) { + *this=(ap_private<32,true>)b; + report(); + } + + INLINE ap_fixed_base(unsigned long b) { + *this=(ap_private<32,false>)b; + report(); + } +# endif + + INLINE ap_fixed_base(ap_slong b) { + *this=(ap_private<64,true>)b; + report(); + } + + INLINE ap_fixed_base(ap_ulong b) { + *this=(ap_private<64,false>)b; + report(); + } + +#if 1 + INLINE ap_fixed_base(const char* val):V(0) { + ap_private<_AP_W, _AP_S> Tmp(val); + V = Tmp; + } + + INLINE ap_fixed_base(const char* val, signed char rd): V(0) { + ap_private<_AP_W, _AP_S> Tmp(val, rd); + V = Tmp; + } + +#endif + + INLINE ap_fixed_base(const std::string& val) { + ap_private<_AP_W, _AP_S> Tmp(val, 2); + V = Tmp; + report(); + } + + template + INLINE ap_fixed_base(const ap_bit_ref<_AP_W2, _AP_S2>& op) { + *this = ((bool)op); + report(); + } + + template + INLINE ap_fixed_base(const ap_range_ref<_AP_W2, _AP_S2>& op) { + *this = ap_private<_AP_W2, _AP_S2>(op); + report(); + } + + template + INLINE ap_fixed_base(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& op) { + *this = ((const ap_private<_AP_W2 + _AP_W3, false>&)(op)); + report(); + } + + template + INLINE ap_fixed_base(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) { + *this = (bool(op)); + report(); + } + + template + INLINE ap_fixed_base(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) { + *this = (ap_private<_AP_W2, false>(op)); + report(); + } + + //helper function + INLINE unsigned long long doubleToRawBits(double pf)const { + union { + unsigned long long __L; + double __D; + }LD; + LD.__D=pf; + return LD.__L; + } + + + INLINE double rawBitsToDouble(unsigned long long pi) const { + union { + unsigned long long __L; + double __D; + }LD; + LD.__L=pi; + return LD.__D; + } + + INLINE float rawBitsToFloat(uint32_t pi) const { + union { + uint32_t __L; + float __D; + }LD; + LD.__L = pi; + return LD.__D; + } + + INLINE ap_fixed_base(double d):V(0) { + if (!d) return; + const bool isneg=d<0; + + const uint64_t ireg=doubleToRawBits(isneg?-d:d); + if ((ireg&0x7fffffffffffffffULL)!=0) { + const int32_t exp=(((ireg)>>DOUBLE_MAN)&0x07ff)-DOUBLE_BIAS; + ap_private man = ireg & DOUBLE_MAN_MASK; + man.clear(DOUBLE_MAN+1); + man.set(DOUBLE_MAN); + if (isneg) { + man.flip(); + man++; + } + + enum {_AP_S2=true, _AP_W2=DOUBLE_MAN+2,_AP_F=_AP_W -_AP_I }; + const int _AP_I2=exp+2; + const int F2=_AP_W2-_AP_I2; + const bool QUAN_INC=F2>_AP_F && !(_AP_Q==AP_TRN || (_AP_Q==AP_TRN_ZERO && + !_AP_S2)); + bool carry=false; + //handle quantization + const unsigned sh_amt=abs(F2-_AP_F); // sh_amt = F2>_AP_F ? F2 -_AP_F : _AP_F-F2; + if (F2==_AP_F ) + V=man; + else if (F2>_AP_F) { + if (sh_amt >= DOUBLE_MAN+2) + V=isneg?-1:0; + else + V=(man>>sh_amt) | ((man & 1ULL<<(DOUBLE_MAN+1)) ? (DOUBLE_MAN_MASK>>(DOUBLE_MAN+2-sh_amt) <<(DOUBLE_MAN+2-sh_amt)):0); + + if (_AP_Q!=AP_TRN && !(_AP_Q==AP_TRN_ZERO && !_AP_S2)) { + const bool qb=((F2-_AP_F > DOUBLE_MAN+2) ? isneg : (man & (1ULL<<(F2-_AP_F-1))) != 0); + const int pos3=F2-_AP_F-2; + const bool r = (pos3>= 0) ? (man << AP_MAX(0, _AP_W2-pos3-1)& DOUBLE_MAN_MASK)!=0 : false; + carry = quantization_adjust(qb,r,isneg); + } + } + else { //no quantization + // V=man; + if (sh_amt < _AP_W) { + V = man; + V <<= sh_amt; + } + } + //handle overflow/underflow + if ((_AP_O != AP_WRAP || _AP_N != 0) && + ((!_AP_S && _AP_S2) || _AP_I-_AP_S < + _AP_I2-_AP_S2+(QUAN_INC|| (_AP_S2 && + _AP_O==AP_SAT_SYM)) )) {// saturation + bool deleted_zeros = _AP_S2?true:!carry, + deleted_ones = true; + bool neg_src; + const bool lD=(_AP_I2>_AP_I) && (_AP_W2-_AP_I2+_AP_I>=0) && (man & (1ULL <<(DOUBLE_MAN+2-_AP_I2+_AP_I))); + int pos1=F2+_AP_W-_AP_F; + if (pos1 < _AP_W2) { + int pos2=pos1+1; + bool Range1_all_ones=true; + bool Range1_all_zeros=true; + if (pos1>=0) { + ap_private<_AP_W,_AP_S> Range1= + ap_private<_AP_W,_AP_S>((man >> pos1) | ((1ULL<<(DOUBLE_MAN+1)&man) ? (DOUBLE_MAN_MASK >> (DOUBLE_MAN+2-pos1) <<(DOUBLE_MAN+2-pos1)):0)); + Range1_all_ones = Range1.isAllOnesValue(); // Range1.isAllOnesValue(); + Range1_all_zeros = Range1.isMinValue(); // Range1.isMinValue(); + } else { + Range1_all_ones=false; + Range1_all_zeros = man==0; // man.isMinValue(); + } + bool Range2_all_ones=true; + if (pos2<_AP_W2 && pos2>=0) { + ap_private<_AP_W, _AP_S> Range2= + ap_private<_AP_W, _AP_S>((man >> pos2) | ((1ULL<<(DOUBLE_MAN+1)&man) ? (DOUBLE_MAN_MASK >> (DOUBLE_MAN+2-pos2) <<(DOUBLE_MAN+2-pos2)):0)); + Range2_all_ones=Range2.isAllOnesValue(); // Range2.isAllOnesValue(); + } else if (pos2<0) + Range2_all_ones=false; + deleted_zeros=deleted_zeros && (carry?Range1_all_ones:Range1_all_zeros); + deleted_ones=carry?Range2_all_ones&&(F2-_AP_F+_AP_W<0||!lD) : Range1_all_ones; + neg_src=isneg&&!(carry&Range1_all_ones); + } else + neg_src = isneg && V[_AP_W -1]; + + const bool neg_trg=V.isNegative(); + const bool overflow=(neg_trg||!deleted_zeros) && !isneg; + bool underflow=(!neg_trg||!deleted_ones)&&neg_src; + //printf("neg_src = %d, neg_trg = %d, deleted_zeros = %d, + // deleted_ones = %d, overflow = %d, underflow = %d\n", + // neg_src, neg_trg, deleted_zeros, deleted_ones, + // overflow, underflow); + if (_AP_O==AP_SAT_SYM && _AP_S2 && _AP_S) + underflow |= neg_src && (_AP_W>1?V.isMinSignedValue():true); + overflow_adjust(underflow,overflow,lD, neg_src); + } + } + report(); + } + + + ///assign operators + //------------------------------------------------------------------------- + + INLINE volatile ap_fixed_base& operator=(const ap_fixed_base<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& op) volatile { + V = op.V; + return *this; + } + + INLINE ap_fixed_base& operator=(const ap_fixed_base<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& op) { + V = op.V; + return *this; + } + + INLINE volatile ap_fixed_base& operator=(const volatile ap_fixed_base<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& op) volatile { + V = op.V; + return *this; + } + + INLINE ap_fixed_base& operator=(const volatile ap_fixed_base<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& op) { + V = op.V; + return *this; + } + + // Set this ap_fixed_base with a bits string. That means the ssdm_int::V + // inside this ap_fixed_base is assigned by bv. + // Note the input parameter should be a fixed-point formatted bit string. + INLINE ap_fixed_base& setBits(unsigned long long bv) { + V=bv; + return *this; + } + + // Return a ap_fixed_base object whose ssdm_int::V is assigned by bv. + // Note the input parameter should be a fixed-point formatted bit string. + static INLINE ap_fixed_base bitsToFixed(unsigned long long bv) { + ap_fixed_base Tmp=bv; + return Tmp; + } + + // Explicit conversion functions to ap_private that captures + // all integer bits (bits are truncated) + INLINE ap_private + to_ap_private(bool Cnative = true) const { + ap_private ret = ap_private ((_AP_I >= 1) ? (_AP_S==true ? V.ashr(AP_MAX(0,_AP_W - _AP_I)) : V.lshr(AP_MAX(0,_AP_W - _AP_I))) : ap_private<_AP_W, _AP_S>(0)); + + if (Cnative) { + bool r = false; + if (_AP_I < _AP_W) { + if (_AP_I > 0) r = !(V.getLoBits(_AP_W - _AP_I).isMinValue()); + else r = !(V.isMinValue()); + } + if (r && V.isNegative()) { // if this is negative integer + ++ret;//ap_private(1,_AP_S); + } + } else { + //Follow OSCI library, conversion from sc_fixed to sc_int + } + return ret; + } + + template + INLINE operator ap_private<_AP_W2,_AP_S2> () const { + return (ap_private<_AP_W2,_AP_S2>)to_ap_private(); + } + + template + INLINE operator ap_private<_AP_W2,_AP_S2,_AP_N2> () const { + return (ap_private<_AP_W2,_AP_S2,_AP_N2>)to_ap_private(); + } + + //Explict conversion function to C built-in integral type + INLINE int to_int() const { + return to_ap_private().to_int(); + } + + INLINE int to_uint() const { + return to_ap_private().to_uint(); + } + + INLINE ap_slong to_int64() const { + return to_ap_private().to_int64(); + } + + INLINE ap_ulong to_uint64() const { + return to_ap_private().to_uint64(); + } + + INLINE double to_double() const { + if (!V) + return 0; + if (_AP_W>64 || (_AP_W - _AP_I) > 0) { + bool isneg = _AP_S && V[_AP_W-1]; + uint64_t res = isneg ? 0x8000000000000000ULL : 0; + ap_private<_AP_W, false> tmp = V; + if (isneg) tmp = -tmp; + int i = _AP_W -1 - tmp.countLeadingZeros(); + int exp = _AP_I-(_AP_W-i); + res|=((uint64_t)(exp+DOUBLE_BIAS))<DOUBLE_MAN)?tmp.lshr(i-DOUBLE_MAN):tmp).to_uint64() & DOUBLE_MAN_MASK; + res |= i 0) { + /* This specialization is disabled. It is giving wrong results in some cases. + bool isneg=V.isNegative(); + double dp = V.get(); + dp /= (1<< (_AP_W - _AP_I)); + return dp;*/ + } else + return double(to_int64()); + } + + INLINE float to_float() const { + uint32_t res=0; + if (V==0) + return 0; + bool isneg=V.isNegative(); + ap_private<_AP_W, _AP_S> tmp=V; + if (isneg) tmp = -tmp; + if (_AP_W-_AP_I>0||_AP_W>64) { + if (isneg) + res=0x80000000; + int i=_AP_W-1; + i-=tmp.countLeadingZeros(); + int exp=_AP_I-(_AP_W-i); + res|=(exp+FLOAT_BIAS)< man = 0; + if (i!=0) { + tmp.clear(i); + if (i>FLOAT_MAN) + man=tmp.lshr(i-FLOAT_MAN); + else + man=tmp; + res |= i < FLOAT_MAN?man.getZExtValue()<<(FLOAT_MAN-i):man.getZExtValue(); + } + } else { + return float(to_int64()); + } + float dp=rawBitsToFloat(res); + return dp; + } + + INLINE operator double () const { + return to_double(); + } +#ifndef __SC_COMPATIBLE__ + INLINE operator float () const { + return to_float(); + } + + INLINE operator char () const { + return (char) to_int(); + } + + INLINE operator unsigned char () const { + return (unsigned char) to_uint(); + } + + INLINE operator short () const { + return (short) to_int(); + } + + INLINE operator unsigned short () const { + return (unsigned short) to_uint(); + } + + INLINE operator int () const { + return to_int(); + } + + INLINE operator unsigned int () const { + return to_uint(); + } +#if 1 +#ifdef __x86_64__ + INLINE operator long () const { + return (long)to_int64(); + } + + INLINE operator unsigned long () const { + return (unsigned long) to_uint64(); + } +#else + INLINE operator long () const { + return to_int64(); + } + + INLINE operator unsigned long () const { + return to_uint64(); + } + +#endif +#endif + INLINE operator unsigned long long () const { + return to_uint64(); + } + + INLINE operator long long () const { + return to_int64(); + } +#endif + + INLINE std::string to_string(uint8_t radix=2, bool sign=false) const; + + INLINE ap_slong bits_to_int64() const { + ap_private res(V); + return (ap_slong) res; + } + + INLINE ap_ulong bits_to_uint64() const { + ap_private res(V); + return (ap_ulong) res; + } + + INLINE int length() const {return _AP_W;} + + // Count the number of zeros from the most significant bit + // to the first one bit. Note this is only for ap_fixed_base whose + // _AP_W <= 64, otherwise will incur assertion. + INLINE int countLeadingZeros() { + return V.countLeadingZeros(); + } + + ///Arithmetic:Binary + //------------------------------------------------------------------------- + template + INLINE typename RType<_AP_W2,_AP_I2,_AP_S2>::mult + operator * (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + typename RType<_AP_W2,_AP_I2,_AP_S2>::mult r; + r.V = V * op2.V; + return r; + } + + template + static INLINE ap_fixed_base multiply(const ap_fixed_base<_AP_W1,_AP_I1,_AP_S1>& op1, const + ap_fixed_base<_AP_W2,_AP_I2,_AP_S2>& op2) { + ap_private<_AP_W+_AP_W2, _AP_S> OP1=op1.V; + ap_private<_AP_W2,_AP_S2> OP2=op2.V; + return OP1*OP2; + } + + template + INLINE typename RType<_AP_W2,_AP_I2,_AP_S2>::div + operator / (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + enum {F2 = _AP_W2-_AP_I2, _W1=AP_MAX(_AP_W + AP_MAX(F2, 0), _AP_W2), + _W2=AP_MAX(_AP_W2,AP_MAX(_AP_W + AP_MAX(F2, 0), _AP_W2))}; + ap_private<_W1, _AP_S> dividend = (ap_private<_W1, _AP_S>(V)) << ((_W1>_AP_W)?F2:0); + ap_private<_W1, _AP_S2> divisior = ap_private<_W2, _AP_S2>(op2.V); + ap_private<_W1, _AP_S> ret = ap_private<_W1,_AP_S> ((_AP_S||_AP_S2) ? dividend.sdiv(divisior): dividend.udiv(divisior)); + typename RType<_AP_W2, _AP_I2, _AP_S2>::div r; + r.V = ret; + return r; + } +#define OP_BIN_AF(Sym, Rty, Width, Sign, Fun) \ + template \ + INLINE typename RType<_AP_W2,_AP_I2,_AP_S2>::Rty \ + operator Sym (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const \ + { \ + enum {_AP_F=_AP_W-_AP_I, F2=_AP_W2-_AP_I2}; \ + typename RType<_AP_W2,_AP_I2,_AP_S2>::Rty r, lhs(*this), rhs(op2); \ + r.V = lhs.V.Fun(rhs.V); \ + return r; \ + } \ + INLINE typename RType<_AP_W,_AP_I,_AP_S>::Rty \ + operator Sym (const ap_fixed_base& op2) const \ + { \ + typename RType<_AP_W,_AP_I,_AP_S>::Rty r; \ + r.V = V Sym op2.V; \ + return r; \ + } \ + + OP_BIN_AF(+, plus, plus_w, plus_s, Add) + OP_BIN_AF(-, minus, minus_w, minus_s, Sub) + +#define OP_LOGIC_BIN_AF(Sym, Rty, Width, Sign) \ + template \ + INLINE typename RType<_AP_W2,_AP_I2,_AP_S2>::Rty \ + operator Sym (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const \ + { \ + typename RType<_AP_W2,_AP_I2,_AP_S2>::Rty r, lhs(*this), rhs(op2); \ + r.V=lhs.V Sym rhs.V; \ + return r; \ + } \ + INLINE typename RType<_AP_W,_AP_I,_AP_S>::Rty \ + operator Sym (const ap_fixed_base& op2) const \ + { \ + typename RType<_AP_W,_AP_I,_AP_S>::Rty r; \ + r.V = V Sym op2.V; \ + return r; \ + } \ + INLINE typename RType<_AP_W,_AP_I,_AP_S>::Rty operator Sym(int op2) const \ + { \ + return V Sym (op2<<(_AP_W - _AP_I)); \ + } + OP_LOGIC_BIN_AF(&, logic, logic_w, logic_s) + OP_LOGIC_BIN_AF(|, logic, logic_w, logic_s) + OP_LOGIC_BIN_AF(^, logic, logic_w, logic_s) + + ///Arithmic : assign + //------------------------------------------------------------------------- +#define OP_ASSIGN_AF(Sym) \ + template \ + INLINE ap_fixed_base& operator Sym##= (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) \ + { \ + *this=operator Sym (op2) ; \ + return *this; \ + } + + OP_ASSIGN_AF(+) + OP_ASSIGN_AF(-) + OP_ASSIGN_AF(&) + OP_ASSIGN_AF(|) + OP_ASSIGN_AF(^) + OP_ASSIGN_AF(*) + OP_ASSIGN_AF(/) + + ///Prefix increment, decrement + //------------------------------------------------------------------------- + INLINE ap_fixed_base& operator ++() { + operator+=(ap_fixed_base<1,1,false>(1)); //SystemC's semantics + return *this; + } + + INLINE ap_fixed_base& operator --() { + operator-=(ap_fixed_base<1,1,false>(1)); //SystemC's semantics + return *this; + } + + //Postfix increment, decrement + //------------------------------------------------------------------------- + INLINE const ap_fixed_base operator ++(int) { + ap_fixed_base t(*this); + operator++(); + return t; + } + + INLINE const ap_fixed_base operator --(int) { + ap_fixed_base t = *this; + operator--(); + return t; + } + + ///Unary arithmetic + //------------------------------------------------------------------------- + INLINE ap_fixed_base operator +() {return *this;} + + INLINE ap_fixed_base<_AP_W + 1, _AP_I + 1, true> operator -() const { + ap_fixed_base<_AP_W + 1, _AP_I + 1, true> Tmp(*this); + Tmp.V = - Tmp.V; + return Tmp; + } + + INLINE ap_fixed_base<_AP_W,_AP_I,true,_AP_Q,_AP_O, _AP_N> getNeg() { + ap_fixed_base<_AP_W,_AP_I,true,_AP_Q,_AP_O, _AP_N> Tmp(*this); + Tmp.V=-Tmp.V; + return Tmp; + } + + ///Not (!) + //------------------------------------------------------------------------- + INLINE bool operator !() const { + return !V; + } + + ///Bitwise complement + //------------------------------------------------------------------------- + INLINE ap_fixed_base<_AP_W, _AP_I, _AP_S> + operator ~() const { + ap_fixed_base<_AP_W, _AP_I, _AP_S> res(*this); + res.V.flip(); + return res; + } + + ///Shift + ///template argument as shift value + template + INLINE ap_fixed_base<_AP_W, _AP_I + _AP_SHIFT, _AP_S> lshift () const { + ap_fixed_base<_AP_W, _AP_I + _AP_SHIFT, _AP_S> r; + r.V = V; + return r; + } + + template + INLINE ap_fixed_base<_AP_W, _AP_I - _AP_SHIFT, _AP_S> rshift () const { + ap_fixed_base<_AP_W, _AP_I - _AP_SHIFT, _AP_S> r; + r.V = V; + return r; + } + + //Because the return type is the type of the the first operand, shift assign + //operators do not carry out any quantization or overflow + //While systemc, shift assigns for sc_fixed/sc_ufixed will result in + //quantization or overflow (depending on the mode of the first operand) + //------------------------------------------------------------------------- + INLINE ap_fixed_base operator << (int sh) const { + ap_fixed_base r; + bool isNeg=(sh&0x80000000) != 0; + sh=isNeg?-sh:sh; + bool shiftoverflow = sh >= _AP_W; + bool NegSrc = V.isNegative(); + if (isNeg) { + if (shiftoverflow) + NegSrc?r.V.set():r.V.clear(); + else + r.V=_AP_S?V.ashr(sh):V.lshr(sh); + } else { + if (shiftoverflow) + r.V.clear(); + else + r.V=V< 1 && sh <= _AP_W) + rb = (V << (_AP_W - sh + 1 )) != 0; + else if (sh > _AP_W) + rb = V != 0; + r.quantization_adjust(qb, rb, NegSrc); + } else if (isNeg == false && _AP_O != AP_WRAP) { + bool allones, allzeros; + if (sh < _AP_W ) { + ap_private<_AP_W, _AP_S > range1 = V.lshr(_AP_W - sh - 1); + allones = range1.isAllOnesValue(); + allzeros = range1.isMinValue(); + } else { + allones = false; + allzeros = V.isMinValue(); + } + bool overflow = !allzeros && !NegSrc; + bool underflow = !allones && NegSrc; + if (_AP_O == AP_SAT_SYM && _AP_S) + underflow |= NegSrc && (_AP_W > 1 ? r.V.isMinSignedValue():true); + bool lD = false; + if ( sh < _AP_W ) lD = V[_AP_W - sh - 1]; + r.overflow_adjust(underflow, overflow, lD, NegSrc); + } +#endif + return r; + } + + template + INLINE ap_fixed_base operator<<(const ap_private<_AP_W2,true>& op2) const { + int sh = op2.to_int(); + return operator << (sh); + } + + INLINE ap_fixed_base operator << (unsigned int sh ) const { + ap_fixed_base r; + bool shiftoverflow = sh >= _AP_W; + r.V = shiftoverflow ? ap_private<_AP_W, _AP_S >(0) : V << sh; + if (sh == 0) return r; +#ifdef __SC_COMPATIBLE__ + bool NegSrc = V.isNegative(); + if (_AP_O != AP_WRAP) { + bool allones, allzeros; + if (sh < _AP_W ) { + ap_private<_AP_W, _AP_S > range1 = V.lshr(_AP_W - sh -1); + allones = range1.isAllOnesValue(); + allzeros = range1.isMinValue(); + } else { + allones = false; + allzeros = V.isMinValue(); + } + bool overflow = !allzeros && !NegSrc; + bool underflow = !allones && NegSrc; + if (_AP_O == AP_SAT_SYM && _AP_S) + underflow |= NegSrc && (_AP_W > 1 ? r.V.isMinSignedValue():true); + bool lD = false; + if ( sh < _AP_W ) lD = V[_AP_W - sh - 1]; + r.overflow_adjust(underflow, overflow, lD, NegSrc); + } +#endif + return r; + } + + template + INLINE ap_fixed_base operator << (const ap_private<_AP_W2,false>& op2) const { + unsigned int sh = op2.to_uint(); + return operator << (sh); + } + + INLINE ap_fixed_base operator >> (int sh) const { + ap_fixed_base r; + bool isNeg=(sh&0x80000000) != 0; + bool NegSrc = V.isNegative(); + sh=isNeg?-sh:sh; + bool shiftoverflow = sh >= _AP_W; + if (isNeg && !shiftoverflow) r.V=V< 1 && sh <= _AP_W) + rb = (V << (_AP_W - sh + 1 )) != 0; + else if (sh > _AP_W) + rb = V != 0; + r.quantization_adjust(qb, rb, NegSrc); + } else if (isNeg == true && _AP_O != AP_WRAP) { + bool allones, allzeros; + if (sh < _AP_W ) { + ap_private<_AP_W, _AP_S > range1 = V.lshr(_AP_W - sh - 1); + allones = range1.isAllOnesValue(); + allzeros = range1.isMinValue(); + } else { + allones = false; + allzeros = V.isMinValue(); + } + bool overflow = !allzeros && !NegSrc; + bool underflow = !allones && NegSrc; + if (_AP_O == AP_SAT_SYM && _AP_S) + underflow |= NegSrc && (_AP_W > 1 ? r.V.isMinSignedValue():true); + bool lD = false; + if ( sh < _AP_W ) lD = V[_AP_W - sh - 1]; + r.overflow_adjust(underflow, overflow, lD, NegSrc); + } +#endif + return r; + } + + template + INLINE ap_fixed_base operator >> (const ap_private<_AP_W2,true>& op2) const { + int sh = op2.to_int(); + return operator >> (sh); + } + + INLINE ap_fixed_base operator >> (unsigned int sh) const { + ap_fixed_base r; + bool NegSrc = V.isNegative(); + bool shiftoverflow = sh >= _AP_W; + if (shiftoverflow) + NegSrc?r.V.set():r.V.clear(); + else + r.V=_AP_S?V.ashr(sh):V.lshr(sh); +#ifdef __SC_COMPATIBLE__ + if (sh == 0) return r; + if (_AP_Q != AP_TRN) { + bool qb = false; + if (sh <= _AP_W) qb = V[sh - 1]; + bool rb = false; + if (sh > 1 && sh <= _AP_W) + rb = (V << (_AP_W - sh + 1 )) != 0; + else if (sh > _AP_W) + rb = V != 0; + r.quantization_adjust(qb, rb, NegSrc); + } +#endif + return r; + } + + template + INLINE ap_fixed_base operator >> (const ap_private<_AP_W2,false>& op2) const { + unsigned int sh = op2.to_uint(); + return operator >> (sh); + } + + ///shift assign + //------------------------------------------------------------------------- +#define OP_AP_SHIFT_AP_ASSIGN_AF(Sym) \ + template \ + INLINE ap_fixed_base& operator Sym##=(const ap_private<_AP_W2,_AP_S2>& op2) \ + { \ + *this=operator Sym (op2); \ + return *this; \ + } + + OP_AP_SHIFT_AP_ASSIGN_AF(<<) + OP_AP_SHIFT_AP_ASSIGN_AF(>>) + + ///Support shift(ap_fixed_base) +#define OP_AP_SHIFT_AF(Sym) \ + template \ + INLINE ap_fixed_base operator Sym (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const \ + { \ + return operator Sym (op2.to_ap_private()); \ + } \ + template \ + INLINE ap_fixed_base& operator Sym##= (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) \ + { \ + *this=operator Sym (op2); \ + return *this; \ + } + + OP_AP_SHIFT_AF(<<) + OP_AP_SHIFT_AF(>>) + + INLINE ap_fixed_base& operator >>= (unsigned int sh) { + *this = operator >> (sh); + return *this; + } + + INLINE ap_fixed_base& operator <<= (unsigned int sh) { + *this = operator << (sh); + return *this; + } + + INLINE ap_fixed_base& operator >>= (int sh) { + *this = operator >> (sh); + return *this; + } + + INLINE ap_fixed_base& operator <<= (int sh) { + *this = operator << (sh); + return *this; + } + + ///Comparisons + //------------------------------------------------------------------------- + template + INLINE bool operator == (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + enum {_AP_F=_AP_W-_AP_I,F2=_AP_W2-_AP_I2, shAmt1 = AP_MAX(F2-_AP_F, 0), shAmt2 = AP_MAX(_AP_F-F2,0), _AP_W3 = (_AP_F==F2) ? AP_MAX(_AP_W,_AP_W2) : AP_MAX(_AP_W+shAmt1, _AP_W2+shAmt2)}; + ap_private<_AP_W3, _AP_S > OP1= ap_private<_AP_W3, _AP_S >(V)< OP2=ap_private<_AP_W3,_AP_S2 >(op2.V)< + INLINE bool operator != (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + return !(*this==op2); + } + + template + INLINE bool operator > (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + enum {_AP_F=_AP_W-_AP_I,F2=_AP_W2-_AP_I2, shAmt1 = AP_MAX(F2-_AP_F, 0), shAmt2 = AP_MAX(_AP_F-F2,0), _AP_W3 = (_AP_F==F2) ? AP_MAX(_AP_W,_AP_W2) : AP_MAX(_AP_W+shAmt1, _AP_W2+shAmt2)}; + ap_private<_AP_W3, _AP_S > OP1= ap_private<_AP_W3, _AP_S >(V)< OP2=ap_private<_AP_W3,_AP_S2 >(op2.V)< + INLINE bool operator <= (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + return !(*this>op2); + } + + template + INLINE bool operator < (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + enum {_AP_F=_AP_W-_AP_I,F2=_AP_W2-_AP_I2, shAmt1 = AP_MAX(F2-_AP_F, 0), shAmt2 = AP_MAX(_AP_F-F2,0), _AP_W3 = (_AP_F==F2) ? AP_MAX(_AP_W,_AP_W2) : AP_MAX(_AP_W+shAmt1, _AP_W2+shAmt2)}; + ap_private<_AP_W3, _AP_S > OP1= ap_private<_AP_W3, _AP_S >(V)< OP2=ap_private<_AP_W3,_AP_S2 >(op2.V)< + INLINE bool operator >= (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + return !(*this) + DOUBLE_CMP_AF(>=) + DOUBLE_CMP_AF(<) + DOUBLE_CMP_AF(<=) + + // Bit and Slice Select + INLINE af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N> operator [] (unsigned int index) { + assert(index<_AP_W&&"Attemping to read bit beyond MSB"); + return af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>(this, index); + } + + INLINE af_bit_ref<_AP_W, _AP_I,_AP_S,_AP_Q,_AP_O, _AP_N> bit(unsigned int index) { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>(this, index); + } + + template + INLINE af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N> bit (const ap_private<_AP_W2,_AP_S2>& index) { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>(this, index.to_int()); + } + + INLINE bool bit (unsigned int index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return V[index]; + } + + INLINE bool operator [] (unsigned int index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return V[index]; + } + + template + INLINE bool bit (const ap_private<_AP_W2, _AP_S2>& index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return V[index.to_uint()]; + } + + template + INLINE bool operator [] (const ap_private<_AP_W2, _AP_S2>& index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return V[index.to_uint()]; + } + + INLINE af_bit_ref<_AP_W, _AP_I,_AP_S,_AP_Q,_AP_O, _AP_N> get_bit(int index) { + assert(index < _AP_I && "Attempting to read bit beyond MSB"); + assert(index >= _AP_I - _AP_W&& "Attempting to read bit beyond MSB"); + return af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>(this, index + _AP_W - _AP_I); + } + + template + INLINE af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N> get_bit (const ap_private<_AP_W2, true>& index) { + assert(index >= _AP_I - _AP_W && "Attempting to read bit with negative index"); + assert(index < _AP_I && "Attempting to read bit beyond MSB"); + return af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>(this, index.to_int() + _AP_W - _AP_I); + } + + INLINE bool get_bit (int index) const { + assert(index >= _AP_I - _AP_W && "Attempting to read bit with negative index"); + assert(index < _AP_I && "Attempting to read bit beyond MSB"); + return V[index + _AP_W - _AP_I]; + } + + template + INLINE bool get_bit (const ap_private<_AP_W2, true>& index) const { + assert(index >= _AP_I - _AP_W && "Attempting to read bit with negative index"); + assert(index < _AP_I && "Attempting to read bit beyond MSB"); + return V[index.to_int() + _AP_W - _AP_I]; + } + + INLINE af_range_ref<_AP_W,_AP_I,_AP_S, _AP_Q, _AP_O, _AP_N> + range(int Hi, int Lo) { + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>(this, Hi, Lo); + } + + INLINE af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> + operator () (int Hi, int Lo) { + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>(this, Hi, Lo); + } + + INLINE af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> + range(int Hi, int Lo) const { + assert((Hi < _AP_W) && (Lo < _AP_W) &&"Out of bounds in range()"); + return af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>(const_cast(this), Hi, Lo); + } + + INLINE af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> + operator () (int Hi, int Lo) const { + return this->range(Hi, Lo); + } + + template + INLINE af_range_ref<_AP_W,_AP_I,_AP_S, _AP_Q, _AP_O, _AP_N> + range(const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>(this, Hi, Lo); + } + + template + INLINE af_range_ref<_AP_W,_AP_I,_AP_S, _AP_Q, _AP_O, _AP_N> + operator () (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>(this, Hi, Lo); + } + + template + INLINE af_range_ref<_AP_W,_AP_I,_AP_S, _AP_Q, _AP_O, _AP_N> + range(const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) const { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>(const_cast< + ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>*>(this), + Hi, Lo); + } + + template + INLINE af_range_ref<_AP_W,_AP_I,_AP_S, _AP_Q, _AP_O, _AP_N> + operator () (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) const { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + return this->range(Hi, Lo); + } + + INLINE af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> + range() { + return this->range(_AP_W - 1, 0); + } + + INLINE af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> + range() const { + return this->range(_AP_W - 1, 0); + } + + INLINE bool is_zero () const { + return V.isMinValue(); + } + + INLINE bool is_neg () const { + if (V.isNegative()) + return true; + return false; + } + + INLINE int wl () const { + return _AP_W; + } + + INLINE int iwl () const { + return _AP_I; + } + + INLINE ap_q_mode q_mode () const { + return _AP_Q; + } + + INLINE ap_o_mode o_mode () const { + return _AP_O; + } + + INLINE int n_bits () const { + return 0; + } + + //private: +public: + ap_private<_AP_W, _AP_S> V; +}; + +template +std::string ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>::to_string( + uint8_t radix, bool sign) const { + std::string str; + str.clear(); + char step; + std::string prefix; + switch (radix) { + case 2 : prefix = "0b"; step = 1; break; + case 8 : prefix = "0o"; step = 3; break; + case 16 : prefix = "0x"; step = 4; break; + default : break; + } + if (_AP_W <= _AP_I) + str = this->to_ap_private().to_string(radix, + radix == 10 ? _AP_S : sign); + else { + if (radix == 10) { + bool isNeg = _AP_S && V.isNegative(); + if (_AP_I > 0) { + ap_private int_part(0); + int_part = this->to_ap_private(); + str += int_part.to_string(radix, false); + } else { + if (isNeg) str += '-'; + } + ap_fixed_base<_AP_W, _AP_I, _AP_S> tmp(*this); + if (isNeg && _AP_I <= 0) tmp = -tmp; + ap_fixed_base<_AP_W - AP_MIN(_AP_I, 0), 0, false> frac_part = tmp; + if (frac_part == 0) return str; + str += "."; + while (frac_part != 0) { + char digit = (frac_part * radix).to_ap_private(); + str += static_cast(digit + '0'); + frac_part *= radix; + } + } else { + if (_AP_I > 0) { + for (signed i = _AP_W - _AP_I; i < _AP_W; i += step) { + + char digit = (char)(this->range(AP_MIN(i + step - 1, _AP_W - 1), i)); + str = (digit < 10 ? static_cast(digit + '0') : + static_cast(digit - 10 + 'a')) + str; + } + } + str += '.'; + ap_fixed_base tmp(*this); + for (signed i = _AP_W - _AP_I - 1; i >= 0; i -= step) { + char digit = (char)(tmp.range(i, AP_MAX(0, i - step + 1))); + str += digit < 10 ? static_cast(digit + '0') : + static_cast(digit - 10 + 'a'); + } + } + } + str = prefix + str; + return str; +} + +template +INLINE void b_not(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op) { + ret.V = op.V; + ret.V.flip(); +} + +template +INLINE void b_and(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op1, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op2) { + ret.V = op1.V & op2.V; +} + +template +INLINE void b_or(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op1, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op2) { + ret.V = op1.V | op2.V; +} + +template +INLINE void b_xor(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op1, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op2) { + ret.V = op1.V ^ op2.V; +} + +template +INLINE void neg(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) { + ap_fixed_base<_AP_W2+!_AP_S2, _AP_I2+!_AP_S2, true, _AP_Q2, _AP_O2, _AP_N2> Tmp; + Tmp.V = - op.V; + ret = Tmp; +} + +template +INLINE void neg(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op) { + ret.V = -op.V; +} + +template +INLINE void lshift(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op, + int i) { + ap_fixed_base<_AP_W2 - _AP_I2 + AP_MAX(_AP_I, _AP_I2), AP_MAX(_AP_I, _AP_I2), _AP_S2, _AP_Q2, _AP_O2, _AP_N2> Tmp; + Tmp = op; + Tmp.V <<= i; + ret = Tmp; +} + +template +INLINE void lshift(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op, + int i) { + ret.V = op.V << i; +} + +template +INLINE void rshift(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op, + int i) { + ap_fixed_base<_AP_I2 + AP_MAX(_AP_W - _AP_I, _AP_W2 - _AP_I2), _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> Tmp; + Tmp = op; + Tmp.V = _AP_S2 ? Tmp.V.ashr(i): Tmp.V.lshr(i); + ret = Tmp; +} + +template +INLINE void rshift(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op, + int i) { + ret.V = _AP_S ? op.V.ashr(i): op.V.lshr(i); +} + +#define AF_CTOR_SPEC_BASE(_AP_W,_AP_S,C_TYPE) \ + template<> INLINE ap_fixed_base<_AP_W,_AP_W,_AP_S,AP_TRN,AP_WRAP>::ap_fixed_base(C_TYPE i_op):V(i_op) \ + { \ + } + +#define AF_CTOR_SPEC(__W,C_TYPE) \ + AF_CTOR_SPEC_BASE(__W,true,C_TYPE) \ + AF_CTOR_SPEC_BASE(__W,false,C_TYPE) + +AF_CTOR_SPEC(1,bool) +AF_CTOR_SPEC(8, signed char) +AF_CTOR_SPEC(8, unsigned char) +AF_CTOR_SPEC(16, signed short) +AF_CTOR_SPEC(16, unsigned short) +AF_CTOR_SPEC(32, signed int) +AF_CTOR_SPEC(32, unsigned int) +AF_CTOR_SPEC(64, ap_slong) +AF_CTOR_SPEC(64, ap_ulong) + +///Output streaming +//----------------------------------------------------------------------------- +template +INLINE std::ostream& +operator <<(std::ostream& os, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& x) { + os << x.to_double(); + return os; +} + +///Input streaming +//----------------------------------------------------------------------------- +template +INLINE std::istream& +operator >> (std::istream& os, ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& x) { + double d; + os >> d; + x = ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>(x); + return os; +} + +template +INLINE void print(const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& x) { + ap_private<_AP_W,_AP_S> data=x.V; + if (_AP_I>0) { + const ap_private<_AP_I,_AP_S> p1=data>>(_AP_W-_AP_I); + print(p1); + + } else + printf("0"); + printf("."); + if (_AP_I<_AP_W) { + const ap_private<_AP_W-_AP_I,false> p2=data; + print(p2,false); + } +} + +///Operators mixing Integers with ap_fixed_base +//----------------------------------------------------------------------------- +#if 1 +#define AF_BIN_OP_WITH_INT_SF(BIN_OP,C_TYPE,_AP_W2,_AP_S2,RTYPE) \ + template \ + INLINE typename ap_fixed_base<_AP_W,_AP_I,_AP_S>::template RType<_AP_W2,_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP (const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) \ + { \ + return op.operator BIN_OP(ap_private<_AP_W2,_AP_S2>(i_op)); \ + } +#define AF_BIN_OP_WITH_INT(BIN_OP, C_TYPE, _AP_W2,_AP_S2,RTYPE) \ + template \ + INLINE typename ap_fixed_base<_AP_W,_AP_I,_AP_S>::template RType<_AP_W2,_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP (const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) \ + { \ + return op.operator BIN_OP (ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op)); \ + } \ + \ + template \ + INLINE typename ap_fixed_base<_AP_W,_AP_I,_AP_S>::template RType<_AP_W2,_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP (C_TYPE i_op, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op) \ + { \ + return ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op).operator BIN_OP (op); \ + } + +#else +#define AF_BIN_OP_WITH_INT_SF(BIN_OP,C_TYPE,_AP_W2,_AP_S2,RTYPE) \ + template \ + INLINE typename ap_fixed_base<_AP_W,_AP_I,_AP_S>::template RType<_AP_W2,_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP (const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) \ + { \ + return op BIN_OP (i_op); \ + } +#define AF_BIN_OP_WITH_INT(BIN_OP, C_TYPE, _AP_W2,_AP_S2,RTYPE) \ + template \ + INLINE typename ap_fixed_base<_AP_W,_AP_I,_AP_S>::template RType<_AP_W2,_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP (const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) \ + { \ + return op.V BIN_OP (i_op<<(_AP_W-_AP_I)); \ + } \ + \ + \ + template \ + INLINE typename ap_fixed_base<_AP_W,_AP_I,_AP_S>::template RType<_AP_W2,_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP (C_TYPE i_op, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op) \ + { \ + return ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op).operator BIN_OP (op); \ + } + +#endif +#if 1 +#define AF_REL_OP_WITH_INT(REL_OP, C_TYPE, _AP_W2,_AP_S2) \ + template \ + INLINE bool operator REL_OP (const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) \ + { \ + return op.operator REL_OP (ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op)); \ + } \ + \ + \ + template \ + INLINE bool operator REL_OP (C_TYPE i_op, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op) \ + { \ + return ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op).operator REL_OP (op); \ + } +#else +#define AF_REL_OP_WITH_INT(REL_OP, C_TYPE, _AP_W2,_AP_S2) \ + template \ + INLINE bool operator REL_OP (const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) \ + { \ + return op.V.operator REL_OP (i_op<<(_AP_W-_AP_I)); \ + } \ + \ + \ + template \ + INLINE bool operator REL_OP (C_TYPE i_op, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op) \ + { \ + return (i_op<<(_AP_W-_AP_I)) REL_OP (op.V.VAL); \ + } +#endif +#if 1 +#define AF_ASSIGN_OP_WITH_INT(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& operator ASSIGN_OP ( ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) { \ + return op.operator ASSIGN_OP (ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op)); \ + } +#define AF_ASSIGN_OP_WITH_INT_SF(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& operator ASSIGN_OP ( ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) { \ + return op.operator ASSIGN_OP (ap_private<_AP_W2,_AP_S2>(i_op)); \ + } +#else +#define AF_ASSIGN_OP_WITH_INT(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& operator ASSIGN_OP ( ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) { \ + return op.V.operator ASSIGN_OP (i_op); \ + } +#define AF_ASSIGN_OP_WITH_INT_SF(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& operator ASSIGN_OP ( ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) { \ + return op.V.operator ASSIGN_OP (i_op); \ + } +#endif + +#define AF_OPS_WITH_INT(C_TYPE, WI, SI) \ + AF_BIN_OP_WITH_INT(+, C_TYPE, WI, SI, plus) \ + AF_BIN_OP_WITH_INT(-, C_TYPE, WI, SI, minus) \ + AF_BIN_OP_WITH_INT(*, C_TYPE, WI, SI, mult) \ + AF_BIN_OP_WITH_INT(/, C_TYPE, WI, SI, div) \ + AF_BIN_OP_WITH_INT_SF(>>, C_TYPE, WI, SI, arg1) \ + AF_BIN_OP_WITH_INT_SF(<<, C_TYPE, WI, SI, arg1) \ + AF_BIN_OP_WITH_INT(&, C_TYPE, WI, SI, logic) \ + AF_BIN_OP_WITH_INT(|, C_TYPE, WI, SI, logic) \ + AF_BIN_OP_WITH_INT(^, C_TYPE, WI, SI, logic) \ + \ + AF_REL_OP_WITH_INT(==, C_TYPE, WI, SI) \ + AF_REL_OP_WITH_INT(!=, C_TYPE, WI, SI) \ + AF_REL_OP_WITH_INT(>, C_TYPE, WI, SI) \ + AF_REL_OP_WITH_INT(>=, C_TYPE, WI, SI) \ + AF_REL_OP_WITH_INT(<, C_TYPE, WI, SI) \ + AF_REL_OP_WITH_INT(<=, C_TYPE, WI, SI) \ + \ + AF_ASSIGN_OP_WITH_INT(+=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT(-=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT(*=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT(/=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT_SF(>>=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT_SF(<<=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT(&=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT(|=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT(^=, C_TYPE, WI, SI) + +AF_OPS_WITH_INT(bool, 1, false) +AF_OPS_WITH_INT(char, 8, true) +AF_OPS_WITH_INT(signed char, 8, true) +AF_OPS_WITH_INT(unsigned char, 8, false) +AF_OPS_WITH_INT(short, 16, true) +AF_OPS_WITH_INT(unsigned short, 16, false) +AF_OPS_WITH_INT(int, 32, true) +AF_OPS_WITH_INT(unsigned int, 32, false) +# if defined __x86_64__ +AF_OPS_WITH_INT(long, 64, true) +AF_OPS_WITH_INT(unsigned long, 64, false) +# else +AF_OPS_WITH_INT(long, 32, true) +AF_OPS_WITH_INT(unsigned long, 32, false) +# endif +AF_OPS_WITH_INT(ap_slong, 64, true) +AF_OPS_WITH_INT(ap_ulong, 64, false) + +#define AF_BIN_OP_WITH_AP_INT(BIN_OP, RTYPE) \ + template \ + INLINE typename ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>::template RType<_AP_W,_AP_I,_AP_S>::RTYPE \ + operator BIN_OP ( const ap_private<_AP_W2,_AP_S2>& i_op, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op) { \ + return ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op).operator BIN_OP (op); \ + } \ + template \ + INLINE typename ap_fixed_base<_AP_W,_AP_I,_AP_S>::template RType<_AP_W2,_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP ( const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, const ap_private<_AP_W2,_AP_S2>& i_op) { \ + return op.operator BIN_OP (ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op)); \ + } + +#define AF_REL_OP_WITH_AP_INT(REL_OP) \ + template \ + INLINE bool operator REL_OP ( const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, const ap_private<_AP_W2,_AP_S2>& i_op) { \ + return op.operator REL_OP ( ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op)); \ + } \ + template \ + INLINE bool operator REL_OP ( const ap_private<_AP_W2,_AP_S2>& i_op, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op) { \ + return ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op).operator REL_OP (op); \ + } + +#define AF_ASSIGN_OP_WITH_AP_INT(ASSIGN_OP) \ + template \ + INLINE ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& operator ASSIGN_OP ( ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, const ap_private<_AP_W2,_AP_S2>& i_op) { \ + return op.operator ASSIGN_OP (ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op)); \ + } \ + template \ + INLINE ap_private<_AP_W2,_AP_S2>& operator ASSIGN_OP ( ap_private<_AP_W2,_AP_S2>& i_op, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op) { \ + return i_op.operator ASSIGN_OP (op.to_ap_private()); \ + } + +AF_BIN_OP_WITH_AP_INT(+, plus) +AF_BIN_OP_WITH_AP_INT(-, minus) +AF_BIN_OP_WITH_AP_INT(*, mult) +AF_BIN_OP_WITH_AP_INT(/, div) +AF_BIN_OP_WITH_AP_INT(&, logic) +AF_BIN_OP_WITH_AP_INT(|, logic) +AF_BIN_OP_WITH_AP_INT(^, logic) + +AF_REL_OP_WITH_AP_INT(==) +AF_REL_OP_WITH_AP_INT(!=) +AF_REL_OP_WITH_AP_INT(>) +AF_REL_OP_WITH_AP_INT(>=) +AF_REL_OP_WITH_AP_INT(<) +AF_REL_OP_WITH_AP_INT(<=) + +AF_ASSIGN_OP_WITH_AP_INT(+=) +AF_ASSIGN_OP_WITH_AP_INT(-=) +AF_ASSIGN_OP_WITH_AP_INT(*=) +AF_ASSIGN_OP_WITH_AP_INT(/=) +AF_ASSIGN_OP_WITH_AP_INT(&=) +AF_ASSIGN_OP_WITH_AP_INT(|=) +AF_ASSIGN_OP_WITH_AP_INT(^=) + +#define AF_REF_REL_OP_MIX_INT(REL_OP, C_TYPE, _AP_W2, _AP_S2) \ +template \ + INLINE bool operator REL_OP ( const af_range_ref<_AP_W,_AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op, C_TYPE op2) { \ + return (ap_private<_AP_W, false>(op)).operator REL_OP (ap_private<_AP_W2,_AP_S2>(op2)); \ + } \ +template \ + INLINE bool operator REL_OP ( C_TYPE op2, const af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op) { \ + return ap_private<_AP_W2,_AP_S2>(op2).operator REL_OP (ap_private<_AP_W, false>(op)); \ + } \ +template \ + INLINE bool operator REL_OP ( const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op, C_TYPE op2) { \ + return (bool(op)) REL_OP op2; \ + } \ +template \ + INLINE bool operator REL_OP ( C_TYPE op2, const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op) { \ + return op2 REL_OP (bool(op)); \ + } + +#define AF_REF_REL_MIX_INT(C_TYPE, _AP_WI, _AP_SI) \ +AF_REF_REL_OP_MIX_INT(>, C_TYPE, _AP_WI, _AP_SI) \ +AF_REF_REL_OP_MIX_INT(<, C_TYPE, _AP_WI, _AP_SI) \ +AF_REF_REL_OP_MIX_INT(>=, C_TYPE, _AP_WI, _AP_SI) \ +AF_REF_REL_OP_MIX_INT(<=, C_TYPE, _AP_WI, _AP_SI) \ +AF_REF_REL_OP_MIX_INT(==, C_TYPE, _AP_WI, _AP_SI) \ +AF_REF_REL_OP_MIX_INT(!=, C_TYPE, _AP_WI, _AP_SI) + +AF_REF_REL_MIX_INT(bool, 1, false) +AF_REF_REL_MIX_INT(char, 8, true) +AF_REF_REL_MIX_INT(signed char, 8, true) +AF_REF_REL_MIX_INT(unsigned char, 8, false) +AF_REF_REL_MIX_INT(short, 16, true) +AF_REF_REL_MIX_INT(unsigned short, 16, false) +AF_REF_REL_MIX_INT(int, 32, true) +AF_REF_REL_MIX_INT(unsigned int, 32, false) +# if defined __x86_64__ +AF_REF_REL_MIX_INT(long, 64, true) +AF_REF_REL_MIX_INT(unsigned long, 64, false) +# else +AF_REF_REL_MIX_INT(long, 32, true) +AF_REF_REL_MIX_INT(unsigned long, 32, false) +# endif +AF_REF_REL_MIX_INT(ap_slong, 64, true) +AF_REF_REL_MIX_INT(ap_ulong, 64, false) + +#define AF_REF_REL_OP_AP_INT(REL_OP) \ +template \ + INLINE bool operator REL_OP ( const af_range_ref<_AP_W,_AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op, const ap_private<_AP_W2, _AP_S> &op2) { \ + return (ap_private<_AP_W, false>(op)).operator REL_OP (op2); \ + } \ +template \ + INLINE bool operator REL_OP (const ap_private<_AP_W2, _AP_S2> &op2, const af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op) { \ + return op2.operator REL_OP (ap_private<_AP_W, false>(op)); \ + } \ +template \ + INLINE bool operator REL_OP ( const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op, const ap_private<_AP_W2, _AP_S2> &op2) { \ + return (ap_private<1, false>(op)).operator REL_OP (op2); \ + } \ +template \ + INLINE bool operator REL_OP ( const ap_private<_AP_W2, _AP_S2> &op2, const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op) { \ + return op2.operator REL_OP (ap_private<1,false>(op)); \ + } + +AF_REF_REL_OP_AP_INT(>) +AF_REF_REL_OP_AP_INT(<) +AF_REF_REL_OP_AP_INT(>=) +AF_REF_REL_OP_AP_INT(<=) +AF_REF_REL_OP_AP_INT(==) +AF_REF_REL_OP_AP_INT(!=) + +// Relational Operators with double +template +INLINE bool operator == ( double op1, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op2) { + return op2.operator == (op1); +} + +template +INLINE bool operator != ( double op1, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op2) { + return op2.operator != (op1); +} + +template +INLINE bool operator > ( double op1, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op2) { + return op2.operator < (op1); +} + +template +INLINE bool operator >= ( double op1, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op2) { + return op2.operator <= (op1); +} + +template +INLINE bool operator < ( double op1, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op2) { + return op2.operator > (op1); +} + +template +INLINE bool operator <= ( double op1, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op2) { + return op2.operator >= (op1); +} + +#endif /* #ifndef __AESL_GCC_AP_FIXED_H__ */ \ No newline at end of file diff --git a/hls_2018/router_04/etc/ap_int_sim.h b/hls_2018/router_04/etc/ap_int_sim.h new file mode 100755 index 0000000..887ccd8 --- /dev/null +++ b/hls_2018/router_04/etc/ap_int_sim.h @@ -0,0 +1,1629 @@ +/* + * Copyright 2012 Xilinx, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __AESL_GCC_AP_INT_H__ +#define __AESL_GCC_AP_INT_H__ + +#ifndef __cplusplus +#error C++ is required to include this header file +#endif /* #ifndef __cplusplus */ + +#undef _AP_DEBUG_ +#include +#include + +// for safety +#if (defined(_AP_N)|| defined(_AP_C)) +#error One or more of the following is defined: _AP_N, _AP_C. Definition conflicts with their usage as template parameters. +#endif /* #if (defined(_AP_N)|| defined(_AP_C)) */ + +// for safety +#if (defined(_AP_W) || defined(_AP_I) || defined(_AP_S) || defined(_AP_Q) || defined(_AP_O) || defined(_AP_W2) || defined(_AP_I2) || defined(_AP_S2) || defined(_AP_Q2) || defined(_AP_O2)) +#error One or more of the following is defined: _AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2. Definition conflicts with their usage as template parameters. +#endif /* #if (defined(_AP_W) || defined(_AP_I) || defined(_AP_S) || defined(_AP_Q) || defined(_AP_O) || defined(_AP_W2) || defined(_AP_I2) || defined(_AP_S2) || defined(_AP_Q2) || defined(_AP_O2)) */ + +//for safety +#if (defined(_AP_W3) || defined(_AP_S3) || defined(_AP_W4) || defined(_AP_S4)) +#error One or more of the following is defined: _AP_W3, _AP_S3, _AP_W4,_AP_S4. Definition conflicts with their usage as template parameters. +#endif /* #if (defined(_AP_W3) || defined(_AP_S3) || defined(_AP_W4) || defined(_AP_S4)) */ + +//for safety +#if (defined(_AP_W1) || defined(_AP_S1) || defined(_AP_I1) || defined(_AP_T) || defined(_AP_T1) || defined(_AP_T2) || defined(_AP_T3) || defined(_AP_T4)) +#error One or more of the following is defined: _AP_W1, _AP_S1, _AP_I1, _AP_T, _AP_T1, _AP_T2, _AP_T3, _AP_T4. Definition conflicts with their usage as template parameters. +#endif /* #if (defined(_AP_W1) || defined(_AP_S1) || defined(_AP_I1) || defined(_AP_T) || defined(_AP_T1) || defined(_AP_T2) || defined(_AP_T3) || defined(_AP_T4)) */ + +#define __AESL_APDT_IN_SCFLOW__ +#ifndef __AESL_APDT_IN_SCFLOW__ + #include "etc/ap_private.h" +#else + #include "../etc/ap_private.h" +#endif /* #ifndef __AESL_APDT_IN_SCFLOW__ */ + +#ifdef _AP_DEBUG_ + #define AP_DEBUG(s) s +#else + #define AP_DEBUG(s) +#endif /* #ifdef _AP_DEBUG_ */ + +#ifndef __SIMULATION__ + #define __SIMULATION__ +#endif /* #ifndef __SIMULATION__ */ + +#if !(defined SYSTEMC_H) && !(defined SYSTEMC_INCLUDED) + #ifndef SC_TRN + #define SC_TRN AP_TRN + #endif /* #ifndef SC_TRN */ + #ifndef SC_RND + #define SC_RND AP_RND + #endif /* #ifndef SC_RND */ + #ifndef SC_TRN_ZERO + #define SC_TRN_ZERO AP_TRN_ZERO + #endif /* #ifndef SC_TRN_ZERO */ + #ifndef SC_RND_ZERO + #define SC_RND_ZERO AP_RND_ZERO + #endif /* #ifndef SC_RND_ZERO */ + #ifndef SC_RND_INF + #define SC_RND_INF AP_RND_INF + #endif /* #ifndef SC_RND_INF */ + #ifndef SC_RND_MIN_INF + #define SC_RND_MIN_INF AP_RND_MIN_INF + #endif /* #ifndef SC_RND_MIN_INF */ + #ifndef SC_RND_CONV + #define SC_RND_CONV AP_RND_CONV + #endif /* #ifndef SC_RND_CONV */ + #ifndef SC_WRAP + #define SC_WRAP AP_WRAP + #endif /* #ifndef SC_WRAP */ + #ifndef SC_SAT + #define SC_SAT AP_SAT + #endif /* #ifndef SC_SAT */ + #ifndef SC_SAT_ZERO + #define SC_SAT_ZERO AP_SAT_ZERO + #endif /* #ifndef SC_SAT_ZERO */ + #ifndef SC_SAT_SYM + #define SC_SAT_SYM AP_SAT_SYM + #endif /* #ifndef SC_SAT_SYM */ + #ifndef SC_WRAP_SM + #define SC_WRAP_SM AP_WRAP_SM + #endif /* #ifndef SC_WRAP_SM */ + #ifndef SC_BIN + #define SC_BIN AP_BIN + #endif /* #ifndef SC_BIN */ + #ifndef SC_OCT + #define SC_OCT AP_OCT + #endif /* #ifndef SC_OCT */ + #ifndef SC_DEC + #define SC_DEC AP_DEC + #endif /* #ifndef SC_DEC */ + #ifndef SC_HEX + #define SC_HEX AP_HEX + #endif /* #ifndef SC_HEX */ +#endif /* #if !(defined SYSTEMC_H) && !(defined SYSTEMC_INCLUDED) */ +#ifndef AP_INT_MAX_W +#define AP_INT_MAX_W 1024 +#endif +#define BIT_WIDTH_UPPER_LIMIT (1 << 15) +#if AP_INT_MAX_W > BIT_WIDTH_UPPER_LIMIT +#error "Bitwidth exceeds 32768 (1 << 15), the maximum allowed value" +#endif +#define MAX_MODE(BITS) ((BITS + 1023) / 1024) + +///Forward declaration +template struct ap_range_ref; +template struct ap_bit_ref; + +template struct ap_fixed_base; +template struct af_range_ref; +template struct af_bit_ref; +template class ap_uint; + +enum { + AP_BIN = 2, + AP_OCT = 8, + AP_DEC = 10, + AP_HEX = 16 +}; + +///Why to use reference? +///Because we will operate the original object indirectly by operating the +///result object directly after concating or part selecting + +///Proxy class which allows concatination to be used as rvalue(for reading) and +//lvalue(for writing) + +/// Concatination reference. +// ---------------------------------------------------------------- +template +struct ap_concat_ref { +#ifdef _MSC_VER + #pragma warning(disable: 4521 4522) +#endif /* #ifdef _MSC_VER */ + enum {_AP_WR=_AP_W1+_AP_W2,}; + _AP_T1& mbv1; + _AP_T2& mbv2; + + INLINE ap_concat_ref(const ap_concat_ref<_AP_W1, _AP_T1, + _AP_W2, _AP_T2>& ref): + mbv1(ref.mbv1), mbv2(ref.mbv2) {} + + INLINE ap_concat_ref(_AP_T1& bv1, _AP_T2& bv2):mbv1(bv1),mbv2(bv2) {} + + template + INLINE ap_concat_ref& operator = (const ap_private<_AP_W3,_AP_S3>& val) { + ap_private<_AP_W1+_AP_W2, false> vval(val); + int W_ref1=mbv1.length(); + int W_ref2=mbv2.length(); + ap_private<_AP_W1,false> mask1(-1); + mask1>>=_AP_W1-W_ref1; + ap_private<_AP_W2,false> mask2(-1); + mask2>>=_AP_W2-W_ref2; + mbv1.set(ap_private<_AP_W1,false>((vval>>W_ref2)&mask1)); + mbv2.set(ap_private<_AP_W2,false>(vval&mask2)); + return *this; + } + + INLINE ap_concat_ref& operator = (unsigned long long val) { + ap_private<_AP_W1+_AP_W2, false> tmpVal(val); + return operator = (tmpVal); + } + + template + INLINE ap_concat_ref& operator = + (const ap_concat_ref <_AP_W3, _AP_T3, _AP_W4, _AP_T4>& val) { + ap_private<_AP_W1+_AP_W2, false> tmpVal(val); + return operator = (tmpVal); + } + + INLINE ap_concat_ref& operator = + (const ap_concat_ref <_AP_W1, _AP_T1, _AP_W2, _AP_T2>& val) { + ap_private<_AP_W1+_AP_W2, false> tmpVal(val); + return operator = (tmpVal); + } + + template + INLINE ap_concat_ref& operator =(const ap_bit_ref<_AP_W3, _AP_S3>& val) { + ap_private<_AP_W1+_AP_W2, false> tmpVal(val); + return operator = (tmpVal); + } + + template + INLINE ap_concat_ref& operator =(const ap_range_ref<_AP_W3,_AP_S3>& val) { + ap_private<_AP_W1+_AP_W2, false> tmpVal(val); + return operator =(tmpVal); + } + + template + INLINE ap_concat_ref& operator= (const af_range_ref<_AP_W3, _AP_I3, _AP_S3, + _AP_Q3, _AP_O3, _AP_N3>& val) { + return operator = ((const ap_private<_AP_W3, false>)(val)); + } + + template + INLINE ap_concat_ref& operator= (const ap_fixed_base<_AP_W3, _AP_I3, _AP_S3, + _AP_Q3, _AP_O3, _AP_N3>& val) { + return operator = (val.to_ap_private()); + } + + template + INLINE ap_concat_ref& operator= (const af_bit_ref<_AP_W3, _AP_I3, _AP_S3, + _AP_Q3, _AP_O3, _AP_N3>& val) { + return operator=((unsigned long long)(bool)(val)); + } + + + INLINE operator ap_private<_AP_WR, false> () const { + return get(); + } + + INLINE operator unsigned long long () const { + return get().to_uint64(); + } + + template + INLINE ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, ap_range_ref<_AP_W3, _AP_S3> > + operator, (const ap_range_ref<_AP_W3, _AP_S3> &a2) { + return ap_concat_ref<_AP_WR, ap_concat_ref, + _AP_W3, ap_range_ref<_AP_W3, _AP_S3> >(*this, + const_cast &>(a2)); + } + + template + INLINE ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, ap_private<_AP_W3, _AP_S3> > + operator, (ap_private<_AP_W3, _AP_S3> &a2) { + return ap_concat_ref<_AP_WR, ap_concat_ref, + _AP_W3, ap_private<_AP_W3, _AP_S3> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, ap_private<_AP_W3, _AP_S3> > + operator, (const ap_private<_AP_W3, _AP_S3> &a2) { + return ap_concat_ref<_AP_WR, ap_concat_ref, + _AP_W3, ap_private<_AP_W3, _AP_S3> >(*this, + const_cast&>(a2)); + } + + template + INLINE ap_concat_ref<_AP_WR, ap_concat_ref, 1, ap_bit_ref<_AP_W3, _AP_S3> > + operator, (const ap_bit_ref<_AP_W3, _AP_S3> &a2) { + return ap_concat_ref<_AP_WR, ap_concat_ref, + 1, ap_bit_ref<_AP_W3, _AP_S3> >(*this, + const_cast &>(a2)); + } + + template + INLINE ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3+_AP_W4, ap_concat_ref<_AP_W3,_AP_T3,_AP_W4,_AP_T4> > + operator, (const ap_concat_ref<_AP_W3,_AP_T3,_AP_W4,_AP_T4> &a2) + { + return ap_concat_ref<_AP_WR, ap_concat_ref, + _AP_W3+_AP_W4, ap_concat_ref<_AP_W3,_AP_T3,_AP_W4, + _AP_T4> >(*this, const_cast& >(a2)); + } + + template + INLINE + ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, af_range_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3> > + operator, (const af_range_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, + _AP_O3, _AP_N3> &a2) { + return ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, af_range_ref<_AP_W3, + _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3> >(*this, + const_cast& >(a2)); + } + + template + INLINE + ap_concat_ref<_AP_WR, ap_concat_ref, 1, af_bit_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3> > + operator, (const af_bit_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, + _AP_O3, _AP_N3> &a2) { + return ap_concat_ref<_AP_WR, ap_concat_ref, 1, af_bit_ref<_AP_W3, + _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3> >(*this, + const_cast& >(a2)); + } + + template + INLINE ap_private + operator & (const ap_private<_AP_W3,_AP_S3>& a2) { + return get() & a2; + } + + + template + INLINE ap_private + operator | (const ap_private<_AP_W3,_AP_S3>& a2) { + return get() | a2; + } + + + template + INLINE ap_private + operator ^ (const ap_private<_AP_W3,_AP_S3>& a2) { + return ap_private(get() ^ a2); + } + + INLINE const ap_private<_AP_WR, false> get() const + { + ap_private<_AP_W1+_AP_W2, false> tmpVal = ap_private<_AP_W1+_AP_W2, false> (mbv1.get()); + ap_private<_AP_W1+_AP_W2, false> tmpVal2 = ap_private<_AP_W1+_AP_W2, false> (mbv2.get()); + int W_ref2 = mbv2.length(); + tmpVal <<= W_ref2; + tmpVal |= tmpVal2; + return tmpVal; + } + + INLINE const ap_private<_AP_WR, false> get() { + ap_private<_AP_W1+_AP_W2, false> tmpVal = ap_private<_AP_W1+_AP_W2, false> ( mbv1.get()); + ap_private<_AP_W1+_AP_W2, false> tmpVal2 = ap_private<_AP_W1+_AP_W2, false> (mbv2.get()); + int W_ref2 = mbv2.length(); + tmpVal <<= W_ref2; + tmpVal |= tmpVal2; + return tmpVal; + } + + template + INLINE void set(const ap_private<_AP_W3,false> & val) { + ap_private<_AP_W1+_AP_W2, false> vval(val); + int W_ref1=mbv1.length(); + int W_ref2=mbv2.length(); + ap_private<_AP_W1,false> mask1(-1); + mask1>>=_AP_W1-W_ref1; + ap_private<_AP_W2,false> mask2(-1); + mask2>>=_AP_W2-W_ref2; + mbv1.set(ap_private<_AP_W1,false>((vval>>W_ref2)&mask1)); + mbv2.set(ap_private<_AP_W2,false>(vval&mask2)); + } + + INLINE int length() const { + return mbv1.length()+mbv2.length(); + } + + INLINE std::string to_string(uint8_t radix=2) const { + return get().to_string(radix); + } +}; + +///Proxy class, which allows part selection to be used as rvalue(for reading) and +//lvalue(for writing) + +///Range(slice) reference +//------------------------------------------------------------ +template +struct ap_range_ref { +#ifdef _MSC_VER + #pragma warning( disable : 4521 4522 ) +#endif /* #ifdef _MSC_VER */ + ap_private<_AP_W,_AP_S> &d_bv; + int l_index; + int h_index; + +public: + INLINE ap_range_ref(const ap_range_ref<_AP_W, _AP_S>& ref): + d_bv(ref.d_bv), l_index(ref.l_index), h_index(ref.h_index) {} + + INLINE ap_range_ref(ap_private<_AP_W,_AP_S>* bv, int h, int l): + d_bv(*bv),l_index(l),h_index(h) { + //if (h < l) + //fprintf(stderr, "Warning! The bits selected will be returned in reverse order\n"); + } + + INLINE operator ap_private<_AP_W, false> () const { + ap_private<_AP_W, false> val(0); + if(h_index>=l_index) { + if (_AP_W > 64) { + val=d_bv; + ap_private<_AP_W,false> mask(-1); + mask>>=_AP_W-(h_index-l_index+1); + val>>=l_index; + val&=mask; + } else { + const static uint64_t mask = (~0ULL>> (64>_AP_W ? (64-_AP_W):0)); + val = (d_bv >> l_index) & (mask >>(_AP_W-(h_index-l_index+1))); + } + } else { + for(int i=0, j=l_index;j>=0&&j>=h_index;j--,i++) + if((d_bv)[j]) val.set(i); + } + return val; + } + + INLINE operator unsigned long long () const { + return to_uint64(); + } + + template + INLINE ap_range_ref& operator =(const ap_private<_AP_W2,_AP_S2>& val) { + ap_private<_AP_W,false> vval=ap_private<_AP_W,false>(val); + if (l_index>h_index) { + for (int i=0, j=l_index;j>=0&&j>=h_index;j--,i++) + (vval)[i]? d_bv.set(j):d_bv.clear(j); + } else { + if (_AP_W > 64) { + ap_private<_AP_W,false> mask(-1); + if (l_index>0) { + mask<<=l_index; + vval<<=l_index; + } + if(h_index<_AP_W-1) + { + ap_private<_AP_W,false> mask2(-1); + mask2>>=_AP_W-h_index-1; + mask&=mask2; + vval&=mask2; + } + mask.flip(); + d_bv&=mask; + d_bv|=vval; + } else { + unsigned shift = 64-_AP_W; + uint64_t mask = ~0ULL>>(shift); + if(l_index>0) + { + vval = mask & vval << l_index; + mask = mask & mask << l_index; + } + if(h_index<_AP_W-1) + { + uint64_t mask2 = mask; + mask2 >>= (_AP_W-h_index-1); + mask&=mask2; + vval&=mask2; + } + mask = ~mask; + d_bv&=mask; + d_bv|=vval; + } + } + return *this; + } + + INLINE ap_range_ref& operator = (unsigned long long val) + { + const ap_private<_AP_W,_AP_S> vval=val; + return operator = (vval); + } + + + INLINE ap_range_ref& operator =(const ap_range_ref<_AP_W, _AP_S>& val) + { + const ap_private<_AP_W, false> tmpVal(val); + return operator =(tmpVal); + } + + + + template + INLINE ap_range_ref& operator = + (const ap_concat_ref <_AP_W3, _AP_T3, _AP_W4, _AP_T4>& val) + { + const ap_private<_AP_W, false> tmpVal(val); + return operator = (tmpVal); + } + + template + INLINE ap_range_ref& operator =(const ap_range_ref<_AP_W3,_AP_S3>& val) + { + const ap_private<_AP_W, false> tmpVal(val); + return operator =(tmpVal); + } + + template + INLINE ap_range_ref& operator= (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& val) { + return operator=((const ap_private<_AP_W2, _AP_S2>)(val)); + } + + template + INLINE ap_range_ref& operator= (const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& val) { + return operator=(val.to_ap_private()); + } + + template + INLINE ap_range_ref& operator= (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& val) { + return operator=((unsigned long long)(bool)(val)); + } + + template + INLINE ap_range_ref& operator= (const ap_bit_ref<_AP_W2, _AP_S2>& val) { + return operator=((unsigned long long)(bool)(val)); + } + + template + INLINE + ap_concat_ref<_AP_W,ap_range_ref,_AP_W2,ap_range_ref<_AP_W2,_AP_S2> > + operator, (const ap_range_ref<_AP_W2,_AP_S2> &a2) + { + return + ap_concat_ref<_AP_W, ap_range_ref, _AP_W2, + ap_range_ref<_AP_W2,_AP_S2> >(*this, + const_cast& >(a2)); + } + + + template + INLINE ap_concat_ref<_AP_W,ap_range_ref,_AP_W2,ap_private<_AP_W2,_AP_S2> > + operator , (ap_private<_AP_W2,_AP_S2>& a2) + { + return + ap_concat_ref<_AP_W, ap_range_ref, _AP_W2, ap_private<_AP_W2,_AP_S2> >(*this, a2); + } + + INLINE ap_concat_ref<_AP_W,ap_range_ref,_AP_W,ap_private<_AP_W,_AP_S> > + operator , (ap_private<_AP_W, _AP_S>& a2) + { + return + ap_concat_ref<_AP_W, ap_range_ref, _AP_W, + ap_private<_AP_W,_AP_S> >(*this, a2); + } + + + + template + INLINE + ap_concat_ref<_AP_W,ap_range_ref,1,ap_bit_ref<_AP_W2,_AP_S2> > + operator, (const ap_bit_ref<_AP_W2,_AP_S2> &a2) + { + return + ap_concat_ref<_AP_W, ap_range_ref, 1, + ap_bit_ref<_AP_W2,_AP_S2> >(*this, const_cast& >(a2)); + } + + + template + INLINE + ap_concat_ref<_AP_W, ap_range_ref, _AP_W2+_AP_W3, ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > + operator, (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) + { + return ap_concat_ref<_AP_W, ap_range_ref, _AP_W2+_AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(*this, + const_cast& >(a2)); + } + + template + INLINE + ap_concat_ref<_AP_W, ap_range_ref, _AP_W2, af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<_AP_W, ap_range_ref, _AP_W2, af_range_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, + const_cast& >(a2)); + } + + template + INLINE + ap_concat_ref<_AP_W, ap_range_ref, 1, af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<_AP_W, ap_range_ref, 1, af_bit_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, + const_cast& >(a2)); + } + + template + INLINE bool operator == (const ap_range_ref<_AP_W2, _AP_S2>& op2) + { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs==rhs; + } + + + template + INLINE bool operator != (const ap_range_ref<_AP_W2, _AP_S2>& op2) + { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs!=rhs; + } + + + template + INLINE bool operator > (const ap_range_ref<_AP_W2, _AP_S2>& op2) + { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs>rhs; + } + + + template + INLINE bool operator >= (const ap_range_ref<_AP_W2, _AP_S2>& op2) + { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs>=rhs; + } + + + template + INLINE bool operator < (const ap_range_ref<_AP_W2, _AP_S2>& op2) + { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs + INLINE bool operator <= (const ap_range_ref<_AP_W2, _AP_S2>& op2) + { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs<=rhs; + } + + + template + INLINE void set(const ap_private<_AP_W2,false>& val) + { + ap_private<_AP_W,_AP_S> vval=val; + if(l_index>h_index) + { + for(int i=0, j=l_index;j>=0&&j>=h_index;j--,i++) + (vval)[i]? d_bv.set(j):d_bv.clear(j); + } else { + if (_AP_W>64 ) { + ap_private<_AP_W,_AP_S> mask(-1); + if(l_index>0) + { + ap_private<_AP_W,false> mask1(-1); + mask1>>=_AP_W-l_index; + mask1.flip(); + mask=mask1; + //vval&=mask1; + vval<<=l_index; + } + if(h_index<_AP_W-1) + { + ap_private<_AP_W,false> mask2(-1); + mask2<<=h_index+1; + mask2.flip(); + mask&=mask2; + vval&=mask2; + } + mask.flip(); + d_bv&=mask; + d_bv|=vval; + } else { + uint64_t mask = ~0ULL >> (64-_AP_W); + if(l_index>0) + { + uint64_t mask1 = mask; + mask1=mask & (mask1>>(_AP_W-l_index)); + vval =mask&( vval <> (64-_AP_W); + mask2 = mask &(mask2<<(h_index+1)); + mask&=~mask2; + vval&=~mask2; + } + d_bv&=(~mask&(~0ULL >> (64-_AP_W))); + d_bv|=vval; + } + } + } + + + INLINE ap_private<_AP_W,false> get() const + { + ap_private<_AP_W,false> val(0); + if(h_index=0&&j>=h_index;j--,i++) + if((d_bv)[j]) val.set(i); + } else { + val=d_bv; + val>>=l_index; + if(h_index<_AP_W-1) + { + if (_AP_W <= 64) { + const static uint64_t mask = (~0ULL>> (64>_AP_W ? (64-_AP_W):0)); + val &= (mask>> (_AP_W-(h_index-l_index+1))); + } else { + ap_private<_AP_W,false> mask(-1); + mask>>=_AP_W-(h_index-l_index+1); + val&=mask; + } + } + } + return val; + } + + + INLINE ap_private<_AP_W,false> get() + { + ap_private<_AP_W,false> val(0); + if(h_index=0&&j>=h_index;j--,i++) + if((d_bv)[j]) val.set(i); + } else { + val=d_bv; + val>>=l_index; + if(h_index<_AP_W-1) + { + if (_AP_W <= 64 ) { + static const uint64_t mask = ~0ULL>> (64>_AP_W ? (64-_AP_W):0); + return val &= ( (mask) >> (_AP_W - (h_index-l_index+1))); + } else { + ap_private<_AP_W,false> mask(-1); + mask>>=_AP_W-(h_index-l_index+1); + val&=mask; + } + } + } + return val; + } + + + INLINE int length() const + { + return h_index>=l_index?h_index-l_index+1:l_index-h_index+1; + } + + + INLINE int to_int() const + { + ap_private<_AP_W,false> val=get(); + return val.to_int(); + } + + + INLINE unsigned int to_uint() const + { + ap_private<_AP_W,false> val=get(); + return val.to_uint(); + } + + + INLINE long to_long() const + { + ap_private<_AP_W,false> val=get(); + return val.to_long(); + } + + + INLINE unsigned long to_ulong() const + { + ap_private<_AP_W,false> val=get(); + return val.to_ulong(); + } + + + INLINE ap_slong to_int64() const + { + ap_private<_AP_W,false> val=get(); + return val.to_int64(); + } + + + INLINE ap_ulong to_uint64() const + { + ap_private<_AP_W,false> val=get(); + return val.to_uint64(); + } + + INLINE std::string to_string(uint8_t radix=2) const { + return get().to_string(radix); + } + +}; + +///Proxy class, which allows bit selection to be used as rvalue(for reading) and +//lvalue(for writing) + +///Bit reference +//-------------------------------------------------------------- +template +struct ap_bit_ref { +#ifdef _MSC_VER +#pragma warning( disable : 4521 4522 ) +#endif + ap_private<_AP_W,_AP_S>& d_bv; + int d_index; + +public: + INLINE ap_bit_ref(const ap_bit_ref<_AP_W, _AP_S>& ref): + d_bv(ref.d_bv), d_index(ref.d_index) {} + + INLINE ap_bit_ref(ap_private<_AP_W,_AP_S>& bv, int index=0): + d_bv(bv),d_index(index) + { +#ifdef _AP_DEBUG_ + assert(d_index<_AP_W&&"index out of bound"); +#endif + } + + + INLINE operator bool () const + { + return d_bv.get_bit(d_index); + } + + + INLINE bool to_bool() const + { + return operator bool (); + } + + + INLINE ap_bit_ref& operator = (unsigned long long val) + { + if(val) + d_bv.set(d_index); + else + d_bv.clear(d_index); + return *this; + } + + +#if 0 + INLINE ap_bit_ref& operator = (bool val) + { + if(val) + d_bv.set(d_index); + else + d_bv.clear(d_index); + return *this; + } +#endif + template + INLINE ap_bit_ref& operator =(const ap_private<_AP_W2,_AP_S2>& val) + { + return operator =((unsigned long long)(val != 0)); + } + + + template + INLINE ap_bit_ref& operator =(const ap_bit_ref<_AP_W2,_AP_S2>& val) + { + return operator =((unsigned long long)(bool)val); + } + + INLINE ap_bit_ref& operator =(const ap_bit_ref<_AP_W,_AP_S>& val) + { + return operator =((unsigned long long)(bool)val); + } + + template + INLINE ap_bit_ref& operator =(const ap_range_ref<_AP_W2,_AP_S2>& val) + { + return operator =((unsigned long long)(bool) val); + } + + + template + INLINE ap_bit_ref& operator= (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& val) { + return operator=((const ap_private<_AP_W2, false>)(val)); + } + + template + INLINE ap_bit_ref& operator= (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& val) { + return operator=((unsigned long long)(bool)(val)); + } + + template + INLINE ap_bit_ref& operator= (const ap_concat_ref<_AP_W2, _AP_T3, _AP_W3, _AP_T3>& val) { + return operator=((const ap_private<_AP_W2 + _AP_W3, false>)(val)); + } + + + + template + INLINE ap_concat_ref<1, ap_bit_ref, _AP_W2, ap_private<_AP_W2,_AP_S2> > + operator , (ap_private<_AP_W2, _AP_S2>& a2) + { + return ap_concat_ref<1, ap_bit_ref, _AP_W2, ap_private<_AP_W2,_AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<1, ap_bit_ref, _AP_W2, ap_range_ref<_AP_W2,_AP_S2> > + operator, (const ap_range_ref<_AP_W2, _AP_S2> &a2) + { + return + ap_concat_ref<1, ap_bit_ref, _AP_W2, ap_range_ref<_AP_W2,_AP_S2> >(*this, + const_cast &>(a2)); + } + + + template + INLINE ap_concat_ref<1, ap_bit_ref, 1, ap_bit_ref<_AP_W2,_AP_S2> > + operator, (const ap_bit_ref<_AP_W2, _AP_S2> &a2) + { + return + ap_concat_ref<1, ap_bit_ref, 1, ap_bit_ref<_AP_W2,_AP_S2> >(*this, + const_cast &>(a2)); + } + + + INLINE ap_concat_ref<1, ap_bit_ref, 1, ap_bit_ref > + operator, (const ap_bit_ref &a2) + { + return + ap_concat_ref<1, ap_bit_ref, 1, ap_bit_ref >(*this, + const_cast(a2)); + } + + + template + INLINE ap_concat_ref<1, ap_bit_ref, _AP_W2+_AP_W3, ap_concat_ref<_AP_W2,_AP_T2,_AP_W3,_AP_T3> > + operator, (const ap_concat_ref<_AP_W2,_AP_T2,_AP_W3,_AP_T3> &a2) + { + return + ap_concat_ref<1,ap_bit_ref,_AP_W2+_AP_W3, + ap_concat_ref<_AP_W2,_AP_T2,_AP_W3,_AP_T3> >(*this, + const_cast& >(a2)); + } + + template + INLINE + ap_concat_ref<1, ap_bit_ref, _AP_W2, af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<1, ap_bit_ref, _AP_W2, af_range_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, + const_cast& >(a2)); + } + + template + INLINE + ap_concat_ref<1, ap_bit_ref, 1, af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<1, ap_bit_ref, 1, af_bit_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, + const_cast& >(a2)); + } + + template + INLINE bool operator == (const ap_bit_ref<_AP_W2, _AP_S2>& op) { + return get() == op.get(); + } + + template + INLINE bool operator != (const ap_bit_ref<_AP_W2, _AP_S2>& op) { + return get() != op.get(); + } + + + INLINE bool get() const + { + return operator bool (); + } + + + INLINE bool get() + { + return operator bool (); + } + + + template + INLINE void set(const ap_private<_AP_W3, false>& val) + { + operator = (val); + } + + INLINE bool operator ~ () const { + bool bit = (d_bv)[d_index]; + return bit ? false : true; + } + + INLINE int length() const { return 1; } + + INLINE std::string to_string() const { + bool val = get(); + return val ? "1" : "0"; + } +}; + +/// Operators mixing Integers with AP_Int +// ---------------------------------------------------------------- +#if 1 +#define OP_BIN_MIX_INT(BIN_OP, C_TYPE, _AP_WI, _AP_SI, RTYPE) \ + template \ + INLINE typename ap_private<_AP_WI,_AP_SI>::template RType<_AP_W,_AP_S>::RTYPE \ + operator BIN_OP ( C_TYPE i_op, const ap_private<_AP_W,_AP_S> &op) { \ + return ap_private<_AP_WI,_AP_SI>(i_op).operator BIN_OP (op); \ + } \ + template \ + INLINE typename ap_private<_AP_W,_AP_S>::template RType<_AP_WI,_AP_SI>::RTYPE \ + operator BIN_OP ( const ap_private<_AP_W,_AP_S> &op, C_TYPE i_op) { \ + return op.operator BIN_OP (ap_private<_AP_WI,_AP_SI>(i_op)); \ + } +#else +#define OP_BIN_MIX_INT(BIN_OP, C_TYPE, _AP_WI, _AP_SI, RTYPE) \ + template \ + INLINE typename ap_private<_AP_WI,_AP_SI>::template RType<_AP_W,_AP_S>::RTYPE \ + operator BIN_OP ( C_TYPE i_op, const ap_private<_AP_W,_AP_S> &op) { \ + return ap_private<_AP_WI,_AP_SI>(i_op).operator BIN_OP (op); \ + } \ + template \ + INLINE typename ap_private<_AP_W,_AP_S>::template RType<_AP_WI,_AP_SI>::RTYPE \ + operator BIN_OP ( const ap_private<_AP_W,_AP_S> &op, C_TYPE i_op) { \ + return op.operator BIN_OP (ap_private<_AP_WI,_AP_SI>(i_op)); \ + } +#endif +#define OP_REL_MIX_INT(REL_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE bool operator REL_OP ( const ap_private<_AP_W,_AP_S> &op, C_TYPE op2) { \ + return op.operator REL_OP (ap_private<_AP_W2, _AP_S2>(op2)); \ + } \ + template \ + INLINE bool operator REL_OP ( C_TYPE op2, const ap_private<_AP_W,_AP_S> &op) { \ + return ap_private<_AP_W2,_AP_S2>(op2).operator REL_OP (op); \ + } +#define OP_ASSIGN_MIX_INT(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE ap_private<_AP_W,_AP_S> &operator ASSIGN_OP ( ap_private<_AP_W,_AP_S> &op, C_TYPE op2) { \ + return op.operator ASSIGN_OP (ap_private<_AP_W2,_AP_S2>(op2)); \ + } + +#define OP_BIN_SHIFT_INT(BIN_OP, C_TYPE, _AP_WI, _AP_SI, RTYPE) \ + template \ + C_TYPE operator BIN_OP ( C_TYPE i_op, const ap_private<_AP_W,_AP_S> &op) { \ + return i_op BIN_OP (op.getVal()); \ + } \ + template \ + INLINE typename ap_private<_AP_W,_AP_S>::template RType<_AP_WI,_AP_SI>::RTYPE \ + operator BIN_OP ( const ap_private<_AP_W,_AP_S> &op, C_TYPE i_op) { \ + return op.operator BIN_OP (i_op); \ + } +#define OP_ASSIGN_RSHIFT_INT(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE ap_private<_AP_W,_AP_S> &operator ASSIGN_OP ( ap_private<_AP_W,_AP_S> &op, C_TYPE op2) { \ + op = op.operator >> (op2); \ + return op; \ + } +#define OP_ASSIGN_LSHIFT_INT(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE ap_private<_AP_W,_AP_S> &operator ASSIGN_OP ( ap_private<_AP_W,_AP_S> &op, C_TYPE op2) { \ + op = op.operator << (op2); \ + return op; \ + } + +#define OPS_MIX_INT(C_TYPE, WI, SI) \ + OP_BIN_MIX_INT(*, C_TYPE, WI, SI, mult) \ + OP_BIN_MIX_INT(+, C_TYPE, WI, SI, plus) \ + OP_BIN_MIX_INT(-, C_TYPE, WI, SI, minus) \ + OP_BIN_MIX_INT(/, C_TYPE, WI, SI, div) \ + OP_BIN_MIX_INT(%, C_TYPE, WI, SI, mod) \ + OP_BIN_MIX_INT(&, C_TYPE, WI, SI, logic) \ + OP_BIN_MIX_INT(|, C_TYPE, WI, SI, logic) \ + OP_BIN_MIX_INT(^, C_TYPE, WI, SI, logic) \ + OP_BIN_SHIFT_INT(>>, C_TYPE, WI, SI, arg1) \ + OP_BIN_SHIFT_INT(<<, C_TYPE, WI, SI, arg1) \ + \ + OP_REL_MIX_INT(==, C_TYPE, WI, SI) \ + OP_REL_MIX_INT(!=, C_TYPE, WI, SI) \ + OP_REL_MIX_INT(>, C_TYPE, WI, SI) \ + OP_REL_MIX_INT(>=, C_TYPE, WI, SI) \ + OP_REL_MIX_INT(<, C_TYPE, WI, SI) \ + OP_REL_MIX_INT(<=, C_TYPE, WI, SI) \ + \ + OP_ASSIGN_MIX_INT(+=, C_TYPE, WI, SI) \ + OP_ASSIGN_MIX_INT(-=, C_TYPE, WI, SI) \ + OP_ASSIGN_MIX_INT(*=, C_TYPE, WI, SI) \ + OP_ASSIGN_MIX_INT(/=, C_TYPE, WI, SI) \ + OP_ASSIGN_MIX_INT(%=, C_TYPE, WI, SI) \ + OP_ASSIGN_MIX_INT(&=, C_TYPE, WI, SI) \ + OP_ASSIGN_MIX_INT(|=, C_TYPE, WI, SI) \ + OP_ASSIGN_MIX_INT(^=, C_TYPE, WI, SI) \ + OP_ASSIGN_RSHIFT_INT(>>=, C_TYPE, WI, SI) \ + OP_ASSIGN_LSHIFT_INT(<<=, C_TYPE, WI, SI) + + +OPS_MIX_INT(bool, 1, false) +OPS_MIX_INT(char, 8, true) +OPS_MIX_INT(signed char, 8, true) +OPS_MIX_INT(unsigned char, 8, false) +OPS_MIX_INT(short, 16, true) +OPS_MIX_INT(unsigned short, 16, false) +OPS_MIX_INT(int, 32, true) +OPS_MIX_INT(unsigned int, 32, false) +# if defined __x86_64__ +OPS_MIX_INT(long, 64, true) +OPS_MIX_INT(unsigned long, 64, false) +# else +OPS_MIX_INT(long, 32, true) +OPS_MIX_INT(unsigned long, 32, false) +# endif +OPS_MIX_INT(ap_slong, 64, true) +OPS_MIX_INT(ap_ulong, 64, false) + +#define OP_BIN_MIX_RANGE(BIN_OP, RTYPE) \ + template \ + INLINE typename ap_private<_AP_W1,_AP_S1>::template RType<_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP ( const ap_range_ref<_AP_W1,_AP_S1>& op1, const ap_private<_AP_W2,_AP_S2>& op2) { \ + return ap_private<_AP_W1, false>(op1).operator BIN_OP (op2); \ + } \ + template \ + INLINE typename ap_private<_AP_W1,_AP_S1>::template RType<_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP ( const ap_private<_AP_W1,_AP_S1>& op1, const ap_range_ref<_AP_W2,_AP_S2>& op2) { \ + return op1.operator BIN_OP (ap_private<_AP_W2, false>(op2)); \ + } + +#define OP_REL_MIX_RANGE(REL_OP) \ + template \ + INLINE bool operator REL_OP ( const ap_range_ref<_AP_W1,_AP_S1>& op1, const ap_private<_AP_W2,_AP_S2>& op2) { \ + return ap_private<_AP_W1,false>(op1).operator REL_OP (op2); \ + } \ + template \ + INLINE bool operator REL_OP ( const ap_private<_AP_W1,_AP_S1>& op1, const ap_range_ref<_AP_W2,_AP_S2>& op2) { \ + return op1.operator REL_OP (op2.operator ap_private<_AP_W2, false>()); \ + } + +#define OP_ASSIGN_MIX_RANGE(ASSIGN_OP) \ + template \ + INLINE ap_private<_AP_W1,_AP_S1>& operator ASSIGN_OP ( ap_private<_AP_W1,_AP_S1>& op1, const ap_range_ref<_AP_W2,_AP_S2>& op2) { \ + return op1.operator ASSIGN_OP (ap_private<_AP_W2, false>(op2)); \ + } \ + template \ + INLINE ap_range_ref<_AP_W1,_AP_S1>& operator ASSIGN_OP (ap_range_ref<_AP_W1,_AP_S1>& op1, ap_private<_AP_W2,_AP_S2>& op2) { \ + ap_private<_AP_W1, false> tmp(op1); \ + tmp.operator ASSIGN_OP (op2); \ + op1 = tmp; \ + return op1; \ + } + + +OP_ASSIGN_MIX_RANGE(+=) +OP_ASSIGN_MIX_RANGE(-=) +OP_ASSIGN_MIX_RANGE(*=) +OP_ASSIGN_MIX_RANGE(/=) +OP_ASSIGN_MIX_RANGE(%=) +OP_ASSIGN_MIX_RANGE(>>=) +OP_ASSIGN_MIX_RANGE(<<=) +OP_ASSIGN_MIX_RANGE(&=) +OP_ASSIGN_MIX_RANGE(|=) +OP_ASSIGN_MIX_RANGE(^=) + +OP_REL_MIX_RANGE(==) +OP_REL_MIX_RANGE(!=) +OP_REL_MIX_RANGE(>) +OP_REL_MIX_RANGE(>=) +OP_REL_MIX_RANGE(<) +OP_REL_MIX_RANGE(<=) + +OP_BIN_MIX_RANGE(+, plus) +OP_BIN_MIX_RANGE(-, minus) +OP_BIN_MIX_RANGE(*, mult) +OP_BIN_MIX_RANGE(/, div) +OP_BIN_MIX_RANGE(%, mod) +OP_BIN_MIX_RANGE(>>, arg1) +OP_BIN_MIX_RANGE(<<, arg1) +OP_BIN_MIX_RANGE(&, logic) +OP_BIN_MIX_RANGE(|, logic) +OP_BIN_MIX_RANGE(^, logic) + +#define OP_BIN_MIX_BIT(BIN_OP, RTYPE) \ + template \ + INLINE typename ap_private<1, false>::template RType<_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP ( const ap_bit_ref<_AP_W1,_AP_S1>& op1, const ap_private<_AP_W2,_AP_S2>& op2) { \ + return ap_private<1, false>(op1).operator BIN_OP (op2); \ + } \ + template \ + INLINE typename ap_private<_AP_W1,_AP_S1>::template RType<1,false>::RTYPE \ + operator BIN_OP ( const ap_private<_AP_W1,_AP_S1>& op1, const ap_bit_ref<_AP_W2,_AP_S2>& op2) { \ + return op1.operator BIN_OP (ap_private<1, false>(op2)); \ + } + +#define OP_REL_MIX_BIT(REL_OP) \ + template \ + INLINE bool operator REL_OP ( const ap_bit_ref<_AP_W1,_AP_S1>& op1, const ap_private<_AP_W2,_AP_S2>& op2) { \ + return ap_private<_AP_W1,false>(op1).operator REL_OP (op2); \ + } \ + template \ + INLINE bool operator REL_OP ( const ap_private<_AP_W1,_AP_S1>& op1, const ap_bit_ref<_AP_W2,_AP_S2>& op2) { \ + return op1.operator REL_OP (ap_private<1, false>(op2)); \ + } + +#define OP_ASSIGN_MIX_BIT(ASSIGN_OP) \ + template \ + INLINE ap_private<_AP_W1,_AP_S1>& operator ASSIGN_OP ( ap_private<_AP_W1,_AP_S1>& op1, ap_bit_ref<_AP_W2,_AP_S2>& op2) { \ + return op1.operator ASSIGN_OP (ap_private<1, false>(op2)); \ + } \ + template \ + INLINE ap_bit_ref<_AP_W1,_AP_S1>& operator ASSIGN_OP ( ap_bit_ref<_AP_W1,_AP_S1>& op1, ap_private<_AP_W2,_AP_S2>& op2) { \ + ap_private<1, false> tmp(op1); \ + tmp.operator ASSIGN_OP (op2); \ + op1 = tmp; \ + return op1; \ + } + + +OP_ASSIGN_MIX_BIT(+=) +OP_ASSIGN_MIX_BIT(-=) +OP_ASSIGN_MIX_BIT(*=) +OP_ASSIGN_MIX_BIT(/=) +OP_ASSIGN_MIX_BIT(%=) +OP_ASSIGN_MIX_BIT(>>=) +OP_ASSIGN_MIX_BIT(<<=) +OP_ASSIGN_MIX_BIT(&=) +OP_ASSIGN_MIX_BIT(|=) +OP_ASSIGN_MIX_BIT(^=) + +OP_REL_MIX_BIT(==) +OP_REL_MIX_BIT(!=) +OP_REL_MIX_BIT(>) +OP_REL_MIX_BIT(>=) +OP_REL_MIX_BIT(<) +OP_REL_MIX_BIT(<=) + +OP_BIN_MIX_BIT(+, plus) +OP_BIN_MIX_BIT(-, minus) +OP_BIN_MIX_BIT(*, mult) +OP_BIN_MIX_BIT(/, div) +OP_BIN_MIX_BIT(%, mod) +OP_BIN_MIX_BIT(>>, arg1) +OP_BIN_MIX_BIT(<<, arg1) +OP_BIN_MIX_BIT(&, logic) +OP_BIN_MIX_BIT(|, logic) +OP_BIN_MIX_BIT(^, logic) + +#define REF_REL_OP_MIX_INT(REL_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE bool operator REL_OP ( const ap_range_ref<_AP_W,_AP_S> &op, C_TYPE op2) { \ + return (ap_private<_AP_W, false>(op)).operator REL_OP (ap_private<_AP_W2,_AP_S2>(op2)); \ + } \ + template \ + INLINE bool operator REL_OP ( C_TYPE op2, const ap_range_ref<_AP_W,_AP_S> &op) { \ + return ap_private<_AP_W2,_AP_S2>(op2).operator REL_OP (ap_private<_AP_W, false>(op)); \ + } \ + template \ + INLINE bool operator REL_OP ( const ap_bit_ref<_AP_W,_AP_S> &op, C_TYPE op2) { \ + return (bool(op)) REL_OP op2; \ + } \ + template \ + INLINE bool operator REL_OP ( C_TYPE op2, const ap_bit_ref<_AP_W,_AP_S> &op) { \ + return op2 REL_OP (bool(op)); \ + } \ + template \ + INLINE bool operator REL_OP ( const ap_concat_ref<_AP_W,_AP_T, _AP_W1, _AP_T1> &op, C_TYPE op2) { \ + return (ap_private<_AP_W + _AP_W1, false>(op)).operator REL_OP (ap_private<_AP_W2,_AP_S2>(op2)); \ + } \ + template \ + INLINE bool operator REL_OP ( C_TYPE op2, const ap_concat_ref<_AP_W,_AP_T, _AP_W1, _AP_T1> &op) { \ + return ap_private<_AP_W2,_AP_S2>(op2).operator REL_OP (ap_private<_AP_W + _AP_W1, false>(op)); \ + } + +#define REF_REL_MIX_INT(C_TYPE, _AP_WI, _AP_SI) \ +REF_REL_OP_MIX_INT(>, C_TYPE, _AP_WI, _AP_SI) \ +REF_REL_OP_MIX_INT(<, C_TYPE, _AP_WI, _AP_SI) \ +REF_REL_OP_MIX_INT(>=, C_TYPE, _AP_WI, _AP_SI) \ +REF_REL_OP_MIX_INT(<=, C_TYPE, _AP_WI, _AP_SI) \ +REF_REL_OP_MIX_INT(==, C_TYPE, _AP_WI, _AP_SI) \ +REF_REL_OP_MIX_INT(!=, C_TYPE, _AP_WI, _AP_SI) + +REF_REL_MIX_INT(bool, 1, false) +REF_REL_MIX_INT(char, 8, true) +REF_REL_MIX_INT(signed char, 8, true) +REF_REL_MIX_INT(unsigned char, 8, false) +REF_REL_MIX_INT(short, 16, true) +REF_REL_MIX_INT(unsigned short, 16, false) +REF_REL_MIX_INT(int, 32, true) +REF_REL_MIX_INT(unsigned int, 32, false) +# if defined __x86_64__ +REF_REL_MIX_INT(long, 64, true) +REF_REL_MIX_INT(unsigned long, 64, false) +# else +REF_REL_MIX_INT(long, 32, true) +REF_REL_MIX_INT(unsigned long, 32, false) +# endif +REF_REL_MIX_INT(ap_slong, 64, true) +REF_REL_MIX_INT(ap_ulong, 64, false) + +#define REF_BIN_OP_MIX_INT(BIN_OP, RTYPE, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE typename ap_private<_AP_W, false>::template RType<_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP ( const ap_range_ref<_AP_W,_AP_S> &op, C_TYPE op2) { \ + return (ap_private<_AP_W, false>(op)).operator BIN_OP (ap_private<_AP_W2,_AP_S2>(op2)); \ + } \ + template \ + INLINE typename ap_private<_AP_W2, _AP_S2>::template RType<_AP_W,false>::RTYPE \ + operator BIN_OP ( C_TYPE op2, const ap_range_ref<_AP_W,_AP_S> &op) { \ + return ap_private<_AP_W2,_AP_S2>(op2).operator BIN_OP (ap_private<_AP_W, false>(op)); \ + } + +#define REF_BIN_MIX_INT(C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(+, plus, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(-, minus, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(*, mult, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(/, div, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(%, mod, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(>>, arg1, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(<<, arg1, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(&, logic, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(|, logic, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(^, logic, C_TYPE, _AP_WI, _AP_SI) + +REF_BIN_MIX_INT(bool, 1, false) +REF_BIN_MIX_INT(char, 8, true) +REF_BIN_MIX_INT(signed char, 8, true) +REF_BIN_MIX_INT(unsigned char, 8, false) +REF_BIN_MIX_INT(short, 16, true) +REF_BIN_MIX_INT(unsigned short, 16, false) +REF_BIN_MIX_INT(int, 32, true) +REF_BIN_MIX_INT(unsigned int, 32, false) +# if defined __x86_64__ +REF_BIN_MIX_INT(long, 64, true) +REF_BIN_MIX_INT(unsigned long, 64, false) +#else +REF_BIN_MIX_INT(long, 32, true) +REF_BIN_MIX_INT(unsigned long, 32, false) +#endif +REF_BIN_MIX_INT(ap_slong, 64, true) +REF_BIN_MIX_INT(ap_ulong, 64, false) + +#define REF_BIN_OP(BIN_OP, RTYPE) \ +template \ +INLINE typename ap_private<_AP_W, false>::template RType<_AP_W2, false>::RTYPE \ +operator BIN_OP (const ap_range_ref<_AP_W,_AP_S> &lhs, const ap_range_ref<_AP_W2,_AP_S2> &rhs) { \ + return ap_private<_AP_W,false>(lhs).operator BIN_OP (ap_private<_AP_W2, false>(rhs)); \ +} + +REF_BIN_OP(+, plus) +REF_BIN_OP(-, minus) +REF_BIN_OP(*, mult) +REF_BIN_OP(/, div) +REF_BIN_OP(%, mod) +REF_BIN_OP(>>, arg1) +REF_BIN_OP(<<, arg1) +REF_BIN_OP(&, logic) +REF_BIN_OP(|, logic) +REF_BIN_OP(^, logic) + +#if 1 +#define CONCAT_OP_MIX_INT(C_TYPE, _AP_WI, _AP_SI) \ +template \ +INLINE \ +ap_private< _AP_W + _AP_WI, false > \ + operator, (const ap_private<_AP_W, _AP_S> &op1, C_TYPE op2) { \ + ap_private<_AP_WI + _AP_W, false> val(op2); \ + ap_private<_AP_WI + _AP_W, false> ret(op1); \ + ret <<= _AP_WI; \ + if (_AP_SI) { \ + val <<= _AP_W; val >>= _AP_W; \ + }\ + ret |= val; \ + return ret;\ +} \ +template \ +INLINE \ +ap_private< _AP_W + _AP_WI, false > \ + operator, (C_TYPE op1, const ap_private<_AP_W, _AP_S>& op2) { \ + ap_private<_AP_WI + _AP_W, false> val(op1); \ + ap_private<_AP_WI + _AP_W, false> ret(op2); \ + if (_AP_S) { \ + ret <<= _AP_WI; ret >>= _AP_WI; \ + } \ + ret |= val << _AP_W; \ + return ret; \ +} \ +template \ +INLINE \ +ap_private< _AP_W + _AP_WI, false > \ + operator, (const ap_range_ref<_AP_W, _AP_S> &op1, C_TYPE op2) { \ + ap_private<_AP_WI + _AP_W, false> val(op2); \ + ap_private<_AP_WI + _AP_W, false> ret(op1); \ + ret <<= _AP_WI; \ + if (_AP_SI) { \ + val <<= _AP_W; val >>= _AP_W; \ + } \ + ret |= val; \ + return ret; \ +} \ +template \ +INLINE \ +ap_private< _AP_W + _AP_WI, false > \ + operator, (C_TYPE op1, const ap_range_ref<_AP_W, _AP_S> &op2) { \ + ap_private<_AP_WI + _AP_W, false> val(op1); \ + ap_private<_AP_WI + _AP_W, false> ret(op2); \ + int len = op2.length(); \ + val <<= len; \ + ret |= val; \ + return ret; \ +} \ +template \ +INLINE \ +ap_private<_AP_WI + 1, false > \ + operator, (const ap_bit_ref<_AP_W, _AP_S> &op1, C_TYPE op2) { \ + ap_private<_AP_WI + 1, false> val(op2); \ + val[_AP_WI] = op1; \ + return val; \ +} \ +template \ +INLINE \ +ap_private<_AP_WI + 1, false > \ + operator, (C_TYPE op1, const ap_bit_ref<_AP_W, _AP_S> &op2) { \ + ap_private<_AP_WI + 1, false> val(op1); \ + val <<= 1; \ + val[0] = op2; \ + return val; \ +} \ +template \ +INLINE \ +ap_private<_AP_W + _AP_W2 + _AP_WI, false > \ + operator, (const ap_concat_ref<_AP_W, _AP_T, _AP_W2, _AP_T2> &op1, C_TYPE op2) {\ + ap_private<_AP_WI + _AP_W + _AP_W2, _AP_SI> val(op2);\ + ap_private<_AP_WI + _AP_W + _AP_W2, _AP_SI> ret(op1);\ + if (_AP_SI) { \ + val <<= _AP_W + _AP_W2; val >>= _AP_W + _AP_W2; \ + } \ + ret <<= _AP_WI; \ + ret |= val; \ + return ret; \ +}\ +template \ +INLINE \ +ap_private<_AP_W + _AP_W2 + _AP_WI, false > \ + operator, (C_TYPE op1, const ap_concat_ref<_AP_W, _AP_T, _AP_W2, _AP_T2> &op2) {\ + ap_private<_AP_WI + _AP_W + _AP_W2, _AP_SI> val(op1);\ + ap_private<_AP_WI + _AP_W + _AP_W2, _AP_SI> ret(op2);\ + int len = op2.length(); \ + val <<= len; \ + ret |= val;\ + return ret; \ +}\ +template \ +INLINE \ +ap_private< _AP_W + _AP_WI, false > \ + operator, (const af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op1, C_TYPE op2) { \ + ap_private<_AP_WI + _AP_W, false> val(op2); \ + ap_private<_AP_WI + _AP_W, false> ret(op1); \ + if (_AP_SI) { \ + val <<= _AP_W; val >>= _AP_W; \ + }\ + ret <<= _AP_WI; \ + ret |= val; \ + return ret; \ +} \ +template \ +INLINE \ +ap_private< _AP_W + _AP_WI, false > \ + operator, (C_TYPE op1, const af_range_ref<_AP_W, _AP_I, _AP_S, \ + _AP_Q, _AP_O, _AP_N> &op2) { \ + ap_private<_AP_WI + _AP_W, false> val(op1); \ + ap_private<_AP_WI + _AP_W, false> ret(op2); \ + int len = op2.length(); \ + val <<= len; \ + ret |= val; \ + return ret; \ +} \ +template \ +INLINE \ +ap_private< 1 + _AP_WI, false> \ + operator, (const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, \ + _AP_N> &op1, C_TYPE op2) { \ + ap_private<_AP_WI + 1, _AP_SI> val(op2); \ + val[_AP_WI] = op1; \ + return val; \ +} \ +template \ +INLINE \ +ap_private< 1 + _AP_WI, false> \ + operator, (C_TYPE op1, const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q,\ + _AP_O, _AP_N> &op2) { \ + ap_private<_AP_WI + 1, _AP_SI> val(op1); \ + val <<= 1; \ + val[0] = op2; \ + return val; \ +} + +CONCAT_OP_MIX_INT(bool, 1, false) +CONCAT_OP_MIX_INT(char, 8, true) +CONCAT_OP_MIX_INT(signed char, 8, true) +CONCAT_OP_MIX_INT(unsigned char, 8, false) +CONCAT_OP_MIX_INT(short, 16, true) +CONCAT_OP_MIX_INT(unsigned short, 16, false) +CONCAT_OP_MIX_INT(int, 32, true) +CONCAT_OP_MIX_INT(unsigned int, 32, false) +# if defined __x86_64__ +CONCAT_OP_MIX_INT(long, 64, true) +CONCAT_OP_MIX_INT(unsigned long, 64, false) +# else +CONCAT_OP_MIX_INT(long, 32, true) +CONCAT_OP_MIX_INT(unsigned long, 32, false) +# endif +CONCAT_OP_MIX_INT(ap_slong, 64, true) +CONCAT_OP_MIX_INT(ap_ulong, 64, false) +#endif + +#if 1 +#define CONCAT_SHIFT_MIX_INT(C_TYPE, op) \ +template \ +INLINE ap_uint<_AP_W+_AP_W1> operator op (const ap_concat_ref<_AP_W, _AP_T, _AP_W1, _AP_T1> lhs, C_TYPE rhs) { \ + return ((ap_uint<_AP_W+_AP_W1>)lhs.get()) op ((int)rhs); \ +} + +CONCAT_SHIFT_MIX_INT(long, <<) +CONCAT_SHIFT_MIX_INT(unsigned long, <<) +CONCAT_SHIFT_MIX_INT(unsigned int, <<) +CONCAT_SHIFT_MIX_INT(ap_ulong, <<) +CONCAT_SHIFT_MIX_INT(ap_slong, <<) +CONCAT_SHIFT_MIX_INT(long, >>) +CONCAT_SHIFT_MIX_INT(unsigned long, >>) +CONCAT_SHIFT_MIX_INT(unsigned int, >>) +CONCAT_SHIFT_MIX_INT(ap_ulong, >>) +CONCAT_SHIFT_MIX_INT(ap_slong, >>) +#endif + +#if defined(SYSTEMC_H) || defined(SYSTEMC_INCLUDED) +template +INLINE void sc_trace(sc_core::sc_trace_file *tf, const ap_private<_AP_W, _AP_S> &op, + const std::string &name) { + if (tf) + tf->trace(sc_dt::sc_lv<_AP_W>(op.to_string(2).c_str()), name); +} +#endif + +template +INLINE std::ostream& operator<<(std::ostream& out, const ap_private<_AP_W,_AP_S> &op) +{ + ap_private<_AP_W, _AP_S> v=op; + const std::ios_base::fmtflags basefield = out.flags() & std::ios_base::basefield; + unsigned radix = (basefield == std::ios_base::hex) ? 16 : + ((basefield == std::ios_base::oct) ? 8 : 10); + std::string str=v.toString(radix,_AP_S); + out< +INLINE std::istream& operator >> (std::istream& in, ap_private<_AP_W,_AP_S> &op) +{ + std::string str; + in >> str; + op = ap_private<_AP_W, _AP_S>(str.c_str()); + return in; + +} + +template +INLINE std::ostream& operator<<(std::ostream& out, const ap_range_ref<_AP_W,_AP_S> &op) +{ + return operator<<(out, ap_private<_AP_W, _AP_S>(op)); +} + +template +INLINE std::istream& operator >> (std::istream& in, ap_range_ref<_AP_W,_AP_S> &op) +{ + return operator>>(in, ap_private<_AP_W, _AP_S>(op));; +} + +template +INLINE void print(const ap_private<_AP_W,_AP_S> &op, bool fill=true ) +{ + ap_private<_AP_W, _AP_S> v=op; + uint32_t ws=v.getNumWords(); + const uint64_t *ptr=v.getRawData(); + int i=ws-1; +#if 0 + if(fill) + printf("%016llx",*(ptr+i)); + else + printf("%llx",*(ptr+i)); +#else +//match SystemC output + if(_AP_W%64 != 0) { + uint32_t offset=_AP_W%64; + uint32_t count=(offset+3)/4; + int64_t data=*(ptr+i); + if(_AP_S) + data=(data<<(64-offset))>>(64-offset); + else + count=(offset+4)/4; + while(count-->0) + printf("%llx",(data>>(count*4))&0xf); + } else { + if(_AP_S==false) + printf("0"); + printf("%016llx",*(ptr+i)); + } +#endif + for(--i;i>=0;i--) + printf("%016llx",*(ptr+i)); + printf("\n"); + +} +#endif /* #ifndef __AESL_GCC_AP_INT_H__ */ \ No newline at end of file diff --git a/hls_2018/router_04/etc/ap_private.h b/hls_2018/router_04/etc/ap_private.h new file mode 100755 index 0000000..1a68a9e --- /dev/null +++ b/hls_2018/router_04/etc/ap_private.h @@ -0,0 +1,5858 @@ +/* + * Copyright 2012 Xilinx, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LLVM_SUPPORT_MATHEXTRAS_H +#define LLVM_SUPPORT_MATHEXTRAS_H + +#ifdef _MSC_VER +#if _MSC_VER <= 1500 +typedef __int8 int8_t; +typedef unsigned __int8 uint8_t; +typedef __int16 int16_t; +typedef unsigned __int16 uint16_t; +typedef __int32 int32_t; +typedef unsigned __int32 uint32_t; +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; +#else if +#include +#endif /* #if _MSC_VER <= 1500 */ +#else +#include +#endif /* #if _MSC_VER <= 1500 */ +#undef INLINE +#if 1 +#define INLINE inline +#else +//Enable to debug ap_int/ap_fixed +#define INLINE __attribute__((weak)) +#endif +#define AP_MAX(a,b) ((a) > (b) ? (a) : (b)) +#define AP_MIN(a,b) ((a) < (b) ? (a) : (b)) +#define AP_ABS(a) ((a)>=0 ? (a):-(a)) +#ifndef AP_INT_MAX_W +#define AP_INT_MAX_W 1024 +#endif +#define BIT_WIDTH_UPPER_LIMIT (1 << 15) +#if AP_INT_MAX_W > BIT_WIDTH_UPPER_LIMIT +#error "Bitwidth exceeds 32768 (1 << 15), the maximum allowed value" +#endif +#define MAX_MODE(BITS) ((BITS + 1023) / 1024) + +// NOTE: The following support functions use the _32/_64 extensions instead of +// type overloading so that signed and unsigned integers can be used without +// ambiguity. + +/// Hi_32 - This function returns the high 32 bits of a 64 bit value. +INLINE uint32_t Hi_32(uint64_t Value) { + return static_cast(Value >> 32); +} + +/// Lo_32 - This function returns the low 32 bits of a 64 bit value. +INLINE uint32_t Lo_32(uint64_t Value) { + return static_cast(Value); +} + +/// ByteSwap_16 - This function returns a byte-swapped representation of the +/// 16-bit argument, Value. +INLINE uint16_t ByteSwap_16(uint16_t Value) { +#if defined(_MSC_VER) && !defined(_DEBUG) + // The DLL version of the runtime lacks these functions (bug!?), but in a + // release build they're replaced with BSWAP instructions anyway. + return (uint16_t)(_byteswap_ushort(Value)); +#else + uint16_t Hi = (uint16_t)((Value) << 8); + uint16_t Lo = (uint16_t)((Value) >> 8); + return Hi | Lo; +#endif +} + +/// ByteSwap_32 - This function returns a byte-swapped representation of the +/// 32-bit argument, Value. +INLINE uint32_t ByteSwap_32(uint32_t Value) { + uint32_t Byte0 = Value & 0x000000FF; + uint32_t Byte1 = Value & 0x0000FF00; + uint32_t Byte2 = Value & 0x00FF0000; + uint32_t Byte3 = Value & 0xFF000000; + return ((Byte0) << 24) | ((Byte1) << 8) | ((Byte2) >> 8) | ((Byte3) >> 24); +} + +/// ByteSwap_64 - This function returns a byte-swapped representation of the +/// 64-bit argument, Value. +INLINE uint64_t ByteSwap_64(uint64_t Value) { + uint64_t Hi = ByteSwap_32(uint32_t(Value)); + uint32_t Lo = ByteSwap_32(uint32_t(Value >> 32)); + return ((Hi) << 32) | Lo; +} + +/// CountLeadingZeros_32 - this function performs the platform optimal form of +/// counting the number of zeros from the most significant bit to the first one +/// bit. Ex. CountLeadingZeros_32(0x00F000FF) == 8. +/// Returns 32 if the word is zero. +INLINE unsigned CountLeadingZeros_32(uint32_t Value) { + unsigned Count; // result +#if __GNUC__ >= 4 + // PowerPC is defined for __builtin_clz(0) +#if !defined(__ppc__) && !defined(__ppc64__) + if (Value == 0) return 32; +#endif + Count = __builtin_clz(Value); +#else + if (Value == 0) return 32; + Count = 0; + // bisecton method for count leading zeros + for (unsigned Shift = 32 >> 1; Shift; Shift >>= 1) { + uint32_t Tmp = (Value) >> (Shift); + if (Tmp) { + Value = Tmp; + } else { + Count |= Shift; + } + } +#endif + return Count; +} + +/// CountLeadingZeros_64 - This function performs the platform optimal form +/// of counting the number of zeros from the most significant bit to the first +/// one bit (64 bit edition.) +/// Returns 64 if the word is zero. +INLINE unsigned CountLeadingZeros_64(uint64_t Value) { + unsigned Count; // result +#if __GNUC__ >= 4 + // PowerPC is defined for __builtin_clzll(0) +#if !defined(__ppc__) && !defined(__ppc64__) + if (!Value) return 64; +#endif + Count = __builtin_clzll(Value); +#else + if (sizeof(long) == sizeof(int64_t)) { + if (!Value) return 64; + Count = 0; + // bisecton method for count leading zeros + for (unsigned Shift = 64 >> 1; Shift; Shift >>= 1) { + uint64_t Tmp = (Value) >> (Shift); + if (Tmp) { + Value = Tmp; + } else { + Count |= Shift; + } + } + } else { + // get hi portion + uint32_t Hi = Hi_32(Value); + + // if some bits in hi portion + if (Hi) { + // leading zeros in hi portion plus all bits in lo portion + Count = CountLeadingZeros_32(Hi); + } else { + // get lo portion + uint32_t Lo = Lo_32(Value); + // same as 32 bit value + Count = CountLeadingZeros_32(Lo)+32; + } + } +#endif + return Count; +} + +/// CountTrailingZeros_64 - This function performs the platform optimal form +/// of counting the number of zeros from the least significant bit to the first +/// one bit (64 bit edition.) +/// Returns 64 if the word is zero. +INLINE unsigned CountTrailingZeros_64(uint64_t Value) { +#if __GNUC__ >= 4 + return (Value != 0) ? __builtin_ctzll(Value) : 64; +#else + static const unsigned Mod67Position[] = { + 64, 0, 1, 39, 2, 15, 40, 23, 3, 12, 16, 59, 41, 19, 24, 54, + 4, 64, 13, 10, 17, 62, 60, 28, 42, 30, 20, 51, 25, 44, 55, + 47, 5, 32, 65, 38, 14, 22, 11, 58, 18, 53, 63, 9, 61, 27, + 29, 50, 43, 46, 31, 37, 21, 57, 52, 8, 26, 49, 45, 36, 56, + 7, 48, 35, 6, 34, 33, 0 + }; + return Mod67Position[(uint64_t)(-(int64_t)Value & (int64_t)Value) % 67]; +#endif +} + +/// CountPopulation_64 - this function counts the number of set bits in a value, +/// (64 bit edition.) +INLINE unsigned CountPopulation_64(uint64_t Value) { +#if __GNUC__ >= 4 + return __builtin_popcountll(Value); +#else + uint64_t v = Value - (((Value) >> 1) & 0x5555555555555555ULL); + v = (v & 0x3333333333333333ULL) + (((v) >> 2) & 0x3333333333333333ULL); + v = (v + ((v) >> 4)) & 0x0F0F0F0F0F0F0F0FULL; + return unsigned((uint64_t)(v * 0x0101010101010101ULL) >> 56); +#endif +} + +#endif // LLVM_SUPPORT_MATHEXTRAS_H + + +#ifndef AP_PRIVATE_H +#define AP_PRIVATE_H + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace AESL_std { + template + DataType INLINE min(DataType a, DataType b) { + // if (a >= b) return b; + // else return a; + return (a>=b) ? b : a; + } + + template + DataType INLINE max(DataType a, DataType b) { + // if (a >= b) return a; + // else return b; + return (a>=b) ? a : b; + } +} +enum ap_q_mode { + AP_RND, // rounding to plus infinity + AP_RND_ZERO,// rounding to zero + AP_RND_MIN_INF,// rounding to minus infinity + AP_RND_INF,// rounding to infinity + AP_RND_CONV, // convergent rounding + AP_TRN, // truncation + AP_TRN_ZERO // truncation to zero + +}; +enum ap_o_mode { + AP_SAT, // saturation + AP_SAT_ZERO, // saturation to zero + AP_SAT_SYM, // symmetrical saturation + AP_WRAP, // wrap-around (*) + AP_WRAP_SM // sign magnitude wrap-around (*) +}; + +template struct ap_fixed_base; +template struct af_range_ref; +template struct af_bit_ref; + +template struct ap_range_ref; +template struct ap_bit_ref; +template struct ap_concat_ref; +static bool InvalidDigit(const char* str, unsigned len, unsigned start, unsigned radix) { + unsigned i; + for (i = start; i < len; ++i) + if ((radix == 2 && (str[i] == '0' || str[i] == '1')) || + (radix == 8 && str[i] >= '0' && str[i] <= '7') || + (radix == 10 && str[i] >= '0' && str[i] <= '9') || + (radix == 16 && ((str[i] >= '0' && str[i] <= '9') || + (str[i] >= 'a' && str[i] <= 'f') || + (str[i] >= 'A' && str[i] <= 'F')))) + continue; + else + return true; + return false; +} + +static void ap_parse_sign(const char* str, uint32_t &base, bool &neg) { + if (str[0] == '+' || str[0] == '-') base = 1; + if (str[0] == '-') neg = true; + else neg = false; + return; +} + +static void ap_parse_prefix(const char* str, uint32_t &offset, uint32_t &radix) { + if (str[0] == '0') { + switch (str[1]) { + case 'b': + case 'B': offset = 2; radix = 2; break; + case 'x': + case 'X': offset = 2; radix = 16; break; + case 'd': + case 'D': offset = 2; radix = 10; break; + case 'o': + case 'O': offset = 2; radix = 8; break; + default: break; + } + } + if (offset == 0) + for (int i=0, len = strlen(str); i= 'a') || (str[i] <= 'F' && str[i] >= 'A')) { + radix = 16; + break; + } + return; +} + +/// sub_1 - This function subtracts a single "digit" (64-bit word), y, from +/// the multi-digit integer array, x[], propagating the borrowed 1 value until +/// no further borrowing is neeeded or it runs out of "digits" in x. The result +/// is 1 if "borrowing" exhausted the digits in x, or 0 if x was not exhausted. +/// In other words, if y > x then this function returns 1, otherwise 0. +/// @returns the borrow out of the subtraction +static bool sub_1(uint64_t x[], uint32_t len, uint64_t y) { + for (uint32_t i = 0; i < len; ++i) { + uint64_t __X = x[i]; + x[i] -= y; + if (y > __X) + y = 1; // We have to "borrow 1" from next "digit" + else { + y = 0; // No need to borrow + break; // Remaining digits are unchanged so exit early + } + } + return (y != 0); +} + + /// This enumeration just provides for internal constants used in this + /// translation unit. + enum { + MIN_INT_BITS = 1, ///< Minimum number of bits that can be specified + ///< Note that this must remain synchronized with IntegerType::MIN_INT_BITS + MAX_INT_BITS = (1<<23)-1 ///< Maximum number of bits that can be specified + ///< Note that this must remain synchronized with IntegerType::MAX_INT_BITS + }; + + /// A utility function for allocating memory and checking for allocation + /// failure. The content is not zeroed. + static uint64_t* getMemory(uint32_t numWords) { + return (uint64_t*) malloc(numWords*sizeof(uint64_t)); + } + + //===----------------------------------------------------------------------===// + // ap_private Class + //===----------------------------------------------------------------------===// + + /// ap_private - This class represents arbitrary precision constant integral values. + /// It is a functional replacement for common case unsigned integer type like + /// "unsigned", "unsigned long" or "uint64_t", but also allows non-byte-width + /// integer sizes and large integer value types such as 3-bits, 15-bits, or more + /// than 64-bits of precision. ap_private provides a variety of arithmetic operators + /// and methods to manipulate integer values of any bit-width. It supports both + /// the typical integer arithmetic and comparison operations as well as bitwise + /// manipulation. + /// + /// The class has several invariants worth noting: + /// * All bit, byte, and word positions are zero-based. + /// * Once the bit width is set, it doesn't change except by the Truncate, + /// SignExtend, or ZeroExtend operations. + /// * All binary operators must be on ap_private instances of the same bit width. + /// Attempting to use these operators on instances with different bit + /// widths will yield an assertion. + /// * The value is stored canonically as an unsigned value. For operations + /// where it makes a difference, there are both signed and unsigned variants + /// of the operation. For example, sdiv and udiv. However, because the bit + /// widths must be the same, operations such as Mul and Add produce the same + /// results regardless of whether the values are interpreted as signed or + /// not. + /// * In general, the class tries to follow the style of computation that LLVM + /// uses in its IR. This simplifies its use for LLVM. + /// + /// @brief Class for arbitrary precision integers. + template class ap_private; + namespace ap_private_ops{ + template + INLINE ap_private<_AP_W, _AP_S, _AP_N> lshr(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, uint32_t shiftAmt); + template + INLINE ap_private<_AP_W, _AP_S, _AP_N> shl(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, uint32_t shiftAmt); + } + +#if defined(_MSC_VER) +# if _MSC_VER < 1400 && !defined(for) +# define for if(0);else for +# endif + typedef unsigned __int64 ap_ulong; + typedef signed __int64 ap_slong; +#else + typedef unsigned long long ap_ulong; + typedef signed long long ap_slong; +#endif + template struct retval { + }; + template<> struct retval { + typedef ap_slong Type; + }; + template<> struct retval { + typedef ap_ulong Type; + }; + + template + class ap_private { +#ifdef _MSC_VER +#pragma warning( disable : 4521 4522 ) +#endif +public: + typedef typename retval<_AP_S>::Type ValType; + template friend struct ap_fixed_base; + ///return type of variety of operations + //---------------------------------------------------------- + template + struct RType { + enum { + mult_w = _AP_W+_AP_W2, + mult_s = _AP_S||_AP_S2, + plus_w = AP_MAX(_AP_W+(_AP_S2&&!_AP_S),_AP_W2+(_AP_S&&!_AP_S2))+1, + plus_s = _AP_S||_AP_S2, + minus_w = AP_MAX(_AP_W+(_AP_S2&&!_AP_S),_AP_W2+(_AP_S&&!_AP_S2))+1, + minus_s = true, + div_w = _AP_W+_AP_S2, + div_s = _AP_S||_AP_S2, + mod_w = AP_MIN(_AP_W,_AP_W2+(!_AP_S2&&_AP_S)), + mod_s = _AP_S, + logic_w = AP_MAX(_AP_W+(_AP_S2&&!_AP_S),_AP_W2+(_AP_S&&!_AP_S2)), + logic_s = _AP_S||_AP_S2 + }; + typedef ap_private mult; + typedef ap_private plus; + typedef ap_private minus; + typedef ap_private logic; + typedef ap_private div; + typedef ap_private mod; + typedef ap_private<_AP_W, _AP_S> arg1; + typedef bool reduce; + }; + + INLINE void report() { +#if 0 + if (_AP_W > 1024 && _AP_W <= 4096) { + fprintf(stderr, "[W] W=%d is out of bound (1<=W<=1024): for" + " synthesis: please define macro AP_INT_TYPE_EXT(N)" + " to extend the valid range.\n", _AP_W); + } else +#endif + if (_AP_W > MAX_MODE(AP_INT_MAX_W) * 1024) { + fprintf(stderr, "[E] ap_%sint<%d>: Bitwidth exceeds the " + "default max value %d. Please use macro " + "AP_INT_MAX_W to set a larger max value.\n", + _AP_S?"":"u", _AP_W, + MAX_MODE(AP_INT_MAX_W) * 1024); + exit(1); + } + } + + enum { BitWidth = _AP_W }; + /// This union is used to store the integer value. When the + /// integer bit-width <= 64, it uses VAL, otherwise it uses pVal. + + /// This enum is used to hold the constants we needed for ap_private. + uint64_t VAL; ///< Used to store the <= 64 bits integer value. + uint64_t pVal[_AP_N]; ///< Used to store the >64 bits integer value. + + /// This enum is used to hold the constants we needed for ap_private. + enum { + APINT_BITS_PER_WORD = sizeof(uint64_t) * 8, ///< Bits in a word + APINT_WORD_SIZE = sizeof(uint64_t) ///< Byte size of a word + }; + + enum { excess_bits = (_AP_W%APINT_BITS_PER_WORD) ? APINT_BITS_PER_WORD -(_AP_W%APINT_BITS_PER_WORD) : 0}; + static const uint64_t mask = ((uint64_t)~0ULL >> (excess_bits)); + + /// This constructor is used only internally for speed of construction of + /// temporaries. It is unsafe for general use so it is not public. + /* Constructors */ + + ap_private(const char* val) { + std::string str(val); + uint32_t strLen = str.length(); + const char *strp = str.c_str(); + uint32_t offset = 0; + uint32_t base = 0; + bool neg = false; + uint32_t radix = 16; + ap_parse_sign(strp, base, neg); + ap_parse_prefix(strp + base, offset, radix); + + if ((radix != 10 && neg) || + (strLen - base - offset <= 0) || + InvalidDigit(strp, strLen, base + offset, radix)) { + fprintf(stderr, "invalid character string %s !\n", val); + assert(0); + } + + ap_private ap_private_val(str.c_str(), strLen, radix, base, offset); + if (neg) + ap_private_val = -ap_private_val; + operator = (ap_private_val); + report(); + } + + ap_private(const char* val, int rd) { + std::string str(val); + uint32_t strLen = str.length(); + const char *strp = str.c_str(); + uint32_t offset = 0; + uint32_t base = 0; + uint32_t radix = rd; + bool neg = false; + ap_parse_sign(strp, base, neg); + ap_parse_prefix(strp + base, offset, radix); + + if ((radix != 10 && neg) || + (strLen - base - offset <= 0) || + InvalidDigit(strp, strLen, base + offset, radix)) { + fprintf(stderr, "invalid character string %s !\n", val); + assert(0); + } + + // uint32_t bitsNeeded = ap_private<_AP_W, _AP_S>::getBitsNeeded(strp, strLen, radix); + // ap_private<_AP_W, _AP_S> ap_private_val(bitsNeeded, strp , strLen, radix, base, offset); + ap_private ap_private_val(strp , strLen, radix, base, offset); + if (neg) + ap_private_val = -ap_private_val; + operator = (ap_private_val); + report(); + } + + /// Note that numWords can be smaller or larger than the corresponding bit + /// width but any extraneous bits will be dropped. + /// @param numBits the bit width of the constructed ap_private + /// @param numWords the number of words in bigVal + /// @param bigVal a sequence of words to form the initial value of the ap_private + /// @brief Construct an ap_private of numBits width, initialized as bigVal[]. + ap_private(uint32_t numWords, const uint64_t bigVal[]): VAL(0) { + assert(bigVal && "Null pointer detected!"); + { + // Get memory, cleared to 0 + memset(pVal, 0, _AP_N * sizeof(uint64_t)); + + // Calculate the number of words to copy + uint32_t words = AESL_std::min(numWords, _AP_N); + // Copy the words from bigVal to pVal + memcpy(pVal, bigVal, words * APINT_WORD_SIZE); + if (words >= _AP_W) + clearUnusedBits(); + // Make sure unused high bits are cleared + } + } + + /// This constructor interprets Val as a string in the given radix. The + /// interpretation stops when the first charater that is not suitable for the + /// radix is encountered. Acceptable radix values are 2, 8, 10 and 16. It is + /// an error for the value implied by the string to require more bits than + /// numBits. + /// @param numBits the bit width of the constructed ap_private + /// @param val the string to be interpreted + /// @param radix the radix of Val to use for the intepretation + /// @brief Construct an ap_private from a string representation. + ap_private(const std::string& val, uint8_t radix=2, int base=0, int offset=0): VAL(0) { + assert(!val.empty() && "The input string is empty."); + const char *c_str = val.c_str(); + fromString(c_str+base+offset, val.size()-base-offset, radix); + } + + /// This constructor interprets the slen characters starting at StrStart as + /// a string in the given radix. The interpretation stops when the first + /// character that is not suitable for the radix is encountered. Acceptable + /// radix values are 2, 8, 10 and 16. It is an error for the value implied by + /// the string to require more bits than numBits. + /// @param numBits the bit width of the constructed ap_private + /// @param strStart the start of the string to be interpreted + /// @param slen the maximum number of characters to interpret + /// @param radix the radix to use for the conversion + /// @brief Construct an ap_private from a string representation. + /// This method does not consider whether it is negative or not. + ap_private(const char strStart[], uint32_t slen, uint8_t radix, int base=0, int offset=0) : VAL(0) { + fromString(strStart+base+offset, slen-base-offset, radix); + } + + template + INLINE ap_private(const ap_range_ref<_AP_W2,_AP_S2>& ref) { + *this=ref.get(); + report(); + } + + template + INLINE ap_private(const ap_bit_ref<_AP_W2,_AP_S2>& ref) { + *this = ((uint64_t)(bool)ref); + report(); + } + + template + INLINE ap_private(const ap_concat_ref<_AP_W2, _AP_T2,_AP_W3, _AP_T3>& ref) { + *this=ref.get(); + report(); + } + + template + INLINE ap_private(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2> &val) { + *this = ((val.operator ap_private<_AP_W2, false> ())); + report(); + } + + template + INLINE ap_private(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2> &val) { + *this = (uint64_t)(bool)val; + report(); + } + + /// Simply makes *this a copy of that. + /// @brief Copy Constructor. + template + ap_private(const volatile ap_private<_AP_W1, _AP_S1, _AP_N1>& that): VAL(0) { + operator = (const_cast& >(that)); + } + + template + ap_private(const ap_private<_AP_W1, _AP_S1, _AP_N1>& that): VAL(0) { + operator = (that); + } + + template + explicit ap_private(const ap_private<_AP_W1, _AP_S1, 1>& that): VAL(0) { + static const uint64_t that_sign_ext_mask = (_AP_W1==APINT_BITS_PER_WORD)?0:~0ULL>>(_AP_W1%APINT_BITS_PER_WORD)<<(_AP_W1%APINT_BITS_PER_WORD); + if (that.isNegative()) { + pVal[0] = that.VAL|that_sign_ext_mask; + memset(pVal+1, ~0, sizeof(uint64_t)*(_AP_N-1)); + } else { + pVal[0] = that.VAL; + memset(pVal+1, 0, sizeof(uint64_t)*(_AP_N-1)); + } + clearUnusedBits(); + } + + ap_private(const ap_private& that): VAL(0) { + memcpy(pVal, that.pVal, _AP_N * APINT_WORD_SIZE); + clearUnusedBits(); + } + + /// @brief Destructor. + virtual ~ap_private() {} + + /// Default constructor that creates an uninitialized ap_private. This is useful + /// for object deserialization (pair this with the static method Read). + ap_private(){memset(pVal, 0, sizeof(uint64_t)*(_AP_N));} + + ap_private(uint64_t* val, uint32_t bits=_AP_W) {assert(0);} + ap_private(const uint64_t *const val, uint32_t bits) {assert(0);} + + /// @name Constructors + /// @{ + /// If isSigned is true then val is treated as if it were a signed value + /// (i.e. as an int64_t) and the appropriate sign extension to the bit width + /// will be done. Otherwise, no sign extension occurs (high order bits beyond + /// the range of val are zero filled). + /// @param numBits the bit width of the constructed ap_private + /// @param val the initial value of the ap_private + /// @param isSigned how to treat signedness of val + /// @brief Create a new ap_private of numBits width, initialized as val. +#define CTOR(TYPE, SIGNED) \ + ap_private(TYPE val, bool isSigned=SIGNED) { \ + pVal[0] = val; \ + if (isSigned && int64_t(pVal[0]) < 0) { \ + memset(pVal+1, ~0, sizeof(uint64_t)*(_AP_N-1)); \ + } else { \ + memset(pVal+1, 0, sizeof(uint64_t)*(_AP_N-1)); \ + } \ + clearUnusedBits(); \ + } +#if 1 + CTOR(int, true) + CTOR(bool, false) + CTOR(signed char, true) + CTOR(unsigned char, false) + CTOR(short, true) + CTOR(unsigned short, false) + CTOR(unsigned int, false) + CTOR(long, true) + CTOR(unsigned long, false) + CTOR(unsigned long long, false) + CTOR(long long, true) + CTOR(float, false) + CTOR(double, false) +#undef CTOR +#else + CTOR(uint64_t) +#undef CTOR +#endif + + + /// @returns true if the number of bits <= 64, false otherwise. + /// @brief Determine if this ap_private just has one word to store value. + INLINE bool isSingleWord() const { + return false; + } + + /// @returns the word position for the specified bit position. + /// @brief Determine which word a bit is in. + static uint32_t whichWord(uint32_t bitPosition) { + // return bitPosition / APINT_BITS_PER_WORD; + return (bitPosition) >> 6; + } + + /// @returns the bit position in a word for the specified bit position + /// in the ap_private. + /// @brief Determine which bit in a word a bit is in. + static uint32_t whichBit(uint32_t bitPosition) { + // return bitPosition % APINT_BITS_PER_WORD; + return bitPosition & 0x3f; + } + + /// bit at a specific bit position. This is used to mask the bit in the + /// corresponding word. + /// @returns a uint64_t with only bit at "whichBit(bitPosition)" set + /// @brief Get a single bit mask. + static uint64_t maskBit(uint32_t bitPosition) { + return 1ULL << (whichBit(bitPosition)); + } + + /// @returns the corresponding word for the specified bit position. + /// @brief Get the word corresponding to a bit position + INLINE uint64_t getWord(uint32_t bitPosition) const { + return isSingleWord() ? VAL : pVal[whichWord(bitPosition)]; + } + + /// This method is used internally to clear the to "N" bits in the high order + /// word that are not used by the ap_private. This is needed after the most + /// significant word is assigned a value to ensure that those bits are + /// zero'd out. + /// @brief Clear unused high order bits + INLINE void clearUnusedBits(void) { + pVal[_AP_N-1] = _AP_S ? ((((int64_t)pVal[_AP_N-1])<<(excess_bits))>> excess_bits) : (excess_bits ? ((pVal[_AP_N-1])<<(excess_bits))>>(excess_bits) : pVal[_AP_N-1]); + } + + INLINE void clearUnusedBitsToZero(void) { + pVal[_AP_N-1] &= mask; + } + + INLINE void clearUnusedBitsToOne(void) { + pVal[_AP_N-1] |= mask; + } + + /// This is used by the constructors that take string arguments. + /// @brief Convert a char array into an ap_private + INLINE void fromString(const char *strStart, uint32_t slen, + uint8_t radix) ; + + INLINE ap_private read() volatile { + return *this; + } + + INLINE void write(const ap_private& op2) volatile { + *this = (op2); + } + + //Explicit conversions to C interger types + //----------------------------------------------------------- + operator ValType() const { + return getVal(); + } + + INLINE ValType getVal() const{ + return *pVal; + } + + INLINE int to_int() const { + return int(*this); + } + + INLINE unsigned to_uint() const { + return (unsigned) getVal(); + } + + INLINE long to_long() const { + return (long) getVal(); + } + + INLINE unsigned long to_ulong() const { + return (unsigned long) getVal(); + } + + INLINE ap_slong to_int64() const { + return (ap_slong) getVal(); + } + + INLINE ap_ulong to_uint64() const { + return (ap_ulong) getVal(); + } + + INLINE double to_double() const { + if (isNegative()) + return roundToDouble(true); + else + return roundToDouble(false); + } + + INLINE unsigned length() const { return _AP_W; } + + /*Reverse the contents of ap_private instance. I.e. LSB becomes MSB and vise versa*/ + INLINE ap_private& reverse () { + for (int i = 0; i < _AP_W/2; ++i) { + bool tmp = operator[](i); + if (operator[](_AP_W - 1 - i)) + set(i); + else + clear(i); + if (tmp) + set(_AP_W - 1 - i); + else + clear(_AP_W - 1 - i); + } + clearUnusedBits(); + return *this; + } + + /*Return true if the value of ap_private instance is zero*/ + INLINE bool iszero () const { + return isMinValue(); + } + + /* x < 0 */ + INLINE bool sign () const { + if (isNegative()) + return true; + return false; + } + + /* x[i] = !x[i] */ + INLINE void invert (int i) { + assert( i >= 0 && "Attempting to read bit with negative index"); + assert( i < _AP_W && "Attempting to read bit beyond MSB"); + flip(i); + } + + /* x[i] */ + INLINE bool test (int i) const { + assert( i >= 0 && "Attempting to read bit with negative index"); + assert( i < _AP_W && "Attempting to read bit beyond MSB"); + return operator[](i); + } + + //Set the ith bit into v + INLINE void set (int i, bool v) { + assert( i >= 0 && "Attempting to write bit with negative index"); + assert( i < _AP_W && "Attempting to write bit beyond MSB"); + v ? set(i) : clear(i); + } + + //Set the ith bit into v + INLINE void set_bit (int i, bool v) { + assert( i >= 0 && "Attempting to write bit with negative index"); + assert( i < _AP_W && "Attempting to write bit beyond MSB"); + v ? set(i) : clear(i); + } + + INLINE ap_private& set(uint32_t bitPosition) { + pVal[whichWord(bitPosition)] |= maskBit(bitPosition); + clearUnusedBits(); + return *this; + } + + INLINE void set() { + for (uint32_t i = 0; i < _AP_N; ++i) + pVal[i] = ~0ULL; + clearUnusedBits(); + } + + //Get the value of ith bit + INLINE bool get (int i) const { + assert( i >= 0 && "Attempting to read bit with negative index"); + assert( i < _AP_W && "Attempting to read bit beyond MSB"); + return operator [](i); + } + + //Get the value of ith bit + INLINE bool get_bit (int i) const { + assert( i >= 0 && "Attempting to read bit with negative index"); + assert( i < _AP_W && "Attempting to read bit beyond MSB"); + return operator [](i); + } + + //This is used for sc_lv and sc_bv, which is implemented by sc_uint + //Rotate an ap_private object n places to the left + INLINE void lrotate(int n) { + assert( n >= 0 && "Attempting to shift negative index"); + assert( n < _AP_W && "Shift value larger than bit width"); + operator = (shl(n) | lshr(_AP_W - n)); + } + + //This is used for sc_lv and sc_bv, which is implemented by sc_uint + //Rotate an ap_private object n places to the right + INLINE void rrotate(int n) { + assert( n >= 0 && "Attempting to shift negative index"); + assert( n < _AP_W && "Shift value larger than bit width"); + operator = (lshr(n) | shl(_AP_W - n)); + } + + /// Set the given bit to 0 whose position is given as "bitPosition". + /// @brief Set a given bit to 0. + ap_private& clear(uint32_t bitPosition) { + pVal[whichWord(bitPosition)] &= ~maskBit(bitPosition); + clearUnusedBits(); + return *this; + } + + /// @brief Set every bit to 0. + void clear() { + memset(pVal, 0, _AP_N * APINT_WORD_SIZE); + } + + /// @brief Toggle every bit to its opposite value. + ap_private& flip() { + for (uint32_t i = 0; i < _AP_N; ++i) + pVal[i] ^= ~0ULL; + clearUnusedBits(); + return *this; + } + + /// Toggle a given bit to its opposite value whose position is given + /// as "bitPosition". + /// @brief Toggles a given bit to its opposite value. + ap_private& flip(uint32_t bitPosition) { + assert(bitPosition < BitWidth && "Out of the bit-width range!"); + if ((*this)[bitPosition]) clear(bitPosition); + else set(bitPosition); + return *this; + } + + //complements every bit + INLINE void b_not() { + flip(); + } + + ap_private getLoBits(uint32_t numBits) const { + return ap_private_ops::lshr(ap_private_ops::shl(*this, _AP_W - numBits), + _AP_W - numBits); + } + + ap_private getHiBits(uint32_t numBits) const { + return ap_private_ops::lshr(*this, _AP_W - numBits); + } + + //Binary Arithmetic + //----------------------------------------------------------- + + template + INLINE ap_private + operator & (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) { + return *this & a2.get(); + } + + template + INLINE ap_private + operator | (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) { + return *this | a2.get(); + } + + template + INLINE ap_private + operator ^ (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) { + return *this ^ a2.get(); + } + + + ///Arithmetic assign + //------------------------------------------------------------- + +#define OP_BIN_LOGIC_ASSIGN_AP(Sym) \ + template \ + INLINE ap_private& operator Sym(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { \ + uint32_t numWords = AESL_std::min(_AP_N, _AP_N1); \ + uint32_t i; \ + for (i = 0; i < numWords; ++i) \ + pVal[i] Sym RHS.pVal[i]; \ + if (_AP_N1 < _AP_N) { \ + uint64_t ext = RHS.isNegative()?~0ULL:0; \ + for (;i<_AP_N; i++) \ + pVal[i] Sym ext; \ + } \ + clearUnusedBits(); \ + return *this; \ + } + + OP_BIN_LOGIC_ASSIGN_AP(&=); + OP_BIN_LOGIC_ASSIGN_AP(|=); + OP_BIN_LOGIC_ASSIGN_AP(^=); +#undef OP_BIN_LOGIC_ASSIGN_AP + + /// Adds the RHS APint to this ap_private. + /// @returns this, after addition of RHS. + /// @brief Addition assignment operator. + template + INLINE ap_private& operator+=(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { + add(pVal, pVal, RHS.pVal, _AP_N, _AP_N, _AP_N1, _AP_S, _AP_S1); + clearUnusedBits(); + return *this; + } + + template + INLINE ap_private& operator-=(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { + sub(pVal, pVal, RHS.pVal, _AP_N, _AP_N, _AP_N1, _AP_S, _AP_S1); + clearUnusedBits(); + return *this; + } + + template + ap_private& operator*=(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { + // Get some bit facts about LHS and check for zero + uint32_t lhsBits = getActiveBits(); + uint32_t lhsWords = !lhsBits ? 0 : whichWord(lhsBits - 1) + 1; + if (!lhsWords) { + // 0 * X ===> 0 + return *this; + } + + ap_private dupRHS = RHS; + // Get some bit facts about RHS and check for zero + uint32_t rhsBits = dupRHS.getActiveBits(); + uint32_t rhsWords = !rhsBits ? 0 : whichWord(rhsBits - 1) + 1; + if (!rhsWords) { + // X * 0 ===> 0 + clear(); + return *this; + } + + // Allocate space for the result + uint32_t destWords = rhsWords + lhsWords; + uint64_t *dest = getMemory(destWords); + + // Perform the long multiply + mul(dest, pVal, lhsWords, dupRHS.pVal, rhsWords, destWords); + + // Copy result back into *this + clear(); + uint32_t wordsToCopy = destWords >= _AP_N ? _AP_N : destWords; + + memcpy(pVal, dest, wordsToCopy* APINT_WORD_SIZE); + + uint64_t ext = (isNegative() ^ RHS.isNegative()) ? ~0ULL : 0ULL; + for (int i=wordsToCopy; i<_AP_N; i++) + pVal[i]=ext; + clearUnusedBits(); + // delete dest array and return + free(dest); + return *this; + } + +#define OP_ASSIGN_AP(Sym) \ + template \ + INLINE ap_private& operator Sym##=(const ap_private<_AP_W2,_AP_S2>& op) \ + { \ + *this=operator Sym (op); \ + return *this; \ + } \ + + OP_ASSIGN_AP(/) + OP_ASSIGN_AP(%) +#undef OP_ASSIGN_AP + +#define OP_BIN_LOGIC_AP(Sym) \ + template \ + INLINE \ + typename RType<_AP_W1, _AP_S1>::logic \ + operator Sym (const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) const { \ + enum { numWords = (RType<_AP_W1, _AP_S1>::logic_w +APINT_BITS_PER_WORD-1)/APINT_BITS_PER_WORD}; \ + typename RType<_AP_W1, _AP_S1>::logic Result; \ + uint64_t *val = Result.pVal; \ + uint32_t i; \ + uint32_t min_N = std::min(_AP_N, _AP_N1); \ + uint32_t max_N = std::max(_AP_N, _AP_N1); \ + for (i = 0; i < min_N; ++i) \ + val[i] = pVal[i] Sym RHS.pVal[i]; \ + if (numWords > i) { \ + const uint64_t* tmpVal = (_AP_N>_AP_N1 ? pVal : RHS.pVal)+i; \ + uint64_t ext = ((_AP_N<_AP_N1 && isNegative() )||(_AP_N1 < _AP_N && RHS.isNegative())) ? ~0ULL : 0; \ + for (;i i) { \ + uint64_t ext2 = ((_AP_N>_AP_N1 && isNegative() )||(_AP_N1 > _AP_N && RHS.isNegative())) ? ~0ULL : 0; \ + val[i] = ext Sym ext2; \ + } \ + } \ + Result.clearUnusedBits(); \ + return Result; \ + } + + OP_BIN_LOGIC_AP(|); + OP_BIN_LOGIC_AP(&); + OP_BIN_LOGIC_AP(^); + +#undef OP_BIN_LOGIC_AP + + template + INLINE typename RType<_AP_W1,_AP_S1>::plus operator+(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) const { + // assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + typename RType<_AP_W1,_AP_S1>::plus Result; + bool carry = add(Result.pVal, this->pVal, RHS.pVal, (RType<_AP_W1,_AP_S1>::plus_w + 63) / 64, _AP_N, _AP_N1, _AP_S, _AP_S1); + if ((RType<_AP_W1,_AP_S1>::plus_w + 63) / 64> std::max(_AP_W, _AP_W1) ) + Result.pVal[(RType<_AP_W1,_AP_S1>::plus_w + 63)/64 - 1] = carry; + Result.clearUnusedBits(); + return Result; + } + + template + INLINE typename RType<_AP_W1,_AP_S1>::minus operator-(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) const { + typename RType<_AP_W1,_AP_S1>::minus Result; + bool borrow = sub(Result.pVal, this->pVal, RHS.pVal, (RType<_AP_W1,_AP_S1>::minus_w + 63) / 64, _AP_N, _AP_N1, _AP_S, _AP_S1); + if ((RType<_AP_W1,_AP_S1>::minus_w + 63) / 64 > AESL_std::max(_AP_W, _AP_W1) ) { + Result.pVal[(RType<_AP_W1,_AP_S1>::minus_w+63)/64 - 1] = borrow; + } + Result.clearUnusedBits(); + return Result; + } + + template + typename RType<_AP_W1, _AP_S1>::mult operator*(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) const { + + // Get some bit facts about LHS and check for zero + uint32_t lhsBits = getActiveBits(); + uint32_t lhsWords = !lhsBits ? 0 : whichWord(lhsBits - 1) + 1; + if (!lhsWords) + // 0 * X ===> 0 + return typename RType<_AP_W1, _AP_S1>::mult(); + + // Get some bit facts about RHS and check for zero + uint32_t rhsBits = RHS.getActiveBits(); + uint32_t rhsWords = !rhsBits ? 0 : whichWord(rhsBits - 1) + 1; + if (!rhsWords) { + // X * 0 ===> 0 + return typename RType<_AP_W1, _AP_S1>::mult(); + } + + //extend size to avoid result loss + typename RType<_AP_W1, _AP_S1>::mult dupLHS = *this; + typename RType<_AP_W1, _AP_S1>::mult dupRHS = RHS; + lhsBits = dupLHS.getActiveBits(); + lhsWords = !lhsBits ? 0 : whichWord(lhsBits - 1) + 1; + rhsBits = dupRHS.getActiveBits(); + rhsWords = !rhsBits ? 0 : whichWord(rhsBits - 1) + 1; + + // Allocate space for the result + enum { destWords =(RType<_AP_W1, _AP_S1>::mult_w+APINT_BITS_PER_WORD-1)/APINT_BITS_PER_WORD}; + int destw = destWords; + typename RType<_AP_W1, _AP_S1>::mult Result; + uint64_t *dest = Result.pVal; + uint64_t ext = (isNegative() ^ RHS.isNegative()) ? ~0ULL : 0; + + // Perform the long multiply + mul(dest, dupLHS.pVal, lhsWords, dupRHS.pVal, rhsWords, destWords); + + for (int i=lhsWords+rhsWords; i + INLINE typename RType<_AP_W2,_AP_S2>::div + operator / (const ap_private<_AP_W2,_AP_S2>& op) const { + ap_private lhs=ap_private(*this); + ap_private rhs=ap_private(op); + return typename RType<_AP_W2,_AP_S2>::div((_AP_S||_AP_S2)?lhs.sdiv(rhs):lhs.udiv(rhs)); + } + + template + INLINE typename RType<_AP_W2,_AP_S2>::mod + operator % (const ap_private<_AP_W2,_AP_S2>& op) const { + ap_private lhs=*this; + ap_private rhs= op; + typename RType<_AP_W2,_AP_S2>::mod res = typename RType<_AP_W2,_AP_S2>::mod(_AP_S?lhs.srem(rhs):lhs.urem(rhs)); + return res; + } + + template + INLINE ap_private + operator << (const ap_private<_AP_W2, _AP_S2>& op2) const { + uint32_t sh=op2.to_uint(); + return *this << sh; + } + + INLINE ap_private + operator << (uint32_t sh) const { + ap_private r(*this); + bool overflow=(sh>=length()); + if(overflow) + r.clear(); + else + r = ap_private(r.shl(sh)); + return r; + } + + template + INLINE ap_private + operator >> (const ap_private<_AP_W2, _AP_S2>& op2) const { + uint32_t sh = op2.to_uint(); + return *this >> sh; + } + + INLINE ap_private + operator >> (uint32_t sh) const { + ap_private r(*this); + bool overflow=(sh>=_AP_W); + bool neg_v=r.isNegative(); + if(_AP_S) { + if(overflow) + neg_v?r.set():r.clear(); + else + return r.ashr(sh); + } else { + if(overflow) + r.clear(); + else + return r.lshr(sh); + } + return r; + } + + ///Shift assign + //------------------------------------------------------------------ +#define OP_ASSIGN_AP(Sym) \ + template \ + INLINE ap_private& operator Sym##=(int op) \ + { \ + *this = operator Sym (op); \ + return *this; \ + } \ + INLINE ap_private& operator Sym##=(unsigned int op) \ + { \ + *this = operator Sym (op); \ + return *this; \ + } \ + template \ + INLINE ap_private& operator Sym##=(const ap_private<_AP_W2,_AP_S2>& op) \ + { \ + *this = operator Sym (op); \ + return *this; \ + } + OP_ASSIGN_AP(>>) + OP_ASSIGN_AP(<<) +#undef OP_ASSIGN_AP + ///Comparisons + //----------------------------------------------------------------- + bool operator==(const ap_private& RHS) const { + // Get some facts about the number of bits used in the two operands. + uint32_t n1 = getActiveBits(); + uint32_t n2 = RHS.getActiveBits(); + + // If the number of bits isn't the same, they aren't equal + if (n1 != n2) + return false; + + // If the number of bits fits in a word, we only need to compare the low word. + if (n1 <= APINT_BITS_PER_WORD) + return pVal[0] == RHS.pVal[0]; + + // Otherwise, compare everything + for (int i = whichWord(n1 - 1); i >= 0; --i) + if (pVal[i] != RHS.pVal[i]) + return false; + return true; + } + + template + INLINE bool operator == (const ap_private<_AP_W2, _AP_S2>& op) const { + enum { _AP_MAX_W = AP_MAX(_AP_W+(_AP_S||_AP_S2),_AP_W2+(_AP_S||_AP_S2))}; + ap_private<_AP_MAX_W, _AP_S|_AP_S2> lhs(*this); + ap_private<_AP_MAX_W, _AP_S|_AP_S2> rhs(op); + return lhs==rhs; + } + + bool operator==(uint64_t Val) const { + uint32_t n = getActiveBits(); + if (n <= APINT_BITS_PER_WORD) + return pVal[0] == Val; + else + return false; + } + + template + INLINE bool operator != (const ap_private<_AP_W2, _AP_S2>& op) const { + return !(*this==op); + } + + template + INLINE bool operator!=(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return !((*this) == RHS); + } + + INLINE bool operator!=(uint64_t Val) const { + return !((*this) == Val); + } + + + template + INLINE bool operator <= (const ap_private<_AP_W2,_AP_S2>& op) const { + return !(*this>op); + } + + INLINE bool operator <(const ap_private& op) const { + return _AP_S ? slt(op):ult(op); + } + + template + INLINE bool operator < (const ap_private<_AP_W2, _AP_S2>& op) const { + enum { _AP_MAX_W = AP_MAX(_AP_W+(_AP_S||_AP_S2),_AP_W2+(_AP_S||_AP_S2))}; + ap_private<_AP_MAX_W, _AP_S> lhs(*this); + ap_private<_AP_MAX_W, _AP_S2> rhs(op); + if (_AP_S == _AP_S2) + return _AP_S?lhs.slt(rhs):lhs.ult(rhs); + else + if (_AP_S) + if (_AP_W2 >= _AP_W) + return lhs.ult(rhs); + else + return lhs.slt(rhs); + else + if (_AP_W >= _AP_W2) + return lhs.ult(rhs); + else + return lhs.slt(rhs); + } + + template + INLINE bool operator >=(const ap_private<_AP_W2,_AP_S2>& op) const { + return !(*this + INLINE bool operator > (const ap_private<_AP_W2, _AP_S2>& op) const { + enum { _AP_MAX_W = AP_MAX(_AP_W+(_AP_S||_AP_S2),_AP_W2+(_AP_S||_AP_S2))}; + ap_private<_AP_MAX_W, _AP_S> lhs(*this); + ap_private<_AP_MAX_W, _AP_S2> rhs(op); + if (_AP_S == _AP_S2) + return _AP_S?lhs.sgt(rhs):lhs.ugt(rhs); + else + if (_AP_S) + if (_AP_W2 >= _AP_W) + return lhs.ugt(rhs); + else + return lhs.sgt(rhs); + else + if (_AP_W >= _AP_W2) + return lhs.ugt(rhs); + else + return lhs.sgt(rhs); + } + + ///Bit and Part Select + //-------------------------------------------------------------- + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (int Hi, int Lo) { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (int Hi, int Lo) const { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(const_cast*>(this), Hi, Lo); + } + + INLINE ap_range_ref<_AP_W,_AP_S> + range (int Hi, int Lo) const { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>((const_cast*> (this)), Hi, Lo); + } + + INLINE ap_range_ref<_AP_W,_AP_S> + range (int Hi, int Lo) { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + range (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + range (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) const { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(const_cast(this), Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) const { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + return this->range(Hi, Lo); + } + + INLINE ap_bit_ref<_AP_W,_AP_S> operator [] (uint32_t index) { + assert(index >= 0&&"Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S>( *this, index ); + } + + template + INLINE ap_bit_ref<_AP_W,_AP_S> operator [] (const ap_private<_AP_W2,_AP_S2> &index) { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S>( *this, index.to_int() ); + } + + template + INLINE bool operator [] (const ap_private<_AP_W2,_AP_S2>& index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + ap_bit_ref<_AP_W,_AP_S> br =operator [] (index); + return br.to_bool(); + } + + INLINE bool operator [](uint32_t bitPosition) const { + return (maskBit(bitPosition) & (pVal[whichWord(bitPosition)])) != 0; + } + + INLINE ap_bit_ref<_AP_W,_AP_S> bit (int index) { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S>( *this, index ); + } + + template + INLINE ap_bit_ref<_AP_W,_AP_S> bit (const ap_private<_AP_W2,_AP_S2> &index) { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W &&"Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S>( *this, index.to_int() ); + } + + INLINE bool bit (int index) const { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + ap_bit_ref<_AP_W,_AP_S> br(const_cast*>(this), index); + return br.to_bool(); + } + + template + INLINE bool bit (const ap_private<_AP_W2,_AP_S2>& index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + ap_bit_ref<_AP_W,_AP_S> br = bit(index); + return br.to_bool(); + } + + template + INLINE ap_concat_ref<_AP_W,ap_private<_AP_W, _AP_S>,_AP_W2,ap_private<_AP_W2,_AP_S2> > concat(ap_private<_AP_W2,_AP_S2>& a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_private<_AP_W2,_AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W,ap_private<_AP_W, _AP_S>,_AP_W2,ap_private<_AP_W2,_AP_S2> > concat(const ap_private<_AP_W2,_AP_S2>& a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_private<_AP_W2,_AP_S2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (ap_private<_AP_W2, _AP_S2>& a2) { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (ap_private<_AP_W2, _AP_S2>& a2) const { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(const_cast& >(*this), a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (const ap_private<_AP_W2, _AP_S2>& a2) { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(*this, const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (const ap_private<_AP_W2, _AP_S2>& a2) const { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(const_cast& >(*this), const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > + operator, (const ap_range_ref<_AP_W2, _AP_S2> &a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, + ap_range_ref<_AP_W2, _AP_S2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > + operator, (ap_range_ref<_AP_W2, _AP_S2> &a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, + ap_range_ref<_AP_W2, _AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, ap_bit_ref<_AP_W2, _AP_S2> > + operator, (const ap_bit_ref<_AP_W2, _AP_S2> &a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, + ap_bit_ref<_AP_W2, _AP_S2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, ap_bit_ref<_AP_W2, _AP_S2> > + operator, (ap_bit_ref<_AP_W2, _AP_S2> &a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, + ap_bit_ref<_AP_W2, _AP_S2> >(*this, a2); + } + + template + INLINE + ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > + operator, (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE + ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > + operator, (ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) const { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) const { + return ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, a2); + } + + INLINE ap_private<_AP_W,false> get() const { + ap_private<_AP_W,false> ret(*this); + return ret; + } + + template + INLINE void set(const ap_private<_AP_W3, false> & val) { + operator = (ap_private<_AP_W3, _AP_S>(val)); + } + + /// @} + /// @name Value Tests + /// @{ + /// This tests the high bit of this ap_private to determine if it is set. + /// @returns true if this ap_private is negative, false otherwise + /// @brief Determine sign of this ap_private. + INLINE bool isNegative() const { + //just for get rid of warnings + enum {shift = (_AP_W-APINT_BITS_PER_WORD*(_AP_N-1)-1)}; + static const uint64_t mask = 1ULL << (shift); + return _AP_S && (pVal[_AP_N-1]&mask); + } + + /// This tests the high bit of the ap_private to determine if it is unset. + /// @brief Determine if this ap_private Value is positive (not negative). + INLINE bool isPositive() const { + return !isNegative(); + } + + /// This tests if the value of this ap_private is strictly positive (> 0). + /// @returns true if this ap_private is Positive and not zero. + /// @brief Determine if this ap_private Value is strictly positive. + INLINE bool isStrictlyPositive() const { + return isPositive() && (*this) != 0; + } + + /// This checks to see if the value has all bits of the ap_private are set or not. + /// @brief Determine if all bits are set + INLINE bool isAllOnesValue() const { + return countPopulation() == _AP_W; + } + + /// This checks to see if the value of this ap_private is the maximum unsigned + /// value for the ap_private's bit width. + /// @brief Determine if this is the largest unsigned value. + INLINE bool isMaxValue() const { + return countPopulation() == _AP_W; + } + + /// This checks to see if the value of this ap_private is the maximum signed + /// value for the ap_private's bit width. + /// @brief Determine if this is the largest signed value. + INLINE bool isMaxSignedValue() const { + return BitWidth == 1 ? VAL == 0 : + !isNegative() && countPopulation() == _AP_W - 1; + } + + /// This checks to see if the value of this ap_private is the minimum unsigned + /// value for the ap_private's bit width. + /// @brief Determine if this is the smallest unsigned value. + INLINE bool isMinValue() const { + return countPopulation() == 0; + } + + /// This checks to see if the value of this ap_private is the minimum signed + /// value for the ap_private's bit width. + /// @brief Determine if this is the smallest signed value. + INLINE bool isMinSignedValue() const { + return BitWidth == 1 ? VAL == 1 : + isNegative() && countPopulation() == 1; + } + + /// This function returns a pointer to the internal storage of the ap_private. + /// This is useful for writing out the ap_private in binary form without any + /// conversions. + INLINE const uint64_t* getRawData() const { + if (isSingleWord()) + return &VAL; + return &pVal[0]; + } + + ap_private sqrt() const; + + /// @} + /// @Assignment Operators + /// @{ + /// @returns *this after assignment of RHS. + /// @brief Copy assignment operator. + INLINE ap_private& operator=(const ap_private& RHS) { + if (this != &RHS) + memcpy(pVal, RHS.pVal, _AP_N * APINT_WORD_SIZE); + return *this; + } + INLINE ap_private& operator=(const volatile ap_private& RHS) { + if (this != &RHS) + for (int i=0; i<_AP_N; ++i) + pVal[i] = RHS.pVal[i]; + return *this; + } + INLINE volatile ap_private& operator=(const ap_private& RHS) volatile { + if (this != &RHS) + for (int i=0; i<_AP_N; ++i) + pVal[i] = RHS.pVal[i]; + return *this; + } + INLINE volatile ap_private& operator=(const volatile ap_private& RHS) volatile { + if (this != &RHS) + for (int i=0; i<_AP_N; ++i) + pVal[i] = RHS.pVal[i]; + return *this; + } + + template + INLINE ap_private& operator=(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { + if (_AP_S1) + cpSextOrTrunc(RHS); + else + cpZextOrTrunc(RHS); + clearUnusedBits(); + return *this; + } + + template + INLINE ap_private& operator=(const volatile ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { + if (_AP_S1) + cpSextOrTrunc(RHS); + else + cpZextOrTrunc(RHS); + clearUnusedBits(); + return *this; + } + + template + INLINE ap_private& operator=(const ap_private<_AP_W1, _AP_S1, 1>& RHS) { + static const uint64_t that_sign_ext_mask = (_AP_W1==APINT_BITS_PER_WORD)?0:~0ULL>>(_AP_W1%APINT_BITS_PER_WORD)<<(_AP_W1%APINT_BITS_PER_WORD); + if (RHS.isNegative()) { + pVal[0] = RHS.VAL | that_sign_ext_mask; + memset(pVal+1,~0, APINT_WORD_SIZE*(_AP_N-1)); + } else { + pVal[0] = RHS.VAL; + memset(pVal+1, 0, APINT_WORD_SIZE*(_AP_N-1)); + } + clearUnusedBits(); + return *this; + } + + template + INLINE ap_private& operator=(const volatile ap_private<_AP_W1, _AP_S1, 1>& RHS) { + static const uint64_t that_sign_ext_mask = (_AP_W1==APINT_BITS_PER_WORD)?0:~0ULL>>(_AP_W1%APINT_BITS_PER_WORD)<<(_AP_W1%APINT_BITS_PER_WORD); + if (RHS.isNegative()) { + pVal[0] = RHS.VAL | that_sign_ext_mask; + memset(pVal+1,~0, APINT_WORD_SIZE*(_AP_N-1)); + } else { + pVal[0] = RHS.VAL; + memset(pVal+1, 0, APINT_WORD_SIZE*(_AP_N-1)); + } + clearUnusedBits(); + return *this; + } + + /// @} + /// @name Unary Operators + /// @{ + /// @returns a new ap_private value representing *this incremented by one + /// @brief Postfix increment operator. + INLINE const ap_private operator++(int) { + ap_private API(*this); + ++(*this); + return API; + } + + /// @returns *this incremented by one + /// @brief Prefix increment operator. + INLINE ap_private& operator++() { + add_1(pVal, pVal, _AP_N, 1); + clearUnusedBits(); + return *this; + } + + /// @returns a new ap_private representing *this decremented by one. + /// @brief Postfix decrement operator. + INLINE const ap_private operator--(int) { + ap_private API(*this); + --(*this); + return API; + } + + /// @returns *this decremented by one. + /// @brief Prefix decrement operator. + INLINE ap_private& operator--() { + sub_1(pVal, _AP_N, 1); + clearUnusedBits(); + return *this; + } + + /// Performs a bitwise complement operation on this ap_private. + /// @returns an ap_private that is the bitwise complement of *this + /// @brief Unary bitwise complement operator. + INLINE ap_private operator~() const { + ap_private Result(*this); + Result.flip(); + return Result; + } + + /// Negates *this using two's complement logic. + /// @returns An ap_private value representing the negation of *this. + /// @brief Unary negation operator + INLINE typename RType<1,false>::minus operator-() const { + return ap_private<1,false>(0) - (*this); + } + + /// Performs logical negation operation on this ap_private. + /// @returns true if *this is zero, false otherwise. + /// @brief Logical negation operator. + INLINE bool operator !() const { + for (uint32_t i = 0; i < _AP_N; ++i) + if (pVal[i]) + return false; + return true; + } + + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> And(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return this->operator&(RHS); + } + template + INLINE ap_private Or(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return this->operator|(RHS); + } + template + ap_private Xor(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return this->operator^(RHS); + } + + ap_private Mul(const ap_private& RHS) const { + ap_private Result(*this); + Result *= RHS; + return Result; + } + + ap_private Add(const ap_private& RHS) const { + ap_private Result(0); + bool carry = add(Result.pVal, this->pVal, RHS.pVal, _AP_N, _AP_N, _AP_N, _AP_S, _AP_S); + Result.clearUnusedBits(); + return Result; + } + + ap_private Sub(const ap_private& RHS) const { + ap_private Result(0); + sub(Result.pVal, this->pVal, RHS.pVal, _AP_N, _AP_N, _AP_N, _AP_S, _AP_S); + Result.clearUnusedBits(); + return Result; + } + + /// Arithmetic right-shift this ap_private by shiftAmt. + /// @brief Arithmetic right-shift function. + ap_private ashr(uint32_t shiftAmt) const { + assert(shiftAmt <= BitWidth && "Invalid shift amount, too big"); + // Handle a degenerate case + if (shiftAmt == 0) + return *this; + + // Handle single word shifts with built-in ashr + if (isSingleWord()) { + if (shiftAmt == BitWidth) + return ap_private(/*BitWidth, 0*/); // undefined + else { + uint32_t SignBit = APINT_BITS_PER_WORD - BitWidth; + return ap_private(/*BitWidth,*/ + (((int64_t(VAL) << (SignBit)) >> (SignBit)) >> (shiftAmt))); + } + } + + // If all the bits were shifted out, the result is, technically, undefined. + // We return -1 if it was negative, 0 otherwise. We check this early to avoid + // issues in the algorithm below. + if (shiftAmt == BitWidth) { + if (isNegative()) + return ap_private(-1); + else + return ap_private(0); + } + + // Create some space for the result. + ap_private Retval(0); + uint64_t * val = Retval.pVal; + + // Compute some values needed by the following shift algorithms + uint32_t wordShift = shiftAmt % APINT_BITS_PER_WORD; // bits to shift per word + uint32_t offset = shiftAmt / APINT_BITS_PER_WORD; // word offset for shift + uint32_t breakWord = _AP_N - 1 - offset; // last word affected + uint32_t bitsInWord = whichBit(BitWidth); // how many bits in last word? + if (bitsInWord == 0) + bitsInWord = APINT_BITS_PER_WORD; + + // If we are shifting whole words, just move whole words + if (wordShift == 0) { + // Move the words containing significant bits + for (uint32_t i = 0; i <= breakWord; ++i) + val[i] = pVal[i+offset]; // move whole word + + // Adjust the top significant word for sign bit fill, if negative + if (isNegative()) + if (bitsInWord < APINT_BITS_PER_WORD) + val[breakWord] |= ~0ULL << (bitsInWord); // set high bits + } else { + // Shift the low order words + for (uint32_t i = 0; i < breakWord; ++i) { + // This combines the shifted corresponding word with the low bits from + // the next word (shifted into this word's high bits). + val[i] = ((pVal[i+offset]) >> (wordShift)); + val[i] |= ((pVal[i+offset+1]) << (APINT_BITS_PER_WORD - wordShift)); + } + + // Shift the break word. In this case there are no bits from the next word + // to include in this word. + val[breakWord] = (pVal[breakWord+offset]) >> (wordShift); + + // Deal with sign extenstion in the break word, and possibly the word before + // it. + if (isNegative()) { + if (wordShift > bitsInWord) { + if (breakWord > 0) + val[breakWord-1] |= + ~0ULL << (APINT_BITS_PER_WORD - (wordShift - bitsInWord)); + val[breakWord] |= ~0ULL; + } else + val[breakWord] |= (~0ULL << (bitsInWord - wordShift)); + } + } + + // Remaining words are 0 or -1, just assign them. + uint64_t fillValue = (isNegative() ? ~0ULL : 0); + for (uint32_t i = breakWord+1; i < _AP_N; ++i) + val[i] = fillValue; + Retval.clearUnusedBits(); + return Retval; + } + + /// Logical right-shift this ap_private by shiftAmt. + /// @brief Logical right-shift function. + ap_private lshr(uint32_t shiftAmt) const { + if (isSingleWord()) { + if (shiftAmt == BitWidth) + return ap_private(0); + else + return ap_private((this->VAL) >> (shiftAmt)); + } + + // If all the bits were shifted out, the result is 0. This avoids issues + // with shifting by the size of the integer type, which produces undefined + // results. We define these "undefined results" to always be 0. + if (shiftAmt == BitWidth) + return ap_private(0); + + // If none of the bits are shifted out, the result is *this. This avoids + // issues with shifting byt he size of the integer type, which produces + // undefined results in the code below. This is also an optimization. + if (shiftAmt == 0) + return *this; + + // Create some space for the result. + ap_private Retval(0); + uint64_t * val = Retval.pVal; + + // If we are shifting less than a word, compute the shift with a simple carry + if (shiftAmt < APINT_BITS_PER_WORD) { + uint64_t carry = 0; + for (int i = _AP_N-1; i >= 0; --i) { + val[i] = ((pVal[i]) >> (shiftAmt)) | carry; + carry = (pVal[i]) << (APINT_BITS_PER_WORD - shiftAmt); + } + Retval.clearUnusedBits(); + return Retval; + } + + // Compute some values needed by the remaining shift algorithms + uint32_t wordShift = shiftAmt % APINT_BITS_PER_WORD; + uint32_t offset = shiftAmt / APINT_BITS_PER_WORD; + + // If we are shifting whole words, just move whole words + if (wordShift == 0) { + for (uint32_t i = 0; i < _AP_N - offset; ++i) + val[i] = pVal[i+offset]; + for (uint32_t i = _AP_N-offset; i < _AP_N; i++) + val[i] = 0; + Retval.clearUnusedBits(); + return Retval; + } + + // Shift the low order words + uint32_t breakWord = _AP_N - offset -1; + for (uint32_t i = 0; i < breakWord; ++i) + val[i] = ((pVal[i+offset]) >> (wordShift)) | + ((pVal[i+offset+1]) << (APINT_BITS_PER_WORD - wordShift)); + // Shift the break word. + val[breakWord] = (pVal[breakWord+offset]) >> (wordShift); + + // Remaining words are 0 + for (uint32_t i = breakWord+1; i < _AP_N; ++i) + val[i] = 0; + Retval.clearUnusedBits(); + return Retval; + } + + /// Left-shift this ap_private by shiftAmt. + /// @brief Left-shift function. + ap_private shl(uint32_t shiftAmt) const { + assert(shiftAmt <= BitWidth && "Invalid shift amount, too big"); + if (isSingleWord()) { + if (shiftAmt == BitWidth) + return ap_private(0); // avoid undefined shift results + return ap_private((VAL) << (shiftAmt)); + } + + // If all the bits were shifted out, the result is 0. This avoids issues + // with shifting by the size of the integer type, which produces undefined + // results. We define these "undefined results" to always be 0. + if (shiftAmt == BitWidth) + return ap_private(0); + + // If none of the bits are shifted out, the result is *this. This avoids a + // lshr by the words size in the loop below which can produce incorrect + // results. It also avoids the expensive computation below for a common case. + if (shiftAmt == 0) + return *this; + + // Create some space for the result. + ap_private Retval(0); + uint64_t* val = Retval.pVal; + // If we are shifting less than a word, do it the easy way + if (shiftAmt < APINT_BITS_PER_WORD) { + uint64_t carry = 0; + for (uint32_t i = 0; i < _AP_N; i++) { + val[i] = ((pVal[i]) << (shiftAmt)) | carry; + carry = (pVal[i]) >> (APINT_BITS_PER_WORD - shiftAmt); + } + Retval.clearUnusedBits(); + return Retval; + } + + // Compute some values needed by the remaining shift algorithms + uint32_t wordShift = shiftAmt % APINT_BITS_PER_WORD; + uint32_t offset = shiftAmt / APINT_BITS_PER_WORD; + + // If we are shifting whole words, just move whole words + if (wordShift == 0) { + for (uint32_t i = 0; i < offset; i++) + val[i] = 0; + for (uint32_t i = offset; i < _AP_N; i++) + val[i] = pVal[i-offset]; + Retval.clearUnusedBits(); + return Retval; + } + + // Copy whole words from this to Result. + uint32_t i = _AP_N - 1; + for (; i > offset; --i) + val[i] = (pVal[i-offset]) << (wordShift) | + (pVal[i-offset-1]) >> (APINT_BITS_PER_WORD - wordShift); + val[offset] = (pVal[0]) << (wordShift); + for (i = 0; i < offset; ++i) + val[i] = 0; + Retval.clearUnusedBits(); + return Retval; + } + + INLINE ap_private rotl(uint32_t rotateAmt) const { + if (rotateAmt == 0) + return *this; + // Don't get too fancy, just use existing shift/or facilities + ap_private hi(*this); + ap_private lo(*this); + hi.shl(rotateAmt); + lo.lshr(BitWidth - rotateAmt); + return hi | lo; + } + + INLINE ap_private rotr(uint32_t rotateAmt) const { + if (rotateAmt == 0) + return *this; + // Don't get too fancy, just use existing shift/or facilities + ap_private hi(*this); + ap_private lo(*this); + lo.lshr(rotateAmt); + hi.shl(BitWidth - rotateAmt); + return hi | lo; + } + + /// Perform an unsigned divide operation on this ap_private by RHS. Both this and + /// RHS are treated as unsigned quantities for purposes of this division. + /// @returns a new ap_private value containing the division result + /// @brief Unsigned division operation. + ap_private udiv(const ap_private& RHS) const { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + + // First, deal with the easy case + if (isSingleWord()) { + assert(RHS.VAL != 0 && "Divide by zero?"); + return ap_private(VAL / RHS.VAL); + } + + // Get some facts about the LHS and RHS number of bits and words + uint32_t rhsBits = RHS.getActiveBits(); + uint32_t rhsWords = !rhsBits ? 0 : (whichWord(rhsBits - 1) + 1); + assert(rhsWords && "Divided by zero???"); + uint32_t lhsBits = this->getActiveBits(); + uint32_t lhsWords = !lhsBits ? 0 : (whichWord(lhsBits - 1) + 1); + + // Deal with some degenerate cases + if (!lhsWords) + // 0 / X ===> 0 + return ap_private(0); + else if (lhsWords < rhsWords || this->ult(RHS)) { + // X / Y ===> 0, iff X < Y + return ap_private(0); + } else if (*this == RHS) { + // X / X ===> 1 + return ap_private(1); + } else if (lhsWords == 1 && rhsWords == 1) { + // All high words are zero, just use native divide + return ap_private(this->pVal[0] / RHS.pVal[0]); + } + + // We have to compute it the hard way. Invoke the Knuth divide algorithm. + ap_private Quotient(0); // to hold result. + divide(*this, lhsWords, RHS, rhsWords, &Quotient, (ap_private*)0); + return Quotient; + } + + /// Signed divide this ap_private by ap_private RHS. + /// @brief Signed division function for ap_private. + INLINE ap_private sdiv(const ap_private& RHS) const { + if (isNegative()) + if (RHS.isNegative()) + return (-(*this)).udiv(-RHS); + else + return -((-(*this)).udiv(RHS)); + else if (RHS.isNegative()) + return -(this->udiv(-RHS)); + return this->udiv(RHS); + } + + /// Perform an unsigned remainder operation on this ap_private with RHS being the + /// divisor. Both this and RHS are treated as unsigned quantities for purposes + /// of this operation. Note that this is a true remainder operation and not + /// a modulo operation because the sign follows the sign of the dividend + /// which is *this. + /// @returns a new ap_private value containing the remainder result + /// @brief Unsigned remainder operation. + ap_private urem(const ap_private& RHS) const { + if (isSingleWord()) { + assert(RHS.VAL != 0 && "Remainder by zero?"); + return ap_private(VAL % RHS.VAL); + } + + // Get some facts about the LHS + uint32_t lhsBits = getActiveBits(); + uint32_t lhsWords = !lhsBits ? 0 : (whichWord(lhsBits - 1) + 1); + + // Get some facts about the RHS + uint32_t rhsBits = RHS.getActiveBits(); + uint32_t rhsWords = !rhsBits ? 0 : (whichWord(rhsBits - 1) + 1); + assert(rhsWords && "Performing remainder operation by zero ???"); + + // Check the degenerate cases + if (lhsWords == 0) { + // 0 % Y ===> 0 + return ap_private(0); + } else if (lhsWords < rhsWords || this->ult(RHS)) { + // X % Y ===> X, iff X < Y + return *this; + } else if (*this == RHS) { + // X % X == 0; + return ap_private(0); + } else if (lhsWords == 1) { + // All high words are zero, just use native remainder + return ap_private(pVal[0] % RHS.pVal[0]); + } + + // We have to compute it the hard way. Invoke the Knuth divide algorithm. + ap_private Remainder(0); + divide(*this, lhsWords, RHS, rhsWords, (ap_private*)(0), &Remainder); + return Remainder; + } + + ap_private urem(uint64_t RHS) const { + // Get some facts about the LHS + uint32_t lhsBits = getActiveBits(); + uint32_t lhsWords = !lhsBits ? 0 : (whichWord(lhsBits - 1) + 1); + // Get some facts about the RHS + uint32_t rhsBits = 64 - CountLeadingZeros_64(RHS); // RHS.getActiveBits(); + uint32_t rhsWords = 1;//!rhsBits ? 0 : (ap_private<_AP_W, _AP_S, _AP_N>::whichWord(rhsBits - 1) + 1); + assert(rhsWords && "Performing remainder operation by zero ???"); + // Check the degenerate cases + if (lhsWords == 0) { + // 0 % Y ===> 0 + return ap_private(0); + } else if (lhsWords < rhsWords || this->ult(RHS)) { + // X % Y ===> X, iff X < Y + return *this; + } else if (*this == RHS) { + // X % X == 0; + return ap_private(0); + } else if (lhsWords == 1) { + // All high words are zero, just use native remainder + return ap_private(pVal[0] % RHS); + } + + // We have to compute it the hard way. Invoke the Knuth divide algorithm. + ap_private Remainder(0); + divide(*this, lhsWords, RHS, (ap_private*)(0), &Remainder); + return Remainder; + } + + /// Signed remainder operation on ap_private. + /// @brief Function for signed remainder operation. + INLINE ap_private srem(const ap_private& RHS) const { + if (isNegative()) { + ap_private lhs = -(*this); + if (RHS.isNegative()) { + ap_private rhs = -RHS; + return -(lhs.urem(rhs)); + } else + return -(lhs.urem(RHS)); + } else if (RHS.isNegative()) { + ap_private rhs = -RHS; + return this->urem(rhs); + } + return this->urem(RHS); + } + + /// Signed remainder operation on ap_private. + /// @brief Function for signed remainder operation. + INLINE ap_private srem(int64_t RHS) const { + if (isNegative()) + if (RHS<0) + return -((-(*this)).urem(-RHS)); + else + return -((-(*this)).urem(RHS)); + else if (RHS<0) + return this->urem(-RHS); + return this->urem(RHS); + } + + /// Sometimes it is convenient to divide two ap_private values and obtain both + /// the quotient and remainder. This function does both operations in the + /// same computation making it a little more efficient. + /// @brief Dual division/remainder interface. + static void udivrem(const ap_private& LHS, const ap_private& RHS, ap_private &Quotient, ap_private& Remainder) { + // Get some size facts about the dividend and divisor + uint32_t lhsBits = LHS.getActiveBits(); + uint32_t lhsWords = !lhsBits ? 0 : (ap_private::whichWord(lhsBits - 1) + 1); + uint32_t rhsBits = RHS.getActiveBits(); + uint32_t rhsWords = !rhsBits ? 0 : (ap_private::whichWord(rhsBits - 1) + 1); + + // Check the degenerate cases + if (lhsWords == 0) { + Quotient = 0; // 0 / Y ===> 0 + Remainder = 0; // 0 % Y ===> 0 + return; + } + + if (lhsWords < rhsWords || LHS.ult(RHS)) { + Quotient = 0; // X / Y ===> 0, iff X < Y + Remainder = LHS; // X % Y ===> X, iff X < Y + return; + } + + if (LHS == RHS) { + Quotient = 1; // X / X ===> 1 + Remainder = 0; // X % X ===> 0; + return; + } + + if (lhsWords == 1 && rhsWords == 1) { + // There is only one word to consider so use the native versions. + if (LHS.isSingleWord()) { + Quotient = ap_private(LHS.VAL / RHS.VAL); + Remainder = ap_private(LHS.VAL % RHS.VAL); + } else { + Quotient = ap_private(LHS.pVal[0] / RHS.pVal[0]); + Remainder = ap_private(LHS.pVal[0] % RHS.pVal[0]); + } + return; + } + + // Okay, lets do it the long way + divide(LHS, lhsWords, RHS, rhsWords, &Quotient, &Remainder); + } + + static void sdivrem(const ap_private &LHS, const ap_private &RHS, + ap_private &Quotient, ap_private &Remainder) { + if (LHS.isNegative()) { + if (RHS.isNegative()) + ap_private::udivrem(-LHS, -RHS, Quotient, Remainder); + else + ap_private::udivrem(-LHS, RHS, Quotient, Remainder); + Quotient = -Quotient; + Remainder = -Remainder; + } else if (RHS.isNegative()) { + ap_private::udivrem(LHS, -RHS, Quotient, Remainder); + Quotient = -Quotient; + } else { + ap_private::udivrem(LHS, RHS, Quotient, Remainder); + } + } + + /// Compares this ap_private with RHS for the validity of the equality + /// relationship. + /// @returns true if *this == Val + /// @brief Equality comparison. + template + INLINE bool eq(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return (*this) == RHS; + } + + /// Compares this ap_private with RHS for the validity of the inequality + /// relationship. + /// @returns true if *this != Val + /// @brief Inequality comparison + template + INLINE bool ne(const ap_private<_AP_W, _AP_S1, _AP_N> &RHS) const { + return !((*this) == RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// the validity of the less-than relationship. + /// @returns true if *this < RHS when both are considered unsigned. + /// @brief Unsigned less than comparison + template + INLINE bool ult(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + // Get active bit length of both operands + uint32_t n1 = getActiveBits(); + uint32_t n2 = RHS.getActiveBits(); + + // If magnitude of LHS is less than RHS, return true. + if (n1 < n2) + return true; + + // If magnitude of RHS is greather than LHS, return false. + if (n2 < n1) + return false; + + // If they bot fit in a word, just compare the low order word + if (n1 <= APINT_BITS_PER_WORD && n2 <= APINT_BITS_PER_WORD) + return pVal[0] < RHS.pVal[0]; + + // Otherwise, compare all words + uint32_t topWord = whichWord(AESL_std::max(n1,n2)-1); + for (int i = topWord; i >= 0; --i) { + if (pVal[i] > RHS.pVal[i]) + return false; + if (pVal[i] < RHS.pVal[i]) + return true; + } + return false; + } + + INLINE bool ult(uint64_t RHS) const { + // Get active bit length of both operands + uint32_t n1 = getActiveBits(); + uint32_t n2 = 64 - CountLeadingZeros_64(RHS); //RHS.getActiveBits(); + + // If magnitude of LHS is less than RHS, return true. + if (n1 < n2) + return true; + + // If magnitude of RHS is greather than LHS, return false. + if (n2 < n1) + return false; + + // If they bot fit in a word, just compare the low order word + if (n1 <= APINT_BITS_PER_WORD && n2 <= APINT_BITS_PER_WORD) + return pVal[0] < RHS; + assert(0); + } + + template + INLINE bool slt(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + ap_private lhs(*this); + ap_private<_AP_W, _AP_S1, _AP_N> rhs(RHS); + bool lhsNeg = isNegative(); + bool rhsNeg = rhs.isNegative(); + if (lhsNeg) { + // Sign bit is set so perform two's complement to make it positive + lhs.flip(); + lhs++; + } + if (rhsNeg) { + // Sign bit is set so perform two's complement to make it positive + rhs.flip(); + rhs++; + } + + // Now we have unsigned values to compare so do the comparison if necessary + // based on the negativeness of the values. + if (lhsNeg) + if (rhsNeg) + return lhs.ugt(rhs); + else + return true; + else if (rhsNeg) + return false; + else + return lhs.ult(rhs); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// validity of the less-or-equal relationship. + /// @returns true if *this <= RHS when both are considered unsigned. + /// @brief Unsigned less or equal comparison + template + INLINE bool ule(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return ult(RHS) || eq(RHS); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the less-or-equal relationship. + /// @returns true if *this <= RHS when both are considered signed. + /// @brief Signed less or equal comparison + template + INLINE bool sle(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return slt(RHS) || eq(RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// the validity of the greater-than relationship. + /// @returns true if *this > RHS when both are considered unsigned. + /// @brief Unsigned greather than comparison + template + INLINE bool ugt(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return !ult(RHS) && !eq(RHS); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// the validity of the greater-than relationship. + /// @returns true if *this > RHS when both are considered signed. + /// @brief Signed greather than comparison + template + INLINE bool sgt(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return !slt(RHS) && !eq(RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// validity of the greater-or-equal relationship. + /// @returns true if *this >= RHS when both are considered unsigned. + /// @brief Unsigned greater or equal comparison + template + INLINE bool uge(const ap_private<_AP_W, _AP_S, _AP_N>& RHS) const { + return !ult(RHS); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the greater-or-equal relationship. + /// @returns true if *this >= RHS when both are considered signed. + /// @brief Signed greather or equal comparison + template + INLINE bool sge(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return !slt(RHS); + } + + template + void cpTrunc(const ap_private<_AP_W1, _AP_S1, _AP_N1>& that) { + assert(_AP_W1 > BitWidth && "Invalid ap_private Truncate request"); + assert(_AP_W1 >= MIN_INT_BITS && "Can't truncate to 0 bits"); + memcpy(pVal, that.pVal, _AP_N*APINT_WORD_SIZE); + } + + // Sign extend to a new width. + template + void cpSext(const ap_private<_AP_W1, _AP_S1, _AP_N1>& that) { + assert(_AP_W1 < BitWidth && "Invalid ap_private SignExtend request"); + assert(_AP_W1 <= MAX_INT_BITS && "Too many bits"); + // If the sign bit isn't set, this is the same as zext. + if (!that.isNegative()) { + cpZext(that); + return; + } + + // The sign bit is set. First, get some facts + enum { wordBits = _AP_W1 % APINT_BITS_PER_WORD}; + + // Mask the high order word appropriately + if (_AP_N1 == _AP_N) { + enum { newWordBits = _AP_W % APINT_BITS_PER_WORD}; + // The extension is contained to the wordsBefore-1th word. + static const uint64_t mask = wordBits?(~0ULL<<(wordBits)):0ULL; + if (_AP_N1 == 1) { + assert(0); + } else { + for (uint32_t i = 0; i < _AP_N1; ++i) + pVal[i] = that.pVal[i]; + pVal[_AP_N1-1] |= mask; + return; + } + } + + if (_AP_N1 == 1) { + assert(0);// newVal[0] = VAL | mask; + } else { + enum { newWordBits = _AP_W % APINT_BITS_PER_WORD}; + // The extension is contained to the wordsBefore-1th word. + static const uint64_t mask = wordBits?(~0ULL<<(wordBits)):0ULL; + for (uint32_t i = 0; i < _AP_N1; ++i) + pVal[i] = that.pVal[i]; + pVal[_AP_N1-1] |= mask; + } + for (uint32_t i=_AP_N1; i < _AP_N-1; i++) + pVal[i] = ~0ULL; + pVal[_AP_N-1] = ~0ULL; + clearUnusedBits(); + return; + } + + // Zero extend to a new width. + template + void cpZext(const ap_private<_AP_W1, _AP_S1, _AP_N1>& that) { + assert(_AP_W1 < BitWidth && "Invalid ap_private ZeroExtend request"); + assert(_AP_W1 <= MAX_INT_BITS && "Too many bits"); + uint32_t wordsAfter = _AP_N; + if (wordsAfter==1) { + assert(0); // return ap_private<_AP_W1, _AP_S, _AP_N1> (_AP_W1, VAL, _AP_S); + } else { + if (_AP_N1 == 1) { + assert(0); + // newVal[0] = VAL; + } else { + uint32_t i = 0; + for (; i < _AP_N1; ++i) + pVal[i] = that.pVal[i]; + for (; i < _AP_N; ++i) + pVal[i] = 0; + } + } + clearUnusedBits(); + } + + template + void cpZextOrTrunc(const ap_private<_AP_W1, _AP_S1, _AP_N1>& that) { + if (BitWidth > _AP_W1) + cpZext(that); + else if (BitWidth < _AP_W1) + cpTrunc(that); + else { + for (int i=0; i<_AP_N1; ++i) + pVal[i]=that.pVal[i]; + clearUnusedBits(); + } + } + + template + void cpSextOrTrunc(const ap_private<_AP_W1, _AP_S1, _AP_N1>& that) { + if (BitWidth > _AP_W1) + cpSext(that); + else if (BitWidth < _AP_W1) + cpTrunc(that); + else { + for (int i=0; i<_AP_N1; ++i) + pVal[i] = that.pVal[i]; + clearUnusedBits(); + } + } + + /// @name Value Characterization Functions + /// @{ + + /// @returns the total number of bits. + INLINE uint32_t getBitWidth() const { + return BitWidth; + } + + /// Here one word's bitwidth equals to that of uint64_t. + /// @returns the number of words to hold the integer value of this ap_private. + /// @brief Get the number of words. + INLINE uint32_t getNumWords() const { + return (BitWidth + APINT_BITS_PER_WORD - 1) / APINT_BITS_PER_WORD; + } + + /// This function returns the number of active bits which is defined as the + /// bit width minus the number of leading zeros. This is used in several + /// computations to see how "wide" the value is. + /// @brief Compute the number of active bits in the value + INLINE uint32_t getActiveBits() const { + uint32_t bits=BitWidth - countLeadingZeros(); + return bits?bits:1; + } + + + /// This method attempts to return the value of this ap_private as a zero extended + /// uint64_t. The bitwidth must be <= 64 or the value must fit within a + /// uint64_t. Otherwise an assertion will result. + /// @brief Get zero extended value + INLINE uint64_t getZExtValue() const { + assert(getActiveBits() <= 64 && "Too many bits for uint64_t"); + return *pVal; + } + + /// This method attempts to return the value of this ap_private as a sign extended + /// int64_t. The bit width must be <= 64 or the value must fit within an + /// int64_t. Otherwise an assertion will result. + /// @brief Get sign extended value + INLINE int64_t getSExtValue() const { + assert(getActiveBits() <= 64 && "Too many bits for int64_t"); + return int64_t(pVal[0]); + } + + /// This method determines how many bits are required to hold the ap_private + /// equivalent of the string given by \p str of length \p slen. + /// @brief Get bits required for string value. + static uint32_t getBitsNeeded(const char* str, uint32_t slen, uint8_t radix); + + /// countLeadingZeros - This function is an ap_private version of the + /// countLeadingZeros_{32,64} functions in MathExtras.h. It counts the number + /// of zeros from the most significant bit to the first one bit. + /// @returns BitWidth if the value is zero. + /// @returns the number of zeros from the most significant bit to the first + /// one bits. + INLINE uint32_t countLeadingZeros() const ; + + /// countLeadingOnes - This function counts the number of contiguous 1 bits + /// in the high order bits. The count stops when the first 0 bit is reached. + /// @returns 0 if the high order bit is not set + /// @returns the number of 1 bits from the most significant to the least + /// @brief Count the number of leading one bits. + INLINE uint32_t countLeadingOnes() const ; + + /// countTrailingZeros - This function is an ap_private version of the + /// countTrailingZoers_{32,64} functions in MathExtras.h. It counts + /// the number of zeros from the least significant bit to the first set bit. + /// @returns BitWidth if the value is zero. + /// @returns the number of zeros from the least significant bit to the first + /// one bit. + /// @brief Count the number of trailing zero bits. + INLINE uint32_t countTrailingZeros() const ; + + /// countPopulation - This function is an ap_private version of the + /// countPopulation_{32,64} functions in MathExtras.h. It counts the number + /// of 1 bits in the ap_private value. + /// @returns 0 if the value is zero. + /// @returns the number of set bits. + /// @brief Count the number of bits set. + INLINE uint32_t countPopulation() const { + uint32_t Count = 0; + for (uint32_t i = 0; i<_AP_N-1 ; ++i) + Count += CountPopulation_64(pVal[i]); + Count += CountPopulation_64(pVal[_AP_N-1]&mask); + return Count; + } + + /// @} + /// @name Conversion Functions + /// @{ + + /// This is used internally to convert an ap_private to a string. + /// @brief Converts an ap_private to a std::string + INLINE std::string toString(uint8_t radix, bool wantSigned) const + ; + + /// Considers the ap_private to be unsigned and converts it into a string in the + /// radix given. The radix can be 2, 8, 10 or 16. + /// @returns a character interpretation of the ap_private + /// @brief Convert unsigned ap_private to string representation. + INLINE std::string toStringUnsigned(uint8_t radix = 10) const { + return toString(radix, false); + } + + /// Considers the ap_private to be unsigned and converts it into a string in the + /// radix given. The radix can be 2, 8, 10 or 16. + /// @returns a character interpretation of the ap_private + /// @brief Convert unsigned ap_private to string representation. + INLINE std::string toStringSigned(uint8_t radix = 10) const { + return toString(radix, true); + } + + /// @returns a byte-swapped representation of this ap_private Value. + INLINE ap_private byteSwap() const ; + + /// @brief Converts this ap_private to a double value. + INLINE double roundToDouble(bool isSigned) const ; + + /// @brief Converts this unsigned ap_private to a double value. + INLINE double roundToDouble() const { + return roundToDouble(false); + } + + /// @brief Converts this signed ap_private to a double value. + INLINE double signedRoundToDouble() const { + return roundToDouble(true); + } + + /// The conversion does not do a translation from integer to double, it just + /// re-interprets the bits as a double. Note that it is valid to do this on + /// any bit width. Exactly 64 bits will be translated. + /// @brief Converts ap_private bits to a double + INLINE double bitsToDouble() const { + union { + uint64_t __I; + double __D; + } __T; + __T.__I = pVal[0]; + return __T.__D; + } + + /// The conversion does not do a translation from integer to float, it just + /// re-interprets the bits as a float. Note that it is valid to do this on + /// any bit width. Exactly 32 bits will be translated. + /// @brief Converts ap_private bits to a double + INLINE float bitsToFloat() const { + union { + uint32_t __I; + float __F; + } __T; + __T.__I = uint32_t(pVal[0]); + return __T.__F; + } + + /// The conversion does not do a translation from double to integer, it just + /// re-interprets the bits of the double. Note that it is valid to do this on + /// any bit width but bits from V may get truncated. + /// @brief Converts a double to ap_private bits. + INLINE ap_private& doubleToBits(double __V) { + union { + uint64_t __I; + double __D; + } __T; + __T.__D = __V; + pVal[0] = __T.__I; + return *this; + } + + /// The conversion does not do a translation from float to integer, it just + /// re-interprets the bits of the float. Note that it is valid to do this on + /// any bit width but bits from V may get truncated. + /// @brief Converts a float to ap_private bits. + INLINE ap_private& floatToBits(float __V) { + union { + uint32_t __I; + float __F; + } __T; + __T.__F = __V; + pVal[0] = __T.__I; + } + + //Reduce operation + //----------------------------------------------------------- + INLINE bool and_reduce() const { + return isMaxValue(); + } + + INLINE bool nand_reduce() const { + return isMinValue(); + } + + INLINE bool or_reduce() const { + return (bool)countPopulation(); + } + + INLINE bool nor_reduce() const { + return countPopulation()==0; + } + + INLINE bool xor_reduce() const { + unsigned int i=countPopulation(); + return (i%2)?true:false; + } + + INLINE bool xnor_reduce() const { + unsigned int i=countPopulation(); + return (i%2)?false:true; + } + INLINE std::string to_string(uint8_t radix=16, bool sign=false) const { + return toString(radix, radix==10?_AP_S:sign); + } +}; + +template +INLINE bool operator==(uint64_t V1, const ap_private<_AP_W, _AP_S, _AP_N>& V2) { + return V2 == V1; +} + +template +INLINE bool operator!=(uint64_t V1, const ap_private<_AP_W, _AP_S, _AP_N>& V2) { + return V2 != V1; +} + +namespace ap_private_ops { + enum {APINT_BITS_PER_WORD=64}; + /// @brief Determine the smaller of two ap_privates considered to be signed. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> smin(const ap_private<_AP_W, _AP_S, _AP_N> &LHS, const ap_private<_AP_W, _AP_S1, _AP_N> &RHS) { + return LHS.slt(RHS) ? LHS : RHS; + } + + /// @brief Determine the larger of two ap_privates considered to be signed. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> smax(const ap_private<_AP_W, _AP_S, _AP_N> &LHS, const ap_private<_AP_W, _AP_S1, _AP_N> &RHS) { + return LHS.sgt(RHS) ? LHS : RHS; + } + + /// @brief Determine the smaller of two ap_privates considered to be signed. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> umin(const ap_private<_AP_W, _AP_S, _AP_N> &LHS, const ap_private<_AP_W, _AP_S1, _AP_N> &RHS) { + return LHS.ult(RHS) ? LHS : RHS; + } + + /// @brief Determine the larger of two ap_privates considered to be unsigned. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> umax(const ap_private<_AP_W, _AP_S, _AP_N> &LHS, const ap_private<_AP_W, _AP_S1, _AP_N> &RHS) { + return LHS.ugt(RHS) ? LHS : RHS; + } + + /// @brief Check if the specified ap_private has a N-bits integer value. + template + INLINE bool isIntN(uint32_t __N, const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.isIntN(__N); + } + + /// @returns true if the argument ap_private value is a sequence of ones + /// starting at the least significant bit with the remainder zero. + template + INLINE bool isMask(uint32_t numBits, const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.getBoolValue() && ((APIVal + ap_private<_AP_W, _AP_S, _AP_N>(numBits,1)) & APIVal) == 0; + } + + /// @returns true if the argument ap_private value contains a sequence of ones + /// with the remainder zero. + template + INLINE bool isShiftedMask(uint32_t numBits, const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return isMask(numBits, (APIVal - ap_private<_AP_W, _AP_S, _AP_N>(numBits,1)) | APIVal); + } + + /// @returns a byte-swapped representation of the specified ap_private Value. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> byteSwap(const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.byteSwap(); + } + + /// @returns the floor log base 2 of the specified ap_private value. + template INLINE uint32_t logBase2(const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.logBase2(); + } + + /// GreatestCommonDivisor - This function returns the greatest common + /// divisor of the two ap_private values using Enclid's algorithm. + /// @returns the greatest common divisor of Val1 and Val2 + /// @brief Compute GCD of two ap_private values. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> GreatestCommonDivisor(const ap_private<_AP_W, _AP_S, _AP_N>& Val1, const ap_private<_AP_W, _AP_S, _AP_N>& Val2) + ; + + /// Treats the ap_private as an unsigned value for conversion purposes. + /// @brief Converts the given ap_private to a double value. + template INLINE double Roundap_privateToDouble(const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.roundToDouble(); + } + + /// Treats the ap_private as a signed value for conversion purposes. + /// @brief Converts the given ap_private to a double value. + template INLINE double RoundSignedap_privateToDouble(const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.signedRoundToDouble(); + } + + /// @brief Converts the given ap_private to a float vlalue. + template INLINE float Roundap_privateToFloat(const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return float(Roundap_privateToDouble(APIVal)); + } + + /// Treast the ap_private as a signed value for conversion purposes. + /// @brief Converts the given ap_private to a float value. + template INLINE float RoundSignedap_privateToFloat(const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return float(APIVal.signedRoundToDouble()); + } + + /// RoundDoubleToap_private - This function convert a double value to an ap_private value. + /// @brief Converts the given double value into a ap_private. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> RoundDoubleToap_private(double Double, uint32_t width) ; + + /// RoundFloatToap_private - Converts a float value into an ap_private value. + /// @brief Converts a float value into a ap_private. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> RoundFloatToap_private(float Float, uint32_t width) { + return RoundDoubleToap_private<_AP_W, _AP_S, _AP_N>(double(Float), width); + } + + /// Arithmetic right-shift the ap_private by shiftAmt. + /// @brief Arithmetic right-shift function. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> ashr(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, uint32_t shiftAmt) { + return LHS.ashr(shiftAmt); + } + + /// Logical right-shift the ap_private by shiftAmt. + /// @brief Logical right-shift function. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> lshr(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, uint32_t shiftAmt) { + return LHS.lshr(shiftAmt); + } + + /// Left-shift the ap_private by shiftAmt. + /// @brief Left-shift function. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> shl(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, uint32_t shiftAmt) { + return LHS.shl(shiftAmt); + } + + /// Signed divide ap_private LHS by ap_private RHS. + /// @brief Signed division function for ap_private. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> sdiv(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS.sdiv(RHS); + } + + /// Unsigned divide ap_private LHS by ap_private RHS. + /// @brief Unsigned division function for ap_private. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> udiv(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS.udiv(RHS); + } + + /// Signed remainder operation on ap_private. + /// @brief Function for signed remainder operation. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> srem(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS.srem(RHS); + } + + /// Unsigned remainder operation on ap_private. + /// @brief Function for unsigned remainder operation. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> urem(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS.urem(RHS); + } + + /// Performs multiplication on ap_private values. + /// @brief Function for multiplication operation. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> mul(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS * RHS; + } + + /// Performs addition on ap_private values. + /// @brief Function for addition operation. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> add(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS + RHS; + } + + /// Performs subtraction on ap_private values. + /// @brief Function for subtraction operation. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> sub(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS - RHS; + } + + /// Performs bitwise AND operation on ap_private LHS and + /// ap_private RHS. + /// @brief Bitwise AND function for ap_private. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> And(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS & RHS; + } + + /// Performs bitwise OR operation on ap_private LHS and ap_private RHS. + /// @brief Bitwise OR function for ap_private. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> Or(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS | RHS; + } + + /// Performs bitwise XOR operation on ap_private. + /// @brief Bitwise XOR function for ap_private. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> Xor(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS ^ RHS; + } + + /// Performs a bitwise complement operation on ap_private. + /// @brief Bitwise complement function. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> Not(const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return ~APIVal; + } + + template void clearUnusedBits(uint64_t& msw) { + // Compute how many bits are used in the final word + // uint32_t wordBits = APIVal.getBitWidth() & 0x3f; + if (wordBits == 0) + // If all bits are used, we want to leave the value alone. This also + // avoids the undefined behavior of >> when the shfit is the same size as + // the word size (64). + return; + + // Mask out the hight bits. + uint64_t mask = ~uint64_t(0ULL) >> (64 /*ap_private::APINT_BITS_PER_WORD */- wordBits); + msw &= mask; + } + template <> INLINE void clearUnusedBits<1>(uint64_t& msw) { + uint64_t mask = ~uint64_t(0ULL) >> (64 /*ap_private::APINT_BITS_PER_WORD */- 1); + msw &= mask; + } + template void clearUnusedBits(int64_t& msw) { + // Compute how many bits are used in the final word + // uint32_t wordBits = APIVal.getBitWidth() & 0x3f; + if (wordBits == 0) + // If all bits are used, we want to leave the value alone. This also + // avoids the undefined behavior of >> when the shfit is the same size as + // the word size (64). + return; + + // Mask out the hight bits. + uint64_t mask = ~uint64_t(0ULL) >> (64 /*ap_private::APINT_BITS_PER_WORD */- wordBits); + msw &= mask; + } + template <> INLINE void clearUnusedBits<1>(int64_t& msw) { + uint64_t mask = ~uint64_t(0ULL) >> (64 /*ap_private::APINT_BITS_PER_WORD */- 1); + msw &= mask; + } + // template + template + INLINE ap_private<_AP_W, _AP_S> ashr(const ap_private<_AP_W, _AP_S>& a) { + return ashr(a, shiftAmt); + } + + template + INLINE ap_private<_AP_W, _AP_S> lshr(const ap_private<_AP_W, _AP_S>& a) { + return lshr(a, shiftAmt); + } + + template + INLINE ap_private<_AP_W, true> ashr(const ap_private<_AP_W, true, 1>& a) { + enum {APINT_BITS_PER_WORD=64, excess_bits=APINT_BITS_PER_WORD-_AP_W}; + static const uint64_t sign_bit = (1ULL<<(_AP_W-1)); + static const uint64_t sign_ext_mask = (_AP_W-shiftAmt>0)?~0ULL<<(APINT_BITS_PER_WORD-_AP_W+shiftAmt):~0ULL; + return ap_private<_AP_W, true>((((int64_t)a.VAL) >> (shiftAmt)) | (a.VAL & sign_bit? sign_ext_mask : 0ULL)); + } + + template + INLINE ap_private<_AP_W, false> ashr(const ap_private<_AP_W, false, 1>& a) { + return ap_private<_AP_W, false>((a.VAL) >> (shiftAmt)); + } + + template + INLINE ap_private<_AP_W, _AP_S> lshr(const ap_private<_AP_W, _AP_S, 1>& a) { + static const uint64_t mask = ~0ULL<<_AP_W; + return ap_private<_AP_W, _AP_S>((a.VAL&mask) >> (shiftAmt)); + } + + template + INLINE ap_private<_AP_W-shiftAmt, _AP_S> shr(const ap_private<_AP_W, _AP_S>& a) { + return ap_private<_AP_W-shiftAmt, _AP_S>((a.VAL) >> (shiftAmt)); + } + + template + INLINE ap_private<_AP_W+shiftAmt, _AP_S> shl(const ap_private<_AP_W, _AP_S>& a) { + return ap_private<_AP_W+shiftAmt, _AP_S>((a.VAL) << (shiftAmt)); + } + + template + INLINE bool get(const ap_private<_AP_W, _AP_S, 1>& a) { + unsigned shift = (index%APINT_BITS_PER_WORD); + static const uint64_t mask=1ULL << (shift); + return ((mask & a.VAL) != 0); + } + + template + INLINE bool get(const ap_private<_AP_W, _AP_S>& a) { + static const uint64_t mask=1ULL << (index&0x3f); + return ((mask & a.pVal[(index)>>6]) != 0); + } + + template + INLINE void set(ap_private<_AP_W, _AP_S, 1>& a) { + const uint64_t mask = ~0ULL >> (lsb) << (APINT_BITS_PER_WORD-msb+lsb-1)>>(APINT_BITS_PER_WORD-msb-1); + a.VAL |= mask; + } + + template + INLINE void clear(ap_private<_AP_W, _AP_S, 1>& a) { + static const uint64_t mask = ~(~0ULL >> (lsb) <<(APINT_BITS_PER_WORD-msb+lsb-1) >> (APINT_BITS_PER_WORD-msb-1)); + a.VAL &= mask; + } + + template + INLINE void set(ap_private<_AP_W, _AP_S>& a) { + enum { APINT_BITS_PER_WORD=64, + lsb_word = lsb_index /APINT_BITS_PER_WORD, + msb_word = msb_index / APINT_BITS_PER_WORD, + msb = msb_index % APINT_BITS_PER_WORD, + lsb=lsb_index % APINT_BITS_PER_WORD}; + if (msb_word==lsb_word) { + const uint64_t mask = ~0ULL >> (lsb) << (APINT_BITS_PER_WORD-msb+lsb-1)>>(APINT_BITS_PER_WORD-msb-1); + a.pVal[msb_word] |= mask; + } else { + const uint64_t lsb_mask = ~0ULL >> (lsb) << (lsb); + const uint64_t msb_mask = ~0ULL << (APINT_BITS_PER_WORD-msb-1)>>(APINT_BITS_PER_WORD-msb-1); + a.pVal[lsb_word] |=lsb_mask; + for (int i=lsb_word+1; i + INLINE void clear(ap_private<_AP_W, _AP_S>& a) { + enum { APINT_BITS_PER_WORD=64, + lsb_word = lsb_index /APINT_BITS_PER_WORD, + msb_word = msb_index / APINT_BITS_PER_WORD, + msb = msb_index % APINT_BITS_PER_WORD, + lsb=lsb_index % APINT_BITS_PER_WORD}; + if (msb_word == lsb_word) { + const uint64_t mask = ~(~0ULL >> (lsb) << (APINT_BITS_PER_WORD-msb+lsb-1)>>(APINT_BITS_PER_WORD-msb-1)); + a.pVal[msb_word] &= mask; + } else { + const uint64_t lsb_mask = ~(~0ULL >> (lsb) << (lsb)); + const uint64_t msb_mask = ~(~0ULL << (APINT_BITS_PER_WORD-msb-1)>>(APINT_BITS_PER_WORD-msb-1)); + a.pVal[lsb_word] &=lsb_mask; + for (int i=lsb_word+1; i + INLINE void set(ap_private<_AP_W, _AP_S, 1>& a) { + static const uint64_t mask=1ULL << (index); + a.VAL |= mask; + a.clearUnusedBits(); + } + + template + INLINE void clear(ap_private<_AP_W, _AP_S, 1>& a) { + static const uint64_t mask=~(1ULL << (index)); + a.VAL &= mask; + a.clearUnusedBits(); + } + + template + INLINE void set(ap_private<_AP_W, _AP_S>& a) { + enum { APINT_BITS_PER_WORD=64, word = index/APINT_BITS_PER_WORD}; + static const uint64_t mask=1ULL << (index%APINT_BITS_PER_WORD); + a.pVal[word] |= mask; + a.clearUnusedBits(); + } + + template + INLINE void clear(ap_private<_AP_W, _AP_S>& a) { + enum { APINT_BITS_PER_WORD=64, word = index/APINT_BITS_PER_WORD}; + static const uint64_t mask=~(1ULL << (index%APINT_BITS_PER_WORD)); + a.pVal[word] &= mask; + a.clearUnusedBits(); + } + + template + INLINE bool isNegative(const ap_private<_AP_W, false>& a) { + return false; + } + + template + INLINE bool isNegative(const ap_private<_AP_W, true, 1>& a) { + static const uint64_t sign_mask = (1ULL << (_AP_W-1)); + return ((sign_mask & a.VAL) != 0); + } + + template + INLINE bool isNegative(const ap_private<_AP_W, true>& a) { + enum {APINT_BITS_PER_WORD=64,_AP_N=(_AP_W+APINT_BITS_PER_WORD-1)/APINT_BITS_PER_WORD}; + static const uint64_t sign_mask = (1ULL << (_AP_W%APINT_BITS_PER_WORD-1)); + return sign_mask & a.pVal[_AP_N-1]; + } +} // End of ap_private_ops namespace + +/// @brief Check if the specified ap_private has a N-bits integer value. +template +INLINE bool isIntN(uint32_t __N, const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.isIntN(__N); +} + +/// @returns true if the argument ap_private value is a sequence of ones +/// starting at the least significant bit with the remainder zero. +template +INLINE bool isMask(uint32_t numBits, const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.getBoolValue() && ((APIVal + ap_private<_AP_W, _AP_S, _AP_N>(numBits,1)) & APIVal) == 0; +} + +/// @returns true if the argument ap_private value contains a sequence of ones +/// with the remainder zero. +template +INLINE bool isShiftedMask(uint32_t numBits, const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return isMask(numBits, (APIVal - ap_private<_AP_W, _AP_S, _AP_N>(numBits,1)) | APIVal); +} + +#if 0 +/// add_1 - This function adds a single "digit" integer, y, to the multiple +/// "digit" integer array, x[]. x[] is modified to reflect the addition and +/// 1 is returned if there is a carry out, otherwise 0 is returned. +/// @returns the carry of the addition. +static bool add_1(uint64_t dest[], uint64_t x[], uint32_t len, uint64_t y) { + for (uint32_t i = 0; i < len; ++i) { + dest[i] = y + x[i]; + if (dest[i] < y) + y = 1; // Carry one to next digit. + else { + y = 0; // No need to carry so exit early + break; + } + } + return (y != 0); +} +#endif + +#if 0 +/// add - This function adds the integer array x to the integer array Y and +/// places the result in dest. +/// @returns the carry out from the addition +/// @brief General addition of 64-bit integer arrays +static bool add(uint64_t *dest, const uint64_t *x, const uint64_t *y, + uint32_t destlen, uint32_t xlen, uint32_t ylen, bool xsigned, bool ysigned) { + bool carry = false; + uint32_t len = AESL_std::min(xlen, ylen); + uint32_t i; + for (i = 0; i< len && i < destlen; ++i) { + uint64_t limit = AESL_std::min(x[i],y[i]); // must come first in case dest == x + dest[i] = x[i] + y[i] + carry; + carry = dest[i] < limit || (carry && dest[i] == limit); + } + if (xlen > ylen) { + const uint64_t yext = xsigned && int64_t(y[ylen-1])<0 ? -1 : 0; + for (i=ylen; i< xlen && i < destlen; i++) { + uint64_t limit = AESL_std::min(x[i], yext); + dest[i] = x[i] + yext + carry; + carry = (dest[i] < limit)||(carry && dest[i] == x[i]); + } + } else if (ylen> xlen) { + const uint64_t xext = ysigned && int64_t(x[xlen-1])<0 ? -1 : 0; + for (i=xlen; i< ylen && i < destlen; i++) { + uint64_t limit = AESL_std::min(xext, y[i]); + dest[i] = xext + y[i] + carry; + carry = (dest[i] < limit)||(carry && dest[i] == y[i]); + } + } + return carry; +} +#endif + +#if 0 +/// @returns returns the borrow out. +/// @brief Generalized subtraction of 64-bit integer arrays. +static bool sub(uint64_t *dest, const uint64_t *x, const uint64_t *y, + uint32_t destlen, uint32_t xlen, uint32_t ylen, bool xsigned, bool ysigned) { + bool borrow = false; + uint32_t i; + uint32_t len = AESL_std::min(xlen, ylen); + for (i = 0; i < len && i < destlen; ++i) { + uint64_t x_tmp = borrow ? x[i] - 1 : x[i]; + borrow = y[i] > x_tmp || (borrow && x[i] == 0); + dest[i] = x_tmp - y[i]; + } + if (xlen > ylen) { + const uint64_t yext = ysigned && int64_t(y[ylen-1])<0 ? -1 : 0; + for (i=ylen; i< xlen && i < destlen; i++) { + uint64_t x_tmp = borrow ? x[i] - 1 : x[i]; + borrow = yext > x_tmp || (borrow && x[i] == 0); + dest[i] = x_tmp - yext; + } + } else if (ylen> xlen) { + const uint64_t xext = xsigned && int64_t(x[xlen-1])<0 ? -1 : 0; + for (i=xlen; i< ylen && i < destlen; i++) { + uint64_t x_tmp = borrow ? xext - 1 : xext; + borrow = y[i] > x_tmp || (borrow && xext==0); + dest[i] = x_tmp - y[i]; + } + } + return borrow; +} +#endif + +/// Subtracts the RHS ap_private from this ap_private +/// @returns this, after subtraction +/// @brief Subtraction assignment operator. + +#if 0 +/// Multiplies an integer array, x by a a uint64_t integer and places the result +/// into dest. +/// @returns the carry out of the multiplication. +/// @brief Multiply a multi-digit ap_private by a single digit (64-bit) integer. +static uint64_t mul_1(uint64_t dest[], const uint64_t x[], uint32_t len, uint64_t y) { + // Split y into high 32-bit part (hy) and low 32-bit part (ly) + uint64_t ly = y & 0xffffffffULL, hy = (y) >> 32; + uint64_t carry = 0; + static const uint64_t two_power_32 = 1ULL << 32; + // For each digit of x. + for (uint32_t i = 0; i < len; ++i) { + // Split x into high and low words + uint64_t lx = x[i] & 0xffffffffULL; + uint64_t hx = (x[i]) >> 32; + // hasCarry - A flag to indicate if there is a carry to the next digit. + // hasCarry == 0, no carry + // hasCarry == 1, has carry + // hasCarry == 2, no carry and the calculation result == 0. + uint8_t hasCarry = 0; + dest[i] = carry + lx * ly; + // Determine if the add above introduces carry. + hasCarry = (dest[i] < carry) ? 1 : 0; + carry = hx * ly + ((dest[i]) >> 32) + (hasCarry ? two_power_32 : 0); + // The upper limit of carry can be (2^32 - 1)(2^32 - 1) + + // (2^32 - 1) + 2^32 = 2^64. + hasCarry = (!carry && hasCarry) ? 1 : (!carry ? 2 : 0); + + carry += (lx * hy) & 0xffffffffULL; + dest[i] = ((carry) << 32) | (dest[i] & 0xffffffffULL); + carry = (((!carry && hasCarry != 2) || hasCarry == 1) ? two_power_32 : 0) + + ((carry) >> 32) + ((lx * hy) >> 32) + hx * hy; + } + return carry; +} +#endif + +#if 0 +/// Multiplies integer array x by integer array y and stores the result into +/// the integer array dest. Note that dest's size must be >= xlen + ylen. +/// @brief Generalized multiplicate of integer arrays. +static void mul(uint64_t dest[], const uint64_t x[], uint32_t xlen, const uint64_t y[], + uint32_t ylen, uint32_t destlen) { + dest[xlen] = mul_1(dest, x, xlen, y[0]); + for (uint32_t i = 1; i < ylen; ++i) { + uint64_t ly = y[i] & 0xffffffffULL, hy = (y[i]) >> 32; + uint64_t carry = 0, lx = 0, hx = 0; + for (uint32_t j = 0; j < xlen; ++j) { + lx = x[j] & 0xffffffffULL; + hx = (x[j]) >> 32; + // hasCarry - A flag to indicate if has carry. + // hasCarry == 0, no carry + // hasCarry == 1, has carry + // hasCarry == 2, no carry and the calculation result == 0. + uint8_t hasCarry = 0; + uint64_t resul = carry + lx * ly; + hasCarry = (resul < carry) ? 1 : 0; + carry = (hasCarry ? (1ULL << 32) : 0) + hx * ly + ((resul) >> 32); + hasCarry = (!carry && hasCarry) ? 1 : (!carry ? 2 : 0); + carry += (lx * hy) & 0xffffffffULL; + resul = ((carry) << 32) | (resul & 0xffffffffULL); + dest[i+j] += resul; + carry = (((!carry && hasCarry != 2) || hasCarry == 1) ? (1ULL << 32) : 0)+ + ((carry) >> 32) + (dest[i+j] < resul ? 1 : 0) + + ((lx * hy) >> 32) + hx * hy; + } + dest[i+xlen] = carry; + } +} +#endif + + + +template +uint32_t ap_private<_AP_W, _AP_S, _AP_N>::getBitsNeeded(const char* str, uint32_t slen, uint8_t radix) { + assert(str != 0 && "Invalid value string"); + assert(slen > 0 && "Invalid string length"); + + // Each computation below needs to know if its negative + uint32_t isNegative = str[0] == '-'; + if (isNegative) { + slen--; + str++; + } + // For radixes of power-of-two values, the bits required is accurately and + // easily computed + if (radix == 2) + return slen + isNegative; + if (radix == 8) + return slen * 3 + isNegative; + if (radix == 16) + return slen * 4 + isNegative; + + // Otherwise it must be radix == 10, the hard case + assert(radix == 10 && "Invalid radix"); + + // Convert to the actual binary value. + //ap_private<_AP_W, _AP_S, _AP_N> tmp(sufficient, str, slen, radix); + + // Compute how many bits are required. + //return isNegative + tmp.logBase2() + 1; + return isNegative + slen * 4; +} + +template +uint32_t ap_private<_AP_W, _AP_S, _AP_N>::countLeadingZeros() const { + enum { msw_bits = (BitWidth % APINT_BITS_PER_WORD)?(BitWidth % APINT_BITS_PER_WORD):APINT_BITS_PER_WORD, + excessBits = APINT_BITS_PER_WORD - msw_bits }; + uint32_t Count = CountLeadingZeros_64(pVal[_AP_N-1]); + if (Count>=excessBits) + Count -= excessBits; + if (!pVal[_AP_N-1]) { + for (uint32_t i = _AP_N-1 ; i ; --i) { + if (!pVal[i-1]) + Count += APINT_BITS_PER_WORD; + else { + Count += CountLeadingZeros_64(pVal[i-1]); + break; + } + } + } + return Count; +} + +static uint32_t countLeadingOnes_64(uint64_t __V, uint32_t skip) { + uint32_t Count = 0; + if (skip) + (__V) <<= (skip); + while (__V && (__V & (1ULL << 63))) { + Count++; + (__V) <<= 1; + } + return Count; +} + +template +uint32_t ap_private<_AP_W, _AP_S, _AP_N>::countLeadingOnes() const { + if (isSingleWord()) + return countLeadingOnes_64(VAL, APINT_BITS_PER_WORD - BitWidth); + + uint32_t highWordBits = BitWidth % APINT_BITS_PER_WORD; + uint32_t shift = (highWordBits == 0 ? 0 : APINT_BITS_PER_WORD - highWordBits); + int i = _AP_N - 1; + uint32_t Count = countLeadingOnes_64(pVal[i], shift); + if (Count == highWordBits) { + for (i--; i >= 0; --i) { + if (pVal[i] == ~0ULL) + Count += APINT_BITS_PER_WORD; + else { + Count += countLeadingOnes_64(pVal[i], 0); + break; + } + } + } + return Count; +} + +template +INLINE uint32_t ap_private<_AP_W, _AP_S, _AP_N>::countTrailingZeros() const { + if (isSingleWord()) + return AESL_std::min(uint32_t(CountTrailingZeros_64(VAL)), BitWidth); + uint32_t Count = 0; + uint32_t i = 0; + for (; i < _AP_N && pVal[i] == 0; ++i) + Count += APINT_BITS_PER_WORD; + if (i < _AP_N) + Count += CountTrailingZeros_64(pVal[i]); + return AESL_std::min(Count, BitWidth); +} + +template +ap_private<_AP_W, _AP_S, _AP_N> ap_private<_AP_W, _AP_S, _AP_N>::byteSwap() const { + assert(BitWidth >= 16 && BitWidth % 16 == 0 && "Cannot byteswap!"); + if (BitWidth == 16) + return ap_private<_AP_W, _AP_S, _AP_N>(/*BitWidth,*/ ByteSwap_16(uint16_t(VAL))); + else if (BitWidth == 32) + return ap_private<_AP_W, _AP_S, _AP_N>(/*BitWidth,*/ ByteSwap_32(uint32_t(VAL))); + else if (BitWidth == 48) { + uint32_t Tmp1 = uint32_t((VAL) >> 16); + Tmp1 = ByteSwap_32(Tmp1); + uint16_t Tmp2 = uint16_t(VAL); + Tmp2 = ByteSwap_16(Tmp2); + return ap_private<_AP_W, _AP_S, _AP_N>(/*BitWidth,*/ ((uint64_t(Tmp2)) << 32) | Tmp1); + } else if (BitWidth == 64) + return ap_private<_AP_W, _AP_S, _AP_N>(/*BitWidth,*/ ByteSwap_64(VAL)); + else { + ap_private<_AP_W, _AP_S, _AP_N> Result(0); + char *pByte = (char*)Result.pVal; + for (uint32_t i = 0; i < BitWidth / APINT_WORD_SIZE / 2; ++i) { + char Tmp = pByte[i]; + pByte[i] = pByte[BitWidth / APINT_WORD_SIZE - 1 - i]; + pByte[BitWidth / APINT_WORD_SIZE - i - 1] = Tmp; + } + return Result; + } +} + +template +ap_private<_AP_W, _AP_S, _AP_N> ap_private_ops::GreatestCommonDivisor(const ap_private<_AP_W, _AP_S, _AP_N>& API1, const ap_private<_AP_W, _AP_S, _AP_N>& API2) { + ap_private<_AP_W, _AP_S, _AP_N> __A = API1, __B = API2; + while (!!__B) { + ap_private<_AP_W, _AP_S, _AP_N> __T = __B; + __B = ap_private_ops::urem(__A, __B); + __A = __T; + } + return __A; +} + +template +ap_private<_AP_W, _AP_S, _AP_N> ap_private_ops::RoundDoubleToap_private(double Double, uint32_t width) { + union { + double __D; + uint64_t __I; + } __T; + __T.__D = Double; + + // Get the sign bit from the highest order bit + bool isNeg = (__T.__I) >> 63; + + // Get the 11-bit exponent and adjust for the 1023 bit bias + int64_t exp = (((__T.__I) >> 52) & 0x7ffULL) - 1023; + + // If the exponent is negative, the value is < 0 so just return 0. + if (exp < 0) + return ap_private<_AP_W, _AP_S, _AP_N>(width, 0u); + + // Extract the mantissa by clearing the top 12 bits (sign + exponent). + uint64_t mantissa = (__T.__I & (~0ULL >> 12)) | 1ULL << 52; + + // If the exponent doesn't shift all bits out of the mantissa + if (exp < 52) + return isNeg ? -ap_private<_AP_W, _AP_S, _AP_N>(width, (mantissa) >> (52 - exp)) : + ap_private<_AP_W, _AP_S, _AP_N>((mantissa) >> (52 - exp)); + + // If the client didn't provide enough bits for us to shift the mantissa into + // then the result is undefined, just return 0 + if (width <= exp - 52) + return ap_private<_AP_W, _AP_S, _AP_N>(width, 0); + + // Otherwise, we have to shift the mantissa bits up to the right location + ap_private<_AP_W, _AP_S, _AP_N> Tmp(width, mantissa); + Tmp = Tmp.shl(exp - 52); + return isNeg ? -Tmp : Tmp; +} + +/// RoundToDouble - This function convert this ap_private to a double. +/// The layout for double is as following (IEEE Standard 754): +/// -------------------------------------- +/// | Sign Exponent Fraction Bias | +/// |-------------------------------------- | +/// | 1[63] 11[62-52] 52[51-00] 1023 | +/// -------------------------------------- +template +double ap_private<_AP_W, _AP_S, _AP_N>::roundToDouble(bool isSigned) const { + + // Handle the simple case where the value is contained in one uint64_t. + if (isSingleWord() || getActiveBits() <= APINT_BITS_PER_WORD) { + uint64_t val; + if (isSingleWord()) val = VAL; + else val = pVal[0]; + if (isSigned) { + int64_t sext = ((int64_t(val)) << (64-BitWidth)) >> (64-BitWidth); + return double(sext); + } else + return double(val); + } + + // Determine if the value is negative. + bool isNeg = isSigned ? (*this)[BitWidth-1] : false; + + // Construct the absolute value if we're negative. + ap_private<_AP_W, _AP_S, _AP_N> Tmp(isNeg ? -(*this) : (*this)); + + // Figure out how many bits we're using. + uint32_t n = Tmp.getActiveBits(); + + // The exponent (without bias normalization) is just the number of bits + // we are using. Note that the sign bit is gone since we constructed the + // absolute value. + uint64_t exp = n; + + // Return infinity for exponent overflow + if (exp > 1023) { + if (!isSigned || !isNeg) + return std::numeric_limits::infinity(); + else + return -std::numeric_limits::infinity(); + } + exp += 1023; // Increment for 1023 bias + + // Number of bits in mantissa is 52. To obtain the mantissa value, we must + // extract the high 52 bits from the correct words in pVal. + uint64_t mantissa; + unsigned hiWord = whichWord(n-1); + if (hiWord == 0) { + mantissa = Tmp.pVal[0]; + if (n > 52) + (mantissa) >>= (n - 52); // shift down, we want the top 52 bits. + } else { + assert(hiWord > 0 && "High word is negative?"); + uint64_t hibits = (Tmp.pVal[hiWord]) << (52 - n % APINT_BITS_PER_WORD); + uint64_t lobits = (Tmp.pVal[hiWord-1]) >> (11 + n % APINT_BITS_PER_WORD); + mantissa = hibits | lobits; + } + + // The leading bit of mantissa is implicit, so get rid of it. + uint64_t sign = isNeg ? (1ULL << (APINT_BITS_PER_WORD - 1)) : 0; + union { + double __D; + uint64_t __I; + } __T; + __T.__I = sign | ((exp) << 52) | mantissa; + return __T.__D; +} + +// Square Root - this method computes and returns the square root of "this". +// Three mechanisms are used for computation. For small values (<= 5 bits), +// a table lookup is done. This gets some performance for common cases. For +// values using less than 52 bits, the value is converted to double and then +// the libc sqrt function is called. The result is rounded and then converted +// back to a uint64_t which is then used to construct the result. Finally, +// the Babylonian method for computing square roots is used. +template +ap_private<_AP_W, _AP_S, _AP_N> ap_private<_AP_W, _AP_S, _AP_N>::sqrt() const { + + // Determine the magnitude of the value. + uint32_t magnitude = getActiveBits(); + + // Use a fast table for some small values. This also gets rid of some + // rounding errors in libc sqrt for small values. + if (magnitude <= 5) { + static const uint8_t results[32] = { + /* 0 */ 0, + /* 1- 2 */ 1, 1, + /* 3- 6 */ 2, 2, 2, 2, + /* 7-12 */ 3, 3, 3, 3, 3, 3, + /* 13-20 */ 4, 4, 4, 4, 4, 4, 4, 4, + /* 21-30 */ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + /* 31 */ 6 + }; + return ap_private<_AP_W, _AP_S, _AP_N>(/*BitWidth,*/ results[ (isSingleWord() ? VAL : pVal[0]) ]); + } + + // If the magnitude of the value fits in less than 52 bits (the precision of + // an IEEE double precision floating point value), then we can use the + // libc sqrt function which will probably use a hardware sqrt computation. + // This should be faster than the algorithm below. + if (magnitude < 52) { +#ifdef _MSC_VER + // Amazingly, VC++ doesn't have round(). + return ap_private<_AP_W, _AP_S, _AP_N>(/*BitWidth,*/ + uint64_t(::sqrt(double(isSingleWord()?VAL:pVal[0]))) + 0.5); +#else + return ap_private<_AP_W, _AP_S, _AP_N>(/*BitWidth,*/ + uint64_t(::round(::sqrt(double(isSingleWord()?VAL:pVal[0]))))); +#endif + } + + // Okay, all the short cuts are exhausted. We must compute it. The following + // is a classical Babylonian method for computing the square root. This code + // was adapted to APINt from a wikipedia article on such computations. + // See http://www.wikipedia.org/ and go to the page named + // Calculate_an_integer_square_root. + uint32_t nbits = BitWidth, i = 4; + ap_private<_AP_W, _AP_S, _AP_N> testy(16); + ap_private<_AP_W, _AP_S, _AP_N> x_old(/*BitWidth,*/ 1); + ap_private<_AP_W, _AP_S, _AP_N> x_new(0); + ap_private<_AP_W, _AP_S, _AP_N> two(/*BitWidth,*/ 2); + + // Select a good starting value using binary logarithms. + for (;; i += 2, testy = testy.shl(2)) + if (i >= nbits || this->ule(testy)) { + x_old = x_old.shl(i / 2); + break; + } + + // Use the Babylonian method to arrive at the integer square root: + for (;;) { + x_new = (this->udiv(x_old) + x_old).udiv(two); + if (x_old.ule(x_new)) + break; + x_old = x_new; + } + + // Make sure we return the closest approximation + // NOTE: The rounding calculation below is correct. It will produce an + // off-by-one discrepancy with results from pari/gp. That discrepancy has been + // determined to be a rounding issue with pari/gp as it begins to use a + // floating point representation after 192 bits. There are no discrepancies + // between this algorithm and pari/gp for bit widths < 192 bits. + ap_private<_AP_W, _AP_S, _AP_N> square(x_old * x_old); + ap_private<_AP_W, _AP_S, _AP_N> nextSquare((x_old + 1) * (x_old +1)); + if (this->ult(square)) + return x_old; + else if (this->ule(nextSquare)) { + ap_private<_AP_W, _AP_S, _AP_N> midpoint((nextSquare - square).udiv(two)); + ap_private<_AP_W, _AP_S, _AP_N> offset(*this - square); + if (offset.ult(midpoint)) + return x_old; + else + return x_old + 1; + } else + assert(0 && "Error in ap_private<_AP_W, _AP_S, _AP_N>::sqrt computation"); + return x_old + 1; +} + +/// Implementation of Knuth's Algorithm D (Division of nonnegative integers) +/// from "Art of Computer Programming, Volume 2", section 4.3.1, p. 272. The +/// variables here have the same names as in the algorithm. Comments explain +/// the algorithm and any deviation from it. +static void KnuthDiv(uint32_t *u, uint32_t *v, uint32_t *q, uint32_t* r, + uint32_t m, uint32_t n) { + assert(u && "Must provide dividend"); + assert(v && "Must provide divisor"); + assert(q && "Must provide quotient"); + assert(u != v && u != q && v != q && "Must us different memory"); + assert(n>1 && "n must be > 1"); + + // Knuth uses the value b as the base of the number system. In our case b + // is 2^31 so we just set it to -1u. + uint64_t b = uint64_t(1) << 32; + + //DEBUG(cerr << "KnuthDiv: m=" << m << " n=" << n << '\n'); + //DEBUG(cerr << "KnuthDiv: original:"); + //DEBUG(for (int i = m+n; i >=0; i--) cerr << " " << std::setbase(16) << u[i]); + //DEBUG(cerr << " by"); + //DEBUG(for (int i = n; i >0; i--) cerr << " " << std::setbase(16) << v[i-1]); + //DEBUG(cerr << '\n'); + // D1. [Normalize.] Set d = b / (v[n-1] + 1) and multiply all the digits of + // u and v by d. Note that we have taken Knuth's advice here to use a power + // of 2 value for d such that d * v[n-1] >= b/2 (b is the base). A power of + // 2 allows us to shift instead of multiply and it is easy to determine the + // shift amount from the leading zeros. We are basically normalizing the u + // and v so that its high bits are shifted to the top of v's range without + // overflow. Note that this can require an extra word in u so that u must + // be of length m+n+1. + uint32_t shift = CountLeadingZeros_32(v[n-1]); + uint32_t v_carry = 0; + uint32_t u_carry = 0; + if (shift) { + for (uint32_t i = 0; i < m+n; ++i) { + uint32_t u_tmp = (u[i]) >> (32 - shift); + u[i] = ((u[i]) << (shift)) | u_carry; + u_carry = u_tmp; + } + for (uint32_t i = 0; i < n; ++i) { + uint32_t v_tmp = (v[i]) >> (32 - shift); + v[i] = ((v[i]) << (shift)) | v_carry; + v_carry = v_tmp; + } + } + u[m+n] = u_carry; + //DEBUG(cerr << "KnuthDiv: normal:"); + //DEBUG(for (int i = m+n; i >=0; i--) cerr << " " << std::setbase(16) << u[i]); + //DEBUG(cerr << " by"); + //DEBUG(for (int i = n; i >0; i--) cerr << " " << std::setbase(16) << v[i-1]); + //DEBUG(cerr << '\n'); + + // D2. [Initialize j.] Set j to m. This is the loop counter over the places. + int j = m; + do { + //DEBUG(cerr << "KnuthDiv: quotient digit #" << j << '\n'); + // D3. [Calculate q'.]. + // Set qp = (u[j+n]*b + u[j+n-1]) / v[n-1]. (qp=qprime=q') + // Set rp = (u[j+n]*b + u[j+n-1]) % v[n-1]. (rp=rprime=r') + // Now test if qp == b or qp*v[n-2] > b*rp + u[j+n-2]; if so, decrease + // qp by 1, inrease rp by v[n-1], and repeat this test if rp < b. The test + // on v[n-2] determines at high speed most of the cases in which the trial + // value qp is one too large, and it eliminates all cases where qp is two + // too large. + uint64_t dividend = ((uint64_t(u[j+n]) << 32) + u[j+n-1]); + //DEBUG(cerr << "KnuthDiv: dividend == " << dividend << '\n'); + uint64_t qp = dividend / v[n-1]; + uint64_t rp = dividend % v[n-1]; + if (qp == b || qp*v[n-2] > b*rp + u[j+n-2]) { + qp--; + rp += v[n-1]; + if (rp < b && (qp == b || qp*v[n-2] > b*rp + u[j+n-2])) + qp--; + } + //DEBUG(cerr << "KnuthDiv: qp == " << qp << ", rp == " << rp << '\n'); + + // D4. [Multiply and subtract.] Replace (u[j+n]u[j+n-1]...u[j]) with + // (u[j+n]u[j+n-1]..u[j]) - qp * (v[n-1]...v[1]v[0]). This computation + // consists of a simple multiplication by a one-place number, combined with + // a subtraction. + bool isNeg = false; + for (uint32_t i = 0; i < n; ++i) { + uint64_t u_tmp = uint64_t(u[j+i]) | ((uint64_t(u[j+i+1])) << 32); + uint64_t subtrahend = uint64_t(qp) * uint64_t(v[i]); + bool borrow = subtrahend > u_tmp; + /*DEBUG(cerr << "KnuthDiv: u_tmp == " << u_tmp + << ", subtrahend == " << subtrahend + << ", borrow = " << borrow << '\n');*/ + + uint64_t result = u_tmp - subtrahend; + uint32_t k = j + i; + u[k++] = (uint32_t)(result & (b-1)); // subtract low word + u[k++] = (uint32_t)((result) >> 32); // subtract high word + while (borrow && k <= m+n) { // deal with borrow to the left + borrow = u[k] == 0; + u[k]--; + k++; + } + isNeg |= borrow; + /*DEBUG(cerr << "KnuthDiv: u[j+i] == " << u[j+i] << ", u[j+i+1] == " << + u[j+i+1] << '\n');*/ + } + /*DEBUG(cerr << "KnuthDiv: after subtraction:"); + DEBUG(for (int i = m+n; i >=0; i--) cerr << " " << u[i]); + DEBUG(cerr << '\n');*/ + // The digits (u[j+n]...u[j]) should be kept positive; if the result of + // this step is actually negative, (u[j+n]...u[j]) should be left as the + // true value plus b**(n+1), namely as the b's complement of + // the true value, and a "borrow" to the left should be remembered. + // + if (isNeg) { + bool carry = true; // true because b's complement is "complement + 1" + for (uint32_t i = 0; i <= m+n; ++i) { + u[i] = ~u[i] + carry; // b's complement + carry = carry && u[i] == 0; + } + } + /*DEBUG(cerr << "KnuthDiv: after complement:"); + DEBUG(for (int i = m+n; i >=0; i--) cerr << " " << u[i]); + DEBUG(cerr << '\n');*/ + + // D5. [Test remainder.] Set q[j] = qp. If the result of step D4 was + // negative, go to step D6; otherwise go on to step D7. + q[j] = (uint32_t)qp; + if (isNeg) { + // D6. [Add back]. The probability that this step is necessary is very + // small, on the order of only 2/b. Make sure that test data accounts for + // this possibility. Decrease q[j] by 1 + q[j]--; + // and add (0v[n-1]...v[1]v[0]) to (u[j+n]u[j+n-1]...u[j+1]u[j]). + // A carry will occur to the left of u[j+n], and it should be ignored + // since it cancels with the borrow that occurred in D4. + bool carry = false; + for (uint32_t i = 0; i < n; i++) { + uint32_t limit = AESL_std::min(u[j+i],v[i]); + u[j+i] += v[i] + carry; + carry = u[j+i] < limit || (carry && u[j+i] == limit); + } + u[j+n] += carry; + } + /*DEBUG(cerr << "KnuthDiv: after correction:"); + DEBUG(for (int i = m+n; i >=0; i--) cerr <<" " << u[i]); + DEBUG(cerr << "\nKnuthDiv: digit result = " << q[j] << '\n');*/ + + // D7. [Loop on j.] Decrease j by one. Now if j >= 0, go back to D3. + } while (--j >= 0); + + /*DEBUG(cerr << "KnuthDiv: quotient:"); + DEBUG(for (int i = m; i >=0; i--) cerr <<" " << q[i]); + DEBUG(cerr << '\n');*/ + + // D8. [Unnormalize]. Now q[...] is the desired quotient, and the desired + // remainder may be obtained by dividing u[...] by d. If r is non-null we + // compute the remainder (urem uses this). + if (r) { + // The value d is expressed by the "shift" value above since we avoided + // multiplication by d by using a shift left. So, all we have to do is + // shift right here. In order to mak + if (shift) { + uint32_t carry = 0; + //DEBUG(cerr << "KnuthDiv: remainder:"); + for (int i = n-1; i >= 0; i--) { + r[i] = ((u[i]) >> (shift)) | carry; + carry = (u[i]) << (32 - shift); + //DEBUG(cerr << " " << r[i]); + } + } else { + for (int i = n-1; i >= 0; i--) { + r[i] = u[i]; + //DEBUG(cerr << " " << r[i]); + } + } + //DEBUG(cerr << '\n'); + } + //DEBUG(cerr << std::setbase(10) << '\n'); +} + +template +void divide(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, uint32_t lhsWords, + const ap_private<_AP_W, _AP_S, _AP_N>& RHS, uint32_t rhsWords, + ap_private<_AP_W, _AP_S, _AP_N> *Quotient, ap_private<_AP_W, _AP_S, _AP_N> *Remainder) { + assert(lhsWords >= rhsWords && "Fractional result"); + enum {APINT_BITS_PER_WORD=64}; + // First, compose the values into an array of 32-bit words instead of + // 64-bit words. This is a necessity of both the "short division" algorithm + // and the the Knuth "classical algorithm" which requires there to be native + // operations for +, -, and * on an m bit value with an m*2 bit result. We + // can't use 64-bit operands here because we don't have native results of + // 128-bits. Furthremore, casting the 64-bit values to 32-bit values won't + // work on large-endian machines. + uint64_t mask = ~0ull >> (sizeof(uint32_t)*8); + uint32_t n = rhsWords * 2; + uint32_t m = (lhsWords * 2) - n; + + // Allocate space for the temporary values we need either on the stack, if + // it will fit, or on the heap if it won't. + uint32_t SPACE[128]; + uint32_t *__U = 0; + uint32_t *__V = 0; + uint32_t *__Q = 0; + uint32_t *__R = 0; + if ((Remainder?4:3)*n+2*m+1 <= 128) { + __U = &SPACE[0]; + __V = &SPACE[m+n+1]; + __Q = &SPACE[(m+n+1) + n]; + if (Remainder) + __R = &SPACE[(m+n+1) + n + (m+n)]; + } else { + __U = new uint32_t[m + n + 1]; + __V = new uint32_t[n]; + __Q = new uint32_t[m+n]; + if (Remainder) + __R = new uint32_t[n]; + } + + // Initialize the dividend + memset(__U, 0, (m+n+1)*sizeof(uint32_t)); + for (unsigned i = 0; i < lhsWords; ++i) { + uint64_t tmp = (LHS.getNumWords() == 1 ? LHS.VAL : LHS.pVal[i]); + __U[i * 2] = (uint32_t)(tmp & mask); + __U[i * 2 + 1] = (tmp) >> (sizeof(uint32_t)*8); + } + __U[m+n] = 0; // this extra word is for "spill" in the Knuth algorithm. + + // Initialize the divisor + memset(__V, 0, (n)*sizeof(uint32_t)); + for (unsigned i = 0; i < rhsWords; ++i) { + uint64_t tmp = (RHS.getNumWords() == 1 ? RHS.VAL : RHS.pVal[i]); + __V[i * 2] = (uint32_t)(tmp & mask); + __V[i * 2 + 1] = (tmp) >> (sizeof(uint32_t)*8); + } + + // initialize the quotient and remainder + memset(__Q, 0, (m+n) * sizeof(uint32_t)); + if (Remainder) + memset(__R, 0, n * sizeof(uint32_t)); + + // Now, adjust m and n for the Knuth division. n is the number of words in + // the divisor. m is the number of words by which the dividend exceeds the + // divisor (i.e. m+n is the length of the dividend). These sizes must not + // contain any zero words or the Knuth algorithm fails. + for (unsigned i = n; i > 0 && __V[i-1] == 0; i--) { + n--; + m++; + } + for (unsigned i = m+n; i > 0 && __U[i-1] == 0; i--) + m--; + + // If we're left with only a single word for the divisor, Knuth doesn't work + // so we implement the short division algorithm here. This is much simpler + // and faster because we are certain that we can divide a 64-bit quantity + // by a 32-bit quantity at hardware speed and short division is simply a + // series of such operations. This is just like doing short division but we + // are using base 2^32 instead of base 10. + assert(n != 0 && "Divide by zero?"); + if (n == 1) { + uint32_t divisor = __V[0]; + uint32_t remainder = 0; + for (int i = m+n-1; i >= 0; i--) { + uint64_t partial_dividend = (uint64_t(remainder)) << 32 | __U[i]; + if (partial_dividend == 0) { + __Q[i] = 0; + remainder = 0; + } else if (partial_dividend < divisor) { + __Q[i] = 0; + remainder = (uint32_t)partial_dividend; + } else if (partial_dividend == divisor) { + __Q[i] = 1; + remainder = 0; + } else { + __Q[i] = (uint32_t)(partial_dividend / divisor); + remainder = (uint32_t)(partial_dividend - (__Q[i] * divisor)); + } + } + if (__R) + __R[0] = remainder; + } else { + // Now we're ready to invoke the Knuth classical divide algorithm. In this + // case n > 1. + KnuthDiv(__U, __V, __Q, __R, m, n); + } + + // If the caller wants the quotient + if (Quotient) { + // Set up the Quotient value's memory. + if (Quotient->BitWidth != LHS.BitWidth) { + if (Quotient->isSingleWord()) + Quotient->VAL = 0; + } else + Quotient->clear(); + + // The quotient is in Q. Reconstitute the quotient into Quotient's low + // order words. + if (lhsWords == 1) { + uint64_t tmp = + uint64_t(__Q[0]) | ((uint64_t(__Q[1])) << (APINT_BITS_PER_WORD / 2)); + if (Quotient->isSingleWord()) + Quotient->VAL = tmp; + else + Quotient->pVal[0] = tmp; + } else { + assert(!Quotient->isSingleWord() && "Quotient ap_private not large enough"); + for (unsigned i = 0; i < lhsWords; ++i) + Quotient->pVal[i] = + uint64_t(__Q[i*2]) | ((uint64_t(__Q[i*2+1])) << (APINT_BITS_PER_WORD / 2)); + } + Quotient->clearUnusedBits(); + } + + // If the caller wants the remainder + if (Remainder) { + // Set up the Remainder value's memory. + if (Remainder->BitWidth != RHS.BitWidth) { + if (Remainder->isSingleWord()) + Remainder->VAL = 0; + } else + Remainder->clear(); + + // The remainder is in R. Reconstitute the remainder into Remainder's low + // order words. + if (rhsWords == 1) { + uint64_t tmp = + uint64_t(__R[0]) | ((uint64_t(__R[1])) << (APINT_BITS_PER_WORD / 2)); + if (Remainder->isSingleWord()) + Remainder->VAL = tmp; + else + Remainder->pVal[0] = tmp; + } else { + assert(!Remainder->isSingleWord() && "Remainder ap_private not large enough"); + for (unsigned i = 0; i < rhsWords; ++i) + Remainder->pVal[i] = + uint64_t(__R[i*2]) | ((uint64_t(__R[i*2+1])) << (APINT_BITS_PER_WORD / 2)); + } + Remainder->clearUnusedBits(); + } + + // Clean up the memory we allocated. + if (__U != &SPACE[0]) { + delete [] __U; + delete [] __V; + delete [] __Q; + delete [] __R; + } +} + + +template +void ap_private<_AP_W, _AP_S, _AP_N>::fromString(const char *str, uint32_t slen, uint8_t radix) { + enum { numbits=_AP_W}; + // Check our assumptions here + assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) && + "Radix should be 2, 8, 10, or 16!"); + assert(str && "String is null?"); + bool isNeg = str[0] == '-'; + if (isNeg) + str++, slen--; + + //skip any leading zero + while(*str == '0' && *(str+1) != '\0') {str++; slen--;} + assert((slen <= numbits || radix != 2) && "Insufficient bit width"); + assert(((slen - 1)*3 <= numbits || radix != 8) && "Insufficient bit width"); + assert(((slen - 1)*4 <= numbits || radix != 16) && "Insufficient bit width"); + assert((((slen -1)*64)/22 <= numbits || radix != 10) && "Insufficient bit width"); + + memset(pVal, 0, _AP_N * sizeof(uint64_t)); + + // Figure out if we can shift instead of multiply + uint32_t shift = (radix == 16 ? 4 : radix == 8 ? 3 : radix == 2 ? 1 : 0); + + // Set up an ap_private for the digit to add outside the loop so we don't + // constantly construct/destruct it. + uint64_t bigVal[_AP_N]; + memset(bigVal, 0, _AP_N * sizeof(uint64_t)); + ap_private<_AP_W, _AP_S, _AP_N> apdigit(getBitWidth(), bigVal); + ap_private<_AP_W, _AP_S, _AP_N> apradix(radix); + + // Enter digit traversal loop + for (unsigned i = 0; i < slen; i++) { + // Get a digit + uint32_t digit = 0; + char cdigit = str[i]; + if (radix == 16) { +#define isxdigit(c) (((c) >= '0' && (c) <= '9') || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F')) +#define isdigit(c) ((c) >= '0' && (c) <= '9') + if (!isxdigit(cdigit)) + assert(0 && "Invalid hex digit in string"); + if (isdigit(cdigit)) + digit = cdigit - '0'; + else if (cdigit >= 'a') + digit = cdigit - 'a' + 10; + else if (cdigit >= 'A') + digit = cdigit - 'A' + 10; + else + assert(0 && "huh? we shouldn't get here"); + } else if (isdigit(cdigit)) { + digit = cdigit - '0'; + } else { + assert(0 && "Invalid character in digit string"); + } +#undef isxdigit +#undef isdigit + // Shift or multiply the value by the radix + if (shift) + *this <<= shift; + else + *this *= apradix; + + // Add in the digit we just interpreted + if (apdigit.isSingleWord()) + apdigit.VAL = digit; + else + apdigit.pVal[0] = digit; + *this += apdigit; + } + // If its negative, put it in two's complement form + if (isNeg) { + (*this)--; + this->flip(); + } + clearUnusedBits(); +} + +template +std::string ap_private<_AP_W, _AP_S, _AP_N>::toString(uint8_t radix, bool wantSigned) const { + assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) && + "Radix should be 2, 8, 10, or 16!"); + static const char *digits[] = { + "0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F" + }; + std::string result; + uint32_t bits_used = getActiveBits(); + + if (radix != 10) { + // For the 2, 8 and 16 bit cases, we can just shift instead of divide + // because the number of bits per digit (1,3 and 4 respectively) divides + // equaly. We just shift until there value is zero. + + // First, check for a zero value and just short circuit the logic below. + if (*this == (uint64_t)(0)) + result = "0"; + else { + ap_private<_AP_W, false, _AP_N> tmp(*this); + size_t insert_at = 0; + if (wantSigned && isNegative()) { + // They want to print the signed version and it is a negative value + // Flip the bits and add one to turn it into the equivalent positive + // value and put a '-' in the result. + tmp.flip(); + tmp++; + tmp.clearUnusedBitsToZero(); + result = "-"; + insert_at = 1; + } + // Just shift tmp right for each digit width until it becomes zero + uint32_t shift = (radix == 16 ? 4 : (radix == 8 ? 3 : 1)); + uint64_t mask = radix - 1; + ap_private<_AP_W, false, _AP_N> zero(0); + while (tmp.ne(zero)) { + unsigned digit = (tmp.isSingleWord() ? tmp.VAL : tmp.pVal[0]) & mask; + result.insert(insert_at, digits[digit]); + tmp = tmp.lshr(shift); + } + } + return result; + } + + ap_private<_AP_W, false, _AP_N> tmp(*this); + ap_private<_AP_W, false, _AP_N> divisor(radix); + ap_private<_AP_W, false, _AP_N> zero(0); + size_t insert_at = 0; + if (wantSigned && isNegative()) { + // They want to print the signed version and it is a negative value + // Flip the bits and add one to turn it into the equivalent positive + // value and put a '-' in the result. + tmp.flip(); + tmp++; + tmp.clearUnusedBitsToZero(); + result = "-"; + insert_at = 1; + } + if (tmp == ap_private<_AP_W, false, _AP_N>(0)) + result = "0"; + else while (tmp.ne(zero)) { + ap_private<_AP_W, false, _AP_N> APdigit(0); + ap_private<_AP_W, false, _AP_N> tmp2(0); + divide(tmp, tmp.getNumWords(), divisor, divisor.getNumWords(), &tmp2, + &APdigit); + uint32_t digit = APdigit.getZExtValue(); + assert(digit < radix && "divide failed"); + result.insert(insert_at,digits[digit]); + tmp = tmp2; + } + + return result; +} + +// This implements a variety of operations on a representation of +// arbitrary precision, two's-complement, bignum integer values. + +/* Assumed by lowHalf, highHalf, partMSB and partLSB. A fairly safe + and unrestricting assumption. */ + +/* Some handy functions local to this file. */ + +template +void divide(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, uint32_t lhsWords, + uint64_t RHS, + ap_private<_AP_W, _AP_S, _AP_N> *Quotient, ap_private<_AP_W, _AP_S, _AP_N> *Remainder) { + uint32_t rhsWords=1; + assert(lhsWords >= rhsWords && "Fractional result"); + enum {APINT_BITS_PER_WORD=64}; + // First, compose the values into an array of 32-bit words instead of + // 64-bit words. This is a necessity of both the "short division" algorithm + // and the the Knuth "classical algorithm" which requires there to be native + // operations for +, -, and * on an m bit value with an m*2 bit result. We + // can't use 64-bit operands here because we don't have native results of + // 128-bits. Furthremore, casting the 64-bit values to 32-bit values won't + // work on large-endian machines. + uint64_t mask = ~0ull >> (sizeof(uint32_t)*8); + uint32_t n = 2; + uint32_t m = (lhsWords * 2) - n; + + // Allocate space for the temporary values we need either on the stack, if + // it will fit, or on the heap if it won't. + uint32_t SPACE[128]; + uint32_t *__U = 0; + uint32_t *__V = 0; + uint32_t *__Q = 0; + uint32_t *__R = 0; + if ((Remainder?4:3)*n+2*m+1 <= 128) { + __U = &SPACE[0]; + __V = &SPACE[m+n+1]; + __Q = &SPACE[(m+n+1) + n]; + if (Remainder) + __R = &SPACE[(m+n+1) + n + (m+n)]; + } else { + __U = new uint32_t[m + n + 1]; + __V = new uint32_t[n]; + __Q = new uint32_t[m+n]; + if (Remainder) + __R = new uint32_t[n]; + } + + // Initialize the dividend + memset(__U, 0, (m+n+1)*sizeof(uint32_t)); + for (unsigned i = 0; i < lhsWords; ++i) { + uint64_t tmp = (LHS.getNumWords() == 1 ? LHS.VAL : LHS.pVal[i]); + __U[i * 2] = tmp & mask; + __U[i * 2 + 1] = (tmp) >> (sizeof(uint32_t)*8); + } + __U[m+n] = 0; // this extra word is for "spill" in the Knuth algorithm. + + // Initialize the divisor + memset(__V, 0, (n)*sizeof(uint32_t)); + __V[0] = RHS & mask; + __V[1] = (RHS) >> (sizeof(uint32_t)*8); + + // initialize the quotient and remainder + memset(__Q, 0, (m+n) * sizeof(uint32_t)); + if (Remainder) + memset(__R, 0, n * sizeof(uint32_t)); + + // Now, adjust m and n for the Knuth division. n is the number of words in + // the divisor. m is the number of words by which the dividend exceeds the + // divisor (i.e. m+n is the length of the dividend). These sizes must not + // contain any zero words or the Knuth algorithm fails. + for (unsigned i = n; i > 0 && __V[i-1] == 0; i--) { + n--; + m++; + } + for (unsigned i = m+n; i > 0 && __U[i-1] == 0; i--) + m--; + + // If we're left with only a single word for the divisor, Knuth doesn't work + // so we implement the short division algorithm here. This is much simpler + // and faster because we are certain that we can divide a 64-bit quantity + // by a 32-bit quantity at hardware speed and short division is simply a + // series of such operations. This is just like doing short division but we + // are using base 2^32 instead of base 10. + assert(n != 0 && "Divide by zero?"); + if (n == 1) { + uint32_t divisor = __V[0]; + uint32_t remainder = 0; + for (int i = m+n-1; i >= 0; i--) { + uint64_t partial_dividend = (uint64_t(remainder)) << 32 | __U[i]; + if (partial_dividend == 0) { + __Q[i] = 0; + remainder = 0; + } else if (partial_dividend < divisor) { + __Q[i] = 0; + remainder = partial_dividend; + } else if (partial_dividend == divisor) { + __Q[i] = 1; + remainder = 0; + } else { + __Q[i] = partial_dividend / divisor; + remainder = partial_dividend - (__Q[i] * divisor); + } + } + if (__R) + __R[0] = remainder; + } else { + // Now we're ready to invoke the Knuth classical divide algorithm. In this + // case n > 1. + KnuthDiv(__U, __V, __Q, __R, m, n); + } + + // If the caller wants the quotient + if (Quotient) { + // Set up the Quotient value's memory. + if (Quotient->BitWidth != LHS.BitWidth) { + if (Quotient->isSingleWord()) + Quotient->VAL = 0; + else + delete [] Quotient->pVal; + } else + Quotient->clear(); + + // The quotient is in Q. Reconstitute the quotient into Quotient's low + // order words. + if (lhsWords == 1) { + uint64_t tmp = + uint64_t(__Q[0]) | ((uint64_t(__Q[1])) << (APINT_BITS_PER_WORD / 2)); + if (Quotient->isSingleWord()) + Quotient->VAL = tmp; + else + Quotient->pVal[0] = tmp; + } else { + assert(!Quotient->isSingleWord() && "Quotient ap_private not large enough"); + for (unsigned i = 0; i < lhsWords; ++i) + Quotient->pVal[i] = + uint64_t(__Q[i*2]) | ((uint64_t(__Q[i*2+1])) << (APINT_BITS_PER_WORD / 2)); + } + Quotient->clearUnusedBits(); + } + + // If the caller wants the remainder + if (Remainder) { + // Set up the Remainder value's memory. + if (Remainder->BitWidth != 64 /* RHS.BitWidth */) { + if (Remainder->isSingleWord()) + Remainder->VAL = 0; + } else + Remainder->clear(); + + // The remainder is in __R. Reconstitute the remainder into Remainder's low + // order words. + if (rhsWords == 1) { + uint64_t tmp = + uint64_t(__R[0]) | ((uint64_t(__R[1])) << (APINT_BITS_PER_WORD / 2)); + if (Remainder->isSingleWord()) + Remainder->VAL = tmp; + else + Remainder->pVal[0] = tmp; + } else { + assert(!Remainder->isSingleWord() && "Remainder ap_private not large enough"); + for (unsigned i = 0; i < rhsWords; ++i) + Remainder->pVal[i] = + uint64_t(__R[i*2]) | ((uint64_t(__R[i*2+1])) << (APINT_BITS_PER_WORD / 2)); + } + Remainder->clearUnusedBits(); + } + + // Clean up the memory we allocated. + if (__U != &SPACE[0]) { + delete [] __U; + delete [] __V; + delete [] __Q; + delete [] __R; + } +} + +//When bitwidth < 64 +template class ap_private <_AP_W, _AP_S, 1> { +#ifdef _MSC_VER +#pragma warning( disable : 4521 4522 ) +#endif +public: + typedef typename retval<_AP_S>::Type ValType; + template + struct RType { + enum { + _AP_N =1, + mult_w = _AP_W+_AP_W2, + mult_s = _AP_S||_AP_S2, //?? why + plus_w = AP_MAX(_AP_W+(_AP_S2&&!_AP_S),_AP_W2+(_AP_S&&!_AP_S2))+1, //shouldn't it be AP_MAX(_AP_W,_AP_W2)+!(_AP_S^_AP_S2)+1 ???? + plus_s = _AP_S||_AP_S2, + minus_w = AP_MAX(_AP_W+(_AP_S2&&!_AP_S),_AP_W2+(_AP_S&&!_AP_S2))+1, + minus_s = true, + div_w = _AP_W+_AP_S2, + div_s = _AP_S||_AP_S2, + mod_w = AP_MIN(_AP_W,_AP_W2+(!_AP_S2&&_AP_S)), + mod_s = _AP_S, + logic_w = AP_MAX(_AP_W+(_AP_S2&&!_AP_S),_AP_W2+(_AP_S&&!_AP_S2)), + logic_s = _AP_S||_AP_S2 + }; + typedef ap_private mult; + typedef ap_private plus; + typedef ap_private minus; + typedef ap_private logic; + typedef ap_private div; + typedef ap_private mod; + typedef ap_private<_AP_W, _AP_S> arg1; + typedef bool reduce; + }; + enum { APINT_BITS_PER_WORD = 64}; + enum { excess_bits = (_AP_W%APINT_BITS_PER_WORD) ? APINT_BITS_PER_WORD -(_AP_W%APINT_BITS_PER_WORD) : 0}; + static const uint64_t mask = ((uint64_t)~0ULL >> (excess_bits)); + static const uint64_t not_mask = ~mask; + static const uint64_t sign_bit_mask = 1ULL << (APINT_BITS_PER_WORD-1); + template struct sign_ext_mask { static const uint64_t mask=~0ULL<<_AP_W1;}; + + enum { BitWidth=_AP_W}; + uint64_t VAL; ///< Used to store the <= 64 bits integer value. + const uint64_t *const pVal; + + INLINE uint32_t getBitWidth() const { + return BitWidth; + } + + template + ap_private<_AP_W, _AP_S, 1>& operator=(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { + VAL = RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + + template + ap_private<_AP_W, _AP_S, 1>& operator=(const volatile ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { + VAL = RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + + template + ap_private<_AP_W, _AP_S, 1>& operator=(const ap_private<_AP_W1, _AP_S1, 1>& RHS) { + VAL = RHS.VAL; + clearUnusedBits(); + return *this; + } + + template + ap_private<_AP_W, _AP_S, 1>& operator=(const volatile ap_private<_AP_W1, _AP_S1, 1>& RHS) { + VAL = RHS.VAL; + clearUnusedBits(); + return *this; + } + + volatile ap_private& operator=(const ap_private& RHS) volatile { + // Don't do anything for X = X + VAL = RHS.VAL; // No need to check because no harm done by copying. + return *this; + } + ap_private& operator=(const ap_private& RHS) { + // Don't do anything for X = X + VAL = RHS.VAL; // No need to check because no harm done by copying. + return *this; + } + + volatile ap_private& operator=(const volatile ap_private& RHS) volatile { + // Don't do anything for X = X + VAL = RHS.VAL; // No need to check because no harm done by copying. + return *this; + } + ap_private& operator=(const volatile ap_private& RHS) { + // Don't do anything for X = X + VAL = RHS.VAL; // No need to check because no harm done by copying. + return *this; + } + + template + INLINE ap_private& operator = (const ap_range_ref<_AP_W2, _AP_S2>& op2) { + *this = ap_private<_AP_W2, false>(op2); + return *this; + } + + explicit INLINE ap_private(uint64_t* val) : VAL(val[0]), pVal(&VAL){ + clearUnusedBits(); + } + + INLINE bool isSingleWord() const { return true; } + + INLINE void fromString(const char *strStart, uint32_t slen, + uint8_t radix, int offset=0) { + // Check our assumptions here + assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) && + "Radix should be 2, 8, 10, or 16!"); + assert(strStart && "String is null?"); + strStart+=offset; + switch(radix) { + case 2: + // sscanf(strStart,"%b",&VAL); + VAL = *strStart =='1' ? ~0ULL : 0; + for (;*strStart; ++strStart) { + assert((*strStart=='0'|| *strStart=='1')&&("Wrong binary number") ); + VAL <<=1; + VAL |= (*strStart-'0'); + } + break; + case 8: +#if __WIN32__ + sscanf(strStart,"%I64o",&VAL); +#else + +#if defined __x86_64__ + sscanf(strStart,"%lo",&VAL); +#else + sscanf(strStart,"%llo",&VAL); +#endif + +#endif + break; + case 10: +#if __WIN32__ + sscanf(strStart,"%I64u",&VAL); +#else + +#if defined __x86_64__ + sscanf(strStart,"%lu",&VAL); +#else + sscanf(strStart,"%llu",&VAL); +#endif + +#endif + break; + case 16: +#if __WIN32__ + sscanf(strStart,"%I64x",&VAL); +#else + +#if defined __x86_64__ + sscanf(strStart,"%lx",&VAL); +#else + sscanf(strStart,"%llx",&VAL); +#endif + +#endif + break; + default: + assert(true && "Unknown radix"); + // error + } + clearUnusedBits(); + } + + INLINE ap_private() : pVal(&VAL){VAL = 0ULL;} + +#define CTOR(TYPE) \ + INLINE ap_private(TYPE v) : VAL((uint64_t)v), pVal(&VAL) { \ + clearUnusedBits(); \ + } + CTOR(int) + CTOR(bool) + CTOR(signed char) + CTOR(unsigned char) + CTOR(short) + CTOR(unsigned short) + CTOR(unsigned int) + CTOR(long) + CTOR(unsigned long) + CTOR(unsigned long long) + CTOR(long long) + CTOR(float) + CTOR(double) +#undef CTOR + ap_private(uint32_t numWords, const uint64_t bigVal[]): VAL(bigVal[0]), pVal(&VAL) {clearUnusedBits();} + + ap_private(const std::string& val, uint8_t radix=2, int base=0, int offset=0): VAL(0), pVal(&VAL) { + assert(!val.empty() && "String empty?"); + fromString(val.c_str()+base, val.size()-base, radix); + } + + ap_private(const char strStart[], uint32_t slen, uint8_t radix, int base=0, int offset=0) : VAL(0), pVal(&VAL) { + fromString(strStart+base, slen-base, radix, offset); + } + + ap_private(const ap_private& that) : VAL(that.VAL), pVal(&VAL) { + clearUnusedBits(); + } + + template + ap_private(const ap_private<_AP_W1, _AP_S1, 1>& that) : VAL(that.VAL), pVal(&VAL) { + clearUnusedBits(); + } + + template + ap_private(const ap_private<_AP_W1, _AP_S1, _AP_N1>& that) : VAL(that.pVal[0]), pVal(&VAL) { + clearUnusedBits(); + } + + template + ap_private(const volatile ap_private<_AP_W1, _AP_S1, _AP_N1>& that) : VAL(that.pVal[0]), pVal(&VAL) { + clearUnusedBits(); + } + +#if 0 +template + explicit ap_private(const ap_private<_AP_W1, true, 1+_AP_W1/64>& that) + : VAL((_AP_W1>_AP_W) ? that.VAL & mask : ((1ULL<<(_AP_W1-1)&that.pVal[0]) ? sign_ext_mask<_AP_W1>::mask | that.VAL : that.pVal[0])), pVal(&VAL) {} + +template + explicit ap_private(const ap_private<_AP_W1, false, (_AP_W1+63)/64>& that) + : VAL(that.VAL & mask), pVal(&VAL) {} +#endif + + explicit ap_private(const char* val) : pVal(&VAL) { + std::string str(val); + uint32_t strLen = str.length(); + const char *strp = str.c_str(); + uint32_t offset = 0; + uint32_t base = 0; + bool neg = false; + uint32_t radix = 10; + ap_parse_sign(strp, base, neg); + ap_parse_prefix(strp + base, offset, radix); + + if ((radix != 10 && neg) || + (strLen - base - offset <= 0) || + InvalidDigit(strp, strLen, base + offset, radix)) { + fprintf(stderr, "invalid character string %s !\n", val); + assert(0); + } + + ap_private<_AP_W, _AP_S> ap_private_val(str.c_str(), strLen, radix, base, offset); + if (neg) + ap_private_val = -ap_private_val; + operator = (ap_private_val); + } + + ap_private(const char* val, signed char rd): pVal(&VAL) { + std::string str(val); + uint32_t strLen = str.length(); + const char *strp = str.c_str(); + uint32_t offset = 0; + uint32_t base = 0; + uint32_t radix = rd; + bool neg = false; + ap_parse_sign(strp, base, neg); + ap_parse_prefix(strp + base, offset, radix); + + if ((radix != 10 && neg) || + (strLen - base - offset <= 0) || + InvalidDigit(strp, strLen, base + offset, radix)) { + fprintf(stderr, "invalid character string %s !\n", val); + assert(0); + } + + uint32_t bitsNeeded = ap_private<_AP_W, _AP_S>::getBitsNeeded(strp, strLen, radix); + ap_private<_AP_W, _AP_S> ap_private_val(strp , strLen, radix, base, offset); + //ap_private<_AP_W, _AP_S> ap_private_val(bitsNeeded, strp , strLen, radix, base, offset); + if (strp[0] == '-') + ap_private_val = -ap_private_val; + operator = (ap_private_val); + } + + INLINE bool isNegative() const { + static const uint64_t sign_mask = 1ULL << (_AP_W-1); + return _AP_S && (sign_mask & VAL); + } + + INLINE bool isPositive() const { + return !isNegative(); + } + + INLINE bool isStrictlyPositive() const { + return !isNegative() && VAL!=0; + } + + INLINE bool isAllOnesValue() const { + return (mask & VAL) == mask; + } + + template + INLINE bool operator==(const ap_private<_AP_W1, _AP_S1, 1>& RHS) const { + return (VAL == RHS.VAL); + } + + INLINE bool operator==(const ap_private<_AP_W, _AP_S>& RHS) const { return VAL == RHS.VAL; } + INLINE bool operator==(const ap_private<_AP_W, !_AP_S>& RHS) const { return getVal() == RHS.getVal(); } + INLINE bool operator==(uint64_t Val) const { return (VAL == Val); } + INLINE bool operator!=(uint64_t Val) const { return (VAL != Val); } + INLINE bool operator!=(const ap_private<_AP_W, _AP_S>& RHS) const { return VAL != RHS.VAL; } + INLINE bool operator!=(const ap_private<_AP_W, !_AP_S>& RHS) const { return getVal() != RHS.getVal(); } + const ap_private operator++() { ++VAL; clearUnusedBits(); return *this; } + const ap_private operator--(int) { + ap_private orig(*this); + --VAL; clearUnusedBits(); + return orig; + } + const ap_private operator--() { --VAL; clearUnusedBits(); return *this;} + INLINE bool operator !() const { return !VAL;} + + const ap_private operator++(int) { + ap_private orig(*this); + VAL++; clearUnusedBits(); + return orig; + } + + const ap_private operator~() {return ap_private(~VAL);} + INLINE typename RType<1,false>::minus operator-() const { + return ap_private<1,false>(0) - (*this); + } + + INLINE std::string toString(uint8_t radix, bool wantSigned) const ; + INLINE std::string toStringUnsigned(uint8_t radix = 10) const { + return toString(radix, false); + } + INLINE std::string toStringSigned(uint8_t radix = 10) const { + return toString(radix, true); + } + INLINE void clear() { + VAL=0; + } + INLINE ap_private& clear(uint32_t bitPosition) { VAL &= ~(1ULL<<(bitPosition)); clearUnusedBits(); return *this;} + + INLINE ap_private ashr(uint32_t shiftAmt) const { + enum {excess_bits = APINT_BITS_PER_WORD - BitWidth}; + if (_AP_S) + return ap_private((shiftAmt == BitWidth) ? 0 : ((int64_t)VAL) >> (shiftAmt)); + else + return ap_private((shiftAmt == BitWidth) ? 0 : (VAL) >> (shiftAmt)); + } + + INLINE ap_private lshr(uint32_t shiftAmt) const { + return ap_private((shiftAmt == BitWidth) ? ap_private(0) : ap_private((VAL&mask) >> (shiftAmt))); + } + + INLINE ap_private shl(uint32_t shiftAmt) const { + if (shiftAmt > BitWidth) { + if (!isNegative()) + return ap_private(0); + else return ap_private(-1); + } + if (shiftAmt == BitWidth) return ap_private(0); + else return ap_private((VAL) << (shiftAmt)); + //return ap_private((shiftAmt == BitWidth) ? ap_private(0ULL) : ap_private(VAL << shiftAmt)); + } + + INLINE int64_t getSExtValue() const { + return VAL; + } + + INLINE uint64_t getZExtValue() const { + return VAL & mask; + } + + template + INLINE ap_private(const ap_range_ref<_AP_W2,_AP_S2>& ref) : pVal(&VAL) { + *this=ref.get(); + } + + template + INLINE ap_private(const ap_bit_ref<_AP_W2,_AP_S2>& ref) : pVal(&VAL) { + *this = ((uint64_t)(bool)ref); + } + + template + INLINE ap_private(const ap_concat_ref<_AP_W2, _AP_T2,_AP_W3, _AP_T3>& ref) : pVal(&VAL) { + *this=ref.get(); + } + + template + INLINE ap_private(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2> &val) : pVal(&VAL) { + *this = ((val.operator ap_private<_AP_W2, false> ())); + } + + template + INLINE ap_private(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2> &val) : pVal(&VAL) { + *this = (uint64_t)(bool)val; + } + + INLINE void write(const ap_private<_AP_W, _AP_S>& op2) volatile { + *this = (op2); + } + + //Explicit conversions to C interger types + //----------------------------------------------------------- + ValType getVal() const { + return VAL; + } + operator ValType () const { + return getVal(); + } + INLINE int to_int() const { + // ap_private<64 /* _AP_W */, _AP_S> res(V); + return (int) getVal(); + } + + INLINE unsigned to_uint() const { + return (unsigned) getVal(); + } + + INLINE long to_long() const { + return (long) getVal(); + } + + INLINE unsigned long to_ulong() const { + return (unsigned long) getVal(); + } + + INLINE ap_slong to_int64() const { + return (ap_slong) getVal(); + } + + INLINE ap_ulong to_uint64() const { + return (ap_ulong) getVal(); + } + + INLINE double to_double() const { + if (isNegative()) + return roundToDouble(true); + else + return roundToDouble(false); + } + + INLINE bool isMinValue() const { return VAL == 0;} + template INLINE ap_private& operator&=(const ap_private<_AP_W1, _AP_S1>& RHS) { + VAL = VAL&RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + + template INLINE ap_private& operator|=(const ap_private<_AP_W1, _AP_S1>& RHS) { + VAL = VAL|RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + + template INLINE ap_private& operator^=(const ap_private<_AP_W1, _AP_S1>& RHS){ + VAL = VAL^RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + + template INLINE ap_private& operator*=(const ap_private<_AP_W1, _AP_S1>& RHS){ + VAL = VAL*RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + + template INLINE ap_private& operator+=(const ap_private<_AP_W1, _AP_S1>& RHS){ + VAL = VAL+RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + + template INLINE ap_private& operator-=(const ap_private<_AP_W1, _AP_S1>& RHS){ + VAL = VAL-RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + INLINE const ap_private& operator<<=(uint32_t shiftAmt) { VAL<<=shiftAmt; clearUnusedBits(); return *this; } + + template INLINE typename RType<_AP_W1, _AP_S1>::logic operator&(const ap_private<_AP_W1, _AP_S1>& RHS) const { + if (RType<_AP_W1, _AP_S1>::logic_w <= 64) { + typename RType<_AP_W1, _AP_S1>::logic Ret(VAL & RHS.VAL); + return Ret; + } else { + typename RType<_AP_W1, _AP_S1>::logic Ret = *this; + return Ret & RHS; + } + } + + template INLINE typename RType<_AP_W1, _AP_S1>::logic operator^(const ap_private<_AP_W1, _AP_S1>& RHS) const { + if (RType<_AP_W1, _AP_S1>::logic_w <= 64) { + typename RType<_AP_W1, _AP_S1>::logic Ret(VAL ^ RHS.VAL); + return Ret; + } else { + typename RType<_AP_W1, _AP_S1>::logic Ret = *this; + return Ret ^ RHS; + } + } + + template INLINE typename RType<_AP_W1, _AP_S1>::logic operator|(const ap_private<_AP_W1, _AP_S1>& RHS) const { + if (RType<_AP_W1, _AP_S1>::logic_w <= 64) { + typename RType<_AP_W1, _AP_S1>::logic Ret(VAL | RHS.VAL); + return Ret; + } else { + typename RType<_AP_W1, _AP_S1>::logic Ret = *this; + return Ret | RHS; + } + } + + INLINE ap_private<_AP_W, _AP_S> And(const ap_private<_AP_W, _AP_S>& RHS) const { + return ap_private<_AP_W, _AP_S>(VAL & RHS.VAL); + } + + INLINE ap_private<_AP_W, _AP_S> Or(const ap_private<_AP_W, _AP_S>& RHS) const { + return ap_private<_AP_W, _AP_S>(VAL | RHS.VAL); + } + + INLINE ap_private<_AP_W, _AP_S> Xor(const ap_private<_AP_W, _AP_S>& RHS) const { + return ap_private<_AP_W, _AP_S>(VAL ^ RHS.VAL); + } +#if 1 + template + INLINE typename RType<_AP_W1, _AP_S1>::mult operator*(const ap_private<_AP_W1, _AP_S1>& RHS) const { + if (RType<_AP_W1, _AP_S1>::mult_w <= 64) { + typename RType<_AP_W1, _AP_S1>::mult Result(VAL * RHS.VAL); + return Result; + } else { + typename RType<_AP_W1, _AP_S1>::mult Result = typename RType<_AP_W1, _AP_S1>::mult(*this); + Result *= RHS; + return Result; + } + } +#endif + INLINE ap_private<_AP_W, _AP_S> Mul(const ap_private<_AP_W, _AP_S>& RHS) const { + return ap_private<_AP_W, _AP_S>(VAL * RHS.VAL); + } + + INLINE ap_private<_AP_W, _AP_S> Add(const ap_private<_AP_W, _AP_S>& RHS) const { + return ap_private<_AP_W, _AP_S>(VAL + RHS.VAL); + } + + INLINE ap_private<_AP_W, _AP_S> Sub(const ap_private<_AP_W, _AP_S>& RHS) const { + return ap_private<_AP_W, _AP_S>(VAL - RHS.VAL); + } + +#if 1 + INLINE ap_private& operator&=(uint64_t RHS) { VAL &= RHS; clearUnusedBits(); return *this;} + INLINE ap_private& operator|=(uint64_t RHS) { VAL |= RHS; clearUnusedBits(); return *this;} + INLINE ap_private& operator^=(uint64_t RHS){ VAL ^= RHS; clearUnusedBits(); return *this;} + INLINE ap_private& operator*=(uint64_t RHS){ VAL *= RHS; clearUnusedBits(); return *this; } + INLINE ap_private& operator+=(uint64_t RHS){ VAL += RHS; clearUnusedBits(); return *this;} + INLINE ap_private& operator-=(uint64_t RHS){ VAL -= RHS; clearUnusedBits(); return *this; } + INLINE ap_private operator&(uint64_t RHS) const { return ap_private(VAL & RHS); } + INLINE ap_private operator|(uint64_t RHS) const { return ap_private(VAL | RHS); } + INLINE ap_private operator^(uint64_t RHS) const { return ap_private(VAL ^ RHS); } + INLINE ap_private operator*(uint64_t RHS) const { return ap_private(VAL * RHS); } + INLINE ap_private operator/(uint64_t RHS) const { return ap_private(VAL / RHS); } + INLINE ap_private operator+(uint64_t RHS) const { return ap_private(VAL + RHS); } + INLINE ap_private operator-(uint64_t RHS) const { return ap_private(VAL - RHS); } +#endif + INLINE bool isMinSignedValue() const { + static const uint64_t min_mask = ~(~0ULL << (_AP_W-1)); + return BitWidth == 1 ? VAL == 1 : + (ap_private_ops::isNegative<_AP_W>(*this) && ((min_mask & VAL)==0)); + } + +#if 1 + + template INLINE + typename RType<_AP_W1,_AP_S1>::plus operator+(const ap_private<_AP_W1, _AP_S1>& RHS) const { + if (RType<_AP_W1,_AP_S1>::plus_w <=64) + return typename RType<_AP_W1,_AP_S1>::plus(RType<_AP_W1,_AP_S1>::plus_s ? int64_t(VAL+RHS.VAL):uint64_t(VAL+RHS.VAL)); + typename RType<_AP_W1,_AP_S1>::plus Result=RHS; + Result += VAL; + return Result; + } + + template INLINE + typename RType<_AP_W1,_AP_S1>::minus operator-(const ap_private<_AP_W1, _AP_S1>& RHS) const { + if (RType<_AP_W1,_AP_S1>::minus_w <=64) + return typename RType<_AP_W1,_AP_S1>::minus(int64_t(VAL-RHS.VAL)); + typename RType<_AP_W1,_AP_S1>::minus Result=*this; + Result -= RHS; + return Result; + } +#endif // #if 1 + + INLINE ap_private& flip() { + VAL = (~0ULL^VAL)&mask; + clearUnusedBits(); + return *this; + } + + uint32_t countPopulation() const { return CountPopulation_64(VAL);} + uint32_t countLeadingZeros() const { + int remainder = BitWidth % APINT_BITS_PER_WORD; + int excessBits = (APINT_BITS_PER_WORD - remainder) % APINT_BITS_PER_WORD; + //enum { remainder = BitWidth % APINT_BITS_PER_WORD, excessBits = APINT_BITS_PER_WORD - remainder}; + uint32_t Count = CountLeadingZeros_64(VAL); + if (Count) + Count-=excessBits; + return AESL_std::min(Count, (uint32_t)_AP_W); + } + + /// HiBits - This function returns the high "numBits" bits of this ap_private. + ap_private<_AP_W, _AP_S, 1> getHiBits(uint32_t numBits) const { + ap_private<_AP_W, _AP_S, 1> ret(*this); + ret = (ret)>>(BitWidth - numBits); + return ret; + } + + /// LoBits - This function returns the low "numBits" bits of this ap_private. + ap_private<_AP_W, _AP_S, 1> getLoBits(uint32_t numBits) const { + ap_private<_AP_W, _AP_S, 1> ret((VAL) << (BitWidth - numBits)); + ret = (ret)>>(BitWidth - numBits); + return ret; + //return ap_private(numBits, (VAL << (BitWidth - numBits))>> (BitWidth - numBits)); + } + + ap_private<_AP_W, _AP_S,1>& set(uint32_t bitPosition) { + VAL |= (1ULL << (bitPosition)); + clearUnusedBits(); + return *this; // clearUnusedBits(); + } + + void set() { + VAL = ~0ULL; + clearUnusedBits(); + } + + template + INLINE void set(const ap_private<_AP_W3, false> & val) { + operator = (ap_private<_AP_W3, _AP_S>(val)); + } + + INLINE void set(const ap_private & val) { + operator = (val); + } + + bool operator[](uint32_t bitPosition) const { + return (((1ULL << (bitPosition)) & VAL) != 0); + } + + INLINE void clearUnusedBits(void) { + enum { excess_bits = (_AP_W%APINT_BITS_PER_WORD) ? APINT_BITS_PER_WORD -_AP_W%APINT_BITS_PER_WORD : 0}; + VAL = _AP_S ? ((((int64_t)VAL)<<(excess_bits))>> (excess_bits)) : (excess_bits ? ((VAL)<<(excess_bits))>>(excess_bits) : VAL); + } + + INLINE void clearUnusedBitsToZero(void) { + enum { excess_bits = (_AP_W%APINT_BITS_PER_WORD) ? APINT_BITS_PER_WORD -_AP_W%APINT_BITS_PER_WORD : 0}; + static uint64_t mask = ~0ULL >> (excess_bits); + VAL &= mask; + } + + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1> udiv(const ap_private<_AP_W, _AP_S1>& RHS) const { + return ap_private<_AP_W, _AP_S||_AP_S1>(VAL / RHS.VAL); + } + + INLINE ap_private udiv(uint64_t RHS) const { + return ap_private(VAL / RHS); + } + + /// Signed divide this ap_private by ap_private RHS. + /// @brief Signed division function for ap_private. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1> sdiv(const ap_private<_AP_W, _AP_S1> & RHS) const { + if (isNegative()) + if (RHS.isNegative()) + return (-(*this)).udiv(-RHS); + else + return -((-(*this)).udiv(RHS)); + else if (RHS.isNegative()) + return -(this->udiv(-RHS)); + return this->udiv(RHS); + } + + /// Signed divide this ap_private by ap_private RHS. + /// @brief Signed division function for ap_private. + INLINE ap_private sdiv(int64_t RHS) const { + if (isNegative()) + if (RHS<0) + return (-(*this)).udiv(-RHS); + else + return -((-(*this)).udiv(RHS)); + else if (RHS<0) + return -(this->udiv(-RHS)); + return this->udiv(RHS); + } + + template + INLINE ap_private urem(const ap_private<_AP_W, _AP_S2>& RHS) const { + assert(RHS.VAL != 0 && "Divide by 0"); + return ap_private(VAL%RHS.VAL); + } + + INLINE ap_private urem(uint64_t RHS) const { + assert(RHS != 0 && "Divide by 0"); + return ap_private(VAL%RHS); + } + + /// Signed remainder operation on ap_private. + /// @brief Function for signed remainder operation. + template + INLINE ap_private srem(const ap_private<_AP_W, _AP_S2>& RHS) const { + if (isNegative()) { + ap_private lhs = -(*this); + if (RHS.isNegative()) { + ap_private rhs = -RHS; + return -(lhs.urem(rhs)); + } else + return -(lhs.urem(RHS)); + } else if (RHS.isNegative()) { + ap_private rhs = -RHS; + return this->urem(rhs); + } + return this->urem(RHS); + } + + /// Signed remainder operation on ap_private. + /// @brief Function for signed remainder operation. + INLINE ap_private srem(int64_t RHS) const { + if (isNegative()) + if (RHS<0) + return -((-(*this)).urem(-RHS)); + else + return -((-(*this)).urem(RHS)); + else if (RHS<0) + return this->urem(-RHS); + return this->urem(RHS); + } + + INLINE static void udivrem(const ap_private &LHS, const ap_private &RHS, + ap_private &Quotient, ap_private &Remainder){ + assert(RHS!=0 && "Divide by 0"); + Quotient = LHS.VAl/RHS.VAl; + Remainder = LHS.VAL % RHS.VAL; + } + + INLINE static void udivrem(const ap_private &LHS, uint64_t RHS, + ap_private &Quotient, ap_private &Remainder){ + assert(RHS!=0 && "Divide by 0"); + Quotient = LHS.VAl/RHS; + Remainder = LHS.VAL % RHS; + } + + INLINE static void sdivrem(const ap_private &LHS, const ap_private &RHS, + ap_private &Quotient, ap_private &Remainder) { + if (LHS.isNegative()) { + if (RHS.isNegative()) + ap_private::udivrem(-LHS, -RHS, Quotient, Remainder); + else + ap_private::udivrem(-LHS, RHS, Quotient, Remainder); + Quotient = -Quotient; + Remainder = -Remainder; + } else if (RHS.isNegative()) { + ap_private::udivrem(LHS, -RHS, Quotient, Remainder); + Quotient = -Quotient; + } else { + ap_private::udivrem(LHS, RHS, Quotient, Remainder); + } + } + + INLINE static void sdivrem(const ap_private &LHS, int64_t RHS, + ap_private &Quotient, ap_private &Remainder) { + if (LHS.isNegative()) { + if (RHS<0) + ap_private::udivrem(-LHS, -RHS, Quotient, Remainder); + else + ap_private::udivrem(-LHS, RHS, Quotient, Remainder); + Quotient = -Quotient; + Remainder = -Remainder; + } else if (RHS<0) { + ap_private::udivrem(LHS, -RHS, Quotient, Remainder); + Quotient = -Quotient; + } else { + ap_private::udivrem(LHS, RHS, Quotient, Remainder); + } + } + + template INLINE bool eq(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return (*this) == RHS; + } + + template INLINE bool ne(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return !((*this) == RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// the validity of the less-than relationship. + /// @returns true if *this < RHS when both are considered unsigned. + /// @brief Unsigned less than comparison + template INLINE bool ult(const ap_private<_AP_W1, _AP_S1, 1>& RHS) const { + uint64_t lhsZext = ((uint64_t(VAL)) << (64-_AP_W)) >> (64-_AP_W); + uint64_t rhsZext = ((uint64_t(RHS.VAL)) << (64-_AP_W1)) >> (64-_AP_W1); + return lhsZext < rhsZext; + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the less-than relationship. + /// @returns true if *this < RHS when both are considered signed. + /// @brief Signed less than comparison + template INLINE bool slt(const ap_private<_AP_W1, _AP_S1, 1>& RHS) const { + int64_t lhsSext = ((int64_t(VAL)) << (64-_AP_W)) >> (64-_AP_W); + int64_t rhsSext = ((int64_t(RHS.VAL)) << (64-_AP_W1)) >> (64-_AP_W1); + return lhsSext < rhsSext; + } + + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// validity of the less-or-equal relationship. + /// @returns true if *this <= RHS when both are considered unsigned. + /// @brief Unsigned less or equal comparison + template INLINE bool ule(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return ult(RHS) || eq(RHS); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the less-or-equal relationship. + /// @returns true if *this <= RHS when both are considered signed. + /// @brief Signed less or equal comparison + template INLINE bool sle(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return slt(RHS) || eq(RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// the validity of the greater-than relationship. + /// @returns true if *this > RHS when both are considered unsigned. + /// @brief Unsigned greather than comparison + template INLINE bool ugt(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return !ult(RHS) && !eq(RHS); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// the validity of the greater-than relationship. + /// @returns true if *this > RHS when both are considered signed. + /// @brief Signed greather than comparison + template INLINE bool sgt(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return !slt(RHS) && !eq(RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// validity of the greater-or-equal relationship. + /// @returns true if *this >= RHS when both are considered unsigned. + /// @brief Unsigned greater or equal comparison + template INLINE bool uge(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return !ult(RHS); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the greater-or-equal relationship. + /// @returns true if *this >= RHS when both are considered signed. + /// @brief Signed greather or equal comparison + template INLINE bool sge(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return !slt(RHS); + } + + INLINE ap_private abs() const { + if (isNegative()) + return -(*this); + return *this; + } + + ap_private<_AP_W, false> get() const { + ap_private<_AP_W,false> ret(*this); + return ret; + } + + INLINE static uint32_t getBitsNeeded(const char* str, uint32_t slen, uint8_t radix) { + return _AP_W; + } + + INLINE uint32_t getActiveBits() const { + uint32_t bits=_AP_W - countLeadingZeros(); + return bits?bits:1; + } + + INLINE double roundToDouble(bool isSigned=false) const { + const static uint64_t mask = ~0ULL << (APINT_BITS_PER_WORD - _AP_W); + return double(VAL); + } + + INLINE unsigned length() const { return _AP_W; } + + /*Reverse the contents of ap_private instance. I.e. LSB becomes MSB and vise versa*/ + INLINE ap_private& reverse () { + for (int i = 0; i < _AP_W/2; ++i) { + bool tmp = operator[](i); + if (operator[](_AP_W - 1 - i)) + set(i); + else + clear(i); + if (tmp) + set(_AP_W - 1 - i); + else + clear(_AP_W - 1 - i); + } + clearUnusedBits(); + return *this; + } + + /*Return true if the value of ap_private instance is zero*/ + INLINE bool iszero () const { + return isMinValue(); + } + + /* x < 0 */ + INLINE bool sign () const { + if (isNegative()) + return true; + return false; + } + + /* x[i] = !x[i] */ + INLINE void invert (int i) { + assert( i >= 0 && "Attempting to read bit with negative index"); + assert( i < _AP_W && "Attempting to read bit beyond MSB"); + flip(i); + } + + /* x[i] */ + INLINE bool test (int i) const { + assert( i >= 0 && "Attempting to read bit with negative index"); + assert( i < _AP_W && "Attempting to read bit beyond MSB"); + return operator[](i); + } + + //This is used for sc_lv and sc_bv, which is implemented by sc_uint + //Rotate an ap_private object n places to the left + INLINE void lrotate(int n) { + assert( n >= 0 && "Attempting to shift negative index"); + assert( n < _AP_W && "Shift value larger than bit width"); + operator = (shl(n) | lshr(_AP_W - n)); + } + + //This is used for sc_lv and sc_bv, which is implemented by sc_uint + //Rotate an ap_private object n places to the right + INLINE void rrotate(int n) { + assert( n >= 0 && "Attempting to shift negative index"); + assert( n < _AP_W && "Shift value larger than bit width"); + operator = (lshr(n) | shl(_AP_W - n)); + } + + //Set the ith bit into v + INLINE void set (int i, bool v) { + assert( i >= 0 && "Attempting to write bit with negative index"); + assert( i < _AP_W && "Attempting to write bit beyond MSB"); + v ? set(i) : clear(i); + } + + //Set the ith bit into v + INLINE void set_bit (int i, bool v) { + assert( i >= 0 && "Attempting to write bit with negative index"); + assert( i < _AP_W && "Attempting to write bit beyond MSB"); + v ? set(i) : clear(i); + } + + //Get the value of ith bit + INLINE bool get_bit (int i) const { + assert( i >= 0 && "Attempting to read bit with negative index"); + assert( i < _AP_W && "Attempting to read bit beyond MSB"); + return operator [](i); + } + + //complements every bit + INLINE void b_not() { + flip(); + } + + //Binary Arithmetic + //----------------------------------------------------------- +#define OP_BIN_AP(Sym,Rty, Fun) \ + template \ + INLINE \ + typename RType<_AP_W2,_AP_S2>::Rty \ + operator Sym (const ap_private<_AP_W2,_AP_S2>& op) const { \ + typename RType<_AP_W2,_AP_S2>::Rty lhs(*this); \ + typename RType<_AP_W2,_AP_S2>::Rty rhs(op); \ + return lhs.Fun(rhs); \ + } \ + + ///Bitwise and, or, xor + //OP_BIN_AP(&,logic, And) + //OP_BIN_AP(|,logic, Or) + //OP_BIN_AP(^,logic, Xor) + +#undef OP_BIN_AP + template + INLINE typename RType<_AP_W2,_AP_S2>::div + operator / (const ap_private<_AP_W2,_AP_S2>&op) const { + ap_private lhs=ap_private(*this); + ap_private rhs=ap_private(op); + return typename RType<_AP_W2,_AP_S2>::div((_AP_S||_AP_S2)?lhs.sdiv(rhs):lhs.udiv(rhs)); + } + + + template + INLINE typename RType<_AP_W2,_AP_S2>::mod + operator % (const ap_private<_AP_W2,_AP_S2>&op) const { + ap_private lhs=*this; + ap_private rhs=op; + typename RType<_AP_W2,_AP_S2>::mod res = typename RType<_AP_W2,_AP_S2>::mod (_AP_S?lhs.srem(rhs):lhs.urem(rhs)); + return res; + } + + +#define OP_ASSIGN_AP_2(Sym) \ + template \ + INLINE ap_private<_AP_W, _AP_S>& operator Sym##=(const ap_private<_AP_W2,_AP_S2>& op) \ + { \ + *this=operator Sym (op); \ + return *this; \ + } \ + + OP_ASSIGN_AP_2(/) + OP_ASSIGN_AP_2(%) +#undef OP_ASSIGN_AP_2 + + ///Bitwise assign: and, or, xor + //------------------------------------------------------------- + // OP_ASSIGN_AP(&) + // OP_ASSIGN_AP(^) + // OP_ASSIGN_AP(|) +#undef OP_ASSIGN_AP +#if 1 + + template + INLINE ap_private<_AP_W, _AP_S> + operator << (const ap_private<_AP_W2, _AP_S2>& op2) const { + uint32_t sh=op2.to_uint(); + return *this << sh; + } + + INLINE ap_private<_AP_W, _AP_S> + operator << (uint32_t sh) const { + return shl(sh); + } + +#endif + + template + INLINE ap_private<_AP_W, _AP_S> + operator >> (const ap_private<_AP_W2, _AP_S2>& op2) const { + uint32_t sh = op2.to_uint(); + return *this >> sh; + } + + INLINE ap_private<_AP_W, _AP_S> + operator >>(uint32_t sh) const { + ap_private<_AP_W, _AP_S> r(*this); + bool overflow=(sh>=_AP_W); + bool neg_v=r.isNegative(); + if(_AP_S) { + if(overflow) + neg_v?r.set():r.clear(); + else + return r.ashr(sh); + } else { + if(overflow) + r.clear(); + else + return r.lshr(sh); + } + return r; + } + + ///Shift assign + //------------------------------------------------------------------ +#define OP_ASSIGN_AP_3_SINGLE(Sym) \ + template \ + INLINE ap_private<_AP_W, _AP_S>& operator Sym##=(const ap_private<_AP_W2,_AP_S2>& op) \ + { \ + *this=operator Sym (op.getVal()); \ + return *this; \ + } + OP_ASSIGN_AP_3_SINGLE(>>) +#undef OP_ASSIGN_AP_3_SINGLE + + ///Comparisons + //----------------------------------------------------------------- + template + INLINE bool operator != (const ap_private<_AP_W2, _AP_S2, 1>& op) const { + return !(*this==op); + } + + template + INLINE bool operator > (const ap_private<_AP_W2, _AP_S2, 1>& op) const { + return op < *this; + } + + template + INLINE bool operator <= (const ap_private<_AP_W2, _AP_S2, 1>& op) const { + return !(*this>op); + } + + template + INLINE bool operator < (const ap_private<_AP_W2, _AP_S2, 1>& op) const { + enum { _AP_MAX_W = AP_MAX(_AP_W+(_AP_S||_AP_S2),_AP_W2+(_AP_S||_AP_S2))}; + ap_private<_AP_MAX_W, _AP_S> lhs(*this); + ap_private<_AP_MAX_W, _AP_S2> rhs(op); + if (_AP_S == _AP_S2) + return _AP_S?lhs.slt(rhs):lhs.ult(rhs); + else if (_AP_W < 32 && _AP_W2 < 32) + return lhs.slt(rhs); + else + if (_AP_S) + if (_AP_W2 >= _AP_W) + return lhs.ult(rhs); + else + return lhs.slt(rhs); + else + if (_AP_W >= _AP_W2) + return lhs.ult(rhs); + else + return lhs.slt(rhs); + } + + template + INLINE bool operator >=(const ap_private<_AP_W2, _AP_S2, 1>& op) const { + return !(*this + INLINE bool operator == (const ap_private<_AP_W2, _AP_S2, _AP_N2>& op) const { + return op == *this; + } + + template + INLINE bool operator != (const ap_private<_AP_W2, _AP_S2, _AP_N2>& op) const { + return !(op==*this); + } + + template + INLINE bool operator > (const ap_private<_AP_W2, _AP_S2, _AP_N2>& op) const { + return op < (*this); + } + + template + INLINE bool operator <= (const ap_private<_AP_W2, _AP_S2, _AP_N2>& op) const { + return op >= *this; + } + + template + INLINE bool operator <(const ap_private<_AP_W2, _AP_S2, _AP_N2>& op) const { + return op > *this; + } + + template + INLINE bool operator >=(const ap_private<_AP_W2,_AP_S2,_AP_N2>& op) const { + return op <= *this; + } + ///Bit and Part Select + //-------------------------------------------------------------- + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (int Hi, int Lo) { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (int Hi, int Lo) const { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(const_cast*>(this), Hi, Lo); + } + + INLINE ap_range_ref<_AP_W,_AP_S> + range (int Hi, int Lo) const { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>((const_cast*> (this)), Hi, Lo); + } + + INLINE ap_range_ref<_AP_W,_AP_S> + range (int Hi, int Lo) { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + range (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + range (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) const { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(const_cast(this), Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) const { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + return this->range(Hi, Lo); + } + + + INLINE ap_bit_ref<_AP_W,_AP_S> operator [] (uint32_t index) { + assert(index >= 0&&"Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S> (*this, (int)index); + } + + template + INLINE ap_bit_ref<_AP_W,_AP_S> operator [] (const ap_private<_AP_W2,_AP_S2> &index) { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S>( *this, index.to_int() ); + } + + template + INLINE bool operator [] (const ap_private<_AP_W2,_AP_S2>& index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + ap_bit_ref<_AP_W,_AP_S> br =operator [] (index); + return br.to_bool(); + } + + INLINE ap_bit_ref<_AP_W,_AP_S> bit (int index) { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S>( *this, index ); + } + + template + INLINE ap_bit_ref<_AP_W,_AP_S> bit (const ap_private<_AP_W2,_AP_S2> &index) { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W &&"Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S>( *this, index.to_int() ); + } + + INLINE bool bit (int index) const { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + ap_bit_ref<_AP_W,_AP_S> br(const_cast*>(this), index); + return br.to_bool(); + } + + template + INLINE bool bit (const ap_private<_AP_W2,_AP_S2>& index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + ap_bit_ref<_AP_W,_AP_S> br = bit(index); + return br.to_bool(); + } + + template + INLINE ap_concat_ref<_AP_W,ap_private<_AP_W, _AP_S>,_AP_W2,ap_private<_AP_W2,_AP_S2> > concat(const ap_private<_AP_W2,_AP_S2>& a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_private<_AP_W2,_AP_S2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W,ap_private<_AP_W, _AP_S>,_AP_W2,ap_private<_AP_W2,_AP_S2> > concat(ap_private<_AP_W2,_AP_S2>& a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_private<_AP_W2,_AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (const ap_private<_AP_W2, _AP_S2>& a2) const { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(const_cast& >(*this), const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (const ap_private<_AP_W2, _AP_S2>& a2) { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(*this, const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (ap_private<_AP_W2, _AP_S2>& a2) const { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(const_cast& >(*this), a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (ap_private<_AP_W2, _AP_S2>& a2) { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > + operator, (const ap_range_ref<_AP_W2, _AP_S2> &a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, + ap_range_ref<_AP_W2, _AP_S2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > + operator, (ap_range_ref<_AP_W2, _AP_S2> &a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, + ap_range_ref<_AP_W2, _AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, ap_bit_ref<_AP_W2, _AP_S2> > + operator, (const ap_bit_ref<_AP_W2, _AP_S2> &a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, + ap_bit_ref<_AP_W2, _AP_S2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, ap_bit_ref<_AP_W2, _AP_S2> > + operator, (ap_bit_ref<_AP_W2, _AP_S2> &a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, + ap_bit_ref<_AP_W2, _AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > + operator, (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > + operator, (ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) const { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) const { + return ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, a2); + } + + template + INLINE ap_private + operator & (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) { + return *this & a2.get(); + } + + template + INLINE ap_private + operator | (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) { + return *this | a2.get(); + } + + template + INLINE ap_private + operator ^ (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) { + return *this ^ a2.get(); + } + + + //Reduce operation + //----------------------------------------------------------- + INLINE bool and_reduce() const { + return (VAL & mask) == mask; + } + + INLINE bool nand_reduce() const { + return (VAL & mask) != mask; + } + + INLINE bool or_reduce() const { + return (bool)VAL; + } + + INLINE bool nor_reduce() const { + return VAL==0; + } + + INLINE bool xor_reduce() const { + unsigned int i=countPopulation(); + return (i%2)?true:false; + } + + INLINE bool xnor_reduce() const { + unsigned int i=countPopulation(); + return (i%2)?false:true; + } + + INLINE std::string to_string(uint8_t radix=2, bool sign=false) const { + return toString(radix, radix==10?_AP_S:sign); + } +}; +template +std::string ap_private<_AP_W, _AP_S, 1>::toString(uint8_t radix, bool wantSigned) const { + assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) && + "Radix should be 2, 8, 10, or 16!"); + static const char *digits[] = { + "0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f" + }; + std::string result; + if (radix != 10) { + // For the 2, 8 and 16 bit cases, we can just shift instead of divide + // because the number of bits per digit (1,3 and 4 respectively) divides + // equaly. We just shift until there value is zero. + + // First, check for a zero value and just short circuit the logic below. + if (*this == (uint64_t)(0)) + result = "0"; + else { + ap_private<_AP_W, false, 1> tmp(*this); + size_t insert_at = 0; + if (wantSigned && isNegative()) { + // They want to print the signed version and it is a negative value + // Flip the bits and add one to turn it into the equivalent positive + // value and put a '-' in the result. + tmp.flip(); + tmp++; + result = "-"; + insert_at = 1; + } + // Just shift tmp right for each digit width until it becomes zero + uint32_t shift = (radix == 16 ? 4 : (radix == 8 ? 3 : 1)); + uint64_t mask = radix - 1; + ap_private<_AP_W, false, 1> zero(0); + while (tmp.ne(zero)) { + unsigned digit = (unsigned)(tmp.VAL & mask); + result.insert(insert_at, digits[digit]); + tmp = tmp.lshr(shift); + } + } + return result; + } + + ap_private<_AP_W, false, 1> tmp(*this); + ap_private<6, false, 1> divisor(radix); + ap_private<_AP_W, _AP_S, 1> zero(0); + size_t insert_at = 0; + if (wantSigned && isNegative()) { + // They want to print the signed version and it is a negative value + // Flip the bits and add one to turn it into the equivalent positive + // value and put a '-' in the result. + tmp.flip(); + tmp++; + result = "-"; + insert_at = 1; + } + if (tmp == ap_private<_AP_W, false, 1>(0ULL)) + result = "0"; + else while (tmp.ne(zero)) { + ap_private<_AP_W, false, 1> APdigit = tmp%divisor; + ap_private<_AP_W, false, 1> tmp2 = tmp/divisor; + uint32_t digit = (uint32_t)(APdigit.getZExtValue()); + assert(digit < radix && "divide failed"); + result.insert(insert_at,digits[digit]); + tmp = tmp2; + } + return result; + +} + +#endif /* #ifndef LLVM_SUPPORT_MATHEXTRAS_H */ \ No newline at end of file diff --git a/hls_2018/router_04/main.cpp b/hls_2018/router_04/main.cpp new file mode 100755 index 0000000..2a4e7f5 --- /dev/null +++ b/hls_2018/router_04/main.cpp @@ -0,0 +1,97 @@ +/** + * main.cpp + * + * for Vivado HLS + */ + +#ifdef SOFTWARE +#include "ap_int.h" +#else +#include +#endif + +#ifdef CALCTIME +#include +#include +#endif + +#include "router.hpp" + +#define PRINT_SOLUTION + + +int main(int argc, char *argv[]) { + using namespace std; + + // Test data // + // NL_Q00.txt + //char boardstr[BOARDSTR_SIZE] = "X10Y05Z3L0000107041L0004107002L0102102021L0900100003"; + // NL_Q06.txt + char boardstr[BOARDSTR_SIZE] = "X10Y18Z2L0900109002L0901105012L0902103052L0903103062L0904100102L0905106012L0906109022L0717109102L0808109112L0017209172L0401200072L0912208152L0009201092L0709209092L0901206052L0309204092L0701209072L0101201022L0011202152L0016202162"; + // NL_Q08.txt + //char boardstr[BOARDSTR_SIZE] = "X17Y20Z2L0000103022L1603115052L0916107032L0302108012L1104111042L1002100002L0919116162L1616113182L1001115012L0500201182L1603213152L0600210022"; + + // Read boardstr from command line + if (1 < argc) { + // From stdin + if(argv[1][0]!='X') + { + char* c_p=fgets(boardstr, BOARDSTR_SIZE, stdin); + int length=strlen(c_p); + boardstr[length-1]=0; + } + else + { + strcpy(boardstr, argv[1]); + } + } + + // Seed value + int seed = 12345; + if (2 < argc) { + seed = atoi(argv[2]); + } + +#ifdef PRINT_SOLUTION + int size_x = (boardstr[1] - '0') * 10 + (boardstr[2] - '0'); + int size_y = (boardstr[4] - '0') * 10 + (boardstr[5] - '0'); + int size_z = (boardstr[7] - '0'); +#endif + + // Solver + ap_int<32> status; + clock_t clock_start, clock_done; + clock_start = clock(); + bool result = pynqrouter(boardstr, seed, &status); + clock_done = clock(); + if (result) { + cout << endl << "Test Passed!" << endl; + } else { + cout << endl << "Test Failed!" << endl; + } + cout << "status = " << (int)status << endl; + cout << "elapsed = " << ((double)(clock_done - clock_start) / CLOCKS_PER_SEC) << endl << endl; + +#ifdef PRINT_SOLUTION + cout << "SOLUTION" << endl; + cout << "========" << endl; + cout << "SIZE " << size_x << "X" << size_y << "X" << size_z << endl; + for (int z = 0; z < size_z; z++) { + cout << "LAYER " << (z + 1) << endl; + for (int y = 0; y < size_y; y++) { + for (int x = 0; x < size_x; x++) { + if (x != 0) { + cout << ","; + } + int i = ((x * MAX_WIDTH + y) << BITWIDTH_Z) | z; + cout << setfill('0') << setw(3) << right << (unsigned int)(unsigned char)(boardstr[i]); + //cout << (unsigned int)(unsigned char)(boardstr[i]); + } + cout << endl; + } + } +#endif + + return 0; +} + diff --git a/hls_2018/router_04/router.cpp b/hls_2018/router_04/router.cpp index a2e01cb..81804e0 100755 --- a/hls_2018/router_04/router.cpp +++ b/hls_2018/router_04/router.cpp @@ -171,8 +171,8 @@ bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *stat if (next_target == line_num) next_target = 0; #ifdef DEBUG_PRINT - cout << "(round " << round << ") LINE #" << (int)(target + 1); - cout << " -> " << pointer << endl; + //cout << "(round " << round << ") LINE #" << (int)(target + 1); + //cout << " -> " << pointer << endl; #endif #ifdef DEBUG_PRINT int buffer_length = pointer - s_idx[target]; diff --git a/hls_2018/router_04/router.hpp b/hls_2018/router_04/router.hpp index 0f523d4..cb3ba27 100755 --- a/hls_2018/router_04/router.hpp +++ b/hls_2018/router_04/router.hpp @@ -29,11 +29,11 @@ using namespace std; #define MAX_CELLS 41472 // Max #cells (16bit) #define MAX_LINES 1024 // Max #lines (10bit) -#define MAX_PQ 32768 // Queue size (15bit) +#define MAX_PQ 65536 // Queue size (16bit) #define MAX_BUFFER 16384 // Line buffer size (14bit) #define CELL_BIT 16 #define LINE_BIT 10 -#define PQ_BIT 15 +#define PQ_BIT 16 #define BUFF_BIT 14 #define PQ_PRIORITY_WIDTH 16 -- 2.22.0 From a155657bfd5f3de23a5e151997c308c98f9413c8 Mon Sep 17 00:00:00 2001 From: Kazushi Kawamura Date: Fri, 24 Aug 2018 23:48:38 +0900 Subject: [PATCH 05/30] Bug fixed (in pq_pop func.) --- hls_2018/README.md | 37 ++++++++++++++++++++++++++++++++++- hls_2018/router_03/router.cpp | 2 +- hls_2018/router_04/router.cpp | 2 +- 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/hls_2018/README.md b/hls_2018/README.md index 3994d6f..9785b00 100644 --- a/hls_2018/README.md +++ b/hls_2018/README.md @@ -27,5 +27,40 @@ Options: * Input/Output: boardstr(8bit\*41472), seed(32bit), &status(32bit), return(1bit) ## Results -TODO +|Q|heap(seed:0)|c-array(seed:0)| +|:---|:---|:---| +|01|1|1| +|02|1|1| +|03|1|1| +|04|1|1| +|05|1|1| +|06|1|1| +|07|1|1| +|08|1|1| +|09|1|1| +|10|1|1| +|11|1|1| +|12|1|1| +|13|1|1| +|14|1|1| +|15|1|1| +|16|1|1| +|17|1|1| +|18|1|1| +|19|1|1| +|20|1|1| +|21|1|1| +|22|1|1| +|23|1|1| +|24|1|1| +|25|1|1| +|26|1|1| +|27|1|1| +|28|1|1| +|29|1|1| +|30|1|1| +|31|1|1| +|32|1|1| +|33|1|1| +|34|1|1| diff --git a/hls_2018/router_03/router.cpp b/hls_2018/router_03/router.cpp index adf00df..0a21b17 100755 --- a/hls_2018/router_03/router.cpp +++ b/hls_2018/router_03/router.cpp @@ -481,7 +481,7 @@ void pq_pop(ap_uint<32> pq_nodes[MAX_PQ], ap_uint<16> *ret_priority, ap_uint<16> ap_uint last_priority = (ap_uint<16>)(pq_nodes[*pq_len] & PQ_PRIORITY_MASK); // Priority of last element PQ_POP_LOOP: - while (1) { + while (!(i >> (PQ_BIT-1))) { // (2018.08.24) Loop condition fixed #pragma HLS LOOP_TRIPCOUNT min=1 max=15 /** Set!: min=0 max=PQ_BIT **/ ap_uint c1 = i << 1; // child node(left) diff --git a/hls_2018/router_04/router.cpp b/hls_2018/router_04/router.cpp index 81804e0..2fde0ec 100755 --- a/hls_2018/router_04/router.cpp +++ b/hls_2018/router_04/router.cpp @@ -481,7 +481,7 @@ void pq_pop(ap_uint<32> pq_nodes[MAX_PQ], ap_uint<16> *ret_priority, ap_uint<16> ap_uint last_priority = (ap_uint<16>)(pq_nodes[*pq_len] & PQ_PRIORITY_MASK); // Priority of last element PQ_POP_LOOP: - while (1) { + while (!(i >> (PQ_BIT-1))) { // (2018.08.24) Loop condition fixed #pragma HLS LOOP_TRIPCOUNT min=1 max=16 /** Set!: min=0 max=PQ_BIT **/ ap_uint c1 = i << 1; // child node(left) -- 2.22.0 From 04549b4c6beb0a8fab9fb88d85477d2c083b1ae3 Mon Sep 17 00:00:00 2001 From: Kazushi Kawamura Date: Sat, 25 Aug 2018 00:08:13 +0900 Subject: [PATCH 06/30] Add results --- hls_2018/README.md | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/hls_2018/README.md b/hls_2018/README.md index 9785b00..dac6516 100644 --- a/hls_2018/README.md +++ b/hls_2018/README.md @@ -36,31 +36,32 @@ Options: |05|1|1| |06|1|1| |07|1|1| -|08|1|1| +|08|0|1| |09|1|1| |10|1|1| |11|1|1| |12|1|1| |13|1|1| -|14|1|1| +|14|0|1| |15|1|1| |16|1|1| -|17|1|1| +|17|0|0| |18|1|1| -|19|1|1| +|19|0|0| |20|1|1| -|21|1|1| +|21|0|0| |22|1|1| -|23|1|1| -|24|1|1| -|25|1|1| +|23|1|0| +|24|0|0| +|25|0|0| |26|1|1| -|27|1|1| +|27|1|0| |28|1|1| -|29|1|1| -|30|1|1| -|31|1|1| +|29|0|0| +|30|0|0| +|31|0|0| |32|1|1| -|33|1|1| -|34|1|1| +|33|0|0| +|34|0|0| +|Total|22|22| -- 2.22.0 From 4c4a8f61c280ea8e24f296cf5805720af10739c9 Mon Sep 17 00:00:00 2001 From: KazushiKawamura Date: Sat, 25 Aug 2018 02:38:29 +0900 Subject: [PATCH 07/30] Change comment out --- hls_2018/README.md | 74 +++++++++++++++++------------------ hls_2018/auto/auto_compile.c | 30 ++++++++++++++ hls_2018/router_03/router.cpp | 4 +- 3 files changed, 69 insertions(+), 39 deletions(-) create mode 100755 hls_2018/auto/auto_compile.c diff --git a/hls_2018/README.md b/hls_2018/README.md index dac6516..eb409d8 100644 --- a/hls_2018/README.md +++ b/hls_2018/README.md @@ -27,41 +27,41 @@ Options: * Input/Output: boardstr(8bit\*41472), seed(32bit), &status(32bit), return(1bit) ## Results -|Q|heap(seed:0)|c-array(seed:0)| -|:---|:---|:---| -|01|1|1| -|02|1|1| -|03|1|1| -|04|1|1| -|05|1|1| -|06|1|1| -|07|1|1| -|08|0|1| -|09|1|1| -|10|1|1| -|11|1|1| -|12|1|1| -|13|1|1| -|14|0|1| -|15|1|1| -|16|1|1| -|17|0|0| -|18|1|1| -|19|0|0| -|20|1|1| -|21|0|0| -|22|1|1| -|23|1|0| -|24|0|0| -|25|0|0| -|26|1|1| -|27|1|0| -|28|1|1| -|29|0|0| -|30|0|0| -|31|0|0| -|32|1|1| -|33|0|0| -|34|0|0| -|Total|22|22| +|Q|heap(seed:0)|c-array(seed:0)|OR| +|:---|:---|:---|:---| +|01|1|1|1| +|02|1|1|1| +|03|1|1|1| +|04|1|1|1| +|05|1|1|1| +|06|1|1|1| +|07|1|1|1| +|08|0|1|1| +|09|1|1|1| +|10|1|1|1| +|11|1|1|1| +|12|1|1|1| +|13|1|1|1| +|14|0|1|1| +|15|1|1|1| +|16|1|1|1| +|17|0|0|0| +|18|1|1|1| +|19|0|0|0| +|20|1|1|1| +|21|0|0|0| +|22|1|1|1| +|23|1|0|1| +|24|0|0|0| +|25|0|0|0| +|26|1|1|1| +|27|1|0|1| +|28|1|1|1| +|29|0|0|0| +|30|0|0|0| +|31|0|0|0| +|32|1|1|1| +|33|0|0|0| +|34|0|0|0| +|Total|22|22|24| diff --git a/hls_2018/auto/auto_compile.c b/hls_2018/auto/auto_compile.c new file mode 100755 index 0000000..66f672e --- /dev/null +++ b/hls_2018/auto/auto_compile.c @@ -0,0 +1,30 @@ +#include +#include + +#define STRLEN 65536 + +int main(void){ + + char q[STRLEN], command[STRLEN]; + char dir[64] = "../router_01"; + + FILE *fp; + fp = fopen("b.txt", "r"); + if(fp == NULL){ + printf("File does not exist.\n"); + exit(1); + } + + int counter = 1; + while(1){ + if(fscanf(fp, "%s", q) == EOF) break; + printf("Q. %d\n", counter++); + sprintf(command, "./%s/sim.exe %s", dir, q); + //printf("(command) %s\n", command); + int ret = system(command); + printf("ret: %d\n", ret); + } + fclose(fp); + return 0; +} + diff --git a/hls_2018/router_03/router.cpp b/hls_2018/router_03/router.cpp index 0a21b17..772d420 100755 --- a/hls_2018/router_03/router.cpp +++ b/hls_2018/router_03/router.cpp @@ -171,8 +171,8 @@ bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *stat if (next_target == line_num) next_target = 0; #ifdef DEBUG_PRINT - cout << "(round " << round << ") LINE #" << (int)(target + 1); - cout << " -> " << pointer << endl; + //cout << "(round " << round << ") LINE #" << (int)(target + 1); + //cout << " -> " << pointer << endl; #endif #ifdef DEBUG_PRINT int buffer_length = pointer - s_idx[target]; -- 2.22.0 From 0963b76135e8e41f6d2ab79e37db15007923a608 Mon Sep 17 00:00:00 2001 From: KazushiKawamura Date: Sat, 25 Aug 2018 02:46:38 +0900 Subject: [PATCH 08/30] Add file --- hls_2018/auto/q.txt | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100755 hls_2018/auto/q.txt diff --git a/hls_2018/auto/q.txt b/hls_2018/auto/q.txt new file mode 100755 index 0000000..f7ee6af --- /dev/null +++ b/hls_2018/auto/q.txt @@ -0,0 +1,34 @@ +X24Y24Z4L0613304164L1702122032L0101403204L1601420204L2117419044L0023116021L1520309084L1921116154L1709121031L1812103211L0905208142L0704412013L0421110094L2320100142L1500319034L0915104123L0907418124L2001109101L0122202213L2102422011L2120105211L2319117132L0404119103L1215322223L0607218074L1715113123L1217220172L1602320113L0003306053L0405413144L2006421214L1301103212L0614322183L1108323004L0004322043L0602322213L1210120142L1321419172L1202116012L1303103081L0820211202L1003116142L1701305123L0312223072L0720301063L1202214024L0506207072L1610417224L1309404154L1201408124L1704410064L0822110211L1210321153L1708116072L0000100111L0201112011L0808104103L0923210212L1210413134L1500421014 +X15Y15Z2L0202212102L0303211112L0404210122L0503209112L0402210102L0204212122L0203212112L0302211102L0403210112L0504209122L0502209102L0304211122 +X20Y20Z8L0203202066L0400403037L0403105088L0503101016L0500206038L0703317055L1001104054L0505317087L0108204086L0111101177L0810406188L0313406138L0413215177L0513106176L0317302158L0715100195L0318307064L1503212048L1702112058L1206318087L1007417036L1101317047L1406216094L1111217187L1310418146L1510315145L1014310177L1317219198L0919218177 +X72Y72Z8L0000171718L0036871001L0000800718L0036171008L0071171711L3671171368 +X08Y08Z4L0000107072L0100103032L0007106072L0503106032L0506101062L0001205062L0404106051L0700207032L0201202032L0205203052L0000307074L0100303034L0007306074L0503306034L0506301064L0001405064L0404306053L0700407034L0201402034L0205403054 +X48Y36Z8L0609109051L0608108091L0709109021L0306109041L0204109091L0207105091L0208105041L0209104041L0607109031L0516105191L0417106171L0418106181L0113103131L0213104211L0214107211L0413110211L0814108211L0221110221L0226103321L0331104251L0128105321L0329108321L0733109261L0629107261L0630107271L0233106281L1400123101L1503123061L1504122101L1508122081L1509122011L1606118111L1702122041L1212119211L1319115141L1316120151L1217118171L1313119221L2020122121L1517116221L1421116171L1527123351L1328120261L1533122251L1830121311L1334120291L1426119261L1632119251L1730122291L1431121341L2501131011L2708128051L2800134051L3400135111L2400132031L2704132081L2406125021L2504133101L2401128101L2522134151L2921134161L2513134171L3013134221L2614130171L3019135191L2415130181L3414135121L3524135341L2533135281L2727135351L2435129311L2734129351L2829131331L2833132321L3607146111L4207147111L4010147001L3600137101L3608144021L4509146051L4020145141L3614141151L4218147231L3612145201L3712143141L3623144181L3912146231L3624144301L4030147241L3635137321L3835147351L4132146351L3634145311L3726144291L3733142281L2935227213L0629622066L0606335013L1728617245L0814411182L2608416057 +X72Y72Z8L0000166038L0004128038L0013104688L0016158688L0030133688L0046120038L0071149038L7165169688 +X70Y70Z8L1006530061L6936145414L0200136021L0349503538L6038613668L3754663198L5736462345L1925421692L2610640004L0836536045L5820736441L1344511357L4920658368L2319455092L5761834521L1203503086L6860757648L3133653206L4411730011L2624861188L6211867455L0645520521L3102432307L4908444021L0932510398L0841516497L6313158085L5746565678L1606405095L5753837421L3159825694L3753336537L6009349074L2012636101L3943238543L4466665497L2312224103L5369269585L6467265683L0038200558L0861220691L1111205002L5158452558L4029156215L2846714572L3030467483L3755137694L5849500646L6610667108L4761648684L4823235011L0820817098L2141114503L0361602618L1712200057L2700229021L2032713308L0964710682L6050858538L3838341491L6022363175L4400735031L4229837288L6110667088L6661368642L2804511005L0632803446L0817704004L2502529018L0214531131L4428345162L3900335061L1967511678L5856869694L4127653172L3855443656L4310561006L1318807218L3667234694L2806631045L5955466554L3621137221L4855147461L0736808428L0543201482L3446822598L4069223584L4446346462L1457716314L5249768692L3339324181L3003733086L6636844652L2929440362L2727518336L2355641666L2059831608L4730252231L0436421253L5350456605L3319536105L3903624138L4429540374L2263216691L2733116375L4105555217L5715666025L1312537134L4747547544L6012367533L4456566454L2649327638L4930563387L5219557168L2357221682L0529205321L1624115307L5640145442L1639722257L3739842397L4165337628L3731537276L2008723038L2940631346L4231151241L6104161024L3761739636L1659303485L2703226041L5116150151L5726556326L1418236114L5811158091L5538649413L6701264031L1708208112L3360532611L6218564205L4605646026L2210117013L4844148411L6837563188L4246144525L4204239041L4912860388L3057432624L0640112373L0812601373L4122529268L4930846361L1110513105L1827532425L6467569613L6914162331L1044725538L5230849268L3208332063L3857634627L5122252172L1344224408L1119306061L0244408364L0603208026L5645658554L2909223144L6945169391L4416449142L1007809255L5158237585L3861435594L1107308083L6401865017L2945831438L0207301044L0217511154L6358861628L1150604456L6165369675L3630138303L4317150121L5104757056L0224807207L1922318303L2123812227L6636660611L5551853586L4645444484L1830720344L1617808036L1957722597L5305153022L0822407362L5455556527L0416506195L1061815678L4215655238L4933549276L6414357154L5113834086L3146631614L4405645046L3540235616L4009445078L5064151674L0467413553L1706508105L3407535045L4546434375L5050648314L2142722472L6535560333L6254463453L1218708157L3918139143L4518842016L4144243382L3012131071L4663648587L6545668108L6613361126L4946550555L0407103062L4754747558L5721358192L4443844357L2253715508L3731136336L6264759472L2239516422L1541708398L3055727507L6841266443L6336360343L0524303211L1365201624L5143451371L1154712502L1354820571L3756535607L5326145424L6626359188L4152335487L0456110563L6437161348L4123344193L5542454474L1554518535L4651741547L2409211346L2039722336L0708605038L0337710387L1107209062L5117456165L0715506158L5407853067L1221100091L2348628466L6519363194L2701217012L0746208241L5901844005L2101815018L5267853588L3756235491L4230739307L5322856195L4918149201L2020518215L4543862438L5157349563L1112113153L2648326562L3025237322L6115260151L6061569628L3135841406L2341229332L1860817638L6957866578L5760249591L3810839117L3500736038L1335328332L5661858588L0225615054L3350131471L1254423488L3909343026L1823716184L6330364391L5363164573L3959647568L1128610356L5551252333L1401813015L2810226131L1034312353L3258236562L5638157345L1350609458L2941727487L5212652107L2140620417L4162751666L4937350393L1428325177L4143240442L0769609696L0538601518L2830329358L0732806276L3921736168L3013837148L5100143042L2461425693L1922224102L0009606146L0645201632L2015818188L5255153531L2550229452L6546666447L6334768358L0752108531L5412159103L0750806516L0418211165L0152103413L1107812106L1910518096L1838407372L6609560168L0942509462L6019458163L1533212241L2550624516L2369321693L4325742238L6213160144L6767859695L1906522008L4258639538L6368367575L4762557692L2601424018L2916516046L4863740697L0828704277L3531334274L4714543175L1161508662L0530309302L2527432296L6943268462L2439723376L4407749117L2112734037L0126801308L6431654308L1334818308L1660211673L2110527121L1621814208L3307529006L3724532137L6632869386L4203540046L3434337331L2957326424L3251634506L5431451311L6731262326L2122524164L2346528455L3769151691L3125835288L2529222252L6765767668L1112611146L3629329304L0236601306L5608556094L3935738317L2224321211L2339735405L0719401084L2845726457L0941721403L3357736594L0125214181L3440840404L1739519436L4761351694L6065163671L4264541618L3019337244L1061213671L5148856508L4553244481L4734248351L4361148572L4066743585L0307604056L1139313393L6129561325L0232205311L5231351293L0334208303L3629439275L4643151401L6618161103L3110525108L5844555425L5459555645L1868717696L0512207141L6833867328L5062352623L0302203031L0468109682L5207649001L3337533314L0739210373L2501519005L5923763266L4432145282L3735639346L6759265521L1837819377L5403656015L6761663647L3767538667L0835602371L5406455052L4053239543L6562569688L0367507652L3827238246L4708545025L3027232252L2109733146L3511731118L0761405521L1957320561L0545302594L6817559086L2764328685L5121252228L3347739388L2349219423L0363800695L6902566006L4424743238L4651152521L3403634008L4113138142L3647136491L2819331193L4117638137L4362239693L2727121281L5321250211L0950310496L1646513428L5153851551L2809629108L2661716698L6525167211L0156207531L1338617427L0769418673L0964209631L3036330402L0360202511L0946107461L3303832028L6148863508L5032251312L3820540195L3520130181L2719125124L1461113614L3707434105L4616152092L2514625166L1828324186L2501326021L3556635546L6024457254L5534667302L6951365533L0630301323L5963859658L5040730427L5706856038L4837745357L0958412587L5426268231L2255424535L5029552316L1030410324L6246163411L4601445005L6644266471L4224640237L1555604575L4643843388L6543647417L2429823328L4522236162L0947409483L0854807548L1339612406L0168708698L0238207432L0143700427L6140267314L4246446463L3512335142L2102418034L2063418694L2647128501L6648367491L0133808138L2461819687L2069620684L0425801248L2563226592L1457802485L6744562418L6904267002L5827360283L6040253361L3539440425L3317724234L0217300142L2660729597L3004328104L4041637487L5755445484L2203226037L1540515416L2601724006L5530651296L3436731297L5347251491L0458204571L0918609177L1132511344L5350251411L6138463403L5360151623L6829569334L1950318504L6616466184L2334121331L4015840165L0818306181L2823123193L2241420425L6252460521L4713440222L6114565171L0336205331L4709847107L1356413574L2302333011L4535545364L2205729053L3962638613L6247462444L1244820555L5643561464L1801821028L1504813048L3449435464L3857837598L1047416491L5353554525L6759465584L3269732657L0230302311L5506657027L2220824165L4812546077L3255624557L5729160282L6745768457L0928804308L5607355042L3962438622L2202116002L0765508664L5523457235L2063320663L2545226461L1039611417L5221251202L0336804358L2205319034L5259453614L2661824617L4439740427L3545135471L6524263225L5838659397L5611456086L1450614535L5830857318L4711648073L0926708288L6829469284L0036602376L1935720347L2062519634L6558163562L3468530638L4817449148L6417160171L4054542556L0823516177L6430561315L1662818628L2315619196L3152532515L4813652116L5500355024L6926869248L1362614646L1522820278L0366805658L1820709336L4228745307L6108562064L1865516591L5336549365L6117561186L0745406466L1640813408L3308132073L3321133251L5302153041L4904549065L3146534405L0169703686L3505535075L1323618287L6827862298L3847434485L2244324434L0755509587L2949426504L0457201572L5852656515L5320455215L6856267553L2767528645L6315565165L4721152101L0018400173L2155215501L4833445314L1901720046L0824607228L6249761538L1150714478L5605556035L1565312684L2633825328L5912659065L0816509145L2616830165L3609336073L6439668401L1907222091L5265447684L3452339611L0739602457L4942447454L3458837588L2664625647L0705806108L2221315123L3550543495L1126612266L4521245221L6433669364L1354611546L0103700047L1018215181L5521354193L0940110391L2617324173L5541258443L1610114141L6715165151L3665237561L6537767396L2445216462L1738121424L1855817565L2706531132L0056501496L0246503435L1733717344L0253701547L6917365114L1340412393L3822839258L4961448574L2959131641L4508650128L4627450232L3310531128L1156609556L4656142561L3015431134L6143758516L2168626658L5414151112L1232107331L4101844018L3952140571L4041442415L1457114591L4064440653L5200554034L1222503256L2632129341L2528424222L1403519032L6651469504L0758106601L3666633646L1549515484L2212823187L6833169312L4848754418L6140363451L0954309472L1854721537L1958418574L4363844606L5226253263L1406120074L0746809468L4035537354L0258101622L6104460034L4936846337L1816817178L6420861216L4850447524L0202104001L6207261111L1166611686L2429326303L1134821355L2235421335L3116128183L0214401188L6915468134L6728768296L0234508342L0041201382L5925764198L1526208321L6068846687L1011705068L2740628386L2503526045L6332863306L4553843548L0359306543L2852127542L5608453081L0943307422L0630504306L6609667086L1628111242L2340124381L4246745447L3022230192L1409416092L0314703155L0128207232L4227249241L4203238032L0436601347L6637869388L2753220522L5239754337L3941140401L3520735187L1830117292L5308853108L5067451592L2721324213L1607812057L1148410504L5500155031L5907157042L0311601157L3519432182L2567618698L6621665215L4750752466L3115229162L1428815248L0354405555L0558604595L4613747108L3300629008L4649346502L0446404495L3846141462L2210621094L4443441366L5033249363L3443436414L6503363003L0322312173L0154300581L4257340594L1544819456L2421823214L3467530647L2951626496L4902850018L6222166251L3945439494L2937332371L6650761537L4249340513L2956729548L6234162371L0264401675L1046411436L6163357641L4001342003L3568140655L2647427485L4208842128L3119631236L6702368032L5227254321L5020851216L3423538227L1256213611L5743257421L5127352276L4840849438L0026604178L4556250611L6843566385L6167660696L5727360301L4401347002L3430136291L6043859437L4305340054L4435539303L1503314004L4632626328L1244318451L4835449333L2525630257L6513668136L6258765557L6620264212L4521547225L6835667357L4827549272L6850466508L0668707675L3409833118L2529525306L0539806418L3667736658L1560718584L3917342154L2914333143L1936415364L5242651446L2214119221L0658704577L1663607605L4261442644L1236811358L4716650134L6043361444L2358323574L2763627616L6568265673L2804626075L5363753617L1902820018L1028107291L3821331223L6234463334L3948239512L2805823108L4843246432L4768247651L0341206411L2403221032L0512108171L5348354503L4367140671L5246854467L5145350442L4353141544L5824659217L6534269351L2528126301L0021101221L5039548373L0011601096L1704516068L3343331484L2855529504L4267746698L3433636334L6103160071L3003631046L1913217132L3643838388L0610204142L2349819487L5711458105L6468765677L2202320023L1625614277L4910648056L6459165571L6337461363L3855841467L3450330523L3642539425L0565206682L3004629137L1045710477L5965261671L6859669586L0502806027L5247753461L3913140142L0619109211L3539128381L0748509485L0751706497L3127136271L5606553065L0565302654L1810218114L6652468524L1027811298L4133842347L0750415505L2352126531L4407243061L5566757658L0469805688L3808837108L0255603505L6527566285L6443567416L0232504325L2444823458L3940834457L5724265232L6633768346L1510715077L1628816338L2843830458L3441733418L1153209523L5268153671L1328613315L1637317413L6966869647L5458352573L2424621224L6306366083L2813227144L2307621086L6710467095L2302721037L2427423264L4203747057L0006101051L3528336273L5660858608L5868259662L3701836028L4742446444L0623305283L6245663455 +X15Y15Z2L0602214082L1406114081L0901111112L0110100072L0405209012L1108112071L0707208011L0301107002L0014101142L0405103072L0006203042L1008111071L1301214132L1403114012L1404210011L1113207112L0206206052L0603104031L1211110121L0512202141L0201203032L0105101042L0809209062L0609100121L0501204022L1110211082L0809112091L0000201001L1304114051L0102100001L1114113141L0401101012L1007109132L0714204131L1005110031L0611103112L0112102131L0208102061L0708206092L0007100101L1409214112L1300211002L0501106001L1114212142L0511104111L0704107031L0702208022 +X23Y12Z6L0303122021L1102219103L0503504065L0302105101L0200305093L0907100081L1309100071L0706221102L0500212014L0301605026L0104216063L0204408034L0910502106L1805113052L1406116041L0409310114L2106122103L1710201033L0510412024L1411222072L1503421106L1310519035L1306220044L0101201112L1701221014L0802503105L0603107091L0407113012L0000513106L0201405045L2104320086L0202606086L1804120091L0609411104L1607522005L0000101102L2002320095L0610110111L0709500116L1603422006L0203109041L2201113011L0808611016L1807519006L0611316083L0910318074L1608415035L1001602076L1203603106 +X08Y04Z8L0000107018L0100103014L0000806018L0500406014L0500701017L0001205017L0400506006L0701107014L0201202014L0201603016L0002107038L0102103034L0002806038L0502406034L0502701037L0003205037L0402506026L0703107034L0203202034L0203603036 +X36Y19Z4L0101113011L0702107151L0804112071L0803108051L0802108071L1202108091L1503106151L1501106161L0204104041L1500101041L1612109161L0216104161L1114117161L1616114171L0503105161L1216117171L0203121091L0403103141L2606132061L2706131061L2907124111L2212128121L2112129121L3103122051L2503130041L2304128051L2213131151L2813123141L3014125151L2707126111L2608128111L2408129101L2309131101L0000205052L0101204042L0202203032L0007205122L0108204112L0209203102L0115204182L2301323143L0216203172L0700219122L0801218112L0902217102L1003216092L1104215082L1205214072L2100235002L2201235012L2302235022L2403235032L2504235042L2605235052L2706235062L2807235072L2908235082L3009235092L3110235102L3211235112L3312235122L3413235142L1302402134L0709413154L0000308033L0012308153L1300335153L1301334153L0215410154L1505415134L1615426154 +X72Y72Z8L0000109098L0000809091L0000401004L0001401014L0002401024L0003401034L0004401044L0005401054L0006401064L0007401074L0008401084L0009401094L0202403024L0203403034L0204403044L0205403054L0206403064L0208403084L0209403094L0200402014L0300404004L0307404074L0401405014L0402405024L0403405034L0404405044L0405405054L0406405064L0408405084L0409405094L0604406054L0704407054L0804408054L0904409054L0608406094L0708407094L0808408094L0908409094L0507406074L0500406004L0601407014L0602406034L0700408004L0703408034L0706408064L0707408074L0801408024L0900409014L0902409034L0906409074L0009109008L0900100098 +X10Y10Z2L0802106042L0001208031L0701209021L0206209011L0004100022L0000206071L0201102022L0105101072L0809106081L0805209091L0407207051L0208101061L0108200091L0303202012L0702205042L0008200032L0703207011L0601205022L0506204062L0904209052L0404104031L0203102021 +X60Y36Z8L1702113248L1503212078L1304112137L1105311206L1309202336L1508310125L1707105075L2306307228L1804417226L1514210145L1824104328L0421106315L0319308307L0728200297L0523306266L0427322325L0228305186L0131309237L0706108136L0604201114L0502114124L0303404128L0405208156L1428114338L1229116328L1530415237L1616316257L1426311225L0310305095L0213106115L1417207175L0921312184L2400420057L2500121028L2600325026L1934213316L2219422338L2119222348L2019326255L3233335335L3331436337L3332437336L2601232035L2101124046L2206321176L2604224067L2435137357L3708324344L2433238354L2103221068L3803133018L3517237327L3617335226L3717236306L3918339358L3126322287L2229127315L2230126306L2603134037L3503259165L3603437055L3411429198L3412330204L3413337125L2607324085L2309224157L2316124097L2907436085L3325432296L2317423197L2528430268L2805131094L3307235084L3713334204L3524235288L2318124218L3009227126L3711332228L2614227227L2609326125L4006144215L5917244205L5406244196L3906245197L4905445208L5420344264L4016154194L5519250344L5520349345L5521254275L4609348155L4816356326L5115344045L5504351165L4625344305L5113346265L4925253257L5309150256L5308253246L4506250057L4608149128L5530243326 +X15Y15Z4L0401105001L0601114013L0213213023L0105105051L0014102131L0704210074L1208211133L0812110081L0612306141L1201213003L0408300142L0911114064L0411300131L0007208004L0913409121L1210307101L0502401072L0108400032L0608105074L0103301021L0814308112L0510201083L0800106001L1414310134L1209313103L0604405023L0714206144L1109412083L0409205083L1207113051L1213314123L0514206143L1207212053L0804307013L0208302064L0302300054L1009413134L0412103111L0408203074L0810309093L0313302122L1410114071L0812209132L0902408034L0604208041L0203202021L1313113092L0709406104L0510302084L0709108081L1201412034L1307214104L0611206092L1100309044L0412203132L0301304003L1002409034L1411213101L0411402114L0101301011L0907209052L0900111001L0809308102L0101401044L1404314044L0310203092L0504305041L0111301112L0205202042L0612205122L0505406054L0314102141L0011400104L1210411104L1201113011L0305104051L0401405014L1002309023L0609405094L1108112081L0900310003 +X50Y50Z4L3445116362L1019117072L0522204221L0819441201L2000412094L4030442411L0104204201L2735421433L3813228071L3021210062L4302448011L2010412151L1144412472L3338127344L1220303101L4749131464L2330243241L1726217104L3522430223L0509210074L3019300001L0542301444L1505326093L1303421042L1431329254L4437325204L0310408073L4933349322L3008212084L1842321414L0640200234L1224205234L4223343312L2805222012L3649143492L0737139174L1011410083L1746243481L0813412131L4335123151L1133124311L3716338194L1713316183L1841426312L2224424224L4346434474L3325241251L4704346054L1729418154L4445346484L3227231314L3221336021L0508400002L3501330004L3541233473L2526425333L0805200011L1136431454L0645314481L3138435273L1324217263L3704327124L0635411131L4239129461L0731319114L2039121371L1928121203L0042425323L0006308083L2426117184L1217104442L2506230003L0530303273L1319217152L0634108311L4536247484L3945237413L1240404344L1806433064L4928149323L3100430091L2913228113L4637246462L4305443171L2923123191L1018313203L0736306353L4923239164L0839404354L4911445214L2341421484L0846407471L0215302151L0235201374L4801242031L3008431074L0313208122L1747115471L2426222254L3801436004L2114220061L2816420154L0607201041L3614330224L2709128102L0726306221L2942430452L0240201331L2421225164L4503349024L0540409322L4421342213L3237245363L0124100232L3723135172L2239425362L1524117241L0849205494L2724132241L3321135203L4613144131L3513134161L1301221002L2618129221L3831242302L0543403444L1904417063L0309303012L1642114421L3817240191L0926410274L1331413291L1911119113L0222302121L4125449253L2943233494L3120130133L2029212213L4844448473L4820448242L2947427462L2049122491L3634433344L2301324003L0722410253L3937330394L2428125291L4041235202L3314336102L0735411371L1705421004L2902327083L1737421343L3211229204L0028301323L0333204301L0042305413L2502126011L0737311282L0819301101L2719326143L2628225281L2639223403L4607241092L2608224061L2036312442L3749340493L2634126322L2025321283L1132413304L1832316302L0440204433L4505442002L4621149182L0343111393L0510107102L2447224452L4603148084L0112403124L0100320014L3738432404L4129239293L2826232262L2220423212L4635444454L3736241431L0516105142L3944443484L1625212271L0043411404L4442145451L0636307362L0839308414L0411202112L3204431054L2507323073L4208343064L0841206474L4841448384L0738206392L2829331213L0405301013L0929309263L1236111334L3901237022L3107129093L2110221122L0904405071L1941119441L3302332013L1049407494L0220413183L2641125451L0134400334L3236131372L0247402443L2937330363L3612240131L4736148364L0306403084L4628348293L2239320294L1146312471L1816120151L1523217232L1405316074L1602410052L3005133061L3430134293L4526141261L3304236013L0107203092L0629304313L2739125391L1420412254L4401143021L1737313394L0948311492L0505104093L0914110182L2929129372L2244425483L4113341153L4315240143L2348322461L0049204492L4743345444L0102301082L0604405074L3745137472L1422117221L3614440123L3503436044L0114209191L4629346321L2213122111L2722425224L0144103441L0437404394L0303204033L0118402174L3827443292L1649214492L3803138051L2829127251L3809339064L3739138331L1101207041L3739443394L4611245122L2902226023L0812410154L3238327384L0047102481L3644128393L3421134222L2340123421L0938210452L0902319013L0542105432L4021441204L0416407154L4831343314L1401217003L1333422332L4723347253L4047237471L3018132193L4305242062L2002116011L3337432384L3922340213L4123138231L4238142361L2408125103L1212311143L2620129182L3124128251L3218435174L0134202332L1840319453L1021211202L0718101161L0943110421L0643408434L1046408484L1503315064L0122303241L1333316361L1348412463L0649108481L4639243391L0027102291L0419406184L1409314181L2640325402L2105120042L4419443164L1209111121L4042239402L3042131443L1407311052L3134427343L4841249392L3709137071L3116331144L2336219391L4817148221L3340333383L4246143471L2600427023L3905239014L0742207413L0743108442L0147301481L4834447342L3414235111L4638446364L1818116181L3141330432L1242113391L0525308242L0431107311L1336214352L3928341293L2522228222L4849347393L2325225282L2401425034L2109117143L0801113033L4614242142L3140329403L0239104331L3846143451L1935216344L0219404184L0339104381L2720126162L3537437373L3435234341L1132313323L1035410323L4716348202L3836241352L3530235322L1934419303L2318422203L3733435313L2202118011L3605236041L0139403421L3149229482L3412236152L3911247081L0320101211L1500216003L2905332081L0524105261L1616415184L2844228422L0400404024L3309330093L3926341234L2817328193L2117319173L4243342403L1525314263L1101112023L4948145471L4101341033L1439216392L1428317293L4947146471L3204333033L0227406254L4920448173L3024231231L4535145342L4541444424L3425235251L0317201192L1605117052L4823447223L4703146021L4501447014L4815247131L3829239292L1014210162L3314131173L0613306153L4045338413L3740438393L0435105361L2038417364L2705126071L4107344073L0817410173L3323337244L4949148492L0628406331L2228123282L3831438294L1540415413L2831329303L2027318281L4004338022L1644316434L0214304143L4738148401L4318345193L4247239432L1022411214L2827338273L0448103462L4733446344L2704225074L0935409394L0226404243L4044342453L3436430352L2331221302L1324316243L4723147272L3039232392L3537234363L1507116081L4140140411L0336102381L0127401314L2447423484L0027300262L4814448124L3947341462L1424414223L2724229242L3504434034L4924149272L1805419034L2903129051L2143420443L0227203282L1239212413L4328243262L3446131461L2340222412L3348230482L2234120341L2120220212L4604148021L0903110041L4436441354L2424422274L1732216311L3344233462L2434324322L2543424414L2319323173L1225114253L1919320203L1544317464L2322122231L4333439374L1043310444L0201105001L0337202342L1622316232L4425346263L3134329324L1542114411L4320243222L3541137401L2218221192L2619224192L4510144071L0618203173L2235327372L4005242052L3834236342L1344113443L4112446114L2606127041L4518143192L0225203262L1103209033L1837420404L3438234361L4506445084L1122111223L2920229212L1617317192L4037341364L4210245102L4132340334L1019411184L0445302453L1821315214L0646304444L0436404383L4813148111L0348403472L0319402203L3432133302L2527426254L0125301264L0907210071L0206401074L1646417441L1637314373L4249242483L0415202152L2123422233L2405322053L2804329044L0629406274L0340101422L4842347413L0628207302L3440335393L0117101182L1946117461L3120229192L0511303113L0137201352L3906240072L1505214042L0205401044L3242233412L2721227243L2141121391L3827240251L2831229301L2306421064L1926319283L2041119431L1038209392L3012432134L3700238013L3744238443L3545136461L4303442014L4644447434L0320304222L0707408064L1932320322L0638207381L1526115291L0039302403L0405403044L4430344293L1528215274L3340434404L4631146291L0132202312L1000313002L1532214312L4043438434L4010139111L2301224023L4332344313L3317433153L1733417304L1913422134L4343242413L0227101271L0205102071L1904120031L3907438074L4112243122L1739418384L0700105021L4243441434L4743147461L1031111301L4704448054L4505244062L3530138291L3129432274L3746440474L0417203182L0235400354L3002431014L2747228484L4909149102L0234401334L0909109103L0514406134L3649336484L4217141161L1909420084L4543245421L3002329013L0428106291L1937219393L1949220482L4714245152L4814348134L3919139181L4226443254L3001130031L3006329043L3342134441L2842428404L1311213142L2618425184L1410212102L2338422374L4336444354L4349342493L0315102141L3542135443L4503446044L1223213233L0029100331L4833449344L0638405374L3710137121L0832409314L2413423123L2310125101L2640225422L1138411374L0708406083L4940249412L3641237432L0332204322L3914239132L1504415034L2715429154L3433336333L2836129361L4641246402L2505223043L2023319253L2907428084L4045138451L3106131051L3727435274L0541108411L1502116022L0534304343L3247332464L0946110461L1826418244L4209341083L1131112311L3220430204L3015130141L2012420114L2417123171L2315422154L0134300343L1612116101L3428133281L4943149451L4447345483L1135209352L0336301363L1228312293L2047321473L1427113271L3204232033L2041220422L1537316383L4118342193L1022208202L4721449234L1744418444L4910446104L0746307473L3729336293L4524145251L2844427444L3624336223L2623127231L4404344034L1029411294L2016421184L3135231362L2812127111L0102400024L4840448394L0837309373L4915148151L3230331303L2333422334L2323223242L3505435064L4230441304L4623246242L4301344013L1309313103L2813227132L2034318343L1129210292L0919309194L4009239092L3816139162L2822428214L0619106201L3925440254L4705246052L3223433234L4142342423L0603306023L3127130271L0815209152L1024310242L3124331242L4810348113L3443433444L3804338053L4422144211L4518445174L3416233162L1333112331L1849217492L4716448164L3301334013L1846219462L2023120221L2533126331L4616145161L3345234452L1703318033L0430203302L4547447474L0631306314L2142121431L3103431044L2914330143L1813218131L3825237252L1236312373L1141411424L1831418324L4247141471L3714138141L3023330234L2303222032L2728227292L0822107221L3115431164L3403234042L0116401174L2740227392L3408134091L1515115161L2102421034L2731327333L2344223432L0123202232L4211343113L0111401104L1813417134L1613316132L2521324213L1027109271L4336243352L3322333213L2818428174L4900449003L4718147171L2409325093L3928139271L1040111401L0146401474L2926230262L1306313053L0743407444L1013410144L3304133051L2902129011L0804208041L3810338104L1648417484L0041300414L3205332063L4039140401L1802219022L4804349043L2624225242L4205442064L0905308053L2246322464L3534434344L2243322434L1307413084L4541345423L3502335033L4844248432L3135431364L4838148391L1538116381L0025100241L0105401064L0711307123L3031230322L4100340003L2613125131L3947239482L4228242281L2516125151L4039441394L0901409024 +X20Y35Z8L1916104218L1917204208L1406104196L1934305197L0905205206L1420404266L0016414195L1519410346L1520309348L1521414277L0609108158L0816316327L1115204046L1504411165L0625404306L1113406266L0925113258L1309210257L1308213248L0506410056L0608409126L1530403325L0017400346 +X36Y24Z1L0003102031L0302105021L0101104041L0005104011L0603108051L0605107011L0801110011L0802110041L0009102091L0308105081L0107104101L0011104071L0608108061L0606107101L0810110101L0809110071L1203114031L1502117021L1301116041L1205116011L1803120051L1805119011L2001122011L2002122041L1209114091L1508117081L1307116101L1211116071L1808120061L1806119101L2010122101L2009122071L2403126031L2702129021L2501128041L2405128011L3003132051L3005131011L3201134011L3202134041L2409126091L2708129081L2507128101L2411128071L3008132061L3006131101L3210134101L3209134071L0015102151L0314105141L0113104161L0017104131L0615108171L0617107131L0813110131L0814110161L0021102211L0320105201L0119104221L0023104191L0620108181L0618107221L0822110221L0821110191L1215114151L1514117141L1313116161L1217116131L1815120171L1817119131L2013122131L2014122161L1221114211L1520117201L1319116221L1223116191L1820120181L1818119221L2022122221L2021122191L2415126151L2714129141L2513128161L2417128131L3015132171L3017131131L3213134131L3214134161L2421126211L2720129201L2519128221L2423128191L3020132181L3018131221L3222134221L3221134191 +X30Y30Z3L1212111103L1811311041L0412101102L0410218072L2612328231L2411128111L0503313081L1810314062L2301315031L2415326192L2224229251L0323201211L2911229192L1801317002L1128115162L1629211293L2026212291L1701317033L1714120233L2105121031L1014309152L0716104051L2221128271L1205311042L0420308243L0718204271L1221311252L0223201273L0502209071L1314109142L0317204222L2312319131L2026119241L0302116022L1611118011L1224110263L2229116171L1319220271L1710114091L0607203032L0513203131L0109100161L1424315231L1727113241L1416111182L1213213112L2510316102L2521228222L0321306273L2305228003L1501310013L1918120182L2226222241L2313220152L0117203201L2700318033L2103228022L1806215073L2813329182L0318202172L0903109022L2629228193L2610123121L1528320243L1607115061L0124103231L0216103141L2506223051L0624307253L0902110011L1128201291L2907228011L0109202103L2923329263L1016309153L1912320142L1807118051L1216211143L2504124051L1714217113L1828312293L0200100032L0705208072L1321312173L2007120031L0001201002L1312315123L0819107181L0927210281L2410225071L2726121282L1705316033L2609328093L2503321011L0018101201L2328222261L0301306011L2617225202L1112115142L0712108111L0624109221L0606104101L2728228272L0607304073L0514206161L0800306003L1006107042L2013321143L0827310273L1206111051L2715128141L2608122081L0116301183L0313302102L0715209131L2120223212L1627217243L2324322203L0423303241L0818209193L1624315241L2512327101L1912117111L2003323033L2416325132L0504106051L1404314022L1618317143L1318213191L2811326112L2516325142L1619315203L1606118081L2102222013L2806223021L2622324223L0805112041L0923309252L2307324053L2625225232L2023122212L0521105191L0717307153L1920118181L1226312283L2116122141L0727104261L0615105141L2427325263L0204100062L0225200253L1713115131L1928320273L0308203052L1822214232L0811310123L2428123271L2522127231L1109310073L0405207053L0215201142L2815127152L2905128041L2217322152L1216113171L0105202022L2317320172L1810114093L2707128081L0528306263L2418124161L2802329032L0411207122L0619305163L0208201103L1725217272L1108112092L0702208013L2106122063L2921129231L2118123181L2619324193L2908229102L0819307192L0022101231L1315115151L0729209282L0125201272L2708227093L0922308233L1320212222L0424305242L2606328063L1413214123L1819316203L0317104181L1719315201L1315314162L1212312133L2609224092L1212211132L2717327172L1428117281L2010220093L1316213152L0507106081L0113101121L1428314293L1117211162L0812108131 +X72Y72Z5L0000171715L0001170715L0002169715L0003168715L0004167715L0005166715L0006165715L0007164715L0008163715L0009162715L0010161715L0011160715L0012159715L0013158715L0014157715L0015156715L0016155715L0017154715L0018153715L0019152715L0020151715L0021150715L0022149715L0023148715L0024147715L0025146715L0026145715L0027144715L0028143715L0029142715L0030141715L0031140715L0032139715L0033138715L0034137715L0035136715L0037135715L0038134715L0039133715L0040132715L0041131715L0042130715L0043129715L0044128715L0045127715L0046126715L0047125715L0048124715L0049123715L0050122715L0051121715L0052120715L0053119715L0054118715L0055117715L0056116715L0057115715L0058114715L0059113715L0060112715L0061111715L0062110715L0063109715L0064108715L0065107715L0066106715L0067105715L0068104715L0069103715L0070102715L0071101715L3600136004L0036535365 +X72Y72Z2L0000271712L0071271002 +X40Y40Z3L0313329331L1415127043L0237337351L0039335171L3816115013L0016121091L0206138381L1119118151L3703139001L0317137381L1000139393L0932139392L3611108333L3401100383L0125104033L1911124211L1727119261L3117132101L0015106341L1201116051L0025325061L0539333181L0508330061L3200326331L0700234041L0804109001L1614130331L0516122331L2007124221L1218128301L1804100392L1301133383L2125130073L1509105093L1118138393L2705137361L1429127341L3013138361L3007136121L3118137141L2100225033L0204205022L1412338392L0738339162L0028236043L1501236022L2811221232L1408209192L0622205052L2634237192L0633228073L3613212323L2101234042L3438219373L0802216032L2710219363L0038209372L0405207242L1124225112L1217217092L1732236343L1239214193L3008237113L0401303312L1316333152L1004217032L2628231272L1125224242L1227230172L0137210372L0504206062L0611326102L1932234372L0226207063L1512331202L3227236302L0509205162L0233207282L2124229112L1231219382L0314305222L2339334172L3226335352L2934336142L3026231133L2633236332L3502239083L0032301033L2434333393L0507310043L3617336333L1601333003L0907307333L3330336353L2023323233L1305324123L3501339073L0737311303L2239329073L0239304353L3731332303L1106324053L2705332163L0238306243L2029318283L1010310273L1521326153L1207320123L2206322123L0736311293L1334318253L1738319273L0315303173L0419304213L2120324213L2222327233L2319324233L0632307343L3019331273L3418335243L3409337103L3505336133L3605336073 +X60Y60Z4L3639150041L4148440401L2447445584L1336216534L3530235114L5950244482L2922448111L0329310371L1009425043L1923157584L3623358004L1157414342L3634223362L0756215591L4141427494L3018338093L0451102401L4617436201L2415337113L2114425053L5326114374L5748452494L3337234341L2545134414L4027331243L2338328564L5945256401L4629259012L1423213231L1824440141L4850237392L0044309571L2726336231L3244436444L4714449101L4745437383L4540348391L1516328084L0445107391L0217304351L3401317084L2352324524L1225114234L5023355583L0314312441L3023305593L2204124041L4820248274L4218347002L4015432134L4101346002L0841304224L4637452364L5652153371L2723221171L1455410521L5255451584L3235131313L3613122121L2945424504L0248303351L1131415334L0855314544L0855412573L4445140323L2202319014L1306212032L1007305054L3604235041L3927335214L0157402564L5300354011L1726318351L1841138401L0803412004L1245410533L4559327501L1244321521L0641306411L5224340033L2704229083L2805429043L0853410554L5640352441L3513146121L1828313253L5631157321L2344422453L3202340011L5325157283L5907258194L4310352214L5753137582L1954220541L2815237081L5118157194L4750449534L4950243291L0645301344L0447408414L0720405224L2847322544L0914402081L5902155241L0531201342L4043336501L4828146254L2019317122L4705355142L5540155363L3314237124L3104329044L0253307581L5844451454L3943336392L2851131571L2111222131L0336301401L4922451222L3626221201L0048301391L1647115351L5914249044L4535353343L2508137102L1858416594L0821405214L4710140121L5314254202L2257119541L3445235491L1749219434L4946154451L0627316342L5948253451L3421417213L0344116393L1505416064L4836455313L0641403442L1509207021L5217448112L4330350284L0918113232L1640318423L2936427354L5329159411L1251126412L1246212421L2309325134L4719346283L4619453171L5556457524L3627437334L3537131321L1541417424L3205231022L3049435514L2823329223L1322309273L2221135251L3401238003L4255343562L2220315374L5615356164L3024137332L1230411284L1215410081L1002116011L0909109122L5655357541L1913420131L4225344252L2309226071L1444217481L4635452343L0634404331L5456252522L2403120111L5951259551L3401430012L1151220553L3947449524L3515134161L2717329142L4603247013L0738411344L4501441024L4012443104L4128437324L4144438444L3852236512L2531130302L5049154492L4203241022L2916129191L1958420554L4745159283L4939248434L4432447354L4845254442L2428115263L3437231363L2037322344L4753449531L4609345084L0830411313L4121238311L3231426274L5715256163L0313203043L1812316184L0326400184L5929453314L3110433114L0411401072L0051205422L4418343133L0151102531L0130306284L2359316522L4525344274L2650352403L4832444364L1011109101L4443247442L2504126021L3400138022L4244340444L3924438274L5722256243L2934331343L2422422204L5011355081L3325231242L2335118263L4152241584L3427326253L0351203532L5345454444L5257358543L0518100272L4022335161L4716241182L2205310022L0625405244L5232254322L3523332263L0522205211L2728335294L1741215361L5606458053L1047206464L2226122241L2128220292L4106438064L5021149201L5506158051L2433229303L2005215003L5836259314L0842407464L4632247332L0836107351L4208147081L3222435194L1351312521L2541434384L2629424264L2758426523L0424206221L0818202101L3730339274L1805419044L0412403142L1327113251L1746215501L3306333083L2442432473L5058148581L3229231262L4841249441L1035112374L4256143592L1929319314L5204250052L3722438264L4239240411L3658338532L1906323064L5441152412L3345439531L2724430244L5741456513L4917445183L2245228432L2027320281L1305114062L1025110231L1840118431L5312144163L2816122163L5416452154L2947430464L5853158511L5457253584L5500155003L0833109321L4320436212L5859152581L0822306222L4749337524L3719443224L1210211111L3251430554L0256205591L0726210292L2900136082L0847107412L2131219312L5609352082L0446404442L3020330174L2636126311L1747319464L1906223031L1647415481L1656416584L4603150031L0834310333L5247353453L1653315492L3335133331L2112222123L5658256571L2805328071L0127205252L3505438004L0506109074L4403447034L5527157203L1740318453L1242411434L0554403554L1923416204L5655455544L3815138201L2256124584L5749153363L1925420244L1555216582L4313141171L5749451524L2721326181L5647455413L0309402114L0231200194L2537326382L4432343283L3700336012L4324344234L0022203261L4350141482L3118231212L4823248271L3310136091L1520314191L3648338454L3317229171L2424425224L3908144021L1312411124L4421244184L0530206282L2920433194L3258333573L3925340252L2101320002L2845428474L1036109371L0255101581L2418323173L5740359472L2634325333L0653305523L3304232072L5139149371L5428357252L2402426023L1054111531L2351122521L1445411424L0011411211L1005208093L1438313361L0712408122L4729448323L2757230552L0546207452L2723326231L2307125051L4949248461L4215144102L3341331384L3459134571L0450103482L2416131141L5140452423L1551314504L1930125271L4158231584L1304209042L1720120221L1737217404L2417327191L2659129561L0925306253L1117412183L2308125062L5852259532L0247303463L5608356061L3653335553L3119231183L2832431314L3940441443L5655255501L4446145442L1515113171L1645314434L5727251282L5446252463L3903437034L3921142224L5407456094L4233141354L0453104571L2457125591L0322102191L1715217193L4218243172L5154352531L4139137371L2725228292L3005128061L5224148252L4527347263L0716106171L5117245191L1147208461L0809207082L3204431054L5519156181L3053329482L4035238352L2844128421L5013152091L0206301083L0012301154L0503406012L4143339432L5716454134L2534424364L5735456334L2100422024L1313213091L0437306314L3859437584L1315111131L2604225032L4127440244L0603306063L5509456113L2236419394L1729217272L5022347232L0650209472L2454420481L0203403003L5738453394L0302204012L2600321003L2142119421L1144311432L5039351403L1738116372L5136351352L3445138461L5610159132L1532319343L2301222004L3321234181L0119301211L1543115411L2306223053L1654419554L1305413074L5255254543L3558237572L3045231421L4134142351L3535433344L4452446543L2322220181L3340234411L3258234582L2853428514L2607425114L4833153321L0817306173L4845351423L0157300561L5320154191L2439424414L4610347113L1044313484L5522156211L2037416374L5458159591L3726334274L2816225151L0919308192L0903307024L2818427214L3006228031L2051419533L5931258292L4849349593L2733329314L0447207472L4308242071L1629318293L3537336394L5133450333L4631245283L1304307053L4618251161L0033301323L1031307322L5803254052L0511107131L0655106531L0420303281L2002317023L2652124521L1333416292L1232215322L2042221432L3355331553L5026252242L4228443293L5727454263L5703455043L3352236541L2121422253L2548125512L3140331433L4105241032L5500258012L2912427114L3327237313L4621445223L5925159242L3412235164L1038409344L3815440164L4846349482L1809217102L5017248193L2135324324L1913315171L5732355323L0637310373L2010319092L4932251303L1326214252L4040239392L5239154422L4749250481L4428148291L5511155092L4157143591L5535358372L4031139301L3631137232L4931350294L3342332434L4305143071L5747357413L2834327334L1835215333L1559215582L3141231394L3250431501L2654122541L2926328253L4146441473L4033340353L0724107224L3241234392L3403435044L2544326464L2955228533L1309411104L3602334022L1948423483L2342124401L2958428553L2858325593L3648438503L0151303533L2442322443L1907116081L1729316304L5556258563L2109224093L3902440023L3937336373L5908257093L4354141541L2700330003L1304414012L3150330523L4906144124L0045101461L1119212152L3512433134L3431232311L0154203552L1157115571L3841338404L5625254252L1857416573L4726145261L5529455264L2007221073L4817446172L1650416524L1310412133L3058233591L4814451124L2530220324L4641445404L4231343323L2835432354L1202411044L4914250112L4950147491L2434323322L4228140261L3957140581L0647206491L5803456044L4153341552L5539254371L5030148311L3315233174L1014309141L0549304504L5649256462L5256448564L1246311454L3606236072L1341313422L4203343034L0003100061L5442452424L1034209331L1105109061L1503113041L5329252302L1704218032L4807451074L1622416254L1631114311L4005338051L2437220351L0849114481L0144401424L4247140501L5348153511L3707337063L1349114501L0635209301L0125103241L3103431014L0635309353L1839219402L1626316252L3632140341L2017319173L5139351373L0407305101L3033229322L2600128013L0010100081L4358441574L0851108541L3458432584L3759135581L3546437464L0312200111L1134213341L2208422064L0955308584L0318301163L5906259023L2022319213L1911214141L1617415153L0252401544L0624106232L4137440383L0437101351L5645458454L4226342271L2356220572L1108211073L5452453534L2310118042L1736119381L5124456234L4507246062L1504215053L0920108201L0001300054L0615409154L0458403594L5531456313L5126452263L3041231413L2645325453L4756245551L2028319294L3143132441L4642247412L4343242432L5907358063L3228332271L4342344433L3351232492L2946232453L2340321383L5723156241L3614237133L1235211331L1858117571L0645206461L5743158471L4909445094L1447411474L0122202232L5536456384L4105444031L0215200142L4912349103L2332421324L3018431193L4044139492L0127401254L4847447464L4707447043L1546116462L1509314104L3522437204L0142101441L4016242142L0413103152L5704457053L3755236552L0049302494L1050210511L1116310183L2146122471L5916258152L1209311083L0216101171L0023200262L2845125461L5304451034L3017129192L3543335413L1704117021L1001112011L4451145522L5459358593L5032449324L2616427202L2509124101L4942150412L5421454223L3330335324L4401345013L2454323542L4523144241L0751105511L4447343483L5310350083L0130400294L1457314564L2418424213L2358221583L0911309104L3549233492L1852218512L0737403372L2757126561L1636318363L4110339111L3817338192L0331200301L0240201393L1059111581L0201102031L3506134082L2658228572L0430102301L3449434483L5256255551L5748258492L2126120272L3800137002L5811358112L3225130251L5707157051L5349253503L1016310174L2644424444L1058109591L2145222441L2228423294L2544124441L4856249572L2520425202L0321302202L2424222251L0339303422L2701228002L0927108262L3749137501L4320142231L0132100331L2447225482L1646415454L5449452484L0754207563L1326411264L3734338343L1337412394L0542305434L2015218152L5102250023L1907218062L4631347334L2814431123L4914448154L2327224252L0652307533L4416142161L0537305353L0127100291L2717427193L4233243331L4336241362L4337143381L1050410514L5909258093L0717109192L3917339183L4208340083L5558255572L1816117171L4552446534L3133131351L1103411024L4357342573L3314134151L5259153592L4643348424L4250444494L4639146362L2626225281L4547345464L5138151371L1811417114L0813408133L1457414583L2016319114L2723426244L4120241203L4740447414L1755315553L4304343022L5615257142L5143250422L1339214382L2246321474L3547134472L2842327433L3204131051L3624438254L0207104061L2631426304L1649318514L0305403064L3330133311L1207413064L1409312082L0202203012L1958122581L3758136582L1046112451L0848111491L1413315124L1040109391L4153442554L4230242282L4541445424L4453344523L3410435094L0044200422L1846118481L5801459004L4520146191L5022248222L1957420594L3402433014L1514117141L2214223142L4512449124L0053302534L1743215432L2110421084L3356431564L5739157351L4141342404L0456404574L4753144531L1522115211L0402304034L2257422564L2233122321L4826449253L1633417334L3544134441L0944409424L2915328153L5220251211L3108229082L0118202182L2222222202L3012130141L5906359043L1512215132L0431103311L1339315394L2152321533L5838458394L3510134101L4715247132L3708437094L4637147351L1655216541L1321313214L2508226092L0703107051L2655427564L3539135381L1255211542L3946339453L3644138442L5114250142L3921340222L1813318122L2414424134L3828237293L1244213442L5545454454L0111201102L2338426384L1014209152L2604327043L2840328394L3346433474L5036251362L5113151121L2748426484L0049100461L1220310203L0752208522L4107442074L0511406104L4900351004L3422233222L1910319102L4608144081L1848416484L1315413174L1330313293 +X40Y40Z4L0000139394L3900100394L0039139004L3939100004L3800100384L3700100374L3600100364L3500100354L3400100344L3300100334L3200100324L3100100314L3000100304L2900100294L2800100284L2700100274L2600100264L2500100254L2401100244L2301100234L2201100224L2101100214L2001100204L0601119011L3938101004L3937102004L3936103004L3935104014L3934105014L3933106014L3932107014L3931108014L3930109014L3929110014L3928111014L3927112014L3926113014L3925114014L3924115014L3923116014L3922117014L0121119391L0222118381L0323117371L0424116361L0525115351L0626114341L0727113331L0828112321L0929109311L3722121381L3623122371L3524123361L3425124351L3326125341L3227126331L3128127321L2829130291L1030111311L2930128311L1801422014L0220420384L0321419374L0422418364L0523417354L0624416344L0725415334L0826414324L0927413314L1028412284L1129412304L3823422394L3724423384L3625424374L3526425364L3427426354L3328427344L3229428334L3130431324L3031429324L0020219392L0121218382L0222217372L0323216362L0424215352L0525214342L0626213332L0727212322L0828211312L0929210302L3922222392L3823223382L3724224372L3625225362L3526226352L3427227342L3328228332L3229229322L3130230312L0000220283L0100220273L0200220263L0300220253L0401220243L0500220233L0600220223L0700220213L0800220203L0900220193L1000220183L3900211293L3800221283L3700221273L3600221263L3500221253L3400221243L3300221233L3200221223L3100221213L3000221203L0019221023L0119220033L0220220043L0321220053L0422220063L0523220073L0624220083L0725220093L0826220103L0927220113L2100223002L2500229002L3128221113L3227221103L3326221093L3425221083L3524221073L3623221063L3722221053L3821221043L3921221033L2019220382L1920219372L1821218362L1722217352L1623216342L1524215332L1425214322L1326213312L1227212302L1128211292L2121221382L2222222372L2323223362L2424224352L2525225342L2626226332L2727227322L2828228312L2929229302L1912319393L2012322393L0000339003L0001302013L0601339013L2702339023L0119338213L0220337223L0321336233L0422335243L0523334253L1918306243L1819307253L1720308263L1621309273L1522310273L1423311263L1324312253L2118333263L2119332273L2220331283L2321330283L2422329273L2523328263L2624327253L1230320383L1331319373L1432318363L1533317333L1634317353L2930321383L2831322373L2732323363L2433326333L2534324353L0121318383L0222317373L0323316363L0424315353L0525314343L0626313333L0727312323L0828311313L0929310303L3823323383L3724324373L3625325363L3526326353L3427327343L3328328333L3229329323L3130330313 +X15Y15Z3L1212303012L0506203113L0705209113L1102212113L1005110033L0414200012L0701302001L0107200083L0612305143L1102112001L0702109051L1105214022L0512110042L1309113071L0507206063L1212114121L0612213121L0303306033L1110112081L0312202142L1013214123L0710108071L0806302012L1108214062L0701203023L0900303021L1307313103L1114111121L0004100081L0011101101L0614104141L0914310133L0507106061L1101113011L0914108131L1010110071L0513303101L1204110011L0305304063L0809206082L1309214082L1301311002L0500107011L0901208002L1209311083L0506105031L0210202113L1106310053L0102301003L0802308043L0311203121L1111311123L0205301053L0313303143L0909309103L1013110141L1014311143 +X72Y72Z8L0000171023L0000271022L0000371021L0001171013L0001371011L0002171003L0002271002L0002371001 +X03Y03Z3L0000102002L0101101002L0200101012L0001101023L0001201013L0102102013 +X72Y72Z1L0100161061L2300164131L5500142501L0062106031L1771171341L2271166661L5967146631L2565161681L2665167661L2467159701L2369169691L5668157661L5569157671L0200159181L0116125331L4701170011L0209139261L6117103351L1628148341L0428103091L2400150061L1860119691L0114152461L2107156021L2158170361L0117112321L1213168041L0342114681L1643151591L5544161161L1115134161L1116134151L4342124521L0238146371L1449120631L0259113681L2243138471L0642146381L0404151031L5616159471L1216135161L1137126331L3911141261L0214159331L0269111321L6315168051L1741155561L0540109331L2322134211L4353129461L0713160351L1362118691L2244127471L0934108431L1120126191L1410140261L1957168571L5808146391L6653169311L0765166521L2719129191L3044125471L0425133311L1352110631L0405163111L0858110571L2645143541L5809165141L0515132261L2649141431L1252109611L0604141061L1955143411L1704153121L1448119541L2405145181L2447142511L1058113461L4605146211L1639122391L4613151111L4710146221L4414144181L0516105251L6822168331 +X72Y72Z1L0000108151L0004171321L0013171421L0016171431L0030100631L0046170601L7164100711L7165128711L1001170321L0500105031L0501107011L0502107021L0001100031L0002102021L0705107071L0506107061L0005106161L0105101111L0106105101L0117171541L0015170341L0014165331L0518165321L0017123261L0024133411L3330169531L2228100291L0025121281L0825108271L2312169321L2412168321L2512167321L0226108261L7065131701L7066135701L7067139701L4669169691L4968143701L2605166051L2705165051L2706165061L3706149061L2707150171L2708150161L2808151161L2809161131L6009162101L5309152141L5210152131L2810132101L5512153131L5610154111L5710157131L5810158131L0664144641L0764101691L4064102661L3664103681L1564103671L3264104671L2565122661L2864109661L0965120651L1664120641L1204162311L0031169571L3131124591L0045169581L1632100441L1521140211L6421164321L1905161231L1805137231L3020130221L3021136211L2247106591L1458170611L0062170621L1457121611L1749119501L1859120591L2149120601L1205117051L1605113171L1606114161L1417116191L1607115161L1507115151L2216145201L4420146201L4118143181L4117141191L3531168511L4034143341L4434134391L3933135391L3532138381L3632138371L3634136371L3734137371L3930155361L4035164521L4330155341L4831154311L5332154331L4036162521L4840160521L4941159511L5042158501L5143157491L5244156481L5345154461L5347155471L4137147391L4037145391L5738169491L6847169481L6039169461L5938167441L6239166431L6340164411L6540165421L0234104351L0342105441L0434125571L0433126571L1534107431L0836108431L0741109421L0943125431L1035125421L1036111381L1337114391L1040110421L1041113411L1831143561L1839142451L4145129551L1838140541L2932118371L2832118361L2833119361L1933127331L2033126331L2034126341L1456100611L1447100601L1354101591L1347100591L1247100521L1248101521L1148101511L0249102511L0250110501L4045132471L3845139471L4046139521L3645140511L3646134491L3547135491 +X16Y20Z5L0002100041L0004200044L0002300043L0002500045L0001100015L0005500091L0006200083L0007100084L0007200081L0010100105L0010400132L0011100112L0016100173L0015100182L0017500194L0016300184L0015300165L0102101041L0104201044L0102301043L0102501045L0101101015L0105501091L0106201083L0107101084L0107201081L0110101105L0110401132L0111101112L0116101173L0115101182L0117501194L0116301184L0115301165L0202102041L0204202044L0202302043L0202502045L0201102015L0205502091L0206202083L0207102084L0207202081L0210102105L0210402132L0211102112L0216102173L0215102182L0217502194L0216302184L0215302165L0302103041L0304203044L0302303043L0302503045L0301103015L0305503091L0306203083L0307103084L0307203081L0310103105L0310403132L0311103112L0316103173L0315103182L0317503194L0316303184L0315303165L0402104041L0404204044L0402304043L0402504045L0401104015L0405504091L0406204083L0407104084L0407204081L0410104105L0410404132L0411104112L0416104173L0415104182L0417504194L0416304184L0415304165L0502105041L0504205044L0502305043L0502505045L0501105015L0505505091L0506205083L0507105084L0507205081L0510105105L0510405132L0511105112L0516105173L0515105182L0517505194L0516305184L0515305165L0602106041L0604206044L0602306043L0602506045L0601106015L0605506091L0606206083L0607106084L0607206081L0610106105L0610406132L0611106112L0616106173L0615106182L0617506194L0616306184L0615306165L0702107041L0704207044L0702307043L0702507045L0701107015L0705507091L0706207083L0707107084L0707207081L0710107105L0710407132L0711107112L0716107173L0715107182L0717507194L0716307184L0715307165L0802108041L0804208044L0802308043L0802508045L0801108015L0805508091L0806208083L0807108084L0807208081L0810108105L0810408132L0811108112L0816108173L0815108182L0817508194L0816308184L0815308165L0902109041L0904209044L0902309043L0902509045L0901109015L0905509091L0906209083L0907109084L0907209081L0910109105L0910409132L0911109112L0916109173L0915109182L0917509194L0916309184L0915309165L1002110041L1004210044L1002310043L1002510045L1001110015L1005510091L1006210083L1007110084L1007210081L1010110105L1010410132L1011110112L1016110173L1015110182L1017510194L1016310184L1015310165L1102111041L1104211044L1102311043L1102511045L1101111015L1105511091L1106211083L1107111084L1107211081L1110111105L1110411132L1111111112L1116111173L1115111182L1117511194L1116311184L1115311165L1202112041L1204212044L1202312043L1202512045L1201112015L1205512091L1206212083L1207112084L1207212081L1210112105L1210412132L1211112112L1216112173L1215112182L1217512194L1216312184L1215312165L1302113041L1304213044L1302313043L1302513045L1301113015L1305513091L1306213083L1307113084L1307213081L1310113105L1310413132L1311113112L1316113173L1315113182L1317513194L1316313184L1315313165L1402114041L1404214044L1402314043L1402514045L1401114015L1405514091L1406214083L1407114084L1407214081L1410114105L1410414132L1411114112L1416114173L1415114182L1417514194L1416314184L1415314165L1502115041L1504215044L1502315043L1502515045L1501115015L1505515091L1506215083L1507115084L1507215081L1510115105L1510415132L1511115112L1516115173L1515115182L1517515194L1516315184L1515315165 +X40Y40Z3L3327238181L2637320341L2627222261L1100317123L0312103052L2902238051L2809330383L2404116163L2006318123L1836121351L0702304103L0429309233L3126238091L1039332023L2723233222L1122211391L0925315271L0532106281L1332110281L3004339001L1906108233L3928136321L1506317113L0632211373L1819221222L2309328002L1216308213L3826139241L1139217383L1504115132L3932336383L3813135173L2213218152L1824308323L2123239313L0420307201L0310102091L1631226213L1526315291L1030210213L0015203051L0039109351L1406115091L3721235172L0803108023L1519115161L3305334003L1101334173L2307123101L3120129242L2139322331L2237223293L3917339052L3002131011L0620307183L3827137171L3925139271L1435114291L2202109031L3435335283L1913119112L0023100211L3311224103L1037302383L3201330003L0223207263L2130217331L2739321361L3134232381L2319321223L1111307153L1724123211L2617324213L3929338193L2721127231L3725229273L2516219171L2526122231L3210230072L2315324183L0005101081L0908305093L0605209043L3207138063L0924105183L3207335033L1333108343L0031100331L0728112301L0230314293L0123106263L2327122313L3507234042L1438119381L0214207163L2935328312L2810237063L3314323103L2316221213L2520127212L0632113341L0811309112L2725326293L1621219192L0112309003L3834137321L2120115241L1223213293L0421206261L1026310283L3830233352L2101111001L0004101021L3018329153L3525231252L1302306073L1604112003L2406221043L0221203222L2515130171L0201202032L2217324121L0715106161L0331305272L3316132171L1425316253L0920114131L3108126033L3315233191L1807227002L3501136013L3020232223L2839218383L1635216363L0135101362L0330203332L2810127111L0235104363L0918314133L3413337133L3629137271L0738214361L3720236252L3735133333L1603214032L2818229173L3433137323L2403228042L3522236213L1501220011L3530337303L1605116013L2112119092L2201222051L1708215081L3739239362L1732315333L2506226053L3037329383L2200223013L1421113161L3130130291L0015301232L0722209232L2534125311L1826222253L1102210051L0810307093L1118208172L1632218322L1331311323L2235321333L1923217212L1420313223L3027334313L1218213183L3636334363L3128331272L2130118341L0305304042L3729239282L3220235213L3132133321L0239204391L3819138221L0634206303L1914319173L1111212122L1719320263L2809124092L3828334263L2424227282L2635122381L0534103351L0420103211L3102232021L0024200353L0603305023L1107210071L1926218291L2825329262L1224110241L0925209302L1927117271L3100333003L2121118241L0602106061L1902321012L1913223122L0113200161L3332333312L3904139021L3119232111L2601228013L0332302312L3314235143L0211200142L0234204321L2424123242L2932130352L2110222082L1635117391L2725124271L3402235012L3410237112L2508226092L2128122271L2720128161L2124320253L2833223323L1804119022L1420211161L2835229343L0814207152L1714315182L0915310183L1101216011L3613137142L3239332363L1109103091L0610104111L2537125391L3703238012L3834237361L1317113182L0613105111L0429104272L3019231191L2430223292L2115121171L2238320383L3032130312L2030221312L3735335363L1227114271L2414125161L2315223143L2624227252L0838303372L1921219223L2714226162L2723326223L3215331163L0937206381L0107204061L1006211073L1806218071L2735228372L2032319353L2738323363L3633236372L1506216061L2119320183L3005128061L1134210352L0733111341L1311108122L2538226372L0414302143L0125100241L1621115201L3235130341L3604135051L2115321173L2733228342L1011309141L2029320313L1733316353L0523305253L2626124263L3126133271L3319332203L0110102102L0405306053L1930220292L3622237232L3236130361L1716117141L2300122011L2000318003L1222113191L3102330033L0219203203L2605125041L1806317053L2529226302L2034221343L0736108351L1907220062L1823214232L1422315233L2115220162L2519224191L0011200092L3533337343L3108330082L1511216102L2625326273L1525215261L2012320133L0926110271L2515225143L2106325053L0608202072L2806328073L2510326103L2821328233L3707134071L0710307123L2911229091L3237234372L1219111181L3309135111L3411233113L2415226142L3909338103L3733136341L3406333063L1207213072L1213313133L1916119141L0614306153L2706227072L0919208192L1337313363L3408335093L1202212032L0022201221L3900338003L2815327143L1426313243L1320312203L0239103392L3703337043L3324331243L1034210341L0831309323L3423133232L1321113221L1022111221L1008310103L2113120131L1817218182L2322323233L1117209172L0101302013L3524336243L0902108021L2512225112L3134132341L0205202053L3413134141L3313332133L0613206122L0402105021L3616335163L0410205102L0326103271L3229131291L0232202332L2817327173L3818238172L3938239372L0137302373L3638137381L0001100021L1612117121L1821118221L0113101141L3809237092L1204113041L0731206312L3016130151L3535134351L3203232022L0212202132L2439325393L1232212323L1727317283L0824307243L1406314073L3339334393L3328334283L0315202152L2912328123L0727107261L1804219042L3531235302L1310213101L0705208052L3205232062L2432224332L1528215292L0234303343L0829108292L3803138041L2211222102L2302223012L1001210022L0126100261L0132100321L0604106031L3020330193L2928230282L3107331063L3039331393 +X40Y40Z2L0000139001L0100138001L0200137001L0300136001L0400135001L0500134001L0600133001L0700132001L0800131001L0900130001L1000129001L1100128001L1200127001L1300126001L1400125001L1500124001L1600123001L1700122001L1800121001L1900120001L0001100381L0002100371L0003100361L0004100351L0005100341L0006100331L0007100321L0008100311L0009100301L0010100291L0011100281L0012100271L0013100261L0014100251L0015100241L0016100231L0017100221L0018100211L0019100201L0039139391L0139138391L0239137391L0339136391L0439135391L0539134391L0639133391L0739132391L0839131391L0939130391L1039129391L1139128391L1239127391L1339126391L1439125391L1539124391L1639123391L1739122391L1839121391L1939120391L3901139381L3902139371L3903139361L3904139351L3905139341L3906139331L3907139321L3908139311L3909139301L3910139291L3911139281L3912139271L3913139261L3914139251L3915139241L3916139231L3917139221L3918139211L3919139201L1010129101L1110128101L1210127101L1310126101L1410125101L1510124101L1610123101L1710122101L1810121101L1910120101L1011110281L1012110271L1013110261L1014110251L1015110241L1016110231L1017110221L1018110211L1019110201L1029129291L1129128291L1229127291L1329126291L1429125291L1529124291L1629123291L1729122291L1829121291L1929120291L2911129281L2912129271L2913129261L2914129251L2915129241L2916129231L2917129221L2918129211L2919129201L1515124151L1615123151L1715122151L1815121151L1915120151L1516115231L1517115221L1518115211L1519115201L1524124241L1624123241L1724122241L1824121241L1924120241L2416124231L2417124221L2418124211L2419124201L1718122181L1818121181L1918120181L1719117201L1721122211L1821121211L1921120211L2219122201L0910209292L3010230292L1415214242L2515225242L1717222172L1719222192L1720222202L1722222222 +X40Y40Z3L0000139001L0001139011L0002139021L0003139031L0004139041L0005139051L0006139061L0007139071L0008139081L0009139091L0010139101L0011139111L0012139121L0013139131L0014139141L0015139151L0016139161L0017139171L0018139181L0019139191L0020139201L0021139211L0022139221L0023139231L0024139241L0025139251L0026139261L0027139271L0028139281L0029139291L0030139301L0031139311L0032139321L0033139331L0034139341L0035139351L0036139361L0037139371L0038139381L0039139391L0100101391L0500105391L0900109391L1300113391L1700117391L2100121391L2500125391L2900129391L3300133391L3700137391L0100201392L0300203392L0500205392L0700207392L0900209392L1100211392L1300213392L1500215392L1700217392L1900219392L2100221392L2300223392L2500225392L2700227392L2900229392L3100231392L3300233392L3500235392L3700237392L3900239392L0300303393L0700307393L1100311393L1500315393L1900319393L2300323393L2700327393L3100331393L3500335393L3900339393 -- 2.22.0 From 1c1026484b5ec66145ea9c1b2e9b61308d3dd690 Mon Sep 17 00:00:00 2001 From: KazushiKawamura Date: Sat, 25 Aug 2018 02:49:00 +0900 Subject: [PATCH 09/30] Fix a bug --- hls_2018/auto/auto_compile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hls_2018/auto/auto_compile.c b/hls_2018/auto/auto_compile.c index 66f672e..d0589dd 100755 --- a/hls_2018/auto/auto_compile.c +++ b/hls_2018/auto/auto_compile.c @@ -9,7 +9,7 @@ int main(void){ char dir[64] = "../router_01"; FILE *fp; - fp = fopen("b.txt", "r"); + fp = fopen("q.txt", "r"); if(fp == NULL){ printf("File does not exist.\n"); exit(1); -- 2.22.0 From a172ac00c9acc80953702abdd0a6af7308c8549e Mon Sep 17 00:00:00 2001 From: Kazushi Kawamura Date: Sat, 25 Aug 2018 12:30:32 +0900 Subject: [PATCH 10/30] Add description --- hls_2018/router_02/README.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 hls_2018/router_02/README.md diff --git a/hls_2018/router_02/README.md b/hls_2018/router_02/README.md new file mode 100644 index 0000000..000e60f --- /dev/null +++ b/hls_2018/router_02/README.md @@ -0,0 +1,13 @@ +# 並列度ã®å¤‰æ›´ (変更箇所) +優先度キューã«è¦ç´ ã‚’挿入ã™ã‚‹éš›ï¼Œè¦ç´ ã®ç§»å‹•を並列ã—ã¦å®Ÿè¡Œã§ãã‚‹ +コードã«ã„ãã¤ã‹ã®å¤‰æ›´ã‚’加ãˆã‚‹ã“ã¨ã§ä¸¦åˆ—度を変更å¯èƒ½ + +## router.hpp +* #define PP **32** <-- 並列度 +* #define LOG_PP **5** <-- 並列度ã®log2 + +## router.cpp +* (in search func.) #pragma HLS ARRAY_PARTITION variable=pq_nodes cyclic factor=**32** dim=1 <-- 並列度 +* (in pq_push func.) #pragma HLS LOOP_TRIPCOUNT min=0 max=**31** <-- 並列度-1 (計3箇所) +* (in pq_push func.) #pragma HLS LOOP_TRIPCOUNT min=0 max=**255** <-- ã‚­ãƒ¥ãƒ¼ã®æœ€å¤§è¦ç´ æ•°/並列度-1 + -- 2.22.0 From de0cef62e11616b79c2a0fc60ed5e0cbeba2d1b4 Mon Sep 17 00:00:00 2001 From: Kazushi Kawamura Date: Sat, 25 Aug 2018 12:34:53 +0900 Subject: [PATCH 11/30] Add description --- hls_2018/router_02/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hls_2018/router_02/README.md b/hls_2018/router_02/README.md index 000e60f..2213393 100644 --- a/hls_2018/router_02/README.md +++ b/hls_2018/router_02/README.md @@ -1,12 +1,15 @@ # 並列度ã®å¤‰æ›´ (変更箇所) 優先度キューã«è¦ç´ ã‚’挿入ã™ã‚‹éš›ï¼Œè¦ç´ ã®ç§»å‹•を並列ã—ã¦å®Ÿè¡Œã§ãã‚‹ + コードã«ã„ãã¤ã‹ã®å¤‰æ›´ã‚’加ãˆã‚‹ã“ã¨ã§ä¸¦åˆ—度を変更å¯èƒ½ ## router.hpp +以下ã®2箇所を変更ã™ã‚‹ * #define PP **32** <-- 並列度 * #define LOG_PP **5** <-- 並列度ã®log2 ## router.cpp +以下ã®5箇所を変更ã™ã‚‹ * (in search func.) #pragma HLS ARRAY_PARTITION variable=pq_nodes cyclic factor=**32** dim=1 <-- 並列度 * (in pq_push func.) #pragma HLS LOOP_TRIPCOUNT min=0 max=**31** <-- 並列度-1 (計3箇所) * (in pq_push func.) #pragma HLS LOOP_TRIPCOUNT min=0 max=**255** <-- ã‚­ãƒ¥ãƒ¼ã®æœ€å¤§è¦ç´ æ•°/並列度-1 -- 2.22.0 From a8cb464b15399cefdb8cc2831ded973c131ff118 Mon Sep 17 00:00:00 2001 From: Kazushi Kawamura Date: Sat, 25 Aug 2018 14:50:02 +0900 Subject: [PATCH 12/30] Fix bugs and debug comments --- hls/auto/auto_compile.c | 30 +++++++++++++++++ hls/lines128_length256/main.cpp | 9 ++++-- hls/lines128_length256/router.cpp | 54 ++++++++++++++++++------------- 3 files changed, 68 insertions(+), 25 deletions(-) create mode 100755 hls/auto/auto_compile.c diff --git a/hls/auto/auto_compile.c b/hls/auto/auto_compile.c new file mode 100755 index 0000000..25a5115 --- /dev/null +++ b/hls/auto/auto_compile.c @@ -0,0 +1,30 @@ +#include +#include + +#define STRLEN 65536 + +int main(void){ + + char q[STRLEN], command[STRLEN]; + char dir[64] = "../lines128_length256"; + + FILE *fp; + fp = fopen("q.txt", "r"); + if(fp == NULL){ + printf("File does not exist.\n"); + exit(1); + } + + int counter = 1; + while(1){ + if(fscanf(fp, "%s", q) == EOF) break; + printf("Q. %d\n", counter++); + sprintf(command, "./%s/sim.exe %s", dir, q); + //printf("(command) %s\n", command); + int ret = system(command); + printf("ret: %d\n", ret); + } + fclose(fp); + return 0; +} + diff --git a/hls/lines128_length256/main.cpp b/hls/lines128_length256/main.cpp index 41f1f51..cbba258 100644 --- a/hls/lines128_length256/main.cpp +++ b/hls/lines128_length256/main.cpp @@ -17,6 +17,7 @@ #include "router.hpp" +#define PRINT_SOLUTION int main(int argc, char *argv[]) { using namespace std; @@ -50,9 +51,11 @@ int main(int argc, char *argv[]) { seed = atoi(argv[2]); } +#ifdef PRINT_SOLUTION int size_x = (boardstr[1] - '0') * 10 + (boardstr[2] - '0'); int size_y = (boardstr[4] - '0') * 10 + (boardstr[5] - '0'); int size_z = (boardstr[7] - '0'); +#endif // ソルãƒå®Ÿè¡Œ ap_int<32> status; @@ -68,6 +71,7 @@ int main(int argc, char *argv[]) { cout << "status = " << (int)status << endl; cout << "elapsed = " << ((double)(clock_done - clock_start) / CLOCKS_PER_SEC) << endl << endl; +#ifdef PRINT_SOLUTION // 解表示 cout << "SOLUTION" << endl; cout << "========" << endl; @@ -80,12 +84,13 @@ int main(int argc, char *argv[]) { cout << ","; } int i = ((x * MAX_WIDTH + y) << BITWIDTH_Z) | z; - //cout << setfill('0') << setw(2) << right << (unsigned int)(unsigned char)(boardstr[i]); - cout << (unsigned int)(unsigned char)(boardstr[i]); + cout << setfill('0') << setw(3) << right << (unsigned int)(unsigned char)(boardstr[i]); + //cout << (unsigned int)(unsigned char)(boardstr[i]); } cout << endl; } } +#endif return 0; } diff --git a/hls/lines128_length256/router.cpp b/hls/lines128_length256/router.cpp index a5a64cf..437fa47 100644 --- a/hls/lines128_length256/router.cpp +++ b/hls/lines128_length256/router.cpp @@ -244,6 +244,7 @@ bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *stat ap_uint<8> last_target = 255; // [Step 2] Rip-up å†ãƒ«ãƒ¼ãƒ†ã‚£ãƒ³ã‚° + cout << "Rip-up Routing" << endl; ROUTING: for (ap_uint<16> round = 1; round <= 32768 /* = (2048 * 16) */; round++) { #pragma HLS LOOP_TRIPCOUNT min=1 max=4000 avg=50 @@ -284,8 +285,6 @@ bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *stat #pragma HLS LOOP_TRIPCOUNT min=1 max=255 avg=50 weights[paths[target][j]] = 1; } - // 対象ラインã®ã‚¹ã‚¿ãƒ¼ãƒˆã®é‡ã¿ã‚‚一旦リセット ã‚ã¨ã§ (*) ã§æˆ»ã™ - weights[starts[target]] = 1; // (2) é‡ã¿ã‚’æ›´æ–° ap_uint<8> current_round_weight = new_weight(round); @@ -303,10 +302,18 @@ bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *stat } } } + WEIGHT_TERMINAL: + for (ap_uint<8> i = 0; i < (ap_uint<8>)(line_num); i++) { +#pragma HLS LOOP_TRIPCOUNT min=2 max=127 avg=50 + weights[starts[i]] = MAX_WEIGHT; + weights[goals[i]] = MAX_WEIGHT; + } + // 対象ラインã®ã‚¹ã‚¿ãƒ¼ãƒˆã®é‡ã¿ã‚‚一旦リセット ã‚ã¨ã§ (*) ã§æˆ»ã™ + weights[starts[target]] = 1; // 経路探索 #ifdef DEBUG_PRINT - cout << "LINE #" << (int)(target + 1) << endl; + cout << "(round: " << round << ")" << "LINE #" << (int)(target + 1) << endl; #endif search(&(paths_size[target]), paths[target], starts[target], goals[target], weights); @@ -611,18 +618,18 @@ void search(ap_uint<8> *path_size, ap_uint<16> path[MAX_PATH], ap_uint<16> start ap_uint<16> t = prev[goal]; #ifdef DEBUG_PRINT - int dbg_start_xy = start >> BITWIDTH_Z; - int dbg_start_x = dbg_start_xy / MAX_WIDTH; - int dbg_start_y = dbg_start_xy % MAX_WIDTH; - int dbg_start_z = start & BITMASK_Z; - - int dbg_goal_xy = goal >> BITWIDTH_Z; - int dbg_goal_x = dbg_goal_xy / MAX_WIDTH; - int dbg_goal_y = dbg_goal_xy % MAX_WIDTH; - int dbg_goal_z = goal & BITMASK_Z; - - cout << "(" << dbg_start_x << ", " << dbg_start_y << ", " << dbg_start_z << ") #" << start << " -> " - << "(" << dbg_goal_x << ", " << dbg_goal_y << ", " << dbg_goal_z << ") #" << goal << endl; + //int dbg_start_xy = start >> BITWIDTH_Z; + //int dbg_start_x = dbg_start_xy / MAX_WIDTH; + //int dbg_start_y = dbg_start_xy % MAX_WIDTH; + //int dbg_start_z = start & BITMASK_Z; + + //int dbg_goal_xy = goal >> BITWIDTH_Z; + //int dbg_goal_x = dbg_goal_xy / MAX_WIDTH; + //int dbg_goal_y = dbg_goal_xy % MAX_WIDTH; + //int dbg_goal_z = goal & BITMASK_Z; + + //cout << "(" << dbg_start_x << ", " << dbg_start_y << ", " << dbg_start_z << ") #" << start << " -> " + // << "(" << dbg_goal_x << ", " << dbg_goal_y << ", " << dbg_goal_z << ") #" << goal << endl; #endif // ãƒãƒƒã‚¯ãƒˆãƒ©ãƒƒã‚¯ @@ -633,11 +640,11 @@ void search(ap_uint<8> *path_size, ap_uint<16> path[MAX_PATH], ap_uint<16> start #pragma HLS PIPELINE II=2 #ifdef DEBUG_PRINT - int t_xy = prev[t] >> BITWIDTH_Z; - int t_x = t_xy / MAX_WIDTH; - int t_y = t_xy % MAX_WIDTH; - int t_z = prev[t] & BITMASK_Z; - cout << " via " << "(" << t_x << ", " << t_y << ", " << t_z << ") #" << prev[t] << " dist=" << dist[t] << endl; + //int t_xy = prev[t] >> BITWIDTH_Z; + //int t_x = t_xy / MAX_WIDTH; + //int t_y = t_xy % MAX_WIDTH; + //int t_z = prev[t] & BITMASK_Z; + //cout << " via " << "(" << t_x << ", " << t_y << ", " << t_z << ") #" << prev[t] << " dist=" << dist[t] << endl; #endif path[p] = t; // 記録 @@ -648,8 +655,8 @@ void search(ap_uint<8> *path_size, ap_uint<16> path[MAX_PATH], ap_uint<16> start *path_size = p; #ifdef DEBUG_PRINT - cout << "max_path_len = " << p << endl; - cout << "max_pq_len = " << max_pq_len << endl; + //cout << "max_path_len = " << p << endl; + //cout << "max_pq_len = " << max_pq_len << endl; #endif } @@ -675,6 +682,7 @@ void pq_push(ap_uint<16> priority, ap_uint<16> data, ap_uint<12> *pq_len, ap_uin #pragma HLS INLINE (*pq_len)++; + if ((*pq_len) == 0) { (*pq_len)--; } // Queue is full -> Last element is automatically removed ap_uint<12> i = (*pq_len); // target ap_uint<12> p = (*pq_len) >> 1; // i.e., (*pq_len) / 2; // 親 PQ_PUSH_LOOP: @@ -707,7 +715,7 @@ void pq_pop(ap_uint<16> *ret_priority, ap_uint<16> *ret_data, ap_uint<12> *pq_le ap_uint<16> last_priority = (ap_uint<16>)(pq_nodes[*pq_len] & PQ_PRIORITY_MASK); // 末尾ノードã®å„ªå…ˆåº¦ PQ_POP_LOOP: - while (1) { + while (!(i >> 11)) { // (2018.08.25) Loop condition fixed #pragma HLS LOOP_TRIPCOUNT min=1 max=8 avg=4 //#pragma HLS PIPELINE //#pragma HLS UNROLL factor=2 -- 2.22.0 From f3520d38546c16fa4c0e1d830dd5114fc5ccedcf Mon Sep 17 00:00:00 2001 From: Kazushi Kawamura Date: Sat, 25 Aug 2018 14:54:03 +0900 Subject: [PATCH 13/30] Add a test-input file --- hls/auto/q.txt | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100755 hls/auto/q.txt diff --git a/hls/auto/q.txt b/hls/auto/q.txt new file mode 100755 index 0000000..d335ae7 --- /dev/null +++ b/hls/auto/q.txt @@ -0,0 +1,25 @@ +X24Y24Z4L0613304164L1702122032L0101403204L1601420204L2117419044L0023116021L1520309084L1921116154L1709121031L1812103211L0905208142L0704412013L0421110094L2320100142L1500319034L0915104123L0907418124L2001109101L0122202213L2102422011L2120105211L2319117132L0404119103L1215322223L0607218074L1715113123L1217220172L1602320113L0003306053L0405413144L2006421214L1301103212L0614322183L1108323004L0004322043L0602322213L1210120142L1321419172L1202116012L1303103081L0820211202L1003116142L1701305123L0312223072L0720301063L1202214024L0506207072L1610417224L1309404154L1201408124L1704410064L0822110211L1210321153L1708116072L0000100111L0201112011L0808104103L0923210212L1210413134L1500421014 +X15Y15Z2L0202212102L0303211112L0404210122L0503209112L0402210102L0204212122L0203212112L0302211102L0403210112L0504209122L0502209102L0304211122 +X20Y20Z8L0203202066L0400403037L0403105088L0503101016L0500206038L0703317055L1001104054L0505317087L0108204086L0111101177L0810406188L0313406138L0413215177L0513106176L0317302158L0715100195L0318307064L1503212048L1702112058L1206318087L1007417036L1101317047L1406216094L1111217187L1310418146L1510315145L1014310177L1317219198L0919218177 +X72Y72Z8L0000171718L0036871001L0000800718L0036171008L0071171711L3671171368 +X08Y08Z4L0000107072L0100103032L0007106072L0503106032L0506101062L0001205062L0404106051L0700207032L0201202032L0205203052L0000307074L0100303034L0007306074L0503306034L0506301064L0001405064L0404306053L0700407034L0201402034L0205403054 +X48Y36Z8L0609109051L0608108091L0709109021L0306109041L0204109091L0207105091L0208105041L0209104041L0607109031L0516105191L0417106171L0418106181L0113103131L0213104211L0214107211L0413110211L0814108211L0221110221L0226103321L0331104251L0128105321L0329108321L0733109261L0629107261L0630107271L0233106281L1400123101L1503123061L1504122101L1508122081L1509122011L1606118111L1702122041L1212119211L1319115141L1316120151L1217118171L1313119221L2020122121L1517116221L1421116171L1527123351L1328120261L1533122251L1830121311L1334120291L1426119261L1632119251L1730122291L1431121341L2501131011L2708128051L2800134051L3400135111L2400132031L2704132081L2406125021L2504133101L2401128101L2522134151L2921134161L2513134171L3013134221L2614130171L3019135191L2415130181L3414135121L3524135341L2533135281L2727135351L2435129311L2734129351L2829131331L2833132321L3607146111L4207147111L4010147001L3600137101L3608144021L4509146051L4020145141L3614141151L4218147231L3612145201L3712143141L3623144181L3912146231L3624144301L4030147241L3635137321L3835147351L4132146351L3634145311L3726144291L3733142281L2935227213L0629622066L0606335013L1728617245L0814411182L2608416057 +X72Y72Z8L0000166038L0004128038L0013104688L0016158688L0030133688L0046120038L0071149038L7165169688 +X15Y15Z2L0602214082L1406114081L0901111112L0110100072L0405209012L1108112071L0707208011L0301107002L0014101142L0405103072L0006203042L1008111071L1301214132L1403114012L1404210011L1113207112L0206206052L0603104031L1211110121L0512202141L0201203032L0105101042L0809209062L0609100121L0501204022L1110211082L0809112091L0000201001L1304114051L0102100001L1114113141L0401101012L1007109132L0714204131L1005110031L0611103112L0112102131L0208102061L0708206092L0007100101L1409214112L1300211002L0501106001L1114212142L0511104111L0704107031L0702208022 +X23Y12Z6L0303122021L1102219103L0503504065L0302105101L0200305093L0907100081L1309100071L0706221102L0500212014L0301605026L0104216063L0204408034L0910502106L1805113052L1406116041L0409310114L2106122103L1710201033L0510412024L1411222072L1503421106L1310519035L1306220044L0101201112L1701221014L0802503105L0603107091L0407113012L0000513106L0201405045L2104320086L0202606086L1804120091L0609411104L1607522005L0000101102L2002320095L0610110111L0709500116L1603422006L0203109041L2201113011L0808611016L1807519006L0611316083L0910318074L1608415035L1001602076L1203603106 +X08Y04Z8L0000107018L0100103014L0000806018L0500406014L0500701017L0001205017L0400506006L0701107014L0201202014L0201603016L0002107038L0102103034L0002806038L0502406034L0502701037L0003205037L0402506026L0703107034L0203202034L0203603036 +X36Y19Z4L0101113011L0702107151L0804112071L0803108051L0802108071L1202108091L1503106151L1501106161L0204104041L1500101041L1612109161L0216104161L1114117161L1616114171L0503105161L1216117171L0203121091L0403103141L2606132061L2706131061L2907124111L2212128121L2112129121L3103122051L2503130041L2304128051L2213131151L2813123141L3014125151L2707126111L2608128111L2408129101L2309131101L0000205052L0101204042L0202203032L0007205122L0108204112L0209203102L0115204182L2301323143L0216203172L0700219122L0801218112L0902217102L1003216092L1104215082L1205214072L2100235002L2201235012L2302235022L2403235032L2504235042L2605235052L2706235062L2807235072L2908235082L3009235092L3110235102L3211235112L3312235122L3413235142L1302402134L0709413154L0000308033L0012308153L1300335153L1301334153L0215410154L1505415134L1615426154 +X72Y72Z8L0000109098L0000809091L0000401004L0001401014L0002401024L0003401034L0004401044L0005401054L0006401064L0007401074L0008401084L0009401094L0202403024L0203403034L0204403044L0205403054L0206403064L0208403084L0209403094L0200402014L0300404004L0307404074L0401405014L0402405024L0403405034L0404405044L0405405054L0406405064L0408405084L0409405094L0604406054L0704407054L0804408054L0904409054L0608406094L0708407094L0808408094L0908409094L0507406074L0500406004L0601407014L0602406034L0700408004L0703408034L0706408064L0707408074L0801408024L0900409014L0902409034L0906409074L0009109008L0900100098 +X10Y10Z2L0802106042L0001208031L0701209021L0206209011L0004100022L0000206071L0201102022L0105101072L0809106081L0805209091L0407207051L0208101061L0108200091L0303202012L0702205042L0008200032L0703207011L0601205022L0506204062L0904209052L0404104031L0203102021 +X60Y36Z8L1702113248L1503212078L1304112137L1105311206L1309202336L1508310125L1707105075L2306307228L1804417226L1514210145L1824104328L0421106315L0319308307L0728200297L0523306266L0427322325L0228305186L0131309237L0706108136L0604201114L0502114124L0303404128L0405208156L1428114338L1229116328L1530415237L1616316257L1426311225L0310305095L0213106115L1417207175L0921312184L2400420057L2500121028L2600325026L1934213316L2219422338L2119222348L2019326255L3233335335L3331436337L3332437336L2601232035L2101124046L2206321176L2604224067L2435137357L3708324344L2433238354L2103221068L3803133018L3517237327L3617335226L3717236306L3918339358L3126322287L2229127315L2230126306L2603134037L3503259165L3603437055L3411429198L3412330204L3413337125L2607324085L2309224157L2316124097L2907436085L3325432296L2317423197L2528430268L2805131094L3307235084L3713334204L3524235288L2318124218L3009227126L3711332228L2614227227L2609326125L4006144215L5917244205L5406244196L3906245197L4905445208L5420344264L4016154194L5519250344L5520349345L5521254275L4609348155L4816356326L5115344045L5504351165L4625344305L5113346265L4925253257L5309150256L5308253246L4506250057L4608149128L5530243326 +X15Y15Z4L0401105001L0601114013L0213213023L0105105051L0014102131L0704210074L1208211133L0812110081L0612306141L1201213003L0408300142L0911114064L0411300131L0007208004L0913409121L1210307101L0502401072L0108400032L0608105074L0103301021L0814308112L0510201083L0800106001L1414310134L1209313103L0604405023L0714206144L1109412083L0409205083L1207113051L1213314123L0514206143L1207212053L0804307013L0208302064L0302300054L1009413134L0412103111L0408203074L0810309093L0313302122L1410114071L0812209132L0902408034L0604208041L0203202021L1313113092L0709406104L0510302084L0709108081L1201412034L1307214104L0611206092L1100309044L0412203132L0301304003L1002409034L1411213101L0411402114L0101301011L0907209052L0900111001L0809308102L0101401044L1404314044L0310203092L0504305041L0111301112L0205202042L0612205122L0505406054L0314102141L0011400104L1210411104L1201113011L0305104051L0401405014L1002309023L0609405094L1108112081L0900310003 +X20Y35Z8L1916104218L1917204208L1406104196L1934305197L0905205206L1420404266L0016414195L1519410346L1520309348L1521414277L0609108158L0816316327L1115204046L1504411165L0625404306L1113406266L0925113258L1309210257L1308213248L0506410056L0608409126L1530403325L0017400346 +X36Y24Z1L0003102031L0302105021L0101104041L0005104011L0603108051L0605107011L0801110011L0802110041L0009102091L0308105081L0107104101L0011104071L0608108061L0606107101L0810110101L0809110071L1203114031L1502117021L1301116041L1205116011L1803120051L1805119011L2001122011L2002122041L1209114091L1508117081L1307116101L1211116071L1808120061L1806119101L2010122101L2009122071L2403126031L2702129021L2501128041L2405128011L3003132051L3005131011L3201134011L3202134041L2409126091L2708129081L2507128101L2411128071L3008132061L3006131101L3210134101L3209134071L0015102151L0314105141L0113104161L0017104131L0615108171L0617107131L0813110131L0814110161L0021102211L0320105201L0119104221L0023104191L0620108181L0618107221L0822110221L0821110191L1215114151L1514117141L1313116161L1217116131L1815120171L1817119131L2013122131L2014122161L1221114211L1520117201L1319116221L1223116191L1820120181L1818119221L2022122221L2021122191L2415126151L2714129141L2513128161L2417128131L3015132171L3017131131L3213134131L3214134161L2421126211L2720129201L2519128221L2423128191L3020132181L3018131221L3222134221L3221134191 +X72Y72Z5L0000171715L0001170715L0002169715L0003168715L0004167715L0005166715L0006165715L0007164715L0008163715L0009162715L0010161715L0011160715L0012159715L0013158715L0014157715L0015156715L0016155715L0017154715L0018153715L0019152715L0020151715L0021150715L0022149715L0023148715L0024147715L0025146715L0026145715L0027144715L0028143715L0029142715L0030141715L0031140715L0032139715L0033138715L0034137715L0035136715L0037135715L0038134715L0039133715L0040132715L0041131715L0042130715L0043129715L0044128715L0045127715L0046126715L0047125715L0048124715L0049123715L0050122715L0051121715L0052120715L0053119715L0054118715L0055117715L0056116715L0057115715L0058114715L0059113715L0060112715L0061111715L0062110715L0063109715L0064108715L0065107715L0066106715L0067105715L0068104715L0069103715L0070102715L0071101715L3600136004L0036535365 +X72Y72Z2L0000271712L0071271002 +X40Y40Z3L0313329331L1415127043L0237337351L0039335171L3816115013L0016121091L0206138381L1119118151L3703139001L0317137381L1000139393L0932139392L3611108333L3401100383L0125104033L1911124211L1727119261L3117132101L0015106341L1201116051L0025325061L0539333181L0508330061L3200326331L0700234041L0804109001L1614130331L0516122331L2007124221L1218128301L1804100392L1301133383L2125130073L1509105093L1118138393L2705137361L1429127341L3013138361L3007136121L3118137141L2100225033L0204205022L1412338392L0738339162L0028236043L1501236022L2811221232L1408209192L0622205052L2634237192L0633228073L3613212323L2101234042L3438219373L0802216032L2710219363L0038209372L0405207242L1124225112L1217217092L1732236343L1239214193L3008237113L0401303312L1316333152L1004217032L2628231272L1125224242L1227230172L0137210372L0504206062L0611326102L1932234372L0226207063L1512331202L3227236302L0509205162L0233207282L2124229112L1231219382L0314305222L2339334172L3226335352L2934336142L3026231133L2633236332L3502239083L0032301033L2434333393L0507310043L3617336333L1601333003L0907307333L3330336353L2023323233L1305324123L3501339073L0737311303L2239329073L0239304353L3731332303L1106324053L2705332163L0238306243L2029318283L1010310273L1521326153L1207320123L2206322123L0736311293L1334318253L1738319273L0315303173L0419304213L2120324213L2222327233L2319324233L0632307343L3019331273L3418335243L3409337103L3505336133L3605336073 +X15Y15Z3L1212303012L0506203113L0705209113L1102212113L1005110033L0414200012L0701302001L0107200083L0612305143L1102112001L0702109051L1105214022L0512110042L1309113071L0507206063L1212114121L0612213121L0303306033L1110112081L0312202142L1013214123L0710108071L0806302012L1108214062L0701203023L0900303021L1307313103L1114111121L0004100081L0011101101L0614104141L0914310133L0507106061L1101113011L0914108131L1010110071L0513303101L1204110011L0305304063L0809206082L1309214082L1301311002L0500107011L0901208002L1209311083L0506105031L0210202113L1106310053L0102301003L0802308043L0311203121L1111311123L0205301053L0313303143L0909309103L1013110141L1014311143 +X72Y72Z8L0000171023L0000271022L0000371021L0001171013L0001371011L0002171003L0002271002L0002371001 +X03Y03Z3L0000102002L0101101002L0200101012L0001101023L0001201013L0102102013 +X72Y72Z1L0100161061L2300164131L5500142501L0062106031L1771171341L2271166661L5967146631L2565161681L2665167661L2467159701L2369169691L5668157661L5569157671L0200159181L0116125331L4701170011L0209139261L6117103351L1628148341L0428103091L2400150061L1860119691L0114152461L2107156021L2158170361L0117112321L1213168041L0342114681L1643151591L5544161161L1115134161L1116134151L4342124521L0238146371L1449120631L0259113681L2243138471L0642146381L0404151031L5616159471L1216135161L1137126331L3911141261L0214159331L0269111321L6315168051L1741155561L0540109331L2322134211L4353129461L0713160351L1362118691L2244127471L0934108431L1120126191L1410140261L1957168571L5808146391L6653169311L0765166521L2719129191L3044125471L0425133311L1352110631L0405163111L0858110571L2645143541L5809165141L0515132261L2649141431L1252109611L0604141061L1955143411L1704153121L1448119541L2405145181L2447142511L1058113461L4605146211L1639122391L4613151111L4710146221L4414144181L0516105251L6822168331 +X40Y40Z3L0000139001L0001139011L0002139021L0003139031L0004139041L0005139051L0006139061L0007139071L0008139081L0009139091L0010139101L0011139111L0012139121L0013139131L0014139141L0015139151L0016139161L0017139171L0018139181L0019139191L0020139201L0021139211L0022139221L0023139231L0024139241L0025139251L0026139261L0027139271L0028139281L0029139291L0030139301L0031139311L0032139321L0033139331L0034139341L0035139351L0036139361L0037139371L0038139381L0039139391L0100101391L0500105391L0900109391L1300113391L1700117391L2100121391L2500125391L2900129391L3300133391L3700137391L0100201392L0300203392L0500205392L0700207392L0900209392L1100211392L1300213392L1500215392L1700217392L1900219392L2100221392L2300223392L2500225392L2700227392L2900229392L3100231392L3300233392L3500235392L3700237392L3900239392L0300303393L0700307393L1100311393L1500315393L1900319393L2300323393L2700327393L3100331393L3500335393L3900339393 -- 2.22.0 From 11c048570aa34fa6f24618efe6120249d5f3ced4 Mon Sep 17 00:00:00 2001 From: "kazushi.kawamura" Date: Sat, 25 Aug 2018 16:29:56 +0900 Subject: [PATCH 14/30] Fix a little --- solver/pynqrouter.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/solver/pynqrouter.py b/solver/pynqrouter.py index bbd9ff1..19a4ddf 100644 --- a/solver/pynqrouter.py +++ b/solver/pynqrouter.py @@ -42,16 +42,16 @@ def solve(boardstr, seed=12345, zero_padding=False): size_z = (ord(boardstr[7]) - ord('0')) # Overlay 読ã¿è¾¼ã¿ - OL = Overlay('pynqrouter.bit') + OL = Overlay('router_design.bit') OL.download() print(OL.ip_dict) print('Overlay loaded!') # MMIO 接続 (pynqrouter) - mmio = MMIO(int(PL.ip_dict[IP][0]), int(PL.ip_dict[IP][1])) + mmio = MMIO(int(PL.ip_dict[IP][0],16), int(PL.ip_dict[IP][1],16)) # MMIO 接続 & リセット (LED) - mmio_led = MMIO(int(PL.ip_dict[IP_LED][0]), int(PL.ip_dict[IP_LED][1])) + mmio_led = MMIO(int(PL.ip_dict[IP_LED][0],16), int(PL.ip_dict[IP_LED][1],16)) mmio_led.write(0, 0) # 入力データをセット -- 2.22.0 From 2a7c9ca776f341d52523d7d5abd8651a2d7ba269 Mon Sep 17 00:00:00 2001 From: KazushiKawamura Date: Sat, 25 Aug 2018 16:38:53 +0900 Subject: [PATCH 15/30] Upload a bitstream file --- .../bitstream/router_design.bit | Bin 0 -> 4045681 bytes .../bitstream/router_design.tcl | 1113 +++++++++++++++++ 2 files changed, 1113 insertions(+) create mode 100755 hls/lines128_length256/bitstream/router_design.bit create mode 100755 hls/lines128_length256/bitstream/router_design.tcl diff --git a/hls/lines128_length256/bitstream/router_design.bit b/hls/lines128_length256/bitstream/router_design.bit new file mode 100755 index 0000000000000000000000000000000000000000..fb931486840eb7a813e994b1f19168e2e666db02 GIT binary patch literal 4045681 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 z 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 z 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

nMwr@dz# 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 zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UATT6wyC_DVzxlnt&f;MDce^+k#na1c`&lhJst%bF44mbxc!#VI@Z8EF5 literal 0 HcmV?d00001 diff --git a/hls/lines128_length256/bitstream/router_design.tcl b/hls/lines128_length256/bitstream/router_design.tcl new file mode 100755 index 0000000..e5347df --- /dev/null +++ b/hls/lines128_length256/bitstream/router_design.tcl @@ -0,0 +1,1113 @@ + +################################################################ +# This is a generated script based on design: router_design +# +# Though there are limitations about the generated script, +# the main purpose of this utility is to make learning +# IP Integrator Tcl commands easier. +################################################################ + +namespace eval _tcl { +proc get_script_folder {} { + set script_path [file normalize [info script]] + set script_folder [file dirname $script_path] + return $script_folder +} +} +variable script_folder +set script_folder [_tcl::get_script_folder] + +################################################################ +# Check if script is running in correct Vivado version. +################################################################ +set scripts_vivado_version 2018.2 +set current_vivado_version [version -short] + +if { [string first $scripts_vivado_version $current_vivado_version] == -1 } { + puts "" + catch {common::send_msg_id "BD_TCL-109" "ERROR" "This script was generated using Vivado <$scripts_vivado_version> and is being run in <$current_vivado_version> of Vivado. Please run the script in Vivado <$scripts_vivado_version> then open the design in Vivado <$current_vivado_version>. Upgrade the design by running \"Tools => Report => Report IP Status...\", then run write_bd_tcl to create an updated script."} + + return 1 +} + +################################################################ +# START +################################################################ + +# To test this script, run the following commands from Vivado Tcl console: +# source router_design_script.tcl + +# If there is no project opened, this script will create a +# project, but make sure you do not have an existing project +# <./myproj/project_1.xpr> in the current working folder. + +set list_projs [get_projects -quiet] +if { $list_projs eq "" } { + create_project project_1 myproj -part xc7z020clg400-1 +} + + +# CHANGE DESIGN NAME HERE +variable design_name +set design_name router_design + +# If you do not already have an existing IP Integrator design open, +# you can create a design using the following command: +# create_bd_design $design_name + +# Creating design if needed +set errMsg "" +set nRet 0 + +set cur_design [current_bd_design -quiet] +set list_cells [get_bd_cells -quiet] + +if { ${design_name} eq "" } { + # USE CASES: + # 1) Design_name not set + + set errMsg "Please set the variable to a non-empty value." + set nRet 1 + +} elseif { ${cur_design} ne "" && ${list_cells} eq "" } { + # USE CASES: + # 2): Current design opened AND is empty AND names same. + # 3): Current design opened AND is empty AND names diff; design_name NOT in project. + # 4): Current design opened AND is empty AND names diff; design_name exists in project. + + if { $cur_design ne $design_name } { + common::send_msg_id "BD_TCL-001" "INFO" "Changing value of from <$design_name> to <$cur_design> since current design is empty." + set design_name [get_property NAME $cur_design] + } + common::send_msg_id "BD_TCL-002" "INFO" "Constructing design in IPI design <$cur_design>..." + +} elseif { ${cur_design} ne "" && $list_cells ne "" && $cur_design eq $design_name } { + # USE CASES: + # 5) Current design opened AND has components AND same names. + + set errMsg "Design <$design_name> already exists in your project, please set the variable to another value." + set nRet 1 +} elseif { [get_files -quiet ${design_name}.bd] ne "" } { + # USE CASES: + # 6) Current opened design, has components, but diff names, design_name exists in project. + # 7) No opened design, design_name exists in project. + + set errMsg "Design <$design_name> already exists in your project, please set the variable to another value." + set nRet 2 + +} else { + # USE CASES: + # 8) No opened design, design_name not in project. + # 9) Current opened design, has components, but diff names, design_name not in project. + + common::send_msg_id "BD_TCL-003" "INFO" "Currently there is no design <$design_name> in project, so creating one..." + + create_bd_design $design_name + + common::send_msg_id "BD_TCL-004" "INFO" "Making design <$design_name> as current_bd_design." + current_bd_design $design_name + +} + +common::send_msg_id "BD_TCL-005" "INFO" "Currently the variable is equal to \"$design_name\"." + +if { $nRet != 0 } { + catch {common::send_msg_id "BD_TCL-114" "ERROR" $errMsg} + return $nRet +} + +set bCheckIPsPassed 1 +################################################################## +# CHECK IPs +################################################################## +set bCheckIPs 1 +if { $bCheckIPs == 1 } { + set list_check_ips "\ +xilinx.com:ip:axi_gpio:2.0\ +xilinx.com:ip:processing_system7:5.5\ +xilinx.com:hls:pynqrouter:1.0\ +xilinx.com:ip:proc_sys_reset:5.0\ +" + + set list_ips_missing "" + common::send_msg_id "BD_TCL-006" "INFO" "Checking if the following IPs exist in the project's IP catalog: $list_check_ips ." + + foreach ip_vlnv $list_check_ips { + set ip_obj [get_ipdefs -all $ip_vlnv] + if { $ip_obj eq "" } { + lappend list_ips_missing $ip_vlnv + } + } + + if { $list_ips_missing ne "" } { + catch {common::send_msg_id "BD_TCL-115" "ERROR" "The following IPs are not found in the IP Catalog:\n $list_ips_missing\n\nResolution: Please add the repository containing the IP(s) to the project." } + set bCheckIPsPassed 0 + } + +} + +if { $bCheckIPsPassed != 1 } { + common::send_msg_id "BD_TCL-1003" "WARNING" "Will not continue with creation of design due to the error(s) above." + return 3 +} + +################################################################## +# DESIGN PROCs +################################################################## + + + +# Procedure to create entire design; Provide argument to make +# procedure reusable. If parentCell is "", will use root. +proc create_root_design { parentCell } { + + variable script_folder + variable design_name + + if { $parentCell eq "" } { + set parentCell [get_bd_cells /] + } + + # Get object for parentCell + set parentObj [get_bd_cells $parentCell] + if { $parentObj == "" } { + catch {common::send_msg_id "BD_TCL-100" "ERROR" "Unable to find parent cell <$parentCell>!"} + return + } + + # Make sure parentObj is hier blk + set parentType [get_property TYPE $parentObj] + if { $parentType ne "hier" } { + catch {common::send_msg_id "BD_TCL-101" "ERROR" "Parent <$parentObj> has TYPE = <$parentType>. Expected to be ."} + return + } + + # Save current instance; Restore later + set oldCurInst [current_bd_instance .] + + # Set parent object as current + current_bd_instance $parentObj + + + # Create interface ports + set DDR [ create_bd_intf_port -mode Master -vlnv xilinx.com:interface:ddrx_rtl:1.0 DDR ] + set FIXED_IO [ create_bd_intf_port -mode Master -vlnv xilinx.com:display_processing_system7:fixedio_rtl:1.0 FIXED_IO ] + + # Create ports + set LD [ create_bd_port -dir O -from 3 -to 0 LD ] + + # Create instance: axi_gpio_0, and set properties + set axi_gpio_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:axi_gpio:2.0 axi_gpio_0 ] + set_property -dict [ list \ + CONFIG.C_GPIO_WIDTH {4} \ + ] $axi_gpio_0 + + # Create instance: processing_system7_0, and set properties + set processing_system7_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:processing_system7:5.5 processing_system7_0 ] + set_property -dict [ list \ + CONFIG.PCW_ACT_APU_PERIPHERAL_FREQMHZ {650.000000} \ + CONFIG.PCW_ACT_CAN0_PERIPHERAL_FREQMHZ {23.8095} \ + CONFIG.PCW_ACT_CAN1_PERIPHERAL_FREQMHZ {23.8095} \ + CONFIG.PCW_ACT_CAN_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_DCI_PERIPHERAL_FREQMHZ {10.096154} \ + CONFIG.PCW_ACT_ENET0_PERIPHERAL_FREQMHZ {125.000000} \ + CONFIG.PCW_ACT_ENET1_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_FPGA0_PERIPHERAL_FREQMHZ {100.000000} \ + CONFIG.PCW_ACT_FPGA1_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_FPGA2_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_FPGA3_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_I2C_PERIPHERAL_FREQMHZ {50} \ + CONFIG.PCW_ACT_PCAP_PERIPHERAL_FREQMHZ {200.000000} \ + CONFIG.PCW_ACT_QSPI_PERIPHERAL_FREQMHZ {200.000000} \ + CONFIG.PCW_ACT_SDIO_PERIPHERAL_FREQMHZ {50.000000} \ + CONFIG.PCW_ACT_SMC_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_SPI_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_TPIU_PERIPHERAL_FREQMHZ {200.000000} \ + CONFIG.PCW_ACT_TTC0_CLK0_PERIPHERAL_FREQMHZ {108.333336} \ + CONFIG.PCW_ACT_TTC0_CLK1_PERIPHERAL_FREQMHZ {108.333336} \ + CONFIG.PCW_ACT_TTC0_CLK2_PERIPHERAL_FREQMHZ {108.333336} \ + CONFIG.PCW_ACT_TTC1_CLK0_PERIPHERAL_FREQMHZ {108.333336} \ + CONFIG.PCW_ACT_TTC1_CLK1_PERIPHERAL_FREQMHZ {108.333336} \ + CONFIG.PCW_ACT_TTC1_CLK2_PERIPHERAL_FREQMHZ {108.333336} \ + CONFIG.PCW_ACT_TTC_PERIPHERAL_FREQMHZ {50} \ + CONFIG.PCW_ACT_UART_PERIPHERAL_FREQMHZ {100.000000} \ + CONFIG.PCW_ACT_USB0_PERIPHERAL_FREQMHZ {60} \ + CONFIG.PCW_ACT_USB1_PERIPHERAL_FREQMHZ {60} \ + CONFIG.PCW_ACT_WDT_PERIPHERAL_FREQMHZ {108.333336} \ + CONFIG.PCW_APU_CLK_RATIO_ENABLE {6:2:1} \ + CONFIG.PCW_APU_PERIPHERAL_FREQMHZ {650} \ + CONFIG.PCW_ARMPLL_CTRL_FBDIV {26} \ + CONFIG.PCW_CAN0_BASEADDR {0xE0008000} \ + CONFIG.PCW_CAN0_CAN0_IO {} \ + CONFIG.PCW_CAN0_HIGHADDR {0xE0008FFF} \ + CONFIG.PCW_CAN0_PERIPHERAL_CLKSRC {External} \ + CONFIG.PCW_CAN0_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_CAN0_PERIPHERAL_FREQMHZ {-1} \ + CONFIG.PCW_CAN1_BASEADDR {0xE0009000} \ + CONFIG.PCW_CAN1_CAN1_IO {} \ + CONFIG.PCW_CAN1_HIGHADDR {0xE0009FFF} \ + CONFIG.PCW_CAN1_PERIPHERAL_CLKSRC {External} \ + CONFIG.PCW_CAN1_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_CAN1_PERIPHERAL_FREQMHZ {-1} \ + CONFIG.PCW_CAN_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_CAN_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_CAN_PERIPHERAL_DIVISOR1 {1} \ + CONFIG.PCW_CAN_PERIPHERAL_FREQMHZ {100} \ + CONFIG.PCW_CAN_PERIPHERAL_VALID {0} \ + CONFIG.PCW_CLK0_FREQ {100000000} \ + CONFIG.PCW_CLK1_FREQ {10000000} \ + CONFIG.PCW_CLK2_FREQ {10000000} \ + CONFIG.PCW_CLK3_FREQ {10000000} \ + CONFIG.PCW_CORE0_FIQ_INTR {0} \ + CONFIG.PCW_CORE0_IRQ_INTR {0} \ + CONFIG.PCW_CORE1_FIQ_INTR {0} \ + CONFIG.PCW_CORE1_IRQ_INTR {0} \ + CONFIG.PCW_CPU_CPU_6X4X_MAX_RANGE {667} \ + CONFIG.PCW_CPU_CPU_PLL_FREQMHZ {1300.000} \ + CONFIG.PCW_CPU_PERIPHERAL_CLKSRC {ARM PLL} \ + CONFIG.PCW_CPU_PERIPHERAL_DIVISOR0 {2} \ + CONFIG.PCW_CRYSTAL_PERIPHERAL_FREQMHZ {50} \ + CONFIG.PCW_DCI_PERIPHERAL_CLKSRC {DDR PLL} \ + CONFIG.PCW_DCI_PERIPHERAL_DIVISOR0 {52} \ + CONFIG.PCW_DCI_PERIPHERAL_DIVISOR1 {2} \ + CONFIG.PCW_DCI_PERIPHERAL_FREQMHZ {10.159} \ + CONFIG.PCW_DDRPLL_CTRL_FBDIV {21} \ + CONFIG.PCW_DDR_DDR_PLL_FREQMHZ {1050.000} \ + CONFIG.PCW_DDR_HPRLPR_QUEUE_PARTITION {HPR(0)/LPR(32)} \ + CONFIG.PCW_DDR_HPR_TO_CRITICAL_PRIORITY_LEVEL {15} \ + CONFIG.PCW_DDR_LPR_TO_CRITICAL_PRIORITY_LEVEL {2} \ + CONFIG.PCW_DDR_PERIPHERAL_CLKSRC {DDR PLL} \ + CONFIG.PCW_DDR_PERIPHERAL_DIVISOR0 {2} \ + CONFIG.PCW_DDR_PORT0_HPR_ENABLE {0} \ + CONFIG.PCW_DDR_PORT1_HPR_ENABLE {0} \ + CONFIG.PCW_DDR_PORT2_HPR_ENABLE {0} \ + CONFIG.PCW_DDR_PORT3_HPR_ENABLE {0} \ + CONFIG.PCW_DDR_PRIORITY_READPORT_0 {} \ + CONFIG.PCW_DDR_PRIORITY_READPORT_2 {} \ + CONFIG.PCW_DDR_PRIORITY_WRITEPORT_0 {} \ + CONFIG.PCW_DDR_PRIORITY_WRITEPORT_2 {} \ + CONFIG.PCW_DDR_RAM_BASEADDR {0x00100000} \ + CONFIG.PCW_DDR_RAM_HIGHADDR {0x1FFFFFFF} \ + CONFIG.PCW_DDR_WRITE_TO_CRITICAL_PRIORITY_LEVEL {2} \ + CONFIG.PCW_DM_WIDTH {4} \ + CONFIG.PCW_DQS_WIDTH {4} \ + CONFIG.PCW_DQ_WIDTH {32} \ + CONFIG.PCW_ENET0_BASEADDR {0xE000B000} \ + CONFIG.PCW_ENET0_ENET0_IO {MIO 16 .. 27} \ + CONFIG.PCW_ENET0_GRP_MDIO_ENABLE {1} \ + CONFIG.PCW_ENET0_GRP_MDIO_IO {MIO 52 .. 53} \ + CONFIG.PCW_ENET0_HIGHADDR {0xE000BFFF} \ + CONFIG.PCW_ENET0_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_ENET0_PERIPHERAL_DIVISOR0 {8} \ + CONFIG.PCW_ENET0_PERIPHERAL_DIVISOR1 {1} \ + CONFIG.PCW_ENET0_PERIPHERAL_ENABLE {1} \ + CONFIG.PCW_ENET0_PERIPHERAL_FREQMHZ {1000 Mbps} \ + CONFIG.PCW_ENET0_RESET_ENABLE {1} \ + CONFIG.PCW_ENET0_RESET_IO {MIO 9} \ + CONFIG.PCW_ENET1_BASEADDR {0xE000C000} \ + CONFIG.PCW_ENET1_ENET1_IO {} \ + CONFIG.PCW_ENET1_HIGHADDR {0xE000CFFF} \ + CONFIG.PCW_ENET1_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_ENET1_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_ENET1_PERIPHERAL_DIVISOR1 {1} \ + CONFIG.PCW_ENET1_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_ENET1_PERIPHERAL_FREQMHZ {1000 Mbps} \ + CONFIG.PCW_ENET1_RESET_ENABLE {0} \ + CONFIG.PCW_ENET1_RESET_IO {} \ + CONFIG.PCW_FTM_CTI_IN1 {} \ + CONFIG.PCW_FTM_CTI_IN3 {} \ + CONFIG.PCW_FTM_CTI_OUT1 {} \ + CONFIG.PCW_FTM_CTI_OUT3 {} \ + CONFIG.PCW_GPIO_EMIO_GPIO_WIDTH {64} \ + CONFIG.PCW_GPIO_HIGHADDR {0xE000AFFF} \ + CONFIG.PCW_GPIO_MIO_GPIO_ENABLE {1} \ + CONFIG.PCW_GPIO_MIO_GPIO_IO {MIO} \ + CONFIG.PCW_GPIO_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_I2C0_BASEADDR {0xE0004000} \ + CONFIG.PCW_I2C0_GRP_INT_ENABLE {0} \ + CONFIG.PCW_I2C0_GRP_INT_IO {} \ + CONFIG.PCW_I2C0_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_I2C0_RESET_ENABLE {0} \ + CONFIG.PCW_I2C0_RESET_IO {} \ + CONFIG.PCW_I2C1_HIGHADDR {0xE0005FFF} \ + CONFIG.PCW_I2C1_I2C1_IO {} \ + CONFIG.PCW_I2C_PERIPHERAL_FREQMHZ {25} \ + CONFIG.PCW_I2C_RESET_ENABLE {1} \ + CONFIG.PCW_I2C_RESET_POLARITY {Active Low} \ + CONFIG.PCW_I2C_RESET_SELECT {} \ + CONFIG.PCW_NAND_NAND_IO {} \ + CONFIG.PCW_NOR_GRP_CS0_ENABLE {0} \ + CONFIG.PCW_NOR_GRP_CS0_IO {} \ + CONFIG.PCW_NOR_GRP_SRAM_CS0_ENABLE {0} \ + CONFIG.PCW_NOR_GRP_SRAM_CS0_IO {} \ + CONFIG.PCW_NOR_GRP_SRAM_INT_ENABLE {0} \ + CONFIG.PCW_NOR_GRP_SRAM_INT_IO {} \ + CONFIG.PCW_NOR_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_NOR_SRAM_CS0_T_CEOE {1} \ + CONFIG.PCW_NOR_SRAM_CS0_T_PC {1} \ + CONFIG.PCW_NOR_SRAM_CS0_T_RC {11} \ + CONFIG.PCW_NOR_SRAM_CS0_T_TR {1} \ + CONFIG.PCW_NOR_SRAM_CS0_T_WC {11} \ + CONFIG.PCW_NOR_SRAM_CS0_T_WP {1} \ + CONFIG.PCW_NOR_SRAM_CS0_WE_TIME {0} \ + CONFIG.PCW_NOR_SRAM_CS1_T_CEOE {1} \ + CONFIG.PCW_NOR_SRAM_CS1_T_PC {1} \ + CONFIG.PCW_NOR_SRAM_CS1_T_RC {11} \ + CONFIG.PCW_NOR_SRAM_CS1_T_TR {1} \ + CONFIG.PCW_NOR_SRAM_CS1_T_WC {11} \ + CONFIG.PCW_NOR_SRAM_CS1_T_WP {1} \ + CONFIG.PCW_NOR_SRAM_CS1_WE_TIME {0} \ + CONFIG.PCW_OVERRIDE_BASIC_CLOCK {0} \ + CONFIG.PCW_P2F_CAN0_INTR {0} \ + CONFIG.PCW_P2F_CAN1_INTR {0} \ + CONFIG.PCW_P2F_CTI_INTR {0} \ + CONFIG.PCW_P2F_DMAC0_INTR {0} \ + CONFIG.PCW_P2F_DMAC1_INTR {0} \ + CONFIG.PCW_P2F_DMAC2_INTR {0} \ + CONFIG.PCW_P2F_DMAC3_INTR {0} \ + CONFIG.PCW_P2F_DMAC4_INTR {0} \ + CONFIG.PCW_P2F_DMAC5_INTR {0} \ + CONFIG.PCW_P2F_DMAC6_INTR {0} \ + CONFIG.PCW_P2F_DMAC7_INTR {0} \ + CONFIG.PCW_P2F_DMAC_ABORT_INTR {0} \ + CONFIG.PCW_P2F_ENET0_INTR {0} \ + CONFIG.PCW_P2F_ENET1_INTR {0} \ + CONFIG.PCW_P2F_GPIO_INTR {0} \ + CONFIG.PCW_P2F_I2C0_INTR {0} \ + CONFIG.PCW_P2F_I2C1_INTR {0} \ + CONFIG.PCW_P2F_QSPI_INTR {0} \ + CONFIG.PCW_P2F_SDIO0_INTR {0} \ + CONFIG.PCW_P2F_SDIO1_INTR {0} \ + CONFIG.PCW_P2F_SMC_INTR {0} \ + CONFIG.PCW_P2F_SPI0_INTR {0} \ + CONFIG.PCW_P2F_SPI1_INTR {0} \ + CONFIG.PCW_P2F_UART0_INTR {0} \ + CONFIG.PCW_P2F_UART1_INTR {0} \ + CONFIG.PCW_P2F_USB0_INTR {0} \ + CONFIG.PCW_P2F_USB1_INTR {0} \ + CONFIG.PCW_PACKAGE_DDR_BOARD_DELAY0 {0.223} \ + CONFIG.PCW_PACKAGE_DDR_BOARD_DELAY1 {0.212} \ + CONFIG.PCW_PACKAGE_DDR_BOARD_DELAY2 {0.085} \ + CONFIG.PCW_PACKAGE_DDR_BOARD_DELAY3 {0.092} \ + CONFIG.PCW_PACKAGE_DDR_DQS_TO_CLK_DELAY_0 {0.040} \ + CONFIG.PCW_PACKAGE_DDR_DQS_TO_CLK_DELAY_1 {0.058} \ + CONFIG.PCW_PACKAGE_DDR_DQS_TO_CLK_DELAY_2 {-0.009} \ + CONFIG.PCW_PACKAGE_DDR_DQS_TO_CLK_DELAY_3 {-0.033} \ + CONFIG.PCW_PACKAGE_NAME {clg400} \ + CONFIG.PCW_PCAP_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_PCAP_PERIPHERAL_DIVISOR0 {5} \ + CONFIG.PCW_PCAP_PERIPHERAL_FREQMHZ {200} \ + CONFIG.PCW_PERIPHERAL_BOARD_PRESET {None} \ + CONFIG.PCW_PJTAG_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_PJTAG_PJTAG_IO {} \ + CONFIG.PCW_QSPI_GRP_SINGLE_SS_ENABLE {1} \ + CONFIG.PCW_QSPI_GRP_SINGLE_SS_IO {MIO 1 .. 6} \ + CONFIG.PCW_QSPI_GRP_SS1_ENABLE {0} \ + CONFIG.PCW_QSPI_GRP_SS1_IO {} \ + CONFIG.PCW_SD0_GRP_WP_ENABLE {0} \ + CONFIG.PCW_SD0_GRP_WP_IO {} \ + CONFIG.PCW_SD1_GRP_POW_ENABLE {0} \ + CONFIG.PCW_SD1_GRP_POW_IO {} \ + CONFIG.PCW_SD1_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_SD1_SD1_IO {} \ + CONFIG.PCW_SPI0_GRP_SS1_ENABLE {0} \ + CONFIG.PCW_SPI0_GRP_SS1_IO {} \ + CONFIG.PCW_SPI0_HIGHADDR {0xE0006FFF} \ + CONFIG.PCW_SPI0_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_SPI0_SPI0_IO {} \ + CONFIG.PCW_SPI1_GRP_SS1_ENABLE {0} \ + CONFIG.PCW_SPI1_GRP_SS1_IO {} \ + CONFIG.PCW_SPI1_HIGHADDR {0xE0007FFF} \ + CONFIG.PCW_SPI1_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_SPI1_SPI1_IO {} \ + CONFIG.PCW_TRACE_GRP_2BIT_ENABLE {0} \ + CONFIG.PCW_TRACE_GRP_2BIT_IO {} \ + CONFIG.PCW_TRACE_GRP_4BIT_ENABLE {0} \ + CONFIG.PCW_TRACE_GRP_4BIT_IO {} \ + CONFIG.PCW_TRACE_INTERNAL_WIDTH {2} \ + CONFIG.PCW_TRACE_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_TRACE_PIPELINE_WIDTH {8} \ + CONFIG.PCW_TRACE_TRACE_IO {} \ + CONFIG.PCW_TTC1_BASEADDR {0xE0105000} \ + CONFIG.PCW_TTC1_CLK0_PERIPHERAL_CLKSRC {CPU_1X} \ + CONFIG.PCW_TTC1_CLK0_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_TTC1_CLK0_PERIPHERAL_FREQMHZ {133.333333} \ + CONFIG.PCW_TTC1_CLK1_PERIPHERAL_CLKSRC {CPU_1X} \ + CONFIG.PCW_TTC1_CLK1_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_TTC1_CLK1_PERIPHERAL_FREQMHZ {133.333333} \ + CONFIG.PCW_TTC1_CLK2_PERIPHERAL_CLKSRC {CPU_1X} \ + CONFIG.PCW_TTC1_CLK2_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_TTC1_CLK2_PERIPHERAL_FREQMHZ {133.333333} \ + CONFIG.PCW_TTC1_HIGHADDR {0xE0105fff} \ + CONFIG.PCW_TTC1_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_TTC1_TTC1_IO {} \ + CONFIG.PCW_UART0_HIGHADDR {0xE0000FFF} \ + CONFIG.PCW_UART0_PERIPHERAL_ENABLE {1} \ + CONFIG.PCW_UART0_UART0_IO {MIO 14 .. 15} \ + CONFIG.PCW_UART1_BASEADDR {0xE0001000} \ + CONFIG.PCW_UART1_BAUD_RATE {115200} \ + CONFIG.PCW_UART1_GRP_FULL_ENABLE {0} \ + CONFIG.PCW_UART1_GRP_FULL_IO {} \ + CONFIG.PCW_UART_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_UART_PERIPHERAL_DIVISOR0 {10} \ + CONFIG.PCW_UART_PERIPHERAL_FREQMHZ {100} \ + CONFIG.PCW_UART_PERIPHERAL_VALID {1} \ + CONFIG.PCW_UIPARAM_ACT_DDR_FREQ_MHZ {525.000000} \ + CONFIG.PCW_UIPARAM_DDR_ADV_ENABLE {0} \ + CONFIG.PCW_UIPARAM_DDR_AL {0} \ + CONFIG.PCW_UIPARAM_DDR_BANK_ADDR_COUNT {3} \ + CONFIG.PCW_UIPARAM_DDR_BL {8} \ + CONFIG.PCW_UIPARAM_DDR_BOARD_DELAY0 {0.223} \ + CONFIG.PCW_UIPARAM_DDR_BOARD_DELAY1 {0.212} \ + CONFIG.PCW_UIPARAM_DDR_BOARD_DELAY2 {0.085} \ + CONFIG.PCW_UIPARAM_DDR_BOARD_DELAY3 {0.092} \ + CONFIG.PCW_UIPARAM_DDR_BUS_WIDTH {16 Bit} \ + CONFIG.PCW_UIPARAM_DDR_CL {7} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_0_LENGTH_MM {25.8} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_0_PACKAGE_LENGTH {80.4535} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_0_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_1_LENGTH_MM {25.8} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_1_PACKAGE_LENGTH {80.4535} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_1_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_2_LENGTH_MM {0} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_2_PACKAGE_LENGTH {80.4535} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_2_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_3_LENGTH_MM {0} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_3_PACKAGE_LENGTH {80.4535} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_3_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_STOP_EN {0} \ + CONFIG.PCW_UIPARAM_DDR_COL_ADDR_COUNT {10} \ + CONFIG.PCW_UIPARAM_DDR_CWL {6} \ + CONFIG.PCW_UIPARAM_DDR_DEVICE_CAPACITY {4096 MBits} \ + CONFIG.PCW_UIPARAM_DDR_DQS_0_LENGTH_MM {15.6} \ + CONFIG.PCW_UIPARAM_DDR_DQS_0_PACKAGE_LENGTH {105.056} \ + CONFIG.PCW_UIPARAM_DDR_DQS_0_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_DQS_1_LENGTH_MM {18.8} \ + CONFIG.PCW_UIPARAM_DDR_DQS_1_PACKAGE_LENGTH {66.904} \ + CONFIG.PCW_UIPARAM_DDR_DQS_1_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_DQS_2_LENGTH_MM {0} \ + CONFIG.PCW_UIPARAM_DDR_DQS_2_PACKAGE_LENGTH {89.1715} \ + CONFIG.PCW_UIPARAM_DDR_DQS_2_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_DQS_3_LENGTH_MM {0} \ + CONFIG.PCW_UIPARAM_DDR_DQS_3_PACKAGE_LENGTH {113.63} \ + CONFIG.PCW_UIPARAM_DDR_DQS_3_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_DQS_TO_CLK_DELAY_0 {0.040} \ + CONFIG.PCW_UIPARAM_DDR_DQS_TO_CLK_DELAY_1 {0.058} \ + CONFIG.PCW_UIPARAM_DDR_DQS_TO_CLK_DELAY_2 {-0.009} \ + CONFIG.PCW_UIPARAM_DDR_DQS_TO_CLK_DELAY_3 {-0.033} \ + CONFIG.PCW_UIPARAM_DDR_DQ_0_LENGTH_MM {16.5} \ + CONFIG.PCW_UIPARAM_DDR_DQ_0_PACKAGE_LENGTH {98.503} \ + CONFIG.PCW_UIPARAM_DDR_DQ_0_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_DQ_1_LENGTH_MM {18} \ + CONFIG.PCW_UIPARAM_DDR_DQ_1_PACKAGE_LENGTH {68.5855} \ + CONFIG.PCW_UIPARAM_DDR_DQ_1_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_DQ_2_LENGTH_MM {0} \ + CONFIG.PCW_UIPARAM_DDR_DQ_2_PACKAGE_LENGTH {90.295} \ + CONFIG.PCW_UIPARAM_DDR_DQ_2_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_DQ_3_LENGTH_MM {0} \ + CONFIG.PCW_UIPARAM_DDR_DQ_3_PACKAGE_LENGTH {103.977} \ + CONFIG.PCW_UIPARAM_DDR_DQ_3_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_DRAM_WIDTH {16 Bits} \ + CONFIG.PCW_UIPARAM_DDR_ECC {Disabled} \ + CONFIG.PCW_UIPARAM_DDR_ENABLE {1} \ + CONFIG.PCW_UIPARAM_DDR_FREQ_MHZ {525} \ + CONFIG.PCW_UIPARAM_DDR_HIGH_TEMP {Normal (0-85)} \ + CONFIG.PCW_UIPARAM_DDR_MEMORY_TYPE {DDR 3} \ + CONFIG.PCW_UIPARAM_DDR_PARTNO {MT41J256M16 RE-125} \ + CONFIG.PCW_UIPARAM_DDR_ROW_ADDR_COUNT {15} \ + CONFIG.PCW_UIPARAM_DDR_SPEED_BIN {DDR3_1066F} \ + CONFIG.PCW_UIPARAM_DDR_TRAIN_DATA_EYE {1} \ + CONFIG.PCW_UIPARAM_DDR_TRAIN_READ_GATE {1} \ + CONFIG.PCW_UIPARAM_DDR_TRAIN_WRITE_LEVEL {1} \ + CONFIG.PCW_UIPARAM_DDR_T_FAW {40.0} \ + CONFIG.PCW_UIPARAM_DDR_T_RAS_MIN {35.0} \ + CONFIG.PCW_UIPARAM_DDR_T_RC {48.91} \ + CONFIG.PCW_UIPARAM_DDR_T_RCD {7} \ + CONFIG.PCW_UIPARAM_DDR_T_RP {7} \ + CONFIG.PCW_UIPARAM_DDR_USE_INTERNAL_VREF {0} \ + CONFIG.PCW_UIPARAM_GENERATE_SUMMARY {NA} \ + CONFIG.PCW_USB0_BASEADDR {0xE0102000} \ + CONFIG.PCW_USB0_HIGHADDR {0xE0102fff} \ + CONFIG.PCW_USB0_PERIPHERAL_ENABLE {1} \ + CONFIG.PCW_USB0_PERIPHERAL_FREQMHZ {60} \ + CONFIG.PCW_USB0_RESET_ENABLE {1} \ + CONFIG.PCW_USB0_RESET_IO {MIO 46} \ + CONFIG.PCW_USB0_USB0_IO {MIO 28 .. 39} \ + CONFIG.PCW_USB1_BASEADDR {0xE0103000} \ + CONFIG.PCW_USB1_HIGHADDR {0xE0103fff} \ + CONFIG.PCW_USB1_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_USB1_PERIPHERAL_FREQMHZ {60} \ + CONFIG.PCW_USB1_RESET_ENABLE {0} \ + CONFIG.PCW_USB1_RESET_IO {} \ + CONFIG.PCW_USB_RESET_ENABLE {1} \ + CONFIG.PCW_USB_RESET_POLARITY {Active Low} \ + CONFIG.PCW_USB_RESET_SELECT {Share reset pin} \ + CONFIG.PCW_USE_AXI_FABRIC_IDLE {0} \ + CONFIG.PCW_USE_AXI_NONSECURE {0} \ + CONFIG.PCW_USE_CORESIGHT {0} \ + CONFIG.PCW_USE_CROSS_TRIGGER {0} \ + CONFIG.PCW_USE_CR_FABRIC {1} \ + CONFIG.PCW_USE_DDR_BYPASS {0} \ + CONFIG.PCW_USE_DEBUG {0} \ + CONFIG.PCW_USE_DEFAULT_ACP_USER_VAL {0} \ + CONFIG.PCW_USE_DMA0 {0} \ + CONFIG.PCW_USE_DMA1 {0} \ + CONFIG.PCW_USE_DMA2 {0} \ + CONFIG.PCW_USE_DMA3 {0} \ + CONFIG.PCW_USE_EXPANDED_IOP {0} \ + CONFIG.PCW_USE_EXPANDED_PS_SLCR_REGISTERS {0} \ + CONFIG.PCW_USE_FABRIC_INTERRUPT {0} \ + CONFIG.PCW_USE_HIGH_OCM {0} \ + CONFIG.PCW_USE_M_AXI_GP0 {1} \ + CONFIG.PCW_USE_M_AXI_GP1 {0} \ + CONFIG.PCW_USE_PROC_EVENT_BUS {0} \ + CONFIG.PCW_USE_PS_SLCR_REGISTERS {0} \ + CONFIG.PCW_USE_S_AXI_ACP {0} \ + CONFIG.PCW_USE_S_AXI_GP0 {0} \ + CONFIG.PCW_USE_S_AXI_GP1 {0} \ + CONFIG.PCW_USE_S_AXI_HP0 {0} \ + CONFIG.PCW_USE_S_AXI_HP1 {0} \ + CONFIG.PCW_USE_S_AXI_HP2 {0} \ + CONFIG.PCW_USE_S_AXI_HP3 {0} \ + CONFIG.PCW_USE_TRACE {0} \ + CONFIG.PCW_USE_TRACE_DATA_EDGE_DETECTOR {0} \ + CONFIG.PCW_VALUE_SILVERSION {3} \ + CONFIG.PCW_WDT_PERIPHERAL_CLKSRC {CPU_1X} \ + CONFIG.PCW_WDT_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_WDT_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_WDT_PERIPHERAL_FREQMHZ {133.333333} \ + CONFIG.PCW_WDT_WDT_IO {} \ + CONFIG.PCW_CAN0_GRP_CLK_ENABLE {0} \ + CONFIG.PCW_CAN0_GRP_CLK_IO {} \ + CONFIG.PCW_CAN1_GRP_CLK_ENABLE {0} \ + CONFIG.PCW_CAN1_GRP_CLK_IO {} \ + CONFIG.PCW_DDR_PRIORITY_READPORT_1 {} \ + CONFIG.PCW_DDR_PRIORITY_READPORT_3 {} \ + CONFIG.PCW_DDR_PRIORITY_WRITEPORT_1 {} \ + CONFIG.PCW_DDR_PRIORITY_WRITEPORT_3 {} \ + CONFIG.PCW_ENET1_GRP_MDIO_ENABLE {0} \ + CONFIG.PCW_ENET1_GRP_MDIO_IO {} \ + CONFIG.PCW_ENET_RESET_ENABLE {1} \ + CONFIG.PCW_ENET_RESET_POLARITY {Active Low} \ + CONFIG.PCW_ENET_RESET_SELECT {Share reset pin} \ + CONFIG.PCW_EN_4K_TIMER {0} \ + CONFIG.PCW_EN_CAN0 {0} \ + CONFIG.PCW_EN_CAN1 {0} \ + CONFIG.PCW_EN_CLK0_PORT {1} \ + CONFIG.PCW_EN_CLK1_PORT {0} \ + CONFIG.PCW_EN_CLK2_PORT {0} \ + CONFIG.PCW_EN_CLK3_PORT {0} \ + CONFIG.PCW_EN_CLKTRIG0_PORT {0} \ + CONFIG.PCW_EN_CLKTRIG1_PORT {0} \ + CONFIG.PCW_EN_CLKTRIG2_PORT {0} \ + CONFIG.PCW_EN_CLKTRIG3_PORT {0} \ + CONFIG.PCW_EN_DDR {1} \ + CONFIG.PCW_EN_EMIO_CAN0 {0} \ + CONFIG.PCW_EN_EMIO_CAN1 {0} \ + CONFIG.PCW_EN_EMIO_CD_SDIO0 {0} \ + CONFIG.PCW_EN_EMIO_CD_SDIO1 {0} \ + CONFIG.PCW_EN_EMIO_ENET0 {0} \ + CONFIG.PCW_EN_EMIO_ENET1 {0} \ + CONFIG.PCW_EN_EMIO_GPIO {0} \ + CONFIG.PCW_EN_EMIO_I2C0 {0} \ + CONFIG.PCW_EN_EMIO_I2C1 {0} \ + CONFIG.PCW_EN_EMIO_MODEM_UART0 {0} \ + CONFIG.PCW_EN_EMIO_MODEM_UART1 {0} \ + CONFIG.PCW_EN_EMIO_PJTAG {0} \ + CONFIG.PCW_EN_EMIO_SDIO0 {0} \ + CONFIG.PCW_EN_EMIO_SDIO1 {0} \ + CONFIG.PCW_EN_EMIO_SPI0 {0} \ + CONFIG.PCW_EN_EMIO_SPI1 {0} \ + CONFIG.PCW_EN_EMIO_SRAM_INT {0} \ + CONFIG.PCW_EN_EMIO_TRACE {0} \ + CONFIG.PCW_EN_EMIO_TTC0 {0} \ + CONFIG.PCW_EN_EMIO_TTC1 {0} \ + CONFIG.PCW_EN_EMIO_UART0 {0} \ + CONFIG.PCW_EN_EMIO_UART1 {0} \ + CONFIG.PCW_EN_EMIO_WDT {0} \ + CONFIG.PCW_EN_EMIO_WP_SDIO0 {0} \ + CONFIG.PCW_EN_EMIO_WP_SDIO1 {0} \ + CONFIG.PCW_EN_ENET0 {1} \ + CONFIG.PCW_EN_ENET1 {0} \ + CONFIG.PCW_EN_GPIO {1} \ + CONFIG.PCW_EN_I2C0 {0} \ + CONFIG.PCW_EN_I2C1 {0} \ + CONFIG.PCW_EN_MODEM_UART0 {0} \ + CONFIG.PCW_EN_MODEM_UART1 {0} \ + CONFIG.PCW_EN_PJTAG {0} \ + CONFIG.PCW_EN_PTP_ENET0 {0} \ + CONFIG.PCW_EN_PTP_ENET1 {0} \ + CONFIG.PCW_EN_QSPI {1} \ + CONFIG.PCW_EN_RST0_PORT {1} \ + CONFIG.PCW_EN_RST1_PORT {0} \ + CONFIG.PCW_EN_RST2_PORT {0} \ + CONFIG.PCW_EN_RST3_PORT {0} \ + CONFIG.PCW_EN_SDIO0 {1} \ + CONFIG.PCW_EN_SDIO1 {0} \ + CONFIG.PCW_EN_SMC {0} \ + CONFIG.PCW_EN_SPI0 {0} \ + CONFIG.PCW_EN_SPI1 {0} \ + CONFIG.PCW_EN_TRACE {0} \ + CONFIG.PCW_EN_TTC0 {0} \ + CONFIG.PCW_EN_TTC1 {0} \ + CONFIG.PCW_EN_UART0 {1} \ + CONFIG.PCW_EN_UART1 {0} \ + CONFIG.PCW_EN_USB0 {1} \ + CONFIG.PCW_EN_USB1 {0} \ + CONFIG.PCW_EN_WDT {0} \ + CONFIG.PCW_FCLK0_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_FCLK0_PERIPHERAL_DIVISOR0 {5} \ + CONFIG.PCW_FCLK0_PERIPHERAL_DIVISOR1 {2} \ + CONFIG.PCW_FCLK1_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_FCLK1_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_FCLK1_PERIPHERAL_DIVISOR1 {1} \ + CONFIG.PCW_FCLK2_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_FCLK2_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_FCLK2_PERIPHERAL_DIVISOR1 {1} \ + CONFIG.PCW_FCLK3_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_FCLK3_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_FCLK3_PERIPHERAL_DIVISOR1 {1} \ + CONFIG.PCW_FCLK_CLK0_BUF {TRUE} \ + CONFIG.PCW_FCLK_CLK1_BUF {FALSE} \ + CONFIG.PCW_FCLK_CLK2_BUF {FALSE} \ + CONFIG.PCW_FCLK_CLK3_BUF {FALSE} \ + CONFIG.PCW_FPGA0_PERIPHERAL_FREQMHZ {100} \ + CONFIG.PCW_FPGA1_PERIPHERAL_FREQMHZ {50} \ + CONFIG.PCW_FPGA2_PERIPHERAL_FREQMHZ {50} \ + CONFIG.PCW_FPGA3_PERIPHERAL_FREQMHZ {50} \ + CONFIG.PCW_FPGA_FCLK0_ENABLE {1} \ + CONFIG.PCW_FPGA_FCLK1_ENABLE {0} \ + CONFIG.PCW_FPGA_FCLK2_ENABLE {0} \ + CONFIG.PCW_FPGA_FCLK3_ENABLE {0} \ + CONFIG.PCW_FTM_CTI_IN0 {} \ + CONFIG.PCW_FTM_CTI_IN2 {} \ + CONFIG.PCW_FTM_CTI_OUT0 {} \ + CONFIG.PCW_FTM_CTI_OUT2 {} \ + CONFIG.PCW_GPIO_BASEADDR {0xE000A000} \ + CONFIG.PCW_GPIO_EMIO_GPIO_ENABLE {0} \ + CONFIG.PCW_GPIO_EMIO_GPIO_IO {} \ + CONFIG.PCW_I2C0_HIGHADDR {0xE0004FFF} \ + CONFIG.PCW_I2C0_I2C0_IO {} \ + CONFIG.PCW_I2C1_BASEADDR {0xE0005000} \ + CONFIG.PCW_I2C1_GRP_INT_ENABLE {0} \ + CONFIG.PCW_I2C1_GRP_INT_IO {} \ + CONFIG.PCW_I2C1_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_I2C1_RESET_ENABLE {0} \ + CONFIG.PCW_I2C1_RESET_IO {} \ + CONFIG.PCW_IMPORT_BOARD_PRESET {None} \ + CONFIG.PCW_INCLUDE_ACP_TRANS_CHECK {0} \ + CONFIG.PCW_INCLUDE_TRACE_BUFFER {0} \ + CONFIG.PCW_IOPLL_CTRL_FBDIV {20} \ + CONFIG.PCW_IO_IO_PLL_FREQMHZ {1000.000} \ + CONFIG.PCW_IRQ_F2P_INTR {0} \ + CONFIG.PCW_IRQ_F2P_MODE {DIRECT} \ + CONFIG.PCW_MIO_0_DIRECTION {inout} \ + CONFIG.PCW_MIO_0_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_0_PULLUP {enabled} \ + CONFIG.PCW_MIO_0_SLEW {slow} \ + CONFIG.PCW_MIO_10_DIRECTION {inout} \ + CONFIG.PCW_MIO_10_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_10_PULLUP {enabled} \ + CONFIG.PCW_MIO_10_SLEW {slow} \ + CONFIG.PCW_MIO_11_DIRECTION {inout} \ + CONFIG.PCW_MIO_11_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_11_PULLUP {enabled} \ + CONFIG.PCW_MIO_11_SLEW {slow} \ + CONFIG.PCW_MIO_12_DIRECTION {inout} \ + CONFIG.PCW_MIO_12_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_12_PULLUP {enabled} \ + CONFIG.PCW_MIO_12_SLEW {slow} \ + CONFIG.PCW_MIO_13_DIRECTION {inout} \ + CONFIG.PCW_MIO_13_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_13_PULLUP {enabled} \ + CONFIG.PCW_MIO_13_SLEW {slow} \ + CONFIG.PCW_MIO_14_DIRECTION {in} \ + CONFIG.PCW_MIO_14_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_14_PULLUP {enabled} \ + CONFIG.PCW_MIO_14_SLEW {slow} \ + CONFIG.PCW_MIO_15_DIRECTION {out} \ + CONFIG.PCW_MIO_15_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_15_PULLUP {enabled} \ + CONFIG.PCW_MIO_15_SLEW {slow} \ + CONFIG.PCW_MIO_16_DIRECTION {out} \ + CONFIG.PCW_MIO_16_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_16_PULLUP {enabled} \ + CONFIG.PCW_MIO_16_SLEW {slow} \ + CONFIG.PCW_MIO_17_DIRECTION {out} \ + CONFIG.PCW_MIO_17_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_17_PULLUP {enabled} \ + CONFIG.PCW_MIO_17_SLEW {slow} \ + CONFIG.PCW_MIO_18_DIRECTION {out} \ + CONFIG.PCW_MIO_18_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_18_PULLUP {enabled} \ + CONFIG.PCW_MIO_18_SLEW {slow} \ + CONFIG.PCW_MIO_19_DIRECTION {out} \ + CONFIG.PCW_MIO_19_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_19_PULLUP {enabled} \ + CONFIG.PCW_MIO_19_SLEW {slow} \ + CONFIG.PCW_MIO_1_DIRECTION {out} \ + CONFIG.PCW_MIO_1_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_1_PULLUP {enabled} \ + CONFIG.PCW_MIO_1_SLEW {slow} \ + CONFIG.PCW_MIO_20_DIRECTION {out} \ + CONFIG.PCW_MIO_20_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_20_PULLUP {enabled} \ + CONFIG.PCW_MIO_20_SLEW {slow} \ + CONFIG.PCW_MIO_21_DIRECTION {out} \ + CONFIG.PCW_MIO_21_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_21_PULLUP {enabled} \ + CONFIG.PCW_MIO_21_SLEW {slow} \ + CONFIG.PCW_MIO_22_DIRECTION {in} \ + CONFIG.PCW_MIO_22_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_22_PULLUP {enabled} \ + CONFIG.PCW_MIO_22_SLEW {slow} \ + CONFIG.PCW_MIO_23_DIRECTION {in} \ + CONFIG.PCW_MIO_23_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_23_PULLUP {enabled} \ + CONFIG.PCW_MIO_23_SLEW {slow} \ + CONFIG.PCW_MIO_24_DIRECTION {in} \ + CONFIG.PCW_MIO_24_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_24_PULLUP {enabled} \ + CONFIG.PCW_MIO_24_SLEW {slow} \ + CONFIG.PCW_MIO_25_DIRECTION {in} \ + CONFIG.PCW_MIO_25_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_25_PULLUP {enabled} \ + CONFIG.PCW_MIO_25_SLEW {slow} \ + CONFIG.PCW_MIO_26_DIRECTION {in} \ + CONFIG.PCW_MIO_26_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_26_PULLUP {enabled} \ + CONFIG.PCW_MIO_26_SLEW {slow} \ + CONFIG.PCW_MIO_27_DIRECTION {in} \ + CONFIG.PCW_MIO_27_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_27_PULLUP {enabled} \ + CONFIG.PCW_MIO_27_SLEW {slow} \ + CONFIG.PCW_MIO_28_DIRECTION {inout} \ + CONFIG.PCW_MIO_28_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_28_PULLUP {enabled} \ + CONFIG.PCW_MIO_28_SLEW {slow} \ + CONFIG.PCW_MIO_29_DIRECTION {in} \ + CONFIG.PCW_MIO_29_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_29_PULLUP {enabled} \ + CONFIG.PCW_MIO_29_SLEW {slow} \ + CONFIG.PCW_MIO_2_DIRECTION {inout} \ + CONFIG.PCW_MIO_2_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_2_PULLUP {disabled} \ + CONFIG.PCW_MIO_2_SLEW {slow} \ + CONFIG.PCW_MIO_30_DIRECTION {out} \ + CONFIG.PCW_MIO_30_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_30_PULLUP {enabled} \ + CONFIG.PCW_MIO_30_SLEW {slow} \ + CONFIG.PCW_MIO_31_DIRECTION {in} \ + CONFIG.PCW_MIO_31_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_31_PULLUP {enabled} \ + CONFIG.PCW_MIO_31_SLEW {slow} \ + CONFIG.PCW_MIO_32_DIRECTION {inout} \ + CONFIG.PCW_MIO_32_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_32_PULLUP {enabled} \ + CONFIG.PCW_MIO_32_SLEW {slow} \ + CONFIG.PCW_MIO_33_DIRECTION {inout} \ + CONFIG.PCW_MIO_33_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_33_PULLUP {enabled} \ + CONFIG.PCW_MIO_33_SLEW {slow} \ + CONFIG.PCW_MIO_34_DIRECTION {inout} \ + CONFIG.PCW_MIO_34_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_34_PULLUP {enabled} \ + CONFIG.PCW_MIO_34_SLEW {slow} \ + CONFIG.PCW_MIO_35_DIRECTION {inout} \ + CONFIG.PCW_MIO_35_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_35_PULLUP {enabled} \ + CONFIG.PCW_MIO_35_SLEW {slow} \ + CONFIG.PCW_MIO_36_DIRECTION {in} \ + CONFIG.PCW_MIO_36_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_36_PULLUP {enabled} \ + CONFIG.PCW_MIO_36_SLEW {slow} \ + CONFIG.PCW_MIO_37_DIRECTION {inout} \ + CONFIG.PCW_MIO_37_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_37_PULLUP {enabled} \ + CONFIG.PCW_MIO_37_SLEW {slow} \ + CONFIG.PCW_MIO_38_DIRECTION {inout} \ + CONFIG.PCW_MIO_38_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_38_PULLUP {enabled} \ + CONFIG.PCW_MIO_38_SLEW {slow} \ + CONFIG.PCW_MIO_39_DIRECTION {inout} \ + CONFIG.PCW_MIO_39_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_39_PULLUP {enabled} \ + CONFIG.PCW_MIO_39_SLEW {slow} \ + CONFIG.PCW_MIO_3_DIRECTION {inout} \ + CONFIG.PCW_MIO_3_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_3_PULLUP {disabled} \ + CONFIG.PCW_MIO_3_SLEW {slow} \ + CONFIG.PCW_MIO_40_DIRECTION {inout} \ + CONFIG.PCW_MIO_40_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_40_PULLUP {enabled} \ + CONFIG.PCW_MIO_40_SLEW {slow} \ + CONFIG.PCW_MIO_41_DIRECTION {inout} \ + CONFIG.PCW_MIO_41_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_41_PULLUP {enabled} \ + CONFIG.PCW_MIO_41_SLEW {slow} \ + CONFIG.PCW_MIO_42_DIRECTION {inout} \ + CONFIG.PCW_MIO_42_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_42_PULLUP {enabled} \ + CONFIG.PCW_MIO_42_SLEW {slow} \ + CONFIG.PCW_MIO_43_DIRECTION {inout} \ + CONFIG.PCW_MIO_43_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_43_PULLUP {enabled} \ + CONFIG.PCW_MIO_43_SLEW {slow} \ + CONFIG.PCW_MIO_44_DIRECTION {inout} \ + CONFIG.PCW_MIO_44_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_44_PULLUP {enabled} \ + CONFIG.PCW_MIO_44_SLEW {slow} \ + CONFIG.PCW_MIO_45_DIRECTION {inout} \ + CONFIG.PCW_MIO_45_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_45_PULLUP {enabled} \ + CONFIG.PCW_MIO_45_SLEW {slow} \ + CONFIG.PCW_MIO_46_DIRECTION {out} \ + CONFIG.PCW_MIO_46_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_46_PULLUP {enabled} \ + CONFIG.PCW_MIO_46_SLEW {slow} \ + CONFIG.PCW_MIO_47_DIRECTION {in} \ + CONFIG.PCW_MIO_47_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_47_PULLUP {enabled} \ + CONFIG.PCW_MIO_47_SLEW {slow} \ + CONFIG.PCW_MIO_48_DIRECTION {inout} \ + CONFIG.PCW_MIO_48_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_48_PULLUP {enabled} \ + CONFIG.PCW_MIO_48_SLEW {slow} \ + CONFIG.PCW_MIO_49_DIRECTION {inout} \ + CONFIG.PCW_MIO_49_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_49_PULLUP {enabled} \ + CONFIG.PCW_MIO_49_SLEW {slow} \ + CONFIG.PCW_MIO_4_DIRECTION {inout} \ + CONFIG.PCW_MIO_4_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_4_PULLUP {disabled} \ + CONFIG.PCW_MIO_4_SLEW {slow} \ + CONFIG.PCW_MIO_50_DIRECTION {inout} \ + CONFIG.PCW_MIO_50_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_50_PULLUP {enabled} \ + CONFIG.PCW_MIO_50_SLEW {slow} \ + CONFIG.PCW_MIO_51_DIRECTION {inout} \ + CONFIG.PCW_MIO_51_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_51_PULLUP {enabled} \ + CONFIG.PCW_MIO_51_SLEW {slow} \ + CONFIG.PCW_MIO_52_DIRECTION {out} \ + CONFIG.PCW_MIO_52_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_52_PULLUP {enabled} \ + CONFIG.PCW_MIO_52_SLEW {slow} \ + CONFIG.PCW_MIO_53_DIRECTION {inout} \ + CONFIG.PCW_MIO_53_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_53_PULLUP {enabled} \ + CONFIG.PCW_MIO_53_SLEW {slow} \ + CONFIG.PCW_MIO_5_DIRECTION {inout} \ + CONFIG.PCW_MIO_5_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_5_PULLUP {disabled} \ + CONFIG.PCW_MIO_5_SLEW {slow} \ + CONFIG.PCW_MIO_6_DIRECTION {out} \ + CONFIG.PCW_MIO_6_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_6_PULLUP {disabled} \ + CONFIG.PCW_MIO_6_SLEW {slow} \ + CONFIG.PCW_MIO_7_DIRECTION {out} \ + CONFIG.PCW_MIO_7_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_7_PULLUP {disabled} \ + CONFIG.PCW_MIO_7_SLEW {slow} \ + CONFIG.PCW_MIO_8_DIRECTION {out} \ + CONFIG.PCW_MIO_8_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_8_PULLUP {disabled} \ + CONFIG.PCW_MIO_8_SLEW {slow} \ + CONFIG.PCW_MIO_9_DIRECTION {out} \ + CONFIG.PCW_MIO_9_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_9_PULLUP {enabled} \ + CONFIG.PCW_MIO_9_SLEW {slow} \ + CONFIG.PCW_MIO_PRIMITIVE {54} \ + CONFIG.PCW_MIO_TREE_PERIPHERALS {GPIO#Quad SPI Flash#Quad SPI Flash#Quad SPI Flash#Quad SPI Flash#Quad SPI Flash#Quad SPI Flash#GPIO#Quad SPI Flash#ENET Reset#GPIO#GPIO#GPIO#GPIO#UART 0#UART 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#SD 0#SD 0#SD 0#SD 0#SD 0#SD 0#USB Reset#SD 0#GPIO#GPIO#GPIO#GPIO#Enet 0#Enet 0} \ + CONFIG.PCW_MIO_TREE_SIGNALS {gpio[0]#qspi0_ss_b#qspi0_io[0]#qspi0_io[1]#qspi0_io[2]#qspi0_io[3]/HOLD_B#qspi0_sclk#gpio[7]#qspi_fbclk#reset#gpio[10]#gpio[11]#gpio[12]#gpio[13]#rx#tx#tx_clk#txd[0]#txd[1]#txd[2]#txd[3]#tx_ctl#rx_clk#rxd[0]#rxd[1]#rxd[2]#rxd[3]#rx_ctl#data[4]#dir#stp#nxt#data[0]#data[1]#data[2]#data[3]#clk#data[5]#data[6]#data[7]#clk#cmd#data[0]#data[1]#data[2]#data[3]#reset#cd#gpio[48]#gpio[49]#gpio[50]#gpio[51]#mdc#mdio} \ + CONFIG.PCW_M_AXI_GP0_ENABLE_STATIC_REMAP {0} \ + CONFIG.PCW_M_AXI_GP0_ID_WIDTH {12} \ + CONFIG.PCW_M_AXI_GP0_SUPPORT_NARROW_BURST {0} \ + CONFIG.PCW_M_AXI_GP0_THREAD_ID_WIDTH {12} \ + CONFIG.PCW_M_AXI_GP1_ENABLE_STATIC_REMAP {0} \ + CONFIG.PCW_M_AXI_GP1_ID_WIDTH {12} \ + CONFIG.PCW_M_AXI_GP1_SUPPORT_NARROW_BURST {0} \ + CONFIG.PCW_M_AXI_GP1_THREAD_ID_WIDTH {12} \ + CONFIG.PCW_NAND_CYCLES_T_AR {1} \ + CONFIG.PCW_NAND_CYCLES_T_CLR {1} \ + CONFIG.PCW_NAND_CYCLES_T_RC {11} \ + CONFIG.PCW_NAND_CYCLES_T_REA {1} \ + CONFIG.PCW_NAND_CYCLES_T_RR {1} \ + CONFIG.PCW_NAND_CYCLES_T_WC {11} \ + CONFIG.PCW_NAND_CYCLES_T_WP {1} \ + CONFIG.PCW_NAND_GRP_D8_ENABLE {0} \ + CONFIG.PCW_NAND_GRP_D8_IO {} \ + CONFIG.PCW_NAND_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_NOR_CS0_T_CEOE {1} \ + CONFIG.PCW_NOR_CS0_T_PC {1} \ + CONFIG.PCW_NOR_CS0_T_RC {11} \ + CONFIG.PCW_NOR_CS0_T_TR {1} \ + CONFIG.PCW_NOR_CS0_T_WC {11} \ + CONFIG.PCW_NOR_CS0_T_WP {1} \ + CONFIG.PCW_NOR_CS0_WE_TIME {0} \ + CONFIG.PCW_NOR_CS1_T_CEOE {1} \ + CONFIG.PCW_NOR_CS1_T_PC {1} \ + CONFIG.PCW_NOR_CS1_T_RC {11} \ + CONFIG.PCW_NOR_CS1_T_TR {1} \ + CONFIG.PCW_NOR_CS1_T_WC {11} \ + CONFIG.PCW_NOR_CS1_T_WP {1} \ + CONFIG.PCW_NOR_CS1_WE_TIME {0} \ + CONFIG.PCW_NOR_GRP_A25_ENABLE {0} \ + CONFIG.PCW_NOR_GRP_A25_IO {} \ + CONFIG.PCW_NOR_GRP_CS1_ENABLE {0} \ + CONFIG.PCW_NOR_GRP_CS1_IO {} \ + CONFIG.PCW_NOR_GRP_SRAM_CS1_ENABLE {0} \ + CONFIG.PCW_NOR_GRP_SRAM_CS1_IO {} \ + CONFIG.PCW_NOR_NOR_IO {} \ + CONFIG.PCW_PLL_BYPASSMODE_ENABLE {0} \ + CONFIG.PCW_PRESET_BANK0_VOLTAGE {LVCMOS 3.3V} \ + CONFIG.PCW_PRESET_BANK1_VOLTAGE {LVCMOS 1.8V} \ + CONFIG.PCW_PS7_SI_REV {PRODUCTION} \ + CONFIG.PCW_QSPI_GRP_FBCLK_ENABLE {1} \ + CONFIG.PCW_QSPI_GRP_FBCLK_IO {MIO 8} \ + CONFIG.PCW_QSPI_GRP_IO1_ENABLE {0} \ + CONFIG.PCW_QSPI_GRP_IO1_IO {} \ + CONFIG.PCW_QSPI_INTERNAL_HIGHADDRESS {0xFCFFFFFF} \ + CONFIG.PCW_QSPI_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_QSPI_PERIPHERAL_DIVISOR0 {5} \ + CONFIG.PCW_QSPI_PERIPHERAL_ENABLE {1} \ + CONFIG.PCW_QSPI_PERIPHERAL_FREQMHZ {200} \ + CONFIG.PCW_QSPI_QSPI_IO {MIO 1 .. 6} \ + CONFIG.PCW_SD0_GRP_CD_ENABLE {1} \ + CONFIG.PCW_SD0_GRP_CD_IO {MIO 47} \ + CONFIG.PCW_SD0_GRP_POW_ENABLE {0} \ + CONFIG.PCW_SD0_GRP_POW_IO {} \ + CONFIG.PCW_SD0_PERIPHERAL_ENABLE {1} \ + CONFIG.PCW_SD0_SD0_IO {MIO 40 .. 45} \ + CONFIG.PCW_SD1_GRP_CD_ENABLE {0} \ + CONFIG.PCW_SD1_GRP_CD_IO {} \ + CONFIG.PCW_SD1_GRP_WP_ENABLE {0} \ + CONFIG.PCW_SD1_GRP_WP_IO {} \ + CONFIG.PCW_SDIO0_BASEADDR {0xE0100000} \ + CONFIG.PCW_SDIO0_HIGHADDR {0xE0100FFF} \ + CONFIG.PCW_SDIO1_BASEADDR {0xE0101000} \ + CONFIG.PCW_SDIO1_HIGHADDR {0xE0101FFF} \ + CONFIG.PCW_SDIO_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_SDIO_PERIPHERAL_DIVISOR0 {20} \ + CONFIG.PCW_SDIO_PERIPHERAL_FREQMHZ {50} \ + CONFIG.PCW_SDIO_PERIPHERAL_VALID {1} \ + CONFIG.PCW_SINGLE_QSPI_DATA_MODE {x4} \ + CONFIG.PCW_SMC_CYCLE_T0 {NA} \ + CONFIG.PCW_SMC_CYCLE_T1 {NA} \ + CONFIG.PCW_SMC_CYCLE_T2 {NA} \ + CONFIG.PCW_SMC_CYCLE_T3 {NA} \ + CONFIG.PCW_SMC_CYCLE_T4 {NA} \ + CONFIG.PCW_SMC_CYCLE_T5 {NA} \ + CONFIG.PCW_SMC_CYCLE_T6 {NA} \ + CONFIG.PCW_SMC_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_SMC_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_SMC_PERIPHERAL_FREQMHZ {100} \ + CONFIG.PCW_SMC_PERIPHERAL_VALID {0} \ + CONFIG.PCW_SPI0_BASEADDR {0xE0006000} \ + CONFIG.PCW_SPI0_GRP_SS0_ENABLE {0} \ + CONFIG.PCW_SPI0_GRP_SS0_IO {} \ + CONFIG.PCW_SPI0_GRP_SS2_ENABLE {0} \ + CONFIG.PCW_SPI0_GRP_SS2_IO {} \ + CONFIG.PCW_SPI1_BASEADDR {0xE0007000} \ + CONFIG.PCW_SPI1_GRP_SS0_ENABLE {0} \ + CONFIG.PCW_SPI1_GRP_SS0_IO {} \ + CONFIG.PCW_SPI1_GRP_SS2_ENABLE {0} \ + CONFIG.PCW_SPI1_GRP_SS2_IO {} \ + CONFIG.PCW_SPI_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_SPI_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_SPI_PERIPHERAL_FREQMHZ {166.666666} \ + CONFIG.PCW_SPI_PERIPHERAL_VALID {0} \ + CONFIG.PCW_S_AXI_ACP_ARUSER_VAL {31} \ + CONFIG.PCW_S_AXI_ACP_AWUSER_VAL {31} \ + CONFIG.PCW_S_AXI_ACP_ID_WIDTH {3} \ + CONFIG.PCW_S_AXI_GP0_ID_WIDTH {6} \ + CONFIG.PCW_S_AXI_GP1_ID_WIDTH {6} \ + CONFIG.PCW_S_AXI_HP0_DATA_WIDTH {64} \ + CONFIG.PCW_S_AXI_HP0_ID_WIDTH {6} \ + CONFIG.PCW_S_AXI_HP1_DATA_WIDTH {64} \ + CONFIG.PCW_S_AXI_HP1_ID_WIDTH {6} \ + CONFIG.PCW_S_AXI_HP2_DATA_WIDTH {64} \ + CONFIG.PCW_S_AXI_HP2_ID_WIDTH {6} \ + CONFIG.PCW_S_AXI_HP3_DATA_WIDTH {64} \ + CONFIG.PCW_S_AXI_HP3_ID_WIDTH {6} \ + CONFIG.PCW_TPIU_PERIPHERAL_CLKSRC {External} \ + CONFIG.PCW_TPIU_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_TPIU_PERIPHERAL_FREQMHZ {200} \ + CONFIG.PCW_TRACE_BUFFER_CLOCK_DELAY {12} \ + CONFIG.PCW_TRACE_BUFFER_FIFO_SIZE {128} \ + CONFIG.PCW_TRACE_GRP_16BIT_ENABLE {0} \ + CONFIG.PCW_TRACE_GRP_16BIT_IO {} \ + CONFIG.PCW_TRACE_GRP_32BIT_ENABLE {0} \ + CONFIG.PCW_TRACE_GRP_32BIT_IO {} \ + CONFIG.PCW_TRACE_GRP_8BIT_ENABLE {0} \ + CONFIG.PCW_TRACE_GRP_8BIT_IO {} \ + CONFIG.PCW_TTC0_BASEADDR {0xE0104000} \ + CONFIG.PCW_TTC0_CLK0_PERIPHERAL_CLKSRC {CPU_1X} \ + CONFIG.PCW_TTC0_CLK0_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_TTC0_CLK0_PERIPHERAL_FREQMHZ {133.333333} \ + CONFIG.PCW_TTC0_CLK1_PERIPHERAL_CLKSRC {CPU_1X} \ + CONFIG.PCW_TTC0_CLK1_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_TTC0_CLK1_PERIPHERAL_FREQMHZ {133.333333} \ + CONFIG.PCW_TTC0_CLK2_PERIPHERAL_CLKSRC {CPU_1X} \ + CONFIG.PCW_TTC0_CLK2_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_TTC0_CLK2_PERIPHERAL_FREQMHZ {133.333333} \ + CONFIG.PCW_TTC0_HIGHADDR {0xE0104fff} \ + CONFIG.PCW_TTC0_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_TTC0_TTC0_IO {} \ + CONFIG.PCW_TTC_PERIPHERAL_FREQMHZ {50} \ + CONFIG.PCW_UART0_BASEADDR {0xE0000000} \ + CONFIG.PCW_UART0_BAUD_RATE {115200} \ + CONFIG.PCW_UART0_GRP_FULL_ENABLE {0} \ + CONFIG.PCW_UART0_GRP_FULL_IO {} \ + CONFIG.PCW_UART1_HIGHADDR {0xE0001FFF} \ + CONFIG.PCW_UART1_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_UART1_UART1_IO {} \ + CONFIG.PCW_USB1_USB1_IO {} \ + ] $processing_system7_0 + + # Create instance: ps7_0_axi_periph, and set properties + set ps7_0_axi_periph [ create_bd_cell -type ip -vlnv xilinx.com:ip:axi_interconnect:2.1 ps7_0_axi_periph ] + set_property -dict [ list \ + CONFIG.NUM_MI {2} \ + ] $ps7_0_axi_periph + + # Create instance: pynqrouter_0, and set properties + set pynqrouter_0 [ create_bd_cell -type ip -vlnv xilinx.com:hls:pynqrouter:1.0 pynqrouter_0 ] + + # Create instance: rst_ps7_0_100M, and set properties + set rst_ps7_0_100M [ create_bd_cell -type ip -vlnv xilinx.com:ip:proc_sys_reset:5.0 rst_ps7_0_100M ] + + # Create interface connections + connect_bd_intf_net -intf_net processing_system7_0_DDR [get_bd_intf_ports DDR] [get_bd_intf_pins processing_system7_0/DDR] + connect_bd_intf_net -intf_net processing_system7_0_FIXED_IO [get_bd_intf_ports FIXED_IO] [get_bd_intf_pins processing_system7_0/FIXED_IO] + connect_bd_intf_net -intf_net processing_system7_0_M_AXI_GP0 [get_bd_intf_pins processing_system7_0/M_AXI_GP0] [get_bd_intf_pins ps7_0_axi_periph/S00_AXI] + connect_bd_intf_net -intf_net ps7_0_axi_periph_M00_AXI [get_bd_intf_pins ps7_0_axi_periph/M00_AXI] [get_bd_intf_pins pynqrouter_0/s_axi_AXI4LS] + connect_bd_intf_net -intf_net ps7_0_axi_periph_M01_AXI [get_bd_intf_pins axi_gpio_0/S_AXI] [get_bd_intf_pins ps7_0_axi_periph/M01_AXI] + + # Create port connections + connect_bd_net -net axi_gpio_0_gpio_io_o [get_bd_ports LD] [get_bd_pins axi_gpio_0/gpio_io_o] + connect_bd_net -net processing_system7_0_FCLK_CLK0 [get_bd_pins axi_gpio_0/s_axi_aclk] [get_bd_pins processing_system7_0/FCLK_CLK0] [get_bd_pins processing_system7_0/M_AXI_GP0_ACLK] [get_bd_pins ps7_0_axi_periph/ACLK] [get_bd_pins ps7_0_axi_periph/M00_ACLK] [get_bd_pins ps7_0_axi_periph/M01_ACLK] [get_bd_pins ps7_0_axi_periph/S00_ACLK] [get_bd_pins pynqrouter_0/ap_clk] [get_bd_pins rst_ps7_0_100M/slowest_sync_clk] + connect_bd_net -net processing_system7_0_FCLK_RESET0_N [get_bd_pins processing_system7_0/FCLK_RESET0_N] [get_bd_pins rst_ps7_0_100M/ext_reset_in] + connect_bd_net -net rst_ps7_0_100M_interconnect_aresetn [get_bd_pins ps7_0_axi_periph/ARESETN] [get_bd_pins rst_ps7_0_100M/interconnect_aresetn] + connect_bd_net -net rst_ps7_0_100M_peripheral_aresetn [get_bd_pins axi_gpio_0/s_axi_aresetn] [get_bd_pins ps7_0_axi_periph/M00_ARESETN] [get_bd_pins ps7_0_axi_periph/M01_ARESETN] [get_bd_pins ps7_0_axi_periph/S00_ARESETN] [get_bd_pins pynqrouter_0/ap_rst_n] [get_bd_pins rst_ps7_0_100M/peripheral_aresetn] + + # Create address segments + create_bd_addr_seg -range 0x00010000 -offset 0x41200000 [get_bd_addr_spaces processing_system7_0/Data] [get_bd_addr_segs axi_gpio_0/S_AXI/Reg] SEG_axi_gpio_0_Reg + create_bd_addr_seg -range 0x00040000 -offset 0x43C00000 [get_bd_addr_spaces processing_system7_0/Data] [get_bd_addr_segs pynqrouter_0/s_axi_AXI4LS/Reg] SEG_pynqrouter_0_Reg + + + # Restore current instance + current_bd_instance $oldCurInst + + save_bd_design +} +# End of create_root_design() + + +################################################################## +# MAIN FLOW +################################################################## + +create_root_design "" + + -- 2.22.0 From 271f4008576bf56178661069695034e5fdd6f801 Mon Sep 17 00:00:00 2001 From: Kazushi Kawamura Date: Sat, 25 Aug 2018 20:12:39 +0900 Subject: [PATCH 18/30] Move files --- .../bitstream/router_design.bit | Bin .../bitstream/router_design.tcl | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename hls_2018/{router_01 => router_03}/bitstream/router_design.bit (100%) rename hls_2018/{router_01 => router_03}/bitstream/router_design.tcl (100%) diff --git a/hls_2018/router_01/bitstream/router_design.bit b/hls_2018/router_03/bitstream/router_design.bit similarity index 100% rename from hls_2018/router_01/bitstream/router_design.bit rename to hls_2018/router_03/bitstream/router_design.bit diff --git a/hls_2018/router_01/bitstream/router_design.tcl b/hls_2018/router_03/bitstream/router_design.tcl similarity index 100% rename from hls_2018/router_01/bitstream/router_design.tcl rename to hls_2018/router_03/bitstream/router_design.tcl -- 2.22.0 From 0930680cb96213cbe195d8f5a11516d80f80e88d Mon Sep 17 00:00:00 2001 From: KazushiKawamura Date: Sun, 26 Aug 2018 00:01:12 +0900 Subject: [PATCH 19/30] Address boardstr issue --- hls_2018/router_03_boardstr/Makefile | 20 + hls_2018/router_03_boardstr/Makefile.cygwin | 14 + hls_2018/router_03_boardstr/ap_int.h | 521 ++ .../router_03_boardstr/etc/ap_fixed_sim.h | 2451 +++++++ hls_2018/router_03_boardstr/etc/ap_int_sim.h | 1629 +++++ hls_2018/router_03_boardstr/etc/ap_private.h | 5858 +++++++++++++++++ hls_2018/router_03_boardstr/main.cpp | 99 + hls_2018/router_03_boardstr/router.cpp | 518 ++ hls_2018/router_03_boardstr/router.hpp | 56 + 9 files changed, 11166 insertions(+) create mode 100755 hls_2018/router_03_boardstr/Makefile create mode 100755 hls_2018/router_03_boardstr/Makefile.cygwin create mode 100755 hls_2018/router_03_boardstr/ap_int.h create mode 100755 hls_2018/router_03_boardstr/etc/ap_fixed_sim.h create mode 100755 hls_2018/router_03_boardstr/etc/ap_int_sim.h create mode 100755 hls_2018/router_03_boardstr/etc/ap_private.h create mode 100755 hls_2018/router_03_boardstr/main.cpp create mode 100755 hls_2018/router_03_boardstr/router.cpp create mode 100755 hls_2018/router_03_boardstr/router.hpp diff --git a/hls_2018/router_03_boardstr/Makefile b/hls_2018/router_03_boardstr/Makefile new file mode 100755 index 0000000..8f79e7a --- /dev/null +++ b/hls_2018/router_03_boardstr/Makefile @@ -0,0 +1,20 @@ +TARGET = sim +OBJS = $(CPPS:.cpp=.o) +CPPS = $(wildcard *.cpp) +CXX = g++ +CXXFLAGS = -O3 -Wall -Wno-unknown-pragmas -Wno-unused-label -DSOFTWARE -DCALCTIME + +all: $(TARGET) + +$(TARGET): $(OBJS) + $(CXX) -O3 -o $@ $(OBJS) + +run: + python3 ../NLGenerator.py -x 20 -y 20 -z 6 -l 100;\ + python3 ./gen_boardstr.py Q-20x20x5_100_10.txt |\ + ./$(TARGET) - + + +clean: + rm *.o + rm $(TARGET) diff --git a/hls_2018/router_03_boardstr/Makefile.cygwin b/hls_2018/router_03_boardstr/Makefile.cygwin new file mode 100755 index 0000000..866fdcd --- /dev/null +++ b/hls_2018/router_03_boardstr/Makefile.cygwin @@ -0,0 +1,14 @@ +TARGET = sim +OBJS = $(CPPS:.cpp=.o) +CPPS = $(wildcard *.cpp) +CXX = g++ +CXXFLAGS = -O3 -Wall -Wno-unknown-pragmas -Wno-unused-label -DSOFTWARE -DCALCTIME + +all: $(TARGET) + +$(TARGET): $(OBJS) + $(CXX) -O3 -Wl,--stack,33554432 -o $@ $(OBJS) + +clean: + rm *.o + rm $(TARGET) diff --git a/hls_2018/router_03_boardstr/ap_int.h b/hls_2018/router_03_boardstr/ap_int.h new file mode 100755 index 0000000..b8d9fdc --- /dev/null +++ b/hls_2018/router_03_boardstr/ap_int.h @@ -0,0 +1,521 @@ +/* + * Copyright 2012 Xilinx, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __AESL_AP_SIM_H__ +#define __AESL_AP_SIM_H__ + +#ifndef __cplusplus +#error C++ is required to include this header file +#else + +#include "etc/ap_int_sim.h" +#include "etc/ap_fixed_sim.h" + +//Forward declaration +template class ap_fixed; +template class ap_ufixed; +template class ap_int; +template class ap_uint; + +//AP_INT +//-------------------------------------------------------- +template +class ap_int : public ap_private<_AP_W, true> { +#ifdef _MSC_VER +#pragma warning(disable: 4521 4522) +#endif /* #ifdef _MSC_VER */ +public: + typedef ap_private<_AP_W, true> Base; + + //Constructor + INLINE ap_int(): Base() {} + template + INLINE ap_int(const volatile ap_int<_AP_W2> &op):Base((const ap_private<_AP_W2,true> &)(op)) {} + + template + INLINE ap_int(const ap_int<_AP_W2> &op):Base((const ap_private<_AP_W2,true> &)(op)) {} + + template + INLINE ap_int(const ap_uint<_AP_W2> &op):Base((const ap_private<_AP_W2,false> &)(op)) {} + + template + INLINE ap_int(const volatile ap_uint<_AP_W2> &op):Base((const ap_private<_AP_W2,false> &)(op)) {} + + template + INLINE ap_int(const ap_range_ref<_AP_W2, _AP_S2>& ref):Base(ref) {} + + template + INLINE ap_int(const ap_bit_ref<_AP_W2, _AP_S2>& ref):Base(ref) {} + + template + INLINE ap_int(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& ref):Base(ref) {} + + template + INLINE ap_int(const ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op.to_ap_private()) {} + + template + INLINE ap_int(const ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op.to_ap_private()) {} + + template + INLINE ap_int(const volatile ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op.to_ap_private()) {} + + template + INLINE ap_int(const volatile ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op.to_ap_private()) {} + + template + INLINE ap_int(const ap_private<_AP_W2, _AP_S2>& op):Base(op) {} + + template + INLINE ap_int(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, + _AP_N2>& op):Base(op) {} + + template + INLINE ap_int(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, + _AP_N2>& op):Base(op) {} + + template + INLINE ap_int(const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& op):Base(op.to_ap_private()) {} + +#define CTOR(TYPE) \ + INLINE ap_int(TYPE v):Base(v) {} + CTOR(bool) + CTOR(signed char) + CTOR(unsigned char) + CTOR(short) + CTOR(unsigned short) + CTOR(int) + CTOR(unsigned int) + CTOR(long) + CTOR(unsigned long) + CTOR(unsigned long long) + CTOR(long long) + CTOR(float) + CTOR(double) + CTOR(const char*) + CTOR(const std::string&) +#undef CTOR + INLINE ap_int(const char* str, signed char rd):Base(str, rd) {} + //Assignment + //Another form of "write" + INLINE void operator = (const ap_int<_AP_W>& op2) volatile { + const_cast(this)->operator = (op2); + } + + INLINE void operator = (const volatile ap_int<_AP_W>& op2) volatile { + const_cast(this)->operator = (op2); + } + + INLINE ap_int<_AP_W>& operator = (const volatile ap_int<_AP_W>& op2) { + Base::operator = (const_cast& >(op2)); + return *this; + } + + INLINE ap_int<_AP_W>& operator = (const ap_int<_AP_W>& op2) { + Base::operator = ((const ap_private<_AP_W, true>&)op2); + return *this; + } +}; + +//AP_UINT +//--------------------------------------------------------------- +template +class ap_uint: public ap_private<_AP_W, false> { +#ifdef _MSC_VER +#pragma warning( disable : 4521 4522 ) +#endif +public: + typedef ap_private<_AP_W, false> Base; + //Constructor + INLINE ap_uint(): Base() {} + INLINE ap_uint(const ap_uint<_AP_W>& op) :Base(dynamic_cast&>(op)) {} + INLINE ap_uint(const volatile ap_uint<_AP_W>& op):Base(dynamic_cast&>(op)){} + template + INLINE ap_uint(const volatile ap_uint<_AP_W2> &op):Base((const ap_private<_AP_W2, false>&)(op)) {} + + template + INLINE ap_uint(const ap_uint<_AP_W2> &op) : Base((const ap_private<_AP_W2, false>&)(op)){} + + template + INLINE ap_uint(const ap_int<_AP_W2> &op) : Base((const ap_private<_AP_W2, true>&)(op)) {} + + template + INLINE ap_uint(const volatile ap_int<_AP_W2> &op) : Base((const ap_private<_AP_W2, false>&)(op)) {} + + template + INLINE ap_uint(const ap_range_ref<_AP_W2, _AP_S2>& ref):Base(ref) {} + + template + INLINE ap_uint(const ap_bit_ref<_AP_W2, _AP_S2>& ref):Base(ref) {} + + template + INLINE ap_uint(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& ref):Base(ref) {} + + template + INLINE ap_uint(const ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op.to_ap_private()) {} + + template + INLINE ap_uint(const ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op.to_ap_private()) {} + + template + INLINE ap_uint(const volatile ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op.to_ap_private()) {} + + template + INLINE ap_uint(const volatile ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op) {} + + template + INLINE ap_uint(const ap_private<_AP_W2, _AP_S2>& op):Base(op) {} + + template + INLINE ap_uint(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, + _AP_N2>& op):Base(op) {} + + template + INLINE ap_uint(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, + _AP_N2>& op):Base(op) {} + + template + INLINE ap_uint(const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& op):Base(op.to_ap_private()) {} + +#define CTOR(TYPE) \ + INLINE ap_uint(TYPE v):Base(v) {} + CTOR(bool) + CTOR(signed char) + CTOR(unsigned char) + CTOR(short) + CTOR(unsigned short) + CTOR(int) + CTOR(unsigned int) + CTOR(long) + CTOR(unsigned long) + CTOR(unsigned long long) + CTOR(long long) + CTOR(float) + CTOR(double) + CTOR(const char*) + CTOR(const std::string&) +#undef CTOR + INLINE ap_uint(const char* str, signed char rd):Base(str, rd) {} + //Assignment + //Another form of "write" + INLINE void operator = (const ap_uint<_AP_W>& op2) volatile { + Base::operator = (op2); + } + + INLINE void operator = (const volatile ap_uint<_AP_W>& op2) volatile { + Base::operator = (op2); + } + + INLINE ap_uint<_AP_W>& operator = (const volatile ap_uint<_AP_W>& op2) { + Base::operator = (op2); + return *this; + } + + INLINE ap_uint<_AP_W>& operator = (const ap_uint<_AP_W>& op2) { + Base::operator = ((const ap_private<_AP_W, false>&)(op2)); + return *this; + } +}; + +#define ap_bigint ap_int +#define ap_biguint ap_uint + +//AP_FIXED +//--------------------------------------------------------------------- +template +class ap_fixed: public ap_fixed_base<_AP_W, _AP_I, true, _AP_Q, _AP_O, _AP_N> { +#ifdef _MSC_VER +#pragma warning( disable : 4521 4522 ) +#endif +public: + typedef ap_fixed_base<_AP_W, _AP_I, true, _AP_Q, _AP_O, _AP_N> Base; + //Constructor + INLINE ap_fixed():Base() {} + + template + INLINE ap_fixed(const ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, + _AP_N2>& op): Base(op) {} + + template + INLINE ap_fixed(const ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, + _AP_N2>& op): Base(ap_fixed_base<_AP_W2, _AP_I2, + false, _AP_Q2, _AP_O2, _AP_N2>(op)) {} + + template + INLINE ap_fixed(const ap_int<_AP_W2>& op): + Base(ap_private<_AP_W2, true>(op)) {} + + template + INLINE ap_fixed(const ap_uint<_AP_W2>& op):Base(ap_private<_AP_W2, false>(op)) {} + + template + INLINE ap_fixed(const volatile ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, + _AP_N2>& op): Base(ap_fixed_base<_AP_W2, _AP_I2, + true, _AP_Q2, _AP_O2, _AP_N2>(op)) {} + + template + INLINE ap_fixed(const volatile ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, + _AP_N2>& op): Base(ap_fixed_base<_AP_W2, _AP_I2, + false, _AP_Q2, _AP_O2, _AP_N2>(op)) {} + + template + INLINE ap_fixed(const volatile ap_int<_AP_W2>& op): + Base(ap_private<_AP_W2, true>(op)) {} + + template + INLINE ap_fixed(const volatile ap_uint<_AP_W2>& op):Base(op) {} + + template + INLINE ap_fixed(const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& op):Base(op) {} + + template + INLINE ap_fixed(const ap_bit_ref<_AP_W2, _AP_S2>& op): + Base(op) {} + + template + INLINE ap_fixed(const ap_range_ref<_AP_W2, _AP_S2>& op): + Base(op) {} + + template + INLINE ap_fixed(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& op): + Base(op) {} + + template + INLINE ap_fixed(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& op): Base(op) {} + + template + INLINE ap_fixed(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& op): Base(op) {} + + template + INLINE ap_fixed(const ap_private<_AP_W2, _AP_S2>& op):Base(op) {} + + #define CTOR(TYPE) \ + INLINE ap_fixed(TYPE v):Base(v) {} + CTOR(bool) + CTOR(signed char) + CTOR(unsigned char) + CTOR(short) + CTOR(unsigned short) + CTOR(int) + CTOR(unsigned int) + CTOR(long) + CTOR(unsigned long) + CTOR(unsigned long long) + CTOR(long long) + CTOR(float) + CTOR(double) + CTOR(const char*) + CTOR(const std::string&) +#undef CTOR + INLINE ap_fixed(const char* str, signed char rd):Base(str, rd) {} + + //Assignment + INLINE ap_fixed& operator = (const ap_fixed<_AP_W, _AP_I, + _AP_Q, _AP_O, _AP_N>& op) { + Base::operator = (op); + return *this; + } + + INLINE ap_fixed& operator = (const volatile ap_fixed<_AP_W, _AP_I, + _AP_Q, _AP_O, _AP_N>& op) { + Base::operator = (op); + return *this; + } +}; + +//AP_ UFIXED +//--- ---------------------------------------------------------------- +template +class ap_ufixed : public ap_fixed_base<_AP_W, _AP_I, false, _AP_Q, _AP_O, _AP_N> { +#ifdef _MSC_VER +#pragma warning(disable: 4521 4522) +#endif /* #ifdef _MSC_VER */ +public: + typedef ap_fixed_base<_AP_W, _AP_I, false, _AP_Q, _AP_O, _AP_N> Base; + + //Constructor + INLINE ap_ufixed():Base() {} + + template + INLINE ap_ufixed(const ap_fixed<_AP_W2, _AP_I2, _AP_Q2, + _AP_O2, _AP_N2>& op) : Base(ap_fixed_base<_AP_W2, + _AP_I2, true, _AP_Q2, _AP_O2, _AP_N2>(op)) {} + + template + INLINE ap_ufixed(const ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, + _AP_O2, _AP_N2>& op): Base(ap_fixed_base<_AP_W2, _AP_I2, + false, _AP_Q2, _AP_O2, _AP_N2>(op)) {} + + template + INLINE ap_ufixed(const ap_int<_AP_W2>& op): + Base((const ap_private<_AP_W2, true>&)(op)) {} + + template + INLINE ap_ufixed(const ap_uint<_AP_W2>& op): + Base((const ap_private<_AP_W2, false>&)(op)) {} + + template + INLINE ap_ufixed(const volatile ap_fixed<_AP_W2, _AP_I2, _AP_Q2, + _AP_O2, _AP_N2>& op) : Base(ap_fixed_base<_AP_W2, + _AP_I2, true, _AP_Q2, _AP_O2, _AP_N2>(op)) {} + + template + INLINE ap_ufixed(const volatile ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, + _AP_O2, _AP_N2>& op): Base(ap_fixed_base<_AP_W2, _AP_I2, + false, _AP_Q2, _AP_O2, _AP_N2>(op)) {} + + template + INLINE ap_ufixed(const volatile ap_int<_AP_W2>& op): + Base(ap_private<_AP_W2, true>(op)) {} + + template + INLINE ap_ufixed(const volatile ap_uint<_AP_W2>& op): + Base(ap_private<_AP_W2, false>(op)) {} + + template + INLINE ap_ufixed(const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2>& op):Base(op) {} + + template + INLINE ap_ufixed(const ap_bit_ref<_AP_W2, _AP_S2>& op): + Base(op) {} + + template + INLINE ap_ufixed(const ap_range_ref<_AP_W2, _AP_S2>& op): + Base(op) {} + + template + INLINE ap_ufixed(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& op): + Base(op) {} + + template + INLINE ap_ufixed(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& op): Base(op) {} + + template + INLINE ap_ufixed(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& op): Base(op) {} + + template + INLINE ap_ufixed(const ap_private<_AP_W2, _AP_S2>& op):Base(op) {} + + #define CTOR(TYPE) \ + INLINE ap_ufixed(TYPE v):Base(v) {} + CTOR(bool) + CTOR(signed char) + CTOR(unsigned char) + CTOR(short) + CTOR(unsigned short) + CTOR(int) + CTOR(unsigned int) + CTOR(long) + CTOR(unsigned long) + CTOR(unsigned long long) + CTOR(long long) + CTOR(float) + CTOR(double) + CTOR(const char*) + CTOR(const std::string&) +#undef CTOR + INLINE ap_ufixed(const char* str, signed char rd):Base(str, rd) {} + + //Assignment + INLINE ap_ufixed& operator = (const ap_ufixed<_AP_W, _AP_I, + _AP_Q, _AP_O, _AP_N>& op) { + Base::operator = (op); + return *this; + } + + INLINE ap_ufixed& operator = (const volatile ap_ufixed<_AP_W, _AP_I, + _AP_Q, _AP_O, _AP_N>& op) { + Base::V = const_cast(op); + return *this; + } +}; + +#if defined(SYSTEMC_H) || defined(SYSTEMC_INCLUDED) +template +INLINE void sc_trace(sc_core::sc_trace_file *tf, const ap_int<_AP_W> &op, + const std::string &name) { + if (tf) + tf->trace(sc_dt::sc_lv<_AP_W>(op.to_string(2).c_str()), name); +} + +template +INLINE void sc_trace(sc_core::sc_trace_file *tf, const ap_uint<_AP_W> &op, + const std::string &name) { + if (tf) + tf->trace(sc_dt::sc_lv<_AP_W>(op.to_string(2).c_str()), name); +} + +template +INLINE void sc_trace(sc_core::sc_trace_file *tf, const ap_fixed<_AP_W, _AP_I, _AP_Q, _AP_O, _AP_N >&op, const std::string &name) { + tf->trace(sc_dt::sc_lv<_AP_W>(op.to_string(2).c_str()), name); +} + +template +INLINE void sc_trace(sc_core::sc_trace_file *tf, const ap_ufixed<_AP_W, _AP_I, _AP_Q, _AP_O, _AP_N >&op, const std::string &name) { + tf->trace(sc_dt::sc_lv<_AP_W>(op.to_string(2).c_str()), name); +} +#endif /* #if defined(SYSTEMC_H) || defined(SYSTEMC_INCLUDED) */ +#endif /* #ifndef __cplusplus */ +#endif /* #ifndef __AESL_AP_SIM_H__ */ \ No newline at end of file diff --git a/hls_2018/router_03_boardstr/etc/ap_fixed_sim.h b/hls_2018/router_03_boardstr/etc/ap_fixed_sim.h new file mode 100755 index 0000000..5be571d --- /dev/null +++ b/hls_2018/router_03_boardstr/etc/ap_fixed_sim.h @@ -0,0 +1,2451 @@ +/* + * Copyright 2012 Xilinx, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __AESL_GCC_AP_FIXED_H__ +#define __AESL_GCC_AP_FIXED_H__ + +#ifndef __cplusplus + #error C++ is required to include this header file +#endif /* #ifndef __cplusplus */ + + +#include +#ifndef __AESL_APDT_IN_SCFLOW__ + #include "etc/ap_int_sim.h" +#else + #include "../etc/ap_private.h" +#endif /* #ifndef __AESL_APDT_IN_SCFLOW__ */ + +#define FLOAT_MAN 23 +#define FLOAT_EXP 8 +#define DOUBLE_MAN 52 +#define DOUBLE_EXP 11 +// #define DOUBLE_MAN_MASK (~0ULL >> (64-DOUBLE_MAN-2)) +#define DOUBLE_MAN_MASK 0x3fffffffffffffULL +#define BIAS(e) ((1ULL<<(e-1))-1) +#define FLOAT_BIAS BIAS(FLOAT_EXP) +#define DOUBLE_BIAS BIAS(DOUBLE_EXP) + +/// Forward declaration. +template struct ap_fixed_base; + +///Proxy class, which allows bit selection to be used as both rvalue(for reading) and +//lvalue(for writing) +template +struct af_bit_ref { +#ifdef _MSC_VER + #pragma warning(disable: 4521 4522) +#endif /* #ifdef _MSC_VER */ + ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& d_bv; + int d_index; +public: + INLINE af_bit_ref(const af_bit_ref<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& ref): + d_bv(ref.d_bv), d_index(ref.d_index) {} + + INLINE af_bit_ref(ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>* bv, int index=0): + d_bv(*bv),d_index(index) {} + + INLINE operator bool() const { + return d_bv.V[d_index]; + } + + INLINE af_bit_ref& operator=(unsigned long long val) { + if (val) + d_bv.V.set(d_index); + else + d_bv.V.clear(d_index); + return *this; + } + + template + INLINE af_bit_ref& operator =(const ap_private<_AP_W2,_AP_S2>& val) { + return operator=(val!=0); + } + + INLINE af_bit_ref& operator =(const af_bit_ref<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& val) { + return operator=((unsigned long long)(bool)val); + } + + template + INLINE af_bit_ref operator=(const af_bit_ref<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& val) { + return operator=((unsigned long long)(bool)val); + } + + template + INLINE af_bit_ref& operator = ( const ap_bit_ref<_AP_W2, _AP_S2> &val) { + return operator =((unsigned long long) (bool) val); + } + + template + INLINE af_bit_ref& operator = ( const ap_range_ref<_AP_W2,_AP_S2>& val) { + return operator =((const ap_private<_AP_W2, false>) val); + } + + template + INLINE af_bit_ref& operator= (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& val) { + return operator=((const ap_private<_AP_W2, false>)(val)); + } + + template + INLINE af_bit_ref& operator= (const ap_concat_ref<_AP_W2, _AP_T3, _AP_W3, _AP_T3>& val) { + return operator=((const ap_private<_AP_W2 + _AP_W3, false>)(val)); + } + + template + INLINE ap_concat_ref<1, af_bit_ref, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (ap_private<_AP_W2, _AP_S2>& op) { + return ap_concat_ref<1, af_bit_ref, _AP_W2, + ap_private<_AP_W2, _AP_S2> >(*this, op); + } + + template + INLINE ap_concat_ref<1, af_bit_ref, 1, ap_bit_ref<_AP_W2, _AP_S2> > + operator, (const ap_bit_ref<_AP_W2, _AP_S2> &op) { + return ap_concat_ref<1, af_bit_ref, 1, + ap_bit_ref<_AP_W2, _AP_S2> >(*this, + const_cast& >(op)); + } + + template + INLINE ap_concat_ref<1, af_bit_ref, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > + operator, (const ap_range_ref<_AP_W2, _AP_S2> &op) { + return ap_concat_ref<1, af_bit_ref, _AP_W2, + ap_range_ref<_AP_W2, _AP_S2> >(*this, + const_cast& >(op)); + } + + template + INLINE ap_concat_ref<1, af_bit_ref, _AP_W2 + _AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > + operator, (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &op) { + return ap_concat_ref<1, af_bit_ref, _AP_W2 + _AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(*this, + const_cast& >(op)); + } + + template + INLINE ap_concat_ref<1, af_bit_ref, _AP_W2, + af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &op) { + return ap_concat_ref<1, af_bit_ref, _AP_W2, + af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, + _AP_N2> >(*this, const_cast& >(op)); + } + + template + INLINE ap_concat_ref<1, af_bit_ref, 1, + af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &op) { + return ap_concat_ref<1, af_bit_ref, 1, + af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, + const_cast& >(op)); + } + + template + INLINE bool operator == (const af_bit_ref<_AP_W2, _AP_I2, + _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) { + return get() == op.get(); + } + + template + INLINE bool operator != (const af_bit_ref<_AP_W2, _AP_I2, + _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) { + return get() != op.get(); + } + + INLINE bool operator ~ () const { + bool bit = (d_bv.V)[d_index]; + return bit ? false : true; + } + + INLINE int length() const { + return 1; + } + + INLINE bool get() { + return d_bv.V[d_index]; + } + + INLINE bool get() const { + return d_bv.V[d_index]; + } + + INLINE std::string to_string() const { + return d_bv.V[d_index] ? "1" : "0"; + } +}; + +///Range(slice) reference +//------------------------------------------------------------ +template +struct af_range_ref { +#ifdef _MSC_VER + #pragma warning(disable: 4521 4522) +#endif /* #ifdef _MSC_VER */ + ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &d_bv; + int l_index; + int h_index; + +public: + INLINE af_range_ref(const af_range_ref<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& ref): + d_bv(ref.d_bv), l_index(ref.l_index), h_index(ref.h_index) {} + + INLINE af_range_ref(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>* bv, int h, int l): + d_bv(*bv),l_index(l),h_index(h) { + //if (h < l) + // fprintf(stderr, + //"Warning! The bits selected will be returned in reverse order\n"); + } + + INLINE operator ap_private<_AP_W, false> () const { + if (h_index >= l_index) { + ap_private<_AP_W, false> val(d_bv.V); + ap_private<_AP_W,false> mask(-1); + mask>>=_AP_W-(h_index-l_index+1); + val>>=l_index; + return val&=mask; + } else { + ap_private<_AP_W, false> val = 0; + for (int i=0, j=l_index;j>=0&&j>=h_index;j--,i++) + if ((d_bv.V)[j]) val.set(i); + return val; + } + } + + INLINE operator unsigned long long() const { + return get().to_uint64(); + } + + template + INLINE af_range_ref& operator =(const ap_private<_AP_W2,_AP_S2>& val) { + ap_private<_AP_W, false> vval= ap_private<_AP_W, false>(val); + if (l_index > h_index) { + for (int i=0, j=l_index;j>=0&&j>=h_index;j--,i++) + vval[i]? d_bv.V.set(j):d_bv.V.clear(j); + } else { + ap_private<_AP_W,false> mask(-1); + if (l_index>0) { + mask<<=l_index; + vval<<=l_index; + } + if (h_index<_AP_W-1) { + ap_private<_AP_W,false> mask2(-1); + mask2>>=_AP_W-h_index-1; + mask&=mask2; + vval&=mask2; + } + mask.flip(); + d_bv.V &= mask; + d_bv.V |= vval; + } + return *this; + } + + INLINE af_range_ref& operator = (unsigned long long val) { + const ap_private<_AP_W, false> tmpVal(val); + return operator = (tmpVal); + } + + template + INLINE af_range_ref& operator = + (const ap_concat_ref <_AP_W3, _AP_T3, _AP_W4, _AP_T4>& val) { + const ap_private<_AP_W, false> tmpVal(val); + return operator = (tmpVal); + } + + template + INLINE af_range_ref& operator =(const ap_bit_ref<_AP_W3, _AP_S3>& val) { + const ap_private<_AP_W, false> tmpVal(val); + return operator = (tmpVal); + } + + template + INLINE af_range_ref& operator =(const ap_range_ref<_AP_W3,_AP_S3>& val) { + const ap_private<_AP_W, false> tmpVal(val); + return operator =(tmpVal); + } + + template + INLINE af_range_ref& operator= (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& val) { + const ap_private<_AP_W2, false> tmp= val.get(); + return operator = (tmp); + } + + INLINE af_range_ref& operator= (const af_range_ref<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& val) { + const ap_private<_AP_W, false> tmp= val.get(); + return operator = (tmp); + } + + template + INLINE af_range_ref& operator= (const ap_fixed_base<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& val) { + return operator=(val.to_ap_private()); + } + + template + INLINE bool operator == (const ap_range_ref<_AP_W2, _AP_S2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs==rhs; + } + + template + INLINE bool operator != (const ap_range_ref<_AP_W2, _AP_S2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs!=rhs; + } + + template + INLINE bool operator > (const ap_range_ref<_AP_W2, _AP_S2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs>rhs; + } + + template + INLINE bool operator >= (const ap_range_ref<_AP_W2, _AP_S2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs>=rhs; + } + + template + INLINE bool operator < (const ap_range_ref<_AP_W2, _AP_S2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs + INLINE bool operator <= (const ap_range_ref<_AP_W2, _AP_S2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs<=rhs; + } + + template + INLINE bool operator == (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs==rhs; + } + + template + INLINE bool operator != (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs!=rhs; + } + + template + INLINE bool operator > (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs>rhs; + } + + template + INLINE bool operator >= (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs>=rhs; + } + + template + INLINE bool operator < (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs + INLINE bool operator <= (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs<=rhs; + } + + template + INLINE void set(const ap_private<_AP_W2,false>& val) { + ap_private<_AP_W,_AP_S> vval=val; + if (l_index>h_index) { + for (int i=0, j=l_index;j>=0&&j>=h_index;j--,i++) + vval[i]? d_bv.V.set(j):d_bv.V.clear(j); + } else { + ap_private<_AP_W,_AP_S> mask(-1); + if (l_index>0) { + ap_private<_AP_W,false> mask1(-1); + mask1>>=_AP_W-l_index; + mask1.flip(); + mask=mask1; + //vval&=mask1; + vval<<=l_index; + } + if (h_index<_AP_W-1) { + ap_private<_AP_W,false> mask2(-1); + mask2<<=h_index+1; + mask2.flip(); + mask&=mask2; + vval&=mask2; + } + mask.flip(); + d_bv&=mask; + d_bv|=vval; + } + + } + + INLINE ap_private<_AP_W,false> get() const { + if (h_index val(0); + for (int i=0, j=l_index;j>=0&&j>=h_index;j--,i++) + if ((d_bv.V)[j]) val.set(i); + return val; + } else { + ap_private<_AP_W, false> val = ap_private<_AP_W,false>(d_bv.V); + val>>= l_index; + if (h_index<_AP_W-1) + { + ap_private<_AP_W,false> mask(-1); + mask>>=_AP_W-(h_index-l_index+1); + val&=mask; + } + return val; + } + } + + template + INLINE ap_concat_ref<_AP_W, af_range_ref, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (ap_private<_AP_W2, _AP_S2>& op) { + return ap_concat_ref<_AP_W, af_range_ref, _AP_W2, + ap_private<_AP_W2, _AP_S2> >(*this, op); + } + + template + INLINE ap_concat_ref<_AP_W, af_range_ref, 1, ap_bit_ref<_AP_W2, _AP_S2> > + operator, (const ap_bit_ref<_AP_W2, _AP_S2> &op) { + return ap_concat_ref<_AP_W, af_range_ref, 1, + ap_bit_ref<_AP_W2, _AP_S2> >(*this, + const_cast& >(op)); + } + + template + INLINE ap_concat_ref<_AP_W, af_range_ref, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > + operator, (const ap_range_ref<_AP_W2, _AP_S2> &op) { + return ap_concat_ref<_AP_W, af_range_ref, _AP_W2, + ap_range_ref<_AP_W2, _AP_S2> >(*this, + const_cast& >(op)); + } + + template + INLINE ap_concat_ref<_AP_W, af_range_ref, _AP_W2 + _AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > + operator, (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &op) { + return ap_concat_ref<_AP_W, af_range_ref, _AP_W2 + _AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(*this, + const_cast& >(op)); + } + + template + INLINE ap_concat_ref<_AP_W, af_range_ref, _AP_W2, + af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &op) { + return ap_concat_ref<_AP_W, af_range_ref, _AP_W2, + af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, + const_cast& > (op)); + } + + template + INLINE ap_concat_ref<_AP_W, af_range_ref, 1, + af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &op) { + return ap_concat_ref<_AP_W, af_range_ref, 1, + af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, + const_cast& >(op)); + } + + INLINE int length() const { + return h_index>=l_index?h_index-l_index+1:l_index-h_index+1; + } + + INLINE int to_int() const { + ap_private<_AP_W,false> val=get(); + return val.to_int(); + } + + INLINE unsigned int to_uint() const { + ap_private<_AP_W,false> val=get(); + return val.to_uint(); + } + + INLINE long to_long() const { + ap_private<_AP_W,false> val=get(); + return val.to_long(); + } + + INLINE unsigned long to_ulong() const { + ap_private<_AP_W,false> val=get(); + return val.to_ulong(); + } + + INLINE ap_slong to_int64() const { + ap_private<_AP_W,false> val=get(); + return val.to_int64(); + } + + INLINE ap_ulong to_uint64() const { + ap_private<_AP_W,false> val=get(); + return val.to_uint64(); + } + + INLINE std::string to_string(uint8_t radix) const { + return get().to_string(radix); + } + +}; + +//----------------------------------------------------------------------------- +///ap_fixed_base: AutoPilot fixed point +//----------------------------------------------------------------------------- +template +struct ap_fixed_base { +#ifdef _MSC_VER + #pragma warning(disable: 4521 4522) +#endif /* #ifdef _MSC_VER */ +public: + template friend struct +ap_fixed_base; + template friend struct +af_bit_ref; + + INLINE void overflow_adjust(bool underflow, bool overflow, + bool lD, bool sign) { + if (!overflow && !underflow) return; + switch (_AP_O) { + case AP_WRAP: + if (_AP_N == 0) + return; + if (_AP_S) { + //signed SC_WRAP + //n_bits == 1; + if (_AP_N > 1) { + ap_private<_AP_W, _AP_S> mask(-1); + if (_AP_N >= _AP_W) mask = 0; + else mask.lshr(_AP_N); + if (sign) + V &= mask; + else + V |= ~mask; + } + sign ? V.set(_AP_W - 1) : V.clear(_AP_W - 1); + } else { + //unsigned SC_WRAP + ap_private<_AP_W, _AP_S> mask(-1); + if (_AP_N >= _AP_W) mask = 0; + else mask.lshr(_AP_N); + mask.flip(); + V |= mask; + } + break; + case AP_SAT_ZERO: + V.clear(); + break; + case AP_WRAP_SM: + { + bool Ro = ap_private_ops::get<_AP_W, _AP_S, _AP_W -1>(V); // V[_AP_W -1]; + if (_AP_N == 0) { + if (lD != Ro) { + V.flip(); + lD ? ap_private_ops::set<_AP_W, _AP_S, _AP_W - 1>(V) : + ap_private_ops::clear<_AP_W, _AP_S, _AP_W - 1>(V); + } + } else { + if (_AP_N == 1 && sign != Ro) { + V.flip(); + } else if (_AP_N > 1) { + bool lNo = ap_private_ops::get<_AP_W, _AP_S, _AP_W - _AP_N> (V); // V[_AP_W - _AP_N]; + if (lNo == sign) + V.flip(); + ap_private<_AP_W, false> mask(-1); + if (_AP_N >= _AP_W) mask = 0; + else mask.lshr(_AP_N); + if (sign) + V &= mask; + else + V |= mask.flip(); + sign ? ap_private_ops::set<_AP_W, _AP_S, _AP_W - 1>(V) : ap_private_ops::clear<_AP_W, _AP_S, _AP_W - 1>(V); + } + } + } + break; + default: + if (_AP_S) { + if (overflow) { + V.set(); ap_private_ops::clear<_AP_W, _AP_S, _AP_W-1>(V); + } else if (underflow) { + V.clear(); + ap_private_ops::set<_AP_W, _AP_S, _AP_W-1>(V); + if (_AP_O == AP_SAT_SYM) + ap_private_ops::set<_AP_W, _AP_S, 0>(V); + } + } else { + if (overflow) + V.set(); + else if (underflow) + V.clear(); + } + } + } + + INLINE bool quantization_adjust(bool qb, bool r, bool s) { + bool carry=ap_private_ops::get<_AP_W, _AP_S, _AP_W-1>(V); + switch (_AP_Q) { + case AP_TRN: + return false; + case AP_RND_ZERO: + qb &= s || r; + break; + case AP_RND_MIN_INF: + qb &= r; + break; + case AP_RND_INF: + qb &= !s || r; + break; + case AP_RND_CONV: + qb &= ap_private_ops::get<_AP_W, _AP_S, 0>(V) || r; + break; + case AP_TRN_ZERO: + qb = s && ( qb || r ); + break; + default:; + + } + if (qb) ++V; + //only when old V[_AP_W-1]==1 && new V[_AP_W-1]==0 + return carry && !(ap_private_ops::get<_AP_W, _AP_S, _AP_W-1>(V)); //(!V[_AP_W-1]); + } + + template + struct RType { + enum { + _AP_F=_AP_W-_AP_I, + F2=_AP_W2-_AP_I2, + mult_w = _AP_W+_AP_W2, + mult_i = _AP_I+_AP_I2, + mult_s = _AP_S||_AP_S2, + plus_w = AP_MAX(_AP_I+(_AP_S2&&!_AP_S),_AP_I2+(_AP_S&&!_AP_S2))+1+AP_MAX(_AP_F,F2), + plus_i = AP_MAX(_AP_I+(_AP_S2&&!_AP_S),_AP_I2+(_AP_S&&!_AP_S2))+1, + plus_s = _AP_S||_AP_S2, + minus_w = AP_MAX(_AP_I+(_AP_S2&&!_AP_S),_AP_I2+(_AP_S&&!_AP_S2))+1+AP_MAX(_AP_F,F2), + minus_i = AP_MAX(_AP_I+(_AP_S2&&!_AP_S),_AP_I2+(_AP_S&&!_AP_S2))+1, + minus_s = true, +#ifndef __SC_COMPATIBLE__ + div_w = _AP_W + AP_MAX(_AP_W2 - _AP_I2, 0) + _AP_S2, +#else + div_w = _AP_W + AP_MAX(_AP_W2 - _AP_I2, 0) + _AP_S2 + AP_MAX(_AP_I2, 0), +#endif /* #ifndef __SC_COMPATIBLE__ */ + div_i = _AP_I + (_AP_W2-_AP_I2) + _AP_S2, + div_s = _AP_S||_AP_S2, + logic_w = AP_MAX(_AP_I+(_AP_S2&&!_AP_S),_AP_I2+(_AP_S&&!_AP_S2))+AP_MAX(_AP_F,F2), + logic_i = AP_MAX(_AP_I+(_AP_S2&&!_AP_S),_AP_I2+(_AP_S&&!_AP_S2)), + logic_s = _AP_S||_AP_S2 + }; + + typedef ap_fixed_base mult; + typedef ap_fixed_base plus; + typedef ap_fixed_base minus; + typedef ap_fixed_base logic; + typedef ap_fixed_base div; + typedef ap_fixed_base<_AP_W, _AP_I, _AP_S> arg1; + }; + INLINE void report() { +#if 0 + if (_AP_W > 1024 && _AP_W <= 4096) { + fprintf(stderr, "[W] W=%d is out of bound (1<=W<=1024):" + " for synthesis, please define macro AP_INT_TYPE_EXT(N) to" + " extend the valid range.\n", _AP_W); + } else +#endif /* #if 0 */ + if (_AP_W > MAX_MODE(AP_INT_MAX_W) * 1024) { + fprintf(stderr, "[E] ap_%sfixed<%d, ...>: Bitwidth exceeds the " + "default max value %d. Please use macro " + "AP_INT_MAX_W to set a larger max value.\n", + _AP_S?"":"u", _AP_W, + MAX_MODE(AP_INT_MAX_W) * 1024); + exit(1); + } + } + + /// Constructors. + // ------------------------------------------------------------------------- +#if 0 + #ifdef __SC_COMPATIBLE__ + INLINE ap_fixed_base():V(uint32_t(_AP_W), uint64_t(0)) {} + #else + INLINE ap_fixed_base():V(uint32_t(_AP_W)) {} + #endif /* #ifdef __SC_COMPATIBLE__ */ +#else + INLINE ap_fixed_base():V(0) {} +#endif /* #if 0 */ + // INLINE ap_fixed_base():V() {} + // INLINE explicit ap_fixed_base(const ap_private<_AP_W+_AP_I, _AP_S>& _V):V(_V) {} + INLINE ap_fixed_base(const ap_fixed_base& op):V(op.V) {} + template + INLINE ap_fixed_base(const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op):V(0) { + enum {N2=_AP_W2,_AP_F=_AP_W-_AP_I,F2=_AP_W2-_AP_I2,QUAN_INC=F2>_AP_F && !(_AP_Q==AP_TRN || + (_AP_Q==AP_TRN_ZERO && !_AP_S2))}; + if (!op) return; + bool carry=false; + //handle quantization + enum { sh_amt =(F2>_AP_F)?F2-_AP_F:_AP_F-F2}; + const ap_private<_AP_W2, _AP_S2>& val = op.V; + bool neg_src=val.isNegative(); + if (F2==_AP_F) + V=val; + + else if (F2>_AP_F) { + if (sh_amt >= _AP_W2) + V = neg_src ? -1 : 0; + else + V = _AP_S2?val.ashr(sh_amt):val.lshr(sh_amt); + if (_AP_Q!=AP_TRN && !(_AP_Q==AP_TRN_ZERO && !_AP_S2)) { + bool qb = false; + if (F2-_AP_F>_AP_W2) + qb = neg_src; + else + qb = ap_private_ops::get<_AP_W2, _AP_S2, F2-_AP_F-1>(val); + + bool r=false; + enum { pos3 = F2-_AP_F-2}; + if (pos3>=_AP_W2-1) + r=val!=0; + else if (pos3>=0) + r = (val<<(_AP_W2-1-pos3))!=0; + carry = quantization_adjust(qb,r,neg_src); + } + } else { //no quantization + if (sh_amt < _AP_W) { + V=val; + V <<= sh_amt; + } + } + //hanle overflow/underflow + if ((_AP_O!=AP_WRAP || _AP_N != 0) && + ((!_AP_S && _AP_S2) || _AP_I-_AP_S < + _AP_I2 - _AP_S2 + (QUAN_INC|| (_AP_S2 && + _AP_O==AP_SAT_SYM)))) {//saturation + bool deleted_zeros = _AP_S2?true:!carry, + deleted_ones = true; + bool lD=(_AP_I2>_AP_I && _AP_W2-_AP_I2+_AP_I>=0) && + ap_private_ops::get<_AP_W2, _AP_S2, _AP_W2-_AP_I2+_AP_I>(val); + enum { pos1=F2-_AP_F+_AP_W, pos2=F2-_AP_F+_AP_W+1}; + if (pos1 < _AP_W2) { + bool Range1_all_ones= true; + bool Range1_all_zeros= true; + if (pos1 >= 0) { + enum { __W = (_AP_W2-pos1) > 0 ? (_AP_W2-pos1) : 1 }; + const ap_private<__W, _AP_S2> Range1=ap_private<__W, _AP_S2>(val.lshr(pos1)); + Range1_all_ones=Range1.isAllOnesValue(); + Range1_all_zeros=Range1.isMinValue(); + } else { + Range1_all_ones=false; + Range1_all_zeros=val.isMinValue(); + } + bool Range2_all_ones=true; + if (pos2<_AP_W2 && pos2>=0) { + enum { __W = (_AP_W2-pos2)>0 ? (_AP_W2-pos2) : 1}; + ap_private<__W, true> Range2=ap_private<__W, true>(val.lshr(pos2)); + Range2_all_ones=Range2.isAllOnesValue(); + } else if (pos2<0) + Range2_all_ones=false; + + deleted_zeros=deleted_zeros && (carry?Range1_all_ones:Range1_all_zeros); + deleted_ones=carry?Range2_all_ones&&(F2-_AP_F+_AP_W<0||!lD) + :Range1_all_ones; + neg_src= neg_src&&!(carry && Range1_all_ones); + } else + neg_src = neg_src && V[_AP_W-1]; + + bool neg_trg= V.isNegative(); + bool overflow=(neg_trg||!deleted_zeros) && !val.isNegative(); + bool underflow=(!neg_trg||!deleted_ones)&&neg_src; + //printf("neg_src = %d, neg_trg = %d, deleted_zeros = %d, + // deleted_ones = %d, overflow = %d, underflow = %d\n", + // neg_src, neg_trg, deleted_zeros, deleted_ones, + // overflow, underflow); + if (_AP_O==AP_SAT_SYM && _AP_S2 && _AP_S) + underflow |= neg_src && (_AP_W>1?V.isMinSignedValue():true); + overflow_adjust(underflow, overflow, lD, neg_src); + } + report(); + } + + template + INLINE ap_fixed_base(const volatile ap_fixed_base<_AP_W2,_AP_I2, + _AP_S2,_AP_Q2,_AP_O2, _AP_N2> &op) : V(op.V) { + *this = const_cast&>(op); + } + + template + INLINE ap_fixed_base(const ap_private<_AP_W2,_AP_S2>& op) { + ap_fixed_base<_AP_W2,_AP_W2,_AP_S2> f_op; + f_op.V=op; + *this = f_op; + } + + INLINE ap_fixed_base(bool b) { + *this=(ap_private<1,false>)b; + report(); + } + + INLINE ap_fixed_base(char b) { + *this=(ap_private<8,false>)b; + report(); + } + + INLINE ap_fixed_base(signed char b) { + *this=(ap_private<8,true>)b; + report(); + } + + INLINE ap_fixed_base(unsigned char b) { + *this=(ap_private<8,false>)b; + report(); + } + + INLINE ap_fixed_base(signed short b) { + *this=(ap_private<16,true>)b; + report(); + } + + INLINE ap_fixed_base(unsigned short b) { + *this=(ap_private<16,false>)b; + report(); + } + + INLINE ap_fixed_base(signed int b) { + *this=(ap_private<32,true>)b; + report(); + } + + INLINE ap_fixed_base(unsigned int b) { + *this=(ap_private<32,false>)b; + report(); + } +# if defined __x86_64__ + INLINE ap_fixed_base(signed long b) { + *this=(ap_private<64,true>)b; + report(); + } + + INLINE ap_fixed_base(unsigned long b) { + *this=(ap_private<64,false>)b; + report(); + } +# else + INLINE ap_fixed_base(signed long b) { + *this=(ap_private<32,true>)b; + report(); + } + + INLINE ap_fixed_base(unsigned long b) { + *this=(ap_private<32,false>)b; + report(); + } +# endif + + INLINE ap_fixed_base(ap_slong b) { + *this=(ap_private<64,true>)b; + report(); + } + + INLINE ap_fixed_base(ap_ulong b) { + *this=(ap_private<64,false>)b; + report(); + } + +#if 1 + INLINE ap_fixed_base(const char* val):V(0) { + ap_private<_AP_W, _AP_S> Tmp(val); + V = Tmp; + } + + INLINE ap_fixed_base(const char* val, signed char rd): V(0) { + ap_private<_AP_W, _AP_S> Tmp(val, rd); + V = Tmp; + } + +#endif + + INLINE ap_fixed_base(const std::string& val) { + ap_private<_AP_W, _AP_S> Tmp(val, 2); + V = Tmp; + report(); + } + + template + INLINE ap_fixed_base(const ap_bit_ref<_AP_W2, _AP_S2>& op) { + *this = ((bool)op); + report(); + } + + template + INLINE ap_fixed_base(const ap_range_ref<_AP_W2, _AP_S2>& op) { + *this = ap_private<_AP_W2, _AP_S2>(op); + report(); + } + + template + INLINE ap_fixed_base(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& op) { + *this = ((const ap_private<_AP_W2 + _AP_W3, false>&)(op)); + report(); + } + + template + INLINE ap_fixed_base(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) { + *this = (bool(op)); + report(); + } + + template + INLINE ap_fixed_base(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) { + *this = (ap_private<_AP_W2, false>(op)); + report(); + } + + //helper function + INLINE unsigned long long doubleToRawBits(double pf)const { + union { + unsigned long long __L; + double __D; + }LD; + LD.__D=pf; + return LD.__L; + } + + + INLINE double rawBitsToDouble(unsigned long long pi) const { + union { + unsigned long long __L; + double __D; + }LD; + LD.__L=pi; + return LD.__D; + } + + INLINE float rawBitsToFloat(uint32_t pi) const { + union { + uint32_t __L; + float __D; + }LD; + LD.__L = pi; + return LD.__D; + } + + INLINE ap_fixed_base(double d):V(0) { + if (!d) return; + const bool isneg=d<0; + + const uint64_t ireg=doubleToRawBits(isneg?-d:d); + if ((ireg&0x7fffffffffffffffULL)!=0) { + const int32_t exp=(((ireg)>>DOUBLE_MAN)&0x07ff)-DOUBLE_BIAS; + ap_private man = ireg & DOUBLE_MAN_MASK; + man.clear(DOUBLE_MAN+1); + man.set(DOUBLE_MAN); + if (isneg) { + man.flip(); + man++; + } + + enum {_AP_S2=true, _AP_W2=DOUBLE_MAN+2,_AP_F=_AP_W -_AP_I }; + const int _AP_I2=exp+2; + const int F2=_AP_W2-_AP_I2; + const bool QUAN_INC=F2>_AP_F && !(_AP_Q==AP_TRN || (_AP_Q==AP_TRN_ZERO && + !_AP_S2)); + bool carry=false; + //handle quantization + const unsigned sh_amt=abs(F2-_AP_F); // sh_amt = F2>_AP_F ? F2 -_AP_F : _AP_F-F2; + if (F2==_AP_F ) + V=man; + else if (F2>_AP_F) { + if (sh_amt >= DOUBLE_MAN+2) + V=isneg?-1:0; + else + V=(man>>sh_amt) | ((man & 1ULL<<(DOUBLE_MAN+1)) ? (DOUBLE_MAN_MASK>>(DOUBLE_MAN+2-sh_amt) <<(DOUBLE_MAN+2-sh_amt)):0); + + if (_AP_Q!=AP_TRN && !(_AP_Q==AP_TRN_ZERO && !_AP_S2)) { + const bool qb=((F2-_AP_F > DOUBLE_MAN+2) ? isneg : (man & (1ULL<<(F2-_AP_F-1))) != 0); + const int pos3=F2-_AP_F-2; + const bool r = (pos3>= 0) ? (man << AP_MAX(0, _AP_W2-pos3-1)& DOUBLE_MAN_MASK)!=0 : false; + carry = quantization_adjust(qb,r,isneg); + } + } + else { //no quantization + // V=man; + if (sh_amt < _AP_W) { + V = man; + V <<= sh_amt; + } + } + //handle overflow/underflow + if ((_AP_O != AP_WRAP || _AP_N != 0) && + ((!_AP_S && _AP_S2) || _AP_I-_AP_S < + _AP_I2-_AP_S2+(QUAN_INC|| (_AP_S2 && + _AP_O==AP_SAT_SYM)) )) {// saturation + bool deleted_zeros = _AP_S2?true:!carry, + deleted_ones = true; + bool neg_src; + const bool lD=(_AP_I2>_AP_I) && (_AP_W2-_AP_I2+_AP_I>=0) && (man & (1ULL <<(DOUBLE_MAN+2-_AP_I2+_AP_I))); + int pos1=F2+_AP_W-_AP_F; + if (pos1 < _AP_W2) { + int pos2=pos1+1; + bool Range1_all_ones=true; + bool Range1_all_zeros=true; + if (pos1>=0) { + ap_private<_AP_W,_AP_S> Range1= + ap_private<_AP_W,_AP_S>((man >> pos1) | ((1ULL<<(DOUBLE_MAN+1)&man) ? (DOUBLE_MAN_MASK >> (DOUBLE_MAN+2-pos1) <<(DOUBLE_MAN+2-pos1)):0)); + Range1_all_ones = Range1.isAllOnesValue(); // Range1.isAllOnesValue(); + Range1_all_zeros = Range1.isMinValue(); // Range1.isMinValue(); + } else { + Range1_all_ones=false; + Range1_all_zeros = man==0; // man.isMinValue(); + } + bool Range2_all_ones=true; + if (pos2<_AP_W2 && pos2>=0) { + ap_private<_AP_W, _AP_S> Range2= + ap_private<_AP_W, _AP_S>((man >> pos2) | ((1ULL<<(DOUBLE_MAN+1)&man) ? (DOUBLE_MAN_MASK >> (DOUBLE_MAN+2-pos2) <<(DOUBLE_MAN+2-pos2)):0)); + Range2_all_ones=Range2.isAllOnesValue(); // Range2.isAllOnesValue(); + } else if (pos2<0) + Range2_all_ones=false; + deleted_zeros=deleted_zeros && (carry?Range1_all_ones:Range1_all_zeros); + deleted_ones=carry?Range2_all_ones&&(F2-_AP_F+_AP_W<0||!lD) : Range1_all_ones; + neg_src=isneg&&!(carry&Range1_all_ones); + } else + neg_src = isneg && V[_AP_W -1]; + + const bool neg_trg=V.isNegative(); + const bool overflow=(neg_trg||!deleted_zeros) && !isneg; + bool underflow=(!neg_trg||!deleted_ones)&&neg_src; + //printf("neg_src = %d, neg_trg = %d, deleted_zeros = %d, + // deleted_ones = %d, overflow = %d, underflow = %d\n", + // neg_src, neg_trg, deleted_zeros, deleted_ones, + // overflow, underflow); + if (_AP_O==AP_SAT_SYM && _AP_S2 && _AP_S) + underflow |= neg_src && (_AP_W>1?V.isMinSignedValue():true); + overflow_adjust(underflow,overflow,lD, neg_src); + } + } + report(); + } + + + ///assign operators + //------------------------------------------------------------------------- + + INLINE volatile ap_fixed_base& operator=(const ap_fixed_base<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& op) volatile { + V = op.V; + return *this; + } + + INLINE ap_fixed_base& operator=(const ap_fixed_base<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& op) { + V = op.V; + return *this; + } + + INLINE volatile ap_fixed_base& operator=(const volatile ap_fixed_base<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& op) volatile { + V = op.V; + return *this; + } + + INLINE ap_fixed_base& operator=(const volatile ap_fixed_base<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& op) { + V = op.V; + return *this; + } + + // Set this ap_fixed_base with a bits string. That means the ssdm_int::V + // inside this ap_fixed_base is assigned by bv. + // Note the input parameter should be a fixed-point formatted bit string. + INLINE ap_fixed_base& setBits(unsigned long long bv) { + V=bv; + return *this; + } + + // Return a ap_fixed_base object whose ssdm_int::V is assigned by bv. + // Note the input parameter should be a fixed-point formatted bit string. + static INLINE ap_fixed_base bitsToFixed(unsigned long long bv) { + ap_fixed_base Tmp=bv; + return Tmp; + } + + // Explicit conversion functions to ap_private that captures + // all integer bits (bits are truncated) + INLINE ap_private + to_ap_private(bool Cnative = true) const { + ap_private ret = ap_private ((_AP_I >= 1) ? (_AP_S==true ? V.ashr(AP_MAX(0,_AP_W - _AP_I)) : V.lshr(AP_MAX(0,_AP_W - _AP_I))) : ap_private<_AP_W, _AP_S>(0)); + + if (Cnative) { + bool r = false; + if (_AP_I < _AP_W) { + if (_AP_I > 0) r = !(V.getLoBits(_AP_W - _AP_I).isMinValue()); + else r = !(V.isMinValue()); + } + if (r && V.isNegative()) { // if this is negative integer + ++ret;//ap_private(1,_AP_S); + } + } else { + //Follow OSCI library, conversion from sc_fixed to sc_int + } + return ret; + } + + template + INLINE operator ap_private<_AP_W2,_AP_S2> () const { + return (ap_private<_AP_W2,_AP_S2>)to_ap_private(); + } + + template + INLINE operator ap_private<_AP_W2,_AP_S2,_AP_N2> () const { + return (ap_private<_AP_W2,_AP_S2,_AP_N2>)to_ap_private(); + } + + //Explict conversion function to C built-in integral type + INLINE int to_int() const { + return to_ap_private().to_int(); + } + + INLINE int to_uint() const { + return to_ap_private().to_uint(); + } + + INLINE ap_slong to_int64() const { + return to_ap_private().to_int64(); + } + + INLINE ap_ulong to_uint64() const { + return to_ap_private().to_uint64(); + } + + INLINE double to_double() const { + if (!V) + return 0; + if (_AP_W>64 || (_AP_W - _AP_I) > 0) { + bool isneg = _AP_S && V[_AP_W-1]; + uint64_t res = isneg ? 0x8000000000000000ULL : 0; + ap_private<_AP_W, false> tmp = V; + if (isneg) tmp = -tmp; + int i = _AP_W -1 - tmp.countLeadingZeros(); + int exp = _AP_I-(_AP_W-i); + res|=((uint64_t)(exp+DOUBLE_BIAS))<DOUBLE_MAN)?tmp.lshr(i-DOUBLE_MAN):tmp).to_uint64() & DOUBLE_MAN_MASK; + res |= i 0) { + /* This specialization is disabled. It is giving wrong results in some cases. + bool isneg=V.isNegative(); + double dp = V.get(); + dp /= (1<< (_AP_W - _AP_I)); + return dp;*/ + } else + return double(to_int64()); + } + + INLINE float to_float() const { + uint32_t res=0; + if (V==0) + return 0; + bool isneg=V.isNegative(); + ap_private<_AP_W, _AP_S> tmp=V; + if (isneg) tmp = -tmp; + if (_AP_W-_AP_I>0||_AP_W>64) { + if (isneg) + res=0x80000000; + int i=_AP_W-1; + i-=tmp.countLeadingZeros(); + int exp=_AP_I-(_AP_W-i); + res|=(exp+FLOAT_BIAS)< man = 0; + if (i!=0) { + tmp.clear(i); + if (i>FLOAT_MAN) + man=tmp.lshr(i-FLOAT_MAN); + else + man=tmp; + res |= i < FLOAT_MAN?man.getZExtValue()<<(FLOAT_MAN-i):man.getZExtValue(); + } + } else { + return float(to_int64()); + } + float dp=rawBitsToFloat(res); + return dp; + } + + INLINE operator double () const { + return to_double(); + } +#ifndef __SC_COMPATIBLE__ + INLINE operator float () const { + return to_float(); + } + + INLINE operator char () const { + return (char) to_int(); + } + + INLINE operator unsigned char () const { + return (unsigned char) to_uint(); + } + + INLINE operator short () const { + return (short) to_int(); + } + + INLINE operator unsigned short () const { + return (unsigned short) to_uint(); + } + + INLINE operator int () const { + return to_int(); + } + + INLINE operator unsigned int () const { + return to_uint(); + } +#if 1 +#ifdef __x86_64__ + INLINE operator long () const { + return (long)to_int64(); + } + + INLINE operator unsigned long () const { + return (unsigned long) to_uint64(); + } +#else + INLINE operator long () const { + return to_int64(); + } + + INLINE operator unsigned long () const { + return to_uint64(); + } + +#endif +#endif + INLINE operator unsigned long long () const { + return to_uint64(); + } + + INLINE operator long long () const { + return to_int64(); + } +#endif + + INLINE std::string to_string(uint8_t radix=2, bool sign=false) const; + + INLINE ap_slong bits_to_int64() const { + ap_private res(V); + return (ap_slong) res; + } + + INLINE ap_ulong bits_to_uint64() const { + ap_private res(V); + return (ap_ulong) res; + } + + INLINE int length() const {return _AP_W;} + + // Count the number of zeros from the most significant bit + // to the first one bit. Note this is only for ap_fixed_base whose + // _AP_W <= 64, otherwise will incur assertion. + INLINE int countLeadingZeros() { + return V.countLeadingZeros(); + } + + ///Arithmetic:Binary + //------------------------------------------------------------------------- + template + INLINE typename RType<_AP_W2,_AP_I2,_AP_S2>::mult + operator * (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + typename RType<_AP_W2,_AP_I2,_AP_S2>::mult r; + r.V = V * op2.V; + return r; + } + + template + static INLINE ap_fixed_base multiply(const ap_fixed_base<_AP_W1,_AP_I1,_AP_S1>& op1, const + ap_fixed_base<_AP_W2,_AP_I2,_AP_S2>& op2) { + ap_private<_AP_W+_AP_W2, _AP_S> OP1=op1.V; + ap_private<_AP_W2,_AP_S2> OP2=op2.V; + return OP1*OP2; + } + + template + INLINE typename RType<_AP_W2,_AP_I2,_AP_S2>::div + operator / (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + enum {F2 = _AP_W2-_AP_I2, _W1=AP_MAX(_AP_W + AP_MAX(F2, 0), _AP_W2), + _W2=AP_MAX(_AP_W2,AP_MAX(_AP_W + AP_MAX(F2, 0), _AP_W2))}; + ap_private<_W1, _AP_S> dividend = (ap_private<_W1, _AP_S>(V)) << ((_W1>_AP_W)?F2:0); + ap_private<_W1, _AP_S2> divisior = ap_private<_W2, _AP_S2>(op2.V); + ap_private<_W1, _AP_S> ret = ap_private<_W1,_AP_S> ((_AP_S||_AP_S2) ? dividend.sdiv(divisior): dividend.udiv(divisior)); + typename RType<_AP_W2, _AP_I2, _AP_S2>::div r; + r.V = ret; + return r; + } +#define OP_BIN_AF(Sym, Rty, Width, Sign, Fun) \ + template \ + INLINE typename RType<_AP_W2,_AP_I2,_AP_S2>::Rty \ + operator Sym (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const \ + { \ + enum {_AP_F=_AP_W-_AP_I, F2=_AP_W2-_AP_I2}; \ + typename RType<_AP_W2,_AP_I2,_AP_S2>::Rty r, lhs(*this), rhs(op2); \ + r.V = lhs.V.Fun(rhs.V); \ + return r; \ + } \ + INLINE typename RType<_AP_W,_AP_I,_AP_S>::Rty \ + operator Sym (const ap_fixed_base& op2) const \ + { \ + typename RType<_AP_W,_AP_I,_AP_S>::Rty r; \ + r.V = V Sym op2.V; \ + return r; \ + } \ + + OP_BIN_AF(+, plus, plus_w, plus_s, Add) + OP_BIN_AF(-, minus, minus_w, minus_s, Sub) + +#define OP_LOGIC_BIN_AF(Sym, Rty, Width, Sign) \ + template \ + INLINE typename RType<_AP_W2,_AP_I2,_AP_S2>::Rty \ + operator Sym (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const \ + { \ + typename RType<_AP_W2,_AP_I2,_AP_S2>::Rty r, lhs(*this), rhs(op2); \ + r.V=lhs.V Sym rhs.V; \ + return r; \ + } \ + INLINE typename RType<_AP_W,_AP_I,_AP_S>::Rty \ + operator Sym (const ap_fixed_base& op2) const \ + { \ + typename RType<_AP_W,_AP_I,_AP_S>::Rty r; \ + r.V = V Sym op2.V; \ + return r; \ + } \ + INLINE typename RType<_AP_W,_AP_I,_AP_S>::Rty operator Sym(int op2) const \ + { \ + return V Sym (op2<<(_AP_W - _AP_I)); \ + } + OP_LOGIC_BIN_AF(&, logic, logic_w, logic_s) + OP_LOGIC_BIN_AF(|, logic, logic_w, logic_s) + OP_LOGIC_BIN_AF(^, logic, logic_w, logic_s) + + ///Arithmic : assign + //------------------------------------------------------------------------- +#define OP_ASSIGN_AF(Sym) \ + template \ + INLINE ap_fixed_base& operator Sym##= (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) \ + { \ + *this=operator Sym (op2) ; \ + return *this; \ + } + + OP_ASSIGN_AF(+) + OP_ASSIGN_AF(-) + OP_ASSIGN_AF(&) + OP_ASSIGN_AF(|) + OP_ASSIGN_AF(^) + OP_ASSIGN_AF(*) + OP_ASSIGN_AF(/) + + ///Prefix increment, decrement + //------------------------------------------------------------------------- + INLINE ap_fixed_base& operator ++() { + operator+=(ap_fixed_base<1,1,false>(1)); //SystemC's semantics + return *this; + } + + INLINE ap_fixed_base& operator --() { + operator-=(ap_fixed_base<1,1,false>(1)); //SystemC's semantics + return *this; + } + + //Postfix increment, decrement + //------------------------------------------------------------------------- + INLINE const ap_fixed_base operator ++(int) { + ap_fixed_base t(*this); + operator++(); + return t; + } + + INLINE const ap_fixed_base operator --(int) { + ap_fixed_base t = *this; + operator--(); + return t; + } + + ///Unary arithmetic + //------------------------------------------------------------------------- + INLINE ap_fixed_base operator +() {return *this;} + + INLINE ap_fixed_base<_AP_W + 1, _AP_I + 1, true> operator -() const { + ap_fixed_base<_AP_W + 1, _AP_I + 1, true> Tmp(*this); + Tmp.V = - Tmp.V; + return Tmp; + } + + INLINE ap_fixed_base<_AP_W,_AP_I,true,_AP_Q,_AP_O, _AP_N> getNeg() { + ap_fixed_base<_AP_W,_AP_I,true,_AP_Q,_AP_O, _AP_N> Tmp(*this); + Tmp.V=-Tmp.V; + return Tmp; + } + + ///Not (!) + //------------------------------------------------------------------------- + INLINE bool operator !() const { + return !V; + } + + ///Bitwise complement + //------------------------------------------------------------------------- + INLINE ap_fixed_base<_AP_W, _AP_I, _AP_S> + operator ~() const { + ap_fixed_base<_AP_W, _AP_I, _AP_S> res(*this); + res.V.flip(); + return res; + } + + ///Shift + ///template argument as shift value + template + INLINE ap_fixed_base<_AP_W, _AP_I + _AP_SHIFT, _AP_S> lshift () const { + ap_fixed_base<_AP_W, _AP_I + _AP_SHIFT, _AP_S> r; + r.V = V; + return r; + } + + template + INLINE ap_fixed_base<_AP_W, _AP_I - _AP_SHIFT, _AP_S> rshift () const { + ap_fixed_base<_AP_W, _AP_I - _AP_SHIFT, _AP_S> r; + r.V = V; + return r; + } + + //Because the return type is the type of the the first operand, shift assign + //operators do not carry out any quantization or overflow + //While systemc, shift assigns for sc_fixed/sc_ufixed will result in + //quantization or overflow (depending on the mode of the first operand) + //------------------------------------------------------------------------- + INLINE ap_fixed_base operator << (int sh) const { + ap_fixed_base r; + bool isNeg=(sh&0x80000000) != 0; + sh=isNeg?-sh:sh; + bool shiftoverflow = sh >= _AP_W; + bool NegSrc = V.isNegative(); + if (isNeg) { + if (shiftoverflow) + NegSrc?r.V.set():r.V.clear(); + else + r.V=_AP_S?V.ashr(sh):V.lshr(sh); + } else { + if (shiftoverflow) + r.V.clear(); + else + r.V=V< 1 && sh <= _AP_W) + rb = (V << (_AP_W - sh + 1 )) != 0; + else if (sh > _AP_W) + rb = V != 0; + r.quantization_adjust(qb, rb, NegSrc); + } else if (isNeg == false && _AP_O != AP_WRAP) { + bool allones, allzeros; + if (sh < _AP_W ) { + ap_private<_AP_W, _AP_S > range1 = V.lshr(_AP_W - sh - 1); + allones = range1.isAllOnesValue(); + allzeros = range1.isMinValue(); + } else { + allones = false; + allzeros = V.isMinValue(); + } + bool overflow = !allzeros && !NegSrc; + bool underflow = !allones && NegSrc; + if (_AP_O == AP_SAT_SYM && _AP_S) + underflow |= NegSrc && (_AP_W > 1 ? r.V.isMinSignedValue():true); + bool lD = false; + if ( sh < _AP_W ) lD = V[_AP_W - sh - 1]; + r.overflow_adjust(underflow, overflow, lD, NegSrc); + } +#endif + return r; + } + + template + INLINE ap_fixed_base operator<<(const ap_private<_AP_W2,true>& op2) const { + int sh = op2.to_int(); + return operator << (sh); + } + + INLINE ap_fixed_base operator << (unsigned int sh ) const { + ap_fixed_base r; + bool shiftoverflow = sh >= _AP_W; + r.V = shiftoverflow ? ap_private<_AP_W, _AP_S >(0) : V << sh; + if (sh == 0) return r; +#ifdef __SC_COMPATIBLE__ + bool NegSrc = V.isNegative(); + if (_AP_O != AP_WRAP) { + bool allones, allzeros; + if (sh < _AP_W ) { + ap_private<_AP_W, _AP_S > range1 = V.lshr(_AP_W - sh -1); + allones = range1.isAllOnesValue(); + allzeros = range1.isMinValue(); + } else { + allones = false; + allzeros = V.isMinValue(); + } + bool overflow = !allzeros && !NegSrc; + bool underflow = !allones && NegSrc; + if (_AP_O == AP_SAT_SYM && _AP_S) + underflow |= NegSrc && (_AP_W > 1 ? r.V.isMinSignedValue():true); + bool lD = false; + if ( sh < _AP_W ) lD = V[_AP_W - sh - 1]; + r.overflow_adjust(underflow, overflow, lD, NegSrc); + } +#endif + return r; + } + + template + INLINE ap_fixed_base operator << (const ap_private<_AP_W2,false>& op2) const { + unsigned int sh = op2.to_uint(); + return operator << (sh); + } + + INLINE ap_fixed_base operator >> (int sh) const { + ap_fixed_base r; + bool isNeg=(sh&0x80000000) != 0; + bool NegSrc = V.isNegative(); + sh=isNeg?-sh:sh; + bool shiftoverflow = sh >= _AP_W; + if (isNeg && !shiftoverflow) r.V=V< 1 && sh <= _AP_W) + rb = (V << (_AP_W - sh + 1 )) != 0; + else if (sh > _AP_W) + rb = V != 0; + r.quantization_adjust(qb, rb, NegSrc); + } else if (isNeg == true && _AP_O != AP_WRAP) { + bool allones, allzeros; + if (sh < _AP_W ) { + ap_private<_AP_W, _AP_S > range1 = V.lshr(_AP_W - sh - 1); + allones = range1.isAllOnesValue(); + allzeros = range1.isMinValue(); + } else { + allones = false; + allzeros = V.isMinValue(); + } + bool overflow = !allzeros && !NegSrc; + bool underflow = !allones && NegSrc; + if (_AP_O == AP_SAT_SYM && _AP_S) + underflow |= NegSrc && (_AP_W > 1 ? r.V.isMinSignedValue():true); + bool lD = false; + if ( sh < _AP_W ) lD = V[_AP_W - sh - 1]; + r.overflow_adjust(underflow, overflow, lD, NegSrc); + } +#endif + return r; + } + + template + INLINE ap_fixed_base operator >> (const ap_private<_AP_W2,true>& op2) const { + int sh = op2.to_int(); + return operator >> (sh); + } + + INLINE ap_fixed_base operator >> (unsigned int sh) const { + ap_fixed_base r; + bool NegSrc = V.isNegative(); + bool shiftoverflow = sh >= _AP_W; + if (shiftoverflow) + NegSrc?r.V.set():r.V.clear(); + else + r.V=_AP_S?V.ashr(sh):V.lshr(sh); +#ifdef __SC_COMPATIBLE__ + if (sh == 0) return r; + if (_AP_Q != AP_TRN) { + bool qb = false; + if (sh <= _AP_W) qb = V[sh - 1]; + bool rb = false; + if (sh > 1 && sh <= _AP_W) + rb = (V << (_AP_W - sh + 1 )) != 0; + else if (sh > _AP_W) + rb = V != 0; + r.quantization_adjust(qb, rb, NegSrc); + } +#endif + return r; + } + + template + INLINE ap_fixed_base operator >> (const ap_private<_AP_W2,false>& op2) const { + unsigned int sh = op2.to_uint(); + return operator >> (sh); + } + + ///shift assign + //------------------------------------------------------------------------- +#define OP_AP_SHIFT_AP_ASSIGN_AF(Sym) \ + template \ + INLINE ap_fixed_base& operator Sym##=(const ap_private<_AP_W2,_AP_S2>& op2) \ + { \ + *this=operator Sym (op2); \ + return *this; \ + } + + OP_AP_SHIFT_AP_ASSIGN_AF(<<) + OP_AP_SHIFT_AP_ASSIGN_AF(>>) + + ///Support shift(ap_fixed_base) +#define OP_AP_SHIFT_AF(Sym) \ + template \ + INLINE ap_fixed_base operator Sym (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const \ + { \ + return operator Sym (op2.to_ap_private()); \ + } \ + template \ + INLINE ap_fixed_base& operator Sym##= (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) \ + { \ + *this=operator Sym (op2); \ + return *this; \ + } + + OP_AP_SHIFT_AF(<<) + OP_AP_SHIFT_AF(>>) + + INLINE ap_fixed_base& operator >>= (unsigned int sh) { + *this = operator >> (sh); + return *this; + } + + INLINE ap_fixed_base& operator <<= (unsigned int sh) { + *this = operator << (sh); + return *this; + } + + INLINE ap_fixed_base& operator >>= (int sh) { + *this = operator >> (sh); + return *this; + } + + INLINE ap_fixed_base& operator <<= (int sh) { + *this = operator << (sh); + return *this; + } + + ///Comparisons + //------------------------------------------------------------------------- + template + INLINE bool operator == (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + enum {_AP_F=_AP_W-_AP_I,F2=_AP_W2-_AP_I2, shAmt1 = AP_MAX(F2-_AP_F, 0), shAmt2 = AP_MAX(_AP_F-F2,0), _AP_W3 = (_AP_F==F2) ? AP_MAX(_AP_W,_AP_W2) : AP_MAX(_AP_W+shAmt1, _AP_W2+shAmt2)}; + ap_private<_AP_W3, _AP_S > OP1= ap_private<_AP_W3, _AP_S >(V)< OP2=ap_private<_AP_W3,_AP_S2 >(op2.V)< + INLINE bool operator != (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + return !(*this==op2); + } + + template + INLINE bool operator > (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + enum {_AP_F=_AP_W-_AP_I,F2=_AP_W2-_AP_I2, shAmt1 = AP_MAX(F2-_AP_F, 0), shAmt2 = AP_MAX(_AP_F-F2,0), _AP_W3 = (_AP_F==F2) ? AP_MAX(_AP_W,_AP_W2) : AP_MAX(_AP_W+shAmt1, _AP_W2+shAmt2)}; + ap_private<_AP_W3, _AP_S > OP1= ap_private<_AP_W3, _AP_S >(V)< OP2=ap_private<_AP_W3,_AP_S2 >(op2.V)< + INLINE bool operator <= (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + return !(*this>op2); + } + + template + INLINE bool operator < (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + enum {_AP_F=_AP_W-_AP_I,F2=_AP_W2-_AP_I2, shAmt1 = AP_MAX(F2-_AP_F, 0), shAmt2 = AP_MAX(_AP_F-F2,0), _AP_W3 = (_AP_F==F2) ? AP_MAX(_AP_W,_AP_W2) : AP_MAX(_AP_W+shAmt1, _AP_W2+shAmt2)}; + ap_private<_AP_W3, _AP_S > OP1= ap_private<_AP_W3, _AP_S >(V)< OP2=ap_private<_AP_W3,_AP_S2 >(op2.V)< + INLINE bool operator >= (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + return !(*this) + DOUBLE_CMP_AF(>=) + DOUBLE_CMP_AF(<) + DOUBLE_CMP_AF(<=) + + // Bit and Slice Select + INLINE af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N> operator [] (unsigned int index) { + assert(index<_AP_W&&"Attemping to read bit beyond MSB"); + return af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>(this, index); + } + + INLINE af_bit_ref<_AP_W, _AP_I,_AP_S,_AP_Q,_AP_O, _AP_N> bit(unsigned int index) { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>(this, index); + } + + template + INLINE af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N> bit (const ap_private<_AP_W2,_AP_S2>& index) { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>(this, index.to_int()); + } + + INLINE bool bit (unsigned int index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return V[index]; + } + + INLINE bool operator [] (unsigned int index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return V[index]; + } + + template + INLINE bool bit (const ap_private<_AP_W2, _AP_S2>& index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return V[index.to_uint()]; + } + + template + INLINE bool operator [] (const ap_private<_AP_W2, _AP_S2>& index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return V[index.to_uint()]; + } + + INLINE af_bit_ref<_AP_W, _AP_I,_AP_S,_AP_Q,_AP_O, _AP_N> get_bit(int index) { + assert(index < _AP_I && "Attempting to read bit beyond MSB"); + assert(index >= _AP_I - _AP_W&& "Attempting to read bit beyond MSB"); + return af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>(this, index + _AP_W - _AP_I); + } + + template + INLINE af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N> get_bit (const ap_private<_AP_W2, true>& index) { + assert(index >= _AP_I - _AP_W && "Attempting to read bit with negative index"); + assert(index < _AP_I && "Attempting to read bit beyond MSB"); + return af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>(this, index.to_int() + _AP_W - _AP_I); + } + + INLINE bool get_bit (int index) const { + assert(index >= _AP_I - _AP_W && "Attempting to read bit with negative index"); + assert(index < _AP_I && "Attempting to read bit beyond MSB"); + return V[index + _AP_W - _AP_I]; + } + + template + INLINE bool get_bit (const ap_private<_AP_W2, true>& index) const { + assert(index >= _AP_I - _AP_W && "Attempting to read bit with negative index"); + assert(index < _AP_I && "Attempting to read bit beyond MSB"); + return V[index.to_int() + _AP_W - _AP_I]; + } + + INLINE af_range_ref<_AP_W,_AP_I,_AP_S, _AP_Q, _AP_O, _AP_N> + range(int Hi, int Lo) { + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>(this, Hi, Lo); + } + + INLINE af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> + operator () (int Hi, int Lo) { + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>(this, Hi, Lo); + } + + INLINE af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> + range(int Hi, int Lo) const { + assert((Hi < _AP_W) && (Lo < _AP_W) &&"Out of bounds in range()"); + return af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>(const_cast(this), Hi, Lo); + } + + INLINE af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> + operator () (int Hi, int Lo) const { + return this->range(Hi, Lo); + } + + template + INLINE af_range_ref<_AP_W,_AP_I,_AP_S, _AP_Q, _AP_O, _AP_N> + range(const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>(this, Hi, Lo); + } + + template + INLINE af_range_ref<_AP_W,_AP_I,_AP_S, _AP_Q, _AP_O, _AP_N> + operator () (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>(this, Hi, Lo); + } + + template + INLINE af_range_ref<_AP_W,_AP_I,_AP_S, _AP_Q, _AP_O, _AP_N> + range(const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) const { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>(const_cast< + ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>*>(this), + Hi, Lo); + } + + template + INLINE af_range_ref<_AP_W,_AP_I,_AP_S, _AP_Q, _AP_O, _AP_N> + operator () (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) const { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + return this->range(Hi, Lo); + } + + INLINE af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> + range() { + return this->range(_AP_W - 1, 0); + } + + INLINE af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> + range() const { + return this->range(_AP_W - 1, 0); + } + + INLINE bool is_zero () const { + return V.isMinValue(); + } + + INLINE bool is_neg () const { + if (V.isNegative()) + return true; + return false; + } + + INLINE int wl () const { + return _AP_W; + } + + INLINE int iwl () const { + return _AP_I; + } + + INLINE ap_q_mode q_mode () const { + return _AP_Q; + } + + INLINE ap_o_mode o_mode () const { + return _AP_O; + } + + INLINE int n_bits () const { + return 0; + } + + //private: +public: + ap_private<_AP_W, _AP_S> V; +}; + +template +std::string ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>::to_string( + uint8_t radix, bool sign) const { + std::string str; + str.clear(); + char step; + std::string prefix; + switch (radix) { + case 2 : prefix = "0b"; step = 1; break; + case 8 : prefix = "0o"; step = 3; break; + case 16 : prefix = "0x"; step = 4; break; + default : break; + } + if (_AP_W <= _AP_I) + str = this->to_ap_private().to_string(radix, + radix == 10 ? _AP_S : sign); + else { + if (radix == 10) { + bool isNeg = _AP_S && V.isNegative(); + if (_AP_I > 0) { + ap_private int_part(0); + int_part = this->to_ap_private(); + str += int_part.to_string(radix, false); + } else { + if (isNeg) str += '-'; + } + ap_fixed_base<_AP_W, _AP_I, _AP_S> tmp(*this); + if (isNeg && _AP_I <= 0) tmp = -tmp; + ap_fixed_base<_AP_W - AP_MIN(_AP_I, 0), 0, false> frac_part = tmp; + if (frac_part == 0) return str; + str += "."; + while (frac_part != 0) { + char digit = (frac_part * radix).to_ap_private(); + str += static_cast(digit + '0'); + frac_part *= radix; + } + } else { + if (_AP_I > 0) { + for (signed i = _AP_W - _AP_I; i < _AP_W; i += step) { + + char digit = (char)(this->range(AP_MIN(i + step - 1, _AP_W - 1), i)); + str = (digit < 10 ? static_cast(digit + '0') : + static_cast(digit - 10 + 'a')) + str; + } + } + str += '.'; + ap_fixed_base tmp(*this); + for (signed i = _AP_W - _AP_I - 1; i >= 0; i -= step) { + char digit = (char)(tmp.range(i, AP_MAX(0, i - step + 1))); + str += digit < 10 ? static_cast(digit + '0') : + static_cast(digit - 10 + 'a'); + } + } + } + str = prefix + str; + return str; +} + +template +INLINE void b_not(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op) { + ret.V = op.V; + ret.V.flip(); +} + +template +INLINE void b_and(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op1, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op2) { + ret.V = op1.V & op2.V; +} + +template +INLINE void b_or(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op1, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op2) { + ret.V = op1.V | op2.V; +} + +template +INLINE void b_xor(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op1, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op2) { + ret.V = op1.V ^ op2.V; +} + +template +INLINE void neg(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) { + ap_fixed_base<_AP_W2+!_AP_S2, _AP_I2+!_AP_S2, true, _AP_Q2, _AP_O2, _AP_N2> Tmp; + Tmp.V = - op.V; + ret = Tmp; +} + +template +INLINE void neg(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op) { + ret.V = -op.V; +} + +template +INLINE void lshift(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op, + int i) { + ap_fixed_base<_AP_W2 - _AP_I2 + AP_MAX(_AP_I, _AP_I2), AP_MAX(_AP_I, _AP_I2), _AP_S2, _AP_Q2, _AP_O2, _AP_N2> Tmp; + Tmp = op; + Tmp.V <<= i; + ret = Tmp; +} + +template +INLINE void lshift(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op, + int i) { + ret.V = op.V << i; +} + +template +INLINE void rshift(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op, + int i) { + ap_fixed_base<_AP_I2 + AP_MAX(_AP_W - _AP_I, _AP_W2 - _AP_I2), _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> Tmp; + Tmp = op; + Tmp.V = _AP_S2 ? Tmp.V.ashr(i): Tmp.V.lshr(i); + ret = Tmp; +} + +template +INLINE void rshift(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op, + int i) { + ret.V = _AP_S ? op.V.ashr(i): op.V.lshr(i); +} + +#define AF_CTOR_SPEC_BASE(_AP_W,_AP_S,C_TYPE) \ + template<> INLINE ap_fixed_base<_AP_W,_AP_W,_AP_S,AP_TRN,AP_WRAP>::ap_fixed_base(C_TYPE i_op):V(i_op) \ + { \ + } + +#define AF_CTOR_SPEC(__W,C_TYPE) \ + AF_CTOR_SPEC_BASE(__W,true,C_TYPE) \ + AF_CTOR_SPEC_BASE(__W,false,C_TYPE) + +AF_CTOR_SPEC(1,bool) +AF_CTOR_SPEC(8, signed char) +AF_CTOR_SPEC(8, unsigned char) +AF_CTOR_SPEC(16, signed short) +AF_CTOR_SPEC(16, unsigned short) +AF_CTOR_SPEC(32, signed int) +AF_CTOR_SPEC(32, unsigned int) +AF_CTOR_SPEC(64, ap_slong) +AF_CTOR_SPEC(64, ap_ulong) + +///Output streaming +//----------------------------------------------------------------------------- +template +INLINE std::ostream& +operator <<(std::ostream& os, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& x) { + os << x.to_double(); + return os; +} + +///Input streaming +//----------------------------------------------------------------------------- +template +INLINE std::istream& +operator >> (std::istream& os, ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& x) { + double d; + os >> d; + x = ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>(x); + return os; +} + +template +INLINE void print(const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& x) { + ap_private<_AP_W,_AP_S> data=x.V; + if (_AP_I>0) { + const ap_private<_AP_I,_AP_S> p1=data>>(_AP_W-_AP_I); + print(p1); + + } else + printf("0"); + printf("."); + if (_AP_I<_AP_W) { + const ap_private<_AP_W-_AP_I,false> p2=data; + print(p2,false); + } +} + +///Operators mixing Integers with ap_fixed_base +//----------------------------------------------------------------------------- +#if 1 +#define AF_BIN_OP_WITH_INT_SF(BIN_OP,C_TYPE,_AP_W2,_AP_S2,RTYPE) \ + template \ + INLINE typename ap_fixed_base<_AP_W,_AP_I,_AP_S>::template RType<_AP_W2,_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP (const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) \ + { \ + return op.operator BIN_OP(ap_private<_AP_W2,_AP_S2>(i_op)); \ + } +#define AF_BIN_OP_WITH_INT(BIN_OP, C_TYPE, _AP_W2,_AP_S2,RTYPE) \ + template \ + INLINE typename ap_fixed_base<_AP_W,_AP_I,_AP_S>::template RType<_AP_W2,_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP (const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) \ + { \ + return op.operator BIN_OP (ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op)); \ + } \ + \ + template \ + INLINE typename ap_fixed_base<_AP_W,_AP_I,_AP_S>::template RType<_AP_W2,_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP (C_TYPE i_op, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op) \ + { \ + return ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op).operator BIN_OP (op); \ + } + +#else +#define AF_BIN_OP_WITH_INT_SF(BIN_OP,C_TYPE,_AP_W2,_AP_S2,RTYPE) \ + template \ + INLINE typename ap_fixed_base<_AP_W,_AP_I,_AP_S>::template RType<_AP_W2,_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP (const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) \ + { \ + return op BIN_OP (i_op); \ + } +#define AF_BIN_OP_WITH_INT(BIN_OP, C_TYPE, _AP_W2,_AP_S2,RTYPE) \ + template \ + INLINE typename ap_fixed_base<_AP_W,_AP_I,_AP_S>::template RType<_AP_W2,_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP (const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) \ + { \ + return op.V BIN_OP (i_op<<(_AP_W-_AP_I)); \ + } \ + \ + \ + template \ + INLINE typename ap_fixed_base<_AP_W,_AP_I,_AP_S>::template RType<_AP_W2,_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP (C_TYPE i_op, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op) \ + { \ + return ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op).operator BIN_OP (op); \ + } + +#endif +#if 1 +#define AF_REL_OP_WITH_INT(REL_OP, C_TYPE, _AP_W2,_AP_S2) \ + template \ + INLINE bool operator REL_OP (const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) \ + { \ + return op.operator REL_OP (ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op)); \ + } \ + \ + \ + template \ + INLINE bool operator REL_OP (C_TYPE i_op, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op) \ + { \ + return ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op).operator REL_OP (op); \ + } +#else +#define AF_REL_OP_WITH_INT(REL_OP, C_TYPE, _AP_W2,_AP_S2) \ + template \ + INLINE bool operator REL_OP (const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) \ + { \ + return op.V.operator REL_OP (i_op<<(_AP_W-_AP_I)); \ + } \ + \ + \ + template \ + INLINE bool operator REL_OP (C_TYPE i_op, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op) \ + { \ + return (i_op<<(_AP_W-_AP_I)) REL_OP (op.V.VAL); \ + } +#endif +#if 1 +#define AF_ASSIGN_OP_WITH_INT(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& operator ASSIGN_OP ( ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) { \ + return op.operator ASSIGN_OP (ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op)); \ + } +#define AF_ASSIGN_OP_WITH_INT_SF(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& operator ASSIGN_OP ( ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) { \ + return op.operator ASSIGN_OP (ap_private<_AP_W2,_AP_S2>(i_op)); \ + } +#else +#define AF_ASSIGN_OP_WITH_INT(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& operator ASSIGN_OP ( ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) { \ + return op.V.operator ASSIGN_OP (i_op); \ + } +#define AF_ASSIGN_OP_WITH_INT_SF(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& operator ASSIGN_OP ( ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) { \ + return op.V.operator ASSIGN_OP (i_op); \ + } +#endif + +#define AF_OPS_WITH_INT(C_TYPE, WI, SI) \ + AF_BIN_OP_WITH_INT(+, C_TYPE, WI, SI, plus) \ + AF_BIN_OP_WITH_INT(-, C_TYPE, WI, SI, minus) \ + AF_BIN_OP_WITH_INT(*, C_TYPE, WI, SI, mult) \ + AF_BIN_OP_WITH_INT(/, C_TYPE, WI, SI, div) \ + AF_BIN_OP_WITH_INT_SF(>>, C_TYPE, WI, SI, arg1) \ + AF_BIN_OP_WITH_INT_SF(<<, C_TYPE, WI, SI, arg1) \ + AF_BIN_OP_WITH_INT(&, C_TYPE, WI, SI, logic) \ + AF_BIN_OP_WITH_INT(|, C_TYPE, WI, SI, logic) \ + AF_BIN_OP_WITH_INT(^, C_TYPE, WI, SI, logic) \ + \ + AF_REL_OP_WITH_INT(==, C_TYPE, WI, SI) \ + AF_REL_OP_WITH_INT(!=, C_TYPE, WI, SI) \ + AF_REL_OP_WITH_INT(>, C_TYPE, WI, SI) \ + AF_REL_OP_WITH_INT(>=, C_TYPE, WI, SI) \ + AF_REL_OP_WITH_INT(<, C_TYPE, WI, SI) \ + AF_REL_OP_WITH_INT(<=, C_TYPE, WI, SI) \ + \ + AF_ASSIGN_OP_WITH_INT(+=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT(-=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT(*=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT(/=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT_SF(>>=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT_SF(<<=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT(&=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT(|=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT(^=, C_TYPE, WI, SI) + +AF_OPS_WITH_INT(bool, 1, false) +AF_OPS_WITH_INT(char, 8, true) +AF_OPS_WITH_INT(signed char, 8, true) +AF_OPS_WITH_INT(unsigned char, 8, false) +AF_OPS_WITH_INT(short, 16, true) +AF_OPS_WITH_INT(unsigned short, 16, false) +AF_OPS_WITH_INT(int, 32, true) +AF_OPS_WITH_INT(unsigned int, 32, false) +# if defined __x86_64__ +AF_OPS_WITH_INT(long, 64, true) +AF_OPS_WITH_INT(unsigned long, 64, false) +# else +AF_OPS_WITH_INT(long, 32, true) +AF_OPS_WITH_INT(unsigned long, 32, false) +# endif +AF_OPS_WITH_INT(ap_slong, 64, true) +AF_OPS_WITH_INT(ap_ulong, 64, false) + +#define AF_BIN_OP_WITH_AP_INT(BIN_OP, RTYPE) \ + template \ + INLINE typename ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>::template RType<_AP_W,_AP_I,_AP_S>::RTYPE \ + operator BIN_OP ( const ap_private<_AP_W2,_AP_S2>& i_op, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op) { \ + return ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op).operator BIN_OP (op); \ + } \ + template \ + INLINE typename ap_fixed_base<_AP_W,_AP_I,_AP_S>::template RType<_AP_W2,_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP ( const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, const ap_private<_AP_W2,_AP_S2>& i_op) { \ + return op.operator BIN_OP (ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op)); \ + } + +#define AF_REL_OP_WITH_AP_INT(REL_OP) \ + template \ + INLINE bool operator REL_OP ( const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, const ap_private<_AP_W2,_AP_S2>& i_op) { \ + return op.operator REL_OP ( ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op)); \ + } \ + template \ + INLINE bool operator REL_OP ( const ap_private<_AP_W2,_AP_S2>& i_op, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op) { \ + return ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op).operator REL_OP (op); \ + } + +#define AF_ASSIGN_OP_WITH_AP_INT(ASSIGN_OP) \ + template \ + INLINE ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& operator ASSIGN_OP ( ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, const ap_private<_AP_W2,_AP_S2>& i_op) { \ + return op.operator ASSIGN_OP (ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op)); \ + } \ + template \ + INLINE ap_private<_AP_W2,_AP_S2>& operator ASSIGN_OP ( ap_private<_AP_W2,_AP_S2>& i_op, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op) { \ + return i_op.operator ASSIGN_OP (op.to_ap_private()); \ + } + +AF_BIN_OP_WITH_AP_INT(+, plus) +AF_BIN_OP_WITH_AP_INT(-, minus) +AF_BIN_OP_WITH_AP_INT(*, mult) +AF_BIN_OP_WITH_AP_INT(/, div) +AF_BIN_OP_WITH_AP_INT(&, logic) +AF_BIN_OP_WITH_AP_INT(|, logic) +AF_BIN_OP_WITH_AP_INT(^, logic) + +AF_REL_OP_WITH_AP_INT(==) +AF_REL_OP_WITH_AP_INT(!=) +AF_REL_OP_WITH_AP_INT(>) +AF_REL_OP_WITH_AP_INT(>=) +AF_REL_OP_WITH_AP_INT(<) +AF_REL_OP_WITH_AP_INT(<=) + +AF_ASSIGN_OP_WITH_AP_INT(+=) +AF_ASSIGN_OP_WITH_AP_INT(-=) +AF_ASSIGN_OP_WITH_AP_INT(*=) +AF_ASSIGN_OP_WITH_AP_INT(/=) +AF_ASSIGN_OP_WITH_AP_INT(&=) +AF_ASSIGN_OP_WITH_AP_INT(|=) +AF_ASSIGN_OP_WITH_AP_INT(^=) + +#define AF_REF_REL_OP_MIX_INT(REL_OP, C_TYPE, _AP_W2, _AP_S2) \ +template \ + INLINE bool operator REL_OP ( const af_range_ref<_AP_W,_AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op, C_TYPE op2) { \ + return (ap_private<_AP_W, false>(op)).operator REL_OP (ap_private<_AP_W2,_AP_S2>(op2)); \ + } \ +template \ + INLINE bool operator REL_OP ( C_TYPE op2, const af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op) { \ + return ap_private<_AP_W2,_AP_S2>(op2).operator REL_OP (ap_private<_AP_W, false>(op)); \ + } \ +template \ + INLINE bool operator REL_OP ( const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op, C_TYPE op2) { \ + return (bool(op)) REL_OP op2; \ + } \ +template \ + INLINE bool operator REL_OP ( C_TYPE op2, const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op) { \ + return op2 REL_OP (bool(op)); \ + } + +#define AF_REF_REL_MIX_INT(C_TYPE, _AP_WI, _AP_SI) \ +AF_REF_REL_OP_MIX_INT(>, C_TYPE, _AP_WI, _AP_SI) \ +AF_REF_REL_OP_MIX_INT(<, C_TYPE, _AP_WI, _AP_SI) \ +AF_REF_REL_OP_MIX_INT(>=, C_TYPE, _AP_WI, _AP_SI) \ +AF_REF_REL_OP_MIX_INT(<=, C_TYPE, _AP_WI, _AP_SI) \ +AF_REF_REL_OP_MIX_INT(==, C_TYPE, _AP_WI, _AP_SI) \ +AF_REF_REL_OP_MIX_INT(!=, C_TYPE, _AP_WI, _AP_SI) + +AF_REF_REL_MIX_INT(bool, 1, false) +AF_REF_REL_MIX_INT(char, 8, true) +AF_REF_REL_MIX_INT(signed char, 8, true) +AF_REF_REL_MIX_INT(unsigned char, 8, false) +AF_REF_REL_MIX_INT(short, 16, true) +AF_REF_REL_MIX_INT(unsigned short, 16, false) +AF_REF_REL_MIX_INT(int, 32, true) +AF_REF_REL_MIX_INT(unsigned int, 32, false) +# if defined __x86_64__ +AF_REF_REL_MIX_INT(long, 64, true) +AF_REF_REL_MIX_INT(unsigned long, 64, false) +# else +AF_REF_REL_MIX_INT(long, 32, true) +AF_REF_REL_MIX_INT(unsigned long, 32, false) +# endif +AF_REF_REL_MIX_INT(ap_slong, 64, true) +AF_REF_REL_MIX_INT(ap_ulong, 64, false) + +#define AF_REF_REL_OP_AP_INT(REL_OP) \ +template \ + INLINE bool operator REL_OP ( const af_range_ref<_AP_W,_AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op, const ap_private<_AP_W2, _AP_S> &op2) { \ + return (ap_private<_AP_W, false>(op)).operator REL_OP (op2); \ + } \ +template \ + INLINE bool operator REL_OP (const ap_private<_AP_W2, _AP_S2> &op2, const af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op) { \ + return op2.operator REL_OP (ap_private<_AP_W, false>(op)); \ + } \ +template \ + INLINE bool operator REL_OP ( const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op, const ap_private<_AP_W2, _AP_S2> &op2) { \ + return (ap_private<1, false>(op)).operator REL_OP (op2); \ + } \ +template \ + INLINE bool operator REL_OP ( const ap_private<_AP_W2, _AP_S2> &op2, const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op) { \ + return op2.operator REL_OP (ap_private<1,false>(op)); \ + } + +AF_REF_REL_OP_AP_INT(>) +AF_REF_REL_OP_AP_INT(<) +AF_REF_REL_OP_AP_INT(>=) +AF_REF_REL_OP_AP_INT(<=) +AF_REF_REL_OP_AP_INT(==) +AF_REF_REL_OP_AP_INT(!=) + +// Relational Operators with double +template +INLINE bool operator == ( double op1, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op2) { + return op2.operator == (op1); +} + +template +INLINE bool operator != ( double op1, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op2) { + return op2.operator != (op1); +} + +template +INLINE bool operator > ( double op1, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op2) { + return op2.operator < (op1); +} + +template +INLINE bool operator >= ( double op1, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op2) { + return op2.operator <= (op1); +} + +template +INLINE bool operator < ( double op1, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op2) { + return op2.operator > (op1); +} + +template +INLINE bool operator <= ( double op1, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op2) { + return op2.operator >= (op1); +} + +#endif /* #ifndef __AESL_GCC_AP_FIXED_H__ */ \ No newline at end of file diff --git a/hls_2018/router_03_boardstr/etc/ap_int_sim.h b/hls_2018/router_03_boardstr/etc/ap_int_sim.h new file mode 100755 index 0000000..887ccd8 --- /dev/null +++ b/hls_2018/router_03_boardstr/etc/ap_int_sim.h @@ -0,0 +1,1629 @@ +/* + * Copyright 2012 Xilinx, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __AESL_GCC_AP_INT_H__ +#define __AESL_GCC_AP_INT_H__ + +#ifndef __cplusplus +#error C++ is required to include this header file +#endif /* #ifndef __cplusplus */ + +#undef _AP_DEBUG_ +#include +#include + +// for safety +#if (defined(_AP_N)|| defined(_AP_C)) +#error One or more of the following is defined: _AP_N, _AP_C. Definition conflicts with their usage as template parameters. +#endif /* #if (defined(_AP_N)|| defined(_AP_C)) */ + +// for safety +#if (defined(_AP_W) || defined(_AP_I) || defined(_AP_S) || defined(_AP_Q) || defined(_AP_O) || defined(_AP_W2) || defined(_AP_I2) || defined(_AP_S2) || defined(_AP_Q2) || defined(_AP_O2)) +#error One or more of the following is defined: _AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2. Definition conflicts with their usage as template parameters. +#endif /* #if (defined(_AP_W) || defined(_AP_I) || defined(_AP_S) || defined(_AP_Q) || defined(_AP_O) || defined(_AP_W2) || defined(_AP_I2) || defined(_AP_S2) || defined(_AP_Q2) || defined(_AP_O2)) */ + +//for safety +#if (defined(_AP_W3) || defined(_AP_S3) || defined(_AP_W4) || defined(_AP_S4)) +#error One or more of the following is defined: _AP_W3, _AP_S3, _AP_W4,_AP_S4. Definition conflicts with their usage as template parameters. +#endif /* #if (defined(_AP_W3) || defined(_AP_S3) || defined(_AP_W4) || defined(_AP_S4)) */ + +//for safety +#if (defined(_AP_W1) || defined(_AP_S1) || defined(_AP_I1) || defined(_AP_T) || defined(_AP_T1) || defined(_AP_T2) || defined(_AP_T3) || defined(_AP_T4)) +#error One or more of the following is defined: _AP_W1, _AP_S1, _AP_I1, _AP_T, _AP_T1, _AP_T2, _AP_T3, _AP_T4. Definition conflicts with their usage as template parameters. +#endif /* #if (defined(_AP_W1) || defined(_AP_S1) || defined(_AP_I1) || defined(_AP_T) || defined(_AP_T1) || defined(_AP_T2) || defined(_AP_T3) || defined(_AP_T4)) */ + +#define __AESL_APDT_IN_SCFLOW__ +#ifndef __AESL_APDT_IN_SCFLOW__ + #include "etc/ap_private.h" +#else + #include "../etc/ap_private.h" +#endif /* #ifndef __AESL_APDT_IN_SCFLOW__ */ + +#ifdef _AP_DEBUG_ + #define AP_DEBUG(s) s +#else + #define AP_DEBUG(s) +#endif /* #ifdef _AP_DEBUG_ */ + +#ifndef __SIMULATION__ + #define __SIMULATION__ +#endif /* #ifndef __SIMULATION__ */ + +#if !(defined SYSTEMC_H) && !(defined SYSTEMC_INCLUDED) + #ifndef SC_TRN + #define SC_TRN AP_TRN + #endif /* #ifndef SC_TRN */ + #ifndef SC_RND + #define SC_RND AP_RND + #endif /* #ifndef SC_RND */ + #ifndef SC_TRN_ZERO + #define SC_TRN_ZERO AP_TRN_ZERO + #endif /* #ifndef SC_TRN_ZERO */ + #ifndef SC_RND_ZERO + #define SC_RND_ZERO AP_RND_ZERO + #endif /* #ifndef SC_RND_ZERO */ + #ifndef SC_RND_INF + #define SC_RND_INF AP_RND_INF + #endif /* #ifndef SC_RND_INF */ + #ifndef SC_RND_MIN_INF + #define SC_RND_MIN_INF AP_RND_MIN_INF + #endif /* #ifndef SC_RND_MIN_INF */ + #ifndef SC_RND_CONV + #define SC_RND_CONV AP_RND_CONV + #endif /* #ifndef SC_RND_CONV */ + #ifndef SC_WRAP + #define SC_WRAP AP_WRAP + #endif /* #ifndef SC_WRAP */ + #ifndef SC_SAT + #define SC_SAT AP_SAT + #endif /* #ifndef SC_SAT */ + #ifndef SC_SAT_ZERO + #define SC_SAT_ZERO AP_SAT_ZERO + #endif /* #ifndef SC_SAT_ZERO */ + #ifndef SC_SAT_SYM + #define SC_SAT_SYM AP_SAT_SYM + #endif /* #ifndef SC_SAT_SYM */ + #ifndef SC_WRAP_SM + #define SC_WRAP_SM AP_WRAP_SM + #endif /* #ifndef SC_WRAP_SM */ + #ifndef SC_BIN + #define SC_BIN AP_BIN + #endif /* #ifndef SC_BIN */ + #ifndef SC_OCT + #define SC_OCT AP_OCT + #endif /* #ifndef SC_OCT */ + #ifndef SC_DEC + #define SC_DEC AP_DEC + #endif /* #ifndef SC_DEC */ + #ifndef SC_HEX + #define SC_HEX AP_HEX + #endif /* #ifndef SC_HEX */ +#endif /* #if !(defined SYSTEMC_H) && !(defined SYSTEMC_INCLUDED) */ +#ifndef AP_INT_MAX_W +#define AP_INT_MAX_W 1024 +#endif +#define BIT_WIDTH_UPPER_LIMIT (1 << 15) +#if AP_INT_MAX_W > BIT_WIDTH_UPPER_LIMIT +#error "Bitwidth exceeds 32768 (1 << 15), the maximum allowed value" +#endif +#define MAX_MODE(BITS) ((BITS + 1023) / 1024) + +///Forward declaration +template struct ap_range_ref; +template struct ap_bit_ref; + +template struct ap_fixed_base; +template struct af_range_ref; +template struct af_bit_ref; +template class ap_uint; + +enum { + AP_BIN = 2, + AP_OCT = 8, + AP_DEC = 10, + AP_HEX = 16 +}; + +///Why to use reference? +///Because we will operate the original object indirectly by operating the +///result object directly after concating or part selecting + +///Proxy class which allows concatination to be used as rvalue(for reading) and +//lvalue(for writing) + +/// Concatination reference. +// ---------------------------------------------------------------- +template +struct ap_concat_ref { +#ifdef _MSC_VER + #pragma warning(disable: 4521 4522) +#endif /* #ifdef _MSC_VER */ + enum {_AP_WR=_AP_W1+_AP_W2,}; + _AP_T1& mbv1; + _AP_T2& mbv2; + + INLINE ap_concat_ref(const ap_concat_ref<_AP_W1, _AP_T1, + _AP_W2, _AP_T2>& ref): + mbv1(ref.mbv1), mbv2(ref.mbv2) {} + + INLINE ap_concat_ref(_AP_T1& bv1, _AP_T2& bv2):mbv1(bv1),mbv2(bv2) {} + + template + INLINE ap_concat_ref& operator = (const ap_private<_AP_W3,_AP_S3>& val) { + ap_private<_AP_W1+_AP_W2, false> vval(val); + int W_ref1=mbv1.length(); + int W_ref2=mbv2.length(); + ap_private<_AP_W1,false> mask1(-1); + mask1>>=_AP_W1-W_ref1; + ap_private<_AP_W2,false> mask2(-1); + mask2>>=_AP_W2-W_ref2; + mbv1.set(ap_private<_AP_W1,false>((vval>>W_ref2)&mask1)); + mbv2.set(ap_private<_AP_W2,false>(vval&mask2)); + return *this; + } + + INLINE ap_concat_ref& operator = (unsigned long long val) { + ap_private<_AP_W1+_AP_W2, false> tmpVal(val); + return operator = (tmpVal); + } + + template + INLINE ap_concat_ref& operator = + (const ap_concat_ref <_AP_W3, _AP_T3, _AP_W4, _AP_T4>& val) { + ap_private<_AP_W1+_AP_W2, false> tmpVal(val); + return operator = (tmpVal); + } + + INLINE ap_concat_ref& operator = + (const ap_concat_ref <_AP_W1, _AP_T1, _AP_W2, _AP_T2>& val) { + ap_private<_AP_W1+_AP_W2, false> tmpVal(val); + return operator = (tmpVal); + } + + template + INLINE ap_concat_ref& operator =(const ap_bit_ref<_AP_W3, _AP_S3>& val) { + ap_private<_AP_W1+_AP_W2, false> tmpVal(val); + return operator = (tmpVal); + } + + template + INLINE ap_concat_ref& operator =(const ap_range_ref<_AP_W3,_AP_S3>& val) { + ap_private<_AP_W1+_AP_W2, false> tmpVal(val); + return operator =(tmpVal); + } + + template + INLINE ap_concat_ref& operator= (const af_range_ref<_AP_W3, _AP_I3, _AP_S3, + _AP_Q3, _AP_O3, _AP_N3>& val) { + return operator = ((const ap_private<_AP_W3, false>)(val)); + } + + template + INLINE ap_concat_ref& operator= (const ap_fixed_base<_AP_W3, _AP_I3, _AP_S3, + _AP_Q3, _AP_O3, _AP_N3>& val) { + return operator = (val.to_ap_private()); + } + + template + INLINE ap_concat_ref& operator= (const af_bit_ref<_AP_W3, _AP_I3, _AP_S3, + _AP_Q3, _AP_O3, _AP_N3>& val) { + return operator=((unsigned long long)(bool)(val)); + } + + + INLINE operator ap_private<_AP_WR, false> () const { + return get(); + } + + INLINE operator unsigned long long () const { + return get().to_uint64(); + } + + template + INLINE ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, ap_range_ref<_AP_W3, _AP_S3> > + operator, (const ap_range_ref<_AP_W3, _AP_S3> &a2) { + return ap_concat_ref<_AP_WR, ap_concat_ref, + _AP_W3, ap_range_ref<_AP_W3, _AP_S3> >(*this, + const_cast &>(a2)); + } + + template + INLINE ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, ap_private<_AP_W3, _AP_S3> > + operator, (ap_private<_AP_W3, _AP_S3> &a2) { + return ap_concat_ref<_AP_WR, ap_concat_ref, + _AP_W3, ap_private<_AP_W3, _AP_S3> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, ap_private<_AP_W3, _AP_S3> > + operator, (const ap_private<_AP_W3, _AP_S3> &a2) { + return ap_concat_ref<_AP_WR, ap_concat_ref, + _AP_W3, ap_private<_AP_W3, _AP_S3> >(*this, + const_cast&>(a2)); + } + + template + INLINE ap_concat_ref<_AP_WR, ap_concat_ref, 1, ap_bit_ref<_AP_W3, _AP_S3> > + operator, (const ap_bit_ref<_AP_W3, _AP_S3> &a2) { + return ap_concat_ref<_AP_WR, ap_concat_ref, + 1, ap_bit_ref<_AP_W3, _AP_S3> >(*this, + const_cast &>(a2)); + } + + template + INLINE ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3+_AP_W4, ap_concat_ref<_AP_W3,_AP_T3,_AP_W4,_AP_T4> > + operator, (const ap_concat_ref<_AP_W3,_AP_T3,_AP_W4,_AP_T4> &a2) + { + return ap_concat_ref<_AP_WR, ap_concat_ref, + _AP_W3+_AP_W4, ap_concat_ref<_AP_W3,_AP_T3,_AP_W4, + _AP_T4> >(*this, const_cast& >(a2)); + } + + template + INLINE + ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, af_range_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3> > + operator, (const af_range_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, + _AP_O3, _AP_N3> &a2) { + return ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, af_range_ref<_AP_W3, + _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3> >(*this, + const_cast& >(a2)); + } + + template + INLINE + ap_concat_ref<_AP_WR, ap_concat_ref, 1, af_bit_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3> > + operator, (const af_bit_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, + _AP_O3, _AP_N3> &a2) { + return ap_concat_ref<_AP_WR, ap_concat_ref, 1, af_bit_ref<_AP_W3, + _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3> >(*this, + const_cast& >(a2)); + } + + template + INLINE ap_private + operator & (const ap_private<_AP_W3,_AP_S3>& a2) { + return get() & a2; + } + + + template + INLINE ap_private + operator | (const ap_private<_AP_W3,_AP_S3>& a2) { + return get() | a2; + } + + + template + INLINE ap_private + operator ^ (const ap_private<_AP_W3,_AP_S3>& a2) { + return ap_private(get() ^ a2); + } + + INLINE const ap_private<_AP_WR, false> get() const + { + ap_private<_AP_W1+_AP_W2, false> tmpVal = ap_private<_AP_W1+_AP_W2, false> (mbv1.get()); + ap_private<_AP_W1+_AP_W2, false> tmpVal2 = ap_private<_AP_W1+_AP_W2, false> (mbv2.get()); + int W_ref2 = mbv2.length(); + tmpVal <<= W_ref2; + tmpVal |= tmpVal2; + return tmpVal; + } + + INLINE const ap_private<_AP_WR, false> get() { + ap_private<_AP_W1+_AP_W2, false> tmpVal = ap_private<_AP_W1+_AP_W2, false> ( mbv1.get()); + ap_private<_AP_W1+_AP_W2, false> tmpVal2 = ap_private<_AP_W1+_AP_W2, false> (mbv2.get()); + int W_ref2 = mbv2.length(); + tmpVal <<= W_ref2; + tmpVal |= tmpVal2; + return tmpVal; + } + + template + INLINE void set(const ap_private<_AP_W3,false> & val) { + ap_private<_AP_W1+_AP_W2, false> vval(val); + int W_ref1=mbv1.length(); + int W_ref2=mbv2.length(); + ap_private<_AP_W1,false> mask1(-1); + mask1>>=_AP_W1-W_ref1; + ap_private<_AP_W2,false> mask2(-1); + mask2>>=_AP_W2-W_ref2; + mbv1.set(ap_private<_AP_W1,false>((vval>>W_ref2)&mask1)); + mbv2.set(ap_private<_AP_W2,false>(vval&mask2)); + } + + INLINE int length() const { + return mbv1.length()+mbv2.length(); + } + + INLINE std::string to_string(uint8_t radix=2) const { + return get().to_string(radix); + } +}; + +///Proxy class, which allows part selection to be used as rvalue(for reading) and +//lvalue(for writing) + +///Range(slice) reference +//------------------------------------------------------------ +template +struct ap_range_ref { +#ifdef _MSC_VER + #pragma warning( disable : 4521 4522 ) +#endif /* #ifdef _MSC_VER */ + ap_private<_AP_W,_AP_S> &d_bv; + int l_index; + int h_index; + +public: + INLINE ap_range_ref(const ap_range_ref<_AP_W, _AP_S>& ref): + d_bv(ref.d_bv), l_index(ref.l_index), h_index(ref.h_index) {} + + INLINE ap_range_ref(ap_private<_AP_W,_AP_S>* bv, int h, int l): + d_bv(*bv),l_index(l),h_index(h) { + //if (h < l) + //fprintf(stderr, "Warning! The bits selected will be returned in reverse order\n"); + } + + INLINE operator ap_private<_AP_W, false> () const { + ap_private<_AP_W, false> val(0); + if(h_index>=l_index) { + if (_AP_W > 64) { + val=d_bv; + ap_private<_AP_W,false> mask(-1); + mask>>=_AP_W-(h_index-l_index+1); + val>>=l_index; + val&=mask; + } else { + const static uint64_t mask = (~0ULL>> (64>_AP_W ? (64-_AP_W):0)); + val = (d_bv >> l_index) & (mask >>(_AP_W-(h_index-l_index+1))); + } + } else { + for(int i=0, j=l_index;j>=0&&j>=h_index;j--,i++) + if((d_bv)[j]) val.set(i); + } + return val; + } + + INLINE operator unsigned long long () const { + return to_uint64(); + } + + template + INLINE ap_range_ref& operator =(const ap_private<_AP_W2,_AP_S2>& val) { + ap_private<_AP_W,false> vval=ap_private<_AP_W,false>(val); + if (l_index>h_index) { + for (int i=0, j=l_index;j>=0&&j>=h_index;j--,i++) + (vval)[i]? d_bv.set(j):d_bv.clear(j); + } else { + if (_AP_W > 64) { + ap_private<_AP_W,false> mask(-1); + if (l_index>0) { + mask<<=l_index; + vval<<=l_index; + } + if(h_index<_AP_W-1) + { + ap_private<_AP_W,false> mask2(-1); + mask2>>=_AP_W-h_index-1; + mask&=mask2; + vval&=mask2; + } + mask.flip(); + d_bv&=mask; + d_bv|=vval; + } else { + unsigned shift = 64-_AP_W; + uint64_t mask = ~0ULL>>(shift); + if(l_index>0) + { + vval = mask & vval << l_index; + mask = mask & mask << l_index; + } + if(h_index<_AP_W-1) + { + uint64_t mask2 = mask; + mask2 >>= (_AP_W-h_index-1); + mask&=mask2; + vval&=mask2; + } + mask = ~mask; + d_bv&=mask; + d_bv|=vval; + } + } + return *this; + } + + INLINE ap_range_ref& operator = (unsigned long long val) + { + const ap_private<_AP_W,_AP_S> vval=val; + return operator = (vval); + } + + + INLINE ap_range_ref& operator =(const ap_range_ref<_AP_W, _AP_S>& val) + { + const ap_private<_AP_W, false> tmpVal(val); + return operator =(tmpVal); + } + + + + template + INLINE ap_range_ref& operator = + (const ap_concat_ref <_AP_W3, _AP_T3, _AP_W4, _AP_T4>& val) + { + const ap_private<_AP_W, false> tmpVal(val); + return operator = (tmpVal); + } + + template + INLINE ap_range_ref& operator =(const ap_range_ref<_AP_W3,_AP_S3>& val) + { + const ap_private<_AP_W, false> tmpVal(val); + return operator =(tmpVal); + } + + template + INLINE ap_range_ref& operator= (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& val) { + return operator=((const ap_private<_AP_W2, _AP_S2>)(val)); + } + + template + INLINE ap_range_ref& operator= (const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& val) { + return operator=(val.to_ap_private()); + } + + template + INLINE ap_range_ref& operator= (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& val) { + return operator=((unsigned long long)(bool)(val)); + } + + template + INLINE ap_range_ref& operator= (const ap_bit_ref<_AP_W2, _AP_S2>& val) { + return operator=((unsigned long long)(bool)(val)); + } + + template + INLINE + ap_concat_ref<_AP_W,ap_range_ref,_AP_W2,ap_range_ref<_AP_W2,_AP_S2> > + operator, (const ap_range_ref<_AP_W2,_AP_S2> &a2) + { + return + ap_concat_ref<_AP_W, ap_range_ref, _AP_W2, + ap_range_ref<_AP_W2,_AP_S2> >(*this, + const_cast& >(a2)); + } + + + template + INLINE ap_concat_ref<_AP_W,ap_range_ref,_AP_W2,ap_private<_AP_W2,_AP_S2> > + operator , (ap_private<_AP_W2,_AP_S2>& a2) + { + return + ap_concat_ref<_AP_W, ap_range_ref, _AP_W2, ap_private<_AP_W2,_AP_S2> >(*this, a2); + } + + INLINE ap_concat_ref<_AP_W,ap_range_ref,_AP_W,ap_private<_AP_W,_AP_S> > + operator , (ap_private<_AP_W, _AP_S>& a2) + { + return + ap_concat_ref<_AP_W, ap_range_ref, _AP_W, + ap_private<_AP_W,_AP_S> >(*this, a2); + } + + + + template + INLINE + ap_concat_ref<_AP_W,ap_range_ref,1,ap_bit_ref<_AP_W2,_AP_S2> > + operator, (const ap_bit_ref<_AP_W2,_AP_S2> &a2) + { + return + ap_concat_ref<_AP_W, ap_range_ref, 1, + ap_bit_ref<_AP_W2,_AP_S2> >(*this, const_cast& >(a2)); + } + + + template + INLINE + ap_concat_ref<_AP_W, ap_range_ref, _AP_W2+_AP_W3, ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > + operator, (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) + { + return ap_concat_ref<_AP_W, ap_range_ref, _AP_W2+_AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(*this, + const_cast& >(a2)); + } + + template + INLINE + ap_concat_ref<_AP_W, ap_range_ref, _AP_W2, af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<_AP_W, ap_range_ref, _AP_W2, af_range_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, + const_cast& >(a2)); + } + + template + INLINE + ap_concat_ref<_AP_W, ap_range_ref, 1, af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<_AP_W, ap_range_ref, 1, af_bit_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, + const_cast& >(a2)); + } + + template + INLINE bool operator == (const ap_range_ref<_AP_W2, _AP_S2>& op2) + { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs==rhs; + } + + + template + INLINE bool operator != (const ap_range_ref<_AP_W2, _AP_S2>& op2) + { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs!=rhs; + } + + + template + INLINE bool operator > (const ap_range_ref<_AP_W2, _AP_S2>& op2) + { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs>rhs; + } + + + template + INLINE bool operator >= (const ap_range_ref<_AP_W2, _AP_S2>& op2) + { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs>=rhs; + } + + + template + INLINE bool operator < (const ap_range_ref<_AP_W2, _AP_S2>& op2) + { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs + INLINE bool operator <= (const ap_range_ref<_AP_W2, _AP_S2>& op2) + { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs<=rhs; + } + + + template + INLINE void set(const ap_private<_AP_W2,false>& val) + { + ap_private<_AP_W,_AP_S> vval=val; + if(l_index>h_index) + { + for(int i=0, j=l_index;j>=0&&j>=h_index;j--,i++) + (vval)[i]? d_bv.set(j):d_bv.clear(j); + } else { + if (_AP_W>64 ) { + ap_private<_AP_W,_AP_S> mask(-1); + if(l_index>0) + { + ap_private<_AP_W,false> mask1(-1); + mask1>>=_AP_W-l_index; + mask1.flip(); + mask=mask1; + //vval&=mask1; + vval<<=l_index; + } + if(h_index<_AP_W-1) + { + ap_private<_AP_W,false> mask2(-1); + mask2<<=h_index+1; + mask2.flip(); + mask&=mask2; + vval&=mask2; + } + mask.flip(); + d_bv&=mask; + d_bv|=vval; + } else { + uint64_t mask = ~0ULL >> (64-_AP_W); + if(l_index>0) + { + uint64_t mask1 = mask; + mask1=mask & (mask1>>(_AP_W-l_index)); + vval =mask&( vval <> (64-_AP_W); + mask2 = mask &(mask2<<(h_index+1)); + mask&=~mask2; + vval&=~mask2; + } + d_bv&=(~mask&(~0ULL >> (64-_AP_W))); + d_bv|=vval; + } + } + } + + + INLINE ap_private<_AP_W,false> get() const + { + ap_private<_AP_W,false> val(0); + if(h_index=0&&j>=h_index;j--,i++) + if((d_bv)[j]) val.set(i); + } else { + val=d_bv; + val>>=l_index; + if(h_index<_AP_W-1) + { + if (_AP_W <= 64) { + const static uint64_t mask = (~0ULL>> (64>_AP_W ? (64-_AP_W):0)); + val &= (mask>> (_AP_W-(h_index-l_index+1))); + } else { + ap_private<_AP_W,false> mask(-1); + mask>>=_AP_W-(h_index-l_index+1); + val&=mask; + } + } + } + return val; + } + + + INLINE ap_private<_AP_W,false> get() + { + ap_private<_AP_W,false> val(0); + if(h_index=0&&j>=h_index;j--,i++) + if((d_bv)[j]) val.set(i); + } else { + val=d_bv; + val>>=l_index; + if(h_index<_AP_W-1) + { + if (_AP_W <= 64 ) { + static const uint64_t mask = ~0ULL>> (64>_AP_W ? (64-_AP_W):0); + return val &= ( (mask) >> (_AP_W - (h_index-l_index+1))); + } else { + ap_private<_AP_W,false> mask(-1); + mask>>=_AP_W-(h_index-l_index+1); + val&=mask; + } + } + } + return val; + } + + + INLINE int length() const + { + return h_index>=l_index?h_index-l_index+1:l_index-h_index+1; + } + + + INLINE int to_int() const + { + ap_private<_AP_W,false> val=get(); + return val.to_int(); + } + + + INLINE unsigned int to_uint() const + { + ap_private<_AP_W,false> val=get(); + return val.to_uint(); + } + + + INLINE long to_long() const + { + ap_private<_AP_W,false> val=get(); + return val.to_long(); + } + + + INLINE unsigned long to_ulong() const + { + ap_private<_AP_W,false> val=get(); + return val.to_ulong(); + } + + + INLINE ap_slong to_int64() const + { + ap_private<_AP_W,false> val=get(); + return val.to_int64(); + } + + + INLINE ap_ulong to_uint64() const + { + ap_private<_AP_W,false> val=get(); + return val.to_uint64(); + } + + INLINE std::string to_string(uint8_t radix=2) const { + return get().to_string(radix); + } + +}; + +///Proxy class, which allows bit selection to be used as rvalue(for reading) and +//lvalue(for writing) + +///Bit reference +//-------------------------------------------------------------- +template +struct ap_bit_ref { +#ifdef _MSC_VER +#pragma warning( disable : 4521 4522 ) +#endif + ap_private<_AP_W,_AP_S>& d_bv; + int d_index; + +public: + INLINE ap_bit_ref(const ap_bit_ref<_AP_W, _AP_S>& ref): + d_bv(ref.d_bv), d_index(ref.d_index) {} + + INLINE ap_bit_ref(ap_private<_AP_W,_AP_S>& bv, int index=0): + d_bv(bv),d_index(index) + { +#ifdef _AP_DEBUG_ + assert(d_index<_AP_W&&"index out of bound"); +#endif + } + + + INLINE operator bool () const + { + return d_bv.get_bit(d_index); + } + + + INLINE bool to_bool() const + { + return operator bool (); + } + + + INLINE ap_bit_ref& operator = (unsigned long long val) + { + if(val) + d_bv.set(d_index); + else + d_bv.clear(d_index); + return *this; + } + + +#if 0 + INLINE ap_bit_ref& operator = (bool val) + { + if(val) + d_bv.set(d_index); + else + d_bv.clear(d_index); + return *this; + } +#endif + template + INLINE ap_bit_ref& operator =(const ap_private<_AP_W2,_AP_S2>& val) + { + return operator =((unsigned long long)(val != 0)); + } + + + template + INLINE ap_bit_ref& operator =(const ap_bit_ref<_AP_W2,_AP_S2>& val) + { + return operator =((unsigned long long)(bool)val); + } + + INLINE ap_bit_ref& operator =(const ap_bit_ref<_AP_W,_AP_S>& val) + { + return operator =((unsigned long long)(bool)val); + } + + template + INLINE ap_bit_ref& operator =(const ap_range_ref<_AP_W2,_AP_S2>& val) + { + return operator =((unsigned long long)(bool) val); + } + + + template + INLINE ap_bit_ref& operator= (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& val) { + return operator=((const ap_private<_AP_W2, false>)(val)); + } + + template + INLINE ap_bit_ref& operator= (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& val) { + return operator=((unsigned long long)(bool)(val)); + } + + template + INLINE ap_bit_ref& operator= (const ap_concat_ref<_AP_W2, _AP_T3, _AP_W3, _AP_T3>& val) { + return operator=((const ap_private<_AP_W2 + _AP_W3, false>)(val)); + } + + + + template + INLINE ap_concat_ref<1, ap_bit_ref, _AP_W2, ap_private<_AP_W2,_AP_S2> > + operator , (ap_private<_AP_W2, _AP_S2>& a2) + { + return ap_concat_ref<1, ap_bit_ref, _AP_W2, ap_private<_AP_W2,_AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<1, ap_bit_ref, _AP_W2, ap_range_ref<_AP_W2,_AP_S2> > + operator, (const ap_range_ref<_AP_W2, _AP_S2> &a2) + { + return + ap_concat_ref<1, ap_bit_ref, _AP_W2, ap_range_ref<_AP_W2,_AP_S2> >(*this, + const_cast &>(a2)); + } + + + template + INLINE ap_concat_ref<1, ap_bit_ref, 1, ap_bit_ref<_AP_W2,_AP_S2> > + operator, (const ap_bit_ref<_AP_W2, _AP_S2> &a2) + { + return + ap_concat_ref<1, ap_bit_ref, 1, ap_bit_ref<_AP_W2,_AP_S2> >(*this, + const_cast &>(a2)); + } + + + INLINE ap_concat_ref<1, ap_bit_ref, 1, ap_bit_ref > + operator, (const ap_bit_ref &a2) + { + return + ap_concat_ref<1, ap_bit_ref, 1, ap_bit_ref >(*this, + const_cast(a2)); + } + + + template + INLINE ap_concat_ref<1, ap_bit_ref, _AP_W2+_AP_W3, ap_concat_ref<_AP_W2,_AP_T2,_AP_W3,_AP_T3> > + operator, (const ap_concat_ref<_AP_W2,_AP_T2,_AP_W3,_AP_T3> &a2) + { + return + ap_concat_ref<1,ap_bit_ref,_AP_W2+_AP_W3, + ap_concat_ref<_AP_W2,_AP_T2,_AP_W3,_AP_T3> >(*this, + const_cast& >(a2)); + } + + template + INLINE + ap_concat_ref<1, ap_bit_ref, _AP_W2, af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<1, ap_bit_ref, _AP_W2, af_range_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, + const_cast& >(a2)); + } + + template + INLINE + ap_concat_ref<1, ap_bit_ref, 1, af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<1, ap_bit_ref, 1, af_bit_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, + const_cast& >(a2)); + } + + template + INLINE bool operator == (const ap_bit_ref<_AP_W2, _AP_S2>& op) { + return get() == op.get(); + } + + template + INLINE bool operator != (const ap_bit_ref<_AP_W2, _AP_S2>& op) { + return get() != op.get(); + } + + + INLINE bool get() const + { + return operator bool (); + } + + + INLINE bool get() + { + return operator bool (); + } + + + template + INLINE void set(const ap_private<_AP_W3, false>& val) + { + operator = (val); + } + + INLINE bool operator ~ () const { + bool bit = (d_bv)[d_index]; + return bit ? false : true; + } + + INLINE int length() const { return 1; } + + INLINE std::string to_string() const { + bool val = get(); + return val ? "1" : "0"; + } +}; + +/// Operators mixing Integers with AP_Int +// ---------------------------------------------------------------- +#if 1 +#define OP_BIN_MIX_INT(BIN_OP, C_TYPE, _AP_WI, _AP_SI, RTYPE) \ + template \ + INLINE typename ap_private<_AP_WI,_AP_SI>::template RType<_AP_W,_AP_S>::RTYPE \ + operator BIN_OP ( C_TYPE i_op, const ap_private<_AP_W,_AP_S> &op) { \ + return ap_private<_AP_WI,_AP_SI>(i_op).operator BIN_OP (op); \ + } \ + template \ + INLINE typename ap_private<_AP_W,_AP_S>::template RType<_AP_WI,_AP_SI>::RTYPE \ + operator BIN_OP ( const ap_private<_AP_W,_AP_S> &op, C_TYPE i_op) { \ + return op.operator BIN_OP (ap_private<_AP_WI,_AP_SI>(i_op)); \ + } +#else +#define OP_BIN_MIX_INT(BIN_OP, C_TYPE, _AP_WI, _AP_SI, RTYPE) \ + template \ + INLINE typename ap_private<_AP_WI,_AP_SI>::template RType<_AP_W,_AP_S>::RTYPE \ + operator BIN_OP ( C_TYPE i_op, const ap_private<_AP_W,_AP_S> &op) { \ + return ap_private<_AP_WI,_AP_SI>(i_op).operator BIN_OP (op); \ + } \ + template \ + INLINE typename ap_private<_AP_W,_AP_S>::template RType<_AP_WI,_AP_SI>::RTYPE \ + operator BIN_OP ( const ap_private<_AP_W,_AP_S> &op, C_TYPE i_op) { \ + return op.operator BIN_OP (ap_private<_AP_WI,_AP_SI>(i_op)); \ + } +#endif +#define OP_REL_MIX_INT(REL_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE bool operator REL_OP ( const ap_private<_AP_W,_AP_S> &op, C_TYPE op2) { \ + return op.operator REL_OP (ap_private<_AP_W2, _AP_S2>(op2)); \ + } \ + template \ + INLINE bool operator REL_OP ( C_TYPE op2, const ap_private<_AP_W,_AP_S> &op) { \ + return ap_private<_AP_W2,_AP_S2>(op2).operator REL_OP (op); \ + } +#define OP_ASSIGN_MIX_INT(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE ap_private<_AP_W,_AP_S> &operator ASSIGN_OP ( ap_private<_AP_W,_AP_S> &op, C_TYPE op2) { \ + return op.operator ASSIGN_OP (ap_private<_AP_W2,_AP_S2>(op2)); \ + } + +#define OP_BIN_SHIFT_INT(BIN_OP, C_TYPE, _AP_WI, _AP_SI, RTYPE) \ + template \ + C_TYPE operator BIN_OP ( C_TYPE i_op, const ap_private<_AP_W,_AP_S> &op) { \ + return i_op BIN_OP (op.getVal()); \ + } \ + template \ + INLINE typename ap_private<_AP_W,_AP_S>::template RType<_AP_WI,_AP_SI>::RTYPE \ + operator BIN_OP ( const ap_private<_AP_W,_AP_S> &op, C_TYPE i_op) { \ + return op.operator BIN_OP (i_op); \ + } +#define OP_ASSIGN_RSHIFT_INT(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE ap_private<_AP_W,_AP_S> &operator ASSIGN_OP ( ap_private<_AP_W,_AP_S> &op, C_TYPE op2) { \ + op = op.operator >> (op2); \ + return op; \ + } +#define OP_ASSIGN_LSHIFT_INT(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE ap_private<_AP_W,_AP_S> &operator ASSIGN_OP ( ap_private<_AP_W,_AP_S> &op, C_TYPE op2) { \ + op = op.operator << (op2); \ + return op; \ + } + +#define OPS_MIX_INT(C_TYPE, WI, SI) \ + OP_BIN_MIX_INT(*, C_TYPE, WI, SI, mult) \ + OP_BIN_MIX_INT(+, C_TYPE, WI, SI, plus) \ + OP_BIN_MIX_INT(-, C_TYPE, WI, SI, minus) \ + OP_BIN_MIX_INT(/, C_TYPE, WI, SI, div) \ + OP_BIN_MIX_INT(%, C_TYPE, WI, SI, mod) \ + OP_BIN_MIX_INT(&, C_TYPE, WI, SI, logic) \ + OP_BIN_MIX_INT(|, C_TYPE, WI, SI, logic) \ + OP_BIN_MIX_INT(^, C_TYPE, WI, SI, logic) \ + OP_BIN_SHIFT_INT(>>, C_TYPE, WI, SI, arg1) \ + OP_BIN_SHIFT_INT(<<, C_TYPE, WI, SI, arg1) \ + \ + OP_REL_MIX_INT(==, C_TYPE, WI, SI) \ + OP_REL_MIX_INT(!=, C_TYPE, WI, SI) \ + OP_REL_MIX_INT(>, C_TYPE, WI, SI) \ + OP_REL_MIX_INT(>=, C_TYPE, WI, SI) \ + OP_REL_MIX_INT(<, C_TYPE, WI, SI) \ + OP_REL_MIX_INT(<=, C_TYPE, WI, SI) \ + \ + OP_ASSIGN_MIX_INT(+=, C_TYPE, WI, SI) \ + OP_ASSIGN_MIX_INT(-=, C_TYPE, WI, SI) \ + OP_ASSIGN_MIX_INT(*=, C_TYPE, WI, SI) \ + OP_ASSIGN_MIX_INT(/=, C_TYPE, WI, SI) \ + OP_ASSIGN_MIX_INT(%=, C_TYPE, WI, SI) \ + OP_ASSIGN_MIX_INT(&=, C_TYPE, WI, SI) \ + OP_ASSIGN_MIX_INT(|=, C_TYPE, WI, SI) \ + OP_ASSIGN_MIX_INT(^=, C_TYPE, WI, SI) \ + OP_ASSIGN_RSHIFT_INT(>>=, C_TYPE, WI, SI) \ + OP_ASSIGN_LSHIFT_INT(<<=, C_TYPE, WI, SI) + + +OPS_MIX_INT(bool, 1, false) +OPS_MIX_INT(char, 8, true) +OPS_MIX_INT(signed char, 8, true) +OPS_MIX_INT(unsigned char, 8, false) +OPS_MIX_INT(short, 16, true) +OPS_MIX_INT(unsigned short, 16, false) +OPS_MIX_INT(int, 32, true) +OPS_MIX_INT(unsigned int, 32, false) +# if defined __x86_64__ +OPS_MIX_INT(long, 64, true) +OPS_MIX_INT(unsigned long, 64, false) +# else +OPS_MIX_INT(long, 32, true) +OPS_MIX_INT(unsigned long, 32, false) +# endif +OPS_MIX_INT(ap_slong, 64, true) +OPS_MIX_INT(ap_ulong, 64, false) + +#define OP_BIN_MIX_RANGE(BIN_OP, RTYPE) \ + template \ + INLINE typename ap_private<_AP_W1,_AP_S1>::template RType<_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP ( const ap_range_ref<_AP_W1,_AP_S1>& op1, const ap_private<_AP_W2,_AP_S2>& op2) { \ + return ap_private<_AP_W1, false>(op1).operator BIN_OP (op2); \ + } \ + template \ + INLINE typename ap_private<_AP_W1,_AP_S1>::template RType<_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP ( const ap_private<_AP_W1,_AP_S1>& op1, const ap_range_ref<_AP_W2,_AP_S2>& op2) { \ + return op1.operator BIN_OP (ap_private<_AP_W2, false>(op2)); \ + } + +#define OP_REL_MIX_RANGE(REL_OP) \ + template \ + INLINE bool operator REL_OP ( const ap_range_ref<_AP_W1,_AP_S1>& op1, const ap_private<_AP_W2,_AP_S2>& op2) { \ + return ap_private<_AP_W1,false>(op1).operator REL_OP (op2); \ + } \ + template \ + INLINE bool operator REL_OP ( const ap_private<_AP_W1,_AP_S1>& op1, const ap_range_ref<_AP_W2,_AP_S2>& op2) { \ + return op1.operator REL_OP (op2.operator ap_private<_AP_W2, false>()); \ + } + +#define OP_ASSIGN_MIX_RANGE(ASSIGN_OP) \ + template \ + INLINE ap_private<_AP_W1,_AP_S1>& operator ASSIGN_OP ( ap_private<_AP_W1,_AP_S1>& op1, const ap_range_ref<_AP_W2,_AP_S2>& op2) { \ + return op1.operator ASSIGN_OP (ap_private<_AP_W2, false>(op2)); \ + } \ + template \ + INLINE ap_range_ref<_AP_W1,_AP_S1>& operator ASSIGN_OP (ap_range_ref<_AP_W1,_AP_S1>& op1, ap_private<_AP_W2,_AP_S2>& op2) { \ + ap_private<_AP_W1, false> tmp(op1); \ + tmp.operator ASSIGN_OP (op2); \ + op1 = tmp; \ + return op1; \ + } + + +OP_ASSIGN_MIX_RANGE(+=) +OP_ASSIGN_MIX_RANGE(-=) +OP_ASSIGN_MIX_RANGE(*=) +OP_ASSIGN_MIX_RANGE(/=) +OP_ASSIGN_MIX_RANGE(%=) +OP_ASSIGN_MIX_RANGE(>>=) +OP_ASSIGN_MIX_RANGE(<<=) +OP_ASSIGN_MIX_RANGE(&=) +OP_ASSIGN_MIX_RANGE(|=) +OP_ASSIGN_MIX_RANGE(^=) + +OP_REL_MIX_RANGE(==) +OP_REL_MIX_RANGE(!=) +OP_REL_MIX_RANGE(>) +OP_REL_MIX_RANGE(>=) +OP_REL_MIX_RANGE(<) +OP_REL_MIX_RANGE(<=) + +OP_BIN_MIX_RANGE(+, plus) +OP_BIN_MIX_RANGE(-, minus) +OP_BIN_MIX_RANGE(*, mult) +OP_BIN_MIX_RANGE(/, div) +OP_BIN_MIX_RANGE(%, mod) +OP_BIN_MIX_RANGE(>>, arg1) +OP_BIN_MIX_RANGE(<<, arg1) +OP_BIN_MIX_RANGE(&, logic) +OP_BIN_MIX_RANGE(|, logic) +OP_BIN_MIX_RANGE(^, logic) + +#define OP_BIN_MIX_BIT(BIN_OP, RTYPE) \ + template \ + INLINE typename ap_private<1, false>::template RType<_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP ( const ap_bit_ref<_AP_W1,_AP_S1>& op1, const ap_private<_AP_W2,_AP_S2>& op2) { \ + return ap_private<1, false>(op1).operator BIN_OP (op2); \ + } \ + template \ + INLINE typename ap_private<_AP_W1,_AP_S1>::template RType<1,false>::RTYPE \ + operator BIN_OP ( const ap_private<_AP_W1,_AP_S1>& op1, const ap_bit_ref<_AP_W2,_AP_S2>& op2) { \ + return op1.operator BIN_OP (ap_private<1, false>(op2)); \ + } + +#define OP_REL_MIX_BIT(REL_OP) \ + template \ + INLINE bool operator REL_OP ( const ap_bit_ref<_AP_W1,_AP_S1>& op1, const ap_private<_AP_W2,_AP_S2>& op2) { \ + return ap_private<_AP_W1,false>(op1).operator REL_OP (op2); \ + } \ + template \ + INLINE bool operator REL_OP ( const ap_private<_AP_W1,_AP_S1>& op1, const ap_bit_ref<_AP_W2,_AP_S2>& op2) { \ + return op1.operator REL_OP (ap_private<1, false>(op2)); \ + } + +#define OP_ASSIGN_MIX_BIT(ASSIGN_OP) \ + template \ + INLINE ap_private<_AP_W1,_AP_S1>& operator ASSIGN_OP ( ap_private<_AP_W1,_AP_S1>& op1, ap_bit_ref<_AP_W2,_AP_S2>& op2) { \ + return op1.operator ASSIGN_OP (ap_private<1, false>(op2)); \ + } \ + template \ + INLINE ap_bit_ref<_AP_W1,_AP_S1>& operator ASSIGN_OP ( ap_bit_ref<_AP_W1,_AP_S1>& op1, ap_private<_AP_W2,_AP_S2>& op2) { \ + ap_private<1, false> tmp(op1); \ + tmp.operator ASSIGN_OP (op2); \ + op1 = tmp; \ + return op1; \ + } + + +OP_ASSIGN_MIX_BIT(+=) +OP_ASSIGN_MIX_BIT(-=) +OP_ASSIGN_MIX_BIT(*=) +OP_ASSIGN_MIX_BIT(/=) +OP_ASSIGN_MIX_BIT(%=) +OP_ASSIGN_MIX_BIT(>>=) +OP_ASSIGN_MIX_BIT(<<=) +OP_ASSIGN_MIX_BIT(&=) +OP_ASSIGN_MIX_BIT(|=) +OP_ASSIGN_MIX_BIT(^=) + +OP_REL_MIX_BIT(==) +OP_REL_MIX_BIT(!=) +OP_REL_MIX_BIT(>) +OP_REL_MIX_BIT(>=) +OP_REL_MIX_BIT(<) +OP_REL_MIX_BIT(<=) + +OP_BIN_MIX_BIT(+, plus) +OP_BIN_MIX_BIT(-, minus) +OP_BIN_MIX_BIT(*, mult) +OP_BIN_MIX_BIT(/, div) +OP_BIN_MIX_BIT(%, mod) +OP_BIN_MIX_BIT(>>, arg1) +OP_BIN_MIX_BIT(<<, arg1) +OP_BIN_MIX_BIT(&, logic) +OP_BIN_MIX_BIT(|, logic) +OP_BIN_MIX_BIT(^, logic) + +#define REF_REL_OP_MIX_INT(REL_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE bool operator REL_OP ( const ap_range_ref<_AP_W,_AP_S> &op, C_TYPE op2) { \ + return (ap_private<_AP_W, false>(op)).operator REL_OP (ap_private<_AP_W2,_AP_S2>(op2)); \ + } \ + template \ + INLINE bool operator REL_OP ( C_TYPE op2, const ap_range_ref<_AP_W,_AP_S> &op) { \ + return ap_private<_AP_W2,_AP_S2>(op2).operator REL_OP (ap_private<_AP_W, false>(op)); \ + } \ + template \ + INLINE bool operator REL_OP ( const ap_bit_ref<_AP_W,_AP_S> &op, C_TYPE op2) { \ + return (bool(op)) REL_OP op2; \ + } \ + template \ + INLINE bool operator REL_OP ( C_TYPE op2, const ap_bit_ref<_AP_W,_AP_S> &op) { \ + return op2 REL_OP (bool(op)); \ + } \ + template \ + INLINE bool operator REL_OP ( const ap_concat_ref<_AP_W,_AP_T, _AP_W1, _AP_T1> &op, C_TYPE op2) { \ + return (ap_private<_AP_W + _AP_W1, false>(op)).operator REL_OP (ap_private<_AP_W2,_AP_S2>(op2)); \ + } \ + template \ + INLINE bool operator REL_OP ( C_TYPE op2, const ap_concat_ref<_AP_W,_AP_T, _AP_W1, _AP_T1> &op) { \ + return ap_private<_AP_W2,_AP_S2>(op2).operator REL_OP (ap_private<_AP_W + _AP_W1, false>(op)); \ + } + +#define REF_REL_MIX_INT(C_TYPE, _AP_WI, _AP_SI) \ +REF_REL_OP_MIX_INT(>, C_TYPE, _AP_WI, _AP_SI) \ +REF_REL_OP_MIX_INT(<, C_TYPE, _AP_WI, _AP_SI) \ +REF_REL_OP_MIX_INT(>=, C_TYPE, _AP_WI, _AP_SI) \ +REF_REL_OP_MIX_INT(<=, C_TYPE, _AP_WI, _AP_SI) \ +REF_REL_OP_MIX_INT(==, C_TYPE, _AP_WI, _AP_SI) \ +REF_REL_OP_MIX_INT(!=, C_TYPE, _AP_WI, _AP_SI) + +REF_REL_MIX_INT(bool, 1, false) +REF_REL_MIX_INT(char, 8, true) +REF_REL_MIX_INT(signed char, 8, true) +REF_REL_MIX_INT(unsigned char, 8, false) +REF_REL_MIX_INT(short, 16, true) +REF_REL_MIX_INT(unsigned short, 16, false) +REF_REL_MIX_INT(int, 32, true) +REF_REL_MIX_INT(unsigned int, 32, false) +# if defined __x86_64__ +REF_REL_MIX_INT(long, 64, true) +REF_REL_MIX_INT(unsigned long, 64, false) +# else +REF_REL_MIX_INT(long, 32, true) +REF_REL_MIX_INT(unsigned long, 32, false) +# endif +REF_REL_MIX_INT(ap_slong, 64, true) +REF_REL_MIX_INT(ap_ulong, 64, false) + +#define REF_BIN_OP_MIX_INT(BIN_OP, RTYPE, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE typename ap_private<_AP_W, false>::template RType<_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP ( const ap_range_ref<_AP_W,_AP_S> &op, C_TYPE op2) { \ + return (ap_private<_AP_W, false>(op)).operator BIN_OP (ap_private<_AP_W2,_AP_S2>(op2)); \ + } \ + template \ + INLINE typename ap_private<_AP_W2, _AP_S2>::template RType<_AP_W,false>::RTYPE \ + operator BIN_OP ( C_TYPE op2, const ap_range_ref<_AP_W,_AP_S> &op) { \ + return ap_private<_AP_W2,_AP_S2>(op2).operator BIN_OP (ap_private<_AP_W, false>(op)); \ + } + +#define REF_BIN_MIX_INT(C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(+, plus, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(-, minus, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(*, mult, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(/, div, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(%, mod, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(>>, arg1, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(<<, arg1, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(&, logic, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(|, logic, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(^, logic, C_TYPE, _AP_WI, _AP_SI) + +REF_BIN_MIX_INT(bool, 1, false) +REF_BIN_MIX_INT(char, 8, true) +REF_BIN_MIX_INT(signed char, 8, true) +REF_BIN_MIX_INT(unsigned char, 8, false) +REF_BIN_MIX_INT(short, 16, true) +REF_BIN_MIX_INT(unsigned short, 16, false) +REF_BIN_MIX_INT(int, 32, true) +REF_BIN_MIX_INT(unsigned int, 32, false) +# if defined __x86_64__ +REF_BIN_MIX_INT(long, 64, true) +REF_BIN_MIX_INT(unsigned long, 64, false) +#else +REF_BIN_MIX_INT(long, 32, true) +REF_BIN_MIX_INT(unsigned long, 32, false) +#endif +REF_BIN_MIX_INT(ap_slong, 64, true) +REF_BIN_MIX_INT(ap_ulong, 64, false) + +#define REF_BIN_OP(BIN_OP, RTYPE) \ +template \ +INLINE typename ap_private<_AP_W, false>::template RType<_AP_W2, false>::RTYPE \ +operator BIN_OP (const ap_range_ref<_AP_W,_AP_S> &lhs, const ap_range_ref<_AP_W2,_AP_S2> &rhs) { \ + return ap_private<_AP_W,false>(lhs).operator BIN_OP (ap_private<_AP_W2, false>(rhs)); \ +} + +REF_BIN_OP(+, plus) +REF_BIN_OP(-, minus) +REF_BIN_OP(*, mult) +REF_BIN_OP(/, div) +REF_BIN_OP(%, mod) +REF_BIN_OP(>>, arg1) +REF_BIN_OP(<<, arg1) +REF_BIN_OP(&, logic) +REF_BIN_OP(|, logic) +REF_BIN_OP(^, logic) + +#if 1 +#define CONCAT_OP_MIX_INT(C_TYPE, _AP_WI, _AP_SI) \ +template \ +INLINE \ +ap_private< _AP_W + _AP_WI, false > \ + operator, (const ap_private<_AP_W, _AP_S> &op1, C_TYPE op2) { \ + ap_private<_AP_WI + _AP_W, false> val(op2); \ + ap_private<_AP_WI + _AP_W, false> ret(op1); \ + ret <<= _AP_WI; \ + if (_AP_SI) { \ + val <<= _AP_W; val >>= _AP_W; \ + }\ + ret |= val; \ + return ret;\ +} \ +template \ +INLINE \ +ap_private< _AP_W + _AP_WI, false > \ + operator, (C_TYPE op1, const ap_private<_AP_W, _AP_S>& op2) { \ + ap_private<_AP_WI + _AP_W, false> val(op1); \ + ap_private<_AP_WI + _AP_W, false> ret(op2); \ + if (_AP_S) { \ + ret <<= _AP_WI; ret >>= _AP_WI; \ + } \ + ret |= val << _AP_W; \ + return ret; \ +} \ +template \ +INLINE \ +ap_private< _AP_W + _AP_WI, false > \ + operator, (const ap_range_ref<_AP_W, _AP_S> &op1, C_TYPE op2) { \ + ap_private<_AP_WI + _AP_W, false> val(op2); \ + ap_private<_AP_WI + _AP_W, false> ret(op1); \ + ret <<= _AP_WI; \ + if (_AP_SI) { \ + val <<= _AP_W; val >>= _AP_W; \ + } \ + ret |= val; \ + return ret; \ +} \ +template \ +INLINE \ +ap_private< _AP_W + _AP_WI, false > \ + operator, (C_TYPE op1, const ap_range_ref<_AP_W, _AP_S> &op2) { \ + ap_private<_AP_WI + _AP_W, false> val(op1); \ + ap_private<_AP_WI + _AP_W, false> ret(op2); \ + int len = op2.length(); \ + val <<= len; \ + ret |= val; \ + return ret; \ +} \ +template \ +INLINE \ +ap_private<_AP_WI + 1, false > \ + operator, (const ap_bit_ref<_AP_W, _AP_S> &op1, C_TYPE op2) { \ + ap_private<_AP_WI + 1, false> val(op2); \ + val[_AP_WI] = op1; \ + return val; \ +} \ +template \ +INLINE \ +ap_private<_AP_WI + 1, false > \ + operator, (C_TYPE op1, const ap_bit_ref<_AP_W, _AP_S> &op2) { \ + ap_private<_AP_WI + 1, false> val(op1); \ + val <<= 1; \ + val[0] = op2; \ + return val; \ +} \ +template \ +INLINE \ +ap_private<_AP_W + _AP_W2 + _AP_WI, false > \ + operator, (const ap_concat_ref<_AP_W, _AP_T, _AP_W2, _AP_T2> &op1, C_TYPE op2) {\ + ap_private<_AP_WI + _AP_W + _AP_W2, _AP_SI> val(op2);\ + ap_private<_AP_WI + _AP_W + _AP_W2, _AP_SI> ret(op1);\ + if (_AP_SI) { \ + val <<= _AP_W + _AP_W2; val >>= _AP_W + _AP_W2; \ + } \ + ret <<= _AP_WI; \ + ret |= val; \ + return ret; \ +}\ +template \ +INLINE \ +ap_private<_AP_W + _AP_W2 + _AP_WI, false > \ + operator, (C_TYPE op1, const ap_concat_ref<_AP_W, _AP_T, _AP_W2, _AP_T2> &op2) {\ + ap_private<_AP_WI + _AP_W + _AP_W2, _AP_SI> val(op1);\ + ap_private<_AP_WI + _AP_W + _AP_W2, _AP_SI> ret(op2);\ + int len = op2.length(); \ + val <<= len; \ + ret |= val;\ + return ret; \ +}\ +template \ +INLINE \ +ap_private< _AP_W + _AP_WI, false > \ + operator, (const af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op1, C_TYPE op2) { \ + ap_private<_AP_WI + _AP_W, false> val(op2); \ + ap_private<_AP_WI + _AP_W, false> ret(op1); \ + if (_AP_SI) { \ + val <<= _AP_W; val >>= _AP_W; \ + }\ + ret <<= _AP_WI; \ + ret |= val; \ + return ret; \ +} \ +template \ +INLINE \ +ap_private< _AP_W + _AP_WI, false > \ + operator, (C_TYPE op1, const af_range_ref<_AP_W, _AP_I, _AP_S, \ + _AP_Q, _AP_O, _AP_N> &op2) { \ + ap_private<_AP_WI + _AP_W, false> val(op1); \ + ap_private<_AP_WI + _AP_W, false> ret(op2); \ + int len = op2.length(); \ + val <<= len; \ + ret |= val; \ + return ret; \ +} \ +template \ +INLINE \ +ap_private< 1 + _AP_WI, false> \ + operator, (const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, \ + _AP_N> &op1, C_TYPE op2) { \ + ap_private<_AP_WI + 1, _AP_SI> val(op2); \ + val[_AP_WI] = op1; \ + return val; \ +} \ +template \ +INLINE \ +ap_private< 1 + _AP_WI, false> \ + operator, (C_TYPE op1, const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q,\ + _AP_O, _AP_N> &op2) { \ + ap_private<_AP_WI + 1, _AP_SI> val(op1); \ + val <<= 1; \ + val[0] = op2; \ + return val; \ +} + +CONCAT_OP_MIX_INT(bool, 1, false) +CONCAT_OP_MIX_INT(char, 8, true) +CONCAT_OP_MIX_INT(signed char, 8, true) +CONCAT_OP_MIX_INT(unsigned char, 8, false) +CONCAT_OP_MIX_INT(short, 16, true) +CONCAT_OP_MIX_INT(unsigned short, 16, false) +CONCAT_OP_MIX_INT(int, 32, true) +CONCAT_OP_MIX_INT(unsigned int, 32, false) +# if defined __x86_64__ +CONCAT_OP_MIX_INT(long, 64, true) +CONCAT_OP_MIX_INT(unsigned long, 64, false) +# else +CONCAT_OP_MIX_INT(long, 32, true) +CONCAT_OP_MIX_INT(unsigned long, 32, false) +# endif +CONCAT_OP_MIX_INT(ap_slong, 64, true) +CONCAT_OP_MIX_INT(ap_ulong, 64, false) +#endif + +#if 1 +#define CONCAT_SHIFT_MIX_INT(C_TYPE, op) \ +template \ +INLINE ap_uint<_AP_W+_AP_W1> operator op (const ap_concat_ref<_AP_W, _AP_T, _AP_W1, _AP_T1> lhs, C_TYPE rhs) { \ + return ((ap_uint<_AP_W+_AP_W1>)lhs.get()) op ((int)rhs); \ +} + +CONCAT_SHIFT_MIX_INT(long, <<) +CONCAT_SHIFT_MIX_INT(unsigned long, <<) +CONCAT_SHIFT_MIX_INT(unsigned int, <<) +CONCAT_SHIFT_MIX_INT(ap_ulong, <<) +CONCAT_SHIFT_MIX_INT(ap_slong, <<) +CONCAT_SHIFT_MIX_INT(long, >>) +CONCAT_SHIFT_MIX_INT(unsigned long, >>) +CONCAT_SHIFT_MIX_INT(unsigned int, >>) +CONCAT_SHIFT_MIX_INT(ap_ulong, >>) +CONCAT_SHIFT_MIX_INT(ap_slong, >>) +#endif + +#if defined(SYSTEMC_H) || defined(SYSTEMC_INCLUDED) +template +INLINE void sc_trace(sc_core::sc_trace_file *tf, const ap_private<_AP_W, _AP_S> &op, + const std::string &name) { + if (tf) + tf->trace(sc_dt::sc_lv<_AP_W>(op.to_string(2).c_str()), name); +} +#endif + +template +INLINE std::ostream& operator<<(std::ostream& out, const ap_private<_AP_W,_AP_S> &op) +{ + ap_private<_AP_W, _AP_S> v=op; + const std::ios_base::fmtflags basefield = out.flags() & std::ios_base::basefield; + unsigned radix = (basefield == std::ios_base::hex) ? 16 : + ((basefield == std::ios_base::oct) ? 8 : 10); + std::string str=v.toString(radix,_AP_S); + out< +INLINE std::istream& operator >> (std::istream& in, ap_private<_AP_W,_AP_S> &op) +{ + std::string str; + in >> str; + op = ap_private<_AP_W, _AP_S>(str.c_str()); + return in; + +} + +template +INLINE std::ostream& operator<<(std::ostream& out, const ap_range_ref<_AP_W,_AP_S> &op) +{ + return operator<<(out, ap_private<_AP_W, _AP_S>(op)); +} + +template +INLINE std::istream& operator >> (std::istream& in, ap_range_ref<_AP_W,_AP_S> &op) +{ + return operator>>(in, ap_private<_AP_W, _AP_S>(op));; +} + +template +INLINE void print(const ap_private<_AP_W,_AP_S> &op, bool fill=true ) +{ + ap_private<_AP_W, _AP_S> v=op; + uint32_t ws=v.getNumWords(); + const uint64_t *ptr=v.getRawData(); + int i=ws-1; +#if 0 + if(fill) + printf("%016llx",*(ptr+i)); + else + printf("%llx",*(ptr+i)); +#else +//match SystemC output + if(_AP_W%64 != 0) { + uint32_t offset=_AP_W%64; + uint32_t count=(offset+3)/4; + int64_t data=*(ptr+i); + if(_AP_S) + data=(data<<(64-offset))>>(64-offset); + else + count=(offset+4)/4; + while(count-->0) + printf("%llx",(data>>(count*4))&0xf); + } else { + if(_AP_S==false) + printf("0"); + printf("%016llx",*(ptr+i)); + } +#endif + for(--i;i>=0;i--) + printf("%016llx",*(ptr+i)); + printf("\n"); + +} +#endif /* #ifndef __AESL_GCC_AP_INT_H__ */ \ No newline at end of file diff --git a/hls_2018/router_03_boardstr/etc/ap_private.h b/hls_2018/router_03_boardstr/etc/ap_private.h new file mode 100755 index 0000000..1a68a9e --- /dev/null +++ b/hls_2018/router_03_boardstr/etc/ap_private.h @@ -0,0 +1,5858 @@ +/* + * Copyright 2012 Xilinx, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LLVM_SUPPORT_MATHEXTRAS_H +#define LLVM_SUPPORT_MATHEXTRAS_H + +#ifdef _MSC_VER +#if _MSC_VER <= 1500 +typedef __int8 int8_t; +typedef unsigned __int8 uint8_t; +typedef __int16 int16_t; +typedef unsigned __int16 uint16_t; +typedef __int32 int32_t; +typedef unsigned __int32 uint32_t; +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; +#else if +#include +#endif /* #if _MSC_VER <= 1500 */ +#else +#include +#endif /* #if _MSC_VER <= 1500 */ +#undef INLINE +#if 1 +#define INLINE inline +#else +//Enable to debug ap_int/ap_fixed +#define INLINE __attribute__((weak)) +#endif +#define AP_MAX(a,b) ((a) > (b) ? (a) : (b)) +#define AP_MIN(a,b) ((a) < (b) ? (a) : (b)) +#define AP_ABS(a) ((a)>=0 ? (a):-(a)) +#ifndef AP_INT_MAX_W +#define AP_INT_MAX_W 1024 +#endif +#define BIT_WIDTH_UPPER_LIMIT (1 << 15) +#if AP_INT_MAX_W > BIT_WIDTH_UPPER_LIMIT +#error "Bitwidth exceeds 32768 (1 << 15), the maximum allowed value" +#endif +#define MAX_MODE(BITS) ((BITS + 1023) / 1024) + +// NOTE: The following support functions use the _32/_64 extensions instead of +// type overloading so that signed and unsigned integers can be used without +// ambiguity. + +/// Hi_32 - This function returns the high 32 bits of a 64 bit value. +INLINE uint32_t Hi_32(uint64_t Value) { + return static_cast(Value >> 32); +} + +/// Lo_32 - This function returns the low 32 bits of a 64 bit value. +INLINE uint32_t Lo_32(uint64_t Value) { + return static_cast(Value); +} + +/// ByteSwap_16 - This function returns a byte-swapped representation of the +/// 16-bit argument, Value. +INLINE uint16_t ByteSwap_16(uint16_t Value) { +#if defined(_MSC_VER) && !defined(_DEBUG) + // The DLL version of the runtime lacks these functions (bug!?), but in a + // release build they're replaced with BSWAP instructions anyway. + return (uint16_t)(_byteswap_ushort(Value)); +#else + uint16_t Hi = (uint16_t)((Value) << 8); + uint16_t Lo = (uint16_t)((Value) >> 8); + return Hi | Lo; +#endif +} + +/// ByteSwap_32 - This function returns a byte-swapped representation of the +/// 32-bit argument, Value. +INLINE uint32_t ByteSwap_32(uint32_t Value) { + uint32_t Byte0 = Value & 0x000000FF; + uint32_t Byte1 = Value & 0x0000FF00; + uint32_t Byte2 = Value & 0x00FF0000; + uint32_t Byte3 = Value & 0xFF000000; + return ((Byte0) << 24) | ((Byte1) << 8) | ((Byte2) >> 8) | ((Byte3) >> 24); +} + +/// ByteSwap_64 - This function returns a byte-swapped representation of the +/// 64-bit argument, Value. +INLINE uint64_t ByteSwap_64(uint64_t Value) { + uint64_t Hi = ByteSwap_32(uint32_t(Value)); + uint32_t Lo = ByteSwap_32(uint32_t(Value >> 32)); + return ((Hi) << 32) | Lo; +} + +/// CountLeadingZeros_32 - this function performs the platform optimal form of +/// counting the number of zeros from the most significant bit to the first one +/// bit. Ex. CountLeadingZeros_32(0x00F000FF) == 8. +/// Returns 32 if the word is zero. +INLINE unsigned CountLeadingZeros_32(uint32_t Value) { + unsigned Count; // result +#if __GNUC__ >= 4 + // PowerPC is defined for __builtin_clz(0) +#if !defined(__ppc__) && !defined(__ppc64__) + if (Value == 0) return 32; +#endif + Count = __builtin_clz(Value); +#else + if (Value == 0) return 32; + Count = 0; + // bisecton method for count leading zeros + for (unsigned Shift = 32 >> 1; Shift; Shift >>= 1) { + uint32_t Tmp = (Value) >> (Shift); + if (Tmp) { + Value = Tmp; + } else { + Count |= Shift; + } + } +#endif + return Count; +} + +/// CountLeadingZeros_64 - This function performs the platform optimal form +/// of counting the number of zeros from the most significant bit to the first +/// one bit (64 bit edition.) +/// Returns 64 if the word is zero. +INLINE unsigned CountLeadingZeros_64(uint64_t Value) { + unsigned Count; // result +#if __GNUC__ >= 4 + // PowerPC is defined for __builtin_clzll(0) +#if !defined(__ppc__) && !defined(__ppc64__) + if (!Value) return 64; +#endif + Count = __builtin_clzll(Value); +#else + if (sizeof(long) == sizeof(int64_t)) { + if (!Value) return 64; + Count = 0; + // bisecton method for count leading zeros + for (unsigned Shift = 64 >> 1; Shift; Shift >>= 1) { + uint64_t Tmp = (Value) >> (Shift); + if (Tmp) { + Value = Tmp; + } else { + Count |= Shift; + } + } + } else { + // get hi portion + uint32_t Hi = Hi_32(Value); + + // if some bits in hi portion + if (Hi) { + // leading zeros in hi portion plus all bits in lo portion + Count = CountLeadingZeros_32(Hi); + } else { + // get lo portion + uint32_t Lo = Lo_32(Value); + // same as 32 bit value + Count = CountLeadingZeros_32(Lo)+32; + } + } +#endif + return Count; +} + +/// CountTrailingZeros_64 - This function performs the platform optimal form +/// of counting the number of zeros from the least significant bit to the first +/// one bit (64 bit edition.) +/// Returns 64 if the word is zero. +INLINE unsigned CountTrailingZeros_64(uint64_t Value) { +#if __GNUC__ >= 4 + return (Value != 0) ? __builtin_ctzll(Value) : 64; +#else + static const unsigned Mod67Position[] = { + 64, 0, 1, 39, 2, 15, 40, 23, 3, 12, 16, 59, 41, 19, 24, 54, + 4, 64, 13, 10, 17, 62, 60, 28, 42, 30, 20, 51, 25, 44, 55, + 47, 5, 32, 65, 38, 14, 22, 11, 58, 18, 53, 63, 9, 61, 27, + 29, 50, 43, 46, 31, 37, 21, 57, 52, 8, 26, 49, 45, 36, 56, + 7, 48, 35, 6, 34, 33, 0 + }; + return Mod67Position[(uint64_t)(-(int64_t)Value & (int64_t)Value) % 67]; +#endif +} + +/// CountPopulation_64 - this function counts the number of set bits in a value, +/// (64 bit edition.) +INLINE unsigned CountPopulation_64(uint64_t Value) { +#if __GNUC__ >= 4 + return __builtin_popcountll(Value); +#else + uint64_t v = Value - (((Value) >> 1) & 0x5555555555555555ULL); + v = (v & 0x3333333333333333ULL) + (((v) >> 2) & 0x3333333333333333ULL); + v = (v + ((v) >> 4)) & 0x0F0F0F0F0F0F0F0FULL; + return unsigned((uint64_t)(v * 0x0101010101010101ULL) >> 56); +#endif +} + +#endif // LLVM_SUPPORT_MATHEXTRAS_H + + +#ifndef AP_PRIVATE_H +#define AP_PRIVATE_H + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace AESL_std { + template + DataType INLINE min(DataType a, DataType b) { + // if (a >= b) return b; + // else return a; + return (a>=b) ? b : a; + } + + template + DataType INLINE max(DataType a, DataType b) { + // if (a >= b) return a; + // else return b; + return (a>=b) ? a : b; + } +} +enum ap_q_mode { + AP_RND, // rounding to plus infinity + AP_RND_ZERO,// rounding to zero + AP_RND_MIN_INF,// rounding to minus infinity + AP_RND_INF,// rounding to infinity + AP_RND_CONV, // convergent rounding + AP_TRN, // truncation + AP_TRN_ZERO // truncation to zero + +}; +enum ap_o_mode { + AP_SAT, // saturation + AP_SAT_ZERO, // saturation to zero + AP_SAT_SYM, // symmetrical saturation + AP_WRAP, // wrap-around (*) + AP_WRAP_SM // sign magnitude wrap-around (*) +}; + +template struct ap_fixed_base; +template struct af_range_ref; +template struct af_bit_ref; + +template struct ap_range_ref; +template struct ap_bit_ref; +template struct ap_concat_ref; +static bool InvalidDigit(const char* str, unsigned len, unsigned start, unsigned radix) { + unsigned i; + for (i = start; i < len; ++i) + if ((radix == 2 && (str[i] == '0' || str[i] == '1')) || + (radix == 8 && str[i] >= '0' && str[i] <= '7') || + (radix == 10 && str[i] >= '0' && str[i] <= '9') || + (radix == 16 && ((str[i] >= '0' && str[i] <= '9') || + (str[i] >= 'a' && str[i] <= 'f') || + (str[i] >= 'A' && str[i] <= 'F')))) + continue; + else + return true; + return false; +} + +static void ap_parse_sign(const char* str, uint32_t &base, bool &neg) { + if (str[0] == '+' || str[0] == '-') base = 1; + if (str[0] == '-') neg = true; + else neg = false; + return; +} + +static void ap_parse_prefix(const char* str, uint32_t &offset, uint32_t &radix) { + if (str[0] == '0') { + switch (str[1]) { + case 'b': + case 'B': offset = 2; radix = 2; break; + case 'x': + case 'X': offset = 2; radix = 16; break; + case 'd': + case 'D': offset = 2; radix = 10; break; + case 'o': + case 'O': offset = 2; radix = 8; break; + default: break; + } + } + if (offset == 0) + for (int i=0, len = strlen(str); i= 'a') || (str[i] <= 'F' && str[i] >= 'A')) { + radix = 16; + break; + } + return; +} + +/// sub_1 - This function subtracts a single "digit" (64-bit word), y, from +/// the multi-digit integer array, x[], propagating the borrowed 1 value until +/// no further borrowing is neeeded or it runs out of "digits" in x. The result +/// is 1 if "borrowing" exhausted the digits in x, or 0 if x was not exhausted. +/// In other words, if y > x then this function returns 1, otherwise 0. +/// @returns the borrow out of the subtraction +static bool sub_1(uint64_t x[], uint32_t len, uint64_t y) { + for (uint32_t i = 0; i < len; ++i) { + uint64_t __X = x[i]; + x[i] -= y; + if (y > __X) + y = 1; // We have to "borrow 1" from next "digit" + else { + y = 0; // No need to borrow + break; // Remaining digits are unchanged so exit early + } + } + return (y != 0); +} + + /// This enumeration just provides for internal constants used in this + /// translation unit. + enum { + MIN_INT_BITS = 1, ///< Minimum number of bits that can be specified + ///< Note that this must remain synchronized with IntegerType::MIN_INT_BITS + MAX_INT_BITS = (1<<23)-1 ///< Maximum number of bits that can be specified + ///< Note that this must remain synchronized with IntegerType::MAX_INT_BITS + }; + + /// A utility function for allocating memory and checking for allocation + /// failure. The content is not zeroed. + static uint64_t* getMemory(uint32_t numWords) { + return (uint64_t*) malloc(numWords*sizeof(uint64_t)); + } + + //===----------------------------------------------------------------------===// + // ap_private Class + //===----------------------------------------------------------------------===// + + /// ap_private - This class represents arbitrary precision constant integral values. + /// It is a functional replacement for common case unsigned integer type like + /// "unsigned", "unsigned long" or "uint64_t", but also allows non-byte-width + /// integer sizes and large integer value types such as 3-bits, 15-bits, or more + /// than 64-bits of precision. ap_private provides a variety of arithmetic operators + /// and methods to manipulate integer values of any bit-width. It supports both + /// the typical integer arithmetic and comparison operations as well as bitwise + /// manipulation. + /// + /// The class has several invariants worth noting: + /// * All bit, byte, and word positions are zero-based. + /// * Once the bit width is set, it doesn't change except by the Truncate, + /// SignExtend, or ZeroExtend operations. + /// * All binary operators must be on ap_private instances of the same bit width. + /// Attempting to use these operators on instances with different bit + /// widths will yield an assertion. + /// * The value is stored canonically as an unsigned value. For operations + /// where it makes a difference, there are both signed and unsigned variants + /// of the operation. For example, sdiv and udiv. However, because the bit + /// widths must be the same, operations such as Mul and Add produce the same + /// results regardless of whether the values are interpreted as signed or + /// not. + /// * In general, the class tries to follow the style of computation that LLVM + /// uses in its IR. This simplifies its use for LLVM. + /// + /// @brief Class for arbitrary precision integers. + template class ap_private; + namespace ap_private_ops{ + template + INLINE ap_private<_AP_W, _AP_S, _AP_N> lshr(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, uint32_t shiftAmt); + template + INLINE ap_private<_AP_W, _AP_S, _AP_N> shl(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, uint32_t shiftAmt); + } + +#if defined(_MSC_VER) +# if _MSC_VER < 1400 && !defined(for) +# define for if(0);else for +# endif + typedef unsigned __int64 ap_ulong; + typedef signed __int64 ap_slong; +#else + typedef unsigned long long ap_ulong; + typedef signed long long ap_slong; +#endif + template struct retval { + }; + template<> struct retval { + typedef ap_slong Type; + }; + template<> struct retval { + typedef ap_ulong Type; + }; + + template + class ap_private { +#ifdef _MSC_VER +#pragma warning( disable : 4521 4522 ) +#endif +public: + typedef typename retval<_AP_S>::Type ValType; + template friend struct ap_fixed_base; + ///return type of variety of operations + //---------------------------------------------------------- + template + struct RType { + enum { + mult_w = _AP_W+_AP_W2, + mult_s = _AP_S||_AP_S2, + plus_w = AP_MAX(_AP_W+(_AP_S2&&!_AP_S),_AP_W2+(_AP_S&&!_AP_S2))+1, + plus_s = _AP_S||_AP_S2, + minus_w = AP_MAX(_AP_W+(_AP_S2&&!_AP_S),_AP_W2+(_AP_S&&!_AP_S2))+1, + minus_s = true, + div_w = _AP_W+_AP_S2, + div_s = _AP_S||_AP_S2, + mod_w = AP_MIN(_AP_W,_AP_W2+(!_AP_S2&&_AP_S)), + mod_s = _AP_S, + logic_w = AP_MAX(_AP_W+(_AP_S2&&!_AP_S),_AP_W2+(_AP_S&&!_AP_S2)), + logic_s = _AP_S||_AP_S2 + }; + typedef ap_private mult; + typedef ap_private plus; + typedef ap_private minus; + typedef ap_private logic; + typedef ap_private div; + typedef ap_private mod; + typedef ap_private<_AP_W, _AP_S> arg1; + typedef bool reduce; + }; + + INLINE void report() { +#if 0 + if (_AP_W > 1024 && _AP_W <= 4096) { + fprintf(stderr, "[W] W=%d is out of bound (1<=W<=1024): for" + " synthesis: please define macro AP_INT_TYPE_EXT(N)" + " to extend the valid range.\n", _AP_W); + } else +#endif + if (_AP_W > MAX_MODE(AP_INT_MAX_W) * 1024) { + fprintf(stderr, "[E] ap_%sint<%d>: Bitwidth exceeds the " + "default max value %d. Please use macro " + "AP_INT_MAX_W to set a larger max value.\n", + _AP_S?"":"u", _AP_W, + MAX_MODE(AP_INT_MAX_W) * 1024); + exit(1); + } + } + + enum { BitWidth = _AP_W }; + /// This union is used to store the integer value. When the + /// integer bit-width <= 64, it uses VAL, otherwise it uses pVal. + + /// This enum is used to hold the constants we needed for ap_private. + uint64_t VAL; ///< Used to store the <= 64 bits integer value. + uint64_t pVal[_AP_N]; ///< Used to store the >64 bits integer value. + + /// This enum is used to hold the constants we needed for ap_private. + enum { + APINT_BITS_PER_WORD = sizeof(uint64_t) * 8, ///< Bits in a word + APINT_WORD_SIZE = sizeof(uint64_t) ///< Byte size of a word + }; + + enum { excess_bits = (_AP_W%APINT_BITS_PER_WORD) ? APINT_BITS_PER_WORD -(_AP_W%APINT_BITS_PER_WORD) : 0}; + static const uint64_t mask = ((uint64_t)~0ULL >> (excess_bits)); + + /// This constructor is used only internally for speed of construction of + /// temporaries. It is unsafe for general use so it is not public. + /* Constructors */ + + ap_private(const char* val) { + std::string str(val); + uint32_t strLen = str.length(); + const char *strp = str.c_str(); + uint32_t offset = 0; + uint32_t base = 0; + bool neg = false; + uint32_t radix = 16; + ap_parse_sign(strp, base, neg); + ap_parse_prefix(strp + base, offset, radix); + + if ((radix != 10 && neg) || + (strLen - base - offset <= 0) || + InvalidDigit(strp, strLen, base + offset, radix)) { + fprintf(stderr, "invalid character string %s !\n", val); + assert(0); + } + + ap_private ap_private_val(str.c_str(), strLen, radix, base, offset); + if (neg) + ap_private_val = -ap_private_val; + operator = (ap_private_val); + report(); + } + + ap_private(const char* val, int rd) { + std::string str(val); + uint32_t strLen = str.length(); + const char *strp = str.c_str(); + uint32_t offset = 0; + uint32_t base = 0; + uint32_t radix = rd; + bool neg = false; + ap_parse_sign(strp, base, neg); + ap_parse_prefix(strp + base, offset, radix); + + if ((radix != 10 && neg) || + (strLen - base - offset <= 0) || + InvalidDigit(strp, strLen, base + offset, radix)) { + fprintf(stderr, "invalid character string %s !\n", val); + assert(0); + } + + // uint32_t bitsNeeded = ap_private<_AP_W, _AP_S>::getBitsNeeded(strp, strLen, radix); + // ap_private<_AP_W, _AP_S> ap_private_val(bitsNeeded, strp , strLen, radix, base, offset); + ap_private ap_private_val(strp , strLen, radix, base, offset); + if (neg) + ap_private_val = -ap_private_val; + operator = (ap_private_val); + report(); + } + + /// Note that numWords can be smaller or larger than the corresponding bit + /// width but any extraneous bits will be dropped. + /// @param numBits the bit width of the constructed ap_private + /// @param numWords the number of words in bigVal + /// @param bigVal a sequence of words to form the initial value of the ap_private + /// @brief Construct an ap_private of numBits width, initialized as bigVal[]. + ap_private(uint32_t numWords, const uint64_t bigVal[]): VAL(0) { + assert(bigVal && "Null pointer detected!"); + { + // Get memory, cleared to 0 + memset(pVal, 0, _AP_N * sizeof(uint64_t)); + + // Calculate the number of words to copy + uint32_t words = AESL_std::min(numWords, _AP_N); + // Copy the words from bigVal to pVal + memcpy(pVal, bigVal, words * APINT_WORD_SIZE); + if (words >= _AP_W) + clearUnusedBits(); + // Make sure unused high bits are cleared + } + } + + /// This constructor interprets Val as a string in the given radix. The + /// interpretation stops when the first charater that is not suitable for the + /// radix is encountered. Acceptable radix values are 2, 8, 10 and 16. It is + /// an error for the value implied by the string to require more bits than + /// numBits. + /// @param numBits the bit width of the constructed ap_private + /// @param val the string to be interpreted + /// @param radix the radix of Val to use for the intepretation + /// @brief Construct an ap_private from a string representation. + ap_private(const std::string& val, uint8_t radix=2, int base=0, int offset=0): VAL(0) { + assert(!val.empty() && "The input string is empty."); + const char *c_str = val.c_str(); + fromString(c_str+base+offset, val.size()-base-offset, radix); + } + + /// This constructor interprets the slen characters starting at StrStart as + /// a string in the given radix. The interpretation stops when the first + /// character that is not suitable for the radix is encountered. Acceptable + /// radix values are 2, 8, 10 and 16. It is an error for the value implied by + /// the string to require more bits than numBits. + /// @param numBits the bit width of the constructed ap_private + /// @param strStart the start of the string to be interpreted + /// @param slen the maximum number of characters to interpret + /// @param radix the radix to use for the conversion + /// @brief Construct an ap_private from a string representation. + /// This method does not consider whether it is negative or not. + ap_private(const char strStart[], uint32_t slen, uint8_t radix, int base=0, int offset=0) : VAL(0) { + fromString(strStart+base+offset, slen-base-offset, radix); + } + + template + INLINE ap_private(const ap_range_ref<_AP_W2,_AP_S2>& ref) { + *this=ref.get(); + report(); + } + + template + INLINE ap_private(const ap_bit_ref<_AP_W2,_AP_S2>& ref) { + *this = ((uint64_t)(bool)ref); + report(); + } + + template + INLINE ap_private(const ap_concat_ref<_AP_W2, _AP_T2,_AP_W3, _AP_T3>& ref) { + *this=ref.get(); + report(); + } + + template + INLINE ap_private(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2> &val) { + *this = ((val.operator ap_private<_AP_W2, false> ())); + report(); + } + + template + INLINE ap_private(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2> &val) { + *this = (uint64_t)(bool)val; + report(); + } + + /// Simply makes *this a copy of that. + /// @brief Copy Constructor. + template + ap_private(const volatile ap_private<_AP_W1, _AP_S1, _AP_N1>& that): VAL(0) { + operator = (const_cast& >(that)); + } + + template + ap_private(const ap_private<_AP_W1, _AP_S1, _AP_N1>& that): VAL(0) { + operator = (that); + } + + template + explicit ap_private(const ap_private<_AP_W1, _AP_S1, 1>& that): VAL(0) { + static const uint64_t that_sign_ext_mask = (_AP_W1==APINT_BITS_PER_WORD)?0:~0ULL>>(_AP_W1%APINT_BITS_PER_WORD)<<(_AP_W1%APINT_BITS_PER_WORD); + if (that.isNegative()) { + pVal[0] = that.VAL|that_sign_ext_mask; + memset(pVal+1, ~0, sizeof(uint64_t)*(_AP_N-1)); + } else { + pVal[0] = that.VAL; + memset(pVal+1, 0, sizeof(uint64_t)*(_AP_N-1)); + } + clearUnusedBits(); + } + + ap_private(const ap_private& that): VAL(0) { + memcpy(pVal, that.pVal, _AP_N * APINT_WORD_SIZE); + clearUnusedBits(); + } + + /// @brief Destructor. + virtual ~ap_private() {} + + /// Default constructor that creates an uninitialized ap_private. This is useful + /// for object deserialization (pair this with the static method Read). + ap_private(){memset(pVal, 0, sizeof(uint64_t)*(_AP_N));} + + ap_private(uint64_t* val, uint32_t bits=_AP_W) {assert(0);} + ap_private(const uint64_t *const val, uint32_t bits) {assert(0);} + + /// @name Constructors + /// @{ + /// If isSigned is true then val is treated as if it were a signed value + /// (i.e. as an int64_t) and the appropriate sign extension to the bit width + /// will be done. Otherwise, no sign extension occurs (high order bits beyond + /// the range of val are zero filled). + /// @param numBits the bit width of the constructed ap_private + /// @param val the initial value of the ap_private + /// @param isSigned how to treat signedness of val + /// @brief Create a new ap_private of numBits width, initialized as val. +#define CTOR(TYPE, SIGNED) \ + ap_private(TYPE val, bool isSigned=SIGNED) { \ + pVal[0] = val; \ + if (isSigned && int64_t(pVal[0]) < 0) { \ + memset(pVal+1, ~0, sizeof(uint64_t)*(_AP_N-1)); \ + } else { \ + memset(pVal+1, 0, sizeof(uint64_t)*(_AP_N-1)); \ + } \ + clearUnusedBits(); \ + } +#if 1 + CTOR(int, true) + CTOR(bool, false) + CTOR(signed char, true) + CTOR(unsigned char, false) + CTOR(short, true) + CTOR(unsigned short, false) + CTOR(unsigned int, false) + CTOR(long, true) + CTOR(unsigned long, false) + CTOR(unsigned long long, false) + CTOR(long long, true) + CTOR(float, false) + CTOR(double, false) +#undef CTOR +#else + CTOR(uint64_t) +#undef CTOR +#endif + + + /// @returns true if the number of bits <= 64, false otherwise. + /// @brief Determine if this ap_private just has one word to store value. + INLINE bool isSingleWord() const { + return false; + } + + /// @returns the word position for the specified bit position. + /// @brief Determine which word a bit is in. + static uint32_t whichWord(uint32_t bitPosition) { + // return bitPosition / APINT_BITS_PER_WORD; + return (bitPosition) >> 6; + } + + /// @returns the bit position in a word for the specified bit position + /// in the ap_private. + /// @brief Determine which bit in a word a bit is in. + static uint32_t whichBit(uint32_t bitPosition) { + // return bitPosition % APINT_BITS_PER_WORD; + return bitPosition & 0x3f; + } + + /// bit at a specific bit position. This is used to mask the bit in the + /// corresponding word. + /// @returns a uint64_t with only bit at "whichBit(bitPosition)" set + /// @brief Get a single bit mask. + static uint64_t maskBit(uint32_t bitPosition) { + return 1ULL << (whichBit(bitPosition)); + } + + /// @returns the corresponding word for the specified bit position. + /// @brief Get the word corresponding to a bit position + INLINE uint64_t getWord(uint32_t bitPosition) const { + return isSingleWord() ? VAL : pVal[whichWord(bitPosition)]; + } + + /// This method is used internally to clear the to "N" bits in the high order + /// word that are not used by the ap_private. This is needed after the most + /// significant word is assigned a value to ensure that those bits are + /// zero'd out. + /// @brief Clear unused high order bits + INLINE void clearUnusedBits(void) { + pVal[_AP_N-1] = _AP_S ? ((((int64_t)pVal[_AP_N-1])<<(excess_bits))>> excess_bits) : (excess_bits ? ((pVal[_AP_N-1])<<(excess_bits))>>(excess_bits) : pVal[_AP_N-1]); + } + + INLINE void clearUnusedBitsToZero(void) { + pVal[_AP_N-1] &= mask; + } + + INLINE void clearUnusedBitsToOne(void) { + pVal[_AP_N-1] |= mask; + } + + /// This is used by the constructors that take string arguments. + /// @brief Convert a char array into an ap_private + INLINE void fromString(const char *strStart, uint32_t slen, + uint8_t radix) ; + + INLINE ap_private read() volatile { + return *this; + } + + INLINE void write(const ap_private& op2) volatile { + *this = (op2); + } + + //Explicit conversions to C interger types + //----------------------------------------------------------- + operator ValType() const { + return getVal(); + } + + INLINE ValType getVal() const{ + return *pVal; + } + + INLINE int to_int() const { + return int(*this); + } + + INLINE unsigned to_uint() const { + return (unsigned) getVal(); + } + + INLINE long to_long() const { + return (long) getVal(); + } + + INLINE unsigned long to_ulong() const { + return (unsigned long) getVal(); + } + + INLINE ap_slong to_int64() const { + return (ap_slong) getVal(); + } + + INLINE ap_ulong to_uint64() const { + return (ap_ulong) getVal(); + } + + INLINE double to_double() const { + if (isNegative()) + return roundToDouble(true); + else + return roundToDouble(false); + } + + INLINE unsigned length() const { return _AP_W; } + + /*Reverse the contents of ap_private instance. I.e. LSB becomes MSB and vise versa*/ + INLINE ap_private& reverse () { + for (int i = 0; i < _AP_W/2; ++i) { + bool tmp = operator[](i); + if (operator[](_AP_W - 1 - i)) + set(i); + else + clear(i); + if (tmp) + set(_AP_W - 1 - i); + else + clear(_AP_W - 1 - i); + } + clearUnusedBits(); + return *this; + } + + /*Return true if the value of ap_private instance is zero*/ + INLINE bool iszero () const { + return isMinValue(); + } + + /* x < 0 */ + INLINE bool sign () const { + if (isNegative()) + return true; + return false; + } + + /* x[i] = !x[i] */ + INLINE void invert (int i) { + assert( i >= 0 && "Attempting to read bit with negative index"); + assert( i < _AP_W && "Attempting to read bit beyond MSB"); + flip(i); + } + + /* x[i] */ + INLINE bool test (int i) const { + assert( i >= 0 && "Attempting to read bit with negative index"); + assert( i < _AP_W && "Attempting to read bit beyond MSB"); + return operator[](i); + } + + //Set the ith bit into v + INLINE void set (int i, bool v) { + assert( i >= 0 && "Attempting to write bit with negative index"); + assert( i < _AP_W && "Attempting to write bit beyond MSB"); + v ? set(i) : clear(i); + } + + //Set the ith bit into v + INLINE void set_bit (int i, bool v) { + assert( i >= 0 && "Attempting to write bit with negative index"); + assert( i < _AP_W && "Attempting to write bit beyond MSB"); + v ? set(i) : clear(i); + } + + INLINE ap_private& set(uint32_t bitPosition) { + pVal[whichWord(bitPosition)] |= maskBit(bitPosition); + clearUnusedBits(); + return *this; + } + + INLINE void set() { + for (uint32_t i = 0; i < _AP_N; ++i) + pVal[i] = ~0ULL; + clearUnusedBits(); + } + + //Get the value of ith bit + INLINE bool get (int i) const { + assert( i >= 0 && "Attempting to read bit with negative index"); + assert( i < _AP_W && "Attempting to read bit beyond MSB"); + return operator [](i); + } + + //Get the value of ith bit + INLINE bool get_bit (int i) const { + assert( i >= 0 && "Attempting to read bit with negative index"); + assert( i < _AP_W && "Attempting to read bit beyond MSB"); + return operator [](i); + } + + //This is used for sc_lv and sc_bv, which is implemented by sc_uint + //Rotate an ap_private object n places to the left + INLINE void lrotate(int n) { + assert( n >= 0 && "Attempting to shift negative index"); + assert( n < _AP_W && "Shift value larger than bit width"); + operator = (shl(n) | lshr(_AP_W - n)); + } + + //This is used for sc_lv and sc_bv, which is implemented by sc_uint + //Rotate an ap_private object n places to the right + INLINE void rrotate(int n) { + assert( n >= 0 && "Attempting to shift negative index"); + assert( n < _AP_W && "Shift value larger than bit width"); + operator = (lshr(n) | shl(_AP_W - n)); + } + + /// Set the given bit to 0 whose position is given as "bitPosition". + /// @brief Set a given bit to 0. + ap_private& clear(uint32_t bitPosition) { + pVal[whichWord(bitPosition)] &= ~maskBit(bitPosition); + clearUnusedBits(); + return *this; + } + + /// @brief Set every bit to 0. + void clear() { + memset(pVal, 0, _AP_N * APINT_WORD_SIZE); + } + + /// @brief Toggle every bit to its opposite value. + ap_private& flip() { + for (uint32_t i = 0; i < _AP_N; ++i) + pVal[i] ^= ~0ULL; + clearUnusedBits(); + return *this; + } + + /// Toggle a given bit to its opposite value whose position is given + /// as "bitPosition". + /// @brief Toggles a given bit to its opposite value. + ap_private& flip(uint32_t bitPosition) { + assert(bitPosition < BitWidth && "Out of the bit-width range!"); + if ((*this)[bitPosition]) clear(bitPosition); + else set(bitPosition); + return *this; + } + + //complements every bit + INLINE void b_not() { + flip(); + } + + ap_private getLoBits(uint32_t numBits) const { + return ap_private_ops::lshr(ap_private_ops::shl(*this, _AP_W - numBits), + _AP_W - numBits); + } + + ap_private getHiBits(uint32_t numBits) const { + return ap_private_ops::lshr(*this, _AP_W - numBits); + } + + //Binary Arithmetic + //----------------------------------------------------------- + + template + INLINE ap_private + operator & (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) { + return *this & a2.get(); + } + + template + INLINE ap_private + operator | (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) { + return *this | a2.get(); + } + + template + INLINE ap_private + operator ^ (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) { + return *this ^ a2.get(); + } + + + ///Arithmetic assign + //------------------------------------------------------------- + +#define OP_BIN_LOGIC_ASSIGN_AP(Sym) \ + template \ + INLINE ap_private& operator Sym(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { \ + uint32_t numWords = AESL_std::min(_AP_N, _AP_N1); \ + uint32_t i; \ + for (i = 0; i < numWords; ++i) \ + pVal[i] Sym RHS.pVal[i]; \ + if (_AP_N1 < _AP_N) { \ + uint64_t ext = RHS.isNegative()?~0ULL:0; \ + for (;i<_AP_N; i++) \ + pVal[i] Sym ext; \ + } \ + clearUnusedBits(); \ + return *this; \ + } + + OP_BIN_LOGIC_ASSIGN_AP(&=); + OP_BIN_LOGIC_ASSIGN_AP(|=); + OP_BIN_LOGIC_ASSIGN_AP(^=); +#undef OP_BIN_LOGIC_ASSIGN_AP + + /// Adds the RHS APint to this ap_private. + /// @returns this, after addition of RHS. + /// @brief Addition assignment operator. + template + INLINE ap_private& operator+=(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { + add(pVal, pVal, RHS.pVal, _AP_N, _AP_N, _AP_N1, _AP_S, _AP_S1); + clearUnusedBits(); + return *this; + } + + template + INLINE ap_private& operator-=(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { + sub(pVal, pVal, RHS.pVal, _AP_N, _AP_N, _AP_N1, _AP_S, _AP_S1); + clearUnusedBits(); + return *this; + } + + template + ap_private& operator*=(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { + // Get some bit facts about LHS and check for zero + uint32_t lhsBits = getActiveBits(); + uint32_t lhsWords = !lhsBits ? 0 : whichWord(lhsBits - 1) + 1; + if (!lhsWords) { + // 0 * X ===> 0 + return *this; + } + + ap_private dupRHS = RHS; + // Get some bit facts about RHS and check for zero + uint32_t rhsBits = dupRHS.getActiveBits(); + uint32_t rhsWords = !rhsBits ? 0 : whichWord(rhsBits - 1) + 1; + if (!rhsWords) { + // X * 0 ===> 0 + clear(); + return *this; + } + + // Allocate space for the result + uint32_t destWords = rhsWords + lhsWords; + uint64_t *dest = getMemory(destWords); + + // Perform the long multiply + mul(dest, pVal, lhsWords, dupRHS.pVal, rhsWords, destWords); + + // Copy result back into *this + clear(); + uint32_t wordsToCopy = destWords >= _AP_N ? _AP_N : destWords; + + memcpy(pVal, dest, wordsToCopy* APINT_WORD_SIZE); + + uint64_t ext = (isNegative() ^ RHS.isNegative()) ? ~0ULL : 0ULL; + for (int i=wordsToCopy; i<_AP_N; i++) + pVal[i]=ext; + clearUnusedBits(); + // delete dest array and return + free(dest); + return *this; + } + +#define OP_ASSIGN_AP(Sym) \ + template \ + INLINE ap_private& operator Sym##=(const ap_private<_AP_W2,_AP_S2>& op) \ + { \ + *this=operator Sym (op); \ + return *this; \ + } \ + + OP_ASSIGN_AP(/) + OP_ASSIGN_AP(%) +#undef OP_ASSIGN_AP + +#define OP_BIN_LOGIC_AP(Sym) \ + template \ + INLINE \ + typename RType<_AP_W1, _AP_S1>::logic \ + operator Sym (const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) const { \ + enum { numWords = (RType<_AP_W1, _AP_S1>::logic_w +APINT_BITS_PER_WORD-1)/APINT_BITS_PER_WORD}; \ + typename RType<_AP_W1, _AP_S1>::logic Result; \ + uint64_t *val = Result.pVal; \ + uint32_t i; \ + uint32_t min_N = std::min(_AP_N, _AP_N1); \ + uint32_t max_N = std::max(_AP_N, _AP_N1); \ + for (i = 0; i < min_N; ++i) \ + val[i] = pVal[i] Sym RHS.pVal[i]; \ + if (numWords > i) { \ + const uint64_t* tmpVal = (_AP_N>_AP_N1 ? pVal : RHS.pVal)+i; \ + uint64_t ext = ((_AP_N<_AP_N1 && isNegative() )||(_AP_N1 < _AP_N && RHS.isNegative())) ? ~0ULL : 0; \ + for (;i i) { \ + uint64_t ext2 = ((_AP_N>_AP_N1 && isNegative() )||(_AP_N1 > _AP_N && RHS.isNegative())) ? ~0ULL : 0; \ + val[i] = ext Sym ext2; \ + } \ + } \ + Result.clearUnusedBits(); \ + return Result; \ + } + + OP_BIN_LOGIC_AP(|); + OP_BIN_LOGIC_AP(&); + OP_BIN_LOGIC_AP(^); + +#undef OP_BIN_LOGIC_AP + + template + INLINE typename RType<_AP_W1,_AP_S1>::plus operator+(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) const { + // assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + typename RType<_AP_W1,_AP_S1>::plus Result; + bool carry = add(Result.pVal, this->pVal, RHS.pVal, (RType<_AP_W1,_AP_S1>::plus_w + 63) / 64, _AP_N, _AP_N1, _AP_S, _AP_S1); + if ((RType<_AP_W1,_AP_S1>::plus_w + 63) / 64> std::max(_AP_W, _AP_W1) ) + Result.pVal[(RType<_AP_W1,_AP_S1>::plus_w + 63)/64 - 1] = carry; + Result.clearUnusedBits(); + return Result; + } + + template + INLINE typename RType<_AP_W1,_AP_S1>::minus operator-(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) const { + typename RType<_AP_W1,_AP_S1>::minus Result; + bool borrow = sub(Result.pVal, this->pVal, RHS.pVal, (RType<_AP_W1,_AP_S1>::minus_w + 63) / 64, _AP_N, _AP_N1, _AP_S, _AP_S1); + if ((RType<_AP_W1,_AP_S1>::minus_w + 63) / 64 > AESL_std::max(_AP_W, _AP_W1) ) { + Result.pVal[(RType<_AP_W1,_AP_S1>::minus_w+63)/64 - 1] = borrow; + } + Result.clearUnusedBits(); + return Result; + } + + template + typename RType<_AP_W1, _AP_S1>::mult operator*(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) const { + + // Get some bit facts about LHS and check for zero + uint32_t lhsBits = getActiveBits(); + uint32_t lhsWords = !lhsBits ? 0 : whichWord(lhsBits - 1) + 1; + if (!lhsWords) + // 0 * X ===> 0 + return typename RType<_AP_W1, _AP_S1>::mult(); + + // Get some bit facts about RHS and check for zero + uint32_t rhsBits = RHS.getActiveBits(); + uint32_t rhsWords = !rhsBits ? 0 : whichWord(rhsBits - 1) + 1; + if (!rhsWords) { + // X * 0 ===> 0 + return typename RType<_AP_W1, _AP_S1>::mult(); + } + + //extend size to avoid result loss + typename RType<_AP_W1, _AP_S1>::mult dupLHS = *this; + typename RType<_AP_W1, _AP_S1>::mult dupRHS = RHS; + lhsBits = dupLHS.getActiveBits(); + lhsWords = !lhsBits ? 0 : whichWord(lhsBits - 1) + 1; + rhsBits = dupRHS.getActiveBits(); + rhsWords = !rhsBits ? 0 : whichWord(rhsBits - 1) + 1; + + // Allocate space for the result + enum { destWords =(RType<_AP_W1, _AP_S1>::mult_w+APINT_BITS_PER_WORD-1)/APINT_BITS_PER_WORD}; + int destw = destWords; + typename RType<_AP_W1, _AP_S1>::mult Result; + uint64_t *dest = Result.pVal; + uint64_t ext = (isNegative() ^ RHS.isNegative()) ? ~0ULL : 0; + + // Perform the long multiply + mul(dest, dupLHS.pVal, lhsWords, dupRHS.pVal, rhsWords, destWords); + + for (int i=lhsWords+rhsWords; i + INLINE typename RType<_AP_W2,_AP_S2>::div + operator / (const ap_private<_AP_W2,_AP_S2>& op) const { + ap_private lhs=ap_private(*this); + ap_private rhs=ap_private(op); + return typename RType<_AP_W2,_AP_S2>::div((_AP_S||_AP_S2)?lhs.sdiv(rhs):lhs.udiv(rhs)); + } + + template + INLINE typename RType<_AP_W2,_AP_S2>::mod + operator % (const ap_private<_AP_W2,_AP_S2>& op) const { + ap_private lhs=*this; + ap_private rhs= op; + typename RType<_AP_W2,_AP_S2>::mod res = typename RType<_AP_W2,_AP_S2>::mod(_AP_S?lhs.srem(rhs):lhs.urem(rhs)); + return res; + } + + template + INLINE ap_private + operator << (const ap_private<_AP_W2, _AP_S2>& op2) const { + uint32_t sh=op2.to_uint(); + return *this << sh; + } + + INLINE ap_private + operator << (uint32_t sh) const { + ap_private r(*this); + bool overflow=(sh>=length()); + if(overflow) + r.clear(); + else + r = ap_private(r.shl(sh)); + return r; + } + + template + INLINE ap_private + operator >> (const ap_private<_AP_W2, _AP_S2>& op2) const { + uint32_t sh = op2.to_uint(); + return *this >> sh; + } + + INLINE ap_private + operator >> (uint32_t sh) const { + ap_private r(*this); + bool overflow=(sh>=_AP_W); + bool neg_v=r.isNegative(); + if(_AP_S) { + if(overflow) + neg_v?r.set():r.clear(); + else + return r.ashr(sh); + } else { + if(overflow) + r.clear(); + else + return r.lshr(sh); + } + return r; + } + + ///Shift assign + //------------------------------------------------------------------ +#define OP_ASSIGN_AP(Sym) \ + template \ + INLINE ap_private& operator Sym##=(int op) \ + { \ + *this = operator Sym (op); \ + return *this; \ + } \ + INLINE ap_private& operator Sym##=(unsigned int op) \ + { \ + *this = operator Sym (op); \ + return *this; \ + } \ + template \ + INLINE ap_private& operator Sym##=(const ap_private<_AP_W2,_AP_S2>& op) \ + { \ + *this = operator Sym (op); \ + return *this; \ + } + OP_ASSIGN_AP(>>) + OP_ASSIGN_AP(<<) +#undef OP_ASSIGN_AP + ///Comparisons + //----------------------------------------------------------------- + bool operator==(const ap_private& RHS) const { + // Get some facts about the number of bits used in the two operands. + uint32_t n1 = getActiveBits(); + uint32_t n2 = RHS.getActiveBits(); + + // If the number of bits isn't the same, they aren't equal + if (n1 != n2) + return false; + + // If the number of bits fits in a word, we only need to compare the low word. + if (n1 <= APINT_BITS_PER_WORD) + return pVal[0] == RHS.pVal[0]; + + // Otherwise, compare everything + for (int i = whichWord(n1 - 1); i >= 0; --i) + if (pVal[i] != RHS.pVal[i]) + return false; + return true; + } + + template + INLINE bool operator == (const ap_private<_AP_W2, _AP_S2>& op) const { + enum { _AP_MAX_W = AP_MAX(_AP_W+(_AP_S||_AP_S2),_AP_W2+(_AP_S||_AP_S2))}; + ap_private<_AP_MAX_W, _AP_S|_AP_S2> lhs(*this); + ap_private<_AP_MAX_W, _AP_S|_AP_S2> rhs(op); + return lhs==rhs; + } + + bool operator==(uint64_t Val) const { + uint32_t n = getActiveBits(); + if (n <= APINT_BITS_PER_WORD) + return pVal[0] == Val; + else + return false; + } + + template + INLINE bool operator != (const ap_private<_AP_W2, _AP_S2>& op) const { + return !(*this==op); + } + + template + INLINE bool operator!=(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return !((*this) == RHS); + } + + INLINE bool operator!=(uint64_t Val) const { + return !((*this) == Val); + } + + + template + INLINE bool operator <= (const ap_private<_AP_W2,_AP_S2>& op) const { + return !(*this>op); + } + + INLINE bool operator <(const ap_private& op) const { + return _AP_S ? slt(op):ult(op); + } + + template + INLINE bool operator < (const ap_private<_AP_W2, _AP_S2>& op) const { + enum { _AP_MAX_W = AP_MAX(_AP_W+(_AP_S||_AP_S2),_AP_W2+(_AP_S||_AP_S2))}; + ap_private<_AP_MAX_W, _AP_S> lhs(*this); + ap_private<_AP_MAX_W, _AP_S2> rhs(op); + if (_AP_S == _AP_S2) + return _AP_S?lhs.slt(rhs):lhs.ult(rhs); + else + if (_AP_S) + if (_AP_W2 >= _AP_W) + return lhs.ult(rhs); + else + return lhs.slt(rhs); + else + if (_AP_W >= _AP_W2) + return lhs.ult(rhs); + else + return lhs.slt(rhs); + } + + template + INLINE bool operator >=(const ap_private<_AP_W2,_AP_S2>& op) const { + return !(*this + INLINE bool operator > (const ap_private<_AP_W2, _AP_S2>& op) const { + enum { _AP_MAX_W = AP_MAX(_AP_W+(_AP_S||_AP_S2),_AP_W2+(_AP_S||_AP_S2))}; + ap_private<_AP_MAX_W, _AP_S> lhs(*this); + ap_private<_AP_MAX_W, _AP_S2> rhs(op); + if (_AP_S == _AP_S2) + return _AP_S?lhs.sgt(rhs):lhs.ugt(rhs); + else + if (_AP_S) + if (_AP_W2 >= _AP_W) + return lhs.ugt(rhs); + else + return lhs.sgt(rhs); + else + if (_AP_W >= _AP_W2) + return lhs.ugt(rhs); + else + return lhs.sgt(rhs); + } + + ///Bit and Part Select + //-------------------------------------------------------------- + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (int Hi, int Lo) { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (int Hi, int Lo) const { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(const_cast*>(this), Hi, Lo); + } + + INLINE ap_range_ref<_AP_W,_AP_S> + range (int Hi, int Lo) const { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>((const_cast*> (this)), Hi, Lo); + } + + INLINE ap_range_ref<_AP_W,_AP_S> + range (int Hi, int Lo) { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + range (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + range (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) const { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(const_cast(this), Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) const { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + return this->range(Hi, Lo); + } + + INLINE ap_bit_ref<_AP_W,_AP_S> operator [] (uint32_t index) { + assert(index >= 0&&"Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S>( *this, index ); + } + + template + INLINE ap_bit_ref<_AP_W,_AP_S> operator [] (const ap_private<_AP_W2,_AP_S2> &index) { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S>( *this, index.to_int() ); + } + + template + INLINE bool operator [] (const ap_private<_AP_W2,_AP_S2>& index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + ap_bit_ref<_AP_W,_AP_S> br =operator [] (index); + return br.to_bool(); + } + + INLINE bool operator [](uint32_t bitPosition) const { + return (maskBit(bitPosition) & (pVal[whichWord(bitPosition)])) != 0; + } + + INLINE ap_bit_ref<_AP_W,_AP_S> bit (int index) { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S>( *this, index ); + } + + template + INLINE ap_bit_ref<_AP_W,_AP_S> bit (const ap_private<_AP_W2,_AP_S2> &index) { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W &&"Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S>( *this, index.to_int() ); + } + + INLINE bool bit (int index) const { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + ap_bit_ref<_AP_W,_AP_S> br(const_cast*>(this), index); + return br.to_bool(); + } + + template + INLINE bool bit (const ap_private<_AP_W2,_AP_S2>& index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + ap_bit_ref<_AP_W,_AP_S> br = bit(index); + return br.to_bool(); + } + + template + INLINE ap_concat_ref<_AP_W,ap_private<_AP_W, _AP_S>,_AP_W2,ap_private<_AP_W2,_AP_S2> > concat(ap_private<_AP_W2,_AP_S2>& a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_private<_AP_W2,_AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W,ap_private<_AP_W, _AP_S>,_AP_W2,ap_private<_AP_W2,_AP_S2> > concat(const ap_private<_AP_W2,_AP_S2>& a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_private<_AP_W2,_AP_S2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (ap_private<_AP_W2, _AP_S2>& a2) { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (ap_private<_AP_W2, _AP_S2>& a2) const { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(const_cast& >(*this), a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (const ap_private<_AP_W2, _AP_S2>& a2) { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(*this, const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (const ap_private<_AP_W2, _AP_S2>& a2) const { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(const_cast& >(*this), const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > + operator, (const ap_range_ref<_AP_W2, _AP_S2> &a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, + ap_range_ref<_AP_W2, _AP_S2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > + operator, (ap_range_ref<_AP_W2, _AP_S2> &a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, + ap_range_ref<_AP_W2, _AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, ap_bit_ref<_AP_W2, _AP_S2> > + operator, (const ap_bit_ref<_AP_W2, _AP_S2> &a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, + ap_bit_ref<_AP_W2, _AP_S2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, ap_bit_ref<_AP_W2, _AP_S2> > + operator, (ap_bit_ref<_AP_W2, _AP_S2> &a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, + ap_bit_ref<_AP_W2, _AP_S2> >(*this, a2); + } + + template + INLINE + ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > + operator, (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE + ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > + operator, (ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) const { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) const { + return ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, a2); + } + + INLINE ap_private<_AP_W,false> get() const { + ap_private<_AP_W,false> ret(*this); + return ret; + } + + template + INLINE void set(const ap_private<_AP_W3, false> & val) { + operator = (ap_private<_AP_W3, _AP_S>(val)); + } + + /// @} + /// @name Value Tests + /// @{ + /// This tests the high bit of this ap_private to determine if it is set. + /// @returns true if this ap_private is negative, false otherwise + /// @brief Determine sign of this ap_private. + INLINE bool isNegative() const { + //just for get rid of warnings + enum {shift = (_AP_W-APINT_BITS_PER_WORD*(_AP_N-1)-1)}; + static const uint64_t mask = 1ULL << (shift); + return _AP_S && (pVal[_AP_N-1]&mask); + } + + /// This tests the high bit of the ap_private to determine if it is unset. + /// @brief Determine if this ap_private Value is positive (not negative). + INLINE bool isPositive() const { + return !isNegative(); + } + + /// This tests if the value of this ap_private is strictly positive (> 0). + /// @returns true if this ap_private is Positive and not zero. + /// @brief Determine if this ap_private Value is strictly positive. + INLINE bool isStrictlyPositive() const { + return isPositive() && (*this) != 0; + } + + /// This checks to see if the value has all bits of the ap_private are set or not. + /// @brief Determine if all bits are set + INLINE bool isAllOnesValue() const { + return countPopulation() == _AP_W; + } + + /// This checks to see if the value of this ap_private is the maximum unsigned + /// value for the ap_private's bit width. + /// @brief Determine if this is the largest unsigned value. + INLINE bool isMaxValue() const { + return countPopulation() == _AP_W; + } + + /// This checks to see if the value of this ap_private is the maximum signed + /// value for the ap_private's bit width. + /// @brief Determine if this is the largest signed value. + INLINE bool isMaxSignedValue() const { + return BitWidth == 1 ? VAL == 0 : + !isNegative() && countPopulation() == _AP_W - 1; + } + + /// This checks to see if the value of this ap_private is the minimum unsigned + /// value for the ap_private's bit width. + /// @brief Determine if this is the smallest unsigned value. + INLINE bool isMinValue() const { + return countPopulation() == 0; + } + + /// This checks to see if the value of this ap_private is the minimum signed + /// value for the ap_private's bit width. + /// @brief Determine if this is the smallest signed value. + INLINE bool isMinSignedValue() const { + return BitWidth == 1 ? VAL == 1 : + isNegative() && countPopulation() == 1; + } + + /// This function returns a pointer to the internal storage of the ap_private. + /// This is useful for writing out the ap_private in binary form without any + /// conversions. + INLINE const uint64_t* getRawData() const { + if (isSingleWord()) + return &VAL; + return &pVal[0]; + } + + ap_private sqrt() const; + + /// @} + /// @Assignment Operators + /// @{ + /// @returns *this after assignment of RHS. + /// @brief Copy assignment operator. + INLINE ap_private& operator=(const ap_private& RHS) { + if (this != &RHS) + memcpy(pVal, RHS.pVal, _AP_N * APINT_WORD_SIZE); + return *this; + } + INLINE ap_private& operator=(const volatile ap_private& RHS) { + if (this != &RHS) + for (int i=0; i<_AP_N; ++i) + pVal[i] = RHS.pVal[i]; + return *this; + } + INLINE volatile ap_private& operator=(const ap_private& RHS) volatile { + if (this != &RHS) + for (int i=0; i<_AP_N; ++i) + pVal[i] = RHS.pVal[i]; + return *this; + } + INLINE volatile ap_private& operator=(const volatile ap_private& RHS) volatile { + if (this != &RHS) + for (int i=0; i<_AP_N; ++i) + pVal[i] = RHS.pVal[i]; + return *this; + } + + template + INLINE ap_private& operator=(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { + if (_AP_S1) + cpSextOrTrunc(RHS); + else + cpZextOrTrunc(RHS); + clearUnusedBits(); + return *this; + } + + template + INLINE ap_private& operator=(const volatile ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { + if (_AP_S1) + cpSextOrTrunc(RHS); + else + cpZextOrTrunc(RHS); + clearUnusedBits(); + return *this; + } + + template + INLINE ap_private& operator=(const ap_private<_AP_W1, _AP_S1, 1>& RHS) { + static const uint64_t that_sign_ext_mask = (_AP_W1==APINT_BITS_PER_WORD)?0:~0ULL>>(_AP_W1%APINT_BITS_PER_WORD)<<(_AP_W1%APINT_BITS_PER_WORD); + if (RHS.isNegative()) { + pVal[0] = RHS.VAL | that_sign_ext_mask; + memset(pVal+1,~0, APINT_WORD_SIZE*(_AP_N-1)); + } else { + pVal[0] = RHS.VAL; + memset(pVal+1, 0, APINT_WORD_SIZE*(_AP_N-1)); + } + clearUnusedBits(); + return *this; + } + + template + INLINE ap_private& operator=(const volatile ap_private<_AP_W1, _AP_S1, 1>& RHS) { + static const uint64_t that_sign_ext_mask = (_AP_W1==APINT_BITS_PER_WORD)?0:~0ULL>>(_AP_W1%APINT_BITS_PER_WORD)<<(_AP_W1%APINT_BITS_PER_WORD); + if (RHS.isNegative()) { + pVal[0] = RHS.VAL | that_sign_ext_mask; + memset(pVal+1,~0, APINT_WORD_SIZE*(_AP_N-1)); + } else { + pVal[0] = RHS.VAL; + memset(pVal+1, 0, APINT_WORD_SIZE*(_AP_N-1)); + } + clearUnusedBits(); + return *this; + } + + /// @} + /// @name Unary Operators + /// @{ + /// @returns a new ap_private value representing *this incremented by one + /// @brief Postfix increment operator. + INLINE const ap_private operator++(int) { + ap_private API(*this); + ++(*this); + return API; + } + + /// @returns *this incremented by one + /// @brief Prefix increment operator. + INLINE ap_private& operator++() { + add_1(pVal, pVal, _AP_N, 1); + clearUnusedBits(); + return *this; + } + + /// @returns a new ap_private representing *this decremented by one. + /// @brief Postfix decrement operator. + INLINE const ap_private operator--(int) { + ap_private API(*this); + --(*this); + return API; + } + + /// @returns *this decremented by one. + /// @brief Prefix decrement operator. + INLINE ap_private& operator--() { + sub_1(pVal, _AP_N, 1); + clearUnusedBits(); + return *this; + } + + /// Performs a bitwise complement operation on this ap_private. + /// @returns an ap_private that is the bitwise complement of *this + /// @brief Unary bitwise complement operator. + INLINE ap_private operator~() const { + ap_private Result(*this); + Result.flip(); + return Result; + } + + /// Negates *this using two's complement logic. + /// @returns An ap_private value representing the negation of *this. + /// @brief Unary negation operator + INLINE typename RType<1,false>::minus operator-() const { + return ap_private<1,false>(0) - (*this); + } + + /// Performs logical negation operation on this ap_private. + /// @returns true if *this is zero, false otherwise. + /// @brief Logical negation operator. + INLINE bool operator !() const { + for (uint32_t i = 0; i < _AP_N; ++i) + if (pVal[i]) + return false; + return true; + } + + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> And(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return this->operator&(RHS); + } + template + INLINE ap_private Or(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return this->operator|(RHS); + } + template + ap_private Xor(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return this->operator^(RHS); + } + + ap_private Mul(const ap_private& RHS) const { + ap_private Result(*this); + Result *= RHS; + return Result; + } + + ap_private Add(const ap_private& RHS) const { + ap_private Result(0); + bool carry = add(Result.pVal, this->pVal, RHS.pVal, _AP_N, _AP_N, _AP_N, _AP_S, _AP_S); + Result.clearUnusedBits(); + return Result; + } + + ap_private Sub(const ap_private& RHS) const { + ap_private Result(0); + sub(Result.pVal, this->pVal, RHS.pVal, _AP_N, _AP_N, _AP_N, _AP_S, _AP_S); + Result.clearUnusedBits(); + return Result; + } + + /// Arithmetic right-shift this ap_private by shiftAmt. + /// @brief Arithmetic right-shift function. + ap_private ashr(uint32_t shiftAmt) const { + assert(shiftAmt <= BitWidth && "Invalid shift amount, too big"); + // Handle a degenerate case + if (shiftAmt == 0) + return *this; + + // Handle single word shifts with built-in ashr + if (isSingleWord()) { + if (shiftAmt == BitWidth) + return ap_private(/*BitWidth, 0*/); // undefined + else { + uint32_t SignBit = APINT_BITS_PER_WORD - BitWidth; + return ap_private(/*BitWidth,*/ + (((int64_t(VAL) << (SignBit)) >> (SignBit)) >> (shiftAmt))); + } + } + + // If all the bits were shifted out, the result is, technically, undefined. + // We return -1 if it was negative, 0 otherwise. We check this early to avoid + // issues in the algorithm below. + if (shiftAmt == BitWidth) { + if (isNegative()) + return ap_private(-1); + else + return ap_private(0); + } + + // Create some space for the result. + ap_private Retval(0); + uint64_t * val = Retval.pVal; + + // Compute some values needed by the following shift algorithms + uint32_t wordShift = shiftAmt % APINT_BITS_PER_WORD; // bits to shift per word + uint32_t offset = shiftAmt / APINT_BITS_PER_WORD; // word offset for shift + uint32_t breakWord = _AP_N - 1 - offset; // last word affected + uint32_t bitsInWord = whichBit(BitWidth); // how many bits in last word? + if (bitsInWord == 0) + bitsInWord = APINT_BITS_PER_WORD; + + // If we are shifting whole words, just move whole words + if (wordShift == 0) { + // Move the words containing significant bits + for (uint32_t i = 0; i <= breakWord; ++i) + val[i] = pVal[i+offset]; // move whole word + + // Adjust the top significant word for sign bit fill, if negative + if (isNegative()) + if (bitsInWord < APINT_BITS_PER_WORD) + val[breakWord] |= ~0ULL << (bitsInWord); // set high bits + } else { + // Shift the low order words + for (uint32_t i = 0; i < breakWord; ++i) { + // This combines the shifted corresponding word with the low bits from + // the next word (shifted into this word's high bits). + val[i] = ((pVal[i+offset]) >> (wordShift)); + val[i] |= ((pVal[i+offset+1]) << (APINT_BITS_PER_WORD - wordShift)); + } + + // Shift the break word. In this case there are no bits from the next word + // to include in this word. + val[breakWord] = (pVal[breakWord+offset]) >> (wordShift); + + // Deal with sign extenstion in the break word, and possibly the word before + // it. + if (isNegative()) { + if (wordShift > bitsInWord) { + if (breakWord > 0) + val[breakWord-1] |= + ~0ULL << (APINT_BITS_PER_WORD - (wordShift - bitsInWord)); + val[breakWord] |= ~0ULL; + } else + val[breakWord] |= (~0ULL << (bitsInWord - wordShift)); + } + } + + // Remaining words are 0 or -1, just assign them. + uint64_t fillValue = (isNegative() ? ~0ULL : 0); + for (uint32_t i = breakWord+1; i < _AP_N; ++i) + val[i] = fillValue; + Retval.clearUnusedBits(); + return Retval; + } + + /// Logical right-shift this ap_private by shiftAmt. + /// @brief Logical right-shift function. + ap_private lshr(uint32_t shiftAmt) const { + if (isSingleWord()) { + if (shiftAmt == BitWidth) + return ap_private(0); + else + return ap_private((this->VAL) >> (shiftAmt)); + } + + // If all the bits were shifted out, the result is 0. This avoids issues + // with shifting by the size of the integer type, which produces undefined + // results. We define these "undefined results" to always be 0. + if (shiftAmt == BitWidth) + return ap_private(0); + + // If none of the bits are shifted out, the result is *this. This avoids + // issues with shifting byt he size of the integer type, which produces + // undefined results in the code below. This is also an optimization. + if (shiftAmt == 0) + return *this; + + // Create some space for the result. + ap_private Retval(0); + uint64_t * val = Retval.pVal; + + // If we are shifting less than a word, compute the shift with a simple carry + if (shiftAmt < APINT_BITS_PER_WORD) { + uint64_t carry = 0; + for (int i = _AP_N-1; i >= 0; --i) { + val[i] = ((pVal[i]) >> (shiftAmt)) | carry; + carry = (pVal[i]) << (APINT_BITS_PER_WORD - shiftAmt); + } + Retval.clearUnusedBits(); + return Retval; + } + + // Compute some values needed by the remaining shift algorithms + uint32_t wordShift = shiftAmt % APINT_BITS_PER_WORD; + uint32_t offset = shiftAmt / APINT_BITS_PER_WORD; + + // If we are shifting whole words, just move whole words + if (wordShift == 0) { + for (uint32_t i = 0; i < _AP_N - offset; ++i) + val[i] = pVal[i+offset]; + for (uint32_t i = _AP_N-offset; i < _AP_N; i++) + val[i] = 0; + Retval.clearUnusedBits(); + return Retval; + } + + // Shift the low order words + uint32_t breakWord = _AP_N - offset -1; + for (uint32_t i = 0; i < breakWord; ++i) + val[i] = ((pVal[i+offset]) >> (wordShift)) | + ((pVal[i+offset+1]) << (APINT_BITS_PER_WORD - wordShift)); + // Shift the break word. + val[breakWord] = (pVal[breakWord+offset]) >> (wordShift); + + // Remaining words are 0 + for (uint32_t i = breakWord+1; i < _AP_N; ++i) + val[i] = 0; + Retval.clearUnusedBits(); + return Retval; + } + + /// Left-shift this ap_private by shiftAmt. + /// @brief Left-shift function. + ap_private shl(uint32_t shiftAmt) const { + assert(shiftAmt <= BitWidth && "Invalid shift amount, too big"); + if (isSingleWord()) { + if (shiftAmt == BitWidth) + return ap_private(0); // avoid undefined shift results + return ap_private((VAL) << (shiftAmt)); + } + + // If all the bits were shifted out, the result is 0. This avoids issues + // with shifting by the size of the integer type, which produces undefined + // results. We define these "undefined results" to always be 0. + if (shiftAmt == BitWidth) + return ap_private(0); + + // If none of the bits are shifted out, the result is *this. This avoids a + // lshr by the words size in the loop below which can produce incorrect + // results. It also avoids the expensive computation below for a common case. + if (shiftAmt == 0) + return *this; + + // Create some space for the result. + ap_private Retval(0); + uint64_t* val = Retval.pVal; + // If we are shifting less than a word, do it the easy way + if (shiftAmt < APINT_BITS_PER_WORD) { + uint64_t carry = 0; + for (uint32_t i = 0; i < _AP_N; i++) { + val[i] = ((pVal[i]) << (shiftAmt)) | carry; + carry = (pVal[i]) >> (APINT_BITS_PER_WORD - shiftAmt); + } + Retval.clearUnusedBits(); + return Retval; + } + + // Compute some values needed by the remaining shift algorithms + uint32_t wordShift = shiftAmt % APINT_BITS_PER_WORD; + uint32_t offset = shiftAmt / APINT_BITS_PER_WORD; + + // If we are shifting whole words, just move whole words + if (wordShift == 0) { + for (uint32_t i = 0; i < offset; i++) + val[i] = 0; + for (uint32_t i = offset; i < _AP_N; i++) + val[i] = pVal[i-offset]; + Retval.clearUnusedBits(); + return Retval; + } + + // Copy whole words from this to Result. + uint32_t i = _AP_N - 1; + for (; i > offset; --i) + val[i] = (pVal[i-offset]) << (wordShift) | + (pVal[i-offset-1]) >> (APINT_BITS_PER_WORD - wordShift); + val[offset] = (pVal[0]) << (wordShift); + for (i = 0; i < offset; ++i) + val[i] = 0; + Retval.clearUnusedBits(); + return Retval; + } + + INLINE ap_private rotl(uint32_t rotateAmt) const { + if (rotateAmt == 0) + return *this; + // Don't get too fancy, just use existing shift/or facilities + ap_private hi(*this); + ap_private lo(*this); + hi.shl(rotateAmt); + lo.lshr(BitWidth - rotateAmt); + return hi | lo; + } + + INLINE ap_private rotr(uint32_t rotateAmt) const { + if (rotateAmt == 0) + return *this; + // Don't get too fancy, just use existing shift/or facilities + ap_private hi(*this); + ap_private lo(*this); + lo.lshr(rotateAmt); + hi.shl(BitWidth - rotateAmt); + return hi | lo; + } + + /// Perform an unsigned divide operation on this ap_private by RHS. Both this and + /// RHS are treated as unsigned quantities for purposes of this division. + /// @returns a new ap_private value containing the division result + /// @brief Unsigned division operation. + ap_private udiv(const ap_private& RHS) const { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + + // First, deal with the easy case + if (isSingleWord()) { + assert(RHS.VAL != 0 && "Divide by zero?"); + return ap_private(VAL / RHS.VAL); + } + + // Get some facts about the LHS and RHS number of bits and words + uint32_t rhsBits = RHS.getActiveBits(); + uint32_t rhsWords = !rhsBits ? 0 : (whichWord(rhsBits - 1) + 1); + assert(rhsWords && "Divided by zero???"); + uint32_t lhsBits = this->getActiveBits(); + uint32_t lhsWords = !lhsBits ? 0 : (whichWord(lhsBits - 1) + 1); + + // Deal with some degenerate cases + if (!lhsWords) + // 0 / X ===> 0 + return ap_private(0); + else if (lhsWords < rhsWords || this->ult(RHS)) { + // X / Y ===> 0, iff X < Y + return ap_private(0); + } else if (*this == RHS) { + // X / X ===> 1 + return ap_private(1); + } else if (lhsWords == 1 && rhsWords == 1) { + // All high words are zero, just use native divide + return ap_private(this->pVal[0] / RHS.pVal[0]); + } + + // We have to compute it the hard way. Invoke the Knuth divide algorithm. + ap_private Quotient(0); // to hold result. + divide(*this, lhsWords, RHS, rhsWords, &Quotient, (ap_private*)0); + return Quotient; + } + + /// Signed divide this ap_private by ap_private RHS. + /// @brief Signed division function for ap_private. + INLINE ap_private sdiv(const ap_private& RHS) const { + if (isNegative()) + if (RHS.isNegative()) + return (-(*this)).udiv(-RHS); + else + return -((-(*this)).udiv(RHS)); + else if (RHS.isNegative()) + return -(this->udiv(-RHS)); + return this->udiv(RHS); + } + + /// Perform an unsigned remainder operation on this ap_private with RHS being the + /// divisor. Both this and RHS are treated as unsigned quantities for purposes + /// of this operation. Note that this is a true remainder operation and not + /// a modulo operation because the sign follows the sign of the dividend + /// which is *this. + /// @returns a new ap_private value containing the remainder result + /// @brief Unsigned remainder operation. + ap_private urem(const ap_private& RHS) const { + if (isSingleWord()) { + assert(RHS.VAL != 0 && "Remainder by zero?"); + return ap_private(VAL % RHS.VAL); + } + + // Get some facts about the LHS + uint32_t lhsBits = getActiveBits(); + uint32_t lhsWords = !lhsBits ? 0 : (whichWord(lhsBits - 1) + 1); + + // Get some facts about the RHS + uint32_t rhsBits = RHS.getActiveBits(); + uint32_t rhsWords = !rhsBits ? 0 : (whichWord(rhsBits - 1) + 1); + assert(rhsWords && "Performing remainder operation by zero ???"); + + // Check the degenerate cases + if (lhsWords == 0) { + // 0 % Y ===> 0 + return ap_private(0); + } else if (lhsWords < rhsWords || this->ult(RHS)) { + // X % Y ===> X, iff X < Y + return *this; + } else if (*this == RHS) { + // X % X == 0; + return ap_private(0); + } else if (lhsWords == 1) { + // All high words are zero, just use native remainder + return ap_private(pVal[0] % RHS.pVal[0]); + } + + // We have to compute it the hard way. Invoke the Knuth divide algorithm. + ap_private Remainder(0); + divide(*this, lhsWords, RHS, rhsWords, (ap_private*)(0), &Remainder); + return Remainder; + } + + ap_private urem(uint64_t RHS) const { + // Get some facts about the LHS + uint32_t lhsBits = getActiveBits(); + uint32_t lhsWords = !lhsBits ? 0 : (whichWord(lhsBits - 1) + 1); + // Get some facts about the RHS + uint32_t rhsBits = 64 - CountLeadingZeros_64(RHS); // RHS.getActiveBits(); + uint32_t rhsWords = 1;//!rhsBits ? 0 : (ap_private<_AP_W, _AP_S, _AP_N>::whichWord(rhsBits - 1) + 1); + assert(rhsWords && "Performing remainder operation by zero ???"); + // Check the degenerate cases + if (lhsWords == 0) { + // 0 % Y ===> 0 + return ap_private(0); + } else if (lhsWords < rhsWords || this->ult(RHS)) { + // X % Y ===> X, iff X < Y + return *this; + } else if (*this == RHS) { + // X % X == 0; + return ap_private(0); + } else if (lhsWords == 1) { + // All high words are zero, just use native remainder + return ap_private(pVal[0] % RHS); + } + + // We have to compute it the hard way. Invoke the Knuth divide algorithm. + ap_private Remainder(0); + divide(*this, lhsWords, RHS, (ap_private*)(0), &Remainder); + return Remainder; + } + + /// Signed remainder operation on ap_private. + /// @brief Function for signed remainder operation. + INLINE ap_private srem(const ap_private& RHS) const { + if (isNegative()) { + ap_private lhs = -(*this); + if (RHS.isNegative()) { + ap_private rhs = -RHS; + return -(lhs.urem(rhs)); + } else + return -(lhs.urem(RHS)); + } else if (RHS.isNegative()) { + ap_private rhs = -RHS; + return this->urem(rhs); + } + return this->urem(RHS); + } + + /// Signed remainder operation on ap_private. + /// @brief Function for signed remainder operation. + INLINE ap_private srem(int64_t RHS) const { + if (isNegative()) + if (RHS<0) + return -((-(*this)).urem(-RHS)); + else + return -((-(*this)).urem(RHS)); + else if (RHS<0) + return this->urem(-RHS); + return this->urem(RHS); + } + + /// Sometimes it is convenient to divide two ap_private values and obtain both + /// the quotient and remainder. This function does both operations in the + /// same computation making it a little more efficient. + /// @brief Dual division/remainder interface. + static void udivrem(const ap_private& LHS, const ap_private& RHS, ap_private &Quotient, ap_private& Remainder) { + // Get some size facts about the dividend and divisor + uint32_t lhsBits = LHS.getActiveBits(); + uint32_t lhsWords = !lhsBits ? 0 : (ap_private::whichWord(lhsBits - 1) + 1); + uint32_t rhsBits = RHS.getActiveBits(); + uint32_t rhsWords = !rhsBits ? 0 : (ap_private::whichWord(rhsBits - 1) + 1); + + // Check the degenerate cases + if (lhsWords == 0) { + Quotient = 0; // 0 / Y ===> 0 + Remainder = 0; // 0 % Y ===> 0 + return; + } + + if (lhsWords < rhsWords || LHS.ult(RHS)) { + Quotient = 0; // X / Y ===> 0, iff X < Y + Remainder = LHS; // X % Y ===> X, iff X < Y + return; + } + + if (LHS == RHS) { + Quotient = 1; // X / X ===> 1 + Remainder = 0; // X % X ===> 0; + return; + } + + if (lhsWords == 1 && rhsWords == 1) { + // There is only one word to consider so use the native versions. + if (LHS.isSingleWord()) { + Quotient = ap_private(LHS.VAL / RHS.VAL); + Remainder = ap_private(LHS.VAL % RHS.VAL); + } else { + Quotient = ap_private(LHS.pVal[0] / RHS.pVal[0]); + Remainder = ap_private(LHS.pVal[0] % RHS.pVal[0]); + } + return; + } + + // Okay, lets do it the long way + divide(LHS, lhsWords, RHS, rhsWords, &Quotient, &Remainder); + } + + static void sdivrem(const ap_private &LHS, const ap_private &RHS, + ap_private &Quotient, ap_private &Remainder) { + if (LHS.isNegative()) { + if (RHS.isNegative()) + ap_private::udivrem(-LHS, -RHS, Quotient, Remainder); + else + ap_private::udivrem(-LHS, RHS, Quotient, Remainder); + Quotient = -Quotient; + Remainder = -Remainder; + } else if (RHS.isNegative()) { + ap_private::udivrem(LHS, -RHS, Quotient, Remainder); + Quotient = -Quotient; + } else { + ap_private::udivrem(LHS, RHS, Quotient, Remainder); + } + } + + /// Compares this ap_private with RHS for the validity of the equality + /// relationship. + /// @returns true if *this == Val + /// @brief Equality comparison. + template + INLINE bool eq(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return (*this) == RHS; + } + + /// Compares this ap_private with RHS for the validity of the inequality + /// relationship. + /// @returns true if *this != Val + /// @brief Inequality comparison + template + INLINE bool ne(const ap_private<_AP_W, _AP_S1, _AP_N> &RHS) const { + return !((*this) == RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// the validity of the less-than relationship. + /// @returns true if *this < RHS when both are considered unsigned. + /// @brief Unsigned less than comparison + template + INLINE bool ult(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + // Get active bit length of both operands + uint32_t n1 = getActiveBits(); + uint32_t n2 = RHS.getActiveBits(); + + // If magnitude of LHS is less than RHS, return true. + if (n1 < n2) + return true; + + // If magnitude of RHS is greather than LHS, return false. + if (n2 < n1) + return false; + + // If they bot fit in a word, just compare the low order word + if (n1 <= APINT_BITS_PER_WORD && n2 <= APINT_BITS_PER_WORD) + return pVal[0] < RHS.pVal[0]; + + // Otherwise, compare all words + uint32_t topWord = whichWord(AESL_std::max(n1,n2)-1); + for (int i = topWord; i >= 0; --i) { + if (pVal[i] > RHS.pVal[i]) + return false; + if (pVal[i] < RHS.pVal[i]) + return true; + } + return false; + } + + INLINE bool ult(uint64_t RHS) const { + // Get active bit length of both operands + uint32_t n1 = getActiveBits(); + uint32_t n2 = 64 - CountLeadingZeros_64(RHS); //RHS.getActiveBits(); + + // If magnitude of LHS is less than RHS, return true. + if (n1 < n2) + return true; + + // If magnitude of RHS is greather than LHS, return false. + if (n2 < n1) + return false; + + // If they bot fit in a word, just compare the low order word + if (n1 <= APINT_BITS_PER_WORD && n2 <= APINT_BITS_PER_WORD) + return pVal[0] < RHS; + assert(0); + } + + template + INLINE bool slt(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + ap_private lhs(*this); + ap_private<_AP_W, _AP_S1, _AP_N> rhs(RHS); + bool lhsNeg = isNegative(); + bool rhsNeg = rhs.isNegative(); + if (lhsNeg) { + // Sign bit is set so perform two's complement to make it positive + lhs.flip(); + lhs++; + } + if (rhsNeg) { + // Sign bit is set so perform two's complement to make it positive + rhs.flip(); + rhs++; + } + + // Now we have unsigned values to compare so do the comparison if necessary + // based on the negativeness of the values. + if (lhsNeg) + if (rhsNeg) + return lhs.ugt(rhs); + else + return true; + else if (rhsNeg) + return false; + else + return lhs.ult(rhs); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// validity of the less-or-equal relationship. + /// @returns true if *this <= RHS when both are considered unsigned. + /// @brief Unsigned less or equal comparison + template + INLINE bool ule(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return ult(RHS) || eq(RHS); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the less-or-equal relationship. + /// @returns true if *this <= RHS when both are considered signed. + /// @brief Signed less or equal comparison + template + INLINE bool sle(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return slt(RHS) || eq(RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// the validity of the greater-than relationship. + /// @returns true if *this > RHS when both are considered unsigned. + /// @brief Unsigned greather than comparison + template + INLINE bool ugt(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return !ult(RHS) && !eq(RHS); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// the validity of the greater-than relationship. + /// @returns true if *this > RHS when both are considered signed. + /// @brief Signed greather than comparison + template + INLINE bool sgt(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return !slt(RHS) && !eq(RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// validity of the greater-or-equal relationship. + /// @returns true if *this >= RHS when both are considered unsigned. + /// @brief Unsigned greater or equal comparison + template + INLINE bool uge(const ap_private<_AP_W, _AP_S, _AP_N>& RHS) const { + return !ult(RHS); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the greater-or-equal relationship. + /// @returns true if *this >= RHS when both are considered signed. + /// @brief Signed greather or equal comparison + template + INLINE bool sge(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return !slt(RHS); + } + + template + void cpTrunc(const ap_private<_AP_W1, _AP_S1, _AP_N1>& that) { + assert(_AP_W1 > BitWidth && "Invalid ap_private Truncate request"); + assert(_AP_W1 >= MIN_INT_BITS && "Can't truncate to 0 bits"); + memcpy(pVal, that.pVal, _AP_N*APINT_WORD_SIZE); + } + + // Sign extend to a new width. + template + void cpSext(const ap_private<_AP_W1, _AP_S1, _AP_N1>& that) { + assert(_AP_W1 < BitWidth && "Invalid ap_private SignExtend request"); + assert(_AP_W1 <= MAX_INT_BITS && "Too many bits"); + // If the sign bit isn't set, this is the same as zext. + if (!that.isNegative()) { + cpZext(that); + return; + } + + // The sign bit is set. First, get some facts + enum { wordBits = _AP_W1 % APINT_BITS_PER_WORD}; + + // Mask the high order word appropriately + if (_AP_N1 == _AP_N) { + enum { newWordBits = _AP_W % APINT_BITS_PER_WORD}; + // The extension is contained to the wordsBefore-1th word. + static const uint64_t mask = wordBits?(~0ULL<<(wordBits)):0ULL; + if (_AP_N1 == 1) { + assert(0); + } else { + for (uint32_t i = 0; i < _AP_N1; ++i) + pVal[i] = that.pVal[i]; + pVal[_AP_N1-1] |= mask; + return; + } + } + + if (_AP_N1 == 1) { + assert(0);// newVal[0] = VAL | mask; + } else { + enum { newWordBits = _AP_W % APINT_BITS_PER_WORD}; + // The extension is contained to the wordsBefore-1th word. + static const uint64_t mask = wordBits?(~0ULL<<(wordBits)):0ULL; + for (uint32_t i = 0; i < _AP_N1; ++i) + pVal[i] = that.pVal[i]; + pVal[_AP_N1-1] |= mask; + } + for (uint32_t i=_AP_N1; i < _AP_N-1; i++) + pVal[i] = ~0ULL; + pVal[_AP_N-1] = ~0ULL; + clearUnusedBits(); + return; + } + + // Zero extend to a new width. + template + void cpZext(const ap_private<_AP_W1, _AP_S1, _AP_N1>& that) { + assert(_AP_W1 < BitWidth && "Invalid ap_private ZeroExtend request"); + assert(_AP_W1 <= MAX_INT_BITS && "Too many bits"); + uint32_t wordsAfter = _AP_N; + if (wordsAfter==1) { + assert(0); // return ap_private<_AP_W1, _AP_S, _AP_N1> (_AP_W1, VAL, _AP_S); + } else { + if (_AP_N1 == 1) { + assert(0); + // newVal[0] = VAL; + } else { + uint32_t i = 0; + for (; i < _AP_N1; ++i) + pVal[i] = that.pVal[i]; + for (; i < _AP_N; ++i) + pVal[i] = 0; + } + } + clearUnusedBits(); + } + + template + void cpZextOrTrunc(const ap_private<_AP_W1, _AP_S1, _AP_N1>& that) { + if (BitWidth > _AP_W1) + cpZext(that); + else if (BitWidth < _AP_W1) + cpTrunc(that); + else { + for (int i=0; i<_AP_N1; ++i) + pVal[i]=that.pVal[i]; + clearUnusedBits(); + } + } + + template + void cpSextOrTrunc(const ap_private<_AP_W1, _AP_S1, _AP_N1>& that) { + if (BitWidth > _AP_W1) + cpSext(that); + else if (BitWidth < _AP_W1) + cpTrunc(that); + else { + for (int i=0; i<_AP_N1; ++i) + pVal[i] = that.pVal[i]; + clearUnusedBits(); + } + } + + /// @name Value Characterization Functions + /// @{ + + /// @returns the total number of bits. + INLINE uint32_t getBitWidth() const { + return BitWidth; + } + + /// Here one word's bitwidth equals to that of uint64_t. + /// @returns the number of words to hold the integer value of this ap_private. + /// @brief Get the number of words. + INLINE uint32_t getNumWords() const { + return (BitWidth + APINT_BITS_PER_WORD - 1) / APINT_BITS_PER_WORD; + } + + /// This function returns the number of active bits which is defined as the + /// bit width minus the number of leading zeros. This is used in several + /// computations to see how "wide" the value is. + /// @brief Compute the number of active bits in the value + INLINE uint32_t getActiveBits() const { + uint32_t bits=BitWidth - countLeadingZeros(); + return bits?bits:1; + } + + + /// This method attempts to return the value of this ap_private as a zero extended + /// uint64_t. The bitwidth must be <= 64 or the value must fit within a + /// uint64_t. Otherwise an assertion will result. + /// @brief Get zero extended value + INLINE uint64_t getZExtValue() const { + assert(getActiveBits() <= 64 && "Too many bits for uint64_t"); + return *pVal; + } + + /// This method attempts to return the value of this ap_private as a sign extended + /// int64_t. The bit width must be <= 64 or the value must fit within an + /// int64_t. Otherwise an assertion will result. + /// @brief Get sign extended value + INLINE int64_t getSExtValue() const { + assert(getActiveBits() <= 64 && "Too many bits for int64_t"); + return int64_t(pVal[0]); + } + + /// This method determines how many bits are required to hold the ap_private + /// equivalent of the string given by \p str of length \p slen. + /// @brief Get bits required for string value. + static uint32_t getBitsNeeded(const char* str, uint32_t slen, uint8_t radix); + + /// countLeadingZeros - This function is an ap_private version of the + /// countLeadingZeros_{32,64} functions in MathExtras.h. It counts the number + /// of zeros from the most significant bit to the first one bit. + /// @returns BitWidth if the value is zero. + /// @returns the number of zeros from the most significant bit to the first + /// one bits. + INLINE uint32_t countLeadingZeros() const ; + + /// countLeadingOnes - This function counts the number of contiguous 1 bits + /// in the high order bits. The count stops when the first 0 bit is reached. + /// @returns 0 if the high order bit is not set + /// @returns the number of 1 bits from the most significant to the least + /// @brief Count the number of leading one bits. + INLINE uint32_t countLeadingOnes() const ; + + /// countTrailingZeros - This function is an ap_private version of the + /// countTrailingZoers_{32,64} functions in MathExtras.h. It counts + /// the number of zeros from the least significant bit to the first set bit. + /// @returns BitWidth if the value is zero. + /// @returns the number of zeros from the least significant bit to the first + /// one bit. + /// @brief Count the number of trailing zero bits. + INLINE uint32_t countTrailingZeros() const ; + + /// countPopulation - This function is an ap_private version of the + /// countPopulation_{32,64} functions in MathExtras.h. It counts the number + /// of 1 bits in the ap_private value. + /// @returns 0 if the value is zero. + /// @returns the number of set bits. + /// @brief Count the number of bits set. + INLINE uint32_t countPopulation() const { + uint32_t Count = 0; + for (uint32_t i = 0; i<_AP_N-1 ; ++i) + Count += CountPopulation_64(pVal[i]); + Count += CountPopulation_64(pVal[_AP_N-1]&mask); + return Count; + } + + /// @} + /// @name Conversion Functions + /// @{ + + /// This is used internally to convert an ap_private to a string. + /// @brief Converts an ap_private to a std::string + INLINE std::string toString(uint8_t radix, bool wantSigned) const + ; + + /// Considers the ap_private to be unsigned and converts it into a string in the + /// radix given. The radix can be 2, 8, 10 or 16. + /// @returns a character interpretation of the ap_private + /// @brief Convert unsigned ap_private to string representation. + INLINE std::string toStringUnsigned(uint8_t radix = 10) const { + return toString(radix, false); + } + + /// Considers the ap_private to be unsigned and converts it into a string in the + /// radix given. The radix can be 2, 8, 10 or 16. + /// @returns a character interpretation of the ap_private + /// @brief Convert unsigned ap_private to string representation. + INLINE std::string toStringSigned(uint8_t radix = 10) const { + return toString(radix, true); + } + + /// @returns a byte-swapped representation of this ap_private Value. + INLINE ap_private byteSwap() const ; + + /// @brief Converts this ap_private to a double value. + INLINE double roundToDouble(bool isSigned) const ; + + /// @brief Converts this unsigned ap_private to a double value. + INLINE double roundToDouble() const { + return roundToDouble(false); + } + + /// @brief Converts this signed ap_private to a double value. + INLINE double signedRoundToDouble() const { + return roundToDouble(true); + } + + /// The conversion does not do a translation from integer to double, it just + /// re-interprets the bits as a double. Note that it is valid to do this on + /// any bit width. Exactly 64 bits will be translated. + /// @brief Converts ap_private bits to a double + INLINE double bitsToDouble() const { + union { + uint64_t __I; + double __D; + } __T; + __T.__I = pVal[0]; + return __T.__D; + } + + /// The conversion does not do a translation from integer to float, it just + /// re-interprets the bits as a float. Note that it is valid to do this on + /// any bit width. Exactly 32 bits will be translated. + /// @brief Converts ap_private bits to a double + INLINE float bitsToFloat() const { + union { + uint32_t __I; + float __F; + } __T; + __T.__I = uint32_t(pVal[0]); + return __T.__F; + } + + /// The conversion does not do a translation from double to integer, it just + /// re-interprets the bits of the double. Note that it is valid to do this on + /// any bit width but bits from V may get truncated. + /// @brief Converts a double to ap_private bits. + INLINE ap_private& doubleToBits(double __V) { + union { + uint64_t __I; + double __D; + } __T; + __T.__D = __V; + pVal[0] = __T.__I; + return *this; + } + + /// The conversion does not do a translation from float to integer, it just + /// re-interprets the bits of the float. Note that it is valid to do this on + /// any bit width but bits from V may get truncated. + /// @brief Converts a float to ap_private bits. + INLINE ap_private& floatToBits(float __V) { + union { + uint32_t __I; + float __F; + } __T; + __T.__F = __V; + pVal[0] = __T.__I; + } + + //Reduce operation + //----------------------------------------------------------- + INLINE bool and_reduce() const { + return isMaxValue(); + } + + INLINE bool nand_reduce() const { + return isMinValue(); + } + + INLINE bool or_reduce() const { + return (bool)countPopulation(); + } + + INLINE bool nor_reduce() const { + return countPopulation()==0; + } + + INLINE bool xor_reduce() const { + unsigned int i=countPopulation(); + return (i%2)?true:false; + } + + INLINE bool xnor_reduce() const { + unsigned int i=countPopulation(); + return (i%2)?false:true; + } + INLINE std::string to_string(uint8_t radix=16, bool sign=false) const { + return toString(radix, radix==10?_AP_S:sign); + } +}; + +template +INLINE bool operator==(uint64_t V1, const ap_private<_AP_W, _AP_S, _AP_N>& V2) { + return V2 == V1; +} + +template +INLINE bool operator!=(uint64_t V1, const ap_private<_AP_W, _AP_S, _AP_N>& V2) { + return V2 != V1; +} + +namespace ap_private_ops { + enum {APINT_BITS_PER_WORD=64}; + /// @brief Determine the smaller of two ap_privates considered to be signed. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> smin(const ap_private<_AP_W, _AP_S, _AP_N> &LHS, const ap_private<_AP_W, _AP_S1, _AP_N> &RHS) { + return LHS.slt(RHS) ? LHS : RHS; + } + + /// @brief Determine the larger of two ap_privates considered to be signed. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> smax(const ap_private<_AP_W, _AP_S, _AP_N> &LHS, const ap_private<_AP_W, _AP_S1, _AP_N> &RHS) { + return LHS.sgt(RHS) ? LHS : RHS; + } + + /// @brief Determine the smaller of two ap_privates considered to be signed. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> umin(const ap_private<_AP_W, _AP_S, _AP_N> &LHS, const ap_private<_AP_W, _AP_S1, _AP_N> &RHS) { + return LHS.ult(RHS) ? LHS : RHS; + } + + /// @brief Determine the larger of two ap_privates considered to be unsigned. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> umax(const ap_private<_AP_W, _AP_S, _AP_N> &LHS, const ap_private<_AP_W, _AP_S1, _AP_N> &RHS) { + return LHS.ugt(RHS) ? LHS : RHS; + } + + /// @brief Check if the specified ap_private has a N-bits integer value. + template + INLINE bool isIntN(uint32_t __N, const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.isIntN(__N); + } + + /// @returns true if the argument ap_private value is a sequence of ones + /// starting at the least significant bit with the remainder zero. + template + INLINE bool isMask(uint32_t numBits, const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.getBoolValue() && ((APIVal + ap_private<_AP_W, _AP_S, _AP_N>(numBits,1)) & APIVal) == 0; + } + + /// @returns true if the argument ap_private value contains a sequence of ones + /// with the remainder zero. + template + INLINE bool isShiftedMask(uint32_t numBits, const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return isMask(numBits, (APIVal - ap_private<_AP_W, _AP_S, _AP_N>(numBits,1)) | APIVal); + } + + /// @returns a byte-swapped representation of the specified ap_private Value. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> byteSwap(const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.byteSwap(); + } + + /// @returns the floor log base 2 of the specified ap_private value. + template INLINE uint32_t logBase2(const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.logBase2(); + } + + /// GreatestCommonDivisor - This function returns the greatest common + /// divisor of the two ap_private values using Enclid's algorithm. + /// @returns the greatest common divisor of Val1 and Val2 + /// @brief Compute GCD of two ap_private values. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> GreatestCommonDivisor(const ap_private<_AP_W, _AP_S, _AP_N>& Val1, const ap_private<_AP_W, _AP_S, _AP_N>& Val2) + ; + + /// Treats the ap_private as an unsigned value for conversion purposes. + /// @brief Converts the given ap_private to a double value. + template INLINE double Roundap_privateToDouble(const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.roundToDouble(); + } + + /// Treats the ap_private as a signed value for conversion purposes. + /// @brief Converts the given ap_private to a double value. + template INLINE double RoundSignedap_privateToDouble(const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.signedRoundToDouble(); + } + + /// @brief Converts the given ap_private to a float vlalue. + template INLINE float Roundap_privateToFloat(const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return float(Roundap_privateToDouble(APIVal)); + } + + /// Treast the ap_private as a signed value for conversion purposes. + /// @brief Converts the given ap_private to a float value. + template INLINE float RoundSignedap_privateToFloat(const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return float(APIVal.signedRoundToDouble()); + } + + /// RoundDoubleToap_private - This function convert a double value to an ap_private value. + /// @brief Converts the given double value into a ap_private. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> RoundDoubleToap_private(double Double, uint32_t width) ; + + /// RoundFloatToap_private - Converts a float value into an ap_private value. + /// @brief Converts a float value into a ap_private. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> RoundFloatToap_private(float Float, uint32_t width) { + return RoundDoubleToap_private<_AP_W, _AP_S, _AP_N>(double(Float), width); + } + + /// Arithmetic right-shift the ap_private by shiftAmt. + /// @brief Arithmetic right-shift function. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> ashr(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, uint32_t shiftAmt) { + return LHS.ashr(shiftAmt); + } + + /// Logical right-shift the ap_private by shiftAmt. + /// @brief Logical right-shift function. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> lshr(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, uint32_t shiftAmt) { + return LHS.lshr(shiftAmt); + } + + /// Left-shift the ap_private by shiftAmt. + /// @brief Left-shift function. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> shl(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, uint32_t shiftAmt) { + return LHS.shl(shiftAmt); + } + + /// Signed divide ap_private LHS by ap_private RHS. + /// @brief Signed division function for ap_private. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> sdiv(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS.sdiv(RHS); + } + + /// Unsigned divide ap_private LHS by ap_private RHS. + /// @brief Unsigned division function for ap_private. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> udiv(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS.udiv(RHS); + } + + /// Signed remainder operation on ap_private. + /// @brief Function for signed remainder operation. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> srem(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS.srem(RHS); + } + + /// Unsigned remainder operation on ap_private. + /// @brief Function for unsigned remainder operation. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> urem(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS.urem(RHS); + } + + /// Performs multiplication on ap_private values. + /// @brief Function for multiplication operation. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> mul(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS * RHS; + } + + /// Performs addition on ap_private values. + /// @brief Function for addition operation. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> add(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS + RHS; + } + + /// Performs subtraction on ap_private values. + /// @brief Function for subtraction operation. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> sub(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS - RHS; + } + + /// Performs bitwise AND operation on ap_private LHS and + /// ap_private RHS. + /// @brief Bitwise AND function for ap_private. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> And(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS & RHS; + } + + /// Performs bitwise OR operation on ap_private LHS and ap_private RHS. + /// @brief Bitwise OR function for ap_private. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> Or(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS | RHS; + } + + /// Performs bitwise XOR operation on ap_private. + /// @brief Bitwise XOR function for ap_private. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> Xor(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS ^ RHS; + } + + /// Performs a bitwise complement operation on ap_private. + /// @brief Bitwise complement function. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> Not(const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return ~APIVal; + } + + template void clearUnusedBits(uint64_t& msw) { + // Compute how many bits are used in the final word + // uint32_t wordBits = APIVal.getBitWidth() & 0x3f; + if (wordBits == 0) + // If all bits are used, we want to leave the value alone. This also + // avoids the undefined behavior of >> when the shfit is the same size as + // the word size (64). + return; + + // Mask out the hight bits. + uint64_t mask = ~uint64_t(0ULL) >> (64 /*ap_private::APINT_BITS_PER_WORD */- wordBits); + msw &= mask; + } + template <> INLINE void clearUnusedBits<1>(uint64_t& msw) { + uint64_t mask = ~uint64_t(0ULL) >> (64 /*ap_private::APINT_BITS_PER_WORD */- 1); + msw &= mask; + } + template void clearUnusedBits(int64_t& msw) { + // Compute how many bits are used in the final word + // uint32_t wordBits = APIVal.getBitWidth() & 0x3f; + if (wordBits == 0) + // If all bits are used, we want to leave the value alone. This also + // avoids the undefined behavior of >> when the shfit is the same size as + // the word size (64). + return; + + // Mask out the hight bits. + uint64_t mask = ~uint64_t(0ULL) >> (64 /*ap_private::APINT_BITS_PER_WORD */- wordBits); + msw &= mask; + } + template <> INLINE void clearUnusedBits<1>(int64_t& msw) { + uint64_t mask = ~uint64_t(0ULL) >> (64 /*ap_private::APINT_BITS_PER_WORD */- 1); + msw &= mask; + } + // template + template + INLINE ap_private<_AP_W, _AP_S> ashr(const ap_private<_AP_W, _AP_S>& a) { + return ashr(a, shiftAmt); + } + + template + INLINE ap_private<_AP_W, _AP_S> lshr(const ap_private<_AP_W, _AP_S>& a) { + return lshr(a, shiftAmt); + } + + template + INLINE ap_private<_AP_W, true> ashr(const ap_private<_AP_W, true, 1>& a) { + enum {APINT_BITS_PER_WORD=64, excess_bits=APINT_BITS_PER_WORD-_AP_W}; + static const uint64_t sign_bit = (1ULL<<(_AP_W-1)); + static const uint64_t sign_ext_mask = (_AP_W-shiftAmt>0)?~0ULL<<(APINT_BITS_PER_WORD-_AP_W+shiftAmt):~0ULL; + return ap_private<_AP_W, true>((((int64_t)a.VAL) >> (shiftAmt)) | (a.VAL & sign_bit? sign_ext_mask : 0ULL)); + } + + template + INLINE ap_private<_AP_W, false> ashr(const ap_private<_AP_W, false, 1>& a) { + return ap_private<_AP_W, false>((a.VAL) >> (shiftAmt)); + } + + template + INLINE ap_private<_AP_W, _AP_S> lshr(const ap_private<_AP_W, _AP_S, 1>& a) { + static const uint64_t mask = ~0ULL<<_AP_W; + return ap_private<_AP_W, _AP_S>((a.VAL&mask) >> (shiftAmt)); + } + + template + INLINE ap_private<_AP_W-shiftAmt, _AP_S> shr(const ap_private<_AP_W, _AP_S>& a) { + return ap_private<_AP_W-shiftAmt, _AP_S>((a.VAL) >> (shiftAmt)); + } + + template + INLINE ap_private<_AP_W+shiftAmt, _AP_S> shl(const ap_private<_AP_W, _AP_S>& a) { + return ap_private<_AP_W+shiftAmt, _AP_S>((a.VAL) << (shiftAmt)); + } + + template + INLINE bool get(const ap_private<_AP_W, _AP_S, 1>& a) { + unsigned shift = (index%APINT_BITS_PER_WORD); + static const uint64_t mask=1ULL << (shift); + return ((mask & a.VAL) != 0); + } + + template + INLINE bool get(const ap_private<_AP_W, _AP_S>& a) { + static const uint64_t mask=1ULL << (index&0x3f); + return ((mask & a.pVal[(index)>>6]) != 0); + } + + template + INLINE void set(ap_private<_AP_W, _AP_S, 1>& a) { + const uint64_t mask = ~0ULL >> (lsb) << (APINT_BITS_PER_WORD-msb+lsb-1)>>(APINT_BITS_PER_WORD-msb-1); + a.VAL |= mask; + } + + template + INLINE void clear(ap_private<_AP_W, _AP_S, 1>& a) { + static const uint64_t mask = ~(~0ULL >> (lsb) <<(APINT_BITS_PER_WORD-msb+lsb-1) >> (APINT_BITS_PER_WORD-msb-1)); + a.VAL &= mask; + } + + template + INLINE void set(ap_private<_AP_W, _AP_S>& a) { + enum { APINT_BITS_PER_WORD=64, + lsb_word = lsb_index /APINT_BITS_PER_WORD, + msb_word = msb_index / APINT_BITS_PER_WORD, + msb = msb_index % APINT_BITS_PER_WORD, + lsb=lsb_index % APINT_BITS_PER_WORD}; + if (msb_word==lsb_word) { + const uint64_t mask = ~0ULL >> (lsb) << (APINT_BITS_PER_WORD-msb+lsb-1)>>(APINT_BITS_PER_WORD-msb-1); + a.pVal[msb_word] |= mask; + } else { + const uint64_t lsb_mask = ~0ULL >> (lsb) << (lsb); + const uint64_t msb_mask = ~0ULL << (APINT_BITS_PER_WORD-msb-1)>>(APINT_BITS_PER_WORD-msb-1); + a.pVal[lsb_word] |=lsb_mask; + for (int i=lsb_word+1; i + INLINE void clear(ap_private<_AP_W, _AP_S>& a) { + enum { APINT_BITS_PER_WORD=64, + lsb_word = lsb_index /APINT_BITS_PER_WORD, + msb_word = msb_index / APINT_BITS_PER_WORD, + msb = msb_index % APINT_BITS_PER_WORD, + lsb=lsb_index % APINT_BITS_PER_WORD}; + if (msb_word == lsb_word) { + const uint64_t mask = ~(~0ULL >> (lsb) << (APINT_BITS_PER_WORD-msb+lsb-1)>>(APINT_BITS_PER_WORD-msb-1)); + a.pVal[msb_word] &= mask; + } else { + const uint64_t lsb_mask = ~(~0ULL >> (lsb) << (lsb)); + const uint64_t msb_mask = ~(~0ULL << (APINT_BITS_PER_WORD-msb-1)>>(APINT_BITS_PER_WORD-msb-1)); + a.pVal[lsb_word] &=lsb_mask; + for (int i=lsb_word+1; i + INLINE void set(ap_private<_AP_W, _AP_S, 1>& a) { + static const uint64_t mask=1ULL << (index); + a.VAL |= mask; + a.clearUnusedBits(); + } + + template + INLINE void clear(ap_private<_AP_W, _AP_S, 1>& a) { + static const uint64_t mask=~(1ULL << (index)); + a.VAL &= mask; + a.clearUnusedBits(); + } + + template + INLINE void set(ap_private<_AP_W, _AP_S>& a) { + enum { APINT_BITS_PER_WORD=64, word = index/APINT_BITS_PER_WORD}; + static const uint64_t mask=1ULL << (index%APINT_BITS_PER_WORD); + a.pVal[word] |= mask; + a.clearUnusedBits(); + } + + template + INLINE void clear(ap_private<_AP_W, _AP_S>& a) { + enum { APINT_BITS_PER_WORD=64, word = index/APINT_BITS_PER_WORD}; + static const uint64_t mask=~(1ULL << (index%APINT_BITS_PER_WORD)); + a.pVal[word] &= mask; + a.clearUnusedBits(); + } + + template + INLINE bool isNegative(const ap_private<_AP_W, false>& a) { + return false; + } + + template + INLINE bool isNegative(const ap_private<_AP_W, true, 1>& a) { + static const uint64_t sign_mask = (1ULL << (_AP_W-1)); + return ((sign_mask & a.VAL) != 0); + } + + template + INLINE bool isNegative(const ap_private<_AP_W, true>& a) { + enum {APINT_BITS_PER_WORD=64,_AP_N=(_AP_W+APINT_BITS_PER_WORD-1)/APINT_BITS_PER_WORD}; + static const uint64_t sign_mask = (1ULL << (_AP_W%APINT_BITS_PER_WORD-1)); + return sign_mask & a.pVal[_AP_N-1]; + } +} // End of ap_private_ops namespace + +/// @brief Check if the specified ap_private has a N-bits integer value. +template +INLINE bool isIntN(uint32_t __N, const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.isIntN(__N); +} + +/// @returns true if the argument ap_private value is a sequence of ones +/// starting at the least significant bit with the remainder zero. +template +INLINE bool isMask(uint32_t numBits, const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.getBoolValue() && ((APIVal + ap_private<_AP_W, _AP_S, _AP_N>(numBits,1)) & APIVal) == 0; +} + +/// @returns true if the argument ap_private value contains a sequence of ones +/// with the remainder zero. +template +INLINE bool isShiftedMask(uint32_t numBits, const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return isMask(numBits, (APIVal - ap_private<_AP_W, _AP_S, _AP_N>(numBits,1)) | APIVal); +} + +#if 0 +/// add_1 - This function adds a single "digit" integer, y, to the multiple +/// "digit" integer array, x[]. x[] is modified to reflect the addition and +/// 1 is returned if there is a carry out, otherwise 0 is returned. +/// @returns the carry of the addition. +static bool add_1(uint64_t dest[], uint64_t x[], uint32_t len, uint64_t y) { + for (uint32_t i = 0; i < len; ++i) { + dest[i] = y + x[i]; + if (dest[i] < y) + y = 1; // Carry one to next digit. + else { + y = 0; // No need to carry so exit early + break; + } + } + return (y != 0); +} +#endif + +#if 0 +/// add - This function adds the integer array x to the integer array Y and +/// places the result in dest. +/// @returns the carry out from the addition +/// @brief General addition of 64-bit integer arrays +static bool add(uint64_t *dest, const uint64_t *x, const uint64_t *y, + uint32_t destlen, uint32_t xlen, uint32_t ylen, bool xsigned, bool ysigned) { + bool carry = false; + uint32_t len = AESL_std::min(xlen, ylen); + uint32_t i; + for (i = 0; i< len && i < destlen; ++i) { + uint64_t limit = AESL_std::min(x[i],y[i]); // must come first in case dest == x + dest[i] = x[i] + y[i] + carry; + carry = dest[i] < limit || (carry && dest[i] == limit); + } + if (xlen > ylen) { + const uint64_t yext = xsigned && int64_t(y[ylen-1])<0 ? -1 : 0; + for (i=ylen; i< xlen && i < destlen; i++) { + uint64_t limit = AESL_std::min(x[i], yext); + dest[i] = x[i] + yext + carry; + carry = (dest[i] < limit)||(carry && dest[i] == x[i]); + } + } else if (ylen> xlen) { + const uint64_t xext = ysigned && int64_t(x[xlen-1])<0 ? -1 : 0; + for (i=xlen; i< ylen && i < destlen; i++) { + uint64_t limit = AESL_std::min(xext, y[i]); + dest[i] = xext + y[i] + carry; + carry = (dest[i] < limit)||(carry && dest[i] == y[i]); + } + } + return carry; +} +#endif + +#if 0 +/// @returns returns the borrow out. +/// @brief Generalized subtraction of 64-bit integer arrays. +static bool sub(uint64_t *dest, const uint64_t *x, const uint64_t *y, + uint32_t destlen, uint32_t xlen, uint32_t ylen, bool xsigned, bool ysigned) { + bool borrow = false; + uint32_t i; + uint32_t len = AESL_std::min(xlen, ylen); + for (i = 0; i < len && i < destlen; ++i) { + uint64_t x_tmp = borrow ? x[i] - 1 : x[i]; + borrow = y[i] > x_tmp || (borrow && x[i] == 0); + dest[i] = x_tmp - y[i]; + } + if (xlen > ylen) { + const uint64_t yext = ysigned && int64_t(y[ylen-1])<0 ? -1 : 0; + for (i=ylen; i< xlen && i < destlen; i++) { + uint64_t x_tmp = borrow ? x[i] - 1 : x[i]; + borrow = yext > x_tmp || (borrow && x[i] == 0); + dest[i] = x_tmp - yext; + } + } else if (ylen> xlen) { + const uint64_t xext = xsigned && int64_t(x[xlen-1])<0 ? -1 : 0; + for (i=xlen; i< ylen && i < destlen; i++) { + uint64_t x_tmp = borrow ? xext - 1 : xext; + borrow = y[i] > x_tmp || (borrow && xext==0); + dest[i] = x_tmp - y[i]; + } + } + return borrow; +} +#endif + +/// Subtracts the RHS ap_private from this ap_private +/// @returns this, after subtraction +/// @brief Subtraction assignment operator. + +#if 0 +/// Multiplies an integer array, x by a a uint64_t integer and places the result +/// into dest. +/// @returns the carry out of the multiplication. +/// @brief Multiply a multi-digit ap_private by a single digit (64-bit) integer. +static uint64_t mul_1(uint64_t dest[], const uint64_t x[], uint32_t len, uint64_t y) { + // Split y into high 32-bit part (hy) and low 32-bit part (ly) + uint64_t ly = y & 0xffffffffULL, hy = (y) >> 32; + uint64_t carry = 0; + static const uint64_t two_power_32 = 1ULL << 32; + // For each digit of x. + for (uint32_t i = 0; i < len; ++i) { + // Split x into high and low words + uint64_t lx = x[i] & 0xffffffffULL; + uint64_t hx = (x[i]) >> 32; + // hasCarry - A flag to indicate if there is a carry to the next digit. + // hasCarry == 0, no carry + // hasCarry == 1, has carry + // hasCarry == 2, no carry and the calculation result == 0. + uint8_t hasCarry = 0; + dest[i] = carry + lx * ly; + // Determine if the add above introduces carry. + hasCarry = (dest[i] < carry) ? 1 : 0; + carry = hx * ly + ((dest[i]) >> 32) + (hasCarry ? two_power_32 : 0); + // The upper limit of carry can be (2^32 - 1)(2^32 - 1) + + // (2^32 - 1) + 2^32 = 2^64. + hasCarry = (!carry && hasCarry) ? 1 : (!carry ? 2 : 0); + + carry += (lx * hy) & 0xffffffffULL; + dest[i] = ((carry) << 32) | (dest[i] & 0xffffffffULL); + carry = (((!carry && hasCarry != 2) || hasCarry == 1) ? two_power_32 : 0) + + ((carry) >> 32) + ((lx * hy) >> 32) + hx * hy; + } + return carry; +} +#endif + +#if 0 +/// Multiplies integer array x by integer array y and stores the result into +/// the integer array dest. Note that dest's size must be >= xlen + ylen. +/// @brief Generalized multiplicate of integer arrays. +static void mul(uint64_t dest[], const uint64_t x[], uint32_t xlen, const uint64_t y[], + uint32_t ylen, uint32_t destlen) { + dest[xlen] = mul_1(dest, x, xlen, y[0]); + for (uint32_t i = 1; i < ylen; ++i) { + uint64_t ly = y[i] & 0xffffffffULL, hy = (y[i]) >> 32; + uint64_t carry = 0, lx = 0, hx = 0; + for (uint32_t j = 0; j < xlen; ++j) { + lx = x[j] & 0xffffffffULL; + hx = (x[j]) >> 32; + // hasCarry - A flag to indicate if has carry. + // hasCarry == 0, no carry + // hasCarry == 1, has carry + // hasCarry == 2, no carry and the calculation result == 0. + uint8_t hasCarry = 0; + uint64_t resul = carry + lx * ly; + hasCarry = (resul < carry) ? 1 : 0; + carry = (hasCarry ? (1ULL << 32) : 0) + hx * ly + ((resul) >> 32); + hasCarry = (!carry && hasCarry) ? 1 : (!carry ? 2 : 0); + carry += (lx * hy) & 0xffffffffULL; + resul = ((carry) << 32) | (resul & 0xffffffffULL); + dest[i+j] += resul; + carry = (((!carry && hasCarry != 2) || hasCarry == 1) ? (1ULL << 32) : 0)+ + ((carry) >> 32) + (dest[i+j] < resul ? 1 : 0) + + ((lx * hy) >> 32) + hx * hy; + } + dest[i+xlen] = carry; + } +} +#endif + + + +template +uint32_t ap_private<_AP_W, _AP_S, _AP_N>::getBitsNeeded(const char* str, uint32_t slen, uint8_t radix) { + assert(str != 0 && "Invalid value string"); + assert(slen > 0 && "Invalid string length"); + + // Each computation below needs to know if its negative + uint32_t isNegative = str[0] == '-'; + if (isNegative) { + slen--; + str++; + } + // For radixes of power-of-two values, the bits required is accurately and + // easily computed + if (radix == 2) + return slen + isNegative; + if (radix == 8) + return slen * 3 + isNegative; + if (radix == 16) + return slen * 4 + isNegative; + + // Otherwise it must be radix == 10, the hard case + assert(radix == 10 && "Invalid radix"); + + // Convert to the actual binary value. + //ap_private<_AP_W, _AP_S, _AP_N> tmp(sufficient, str, slen, radix); + + // Compute how many bits are required. + //return isNegative + tmp.logBase2() + 1; + return isNegative + slen * 4; +} + +template +uint32_t ap_private<_AP_W, _AP_S, _AP_N>::countLeadingZeros() const { + enum { msw_bits = (BitWidth % APINT_BITS_PER_WORD)?(BitWidth % APINT_BITS_PER_WORD):APINT_BITS_PER_WORD, + excessBits = APINT_BITS_PER_WORD - msw_bits }; + uint32_t Count = CountLeadingZeros_64(pVal[_AP_N-1]); + if (Count>=excessBits) + Count -= excessBits; + if (!pVal[_AP_N-1]) { + for (uint32_t i = _AP_N-1 ; i ; --i) { + if (!pVal[i-1]) + Count += APINT_BITS_PER_WORD; + else { + Count += CountLeadingZeros_64(pVal[i-1]); + break; + } + } + } + return Count; +} + +static uint32_t countLeadingOnes_64(uint64_t __V, uint32_t skip) { + uint32_t Count = 0; + if (skip) + (__V) <<= (skip); + while (__V && (__V & (1ULL << 63))) { + Count++; + (__V) <<= 1; + } + return Count; +} + +template +uint32_t ap_private<_AP_W, _AP_S, _AP_N>::countLeadingOnes() const { + if (isSingleWord()) + return countLeadingOnes_64(VAL, APINT_BITS_PER_WORD - BitWidth); + + uint32_t highWordBits = BitWidth % APINT_BITS_PER_WORD; + uint32_t shift = (highWordBits == 0 ? 0 : APINT_BITS_PER_WORD - highWordBits); + int i = _AP_N - 1; + uint32_t Count = countLeadingOnes_64(pVal[i], shift); + if (Count == highWordBits) { + for (i--; i >= 0; --i) { + if (pVal[i] == ~0ULL) + Count += APINT_BITS_PER_WORD; + else { + Count += countLeadingOnes_64(pVal[i], 0); + break; + } + } + } + return Count; +} + +template +INLINE uint32_t ap_private<_AP_W, _AP_S, _AP_N>::countTrailingZeros() const { + if (isSingleWord()) + return AESL_std::min(uint32_t(CountTrailingZeros_64(VAL)), BitWidth); + uint32_t Count = 0; + uint32_t i = 0; + for (; i < _AP_N && pVal[i] == 0; ++i) + Count += APINT_BITS_PER_WORD; + if (i < _AP_N) + Count += CountTrailingZeros_64(pVal[i]); + return AESL_std::min(Count, BitWidth); +} + +template +ap_private<_AP_W, _AP_S, _AP_N> ap_private<_AP_W, _AP_S, _AP_N>::byteSwap() const { + assert(BitWidth >= 16 && BitWidth % 16 == 0 && "Cannot byteswap!"); + if (BitWidth == 16) + return ap_private<_AP_W, _AP_S, _AP_N>(/*BitWidth,*/ ByteSwap_16(uint16_t(VAL))); + else if (BitWidth == 32) + return ap_private<_AP_W, _AP_S, _AP_N>(/*BitWidth,*/ ByteSwap_32(uint32_t(VAL))); + else if (BitWidth == 48) { + uint32_t Tmp1 = uint32_t((VAL) >> 16); + Tmp1 = ByteSwap_32(Tmp1); + uint16_t Tmp2 = uint16_t(VAL); + Tmp2 = ByteSwap_16(Tmp2); + return ap_private<_AP_W, _AP_S, _AP_N>(/*BitWidth,*/ ((uint64_t(Tmp2)) << 32) | Tmp1); + } else if (BitWidth == 64) + return ap_private<_AP_W, _AP_S, _AP_N>(/*BitWidth,*/ ByteSwap_64(VAL)); + else { + ap_private<_AP_W, _AP_S, _AP_N> Result(0); + char *pByte = (char*)Result.pVal; + for (uint32_t i = 0; i < BitWidth / APINT_WORD_SIZE / 2; ++i) { + char Tmp = pByte[i]; + pByte[i] = pByte[BitWidth / APINT_WORD_SIZE - 1 - i]; + pByte[BitWidth / APINT_WORD_SIZE - i - 1] = Tmp; + } + return Result; + } +} + +template +ap_private<_AP_W, _AP_S, _AP_N> ap_private_ops::GreatestCommonDivisor(const ap_private<_AP_W, _AP_S, _AP_N>& API1, const ap_private<_AP_W, _AP_S, _AP_N>& API2) { + ap_private<_AP_W, _AP_S, _AP_N> __A = API1, __B = API2; + while (!!__B) { + ap_private<_AP_W, _AP_S, _AP_N> __T = __B; + __B = ap_private_ops::urem(__A, __B); + __A = __T; + } + return __A; +} + +template +ap_private<_AP_W, _AP_S, _AP_N> ap_private_ops::RoundDoubleToap_private(double Double, uint32_t width) { + union { + double __D; + uint64_t __I; + } __T; + __T.__D = Double; + + // Get the sign bit from the highest order bit + bool isNeg = (__T.__I) >> 63; + + // Get the 11-bit exponent and adjust for the 1023 bit bias + int64_t exp = (((__T.__I) >> 52) & 0x7ffULL) - 1023; + + // If the exponent is negative, the value is < 0 so just return 0. + if (exp < 0) + return ap_private<_AP_W, _AP_S, _AP_N>(width, 0u); + + // Extract the mantissa by clearing the top 12 bits (sign + exponent). + uint64_t mantissa = (__T.__I & (~0ULL >> 12)) | 1ULL << 52; + + // If the exponent doesn't shift all bits out of the mantissa + if (exp < 52) + return isNeg ? -ap_private<_AP_W, _AP_S, _AP_N>(width, (mantissa) >> (52 - exp)) : + ap_private<_AP_W, _AP_S, _AP_N>((mantissa) >> (52 - exp)); + + // If the client didn't provide enough bits for us to shift the mantissa into + // then the result is undefined, just return 0 + if (width <= exp - 52) + return ap_private<_AP_W, _AP_S, _AP_N>(width, 0); + + // Otherwise, we have to shift the mantissa bits up to the right location + ap_private<_AP_W, _AP_S, _AP_N> Tmp(width, mantissa); + Tmp = Tmp.shl(exp - 52); + return isNeg ? -Tmp : Tmp; +} + +/// RoundToDouble - This function convert this ap_private to a double. +/// The layout for double is as following (IEEE Standard 754): +/// -------------------------------------- +/// | Sign Exponent Fraction Bias | +/// |-------------------------------------- | +/// | 1[63] 11[62-52] 52[51-00] 1023 | +/// -------------------------------------- +template +double ap_private<_AP_W, _AP_S, _AP_N>::roundToDouble(bool isSigned) const { + + // Handle the simple case where the value is contained in one uint64_t. + if (isSingleWord() || getActiveBits() <= APINT_BITS_PER_WORD) { + uint64_t val; + if (isSingleWord()) val = VAL; + else val = pVal[0]; + if (isSigned) { + int64_t sext = ((int64_t(val)) << (64-BitWidth)) >> (64-BitWidth); + return double(sext); + } else + return double(val); + } + + // Determine if the value is negative. + bool isNeg = isSigned ? (*this)[BitWidth-1] : false; + + // Construct the absolute value if we're negative. + ap_private<_AP_W, _AP_S, _AP_N> Tmp(isNeg ? -(*this) : (*this)); + + // Figure out how many bits we're using. + uint32_t n = Tmp.getActiveBits(); + + // The exponent (without bias normalization) is just the number of bits + // we are using. Note that the sign bit is gone since we constructed the + // absolute value. + uint64_t exp = n; + + // Return infinity for exponent overflow + if (exp > 1023) { + if (!isSigned || !isNeg) + return std::numeric_limits::infinity(); + else + return -std::numeric_limits::infinity(); + } + exp += 1023; // Increment for 1023 bias + + // Number of bits in mantissa is 52. To obtain the mantissa value, we must + // extract the high 52 bits from the correct words in pVal. + uint64_t mantissa; + unsigned hiWord = whichWord(n-1); + if (hiWord == 0) { + mantissa = Tmp.pVal[0]; + if (n > 52) + (mantissa) >>= (n - 52); // shift down, we want the top 52 bits. + } else { + assert(hiWord > 0 && "High word is negative?"); + uint64_t hibits = (Tmp.pVal[hiWord]) << (52 - n % APINT_BITS_PER_WORD); + uint64_t lobits = (Tmp.pVal[hiWord-1]) >> (11 + n % APINT_BITS_PER_WORD); + mantissa = hibits | lobits; + } + + // The leading bit of mantissa is implicit, so get rid of it. + uint64_t sign = isNeg ? (1ULL << (APINT_BITS_PER_WORD - 1)) : 0; + union { + double __D; + uint64_t __I; + } __T; + __T.__I = sign | ((exp) << 52) | mantissa; + return __T.__D; +} + +// Square Root - this method computes and returns the square root of "this". +// Three mechanisms are used for computation. For small values (<= 5 bits), +// a table lookup is done. This gets some performance for common cases. For +// values using less than 52 bits, the value is converted to double and then +// the libc sqrt function is called. The result is rounded and then converted +// back to a uint64_t which is then used to construct the result. Finally, +// the Babylonian method for computing square roots is used. +template +ap_private<_AP_W, _AP_S, _AP_N> ap_private<_AP_W, _AP_S, _AP_N>::sqrt() const { + + // Determine the magnitude of the value. + uint32_t magnitude = getActiveBits(); + + // Use a fast table for some small values. This also gets rid of some + // rounding errors in libc sqrt for small values. + if (magnitude <= 5) { + static const uint8_t results[32] = { + /* 0 */ 0, + /* 1- 2 */ 1, 1, + /* 3- 6 */ 2, 2, 2, 2, + /* 7-12 */ 3, 3, 3, 3, 3, 3, + /* 13-20 */ 4, 4, 4, 4, 4, 4, 4, 4, + /* 21-30 */ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + /* 31 */ 6 + }; + return ap_private<_AP_W, _AP_S, _AP_N>(/*BitWidth,*/ results[ (isSingleWord() ? VAL : pVal[0]) ]); + } + + // If the magnitude of the value fits in less than 52 bits (the precision of + // an IEEE double precision floating point value), then we can use the + // libc sqrt function which will probably use a hardware sqrt computation. + // This should be faster than the algorithm below. + if (magnitude < 52) { +#ifdef _MSC_VER + // Amazingly, VC++ doesn't have round(). + return ap_private<_AP_W, _AP_S, _AP_N>(/*BitWidth,*/ + uint64_t(::sqrt(double(isSingleWord()?VAL:pVal[0]))) + 0.5); +#else + return ap_private<_AP_W, _AP_S, _AP_N>(/*BitWidth,*/ + uint64_t(::round(::sqrt(double(isSingleWord()?VAL:pVal[0]))))); +#endif + } + + // Okay, all the short cuts are exhausted. We must compute it. The following + // is a classical Babylonian method for computing the square root. This code + // was adapted to APINt from a wikipedia article on such computations. + // See http://www.wikipedia.org/ and go to the page named + // Calculate_an_integer_square_root. + uint32_t nbits = BitWidth, i = 4; + ap_private<_AP_W, _AP_S, _AP_N> testy(16); + ap_private<_AP_W, _AP_S, _AP_N> x_old(/*BitWidth,*/ 1); + ap_private<_AP_W, _AP_S, _AP_N> x_new(0); + ap_private<_AP_W, _AP_S, _AP_N> two(/*BitWidth,*/ 2); + + // Select a good starting value using binary logarithms. + for (;; i += 2, testy = testy.shl(2)) + if (i >= nbits || this->ule(testy)) { + x_old = x_old.shl(i / 2); + break; + } + + // Use the Babylonian method to arrive at the integer square root: + for (;;) { + x_new = (this->udiv(x_old) + x_old).udiv(two); + if (x_old.ule(x_new)) + break; + x_old = x_new; + } + + // Make sure we return the closest approximation + // NOTE: The rounding calculation below is correct. It will produce an + // off-by-one discrepancy with results from pari/gp. That discrepancy has been + // determined to be a rounding issue with pari/gp as it begins to use a + // floating point representation after 192 bits. There are no discrepancies + // between this algorithm and pari/gp for bit widths < 192 bits. + ap_private<_AP_W, _AP_S, _AP_N> square(x_old * x_old); + ap_private<_AP_W, _AP_S, _AP_N> nextSquare((x_old + 1) * (x_old +1)); + if (this->ult(square)) + return x_old; + else if (this->ule(nextSquare)) { + ap_private<_AP_W, _AP_S, _AP_N> midpoint((nextSquare - square).udiv(two)); + ap_private<_AP_W, _AP_S, _AP_N> offset(*this - square); + if (offset.ult(midpoint)) + return x_old; + else + return x_old + 1; + } else + assert(0 && "Error in ap_private<_AP_W, _AP_S, _AP_N>::sqrt computation"); + return x_old + 1; +} + +/// Implementation of Knuth's Algorithm D (Division of nonnegative integers) +/// from "Art of Computer Programming, Volume 2", section 4.3.1, p. 272. The +/// variables here have the same names as in the algorithm. Comments explain +/// the algorithm and any deviation from it. +static void KnuthDiv(uint32_t *u, uint32_t *v, uint32_t *q, uint32_t* r, + uint32_t m, uint32_t n) { + assert(u && "Must provide dividend"); + assert(v && "Must provide divisor"); + assert(q && "Must provide quotient"); + assert(u != v && u != q && v != q && "Must us different memory"); + assert(n>1 && "n must be > 1"); + + // Knuth uses the value b as the base of the number system. In our case b + // is 2^31 so we just set it to -1u. + uint64_t b = uint64_t(1) << 32; + + //DEBUG(cerr << "KnuthDiv: m=" << m << " n=" << n << '\n'); + //DEBUG(cerr << "KnuthDiv: original:"); + //DEBUG(for (int i = m+n; i >=0; i--) cerr << " " << std::setbase(16) << u[i]); + //DEBUG(cerr << " by"); + //DEBUG(for (int i = n; i >0; i--) cerr << " " << std::setbase(16) << v[i-1]); + //DEBUG(cerr << '\n'); + // D1. [Normalize.] Set d = b / (v[n-1] + 1) and multiply all the digits of + // u and v by d. Note that we have taken Knuth's advice here to use a power + // of 2 value for d such that d * v[n-1] >= b/2 (b is the base). A power of + // 2 allows us to shift instead of multiply and it is easy to determine the + // shift amount from the leading zeros. We are basically normalizing the u + // and v so that its high bits are shifted to the top of v's range without + // overflow. Note that this can require an extra word in u so that u must + // be of length m+n+1. + uint32_t shift = CountLeadingZeros_32(v[n-1]); + uint32_t v_carry = 0; + uint32_t u_carry = 0; + if (shift) { + for (uint32_t i = 0; i < m+n; ++i) { + uint32_t u_tmp = (u[i]) >> (32 - shift); + u[i] = ((u[i]) << (shift)) | u_carry; + u_carry = u_tmp; + } + for (uint32_t i = 0; i < n; ++i) { + uint32_t v_tmp = (v[i]) >> (32 - shift); + v[i] = ((v[i]) << (shift)) | v_carry; + v_carry = v_tmp; + } + } + u[m+n] = u_carry; + //DEBUG(cerr << "KnuthDiv: normal:"); + //DEBUG(for (int i = m+n; i >=0; i--) cerr << " " << std::setbase(16) << u[i]); + //DEBUG(cerr << " by"); + //DEBUG(for (int i = n; i >0; i--) cerr << " " << std::setbase(16) << v[i-1]); + //DEBUG(cerr << '\n'); + + // D2. [Initialize j.] Set j to m. This is the loop counter over the places. + int j = m; + do { + //DEBUG(cerr << "KnuthDiv: quotient digit #" << j << '\n'); + // D3. [Calculate q'.]. + // Set qp = (u[j+n]*b + u[j+n-1]) / v[n-1]. (qp=qprime=q') + // Set rp = (u[j+n]*b + u[j+n-1]) % v[n-1]. (rp=rprime=r') + // Now test if qp == b or qp*v[n-2] > b*rp + u[j+n-2]; if so, decrease + // qp by 1, inrease rp by v[n-1], and repeat this test if rp < b. The test + // on v[n-2] determines at high speed most of the cases in which the trial + // value qp is one too large, and it eliminates all cases where qp is two + // too large. + uint64_t dividend = ((uint64_t(u[j+n]) << 32) + u[j+n-1]); + //DEBUG(cerr << "KnuthDiv: dividend == " << dividend << '\n'); + uint64_t qp = dividend / v[n-1]; + uint64_t rp = dividend % v[n-1]; + if (qp == b || qp*v[n-2] > b*rp + u[j+n-2]) { + qp--; + rp += v[n-1]; + if (rp < b && (qp == b || qp*v[n-2] > b*rp + u[j+n-2])) + qp--; + } + //DEBUG(cerr << "KnuthDiv: qp == " << qp << ", rp == " << rp << '\n'); + + // D4. [Multiply and subtract.] Replace (u[j+n]u[j+n-1]...u[j]) with + // (u[j+n]u[j+n-1]..u[j]) - qp * (v[n-1]...v[1]v[0]). This computation + // consists of a simple multiplication by a one-place number, combined with + // a subtraction. + bool isNeg = false; + for (uint32_t i = 0; i < n; ++i) { + uint64_t u_tmp = uint64_t(u[j+i]) | ((uint64_t(u[j+i+1])) << 32); + uint64_t subtrahend = uint64_t(qp) * uint64_t(v[i]); + bool borrow = subtrahend > u_tmp; + /*DEBUG(cerr << "KnuthDiv: u_tmp == " << u_tmp + << ", subtrahend == " << subtrahend + << ", borrow = " << borrow << '\n');*/ + + uint64_t result = u_tmp - subtrahend; + uint32_t k = j + i; + u[k++] = (uint32_t)(result & (b-1)); // subtract low word + u[k++] = (uint32_t)((result) >> 32); // subtract high word + while (borrow && k <= m+n) { // deal with borrow to the left + borrow = u[k] == 0; + u[k]--; + k++; + } + isNeg |= borrow; + /*DEBUG(cerr << "KnuthDiv: u[j+i] == " << u[j+i] << ", u[j+i+1] == " << + u[j+i+1] << '\n');*/ + } + /*DEBUG(cerr << "KnuthDiv: after subtraction:"); + DEBUG(for (int i = m+n; i >=0; i--) cerr << " " << u[i]); + DEBUG(cerr << '\n');*/ + // The digits (u[j+n]...u[j]) should be kept positive; if the result of + // this step is actually negative, (u[j+n]...u[j]) should be left as the + // true value plus b**(n+1), namely as the b's complement of + // the true value, and a "borrow" to the left should be remembered. + // + if (isNeg) { + bool carry = true; // true because b's complement is "complement + 1" + for (uint32_t i = 0; i <= m+n; ++i) { + u[i] = ~u[i] + carry; // b's complement + carry = carry && u[i] == 0; + } + } + /*DEBUG(cerr << "KnuthDiv: after complement:"); + DEBUG(for (int i = m+n; i >=0; i--) cerr << " " << u[i]); + DEBUG(cerr << '\n');*/ + + // D5. [Test remainder.] Set q[j] = qp. If the result of step D4 was + // negative, go to step D6; otherwise go on to step D7. + q[j] = (uint32_t)qp; + if (isNeg) { + // D6. [Add back]. The probability that this step is necessary is very + // small, on the order of only 2/b. Make sure that test data accounts for + // this possibility. Decrease q[j] by 1 + q[j]--; + // and add (0v[n-1]...v[1]v[0]) to (u[j+n]u[j+n-1]...u[j+1]u[j]). + // A carry will occur to the left of u[j+n], and it should be ignored + // since it cancels with the borrow that occurred in D4. + bool carry = false; + for (uint32_t i = 0; i < n; i++) { + uint32_t limit = AESL_std::min(u[j+i],v[i]); + u[j+i] += v[i] + carry; + carry = u[j+i] < limit || (carry && u[j+i] == limit); + } + u[j+n] += carry; + } + /*DEBUG(cerr << "KnuthDiv: after correction:"); + DEBUG(for (int i = m+n; i >=0; i--) cerr <<" " << u[i]); + DEBUG(cerr << "\nKnuthDiv: digit result = " << q[j] << '\n');*/ + + // D7. [Loop on j.] Decrease j by one. Now if j >= 0, go back to D3. + } while (--j >= 0); + + /*DEBUG(cerr << "KnuthDiv: quotient:"); + DEBUG(for (int i = m; i >=0; i--) cerr <<" " << q[i]); + DEBUG(cerr << '\n');*/ + + // D8. [Unnormalize]. Now q[...] is the desired quotient, and the desired + // remainder may be obtained by dividing u[...] by d. If r is non-null we + // compute the remainder (urem uses this). + if (r) { + // The value d is expressed by the "shift" value above since we avoided + // multiplication by d by using a shift left. So, all we have to do is + // shift right here. In order to mak + if (shift) { + uint32_t carry = 0; + //DEBUG(cerr << "KnuthDiv: remainder:"); + for (int i = n-1; i >= 0; i--) { + r[i] = ((u[i]) >> (shift)) | carry; + carry = (u[i]) << (32 - shift); + //DEBUG(cerr << " " << r[i]); + } + } else { + for (int i = n-1; i >= 0; i--) { + r[i] = u[i]; + //DEBUG(cerr << " " << r[i]); + } + } + //DEBUG(cerr << '\n'); + } + //DEBUG(cerr << std::setbase(10) << '\n'); +} + +template +void divide(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, uint32_t lhsWords, + const ap_private<_AP_W, _AP_S, _AP_N>& RHS, uint32_t rhsWords, + ap_private<_AP_W, _AP_S, _AP_N> *Quotient, ap_private<_AP_W, _AP_S, _AP_N> *Remainder) { + assert(lhsWords >= rhsWords && "Fractional result"); + enum {APINT_BITS_PER_WORD=64}; + // First, compose the values into an array of 32-bit words instead of + // 64-bit words. This is a necessity of both the "short division" algorithm + // and the the Knuth "classical algorithm" which requires there to be native + // operations for +, -, and * on an m bit value with an m*2 bit result. We + // can't use 64-bit operands here because we don't have native results of + // 128-bits. Furthremore, casting the 64-bit values to 32-bit values won't + // work on large-endian machines. + uint64_t mask = ~0ull >> (sizeof(uint32_t)*8); + uint32_t n = rhsWords * 2; + uint32_t m = (lhsWords * 2) - n; + + // Allocate space for the temporary values we need either on the stack, if + // it will fit, or on the heap if it won't. + uint32_t SPACE[128]; + uint32_t *__U = 0; + uint32_t *__V = 0; + uint32_t *__Q = 0; + uint32_t *__R = 0; + if ((Remainder?4:3)*n+2*m+1 <= 128) { + __U = &SPACE[0]; + __V = &SPACE[m+n+1]; + __Q = &SPACE[(m+n+1) + n]; + if (Remainder) + __R = &SPACE[(m+n+1) + n + (m+n)]; + } else { + __U = new uint32_t[m + n + 1]; + __V = new uint32_t[n]; + __Q = new uint32_t[m+n]; + if (Remainder) + __R = new uint32_t[n]; + } + + // Initialize the dividend + memset(__U, 0, (m+n+1)*sizeof(uint32_t)); + for (unsigned i = 0; i < lhsWords; ++i) { + uint64_t tmp = (LHS.getNumWords() == 1 ? LHS.VAL : LHS.pVal[i]); + __U[i * 2] = (uint32_t)(tmp & mask); + __U[i * 2 + 1] = (tmp) >> (sizeof(uint32_t)*8); + } + __U[m+n] = 0; // this extra word is for "spill" in the Knuth algorithm. + + // Initialize the divisor + memset(__V, 0, (n)*sizeof(uint32_t)); + for (unsigned i = 0; i < rhsWords; ++i) { + uint64_t tmp = (RHS.getNumWords() == 1 ? RHS.VAL : RHS.pVal[i]); + __V[i * 2] = (uint32_t)(tmp & mask); + __V[i * 2 + 1] = (tmp) >> (sizeof(uint32_t)*8); + } + + // initialize the quotient and remainder + memset(__Q, 0, (m+n) * sizeof(uint32_t)); + if (Remainder) + memset(__R, 0, n * sizeof(uint32_t)); + + // Now, adjust m and n for the Knuth division. n is the number of words in + // the divisor. m is the number of words by which the dividend exceeds the + // divisor (i.e. m+n is the length of the dividend). These sizes must not + // contain any zero words or the Knuth algorithm fails. + for (unsigned i = n; i > 0 && __V[i-1] == 0; i--) { + n--; + m++; + } + for (unsigned i = m+n; i > 0 && __U[i-1] == 0; i--) + m--; + + // If we're left with only a single word for the divisor, Knuth doesn't work + // so we implement the short division algorithm here. This is much simpler + // and faster because we are certain that we can divide a 64-bit quantity + // by a 32-bit quantity at hardware speed and short division is simply a + // series of such operations. This is just like doing short division but we + // are using base 2^32 instead of base 10. + assert(n != 0 && "Divide by zero?"); + if (n == 1) { + uint32_t divisor = __V[0]; + uint32_t remainder = 0; + for (int i = m+n-1; i >= 0; i--) { + uint64_t partial_dividend = (uint64_t(remainder)) << 32 | __U[i]; + if (partial_dividend == 0) { + __Q[i] = 0; + remainder = 0; + } else if (partial_dividend < divisor) { + __Q[i] = 0; + remainder = (uint32_t)partial_dividend; + } else if (partial_dividend == divisor) { + __Q[i] = 1; + remainder = 0; + } else { + __Q[i] = (uint32_t)(partial_dividend / divisor); + remainder = (uint32_t)(partial_dividend - (__Q[i] * divisor)); + } + } + if (__R) + __R[0] = remainder; + } else { + // Now we're ready to invoke the Knuth classical divide algorithm. In this + // case n > 1. + KnuthDiv(__U, __V, __Q, __R, m, n); + } + + // If the caller wants the quotient + if (Quotient) { + // Set up the Quotient value's memory. + if (Quotient->BitWidth != LHS.BitWidth) { + if (Quotient->isSingleWord()) + Quotient->VAL = 0; + } else + Quotient->clear(); + + // The quotient is in Q. Reconstitute the quotient into Quotient's low + // order words. + if (lhsWords == 1) { + uint64_t tmp = + uint64_t(__Q[0]) | ((uint64_t(__Q[1])) << (APINT_BITS_PER_WORD / 2)); + if (Quotient->isSingleWord()) + Quotient->VAL = tmp; + else + Quotient->pVal[0] = tmp; + } else { + assert(!Quotient->isSingleWord() && "Quotient ap_private not large enough"); + for (unsigned i = 0; i < lhsWords; ++i) + Quotient->pVal[i] = + uint64_t(__Q[i*2]) | ((uint64_t(__Q[i*2+1])) << (APINT_BITS_PER_WORD / 2)); + } + Quotient->clearUnusedBits(); + } + + // If the caller wants the remainder + if (Remainder) { + // Set up the Remainder value's memory. + if (Remainder->BitWidth != RHS.BitWidth) { + if (Remainder->isSingleWord()) + Remainder->VAL = 0; + } else + Remainder->clear(); + + // The remainder is in R. Reconstitute the remainder into Remainder's low + // order words. + if (rhsWords == 1) { + uint64_t tmp = + uint64_t(__R[0]) | ((uint64_t(__R[1])) << (APINT_BITS_PER_WORD / 2)); + if (Remainder->isSingleWord()) + Remainder->VAL = tmp; + else + Remainder->pVal[0] = tmp; + } else { + assert(!Remainder->isSingleWord() && "Remainder ap_private not large enough"); + for (unsigned i = 0; i < rhsWords; ++i) + Remainder->pVal[i] = + uint64_t(__R[i*2]) | ((uint64_t(__R[i*2+1])) << (APINT_BITS_PER_WORD / 2)); + } + Remainder->clearUnusedBits(); + } + + // Clean up the memory we allocated. + if (__U != &SPACE[0]) { + delete [] __U; + delete [] __V; + delete [] __Q; + delete [] __R; + } +} + + +template +void ap_private<_AP_W, _AP_S, _AP_N>::fromString(const char *str, uint32_t slen, uint8_t radix) { + enum { numbits=_AP_W}; + // Check our assumptions here + assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) && + "Radix should be 2, 8, 10, or 16!"); + assert(str && "String is null?"); + bool isNeg = str[0] == '-'; + if (isNeg) + str++, slen--; + + //skip any leading zero + while(*str == '0' && *(str+1) != '\0') {str++; slen--;} + assert((slen <= numbits || radix != 2) && "Insufficient bit width"); + assert(((slen - 1)*3 <= numbits || radix != 8) && "Insufficient bit width"); + assert(((slen - 1)*4 <= numbits || radix != 16) && "Insufficient bit width"); + assert((((slen -1)*64)/22 <= numbits || radix != 10) && "Insufficient bit width"); + + memset(pVal, 0, _AP_N * sizeof(uint64_t)); + + // Figure out if we can shift instead of multiply + uint32_t shift = (radix == 16 ? 4 : radix == 8 ? 3 : radix == 2 ? 1 : 0); + + // Set up an ap_private for the digit to add outside the loop so we don't + // constantly construct/destruct it. + uint64_t bigVal[_AP_N]; + memset(bigVal, 0, _AP_N * sizeof(uint64_t)); + ap_private<_AP_W, _AP_S, _AP_N> apdigit(getBitWidth(), bigVal); + ap_private<_AP_W, _AP_S, _AP_N> apradix(radix); + + // Enter digit traversal loop + for (unsigned i = 0; i < slen; i++) { + // Get a digit + uint32_t digit = 0; + char cdigit = str[i]; + if (radix == 16) { +#define isxdigit(c) (((c) >= '0' && (c) <= '9') || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F')) +#define isdigit(c) ((c) >= '0' && (c) <= '9') + if (!isxdigit(cdigit)) + assert(0 && "Invalid hex digit in string"); + if (isdigit(cdigit)) + digit = cdigit - '0'; + else if (cdigit >= 'a') + digit = cdigit - 'a' + 10; + else if (cdigit >= 'A') + digit = cdigit - 'A' + 10; + else + assert(0 && "huh? we shouldn't get here"); + } else if (isdigit(cdigit)) { + digit = cdigit - '0'; + } else { + assert(0 && "Invalid character in digit string"); + } +#undef isxdigit +#undef isdigit + // Shift or multiply the value by the radix + if (shift) + *this <<= shift; + else + *this *= apradix; + + // Add in the digit we just interpreted + if (apdigit.isSingleWord()) + apdigit.VAL = digit; + else + apdigit.pVal[0] = digit; + *this += apdigit; + } + // If its negative, put it in two's complement form + if (isNeg) { + (*this)--; + this->flip(); + } + clearUnusedBits(); +} + +template +std::string ap_private<_AP_W, _AP_S, _AP_N>::toString(uint8_t radix, bool wantSigned) const { + assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) && + "Radix should be 2, 8, 10, or 16!"); + static const char *digits[] = { + "0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F" + }; + std::string result; + uint32_t bits_used = getActiveBits(); + + if (radix != 10) { + // For the 2, 8 and 16 bit cases, we can just shift instead of divide + // because the number of bits per digit (1,3 and 4 respectively) divides + // equaly. We just shift until there value is zero. + + // First, check for a zero value and just short circuit the logic below. + if (*this == (uint64_t)(0)) + result = "0"; + else { + ap_private<_AP_W, false, _AP_N> tmp(*this); + size_t insert_at = 0; + if (wantSigned && isNegative()) { + // They want to print the signed version and it is a negative value + // Flip the bits and add one to turn it into the equivalent positive + // value and put a '-' in the result. + tmp.flip(); + tmp++; + tmp.clearUnusedBitsToZero(); + result = "-"; + insert_at = 1; + } + // Just shift tmp right for each digit width until it becomes zero + uint32_t shift = (radix == 16 ? 4 : (radix == 8 ? 3 : 1)); + uint64_t mask = radix - 1; + ap_private<_AP_W, false, _AP_N> zero(0); + while (tmp.ne(zero)) { + unsigned digit = (tmp.isSingleWord() ? tmp.VAL : tmp.pVal[0]) & mask; + result.insert(insert_at, digits[digit]); + tmp = tmp.lshr(shift); + } + } + return result; + } + + ap_private<_AP_W, false, _AP_N> tmp(*this); + ap_private<_AP_W, false, _AP_N> divisor(radix); + ap_private<_AP_W, false, _AP_N> zero(0); + size_t insert_at = 0; + if (wantSigned && isNegative()) { + // They want to print the signed version and it is a negative value + // Flip the bits and add one to turn it into the equivalent positive + // value and put a '-' in the result. + tmp.flip(); + tmp++; + tmp.clearUnusedBitsToZero(); + result = "-"; + insert_at = 1; + } + if (tmp == ap_private<_AP_W, false, _AP_N>(0)) + result = "0"; + else while (tmp.ne(zero)) { + ap_private<_AP_W, false, _AP_N> APdigit(0); + ap_private<_AP_W, false, _AP_N> tmp2(0); + divide(tmp, tmp.getNumWords(), divisor, divisor.getNumWords(), &tmp2, + &APdigit); + uint32_t digit = APdigit.getZExtValue(); + assert(digit < radix && "divide failed"); + result.insert(insert_at,digits[digit]); + tmp = tmp2; + } + + return result; +} + +// This implements a variety of operations on a representation of +// arbitrary precision, two's-complement, bignum integer values. + +/* Assumed by lowHalf, highHalf, partMSB and partLSB. A fairly safe + and unrestricting assumption. */ + +/* Some handy functions local to this file. */ + +template +void divide(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, uint32_t lhsWords, + uint64_t RHS, + ap_private<_AP_W, _AP_S, _AP_N> *Quotient, ap_private<_AP_W, _AP_S, _AP_N> *Remainder) { + uint32_t rhsWords=1; + assert(lhsWords >= rhsWords && "Fractional result"); + enum {APINT_BITS_PER_WORD=64}; + // First, compose the values into an array of 32-bit words instead of + // 64-bit words. This is a necessity of both the "short division" algorithm + // and the the Knuth "classical algorithm" which requires there to be native + // operations for +, -, and * on an m bit value with an m*2 bit result. We + // can't use 64-bit operands here because we don't have native results of + // 128-bits. Furthremore, casting the 64-bit values to 32-bit values won't + // work on large-endian machines. + uint64_t mask = ~0ull >> (sizeof(uint32_t)*8); + uint32_t n = 2; + uint32_t m = (lhsWords * 2) - n; + + // Allocate space for the temporary values we need either on the stack, if + // it will fit, or on the heap if it won't. + uint32_t SPACE[128]; + uint32_t *__U = 0; + uint32_t *__V = 0; + uint32_t *__Q = 0; + uint32_t *__R = 0; + if ((Remainder?4:3)*n+2*m+1 <= 128) { + __U = &SPACE[0]; + __V = &SPACE[m+n+1]; + __Q = &SPACE[(m+n+1) + n]; + if (Remainder) + __R = &SPACE[(m+n+1) + n + (m+n)]; + } else { + __U = new uint32_t[m + n + 1]; + __V = new uint32_t[n]; + __Q = new uint32_t[m+n]; + if (Remainder) + __R = new uint32_t[n]; + } + + // Initialize the dividend + memset(__U, 0, (m+n+1)*sizeof(uint32_t)); + for (unsigned i = 0; i < lhsWords; ++i) { + uint64_t tmp = (LHS.getNumWords() == 1 ? LHS.VAL : LHS.pVal[i]); + __U[i * 2] = tmp & mask; + __U[i * 2 + 1] = (tmp) >> (sizeof(uint32_t)*8); + } + __U[m+n] = 0; // this extra word is for "spill" in the Knuth algorithm. + + // Initialize the divisor + memset(__V, 0, (n)*sizeof(uint32_t)); + __V[0] = RHS & mask; + __V[1] = (RHS) >> (sizeof(uint32_t)*8); + + // initialize the quotient and remainder + memset(__Q, 0, (m+n) * sizeof(uint32_t)); + if (Remainder) + memset(__R, 0, n * sizeof(uint32_t)); + + // Now, adjust m and n for the Knuth division. n is the number of words in + // the divisor. m is the number of words by which the dividend exceeds the + // divisor (i.e. m+n is the length of the dividend). These sizes must not + // contain any zero words or the Knuth algorithm fails. + for (unsigned i = n; i > 0 && __V[i-1] == 0; i--) { + n--; + m++; + } + for (unsigned i = m+n; i > 0 && __U[i-1] == 0; i--) + m--; + + // If we're left with only a single word for the divisor, Knuth doesn't work + // so we implement the short division algorithm here. This is much simpler + // and faster because we are certain that we can divide a 64-bit quantity + // by a 32-bit quantity at hardware speed and short division is simply a + // series of such operations. This is just like doing short division but we + // are using base 2^32 instead of base 10. + assert(n != 0 && "Divide by zero?"); + if (n == 1) { + uint32_t divisor = __V[0]; + uint32_t remainder = 0; + for (int i = m+n-1; i >= 0; i--) { + uint64_t partial_dividend = (uint64_t(remainder)) << 32 | __U[i]; + if (partial_dividend == 0) { + __Q[i] = 0; + remainder = 0; + } else if (partial_dividend < divisor) { + __Q[i] = 0; + remainder = partial_dividend; + } else if (partial_dividend == divisor) { + __Q[i] = 1; + remainder = 0; + } else { + __Q[i] = partial_dividend / divisor; + remainder = partial_dividend - (__Q[i] * divisor); + } + } + if (__R) + __R[0] = remainder; + } else { + // Now we're ready to invoke the Knuth classical divide algorithm. In this + // case n > 1. + KnuthDiv(__U, __V, __Q, __R, m, n); + } + + // If the caller wants the quotient + if (Quotient) { + // Set up the Quotient value's memory. + if (Quotient->BitWidth != LHS.BitWidth) { + if (Quotient->isSingleWord()) + Quotient->VAL = 0; + else + delete [] Quotient->pVal; + } else + Quotient->clear(); + + // The quotient is in Q. Reconstitute the quotient into Quotient's low + // order words. + if (lhsWords == 1) { + uint64_t tmp = + uint64_t(__Q[0]) | ((uint64_t(__Q[1])) << (APINT_BITS_PER_WORD / 2)); + if (Quotient->isSingleWord()) + Quotient->VAL = tmp; + else + Quotient->pVal[0] = tmp; + } else { + assert(!Quotient->isSingleWord() && "Quotient ap_private not large enough"); + for (unsigned i = 0; i < lhsWords; ++i) + Quotient->pVal[i] = + uint64_t(__Q[i*2]) | ((uint64_t(__Q[i*2+1])) << (APINT_BITS_PER_WORD / 2)); + } + Quotient->clearUnusedBits(); + } + + // If the caller wants the remainder + if (Remainder) { + // Set up the Remainder value's memory. + if (Remainder->BitWidth != 64 /* RHS.BitWidth */) { + if (Remainder->isSingleWord()) + Remainder->VAL = 0; + } else + Remainder->clear(); + + // The remainder is in __R. Reconstitute the remainder into Remainder's low + // order words. + if (rhsWords == 1) { + uint64_t tmp = + uint64_t(__R[0]) | ((uint64_t(__R[1])) << (APINT_BITS_PER_WORD / 2)); + if (Remainder->isSingleWord()) + Remainder->VAL = tmp; + else + Remainder->pVal[0] = tmp; + } else { + assert(!Remainder->isSingleWord() && "Remainder ap_private not large enough"); + for (unsigned i = 0; i < rhsWords; ++i) + Remainder->pVal[i] = + uint64_t(__R[i*2]) | ((uint64_t(__R[i*2+1])) << (APINT_BITS_PER_WORD / 2)); + } + Remainder->clearUnusedBits(); + } + + // Clean up the memory we allocated. + if (__U != &SPACE[0]) { + delete [] __U; + delete [] __V; + delete [] __Q; + delete [] __R; + } +} + +//When bitwidth < 64 +template class ap_private <_AP_W, _AP_S, 1> { +#ifdef _MSC_VER +#pragma warning( disable : 4521 4522 ) +#endif +public: + typedef typename retval<_AP_S>::Type ValType; + template + struct RType { + enum { + _AP_N =1, + mult_w = _AP_W+_AP_W2, + mult_s = _AP_S||_AP_S2, //?? why + plus_w = AP_MAX(_AP_W+(_AP_S2&&!_AP_S),_AP_W2+(_AP_S&&!_AP_S2))+1, //shouldn't it be AP_MAX(_AP_W,_AP_W2)+!(_AP_S^_AP_S2)+1 ???? + plus_s = _AP_S||_AP_S2, + minus_w = AP_MAX(_AP_W+(_AP_S2&&!_AP_S),_AP_W2+(_AP_S&&!_AP_S2))+1, + minus_s = true, + div_w = _AP_W+_AP_S2, + div_s = _AP_S||_AP_S2, + mod_w = AP_MIN(_AP_W,_AP_W2+(!_AP_S2&&_AP_S)), + mod_s = _AP_S, + logic_w = AP_MAX(_AP_W+(_AP_S2&&!_AP_S),_AP_W2+(_AP_S&&!_AP_S2)), + logic_s = _AP_S||_AP_S2 + }; + typedef ap_private mult; + typedef ap_private plus; + typedef ap_private minus; + typedef ap_private logic; + typedef ap_private div; + typedef ap_private mod; + typedef ap_private<_AP_W, _AP_S> arg1; + typedef bool reduce; + }; + enum { APINT_BITS_PER_WORD = 64}; + enum { excess_bits = (_AP_W%APINT_BITS_PER_WORD) ? APINT_BITS_PER_WORD -(_AP_W%APINT_BITS_PER_WORD) : 0}; + static const uint64_t mask = ((uint64_t)~0ULL >> (excess_bits)); + static const uint64_t not_mask = ~mask; + static const uint64_t sign_bit_mask = 1ULL << (APINT_BITS_PER_WORD-1); + template struct sign_ext_mask { static const uint64_t mask=~0ULL<<_AP_W1;}; + + enum { BitWidth=_AP_W}; + uint64_t VAL; ///< Used to store the <= 64 bits integer value. + const uint64_t *const pVal; + + INLINE uint32_t getBitWidth() const { + return BitWidth; + } + + template + ap_private<_AP_W, _AP_S, 1>& operator=(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { + VAL = RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + + template + ap_private<_AP_W, _AP_S, 1>& operator=(const volatile ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { + VAL = RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + + template + ap_private<_AP_W, _AP_S, 1>& operator=(const ap_private<_AP_W1, _AP_S1, 1>& RHS) { + VAL = RHS.VAL; + clearUnusedBits(); + return *this; + } + + template + ap_private<_AP_W, _AP_S, 1>& operator=(const volatile ap_private<_AP_W1, _AP_S1, 1>& RHS) { + VAL = RHS.VAL; + clearUnusedBits(); + return *this; + } + + volatile ap_private& operator=(const ap_private& RHS) volatile { + // Don't do anything for X = X + VAL = RHS.VAL; // No need to check because no harm done by copying. + return *this; + } + ap_private& operator=(const ap_private& RHS) { + // Don't do anything for X = X + VAL = RHS.VAL; // No need to check because no harm done by copying. + return *this; + } + + volatile ap_private& operator=(const volatile ap_private& RHS) volatile { + // Don't do anything for X = X + VAL = RHS.VAL; // No need to check because no harm done by copying. + return *this; + } + ap_private& operator=(const volatile ap_private& RHS) { + // Don't do anything for X = X + VAL = RHS.VAL; // No need to check because no harm done by copying. + return *this; + } + + template + INLINE ap_private& operator = (const ap_range_ref<_AP_W2, _AP_S2>& op2) { + *this = ap_private<_AP_W2, false>(op2); + return *this; + } + + explicit INLINE ap_private(uint64_t* val) : VAL(val[0]), pVal(&VAL){ + clearUnusedBits(); + } + + INLINE bool isSingleWord() const { return true; } + + INLINE void fromString(const char *strStart, uint32_t slen, + uint8_t radix, int offset=0) { + // Check our assumptions here + assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) && + "Radix should be 2, 8, 10, or 16!"); + assert(strStart && "String is null?"); + strStart+=offset; + switch(radix) { + case 2: + // sscanf(strStart,"%b",&VAL); + VAL = *strStart =='1' ? ~0ULL : 0; + for (;*strStart; ++strStart) { + assert((*strStart=='0'|| *strStart=='1')&&("Wrong binary number") ); + VAL <<=1; + VAL |= (*strStart-'0'); + } + break; + case 8: +#if __WIN32__ + sscanf(strStart,"%I64o",&VAL); +#else + +#if defined __x86_64__ + sscanf(strStart,"%lo",&VAL); +#else + sscanf(strStart,"%llo",&VAL); +#endif + +#endif + break; + case 10: +#if __WIN32__ + sscanf(strStart,"%I64u",&VAL); +#else + +#if defined __x86_64__ + sscanf(strStart,"%lu",&VAL); +#else + sscanf(strStart,"%llu",&VAL); +#endif + +#endif + break; + case 16: +#if __WIN32__ + sscanf(strStart,"%I64x",&VAL); +#else + +#if defined __x86_64__ + sscanf(strStart,"%lx",&VAL); +#else + sscanf(strStart,"%llx",&VAL); +#endif + +#endif + break; + default: + assert(true && "Unknown radix"); + // error + } + clearUnusedBits(); + } + + INLINE ap_private() : pVal(&VAL){VAL = 0ULL;} + +#define CTOR(TYPE) \ + INLINE ap_private(TYPE v) : VAL((uint64_t)v), pVal(&VAL) { \ + clearUnusedBits(); \ + } + CTOR(int) + CTOR(bool) + CTOR(signed char) + CTOR(unsigned char) + CTOR(short) + CTOR(unsigned short) + CTOR(unsigned int) + CTOR(long) + CTOR(unsigned long) + CTOR(unsigned long long) + CTOR(long long) + CTOR(float) + CTOR(double) +#undef CTOR + ap_private(uint32_t numWords, const uint64_t bigVal[]): VAL(bigVal[0]), pVal(&VAL) {clearUnusedBits();} + + ap_private(const std::string& val, uint8_t radix=2, int base=0, int offset=0): VAL(0), pVal(&VAL) { + assert(!val.empty() && "String empty?"); + fromString(val.c_str()+base, val.size()-base, radix); + } + + ap_private(const char strStart[], uint32_t slen, uint8_t radix, int base=0, int offset=0) : VAL(0), pVal(&VAL) { + fromString(strStart+base, slen-base, radix, offset); + } + + ap_private(const ap_private& that) : VAL(that.VAL), pVal(&VAL) { + clearUnusedBits(); + } + + template + ap_private(const ap_private<_AP_W1, _AP_S1, 1>& that) : VAL(that.VAL), pVal(&VAL) { + clearUnusedBits(); + } + + template + ap_private(const ap_private<_AP_W1, _AP_S1, _AP_N1>& that) : VAL(that.pVal[0]), pVal(&VAL) { + clearUnusedBits(); + } + + template + ap_private(const volatile ap_private<_AP_W1, _AP_S1, _AP_N1>& that) : VAL(that.pVal[0]), pVal(&VAL) { + clearUnusedBits(); + } + +#if 0 +template + explicit ap_private(const ap_private<_AP_W1, true, 1+_AP_W1/64>& that) + : VAL((_AP_W1>_AP_W) ? that.VAL & mask : ((1ULL<<(_AP_W1-1)&that.pVal[0]) ? sign_ext_mask<_AP_W1>::mask | that.VAL : that.pVal[0])), pVal(&VAL) {} + +template + explicit ap_private(const ap_private<_AP_W1, false, (_AP_W1+63)/64>& that) + : VAL(that.VAL & mask), pVal(&VAL) {} +#endif + + explicit ap_private(const char* val) : pVal(&VAL) { + std::string str(val); + uint32_t strLen = str.length(); + const char *strp = str.c_str(); + uint32_t offset = 0; + uint32_t base = 0; + bool neg = false; + uint32_t radix = 10; + ap_parse_sign(strp, base, neg); + ap_parse_prefix(strp + base, offset, radix); + + if ((radix != 10 && neg) || + (strLen - base - offset <= 0) || + InvalidDigit(strp, strLen, base + offset, radix)) { + fprintf(stderr, "invalid character string %s !\n", val); + assert(0); + } + + ap_private<_AP_W, _AP_S> ap_private_val(str.c_str(), strLen, radix, base, offset); + if (neg) + ap_private_val = -ap_private_val; + operator = (ap_private_val); + } + + ap_private(const char* val, signed char rd): pVal(&VAL) { + std::string str(val); + uint32_t strLen = str.length(); + const char *strp = str.c_str(); + uint32_t offset = 0; + uint32_t base = 0; + uint32_t radix = rd; + bool neg = false; + ap_parse_sign(strp, base, neg); + ap_parse_prefix(strp + base, offset, radix); + + if ((radix != 10 && neg) || + (strLen - base - offset <= 0) || + InvalidDigit(strp, strLen, base + offset, radix)) { + fprintf(stderr, "invalid character string %s !\n", val); + assert(0); + } + + uint32_t bitsNeeded = ap_private<_AP_W, _AP_S>::getBitsNeeded(strp, strLen, radix); + ap_private<_AP_W, _AP_S> ap_private_val(strp , strLen, radix, base, offset); + //ap_private<_AP_W, _AP_S> ap_private_val(bitsNeeded, strp , strLen, radix, base, offset); + if (strp[0] == '-') + ap_private_val = -ap_private_val; + operator = (ap_private_val); + } + + INLINE bool isNegative() const { + static const uint64_t sign_mask = 1ULL << (_AP_W-1); + return _AP_S && (sign_mask & VAL); + } + + INLINE bool isPositive() const { + return !isNegative(); + } + + INLINE bool isStrictlyPositive() const { + return !isNegative() && VAL!=0; + } + + INLINE bool isAllOnesValue() const { + return (mask & VAL) == mask; + } + + template + INLINE bool operator==(const ap_private<_AP_W1, _AP_S1, 1>& RHS) const { + return (VAL == RHS.VAL); + } + + INLINE bool operator==(const ap_private<_AP_W, _AP_S>& RHS) const { return VAL == RHS.VAL; } + INLINE bool operator==(const ap_private<_AP_W, !_AP_S>& RHS) const { return getVal() == RHS.getVal(); } + INLINE bool operator==(uint64_t Val) const { return (VAL == Val); } + INLINE bool operator!=(uint64_t Val) const { return (VAL != Val); } + INLINE bool operator!=(const ap_private<_AP_W, _AP_S>& RHS) const { return VAL != RHS.VAL; } + INLINE bool operator!=(const ap_private<_AP_W, !_AP_S>& RHS) const { return getVal() != RHS.getVal(); } + const ap_private operator++() { ++VAL; clearUnusedBits(); return *this; } + const ap_private operator--(int) { + ap_private orig(*this); + --VAL; clearUnusedBits(); + return orig; + } + const ap_private operator--() { --VAL; clearUnusedBits(); return *this;} + INLINE bool operator !() const { return !VAL;} + + const ap_private operator++(int) { + ap_private orig(*this); + VAL++; clearUnusedBits(); + return orig; + } + + const ap_private operator~() {return ap_private(~VAL);} + INLINE typename RType<1,false>::minus operator-() const { + return ap_private<1,false>(0) - (*this); + } + + INLINE std::string toString(uint8_t radix, bool wantSigned) const ; + INLINE std::string toStringUnsigned(uint8_t radix = 10) const { + return toString(radix, false); + } + INLINE std::string toStringSigned(uint8_t radix = 10) const { + return toString(radix, true); + } + INLINE void clear() { + VAL=0; + } + INLINE ap_private& clear(uint32_t bitPosition) { VAL &= ~(1ULL<<(bitPosition)); clearUnusedBits(); return *this;} + + INLINE ap_private ashr(uint32_t shiftAmt) const { + enum {excess_bits = APINT_BITS_PER_WORD - BitWidth}; + if (_AP_S) + return ap_private((shiftAmt == BitWidth) ? 0 : ((int64_t)VAL) >> (shiftAmt)); + else + return ap_private((shiftAmt == BitWidth) ? 0 : (VAL) >> (shiftAmt)); + } + + INLINE ap_private lshr(uint32_t shiftAmt) const { + return ap_private((shiftAmt == BitWidth) ? ap_private(0) : ap_private((VAL&mask) >> (shiftAmt))); + } + + INLINE ap_private shl(uint32_t shiftAmt) const { + if (shiftAmt > BitWidth) { + if (!isNegative()) + return ap_private(0); + else return ap_private(-1); + } + if (shiftAmt == BitWidth) return ap_private(0); + else return ap_private((VAL) << (shiftAmt)); + //return ap_private((shiftAmt == BitWidth) ? ap_private(0ULL) : ap_private(VAL << shiftAmt)); + } + + INLINE int64_t getSExtValue() const { + return VAL; + } + + INLINE uint64_t getZExtValue() const { + return VAL & mask; + } + + template + INLINE ap_private(const ap_range_ref<_AP_W2,_AP_S2>& ref) : pVal(&VAL) { + *this=ref.get(); + } + + template + INLINE ap_private(const ap_bit_ref<_AP_W2,_AP_S2>& ref) : pVal(&VAL) { + *this = ((uint64_t)(bool)ref); + } + + template + INLINE ap_private(const ap_concat_ref<_AP_W2, _AP_T2,_AP_W3, _AP_T3>& ref) : pVal(&VAL) { + *this=ref.get(); + } + + template + INLINE ap_private(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2> &val) : pVal(&VAL) { + *this = ((val.operator ap_private<_AP_W2, false> ())); + } + + template + INLINE ap_private(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2> &val) : pVal(&VAL) { + *this = (uint64_t)(bool)val; + } + + INLINE void write(const ap_private<_AP_W, _AP_S>& op2) volatile { + *this = (op2); + } + + //Explicit conversions to C interger types + //----------------------------------------------------------- + ValType getVal() const { + return VAL; + } + operator ValType () const { + return getVal(); + } + INLINE int to_int() const { + // ap_private<64 /* _AP_W */, _AP_S> res(V); + return (int) getVal(); + } + + INLINE unsigned to_uint() const { + return (unsigned) getVal(); + } + + INLINE long to_long() const { + return (long) getVal(); + } + + INLINE unsigned long to_ulong() const { + return (unsigned long) getVal(); + } + + INLINE ap_slong to_int64() const { + return (ap_slong) getVal(); + } + + INLINE ap_ulong to_uint64() const { + return (ap_ulong) getVal(); + } + + INLINE double to_double() const { + if (isNegative()) + return roundToDouble(true); + else + return roundToDouble(false); + } + + INLINE bool isMinValue() const { return VAL == 0;} + template INLINE ap_private& operator&=(const ap_private<_AP_W1, _AP_S1>& RHS) { + VAL = VAL&RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + + template INLINE ap_private& operator|=(const ap_private<_AP_W1, _AP_S1>& RHS) { + VAL = VAL|RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + + template INLINE ap_private& operator^=(const ap_private<_AP_W1, _AP_S1>& RHS){ + VAL = VAL^RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + + template INLINE ap_private& operator*=(const ap_private<_AP_W1, _AP_S1>& RHS){ + VAL = VAL*RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + + template INLINE ap_private& operator+=(const ap_private<_AP_W1, _AP_S1>& RHS){ + VAL = VAL+RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + + template INLINE ap_private& operator-=(const ap_private<_AP_W1, _AP_S1>& RHS){ + VAL = VAL-RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + INLINE const ap_private& operator<<=(uint32_t shiftAmt) { VAL<<=shiftAmt; clearUnusedBits(); return *this; } + + template INLINE typename RType<_AP_W1, _AP_S1>::logic operator&(const ap_private<_AP_W1, _AP_S1>& RHS) const { + if (RType<_AP_W1, _AP_S1>::logic_w <= 64) { + typename RType<_AP_W1, _AP_S1>::logic Ret(VAL & RHS.VAL); + return Ret; + } else { + typename RType<_AP_W1, _AP_S1>::logic Ret = *this; + return Ret & RHS; + } + } + + template INLINE typename RType<_AP_W1, _AP_S1>::logic operator^(const ap_private<_AP_W1, _AP_S1>& RHS) const { + if (RType<_AP_W1, _AP_S1>::logic_w <= 64) { + typename RType<_AP_W1, _AP_S1>::logic Ret(VAL ^ RHS.VAL); + return Ret; + } else { + typename RType<_AP_W1, _AP_S1>::logic Ret = *this; + return Ret ^ RHS; + } + } + + template INLINE typename RType<_AP_W1, _AP_S1>::logic operator|(const ap_private<_AP_W1, _AP_S1>& RHS) const { + if (RType<_AP_W1, _AP_S1>::logic_w <= 64) { + typename RType<_AP_W1, _AP_S1>::logic Ret(VAL | RHS.VAL); + return Ret; + } else { + typename RType<_AP_W1, _AP_S1>::logic Ret = *this; + return Ret | RHS; + } + } + + INLINE ap_private<_AP_W, _AP_S> And(const ap_private<_AP_W, _AP_S>& RHS) const { + return ap_private<_AP_W, _AP_S>(VAL & RHS.VAL); + } + + INLINE ap_private<_AP_W, _AP_S> Or(const ap_private<_AP_W, _AP_S>& RHS) const { + return ap_private<_AP_W, _AP_S>(VAL | RHS.VAL); + } + + INLINE ap_private<_AP_W, _AP_S> Xor(const ap_private<_AP_W, _AP_S>& RHS) const { + return ap_private<_AP_W, _AP_S>(VAL ^ RHS.VAL); + } +#if 1 + template + INLINE typename RType<_AP_W1, _AP_S1>::mult operator*(const ap_private<_AP_W1, _AP_S1>& RHS) const { + if (RType<_AP_W1, _AP_S1>::mult_w <= 64) { + typename RType<_AP_W1, _AP_S1>::mult Result(VAL * RHS.VAL); + return Result; + } else { + typename RType<_AP_W1, _AP_S1>::mult Result = typename RType<_AP_W1, _AP_S1>::mult(*this); + Result *= RHS; + return Result; + } + } +#endif + INLINE ap_private<_AP_W, _AP_S> Mul(const ap_private<_AP_W, _AP_S>& RHS) const { + return ap_private<_AP_W, _AP_S>(VAL * RHS.VAL); + } + + INLINE ap_private<_AP_W, _AP_S> Add(const ap_private<_AP_W, _AP_S>& RHS) const { + return ap_private<_AP_W, _AP_S>(VAL + RHS.VAL); + } + + INLINE ap_private<_AP_W, _AP_S> Sub(const ap_private<_AP_W, _AP_S>& RHS) const { + return ap_private<_AP_W, _AP_S>(VAL - RHS.VAL); + } + +#if 1 + INLINE ap_private& operator&=(uint64_t RHS) { VAL &= RHS; clearUnusedBits(); return *this;} + INLINE ap_private& operator|=(uint64_t RHS) { VAL |= RHS; clearUnusedBits(); return *this;} + INLINE ap_private& operator^=(uint64_t RHS){ VAL ^= RHS; clearUnusedBits(); return *this;} + INLINE ap_private& operator*=(uint64_t RHS){ VAL *= RHS; clearUnusedBits(); return *this; } + INLINE ap_private& operator+=(uint64_t RHS){ VAL += RHS; clearUnusedBits(); return *this;} + INLINE ap_private& operator-=(uint64_t RHS){ VAL -= RHS; clearUnusedBits(); return *this; } + INLINE ap_private operator&(uint64_t RHS) const { return ap_private(VAL & RHS); } + INLINE ap_private operator|(uint64_t RHS) const { return ap_private(VAL | RHS); } + INLINE ap_private operator^(uint64_t RHS) const { return ap_private(VAL ^ RHS); } + INLINE ap_private operator*(uint64_t RHS) const { return ap_private(VAL * RHS); } + INLINE ap_private operator/(uint64_t RHS) const { return ap_private(VAL / RHS); } + INLINE ap_private operator+(uint64_t RHS) const { return ap_private(VAL + RHS); } + INLINE ap_private operator-(uint64_t RHS) const { return ap_private(VAL - RHS); } +#endif + INLINE bool isMinSignedValue() const { + static const uint64_t min_mask = ~(~0ULL << (_AP_W-1)); + return BitWidth == 1 ? VAL == 1 : + (ap_private_ops::isNegative<_AP_W>(*this) && ((min_mask & VAL)==0)); + } + +#if 1 + + template INLINE + typename RType<_AP_W1,_AP_S1>::plus operator+(const ap_private<_AP_W1, _AP_S1>& RHS) const { + if (RType<_AP_W1,_AP_S1>::plus_w <=64) + return typename RType<_AP_W1,_AP_S1>::plus(RType<_AP_W1,_AP_S1>::plus_s ? int64_t(VAL+RHS.VAL):uint64_t(VAL+RHS.VAL)); + typename RType<_AP_W1,_AP_S1>::plus Result=RHS; + Result += VAL; + return Result; + } + + template INLINE + typename RType<_AP_W1,_AP_S1>::minus operator-(const ap_private<_AP_W1, _AP_S1>& RHS) const { + if (RType<_AP_W1,_AP_S1>::minus_w <=64) + return typename RType<_AP_W1,_AP_S1>::minus(int64_t(VAL-RHS.VAL)); + typename RType<_AP_W1,_AP_S1>::minus Result=*this; + Result -= RHS; + return Result; + } +#endif // #if 1 + + INLINE ap_private& flip() { + VAL = (~0ULL^VAL)&mask; + clearUnusedBits(); + return *this; + } + + uint32_t countPopulation() const { return CountPopulation_64(VAL);} + uint32_t countLeadingZeros() const { + int remainder = BitWidth % APINT_BITS_PER_WORD; + int excessBits = (APINT_BITS_PER_WORD - remainder) % APINT_BITS_PER_WORD; + //enum { remainder = BitWidth % APINT_BITS_PER_WORD, excessBits = APINT_BITS_PER_WORD - remainder}; + uint32_t Count = CountLeadingZeros_64(VAL); + if (Count) + Count-=excessBits; + return AESL_std::min(Count, (uint32_t)_AP_W); + } + + /// HiBits - This function returns the high "numBits" bits of this ap_private. + ap_private<_AP_W, _AP_S, 1> getHiBits(uint32_t numBits) const { + ap_private<_AP_W, _AP_S, 1> ret(*this); + ret = (ret)>>(BitWidth - numBits); + return ret; + } + + /// LoBits - This function returns the low "numBits" bits of this ap_private. + ap_private<_AP_W, _AP_S, 1> getLoBits(uint32_t numBits) const { + ap_private<_AP_W, _AP_S, 1> ret((VAL) << (BitWidth - numBits)); + ret = (ret)>>(BitWidth - numBits); + return ret; + //return ap_private(numBits, (VAL << (BitWidth - numBits))>> (BitWidth - numBits)); + } + + ap_private<_AP_W, _AP_S,1>& set(uint32_t bitPosition) { + VAL |= (1ULL << (bitPosition)); + clearUnusedBits(); + return *this; // clearUnusedBits(); + } + + void set() { + VAL = ~0ULL; + clearUnusedBits(); + } + + template + INLINE void set(const ap_private<_AP_W3, false> & val) { + operator = (ap_private<_AP_W3, _AP_S>(val)); + } + + INLINE void set(const ap_private & val) { + operator = (val); + } + + bool operator[](uint32_t bitPosition) const { + return (((1ULL << (bitPosition)) & VAL) != 0); + } + + INLINE void clearUnusedBits(void) { + enum { excess_bits = (_AP_W%APINT_BITS_PER_WORD) ? APINT_BITS_PER_WORD -_AP_W%APINT_BITS_PER_WORD : 0}; + VAL = _AP_S ? ((((int64_t)VAL)<<(excess_bits))>> (excess_bits)) : (excess_bits ? ((VAL)<<(excess_bits))>>(excess_bits) : VAL); + } + + INLINE void clearUnusedBitsToZero(void) { + enum { excess_bits = (_AP_W%APINT_BITS_PER_WORD) ? APINT_BITS_PER_WORD -_AP_W%APINT_BITS_PER_WORD : 0}; + static uint64_t mask = ~0ULL >> (excess_bits); + VAL &= mask; + } + + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1> udiv(const ap_private<_AP_W, _AP_S1>& RHS) const { + return ap_private<_AP_W, _AP_S||_AP_S1>(VAL / RHS.VAL); + } + + INLINE ap_private udiv(uint64_t RHS) const { + return ap_private(VAL / RHS); + } + + /// Signed divide this ap_private by ap_private RHS. + /// @brief Signed division function for ap_private. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1> sdiv(const ap_private<_AP_W, _AP_S1> & RHS) const { + if (isNegative()) + if (RHS.isNegative()) + return (-(*this)).udiv(-RHS); + else + return -((-(*this)).udiv(RHS)); + else if (RHS.isNegative()) + return -(this->udiv(-RHS)); + return this->udiv(RHS); + } + + /// Signed divide this ap_private by ap_private RHS. + /// @brief Signed division function for ap_private. + INLINE ap_private sdiv(int64_t RHS) const { + if (isNegative()) + if (RHS<0) + return (-(*this)).udiv(-RHS); + else + return -((-(*this)).udiv(RHS)); + else if (RHS<0) + return -(this->udiv(-RHS)); + return this->udiv(RHS); + } + + template + INLINE ap_private urem(const ap_private<_AP_W, _AP_S2>& RHS) const { + assert(RHS.VAL != 0 && "Divide by 0"); + return ap_private(VAL%RHS.VAL); + } + + INLINE ap_private urem(uint64_t RHS) const { + assert(RHS != 0 && "Divide by 0"); + return ap_private(VAL%RHS); + } + + /// Signed remainder operation on ap_private. + /// @brief Function for signed remainder operation. + template + INLINE ap_private srem(const ap_private<_AP_W, _AP_S2>& RHS) const { + if (isNegative()) { + ap_private lhs = -(*this); + if (RHS.isNegative()) { + ap_private rhs = -RHS; + return -(lhs.urem(rhs)); + } else + return -(lhs.urem(RHS)); + } else if (RHS.isNegative()) { + ap_private rhs = -RHS; + return this->urem(rhs); + } + return this->urem(RHS); + } + + /// Signed remainder operation on ap_private. + /// @brief Function for signed remainder operation. + INLINE ap_private srem(int64_t RHS) const { + if (isNegative()) + if (RHS<0) + return -((-(*this)).urem(-RHS)); + else + return -((-(*this)).urem(RHS)); + else if (RHS<0) + return this->urem(-RHS); + return this->urem(RHS); + } + + INLINE static void udivrem(const ap_private &LHS, const ap_private &RHS, + ap_private &Quotient, ap_private &Remainder){ + assert(RHS!=0 && "Divide by 0"); + Quotient = LHS.VAl/RHS.VAl; + Remainder = LHS.VAL % RHS.VAL; + } + + INLINE static void udivrem(const ap_private &LHS, uint64_t RHS, + ap_private &Quotient, ap_private &Remainder){ + assert(RHS!=0 && "Divide by 0"); + Quotient = LHS.VAl/RHS; + Remainder = LHS.VAL % RHS; + } + + INLINE static void sdivrem(const ap_private &LHS, const ap_private &RHS, + ap_private &Quotient, ap_private &Remainder) { + if (LHS.isNegative()) { + if (RHS.isNegative()) + ap_private::udivrem(-LHS, -RHS, Quotient, Remainder); + else + ap_private::udivrem(-LHS, RHS, Quotient, Remainder); + Quotient = -Quotient; + Remainder = -Remainder; + } else if (RHS.isNegative()) { + ap_private::udivrem(LHS, -RHS, Quotient, Remainder); + Quotient = -Quotient; + } else { + ap_private::udivrem(LHS, RHS, Quotient, Remainder); + } + } + + INLINE static void sdivrem(const ap_private &LHS, int64_t RHS, + ap_private &Quotient, ap_private &Remainder) { + if (LHS.isNegative()) { + if (RHS<0) + ap_private::udivrem(-LHS, -RHS, Quotient, Remainder); + else + ap_private::udivrem(-LHS, RHS, Quotient, Remainder); + Quotient = -Quotient; + Remainder = -Remainder; + } else if (RHS<0) { + ap_private::udivrem(LHS, -RHS, Quotient, Remainder); + Quotient = -Quotient; + } else { + ap_private::udivrem(LHS, RHS, Quotient, Remainder); + } + } + + template INLINE bool eq(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return (*this) == RHS; + } + + template INLINE bool ne(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return !((*this) == RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// the validity of the less-than relationship. + /// @returns true if *this < RHS when both are considered unsigned. + /// @brief Unsigned less than comparison + template INLINE bool ult(const ap_private<_AP_W1, _AP_S1, 1>& RHS) const { + uint64_t lhsZext = ((uint64_t(VAL)) << (64-_AP_W)) >> (64-_AP_W); + uint64_t rhsZext = ((uint64_t(RHS.VAL)) << (64-_AP_W1)) >> (64-_AP_W1); + return lhsZext < rhsZext; + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the less-than relationship. + /// @returns true if *this < RHS when both are considered signed. + /// @brief Signed less than comparison + template INLINE bool slt(const ap_private<_AP_W1, _AP_S1, 1>& RHS) const { + int64_t lhsSext = ((int64_t(VAL)) << (64-_AP_W)) >> (64-_AP_W); + int64_t rhsSext = ((int64_t(RHS.VAL)) << (64-_AP_W1)) >> (64-_AP_W1); + return lhsSext < rhsSext; + } + + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// validity of the less-or-equal relationship. + /// @returns true if *this <= RHS when both are considered unsigned. + /// @brief Unsigned less or equal comparison + template INLINE bool ule(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return ult(RHS) || eq(RHS); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the less-or-equal relationship. + /// @returns true if *this <= RHS when both are considered signed. + /// @brief Signed less or equal comparison + template INLINE bool sle(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return slt(RHS) || eq(RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// the validity of the greater-than relationship. + /// @returns true if *this > RHS when both are considered unsigned. + /// @brief Unsigned greather than comparison + template INLINE bool ugt(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return !ult(RHS) && !eq(RHS); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// the validity of the greater-than relationship. + /// @returns true if *this > RHS when both are considered signed. + /// @brief Signed greather than comparison + template INLINE bool sgt(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return !slt(RHS) && !eq(RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// validity of the greater-or-equal relationship. + /// @returns true if *this >= RHS when both are considered unsigned. + /// @brief Unsigned greater or equal comparison + template INLINE bool uge(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return !ult(RHS); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the greater-or-equal relationship. + /// @returns true if *this >= RHS when both are considered signed. + /// @brief Signed greather or equal comparison + template INLINE bool sge(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return !slt(RHS); + } + + INLINE ap_private abs() const { + if (isNegative()) + return -(*this); + return *this; + } + + ap_private<_AP_W, false> get() const { + ap_private<_AP_W,false> ret(*this); + return ret; + } + + INLINE static uint32_t getBitsNeeded(const char* str, uint32_t slen, uint8_t radix) { + return _AP_W; + } + + INLINE uint32_t getActiveBits() const { + uint32_t bits=_AP_W - countLeadingZeros(); + return bits?bits:1; + } + + INLINE double roundToDouble(bool isSigned=false) const { + const static uint64_t mask = ~0ULL << (APINT_BITS_PER_WORD - _AP_W); + return double(VAL); + } + + INLINE unsigned length() const { return _AP_W; } + + /*Reverse the contents of ap_private instance. I.e. LSB becomes MSB and vise versa*/ + INLINE ap_private& reverse () { + for (int i = 0; i < _AP_W/2; ++i) { + bool tmp = operator[](i); + if (operator[](_AP_W - 1 - i)) + set(i); + else + clear(i); + if (tmp) + set(_AP_W - 1 - i); + else + clear(_AP_W - 1 - i); + } + clearUnusedBits(); + return *this; + } + + /*Return true if the value of ap_private instance is zero*/ + INLINE bool iszero () const { + return isMinValue(); + } + + /* x < 0 */ + INLINE bool sign () const { + if (isNegative()) + return true; + return false; + } + + /* x[i] = !x[i] */ + INLINE void invert (int i) { + assert( i >= 0 && "Attempting to read bit with negative index"); + assert( i < _AP_W && "Attempting to read bit beyond MSB"); + flip(i); + } + + /* x[i] */ + INLINE bool test (int i) const { + assert( i >= 0 && "Attempting to read bit with negative index"); + assert( i < _AP_W && "Attempting to read bit beyond MSB"); + return operator[](i); + } + + //This is used for sc_lv and sc_bv, which is implemented by sc_uint + //Rotate an ap_private object n places to the left + INLINE void lrotate(int n) { + assert( n >= 0 && "Attempting to shift negative index"); + assert( n < _AP_W && "Shift value larger than bit width"); + operator = (shl(n) | lshr(_AP_W - n)); + } + + //This is used for sc_lv and sc_bv, which is implemented by sc_uint + //Rotate an ap_private object n places to the right + INLINE void rrotate(int n) { + assert( n >= 0 && "Attempting to shift negative index"); + assert( n < _AP_W && "Shift value larger than bit width"); + operator = (lshr(n) | shl(_AP_W - n)); + } + + //Set the ith bit into v + INLINE void set (int i, bool v) { + assert( i >= 0 && "Attempting to write bit with negative index"); + assert( i < _AP_W && "Attempting to write bit beyond MSB"); + v ? set(i) : clear(i); + } + + //Set the ith bit into v + INLINE void set_bit (int i, bool v) { + assert( i >= 0 && "Attempting to write bit with negative index"); + assert( i < _AP_W && "Attempting to write bit beyond MSB"); + v ? set(i) : clear(i); + } + + //Get the value of ith bit + INLINE bool get_bit (int i) const { + assert( i >= 0 && "Attempting to read bit with negative index"); + assert( i < _AP_W && "Attempting to read bit beyond MSB"); + return operator [](i); + } + + //complements every bit + INLINE void b_not() { + flip(); + } + + //Binary Arithmetic + //----------------------------------------------------------- +#define OP_BIN_AP(Sym,Rty, Fun) \ + template \ + INLINE \ + typename RType<_AP_W2,_AP_S2>::Rty \ + operator Sym (const ap_private<_AP_W2,_AP_S2>& op) const { \ + typename RType<_AP_W2,_AP_S2>::Rty lhs(*this); \ + typename RType<_AP_W2,_AP_S2>::Rty rhs(op); \ + return lhs.Fun(rhs); \ + } \ + + ///Bitwise and, or, xor + //OP_BIN_AP(&,logic, And) + //OP_BIN_AP(|,logic, Or) + //OP_BIN_AP(^,logic, Xor) + +#undef OP_BIN_AP + template + INLINE typename RType<_AP_W2,_AP_S2>::div + operator / (const ap_private<_AP_W2,_AP_S2>&op) const { + ap_private lhs=ap_private(*this); + ap_private rhs=ap_private(op); + return typename RType<_AP_W2,_AP_S2>::div((_AP_S||_AP_S2)?lhs.sdiv(rhs):lhs.udiv(rhs)); + } + + + template + INLINE typename RType<_AP_W2,_AP_S2>::mod + operator % (const ap_private<_AP_W2,_AP_S2>&op) const { + ap_private lhs=*this; + ap_private rhs=op; + typename RType<_AP_W2,_AP_S2>::mod res = typename RType<_AP_W2,_AP_S2>::mod (_AP_S?lhs.srem(rhs):lhs.urem(rhs)); + return res; + } + + +#define OP_ASSIGN_AP_2(Sym) \ + template \ + INLINE ap_private<_AP_W, _AP_S>& operator Sym##=(const ap_private<_AP_W2,_AP_S2>& op) \ + { \ + *this=operator Sym (op); \ + return *this; \ + } \ + + OP_ASSIGN_AP_2(/) + OP_ASSIGN_AP_2(%) +#undef OP_ASSIGN_AP_2 + + ///Bitwise assign: and, or, xor + //------------------------------------------------------------- + // OP_ASSIGN_AP(&) + // OP_ASSIGN_AP(^) + // OP_ASSIGN_AP(|) +#undef OP_ASSIGN_AP +#if 1 + + template + INLINE ap_private<_AP_W, _AP_S> + operator << (const ap_private<_AP_W2, _AP_S2>& op2) const { + uint32_t sh=op2.to_uint(); + return *this << sh; + } + + INLINE ap_private<_AP_W, _AP_S> + operator << (uint32_t sh) const { + return shl(sh); + } + +#endif + + template + INLINE ap_private<_AP_W, _AP_S> + operator >> (const ap_private<_AP_W2, _AP_S2>& op2) const { + uint32_t sh = op2.to_uint(); + return *this >> sh; + } + + INLINE ap_private<_AP_W, _AP_S> + operator >>(uint32_t sh) const { + ap_private<_AP_W, _AP_S> r(*this); + bool overflow=(sh>=_AP_W); + bool neg_v=r.isNegative(); + if(_AP_S) { + if(overflow) + neg_v?r.set():r.clear(); + else + return r.ashr(sh); + } else { + if(overflow) + r.clear(); + else + return r.lshr(sh); + } + return r; + } + + ///Shift assign + //------------------------------------------------------------------ +#define OP_ASSIGN_AP_3_SINGLE(Sym) \ + template \ + INLINE ap_private<_AP_W, _AP_S>& operator Sym##=(const ap_private<_AP_W2,_AP_S2>& op) \ + { \ + *this=operator Sym (op.getVal()); \ + return *this; \ + } + OP_ASSIGN_AP_3_SINGLE(>>) +#undef OP_ASSIGN_AP_3_SINGLE + + ///Comparisons + //----------------------------------------------------------------- + template + INLINE bool operator != (const ap_private<_AP_W2, _AP_S2, 1>& op) const { + return !(*this==op); + } + + template + INLINE bool operator > (const ap_private<_AP_W2, _AP_S2, 1>& op) const { + return op < *this; + } + + template + INLINE bool operator <= (const ap_private<_AP_W2, _AP_S2, 1>& op) const { + return !(*this>op); + } + + template + INLINE bool operator < (const ap_private<_AP_W2, _AP_S2, 1>& op) const { + enum { _AP_MAX_W = AP_MAX(_AP_W+(_AP_S||_AP_S2),_AP_W2+(_AP_S||_AP_S2))}; + ap_private<_AP_MAX_W, _AP_S> lhs(*this); + ap_private<_AP_MAX_W, _AP_S2> rhs(op); + if (_AP_S == _AP_S2) + return _AP_S?lhs.slt(rhs):lhs.ult(rhs); + else if (_AP_W < 32 && _AP_W2 < 32) + return lhs.slt(rhs); + else + if (_AP_S) + if (_AP_W2 >= _AP_W) + return lhs.ult(rhs); + else + return lhs.slt(rhs); + else + if (_AP_W >= _AP_W2) + return lhs.ult(rhs); + else + return lhs.slt(rhs); + } + + template + INLINE bool operator >=(const ap_private<_AP_W2, _AP_S2, 1>& op) const { + return !(*this + INLINE bool operator == (const ap_private<_AP_W2, _AP_S2, _AP_N2>& op) const { + return op == *this; + } + + template + INLINE bool operator != (const ap_private<_AP_W2, _AP_S2, _AP_N2>& op) const { + return !(op==*this); + } + + template + INLINE bool operator > (const ap_private<_AP_W2, _AP_S2, _AP_N2>& op) const { + return op < (*this); + } + + template + INLINE bool operator <= (const ap_private<_AP_W2, _AP_S2, _AP_N2>& op) const { + return op >= *this; + } + + template + INLINE bool operator <(const ap_private<_AP_W2, _AP_S2, _AP_N2>& op) const { + return op > *this; + } + + template + INLINE bool operator >=(const ap_private<_AP_W2,_AP_S2,_AP_N2>& op) const { + return op <= *this; + } + ///Bit and Part Select + //-------------------------------------------------------------- + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (int Hi, int Lo) { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (int Hi, int Lo) const { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(const_cast*>(this), Hi, Lo); + } + + INLINE ap_range_ref<_AP_W,_AP_S> + range (int Hi, int Lo) const { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>((const_cast*> (this)), Hi, Lo); + } + + INLINE ap_range_ref<_AP_W,_AP_S> + range (int Hi, int Lo) { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + range (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + range (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) const { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(const_cast(this), Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) const { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + return this->range(Hi, Lo); + } + + + INLINE ap_bit_ref<_AP_W,_AP_S> operator [] (uint32_t index) { + assert(index >= 0&&"Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S> (*this, (int)index); + } + + template + INLINE ap_bit_ref<_AP_W,_AP_S> operator [] (const ap_private<_AP_W2,_AP_S2> &index) { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S>( *this, index.to_int() ); + } + + template + INLINE bool operator [] (const ap_private<_AP_W2,_AP_S2>& index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + ap_bit_ref<_AP_W,_AP_S> br =operator [] (index); + return br.to_bool(); + } + + INLINE ap_bit_ref<_AP_W,_AP_S> bit (int index) { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S>( *this, index ); + } + + template + INLINE ap_bit_ref<_AP_W,_AP_S> bit (const ap_private<_AP_W2,_AP_S2> &index) { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W &&"Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S>( *this, index.to_int() ); + } + + INLINE bool bit (int index) const { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + ap_bit_ref<_AP_W,_AP_S> br(const_cast*>(this), index); + return br.to_bool(); + } + + template + INLINE bool bit (const ap_private<_AP_W2,_AP_S2>& index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + ap_bit_ref<_AP_W,_AP_S> br = bit(index); + return br.to_bool(); + } + + template + INLINE ap_concat_ref<_AP_W,ap_private<_AP_W, _AP_S>,_AP_W2,ap_private<_AP_W2,_AP_S2> > concat(const ap_private<_AP_W2,_AP_S2>& a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_private<_AP_W2,_AP_S2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W,ap_private<_AP_W, _AP_S>,_AP_W2,ap_private<_AP_W2,_AP_S2> > concat(ap_private<_AP_W2,_AP_S2>& a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_private<_AP_W2,_AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (const ap_private<_AP_W2, _AP_S2>& a2) const { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(const_cast& >(*this), const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (const ap_private<_AP_W2, _AP_S2>& a2) { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(*this, const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (ap_private<_AP_W2, _AP_S2>& a2) const { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(const_cast& >(*this), a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (ap_private<_AP_W2, _AP_S2>& a2) { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > + operator, (const ap_range_ref<_AP_W2, _AP_S2> &a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, + ap_range_ref<_AP_W2, _AP_S2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > + operator, (ap_range_ref<_AP_W2, _AP_S2> &a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, + ap_range_ref<_AP_W2, _AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, ap_bit_ref<_AP_W2, _AP_S2> > + operator, (const ap_bit_ref<_AP_W2, _AP_S2> &a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, + ap_bit_ref<_AP_W2, _AP_S2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, ap_bit_ref<_AP_W2, _AP_S2> > + operator, (ap_bit_ref<_AP_W2, _AP_S2> &a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, + ap_bit_ref<_AP_W2, _AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > + operator, (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > + operator, (ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) const { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) const { + return ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, a2); + } + + template + INLINE ap_private + operator & (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) { + return *this & a2.get(); + } + + template + INLINE ap_private + operator | (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) { + return *this | a2.get(); + } + + template + INLINE ap_private + operator ^ (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) { + return *this ^ a2.get(); + } + + + //Reduce operation + //----------------------------------------------------------- + INLINE bool and_reduce() const { + return (VAL & mask) == mask; + } + + INLINE bool nand_reduce() const { + return (VAL & mask) != mask; + } + + INLINE bool or_reduce() const { + return (bool)VAL; + } + + INLINE bool nor_reduce() const { + return VAL==0; + } + + INLINE bool xor_reduce() const { + unsigned int i=countPopulation(); + return (i%2)?true:false; + } + + INLINE bool xnor_reduce() const { + unsigned int i=countPopulation(); + return (i%2)?false:true; + } + + INLINE std::string to_string(uint8_t radix=2, bool sign=false) const { + return toString(radix, radix==10?_AP_S:sign); + } +}; +template +std::string ap_private<_AP_W, _AP_S, 1>::toString(uint8_t radix, bool wantSigned) const { + assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) && + "Radix should be 2, 8, 10, or 16!"); + static const char *digits[] = { + "0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f" + }; + std::string result; + if (radix != 10) { + // For the 2, 8 and 16 bit cases, we can just shift instead of divide + // because the number of bits per digit (1,3 and 4 respectively) divides + // equaly. We just shift until there value is zero. + + // First, check for a zero value and just short circuit the logic below. + if (*this == (uint64_t)(0)) + result = "0"; + else { + ap_private<_AP_W, false, 1> tmp(*this); + size_t insert_at = 0; + if (wantSigned && isNegative()) { + // They want to print the signed version and it is a negative value + // Flip the bits and add one to turn it into the equivalent positive + // value and put a '-' in the result. + tmp.flip(); + tmp++; + result = "-"; + insert_at = 1; + } + // Just shift tmp right for each digit width until it becomes zero + uint32_t shift = (radix == 16 ? 4 : (radix == 8 ? 3 : 1)); + uint64_t mask = radix - 1; + ap_private<_AP_W, false, 1> zero(0); + while (tmp.ne(zero)) { + unsigned digit = (unsigned)(tmp.VAL & mask); + result.insert(insert_at, digits[digit]); + tmp = tmp.lshr(shift); + } + } + return result; + } + + ap_private<_AP_W, false, 1> tmp(*this); + ap_private<6, false, 1> divisor(radix); + ap_private<_AP_W, _AP_S, 1> zero(0); + size_t insert_at = 0; + if (wantSigned && isNegative()) { + // They want to print the signed version and it is a negative value + // Flip the bits and add one to turn it into the equivalent positive + // value and put a '-' in the result. + tmp.flip(); + tmp++; + result = "-"; + insert_at = 1; + } + if (tmp == ap_private<_AP_W, false, 1>(0ULL)) + result = "0"; + else while (tmp.ne(zero)) { + ap_private<_AP_W, false, 1> APdigit = tmp%divisor; + ap_private<_AP_W, false, 1> tmp2 = tmp/divisor; + uint32_t digit = (uint32_t)(APdigit.getZExtValue()); + assert(digit < radix && "divide failed"); + result.insert(insert_at,digits[digit]); + tmp = tmp2; + } + return result; + +} + +#endif /* #ifndef LLVM_SUPPORT_MATHEXTRAS_H */ \ No newline at end of file diff --git a/hls_2018/router_03_boardstr/main.cpp b/hls_2018/router_03_boardstr/main.cpp new file mode 100755 index 0000000..2de79fc --- /dev/null +++ b/hls_2018/router_03_boardstr/main.cpp @@ -0,0 +1,99 @@ +/** + * main.cpp + * + * for Vivado HLS + */ + +#ifdef SOFTWARE +#include "ap_int.h" +#else +#include +#endif + +#ifdef CALCTIME +#include +#include +#endif + +#include "router.hpp" + +#define PRINT_SOLUTION + + +int main(int argc, char *argv[]) { + using namespace std; + + // Test data // + // NL_Q00.txt + //char boardstr[BOARDSTR_SIZE] = "X10Y05Z3L0000107041L0004107002L0102102021L0900100003"; + // NL_Q06.txt + char boardstr[BOARDSTR_SIZE] = "X10Y18Z2L0900109002L0901105012L0902103052L0903103062L0904100102L0905106012L0906109022L0717109102L0808109112L0017209172L0401200072L0912208152L0009201092L0709209092L0901206052L0309204092L0701209072L0101201022L0011202152L0016202162"; + // NL_Q08.txt + //char boardstr[BOARDSTR_SIZE] = "X17Y20Z2L0000103022L1603115052L0916107032L0302108012L1104111042L1002100002L0919116162L1616113182L1001115012L0500201182L1603213152L0600210022"; + char boardstr_high[BOARDSTR_SIZE] = {}; + + // Read boardstr from command line + if (1 < argc) { + // From stdin + if(argv[1][0]!='X') + { + char* c_p=fgets(boardstr, BOARDSTR_SIZE, stdin); + int length=strlen(c_p); + boardstr[length-1]=0; + } + else + { + strcpy(boardstr, argv[1]); + } + } + + // Seed value + int seed = 12345; + if (2 < argc) { + seed = atoi(argv[2]); + } + +#ifdef PRINT_SOLUTION + int size_x = (boardstr[1] - '0') * 10 + (boardstr[2] - '0'); + int size_y = (boardstr[4] - '0') * 10 + (boardstr[5] - '0'); + int size_z = (boardstr[7] - '0'); +#endif + + // Solver + ap_int<32> status; + clock_t clock_start, clock_done; + clock_start = clock(); + bool result = pynqrouter(boardstr, boardstr_high, seed, &status); + clock_done = clock(); + if (result) { + cout << endl << "Test Passed!" << endl; + } else { + cout << endl << "Test Failed!" << endl; + } + cout << "status = " << (int)status << endl; + cout << "elapsed = " << ((double)(clock_done - clock_start) / CLOCKS_PER_SEC) << endl << endl; + +#ifdef PRINT_SOLUTION + cout << "SOLUTION" << endl; + cout << "========" << endl; + cout << "SIZE " << size_x << "X" << size_y << "X" << size_z << endl; + for (int z = 0; z < size_z; z++) { + cout << "LAYER " << (z + 1) << endl; + for (int y = 0; y < size_y; y++) { + for (int x = 0; x < size_x; x++) { + if (x != 0) { + cout << ","; + } + int i = ((x * MAX_WIDTH + y) << BITWIDTH_Z) | z; + unsigned int num = (unsigned char)(boardstr[i]) + ((unsigned char)(boardstr_high[i]) << 8); + cout << setfill('0') << setw(3) << right << num; + //cout << num; + } + cout << endl; + } + } +#endif + + return 0; +} + diff --git a/hls_2018/router_03_boardstr/router.cpp b/hls_2018/router_03_boardstr/router.cpp new file mode 100755 index 0000000..93ea273 --- /dev/null +++ b/hls_2018/router_03_boardstr/router.cpp @@ -0,0 +1,518 @@ +/** + * router.cpp + * + * for Vivado HLS + */ + +#ifdef SOFTWARE +#include "ap_int.h" +#else +#include +#endif + +#include "./router.hpp" + +// Set weight +ap_uint<8> new_weight(ap_uint<16> x) { +#pragma HLS INLINE + // K. Terada: y = 1~32 (8bit) + ap_uint<8> y; + y = ((x & 255) >> 3) + 1; + return y; +} + + +// Global values +static ap_uint<7> size_x; // X +static ap_uint<7> size_y; // Y +static ap_uint<4> size_z; // Z + +static ap_uint line_num = 0; // #Lines + +#ifdef DEBUG_PRINT +int max_queue_length; // Max length of priority queue +int max_search_count; // Max count of queue pop +int max_buffer_length; // Max length of line buffer +#endif + + +bool pynqrouter(char boardstr[BOARDSTR_SIZE], char boardstr_high[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *status) { +#pragma HLS INTERFACE s_axilite port=boardstr bundle=AXI4LS +#pragma HLS INTERFACE s_axilite port=boardstr_high bundle=AXI4LS +#pragma HLS INTERFACE s_axilite port=seed bundle=AXI4LS +#pragma HLS INTERFACE s_axilite port=status bundle=AXI4LS +#pragma HLS INTERFACE s_axilite port=return bundle=AXI4LS + + // status(0:Solved, 1:Not solved) + *status = -1; + + // For all lines + ap_uint paths[MAX_BUFFER]; // Line buffer + + // For each line + // Note: Should not partition completely + bool adjacents[MAX_LINES]; // Line has adjacent terminals? + ap_uint starts[MAX_LINES]; // Start list + ap_uint goals[MAX_LINES]; // Goal list + ap_uint s_idx[MAX_LINES]; // Start point on line buffer + + ap_uint<8> weights[MAX_CELLS]; // Weight of each cell + // Note: Should not partition weight array + // since each element will be accessed in "random" order + + + // ================================ + // (Step.0) Initialization (BEGIN) + // ================================ + + // Note: Loop counter -> need an extra bit (for condition determination) + + INIT_WEIGHTS: + for (ap_uint i = 0; i < (ap_uint)(MAX_CELLS); i++) { + weights[i] = 1; + } + + /// Parse /// + size_x = (boardstr[1] - '0') * 10 + (boardstr[2] - '0'); + size_y = (boardstr[4] - '0') * 10 + (boardstr[5] - '0'); + size_z = (boardstr[7] - '0'); + + INIT_BOARDS: + for (ap_uint idx = 8; idx < (ap_uint)(BOARDSTR_SIZE); idx+=11) { + + // NULL-terminated + if (boardstr[idx] == 0) break; + + // Start & Goal of each line + ap_uint<7> s_x = (boardstr[idx+1] - '0') * 10 + (boardstr[idx+2] - '0'); + ap_uint<7> s_y = (boardstr[idx+3] - '0') * 10 + (boardstr[idx+4] - '0'); + ap_uint<3> s_z = (boardstr[idx+5] - '0') - 1; + ap_uint<7> g_x = (boardstr[idx+6] - '0') * 10 + (boardstr[idx+7] - '0'); + ap_uint<7> g_y = (boardstr[idx+8] - '0') * 10 + (boardstr[idx+9] - '0'); + ap_uint<3> g_z = (boardstr[idx+10] - '0') - 1; + + ap_uint start_id = (((ap_uint)s_x * MAX_WIDTH + (ap_uint)s_y) << BITWIDTH_Z) | (ap_uint)s_z; + ap_uint goal_id = (((ap_uint)g_x * MAX_WIDTH + (ap_uint)g_y) << BITWIDTH_Z) | (ap_uint)g_z; + starts[line_num] = start_id; + goals[line_num] = goal_id; + weights[start_id] = MAX_WEIGHT; + weights[goal_id] = MAX_WEIGHT; + + // Line has adjacent terminals? + adjacents[line_num] = false; + ap_int<8> dx = (ap_int<8>)g_x - (ap_int<8>)s_x; // Min: -71, Max: 71 (Signed 8bit) + ap_int<8> dy = (ap_int<8>)g_y - (ap_int<8>)s_y; // Min: -71, Max: 71 (Signed 8bit) + ap_int<4> dz = (ap_int<4>)g_z - (ap_int<4>)s_z; // Min: -7, Max: 7 (Signed 4bit) + 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; + } + + line_num++; + } + + // ================================ + // (Step.0) Initialization (END) + // ================================ + +#ifdef DEBUG_PRINT + max_queue_length = 0; + max_search_count = 0; + max_buffer_length = 0; +#endif + + ap_uint pointer = 0; // Pointer for line buffer + + // ================================ + // (Step.1) Initial Routing (BEGIN) + // ================================ + +#ifdef DEBUG_PRINT + cout << "Initial Routing ..." << endl; +#endif + + FIRST_ROUTING: + for (ap_uint i = 0; i < (ap_uint)(line_num); i++) { +#pragma HLS LOOP_TRIPCOUNT min=2 max=999 + + s_idx[i] = pointer; + + if (adjacents[i] == true) continue; // Skip routing + +#ifdef DEBUG_PRINT + //cout << "LINE #" << (int)(i + 1) << endl; +#endif + // Routing + pointer = search(s_idx[i], paths, starts[i], goals[i], weights); + } + + // ================================ + // (Step.1) Initial Routing (END) + // ================================ + + + // Memories for Overlap Check + ap_uint<1> overlap_checks[MAX_CELLS]; + bool has_overlap = false; + + // ================================ + // (Step.2) Rip-up Routing (BEGIN) + // ================================ + +#ifdef DEBUG_PRINT + cout << "Rip-up Routing ..." << endl; +#endif + + ROUTING: + for (ap_uint<16> round = 0; round < 32768 /* = (2048 * 16) */; round++) { +#pragma HLS LOOP_TRIPCOUNT min=1 max=32768 + + // Target line + ap_uint target = round % line_num; + ap_uint next_target = target + 1; + if (next_target == line_num) next_target = 0; + +#ifdef DEBUG_PRINT + //cout << "(round " << round << ") LINE #" << (int)(target + 1); + //cout << " -> " << pointer << endl; +#endif +#ifdef DEBUG_PRINT + int buffer_length = pointer - s_idx[target]; + if (max_buffer_length < buffer_length) { max_buffer_length = buffer_length; } +#endif + + // Skip routing + if (adjacents[target] == true) { + s_idx[target] = pointer; continue; + } + + + // (Step.2-1) Reset weights of target line + WEIGHT_RESET: + for (ap_uint j = s_idx[target]; j != s_idx[next_target]; j++) { +#pragma HLS LOOP_TRIPCOUNT min=1 max=256 + weights[paths[j]] = 1; + } + + // (Step.2-2) Set weights of non-target lines and terminals + ap_uint<8> current_round_weight = new_weight(round); + WEIGHT_PATH: + for (ap_uint j = s_idx[next_target]; j != pointer; j++) { +#pragma HLS LOOP_TRIPCOUNT min=1 max=8192 + weights[paths[j]] = current_round_weight; + } + WEIGHT_TERMINAL: + for (ap_uint i = 0; i < (ap_uint)(line_num); i++) { +#pragma HLS LOOP_TRIPCOUNT min=2 max=999 + weights[starts[i]] = MAX_WEIGHT; + weights[goals[i]] = MAX_WEIGHT; + } + // Reset weight of start terminal of target line (bug avoiding) + // Restore original settings in (*) + weights[starts[target]] = 1; + + // (Step.2-3) Routing + s_idx[target] = pointer; + pointer = search(s_idx[target], paths, starts[target], goals[target], weights); + + // (*) + weights[starts[target]] = MAX_WEIGHT; + +#ifdef DEBUG_PRINT + bool ng = false; + for (ap_uint i = 0; i < (ap_uint)(line_num); i++) { + if (weights[starts[i]] != 255 || weights[goals[i]] != 255) { + cout << i << " "; ng = true; + } + } + if(ng) { cout << endl; } +#endif + + // (Step.2-4) Overlap check + has_overlap = false; + OVERLAP_RESET: + for (ap_uint i = 0; i < (ap_uint)(MAX_CELLS); i++) { + overlap_checks[i] = 0; + } + OVERLAP_CHECK_LINE: + for (ap_uint i = 0; i < (ap_uint)(line_num); i++) { +#pragma HLS LOOP_TRIPCOUNT min=2 max=999 + overlap_checks[starts[i]] = 1; + overlap_checks[goals[i]] = 1; + } + OVERLAP_CHECK_PATH: + for (ap_uint j = s_idx[next_target]; j != pointer; j++) { +#pragma HLS LOOP_TRIPCOUNT min=1 max=8192 + ap_uint cell_id = paths[j]; + if (overlap_checks[cell_id]) { + has_overlap = true; break; + } + overlap_checks[cell_id] = 1; + } +#ifdef DEBUG_PRINT + if(!has_overlap){ cout << "ROUND: " << round << endl; } +#endif + if (!has_overlap) break; // Finish routing? + } + +#ifdef DEBUG_PRINT + cout << "MAX PQ LENGTH: " << max_queue_length << endl; + cout << "MAX SEARCH COUNT: " << max_search_count << endl; + cout << "MAX BUFFER: " << max_buffer_length << endl; +#endif + + // Not solved + if (has_overlap) { + *status = 1; return false; + } + + // ================================ + // (Step.2) Rip-up Routing (END) + // ================================ + + + // ================================ + // (Step.3) Output (BEGIN) + // ================================ + +#ifdef DEBUG_PRINT + cout << "Output ..." << endl; +#endif + + // Init: Blank = 0 + OUTPUT_INIT: + for (ap_uint i = 0; i < (ap_uint)(MAX_CELLS); i++) { + boardstr[i] = 0; + boardstr_high[i] = 0; + } + // Line + OUTPUT_LINE: + for (ap_uint i = 0; i < (ap_uint)(line_num); i++) { +#pragma HLS LOOP_TRIPCOUNT min=2 max=999 + boardstr[starts[i]] = (i + 1); + boardstr[goals[i]] = (i + 1); + boardstr_high[starts[i]] = (i + 1) >> 8; + boardstr_high[goals[i]] = (i + 1) >> 8; + + ap_uint p1; // p1: s_idx of target + ap_uint p2; // p2: s_idx of next target + p1 = s_idx[i]; + if (i == (ap_uint)(line_num-1)) { + p2 = s_idx[0]; + } + else { + p2 = s_idx[i+1]; + } + if ((ap_uint)(p2 - p1) > 8192){ + p2 = pointer; + } + OUTPUT_LINE_PATH: + for (ap_uint j = p1; j != p2; j++) { +#pragma HLS LOOP_TRIPCOUNT min=1 max=256 + boardstr[paths[j]] = (i + 1); + boardstr_high[paths[j]] = (i + 1) >> 8; + } + } + + // ================================ + // (Step.3) Output (END) + // ================================ + + *status = 0; return true; +} + + +// ================================ // +// For Routing +// ================================ // + +// Max: 71, Min: 0 (7bit) +ap_uint<7> abs_uint7(ap_uint<7> a, ap_uint<7> b) { +#pragma HLS INLINE + if (a < b) { return b - a; } + else { return a - b; } +} +// Max: 7, Min: 0 (3bit) +ap_uint<3> abs_uint3(ap_uint<3> a, ap_uint<3> b) { +#pragma HLS INLINE + if (a < b) { return b - a; } + else { return a - b; } +} + +// Reference codes: +// http://lethe2211.hatenablog.com/entry/2014/12/30/011030 +// http://www.redblobgames.com/pathfinding/a-star/implementation.html +// Need to modify "array partition factor" +ap_uint search(ap_uint idx, ap_uint paths[MAX_BUFFER], ap_uint start, ap_uint goal, ap_uint<8> w[MAX_CELLS]) { + + ap_uint dist[MAX_CELLS]; + ap_uint prev[MAX_CELLS]; + + SEARCH_INIT_DIST: + for (ap_uint i = 0; i < (ap_uint)(MAX_CELLS); i++) { + dist[i] = 65535; // = (2^16 - 1) + } + + // Priority queue (Heap) + ap_uint pq_len = 0; + bool is_empty = true; + ap_uint<32> pq_nodes[MAX_PQ]; + +#ifdef DEBUG_PRINT + int queue_length = 0; + int search_count = 0; +#endif + + // Point of goal terminal + 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_y = (ap_uint<7>)(goal_xy - goal_x * MAX_WIDTH); + ap_uint<3> goal_z = (ap_uint<3>)(goal & BITMASK_Z); + + dist[start] = 0; + pq_push(pq_nodes, 0, start, &pq_len, &is_empty); // push start terminal + + SEARCH_PQ: + while (!is_empty) { +#pragma HLS LOOP_TRIPCOUNT min=1 max=1000 +#pragma HLS LOOP_FLATTEN off + + ap_uint<16> prev_cost; + ap_uint<16> src; // target cell + pq_pop(pq_nodes, &prev_cost, &src, &pq_len, &is_empty); +#ifdef DEBUG_PRINT + search_count++; +#endif + + + // End routing + if (src == goal) break; + + + // Target cell + ap_uint<16> dist_src = dist[src]; + ap_uint<8> cost = w[src]; + // Point of target cell + 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_y = (ap_uint<7>)(src_xy - src_x * MAX_WIDTH); + ap_uint<3> src_z = (ap_uint<3>)(src & BITMASK_Z); + + // Search adjacent cells + SEARCH_ADJACENTS: + for (ap_uint<3> a = 0; a < 6; a++) { + ap_int<8> dest_x = (ap_int<8>)src_x; // Min: -1, Max: 72 (Signed 8bit) + ap_int<8> dest_y = (ap_int<8>)src_y; // Min: -1, Max: 72 (Signed 8bit) + ap_int<5> dest_z = (ap_int<5>)src_z; // Min: -1, Max: 8 (Signed 5bit) + if (a == 0) { dest_x -= 1; } + if (a == 1) { dest_x += 1; } + if (a == 2) { dest_y -= 1; } + if (a == 3) { dest_y += 1; } + if (a == 4) { dest_z -= 1; } + if (a == 5) { dest_z += 1; } + + // Inside the board ? // + if (0 <= dest_x && dest_x < (ap_int<8>)size_x && 0 <= dest_y && dest_y < (ap_int<8>)size_y && 0 <= dest_z && dest_z < (ap_int<5>)size_z) { + // Adjacent cell + ap_uint<16> dest = (((ap_uint<16>)dest_x * MAX_WIDTH + (ap_uint<16>)dest_y) << BITWIDTH_Z) | (ap_uint<16>)dest_z; + ap_uint<16> dist_new = dist_src + cost; + + if (dist[dest] > dist_new) { + dist[dest] = dist_new; // Update dist + prev[dest] = src; // Recode previous cell + dist_new += abs_uint7(dest_x, goal_x) + abs_uint7(dest_y, goal_y) + abs_uint3(dest_z, goal_z); // A* heuristic + pq_push(pq_nodes, dist_new, dest, &pq_len, &is_empty); // push adjacent cell + } + } + } +#ifdef DEBUG_PRINT + if (queue_length < pq_len) { queue_length = pq_len; } +#endif + } + + // Output target path + // Note: Do not include start & goal terminals + ap_uint<16> t = prev[goal]; + + // Backtracking + ap_uint p = idx; // buffer-idx + SEARCH_BACKTRACK: + while (t != start) { +#pragma HLS LOOP_TRIPCOUNT min=1 max=256 + paths[p] = t; + p++; + t = prev[t]; + } + +#ifdef DEBUG_PRINT + if (max_queue_length < queue_length) { max_queue_length = queue_length; } + if (max_search_count < search_count) { max_search_count = search_count; } +#endif + + return p; +} + +// Queue push (Enqueue) +// Need to modify "trip count" (1) +void pq_push(ap_uint<32> pq_nodes[MAX_PQ], ap_uint<16> priority, ap_uint<16> data, ap_uint *pq_len, bool *is_empty) { +#pragma HLS INLINE + + (*pq_len)++; + if ((*pq_len) == 0) { (*pq_len)--; } // Queue is full -> Last element is automatically removed + + // Binary search for circular list + ap_uint i = (*pq_len); + ap_uint p = (*pq_len) >> 1; // parent node + PQ_PUSH_LOOP: + while (i > 1 && (ap_uint<16>)(pq_nodes[p] & PQ_PRIORITY_MASK) >= priority) { +#pragma HLS LOOP_TRIPCOUNT min=0 max=15 +/** Set!: min=0 max=PQ_BIT **/ + pq_nodes[i] = pq_nodes[p]; + i = p; + p = p >> 1; // parent node + } + pq_nodes[i] = ((ap_uint<32>)data << PQ_PRIORITY_WIDTH) | (ap_uint<32>)priority; + *is_empty = false; +} + +// Queue pop (Dequeue) +// Need to modify "trip count" (1) +void pq_pop(ap_uint<32> pq_nodes[MAX_PQ], ap_uint<16> *ret_priority, ap_uint<16> *ret_data, ap_uint *pq_len, bool *is_empty) { +#pragma HLS INLINE + + *ret_priority = (ap_uint<16>)(pq_nodes[1] & PQ_PRIORITY_MASK); + *ret_data = (ap_uint<16>)(pq_nodes[1] >> PQ_PRIORITY_WIDTH); + + ap_uint i = 1; // root node + ap_uint last_priority = (ap_uint<16>)(pq_nodes[*pq_len] & PQ_PRIORITY_MASK); // Priority of last element + + PQ_POP_LOOP: + while (!(i >> (PQ_BIT-1))) { // (2018.08.24) Loop condition fixed +#pragma HLS LOOP_TRIPCOUNT min=1 max=15 +/** Set!: min=0 max=PQ_BIT **/ + ap_uint c1 = i << 1; // child node(left) + ap_uint c2 = c1 + 1; // child node(right) + 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)) { + pq_nodes[i] = pq_nodes[c2]; + i = c2; + } + else { + pq_nodes[i] = pq_nodes[c1]; + i = c1; + } + } + else { + if (c2 < *pq_len && (ap_uint<16>)(pq_nodes[c2] & PQ_PRIORITY_MASK) <= last_priority) { + pq_nodes[i] = pq_nodes[c2]; + i = c2; + } + else { + break; + } + } + } + pq_nodes[i] = pq_nodes[*pq_len]; + (*pq_len)--; + if ((*pq_len) == 0) { *is_empty = true; } +} + diff --git a/hls_2018/router_03_boardstr/router.hpp b/hls_2018/router_03_boardstr/router.hpp new file mode 100755 index 0000000..cdc6ef0 --- /dev/null +++ b/hls_2018/router_03_boardstr/router.hpp @@ -0,0 +1,56 @@ +/** + * router.hpp + * + * for Vivado HLS + */ + +#ifndef __ROUTER_HPP__ +#define __ROUTER_HPP__ + +#ifdef SOFTWARE +#include "ap_int.h" +#else +#include +#endif + +//#define DEBUG_PRINT // for debug + +#ifdef DEBUG_PRINT +using namespace std; +#endif + +// Parameters +#define MAX_WIDTH 72 // Max of X, Y +#define BITWIDTH_XY 13 +#define BITMASK_XY 65528 // 1111 1111 1111 1000 +#define MAX_LAYER 8 // Max of Z +#define BITWIDTH_Z 3 +#define BITMASK_Z 7 // 0000 0000 0000 0111 + +#define MAX_CELLS 41472 // Max #cells (16bit) +#define MAX_LINES 1024 // Max #lines (10bit) +#define MAX_PQ 32768 // Queue size (15bit) +#define MAX_BUFFER 16384 // Line buffer size (14bit) +#define CELL_BIT 16 +#define LINE_BIT 10 +#define PQ_BIT 15 +#define BUFF_BIT 14 + +#define PQ_PRIORITY_WIDTH 16 +#define PQ_PRIORITY_MASK 65535 // 0000 0000 0000 0000 1111 1111 1111 1111 +#define PQ_DATA_WIDTH 16 +#define PQ_DATA_MASK 4294901760 // 1111 1111 1111 1111 0000 0000 0000 0000 + +#define MAX_WEIGHT 255 // Max weight +#define BOARDSTR_SIZE 41472 // Size of I/O + +ap_uint<8> new_weight(ap_uint<16> x); +bool pynqrouter(char boardstr[BOARDSTR_SIZE], char boardstr_high[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *status); + +ap_uint<7> abs_uint7(ap_uint<7> a, ap_uint<7> b); +ap_uint<3> abs_uint3(ap_uint<3> a, ap_uint<3> b); +ap_uint search(ap_uint idx, ap_uint paths[MAX_BUFFER], ap_uint start, ap_uint goal, ap_uint<8> w[MAX_WEIGHT]); +void pq_push(ap_uint<32> pq_nodes[MAX_PQ], ap_uint<16> priority, ap_uint<16> data, ap_uint *pq_len, bool *is_empty); +void pq_pop(ap_uint<32> pq_nodes[MAX_PQ], ap_uint<16> *ret_priority, ap_uint<16> *ret_data, ap_uint *pq_len, bool *is_empty); + +#endif /* __ROUTER_HPP__ */ -- 2.22.0 From b285fa2a2dece20eabc74430fef3fbe7a93c5930 Mon Sep 17 00:00:00 2001 From: KazushiKawamura Date: Sun, 26 Aug 2018 12:31:42 +0900 Subject: [PATCH 20/30] Add a bitstream file --- .../bitstream/pynqrouter_AXI4LS_s_axi.v | 654 ++++++++++ .../bitstream/router_design.bit | Bin 0 -> 4045681 bytes .../bitstream/router_design.tcl | 1113 +++++++++++++++++ 3 files changed, 1767 insertions(+) create mode 100755 hls_2018/router_03_boardstr/bitstream/pynqrouter_AXI4LS_s_axi.v create mode 100755 hls_2018/router_03_boardstr/bitstream/router_design.bit create mode 100755 hls_2018/router_03_boardstr/bitstream/router_design.tcl diff --git a/hls_2018/router_03_boardstr/bitstream/pynqrouter_AXI4LS_s_axi.v b/hls_2018/router_03_boardstr/bitstream/pynqrouter_AXI4LS_s_axi.v new file mode 100755 index 0000000..adfcc74 --- /dev/null +++ b/hls_2018/router_03_boardstr/bitstream/pynqrouter_AXI4LS_s_axi.v @@ -0,0 +1,654 @@ +// ============================================================== +// File generated by Vivado(TM) HLS - High-Level Synthesis from C, C++ and SystemC +// Version: 2018.2 +// Copyright (C) 1986-2018 Xilinx, Inc. All Rights Reserved. +// +// ============================================================== + +`timescale 1ns/1ps +module pynqrouter_AXI4LS_s_axi +#(parameter + C_S_AXI_ADDR_WIDTH = 18, + C_S_AXI_DATA_WIDTH = 32 +)( + // axi4 lite slave signals + input wire ACLK, + input wire ARESET, + input wire ACLK_EN, + input wire [C_S_AXI_ADDR_WIDTH-1:0] AWADDR, + input wire AWVALID, + output wire AWREADY, + input wire [C_S_AXI_DATA_WIDTH-1:0] WDATA, + input wire [C_S_AXI_DATA_WIDTH/8-1:0] WSTRB, + input wire WVALID, + output wire WREADY, + output wire [1:0] BRESP, + output wire BVALID, + input wire BREADY, + input wire [C_S_AXI_ADDR_WIDTH-1:0] ARADDR, + input wire ARVALID, + output wire ARREADY, + output wire [C_S_AXI_DATA_WIDTH-1:0] RDATA, + output wire [1:0] RRESP, + output wire RVALID, + input wire RREADY, + output wire interrupt, + // user signals + output wire ap_start, + input wire ap_done, + input wire ap_ready, + input wire ap_idle, + input wire [0:0] ap_return, + input wire [15:0] boardstr_address0, + input wire boardstr_ce0, + input wire boardstr_we0, + input wire [7:0] boardstr_d0, + output wire [7:0] boardstr_q0, + input wire [15:0] boardstr_high_address0, + input wire boardstr_high_ce0, + input wire boardstr_high_we0, + input wire [7:0] boardstr_high_d0, + output wire [31:0] seed_V, + input wire [31:0] status_V, + input wire status_V_ap_vld +); +//------------------------Address Info------------------- +// 0x00000 : Control signals +// bit 0 - ap_start (Read/Write/COH) +// bit 1 - ap_done (Read/COR) +// bit 2 - ap_idle (Read) +// bit 3 - ap_ready (Read) +// bit 7 - auto_restart (Read/Write) +// others - reserved +// 0x00004 : Global Interrupt Enable Register +// bit 0 - Global Interrupt Enable (Read/Write) +// others - reserved +// 0x00008 : IP Interrupt Enable Register (Read/Write) +// bit 0 - Channel 0 (ap_done) +// bit 1 - Channel 1 (ap_ready) +// others - reserved +// 0x0000c : IP Interrupt Status Register (Read/TOW) +// bit 0 - Channel 0 (ap_done) +// bit 1 - Channel 1 (ap_ready) +// others - reserved +// 0x00010 : Data signal of ap_return +// bit 0 - ap_return[0] (Read) +// others - reserved +// 0x30000 : Data signal of seed_V +// bit 31~0 - seed_V[31:0] (Read/Write) +// 0x30004 : reserved +// 0x30008 : Data signal of status_V +// bit 31~0 - status_V[31:0] (Read) +// 0x3000c : Control signal of status_V +// bit 0 - status_V_ap_vld (Read/COR) +// others - reserved +// 0x10000 ~ +// 0x1ffff : Memory 'boardstr' (41472 * 8b) +// Word n : bit [ 7: 0] - boardstr[4n] +// bit [15: 8] - boardstr[4n+1] +// bit [23:16] - boardstr[4n+2] +// bit [31:24] - boardstr[4n+3] +// 0x20000 ~ +// 0x2ffff : Memory 'boardstr_high' (41472 * 8b) +// Word n : bit [ 7: 0] - boardstr_high[4n] +// bit [15: 8] - boardstr_high[4n+1] +// bit [23:16] - boardstr_high[4n+2] +// bit [31:24] - boardstr_high[4n+3] +// (SC = Self Clear, COR = Clear on Read, TOW = Toggle on Write, COH = Clear on Handshake) + +//------------------------Parameter---------------------- +localparam + ADDR_AP_CTRL = 18'h00000, + ADDR_GIE = 18'h00004, + ADDR_IER = 18'h00008, + ADDR_ISR = 18'h0000c, + ADDR_AP_RETURN_0 = 18'h00010, + ADDR_SEED_V_DATA_0 = 18'h30000, + ADDR_SEED_V_CTRL = 18'h30004, + ADDR_STATUS_V_DATA_0 = 18'h30008, + ADDR_STATUS_V_CTRL = 18'h3000c, + ADDR_BOARDSTR_BASE = 18'h10000, + ADDR_BOARDSTR_HIGH = 18'h1ffff, + ADDR_BOARDSTR_HIGH_BASE = 18'h20000, + ADDR_BOARDSTR_HIGH_HIGH = 18'h2ffff, + WRIDLE = 2'd0, + WRDATA = 2'd1, + WRRESP = 2'd2, + WRRESET = 2'd3, + RDIDLE = 2'd0, + RDDATA = 2'd1, + RDRESET = 2'd2, + ADDR_BITS = 18; + +//------------------------Local signal------------------- + reg [1:0] wstate = WRRESET; + reg [1:0] wnext; + reg [ADDR_BITS-1:0] waddr; + wire [31:0] wmask; + wire aw_hs; + wire w_hs; + reg [1:0] rstate = RDRESET; + reg [1:0] rnext; + reg [31:0] rdata; + wire ar_hs; + wire [ADDR_BITS-1:0] raddr; + // internal registers + reg int_ap_idle; + reg int_ap_ready; + reg int_ap_done = 1'b0; + reg int_ap_start = 1'b0; + reg int_auto_restart = 1'b0; + reg int_gie = 1'b0; + reg [1:0] int_ier = 2'b0; + reg [1:0] int_isr = 2'b0; + reg [0:0] int_ap_return; + reg [31:0] int_seed_V = 'b0; + reg [31:0] int_status_V = 'b0; + reg int_status_V_ap_vld; + // memory signals + wire [13:0] int_boardstr_address0; + wire int_boardstr_ce0; + wire int_boardstr_we0; + wire [3:0] int_boardstr_be0; + wire [31:0] int_boardstr_d0; + wire [31:0] int_boardstr_q0; + wire [13:0] int_boardstr_address1; + wire int_boardstr_ce1; + wire int_boardstr_we1; + wire [3:0] int_boardstr_be1; + wire [31:0] int_boardstr_d1; + wire [31:0] int_boardstr_q1; + reg int_boardstr_read; + reg int_boardstr_write; + reg [1:0] int_boardstr_shift; + wire [13:0] int_boardstr_high_address0; + wire int_boardstr_high_ce0; + wire int_boardstr_high_we0; + wire [3:0] int_boardstr_high_be0; + wire [31:0] int_boardstr_high_d0; + wire [31:0] int_boardstr_high_q0; + wire [13:0] int_boardstr_high_address1; + wire int_boardstr_high_ce1; + wire int_boardstr_high_we1; + wire [3:0] int_boardstr_high_be1; + wire [31:0] int_boardstr_high_d1; + wire [31:0] int_boardstr_high_q1; + reg int_boardstr_high_read; + reg int_boardstr_high_write; + reg [1:0] int_boardstr_high_shift; + +//------------------------Instantiation------------------ +// int_boardstr +pynqrouter_AXI4LS_s_axi_ram #( + .BYTES ( 4 ), + .DEPTH ( 10368 ) +) int_boardstr ( + .clk0 ( ACLK ), + .address0 ( int_boardstr_address0 ), + .ce0 ( int_boardstr_ce0 ), + .we0 ( int_boardstr_we0 ), + .be0 ( int_boardstr_be0 ), + .d0 ( int_boardstr_d0 ), + .q0 ( int_boardstr_q0 ), + .clk1 ( ACLK ), + .address1 ( int_boardstr_address1 ), + .ce1 ( int_boardstr_ce1 ), + .we1 ( int_boardstr_we1 ), + .be1 ( int_boardstr_be1 ), + .d1 ( int_boardstr_d1 ), + .q1 ( int_boardstr_q1 ) +); +// int_boardstr_high +pynqrouter_AXI4LS_s_axi_ram #( + .BYTES ( 4 ), + .DEPTH ( 10368 ) +) int_boardstr_high ( + .clk0 ( ACLK ), + .address0 ( int_boardstr_high_address0 ), + .ce0 ( int_boardstr_high_ce0 ), + .we0 ( int_boardstr_high_we0 ), + .be0 ( int_boardstr_high_be0 ), + .d0 ( int_boardstr_high_d0 ), + .q0 ( int_boardstr_high_q0 ), + .clk1 ( ACLK ), + .address1 ( int_boardstr_high_address1 ), + .ce1 ( int_boardstr_high_ce1 ), + .we1 ( int_boardstr_high_we1 ), + .be1 ( int_boardstr_high_be1 ), + .d1 ( int_boardstr_high_d1 ), + .q1 ( int_boardstr_high_q1 ) +); + +//------------------------AXI write fsm------------------ +assign AWREADY = (wstate == WRIDLE); +assign WREADY = (wstate == WRDATA); +assign BRESP = 2'b00; // OKAY +assign BVALID = (wstate == WRRESP); +assign wmask = { {8{WSTRB[3]}}, {8{WSTRB[2]}}, {8{WSTRB[1]}}, {8{WSTRB[0]}} }; +assign aw_hs = AWVALID & AWREADY; +assign w_hs = WVALID & WREADY; + +// wstate +always @(posedge ACLK) begin + if (ARESET) + wstate <= WRRESET; + else if (ACLK_EN) + wstate <= wnext; +end + +// wnext +always @(*) begin + case (wstate) + WRIDLE: + if (AWVALID) + wnext = WRDATA; + else + wnext = WRIDLE; + WRDATA: + if (WVALID) + wnext = WRRESP; + else + wnext = WRDATA; + WRRESP: + if (BREADY) + wnext = WRIDLE; + else + wnext = WRRESP; + default: + wnext = WRIDLE; + endcase +end + +// waddr +always @(posedge ACLK) begin + if (ACLK_EN) begin + if (aw_hs) + waddr <= AWADDR[ADDR_BITS-1:0]; + end +end + +//------------------------AXI read fsm------------------- +assign ARREADY = (rstate == RDIDLE); +assign RDATA = rdata; +assign RRESP = 2'b00; // OKAY +assign RVALID = (rstate == RDDATA) & !int_boardstr_read & !int_boardstr_high_read; +assign ar_hs = ARVALID & ARREADY; +assign raddr = ARADDR[ADDR_BITS-1:0]; + +// rstate +always @(posedge ACLK) begin + if (ARESET) + rstate <= RDRESET; + else if (ACLK_EN) + rstate <= rnext; +end + +// rnext +always @(*) begin + case (rstate) + RDIDLE: + if (ARVALID) + rnext = RDDATA; + else + rnext = RDIDLE; + RDDATA: + if (RREADY & RVALID) + rnext = RDIDLE; + else + rnext = RDDATA; + default: + rnext = RDIDLE; + endcase +end + +// rdata +always @(posedge ACLK) begin + if (ACLK_EN) begin + if (ar_hs) begin + rdata <= 1'b0; + case (raddr) + ADDR_AP_CTRL: begin + rdata[0] <= int_ap_start; + rdata[1] <= int_ap_done; + rdata[2] <= int_ap_idle; + rdata[3] <= int_ap_ready; + rdata[7] <= int_auto_restart; + end + ADDR_GIE: begin + rdata <= int_gie; + end + ADDR_IER: begin + rdata <= int_ier; + end + ADDR_ISR: begin + rdata <= int_isr; + end + ADDR_AP_RETURN_0: begin + rdata <= int_ap_return[0:0]; + end + ADDR_SEED_V_DATA_0: begin + rdata <= int_seed_V[31:0]; + end + ADDR_STATUS_V_DATA_0: begin + rdata <= int_status_V[31:0]; + end + ADDR_STATUS_V_CTRL: begin + rdata[0] <= int_status_V_ap_vld; + end + endcase + end + else if (int_boardstr_read) begin + rdata <= int_boardstr_q1; + end + else if (int_boardstr_high_read) begin + rdata <= int_boardstr_high_q1; + end + end +end + + +//------------------------Register logic----------------- +assign interrupt = int_gie & (|int_isr); +assign ap_start = int_ap_start; +assign seed_V = int_seed_V; +// int_ap_start +always @(posedge ACLK) begin + if (ARESET) + int_ap_start <= 1'b0; + else if (ACLK_EN) begin + if (w_hs && waddr == ADDR_AP_CTRL && WSTRB[0] && WDATA[0]) + int_ap_start <= 1'b1; + else if (ap_ready) + int_ap_start <= int_auto_restart; // clear on handshake/auto restart + end +end + +// int_ap_done +always @(posedge ACLK) begin + if (ARESET) + int_ap_done <= 1'b0; + else if (ACLK_EN) begin + if (ap_done) + int_ap_done <= 1'b1; + else if (ar_hs && raddr == ADDR_AP_CTRL) + int_ap_done <= 1'b0; // clear on read + end +end + +// int_ap_idle +always @(posedge ACLK) begin + if (ARESET) + int_ap_idle <= 1'b0; + else if (ACLK_EN) begin + int_ap_idle <= ap_idle; + end +end + +// int_ap_ready +always @(posedge ACLK) begin + if (ARESET) + int_ap_ready <= 1'b0; + else if (ACLK_EN) begin + int_ap_ready <= ap_ready; + end +end + +// int_auto_restart +always @(posedge ACLK) begin + if (ARESET) + int_auto_restart <= 1'b0; + else if (ACLK_EN) begin + if (w_hs && waddr == ADDR_AP_CTRL && WSTRB[0]) + int_auto_restart <= WDATA[7]; + end +end + +// int_gie +always @(posedge ACLK) begin + if (ARESET) + int_gie <= 1'b0; + else if (ACLK_EN) begin + if (w_hs && waddr == ADDR_GIE && WSTRB[0]) + int_gie <= WDATA[0]; + end +end + +// int_ier +always @(posedge ACLK) begin + if (ARESET) + int_ier <= 1'b0; + else if (ACLK_EN) begin + if (w_hs && waddr == ADDR_IER && WSTRB[0]) + int_ier <= WDATA[1:0]; + end +end + +// int_isr[0] +always @(posedge ACLK) begin + if (ARESET) + int_isr[0] <= 1'b0; + else if (ACLK_EN) begin + if (int_ier[0] & ap_done) + int_isr[0] <= 1'b1; + else if (w_hs && waddr == ADDR_ISR && WSTRB[0]) + int_isr[0] <= int_isr[0] ^ WDATA[0]; // toggle on write + end +end + +// int_isr[1] +always @(posedge ACLK) begin + if (ARESET) + int_isr[1] <= 1'b0; + else if (ACLK_EN) begin + if (int_ier[1] & ap_ready) + int_isr[1] <= 1'b1; + else if (w_hs && waddr == ADDR_ISR && WSTRB[0]) + int_isr[1] <= int_isr[1] ^ WDATA[1]; // toggle on write + end +end + +// int_ap_return +always @(posedge ACLK) begin + if (ARESET) + int_ap_return <= 0; + else if (ACLK_EN) begin + if (ap_done) + int_ap_return <= ap_return; + end +end + +// int_seed_V[31:0] +always @(posedge ACLK) begin + if (ARESET) + int_seed_V[31:0] <= 0; + else if (ACLK_EN) begin + if (w_hs && waddr == ADDR_SEED_V_DATA_0) + int_seed_V[31:0] <= (WDATA[31:0] & wmask) | (int_seed_V[31:0] & ~wmask); + end +end + +// int_status_V +always @(posedge ACLK) begin + if (ARESET) + int_status_V <= 0; + else if (ACLK_EN) begin + if (status_V_ap_vld) + int_status_V <= status_V; + end +end + +// int_status_V_ap_vld +always @(posedge ACLK) begin + if (ARESET) + int_status_V_ap_vld <= 1'b0; + else if (ACLK_EN) begin + if (status_V_ap_vld) + int_status_V_ap_vld <= 1'b1; + else if (ar_hs && raddr == ADDR_STATUS_V_CTRL) + int_status_V_ap_vld <= 1'b0; // clear on read + end +end + + +//------------------------Memory logic------------------- +// boardstr +assign int_boardstr_address0 = boardstr_address0 >> 2; +assign int_boardstr_ce0 = boardstr_ce0; +assign int_boardstr_we0 = boardstr_we0; +assign int_boardstr_be0 = 1 << boardstr_address0[1:0]; +assign int_boardstr_d0 = {4{boardstr_d0}}; +assign boardstr_q0 = int_boardstr_q0 >> (int_boardstr_shift * 8); +assign int_boardstr_address1 = ar_hs? raddr[15:2] : waddr[15:2]; +assign int_boardstr_ce1 = ar_hs | (int_boardstr_write & WVALID); +assign int_boardstr_we1 = int_boardstr_write & WVALID; +assign int_boardstr_be1 = WSTRB; +assign int_boardstr_d1 = WDATA; +// boardstr_high +assign int_boardstr_high_address0 = boardstr_high_address0 >> 2; +assign int_boardstr_high_ce0 = boardstr_high_ce0; +assign int_boardstr_high_we0 = boardstr_high_we0; +assign int_boardstr_high_be0 = 1 << boardstr_high_address0[1:0]; +assign int_boardstr_high_d0 = {4{boardstr_high_d0}}; +assign int_boardstr_high_address1 = ar_hs? raddr[15:2] : waddr[15:2]; +assign int_boardstr_high_ce1 = ar_hs | (int_boardstr_high_write & WVALID); +assign int_boardstr_high_we1 = int_boardstr_high_write & WVALID; +assign int_boardstr_high_be1 = WSTRB; +assign int_boardstr_high_d1 = WDATA; +// int_boardstr_read +always @(posedge ACLK) begin + if (ARESET) + int_boardstr_read <= 1'b0; + else if (ACLK_EN) begin + if (ar_hs && raddr >= ADDR_BOARDSTR_BASE && raddr <= ADDR_BOARDSTR_HIGH) + int_boardstr_read <= 1'b1; + else + int_boardstr_read <= 1'b0; + end +end + +// int_boardstr_write +always @(posedge ACLK) begin + if (ARESET) + int_boardstr_write <= 1'b0; + else if (ACLK_EN) begin + if (aw_hs && AWADDR[ADDR_BITS-1:0] >= ADDR_BOARDSTR_BASE && AWADDR[ADDR_BITS-1:0] <= ADDR_BOARDSTR_HIGH) + int_boardstr_write <= 1'b1; + else if (WVALID) + int_boardstr_write <= 1'b0; + end +end + +// int_boardstr_shift +always @(posedge ACLK) begin + if (ACLK_EN) begin + if (boardstr_ce0) + int_boardstr_shift <= boardstr_address0[1:0]; + end +end + +// int_boardstr_high_read +always @(posedge ACLK) begin + if (ARESET) + int_boardstr_high_read <= 1'b0; + else if (ACLK_EN) begin + if (ar_hs && raddr >= ADDR_BOARDSTR_HIGH_BASE && raddr <= ADDR_BOARDSTR_HIGH_HIGH) + int_boardstr_high_read <= 1'b1; + else + int_boardstr_high_read <= 1'b0; + end +end + +// int_boardstr_high_write +always @(posedge ACLK) begin + if (ARESET) + int_boardstr_high_write <= 1'b0; + else if (ACLK_EN) begin + if (aw_hs && AWADDR[ADDR_BITS-1:0] >= ADDR_BOARDSTR_HIGH_BASE && AWADDR[ADDR_BITS-1:0] <= ADDR_BOARDSTR_HIGH_HIGH) + int_boardstr_high_write <= 1'b1; + else if (WVALID) + int_boardstr_high_write <= 1'b0; + end +end + +// int_boardstr_high_shift +always @(posedge ACLK) begin + if (ACLK_EN) begin + if (boardstr_high_ce0) + int_boardstr_high_shift <= boardstr_high_address0[1:0]; + end +end + + +endmodule + + +`timescale 1ns/1ps + +module pynqrouter_AXI4LS_s_axi_ram +#(parameter + BYTES = 4, + DEPTH = 256, + AWIDTH = log2(DEPTH) +) ( + input wire clk0, + input wire [AWIDTH-1:0] address0, + input wire ce0, + input wire we0, + input wire [BYTES-1:0] be0, + input wire [BYTES*8-1:0] d0, + output reg [BYTES*8-1:0] q0, + input wire clk1, + input wire [AWIDTH-1:0] address1, + input wire ce1, + input wire we1, + input wire [BYTES-1:0] be1, + input wire [BYTES*8-1:0] d1, + output reg [BYTES*8-1:0] q1 +); +//------------------------Local signal------------------- +reg [BYTES*8-1:0] mem[0:DEPTH-1]; +//------------------------Task and function-------------- +function integer log2; + input integer x; + integer n, m; +begin + n = 1; + m = 2; + while (m < x) begin + n = n + 1; + m = m * 2; + end + log2 = n; +end +endfunction +//------------------------Body--------------------------- +// read port 0 +always @(posedge clk0) begin + if (ce0) q0 <= mem[address0]; +end + +// read port 1 +always @(posedge clk1) begin + if (ce1) q1 <= mem[address1]; +end + +genvar i; +generate + for (i = 0; i < BYTES; i = i + 1) begin : gen_write + // write port 0 + always @(posedge clk0) begin + if (ce0 & we0 & be0[i]) begin + mem[address0][8*i+7:8*i] <= d0[8*i+7:8*i]; + end + end + // write port 1 + always @(posedge clk1) begin + if (ce1 & we1 & be1[i]) begin + mem[address1][8*i+7:8*i] <= d1[8*i+7:8*i]; + end + end + end +endgenerate + +endmodule + diff --git a/hls_2018/router_03_boardstr/bitstream/router_design.bit b/hls_2018/router_03_boardstr/bitstream/router_design.bit new file mode 100755 index 0000000000000000000000000000000000000000..38548854bbee9afbe307d91ebb5fe19c7d1d229d GIT binary patch literal 4045681 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�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 z1W14cNPq-LfCNZ@1W14cNPq-LfCNZ@1W14cNPq-LfCNZ@1W14cNPq-LfCNZ@1W14c zNPq-LfCNZ@1W14cNPq-LfCNZ@1W14cNPq-LfCNZ@1W14cNPq-LfCNZ@1W14cNPq-L zfCNZ@1W14cNPq-LfCNZ@1W14cNPq-LfCNZ@1W14cNPq-LfCNZ@1W14cNPq-LfCNZ@ z1W14cNPq-LfCNZ@1W14cNPq-LfCNZ@1W14cNPq-LfCNZ@1W14cNPq-LfCNZ@1W14c zNPq-LfCNZ@1W14cNPq-LfCNZ@1W14cNPq-LfCNZ@1W14cNPq-LfCNZ@1W14cNPq-L zfCNZ@1W14cNPq-LfCNZ@1W14cNPq-LfCNZ@1W14cNPq-LfCNZ@1W14cNPq-LfCNZ@ z1W14cNPq-LfCNZ@1W14cNPq-LfCNZ@1W14cNPq-LfCNZ@1W14cNPq-LfCNZ@1W14c zNPq-LfCNZ@1W14cNPq-LfCNZ@1W14cNPq-LfCNZ@1W14cNPq-LfCNZ@1W14cNPq-L zfCNZ@1W14cNPq-LfCNZ@1W14cNPq-LfCNZ@1W14cNPq-LfCNZ@1W14cNPq-LfCNZ@ z1W14cNPq-LfCNZ@1W14cNPq-LfCNZ@1W14cNPq-LfCNZ@1W14cNPq-LfCNZ@1W14c zNPq-LfCNZ@1W14cNPq-LfCNZ@1W14cNPq-LfCNZ@1W14cNPq-LfCNZ@1W14cNPq-L zfCNZ@1W14cNPq-LfCNZ@1W14cNPq-LfCNZ@1W14cNPq-LfCNZ@1W14cNPq-LfCNZ@ z1W14cNPq-LfCNZ@1W14cNPq-LfCNZ@1W14cNPq-LfCNZ@1W14cNPq-LfCNZ@1W14c zNPq-LfCNZ@1W14cNPq-LfCNZ@1W14cNPq-LfCNZ@1W14cNPq-LfCNZ@1W14cNPq-L zfCNZ@1W14cNPq-LfCNZ@1W14cNPq-LfCNZ@1W14cNPq-LfCNZ@1W14cNPq-LfCNZ@ z1W14cNPq-LfCNZ@1W14cNPq-LfCNZ@1W14cNPq-LfCNZ@1W14cNPq-LfCNZ@1W14c zNPq-LfCNZ@1W14cNPq-LfCNZ@1W14cNPq-LfCNZ@1W14cNPq-LfCNZ@1W14cNPq-L zfCNZ@1W14cNPq-LfCNZ@1W14cNPq-LfCNZ@1W14cNPq-LfCNZ@1W14cNPq-LfCNZ@ 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

{q?`0Aq& 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�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 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly@DV5xxh|LURA23sIAtA& ypZn16&VCGfqw(8l%Hh$vJ!`iyOI-VmeBI~U)~)|JZf|oxJ+;un4%mTz*nu~MD*;^q literal 0 HcmV?d00001 diff --git a/hls_2018/router_02/bitstream/04/router_design.tcl b/hls_2018/router_02/bitstream/04/router_design.tcl new file mode 100755 index 0000000..e5347df --- /dev/null +++ b/hls_2018/router_02/bitstream/04/router_design.tcl @@ -0,0 +1,1113 @@ + +################################################################ +# This is a generated script based on design: router_design +# +# Though there are limitations about the generated script, +# the main purpose of this utility is to make learning +# IP Integrator Tcl commands easier. +################################################################ + +namespace eval _tcl { +proc get_script_folder {} { + set script_path [file normalize [info script]] + set script_folder [file dirname $script_path] + return $script_folder +} +} +variable script_folder +set script_folder [_tcl::get_script_folder] + +################################################################ +# Check if script is running in correct Vivado version. +################################################################ +set scripts_vivado_version 2018.2 +set current_vivado_version [version -short] + +if { [string first $scripts_vivado_version $current_vivado_version] == -1 } { + puts "" + catch {common::send_msg_id "BD_TCL-109" "ERROR" "This script was generated using Vivado <$scripts_vivado_version> and is being run in <$current_vivado_version> of Vivado. Please run the script in Vivado <$scripts_vivado_version> then open the design in Vivado <$current_vivado_version>. Upgrade the design by running \"Tools => Report => Report IP Status...\", then run write_bd_tcl to create an updated script."} + + return 1 +} + +################################################################ +# START +################################################################ + +# To test this script, run the following commands from Vivado Tcl console: +# source router_design_script.tcl + +# If there is no project opened, this script will create a +# project, but make sure you do not have an existing project +# <./myproj/project_1.xpr> in the current working folder. + +set list_projs [get_projects -quiet] +if { $list_projs eq "" } { + create_project project_1 myproj -part xc7z020clg400-1 +} + + +# CHANGE DESIGN NAME HERE +variable design_name +set design_name router_design + +# If you do not already have an existing IP Integrator design open, +# you can create a design using the following command: +# create_bd_design $design_name + +# Creating design if needed +set errMsg "" +set nRet 0 + +set cur_design [current_bd_design -quiet] +set list_cells [get_bd_cells -quiet] + +if { ${design_name} eq "" } { + # USE CASES: + # 1) Design_name not set + + set errMsg "Please set the variable to a non-empty value." + set nRet 1 + +} elseif { ${cur_design} ne "" && ${list_cells} eq "" } { + # USE CASES: + # 2): Current design opened AND is empty AND names same. + # 3): Current design opened AND is empty AND names diff; design_name NOT in project. + # 4): Current design opened AND is empty AND names diff; design_name exists in project. + + if { $cur_design ne $design_name } { + common::send_msg_id "BD_TCL-001" "INFO" "Changing value of from <$design_name> to <$cur_design> since current design is empty." + set design_name [get_property NAME $cur_design] + } + common::send_msg_id "BD_TCL-002" "INFO" "Constructing design in IPI design <$cur_design>..." + +} elseif { ${cur_design} ne "" && $list_cells ne "" && $cur_design eq $design_name } { + # USE CASES: + # 5) Current design opened AND has components AND same names. + + set errMsg "Design <$design_name> already exists in your project, please set the variable to another value." + set nRet 1 +} elseif { [get_files -quiet ${design_name}.bd] ne "" } { + # USE CASES: + # 6) Current opened design, has components, but diff names, design_name exists in project. + # 7) No opened design, design_name exists in project. + + set errMsg "Design <$design_name> already exists in your project, please set the variable to another value." + set nRet 2 + +} else { + # USE CASES: + # 8) No opened design, design_name not in project. + # 9) Current opened design, has components, but diff names, design_name not in project. + + common::send_msg_id "BD_TCL-003" "INFO" "Currently there is no design <$design_name> in project, so creating one..." + + create_bd_design $design_name + + common::send_msg_id "BD_TCL-004" "INFO" "Making design <$design_name> as current_bd_design." + current_bd_design $design_name + +} + +common::send_msg_id "BD_TCL-005" "INFO" "Currently the variable is equal to \"$design_name\"." + +if { $nRet != 0 } { + catch {common::send_msg_id "BD_TCL-114" "ERROR" $errMsg} + return $nRet +} + +set bCheckIPsPassed 1 +################################################################## +# CHECK IPs +################################################################## +set bCheckIPs 1 +if { $bCheckIPs == 1 } { + set list_check_ips "\ +xilinx.com:ip:axi_gpio:2.0\ +xilinx.com:ip:processing_system7:5.5\ +xilinx.com:hls:pynqrouter:1.0\ +xilinx.com:ip:proc_sys_reset:5.0\ +" + + set list_ips_missing "" + common::send_msg_id "BD_TCL-006" "INFO" "Checking if the following IPs exist in the project's IP catalog: $list_check_ips ." + + foreach ip_vlnv $list_check_ips { + set ip_obj [get_ipdefs -all $ip_vlnv] + if { $ip_obj eq "" } { + lappend list_ips_missing $ip_vlnv + } + } + + if { $list_ips_missing ne "" } { + catch {common::send_msg_id "BD_TCL-115" "ERROR" "The following IPs are not found in the IP Catalog:\n $list_ips_missing\n\nResolution: Please add the repository containing the IP(s) to the project." } + set bCheckIPsPassed 0 + } + +} + +if { $bCheckIPsPassed != 1 } { + common::send_msg_id "BD_TCL-1003" "WARNING" "Will not continue with creation of design due to the error(s) above." + return 3 +} + +################################################################## +# DESIGN PROCs +################################################################## + + + +# Procedure to create entire design; Provide argument to make +# procedure reusable. If parentCell is "", will use root. +proc create_root_design { parentCell } { + + variable script_folder + variable design_name + + if { $parentCell eq "" } { + set parentCell [get_bd_cells /] + } + + # Get object for parentCell + set parentObj [get_bd_cells $parentCell] + if { $parentObj == "" } { + catch {common::send_msg_id "BD_TCL-100" "ERROR" "Unable to find parent cell <$parentCell>!"} + return + } + + # Make sure parentObj is hier blk + set parentType [get_property TYPE $parentObj] + if { $parentType ne "hier" } { + catch {common::send_msg_id "BD_TCL-101" "ERROR" "Parent <$parentObj> has TYPE = <$parentType>. Expected to be ."} + return + } + + # Save current instance; Restore later + set oldCurInst [current_bd_instance .] + + # Set parent object as current + current_bd_instance $parentObj + + + # Create interface ports + set DDR [ create_bd_intf_port -mode Master -vlnv xilinx.com:interface:ddrx_rtl:1.0 DDR ] + set FIXED_IO [ create_bd_intf_port -mode Master -vlnv xilinx.com:display_processing_system7:fixedio_rtl:1.0 FIXED_IO ] + + # Create ports + set LD [ create_bd_port -dir O -from 3 -to 0 LD ] + + # Create instance: axi_gpio_0, and set properties + set axi_gpio_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:axi_gpio:2.0 axi_gpio_0 ] + set_property -dict [ list \ + CONFIG.C_GPIO_WIDTH {4} \ + ] $axi_gpio_0 + + # Create instance: processing_system7_0, and set properties + set processing_system7_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:processing_system7:5.5 processing_system7_0 ] + set_property -dict [ list \ + CONFIG.PCW_ACT_APU_PERIPHERAL_FREQMHZ {650.000000} \ + CONFIG.PCW_ACT_CAN0_PERIPHERAL_FREQMHZ {23.8095} \ + CONFIG.PCW_ACT_CAN1_PERIPHERAL_FREQMHZ {23.8095} \ + CONFIG.PCW_ACT_CAN_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_DCI_PERIPHERAL_FREQMHZ {10.096154} \ + CONFIG.PCW_ACT_ENET0_PERIPHERAL_FREQMHZ {125.000000} \ + CONFIG.PCW_ACT_ENET1_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_FPGA0_PERIPHERAL_FREQMHZ {100.000000} \ + CONFIG.PCW_ACT_FPGA1_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_FPGA2_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_FPGA3_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_I2C_PERIPHERAL_FREQMHZ {50} \ + CONFIG.PCW_ACT_PCAP_PERIPHERAL_FREQMHZ {200.000000} \ + CONFIG.PCW_ACT_QSPI_PERIPHERAL_FREQMHZ {200.000000} \ + CONFIG.PCW_ACT_SDIO_PERIPHERAL_FREQMHZ {50.000000} \ + CONFIG.PCW_ACT_SMC_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_SPI_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_TPIU_PERIPHERAL_FREQMHZ {200.000000} \ + CONFIG.PCW_ACT_TTC0_CLK0_PERIPHERAL_FREQMHZ {108.333336} \ + CONFIG.PCW_ACT_TTC0_CLK1_PERIPHERAL_FREQMHZ {108.333336} \ + CONFIG.PCW_ACT_TTC0_CLK2_PERIPHERAL_FREQMHZ {108.333336} \ + CONFIG.PCW_ACT_TTC1_CLK0_PERIPHERAL_FREQMHZ {108.333336} \ + CONFIG.PCW_ACT_TTC1_CLK1_PERIPHERAL_FREQMHZ {108.333336} \ + CONFIG.PCW_ACT_TTC1_CLK2_PERIPHERAL_FREQMHZ {108.333336} \ + CONFIG.PCW_ACT_TTC_PERIPHERAL_FREQMHZ {50} \ + CONFIG.PCW_ACT_UART_PERIPHERAL_FREQMHZ {100.000000} \ + CONFIG.PCW_ACT_USB0_PERIPHERAL_FREQMHZ {60} \ + CONFIG.PCW_ACT_USB1_PERIPHERAL_FREQMHZ {60} \ + CONFIG.PCW_ACT_WDT_PERIPHERAL_FREQMHZ {108.333336} \ + CONFIG.PCW_APU_CLK_RATIO_ENABLE {6:2:1} \ + CONFIG.PCW_APU_PERIPHERAL_FREQMHZ {650} \ + CONFIG.PCW_ARMPLL_CTRL_FBDIV {26} \ + CONFIG.PCW_CAN0_BASEADDR {0xE0008000} \ + CONFIG.PCW_CAN0_CAN0_IO {} \ + CONFIG.PCW_CAN0_HIGHADDR {0xE0008FFF} \ + CONFIG.PCW_CAN0_PERIPHERAL_CLKSRC {External} \ + CONFIG.PCW_CAN0_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_CAN0_PERIPHERAL_FREQMHZ {-1} \ + CONFIG.PCW_CAN1_BASEADDR {0xE0009000} \ + CONFIG.PCW_CAN1_CAN1_IO {} \ + CONFIG.PCW_CAN1_HIGHADDR {0xE0009FFF} \ + CONFIG.PCW_CAN1_PERIPHERAL_CLKSRC {External} \ + CONFIG.PCW_CAN1_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_CAN1_PERIPHERAL_FREQMHZ {-1} \ + CONFIG.PCW_CAN_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_CAN_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_CAN_PERIPHERAL_DIVISOR1 {1} \ + CONFIG.PCW_CAN_PERIPHERAL_FREQMHZ {100} \ + CONFIG.PCW_CAN_PERIPHERAL_VALID {0} \ + CONFIG.PCW_CLK0_FREQ {100000000} \ + CONFIG.PCW_CLK1_FREQ {10000000} \ + CONFIG.PCW_CLK2_FREQ {10000000} \ + CONFIG.PCW_CLK3_FREQ {10000000} \ + CONFIG.PCW_CORE0_FIQ_INTR {0} \ + CONFIG.PCW_CORE0_IRQ_INTR {0} \ + CONFIG.PCW_CORE1_FIQ_INTR {0} \ + CONFIG.PCW_CORE1_IRQ_INTR {0} \ + CONFIG.PCW_CPU_CPU_6X4X_MAX_RANGE {667} \ + CONFIG.PCW_CPU_CPU_PLL_FREQMHZ {1300.000} \ + CONFIG.PCW_CPU_PERIPHERAL_CLKSRC {ARM PLL} \ + CONFIG.PCW_CPU_PERIPHERAL_DIVISOR0 {2} \ + CONFIG.PCW_CRYSTAL_PERIPHERAL_FREQMHZ {50} \ + CONFIG.PCW_DCI_PERIPHERAL_CLKSRC {DDR PLL} \ + CONFIG.PCW_DCI_PERIPHERAL_DIVISOR0 {52} \ + CONFIG.PCW_DCI_PERIPHERAL_DIVISOR1 {2} \ + CONFIG.PCW_DCI_PERIPHERAL_FREQMHZ {10.159} \ + CONFIG.PCW_DDRPLL_CTRL_FBDIV {21} \ + CONFIG.PCW_DDR_DDR_PLL_FREQMHZ {1050.000} \ + CONFIG.PCW_DDR_HPRLPR_QUEUE_PARTITION {HPR(0)/LPR(32)} \ + CONFIG.PCW_DDR_HPR_TO_CRITICAL_PRIORITY_LEVEL {15} \ + CONFIG.PCW_DDR_LPR_TO_CRITICAL_PRIORITY_LEVEL {2} \ + CONFIG.PCW_DDR_PERIPHERAL_CLKSRC {DDR PLL} \ + CONFIG.PCW_DDR_PERIPHERAL_DIVISOR0 {2} \ + CONFIG.PCW_DDR_PORT0_HPR_ENABLE {0} \ + CONFIG.PCW_DDR_PORT1_HPR_ENABLE {0} \ + CONFIG.PCW_DDR_PORT2_HPR_ENABLE {0} \ + CONFIG.PCW_DDR_PORT3_HPR_ENABLE {0} \ + CONFIG.PCW_DDR_PRIORITY_READPORT_0 {} \ + CONFIG.PCW_DDR_PRIORITY_READPORT_2 {} \ + CONFIG.PCW_DDR_PRIORITY_WRITEPORT_0 {} \ + CONFIG.PCW_DDR_PRIORITY_WRITEPORT_2 {} \ + CONFIG.PCW_DDR_RAM_BASEADDR {0x00100000} \ + CONFIG.PCW_DDR_RAM_HIGHADDR {0x1FFFFFFF} \ + CONFIG.PCW_DDR_WRITE_TO_CRITICAL_PRIORITY_LEVEL {2} \ + CONFIG.PCW_DM_WIDTH {4} \ + CONFIG.PCW_DQS_WIDTH {4} \ + CONFIG.PCW_DQ_WIDTH {32} \ + CONFIG.PCW_ENET0_BASEADDR {0xE000B000} \ + CONFIG.PCW_ENET0_ENET0_IO {MIO 16 .. 27} \ + CONFIG.PCW_ENET0_GRP_MDIO_ENABLE {1} \ + CONFIG.PCW_ENET0_GRP_MDIO_IO {MIO 52 .. 53} \ + CONFIG.PCW_ENET0_HIGHADDR {0xE000BFFF} \ + CONFIG.PCW_ENET0_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_ENET0_PERIPHERAL_DIVISOR0 {8} \ + CONFIG.PCW_ENET0_PERIPHERAL_DIVISOR1 {1} \ + CONFIG.PCW_ENET0_PERIPHERAL_ENABLE {1} \ + CONFIG.PCW_ENET0_PERIPHERAL_FREQMHZ {1000 Mbps} \ + CONFIG.PCW_ENET0_RESET_ENABLE {1} \ + CONFIG.PCW_ENET0_RESET_IO {MIO 9} \ + CONFIG.PCW_ENET1_BASEADDR {0xE000C000} \ + CONFIG.PCW_ENET1_ENET1_IO {} \ + CONFIG.PCW_ENET1_HIGHADDR {0xE000CFFF} \ + CONFIG.PCW_ENET1_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_ENET1_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_ENET1_PERIPHERAL_DIVISOR1 {1} \ + CONFIG.PCW_ENET1_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_ENET1_PERIPHERAL_FREQMHZ {1000 Mbps} \ + CONFIG.PCW_ENET1_RESET_ENABLE {0} \ + CONFIG.PCW_ENET1_RESET_IO {} \ + CONFIG.PCW_FTM_CTI_IN1 {} \ + CONFIG.PCW_FTM_CTI_IN3 {} \ + CONFIG.PCW_FTM_CTI_OUT1 {} \ + CONFIG.PCW_FTM_CTI_OUT3 {} \ + CONFIG.PCW_GPIO_EMIO_GPIO_WIDTH {64} \ + CONFIG.PCW_GPIO_HIGHADDR {0xE000AFFF} \ + CONFIG.PCW_GPIO_MIO_GPIO_ENABLE {1} \ + CONFIG.PCW_GPIO_MIO_GPIO_IO {MIO} \ + CONFIG.PCW_GPIO_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_I2C0_BASEADDR {0xE0004000} \ + CONFIG.PCW_I2C0_GRP_INT_ENABLE {0} \ + CONFIG.PCW_I2C0_GRP_INT_IO {} \ + CONFIG.PCW_I2C0_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_I2C0_RESET_ENABLE {0} \ + CONFIG.PCW_I2C0_RESET_IO {} \ + CONFIG.PCW_I2C1_HIGHADDR {0xE0005FFF} \ + CONFIG.PCW_I2C1_I2C1_IO {} \ + CONFIG.PCW_I2C_PERIPHERAL_FREQMHZ {25} \ + CONFIG.PCW_I2C_RESET_ENABLE {1} \ + CONFIG.PCW_I2C_RESET_POLARITY {Active Low} \ + CONFIG.PCW_I2C_RESET_SELECT {} \ + CONFIG.PCW_NAND_NAND_IO {} \ + CONFIG.PCW_NOR_GRP_CS0_ENABLE {0} \ + CONFIG.PCW_NOR_GRP_CS0_IO {} \ + CONFIG.PCW_NOR_GRP_SRAM_CS0_ENABLE {0} \ + CONFIG.PCW_NOR_GRP_SRAM_CS0_IO {} \ + CONFIG.PCW_NOR_GRP_SRAM_INT_ENABLE {0} \ + CONFIG.PCW_NOR_GRP_SRAM_INT_IO {} \ + CONFIG.PCW_NOR_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_NOR_SRAM_CS0_T_CEOE {1} \ + CONFIG.PCW_NOR_SRAM_CS0_T_PC {1} \ + CONFIG.PCW_NOR_SRAM_CS0_T_RC {11} \ + CONFIG.PCW_NOR_SRAM_CS0_T_TR {1} \ + CONFIG.PCW_NOR_SRAM_CS0_T_WC {11} \ + CONFIG.PCW_NOR_SRAM_CS0_T_WP {1} \ + CONFIG.PCW_NOR_SRAM_CS0_WE_TIME {0} \ + CONFIG.PCW_NOR_SRAM_CS1_T_CEOE {1} \ + CONFIG.PCW_NOR_SRAM_CS1_T_PC {1} \ + CONFIG.PCW_NOR_SRAM_CS1_T_RC {11} \ + CONFIG.PCW_NOR_SRAM_CS1_T_TR {1} \ + CONFIG.PCW_NOR_SRAM_CS1_T_WC {11} \ + CONFIG.PCW_NOR_SRAM_CS1_T_WP {1} \ + CONFIG.PCW_NOR_SRAM_CS1_WE_TIME {0} \ + CONFIG.PCW_OVERRIDE_BASIC_CLOCK {0} \ + CONFIG.PCW_P2F_CAN0_INTR {0} \ + CONFIG.PCW_P2F_CAN1_INTR {0} \ + CONFIG.PCW_P2F_CTI_INTR {0} \ + CONFIG.PCW_P2F_DMAC0_INTR {0} \ + CONFIG.PCW_P2F_DMAC1_INTR {0} \ + CONFIG.PCW_P2F_DMAC2_INTR {0} \ + CONFIG.PCW_P2F_DMAC3_INTR {0} \ + CONFIG.PCW_P2F_DMAC4_INTR {0} \ + CONFIG.PCW_P2F_DMAC5_INTR {0} \ + CONFIG.PCW_P2F_DMAC6_INTR {0} \ + CONFIG.PCW_P2F_DMAC7_INTR {0} \ + CONFIG.PCW_P2F_DMAC_ABORT_INTR {0} \ + CONFIG.PCW_P2F_ENET0_INTR {0} \ + CONFIG.PCW_P2F_ENET1_INTR {0} \ + CONFIG.PCW_P2F_GPIO_INTR {0} \ + CONFIG.PCW_P2F_I2C0_INTR {0} \ + CONFIG.PCW_P2F_I2C1_INTR {0} \ + CONFIG.PCW_P2F_QSPI_INTR {0} \ + CONFIG.PCW_P2F_SDIO0_INTR {0} \ + CONFIG.PCW_P2F_SDIO1_INTR {0} \ + CONFIG.PCW_P2F_SMC_INTR {0} \ + CONFIG.PCW_P2F_SPI0_INTR {0} \ + CONFIG.PCW_P2F_SPI1_INTR {0} \ + CONFIG.PCW_P2F_UART0_INTR {0} \ + CONFIG.PCW_P2F_UART1_INTR {0} \ + CONFIG.PCW_P2F_USB0_INTR {0} \ + CONFIG.PCW_P2F_USB1_INTR {0} \ + CONFIG.PCW_PACKAGE_DDR_BOARD_DELAY0 {0.223} \ + CONFIG.PCW_PACKAGE_DDR_BOARD_DELAY1 {0.212} \ + CONFIG.PCW_PACKAGE_DDR_BOARD_DELAY2 {0.085} \ + CONFIG.PCW_PACKAGE_DDR_BOARD_DELAY3 {0.092} \ + CONFIG.PCW_PACKAGE_DDR_DQS_TO_CLK_DELAY_0 {0.040} \ + CONFIG.PCW_PACKAGE_DDR_DQS_TO_CLK_DELAY_1 {0.058} \ + CONFIG.PCW_PACKAGE_DDR_DQS_TO_CLK_DELAY_2 {-0.009} \ + CONFIG.PCW_PACKAGE_DDR_DQS_TO_CLK_DELAY_3 {-0.033} \ + CONFIG.PCW_PACKAGE_NAME {clg400} \ + CONFIG.PCW_PCAP_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_PCAP_PERIPHERAL_DIVISOR0 {5} \ + CONFIG.PCW_PCAP_PERIPHERAL_FREQMHZ {200} \ + CONFIG.PCW_PERIPHERAL_BOARD_PRESET {None} \ + CONFIG.PCW_PJTAG_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_PJTAG_PJTAG_IO {} \ + CONFIG.PCW_QSPI_GRP_SINGLE_SS_ENABLE {1} \ + CONFIG.PCW_QSPI_GRP_SINGLE_SS_IO {MIO 1 .. 6} \ + CONFIG.PCW_QSPI_GRP_SS1_ENABLE {0} \ + CONFIG.PCW_QSPI_GRP_SS1_IO {} \ + CONFIG.PCW_SD0_GRP_WP_ENABLE {0} \ + CONFIG.PCW_SD0_GRP_WP_IO {} \ + CONFIG.PCW_SD1_GRP_POW_ENABLE {0} \ + CONFIG.PCW_SD1_GRP_POW_IO {} \ + CONFIG.PCW_SD1_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_SD1_SD1_IO {} \ + CONFIG.PCW_SPI0_GRP_SS1_ENABLE {0} \ + CONFIG.PCW_SPI0_GRP_SS1_IO {} \ + CONFIG.PCW_SPI0_HIGHADDR {0xE0006FFF} \ + CONFIG.PCW_SPI0_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_SPI0_SPI0_IO {} \ + CONFIG.PCW_SPI1_GRP_SS1_ENABLE {0} \ + CONFIG.PCW_SPI1_GRP_SS1_IO {} \ + CONFIG.PCW_SPI1_HIGHADDR {0xE0007FFF} \ + CONFIG.PCW_SPI1_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_SPI1_SPI1_IO {} \ + CONFIG.PCW_TRACE_GRP_2BIT_ENABLE {0} \ + CONFIG.PCW_TRACE_GRP_2BIT_IO {} \ + CONFIG.PCW_TRACE_GRP_4BIT_ENABLE {0} \ + CONFIG.PCW_TRACE_GRP_4BIT_IO {} \ + CONFIG.PCW_TRACE_INTERNAL_WIDTH {2} \ + CONFIG.PCW_TRACE_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_TRACE_PIPELINE_WIDTH {8} \ + CONFIG.PCW_TRACE_TRACE_IO {} \ + CONFIG.PCW_TTC1_BASEADDR {0xE0105000} \ + CONFIG.PCW_TTC1_CLK0_PERIPHERAL_CLKSRC {CPU_1X} \ + CONFIG.PCW_TTC1_CLK0_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_TTC1_CLK0_PERIPHERAL_FREQMHZ {133.333333} \ + CONFIG.PCW_TTC1_CLK1_PERIPHERAL_CLKSRC {CPU_1X} \ + CONFIG.PCW_TTC1_CLK1_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_TTC1_CLK1_PERIPHERAL_FREQMHZ {133.333333} \ + CONFIG.PCW_TTC1_CLK2_PERIPHERAL_CLKSRC {CPU_1X} \ + CONFIG.PCW_TTC1_CLK2_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_TTC1_CLK2_PERIPHERAL_FREQMHZ {133.333333} \ + CONFIG.PCW_TTC1_HIGHADDR {0xE0105fff} \ + CONFIG.PCW_TTC1_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_TTC1_TTC1_IO {} \ + CONFIG.PCW_UART0_HIGHADDR {0xE0000FFF} \ + CONFIG.PCW_UART0_PERIPHERAL_ENABLE {1} \ + CONFIG.PCW_UART0_UART0_IO {MIO 14 .. 15} \ + CONFIG.PCW_UART1_BASEADDR {0xE0001000} \ + CONFIG.PCW_UART1_BAUD_RATE {115200} \ + CONFIG.PCW_UART1_GRP_FULL_ENABLE {0} \ + CONFIG.PCW_UART1_GRP_FULL_IO {} \ + CONFIG.PCW_UART_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_UART_PERIPHERAL_DIVISOR0 {10} \ + CONFIG.PCW_UART_PERIPHERAL_FREQMHZ {100} \ + CONFIG.PCW_UART_PERIPHERAL_VALID {1} \ + CONFIG.PCW_UIPARAM_ACT_DDR_FREQ_MHZ {525.000000} \ + CONFIG.PCW_UIPARAM_DDR_ADV_ENABLE {0} \ + CONFIG.PCW_UIPARAM_DDR_AL {0} \ + CONFIG.PCW_UIPARAM_DDR_BANK_ADDR_COUNT {3} \ + CONFIG.PCW_UIPARAM_DDR_BL {8} \ + CONFIG.PCW_UIPARAM_DDR_BOARD_DELAY0 {0.223} \ + CONFIG.PCW_UIPARAM_DDR_BOARD_DELAY1 {0.212} \ + CONFIG.PCW_UIPARAM_DDR_BOARD_DELAY2 {0.085} \ + CONFIG.PCW_UIPARAM_DDR_BOARD_DELAY3 {0.092} \ + CONFIG.PCW_UIPARAM_DDR_BUS_WIDTH {16 Bit} \ + CONFIG.PCW_UIPARAM_DDR_CL {7} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_0_LENGTH_MM {25.8} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_0_PACKAGE_LENGTH {80.4535} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_0_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_1_LENGTH_MM {25.8} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_1_PACKAGE_LENGTH {80.4535} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_1_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_2_LENGTH_MM {0} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_2_PACKAGE_LENGTH {80.4535} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_2_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_3_LENGTH_MM {0} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_3_PACKAGE_LENGTH {80.4535} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_3_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_STOP_EN {0} \ + CONFIG.PCW_UIPARAM_DDR_COL_ADDR_COUNT {10} \ + CONFIG.PCW_UIPARAM_DDR_CWL {6} \ + CONFIG.PCW_UIPARAM_DDR_DEVICE_CAPACITY {4096 MBits} \ + CONFIG.PCW_UIPARAM_DDR_DQS_0_LENGTH_MM {15.6} \ + CONFIG.PCW_UIPARAM_DDR_DQS_0_PACKAGE_LENGTH {105.056} \ + CONFIG.PCW_UIPARAM_DDR_DQS_0_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_DQS_1_LENGTH_MM {18.8} \ + CONFIG.PCW_UIPARAM_DDR_DQS_1_PACKAGE_LENGTH {66.904} \ + CONFIG.PCW_UIPARAM_DDR_DQS_1_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_DQS_2_LENGTH_MM {0} \ + CONFIG.PCW_UIPARAM_DDR_DQS_2_PACKAGE_LENGTH {89.1715} \ + CONFIG.PCW_UIPARAM_DDR_DQS_2_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_DQS_3_LENGTH_MM {0} \ + CONFIG.PCW_UIPARAM_DDR_DQS_3_PACKAGE_LENGTH {113.63} \ + CONFIG.PCW_UIPARAM_DDR_DQS_3_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_DQS_TO_CLK_DELAY_0 {0.040} \ + CONFIG.PCW_UIPARAM_DDR_DQS_TO_CLK_DELAY_1 {0.058} \ + CONFIG.PCW_UIPARAM_DDR_DQS_TO_CLK_DELAY_2 {-0.009} \ + CONFIG.PCW_UIPARAM_DDR_DQS_TO_CLK_DELAY_3 {-0.033} \ + CONFIG.PCW_UIPARAM_DDR_DQ_0_LENGTH_MM {16.5} \ + CONFIG.PCW_UIPARAM_DDR_DQ_0_PACKAGE_LENGTH {98.503} \ + CONFIG.PCW_UIPARAM_DDR_DQ_0_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_DQ_1_LENGTH_MM {18} \ + CONFIG.PCW_UIPARAM_DDR_DQ_1_PACKAGE_LENGTH {68.5855} \ + CONFIG.PCW_UIPARAM_DDR_DQ_1_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_DQ_2_LENGTH_MM {0} \ + CONFIG.PCW_UIPARAM_DDR_DQ_2_PACKAGE_LENGTH {90.295} \ + CONFIG.PCW_UIPARAM_DDR_DQ_2_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_DQ_3_LENGTH_MM {0} \ + CONFIG.PCW_UIPARAM_DDR_DQ_3_PACKAGE_LENGTH {103.977} \ + CONFIG.PCW_UIPARAM_DDR_DQ_3_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_DRAM_WIDTH {16 Bits} \ + CONFIG.PCW_UIPARAM_DDR_ECC {Disabled} \ + CONFIG.PCW_UIPARAM_DDR_ENABLE {1} \ + CONFIG.PCW_UIPARAM_DDR_FREQ_MHZ {525} \ + CONFIG.PCW_UIPARAM_DDR_HIGH_TEMP {Normal (0-85)} \ + CONFIG.PCW_UIPARAM_DDR_MEMORY_TYPE {DDR 3} \ + CONFIG.PCW_UIPARAM_DDR_PARTNO {MT41J256M16 RE-125} \ + CONFIG.PCW_UIPARAM_DDR_ROW_ADDR_COUNT {15} \ + CONFIG.PCW_UIPARAM_DDR_SPEED_BIN {DDR3_1066F} \ + CONFIG.PCW_UIPARAM_DDR_TRAIN_DATA_EYE {1} \ + CONFIG.PCW_UIPARAM_DDR_TRAIN_READ_GATE {1} \ + CONFIG.PCW_UIPARAM_DDR_TRAIN_WRITE_LEVEL {1} \ + CONFIG.PCW_UIPARAM_DDR_T_FAW {40.0} \ + CONFIG.PCW_UIPARAM_DDR_T_RAS_MIN {35.0} \ + CONFIG.PCW_UIPARAM_DDR_T_RC {48.91} \ + CONFIG.PCW_UIPARAM_DDR_T_RCD {7} \ + CONFIG.PCW_UIPARAM_DDR_T_RP {7} \ + CONFIG.PCW_UIPARAM_DDR_USE_INTERNAL_VREF {0} \ + CONFIG.PCW_UIPARAM_GENERATE_SUMMARY {NA} \ + CONFIG.PCW_USB0_BASEADDR {0xE0102000} \ + CONFIG.PCW_USB0_HIGHADDR {0xE0102fff} \ + CONFIG.PCW_USB0_PERIPHERAL_ENABLE {1} \ + CONFIG.PCW_USB0_PERIPHERAL_FREQMHZ {60} \ + CONFIG.PCW_USB0_RESET_ENABLE {1} \ + CONFIG.PCW_USB0_RESET_IO {MIO 46} \ + CONFIG.PCW_USB0_USB0_IO {MIO 28 .. 39} \ + CONFIG.PCW_USB1_BASEADDR {0xE0103000} \ + CONFIG.PCW_USB1_HIGHADDR {0xE0103fff} \ + CONFIG.PCW_USB1_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_USB1_PERIPHERAL_FREQMHZ {60} \ + CONFIG.PCW_USB1_RESET_ENABLE {0} \ + CONFIG.PCW_USB1_RESET_IO {} \ + CONFIG.PCW_USB_RESET_ENABLE {1} \ + CONFIG.PCW_USB_RESET_POLARITY {Active Low} \ + CONFIG.PCW_USB_RESET_SELECT {Share reset pin} \ + CONFIG.PCW_USE_AXI_FABRIC_IDLE {0} \ + CONFIG.PCW_USE_AXI_NONSECURE {0} \ + CONFIG.PCW_USE_CORESIGHT {0} \ + CONFIG.PCW_USE_CROSS_TRIGGER {0} \ + CONFIG.PCW_USE_CR_FABRIC {1} \ + CONFIG.PCW_USE_DDR_BYPASS {0} \ + CONFIG.PCW_USE_DEBUG {0} \ + CONFIG.PCW_USE_DEFAULT_ACP_USER_VAL {0} \ + CONFIG.PCW_USE_DMA0 {0} \ + CONFIG.PCW_USE_DMA1 {0} \ + CONFIG.PCW_USE_DMA2 {0} \ + CONFIG.PCW_USE_DMA3 {0} \ + CONFIG.PCW_USE_EXPANDED_IOP {0} \ + CONFIG.PCW_USE_EXPANDED_PS_SLCR_REGISTERS {0} \ + CONFIG.PCW_USE_FABRIC_INTERRUPT {0} \ + CONFIG.PCW_USE_HIGH_OCM {0} \ + CONFIG.PCW_USE_M_AXI_GP0 {1} \ + CONFIG.PCW_USE_M_AXI_GP1 {0} \ + CONFIG.PCW_USE_PROC_EVENT_BUS {0} \ + CONFIG.PCW_USE_PS_SLCR_REGISTERS {0} \ + CONFIG.PCW_USE_S_AXI_ACP {0} \ + CONFIG.PCW_USE_S_AXI_GP0 {0} \ + CONFIG.PCW_USE_S_AXI_GP1 {0} \ + CONFIG.PCW_USE_S_AXI_HP0 {0} \ + CONFIG.PCW_USE_S_AXI_HP1 {0} \ + CONFIG.PCW_USE_S_AXI_HP2 {0} \ + CONFIG.PCW_USE_S_AXI_HP3 {0} \ + CONFIG.PCW_USE_TRACE {0} \ + CONFIG.PCW_USE_TRACE_DATA_EDGE_DETECTOR {0} \ + CONFIG.PCW_VALUE_SILVERSION {3} \ + CONFIG.PCW_WDT_PERIPHERAL_CLKSRC {CPU_1X} \ + CONFIG.PCW_WDT_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_WDT_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_WDT_PERIPHERAL_FREQMHZ {133.333333} \ + CONFIG.PCW_WDT_WDT_IO {} \ + CONFIG.PCW_CAN0_GRP_CLK_ENABLE {0} \ + CONFIG.PCW_CAN0_GRP_CLK_IO {} \ + CONFIG.PCW_CAN1_GRP_CLK_ENABLE {0} \ + CONFIG.PCW_CAN1_GRP_CLK_IO {} \ + CONFIG.PCW_DDR_PRIORITY_READPORT_1 {} \ + CONFIG.PCW_DDR_PRIORITY_READPORT_3 {} \ + CONFIG.PCW_DDR_PRIORITY_WRITEPORT_1 {} \ + CONFIG.PCW_DDR_PRIORITY_WRITEPORT_3 {} \ + CONFIG.PCW_ENET1_GRP_MDIO_ENABLE {0} \ + CONFIG.PCW_ENET1_GRP_MDIO_IO {} \ + CONFIG.PCW_ENET_RESET_ENABLE {1} \ + CONFIG.PCW_ENET_RESET_POLARITY {Active Low} \ + CONFIG.PCW_ENET_RESET_SELECT {Share reset pin} \ + CONFIG.PCW_EN_4K_TIMER {0} \ + CONFIG.PCW_EN_CAN0 {0} \ + CONFIG.PCW_EN_CAN1 {0} \ + CONFIG.PCW_EN_CLK0_PORT {1} \ + CONFIG.PCW_EN_CLK1_PORT {0} \ + CONFIG.PCW_EN_CLK2_PORT {0} \ + CONFIG.PCW_EN_CLK3_PORT {0} \ + CONFIG.PCW_EN_CLKTRIG0_PORT {0} \ + CONFIG.PCW_EN_CLKTRIG1_PORT {0} \ + CONFIG.PCW_EN_CLKTRIG2_PORT {0} \ + CONFIG.PCW_EN_CLKTRIG3_PORT {0} \ + CONFIG.PCW_EN_DDR {1} \ + CONFIG.PCW_EN_EMIO_CAN0 {0} \ + CONFIG.PCW_EN_EMIO_CAN1 {0} \ + CONFIG.PCW_EN_EMIO_CD_SDIO0 {0} \ + CONFIG.PCW_EN_EMIO_CD_SDIO1 {0} \ + CONFIG.PCW_EN_EMIO_ENET0 {0} \ + CONFIG.PCW_EN_EMIO_ENET1 {0} \ + CONFIG.PCW_EN_EMIO_GPIO {0} \ + CONFIG.PCW_EN_EMIO_I2C0 {0} \ + CONFIG.PCW_EN_EMIO_I2C1 {0} \ + CONFIG.PCW_EN_EMIO_MODEM_UART0 {0} \ + CONFIG.PCW_EN_EMIO_MODEM_UART1 {0} \ + CONFIG.PCW_EN_EMIO_PJTAG {0} \ + CONFIG.PCW_EN_EMIO_SDIO0 {0} \ + CONFIG.PCW_EN_EMIO_SDIO1 {0} \ + CONFIG.PCW_EN_EMIO_SPI0 {0} \ + CONFIG.PCW_EN_EMIO_SPI1 {0} \ + CONFIG.PCW_EN_EMIO_SRAM_INT {0} \ + CONFIG.PCW_EN_EMIO_TRACE {0} \ + CONFIG.PCW_EN_EMIO_TTC0 {0} \ + CONFIG.PCW_EN_EMIO_TTC1 {0} \ + CONFIG.PCW_EN_EMIO_UART0 {0} \ + CONFIG.PCW_EN_EMIO_UART1 {0} \ + CONFIG.PCW_EN_EMIO_WDT {0} \ + CONFIG.PCW_EN_EMIO_WP_SDIO0 {0} \ + CONFIG.PCW_EN_EMIO_WP_SDIO1 {0} \ + CONFIG.PCW_EN_ENET0 {1} \ + CONFIG.PCW_EN_ENET1 {0} \ + CONFIG.PCW_EN_GPIO {1} \ + CONFIG.PCW_EN_I2C0 {0} \ + CONFIG.PCW_EN_I2C1 {0} \ + CONFIG.PCW_EN_MODEM_UART0 {0} \ + CONFIG.PCW_EN_MODEM_UART1 {0} \ + CONFIG.PCW_EN_PJTAG {0} \ + CONFIG.PCW_EN_PTP_ENET0 {0} \ + CONFIG.PCW_EN_PTP_ENET1 {0} \ + CONFIG.PCW_EN_QSPI {1} \ + CONFIG.PCW_EN_RST0_PORT {1} \ + CONFIG.PCW_EN_RST1_PORT {0} \ + CONFIG.PCW_EN_RST2_PORT {0} \ + CONFIG.PCW_EN_RST3_PORT {0} \ + CONFIG.PCW_EN_SDIO0 {1} \ + CONFIG.PCW_EN_SDIO1 {0} \ + CONFIG.PCW_EN_SMC {0} \ + CONFIG.PCW_EN_SPI0 {0} \ + CONFIG.PCW_EN_SPI1 {0} \ + CONFIG.PCW_EN_TRACE {0} \ + CONFIG.PCW_EN_TTC0 {0} \ + CONFIG.PCW_EN_TTC1 {0} \ + CONFIG.PCW_EN_UART0 {1} \ + CONFIG.PCW_EN_UART1 {0} \ + CONFIG.PCW_EN_USB0 {1} \ + CONFIG.PCW_EN_USB1 {0} \ + CONFIG.PCW_EN_WDT {0} \ + CONFIG.PCW_FCLK0_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_FCLK0_PERIPHERAL_DIVISOR0 {5} \ + CONFIG.PCW_FCLK0_PERIPHERAL_DIVISOR1 {2} \ + CONFIG.PCW_FCLK1_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_FCLK1_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_FCLK1_PERIPHERAL_DIVISOR1 {1} \ + CONFIG.PCW_FCLK2_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_FCLK2_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_FCLK2_PERIPHERAL_DIVISOR1 {1} \ + CONFIG.PCW_FCLK3_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_FCLK3_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_FCLK3_PERIPHERAL_DIVISOR1 {1} \ + CONFIG.PCW_FCLK_CLK0_BUF {TRUE} \ + CONFIG.PCW_FCLK_CLK1_BUF {FALSE} \ + CONFIG.PCW_FCLK_CLK2_BUF {FALSE} \ + CONFIG.PCW_FCLK_CLK3_BUF {FALSE} \ + CONFIG.PCW_FPGA0_PERIPHERAL_FREQMHZ {100} \ + CONFIG.PCW_FPGA1_PERIPHERAL_FREQMHZ {50} \ + CONFIG.PCW_FPGA2_PERIPHERAL_FREQMHZ {50} \ + CONFIG.PCW_FPGA3_PERIPHERAL_FREQMHZ {50} \ + CONFIG.PCW_FPGA_FCLK0_ENABLE {1} \ + CONFIG.PCW_FPGA_FCLK1_ENABLE {0} \ + CONFIG.PCW_FPGA_FCLK2_ENABLE {0} \ + CONFIG.PCW_FPGA_FCLK3_ENABLE {0} \ + CONFIG.PCW_FTM_CTI_IN0 {} \ + CONFIG.PCW_FTM_CTI_IN2 {} \ + CONFIG.PCW_FTM_CTI_OUT0 {} \ + CONFIG.PCW_FTM_CTI_OUT2 {} \ + CONFIG.PCW_GPIO_BASEADDR {0xE000A000} \ + CONFIG.PCW_GPIO_EMIO_GPIO_ENABLE {0} \ + CONFIG.PCW_GPIO_EMIO_GPIO_IO {} \ + CONFIG.PCW_I2C0_HIGHADDR {0xE0004FFF} \ + CONFIG.PCW_I2C0_I2C0_IO {} \ + CONFIG.PCW_I2C1_BASEADDR {0xE0005000} \ + CONFIG.PCW_I2C1_GRP_INT_ENABLE {0} \ + CONFIG.PCW_I2C1_GRP_INT_IO {} \ + CONFIG.PCW_I2C1_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_I2C1_RESET_ENABLE {0} \ + CONFIG.PCW_I2C1_RESET_IO {} \ + CONFIG.PCW_IMPORT_BOARD_PRESET {None} \ + CONFIG.PCW_INCLUDE_ACP_TRANS_CHECK {0} \ + CONFIG.PCW_INCLUDE_TRACE_BUFFER {0} \ + CONFIG.PCW_IOPLL_CTRL_FBDIV {20} \ + CONFIG.PCW_IO_IO_PLL_FREQMHZ {1000.000} \ + CONFIG.PCW_IRQ_F2P_INTR {0} \ + CONFIG.PCW_IRQ_F2P_MODE {DIRECT} \ + CONFIG.PCW_MIO_0_DIRECTION {inout} \ + CONFIG.PCW_MIO_0_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_0_PULLUP {enabled} \ + CONFIG.PCW_MIO_0_SLEW {slow} \ + CONFIG.PCW_MIO_10_DIRECTION {inout} \ + CONFIG.PCW_MIO_10_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_10_PULLUP {enabled} \ + CONFIG.PCW_MIO_10_SLEW {slow} \ + CONFIG.PCW_MIO_11_DIRECTION {inout} \ + CONFIG.PCW_MIO_11_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_11_PULLUP {enabled} \ + CONFIG.PCW_MIO_11_SLEW {slow} \ + CONFIG.PCW_MIO_12_DIRECTION {inout} \ + CONFIG.PCW_MIO_12_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_12_PULLUP {enabled} \ + CONFIG.PCW_MIO_12_SLEW {slow} \ + CONFIG.PCW_MIO_13_DIRECTION {inout} \ + CONFIG.PCW_MIO_13_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_13_PULLUP {enabled} \ + CONFIG.PCW_MIO_13_SLEW {slow} \ + CONFIG.PCW_MIO_14_DIRECTION {in} \ + CONFIG.PCW_MIO_14_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_14_PULLUP {enabled} \ + CONFIG.PCW_MIO_14_SLEW {slow} \ + CONFIG.PCW_MIO_15_DIRECTION {out} \ + CONFIG.PCW_MIO_15_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_15_PULLUP {enabled} \ + CONFIG.PCW_MIO_15_SLEW {slow} \ + CONFIG.PCW_MIO_16_DIRECTION {out} \ + CONFIG.PCW_MIO_16_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_16_PULLUP {enabled} \ + CONFIG.PCW_MIO_16_SLEW {slow} \ + CONFIG.PCW_MIO_17_DIRECTION {out} \ + CONFIG.PCW_MIO_17_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_17_PULLUP {enabled} \ + CONFIG.PCW_MIO_17_SLEW {slow} \ + CONFIG.PCW_MIO_18_DIRECTION {out} \ + CONFIG.PCW_MIO_18_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_18_PULLUP {enabled} \ + CONFIG.PCW_MIO_18_SLEW {slow} \ + CONFIG.PCW_MIO_19_DIRECTION {out} \ + CONFIG.PCW_MIO_19_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_19_PULLUP {enabled} \ + CONFIG.PCW_MIO_19_SLEW {slow} \ + CONFIG.PCW_MIO_1_DIRECTION {out} \ + CONFIG.PCW_MIO_1_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_1_PULLUP {enabled} \ + CONFIG.PCW_MIO_1_SLEW {slow} \ + CONFIG.PCW_MIO_20_DIRECTION {out} \ + CONFIG.PCW_MIO_20_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_20_PULLUP {enabled} \ + CONFIG.PCW_MIO_20_SLEW {slow} \ + CONFIG.PCW_MIO_21_DIRECTION {out} \ + CONFIG.PCW_MIO_21_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_21_PULLUP {enabled} \ + CONFIG.PCW_MIO_21_SLEW {slow} \ + CONFIG.PCW_MIO_22_DIRECTION {in} \ + CONFIG.PCW_MIO_22_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_22_PULLUP {enabled} \ + CONFIG.PCW_MIO_22_SLEW {slow} \ + CONFIG.PCW_MIO_23_DIRECTION {in} \ + CONFIG.PCW_MIO_23_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_23_PULLUP {enabled} \ + CONFIG.PCW_MIO_23_SLEW {slow} \ + CONFIG.PCW_MIO_24_DIRECTION {in} \ + CONFIG.PCW_MIO_24_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_24_PULLUP {enabled} \ + CONFIG.PCW_MIO_24_SLEW {slow} \ + CONFIG.PCW_MIO_25_DIRECTION {in} \ + CONFIG.PCW_MIO_25_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_25_PULLUP {enabled} \ + CONFIG.PCW_MIO_25_SLEW {slow} \ + CONFIG.PCW_MIO_26_DIRECTION {in} \ + CONFIG.PCW_MIO_26_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_26_PULLUP {enabled} \ + CONFIG.PCW_MIO_26_SLEW {slow} \ + CONFIG.PCW_MIO_27_DIRECTION {in} \ + CONFIG.PCW_MIO_27_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_27_PULLUP {enabled} \ + CONFIG.PCW_MIO_27_SLEW {slow} \ + CONFIG.PCW_MIO_28_DIRECTION {inout} \ + CONFIG.PCW_MIO_28_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_28_PULLUP {enabled} \ + CONFIG.PCW_MIO_28_SLEW {slow} \ + CONFIG.PCW_MIO_29_DIRECTION {in} \ + CONFIG.PCW_MIO_29_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_29_PULLUP {enabled} \ + CONFIG.PCW_MIO_29_SLEW {slow} \ + CONFIG.PCW_MIO_2_DIRECTION {inout} \ + CONFIG.PCW_MIO_2_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_2_PULLUP {disabled} \ + CONFIG.PCW_MIO_2_SLEW {slow} \ + CONFIG.PCW_MIO_30_DIRECTION {out} \ + CONFIG.PCW_MIO_30_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_30_PULLUP {enabled} \ + CONFIG.PCW_MIO_30_SLEW {slow} \ + CONFIG.PCW_MIO_31_DIRECTION {in} \ + CONFIG.PCW_MIO_31_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_31_PULLUP {enabled} \ + CONFIG.PCW_MIO_31_SLEW {slow} \ + CONFIG.PCW_MIO_32_DIRECTION {inout} \ + CONFIG.PCW_MIO_32_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_32_PULLUP {enabled} \ + CONFIG.PCW_MIO_32_SLEW {slow} \ + CONFIG.PCW_MIO_33_DIRECTION {inout} \ + CONFIG.PCW_MIO_33_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_33_PULLUP {enabled} \ + CONFIG.PCW_MIO_33_SLEW {slow} \ + CONFIG.PCW_MIO_34_DIRECTION {inout} \ + CONFIG.PCW_MIO_34_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_34_PULLUP {enabled} \ + CONFIG.PCW_MIO_34_SLEW {slow} \ + CONFIG.PCW_MIO_35_DIRECTION {inout} \ + CONFIG.PCW_MIO_35_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_35_PULLUP {enabled} \ + CONFIG.PCW_MIO_35_SLEW {slow} \ + CONFIG.PCW_MIO_36_DIRECTION {in} \ + CONFIG.PCW_MIO_36_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_36_PULLUP {enabled} \ + CONFIG.PCW_MIO_36_SLEW {slow} \ + CONFIG.PCW_MIO_37_DIRECTION {inout} \ + CONFIG.PCW_MIO_37_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_37_PULLUP {enabled} \ + CONFIG.PCW_MIO_37_SLEW {slow} \ + CONFIG.PCW_MIO_38_DIRECTION {inout} \ + CONFIG.PCW_MIO_38_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_38_PULLUP {enabled} \ + CONFIG.PCW_MIO_38_SLEW {slow} \ + CONFIG.PCW_MIO_39_DIRECTION {inout} \ + CONFIG.PCW_MIO_39_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_39_PULLUP {enabled} \ + CONFIG.PCW_MIO_39_SLEW {slow} \ + CONFIG.PCW_MIO_3_DIRECTION {inout} \ + CONFIG.PCW_MIO_3_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_3_PULLUP {disabled} \ + CONFIG.PCW_MIO_3_SLEW {slow} \ + CONFIG.PCW_MIO_40_DIRECTION {inout} \ + CONFIG.PCW_MIO_40_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_40_PULLUP {enabled} \ + CONFIG.PCW_MIO_40_SLEW {slow} \ + CONFIG.PCW_MIO_41_DIRECTION {inout} \ + CONFIG.PCW_MIO_41_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_41_PULLUP {enabled} \ + CONFIG.PCW_MIO_41_SLEW {slow} \ + CONFIG.PCW_MIO_42_DIRECTION {inout} \ + CONFIG.PCW_MIO_42_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_42_PULLUP {enabled} \ + CONFIG.PCW_MIO_42_SLEW {slow} \ + CONFIG.PCW_MIO_43_DIRECTION {inout} \ + CONFIG.PCW_MIO_43_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_43_PULLUP {enabled} \ + CONFIG.PCW_MIO_43_SLEW {slow} \ + CONFIG.PCW_MIO_44_DIRECTION {inout} \ + CONFIG.PCW_MIO_44_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_44_PULLUP {enabled} \ + CONFIG.PCW_MIO_44_SLEW {slow} \ + CONFIG.PCW_MIO_45_DIRECTION {inout} \ + CONFIG.PCW_MIO_45_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_45_PULLUP {enabled} \ + CONFIG.PCW_MIO_45_SLEW {slow} \ + CONFIG.PCW_MIO_46_DIRECTION {out} \ + CONFIG.PCW_MIO_46_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_46_PULLUP {enabled} \ + CONFIG.PCW_MIO_46_SLEW {slow} \ + CONFIG.PCW_MIO_47_DIRECTION {in} \ + CONFIG.PCW_MIO_47_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_47_PULLUP {enabled} \ + CONFIG.PCW_MIO_47_SLEW {slow} \ + CONFIG.PCW_MIO_48_DIRECTION {inout} \ + CONFIG.PCW_MIO_48_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_48_PULLUP {enabled} \ + CONFIG.PCW_MIO_48_SLEW {slow} \ + CONFIG.PCW_MIO_49_DIRECTION {inout} \ + CONFIG.PCW_MIO_49_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_49_PULLUP {enabled} \ + CONFIG.PCW_MIO_49_SLEW {slow} \ + CONFIG.PCW_MIO_4_DIRECTION {inout} \ + CONFIG.PCW_MIO_4_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_4_PULLUP {disabled} \ + CONFIG.PCW_MIO_4_SLEW {slow} \ + CONFIG.PCW_MIO_50_DIRECTION {inout} \ + CONFIG.PCW_MIO_50_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_50_PULLUP {enabled} \ + CONFIG.PCW_MIO_50_SLEW {slow} \ + CONFIG.PCW_MIO_51_DIRECTION {inout} \ + CONFIG.PCW_MIO_51_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_51_PULLUP {enabled} \ + CONFIG.PCW_MIO_51_SLEW {slow} \ + CONFIG.PCW_MIO_52_DIRECTION {out} \ + CONFIG.PCW_MIO_52_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_52_PULLUP {enabled} \ + CONFIG.PCW_MIO_52_SLEW {slow} \ + CONFIG.PCW_MIO_53_DIRECTION {inout} \ + CONFIG.PCW_MIO_53_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_53_PULLUP {enabled} \ + CONFIG.PCW_MIO_53_SLEW {slow} \ + CONFIG.PCW_MIO_5_DIRECTION {inout} \ + CONFIG.PCW_MIO_5_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_5_PULLUP {disabled} \ + CONFIG.PCW_MIO_5_SLEW {slow} \ + CONFIG.PCW_MIO_6_DIRECTION {out} \ + CONFIG.PCW_MIO_6_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_6_PULLUP {disabled} \ + CONFIG.PCW_MIO_6_SLEW {slow} \ + CONFIG.PCW_MIO_7_DIRECTION {out} \ + CONFIG.PCW_MIO_7_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_7_PULLUP {disabled} \ + CONFIG.PCW_MIO_7_SLEW {slow} \ + CONFIG.PCW_MIO_8_DIRECTION {out} \ + CONFIG.PCW_MIO_8_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_8_PULLUP {disabled} \ + CONFIG.PCW_MIO_8_SLEW {slow} \ + CONFIG.PCW_MIO_9_DIRECTION {out} \ + CONFIG.PCW_MIO_9_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_9_PULLUP {enabled} \ + CONFIG.PCW_MIO_9_SLEW {slow} \ + CONFIG.PCW_MIO_PRIMITIVE {54} \ + CONFIG.PCW_MIO_TREE_PERIPHERALS {GPIO#Quad SPI Flash#Quad SPI Flash#Quad SPI Flash#Quad SPI Flash#Quad SPI Flash#Quad SPI Flash#GPIO#Quad SPI Flash#ENET Reset#GPIO#GPIO#GPIO#GPIO#UART 0#UART 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#SD 0#SD 0#SD 0#SD 0#SD 0#SD 0#USB Reset#SD 0#GPIO#GPIO#GPIO#GPIO#Enet 0#Enet 0} \ + CONFIG.PCW_MIO_TREE_SIGNALS {gpio[0]#qspi0_ss_b#qspi0_io[0]#qspi0_io[1]#qspi0_io[2]#qspi0_io[3]/HOLD_B#qspi0_sclk#gpio[7]#qspi_fbclk#reset#gpio[10]#gpio[11]#gpio[12]#gpio[13]#rx#tx#tx_clk#txd[0]#txd[1]#txd[2]#txd[3]#tx_ctl#rx_clk#rxd[0]#rxd[1]#rxd[2]#rxd[3]#rx_ctl#data[4]#dir#stp#nxt#data[0]#data[1]#data[2]#data[3]#clk#data[5]#data[6]#data[7]#clk#cmd#data[0]#data[1]#data[2]#data[3]#reset#cd#gpio[48]#gpio[49]#gpio[50]#gpio[51]#mdc#mdio} \ + CONFIG.PCW_M_AXI_GP0_ENABLE_STATIC_REMAP {0} \ + CONFIG.PCW_M_AXI_GP0_ID_WIDTH {12} \ + CONFIG.PCW_M_AXI_GP0_SUPPORT_NARROW_BURST {0} \ + CONFIG.PCW_M_AXI_GP0_THREAD_ID_WIDTH {12} \ + CONFIG.PCW_M_AXI_GP1_ENABLE_STATIC_REMAP {0} \ + CONFIG.PCW_M_AXI_GP1_ID_WIDTH {12} \ + CONFIG.PCW_M_AXI_GP1_SUPPORT_NARROW_BURST {0} \ + CONFIG.PCW_M_AXI_GP1_THREAD_ID_WIDTH {12} \ + CONFIG.PCW_NAND_CYCLES_T_AR {1} \ + CONFIG.PCW_NAND_CYCLES_T_CLR {1} \ + CONFIG.PCW_NAND_CYCLES_T_RC {11} \ + CONFIG.PCW_NAND_CYCLES_T_REA {1} \ + CONFIG.PCW_NAND_CYCLES_T_RR {1} \ + CONFIG.PCW_NAND_CYCLES_T_WC {11} \ + CONFIG.PCW_NAND_CYCLES_T_WP {1} \ + CONFIG.PCW_NAND_GRP_D8_ENABLE {0} \ + CONFIG.PCW_NAND_GRP_D8_IO {} \ + CONFIG.PCW_NAND_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_NOR_CS0_T_CEOE {1} \ + CONFIG.PCW_NOR_CS0_T_PC {1} \ + CONFIG.PCW_NOR_CS0_T_RC {11} \ + CONFIG.PCW_NOR_CS0_T_TR {1} \ + CONFIG.PCW_NOR_CS0_T_WC {11} \ + CONFIG.PCW_NOR_CS0_T_WP {1} \ + CONFIG.PCW_NOR_CS0_WE_TIME {0} \ + CONFIG.PCW_NOR_CS1_T_CEOE {1} \ + CONFIG.PCW_NOR_CS1_T_PC {1} \ + CONFIG.PCW_NOR_CS1_T_RC {11} \ + CONFIG.PCW_NOR_CS1_T_TR {1} \ + CONFIG.PCW_NOR_CS1_T_WC {11} \ + CONFIG.PCW_NOR_CS1_T_WP {1} \ + CONFIG.PCW_NOR_CS1_WE_TIME {0} \ + CONFIG.PCW_NOR_GRP_A25_ENABLE {0} \ + CONFIG.PCW_NOR_GRP_A25_IO {} \ + CONFIG.PCW_NOR_GRP_CS1_ENABLE {0} \ + CONFIG.PCW_NOR_GRP_CS1_IO {} \ + CONFIG.PCW_NOR_GRP_SRAM_CS1_ENABLE {0} \ + CONFIG.PCW_NOR_GRP_SRAM_CS1_IO {} \ + CONFIG.PCW_NOR_NOR_IO {} \ + CONFIG.PCW_PLL_BYPASSMODE_ENABLE {0} \ + CONFIG.PCW_PRESET_BANK0_VOLTAGE {LVCMOS 3.3V} \ + CONFIG.PCW_PRESET_BANK1_VOLTAGE {LVCMOS 1.8V} \ + CONFIG.PCW_PS7_SI_REV {PRODUCTION} \ + CONFIG.PCW_QSPI_GRP_FBCLK_ENABLE {1} \ + CONFIG.PCW_QSPI_GRP_FBCLK_IO {MIO 8} \ + CONFIG.PCW_QSPI_GRP_IO1_ENABLE {0} \ + CONFIG.PCW_QSPI_GRP_IO1_IO {} \ + CONFIG.PCW_QSPI_INTERNAL_HIGHADDRESS {0xFCFFFFFF} \ + CONFIG.PCW_QSPI_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_QSPI_PERIPHERAL_DIVISOR0 {5} \ + CONFIG.PCW_QSPI_PERIPHERAL_ENABLE {1} \ + CONFIG.PCW_QSPI_PERIPHERAL_FREQMHZ {200} \ + CONFIG.PCW_QSPI_QSPI_IO {MIO 1 .. 6} \ + CONFIG.PCW_SD0_GRP_CD_ENABLE {1} \ + CONFIG.PCW_SD0_GRP_CD_IO {MIO 47} \ + CONFIG.PCW_SD0_GRP_POW_ENABLE {0} \ + CONFIG.PCW_SD0_GRP_POW_IO {} \ + CONFIG.PCW_SD0_PERIPHERAL_ENABLE {1} \ + CONFIG.PCW_SD0_SD0_IO {MIO 40 .. 45} \ + CONFIG.PCW_SD1_GRP_CD_ENABLE {0} \ + CONFIG.PCW_SD1_GRP_CD_IO {} \ + CONFIG.PCW_SD1_GRP_WP_ENABLE {0} \ + CONFIG.PCW_SD1_GRP_WP_IO {} \ + CONFIG.PCW_SDIO0_BASEADDR {0xE0100000} \ + CONFIG.PCW_SDIO0_HIGHADDR {0xE0100FFF} \ + CONFIG.PCW_SDIO1_BASEADDR {0xE0101000} \ + CONFIG.PCW_SDIO1_HIGHADDR {0xE0101FFF} \ + CONFIG.PCW_SDIO_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_SDIO_PERIPHERAL_DIVISOR0 {20} \ + CONFIG.PCW_SDIO_PERIPHERAL_FREQMHZ {50} \ + CONFIG.PCW_SDIO_PERIPHERAL_VALID {1} \ + CONFIG.PCW_SINGLE_QSPI_DATA_MODE {x4} \ + CONFIG.PCW_SMC_CYCLE_T0 {NA} \ + CONFIG.PCW_SMC_CYCLE_T1 {NA} \ + CONFIG.PCW_SMC_CYCLE_T2 {NA} \ + CONFIG.PCW_SMC_CYCLE_T3 {NA} \ + CONFIG.PCW_SMC_CYCLE_T4 {NA} \ + CONFIG.PCW_SMC_CYCLE_T5 {NA} \ + CONFIG.PCW_SMC_CYCLE_T6 {NA} \ + CONFIG.PCW_SMC_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_SMC_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_SMC_PERIPHERAL_FREQMHZ {100} \ + CONFIG.PCW_SMC_PERIPHERAL_VALID {0} \ + CONFIG.PCW_SPI0_BASEADDR {0xE0006000} \ + CONFIG.PCW_SPI0_GRP_SS0_ENABLE {0} \ + CONFIG.PCW_SPI0_GRP_SS0_IO {} \ + CONFIG.PCW_SPI0_GRP_SS2_ENABLE {0} \ + CONFIG.PCW_SPI0_GRP_SS2_IO {} \ + CONFIG.PCW_SPI1_BASEADDR {0xE0007000} \ + CONFIG.PCW_SPI1_GRP_SS0_ENABLE {0} \ + CONFIG.PCW_SPI1_GRP_SS0_IO {} \ + CONFIG.PCW_SPI1_GRP_SS2_ENABLE {0} \ + CONFIG.PCW_SPI1_GRP_SS2_IO {} \ + CONFIG.PCW_SPI_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_SPI_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_SPI_PERIPHERAL_FREQMHZ {166.666666} \ + CONFIG.PCW_SPI_PERIPHERAL_VALID {0} \ + CONFIG.PCW_S_AXI_ACP_ARUSER_VAL {31} \ + CONFIG.PCW_S_AXI_ACP_AWUSER_VAL {31} \ + CONFIG.PCW_S_AXI_ACP_ID_WIDTH {3} \ + CONFIG.PCW_S_AXI_GP0_ID_WIDTH {6} \ + CONFIG.PCW_S_AXI_GP1_ID_WIDTH {6} \ + CONFIG.PCW_S_AXI_HP0_DATA_WIDTH {64} \ + CONFIG.PCW_S_AXI_HP0_ID_WIDTH {6} \ + CONFIG.PCW_S_AXI_HP1_DATA_WIDTH {64} \ + CONFIG.PCW_S_AXI_HP1_ID_WIDTH {6} \ + CONFIG.PCW_S_AXI_HP2_DATA_WIDTH {64} \ + CONFIG.PCW_S_AXI_HP2_ID_WIDTH {6} \ + CONFIG.PCW_S_AXI_HP3_DATA_WIDTH {64} \ + CONFIG.PCW_S_AXI_HP3_ID_WIDTH {6} \ + CONFIG.PCW_TPIU_PERIPHERAL_CLKSRC {External} \ + CONFIG.PCW_TPIU_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_TPIU_PERIPHERAL_FREQMHZ {200} \ + CONFIG.PCW_TRACE_BUFFER_CLOCK_DELAY {12} \ + CONFIG.PCW_TRACE_BUFFER_FIFO_SIZE {128} \ + CONFIG.PCW_TRACE_GRP_16BIT_ENABLE {0} \ + CONFIG.PCW_TRACE_GRP_16BIT_IO {} \ + CONFIG.PCW_TRACE_GRP_32BIT_ENABLE {0} \ + CONFIG.PCW_TRACE_GRP_32BIT_IO {} \ + CONFIG.PCW_TRACE_GRP_8BIT_ENABLE {0} \ + CONFIG.PCW_TRACE_GRP_8BIT_IO {} \ + CONFIG.PCW_TTC0_BASEADDR {0xE0104000} \ + CONFIG.PCW_TTC0_CLK0_PERIPHERAL_CLKSRC {CPU_1X} \ + CONFIG.PCW_TTC0_CLK0_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_TTC0_CLK0_PERIPHERAL_FREQMHZ {133.333333} \ + CONFIG.PCW_TTC0_CLK1_PERIPHERAL_CLKSRC {CPU_1X} \ + CONFIG.PCW_TTC0_CLK1_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_TTC0_CLK1_PERIPHERAL_FREQMHZ {133.333333} \ + CONFIG.PCW_TTC0_CLK2_PERIPHERAL_CLKSRC {CPU_1X} \ + CONFIG.PCW_TTC0_CLK2_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_TTC0_CLK2_PERIPHERAL_FREQMHZ {133.333333} \ + CONFIG.PCW_TTC0_HIGHADDR {0xE0104fff} \ + CONFIG.PCW_TTC0_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_TTC0_TTC0_IO {} \ + CONFIG.PCW_TTC_PERIPHERAL_FREQMHZ {50} \ + CONFIG.PCW_UART0_BASEADDR {0xE0000000} \ + CONFIG.PCW_UART0_BAUD_RATE {115200} \ + CONFIG.PCW_UART0_GRP_FULL_ENABLE {0} \ + CONFIG.PCW_UART0_GRP_FULL_IO {} \ + CONFIG.PCW_UART1_HIGHADDR {0xE0001FFF} \ + CONFIG.PCW_UART1_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_UART1_UART1_IO {} \ + CONFIG.PCW_USB1_USB1_IO {} \ + ] $processing_system7_0 + + # Create instance: ps7_0_axi_periph, and set properties + set ps7_0_axi_periph [ create_bd_cell -type ip -vlnv xilinx.com:ip:axi_interconnect:2.1 ps7_0_axi_periph ] + set_property -dict [ list \ + CONFIG.NUM_MI {2} \ + ] $ps7_0_axi_periph + + # Create instance: pynqrouter_0, and set properties + set pynqrouter_0 [ create_bd_cell -type ip -vlnv xilinx.com:hls:pynqrouter:1.0 pynqrouter_0 ] + + # Create instance: rst_ps7_0_100M, and set properties + set rst_ps7_0_100M [ create_bd_cell -type ip -vlnv xilinx.com:ip:proc_sys_reset:5.0 rst_ps7_0_100M ] + + # Create interface connections + connect_bd_intf_net -intf_net processing_system7_0_DDR [get_bd_intf_ports DDR] [get_bd_intf_pins processing_system7_0/DDR] + connect_bd_intf_net -intf_net processing_system7_0_FIXED_IO [get_bd_intf_ports FIXED_IO] [get_bd_intf_pins processing_system7_0/FIXED_IO] + connect_bd_intf_net -intf_net processing_system7_0_M_AXI_GP0 [get_bd_intf_pins processing_system7_0/M_AXI_GP0] [get_bd_intf_pins ps7_0_axi_periph/S00_AXI] + connect_bd_intf_net -intf_net ps7_0_axi_periph_M00_AXI [get_bd_intf_pins ps7_0_axi_periph/M00_AXI] [get_bd_intf_pins pynqrouter_0/s_axi_AXI4LS] + connect_bd_intf_net -intf_net ps7_0_axi_periph_M01_AXI [get_bd_intf_pins axi_gpio_0/S_AXI] [get_bd_intf_pins ps7_0_axi_periph/M01_AXI] + + # Create port connections + connect_bd_net -net axi_gpio_0_gpio_io_o [get_bd_ports LD] [get_bd_pins axi_gpio_0/gpio_io_o] + connect_bd_net -net processing_system7_0_FCLK_CLK0 [get_bd_pins axi_gpio_0/s_axi_aclk] [get_bd_pins processing_system7_0/FCLK_CLK0] [get_bd_pins processing_system7_0/M_AXI_GP0_ACLK] [get_bd_pins ps7_0_axi_periph/ACLK] [get_bd_pins ps7_0_axi_periph/M00_ACLK] [get_bd_pins ps7_0_axi_periph/M01_ACLK] [get_bd_pins ps7_0_axi_periph/S00_ACLK] [get_bd_pins pynqrouter_0/ap_clk] [get_bd_pins rst_ps7_0_100M/slowest_sync_clk] + connect_bd_net -net processing_system7_0_FCLK_RESET0_N [get_bd_pins processing_system7_0/FCLK_RESET0_N] [get_bd_pins rst_ps7_0_100M/ext_reset_in] + connect_bd_net -net rst_ps7_0_100M_interconnect_aresetn [get_bd_pins ps7_0_axi_periph/ARESETN] [get_bd_pins rst_ps7_0_100M/interconnect_aresetn] + connect_bd_net -net rst_ps7_0_100M_peripheral_aresetn [get_bd_pins axi_gpio_0/s_axi_aresetn] [get_bd_pins ps7_0_axi_periph/M00_ARESETN] [get_bd_pins ps7_0_axi_periph/M01_ARESETN] [get_bd_pins ps7_0_axi_periph/S00_ARESETN] [get_bd_pins pynqrouter_0/ap_rst_n] [get_bd_pins rst_ps7_0_100M/peripheral_aresetn] + + # Create address segments + create_bd_addr_seg -range 0x00010000 -offset 0x41200000 [get_bd_addr_spaces processing_system7_0/Data] [get_bd_addr_segs axi_gpio_0/S_AXI/Reg] SEG_axi_gpio_0_Reg + create_bd_addr_seg -range 0x00040000 -offset 0x43C00000 [get_bd_addr_spaces processing_system7_0/Data] [get_bd_addr_segs pynqrouter_0/s_axi_AXI4LS/Reg] SEG_pynqrouter_0_Reg + + + # Restore current instance + current_bd_instance $oldCurInst + + save_bd_design +} +# End of create_root_design() + + +################################################################## +# MAIN FLOW +################################################################## + +create_root_design "" + + -- 2.22.0 From bb9db10da3172725f57ffd3a2910a6ecf2afde38 Mon Sep 17 00:00:00 2001 From: KazushiKawamura Date: Sun, 26 Aug 2018 22:02:04 +0900 Subject: [PATCH 26/30] Upload a bitstream file --- .../router_01/bitstream/router_design.bit | Bin 0 -> 4045681 bytes .../router_01/bitstream/router_design.tcl | 1113 +++++++++++++++++ 2 files changed, 1113 insertions(+) create mode 100755 hls_2018/router_01/bitstream/router_design.bit create mode 100755 hls_2018/router_01/bitstream/router_design.tcl diff --git a/hls_2018/router_01/bitstream/router_design.bit b/hls_2018/router_01/bitstream/router_design.bit new file mode 100755 index 0000000000000000000000000000000000000000..5774d9ef5786cdc8d9ed35d0f2d614a6a545f391 GIT binary patch literal 4045681 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 z0wh2JBtQZrKmsH{0wh2JBtQZrKmsH{0wh2JBtQZrKmsH{0wh2JBtQZrKmsH{0wh2J zBtQZrKmsH{0wh2JBtQZrKmsH{0wh2JBtQZrKmsH{0wh2JBtQZrKmsH{0wh2JBtQZr zKmsH{0wh2JBtQZrKmsH{0wh2JBtQZrKmsH{0wh2JBtQZrKmsH{0wh2JBtQZrKmsH{ z0wh2JBtQZrKmsH{0wh2JBtQZrKmsH{0wh2JBtQZrKmsH{0wh2JBtQZrKmsH{0wh2J zBtQZrKmsH{0wh2JBtQZrKmsH{0wh2JBtQZrKmsH{0wh2JBtQZrKmsH{0wh2JBtQZr zKmsH{0wh2JBtQZrKmsH{0wh2JBtQZrKmsH{0wh2JBtQZrKmsH{0wh2JBtQZrKmsH{ z0wh2JBtQZrKmsH{0wh2JBtQZrKmsH{0wh2JBtQZrKmsH{0wh2JBtQZrKmsH{0wh2J zBtQZrKmsH{0wh2JBtQZrKmsH{0wh2JBtQZrKmsH{0wh2JBtQZrKmsH{0wh2JBtQZr zKmsH{0wh2JBtQZrKmsH{0wh2JBtQZrKmsH{0wh2JBtQZrKmsH{0wh2JBtQZrKmsH{ z0wh2JBtQZrKmsH{0wh2JBtQZrKmsH{0wh2JBtQZrKmsH{0wh2JBtQZrKmsH{0wh2J zBtQZrKmsH{0wh2JBtQZrKmsH{0wh2JBtQZrKmsH{0wh2JBtQZrKmsH{0wh2JBtQZr zKmsH{0wh2JBtQZrKmsH{0wh2JBtQZrKmsH{0wh2JBtQZrKmsH{0wh2JBtQZrKmsH{ z0wh2JBtQZrKmsH{0wh2JBtQZrKmsH{0wh2JBtQZrKmsH{0wh2JBtQZrKmsH{0wh2J zBtQZrKmsH{0wh2JBtQZrKmsH{0wh2JBtQZrKmsH{0wh2JBtQZrKmsH{0wh2JBtQZr zKmsH{0wh2JBtQZrKmsH{0wh2JBtQZrKmsH{0wh2JBtQZrKmsH{0wh2JBtQZrKmsH{ z0wh2JBtQZrKmsH{0wh2JBtQZrKmsH{0wh2JBtQZrKmsH{0wh2JBtQZrKmsH{0wh2J zBtQZrKmsH{0wh2JBtQZrKmsH{0wh2JBtQZrKmsH{0wh2JBtQZrKmsH{0wh2JBtQZr zKmsH{0wh2JBtQZrKmsH{0wh2JBtQZrKmsH{0wh2JBtQZrKmsH{0wh2JBtQZrKmsH{ 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%0D)cAR-2Tr$7r*sJoaOY)PyamL?rSLi9kiBgPu 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�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

Zd^1RI-*Nk#YsWN}Y~4%==r7?2f=N|y}H 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

^?Wj8%J4_&cL*d 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 z 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 z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0tB{5;PI69{@`c6^i!)CQ~r58HG468LC)u&Zuy~pc~kSQ-wW+Js=bf and is being run in <$current_vivado_version> of Vivado. Please run the script in Vivado <$scripts_vivado_version> then open the design in Vivado <$current_vivado_version>. Upgrade the design by running \"Tools => Report => Report IP Status...\", then run write_bd_tcl to create an updated script."} + + return 1 +} + +################################################################ +# START +################################################################ + +# To test this script, run the following commands from Vivado Tcl console: +# source router_design_script.tcl + +# If there is no project opened, this script will create a +# project, but make sure you do not have an existing project +# <./myproj/project_1.xpr> in the current working folder. + +set list_projs [get_projects -quiet] +if { $list_projs eq "" } { + create_project project_1 myproj -part xczu3eg-sbva484-1-e + set_property BOARD_PART em.avnet.com:ultra96:part0:1.0 [current_project] +} + + +# CHANGE DESIGN NAME HERE +variable design_name +set design_name router_design + +# If you do not already have an existing IP Integrator design open, +# you can create a design using the following command: +# create_bd_design $design_name + +# Creating design if needed +set errMsg "" +set nRet 0 + +set cur_design [current_bd_design -quiet] +set list_cells [get_bd_cells -quiet] + +if { ${design_name} eq "" } { + # USE CASES: + # 1) Design_name not set + + set errMsg "Please set the variable to a non-empty value." + set nRet 1 + +} elseif { ${cur_design} ne "" && ${list_cells} eq "" } { + # USE CASES: + # 2): Current design opened AND is empty AND names same. + # 3): Current design opened AND is empty AND names diff; design_name NOT in project. + # 4): Current design opened AND is empty AND names diff; design_name exists in project. + + if { $cur_design ne $design_name } { + common::send_msg_id "BD_TCL-001" "INFO" "Changing value of from <$design_name> to <$cur_design> since current design is empty." + set design_name [get_property NAME $cur_design] + } + common::send_msg_id "BD_TCL-002" "INFO" "Constructing design in IPI design <$cur_design>..." + +} elseif { ${cur_design} ne "" && $list_cells ne "" && $cur_design eq $design_name } { + # USE CASES: + # 5) Current design opened AND has components AND same names. + + set errMsg "Design <$design_name> already exists in your project, please set the variable to another value." + set nRet 1 +} elseif { [get_files -quiet ${design_name}.bd] ne "" } { + # USE CASES: + # 6) Current opened design, has components, but diff names, design_name exists in project. + # 7) No opened design, design_name exists in project. + + set errMsg "Design <$design_name> already exists in your project, please set the variable to another value." + set nRet 2 + +} else { + # USE CASES: + # 8) No opened design, design_name not in project. + # 9) Current opened design, has components, but diff names, design_name not in project. + + common::send_msg_id "BD_TCL-003" "INFO" "Currently there is no design <$design_name> in project, so creating one..." + + create_bd_design $design_name + + common::send_msg_id "BD_TCL-004" "INFO" "Making design <$design_name> as current_bd_design." + current_bd_design $design_name + +} + +common::send_msg_id "BD_TCL-005" "INFO" "Currently the variable is equal to \"$design_name\"." + +if { $nRet != 0 } { + catch {common::send_msg_id "BD_TCL-114" "ERROR" $errMsg} + return $nRet +} + +set bCheckIPsPassed 1 +################################################################## +# CHECK IPs +################################################################## +set bCheckIPs 1 +if { $bCheckIPs == 1 } { + set list_check_ips "\ +xilinx.com:hls:pynqrouter:1.0\ +xilinx.com:ip:proc_sys_reset:5.0\ +xilinx.com:ip:zynq_ultra_ps_e:3.2\ +" + + set list_ips_missing "" + common::send_msg_id "BD_TCL-006" "INFO" "Checking if the following IPs exist in the project's IP catalog: $list_check_ips ." + + foreach ip_vlnv $list_check_ips { + set ip_obj [get_ipdefs -all $ip_vlnv] + if { $ip_obj eq "" } { + lappend list_ips_missing $ip_vlnv + } + } + + if { $list_ips_missing ne "" } { + catch {common::send_msg_id "BD_TCL-115" "ERROR" "The following IPs are not found in the IP Catalog:\n $list_ips_missing\n\nResolution: Please add the repository containing the IP(s) to the project." } + set bCheckIPsPassed 0 + } + +} + +if { $bCheckIPsPassed != 1 } { + common::send_msg_id "BD_TCL-1003" "WARNING" "Will not continue with creation of design due to the error(s) above." + return 3 +} + +################################################################## +# DESIGN PROCs +################################################################## + + + +# Procedure to create entire design; Provide argument to make +# procedure reusable. If parentCell is "", will use root. +proc create_root_design { parentCell } { + + variable script_folder + variable design_name + + if { $parentCell eq "" } { + set parentCell [get_bd_cells /] + } + + # Get object for parentCell + set parentObj [get_bd_cells $parentCell] + if { $parentObj == "" } { + catch {common::send_msg_id "BD_TCL-100" "ERROR" "Unable to find parent cell <$parentCell>!"} + return + } + + # Make sure parentObj is hier blk + set parentType [get_property TYPE $parentObj] + if { $parentType ne "hier" } { + catch {common::send_msg_id "BD_TCL-101" "ERROR" "Parent <$parentObj> has TYPE = <$parentType>. Expected to be ."} + return + } + + # Save current instance; Restore later + set oldCurInst [current_bd_instance .] + + # Set parent object as current + current_bd_instance $parentObj + + + # Create interface ports + + # Create ports + + # Create instance: ps8_0_axi_periph, and set properties + set ps8_0_axi_periph [ create_bd_cell -type ip -vlnv xilinx.com:ip:axi_interconnect:2.1 ps8_0_axi_periph ] + set_property -dict [ list \ + CONFIG.NUM_MI {1} \ + CONFIG.NUM_SI {2} \ + ] $ps8_0_axi_periph + + # Create instance: pynqrouter_0, and set properties + set pynqrouter_0 [ create_bd_cell -type ip -vlnv xilinx.com:hls:pynqrouter:1.0 pynqrouter_0 ] + + # Create instance: rst_ps8_0_100M, and set properties + set rst_ps8_0_100M [ create_bd_cell -type ip -vlnv xilinx.com:ip:proc_sys_reset:5.0 rst_ps8_0_100M ] + + # Create instance: zynq_ultra_ps_e_0, and set properties + set zynq_ultra_ps_e_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:zynq_ultra_ps_e:3.2 zynq_ultra_ps_e_0 ] + set_property -dict [ list \ + CONFIG.PSU_BANK_0_IO_STANDARD {LVCMOS18} \ + CONFIG.PSU_BANK_1_IO_STANDARD {LVCMOS18} \ + CONFIG.PSU_BANK_2_IO_STANDARD {LVCMOS18} \ + CONFIG.PSU_BANK_3_IO_STANDARD {LVCMOS18} \ + CONFIG.PSU_DDR_RAM_HIGHADDR {0x7FFFFFFF} \ + CONFIG.PSU_DDR_RAM_HIGHADDR_OFFSET {0x00000002} \ + CONFIG.PSU_DDR_RAM_LOWADDR_OFFSET {0x80000000} \ + CONFIG.PSU_MIO_0_DIRECTION {out} \ + CONFIG.PSU_MIO_0_INPUT_TYPE {schmitt} \ + CONFIG.PSU_MIO_10_DIRECTION {inout} \ + CONFIG.PSU_MIO_11_DIRECTION {inout} \ + CONFIG.PSU_MIO_12_DIRECTION {inout} \ + CONFIG.PSU_MIO_13_DIRECTION {inout} \ + CONFIG.PSU_MIO_13_DRIVE_STRENGTH {4} \ + CONFIG.PSU_MIO_14_DIRECTION {inout} \ + CONFIG.PSU_MIO_14_DRIVE_STRENGTH {4} \ + CONFIG.PSU_MIO_15_DIRECTION {inout} \ + CONFIG.PSU_MIO_15_DRIVE_STRENGTH {4} \ + CONFIG.PSU_MIO_16_DIRECTION {inout} \ + CONFIG.PSU_MIO_16_DRIVE_STRENGTH {4} \ + CONFIG.PSU_MIO_17_DIRECTION {inout} \ + CONFIG.PSU_MIO_18_DIRECTION {inout} \ + CONFIG.PSU_MIO_19_DIRECTION {inout} \ + CONFIG.PSU_MIO_1_DIRECTION {in} \ + CONFIG.PSU_MIO_1_DRIVE_STRENGTH {12} \ + CONFIG.PSU_MIO_1_SLEW {slow} \ + CONFIG.PSU_MIO_20_DIRECTION {inout} \ + CONFIG.PSU_MIO_21_DIRECTION {inout} \ + CONFIG.PSU_MIO_21_DRIVE_STRENGTH {4} \ + CONFIG.PSU_MIO_22_DIRECTION {out} \ + CONFIG.PSU_MIO_22_DRIVE_STRENGTH {4} \ + CONFIG.PSU_MIO_22_INPUT_TYPE {schmitt} \ + CONFIG.PSU_MIO_23_DIRECTION {inout} \ + CONFIG.PSU_MIO_24_DIRECTION {in} \ + CONFIG.PSU_MIO_24_DRIVE_STRENGTH {12} \ + CONFIG.PSU_MIO_24_SLEW {slow} \ + CONFIG.PSU_MIO_25_DIRECTION {inout} \ + CONFIG.PSU_MIO_26_DIRECTION {in} \ + CONFIG.PSU_MIO_26_DRIVE_STRENGTH {12} \ + CONFIG.PSU_MIO_26_SLEW {slow} \ + CONFIG.PSU_MIO_27_DIRECTION {out} \ + CONFIG.PSU_MIO_27_INPUT_TYPE {schmitt} \ + CONFIG.PSU_MIO_28_DIRECTION {in} \ + CONFIG.PSU_MIO_28_DRIVE_STRENGTH {12} \ + CONFIG.PSU_MIO_28_SLEW {slow} \ + CONFIG.PSU_MIO_29_DIRECTION {out} \ + CONFIG.PSU_MIO_29_INPUT_TYPE {schmitt} \ + CONFIG.PSU_MIO_2_DIRECTION {in} \ + CONFIG.PSU_MIO_2_DRIVE_STRENGTH {12} \ + CONFIG.PSU_MIO_2_SLEW {slow} \ + CONFIG.PSU_MIO_30_DIRECTION {in} \ + CONFIG.PSU_MIO_30_DRIVE_STRENGTH {12} \ + CONFIG.PSU_MIO_30_SLEW {slow} \ + CONFIG.PSU_MIO_31_DIRECTION {inout} \ + CONFIG.PSU_MIO_32_DIRECTION {out} \ + CONFIG.PSU_MIO_32_INPUT_TYPE {schmitt} \ + CONFIG.PSU_MIO_33_DIRECTION {out} \ + CONFIG.PSU_MIO_33_INPUT_TYPE {schmitt} \ + CONFIG.PSU_MIO_34_DIRECTION {out} \ + CONFIG.PSU_MIO_34_INPUT_TYPE {schmitt} \ + CONFIG.PSU_MIO_35_DIRECTION {inout} \ + CONFIG.PSU_MIO_36_DIRECTION {inout} \ + CONFIG.PSU_MIO_37_DIRECTION {inout} \ + CONFIG.PSU_MIO_38_DIRECTION {inout} \ + CONFIG.PSU_MIO_39_DIRECTION {inout} \ + CONFIG.PSU_MIO_39_DRIVE_STRENGTH {12} \ + CONFIG.PSU_MIO_39_SLEW {slow} \ + CONFIG.PSU_MIO_3_DIRECTION {out} \ + CONFIG.PSU_MIO_3_INPUT_TYPE {schmitt} \ + CONFIG.PSU_MIO_40_DIRECTION {inout} \ + CONFIG.PSU_MIO_41_DIRECTION {inout} \ + CONFIG.PSU_MIO_42_DIRECTION {inout} \ + CONFIG.PSU_MIO_43_DIRECTION {inout} \ + CONFIG.PSU_MIO_44_DIRECTION {inout} \ + CONFIG.PSU_MIO_45_DIRECTION {inout} \ + CONFIG.PSU_MIO_46_DIRECTION {inout} \ + CONFIG.PSU_MIO_47_DIRECTION {inout} \ + CONFIG.PSU_MIO_48_DIRECTION {inout} \ + CONFIG.PSU_MIO_49_DIRECTION {inout} \ + CONFIG.PSU_MIO_4_DIRECTION {inout} \ + CONFIG.PSU_MIO_50_DIRECTION {inout} \ + CONFIG.PSU_MIO_51_DIRECTION {out} \ + CONFIG.PSU_MIO_51_INPUT_TYPE {schmitt} \ + CONFIG.PSU_MIO_52_DIRECTION {in} \ + CONFIG.PSU_MIO_52_DRIVE_STRENGTH {12} \ + CONFIG.PSU_MIO_52_SLEW {slow} \ + CONFIG.PSU_MIO_53_DIRECTION {in} \ + CONFIG.PSU_MIO_53_DRIVE_STRENGTH {12} \ + CONFIG.PSU_MIO_53_SLEW {slow} \ + CONFIG.PSU_MIO_54_DIRECTION {inout} \ + CONFIG.PSU_MIO_55_DIRECTION {in} \ + CONFIG.PSU_MIO_55_DRIVE_STRENGTH {12} \ + CONFIG.PSU_MIO_55_SLEW {slow} \ + CONFIG.PSU_MIO_56_DIRECTION {inout} \ + CONFIG.PSU_MIO_57_DIRECTION {inout} \ + CONFIG.PSU_MIO_58_DIRECTION {out} \ + CONFIG.PSU_MIO_58_INPUT_TYPE {schmitt} \ + CONFIG.PSU_MIO_59_DIRECTION {inout} \ + CONFIG.PSU_MIO_5_DIRECTION {inout} \ + CONFIG.PSU_MIO_60_DIRECTION {inout} \ + CONFIG.PSU_MIO_61_DIRECTION {inout} \ + CONFIG.PSU_MIO_62_DIRECTION {inout} \ + CONFIG.PSU_MIO_63_DIRECTION {inout} \ + CONFIG.PSU_MIO_64_DIRECTION {in} \ + CONFIG.PSU_MIO_64_DRIVE_STRENGTH {12} \ + CONFIG.PSU_MIO_64_SLEW {slow} \ + CONFIG.PSU_MIO_65_DIRECTION {in} \ + CONFIG.PSU_MIO_65_DRIVE_STRENGTH {12} \ + CONFIG.PSU_MIO_65_SLEW {slow} \ + CONFIG.PSU_MIO_66_DIRECTION {inout} \ + CONFIG.PSU_MIO_67_DIRECTION {in} \ + CONFIG.PSU_MIO_67_DRIVE_STRENGTH {12} \ + CONFIG.PSU_MIO_67_SLEW {slow} \ + CONFIG.PSU_MIO_68_DIRECTION {inout} \ + CONFIG.PSU_MIO_69_DIRECTION {inout} \ + CONFIG.PSU_MIO_6_DIRECTION {inout} \ + CONFIG.PSU_MIO_70_DIRECTION {out} \ + CONFIG.PSU_MIO_70_INPUT_TYPE {schmitt} \ + CONFIG.PSU_MIO_71_DIRECTION {inout} \ + CONFIG.PSU_MIO_72_DIRECTION {inout} \ + CONFIG.PSU_MIO_73_DIRECTION {inout} \ + CONFIG.PSU_MIO_74_DIRECTION {inout} \ + CONFIG.PSU_MIO_75_DIRECTION {inout} \ + CONFIG.PSU_MIO_76_DIRECTION {inout} \ + CONFIG.PSU_MIO_77_DIRECTION {inout} \ + CONFIG.PSU_MIO_7_DIRECTION {inout} \ + CONFIG.PSU_MIO_8_DIRECTION {inout} \ + CONFIG.PSU_MIO_9_DIRECTION {inout} \ + CONFIG.PSU_MIO_TREE_PERIPHERALS {UART 1#UART 1#UART 0#UART 0#I2C 1#I2C 1#SPI 1#GPIO0 MIO#GPIO0 MIO#SPI 1#SPI 1#SPI 1#GPIO0 MIO#SD 0#SD 0#SD 0#SD 0#GPIO0 MIO#GPIO0 MIO#GPIO0 MIO#GPIO0 MIO#SD 0#SD 0#GPIO0 MIO#SD 0#GPIO0 MIO#PMU GPI 0#DPAUX#DPAUX#DPAUX#DPAUX#GPIO1 MIO#PMU GPO 0#PMU GPO 1#PMU GPO 2#GPIO1 MIO#GPIO1 MIO#GPIO1 MIO#SPI 0#GPIO1 MIO#GPIO1 MIO#SPI 0#SPI 0#SPI 0#GPIO1 MIO#GPIO1 MIO#SD 1#SD 1#SD 1#SD 1#SD 1#SD 1#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 1#USB 1#USB 1#USB 1#USB 1#USB 1#USB 1#USB 1#USB 1#USB 1#USB 1#USB 1#GPIO2 MIO#GPIO2 MIO} \ + CONFIG.PSU_MIO_TREE_SIGNALS {txd#rxd#rxd#txd#scl_out#sda_out#sclk_out#gpio0[7]#gpio0[8]#n_ss_out[0]#miso#mosi#gpio0[12]#sdio0_data_out[0]#sdio0_data_out[1]#sdio0_data_out[2]#sdio0_data_out[3]#gpio0[17]#gpio0[18]#gpio0[19]#gpio0[20]#sdio0_cmd_out#sdio0_clk_out#gpio0[23]#sdio0_cd_n#gpio0[25]#gpi[0]#dp_aux_data_out#dp_hot_plug_detect#dp_aux_data_oe#dp_aux_data_in#gpio1[31]#gpo[0]#gpo[1]#gpo[2]#gpio1[35]#gpio1[36]#gpio1[37]#sclk_out#gpio1[39]#gpio1[40]#n_ss_out[0]#miso#mosi#gpio1[44]#gpio1[45]#sdio1_data_out[0]#sdio1_data_out[1]#sdio1_data_out[2]#sdio1_data_out[3]#sdio1_cmd_out#sdio1_clk_out#ulpi_clk_in#ulpi_dir#ulpi_tx_data[2]#ulpi_nxt#ulpi_tx_data[0]#ulpi_tx_data[1]#ulpi_stp#ulpi_tx_data[3]#ulpi_tx_data[4]#ulpi_tx_data[5]#ulpi_tx_data[6]#ulpi_tx_data[7]#ulpi_clk_in#ulpi_dir#ulpi_tx_data[2]#ulpi_nxt#ulpi_tx_data[0]#ulpi_tx_data[1]#ulpi_stp#ulpi_tx_data[3]#ulpi_tx_data[4]#ulpi_tx_data[5]#ulpi_tx_data[6]#ulpi_tx_data[7]#gpio2[76]#gpio2[77]} \ + CONFIG.PSU_SD0_INTERNAL_BUS_WIDTH {4} \ + CONFIG.PSU_SD1_INTERNAL_BUS_WIDTH {4} \ + CONFIG.PSU__ACT_DDR_FREQ_MHZ {525.000000} \ + CONFIG.PSU__CAN1__GRP_CLK__ENABLE {0} \ + CONFIG.PSU__CAN1__PERIPHERAL__ENABLE {0} \ + CONFIG.PSU__CRF_APB__ACPU_CTRL__ACT_FREQMHZ {1200.000024} \ + CONFIG.PSU__CRF_APB__ACPU_CTRL__DIVISOR0 {1} \ + CONFIG.PSU__CRF_APB__ACPU_CTRL__FREQMHZ {1200} \ + CONFIG.PSU__CRF_APB__ACPU_CTRL__SRCSEL {APLL} \ + CONFIG.PSU__CRF_APB__APLL_CTRL__DIV2 {1} \ + CONFIG.PSU__CRF_APB__APLL_CTRL__FBDIV {72} \ + CONFIG.PSU__CRF_APB__APLL_CTRL__FRACDATA {0.000000} \ + CONFIG.PSU__CRF_APB__APLL_CTRL__SRCSEL {PSS_REF_CLK} \ + CONFIG.PSU__CRF_APB__APLL_FRAC_CFG__ENABLED {0} \ + CONFIG.PSU__CRF_APB__APLL_TO_LPD_CTRL__DIVISOR0 {3} \ + CONFIG.PSU__CRF_APB__DBG_FPD_CTRL__ACT_FREQMHZ {250.000005} \ + CONFIG.PSU__CRF_APB__DBG_FPD_CTRL__DIVISOR0 {2} \ + CONFIG.PSU__CRF_APB__DBG_FPD_CTRL__FREQMHZ {250} \ + CONFIG.PSU__CRF_APB__DBG_FPD_CTRL__SRCSEL {IOPLL} \ + CONFIG.PSU__CRF_APB__DBG_TRACE_CTRL__DIVISOR0 {5} \ + CONFIG.PSU__CRF_APB__DBG_TRACE_CTRL__FREQMHZ {250} \ + CONFIG.PSU__CRF_APB__DBG_TRACE_CTRL__SRCSEL {IOPLL} \ + CONFIG.PSU__CRF_APB__DBG_TSTMP_CTRL__ACT_FREQMHZ {250.000005} \ + CONFIG.PSU__CRF_APB__DBG_TSTMP_CTRL__DIVISOR0 {2} \ + CONFIG.PSU__CRF_APB__DBG_TSTMP_CTRL__FREQMHZ {250} \ + CONFIG.PSU__CRF_APB__DBG_TSTMP_CTRL__SRCSEL {IOPLL} \ + CONFIG.PSU__CRF_APB__DDR_CTRL__ACT_FREQMHZ {262.500005} \ + CONFIG.PSU__CRF_APB__DDR_CTRL__DIVISOR0 {4} \ + CONFIG.PSU__CRF_APB__DDR_CTRL__FREQMHZ {533} \ + CONFIG.PSU__CRF_APB__DDR_CTRL__SRCSEL {DPLL} \ + CONFIG.PSU__CRF_APB__DPDMA_REF_CTRL__ACT_FREQMHZ {600.000012} \ + CONFIG.PSU__CRF_APB__DPDMA_REF_CTRL__DIVISOR0 {2} \ + CONFIG.PSU__CRF_APB__DPDMA_REF_CTRL__FREQMHZ {600} \ + CONFIG.PSU__CRF_APB__DPDMA_REF_CTRL__SRCSEL {APLL} \ + CONFIG.PSU__CRF_APB__DPLL_CTRL__DIV2 {1} \ + CONFIG.PSU__CRF_APB__DPLL_CTRL__FBDIV {63} \ + CONFIG.PSU__CRF_APB__DPLL_CTRL__FRACDATA {0.000000} \ + CONFIG.PSU__CRF_APB__DPLL_CTRL__SRCSEL {PSS_REF_CLK} \ + CONFIG.PSU__CRF_APB__DPLL_FRAC_CFG__ENABLED {0} \ + CONFIG.PSU__CRF_APB__DPLL_TO_LPD_CTRL__DIVISOR0 {2} \ + CONFIG.PSU__CRF_APB__DP_AUDIO_REF_CTRL__ACT_FREQMHZ {25.000000} \ + CONFIG.PSU__CRF_APB__DP_AUDIO_REF_CTRL__DIVISOR0 {16} \ + CONFIG.PSU__CRF_APB__DP_AUDIO_REF_CTRL__DIVISOR1 {1} \ + CONFIG.PSU__CRF_APB__DP_AUDIO_REF_CTRL__SRCSEL {RPLL} \ + CONFIG.PSU__CRF_APB__DP_AUDIO__FRAC_ENABLED {0} \ + CONFIG.PSU__CRF_APB__DP_STC_REF_CTRL__ACT_FREQMHZ {26.666667} \ + CONFIG.PSU__CRF_APB__DP_STC_REF_CTRL__DIVISOR0 {15} \ + CONFIG.PSU__CRF_APB__DP_STC_REF_CTRL__DIVISOR1 {1} \ + CONFIG.PSU__CRF_APB__DP_STC_REF_CTRL__SRCSEL {RPLL} \ + CONFIG.PSU__CRF_APB__DP_VIDEO_REF_CTRL__ACT_FREQMHZ {300.000006} \ + CONFIG.PSU__CRF_APB__DP_VIDEO_REF_CTRL__DIVISOR0 {5} \ + CONFIG.PSU__CRF_APB__DP_VIDEO_REF_CTRL__DIVISOR1 {1} \ + CONFIG.PSU__CRF_APB__DP_VIDEO_REF_CTRL__SRCSEL {VPLL} \ + CONFIG.PSU__CRF_APB__DP_VIDEO__FRAC_ENABLED {0} \ + CONFIG.PSU__CRF_APB__GDMA_REF_CTRL__ACT_FREQMHZ {600.000012} \ + CONFIG.PSU__CRF_APB__GDMA_REF_CTRL__DIVISOR0 {2} \ + CONFIG.PSU__CRF_APB__GDMA_REF_CTRL__FREQMHZ {600} \ + CONFIG.PSU__CRF_APB__GDMA_REF_CTRL__SRCSEL {APLL} \ + CONFIG.PSU__CRF_APB__GPU_REF_CTRL__ACT_FREQMHZ {500.000010} \ + CONFIG.PSU__CRF_APB__GPU_REF_CTRL__DIVISOR0 {1} \ + CONFIG.PSU__CRF_APB__GPU_REF_CTRL__FREQMHZ {500} \ + CONFIG.PSU__CRF_APB__GPU_REF_CTRL__SRCSEL {IOPLL} \ + CONFIG.PSU__CRF_APB__PCIE_REF_CTRL__DIVISOR0 {6} \ + CONFIG.PSU__CRF_APB__PCIE_REF_CTRL__FREQMHZ {250} \ + CONFIG.PSU__CRF_APB__PCIE_REF_CTRL__SRCSEL {IOPLL} \ + CONFIG.PSU__CRF_APB__SATA_REF_CTRL__DIVISOR0 {5} \ + CONFIG.PSU__CRF_APB__SATA_REF_CTRL__FREQMHZ {250} \ + CONFIG.PSU__CRF_APB__SATA_REF_CTRL__SRCSEL {IOPLL} \ + CONFIG.PSU__CRF_APB__TOPSW_LSBUS_CTRL__ACT_FREQMHZ {100.000002} \ + CONFIG.PSU__CRF_APB__TOPSW_LSBUS_CTRL__DIVISOR0 {5} \ + CONFIG.PSU__CRF_APB__TOPSW_LSBUS_CTRL__FREQMHZ {100} \ + CONFIG.PSU__CRF_APB__TOPSW_LSBUS_CTRL__SRCSEL {IOPLL} \ + CONFIG.PSU__CRF_APB__TOPSW_MAIN_CTRL__ACT_FREQMHZ {525.000011} \ + CONFIG.PSU__CRF_APB__TOPSW_MAIN_CTRL__DIVISOR0 {2} \ + CONFIG.PSU__CRF_APB__TOPSW_MAIN_CTRL__FREQMHZ {533.33} \ + CONFIG.PSU__CRF_APB__TOPSW_MAIN_CTRL__SRCSEL {DPLL} \ + CONFIG.PSU__CRF_APB__VPLL_CTRL__DIV2 {1} \ + CONFIG.PSU__CRF_APB__VPLL_CTRL__FBDIV {90} \ + CONFIG.PSU__CRF_APB__VPLL_CTRL__FRACDATA {0.000000} \ + CONFIG.PSU__CRF_APB__VPLL_CTRL__SRCSEL {PSS_REF_CLK} \ + CONFIG.PSU__CRF_APB__VPLL_FRAC_CFG__ENABLED {0} \ + CONFIG.PSU__CRF_APB__VPLL_TO_LPD_CTRL__DIVISOR0 {3} \ + CONFIG.PSU__CRL_APB__ADMA_REF_CTRL__ACT_FREQMHZ {500.000010} \ + CONFIG.PSU__CRL_APB__ADMA_REF_CTRL__DIVISOR0 {3} \ + CONFIG.PSU__CRL_APB__ADMA_REF_CTRL__FREQMHZ {500} \ + CONFIG.PSU__CRL_APB__ADMA_REF_CTRL__SRCSEL {IOPLL} \ + CONFIG.PSU__CRL_APB__AFI6_REF_CTRL__DIVISOR0 {3} \ + CONFIG.PSU__CRL_APB__AMS_REF_CTRL__ACT_FREQMHZ {50.000001} \ + CONFIG.PSU__CRL_APB__AMS_REF_CTRL__DIVISOR0 {30} \ + CONFIG.PSU__CRL_APB__AMS_REF_CTRL__DIVISOR1 {1} \ + CONFIG.PSU__CRL_APB__CAN0_REF_CTRL__DIVISOR0 {15} \ + CONFIG.PSU__CRL_APB__CAN0_REF_CTRL__DIVISOR1 {1} \ + CONFIG.PSU__CRL_APB__CAN1_REF_CTRL__DIVISOR0 {15} \ + CONFIG.PSU__CRL_APB__CAN1_REF_CTRL__DIVISOR1 {1} \ + CONFIG.PSU__CRL_APB__CAN1_REF_CTRL__FREQMHZ {100} \ + CONFIG.PSU__CRL_APB__CAN1_REF_CTRL__SRCSEL {IOPLL} \ + CONFIG.PSU__CRL_APB__CPU_R5_CTRL__ACT_FREQMHZ {500.000010} \ + CONFIG.PSU__CRL_APB__CPU_R5_CTRL__DIVISOR0 {3} \ + CONFIG.PSU__CRL_APB__CPU_R5_CTRL__FREQMHZ {500} \ + CONFIG.PSU__CRL_APB__CPU_R5_CTRL__SRCSEL {IOPLL} \ + CONFIG.PSU__CRL_APB__DBG_LPD_CTRL__ACT_FREQMHZ {250.000005} \ + CONFIG.PSU__CRL_APB__DBG_LPD_CTRL__DIVISOR0 {6} \ + CONFIG.PSU__CRL_APB__DBG_LPD_CTRL__FREQMHZ {250} \ + CONFIG.PSU__CRL_APB__DBG_LPD_CTRL__SRCSEL {IOPLL} \ + CONFIG.PSU__CRL_APB__DLL_REF_CTRL__ACT_FREQMHZ {1499.999985} \ + CONFIG.PSU__CRL_APB__GEM0_REF_CTRL__DIVISOR0 {12} \ + CONFIG.PSU__CRL_APB__GEM0_REF_CTRL__DIVISOR1 {1} \ + CONFIG.PSU__CRL_APB__GEM1_REF_CTRL__DIVISOR0 {12} \ + CONFIG.PSU__CRL_APB__GEM1_REF_CTRL__DIVISOR1 {1} \ + CONFIG.PSU__CRL_APB__GEM2_REF_CTRL__DIVISOR0 {12} \ + CONFIG.PSU__CRL_APB__GEM2_REF_CTRL__DIVISOR1 {1} \ + CONFIG.PSU__CRL_APB__GEM3_REF_CTRL__DIVISOR0 {12} \ + CONFIG.PSU__CRL_APB__GEM3_REF_CTRL__DIVISOR1 {1} \ + CONFIG.PSU__CRL_APB__GEM3_REF_CTRL__FREQMHZ {125} \ + CONFIG.PSU__CRL_APB__GEM3_REF_CTRL__SRCSEL {IOPLL} \ + CONFIG.PSU__CRL_APB__GEM_TSU_REF_CTRL__DIVISOR0 {4} \ + CONFIG.PSU__CRL_APB__GEM_TSU_REF_CTRL__DIVISOR1 {1} \ + CONFIG.PSU__CRL_APB__I2C0_REF_CTRL__DIVISOR0 {15} \ + CONFIG.PSU__CRL_APB__I2C0_REF_CTRL__DIVISOR1 {1} \ + CONFIG.PSU__CRL_APB__I2C0_REF_CTRL__FREQMHZ {100} \ + CONFIG.PSU__CRL_APB__I2C0_REF_CTRL__SRCSEL {IOPLL} \ + CONFIG.PSU__CRL_APB__I2C1_REF_CTRL__ACT_FREQMHZ {100.000002} \ + CONFIG.PSU__CRL_APB__I2C1_REF_CTRL__DIVISOR0 {15} \ + CONFIG.PSU__CRL_APB__I2C1_REF_CTRL__DIVISOR1 {1} \ + CONFIG.PSU__CRL_APB__I2C1_REF_CTRL__FREQMHZ {100} \ + CONFIG.PSU__CRL_APB__I2C1_REF_CTRL__SRCSEL {IOPLL} \ + CONFIG.PSU__CRL_APB__IOPLL_CTRL__DIV2 {1} \ + CONFIG.PSU__CRL_APB__IOPLL_CTRL__FBDIV {90} \ + CONFIG.PSU__CRL_APB__IOPLL_CTRL__FRACDATA {0.000000} \ + CONFIG.PSU__CRL_APB__IOPLL_CTRL__SRCSEL {PSS_REF_CLK} \ + CONFIG.PSU__CRL_APB__IOPLL_FRAC_CFG__ENABLED {0} \ + CONFIG.PSU__CRL_APB__IOPLL_TO_FPD_CTRL__DIVISOR0 {3} \ + CONFIG.PSU__CRL_APB__IOU_SWITCH_CTRL__ACT_FREQMHZ {250.000005} \ + CONFIG.PSU__CRL_APB__IOU_SWITCH_CTRL__DIVISOR0 {6} \ + CONFIG.PSU__CRL_APB__IOU_SWITCH_CTRL__FREQMHZ {250} \ + CONFIG.PSU__CRL_APB__IOU_SWITCH_CTRL__SRCSEL {IOPLL} \ + CONFIG.PSU__CRL_APB__LPD_LSBUS_CTRL__ACT_FREQMHZ {100.000002} \ + CONFIG.PSU__CRL_APB__LPD_LSBUS_CTRL__DIVISOR0 {15} \ + CONFIG.PSU__CRL_APB__LPD_LSBUS_CTRL__FREQMHZ {100} \ + CONFIG.PSU__CRL_APB__LPD_LSBUS_CTRL__SRCSEL {IOPLL} \ + CONFIG.PSU__CRL_APB__LPD_SWITCH_CTRL__ACT_FREQMHZ {500.000010} \ + CONFIG.PSU__CRL_APB__LPD_SWITCH_CTRL__DIVISOR0 {3} \ + CONFIG.PSU__CRL_APB__LPD_SWITCH_CTRL__FREQMHZ {500} \ + CONFIG.PSU__CRL_APB__LPD_SWITCH_CTRL__SRCSEL {IOPLL} \ + CONFIG.PSU__CRL_APB__NAND_REF_CTRL__DIVISOR0 {15} \ + CONFIG.PSU__CRL_APB__NAND_REF_CTRL__DIVISOR1 {1} \ + CONFIG.PSU__CRL_APB__PCAP_CTRL__ACT_FREQMHZ {187.500004} \ + CONFIG.PSU__CRL_APB__PCAP_CTRL__DIVISOR0 {8} \ + CONFIG.PSU__CRL_APB__PCAP_CTRL__FREQMHZ {200} \ + CONFIG.PSU__CRL_APB__PCAP_CTRL__SRCSEL {IOPLL} \ + CONFIG.PSU__CRL_APB__PL0_REF_CTRL__ACT_FREQMHZ {100.000002} \ + CONFIG.PSU__CRL_APB__PL0_REF_CTRL__DIVISOR0 {15} \ + CONFIG.PSU__CRL_APB__PL0_REF_CTRL__DIVISOR1 {1} \ + CONFIG.PSU__CRL_APB__PL0_REF_CTRL__FREQMHZ {100} \ + CONFIG.PSU__CRL_APB__PL0_REF_CTRL__SRCSEL {IOPLL} \ + CONFIG.PSU__CRL_APB__PL1_REF_CTRL__DIVISOR0 {4} \ + CONFIG.PSU__CRL_APB__PL1_REF_CTRL__DIVISOR1 {1} \ + CONFIG.PSU__CRL_APB__PL2_REF_CTRL__DIVISOR0 {4} \ + CONFIG.PSU__CRL_APB__PL2_REF_CTRL__DIVISOR1 {1} \ + CONFIG.PSU__CRL_APB__PL3_REF_CTRL__DIVISOR0 {4} \ + CONFIG.PSU__CRL_APB__PL3_REF_CTRL__DIVISOR1 {1} \ + CONFIG.PSU__CRL_APB__QSPI_REF_CTRL__DIVISOR0 {5} \ + CONFIG.PSU__CRL_APB__QSPI_REF_CTRL__DIVISOR1 {1} \ + CONFIG.PSU__CRL_APB__QSPI_REF_CTRL__FREQMHZ {125} \ + CONFIG.PSU__CRL_APB__QSPI_REF_CTRL__SRCSEL {IOPLL} \ + CONFIG.PSU__CRL_APB__RPLL_CTRL__DIV2 {1} \ + CONFIG.PSU__CRL_APB__RPLL_CTRL__FBDIV {72} \ + CONFIG.PSU__CRL_APB__RPLL_CTRL__FRACDATA {0.000000} \ + CONFIG.PSU__CRL_APB__RPLL_CTRL__SRCSEL {PSS_REF_CLK} \ + CONFIG.PSU__CRL_APB__RPLL_FRAC_CFG__ENABLED {0} \ + CONFIG.PSU__CRL_APB__RPLL_TO_FPD_CTRL__DIVISOR0 {3} \ + CONFIG.PSU__CRL_APB__SDIO0_REF_CTRL__ACT_FREQMHZ {200.000004} \ + CONFIG.PSU__CRL_APB__SDIO0_REF_CTRL__DIVISOR0 {6} \ + CONFIG.PSU__CRL_APB__SDIO0_REF_CTRL__DIVISOR1 {1} \ + CONFIG.PSU__CRL_APB__SDIO1_REF_CTRL__ACT_FREQMHZ {187.500004} \ + CONFIG.PSU__CRL_APB__SDIO1_REF_CTRL__DIVISOR0 {8} \ + CONFIG.PSU__CRL_APB__SDIO1_REF_CTRL__DIVISOR1 {1} \ + CONFIG.PSU__CRL_APB__SDIO1_REF_CTRL__FREQMHZ {200} \ + CONFIG.PSU__CRL_APB__SDIO1_REF_CTRL__SRCSEL {IOPLL} \ + CONFIG.PSU__CRL_APB__SPI0_REF_CTRL__ACT_FREQMHZ {200.000004} \ + CONFIG.PSU__CRL_APB__SPI0_REF_CTRL__DIVISOR0 {6} \ + CONFIG.PSU__CRL_APB__SPI0_REF_CTRL__DIVISOR1 {1} \ + CONFIG.PSU__CRL_APB__SPI1_REF_CTRL__ACT_FREQMHZ {200.000004} \ + CONFIG.PSU__CRL_APB__SPI1_REF_CTRL__DIVISOR0 {6} \ + CONFIG.PSU__CRL_APB__SPI1_REF_CTRL__DIVISOR1 {1} \ + CONFIG.PSU__CRL_APB__TIMESTAMP_REF_CTRL__ACT_FREQMHZ {100.000002} \ + CONFIG.PSU__CRL_APB__TIMESTAMP_REF_CTRL__DIVISOR0 {15} \ + CONFIG.PSU__CRL_APB__TIMESTAMP_REF_CTRL__FREQMHZ {100} \ + CONFIG.PSU__CRL_APB__TIMESTAMP_REF_CTRL__SRCSEL {IOPLL} \ + CONFIG.PSU__CRL_APB__UART0_REF_CTRL__ACT_FREQMHZ {100.000002} \ + CONFIG.PSU__CRL_APB__UART0_REF_CTRL__DIVISOR0 {15} \ + CONFIG.PSU__CRL_APB__UART0_REF_CTRL__DIVISOR1 {1} \ + CONFIG.PSU__CRL_APB__UART0_REF_CTRL__FREQMHZ {100} \ + CONFIG.PSU__CRL_APB__UART0_REF_CTRL__SRCSEL {IOPLL} \ + CONFIG.PSU__CRL_APB__UART1_REF_CTRL__ACT_FREQMHZ {100.000002} \ + CONFIG.PSU__CRL_APB__UART1_REF_CTRL__DIVISOR0 {15} \ + CONFIG.PSU__CRL_APB__UART1_REF_CTRL__DIVISOR1 {1} \ + CONFIG.PSU__CRL_APB__UART1_REF_CTRL__FREQMHZ {100} \ + CONFIG.PSU__CRL_APB__UART1_REF_CTRL__SRCSEL {IOPLL} \ + CONFIG.PSU__CRL_APB__USB0_BUS_REF_CTRL__ACT_FREQMHZ {250.000005} \ + CONFIG.PSU__CRL_APB__USB0_BUS_REF_CTRL__DIVISOR0 {6} \ + CONFIG.PSU__CRL_APB__USB0_BUS_REF_CTRL__DIVISOR1 {1} \ + CONFIG.PSU__CRL_APB__USB0_BUS_REF_CTRL__FREQMHZ {250} \ + CONFIG.PSU__CRL_APB__USB0_BUS_REF_CTRL__SRCSEL {IOPLL} \ + CONFIG.PSU__CRL_APB__USB1_BUS_REF_CTRL__ACT_FREQMHZ {250.000005} \ + CONFIG.PSU__CRL_APB__USB1_BUS_REF_CTRL__DIVISOR0 {6} \ + CONFIG.PSU__CRL_APB__USB1_BUS_REF_CTRL__DIVISOR1 {1} \ + CONFIG.PSU__CRL_APB__USB3_DUAL_REF_CTRL__ACT_FREQMHZ {20.000000} \ + CONFIG.PSU__CRL_APB__USB3_DUAL_REF_CTRL__DIVISOR0 {25} \ + CONFIG.PSU__CRL_APB__USB3_DUAL_REF_CTRL__DIVISOR1 {3} \ + CONFIG.PSU__CRL_APB__USB3_DUAL_REF_CTRL__FREQMHZ {20} \ + CONFIG.PSU__CRL_APB__USB3_DUAL_REF_CTRL__SRCSEL {IOPLL} \ + CONFIG.PSU__CRL_APB__USB3__ENABLE {1} \ + CONFIG.PSU__CSUPMU__PERIPHERAL__VALID {1} \ + CONFIG.PSU__DDRC__ADDR_MIRROR {1} \ + CONFIG.PSU__DDRC__AL {0} \ + CONFIG.PSU__DDRC__BANK_ADDR_COUNT {3} \ + CONFIG.PSU__DDRC__BG_ADDR_COUNT {NA} \ + CONFIG.PSU__DDRC__BRC_MAPPING {ROW_BANK_COL} \ + CONFIG.PSU__DDRC__BUS_WIDTH {32 Bit} \ + CONFIG.PSU__DDRC__CL {NA} \ + CONFIG.PSU__DDRC__CLOCK_STOP_EN {0} \ + CONFIG.PSU__DDRC__COL_ADDR_COUNT {10} \ + CONFIG.PSU__DDRC__COMPONENTS {Components} \ + CONFIG.PSU__DDRC__CWL {NA} \ + CONFIG.PSU__DDRC__DDR4_ADDR_MAPPING {NA} \ + CONFIG.PSU__DDRC__DDR4_CAL_MODE_ENABLE {NA} \ + CONFIG.PSU__DDRC__DDR4_CRC_CONTROL {NA} \ + CONFIG.PSU__DDRC__DDR4_MAXPWR_SAVING_EN {NA} \ + CONFIG.PSU__DDRC__DDR4_T_REF_MODE {NA} \ + CONFIG.PSU__DDRC__DDR4_T_REF_RANGE {NA} \ + CONFIG.PSU__DDRC__DEEP_PWR_DOWN_EN {0} \ + CONFIG.PSU__DDRC__DEVICE_CAPACITY {16384 MBits} \ + CONFIG.PSU__DDRC__DIMM_ADDR_MIRROR {0} \ + CONFIG.PSU__DDRC__DM_DBI {DM_NO_DBI} \ + CONFIG.PSU__DDRC__DQMAP_0_3 {0} \ + CONFIG.PSU__DDRC__DQMAP_12_15 {0} \ + CONFIG.PSU__DDRC__DQMAP_16_19 {0} \ + CONFIG.PSU__DDRC__DQMAP_20_23 {0} \ + CONFIG.PSU__DDRC__DQMAP_24_27 {0} \ + CONFIG.PSU__DDRC__DQMAP_28_31 {0} \ + CONFIG.PSU__DDRC__DQMAP_32_35 {0} \ + CONFIG.PSU__DDRC__DQMAP_36_39 {0} \ + CONFIG.PSU__DDRC__DQMAP_40_43 {0} \ + CONFIG.PSU__DDRC__DQMAP_44_47 {0} \ + CONFIG.PSU__DDRC__DQMAP_48_51 {0} \ + CONFIG.PSU__DDRC__DQMAP_4_7 {0} \ + CONFIG.PSU__DDRC__DQMAP_52_55 {0} \ + CONFIG.PSU__DDRC__DQMAP_56_59 {0} \ + CONFIG.PSU__DDRC__DQMAP_60_63 {0} \ + CONFIG.PSU__DDRC__DQMAP_64_67 {0} \ + CONFIG.PSU__DDRC__DQMAP_68_71 {0} \ + CONFIG.PSU__DDRC__DQMAP_8_11 {0} \ + CONFIG.PSU__DDRC__DRAM_WIDTH {32 Bits} \ + CONFIG.PSU__DDRC__ECC {Disabled} \ + CONFIG.PSU__DDRC__ENABLE_2T_TIMING {0} \ + CONFIG.PSU__DDRC__ENABLE_DP_SWITCH {1} \ + CONFIG.PSU__DDRC__ENABLE_LP4_HAS_ECC_COMP {0} \ + CONFIG.PSU__DDRC__ENABLE_LP4_SLOWBOOT {0} \ + CONFIG.PSU__DDRC__FGRM {NA} \ + CONFIG.PSU__DDRC__LP_ASR {NA} \ + CONFIG.PSU__DDRC__MEMORY_TYPE {LPDDR 4} \ + CONFIG.PSU__DDRC__PARITY_ENABLE {NA} \ + CONFIG.PSU__DDRC__PER_BANK_REFRESH {0} \ + CONFIG.PSU__DDRC__PHY_DBI_MODE {0} \ + CONFIG.PSU__DDRC__RANK_ADDR_COUNT {0} \ + CONFIG.PSU__DDRC__ROW_ADDR_COUNT {16} \ + CONFIG.PSU__DDRC__SB_TARGET {NA} \ + CONFIG.PSU__DDRC__SELF_REF_ABORT {NA} \ + CONFIG.PSU__DDRC__SPEED_BIN {LPDDR4_1066} \ + CONFIG.PSU__DDRC__STATIC_RD_MODE {0} \ + CONFIG.PSU__DDRC__TRAIN_DATA_EYE {1} \ + CONFIG.PSU__DDRC__TRAIN_READ_GATE {1} \ + CONFIG.PSU__DDRC__TRAIN_WRITE_LEVEL {1} \ + CONFIG.PSU__DDRC__T_FAW {40.0} \ + CONFIG.PSU__DDRC__T_RAS_MIN {42} \ + CONFIG.PSU__DDRC__T_RC {63} \ + CONFIG.PSU__DDRC__T_RCD {15} \ + CONFIG.PSU__DDRC__T_RP {15} \ + CONFIG.PSU__DDRC__VENDOR_PART {OTHERS} \ + CONFIG.PSU__DDRC__VREF {0} \ + CONFIG.PSU__DDR_HIGH_ADDRESS_GUI_ENABLE {0} \ + CONFIG.PSU__DDR_QOS_ENABLE {1} \ + CONFIG.PSU__DDR_QOS_HP0_RDQOS {7} \ + CONFIG.PSU__DDR_QOS_HP0_WRQOS {15} \ + CONFIG.PSU__DDR_QOS_HP1_RDQOS {3} \ + CONFIG.PSU__DDR_QOS_HP1_WRQOS {3} \ + CONFIG.PSU__DDR_QOS_HP2_RDQOS {3} \ + CONFIG.PSU__DDR_QOS_HP2_WRQOS {3} \ + CONFIG.PSU__DDR_QOS_HP3_RDQOS {3} \ + CONFIG.PSU__DDR_QOS_HP3_WRQOS {3} \ + CONFIG.PSU__DDR_QOS_PORT0_TYPE {Low Latency} \ + CONFIG.PSU__DDR_QOS_PORT1_VN1_TYPE {Low Latency} \ + CONFIG.PSU__DDR_QOS_PORT1_VN2_TYPE {Best Effort} \ + CONFIG.PSU__DDR_QOS_PORT2_VN1_TYPE {Low Latency} \ + CONFIG.PSU__DDR_QOS_PORT2_VN2_TYPE {Best Effort} \ + CONFIG.PSU__DDR_QOS_PORT3_TYPE {Video Traffic} \ + CONFIG.PSU__DDR_QOS_PORT4_TYPE {Best Effort} \ + CONFIG.PSU__DDR_QOS_PORT5_TYPE {Best Effort} \ + CONFIG.PSU__DDR_QOS_RD_HPR_THRSHLD {0} \ + CONFIG.PSU__DDR_QOS_RD_LPR_THRSHLD {16} \ + CONFIG.PSU__DDR_QOS_WR_THRSHLD {16} \ + CONFIG.PSU__DDR__INTERFACE__FREQMHZ {266.500} \ + CONFIG.PSU__DISPLAYPORT__LANE0__ENABLE {1} \ + CONFIG.PSU__DISPLAYPORT__LANE0__IO {GT Lane1} \ + CONFIG.PSU__DISPLAYPORT__LANE1__ENABLE {1} \ + CONFIG.PSU__DISPLAYPORT__LANE1__IO {GT Lane0} \ + CONFIG.PSU__DISPLAYPORT__PERIPHERAL__ENABLE {1} \ + CONFIG.PSU__DLL__ISUSED {1} \ + CONFIG.PSU__DPAUX__PERIPHERAL__ENABLE {1} \ + CONFIG.PSU__DPAUX__PERIPHERAL__IO {MIO 27 .. 30} \ + CONFIG.PSU__DP__LANE_SEL {Dual Lower} \ + CONFIG.PSU__DP__REF_CLK_FREQ {27} \ + CONFIG.PSU__DP__REF_CLK_SEL {Ref Clk1} \ + CONFIG.PSU__ENET3__FIFO__ENABLE {0} \ + CONFIG.PSU__ENET3__GRP_MDIO__ENABLE {0} \ + CONFIG.PSU__ENET3__PERIPHERAL__ENABLE {0} \ + CONFIG.PSU__ENET3__PTP__ENABLE {0} \ + CONFIG.PSU__ENET3__TSU__ENABLE {0} \ + CONFIG.PSU__FPD_SLCR__WDT1__ACT_FREQMHZ {100.000000} \ + CONFIG.PSU__FPD_SLCR__WDT1__FREQMHZ {100.000000} \ + CONFIG.PSU__FPD_SLCR__WDT_CLK_SEL__SELECT {APB} \ + CONFIG.PSU__FPGA_PL0_ENABLE {1} \ + CONFIG.PSU__GEM3_COHERENCY {0} \ + CONFIG.PSU__GPIO0_MIO__IO {MIO 0 .. 25} \ + CONFIG.PSU__GPIO0_MIO__PERIPHERAL__ENABLE {1} \ + CONFIG.PSU__GPIO1_MIO__IO {MIO 26 .. 51} \ + CONFIG.PSU__GPIO1_MIO__PERIPHERAL__ENABLE {1} \ + CONFIG.PSU__GPIO2_MIO__IO {MIO 52 .. 77} \ + CONFIG.PSU__GPIO2_MIO__PERIPHERAL__ENABLE {1} \ + CONFIG.PSU__GT__LINK_SPEED {HBR} \ + CONFIG.PSU__GT__PRE_EMPH_LVL_4 {0} \ + CONFIG.PSU__GT__VLT_SWNG_LVL_4 {0} \ + CONFIG.PSU__I2C0__PERIPHERAL__ENABLE {0} \ + CONFIG.PSU__I2C1__PERIPHERAL__ENABLE {1} \ + CONFIG.PSU__I2C1__PERIPHERAL__IO {MIO 4 .. 5} \ + CONFIG.PSU__IOU_SLCR__IOU_TTC_APB_CLK__TTC0_SEL {APB} \ + CONFIG.PSU__IOU_SLCR__IOU_TTC_APB_CLK__TTC1_SEL {APB} \ + CONFIG.PSU__IOU_SLCR__IOU_TTC_APB_CLK__TTC2_SEL {APB} \ + CONFIG.PSU__IOU_SLCR__IOU_TTC_APB_CLK__TTC3_SEL {APB} \ + CONFIG.PSU__IOU_SLCR__TTC0__ACT_FREQMHZ {100.000000} \ + CONFIG.PSU__IOU_SLCR__TTC0__FREQMHZ {100.000000} \ + CONFIG.PSU__IOU_SLCR__TTC1__ACT_FREQMHZ {100.000000} \ + CONFIG.PSU__IOU_SLCR__TTC1__FREQMHZ {100.000000} \ + CONFIG.PSU__IOU_SLCR__TTC2__ACT_FREQMHZ {100.000000} \ + CONFIG.PSU__IOU_SLCR__TTC2__FREQMHZ {100.000000} \ + CONFIG.PSU__IOU_SLCR__TTC3__ACT_FREQMHZ {100.000000} \ + CONFIG.PSU__IOU_SLCR__TTC3__FREQMHZ {100.000000} \ + CONFIG.PSU__IOU_SLCR__WDT0__ACT_FREQMHZ {100.000000} \ + CONFIG.PSU__IOU_SLCR__WDT0__FREQMHZ {100.000000} \ + CONFIG.PSU__IOU_SLCR__WDT_CLK_SEL__SELECT {APB} \ + CONFIG.PSU__LPD_SLCR__CSUPMU__ACT_FREQMHZ {100.000000} \ + CONFIG.PSU__LPD_SLCR__CSUPMU__FREQMHZ {100.000000} \ + CONFIG.PSU__MAXIGP0__DATA_WIDTH {128} \ + CONFIG.PSU__MAXIGP1__DATA_WIDTH {128} \ + CONFIG.PSU__MAXIGP2__DATA_WIDTH {32} \ + CONFIG.PSU__OVERRIDE__BASIC_CLOCK {0} \ + CONFIG.PSU__PL_CLK0_BUF {TRUE} \ + CONFIG.PSU__PMU_COHERENCY {0} \ + CONFIG.PSU__PMU__AIBACK__ENABLE {0} \ + CONFIG.PSU__PMU__EMIO_GPI__ENABLE {0} \ + CONFIG.PSU__PMU__EMIO_GPO__ENABLE {0} \ + CONFIG.PSU__PMU__GPI0__ENABLE {1} \ + CONFIG.PSU__PMU__GPI0__IO {MIO 26} \ + CONFIG.PSU__PMU__GPI1__ENABLE {0} \ + CONFIG.PSU__PMU__GPI2__ENABLE {0} \ + CONFIG.PSU__PMU__GPI3__ENABLE {0} \ + CONFIG.PSU__PMU__GPI4__ENABLE {0} \ + CONFIG.PSU__PMU__GPI5__ENABLE {0} \ + CONFIG.PSU__PMU__GPO0__ENABLE {1} \ + CONFIG.PSU__PMU__GPO0__IO {MIO 32} \ + CONFIG.PSU__PMU__GPO1__ENABLE {1} \ + CONFIG.PSU__PMU__GPO1__IO {MIO 33} \ + CONFIG.PSU__PMU__GPO2__ENABLE {1} \ + CONFIG.PSU__PMU__GPO2__IO {MIO 34} \ + CONFIG.PSU__PMU__GPO2__POLARITY {high} \ + CONFIG.PSU__PMU__GPO3__ENABLE {0} \ + CONFIG.PSU__PMU__GPO4__ENABLE {0} \ + CONFIG.PSU__PMU__GPO5__ENABLE {0} \ + CONFIG.PSU__PMU__PERIPHERAL__ENABLE {1} \ + CONFIG.PSU__PMU__PLERROR__ENABLE {0} \ + CONFIG.PSU__PRESET_APPLIED {1} \ + CONFIG.PSU__PROTECTION__MASTERS {USB1:NonSecure;1|USB0:NonSecure;1|S_AXI_LPD:NA;0|S_AXI_HPC1_FPD:NA;0|S_AXI_HPC0_FPD:NA;0|S_AXI_HP3_FPD:NA;0|S_AXI_HP2_FPD:NA;0|S_AXI_HP1_FPD:NA;0|S_AXI_HP0_FPD:NA;0|S_AXI_ACP:NA;0|S_AXI_ACE:NA;0|SD1:NonSecure;1|SD0:NonSecure;1|SATA1:NonSecure;0|SATA0:NonSecure;0|RPU1:Secure;1|RPU0:Secure;1|QSPI:NonSecure;0|PMU:NA;1|PCIe:NonSecure;0|NAND:NonSecure;0|LDMA:NonSecure;1|GPU:NonSecure;1|GEM3:NonSecure;0|GEM2:NonSecure;0|GEM1:NonSecure;0|GEM0:NonSecure;0|FDMA:NonSecure;1|DP:NonSecure;1|DAP:NA;1|Coresight:NA;1|CSU:NA;1|APU:NA;1} \ + CONFIG.PSU__PROTECTION__SLAVES {LPD;USB3_1_XHCI;FE300000;FE3FFFFF;1|LPD;USB3_1;FF9E0000;FF9EFFFF;1|LPD;USB3_0_XHCI;FE200000;FE2FFFFF;1|LPD;USB3_0;FF9D0000;FF9DFFFF;1|LPD;UART1;FF010000;FF01FFFF;1|LPD;UART0;FF000000;FF00FFFF;1|LPD;TTC3;FF140000;FF14FFFF;1|LPD;TTC2;FF130000;FF13FFFF;1|LPD;TTC1;FF120000;FF12FFFF;1|LPD;TTC0;FF110000;FF11FFFF;1|FPD;SWDT1;FD4D0000;FD4DFFFF;1|LPD;SWDT0;FF150000;FF15FFFF;1|LPD;SPI1;FF050000;FF05FFFF;1|LPD;SPI0;FF040000;FF04FFFF;1|FPD;SMMU_REG;FD5F0000;FD5FFFFF;1|FPD;SMMU;FD800000;FDFFFFFF;1|FPD;SIOU;FD3D0000;FD3DFFFF;1|FPD;SERDES;FD400000;FD47FFFF;1|LPD;SD1;FF170000;FF17FFFF;1|LPD;SD0;FF160000;FF16FFFF;1|FPD;SATA;FD0C0000;FD0CFFFF;0|LPD;RTC;FFA60000;FFA6FFFF;1|LPD;RSA_CORE;FFCE0000;FFCEFFFF;1|LPD;RPU;FF9A0000;FF9AFFFF;1|FPD;RCPU_GIC;F9000000;F900FFFF;1|LPD;R5_TCM_RAM_GLOBAL;FFE00000;FFE3FFFF;1|LPD;R5_1_Instruction_Cache;FFEC0000;FFECFFFF;1|LPD;R5_1_Data_Cache;FFED0000;FFEDFFFF;1|LPD;R5_1_BTCM_GLOBAL;FFEB0000;FFEBFFFF;1|LPD;R5_1_ATCM_GLOBAL;FFE90000;FFE9FFFF;1|LPD;R5_0_Instruction_Cache;FFE40000;FFE4FFFF;1|LPD;R5_0_Data_Cache;FFE50000;FFE5FFFF;1|LPD;R5_0_BTCM_GLOBAL;FFE20000;FFE2FFFF;1|LPD;R5_0_ATCM_GLOBAL;FFE00000;FFE0FFFF;1|LPD;QSPI_Linear_Address;C0000000;DFFFFFFF;1|LPD;QSPI;FF0F0000;FF0FFFFF;0|LPD;PMU_RAM;FFDC0000;FFDDFFFF;1|LPD;PMU_GLOBAL;FFD80000;FFDBFFFF;1|FPD;PCIE_MAIN;FD0E0000;FD0EFFFF;0|FPD;PCIE_LOW;E0000000;EFFFFFFF;0|FPD;PCIE_HIGH2;8000000000;BFFFFFFFFF;0|FPD;PCIE_HIGH1;600000000;7FFFFFFFF;0|FPD;PCIE_DMA;FD0F0000;FD0FFFFF;0|FPD;PCIE_ATTRIB;FD480000;FD48FFFF;0|LPD;OCM_XMPU_CFG;FFA70000;FFA7FFFF;1|LPD;OCM_SLCR;FF960000;FF96FFFF;1|OCM;OCM;FFFC0000;FFFFFFFF;1|LPD;NAND;FF100000;FF10FFFF;0|LPD;MBISTJTAG;FFCF0000;FFCFFFFF;1|LPD;LPD_XPPU_SINK;FF9C0000;FF9CFFFF;1|LPD;LPD_XPPU;FF980000;FF98FFFF;1|LPD;LPD_SLCR_SECURE;FF4B0000;FF4DFFFF;1|LPD;LPD_SLCR;FF410000;FF4AFFFF;1|LPD;LPD_GPV;FE100000;FE1FFFFF;1|LPD;LPD_DMA_7;FFAF0000;FFAFFFFF;1|LPD;LPD_DMA_6;FFAE0000;FFAEFFFF;1|LPD;LPD_DMA_5;FFAD0000;FFADFFFF;1|LPD;LPD_DMA_4;FFAC0000;FFACFFFF;1|LPD;LPD_DMA_3;FFAB0000;FFABFFFF;1|LPD;LPD_DMA_2;FFAA0000;FFAAFFFF;1|LPD;LPD_DMA_1;FFA90000;FFA9FFFF;1|LPD;LPD_DMA_0;FFA80000;FFA8FFFF;1|LPD;IPI_CTRL;FF380000;FF3FFFFF;1|LPD;IOU_SLCR;FF180000;FF23FFFF;1|LPD;IOU_SECURE_SLCR;FF240000;FF24FFFF;1|LPD;IOU_SCNTRS;FF260000;FF26FFFF;1|LPD;IOU_SCNTR;FF250000;FF25FFFF;1|LPD;IOU_GPV;FE000000;FE0FFFFF;1|LPD;I2C1;FF030000;FF03FFFF;1|LPD;I2C0;FF020000;FF02FFFF;0|FPD;GPU;FD4B0000;FD4BFFFF;1|LPD;GPIO;FF0A0000;FF0AFFFF;1|LPD;GEM3;FF0E0000;FF0EFFFF;0|LPD;GEM2;FF0D0000;FF0DFFFF;0|LPD;GEM1;FF0C0000;FF0CFFFF;0|LPD;GEM0;FF0B0000;FF0BFFFF;0|FPD;FPD_XMPU_SINK;FD4F0000;FD4FFFFF;1|FPD;FPD_XMPU_CFG;FD5D0000;FD5DFFFF;1|FPD;FPD_SLCR_SECURE;FD690000;FD6CFFFF;1|FPD;FPD_SLCR;FD610000;FD68FFFF;1|FPD;FPD_GPV;FD700000;FD7FFFFF;1|FPD;FPD_DMA_CH7;FD570000;FD57FFFF;1|FPD;FPD_DMA_CH6;FD560000;FD56FFFF;1|FPD;FPD_DMA_CH5;FD550000;FD55FFFF;1|FPD;FPD_DMA_CH4;FD540000;FD54FFFF;1|FPD;FPD_DMA_CH3;FD530000;FD53FFFF;1|FPD;FPD_DMA_CH2;FD520000;FD52FFFF;1|FPD;FPD_DMA_CH1;FD510000;FD51FFFF;1|FPD;FPD_DMA_CH0;FD500000;FD50FFFF;1|LPD;EFUSE;FFCC0000;FFCCFFFF;1|FPD;Display Port;FD4A0000;FD4AFFFF;1|FPD;DPDMA;FD4C0000;FD4CFFFF;1|FPD;DDR_XMPU5_CFG;FD050000;FD05FFFF;1|FPD;DDR_XMPU4_CFG;FD040000;FD04FFFF;1|FPD;DDR_XMPU3_CFG;FD030000;FD03FFFF;1|FPD;DDR_XMPU2_CFG;FD020000;FD02FFFF;1|FPD;DDR_XMPU1_CFG;FD010000;FD01FFFF;1|FPD;DDR_XMPU0_CFG;FD000000;FD00FFFF;1|FPD;DDR_QOS_CTRL;FD090000;FD09FFFF;1|FPD;DDR_PHY;FD080000;FD08FFFF;1|DDR;DDR_LOW;0;7FFFFFFF;1|DDR;DDR_HIGH;800000000;800000000;0|FPD;DDDR_CTRL;FD070000;FD070FFF;1|LPD;Coresight;FE800000;FEFFFFFF;1|LPD;CSU_DMA;FFC80000;FFC9FFFF;1|LPD;CSU;FFCA0000;FFCAFFFF;0|LPD;CRL_APB;FF5E0000;FF85FFFF;1|FPD;CRF_APB;FD1A0000;FD2DFFFF;1|FPD;CCI_REG;FD5E0000;FD5EFFFF;1|FPD;CCI_GPV;FD6E0000;FD6EFFFF;1|LPD;CAN1;FF070000;FF07FFFF;0|LPD;CAN0;FF060000;FF06FFFF;0|FPD;APU;FD5C0000;FD5CFFFF;1|LPD;APM_INTC_IOU;FFA20000;FFA2FFFF;1|LPD;APM_FPD_LPD;FFA30000;FFA3FFFF;1|FPD;APM_5;FD490000;FD49FFFF;1|FPD;APM_0;FD0B0000;FD0BFFFF;1|LPD;APM2;FFA10000;FFA1FFFF;1|LPD;APM1;FFA00000;FFA0FFFF;1|LPD;AMS;FFA50000;FFA5FFFF;1|FPD;AFI_5;FD3B0000;FD3BFFFF;1|FPD;AFI_4;FD3A0000;FD3AFFFF;1|FPD;AFI_3;FD390000;FD39FFFF;1|FPD;AFI_2;FD380000;FD38FFFF;1|FPD;AFI_1;FD370000;FD37FFFF;1|FPD;AFI_0;FD360000;FD36FFFF;1|LPD;AFIFM6;FF9B0000;FF9BFFFF;1|FPD;ACPU_GIC;F9000000;F907FFFF;1} \ + CONFIG.PSU__PSS_REF_CLK__FREQMHZ {33.333333} \ + CONFIG.PSU__QSPI_COHERENCY {0} \ + CONFIG.PSU__QSPI__GRP_FBCLK__ENABLE {0} \ + CONFIG.PSU__QSPI__PERIPHERAL__ENABLE {0} \ + CONFIG.PSU__SATA__LANE0__ENABLE {0} \ + CONFIG.PSU__SATA__LANE1__ENABLE {0} \ + CONFIG.PSU__SATA__PERIPHERAL__ENABLE {0} \ + CONFIG.PSU__SD0_COHERENCY {0} \ + CONFIG.PSU__SD0__DATA_TRANSFER_MODE {4Bit} \ + CONFIG.PSU__SD0__GRP_CD__ENABLE {1} \ + CONFIG.PSU__SD0__GRP_CD__IO {MIO 24} \ + CONFIG.PSU__SD0__GRP_POW__ENABLE {0} \ + CONFIG.PSU__SD0__GRP_WP__ENABLE {0} \ + CONFIG.PSU__SD0__PERIPHERAL__ENABLE {1} \ + CONFIG.PSU__SD0__PERIPHERAL__IO {MIO 13 .. 16 21 22} \ + CONFIG.PSU__SD0__RESET__ENABLE {0} \ + CONFIG.PSU__SD0__SLOT_TYPE {SD 2.0} \ + CONFIG.PSU__SD1_COHERENCY {0} \ + CONFIG.PSU__SD1__DATA_TRANSFER_MODE {4Bit} \ + CONFIG.PSU__SD1__GRP_CD__ENABLE {0} \ + CONFIG.PSU__SD1__GRP_POW__ENABLE {0} \ + CONFIG.PSU__SD1__GRP_WP__ENABLE {0} \ + CONFIG.PSU__SD1__PERIPHERAL__ENABLE {1} \ + CONFIG.PSU__SD1__PERIPHERAL__IO {MIO 46 .. 51} \ + CONFIG.PSU__SD1__RESET__ENABLE {0} \ + CONFIG.PSU__SD1__SLOT_TYPE {SD 2.0} \ + CONFIG.PSU__SPI0__GRP_SS0__ENABLE {1} \ + CONFIG.PSU__SPI0__GRP_SS0__IO {MIO 41} \ + CONFIG.PSU__SPI0__GRP_SS1__ENABLE {0} \ + CONFIG.PSU__SPI0__GRP_SS2__ENABLE {0} \ + CONFIG.PSU__SPI0__PERIPHERAL__ENABLE {1} \ + CONFIG.PSU__SPI0__PERIPHERAL__IO {MIO 38 .. 43} \ + CONFIG.PSU__SPI1__GRP_SS0__ENABLE {1} \ + CONFIG.PSU__SPI1__GRP_SS0__IO {MIO 9} \ + CONFIG.PSU__SPI1__GRP_SS1__ENABLE {0} \ + CONFIG.PSU__SPI1__GRP_SS2__ENABLE {0} \ + CONFIG.PSU__SPI1__PERIPHERAL__ENABLE {1} \ + CONFIG.PSU__SPI1__PERIPHERAL__IO {MIO 6 .. 11} \ + CONFIG.PSU__SWDT0__CLOCK__ENABLE {0} \ + CONFIG.PSU__SWDT0__PERIPHERAL__ENABLE {1} \ + CONFIG.PSU__SWDT0__RESET__ENABLE {0} \ + CONFIG.PSU__SWDT1__CLOCK__ENABLE {0} \ + CONFIG.PSU__SWDT1__PERIPHERAL__ENABLE {1} \ + CONFIG.PSU__SWDT1__RESET__ENABLE {0} \ + CONFIG.PSU__TTC0__CLOCK__ENABLE {0} \ + CONFIG.PSU__TTC0__PERIPHERAL__ENABLE {1} \ + CONFIG.PSU__TTC0__WAVEOUT__ENABLE {0} \ + CONFIG.PSU__TTC1__CLOCK__ENABLE {0} \ + CONFIG.PSU__TTC1__PERIPHERAL__ENABLE {1} \ + CONFIG.PSU__TTC1__WAVEOUT__ENABLE {0} \ + CONFIG.PSU__TTC2__CLOCK__ENABLE {0} \ + CONFIG.PSU__TTC2__PERIPHERAL__ENABLE {1} \ + CONFIG.PSU__TTC2__WAVEOUT__ENABLE {0} \ + CONFIG.PSU__TTC3__CLOCK__ENABLE {0} \ + CONFIG.PSU__TTC3__PERIPHERAL__ENABLE {1} \ + CONFIG.PSU__TTC3__WAVEOUT__ENABLE {0} \ + CONFIG.PSU__UART0__BAUD_RATE {115200} \ + CONFIG.PSU__UART0__MODEM__ENABLE {0} \ + CONFIG.PSU__UART0__PERIPHERAL__ENABLE {1} \ + CONFIG.PSU__UART0__PERIPHERAL__IO {MIO 2 .. 3} \ + CONFIG.PSU__UART1__BAUD_RATE {115200} \ + CONFIG.PSU__UART1__MODEM__ENABLE {0} \ + CONFIG.PSU__UART1__PERIPHERAL__ENABLE {1} \ + CONFIG.PSU__UART1__PERIPHERAL__IO {MIO 0 .. 1} \ + CONFIG.PSU__USB0_COHERENCY {0} \ + CONFIG.PSU__USB0__PERIPHERAL__ENABLE {1} \ + CONFIG.PSU__USB0__PERIPHERAL__IO {MIO 52 .. 63} \ + CONFIG.PSU__USB0__REF_CLK_FREQ {26} \ + CONFIG.PSU__USB0__REF_CLK_SEL {Ref Clk0} \ + CONFIG.PSU__USB1_COHERENCY {0} \ + CONFIG.PSU__USB1__PERIPHERAL__ENABLE {1} \ + CONFIG.PSU__USB1__PERIPHERAL__IO {MIO 64 .. 75} \ + CONFIG.PSU__USB1__REF_CLK_FREQ {26} \ + CONFIG.PSU__USB1__REF_CLK_SEL {Ref Clk0} \ + CONFIG.PSU__USB2_0__EMIO__ENABLE {0} \ + CONFIG.PSU__USB2_1__EMIO__ENABLE {0} \ + CONFIG.PSU__USB3_0__EMIO__ENABLE {0} \ + CONFIG.PSU__USB3_0__PERIPHERAL__ENABLE {1} \ + CONFIG.PSU__USB3_0__PERIPHERAL__IO {GT Lane2} \ + CONFIG.PSU__USB3_1__EMIO__ENABLE {0} \ + CONFIG.PSU__USB3_1__PERIPHERAL__ENABLE {1} \ + CONFIG.PSU__USB3_1__PERIPHERAL__IO {GT Lane3} \ + CONFIG.PSU__USE__IRQ0 {1} \ + CONFIG.PSU__USE__M_AXI_GP0 {1} \ + CONFIG.PSU__USE__M_AXI_GP1 {1} \ + CONFIG.PSU__USE__M_AXI_GP2 {0} \ + CONFIG.SUBPRESET1 {Custom} \ + ] $zynq_ultra_ps_e_0 + + # Create interface connections + connect_bd_intf_net -intf_net ps8_0_axi_periph_M00_AXI [get_bd_intf_pins ps8_0_axi_periph/M00_AXI] [get_bd_intf_pins pynqrouter_0/s_axi_AXI4LS] + connect_bd_intf_net -intf_net zynq_ultra_ps_e_0_M_AXI_HPM0_FPD [get_bd_intf_pins ps8_0_axi_periph/S00_AXI] [get_bd_intf_pins zynq_ultra_ps_e_0/M_AXI_HPM0_FPD] + connect_bd_intf_net -intf_net zynq_ultra_ps_e_0_M_AXI_HPM1_FPD [get_bd_intf_pins ps8_0_axi_periph/S01_AXI] [get_bd_intf_pins zynq_ultra_ps_e_0/M_AXI_HPM1_FPD] + + # Create port connections + connect_bd_net -net rst_ps8_0_100M_interconnect_aresetn [get_bd_pins ps8_0_axi_periph/ARESETN] [get_bd_pins rst_ps8_0_100M/interconnect_aresetn] + connect_bd_net -net rst_ps8_0_100M_peripheral_aresetn [get_bd_pins ps8_0_axi_periph/M00_ARESETN] [get_bd_pins ps8_0_axi_periph/S00_ARESETN] [get_bd_pins ps8_0_axi_periph/S01_ARESETN] [get_bd_pins pynqrouter_0/ap_rst_n] [get_bd_pins rst_ps8_0_100M/peripheral_aresetn] + connect_bd_net -net zynq_ultra_ps_e_0_pl_clk0 [get_bd_pins ps8_0_axi_periph/ACLK] [get_bd_pins ps8_0_axi_periph/M00_ACLK] [get_bd_pins ps8_0_axi_periph/S00_ACLK] [get_bd_pins ps8_0_axi_periph/S01_ACLK] [get_bd_pins pynqrouter_0/ap_clk] [get_bd_pins rst_ps8_0_100M/slowest_sync_clk] [get_bd_pins zynq_ultra_ps_e_0/maxihpm0_fpd_aclk] [get_bd_pins zynq_ultra_ps_e_0/maxihpm1_fpd_aclk] [get_bd_pins zynq_ultra_ps_e_0/pl_clk0] + connect_bd_net -net zynq_ultra_ps_e_0_pl_resetn0 [get_bd_pins rst_ps8_0_100M/ext_reset_in] [get_bd_pins zynq_ultra_ps_e_0/pl_resetn0] + + # Create address segments + create_bd_addr_seg -range 0x00040000 -offset 0xA0000000 [get_bd_addr_spaces zynq_ultra_ps_e_0/Data] [get_bd_addr_segs pynqrouter_0/s_axi_AXI4LS/Reg] SEG_pynqrouter_0_Reg + + + # Restore current instance + current_bd_instance $oldCurInst + + save_bd_design +} +# End of create_root_design() + + +################################################################## +# MAIN FLOW +################################################################## + +create_root_design "" + + diff --git a/hls_2018/router_04_boardstr/router.cpp b/hls_2018/router_04_boardstr/router.cpp index 9c739e2..367b122 100755 --- a/hls_2018/router_04_boardstr/router.cpp +++ b/hls_2018/router_04_boardstr/router.cpp @@ -164,13 +164,15 @@ bool pynqrouter(char boardstr[BOARDSTR_SIZE], char boardstr_high[BOARDSTR_SIZE], cout << "Rip-up Routing ..." << endl; #endif + ap_uint target = line_num - 1, next_target; + ROUTING: for (ap_uint<16> round = 0; round < 32768 /* = (2048 * 16) */; round++) { #pragma HLS LOOP_TRIPCOUNT min=1 max=32768 // Target line - ap_uint target = round % line_num; - ap_uint next_target = target + 1; + target = round % line_num; + next_target = target + 1; if (next_target == line_num) next_target = 0; #ifdef DEBUG_PRINT @@ -310,7 +312,7 @@ bool pynqrouter(char boardstr[BOARDSTR_SIZE], char boardstr_high[BOARDSTR_SIZE], else { p2 = s_idx[i+1]; } - if ((ap_uint)(p2 - p1) > 8192){ + if (i == target) { p2 = pointer; } OUTPUT_LINE_PATH: @@ -474,7 +476,7 @@ void pq_push(ap_uint<32> pq_nodes[MAX_PQ], ap_uint<16> priority, ap_uint<16> dat ap_uint p = (*pq_len) >> 1; // parent node PQ_PUSH_LOOP: while (i > 1 && (ap_uint<16>)(pq_nodes[p] & PQ_PRIORITY_MASK) >= priority) { -#pragma HLS LOOP_TRIPCOUNT min=0 max=15 +#pragma HLS LOOP_TRIPCOUNT min=0 max=16 /** Set!: min=0 max=PQ_BIT **/ pq_nodes[i] = pq_nodes[p]; i = p; @@ -497,7 +499,7 @@ void pq_pop(ap_uint<32> pq_nodes[MAX_PQ], ap_uint<16> *ret_priority, ap_uint<16> PQ_POP_LOOP: while (!(i >> (PQ_BIT-1))) { // (2018.08.24) Loop condition fixed -#pragma HLS LOOP_TRIPCOUNT min=1 max=15 +#pragma HLS LOOP_TRIPCOUNT min=1 max=16 /** Set!: min=0 max=PQ_BIT **/ ap_uint c1 = i << 1; // child node(left) ap_uint c2 = c1 + 1; // child node(right) diff --git a/hls_2018/router_04_boardstr/router.hpp b/hls_2018/router_04_boardstr/router.hpp index 3a30542..0c0452b 100755 --- a/hls_2018/router_04_boardstr/router.hpp +++ b/hls_2018/router_04_boardstr/router.hpp @@ -28,13 +28,13 @@ using namespace std; #define BITMASK_Z 7 // 0000 0000 0000 0111 #define MAX_CELLS 41472 // Max #cells (16bit) -#define MAX_LINES 1024 // Max #lines (10bit) +#define MAX_LINES 2048 // Max #lines (11bit) #define MAX_PQ 65536 // Queue size (16bit) -#define MAX_BUFFER 16384 // Line buffer size (14bit) +#define MAX_BUFFER 32768 // Line buffer size (15bit) #define CELL_BIT 16 -#define LINE_BIT 10 +#define LINE_BIT 11 #define PQ_BIT 16 -#define BUFF_BIT 14 +#define BUFF_BIT 15 #define PQ_PRIORITY_WIDTH 16 #define PQ_PRIORITY_MASK 65535 // 0000 0000 0000 0000 1111 1111 1111 1111 diff --git a/hls_2018/router_05/Makefile b/hls_2018/router_05/Makefile new file mode 100755 index 0000000..8f79e7a --- /dev/null +++ b/hls_2018/router_05/Makefile @@ -0,0 +1,20 @@ +TARGET = sim +OBJS = $(CPPS:.cpp=.o) +CPPS = $(wildcard *.cpp) +CXX = g++ +CXXFLAGS = -O3 -Wall -Wno-unknown-pragmas -Wno-unused-label -DSOFTWARE -DCALCTIME + +all: $(TARGET) + +$(TARGET): $(OBJS) + $(CXX) -O3 -o $@ $(OBJS) + +run: + python3 ../NLGenerator.py -x 20 -y 20 -z 6 -l 100;\ + python3 ./gen_boardstr.py Q-20x20x5_100_10.txt |\ + ./$(TARGET) - + + +clean: + rm *.o + rm $(TARGET) diff --git a/hls_2018/router_05/Makefile.cygwin b/hls_2018/router_05/Makefile.cygwin new file mode 100755 index 0000000..866fdcd --- /dev/null +++ b/hls_2018/router_05/Makefile.cygwin @@ -0,0 +1,14 @@ +TARGET = sim +OBJS = $(CPPS:.cpp=.o) +CPPS = $(wildcard *.cpp) +CXX = g++ +CXXFLAGS = -O3 -Wall -Wno-unknown-pragmas -Wno-unused-label -DSOFTWARE -DCALCTIME + +all: $(TARGET) + +$(TARGET): $(OBJS) + $(CXX) -O3 -Wl,--stack,33554432 -o $@ $(OBJS) + +clean: + rm *.o + rm $(TARGET) diff --git a/hls_2018/router_05/ap_int.h b/hls_2018/router_05/ap_int.h new file mode 100755 index 0000000..b8d9fdc --- /dev/null +++ b/hls_2018/router_05/ap_int.h @@ -0,0 +1,521 @@ +/* + * Copyright 2012 Xilinx, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __AESL_AP_SIM_H__ +#define __AESL_AP_SIM_H__ + +#ifndef __cplusplus +#error C++ is required to include this header file +#else + +#include "etc/ap_int_sim.h" +#include "etc/ap_fixed_sim.h" + +//Forward declaration +template class ap_fixed; +template class ap_ufixed; +template class ap_int; +template class ap_uint; + +//AP_INT +//-------------------------------------------------------- +template +class ap_int : public ap_private<_AP_W, true> { +#ifdef _MSC_VER +#pragma warning(disable: 4521 4522) +#endif /* #ifdef _MSC_VER */ +public: + typedef ap_private<_AP_W, true> Base; + + //Constructor + INLINE ap_int(): Base() {} + template + INLINE ap_int(const volatile ap_int<_AP_W2> &op):Base((const ap_private<_AP_W2,true> &)(op)) {} + + template + INLINE ap_int(const ap_int<_AP_W2> &op):Base((const ap_private<_AP_W2,true> &)(op)) {} + + template + INLINE ap_int(const ap_uint<_AP_W2> &op):Base((const ap_private<_AP_W2,false> &)(op)) {} + + template + INLINE ap_int(const volatile ap_uint<_AP_W2> &op):Base((const ap_private<_AP_W2,false> &)(op)) {} + + template + INLINE ap_int(const ap_range_ref<_AP_W2, _AP_S2>& ref):Base(ref) {} + + template + INLINE ap_int(const ap_bit_ref<_AP_W2, _AP_S2>& ref):Base(ref) {} + + template + INLINE ap_int(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& ref):Base(ref) {} + + template + INLINE ap_int(const ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op.to_ap_private()) {} + + template + INLINE ap_int(const ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op.to_ap_private()) {} + + template + INLINE ap_int(const volatile ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op.to_ap_private()) {} + + template + INLINE ap_int(const volatile ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op.to_ap_private()) {} + + template + INLINE ap_int(const ap_private<_AP_W2, _AP_S2>& op):Base(op) {} + + template + INLINE ap_int(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, + _AP_N2>& op):Base(op) {} + + template + INLINE ap_int(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, + _AP_N2>& op):Base(op) {} + + template + INLINE ap_int(const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& op):Base(op.to_ap_private()) {} + +#define CTOR(TYPE) \ + INLINE ap_int(TYPE v):Base(v) {} + CTOR(bool) + CTOR(signed char) + CTOR(unsigned char) + CTOR(short) + CTOR(unsigned short) + CTOR(int) + CTOR(unsigned int) + CTOR(long) + CTOR(unsigned long) + CTOR(unsigned long long) + CTOR(long long) + CTOR(float) + CTOR(double) + CTOR(const char*) + CTOR(const std::string&) +#undef CTOR + INLINE ap_int(const char* str, signed char rd):Base(str, rd) {} + //Assignment + //Another form of "write" + INLINE void operator = (const ap_int<_AP_W>& op2) volatile { + const_cast(this)->operator = (op2); + } + + INLINE void operator = (const volatile ap_int<_AP_W>& op2) volatile { + const_cast(this)->operator = (op2); + } + + INLINE ap_int<_AP_W>& operator = (const volatile ap_int<_AP_W>& op2) { + Base::operator = (const_cast& >(op2)); + return *this; + } + + INLINE ap_int<_AP_W>& operator = (const ap_int<_AP_W>& op2) { + Base::operator = ((const ap_private<_AP_W, true>&)op2); + return *this; + } +}; + +//AP_UINT +//--------------------------------------------------------------- +template +class ap_uint: public ap_private<_AP_W, false> { +#ifdef _MSC_VER +#pragma warning( disable : 4521 4522 ) +#endif +public: + typedef ap_private<_AP_W, false> Base; + //Constructor + INLINE ap_uint(): Base() {} + INLINE ap_uint(const ap_uint<_AP_W>& op) :Base(dynamic_cast&>(op)) {} + INLINE ap_uint(const volatile ap_uint<_AP_W>& op):Base(dynamic_cast&>(op)){} + template + INLINE ap_uint(const volatile ap_uint<_AP_W2> &op):Base((const ap_private<_AP_W2, false>&)(op)) {} + + template + INLINE ap_uint(const ap_uint<_AP_W2> &op) : Base((const ap_private<_AP_W2, false>&)(op)){} + + template + INLINE ap_uint(const ap_int<_AP_W2> &op) : Base((const ap_private<_AP_W2, true>&)(op)) {} + + template + INLINE ap_uint(const volatile ap_int<_AP_W2> &op) : Base((const ap_private<_AP_W2, false>&)(op)) {} + + template + INLINE ap_uint(const ap_range_ref<_AP_W2, _AP_S2>& ref):Base(ref) {} + + template + INLINE ap_uint(const ap_bit_ref<_AP_W2, _AP_S2>& ref):Base(ref) {} + + template + INLINE ap_uint(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& ref):Base(ref) {} + + template + INLINE ap_uint(const ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op.to_ap_private()) {} + + template + INLINE ap_uint(const ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op.to_ap_private()) {} + + template + INLINE ap_uint(const volatile ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op.to_ap_private()) {} + + template + INLINE ap_uint(const volatile ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op) {} + + template + INLINE ap_uint(const ap_private<_AP_W2, _AP_S2>& op):Base(op) {} + + template + INLINE ap_uint(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, + _AP_N2>& op):Base(op) {} + + template + INLINE ap_uint(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, + _AP_N2>& op):Base(op) {} + + template + INLINE ap_uint(const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& op):Base(op.to_ap_private()) {} + +#define CTOR(TYPE) \ + INLINE ap_uint(TYPE v):Base(v) {} + CTOR(bool) + CTOR(signed char) + CTOR(unsigned char) + CTOR(short) + CTOR(unsigned short) + CTOR(int) + CTOR(unsigned int) + CTOR(long) + CTOR(unsigned long) + CTOR(unsigned long long) + CTOR(long long) + CTOR(float) + CTOR(double) + CTOR(const char*) + CTOR(const std::string&) +#undef CTOR + INLINE ap_uint(const char* str, signed char rd):Base(str, rd) {} + //Assignment + //Another form of "write" + INLINE void operator = (const ap_uint<_AP_W>& op2) volatile { + Base::operator = (op2); + } + + INLINE void operator = (const volatile ap_uint<_AP_W>& op2) volatile { + Base::operator = (op2); + } + + INLINE ap_uint<_AP_W>& operator = (const volatile ap_uint<_AP_W>& op2) { + Base::operator = (op2); + return *this; + } + + INLINE ap_uint<_AP_W>& operator = (const ap_uint<_AP_W>& op2) { + Base::operator = ((const ap_private<_AP_W, false>&)(op2)); + return *this; + } +}; + +#define ap_bigint ap_int +#define ap_biguint ap_uint + +//AP_FIXED +//--------------------------------------------------------------------- +template +class ap_fixed: public ap_fixed_base<_AP_W, _AP_I, true, _AP_Q, _AP_O, _AP_N> { +#ifdef _MSC_VER +#pragma warning( disable : 4521 4522 ) +#endif +public: + typedef ap_fixed_base<_AP_W, _AP_I, true, _AP_Q, _AP_O, _AP_N> Base; + //Constructor + INLINE ap_fixed():Base() {} + + template + INLINE ap_fixed(const ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, + _AP_N2>& op): Base(op) {} + + template + INLINE ap_fixed(const ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, + _AP_N2>& op): Base(ap_fixed_base<_AP_W2, _AP_I2, + false, _AP_Q2, _AP_O2, _AP_N2>(op)) {} + + template + INLINE ap_fixed(const ap_int<_AP_W2>& op): + Base(ap_private<_AP_W2, true>(op)) {} + + template + INLINE ap_fixed(const ap_uint<_AP_W2>& op):Base(ap_private<_AP_W2, false>(op)) {} + + template + INLINE ap_fixed(const volatile ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, + _AP_N2>& op): Base(ap_fixed_base<_AP_W2, _AP_I2, + true, _AP_Q2, _AP_O2, _AP_N2>(op)) {} + + template + INLINE ap_fixed(const volatile ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, + _AP_N2>& op): Base(ap_fixed_base<_AP_W2, _AP_I2, + false, _AP_Q2, _AP_O2, _AP_N2>(op)) {} + + template + INLINE ap_fixed(const volatile ap_int<_AP_W2>& op): + Base(ap_private<_AP_W2, true>(op)) {} + + template + INLINE ap_fixed(const volatile ap_uint<_AP_W2>& op):Base(op) {} + + template + INLINE ap_fixed(const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& op):Base(op) {} + + template + INLINE ap_fixed(const ap_bit_ref<_AP_W2, _AP_S2>& op): + Base(op) {} + + template + INLINE ap_fixed(const ap_range_ref<_AP_W2, _AP_S2>& op): + Base(op) {} + + template + INLINE ap_fixed(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& op): + Base(op) {} + + template + INLINE ap_fixed(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& op): Base(op) {} + + template + INLINE ap_fixed(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& op): Base(op) {} + + template + INLINE ap_fixed(const ap_private<_AP_W2, _AP_S2>& op):Base(op) {} + + #define CTOR(TYPE) \ + INLINE ap_fixed(TYPE v):Base(v) {} + CTOR(bool) + CTOR(signed char) + CTOR(unsigned char) + CTOR(short) + CTOR(unsigned short) + CTOR(int) + CTOR(unsigned int) + CTOR(long) + CTOR(unsigned long) + CTOR(unsigned long long) + CTOR(long long) + CTOR(float) + CTOR(double) + CTOR(const char*) + CTOR(const std::string&) +#undef CTOR + INLINE ap_fixed(const char* str, signed char rd):Base(str, rd) {} + + //Assignment + INLINE ap_fixed& operator = (const ap_fixed<_AP_W, _AP_I, + _AP_Q, _AP_O, _AP_N>& op) { + Base::operator = (op); + return *this; + } + + INLINE ap_fixed& operator = (const volatile ap_fixed<_AP_W, _AP_I, + _AP_Q, _AP_O, _AP_N>& op) { + Base::operator = (op); + return *this; + } +}; + +//AP_ UFIXED +//--- ---------------------------------------------------------------- +template +class ap_ufixed : public ap_fixed_base<_AP_W, _AP_I, false, _AP_Q, _AP_O, _AP_N> { +#ifdef _MSC_VER +#pragma warning(disable: 4521 4522) +#endif /* #ifdef _MSC_VER */ +public: + typedef ap_fixed_base<_AP_W, _AP_I, false, _AP_Q, _AP_O, _AP_N> Base; + + //Constructor + INLINE ap_ufixed():Base() {} + + template + INLINE ap_ufixed(const ap_fixed<_AP_W2, _AP_I2, _AP_Q2, + _AP_O2, _AP_N2>& op) : Base(ap_fixed_base<_AP_W2, + _AP_I2, true, _AP_Q2, _AP_O2, _AP_N2>(op)) {} + + template + INLINE ap_ufixed(const ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, + _AP_O2, _AP_N2>& op): Base(ap_fixed_base<_AP_W2, _AP_I2, + false, _AP_Q2, _AP_O2, _AP_N2>(op)) {} + + template + INLINE ap_ufixed(const ap_int<_AP_W2>& op): + Base((const ap_private<_AP_W2, true>&)(op)) {} + + template + INLINE ap_ufixed(const ap_uint<_AP_W2>& op): + Base((const ap_private<_AP_W2, false>&)(op)) {} + + template + INLINE ap_ufixed(const volatile ap_fixed<_AP_W2, _AP_I2, _AP_Q2, + _AP_O2, _AP_N2>& op) : Base(ap_fixed_base<_AP_W2, + _AP_I2, true, _AP_Q2, _AP_O2, _AP_N2>(op)) {} + + template + INLINE ap_ufixed(const volatile ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, + _AP_O2, _AP_N2>& op): Base(ap_fixed_base<_AP_W2, _AP_I2, + false, _AP_Q2, _AP_O2, _AP_N2>(op)) {} + + template + INLINE ap_ufixed(const volatile ap_int<_AP_W2>& op): + Base(ap_private<_AP_W2, true>(op)) {} + + template + INLINE ap_ufixed(const volatile ap_uint<_AP_W2>& op): + Base(ap_private<_AP_W2, false>(op)) {} + + template + INLINE ap_ufixed(const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2>& op):Base(op) {} + + template + INLINE ap_ufixed(const ap_bit_ref<_AP_W2, _AP_S2>& op): + Base(op) {} + + template + INLINE ap_ufixed(const ap_range_ref<_AP_W2, _AP_S2>& op): + Base(op) {} + + template + INLINE ap_ufixed(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& op): + Base(op) {} + + template + INLINE ap_ufixed(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& op): Base(op) {} + + template + INLINE ap_ufixed(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& op): Base(op) {} + + template + INLINE ap_ufixed(const ap_private<_AP_W2, _AP_S2>& op):Base(op) {} + + #define CTOR(TYPE) \ + INLINE ap_ufixed(TYPE v):Base(v) {} + CTOR(bool) + CTOR(signed char) + CTOR(unsigned char) + CTOR(short) + CTOR(unsigned short) + CTOR(int) + CTOR(unsigned int) + CTOR(long) + CTOR(unsigned long) + CTOR(unsigned long long) + CTOR(long long) + CTOR(float) + CTOR(double) + CTOR(const char*) + CTOR(const std::string&) +#undef CTOR + INLINE ap_ufixed(const char* str, signed char rd):Base(str, rd) {} + + //Assignment + INLINE ap_ufixed& operator = (const ap_ufixed<_AP_W, _AP_I, + _AP_Q, _AP_O, _AP_N>& op) { + Base::operator = (op); + return *this; + } + + INLINE ap_ufixed& operator = (const volatile ap_ufixed<_AP_W, _AP_I, + _AP_Q, _AP_O, _AP_N>& op) { + Base::V = const_cast(op); + return *this; + } +}; + +#if defined(SYSTEMC_H) || defined(SYSTEMC_INCLUDED) +template +INLINE void sc_trace(sc_core::sc_trace_file *tf, const ap_int<_AP_W> &op, + const std::string &name) { + if (tf) + tf->trace(sc_dt::sc_lv<_AP_W>(op.to_string(2).c_str()), name); +} + +template +INLINE void sc_trace(sc_core::sc_trace_file *tf, const ap_uint<_AP_W> &op, + const std::string &name) { + if (tf) + tf->trace(sc_dt::sc_lv<_AP_W>(op.to_string(2).c_str()), name); +} + +template +INLINE void sc_trace(sc_core::sc_trace_file *tf, const ap_fixed<_AP_W, _AP_I, _AP_Q, _AP_O, _AP_N >&op, const std::string &name) { + tf->trace(sc_dt::sc_lv<_AP_W>(op.to_string(2).c_str()), name); +} + +template +INLINE void sc_trace(sc_core::sc_trace_file *tf, const ap_ufixed<_AP_W, _AP_I, _AP_Q, _AP_O, _AP_N >&op, const std::string &name) { + tf->trace(sc_dt::sc_lv<_AP_W>(op.to_string(2).c_str()), name); +} +#endif /* #if defined(SYSTEMC_H) || defined(SYSTEMC_INCLUDED) */ +#endif /* #ifndef __cplusplus */ +#endif /* #ifndef __AESL_AP_SIM_H__ */ \ No newline at end of file diff --git a/hls_2018/router_05/etc/ap_fixed_sim.h b/hls_2018/router_05/etc/ap_fixed_sim.h new file mode 100755 index 0000000..5be571d --- /dev/null +++ b/hls_2018/router_05/etc/ap_fixed_sim.h @@ -0,0 +1,2451 @@ +/* + * Copyright 2012 Xilinx, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __AESL_GCC_AP_FIXED_H__ +#define __AESL_GCC_AP_FIXED_H__ + +#ifndef __cplusplus + #error C++ is required to include this header file +#endif /* #ifndef __cplusplus */ + + +#include +#ifndef __AESL_APDT_IN_SCFLOW__ + #include "etc/ap_int_sim.h" +#else + #include "../etc/ap_private.h" +#endif /* #ifndef __AESL_APDT_IN_SCFLOW__ */ + +#define FLOAT_MAN 23 +#define FLOAT_EXP 8 +#define DOUBLE_MAN 52 +#define DOUBLE_EXP 11 +// #define DOUBLE_MAN_MASK (~0ULL >> (64-DOUBLE_MAN-2)) +#define DOUBLE_MAN_MASK 0x3fffffffffffffULL +#define BIAS(e) ((1ULL<<(e-1))-1) +#define FLOAT_BIAS BIAS(FLOAT_EXP) +#define DOUBLE_BIAS BIAS(DOUBLE_EXP) + +/// Forward declaration. +template struct ap_fixed_base; + +///Proxy class, which allows bit selection to be used as both rvalue(for reading) and +//lvalue(for writing) +template +struct af_bit_ref { +#ifdef _MSC_VER + #pragma warning(disable: 4521 4522) +#endif /* #ifdef _MSC_VER */ + ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& d_bv; + int d_index; +public: + INLINE af_bit_ref(const af_bit_ref<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& ref): + d_bv(ref.d_bv), d_index(ref.d_index) {} + + INLINE af_bit_ref(ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>* bv, int index=0): + d_bv(*bv),d_index(index) {} + + INLINE operator bool() const { + return d_bv.V[d_index]; + } + + INLINE af_bit_ref& operator=(unsigned long long val) { + if (val) + d_bv.V.set(d_index); + else + d_bv.V.clear(d_index); + return *this; + } + + template + INLINE af_bit_ref& operator =(const ap_private<_AP_W2,_AP_S2>& val) { + return operator=(val!=0); + } + + INLINE af_bit_ref& operator =(const af_bit_ref<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& val) { + return operator=((unsigned long long)(bool)val); + } + + template + INLINE af_bit_ref operator=(const af_bit_ref<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& val) { + return operator=((unsigned long long)(bool)val); + } + + template + INLINE af_bit_ref& operator = ( const ap_bit_ref<_AP_W2, _AP_S2> &val) { + return operator =((unsigned long long) (bool) val); + } + + template + INLINE af_bit_ref& operator = ( const ap_range_ref<_AP_W2,_AP_S2>& val) { + return operator =((const ap_private<_AP_W2, false>) val); + } + + template + INLINE af_bit_ref& operator= (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& val) { + return operator=((const ap_private<_AP_W2, false>)(val)); + } + + template + INLINE af_bit_ref& operator= (const ap_concat_ref<_AP_W2, _AP_T3, _AP_W3, _AP_T3>& val) { + return operator=((const ap_private<_AP_W2 + _AP_W3, false>)(val)); + } + + template + INLINE ap_concat_ref<1, af_bit_ref, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (ap_private<_AP_W2, _AP_S2>& op) { + return ap_concat_ref<1, af_bit_ref, _AP_W2, + ap_private<_AP_W2, _AP_S2> >(*this, op); + } + + template + INLINE ap_concat_ref<1, af_bit_ref, 1, ap_bit_ref<_AP_W2, _AP_S2> > + operator, (const ap_bit_ref<_AP_W2, _AP_S2> &op) { + return ap_concat_ref<1, af_bit_ref, 1, + ap_bit_ref<_AP_W2, _AP_S2> >(*this, + const_cast& >(op)); + } + + template + INLINE ap_concat_ref<1, af_bit_ref, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > + operator, (const ap_range_ref<_AP_W2, _AP_S2> &op) { + return ap_concat_ref<1, af_bit_ref, _AP_W2, + ap_range_ref<_AP_W2, _AP_S2> >(*this, + const_cast& >(op)); + } + + template + INLINE ap_concat_ref<1, af_bit_ref, _AP_W2 + _AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > + operator, (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &op) { + return ap_concat_ref<1, af_bit_ref, _AP_W2 + _AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(*this, + const_cast& >(op)); + } + + template + INLINE ap_concat_ref<1, af_bit_ref, _AP_W2, + af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &op) { + return ap_concat_ref<1, af_bit_ref, _AP_W2, + af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, + _AP_N2> >(*this, const_cast& >(op)); + } + + template + INLINE ap_concat_ref<1, af_bit_ref, 1, + af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &op) { + return ap_concat_ref<1, af_bit_ref, 1, + af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, + const_cast& >(op)); + } + + template + INLINE bool operator == (const af_bit_ref<_AP_W2, _AP_I2, + _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) { + return get() == op.get(); + } + + template + INLINE bool operator != (const af_bit_ref<_AP_W2, _AP_I2, + _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) { + return get() != op.get(); + } + + INLINE bool operator ~ () const { + bool bit = (d_bv.V)[d_index]; + return bit ? false : true; + } + + INLINE int length() const { + return 1; + } + + INLINE bool get() { + return d_bv.V[d_index]; + } + + INLINE bool get() const { + return d_bv.V[d_index]; + } + + INLINE std::string to_string() const { + return d_bv.V[d_index] ? "1" : "0"; + } +}; + +///Range(slice) reference +//------------------------------------------------------------ +template +struct af_range_ref { +#ifdef _MSC_VER + #pragma warning(disable: 4521 4522) +#endif /* #ifdef _MSC_VER */ + ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &d_bv; + int l_index; + int h_index; + +public: + INLINE af_range_ref(const af_range_ref<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& ref): + d_bv(ref.d_bv), l_index(ref.l_index), h_index(ref.h_index) {} + + INLINE af_range_ref(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>* bv, int h, int l): + d_bv(*bv),l_index(l),h_index(h) { + //if (h < l) + // fprintf(stderr, + //"Warning! The bits selected will be returned in reverse order\n"); + } + + INLINE operator ap_private<_AP_W, false> () const { + if (h_index >= l_index) { + ap_private<_AP_W, false> val(d_bv.V); + ap_private<_AP_W,false> mask(-1); + mask>>=_AP_W-(h_index-l_index+1); + val>>=l_index; + return val&=mask; + } else { + ap_private<_AP_W, false> val = 0; + for (int i=0, j=l_index;j>=0&&j>=h_index;j--,i++) + if ((d_bv.V)[j]) val.set(i); + return val; + } + } + + INLINE operator unsigned long long() const { + return get().to_uint64(); + } + + template + INLINE af_range_ref& operator =(const ap_private<_AP_W2,_AP_S2>& val) { + ap_private<_AP_W, false> vval= ap_private<_AP_W, false>(val); + if (l_index > h_index) { + for (int i=0, j=l_index;j>=0&&j>=h_index;j--,i++) + vval[i]? d_bv.V.set(j):d_bv.V.clear(j); + } else { + ap_private<_AP_W,false> mask(-1); + if (l_index>0) { + mask<<=l_index; + vval<<=l_index; + } + if (h_index<_AP_W-1) { + ap_private<_AP_W,false> mask2(-1); + mask2>>=_AP_W-h_index-1; + mask&=mask2; + vval&=mask2; + } + mask.flip(); + d_bv.V &= mask; + d_bv.V |= vval; + } + return *this; + } + + INLINE af_range_ref& operator = (unsigned long long val) { + const ap_private<_AP_W, false> tmpVal(val); + return operator = (tmpVal); + } + + template + INLINE af_range_ref& operator = + (const ap_concat_ref <_AP_W3, _AP_T3, _AP_W4, _AP_T4>& val) { + const ap_private<_AP_W, false> tmpVal(val); + return operator = (tmpVal); + } + + template + INLINE af_range_ref& operator =(const ap_bit_ref<_AP_W3, _AP_S3>& val) { + const ap_private<_AP_W, false> tmpVal(val); + return operator = (tmpVal); + } + + template + INLINE af_range_ref& operator =(const ap_range_ref<_AP_W3,_AP_S3>& val) { + const ap_private<_AP_W, false> tmpVal(val); + return operator =(tmpVal); + } + + template + INLINE af_range_ref& operator= (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& val) { + const ap_private<_AP_W2, false> tmp= val.get(); + return operator = (tmp); + } + + INLINE af_range_ref& operator= (const af_range_ref<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& val) { + const ap_private<_AP_W, false> tmp= val.get(); + return operator = (tmp); + } + + template + INLINE af_range_ref& operator= (const ap_fixed_base<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& val) { + return operator=(val.to_ap_private()); + } + + template + INLINE bool operator == (const ap_range_ref<_AP_W2, _AP_S2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs==rhs; + } + + template + INLINE bool operator != (const ap_range_ref<_AP_W2, _AP_S2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs!=rhs; + } + + template + INLINE bool operator > (const ap_range_ref<_AP_W2, _AP_S2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs>rhs; + } + + template + INLINE bool operator >= (const ap_range_ref<_AP_W2, _AP_S2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs>=rhs; + } + + template + INLINE bool operator < (const ap_range_ref<_AP_W2, _AP_S2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs + INLINE bool operator <= (const ap_range_ref<_AP_W2, _AP_S2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs<=rhs; + } + + template + INLINE bool operator == (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs==rhs; + } + + template + INLINE bool operator != (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs!=rhs; + } + + template + INLINE bool operator > (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs>rhs; + } + + template + INLINE bool operator >= (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs>=rhs; + } + + template + INLINE bool operator < (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs + INLINE bool operator <= (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs<=rhs; + } + + template + INLINE void set(const ap_private<_AP_W2,false>& val) { + ap_private<_AP_W,_AP_S> vval=val; + if (l_index>h_index) { + for (int i=0, j=l_index;j>=0&&j>=h_index;j--,i++) + vval[i]? d_bv.V.set(j):d_bv.V.clear(j); + } else { + ap_private<_AP_W,_AP_S> mask(-1); + if (l_index>0) { + ap_private<_AP_W,false> mask1(-1); + mask1>>=_AP_W-l_index; + mask1.flip(); + mask=mask1; + //vval&=mask1; + vval<<=l_index; + } + if (h_index<_AP_W-1) { + ap_private<_AP_W,false> mask2(-1); + mask2<<=h_index+1; + mask2.flip(); + mask&=mask2; + vval&=mask2; + } + mask.flip(); + d_bv&=mask; + d_bv|=vval; + } + + } + + INLINE ap_private<_AP_W,false> get() const { + if (h_index val(0); + for (int i=0, j=l_index;j>=0&&j>=h_index;j--,i++) + if ((d_bv.V)[j]) val.set(i); + return val; + } else { + ap_private<_AP_W, false> val = ap_private<_AP_W,false>(d_bv.V); + val>>= l_index; + if (h_index<_AP_W-1) + { + ap_private<_AP_W,false> mask(-1); + mask>>=_AP_W-(h_index-l_index+1); + val&=mask; + } + return val; + } + } + + template + INLINE ap_concat_ref<_AP_W, af_range_ref, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (ap_private<_AP_W2, _AP_S2>& op) { + return ap_concat_ref<_AP_W, af_range_ref, _AP_W2, + ap_private<_AP_W2, _AP_S2> >(*this, op); + } + + template + INLINE ap_concat_ref<_AP_W, af_range_ref, 1, ap_bit_ref<_AP_W2, _AP_S2> > + operator, (const ap_bit_ref<_AP_W2, _AP_S2> &op) { + return ap_concat_ref<_AP_W, af_range_ref, 1, + ap_bit_ref<_AP_W2, _AP_S2> >(*this, + const_cast& >(op)); + } + + template + INLINE ap_concat_ref<_AP_W, af_range_ref, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > + operator, (const ap_range_ref<_AP_W2, _AP_S2> &op) { + return ap_concat_ref<_AP_W, af_range_ref, _AP_W2, + ap_range_ref<_AP_W2, _AP_S2> >(*this, + const_cast& >(op)); + } + + template + INLINE ap_concat_ref<_AP_W, af_range_ref, _AP_W2 + _AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > + operator, (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &op) { + return ap_concat_ref<_AP_W, af_range_ref, _AP_W2 + _AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(*this, + const_cast& >(op)); + } + + template + INLINE ap_concat_ref<_AP_W, af_range_ref, _AP_W2, + af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &op) { + return ap_concat_ref<_AP_W, af_range_ref, _AP_W2, + af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, + const_cast& > (op)); + } + + template + INLINE ap_concat_ref<_AP_W, af_range_ref, 1, + af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &op) { + return ap_concat_ref<_AP_W, af_range_ref, 1, + af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, + const_cast& >(op)); + } + + INLINE int length() const { + return h_index>=l_index?h_index-l_index+1:l_index-h_index+1; + } + + INLINE int to_int() const { + ap_private<_AP_W,false> val=get(); + return val.to_int(); + } + + INLINE unsigned int to_uint() const { + ap_private<_AP_W,false> val=get(); + return val.to_uint(); + } + + INLINE long to_long() const { + ap_private<_AP_W,false> val=get(); + return val.to_long(); + } + + INLINE unsigned long to_ulong() const { + ap_private<_AP_W,false> val=get(); + return val.to_ulong(); + } + + INLINE ap_slong to_int64() const { + ap_private<_AP_W,false> val=get(); + return val.to_int64(); + } + + INLINE ap_ulong to_uint64() const { + ap_private<_AP_W,false> val=get(); + return val.to_uint64(); + } + + INLINE std::string to_string(uint8_t radix) const { + return get().to_string(radix); + } + +}; + +//----------------------------------------------------------------------------- +///ap_fixed_base: AutoPilot fixed point +//----------------------------------------------------------------------------- +template +struct ap_fixed_base { +#ifdef _MSC_VER + #pragma warning(disable: 4521 4522) +#endif /* #ifdef _MSC_VER */ +public: + template friend struct +ap_fixed_base; + template friend struct +af_bit_ref; + + INLINE void overflow_adjust(bool underflow, bool overflow, + bool lD, bool sign) { + if (!overflow && !underflow) return; + switch (_AP_O) { + case AP_WRAP: + if (_AP_N == 0) + return; + if (_AP_S) { + //signed SC_WRAP + //n_bits == 1; + if (_AP_N > 1) { + ap_private<_AP_W, _AP_S> mask(-1); + if (_AP_N >= _AP_W) mask = 0; + else mask.lshr(_AP_N); + if (sign) + V &= mask; + else + V |= ~mask; + } + sign ? V.set(_AP_W - 1) : V.clear(_AP_W - 1); + } else { + //unsigned SC_WRAP + ap_private<_AP_W, _AP_S> mask(-1); + if (_AP_N >= _AP_W) mask = 0; + else mask.lshr(_AP_N); + mask.flip(); + V |= mask; + } + break; + case AP_SAT_ZERO: + V.clear(); + break; + case AP_WRAP_SM: + { + bool Ro = ap_private_ops::get<_AP_W, _AP_S, _AP_W -1>(V); // V[_AP_W -1]; + if (_AP_N == 0) { + if (lD != Ro) { + V.flip(); + lD ? ap_private_ops::set<_AP_W, _AP_S, _AP_W - 1>(V) : + ap_private_ops::clear<_AP_W, _AP_S, _AP_W - 1>(V); + } + } else { + if (_AP_N == 1 && sign != Ro) { + V.flip(); + } else if (_AP_N > 1) { + bool lNo = ap_private_ops::get<_AP_W, _AP_S, _AP_W - _AP_N> (V); // V[_AP_W - _AP_N]; + if (lNo == sign) + V.flip(); + ap_private<_AP_W, false> mask(-1); + if (_AP_N >= _AP_W) mask = 0; + else mask.lshr(_AP_N); + if (sign) + V &= mask; + else + V |= mask.flip(); + sign ? ap_private_ops::set<_AP_W, _AP_S, _AP_W - 1>(V) : ap_private_ops::clear<_AP_W, _AP_S, _AP_W - 1>(V); + } + } + } + break; + default: + if (_AP_S) { + if (overflow) { + V.set(); ap_private_ops::clear<_AP_W, _AP_S, _AP_W-1>(V); + } else if (underflow) { + V.clear(); + ap_private_ops::set<_AP_W, _AP_S, _AP_W-1>(V); + if (_AP_O == AP_SAT_SYM) + ap_private_ops::set<_AP_W, _AP_S, 0>(V); + } + } else { + if (overflow) + V.set(); + else if (underflow) + V.clear(); + } + } + } + + INLINE bool quantization_adjust(bool qb, bool r, bool s) { + bool carry=ap_private_ops::get<_AP_W, _AP_S, _AP_W-1>(V); + switch (_AP_Q) { + case AP_TRN: + return false; + case AP_RND_ZERO: + qb &= s || r; + break; + case AP_RND_MIN_INF: + qb &= r; + break; + case AP_RND_INF: + qb &= !s || r; + break; + case AP_RND_CONV: + qb &= ap_private_ops::get<_AP_W, _AP_S, 0>(V) || r; + break; + case AP_TRN_ZERO: + qb = s && ( qb || r ); + break; + default:; + + } + if (qb) ++V; + //only when old V[_AP_W-1]==1 && new V[_AP_W-1]==0 + return carry && !(ap_private_ops::get<_AP_W, _AP_S, _AP_W-1>(V)); //(!V[_AP_W-1]); + } + + template + struct RType { + enum { + _AP_F=_AP_W-_AP_I, + F2=_AP_W2-_AP_I2, + mult_w = _AP_W+_AP_W2, + mult_i = _AP_I+_AP_I2, + mult_s = _AP_S||_AP_S2, + plus_w = AP_MAX(_AP_I+(_AP_S2&&!_AP_S),_AP_I2+(_AP_S&&!_AP_S2))+1+AP_MAX(_AP_F,F2), + plus_i = AP_MAX(_AP_I+(_AP_S2&&!_AP_S),_AP_I2+(_AP_S&&!_AP_S2))+1, + plus_s = _AP_S||_AP_S2, + minus_w = AP_MAX(_AP_I+(_AP_S2&&!_AP_S),_AP_I2+(_AP_S&&!_AP_S2))+1+AP_MAX(_AP_F,F2), + minus_i = AP_MAX(_AP_I+(_AP_S2&&!_AP_S),_AP_I2+(_AP_S&&!_AP_S2))+1, + minus_s = true, +#ifndef __SC_COMPATIBLE__ + div_w = _AP_W + AP_MAX(_AP_W2 - _AP_I2, 0) + _AP_S2, +#else + div_w = _AP_W + AP_MAX(_AP_W2 - _AP_I2, 0) + _AP_S2 + AP_MAX(_AP_I2, 0), +#endif /* #ifndef __SC_COMPATIBLE__ */ + div_i = _AP_I + (_AP_W2-_AP_I2) + _AP_S2, + div_s = _AP_S||_AP_S2, + logic_w = AP_MAX(_AP_I+(_AP_S2&&!_AP_S),_AP_I2+(_AP_S&&!_AP_S2))+AP_MAX(_AP_F,F2), + logic_i = AP_MAX(_AP_I+(_AP_S2&&!_AP_S),_AP_I2+(_AP_S&&!_AP_S2)), + logic_s = _AP_S||_AP_S2 + }; + + typedef ap_fixed_base mult; + typedef ap_fixed_base plus; + typedef ap_fixed_base minus; + typedef ap_fixed_base logic; + typedef ap_fixed_base div; + typedef ap_fixed_base<_AP_W, _AP_I, _AP_S> arg1; + }; + INLINE void report() { +#if 0 + if (_AP_W > 1024 && _AP_W <= 4096) { + fprintf(stderr, "[W] W=%d is out of bound (1<=W<=1024):" + " for synthesis, please define macro AP_INT_TYPE_EXT(N) to" + " extend the valid range.\n", _AP_W); + } else +#endif /* #if 0 */ + if (_AP_W > MAX_MODE(AP_INT_MAX_W) * 1024) { + fprintf(stderr, "[E] ap_%sfixed<%d, ...>: Bitwidth exceeds the " + "default max value %d. Please use macro " + "AP_INT_MAX_W to set a larger max value.\n", + _AP_S?"":"u", _AP_W, + MAX_MODE(AP_INT_MAX_W) * 1024); + exit(1); + } + } + + /// Constructors. + // ------------------------------------------------------------------------- +#if 0 + #ifdef __SC_COMPATIBLE__ + INLINE ap_fixed_base():V(uint32_t(_AP_W), uint64_t(0)) {} + #else + INLINE ap_fixed_base():V(uint32_t(_AP_W)) {} + #endif /* #ifdef __SC_COMPATIBLE__ */ +#else + INLINE ap_fixed_base():V(0) {} +#endif /* #if 0 */ + // INLINE ap_fixed_base():V() {} + // INLINE explicit ap_fixed_base(const ap_private<_AP_W+_AP_I, _AP_S>& _V):V(_V) {} + INLINE ap_fixed_base(const ap_fixed_base& op):V(op.V) {} + template + INLINE ap_fixed_base(const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op):V(0) { + enum {N2=_AP_W2,_AP_F=_AP_W-_AP_I,F2=_AP_W2-_AP_I2,QUAN_INC=F2>_AP_F && !(_AP_Q==AP_TRN || + (_AP_Q==AP_TRN_ZERO && !_AP_S2))}; + if (!op) return; + bool carry=false; + //handle quantization + enum { sh_amt =(F2>_AP_F)?F2-_AP_F:_AP_F-F2}; + const ap_private<_AP_W2, _AP_S2>& val = op.V; + bool neg_src=val.isNegative(); + if (F2==_AP_F) + V=val; + + else if (F2>_AP_F) { + if (sh_amt >= _AP_W2) + V = neg_src ? -1 : 0; + else + V = _AP_S2?val.ashr(sh_amt):val.lshr(sh_amt); + if (_AP_Q!=AP_TRN && !(_AP_Q==AP_TRN_ZERO && !_AP_S2)) { + bool qb = false; + if (F2-_AP_F>_AP_W2) + qb = neg_src; + else + qb = ap_private_ops::get<_AP_W2, _AP_S2, F2-_AP_F-1>(val); + + bool r=false; + enum { pos3 = F2-_AP_F-2}; + if (pos3>=_AP_W2-1) + r=val!=0; + else if (pos3>=0) + r = (val<<(_AP_W2-1-pos3))!=0; + carry = quantization_adjust(qb,r,neg_src); + } + } else { //no quantization + if (sh_amt < _AP_W) { + V=val; + V <<= sh_amt; + } + } + //hanle overflow/underflow + if ((_AP_O!=AP_WRAP || _AP_N != 0) && + ((!_AP_S && _AP_S2) || _AP_I-_AP_S < + _AP_I2 - _AP_S2 + (QUAN_INC|| (_AP_S2 && + _AP_O==AP_SAT_SYM)))) {//saturation + bool deleted_zeros = _AP_S2?true:!carry, + deleted_ones = true; + bool lD=(_AP_I2>_AP_I && _AP_W2-_AP_I2+_AP_I>=0) && + ap_private_ops::get<_AP_W2, _AP_S2, _AP_W2-_AP_I2+_AP_I>(val); + enum { pos1=F2-_AP_F+_AP_W, pos2=F2-_AP_F+_AP_W+1}; + if (pos1 < _AP_W2) { + bool Range1_all_ones= true; + bool Range1_all_zeros= true; + if (pos1 >= 0) { + enum { __W = (_AP_W2-pos1) > 0 ? (_AP_W2-pos1) : 1 }; + const ap_private<__W, _AP_S2> Range1=ap_private<__W, _AP_S2>(val.lshr(pos1)); + Range1_all_ones=Range1.isAllOnesValue(); + Range1_all_zeros=Range1.isMinValue(); + } else { + Range1_all_ones=false; + Range1_all_zeros=val.isMinValue(); + } + bool Range2_all_ones=true; + if (pos2<_AP_W2 && pos2>=0) { + enum { __W = (_AP_W2-pos2)>0 ? (_AP_W2-pos2) : 1}; + ap_private<__W, true> Range2=ap_private<__W, true>(val.lshr(pos2)); + Range2_all_ones=Range2.isAllOnesValue(); + } else if (pos2<0) + Range2_all_ones=false; + + deleted_zeros=deleted_zeros && (carry?Range1_all_ones:Range1_all_zeros); + deleted_ones=carry?Range2_all_ones&&(F2-_AP_F+_AP_W<0||!lD) + :Range1_all_ones; + neg_src= neg_src&&!(carry && Range1_all_ones); + } else + neg_src = neg_src && V[_AP_W-1]; + + bool neg_trg= V.isNegative(); + bool overflow=(neg_trg||!deleted_zeros) && !val.isNegative(); + bool underflow=(!neg_trg||!deleted_ones)&&neg_src; + //printf("neg_src = %d, neg_trg = %d, deleted_zeros = %d, + // deleted_ones = %d, overflow = %d, underflow = %d\n", + // neg_src, neg_trg, deleted_zeros, deleted_ones, + // overflow, underflow); + if (_AP_O==AP_SAT_SYM && _AP_S2 && _AP_S) + underflow |= neg_src && (_AP_W>1?V.isMinSignedValue():true); + overflow_adjust(underflow, overflow, lD, neg_src); + } + report(); + } + + template + INLINE ap_fixed_base(const volatile ap_fixed_base<_AP_W2,_AP_I2, + _AP_S2,_AP_Q2,_AP_O2, _AP_N2> &op) : V(op.V) { + *this = const_cast&>(op); + } + + template + INLINE ap_fixed_base(const ap_private<_AP_W2,_AP_S2>& op) { + ap_fixed_base<_AP_W2,_AP_W2,_AP_S2> f_op; + f_op.V=op; + *this = f_op; + } + + INLINE ap_fixed_base(bool b) { + *this=(ap_private<1,false>)b; + report(); + } + + INLINE ap_fixed_base(char b) { + *this=(ap_private<8,false>)b; + report(); + } + + INLINE ap_fixed_base(signed char b) { + *this=(ap_private<8,true>)b; + report(); + } + + INLINE ap_fixed_base(unsigned char b) { + *this=(ap_private<8,false>)b; + report(); + } + + INLINE ap_fixed_base(signed short b) { + *this=(ap_private<16,true>)b; + report(); + } + + INLINE ap_fixed_base(unsigned short b) { + *this=(ap_private<16,false>)b; + report(); + } + + INLINE ap_fixed_base(signed int b) { + *this=(ap_private<32,true>)b; + report(); + } + + INLINE ap_fixed_base(unsigned int b) { + *this=(ap_private<32,false>)b; + report(); + } +# if defined __x86_64__ + INLINE ap_fixed_base(signed long b) { + *this=(ap_private<64,true>)b; + report(); + } + + INLINE ap_fixed_base(unsigned long b) { + *this=(ap_private<64,false>)b; + report(); + } +# else + INLINE ap_fixed_base(signed long b) { + *this=(ap_private<32,true>)b; + report(); + } + + INLINE ap_fixed_base(unsigned long b) { + *this=(ap_private<32,false>)b; + report(); + } +# endif + + INLINE ap_fixed_base(ap_slong b) { + *this=(ap_private<64,true>)b; + report(); + } + + INLINE ap_fixed_base(ap_ulong b) { + *this=(ap_private<64,false>)b; + report(); + } + +#if 1 + INLINE ap_fixed_base(const char* val):V(0) { + ap_private<_AP_W, _AP_S> Tmp(val); + V = Tmp; + } + + INLINE ap_fixed_base(const char* val, signed char rd): V(0) { + ap_private<_AP_W, _AP_S> Tmp(val, rd); + V = Tmp; + } + +#endif + + INLINE ap_fixed_base(const std::string& val) { + ap_private<_AP_W, _AP_S> Tmp(val, 2); + V = Tmp; + report(); + } + + template + INLINE ap_fixed_base(const ap_bit_ref<_AP_W2, _AP_S2>& op) { + *this = ((bool)op); + report(); + } + + template + INLINE ap_fixed_base(const ap_range_ref<_AP_W2, _AP_S2>& op) { + *this = ap_private<_AP_W2, _AP_S2>(op); + report(); + } + + template + INLINE ap_fixed_base(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& op) { + *this = ((const ap_private<_AP_W2 + _AP_W3, false>&)(op)); + report(); + } + + template + INLINE ap_fixed_base(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) { + *this = (bool(op)); + report(); + } + + template + INLINE ap_fixed_base(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) { + *this = (ap_private<_AP_W2, false>(op)); + report(); + } + + //helper function + INLINE unsigned long long doubleToRawBits(double pf)const { + union { + unsigned long long __L; + double __D; + }LD; + LD.__D=pf; + return LD.__L; + } + + + INLINE double rawBitsToDouble(unsigned long long pi) const { + union { + unsigned long long __L; + double __D; + }LD; + LD.__L=pi; + return LD.__D; + } + + INLINE float rawBitsToFloat(uint32_t pi) const { + union { + uint32_t __L; + float __D; + }LD; + LD.__L = pi; + return LD.__D; + } + + INLINE ap_fixed_base(double d):V(0) { + if (!d) return; + const bool isneg=d<0; + + const uint64_t ireg=doubleToRawBits(isneg?-d:d); + if ((ireg&0x7fffffffffffffffULL)!=0) { + const int32_t exp=(((ireg)>>DOUBLE_MAN)&0x07ff)-DOUBLE_BIAS; + ap_private man = ireg & DOUBLE_MAN_MASK; + man.clear(DOUBLE_MAN+1); + man.set(DOUBLE_MAN); + if (isneg) { + man.flip(); + man++; + } + + enum {_AP_S2=true, _AP_W2=DOUBLE_MAN+2,_AP_F=_AP_W -_AP_I }; + const int _AP_I2=exp+2; + const int F2=_AP_W2-_AP_I2; + const bool QUAN_INC=F2>_AP_F && !(_AP_Q==AP_TRN || (_AP_Q==AP_TRN_ZERO && + !_AP_S2)); + bool carry=false; + //handle quantization + const unsigned sh_amt=abs(F2-_AP_F); // sh_amt = F2>_AP_F ? F2 -_AP_F : _AP_F-F2; + if (F2==_AP_F ) + V=man; + else if (F2>_AP_F) { + if (sh_amt >= DOUBLE_MAN+2) + V=isneg?-1:0; + else + V=(man>>sh_amt) | ((man & 1ULL<<(DOUBLE_MAN+1)) ? (DOUBLE_MAN_MASK>>(DOUBLE_MAN+2-sh_amt) <<(DOUBLE_MAN+2-sh_amt)):0); + + if (_AP_Q!=AP_TRN && !(_AP_Q==AP_TRN_ZERO && !_AP_S2)) { + const bool qb=((F2-_AP_F > DOUBLE_MAN+2) ? isneg : (man & (1ULL<<(F2-_AP_F-1))) != 0); + const int pos3=F2-_AP_F-2; + const bool r = (pos3>= 0) ? (man << AP_MAX(0, _AP_W2-pos3-1)& DOUBLE_MAN_MASK)!=0 : false; + carry = quantization_adjust(qb,r,isneg); + } + } + else { //no quantization + // V=man; + if (sh_amt < _AP_W) { + V = man; + V <<= sh_amt; + } + } + //handle overflow/underflow + if ((_AP_O != AP_WRAP || _AP_N != 0) && + ((!_AP_S && _AP_S2) || _AP_I-_AP_S < + _AP_I2-_AP_S2+(QUAN_INC|| (_AP_S2 && + _AP_O==AP_SAT_SYM)) )) {// saturation + bool deleted_zeros = _AP_S2?true:!carry, + deleted_ones = true; + bool neg_src; + const bool lD=(_AP_I2>_AP_I) && (_AP_W2-_AP_I2+_AP_I>=0) && (man & (1ULL <<(DOUBLE_MAN+2-_AP_I2+_AP_I))); + int pos1=F2+_AP_W-_AP_F; + if (pos1 < _AP_W2) { + int pos2=pos1+1; + bool Range1_all_ones=true; + bool Range1_all_zeros=true; + if (pos1>=0) { + ap_private<_AP_W,_AP_S> Range1= + ap_private<_AP_W,_AP_S>((man >> pos1) | ((1ULL<<(DOUBLE_MAN+1)&man) ? (DOUBLE_MAN_MASK >> (DOUBLE_MAN+2-pos1) <<(DOUBLE_MAN+2-pos1)):0)); + Range1_all_ones = Range1.isAllOnesValue(); // Range1.isAllOnesValue(); + Range1_all_zeros = Range1.isMinValue(); // Range1.isMinValue(); + } else { + Range1_all_ones=false; + Range1_all_zeros = man==0; // man.isMinValue(); + } + bool Range2_all_ones=true; + if (pos2<_AP_W2 && pos2>=0) { + ap_private<_AP_W, _AP_S> Range2= + ap_private<_AP_W, _AP_S>((man >> pos2) | ((1ULL<<(DOUBLE_MAN+1)&man) ? (DOUBLE_MAN_MASK >> (DOUBLE_MAN+2-pos2) <<(DOUBLE_MAN+2-pos2)):0)); + Range2_all_ones=Range2.isAllOnesValue(); // Range2.isAllOnesValue(); + } else if (pos2<0) + Range2_all_ones=false; + deleted_zeros=deleted_zeros && (carry?Range1_all_ones:Range1_all_zeros); + deleted_ones=carry?Range2_all_ones&&(F2-_AP_F+_AP_W<0||!lD) : Range1_all_ones; + neg_src=isneg&&!(carry&Range1_all_ones); + } else + neg_src = isneg && V[_AP_W -1]; + + const bool neg_trg=V.isNegative(); + const bool overflow=(neg_trg||!deleted_zeros) && !isneg; + bool underflow=(!neg_trg||!deleted_ones)&&neg_src; + //printf("neg_src = %d, neg_trg = %d, deleted_zeros = %d, + // deleted_ones = %d, overflow = %d, underflow = %d\n", + // neg_src, neg_trg, deleted_zeros, deleted_ones, + // overflow, underflow); + if (_AP_O==AP_SAT_SYM && _AP_S2 && _AP_S) + underflow |= neg_src && (_AP_W>1?V.isMinSignedValue():true); + overflow_adjust(underflow,overflow,lD, neg_src); + } + } + report(); + } + + + ///assign operators + //------------------------------------------------------------------------- + + INLINE volatile ap_fixed_base& operator=(const ap_fixed_base<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& op) volatile { + V = op.V; + return *this; + } + + INLINE ap_fixed_base& operator=(const ap_fixed_base<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& op) { + V = op.V; + return *this; + } + + INLINE volatile ap_fixed_base& operator=(const volatile ap_fixed_base<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& op) volatile { + V = op.V; + return *this; + } + + INLINE ap_fixed_base& operator=(const volatile ap_fixed_base<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& op) { + V = op.V; + return *this; + } + + // Set this ap_fixed_base with a bits string. That means the ssdm_int::V + // inside this ap_fixed_base is assigned by bv. + // Note the input parameter should be a fixed-point formatted bit string. + INLINE ap_fixed_base& setBits(unsigned long long bv) { + V=bv; + return *this; + } + + // Return a ap_fixed_base object whose ssdm_int::V is assigned by bv. + // Note the input parameter should be a fixed-point formatted bit string. + static INLINE ap_fixed_base bitsToFixed(unsigned long long bv) { + ap_fixed_base Tmp=bv; + return Tmp; + } + + // Explicit conversion functions to ap_private that captures + // all integer bits (bits are truncated) + INLINE ap_private + to_ap_private(bool Cnative = true) const { + ap_private ret = ap_private ((_AP_I >= 1) ? (_AP_S==true ? V.ashr(AP_MAX(0,_AP_W - _AP_I)) : V.lshr(AP_MAX(0,_AP_W - _AP_I))) : ap_private<_AP_W, _AP_S>(0)); + + if (Cnative) { + bool r = false; + if (_AP_I < _AP_W) { + if (_AP_I > 0) r = !(V.getLoBits(_AP_W - _AP_I).isMinValue()); + else r = !(V.isMinValue()); + } + if (r && V.isNegative()) { // if this is negative integer + ++ret;//ap_private(1,_AP_S); + } + } else { + //Follow OSCI library, conversion from sc_fixed to sc_int + } + return ret; + } + + template + INLINE operator ap_private<_AP_W2,_AP_S2> () const { + return (ap_private<_AP_W2,_AP_S2>)to_ap_private(); + } + + template + INLINE operator ap_private<_AP_W2,_AP_S2,_AP_N2> () const { + return (ap_private<_AP_W2,_AP_S2,_AP_N2>)to_ap_private(); + } + + //Explict conversion function to C built-in integral type + INLINE int to_int() const { + return to_ap_private().to_int(); + } + + INLINE int to_uint() const { + return to_ap_private().to_uint(); + } + + INLINE ap_slong to_int64() const { + return to_ap_private().to_int64(); + } + + INLINE ap_ulong to_uint64() const { + return to_ap_private().to_uint64(); + } + + INLINE double to_double() const { + if (!V) + return 0; + if (_AP_W>64 || (_AP_W - _AP_I) > 0) { + bool isneg = _AP_S && V[_AP_W-1]; + uint64_t res = isneg ? 0x8000000000000000ULL : 0; + ap_private<_AP_W, false> tmp = V; + if (isneg) tmp = -tmp; + int i = _AP_W -1 - tmp.countLeadingZeros(); + int exp = _AP_I-(_AP_W-i); + res|=((uint64_t)(exp+DOUBLE_BIAS))<DOUBLE_MAN)?tmp.lshr(i-DOUBLE_MAN):tmp).to_uint64() & DOUBLE_MAN_MASK; + res |= i 0) { + /* This specialization is disabled. It is giving wrong results in some cases. + bool isneg=V.isNegative(); + double dp = V.get(); + dp /= (1<< (_AP_W - _AP_I)); + return dp;*/ + } else + return double(to_int64()); + } + + INLINE float to_float() const { + uint32_t res=0; + if (V==0) + return 0; + bool isneg=V.isNegative(); + ap_private<_AP_W, _AP_S> tmp=V; + if (isneg) tmp = -tmp; + if (_AP_W-_AP_I>0||_AP_W>64) { + if (isneg) + res=0x80000000; + int i=_AP_W-1; + i-=tmp.countLeadingZeros(); + int exp=_AP_I-(_AP_W-i); + res|=(exp+FLOAT_BIAS)< man = 0; + if (i!=0) { + tmp.clear(i); + if (i>FLOAT_MAN) + man=tmp.lshr(i-FLOAT_MAN); + else + man=tmp; + res |= i < FLOAT_MAN?man.getZExtValue()<<(FLOAT_MAN-i):man.getZExtValue(); + } + } else { + return float(to_int64()); + } + float dp=rawBitsToFloat(res); + return dp; + } + + INLINE operator double () const { + return to_double(); + } +#ifndef __SC_COMPATIBLE__ + INLINE operator float () const { + return to_float(); + } + + INLINE operator char () const { + return (char) to_int(); + } + + INLINE operator unsigned char () const { + return (unsigned char) to_uint(); + } + + INLINE operator short () const { + return (short) to_int(); + } + + INLINE operator unsigned short () const { + return (unsigned short) to_uint(); + } + + INLINE operator int () const { + return to_int(); + } + + INLINE operator unsigned int () const { + return to_uint(); + } +#if 1 +#ifdef __x86_64__ + INLINE operator long () const { + return (long)to_int64(); + } + + INLINE operator unsigned long () const { + return (unsigned long) to_uint64(); + } +#else + INLINE operator long () const { + return to_int64(); + } + + INLINE operator unsigned long () const { + return to_uint64(); + } + +#endif +#endif + INLINE operator unsigned long long () const { + return to_uint64(); + } + + INLINE operator long long () const { + return to_int64(); + } +#endif + + INLINE std::string to_string(uint8_t radix=2, bool sign=false) const; + + INLINE ap_slong bits_to_int64() const { + ap_private res(V); + return (ap_slong) res; + } + + INLINE ap_ulong bits_to_uint64() const { + ap_private res(V); + return (ap_ulong) res; + } + + INLINE int length() const {return _AP_W;} + + // Count the number of zeros from the most significant bit + // to the first one bit. Note this is only for ap_fixed_base whose + // _AP_W <= 64, otherwise will incur assertion. + INLINE int countLeadingZeros() { + return V.countLeadingZeros(); + } + + ///Arithmetic:Binary + //------------------------------------------------------------------------- + template + INLINE typename RType<_AP_W2,_AP_I2,_AP_S2>::mult + operator * (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + typename RType<_AP_W2,_AP_I2,_AP_S2>::mult r; + r.V = V * op2.V; + return r; + } + + template + static INLINE ap_fixed_base multiply(const ap_fixed_base<_AP_W1,_AP_I1,_AP_S1>& op1, const + ap_fixed_base<_AP_W2,_AP_I2,_AP_S2>& op2) { + ap_private<_AP_W+_AP_W2, _AP_S> OP1=op1.V; + ap_private<_AP_W2,_AP_S2> OP2=op2.V; + return OP1*OP2; + } + + template + INLINE typename RType<_AP_W2,_AP_I2,_AP_S2>::div + operator / (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + enum {F2 = _AP_W2-_AP_I2, _W1=AP_MAX(_AP_W + AP_MAX(F2, 0), _AP_W2), + _W2=AP_MAX(_AP_W2,AP_MAX(_AP_W + AP_MAX(F2, 0), _AP_W2))}; + ap_private<_W1, _AP_S> dividend = (ap_private<_W1, _AP_S>(V)) << ((_W1>_AP_W)?F2:0); + ap_private<_W1, _AP_S2> divisior = ap_private<_W2, _AP_S2>(op2.V); + ap_private<_W1, _AP_S> ret = ap_private<_W1,_AP_S> ((_AP_S||_AP_S2) ? dividend.sdiv(divisior): dividend.udiv(divisior)); + typename RType<_AP_W2, _AP_I2, _AP_S2>::div r; + r.V = ret; + return r; + } +#define OP_BIN_AF(Sym, Rty, Width, Sign, Fun) \ + template \ + INLINE typename RType<_AP_W2,_AP_I2,_AP_S2>::Rty \ + operator Sym (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const \ + { \ + enum {_AP_F=_AP_W-_AP_I, F2=_AP_W2-_AP_I2}; \ + typename RType<_AP_W2,_AP_I2,_AP_S2>::Rty r, lhs(*this), rhs(op2); \ + r.V = lhs.V.Fun(rhs.V); \ + return r; \ + } \ + INLINE typename RType<_AP_W,_AP_I,_AP_S>::Rty \ + operator Sym (const ap_fixed_base& op2) const \ + { \ + typename RType<_AP_W,_AP_I,_AP_S>::Rty r; \ + r.V = V Sym op2.V; \ + return r; \ + } \ + + OP_BIN_AF(+, plus, plus_w, plus_s, Add) + OP_BIN_AF(-, minus, minus_w, minus_s, Sub) + +#define OP_LOGIC_BIN_AF(Sym, Rty, Width, Sign) \ + template \ + INLINE typename RType<_AP_W2,_AP_I2,_AP_S2>::Rty \ + operator Sym (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const \ + { \ + typename RType<_AP_W2,_AP_I2,_AP_S2>::Rty r, lhs(*this), rhs(op2); \ + r.V=lhs.V Sym rhs.V; \ + return r; \ + } \ + INLINE typename RType<_AP_W,_AP_I,_AP_S>::Rty \ + operator Sym (const ap_fixed_base& op2) const \ + { \ + typename RType<_AP_W,_AP_I,_AP_S>::Rty r; \ + r.V = V Sym op2.V; \ + return r; \ + } \ + INLINE typename RType<_AP_W,_AP_I,_AP_S>::Rty operator Sym(int op2) const \ + { \ + return V Sym (op2<<(_AP_W - _AP_I)); \ + } + OP_LOGIC_BIN_AF(&, logic, logic_w, logic_s) + OP_LOGIC_BIN_AF(|, logic, logic_w, logic_s) + OP_LOGIC_BIN_AF(^, logic, logic_w, logic_s) + + ///Arithmic : assign + //------------------------------------------------------------------------- +#define OP_ASSIGN_AF(Sym) \ + template \ + INLINE ap_fixed_base& operator Sym##= (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) \ + { \ + *this=operator Sym (op2) ; \ + return *this; \ + } + + OP_ASSIGN_AF(+) + OP_ASSIGN_AF(-) + OP_ASSIGN_AF(&) + OP_ASSIGN_AF(|) + OP_ASSIGN_AF(^) + OP_ASSIGN_AF(*) + OP_ASSIGN_AF(/) + + ///Prefix increment, decrement + //------------------------------------------------------------------------- + INLINE ap_fixed_base& operator ++() { + operator+=(ap_fixed_base<1,1,false>(1)); //SystemC's semantics + return *this; + } + + INLINE ap_fixed_base& operator --() { + operator-=(ap_fixed_base<1,1,false>(1)); //SystemC's semantics + return *this; + } + + //Postfix increment, decrement + //------------------------------------------------------------------------- + INLINE const ap_fixed_base operator ++(int) { + ap_fixed_base t(*this); + operator++(); + return t; + } + + INLINE const ap_fixed_base operator --(int) { + ap_fixed_base t = *this; + operator--(); + return t; + } + + ///Unary arithmetic + //------------------------------------------------------------------------- + INLINE ap_fixed_base operator +() {return *this;} + + INLINE ap_fixed_base<_AP_W + 1, _AP_I + 1, true> operator -() const { + ap_fixed_base<_AP_W + 1, _AP_I + 1, true> Tmp(*this); + Tmp.V = - Tmp.V; + return Tmp; + } + + INLINE ap_fixed_base<_AP_W,_AP_I,true,_AP_Q,_AP_O, _AP_N> getNeg() { + ap_fixed_base<_AP_W,_AP_I,true,_AP_Q,_AP_O, _AP_N> Tmp(*this); + Tmp.V=-Tmp.V; + return Tmp; + } + + ///Not (!) + //------------------------------------------------------------------------- + INLINE bool operator !() const { + return !V; + } + + ///Bitwise complement + //------------------------------------------------------------------------- + INLINE ap_fixed_base<_AP_W, _AP_I, _AP_S> + operator ~() const { + ap_fixed_base<_AP_W, _AP_I, _AP_S> res(*this); + res.V.flip(); + return res; + } + + ///Shift + ///template argument as shift value + template + INLINE ap_fixed_base<_AP_W, _AP_I + _AP_SHIFT, _AP_S> lshift () const { + ap_fixed_base<_AP_W, _AP_I + _AP_SHIFT, _AP_S> r; + r.V = V; + return r; + } + + template + INLINE ap_fixed_base<_AP_W, _AP_I - _AP_SHIFT, _AP_S> rshift () const { + ap_fixed_base<_AP_W, _AP_I - _AP_SHIFT, _AP_S> r; + r.V = V; + return r; + } + + //Because the return type is the type of the the first operand, shift assign + //operators do not carry out any quantization or overflow + //While systemc, shift assigns for sc_fixed/sc_ufixed will result in + //quantization or overflow (depending on the mode of the first operand) + //------------------------------------------------------------------------- + INLINE ap_fixed_base operator << (int sh) const { + ap_fixed_base r; + bool isNeg=(sh&0x80000000) != 0; + sh=isNeg?-sh:sh; + bool shiftoverflow = sh >= _AP_W; + bool NegSrc = V.isNegative(); + if (isNeg) { + if (shiftoverflow) + NegSrc?r.V.set():r.V.clear(); + else + r.V=_AP_S?V.ashr(sh):V.lshr(sh); + } else { + if (shiftoverflow) + r.V.clear(); + else + r.V=V< 1 && sh <= _AP_W) + rb = (V << (_AP_W - sh + 1 )) != 0; + else if (sh > _AP_W) + rb = V != 0; + r.quantization_adjust(qb, rb, NegSrc); + } else if (isNeg == false && _AP_O != AP_WRAP) { + bool allones, allzeros; + if (sh < _AP_W ) { + ap_private<_AP_W, _AP_S > range1 = V.lshr(_AP_W - sh - 1); + allones = range1.isAllOnesValue(); + allzeros = range1.isMinValue(); + } else { + allones = false; + allzeros = V.isMinValue(); + } + bool overflow = !allzeros && !NegSrc; + bool underflow = !allones && NegSrc; + if (_AP_O == AP_SAT_SYM && _AP_S) + underflow |= NegSrc && (_AP_W > 1 ? r.V.isMinSignedValue():true); + bool lD = false; + if ( sh < _AP_W ) lD = V[_AP_W - sh - 1]; + r.overflow_adjust(underflow, overflow, lD, NegSrc); + } +#endif + return r; + } + + template + INLINE ap_fixed_base operator<<(const ap_private<_AP_W2,true>& op2) const { + int sh = op2.to_int(); + return operator << (sh); + } + + INLINE ap_fixed_base operator << (unsigned int sh ) const { + ap_fixed_base r; + bool shiftoverflow = sh >= _AP_W; + r.V = shiftoverflow ? ap_private<_AP_W, _AP_S >(0) : V << sh; + if (sh == 0) return r; +#ifdef __SC_COMPATIBLE__ + bool NegSrc = V.isNegative(); + if (_AP_O != AP_WRAP) { + bool allones, allzeros; + if (sh < _AP_W ) { + ap_private<_AP_W, _AP_S > range1 = V.lshr(_AP_W - sh -1); + allones = range1.isAllOnesValue(); + allzeros = range1.isMinValue(); + } else { + allones = false; + allzeros = V.isMinValue(); + } + bool overflow = !allzeros && !NegSrc; + bool underflow = !allones && NegSrc; + if (_AP_O == AP_SAT_SYM && _AP_S) + underflow |= NegSrc && (_AP_W > 1 ? r.V.isMinSignedValue():true); + bool lD = false; + if ( sh < _AP_W ) lD = V[_AP_W - sh - 1]; + r.overflow_adjust(underflow, overflow, lD, NegSrc); + } +#endif + return r; + } + + template + INLINE ap_fixed_base operator << (const ap_private<_AP_W2,false>& op2) const { + unsigned int sh = op2.to_uint(); + return operator << (sh); + } + + INLINE ap_fixed_base operator >> (int sh) const { + ap_fixed_base r; + bool isNeg=(sh&0x80000000) != 0; + bool NegSrc = V.isNegative(); + sh=isNeg?-sh:sh; + bool shiftoverflow = sh >= _AP_W; + if (isNeg && !shiftoverflow) r.V=V< 1 && sh <= _AP_W) + rb = (V << (_AP_W - sh + 1 )) != 0; + else if (sh > _AP_W) + rb = V != 0; + r.quantization_adjust(qb, rb, NegSrc); + } else if (isNeg == true && _AP_O != AP_WRAP) { + bool allones, allzeros; + if (sh < _AP_W ) { + ap_private<_AP_W, _AP_S > range1 = V.lshr(_AP_W - sh - 1); + allones = range1.isAllOnesValue(); + allzeros = range1.isMinValue(); + } else { + allones = false; + allzeros = V.isMinValue(); + } + bool overflow = !allzeros && !NegSrc; + bool underflow = !allones && NegSrc; + if (_AP_O == AP_SAT_SYM && _AP_S) + underflow |= NegSrc && (_AP_W > 1 ? r.V.isMinSignedValue():true); + bool lD = false; + if ( sh < _AP_W ) lD = V[_AP_W - sh - 1]; + r.overflow_adjust(underflow, overflow, lD, NegSrc); + } +#endif + return r; + } + + template + INLINE ap_fixed_base operator >> (const ap_private<_AP_W2,true>& op2) const { + int sh = op2.to_int(); + return operator >> (sh); + } + + INLINE ap_fixed_base operator >> (unsigned int sh) const { + ap_fixed_base r; + bool NegSrc = V.isNegative(); + bool shiftoverflow = sh >= _AP_W; + if (shiftoverflow) + NegSrc?r.V.set():r.V.clear(); + else + r.V=_AP_S?V.ashr(sh):V.lshr(sh); +#ifdef __SC_COMPATIBLE__ + if (sh == 0) return r; + if (_AP_Q != AP_TRN) { + bool qb = false; + if (sh <= _AP_W) qb = V[sh - 1]; + bool rb = false; + if (sh > 1 && sh <= _AP_W) + rb = (V << (_AP_W - sh + 1 )) != 0; + else if (sh > _AP_W) + rb = V != 0; + r.quantization_adjust(qb, rb, NegSrc); + } +#endif + return r; + } + + template + INLINE ap_fixed_base operator >> (const ap_private<_AP_W2,false>& op2) const { + unsigned int sh = op2.to_uint(); + return operator >> (sh); + } + + ///shift assign + //------------------------------------------------------------------------- +#define OP_AP_SHIFT_AP_ASSIGN_AF(Sym) \ + template \ + INLINE ap_fixed_base& operator Sym##=(const ap_private<_AP_W2,_AP_S2>& op2) \ + { \ + *this=operator Sym (op2); \ + return *this; \ + } + + OP_AP_SHIFT_AP_ASSIGN_AF(<<) + OP_AP_SHIFT_AP_ASSIGN_AF(>>) + + ///Support shift(ap_fixed_base) +#define OP_AP_SHIFT_AF(Sym) \ + template \ + INLINE ap_fixed_base operator Sym (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const \ + { \ + return operator Sym (op2.to_ap_private()); \ + } \ + template \ + INLINE ap_fixed_base& operator Sym##= (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) \ + { \ + *this=operator Sym (op2); \ + return *this; \ + } + + OP_AP_SHIFT_AF(<<) + OP_AP_SHIFT_AF(>>) + + INLINE ap_fixed_base& operator >>= (unsigned int sh) { + *this = operator >> (sh); + return *this; + } + + INLINE ap_fixed_base& operator <<= (unsigned int sh) { + *this = operator << (sh); + return *this; + } + + INLINE ap_fixed_base& operator >>= (int sh) { + *this = operator >> (sh); + return *this; + } + + INLINE ap_fixed_base& operator <<= (int sh) { + *this = operator << (sh); + return *this; + } + + ///Comparisons + //------------------------------------------------------------------------- + template + INLINE bool operator == (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + enum {_AP_F=_AP_W-_AP_I,F2=_AP_W2-_AP_I2, shAmt1 = AP_MAX(F2-_AP_F, 0), shAmt2 = AP_MAX(_AP_F-F2,0), _AP_W3 = (_AP_F==F2) ? AP_MAX(_AP_W,_AP_W2) : AP_MAX(_AP_W+shAmt1, _AP_W2+shAmt2)}; + ap_private<_AP_W3, _AP_S > OP1= ap_private<_AP_W3, _AP_S >(V)< OP2=ap_private<_AP_W3,_AP_S2 >(op2.V)< + INLINE bool operator != (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + return !(*this==op2); + } + + template + INLINE bool operator > (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + enum {_AP_F=_AP_W-_AP_I,F2=_AP_W2-_AP_I2, shAmt1 = AP_MAX(F2-_AP_F, 0), shAmt2 = AP_MAX(_AP_F-F2,0), _AP_W3 = (_AP_F==F2) ? AP_MAX(_AP_W,_AP_W2) : AP_MAX(_AP_W+shAmt1, _AP_W2+shAmt2)}; + ap_private<_AP_W3, _AP_S > OP1= ap_private<_AP_W3, _AP_S >(V)< OP2=ap_private<_AP_W3,_AP_S2 >(op2.V)< + INLINE bool operator <= (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + return !(*this>op2); + } + + template + INLINE bool operator < (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + enum {_AP_F=_AP_W-_AP_I,F2=_AP_W2-_AP_I2, shAmt1 = AP_MAX(F2-_AP_F, 0), shAmt2 = AP_MAX(_AP_F-F2,0), _AP_W3 = (_AP_F==F2) ? AP_MAX(_AP_W,_AP_W2) : AP_MAX(_AP_W+shAmt1, _AP_W2+shAmt2)}; + ap_private<_AP_W3, _AP_S > OP1= ap_private<_AP_W3, _AP_S >(V)< OP2=ap_private<_AP_W3,_AP_S2 >(op2.V)< + INLINE bool operator >= (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + return !(*this) + DOUBLE_CMP_AF(>=) + DOUBLE_CMP_AF(<) + DOUBLE_CMP_AF(<=) + + // Bit and Slice Select + INLINE af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N> operator [] (unsigned int index) { + assert(index<_AP_W&&"Attemping to read bit beyond MSB"); + return af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>(this, index); + } + + INLINE af_bit_ref<_AP_W, _AP_I,_AP_S,_AP_Q,_AP_O, _AP_N> bit(unsigned int index) { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>(this, index); + } + + template + INLINE af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N> bit (const ap_private<_AP_W2,_AP_S2>& index) { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>(this, index.to_int()); + } + + INLINE bool bit (unsigned int index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return V[index]; + } + + INLINE bool operator [] (unsigned int index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return V[index]; + } + + template + INLINE bool bit (const ap_private<_AP_W2, _AP_S2>& index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return V[index.to_uint()]; + } + + template + INLINE bool operator [] (const ap_private<_AP_W2, _AP_S2>& index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return V[index.to_uint()]; + } + + INLINE af_bit_ref<_AP_W, _AP_I,_AP_S,_AP_Q,_AP_O, _AP_N> get_bit(int index) { + assert(index < _AP_I && "Attempting to read bit beyond MSB"); + assert(index >= _AP_I - _AP_W&& "Attempting to read bit beyond MSB"); + return af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>(this, index + _AP_W - _AP_I); + } + + template + INLINE af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N> get_bit (const ap_private<_AP_W2, true>& index) { + assert(index >= _AP_I - _AP_W && "Attempting to read bit with negative index"); + assert(index < _AP_I && "Attempting to read bit beyond MSB"); + return af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>(this, index.to_int() + _AP_W - _AP_I); + } + + INLINE bool get_bit (int index) const { + assert(index >= _AP_I - _AP_W && "Attempting to read bit with negative index"); + assert(index < _AP_I && "Attempting to read bit beyond MSB"); + return V[index + _AP_W - _AP_I]; + } + + template + INLINE bool get_bit (const ap_private<_AP_W2, true>& index) const { + assert(index >= _AP_I - _AP_W && "Attempting to read bit with negative index"); + assert(index < _AP_I && "Attempting to read bit beyond MSB"); + return V[index.to_int() + _AP_W - _AP_I]; + } + + INLINE af_range_ref<_AP_W,_AP_I,_AP_S, _AP_Q, _AP_O, _AP_N> + range(int Hi, int Lo) { + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>(this, Hi, Lo); + } + + INLINE af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> + operator () (int Hi, int Lo) { + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>(this, Hi, Lo); + } + + INLINE af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> + range(int Hi, int Lo) const { + assert((Hi < _AP_W) && (Lo < _AP_W) &&"Out of bounds in range()"); + return af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>(const_cast(this), Hi, Lo); + } + + INLINE af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> + operator () (int Hi, int Lo) const { + return this->range(Hi, Lo); + } + + template + INLINE af_range_ref<_AP_W,_AP_I,_AP_S, _AP_Q, _AP_O, _AP_N> + range(const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>(this, Hi, Lo); + } + + template + INLINE af_range_ref<_AP_W,_AP_I,_AP_S, _AP_Q, _AP_O, _AP_N> + operator () (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>(this, Hi, Lo); + } + + template + INLINE af_range_ref<_AP_W,_AP_I,_AP_S, _AP_Q, _AP_O, _AP_N> + range(const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) const { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>(const_cast< + ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>*>(this), + Hi, Lo); + } + + template + INLINE af_range_ref<_AP_W,_AP_I,_AP_S, _AP_Q, _AP_O, _AP_N> + operator () (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) const { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + return this->range(Hi, Lo); + } + + INLINE af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> + range() { + return this->range(_AP_W - 1, 0); + } + + INLINE af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> + range() const { + return this->range(_AP_W - 1, 0); + } + + INLINE bool is_zero () const { + return V.isMinValue(); + } + + INLINE bool is_neg () const { + if (V.isNegative()) + return true; + return false; + } + + INLINE int wl () const { + return _AP_W; + } + + INLINE int iwl () const { + return _AP_I; + } + + INLINE ap_q_mode q_mode () const { + return _AP_Q; + } + + INLINE ap_o_mode o_mode () const { + return _AP_O; + } + + INLINE int n_bits () const { + return 0; + } + + //private: +public: + ap_private<_AP_W, _AP_S> V; +}; + +template +std::string ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>::to_string( + uint8_t radix, bool sign) const { + std::string str; + str.clear(); + char step; + std::string prefix; + switch (radix) { + case 2 : prefix = "0b"; step = 1; break; + case 8 : prefix = "0o"; step = 3; break; + case 16 : prefix = "0x"; step = 4; break; + default : break; + } + if (_AP_W <= _AP_I) + str = this->to_ap_private().to_string(radix, + radix == 10 ? _AP_S : sign); + else { + if (radix == 10) { + bool isNeg = _AP_S && V.isNegative(); + if (_AP_I > 0) { + ap_private int_part(0); + int_part = this->to_ap_private(); + str += int_part.to_string(radix, false); + } else { + if (isNeg) str += '-'; + } + ap_fixed_base<_AP_W, _AP_I, _AP_S> tmp(*this); + if (isNeg && _AP_I <= 0) tmp = -tmp; + ap_fixed_base<_AP_W - AP_MIN(_AP_I, 0), 0, false> frac_part = tmp; + if (frac_part == 0) return str; + str += "."; + while (frac_part != 0) { + char digit = (frac_part * radix).to_ap_private(); + str += static_cast(digit + '0'); + frac_part *= radix; + } + } else { + if (_AP_I > 0) { + for (signed i = _AP_W - _AP_I; i < _AP_W; i += step) { + + char digit = (char)(this->range(AP_MIN(i + step - 1, _AP_W - 1), i)); + str = (digit < 10 ? static_cast(digit + '0') : + static_cast(digit - 10 + 'a')) + str; + } + } + str += '.'; + ap_fixed_base tmp(*this); + for (signed i = _AP_W - _AP_I - 1; i >= 0; i -= step) { + char digit = (char)(tmp.range(i, AP_MAX(0, i - step + 1))); + str += digit < 10 ? static_cast(digit + '0') : + static_cast(digit - 10 + 'a'); + } + } + } + str = prefix + str; + return str; +} + +template +INLINE void b_not(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op) { + ret.V = op.V; + ret.V.flip(); +} + +template +INLINE void b_and(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op1, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op2) { + ret.V = op1.V & op2.V; +} + +template +INLINE void b_or(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op1, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op2) { + ret.V = op1.V | op2.V; +} + +template +INLINE void b_xor(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op1, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op2) { + ret.V = op1.V ^ op2.V; +} + +template +INLINE void neg(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) { + ap_fixed_base<_AP_W2+!_AP_S2, _AP_I2+!_AP_S2, true, _AP_Q2, _AP_O2, _AP_N2> Tmp; + Tmp.V = - op.V; + ret = Tmp; +} + +template +INLINE void neg(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op) { + ret.V = -op.V; +} + +template +INLINE void lshift(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op, + int i) { + ap_fixed_base<_AP_W2 - _AP_I2 + AP_MAX(_AP_I, _AP_I2), AP_MAX(_AP_I, _AP_I2), _AP_S2, _AP_Q2, _AP_O2, _AP_N2> Tmp; + Tmp = op; + Tmp.V <<= i; + ret = Tmp; +} + +template +INLINE void lshift(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op, + int i) { + ret.V = op.V << i; +} + +template +INLINE void rshift(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op, + int i) { + ap_fixed_base<_AP_I2 + AP_MAX(_AP_W - _AP_I, _AP_W2 - _AP_I2), _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> Tmp; + Tmp = op; + Tmp.V = _AP_S2 ? Tmp.V.ashr(i): Tmp.V.lshr(i); + ret = Tmp; +} + +template +INLINE void rshift(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op, + int i) { + ret.V = _AP_S ? op.V.ashr(i): op.V.lshr(i); +} + +#define AF_CTOR_SPEC_BASE(_AP_W,_AP_S,C_TYPE) \ + template<> INLINE ap_fixed_base<_AP_W,_AP_W,_AP_S,AP_TRN,AP_WRAP>::ap_fixed_base(C_TYPE i_op):V(i_op) \ + { \ + } + +#define AF_CTOR_SPEC(__W,C_TYPE) \ + AF_CTOR_SPEC_BASE(__W,true,C_TYPE) \ + AF_CTOR_SPEC_BASE(__W,false,C_TYPE) + +AF_CTOR_SPEC(1,bool) +AF_CTOR_SPEC(8, signed char) +AF_CTOR_SPEC(8, unsigned char) +AF_CTOR_SPEC(16, signed short) +AF_CTOR_SPEC(16, unsigned short) +AF_CTOR_SPEC(32, signed int) +AF_CTOR_SPEC(32, unsigned int) +AF_CTOR_SPEC(64, ap_slong) +AF_CTOR_SPEC(64, ap_ulong) + +///Output streaming +//----------------------------------------------------------------------------- +template +INLINE std::ostream& +operator <<(std::ostream& os, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& x) { + os << x.to_double(); + return os; +} + +///Input streaming +//----------------------------------------------------------------------------- +template +INLINE std::istream& +operator >> (std::istream& os, ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& x) { + double d; + os >> d; + x = ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>(x); + return os; +} + +template +INLINE void print(const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& x) { + ap_private<_AP_W,_AP_S> data=x.V; + if (_AP_I>0) { + const ap_private<_AP_I,_AP_S> p1=data>>(_AP_W-_AP_I); + print(p1); + + } else + printf("0"); + printf("."); + if (_AP_I<_AP_W) { + const ap_private<_AP_W-_AP_I,false> p2=data; + print(p2,false); + } +} + +///Operators mixing Integers with ap_fixed_base +//----------------------------------------------------------------------------- +#if 1 +#define AF_BIN_OP_WITH_INT_SF(BIN_OP,C_TYPE,_AP_W2,_AP_S2,RTYPE) \ + template \ + INLINE typename ap_fixed_base<_AP_W,_AP_I,_AP_S>::template RType<_AP_W2,_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP (const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) \ + { \ + return op.operator BIN_OP(ap_private<_AP_W2,_AP_S2>(i_op)); \ + } +#define AF_BIN_OP_WITH_INT(BIN_OP, C_TYPE, _AP_W2,_AP_S2,RTYPE) \ + template \ + INLINE typename ap_fixed_base<_AP_W,_AP_I,_AP_S>::template RType<_AP_W2,_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP (const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) \ + { \ + return op.operator BIN_OP (ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op)); \ + } \ + \ + template \ + INLINE typename ap_fixed_base<_AP_W,_AP_I,_AP_S>::template RType<_AP_W2,_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP (C_TYPE i_op, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op) \ + { \ + return ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op).operator BIN_OP (op); \ + } + +#else +#define AF_BIN_OP_WITH_INT_SF(BIN_OP,C_TYPE,_AP_W2,_AP_S2,RTYPE) \ + template \ + INLINE typename ap_fixed_base<_AP_W,_AP_I,_AP_S>::template RType<_AP_W2,_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP (const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) \ + { \ + return op BIN_OP (i_op); \ + } +#define AF_BIN_OP_WITH_INT(BIN_OP, C_TYPE, _AP_W2,_AP_S2,RTYPE) \ + template \ + INLINE typename ap_fixed_base<_AP_W,_AP_I,_AP_S>::template RType<_AP_W2,_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP (const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) \ + { \ + return op.V BIN_OP (i_op<<(_AP_W-_AP_I)); \ + } \ + \ + \ + template \ + INLINE typename ap_fixed_base<_AP_W,_AP_I,_AP_S>::template RType<_AP_W2,_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP (C_TYPE i_op, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op) \ + { \ + return ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op).operator BIN_OP (op); \ + } + +#endif +#if 1 +#define AF_REL_OP_WITH_INT(REL_OP, C_TYPE, _AP_W2,_AP_S2) \ + template \ + INLINE bool operator REL_OP (const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) \ + { \ + return op.operator REL_OP (ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op)); \ + } \ + \ + \ + template \ + INLINE bool operator REL_OP (C_TYPE i_op, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op) \ + { \ + return ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op).operator REL_OP (op); \ + } +#else +#define AF_REL_OP_WITH_INT(REL_OP, C_TYPE, _AP_W2,_AP_S2) \ + template \ + INLINE bool operator REL_OP (const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) \ + { \ + return op.V.operator REL_OP (i_op<<(_AP_W-_AP_I)); \ + } \ + \ + \ + template \ + INLINE bool operator REL_OP (C_TYPE i_op, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op) \ + { \ + return (i_op<<(_AP_W-_AP_I)) REL_OP (op.V.VAL); \ + } +#endif +#if 1 +#define AF_ASSIGN_OP_WITH_INT(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& operator ASSIGN_OP ( ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) { \ + return op.operator ASSIGN_OP (ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op)); \ + } +#define AF_ASSIGN_OP_WITH_INT_SF(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& operator ASSIGN_OP ( ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) { \ + return op.operator ASSIGN_OP (ap_private<_AP_W2,_AP_S2>(i_op)); \ + } +#else +#define AF_ASSIGN_OP_WITH_INT(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& operator ASSIGN_OP ( ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) { \ + return op.V.operator ASSIGN_OP (i_op); \ + } +#define AF_ASSIGN_OP_WITH_INT_SF(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& operator ASSIGN_OP ( ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) { \ + return op.V.operator ASSIGN_OP (i_op); \ + } +#endif + +#define AF_OPS_WITH_INT(C_TYPE, WI, SI) \ + AF_BIN_OP_WITH_INT(+, C_TYPE, WI, SI, plus) \ + AF_BIN_OP_WITH_INT(-, C_TYPE, WI, SI, minus) \ + AF_BIN_OP_WITH_INT(*, C_TYPE, WI, SI, mult) \ + AF_BIN_OP_WITH_INT(/, C_TYPE, WI, SI, div) \ + AF_BIN_OP_WITH_INT_SF(>>, C_TYPE, WI, SI, arg1) \ + AF_BIN_OP_WITH_INT_SF(<<, C_TYPE, WI, SI, arg1) \ + AF_BIN_OP_WITH_INT(&, C_TYPE, WI, SI, logic) \ + AF_BIN_OP_WITH_INT(|, C_TYPE, WI, SI, logic) \ + AF_BIN_OP_WITH_INT(^, C_TYPE, WI, SI, logic) \ + \ + AF_REL_OP_WITH_INT(==, C_TYPE, WI, SI) \ + AF_REL_OP_WITH_INT(!=, C_TYPE, WI, SI) \ + AF_REL_OP_WITH_INT(>, C_TYPE, WI, SI) \ + AF_REL_OP_WITH_INT(>=, C_TYPE, WI, SI) \ + AF_REL_OP_WITH_INT(<, C_TYPE, WI, SI) \ + AF_REL_OP_WITH_INT(<=, C_TYPE, WI, SI) \ + \ + AF_ASSIGN_OP_WITH_INT(+=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT(-=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT(*=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT(/=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT_SF(>>=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT_SF(<<=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT(&=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT(|=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT(^=, C_TYPE, WI, SI) + +AF_OPS_WITH_INT(bool, 1, false) +AF_OPS_WITH_INT(char, 8, true) +AF_OPS_WITH_INT(signed char, 8, true) +AF_OPS_WITH_INT(unsigned char, 8, false) +AF_OPS_WITH_INT(short, 16, true) +AF_OPS_WITH_INT(unsigned short, 16, false) +AF_OPS_WITH_INT(int, 32, true) +AF_OPS_WITH_INT(unsigned int, 32, false) +# if defined __x86_64__ +AF_OPS_WITH_INT(long, 64, true) +AF_OPS_WITH_INT(unsigned long, 64, false) +# else +AF_OPS_WITH_INT(long, 32, true) +AF_OPS_WITH_INT(unsigned long, 32, false) +# endif +AF_OPS_WITH_INT(ap_slong, 64, true) +AF_OPS_WITH_INT(ap_ulong, 64, false) + +#define AF_BIN_OP_WITH_AP_INT(BIN_OP, RTYPE) \ + template \ + INLINE typename ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>::template RType<_AP_W,_AP_I,_AP_S>::RTYPE \ + operator BIN_OP ( const ap_private<_AP_W2,_AP_S2>& i_op, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op) { \ + return ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op).operator BIN_OP (op); \ + } \ + template \ + INLINE typename ap_fixed_base<_AP_W,_AP_I,_AP_S>::template RType<_AP_W2,_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP ( const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, const ap_private<_AP_W2,_AP_S2>& i_op) { \ + return op.operator BIN_OP (ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op)); \ + } + +#define AF_REL_OP_WITH_AP_INT(REL_OP) \ + template \ + INLINE bool operator REL_OP ( const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, const ap_private<_AP_W2,_AP_S2>& i_op) { \ + return op.operator REL_OP ( ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op)); \ + } \ + template \ + INLINE bool operator REL_OP ( const ap_private<_AP_W2,_AP_S2>& i_op, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op) { \ + return ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op).operator REL_OP (op); \ + } + +#define AF_ASSIGN_OP_WITH_AP_INT(ASSIGN_OP) \ + template \ + INLINE ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& operator ASSIGN_OP ( ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, const ap_private<_AP_W2,_AP_S2>& i_op) { \ + return op.operator ASSIGN_OP (ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op)); \ + } \ + template \ + INLINE ap_private<_AP_W2,_AP_S2>& operator ASSIGN_OP ( ap_private<_AP_W2,_AP_S2>& i_op, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op) { \ + return i_op.operator ASSIGN_OP (op.to_ap_private()); \ + } + +AF_BIN_OP_WITH_AP_INT(+, plus) +AF_BIN_OP_WITH_AP_INT(-, minus) +AF_BIN_OP_WITH_AP_INT(*, mult) +AF_BIN_OP_WITH_AP_INT(/, div) +AF_BIN_OP_WITH_AP_INT(&, logic) +AF_BIN_OP_WITH_AP_INT(|, logic) +AF_BIN_OP_WITH_AP_INT(^, logic) + +AF_REL_OP_WITH_AP_INT(==) +AF_REL_OP_WITH_AP_INT(!=) +AF_REL_OP_WITH_AP_INT(>) +AF_REL_OP_WITH_AP_INT(>=) +AF_REL_OP_WITH_AP_INT(<) +AF_REL_OP_WITH_AP_INT(<=) + +AF_ASSIGN_OP_WITH_AP_INT(+=) +AF_ASSIGN_OP_WITH_AP_INT(-=) +AF_ASSIGN_OP_WITH_AP_INT(*=) +AF_ASSIGN_OP_WITH_AP_INT(/=) +AF_ASSIGN_OP_WITH_AP_INT(&=) +AF_ASSIGN_OP_WITH_AP_INT(|=) +AF_ASSIGN_OP_WITH_AP_INT(^=) + +#define AF_REF_REL_OP_MIX_INT(REL_OP, C_TYPE, _AP_W2, _AP_S2) \ +template \ + INLINE bool operator REL_OP ( const af_range_ref<_AP_W,_AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op, C_TYPE op2) { \ + return (ap_private<_AP_W, false>(op)).operator REL_OP (ap_private<_AP_W2,_AP_S2>(op2)); \ + } \ +template \ + INLINE bool operator REL_OP ( C_TYPE op2, const af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op) { \ + return ap_private<_AP_W2,_AP_S2>(op2).operator REL_OP (ap_private<_AP_W, false>(op)); \ + } \ +template \ + INLINE bool operator REL_OP ( const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op, C_TYPE op2) { \ + return (bool(op)) REL_OP op2; \ + } \ +template \ + INLINE bool operator REL_OP ( C_TYPE op2, const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op) { \ + return op2 REL_OP (bool(op)); \ + } + +#define AF_REF_REL_MIX_INT(C_TYPE, _AP_WI, _AP_SI) \ +AF_REF_REL_OP_MIX_INT(>, C_TYPE, _AP_WI, _AP_SI) \ +AF_REF_REL_OP_MIX_INT(<, C_TYPE, _AP_WI, _AP_SI) \ +AF_REF_REL_OP_MIX_INT(>=, C_TYPE, _AP_WI, _AP_SI) \ +AF_REF_REL_OP_MIX_INT(<=, C_TYPE, _AP_WI, _AP_SI) \ +AF_REF_REL_OP_MIX_INT(==, C_TYPE, _AP_WI, _AP_SI) \ +AF_REF_REL_OP_MIX_INT(!=, C_TYPE, _AP_WI, _AP_SI) + +AF_REF_REL_MIX_INT(bool, 1, false) +AF_REF_REL_MIX_INT(char, 8, true) +AF_REF_REL_MIX_INT(signed char, 8, true) +AF_REF_REL_MIX_INT(unsigned char, 8, false) +AF_REF_REL_MIX_INT(short, 16, true) +AF_REF_REL_MIX_INT(unsigned short, 16, false) +AF_REF_REL_MIX_INT(int, 32, true) +AF_REF_REL_MIX_INT(unsigned int, 32, false) +# if defined __x86_64__ +AF_REF_REL_MIX_INT(long, 64, true) +AF_REF_REL_MIX_INT(unsigned long, 64, false) +# else +AF_REF_REL_MIX_INT(long, 32, true) +AF_REF_REL_MIX_INT(unsigned long, 32, false) +# endif +AF_REF_REL_MIX_INT(ap_slong, 64, true) +AF_REF_REL_MIX_INT(ap_ulong, 64, false) + +#define AF_REF_REL_OP_AP_INT(REL_OP) \ +template \ + INLINE bool operator REL_OP ( const af_range_ref<_AP_W,_AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op, const ap_private<_AP_W2, _AP_S> &op2) { \ + return (ap_private<_AP_W, false>(op)).operator REL_OP (op2); \ + } \ +template \ + INLINE bool operator REL_OP (const ap_private<_AP_W2, _AP_S2> &op2, const af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op) { \ + return op2.operator REL_OP (ap_private<_AP_W, false>(op)); \ + } \ +template \ + INLINE bool operator REL_OP ( const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op, const ap_private<_AP_W2, _AP_S2> &op2) { \ + return (ap_private<1, false>(op)).operator REL_OP (op2); \ + } \ +template \ + INLINE bool operator REL_OP ( const ap_private<_AP_W2, _AP_S2> &op2, const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op) { \ + return op2.operator REL_OP (ap_private<1,false>(op)); \ + } + +AF_REF_REL_OP_AP_INT(>) +AF_REF_REL_OP_AP_INT(<) +AF_REF_REL_OP_AP_INT(>=) +AF_REF_REL_OP_AP_INT(<=) +AF_REF_REL_OP_AP_INT(==) +AF_REF_REL_OP_AP_INT(!=) + +// Relational Operators with double +template +INLINE bool operator == ( double op1, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op2) { + return op2.operator == (op1); +} + +template +INLINE bool operator != ( double op1, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op2) { + return op2.operator != (op1); +} + +template +INLINE bool operator > ( double op1, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op2) { + return op2.operator < (op1); +} + +template +INLINE bool operator >= ( double op1, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op2) { + return op2.operator <= (op1); +} + +template +INLINE bool operator < ( double op1, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op2) { + return op2.operator > (op1); +} + +template +INLINE bool operator <= ( double op1, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op2) { + return op2.operator >= (op1); +} + +#endif /* #ifndef __AESL_GCC_AP_FIXED_H__ */ \ No newline at end of file diff --git a/hls_2018/router_05/etc/ap_int_sim.h b/hls_2018/router_05/etc/ap_int_sim.h new file mode 100755 index 0000000..887ccd8 --- /dev/null +++ b/hls_2018/router_05/etc/ap_int_sim.h @@ -0,0 +1,1629 @@ +/* + * Copyright 2012 Xilinx, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __AESL_GCC_AP_INT_H__ +#define __AESL_GCC_AP_INT_H__ + +#ifndef __cplusplus +#error C++ is required to include this header file +#endif /* #ifndef __cplusplus */ + +#undef _AP_DEBUG_ +#include +#include + +// for safety +#if (defined(_AP_N)|| defined(_AP_C)) +#error One or more of the following is defined: _AP_N, _AP_C. Definition conflicts with their usage as template parameters. +#endif /* #if (defined(_AP_N)|| defined(_AP_C)) */ + +// for safety +#if (defined(_AP_W) || defined(_AP_I) || defined(_AP_S) || defined(_AP_Q) || defined(_AP_O) || defined(_AP_W2) || defined(_AP_I2) || defined(_AP_S2) || defined(_AP_Q2) || defined(_AP_O2)) +#error One or more of the following is defined: _AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2. Definition conflicts with their usage as template parameters. +#endif /* #if (defined(_AP_W) || defined(_AP_I) || defined(_AP_S) || defined(_AP_Q) || defined(_AP_O) || defined(_AP_W2) || defined(_AP_I2) || defined(_AP_S2) || defined(_AP_Q2) || defined(_AP_O2)) */ + +//for safety +#if (defined(_AP_W3) || defined(_AP_S3) || defined(_AP_W4) || defined(_AP_S4)) +#error One or more of the following is defined: _AP_W3, _AP_S3, _AP_W4,_AP_S4. Definition conflicts with their usage as template parameters. +#endif /* #if (defined(_AP_W3) || defined(_AP_S3) || defined(_AP_W4) || defined(_AP_S4)) */ + +//for safety +#if (defined(_AP_W1) || defined(_AP_S1) || defined(_AP_I1) || defined(_AP_T) || defined(_AP_T1) || defined(_AP_T2) || defined(_AP_T3) || defined(_AP_T4)) +#error One or more of the following is defined: _AP_W1, _AP_S1, _AP_I1, _AP_T, _AP_T1, _AP_T2, _AP_T3, _AP_T4. Definition conflicts with their usage as template parameters. +#endif /* #if (defined(_AP_W1) || defined(_AP_S1) || defined(_AP_I1) || defined(_AP_T) || defined(_AP_T1) || defined(_AP_T2) || defined(_AP_T3) || defined(_AP_T4)) */ + +#define __AESL_APDT_IN_SCFLOW__ +#ifndef __AESL_APDT_IN_SCFLOW__ + #include "etc/ap_private.h" +#else + #include "../etc/ap_private.h" +#endif /* #ifndef __AESL_APDT_IN_SCFLOW__ */ + +#ifdef _AP_DEBUG_ + #define AP_DEBUG(s) s +#else + #define AP_DEBUG(s) +#endif /* #ifdef _AP_DEBUG_ */ + +#ifndef __SIMULATION__ + #define __SIMULATION__ +#endif /* #ifndef __SIMULATION__ */ + +#if !(defined SYSTEMC_H) && !(defined SYSTEMC_INCLUDED) + #ifndef SC_TRN + #define SC_TRN AP_TRN + #endif /* #ifndef SC_TRN */ + #ifndef SC_RND + #define SC_RND AP_RND + #endif /* #ifndef SC_RND */ + #ifndef SC_TRN_ZERO + #define SC_TRN_ZERO AP_TRN_ZERO + #endif /* #ifndef SC_TRN_ZERO */ + #ifndef SC_RND_ZERO + #define SC_RND_ZERO AP_RND_ZERO + #endif /* #ifndef SC_RND_ZERO */ + #ifndef SC_RND_INF + #define SC_RND_INF AP_RND_INF + #endif /* #ifndef SC_RND_INF */ + #ifndef SC_RND_MIN_INF + #define SC_RND_MIN_INF AP_RND_MIN_INF + #endif /* #ifndef SC_RND_MIN_INF */ + #ifndef SC_RND_CONV + #define SC_RND_CONV AP_RND_CONV + #endif /* #ifndef SC_RND_CONV */ + #ifndef SC_WRAP + #define SC_WRAP AP_WRAP + #endif /* #ifndef SC_WRAP */ + #ifndef SC_SAT + #define SC_SAT AP_SAT + #endif /* #ifndef SC_SAT */ + #ifndef SC_SAT_ZERO + #define SC_SAT_ZERO AP_SAT_ZERO + #endif /* #ifndef SC_SAT_ZERO */ + #ifndef SC_SAT_SYM + #define SC_SAT_SYM AP_SAT_SYM + #endif /* #ifndef SC_SAT_SYM */ + #ifndef SC_WRAP_SM + #define SC_WRAP_SM AP_WRAP_SM + #endif /* #ifndef SC_WRAP_SM */ + #ifndef SC_BIN + #define SC_BIN AP_BIN + #endif /* #ifndef SC_BIN */ + #ifndef SC_OCT + #define SC_OCT AP_OCT + #endif /* #ifndef SC_OCT */ + #ifndef SC_DEC + #define SC_DEC AP_DEC + #endif /* #ifndef SC_DEC */ + #ifndef SC_HEX + #define SC_HEX AP_HEX + #endif /* #ifndef SC_HEX */ +#endif /* #if !(defined SYSTEMC_H) && !(defined SYSTEMC_INCLUDED) */ +#ifndef AP_INT_MAX_W +#define AP_INT_MAX_W 1024 +#endif +#define BIT_WIDTH_UPPER_LIMIT (1 << 15) +#if AP_INT_MAX_W > BIT_WIDTH_UPPER_LIMIT +#error "Bitwidth exceeds 32768 (1 << 15), the maximum allowed value" +#endif +#define MAX_MODE(BITS) ((BITS + 1023) / 1024) + +///Forward declaration +template struct ap_range_ref; +template struct ap_bit_ref; + +template struct ap_fixed_base; +template struct af_range_ref; +template struct af_bit_ref; +template class ap_uint; + +enum { + AP_BIN = 2, + AP_OCT = 8, + AP_DEC = 10, + AP_HEX = 16 +}; + +///Why to use reference? +///Because we will operate the original object indirectly by operating the +///result object directly after concating or part selecting + +///Proxy class which allows concatination to be used as rvalue(for reading) and +//lvalue(for writing) + +/// Concatination reference. +// ---------------------------------------------------------------- +template +struct ap_concat_ref { +#ifdef _MSC_VER + #pragma warning(disable: 4521 4522) +#endif /* #ifdef _MSC_VER */ + enum {_AP_WR=_AP_W1+_AP_W2,}; + _AP_T1& mbv1; + _AP_T2& mbv2; + + INLINE ap_concat_ref(const ap_concat_ref<_AP_W1, _AP_T1, + _AP_W2, _AP_T2>& ref): + mbv1(ref.mbv1), mbv2(ref.mbv2) {} + + INLINE ap_concat_ref(_AP_T1& bv1, _AP_T2& bv2):mbv1(bv1),mbv2(bv2) {} + + template + INLINE ap_concat_ref& operator = (const ap_private<_AP_W3,_AP_S3>& val) { + ap_private<_AP_W1+_AP_W2, false> vval(val); + int W_ref1=mbv1.length(); + int W_ref2=mbv2.length(); + ap_private<_AP_W1,false> mask1(-1); + mask1>>=_AP_W1-W_ref1; + ap_private<_AP_W2,false> mask2(-1); + mask2>>=_AP_W2-W_ref2; + mbv1.set(ap_private<_AP_W1,false>((vval>>W_ref2)&mask1)); + mbv2.set(ap_private<_AP_W2,false>(vval&mask2)); + return *this; + } + + INLINE ap_concat_ref& operator = (unsigned long long val) { + ap_private<_AP_W1+_AP_W2, false> tmpVal(val); + return operator = (tmpVal); + } + + template + INLINE ap_concat_ref& operator = + (const ap_concat_ref <_AP_W3, _AP_T3, _AP_W4, _AP_T4>& val) { + ap_private<_AP_W1+_AP_W2, false> tmpVal(val); + return operator = (tmpVal); + } + + INLINE ap_concat_ref& operator = + (const ap_concat_ref <_AP_W1, _AP_T1, _AP_W2, _AP_T2>& val) { + ap_private<_AP_W1+_AP_W2, false> tmpVal(val); + return operator = (tmpVal); + } + + template + INLINE ap_concat_ref& operator =(const ap_bit_ref<_AP_W3, _AP_S3>& val) { + ap_private<_AP_W1+_AP_W2, false> tmpVal(val); + return operator = (tmpVal); + } + + template + INLINE ap_concat_ref& operator =(const ap_range_ref<_AP_W3,_AP_S3>& val) { + ap_private<_AP_W1+_AP_W2, false> tmpVal(val); + return operator =(tmpVal); + } + + template + INLINE ap_concat_ref& operator= (const af_range_ref<_AP_W3, _AP_I3, _AP_S3, + _AP_Q3, _AP_O3, _AP_N3>& val) { + return operator = ((const ap_private<_AP_W3, false>)(val)); + } + + template + INLINE ap_concat_ref& operator= (const ap_fixed_base<_AP_W3, _AP_I3, _AP_S3, + _AP_Q3, _AP_O3, _AP_N3>& val) { + return operator = (val.to_ap_private()); + } + + template + INLINE ap_concat_ref& operator= (const af_bit_ref<_AP_W3, _AP_I3, _AP_S3, + _AP_Q3, _AP_O3, _AP_N3>& val) { + return operator=((unsigned long long)(bool)(val)); + } + + + INLINE operator ap_private<_AP_WR, false> () const { + return get(); + } + + INLINE operator unsigned long long () const { + return get().to_uint64(); + } + + template + INLINE ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, ap_range_ref<_AP_W3, _AP_S3> > + operator, (const ap_range_ref<_AP_W3, _AP_S3> &a2) { + return ap_concat_ref<_AP_WR, ap_concat_ref, + _AP_W3, ap_range_ref<_AP_W3, _AP_S3> >(*this, + const_cast &>(a2)); + } + + template + INLINE ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, ap_private<_AP_W3, _AP_S3> > + operator, (ap_private<_AP_W3, _AP_S3> &a2) { + return ap_concat_ref<_AP_WR, ap_concat_ref, + _AP_W3, ap_private<_AP_W3, _AP_S3> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, ap_private<_AP_W3, _AP_S3> > + operator, (const ap_private<_AP_W3, _AP_S3> &a2) { + return ap_concat_ref<_AP_WR, ap_concat_ref, + _AP_W3, ap_private<_AP_W3, _AP_S3> >(*this, + const_cast&>(a2)); + } + + template + INLINE ap_concat_ref<_AP_WR, ap_concat_ref, 1, ap_bit_ref<_AP_W3, _AP_S3> > + operator, (const ap_bit_ref<_AP_W3, _AP_S3> &a2) { + return ap_concat_ref<_AP_WR, ap_concat_ref, + 1, ap_bit_ref<_AP_W3, _AP_S3> >(*this, + const_cast &>(a2)); + } + + template + INLINE ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3+_AP_W4, ap_concat_ref<_AP_W3,_AP_T3,_AP_W4,_AP_T4> > + operator, (const ap_concat_ref<_AP_W3,_AP_T3,_AP_W4,_AP_T4> &a2) + { + return ap_concat_ref<_AP_WR, ap_concat_ref, + _AP_W3+_AP_W4, ap_concat_ref<_AP_W3,_AP_T3,_AP_W4, + _AP_T4> >(*this, const_cast& >(a2)); + } + + template + INLINE + ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, af_range_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3> > + operator, (const af_range_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, + _AP_O3, _AP_N3> &a2) { + return ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, af_range_ref<_AP_W3, + _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3> >(*this, + const_cast& >(a2)); + } + + template + INLINE + ap_concat_ref<_AP_WR, ap_concat_ref, 1, af_bit_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3> > + operator, (const af_bit_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, + _AP_O3, _AP_N3> &a2) { + return ap_concat_ref<_AP_WR, ap_concat_ref, 1, af_bit_ref<_AP_W3, + _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3> >(*this, + const_cast& >(a2)); + } + + template + INLINE ap_private + operator & (const ap_private<_AP_W3,_AP_S3>& a2) { + return get() & a2; + } + + + template + INLINE ap_private + operator | (const ap_private<_AP_W3,_AP_S3>& a2) { + return get() | a2; + } + + + template + INLINE ap_private + operator ^ (const ap_private<_AP_W3,_AP_S3>& a2) { + return ap_private(get() ^ a2); + } + + INLINE const ap_private<_AP_WR, false> get() const + { + ap_private<_AP_W1+_AP_W2, false> tmpVal = ap_private<_AP_W1+_AP_W2, false> (mbv1.get()); + ap_private<_AP_W1+_AP_W2, false> tmpVal2 = ap_private<_AP_W1+_AP_W2, false> (mbv2.get()); + int W_ref2 = mbv2.length(); + tmpVal <<= W_ref2; + tmpVal |= tmpVal2; + return tmpVal; + } + + INLINE const ap_private<_AP_WR, false> get() { + ap_private<_AP_W1+_AP_W2, false> tmpVal = ap_private<_AP_W1+_AP_W2, false> ( mbv1.get()); + ap_private<_AP_W1+_AP_W2, false> tmpVal2 = ap_private<_AP_W1+_AP_W2, false> (mbv2.get()); + int W_ref2 = mbv2.length(); + tmpVal <<= W_ref2; + tmpVal |= tmpVal2; + return tmpVal; + } + + template + INLINE void set(const ap_private<_AP_W3,false> & val) { + ap_private<_AP_W1+_AP_W2, false> vval(val); + int W_ref1=mbv1.length(); + int W_ref2=mbv2.length(); + ap_private<_AP_W1,false> mask1(-1); + mask1>>=_AP_W1-W_ref1; + ap_private<_AP_W2,false> mask2(-1); + mask2>>=_AP_W2-W_ref2; + mbv1.set(ap_private<_AP_W1,false>((vval>>W_ref2)&mask1)); + mbv2.set(ap_private<_AP_W2,false>(vval&mask2)); + } + + INLINE int length() const { + return mbv1.length()+mbv2.length(); + } + + INLINE std::string to_string(uint8_t radix=2) const { + return get().to_string(radix); + } +}; + +///Proxy class, which allows part selection to be used as rvalue(for reading) and +//lvalue(for writing) + +///Range(slice) reference +//------------------------------------------------------------ +template +struct ap_range_ref { +#ifdef _MSC_VER + #pragma warning( disable : 4521 4522 ) +#endif /* #ifdef _MSC_VER */ + ap_private<_AP_W,_AP_S> &d_bv; + int l_index; + int h_index; + +public: + INLINE ap_range_ref(const ap_range_ref<_AP_W, _AP_S>& ref): + d_bv(ref.d_bv), l_index(ref.l_index), h_index(ref.h_index) {} + + INLINE ap_range_ref(ap_private<_AP_W,_AP_S>* bv, int h, int l): + d_bv(*bv),l_index(l),h_index(h) { + //if (h < l) + //fprintf(stderr, "Warning! The bits selected will be returned in reverse order\n"); + } + + INLINE operator ap_private<_AP_W, false> () const { + ap_private<_AP_W, false> val(0); + if(h_index>=l_index) { + if (_AP_W > 64) { + val=d_bv; + ap_private<_AP_W,false> mask(-1); + mask>>=_AP_W-(h_index-l_index+1); + val>>=l_index; + val&=mask; + } else { + const static uint64_t mask = (~0ULL>> (64>_AP_W ? (64-_AP_W):0)); + val = (d_bv >> l_index) & (mask >>(_AP_W-(h_index-l_index+1))); + } + } else { + for(int i=0, j=l_index;j>=0&&j>=h_index;j--,i++) + if((d_bv)[j]) val.set(i); + } + return val; + } + + INLINE operator unsigned long long () const { + return to_uint64(); + } + + template + INLINE ap_range_ref& operator =(const ap_private<_AP_W2,_AP_S2>& val) { + ap_private<_AP_W,false> vval=ap_private<_AP_W,false>(val); + if (l_index>h_index) { + for (int i=0, j=l_index;j>=0&&j>=h_index;j--,i++) + (vval)[i]? d_bv.set(j):d_bv.clear(j); + } else { + if (_AP_W > 64) { + ap_private<_AP_W,false> mask(-1); + if (l_index>0) { + mask<<=l_index; + vval<<=l_index; + } + if(h_index<_AP_W-1) + { + ap_private<_AP_W,false> mask2(-1); + mask2>>=_AP_W-h_index-1; + mask&=mask2; + vval&=mask2; + } + mask.flip(); + d_bv&=mask; + d_bv|=vval; + } else { + unsigned shift = 64-_AP_W; + uint64_t mask = ~0ULL>>(shift); + if(l_index>0) + { + vval = mask & vval << l_index; + mask = mask & mask << l_index; + } + if(h_index<_AP_W-1) + { + uint64_t mask2 = mask; + mask2 >>= (_AP_W-h_index-1); + mask&=mask2; + vval&=mask2; + } + mask = ~mask; + d_bv&=mask; + d_bv|=vval; + } + } + return *this; + } + + INLINE ap_range_ref& operator = (unsigned long long val) + { + const ap_private<_AP_W,_AP_S> vval=val; + return operator = (vval); + } + + + INLINE ap_range_ref& operator =(const ap_range_ref<_AP_W, _AP_S>& val) + { + const ap_private<_AP_W, false> tmpVal(val); + return operator =(tmpVal); + } + + + + template + INLINE ap_range_ref& operator = + (const ap_concat_ref <_AP_W3, _AP_T3, _AP_W4, _AP_T4>& val) + { + const ap_private<_AP_W, false> tmpVal(val); + return operator = (tmpVal); + } + + template + INLINE ap_range_ref& operator =(const ap_range_ref<_AP_W3,_AP_S3>& val) + { + const ap_private<_AP_W, false> tmpVal(val); + return operator =(tmpVal); + } + + template + INLINE ap_range_ref& operator= (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& val) { + return operator=((const ap_private<_AP_W2, _AP_S2>)(val)); + } + + template + INLINE ap_range_ref& operator= (const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& val) { + return operator=(val.to_ap_private()); + } + + template + INLINE ap_range_ref& operator= (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& val) { + return operator=((unsigned long long)(bool)(val)); + } + + template + INLINE ap_range_ref& operator= (const ap_bit_ref<_AP_W2, _AP_S2>& val) { + return operator=((unsigned long long)(bool)(val)); + } + + template + INLINE + ap_concat_ref<_AP_W,ap_range_ref,_AP_W2,ap_range_ref<_AP_W2,_AP_S2> > + operator, (const ap_range_ref<_AP_W2,_AP_S2> &a2) + { + return + ap_concat_ref<_AP_W, ap_range_ref, _AP_W2, + ap_range_ref<_AP_W2,_AP_S2> >(*this, + const_cast& >(a2)); + } + + + template + INLINE ap_concat_ref<_AP_W,ap_range_ref,_AP_W2,ap_private<_AP_W2,_AP_S2> > + operator , (ap_private<_AP_W2,_AP_S2>& a2) + { + return + ap_concat_ref<_AP_W, ap_range_ref, _AP_W2, ap_private<_AP_W2,_AP_S2> >(*this, a2); + } + + INLINE ap_concat_ref<_AP_W,ap_range_ref,_AP_W,ap_private<_AP_W,_AP_S> > + operator , (ap_private<_AP_W, _AP_S>& a2) + { + return + ap_concat_ref<_AP_W, ap_range_ref, _AP_W, + ap_private<_AP_W,_AP_S> >(*this, a2); + } + + + + template + INLINE + ap_concat_ref<_AP_W,ap_range_ref,1,ap_bit_ref<_AP_W2,_AP_S2> > + operator, (const ap_bit_ref<_AP_W2,_AP_S2> &a2) + { + return + ap_concat_ref<_AP_W, ap_range_ref, 1, + ap_bit_ref<_AP_W2,_AP_S2> >(*this, const_cast& >(a2)); + } + + + template + INLINE + ap_concat_ref<_AP_W, ap_range_ref, _AP_W2+_AP_W3, ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > + operator, (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) + { + return ap_concat_ref<_AP_W, ap_range_ref, _AP_W2+_AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(*this, + const_cast& >(a2)); + } + + template + INLINE + ap_concat_ref<_AP_W, ap_range_ref, _AP_W2, af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<_AP_W, ap_range_ref, _AP_W2, af_range_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, + const_cast& >(a2)); + } + + template + INLINE + ap_concat_ref<_AP_W, ap_range_ref, 1, af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<_AP_W, ap_range_ref, 1, af_bit_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, + const_cast& >(a2)); + } + + template + INLINE bool operator == (const ap_range_ref<_AP_W2, _AP_S2>& op2) + { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs==rhs; + } + + + template + INLINE bool operator != (const ap_range_ref<_AP_W2, _AP_S2>& op2) + { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs!=rhs; + } + + + template + INLINE bool operator > (const ap_range_ref<_AP_W2, _AP_S2>& op2) + { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs>rhs; + } + + + template + INLINE bool operator >= (const ap_range_ref<_AP_W2, _AP_S2>& op2) + { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs>=rhs; + } + + + template + INLINE bool operator < (const ap_range_ref<_AP_W2, _AP_S2>& op2) + { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs + INLINE bool operator <= (const ap_range_ref<_AP_W2, _AP_S2>& op2) + { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs<=rhs; + } + + + template + INLINE void set(const ap_private<_AP_W2,false>& val) + { + ap_private<_AP_W,_AP_S> vval=val; + if(l_index>h_index) + { + for(int i=0, j=l_index;j>=0&&j>=h_index;j--,i++) + (vval)[i]? d_bv.set(j):d_bv.clear(j); + } else { + if (_AP_W>64 ) { + ap_private<_AP_W,_AP_S> mask(-1); + if(l_index>0) + { + ap_private<_AP_W,false> mask1(-1); + mask1>>=_AP_W-l_index; + mask1.flip(); + mask=mask1; + //vval&=mask1; + vval<<=l_index; + } + if(h_index<_AP_W-1) + { + ap_private<_AP_W,false> mask2(-1); + mask2<<=h_index+1; + mask2.flip(); + mask&=mask2; + vval&=mask2; + } + mask.flip(); + d_bv&=mask; + d_bv|=vval; + } else { + uint64_t mask = ~0ULL >> (64-_AP_W); + if(l_index>0) + { + uint64_t mask1 = mask; + mask1=mask & (mask1>>(_AP_W-l_index)); + vval =mask&( vval <> (64-_AP_W); + mask2 = mask &(mask2<<(h_index+1)); + mask&=~mask2; + vval&=~mask2; + } + d_bv&=(~mask&(~0ULL >> (64-_AP_W))); + d_bv|=vval; + } + } + } + + + INLINE ap_private<_AP_W,false> get() const + { + ap_private<_AP_W,false> val(0); + if(h_index=0&&j>=h_index;j--,i++) + if((d_bv)[j]) val.set(i); + } else { + val=d_bv; + val>>=l_index; + if(h_index<_AP_W-1) + { + if (_AP_W <= 64) { + const static uint64_t mask = (~0ULL>> (64>_AP_W ? (64-_AP_W):0)); + val &= (mask>> (_AP_W-(h_index-l_index+1))); + } else { + ap_private<_AP_W,false> mask(-1); + mask>>=_AP_W-(h_index-l_index+1); + val&=mask; + } + } + } + return val; + } + + + INLINE ap_private<_AP_W,false> get() + { + ap_private<_AP_W,false> val(0); + if(h_index=0&&j>=h_index;j--,i++) + if((d_bv)[j]) val.set(i); + } else { + val=d_bv; + val>>=l_index; + if(h_index<_AP_W-1) + { + if (_AP_W <= 64 ) { + static const uint64_t mask = ~0ULL>> (64>_AP_W ? (64-_AP_W):0); + return val &= ( (mask) >> (_AP_W - (h_index-l_index+1))); + } else { + ap_private<_AP_W,false> mask(-1); + mask>>=_AP_W-(h_index-l_index+1); + val&=mask; + } + } + } + return val; + } + + + INLINE int length() const + { + return h_index>=l_index?h_index-l_index+1:l_index-h_index+1; + } + + + INLINE int to_int() const + { + ap_private<_AP_W,false> val=get(); + return val.to_int(); + } + + + INLINE unsigned int to_uint() const + { + ap_private<_AP_W,false> val=get(); + return val.to_uint(); + } + + + INLINE long to_long() const + { + ap_private<_AP_W,false> val=get(); + return val.to_long(); + } + + + INLINE unsigned long to_ulong() const + { + ap_private<_AP_W,false> val=get(); + return val.to_ulong(); + } + + + INLINE ap_slong to_int64() const + { + ap_private<_AP_W,false> val=get(); + return val.to_int64(); + } + + + INLINE ap_ulong to_uint64() const + { + ap_private<_AP_W,false> val=get(); + return val.to_uint64(); + } + + INLINE std::string to_string(uint8_t radix=2) const { + return get().to_string(radix); + } + +}; + +///Proxy class, which allows bit selection to be used as rvalue(for reading) and +//lvalue(for writing) + +///Bit reference +//-------------------------------------------------------------- +template +struct ap_bit_ref { +#ifdef _MSC_VER +#pragma warning( disable : 4521 4522 ) +#endif + ap_private<_AP_W,_AP_S>& d_bv; + int d_index; + +public: + INLINE ap_bit_ref(const ap_bit_ref<_AP_W, _AP_S>& ref): + d_bv(ref.d_bv), d_index(ref.d_index) {} + + INLINE ap_bit_ref(ap_private<_AP_W,_AP_S>& bv, int index=0): + d_bv(bv),d_index(index) + { +#ifdef _AP_DEBUG_ + assert(d_index<_AP_W&&"index out of bound"); +#endif + } + + + INLINE operator bool () const + { + return d_bv.get_bit(d_index); + } + + + INLINE bool to_bool() const + { + return operator bool (); + } + + + INLINE ap_bit_ref& operator = (unsigned long long val) + { + if(val) + d_bv.set(d_index); + else + d_bv.clear(d_index); + return *this; + } + + +#if 0 + INLINE ap_bit_ref& operator = (bool val) + { + if(val) + d_bv.set(d_index); + else + d_bv.clear(d_index); + return *this; + } +#endif + template + INLINE ap_bit_ref& operator =(const ap_private<_AP_W2,_AP_S2>& val) + { + return operator =((unsigned long long)(val != 0)); + } + + + template + INLINE ap_bit_ref& operator =(const ap_bit_ref<_AP_W2,_AP_S2>& val) + { + return operator =((unsigned long long)(bool)val); + } + + INLINE ap_bit_ref& operator =(const ap_bit_ref<_AP_W,_AP_S>& val) + { + return operator =((unsigned long long)(bool)val); + } + + template + INLINE ap_bit_ref& operator =(const ap_range_ref<_AP_W2,_AP_S2>& val) + { + return operator =((unsigned long long)(bool) val); + } + + + template + INLINE ap_bit_ref& operator= (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& val) { + return operator=((const ap_private<_AP_W2, false>)(val)); + } + + template + INLINE ap_bit_ref& operator= (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& val) { + return operator=((unsigned long long)(bool)(val)); + } + + template + INLINE ap_bit_ref& operator= (const ap_concat_ref<_AP_W2, _AP_T3, _AP_W3, _AP_T3>& val) { + return operator=((const ap_private<_AP_W2 + _AP_W3, false>)(val)); + } + + + + template + INLINE ap_concat_ref<1, ap_bit_ref, _AP_W2, ap_private<_AP_W2,_AP_S2> > + operator , (ap_private<_AP_W2, _AP_S2>& a2) + { + return ap_concat_ref<1, ap_bit_ref, _AP_W2, ap_private<_AP_W2,_AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<1, ap_bit_ref, _AP_W2, ap_range_ref<_AP_W2,_AP_S2> > + operator, (const ap_range_ref<_AP_W2, _AP_S2> &a2) + { + return + ap_concat_ref<1, ap_bit_ref, _AP_W2, ap_range_ref<_AP_W2,_AP_S2> >(*this, + const_cast &>(a2)); + } + + + template + INLINE ap_concat_ref<1, ap_bit_ref, 1, ap_bit_ref<_AP_W2,_AP_S2> > + operator, (const ap_bit_ref<_AP_W2, _AP_S2> &a2) + { + return + ap_concat_ref<1, ap_bit_ref, 1, ap_bit_ref<_AP_W2,_AP_S2> >(*this, + const_cast &>(a2)); + } + + + INLINE ap_concat_ref<1, ap_bit_ref, 1, ap_bit_ref > + operator, (const ap_bit_ref &a2) + { + return + ap_concat_ref<1, ap_bit_ref, 1, ap_bit_ref >(*this, + const_cast(a2)); + } + + + template + INLINE ap_concat_ref<1, ap_bit_ref, _AP_W2+_AP_W3, ap_concat_ref<_AP_W2,_AP_T2,_AP_W3,_AP_T3> > + operator, (const ap_concat_ref<_AP_W2,_AP_T2,_AP_W3,_AP_T3> &a2) + { + return + ap_concat_ref<1,ap_bit_ref,_AP_W2+_AP_W3, + ap_concat_ref<_AP_W2,_AP_T2,_AP_W3,_AP_T3> >(*this, + const_cast& >(a2)); + } + + template + INLINE + ap_concat_ref<1, ap_bit_ref, _AP_W2, af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<1, ap_bit_ref, _AP_W2, af_range_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, + const_cast& >(a2)); + } + + template + INLINE + ap_concat_ref<1, ap_bit_ref, 1, af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<1, ap_bit_ref, 1, af_bit_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, + const_cast& >(a2)); + } + + template + INLINE bool operator == (const ap_bit_ref<_AP_W2, _AP_S2>& op) { + return get() == op.get(); + } + + template + INLINE bool operator != (const ap_bit_ref<_AP_W2, _AP_S2>& op) { + return get() != op.get(); + } + + + INLINE bool get() const + { + return operator bool (); + } + + + INLINE bool get() + { + return operator bool (); + } + + + template + INLINE void set(const ap_private<_AP_W3, false>& val) + { + operator = (val); + } + + INLINE bool operator ~ () const { + bool bit = (d_bv)[d_index]; + return bit ? false : true; + } + + INLINE int length() const { return 1; } + + INLINE std::string to_string() const { + bool val = get(); + return val ? "1" : "0"; + } +}; + +/// Operators mixing Integers with AP_Int +// ---------------------------------------------------------------- +#if 1 +#define OP_BIN_MIX_INT(BIN_OP, C_TYPE, _AP_WI, _AP_SI, RTYPE) \ + template \ + INLINE typename ap_private<_AP_WI,_AP_SI>::template RType<_AP_W,_AP_S>::RTYPE \ + operator BIN_OP ( C_TYPE i_op, const ap_private<_AP_W,_AP_S> &op) { \ + return ap_private<_AP_WI,_AP_SI>(i_op).operator BIN_OP (op); \ + } \ + template \ + INLINE typename ap_private<_AP_W,_AP_S>::template RType<_AP_WI,_AP_SI>::RTYPE \ + operator BIN_OP ( const ap_private<_AP_W,_AP_S> &op, C_TYPE i_op) { \ + return op.operator BIN_OP (ap_private<_AP_WI,_AP_SI>(i_op)); \ + } +#else +#define OP_BIN_MIX_INT(BIN_OP, C_TYPE, _AP_WI, _AP_SI, RTYPE) \ + template \ + INLINE typename ap_private<_AP_WI,_AP_SI>::template RType<_AP_W,_AP_S>::RTYPE \ + operator BIN_OP ( C_TYPE i_op, const ap_private<_AP_W,_AP_S> &op) { \ + return ap_private<_AP_WI,_AP_SI>(i_op).operator BIN_OP (op); \ + } \ + template \ + INLINE typename ap_private<_AP_W,_AP_S>::template RType<_AP_WI,_AP_SI>::RTYPE \ + operator BIN_OP ( const ap_private<_AP_W,_AP_S> &op, C_TYPE i_op) { \ + return op.operator BIN_OP (ap_private<_AP_WI,_AP_SI>(i_op)); \ + } +#endif +#define OP_REL_MIX_INT(REL_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE bool operator REL_OP ( const ap_private<_AP_W,_AP_S> &op, C_TYPE op2) { \ + return op.operator REL_OP (ap_private<_AP_W2, _AP_S2>(op2)); \ + } \ + template \ + INLINE bool operator REL_OP ( C_TYPE op2, const ap_private<_AP_W,_AP_S> &op) { \ + return ap_private<_AP_W2,_AP_S2>(op2).operator REL_OP (op); \ + } +#define OP_ASSIGN_MIX_INT(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE ap_private<_AP_W,_AP_S> &operator ASSIGN_OP ( ap_private<_AP_W,_AP_S> &op, C_TYPE op2) { \ + return op.operator ASSIGN_OP (ap_private<_AP_W2,_AP_S2>(op2)); \ + } + +#define OP_BIN_SHIFT_INT(BIN_OP, C_TYPE, _AP_WI, _AP_SI, RTYPE) \ + template \ + C_TYPE operator BIN_OP ( C_TYPE i_op, const ap_private<_AP_W,_AP_S> &op) { \ + return i_op BIN_OP (op.getVal()); \ + } \ + template \ + INLINE typename ap_private<_AP_W,_AP_S>::template RType<_AP_WI,_AP_SI>::RTYPE \ + operator BIN_OP ( const ap_private<_AP_W,_AP_S> &op, C_TYPE i_op) { \ + return op.operator BIN_OP (i_op); \ + } +#define OP_ASSIGN_RSHIFT_INT(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE ap_private<_AP_W,_AP_S> &operator ASSIGN_OP ( ap_private<_AP_W,_AP_S> &op, C_TYPE op2) { \ + op = op.operator >> (op2); \ + return op; \ + } +#define OP_ASSIGN_LSHIFT_INT(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE ap_private<_AP_W,_AP_S> &operator ASSIGN_OP ( ap_private<_AP_W,_AP_S> &op, C_TYPE op2) { \ + op = op.operator << (op2); \ + return op; \ + } + +#define OPS_MIX_INT(C_TYPE, WI, SI) \ + OP_BIN_MIX_INT(*, C_TYPE, WI, SI, mult) \ + OP_BIN_MIX_INT(+, C_TYPE, WI, SI, plus) \ + OP_BIN_MIX_INT(-, C_TYPE, WI, SI, minus) \ + OP_BIN_MIX_INT(/, C_TYPE, WI, SI, div) \ + OP_BIN_MIX_INT(%, C_TYPE, WI, SI, mod) \ + OP_BIN_MIX_INT(&, C_TYPE, WI, SI, logic) \ + OP_BIN_MIX_INT(|, C_TYPE, WI, SI, logic) \ + OP_BIN_MIX_INT(^, C_TYPE, WI, SI, logic) \ + OP_BIN_SHIFT_INT(>>, C_TYPE, WI, SI, arg1) \ + OP_BIN_SHIFT_INT(<<, C_TYPE, WI, SI, arg1) \ + \ + OP_REL_MIX_INT(==, C_TYPE, WI, SI) \ + OP_REL_MIX_INT(!=, C_TYPE, WI, SI) \ + OP_REL_MIX_INT(>, C_TYPE, WI, SI) \ + OP_REL_MIX_INT(>=, C_TYPE, WI, SI) \ + OP_REL_MIX_INT(<, C_TYPE, WI, SI) \ + OP_REL_MIX_INT(<=, C_TYPE, WI, SI) \ + \ + OP_ASSIGN_MIX_INT(+=, C_TYPE, WI, SI) \ + OP_ASSIGN_MIX_INT(-=, C_TYPE, WI, SI) \ + OP_ASSIGN_MIX_INT(*=, C_TYPE, WI, SI) \ + OP_ASSIGN_MIX_INT(/=, C_TYPE, WI, SI) \ + OP_ASSIGN_MIX_INT(%=, C_TYPE, WI, SI) \ + OP_ASSIGN_MIX_INT(&=, C_TYPE, WI, SI) \ + OP_ASSIGN_MIX_INT(|=, C_TYPE, WI, SI) \ + OP_ASSIGN_MIX_INT(^=, C_TYPE, WI, SI) \ + OP_ASSIGN_RSHIFT_INT(>>=, C_TYPE, WI, SI) \ + OP_ASSIGN_LSHIFT_INT(<<=, C_TYPE, WI, SI) + + +OPS_MIX_INT(bool, 1, false) +OPS_MIX_INT(char, 8, true) +OPS_MIX_INT(signed char, 8, true) +OPS_MIX_INT(unsigned char, 8, false) +OPS_MIX_INT(short, 16, true) +OPS_MIX_INT(unsigned short, 16, false) +OPS_MIX_INT(int, 32, true) +OPS_MIX_INT(unsigned int, 32, false) +# if defined __x86_64__ +OPS_MIX_INT(long, 64, true) +OPS_MIX_INT(unsigned long, 64, false) +# else +OPS_MIX_INT(long, 32, true) +OPS_MIX_INT(unsigned long, 32, false) +# endif +OPS_MIX_INT(ap_slong, 64, true) +OPS_MIX_INT(ap_ulong, 64, false) + +#define OP_BIN_MIX_RANGE(BIN_OP, RTYPE) \ + template \ + INLINE typename ap_private<_AP_W1,_AP_S1>::template RType<_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP ( const ap_range_ref<_AP_W1,_AP_S1>& op1, const ap_private<_AP_W2,_AP_S2>& op2) { \ + return ap_private<_AP_W1, false>(op1).operator BIN_OP (op2); \ + } \ + template \ + INLINE typename ap_private<_AP_W1,_AP_S1>::template RType<_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP ( const ap_private<_AP_W1,_AP_S1>& op1, const ap_range_ref<_AP_W2,_AP_S2>& op2) { \ + return op1.operator BIN_OP (ap_private<_AP_W2, false>(op2)); \ + } + +#define OP_REL_MIX_RANGE(REL_OP) \ + template \ + INLINE bool operator REL_OP ( const ap_range_ref<_AP_W1,_AP_S1>& op1, const ap_private<_AP_W2,_AP_S2>& op2) { \ + return ap_private<_AP_W1,false>(op1).operator REL_OP (op2); \ + } \ + template \ + INLINE bool operator REL_OP ( const ap_private<_AP_W1,_AP_S1>& op1, const ap_range_ref<_AP_W2,_AP_S2>& op2) { \ + return op1.operator REL_OP (op2.operator ap_private<_AP_W2, false>()); \ + } + +#define OP_ASSIGN_MIX_RANGE(ASSIGN_OP) \ + template \ + INLINE ap_private<_AP_W1,_AP_S1>& operator ASSIGN_OP ( ap_private<_AP_W1,_AP_S1>& op1, const ap_range_ref<_AP_W2,_AP_S2>& op2) { \ + return op1.operator ASSIGN_OP (ap_private<_AP_W2, false>(op2)); \ + } \ + template \ + INLINE ap_range_ref<_AP_W1,_AP_S1>& operator ASSIGN_OP (ap_range_ref<_AP_W1,_AP_S1>& op1, ap_private<_AP_W2,_AP_S2>& op2) { \ + ap_private<_AP_W1, false> tmp(op1); \ + tmp.operator ASSIGN_OP (op2); \ + op1 = tmp; \ + return op1; \ + } + + +OP_ASSIGN_MIX_RANGE(+=) +OP_ASSIGN_MIX_RANGE(-=) +OP_ASSIGN_MIX_RANGE(*=) +OP_ASSIGN_MIX_RANGE(/=) +OP_ASSIGN_MIX_RANGE(%=) +OP_ASSIGN_MIX_RANGE(>>=) +OP_ASSIGN_MIX_RANGE(<<=) +OP_ASSIGN_MIX_RANGE(&=) +OP_ASSIGN_MIX_RANGE(|=) +OP_ASSIGN_MIX_RANGE(^=) + +OP_REL_MIX_RANGE(==) +OP_REL_MIX_RANGE(!=) +OP_REL_MIX_RANGE(>) +OP_REL_MIX_RANGE(>=) +OP_REL_MIX_RANGE(<) +OP_REL_MIX_RANGE(<=) + +OP_BIN_MIX_RANGE(+, plus) +OP_BIN_MIX_RANGE(-, minus) +OP_BIN_MIX_RANGE(*, mult) +OP_BIN_MIX_RANGE(/, div) +OP_BIN_MIX_RANGE(%, mod) +OP_BIN_MIX_RANGE(>>, arg1) +OP_BIN_MIX_RANGE(<<, arg1) +OP_BIN_MIX_RANGE(&, logic) +OP_BIN_MIX_RANGE(|, logic) +OP_BIN_MIX_RANGE(^, logic) + +#define OP_BIN_MIX_BIT(BIN_OP, RTYPE) \ + template \ + INLINE typename ap_private<1, false>::template RType<_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP ( const ap_bit_ref<_AP_W1,_AP_S1>& op1, const ap_private<_AP_W2,_AP_S2>& op2) { \ + return ap_private<1, false>(op1).operator BIN_OP (op2); \ + } \ + template \ + INLINE typename ap_private<_AP_W1,_AP_S1>::template RType<1,false>::RTYPE \ + operator BIN_OP ( const ap_private<_AP_W1,_AP_S1>& op1, const ap_bit_ref<_AP_W2,_AP_S2>& op2) { \ + return op1.operator BIN_OP (ap_private<1, false>(op2)); \ + } + +#define OP_REL_MIX_BIT(REL_OP) \ + template \ + INLINE bool operator REL_OP ( const ap_bit_ref<_AP_W1,_AP_S1>& op1, const ap_private<_AP_W2,_AP_S2>& op2) { \ + return ap_private<_AP_W1,false>(op1).operator REL_OP (op2); \ + } \ + template \ + INLINE bool operator REL_OP ( const ap_private<_AP_W1,_AP_S1>& op1, const ap_bit_ref<_AP_W2,_AP_S2>& op2) { \ + return op1.operator REL_OP (ap_private<1, false>(op2)); \ + } + +#define OP_ASSIGN_MIX_BIT(ASSIGN_OP) \ + template \ + INLINE ap_private<_AP_W1,_AP_S1>& operator ASSIGN_OP ( ap_private<_AP_W1,_AP_S1>& op1, ap_bit_ref<_AP_W2,_AP_S2>& op2) { \ + return op1.operator ASSIGN_OP (ap_private<1, false>(op2)); \ + } \ + template \ + INLINE ap_bit_ref<_AP_W1,_AP_S1>& operator ASSIGN_OP ( ap_bit_ref<_AP_W1,_AP_S1>& op1, ap_private<_AP_W2,_AP_S2>& op2) { \ + ap_private<1, false> tmp(op1); \ + tmp.operator ASSIGN_OP (op2); \ + op1 = tmp; \ + return op1; \ + } + + +OP_ASSIGN_MIX_BIT(+=) +OP_ASSIGN_MIX_BIT(-=) +OP_ASSIGN_MIX_BIT(*=) +OP_ASSIGN_MIX_BIT(/=) +OP_ASSIGN_MIX_BIT(%=) +OP_ASSIGN_MIX_BIT(>>=) +OP_ASSIGN_MIX_BIT(<<=) +OP_ASSIGN_MIX_BIT(&=) +OP_ASSIGN_MIX_BIT(|=) +OP_ASSIGN_MIX_BIT(^=) + +OP_REL_MIX_BIT(==) +OP_REL_MIX_BIT(!=) +OP_REL_MIX_BIT(>) +OP_REL_MIX_BIT(>=) +OP_REL_MIX_BIT(<) +OP_REL_MIX_BIT(<=) + +OP_BIN_MIX_BIT(+, plus) +OP_BIN_MIX_BIT(-, minus) +OP_BIN_MIX_BIT(*, mult) +OP_BIN_MIX_BIT(/, div) +OP_BIN_MIX_BIT(%, mod) +OP_BIN_MIX_BIT(>>, arg1) +OP_BIN_MIX_BIT(<<, arg1) +OP_BIN_MIX_BIT(&, logic) +OP_BIN_MIX_BIT(|, logic) +OP_BIN_MIX_BIT(^, logic) + +#define REF_REL_OP_MIX_INT(REL_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE bool operator REL_OP ( const ap_range_ref<_AP_W,_AP_S> &op, C_TYPE op2) { \ + return (ap_private<_AP_W, false>(op)).operator REL_OP (ap_private<_AP_W2,_AP_S2>(op2)); \ + } \ + template \ + INLINE bool operator REL_OP ( C_TYPE op2, const ap_range_ref<_AP_W,_AP_S> &op) { \ + return ap_private<_AP_W2,_AP_S2>(op2).operator REL_OP (ap_private<_AP_W, false>(op)); \ + } \ + template \ + INLINE bool operator REL_OP ( const ap_bit_ref<_AP_W,_AP_S> &op, C_TYPE op2) { \ + return (bool(op)) REL_OP op2; \ + } \ + template \ + INLINE bool operator REL_OP ( C_TYPE op2, const ap_bit_ref<_AP_W,_AP_S> &op) { \ + return op2 REL_OP (bool(op)); \ + } \ + template \ + INLINE bool operator REL_OP ( const ap_concat_ref<_AP_W,_AP_T, _AP_W1, _AP_T1> &op, C_TYPE op2) { \ + return (ap_private<_AP_W + _AP_W1, false>(op)).operator REL_OP (ap_private<_AP_W2,_AP_S2>(op2)); \ + } \ + template \ + INLINE bool operator REL_OP ( C_TYPE op2, const ap_concat_ref<_AP_W,_AP_T, _AP_W1, _AP_T1> &op) { \ + return ap_private<_AP_W2,_AP_S2>(op2).operator REL_OP (ap_private<_AP_W + _AP_W1, false>(op)); \ + } + +#define REF_REL_MIX_INT(C_TYPE, _AP_WI, _AP_SI) \ +REF_REL_OP_MIX_INT(>, C_TYPE, _AP_WI, _AP_SI) \ +REF_REL_OP_MIX_INT(<, C_TYPE, _AP_WI, _AP_SI) \ +REF_REL_OP_MIX_INT(>=, C_TYPE, _AP_WI, _AP_SI) \ +REF_REL_OP_MIX_INT(<=, C_TYPE, _AP_WI, _AP_SI) \ +REF_REL_OP_MIX_INT(==, C_TYPE, _AP_WI, _AP_SI) \ +REF_REL_OP_MIX_INT(!=, C_TYPE, _AP_WI, _AP_SI) + +REF_REL_MIX_INT(bool, 1, false) +REF_REL_MIX_INT(char, 8, true) +REF_REL_MIX_INT(signed char, 8, true) +REF_REL_MIX_INT(unsigned char, 8, false) +REF_REL_MIX_INT(short, 16, true) +REF_REL_MIX_INT(unsigned short, 16, false) +REF_REL_MIX_INT(int, 32, true) +REF_REL_MIX_INT(unsigned int, 32, false) +# if defined __x86_64__ +REF_REL_MIX_INT(long, 64, true) +REF_REL_MIX_INT(unsigned long, 64, false) +# else +REF_REL_MIX_INT(long, 32, true) +REF_REL_MIX_INT(unsigned long, 32, false) +# endif +REF_REL_MIX_INT(ap_slong, 64, true) +REF_REL_MIX_INT(ap_ulong, 64, false) + +#define REF_BIN_OP_MIX_INT(BIN_OP, RTYPE, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE typename ap_private<_AP_W, false>::template RType<_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP ( const ap_range_ref<_AP_W,_AP_S> &op, C_TYPE op2) { \ + return (ap_private<_AP_W, false>(op)).operator BIN_OP (ap_private<_AP_W2,_AP_S2>(op2)); \ + } \ + template \ + INLINE typename ap_private<_AP_W2, _AP_S2>::template RType<_AP_W,false>::RTYPE \ + operator BIN_OP ( C_TYPE op2, const ap_range_ref<_AP_W,_AP_S> &op) { \ + return ap_private<_AP_W2,_AP_S2>(op2).operator BIN_OP (ap_private<_AP_W, false>(op)); \ + } + +#define REF_BIN_MIX_INT(C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(+, plus, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(-, minus, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(*, mult, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(/, div, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(%, mod, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(>>, arg1, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(<<, arg1, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(&, logic, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(|, logic, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(^, logic, C_TYPE, _AP_WI, _AP_SI) + +REF_BIN_MIX_INT(bool, 1, false) +REF_BIN_MIX_INT(char, 8, true) +REF_BIN_MIX_INT(signed char, 8, true) +REF_BIN_MIX_INT(unsigned char, 8, false) +REF_BIN_MIX_INT(short, 16, true) +REF_BIN_MIX_INT(unsigned short, 16, false) +REF_BIN_MIX_INT(int, 32, true) +REF_BIN_MIX_INT(unsigned int, 32, false) +# if defined __x86_64__ +REF_BIN_MIX_INT(long, 64, true) +REF_BIN_MIX_INT(unsigned long, 64, false) +#else +REF_BIN_MIX_INT(long, 32, true) +REF_BIN_MIX_INT(unsigned long, 32, false) +#endif +REF_BIN_MIX_INT(ap_slong, 64, true) +REF_BIN_MIX_INT(ap_ulong, 64, false) + +#define REF_BIN_OP(BIN_OP, RTYPE) \ +template \ +INLINE typename ap_private<_AP_W, false>::template RType<_AP_W2, false>::RTYPE \ +operator BIN_OP (const ap_range_ref<_AP_W,_AP_S> &lhs, const ap_range_ref<_AP_W2,_AP_S2> &rhs) { \ + return ap_private<_AP_W,false>(lhs).operator BIN_OP (ap_private<_AP_W2, false>(rhs)); \ +} + +REF_BIN_OP(+, plus) +REF_BIN_OP(-, minus) +REF_BIN_OP(*, mult) +REF_BIN_OP(/, div) +REF_BIN_OP(%, mod) +REF_BIN_OP(>>, arg1) +REF_BIN_OP(<<, arg1) +REF_BIN_OP(&, logic) +REF_BIN_OP(|, logic) +REF_BIN_OP(^, logic) + +#if 1 +#define CONCAT_OP_MIX_INT(C_TYPE, _AP_WI, _AP_SI) \ +template \ +INLINE \ +ap_private< _AP_W + _AP_WI, false > \ + operator, (const ap_private<_AP_W, _AP_S> &op1, C_TYPE op2) { \ + ap_private<_AP_WI + _AP_W, false> val(op2); \ + ap_private<_AP_WI + _AP_W, false> ret(op1); \ + ret <<= _AP_WI; \ + if (_AP_SI) { \ + val <<= _AP_W; val >>= _AP_W; \ + }\ + ret |= val; \ + return ret;\ +} \ +template \ +INLINE \ +ap_private< _AP_W + _AP_WI, false > \ + operator, (C_TYPE op1, const ap_private<_AP_W, _AP_S>& op2) { \ + ap_private<_AP_WI + _AP_W, false> val(op1); \ + ap_private<_AP_WI + _AP_W, false> ret(op2); \ + if (_AP_S) { \ + ret <<= _AP_WI; ret >>= _AP_WI; \ + } \ + ret |= val << _AP_W; \ + return ret; \ +} \ +template \ +INLINE \ +ap_private< _AP_W + _AP_WI, false > \ + operator, (const ap_range_ref<_AP_W, _AP_S> &op1, C_TYPE op2) { \ + ap_private<_AP_WI + _AP_W, false> val(op2); \ + ap_private<_AP_WI + _AP_W, false> ret(op1); \ + ret <<= _AP_WI; \ + if (_AP_SI) { \ + val <<= _AP_W; val >>= _AP_W; \ + } \ + ret |= val; \ + return ret; \ +} \ +template \ +INLINE \ +ap_private< _AP_W + _AP_WI, false > \ + operator, (C_TYPE op1, const ap_range_ref<_AP_W, _AP_S> &op2) { \ + ap_private<_AP_WI + _AP_W, false> val(op1); \ + ap_private<_AP_WI + _AP_W, false> ret(op2); \ + int len = op2.length(); \ + val <<= len; \ + ret |= val; \ + return ret; \ +} \ +template \ +INLINE \ +ap_private<_AP_WI + 1, false > \ + operator, (const ap_bit_ref<_AP_W, _AP_S> &op1, C_TYPE op2) { \ + ap_private<_AP_WI + 1, false> val(op2); \ + val[_AP_WI] = op1; \ + return val; \ +} \ +template \ +INLINE \ +ap_private<_AP_WI + 1, false > \ + operator, (C_TYPE op1, const ap_bit_ref<_AP_W, _AP_S> &op2) { \ + ap_private<_AP_WI + 1, false> val(op1); \ + val <<= 1; \ + val[0] = op2; \ + return val; \ +} \ +template \ +INLINE \ +ap_private<_AP_W + _AP_W2 + _AP_WI, false > \ + operator, (const ap_concat_ref<_AP_W, _AP_T, _AP_W2, _AP_T2> &op1, C_TYPE op2) {\ + ap_private<_AP_WI + _AP_W + _AP_W2, _AP_SI> val(op2);\ + ap_private<_AP_WI + _AP_W + _AP_W2, _AP_SI> ret(op1);\ + if (_AP_SI) { \ + val <<= _AP_W + _AP_W2; val >>= _AP_W + _AP_W2; \ + } \ + ret <<= _AP_WI; \ + ret |= val; \ + return ret; \ +}\ +template \ +INLINE \ +ap_private<_AP_W + _AP_W2 + _AP_WI, false > \ + operator, (C_TYPE op1, const ap_concat_ref<_AP_W, _AP_T, _AP_W2, _AP_T2> &op2) {\ + ap_private<_AP_WI + _AP_W + _AP_W2, _AP_SI> val(op1);\ + ap_private<_AP_WI + _AP_W + _AP_W2, _AP_SI> ret(op2);\ + int len = op2.length(); \ + val <<= len; \ + ret |= val;\ + return ret; \ +}\ +template \ +INLINE \ +ap_private< _AP_W + _AP_WI, false > \ + operator, (const af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op1, C_TYPE op2) { \ + ap_private<_AP_WI + _AP_W, false> val(op2); \ + ap_private<_AP_WI + _AP_W, false> ret(op1); \ + if (_AP_SI) { \ + val <<= _AP_W; val >>= _AP_W; \ + }\ + ret <<= _AP_WI; \ + ret |= val; \ + return ret; \ +} \ +template \ +INLINE \ +ap_private< _AP_W + _AP_WI, false > \ + operator, (C_TYPE op1, const af_range_ref<_AP_W, _AP_I, _AP_S, \ + _AP_Q, _AP_O, _AP_N> &op2) { \ + ap_private<_AP_WI + _AP_W, false> val(op1); \ + ap_private<_AP_WI + _AP_W, false> ret(op2); \ + int len = op2.length(); \ + val <<= len; \ + ret |= val; \ + return ret; \ +} \ +template \ +INLINE \ +ap_private< 1 + _AP_WI, false> \ + operator, (const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, \ + _AP_N> &op1, C_TYPE op2) { \ + ap_private<_AP_WI + 1, _AP_SI> val(op2); \ + val[_AP_WI] = op1; \ + return val; \ +} \ +template \ +INLINE \ +ap_private< 1 + _AP_WI, false> \ + operator, (C_TYPE op1, const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q,\ + _AP_O, _AP_N> &op2) { \ + ap_private<_AP_WI + 1, _AP_SI> val(op1); \ + val <<= 1; \ + val[0] = op2; \ + return val; \ +} + +CONCAT_OP_MIX_INT(bool, 1, false) +CONCAT_OP_MIX_INT(char, 8, true) +CONCAT_OP_MIX_INT(signed char, 8, true) +CONCAT_OP_MIX_INT(unsigned char, 8, false) +CONCAT_OP_MIX_INT(short, 16, true) +CONCAT_OP_MIX_INT(unsigned short, 16, false) +CONCAT_OP_MIX_INT(int, 32, true) +CONCAT_OP_MIX_INT(unsigned int, 32, false) +# if defined __x86_64__ +CONCAT_OP_MIX_INT(long, 64, true) +CONCAT_OP_MIX_INT(unsigned long, 64, false) +# else +CONCAT_OP_MIX_INT(long, 32, true) +CONCAT_OP_MIX_INT(unsigned long, 32, false) +# endif +CONCAT_OP_MIX_INT(ap_slong, 64, true) +CONCAT_OP_MIX_INT(ap_ulong, 64, false) +#endif + +#if 1 +#define CONCAT_SHIFT_MIX_INT(C_TYPE, op) \ +template \ +INLINE ap_uint<_AP_W+_AP_W1> operator op (const ap_concat_ref<_AP_W, _AP_T, _AP_W1, _AP_T1> lhs, C_TYPE rhs) { \ + return ((ap_uint<_AP_W+_AP_W1>)lhs.get()) op ((int)rhs); \ +} + +CONCAT_SHIFT_MIX_INT(long, <<) +CONCAT_SHIFT_MIX_INT(unsigned long, <<) +CONCAT_SHIFT_MIX_INT(unsigned int, <<) +CONCAT_SHIFT_MIX_INT(ap_ulong, <<) +CONCAT_SHIFT_MIX_INT(ap_slong, <<) +CONCAT_SHIFT_MIX_INT(long, >>) +CONCAT_SHIFT_MIX_INT(unsigned long, >>) +CONCAT_SHIFT_MIX_INT(unsigned int, >>) +CONCAT_SHIFT_MIX_INT(ap_ulong, >>) +CONCAT_SHIFT_MIX_INT(ap_slong, >>) +#endif + +#if defined(SYSTEMC_H) || defined(SYSTEMC_INCLUDED) +template +INLINE void sc_trace(sc_core::sc_trace_file *tf, const ap_private<_AP_W, _AP_S> &op, + const std::string &name) { + if (tf) + tf->trace(sc_dt::sc_lv<_AP_W>(op.to_string(2).c_str()), name); +} +#endif + +template +INLINE std::ostream& operator<<(std::ostream& out, const ap_private<_AP_W,_AP_S> &op) +{ + ap_private<_AP_W, _AP_S> v=op; + const std::ios_base::fmtflags basefield = out.flags() & std::ios_base::basefield; + unsigned radix = (basefield == std::ios_base::hex) ? 16 : + ((basefield == std::ios_base::oct) ? 8 : 10); + std::string str=v.toString(radix,_AP_S); + out< +INLINE std::istream& operator >> (std::istream& in, ap_private<_AP_W,_AP_S> &op) +{ + std::string str; + in >> str; + op = ap_private<_AP_W, _AP_S>(str.c_str()); + return in; + +} + +template +INLINE std::ostream& operator<<(std::ostream& out, const ap_range_ref<_AP_W,_AP_S> &op) +{ + return operator<<(out, ap_private<_AP_W, _AP_S>(op)); +} + +template +INLINE std::istream& operator >> (std::istream& in, ap_range_ref<_AP_W,_AP_S> &op) +{ + return operator>>(in, ap_private<_AP_W, _AP_S>(op));; +} + +template +INLINE void print(const ap_private<_AP_W,_AP_S> &op, bool fill=true ) +{ + ap_private<_AP_W, _AP_S> v=op; + uint32_t ws=v.getNumWords(); + const uint64_t *ptr=v.getRawData(); + int i=ws-1; +#if 0 + if(fill) + printf("%016llx",*(ptr+i)); + else + printf("%llx",*(ptr+i)); +#else +//match SystemC output + if(_AP_W%64 != 0) { + uint32_t offset=_AP_W%64; + uint32_t count=(offset+3)/4; + int64_t data=*(ptr+i); + if(_AP_S) + data=(data<<(64-offset))>>(64-offset); + else + count=(offset+4)/4; + while(count-->0) + printf("%llx",(data>>(count*4))&0xf); + } else { + if(_AP_S==false) + printf("0"); + printf("%016llx",*(ptr+i)); + } +#endif + for(--i;i>=0;i--) + printf("%016llx",*(ptr+i)); + printf("\n"); + +} +#endif /* #ifndef __AESL_GCC_AP_INT_H__ */ \ No newline at end of file diff --git a/hls_2018/router_05/etc/ap_private.h b/hls_2018/router_05/etc/ap_private.h new file mode 100755 index 0000000..1a68a9e --- /dev/null +++ b/hls_2018/router_05/etc/ap_private.h @@ -0,0 +1,5858 @@ +/* + * Copyright 2012 Xilinx, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LLVM_SUPPORT_MATHEXTRAS_H +#define LLVM_SUPPORT_MATHEXTRAS_H + +#ifdef _MSC_VER +#if _MSC_VER <= 1500 +typedef __int8 int8_t; +typedef unsigned __int8 uint8_t; +typedef __int16 int16_t; +typedef unsigned __int16 uint16_t; +typedef __int32 int32_t; +typedef unsigned __int32 uint32_t; +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; +#else if +#include +#endif /* #if _MSC_VER <= 1500 */ +#else +#include +#endif /* #if _MSC_VER <= 1500 */ +#undef INLINE +#if 1 +#define INLINE inline +#else +//Enable to debug ap_int/ap_fixed +#define INLINE __attribute__((weak)) +#endif +#define AP_MAX(a,b) ((a) > (b) ? (a) : (b)) +#define AP_MIN(a,b) ((a) < (b) ? (a) : (b)) +#define AP_ABS(a) ((a)>=0 ? (a):-(a)) +#ifndef AP_INT_MAX_W +#define AP_INT_MAX_W 1024 +#endif +#define BIT_WIDTH_UPPER_LIMIT (1 << 15) +#if AP_INT_MAX_W > BIT_WIDTH_UPPER_LIMIT +#error "Bitwidth exceeds 32768 (1 << 15), the maximum allowed value" +#endif +#define MAX_MODE(BITS) ((BITS + 1023) / 1024) + +// NOTE: The following support functions use the _32/_64 extensions instead of +// type overloading so that signed and unsigned integers can be used without +// ambiguity. + +/// Hi_32 - This function returns the high 32 bits of a 64 bit value. +INLINE uint32_t Hi_32(uint64_t Value) { + return static_cast(Value >> 32); +} + +/// Lo_32 - This function returns the low 32 bits of a 64 bit value. +INLINE uint32_t Lo_32(uint64_t Value) { + return static_cast(Value); +} + +/// ByteSwap_16 - This function returns a byte-swapped representation of the +/// 16-bit argument, Value. +INLINE uint16_t ByteSwap_16(uint16_t Value) { +#if defined(_MSC_VER) && !defined(_DEBUG) + // The DLL version of the runtime lacks these functions (bug!?), but in a + // release build they're replaced with BSWAP instructions anyway. + return (uint16_t)(_byteswap_ushort(Value)); +#else + uint16_t Hi = (uint16_t)((Value) << 8); + uint16_t Lo = (uint16_t)((Value) >> 8); + return Hi | Lo; +#endif +} + +/// ByteSwap_32 - This function returns a byte-swapped representation of the +/// 32-bit argument, Value. +INLINE uint32_t ByteSwap_32(uint32_t Value) { + uint32_t Byte0 = Value & 0x000000FF; + uint32_t Byte1 = Value & 0x0000FF00; + uint32_t Byte2 = Value & 0x00FF0000; + uint32_t Byte3 = Value & 0xFF000000; + return ((Byte0) << 24) | ((Byte1) << 8) | ((Byte2) >> 8) | ((Byte3) >> 24); +} + +/// ByteSwap_64 - This function returns a byte-swapped representation of the +/// 64-bit argument, Value. +INLINE uint64_t ByteSwap_64(uint64_t Value) { + uint64_t Hi = ByteSwap_32(uint32_t(Value)); + uint32_t Lo = ByteSwap_32(uint32_t(Value >> 32)); + return ((Hi) << 32) | Lo; +} + +/// CountLeadingZeros_32 - this function performs the platform optimal form of +/// counting the number of zeros from the most significant bit to the first one +/// bit. Ex. CountLeadingZeros_32(0x00F000FF) == 8. +/// Returns 32 if the word is zero. +INLINE unsigned CountLeadingZeros_32(uint32_t Value) { + unsigned Count; // result +#if __GNUC__ >= 4 + // PowerPC is defined for __builtin_clz(0) +#if !defined(__ppc__) && !defined(__ppc64__) + if (Value == 0) return 32; +#endif + Count = __builtin_clz(Value); +#else + if (Value == 0) return 32; + Count = 0; + // bisecton method for count leading zeros + for (unsigned Shift = 32 >> 1; Shift; Shift >>= 1) { + uint32_t Tmp = (Value) >> (Shift); + if (Tmp) { + Value = Tmp; + } else { + Count |= Shift; + } + } +#endif + return Count; +} + +/// CountLeadingZeros_64 - This function performs the platform optimal form +/// of counting the number of zeros from the most significant bit to the first +/// one bit (64 bit edition.) +/// Returns 64 if the word is zero. +INLINE unsigned CountLeadingZeros_64(uint64_t Value) { + unsigned Count; // result +#if __GNUC__ >= 4 + // PowerPC is defined for __builtin_clzll(0) +#if !defined(__ppc__) && !defined(__ppc64__) + if (!Value) return 64; +#endif + Count = __builtin_clzll(Value); +#else + if (sizeof(long) == sizeof(int64_t)) { + if (!Value) return 64; + Count = 0; + // bisecton method for count leading zeros + for (unsigned Shift = 64 >> 1; Shift; Shift >>= 1) { + uint64_t Tmp = (Value) >> (Shift); + if (Tmp) { + Value = Tmp; + } else { + Count |= Shift; + } + } + } else { + // get hi portion + uint32_t Hi = Hi_32(Value); + + // if some bits in hi portion + if (Hi) { + // leading zeros in hi portion plus all bits in lo portion + Count = CountLeadingZeros_32(Hi); + } else { + // get lo portion + uint32_t Lo = Lo_32(Value); + // same as 32 bit value + Count = CountLeadingZeros_32(Lo)+32; + } + } +#endif + return Count; +} + +/// CountTrailingZeros_64 - This function performs the platform optimal form +/// of counting the number of zeros from the least significant bit to the first +/// one bit (64 bit edition.) +/// Returns 64 if the word is zero. +INLINE unsigned CountTrailingZeros_64(uint64_t Value) { +#if __GNUC__ >= 4 + return (Value != 0) ? __builtin_ctzll(Value) : 64; +#else + static const unsigned Mod67Position[] = { + 64, 0, 1, 39, 2, 15, 40, 23, 3, 12, 16, 59, 41, 19, 24, 54, + 4, 64, 13, 10, 17, 62, 60, 28, 42, 30, 20, 51, 25, 44, 55, + 47, 5, 32, 65, 38, 14, 22, 11, 58, 18, 53, 63, 9, 61, 27, + 29, 50, 43, 46, 31, 37, 21, 57, 52, 8, 26, 49, 45, 36, 56, + 7, 48, 35, 6, 34, 33, 0 + }; + return Mod67Position[(uint64_t)(-(int64_t)Value & (int64_t)Value) % 67]; +#endif +} + +/// CountPopulation_64 - this function counts the number of set bits in a value, +/// (64 bit edition.) +INLINE unsigned CountPopulation_64(uint64_t Value) { +#if __GNUC__ >= 4 + return __builtin_popcountll(Value); +#else + uint64_t v = Value - (((Value) >> 1) & 0x5555555555555555ULL); + v = (v & 0x3333333333333333ULL) + (((v) >> 2) & 0x3333333333333333ULL); + v = (v + ((v) >> 4)) & 0x0F0F0F0F0F0F0F0FULL; + return unsigned((uint64_t)(v * 0x0101010101010101ULL) >> 56); +#endif +} + +#endif // LLVM_SUPPORT_MATHEXTRAS_H + + +#ifndef AP_PRIVATE_H +#define AP_PRIVATE_H + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace AESL_std { + template + DataType INLINE min(DataType a, DataType b) { + // if (a >= b) return b; + // else return a; + return (a>=b) ? b : a; + } + + template + DataType INLINE max(DataType a, DataType b) { + // if (a >= b) return a; + // else return b; + return (a>=b) ? a : b; + } +} +enum ap_q_mode { + AP_RND, // rounding to plus infinity + AP_RND_ZERO,// rounding to zero + AP_RND_MIN_INF,// rounding to minus infinity + AP_RND_INF,// rounding to infinity + AP_RND_CONV, // convergent rounding + AP_TRN, // truncation + AP_TRN_ZERO // truncation to zero + +}; +enum ap_o_mode { + AP_SAT, // saturation + AP_SAT_ZERO, // saturation to zero + AP_SAT_SYM, // symmetrical saturation + AP_WRAP, // wrap-around (*) + AP_WRAP_SM // sign magnitude wrap-around (*) +}; + +template struct ap_fixed_base; +template struct af_range_ref; +template struct af_bit_ref; + +template struct ap_range_ref; +template struct ap_bit_ref; +template struct ap_concat_ref; +static bool InvalidDigit(const char* str, unsigned len, unsigned start, unsigned radix) { + unsigned i; + for (i = start; i < len; ++i) + if ((radix == 2 && (str[i] == '0' || str[i] == '1')) || + (radix == 8 && str[i] >= '0' && str[i] <= '7') || + (radix == 10 && str[i] >= '0' && str[i] <= '9') || + (radix == 16 && ((str[i] >= '0' && str[i] <= '9') || + (str[i] >= 'a' && str[i] <= 'f') || + (str[i] >= 'A' && str[i] <= 'F')))) + continue; + else + return true; + return false; +} + +static void ap_parse_sign(const char* str, uint32_t &base, bool &neg) { + if (str[0] == '+' || str[0] == '-') base = 1; + if (str[0] == '-') neg = true; + else neg = false; + return; +} + +static void ap_parse_prefix(const char* str, uint32_t &offset, uint32_t &radix) { + if (str[0] == '0') { + switch (str[1]) { + case 'b': + case 'B': offset = 2; radix = 2; break; + case 'x': + case 'X': offset = 2; radix = 16; break; + case 'd': + case 'D': offset = 2; radix = 10; break; + case 'o': + case 'O': offset = 2; radix = 8; break; + default: break; + } + } + if (offset == 0) + for (int i=0, len = strlen(str); i= 'a') || (str[i] <= 'F' && str[i] >= 'A')) { + radix = 16; + break; + } + return; +} + +/// sub_1 - This function subtracts a single "digit" (64-bit word), y, from +/// the multi-digit integer array, x[], propagating the borrowed 1 value until +/// no further borrowing is neeeded or it runs out of "digits" in x. The result +/// is 1 if "borrowing" exhausted the digits in x, or 0 if x was not exhausted. +/// In other words, if y > x then this function returns 1, otherwise 0. +/// @returns the borrow out of the subtraction +static bool sub_1(uint64_t x[], uint32_t len, uint64_t y) { + for (uint32_t i = 0; i < len; ++i) { + uint64_t __X = x[i]; + x[i] -= y; + if (y > __X) + y = 1; // We have to "borrow 1" from next "digit" + else { + y = 0; // No need to borrow + break; // Remaining digits are unchanged so exit early + } + } + return (y != 0); +} + + /// This enumeration just provides for internal constants used in this + /// translation unit. + enum { + MIN_INT_BITS = 1, ///< Minimum number of bits that can be specified + ///< Note that this must remain synchronized with IntegerType::MIN_INT_BITS + MAX_INT_BITS = (1<<23)-1 ///< Maximum number of bits that can be specified + ///< Note that this must remain synchronized with IntegerType::MAX_INT_BITS + }; + + /// A utility function for allocating memory and checking for allocation + /// failure. The content is not zeroed. + static uint64_t* getMemory(uint32_t numWords) { + return (uint64_t*) malloc(numWords*sizeof(uint64_t)); + } + + //===----------------------------------------------------------------------===// + // ap_private Class + //===----------------------------------------------------------------------===// + + /// ap_private - This class represents arbitrary precision constant integral values. + /// It is a functional replacement for common case unsigned integer type like + /// "unsigned", "unsigned long" or "uint64_t", but also allows non-byte-width + /// integer sizes and large integer value types such as 3-bits, 15-bits, or more + /// than 64-bits of precision. ap_private provides a variety of arithmetic operators + /// and methods to manipulate integer values of any bit-width. It supports both + /// the typical integer arithmetic and comparison operations as well as bitwise + /// manipulation. + /// + /// The class has several invariants worth noting: + /// * All bit, byte, and word positions are zero-based. + /// * Once the bit width is set, it doesn't change except by the Truncate, + /// SignExtend, or ZeroExtend operations. + /// * All binary operators must be on ap_private instances of the same bit width. + /// Attempting to use these operators on instances with different bit + /// widths will yield an assertion. + /// * The value is stored canonically as an unsigned value. For operations + /// where it makes a difference, there are both signed and unsigned variants + /// of the operation. For example, sdiv and udiv. However, because the bit + /// widths must be the same, operations such as Mul and Add produce the same + /// results regardless of whether the values are interpreted as signed or + /// not. + /// * In general, the class tries to follow the style of computation that LLVM + /// uses in its IR. This simplifies its use for LLVM. + /// + /// @brief Class for arbitrary precision integers. + template class ap_private; + namespace ap_private_ops{ + template + INLINE ap_private<_AP_W, _AP_S, _AP_N> lshr(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, uint32_t shiftAmt); + template + INLINE ap_private<_AP_W, _AP_S, _AP_N> shl(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, uint32_t shiftAmt); + } + +#if defined(_MSC_VER) +# if _MSC_VER < 1400 && !defined(for) +# define for if(0);else for +# endif + typedef unsigned __int64 ap_ulong; + typedef signed __int64 ap_slong; +#else + typedef unsigned long long ap_ulong; + typedef signed long long ap_slong; +#endif + template struct retval { + }; + template<> struct retval { + typedef ap_slong Type; + }; + template<> struct retval { + typedef ap_ulong Type; + }; + + template + class ap_private { +#ifdef _MSC_VER +#pragma warning( disable : 4521 4522 ) +#endif +public: + typedef typename retval<_AP_S>::Type ValType; + template friend struct ap_fixed_base; + ///return type of variety of operations + //---------------------------------------------------------- + template + struct RType { + enum { + mult_w = _AP_W+_AP_W2, + mult_s = _AP_S||_AP_S2, + plus_w = AP_MAX(_AP_W+(_AP_S2&&!_AP_S),_AP_W2+(_AP_S&&!_AP_S2))+1, + plus_s = _AP_S||_AP_S2, + minus_w = AP_MAX(_AP_W+(_AP_S2&&!_AP_S),_AP_W2+(_AP_S&&!_AP_S2))+1, + minus_s = true, + div_w = _AP_W+_AP_S2, + div_s = _AP_S||_AP_S2, + mod_w = AP_MIN(_AP_W,_AP_W2+(!_AP_S2&&_AP_S)), + mod_s = _AP_S, + logic_w = AP_MAX(_AP_W+(_AP_S2&&!_AP_S),_AP_W2+(_AP_S&&!_AP_S2)), + logic_s = _AP_S||_AP_S2 + }; + typedef ap_private mult; + typedef ap_private plus; + typedef ap_private minus; + typedef ap_private logic; + typedef ap_private div; + typedef ap_private mod; + typedef ap_private<_AP_W, _AP_S> arg1; + typedef bool reduce; + }; + + INLINE void report() { +#if 0 + if (_AP_W > 1024 && _AP_W <= 4096) { + fprintf(stderr, "[W] W=%d is out of bound (1<=W<=1024): for" + " synthesis: please define macro AP_INT_TYPE_EXT(N)" + " to extend the valid range.\n", _AP_W); + } else +#endif + if (_AP_W > MAX_MODE(AP_INT_MAX_W) * 1024) { + fprintf(stderr, "[E] ap_%sint<%d>: Bitwidth exceeds the " + "default max value %d. Please use macro " + "AP_INT_MAX_W to set a larger max value.\n", + _AP_S?"":"u", _AP_W, + MAX_MODE(AP_INT_MAX_W) * 1024); + exit(1); + } + } + + enum { BitWidth = _AP_W }; + /// This union is used to store the integer value. When the + /// integer bit-width <= 64, it uses VAL, otherwise it uses pVal. + + /// This enum is used to hold the constants we needed for ap_private. + uint64_t VAL; ///< Used to store the <= 64 bits integer value. + uint64_t pVal[_AP_N]; ///< Used to store the >64 bits integer value. + + /// This enum is used to hold the constants we needed for ap_private. + enum { + APINT_BITS_PER_WORD = sizeof(uint64_t) * 8, ///< Bits in a word + APINT_WORD_SIZE = sizeof(uint64_t) ///< Byte size of a word + }; + + enum { excess_bits = (_AP_W%APINT_BITS_PER_WORD) ? APINT_BITS_PER_WORD -(_AP_W%APINT_BITS_PER_WORD) : 0}; + static const uint64_t mask = ((uint64_t)~0ULL >> (excess_bits)); + + /// This constructor is used only internally for speed of construction of + /// temporaries. It is unsafe for general use so it is not public. + /* Constructors */ + + ap_private(const char* val) { + std::string str(val); + uint32_t strLen = str.length(); + const char *strp = str.c_str(); + uint32_t offset = 0; + uint32_t base = 0; + bool neg = false; + uint32_t radix = 16; + ap_parse_sign(strp, base, neg); + ap_parse_prefix(strp + base, offset, radix); + + if ((radix != 10 && neg) || + (strLen - base - offset <= 0) || + InvalidDigit(strp, strLen, base + offset, radix)) { + fprintf(stderr, "invalid character string %s !\n", val); + assert(0); + } + + ap_private ap_private_val(str.c_str(), strLen, radix, base, offset); + if (neg) + ap_private_val = -ap_private_val; + operator = (ap_private_val); + report(); + } + + ap_private(const char* val, int rd) { + std::string str(val); + uint32_t strLen = str.length(); + const char *strp = str.c_str(); + uint32_t offset = 0; + uint32_t base = 0; + uint32_t radix = rd; + bool neg = false; + ap_parse_sign(strp, base, neg); + ap_parse_prefix(strp + base, offset, radix); + + if ((radix != 10 && neg) || + (strLen - base - offset <= 0) || + InvalidDigit(strp, strLen, base + offset, radix)) { + fprintf(stderr, "invalid character string %s !\n", val); + assert(0); + } + + // uint32_t bitsNeeded = ap_private<_AP_W, _AP_S>::getBitsNeeded(strp, strLen, radix); + // ap_private<_AP_W, _AP_S> ap_private_val(bitsNeeded, strp , strLen, radix, base, offset); + ap_private ap_private_val(strp , strLen, radix, base, offset); + if (neg) + ap_private_val = -ap_private_val; + operator = (ap_private_val); + report(); + } + + /// Note that numWords can be smaller or larger than the corresponding bit + /// width but any extraneous bits will be dropped. + /// @param numBits the bit width of the constructed ap_private + /// @param numWords the number of words in bigVal + /// @param bigVal a sequence of words to form the initial value of the ap_private + /// @brief Construct an ap_private of numBits width, initialized as bigVal[]. + ap_private(uint32_t numWords, const uint64_t bigVal[]): VAL(0) { + assert(bigVal && "Null pointer detected!"); + { + // Get memory, cleared to 0 + memset(pVal, 0, _AP_N * sizeof(uint64_t)); + + // Calculate the number of words to copy + uint32_t words = AESL_std::min(numWords, _AP_N); + // Copy the words from bigVal to pVal + memcpy(pVal, bigVal, words * APINT_WORD_SIZE); + if (words >= _AP_W) + clearUnusedBits(); + // Make sure unused high bits are cleared + } + } + + /// This constructor interprets Val as a string in the given radix. The + /// interpretation stops when the first charater that is not suitable for the + /// radix is encountered. Acceptable radix values are 2, 8, 10 and 16. It is + /// an error for the value implied by the string to require more bits than + /// numBits. + /// @param numBits the bit width of the constructed ap_private + /// @param val the string to be interpreted + /// @param radix the radix of Val to use for the intepretation + /// @brief Construct an ap_private from a string representation. + ap_private(const std::string& val, uint8_t radix=2, int base=0, int offset=0): VAL(0) { + assert(!val.empty() && "The input string is empty."); + const char *c_str = val.c_str(); + fromString(c_str+base+offset, val.size()-base-offset, radix); + } + + /// This constructor interprets the slen characters starting at StrStart as + /// a string in the given radix. The interpretation stops when the first + /// character that is not suitable for the radix is encountered. Acceptable + /// radix values are 2, 8, 10 and 16. It is an error for the value implied by + /// the string to require more bits than numBits. + /// @param numBits the bit width of the constructed ap_private + /// @param strStart the start of the string to be interpreted + /// @param slen the maximum number of characters to interpret + /// @param radix the radix to use for the conversion + /// @brief Construct an ap_private from a string representation. + /// This method does not consider whether it is negative or not. + ap_private(const char strStart[], uint32_t slen, uint8_t radix, int base=0, int offset=0) : VAL(0) { + fromString(strStart+base+offset, slen-base-offset, radix); + } + + template + INLINE ap_private(const ap_range_ref<_AP_W2,_AP_S2>& ref) { + *this=ref.get(); + report(); + } + + template + INLINE ap_private(const ap_bit_ref<_AP_W2,_AP_S2>& ref) { + *this = ((uint64_t)(bool)ref); + report(); + } + + template + INLINE ap_private(const ap_concat_ref<_AP_W2, _AP_T2,_AP_W3, _AP_T3>& ref) { + *this=ref.get(); + report(); + } + + template + INLINE ap_private(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2> &val) { + *this = ((val.operator ap_private<_AP_W2, false> ())); + report(); + } + + template + INLINE ap_private(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2> &val) { + *this = (uint64_t)(bool)val; + report(); + } + + /// Simply makes *this a copy of that. + /// @brief Copy Constructor. + template + ap_private(const volatile ap_private<_AP_W1, _AP_S1, _AP_N1>& that): VAL(0) { + operator = (const_cast& >(that)); + } + + template + ap_private(const ap_private<_AP_W1, _AP_S1, _AP_N1>& that): VAL(0) { + operator = (that); + } + + template + explicit ap_private(const ap_private<_AP_W1, _AP_S1, 1>& that): VAL(0) { + static const uint64_t that_sign_ext_mask = (_AP_W1==APINT_BITS_PER_WORD)?0:~0ULL>>(_AP_W1%APINT_BITS_PER_WORD)<<(_AP_W1%APINT_BITS_PER_WORD); + if (that.isNegative()) { + pVal[0] = that.VAL|that_sign_ext_mask; + memset(pVal+1, ~0, sizeof(uint64_t)*(_AP_N-1)); + } else { + pVal[0] = that.VAL; + memset(pVal+1, 0, sizeof(uint64_t)*(_AP_N-1)); + } + clearUnusedBits(); + } + + ap_private(const ap_private& that): VAL(0) { + memcpy(pVal, that.pVal, _AP_N * APINT_WORD_SIZE); + clearUnusedBits(); + } + + /// @brief Destructor. + virtual ~ap_private() {} + + /// Default constructor that creates an uninitialized ap_private. This is useful + /// for object deserialization (pair this with the static method Read). + ap_private(){memset(pVal, 0, sizeof(uint64_t)*(_AP_N));} + + ap_private(uint64_t* val, uint32_t bits=_AP_W) {assert(0);} + ap_private(const uint64_t *const val, uint32_t bits) {assert(0);} + + /// @name Constructors + /// @{ + /// If isSigned is true then val is treated as if it were a signed value + /// (i.e. as an int64_t) and the appropriate sign extension to the bit width + /// will be done. Otherwise, no sign extension occurs (high order bits beyond + /// the range of val are zero filled). + /// @param numBits the bit width of the constructed ap_private + /// @param val the initial value of the ap_private + /// @param isSigned how to treat signedness of val + /// @brief Create a new ap_private of numBits width, initialized as val. +#define CTOR(TYPE, SIGNED) \ + ap_private(TYPE val, bool isSigned=SIGNED) { \ + pVal[0] = val; \ + if (isSigned && int64_t(pVal[0]) < 0) { \ + memset(pVal+1, ~0, sizeof(uint64_t)*(_AP_N-1)); \ + } else { \ + memset(pVal+1, 0, sizeof(uint64_t)*(_AP_N-1)); \ + } \ + clearUnusedBits(); \ + } +#if 1 + CTOR(int, true) + CTOR(bool, false) + CTOR(signed char, true) + CTOR(unsigned char, false) + CTOR(short, true) + CTOR(unsigned short, false) + CTOR(unsigned int, false) + CTOR(long, true) + CTOR(unsigned long, false) + CTOR(unsigned long long, false) + CTOR(long long, true) + CTOR(float, false) + CTOR(double, false) +#undef CTOR +#else + CTOR(uint64_t) +#undef CTOR +#endif + + + /// @returns true if the number of bits <= 64, false otherwise. + /// @brief Determine if this ap_private just has one word to store value. + INLINE bool isSingleWord() const { + return false; + } + + /// @returns the word position for the specified bit position. + /// @brief Determine which word a bit is in. + static uint32_t whichWord(uint32_t bitPosition) { + // return bitPosition / APINT_BITS_PER_WORD; + return (bitPosition) >> 6; + } + + /// @returns the bit position in a word for the specified bit position + /// in the ap_private. + /// @brief Determine which bit in a word a bit is in. + static uint32_t whichBit(uint32_t bitPosition) { + // return bitPosition % APINT_BITS_PER_WORD; + return bitPosition & 0x3f; + } + + /// bit at a specific bit position. This is used to mask the bit in the + /// corresponding word. + /// @returns a uint64_t with only bit at "whichBit(bitPosition)" set + /// @brief Get a single bit mask. + static uint64_t maskBit(uint32_t bitPosition) { + return 1ULL << (whichBit(bitPosition)); + } + + /// @returns the corresponding word for the specified bit position. + /// @brief Get the word corresponding to a bit position + INLINE uint64_t getWord(uint32_t bitPosition) const { + return isSingleWord() ? VAL : pVal[whichWord(bitPosition)]; + } + + /// This method is used internally to clear the to "N" bits in the high order + /// word that are not used by the ap_private. This is needed after the most + /// significant word is assigned a value to ensure that those bits are + /// zero'd out. + /// @brief Clear unused high order bits + INLINE void clearUnusedBits(void) { + pVal[_AP_N-1] = _AP_S ? ((((int64_t)pVal[_AP_N-1])<<(excess_bits))>> excess_bits) : (excess_bits ? ((pVal[_AP_N-1])<<(excess_bits))>>(excess_bits) : pVal[_AP_N-1]); + } + + INLINE void clearUnusedBitsToZero(void) { + pVal[_AP_N-1] &= mask; + } + + INLINE void clearUnusedBitsToOne(void) { + pVal[_AP_N-1] |= mask; + } + + /// This is used by the constructors that take string arguments. + /// @brief Convert a char array into an ap_private + INLINE void fromString(const char *strStart, uint32_t slen, + uint8_t radix) ; + + INLINE ap_private read() volatile { + return *this; + } + + INLINE void write(const ap_private& op2) volatile { + *this = (op2); + } + + //Explicit conversions to C interger types + //----------------------------------------------------------- + operator ValType() const { + return getVal(); + } + + INLINE ValType getVal() const{ + return *pVal; + } + + INLINE int to_int() const { + return int(*this); + } + + INLINE unsigned to_uint() const { + return (unsigned) getVal(); + } + + INLINE long to_long() const { + return (long) getVal(); + } + + INLINE unsigned long to_ulong() const { + return (unsigned long) getVal(); + } + + INLINE ap_slong to_int64() const { + return (ap_slong) getVal(); + } + + INLINE ap_ulong to_uint64() const { + return (ap_ulong) getVal(); + } + + INLINE double to_double() const { + if (isNegative()) + return roundToDouble(true); + else + return roundToDouble(false); + } + + INLINE unsigned length() const { return _AP_W; } + + /*Reverse the contents of ap_private instance. I.e. LSB becomes MSB and vise versa*/ + INLINE ap_private& reverse () { + for (int i = 0; i < _AP_W/2; ++i) { + bool tmp = operator[](i); + if (operator[](_AP_W - 1 - i)) + set(i); + else + clear(i); + if (tmp) + set(_AP_W - 1 - i); + else + clear(_AP_W - 1 - i); + } + clearUnusedBits(); + return *this; + } + + /*Return true if the value of ap_private instance is zero*/ + INLINE bool iszero () const { + return isMinValue(); + } + + /* x < 0 */ + INLINE bool sign () const { + if (isNegative()) + return true; + return false; + } + + /* x[i] = !x[i] */ + INLINE void invert (int i) { + assert( i >= 0 && "Attempting to read bit with negative index"); + assert( i < _AP_W && "Attempting to read bit beyond MSB"); + flip(i); + } + + /* x[i] */ + INLINE bool test (int i) const { + assert( i >= 0 && "Attempting to read bit with negative index"); + assert( i < _AP_W && "Attempting to read bit beyond MSB"); + return operator[](i); + } + + //Set the ith bit into v + INLINE void set (int i, bool v) { + assert( i >= 0 && "Attempting to write bit with negative index"); + assert( i < _AP_W && "Attempting to write bit beyond MSB"); + v ? set(i) : clear(i); + } + + //Set the ith bit into v + INLINE void set_bit (int i, bool v) { + assert( i >= 0 && "Attempting to write bit with negative index"); + assert( i < _AP_W && "Attempting to write bit beyond MSB"); + v ? set(i) : clear(i); + } + + INLINE ap_private& set(uint32_t bitPosition) { + pVal[whichWord(bitPosition)] |= maskBit(bitPosition); + clearUnusedBits(); + return *this; + } + + INLINE void set() { + for (uint32_t i = 0; i < _AP_N; ++i) + pVal[i] = ~0ULL; + clearUnusedBits(); + } + + //Get the value of ith bit + INLINE bool get (int i) const { + assert( i >= 0 && "Attempting to read bit with negative index"); + assert( i < _AP_W && "Attempting to read bit beyond MSB"); + return operator [](i); + } + + //Get the value of ith bit + INLINE bool get_bit (int i) const { + assert( i >= 0 && "Attempting to read bit with negative index"); + assert( i < _AP_W && "Attempting to read bit beyond MSB"); + return operator [](i); + } + + //This is used for sc_lv and sc_bv, which is implemented by sc_uint + //Rotate an ap_private object n places to the left + INLINE void lrotate(int n) { + assert( n >= 0 && "Attempting to shift negative index"); + assert( n < _AP_W && "Shift value larger than bit width"); + operator = (shl(n) | lshr(_AP_W - n)); + } + + //This is used for sc_lv and sc_bv, which is implemented by sc_uint + //Rotate an ap_private object n places to the right + INLINE void rrotate(int n) { + assert( n >= 0 && "Attempting to shift negative index"); + assert( n < _AP_W && "Shift value larger than bit width"); + operator = (lshr(n) | shl(_AP_W - n)); + } + + /// Set the given bit to 0 whose position is given as "bitPosition". + /// @brief Set a given bit to 0. + ap_private& clear(uint32_t bitPosition) { + pVal[whichWord(bitPosition)] &= ~maskBit(bitPosition); + clearUnusedBits(); + return *this; + } + + /// @brief Set every bit to 0. + void clear() { + memset(pVal, 0, _AP_N * APINT_WORD_SIZE); + } + + /// @brief Toggle every bit to its opposite value. + ap_private& flip() { + for (uint32_t i = 0; i < _AP_N; ++i) + pVal[i] ^= ~0ULL; + clearUnusedBits(); + return *this; + } + + /// Toggle a given bit to its opposite value whose position is given + /// as "bitPosition". + /// @brief Toggles a given bit to its opposite value. + ap_private& flip(uint32_t bitPosition) { + assert(bitPosition < BitWidth && "Out of the bit-width range!"); + if ((*this)[bitPosition]) clear(bitPosition); + else set(bitPosition); + return *this; + } + + //complements every bit + INLINE void b_not() { + flip(); + } + + ap_private getLoBits(uint32_t numBits) const { + return ap_private_ops::lshr(ap_private_ops::shl(*this, _AP_W - numBits), + _AP_W - numBits); + } + + ap_private getHiBits(uint32_t numBits) const { + return ap_private_ops::lshr(*this, _AP_W - numBits); + } + + //Binary Arithmetic + //----------------------------------------------------------- + + template + INLINE ap_private + operator & (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) { + return *this & a2.get(); + } + + template + INLINE ap_private + operator | (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) { + return *this | a2.get(); + } + + template + INLINE ap_private + operator ^ (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) { + return *this ^ a2.get(); + } + + + ///Arithmetic assign + //------------------------------------------------------------- + +#define OP_BIN_LOGIC_ASSIGN_AP(Sym) \ + template \ + INLINE ap_private& operator Sym(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { \ + uint32_t numWords = AESL_std::min(_AP_N, _AP_N1); \ + uint32_t i; \ + for (i = 0; i < numWords; ++i) \ + pVal[i] Sym RHS.pVal[i]; \ + if (_AP_N1 < _AP_N) { \ + uint64_t ext = RHS.isNegative()?~0ULL:0; \ + for (;i<_AP_N; i++) \ + pVal[i] Sym ext; \ + } \ + clearUnusedBits(); \ + return *this; \ + } + + OP_BIN_LOGIC_ASSIGN_AP(&=); + OP_BIN_LOGIC_ASSIGN_AP(|=); + OP_BIN_LOGIC_ASSIGN_AP(^=); +#undef OP_BIN_LOGIC_ASSIGN_AP + + /// Adds the RHS APint to this ap_private. + /// @returns this, after addition of RHS. + /// @brief Addition assignment operator. + template + INLINE ap_private& operator+=(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { + add(pVal, pVal, RHS.pVal, _AP_N, _AP_N, _AP_N1, _AP_S, _AP_S1); + clearUnusedBits(); + return *this; + } + + template + INLINE ap_private& operator-=(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { + sub(pVal, pVal, RHS.pVal, _AP_N, _AP_N, _AP_N1, _AP_S, _AP_S1); + clearUnusedBits(); + return *this; + } + + template + ap_private& operator*=(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { + // Get some bit facts about LHS and check for zero + uint32_t lhsBits = getActiveBits(); + uint32_t lhsWords = !lhsBits ? 0 : whichWord(lhsBits - 1) + 1; + if (!lhsWords) { + // 0 * X ===> 0 + return *this; + } + + ap_private dupRHS = RHS; + // Get some bit facts about RHS and check for zero + uint32_t rhsBits = dupRHS.getActiveBits(); + uint32_t rhsWords = !rhsBits ? 0 : whichWord(rhsBits - 1) + 1; + if (!rhsWords) { + // X * 0 ===> 0 + clear(); + return *this; + } + + // Allocate space for the result + uint32_t destWords = rhsWords + lhsWords; + uint64_t *dest = getMemory(destWords); + + // Perform the long multiply + mul(dest, pVal, lhsWords, dupRHS.pVal, rhsWords, destWords); + + // Copy result back into *this + clear(); + uint32_t wordsToCopy = destWords >= _AP_N ? _AP_N : destWords; + + memcpy(pVal, dest, wordsToCopy* APINT_WORD_SIZE); + + uint64_t ext = (isNegative() ^ RHS.isNegative()) ? ~0ULL : 0ULL; + for (int i=wordsToCopy; i<_AP_N; i++) + pVal[i]=ext; + clearUnusedBits(); + // delete dest array and return + free(dest); + return *this; + } + +#define OP_ASSIGN_AP(Sym) \ + template \ + INLINE ap_private& operator Sym##=(const ap_private<_AP_W2,_AP_S2>& op) \ + { \ + *this=operator Sym (op); \ + return *this; \ + } \ + + OP_ASSIGN_AP(/) + OP_ASSIGN_AP(%) +#undef OP_ASSIGN_AP + +#define OP_BIN_LOGIC_AP(Sym) \ + template \ + INLINE \ + typename RType<_AP_W1, _AP_S1>::logic \ + operator Sym (const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) const { \ + enum { numWords = (RType<_AP_W1, _AP_S1>::logic_w +APINT_BITS_PER_WORD-1)/APINT_BITS_PER_WORD}; \ + typename RType<_AP_W1, _AP_S1>::logic Result; \ + uint64_t *val = Result.pVal; \ + uint32_t i; \ + uint32_t min_N = std::min(_AP_N, _AP_N1); \ + uint32_t max_N = std::max(_AP_N, _AP_N1); \ + for (i = 0; i < min_N; ++i) \ + val[i] = pVal[i] Sym RHS.pVal[i]; \ + if (numWords > i) { \ + const uint64_t* tmpVal = (_AP_N>_AP_N1 ? pVal : RHS.pVal)+i; \ + uint64_t ext = ((_AP_N<_AP_N1 && isNegative() )||(_AP_N1 < _AP_N && RHS.isNegative())) ? ~0ULL : 0; \ + for (;i i) { \ + uint64_t ext2 = ((_AP_N>_AP_N1 && isNegative() )||(_AP_N1 > _AP_N && RHS.isNegative())) ? ~0ULL : 0; \ + val[i] = ext Sym ext2; \ + } \ + } \ + Result.clearUnusedBits(); \ + return Result; \ + } + + OP_BIN_LOGIC_AP(|); + OP_BIN_LOGIC_AP(&); + OP_BIN_LOGIC_AP(^); + +#undef OP_BIN_LOGIC_AP + + template + INLINE typename RType<_AP_W1,_AP_S1>::plus operator+(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) const { + // assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + typename RType<_AP_W1,_AP_S1>::plus Result; + bool carry = add(Result.pVal, this->pVal, RHS.pVal, (RType<_AP_W1,_AP_S1>::plus_w + 63) / 64, _AP_N, _AP_N1, _AP_S, _AP_S1); + if ((RType<_AP_W1,_AP_S1>::plus_w + 63) / 64> std::max(_AP_W, _AP_W1) ) + Result.pVal[(RType<_AP_W1,_AP_S1>::plus_w + 63)/64 - 1] = carry; + Result.clearUnusedBits(); + return Result; + } + + template + INLINE typename RType<_AP_W1,_AP_S1>::minus operator-(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) const { + typename RType<_AP_W1,_AP_S1>::minus Result; + bool borrow = sub(Result.pVal, this->pVal, RHS.pVal, (RType<_AP_W1,_AP_S1>::minus_w + 63) / 64, _AP_N, _AP_N1, _AP_S, _AP_S1); + if ((RType<_AP_W1,_AP_S1>::minus_w + 63) / 64 > AESL_std::max(_AP_W, _AP_W1) ) { + Result.pVal[(RType<_AP_W1,_AP_S1>::minus_w+63)/64 - 1] = borrow; + } + Result.clearUnusedBits(); + return Result; + } + + template + typename RType<_AP_W1, _AP_S1>::mult operator*(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) const { + + // Get some bit facts about LHS and check for zero + uint32_t lhsBits = getActiveBits(); + uint32_t lhsWords = !lhsBits ? 0 : whichWord(lhsBits - 1) + 1; + if (!lhsWords) + // 0 * X ===> 0 + return typename RType<_AP_W1, _AP_S1>::mult(); + + // Get some bit facts about RHS and check for zero + uint32_t rhsBits = RHS.getActiveBits(); + uint32_t rhsWords = !rhsBits ? 0 : whichWord(rhsBits - 1) + 1; + if (!rhsWords) { + // X * 0 ===> 0 + return typename RType<_AP_W1, _AP_S1>::mult(); + } + + //extend size to avoid result loss + typename RType<_AP_W1, _AP_S1>::mult dupLHS = *this; + typename RType<_AP_W1, _AP_S1>::mult dupRHS = RHS; + lhsBits = dupLHS.getActiveBits(); + lhsWords = !lhsBits ? 0 : whichWord(lhsBits - 1) + 1; + rhsBits = dupRHS.getActiveBits(); + rhsWords = !rhsBits ? 0 : whichWord(rhsBits - 1) + 1; + + // Allocate space for the result + enum { destWords =(RType<_AP_W1, _AP_S1>::mult_w+APINT_BITS_PER_WORD-1)/APINT_BITS_PER_WORD}; + int destw = destWords; + typename RType<_AP_W1, _AP_S1>::mult Result; + uint64_t *dest = Result.pVal; + uint64_t ext = (isNegative() ^ RHS.isNegative()) ? ~0ULL : 0; + + // Perform the long multiply + mul(dest, dupLHS.pVal, lhsWords, dupRHS.pVal, rhsWords, destWords); + + for (int i=lhsWords+rhsWords; i + INLINE typename RType<_AP_W2,_AP_S2>::div + operator / (const ap_private<_AP_W2,_AP_S2>& op) const { + ap_private lhs=ap_private(*this); + ap_private rhs=ap_private(op); + return typename RType<_AP_W2,_AP_S2>::div((_AP_S||_AP_S2)?lhs.sdiv(rhs):lhs.udiv(rhs)); + } + + template + INLINE typename RType<_AP_W2,_AP_S2>::mod + operator % (const ap_private<_AP_W2,_AP_S2>& op) const { + ap_private lhs=*this; + ap_private rhs= op; + typename RType<_AP_W2,_AP_S2>::mod res = typename RType<_AP_W2,_AP_S2>::mod(_AP_S?lhs.srem(rhs):lhs.urem(rhs)); + return res; + } + + template + INLINE ap_private + operator << (const ap_private<_AP_W2, _AP_S2>& op2) const { + uint32_t sh=op2.to_uint(); + return *this << sh; + } + + INLINE ap_private + operator << (uint32_t sh) const { + ap_private r(*this); + bool overflow=(sh>=length()); + if(overflow) + r.clear(); + else + r = ap_private(r.shl(sh)); + return r; + } + + template + INLINE ap_private + operator >> (const ap_private<_AP_W2, _AP_S2>& op2) const { + uint32_t sh = op2.to_uint(); + return *this >> sh; + } + + INLINE ap_private + operator >> (uint32_t sh) const { + ap_private r(*this); + bool overflow=(sh>=_AP_W); + bool neg_v=r.isNegative(); + if(_AP_S) { + if(overflow) + neg_v?r.set():r.clear(); + else + return r.ashr(sh); + } else { + if(overflow) + r.clear(); + else + return r.lshr(sh); + } + return r; + } + + ///Shift assign + //------------------------------------------------------------------ +#define OP_ASSIGN_AP(Sym) \ + template \ + INLINE ap_private& operator Sym##=(int op) \ + { \ + *this = operator Sym (op); \ + return *this; \ + } \ + INLINE ap_private& operator Sym##=(unsigned int op) \ + { \ + *this = operator Sym (op); \ + return *this; \ + } \ + template \ + INLINE ap_private& operator Sym##=(const ap_private<_AP_W2,_AP_S2>& op) \ + { \ + *this = operator Sym (op); \ + return *this; \ + } + OP_ASSIGN_AP(>>) + OP_ASSIGN_AP(<<) +#undef OP_ASSIGN_AP + ///Comparisons + //----------------------------------------------------------------- + bool operator==(const ap_private& RHS) const { + // Get some facts about the number of bits used in the two operands. + uint32_t n1 = getActiveBits(); + uint32_t n2 = RHS.getActiveBits(); + + // If the number of bits isn't the same, they aren't equal + if (n1 != n2) + return false; + + // If the number of bits fits in a word, we only need to compare the low word. + if (n1 <= APINT_BITS_PER_WORD) + return pVal[0] == RHS.pVal[0]; + + // Otherwise, compare everything + for (int i = whichWord(n1 - 1); i >= 0; --i) + if (pVal[i] != RHS.pVal[i]) + return false; + return true; + } + + template + INLINE bool operator == (const ap_private<_AP_W2, _AP_S2>& op) const { + enum { _AP_MAX_W = AP_MAX(_AP_W+(_AP_S||_AP_S2),_AP_W2+(_AP_S||_AP_S2))}; + ap_private<_AP_MAX_W, _AP_S|_AP_S2> lhs(*this); + ap_private<_AP_MAX_W, _AP_S|_AP_S2> rhs(op); + return lhs==rhs; + } + + bool operator==(uint64_t Val) const { + uint32_t n = getActiveBits(); + if (n <= APINT_BITS_PER_WORD) + return pVal[0] == Val; + else + return false; + } + + template + INLINE bool operator != (const ap_private<_AP_W2, _AP_S2>& op) const { + return !(*this==op); + } + + template + INLINE bool operator!=(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return !((*this) == RHS); + } + + INLINE bool operator!=(uint64_t Val) const { + return !((*this) == Val); + } + + + template + INLINE bool operator <= (const ap_private<_AP_W2,_AP_S2>& op) const { + return !(*this>op); + } + + INLINE bool operator <(const ap_private& op) const { + return _AP_S ? slt(op):ult(op); + } + + template + INLINE bool operator < (const ap_private<_AP_W2, _AP_S2>& op) const { + enum { _AP_MAX_W = AP_MAX(_AP_W+(_AP_S||_AP_S2),_AP_W2+(_AP_S||_AP_S2))}; + ap_private<_AP_MAX_W, _AP_S> lhs(*this); + ap_private<_AP_MAX_W, _AP_S2> rhs(op); + if (_AP_S == _AP_S2) + return _AP_S?lhs.slt(rhs):lhs.ult(rhs); + else + if (_AP_S) + if (_AP_W2 >= _AP_W) + return lhs.ult(rhs); + else + return lhs.slt(rhs); + else + if (_AP_W >= _AP_W2) + return lhs.ult(rhs); + else + return lhs.slt(rhs); + } + + template + INLINE bool operator >=(const ap_private<_AP_W2,_AP_S2>& op) const { + return !(*this + INLINE bool operator > (const ap_private<_AP_W2, _AP_S2>& op) const { + enum { _AP_MAX_W = AP_MAX(_AP_W+(_AP_S||_AP_S2),_AP_W2+(_AP_S||_AP_S2))}; + ap_private<_AP_MAX_W, _AP_S> lhs(*this); + ap_private<_AP_MAX_W, _AP_S2> rhs(op); + if (_AP_S == _AP_S2) + return _AP_S?lhs.sgt(rhs):lhs.ugt(rhs); + else + if (_AP_S) + if (_AP_W2 >= _AP_W) + return lhs.ugt(rhs); + else + return lhs.sgt(rhs); + else + if (_AP_W >= _AP_W2) + return lhs.ugt(rhs); + else + return lhs.sgt(rhs); + } + + ///Bit and Part Select + //-------------------------------------------------------------- + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (int Hi, int Lo) { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (int Hi, int Lo) const { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(const_cast*>(this), Hi, Lo); + } + + INLINE ap_range_ref<_AP_W,_AP_S> + range (int Hi, int Lo) const { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>((const_cast*> (this)), Hi, Lo); + } + + INLINE ap_range_ref<_AP_W,_AP_S> + range (int Hi, int Lo) { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + range (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + range (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) const { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(const_cast(this), Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) const { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + return this->range(Hi, Lo); + } + + INLINE ap_bit_ref<_AP_W,_AP_S> operator [] (uint32_t index) { + assert(index >= 0&&"Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S>( *this, index ); + } + + template + INLINE ap_bit_ref<_AP_W,_AP_S> operator [] (const ap_private<_AP_W2,_AP_S2> &index) { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S>( *this, index.to_int() ); + } + + template + INLINE bool operator [] (const ap_private<_AP_W2,_AP_S2>& index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + ap_bit_ref<_AP_W,_AP_S> br =operator [] (index); + return br.to_bool(); + } + + INLINE bool operator [](uint32_t bitPosition) const { + return (maskBit(bitPosition) & (pVal[whichWord(bitPosition)])) != 0; + } + + INLINE ap_bit_ref<_AP_W,_AP_S> bit (int index) { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S>( *this, index ); + } + + template + INLINE ap_bit_ref<_AP_W,_AP_S> bit (const ap_private<_AP_W2,_AP_S2> &index) { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W &&"Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S>( *this, index.to_int() ); + } + + INLINE bool bit (int index) const { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + ap_bit_ref<_AP_W,_AP_S> br(const_cast*>(this), index); + return br.to_bool(); + } + + template + INLINE bool bit (const ap_private<_AP_W2,_AP_S2>& index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + ap_bit_ref<_AP_W,_AP_S> br = bit(index); + return br.to_bool(); + } + + template + INLINE ap_concat_ref<_AP_W,ap_private<_AP_W, _AP_S>,_AP_W2,ap_private<_AP_W2,_AP_S2> > concat(ap_private<_AP_W2,_AP_S2>& a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_private<_AP_W2,_AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W,ap_private<_AP_W, _AP_S>,_AP_W2,ap_private<_AP_W2,_AP_S2> > concat(const ap_private<_AP_W2,_AP_S2>& a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_private<_AP_W2,_AP_S2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (ap_private<_AP_W2, _AP_S2>& a2) { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (ap_private<_AP_W2, _AP_S2>& a2) const { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(const_cast& >(*this), a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (const ap_private<_AP_W2, _AP_S2>& a2) { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(*this, const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (const ap_private<_AP_W2, _AP_S2>& a2) const { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(const_cast& >(*this), const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > + operator, (const ap_range_ref<_AP_W2, _AP_S2> &a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, + ap_range_ref<_AP_W2, _AP_S2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > + operator, (ap_range_ref<_AP_W2, _AP_S2> &a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, + ap_range_ref<_AP_W2, _AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, ap_bit_ref<_AP_W2, _AP_S2> > + operator, (const ap_bit_ref<_AP_W2, _AP_S2> &a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, + ap_bit_ref<_AP_W2, _AP_S2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, ap_bit_ref<_AP_W2, _AP_S2> > + operator, (ap_bit_ref<_AP_W2, _AP_S2> &a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, + ap_bit_ref<_AP_W2, _AP_S2> >(*this, a2); + } + + template + INLINE + ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > + operator, (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE + ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > + operator, (ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) const { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) const { + return ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, a2); + } + + INLINE ap_private<_AP_W,false> get() const { + ap_private<_AP_W,false> ret(*this); + return ret; + } + + template + INLINE void set(const ap_private<_AP_W3, false> & val) { + operator = (ap_private<_AP_W3, _AP_S>(val)); + } + + /// @} + /// @name Value Tests + /// @{ + /// This tests the high bit of this ap_private to determine if it is set. + /// @returns true if this ap_private is negative, false otherwise + /// @brief Determine sign of this ap_private. + INLINE bool isNegative() const { + //just for get rid of warnings + enum {shift = (_AP_W-APINT_BITS_PER_WORD*(_AP_N-1)-1)}; + static const uint64_t mask = 1ULL << (shift); + return _AP_S && (pVal[_AP_N-1]&mask); + } + + /// This tests the high bit of the ap_private to determine if it is unset. + /// @brief Determine if this ap_private Value is positive (not negative). + INLINE bool isPositive() const { + return !isNegative(); + } + + /// This tests if the value of this ap_private is strictly positive (> 0). + /// @returns true if this ap_private is Positive and not zero. + /// @brief Determine if this ap_private Value is strictly positive. + INLINE bool isStrictlyPositive() const { + return isPositive() && (*this) != 0; + } + + /// This checks to see if the value has all bits of the ap_private are set or not. + /// @brief Determine if all bits are set + INLINE bool isAllOnesValue() const { + return countPopulation() == _AP_W; + } + + /// This checks to see if the value of this ap_private is the maximum unsigned + /// value for the ap_private's bit width. + /// @brief Determine if this is the largest unsigned value. + INLINE bool isMaxValue() const { + return countPopulation() == _AP_W; + } + + /// This checks to see if the value of this ap_private is the maximum signed + /// value for the ap_private's bit width. + /// @brief Determine if this is the largest signed value. + INLINE bool isMaxSignedValue() const { + return BitWidth == 1 ? VAL == 0 : + !isNegative() && countPopulation() == _AP_W - 1; + } + + /// This checks to see if the value of this ap_private is the minimum unsigned + /// value for the ap_private's bit width. + /// @brief Determine if this is the smallest unsigned value. + INLINE bool isMinValue() const { + return countPopulation() == 0; + } + + /// This checks to see if the value of this ap_private is the minimum signed + /// value for the ap_private's bit width. + /// @brief Determine if this is the smallest signed value. + INLINE bool isMinSignedValue() const { + return BitWidth == 1 ? VAL == 1 : + isNegative() && countPopulation() == 1; + } + + /// This function returns a pointer to the internal storage of the ap_private. + /// This is useful for writing out the ap_private in binary form without any + /// conversions. + INLINE const uint64_t* getRawData() const { + if (isSingleWord()) + return &VAL; + return &pVal[0]; + } + + ap_private sqrt() const; + + /// @} + /// @Assignment Operators + /// @{ + /// @returns *this after assignment of RHS. + /// @brief Copy assignment operator. + INLINE ap_private& operator=(const ap_private& RHS) { + if (this != &RHS) + memcpy(pVal, RHS.pVal, _AP_N * APINT_WORD_SIZE); + return *this; + } + INLINE ap_private& operator=(const volatile ap_private& RHS) { + if (this != &RHS) + for (int i=0; i<_AP_N; ++i) + pVal[i] = RHS.pVal[i]; + return *this; + } + INLINE volatile ap_private& operator=(const ap_private& RHS) volatile { + if (this != &RHS) + for (int i=0; i<_AP_N; ++i) + pVal[i] = RHS.pVal[i]; + return *this; + } + INLINE volatile ap_private& operator=(const volatile ap_private& RHS) volatile { + if (this != &RHS) + for (int i=0; i<_AP_N; ++i) + pVal[i] = RHS.pVal[i]; + return *this; + } + + template + INLINE ap_private& operator=(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { + if (_AP_S1) + cpSextOrTrunc(RHS); + else + cpZextOrTrunc(RHS); + clearUnusedBits(); + return *this; + } + + template + INLINE ap_private& operator=(const volatile ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { + if (_AP_S1) + cpSextOrTrunc(RHS); + else + cpZextOrTrunc(RHS); + clearUnusedBits(); + return *this; + } + + template + INLINE ap_private& operator=(const ap_private<_AP_W1, _AP_S1, 1>& RHS) { + static const uint64_t that_sign_ext_mask = (_AP_W1==APINT_BITS_PER_WORD)?0:~0ULL>>(_AP_W1%APINT_BITS_PER_WORD)<<(_AP_W1%APINT_BITS_PER_WORD); + if (RHS.isNegative()) { + pVal[0] = RHS.VAL | that_sign_ext_mask; + memset(pVal+1,~0, APINT_WORD_SIZE*(_AP_N-1)); + } else { + pVal[0] = RHS.VAL; + memset(pVal+1, 0, APINT_WORD_SIZE*(_AP_N-1)); + } + clearUnusedBits(); + return *this; + } + + template + INLINE ap_private& operator=(const volatile ap_private<_AP_W1, _AP_S1, 1>& RHS) { + static const uint64_t that_sign_ext_mask = (_AP_W1==APINT_BITS_PER_WORD)?0:~0ULL>>(_AP_W1%APINT_BITS_PER_WORD)<<(_AP_W1%APINT_BITS_PER_WORD); + if (RHS.isNegative()) { + pVal[0] = RHS.VAL | that_sign_ext_mask; + memset(pVal+1,~0, APINT_WORD_SIZE*(_AP_N-1)); + } else { + pVal[0] = RHS.VAL; + memset(pVal+1, 0, APINT_WORD_SIZE*(_AP_N-1)); + } + clearUnusedBits(); + return *this; + } + + /// @} + /// @name Unary Operators + /// @{ + /// @returns a new ap_private value representing *this incremented by one + /// @brief Postfix increment operator. + INLINE const ap_private operator++(int) { + ap_private API(*this); + ++(*this); + return API; + } + + /// @returns *this incremented by one + /// @brief Prefix increment operator. + INLINE ap_private& operator++() { + add_1(pVal, pVal, _AP_N, 1); + clearUnusedBits(); + return *this; + } + + /// @returns a new ap_private representing *this decremented by one. + /// @brief Postfix decrement operator. + INLINE const ap_private operator--(int) { + ap_private API(*this); + --(*this); + return API; + } + + /// @returns *this decremented by one. + /// @brief Prefix decrement operator. + INLINE ap_private& operator--() { + sub_1(pVal, _AP_N, 1); + clearUnusedBits(); + return *this; + } + + /// Performs a bitwise complement operation on this ap_private. + /// @returns an ap_private that is the bitwise complement of *this + /// @brief Unary bitwise complement operator. + INLINE ap_private operator~() const { + ap_private Result(*this); + Result.flip(); + return Result; + } + + /// Negates *this using two's complement logic. + /// @returns An ap_private value representing the negation of *this. + /// @brief Unary negation operator + INLINE typename RType<1,false>::minus operator-() const { + return ap_private<1,false>(0) - (*this); + } + + /// Performs logical negation operation on this ap_private. + /// @returns true if *this is zero, false otherwise. + /// @brief Logical negation operator. + INLINE bool operator !() const { + for (uint32_t i = 0; i < _AP_N; ++i) + if (pVal[i]) + return false; + return true; + } + + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> And(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return this->operator&(RHS); + } + template + INLINE ap_private Or(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return this->operator|(RHS); + } + template + ap_private Xor(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return this->operator^(RHS); + } + + ap_private Mul(const ap_private& RHS) const { + ap_private Result(*this); + Result *= RHS; + return Result; + } + + ap_private Add(const ap_private& RHS) const { + ap_private Result(0); + bool carry = add(Result.pVal, this->pVal, RHS.pVal, _AP_N, _AP_N, _AP_N, _AP_S, _AP_S); + Result.clearUnusedBits(); + return Result; + } + + ap_private Sub(const ap_private& RHS) const { + ap_private Result(0); + sub(Result.pVal, this->pVal, RHS.pVal, _AP_N, _AP_N, _AP_N, _AP_S, _AP_S); + Result.clearUnusedBits(); + return Result; + } + + /// Arithmetic right-shift this ap_private by shiftAmt. + /// @brief Arithmetic right-shift function. + ap_private ashr(uint32_t shiftAmt) const { + assert(shiftAmt <= BitWidth && "Invalid shift amount, too big"); + // Handle a degenerate case + if (shiftAmt == 0) + return *this; + + // Handle single word shifts with built-in ashr + if (isSingleWord()) { + if (shiftAmt == BitWidth) + return ap_private(/*BitWidth, 0*/); // undefined + else { + uint32_t SignBit = APINT_BITS_PER_WORD - BitWidth; + return ap_private(/*BitWidth,*/ + (((int64_t(VAL) << (SignBit)) >> (SignBit)) >> (shiftAmt))); + } + } + + // If all the bits were shifted out, the result is, technically, undefined. + // We return -1 if it was negative, 0 otherwise. We check this early to avoid + // issues in the algorithm below. + if (shiftAmt == BitWidth) { + if (isNegative()) + return ap_private(-1); + else + return ap_private(0); + } + + // Create some space for the result. + ap_private Retval(0); + uint64_t * val = Retval.pVal; + + // Compute some values needed by the following shift algorithms + uint32_t wordShift = shiftAmt % APINT_BITS_PER_WORD; // bits to shift per word + uint32_t offset = shiftAmt / APINT_BITS_PER_WORD; // word offset for shift + uint32_t breakWord = _AP_N - 1 - offset; // last word affected + uint32_t bitsInWord = whichBit(BitWidth); // how many bits in last word? + if (bitsInWord == 0) + bitsInWord = APINT_BITS_PER_WORD; + + // If we are shifting whole words, just move whole words + if (wordShift == 0) { + // Move the words containing significant bits + for (uint32_t i = 0; i <= breakWord; ++i) + val[i] = pVal[i+offset]; // move whole word + + // Adjust the top significant word for sign bit fill, if negative + if (isNegative()) + if (bitsInWord < APINT_BITS_PER_WORD) + val[breakWord] |= ~0ULL << (bitsInWord); // set high bits + } else { + // Shift the low order words + for (uint32_t i = 0; i < breakWord; ++i) { + // This combines the shifted corresponding word with the low bits from + // the next word (shifted into this word's high bits). + val[i] = ((pVal[i+offset]) >> (wordShift)); + val[i] |= ((pVal[i+offset+1]) << (APINT_BITS_PER_WORD - wordShift)); + } + + // Shift the break word. In this case there are no bits from the next word + // to include in this word. + val[breakWord] = (pVal[breakWord+offset]) >> (wordShift); + + // Deal with sign extenstion in the break word, and possibly the word before + // it. + if (isNegative()) { + if (wordShift > bitsInWord) { + if (breakWord > 0) + val[breakWord-1] |= + ~0ULL << (APINT_BITS_PER_WORD - (wordShift - bitsInWord)); + val[breakWord] |= ~0ULL; + } else + val[breakWord] |= (~0ULL << (bitsInWord - wordShift)); + } + } + + // Remaining words are 0 or -1, just assign them. + uint64_t fillValue = (isNegative() ? ~0ULL : 0); + for (uint32_t i = breakWord+1; i < _AP_N; ++i) + val[i] = fillValue; + Retval.clearUnusedBits(); + return Retval; + } + + /// Logical right-shift this ap_private by shiftAmt. + /// @brief Logical right-shift function. + ap_private lshr(uint32_t shiftAmt) const { + if (isSingleWord()) { + if (shiftAmt == BitWidth) + return ap_private(0); + else + return ap_private((this->VAL) >> (shiftAmt)); + } + + // If all the bits were shifted out, the result is 0. This avoids issues + // with shifting by the size of the integer type, which produces undefined + // results. We define these "undefined results" to always be 0. + if (shiftAmt == BitWidth) + return ap_private(0); + + // If none of the bits are shifted out, the result is *this. This avoids + // issues with shifting byt he size of the integer type, which produces + // undefined results in the code below. This is also an optimization. + if (shiftAmt == 0) + return *this; + + // Create some space for the result. + ap_private Retval(0); + uint64_t * val = Retval.pVal; + + // If we are shifting less than a word, compute the shift with a simple carry + if (shiftAmt < APINT_BITS_PER_WORD) { + uint64_t carry = 0; + for (int i = _AP_N-1; i >= 0; --i) { + val[i] = ((pVal[i]) >> (shiftAmt)) | carry; + carry = (pVal[i]) << (APINT_BITS_PER_WORD - shiftAmt); + } + Retval.clearUnusedBits(); + return Retval; + } + + // Compute some values needed by the remaining shift algorithms + uint32_t wordShift = shiftAmt % APINT_BITS_PER_WORD; + uint32_t offset = shiftAmt / APINT_BITS_PER_WORD; + + // If we are shifting whole words, just move whole words + if (wordShift == 0) { + for (uint32_t i = 0; i < _AP_N - offset; ++i) + val[i] = pVal[i+offset]; + for (uint32_t i = _AP_N-offset; i < _AP_N; i++) + val[i] = 0; + Retval.clearUnusedBits(); + return Retval; + } + + // Shift the low order words + uint32_t breakWord = _AP_N - offset -1; + for (uint32_t i = 0; i < breakWord; ++i) + val[i] = ((pVal[i+offset]) >> (wordShift)) | + ((pVal[i+offset+1]) << (APINT_BITS_PER_WORD - wordShift)); + // Shift the break word. + val[breakWord] = (pVal[breakWord+offset]) >> (wordShift); + + // Remaining words are 0 + for (uint32_t i = breakWord+1; i < _AP_N; ++i) + val[i] = 0; + Retval.clearUnusedBits(); + return Retval; + } + + /// Left-shift this ap_private by shiftAmt. + /// @brief Left-shift function. + ap_private shl(uint32_t shiftAmt) const { + assert(shiftAmt <= BitWidth && "Invalid shift amount, too big"); + if (isSingleWord()) { + if (shiftAmt == BitWidth) + return ap_private(0); // avoid undefined shift results + return ap_private((VAL) << (shiftAmt)); + } + + // If all the bits were shifted out, the result is 0. This avoids issues + // with shifting by the size of the integer type, which produces undefined + // results. We define these "undefined results" to always be 0. + if (shiftAmt == BitWidth) + return ap_private(0); + + // If none of the bits are shifted out, the result is *this. This avoids a + // lshr by the words size in the loop below which can produce incorrect + // results. It also avoids the expensive computation below for a common case. + if (shiftAmt == 0) + return *this; + + // Create some space for the result. + ap_private Retval(0); + uint64_t* val = Retval.pVal; + // If we are shifting less than a word, do it the easy way + if (shiftAmt < APINT_BITS_PER_WORD) { + uint64_t carry = 0; + for (uint32_t i = 0; i < _AP_N; i++) { + val[i] = ((pVal[i]) << (shiftAmt)) | carry; + carry = (pVal[i]) >> (APINT_BITS_PER_WORD - shiftAmt); + } + Retval.clearUnusedBits(); + return Retval; + } + + // Compute some values needed by the remaining shift algorithms + uint32_t wordShift = shiftAmt % APINT_BITS_PER_WORD; + uint32_t offset = shiftAmt / APINT_BITS_PER_WORD; + + // If we are shifting whole words, just move whole words + if (wordShift == 0) { + for (uint32_t i = 0; i < offset; i++) + val[i] = 0; + for (uint32_t i = offset; i < _AP_N; i++) + val[i] = pVal[i-offset]; + Retval.clearUnusedBits(); + return Retval; + } + + // Copy whole words from this to Result. + uint32_t i = _AP_N - 1; + for (; i > offset; --i) + val[i] = (pVal[i-offset]) << (wordShift) | + (pVal[i-offset-1]) >> (APINT_BITS_PER_WORD - wordShift); + val[offset] = (pVal[0]) << (wordShift); + for (i = 0; i < offset; ++i) + val[i] = 0; + Retval.clearUnusedBits(); + return Retval; + } + + INLINE ap_private rotl(uint32_t rotateAmt) const { + if (rotateAmt == 0) + return *this; + // Don't get too fancy, just use existing shift/or facilities + ap_private hi(*this); + ap_private lo(*this); + hi.shl(rotateAmt); + lo.lshr(BitWidth - rotateAmt); + return hi | lo; + } + + INLINE ap_private rotr(uint32_t rotateAmt) const { + if (rotateAmt == 0) + return *this; + // Don't get too fancy, just use existing shift/or facilities + ap_private hi(*this); + ap_private lo(*this); + lo.lshr(rotateAmt); + hi.shl(BitWidth - rotateAmt); + return hi | lo; + } + + /// Perform an unsigned divide operation on this ap_private by RHS. Both this and + /// RHS are treated as unsigned quantities for purposes of this division. + /// @returns a new ap_private value containing the division result + /// @brief Unsigned division operation. + ap_private udiv(const ap_private& RHS) const { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + + // First, deal with the easy case + if (isSingleWord()) { + assert(RHS.VAL != 0 && "Divide by zero?"); + return ap_private(VAL / RHS.VAL); + } + + // Get some facts about the LHS and RHS number of bits and words + uint32_t rhsBits = RHS.getActiveBits(); + uint32_t rhsWords = !rhsBits ? 0 : (whichWord(rhsBits - 1) + 1); + assert(rhsWords && "Divided by zero???"); + uint32_t lhsBits = this->getActiveBits(); + uint32_t lhsWords = !lhsBits ? 0 : (whichWord(lhsBits - 1) + 1); + + // Deal with some degenerate cases + if (!lhsWords) + // 0 / X ===> 0 + return ap_private(0); + else if (lhsWords < rhsWords || this->ult(RHS)) { + // X / Y ===> 0, iff X < Y + return ap_private(0); + } else if (*this == RHS) { + // X / X ===> 1 + return ap_private(1); + } else if (lhsWords == 1 && rhsWords == 1) { + // All high words are zero, just use native divide + return ap_private(this->pVal[0] / RHS.pVal[0]); + } + + // We have to compute it the hard way. Invoke the Knuth divide algorithm. + ap_private Quotient(0); // to hold result. + divide(*this, lhsWords, RHS, rhsWords, &Quotient, (ap_private*)0); + return Quotient; + } + + /// Signed divide this ap_private by ap_private RHS. + /// @brief Signed division function for ap_private. + INLINE ap_private sdiv(const ap_private& RHS) const { + if (isNegative()) + if (RHS.isNegative()) + return (-(*this)).udiv(-RHS); + else + return -((-(*this)).udiv(RHS)); + else if (RHS.isNegative()) + return -(this->udiv(-RHS)); + return this->udiv(RHS); + } + + /// Perform an unsigned remainder operation on this ap_private with RHS being the + /// divisor. Both this and RHS are treated as unsigned quantities for purposes + /// of this operation. Note that this is a true remainder operation and not + /// a modulo operation because the sign follows the sign of the dividend + /// which is *this. + /// @returns a new ap_private value containing the remainder result + /// @brief Unsigned remainder operation. + ap_private urem(const ap_private& RHS) const { + if (isSingleWord()) { + assert(RHS.VAL != 0 && "Remainder by zero?"); + return ap_private(VAL % RHS.VAL); + } + + // Get some facts about the LHS + uint32_t lhsBits = getActiveBits(); + uint32_t lhsWords = !lhsBits ? 0 : (whichWord(lhsBits - 1) + 1); + + // Get some facts about the RHS + uint32_t rhsBits = RHS.getActiveBits(); + uint32_t rhsWords = !rhsBits ? 0 : (whichWord(rhsBits - 1) + 1); + assert(rhsWords && "Performing remainder operation by zero ???"); + + // Check the degenerate cases + if (lhsWords == 0) { + // 0 % Y ===> 0 + return ap_private(0); + } else if (lhsWords < rhsWords || this->ult(RHS)) { + // X % Y ===> X, iff X < Y + return *this; + } else if (*this == RHS) { + // X % X == 0; + return ap_private(0); + } else if (lhsWords == 1) { + // All high words are zero, just use native remainder + return ap_private(pVal[0] % RHS.pVal[0]); + } + + // We have to compute it the hard way. Invoke the Knuth divide algorithm. + ap_private Remainder(0); + divide(*this, lhsWords, RHS, rhsWords, (ap_private*)(0), &Remainder); + return Remainder; + } + + ap_private urem(uint64_t RHS) const { + // Get some facts about the LHS + uint32_t lhsBits = getActiveBits(); + uint32_t lhsWords = !lhsBits ? 0 : (whichWord(lhsBits - 1) + 1); + // Get some facts about the RHS + uint32_t rhsBits = 64 - CountLeadingZeros_64(RHS); // RHS.getActiveBits(); + uint32_t rhsWords = 1;//!rhsBits ? 0 : (ap_private<_AP_W, _AP_S, _AP_N>::whichWord(rhsBits - 1) + 1); + assert(rhsWords && "Performing remainder operation by zero ???"); + // Check the degenerate cases + if (lhsWords == 0) { + // 0 % Y ===> 0 + return ap_private(0); + } else if (lhsWords < rhsWords || this->ult(RHS)) { + // X % Y ===> X, iff X < Y + return *this; + } else if (*this == RHS) { + // X % X == 0; + return ap_private(0); + } else if (lhsWords == 1) { + // All high words are zero, just use native remainder + return ap_private(pVal[0] % RHS); + } + + // We have to compute it the hard way. Invoke the Knuth divide algorithm. + ap_private Remainder(0); + divide(*this, lhsWords, RHS, (ap_private*)(0), &Remainder); + return Remainder; + } + + /// Signed remainder operation on ap_private. + /// @brief Function for signed remainder operation. + INLINE ap_private srem(const ap_private& RHS) const { + if (isNegative()) { + ap_private lhs = -(*this); + if (RHS.isNegative()) { + ap_private rhs = -RHS; + return -(lhs.urem(rhs)); + } else + return -(lhs.urem(RHS)); + } else if (RHS.isNegative()) { + ap_private rhs = -RHS; + return this->urem(rhs); + } + return this->urem(RHS); + } + + /// Signed remainder operation on ap_private. + /// @brief Function for signed remainder operation. + INLINE ap_private srem(int64_t RHS) const { + if (isNegative()) + if (RHS<0) + return -((-(*this)).urem(-RHS)); + else + return -((-(*this)).urem(RHS)); + else if (RHS<0) + return this->urem(-RHS); + return this->urem(RHS); + } + + /// Sometimes it is convenient to divide two ap_private values and obtain both + /// the quotient and remainder. This function does both operations in the + /// same computation making it a little more efficient. + /// @brief Dual division/remainder interface. + static void udivrem(const ap_private& LHS, const ap_private& RHS, ap_private &Quotient, ap_private& Remainder) { + // Get some size facts about the dividend and divisor + uint32_t lhsBits = LHS.getActiveBits(); + uint32_t lhsWords = !lhsBits ? 0 : (ap_private::whichWord(lhsBits - 1) + 1); + uint32_t rhsBits = RHS.getActiveBits(); + uint32_t rhsWords = !rhsBits ? 0 : (ap_private::whichWord(rhsBits - 1) + 1); + + // Check the degenerate cases + if (lhsWords == 0) { + Quotient = 0; // 0 / Y ===> 0 + Remainder = 0; // 0 % Y ===> 0 + return; + } + + if (lhsWords < rhsWords || LHS.ult(RHS)) { + Quotient = 0; // X / Y ===> 0, iff X < Y + Remainder = LHS; // X % Y ===> X, iff X < Y + return; + } + + if (LHS == RHS) { + Quotient = 1; // X / X ===> 1 + Remainder = 0; // X % X ===> 0; + return; + } + + if (lhsWords == 1 && rhsWords == 1) { + // There is only one word to consider so use the native versions. + if (LHS.isSingleWord()) { + Quotient = ap_private(LHS.VAL / RHS.VAL); + Remainder = ap_private(LHS.VAL % RHS.VAL); + } else { + Quotient = ap_private(LHS.pVal[0] / RHS.pVal[0]); + Remainder = ap_private(LHS.pVal[0] % RHS.pVal[0]); + } + return; + } + + // Okay, lets do it the long way + divide(LHS, lhsWords, RHS, rhsWords, &Quotient, &Remainder); + } + + static void sdivrem(const ap_private &LHS, const ap_private &RHS, + ap_private &Quotient, ap_private &Remainder) { + if (LHS.isNegative()) { + if (RHS.isNegative()) + ap_private::udivrem(-LHS, -RHS, Quotient, Remainder); + else + ap_private::udivrem(-LHS, RHS, Quotient, Remainder); + Quotient = -Quotient; + Remainder = -Remainder; + } else if (RHS.isNegative()) { + ap_private::udivrem(LHS, -RHS, Quotient, Remainder); + Quotient = -Quotient; + } else { + ap_private::udivrem(LHS, RHS, Quotient, Remainder); + } + } + + /// Compares this ap_private with RHS for the validity of the equality + /// relationship. + /// @returns true if *this == Val + /// @brief Equality comparison. + template + INLINE bool eq(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return (*this) == RHS; + } + + /// Compares this ap_private with RHS for the validity of the inequality + /// relationship. + /// @returns true if *this != Val + /// @brief Inequality comparison + template + INLINE bool ne(const ap_private<_AP_W, _AP_S1, _AP_N> &RHS) const { + return !((*this) == RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// the validity of the less-than relationship. + /// @returns true if *this < RHS when both are considered unsigned. + /// @brief Unsigned less than comparison + template + INLINE bool ult(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + // Get active bit length of both operands + uint32_t n1 = getActiveBits(); + uint32_t n2 = RHS.getActiveBits(); + + // If magnitude of LHS is less than RHS, return true. + if (n1 < n2) + return true; + + // If magnitude of RHS is greather than LHS, return false. + if (n2 < n1) + return false; + + // If they bot fit in a word, just compare the low order word + if (n1 <= APINT_BITS_PER_WORD && n2 <= APINT_BITS_PER_WORD) + return pVal[0] < RHS.pVal[0]; + + // Otherwise, compare all words + uint32_t topWord = whichWord(AESL_std::max(n1,n2)-1); + for (int i = topWord; i >= 0; --i) { + if (pVal[i] > RHS.pVal[i]) + return false; + if (pVal[i] < RHS.pVal[i]) + return true; + } + return false; + } + + INLINE bool ult(uint64_t RHS) const { + // Get active bit length of both operands + uint32_t n1 = getActiveBits(); + uint32_t n2 = 64 - CountLeadingZeros_64(RHS); //RHS.getActiveBits(); + + // If magnitude of LHS is less than RHS, return true. + if (n1 < n2) + return true; + + // If magnitude of RHS is greather than LHS, return false. + if (n2 < n1) + return false; + + // If they bot fit in a word, just compare the low order word + if (n1 <= APINT_BITS_PER_WORD && n2 <= APINT_BITS_PER_WORD) + return pVal[0] < RHS; + assert(0); + } + + template + INLINE bool slt(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + ap_private lhs(*this); + ap_private<_AP_W, _AP_S1, _AP_N> rhs(RHS); + bool lhsNeg = isNegative(); + bool rhsNeg = rhs.isNegative(); + if (lhsNeg) { + // Sign bit is set so perform two's complement to make it positive + lhs.flip(); + lhs++; + } + if (rhsNeg) { + // Sign bit is set so perform two's complement to make it positive + rhs.flip(); + rhs++; + } + + // Now we have unsigned values to compare so do the comparison if necessary + // based on the negativeness of the values. + if (lhsNeg) + if (rhsNeg) + return lhs.ugt(rhs); + else + return true; + else if (rhsNeg) + return false; + else + return lhs.ult(rhs); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// validity of the less-or-equal relationship. + /// @returns true if *this <= RHS when both are considered unsigned. + /// @brief Unsigned less or equal comparison + template + INLINE bool ule(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return ult(RHS) || eq(RHS); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the less-or-equal relationship. + /// @returns true if *this <= RHS when both are considered signed. + /// @brief Signed less or equal comparison + template + INLINE bool sle(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return slt(RHS) || eq(RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// the validity of the greater-than relationship. + /// @returns true if *this > RHS when both are considered unsigned. + /// @brief Unsigned greather than comparison + template + INLINE bool ugt(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return !ult(RHS) && !eq(RHS); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// the validity of the greater-than relationship. + /// @returns true if *this > RHS when both are considered signed. + /// @brief Signed greather than comparison + template + INLINE bool sgt(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return !slt(RHS) && !eq(RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// validity of the greater-or-equal relationship. + /// @returns true if *this >= RHS when both are considered unsigned. + /// @brief Unsigned greater or equal comparison + template + INLINE bool uge(const ap_private<_AP_W, _AP_S, _AP_N>& RHS) const { + return !ult(RHS); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the greater-or-equal relationship. + /// @returns true if *this >= RHS when both are considered signed. + /// @brief Signed greather or equal comparison + template + INLINE bool sge(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return !slt(RHS); + } + + template + void cpTrunc(const ap_private<_AP_W1, _AP_S1, _AP_N1>& that) { + assert(_AP_W1 > BitWidth && "Invalid ap_private Truncate request"); + assert(_AP_W1 >= MIN_INT_BITS && "Can't truncate to 0 bits"); + memcpy(pVal, that.pVal, _AP_N*APINT_WORD_SIZE); + } + + // Sign extend to a new width. + template + void cpSext(const ap_private<_AP_W1, _AP_S1, _AP_N1>& that) { + assert(_AP_W1 < BitWidth && "Invalid ap_private SignExtend request"); + assert(_AP_W1 <= MAX_INT_BITS && "Too many bits"); + // If the sign bit isn't set, this is the same as zext. + if (!that.isNegative()) { + cpZext(that); + return; + } + + // The sign bit is set. First, get some facts + enum { wordBits = _AP_W1 % APINT_BITS_PER_WORD}; + + // Mask the high order word appropriately + if (_AP_N1 == _AP_N) { + enum { newWordBits = _AP_W % APINT_BITS_PER_WORD}; + // The extension is contained to the wordsBefore-1th word. + static const uint64_t mask = wordBits?(~0ULL<<(wordBits)):0ULL; + if (_AP_N1 == 1) { + assert(0); + } else { + for (uint32_t i = 0; i < _AP_N1; ++i) + pVal[i] = that.pVal[i]; + pVal[_AP_N1-1] |= mask; + return; + } + } + + if (_AP_N1 == 1) { + assert(0);// newVal[0] = VAL | mask; + } else { + enum { newWordBits = _AP_W % APINT_BITS_PER_WORD}; + // The extension is contained to the wordsBefore-1th word. + static const uint64_t mask = wordBits?(~0ULL<<(wordBits)):0ULL; + for (uint32_t i = 0; i < _AP_N1; ++i) + pVal[i] = that.pVal[i]; + pVal[_AP_N1-1] |= mask; + } + for (uint32_t i=_AP_N1; i < _AP_N-1; i++) + pVal[i] = ~0ULL; + pVal[_AP_N-1] = ~0ULL; + clearUnusedBits(); + return; + } + + // Zero extend to a new width. + template + void cpZext(const ap_private<_AP_W1, _AP_S1, _AP_N1>& that) { + assert(_AP_W1 < BitWidth && "Invalid ap_private ZeroExtend request"); + assert(_AP_W1 <= MAX_INT_BITS && "Too many bits"); + uint32_t wordsAfter = _AP_N; + if (wordsAfter==1) { + assert(0); // return ap_private<_AP_W1, _AP_S, _AP_N1> (_AP_W1, VAL, _AP_S); + } else { + if (_AP_N1 == 1) { + assert(0); + // newVal[0] = VAL; + } else { + uint32_t i = 0; + for (; i < _AP_N1; ++i) + pVal[i] = that.pVal[i]; + for (; i < _AP_N; ++i) + pVal[i] = 0; + } + } + clearUnusedBits(); + } + + template + void cpZextOrTrunc(const ap_private<_AP_W1, _AP_S1, _AP_N1>& that) { + if (BitWidth > _AP_W1) + cpZext(that); + else if (BitWidth < _AP_W1) + cpTrunc(that); + else { + for (int i=0; i<_AP_N1; ++i) + pVal[i]=that.pVal[i]; + clearUnusedBits(); + } + } + + template + void cpSextOrTrunc(const ap_private<_AP_W1, _AP_S1, _AP_N1>& that) { + if (BitWidth > _AP_W1) + cpSext(that); + else if (BitWidth < _AP_W1) + cpTrunc(that); + else { + for (int i=0; i<_AP_N1; ++i) + pVal[i] = that.pVal[i]; + clearUnusedBits(); + } + } + + /// @name Value Characterization Functions + /// @{ + + /// @returns the total number of bits. + INLINE uint32_t getBitWidth() const { + return BitWidth; + } + + /// Here one word's bitwidth equals to that of uint64_t. + /// @returns the number of words to hold the integer value of this ap_private. + /// @brief Get the number of words. + INLINE uint32_t getNumWords() const { + return (BitWidth + APINT_BITS_PER_WORD - 1) / APINT_BITS_PER_WORD; + } + + /// This function returns the number of active bits which is defined as the + /// bit width minus the number of leading zeros. This is used in several + /// computations to see how "wide" the value is. + /// @brief Compute the number of active bits in the value + INLINE uint32_t getActiveBits() const { + uint32_t bits=BitWidth - countLeadingZeros(); + return bits?bits:1; + } + + + /// This method attempts to return the value of this ap_private as a zero extended + /// uint64_t. The bitwidth must be <= 64 or the value must fit within a + /// uint64_t. Otherwise an assertion will result. + /// @brief Get zero extended value + INLINE uint64_t getZExtValue() const { + assert(getActiveBits() <= 64 && "Too many bits for uint64_t"); + return *pVal; + } + + /// This method attempts to return the value of this ap_private as a sign extended + /// int64_t. The bit width must be <= 64 or the value must fit within an + /// int64_t. Otherwise an assertion will result. + /// @brief Get sign extended value + INLINE int64_t getSExtValue() const { + assert(getActiveBits() <= 64 && "Too many bits for int64_t"); + return int64_t(pVal[0]); + } + + /// This method determines how many bits are required to hold the ap_private + /// equivalent of the string given by \p str of length \p slen. + /// @brief Get bits required for string value. + static uint32_t getBitsNeeded(const char* str, uint32_t slen, uint8_t radix); + + /// countLeadingZeros - This function is an ap_private version of the + /// countLeadingZeros_{32,64} functions in MathExtras.h. It counts the number + /// of zeros from the most significant bit to the first one bit. + /// @returns BitWidth if the value is zero. + /// @returns the number of zeros from the most significant bit to the first + /// one bits. + INLINE uint32_t countLeadingZeros() const ; + + /// countLeadingOnes - This function counts the number of contiguous 1 bits + /// in the high order bits. The count stops when the first 0 bit is reached. + /// @returns 0 if the high order bit is not set + /// @returns the number of 1 bits from the most significant to the least + /// @brief Count the number of leading one bits. + INLINE uint32_t countLeadingOnes() const ; + + /// countTrailingZeros - This function is an ap_private version of the + /// countTrailingZoers_{32,64} functions in MathExtras.h. It counts + /// the number of zeros from the least significant bit to the first set bit. + /// @returns BitWidth if the value is zero. + /// @returns the number of zeros from the least significant bit to the first + /// one bit. + /// @brief Count the number of trailing zero bits. + INLINE uint32_t countTrailingZeros() const ; + + /// countPopulation - This function is an ap_private version of the + /// countPopulation_{32,64} functions in MathExtras.h. It counts the number + /// of 1 bits in the ap_private value. + /// @returns 0 if the value is zero. + /// @returns the number of set bits. + /// @brief Count the number of bits set. + INLINE uint32_t countPopulation() const { + uint32_t Count = 0; + for (uint32_t i = 0; i<_AP_N-1 ; ++i) + Count += CountPopulation_64(pVal[i]); + Count += CountPopulation_64(pVal[_AP_N-1]&mask); + return Count; + } + + /// @} + /// @name Conversion Functions + /// @{ + + /// This is used internally to convert an ap_private to a string. + /// @brief Converts an ap_private to a std::string + INLINE std::string toString(uint8_t radix, bool wantSigned) const + ; + + /// Considers the ap_private to be unsigned and converts it into a string in the + /// radix given. The radix can be 2, 8, 10 or 16. + /// @returns a character interpretation of the ap_private + /// @brief Convert unsigned ap_private to string representation. + INLINE std::string toStringUnsigned(uint8_t radix = 10) const { + return toString(radix, false); + } + + /// Considers the ap_private to be unsigned and converts it into a string in the + /// radix given. The radix can be 2, 8, 10 or 16. + /// @returns a character interpretation of the ap_private + /// @brief Convert unsigned ap_private to string representation. + INLINE std::string toStringSigned(uint8_t radix = 10) const { + return toString(radix, true); + } + + /// @returns a byte-swapped representation of this ap_private Value. + INLINE ap_private byteSwap() const ; + + /// @brief Converts this ap_private to a double value. + INLINE double roundToDouble(bool isSigned) const ; + + /// @brief Converts this unsigned ap_private to a double value. + INLINE double roundToDouble() const { + return roundToDouble(false); + } + + /// @brief Converts this signed ap_private to a double value. + INLINE double signedRoundToDouble() const { + return roundToDouble(true); + } + + /// The conversion does not do a translation from integer to double, it just + /// re-interprets the bits as a double. Note that it is valid to do this on + /// any bit width. Exactly 64 bits will be translated. + /// @brief Converts ap_private bits to a double + INLINE double bitsToDouble() const { + union { + uint64_t __I; + double __D; + } __T; + __T.__I = pVal[0]; + return __T.__D; + } + + /// The conversion does not do a translation from integer to float, it just + /// re-interprets the bits as a float. Note that it is valid to do this on + /// any bit width. Exactly 32 bits will be translated. + /// @brief Converts ap_private bits to a double + INLINE float bitsToFloat() const { + union { + uint32_t __I; + float __F; + } __T; + __T.__I = uint32_t(pVal[0]); + return __T.__F; + } + + /// The conversion does not do a translation from double to integer, it just + /// re-interprets the bits of the double. Note that it is valid to do this on + /// any bit width but bits from V may get truncated. + /// @brief Converts a double to ap_private bits. + INLINE ap_private& doubleToBits(double __V) { + union { + uint64_t __I; + double __D; + } __T; + __T.__D = __V; + pVal[0] = __T.__I; + return *this; + } + + /// The conversion does not do a translation from float to integer, it just + /// re-interprets the bits of the float. Note that it is valid to do this on + /// any bit width but bits from V may get truncated. + /// @brief Converts a float to ap_private bits. + INLINE ap_private& floatToBits(float __V) { + union { + uint32_t __I; + float __F; + } __T; + __T.__F = __V; + pVal[0] = __T.__I; + } + + //Reduce operation + //----------------------------------------------------------- + INLINE bool and_reduce() const { + return isMaxValue(); + } + + INLINE bool nand_reduce() const { + return isMinValue(); + } + + INLINE bool or_reduce() const { + return (bool)countPopulation(); + } + + INLINE bool nor_reduce() const { + return countPopulation()==0; + } + + INLINE bool xor_reduce() const { + unsigned int i=countPopulation(); + return (i%2)?true:false; + } + + INLINE bool xnor_reduce() const { + unsigned int i=countPopulation(); + return (i%2)?false:true; + } + INLINE std::string to_string(uint8_t radix=16, bool sign=false) const { + return toString(radix, radix==10?_AP_S:sign); + } +}; + +template +INLINE bool operator==(uint64_t V1, const ap_private<_AP_W, _AP_S, _AP_N>& V2) { + return V2 == V1; +} + +template +INLINE bool operator!=(uint64_t V1, const ap_private<_AP_W, _AP_S, _AP_N>& V2) { + return V2 != V1; +} + +namespace ap_private_ops { + enum {APINT_BITS_PER_WORD=64}; + /// @brief Determine the smaller of two ap_privates considered to be signed. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> smin(const ap_private<_AP_W, _AP_S, _AP_N> &LHS, const ap_private<_AP_W, _AP_S1, _AP_N> &RHS) { + return LHS.slt(RHS) ? LHS : RHS; + } + + /// @brief Determine the larger of two ap_privates considered to be signed. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> smax(const ap_private<_AP_W, _AP_S, _AP_N> &LHS, const ap_private<_AP_W, _AP_S1, _AP_N> &RHS) { + return LHS.sgt(RHS) ? LHS : RHS; + } + + /// @brief Determine the smaller of two ap_privates considered to be signed. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> umin(const ap_private<_AP_W, _AP_S, _AP_N> &LHS, const ap_private<_AP_W, _AP_S1, _AP_N> &RHS) { + return LHS.ult(RHS) ? LHS : RHS; + } + + /// @brief Determine the larger of two ap_privates considered to be unsigned. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> umax(const ap_private<_AP_W, _AP_S, _AP_N> &LHS, const ap_private<_AP_W, _AP_S1, _AP_N> &RHS) { + return LHS.ugt(RHS) ? LHS : RHS; + } + + /// @brief Check if the specified ap_private has a N-bits integer value. + template + INLINE bool isIntN(uint32_t __N, const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.isIntN(__N); + } + + /// @returns true if the argument ap_private value is a sequence of ones + /// starting at the least significant bit with the remainder zero. + template + INLINE bool isMask(uint32_t numBits, const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.getBoolValue() && ((APIVal + ap_private<_AP_W, _AP_S, _AP_N>(numBits,1)) & APIVal) == 0; + } + + /// @returns true if the argument ap_private value contains a sequence of ones + /// with the remainder zero. + template + INLINE bool isShiftedMask(uint32_t numBits, const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return isMask(numBits, (APIVal - ap_private<_AP_W, _AP_S, _AP_N>(numBits,1)) | APIVal); + } + + /// @returns a byte-swapped representation of the specified ap_private Value. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> byteSwap(const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.byteSwap(); + } + + /// @returns the floor log base 2 of the specified ap_private value. + template INLINE uint32_t logBase2(const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.logBase2(); + } + + /// GreatestCommonDivisor - This function returns the greatest common + /// divisor of the two ap_private values using Enclid's algorithm. + /// @returns the greatest common divisor of Val1 and Val2 + /// @brief Compute GCD of two ap_private values. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> GreatestCommonDivisor(const ap_private<_AP_W, _AP_S, _AP_N>& Val1, const ap_private<_AP_W, _AP_S, _AP_N>& Val2) + ; + + /// Treats the ap_private as an unsigned value for conversion purposes. + /// @brief Converts the given ap_private to a double value. + template INLINE double Roundap_privateToDouble(const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.roundToDouble(); + } + + /// Treats the ap_private as a signed value for conversion purposes. + /// @brief Converts the given ap_private to a double value. + template INLINE double RoundSignedap_privateToDouble(const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.signedRoundToDouble(); + } + + /// @brief Converts the given ap_private to a float vlalue. + template INLINE float Roundap_privateToFloat(const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return float(Roundap_privateToDouble(APIVal)); + } + + /// Treast the ap_private as a signed value for conversion purposes. + /// @brief Converts the given ap_private to a float value. + template INLINE float RoundSignedap_privateToFloat(const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return float(APIVal.signedRoundToDouble()); + } + + /// RoundDoubleToap_private - This function convert a double value to an ap_private value. + /// @brief Converts the given double value into a ap_private. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> RoundDoubleToap_private(double Double, uint32_t width) ; + + /// RoundFloatToap_private - Converts a float value into an ap_private value. + /// @brief Converts a float value into a ap_private. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> RoundFloatToap_private(float Float, uint32_t width) { + return RoundDoubleToap_private<_AP_W, _AP_S, _AP_N>(double(Float), width); + } + + /// Arithmetic right-shift the ap_private by shiftAmt. + /// @brief Arithmetic right-shift function. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> ashr(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, uint32_t shiftAmt) { + return LHS.ashr(shiftAmt); + } + + /// Logical right-shift the ap_private by shiftAmt. + /// @brief Logical right-shift function. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> lshr(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, uint32_t shiftAmt) { + return LHS.lshr(shiftAmt); + } + + /// Left-shift the ap_private by shiftAmt. + /// @brief Left-shift function. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> shl(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, uint32_t shiftAmt) { + return LHS.shl(shiftAmt); + } + + /// Signed divide ap_private LHS by ap_private RHS. + /// @brief Signed division function for ap_private. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> sdiv(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS.sdiv(RHS); + } + + /// Unsigned divide ap_private LHS by ap_private RHS. + /// @brief Unsigned division function for ap_private. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> udiv(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS.udiv(RHS); + } + + /// Signed remainder operation on ap_private. + /// @brief Function for signed remainder operation. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> srem(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS.srem(RHS); + } + + /// Unsigned remainder operation on ap_private. + /// @brief Function for unsigned remainder operation. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> urem(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS.urem(RHS); + } + + /// Performs multiplication on ap_private values. + /// @brief Function for multiplication operation. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> mul(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS * RHS; + } + + /// Performs addition on ap_private values. + /// @brief Function for addition operation. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> add(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS + RHS; + } + + /// Performs subtraction on ap_private values. + /// @brief Function for subtraction operation. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> sub(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS - RHS; + } + + /// Performs bitwise AND operation on ap_private LHS and + /// ap_private RHS. + /// @brief Bitwise AND function for ap_private. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> And(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS & RHS; + } + + /// Performs bitwise OR operation on ap_private LHS and ap_private RHS. + /// @brief Bitwise OR function for ap_private. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> Or(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS | RHS; + } + + /// Performs bitwise XOR operation on ap_private. + /// @brief Bitwise XOR function for ap_private. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> Xor(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS ^ RHS; + } + + /// Performs a bitwise complement operation on ap_private. + /// @brief Bitwise complement function. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> Not(const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return ~APIVal; + } + + template void clearUnusedBits(uint64_t& msw) { + // Compute how many bits are used in the final word + // uint32_t wordBits = APIVal.getBitWidth() & 0x3f; + if (wordBits == 0) + // If all bits are used, we want to leave the value alone. This also + // avoids the undefined behavior of >> when the shfit is the same size as + // the word size (64). + return; + + // Mask out the hight bits. + uint64_t mask = ~uint64_t(0ULL) >> (64 /*ap_private::APINT_BITS_PER_WORD */- wordBits); + msw &= mask; + } + template <> INLINE void clearUnusedBits<1>(uint64_t& msw) { + uint64_t mask = ~uint64_t(0ULL) >> (64 /*ap_private::APINT_BITS_PER_WORD */- 1); + msw &= mask; + } + template void clearUnusedBits(int64_t& msw) { + // Compute how many bits are used in the final word + // uint32_t wordBits = APIVal.getBitWidth() & 0x3f; + if (wordBits == 0) + // If all bits are used, we want to leave the value alone. This also + // avoids the undefined behavior of >> when the shfit is the same size as + // the word size (64). + return; + + // Mask out the hight bits. + uint64_t mask = ~uint64_t(0ULL) >> (64 /*ap_private::APINT_BITS_PER_WORD */- wordBits); + msw &= mask; + } + template <> INLINE void clearUnusedBits<1>(int64_t& msw) { + uint64_t mask = ~uint64_t(0ULL) >> (64 /*ap_private::APINT_BITS_PER_WORD */- 1); + msw &= mask; + } + // template + template + INLINE ap_private<_AP_W, _AP_S> ashr(const ap_private<_AP_W, _AP_S>& a) { + return ashr(a, shiftAmt); + } + + template + INLINE ap_private<_AP_W, _AP_S> lshr(const ap_private<_AP_W, _AP_S>& a) { + return lshr(a, shiftAmt); + } + + template + INLINE ap_private<_AP_W, true> ashr(const ap_private<_AP_W, true, 1>& a) { + enum {APINT_BITS_PER_WORD=64, excess_bits=APINT_BITS_PER_WORD-_AP_W}; + static const uint64_t sign_bit = (1ULL<<(_AP_W-1)); + static const uint64_t sign_ext_mask = (_AP_W-shiftAmt>0)?~0ULL<<(APINT_BITS_PER_WORD-_AP_W+shiftAmt):~0ULL; + return ap_private<_AP_W, true>((((int64_t)a.VAL) >> (shiftAmt)) | (a.VAL & sign_bit? sign_ext_mask : 0ULL)); + } + + template + INLINE ap_private<_AP_W, false> ashr(const ap_private<_AP_W, false, 1>& a) { + return ap_private<_AP_W, false>((a.VAL) >> (shiftAmt)); + } + + template + INLINE ap_private<_AP_W, _AP_S> lshr(const ap_private<_AP_W, _AP_S, 1>& a) { + static const uint64_t mask = ~0ULL<<_AP_W; + return ap_private<_AP_W, _AP_S>((a.VAL&mask) >> (shiftAmt)); + } + + template + INLINE ap_private<_AP_W-shiftAmt, _AP_S> shr(const ap_private<_AP_W, _AP_S>& a) { + return ap_private<_AP_W-shiftAmt, _AP_S>((a.VAL) >> (shiftAmt)); + } + + template + INLINE ap_private<_AP_W+shiftAmt, _AP_S> shl(const ap_private<_AP_W, _AP_S>& a) { + return ap_private<_AP_W+shiftAmt, _AP_S>((a.VAL) << (shiftAmt)); + } + + template + INLINE bool get(const ap_private<_AP_W, _AP_S, 1>& a) { + unsigned shift = (index%APINT_BITS_PER_WORD); + static const uint64_t mask=1ULL << (shift); + return ((mask & a.VAL) != 0); + } + + template + INLINE bool get(const ap_private<_AP_W, _AP_S>& a) { + static const uint64_t mask=1ULL << (index&0x3f); + return ((mask & a.pVal[(index)>>6]) != 0); + } + + template + INLINE void set(ap_private<_AP_W, _AP_S, 1>& a) { + const uint64_t mask = ~0ULL >> (lsb) << (APINT_BITS_PER_WORD-msb+lsb-1)>>(APINT_BITS_PER_WORD-msb-1); + a.VAL |= mask; + } + + template + INLINE void clear(ap_private<_AP_W, _AP_S, 1>& a) { + static const uint64_t mask = ~(~0ULL >> (lsb) <<(APINT_BITS_PER_WORD-msb+lsb-1) >> (APINT_BITS_PER_WORD-msb-1)); + a.VAL &= mask; + } + + template + INLINE void set(ap_private<_AP_W, _AP_S>& a) { + enum { APINT_BITS_PER_WORD=64, + lsb_word = lsb_index /APINT_BITS_PER_WORD, + msb_word = msb_index / APINT_BITS_PER_WORD, + msb = msb_index % APINT_BITS_PER_WORD, + lsb=lsb_index % APINT_BITS_PER_WORD}; + if (msb_word==lsb_word) { + const uint64_t mask = ~0ULL >> (lsb) << (APINT_BITS_PER_WORD-msb+lsb-1)>>(APINT_BITS_PER_WORD-msb-1); + a.pVal[msb_word] |= mask; + } else { + const uint64_t lsb_mask = ~0ULL >> (lsb) << (lsb); + const uint64_t msb_mask = ~0ULL << (APINT_BITS_PER_WORD-msb-1)>>(APINT_BITS_PER_WORD-msb-1); + a.pVal[lsb_word] |=lsb_mask; + for (int i=lsb_word+1; i + INLINE void clear(ap_private<_AP_W, _AP_S>& a) { + enum { APINT_BITS_PER_WORD=64, + lsb_word = lsb_index /APINT_BITS_PER_WORD, + msb_word = msb_index / APINT_BITS_PER_WORD, + msb = msb_index % APINT_BITS_PER_WORD, + lsb=lsb_index % APINT_BITS_PER_WORD}; + if (msb_word == lsb_word) { + const uint64_t mask = ~(~0ULL >> (lsb) << (APINT_BITS_PER_WORD-msb+lsb-1)>>(APINT_BITS_PER_WORD-msb-1)); + a.pVal[msb_word] &= mask; + } else { + const uint64_t lsb_mask = ~(~0ULL >> (lsb) << (lsb)); + const uint64_t msb_mask = ~(~0ULL << (APINT_BITS_PER_WORD-msb-1)>>(APINT_BITS_PER_WORD-msb-1)); + a.pVal[lsb_word] &=lsb_mask; + for (int i=lsb_word+1; i + INLINE void set(ap_private<_AP_W, _AP_S, 1>& a) { + static const uint64_t mask=1ULL << (index); + a.VAL |= mask; + a.clearUnusedBits(); + } + + template + INLINE void clear(ap_private<_AP_W, _AP_S, 1>& a) { + static const uint64_t mask=~(1ULL << (index)); + a.VAL &= mask; + a.clearUnusedBits(); + } + + template + INLINE void set(ap_private<_AP_W, _AP_S>& a) { + enum { APINT_BITS_PER_WORD=64, word = index/APINT_BITS_PER_WORD}; + static const uint64_t mask=1ULL << (index%APINT_BITS_PER_WORD); + a.pVal[word] |= mask; + a.clearUnusedBits(); + } + + template + INLINE void clear(ap_private<_AP_W, _AP_S>& a) { + enum { APINT_BITS_PER_WORD=64, word = index/APINT_BITS_PER_WORD}; + static const uint64_t mask=~(1ULL << (index%APINT_BITS_PER_WORD)); + a.pVal[word] &= mask; + a.clearUnusedBits(); + } + + template + INLINE bool isNegative(const ap_private<_AP_W, false>& a) { + return false; + } + + template + INLINE bool isNegative(const ap_private<_AP_W, true, 1>& a) { + static const uint64_t sign_mask = (1ULL << (_AP_W-1)); + return ((sign_mask & a.VAL) != 0); + } + + template + INLINE bool isNegative(const ap_private<_AP_W, true>& a) { + enum {APINT_BITS_PER_WORD=64,_AP_N=(_AP_W+APINT_BITS_PER_WORD-1)/APINT_BITS_PER_WORD}; + static const uint64_t sign_mask = (1ULL << (_AP_W%APINT_BITS_PER_WORD-1)); + return sign_mask & a.pVal[_AP_N-1]; + } +} // End of ap_private_ops namespace + +/// @brief Check if the specified ap_private has a N-bits integer value. +template +INLINE bool isIntN(uint32_t __N, const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.isIntN(__N); +} + +/// @returns true if the argument ap_private value is a sequence of ones +/// starting at the least significant bit with the remainder zero. +template +INLINE bool isMask(uint32_t numBits, const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.getBoolValue() && ((APIVal + ap_private<_AP_W, _AP_S, _AP_N>(numBits,1)) & APIVal) == 0; +} + +/// @returns true if the argument ap_private value contains a sequence of ones +/// with the remainder zero. +template +INLINE bool isShiftedMask(uint32_t numBits, const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return isMask(numBits, (APIVal - ap_private<_AP_W, _AP_S, _AP_N>(numBits,1)) | APIVal); +} + +#if 0 +/// add_1 - This function adds a single "digit" integer, y, to the multiple +/// "digit" integer array, x[]. x[] is modified to reflect the addition and +/// 1 is returned if there is a carry out, otherwise 0 is returned. +/// @returns the carry of the addition. +static bool add_1(uint64_t dest[], uint64_t x[], uint32_t len, uint64_t y) { + for (uint32_t i = 0; i < len; ++i) { + dest[i] = y + x[i]; + if (dest[i] < y) + y = 1; // Carry one to next digit. + else { + y = 0; // No need to carry so exit early + break; + } + } + return (y != 0); +} +#endif + +#if 0 +/// add - This function adds the integer array x to the integer array Y and +/// places the result in dest. +/// @returns the carry out from the addition +/// @brief General addition of 64-bit integer arrays +static bool add(uint64_t *dest, const uint64_t *x, const uint64_t *y, + uint32_t destlen, uint32_t xlen, uint32_t ylen, bool xsigned, bool ysigned) { + bool carry = false; + uint32_t len = AESL_std::min(xlen, ylen); + uint32_t i; + for (i = 0; i< len && i < destlen; ++i) { + uint64_t limit = AESL_std::min(x[i],y[i]); // must come first in case dest == x + dest[i] = x[i] + y[i] + carry; + carry = dest[i] < limit || (carry && dest[i] == limit); + } + if (xlen > ylen) { + const uint64_t yext = xsigned && int64_t(y[ylen-1])<0 ? -1 : 0; + for (i=ylen; i< xlen && i < destlen; i++) { + uint64_t limit = AESL_std::min(x[i], yext); + dest[i] = x[i] + yext + carry; + carry = (dest[i] < limit)||(carry && dest[i] == x[i]); + } + } else if (ylen> xlen) { + const uint64_t xext = ysigned && int64_t(x[xlen-1])<0 ? -1 : 0; + for (i=xlen; i< ylen && i < destlen; i++) { + uint64_t limit = AESL_std::min(xext, y[i]); + dest[i] = xext + y[i] + carry; + carry = (dest[i] < limit)||(carry && dest[i] == y[i]); + } + } + return carry; +} +#endif + +#if 0 +/// @returns returns the borrow out. +/// @brief Generalized subtraction of 64-bit integer arrays. +static bool sub(uint64_t *dest, const uint64_t *x, const uint64_t *y, + uint32_t destlen, uint32_t xlen, uint32_t ylen, bool xsigned, bool ysigned) { + bool borrow = false; + uint32_t i; + uint32_t len = AESL_std::min(xlen, ylen); + for (i = 0; i < len && i < destlen; ++i) { + uint64_t x_tmp = borrow ? x[i] - 1 : x[i]; + borrow = y[i] > x_tmp || (borrow && x[i] == 0); + dest[i] = x_tmp - y[i]; + } + if (xlen > ylen) { + const uint64_t yext = ysigned && int64_t(y[ylen-1])<0 ? -1 : 0; + for (i=ylen; i< xlen && i < destlen; i++) { + uint64_t x_tmp = borrow ? x[i] - 1 : x[i]; + borrow = yext > x_tmp || (borrow && x[i] == 0); + dest[i] = x_tmp - yext; + } + } else if (ylen> xlen) { + const uint64_t xext = xsigned && int64_t(x[xlen-1])<0 ? -1 : 0; + for (i=xlen; i< ylen && i < destlen; i++) { + uint64_t x_tmp = borrow ? xext - 1 : xext; + borrow = y[i] > x_tmp || (borrow && xext==0); + dest[i] = x_tmp - y[i]; + } + } + return borrow; +} +#endif + +/// Subtracts the RHS ap_private from this ap_private +/// @returns this, after subtraction +/// @brief Subtraction assignment operator. + +#if 0 +/// Multiplies an integer array, x by a a uint64_t integer and places the result +/// into dest. +/// @returns the carry out of the multiplication. +/// @brief Multiply a multi-digit ap_private by a single digit (64-bit) integer. +static uint64_t mul_1(uint64_t dest[], const uint64_t x[], uint32_t len, uint64_t y) { + // Split y into high 32-bit part (hy) and low 32-bit part (ly) + uint64_t ly = y & 0xffffffffULL, hy = (y) >> 32; + uint64_t carry = 0; + static const uint64_t two_power_32 = 1ULL << 32; + // For each digit of x. + for (uint32_t i = 0; i < len; ++i) { + // Split x into high and low words + uint64_t lx = x[i] & 0xffffffffULL; + uint64_t hx = (x[i]) >> 32; + // hasCarry - A flag to indicate if there is a carry to the next digit. + // hasCarry == 0, no carry + // hasCarry == 1, has carry + // hasCarry == 2, no carry and the calculation result == 0. + uint8_t hasCarry = 0; + dest[i] = carry + lx * ly; + // Determine if the add above introduces carry. + hasCarry = (dest[i] < carry) ? 1 : 0; + carry = hx * ly + ((dest[i]) >> 32) + (hasCarry ? two_power_32 : 0); + // The upper limit of carry can be (2^32 - 1)(2^32 - 1) + + // (2^32 - 1) + 2^32 = 2^64. + hasCarry = (!carry && hasCarry) ? 1 : (!carry ? 2 : 0); + + carry += (lx * hy) & 0xffffffffULL; + dest[i] = ((carry) << 32) | (dest[i] & 0xffffffffULL); + carry = (((!carry && hasCarry != 2) || hasCarry == 1) ? two_power_32 : 0) + + ((carry) >> 32) + ((lx * hy) >> 32) + hx * hy; + } + return carry; +} +#endif + +#if 0 +/// Multiplies integer array x by integer array y and stores the result into +/// the integer array dest. Note that dest's size must be >= xlen + ylen. +/// @brief Generalized multiplicate of integer arrays. +static void mul(uint64_t dest[], const uint64_t x[], uint32_t xlen, const uint64_t y[], + uint32_t ylen, uint32_t destlen) { + dest[xlen] = mul_1(dest, x, xlen, y[0]); + for (uint32_t i = 1; i < ylen; ++i) { + uint64_t ly = y[i] & 0xffffffffULL, hy = (y[i]) >> 32; + uint64_t carry = 0, lx = 0, hx = 0; + for (uint32_t j = 0; j < xlen; ++j) { + lx = x[j] & 0xffffffffULL; + hx = (x[j]) >> 32; + // hasCarry - A flag to indicate if has carry. + // hasCarry == 0, no carry + // hasCarry == 1, has carry + // hasCarry == 2, no carry and the calculation result == 0. + uint8_t hasCarry = 0; + uint64_t resul = carry + lx * ly; + hasCarry = (resul < carry) ? 1 : 0; + carry = (hasCarry ? (1ULL << 32) : 0) + hx * ly + ((resul) >> 32); + hasCarry = (!carry && hasCarry) ? 1 : (!carry ? 2 : 0); + carry += (lx * hy) & 0xffffffffULL; + resul = ((carry) << 32) | (resul & 0xffffffffULL); + dest[i+j] += resul; + carry = (((!carry && hasCarry != 2) || hasCarry == 1) ? (1ULL << 32) : 0)+ + ((carry) >> 32) + (dest[i+j] < resul ? 1 : 0) + + ((lx * hy) >> 32) + hx * hy; + } + dest[i+xlen] = carry; + } +} +#endif + + + +template +uint32_t ap_private<_AP_W, _AP_S, _AP_N>::getBitsNeeded(const char* str, uint32_t slen, uint8_t radix) { + assert(str != 0 && "Invalid value string"); + assert(slen > 0 && "Invalid string length"); + + // Each computation below needs to know if its negative + uint32_t isNegative = str[0] == '-'; + if (isNegative) { + slen--; + str++; + } + // For radixes of power-of-two values, the bits required is accurately and + // easily computed + if (radix == 2) + return slen + isNegative; + if (radix == 8) + return slen * 3 + isNegative; + if (radix == 16) + return slen * 4 + isNegative; + + // Otherwise it must be radix == 10, the hard case + assert(radix == 10 && "Invalid radix"); + + // Convert to the actual binary value. + //ap_private<_AP_W, _AP_S, _AP_N> tmp(sufficient, str, slen, radix); + + // Compute how many bits are required. + //return isNegative + tmp.logBase2() + 1; + return isNegative + slen * 4; +} + +template +uint32_t ap_private<_AP_W, _AP_S, _AP_N>::countLeadingZeros() const { + enum { msw_bits = (BitWidth % APINT_BITS_PER_WORD)?(BitWidth % APINT_BITS_PER_WORD):APINT_BITS_PER_WORD, + excessBits = APINT_BITS_PER_WORD - msw_bits }; + uint32_t Count = CountLeadingZeros_64(pVal[_AP_N-1]); + if (Count>=excessBits) + Count -= excessBits; + if (!pVal[_AP_N-1]) { + for (uint32_t i = _AP_N-1 ; i ; --i) { + if (!pVal[i-1]) + Count += APINT_BITS_PER_WORD; + else { + Count += CountLeadingZeros_64(pVal[i-1]); + break; + } + } + } + return Count; +} + +static uint32_t countLeadingOnes_64(uint64_t __V, uint32_t skip) { + uint32_t Count = 0; + if (skip) + (__V) <<= (skip); + while (__V && (__V & (1ULL << 63))) { + Count++; + (__V) <<= 1; + } + return Count; +} + +template +uint32_t ap_private<_AP_W, _AP_S, _AP_N>::countLeadingOnes() const { + if (isSingleWord()) + return countLeadingOnes_64(VAL, APINT_BITS_PER_WORD - BitWidth); + + uint32_t highWordBits = BitWidth % APINT_BITS_PER_WORD; + uint32_t shift = (highWordBits == 0 ? 0 : APINT_BITS_PER_WORD - highWordBits); + int i = _AP_N - 1; + uint32_t Count = countLeadingOnes_64(pVal[i], shift); + if (Count == highWordBits) { + for (i--; i >= 0; --i) { + if (pVal[i] == ~0ULL) + Count += APINT_BITS_PER_WORD; + else { + Count += countLeadingOnes_64(pVal[i], 0); + break; + } + } + } + return Count; +} + +template +INLINE uint32_t ap_private<_AP_W, _AP_S, _AP_N>::countTrailingZeros() const { + if (isSingleWord()) + return AESL_std::min(uint32_t(CountTrailingZeros_64(VAL)), BitWidth); + uint32_t Count = 0; + uint32_t i = 0; + for (; i < _AP_N && pVal[i] == 0; ++i) + Count += APINT_BITS_PER_WORD; + if (i < _AP_N) + Count += CountTrailingZeros_64(pVal[i]); + return AESL_std::min(Count, BitWidth); +} + +template +ap_private<_AP_W, _AP_S, _AP_N> ap_private<_AP_W, _AP_S, _AP_N>::byteSwap() const { + assert(BitWidth >= 16 && BitWidth % 16 == 0 && "Cannot byteswap!"); + if (BitWidth == 16) + return ap_private<_AP_W, _AP_S, _AP_N>(/*BitWidth,*/ ByteSwap_16(uint16_t(VAL))); + else if (BitWidth == 32) + return ap_private<_AP_W, _AP_S, _AP_N>(/*BitWidth,*/ ByteSwap_32(uint32_t(VAL))); + else if (BitWidth == 48) { + uint32_t Tmp1 = uint32_t((VAL) >> 16); + Tmp1 = ByteSwap_32(Tmp1); + uint16_t Tmp2 = uint16_t(VAL); + Tmp2 = ByteSwap_16(Tmp2); + return ap_private<_AP_W, _AP_S, _AP_N>(/*BitWidth,*/ ((uint64_t(Tmp2)) << 32) | Tmp1); + } else if (BitWidth == 64) + return ap_private<_AP_W, _AP_S, _AP_N>(/*BitWidth,*/ ByteSwap_64(VAL)); + else { + ap_private<_AP_W, _AP_S, _AP_N> Result(0); + char *pByte = (char*)Result.pVal; + for (uint32_t i = 0; i < BitWidth / APINT_WORD_SIZE / 2; ++i) { + char Tmp = pByte[i]; + pByte[i] = pByte[BitWidth / APINT_WORD_SIZE - 1 - i]; + pByte[BitWidth / APINT_WORD_SIZE - i - 1] = Tmp; + } + return Result; + } +} + +template +ap_private<_AP_W, _AP_S, _AP_N> ap_private_ops::GreatestCommonDivisor(const ap_private<_AP_W, _AP_S, _AP_N>& API1, const ap_private<_AP_W, _AP_S, _AP_N>& API2) { + ap_private<_AP_W, _AP_S, _AP_N> __A = API1, __B = API2; + while (!!__B) { + ap_private<_AP_W, _AP_S, _AP_N> __T = __B; + __B = ap_private_ops::urem(__A, __B); + __A = __T; + } + return __A; +} + +template +ap_private<_AP_W, _AP_S, _AP_N> ap_private_ops::RoundDoubleToap_private(double Double, uint32_t width) { + union { + double __D; + uint64_t __I; + } __T; + __T.__D = Double; + + // Get the sign bit from the highest order bit + bool isNeg = (__T.__I) >> 63; + + // Get the 11-bit exponent and adjust for the 1023 bit bias + int64_t exp = (((__T.__I) >> 52) & 0x7ffULL) - 1023; + + // If the exponent is negative, the value is < 0 so just return 0. + if (exp < 0) + return ap_private<_AP_W, _AP_S, _AP_N>(width, 0u); + + // Extract the mantissa by clearing the top 12 bits (sign + exponent). + uint64_t mantissa = (__T.__I & (~0ULL >> 12)) | 1ULL << 52; + + // If the exponent doesn't shift all bits out of the mantissa + if (exp < 52) + return isNeg ? -ap_private<_AP_W, _AP_S, _AP_N>(width, (mantissa) >> (52 - exp)) : + ap_private<_AP_W, _AP_S, _AP_N>((mantissa) >> (52 - exp)); + + // If the client didn't provide enough bits for us to shift the mantissa into + // then the result is undefined, just return 0 + if (width <= exp - 52) + return ap_private<_AP_W, _AP_S, _AP_N>(width, 0); + + // Otherwise, we have to shift the mantissa bits up to the right location + ap_private<_AP_W, _AP_S, _AP_N> Tmp(width, mantissa); + Tmp = Tmp.shl(exp - 52); + return isNeg ? -Tmp : Tmp; +} + +/// RoundToDouble - This function convert this ap_private to a double. +/// The layout for double is as following (IEEE Standard 754): +/// -------------------------------------- +/// | Sign Exponent Fraction Bias | +/// |-------------------------------------- | +/// | 1[63] 11[62-52] 52[51-00] 1023 | +/// -------------------------------------- +template +double ap_private<_AP_W, _AP_S, _AP_N>::roundToDouble(bool isSigned) const { + + // Handle the simple case where the value is contained in one uint64_t. + if (isSingleWord() || getActiveBits() <= APINT_BITS_PER_WORD) { + uint64_t val; + if (isSingleWord()) val = VAL; + else val = pVal[0]; + if (isSigned) { + int64_t sext = ((int64_t(val)) << (64-BitWidth)) >> (64-BitWidth); + return double(sext); + } else + return double(val); + } + + // Determine if the value is negative. + bool isNeg = isSigned ? (*this)[BitWidth-1] : false; + + // Construct the absolute value if we're negative. + ap_private<_AP_W, _AP_S, _AP_N> Tmp(isNeg ? -(*this) : (*this)); + + // Figure out how many bits we're using. + uint32_t n = Tmp.getActiveBits(); + + // The exponent (without bias normalization) is just the number of bits + // we are using. Note that the sign bit is gone since we constructed the + // absolute value. + uint64_t exp = n; + + // Return infinity for exponent overflow + if (exp > 1023) { + if (!isSigned || !isNeg) + return std::numeric_limits::infinity(); + else + return -std::numeric_limits::infinity(); + } + exp += 1023; // Increment for 1023 bias + + // Number of bits in mantissa is 52. To obtain the mantissa value, we must + // extract the high 52 bits from the correct words in pVal. + uint64_t mantissa; + unsigned hiWord = whichWord(n-1); + if (hiWord == 0) { + mantissa = Tmp.pVal[0]; + if (n > 52) + (mantissa) >>= (n - 52); // shift down, we want the top 52 bits. + } else { + assert(hiWord > 0 && "High word is negative?"); + uint64_t hibits = (Tmp.pVal[hiWord]) << (52 - n % APINT_BITS_PER_WORD); + uint64_t lobits = (Tmp.pVal[hiWord-1]) >> (11 + n % APINT_BITS_PER_WORD); + mantissa = hibits | lobits; + } + + // The leading bit of mantissa is implicit, so get rid of it. + uint64_t sign = isNeg ? (1ULL << (APINT_BITS_PER_WORD - 1)) : 0; + union { + double __D; + uint64_t __I; + } __T; + __T.__I = sign | ((exp) << 52) | mantissa; + return __T.__D; +} + +// Square Root - this method computes and returns the square root of "this". +// Three mechanisms are used for computation. For small values (<= 5 bits), +// a table lookup is done. This gets some performance for common cases. For +// values using less than 52 bits, the value is converted to double and then +// the libc sqrt function is called. The result is rounded and then converted +// back to a uint64_t which is then used to construct the result. Finally, +// the Babylonian method for computing square roots is used. +template +ap_private<_AP_W, _AP_S, _AP_N> ap_private<_AP_W, _AP_S, _AP_N>::sqrt() const { + + // Determine the magnitude of the value. + uint32_t magnitude = getActiveBits(); + + // Use a fast table for some small values. This also gets rid of some + // rounding errors in libc sqrt for small values. + if (magnitude <= 5) { + static const uint8_t results[32] = { + /* 0 */ 0, + /* 1- 2 */ 1, 1, + /* 3- 6 */ 2, 2, 2, 2, + /* 7-12 */ 3, 3, 3, 3, 3, 3, + /* 13-20 */ 4, 4, 4, 4, 4, 4, 4, 4, + /* 21-30 */ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + /* 31 */ 6 + }; + return ap_private<_AP_W, _AP_S, _AP_N>(/*BitWidth,*/ results[ (isSingleWord() ? VAL : pVal[0]) ]); + } + + // If the magnitude of the value fits in less than 52 bits (the precision of + // an IEEE double precision floating point value), then we can use the + // libc sqrt function which will probably use a hardware sqrt computation. + // This should be faster than the algorithm below. + if (magnitude < 52) { +#ifdef _MSC_VER + // Amazingly, VC++ doesn't have round(). + return ap_private<_AP_W, _AP_S, _AP_N>(/*BitWidth,*/ + uint64_t(::sqrt(double(isSingleWord()?VAL:pVal[0]))) + 0.5); +#else + return ap_private<_AP_W, _AP_S, _AP_N>(/*BitWidth,*/ + uint64_t(::round(::sqrt(double(isSingleWord()?VAL:pVal[0]))))); +#endif + } + + // Okay, all the short cuts are exhausted. We must compute it. The following + // is a classical Babylonian method for computing the square root. This code + // was adapted to APINt from a wikipedia article on such computations. + // See http://www.wikipedia.org/ and go to the page named + // Calculate_an_integer_square_root. + uint32_t nbits = BitWidth, i = 4; + ap_private<_AP_W, _AP_S, _AP_N> testy(16); + ap_private<_AP_W, _AP_S, _AP_N> x_old(/*BitWidth,*/ 1); + ap_private<_AP_W, _AP_S, _AP_N> x_new(0); + ap_private<_AP_W, _AP_S, _AP_N> two(/*BitWidth,*/ 2); + + // Select a good starting value using binary logarithms. + for (;; i += 2, testy = testy.shl(2)) + if (i >= nbits || this->ule(testy)) { + x_old = x_old.shl(i / 2); + break; + } + + // Use the Babylonian method to arrive at the integer square root: + for (;;) { + x_new = (this->udiv(x_old) + x_old).udiv(two); + if (x_old.ule(x_new)) + break; + x_old = x_new; + } + + // Make sure we return the closest approximation + // NOTE: The rounding calculation below is correct. It will produce an + // off-by-one discrepancy with results from pari/gp. That discrepancy has been + // determined to be a rounding issue with pari/gp as it begins to use a + // floating point representation after 192 bits. There are no discrepancies + // between this algorithm and pari/gp for bit widths < 192 bits. + ap_private<_AP_W, _AP_S, _AP_N> square(x_old * x_old); + ap_private<_AP_W, _AP_S, _AP_N> nextSquare((x_old + 1) * (x_old +1)); + if (this->ult(square)) + return x_old; + else if (this->ule(nextSquare)) { + ap_private<_AP_W, _AP_S, _AP_N> midpoint((nextSquare - square).udiv(two)); + ap_private<_AP_W, _AP_S, _AP_N> offset(*this - square); + if (offset.ult(midpoint)) + return x_old; + else + return x_old + 1; + } else + assert(0 && "Error in ap_private<_AP_W, _AP_S, _AP_N>::sqrt computation"); + return x_old + 1; +} + +/// Implementation of Knuth's Algorithm D (Division of nonnegative integers) +/// from "Art of Computer Programming, Volume 2", section 4.3.1, p. 272. The +/// variables here have the same names as in the algorithm. Comments explain +/// the algorithm and any deviation from it. +static void KnuthDiv(uint32_t *u, uint32_t *v, uint32_t *q, uint32_t* r, + uint32_t m, uint32_t n) { + assert(u && "Must provide dividend"); + assert(v && "Must provide divisor"); + assert(q && "Must provide quotient"); + assert(u != v && u != q && v != q && "Must us different memory"); + assert(n>1 && "n must be > 1"); + + // Knuth uses the value b as the base of the number system. In our case b + // is 2^31 so we just set it to -1u. + uint64_t b = uint64_t(1) << 32; + + //DEBUG(cerr << "KnuthDiv: m=" << m << " n=" << n << '\n'); + //DEBUG(cerr << "KnuthDiv: original:"); + //DEBUG(for (int i = m+n; i >=0; i--) cerr << " " << std::setbase(16) << u[i]); + //DEBUG(cerr << " by"); + //DEBUG(for (int i = n; i >0; i--) cerr << " " << std::setbase(16) << v[i-1]); + //DEBUG(cerr << '\n'); + // D1. [Normalize.] Set d = b / (v[n-1] + 1) and multiply all the digits of + // u and v by d. Note that we have taken Knuth's advice here to use a power + // of 2 value for d such that d * v[n-1] >= b/2 (b is the base). A power of + // 2 allows us to shift instead of multiply and it is easy to determine the + // shift amount from the leading zeros. We are basically normalizing the u + // and v so that its high bits are shifted to the top of v's range without + // overflow. Note that this can require an extra word in u so that u must + // be of length m+n+1. + uint32_t shift = CountLeadingZeros_32(v[n-1]); + uint32_t v_carry = 0; + uint32_t u_carry = 0; + if (shift) { + for (uint32_t i = 0; i < m+n; ++i) { + uint32_t u_tmp = (u[i]) >> (32 - shift); + u[i] = ((u[i]) << (shift)) | u_carry; + u_carry = u_tmp; + } + for (uint32_t i = 0; i < n; ++i) { + uint32_t v_tmp = (v[i]) >> (32 - shift); + v[i] = ((v[i]) << (shift)) | v_carry; + v_carry = v_tmp; + } + } + u[m+n] = u_carry; + //DEBUG(cerr << "KnuthDiv: normal:"); + //DEBUG(for (int i = m+n; i >=0; i--) cerr << " " << std::setbase(16) << u[i]); + //DEBUG(cerr << " by"); + //DEBUG(for (int i = n; i >0; i--) cerr << " " << std::setbase(16) << v[i-1]); + //DEBUG(cerr << '\n'); + + // D2. [Initialize j.] Set j to m. This is the loop counter over the places. + int j = m; + do { + //DEBUG(cerr << "KnuthDiv: quotient digit #" << j << '\n'); + // D3. [Calculate q'.]. + // Set qp = (u[j+n]*b + u[j+n-1]) / v[n-1]. (qp=qprime=q') + // Set rp = (u[j+n]*b + u[j+n-1]) % v[n-1]. (rp=rprime=r') + // Now test if qp == b or qp*v[n-2] > b*rp + u[j+n-2]; if so, decrease + // qp by 1, inrease rp by v[n-1], and repeat this test if rp < b. The test + // on v[n-2] determines at high speed most of the cases in which the trial + // value qp is one too large, and it eliminates all cases where qp is two + // too large. + uint64_t dividend = ((uint64_t(u[j+n]) << 32) + u[j+n-1]); + //DEBUG(cerr << "KnuthDiv: dividend == " << dividend << '\n'); + uint64_t qp = dividend / v[n-1]; + uint64_t rp = dividend % v[n-1]; + if (qp == b || qp*v[n-2] > b*rp + u[j+n-2]) { + qp--; + rp += v[n-1]; + if (rp < b && (qp == b || qp*v[n-2] > b*rp + u[j+n-2])) + qp--; + } + //DEBUG(cerr << "KnuthDiv: qp == " << qp << ", rp == " << rp << '\n'); + + // D4. [Multiply and subtract.] Replace (u[j+n]u[j+n-1]...u[j]) with + // (u[j+n]u[j+n-1]..u[j]) - qp * (v[n-1]...v[1]v[0]). This computation + // consists of a simple multiplication by a one-place number, combined with + // a subtraction. + bool isNeg = false; + for (uint32_t i = 0; i < n; ++i) { + uint64_t u_tmp = uint64_t(u[j+i]) | ((uint64_t(u[j+i+1])) << 32); + uint64_t subtrahend = uint64_t(qp) * uint64_t(v[i]); + bool borrow = subtrahend > u_tmp; + /*DEBUG(cerr << "KnuthDiv: u_tmp == " << u_tmp + << ", subtrahend == " << subtrahend + << ", borrow = " << borrow << '\n');*/ + + uint64_t result = u_tmp - subtrahend; + uint32_t k = j + i; + u[k++] = (uint32_t)(result & (b-1)); // subtract low word + u[k++] = (uint32_t)((result) >> 32); // subtract high word + while (borrow && k <= m+n) { // deal with borrow to the left + borrow = u[k] == 0; + u[k]--; + k++; + } + isNeg |= borrow; + /*DEBUG(cerr << "KnuthDiv: u[j+i] == " << u[j+i] << ", u[j+i+1] == " << + u[j+i+1] << '\n');*/ + } + /*DEBUG(cerr << "KnuthDiv: after subtraction:"); + DEBUG(for (int i = m+n; i >=0; i--) cerr << " " << u[i]); + DEBUG(cerr << '\n');*/ + // The digits (u[j+n]...u[j]) should be kept positive; if the result of + // this step is actually negative, (u[j+n]...u[j]) should be left as the + // true value plus b**(n+1), namely as the b's complement of + // the true value, and a "borrow" to the left should be remembered. + // + if (isNeg) { + bool carry = true; // true because b's complement is "complement + 1" + for (uint32_t i = 0; i <= m+n; ++i) { + u[i] = ~u[i] + carry; // b's complement + carry = carry && u[i] == 0; + } + } + /*DEBUG(cerr << "KnuthDiv: after complement:"); + DEBUG(for (int i = m+n; i >=0; i--) cerr << " " << u[i]); + DEBUG(cerr << '\n');*/ + + // D5. [Test remainder.] Set q[j] = qp. If the result of step D4 was + // negative, go to step D6; otherwise go on to step D7. + q[j] = (uint32_t)qp; + if (isNeg) { + // D6. [Add back]. The probability that this step is necessary is very + // small, on the order of only 2/b. Make sure that test data accounts for + // this possibility. Decrease q[j] by 1 + q[j]--; + // and add (0v[n-1]...v[1]v[0]) to (u[j+n]u[j+n-1]...u[j+1]u[j]). + // A carry will occur to the left of u[j+n], and it should be ignored + // since it cancels with the borrow that occurred in D4. + bool carry = false; + for (uint32_t i = 0; i < n; i++) { + uint32_t limit = AESL_std::min(u[j+i],v[i]); + u[j+i] += v[i] + carry; + carry = u[j+i] < limit || (carry && u[j+i] == limit); + } + u[j+n] += carry; + } + /*DEBUG(cerr << "KnuthDiv: after correction:"); + DEBUG(for (int i = m+n; i >=0; i--) cerr <<" " << u[i]); + DEBUG(cerr << "\nKnuthDiv: digit result = " << q[j] << '\n');*/ + + // D7. [Loop on j.] Decrease j by one. Now if j >= 0, go back to D3. + } while (--j >= 0); + + /*DEBUG(cerr << "KnuthDiv: quotient:"); + DEBUG(for (int i = m; i >=0; i--) cerr <<" " << q[i]); + DEBUG(cerr << '\n');*/ + + // D8. [Unnormalize]. Now q[...] is the desired quotient, and the desired + // remainder may be obtained by dividing u[...] by d. If r is non-null we + // compute the remainder (urem uses this). + if (r) { + // The value d is expressed by the "shift" value above since we avoided + // multiplication by d by using a shift left. So, all we have to do is + // shift right here. In order to mak + if (shift) { + uint32_t carry = 0; + //DEBUG(cerr << "KnuthDiv: remainder:"); + for (int i = n-1; i >= 0; i--) { + r[i] = ((u[i]) >> (shift)) | carry; + carry = (u[i]) << (32 - shift); + //DEBUG(cerr << " " << r[i]); + } + } else { + for (int i = n-1; i >= 0; i--) { + r[i] = u[i]; + //DEBUG(cerr << " " << r[i]); + } + } + //DEBUG(cerr << '\n'); + } + //DEBUG(cerr << std::setbase(10) << '\n'); +} + +template +void divide(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, uint32_t lhsWords, + const ap_private<_AP_W, _AP_S, _AP_N>& RHS, uint32_t rhsWords, + ap_private<_AP_W, _AP_S, _AP_N> *Quotient, ap_private<_AP_W, _AP_S, _AP_N> *Remainder) { + assert(lhsWords >= rhsWords && "Fractional result"); + enum {APINT_BITS_PER_WORD=64}; + // First, compose the values into an array of 32-bit words instead of + // 64-bit words. This is a necessity of both the "short division" algorithm + // and the the Knuth "classical algorithm" which requires there to be native + // operations for +, -, and * on an m bit value with an m*2 bit result. We + // can't use 64-bit operands here because we don't have native results of + // 128-bits. Furthremore, casting the 64-bit values to 32-bit values won't + // work on large-endian machines. + uint64_t mask = ~0ull >> (sizeof(uint32_t)*8); + uint32_t n = rhsWords * 2; + uint32_t m = (lhsWords * 2) - n; + + // Allocate space for the temporary values we need either on the stack, if + // it will fit, or on the heap if it won't. + uint32_t SPACE[128]; + uint32_t *__U = 0; + uint32_t *__V = 0; + uint32_t *__Q = 0; + uint32_t *__R = 0; + if ((Remainder?4:3)*n+2*m+1 <= 128) { + __U = &SPACE[0]; + __V = &SPACE[m+n+1]; + __Q = &SPACE[(m+n+1) + n]; + if (Remainder) + __R = &SPACE[(m+n+1) + n + (m+n)]; + } else { + __U = new uint32_t[m + n + 1]; + __V = new uint32_t[n]; + __Q = new uint32_t[m+n]; + if (Remainder) + __R = new uint32_t[n]; + } + + // Initialize the dividend + memset(__U, 0, (m+n+1)*sizeof(uint32_t)); + for (unsigned i = 0; i < lhsWords; ++i) { + uint64_t tmp = (LHS.getNumWords() == 1 ? LHS.VAL : LHS.pVal[i]); + __U[i * 2] = (uint32_t)(tmp & mask); + __U[i * 2 + 1] = (tmp) >> (sizeof(uint32_t)*8); + } + __U[m+n] = 0; // this extra word is for "spill" in the Knuth algorithm. + + // Initialize the divisor + memset(__V, 0, (n)*sizeof(uint32_t)); + for (unsigned i = 0; i < rhsWords; ++i) { + uint64_t tmp = (RHS.getNumWords() == 1 ? RHS.VAL : RHS.pVal[i]); + __V[i * 2] = (uint32_t)(tmp & mask); + __V[i * 2 + 1] = (tmp) >> (sizeof(uint32_t)*8); + } + + // initialize the quotient and remainder + memset(__Q, 0, (m+n) * sizeof(uint32_t)); + if (Remainder) + memset(__R, 0, n * sizeof(uint32_t)); + + // Now, adjust m and n for the Knuth division. n is the number of words in + // the divisor. m is the number of words by which the dividend exceeds the + // divisor (i.e. m+n is the length of the dividend). These sizes must not + // contain any zero words or the Knuth algorithm fails. + for (unsigned i = n; i > 0 && __V[i-1] == 0; i--) { + n--; + m++; + } + for (unsigned i = m+n; i > 0 && __U[i-1] == 0; i--) + m--; + + // If we're left with only a single word for the divisor, Knuth doesn't work + // so we implement the short division algorithm here. This is much simpler + // and faster because we are certain that we can divide a 64-bit quantity + // by a 32-bit quantity at hardware speed and short division is simply a + // series of such operations. This is just like doing short division but we + // are using base 2^32 instead of base 10. + assert(n != 0 && "Divide by zero?"); + if (n == 1) { + uint32_t divisor = __V[0]; + uint32_t remainder = 0; + for (int i = m+n-1; i >= 0; i--) { + uint64_t partial_dividend = (uint64_t(remainder)) << 32 | __U[i]; + if (partial_dividend == 0) { + __Q[i] = 0; + remainder = 0; + } else if (partial_dividend < divisor) { + __Q[i] = 0; + remainder = (uint32_t)partial_dividend; + } else if (partial_dividend == divisor) { + __Q[i] = 1; + remainder = 0; + } else { + __Q[i] = (uint32_t)(partial_dividend / divisor); + remainder = (uint32_t)(partial_dividend - (__Q[i] * divisor)); + } + } + if (__R) + __R[0] = remainder; + } else { + // Now we're ready to invoke the Knuth classical divide algorithm. In this + // case n > 1. + KnuthDiv(__U, __V, __Q, __R, m, n); + } + + // If the caller wants the quotient + if (Quotient) { + // Set up the Quotient value's memory. + if (Quotient->BitWidth != LHS.BitWidth) { + if (Quotient->isSingleWord()) + Quotient->VAL = 0; + } else + Quotient->clear(); + + // The quotient is in Q. Reconstitute the quotient into Quotient's low + // order words. + if (lhsWords == 1) { + uint64_t tmp = + uint64_t(__Q[0]) | ((uint64_t(__Q[1])) << (APINT_BITS_PER_WORD / 2)); + if (Quotient->isSingleWord()) + Quotient->VAL = tmp; + else + Quotient->pVal[0] = tmp; + } else { + assert(!Quotient->isSingleWord() && "Quotient ap_private not large enough"); + for (unsigned i = 0; i < lhsWords; ++i) + Quotient->pVal[i] = + uint64_t(__Q[i*2]) | ((uint64_t(__Q[i*2+1])) << (APINT_BITS_PER_WORD / 2)); + } + Quotient->clearUnusedBits(); + } + + // If the caller wants the remainder + if (Remainder) { + // Set up the Remainder value's memory. + if (Remainder->BitWidth != RHS.BitWidth) { + if (Remainder->isSingleWord()) + Remainder->VAL = 0; + } else + Remainder->clear(); + + // The remainder is in R. Reconstitute the remainder into Remainder's low + // order words. + if (rhsWords == 1) { + uint64_t tmp = + uint64_t(__R[0]) | ((uint64_t(__R[1])) << (APINT_BITS_PER_WORD / 2)); + if (Remainder->isSingleWord()) + Remainder->VAL = tmp; + else + Remainder->pVal[0] = tmp; + } else { + assert(!Remainder->isSingleWord() && "Remainder ap_private not large enough"); + for (unsigned i = 0; i < rhsWords; ++i) + Remainder->pVal[i] = + uint64_t(__R[i*2]) | ((uint64_t(__R[i*2+1])) << (APINT_BITS_PER_WORD / 2)); + } + Remainder->clearUnusedBits(); + } + + // Clean up the memory we allocated. + if (__U != &SPACE[0]) { + delete [] __U; + delete [] __V; + delete [] __Q; + delete [] __R; + } +} + + +template +void ap_private<_AP_W, _AP_S, _AP_N>::fromString(const char *str, uint32_t slen, uint8_t radix) { + enum { numbits=_AP_W}; + // Check our assumptions here + assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) && + "Radix should be 2, 8, 10, or 16!"); + assert(str && "String is null?"); + bool isNeg = str[0] == '-'; + if (isNeg) + str++, slen--; + + //skip any leading zero + while(*str == '0' && *(str+1) != '\0') {str++; slen--;} + assert((slen <= numbits || radix != 2) && "Insufficient bit width"); + assert(((slen - 1)*3 <= numbits || radix != 8) && "Insufficient bit width"); + assert(((slen - 1)*4 <= numbits || radix != 16) && "Insufficient bit width"); + assert((((slen -1)*64)/22 <= numbits || radix != 10) && "Insufficient bit width"); + + memset(pVal, 0, _AP_N * sizeof(uint64_t)); + + // Figure out if we can shift instead of multiply + uint32_t shift = (radix == 16 ? 4 : radix == 8 ? 3 : radix == 2 ? 1 : 0); + + // Set up an ap_private for the digit to add outside the loop so we don't + // constantly construct/destruct it. + uint64_t bigVal[_AP_N]; + memset(bigVal, 0, _AP_N * sizeof(uint64_t)); + ap_private<_AP_W, _AP_S, _AP_N> apdigit(getBitWidth(), bigVal); + ap_private<_AP_W, _AP_S, _AP_N> apradix(radix); + + // Enter digit traversal loop + for (unsigned i = 0; i < slen; i++) { + // Get a digit + uint32_t digit = 0; + char cdigit = str[i]; + if (radix == 16) { +#define isxdigit(c) (((c) >= '0' && (c) <= '9') || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F')) +#define isdigit(c) ((c) >= '0' && (c) <= '9') + if (!isxdigit(cdigit)) + assert(0 && "Invalid hex digit in string"); + if (isdigit(cdigit)) + digit = cdigit - '0'; + else if (cdigit >= 'a') + digit = cdigit - 'a' + 10; + else if (cdigit >= 'A') + digit = cdigit - 'A' + 10; + else + assert(0 && "huh? we shouldn't get here"); + } else if (isdigit(cdigit)) { + digit = cdigit - '0'; + } else { + assert(0 && "Invalid character in digit string"); + } +#undef isxdigit +#undef isdigit + // Shift or multiply the value by the radix + if (shift) + *this <<= shift; + else + *this *= apradix; + + // Add in the digit we just interpreted + if (apdigit.isSingleWord()) + apdigit.VAL = digit; + else + apdigit.pVal[0] = digit; + *this += apdigit; + } + // If its negative, put it in two's complement form + if (isNeg) { + (*this)--; + this->flip(); + } + clearUnusedBits(); +} + +template +std::string ap_private<_AP_W, _AP_S, _AP_N>::toString(uint8_t radix, bool wantSigned) const { + assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) && + "Radix should be 2, 8, 10, or 16!"); + static const char *digits[] = { + "0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F" + }; + std::string result; + uint32_t bits_used = getActiveBits(); + + if (radix != 10) { + // For the 2, 8 and 16 bit cases, we can just shift instead of divide + // because the number of bits per digit (1,3 and 4 respectively) divides + // equaly. We just shift until there value is zero. + + // First, check for a zero value and just short circuit the logic below. + if (*this == (uint64_t)(0)) + result = "0"; + else { + ap_private<_AP_W, false, _AP_N> tmp(*this); + size_t insert_at = 0; + if (wantSigned && isNegative()) { + // They want to print the signed version and it is a negative value + // Flip the bits and add one to turn it into the equivalent positive + // value and put a '-' in the result. + tmp.flip(); + tmp++; + tmp.clearUnusedBitsToZero(); + result = "-"; + insert_at = 1; + } + // Just shift tmp right for each digit width until it becomes zero + uint32_t shift = (radix == 16 ? 4 : (radix == 8 ? 3 : 1)); + uint64_t mask = radix - 1; + ap_private<_AP_W, false, _AP_N> zero(0); + while (tmp.ne(zero)) { + unsigned digit = (tmp.isSingleWord() ? tmp.VAL : tmp.pVal[0]) & mask; + result.insert(insert_at, digits[digit]); + tmp = tmp.lshr(shift); + } + } + return result; + } + + ap_private<_AP_W, false, _AP_N> tmp(*this); + ap_private<_AP_W, false, _AP_N> divisor(radix); + ap_private<_AP_W, false, _AP_N> zero(0); + size_t insert_at = 0; + if (wantSigned && isNegative()) { + // They want to print the signed version and it is a negative value + // Flip the bits and add one to turn it into the equivalent positive + // value and put a '-' in the result. + tmp.flip(); + tmp++; + tmp.clearUnusedBitsToZero(); + result = "-"; + insert_at = 1; + } + if (tmp == ap_private<_AP_W, false, _AP_N>(0)) + result = "0"; + else while (tmp.ne(zero)) { + ap_private<_AP_W, false, _AP_N> APdigit(0); + ap_private<_AP_W, false, _AP_N> tmp2(0); + divide(tmp, tmp.getNumWords(), divisor, divisor.getNumWords(), &tmp2, + &APdigit); + uint32_t digit = APdigit.getZExtValue(); + assert(digit < radix && "divide failed"); + result.insert(insert_at,digits[digit]); + tmp = tmp2; + } + + return result; +} + +// This implements a variety of operations on a representation of +// arbitrary precision, two's-complement, bignum integer values. + +/* Assumed by lowHalf, highHalf, partMSB and partLSB. A fairly safe + and unrestricting assumption. */ + +/* Some handy functions local to this file. */ + +template +void divide(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, uint32_t lhsWords, + uint64_t RHS, + ap_private<_AP_W, _AP_S, _AP_N> *Quotient, ap_private<_AP_W, _AP_S, _AP_N> *Remainder) { + uint32_t rhsWords=1; + assert(lhsWords >= rhsWords && "Fractional result"); + enum {APINT_BITS_PER_WORD=64}; + // First, compose the values into an array of 32-bit words instead of + // 64-bit words. This is a necessity of both the "short division" algorithm + // and the the Knuth "classical algorithm" which requires there to be native + // operations for +, -, and * on an m bit value with an m*2 bit result. We + // can't use 64-bit operands here because we don't have native results of + // 128-bits. Furthremore, casting the 64-bit values to 32-bit values won't + // work on large-endian machines. + uint64_t mask = ~0ull >> (sizeof(uint32_t)*8); + uint32_t n = 2; + uint32_t m = (lhsWords * 2) - n; + + // Allocate space for the temporary values we need either on the stack, if + // it will fit, or on the heap if it won't. + uint32_t SPACE[128]; + uint32_t *__U = 0; + uint32_t *__V = 0; + uint32_t *__Q = 0; + uint32_t *__R = 0; + if ((Remainder?4:3)*n+2*m+1 <= 128) { + __U = &SPACE[0]; + __V = &SPACE[m+n+1]; + __Q = &SPACE[(m+n+1) + n]; + if (Remainder) + __R = &SPACE[(m+n+1) + n + (m+n)]; + } else { + __U = new uint32_t[m + n + 1]; + __V = new uint32_t[n]; + __Q = new uint32_t[m+n]; + if (Remainder) + __R = new uint32_t[n]; + } + + // Initialize the dividend + memset(__U, 0, (m+n+1)*sizeof(uint32_t)); + for (unsigned i = 0; i < lhsWords; ++i) { + uint64_t tmp = (LHS.getNumWords() == 1 ? LHS.VAL : LHS.pVal[i]); + __U[i * 2] = tmp & mask; + __U[i * 2 + 1] = (tmp) >> (sizeof(uint32_t)*8); + } + __U[m+n] = 0; // this extra word is for "spill" in the Knuth algorithm. + + // Initialize the divisor + memset(__V, 0, (n)*sizeof(uint32_t)); + __V[0] = RHS & mask; + __V[1] = (RHS) >> (sizeof(uint32_t)*8); + + // initialize the quotient and remainder + memset(__Q, 0, (m+n) * sizeof(uint32_t)); + if (Remainder) + memset(__R, 0, n * sizeof(uint32_t)); + + // Now, adjust m and n for the Knuth division. n is the number of words in + // the divisor. m is the number of words by which the dividend exceeds the + // divisor (i.e. m+n is the length of the dividend). These sizes must not + // contain any zero words or the Knuth algorithm fails. + for (unsigned i = n; i > 0 && __V[i-1] == 0; i--) { + n--; + m++; + } + for (unsigned i = m+n; i > 0 && __U[i-1] == 0; i--) + m--; + + // If we're left with only a single word for the divisor, Knuth doesn't work + // so we implement the short division algorithm here. This is much simpler + // and faster because we are certain that we can divide a 64-bit quantity + // by a 32-bit quantity at hardware speed and short division is simply a + // series of such operations. This is just like doing short division but we + // are using base 2^32 instead of base 10. + assert(n != 0 && "Divide by zero?"); + if (n == 1) { + uint32_t divisor = __V[0]; + uint32_t remainder = 0; + for (int i = m+n-1; i >= 0; i--) { + uint64_t partial_dividend = (uint64_t(remainder)) << 32 | __U[i]; + if (partial_dividend == 0) { + __Q[i] = 0; + remainder = 0; + } else if (partial_dividend < divisor) { + __Q[i] = 0; + remainder = partial_dividend; + } else if (partial_dividend == divisor) { + __Q[i] = 1; + remainder = 0; + } else { + __Q[i] = partial_dividend / divisor; + remainder = partial_dividend - (__Q[i] * divisor); + } + } + if (__R) + __R[0] = remainder; + } else { + // Now we're ready to invoke the Knuth classical divide algorithm. In this + // case n > 1. + KnuthDiv(__U, __V, __Q, __R, m, n); + } + + // If the caller wants the quotient + if (Quotient) { + // Set up the Quotient value's memory. + if (Quotient->BitWidth != LHS.BitWidth) { + if (Quotient->isSingleWord()) + Quotient->VAL = 0; + else + delete [] Quotient->pVal; + } else + Quotient->clear(); + + // The quotient is in Q. Reconstitute the quotient into Quotient's low + // order words. + if (lhsWords == 1) { + uint64_t tmp = + uint64_t(__Q[0]) | ((uint64_t(__Q[1])) << (APINT_BITS_PER_WORD / 2)); + if (Quotient->isSingleWord()) + Quotient->VAL = tmp; + else + Quotient->pVal[0] = tmp; + } else { + assert(!Quotient->isSingleWord() && "Quotient ap_private not large enough"); + for (unsigned i = 0; i < lhsWords; ++i) + Quotient->pVal[i] = + uint64_t(__Q[i*2]) | ((uint64_t(__Q[i*2+1])) << (APINT_BITS_PER_WORD / 2)); + } + Quotient->clearUnusedBits(); + } + + // If the caller wants the remainder + if (Remainder) { + // Set up the Remainder value's memory. + if (Remainder->BitWidth != 64 /* RHS.BitWidth */) { + if (Remainder->isSingleWord()) + Remainder->VAL = 0; + } else + Remainder->clear(); + + // The remainder is in __R. Reconstitute the remainder into Remainder's low + // order words. + if (rhsWords == 1) { + uint64_t tmp = + uint64_t(__R[0]) | ((uint64_t(__R[1])) << (APINT_BITS_PER_WORD / 2)); + if (Remainder->isSingleWord()) + Remainder->VAL = tmp; + else + Remainder->pVal[0] = tmp; + } else { + assert(!Remainder->isSingleWord() && "Remainder ap_private not large enough"); + for (unsigned i = 0; i < rhsWords; ++i) + Remainder->pVal[i] = + uint64_t(__R[i*2]) | ((uint64_t(__R[i*2+1])) << (APINT_BITS_PER_WORD / 2)); + } + Remainder->clearUnusedBits(); + } + + // Clean up the memory we allocated. + if (__U != &SPACE[0]) { + delete [] __U; + delete [] __V; + delete [] __Q; + delete [] __R; + } +} + +//When bitwidth < 64 +template class ap_private <_AP_W, _AP_S, 1> { +#ifdef _MSC_VER +#pragma warning( disable : 4521 4522 ) +#endif +public: + typedef typename retval<_AP_S>::Type ValType; + template + struct RType { + enum { + _AP_N =1, + mult_w = _AP_W+_AP_W2, + mult_s = _AP_S||_AP_S2, //?? why + plus_w = AP_MAX(_AP_W+(_AP_S2&&!_AP_S),_AP_W2+(_AP_S&&!_AP_S2))+1, //shouldn't it be AP_MAX(_AP_W,_AP_W2)+!(_AP_S^_AP_S2)+1 ???? + plus_s = _AP_S||_AP_S2, + minus_w = AP_MAX(_AP_W+(_AP_S2&&!_AP_S),_AP_W2+(_AP_S&&!_AP_S2))+1, + minus_s = true, + div_w = _AP_W+_AP_S2, + div_s = _AP_S||_AP_S2, + mod_w = AP_MIN(_AP_W,_AP_W2+(!_AP_S2&&_AP_S)), + mod_s = _AP_S, + logic_w = AP_MAX(_AP_W+(_AP_S2&&!_AP_S),_AP_W2+(_AP_S&&!_AP_S2)), + logic_s = _AP_S||_AP_S2 + }; + typedef ap_private mult; + typedef ap_private plus; + typedef ap_private minus; + typedef ap_private logic; + typedef ap_private div; + typedef ap_private mod; + typedef ap_private<_AP_W, _AP_S> arg1; + typedef bool reduce; + }; + enum { APINT_BITS_PER_WORD = 64}; + enum { excess_bits = (_AP_W%APINT_BITS_PER_WORD) ? APINT_BITS_PER_WORD -(_AP_W%APINT_BITS_PER_WORD) : 0}; + static const uint64_t mask = ((uint64_t)~0ULL >> (excess_bits)); + static const uint64_t not_mask = ~mask; + static const uint64_t sign_bit_mask = 1ULL << (APINT_BITS_PER_WORD-1); + template struct sign_ext_mask { static const uint64_t mask=~0ULL<<_AP_W1;}; + + enum { BitWidth=_AP_W}; + uint64_t VAL; ///< Used to store the <= 64 bits integer value. + const uint64_t *const pVal; + + INLINE uint32_t getBitWidth() const { + return BitWidth; + } + + template + ap_private<_AP_W, _AP_S, 1>& operator=(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { + VAL = RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + + template + ap_private<_AP_W, _AP_S, 1>& operator=(const volatile ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { + VAL = RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + + template + ap_private<_AP_W, _AP_S, 1>& operator=(const ap_private<_AP_W1, _AP_S1, 1>& RHS) { + VAL = RHS.VAL; + clearUnusedBits(); + return *this; + } + + template + ap_private<_AP_W, _AP_S, 1>& operator=(const volatile ap_private<_AP_W1, _AP_S1, 1>& RHS) { + VAL = RHS.VAL; + clearUnusedBits(); + return *this; + } + + volatile ap_private& operator=(const ap_private& RHS) volatile { + // Don't do anything for X = X + VAL = RHS.VAL; // No need to check because no harm done by copying. + return *this; + } + ap_private& operator=(const ap_private& RHS) { + // Don't do anything for X = X + VAL = RHS.VAL; // No need to check because no harm done by copying. + return *this; + } + + volatile ap_private& operator=(const volatile ap_private& RHS) volatile { + // Don't do anything for X = X + VAL = RHS.VAL; // No need to check because no harm done by copying. + return *this; + } + ap_private& operator=(const volatile ap_private& RHS) { + // Don't do anything for X = X + VAL = RHS.VAL; // No need to check because no harm done by copying. + return *this; + } + + template + INLINE ap_private& operator = (const ap_range_ref<_AP_W2, _AP_S2>& op2) { + *this = ap_private<_AP_W2, false>(op2); + return *this; + } + + explicit INLINE ap_private(uint64_t* val) : VAL(val[0]), pVal(&VAL){ + clearUnusedBits(); + } + + INLINE bool isSingleWord() const { return true; } + + INLINE void fromString(const char *strStart, uint32_t slen, + uint8_t radix, int offset=0) { + // Check our assumptions here + assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) && + "Radix should be 2, 8, 10, or 16!"); + assert(strStart && "String is null?"); + strStart+=offset; + switch(radix) { + case 2: + // sscanf(strStart,"%b",&VAL); + VAL = *strStart =='1' ? ~0ULL : 0; + for (;*strStart; ++strStart) { + assert((*strStart=='0'|| *strStart=='1')&&("Wrong binary number") ); + VAL <<=1; + VAL |= (*strStart-'0'); + } + break; + case 8: +#if __WIN32__ + sscanf(strStart,"%I64o",&VAL); +#else + +#if defined __x86_64__ + sscanf(strStart,"%lo",&VAL); +#else + sscanf(strStart,"%llo",&VAL); +#endif + +#endif + break; + case 10: +#if __WIN32__ + sscanf(strStart,"%I64u",&VAL); +#else + +#if defined __x86_64__ + sscanf(strStart,"%lu",&VAL); +#else + sscanf(strStart,"%llu",&VAL); +#endif + +#endif + break; + case 16: +#if __WIN32__ + sscanf(strStart,"%I64x",&VAL); +#else + +#if defined __x86_64__ + sscanf(strStart,"%lx",&VAL); +#else + sscanf(strStart,"%llx",&VAL); +#endif + +#endif + break; + default: + assert(true && "Unknown radix"); + // error + } + clearUnusedBits(); + } + + INLINE ap_private() : pVal(&VAL){VAL = 0ULL;} + +#define CTOR(TYPE) \ + INLINE ap_private(TYPE v) : VAL((uint64_t)v), pVal(&VAL) { \ + clearUnusedBits(); \ + } + CTOR(int) + CTOR(bool) + CTOR(signed char) + CTOR(unsigned char) + CTOR(short) + CTOR(unsigned short) + CTOR(unsigned int) + CTOR(long) + CTOR(unsigned long) + CTOR(unsigned long long) + CTOR(long long) + CTOR(float) + CTOR(double) +#undef CTOR + ap_private(uint32_t numWords, const uint64_t bigVal[]): VAL(bigVal[0]), pVal(&VAL) {clearUnusedBits();} + + ap_private(const std::string& val, uint8_t radix=2, int base=0, int offset=0): VAL(0), pVal(&VAL) { + assert(!val.empty() && "String empty?"); + fromString(val.c_str()+base, val.size()-base, radix); + } + + ap_private(const char strStart[], uint32_t slen, uint8_t radix, int base=0, int offset=0) : VAL(0), pVal(&VAL) { + fromString(strStart+base, slen-base, radix, offset); + } + + ap_private(const ap_private& that) : VAL(that.VAL), pVal(&VAL) { + clearUnusedBits(); + } + + template + ap_private(const ap_private<_AP_W1, _AP_S1, 1>& that) : VAL(that.VAL), pVal(&VAL) { + clearUnusedBits(); + } + + template + ap_private(const ap_private<_AP_W1, _AP_S1, _AP_N1>& that) : VAL(that.pVal[0]), pVal(&VAL) { + clearUnusedBits(); + } + + template + ap_private(const volatile ap_private<_AP_W1, _AP_S1, _AP_N1>& that) : VAL(that.pVal[0]), pVal(&VAL) { + clearUnusedBits(); + } + +#if 0 +template + explicit ap_private(const ap_private<_AP_W1, true, 1+_AP_W1/64>& that) + : VAL((_AP_W1>_AP_W) ? that.VAL & mask : ((1ULL<<(_AP_W1-1)&that.pVal[0]) ? sign_ext_mask<_AP_W1>::mask | that.VAL : that.pVal[0])), pVal(&VAL) {} + +template + explicit ap_private(const ap_private<_AP_W1, false, (_AP_W1+63)/64>& that) + : VAL(that.VAL & mask), pVal(&VAL) {} +#endif + + explicit ap_private(const char* val) : pVal(&VAL) { + std::string str(val); + uint32_t strLen = str.length(); + const char *strp = str.c_str(); + uint32_t offset = 0; + uint32_t base = 0; + bool neg = false; + uint32_t radix = 10; + ap_parse_sign(strp, base, neg); + ap_parse_prefix(strp + base, offset, radix); + + if ((radix != 10 && neg) || + (strLen - base - offset <= 0) || + InvalidDigit(strp, strLen, base + offset, radix)) { + fprintf(stderr, "invalid character string %s !\n", val); + assert(0); + } + + ap_private<_AP_W, _AP_S> ap_private_val(str.c_str(), strLen, radix, base, offset); + if (neg) + ap_private_val = -ap_private_val; + operator = (ap_private_val); + } + + ap_private(const char* val, signed char rd): pVal(&VAL) { + std::string str(val); + uint32_t strLen = str.length(); + const char *strp = str.c_str(); + uint32_t offset = 0; + uint32_t base = 0; + uint32_t radix = rd; + bool neg = false; + ap_parse_sign(strp, base, neg); + ap_parse_prefix(strp + base, offset, radix); + + if ((radix != 10 && neg) || + (strLen - base - offset <= 0) || + InvalidDigit(strp, strLen, base + offset, radix)) { + fprintf(stderr, "invalid character string %s !\n", val); + assert(0); + } + + uint32_t bitsNeeded = ap_private<_AP_W, _AP_S>::getBitsNeeded(strp, strLen, radix); + ap_private<_AP_W, _AP_S> ap_private_val(strp , strLen, radix, base, offset); + //ap_private<_AP_W, _AP_S> ap_private_val(bitsNeeded, strp , strLen, radix, base, offset); + if (strp[0] == '-') + ap_private_val = -ap_private_val; + operator = (ap_private_val); + } + + INLINE bool isNegative() const { + static const uint64_t sign_mask = 1ULL << (_AP_W-1); + return _AP_S && (sign_mask & VAL); + } + + INLINE bool isPositive() const { + return !isNegative(); + } + + INLINE bool isStrictlyPositive() const { + return !isNegative() && VAL!=0; + } + + INLINE bool isAllOnesValue() const { + return (mask & VAL) == mask; + } + + template + INLINE bool operator==(const ap_private<_AP_W1, _AP_S1, 1>& RHS) const { + return (VAL == RHS.VAL); + } + + INLINE bool operator==(const ap_private<_AP_W, _AP_S>& RHS) const { return VAL == RHS.VAL; } + INLINE bool operator==(const ap_private<_AP_W, !_AP_S>& RHS) const { return getVal() == RHS.getVal(); } + INLINE bool operator==(uint64_t Val) const { return (VAL == Val); } + INLINE bool operator!=(uint64_t Val) const { return (VAL != Val); } + INLINE bool operator!=(const ap_private<_AP_W, _AP_S>& RHS) const { return VAL != RHS.VAL; } + INLINE bool operator!=(const ap_private<_AP_W, !_AP_S>& RHS) const { return getVal() != RHS.getVal(); } + const ap_private operator++() { ++VAL; clearUnusedBits(); return *this; } + const ap_private operator--(int) { + ap_private orig(*this); + --VAL; clearUnusedBits(); + return orig; + } + const ap_private operator--() { --VAL; clearUnusedBits(); return *this;} + INLINE bool operator !() const { return !VAL;} + + const ap_private operator++(int) { + ap_private orig(*this); + VAL++; clearUnusedBits(); + return orig; + } + + const ap_private operator~() {return ap_private(~VAL);} + INLINE typename RType<1,false>::minus operator-() const { + return ap_private<1,false>(0) - (*this); + } + + INLINE std::string toString(uint8_t radix, bool wantSigned) const ; + INLINE std::string toStringUnsigned(uint8_t radix = 10) const { + return toString(radix, false); + } + INLINE std::string toStringSigned(uint8_t radix = 10) const { + return toString(radix, true); + } + INLINE void clear() { + VAL=0; + } + INLINE ap_private& clear(uint32_t bitPosition) { VAL &= ~(1ULL<<(bitPosition)); clearUnusedBits(); return *this;} + + INLINE ap_private ashr(uint32_t shiftAmt) const { + enum {excess_bits = APINT_BITS_PER_WORD - BitWidth}; + if (_AP_S) + return ap_private((shiftAmt == BitWidth) ? 0 : ((int64_t)VAL) >> (shiftAmt)); + else + return ap_private((shiftAmt == BitWidth) ? 0 : (VAL) >> (shiftAmt)); + } + + INLINE ap_private lshr(uint32_t shiftAmt) const { + return ap_private((shiftAmt == BitWidth) ? ap_private(0) : ap_private((VAL&mask) >> (shiftAmt))); + } + + INLINE ap_private shl(uint32_t shiftAmt) const { + if (shiftAmt > BitWidth) { + if (!isNegative()) + return ap_private(0); + else return ap_private(-1); + } + if (shiftAmt == BitWidth) return ap_private(0); + else return ap_private((VAL) << (shiftAmt)); + //return ap_private((shiftAmt == BitWidth) ? ap_private(0ULL) : ap_private(VAL << shiftAmt)); + } + + INLINE int64_t getSExtValue() const { + return VAL; + } + + INLINE uint64_t getZExtValue() const { + return VAL & mask; + } + + template + INLINE ap_private(const ap_range_ref<_AP_W2,_AP_S2>& ref) : pVal(&VAL) { + *this=ref.get(); + } + + template + INLINE ap_private(const ap_bit_ref<_AP_W2,_AP_S2>& ref) : pVal(&VAL) { + *this = ((uint64_t)(bool)ref); + } + + template + INLINE ap_private(const ap_concat_ref<_AP_W2, _AP_T2,_AP_W3, _AP_T3>& ref) : pVal(&VAL) { + *this=ref.get(); + } + + template + INLINE ap_private(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2> &val) : pVal(&VAL) { + *this = ((val.operator ap_private<_AP_W2, false> ())); + } + + template + INLINE ap_private(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2> &val) : pVal(&VAL) { + *this = (uint64_t)(bool)val; + } + + INLINE void write(const ap_private<_AP_W, _AP_S>& op2) volatile { + *this = (op2); + } + + //Explicit conversions to C interger types + //----------------------------------------------------------- + ValType getVal() const { + return VAL; + } + operator ValType () const { + return getVal(); + } + INLINE int to_int() const { + // ap_private<64 /* _AP_W */, _AP_S> res(V); + return (int) getVal(); + } + + INLINE unsigned to_uint() const { + return (unsigned) getVal(); + } + + INLINE long to_long() const { + return (long) getVal(); + } + + INLINE unsigned long to_ulong() const { + return (unsigned long) getVal(); + } + + INLINE ap_slong to_int64() const { + return (ap_slong) getVal(); + } + + INLINE ap_ulong to_uint64() const { + return (ap_ulong) getVal(); + } + + INLINE double to_double() const { + if (isNegative()) + return roundToDouble(true); + else + return roundToDouble(false); + } + + INLINE bool isMinValue() const { return VAL == 0;} + template INLINE ap_private& operator&=(const ap_private<_AP_W1, _AP_S1>& RHS) { + VAL = VAL&RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + + template INLINE ap_private& operator|=(const ap_private<_AP_W1, _AP_S1>& RHS) { + VAL = VAL|RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + + template INLINE ap_private& operator^=(const ap_private<_AP_W1, _AP_S1>& RHS){ + VAL = VAL^RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + + template INLINE ap_private& operator*=(const ap_private<_AP_W1, _AP_S1>& RHS){ + VAL = VAL*RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + + template INLINE ap_private& operator+=(const ap_private<_AP_W1, _AP_S1>& RHS){ + VAL = VAL+RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + + template INLINE ap_private& operator-=(const ap_private<_AP_W1, _AP_S1>& RHS){ + VAL = VAL-RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + INLINE const ap_private& operator<<=(uint32_t shiftAmt) { VAL<<=shiftAmt; clearUnusedBits(); return *this; } + + template INLINE typename RType<_AP_W1, _AP_S1>::logic operator&(const ap_private<_AP_W1, _AP_S1>& RHS) const { + if (RType<_AP_W1, _AP_S1>::logic_w <= 64) { + typename RType<_AP_W1, _AP_S1>::logic Ret(VAL & RHS.VAL); + return Ret; + } else { + typename RType<_AP_W1, _AP_S1>::logic Ret = *this; + return Ret & RHS; + } + } + + template INLINE typename RType<_AP_W1, _AP_S1>::logic operator^(const ap_private<_AP_W1, _AP_S1>& RHS) const { + if (RType<_AP_W1, _AP_S1>::logic_w <= 64) { + typename RType<_AP_W1, _AP_S1>::logic Ret(VAL ^ RHS.VAL); + return Ret; + } else { + typename RType<_AP_W1, _AP_S1>::logic Ret = *this; + return Ret ^ RHS; + } + } + + template INLINE typename RType<_AP_W1, _AP_S1>::logic operator|(const ap_private<_AP_W1, _AP_S1>& RHS) const { + if (RType<_AP_W1, _AP_S1>::logic_w <= 64) { + typename RType<_AP_W1, _AP_S1>::logic Ret(VAL | RHS.VAL); + return Ret; + } else { + typename RType<_AP_W1, _AP_S1>::logic Ret = *this; + return Ret | RHS; + } + } + + INLINE ap_private<_AP_W, _AP_S> And(const ap_private<_AP_W, _AP_S>& RHS) const { + return ap_private<_AP_W, _AP_S>(VAL & RHS.VAL); + } + + INLINE ap_private<_AP_W, _AP_S> Or(const ap_private<_AP_W, _AP_S>& RHS) const { + return ap_private<_AP_W, _AP_S>(VAL | RHS.VAL); + } + + INLINE ap_private<_AP_W, _AP_S> Xor(const ap_private<_AP_W, _AP_S>& RHS) const { + return ap_private<_AP_W, _AP_S>(VAL ^ RHS.VAL); + } +#if 1 + template + INLINE typename RType<_AP_W1, _AP_S1>::mult operator*(const ap_private<_AP_W1, _AP_S1>& RHS) const { + if (RType<_AP_W1, _AP_S1>::mult_w <= 64) { + typename RType<_AP_W1, _AP_S1>::mult Result(VAL * RHS.VAL); + return Result; + } else { + typename RType<_AP_W1, _AP_S1>::mult Result = typename RType<_AP_W1, _AP_S1>::mult(*this); + Result *= RHS; + return Result; + } + } +#endif + INLINE ap_private<_AP_W, _AP_S> Mul(const ap_private<_AP_W, _AP_S>& RHS) const { + return ap_private<_AP_W, _AP_S>(VAL * RHS.VAL); + } + + INLINE ap_private<_AP_W, _AP_S> Add(const ap_private<_AP_W, _AP_S>& RHS) const { + return ap_private<_AP_W, _AP_S>(VAL + RHS.VAL); + } + + INLINE ap_private<_AP_W, _AP_S> Sub(const ap_private<_AP_W, _AP_S>& RHS) const { + return ap_private<_AP_W, _AP_S>(VAL - RHS.VAL); + } + +#if 1 + INLINE ap_private& operator&=(uint64_t RHS) { VAL &= RHS; clearUnusedBits(); return *this;} + INLINE ap_private& operator|=(uint64_t RHS) { VAL |= RHS; clearUnusedBits(); return *this;} + INLINE ap_private& operator^=(uint64_t RHS){ VAL ^= RHS; clearUnusedBits(); return *this;} + INLINE ap_private& operator*=(uint64_t RHS){ VAL *= RHS; clearUnusedBits(); return *this; } + INLINE ap_private& operator+=(uint64_t RHS){ VAL += RHS; clearUnusedBits(); return *this;} + INLINE ap_private& operator-=(uint64_t RHS){ VAL -= RHS; clearUnusedBits(); return *this; } + INLINE ap_private operator&(uint64_t RHS) const { return ap_private(VAL & RHS); } + INLINE ap_private operator|(uint64_t RHS) const { return ap_private(VAL | RHS); } + INLINE ap_private operator^(uint64_t RHS) const { return ap_private(VAL ^ RHS); } + INLINE ap_private operator*(uint64_t RHS) const { return ap_private(VAL * RHS); } + INLINE ap_private operator/(uint64_t RHS) const { return ap_private(VAL / RHS); } + INLINE ap_private operator+(uint64_t RHS) const { return ap_private(VAL + RHS); } + INLINE ap_private operator-(uint64_t RHS) const { return ap_private(VAL - RHS); } +#endif + INLINE bool isMinSignedValue() const { + static const uint64_t min_mask = ~(~0ULL << (_AP_W-1)); + return BitWidth == 1 ? VAL == 1 : + (ap_private_ops::isNegative<_AP_W>(*this) && ((min_mask & VAL)==0)); + } + +#if 1 + + template INLINE + typename RType<_AP_W1,_AP_S1>::plus operator+(const ap_private<_AP_W1, _AP_S1>& RHS) const { + if (RType<_AP_W1,_AP_S1>::plus_w <=64) + return typename RType<_AP_W1,_AP_S1>::plus(RType<_AP_W1,_AP_S1>::plus_s ? int64_t(VAL+RHS.VAL):uint64_t(VAL+RHS.VAL)); + typename RType<_AP_W1,_AP_S1>::plus Result=RHS; + Result += VAL; + return Result; + } + + template INLINE + typename RType<_AP_W1,_AP_S1>::minus operator-(const ap_private<_AP_W1, _AP_S1>& RHS) const { + if (RType<_AP_W1,_AP_S1>::minus_w <=64) + return typename RType<_AP_W1,_AP_S1>::minus(int64_t(VAL-RHS.VAL)); + typename RType<_AP_W1,_AP_S1>::minus Result=*this; + Result -= RHS; + return Result; + } +#endif // #if 1 + + INLINE ap_private& flip() { + VAL = (~0ULL^VAL)&mask; + clearUnusedBits(); + return *this; + } + + uint32_t countPopulation() const { return CountPopulation_64(VAL);} + uint32_t countLeadingZeros() const { + int remainder = BitWidth % APINT_BITS_PER_WORD; + int excessBits = (APINT_BITS_PER_WORD - remainder) % APINT_BITS_PER_WORD; + //enum { remainder = BitWidth % APINT_BITS_PER_WORD, excessBits = APINT_BITS_PER_WORD - remainder}; + uint32_t Count = CountLeadingZeros_64(VAL); + if (Count) + Count-=excessBits; + return AESL_std::min(Count, (uint32_t)_AP_W); + } + + /// HiBits - This function returns the high "numBits" bits of this ap_private. + ap_private<_AP_W, _AP_S, 1> getHiBits(uint32_t numBits) const { + ap_private<_AP_W, _AP_S, 1> ret(*this); + ret = (ret)>>(BitWidth - numBits); + return ret; + } + + /// LoBits - This function returns the low "numBits" bits of this ap_private. + ap_private<_AP_W, _AP_S, 1> getLoBits(uint32_t numBits) const { + ap_private<_AP_W, _AP_S, 1> ret((VAL) << (BitWidth - numBits)); + ret = (ret)>>(BitWidth - numBits); + return ret; + //return ap_private(numBits, (VAL << (BitWidth - numBits))>> (BitWidth - numBits)); + } + + ap_private<_AP_W, _AP_S,1>& set(uint32_t bitPosition) { + VAL |= (1ULL << (bitPosition)); + clearUnusedBits(); + return *this; // clearUnusedBits(); + } + + void set() { + VAL = ~0ULL; + clearUnusedBits(); + } + + template + INLINE void set(const ap_private<_AP_W3, false> & val) { + operator = (ap_private<_AP_W3, _AP_S>(val)); + } + + INLINE void set(const ap_private & val) { + operator = (val); + } + + bool operator[](uint32_t bitPosition) const { + return (((1ULL << (bitPosition)) & VAL) != 0); + } + + INLINE void clearUnusedBits(void) { + enum { excess_bits = (_AP_W%APINT_BITS_PER_WORD) ? APINT_BITS_PER_WORD -_AP_W%APINT_BITS_PER_WORD : 0}; + VAL = _AP_S ? ((((int64_t)VAL)<<(excess_bits))>> (excess_bits)) : (excess_bits ? ((VAL)<<(excess_bits))>>(excess_bits) : VAL); + } + + INLINE void clearUnusedBitsToZero(void) { + enum { excess_bits = (_AP_W%APINT_BITS_PER_WORD) ? APINT_BITS_PER_WORD -_AP_W%APINT_BITS_PER_WORD : 0}; + static uint64_t mask = ~0ULL >> (excess_bits); + VAL &= mask; + } + + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1> udiv(const ap_private<_AP_W, _AP_S1>& RHS) const { + return ap_private<_AP_W, _AP_S||_AP_S1>(VAL / RHS.VAL); + } + + INLINE ap_private udiv(uint64_t RHS) const { + return ap_private(VAL / RHS); + } + + /// Signed divide this ap_private by ap_private RHS. + /// @brief Signed division function for ap_private. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1> sdiv(const ap_private<_AP_W, _AP_S1> & RHS) const { + if (isNegative()) + if (RHS.isNegative()) + return (-(*this)).udiv(-RHS); + else + return -((-(*this)).udiv(RHS)); + else if (RHS.isNegative()) + return -(this->udiv(-RHS)); + return this->udiv(RHS); + } + + /// Signed divide this ap_private by ap_private RHS. + /// @brief Signed division function for ap_private. + INLINE ap_private sdiv(int64_t RHS) const { + if (isNegative()) + if (RHS<0) + return (-(*this)).udiv(-RHS); + else + return -((-(*this)).udiv(RHS)); + else if (RHS<0) + return -(this->udiv(-RHS)); + return this->udiv(RHS); + } + + template + INLINE ap_private urem(const ap_private<_AP_W, _AP_S2>& RHS) const { + assert(RHS.VAL != 0 && "Divide by 0"); + return ap_private(VAL%RHS.VAL); + } + + INLINE ap_private urem(uint64_t RHS) const { + assert(RHS != 0 && "Divide by 0"); + return ap_private(VAL%RHS); + } + + /// Signed remainder operation on ap_private. + /// @brief Function for signed remainder operation. + template + INLINE ap_private srem(const ap_private<_AP_W, _AP_S2>& RHS) const { + if (isNegative()) { + ap_private lhs = -(*this); + if (RHS.isNegative()) { + ap_private rhs = -RHS; + return -(lhs.urem(rhs)); + } else + return -(lhs.urem(RHS)); + } else if (RHS.isNegative()) { + ap_private rhs = -RHS; + return this->urem(rhs); + } + return this->urem(RHS); + } + + /// Signed remainder operation on ap_private. + /// @brief Function for signed remainder operation. + INLINE ap_private srem(int64_t RHS) const { + if (isNegative()) + if (RHS<0) + return -((-(*this)).urem(-RHS)); + else + return -((-(*this)).urem(RHS)); + else if (RHS<0) + return this->urem(-RHS); + return this->urem(RHS); + } + + INLINE static void udivrem(const ap_private &LHS, const ap_private &RHS, + ap_private &Quotient, ap_private &Remainder){ + assert(RHS!=0 && "Divide by 0"); + Quotient = LHS.VAl/RHS.VAl; + Remainder = LHS.VAL % RHS.VAL; + } + + INLINE static void udivrem(const ap_private &LHS, uint64_t RHS, + ap_private &Quotient, ap_private &Remainder){ + assert(RHS!=0 && "Divide by 0"); + Quotient = LHS.VAl/RHS; + Remainder = LHS.VAL % RHS; + } + + INLINE static void sdivrem(const ap_private &LHS, const ap_private &RHS, + ap_private &Quotient, ap_private &Remainder) { + if (LHS.isNegative()) { + if (RHS.isNegative()) + ap_private::udivrem(-LHS, -RHS, Quotient, Remainder); + else + ap_private::udivrem(-LHS, RHS, Quotient, Remainder); + Quotient = -Quotient; + Remainder = -Remainder; + } else if (RHS.isNegative()) { + ap_private::udivrem(LHS, -RHS, Quotient, Remainder); + Quotient = -Quotient; + } else { + ap_private::udivrem(LHS, RHS, Quotient, Remainder); + } + } + + INLINE static void sdivrem(const ap_private &LHS, int64_t RHS, + ap_private &Quotient, ap_private &Remainder) { + if (LHS.isNegative()) { + if (RHS<0) + ap_private::udivrem(-LHS, -RHS, Quotient, Remainder); + else + ap_private::udivrem(-LHS, RHS, Quotient, Remainder); + Quotient = -Quotient; + Remainder = -Remainder; + } else if (RHS<0) { + ap_private::udivrem(LHS, -RHS, Quotient, Remainder); + Quotient = -Quotient; + } else { + ap_private::udivrem(LHS, RHS, Quotient, Remainder); + } + } + + template INLINE bool eq(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return (*this) == RHS; + } + + template INLINE bool ne(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return !((*this) == RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// the validity of the less-than relationship. + /// @returns true if *this < RHS when both are considered unsigned. + /// @brief Unsigned less than comparison + template INLINE bool ult(const ap_private<_AP_W1, _AP_S1, 1>& RHS) const { + uint64_t lhsZext = ((uint64_t(VAL)) << (64-_AP_W)) >> (64-_AP_W); + uint64_t rhsZext = ((uint64_t(RHS.VAL)) << (64-_AP_W1)) >> (64-_AP_W1); + return lhsZext < rhsZext; + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the less-than relationship. + /// @returns true if *this < RHS when both are considered signed. + /// @brief Signed less than comparison + template INLINE bool slt(const ap_private<_AP_W1, _AP_S1, 1>& RHS) const { + int64_t lhsSext = ((int64_t(VAL)) << (64-_AP_W)) >> (64-_AP_W); + int64_t rhsSext = ((int64_t(RHS.VAL)) << (64-_AP_W1)) >> (64-_AP_W1); + return lhsSext < rhsSext; + } + + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// validity of the less-or-equal relationship. + /// @returns true if *this <= RHS when both are considered unsigned. + /// @brief Unsigned less or equal comparison + template INLINE bool ule(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return ult(RHS) || eq(RHS); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the less-or-equal relationship. + /// @returns true if *this <= RHS when both are considered signed. + /// @brief Signed less or equal comparison + template INLINE bool sle(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return slt(RHS) || eq(RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// the validity of the greater-than relationship. + /// @returns true if *this > RHS when both are considered unsigned. + /// @brief Unsigned greather than comparison + template INLINE bool ugt(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return !ult(RHS) && !eq(RHS); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// the validity of the greater-than relationship. + /// @returns true if *this > RHS when both are considered signed. + /// @brief Signed greather than comparison + template INLINE bool sgt(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return !slt(RHS) && !eq(RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// validity of the greater-or-equal relationship. + /// @returns true if *this >= RHS when both are considered unsigned. + /// @brief Unsigned greater or equal comparison + template INLINE bool uge(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return !ult(RHS); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the greater-or-equal relationship. + /// @returns true if *this >= RHS when both are considered signed. + /// @brief Signed greather or equal comparison + template INLINE bool sge(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return !slt(RHS); + } + + INLINE ap_private abs() const { + if (isNegative()) + return -(*this); + return *this; + } + + ap_private<_AP_W, false> get() const { + ap_private<_AP_W,false> ret(*this); + return ret; + } + + INLINE static uint32_t getBitsNeeded(const char* str, uint32_t slen, uint8_t radix) { + return _AP_W; + } + + INLINE uint32_t getActiveBits() const { + uint32_t bits=_AP_W - countLeadingZeros(); + return bits?bits:1; + } + + INLINE double roundToDouble(bool isSigned=false) const { + const static uint64_t mask = ~0ULL << (APINT_BITS_PER_WORD - _AP_W); + return double(VAL); + } + + INLINE unsigned length() const { return _AP_W; } + + /*Reverse the contents of ap_private instance. I.e. LSB becomes MSB and vise versa*/ + INLINE ap_private& reverse () { + for (int i = 0; i < _AP_W/2; ++i) { + bool tmp = operator[](i); + if (operator[](_AP_W - 1 - i)) + set(i); + else + clear(i); + if (tmp) + set(_AP_W - 1 - i); + else + clear(_AP_W - 1 - i); + } + clearUnusedBits(); + return *this; + } + + /*Return true if the value of ap_private instance is zero*/ + INLINE bool iszero () const { + return isMinValue(); + } + + /* x < 0 */ + INLINE bool sign () const { + if (isNegative()) + return true; + return false; + } + + /* x[i] = !x[i] */ + INLINE void invert (int i) { + assert( i >= 0 && "Attempting to read bit with negative index"); + assert( i < _AP_W && "Attempting to read bit beyond MSB"); + flip(i); + } + + /* x[i] */ + INLINE bool test (int i) const { + assert( i >= 0 && "Attempting to read bit with negative index"); + assert( i < _AP_W && "Attempting to read bit beyond MSB"); + return operator[](i); + } + + //This is used for sc_lv and sc_bv, which is implemented by sc_uint + //Rotate an ap_private object n places to the left + INLINE void lrotate(int n) { + assert( n >= 0 && "Attempting to shift negative index"); + assert( n < _AP_W && "Shift value larger than bit width"); + operator = (shl(n) | lshr(_AP_W - n)); + } + + //This is used for sc_lv and sc_bv, which is implemented by sc_uint + //Rotate an ap_private object n places to the right + INLINE void rrotate(int n) { + assert( n >= 0 && "Attempting to shift negative index"); + assert( n < _AP_W && "Shift value larger than bit width"); + operator = (lshr(n) | shl(_AP_W - n)); + } + + //Set the ith bit into v + INLINE void set (int i, bool v) { + assert( i >= 0 && "Attempting to write bit with negative index"); + assert( i < _AP_W && "Attempting to write bit beyond MSB"); + v ? set(i) : clear(i); + } + + //Set the ith bit into v + INLINE void set_bit (int i, bool v) { + assert( i >= 0 && "Attempting to write bit with negative index"); + assert( i < _AP_W && "Attempting to write bit beyond MSB"); + v ? set(i) : clear(i); + } + + //Get the value of ith bit + INLINE bool get_bit (int i) const { + assert( i >= 0 && "Attempting to read bit with negative index"); + assert( i < _AP_W && "Attempting to read bit beyond MSB"); + return operator [](i); + } + + //complements every bit + INLINE void b_not() { + flip(); + } + + //Binary Arithmetic + //----------------------------------------------------------- +#define OP_BIN_AP(Sym,Rty, Fun) \ + template \ + INLINE \ + typename RType<_AP_W2,_AP_S2>::Rty \ + operator Sym (const ap_private<_AP_W2,_AP_S2>& op) const { \ + typename RType<_AP_W2,_AP_S2>::Rty lhs(*this); \ + typename RType<_AP_W2,_AP_S2>::Rty rhs(op); \ + return lhs.Fun(rhs); \ + } \ + + ///Bitwise and, or, xor + //OP_BIN_AP(&,logic, And) + //OP_BIN_AP(|,logic, Or) + //OP_BIN_AP(^,logic, Xor) + +#undef OP_BIN_AP + template + INLINE typename RType<_AP_W2,_AP_S2>::div + operator / (const ap_private<_AP_W2,_AP_S2>&op) const { + ap_private lhs=ap_private(*this); + ap_private rhs=ap_private(op); + return typename RType<_AP_W2,_AP_S2>::div((_AP_S||_AP_S2)?lhs.sdiv(rhs):lhs.udiv(rhs)); + } + + + template + INLINE typename RType<_AP_W2,_AP_S2>::mod + operator % (const ap_private<_AP_W2,_AP_S2>&op) const { + ap_private lhs=*this; + ap_private rhs=op; + typename RType<_AP_W2,_AP_S2>::mod res = typename RType<_AP_W2,_AP_S2>::mod (_AP_S?lhs.srem(rhs):lhs.urem(rhs)); + return res; + } + + +#define OP_ASSIGN_AP_2(Sym) \ + template \ + INLINE ap_private<_AP_W, _AP_S>& operator Sym##=(const ap_private<_AP_W2,_AP_S2>& op) \ + { \ + *this=operator Sym (op); \ + return *this; \ + } \ + + OP_ASSIGN_AP_2(/) + OP_ASSIGN_AP_2(%) +#undef OP_ASSIGN_AP_2 + + ///Bitwise assign: and, or, xor + //------------------------------------------------------------- + // OP_ASSIGN_AP(&) + // OP_ASSIGN_AP(^) + // OP_ASSIGN_AP(|) +#undef OP_ASSIGN_AP +#if 1 + + template + INLINE ap_private<_AP_W, _AP_S> + operator << (const ap_private<_AP_W2, _AP_S2>& op2) const { + uint32_t sh=op2.to_uint(); + return *this << sh; + } + + INLINE ap_private<_AP_W, _AP_S> + operator << (uint32_t sh) const { + return shl(sh); + } + +#endif + + template + INLINE ap_private<_AP_W, _AP_S> + operator >> (const ap_private<_AP_W2, _AP_S2>& op2) const { + uint32_t sh = op2.to_uint(); + return *this >> sh; + } + + INLINE ap_private<_AP_W, _AP_S> + operator >>(uint32_t sh) const { + ap_private<_AP_W, _AP_S> r(*this); + bool overflow=(sh>=_AP_W); + bool neg_v=r.isNegative(); + if(_AP_S) { + if(overflow) + neg_v?r.set():r.clear(); + else + return r.ashr(sh); + } else { + if(overflow) + r.clear(); + else + return r.lshr(sh); + } + return r; + } + + ///Shift assign + //------------------------------------------------------------------ +#define OP_ASSIGN_AP_3_SINGLE(Sym) \ + template \ + INLINE ap_private<_AP_W, _AP_S>& operator Sym##=(const ap_private<_AP_W2,_AP_S2>& op) \ + { \ + *this=operator Sym (op.getVal()); \ + return *this; \ + } + OP_ASSIGN_AP_3_SINGLE(>>) +#undef OP_ASSIGN_AP_3_SINGLE + + ///Comparisons + //----------------------------------------------------------------- + template + INLINE bool operator != (const ap_private<_AP_W2, _AP_S2, 1>& op) const { + return !(*this==op); + } + + template + INLINE bool operator > (const ap_private<_AP_W2, _AP_S2, 1>& op) const { + return op < *this; + } + + template + INLINE bool operator <= (const ap_private<_AP_W2, _AP_S2, 1>& op) const { + return !(*this>op); + } + + template + INLINE bool operator < (const ap_private<_AP_W2, _AP_S2, 1>& op) const { + enum { _AP_MAX_W = AP_MAX(_AP_W+(_AP_S||_AP_S2),_AP_W2+(_AP_S||_AP_S2))}; + ap_private<_AP_MAX_W, _AP_S> lhs(*this); + ap_private<_AP_MAX_W, _AP_S2> rhs(op); + if (_AP_S == _AP_S2) + return _AP_S?lhs.slt(rhs):lhs.ult(rhs); + else if (_AP_W < 32 && _AP_W2 < 32) + return lhs.slt(rhs); + else + if (_AP_S) + if (_AP_W2 >= _AP_W) + return lhs.ult(rhs); + else + return lhs.slt(rhs); + else + if (_AP_W >= _AP_W2) + return lhs.ult(rhs); + else + return lhs.slt(rhs); + } + + template + INLINE bool operator >=(const ap_private<_AP_W2, _AP_S2, 1>& op) const { + return !(*this + INLINE bool operator == (const ap_private<_AP_W2, _AP_S2, _AP_N2>& op) const { + return op == *this; + } + + template + INLINE bool operator != (const ap_private<_AP_W2, _AP_S2, _AP_N2>& op) const { + return !(op==*this); + } + + template + INLINE bool operator > (const ap_private<_AP_W2, _AP_S2, _AP_N2>& op) const { + return op < (*this); + } + + template + INLINE bool operator <= (const ap_private<_AP_W2, _AP_S2, _AP_N2>& op) const { + return op >= *this; + } + + template + INLINE bool operator <(const ap_private<_AP_W2, _AP_S2, _AP_N2>& op) const { + return op > *this; + } + + template + INLINE bool operator >=(const ap_private<_AP_W2,_AP_S2,_AP_N2>& op) const { + return op <= *this; + } + ///Bit and Part Select + //-------------------------------------------------------------- + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (int Hi, int Lo) { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (int Hi, int Lo) const { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(const_cast*>(this), Hi, Lo); + } + + INLINE ap_range_ref<_AP_W,_AP_S> + range (int Hi, int Lo) const { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>((const_cast*> (this)), Hi, Lo); + } + + INLINE ap_range_ref<_AP_W,_AP_S> + range (int Hi, int Lo) { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + range (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + range (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) const { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(const_cast(this), Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) const { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + return this->range(Hi, Lo); + } + + + INLINE ap_bit_ref<_AP_W,_AP_S> operator [] (uint32_t index) { + assert(index >= 0&&"Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S> (*this, (int)index); + } + + template + INLINE ap_bit_ref<_AP_W,_AP_S> operator [] (const ap_private<_AP_W2,_AP_S2> &index) { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S>( *this, index.to_int() ); + } + + template + INLINE bool operator [] (const ap_private<_AP_W2,_AP_S2>& index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + ap_bit_ref<_AP_W,_AP_S> br =operator [] (index); + return br.to_bool(); + } + + INLINE ap_bit_ref<_AP_W,_AP_S> bit (int index) { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S>( *this, index ); + } + + template + INLINE ap_bit_ref<_AP_W,_AP_S> bit (const ap_private<_AP_W2,_AP_S2> &index) { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W &&"Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S>( *this, index.to_int() ); + } + + INLINE bool bit (int index) const { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + ap_bit_ref<_AP_W,_AP_S> br(const_cast*>(this), index); + return br.to_bool(); + } + + template + INLINE bool bit (const ap_private<_AP_W2,_AP_S2>& index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + ap_bit_ref<_AP_W,_AP_S> br = bit(index); + return br.to_bool(); + } + + template + INLINE ap_concat_ref<_AP_W,ap_private<_AP_W, _AP_S>,_AP_W2,ap_private<_AP_W2,_AP_S2> > concat(const ap_private<_AP_W2,_AP_S2>& a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_private<_AP_W2,_AP_S2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W,ap_private<_AP_W, _AP_S>,_AP_W2,ap_private<_AP_W2,_AP_S2> > concat(ap_private<_AP_W2,_AP_S2>& a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_private<_AP_W2,_AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (const ap_private<_AP_W2, _AP_S2>& a2) const { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(const_cast& >(*this), const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (const ap_private<_AP_W2, _AP_S2>& a2) { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(*this, const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (ap_private<_AP_W2, _AP_S2>& a2) const { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(const_cast& >(*this), a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (ap_private<_AP_W2, _AP_S2>& a2) { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > + operator, (const ap_range_ref<_AP_W2, _AP_S2> &a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, + ap_range_ref<_AP_W2, _AP_S2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > + operator, (ap_range_ref<_AP_W2, _AP_S2> &a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, + ap_range_ref<_AP_W2, _AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, ap_bit_ref<_AP_W2, _AP_S2> > + operator, (const ap_bit_ref<_AP_W2, _AP_S2> &a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, + ap_bit_ref<_AP_W2, _AP_S2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, ap_bit_ref<_AP_W2, _AP_S2> > + operator, (ap_bit_ref<_AP_W2, _AP_S2> &a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, + ap_bit_ref<_AP_W2, _AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > + operator, (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > + operator, (ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) const { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) const { + return ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, a2); + } + + template + INLINE ap_private + operator & (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) { + return *this & a2.get(); + } + + template + INLINE ap_private + operator | (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) { + return *this | a2.get(); + } + + template + INLINE ap_private + operator ^ (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) { + return *this ^ a2.get(); + } + + + //Reduce operation + //----------------------------------------------------------- + INLINE bool and_reduce() const { + return (VAL & mask) == mask; + } + + INLINE bool nand_reduce() const { + return (VAL & mask) != mask; + } + + INLINE bool or_reduce() const { + return (bool)VAL; + } + + INLINE bool nor_reduce() const { + return VAL==0; + } + + INLINE bool xor_reduce() const { + unsigned int i=countPopulation(); + return (i%2)?true:false; + } + + INLINE bool xnor_reduce() const { + unsigned int i=countPopulation(); + return (i%2)?false:true; + } + + INLINE std::string to_string(uint8_t radix=2, bool sign=false) const { + return toString(radix, radix==10?_AP_S:sign); + } +}; +template +std::string ap_private<_AP_W, _AP_S, 1>::toString(uint8_t radix, bool wantSigned) const { + assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) && + "Radix should be 2, 8, 10, or 16!"); + static const char *digits[] = { + "0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f" + }; + std::string result; + if (radix != 10) { + // For the 2, 8 and 16 bit cases, we can just shift instead of divide + // because the number of bits per digit (1,3 and 4 respectively) divides + // equaly. We just shift until there value is zero. + + // First, check for a zero value and just short circuit the logic below. + if (*this == (uint64_t)(0)) + result = "0"; + else { + ap_private<_AP_W, false, 1> tmp(*this); + size_t insert_at = 0; + if (wantSigned && isNegative()) { + // They want to print the signed version and it is a negative value + // Flip the bits and add one to turn it into the equivalent positive + // value and put a '-' in the result. + tmp.flip(); + tmp++; + result = "-"; + insert_at = 1; + } + // Just shift tmp right for each digit width until it becomes zero + uint32_t shift = (radix == 16 ? 4 : (radix == 8 ? 3 : 1)); + uint64_t mask = radix - 1; + ap_private<_AP_W, false, 1> zero(0); + while (tmp.ne(zero)) { + unsigned digit = (unsigned)(tmp.VAL & mask); + result.insert(insert_at, digits[digit]); + tmp = tmp.lshr(shift); + } + } + return result; + } + + ap_private<_AP_W, false, 1> tmp(*this); + ap_private<6, false, 1> divisor(radix); + ap_private<_AP_W, _AP_S, 1> zero(0); + size_t insert_at = 0; + if (wantSigned && isNegative()) { + // They want to print the signed version and it is a negative value + // Flip the bits and add one to turn it into the equivalent positive + // value and put a '-' in the result. + tmp.flip(); + tmp++; + result = "-"; + insert_at = 1; + } + if (tmp == ap_private<_AP_W, false, 1>(0ULL)) + result = "0"; + else while (tmp.ne(zero)) { + ap_private<_AP_W, false, 1> APdigit = tmp%divisor; + ap_private<_AP_W, false, 1> tmp2 = tmp/divisor; + uint32_t digit = (uint32_t)(APdigit.getZExtValue()); + assert(digit < radix && "divide failed"); + result.insert(insert_at,digits[digit]); + tmp = tmp2; + } + return result; + +} + +#endif /* #ifndef LLVM_SUPPORT_MATHEXTRAS_H */ \ No newline at end of file diff --git a/hls_2018/router_05/main.cpp b/hls_2018/router_05/main.cpp new file mode 100755 index 0000000..60f08ea --- /dev/null +++ b/hls_2018/router_05/main.cpp @@ -0,0 +1,99 @@ +/** + * main.cpp + * + * for Vivado HLS + */ + +#ifdef SOFTWARE +#include "ap_int.h" +#else +#include +#endif + +#ifdef CALCTIME +#include +#include +#endif + +#include "router.hpp" + +#define PRINT_SOLUTION + + +int main(int argc, char *argv[]) { + using namespace std; + + // Test data // + // NL_Q00.txt + //char boardstr[BOARDSTR_SIZE] = "X10Y05Z3L0000107041L0004107002L0102102021L0900100003"; + // NL_Q06.txt + char boardstr[BOARDSTR_SIZE] = "X10Y18Z2L0900109002L0901105012L0902103052L0903103062L0904100102L0905106012L0906109022L0717109102L0808109112L0017209172L0401200072L0912208152L0009201092L0709209092L0901206052L0309204092L0701209072L0101201022L0011202152L0016202162"; + // NL_Q08.txt + //char boardstr[BOARDSTR_SIZE] = "X17Y20Z2L0000103022L1603115052L0916107032L0302108012L1104111042L1002100002L0919116162L1616113182L1001115012L0500201182L1603213152L0600210022"; + char boardstr_high[BOARDSTR_SIZE] = {}; + + // Read boardstr from command line + if (1 < argc) { + // From stdin + if(argv[1][0]!='X') + { + char* c_p=fgets(boardstr, BOARDSTR_SIZE, stdin); + int length=strlen(c_p); + boardstr[length-1]=0; + } + else + { + strcpy(boardstr, argv[1]); + } + } + + // Seed value + int seed = 12345; + if (2 < argc) { + seed = atoi(argv[2]); + } + +#ifdef PRINT_SOLUTION + int size_x = (boardstr[1] - '0') * 10 + (boardstr[2] - '0'); + int size_y = (boardstr[4] - '0') * 10 + (boardstr[5] - '0'); + int size_z = (boardstr[7] - '0'); +#endif + + // Solver + ap_int<32> status; + clock_t clock_start, clock_done; + clock_start = clock(); + bool result = pynqrouter(boardstr, boardstr_high, seed, &status); + clock_done = clock(); + if (result) { + cout << endl << "Test Passed!" << endl; + } else { + cout << endl << "Test Failed!" << endl; + } + cout << "status = " << (int)status << endl; + cout << "elapsed = " << ((double)(clock_done - clock_start) / CLOCKS_PER_SEC) << endl << endl; + +#ifdef PRINT_SOLUTION + cout << "SOLUTION" << endl; + cout << "========" << endl; + cout << "SIZE " << size_x << "X" << size_y << "X" << size_z << endl; + for (int z = 0; z < size_z; z++) { + cout << "LAYER " << (z + 1) << endl; + for (int y = 0; y < size_y; y++) { + for (int x = 0; x < size_x; x++) { + if (x != 0) { + cout << ","; + } + int i = ((x * MAX_WIDTH + y) << BITWIDTH_Z) | z; + unsigned int num = (unsigned char)(boardstr[i]) + ((unsigned char)(boardstr_high[i]) << 8); + cout << setfill('0') << setw(5) << right << num; + //cout << (unsigned int)(unsigned char)(boardstr[i]); + } + cout << endl; + } + } +#endif + + return 0; +} + diff --git a/hls_2018/router_05/router.cpp b/hls_2018/router_05/router.cpp new file mode 100755 index 0000000..d086860 --- /dev/null +++ b/hls_2018/router_05/router.cpp @@ -0,0 +1,457 @@ +/** + * router.cpp + * + * for Vivado HLS +*/ + +#ifdef SOFTWARE +#include "ap_int.h" +#else +#include +#endif + +#include "./router.hpp" + + + +static ap_uint<32> lfsr; + +void lfsr_random_init(ap_uint<32> seed) { + + lfsr = seed; +} + +ap_uint<32> lfsr_random() { + + bool b_32 = lfsr.get_bit(32-32); + bool b_22 = lfsr.get_bit(32-22); + bool b_2 = lfsr.get_bit(32-2); + bool b_1 = lfsr.get_bit(32-1); + bool new_bit = b_32 ^ b_22 ^ b_2 ^ b_1; + lfsr = lfsr >> 1; + lfsr.set_bit(31, new_bit); + + return lfsr.to_uint(); +} + + + +// Global values +static ap_uint<7> size_x; // X +static ap_uint<7> size_y; // Y +static ap_uint<4> size_z; // Z + +static ap_uint line_num = 0; // #Lines + +bool pynqrouter(char boardstr[BOARDSTR_SIZE], char boardstr_high[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *status) { +#pragma HLS INTERFACE s_axilite port=boardstr bundle=AXI4LS +#pragma HLS INTERFACE s_axilite port=boardstr_high bundle=AXI4LS +#pragma HLS INTERFACE s_axilite port=seed bundle=AXI4LS +#pragma HLS INTERFACE s_axilite port=status bundle=AXI4LS +#pragma HLS INTERFACE s_axilite port=return bundle=AXI4LS + + // status(0:Solved, 1:Not solved) + *status = -1; + + // board + ap_int board[MAX_CELLS]; // -1024 ~ 1023 (Negative values mean terminals) + INIT_BOARD_ARRAY: + for (ap_uint i = 0; i < (ap_uint)(BOARDSTR_SIZE); i++) { + board[i] = 0; + } + + + // ================================ + // (Step.0) Initialization (BEGIN) + // ================================ + + // Note: Loop counter -> need an extra bit (for condition determination) + + /// Parse /// + size_x = (boardstr[1] - '0') * 10 + (boardstr[2] - '0'); + size_y = (boardstr[4] - '0') * 10 + (boardstr[5] - '0'); + size_z = (boardstr[7] - '0'); + + INIT_BOARDS: + for (ap_uint idx = 8; idx < (ap_uint)(BOARDSTR_SIZE); idx+=11) { + + // NULL-terminated + if (boardstr[idx] == 0) break; + + line_num++; + + // Start & Goal of each line + ap_uint<7> s_x = (boardstr[idx+1] - '0') * 10 + (boardstr[idx+2] - '0'); + ap_uint<7> s_y = (boardstr[idx+3] - '0') * 10 + (boardstr[idx+4] - '0'); + ap_uint<3> s_z = (boardstr[idx+5] - '0') - 1; + ap_uint<7> g_x = (boardstr[idx+6] - '0') * 10 + (boardstr[idx+7] - '0'); + ap_uint<7> g_y = (boardstr[idx+8] - '0') * 10 + (boardstr[idx+9] - '0'); + ap_uint<3> g_z = (boardstr[idx+10] - '0') - 1; + + ap_uint start_id = (((ap_uint)s_x * MAX_WIDTH + (ap_uint)s_y) << BITWIDTH_Z) | (ap_uint)s_z; + ap_uint goal_id = (((ap_uint)g_x * MAX_WIDTH + (ap_uint)g_y) << BITWIDTH_Z) | (ap_uint)g_z; + board[start_id] = -line_num; + board[goal_id] = -line_num; + } + + // For each line + ap_uint connected_line_num = 0; + bool connected[MAX_LINES]; + INIT_CONNECTED: + for (ap_uint i = 1; i <= (ap_uint)(line_num); i++) { + connected[i] = false; + } + + lfsr_random_init(seed); + + // ================================ + // (Step.0) Initialization (END) + // ================================ + + + // ================================ + // (Step.2) Rip-up Routing (BEGIN) + // ================================ + +#ifdef DEBUG_PRINT + cout << "Routing ..." << endl; +#endif + + bool solved = false; + + ROUTING: + for (ap_uint<16> round = 0; round < 32768 ; round++) { +#pragma HLS LOOP_TRIPCOUNT min=1 max=32768 + + // Target line + ap_uint target = lfsr_random() % line_num + 1; + +#ifdef DEBUG_PRINT + cout << "(round " << round << ") LINE #" << (int)target << " " << lfsr_random() << endl; +#endif + + if (connected[target]) continue; + + if (connectable(board, target, 0)) { + connected[target] = true; connected_line_num++; + } + else { + ap_uint<16> j; + for (j = 0; j < 10000; j++) { + + // Ripped-up line + ap_uint rip_up = lfsr_random() % line_num + 1; + if (connectable(board, target, rip_up)) { + connected[target] = true; + connected[rip_up] = false; + break; + } + } + if (j == 10000) break; + } + if (connected_line_num == line_num) { + solved = true; + break; + } + } + + // Not solved + if (!solved) { + *status = 1; return false; + } + + // ================================ + // (Step.2) Rip-up Routing (END) + // ================================ + + + // ================================ + // (Step.3) Output (BEGIN) + // ================================ + +#ifdef DEBUG_PRINT + cout << "Output ..." << endl; +#endif + + // Init: Blank = 0 + OUTPUT_INIT: + for (ap_uint i = 0; i < (ap_uint)(MAX_CELLS); i++) { + + if (board[i] < 0) { + boardstr[i] = (unsigned char)(((-1) * board[i])); + boardstr_high[i] = (unsigned char)(((-1) * board[i]) >> 8); + } + else { + boardstr[i] = (unsigned char)((board[i])); + boardstr_high[i] = (unsigned char)((board[i]) >> 8); + } + } + + // ================================ + // (Step.3) Output (END) + // ================================ + + *status = 0; return true; +} + + +// ================================ // +// For Routing +// ================================ // + +bool inside_board(ap_uint cell_id) { + + ap_uint<13> cell_xy = (ap_uint<13>)(cell_id >> BITWIDTH_Z); + ap_uint<7> cell_x = (ap_uint<7>)(cell_xy / MAX_WIDTH); + ap_uint<7> cell_y = (ap_uint<7>)(cell_xy - cell_x * MAX_WIDTH); + ap_uint<3> cell_z = (ap_uint<3>)(cell_id & BITMASK_Z); + + bool ret = false; + if (cell_x < size_x && cell_y < size_y && cell_z < size_z) { + ret = true; + } + else { + ret = false; + } + + return ret; +} + +bool connectable(ap_int board[MAX_CELLS], ap_uint target, ap_uint rip_up) { + + ap_uint<2> avail[MAX_CELLS]; + ap_uint prev[MAX_CELLS]; + + ap_uint start_id = 65535, goal_id = 65535; + for (ap_uint i = 0; i < (ap_uint)(MAX_CELLS); i++) { + + if (!inside_board(i)) continue; + + prev[i] = 65535; // init. + + if (board[i] == target * (-1)) { + if (start_id == 65535) { + start_id = i; + avail[i] = 3; + } + else { + goal_id = i; + avail[i] = 0; + } + } + else if (board[i] == 0 || board[i] == rip_up || board[i] == target) { + avail[i] = 1; + } + else { + avail[i] = 0; + } + } + + bool try_connect = available(avail, prev, start_id, goal_id); + if (try_connect) { + if (rip_up > 0) { + remove_line(board, rip_up); + } + // Connect line for target + ap_uint id = prev[goal_id]; + BACKTRACK: + while (id != start_id) { + board[id] = target; id = prev[id]; + } + } + + return try_connect; +} + +void remove_line(ap_int board[MAX_CELLS], ap_uint rip_up) { + + for (ap_uint i = 0; i < (ap_uint)(MAX_CELLS); i++) { + + if (!inside_board(i)) continue; + if (board[i] == rip_up) board[i] = 0; + } +} + +bool available(ap_uint<2> avail[MAX_CELLS], ap_uint prev[MAX_CELLS], ap_uint start_id, ap_uint goal_id) { + + // Priority queue (Circular list) + ap_uint top = 1, bottom = 0; + bool is_empty = true; + ap_uint qu_nodes[MAX_PQ]; + + // Point of goal terminal + ap_uint<13> goal_xy = (ap_uint<13>)(goal_id >> BITWIDTH_Z); + 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<3> goal_z = (ap_uint<3>)(goal_id & BITMASK_Z); + + qu_push(qu_nodes, start_id, &top, &bottom, &is_empty); + + bool complete = false; + + SEARCH_QUEUE: + while (!is_empty) { +#pragma HLS LOOP_TRIPCOUNT min=1 max=1000 +#pragma HLS LOOP_FLATTEN off + + ap_uint src_id; // target cell + qu_pop(qu_nodes, &src_id, &top, &bottom, &is_empty); + + + // End routing + //if (avail[src_id] == -1) { complete = true; break; } // goal + + if (avail[src_id] != 1 && avail[src_id] != 3) continue; // Keep searching + + // Point of target cell + ap_uint<13> src_xy = (ap_uint<13>)(src_id >> BITWIDTH_Z); + 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<3> src_z = (ap_uint<3>)(src_id & BITMASK_Z); + + ap_uint<3> isbranch = 0; + ap_uint tmp_dest_id = 65535; + // Search adjacent cells (1) + SEARCH_ADJACENTS_1: + for (ap_uint<3> a = 0; a < 6; a++) { + ap_int<8> dest_x = (ap_int<8>)src_x; // Min: -1, Max: 72 (Signed 8bit) + ap_int<8> dest_y = (ap_int<8>)src_y; // Min: -1, Max: 72 (Signed 8bit) + ap_int<5> dest_z = (ap_int<5>)src_z; // Min: -1, Max: 8 (Signed 5bit) + if (a == 0) { dest_x -= 1; } + if (a == 1) { dest_x += 1; } + if (a == 2) { dest_y -= 1; } + if (a == 3) { dest_y += 1; } + if (a == 4) { dest_z -= 1; } + if (a == 5) { dest_z += 1; } + + // Inside the board ? // + if (0 <= dest_x && dest_x < (ap_int<8>)size_x && 0 <= dest_y && dest_y < (ap_int<8>)size_y && 0 <= dest_z && dest_z < (ap_int<5>)size_z) { + + // Adjacent cell + ap_uint dest_id = (((ap_uint)dest_x * MAX_WIDTH + (ap_uint)dest_y) << BITWIDTH_Z) | (ap_uint)dest_z; + if (avail[dest_id] >= 2) { + isbranch++; + tmp_dest_id = dest_id; + } + } + } + if (isbranch > 1) { avail[src_id] = 0; continue; } + if (avail[src_id] == 1) { + avail[src_id] = 2; + prev[src_id] = tmp_dest_id; + } + + ap_uint<3> p = 0; + ap_uint<3> search_order[6]; + if (src_x > goal_x) { + search_order[p++] = 0; // To src_x-- + } + else { + search_order[5+p] = 0; + } + if (src_y > goal_y) { + search_order[p++] = 1; // To src_y-- + } + else { + search_order[4+p] = 1; + } + if (src_z > goal_z) { + search_order[p++] = 2; // To src_z-- + } + else { + search_order[3+p] = 2; + } + if (src_x < goal_x) { + search_order[p++] = 3; // To src_x++ + } + else { + search_order[2+p] = 3; + } + if (src_y < goal_y) { + search_order[p++] = 4; // To src_y++ + } + else { + search_order[1+p] = 4; + } + if (src_z < goal_z) { + search_order[p++] = 5; // To src_z++ + } + else { + search_order[0+p] = 5; + } + + ap_uint<3> j, t; + SHUFFLE_1: + for (ap_uint<3> a = 0; a < p; a++) { + j = lfsr_random() % p; + t = search_order[a]; + search_order[a] = search_order[j]; + search_order[j] = t; + } + SHUFFLE_2: + for (ap_uint<3> a = p; a < 6; a++) { + j = lfsr_random() % (6-p) + p; + t = search_order[a]; + search_order[a] = search_order[j]; + search_order[j] = t; + } + + //cout << "(" << src_x << ", " << src_y << ", " << src_z << ")->"; + //cout << "(" << goal_x << ", " << goal_y << ", " << goal_z << "): p = " << p << " ["; + //for (ap_uint<3> a = 0; a < 6; a++) { + // cout << search_order[a]; + // if (a != 5) cout << " "; + //} + //cout << "]" << endl; + + // Search adjacent cells (2) + SEARCH_ADJACENTS_2: + for (ap_uint<3> a = 0; a < 6; a++) { + ap_int<8> dest_x = (ap_int<8>)src_x; // Min: -1, Max: 72 (Signed 8bit) + ap_int<8> dest_y = (ap_int<8>)src_y; // Min: -1, Max: 72 (Signed 8bit) + ap_int<5> dest_z = (ap_int<5>)src_z; // Min: -1, Max: 8 (Signed 5bit) + if (search_order[5-a] == 0) { dest_x -= 1; } + if (search_order[5-a] == 1) { dest_y -= 1; } + if (search_order[5-a] == 2) { dest_z -= 1; } + if (search_order[5-a] == 3) { dest_x += 1; } + if (search_order[5-a] == 4) { dest_y += 1; } + if (search_order[5-a] == 5) { dest_z += 1; } + + // Inside the board ? // + if (0 <= dest_x && dest_x < (ap_int<8>)size_x && 0 <= dest_y && dest_y < (ap_int<8>)size_y && 0 <= dest_z && dest_z < (ap_int<5>)size_z) { + + // Adjacent cell + ap_uint dest_id = (((ap_uint)dest_x * MAX_WIDTH + (ap_uint)dest_y) << BITWIDTH_Z) | (ap_uint)dest_z; + if (dest_id == goal_id) { + prev[dest_id] = src_id; + complete = true; + } + qu_push(qu_nodes, dest_id, &top, &bottom, &is_empty); + } + } + if (complete) break; + } + + return complete; +} + +// Queue push (Enqueue) +// First In Last Out +void qu_push(ap_uint qu_nodes[MAX_PQ], ap_uint id, ap_uint *top, ap_uint *bottom, bool *is_empty) { +#pragma HLS INLINE + + (*bottom)++; + if ((*bottom) == (*top) && !(*is_empty)) { (*top)++; } // Queue is full -> First element is automatically removed + qu_nodes[(*bottom)] = id; + *is_empty = false; +} + +// Queue pop (Dequeue) +// First In Last Out +void qu_pop(ap_uint qu_nodes[MAX_PQ], ap_uint *id, ap_uint *top, ap_uint *bottom, bool *is_empty) { +#pragma HLS INLINE + + *id = qu_nodes[(*bottom)]; + (*bottom)--; + if (((*bottom)-(*top)+1) == 0) { *is_empty = true; } +} diff --git a/hls_2018/router_05/router.hpp b/hls_2018/router_05/router.hpp new file mode 100755 index 0000000..08d9363 --- /dev/null +++ b/hls_2018/router_05/router.hpp @@ -0,0 +1,53 @@ +/** + * router.hpp + * + * for Vivado HLS + */ + +#ifndef __ROUTER_HPP__ +#define __ROUTER_HPP__ + +#ifdef SOFTWARE +#include "ap_int.h" +#else +#include +#endif + +//#define DEBUG_PRINT // for debug + +#ifdef DEBUG_PRINT +using namespace std; +#endif + +// Parameters +#define MAX_WIDTH 72 // Max of X, Y +#define BITWIDTH_XY 13 +#define BITMASK_XY 65528 // 1111 1111 1111 1000 +#define MAX_LAYER 8 // Max of Z +#define BITWIDTH_Z 3 +#define BITMASK_Z 7 // 0000 0000 0000 0111 + +#define MAX_CELLS 41472 // Max #cells (16bit) +#define MAX_LINES 32768 // Max #lines (15bit) +#define MAX_PQ 16384 // Queue size (14bit) +#define MAX_BUFFER 16384 // Line buffer size (14bit) +#define CELL_BIT 16 +#define LINE_BIT 15 +#define PQ_BIT 14 +#define BUFF_BIT 14 + +#define BOARDSTR_SIZE 41472 // Size of I/O + +// For random num generation +void lfsr_random_init(ap_uint<32> seed); +ap_uint<32> lfsr_random(); + +bool pynqrouter(char boardstr[BOARDSTR_SIZE], char boardstr_high[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *status); +bool inside_board(ap_uint cell_id); +bool connectable(ap_int board[MAX_CELLS], ap_uint target, ap_uint rip_up); +void remove_line(ap_int board[MAX_CELLS], ap_uint rip_up); +bool available(ap_uint<2> avail[MAX_CELLS], ap_uint prev[MAX_CELLS], ap_uint start_id, ap_uint goal_id); +void qu_push(ap_uint qu_nodes[MAX_PQ], ap_uint id, ap_uint *top, ap_uint *bottom, bool *is_empty); +void qu_pop(ap_uint qu_nodes[MAX_PQ], ap_uint *id, ap_uint *top, ap_uint *bottom, bool *is_empty); + +#endif /* __ROUTER_HPP__ */ diff --git a/hls_2018/router_05/solver.c b/hls_2018/router_05/solver.c deleted file mode 100644 index ba77daa..0000000 --- a/hls_2018/router_05/solver.c +++ /dev/null @@ -1,317 +0,0 @@ -/* solver.c */ -/* Last Change: 2018/08/26 (Sun) 23:31:34. */ - -#define MAX_ATTEMPS 100000 - -#include -#include -#include -/* #include */ -/* #include */ -#include - -int board[8][72][72]={}; -int avail[8][72][72]={}; //start=3,path=2,avail=1,nonavail=0,goal=-1 -int connected[8*72*72/2+1]={}; //connected[0]=(number of connected lines) -int depth,height,width; -int goalx,goaly,goalz; -int lines; -//z,y,x - -void read(void){ //read problem - int x,y,z,i; - char c,str[8]; - scanf(" %s",str); //SIZE - scanf(" %d",&width); - if(width>72||width<=0) - printf("Error: width\n"); - scanf(" %c",&c); //X - scanf(" %d",&height); - if(height>72||height<=0) - printf("Error: height\n"); - scanf(" %c",&c); //X - scanf(" %d",&depth); - if(depth>8||depth<=0) - printf("Error: depth\n"); - scanf(" %s",str); //LINE_NUM - scanf(" %d",&lines); - if(lines<=0) - printf("Error: lines\n"); - for(i=1;i<=lines;i++){ - scanf(" %s",str); //LINE#X - scanf(" %c",&c); //( - scanf(" %d",&x); - if(x>=72||x<0) - printf("Error: x\n"); - scanf(" %c",&c); //, - scanf(" %d",&y); - if(y>=72||y<0) - printf("Error: y\n"); - scanf(" %c",&c); //, - scanf(" %d",&z); - if(z>=72||z<0) - printf("Error: z\n"); - scanf(" %c",&c); //) - board[z-1][y][x]=-i; - scanf("%c",&c); //) - /* scanf(" %[ -]",&c); //space or - */ - scanf(" %c",&c); //( - scanf(" %d",&x); - if(x>=72||x<0) - printf("Error: x\n"); - scanf(" %c",&c); //, - scanf(" %d",&y); - if(y>=72||y<0) - printf("Error: y\n"); - scanf(" %c",&c); //, - scanf(" %d",&z); - if(z>=72||z<0) - printf("Error: z\n"); - scanf(" %c",&c); //) - board[z-1][y][x]=-i; - } - return; -} - -int randline(void){ //return random line number - return rand()%lines+1; -} - -void shuffle(int array[],int start,int end){ - int i,j,t; - if(end==start) - return; - for(i=start;i0&&avail[nowz][nowy][nowx-1]>=2) - isbranch++; - if(nowy>0&&avail[nowz][nowy-1][nowx]>=2) - isbranch++; - if(nowz>0&&avail[nowz-1][nowy][nowx]>=2) - isbranch++; - if(nowx=2) - isbranch++; - if(nowy=2) - isbranch++; - if(nowz=2) - isbranch++; - if(isbranch>0){ - avail[nowz][nowy][nowx]=1; - return 0; - } - if(avail[nowz][nowy][nowx]==1) - avail[nowz][nowy][nowx]=2; - int i,src=0; - int searchorder[6]; //x+-,y+-,z+- - /* for(i=0;i<6;i++) */ - /* searchorder[i]=-1; */ - if(nowx>goalx){ - searchorder[src]=0; - src++; - }else - searchorder[5+src]=0; - if(nowy>goaly){ - searchorder[src]=1; - src++; - }else - searchorder[4+src]=1; - if(nowz>goalz){ - searchorder[src]=2; - src++; - }else - searchorder[3+src]=2; - if(nowx0&&available(nowx-1,nowy,nowz,0)) - return 1; - break; - case 1: - if(nowy>0&&available(nowx,nowy-1,nowz,0)) - return 1; - break; - case 2: - if(nowz>0&&available(nowx,nowy,nowz-1,0)) - return 1; - break; - case 3: - if(nowx

M|v$#bIg?Xz-A`G@qp?uGmzj34T{YdqjJY=e>+aV<-oM zkW0Xme`3%Bm`9v=?*;n26pTT^ht`lLH9R0}{Hq}yo0RW_5LUeN!AHhhTmZ}Y#*h!cu|ms(^E%R|buENmoXP~ zLphIuL&F-lBu0d>h`Q1I3X0Zbp~z*DHq)cGw5h0S4l&-1=n!y}IFk(FA(a(3X=+nA z=>gJC8GJg5V1m4${uy_lw!+gD3B(dsBns!R#F4hMX4)7FZ%>;gTwy$B z;Zdm{fa;@vC`d?TrU`60EiTweWW4I?jxe0C777kmtXQ(ReS~2NTmA?!G&e`CO*8Ez z4&!sFqNHgFPLO;WYF^iwyo_PX1o1GN%E3)|OXxor($kup#;5lPvYbGn&sWW4T$LuS zHUcv8Fr2AjkCgU9|QzuM{kUbm;iP)X7Mb$#4SIE+#;8=oM^_OrwIatF*LcM$s zgboh$NL3`6G4rlbILBg6qtKKyOb-z6B%{HlX(@?H`OUI}e}6NL`g$#?62e1Hi5!Vu*W-SX2}LjHs!uu-*(3&IuQHv<+oh$$e2}>K z<57ahFIr>}@F<}C-iUN8uS4@DIRfQ5sK!`x--Tz?+=7$tJvIa;*cRYx#vR8~H2U|4 zV}B1?S*wjDhu4-u^oMOXOQ7lSFN7>b3G;wls*y%=twe}5){%M5u3|2D*CuKz@cyJW z!F}tLC=4Z&;uEYra-LwPYXT zsmNsHjX`^E6t*Z=|F}g(Yq1`ha+KQzy;-R)cuWk3*))5bm`-H{EfA`hq@>U}k4Wa2wqEhZe9#(y22yAA%HnZcGz}KsNkaZX7}M-1oD&Vjcv8{|Wrvf{S3i{ae`aI}C@#_W1Rumc9n(>K zEQjgglyzQAp=+^+vq)lmu`Q{z*raV=UnU$xVIVPPR& zIKPmpq80u@JJQ_4>DT_wxM?wl!@@vK1C%tZN-T>XS^(IpMT+Q{LwFWa4J-o~qvI+LIg=gsfG5j?Lxt^fqlsA6W zJK^+8P=rJS)@itCCZ3BhRiRZok|cdT(aOX^1|V2iTo5=-bmmbMJc3`?s2fm& z|0++=1M&&3Tv!!lc=|_-&O~uP7F{2E)k`C9hP6Czzv|_(VaSX{O-A;J zL96~nNa5upaXdF>#-}2im@@;AFUftEhGi_n9=XK?aVkS`>*0!(4%*6`s>2wx9D43t zwThhqzG9uR@WPyP)o~e8(mzv+otZ|qmK~$e7muPW8_sp;y3fNH|2mkP#MfC4;>p8P zV!=tfI9`^A>hsX&@Cdg#efX1jJReI$U)6YdSR99|UN4~Of^M3m7k{)#gV)}*5X-5J zKb|5(8M?)RWcA1#=Cz>bmlGZJpC7_)VhA_mw8WI~zHkLciTl!K#8=z*^+y`fB56KwRda@00tT8Iz+WJ_EyE))6ToR1=4rU}s*B z1KT8jjx`{5XmVmHnntaU?J)l0B5tC_VG1CwQQJl$A764daNdpp_SbwNW`fWq4peB|*ecyiw8T2ooVatAvI3z1A6rX(GB)q)kDV$Qe|MQ>u= zIk9mXFN>vdGP1}y=%OrcmG}7gUxaeLkfLKPC{8reVin6@JTPyn^Qe>h2qQ7ZOB6!l zk@^*MBf;YOh$OWkl7^7#HAp)u_APd#9;O8txEA7+@-iAwmyD`H>>xl5P6cE_zmdj$RroNlM^ZOUUfokf_@OZ#-#|u zfGmjBy{Nl>(c`@aR@)G81r(AfE_=2A9Q5CU-xj(4^RDuEpR=k~`4HfbARGCmhvK2p z#Y27L*Lsh6MXU3OKXclQ%{?qj0Sw`PKUVN%r1;$lzr3X9uG-m7bo^ayw@xhH{>d-F zB*``SX^lCT;8^x1I)hYyld0e1*oj4rekfVO-M;sS{LL_hAO6u#eDTlDo5!CV`_mVmSsHkB<5u-|D^J~d-Ho6B$oa>XtB-vA zu>ao%?C&mBUtzGZ(+>aoy!Yx8^XTFdTp5}BpI!i6yr0B@jPoSEHTa~GfL&jI^!eXi zdg>Q{`_~@*))&5b(@kIa?YBIYBp%;2ekiGWS-UEqeE6XS^~tsGdFZpX@drQh)qlBg z_3wS|>Z4EJ|M0+xYdBj(cIs9yQwr%v5ox#w`)cZ-b< zdHBSekDa)G@cgl%>JPr-AAT@8JbCS#Z~M8ClZ)OQ{_wlL<&Q^Kzv%~Wy=fr2CHj%s zA2FA^%goVB7Qgn_M-Tt}LneM<5wMemD}MYhPu1=`dGgVZ_{Xrr_Ji|-?M_k&s*55Bk>a%&TV z7cUOp_*Z7|#^0a)>gsD=GrE=>TC+#4F#0>d&pxYaYZnLg8QHY;wvxNsZ5^I&mnVWB z_^DC+{hpzrcf7-xSH0>8W)10#me*#lxMltBiS$|3iO|&qc0wZDamV0=*?UJv@zieE z51H;6l83@^eVO(j@SrHqBICJf)PXfx70;+nPY({BIWseJ#TC;HzmXh#qJNigNY>f( z#=zW&KV5`>Yhe!-EU8bhkMV}^ynLfi(qXSnyz%12w|(G6^X%I1&t6>pzy}^c#oEes zH<}N~JTjlG4a%M+41L>S;Da5TSbN|B@yYYgzvCTi@X4hZhWx!aDVquLiR|+{bEafB zom}tfl6EC{epZmA}wd9j;|7WdJdzEMJLOM8jv1>l5 z{J&|>n4YF`LMgq#kFYUj+ZY!lLp6Z|#?#?xY)JFJ-1zG#rA4t>hk#rJwytsFt zGP2a*lM9qzkIY$95#?3+x&-M9h{8U|nw0HV<+rh5>#L%#`x~dt$PyR~~F-}Wgp`m_^k=tZ{nlNIedAM{=ts>z-l}()7d`A zR6p-8*lHHnul2HVM%H5akKJ_|zxb7ji@!WL_@cC)y)bd{#jgy$c<+T!E-cnvD+_Vg za#udov8jvU<^p$2vODU(Vm9gZK&EKcuDGJ|teJg9@i#p5(vH<_UC@12>!qM$uulla zel4v`*S>YCD!_$%a6<0SHVrL(GIYal7CyP-#l7~)(S=Q?(x`AT+>nfpE-f|q1Re=K zxv*CF1lM#h?Z_wC>D7TxeV_sPo9_!%bFSb%^M1z+<`w5EiGF6WT)4zS3H=Fxa~Ca$@r2VyfXe9%qCmAq(;}S z`tt-*nftoX(kHOeflqLbh);f4zhJ@>rBiZ=#uX|3!YM0f^&uTA=>_+To=3Zqo)bG+ zSw4T2klD*p)cc?(_1Z5Y(US*qit%K2vK01EU)am#=C+4_Solr%jFR;z@(eGk9=hWVSFYCS9&WZf)?@d!< zv~03+R*w|VV+TEadWp|5<{VPh!_CLtq9<~svDnMni5|+iy^>w|VGGd{J7Uk8$TicG z=4E?Q7QITneDG?qC9 zR^W5&+mOL2yGgK{)VEa~x6o4ZTGwyntB!g-{5Yf51!;&wi{g0)Y2(xPdRZr4B&FbU zyCQd`8o0JxvNKYG$R{On6ngd{$t$3i2hA_%#TFS~-&>(o!+S6ZuJTQZC0h=@TqyER zv%!NQF6u(APU;(K^(|$30Msd}9U@~2fy4*(=`*8 zWZ3~Es9Fb?R|UPSl}-tDMe9&AW-3O$Y)nx+XPy%Sk$F(<1gXY0w8R&{;jO>6v8rW+ zu7)g4i%2rWE{Jrg#P_&n81@#Biq(8fHskI6ut5RAr!UDPh^m*2)wt*x5)o%1zdAUT zI1^GSAeYxlIfPU1ElHcyr)v0QD{GPFq%5O~CCY=%^dPOP5Dhu~EmCQURO_WILDn9h z&ZX$eY8}LB21TuOA}`dWR7Mg|8E2f=nn?YD4$`wj)5JqT>z54_dCXF_UzQM9CJyv8-}wCH83X@#a*i|0`t#7l`Yar$NLsyQW9ff#a$`Kszq zB4?KI3L!CzJ`f74l!w?x^HM2U4e1PATC7i|bU-s1JukHu57A*L#>Rx(-4N>B=Hh$7TkJ;L+^tuMsqn5)&&;x!qI9aivZ2^@LjPgK;%wK&Y7fU=3a8{7@vGwCl?{zEdVX)+=WC+rBLdtB;7cB zO0-X{kjUn_kg4UaN2fs~pwy-mL+8Hc`pn1bhHjyVN@*W~#Z0L} zvMvDV1Ji5-n%Z#wh3TpV6{DlnoL-E*m?#3OTwaprXR8>N9OvPv@+jdkb1YKXQ8pGk z^+wHl9QAls3A(4OJ`kH7qSLVmW$>|wU*!C7_{wM$vz7{2(t7Dl9&s`bKZ~jT1TSk_ zjdc8yb6U)!T%Jop<`w^?K~O4Y<4;B2td=T$eyF+l9OMpT7yno}$|ZRHUmQtRgjtxA zCe}*yT6@M}h89QTOeA*<0hGH;KpyaOuK9WU$W=*I@*#j1mIrB`hq` zLITzoD+7}S+Rv!2$~AJRit*)GZB-sQ8a4|HI3gx%cm^r*sIV9e{+i(`dc+rxqtmZ_ zPHt4Zd2RBPJEP{8Q31Uu_D&vRO+%em8oJDM(sWVU*M~kim_%p`InI+*4;_UNE^0n4 zL0_(dQpAB%4wy|SMv^RO-m8kA#-wpfn%e3NdaF5i%K2Jcdy|FKs-lhM&Qvay9-IWs zWdXRX<}jF`&dOQk^!(H|c#c;uMp{UxCwk$LZ?8EAqhdEUQ(DF)8a2f>*gy-9hcPU}IEjrRF?LDFZP5@%A#FpLJVx=DU>X*Cv!2ZlXKaBP!(^M-WRkEm z0~lr*!m_*2j3MwO;CDaYQ}@0iL2Iu|YW^cG>uP7g5}q_Vx!#7@X{!3d8`#@vTlYL9{WH^$ekw5*V978YohX5QIMuaQ4j|mR7bq7nABXV@**q zQ*Ou@F@adex={5R;p?i-QY1-~m$3y~>tAGo9(QWM_Ifg{>+TSu0j~q{i_SfpxMqa#CRX zW7KLd1x4X%ksW2HM9$Wf%7Lj=-}1E!Qg#Drkex1i(bi|kEKV0lE}e{J0Bg3UMI>kL#j51=)a1;4YXJ+XadMpUt(6eRI-n49y_$q-r830jJ&Kp5IEAFB zqFy@)z)3Fc6cBE&tEtk(h$SUQt(J0)jh4UWqUypNEL%E@u5vI>4~}S^BOB2>+!(=) zzDn+jRRgDs1AARrcvrHB);Qr+ylR{@R*w@2GEOE{-Ey3uS`DmeWHp*TF zsmWkkXQ*nrM$Q~7*;;Kx8rG^h`>INF>V#aTo$5GAZj-U-m*w3cV^X8a#uJVc@_Kw> zeLpDXw<54LixHp;cXyIjjJKKmwKv78V3qj3t5sx ze)@58+HZF#XFgD2CmkpFxabQf8z(hRh}H>Ii4%^K8sh{r)aOrWoFKP$oOtgYhu5oE zdA>Ct;qA8C5l%kaIElezN-?P9wr!PM-Zzr-Ci9VAUJjSsww7FnUkvpM`B)0DZi6U6 z;1wh}VaJ0s$*e2acynbV_VKyyTy?=l>S8votxLDu%!%ZbR_QB_r?0Qid{g>x`c(DF z)-GRb!OFpfPY5o|hC$vIFLQC0=Rv#Vst&oG%?LRE^V&8aEp$hm-%hV<*g&jAQjE~>$Z#XtP0V`H z@FT3xYiRwYvivBnuLpyVbYkAllHdU&Yx@Jnrm#b zgf+t~hJAz`=?RtDHLW}BUaHb1wN7PRKl3Z;s>_VWT;*G%uQurVGw(K%I;{J!gS;cp zd3TLI7^7uo1dgOrOF74rw*|u^h$;d%t_WC`Kx-u6ph{?prTyZP|NZ@aOWd1%M?-+9|@XI%V->pJBS zYfSCix3AbYwQoni^v(1`?i=ji_Y14#!oH~~w{KslS}T2Yy}zPZJ2x_~zq8o4?-vH$jo8@i$Ck;0u##=b?F+Xdcj@8y&bLYDio>YZ8zV1V{!51+g9t_Hx+JE zVS{e}kFamY)V|5dqTqFf5?cKgGtjPkGqeTgyM80PQ`D_o)A0Z zG9{}HPaNm3vxaNs{zEI*TDhb%h3m^D(~`-_kI6TyeOgs8Ra@a7b0lu6zMg(O1Te_vDk$Jm=ise)pSCep4yH=ky_vb>u#GV!3ZV`MIZ_k-jhewR1oG8x>&X ztk&0(``n4;$o=Q0@5v{z4}CJt0*qq{|0~%DL%dd9Otw{*&$Y__|FWFg*GE0c2f{7Q zGKNTyhY~5HlKyl)VT?~hFMu`jkc-i9eZdAr9_$$?Zs4=50qoh_Ui43JLZh5K7{5(V zm_qoH)+yy=VC8iPZU0LDC`$~OZBMz`v)h*w++s(qx`>XWb zPypr7JSjGM&MT@Q1hl0;SSuXC{y_vJYxU*}8RdO+5r$6^Bcvw?E*ipGJ~1XzIwxmokGYPLxj(`USksXQAOip@A>s&K78~)<oha+nL_&t(0P&TtV5} z#f=KukjXUVT&pWl(OmQea58Z|t9+jet1NhwU2;@HBKPghmt zPvs&3yVsG>wcajoyUTSvKM_pqX$$ir60dM{bt_4_{bl)T8$>X!{gamXtWE_5lh z8J^lD145TyDhb>Ch(dI;H=47^0r2dC#bu!THtGg;PNIX?rBgQOsDSK2^k`y47b9rK zDL2MahFB6TUi=(|WJBX_9u8YEC4r#G%&;Ia2|In*Vy;F``%4VyX8MY3A^Zeb@hYuR z6GFp!xh3()LrWwfRE0kSOPUwuMMrEmJ*%^jw#ZY6k(eKVriL z@M3SIf6uu&$}nIs#Zcl>2uK}sp!crNN7QGIjqLa>vPhne@W5b8N04tlh+TGJljD}>9q+8JWsC8nlD2k;*!$h^A{wv8nZBB_rnZP~Rl!vg0 zB6Kd@qIle088j(GGrUnmI26OlkxRL#e*z%0DcVrYx7vho|0F#uZlNZwkWRb?zmTQ~ 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�aI^k*KK1 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%0A5YqfEE)LLYJt|F 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 zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~ z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY** z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0 z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{ z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~ z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY** z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0 z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{ z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~ z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY** z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0 z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{ z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~ z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY** z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0 z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{ z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~ z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY** z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0 z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{ z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~ z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY** z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0 z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{ z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~ z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY** z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0 z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{ z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~ z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY** z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0 z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{ z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~ z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY** z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0 z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{ z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~ z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY** z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0 z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{ z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~ z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY** z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0 z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{ z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~ z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY** z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0 z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{ z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~ z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY** z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0 z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{ z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~ z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY** z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0 z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{ z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~ z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY** z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0 z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{ z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~ z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY** z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0 z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{ z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~ z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY** z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0 z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{ z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~ z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY** z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5O|getc5Um)r0@{ zy9#Z$J=Q`w&}zArU$Q)p8^@s9M|;vfDh5lxYWwZ7_S>GpTDVxP!{C4V&mR5zdB0VC YZp&rXH_rZKU$8GY1~>+u4adO$4~)xISO5S3 literal 0 HcmV?d00001 diff --git a/hls_2018/router_01/bitstream/router_design.tcl b/hls_2018/router_01/bitstream/router_design.tcl new file mode 100755 index 0000000..e5347df --- /dev/null +++ b/hls_2018/router_01/bitstream/router_design.tcl @@ -0,0 +1,1113 @@ + +################################################################ +# This is a generated script based on design: router_design +# +# Though there are limitations about the generated script, +# the main purpose of this utility is to make learning +# IP Integrator Tcl commands easier. +################################################################ + +namespace eval _tcl { +proc get_script_folder {} { + set script_path [file normalize [info script]] + set script_folder [file dirname $script_path] + return $script_folder +} +} +variable script_folder +set script_folder [_tcl::get_script_folder] + +################################################################ +# Check if script is running in correct Vivado version. +################################################################ +set scripts_vivado_version 2018.2 +set current_vivado_version [version -short] + +if { [string first $scripts_vivado_version $current_vivado_version] == -1 } { + puts "" + catch {common::send_msg_id "BD_TCL-109" "ERROR" "This script was generated using Vivado <$scripts_vivado_version> and is being run in <$current_vivado_version> of Vivado. Please run the script in Vivado <$scripts_vivado_version> then open the design in Vivado <$current_vivado_version>. Upgrade the design by running \"Tools => Report => Report IP Status...\", then run write_bd_tcl to create an updated script."} + + return 1 +} + +################################################################ +# START +################################################################ + +# To test this script, run the following commands from Vivado Tcl console: +# source router_design_script.tcl + +# If there is no project opened, this script will create a +# project, but make sure you do not have an existing project +# <./myproj/project_1.xpr> in the current working folder. + +set list_projs [get_projects -quiet] +if { $list_projs eq "" } { + create_project project_1 myproj -part xc7z020clg400-1 +} + + +# CHANGE DESIGN NAME HERE +variable design_name +set design_name router_design + +# If you do not already have an existing IP Integrator design open, +# you can create a design using the following command: +# create_bd_design $design_name + +# Creating design if needed +set errMsg "" +set nRet 0 + +set cur_design [current_bd_design -quiet] +set list_cells [get_bd_cells -quiet] + +if { ${design_name} eq "" } { + # USE CASES: + # 1) Design_name not set + + set errMsg "Please set the variable to a non-empty value." + set nRet 1 + +} elseif { ${cur_design} ne "" && ${list_cells} eq "" } { + # USE CASES: + # 2): Current design opened AND is empty AND names same. + # 3): Current design opened AND is empty AND names diff; design_name NOT in project. + # 4): Current design opened AND is empty AND names diff; design_name exists in project. + + if { $cur_design ne $design_name } { + common::send_msg_id "BD_TCL-001" "INFO" "Changing value of from <$design_name> to <$cur_design> since current design is empty." + set design_name [get_property NAME $cur_design] + } + common::send_msg_id "BD_TCL-002" "INFO" "Constructing design in IPI design <$cur_design>..." + +} elseif { ${cur_design} ne "" && $list_cells ne "" && $cur_design eq $design_name } { + # USE CASES: + # 5) Current design opened AND has components AND same names. + + set errMsg "Design <$design_name> already exists in your project, please set the variable to another value." + set nRet 1 +} elseif { [get_files -quiet ${design_name}.bd] ne "" } { + # USE CASES: + # 6) Current opened design, has components, but diff names, design_name exists in project. + # 7) No opened design, design_name exists in project. + + set errMsg "Design <$design_name> already exists in your project, please set the variable to another value." + set nRet 2 + +} else { + # USE CASES: + # 8) No opened design, design_name not in project. + # 9) Current opened design, has components, but diff names, design_name not in project. + + common::send_msg_id "BD_TCL-003" "INFO" "Currently there is no design <$design_name> in project, so creating one..." + + create_bd_design $design_name + + common::send_msg_id "BD_TCL-004" "INFO" "Making design <$design_name> as current_bd_design." + current_bd_design $design_name + +} + +common::send_msg_id "BD_TCL-005" "INFO" "Currently the variable is equal to \"$design_name\"." + +if { $nRet != 0 } { + catch {common::send_msg_id "BD_TCL-114" "ERROR" $errMsg} + return $nRet +} + +set bCheckIPsPassed 1 +################################################################## +# CHECK IPs +################################################################## +set bCheckIPs 1 +if { $bCheckIPs == 1 } { + set list_check_ips "\ +xilinx.com:ip:axi_gpio:2.0\ +xilinx.com:ip:processing_system7:5.5\ +xilinx.com:hls:pynqrouter:1.0\ +xilinx.com:ip:proc_sys_reset:5.0\ +" + + set list_ips_missing "" + common::send_msg_id "BD_TCL-006" "INFO" "Checking if the following IPs exist in the project's IP catalog: $list_check_ips ." + + foreach ip_vlnv $list_check_ips { + set ip_obj [get_ipdefs -all $ip_vlnv] + if { $ip_obj eq "" } { + lappend list_ips_missing $ip_vlnv + } + } + + if { $list_ips_missing ne "" } { + catch {common::send_msg_id "BD_TCL-115" "ERROR" "The following IPs are not found in the IP Catalog:\n $list_ips_missing\n\nResolution: Please add the repository containing the IP(s) to the project." } + set bCheckIPsPassed 0 + } + +} + +if { $bCheckIPsPassed != 1 } { + common::send_msg_id "BD_TCL-1003" "WARNING" "Will not continue with creation of design due to the error(s) above." + return 3 +} + +################################################################## +# DESIGN PROCs +################################################################## + + + +# Procedure to create entire design; Provide argument to make +# procedure reusable. If parentCell is "", will use root. +proc create_root_design { parentCell } { + + variable script_folder + variable design_name + + if { $parentCell eq "" } { + set parentCell [get_bd_cells /] + } + + # Get object for parentCell + set parentObj [get_bd_cells $parentCell] + if { $parentObj == "" } { + catch {common::send_msg_id "BD_TCL-100" "ERROR" "Unable to find parent cell <$parentCell>!"} + return + } + + # Make sure parentObj is hier blk + set parentType [get_property TYPE $parentObj] + if { $parentType ne "hier" } { + catch {common::send_msg_id "BD_TCL-101" "ERROR" "Parent <$parentObj> has TYPE = <$parentType>. Expected to be ."} + return + } + + # Save current instance; Restore later + set oldCurInst [current_bd_instance .] + + # Set parent object as current + current_bd_instance $parentObj + + + # Create interface ports + set DDR [ create_bd_intf_port -mode Master -vlnv xilinx.com:interface:ddrx_rtl:1.0 DDR ] + set FIXED_IO [ create_bd_intf_port -mode Master -vlnv xilinx.com:display_processing_system7:fixedio_rtl:1.0 FIXED_IO ] + + # Create ports + set LD [ create_bd_port -dir O -from 3 -to 0 LD ] + + # Create instance: axi_gpio_0, and set properties + set axi_gpio_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:axi_gpio:2.0 axi_gpio_0 ] + set_property -dict [ list \ + CONFIG.C_GPIO_WIDTH {4} \ + ] $axi_gpio_0 + + # Create instance: processing_system7_0, and set properties + set processing_system7_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:processing_system7:5.5 processing_system7_0 ] + set_property -dict [ list \ + CONFIG.PCW_ACT_APU_PERIPHERAL_FREQMHZ {650.000000} \ + CONFIG.PCW_ACT_CAN0_PERIPHERAL_FREQMHZ {23.8095} \ + CONFIG.PCW_ACT_CAN1_PERIPHERAL_FREQMHZ {23.8095} \ + CONFIG.PCW_ACT_CAN_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_DCI_PERIPHERAL_FREQMHZ {10.096154} \ + CONFIG.PCW_ACT_ENET0_PERIPHERAL_FREQMHZ {125.000000} \ + CONFIG.PCW_ACT_ENET1_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_FPGA0_PERIPHERAL_FREQMHZ {100.000000} \ + CONFIG.PCW_ACT_FPGA1_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_FPGA2_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_FPGA3_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_I2C_PERIPHERAL_FREQMHZ {50} \ + CONFIG.PCW_ACT_PCAP_PERIPHERAL_FREQMHZ {200.000000} \ + CONFIG.PCW_ACT_QSPI_PERIPHERAL_FREQMHZ {200.000000} \ + CONFIG.PCW_ACT_SDIO_PERIPHERAL_FREQMHZ {50.000000} \ + CONFIG.PCW_ACT_SMC_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_SPI_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_TPIU_PERIPHERAL_FREQMHZ {200.000000} \ + CONFIG.PCW_ACT_TTC0_CLK0_PERIPHERAL_FREQMHZ {108.333336} \ + CONFIG.PCW_ACT_TTC0_CLK1_PERIPHERAL_FREQMHZ {108.333336} \ + CONFIG.PCW_ACT_TTC0_CLK2_PERIPHERAL_FREQMHZ {108.333336} \ + CONFIG.PCW_ACT_TTC1_CLK0_PERIPHERAL_FREQMHZ {108.333336} \ + CONFIG.PCW_ACT_TTC1_CLK1_PERIPHERAL_FREQMHZ {108.333336} \ + CONFIG.PCW_ACT_TTC1_CLK2_PERIPHERAL_FREQMHZ {108.333336} \ + CONFIG.PCW_ACT_TTC_PERIPHERAL_FREQMHZ {50} \ + CONFIG.PCW_ACT_UART_PERIPHERAL_FREQMHZ {100.000000} \ + CONFIG.PCW_ACT_USB0_PERIPHERAL_FREQMHZ {60} \ + CONFIG.PCW_ACT_USB1_PERIPHERAL_FREQMHZ {60} \ + CONFIG.PCW_ACT_WDT_PERIPHERAL_FREQMHZ {108.333336} \ + CONFIG.PCW_APU_CLK_RATIO_ENABLE {6:2:1} \ + CONFIG.PCW_APU_PERIPHERAL_FREQMHZ {650} \ + CONFIG.PCW_ARMPLL_CTRL_FBDIV {26} \ + CONFIG.PCW_CAN0_BASEADDR {0xE0008000} \ + CONFIG.PCW_CAN0_CAN0_IO {} \ + CONFIG.PCW_CAN0_HIGHADDR {0xE0008FFF} \ + CONFIG.PCW_CAN0_PERIPHERAL_CLKSRC {External} \ + CONFIG.PCW_CAN0_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_CAN0_PERIPHERAL_FREQMHZ {-1} \ + CONFIG.PCW_CAN1_BASEADDR {0xE0009000} \ + CONFIG.PCW_CAN1_CAN1_IO {} \ + CONFIG.PCW_CAN1_HIGHADDR {0xE0009FFF} \ + CONFIG.PCW_CAN1_PERIPHERAL_CLKSRC {External} \ + CONFIG.PCW_CAN1_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_CAN1_PERIPHERAL_FREQMHZ {-1} \ + CONFIG.PCW_CAN_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_CAN_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_CAN_PERIPHERAL_DIVISOR1 {1} \ + CONFIG.PCW_CAN_PERIPHERAL_FREQMHZ {100} \ + CONFIG.PCW_CAN_PERIPHERAL_VALID {0} \ + CONFIG.PCW_CLK0_FREQ {100000000} \ + CONFIG.PCW_CLK1_FREQ {10000000} \ + CONFIG.PCW_CLK2_FREQ {10000000} \ + CONFIG.PCW_CLK3_FREQ {10000000} \ + CONFIG.PCW_CORE0_FIQ_INTR {0} \ + CONFIG.PCW_CORE0_IRQ_INTR {0} \ + CONFIG.PCW_CORE1_FIQ_INTR {0} \ + CONFIG.PCW_CORE1_IRQ_INTR {0} \ + CONFIG.PCW_CPU_CPU_6X4X_MAX_RANGE {667} \ + CONFIG.PCW_CPU_CPU_PLL_FREQMHZ {1300.000} \ + CONFIG.PCW_CPU_PERIPHERAL_CLKSRC {ARM PLL} \ + CONFIG.PCW_CPU_PERIPHERAL_DIVISOR0 {2} \ + CONFIG.PCW_CRYSTAL_PERIPHERAL_FREQMHZ {50} \ + CONFIG.PCW_DCI_PERIPHERAL_CLKSRC {DDR PLL} \ + CONFIG.PCW_DCI_PERIPHERAL_DIVISOR0 {52} \ + CONFIG.PCW_DCI_PERIPHERAL_DIVISOR1 {2} \ + CONFIG.PCW_DCI_PERIPHERAL_FREQMHZ {10.159} \ + CONFIG.PCW_DDRPLL_CTRL_FBDIV {21} \ + CONFIG.PCW_DDR_DDR_PLL_FREQMHZ {1050.000} \ + CONFIG.PCW_DDR_HPRLPR_QUEUE_PARTITION {HPR(0)/LPR(32)} \ + CONFIG.PCW_DDR_HPR_TO_CRITICAL_PRIORITY_LEVEL {15} \ + CONFIG.PCW_DDR_LPR_TO_CRITICAL_PRIORITY_LEVEL {2} \ + CONFIG.PCW_DDR_PERIPHERAL_CLKSRC {DDR PLL} \ + CONFIG.PCW_DDR_PERIPHERAL_DIVISOR0 {2} \ + CONFIG.PCW_DDR_PORT0_HPR_ENABLE {0} \ + CONFIG.PCW_DDR_PORT1_HPR_ENABLE {0} \ + CONFIG.PCW_DDR_PORT2_HPR_ENABLE {0} \ + CONFIG.PCW_DDR_PORT3_HPR_ENABLE {0} \ + CONFIG.PCW_DDR_PRIORITY_READPORT_0 {} \ + CONFIG.PCW_DDR_PRIORITY_READPORT_2 {} \ + CONFIG.PCW_DDR_PRIORITY_WRITEPORT_0 {} \ + CONFIG.PCW_DDR_PRIORITY_WRITEPORT_2 {} \ + CONFIG.PCW_DDR_RAM_BASEADDR {0x00100000} \ + CONFIG.PCW_DDR_RAM_HIGHADDR {0x1FFFFFFF} \ + CONFIG.PCW_DDR_WRITE_TO_CRITICAL_PRIORITY_LEVEL {2} \ + CONFIG.PCW_DM_WIDTH {4} \ + CONFIG.PCW_DQS_WIDTH {4} \ + CONFIG.PCW_DQ_WIDTH {32} \ + CONFIG.PCW_ENET0_BASEADDR {0xE000B000} \ + CONFIG.PCW_ENET0_ENET0_IO {MIO 16 .. 27} \ + CONFIG.PCW_ENET0_GRP_MDIO_ENABLE {1} \ + CONFIG.PCW_ENET0_GRP_MDIO_IO {MIO 52 .. 53} \ + CONFIG.PCW_ENET0_HIGHADDR {0xE000BFFF} \ + CONFIG.PCW_ENET0_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_ENET0_PERIPHERAL_DIVISOR0 {8} \ + CONFIG.PCW_ENET0_PERIPHERAL_DIVISOR1 {1} \ + CONFIG.PCW_ENET0_PERIPHERAL_ENABLE {1} \ + CONFIG.PCW_ENET0_PERIPHERAL_FREQMHZ {1000 Mbps} \ + CONFIG.PCW_ENET0_RESET_ENABLE {1} \ + CONFIG.PCW_ENET0_RESET_IO {MIO 9} \ + CONFIG.PCW_ENET1_BASEADDR {0xE000C000} \ + CONFIG.PCW_ENET1_ENET1_IO {} \ + CONFIG.PCW_ENET1_HIGHADDR {0xE000CFFF} \ + CONFIG.PCW_ENET1_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_ENET1_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_ENET1_PERIPHERAL_DIVISOR1 {1} \ + CONFIG.PCW_ENET1_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_ENET1_PERIPHERAL_FREQMHZ {1000 Mbps} \ + CONFIG.PCW_ENET1_RESET_ENABLE {0} \ + CONFIG.PCW_ENET1_RESET_IO {} \ + CONFIG.PCW_FTM_CTI_IN1 {} \ + CONFIG.PCW_FTM_CTI_IN3 {} \ + CONFIG.PCW_FTM_CTI_OUT1 {} \ + CONFIG.PCW_FTM_CTI_OUT3 {} \ + CONFIG.PCW_GPIO_EMIO_GPIO_WIDTH {64} \ + CONFIG.PCW_GPIO_HIGHADDR {0xE000AFFF} \ + CONFIG.PCW_GPIO_MIO_GPIO_ENABLE {1} \ + CONFIG.PCW_GPIO_MIO_GPIO_IO {MIO} \ + CONFIG.PCW_GPIO_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_I2C0_BASEADDR {0xE0004000} \ + CONFIG.PCW_I2C0_GRP_INT_ENABLE {0} \ + CONFIG.PCW_I2C0_GRP_INT_IO {} \ + CONFIG.PCW_I2C0_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_I2C0_RESET_ENABLE {0} \ + CONFIG.PCW_I2C0_RESET_IO {} \ + CONFIG.PCW_I2C1_HIGHADDR {0xE0005FFF} \ + CONFIG.PCW_I2C1_I2C1_IO {} \ + CONFIG.PCW_I2C_PERIPHERAL_FREQMHZ {25} \ + CONFIG.PCW_I2C_RESET_ENABLE {1} \ + CONFIG.PCW_I2C_RESET_POLARITY {Active Low} \ + CONFIG.PCW_I2C_RESET_SELECT {} \ + CONFIG.PCW_NAND_NAND_IO {} \ + CONFIG.PCW_NOR_GRP_CS0_ENABLE {0} \ + CONFIG.PCW_NOR_GRP_CS0_IO {} \ + CONFIG.PCW_NOR_GRP_SRAM_CS0_ENABLE {0} \ + CONFIG.PCW_NOR_GRP_SRAM_CS0_IO {} \ + CONFIG.PCW_NOR_GRP_SRAM_INT_ENABLE {0} \ + CONFIG.PCW_NOR_GRP_SRAM_INT_IO {} \ + CONFIG.PCW_NOR_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_NOR_SRAM_CS0_T_CEOE {1} \ + CONFIG.PCW_NOR_SRAM_CS0_T_PC {1} \ + CONFIG.PCW_NOR_SRAM_CS0_T_RC {11} \ + CONFIG.PCW_NOR_SRAM_CS0_T_TR {1} \ + CONFIG.PCW_NOR_SRAM_CS0_T_WC {11} \ + CONFIG.PCW_NOR_SRAM_CS0_T_WP {1} \ + CONFIG.PCW_NOR_SRAM_CS0_WE_TIME {0} \ + CONFIG.PCW_NOR_SRAM_CS1_T_CEOE {1} \ + CONFIG.PCW_NOR_SRAM_CS1_T_PC {1} \ + CONFIG.PCW_NOR_SRAM_CS1_T_RC {11} \ + CONFIG.PCW_NOR_SRAM_CS1_T_TR {1} \ + CONFIG.PCW_NOR_SRAM_CS1_T_WC {11} \ + CONFIG.PCW_NOR_SRAM_CS1_T_WP {1} \ + CONFIG.PCW_NOR_SRAM_CS1_WE_TIME {0} \ + CONFIG.PCW_OVERRIDE_BASIC_CLOCK {0} \ + CONFIG.PCW_P2F_CAN0_INTR {0} \ + CONFIG.PCW_P2F_CAN1_INTR {0} \ + CONFIG.PCW_P2F_CTI_INTR {0} \ + CONFIG.PCW_P2F_DMAC0_INTR {0} \ + CONFIG.PCW_P2F_DMAC1_INTR {0} \ + CONFIG.PCW_P2F_DMAC2_INTR {0} \ + CONFIG.PCW_P2F_DMAC3_INTR {0} \ + CONFIG.PCW_P2F_DMAC4_INTR {0} \ + CONFIG.PCW_P2F_DMAC5_INTR {0} \ + CONFIG.PCW_P2F_DMAC6_INTR {0} \ + CONFIG.PCW_P2F_DMAC7_INTR {0} \ + CONFIG.PCW_P2F_DMAC_ABORT_INTR {0} \ + CONFIG.PCW_P2F_ENET0_INTR {0} \ + CONFIG.PCW_P2F_ENET1_INTR {0} \ + CONFIG.PCW_P2F_GPIO_INTR {0} \ + CONFIG.PCW_P2F_I2C0_INTR {0} \ + CONFIG.PCW_P2F_I2C1_INTR {0} \ + CONFIG.PCW_P2F_QSPI_INTR {0} \ + CONFIG.PCW_P2F_SDIO0_INTR {0} \ + CONFIG.PCW_P2F_SDIO1_INTR {0} \ + CONFIG.PCW_P2F_SMC_INTR {0} \ + CONFIG.PCW_P2F_SPI0_INTR {0} \ + CONFIG.PCW_P2F_SPI1_INTR {0} \ + CONFIG.PCW_P2F_UART0_INTR {0} \ + CONFIG.PCW_P2F_UART1_INTR {0} \ + CONFIG.PCW_P2F_USB0_INTR {0} \ + CONFIG.PCW_P2F_USB1_INTR {0} \ + CONFIG.PCW_PACKAGE_DDR_BOARD_DELAY0 {0.223} \ + CONFIG.PCW_PACKAGE_DDR_BOARD_DELAY1 {0.212} \ + CONFIG.PCW_PACKAGE_DDR_BOARD_DELAY2 {0.085} \ + CONFIG.PCW_PACKAGE_DDR_BOARD_DELAY3 {0.092} \ + CONFIG.PCW_PACKAGE_DDR_DQS_TO_CLK_DELAY_0 {0.040} \ + CONFIG.PCW_PACKAGE_DDR_DQS_TO_CLK_DELAY_1 {0.058} \ + CONFIG.PCW_PACKAGE_DDR_DQS_TO_CLK_DELAY_2 {-0.009} \ + CONFIG.PCW_PACKAGE_DDR_DQS_TO_CLK_DELAY_3 {-0.033} \ + CONFIG.PCW_PACKAGE_NAME {clg400} \ + CONFIG.PCW_PCAP_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_PCAP_PERIPHERAL_DIVISOR0 {5} \ + CONFIG.PCW_PCAP_PERIPHERAL_FREQMHZ {200} \ + CONFIG.PCW_PERIPHERAL_BOARD_PRESET {None} \ + CONFIG.PCW_PJTAG_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_PJTAG_PJTAG_IO {} \ + CONFIG.PCW_QSPI_GRP_SINGLE_SS_ENABLE {1} \ + CONFIG.PCW_QSPI_GRP_SINGLE_SS_IO {MIO 1 .. 6} \ + CONFIG.PCW_QSPI_GRP_SS1_ENABLE {0} \ + CONFIG.PCW_QSPI_GRP_SS1_IO {} \ + CONFIG.PCW_SD0_GRP_WP_ENABLE {0} \ + CONFIG.PCW_SD0_GRP_WP_IO {} \ + CONFIG.PCW_SD1_GRP_POW_ENABLE {0} \ + CONFIG.PCW_SD1_GRP_POW_IO {} \ + CONFIG.PCW_SD1_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_SD1_SD1_IO {} \ + CONFIG.PCW_SPI0_GRP_SS1_ENABLE {0} \ + CONFIG.PCW_SPI0_GRP_SS1_IO {} \ + CONFIG.PCW_SPI0_HIGHADDR {0xE0006FFF} \ + CONFIG.PCW_SPI0_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_SPI0_SPI0_IO {} \ + CONFIG.PCW_SPI1_GRP_SS1_ENABLE {0} \ + CONFIG.PCW_SPI1_GRP_SS1_IO {} \ + CONFIG.PCW_SPI1_HIGHADDR {0xE0007FFF} \ + CONFIG.PCW_SPI1_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_SPI1_SPI1_IO {} \ + CONFIG.PCW_TRACE_GRP_2BIT_ENABLE {0} \ + CONFIG.PCW_TRACE_GRP_2BIT_IO {} \ + CONFIG.PCW_TRACE_GRP_4BIT_ENABLE {0} \ + CONFIG.PCW_TRACE_GRP_4BIT_IO {} \ + CONFIG.PCW_TRACE_INTERNAL_WIDTH {2} \ + CONFIG.PCW_TRACE_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_TRACE_PIPELINE_WIDTH {8} \ + CONFIG.PCW_TRACE_TRACE_IO {} \ + CONFIG.PCW_TTC1_BASEADDR {0xE0105000} \ + CONFIG.PCW_TTC1_CLK0_PERIPHERAL_CLKSRC {CPU_1X} \ + CONFIG.PCW_TTC1_CLK0_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_TTC1_CLK0_PERIPHERAL_FREQMHZ {133.333333} \ + CONFIG.PCW_TTC1_CLK1_PERIPHERAL_CLKSRC {CPU_1X} \ + CONFIG.PCW_TTC1_CLK1_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_TTC1_CLK1_PERIPHERAL_FREQMHZ {133.333333} \ + CONFIG.PCW_TTC1_CLK2_PERIPHERAL_CLKSRC {CPU_1X} \ + CONFIG.PCW_TTC1_CLK2_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_TTC1_CLK2_PERIPHERAL_FREQMHZ {133.333333} \ + CONFIG.PCW_TTC1_HIGHADDR {0xE0105fff} \ + CONFIG.PCW_TTC1_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_TTC1_TTC1_IO {} \ + CONFIG.PCW_UART0_HIGHADDR {0xE0000FFF} \ + CONFIG.PCW_UART0_PERIPHERAL_ENABLE {1} \ + CONFIG.PCW_UART0_UART0_IO {MIO 14 .. 15} \ + CONFIG.PCW_UART1_BASEADDR {0xE0001000} \ + CONFIG.PCW_UART1_BAUD_RATE {115200} \ + CONFIG.PCW_UART1_GRP_FULL_ENABLE {0} \ + CONFIG.PCW_UART1_GRP_FULL_IO {} \ + CONFIG.PCW_UART_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_UART_PERIPHERAL_DIVISOR0 {10} \ + CONFIG.PCW_UART_PERIPHERAL_FREQMHZ {100} \ + CONFIG.PCW_UART_PERIPHERAL_VALID {1} \ + CONFIG.PCW_UIPARAM_ACT_DDR_FREQ_MHZ {525.000000} \ + CONFIG.PCW_UIPARAM_DDR_ADV_ENABLE {0} \ + CONFIG.PCW_UIPARAM_DDR_AL {0} \ + CONFIG.PCW_UIPARAM_DDR_BANK_ADDR_COUNT {3} \ + CONFIG.PCW_UIPARAM_DDR_BL {8} \ + CONFIG.PCW_UIPARAM_DDR_BOARD_DELAY0 {0.223} \ + CONFIG.PCW_UIPARAM_DDR_BOARD_DELAY1 {0.212} \ + CONFIG.PCW_UIPARAM_DDR_BOARD_DELAY2 {0.085} \ + CONFIG.PCW_UIPARAM_DDR_BOARD_DELAY3 {0.092} \ + CONFIG.PCW_UIPARAM_DDR_BUS_WIDTH {16 Bit} \ + CONFIG.PCW_UIPARAM_DDR_CL {7} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_0_LENGTH_MM {25.8} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_0_PACKAGE_LENGTH {80.4535} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_0_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_1_LENGTH_MM {25.8} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_1_PACKAGE_LENGTH {80.4535} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_1_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_2_LENGTH_MM {0} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_2_PACKAGE_LENGTH {80.4535} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_2_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_3_LENGTH_MM {0} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_3_PACKAGE_LENGTH {80.4535} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_3_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_STOP_EN {0} \ + CONFIG.PCW_UIPARAM_DDR_COL_ADDR_COUNT {10} \ + CONFIG.PCW_UIPARAM_DDR_CWL {6} \ + CONFIG.PCW_UIPARAM_DDR_DEVICE_CAPACITY {4096 MBits} \ + CONFIG.PCW_UIPARAM_DDR_DQS_0_LENGTH_MM {15.6} \ + CONFIG.PCW_UIPARAM_DDR_DQS_0_PACKAGE_LENGTH {105.056} \ + CONFIG.PCW_UIPARAM_DDR_DQS_0_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_DQS_1_LENGTH_MM {18.8} \ + CONFIG.PCW_UIPARAM_DDR_DQS_1_PACKAGE_LENGTH {66.904} \ + CONFIG.PCW_UIPARAM_DDR_DQS_1_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_DQS_2_LENGTH_MM {0} \ + CONFIG.PCW_UIPARAM_DDR_DQS_2_PACKAGE_LENGTH {89.1715} \ + CONFIG.PCW_UIPARAM_DDR_DQS_2_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_DQS_3_LENGTH_MM {0} \ + CONFIG.PCW_UIPARAM_DDR_DQS_3_PACKAGE_LENGTH {113.63} \ + CONFIG.PCW_UIPARAM_DDR_DQS_3_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_DQS_TO_CLK_DELAY_0 {0.040} \ + CONFIG.PCW_UIPARAM_DDR_DQS_TO_CLK_DELAY_1 {0.058} \ + CONFIG.PCW_UIPARAM_DDR_DQS_TO_CLK_DELAY_2 {-0.009} \ + CONFIG.PCW_UIPARAM_DDR_DQS_TO_CLK_DELAY_3 {-0.033} \ + CONFIG.PCW_UIPARAM_DDR_DQ_0_LENGTH_MM {16.5} \ + CONFIG.PCW_UIPARAM_DDR_DQ_0_PACKAGE_LENGTH {98.503} \ + CONFIG.PCW_UIPARAM_DDR_DQ_0_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_DQ_1_LENGTH_MM {18} \ + CONFIG.PCW_UIPARAM_DDR_DQ_1_PACKAGE_LENGTH {68.5855} \ + CONFIG.PCW_UIPARAM_DDR_DQ_1_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_DQ_2_LENGTH_MM {0} \ + CONFIG.PCW_UIPARAM_DDR_DQ_2_PACKAGE_LENGTH {90.295} \ + CONFIG.PCW_UIPARAM_DDR_DQ_2_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_DQ_3_LENGTH_MM {0} \ + CONFIG.PCW_UIPARAM_DDR_DQ_3_PACKAGE_LENGTH {103.977} \ + CONFIG.PCW_UIPARAM_DDR_DQ_3_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_DRAM_WIDTH {16 Bits} \ + CONFIG.PCW_UIPARAM_DDR_ECC {Disabled} \ + CONFIG.PCW_UIPARAM_DDR_ENABLE {1} \ + CONFIG.PCW_UIPARAM_DDR_FREQ_MHZ {525} \ + CONFIG.PCW_UIPARAM_DDR_HIGH_TEMP {Normal (0-85)} \ + CONFIG.PCW_UIPARAM_DDR_MEMORY_TYPE {DDR 3} \ + CONFIG.PCW_UIPARAM_DDR_PARTNO {MT41J256M16 RE-125} \ + CONFIG.PCW_UIPARAM_DDR_ROW_ADDR_COUNT {15} \ + CONFIG.PCW_UIPARAM_DDR_SPEED_BIN {DDR3_1066F} \ + CONFIG.PCW_UIPARAM_DDR_TRAIN_DATA_EYE {1} \ + CONFIG.PCW_UIPARAM_DDR_TRAIN_READ_GATE {1} \ + CONFIG.PCW_UIPARAM_DDR_TRAIN_WRITE_LEVEL {1} \ + CONFIG.PCW_UIPARAM_DDR_T_FAW {40.0} \ + CONFIG.PCW_UIPARAM_DDR_T_RAS_MIN {35.0} \ + CONFIG.PCW_UIPARAM_DDR_T_RC {48.91} \ + CONFIG.PCW_UIPARAM_DDR_T_RCD {7} \ + CONFIG.PCW_UIPARAM_DDR_T_RP {7} \ + CONFIG.PCW_UIPARAM_DDR_USE_INTERNAL_VREF {0} \ + CONFIG.PCW_UIPARAM_GENERATE_SUMMARY {NA} \ + CONFIG.PCW_USB0_BASEADDR {0xE0102000} \ + CONFIG.PCW_USB0_HIGHADDR {0xE0102fff} \ + CONFIG.PCW_USB0_PERIPHERAL_ENABLE {1} \ + CONFIG.PCW_USB0_PERIPHERAL_FREQMHZ {60} \ + CONFIG.PCW_USB0_RESET_ENABLE {1} \ + CONFIG.PCW_USB0_RESET_IO {MIO 46} \ + CONFIG.PCW_USB0_USB0_IO {MIO 28 .. 39} \ + CONFIG.PCW_USB1_BASEADDR {0xE0103000} \ + CONFIG.PCW_USB1_HIGHADDR {0xE0103fff} \ + CONFIG.PCW_USB1_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_USB1_PERIPHERAL_FREQMHZ {60} \ + CONFIG.PCW_USB1_RESET_ENABLE {0} \ + CONFIG.PCW_USB1_RESET_IO {} \ + CONFIG.PCW_USB_RESET_ENABLE {1} \ + CONFIG.PCW_USB_RESET_POLARITY {Active Low} \ + CONFIG.PCW_USB_RESET_SELECT {Share reset pin} \ + CONFIG.PCW_USE_AXI_FABRIC_IDLE {0} \ + CONFIG.PCW_USE_AXI_NONSECURE {0} \ + CONFIG.PCW_USE_CORESIGHT {0} \ + CONFIG.PCW_USE_CROSS_TRIGGER {0} \ + CONFIG.PCW_USE_CR_FABRIC {1} \ + CONFIG.PCW_USE_DDR_BYPASS {0} \ + CONFIG.PCW_USE_DEBUG {0} \ + CONFIG.PCW_USE_DEFAULT_ACP_USER_VAL {0} \ + CONFIG.PCW_USE_DMA0 {0} \ + CONFIG.PCW_USE_DMA1 {0} \ + CONFIG.PCW_USE_DMA2 {0} \ + CONFIG.PCW_USE_DMA3 {0} \ + CONFIG.PCW_USE_EXPANDED_IOP {0} \ + CONFIG.PCW_USE_EXPANDED_PS_SLCR_REGISTERS {0} \ + CONFIG.PCW_USE_FABRIC_INTERRUPT {0} \ + CONFIG.PCW_USE_HIGH_OCM {0} \ + CONFIG.PCW_USE_M_AXI_GP0 {1} \ + CONFIG.PCW_USE_M_AXI_GP1 {0} \ + CONFIG.PCW_USE_PROC_EVENT_BUS {0} \ + CONFIG.PCW_USE_PS_SLCR_REGISTERS {0} \ + CONFIG.PCW_USE_S_AXI_ACP {0} \ + CONFIG.PCW_USE_S_AXI_GP0 {0} \ + CONFIG.PCW_USE_S_AXI_GP1 {0} \ + CONFIG.PCW_USE_S_AXI_HP0 {0} \ + CONFIG.PCW_USE_S_AXI_HP1 {0} \ + CONFIG.PCW_USE_S_AXI_HP2 {0} \ + CONFIG.PCW_USE_S_AXI_HP3 {0} \ + CONFIG.PCW_USE_TRACE {0} \ + CONFIG.PCW_USE_TRACE_DATA_EDGE_DETECTOR {0} \ + CONFIG.PCW_VALUE_SILVERSION {3} \ + CONFIG.PCW_WDT_PERIPHERAL_CLKSRC {CPU_1X} \ + CONFIG.PCW_WDT_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_WDT_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_WDT_PERIPHERAL_FREQMHZ {133.333333} \ + CONFIG.PCW_WDT_WDT_IO {} \ + CONFIG.PCW_CAN0_GRP_CLK_ENABLE {0} \ + CONFIG.PCW_CAN0_GRP_CLK_IO {} \ + CONFIG.PCW_CAN1_GRP_CLK_ENABLE {0} \ + CONFIG.PCW_CAN1_GRP_CLK_IO {} \ + CONFIG.PCW_DDR_PRIORITY_READPORT_1 {} \ + CONFIG.PCW_DDR_PRIORITY_READPORT_3 {} \ + CONFIG.PCW_DDR_PRIORITY_WRITEPORT_1 {} \ + CONFIG.PCW_DDR_PRIORITY_WRITEPORT_3 {} \ + CONFIG.PCW_ENET1_GRP_MDIO_ENABLE {0} \ + CONFIG.PCW_ENET1_GRP_MDIO_IO {} \ + CONFIG.PCW_ENET_RESET_ENABLE {1} \ + CONFIG.PCW_ENET_RESET_POLARITY {Active Low} \ + CONFIG.PCW_ENET_RESET_SELECT {Share reset pin} \ + CONFIG.PCW_EN_4K_TIMER {0} \ + CONFIG.PCW_EN_CAN0 {0} \ + CONFIG.PCW_EN_CAN1 {0} \ + CONFIG.PCW_EN_CLK0_PORT {1} \ + CONFIG.PCW_EN_CLK1_PORT {0} \ + CONFIG.PCW_EN_CLK2_PORT {0} \ + CONFIG.PCW_EN_CLK3_PORT {0} \ + CONFIG.PCW_EN_CLKTRIG0_PORT {0} \ + CONFIG.PCW_EN_CLKTRIG1_PORT {0} \ + CONFIG.PCW_EN_CLKTRIG2_PORT {0} \ + CONFIG.PCW_EN_CLKTRIG3_PORT {0} \ + CONFIG.PCW_EN_DDR {1} \ + CONFIG.PCW_EN_EMIO_CAN0 {0} \ + CONFIG.PCW_EN_EMIO_CAN1 {0} \ + CONFIG.PCW_EN_EMIO_CD_SDIO0 {0} \ + CONFIG.PCW_EN_EMIO_CD_SDIO1 {0} \ + CONFIG.PCW_EN_EMIO_ENET0 {0} \ + CONFIG.PCW_EN_EMIO_ENET1 {0} \ + CONFIG.PCW_EN_EMIO_GPIO {0} \ + CONFIG.PCW_EN_EMIO_I2C0 {0} \ + CONFIG.PCW_EN_EMIO_I2C1 {0} \ + CONFIG.PCW_EN_EMIO_MODEM_UART0 {0} \ + CONFIG.PCW_EN_EMIO_MODEM_UART1 {0} \ + CONFIG.PCW_EN_EMIO_PJTAG {0} \ + CONFIG.PCW_EN_EMIO_SDIO0 {0} \ + CONFIG.PCW_EN_EMIO_SDIO1 {0} \ + CONFIG.PCW_EN_EMIO_SPI0 {0} \ + CONFIG.PCW_EN_EMIO_SPI1 {0} \ + CONFIG.PCW_EN_EMIO_SRAM_INT {0} \ + CONFIG.PCW_EN_EMIO_TRACE {0} \ + CONFIG.PCW_EN_EMIO_TTC0 {0} \ + CONFIG.PCW_EN_EMIO_TTC1 {0} \ + CONFIG.PCW_EN_EMIO_UART0 {0} \ + CONFIG.PCW_EN_EMIO_UART1 {0} \ + CONFIG.PCW_EN_EMIO_WDT {0} \ + CONFIG.PCW_EN_EMIO_WP_SDIO0 {0} \ + CONFIG.PCW_EN_EMIO_WP_SDIO1 {0} \ + CONFIG.PCW_EN_ENET0 {1} \ + CONFIG.PCW_EN_ENET1 {0} \ + CONFIG.PCW_EN_GPIO {1} \ + CONFIG.PCW_EN_I2C0 {0} \ + CONFIG.PCW_EN_I2C1 {0} \ + CONFIG.PCW_EN_MODEM_UART0 {0} \ + CONFIG.PCW_EN_MODEM_UART1 {0} \ + CONFIG.PCW_EN_PJTAG {0} \ + CONFIG.PCW_EN_PTP_ENET0 {0} \ + CONFIG.PCW_EN_PTP_ENET1 {0} \ + CONFIG.PCW_EN_QSPI {1} \ + CONFIG.PCW_EN_RST0_PORT {1} \ + CONFIG.PCW_EN_RST1_PORT {0} \ + CONFIG.PCW_EN_RST2_PORT {0} \ + CONFIG.PCW_EN_RST3_PORT {0} \ + CONFIG.PCW_EN_SDIO0 {1} \ + CONFIG.PCW_EN_SDIO1 {0} \ + CONFIG.PCW_EN_SMC {0} \ + CONFIG.PCW_EN_SPI0 {0} \ + CONFIG.PCW_EN_SPI1 {0} \ + CONFIG.PCW_EN_TRACE {0} \ + CONFIG.PCW_EN_TTC0 {0} \ + CONFIG.PCW_EN_TTC1 {0} \ + CONFIG.PCW_EN_UART0 {1} \ + CONFIG.PCW_EN_UART1 {0} \ + CONFIG.PCW_EN_USB0 {1} \ + CONFIG.PCW_EN_USB1 {0} \ + CONFIG.PCW_EN_WDT {0} \ + CONFIG.PCW_FCLK0_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_FCLK0_PERIPHERAL_DIVISOR0 {5} \ + CONFIG.PCW_FCLK0_PERIPHERAL_DIVISOR1 {2} \ + CONFIG.PCW_FCLK1_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_FCLK1_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_FCLK1_PERIPHERAL_DIVISOR1 {1} \ + CONFIG.PCW_FCLK2_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_FCLK2_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_FCLK2_PERIPHERAL_DIVISOR1 {1} \ + CONFIG.PCW_FCLK3_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_FCLK3_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_FCLK3_PERIPHERAL_DIVISOR1 {1} \ + CONFIG.PCW_FCLK_CLK0_BUF {TRUE} \ + CONFIG.PCW_FCLK_CLK1_BUF {FALSE} \ + CONFIG.PCW_FCLK_CLK2_BUF {FALSE} \ + CONFIG.PCW_FCLK_CLK3_BUF {FALSE} \ + CONFIG.PCW_FPGA0_PERIPHERAL_FREQMHZ {100} \ + CONFIG.PCW_FPGA1_PERIPHERAL_FREQMHZ {50} \ + CONFIG.PCW_FPGA2_PERIPHERAL_FREQMHZ {50} \ + CONFIG.PCW_FPGA3_PERIPHERAL_FREQMHZ {50} \ + CONFIG.PCW_FPGA_FCLK0_ENABLE {1} \ + CONFIG.PCW_FPGA_FCLK1_ENABLE {0} \ + CONFIG.PCW_FPGA_FCLK2_ENABLE {0} \ + CONFIG.PCW_FPGA_FCLK3_ENABLE {0} \ + CONFIG.PCW_FTM_CTI_IN0 {} \ + CONFIG.PCW_FTM_CTI_IN2 {} \ + CONFIG.PCW_FTM_CTI_OUT0 {} \ + CONFIG.PCW_FTM_CTI_OUT2 {} \ + CONFIG.PCW_GPIO_BASEADDR {0xE000A000} \ + CONFIG.PCW_GPIO_EMIO_GPIO_ENABLE {0} \ + CONFIG.PCW_GPIO_EMIO_GPIO_IO {} \ + CONFIG.PCW_I2C0_HIGHADDR {0xE0004FFF} \ + CONFIG.PCW_I2C0_I2C0_IO {} \ + CONFIG.PCW_I2C1_BASEADDR {0xE0005000} \ + CONFIG.PCW_I2C1_GRP_INT_ENABLE {0} \ + CONFIG.PCW_I2C1_GRP_INT_IO {} \ + CONFIG.PCW_I2C1_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_I2C1_RESET_ENABLE {0} \ + CONFIG.PCW_I2C1_RESET_IO {} \ + CONFIG.PCW_IMPORT_BOARD_PRESET {None} \ + CONFIG.PCW_INCLUDE_ACP_TRANS_CHECK {0} \ + CONFIG.PCW_INCLUDE_TRACE_BUFFER {0} \ + CONFIG.PCW_IOPLL_CTRL_FBDIV {20} \ + CONFIG.PCW_IO_IO_PLL_FREQMHZ {1000.000} \ + CONFIG.PCW_IRQ_F2P_INTR {0} \ + CONFIG.PCW_IRQ_F2P_MODE {DIRECT} \ + CONFIG.PCW_MIO_0_DIRECTION {inout} \ + CONFIG.PCW_MIO_0_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_0_PULLUP {enabled} \ + CONFIG.PCW_MIO_0_SLEW {slow} \ + CONFIG.PCW_MIO_10_DIRECTION {inout} \ + CONFIG.PCW_MIO_10_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_10_PULLUP {enabled} \ + CONFIG.PCW_MIO_10_SLEW {slow} \ + CONFIG.PCW_MIO_11_DIRECTION {inout} \ + CONFIG.PCW_MIO_11_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_11_PULLUP {enabled} \ + CONFIG.PCW_MIO_11_SLEW {slow} \ + CONFIG.PCW_MIO_12_DIRECTION {inout} \ + CONFIG.PCW_MIO_12_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_12_PULLUP {enabled} \ + CONFIG.PCW_MIO_12_SLEW {slow} \ + CONFIG.PCW_MIO_13_DIRECTION {inout} \ + CONFIG.PCW_MIO_13_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_13_PULLUP {enabled} \ + CONFIG.PCW_MIO_13_SLEW {slow} \ + CONFIG.PCW_MIO_14_DIRECTION {in} \ + CONFIG.PCW_MIO_14_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_14_PULLUP {enabled} \ + CONFIG.PCW_MIO_14_SLEW {slow} \ + CONFIG.PCW_MIO_15_DIRECTION {out} \ + CONFIG.PCW_MIO_15_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_15_PULLUP {enabled} \ + CONFIG.PCW_MIO_15_SLEW {slow} \ + CONFIG.PCW_MIO_16_DIRECTION {out} \ + CONFIG.PCW_MIO_16_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_16_PULLUP {enabled} \ + CONFIG.PCW_MIO_16_SLEW {slow} \ + CONFIG.PCW_MIO_17_DIRECTION {out} \ + CONFIG.PCW_MIO_17_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_17_PULLUP {enabled} \ + CONFIG.PCW_MIO_17_SLEW {slow} \ + CONFIG.PCW_MIO_18_DIRECTION {out} \ + CONFIG.PCW_MIO_18_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_18_PULLUP {enabled} \ + CONFIG.PCW_MIO_18_SLEW {slow} \ + CONFIG.PCW_MIO_19_DIRECTION {out} \ + CONFIG.PCW_MIO_19_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_19_PULLUP {enabled} \ + CONFIG.PCW_MIO_19_SLEW {slow} \ + CONFIG.PCW_MIO_1_DIRECTION {out} \ + CONFIG.PCW_MIO_1_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_1_PULLUP {enabled} \ + CONFIG.PCW_MIO_1_SLEW {slow} \ + CONFIG.PCW_MIO_20_DIRECTION {out} \ + CONFIG.PCW_MIO_20_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_20_PULLUP {enabled} \ + CONFIG.PCW_MIO_20_SLEW {slow} \ + CONFIG.PCW_MIO_21_DIRECTION {out} \ + CONFIG.PCW_MIO_21_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_21_PULLUP {enabled} \ + CONFIG.PCW_MIO_21_SLEW {slow} \ + CONFIG.PCW_MIO_22_DIRECTION {in} \ + CONFIG.PCW_MIO_22_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_22_PULLUP {enabled} \ + CONFIG.PCW_MIO_22_SLEW {slow} \ + CONFIG.PCW_MIO_23_DIRECTION {in} \ + CONFIG.PCW_MIO_23_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_23_PULLUP {enabled} \ + CONFIG.PCW_MIO_23_SLEW {slow} \ + CONFIG.PCW_MIO_24_DIRECTION {in} \ + CONFIG.PCW_MIO_24_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_24_PULLUP {enabled} \ + CONFIG.PCW_MIO_24_SLEW {slow} \ + CONFIG.PCW_MIO_25_DIRECTION {in} \ + CONFIG.PCW_MIO_25_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_25_PULLUP {enabled} \ + CONFIG.PCW_MIO_25_SLEW {slow} \ + CONFIG.PCW_MIO_26_DIRECTION {in} \ + CONFIG.PCW_MIO_26_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_26_PULLUP {enabled} \ + CONFIG.PCW_MIO_26_SLEW {slow} \ + CONFIG.PCW_MIO_27_DIRECTION {in} \ + CONFIG.PCW_MIO_27_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_27_PULLUP {enabled} \ + CONFIG.PCW_MIO_27_SLEW {slow} \ + CONFIG.PCW_MIO_28_DIRECTION {inout} \ + CONFIG.PCW_MIO_28_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_28_PULLUP {enabled} \ + CONFIG.PCW_MIO_28_SLEW {slow} \ + CONFIG.PCW_MIO_29_DIRECTION {in} \ + CONFIG.PCW_MIO_29_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_29_PULLUP {enabled} \ + CONFIG.PCW_MIO_29_SLEW {slow} \ + CONFIG.PCW_MIO_2_DIRECTION {inout} \ + CONFIG.PCW_MIO_2_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_2_PULLUP {disabled} \ + CONFIG.PCW_MIO_2_SLEW {slow} \ + CONFIG.PCW_MIO_30_DIRECTION {out} \ + CONFIG.PCW_MIO_30_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_30_PULLUP {enabled} \ + CONFIG.PCW_MIO_30_SLEW {slow} \ + CONFIG.PCW_MIO_31_DIRECTION {in} \ + CONFIG.PCW_MIO_31_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_31_PULLUP {enabled} \ + CONFIG.PCW_MIO_31_SLEW {slow} \ + CONFIG.PCW_MIO_32_DIRECTION {inout} \ + CONFIG.PCW_MIO_32_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_32_PULLUP {enabled} \ + CONFIG.PCW_MIO_32_SLEW {slow} \ + CONFIG.PCW_MIO_33_DIRECTION {inout} \ + CONFIG.PCW_MIO_33_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_33_PULLUP {enabled} \ + CONFIG.PCW_MIO_33_SLEW {slow} \ + CONFIG.PCW_MIO_34_DIRECTION {inout} \ + CONFIG.PCW_MIO_34_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_34_PULLUP {enabled} \ + CONFIG.PCW_MIO_34_SLEW {slow} \ + CONFIG.PCW_MIO_35_DIRECTION {inout} \ + CONFIG.PCW_MIO_35_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_35_PULLUP {enabled} \ + CONFIG.PCW_MIO_35_SLEW {slow} \ + CONFIG.PCW_MIO_36_DIRECTION {in} \ + CONFIG.PCW_MIO_36_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_36_PULLUP {enabled} \ + CONFIG.PCW_MIO_36_SLEW {slow} \ + CONFIG.PCW_MIO_37_DIRECTION {inout} \ + CONFIG.PCW_MIO_37_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_37_PULLUP {enabled} \ + CONFIG.PCW_MIO_37_SLEW {slow} \ + CONFIG.PCW_MIO_38_DIRECTION {inout} \ + CONFIG.PCW_MIO_38_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_38_PULLUP {enabled} \ + CONFIG.PCW_MIO_38_SLEW {slow} \ + CONFIG.PCW_MIO_39_DIRECTION {inout} \ + CONFIG.PCW_MIO_39_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_39_PULLUP {enabled} \ + CONFIG.PCW_MIO_39_SLEW {slow} \ + CONFIG.PCW_MIO_3_DIRECTION {inout} \ + CONFIG.PCW_MIO_3_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_3_PULLUP {disabled} \ + CONFIG.PCW_MIO_3_SLEW {slow} \ + CONFIG.PCW_MIO_40_DIRECTION {inout} \ + CONFIG.PCW_MIO_40_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_40_PULLUP {enabled} \ + CONFIG.PCW_MIO_40_SLEW {slow} \ + CONFIG.PCW_MIO_41_DIRECTION {inout} \ + CONFIG.PCW_MIO_41_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_41_PULLUP {enabled} \ + CONFIG.PCW_MIO_41_SLEW {slow} \ + CONFIG.PCW_MIO_42_DIRECTION {inout} \ + CONFIG.PCW_MIO_42_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_42_PULLUP {enabled} \ + CONFIG.PCW_MIO_42_SLEW {slow} \ + CONFIG.PCW_MIO_43_DIRECTION {inout} \ + CONFIG.PCW_MIO_43_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_43_PULLUP {enabled} \ + CONFIG.PCW_MIO_43_SLEW {slow} \ + CONFIG.PCW_MIO_44_DIRECTION {inout} \ + CONFIG.PCW_MIO_44_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_44_PULLUP {enabled} \ + CONFIG.PCW_MIO_44_SLEW {slow} \ + CONFIG.PCW_MIO_45_DIRECTION {inout} \ + CONFIG.PCW_MIO_45_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_45_PULLUP {enabled} \ + CONFIG.PCW_MIO_45_SLEW {slow} \ + CONFIG.PCW_MIO_46_DIRECTION {out} \ + CONFIG.PCW_MIO_46_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_46_PULLUP {enabled} \ + CONFIG.PCW_MIO_46_SLEW {slow} \ + CONFIG.PCW_MIO_47_DIRECTION {in} \ + CONFIG.PCW_MIO_47_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_47_PULLUP {enabled} \ + CONFIG.PCW_MIO_47_SLEW {slow} \ + CONFIG.PCW_MIO_48_DIRECTION {inout} \ + CONFIG.PCW_MIO_48_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_48_PULLUP {enabled} \ + CONFIG.PCW_MIO_48_SLEW {slow} \ + CONFIG.PCW_MIO_49_DIRECTION {inout} \ + CONFIG.PCW_MIO_49_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_49_PULLUP {enabled} \ + CONFIG.PCW_MIO_49_SLEW {slow} \ + CONFIG.PCW_MIO_4_DIRECTION {inout} \ + CONFIG.PCW_MIO_4_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_4_PULLUP {disabled} \ + CONFIG.PCW_MIO_4_SLEW {slow} \ + CONFIG.PCW_MIO_50_DIRECTION {inout} \ + CONFIG.PCW_MIO_50_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_50_PULLUP {enabled} \ + CONFIG.PCW_MIO_50_SLEW {slow} \ + CONFIG.PCW_MIO_51_DIRECTION {inout} \ + CONFIG.PCW_MIO_51_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_51_PULLUP {enabled} \ + CONFIG.PCW_MIO_51_SLEW {slow} \ + CONFIG.PCW_MIO_52_DIRECTION {out} \ + CONFIG.PCW_MIO_52_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_52_PULLUP {enabled} \ + CONFIG.PCW_MIO_52_SLEW {slow} \ + CONFIG.PCW_MIO_53_DIRECTION {inout} \ + CONFIG.PCW_MIO_53_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_53_PULLUP {enabled} \ + CONFIG.PCW_MIO_53_SLEW {slow} \ + CONFIG.PCW_MIO_5_DIRECTION {inout} \ + CONFIG.PCW_MIO_5_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_5_PULLUP {disabled} \ + CONFIG.PCW_MIO_5_SLEW {slow} \ + CONFIG.PCW_MIO_6_DIRECTION {out} \ + CONFIG.PCW_MIO_6_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_6_PULLUP {disabled} \ + CONFIG.PCW_MIO_6_SLEW {slow} \ + CONFIG.PCW_MIO_7_DIRECTION {out} \ + CONFIG.PCW_MIO_7_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_7_PULLUP {disabled} \ + CONFIG.PCW_MIO_7_SLEW {slow} \ + CONFIG.PCW_MIO_8_DIRECTION {out} \ + CONFIG.PCW_MIO_8_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_8_PULLUP {disabled} \ + CONFIG.PCW_MIO_8_SLEW {slow} \ + CONFIG.PCW_MIO_9_DIRECTION {out} \ + CONFIG.PCW_MIO_9_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_9_PULLUP {enabled} \ + CONFIG.PCW_MIO_9_SLEW {slow} \ + CONFIG.PCW_MIO_PRIMITIVE {54} \ + CONFIG.PCW_MIO_TREE_PERIPHERALS {GPIO#Quad SPI Flash#Quad SPI Flash#Quad SPI Flash#Quad SPI Flash#Quad SPI Flash#Quad SPI Flash#GPIO#Quad SPI Flash#ENET Reset#GPIO#GPIO#GPIO#GPIO#UART 0#UART 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#SD 0#SD 0#SD 0#SD 0#SD 0#SD 0#USB Reset#SD 0#GPIO#GPIO#GPIO#GPIO#Enet 0#Enet 0} \ + CONFIG.PCW_MIO_TREE_SIGNALS {gpio[0]#qspi0_ss_b#qspi0_io[0]#qspi0_io[1]#qspi0_io[2]#qspi0_io[3]/HOLD_B#qspi0_sclk#gpio[7]#qspi_fbclk#reset#gpio[10]#gpio[11]#gpio[12]#gpio[13]#rx#tx#tx_clk#txd[0]#txd[1]#txd[2]#txd[3]#tx_ctl#rx_clk#rxd[0]#rxd[1]#rxd[2]#rxd[3]#rx_ctl#data[4]#dir#stp#nxt#data[0]#data[1]#data[2]#data[3]#clk#data[5]#data[6]#data[7]#clk#cmd#data[0]#data[1]#data[2]#data[3]#reset#cd#gpio[48]#gpio[49]#gpio[50]#gpio[51]#mdc#mdio} \ + CONFIG.PCW_M_AXI_GP0_ENABLE_STATIC_REMAP {0} \ + CONFIG.PCW_M_AXI_GP0_ID_WIDTH {12} \ + CONFIG.PCW_M_AXI_GP0_SUPPORT_NARROW_BURST {0} \ + CONFIG.PCW_M_AXI_GP0_THREAD_ID_WIDTH {12} \ + CONFIG.PCW_M_AXI_GP1_ENABLE_STATIC_REMAP {0} \ + CONFIG.PCW_M_AXI_GP1_ID_WIDTH {12} \ + CONFIG.PCW_M_AXI_GP1_SUPPORT_NARROW_BURST {0} \ + CONFIG.PCW_M_AXI_GP1_THREAD_ID_WIDTH {12} \ + CONFIG.PCW_NAND_CYCLES_T_AR {1} \ + CONFIG.PCW_NAND_CYCLES_T_CLR {1} \ + CONFIG.PCW_NAND_CYCLES_T_RC {11} \ + CONFIG.PCW_NAND_CYCLES_T_REA {1} \ + CONFIG.PCW_NAND_CYCLES_T_RR {1} \ + CONFIG.PCW_NAND_CYCLES_T_WC {11} \ + CONFIG.PCW_NAND_CYCLES_T_WP {1} \ + CONFIG.PCW_NAND_GRP_D8_ENABLE {0} \ + CONFIG.PCW_NAND_GRP_D8_IO {} \ + CONFIG.PCW_NAND_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_NOR_CS0_T_CEOE {1} \ + CONFIG.PCW_NOR_CS0_T_PC {1} \ + CONFIG.PCW_NOR_CS0_T_RC {11} \ + CONFIG.PCW_NOR_CS0_T_TR {1} \ + CONFIG.PCW_NOR_CS0_T_WC {11} \ + CONFIG.PCW_NOR_CS0_T_WP {1} \ + CONFIG.PCW_NOR_CS0_WE_TIME {0} \ + CONFIG.PCW_NOR_CS1_T_CEOE {1} \ + CONFIG.PCW_NOR_CS1_T_PC {1} \ + CONFIG.PCW_NOR_CS1_T_RC {11} \ + CONFIG.PCW_NOR_CS1_T_TR {1} \ + CONFIG.PCW_NOR_CS1_T_WC {11} \ + CONFIG.PCW_NOR_CS1_T_WP {1} \ + CONFIG.PCW_NOR_CS1_WE_TIME {0} \ + CONFIG.PCW_NOR_GRP_A25_ENABLE {0} \ + CONFIG.PCW_NOR_GRP_A25_IO {} \ + CONFIG.PCW_NOR_GRP_CS1_ENABLE {0} \ + CONFIG.PCW_NOR_GRP_CS1_IO {} \ + CONFIG.PCW_NOR_GRP_SRAM_CS1_ENABLE {0} \ + CONFIG.PCW_NOR_GRP_SRAM_CS1_IO {} \ + CONFIG.PCW_NOR_NOR_IO {} \ + CONFIG.PCW_PLL_BYPASSMODE_ENABLE {0} \ + CONFIG.PCW_PRESET_BANK0_VOLTAGE {LVCMOS 3.3V} \ + CONFIG.PCW_PRESET_BANK1_VOLTAGE {LVCMOS 1.8V} \ + CONFIG.PCW_PS7_SI_REV {PRODUCTION} \ + CONFIG.PCW_QSPI_GRP_FBCLK_ENABLE {1} \ + CONFIG.PCW_QSPI_GRP_FBCLK_IO {MIO 8} \ + CONFIG.PCW_QSPI_GRP_IO1_ENABLE {0} \ + CONFIG.PCW_QSPI_GRP_IO1_IO {} \ + CONFIG.PCW_QSPI_INTERNAL_HIGHADDRESS {0xFCFFFFFF} \ + CONFIG.PCW_QSPI_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_QSPI_PERIPHERAL_DIVISOR0 {5} \ + CONFIG.PCW_QSPI_PERIPHERAL_ENABLE {1} \ + CONFIG.PCW_QSPI_PERIPHERAL_FREQMHZ {200} \ + CONFIG.PCW_QSPI_QSPI_IO {MIO 1 .. 6} \ + CONFIG.PCW_SD0_GRP_CD_ENABLE {1} \ + CONFIG.PCW_SD0_GRP_CD_IO {MIO 47} \ + CONFIG.PCW_SD0_GRP_POW_ENABLE {0} \ + CONFIG.PCW_SD0_GRP_POW_IO {} \ + CONFIG.PCW_SD0_PERIPHERAL_ENABLE {1} \ + CONFIG.PCW_SD0_SD0_IO {MIO 40 .. 45} \ + CONFIG.PCW_SD1_GRP_CD_ENABLE {0} \ + CONFIG.PCW_SD1_GRP_CD_IO {} \ + CONFIG.PCW_SD1_GRP_WP_ENABLE {0} \ + CONFIG.PCW_SD1_GRP_WP_IO {} \ + CONFIG.PCW_SDIO0_BASEADDR {0xE0100000} \ + CONFIG.PCW_SDIO0_HIGHADDR {0xE0100FFF} \ + CONFIG.PCW_SDIO1_BASEADDR {0xE0101000} \ + CONFIG.PCW_SDIO1_HIGHADDR {0xE0101FFF} \ + CONFIG.PCW_SDIO_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_SDIO_PERIPHERAL_DIVISOR0 {20} \ + CONFIG.PCW_SDIO_PERIPHERAL_FREQMHZ {50} \ + CONFIG.PCW_SDIO_PERIPHERAL_VALID {1} \ + CONFIG.PCW_SINGLE_QSPI_DATA_MODE {x4} \ + CONFIG.PCW_SMC_CYCLE_T0 {NA} \ + CONFIG.PCW_SMC_CYCLE_T1 {NA} \ + CONFIG.PCW_SMC_CYCLE_T2 {NA} \ + CONFIG.PCW_SMC_CYCLE_T3 {NA} \ + CONFIG.PCW_SMC_CYCLE_T4 {NA} \ + CONFIG.PCW_SMC_CYCLE_T5 {NA} \ + CONFIG.PCW_SMC_CYCLE_T6 {NA} \ + CONFIG.PCW_SMC_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_SMC_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_SMC_PERIPHERAL_FREQMHZ {100} \ + CONFIG.PCW_SMC_PERIPHERAL_VALID {0} \ + CONFIG.PCW_SPI0_BASEADDR {0xE0006000} \ + CONFIG.PCW_SPI0_GRP_SS0_ENABLE {0} \ + CONFIG.PCW_SPI0_GRP_SS0_IO {} \ + CONFIG.PCW_SPI0_GRP_SS2_ENABLE {0} \ + CONFIG.PCW_SPI0_GRP_SS2_IO {} \ + CONFIG.PCW_SPI1_BASEADDR {0xE0007000} \ + CONFIG.PCW_SPI1_GRP_SS0_ENABLE {0} \ + CONFIG.PCW_SPI1_GRP_SS0_IO {} \ + CONFIG.PCW_SPI1_GRP_SS2_ENABLE {0} \ + CONFIG.PCW_SPI1_GRP_SS2_IO {} \ + CONFIG.PCW_SPI_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_SPI_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_SPI_PERIPHERAL_FREQMHZ {166.666666} \ + CONFIG.PCW_SPI_PERIPHERAL_VALID {0} \ + CONFIG.PCW_S_AXI_ACP_ARUSER_VAL {31} \ + CONFIG.PCW_S_AXI_ACP_AWUSER_VAL {31} \ + CONFIG.PCW_S_AXI_ACP_ID_WIDTH {3} \ + CONFIG.PCW_S_AXI_GP0_ID_WIDTH {6} \ + CONFIG.PCW_S_AXI_GP1_ID_WIDTH {6} \ + CONFIG.PCW_S_AXI_HP0_DATA_WIDTH {64} \ + CONFIG.PCW_S_AXI_HP0_ID_WIDTH {6} \ + CONFIG.PCW_S_AXI_HP1_DATA_WIDTH {64} \ + CONFIG.PCW_S_AXI_HP1_ID_WIDTH {6} \ + CONFIG.PCW_S_AXI_HP2_DATA_WIDTH {64} \ + CONFIG.PCW_S_AXI_HP2_ID_WIDTH {6} \ + CONFIG.PCW_S_AXI_HP3_DATA_WIDTH {64} \ + CONFIG.PCW_S_AXI_HP3_ID_WIDTH {6} \ + CONFIG.PCW_TPIU_PERIPHERAL_CLKSRC {External} \ + CONFIG.PCW_TPIU_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_TPIU_PERIPHERAL_FREQMHZ {200} \ + CONFIG.PCW_TRACE_BUFFER_CLOCK_DELAY {12} \ + CONFIG.PCW_TRACE_BUFFER_FIFO_SIZE {128} \ + CONFIG.PCW_TRACE_GRP_16BIT_ENABLE {0} \ + CONFIG.PCW_TRACE_GRP_16BIT_IO {} \ + CONFIG.PCW_TRACE_GRP_32BIT_ENABLE {0} \ + CONFIG.PCW_TRACE_GRP_32BIT_IO {} \ + CONFIG.PCW_TRACE_GRP_8BIT_ENABLE {0} \ + CONFIG.PCW_TRACE_GRP_8BIT_IO {} \ + CONFIG.PCW_TTC0_BASEADDR {0xE0104000} \ + CONFIG.PCW_TTC0_CLK0_PERIPHERAL_CLKSRC {CPU_1X} \ + CONFIG.PCW_TTC0_CLK0_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_TTC0_CLK0_PERIPHERAL_FREQMHZ {133.333333} \ + CONFIG.PCW_TTC0_CLK1_PERIPHERAL_CLKSRC {CPU_1X} \ + CONFIG.PCW_TTC0_CLK1_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_TTC0_CLK1_PERIPHERAL_FREQMHZ {133.333333} \ + CONFIG.PCW_TTC0_CLK2_PERIPHERAL_CLKSRC {CPU_1X} \ + CONFIG.PCW_TTC0_CLK2_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_TTC0_CLK2_PERIPHERAL_FREQMHZ {133.333333} \ + CONFIG.PCW_TTC0_HIGHADDR {0xE0104fff} \ + CONFIG.PCW_TTC0_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_TTC0_TTC0_IO {} \ + CONFIG.PCW_TTC_PERIPHERAL_FREQMHZ {50} \ + CONFIG.PCW_UART0_BASEADDR {0xE0000000} \ + CONFIG.PCW_UART0_BAUD_RATE {115200} \ + CONFIG.PCW_UART0_GRP_FULL_ENABLE {0} \ + CONFIG.PCW_UART0_GRP_FULL_IO {} \ + CONFIG.PCW_UART1_HIGHADDR {0xE0001FFF} \ + CONFIG.PCW_UART1_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_UART1_UART1_IO {} \ + CONFIG.PCW_USB1_USB1_IO {} \ + ] $processing_system7_0 + + # Create instance: ps7_0_axi_periph, and set properties + set ps7_0_axi_periph [ create_bd_cell -type ip -vlnv xilinx.com:ip:axi_interconnect:2.1 ps7_0_axi_periph ] + set_property -dict [ list \ + CONFIG.NUM_MI {2} \ + ] $ps7_0_axi_periph + + # Create instance: pynqrouter_256x128_0, and set properties + set pynqrouter_256x128_0 [ create_bd_cell -type ip -vlnv xilinx.com:hls:pynqrouter_256x128:1.0 pynqrouter_256x128_0 ] + + # Create instance: rst_ps7_0_100M, and set properties + set rst_ps7_0_100M [ create_bd_cell -type ip -vlnv xilinx.com:ip:proc_sys_reset:5.0 rst_ps7_0_100M ] + + # Create interface connections + connect_bd_intf_net -intf_net processing_system7_0_DDR [get_bd_intf_ports DDR] [get_bd_intf_pins processing_system7_0/DDR] + connect_bd_intf_net -intf_net processing_system7_0_FIXED_IO [get_bd_intf_ports FIXED_IO] [get_bd_intf_pins processing_system7_0/FIXED_IO] + connect_bd_intf_net -intf_net processing_system7_0_M_AXI_GP0 [get_bd_intf_pins processing_system7_0/M_AXI_GP0] [get_bd_intf_pins ps7_0_axi_periph/S00_AXI] + connect_bd_intf_net -intf_net ps7_0_axi_periph_M00_AXI [get_bd_intf_pins ps7_0_axi_periph/M00_AXI] [get_bd_intf_pins pynqrouter_256x128_0/s_axi_AXI4LS] + connect_bd_intf_net -intf_net ps7_0_axi_periph_M01_AXI [get_bd_intf_pins axi_gpio_0/S_AXI] [get_bd_intf_pins ps7_0_axi_periph/M01_AXI] + + # Create port connections + connect_bd_net -net axi_gpio_0_gpio_io_o [get_bd_ports LD] [get_bd_pins axi_gpio_0/gpio_io_o] + connect_bd_net -net processing_system7_0_FCLK_CLK0 [get_bd_pins axi_gpio_0/s_axi_aclk] [get_bd_pins processing_system7_0/FCLK_CLK0] [get_bd_pins processing_system7_0/M_AXI_GP0_ACLK] [get_bd_pins ps7_0_axi_periph/ACLK] [get_bd_pins ps7_0_axi_periph/M00_ACLK] [get_bd_pins ps7_0_axi_periph/M01_ACLK] [get_bd_pins ps7_0_axi_periph/S00_ACLK] [get_bd_pins pynqrouter_256x128_0/ap_clk] [get_bd_pins rst_ps7_0_100M/slowest_sync_clk] + connect_bd_net -net processing_system7_0_FCLK_RESET0_N [get_bd_pins processing_system7_0/FCLK_RESET0_N] [get_bd_pins rst_ps7_0_100M/ext_reset_in] + connect_bd_net -net rst_ps7_0_100M_interconnect_aresetn [get_bd_pins ps7_0_axi_periph/ARESETN] [get_bd_pins rst_ps7_0_100M/interconnect_aresetn] + connect_bd_net -net rst_ps7_0_100M_peripheral_aresetn [get_bd_pins axi_gpio_0/s_axi_aresetn] [get_bd_pins ps7_0_axi_periph/M00_ARESETN] [get_bd_pins ps7_0_axi_periph/M01_ARESETN] [get_bd_pins ps7_0_axi_periph/S00_ARESETN] [get_bd_pins pynqrouter_256x128_0/ap_rst_n] [get_bd_pins rst_ps7_0_100M/peripheral_aresetn] + + # Create address segments + create_bd_addr_seg -range 0x00010000 -offset 0x41200000 [get_bd_addr_spaces processing_system7_0/Data] [get_bd_addr_segs axi_gpio_0/S_AXI/Reg] SEG_axi_gpio_0_Reg + create_bd_addr_seg -range 0x00040000 -offset 0x43C00000 [get_bd_addr_spaces processing_system7_0/Data] [get_bd_addr_segs pynqrouter_256x128_0/s_axi_AXI4LS/Reg] SEG_pynqrouter_256x128_0_Reg + + + # Restore current instance + current_bd_instance $oldCurInst + + save_bd_design +} +# End of create_root_design() + + +################################################################## +# MAIN FLOW +################################################################## + +create_root_design "" + + diff --git a/hls/lines256_length128/main.cpp b/hls/lines256_length128/main.cpp index 3803393..49dfbc3 100644 --- a/hls/lines256_length128/main.cpp +++ b/hls/lines256_length128/main.cpp @@ -17,6 +17,7 @@ #include "router.hpp" +#define PRINT_SOLUTION int main(int argc, char *argv[]) { using namespace std; @@ -50,9 +51,11 @@ int main(int argc, char *argv[]) { seed = atoi(argv[2]); } +#ifdef PRINT_SOLUTION int size_x = (boardstr[1] - '0') * 10 + (boardstr[2] - '0'); int size_y = (boardstr[4] - '0') * 10 + (boardstr[5] - '0'); int size_z = (boardstr[7] - '0'); +#endif // ƒ\ƒ‹ƒoŽÀs ap_int<32> status; @@ -68,6 +71,7 @@ int main(int argc, char *argv[]) { cout << "status = " << (int)status << endl; cout << "elapsed = " << ((double)(clock_done - clock_start) / CLOCKS_PER_SEC) << endl << endl; +#ifdef PRINT_SOLUTION // ‰ð•\ަ cout << "SOLUTION" << endl; cout << "========" << endl; @@ -80,12 +84,13 @@ int main(int argc, char *argv[]) { cout << ","; } int i = ((x * MAX_WIDTH + y) << BITWIDTH_Z) | z; - //cout << setfill('0') << setw(2) << right << (unsigned int)(unsigned char)(boardstr[i]); - cout << (unsigned int)(unsigned char)(boardstr[i]); + cout << setfill('0') << setw(3) << right << (unsigned int)(unsigned char)(boardstr[i]); + //cout << (unsigned int)(unsigned char)(boardstr[i]); } cout << endl; } } +#endif return 0; } diff --git a/hls/lines256_length128/router.cpp b/hls/lines256_length128/router.cpp index 08eb1f5..29ad14a 100644 --- a/hls/lines256_length128/router.cpp +++ b/hls/lines256_length128/router.cpp @@ -210,7 +210,6 @@ bool pynqrouter_256x128(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<3 FIRST_ROUTING: for (ap_uint<9> i = 0; i < (ap_uint<9>)(line_num); i++) { #pragma HLS LOOP_TRIPCOUNT min=2 max=255 avg=50 -//#pragma HLS LOOP_TRIPCOUNT min=2 max=127 avg=50 //#pragma HLS PIPELINE //#pragma HLS UNROLL factor=2 @@ -245,6 +244,7 @@ bool pynqrouter_256x128(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<3 ap_uint<8> last_target = 255; // [Step 2] Rip-up å†ãƒ«ãƒ¼ãƒ†ã‚£ãƒ³ã‚° + cout << "Rip-up Routing" << endl; ROUTING: for (ap_uint<16> round = 1; round <= 32768 /* = (2048 * 16) */; round++) { #pragma HLS LOOP_TRIPCOUNT min=1 max=4000 avg=50 @@ -285,8 +285,6 @@ bool pynqrouter_256x128(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<3 #pragma HLS LOOP_TRIPCOUNT min=1 max=255 avg=50 weights[paths[target][j]] = 1; } - // 対象ラインã®ã‚¹ã‚¿ãƒ¼ãƒˆã®é‡ã¿ã‚‚一旦リセット ã‚ã¨ã§ (*) ã§æˆ»ã™ - weights[starts[target]] = 1; // (2) é‡ã¿ã‚’æ›´æ–° ap_uint<8> current_round_weight = new_weight(round); @@ -304,10 +302,18 @@ bool pynqrouter_256x128(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<3 } } } + WEIGHT_TERMINAL: + for (ap_uint<9> i = 0; i < (ap_uint<9>)(line_num); i++) { +#pragma HLS LOOP_TRIPCOUNT min=2 max=255 avg=50 + weights[starts[i]] = MAX_WEIGHT; + weights[goals[i]] = MAX_WEIGHT; + } + // 対象ラインã®ã‚¹ã‚¿ãƒ¼ãƒˆã®é‡ã¿ã‚‚一旦リセット ã‚ã¨ã§ (*) ã§æˆ»ã™ + weights[starts[target]] = 1; // 経路探索 #ifdef DEBUG_PRINT - cout << "LINE #" << (int)(target + 1) << endl; + cout << "(round: " << round << ")" << "LINE #" << (int)(target + 1) << endl; #endif search(&(paths_size[target]), paths[target], starts[target], goals[target], weights); @@ -612,18 +618,18 @@ void search(ap_uint<8> *path_size, ap_uint<16> path[MAX_PATH], ap_uint<16> start ap_uint<16> t = prev[goal]; #ifdef DEBUG_PRINT - int dbg_start_xy = start >> BITWIDTH_Z; - int dbg_start_x = dbg_start_xy / MAX_WIDTH; - int dbg_start_y = dbg_start_xy % MAX_WIDTH; - int dbg_start_z = start & BITMASK_Z; - - int dbg_goal_xy = goal >> BITWIDTH_Z; - int dbg_goal_x = dbg_goal_xy / MAX_WIDTH; - int dbg_goal_y = dbg_goal_xy % MAX_WIDTH; - int dbg_goal_z = goal & BITMASK_Z; - - cout << "(" << dbg_start_x << ", " << dbg_start_y << ", " << dbg_start_z << ") #" << start << " -> " - << "(" << dbg_goal_x << ", " << dbg_goal_y << ", " << dbg_goal_z << ") #" << goal << endl; + //int dbg_start_xy = start >> BITWIDTH_Z; + //int dbg_start_x = dbg_start_xy / MAX_WIDTH; + //int dbg_start_y = dbg_start_xy % MAX_WIDTH; + //int dbg_start_z = start & BITMASK_Z; + + //int dbg_goal_xy = goal >> BITWIDTH_Z; + //int dbg_goal_x = dbg_goal_xy / MAX_WIDTH; + //int dbg_goal_y = dbg_goal_xy % MAX_WIDTH; + //int dbg_goal_z = goal & BITMASK_Z; + + //cout << "(" << dbg_start_x << ", " << dbg_start_y << ", " << dbg_start_z << ") #" << start << " -> " + // << "(" << dbg_goal_x << ", " << dbg_goal_y << ", " << dbg_goal_z << ") #" << goal << endl; #endif // ãƒãƒƒã‚¯ãƒˆãƒ©ãƒƒã‚¯ @@ -634,11 +640,11 @@ void search(ap_uint<8> *path_size, ap_uint<16> path[MAX_PATH], ap_uint<16> start #pragma HLS PIPELINE II=2 #ifdef DEBUG_PRINT - int t_xy = prev[t] >> BITWIDTH_Z; - int t_x = t_xy / MAX_WIDTH; - int t_y = t_xy % MAX_WIDTH; - int t_z = prev[t] & BITMASK_Z; - cout << " via " << "(" << t_x << ", " << t_y << ", " << t_z << ") #" << prev[t] << " dist=" << dist[t] << endl; + //int t_xy = prev[t] >> BITWIDTH_Z; + //int t_x = t_xy / MAX_WIDTH; + //int t_y = t_xy % MAX_WIDTH; + //int t_z = prev[t] & BITMASK_Z; + //cout << " via " << "(" << t_x << ", " << t_y << ", " << t_z << ") #" << prev[t] << " dist=" << dist[t] << endl; #endif path[p] = t; // 記録 @@ -649,8 +655,8 @@ void search(ap_uint<8> *path_size, ap_uint<16> path[MAX_PATH], ap_uint<16> start *path_size = p; #ifdef DEBUG_PRINT - cout << "max_path_len = " << p << endl; - cout << "max_pq_len = " << max_pq_len << endl; + //cout << "max_path_len = " << p << endl; + //cout << "max_pq_len = " << max_pq_len << endl; #endif } @@ -676,6 +682,7 @@ void pq_push(ap_uint<16> priority, ap_uint<16> data, ap_uint<13> *pq_len, ap_uin #pragma HLS INLINE (*pq_len)++; + if ((*pq_len) == 0) { (*pq_len)--; } // Queue is full -> Last element is automatically removed ap_uint<13> i = (*pq_len); // target ap_uint<13> p = (*pq_len) >> 1; // i.e., (*pq_len) / 2; // 親 PQ_PUSH_LOOP: @@ -708,7 +715,7 @@ void pq_pop(ap_uint<16> *ret_priority, ap_uint<16> *ret_data, ap_uint<13> *pq_le ap_uint<16> last_priority = (ap_uint<16>)(pq_nodes[*pq_len] & PQ_PRIORITY_MASK); // 末尾ノードã®å„ªå…ˆåº¦ PQ_POP_LOOP: - while (1) { + while (!(i >> 11)) { // (2018.08.25) Loop condition fixed #pragma HLS LOOP_TRIPCOUNT min=1 max=8 avg=4 //#pragma HLS PIPELINE //#pragma HLS UNROLL factor=2 -- 2.22.0 From f7c0353d599af856b85f9cf764da226e7a9f4fdb Mon Sep 17 00:00:00 2001 From: KazushiKawamura Date: Tue, 28 Aug 2018 21:08:17 +0900 Subject: [PATCH 30/30] Upload files --- hls_2018/router_02_boardstr/Makefile | 20 + hls_2018/router_02_boardstr/Makefile.cygwin | 14 + hls_2018/router_02_boardstr/README.md | 16 + hls_2018/router_02_boardstr/ap_int.h | 521 ++ .../bitstream/04/router_design.bit | Bin 0 -> 4045681 bytes .../bitstream/04/router_design.tcl | 1113 ++++ .../bitstream/16/router_design.bit | Bin 0 -> 4045681 bytes .../bitstream/16/router_design.tcl | 1113 ++++ .../router_02_boardstr/etc/ap_fixed_sim.h | 2451 +++++++ hls_2018/router_02_boardstr/etc/ap_int_sim.h | 1629 +++++ hls_2018/router_02_boardstr/etc/ap_private.h | 5858 +++++++++++++++++ hls_2018/router_02_boardstr/main.cpp | 99 + hls_2018/router_02_boardstr/router.cpp | 609 ++ hls_2018/router_02_boardstr/router.hpp | 59 + .../bitstream/router_design.bit | Bin 0 -> 5568793 bytes .../bitstream/router_design.tcl | 844 +++ hls_2018/router_04_boardstr/router.cpp | 12 +- hls_2018/router_04_boardstr/router.hpp | 8 +- hls_2018/router_05/Makefile | 20 + hls_2018/router_05/Makefile.cygwin | 14 + hls_2018/router_05/ap_int.h | 521 ++ hls_2018/router_05/etc/ap_fixed_sim.h | 2451 +++++++ hls_2018/router_05/etc/ap_int_sim.h | 1629 +++++ hls_2018/router_05/etc/ap_private.h | 5858 +++++++++++++++++ hls_2018/router_05/main.cpp | 99 + hls_2018/router_05/router.cpp | 457 ++ hls_2018/router_05/router.hpp | 53 + hls_2018/router_05/solver.c | 317 - 28 files changed, 25459 insertions(+), 326 deletions(-) create mode 100755 hls_2018/router_02_boardstr/Makefile create mode 100755 hls_2018/router_02_boardstr/Makefile.cygwin create mode 100644 hls_2018/router_02_boardstr/README.md create mode 100755 hls_2018/router_02_boardstr/ap_int.h create mode 100755 hls_2018/router_02_boardstr/bitstream/04/router_design.bit create mode 100755 hls_2018/router_02_boardstr/bitstream/04/router_design.tcl create mode 100755 hls_2018/router_02_boardstr/bitstream/16/router_design.bit create mode 100755 hls_2018/router_02_boardstr/bitstream/16/router_design.tcl create mode 100755 hls_2018/router_02_boardstr/etc/ap_fixed_sim.h create mode 100755 hls_2018/router_02_boardstr/etc/ap_int_sim.h create mode 100755 hls_2018/router_02_boardstr/etc/ap_private.h create mode 100755 hls_2018/router_02_boardstr/main.cpp create mode 100755 hls_2018/router_02_boardstr/router.cpp create mode 100755 hls_2018/router_02_boardstr/router.hpp create mode 100755 hls_2018/router_04_boardstr/bitstream/router_design.bit create mode 100755 hls_2018/router_04_boardstr/bitstream/router_design.tcl create mode 100755 hls_2018/router_05/Makefile create mode 100755 hls_2018/router_05/Makefile.cygwin create mode 100755 hls_2018/router_05/ap_int.h create mode 100755 hls_2018/router_05/etc/ap_fixed_sim.h create mode 100755 hls_2018/router_05/etc/ap_int_sim.h create mode 100755 hls_2018/router_05/etc/ap_private.h create mode 100755 hls_2018/router_05/main.cpp create mode 100755 hls_2018/router_05/router.cpp create mode 100755 hls_2018/router_05/router.hpp delete mode 100644 hls_2018/router_05/solver.c diff --git a/hls_2018/router_02_boardstr/Makefile b/hls_2018/router_02_boardstr/Makefile new file mode 100755 index 0000000..8f79e7a --- /dev/null +++ b/hls_2018/router_02_boardstr/Makefile @@ -0,0 +1,20 @@ +TARGET = sim +OBJS = $(CPPS:.cpp=.o) +CPPS = $(wildcard *.cpp) +CXX = g++ +CXXFLAGS = -O3 -Wall -Wno-unknown-pragmas -Wno-unused-label -DSOFTWARE -DCALCTIME + +all: $(TARGET) + +$(TARGET): $(OBJS) + $(CXX) -O3 -o $@ $(OBJS) + +run: + python3 ../NLGenerator.py -x 20 -y 20 -z 6 -l 100;\ + python3 ./gen_boardstr.py Q-20x20x5_100_10.txt |\ + ./$(TARGET) - + + +clean: + rm *.o + rm $(TARGET) diff --git a/hls_2018/router_02_boardstr/Makefile.cygwin b/hls_2018/router_02_boardstr/Makefile.cygwin new file mode 100755 index 0000000..866fdcd --- /dev/null +++ b/hls_2018/router_02_boardstr/Makefile.cygwin @@ -0,0 +1,14 @@ +TARGET = sim +OBJS = $(CPPS:.cpp=.o) +CPPS = $(wildcard *.cpp) +CXX = g++ +CXXFLAGS = -O3 -Wall -Wno-unknown-pragmas -Wno-unused-label -DSOFTWARE -DCALCTIME + +all: $(TARGET) + +$(TARGET): $(OBJS) + $(CXX) -O3 -Wl,--stack,33554432 -o $@ $(OBJS) + +clean: + rm *.o + rm $(TARGET) diff --git a/hls_2018/router_02_boardstr/README.md b/hls_2018/router_02_boardstr/README.md new file mode 100644 index 0000000..2213393 --- /dev/null +++ b/hls_2018/router_02_boardstr/README.md @@ -0,0 +1,16 @@ +# 並列度ã®å¤‰æ›´ (変更箇所) +優先度キューã«è¦ç´ ã‚’挿入ã™ã‚‹éš›ï¼Œè¦ç´ ã®ç§»å‹•を並列ã—ã¦å®Ÿè¡Œã§ãã‚‹ + +コードã«ã„ãã¤ã‹ã®å¤‰æ›´ã‚’加ãˆã‚‹ã“ã¨ã§ä¸¦åˆ—度を変更å¯èƒ½ + +## router.hpp +以下ã®2箇所を変更ã™ã‚‹ +* #define PP **32** <-- 並列度 +* #define LOG_PP **5** <-- 並列度ã®log2 + +## router.cpp +以下ã®5箇所を変更ã™ã‚‹ +* (in search func.) #pragma HLS ARRAY_PARTITION variable=pq_nodes cyclic factor=**32** dim=1 <-- 並列度 +* (in pq_push func.) #pragma HLS LOOP_TRIPCOUNT min=0 max=**31** <-- 並列度-1 (計3箇所) +* (in pq_push func.) #pragma HLS LOOP_TRIPCOUNT min=0 max=**255** <-- ã‚­ãƒ¥ãƒ¼ã®æœ€å¤§è¦ç´ æ•°/並列度-1 + diff --git a/hls_2018/router_02_boardstr/ap_int.h b/hls_2018/router_02_boardstr/ap_int.h new file mode 100755 index 0000000..b8d9fdc --- /dev/null +++ b/hls_2018/router_02_boardstr/ap_int.h @@ -0,0 +1,521 @@ +/* + * Copyright 2012 Xilinx, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __AESL_AP_SIM_H__ +#define __AESL_AP_SIM_H__ + +#ifndef __cplusplus +#error C++ is required to include this header file +#else + +#include "etc/ap_int_sim.h" +#include "etc/ap_fixed_sim.h" + +//Forward declaration +template class ap_fixed; +template class ap_ufixed; +template class ap_int; +template class ap_uint; + +//AP_INT +//-------------------------------------------------------- +template +class ap_int : public ap_private<_AP_W, true> { +#ifdef _MSC_VER +#pragma warning(disable: 4521 4522) +#endif /* #ifdef _MSC_VER */ +public: + typedef ap_private<_AP_W, true> Base; + + //Constructor + INLINE ap_int(): Base() {} + template + INLINE ap_int(const volatile ap_int<_AP_W2> &op):Base((const ap_private<_AP_W2,true> &)(op)) {} + + template + INLINE ap_int(const ap_int<_AP_W2> &op):Base((const ap_private<_AP_W2,true> &)(op)) {} + + template + INLINE ap_int(const ap_uint<_AP_W2> &op):Base((const ap_private<_AP_W2,false> &)(op)) {} + + template + INLINE ap_int(const volatile ap_uint<_AP_W2> &op):Base((const ap_private<_AP_W2,false> &)(op)) {} + + template + INLINE ap_int(const ap_range_ref<_AP_W2, _AP_S2>& ref):Base(ref) {} + + template + INLINE ap_int(const ap_bit_ref<_AP_W2, _AP_S2>& ref):Base(ref) {} + + template + INLINE ap_int(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& ref):Base(ref) {} + + template + INLINE ap_int(const ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op.to_ap_private()) {} + + template + INLINE ap_int(const ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op.to_ap_private()) {} + + template + INLINE ap_int(const volatile ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op.to_ap_private()) {} + + template + INLINE ap_int(const volatile ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op.to_ap_private()) {} + + template + INLINE ap_int(const ap_private<_AP_W2, _AP_S2>& op):Base(op) {} + + template + INLINE ap_int(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, + _AP_N2>& op):Base(op) {} + + template + INLINE ap_int(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, + _AP_N2>& op):Base(op) {} + + template + INLINE ap_int(const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& op):Base(op.to_ap_private()) {} + +#define CTOR(TYPE) \ + INLINE ap_int(TYPE v):Base(v) {} + CTOR(bool) + CTOR(signed char) + CTOR(unsigned char) + CTOR(short) + CTOR(unsigned short) + CTOR(int) + CTOR(unsigned int) + CTOR(long) + CTOR(unsigned long) + CTOR(unsigned long long) + CTOR(long long) + CTOR(float) + CTOR(double) + CTOR(const char*) + CTOR(const std::string&) +#undef CTOR + INLINE ap_int(const char* str, signed char rd):Base(str, rd) {} + //Assignment + //Another form of "write" + INLINE void operator = (const ap_int<_AP_W>& op2) volatile { + const_cast(this)->operator = (op2); + } + + INLINE void operator = (const volatile ap_int<_AP_W>& op2) volatile { + const_cast(this)->operator = (op2); + } + + INLINE ap_int<_AP_W>& operator = (const volatile ap_int<_AP_W>& op2) { + Base::operator = (const_cast& >(op2)); + return *this; + } + + INLINE ap_int<_AP_W>& operator = (const ap_int<_AP_W>& op2) { + Base::operator = ((const ap_private<_AP_W, true>&)op2); + return *this; + } +}; + +//AP_UINT +//--------------------------------------------------------------- +template +class ap_uint: public ap_private<_AP_W, false> { +#ifdef _MSC_VER +#pragma warning( disable : 4521 4522 ) +#endif +public: + typedef ap_private<_AP_W, false> Base; + //Constructor + INLINE ap_uint(): Base() {} + INLINE ap_uint(const ap_uint<_AP_W>& op) :Base(dynamic_cast&>(op)) {} + INLINE ap_uint(const volatile ap_uint<_AP_W>& op):Base(dynamic_cast&>(op)){} + template + INLINE ap_uint(const volatile ap_uint<_AP_W2> &op):Base((const ap_private<_AP_W2, false>&)(op)) {} + + template + INLINE ap_uint(const ap_uint<_AP_W2> &op) : Base((const ap_private<_AP_W2, false>&)(op)){} + + template + INLINE ap_uint(const ap_int<_AP_W2> &op) : Base((const ap_private<_AP_W2, true>&)(op)) {} + + template + INLINE ap_uint(const volatile ap_int<_AP_W2> &op) : Base((const ap_private<_AP_W2, false>&)(op)) {} + + template + INLINE ap_uint(const ap_range_ref<_AP_W2, _AP_S2>& ref):Base(ref) {} + + template + INLINE ap_uint(const ap_bit_ref<_AP_W2, _AP_S2>& ref):Base(ref) {} + + template + INLINE ap_uint(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& ref):Base(ref) {} + + template + INLINE ap_uint(const ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op.to_ap_private()) {} + + template + INLINE ap_uint(const ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op.to_ap_private()) {} + + template + INLINE ap_uint(const volatile ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op.to_ap_private()) {} + + template + INLINE ap_uint(const volatile ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) + :Base(op) {} + + template + INLINE ap_uint(const ap_private<_AP_W2, _AP_S2>& op):Base(op) {} + + template + INLINE ap_uint(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, + _AP_N2>& op):Base(op) {} + + template + INLINE ap_uint(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, + _AP_N2>& op):Base(op) {} + + template + INLINE ap_uint(const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& op):Base(op.to_ap_private()) {} + +#define CTOR(TYPE) \ + INLINE ap_uint(TYPE v):Base(v) {} + CTOR(bool) + CTOR(signed char) + CTOR(unsigned char) + CTOR(short) + CTOR(unsigned short) + CTOR(int) + CTOR(unsigned int) + CTOR(long) + CTOR(unsigned long) + CTOR(unsigned long long) + CTOR(long long) + CTOR(float) + CTOR(double) + CTOR(const char*) + CTOR(const std::string&) +#undef CTOR + INLINE ap_uint(const char* str, signed char rd):Base(str, rd) {} + //Assignment + //Another form of "write" + INLINE void operator = (const ap_uint<_AP_W>& op2) volatile { + Base::operator = (op2); + } + + INLINE void operator = (const volatile ap_uint<_AP_W>& op2) volatile { + Base::operator = (op2); + } + + INLINE ap_uint<_AP_W>& operator = (const volatile ap_uint<_AP_W>& op2) { + Base::operator = (op2); + return *this; + } + + INLINE ap_uint<_AP_W>& operator = (const ap_uint<_AP_W>& op2) { + Base::operator = ((const ap_private<_AP_W, false>&)(op2)); + return *this; + } +}; + +#define ap_bigint ap_int +#define ap_biguint ap_uint + +//AP_FIXED +//--------------------------------------------------------------------- +template +class ap_fixed: public ap_fixed_base<_AP_W, _AP_I, true, _AP_Q, _AP_O, _AP_N> { +#ifdef _MSC_VER +#pragma warning( disable : 4521 4522 ) +#endif +public: + typedef ap_fixed_base<_AP_W, _AP_I, true, _AP_Q, _AP_O, _AP_N> Base; + //Constructor + INLINE ap_fixed():Base() {} + + template + INLINE ap_fixed(const ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, + _AP_N2>& op): Base(op) {} + + template + INLINE ap_fixed(const ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, + _AP_N2>& op): Base(ap_fixed_base<_AP_W2, _AP_I2, + false, _AP_Q2, _AP_O2, _AP_N2>(op)) {} + + template + INLINE ap_fixed(const ap_int<_AP_W2>& op): + Base(ap_private<_AP_W2, true>(op)) {} + + template + INLINE ap_fixed(const ap_uint<_AP_W2>& op):Base(ap_private<_AP_W2, false>(op)) {} + + template + INLINE ap_fixed(const volatile ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, + _AP_N2>& op): Base(ap_fixed_base<_AP_W2, _AP_I2, + true, _AP_Q2, _AP_O2, _AP_N2>(op)) {} + + template + INLINE ap_fixed(const volatile ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, + _AP_N2>& op): Base(ap_fixed_base<_AP_W2, _AP_I2, + false, _AP_Q2, _AP_O2, _AP_N2>(op)) {} + + template + INLINE ap_fixed(const volatile ap_int<_AP_W2>& op): + Base(ap_private<_AP_W2, true>(op)) {} + + template + INLINE ap_fixed(const volatile ap_uint<_AP_W2>& op):Base(op) {} + + template + INLINE ap_fixed(const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& op):Base(op) {} + + template + INLINE ap_fixed(const ap_bit_ref<_AP_W2, _AP_S2>& op): + Base(op) {} + + template + INLINE ap_fixed(const ap_range_ref<_AP_W2, _AP_S2>& op): + Base(op) {} + + template + INLINE ap_fixed(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& op): + Base(op) {} + + template + INLINE ap_fixed(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& op): Base(op) {} + + template + INLINE ap_fixed(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& op): Base(op) {} + + template + INLINE ap_fixed(const ap_private<_AP_W2, _AP_S2>& op):Base(op) {} + + #define CTOR(TYPE) \ + INLINE ap_fixed(TYPE v):Base(v) {} + CTOR(bool) + CTOR(signed char) + CTOR(unsigned char) + CTOR(short) + CTOR(unsigned short) + CTOR(int) + CTOR(unsigned int) + CTOR(long) + CTOR(unsigned long) + CTOR(unsigned long long) + CTOR(long long) + CTOR(float) + CTOR(double) + CTOR(const char*) + CTOR(const std::string&) +#undef CTOR + INLINE ap_fixed(const char* str, signed char rd):Base(str, rd) {} + + //Assignment + INLINE ap_fixed& operator = (const ap_fixed<_AP_W, _AP_I, + _AP_Q, _AP_O, _AP_N>& op) { + Base::operator = (op); + return *this; + } + + INLINE ap_fixed& operator = (const volatile ap_fixed<_AP_W, _AP_I, + _AP_Q, _AP_O, _AP_N>& op) { + Base::operator = (op); + return *this; + } +}; + +//AP_ UFIXED +//--- ---------------------------------------------------------------- +template +class ap_ufixed : public ap_fixed_base<_AP_W, _AP_I, false, _AP_Q, _AP_O, _AP_N> { +#ifdef _MSC_VER +#pragma warning(disable: 4521 4522) +#endif /* #ifdef _MSC_VER */ +public: + typedef ap_fixed_base<_AP_W, _AP_I, false, _AP_Q, _AP_O, _AP_N> Base; + + //Constructor + INLINE ap_ufixed():Base() {} + + template + INLINE ap_ufixed(const ap_fixed<_AP_W2, _AP_I2, _AP_Q2, + _AP_O2, _AP_N2>& op) : Base(ap_fixed_base<_AP_W2, + _AP_I2, true, _AP_Q2, _AP_O2, _AP_N2>(op)) {} + + template + INLINE ap_ufixed(const ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, + _AP_O2, _AP_N2>& op): Base(ap_fixed_base<_AP_W2, _AP_I2, + false, _AP_Q2, _AP_O2, _AP_N2>(op)) {} + + template + INLINE ap_ufixed(const ap_int<_AP_W2>& op): + Base((const ap_private<_AP_W2, true>&)(op)) {} + + template + INLINE ap_ufixed(const ap_uint<_AP_W2>& op): + Base((const ap_private<_AP_W2, false>&)(op)) {} + + template + INLINE ap_ufixed(const volatile ap_fixed<_AP_W2, _AP_I2, _AP_Q2, + _AP_O2, _AP_N2>& op) : Base(ap_fixed_base<_AP_W2, + _AP_I2, true, _AP_Q2, _AP_O2, _AP_N2>(op)) {} + + template + INLINE ap_ufixed(const volatile ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, + _AP_O2, _AP_N2>& op): Base(ap_fixed_base<_AP_W2, _AP_I2, + false, _AP_Q2, _AP_O2, _AP_N2>(op)) {} + + template + INLINE ap_ufixed(const volatile ap_int<_AP_W2>& op): + Base(ap_private<_AP_W2, true>(op)) {} + + template + INLINE ap_ufixed(const volatile ap_uint<_AP_W2>& op): + Base(ap_private<_AP_W2, false>(op)) {} + + template + INLINE ap_ufixed(const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2>& op):Base(op) {} + + template + INLINE ap_ufixed(const ap_bit_ref<_AP_W2, _AP_S2>& op): + Base(op) {} + + template + INLINE ap_ufixed(const ap_range_ref<_AP_W2, _AP_S2>& op): + Base(op) {} + + template + INLINE ap_ufixed(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& op): + Base(op) {} + + template + INLINE ap_ufixed(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& op): Base(op) {} + + template + INLINE ap_ufixed(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& op): Base(op) {} + + template + INLINE ap_ufixed(const ap_private<_AP_W2, _AP_S2>& op):Base(op) {} + + #define CTOR(TYPE) \ + INLINE ap_ufixed(TYPE v):Base(v) {} + CTOR(bool) + CTOR(signed char) + CTOR(unsigned char) + CTOR(short) + CTOR(unsigned short) + CTOR(int) + CTOR(unsigned int) + CTOR(long) + CTOR(unsigned long) + CTOR(unsigned long long) + CTOR(long long) + CTOR(float) + CTOR(double) + CTOR(const char*) + CTOR(const std::string&) +#undef CTOR + INLINE ap_ufixed(const char* str, signed char rd):Base(str, rd) {} + + //Assignment + INLINE ap_ufixed& operator = (const ap_ufixed<_AP_W, _AP_I, + _AP_Q, _AP_O, _AP_N>& op) { + Base::operator = (op); + return *this; + } + + INLINE ap_ufixed& operator = (const volatile ap_ufixed<_AP_W, _AP_I, + _AP_Q, _AP_O, _AP_N>& op) { + Base::V = const_cast(op); + return *this; + } +}; + +#if defined(SYSTEMC_H) || defined(SYSTEMC_INCLUDED) +template +INLINE void sc_trace(sc_core::sc_trace_file *tf, const ap_int<_AP_W> &op, + const std::string &name) { + if (tf) + tf->trace(sc_dt::sc_lv<_AP_W>(op.to_string(2).c_str()), name); +} + +template +INLINE void sc_trace(sc_core::sc_trace_file *tf, const ap_uint<_AP_W> &op, + const std::string &name) { + if (tf) + tf->trace(sc_dt::sc_lv<_AP_W>(op.to_string(2).c_str()), name); +} + +template +INLINE void sc_trace(sc_core::sc_trace_file *tf, const ap_fixed<_AP_W, _AP_I, _AP_Q, _AP_O, _AP_N >&op, const std::string &name) { + tf->trace(sc_dt::sc_lv<_AP_W>(op.to_string(2).c_str()), name); +} + +template +INLINE void sc_trace(sc_core::sc_trace_file *tf, const ap_ufixed<_AP_W, _AP_I, _AP_Q, _AP_O, _AP_N >&op, const std::string &name) { + tf->trace(sc_dt::sc_lv<_AP_W>(op.to_string(2).c_str()), name); +} +#endif /* #if defined(SYSTEMC_H) || defined(SYSTEMC_INCLUDED) */ +#endif /* #ifndef __cplusplus */ +#endif /* #ifndef __AESL_AP_SIM_H__ */ \ No newline at end of file diff --git a/hls_2018/router_02_boardstr/bitstream/04/router_design.bit b/hls_2018/router_02_boardstr/bitstream/04/router_design.bit new file mode 100755 index 0000000000000000000000000000000000000000..fa71679ac7889dc311c5f113a0b5d508c7039afa GIT binary patch literal 4045681 zcmeFa4U{FvRVElOUsm<&r&4uxSM`rtKMoabx#%%+qn71H7IJh`=oF?gjp;Im5mt+l zg_zYCVGE@7_IRR8CArl2Fl~^rSy;BQVPrLDFtC^b14DakWEQmcvJ8hgyT=$9#_TeK z(O`R6I4rgI-iXMI{Ch9of4-+1-Ia0w;@%ryWJKo6m-$lc-t(gQCq(0Z@tU`P@Ap6Y z*0UJd`yPAy{f|8I*0;ZQ;~j5(`!}q8?XfrCW6Nvb^wzh(<9ojMZC`ua zv9CUH>uut@#KLRddF-}h|K#ECzWvxS@lV7xsCd<}6R*1Mgm^&g{_3x}^Z0Avzj&+o z+K>JHPM0Et__e(&V$GRd`LT@$B?ylNvH=y;!qh@jO*%vGLYnyCoUv)hMj&4IpN=)I zT3$DrZ-3-Rjv4#irY-8i#xZdj>N%*bZBtMi=d-LnCZzFgd^U_vCC==5_;JC75nu!u z0Y-okU<4QeMt~7u1Q-EEfDvE>7y(9r5nu!u0Y-okU<4QeMt~7u1Q-EEfDvE>7y(9r z5nu!u0Y-okU<4QeMt~7u1Q-EEfDvE>7y(9r5nu!u0Y-okU<4QeMt~7u1Q-EEfDvE> z7y(9r5nu!u0Y-okU<4QeMt~7u1Q-EEfDvE>7y(9r5nu!u0Y-okU<4QeMt~7u1Q-EE zfDvE>7y(9r5nu!u0Y-okU<4QeMt~7u1Q-EEfDvE>7y(9r5nu!u0Y-okU<4QeMt~7u z1Q-EEfDvE>7y(9r5nu!u0Y-okU<4QeMt~7u1Q-EEfDvE>7y(9r5nu!u0Y-okU<4Qe zMt~7u1Q-EEfDvE>7y(9r5nu!u0Y-okU<4QeMt~7u1Q-EEfDvE>7y(9r5nu!u0Y-ok zU<4QeMt~7u1Q-EEfDvE>7y(9r5nu!u0Y-okU<4QeMt~7u1Q-EEfDvE>7y(9r5nu!u z0Y-okU<4QeMt~7u1Q-EEfDvE>7y(9r5nu!u0Y-okU<4QeMt~7u1Q-EEfDvE>7y(9r z5nu!u0Y-okU<4QeMt~7u1Q-EEfDvE>7y(9r5nu!u0Y-okU<4QeMt~7u1Q-EEfDvE> z7y(9r5nu!u0Y-okU<4QeMt~7u1Q-EEfDvE>7y(9r5nu!u0Y-okU<4QeMt~7u1Q-EE zfDvE>7y(9r5nu!u0Y-okU<4QeMt~7u1Q-EEfDvE>7y(9r5nu!u0Y-okU<4QeMt~7u z1Q-EEfDvE>7y(9r5nu!u0Y-okU<4QeMt~7u1Q-EEfDvE>7y(9r5nu!u0Y-okU<4Qe zMt~7u1Q-EEfDvE>7y(9r5nu!u0Y-okU<4QeMt~7u1Q-EEfDvE>7y(9r5nu!u0Y-ok zU<4QeMt~7u1Q-EEfDvE>7y(9r5nu!u0Y-okU<4QeMt~7u1Q-EEfDvE>7y(9r5nu!u z0Y-okU<4QeMt~7u1Q-EEfDvE>7y(9r5nu!u0Y-okU<4QeMt~7u1Q-EEfDvE>7y(9r z5nu!u0Y-okU<4QeMt~7u1Q-EEfDvE>7y(9r5nu!u0Y-okU<4QeMt~7u1Q-EEfDvE> z7y(9r5nu!u0Y-okU<4QeMt~7u1Q-EEfDvE>7y(9r5nu!u0Y-okU<4QeMt~7u1Q-EE zfDvE>7y(9r5nu!u0Y-okU<4QeMt~7u1Q-EEfDvE>7y(9r5nu!u0Y-okU<4QeMt~7u z1Q-EEfDvE>7y(9r5nu!u0Y-okU<4QeMt~7u1Q-EEfDvE>7y(9r5nu!u0Y-okU<4Qe zMt~7u1Q-EEfDvE>7y(9r5nu!u0Y-okU<4QeMt~7u1Q-EEfDvE>7y(9r5nu!u0Y-ok zU<4QeMt~7u1Q-EEfDvE>7y(9r5nu!u0Y-okU<4QeMt~7u1Q-EEfDvE>7y(9r5nu!u z0Y-okU<4QeMt~7u1Q-EEfDvE>7y(9r5nu!u0Y-okU<4QeMt~7u1Q-EEfDvE>7y(9r z5nu!u0Y-okU<4QeMt~7u1Q-EEfDvE>7y(9r5nu!u0Y-okU<4QeMt~7u1Q-EEfDvE> z7y(9r5nu!u0Y-okU<4QeMt~7u1Q-EEfDvE>7y(9r5nu!u0Y-okU<4QeMt~7u1Q-EE zfDvE>7y(9r5nu!u0Y-okU<4QeMt~7u1Q-EEfDvE>7y(9r5nu!u0Y-okU<4QeMt~7u z1Q-EEfDvE>7y(9r5nu!u0Y-okU<4QeMt~7u1Q-EEfDvE>7y(9r5nu!u0Y-okU<4Qe zMt~7u1Q-EEfDvE>7y(9r5nu!u0Y-okU<4QeMt~7u1Q-EEfDvE>7y(9r5nu!u0Y-ok zU<4QeMt~7u1Q-EEfDvE>7y(9r5nu!u0Y-okU<4QeMt~7u1Q-EEfDvE>7y(9r5nu!u z0Y-okU<4QeMt~7u1Q-EEfDvE>7y(9r5nu!u0Y-okU<4QeMt~7u1Q-EEfDvE>7y(9r z5nu!u0Y-okU<4QeMt~7u1Q-EEfDvE>7y(9r5nu!u0Y-okU<4QeMt~7u1Q-EEfDvE> z7y(9r5nu!u0Y-okU<4QeMt~7u1Q-EEfDvE>7y(9r5nu!u0Y-okU<4QeMt~7u1Q-EE zfDvE>7y(9r5nu!u0Y-okU<4QeMt~7u1Q-EEfDvE>7y(9r5nu!u0Y-okU<4QeMt~7u z1Q-EEfDvE>7y(9r5nu!ufx03Pv`l6}+t!Xx*YmMmS}rp3s&-}VlJ@C*oZQvf_ClQA z$;wJ?GdXA5Ilf!_oZgP{d|-)eoLHa6F!p2hLY%YIIc12LcXFy5vRLl5@5!#Lofk)u zLz|zIyE@xmi2dK1m6h8L(3dELv`qWFf0J=TN<$>rTHfi;rSyrPl$l{vfoxhtQF~=t zQXOfYa-`mSbiV)9JvNvob2&}P#<{A)OEJyF=n#l{alPx;d$F#sZNsG|g>yrFam*B;A04txb}4cd`7Xnt39=8X9Vr6yb3=b%#&GY z>uj5xzTKucP+<*U-e2<}L*v%S!giS07;(a50Aq(0`7kwZtF;e~4f1Vk}d7 zW9#&YEZQaQL;Qldyo5$i%|yeqi`%8zgE^Er+6qBcXe+ccaw8@lCFB&WglIrFsgC2I zDK-Ns>ILeZf7H1m#NiW;b~OwMkR}%=>!t429)^T+j{6X2jf9U?N@1BqpU1YyzDVW` zW08758FY?{tF!K$+|^mV5ZC6uXAFhC_a$#!Nz$!-h`aYtN`HR(Yt>7_2JHZ+Lt*Kr z-*-IQtX=9WYgx>9YhRvgvA;5D7F%4?T=CaFlx2?_j(4?d=V~jbHQULm*6w)W>TEkF zcXjqy0PEY2nBxE)4(Rx>*j`MIA4Z(;7{DAiN{=Vq+G8#;7C>Y%#}GcIiQd?j>*M1> z(!{4=0Y)~z=Edz&JGNP`dq19FJ3OAun>x9jgb?jjQhA%jaIw(VGwDcn zYd;U!V$PF0p2RRQ!3Zz{i~u9R2rvSS03*N%FanGKBftnS0uw@@tsrniys!OwAQ~dF zeARkFSr>&}zP3m@jk0GYWv!o;bn6P#rWc9a=?iOPT#Ie==~|@0Nxak$P}pJGAW{2r z@KkAv?Tvct)_3&dp%u5qJUQiug0XvTm{1MLdPU{p}! zwoaoRG0}P+PZMXVg!afDn&bN#9#u3RPbw5$!DjR(^V_43F{TJG8MFzdw*(wTHrS`+4JI-UA1srOwo?0 zNj?9AHA!UPG#V=+Xy6)kSqq`S-CD{ej6jG234fdBSb|n9_#QWl8GtEW`LmfyM z2R9U3nwBW++!p-7jh8JA0|Q0V7B;}fw3F4KZvJ=;k{C`35*8&u`9eT*0mp%gwspf1 zp`c@^86T^xSM`N@r87V_ux!C8*8y0Ht^z@Kf}cVH{=9-m8~kV~=0O;m1xCKY-3abx(yu(dCC@1&R9_*}9Q`hDHltVTrhp&BJKSSsN& zftZ)#st`YosKZ3Sd7|OR6*bhz&|oxhOh9;z855W&n)GN>lky`q$z$*|q!6oT@Z3u) zaHcO^Y$MnK{NY%@aU)wa$XfoAmo=CWzx=Bc3Ow|%ty_LHSbdXRy?Rmq*;XssdfyMW zFI^DgsVB|nlV-Ht!m$yJXP}~a0`p3=cGqv7EdO^y2WLVK=Z-wnhB4XwTY>&Fc((Y$ zdoQ*xZNg`EJ0`*VU~FIz8jVX^7hy~q*Ie3yU&i0A;g}r!;)Ea^de|^Lemsgc@OQ;` zIy+y$i}+%0?)vM6*t@s0?L@TAi9{Vi(7*YcYGZQzIFHE);4gHEWAeGrb)P3YJFlbP zTl~mJaGw0yuN69*tZ-)LNf_?gQ)NtEc!9@ce7jtPziklkDK3)+1S|F5o>GWGvbQD_(eJotL2fSa3_dr_&K&P(F#H{ zCRcV~Om-f7493Ks6T30l>2i)-A;efrW@$_|HVCqfJ$q=Ld``G?D*CPQy?gge$#0G? z{lZv=ek?)Em|WR`F~NEAIX6$ll#NOAqho<<3_;oof;7bM;mHX5}Ka-a_# z59n=1m)=^- zwE9TOOb=|>P=fCg?vfRXLqC}lO{>5H2R99y9<*rf!d+1MT>>-W zTapg^K&SUo-*z(e{GUuF?(m~7w{Wp)XiZZCrwKeQ2mkE5JrMX)$sq<8GCVbgHWDvQ{6xtg|-vIvLJ-D!z~{$edWG8 z&M!P%0aNoMz4gO(~-li-6eeuBh#5(q_3<9iDYfz!fH zBU0CCvjn%B&qfKNR&)!kKxQInF$cp!zf#;(hCPG>@McV$08fH7eU_=)n9Q5|)JA~OxLv|`CDHDn6`x*RMbPOh z5;_IO%_inV9Befdm?_)vhvFKQxgV}kG6SV@?d^BmcHJV3iJd2(Y_%SRuS~v0X!?B8 zglqRSCe2VooS<>x@@1`~cf*)mz_>MJ6Pkr`;~h8McHO)`CT$#(lUtf*MzbNd za7-Fanin`vF2f}GAvY#9f?(It8YMGODjRU0aAybRnK>cseZ@O??`q>KI=7jKmY%nq zNaP_0-LnVptAC-xz4Jw5^7PLRIgMeso0%~&^Q6=B4Ca|R0L_dW&6EG_uZ98QkbTV9 zn3%_ciZLo0ldu2oV%v#IXJ$;`c}09C&OOIS&o9E|`%`dT%YIll&oKf|&oe$CqT9f} zhR-vKAD!qPF~s2ZImH9;Ig!QypI;2&r1zotc}4RaBYYk)&ogeB=N=&iJ7z;nW*}Gl zo*JlmjT$$b@C+k7)98K~;?=KiHU&H%1S!5yqcmSqshBa@v*)v)eSyY+#>61NV=|#V z;fr5{=j8;Bi8=Rr^{c=5#T_UxcRHLOPbk@!NLVu_xOSQ6e{oFA+Qnlssa>G0ATr$c z;A%K-e6e=xvk2aM*F5mEO;IAVxpigEMGQ%qVelPK6Ot)jW0E_0n6=nHAkQH#IrQhB)akX?rT<0ZD)ya>u zN!NY&QfUv4gHei1x9n@rT7<$%11{&+vwTxM)9NFu?3%5MeVA#2Itdd-HHxh!DZS=z zdyd}wKHqbQej2E3qjMm*EEL?cy=m7mdYlgEmNvGl_VAG%O`~;N>4;I*ehT~Gd$!RR zKjP@4r6a^Q;lU9dSMHGhxy8BrF(vJ7V9xFy){k`le1w+oC8>5gn9zPnbG`{etqg9>{8FrM}YTo#?{ zelg`S8O3x<->9~0S0-geNvlBP8yl%(oA{P3pb-Q-j(kPDijiq;Hh*55Oa@KFJo6jx zbb+=r1a5h}6yQT#xL$?y8ck5a3m(L}om+7m5T{D1B4yPFlkEEijrT)dnIbd%FxX-G z?C1-3e<9$w4*1hg7MvjgY~an97ROgCvHNLVEE^xJ$-;s9@!S zV|-kIhr@r&)`wVrs6M$2oXM8;;A&!VO>2nx3;HrVHK*{(@SH|Ps9}ugEwjMXsvMk| z=i}jY3MWAz;4QMWAi?umSnxs${NjfWzw7JtrjQ>Bw!jh$!WB5it0S9aRI5$&@mi%b zNHX;BXai4mHMoKKAcPWPpNRCfrjslkHX8FN);K5^^wljm0h1`GS)n9rmQ!Epz^_Qa zn$-xfhH21{Fi%uVym9-I-o9|*DLwb6pV<1)$yeY!(eQa*Jo&+Yx3zilmJjw7Y^06C zUm2(n(!?4*Gd9lRmioA2>}j}BX1anngj&4F-I(Z>+?%zeq2%+008 ztJN-RQ{w+$qbf@d(Wb& z;o>3;i3sq0jjx3FHQrCpFNV)V?mdl`A1vl5TJM6iXQr4n%68{C6nNR0_i%Re%jupT zeQlbr4cF!OFlv)$l|<~Am}lqmWAeq!n7r*@RB<{1n;9At_j@a*hF?|LfzJ8!1TMSy zrFEUp)rfuxjmZ}?V{*E#_pi^)n7n~*M+rsy6n+fGqdT2`#k|wIx_t`u)($GiJH4x& zJn?7RIlZgP?Myz2otIxhTp`}@g~Zm&5wdkLoZi(=-hYniJ`Ky?%jG%9THOB%c}`(1 z#5t&hAU+E3cY0TY9M#4SuyMT8yV}V;f7H(DUERS>VI0qnc=A^eSBPD2@oXv90I{k4 zr2N6e!1%5xya1V!IE|5BjajrqYpA;w@`rZC)~KNpC{xqc(XKYCtKzDVL|%oh{};XN zmEtPww+iI=S5&ToP*E#mgFKe2v`scKkMqFu7Ryl#fA#oi+upaYU<;8H*%#MxnJ8I1i3DQJoaq z52wg-H)ap^_T#YBwu2YH4dLI}79W7|OPcdFFkZ{Qo!V#8+I~2Qmf1(Zi#(Qb1ytY%DFn7Zi>pMx4_*oC6xxPt_6Dy2lin6tnWO*6u6T-!yU&sQn z^Oaa2h0=13Z!3MKw3RW!@7%HIP$*m-v=H;iCq)yfyfMZ(0@47jjh0M`H;VQ)1$OYK z#f6*|XiNcrNkRHD{9#?GEZsn68n%86Z)%g?=(2e$(xo=BNT4cBV$FXcw=N5c_5XhG?0sZ5+j^1W!TuWW#bC<_?IaJ zy7GibOOG!kgPhciP-t7aX{mE|9R#X_F0b--iM+BvlDD@>9)1nHECguyPhb?ZtuDfA zU|gqV4XvL#wRT_k{6GL21^~>AKZfk6Ax-$2&N2wb0I^eJz$_yVh~T#8R965Oa|5 zXE;)4(;{Jdlg%`(HHehkxCi!<)ys?ubkr2>Fa;mGUXyihdGun6Un5Ptc0SMsBpy$C z6w}_|`2ia&rhWW+I3sjh?e-xj@Z(^VOfeGIvsek2ltQu&@k>Sgk8=)+a;R*QtsNII zC@MNFG;A!yMoC|hMoFv&Iw?+L+89flpz)#6)_ObeBS0a&i9#yKVOzI#(MUwnPz$Xc z8`m2BXl!kYc7&@zVEm$u$p}QYxQM2PJFvh4{((OY#w$R>o}~kA_b=BBlvGSJL$|OA z6kmqN6^%kuBvdpWNOUZiD>}kDDfGg+nAJeJU}-yNLVY2|*-<~RVXBzcucvi72%Rr& zZP1G;evJqrkAKU7HU=QGg;W>~3EboH>i8DXPG%WxRwrX;Wu^*z)ctiEk4**kuCY=` z(FTc5rGuAF&2l>557IuLGfoMNWr8s(olMN%PPWLyz0XAVzKOjRc*y&75?A~2s>=K} zj<(n4EvqFE?pYKeG>TVoV@RTKgR?~=QBYKYj6}Lj(X*VUjd71L)qV?yku>`Qx`s`*NWkJyctlfvm{+I2PMHn~cXrDrzqCIg zcCUCjhKWxT8umqcEAI1=DdhG)(g- zQc9f`uvu;?6~a>uO06rnQmjH-Ji9frL*2$@BrDjVzbbZ}{H-f=vMkg?Ccm^lA@+Zx zm*cv%wS7t3#&+iv_&lecX|01#c|nnK1NlM27&?^`;z}r&LpaC5cmHMzq=N&eN!-?O zC;*$hnP~-HNd*%b7LJT3$ATQXY_xVK$eXSnir^3mhSwo3Vp*8OfMqo4V+AyX<%U#tR~8hq1D!HL7S9ldpR5swo)H{Nmgt#`HV zc-5`BHFz;NvDjX0ewdCsuhNUb;zFyv*v{Iu+rf$U{NkeZ*IHQwyC7J}+RX=G2kk#h zagV-dvE2?^^I3nF<=uDRdDks>AH8Yyb$8#@y0UTC(Od66a^jAoH#vVo9DJ+m%WciO zU%7Jlwp&)Q4_9`M+reE8O1Z(aGhyMp%oi4!-? z=Z-tK9X9@+JB+bk_0hX;yQy_(-^XrA`MWIT;hXNf;m*77xYNYlc;%go2kts?_xw`I z4uaqMiaYQ6#hZ@a@!Xv^fxn}_w6gEkg+svyW2|Xyy%a?cKdc@-^2phHmlt52+}Qc5 z$Ist;K0NWA_vY5j)9TTMwbLh`q2tcy^l5eabQqpq%i682sYk>0)2FS!@XTqj6Y5OX zZe6K+!?n|E#_kUmPOq)4hpoK7^XDHuf9U+#hnK(h{P}R>%3WvgJ^$w0Pn><&`Gfs! z(H$oqIeGrx=z&MxynGk*VPogeqmP_Fdt~9o$DOUSd-UEf{r&CdAAab4FTeNi=Qi%U zOPyVR^!8W6anu%P_s9dr-}{bW?9ct``9~gJyInr|=9C>^_`t)DK79N6#~is9EVdX zU!DWeb65oYqwQ~qPY{I-QELj>p-uenH?Sf72O^FFqS(UN{_B|c{W-r$U6kK0N&tOA zF)2_@w&>o9vCfz0U^#s5x!oAwcu1Rg{-7^Oaz(bbCB~(&9c(Zw`tR~1TX_A<^PhSi z|3Clf=Rfm>KN13{=Y{xhfA#t2KaV7+K7}u-nV=md;pO+afAI5z3?VuArK>;39J98c zDzGiGEAm-nHx7So1;gpR|HSg5{f(eV%cZ#1ez3_MwZMl6G;SwXcKzz)Vh=a+vy%M5 zdrq=7oEZpw|4A%Y$lpS&J?%2|>!Y3f$3{OJ4x#}~P zR#2mTm4a6Irz_fnskOvb`9f!r3wWHmnpb9Gq%Bmcg@V@jhegviyHP0ta%o9Q-9JMe z>c4qEEmc2_piReihX;R8P}+Z*gYe@oDjQOhAU|YAp0)OQ^XaU+ox28`SSFP3&(YaW zea;$JS+RJ=nfbNWK37O*y&9v!59)>Oi-g5Ki!2LeL7^0cvP4lP&zg6)bD(TZgW`2MsI3ud19QgpP28?w!6$Xm2ddhDzzc`K)(S~@QN9?r|dTvaz7Vm~sbTvMpA zFQsMMX*3ZH`>l0L!SLXoV)hm(w#;SSl1V~sy-iUXp4yR~H|b=Z>e${{+q!{SzO3ki zODAvfFc>3yP>*APPiNt3G^8K)?cf${rLoHxfi(7QR3LE$ZbWccJCRpwps6hqG%N(L zpB5-Omvn4$h7i+}a3U(uJ%+q`|_h4y1>9A&G!(t_>;7#>N3FEMO^#Fk2!EHy!oo zG`67|QIL@K52!Zs<{$$4Y$+O-v{i1NNaw@hq)E_9yvG*C5@LX4H~g7srXAitYX{^V)r|M@JmA?cP(z9xLh--Nm62WYKKrP>f9o$&GNCEm?*VyyNwxkDS}H#!E&{&;lVk`OBx^W zT^SM@H&@>a#qBHRq{{+GxAVEW%+Qy|(c^iU#l~7lzg33b zGCTsVk&N68+**Pp)G(=02Zd5=7`l$zgFjKntoq4GYHEdR7Zq))0ESoN{I+)tYmnQ? zY%Ppkjke2wT%%+LOU2GiuTsXLtqcQdxGzX4H#e=hQPyL->wl?79)oA$z(ufeVX~mN zQH~F&Dg`qJZg~w9P!*1hU^Ahz^x%X7k0fk}gHc#ugc>*|G)vrprO>hl!gtpohoPhZ z2Z=419GAeEJ(e4{8Y&$%c7srZ-ad3%I(VkhM7PVIoM`wV28Uxfj>Y@n53dG8u^&S; ztYa`5TSgc@BLw`vfVNm_I5^Aqo7AR%E49$ji@;v4Y2bu`GOs1dLk;Nv5}kc*U&I+> zMhFb*S7zs(G_SruYuEc>OmLnwF12W$%wM>y_4a$`wx4+d#-z13eBZ^3&j@{C7Y+=R z8qO1OrhfZLe;NIP7F%$P$1%ZWs_~3jyLRczQn&Qt(@!>Oo;>-?_QhxB^@VvGrG{g2 z@cRA`n4(tjt^ha(UYVkdXFpXMlev$~en+RMhdd_r8!Q@=#~!O+VzZyoNpq|GJ$OYJ zduw_7o)Zx|{TjUgM27H=K>Hq)8X^P7zu72{oA;W)n3(sUSYCV|z2`)%IX%{)xnOTE ziPf$D%P+56M*ZfqL+{B--gk0^)~v+ao}Dj$89p=ao%`aM*CkS>Mv1`A4!*k#$Hct< zqBn{W#c%|UU?DT1c>vbdFGfWWpb1V;2UV@9W4*RLEQX0>~m%ctv@1Z)8WTV^^y4 zm|%Wb=6{!}YCg%dzMHFlFA(!|QC+UjyB3O?fiG>_`);ksuawVNx>FNH%Cv>=Bf5^J zvi0O^j3_Swx#w=(n8CKlvPc#;NC?kgBJ6{5eiXFDziBN?zca0w=kuo9?DJw=p)`rz zpdpi8w=R)|+mJSE;*?&UH8Ffv>Kfp8&*`EqYw8x|sjhnmNiWe>+uV`SB2QD7LXM&jIDFg1o2)i5+PLP4JJ(iX&|8NAT&4na}Fnr1G^st$n6% z`r1c}nhwWz^~qM0LpND2$IuOgy?H)T=8Ii8BPL&3QEjEU=5ajKY{M!8BWxC-vPlhg zXp4W&1Zk8wp4iMrld^-wjqqDBaWQtjwT^X$aPFK$(2VVnc^vSVxT=e(nUq(gc>CH=L(^W zp2>R)zaoLK_G1Y=$AfcLrz7M1RNG{So3R(OV`Rb}{QZnz)NElELkfy`hk@2Y0deeU z09*rMMej;8 z^|e*hO2%!e_c~s_V>uC!iAqZ>Cu6CKDIi>5k{+Oz@P@StdUG|(I%jY8nD0m1tS-yP`?2jnPMkv-m0LKLe1ZW&5jk5;{drTp!zMJL$zP`EjmKi)3 zP6u%_3^X2iFEE6?WaKNp&`xHJLeDv0}il=zfw+C z)4F-Orit~ORtw+#Dd}vaMJtx|unt$QnlK`=<7(`kWb_<)*bVm1%sqEnv^6bN@$v*8 z5TU?$kVLmyK|`XX_T_78pJBxW8&ZR1I}}(!X*hz8?iXNOH0X5dgQT&n+jiGi)-9s} z@}XZ&4t0RXcKW3sJbX0trWWFfCY*eQqJ0U52H0Ac=99HfuZQG*TwL6Oj~`~Gg6pr1 zU=zniJT)KAH=9DM*21QcD5-lnI5TV4k01TXXToSB->!Z{7Yg?EXF)0v6Gp80dT8glklH zSz_2>mJ7plHc?+!{@NZl%rSdu$z}7c--^`6k2RYw?EKh|Ica_CrJL)UTW^`|?6@(x za)nw(`|VFaPTQC?U(;L9>uY`N=Us01y&*j&f*z`Sa0BPbgAY2Z`qoQdRo~ot%Pjen zai6(JAJ3B)X-%7+F%dWQ*7G`ByVEIGL$2=GtD&Xc@r$wEqe$0;{911A7AK{;>b0Ns zRI9o$$|eHe@mB3fkE!?THue5RFQ)TnYMcL@^epIWx)eW!Oixq8VbZyuV;>WnCi4;uX8`!+IMZDW&s=WQs4)iD%vf#2Bl9-RqmaWrRR7$n^>*3 zb@4u7o+~VOgx3gNOXmqbs>UV0%hM^vw$(W+SGy*LN1yPw=Nn0!wK2BZRE1lYQ<9xA zb8=VvjZx<0uJ-lY9#f?E)CDBI*~RT|q%Q6hsibRv$q{~SpDXl4Zf!|KE|N?{c`8<} z!a%`DhZ&#cpTp=lFpJ@A_v~7ca z9c@JutXwZ~=Edb@Z;Z))iTt?q>uIod*<+QGDSz>-vH4;Z!EOO1g-EKAVX|vtGKUjN zXWF4A+Ya{zXXk3uY}-_3d&3shPNuEScyptetTqn^D3jwAChwhz97}ZZ?KD)5lXOIMO%1n75W3$?s(!wDI#5SMAy+p zb~TWNS8I^Oa8iK%Kb`_e=(JmD*!Wx+O=Qv{Z9Hl&PP8ac^XrPF^_9u`rpB2u0*nA7 zzz8q`i~u9R2rvSS03*N%FanGKBftnS0z*WAF6+Tn-?jp$jqn(3HQq05c(@S;R zJQjUHVwEqTS0L4SO)SBCp!}lDm{2=kUPgC+wmS5i9{5+lDPK}RclTM)X#Ap7$5IUB z0(azTN{JMz;!WOR2Aix`MJ_WNx@|3MnX&1>My=l>ZQ$GV@6Pv<&>j4BP$ljAps+vi z=XVRg%reE7mPwp#PqpXRBYSdz#(T^{Hi(O!V~(nUza~SBOQ~;t?XM1tZL(_lwy?x$ zo0F>zo8~}v$;kc2X&b9)rKP4-)ven9=T%KpcG_~TM%K^Ns{5{-FIV^K2q#5D1a@vT zC^zG4h3+`Y?1K$S0n)!#Xuc{pF4B3pH-=y%Xi0}Hq#>e3LE6YD^$I*CUc54-q=(*a zn-n|o{P|>bv*n~OP0?w8E~cxkY3VN}ILxv~*Hnlsqh(eS^OTK>*`A4XZ#p&aY}r|B z{m$VremEtA_i&u{L(0$t)%_22m0s+M)Pa|eY}u)|AA z)=KR9*P_{z?nS6!3S1BkB3sU;!93&7UoTwGUtud>QQDj9{JKQ zjVI3NqbLZWq-Zq7G0_6X4g@Y`8vYtc6cydn^PnqJ7d08Ntoi;C2N;`s^Vtu_!mLwt ztr4PoU@Lct&`-*|O}j?ZMC`l9&u{8!9FRw_7w{8z=4vp|3g5Q@A47KM&W_O%FYg4W zz^FDQ`ggTSW#B~GX8?44xpnbquzdDIu{#(KEHHa4W%y(ZpZV)mF4ZfY0kVPR2iLE& z@c(QemeCUpf<{Wi`EE(kaJ(tkmNXir7~i%!Bc& z^{%Hj8yD!@%$H7(J~#!xw_6RKGtKrRXLhUi|HI$^(s5ktnES- znlTA3M)N@v&Xlud3&-S%Cv;XmIey<;CKr1&k-zj`*S@(uckEc!`-XVME3z`f|HID} z%O@pme%GWTk1FnqU*7vN7?Y1>{g;o)mwq~HJ7NAWCmet1;c-k}`r;Cr@2k$vK6q?WR7zf@MkMBPT9um56TpkBK4B$PZ$f-Y{yJqIS4tw?- z|FKWL@ZzzJjpN5J6Bx(s`{p(_I%BhQrL%tA+9thQXWUUo5f8`Y1v@6j|Lg3S?4fsU z2;s&k7rka07guh^=NX}fYmn}_MLH2^gtGm5Fl>Y$wf66` z<5#U(M>FtCwQB-==dxwg-Rv6nol~8i6>GcsE^aky>9Z0dz@u@u2%+$d7d`2C!m`}{)iGAntvdR)w+0q$y%*7cETI)gw z#Zod&07|H=kGv)?$+p40!jvkuXsK{>!|k}8SWzR49He|BDzJiiC9U@qeUR{k%TNmC z6xHW@gJELS4?sonTNy|2!PFMi`0ohNB+uGgV|$OR_kS2c<$sxM+!u|j=RF=$cT-bg4%eKvO^na% z{Pz42i9I*yn{AS_p`4d&JIA{md^;y|wX^l>WbA#Zqp_veS~VKTS!}^5#GTs25rO|g!qyE6NHmNQ7I+v!Lxq2J zD9i7yLl(ox0dGcy`%j;`Osoxu?>LeNIRO{>U^zo_Dn=6I5QV@t-iq;1BkIyJj$8cMZ(tK4t@)%|oK@fQF)rLufLxKU! z74nuj0Z`lR6uUONoBFE}0A~kDZ-Y zzgmdL@}D<$#Lk}MI~(8r?RVWJ#Lmu}-gMVp$B%Dp{O0R0^55j`hm}z8erj|*wD;tT zTI>M!F97B_9mqF!j_-NvTR-uMcueki@WEd@{&#RpEwIly7?)tKM(gNs`uv42bebo^ z&XYZR+&uZK&(v*9#P!2LqCQ?a&J*G0Nirs1c;WAE`}v=*)jX-$?^+CRY};_*7r$<# z13f&ySniol&&t(f*R21Wv4im3R#(L!J-tQfGh%pB+ z2gq=(QdoO5RX8q{i*3}&K5LTYJGG7Ccbs*y>R;DOF8xPwEqh&r{O7DXwe6&Hv4>dS zpoi!z?`q7w$t5tN-ofY5UJD)8iW|waSk1pHE$D~K`0U5UaN58TJyT?cPqY4OYfRhX zd7by$`?Z)J_RhUqlx9)XbpFhZ41w&dTRby(sH{)V;{?XqEE274n}vef?EPUuGH481 zP5*)Ju)=`W7P>LHvt?GB<(;d-y7m1e?qOyXx+xR(luMbD9_3~PpphiJRgcX_V%`%D zt;-|HVbV@DB(NSQQ7}P3H>&+G4%;sgeyHD;HEpLbFW4=6+B56bm*&j<=Cg+{%mnSR zKJAHXM}{}oE~OzPRJ(c7)2wZM;}9UIp9__wq+_zS2aq^JLoCaTVA@#~cK~i1w!gno zyq6Xq`Qzr3BM$!Ih;Qt_FcRk@bsAkeQumW|PIp2afF(>%GK+p}LyOlE1fpD!QHi*`%pRxnh!!?d+Y>F{#+WDKz7GQoljFe{1hUykii4X%v!@X~Xe0J#2h%XzI z?1|m7!i0^DvsAGJb>k}(e}Cq;dIk*d`ZS=Mu{AFl#IeOM47B`T3&k@cw2<4k3qYrO z`SjR}Z5FSxwq^2E`|Ivav4b*|Vh$RluszLC8$LfhG>^@)^M?HF z{b;No4UvwT=JFA{={r907Ik>oH6N*$<0f|Hnz}A7{b}5VStE2$ zXIXXXeT{wxaagd}1u(agbzd0!&p`FxG}m(JV>!{(3e4K2;{4s(6$_?>n7YNb1FkZw z>-TIZ>!$**D%eyt*>$<9<@DIuHA-hQ9_8AVjWr0r{Qf~&*Q~8fhLZk4eqO zM8L~T>z2|>Eg!mZs1cegD#)pu?u#dkWj-N&rW)PNWi>Cx zO6~fOy_n~0hnY*x`2Yg<=EY=p9c`v2j(29^kv(_gn!$dlI_Y!Ikw@MjhDBkhy_Mrl z{&BBUm2<7Xp}nr9+_$|Z;|n56Mg(-jC?lP9`~GAYDb~tI7B7X_jq*fk*u4)wGHj2N z@|P^5N=PpWoIF17scK3tUsKb>22V>n7xAU~WZ0almi6-CTBbEnQt`pvd7-h8E$<_X z)3{nWq7L;mzKfz8ZYMJa@jS`M>&iC&qOO_sofjPAQ=_1*r|hxc51@Qz(sc08C!N6% z$dRPA!z?T%dxmSIX95J8~*Q{Gl6 z+PAN_7XMP-`-Qi^Y4u%o?+2{3|FZr$R?9HD*usw=Fi$o$v`CKeTe^K@z199p^ zefwy*?>`xR!le=5Go$+^(bZ(TSG68GB*eaN5qcd?mNU;fmb#muV)^qE3_jG*8(+Tu zdgE{fE^GM(9}R*diuo0ZJ-()%bb6lGGskLKJ@(kn6=V5W`W@vv-k40mh*azCbXcvd z(3rpgbQlvMcvQwXoObPkF)3TSUfd&I9AiR#hnk(WtE~WpM*jPFI^f4wTKWcRj19y8 zJjP%n4fU)nc7F?rgQttNb(AjQ0dPi&7FX-u6S#2Qy^~FE(xrx$g3&J*#~V1|*uf0lw-R=I!E>t?kIz+FJNJJk9-c`PLs(bTr28;ZDp*drN!f_iuv_8HHB74ClnD3i&ks$}V7Pw&jw5ERR?wkJADe5} z@#ultr8ICty2wKie+yZpt(9!)##*H_NHPuC)&=dSZ|#bHwV)eQDO$GY{xX}r`;DTk zytaJw=Gvy#V`9^J>?rEw(w#-pX_VomlCp7uds=FHC8YrCDY(zPAnQVr!pmFJgneNz z;J*6(C5q`2(`W?KcSz46-8_*K&6=Rq#@VB%r(4a>PfxDhGHp%~?w$HFJJ-8HL1PmC zn62MyIL1%Yc+LB{Pcz*JG<^MDaEQmXYpRa@vva@jT=2vej7ff;z?ei0abbG)x8`3@ zPp+Lag)!0dWn&_yX-sx~taDFU%Lp(6i~u9R2)wiqI2jc`Bal4jI4yWA-7zhhcFQvo z`fxX!>Ci8|dOGs#o+UjZS77$wgZOUQ7pLNBpn~+LTy*_?MID&FG3j_eXHgexE8}@m z$Dz5NE^K8p<9U)rWPE&EL9Bx38ON8wup+(whlb^8(te(mlz}eDW3E6}V^Q-PYMk8A zQ&S}#b&0&pzQkM%#Xg$r_}uSMVw81Y*mCzP+cM)g%O`68g(xeDI7g+w<1hD@YuKM4 zy1l=4)6hy+P7=O{OqWW}?xdRxjZ+7n8=5b0q=)IOS6`9+k}(EYb@SlgA(?(xV0vbx zzr2k7cXQvbe(rPqwybHp&0Jn1$1oRhK*8*M&j>)k{@nR9u8Z>=PI`*&dx~=|Bj_3=+tWh zbbXrkI{Cmj?LBF}cG`Q882WU^R#?TcP}V=c;&&&6g?X~S$f56 z^aFdL1Cf79YZ|*ZGry_doSWa8s>c>f_m-t^DpgIHqB-}}Q=&Nw$M~gFQwDu$y1Qsh zW@1n}e$QA6Ks^=aO+fX`?WLL(zYnv1BR@0eEA@l6?~Hiu>KnRIH7tIfaa7Sp=Qp}` zbiT*!c~+ih6uZZb-00#R=e28e;P&a6$D~i-M%Zi*pLdNA-TqwjnDmF+EVmlg*Ea`e z>Df8=+@h<;y#uJ>1Uz`paQv_rMxYb{nbH`pXi-Vqr5ahLs8x|2%Cfey%&>|)xKPFF zC21qQUTcr;L=NTVndSF(3Nh6>yerZ?6;%F3SGgwLb(v;!ob!{NFFC_1f@^Q9VpZA3 z`|9mRa>?_F$FQk3tjE$Nf?z?G?8&2zJ7)YBRs4=wtq$c}mRIfJ8udi1= z!^y_XlScCTKRFz~7=Z!=bo;xLuk#bCz>-BG8q@ui*WD0qJGc|dNd~OrufqrQ z!_651Mqo$?(5*x81*5C;ZsBF-#YI`MtBb9ME-kys=j78v4>ci&w+Mmjy@nc#rfs#2 z1IN{ItD9r0FCzPkJlW%sD)xFv7R!es&E_x^r=6TARKkX8q0}yMA2sp7pWwgdJr;N?Wyk&hEx%Qhr9vyA4aX`6lpKy<<3)*9 z1oOlMX%sEiWQTh9r%{s23WcR&qb%G)Os|x<^(+jTvzvQk&SuyGS;?WcR=Er-wMHW? zagT@psiUqFp%@jKYC|`GAxR=ceTqvMqbaZ#NlC1ojO-l)b=o4$p&3YSdP~L%pU{okOA(58wmlTzdL!}1ryD<9W$uPTGsi(RuVhxtIvebO}!LRbU zX{MD)9x7?5WD7EH?UISYlX}8|NZ)&(j&}c4rr{8LW;}LcgIK9zY9Ioq!e-io0@kcu zVZj)nb`(YR?=%|jbH7E2^nZ4n_tvGSQ?fYa`<0R`eMgF&Zbrsm&sFP3GE1x3kI8D+ zACD=}_`>M%g&IwyrN>6&cl=&)-GUvz845lA;KPkLGh^bPTG>w{!$oRr-lAU~Td2_o zqOW~NA7<1MnqM*M2;=kb4%t*s@l;v5IzG%s9LWvIh{KHDee~lqrSIlRs5hs)JJADE-T_XZ z5nu!u0Y-ok7%~FxJwdJ>vU_&d4+8Fbm#h2nQG+&-szDONN?~PKjwb6Tn*K`>34r!{ zhn<~7G>z0ujfs6v5WmBzMtdTUNsR`hIF-`p7i06PCj(XOV#nPG-N~SRT_^3V=x)w* z#PL-xR93aigehe^-(JsAo1)5Yb=VkzP*(gdAxN}TSJwR zh;+$lfpwC!o#RM*?U#rp8YowjFvA&Hr)|1*CrhL2)xNvOnpYm>rca1^cR(I4wTWJjnjt2V=W*R%&jCf!+AA3}hx~JM(ABfz1r1%`yWHY>wEj1nlocashtxa!mOO$piIC3Q;2%4f&Vr@PR6*cHC3j&*8q3Qm=$%ti! z@51UX`dBSvYLo<>4<>sI{niJ@qqPg=jq>Q7=7~2hiT8{vnc)lAg0=;%Zc5%QTcFLk zJ!2#VzH_D|@cL40(37;>Te+sE0QE4wcHh|Y=(Hb>A_<937y(9r5nu!u0Y-okU<4Qe zMt~7u1Q-EEU_uDIA;9|~La}IT5wz(hs`e?owJQ{F5U7CK>f5JUTXaWu(AJnT@YLSv zp$2&v%c*&>9kp}q`?te9@J15#i!O)3eWv>~ZhtSA=b%60{#V#qh;s_>i+hEX0_yu; zE*lb9sLw%_vO^y1&S4en!4B_G^8E?C$)~`M+BrGIMZVDP=8Qi9kHWilm>24W*nM3O zIbx_(j%BeYVJEKQJ|V6Or4$la&cRM6#6!4+e{vONLR>ZmAW@`&_i$m2CbmX`{-6S@ zQwnR8;6MC-)zm~?6(m9ll_Wk&;E(<*s;;8Mh>(}S0uK}wtgnjb#=8s)79c?(*${yY zmbj537A4k{_*m_<&>$v@2&a}td6n!nG7>imH&8Tfvm2Eaczj@KR||Vf8C2$`yk*ZA z$%f^Xt<#ll?LCH9Y?qfR(M-D{F1CvaXC#R*Te!Ivo-tJ z<%Ux?ejz2!#?dKl6~?r<->#y z4|ie<4XG&Ht`g~Ol%usHVu=$_otNe%wn3Z~@IGzTrcx;mnY@HdG;ObH0ne8beO1D$ zg{QP)UANxbl8S<~w8qiULhF6B1qSUwU~44k4=NzErdn)+3`mXffg;9eK#CeFvAMVa zyte|f7%GyA-J~WOCE8K})v!s`n)IkM zML~ss`J(e87pOpEMB3|!GqSO6{6{2EPVAjzIFZwxiZe28o!r@Vs9k)Ww^0@uquIPyfaE%If;ux{1Htbk6Q|*Kx0uI#?)B&+f(tl z`qG$IF_k0SAtJ4CyJ%V(bJrIC4!7I4V!KNFRwrwfD1l0H#UCqaeYI6eY8s!6^#^$H3*44ziOjB`E8rur0c}u!Bw0AhQb_CQ!TdQln z%_x9H3I3I5i>9_6k_DzAwC>zKtC`m<4OppqMjs?Gs)Jd@wY+8|q zmf9L9w1wp6K^BO_LX)l83a~Z#ZwZY}sVI%uB7^=cY3-0LE5?)2Qad6Q9cwh?jd>(; zR1!CTp6oPj%?3S@H!Cz1T3dloKob|ZsIDeOyvat46+pOL5Cat>tV}c3LJTYj~X)jm=t&^ZI(L(xgt%z3;(>TCL`RvU+(S^DsH>BWCpn_Xp6rvwv+_TerkIxsT zlM%){Qyg9s)znHL^#pP_W}5yZCnRmVZOq=-&1!JHjkEu@%C2-}%bcNG<8;1vo&*En zU$?TEG4NbiO?ZgFhe2yBL=7dxVG#fW;|^O}U=B(6$q8IWq!4S-Y6Pq}VrH;2!Wx>u zs%VP_A1!E#GcZ>?;a*UN9`D(b6cV9&AG(jd8>^+C@vM!~TBIxA3Tb!zLo4iPad-j& zR1Mf6$zOpPWDegVxP@|U*(95~+C#yy{W79Mj&vxZ2)yMX#DqWr4i}&b!8ZnNK~wri zzHlSKqScb1l;Cj%KD9uzRpUK20s;&$2*t&IptrOq6i_jCWU%dIxf(tqwUS+9oq7ZA zZH?yF{-$db!u25&&`Pi~o~5%x8$yP34YxB;Cb10=q>iN;CCJ4Rppz2gwc`3)9C_6= zL2M)dDvl(3aN_lQSTdo#%;)k|?^y7_bISA-_o3oqvED|lDl)-_$tV=f zljilV9bkj=n+mSbumG3MlVjdIS+h-YpFN@T$DBVQH2OtTYmRJO@Rx*aFFVeY)#SQp z$9WPV@<(A7gjfC!fQeK~D1|_PIFu6FLJ5K(3ibuTDje)uSD?RG!=`16X9wbWYd6=) z4t0sY`BHyryG&fjwaY@;oQ)(HEL$CvL6(VhmXSXKQx_Sn68*SKjvh)0{m)e~}CuMPk z*#EE7v6YQ|1)8mQ$kF+{jOli?>$xxGeI~5S{KcTdT)cz~oi@ygMR7m@7hEeApwjSX zij2e|7%O`WxDrLkiO77R&9Ma;Ic&`C|2fQs{F2j&4h-*U}7%I`t6hsxOQE3#s|LDQLQ<$q(mFytaF)1 z5yp-HG!Y?3A{x$*t3e85OlX7Xr!hA9c6wJsb4eOC;yq4NtGHJ=4PD$wwAWpI$p1 zE}UM=+QE{09v1wyWwP54YVGvtqT|!)Z&K&OwYAgB3+QhrJgwHjZY}mF#J-<#If5<3 zhT{p?&TZ@naJe3a>U1vlY4zyB`sp>}^A8|L$WN?&ebx?Kfxpx1&fjSTb_*(w9mgeq zXI+l3JiWHQ4*u@V`dfoOFF$_zwDEV}!XxL;pATPoKF-fglKyJ%qlM?-IiR0Q{rioW zLyarX0SR_V5nu;G6o4i+L?Y$yGWkPG)L6T@uSCB_Le}KwIrNGD$jq8LJCc$XEK)hf zhR=P%i%k)2>|%cu-?VW4D67ODP#Do|QEM8-CSqr2=lSP9|NNgnkL6RJ{+tj<2=U+k z>hnlE|7j?n0wc8h6j-3>`Okdek9@n&qamm!X(z<|AJ;v{s`=sJXgzgQ3xvk86XLX{ zN;rPq9FyRt@=xkkGq|3{StdoBF_G6*x1lmQCj;LwWsS7mz>^wc6VG^-AF5v zsey<8-iqrLwUXW2<|A}&1eZa}owi?>(ydsoLyMGs!nl@+WQdf^?z$a)XT}CE?Rc1h zHidZJRouRM)VN9BTkn$Q*Yw_|VhdGnC(BjEnl9*&KMmLmxJOqvaE@wk95gvKTS2P^ z(moGtYM?G#eQ0ZKYpCLO#Z=yZxAD4wPN8Vp!lv<$9aUOyS&c5R(21v5i!nmt%r;g4 zp?wDEyoEJLA(Uy($7fvX!dqm1w*RJbSOUtDBN^+2RN6t?R!+ua_zMBg$L zc<3IXpixR>J;;z}k(K{nj$(iyawj*Uq&qw(Ts*yF zm+Y>&+cS5Tsbiw2FDG5gGK)l?P-V7xdFlQkJ=+Ey5kLZ8T2pD!ZV7F(Qxy0X>x@SP7wJPX#*0KU$ioI)Vqd698UjoOGmOVqm z{Z7L1-t=DC21;m4Q6*8Uhy+RkVaG(1%*|kAoWv?}m5GyxTQZ@O73)GQ^zBh^=7~jd zx#%+^%@faS?5dQ=$0#%PEz4{Yxh68du30ZKu|#xD?*n@qA=*GoxC_jF4~E7l46%PO zPmqUN!C!(uc`iM}uyLtnc7tBJ71O?x7x1wEZ%f=%iI6n4Bb*3;vMZqNUn&of8UF?i z)FJL&W6D&3gh^r8$R?BJDO%FFc9gjQS~)FM(Xs%BiY@y#iw9IY7iQWxu4|pzYpivV ztgE8}16?31617GUX)J(>WI}*8e*1AkCD*CN#*D*U*jtT)yH`>J0WmI9t z;P+i)h%wF(r894wNemXN`E`S}uUqS27Us$Bx}n;4KISuG-_7gOFgjeHTn5cV59**M z?VGQvNg_i?V;g<+cmh0xutRsz{Q9B0oRq_DywKIaJ8Y-C%+i=##4*`52LFx z%+`Q%Zx{hafDvE>7y*O8nuuoLvkCQOX0ENk_gXV>{Sn6`dYReFrhmI}{P>>f@5OBO zfXAeMA8C0vE{WaEay0tnW}=%-0O>9kr|vltjlgEAT*iv*D>=Pr8ik;l}>R1}fK;qMAfIR+TQQjZ&WksbF zI&Pm5ds1g#xbLJJ6>^fKDx*tJ4f|e_X5sruGA&2M#*^*;XYYN0EW7ghzVq(fX}#$g zjoyq}qn0$9Ju7ClgQ5}x$cm7~$0<&g`7h48H6lYUu>?0vS##{F6 zdQ%1`E{|h7urek~g+C!CNyAcF@~5y}7@Q)7+1QmePzhiR1d|x$_xqi5?)h`?eeb^4 zuV24zeb3B0=lB1d`?-JK>+XBId+Xo-W4*3k$Ly-Tshy4`*0X#gxBTf7zQ?!NAKB#O zo%r8=M|S#ZlYXNK=j^S8{5!5pP@AIOFljj`qWOxq`aX&8iV=tJQhzFkm}rX<`8a({>mQDKy*lYdQy z5F^S0oo0?$e!H6e^2nq6J=MbX zn>BV+kmEYH)9*2|ugi&PgJYKjIkR48i=}^Qv-b7OkSHR$=MO>#XWI~B*vg7OZ&@rF z{o*o-h-TX%hVM3VoyPy@A8jHVTk3DTNsjlY@%dTr)=GX&p|Wm2r|4{p?UhEfUh>=7 z*i#{WHZiq}tfR${7*EP+6=TlYNcVs4fh@%goOJ=3wpIEzS=v@-NqY)QJ_fQDnhgSt zshpViB<3~ipX@G{N3~*F7wqZrh6?bjtC>2t+GeY5?r3Q(ziEZcV;H>u_cl$>lHysd z?)$ndX7IYQtm(>r)SNb>VW)J>^`0$zXohl&BWDlQW~Lth<1<5M1eh8AsqUrjFCC|{ zBsS{JXrCqxUW=JlWjzPrt`iU6Ff<#ofa(aS0O5dHT0!)ERnc4UL;I-Tt~;w>hWNg*}nl4n)52 zO$RdV-X`roenVY;#_n}xSWQre`|Lwh_xTpQ)1F?Ly@FU}ZfWy>o;zjngjoz0uiTNj zuh=@~Tb}8@>&vS(rPARAG-adq%eAi8F0-5sUg?>+oFyxD?B|wM33WhVDgin_?r5inMCKdjqk$4C0sJ+i~ttro}eA6)W$;V-F`Wm_~PpxavJ4%L%KvgoGR`ILEY{Y{5<7J-^k6Q-xu3G$q>M*~PqZFYz#KYBq~d zwtJgnzx-?s`07OTJ_Kp+q}s^^K}4Ww?lUjT8@ z{cqzh-s>D@uLY0~0w4eaAOHd&00JNY0w4eaAOHd&00JNY0w4eaAOHd&00JNY0w4ea zAOHd&00JNY0*9P{@#_zx_4?k1@OKx(*jKIZF6e5`Wt{#G`esP&CRL`$eQ|yEDWw*2 zg?Ylbq-PzBuNTI?wS{T>`~&S5J~$+B=wy9yefA-9506>dJ@os$Imdrs_%^S5WVm*O zv3tGKy`0k%p}XrX-+JP;<=0$V#U40|)n8t*dEX!AUGK49oGZgljcz^5xI7M1=k?C; z^jsM8oL~)O?hV?A+#M18#?-tyb@)U2QpR)t{#<4BT+w?C-tUdy>-zR7|NMWuPlcuI zYN0OU9{Q^L)Ykh+sjU6LxzYk11V8`;Kwz~5mhq0V+7)-rcI<1qtcTTxeR5d$9M%m2 zAOHd&00JNY0w4eaAOHd&00JNY0w4eaAOHd&00JNY0w4eaAOHd&00JNY0w4eaAaIlk z@V#B8xM|$T28Y|S!#FR61@fjoGB)eE$gjIFdxf)V%&xGCh{tIXv=Z z!f1lfIkvrROOiOb_b(^fQ4^adt8}wvl}MFxqcb~iYH7mvL6|+ygP%;Nb*oD)UGnUz zU0MCMW!2-q$e1>(tf;PUKRasc;89Z>)tM0(++obiwXJPSl3^x4lW5b#@$^gNv{dIa zvqSb6!GD1nMKe)MzHNNaZwAb>DcEjkhG>L z)%;(8ujQ6ZPOjy$7FksF>T8RntzXWuFIc}dExMvt`8+uS@9~olE=mA-AOHd&00JOz zGzmp&sloO11tFMcOTf)n7D@k_DK(z12kiw93cFjsj*Lb zz^s9J-e>)0eq8fEE9;6g$@T_+Ie)Mxp;N_2eqx&2WX^eOXUVHnOup`!QyVoI^eyFf z+5Ed}!C%fF>@yeQ0v`E$GWM*g*bBzp(>Ad50fd=s&RkQf)Jse0FLkAM)hgQLCs#4c zD&`2!DAIAHllg)yhgWfoQCP_G86n!Mg9pyz*HYSpFE6Fcx)!l^j+K?Mr9MZgJ%yh6 zLwiaenrvg>peuI_A1t|N6y*mf@n&w#560c$8gk{AjbKmY_lAP~U&Ng#poXb{++uYb?|{?VX=tpEWK009sH z0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI z5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X z009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH z0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI z5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X z009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH z0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI z5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X z009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH z0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI z5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!Xn1ev=W5cLSXL8kPO^mN4GK(hHtJ09W z6D=f$F>!T>8{ghxJnSazHz174Oq$)3ZkzGS@zj{fE-(1YooGUVET=;WabfHTaVDAX z+~4T+A1#MDJe#xi_~BXWyerj;4s5Ns?`&E>)@ct$&B-0Dw6^1p6I6qwFuO zZ0oXWu`jGw zOC#x%qM*dlJnWLb)%BQtM(N%9J@07M;R$G)Lc7xyS1c~XCgbdgBzUi)-D`pM$iM&H z>#>e~SOp&rx~Xd$X@3MQWnDkd3>_H{pPW{p>c~jrXJ2z>N2K-kCO4mV&ED!H**1|^ zCO+`@S2opQo+w_!SFjb2eCY}%X-_e3o0ed)Jv9~~YIFa);()Z+VSSH$R!vu4Lf>(=?qTa=OACf!K0 zE7^^S$ezwdF`;^LZ+u7SgKu^i+ot|G`#n@;bhBM5vrNs-A{SBugCf}my~AIwsMJI1 zps}fM8!5}{-Zxt>XF&(76e};(ITmM|*eE$uu4`wcJHk@?MD@QTN(P<9X?!?8eX)+g zM>l7`?ucnj$9}yL7ZY?xT5~sW>m9QU?#eD>2I~D72NqbHunqSfZoO<* zPPX}bx_Ty+nlmM_O&1T>VQ!{x%-*~kKf1U4w`I23->u&G&i$=_D64BV|9QT|4ZZ)9 zQq202d%bprItOqinggTpTf69B)Vvkuia+~Bi!N-*c?Yl;m%Ifi2Ld1f0w4eaAOHd& z00JNY0w4eaAOHd&00JNY0w4eaAOHd&00JNY0w4eaAOHd&00NGH=?2ljGxiHO~j~2 zDTbu=Q)`ghIc4AzJfh1dAwa@Qv)+ zMJUSDWaU@ZblW6;O}$@>&mv1-aFZc|boXsXIk>g26g_0=Xk?}TX)Dy!wL;lUxo*4N zCBLy-#O4V_&N;!0to$x*FW9zCnWgdfUtO9IpBVHoiuvBN-YbJ!acWsiURIsCW;Z_C z(%iBeKdV;w_{adP!rSWKY~lbjO*~UL5o=q>RCDl#|N8BXoynlE}1# z$p6q;COY-hw^NPe&U7hwr-}4ZJ5=JDupxqM|B%2X#U%5|A8u;&X6cP3#mL?!Vy>mc ztSHSW@JRNoLtM{{w6@!Nljd;`b$pqH2kSG#Se`Fpm-9GA_>|6}jB>iBSeAIqo6Xgk zT1WiolQXhhPDkd9yn*gzU*-BQ$I9Zu7$~V9(lel`}r06K1o9Mtur$#KRq*I{{v>Paw%&V@O0g@J-U=N z3@LKv-x(5hNMejq<7re4IVpyk>qV4~b$+d)nPigA)ozFHlO=%*iD9PBS!PrWxiiA{ z#eI--_iWJCXL}qlg8&GC00@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=9 z00@8p2!H?xtSJGz;JQqfS7qA#%FO(Hy4D1zKHV}MVuQbtsd-4sZ%V1Rw$M0BxUb4& z59P$@;16T)1U-zV_&bro9^z;0wDbR42s{#_X|^Ir<=A&`U5IN6c%jeEb^3i}6?aU>L^LzW5|EnFafQ4%waJ%E5Tyx79Io7sWRFLvfG=Cp)>+b?Kxl0$O z-?{wAXL!QqSjlF$PV+2XoI2@ZbSSR&MDN~Ksk90jR2kx%{QM47h#v#ws3fBHc7`qPqRJtd;WZ< zL$|D{C2n6DmPQP*(}M|3SkAFAFH@+ORczK;JN)y_J^8U^Ep?$fcA+dJz1;~I0pR-C zEQZESsdS(7Eum5~$s)BD$!R9slQ8eh-5*i+w1hJG?01!xL$B+7-GW*BWR`!x;@{H!CS+?gK?b(*?ujz5X3<4kk0w4eaAOHd&00JNY z0w4eaAOHd&00JNY0w4eaAOHd&00JNY0w4eaAOHfMfadY1ol?E(Z~UQquEg%l?cTIa zi&?r0wQl(eVPPyLd-S7);V`T8jEUy;2MBcQwCG_B&ozcIJZDJpw>dB9B#O>9Ze+hL zLJ?Qmm6^D^wQu@pKbS^!{;<9UYT!{+gq6 zDzQ1)coRob9K9^PLN6j&jT5MkQe$cfLt-fD+-I`PfmvD3`Y5_tN|eOp)%IPCd>$3C zk|3QpLMNk`U3ZxW?PT|-9(B;Xk%qQ~eQj%QdFb~zs%*M6WP0NDVq!@m$yzuHHHlr4 zNYux#mbDBSb*~TZ&8qt-B_v;CF4_%ddHQCv>gm(Y8WJPSE znM6JmqLmd_qjIs6J06xLkHmzCnlZNGgO_~TaVAMhgi!ac@rvIG*8QDE|JNKtHm69E zzv%I0&*eL7ybMx)Od{#*U&&OjNQ?{2!^NMOlF+gexw6ofS|;pKPoNa@CWS9Ivh`9L z8*EKb0yNqfCq;%t8G{m{$WKlB;0mL7?oz%c$@)4phIa4w1*vO{r*+}AUeBf}Vpz2u zw*54P`NA0I$}Pf_oVhhdM~{_fV*BEvou#PB38Bf9HQPRiGrw0J`pqtDV$+G-CC>79 z<*dwB_skUR&DgaSR+4pdwd;zJkd7`Mt5H&6wvPDBbk9bn?p4uJz{WB|*AX+8Af=yC zrKj%@IJde2~5=5v);Uyv{uI|2UJgC$fk!uJO3z%y>OHqdQ{zR^AkA zgixV6N%O>}c`VP&eMocI5}MgVjlJY9G;MaoQiW1qsOZv?9{rJ}mEuBr zsnt*n1V8`;KmY_l00ck)1V8`;KmY_l00ck)1V8`;KmY_l00ck)1V8`;KmY_l;J^t~ z>TbS<%B$sAnDeA?lU8C4`H5+&IB$GW?4DmM42M}Y#p1)APURS$A1vc9`~1Xyn@!c| zg~Y@b*Fv43hjEYl$kwjxU1Yq&n?O>*(Ixyf8wrKcFm2h-z8J(VXM{D zans!Ga+fqivU?d#A~!94?1C<%Av?cZGeMBiYoi~|tf}H75|gvE?JlIx?!2q-b;p!s zt8#O8uWI5liR?t}Ei@K2yrUWTAfTuzt@P?N{@9Ntdo2_xGlG4Qv2U9fsWm$%oy`{E zucx=x30018QLZOdnx%fi5w)dmYV*%DS_%p;dKyp8OwMClSF>Hl5Pjhfnn%DWthUrq zt1TT1^vYVPXU@fxX6=imcVrp1jXE5B|8V>9#fkq|pj#QTccqZA&N-pc@ALR~ApKOD zL&)z(vbspGlarc_e=G5(7<@-||LCKud+%=Q9cj^O9{p@$kdAC~wwmJYw4Bx)(}L&q zd47&llB^rqh!l0l)ahE*rkm^-73y-brn5;m=U<49u^b~!;)23sh$S&C$gX?%Z_8?y zlGgdxY!iPJbrcIJdZJW>%vR+JGdnCqOq8{J6r^cnXzm8K!kjjESQ)XvOt93M57d~BszIrppF7p>Wd!fr)(ec>XtZ6AkovK?Gl z+Usvyij=lmCnhH+y%wiULKJ)D(LpU%*NezqguoKT>ani*Z`0DsXs6%hn50?B&~>G5 zl0-2+Kidws9%VvaZPX;r6Rh{X!jg|wwWc}KmTRdems@eX4aziiV>GYPMYnR|I%4=f zN%9Upf9>=H^w}BnR>eNAvj=a$m!IlU4zorJMbj?M^kxBtmE!VKXfoEe3C@J{h-F8vOWl+I zdzRsqj9FJeT1$5aWY&DenQLhZUGKw1Jk)GXP%Rd%toKa(7CO5#vaIP}(wcm>k?(|c ze%hS7J}fYORp|1&jir65!zCiAN0GjsrRN>FO~zJ6?zDf=@ZjUrrA>?CdKZ~`gB<)V zeH1L5YyH!F^_cew=kO~u?S(LsDrq5whz0PKmAT znt4h`p~tw$APEUulbAHi%?cC8%EWS|aT^kb&1zC_V~j#18EtV-B(^@0>lZ6JbDC_e zc?U3S1xAOHd&00JNY0w4eaAOHd&00JNY0w4eaAOHd& z00JNY0w4eaAOHd&00JNY0xKr)6&2qDP^-Y1^ORL@XA7ANr=hHhh!IJyT&>Tw~8E`^U!~hJEtcbWTf^GjHs>`BuR&N$kK=iU#>v75bnnu)IqC!N*0+z<>h=fdm;N8; z8>dLWN%9BCPrzghafahLjs=RNc*SwYYo%%Y6Qpvz7if@rv`@1*Rw?eCd@~Ej8P?@L z3GddLdiIa}cw0uAM@Fj2BhSkN&nu%+_g6s1((W$x((aOG4TX5!S@rJtwz{o$$>{8#N$y)@ zi?b?iZYxcyGSnO9cZszCa!gKRNxe%i*Njq@LTTW59;AsuP44+qr0x2bIJmpZfwWB| z@<@YgCJrLXN$PCWi;2d&^m5Gvp>w?3vbHU)kbZ-1Zsn5$(*^1#-rb;hm2|dMjh$3B zsAGaOn(La5KsBLLzfxO;u2TV$%#umb*dCtzb~-{s&!dPhlDpU1c>Nblh&bfqJ?2lG!wtL?G^R3-@ud z$=^<{ZS-<2xy^g5Hfpzv?(w@y*YDCCxKY~gMjwdTomKv${l`O}~0mobKBnpwn z8q1a;@$&d}S7|$br{c?@9`n8K*Xd)iU@>EkHuR!)c5Huu-$TzR`ysBNEPXVfI{YL9 zM_*Q&3Xl++Wzp`wLOn%@CKfO4vXV54p~lZl%0|iP-IcP=YstW`<_``TR$^_p$5V^= zTb(H_EkhYFOqW&qMc9zS#%5u`SRO8hqAW#OW$5FRG3>W~!>&@kA)TA1*G(3@&!|@^ z)2K@B34c|tU6#G>liDi;RQ#O5andTT9V&>$bq~KGqe)C%qVw~LEV)@@iAI_!G}5Gn zF~k{lmF&?fLB6wooBI4|>@c}b!!l*8GL>fLgWjLBoF(q6IZa%2b4jqZr5I^R4(S{b zKU(pJGrpLGx%i0`p1G+b6G$O>2sL`&#aOF<9CkHbBc}s1l9k z@XCW7%MeSWrBK-r{<1pQW2sl8I7E8zKOYiB^MqA}QPz>>+EOXkW|Dx?7hHYz;GZ_y zW{n|gBM7bWY-8aW`4x`suzhs-pM28ePXmOelk5}Oul(YGsA{W@(s zKjUV{uk+rXSoV`H1+=o{?`pA1VCSNKwkx=0bH_`|oEg#?+#H#Eijrqe37p5p2SQpn zIWTN*oe*S|Rj<&+q*5QFZ-j+r+@;8?){hiMpM)pXG0Ndnq*A-`Ybwr&pRP$GK5ycg z>C@!YqKtOCaI&z4RTbt;wO$Kj=4=%Da)xAUxnE`Dt-r_1*Q{JGtzmuNtMkP+b~5smXBSSt@-hC2aYGp#O%x$@vV^8{Zt)>KpZK zcL^{Y?&cz&G)ww~R;lTA?b1YTUm`QVe0$`5L6R@d$MW+ViXFX93#I=>ITt+H+NK)M zvT|09FH1d+&DunhI<9G(Ynt!c)9Yd-?UHSdl4JNW{^G8+Ht|w-QC%~Zek#M?FrkG`lzdqqyfn%wMPpt4 z1vSw$<9E_i`PG&>M?fjTZ=)pWnka1Z`nVK*P`F6uZC+$(qc02+y}QZN{j}d5A5M`? zYa)U`j!Pt;BHq`jHpyG8=Z#V)mt@Cia?sqAMc+5#zHHlLS+pkmb@~>0_oQV~ug>4# zop;zutqLOHI(yc@Kh_PlX@N?9FN0B5_YpJZ*DTUCY{;?_Hl# zC;xParLZLSE~lAv?j+8z^A`Jgn>X_{mT_~i`A`?buuVfpzFI1NNqa+$FVdUUrS=I= zu(!69rpQb52K&ZEI`!$oK-VeXWN(OU&tI;ty?wzLm2aBlGrU*qq^{`d zrN>XQM^|^Arc259DE{;?uIWw4HHtnpksrNWBm=EaZ`JBzvtY7q{6!y1v&ny2lP1$~ zelH+Pybd;T6h@!l#_A$%5+4vx(;NIml9CX?a`B=}F565Wy67W>-cB|q3FqtN$kp>7 zM;kUt)F5$8RNQ+!hrf>qQt_?!c4+d_!U+t2KzZLbZ53@VQ%IV=tJGDaHnjTKXf&p{ z-_=cvDCeWj%ju&W_@wQAZ z+kEjN9jt^vmvN*&={_t)zzOm|I9bv`sKg- zd4Fza{KoNfS8iQ+e*Ex-=R({omp`fWnah{2e#uWg|J2uf$u~do?3cZC>W$yo{I#pU zy)*v1kNlhQsn<@8$EQw(^*y)o>XXks^VH)sFI}tO+P?72mGk2(R~`=a=w6~5A$H>( zl|H?(ar*nK=P35`KC*F|wuQP78{+6a=lpZeUAgka71@@@pV_(cx$NxkuDo^qpV<}KOx>EW7rW5@iNdgt1;Ep_Ww z{l2&Amv(O4sGq;_V)=gZ;rEzZ&tL!W&X(HQp}6O--}vxLb$#nbh`W55-cK%na$>IT z?)(p5@ZNv*^Z)S^Pg2~IFP+V0oL z{o7Z6f2V%t8-DrJ_#^7nshX}=?)~oNKeD^?^oL)3Kg~bEYw^x>VC>gRVp80yg- za~}(_*Z;KHId%Q|jgPCBDfX8?a{UHv%a~rig*bW}d1>p~&WpERl5KhR`V|_V{qQ%G zaXarfJI}xT;TOX;?|g{nes<^OGVc0yvs2%=acyfP^+>#Ntsa|Z-oAa%XaAJ?6uG$P ze?KQ-Y)RWEyb?x!fA|FbQ_U-lUY=a8BYR(Jrg?zBFD#AM6#xBrBfE8ms6|J5>*;8Y zLY%dcJ`wnIB=wlydh4w>Km8{EfAeSG{0G1OPn9C+O{ISKH$MC3XIUiIrzvQjxX*s} zv;RU;JL>%cwNS4wj&pyOT8JC6KDy)|n`e!*jDNz@bZv9G#vyYLowsKf%wev4ERQ2i5%Z+>DzB#V&DFg>>X+9xP|@Lj&}YTefKuZNLso(KnSBuFz?dxgDuyJ6{owq zaEY4u6VXL>E$h)6>8aCIG0E*%*{H*oR56LXD$yz{Q*o~wnXT@hIDPjTjn>Olu8!o7`+bF|lNVs&D)IK8PEPc6AJ zcJ274*vf^J*s#e>78bN?L|a zAKehV(MaFqk4hqyk)@u5E+9@nXVZe|k;8JTbDXpBjn~m5Hcd``sY-hPy;sX|VRkpt z52G3j$GaA*g=0E+!btXa{FW%~{7^Z>x>44ZnBp96rF`y%wS};ByMir_NwkjEb&|^C zhV{}GEXmeP*@Q@qej?Hl_vsE>G<9XL*R3mhyK9F!CI~(=Q429vEF1$>m!J0S#J(ex zBl~@hWB2-^HPZISXnT6G#Ed-P7^~-BNQ|)}<>}{7>mg1`>F_Df|_nC%c(xB zy!Bxj3-wBp?CK_WuE>sbGlgqAX}U>i?P#tYRu)DVE$7*}P{pmm#%Rq^AtN0*@^$fz z)kwR!-Oo+QNLQ{{iS_(iJ!>C@d0ghay_b8Mt>4w+EqT4QIrOECZ(*jOyHRo3uMZCregybiOjKP!Y)z1X0AFun7etAK8Q$!Id>LWkYWj&-ex_e6V(&=tO84WAcf}O4lnhMy-) z^pN95%At6Eg_u-!HnDI-XEUAF#+ctofAWhP2MZ?C!U}TZx@vLl#+@duh3eEIx8|mX zo}?Hu(N$DP%C+d)>pgDA|8=ajzY;TOb6Dn_Iux5I8^mPHY}#sa>1IE$M)#jKdRpO< z#PaXzb4~k^6WpVR^s8#f=H#S?j|+BEtvAWw?c>BR_OtGHbY`(>UQ51HSh_R&-pcyy zMbSO0-G^#w)#_TZbh&IbZqeu>;YT;njlgnqa9rCcid|AjOMN<3yi9SSk{d7lP4Qgp zh#h9qond{ab)UVn$h^je>3~Ff_Raru!67${X$g)@Tdw8#Y22dn#?3`D4^f`=Yvs`@ zOD8K!>F3hdNpBt^@Pc~=z|yaxb@4WdNo5x<7LI6IdQGs6wNnU(svE1PBq-z;xxw67 z2*wrxx(qF$oqYcSMbce0WEpAv0@JN9#iVoDM2T{g5_gB#7uRQxCEoFSQSO#ZhuO%< z?;Krz_E_$cW)t}kit`;;^FU}^Ke9}qh8o}~dbRuN+SB=7NK(7oCW;W@<8 zKT|IQnu>kGLgY4ops!qFH;H_>M7|NNT)orNKHVm=Cm>mLkx5MAPh&$wD?T`ejt`|1 zWJ%%(-Y{knhd|NA8cBCoDAyO>pi)%UTEQ(t79Qp(jJnW!)d#;Sb&EBuF*nj(Oe@kIj(k0+Lblb)HJ<#EnNqF zT0wKf{cfLld-Iq5cs<;-^s$qis6yHg0wcZDs_8y23s3Wvu?y<0!_amVa<(oHUnl5F zketvgrjeIOmy1a=QxeQRYF2vbny6@MORWkQzFdM@cApyTVO#;%_M#7=#qMRz_x#vi zvezs(T*gW^9I{)IFDQGdZh?=i&|1U-y}yGzwwM!HvP2JGN3!-73jEp@S< z`A>rT=!_ABnRBD;toV5g&Z<}V-O5k?*M&J%TRDvjuxeEZD=CB-=!8iSO9)rtBx6lr!Oh|N-$bI6& z;ctQT1sq1Z@ryPyo;%bFZd|Az(>tF_jP6D{GvqMXytj#e8woSX%nVpQtT^TPTbEz` zU@OjhWy#`ozV^)5xaeUzZmt(`@s4Nkvrs+v%bqtr!}Yr7W>07m(GixLaxLVpew1S_ zEGCT2GIV?ju=RuuXX@-R!Fc>O1!fAZ96K|`1;~0f|3%LZkt$=;Q>(QtJ#hzM=6iAZ z)jY5!O3y-Qe`RiZCNXWSh{cBMt9o5TCJacO%J3mJy<#iHoF-(^U%0~<%Wcf4q(n9>)O{C zyRX&vT)dw4EcTwOADRMY!IhRD2W~D{CrcauaHbAb%C!v5Tc0??OIg!5!>?N(OsiXo zEvGW2q0#$298w;eOF2&-`oEjm=Ml=a%#(ZYvG(AXFl_~RKbb}czEu&J<167+Eh(F4 z>$@}cZKJH|ySwnOKk>HN4cJf+009sH0T5U!0etRSDozwTq6GLnS?ABflg~M#;HPXB zu3b~$9F*(6gPIug_7cE8=|yv34(yWyL*F|w_DL@qI6wddKmY_l00ck)1daxQ@I9@{ zsxjXXO=EX6-R53v{N{|*RkQP5TyMeL@!%Kc`VrCG^Mz*M)L1j9tNZ*iP?2WA9oz^7&vI zen52;Sf)w4@7BBL2g7rOGbf;|uGVAj3N38i&srRNvPKo?05kW@c3J@jgFf zbCSr;&SEpe)Pf-@jN|ZU2Jc8(tz_K#6Gai3tFWc2l#74!F)k*|lLj9(dGIl42W@%J zA-diC&VnIKhr|q8%}Ro-A~ZUiD%UcXqG(%KLUyw+Vt~%$n~1zZj3;}n-$d&$gHMzA z>PfFj4s|-}{ZjlJ!tn>&%{={S@PGga9DM?Izc;a#3GVx){hkN)L0}&V*d^C?r$wvi zg}>7>!O%-!)azM}!(Y4p*>b9(N=CqB+MLRRKRRau!a)E8KmY_l00ck)1V8`;KmY_l z00ck)1V8`;KmY_l00ck)1V8`;KmY_l00ck)1P+uy-yO?+_5)q)w8?j;IS-l7^sKkf z-V=V{=G_Bd!9Fa&q%|`oI8FsY#w;XLTwHm>ViqD5rgt1)*67bT|3<%WS)Spm+0%?V zWP73K=_Yq2<31#4|925Xerv3nE$}JX)i9LdG&iTSP@lv(8-+}3m1gfff6yBv{$B68 zI&8Br&Bta!rE$y)2yS{U8`)mv`k4IBx|QzKZ!cn#xlXHD z@>Sa2KTY{+fRAcHw&wbCHYVU1jdzyM` zvJtQAS!}(Zh@U&tNXrnGQtiQyEn_K%uf|f~?bBv&{op1+#GYg=4MZg;j>eNRq@xino)OF#H$QmrNHV$H39H8=&ba1f)B~Hkhc7qUfZF46bL9bAuK}32}cl z(TPQ$$4!#!B3JV*2}(q9>L$Z^5-*( zwr;yZYU8cxI&>L%&yQsmt8AwGy&~7*!m);Gx%PC4(HA70x(iu+;rdeex>TDOQ#mn< zs7phmJCD3qO#WzNg>Y~L+#d1sANzr9A;xLVCp4XT4~t?CXrbv9Y5EeH4-;Ks4}N8r zbq<@EBX<2m=iHjs=Z1N=uyelAf74m!cBhq$dtOCf;Z@sBYeHvf+si>kZ`AW8@S)?lUz^}>>x}G(~<3CCvC5&ryo`fYG+-UYPHU2*1Ug#|? zSErR8dS9wR1_2NN0T2KI5C8!X009sH0T2KI5C8!X009tKR|4go9hL1_Y4fA*9{+;o zN|h@ZR_N4|)8ZDZIj!Qp`pTbWnHjT%UqU`BZbq42x6!?>X^vBmPxCHTb6UlH^qHR8 z!5+pC=5*WoDOQLJV~8)u;4ep|bQT)?!C30S9>?#EVvtM_%IeX6s3q-I?}yf=H1;5b zQ6hCgT#QARB{V*^rk+G5G0`6Ro2jOzxAnf1Sz0{3?)Z_kyxCmMG``m``57$T>eG&H zTe1?FlHMzn=B09)pi|}S*Qc7uM*3uht%$-fM`)3`R5dKaP*r{foy5G6gMH3##5YNf zOtz0$cL8c5V;XTsa;A0R==CL<(90|(A1S<_h9q+Q35icEskh^3Y09sqV6s(N(OjQ7 zT8han2{q^7^N7zKOLXq!v6;qEeJwI})zUiAN7)a3gl2JPnwDZ#`q1Ut$gj+Kb6?0f zxKU?Qo94*3ncXRx2J1v&oa$`n@mhOtoB9eeUdlGUmqS?o3yKAS`>{>Kv zB_{5K3m@&t;2A8vc;sfJ@9GTs`n_El`)!M>(Qc|y-;6P`FCzZgrZm>5+nov4Tdike zI-_P7N57T@xEij{96gF|?52?pTHuxNYuJIJIWlP`k=_2tE#mIj$9uV8#2G|7{%M({ zl78=<)ZBZSB~-AoPxQ=6n%~3w-cQEN#j!CY@r#?Gm!?;{S#JuTsZ2YhuxPKFXutQb zkX*~$&KN$ga7=iSn0!_st!cW)-UJ+gVA6Hd{AS9%<>V_`w}q|wtBk7~KZQy&eryjN zEA&B6y7XWRV_dD1lJo-;-P+;`m%NaUYgakL{Bt)~zv^e2V)3&=SG_Kq zOJz^L*TuX|`sG|T?)guTIIimOZQrqrddm^$l6XPq0tckHCSisQflcsjq&4&8;YNP5rh1c&_mE4mQQ|O1*F=YWVvm!BpzOKJRGe zP2l(k|Lh`J>zQNRvWybJYw3MXjY%16)UH=~pqHgV?b1N9Z@Z1mHhz`Okbz&WnIN>r zeh-Ce4maFMo1D>J$_JCHiB=`@dW(A2^31G&`TctSl=3!LdV;&-`ID)2563>S#Ws|B zcoZkG$6F4I+@L10?xYHiWDGIo=ug8YZ_-FfvKP(9x3-OBv7Oe#W7M?N6f*1FjP$O% zLxWCqCz_U}%b>fAnazl%8=I3#y>Takz3-}M>G~7*Q5KUEUiy75hlxQ#Yu2ir`dS_Z;C6QolRQou`6}wNv!4iV(O|S>n5`9Ecco_=iM>q zJ@g1lN$qOA59k!3X(gTcB3iZi!OYV?rwdDK7Kv-FYF=M{goPCkx1I=oG(-Mu}XHTU1h$9}jRwP#C?L~-hNNQZ^D*EV)d62E+-l3cZ6 z670#|*U{$V+&Ti`j&pPCQ&KhcxEbaN&zC?c8~ zyA_e&ZQc0t$htV^Kj2>ex}j(1my+xSB0fs2qsz3VZZFVQNn9W!3@DbjmS0xVh~a2L zahJVSj8cJPq>?Mg4mXpZPqT%ZTb~QMthCtjjw`9jcZpF}m#m+!0a`q+x3V@dgwD?w zR9)!7zPeGiN2ZHX|Li?6#a8r0g|gw7vIU*SkP$|46;+dP6622a_R}Bpwos!S^ZYnx zX4*U6 z4k$3aoe4br)#cW=-g3$S==)6I;f}wjrRk#~E?@f$9_2v*1olJ#pS$*iZ(ouh{*&Eh z@lM~(Wfj)V8|5rxMc>q^u}?}atJ5c++c6h?=)ykf;Ibmqr1kBwV{ff!YE08dp!KcI zFU3CTW3?(f_Q|S951t3tuED4f2m&Ag0w4eaAOHd&AOyam8q+r)YPETFlWw{pv2s5H z+PunRt;nB^!9FBz+4bc6Bt7d>>fVorwa&A~=`|1LAbFR*ZD{5XyqiYaBOg%y&tZ_x z3;F>0voYASxJlg^w{X3o^Coe$PyTvXYv&r1*r9Q};Ro7`Qg+u^Uc+7P_$fuD482@4 zH1La>X(VqUgS6ccA==g8wX7Pm%YCeRmsH=_YK$T6Gu}dj=tgRoXk|&W)mWQYcS-&g zwcD87$({tv67{TrmHKZgSx@((OjwG8BO2TI#b9{wP5Uw2>Xtb}5RDXP5>-TJpk9lb zbz~jXPJK~VShJeUX)>1~*t5_|-JiNODV} zP1GQVu`{!r`;ixXh0I~Ran>+2ZdRS8`rVeerKJn3TeBEBn%S;fK4)r zvn{%uMa)SjR=exsg56r0!%9W*2Rn^yb+)iNcHZQUYFHUrn$>1U%&M?|{;-8%1`~vi z(K_2`+9q?1adBx+2dK+31jCYYwc$s01~f9%mCcj}uN!tqmKYv+mIfmg+2Ljozi56% zBgLzbC`+SBUL?jQQBgezDLvlu`RiPrs&Ono;K_|E@w0->e&XU^|Z?uKPTxDS~5NV~yfjZ4Oyh z+>3i|75xqy+thWovJbOLJ#tzOAY<+7KBP%?HC|A?fD%4d^f>o7Pz+@y`QZg|d$W=b zncvR4-sX}J66qq*v{xIcB_vU8U;Nr4_1RSEmuvU?yV}u(#jn6BwiiCK_%>~wA!Y@m z-qL))ZPDvmtuE1r*ll&GoR_Xx+e&G%kLXvQ)M`sp3>JI@ksF; zc_Yh&rn=;7Zf}ig)A*XUE^UhlHeXFV#yf-7mTt0JDE|a(%+EfF%kssXz6z0TDYvAq z#}{k0y*07wvB`vBQ&M|-r4$#`lyCWvsMW;1r4$8|Z{Lg@x$GINjbBXSX-nvrQ;yG* zY2*%@@uk)xc{RFO64jj0?AvnmB&7~i94F_=#+37f7U|9t8mFEo?qJ^{-q*HeXIyF> z{z}f1ZFinH)@io`#JTbI# zIX;J-C)-2MlZ)FIpQi1l-SHUJzx1@4T)N0pWo?t6I84qHKJ&WI6ZiWhB$>Vk!#g=U zPwss#smoikrJm*AUNO3Lxu%g;o%lthQ)H5yCuUvF6RowPm)_tH^3*O>)z+B4A|_Fd zsU!Zevnaa$lHyKjT&3m&ouTm#oDc9)czFBSb&&^Bn+tO9D z+>5KxClfmSs9iV4D0*!v^P!rape51JA9pvkZy}EDWHukCu72Mpi&Nunv7hTzx9QOC ztaqKvT<`XfdbB>Ocb8MLdFkiz|FT@8oBOW1Uh!$wIrlX#)L(No`(WxU?o_hWd`cyGe zU#-R$>6)WD-gxL5sC9Gw8DHX$0nN3RXWM*zu441jtBR zc(HEY`nQ#)&vJBC$YKsw+4kE=Ox{Po29VYkFSgCf2s6D0laE$DQn!c;y@!v9ct@jM zN3k{4dxJiIaR%u{ySS}R)iMu-slUw;m*~w$7h$|_$MoSX%u{bMI(H0(Q2OB1w6VTO zGj8+TRE<74s|0?GQhJ*X0^jK9xWv!eg*k$Kcks=u)TTu%K7o>=T4V#beZ11a^cD| zPds(y`Pbig>&kOG4?jPC_^D^gxGPtx^QZs23r~H2b>$M*JAGw?;;yvfHcwa2Kl9w_ z)0Z~+ee7MQuAF{qJU+eI%u8R2ycX6-b3ggSm1nNJapeka%M(9(<;4rnj;}n`+Lni( zs-C4ap8I~O`NU5=@ywMc$4_0L!mh1+XZQ)jHTe4b&Cd3V*KTa7_wUs2d+XkpU%GLl ze)h&o{_Ug=aXUB6PJQFWmp*>VnB(tz>*BQ=J1^CzUcOPr(PjFBr*>|<|JIAwZc)AS zAH49vo%-U7?=RzazRm2MdikXnKdyFealIQaU#Ga850`P*ZkQX-zI@}x$7_B+`Nfay z+<5U?ed<~>uTtl4hBeaMFFyU!jh$ONw`lI4e|G1}&dbN2d~v6&`N0>>%g?{G^Pw%N z`SZ`;`tZ(+_4$`x3~>jwPr|&PQlBC*^gkzNwxsP7UU4J$6ZHxDrMi=0EuLf2tHoZz}b>zwy~OKg%My zK21UM#QnlA{K7w>#Ljx;`-OSy4OyR3_xvEQahY=;+&--aPCYbkV7aA-J$QHNB@eEk z88~%2F8sZdFb*uVKVe5`pOmCa-2sf&C^=8r&+@17^TeikopSXLJIzPXxb9c1h`j!) zC?8?T&be(IKW`3C5pw9uz@i0D7;|?P|7h+zs+vx3DCpV9^s8QqU#Nw=a8kyv_Jb#k zu6&p?#EbQw&im?J0(v2k@md9w^QJY+%Gc0Z!D0qmq?NjJN9$`ve0KdPe6!S8HILM} zO5fMYTj!h)o%KQK_r3DGx2tCMwBaTFIf|XV*aTaW^8FSy_Pw22{}I~nSsI^BEu~g4 z)6$lFP=(?V+P#8V{_d;}>&d^>VN6X+n<*{2mU8#irrWyL4JfPT`VXb$wf|{aw2>uk zM`;fY-Ij0-nH4|F&m4!usI#woL2Jt@CXDbox`Pp821e ziL6pOKTq0q+mqN$LHWX_>2DeJ#8CDcy|sy*y)PoEb9!!3_c+ z00JNY0w4eaAOHd&00JNY0w4eaAOHd&00JNY0w4eaAOHd&00JNY0&foj;U@GjmRsFt zFXIkM-})m5HS<2sYkci6mQ(fF%eVv5x88d|6Cd2PX3nYSji0l8JDh&+DjEnJGy$6} zAlEY25|uDZ7|T0{v%Ba1Sw0fSk=EA-d#ccZUx z)-{>RtjRixWz_W7SJ6NK1VCVo36%HIi9WGwyyBz3wDO){`Peb}_M^Yy*g_Bh0T2KI z5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X z009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH z0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009tK5dpKJ zdG>Xh`@eEu%cD35*rR~p*dIFzTY+r=0T9?n0;7Gby>RLJHy2JlT8WeO*_;P1uFqQb zc_nK^efpMe-J0%)7X(1yZBIb{Hu$Ii*UHHtm%$awB&AWEG8L`Nsw;ukTiys-jnH z97WCgmr~kWNFp1*xap)9@o;yQdgzM|VhapSYUJO0R89X_4{fCQpW@fV$ z(i}OtNuQCW$_AYwlxdW?dby&1oW(I4G@iXo-4SVzJh}G`3DaJiH~B+5 zMDS?5VtIVkaPJ!J0{VQ$UyT_xBE_<~3g^*;zoMa+?%eSldMMk&KfIS^r+8D@v726* z2VWusAst~t~TZ_TC=cdp%*q4wHD^S%ihXJzd~rX6)gTmvO@N%!T)vR-C_O_$~KwW#`fP!*QgOodPIp%uz?C-SbWJZc4Z+#k}$u zE%g|gN+YGNZdqn4m#1B2Y(+MsuF`i;jJib<_cvv{+&l-F9CEw5d8#=6d`u$(>jM)zVL_F zarI#bxZOZI!8ID)UWscKUHqFfTD`e7BVxLHRryMt|Ej)~EV_n}*FV-WWkrqH(#0to z$s)SA9Q$yAYwYfFMuCl=gu33^s$KJA(A~I63##km98tstJ;ay#YV&DRz9X(NtZB|Q zY!!K1Zrkaw6b8-cnFKbDXK(L$_xRi1wxvj|v!5#$&H?J`^3S}|x12@S5b|b?GH*%J z>ohbTcQypIs_O7*Oh)n2k0FDX7TyzZ~uYWu(Q_|bU z1~I0=_3}RApPa5Q?CJevRryNY_ZR!#PX@1{ zct1J4<+i;wdM2mq)51oMe`ZYrcWz|*B-1`2fqsA}BcB(n(>|ho@}2%X*^sfZa~U)c z009sH0T2KI5C8!X009sH0T2LzLqxz%U2F4=wy9AE?tJ7!Lzhq)7rDvfNKJ}SZN9+v z3EAmKO!T9s&70iQXxN^_e;FB4-TNyZmHJ1mc($kU%{^U;WLHi(jr88u-=U47vE_nxTPTz3rjDN-pDHE-KfY zZ3(^qZev+#SM63}bABiL??{%hh0Ym1KBQ$4a_VH3!=Y@=`|O;Vce~02Q!8gG9rG5Z zV~Kag~9^ASsS3X#DIS!5O^t{)uy>8i9)#|Fe4H#d_y(##21pb&1-Xz2y?OODt z^9H(EI5DzlMNfB*vxvE)V=up4vo!Flzgcqe%QZ^_zxtac7r$JyH1Mmpo&61RS^siT zx#nygeb{8WSJyQ@Lni8-awD9xNytc%LK58!Ec%30=XSkVNvxb(`ZJ2#85hqzJ&`q` ziTKehdPJVYnv9j9V7_I7?vWt1zuA7*I(i=bV|!hd9NAoiZmo9j39^sNvb1Xq+bnm~ zjPy#q*Gw#-rTe$#z5lqf*TlmQ1&`I)NSmr}Q`R+Q>TBw88sA9~(&|e4iJgAf`};p< z@D})Y3ORTqDs|lBrG4XQk}fgERc`iKn8=ePjN~#Cbz2;KP2>L~`JE7aPVv`MhIS0c z^L^X?>q4a^o_zG^=|o+p7dMWYznS?{_CMp%Z(Cpv-V%PfM%)rDSi^YLGYfiE=)sC(9I4SQZ<`mjg|2a&9S&jVy$xT%1T+%D|#|C*x9Yg%DSf0fRAp=A->h} zC_5>9?#S~znu2TcYh!&34KBW-(};~@(&^C@iW^JiO|>ienol!n60f}yhi2MnIvmpR zFPnRvHqW42e1f47M$RI7?XP(uNYm|zHYoh=eNz;9s)Ra99gV1`k#?x5NBkxpE=`(J z^&RVWYBf5gC;A#Wd4_2>IZ{GTGd=c$HUGH$|IW(kC))j#d2FBHcmyDwUA%@naR8ZPg{R8mq>eBYT&!#_9$0 zI*skG#G3#P(JL*ij?<6oI$3nE#UWO=AxbqMRbgoS^p4eLZaV4|xIhjHU` zL9S-32t=)v-5|8qTDEZ;h4^r7swn?rRjVzBou1v(o0{ZsX7II-XFf9R-2XCoQ~Wh( zBnb^UB4k1dFZkga!L8Y4xud6cEyELlY@l64-d&M=XJy({gz|t z(+?k~fdRiWB(1*F=tPnZVfQ6DU6Ps)!9C3cM)QV8hwS%Q;g{J zvaD;_DPmEYJT-ks*j3u~Coo4HiFW26&$}6PO_An+uxLc*j&=k6cNTrjJV7z9u+G-n zh~&RS|Yd97C_0idFtJ#n!Qy*+VcjjU#>w=l^%iZL*r0uXSvZ;_gHs{e)Pl zqYr1)+}oIbfr3WHNNlyu-$6S{?d0{vwkGb7EMFeUwTX%L3^xIq36{0k=BFU zbBJH!EZI4X8vA!el5V0o|0@6PF6ZMo6a9x@y6}TTx50YWo0l)jK{*n%oJ}5X`nzBI z4*ykyCF93O>O1HlzA5{pu1DW}huBg3D7|~r@c*;-Hc)mQ)tP9Wb5FO9uG;F`Qd^d7 zNiKC7(-saiZin!IWtBP&7DSV@9kp?QiDW`Dgb;q_nTQDlS2t~^5iIC{Odzv{G>j7y z@t#HABR>zVm?khLYetF541pOE$Ij2>t(BKy#FNeNyga_|`*u~Gzk6@@z1?kFQnb5o z)!w`I-c_~tsXFJLTXjyN1{fc6SS{X%%+^#x<1zq6qyd{3VT~vHVbo{bNP|X%n2aKJ zzZxZt<0<1kj?XeRE*3~%(Nj-2Q&?&&WJkKS?nCZ&gzyPj8wg$#{ASG7tV4H z=NVxUlK6f;too7bg!5aP)-*B!%E7*eEvNwWSS>-uFe1(tQS=Q_n?V%iNnO~m>kqqa zzoip!X!>!=VhF1e*7C4CksCK(xeMK+4k0MJ79fGwtRjR->(-iBqSzLh{>lJlg<6V z#&N=!{CQNr_m;5;a}(tHliA}ElPJWbe{5g}*ygo+PdvV$CKm=jI6fMy;UraziTXga z`2^>#{^)}z5EHX--6n~Nt=+5DopVwDpV#IW5tI37^XEtB5R-1ZaRJD20`ComhU)(0 z9dfVVR83&~RA6wBjK045kz&F0bWJV@YPCTCN@fP14=Kty`!i0D^_4VzJ++62hOkF= zu&>YS7mZ)g_*!CeguaFEyNrpCQZ*(=j^r^>&6$~#O~&L@v#*c#XJ!y1iKUAPXw`I< zN->$3U`)^&U&{p@4Bz4P^~A&zPfSc)iV4RD56kXi0$ze% zo=)7?$7PlWImr(wd3<()d?&tTP9B&a{zQE$eF&y_5uDjC>gh!4+sXP^Pnt+Q+sLP! zD`)A&0Gocd+g`j`S^9M9oyyWTh>7It-O64?8}FQ7cFb5dIoaFyiF z3o|$w0OVZI-8ouppGC^E&x(~?DijY)G<%ClbEdh*nBbxTs+Zipx(D1i>B3jde4OA) ziX+7RtzLzb;6QUDty_(MvT|;mbRQFrlip(D=PUV!*+o6iTqNe7In%WK6R+ykK5lmL z_ErY55mYXw$Pct|k<<;6DBsT*^gX|&ydwYQ4syTh_(|A5d2gui!q0dAuf6u++KR%g zb_~zAfp%QgvY#=?-S71BeT`+>>qW~>F8)wOe(8Qag(~7ty8V;UGKh-<8e8O^(?)d0 zt>bbx(~I_6Ij+YMBp|C#8myZOwgMw(L14o$_Kzlsog`)Et#joi5*U&=K zn@$qM1JX|4xPv1cBFOn|C49ufxSujLsKVq4Drixx(=ouZ3j)kl|7N4w85~}`$gu=`TTGBkRZPA>0;bWKK zH;XlZF6j6%6RAls;Z4v9egZ%M48vgY2b>2oXo8Uxa$x5GfoY+J)wBVEr4)Ux6gCN1 z_?j56W5_r_n+TfA1ZQFe(~@40$tK)O><*mk@d6n95qu~Z1%k%NV2SfH2gm|Gku^v) zgd2@TVANt6VO~sV!I@yeJol==o|kZztrO4<@9as|(omD!ItQ3yjggZnr=fvm?gcJ@Su7!nyPi|5n5B)y>phK}@3Y-JQS_jYqX zYFmhOTlRU)toM9AF?1oI^)RGcoWFp?ZZRp3bu3Rs0+(mYxIwFNcj1+7BO$L0))wg8 z>j(}Fs^>8`_$>GSV`;(g`G+Q#t-npBL)6Lv4x@5#lPDFJ#s^$m*kZCoS7*X$vaF?P ziJe;jViT(@as&b^ig;cDHLpfnhY0up&X+Ei>_SSe{A91K)#xsvI!?BUKT~&>KzTew zuN|kH1{pEIT1Tb=!#=Ot@ob*Y1r}YFxC|i(5CtT~`jrAduqDrgO5F3CxJLKdK7)g_ z2spS2I+Bek{yD4D@1wP4DWqCt3tuN;JnvInX8` zYEmK<%M~#^jemgaXqG#4rFn0JC5OkPY#afZsLJF+^iqU8M%N z1B*;!;VVKD@05sZhKP1h!q3G5+ppZno+SDH#oTOmd7QI|Sx3UB0W6VOt|kK1@8PJB zsZMf)#~=h+Be=W+aGAPiS{sw7?Q;@z2|N`peAu}6Gg=(t!NJB44*JJ^-Hu{7%?$=J z3*elIEvWD~*|F6~BZU+*S)?6>;lWFURJN)Pt0Zki!-pg~xSW7=*nk9?3myi(zuqoP zW(Fcl)YFDI;Q)ONr+Gk#B6r}E5ervJjS*boTe~aY>@VaJbr2;r;c~})vJ7$v!O88& zmOZC_5u|%Ibne<1hqyrb$t{njH@=s7#QSc_DD_f&&GGW&Ulg$QUp@ofutl4ga&Vdf z%on*CZaWoZ5&_{pmPH8!hut)83v)JOK*HD0AbEl3JFZ)A2WFK!qD@-Yu*C@s|2b^O zYy*nhAL+jcTjEJm2>*Nl#60-!%LnPr(?~H)tO2t?`Guk!p68C;Y_efwUk ze%`*@=mg=hUEkZLPY74gm*W5*f1*-qo7K z#TLiFJlXhD$}Fi-jcei8466~fCsF3jYM7;r+C>A&HS6sPoNs9Z^vsh z2V%ygFPgWANEQ>!aS)5b+*Kn*J$u>V+Y-bi{*U+Uc_U&nJe*2Q`ZgmbYUb0?&+M}= zLrh-#13&*LV)EA7@I7`19(sg3E*A?ldfk7rhK?_-qBBrh&on))&Qbw8h8`{}a&OV# z%*ezD_R9^OuAPIVgQ>FIg-$&iF*)M*C3ITj+a@O1OIMA_jO=e5oH;geY~s|Z5EE?Q z;_tr~73_KcGvA%&ldg_Vdq&DJIdWtW>+B^aj~3eoZN%2agm~>7_U>WiD0SM$yeNGk z<3p#Ph1U1EI?kMFUsr2PxWfeFq!bhEXlzD)?t&c`6ES$P#pId;?ftY8*X>`dN^qYd zZZ}SPKF-q)$S1~qhmPZDeA(ayEabBNj)CUhJnnZCdqsVXJ#?T$IrB+x*V}eAT-a&y z`Zcsazh4FAH@kg~{9?j8z%l7D>}L#i!+uAs1)>iLq7OOlgM^&phkcNDfW}6}VbZh* zJ-1&He9*Fgk>!5BBg<)*@w`|-PLdnZnW?FP0nYd>Fe7{F3T()A181hDWII;HX5T4w zvWXB}J$Ut?G3w-?3vo9V|H;W5JGOtn>=~{0d_6JYzC~=XFPd~QQ4$k;VW~u{D0!jc zTeCT4y*=m@6Fjq{vLAH+{*~)$ev#!9&11*74Rz{R`FgGIl#2t$3B)eKnC!t1LmLBb z?kf9_me&;%43ep1?mJ{?Wick0yINur8)YGjJ#|PUoM@N>VuOSi7KYg~0i8~1o%o&F z(Er~$m2}IO6L#Kr_yU{=K5_47{IaL-c0TI=YtL8SXOxF_=ELC2Mjcm#k-YB_rLY$p z}#E5)_4DY zMtlDf3pShVeT|xQ?V#gl?`>4~FTIKde*dDp$B{m>!KcUx1^YUb8}jeh8kw@n;76nQI|jD(Ewlm}kbUvwGQ$ZLI4yytT5T z7Dc~y+w)Deym*7Rh*#wtU65!O=k`kL=i`CeeN;3aPB5Xu@D1Z!g^EVC_!*~%wsu`bo7NX~jRnPz z=3y@&h;_TN*-^b6iN(SnmRkPH>|zt(j)^?gG0HWAC(elypxK)pq2#w1HDn-A(}Rv2 zl2s2af=dIc1zBs-8ZPTi6>4c?JV@ooof8WDlFIJNL0c*;>s9TQMMuk|QU(luJoIx3 zDH^U-r1)Dft%ZKL-1)LUA*JylfX6F?3Yfepwsm)f_SGI0EiGxDggVzYcjb0A7Sly@ zjgJYHcd}Sm#uI-!Epu~f0jPDPmW($?med?QYr$E{!#@W>zQr+yhvd++_@P(YAm{iw zvw+d&j!Edk7{|#Ha)7Ht+0z_U$uTolTlYxEji5UmNy zcSvBuXt5K;IwnSv9mh;%7wUR0orAmO7S{Z6;ae<}!MSTnw zT&;M78@T*1c7;+V^1e#2NfhiFQeI_6yi%Hnyu}C5K)_Hg;B%iPoEBvuy3%T@g|WHH z25nJa8}|9aYW(yDwFFzG9l(XtCLG(k5f8Kf=@cilMMxNI1#Tc7aEwLDWITaDN}XYd z&XbF;l|x!BtEhk0k$y%&Io5P9%U5|TB{Wrn&<<#rQh_7#;x>in2dn%r3$#+(h|&>tK={^*U}n7FOq_x+oJ0yq zh6IMsb(s!g`Hs7C`T0W)VGY3aDr;m{RbIRF zSQbNT44@!BMT9U!z#KL(OeP6}k+hoFT%cNXp3}9Z4Qn8W2LSP~Na#`lbI|g+5Ox++ zf+E7S%GSgS-8Qi$E=)K$z>LxMkQD?*mM;P;olb04bY3GnZhJUaU6M7wWS2^YCLTy)PcCeZzeb!tjaIy_n1*yd2F{ooGa^ zj&CC>c7sbMJUhb&bMXaR*2N?o@d$u9!HQI3C94E21jp*?jWtNOi=D8~rzGMrwr&uw zIfwFqou0&_Yz$&^OEeu1kEq6BHC5Ag?(@dlXtDlb)Q2yNJkTMGf5bAul^M1&j>O5V zKTl{)ff!uNSOZWCFr$wz;eB**xIn{K9?Q}IuxE+e8&4c>Gj~NWfpTw>g6AE?FI#Vu z5{wgEDD-XNMKA8l-)-w(pB!s69{(WT1$f=`ZI6!}|H5m>ZvNIg5tAvqSo@D3{4m}T zc+1SJwTy|4l5q^Ity_MkuKEv4OzL(X*TPS{Q7td-?cWs5&(nd?W*Da{zdCmOu@h>? z9QbqOBPI~f0Sp0q<04`rClpJDj}Ea|!~5dCd*kD9 zT5R9-8MS;u#lNOpOyJxE5=#9$ef+U|b$>0IPb}IV^+ghs5Q?lje9IOHSq7dl1!==7 z3tU9h$Vl7HxVM`W){ve$Rg{~M<-~lWNw&An$!2=)9ci-mm5Q=oi)&I>UY~y{CVZdL zdSjBU{cRf)t`V15b{UhwLB<$wuWNyeaV>sJC!MRX4!&(kcD#qumT`g@$l7lg3yuUr zrsu{_YfM&NpMNPPe52xeV!|MFn!6mob?#a@Cb%BI0Y(#AuE2POKF`SA?^|z!4*30w zup?K)q;VHylDAWoT2@+o!%H$1?^VhKKK3EvDhh1(ouB&`-TNBlJ&!86!@q|SW^pS_ zK3lRn37 zt~6~NRf~asv-c6@P(0=JhOz97`xWDN!&56Sm1?z%JiID9GlAcOtzen!gEKFVdk zqr)$Xbp6Ln<-L5ncb_>^t7Y>LorKkOuXqK|8G~n6cw^kjnHgNZy7vQ$YnwB8mt8o= zWX>KMnm~<3JFCrMnd*gttUD&v_gC)T-E2Pma4{y$r&Yx3+2$F<K zl!tt+azP)tru{&}9_YN@z^~@jdP6ym$sY@N$UDh~@{s3pxLsB1v!h$(o*CZ+Uq4SD zr7P|Txl%%_=X-w0LwU#{C-ZkG4|ymLdDULvBR7?LNoVyIv;Dj7(lb07z&ouZd@gMMjI+A6bl57j%WXWE}hjrlJ;mBR*mWh?Xcxo94 zEd)BYzMxZva)YvEd`e)8)T+;>h%@QR?MjmsRFH}sNIYAW#|NHp2cB9E>HK_%^-q5F99$bN>|C?rGZG-NkbGAj#<*qY+2p zM==sDfM1e3g6UY|3s%rwO?Acc4t8^IIPD#OzoHfGOUu^ERMCKx7*0K%ATP@?Cp%JV zoAw4EWq^jVOv$yuqKF@Nf5!->cuXZ0i3e)~;_}P}N$Yr7PL}6E&KCJRdQITCTqNhb z3935zP=m=hED2oerC?9=vC=?t=nK~WE-#zODfIy_3kh+BrECBz$ShKaK?aC5DuE*m z(BM5t6aaU;r~@Gg^Ve7YIZ6Q|G!&K-7sgG|kj-a$sYw(HNkL7xT2dn^6TFf@%<+Dw z0mT{J&Fb3AB^O@LcV>OrTz@7B2~$1IqCK?74Dwv z+No|RuiDQdU1<$RjbFAJ$?CkKY?~fskt{a2$jtOxrlwGH$cq*_<3-y+DyzdYsx;X- z&tZuLPpZyKC?}Bq_keYo2OA-$Vd9CxL%8wnmY{Jw$SAUzA7`b2hpv?(JRd4pa3v*5 zLq_wqk;brcd#PO=VNe?w!Xilz`G^f1x8Bkg#ve+2T)+j0LkhVtD~W9_2dmUl(V$#z zQHVAP_2vTK1_XI%N?=`nxU~*f+EvmThY1-6o=|xb-R*G^$oU=%Lq1rtSucfSDOPs}V5-Ja zHA+Ubmni{Vml1<+-WG%d*2J$O30A05!~r!~G9Hd?-Dhy-xAdz8U+RN2WH2lY{)YFt zGtV?ivq1nX61tLvj#Svaldc^_y(*_l7i9xZnT~S14+gPyD?uk{6QqJ|>r>M|}XXmcv#rvQkgfXiK~mG)d_MLcKQ9Q9bR)KbuqVLO(D0%z07 zF?G+t38lT~zKt}cluIQ`13`Y)eQ_1uO2*$hh!=Y(Wf%y!PSz;&KSMxB3TOt>FzdFe z*qmL!Ae6Wrkf=mcu}`#9|9}r#sen5Xf|*s*B7j3$3VC>NOOfp$>@8q50U>dj;FSa= z{MTeVrDFTGUXzJCL6F)Xn!bumARyGwguxWLjWA?bW9l1M+V&G{(NcmFhrG{JY@~dV zoY>4|Jca_=^xbfHix7)ljfv|=hj_TkXir;j1gwC14l-XOvSF&Yk0|FdB`oPM=88h- zu}W}W74z_)R1yS+uLu}&S5x9+*2#y^heN-ooo#gDv z-ywj5)p@PAabkKJCx(@l;5i#7oHwP%I<%*)qu~?o#79;fC&fuOs0a71I!0*^ zdky>ygHOW%lsRbdj2x3-xdrJ2DJEHgg4{tCb|D9Q#tdin4$|JiHujtxgjcC|ML8Tn zA1kzRMcJxcL%sRU-PDa6ja{{Iy>eLyaqhtE43~|`;f1aD{t_aS5CjLh`&VOFzY0ht zZAqLhTzL3P6(`tM*pHottC!|GL70oAoN{tu6QuKXohjx`0oO#%5<#e#gDK~zBpH^v zWpeZvi$ysn##H(YiT3u;JDgIWnT}?@!MJPFX`Tlu>g7nZ1BQgPr5MNj2Fd=nX&>(H zz#gk{{czT7i$%5?O{Ya)mO!X&)m}h*2L|~TlQ=&WeL=Y_;K27hFVo1X8S^aqpcTMm z>(b4s_!_s?Atz^!s;uh-d_#jg&Y)(iLhPNpQc8AGE_63*O|Br`fv}gOUORgO9~u}K zNCvJSz0Qz5CH(0wm2%?1pbi`Qt3U{7>Vpdi_1`-sc z>A(;AKC^;$eMTqI=R|qmNYC2#8Maaw9dq_z9WT93T7Bs34XEpb57CjLy)d^PJap*L zz@dYOb`8Auy_j43z6yGHVCqnH{y%iU98yz<%+BP!Pstp7$V??_*|f-kKOi>Vz_~g( zXbycfNe)d_<#5V5glXCgCwH=5oN*4B4(G8$DeWb1I!t?0hPDo6?Zde33w<$%%psh{ zVDr81Jb})&vw7&?!9xR6Q-^l@KA(YHyFR0d=<`A2eKP#D8_70g{iTE1bhfKj<;jk&7ZH605e_Q^XT)=M7cD zmR%}F#9o0WbE}miCc$2iU>+=ILRF+=pMx$HoW+f@=h~FF*W1UM?}q?i!{_fG`r5;f zD)rDq-}s$I0dVjhlh{Z}_TCern8=!J`Vy)qmD@tUA=!*q085p6j*9L~q10OlVWoNZ3 z2z*B|Ju0a4p}Y@;v<-5|b&*yE6an9|B%PP`ECVMvuEPsy97;mD@r8jd$co+G<*jdz zv%I=}HF!HJElLM`*>h10Fom>AxpL!c7Qt1Lu>90r_s%7A_+8B3s*xM=rlfB@B~P~p zKB@Q?^GRT_FL9Z18JKcgp;juqkcg}PLszXeT}kySloS;hsH&Tb$ahqd5*tm#9{{Qrr`n zw=Jk~U}*WoT&GB<<5QJ0U=#A=&C$@MMn^EElE@awR#Sz-R;P;wU4YSZM@WA$mBODGQ!EScufEc-W(Lf@JO=RYj1>fMmf%luVJ&a!o9lkIn zv8o2I%;8zkV#C{nI<&?87>bP&hhqG z7XS9eU2_d3_x#&7@||laI)I8LnvaB#&IXevAR^~a;@g(ceT~C)8$5WA4-VH3s>vK0?kz$%YZ8 zRZ0s&slA9Db9hXEnbYZW43}DFT(_Npfo2KtL_MVo9DkG;Vd2-tF!L3Dd2nU<+$N$S z>3lp=V&&3S8|~zaydoa7RsVN0bghV+WmRg_QJdSaCdYHkc}%`(I7j<1%Aus)Ai%Q= zp}g#sD8|y@c@5m+quq}#z^Z_LT3fT$B12h>@rm5(SZJ~Y>Sft7|`4Y&}Z^!~zK{S7vaA4Sb{8$ici+d(m zhz0f>i+H%~CB{BSIA6ew1qye;B1`3f0&@wtHAn!~%MjO02(7){fJ=-wSztLd zNEZvxY7f3t2fBTp+sLu@l2xuHWANz$JJcnTeWWq50Lz{R`vb`r9Le#iQO-fPA`t*5nv8t4U0-Iu?Cre zRJ5S1D_f8*N}?j|cs{l22SjQfEs5iPYO15L+J;;!HW*nlB6S1La^eIn=|&~)(#2VG ztqqo=fRyv(H_J4r4w5Z$6~>tBbCIhZVT-&XJ_m2uP@Q?drr=1r7uP}>Z^ObDddyn~ z)EvglocbuP#&jGn7xe|tjt3aBq0}0S>t)NG+6KHn)n^Ax-*S=+;a!61fktB(`~>sd zJhYNb%OTV#0UJ_ctc%DR3@b%EGkV33XXsiHe~vfF=Dl%l!{#0`S=G`6jKh!PE#LwgTqR{^T;EA?T(J(5;;c(&AT*Kcx2e+9X(SPzhX>X)#sIbk z8Rtu!uMJ88HI2lm>+t@RC1@Ai37p_V?Fg?9f}$l@CWY2zEiIL{%9o3u1uCBGxsnb? z)FP&+vDV|Q#U-~YqwpW!>V2ZIm?d z3DENmYU3N$B5vj>Lc6Ht@tk zrnF0FX&}f9Y=%8I$Q7G6s@_i@Kdx|*#LF)S4{Qh6odXJ9#ZohZ;Z#{r<@~cnT-}|XAeg7TbeC#p$@b3A4 z{5xyyyuEwy#<-4gvhSn)$M0K?hyF~}=3pNcV4UE#rNjhZWf+q*y=NgF=J!vvcsb@S z%W)DtW;tg?%IDD%Xa!nXH1K?i$&N3S9M%;fL1~H1e?5M@v2D!k2qw_WdEm9ym@GWj zu+IQY9z9A+o8n)X!goe|#oKbDVoYA} zv3~XVa$Nh>$j4;!i4&}b$N5=m;K{~K<{32cK-};?f@;n;6=_t#}T`~8O2v-Kn`&8%~QvylN-UD*Oxv2Sz^Lx87p<>OeS+FCYdW% zManU0o;gEbHk&Rc4?mp6q*;wg{_JAbk;lY6vl~xf7du(~mtvB+VpSxINwYc8j^n zI%s=J4gY~o)Q%}Ubqe`5p9i{>LmcP7M&;aCrLz`4OGx9_HmV}{LcSE__HZXrpxj6J zj=T9@b%(s?Bz~2ePNyNp_n%PyRSk{PHMZq7^j@F8_)518RD3RS)Q2y{K77vKFL@V5 zV)9P4@a_b@Zr}?G^7u~m*e+}yy7o@B*pfr-T3mzVdpc>Tg%;+sm|T5sqbkGuOkP*E zmG#xf#+CBDC)dNLe2>Xkl6?FQWgB?$$uRklfUlKxlDIkp{Ipt>-xDCWGssat`0kxP z7XF=PRFP|d=1H7ZRP!Vm7Z&W=-+Oz{Jkm}_&b(jR^_O{B{YZ}I*wE>dn2QGS_6Fp* z-Wmk(e100&Up&WCa^`gt3*j6uEScxeMxl=GHpL1lLB`9wsrtRZ=k~yk~JnOKGG2sTdYD}u* z#9b3p$IKewM0JR#& z39*&O$%Pw}^7)rNT^-uTWM<||Us5Nx|EFBPb4+k~+QjUGfaLE=bTJtmeBJAomn$*x z<0Ov>^q^agN!_4kTpr-$#hWHA;L95!hn&bGwL~`%thW{NB~MqgP+sA`n&;G>!1qao zyj3||T87+7)ThN$ch_$-^w@0uwn^r9J3IYJiyq>a!Tq^cdfe`yLi%7w|k5~e~o;@|S}1syLNvQQFoXFsQcT*zI?RG}5% zICljRp#v+l$>}L&bEy?DV}pELma35D!e^GMICpK8#p<%ZSexd?YdK#AkA@t#l~uq) zoqYcZ_ysn9H(4WuBg3heDctHWSnc-LzlPsAl&NBhs@l!U3J7O1)@ODd74GUf)L1*L zXkQB18V7kz?Rf5Nk;@e4o5Z41h10w77OUBY9M4swLOaW?_Io*G?2dmcwz}16t*vd- zDop&;R8<6BW+l#-!J{Fkr6LZ}OPVMTSy)vdu^`*I%wSV6gcFI1h(a6&8)}ZZ zYl2{vBreg6j4p9(iF)pds~%fR8>}dO6ekgDtwIXd%qa{215d+uQcNs|6k{N^7Bhx5 zbLs;|9HrH#Ew;}I?j5DQidHdx7D+7vq!EdIYA8{|K_jf0kONHjr7gmnW2v}?q{1uPYAg7n*EN0Wb zG-_;Gp5q#mMk85Ln?l{=)3Fc$B=@+gkZNIsWYi%k+C@OBk>xWO2oFg>Y(U!O+A)1rlxV{$7War>^|w7L z1aV9mp?7eT>NCc@zhg75tcm`@l^(9l| zm~>|9CK08q%0j1g9G=u^kVM z%Atto+!98&tO5q*{FGr(em5=ix~Hrg0!rDstuM##u&ysQ>l;jIgD!%R;{0tf!S&D0 zsbmhj7SlOpu^mo46|32XR@Us3x-GUbT8pVJj!nujliKk)Sc;YTjIUyof=LHH9NJwW zfR~kc0hjqBs0&Y()H1>V<7ag+tBb5Can;|iSlp&C#i52+pyzNbP6iM$_(T?;Z0LZ| z0+x}PvkOQ*lP2PHBrx?Eo{%)maQmVD{J_XTL~jhtDK&r*Fp@xTAb|k>BP5!UH~1XI z2aC1uc@6V+Fh&&xbr|&5+{EL(OlgCbc)4(1!IekW(455U81~mH+3pTjvcN8SA4qqF zgg4+$%jKWA1fEjSD~F@L12*Yb(T={pNGH4@V!3N^3JZJTy?NZppH$Oxs-`hk8hAEp z9L2zFYQ*3?1{96XLs%g4x%K&~nM4UStt$AO2yFQmy;gg8TSHCafX1Sb#=!(LLL3|8 z){fM-`Odbp*?(|nzuFcz;#VDpgAd@4x0_7;)i^OE2&+;reE%X+{PUp(IN6NHX=5lp zxGkxD_DXy=*)|X-+{v}Au?dxnV5lti(^9)yt2~C!swrLNpHFoED|>Fug6wckZ{S&S z?<5xj`IjhT*$D#G35>=IQuXkg(ks=Xj>d0Pi0K$~A&=n$|Bk6hkK0rkrHsCI6oFG_ zZ$qa8I08=WOeRQU$7w7#ye3(Z#iwV$X-(;#wVq9dJ>TfHwnpRd2|8p!4Nt2+YWH)V zvSVW@kMEA=8n1!-6B{iVoF$Apa2+2R1ii={MFy}qiEo;3@QeZIPc-smsDBQGRoh-= z%_#0=&c;^ZyNCo4LyeLd7>=G;DdcSc1r7`|&E!0V^p3SOtj=ew>oIrwaK}356<%Al z-8*4WruRm=KkbiqA~f+%6DJy9;IGn?2q>bVbsM7Zs#d( z0>|8fqHUTSpoWbhO^~gpnZq5gLu$cC7(=r=NImE5%YSGMP1vS}(Gh7Y(RJF7kjO+0D^(XfjuA#Rb( z;z>n75nk;q(%S)W;!*s?9l6dYC#hGl8Pu~D*-AjMC^{kgVhjZ>lk*RfclX++x5j$> zM~C?^i19bqHGF~nzHp=&xN11=!vkm9*|T8ojsA3pil=MQr%YYjp}V82ehF_XosHrX zD22PQIA}<{Al_F~8aGsi`VZrwC_lMxBtaN<-IC~8^?`KDEtuJc6O5j^IuP;R8Nn)U z3PKYA#W)J1lvq-cUC{ZEBj^uIK+i!>NoQmhw*ayEI?`?djPaRb1jr&G6 zzd+`f^yK6gRPgmUt@X31HD08R_z+mvK7@l!u+}06=Gm^Wkj|qZite3VxbJc`O*zo# zBW%Zcvp0C^)EB>h?uLe>mQvZ&Qt1Z`!k? z|BAuRG5Md5KK&cF+%)q)-t+Xgf8)jX|IY6p+5hCPy!#LT%Ri4#oS2)vXI}mCUwr$D zy)Xapi)shQ^&4;c;laCxUVr&dzTgF??%ML2-M2jTg8%*bAK7#DEw!J(cmL##sy_Kj z#)NH8Z0usPYDdnVT~*|~5V+X`?<=n_9`%;Gn(hBu*Mw`#Zb9 z6xUA^6CazvYHZ?aW>Ad`srukVP0fs8*J58EPcb7SGgyXNug}a}eRbF~_b!pAPH%9b z#N@IAz4a^Xt3^1fF*#l1{?CrU)$=naQG8c(7H4yYVx-wbOwOwBP-$kcdF*r(F*(;n zOq$KUzLQuzKZ3Y%KLlfPIB~|uFY=h|<~2)CFxZ?p!+j#U`Emqi0f)SUBc~r;IVRUc zPtTmJjW_RVzOVTm80f<`#^ysmd-k0A94*YuFeXPNCKD4!j+{DmvU%jlv15n{_Cx$r zipiFDdY5*cO)JLat|M-o(h*>uQgNJTJ+x8nI=ix2tib{z&N>^JRqzDc1bL;LEYEai{pK#_yoZ z3HZ!;8C=L|E8EW~zQrP@urD!XX)Cz>j_)@1b*vNR9pqXypIuJ;$Gz6~ZtUTt4)zh^ zyG8eaM{v;(rk13U#>!Zq<2H-LL~>f=UQzn&4tHB+*ykv*hzTLfB?g69xZ+jP35?X6 zZ^jkGc?*p{@3m>K_(4qj&G^T#AMs?0(*pZQz#}!Vd#d(uulB0)cv8g7{{2I|rP&#p z1DLjT?p1}cnBVuy0 zxqtuZ{2l6T8i-R2VzPffi+YU-ccPx(<7Bw)z4bP3$XI&@rxq}^#Q*%3&pZG`jgL3q z#c_f`vSH(7U|{8OGBZ;eCy!>0>k2vF$H_G-&k=3<=*Nk=1;Cq!n7hWCgQrdnZs0f> z80cx7^ca&iomv|Ur#(Wa%ePK^r`0*#^v^n%ty-d;#Hw{`xzFC&ob6oHQ^|Bs(p?Kj zojRz!iI7(TBlvb=cqy?CcL%PY09)0t)^omI=OT;B|;SE-;{o{xg|idf8DELhS4=>{r(tf;V5)@xZ7IEq;JP#!yl(NRFV zx0XpJCPOy{DYlb%;n_}WtbiRf1zpnRPKQ#1yM6(O2zJeJRCo?lunYztukQy8)>wLD zcvVf=EOZGXXaub!#lB+Iled@)wJ`Fc4a3?td1dQExYMv!2+q@RC2z7y7j?y&&`uJI zDBxAR=L7(b<@!>D-$RB3#`%@+eDT`bqoIlqGlK2dRVxePaWKbP zEm0I#yBdn_%ptUx;l2lsn>1chDV~o*gWTj|^GZ0gb*#r*x|Ch=z$Fh{^1vkzT=Kvr z4_xxVB@bNkz$Fh{^1vkzT=Kvr4_xxVB@bNkz{Tr<*tovcnd2w@m^p6q%Uv_v!gM)* zm##t!Yl#xEK|+WPk|M;mNCBVsbd?{(I`IG5M=4;Kv_M?phc>#pVNTX4QMM>b`#{v~;BxRufN|4{iE=x6NuNAI51zs(9 zyHai{d{Zo+)s8}6rB9*HA)nPwU{)VBl)PUbWoGd)_z;YwKAF{m7^Kq2Sq%&TeaWG3 zfcW>FNKP7dnf3&_B)#mZ%=4gETJ^^J)%mYJ5H2dxR<=mZ$2l=z8vnQ;3S>~#l!C^t z9m?WQ@rfEaw3Q9TCLkU2xKu)U*3r%=c@`gnl~g5D$XD`7!mg%%Wl-w^A!nsEjg1@w z#*a_rZJ^xpqJSqdm9Eht%Cw-b&gm>jFAe-dUBgL7PPpIP>C1$_&dL zSL8g^*=SbM^S&pqX)_BeBCXS2D~ASJxvde8HCwVglny8Gy7Lj0OPYPZ0*)bjU0_?ZbB?Retn9a3T*Vo#6+OU| zIl!4(t*e#t+?zB(*z2;$W#JK{CBOKha7bii6){x?=&B)E?_pcmZ8RNg_gZOEOIAP*!_#yQi7 z8Xim>$!dvNywn5+8@Tp)HA_;HQr$_3Xf+A0cWFfFc*HJXjL8OqZD*@mbvv0=dAqKKh*?#v zEMSF9;6G8t7}4N3kMfzbVFa+)fF_5anM6$5frSN&0u5{Y01N^HuuKqqh{Fa$iq2hv~c1YuvYkn-N&fG zO9nuLm%6@bP_fmJlrOfR2<}h^0^dqHtLSq$P)*wT*jQ!o9tgvSwSZ^1sJK2yS;hmI zN-&V{lt`j0g3d}4!Caa#J0a}ZN?=+G+pt=NR^V*fi^A1ARI=b=Vv23WI{2Da8%u6<`42V+}CMd4ci7x{Snd0Nv3LXuAkXGh)bkuL_MSdae2HM z7YPw!AAQD>!%M^xxG`B`wI^(mT_TDF>&CCRsaF#^SHLJv)l@@`Of@#E_zxCF@$CqY z`;QwIyRD2xoDeI#QO+O#>3z6Fbw9(S5#k4V)6TfF5WdE;YX9Cpn7#A2n`&M-l72$ni1{HDcUP7p%=%q!DUqtloUQif}49 z2qUPTp;jP9pHQ+7YyRFSK=jgjWmVfxrS7dz@plQAjIi7&mKvP%Was9 zQrv4nDBD@|JjiMOz=Xmhs{CO$t$n67O7-KfS3S}nDs)KlbEjnvt?ZIqQ%)9`t!@UIR4|k zLFa)aMuaqmR*boA#eq^R+z21)(1vFw@B4XnXpP_w>m`j}D`$uDiy6@H(YUgSnwwXX zAi%+sXmPqWAXWj5^2~8oY0`k_scndqA&ML|W9;yKTsi`$W1uO{+TF})Aq!;qx zxN;;jD4&FT0T)Yi@F z>xX_iY1GrhV@Y2F3R7@U;zHSKb2L@`2^zAb)8QR@@urQ4Dh9Jp-!sM@?krN6C5UZ`G^?D~kV z;|)cfgJKh$c!syC(c|hwlr}Dp^my!IV%dbAJAP-JKHfj34*Qtka-%)K3GDV-z|}Lmm)w}D9d-4*di}&uinlxJ@!~i^Ol&6G4RUyM{P=BSir<(x6gtM#mv>{bBD3=c z>!X-olPwkg>SSMk(vMre@u|Ps^WcjHPd&IPiMOg`uok`Lmv+TBzv%kYUpV~X%Wi%A zJO9t&@#C9s8%sWN_ziEn{f7fvq2S$)T6M{I<8>aoLUE8`!*~KmF28FL`k5kq55%$PHWfs2z9@UI(b1 z<8zSlv{w&}K;zyp-%*V+)S zrrGAp@!aS4yyxwx9`z`7FKcZJXBiVd>Dj^Avy92$*+8Fv`IhggC)XMi7lr1%AN$x{ zc;5IR&L)6~SH2Q1dvaoE>P|lG`iXP9cdIiK6Z`k~^$iZ5I=y@M;9&b_2iMM>J4fG- z?;qcf2;foch{=(@QwlyE8mgVcQ@-&O_Os_6QGIv!I(_os2+6{?A?4JdBt;S!{Frp0(qik@*15a4{KtVu>-C={pPhh8u1^ zcITaEn|-w=JcvQG-_2ckJHYAo?^NLIGBGiAZ2x{gcbz+Y_{b5?U3fVG=Prb7_wIqg znmToobC*&F5R>mUKl#ZYUwQ6wUr3Sz?ry*&dV&+Ed{6P0MIG+Hwd?Y;!rT0!byUN? zsVTK{r%u!kbXD#=q3_Ibmku|iaL)@bm6iK9uhuWV^58(@$5yD%`^rl=edYC&T;IK0 zCe-J1UIVp-J8-`r1;Y*Zev~-S;Dzggkhj%uW!j$ZqPOa=#!2$G@2n=;QZ9YvdrAz{#0lnE~SG*$AADqFt3#SG(zyvjZQRdA3 zgZsPc!$!q~*MyAAGZ&NO7u$QL8*cNjD0MiCiM!r>_>t4jM>q?VVuJGlPA%fcm8_pT zH+=*#VH77OaK%=L2~JIe(0|I?Xh`1dJ|?WT<9EE3+Egq%);!i6KRb?bf@ZD=?|8?G z#T^TWf4*Z;$AU0U-s60;G_fB(#8?>_p-OGYjT5EL;+sfuoZ$MWi*cd`Wt_lb>p0;{ z99adEBY4FJt|`?1!SN;1s{zIdVcjv|IN9IakGhYnQsr9bF7@J746ji9S7;Z<$;f^; zcez;AaIs5%6W5=mn1IpEIH}cSoM57A9VdK=BVv7y_Hk~P`kOu`bpsZDx{?z%JYP2r zp*)5CzNVp4uDAC~0t#ANQqZUyd|5;vxf;&+oHWXpAc1nE^wkcQwt_29w$}~pN6Gf8M9_ET z^fe@4$8+w(hcSGCtckL<|*6-8(dBYssd?Ip72c*M3B zYr{1yJd0I)Elgp=i%R>FQd@a+;L|$vy>Q#C3+d!rZ8e`6rtidt8qdN)t6wjeZg&J1 ziX9r|aWHvd$@5@$8W3Ihmqsm<0NDz+z-Z04bT~FzCD*{wUMJ*hFhLcDvI5>4k@iP$ z`v5RrrI?lJs$GrZ4v@(T9>(WFEb-jUNRPjlqQCmyYr)t9sq7wPZZ%Iq@_ZNdI)79 z&l(Yqfb5WW+XM|)m;pj;T^=YYvXT}$BXs9PK&tgrlUE8Ww)glt`5!8-TAh#Bl=|W%QDYmyk3X zSYv`DHjNk+VL8UfMa7~F&^U_3KnKv!E-xI9F}Q4xm;yonlNJ#mSo>)bw3V$Av&<_H z%!v%kGK2)J6~X;H4~}%9SkeP7x>vru2aU3*Z&a+w*6e_54cF|j{e9#ED5uq4af~oR z0++CxRviV$Kn9W;_x0U^V&lYcaAS=shf!Dt(yt;z?^p^DA!tb}Nntbuxr#(9*|nez zQAw=pV{R)1Gw1Y#?f(6q#LL2N84|-`=d|;A@O)%lfP#XoB(_-1%@MT_xZbgH_-af> zIp1O8pkPQdD)uv&uj*JBiTx7>dUX|wGu=tSEK;-#qCjFjhkYsult{=wD-)6|2Ns!e zC{i1+id0}rNaVOI3P^34$l8#dzq~d*YN39tn73&>iS@b|C1@Lu*S}dB%a244$+2o77edBXrBAB;{s>rY65J_bI~z!J-=M`d!kTw_&gPMKTOo zhyqGcqjf;u2uF97CK6zXYJB{x4GbnFHb5QtIs(~ie)YfWRij1TwI`8z#Ger02Y_?N z5X&0}8lVA^K$c)6M+ahi++wxflC^Yk+K01Fq72r9^Be;e=Rog9S}-oUg=GX*4AUwU zGg#1dt|`Y(j5x;LRE&5q1 zkzA>`u0Df~p{I%+M*^7RIo{&f_g$UCIbP#$DP4l7h-gRvtd|gi4A@e&ohnfy5qO&A zqN#C?M_JvX94pGGy)&MRkJ3Z{IWQaNu8 zBU0sCSL$~OM2-r64b&R)!L|RkJmL<9C57E_SmT?u_|x*;I6-5qYf!os`DRbYYCiB; z3Ng*CKuR0>KTHl_c#x|~4Z>je54`(F(8nc?g=qTOQB0bBFp=N`aH+F_A=jv3xPBR} zgu7V8xQU1a5X02?p=VG4$a)}@b+R}RyjkJqiG>x7kHxw}aJ93Y;$$gTJ)qYLSFio| zX)HQWYOlrF`=DAtXlK!P9)zx=kEsECm0&-!E?Fp`i_Y;VV@zSf@RmqwM)C=o9YilB zjjzJDizFUL*!M-Y4-t&i<^_~4K`~bSi;x`EPJ>!SI0|AJ^{Mz)gcDbTGDa|vV;+eX zpE6Li2SCHHA*~06E=4!JtV_W*V*T(pHm;dQzlrM_0$8My!Q^E-W5WXp2Re?XovOZ5 z)BilC=OCAfZsUbLym3QSrgD?e`%bkZ;hxjq4;B;!AhFg0c+; z>b$Oo+aQfZ8LI|fEoC+vj+t!GDdj7c;>RNo2eXOa?FkVIEH^W3Y-zscC#$N3+0`X` zmFUA-+BHIBTt!gbxf3HrO=o>=U^D3$CYW)W#TM-y^23O#H>PI?=G1oRl()`_Q#n!? zV~H~rbC|_Oy2zqjrBgb2NfHew%G$n0WA05jT_|kD%ViyABtsKIkvS;g1e>z>a8?Bv zd|kIq?9K17ileyOo|-8qwk2MXPnHwsIfln5qZ4 zPPxTx0B)wV@V|z}ag1vD=2KOOB|H%88rmE|UF)tOh-K<)1jIr7F;~B*WFc9|4n4LR zCs$W2<3UZg^aEZN2)QRK8Kyvg0W=*i?~FgIu>>N){nM;2%G-*Pkd4TW8ZOAJr<`Ol zw8qc|tcPd^C36*l$l3}=SLh8QlaY-ulwOXnc>yrD@PG$sU;rzrBwF2Cc4J=D34;x@ zSEbh{N*`6D#zbFMc2<48&mHy!*R~7lm{M1L+TQaw`=Z9y-%v2OXa;cK!#rlMVan;T#Pc#UioyC*O$wGrrs;W4G$DgGO(8 z{q^S7y8Y{06N9fk>Go0OD~7%m1uI!Juj*(5nA7Q4ayZ^=ZwG%0ZA!>au1aL`&>n>R0c{r9Q9{3WUjl3bA##Z@$-T#f`6|bJ2|MI|R zqsE@S*EQ@5p+%pFU!pL#SW87bx$yWqhR4+MuYY&pfxo|N%Zoq!v^{v$+tR&#yT-Qm ze<~fCwGfnXBJ!|;=aC3_I>cCc8VXYElcUk`8{@I*+lsu6!T0>dTJ2mmdTqVl*ROu# zZQpzPXZL^V_Yef@55yzbjCV!ghy3BE-}mibHn;D7;V-`M>9@W2=Z-x3-`?=# z=RV#%_6xUt>V=IT+`b={d`y%T9V=OMx2iAiz})rg-#z}oci#6Szw_az7hZGI+tqa+ z+%@)L?6zyxLwSf0M_<-7xY(4z1_SEl8uDx~J_zfqtYV5w^rYHX4np@uep8pgN zBqz}MB-H!EaeNbw(V-tmW1ZA-v0Q;a`QA@G`T94%3swP9X_GN_7mj$%w%L{~*iAHz=O8^1A8($6 zXD5aRlG+UX`m#CR`zXtm(Q8b;LMp2lVis+W&s%-#2(_AN8tX~KHB8E?ukeCKZU)(C$pHy z-s*xz89jYk<}U11J$4Lp*O}9Rvc&mDUH$E~wrKD-ICtT?>evj9;r&@ml#-ZW3B8-C zd`t!z6RfORp;+|p77(lqT) zEoqvjX&M@m+ulpL`4Knd@%Bu3I~_(h@nO(NzofdVKz9zSu6uzWY0%sCbR$zK#|=(@vGjgbJ&!th)V*_d z^*oSu-;8i9G`MCHdaSR?j1Nfs$)2zHlXM+Pny!wCEXe9log)e90@NV z6IYj{>`6H4N}ewYkqgJ7P3UA@nXb3V9W*)grhK3To#>EP7xcI1P zU3zG#IQH#-_3okPo@=aSr1^lyKl;%HKY9wD*J_kWW3E{93(olsa5AaklLVxJD(XDA z@WSGbcWwLm&++YpSSB^-$8X*YnLJO8y~UvLEWX81Ykx(}v7g{;6Hh6~ll??-se!zX z47OplxkD|uEIG1-)rR*TVFGBn>?dj{n{{*TE2`(y8|oG>{dL3Hu54P19MfjGLQLhYN9Wu-bp_Ii}%cBK3t#KL2^|^H0_G;R`90 z$-a8o*Zks=OVT+ynJBKI7Lv=7O%BW(aH+5c~TYCIEhd#m^`;4(s4xLOZ$% zmu@}MBmI^imSBF&-l7};KYT=QF|fH$67Ovi-wFwRBgDImIP5=3)f)KaU2$5wHgcKj zz|fk|GzsHk!j>{6_cK1Cxm*=qF+Ap-Hw%31uiL`Q82?OcYuHlONBV`YltltY*et%( za?Cl6DkWs7t^?DcS4ulv;4GM??rL?|1`02&U7SYx64j*k^cvJDmr1$doK3t@cxB>j zu}ur639(FY6D>V;ddCr(ejNvo0~~?CM}>J5!U%=qKQRO=CXFBmcm1qr9Suh#`82lf zW_utcwj&2Z6YG3*@>hRH3U?9)hbP{K&4N%Ye6JnrYzT!DRVqRpZ)pqXHUDavuC;Um zD;CP5tPb3fR=GS2s07={$Rth)id5ZCyl-hXgX6Px(iL)Ij3ctnYM2K%UL+DlJeNEZ z5Tv2YfgF=bJWJZC9@((sH+eo`l;lmzSH&S9JVp+TWU4A=$|kjTK|wAe6u zQPm0-2vM+sFT~G5y_F;g*tYJ*(SR5v$*w;5Si@GZt*8{nAlS%Xf^_*3N1z$d0g&{q z_~CS?>wHiIHX#`v9>!W8qz1u8TzC&GZ`+~BX%J$2u`Z^T92UYpMmp|$E>Ke*wMYY= zM`!E^)3wTs+Q!_j8&oN01DSFm8&?x25rjy_0psz<`hl%Jop2dT3k~AXph2I1I*Hl9 zC77k{xUn>dtaGxwbo%}%)~SB3SLsMSsP0sKJijBgiA(S3DJ0SxKJdYVK^#eEN3hQb zFAsJ*a&#}>pvo1in1SXiPOTA~Fau}_ac6k3!A=3<`35Y!U|blN?DGOWuLxvo69n|x zI*KkMoOceGBlt-w8cM7P#qkbU7kEC-Mgy!;57Ay8Y)q2aYW)`B((*AEr(kz@{ zwjQ4)mD0kF=a0o?Z)~;5cpDXzSSS?TgSwSjzXhNeC=Kl*ZTu*#;`EWMznYU~L=7Dz zm{23qHi8dbitGZzJj6#3S;uI!7Xrgb^T16Hp*Nu{0z)aG<;e~!sm%~!@n%cXwCzo? zn~T^K)Z$rFR>}xAXbD>eQ9(Ge*OFb_z^%lY!pSe$a!IG4fdW-8SRbPikxovT+!dKM z-ILF#S!FM9;XXCMEZlK@?!+i$)mF@$yt>gqPd>*tfDE+;MgycO9{l{#6GUDY?m^oc zlNd}{v2!Ua&KHld1oTVEYZUgVcK${xz6BbZnn187$aPcu!k+jWnnkIten4 zTI6<2Mf}x;hfoPy#%TXcl69~QWlOLHhCivEhNA&CkL93S)1oKqRC9;!kg*Ly9inde zqC!3TfYlXSiS#sFQ3cPluqTXmxuE%>cYsrNAEfaEJB|Sp-#-fx%|{hH(8i431D91c z#2Cmybu~>HZAhp%cEOqt5oix^$fRZk7vm z5EDlDFbs!FPzP(1)A(t`$FBjCYKk7*Z|U_T1FgWwqM8}hVZUWS!jxH#>tIsF!kqT~ zXR2-hm=#m`>v`wI_W3(a`b1){09w{W2rf#e;AS%N{TVklFZ29>PHS##hVsO|* zlSk}9K7ZPP5T~=UI1xXiF2jO$5)Wxmmz+2S1YAPI4cH2u-fm{#$eyG|=np2GOedUV z`O$<#$_zeuunFm4XX@rb+=V-Xl-rE5dCY(QX^_j2!m8Ao{Seb~mE;g(BF@t>bX=u+ zI#tgH==D<7?=wQMN=yl|bb7(s_8{o>hgCSeMU948uu*s69f-Bz<47AxIEZW!4xEaJ zOc0KYql28MM((-BZKB!zSUp1y%~B{%eG12IxUP_2W2 zbh?hbB879v(?v-_e zb}zUmq1;dTltv#waKNSzs849d5teJm9VWtbWedjBnhtd-+A&D~-_aPfxVBrQ; zHv%Ln^=B1ETZ8os(lc?Ii5+{Fvix-5ai11n6D}RTxEsZBGl|zuqTUoGC%%x+4zPOc zw1k9M>vFZ*0!Ep^lQ5*HaSS(6G_Bf)$#MX4Q17AP0DCh^X*Gcdg<&UXFAAttoJ?p5 zA)^P5A}uToU_zlAbcf?Y(ekRZ-tX&4q92U zQ_aA_iw^A?3EhVS;fR_{$3w3*21|`WD_Oa=kS18pO+GcjaTzrq)fB$CM@tdPixO02 z>6r>f;lZvJ(AJe;MndrT;L-2+X0g6XL8#iS8uYNHP@X20hX=SuI1q%K(%R$2rW|E_ zghRf{pTsViMIe;Kr!k$(lcPjj+CXIdWBG7qbi4M8;%3^B4vn$?aZmXF`p^b%)7hkn z!6uF+?G~z4lP;$vV=Wli1+_%qFRQNnTAkMGGogAH+I(l#NF^rOqRFTt=0G@HJF;*o z^d6X#t9K8gvzdn~c5g@VRCDdUxpT4u)28H4*-8C&w=SeGAICm#SAdTsRR7v9o?@Z7 zd+lH(<7Shry>ZO$?XtYmx=(fhm`}#j*dj*mtC^`A7{zh0Mk4&YDMFxYT%IV`tz9-} z!&#NzuztOtV>_@1n`BG}`Xq6|9DkBnO}LnJ8Oyi%E^yg1;3o>mQAJ>5XS=@i(R=&G z@l?)ajTUrp73T}BauX;s{yZ`Y;A!-y%qe$fSL=~369jA2s_NHp*RnT(N8^!jI*Vs{ zkojJi>Ax!M?NJkZx`OHQtop%2->ini=DX0bR)Gvr7Ie7m?8E0h-nV97X6yEm{=U=l z7i2@ayUZ}tEECw+yru@T_xNGZ zcE~lZ%j5&+>^^1H85YZRCzB^W{ngpu{p;hNKL5beClt>Av!oobQN86s8fQ~!vNFmx z_nqa_A;lF_A`|cO{Mzv-C6imev+EYfd;7TGZ@bY?2q+2w zGI{v-c7N&0Q~vJ4$M!z+v#lG?_%9!L;Qj+w4&3#2$mH>__W%7l6@VL%N%-e)xj8(0 zL-6bapMLqS5B&QKWpeX7f0O-$PbuV(Kn>UYO+PU6*w9eNQ#e>T2Be(9ym>#KZd88T zSmBO4fSYsFhi<;(H*s#9W2vg2d*)uwOgXy`d7b^!Lr-yjj1!-nk2!dM(hg>4({VaF zaDT}@Fk@_PsN-dv(xpNG{>FHD30*Ca%@9@I=Kmb4{GX>z49}zGA>X+$xmNl#?B2y#q3R*w{+Qq~q$tEZU;c zo`2r;lNOoqGOPvrNo_w9qfAiS^aYpAe1i`%d2MX4c493*v>!ch$K0F@BF$xqWrFQt zj9qD&;L^zY*md|aIrHu-cet@0r4?{8DQBV1w<7)I#QT~nbmYE7CM{#vqB7wyK$-YI zhXt9`pB<=`CG93J`d^E=bKWZ%g0Pt z07fS7nZ%>l#u4>6^Vo>|;zA|%(wU$<=}Le&_iwGZrPD}4QD=OMS&h(6aAIrhyy81f zk?zHpnY!xsR`N;*iuu9nPV$ZIPKVcGBOTgjLJU~XCHFD*T*dU?10G}E*)lxYRi!_b zzmy}^TkKAB?rwlSV?VQ1JpPW<_AG>66s$lsd#^29H>FKhgPY z_=T5f=N7L>2(||@QXibGzPaZ^!TosaBIEA-{Pz!GIiWs-bpyT~fxjJ4UXZ|dp7NRSgAcXrh*RBdCWD38By7tci%m9-x#Kiv7w^+`qvxjVAv+ab9-XD z^;BwA<)~EQLORBdol(}#VhQ)AH*LKpqqbgyuM(7SBw}k!rb_Kx-lV>3;O3^yNqAxx zhPc+sWVjB%ALgi)mPufeyl7J<4?jFKbmO!8_9(UK*>u?9xucs7FCJp?`vI{`(%)t9 z75AFZdRt^7%xP(}ZtXPo59kM$W#PTRoLy*Ibxpm^?0`&$hWK5Bav2$5j>jK!nFj^w zC$GGM+~ki*&LcTOuWlOup(_TN%+2lDG=@I%?4~139MO+|(_yDUnSg(CuXyTP8Na}z z*@4-iW?(q>y>vVW*IiNiijp8e~$dy}F=G zAd(jT6fWcrJ;yG>ta|HPx1w)w?5gcZ%cQi~ja_&Oby~!fcv&Jf8F>RQI%<9d(~zhB zDSr_V@Q2(U#7s~RcXVF{bqu~uTxmO@_l?rPN3bVh-{zj>-DDat-HVK6J_xh;0bF|d z5hM8nq47HiIMyvh4}!8m($sYuXcW?jkKqQhJZzK|oQQcL{#Y+D_c~96xum1>_$7lE4m1m+<=qa03`>u)8o0p= z0rGvAW(_|+; zA}wEpC6pKU5d|nY3kl4>ZP6%Wfwn?mS)Mxhu`39q-#DMC2d5mfDL0FN1QTeu5)ACZ z6>)|s+%j<%Oec=MR9HF(y7@BD;MWZCu?nJHkam_cjS%x73I#O}wD@K7ED3Qa_|T2; zUkBHci8&_5#nDWiq~S0K!!wukjdUW80!2xKPJ5htuobl=CNsKZ@aq)l7|!}8b#|CI zdo#Zn4VJb9HIb%M3DO>=Gzj@Z%;1OjmoOc)irV1~EMz-R0xoO?Oq)t0d`f1e1hZI) zlJIoY1b4W0OZ6Ng{VrXScDzh;G>%D>lg?sAVC$X-dY*rt*NESljUX+~xW~rmBZuHE#-tJ$fNzYvV~;duzyo@$0<k)& zt=|eldscH(A2fSLF`hy+L;2>FjwB{=ldcIEtW%8&E-2##bBDs^1>}<-l}Q4a zwK#-aH@$&>yAqSOYmsG zEwpgLmJmz4fQ{`YtLqz0UgxoOT*FmIsaBk{Cn1Q#;?f)8A_ov7p;Dm06_p4-Yn5+s z6a=LO(Xm9~CmIilo7}FBCXaZ*rT$L@-A^>ldXDiBF=d0m9J`n@Q%b!{v3tO&zL7tr`Keh2*5sja~X>`v8( z>QAr7tNZW~y=jHU=U3Y_5b9nC z0Nh`ZUGzH3tAi?`Mq)6<~6|R zMa^SGD3w-*PhbiS3CXh*mcA8%o{<$v=AaYNsEzCEk1~!8(a6FX3uhJev#1-v(=Y&< zzd$&S0KWe4Rj<%!Fe*f|q_hAWml|Moh!+MyzBr?%#zznms`e^Z06ttu4nVU{Trebw z#FN+#33>yJCf2HoQZq{JnxIbxBaI+yB^aXS9{|WSXw*@_)h!*gu>08mTo`{y*oEp; zt)~!|6y>$Rf$g4OFP-+wauCz{qwDMico&9X#ALg}sMAjw@T2%akl|5SUOmSUmD5&b z`~4!EW%2-M2+n{KpC}NgSBkQjnuirE&O1ob1f&94hzW>&lYYwC;Fkg$yGK~9XvP~? zNMF`eUPbj9q%eViE~EN-M;Upd#FRYtmO)A?)Cf)k_T5b4XPV1F$J}xhM;z`;3S?CR ztb({Fj6CeTG5ya1_%wFqc1Ij1?&p=0~Lw07v5A@^|%VzAk@!~Ueq@B>^K z1J{duC4?{bI<&*>>;!QOsn|H6b6Q1RHZ0qm@R%!l`f&>09X}<83Y;=>Q^iWyBqO zoO>yA&6}4BJ;*TO={(vN91bg@!J?hBMyPC6g}ELzT7Fph6^LQ<>*|h<3XViPWcwzq zW@=hk(XP~`Gl-W7)!f|C3#9S{XPld4I4n$<0dz z70$#cK2CI@2H-ecglM}8zos(yjt?1=)tDXRbdr|P*f8h^0lA^pgQ!=jFH|w?V7uic zsO(uRzmQfyMiv%D7hsd;NG(yw zZh2s&xO@-?VOY%ANTrE3G9TD2m+naOV)RVTLmYK4l!5Ab=sHj8tZ4*74CH7y9PAD9 zsOmiwjf^*tP+6YfgAhZn)5)u+sq{=G3vpCAiggWoV78iVAarRwX)Fravc#oM+xmh>DVAx5Wf(u!}-ID zhaGtcSn9K zF=i=$`xkMIBc4>=XrIjIf?Tevtn(vX$NATud6t3V)jL5e5S9(?Q>+TVcuyGZ=}_>O zFfSLstAqXwiokarAs%@qkx6}Nz&Hy+W)c%pWLNhpeHscSpG+E-CKNdOz@oG^j+@xA z7ZzlN@I!&%@k60L3|h>ot^%i#zf6FSUMOg_r`n0#Di8d|Z0QfIh9k&gVFP7GsYHON zn7aEvH~W>K3m?1*{2bP|m#TJuTHlOarM|Ds2IE1{p7l=;)d*7-Xxsk+`^l-Fy#G^Q z`otgH^~q24|IY8Xmj+IL>FEReZoj4Qf7(kuCv@5V6SHScV!4o8oy1$r9{Sef_xoG- zzTvHXdQ)4FZ$Im%pt7~?f^Mq=Ytc{q+a}Q&?k1!Ct z%}@svkUgy{9O%aO-))u3q>m4red@`%PxXCkZQxyl^@Lr!ZtC|6ofu<$ z2qd`ucF4qk%a0CxH#omz?T#;X=Q@w;y7YZNeEMHb|LBKLJomuMFKzkgHMyJ4J^!Zs zz?Mco+3sZW^!l~0e)9Ay_T1P1j$Ofpr``6EANRQdi%I>}URL=<~Aaoy2B)hZ5E$5As zbP^l)h`d4VFKpho|EJkPtv0v6pq|}daDTNLeD$1?7)NTat{!O$2OEEEtXNFbj@8b@ ziFB1MY%3HzHT0AV+q$(u=kB$e8_Q#RfV-?nofZmuifxO1yalAPwpJY0XzHx4)E zp~h?Q+Ql5JojZg!sA8FbuUu4Ja}Dq8i_?~KvvY+k9&89sCSd+{{C|Xxg6?4L2PudYq06kUQiU&#V=lOk?_TnZ^gFjWMZQD5~GI^@H zzfhakPnMGjYk4Tp^FI!S`bcPdflOL;C0wkAnfZ)*1G?Jgq5Wr{U8ubt zGC6U)k^9kg&6i0$cCnv8CTO+tP)3>5$2iwd#{TASICd43lL^MI0oBg23*Cxfn#V5O z6?m_PZXSb1Hz=&#VERcH z4aT-nqoj{a4Pj2V%H2g=8ykWO7jB`$MYu{m_84}+nEbL( zs0D6ZmHTs%bcf2DWn&!)fn3USBnd1Pm-9BX)ZLg(tuFKv4PLxP{ByGIfxtp#>95r` z3q9QqNUv0R|Gq!L+z;wO#4Bx4&r9g@T+EKKMGXyoFd4=qB%UMi4AhH@(}uAU5E((G z3^L*0p~_@V;zLWEV`=T^%VgChaXpTL^9%Png+vzw2bhO-I5)I$Xq4 zCeWvYO!N;$Cja#E4~sQQ244%|=Q@V!np-3%2oJ59L_ewE=|QF?kPj7jeCsd9ebpOZEOWWxYc0A?Qo37PMrLb7S13qqXq+RbPYB266$)kpQ zJ}Kk#Dbi2)J&t|o8LpqmmsH|@!gwX76@yC`x;jH+!;rOOKl_QALq9oWnMgfinYc0^ zU76(mCaK8E+etrhGQowgVD7(v>Lp%4dt0Qco54=Y- z;$bm`dl6&XianvnY3oO{rH%0Sz)E!XJTsx;T>vI@$q@aBE@@bHLeo-eLep%(M(4B* zj1lJ}T5RMuPCsldHjSmB@HK`n!c7y$P3+jasI?^Bgm&>9@BE8lhZw=2*T?|5W0LkR z7oK4_AmLr+9q=0W=LI2i+5!;?scwsnS*Tav65ucGDy1_ZtUJVoAU6{MT*Q^u<}e6yME zq|G5m>TBlNGO0;17AlKdB{X6i=X3&#(TtaF*o{{h33mPzs~I6OED&y(^QB#hdmQ(w<2nIvFXX4;#XY+)(;ZUk$ysAo(D+s?3=yzbr zKjDqyV7aHV_yIK!Vu9NRdc%KfxR-RL;-u+_<`3m=06n(hja`O(um(JZtLlMcad9L( z1d`I?Pw?U=E}2^|NBaUJ8LB~Nv7hCF15C~xZc&65>=T*QMHO7fSsSWB5Nu9gTLqVV zg@=2b?&f^OzZohDq3aNElr9;!a9&(c%HT3XRl(si1W({>poWGP&RCRjrGYX5E_Ue$ zU4T=z@fN6d(G*H);N%a0GFhd?36#YjApNAmS|g(bI^>x;@f|fA&4b589n(EXBhZ$a zS#a0naj+Kzil-^0cxX}JrsfF~TnFT;qsuC=a^l1WR+%0HzrhK(&?cPJ(0!mr(afFu zFg#9GI!B>m2W7_TqD9{MD?GomP355Rb`^5rs2*wMfQ?;6Fki>J%U_#yHMv z3?`Epd}Pby*3Kj;mr4=L;y$y%Xn{C(giPE$6CzGAQUlD$j`|m23>**qe$8ZEs+1{z zFfHN}XiEc-QfYNV$202Lg0 z3fD9Mn1ias8L5Yi096U70JqXK>J33#R2DSo4MkP0;(Eq@9ljXq5JOL9#_BxyQJKPM z2KiR~qSkO(4K*b~Swz8{0x(YD=VKC3;VhNG?0LS{q3%BwX%EikRA$_&Y@|WV{0Lf= zRbTANT4bc;2Q&05^a)s)PCAGn5FZeC9x?L^yhlJrM*&>XHBv_UVOXq8VRD(#PNPoy z{Sy`nn+WBi$1i4Jf)ZaG0D^+jcyl{Qi!<-&3q@n~MQm(7`kJ;#QB}iH&sQ(1Z**{B zfDK$M5LAGEb^9Jq?Snh)43Ok0QEy(_g{pFr0K`mnp0sJ#OkgU5WZh`nmFYq#PBF(c z25yD)ZH%Cg;bKNr{||gSQ_+tKy+tcPeevhQg~(AhoU!ZpQ(I6+3xOsIwku^vs-98m zxCpvE%4%dMb>f#J2x!IQzzg@mLRMkGBaKCU4V0t7gTQZZ!{-fhszQBK@)RZ*jUEwL z_2MVgRPisa)kYOK(h1Gs_2FrjzU1E^o7UIFFn4e686H&8-W_tSly)i{~ zG-DYam)Q|&jZ{YZN2FshNRqJ1D7{tjnLV%>g%K2@^>FwpP+1TO4ecg~vjJ|6dqdO| zy22id^dv)QI-xulpc-s1N$p2)7sej4@?y0ek}x>C#i@OAM2BiX^OCt!;0=N&A%r68 zY^u0)E>JT?#jZ52XG4_%xuOtFDP|QKcbm4zWC|yF5#1n#GdGN=peG8meGqjP)XTsC zRPVabQTw1|Q3^Z5-oDZ)gUP_dxcGz%n!P`%g5>$crRc^cYoP*#hx*Pi97J&!Ij6jy&)vge(x0Qwg9j z1ZTnl0s2w65ei<=&?@>KR(N4KqYZ+rE0}z!&m zifmbs7#B9u(oh8~hV6cc{sjI|)CN4mAlH8EOolsXD3(&y8R;sKb%a zi*kXTK!4F(%rYgc8~CWx>Gz*H491y^`m(>)@VR7$`5F?%U=l~#z83k;8n&IUP3N`R zpzMP<+^=QuAsyBygO0vAIRm7@N(A5U!BU14y{gUUY(g+btR;V3R_ldk7UI!p z++{EV!MZxB)El*hXhDE^$)M3*3E<-h_z|>0s7PlJ!*;K-Wd`?yNycJbE40Yb zCav87T|CP zV-~g?4An}~U;-0npe7hcqP(fH)@aLtZDJDEuHrXU#3-t*s979N9$+P<5e-{jSL4$g zT3RJJkOE6IK(oavuL|A}d`kHsAbIe~jf6dDGfd2?l8RHQkG4qJBFJk=kqu3u*=f#b z4QM57gvG8m$XyF9=%a+NlCGF|@RNDaE$tO}rmYWu^|`b+PGGV1M^%kAV@U2UTyZ&DK@oKrIKSTE}em#=CD zOP&TBJ59g2)Zc)Iq46Nh_ZCTHDFW@cg92+WF9=#>f(8Bbbf2nTs_s&cuhqG>s0(_W zmXVi-uC>e4tPlm6Sb;*5!7fS;w}GktcE1zrC8f{OQM>PB$Y*t>$#K2n9&iH_1r?D= zfH1&UK4xEGQO zs*m~`e)XmCi*EYpd*9sl&|^__D3zrFYT(mSvI5ATnPyNh4{?8kS1X~#dm^T5uI zkNxBH)aq~D@j1LjflOq6NQ%Z1)@Aa&Th{N1cAei@`<*<-@38-z!QJ=&zHRXLGO-V``6ps z))hXU6PYx|E=n9wm&xzGr8{`$TjzJb?>BC`W!pzjd*_AkyX0SXo_)@{6Pawxw|90c zzq{iO$^_G040as-BhC2jy`b)^{RGGIOn0dSoh5pe|dnI~73A~94 z1(At2bWZkFgdSgemHyhRxES!Y9fhGGNa4BFtD#R(+rAU`I#DLIrDd`WlqefYr*>?E zdD&&Po$P`QsCzKsHGncf7u!Gd><}~`hn_9e#x@}|9kD^YplkhS7epTwoSpgfS*Zy_DeWrg0aWRL@D-@x$hPVjj;<zsRl=EgwsDSKb(zF_Ny$CB?p{kL6V^Z0mS8gk#ABB#{R(6< zH&z;k4jp#RwqTcloBlybO?Tok1iE++n%M8d5BS3onxMmu!gA0{y867o5Ov9gCohDt zE(GWRAH0aVqP}3`rRs6+Hxx++wCGtbluiTJb8*A{y12lrSbs5!&P0v@c}Y8|TWr_$ z8WAq{K-S}_uFtu;^>lh*z_9Grs4djZ!7UZxd8c%ZF}FsGEw;U1Ir`*d#==t>;ek)zYlU_%G{LhK(q3S)^5aZcR9GqD}ht8{fu9G2LzSBu}7L|GaH zQ%^)4`yS^fTEL`ChjGLX?=XwG6MEWdnuEamq}TX4Gw=~U@QVu;p`6&pg{7BF1EGcl%{hsW0|Xnm zV>j5)1Pn={fzpUqj8sx3rr;<^;9N;e7vg*_C0{a$^8>v}Co5^gu!&<~`x&79wP6!d+4BFLY23QS|=%!H9iJQ=i#3`PpwI?ka0f7bIsvfdJ;U&J zz5!c75^xj@uPIGUpQQmnkrSA44ia0z;~2ZV_Z68Wl|=2FjI1U-n`|9?!;>vWO|V^G zUWR7Wv8o3Q>4+lVUhb(9#u<2rz3B;6Q5`v}q7K!S^+qj{kWYN!@DX|hPMCn#=q=tX zO9L-B2o{FrfKv_c(#ZtT;M<4gJwFIDnsoSC+H|_&!n8ad<*8$>7p%b!62@UXWGb&i zB;p~Iol-oEC-hbvc+qgO^T%EZn}=~YTc=2993qWRk<^*rz)5if%M;BgUF01rBSSe0 zW-4VY6&%^lSXMcq*6Dc~0kX@8GY=+_PJnP6coaIif-+5|5trw8uxgtwXj)%mRcAJ}EBmfApd72Cko-!SoP-x1O!kbz}ZU`*mtNtP~c!>OeZR8aPyhh!P+0A z?6LbOSgv46W@0Cm2v7zrCc{V>)DhgAz|cLZr9lN&^=MadeVr>7s$j*Xtt))wywd9G zB%T&$U@?bOron{~GLZ~K2sZA_Gr3ElzCN|QFh2_zyG-TQU8#@!b5#n6fim3yNb~GVVPkfp# zqfDr#)M}oZE27kfNH!j+1qK8RL?}@|0xW~-wWJfv&bXaf&^XYDE&|5~@R`uXr>w!? z0*4u_jI-MfhyHmXHtKUY_!Wj*B{S6}-2wfpLKR(%p_4evjBykx-LAfd2BV?wkn_D& z8i$*C4JYUALB%p@P?y4Obit1lUWy+vl(@FaATt&h9M&MV1X)To-MxJWpv=-^2mP(_JT@7 zWZ8Vl$03}Ksh|Qv{(PiE&|=a+dX__NVDt=!%MR74fd-wW1+Zd*E(ROh9h)U~f?gRr zNxV5}X~P&CcqBfqHD{I}GA`FI2gZPH{#Sx%QUzn}cpb@vB$`n0_z&u2Xd)&YKAkQx zPg$+BhA<)7M{z4rSdG@Rb?yyDjZ(Ay{eC6vuY4^W$X92!&*0>EKe%c8ixn=X{Jl_l z^sxj`6LtojM)^3dTv>(Bg4o#r?DzMA*bloVp;uASIB;6AsN6XCIhgd5q?~M6fL@kO zs~jc{Vg^tbPsC86028o@gRDZhK+pe+TE^}bx01Y*%p`+;7RgoyAR9b0`1vZZ8o!b> zHjQPb4SfTIE4yZ&VnWu6RaDSaBkaXb(*ZQXBg_MxxSL$>!sQ*gK}`6?7xlUQ_H=Zb z0X$i#%gyka;9+)lJOHDz`Db!+_e&7=$t;YaNnOhZ5O|>*W&J)-V;O6V?owrK0_A(k zsA=`L70K3>FLoN`rh9`j=@?hHpuPfPjSl6bq;%6Me@Rk;j*YI~wC||8C8t?tK{2S( zh^aztF58Kxgg`wA3H4)QCZBzSMh{23hc3|5Ua}(~$B2YLfQ(T-XAW0C<;@6QBOL8o zbqwN@9beA;52aRNV7l3am7;xAt64N}r~&&G&-z9wqu!+Uk}Y_jJc#&6+eec|(R?2d zF_=|Q2z=tgVB+%HDky26>PHRs0uhbtS;q757z!z~Y0)IaMe4(fVNmUc_g=pU{-eA3 zeU?3{@7k=4p7F~Ui6m)=%NgrG-|)lXKegr7J>uO81v1%DFth$<94Zsria$t zIGyWM#vi!{BI`r$8^4ZKG3bIe%t&~OYeyPIJlOOD<;SCHKRzK6s#%3aFW&kp^NgpV zX@#6a4^oT<{J@OxuEr7`Cc|BzXa?)NC?|kb4k1TlEONIfeU~3hcXOgc*)2^Jn+0#c zi7z(XN81&)a|JmO)br6J`C$|_$1<_4MJ7ZoENc?^-bT=|>BA3T>0LEdAC^ASG^OhV zh(n+i1B_9@jY;^<5qqHQCpt)|Rx6CQMK)BVDk#Gw_Fd5g!_E z0pq~T^-O;lGXYvQ@mX*+3amj_!rf0AH#;M3XkwC~3xFY>B@O~4C6IJ;>yMhE_SK9- zOYLmzj;&*Ut=WHced`@>Ev;U;+{bzy0cr{^8x@)^2*qlR9>Q|)n2M&u(!dIgmKp{( z$hX)_N5py~2{mXTbC7#L>c_n`lZkkuQRPSO_}rT?l(LaF_x#N{63=M?*AP<)O`OS2#K~s-=wH3lq{atc?tI zTfrhnEfoblpkLFx6>S&`+`42urKi=f4niDM8V|9&>wu)Ony&hzZw#%Du!aI--1e=3 zWbo@{Yi>IxFl{GTKfuR63^=X&a*!FXQ^)5-#@lmm>h+=QYLQff?h&%!VjZZu<0KT(QW^QlFb5xzYN)c6PW6{{^ zhcQL!NVj3fQA4ZQTg}P4vp<65(1caKzXCiY<_d+98!`ZsGNL2A-}l&aG=o{+I&&;M z_}O9UXDWjbL=Mp|X(M9!{mpO1nIQIIFlmmUXtC`Z)IxXS3Wm?II~g9A#K^8`C=*jSlN#1Dx~2A)vu--KF}? z+5o&VY6R{ zMiol91y|jQC!2ixr$(?Bd>1}yp+0M#z!xmOQiVp@dNryc&^{DA>bHp11RCYS(1|`` z{f=NtnbjD+Fghq38Z$HDbzXE4cAA6pKsG@#fEBZDWZqeK9&LwL40^zCv_lK_c_aDU zjPc7j^Seu7fUS6KyjgKpAET6s@OV7!JsA|gX8YOL30b8kVR>CpJUZ$`Pv@`E>=QeG9Q6Vx&4ynG28^li9h7Q_z*lWNlE@E1L*)|Wce zc!baGl_Pb(E&98BukSRgA;^h0Zct_lQpD^NsbNUAyNH~xR#8!1YE=o#fO%lx$1gV+ z@OoqQu{WZ#l!5V3bx6za(|z4I2O>}SZY!e-aIpX%~#??h_10!d)M|rT1fMK~hg)ZXZ5|n6Ud>r2(Qk5)~$W=^mm_k{ri9K@t^sH zuRij*PkyZX)2CjU|K0bU@bneuU-4Aid*AI(b-w!^|AF7T{{G$FYaV&*5B~J&6Yqca z-22NvzT>l3w0-tHKlx^L>$i4i_nd$J!00Wxd-wj^H+F^J{QQ(FU&9=?HYi)0JMW2m z)*iR#j*tEN>ipy7w(_MD)#~i*%$>LX@k=+IbN)Yn;?E!<_7nX3wpk`?{%<3-qwD&m zH3MH-pNmeI2m+KNhi}`t zw*4O8H`n~1*S`DsuYBU>|E&G?k1ss`@;^Us-Q=cyTe^Sk`>W6T@$Ow)&Uo;Fzr5uB z)mz)|xa8e`y8gs1ZyWuMk8T)Q{Lr%za`PMlDamNNPI z?zKNK{$+cP|ITZj1Lnc0Z6AkBZurid-=OtZe{1}#OaA8>kjc02I1TLy^bMK(&OL)$ zAd?%j`KhiP#t3|VQ)H5#*-`!AWd7kXm46sVUKKR-tSS!Giqu=_z{PYmA1_jHcGcg9 z@uv3jFMjbiwV}edzl{qCI|ggt|9%$d?5P7ZcfGoA-`L!o@_(9zj?Dh&JBqc}p8Sif zDq}*&J&l`dGq~mEM=$Jz+SX?L7GoJ^8^COPOE~WSXwNKle)yPOEpd(#g8GXJT2*rW zNGgx9F`jRaB69KUvw7;bSR5SWeKX)zN_QcNQZ5e-oqX~FXQuNVC44Ro(x3tsQY+W2 zD(t8Ybs*p4p-uN1Wdiq=PrWst-?#44K4UUcJ?I;fJpW9i}x==eqL$wUBxJ*pI5-%u|j-_Riy)vom(Y7fO=*mIQ zxS7#TCdVE-R%?<8&aqP_C-0kIE+>=uSe}*_nMgkonLsj7QK$_aGjxuVNuK(3L+aO^$RzIXMbQI?F7D=Iz8A$Z zK^<{FX(e|F1|{g~X*nq|E&7b_aQciGS%e-@oc<%?af1zwJ30>*<6-L6od`dZ zcs@PJ%VqthHnkc{K-~)@?D~RlhVx6n zk_Pgx=S!Wx_fInYa0_$+*E64_T#ZE5wT#z|u$6UDj}a+$CA?sn;1~Ty*gnFq0`s~_ z7u#2nmoXi9?&_9=BaZL}E!FV|BMBxDOa&ODpc@|@gW>;GoW6cuy#oCrxN550JB#&% z(-DF#FO$FhZH}keF~zk2(s;|D)2S=%IO(M9PcxWN0;~-%szL9a*I{>jf9%=pU*T&8 zwG4H_;yw>o0=Ny0e^7pecGv#Gn&+WtlijrGdVJS{=5OBp@E+(0J)4lX+TE|)9DnY) z8S?D9;stz9UyO=Il3@It3o#WBA;SgREWm{PF_ zTNVwDIbg;KwO1*V!J)z?NWw!3xX-%wYU#fG!{y%BScrJubuu~mWNOAyCeWRuOg6iG zF5c-uCY_ImzwhC93}V2#y9ti{)h6#z^qh1W_an@{kjV~eD3a3Y$kR1nCP3|{Oklf(oTSe$g8t^nhpa*#g41zm1$kCb-nIwxfn_@)ijg!ZQ*2Np1hUesaRt zrtCS$bCG@mrAO%}v|T^hF;*^98m^x}Cg>+=nMiIaBj*l-q%cRz8TS+6H1ojiqR>AK zexk3!X+aWBBUwCqW7B6k~6DJd_#__x{xY@}hd@K7&CcfP<)lWnwLz@ms zChvcCPts3X$FBMPWbJh<*Xsf2)@1Ce_tR~)p&hE&{+epP>@w!R>gPj4?Q@@Z{RA>; z?I#VHfWhn=A`|o_k%>RT>8h^37=={bf{5$-jaULGFBj!6GQ>llkbdRG@jemzJ7W7b z+Lre!3LW(wg+7j#6S*?O`2Z@MJI0Hd81ln#cmehn76aclhm_yd>|fGX&u2-hMFR5% z0px|)fu9#11<(aWvUPm!k6azV3r9CN&wkLwQ}_7{XUrHT^tiYl(U!K|sK&)^=r?YG z-@o?}t<(5tTs-RTjb{-6-M(>H)a@I`x+3#e&QEYeCBI$9l#4<>-RPK?Xmw0@tv42 zOh`EQmRrD}rKXWa#H39-M=SwL)1Wj;bE{vOSp?;rjSvR;8g{!6160NeXX){A07@C( zz$tXZ1kRVB3;^zu_|XK69bt+9XNt4gNCiYapGKIGKN6*a=p`62QSLM_2Em!)Y&H&+ zzBx90<7iw-E)1N-;~;HdwO9%)94ABSprz9g(Od66+SG#);K4(!5Oe?@4j|OyN6yD* zCBY(d9H`lX{7A1=#)n>C9?=S|n|QX-O@zVv{tqFaSh2u!(~<`($&G>OO;%`A2Z3vd4C!8w=(Tj1(VQ zW5p@A1}uh=2&|b;3Kj-G&!U3Ubw)BI0asj`cFV2CTg{Thgb9n z)=d>vrA3(nc-7C$C40tnE+Z~fm9d$QXDm@OxG!i1w(A8JE`Tc&DglMP*b@^d1F<@y zl&Q6NoSDLlv+dttxfJII9aTR$22P~Frrhyp@3_Cvpq&*k%fPC9pZs!JjjHt9^sw`?whV|apP_x1ok}6n;sFp z3=jWijzKyAO9LF!(?KznLses+SXj6( zPVWd~{v@%|^d%yb-f4`P6(VdgicK!kF)I`nF1{Tln2NNXK;#ghHOp}%7e;e91k1=l z15eo>^|yK*_D-<8VxwSWiyl>o6ndRFPvNqlwdKN`T`@Q@IaP2m5pDn z(H~73oEq!zcu;rfX*B|dLzcE<9F!KCDxOAC9T;;o`ju|Xx zJ5hph4~sF2!!3xT@q-NrP>D7aJ{<-cv>JF3S5EsL+ zRRhUm@EAaPLS;0VvZYJbqd5OdI@Awr0vNa8@5KOZ1VLmPT&k7Gpoif%-o=!IB8MgG z=wR7d?7ffD&lzHp4uWrJ2#>YL*1*KHjIKDY-HroC!0qRR#G+cQA&}8>k}hat02LuH zV%c~&weWFpTpUa~sQc|{-%)W(O_4H&0vl&A65I3-(ycebFyaE=Xgi;{EX;shf(U)V zz%b4cGl3p0jO5u;A4&A%&svQGs+G_;Ivn3cnpq9a18oDG2v&9mdCS37pGrGbm%2sd zD!#9c9Q?h;4)|uu%u*PmN^JlMi;$tEl{FA63W7AG8xWg-u~H2SI<6i(# z^6pQvysZCV&&skbZyckrHsMmoI}*YXuA2zFGK5RIG9`2a+#Ax;YuY+^^s{W_#g_;k z<0K7_5rzQXwE5SxX+j=bF$B_HH#RLHefor&^hxQ>ZExzvb||^Qx}Wbm=luRj+SP(> zlBa&9GxN^-zVpt^`_9anbAEHqiNpY?t)U9TjI>PC4DMq_# zp|~j2D@DN;3OA5P(mB;DZGjNM(8p8!!i2FZCJ@(8W~@bZ?V=EExpaPB2oRXZQzR4{ z<;^+LeeGj{ssR(qB6*Ci6=QsVY_(eJEx0kx$JWHzWs9*fePTkNGZod9fwvjt>&~6^ z0Mitcl6ycyIb%r{A6S<|bg;X$C@1pSpQak?2U~80nJ;+f&I!>?xEZK}{8AT?1PTiS zVRS1NMnZwlle(1Z86=QGBBxOA!0DxQbDtADtF&0J1CO;c zuv^BNyWSr8RsC+wSdlCkDFn@V^Ui%}l~n2H^B9&7{iD!wtq|Rvc;x*ssq^^_>Z4ZG zEd%WZJ?BsZTKT|;l~9u`uH90{9p>=e9sGsCycIKzm1Xr-P`Yq*%fR<8v5d|zk#p*_ zGfu&?Ymlu?WGF@nB(xQ{T#K^VS=f_qSquks`D^oK(qP_nbLY-q?hD>oS-RK098M#+an@dM&s@;H0minf zq1sg42CM=!`h=p3nnyNEWS-JG;5%q7+op_vu8ls=h;ILSl~FeNdbr|{ueeDtn&4b4 zCg<2hO~nVI#zRC-4UQaw7$Tup&Hy57h^-?5(!S|d3+oCWR9a1*at3Wb~18`Zd-So-}9t~90mD9dP_@(`n> zmg-twJx-UQDW^WQ)zzYRjX8c_Fz>X9r$o+r@|5i7kV%`Ooz~5at=#5YT3)P_cxyph z*Mk+8wF{*kMVcX$Cw9}joKcaBaxVITVuTOb<%9btp?X_A;O0kAg4SZhUPm+K?;9G= zN5-^W=C~W0D<@vh?8a|jWC?arKL}R%5QqRz_i0d-K&*tpR8F*monsQ|4sEYjH{n$H z=nJ;z&g?523&}B2!a=-iZfM(J)kG8Nu5;`pluh|$kv@3Dxhsa4ScZz2$FaE<+Ongl zM%1q__=9dH9xM(G`PRg8^NQ?|Y&AQugy))LT+Snlq<0w$i5Qsrs9SS@F?zNo(jQ!pj2!C6mIrB(TkZ!&b4VS^ANI%P}31fFzS6#{HmKCTsYt+w8*_;MvPfo(iSm3?w7)P z5t}ny^ToT8-ja8zWX`*I>EL-ewJVrnn(7mUi-bgtkWJt?P8nm~Tbb0M7}wIkx9cX+ z9bsl+E#zTG_BM?1Z)`(+en_+pTQ{<5YAw8qF*m*O)h;i2$2c1cH;y5ay`@CuA<{Sb2t zQdpy@K~=Lb==KdH)+dN0Sgk~>}HBw|`un4R-H z59V&H56yYgbuj&y#SKh9BPt4a38plu+HH;(?0gcdL9r6Sx}cSs=Z(ZjiFOa7r_E73 z=!$GGDURt-WUzGE*gqP{`8?y`zjMFmmmYM3%e>pkm&Mp!A1ao^+$V~#{>Hhxipvh& z#nVIn>QKa$^ACl?(_`PlYhxX<%UYwo7rH8^;*i6=P&xv6Hhtf%OGan_!<2bST@ ze83%SW>d{e23%1Uyd{b~6viETTRpT>CocHDQ}drguFeGf7cQ<~QF^b}R6>PYAGy~x ze=eV+EPMjbw3I=WklkJ3_L? z1#kR-b9XOMdRhLj-@TIaVaMs>XtVgik#gbnZ{)mlJt~h5xLlX#dXqw!Saox5>K%bQ zW}}nNUCkQ}UOh5#Fn|{Y{^3e!7qIt4t32y-tfzMkBQv`e{Wb;5$V*{lNwo({XHhfy zO5sL{PLZj{<9D4{j+N~j(VF`GU%dPsPk;EV^56dA<(K^7uiia%?=N2N#&_~b?5WuOANcnlIP1%;Gw{iQ zFZU>T9uq?!%s;@OXsoQP+?D5dc!@zI|>`OrhJ{o=#l_0CsKxbdl>cxPO7 zd$O!y<3z6jUco0^&a_&QyD*LOTyYV}J+z#EJFM3K`+HyU(6vAI-9P`4&2K#T&A;}? z-^llWy!?#?f5jW_`@o-GwESCd*nIYPA9~Nf{*#Y za!6G_+n_z_@{8H$J+V6XGe5o(R-Ds!Xbv+WO=v$XJ713+slPmU!37M}5jS$!El%@2 z#erdWf$n>9Gk_e2-Qn9eU&mI~4Zh2``Q+vkuUS0C6O1a=(rLSERr1c!Ip=J^yq$cz zh4Zyv|Ahg*JDCc)e8OVeZ9P5B?)HhxFQ1!RSYSW)=0LkH`;M@8)nK4QBt3U)+N0VQ ztdK8$apU*CpO!a92liZy?LIRnpZvkW+9!ucFKHZuf8^Nhw_h#`{jysh9pw`pJUV&! z$;IiD`wl;IY|(rozi9ulzIeCk9t%OchBu#BtbDRT`mv2_3vyNZ&e0p*z_)U2H~G#o zy`07!z3JyKH84=Gg>5gqo@u~GM~)<)+}t^sS~YpDf;f`y0#$da`kIbM!Ntr1vq77)iT;Gxy24ynFD4fks374{NB+^*pz ze%GSku3+EXm3+e7Wj@i|m3$)0s;JI5+1=b_)jOc)5ZCnUY*9V8c*7jGsC?n|OrEWw z^$ecpd9c?h?ThPKem4tW6ueL5T+$A?1L&IN&&j|5EcMLzxzgB2}z#_a0 z-pccksO5&|ZsEWKyOsR*<;*55`R$p`vHE#M)%hSck}bF|KC5&pD}BcilUW1C$X8@!ZV!q zT%$d|sJi}Lp1HJVFU6{}_KAMAGpKBQ`9#|%r>y;!@s^cke}_( z89g|_+U#d+?pi#&ZR$S17Rc_Q+;nY+$>oHTB!>+<}^wND;?xGJk{+iR}L^ZKgg6!kE9e6sD_b&7mD zvf_@M?HF56>!DIm$J^yPbK2mmPM?Q6r3PE;bo#tK66-ywZ#(gA*Qb5of0tG9r;|H_ z1@9?T?ZzkV?4gY%q`o&>$8C0f!e|rD44K}gxPC3}K&Vj=;W`ZZdvU1f?Wjm%?R02k zAeHAsBC>2t;9W30k!xxvuIY7LbNbVwZz$-%fhRh+VWBV0B6AC+Ca5i;PV6#H^2rK) zS=7dMn`>T@uTwk6ZMn*ZU6O5(b@~6SM{d9!>P1|_LP+{d-%3Ujny%X$gvxUwNU38Z>T+; zWzKAgNM*CObe)SOH|RFxikR|k%kQWF^F1jNFMUZrWlMUCAGb(6AB4C?=~@@1=60;v zW@c@yjf6JVgZNsMxNam{ngB~BZX_8+NW~}O8W-~r?0P%Vm8+8B{pXLTWC|;dsMsY8 z{p(!{?q00ey=b508ZC_#E%fm^Ni}Y|N;0=pSTlk|ufR582m`!2a|BVZN7f5B!n);T z&x2C67UM*60R-zA0W^gvS9|o-qsTa0gIG3UC`N- zW=+i}qA@KzP2)RSA{*dIWjYr`eqmN_x_#z~8Me;_-AIHZ(8g0f7|;h%4>ORHqwOMz zJgz`qQ#Qe9(h{XGK^svrjom0((aoS@K(z3b!C61q$KFMrc8=}m({1LHb`I)f)l4#m zvONyA{cL3$57l@G^%22Mj<^>p3suB8Uizv(yL{DVl~vBq?C`2 zMfcnDE2`DwloF?A_BPb2D3wip^`PCIQfv8`QqpC{O6ZmlJ0xFLy;1^R0h1Yb-31X3 zM5x)UJ9v49VVQLoscu84 zvD#B@LRNDWuhogUganI}C*pMrjWYN_i(ZHzrb2vGR!}v7S@x2qW>yBWhN&?<4Ki5* zUm>xI+fikYYzB8-?WRLB%c3mrlLS%DPS}jQVj{p2WQ7ZI1#)H<(Wnhl2~26~=0=)v zzTyxWC3MmW^F4%GQJWZR%nPxgGKA6wBj16waHz^A+EQg`e#f!i$+sist)02U@}S)9 z^kJ+q1(AUeaLXhkRt)t5?YlReq{V?Pdf)<2)?i)tI5QjiG`}f|LIJNJD6pYg=QDx@ z-ss4L4ox|#WR*c_FM&cqf<6DO#-9H;Y+rA_m zfXaIuiVwMIzmVAs)x0!7%QQ)5Gc)Hq4IRqJvU4a<=NlFuT;%?#iJisO%qNl@38wYQs6t+5Nn>%AJsq z7_xyNs2Z{l5#OW{$$rZ!*`A%=1;A&>wn8U+YHVAEY;lU=0pwvyE?Px74=lRj_jm@t z)V$6VZfeRb<$0Kqr>BPK&DlIzW;jY8eefgZSyd}=3OG(ked0v=<=9UwqaInQ$`l8% zAVg4CPLA-#=9>p%cnOLdI4mfIB-9I`a|Fc*jlN9CX`#|^TDhGBcFIqm%lsUT&Z)PA zGJ2@D)^v@NTB{o6gHm3t?1N+weKkv~I8Md%Y%PLEGwGWl1@&A4YdF%%(9A?gSxAM^CF*#gN_V1tztX{>rS)ptL zejN$@y9tC1BjGDFMV;%bij(9l7pRw11+hlF5DSEK!};}lBz!mZ`NY*a6{d!!SWOfa z@Lhj4)fly68r}{pb364S@}dP^w7`oNc+mncTHr+syl8R>hH+lybQ zHhg=vd@=Wn7WkjZ0>gpUW`n;xJVU(fK3Jujio-JB!nq-|W5=&6(0SfoKUJ0FEA*-; z`>iC!`eu&O#n0u$kslXQnzvkZL4YB8vFtuv@sVSTjLMruFqI=cjjn7vp)oP|z`TJ^ z(e~lW_T)36`nIsyjMH&DrVZ5jv-)08mNnaL%Y$Y4aGen;wb5)qEICg;U-Lg@SpMlx zO*y?|bG=IQT_8#5`#y&7O`JLwosU<#>lLkDrVyxNzL_IeG;Un>Za`;R(yHhNXpeoN zYeQuHtsP=s9BFA7iLRV$sQag(BXX8^UXI^IRrj(*ypcgI9*_kLwe z-~Gwvq0eKxd(=kap=FD+K*Hd%Do%WTTS=A9?}5y@cZn$IP|$(s)?I5OLXYk3LE`2d z8~GIBQbEAs38J>RqhVHhc#(d9C5VxLED{avZSYD7f(6JcvkQJ{B=?X|m=n_DBoH|i zZ-vlH3XI%~RNXTGO6`~4Lg*GS`Cf@ox2BTwDPFR6cj=F!2i{7j7_c2(LD+@@c>HbD zi9~95E^q0srR1!eNWNe&vhj}Xt)a?tFvT(<|90T-u`%R&v_-9q?$YQn?Dqx>y~w#@NUIwww}sp(~Fud@p-zs$aoYiQP~_uTbv3hyIr8 z;uFjEoX`_f8`(k!IpLK+66*>B{QlZ0J!3Mn?dgK#P**n47_4(w-N)BTENWs3+XlO>1~Y_WgH?^C9Jsajrf?Bg1*x5spg?}XP)-X>>Ac@)Kj zu3229L^~`CHd;lSb>UOzdy-j5@V_m1s5*d5-8xy$(lFHQn5HDfFvZs)(d8rz>cKGY zFC`hbHe*8CTfaRlKn`w=*R8KfI~v*-icGV8kUCmLMAXHXez$0;^giJ#`FKa+_5!ID zJMqqp9x8F-%uIpReMRd;yz)T_c4r&S%K|mPX$f!g{!RU4A6QTY`sY#@ZqQ4kJ0zyd z39Z@D9H3NtN;Dkn=<6HH^jVaUid9W4r&85k(*TwrNGMhbMZUtx9TJM6+xYOSyX2DX#0!PQ$!-!e$yCV6F}vzCOc6@ zwtZ7;Aj={W=hLaAMrgX_SZ2JqTXHGa4Btj+sq7fdkW;nQ=GcBm?wDLD@j^lE$ylfe z!28_J@wey{gkM8kwrYsC9mF<~jZa?s_y35(E>NXU1ymNcj=D~?^%Q`7!7!GD1rcM; zn|!d4AiWGib{Sp>$R~P85h=^p?rNA-1i2{-l^rD7WbZFKj~VoZ3!%W5&dr4^ zpjwu*#7oMaFN7enoSPO#OT2^|6BZhsIrIY-Hp_Lbbmys~AZlqS5Bfq{l**k4(IE)@ zWq}n}P-2Nd%>qK*EK6yL#};$1g!e2DIs+bp`lGcvwEYJ<2i(bhkf|4&rB;(<)Vt}_%Ms%F} z(~*;Xfu87sD`OzLqYK43i0CS;{B^PH!V(ii=i`DIIud%s*}yt)5!@;5M$eks@j9<< zmQ<`68D6X24Mh_opt0Q$YD;v87u>IcULf$4L)8VjJD8Ah6^|K7WvkFbxm*O^sR`8p zyCjs1;2d0#0qYia1;GT_-COwFwp+(BEa;|{X}v@q(}&2%wD6MFItbAb#O*)~lS`eH zb&A4DnhmjwZfN0aN*SoT#{t9wo|E-NOB@D~FnB`=suDw;4mH+x&fqtV=W7YYz4e6P zMeT+y65Y%*z`d#Vb&iY|`qxd1AyH$+OmW0BPKSZ7V$D+t)aCW5nQ8Y4uQ%r8BcWJp zG+&Ko`}|LlFSyr%YLco-$lM(1(rqNYD7VRr{yl}~#)nNY6)i%`gU?r{k7SxOp2}=- z;9na~8P&l+^o!hu7+p>lG%2syt*~6}fVv~sPJ*2OUq~aRN}mzWrgV2zelAgKdY!&kzDzXIwINO=5ZeAi~+_EJwK~qS3P-I5G+z@J{m^D!4Ba zR5*2ulP*C(E2LzOFs?FGeOtD}Xl`inr)TqEgcf0p1VB_^xeMds3sLasQH9dcUKgKr zpGe=rI3bVfw;O27r5BYSfc4`Z82CBvsgANG}k60VT z3DttRY-aiVdg*+=u_A#z9Fa#Cv%#EmS2nwVF0Cg9OKu5=8Ht#xg4Ggoq$Z5Uxj8Zy zMI}OT?onGq$1p=HB&EYZ^A=$JNjA~chi1YtvwY6-LRPPUmH@#*3xw)u!|3<4(H9EI ztqrQDfd0-z#$kj!1}tcExEdu$Z7?*M;g|FQ@kEVAPJu7Vl_{Pk$wMjTmu9E(=}0GE zXttJ>p)Cx;8LTD(bX>cCK>ZzT66DeF7Q5cH~x`dS{Tpc)xNwT z3pjum*cVly(yD=(K#R3@g4KrX;#m;qnxe*Gtwa+{GF_4~w@ZO@D|`}YJ(_DLQ82)W z6jR+~x4=8`t?k8bGd#y~yf5?hoHqGu>UP#_)6KYYY=ka1)ZOYXV_{ehwzz^VULYTSXE4g;eaBGKXXeS6Alnf0^F)m6Uc=nNJ z(9(^EZlP1-!=K5f{HaBrb8e8v90PEBA!7z_u1sD%wsy`GKa|Q8ubn0w0I9*(NKNuC zimhJU@ku3Au8uCd{NIdlQiz#^YB9GB2a){2 zno8`2M^4lkzAg|$5Z7mQJw$MMNR_BN2XhzSS(|kWlbQFIx+MoN2$9+?od5q6K}Ar< z7ZB?DYjkJBBP#h8jL0})sweUi@YGAqSM?OYxBq7S>}l|2m|YdupyYgAHN(riN&`W` zIvqf-5O$nwF_9i~wDUU&vsj8P><^}s+f^eSyMQQ}Y_D4#X1H>`-(|M8=FvZHqc0p1 zQ&ChHz^Kzs=2|AX7MYhJdRzPSH6|rt=N>1mlzEIAF*Ri5(nxchak%k>eJzzTxXG)98kTqfi$+G2Ts;{p)6_NGna+a+-LDzZ0(tUv%&kRRIkFPzW7&~?w=nib zt`J^Oh|X5)8Qp80&s*j{ebFDVsF`1i7c9hLPc{@T#17vx%uq=^Qd61Cp?m5=I5m&? z+zt8Fe8Kq{(G0R7d@|I0$tOPfpTG8vZ#@0m@A!$Uo_+Ek+&uctPyWfXKk?8{y!SVc zJo{tsefy8S;ewyJ|Ie;|)f4|J%lEF4u^8UJUkl;v^<`^Y2WLwe{{|DldNQ zqWk~A4Ug?VF&xKlR}c zJn+D3<9#c4n9^MZFa6KMe}}_`}05hA69?y zvAf^D^pUYw-28oSnmb!Q;g73m+CNAt*<#51izah-*3&0WJl$IV;_uhZtbDTnKYjk= zfAo(3a^i@Xy=Ktj%e&*U||KYFOk37`baA&&LL9pKv4QYCdDZ4DuUiHym|0lQH|Eh@}xaLiK{8i(GAD3*ogimzd(KuPS z?EJ}DclOgKT2FuJ)30mKUF~Y|7UBk=bmRU0U3{PB_PM!YlWzyPkt6Q#K6fz^$J*kH zi?@>&)NxAbE$MqCu(){ScE!7ZB=1g|f?GHBArD^FzH4~tqIDr;LYx z2%jV!r<8k6nRNv%UIY#wzU;Dn6VE)uHx(w5PoCoC=GFIrw)li^3+-F1b!@HJ=H~QM zH+}#2KXLI>UzbnPyU7*q+4Jb;qx9NMz4aVO?^s`0sC`k#waUsTdlG$a?&4!L=QQz? z;%9HT`9Y#@!6)bbSN9j+S)W+@9>piOZf@ceY!U5DP69_My@ zH`L$Csl+N)rJt0QU(9mHfS&^{n{~gW742p4^_`&o-I`8~@BNRb=0EpbpS}ZBV7q^T z_WJuk*H1Rx%O_nvj&1FGLGaS`L%RyrW+y%*zR|?Z%C5FHtMB*x_~%ytzP@o&rS%P* z^H~?=$E$DKxRgdk`qm9dZREZl{n}6 zPL9)I1J|5R;<@JElD-2phwa{j?(6m4p9`_=-&$FnKJf11BTBQ{qEE*@pCsFfkHEOv zthU$nTYTGL&JwI~Hr<9s*v&Uzd+oxp#ajmsA0GYhqt{&XmC?ha)6>&OZn}wY$Bq8> zZ@b2XeN&BJ5OpqQx;$Kc$t!6b7`wMMm!h57_Y{|L>v77xEouMC=BpPjo#wkrbENwh zR|}Hin>0rhKeahL-2L6d@^+1rAm^oV z;wBg;r1Z_E3AeD|_B9&&j$Lp8>HcxDs6io32?jPB4Q0K3^LEC`tz8`bV7wLj$H{%y zK3e(Y_U^n}Gj5?=@He)QUO0m4I?XXr9YkrIOdqpxLb@AL|E$MJW8d(x?yu8ye6ksi z?MptHKC(XXi-&dn_}ln|@0cFjcyt+x{n5`p`Yp~~BOA5O??8-Ca*b2XTjhlA+T#?h9K#R?ovEBUCXuOTCN>4986Cc(Zd1*bu1Q; z*Ugk#Ung$oLq74n*o%0J+H_H zxjL;_ay@ZS8a-C_WzJceeENX^dAL3CQk6D&@xA!V$crIR^Xq&@*fu!uP#4+vSu=F; zy3w8JwM;+X(w8M}Oi?GS>2*wdpmo+94P_%5@bY;kZ|2*HK~+*uEKD}iaa^IH64UXDcuG(Qq<7FL?C~9Tf06uZ*(2^1;IBEqEycc3hw$jWQQc79sOwsU8F?6IhZyL;7B_vcAB0K?K z8x|537@YNZjn#3ChHcF&a^jglCt!x}2IcG{b=cdht@toM)DaaHt7Mfek5CF|O6!-u z8jN2F)ii{I%ed|@qFkbE2@bMdKCT(AE?RLA8AZIE);D)!q+(VBkPhSV16 z7^h9@M%q=CNxgA`g`QTXv?X14B5kUy#OfYVRl;MOC>EO)yc--wjm%}hM+B<7UtT|` z%ZS~b-DEn_R7fBh6<&r25;)wNVjIz@HcHpy{U+0}H8sRp=VG!wMaC zU!t4w+~eL<%GRo{{fwC9;L`+(0e)qio=qrKGi%f-#mXu096WRtqfS2Q1hlrCf$EXE zvEc4u`vfak@mHMt5y|s&uam4>7=aeuGJXyGF>W%QljBBQzLV~|;WnD1zPSuTo?mBt zMq)u-I%vp3B;t?|P<+sl(YeoouNft?kQxy8AI7o(*$cSV1fqrg*lI-=SBD_lq0k`4 zwv4cth=et!xTXt@?stf4S~P5f5GW)UtslnVh}Gs5PXI&(G>hj6AlIpcHQhvQAkSVH z1oQC%NAWN;8CWS@?_F{4ATE>9;Y{+q^wkBJ-noN>VU$U!$S2%H*(%1_iPUrpnN$Fi zMNyEeo~r01gD!JLEaJS#R9hY~#CG3Q^-c_ziva}tHejand-o)>o*74ZFjp}eK)9)4 z=28?~r^>Om3k{FEooZaMH&TWx=h5P^Vewhc&JTvnX2&)4) z_sQrTbC!!?m^x@CX%Tw{O3k zC$2H7Ink&Dp_ubEp5k%tlT{gfqV$AQJ*kxN+tB(*R(2oFu_~=VZA^tqa5cz;6L@0P z_-VS+u0$9H)=+iUSP^!NWMhnP`okrZ!8|pGnU^%>^QhwhC#i+P`NxZ9kg~tkbfXLT z#LP7KEF~_)piT74l^P--F0ssDN)N#)lOJAH&A7AkE^)y(l(xOi?tu&(QRYE8h?7%< zWk9O33$^6m+3Ajs6bd}+A#89E@A;?1k)wiW)NV@6*&1hCNn0qfixMilL!)LgRidBm z?&dP!HPEnr>Q~0-%x+oBC()|pNGceG&_`#R72R-w3Oqd3)JX838*?Z4izmvBmL4nC zAiQxT@PwmTs5#+2;np47{-!jsX}s7FS!b9uv3|2$Vq;)*FL%*KL34z&3HDxcJdd@Z zaZ<8=%VRT^ZVc54xFa|2c;W@Oj7PJ#9xN6#x$fb9rnON?oy;f1xEI+3=l#A5X;52E zh?OrBdrDDAcpdtruSc%tRdF}3gLnC`g`iHiVs3D(^8u{pAq^CHU?p{vd=`$Xom)Iq z#nDma?EM?Fu6PUjCt2NUS&z`J1U%I($Lv#}&4%THvsh~gY z_J7v((?Tu$yv23(QUP_!T5K(wH}6?Jig|lwT9S+@@+qoKRHcZb+%ys0Z_({z&Y~4F z7TMkFAr@}LzhzKMo7I6*d+hyN_L5MSV5rWOGbJKCbUH!u_{f{wEk*FhF@8W&H=xr> z*uyQ;GZU=6){~iezMi7ya`PPIG%=IMJ2hjO1Bez@K~NkO2qsc34EGApzp0CBMEJ%F{%x*eGxPb2CE_kLTgB^v=vcR zcTeMYQr6VNK+SBNS!`5#n(jQer-+kgt*PRiKwq}At<-Xb$#M_O!>-DaU3F^E9zeyY!8N(`9MG&IP6xVMlBg)_tvo%%hFM~l>G_i$KXueS$5=#P zZ)JK4s7xXnQk|y6u3S0BD|r%PXJ9H=nA+=nF_4w3oaKktJc_g2y;Am^!CjaTPfqxl~VddrcA z6tZb8uUsgDy;aK1Bvm@g=n+=~dMr1C8E94kEM7s$s(}{_k;>63=-4*-F`vItN6XVIpm+cs5hMODcu!e@{; zmJ^~>0{DGxjx}qC_`vA|cF6awko&6ER*~p7T^Ow;0!Q>p(#v2VPn18*`t?o9p!LjhsvA^7_d*xi*X)<1{Du zN?$7>eCzj+4O5kx=L`5~Y$|UADsryN2V{IblQbt+O;ta88LdDZ-%PJW=kAIHHzY=R zB6H1n3LtL-nOo_j>TK3^ig)`iqbPKD)B3VJ@5yK-qzlMpW^EeNc2ZQ!sx;?jfa?g~ z0tdBbPn@7%l z-~;>1xxvBcPN>{s=&H9hziZC`J{ewZxyBt|Jf3g-)YSev{?pQG{HZGj?_5?*++du` zTUQTGjlM+ZDLQeMFR#ef*`2>~*GiUs;I7|p-V;6;-}kF7!M*42&GW&oL2=Ii$$c_zhjx+Lxu0VsZ!y@n_UmZ$tkGB_4YeArX9Ys)zK7Z=|D8~EhT&3*g-{59_Nzu!1|+0PEY z;mVI+_w=EM%Y}b5y=V4U?-{=S(8RJkv4VxNp{pjFSM3?NRO5tqVDEX|apzt#wZHKr zORMfBSIq8F_t4yOw9K!*erj}o#w`~rl4r{WKFP8>|Mc_xr1^pOefPaTy}{fy@ZmI0 z1{p?z6yxI;VgI5|bFcoYeEfx(yLd)4QZCKug%y0F-Xou|Y{{~b zyYPu?9KEaSD_R|&49X{yP5C5^yDdI(a|_cdVc)(Bejt^^lPym=p3gcwG2q;j zFgJVlwDKU*=%{;?XSX(Y{OheU`!@}Og`4}Hgs}N@Z+fzO|6-D`aA2V;0eaCN_N4cf zf2}9&2EX9;l|S4|`^%M@o2#A;vX@_;zHWzaJ$6J=9iJTQ@=5-u)0^3|?8omY0{zNY z4(oZkGxSOI%qc!m&YgXd_SAL??DvUdr+7E)|82LgfB$+n|2vQ0dTaFz-7bCd)U9dX z{p#wlUHZA~_RZlxZ~O%hP2T#GoRG{Og`Ck@(GXnoh05Cy2>(s zuTKu|d$d+q<=+3r!~0J5(Y96m0uq1Y;qJoPKH*X7Zu(C6#+f(j-EbHFw)-Jq}XGH7xt!^z{80l&jXjXcN?f&h%p_5PY z`lUVBGkuclJlkjW5UGN?9(B4uE_<$u`nk_>+S;^@&Z@1}X8Le^lVte8Tyb96ww2qV$jd37x|L@j^;~iX_C5K;<4W-~C1;g=PyXD#^!|vB#Hq2yO`Oqt;2hli9fzt; zJUa!v^rh|7hT6{b-wXSW?Av$o#aPVM&xrQ&|L$S=WO32wGdRyT7oX&gnIKt`F!`eP z$+5~8SUO1{`RL~Nf4@A`?UN^;Y<#@IvyiZBIaAy16IR*Zf=}X4nxb~lxUG$T=MeMB z;ltbd0p7RKNb9AYe1gR*pKSJw zlP90N>8b5~@{>{e4{P~^Pu}#Tz0*UaT|wg}UEXv<o?ra(%XiRk&qQx-ZtD{p zJKg#4$>zlu@9dMHt3UTtBNV)UotLrV6Pvt}PZ$dg7o@ND$!_PalkTRQl27{Qu8vPM zcm37!NqcVSHnH#t1&=;@CO(m_-f{8++!@nm2*tMS%F7k$wdWZfw+3eu{Rakv@rSR! zAy#svC8tpN>v%XSUFUPAx1+Bvr;d@MJe}#%X|B#!^M4@MCOU zCCGNlj@>$wj*iaMrn;<-&Z@0dnYH{jaz3@Wmfxx`P@_6ut*4G_dRMtrw&R0K{Svv| zEp_airQPKfUGakPy~)+|j$EQ&>g#xE2f0MA%cPA*bRy$AGVd8Cu+Bu7U@rr z!a7#Uj<94Bf#DR~jZiBX-pC6V^kzMJgc}Yl*TQ_2M>*y>_)8G!2VukINZBu+5l#%V zFoPXP21yeLEVO{z5ci0(VO+OCGu$I@abY&BOFG2di_L;__+KR?q{zaMa*1Tp3i(SA zi9$m26e*qfoiJgwpriiXP|G_L2zh|1!$ohBvC6nnh`K>ae*kG2E_i28OayQNEfT-} zrEO-a`RNj%lDqotxQRB=1X zLL2Qy)WV$HzDxW@~P>SQ!!%Ay`b%Mk+$Og7Qv(e4nve8>^7I zO(3b7MoU5H!u!$3y9t_Zl$)w`L9Nes(Rxr57dP0^WX7tT%7BQ_w6iV4RE6PcVXUy! zZWY+3R2=q)`b5mUNCydD$zD=Fqhj*NZ@hz$!2zl`?7X3okO?cwwRKBi8)TIXrHP4p zZNy(yF=@e-N?do5TPWsP%T{Ms!fb8MGM1IE=b_LPMQQvX!3Ia9aPLkHp<;LR)f6#0 z)JiNBZi$eZ#>|M`jLiI~LNVMth;Zvsk5v`9>K7~EixtP3y6IIY@g9`+!LMI;1@ zR7WTzLJ^!MGW1b9Q3^Ap^GoG?7TBvjBdKz(Tq-b{cg1`;w|ps|5A@88lsxD)_kpo} z+{}&`|4#c^C(u~Hi&S!jLIi~KUUfoi;9v`*J~-*+FK>F_=ou4E-W-UuAtsDgR#-}B zZ*bfbLOKCek+zspgetd61yF%x46+*Ok3$!s8}A~62CHA2A4pT$tcRr|m2F5T@P@_? z;S?Bc@>rwLS`$>R!cH^HId`?_(QYMMU?;tJK`Vz4O79(QV&@FPVJY}G!s8ar5>d`5 zaOXwR#8gwysz^Q8sp(T1W~kbX$h2Y7>?d|F_~hy|s^#W`j2bVwvHMlRsi8|CoA?btjTw3caGRq>vcp%4>6z2rOpUVp-%f;9dlr z<9S>px-MXVpxsvj>u}cbg3iu9NtH#4p-={=5>KonAYtu_0utZDGcgao*+T!#BDG5M2i(`=O}i{tcB9#NQxe{J%kQ9#H#OABvoC_YeQR` zQIg8-74uLVG9w&~bxg_=4m{N8iY#XtbkKR$3VG^@>Ug?p#egpgJR9VRL3W^Y^#m?LnhU`};sM1bQHVc|Z3lAp z%#^IgqZRqT=0T} zk^_I+X=GNZO2!%|uJa0tl#arIq$lC+Fn03PG#2`xu}=2IQrhMP8lA=bF4@KvPS2tP z^w+`=8A>hDvrh@E4wz8w=s*C~A;~!+y1jShjV^eGo%iRBE9WT>)`e*AF}ghb3N&w48EmB;u8D5Hpozp1RorAw;^Z)1r@;- z?t!I&K;t$+Y7;&*K#&?NgBx8zb{=Q6oGPj`_!fJMEl3L6>0nsW+9p=WKtG|KrnPP8 z&KscO0W(4p!1A89iCnb>d8?Ktvy?Z>)P`D59h0A&K&V=m8q;i!R?V_XWUR_;Qslfa z5ROW@EmA#}V8O)IALw3Ct-U0*JM%0V+tBlptO8#TzoO z_nu&y4slt!LK^#jp>BabPi*1$5xUFi#{0y&lG{toAkkR^_SL^DcS3u0v{Qc7*gWCc z8CFK&l7ueo-QQuI72W($SoJ)tGP|w?_L~l2#g)C7G>_TPJN*&^*SV9HkDzT2?;t0L zaiXTLLy6AY6cS6_A753fqJSh^M)(AL|V};Z*iZN`;V;vyFiKyEVR+&3( zz2=#_kn$t6gg>bm_$q;cB`uJU&3`I4OWdx|?utlIdwE7vpR|T_$$*+Fd!$FFY~+%C zdWDoapl?u@lhN8xjPpe@O0e4~TV;!4C|N7I==8rWY#Ap#ZfP#4q^2^z>y_>h`bZAC z>8!YyN^j{i+l>=k=eLxMw=_<;F$WLx>^x5NNl?9CMsmrwWoHS1$==hY+arK7$(?eX zRGLmZPO5I)Gfq++szL*?=df|2xt=a?ig7|SYB=>cVP2wBx5vp`ol9|3T~5$oF(iMS zqi&~LT@TVfe6$I)tCsC?q7zg#PUtmV5>lpi^o*0YpK6?RPMSQMA3rBuEp^$XH2c3y zAp!mR!qmA{>Gn9O*`2tgXPe+@$BByIIPEx**d%hqryVEr>NU?!ivvj zpi{`%jIf}(xi?RwAB`Mpe2<8q;_5`q~Us;Yb$6Br)u0GSH zSt)PCt8;!pSw4$yh@yZlNwSl&?b#dKh$&QwfJ6$i=#OlITAVV47wT7zsY*E9O` ztoxK#R^;)>_DdD-MwEZbPC!dj8}mAqszItak4%2Ap#)ZlnPLi*Hfu!Hr=40zG5v@Z zCl$J^LK6Q~>5d>urmKQz%SkkCuaA`qi_OwSt-$z&q#UPR?3L?isxbAuqLhzu^ifrp za+5PFi7FZ?vXPOID@U%qmh*}F1(vbaCI0j;VXkT4c=aRKzUrdcSN;6UZvIks^7dbQ z@9gYt<#pHngORgG_<(bH4|96P;jg;xx(lzn>bi@j{@QidmM1r_oVf0~D-XQls*7|k z5g_6uH}>*Zy>jBJiR(Un-K(a`lZXEC`7b|o;nYPhZ_ll@9Mklbd#^fi)pxz@x@(J* z{?PH`fAmf_b^M)bil$et8Sk%U_YUXR4)5JNIF(;_C1sBc?%i9Kdx!U>k~?J&?#-{= z3ryvQD0{OU-a9-}lJ1vF`iA#R<@?o^k$msoqTHKr(f5k$@(YLeUUcZw`61+9_UWsx zyX@NX<$JH{*GIXpJpZD-@B1|8k)e~%j+_`CzNg%KRlD5I+=xSI=VuV5OVOi%miSHF7WwqJNl{$sy)`)z+QviQvRT^HW_&Vj3L_?zX~^VP3>vutQk%Pqa@-S2L`dEvJ4Yu|meSp2=0 zzV%&4-+A?w?`oG@%P~bB|MZQ==Rf>6jvp@;pICY46~A-5xN`DG%p-V(xArjNIN<>| z&V_dsH{Liu?rwWCWsl6?c;j3#GIwKt+4DDscaG5Jad(umH;cI&k%7=JhrZj28|Pj- z?vAT1BLUq7VYl2G<-X^(@SftvcOJbrJBr*B_rCeIH{MoE-}vTkIn|GHk50bx#@F6k zhA@D>xjB{l=C(c?1T1HP6e_!nF`a{IHlXRtxT)t)n@+nHdY&*N8mmWe1YR@pZ~&R zPdG>7%g%lMKY#x7znkcv{{lji``XvO1{HYhPyU1CKF?Y8&;Hxjgna&Yfm)8F^!;uv z_r$YF?rRVQJIQ@v2e~hQ`OCjgwzfViH`U||zYAIVn8H7)I#O^?*>xSirh;MBW&dTC ztNp7uM9xeBgiFvW{^0Np5J;EWUcy<)_PVm+V)%yHNII+O`K&$C)2#Tq2t&T`!+{k+ z=KiJ9UimFOSnF4;JI+;la9Y^}(3M~56^;tLYwMjY*U9(ce3qM`Q5S~i?j4@xK4v!f z&+=K5`eIeKb=X*|u$Vgaf#oooC(KKd%gNb9n`g4BjO z)rohaf6CKB*Zxk)`lq~Crg#}oXes`bUsC)CbgB4iORbxps|0A@(jfQ#A;01J$ zw)S)k0s#mXb_JNO0AywF@a)usil}L4ytx~y4BdE3sqJ>nomP_eQ*hdd! z4#tfZh7IZ9CZjA`pgQNMB$5E#0UBm1qIg{Sh#v@NE##-!7|^kr>Js^RR|emRA-~6s zh{JUlC%HP8?vrTDpbIGl#|gMF27^Y1Kssy$9Ami%yW+m&}Gz z{0UNMs0AslFi9w^QyWGls9>YwDcLO-s`RYo6gNTAge+Yv$p;w1Vvpp8Q4>da1$h-K zL&Hu`K2f;Eb9F%vuK2tNA2eTb_8XUolgvqtJfBWIt>B^(Vgn(?Y)KNGYs%0F(9~a# zdSlH@e^2{UA)a21d*Ku07E>l59H#e6Boc&>;sKvBSZbOl)jk3yp5_S8A%MO;WZRSd zw&V^qRQwL5A}DH9ZBD2$R7}KY391N84FIBr+Xbdoj3ikr=Vz?K zbi&CEVcv<1gdA^0$=fCY-T`dJ^{%KYrdP2Vm-|-poRE~zm}^$rk}mxYA52dkQKho0 znmXvBB{js#Ae9&D9wb7Yn*i+`Fbrw}u@zI(702#G8&5gvd~Na$2uiJLVn>saEmS!j z2_lqGCpwL?lTU2Z4XJJI1C1^`Tn5ONir1o<$NiQd2pk!OTDf(WjG}>n<2>xCpb$dL z+`5{W1+?=6VFKHqk}8OsjHb+X_k)!1lRRXP+&91^j};s){`+E@!*Oh@GD z22le+V_@KeWSMiB#!6)SMFF3eKgAGN;{YYE#HJfK2c^0RB;E{}6bB93;TRTf;eM#Un(U2%c}WMWoy)I1{QNf8bbX5{N?a6vD7^5f0PqSj4w^uVK!QpXlIVs&*#gQ`27;v+ha&N;TcOh;svrJ> z;{-m+ySX*V7trJK{N4Kx`Jplltq*<@3Gb2VVBx^N_Or6OPaqtdmTN3-?Be;UXWFn@_ax!+{kTN z@wzqBN?EFDOujU(0vi$Slo_g%Iu%wa?Go8a>0+W;Md^s$~f%=@#n8)$S@s z?qv!R8#pV@o*2sAY+R+|XL>21%O|*RJXm_i6#$nRZio$Gtdv5TD}Nr{QmPLQ#L}w; z`zeR1VD1A-`HX;jtDjvzglHQk+-qq?2#GL-wN)Fmq{uo<;t_gbfj)DR3wVNFxqEz?a;Rp_R)?bJ&oWwL1z8LE6~c&N4pP^oojU@d5p@rlue zBtmrcA3yX!%9@-{V(xq}e#^lJ%8}->cbC!!!V=tr5Fw}p8!tWQAn=p~67mLi4J$1oMNN!3@42teIBO>jDu!*0tNJZA7h4hxFxk(goT3VQJaC655{Q~PBoVC z1sx_(na*lPKSrtY)N++-g_)fxg}8{{Sm9iZtzM_NCICYinSvfNZo4*%c%tCq5`035xk$4 z1TO`eRcI);JQVhWm9QjMbQ>H|nH@7v@k-2zcWG?y;SZf~2bsJY?(V#`c4BG*v+%aV z{2a=TWqER~1kOxwMroa>m6yBn)KwL>ltJ=mc z>zK1HiYQ!;`N4v>PG)hkMc?zQOYR^KU&oCYmgn`-`2kw4Z_bUnqCNFztgLVazpv77 zB3lAj`$)ZGL*wM+;GsjDY8E(6QE1@@Z683>_^B3>bg5DdH=Q@E174doJT>%Es^-)o6Rhh*emW1PfUD$-OUHAF!+dzcLx^-n=L<~?L6z;k9#-P;=<+bxu{|-kfOV)`djyF@#?Ub zie2*!cW&MB#XD#ewZM%`mVk4m=YlEnd;Hh3{B;XzQCwLq^_J#z(x54>D^m0vWVc`i0b$)Fi_%(exLe6pBo@@PrXL@gDK z5th57{k)Y@K-I@mq7zp2&YQDLrMU8FaC3=!@qG-raclW1rylb2c$tbdQj&Rr!kEg@ zCSJBfsC-eF{%f#$aZ>07E*7fh_0p?U_Q&bGFpF8s<`AdJz^8t){E{kD@yPJJ-h=IC zXBS@OM)GoY(9H(TEe$^BWOZ?C=*rz*=JE&@E#wkD&Ff4zU*+7^hC*!3#x)>!DwwqT zXUt&QYLd@7xA!eLAZU`}{oa$#|MNgiRNqY)PszNu<_sI1owp2J6 zC2$_&#pl;!N{mHYBcB*5d1%B(?9PIh2eNXyKeuzyp3xPCnU01r0;g=PJg_bws{`TM zUS?_>7;tPXa#KTzm~lNi#Mx>B5kYRRgVbknDp(@Zseo!S14<&BST@1)ekJAPAU_KP< zu-@*e7z5dp;n-MwmYvu0h@zP-Pl<)Rn+JI9nB)SJsEA8`7+GEvoZf!Jex?jbO_A}k zp9?`(2A_KfYXhz+>-eD@=fDpDpX8?^5VL||lA5E|H_4P>t`)ux-?QHxd!OE@aMqL}UgF9b09T%=d;W#^taO4~IY7Tst`w z7h%kErtzXb*#&z?j~<9_fT_06l`BIr&LKQw!20C6=Q@}L(^U@n`PL@V!2NI1OJW)4 zaT3rHP{)-4>Ina&G5?i6zpwGkn;)G!`s%;D`R>0t{*@0t`uE$~UqA4`5f{GZ-n*ap zUyn`=zw+X5{^P4Z{@!=J_Mg6e@PTiC_Q;=p?tOps4+rJx#z%(d4>Sw0?7n*a`q2%K z%B|xE4m^T8o3l4Yw4>KZly-+Qxy$@#3#r*|d1W2M+N53d2n=r2QoL&j-V= z{ONq-^RNAj%|CJNm*by&)90Qq|H8X2zvzw!E`QZsxLf@8&;QLwr#9@``quZ{aqcVj z{`A#XluGZob=%DDgTrq-7|z5W*)<<0XRl34TgwLzo&Bhsy}eu>-y8>}&0+Ml&D)aF z&mKJZ?Op4_O{q43KB&I6m*tlf0>&wg#~>@D${Tk#C? z?XzE#WcQ<+3$wp*|5Z1PZ9e;|g9kspF)nn4_Ez=uV@_>?Va7qW3%0K-*Ggl_4S342 z$R_9~i^?@TU*??14+Kk;?v6Xs@3l@JKYmqlKpK+^(hwIIJtyow) z2XwYYB3cQ)H0;08O?(MJDuwhLXdc1$xbeN@{9zu}`j}1&i@I%*8MLC zGMh~NytfIe2BVm8LW;!+R=nM&O$JAFt_Rb|tUjftO^Pqf%q*{p>({zb0+!+x9m zD8G@mJS?(Fa#oK$Xq$g=HbKh;wA-}Fj)}%3Zbc`PU_xHDi8eV3o6snyIETbwoq|9Agt*rb=9+plkz7f9l5=EC`2gum_KF)32Fvg~ ziMW?jzAU}x$7DLecTN?$ay{5z{C^INx=mdQ@JUUbjrm(~^cZCU=A zpB11V_w-Ch8CT{fII{y4)bmI#znxBNO@zIF$F`0f9)4&j^jt;$__?_uF zDhN&!@8^SjZi;|C{COvtpQh6kbW*+!o(pJxx2NZ>@SK%t9;+wiw<4@(v2V$1B)y<-Er1ajxbamNF2d3lr#0UjM86hiQm(u)C zkC$C5y|l9i0$gK*Z=s0QynGN_EPI~DaG}tfJ{OT96qV|*by-#41!PF*avY+(Xq;S@N+N8adO_t~UJ0z2eAsB%)xF=rxo;8iF59oz=QsLr@JT#_ zo0<=sszYA$UAa{uq&WBXjRWN#K!W<1L^{QCPTk}X1U-(W^+pU(K7zu2ik|B8|=Holz5g*Fgs(AcUIWWeqa7pjI(8u}yi>MiN`Z z5gdLNzYH91UqPjVxMc8uz-5@==)_K1@GSo66RiHK$SFS;8tBZ6e7sot5!gL$eE>8M zTD}ZX`4-Fso4Vd7!U#>DafB9>UO;&~fjs=-iX#_G2$#R>@hjmET;7Bcs2E#tyfb3x z0#U#`OT&fq)e{RGG-BJ8jo6fWCf%O%X0U`)w}t6XsVv~Aff3>O3R(2 zFfK#2)+8(jUqY)90m|D`6}~}KNU7MLP6!jRA}-_YCV{XPQ@M1<6U zP+f)$E@AYAk~8hW*J}^SdR{13&H(ILmoWRt;jN>U3=DGb1FJZ)r5F~dE4nKgM8}vM zbZZ3SVzJ8UI{ck#F&9VnwA9MdiRF8&PIWqoeV~&^MRDYBGman&q<%J*kgnnu&=ga} zkOhdZt5wWNVp)Wan0b-`$YY9rZ0G{OF#zspK{2E;S}Hn2O3FL zLhLLM%azNbKLU7!zqvdeYn~spw=b8xC$FIyHPZu0^`}h{D#nue;(_18zi8DDinLIXeEPZ^>iKj1HXtD%1}L?x5eq1WN5?;qm_b)Qy|>P zmIQb74z)B$hGpMKWf4MZzb7(@620^ThfvLgOIEFB07gRSJ)soZdl9pveuqeDfr zJ!Dy|q{*T*6UMtVlGU(jIL$1>`u(hk{dAPdDUD?&gu$2`roN~&aciY9f)yyW>!!n* z>hwKBVjtX6ir*60@LZYPX`|S%SH(q)p*lEPF9*HX_~FXVW26ZfHWV)i5=^GF1w}iK zO+z&q1*2sd^a^yHoib9Ji!oBCRVmy^E7TzoY6v<4d?4~9EICgj{8iCoPMlI5X#zKh+SGbVLQWF2ks2_K zINpI6sos~wRjlC_8I6eZo;aQa=Ny)L!Q(a8H+c(x2AIVk?@#E`&%kO1z=DjjtZ$c% z>5p*z1Pel6%~sCOWD@3?&baVRk%68}VB}3wktS4T#vCpRVC2AQIWQ3-9Q`iu9TB0z z@jv5WiSQ}JSpFxY4ndi+-8D6oA30Hoz-)D3ffI$Q$S_k@1Q!0(4L?Uc^EbzgP>PTb z0{|D`_OiObPbTW*(@0=l>3YVvdBL)O$5d2?g{w(5>}i=x_8iz;xF=|OurAW2TTf($ z8RWyPK@Tivms}!;O9)#0`Wmz!=x<@jCbbQ+X@;|U49fs)+>#kn#J7H?D2oAV@P{(k z3c>_*yd|M5L5}Wglp~1qi1A#kbxJ|NcEiTAbsB(8@pP7x#j?apfK&4rh>T>cEHYvX zQ-WR9WPOTP<`{e3Sp$d7iA_9|NBvwF#v_GztRZ96SVK(9mFp5(W0S`o124fMKWlD6 zdO!sO9#rH&b}}VyhD7!bkd>Y(Q;KSE5=oSXMDNHC28$pA|cczmIHU#)&{>{@b z`!{%yG4h*sY|F*Le;f_@i4}+KbO9C~Stw0!Q|B=i-rxiUMSVkPB0{)afg=GO#o@vD z&^jaWoQre?;?+(F&tF)&mVDY-aE%UN5F?!TA&jsThXSM;v7DEC*%AASEhdg>(W5;J zNLnUf0IP0~vjnLp{sf3B(bw<? z(1%RU=qcT0@g2Y0E;^)>3!Ibyv%GAVkHRimp!lLXOwJup&@7>pb|m-;7$xG+)I_es z0HUl7s+Ko~OwXpmpU?)I=@SdZrs9AanNw|JSjn`92{u`mhH_Y0K#Yafu>lNqU-NKe zuHPV+A@?|{sHwxvk(BUdoK%8C>(WtnX^B7JREGg31I%Mw6d3cQRM5=P+%;;N(Wt)X zgQ3D`W@rml99f@IW2gm(O^qZuI!FQ^^EPl=KTMHKln`JewGa7xOp4$(DGPZY_NZED zJBZG85DKxw#ju1u;+Bh>uqy^)8ddV<6DFDPUSTf<%=Q#A>wf`03m$J^^44!ZO8+H2L_@D@#p`;Q2>oe1M%(wheNF#tyW3j*G2rH$1rQLV6hQHK69 z>pF1qmjYG7IandZL&pH7Z;h1Ty&eO2lIvke*$g|f!iE16y_1r9l7^g@q`+)lw_q9h z2i^}HO6|+7fdR}tQOSZqeS!jxx%AK21-QdKH14gzjri(@uzK;B-9VM&XZf^pKjx;x z=svMq0|NyPQNf5_?>FEpwxwO3m1G#u(KxsUq#6w^sFF%&2sh<<*tK39l36%7?E{}) zljs~9&6KC4Y%!kk8XuOhPaIdi?(~4OZb%X_|*FDyA%_}cT&&wu2Z1HbjRbB} z?~XV8(whfMckd2%?!qp2(6O%e@L?AZtt~|5#&8M!F06t&RWV4T5Ekc9o~})vKUg}v zQwqC|UACdR{@NJrru^4;9Q}t^?|#SnU6+4w%LS!18#nKN$L3O4dS$1d9N0eBaQnl0 zCiA7@2W)`O1$av6Z4#9)3}yeCJ8Or^7oUCkz-^H!Ks9TAN_KJVDup%HEGqoOuO58I zHSe^W-*9m4?bv&Jef_Z7WdB7?H&<@ldry$sDa;J|JtBnUGXdygAPt`v3t7SlxvL{Gs|_o8fG#;g!T0bx&}54r(U6lHq?vxrN-R^ z;|vyyx;}jd{bXkpmG@wAt`u(II$@E!WUsDTW|&YYAik$8N`47By*5GT;jD%V#=QVk z4U1s8?;x!KG_^^4kxh=Yk5IEY?VetneD}Mw$slz-c+EBCJp()BcxDr02LQZBAUx&t|jeI|8=WGJ2U>&#G1gp6RC)6fh|7kz*Hp#DTe&ADH3CDAG z%GA=c-a5FbhvU4yeloa&slNMN9wxbC5AIanam{yVlfm}=$9zB0zV6GR8O-c?;t2$L zq-w-V#_6>Q>Kw4>v(nCuUHvxEvCG#vwTU0Q@;1r($x=4y9lKUzlVXuJ8OPYQ<=;k6 z9{4JU(83Me3q-)!m9xon&%HFqt}3RI2KyO(okS+n{ftxcbcDO(%9M-`!{53SAKV%q z#m8%b3li*-WJ6@4%_;wskpz3|!U+2#@ALAq=YKi`QmzjmKjy`JeV&=0m0&qPO`hG# z%jTb7f-~u(8J4M!_5+W;6AKDaXz0hOUGPvCFSE4be9{-bT@L*U{0rZX$B1|vi#h1R zuQ2}Y@UhPkbj8El=H_2D7Db03PxnVco-V=5$xU&6HozNM4a=ygztc{RvFNR{@C(@!EjgD~Dx**Y5I-#Uk>>rM!3*PZ(C{ zy9TAym$=t@4l@}-zb!JnW0Tq0>fS;DBlzGe+sBR_ZGZEdOomB7k4^BI1K6ZcD7FU% z7>^lhYLhMhlUQ|cpgX!4UI~)+Z$E+ESjXqvmCC@53-FEA(v!s(Zh=k4VUsub79?re zR}%CRj62#s+P!9HcF6mwO@8|c+T^+CuyGXoDraXqHo+Fte6@2nX@9Iavj=ygfL$cdxg}IXkX;;g;uGn1j7=73P9ku78;}8Q9T!PIc;QnYV@y zclyZy_VS_+9GO*{bjGfBI`*Z8@ir+BV(d!q=Q5iNXg=`|`<;(@J1!Nz2xAupNx;OXa3MGQqO~b-feQ%RL2A9B+m*mhzNkK0H6Ni8o~T;8yli zAxHp}6)wu^%ZxK3d4^*UJq(<_$;oOmL1<+T$$I8!P0(LF@YV3;U@oCsF0Xu{>c(?@ z*!$RLcqa+EpAqw}<@Pm#u2rU=@~hw4N=(zy^XD^SVh29r9uk{{M3*+AJT9Z8>9rc9 zrRka<9y8!6{4rh^|8CtN0MQUDFXr*qzc4ooO zAiuOuZt1LHH|t}dZ~QAbb&Xa~gXu-tSYQKm2$qg6NzjlXN~&wYbNFc^aH;(D&W5A` z;+lFs#)^&SfJfl7NN4e?H^#H}qquQFwoXh-3?d}-o)~AGfEC4~^>2n<9ss2YRH-nCf}30)C?zu>&-mSw`sWJ zRV4Ib%vw;ll$SK6M@rUP6wd~-;U35iR$$Eue3OUQCF&Cog77uhScV|idm@&BWQs>Y zAe9k|#+w7I(4v+Vu1x)Lp5z$b1q|aRk`U+;D=+{!`#plB_@M+AxH0GrCNc=Zuogdn z@s(p3NtKV}?-#=51mvoQ`tyl;3VwfRhMjalY$v6c*u@c%xK1q9k%424@yZD*3Gl)z zBMX;_bup4X<`C+POW;b|1=OolWwPLb84P~ZCa27fp#}ULo~_(vEJ*x8_v*q?K^AWw ztj{SEtnu9(Gj{sD<;%w)!(LP|+*U85x+Q46Oj(+&3?1C`^7UYW^=-*l3sJ5Ujca(W z=um&w2WSbXiD1>0z`$SdtrejZqEs08aY}(xY9ozvObR73-+%%$$b}JQ_|70l;u&Yz zn`lI*kS={OK>5oc)E5p5V!NDKRM*eP<-=VLA6guTlBL3FP%STV z4xt7y57uR&llOy8lDrVjxD&J50E(W0^MRZqENc|iP!WsvI)ivSIZWT-`GuV;LNyq= zv^Ys(hl4+L638gnxQv3kRxQF55x8k94r7=F`5s&YhIx{}=(B0=?2sxHF3mmXh&dbC zv5c;nSYQOl0nKU)!7KM68#RaAZfrmK<|Ga#z%C0H#08Y?UWn(O(Gaiohk~M%7EoN! zIDAG=EG`mrbS*r^@!FmNfNy$UA#@#y0Hy*#JMGI)EW1;G}7GD<@VUZZEe#XaF zZ)AOKRNvV9C$8qYXh#C@JNL%5FW#4i2#yE@B+CV z!ywgwCSFF04O|kJNW)6xB!j#mGMYgncH;2w4@tq*#*~5bYUpR;rEl>5y@@h-^}+*S zw2IIkIQNUvwap|mZvd}+087VHG<4=17PbeVCEG(F;<+r=KvQ+pgpnGq8)ZE>7KBR3 zkvMLlhHnb6=stW(#xOK;zTnt5f_W&(N@JW7DptN2TEW6z!~^G34A&wrMtShzT7`8E zR0o*=9Av~X)X~wLVz@4iMx&TsHzL!5g)s`+?SZYt(VUA7STs2wg$Ga+ocB(jYgZ7ZaVdl8@}-n6p*NJ8B$$lH`GtbG z%06V?{TW!g%WDBU#99rRIGMotK0sv?@z%QJkRR<=a1YGY!%j31cf}t#e zG0=9C1Uu}Y9oVFWD1d>gO^kaUODT>dp@)Ao1A`pEGu%8h2NK4q88iuz$JiC{yz8GL z%WMJZCs`t-<4aLHjOby|{l4uG;c1k@qK}RR#vzR+n`BbUEKVJ=>$Xa;CnG29Fslwb z7y{NK7^wj|4q*G>7+Se8);YcBMry}M?NS>N965rP7?(|@8S;|jT)BZSc8#I6vNIeY zV`FR}5-dc-Nan4LUjZLPC9QB846YzUPc=~7 zp{USkhL2%CBeWh`uatSnKyPNxl<_8ZXH&Gp7JDZRgqWM5hc=`g6FDpaB-$nDE0J>i z7KJzwER}CgM1OM6?vE`;h01J8?o#gO8Fp)q&(CieC{-kw4mN{+*XUd*e(TW${zW(=1^K#{9&dZo*4R}sLoI=4A-Q7`BM~k%5Ht+}&ZwEb8U9u)o680P=%k=} zk$GS_uxc$Ig<=49vA~d|j6Bk9vnjgb0lxM<2bph{DNNZ-BQP87n`a8uz#2Q$3T&`z zll{Q1Vr{k>*}6@3Vcr$;U9nz-SVIC`|3aMRBZ`YED8p%84bQXn_J7d8q}8=S$5e!+2I9AO*-fs97+42s#&t|>ruAru=^R(X!ZXg(4v z{0H9(5M9e&N7yV5tY=x=nTFG!l@IKU${Xe!`pF9r6QUFYU;^%i(g&2im%23wU^!9< z5Of)GhJ9XZPZnaRE7BXj&{zvqmV(z*Ip*WC`l>1hh9T>Cjdi?Hv{K&k8EHz(V6Yj` z$yhk=A~e8G#xM{fWuR=KJ&ZnB126G*gi?*?%U2!g5)EX-Y?M<_-t(CzkzKe(S9Qx) z;i1~tgZ0vgwhS-EMU3Hst`wHbD_6B!r*n>@bsc(h%3_zVVeL{{H*g^ z+NefYT;(4^pL0nNwk|gK2F^F^ZSnR*UJ*z`IYP7>=3Ics0D`_GMY&=<>cld3L1Vk< z84U5I!>T}a1WxaxtB5#Pw9dtt?KYhgd@e&CbCLQ@7=<{eIbpw?f z5F9SV4QPYm6M&naK_bjG6wp!<)ACXbDCh$h{?G+75()1`&|95x9_nt+xdn!sp5W&6 zUZqnYZDlI-Ogo!U&Qk-U8VgbDup@#WE=iztK54;C01qoy7{f`;B2O|Fylm^vM|50v zJB29X)d3^Yj0|%$>xbT}vXAAe*;JRU0NJkL+@Vtce@6`o%-XFF#kTYsyB5P02z*sE9KU~PH?G*T zrJvY|6A>%Z<+U439L49#%{B}${X&K%%nr&1wy{wW8H8 z(KT0o_j^C|h97$6ZWs$!;coG6XFnOUooDK`|2_Bm;hpQx-VmL=&Vljo|L*+n{_+3w z)i3}4fBp9F@7VLce}y}y&wc4%w?FlJm+b!K=6?vC8@Z?c?6cTvS-;NKivA!_v}6U#^62g;@GwBx8CwYPrY?l z_$ODG%YJP``NE;k#Rsm2O(wZ-5gHFmje*UZWqAEX*MIWY!oo*O@A%&LuDtf@SM0{D zmaU)zw8^f(&Sr#n{LZhvemJ?DHu)utiKTD;Q~ZC+GlO6F-gAHOv7h<#PksxxJWuTV zsZr}|O1DMhWf>Z|q-HoZTvIyuj;rr2&u(KQ)qZ&Y_T+$D zQ*v2eXUgAn04KboGON#TLiK??a#-meu4zmm*xPvA=T)iX^BinnbrtYg*;GvRy#wondG17bYo4z^T$p$zPD>eV@8G(8 zK6Pz+ftqu(E^d(*Ui<)0^&EN#jU&Q+1 z^t_U+j$NCO!uZT4x`!%bTjUp@?YvE9XNy?Dy{~=44Nw0iO#HLB|6I3eQ~bk6j~4vV zDT{1^_5G<$1_v*>#N~3B*>m$7fWCxmf_3qO<-x{e6v#+|zTTc>b?!e#oBXHehQ2(A zbDi4l9Xq(1KC=lnHmXfn&*l0Fwa{+21ZO#7b^M8RauhZhJdS*jhWXFVUIm-9VUs`q zDg|LDf3Rux=6y$xZlq0e77?B=g_DRfwAj?3t$tBT|0K*04%md)D1f!kEUZ6@a1fR@kaH#5BsMFk1^d! zdN?}q%E7!%o_h|boFV;0d*ekiz_Ba-_7HYk;2Y^1A!rGkbjPmBUfQJC$#2JwZ9jaX z{8uX58I0pC9}M8nXM`W)anjV3;Dw^!*U0^iTd}{fv(GW*$38}h(sU7?!O)Hv^VCPs z%j@7thBI{+vi!OfzK<~-G>yOh#<}5-7(B_ubDG~yBcq*o?t}L>74ErAM%5qY-b=+J ztaIs@$vE<&%4DXi3XL%=@%sd=1fIiADJ@&4E`?xsQ%f1q%j!JyL~+(#T&h6!Rm zoO5T792vZ@{f`+%dFbGZLfRm9x8my6Zl61QZM%IKeeuHg96j1ZT%mpB$WcJ=_|=0g zaW-O>&l&ak&4*KfBRE}=$)0!u>ezD}^?l-r=bn4vh0G?rt`pB}(%xI$i)#yP!gH82 zo2U%fB5xC7gr#kQj27EOZJD#l)kEK;iQ8?o7D>)JdX)Lx@{+Mhp|FMz-%cKIwj~qc zB*a-MkMCfJ{RGEgclrtO%qAG6@YMim7YghroU7t=PQCx|d+2VxRq)QcfWHwYe&VIyCMe#Z_LJ~o?I-S*RoH}O_~(aWG50WO6~)Q#Q*;3yPE5sk+kpuSd_Z>} zqXh=K4{eqVkNL2R^Ok) z2zl{V=nVc+uq1h_=Zq;Qk-}4T_<$P5u8*T^snUTe)GSS+(H>VfbJDV8sHkis4g}2` zIDALk;771lJux%hU$vX@)32Llli8(XoJ31TV8-dP82bFB214km$Vk+(4#6(87>pg= zY*y zK0BmOfuRh`e2@x^4yEJ+XgA8GR0M0Vgy-S2c7UOyZio~G%V-jOf`ahLELTsYIT+r) zZ4i8{-fj%i%#5b!ae|@=Q_*P~j*=;GlrZIhsER)2e?M}x+QO}`iD7BA#A#YC4e%u7 z1t?hSFZLdlD^N5P%xGj*M32B#rZlcY>;~|vL6NTS<8qrAl|W5|Bjn0BJ)d_?maXkl z@z%DB~{sR8Qp4(s=M~C1Q6l4na#137z2ax8QOec1!z#P;gJSS$bWo11us%bAW#cKM^zrGUFFea-AW|h!kuV z0GYdN_){4};0zpNLlfYkD5Z#@Bkt^HN9Y^;B3Xc7(C|}mS^geNsU6SAgEVUfdFBN# zo()hNq{gu{O8~Nj6lUD%2tH-u#3u(1VeD>zc;7N~UA)F85SfCC$Pl$!VEIKihx#aZ z&tl|6-Z<8*FeD=w$9@AAl-t4NqzM+s^B%~G1ps(5=Pzppc{dQ1g0)!)J`l_I+!>?` zHebPdKs5Nc_Q4XwDz~%&*!912{YR*_tW~hZ3@WAHY z7<^qg#9)$qx`K5IXv^uCWP_(crf7rJk5J1!=*N!pYdkKKQIdf>gxM1k7i*aO^S&J* z6A#zp3k5KeU-&u{A~uQ;Q~J1z>Xs{5JVe%28A38H{gc3Y0qQaV!5UmpFt7Ackfosf zX-F^a{$(C0PN^u-3BVy9Kj-DL7OEcxC_E0QS)?xb2+&-Ywq%H3Ccy&SI7wbM5@DAR z+Uls-EnMQ?OYe#ZTZxS@jq5(Fi#0 zCxuQRBV@iWPKI%Ff)SI{QFeZQyBX93nxwh{6U+ybB2A1a(8_ecvC2h7CxLL5N7!lt z7Y3sc!HtWFK|1)cOV0 z)=>n;CJ1{SXfvF=2DGw4U15L-J>Otk8`(H7?Ew3L!H=t$3NnrmfSZA>hB60lI=rB6 z(q0BKVyzfWjXM)cW%no_2sOdHl}7VT4#acbhKQQZkHI_X&n`##*lbWxG>*VN9id1L zr=wW7AzaOy@yJ87&>$o`4J>l(BFc#fn!7TgRNp5wncg@Yk(&rUwM5aOUE4w}T2QM& zf5wO6al!uUFve%>VJE2tnrmpWEz8B6F^xHgWCX17##b+#2Hw00EUJoRKdi5 zwg69I7@%xE2-hhdf<1BDFnpb_R}hPLzf}XH1O}J+RE{$k)eLf2ui1=4Y(p&Y#BIhA zhPq9uD$YvS(tIUyEDpeQGIfggIkpd933VE2eFj~|APx4^v>Uxr$l=f(c9J2sHje-J zGw2Vvv?JLl-siF9+9WzGb6BQ>s|zb+(Ms_|i&aM|6ep1d8$vT<@uy)Gs2MFj&2}rd zpHhiWqHTMCy-gbIdg)yaa+74c$jBJ3YG~*XO@JF85OEIQiG=7)f~iAL6rc#9vqUT= zPH3C~@9Sg^>sk#;QGsb24kgCVLo`Z1?ApYWo%bL=4Xo0$VZ7j3p@gi)C{YS1(+Qx% zN5}-$c%w)B2xOn8rIJli5qCfIEPuTl;{Y~wXJV^%A(3w zqp`fkKmcs~ss&EhD97L{QJl_%@S_DM^>VX`2-VdLGDC|%ntA-#G`z!A$W9C4x-^DV zEt#u?6&=*31Ev$|1j?OIH-Hi^4-Ny6m~k=nEyg%Q`$%o=?bzMX8Znd6f0718V%C4S zs+-^fxx*&GhBz)+!4NSzZ&;Zk+Ic~lI(rZ&_tp5-!KvusMX6+MNLTKCkWICd(UAC^KaW^{TE ziAz$0j4@XhYh++9DmqMjrEDv_B*H{MJ#+$E{)~G1{CSG%)VLE^IfF65dfl!)W!kgX z)Kfj<2^OcN<(3%A94}plmKK*de}P3R%4pSPbuk~%F!~?%wFi_y7{^s9!o?qWM)DCI z*YHj!2TsG=2j(1Rxbheeo74Es&&n`(1sf*}dlLQu>KY#!9>bL{Zk0yjfs(;(kJj!UxwHdDXm$lV;1+(crL;(aq7ACg8nDU(Oic7Pf%cw|pq-XoIEg1#K9} zst=&(q7zfY)G8Q|d;S>jh5uof4aI^Fbmi8hX;)E#1mlbz7<-+pK`&S4Fd4={Dd_K! zmNm!~8DH4($xgG2EA1&mAcYY}Td=fAPF=vax`$wtpv4$xM83ucCq*ed8e!8^;J?n*gzxq3qmXn^d>VL8pD^nh4OMOQ%_Ak4~U z6qT^1M6i=E9peR{Lx7b4FGpoW0ce*DB1qIqWrWk@yHk-9!6w*Vw!vy+j5xTc>LyiK zDIAum`%s(Udek7f7WeFuY{TaVW-dg9@dSA~8m^!&e5&sOH{BXo_oO)h6+j=JK0^;5 z(ev1HZr+|wnQoigvL1^XK6_zv%N2#GV_+D5i%G^E4jbGC4u^a>1pu)9tGbzEl*H9t zs9SKG#BbtLI-WimIuowN9dH!5Qul%hZl~`myZ{P0O%N7OO=R8RGGYpWsX1+s7-=D> z6d05XbC^hKxaq)El2_~7aj$V(QmY!&3c9%28q0U&f+s6%$_>>&4?PbGkkP^hQI^T! zhb*K#EMgfZk$UR|V|wuv!;|QRN!hjGVcA*&2ii;YmUXpid|&Z0snv#gy^5?R4cF9a zNEDQ!+BUHz%+o7}@RDom_&ICCXVIeKb+Pgx`~4*c&JH|=VHI=X4t}}<&{5-5WPP@_ z#eH$C@Qc_Jc*xcFyTAHt_-=pwubjgk!TtL$c=j{D5idOO$8Y>l`LVm-y=B+WC3n5` z>dSV&;iCPI{rj6Aefss$?|!JX+1)c);3IfgBN-ULO-mtK_w{EF#JevqL=CNLc$bv7 zN3lge(W&#&HsK?)4rn@gZtna~&R%}&GoNa{dhd?i$3BVY!k>Bh-Otb8_sr#&Kl|*V zI$*!sUmzN)JV&C6cLFs+_ ze+m5rcJlDpfdhw1&UNsN{{8xeVg#EkuIh>8-gD;`**#X+cw5ay5!S}tR>N?GesUWU z20^JbT)X4`IN3J2??;C1-Pdjz`qs?xx4!2<^ymB5Zu^PXkL~=C;?-AT1HxHBA?+tg zJP<~-$>*Oxhym~A5;_)vHrbWLb~jq-vi*cl*t*~}_?-{_>IYx*p>f7(x@sm^S zA4Bp_|LwPa_WqBY{n6iewl-Wxhb?LUkdpQjmiex2<-0e}@80#(&wp>3$7lCgGi|fhVDsIB!Spu5R(;7Gf&MB>@UyV(m z6s!vNHraz6Q|*bpd%aEe?oDk1mh9Y0Z>*}D&Ge@_yYunCs=dm*oz{qk3zhBDW^ z6X!T#pVn$@Qr=V8SV0+g>_a!$gnhAujp;Q`kr&xH$u{Xrvnrdk2L|^5&`+@2GqVZT zTJsFPW5>8wyK58KLCIWEPdK?cFTvlDF+2O^FLRIarq^>X%#MB6v`^Ge9{W^z&%{J| zkJ`lVMR6z(I{Fy{Z96BM+iGkgZH`^uCa>&_U9?HHn%V@}W@DGP3BF)DkBuxRS*GRt zN#!3fcFoczXTSfFOK@!G-fONokxi0|Dtl=YJ=aKdjeQdZJ(D&$rLk)g&-P;MO}o*2 z8q>ujy3t&*mcEz~;&P*0an5ukH(?se>2L&o_y$3}kBJcfIE}|GO6Oe0 z)FvJWl1-*EpUGDP%HQ25srez@&>!HVNJj38oJb8nLgLix_tTQ3W%VrN?v_buWJ@3B zcX&=u!1c6+)yl+p&@LPsAIFY6-RnP#4evcOv9zn>{I{VNPN#<4LD?3T9bT&98(%Onj%0Z z@YMxAXvjhFV>m)O2RJ*JrG~&C4B*Zx+5|iOSFlN2XcL}wjA{?ck#ZSNDa2wVqq_1o z(Rrt@T8~ZeNOy-Px4gGX_qf~vn~Y;KB&OkeXo$0K^49R~k~TS3I5vU3{JMjGhuY+t ze0If;bsG-p)vB5Z0)H@I0@J9%u^l^>vk8v)gCg4U)i!25Qv4XEL8@y!(qD_;By94B zJg_ta-TCX0lz1eK%50KxuFj`Tum^Y+1w=pLcSMFCT#Zfk?!&p8H`vTNqYWX%n=@*2&iAIEO79 zjm~}EZM8{p=ZS1`1At=}zH`x*z1mNDZ196VcIkyQz_W0RP#|9_-(%+#-2VU#=cq5*keW-K`B|K2~@zUiZyY62!Fodfcq8?`8)lJSop1jz#U6L;s z_gC^+Na1GW!|#s%HyG$C%(uopXDv;zg0JteYS5L3P9sV2j%Pce)daFRL*{Ghx)IAj zrc?Ek$bqB)obk?My>664^I?(|cR7ZPCdLZ1(E+C+Cy_T|hi)Lj`ADSb0++?3OyWGr zVupa9N0x96XpVG;Kg)o^1DH?z7lZ~<-1hj9Vqr@2SjI2_IZJ}gsCoVYP}7J`e8$)7 zr>R!r$_w_1qfEG>S%HagC*opAKP#^*K=Rziir|s_A_$eqU?y%DR~0NP2CON($-vVv z3WYA)-$X$|ES83oJ%xPu`jj>VnPO!MKMT^@>ry&Bt6_Y21vicwOdYBr%n^)SoWpv8 zCd2al8Er|Qj9uoOO1ea^i*9P8!EAK`5WA%Ay9x3kjD=Ql?`jY<1>-&EJ-WOlvX-G7 zw77Al2cUhxLp?OyXr#D`4|BC7-Qbr>>1$@3djYJv-ZAi+5MUJz;rbjE?Kpjf^7L3- zhv5_hnR*r_XF&)#hQ7M^_aXKq0|El2N-2;$8G2NW|n9+~nge5j>g6)4E|UH9A>9 zomj67GS&C2c%{@FUp|wCEa6G|E`5B3rP(y|I!qbjIGnqwv!GYBeKl<=H)5tx4E5)H zX}Dx850Uej_i}B=lf9d(YPKR%teQevuyo5}hBzJ?%)`C(Sf*7aw0kV$D8Sg5)%BV> zHxQ?>UiLDs%jo&MGup}f&aNVjTf~#sM{Fe(f@)#Q8TFCP!^r`T*+3YAOJh!y$#X^>JLw6P=u@bwI=oKTI=_f8*iHy}wU9qe zl6uP}Pg8-5A!w$D-#P|a4v;d!FPiquK)Zm`I^4qhZMNGCY% zKwUUp@P+E)Cm-raaJ^|4Dc{F;xHX;u?c$wD+>@=G~7*07K>bQ_#iBMT|y{`yz6WK<0 z%a6;nbrKsIx`KHZ9#$bF&W4^p4xA5Q`6J5|+bPJ!s(kCoAoWNl4p^ivPd>e_*4>?= zOnurNVkAR-Suts;yCAp>uSErL3vV#48SIO~z*FK|5hMIpl_P71W~&hOXaJaVESb?? z6M+SlESGr?fjpS);@xjY1UMGTRAgbFk z8XXMaVr$|lF;k{uI2x4Z!OVZE0d};O2DP?DoRHY3s5|WKw!jc;;DJh)U0Alo?vYq&Uu*ri22 z1xHu&fcX&Q?=*ogIfU6vVA`@&B`(btaf=yqX~5?TrMDCjtil@N3Jay9iV_%HEN}!s zB9rJN)ndI^4A%3qKdhGvgXGYaEWkC6Vb~yqwjdQprND!_4mhp0oen^!bwLKb8o8{* zBxD6e0tI$gUcE>07VR&r6>FqrO$Fy^Jp%(cHj5xIngP190+!#=Pl73CgC1TC?*fh` zkO2zjSJH`RExJ_T+VYoPFDgTMI@-erLalK~gv5}bTIssKTv$cE?z%@E2GHA4*}+?HCLK!Y9- ztLDbV0T&*0K%w!w&*h-H4s3#g>oSKGu8|fg4ku9%ST}hs7QEUSi44NAUb0yO0~H7J zLsHoyb|^k1uZ1KhjbLmHPN z@jNE^k)V^rbJ6y*?wlTzXJfuvyvZ0-ZnF0BFmB*mP+IqfJ+xEEA4N){X`fMIBLu8R zkSZ9_uvJB5)V!ZsM7cm8bI1Tt(GT$3XvV8m&i@Oj5qZ_@oGsbV7OJHPJ!C4fQ6!JJ z1RW5mtc1I@aadi<)m>mmk*625lpT?_6JmfyKNYwKi5wc!04^kUr+lVxlP$epX4baE zmRk<(e@uek6l|Dt=h#v3*0(l7$0<$)aU3u7&m~wziQ-|HbF_`_B!;KGA;$HDgA*J8 zV^;t&H4Pb*J(@JUxFJUwxe3I=>q&P88AJ{lK4PYu=rcH}sr(o&9CMM2f3q|)@E~T5 zdQ_z5#{*hw6q)9(l06Q$7weEuCE$7!nO>CDAb3}UCve7Ru%Ey{W%gq1t1*(CKY}S2 z@Tg)!j5mB-7+{Gy)L|?Xi-(OI#nw}-bB>-g(r1ckqgR@DV8(_3@`4!e&LS@Y+Nl$0XN#|aZBnQ6LV;8b-?m(y!i?;#}y~Z%)mf7au^H| z(IAy0(1L@f&n&3zXqy??vIaJab!Aa!*hJ5<;9COtDMGL>5wjx6;D(V50TvKNPlX7r z`2?;tkQ8E%iK^dsAGHGPM3xj#7)dIeB4DPd4T3d&aloor6Ua0IlW7|bEU_+F4HmkD z6+;C#WUH9U)MRW+JOUMS&~gqJ2mR7fg!7K^qyjwv6@(jL>%15j1!F;-cVpaw;`IY% zp($wHbJ}4d9dPnWQBjOp8my9WbH6s`gvo3{epLT?-$u?hx){+8KbB~Ltni6vW+&a4 zDj1LkWy8e`&E*7nGX3`pJ+r$$VbEN$Q$NEU zl#zw=5~C=OotCh_2bzPdO|Nw=hkWOxg}j~r!RrZme6AIWbFubu@V(fumeyC$<_Ps? zeoFSoD5uDYJ#9c0mE!mRrUFeTX&TaOI>g?9>qSoo7UhKCt`Eg5956E$Tjr#;=#=dRG`v+}J=Ns3DbJ z<9SbD@Q1sY2#T8Ag82~lI^B+IO$0ictfc>l2#^eT9@Oelj*<`O$XU>(fe1CBK!btH zfVTO+;L%$U4{yW#P+1&CTmYU^KT98XE{3CLC~rZ#9joF42Q$O`1P%&ta!OHQC*d@P z@#P=Ksp-@w(yjse?{1y{A zGbLlzrwKDZMZJeo1l1b4)p~=FupXdF{eSN7fym-*VH(4_q1? zcIDB}9=P>TKDWfCO^0Hqp-<^-+RmBkJQJWIr8#W%i$bG*Wf-zc=Q)s9e$Ja z#@xSq{_Ae+k3Lo@AAi0)_Qj9B63>ZVRGZv?)uBdxF2q;%)h6hw4PS}0(!&SJhoFEp zDZ0D|t?+;9{IC4)*6VNnm5ZK#=Qj^O@=AB_UAunu-9Pcum%iDS!uy7!mlf~2^Ho1q z3CD_Cq0H;nkNv{6=iYr@W#=0QZ#V11$XqJ02+R=7FF1^7e6Q6RS2gcpEHN(SY=SJ) zwzOQ)AP%s(wEiFk-gEc%4<<)n_EWeOEd0$~ci%s@`<0j1s$dw3_Sb6UES3D&g-;S0 zbXe?b{M%i3mB(%!ysW%y*MYHHi@OQNRrJQT!hc-^YoR2I{}5BSp;*Mq zRB-d`$->6dQJ$4#6so#jzh@onO8h5`!+K$?8ZO7{cInDMr#>0~Fsec+uvkH@s>y^7<))g1KWxu~UsUQUwki%ep?XyX*|f{%CEYtDz0 zW&AGZnF!s9rkbArnChT&-=^6^VHy1d#qm?7p)X%>L44K(_NW~{j`0cS%wqi3y^Yw@ zgg@?b#1H#{bWal=7>7X|8f4R+J3$5--881z%ZD*%HGmWU$To2t$DSQW31r;|{Ft@a zU1k*1^82h_{Oi2WC)=&2XM=kZ+~hCu%wtvHbxfO-IX}_sIQB#>vI(vfJPt0i$t2zd z1bl|l9$8H`?S1=jUC3W+R%a6}4>IW5BspiXH9Y0SHp%C|no^%Ck3U0Mq}L`JzbboH zC$Za4^hwN7YEJu!r2RzaJZzz9KT)v_G58jtvp`nWPsA8a*LB8M*H6;!K5-m zCr;faXR4oMwd}PCsH?nB==Kwyij9-5(L=PK^w|VE8+|{~3@61|oA6zUtg4^v*@ttn zd-}=hY%(El&_>g>N%)C>`8H7%i|!Y!=gwoC!sRHyB&zQm#<*-j=cy4{~$cww;0~HRSd}Cz*ZF%KA_%;j?vhZKd$q6 zO%5`8M)J703}5UAFXz+v8I7o=(fxi(UhJ90B&ArpOvEb5J<0p)kl~r%k=aQVp`m8Y zCG$I6X&g8@{M|T&dK*MOYAQvvG2|lV#UfFT>U^XXn{v_TFD+OF!5*-{tW3jB4xuFa zIk*|LvcMvrIZiWQJ1^q0{OuyXMFh)|IbS5);w*|MfqLuc(E?CLn4%zS@DGiMa0SLiQA~nXlQttZ8n$@)dFaP|TuL>HQEzGf*>I5KB5PK$xb$B2S0?TL45`u^AInBiu=iF!?);(`YG}Ze^f6m1)UG zagKowXq;l2RfioUguAg!s#vZ>xmcCZk9RWZ4H%E2=Di9RNn^V2g!ln+4{212`9jd% z4iuK{6$VnU zNKy4+rUe*vPtob9xIg{LNQDsNi{UacG4`TmD$jhxp*ccv1au*MjMO27U04<#NI|-v z5nox;)(O_M{c1cMmjyZ@tpFIO#WKzYQ`A_>891~hWbXu_EQt=Bp<-A;mchIRusexQ z*^uw=rTwAm8B$$)gz+f>zT-hajS3dtb)>lt-*N%hVKK|GsQy^k7+IwJogA1b(<>HH ztBkyh5-uw@jp)e2$cU>URt(}{p$lf3Sdkz&ArLOIRSdG4);cD%My!Nl7zT`h2Ydj! z2Jxd!#UXu^RD&=4V+CJ;jYovgq$Pvz!66Mp0UZx6^(`fE&r1ro9g?l48F93V;@c1v zHK2p*T_97j#T)0D$ii>NhWwGiQehFtC*LTT(nwztY)0+ml@V6WFp!~ z21QXcHIp{Xvf89gG~o4OtL<>S*vnbtJ#rvx9aPf{oUy=UoX8~h$(mtL9AqW2iPv$Q zfa6Jsfq2l=omuZiN)Dk5A+>Y4;&|)d$L+C&V6r4x8j;mb<$7iDRwe0?NTNWe0D% zC0c9qKoCdeSs98Yk5n5MMb2d)8wK3F6E1!w3WMq~GC>n^im<&H9TzW3+b8}V3}YEJ zeh*KaG2}##ZgNUGVf?}>Zs}aPI6jSf#Lv~H1<>NpcnFa+8ByDv+qlapG*!2=tNO0n zZNXAi$eqXO^Gwah7|uE?=T3g^^3R!WGN$nPsrcUD~D=>Y*IfL254p?6d zj;vy`h;X>As^+-6$o{+Z5k2E{^A?h51%KnOfw{B1cj+W*y5PJb&b)BB0+}aFCG^@w zd2Sv@@3jV!DHPie>HxE}c@{ZsanwRq_d9mVsf9i|S{b!vXl1Gciir6V!)I9`?ZJp&s2$AxhMq9>hl+%#BetIj%6*$jC zfOJ7H9TCOtXAcU=%hR@eAweQf^B>VI$~9GMasNzxdORaCmqKuRo*Yi0e1wY zvMT7=m_MgX;$xX zDRQ#a6>crfJHR7ZizH%Z(H4^dmlQ@#C;Y@%e22mRaMAGV)fTW#xOlDf`okVNXxm(X zYr=0qTHrXas@36?<$Y1h^fFYL4w%!^9rB#jm^XI8UUxHx_@Y0z#zd^*lJY#%ZLAuo z#-Tilkt)GKLW?kYkwrrkZ+%RKBw^y-cpgV}?js81{tdF&W@l+zD-bAXv;0G=P+rd6 z<|OtTtW^Btn27R{c^^3AE&USFXT=K1S+DKEFc0lFiBs$Od0OpZ?Dhq*F|5UQW*L|H z=kcStc;{=pi9HiW92*=`i9NK&eVzdI2kL3f$?}$Vo@>YJ!|C@qI?AIcL|%{mhBKD2PixV8a?Yckzgn08gWd_zWX{EPjKanHE{iZ4zZ=X zu^sLvQGR)~QjgwgPapnHcDQ!Y{uSh@Z+q#(@Wl;fk8 z2MTi^GGoDUsOCJi$*P(b@yM=0#zdi}M@IKeUpQ|*WH7!Zd;Ai*J5f3mne;FG&wkzJ$K9X4e z5iDkRng_Fcln$bfi)`_096Cd~B4xva>KzVOllRq{2-k`8oTwFBX_g9JN2ne-)jbgg z&ttH+AqzIv=Hx?>H?E>>S1uEDY**NB03NlhS-u!aoI<)0xLUm1Y_HE zr2M9}6;mBw$E#zUqB+eT+n(v+RcH7+zc`}ab$N@`AzS4-H+V9MD(wG#_3+8Xix)q6 z|E&)#;*KhQP2OC6mFfpl_-ToeJ#^kCM%Lqdhs@}XEnX*83-#7A=Hd-2c*(Zu%o%)5 zku~;VoUfPt9WNPAs(O3Mbm(50+FreN$r|2C4Ew}liuX(Ylh|Qif=jsS%T8k~Z3V8n z>{PTYojAGX?6GsFJt_l;{u-xQt? z!%LMm;SCV3g)}Fxx$QQ4yD|Uh_2je?6+N!!Sq&EHfZ~oDpZ`nBY0N!)^ zFZ%rA``;g)V+MhI zV$v8eCp8m-Ik~WxRu@lh$~wiI5@4Cui%_K;gOJ0n3FVD?CnhAlQ((?db^|*#CwS4*3_9nraGUQ>Y3BQXA>7+ z!8dVU^k1Vx?LOuje7JjPWAPPrji-rra0UbXB{GINoBHa3vDf+7q8#Rg&#j%>Ikn%h zUG<#c7YBD1UopN5XQlA_Cxg9}QQUINJ@~!5*S+p7?C&$YANqMaCvg_q{3_=pd_Z;8 zbF#2-&pqG&6W{ze_8k0v)Rg&P&*8h}7X0qf&g*{e5&W8@d4|te?9l%FqxMWRT9^|a zyB@(0TJ3dUn3Kz>bM$Zy4Sj3I`+0>N;F z?-p160u6ZFs??@#oUYzRo7=wy2Cv4+FmKJpF5xuLL6@yYvs|_8yETf(=H$4<-#j~f z*c`ci=XU&N+wD8vT{?8(j!Sr>;-1SA178QUZsh49I~0?5Ot)w(pQn!(zYgD^ePsXN zF|oO`fuB;t_gt98e>?Nog`?WhqjilZn^uqFNo=!u5UtGXX@|5n`6#n!wP7X3BmxH6l_-mCpT^zp%AJo3<@t^-4 zV@{p=JD5&3*0-{Cb1 zh;wr4)H9fopX1PXs!>`e*hfj66MXlFp1Z}87u`A8d3=O9*?FAbHgM`HzRv)!j*dLD z^E;T?+di_}oZwm*qv1DQeBkr;osWMN%n80VMJVz-W7Fj$M;^gY@uW45U8t$YF8nHE zd~+DbF1|Gj;+)`Zf+=$%-#8*TE#4(_a&gQ#IdYYA64uGD>^>*2d)*_CoO{>pICj~0 zG7n$rV^^Gu$g>2s#P-`Fc(>Q{9U3_afiJ(&@eK^UO=>=u8>oePNFWfyULc zaCvTWR3BS*I8P&f1J!tyYb?Xk=)LjncW^zjhPUH0d#d_Gl5zoK73z=Sjj&gaeq4w; zLt-D(5nL<-1$WrW@vD}b?-cqe3ggpW`dEvtsS{>iG6p30!ao<_ZY$AH& z!OuqX;_pFXuee>oMsiZNrDQ^V4`p~Hu7UL=+q3Lya6Lrd(m;4Y6vqwGMwvXy4VseN zSrB}<&)_t1{A=*BUbHXpKBKT}vbGIa;I<%w7UgC@?gelsf?vPV9D9wcB!4gjb5EC&6u?9q+92A0M@tYf~jiQf&^0w-DpAo+8 zHH+MaPsy8MKZjRWr+&M=CgZk)>#Nw;8zb*d5h9OrFy*XDK1ZBt(MGNt%1fb|4?LtG zV086x_lMM)F2>+fSVWBUHYJT}EG+!hItQNmQU7^pafa}FGom$xv|}4xrS-0%t)q`p zuWc2r6`x}Xl!?)#TpY<8GuFmTZ?21L>CzXUnc@zUn#+6?yY`FN&pFUoPcR-6|y5y(j2xjX&me$-eI;Eask|#PTP+$k_MvPL5LF^d7gua zYxt0N%rLs=QNmJ3EI0ak+yXhOPSb=t6Qs-v9pQ{|hGUcCZIA}IW5${r4x7p81*c&` z?(-?|z*zP67C>~|`eM|;zfk*5atGUGZ2U!?*fa2|JwpIw`qz9EIyr0q$Q+pI1Ch{(MF=(l9 z8k}PZ;`0Fx{H7m8;TiliKF&Q4Ucsvc{;qU7eS z+FU^5YV4lesu1#`EY&A8Ujh$x;=~2qv&PWlgCHLV6oO$Cv^ef8UTp1SIQAkTAGk4R zBzwl-9uvGQ86O*MgRdI%e#WsZxZz0T$>t>YS=m`V-ZlF;sxY@3fj7Hx%s3{^8DIMv zKYsv_LwnvhNS?(2xwg%xuBFpxoe;fC>c*8Y2QBDPTMmfW$7LVW9W68@35|J(S;#w~ z0EezR{NV)4vn1C^B=2NDMJaiWX63%EVtLXa1-L`Qe-50qffpTNkHIwiGtwvgTn=;e z#F<0e)Ln(TypMC+e9=H2>Tlm#rS>Qw9z)KiW^}V~c9yg4^GSuY%6`z|Eebq<=-EY% zM-R~$S3a_M?D7N)Ib~az4`bZ8&)8cbedwTvD7zEe}=dcu48#bj5^A>RPo}0@o&~Zd}{Aca5Fq zaT#Q5^b2owUPfq71L%VHOi!&^Dx;30g;L}^pWqxauHU|m{H-EpW$rp_tL@hZpmsYb zfi*Lc?2awe2oPGjY1IeO8=p|7vKOFKE*@c%#}2g@sG&)r5 zwqC8RGF53==T&gz;@J|}TwO#Ro-Z-V$~XzY;aQPp7T(b<_g5g)s5bTr4Iq!|9`AE_ zwtyn1j+$Izch34P);Blv1ASZ%@_8}{h`w~#@kGya{CRAAs+4`NeO-;#AvkPG+Oeq3 z!Lg520`qf#8_0GeUX`RfMa?6EteDmCQj*!5ID}^B$mgK=ybdccJ!Z5T2Zy8y)q$(F zYgu266>ohbj!j$j$gw||0FVouGHLVPYU~y*W^TmaPREN@{-!kX9NF%~qXf=_dm#_7 zmm%$KTywO6AxgLT!omWN&q$UX*oqlnbohWvkL_?wC#x=fc!IJH4qdfpR^{PF8W$Q5 zr4C7zR#Lpdqdvx={oDVod|m4rs%&|!XO*$XGDj!DaTeRM<8L}N@kh}E-2>*_5BSy_ zi;c7@A*;p4`7Ob@>iXPq-KIcp~0CpT8@5*pYUbgW|HWVm}9 z@nnRzCwZnf$M_uxoDp=8l%8jlhk&5-`WJ^wbI6WwfH?BJYYntkvz&)4Ksa2tc8YoG z>Db&{(EWfWhxu&gNsNwbvchlvz8%tBk+6&E{z~*XRPmkyKf`bsFUXx?*{4t;)(Ze6 zR%Q|*zGvB-cIR=~rI2`1KNNZ=RwuU%IEQb(sL^CSxuf6ERLcncb2$8Rldeuhb{%Io zT-S7fItGG0(WQt%T1tj_1&>jAUpvl;KVL(}HL6E~rw(^84O}E|k~WWAR!}feN6m@7FoFjVvWF+u!VXym3a_ zuReSf%K)EsnJq*jSt%PnUSHq7W9hK5>-fBS{6uxH!I2 za{Yx1JPc}JOtV^>?L!LVMZ+=dhYlAJXK_rmD`wM}4~~D@tby-F764qJ;Zg@eg^O0c zcaBKxt{d4^Gug)6z?a&hoD-bl&uuhWTz8=Zlkcj(^Mc*98%sJVXvY$|R5{`Dts^)S zjH=D*sWr1we*>PufFG_0Hw-+ul5K zIL+Vk7hdw^4}I}XuiUutZCl)rm+CFF2`JE(r(>n2a&=N&mGJlqaqx<(Jf6Hi{iQn~H`=cL`r!h+m~jN3pX zweJ;=)?v>3-_wqMMKQM=UHG$8&$%?lfXXT4{Ie*3qXGv4JJX)kj^><44T zD=OUbiT0d4!f_AKZgaxl0GvH1SeG~kr=420*rC;5<$?mxaF>&91ypNgpyAM&ElWF_F^6%|7Cp$Zz|NQIB zH$Q&mnVLIBHYd~8X1gCpj=T%c=yCj#XYh>hI_IQ$=Huwm`Q`+_ocoB5eUEdpA?s?tIm>boMZJao zwBAa82AuaMyk0JBBV-@^48FMw9|NtPL4qPj7#tgL9W+e1Y#ku6S~!mVq>44ZE96T5 zxkf(EXzu`ysJTw*!1c)D0;P2>>LG>=`>i(|Eerr7;Xo?>4kI`}1KIb$*bw7kaQwU@ zaQVGO%!mH&A~9|9lJd5#rQry;6%2ScQmD&=d!Ov>xIW?UEWVu|8}ET)y**Uf4f;6( z-tY$e9wWas0#7yKDWRP=?0in_r}!-0GtIGiw_wT7`n(>>|MqcAyaDZ>ljG2>A3yTQ z>s~jRpg*(z*v9(d!|UrC8~5NhigDF-fX9?Hx@TEnzvG6|<+&(iIq z3kNhO>C~xvc0T^`omn%&vFu!V22aaAV?Ot;op(V8{`p5?ofvRj^L!4! z$c#}hAg9+IF^?bNI(aAl_DTmdCpYZG{T$cAn{_>zK$px+f{{ zUrBsiC!7<|=eSO|cj-F$Gn|wC&;ibgu9NC^TuFUy?m59adCSgQ(D!}ze?Ma`bxH21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7> z21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7> z21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7> z21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7> z21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7> z21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7> z21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7> z21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7> z21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7> z21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7> z21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7> z21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7>21*7> 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 {@$`qRaTbN@xe9gmV2T1p;RL`3ri(< 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 zkN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg z011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!) z36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@ zkN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg z011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!) z36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@ zkN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg z011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!) z36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@ zkN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg z011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!) z36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@ zkN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg z011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!) z36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@ zkN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg z011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!) z36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@ zkN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg z011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!) z36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@ zkN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg z011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!) z36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@ zkN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg z011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!) z36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@ zkN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg z011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!) z36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@ zkN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg z011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!) z36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@ zkN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg z011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!) z36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@ zkN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg z011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!) z36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@ zkN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg z011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!) z36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@ zkN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg z011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!) z36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@ zkN^q%|LxMT4Z<)GK+!uzX^_%VX9TaoC@g^(g@!UKASR(<5p3Z|jF5;|SZ5b0^8OJZ zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1pZB+MC9ppJkRyV+bMC)Iu1Ygq1~PB81zQtx6z!#qjh`MZey0X^%?nIF88%t U|7Kd>=5~5&p@ki=1AEwk4?htslmGw# literal 0 HcmV?d00001 diff --git a/hls_2018/router_02_boardstr/bitstream/04/router_design.tcl b/hls_2018/router_02_boardstr/bitstream/04/router_design.tcl new file mode 100755 index 0000000..e5347df --- /dev/null +++ b/hls_2018/router_02_boardstr/bitstream/04/router_design.tcl @@ -0,0 +1,1113 @@ + +################################################################ +# This is a generated script based on design: router_design +# +# Though there are limitations about the generated script, +# the main purpose of this utility is to make learning +# IP Integrator Tcl commands easier. +################################################################ + +namespace eval _tcl { +proc get_script_folder {} { + set script_path [file normalize [info script]] + set script_folder [file dirname $script_path] + return $script_folder +} +} +variable script_folder +set script_folder [_tcl::get_script_folder] + +################################################################ +# Check if script is running in correct Vivado version. +################################################################ +set scripts_vivado_version 2018.2 +set current_vivado_version [version -short] + +if { [string first $scripts_vivado_version $current_vivado_version] == -1 } { + puts "" + catch {common::send_msg_id "BD_TCL-109" "ERROR" "This script was generated using Vivado <$scripts_vivado_version> and is being run in <$current_vivado_version> of Vivado. Please run the script in Vivado <$scripts_vivado_version> then open the design in Vivado <$current_vivado_version>. Upgrade the design by running \"Tools => Report => Report IP Status...\", then run write_bd_tcl to create an updated script."} + + return 1 +} + +################################################################ +# START +################################################################ + +# To test this script, run the following commands from Vivado Tcl console: +# source router_design_script.tcl + +# If there is no project opened, this script will create a +# project, but make sure you do not have an existing project +# <./myproj/project_1.xpr> in the current working folder. + +set list_projs [get_projects -quiet] +if { $list_projs eq "" } { + create_project project_1 myproj -part xc7z020clg400-1 +} + + +# CHANGE DESIGN NAME HERE +variable design_name +set design_name router_design + +# If you do not already have an existing IP Integrator design open, +# you can create a design using the following command: +# create_bd_design $design_name + +# Creating design if needed +set errMsg "" +set nRet 0 + +set cur_design [current_bd_design -quiet] +set list_cells [get_bd_cells -quiet] + +if { ${design_name} eq "" } { + # USE CASES: + # 1) Design_name not set + + set errMsg "Please set the variable to a non-empty value." + set nRet 1 + +} elseif { ${cur_design} ne "" && ${list_cells} eq "" } { + # USE CASES: + # 2): Current design opened AND is empty AND names same. + # 3): Current design opened AND is empty AND names diff; design_name NOT in project. + # 4): Current design opened AND is empty AND names diff; design_name exists in project. + + if { $cur_design ne $design_name } { + common::send_msg_id "BD_TCL-001" "INFO" "Changing value of from <$design_name> to <$cur_design> since current design is empty." + set design_name [get_property NAME $cur_design] + } + common::send_msg_id "BD_TCL-002" "INFO" "Constructing design in IPI design <$cur_design>..." + +} elseif { ${cur_design} ne "" && $list_cells ne "" && $cur_design eq $design_name } { + # USE CASES: + # 5) Current design opened AND has components AND same names. + + set errMsg "Design <$design_name> already exists in your project, please set the variable to another value." + set nRet 1 +} elseif { [get_files -quiet ${design_name}.bd] ne "" } { + # USE CASES: + # 6) Current opened design, has components, but diff names, design_name exists in project. + # 7) No opened design, design_name exists in project. + + set errMsg "Design <$design_name> already exists in your project, please set the variable to another value." + set nRet 2 + +} else { + # USE CASES: + # 8) No opened design, design_name not in project. + # 9) Current opened design, has components, but diff names, design_name not in project. + + common::send_msg_id "BD_TCL-003" "INFO" "Currently there is no design <$design_name> in project, so creating one..." + + create_bd_design $design_name + + common::send_msg_id "BD_TCL-004" "INFO" "Making design <$design_name> as current_bd_design." + current_bd_design $design_name + +} + +common::send_msg_id "BD_TCL-005" "INFO" "Currently the variable is equal to \"$design_name\"." + +if { $nRet != 0 } { + catch {common::send_msg_id "BD_TCL-114" "ERROR" $errMsg} + return $nRet +} + +set bCheckIPsPassed 1 +################################################################## +# CHECK IPs +################################################################## +set bCheckIPs 1 +if { $bCheckIPs == 1 } { + set list_check_ips "\ +xilinx.com:ip:axi_gpio:2.0\ +xilinx.com:ip:processing_system7:5.5\ +xilinx.com:hls:pynqrouter:1.0\ +xilinx.com:ip:proc_sys_reset:5.0\ +" + + set list_ips_missing "" + common::send_msg_id "BD_TCL-006" "INFO" "Checking if the following IPs exist in the project's IP catalog: $list_check_ips ." + + foreach ip_vlnv $list_check_ips { + set ip_obj [get_ipdefs -all $ip_vlnv] + if { $ip_obj eq "" } { + lappend list_ips_missing $ip_vlnv + } + } + + if { $list_ips_missing ne "" } { + catch {common::send_msg_id "BD_TCL-115" "ERROR" "The following IPs are not found in the IP Catalog:\n $list_ips_missing\n\nResolution: Please add the repository containing the IP(s) to the project." } + set bCheckIPsPassed 0 + } + +} + +if { $bCheckIPsPassed != 1 } { + common::send_msg_id "BD_TCL-1003" "WARNING" "Will not continue with creation of design due to the error(s) above." + return 3 +} + +################################################################## +# DESIGN PROCs +################################################################## + + + +# Procedure to create entire design; Provide argument to make +# procedure reusable. If parentCell is "", will use root. +proc create_root_design { parentCell } { + + variable script_folder + variable design_name + + if { $parentCell eq "" } { + set parentCell [get_bd_cells /] + } + + # Get object for parentCell + set parentObj [get_bd_cells $parentCell] + if { $parentObj == "" } { + catch {common::send_msg_id "BD_TCL-100" "ERROR" "Unable to find parent cell <$parentCell>!"} + return + } + + # Make sure parentObj is hier blk + set parentType [get_property TYPE $parentObj] + if { $parentType ne "hier" } { + catch {common::send_msg_id "BD_TCL-101" "ERROR" "Parent <$parentObj> has TYPE = <$parentType>. Expected to be ."} + return + } + + # Save current instance; Restore later + set oldCurInst [current_bd_instance .] + + # Set parent object as current + current_bd_instance $parentObj + + + # Create interface ports + set DDR [ create_bd_intf_port -mode Master -vlnv xilinx.com:interface:ddrx_rtl:1.0 DDR ] + set FIXED_IO [ create_bd_intf_port -mode Master -vlnv xilinx.com:display_processing_system7:fixedio_rtl:1.0 FIXED_IO ] + + # Create ports + set LD [ create_bd_port -dir O -from 3 -to 0 LD ] + + # Create instance: axi_gpio_0, and set properties + set axi_gpio_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:axi_gpio:2.0 axi_gpio_0 ] + set_property -dict [ list \ + CONFIG.C_GPIO_WIDTH {4} \ + ] $axi_gpio_0 + + # Create instance: processing_system7_0, and set properties + set processing_system7_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:processing_system7:5.5 processing_system7_0 ] + set_property -dict [ list \ + CONFIG.PCW_ACT_APU_PERIPHERAL_FREQMHZ {650.000000} \ + CONFIG.PCW_ACT_CAN0_PERIPHERAL_FREQMHZ {23.8095} \ + CONFIG.PCW_ACT_CAN1_PERIPHERAL_FREQMHZ {23.8095} \ + CONFIG.PCW_ACT_CAN_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_DCI_PERIPHERAL_FREQMHZ {10.096154} \ + CONFIG.PCW_ACT_ENET0_PERIPHERAL_FREQMHZ {125.000000} \ + CONFIG.PCW_ACT_ENET1_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_FPGA0_PERIPHERAL_FREQMHZ {100.000000} \ + CONFIG.PCW_ACT_FPGA1_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_FPGA2_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_FPGA3_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_I2C_PERIPHERAL_FREQMHZ {50} \ + CONFIG.PCW_ACT_PCAP_PERIPHERAL_FREQMHZ {200.000000} \ + CONFIG.PCW_ACT_QSPI_PERIPHERAL_FREQMHZ {200.000000} \ + CONFIG.PCW_ACT_SDIO_PERIPHERAL_FREQMHZ {50.000000} \ + CONFIG.PCW_ACT_SMC_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_SPI_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_TPIU_PERIPHERAL_FREQMHZ {200.000000} \ + CONFIG.PCW_ACT_TTC0_CLK0_PERIPHERAL_FREQMHZ {108.333336} \ + CONFIG.PCW_ACT_TTC0_CLK1_PERIPHERAL_FREQMHZ {108.333336} \ + CONFIG.PCW_ACT_TTC0_CLK2_PERIPHERAL_FREQMHZ {108.333336} \ + CONFIG.PCW_ACT_TTC1_CLK0_PERIPHERAL_FREQMHZ {108.333336} \ + CONFIG.PCW_ACT_TTC1_CLK1_PERIPHERAL_FREQMHZ {108.333336} \ + CONFIG.PCW_ACT_TTC1_CLK2_PERIPHERAL_FREQMHZ {108.333336} \ + CONFIG.PCW_ACT_TTC_PERIPHERAL_FREQMHZ {50} \ + CONFIG.PCW_ACT_UART_PERIPHERAL_FREQMHZ {100.000000} \ + CONFIG.PCW_ACT_USB0_PERIPHERAL_FREQMHZ {60} \ + CONFIG.PCW_ACT_USB1_PERIPHERAL_FREQMHZ {60} \ + CONFIG.PCW_ACT_WDT_PERIPHERAL_FREQMHZ {108.333336} \ + CONFIG.PCW_APU_CLK_RATIO_ENABLE {6:2:1} \ + CONFIG.PCW_APU_PERIPHERAL_FREQMHZ {650} \ + CONFIG.PCW_ARMPLL_CTRL_FBDIV {26} \ + CONFIG.PCW_CAN0_BASEADDR {0xE0008000} \ + CONFIG.PCW_CAN0_CAN0_IO {} \ + CONFIG.PCW_CAN0_HIGHADDR {0xE0008FFF} \ + CONFIG.PCW_CAN0_PERIPHERAL_CLKSRC {External} \ + CONFIG.PCW_CAN0_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_CAN0_PERIPHERAL_FREQMHZ {-1} \ + CONFIG.PCW_CAN1_BASEADDR {0xE0009000} \ + CONFIG.PCW_CAN1_CAN1_IO {} \ + CONFIG.PCW_CAN1_HIGHADDR {0xE0009FFF} \ + CONFIG.PCW_CAN1_PERIPHERAL_CLKSRC {External} \ + CONFIG.PCW_CAN1_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_CAN1_PERIPHERAL_FREQMHZ {-1} \ + CONFIG.PCW_CAN_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_CAN_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_CAN_PERIPHERAL_DIVISOR1 {1} \ + CONFIG.PCW_CAN_PERIPHERAL_FREQMHZ {100} \ + CONFIG.PCW_CAN_PERIPHERAL_VALID {0} \ + CONFIG.PCW_CLK0_FREQ {100000000} \ + CONFIG.PCW_CLK1_FREQ {10000000} \ + CONFIG.PCW_CLK2_FREQ {10000000} \ + CONFIG.PCW_CLK3_FREQ {10000000} \ + CONFIG.PCW_CORE0_FIQ_INTR {0} \ + CONFIG.PCW_CORE0_IRQ_INTR {0} \ + CONFIG.PCW_CORE1_FIQ_INTR {0} \ + CONFIG.PCW_CORE1_IRQ_INTR {0} \ + CONFIG.PCW_CPU_CPU_6X4X_MAX_RANGE {667} \ + CONFIG.PCW_CPU_CPU_PLL_FREQMHZ {1300.000} \ + CONFIG.PCW_CPU_PERIPHERAL_CLKSRC {ARM PLL} \ + CONFIG.PCW_CPU_PERIPHERAL_DIVISOR0 {2} \ + CONFIG.PCW_CRYSTAL_PERIPHERAL_FREQMHZ {50} \ + CONFIG.PCW_DCI_PERIPHERAL_CLKSRC {DDR PLL} \ + CONFIG.PCW_DCI_PERIPHERAL_DIVISOR0 {52} \ + CONFIG.PCW_DCI_PERIPHERAL_DIVISOR1 {2} \ + CONFIG.PCW_DCI_PERIPHERAL_FREQMHZ {10.159} \ + CONFIG.PCW_DDRPLL_CTRL_FBDIV {21} \ + CONFIG.PCW_DDR_DDR_PLL_FREQMHZ {1050.000} \ + CONFIG.PCW_DDR_HPRLPR_QUEUE_PARTITION {HPR(0)/LPR(32)} \ + CONFIG.PCW_DDR_HPR_TO_CRITICAL_PRIORITY_LEVEL {15} \ + CONFIG.PCW_DDR_LPR_TO_CRITICAL_PRIORITY_LEVEL {2} \ + CONFIG.PCW_DDR_PERIPHERAL_CLKSRC {DDR PLL} \ + CONFIG.PCW_DDR_PERIPHERAL_DIVISOR0 {2} \ + CONFIG.PCW_DDR_PORT0_HPR_ENABLE {0} \ + CONFIG.PCW_DDR_PORT1_HPR_ENABLE {0} \ + CONFIG.PCW_DDR_PORT2_HPR_ENABLE {0} \ + CONFIG.PCW_DDR_PORT3_HPR_ENABLE {0} \ + CONFIG.PCW_DDR_PRIORITY_READPORT_0 {} \ + CONFIG.PCW_DDR_PRIORITY_READPORT_2 {} \ + CONFIG.PCW_DDR_PRIORITY_WRITEPORT_0 {} \ + CONFIG.PCW_DDR_PRIORITY_WRITEPORT_2 {} \ + CONFIG.PCW_DDR_RAM_BASEADDR {0x00100000} \ + CONFIG.PCW_DDR_RAM_HIGHADDR {0x1FFFFFFF} \ + CONFIG.PCW_DDR_WRITE_TO_CRITICAL_PRIORITY_LEVEL {2} \ + CONFIG.PCW_DM_WIDTH {4} \ + CONFIG.PCW_DQS_WIDTH {4} \ + CONFIG.PCW_DQ_WIDTH {32} \ + CONFIG.PCW_ENET0_BASEADDR {0xE000B000} \ + CONFIG.PCW_ENET0_ENET0_IO {MIO 16 .. 27} \ + CONFIG.PCW_ENET0_GRP_MDIO_ENABLE {1} \ + CONFIG.PCW_ENET0_GRP_MDIO_IO {MIO 52 .. 53} \ + CONFIG.PCW_ENET0_HIGHADDR {0xE000BFFF} \ + CONFIG.PCW_ENET0_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_ENET0_PERIPHERAL_DIVISOR0 {8} \ + CONFIG.PCW_ENET0_PERIPHERAL_DIVISOR1 {1} \ + CONFIG.PCW_ENET0_PERIPHERAL_ENABLE {1} \ + CONFIG.PCW_ENET0_PERIPHERAL_FREQMHZ {1000 Mbps} \ + CONFIG.PCW_ENET0_RESET_ENABLE {1} \ + CONFIG.PCW_ENET0_RESET_IO {MIO 9} \ + CONFIG.PCW_ENET1_BASEADDR {0xE000C000} \ + CONFIG.PCW_ENET1_ENET1_IO {} \ + CONFIG.PCW_ENET1_HIGHADDR {0xE000CFFF} \ + CONFIG.PCW_ENET1_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_ENET1_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_ENET1_PERIPHERAL_DIVISOR1 {1} \ + CONFIG.PCW_ENET1_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_ENET1_PERIPHERAL_FREQMHZ {1000 Mbps} \ + CONFIG.PCW_ENET1_RESET_ENABLE {0} \ + CONFIG.PCW_ENET1_RESET_IO {} \ + CONFIG.PCW_FTM_CTI_IN1 {} \ + CONFIG.PCW_FTM_CTI_IN3 {} \ + CONFIG.PCW_FTM_CTI_OUT1 {} \ + CONFIG.PCW_FTM_CTI_OUT3 {} \ + CONFIG.PCW_GPIO_EMIO_GPIO_WIDTH {64} \ + CONFIG.PCW_GPIO_HIGHADDR {0xE000AFFF} \ + CONFIG.PCW_GPIO_MIO_GPIO_ENABLE {1} \ + CONFIG.PCW_GPIO_MIO_GPIO_IO {MIO} \ + CONFIG.PCW_GPIO_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_I2C0_BASEADDR {0xE0004000} \ + CONFIG.PCW_I2C0_GRP_INT_ENABLE {0} \ + CONFIG.PCW_I2C0_GRP_INT_IO {} \ + CONFIG.PCW_I2C0_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_I2C0_RESET_ENABLE {0} \ + CONFIG.PCW_I2C0_RESET_IO {} \ + CONFIG.PCW_I2C1_HIGHADDR {0xE0005FFF} \ + CONFIG.PCW_I2C1_I2C1_IO {} \ + CONFIG.PCW_I2C_PERIPHERAL_FREQMHZ {25} \ + CONFIG.PCW_I2C_RESET_ENABLE {1} \ + CONFIG.PCW_I2C_RESET_POLARITY {Active Low} \ + CONFIG.PCW_I2C_RESET_SELECT {} \ + CONFIG.PCW_NAND_NAND_IO {} \ + CONFIG.PCW_NOR_GRP_CS0_ENABLE {0} \ + CONFIG.PCW_NOR_GRP_CS0_IO {} \ + CONFIG.PCW_NOR_GRP_SRAM_CS0_ENABLE {0} \ + CONFIG.PCW_NOR_GRP_SRAM_CS0_IO {} \ + CONFIG.PCW_NOR_GRP_SRAM_INT_ENABLE {0} \ + CONFIG.PCW_NOR_GRP_SRAM_INT_IO {} \ + CONFIG.PCW_NOR_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_NOR_SRAM_CS0_T_CEOE {1} \ + CONFIG.PCW_NOR_SRAM_CS0_T_PC {1} \ + CONFIG.PCW_NOR_SRAM_CS0_T_RC {11} \ + CONFIG.PCW_NOR_SRAM_CS0_T_TR {1} \ + CONFIG.PCW_NOR_SRAM_CS0_T_WC {11} \ + CONFIG.PCW_NOR_SRAM_CS0_T_WP {1} \ + CONFIG.PCW_NOR_SRAM_CS0_WE_TIME {0} \ + CONFIG.PCW_NOR_SRAM_CS1_T_CEOE {1} \ + CONFIG.PCW_NOR_SRAM_CS1_T_PC {1} \ + CONFIG.PCW_NOR_SRAM_CS1_T_RC {11} \ + CONFIG.PCW_NOR_SRAM_CS1_T_TR {1} \ + CONFIG.PCW_NOR_SRAM_CS1_T_WC {11} \ + CONFIG.PCW_NOR_SRAM_CS1_T_WP {1} \ + CONFIG.PCW_NOR_SRAM_CS1_WE_TIME {0} \ + CONFIG.PCW_OVERRIDE_BASIC_CLOCK {0} \ + CONFIG.PCW_P2F_CAN0_INTR {0} \ + CONFIG.PCW_P2F_CAN1_INTR {0} \ + CONFIG.PCW_P2F_CTI_INTR {0} \ + CONFIG.PCW_P2F_DMAC0_INTR {0} \ + CONFIG.PCW_P2F_DMAC1_INTR {0} \ + CONFIG.PCW_P2F_DMAC2_INTR {0} \ + CONFIG.PCW_P2F_DMAC3_INTR {0} \ + CONFIG.PCW_P2F_DMAC4_INTR {0} \ + CONFIG.PCW_P2F_DMAC5_INTR {0} \ + CONFIG.PCW_P2F_DMAC6_INTR {0} \ + CONFIG.PCW_P2F_DMAC7_INTR {0} \ + CONFIG.PCW_P2F_DMAC_ABORT_INTR {0} \ + CONFIG.PCW_P2F_ENET0_INTR {0} \ + CONFIG.PCW_P2F_ENET1_INTR {0} \ + CONFIG.PCW_P2F_GPIO_INTR {0} \ + CONFIG.PCW_P2F_I2C0_INTR {0} \ + CONFIG.PCW_P2F_I2C1_INTR {0} \ + CONFIG.PCW_P2F_QSPI_INTR {0} \ + CONFIG.PCW_P2F_SDIO0_INTR {0} \ + CONFIG.PCW_P2F_SDIO1_INTR {0} \ + CONFIG.PCW_P2F_SMC_INTR {0} \ + CONFIG.PCW_P2F_SPI0_INTR {0} \ + CONFIG.PCW_P2F_SPI1_INTR {0} \ + CONFIG.PCW_P2F_UART0_INTR {0} \ + CONFIG.PCW_P2F_UART1_INTR {0} \ + CONFIG.PCW_P2F_USB0_INTR {0} \ + CONFIG.PCW_P2F_USB1_INTR {0} \ + CONFIG.PCW_PACKAGE_DDR_BOARD_DELAY0 {0.223} \ + CONFIG.PCW_PACKAGE_DDR_BOARD_DELAY1 {0.212} \ + CONFIG.PCW_PACKAGE_DDR_BOARD_DELAY2 {0.085} \ + CONFIG.PCW_PACKAGE_DDR_BOARD_DELAY3 {0.092} \ + CONFIG.PCW_PACKAGE_DDR_DQS_TO_CLK_DELAY_0 {0.040} \ + CONFIG.PCW_PACKAGE_DDR_DQS_TO_CLK_DELAY_1 {0.058} \ + CONFIG.PCW_PACKAGE_DDR_DQS_TO_CLK_DELAY_2 {-0.009} \ + CONFIG.PCW_PACKAGE_DDR_DQS_TO_CLK_DELAY_3 {-0.033} \ + CONFIG.PCW_PACKAGE_NAME {clg400} \ + CONFIG.PCW_PCAP_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_PCAP_PERIPHERAL_DIVISOR0 {5} \ + CONFIG.PCW_PCAP_PERIPHERAL_FREQMHZ {200} \ + CONFIG.PCW_PERIPHERAL_BOARD_PRESET {None} \ + CONFIG.PCW_PJTAG_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_PJTAG_PJTAG_IO {} \ + CONFIG.PCW_QSPI_GRP_SINGLE_SS_ENABLE {1} \ + CONFIG.PCW_QSPI_GRP_SINGLE_SS_IO {MIO 1 .. 6} \ + CONFIG.PCW_QSPI_GRP_SS1_ENABLE {0} \ + CONFIG.PCW_QSPI_GRP_SS1_IO {} \ + CONFIG.PCW_SD0_GRP_WP_ENABLE {0} \ + CONFIG.PCW_SD0_GRP_WP_IO {} \ + CONFIG.PCW_SD1_GRP_POW_ENABLE {0} \ + CONFIG.PCW_SD1_GRP_POW_IO {} \ + CONFIG.PCW_SD1_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_SD1_SD1_IO {} \ + CONFIG.PCW_SPI0_GRP_SS1_ENABLE {0} \ + CONFIG.PCW_SPI0_GRP_SS1_IO {} \ + CONFIG.PCW_SPI0_HIGHADDR {0xE0006FFF} \ + CONFIG.PCW_SPI0_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_SPI0_SPI0_IO {} \ + CONFIG.PCW_SPI1_GRP_SS1_ENABLE {0} \ + CONFIG.PCW_SPI1_GRP_SS1_IO {} \ + CONFIG.PCW_SPI1_HIGHADDR {0xE0007FFF} \ + CONFIG.PCW_SPI1_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_SPI1_SPI1_IO {} \ + CONFIG.PCW_TRACE_GRP_2BIT_ENABLE {0} \ + CONFIG.PCW_TRACE_GRP_2BIT_IO {} \ + CONFIG.PCW_TRACE_GRP_4BIT_ENABLE {0} \ + CONFIG.PCW_TRACE_GRP_4BIT_IO {} \ + CONFIG.PCW_TRACE_INTERNAL_WIDTH {2} \ + CONFIG.PCW_TRACE_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_TRACE_PIPELINE_WIDTH {8} \ + CONFIG.PCW_TRACE_TRACE_IO {} \ + CONFIG.PCW_TTC1_BASEADDR {0xE0105000} \ + CONFIG.PCW_TTC1_CLK0_PERIPHERAL_CLKSRC {CPU_1X} \ + CONFIG.PCW_TTC1_CLK0_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_TTC1_CLK0_PERIPHERAL_FREQMHZ {133.333333} \ + CONFIG.PCW_TTC1_CLK1_PERIPHERAL_CLKSRC {CPU_1X} \ + CONFIG.PCW_TTC1_CLK1_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_TTC1_CLK1_PERIPHERAL_FREQMHZ {133.333333} \ + CONFIG.PCW_TTC1_CLK2_PERIPHERAL_CLKSRC {CPU_1X} \ + CONFIG.PCW_TTC1_CLK2_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_TTC1_CLK2_PERIPHERAL_FREQMHZ {133.333333} \ + CONFIG.PCW_TTC1_HIGHADDR {0xE0105fff} \ + CONFIG.PCW_TTC1_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_TTC1_TTC1_IO {} \ + CONFIG.PCW_UART0_HIGHADDR {0xE0000FFF} \ + CONFIG.PCW_UART0_PERIPHERAL_ENABLE {1} \ + CONFIG.PCW_UART0_UART0_IO {MIO 14 .. 15} \ + CONFIG.PCW_UART1_BASEADDR {0xE0001000} \ + CONFIG.PCW_UART1_BAUD_RATE {115200} \ + CONFIG.PCW_UART1_GRP_FULL_ENABLE {0} \ + CONFIG.PCW_UART1_GRP_FULL_IO {} \ + CONFIG.PCW_UART_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_UART_PERIPHERAL_DIVISOR0 {10} \ + CONFIG.PCW_UART_PERIPHERAL_FREQMHZ {100} \ + CONFIG.PCW_UART_PERIPHERAL_VALID {1} \ + CONFIG.PCW_UIPARAM_ACT_DDR_FREQ_MHZ {525.000000} \ + CONFIG.PCW_UIPARAM_DDR_ADV_ENABLE {0} \ + CONFIG.PCW_UIPARAM_DDR_AL {0} \ + CONFIG.PCW_UIPARAM_DDR_BANK_ADDR_COUNT {3} \ + CONFIG.PCW_UIPARAM_DDR_BL {8} \ + CONFIG.PCW_UIPARAM_DDR_BOARD_DELAY0 {0.223} \ + CONFIG.PCW_UIPARAM_DDR_BOARD_DELAY1 {0.212} \ + CONFIG.PCW_UIPARAM_DDR_BOARD_DELAY2 {0.085} \ + CONFIG.PCW_UIPARAM_DDR_BOARD_DELAY3 {0.092} \ + CONFIG.PCW_UIPARAM_DDR_BUS_WIDTH {16 Bit} \ + CONFIG.PCW_UIPARAM_DDR_CL {7} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_0_LENGTH_MM {25.8} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_0_PACKAGE_LENGTH {80.4535} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_0_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_1_LENGTH_MM {25.8} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_1_PACKAGE_LENGTH {80.4535} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_1_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_2_LENGTH_MM {0} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_2_PACKAGE_LENGTH {80.4535} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_2_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_3_LENGTH_MM {0} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_3_PACKAGE_LENGTH {80.4535} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_3_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_STOP_EN {0} \ + CONFIG.PCW_UIPARAM_DDR_COL_ADDR_COUNT {10} \ + CONFIG.PCW_UIPARAM_DDR_CWL {6} \ + CONFIG.PCW_UIPARAM_DDR_DEVICE_CAPACITY {4096 MBits} \ + CONFIG.PCW_UIPARAM_DDR_DQS_0_LENGTH_MM {15.6} \ + CONFIG.PCW_UIPARAM_DDR_DQS_0_PACKAGE_LENGTH {105.056} \ + CONFIG.PCW_UIPARAM_DDR_DQS_0_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_DQS_1_LENGTH_MM {18.8} \ + CONFIG.PCW_UIPARAM_DDR_DQS_1_PACKAGE_LENGTH {66.904} \ + CONFIG.PCW_UIPARAM_DDR_DQS_1_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_DQS_2_LENGTH_MM {0} \ + CONFIG.PCW_UIPARAM_DDR_DQS_2_PACKAGE_LENGTH {89.1715} \ + CONFIG.PCW_UIPARAM_DDR_DQS_2_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_DQS_3_LENGTH_MM {0} \ + CONFIG.PCW_UIPARAM_DDR_DQS_3_PACKAGE_LENGTH {113.63} \ + CONFIG.PCW_UIPARAM_DDR_DQS_3_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_DQS_TO_CLK_DELAY_0 {0.040} \ + CONFIG.PCW_UIPARAM_DDR_DQS_TO_CLK_DELAY_1 {0.058} \ + CONFIG.PCW_UIPARAM_DDR_DQS_TO_CLK_DELAY_2 {-0.009} \ + CONFIG.PCW_UIPARAM_DDR_DQS_TO_CLK_DELAY_3 {-0.033} \ + CONFIG.PCW_UIPARAM_DDR_DQ_0_LENGTH_MM {16.5} \ + CONFIG.PCW_UIPARAM_DDR_DQ_0_PACKAGE_LENGTH {98.503} \ + CONFIG.PCW_UIPARAM_DDR_DQ_0_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_DQ_1_LENGTH_MM {18} \ + CONFIG.PCW_UIPARAM_DDR_DQ_1_PACKAGE_LENGTH {68.5855} \ + CONFIG.PCW_UIPARAM_DDR_DQ_1_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_DQ_2_LENGTH_MM {0} \ + CONFIG.PCW_UIPARAM_DDR_DQ_2_PACKAGE_LENGTH {90.295} \ + CONFIG.PCW_UIPARAM_DDR_DQ_2_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_DQ_3_LENGTH_MM {0} \ + CONFIG.PCW_UIPARAM_DDR_DQ_3_PACKAGE_LENGTH {103.977} \ + CONFIG.PCW_UIPARAM_DDR_DQ_3_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_DRAM_WIDTH {16 Bits} \ + CONFIG.PCW_UIPARAM_DDR_ECC {Disabled} \ + CONFIG.PCW_UIPARAM_DDR_ENABLE {1} \ + CONFIG.PCW_UIPARAM_DDR_FREQ_MHZ {525} \ + CONFIG.PCW_UIPARAM_DDR_HIGH_TEMP {Normal (0-85)} \ + CONFIG.PCW_UIPARAM_DDR_MEMORY_TYPE {DDR 3} \ + CONFIG.PCW_UIPARAM_DDR_PARTNO {MT41J256M16 RE-125} \ + CONFIG.PCW_UIPARAM_DDR_ROW_ADDR_COUNT {15} \ + CONFIG.PCW_UIPARAM_DDR_SPEED_BIN {DDR3_1066F} \ + CONFIG.PCW_UIPARAM_DDR_TRAIN_DATA_EYE {1} \ + CONFIG.PCW_UIPARAM_DDR_TRAIN_READ_GATE {1} \ + CONFIG.PCW_UIPARAM_DDR_TRAIN_WRITE_LEVEL {1} \ + CONFIG.PCW_UIPARAM_DDR_T_FAW {40.0} \ + CONFIG.PCW_UIPARAM_DDR_T_RAS_MIN {35.0} \ + CONFIG.PCW_UIPARAM_DDR_T_RC {48.91} \ + CONFIG.PCW_UIPARAM_DDR_T_RCD {7} \ + CONFIG.PCW_UIPARAM_DDR_T_RP {7} \ + CONFIG.PCW_UIPARAM_DDR_USE_INTERNAL_VREF {0} \ + CONFIG.PCW_UIPARAM_GENERATE_SUMMARY {NA} \ + CONFIG.PCW_USB0_BASEADDR {0xE0102000} \ + CONFIG.PCW_USB0_HIGHADDR {0xE0102fff} \ + CONFIG.PCW_USB0_PERIPHERAL_ENABLE {1} \ + CONFIG.PCW_USB0_PERIPHERAL_FREQMHZ {60} \ + CONFIG.PCW_USB0_RESET_ENABLE {1} \ + CONFIG.PCW_USB0_RESET_IO {MIO 46} \ + CONFIG.PCW_USB0_USB0_IO {MIO 28 .. 39} \ + CONFIG.PCW_USB1_BASEADDR {0xE0103000} \ + CONFIG.PCW_USB1_HIGHADDR {0xE0103fff} \ + CONFIG.PCW_USB1_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_USB1_PERIPHERAL_FREQMHZ {60} \ + CONFIG.PCW_USB1_RESET_ENABLE {0} \ + CONFIG.PCW_USB1_RESET_IO {} \ + CONFIG.PCW_USB_RESET_ENABLE {1} \ + CONFIG.PCW_USB_RESET_POLARITY {Active Low} \ + CONFIG.PCW_USB_RESET_SELECT {Share reset pin} \ + CONFIG.PCW_USE_AXI_FABRIC_IDLE {0} \ + CONFIG.PCW_USE_AXI_NONSECURE {0} \ + CONFIG.PCW_USE_CORESIGHT {0} \ + CONFIG.PCW_USE_CROSS_TRIGGER {0} \ + CONFIG.PCW_USE_CR_FABRIC {1} \ + CONFIG.PCW_USE_DDR_BYPASS {0} \ + CONFIG.PCW_USE_DEBUG {0} \ + CONFIG.PCW_USE_DEFAULT_ACP_USER_VAL {0} \ + CONFIG.PCW_USE_DMA0 {0} \ + CONFIG.PCW_USE_DMA1 {0} \ + CONFIG.PCW_USE_DMA2 {0} \ + CONFIG.PCW_USE_DMA3 {0} \ + CONFIG.PCW_USE_EXPANDED_IOP {0} \ + CONFIG.PCW_USE_EXPANDED_PS_SLCR_REGISTERS {0} \ + CONFIG.PCW_USE_FABRIC_INTERRUPT {0} \ + CONFIG.PCW_USE_HIGH_OCM {0} \ + CONFIG.PCW_USE_M_AXI_GP0 {1} \ + CONFIG.PCW_USE_M_AXI_GP1 {0} \ + CONFIG.PCW_USE_PROC_EVENT_BUS {0} \ + CONFIG.PCW_USE_PS_SLCR_REGISTERS {0} \ + CONFIG.PCW_USE_S_AXI_ACP {0} \ + CONFIG.PCW_USE_S_AXI_GP0 {0} \ + CONFIG.PCW_USE_S_AXI_GP1 {0} \ + CONFIG.PCW_USE_S_AXI_HP0 {0} \ + CONFIG.PCW_USE_S_AXI_HP1 {0} \ + CONFIG.PCW_USE_S_AXI_HP2 {0} \ + CONFIG.PCW_USE_S_AXI_HP3 {0} \ + CONFIG.PCW_USE_TRACE {0} \ + CONFIG.PCW_USE_TRACE_DATA_EDGE_DETECTOR {0} \ + CONFIG.PCW_VALUE_SILVERSION {3} \ + CONFIG.PCW_WDT_PERIPHERAL_CLKSRC {CPU_1X} \ + CONFIG.PCW_WDT_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_WDT_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_WDT_PERIPHERAL_FREQMHZ {133.333333} \ + CONFIG.PCW_WDT_WDT_IO {} \ + CONFIG.PCW_CAN0_GRP_CLK_ENABLE {0} \ + CONFIG.PCW_CAN0_GRP_CLK_IO {} \ + CONFIG.PCW_CAN1_GRP_CLK_ENABLE {0} \ + CONFIG.PCW_CAN1_GRP_CLK_IO {} \ + CONFIG.PCW_DDR_PRIORITY_READPORT_1 {} \ + CONFIG.PCW_DDR_PRIORITY_READPORT_3 {} \ + CONFIG.PCW_DDR_PRIORITY_WRITEPORT_1 {} \ + CONFIG.PCW_DDR_PRIORITY_WRITEPORT_3 {} \ + CONFIG.PCW_ENET1_GRP_MDIO_ENABLE {0} \ + CONFIG.PCW_ENET1_GRP_MDIO_IO {} \ + CONFIG.PCW_ENET_RESET_ENABLE {1} \ + CONFIG.PCW_ENET_RESET_POLARITY {Active Low} \ + CONFIG.PCW_ENET_RESET_SELECT {Share reset pin} \ + CONFIG.PCW_EN_4K_TIMER {0} \ + CONFIG.PCW_EN_CAN0 {0} \ + CONFIG.PCW_EN_CAN1 {0} \ + CONFIG.PCW_EN_CLK0_PORT {1} \ + CONFIG.PCW_EN_CLK1_PORT {0} \ + CONFIG.PCW_EN_CLK2_PORT {0} \ + CONFIG.PCW_EN_CLK3_PORT {0} \ + CONFIG.PCW_EN_CLKTRIG0_PORT {0} \ + CONFIG.PCW_EN_CLKTRIG1_PORT {0} \ + CONFIG.PCW_EN_CLKTRIG2_PORT {0} \ + CONFIG.PCW_EN_CLKTRIG3_PORT {0} \ + CONFIG.PCW_EN_DDR {1} \ + CONFIG.PCW_EN_EMIO_CAN0 {0} \ + CONFIG.PCW_EN_EMIO_CAN1 {0} \ + CONFIG.PCW_EN_EMIO_CD_SDIO0 {0} \ + CONFIG.PCW_EN_EMIO_CD_SDIO1 {0} \ + CONFIG.PCW_EN_EMIO_ENET0 {0} \ + CONFIG.PCW_EN_EMIO_ENET1 {0} \ + CONFIG.PCW_EN_EMIO_GPIO {0} \ + CONFIG.PCW_EN_EMIO_I2C0 {0} \ + CONFIG.PCW_EN_EMIO_I2C1 {0} \ + CONFIG.PCW_EN_EMIO_MODEM_UART0 {0} \ + CONFIG.PCW_EN_EMIO_MODEM_UART1 {0} \ + CONFIG.PCW_EN_EMIO_PJTAG {0} \ + CONFIG.PCW_EN_EMIO_SDIO0 {0} \ + CONFIG.PCW_EN_EMIO_SDIO1 {0} \ + CONFIG.PCW_EN_EMIO_SPI0 {0} \ + CONFIG.PCW_EN_EMIO_SPI1 {0} \ + CONFIG.PCW_EN_EMIO_SRAM_INT {0} \ + CONFIG.PCW_EN_EMIO_TRACE {0} \ + CONFIG.PCW_EN_EMIO_TTC0 {0} \ + CONFIG.PCW_EN_EMIO_TTC1 {0} \ + CONFIG.PCW_EN_EMIO_UART0 {0} \ + CONFIG.PCW_EN_EMIO_UART1 {0} \ + CONFIG.PCW_EN_EMIO_WDT {0} \ + CONFIG.PCW_EN_EMIO_WP_SDIO0 {0} \ + CONFIG.PCW_EN_EMIO_WP_SDIO1 {0} \ + CONFIG.PCW_EN_ENET0 {1} \ + CONFIG.PCW_EN_ENET1 {0} \ + CONFIG.PCW_EN_GPIO {1} \ + CONFIG.PCW_EN_I2C0 {0} \ + CONFIG.PCW_EN_I2C1 {0} \ + CONFIG.PCW_EN_MODEM_UART0 {0} \ + CONFIG.PCW_EN_MODEM_UART1 {0} \ + CONFIG.PCW_EN_PJTAG {0} \ + CONFIG.PCW_EN_PTP_ENET0 {0} \ + CONFIG.PCW_EN_PTP_ENET1 {0} \ + CONFIG.PCW_EN_QSPI {1} \ + CONFIG.PCW_EN_RST0_PORT {1} \ + CONFIG.PCW_EN_RST1_PORT {0} \ + CONFIG.PCW_EN_RST2_PORT {0} \ + CONFIG.PCW_EN_RST3_PORT {0} \ + CONFIG.PCW_EN_SDIO0 {1} \ + CONFIG.PCW_EN_SDIO1 {0} \ + CONFIG.PCW_EN_SMC {0} \ + CONFIG.PCW_EN_SPI0 {0} \ + CONFIG.PCW_EN_SPI1 {0} \ + CONFIG.PCW_EN_TRACE {0} \ + CONFIG.PCW_EN_TTC0 {0} \ + CONFIG.PCW_EN_TTC1 {0} \ + CONFIG.PCW_EN_UART0 {1} \ + CONFIG.PCW_EN_UART1 {0} \ + CONFIG.PCW_EN_USB0 {1} \ + CONFIG.PCW_EN_USB1 {0} \ + CONFIG.PCW_EN_WDT {0} \ + CONFIG.PCW_FCLK0_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_FCLK0_PERIPHERAL_DIVISOR0 {5} \ + CONFIG.PCW_FCLK0_PERIPHERAL_DIVISOR1 {2} \ + CONFIG.PCW_FCLK1_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_FCLK1_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_FCLK1_PERIPHERAL_DIVISOR1 {1} \ + CONFIG.PCW_FCLK2_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_FCLK2_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_FCLK2_PERIPHERAL_DIVISOR1 {1} \ + CONFIG.PCW_FCLK3_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_FCLK3_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_FCLK3_PERIPHERAL_DIVISOR1 {1} \ + CONFIG.PCW_FCLK_CLK0_BUF {TRUE} \ + CONFIG.PCW_FCLK_CLK1_BUF {FALSE} \ + CONFIG.PCW_FCLK_CLK2_BUF {FALSE} \ + CONFIG.PCW_FCLK_CLK3_BUF {FALSE} \ + CONFIG.PCW_FPGA0_PERIPHERAL_FREQMHZ {100} \ + CONFIG.PCW_FPGA1_PERIPHERAL_FREQMHZ {50} \ + CONFIG.PCW_FPGA2_PERIPHERAL_FREQMHZ {50} \ + CONFIG.PCW_FPGA3_PERIPHERAL_FREQMHZ {50} \ + CONFIG.PCW_FPGA_FCLK0_ENABLE {1} \ + CONFIG.PCW_FPGA_FCLK1_ENABLE {0} \ + CONFIG.PCW_FPGA_FCLK2_ENABLE {0} \ + CONFIG.PCW_FPGA_FCLK3_ENABLE {0} \ + CONFIG.PCW_FTM_CTI_IN0 {} \ + CONFIG.PCW_FTM_CTI_IN2 {} \ + CONFIG.PCW_FTM_CTI_OUT0 {} \ + CONFIG.PCW_FTM_CTI_OUT2 {} \ + CONFIG.PCW_GPIO_BASEADDR {0xE000A000} \ + CONFIG.PCW_GPIO_EMIO_GPIO_ENABLE {0} \ + CONFIG.PCW_GPIO_EMIO_GPIO_IO {} \ + CONFIG.PCW_I2C0_HIGHADDR {0xE0004FFF} \ + CONFIG.PCW_I2C0_I2C0_IO {} \ + CONFIG.PCW_I2C1_BASEADDR {0xE0005000} \ + CONFIG.PCW_I2C1_GRP_INT_ENABLE {0} \ + CONFIG.PCW_I2C1_GRP_INT_IO {} \ + CONFIG.PCW_I2C1_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_I2C1_RESET_ENABLE {0} \ + CONFIG.PCW_I2C1_RESET_IO {} \ + CONFIG.PCW_IMPORT_BOARD_PRESET {None} \ + CONFIG.PCW_INCLUDE_ACP_TRANS_CHECK {0} \ + CONFIG.PCW_INCLUDE_TRACE_BUFFER {0} \ + CONFIG.PCW_IOPLL_CTRL_FBDIV {20} \ + CONFIG.PCW_IO_IO_PLL_FREQMHZ {1000.000} \ + CONFIG.PCW_IRQ_F2P_INTR {0} \ + CONFIG.PCW_IRQ_F2P_MODE {DIRECT} \ + CONFIG.PCW_MIO_0_DIRECTION {inout} \ + CONFIG.PCW_MIO_0_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_0_PULLUP {enabled} \ + CONFIG.PCW_MIO_0_SLEW {slow} \ + CONFIG.PCW_MIO_10_DIRECTION {inout} \ + CONFIG.PCW_MIO_10_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_10_PULLUP {enabled} \ + CONFIG.PCW_MIO_10_SLEW {slow} \ + CONFIG.PCW_MIO_11_DIRECTION {inout} \ + CONFIG.PCW_MIO_11_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_11_PULLUP {enabled} \ + CONFIG.PCW_MIO_11_SLEW {slow} \ + CONFIG.PCW_MIO_12_DIRECTION {inout} \ + CONFIG.PCW_MIO_12_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_12_PULLUP {enabled} \ + CONFIG.PCW_MIO_12_SLEW {slow} \ + CONFIG.PCW_MIO_13_DIRECTION {inout} \ + CONFIG.PCW_MIO_13_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_13_PULLUP {enabled} \ + CONFIG.PCW_MIO_13_SLEW {slow} \ + CONFIG.PCW_MIO_14_DIRECTION {in} \ + CONFIG.PCW_MIO_14_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_14_PULLUP {enabled} \ + CONFIG.PCW_MIO_14_SLEW {slow} \ + CONFIG.PCW_MIO_15_DIRECTION {out} \ + CONFIG.PCW_MIO_15_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_15_PULLUP {enabled} \ + CONFIG.PCW_MIO_15_SLEW {slow} \ + CONFIG.PCW_MIO_16_DIRECTION {out} \ + CONFIG.PCW_MIO_16_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_16_PULLUP {enabled} \ + CONFIG.PCW_MIO_16_SLEW {slow} \ + CONFIG.PCW_MIO_17_DIRECTION {out} \ + CONFIG.PCW_MIO_17_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_17_PULLUP {enabled} \ + CONFIG.PCW_MIO_17_SLEW {slow} \ + CONFIG.PCW_MIO_18_DIRECTION {out} \ + CONFIG.PCW_MIO_18_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_18_PULLUP {enabled} \ + CONFIG.PCW_MIO_18_SLEW {slow} \ + CONFIG.PCW_MIO_19_DIRECTION {out} \ + CONFIG.PCW_MIO_19_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_19_PULLUP {enabled} \ + CONFIG.PCW_MIO_19_SLEW {slow} \ + CONFIG.PCW_MIO_1_DIRECTION {out} \ + CONFIG.PCW_MIO_1_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_1_PULLUP {enabled} \ + CONFIG.PCW_MIO_1_SLEW {slow} \ + CONFIG.PCW_MIO_20_DIRECTION {out} \ + CONFIG.PCW_MIO_20_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_20_PULLUP {enabled} \ + CONFIG.PCW_MIO_20_SLEW {slow} \ + CONFIG.PCW_MIO_21_DIRECTION {out} \ + CONFIG.PCW_MIO_21_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_21_PULLUP {enabled} \ + CONFIG.PCW_MIO_21_SLEW {slow} \ + CONFIG.PCW_MIO_22_DIRECTION {in} \ + CONFIG.PCW_MIO_22_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_22_PULLUP {enabled} \ + CONFIG.PCW_MIO_22_SLEW {slow} \ + CONFIG.PCW_MIO_23_DIRECTION {in} \ + CONFIG.PCW_MIO_23_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_23_PULLUP {enabled} \ + CONFIG.PCW_MIO_23_SLEW {slow} \ + CONFIG.PCW_MIO_24_DIRECTION {in} \ + CONFIG.PCW_MIO_24_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_24_PULLUP {enabled} \ + CONFIG.PCW_MIO_24_SLEW {slow} \ + CONFIG.PCW_MIO_25_DIRECTION {in} \ + CONFIG.PCW_MIO_25_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_25_PULLUP {enabled} \ + CONFIG.PCW_MIO_25_SLEW {slow} \ + CONFIG.PCW_MIO_26_DIRECTION {in} \ + CONFIG.PCW_MIO_26_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_26_PULLUP {enabled} \ + CONFIG.PCW_MIO_26_SLEW {slow} \ + CONFIG.PCW_MIO_27_DIRECTION {in} \ + CONFIG.PCW_MIO_27_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_27_PULLUP {enabled} \ + CONFIG.PCW_MIO_27_SLEW {slow} \ + CONFIG.PCW_MIO_28_DIRECTION {inout} \ + CONFIG.PCW_MIO_28_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_28_PULLUP {enabled} \ + CONFIG.PCW_MIO_28_SLEW {slow} \ + CONFIG.PCW_MIO_29_DIRECTION {in} \ + CONFIG.PCW_MIO_29_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_29_PULLUP {enabled} \ + CONFIG.PCW_MIO_29_SLEW {slow} \ + CONFIG.PCW_MIO_2_DIRECTION {inout} \ + CONFIG.PCW_MIO_2_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_2_PULLUP {disabled} \ + CONFIG.PCW_MIO_2_SLEW {slow} \ + CONFIG.PCW_MIO_30_DIRECTION {out} \ + CONFIG.PCW_MIO_30_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_30_PULLUP {enabled} \ + CONFIG.PCW_MIO_30_SLEW {slow} \ + CONFIG.PCW_MIO_31_DIRECTION {in} \ + CONFIG.PCW_MIO_31_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_31_PULLUP {enabled} \ + CONFIG.PCW_MIO_31_SLEW {slow} \ + CONFIG.PCW_MIO_32_DIRECTION {inout} \ + CONFIG.PCW_MIO_32_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_32_PULLUP {enabled} \ + CONFIG.PCW_MIO_32_SLEW {slow} \ + CONFIG.PCW_MIO_33_DIRECTION {inout} \ + CONFIG.PCW_MIO_33_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_33_PULLUP {enabled} \ + CONFIG.PCW_MIO_33_SLEW {slow} \ + CONFIG.PCW_MIO_34_DIRECTION {inout} \ + CONFIG.PCW_MIO_34_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_34_PULLUP {enabled} \ + CONFIG.PCW_MIO_34_SLEW {slow} \ + CONFIG.PCW_MIO_35_DIRECTION {inout} \ + CONFIG.PCW_MIO_35_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_35_PULLUP {enabled} \ + CONFIG.PCW_MIO_35_SLEW {slow} \ + CONFIG.PCW_MIO_36_DIRECTION {in} \ + CONFIG.PCW_MIO_36_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_36_PULLUP {enabled} \ + CONFIG.PCW_MIO_36_SLEW {slow} \ + CONFIG.PCW_MIO_37_DIRECTION {inout} \ + CONFIG.PCW_MIO_37_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_37_PULLUP {enabled} \ + CONFIG.PCW_MIO_37_SLEW {slow} \ + CONFIG.PCW_MIO_38_DIRECTION {inout} \ + CONFIG.PCW_MIO_38_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_38_PULLUP {enabled} \ + CONFIG.PCW_MIO_38_SLEW {slow} \ + CONFIG.PCW_MIO_39_DIRECTION {inout} \ + CONFIG.PCW_MIO_39_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_39_PULLUP {enabled} \ + CONFIG.PCW_MIO_39_SLEW {slow} \ + CONFIG.PCW_MIO_3_DIRECTION {inout} \ + CONFIG.PCW_MIO_3_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_3_PULLUP {disabled} \ + CONFIG.PCW_MIO_3_SLEW {slow} \ + CONFIG.PCW_MIO_40_DIRECTION {inout} \ + CONFIG.PCW_MIO_40_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_40_PULLUP {enabled} \ + CONFIG.PCW_MIO_40_SLEW {slow} \ + CONFIG.PCW_MIO_41_DIRECTION {inout} \ + CONFIG.PCW_MIO_41_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_41_PULLUP {enabled} \ + CONFIG.PCW_MIO_41_SLEW {slow} \ + CONFIG.PCW_MIO_42_DIRECTION {inout} \ + CONFIG.PCW_MIO_42_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_42_PULLUP {enabled} \ + CONFIG.PCW_MIO_42_SLEW {slow} \ + CONFIG.PCW_MIO_43_DIRECTION {inout} \ + CONFIG.PCW_MIO_43_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_43_PULLUP {enabled} \ + CONFIG.PCW_MIO_43_SLEW {slow} \ + CONFIG.PCW_MIO_44_DIRECTION {inout} \ + CONFIG.PCW_MIO_44_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_44_PULLUP {enabled} \ + CONFIG.PCW_MIO_44_SLEW {slow} \ + CONFIG.PCW_MIO_45_DIRECTION {inout} \ + CONFIG.PCW_MIO_45_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_45_PULLUP {enabled} \ + CONFIG.PCW_MIO_45_SLEW {slow} \ + CONFIG.PCW_MIO_46_DIRECTION {out} \ + CONFIG.PCW_MIO_46_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_46_PULLUP {enabled} \ + CONFIG.PCW_MIO_46_SLEW {slow} \ + CONFIG.PCW_MIO_47_DIRECTION {in} \ + CONFIG.PCW_MIO_47_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_47_PULLUP {enabled} \ + CONFIG.PCW_MIO_47_SLEW {slow} \ + CONFIG.PCW_MIO_48_DIRECTION {inout} \ + CONFIG.PCW_MIO_48_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_48_PULLUP {enabled} \ + CONFIG.PCW_MIO_48_SLEW {slow} \ + CONFIG.PCW_MIO_49_DIRECTION {inout} \ + CONFIG.PCW_MIO_49_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_49_PULLUP {enabled} \ + CONFIG.PCW_MIO_49_SLEW {slow} \ + CONFIG.PCW_MIO_4_DIRECTION {inout} \ + CONFIG.PCW_MIO_4_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_4_PULLUP {disabled} \ + CONFIG.PCW_MIO_4_SLEW {slow} \ + CONFIG.PCW_MIO_50_DIRECTION {inout} \ + CONFIG.PCW_MIO_50_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_50_PULLUP {enabled} \ + CONFIG.PCW_MIO_50_SLEW {slow} \ + CONFIG.PCW_MIO_51_DIRECTION {inout} \ + CONFIG.PCW_MIO_51_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_51_PULLUP {enabled} \ + CONFIG.PCW_MIO_51_SLEW {slow} \ + CONFIG.PCW_MIO_52_DIRECTION {out} \ + CONFIG.PCW_MIO_52_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_52_PULLUP {enabled} \ + CONFIG.PCW_MIO_52_SLEW {slow} \ + CONFIG.PCW_MIO_53_DIRECTION {inout} \ + CONFIG.PCW_MIO_53_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_53_PULLUP {enabled} \ + CONFIG.PCW_MIO_53_SLEW {slow} \ + CONFIG.PCW_MIO_5_DIRECTION {inout} \ + CONFIG.PCW_MIO_5_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_5_PULLUP {disabled} \ + CONFIG.PCW_MIO_5_SLEW {slow} \ + CONFIG.PCW_MIO_6_DIRECTION {out} \ + CONFIG.PCW_MIO_6_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_6_PULLUP {disabled} \ + CONFIG.PCW_MIO_6_SLEW {slow} \ + CONFIG.PCW_MIO_7_DIRECTION {out} \ + CONFIG.PCW_MIO_7_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_7_PULLUP {disabled} \ + CONFIG.PCW_MIO_7_SLEW {slow} \ + CONFIG.PCW_MIO_8_DIRECTION {out} \ + CONFIG.PCW_MIO_8_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_8_PULLUP {disabled} \ + CONFIG.PCW_MIO_8_SLEW {slow} \ + CONFIG.PCW_MIO_9_DIRECTION {out} \ + CONFIG.PCW_MIO_9_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_9_PULLUP {enabled} \ + CONFIG.PCW_MIO_9_SLEW {slow} \ + CONFIG.PCW_MIO_PRIMITIVE {54} \ + CONFIG.PCW_MIO_TREE_PERIPHERALS {GPIO#Quad SPI Flash#Quad SPI Flash#Quad SPI Flash#Quad SPI Flash#Quad SPI Flash#Quad SPI Flash#GPIO#Quad SPI Flash#ENET Reset#GPIO#GPIO#GPIO#GPIO#UART 0#UART 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#SD 0#SD 0#SD 0#SD 0#SD 0#SD 0#USB Reset#SD 0#GPIO#GPIO#GPIO#GPIO#Enet 0#Enet 0} \ + CONFIG.PCW_MIO_TREE_SIGNALS {gpio[0]#qspi0_ss_b#qspi0_io[0]#qspi0_io[1]#qspi0_io[2]#qspi0_io[3]/HOLD_B#qspi0_sclk#gpio[7]#qspi_fbclk#reset#gpio[10]#gpio[11]#gpio[12]#gpio[13]#rx#tx#tx_clk#txd[0]#txd[1]#txd[2]#txd[3]#tx_ctl#rx_clk#rxd[0]#rxd[1]#rxd[2]#rxd[3]#rx_ctl#data[4]#dir#stp#nxt#data[0]#data[1]#data[2]#data[3]#clk#data[5]#data[6]#data[7]#clk#cmd#data[0]#data[1]#data[2]#data[3]#reset#cd#gpio[48]#gpio[49]#gpio[50]#gpio[51]#mdc#mdio} \ + CONFIG.PCW_M_AXI_GP0_ENABLE_STATIC_REMAP {0} \ + CONFIG.PCW_M_AXI_GP0_ID_WIDTH {12} \ + CONFIG.PCW_M_AXI_GP0_SUPPORT_NARROW_BURST {0} \ + CONFIG.PCW_M_AXI_GP0_THREAD_ID_WIDTH {12} \ + CONFIG.PCW_M_AXI_GP1_ENABLE_STATIC_REMAP {0} \ + CONFIG.PCW_M_AXI_GP1_ID_WIDTH {12} \ + CONFIG.PCW_M_AXI_GP1_SUPPORT_NARROW_BURST {0} \ + CONFIG.PCW_M_AXI_GP1_THREAD_ID_WIDTH {12} \ + CONFIG.PCW_NAND_CYCLES_T_AR {1} \ + CONFIG.PCW_NAND_CYCLES_T_CLR {1} \ + CONFIG.PCW_NAND_CYCLES_T_RC {11} \ + CONFIG.PCW_NAND_CYCLES_T_REA {1} \ + CONFIG.PCW_NAND_CYCLES_T_RR {1} \ + CONFIG.PCW_NAND_CYCLES_T_WC {11} \ + CONFIG.PCW_NAND_CYCLES_T_WP {1} \ + CONFIG.PCW_NAND_GRP_D8_ENABLE {0} \ + CONFIG.PCW_NAND_GRP_D8_IO {} \ + CONFIG.PCW_NAND_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_NOR_CS0_T_CEOE {1} \ + CONFIG.PCW_NOR_CS0_T_PC {1} \ + CONFIG.PCW_NOR_CS0_T_RC {11} \ + CONFIG.PCW_NOR_CS0_T_TR {1} \ + CONFIG.PCW_NOR_CS0_T_WC {11} \ + CONFIG.PCW_NOR_CS0_T_WP {1} \ + CONFIG.PCW_NOR_CS0_WE_TIME {0} \ + CONFIG.PCW_NOR_CS1_T_CEOE {1} \ + CONFIG.PCW_NOR_CS1_T_PC {1} \ + CONFIG.PCW_NOR_CS1_T_RC {11} \ + CONFIG.PCW_NOR_CS1_T_TR {1} \ + CONFIG.PCW_NOR_CS1_T_WC {11} \ + CONFIG.PCW_NOR_CS1_T_WP {1} \ + CONFIG.PCW_NOR_CS1_WE_TIME {0} \ + CONFIG.PCW_NOR_GRP_A25_ENABLE {0} \ + CONFIG.PCW_NOR_GRP_A25_IO {} \ + CONFIG.PCW_NOR_GRP_CS1_ENABLE {0} \ + CONFIG.PCW_NOR_GRP_CS1_IO {} \ + CONFIG.PCW_NOR_GRP_SRAM_CS1_ENABLE {0} \ + CONFIG.PCW_NOR_GRP_SRAM_CS1_IO {} \ + CONFIG.PCW_NOR_NOR_IO {} \ + CONFIG.PCW_PLL_BYPASSMODE_ENABLE {0} \ + CONFIG.PCW_PRESET_BANK0_VOLTAGE {LVCMOS 3.3V} \ + CONFIG.PCW_PRESET_BANK1_VOLTAGE {LVCMOS 1.8V} \ + CONFIG.PCW_PS7_SI_REV {PRODUCTION} \ + CONFIG.PCW_QSPI_GRP_FBCLK_ENABLE {1} \ + CONFIG.PCW_QSPI_GRP_FBCLK_IO {MIO 8} \ + CONFIG.PCW_QSPI_GRP_IO1_ENABLE {0} \ + CONFIG.PCW_QSPI_GRP_IO1_IO {} \ + CONFIG.PCW_QSPI_INTERNAL_HIGHADDRESS {0xFCFFFFFF} \ + CONFIG.PCW_QSPI_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_QSPI_PERIPHERAL_DIVISOR0 {5} \ + CONFIG.PCW_QSPI_PERIPHERAL_ENABLE {1} \ + CONFIG.PCW_QSPI_PERIPHERAL_FREQMHZ {200} \ + CONFIG.PCW_QSPI_QSPI_IO {MIO 1 .. 6} \ + CONFIG.PCW_SD0_GRP_CD_ENABLE {1} \ + CONFIG.PCW_SD0_GRP_CD_IO {MIO 47} \ + CONFIG.PCW_SD0_GRP_POW_ENABLE {0} \ + CONFIG.PCW_SD0_GRP_POW_IO {} \ + CONFIG.PCW_SD0_PERIPHERAL_ENABLE {1} \ + CONFIG.PCW_SD0_SD0_IO {MIO 40 .. 45} \ + CONFIG.PCW_SD1_GRP_CD_ENABLE {0} \ + CONFIG.PCW_SD1_GRP_CD_IO {} \ + CONFIG.PCW_SD1_GRP_WP_ENABLE {0} \ + CONFIG.PCW_SD1_GRP_WP_IO {} \ + CONFIG.PCW_SDIO0_BASEADDR {0xE0100000} \ + CONFIG.PCW_SDIO0_HIGHADDR {0xE0100FFF} \ + CONFIG.PCW_SDIO1_BASEADDR {0xE0101000} \ + CONFIG.PCW_SDIO1_HIGHADDR {0xE0101FFF} \ + CONFIG.PCW_SDIO_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_SDIO_PERIPHERAL_DIVISOR0 {20} \ + CONFIG.PCW_SDIO_PERIPHERAL_FREQMHZ {50} \ + CONFIG.PCW_SDIO_PERIPHERAL_VALID {1} \ + CONFIG.PCW_SINGLE_QSPI_DATA_MODE {x4} \ + CONFIG.PCW_SMC_CYCLE_T0 {NA} \ + CONFIG.PCW_SMC_CYCLE_T1 {NA} \ + CONFIG.PCW_SMC_CYCLE_T2 {NA} \ + CONFIG.PCW_SMC_CYCLE_T3 {NA} \ + CONFIG.PCW_SMC_CYCLE_T4 {NA} \ + CONFIG.PCW_SMC_CYCLE_T5 {NA} \ + CONFIG.PCW_SMC_CYCLE_T6 {NA} \ + CONFIG.PCW_SMC_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_SMC_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_SMC_PERIPHERAL_FREQMHZ {100} \ + CONFIG.PCW_SMC_PERIPHERAL_VALID {0} \ + CONFIG.PCW_SPI0_BASEADDR {0xE0006000} \ + CONFIG.PCW_SPI0_GRP_SS0_ENABLE {0} \ + CONFIG.PCW_SPI0_GRP_SS0_IO {} \ + CONFIG.PCW_SPI0_GRP_SS2_ENABLE {0} \ + CONFIG.PCW_SPI0_GRP_SS2_IO {} \ + CONFIG.PCW_SPI1_BASEADDR {0xE0007000} \ + CONFIG.PCW_SPI1_GRP_SS0_ENABLE {0} \ + CONFIG.PCW_SPI1_GRP_SS0_IO {} \ + CONFIG.PCW_SPI1_GRP_SS2_ENABLE {0} \ + CONFIG.PCW_SPI1_GRP_SS2_IO {} \ + CONFIG.PCW_SPI_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_SPI_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_SPI_PERIPHERAL_FREQMHZ {166.666666} \ + CONFIG.PCW_SPI_PERIPHERAL_VALID {0} \ + CONFIG.PCW_S_AXI_ACP_ARUSER_VAL {31} \ + CONFIG.PCW_S_AXI_ACP_AWUSER_VAL {31} \ + CONFIG.PCW_S_AXI_ACP_ID_WIDTH {3} \ + CONFIG.PCW_S_AXI_GP0_ID_WIDTH {6} \ + CONFIG.PCW_S_AXI_GP1_ID_WIDTH {6} \ + CONFIG.PCW_S_AXI_HP0_DATA_WIDTH {64} \ + CONFIG.PCW_S_AXI_HP0_ID_WIDTH {6} \ + CONFIG.PCW_S_AXI_HP1_DATA_WIDTH {64} \ + CONFIG.PCW_S_AXI_HP1_ID_WIDTH {6} \ + CONFIG.PCW_S_AXI_HP2_DATA_WIDTH {64} \ + CONFIG.PCW_S_AXI_HP2_ID_WIDTH {6} \ + CONFIG.PCW_S_AXI_HP3_DATA_WIDTH {64} \ + CONFIG.PCW_S_AXI_HP3_ID_WIDTH {6} \ + CONFIG.PCW_TPIU_PERIPHERAL_CLKSRC {External} \ + CONFIG.PCW_TPIU_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_TPIU_PERIPHERAL_FREQMHZ {200} \ + CONFIG.PCW_TRACE_BUFFER_CLOCK_DELAY {12} \ + CONFIG.PCW_TRACE_BUFFER_FIFO_SIZE {128} \ + CONFIG.PCW_TRACE_GRP_16BIT_ENABLE {0} \ + CONFIG.PCW_TRACE_GRP_16BIT_IO {} \ + CONFIG.PCW_TRACE_GRP_32BIT_ENABLE {0} \ + CONFIG.PCW_TRACE_GRP_32BIT_IO {} \ + CONFIG.PCW_TRACE_GRP_8BIT_ENABLE {0} \ + CONFIG.PCW_TRACE_GRP_8BIT_IO {} \ + CONFIG.PCW_TTC0_BASEADDR {0xE0104000} \ + CONFIG.PCW_TTC0_CLK0_PERIPHERAL_CLKSRC {CPU_1X} \ + CONFIG.PCW_TTC0_CLK0_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_TTC0_CLK0_PERIPHERAL_FREQMHZ {133.333333} \ + CONFIG.PCW_TTC0_CLK1_PERIPHERAL_CLKSRC {CPU_1X} \ + CONFIG.PCW_TTC0_CLK1_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_TTC0_CLK1_PERIPHERAL_FREQMHZ {133.333333} \ + CONFIG.PCW_TTC0_CLK2_PERIPHERAL_CLKSRC {CPU_1X} \ + CONFIG.PCW_TTC0_CLK2_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_TTC0_CLK2_PERIPHERAL_FREQMHZ {133.333333} \ + CONFIG.PCW_TTC0_HIGHADDR {0xE0104fff} \ + CONFIG.PCW_TTC0_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_TTC0_TTC0_IO {} \ + CONFIG.PCW_TTC_PERIPHERAL_FREQMHZ {50} \ + CONFIG.PCW_UART0_BASEADDR {0xE0000000} \ + CONFIG.PCW_UART0_BAUD_RATE {115200} \ + CONFIG.PCW_UART0_GRP_FULL_ENABLE {0} \ + CONFIG.PCW_UART0_GRP_FULL_IO {} \ + CONFIG.PCW_UART1_HIGHADDR {0xE0001FFF} \ + CONFIG.PCW_UART1_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_UART1_UART1_IO {} \ + CONFIG.PCW_USB1_USB1_IO {} \ + ] $processing_system7_0 + + # Create instance: ps7_0_axi_periph, and set properties + set ps7_0_axi_periph [ create_bd_cell -type ip -vlnv xilinx.com:ip:axi_interconnect:2.1 ps7_0_axi_periph ] + set_property -dict [ list \ + CONFIG.NUM_MI {2} \ + ] $ps7_0_axi_periph + + # Create instance: pynqrouter_0, and set properties + set pynqrouter_0 [ create_bd_cell -type ip -vlnv xilinx.com:hls:pynqrouter:1.0 pynqrouter_0 ] + + # Create instance: rst_ps7_0_100M, and set properties + set rst_ps7_0_100M [ create_bd_cell -type ip -vlnv xilinx.com:ip:proc_sys_reset:5.0 rst_ps7_0_100M ] + + # Create interface connections + connect_bd_intf_net -intf_net processing_system7_0_DDR [get_bd_intf_ports DDR] [get_bd_intf_pins processing_system7_0/DDR] + connect_bd_intf_net -intf_net processing_system7_0_FIXED_IO [get_bd_intf_ports FIXED_IO] [get_bd_intf_pins processing_system7_0/FIXED_IO] + connect_bd_intf_net -intf_net processing_system7_0_M_AXI_GP0 [get_bd_intf_pins processing_system7_0/M_AXI_GP0] [get_bd_intf_pins ps7_0_axi_periph/S00_AXI] + connect_bd_intf_net -intf_net ps7_0_axi_periph_M00_AXI [get_bd_intf_pins ps7_0_axi_periph/M00_AXI] [get_bd_intf_pins pynqrouter_0/s_axi_AXI4LS] + connect_bd_intf_net -intf_net ps7_0_axi_periph_M01_AXI [get_bd_intf_pins axi_gpio_0/S_AXI] [get_bd_intf_pins ps7_0_axi_periph/M01_AXI] + + # Create port connections + connect_bd_net -net axi_gpio_0_gpio_io_o [get_bd_ports LD] [get_bd_pins axi_gpio_0/gpio_io_o] + connect_bd_net -net processing_system7_0_FCLK_CLK0 [get_bd_pins axi_gpio_0/s_axi_aclk] [get_bd_pins processing_system7_0/FCLK_CLK0] [get_bd_pins processing_system7_0/M_AXI_GP0_ACLK] [get_bd_pins ps7_0_axi_periph/ACLK] [get_bd_pins ps7_0_axi_periph/M00_ACLK] [get_bd_pins ps7_0_axi_periph/M01_ACLK] [get_bd_pins ps7_0_axi_periph/S00_ACLK] [get_bd_pins pynqrouter_0/ap_clk] [get_bd_pins rst_ps7_0_100M/slowest_sync_clk] + connect_bd_net -net processing_system7_0_FCLK_RESET0_N [get_bd_pins processing_system7_0/FCLK_RESET0_N] [get_bd_pins rst_ps7_0_100M/ext_reset_in] + connect_bd_net -net rst_ps7_0_100M_interconnect_aresetn [get_bd_pins ps7_0_axi_periph/ARESETN] [get_bd_pins rst_ps7_0_100M/interconnect_aresetn] + connect_bd_net -net rst_ps7_0_100M_peripheral_aresetn [get_bd_pins axi_gpio_0/s_axi_aresetn] [get_bd_pins ps7_0_axi_periph/M00_ARESETN] [get_bd_pins ps7_0_axi_periph/M01_ARESETN] [get_bd_pins ps7_0_axi_periph/S00_ARESETN] [get_bd_pins pynqrouter_0/ap_rst_n] [get_bd_pins rst_ps7_0_100M/peripheral_aresetn] + + # Create address segments + create_bd_addr_seg -range 0x00010000 -offset 0x41200000 [get_bd_addr_spaces processing_system7_0/Data] [get_bd_addr_segs axi_gpio_0/S_AXI/Reg] SEG_axi_gpio_0_Reg + create_bd_addr_seg -range 0x00040000 -offset 0x43C00000 [get_bd_addr_spaces processing_system7_0/Data] [get_bd_addr_segs pynqrouter_0/s_axi_AXI4LS/Reg] SEG_pynqrouter_0_Reg + + + # Restore current instance + current_bd_instance $oldCurInst + + save_bd_design +} +# End of create_root_design() + + +################################################################## +# MAIN FLOW +################################################################## + +create_root_design "" + + diff --git a/hls_2018/router_02_boardstr/etc/ap_fixed_sim.h b/hls_2018/router_02_boardstr/etc/ap_fixed_sim.h new file mode 100755 index 0000000..5be571d --- /dev/null +++ b/hls_2018/router_02_boardstr/etc/ap_fixed_sim.h @@ -0,0 +1,2451 @@ +/* + * Copyright 2012 Xilinx, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __AESL_GCC_AP_FIXED_H__ +#define __AESL_GCC_AP_FIXED_H__ + +#ifndef __cplusplus + #error C++ is required to include this header file +#endif /* #ifndef __cplusplus */ + + +#include +#ifndef __AESL_APDT_IN_SCFLOW__ + #include "etc/ap_int_sim.h" +#else + #include "../etc/ap_private.h" +#endif /* #ifndef __AESL_APDT_IN_SCFLOW__ */ + +#define FLOAT_MAN 23 +#define FLOAT_EXP 8 +#define DOUBLE_MAN 52 +#define DOUBLE_EXP 11 +// #define DOUBLE_MAN_MASK (~0ULL >> (64-DOUBLE_MAN-2)) +#define DOUBLE_MAN_MASK 0x3fffffffffffffULL +#define BIAS(e) ((1ULL<<(e-1))-1) +#define FLOAT_BIAS BIAS(FLOAT_EXP) +#define DOUBLE_BIAS BIAS(DOUBLE_EXP) + +/// Forward declaration. +template struct ap_fixed_base; + +///Proxy class, which allows bit selection to be used as both rvalue(for reading) and +//lvalue(for writing) +template +struct af_bit_ref { +#ifdef _MSC_VER + #pragma warning(disable: 4521 4522) +#endif /* #ifdef _MSC_VER */ + ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& d_bv; + int d_index; +public: + INLINE af_bit_ref(const af_bit_ref<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& ref): + d_bv(ref.d_bv), d_index(ref.d_index) {} + + INLINE af_bit_ref(ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>* bv, int index=0): + d_bv(*bv),d_index(index) {} + + INLINE operator bool() const { + return d_bv.V[d_index]; + } + + INLINE af_bit_ref& operator=(unsigned long long val) { + if (val) + d_bv.V.set(d_index); + else + d_bv.V.clear(d_index); + return *this; + } + + template + INLINE af_bit_ref& operator =(const ap_private<_AP_W2,_AP_S2>& val) { + return operator=(val!=0); + } + + INLINE af_bit_ref& operator =(const af_bit_ref<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& val) { + return operator=((unsigned long long)(bool)val); + } + + template + INLINE af_bit_ref operator=(const af_bit_ref<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& val) { + return operator=((unsigned long long)(bool)val); + } + + template + INLINE af_bit_ref& operator = ( const ap_bit_ref<_AP_W2, _AP_S2> &val) { + return operator =((unsigned long long) (bool) val); + } + + template + INLINE af_bit_ref& operator = ( const ap_range_ref<_AP_W2,_AP_S2>& val) { + return operator =((const ap_private<_AP_W2, false>) val); + } + + template + INLINE af_bit_ref& operator= (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& val) { + return operator=((const ap_private<_AP_W2, false>)(val)); + } + + template + INLINE af_bit_ref& operator= (const ap_concat_ref<_AP_W2, _AP_T3, _AP_W3, _AP_T3>& val) { + return operator=((const ap_private<_AP_W2 + _AP_W3, false>)(val)); + } + + template + INLINE ap_concat_ref<1, af_bit_ref, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (ap_private<_AP_W2, _AP_S2>& op) { + return ap_concat_ref<1, af_bit_ref, _AP_W2, + ap_private<_AP_W2, _AP_S2> >(*this, op); + } + + template + INLINE ap_concat_ref<1, af_bit_ref, 1, ap_bit_ref<_AP_W2, _AP_S2> > + operator, (const ap_bit_ref<_AP_W2, _AP_S2> &op) { + return ap_concat_ref<1, af_bit_ref, 1, + ap_bit_ref<_AP_W2, _AP_S2> >(*this, + const_cast& >(op)); + } + + template + INLINE ap_concat_ref<1, af_bit_ref, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > + operator, (const ap_range_ref<_AP_W2, _AP_S2> &op) { + return ap_concat_ref<1, af_bit_ref, _AP_W2, + ap_range_ref<_AP_W2, _AP_S2> >(*this, + const_cast& >(op)); + } + + template + INLINE ap_concat_ref<1, af_bit_ref, _AP_W2 + _AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > + operator, (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &op) { + return ap_concat_ref<1, af_bit_ref, _AP_W2 + _AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(*this, + const_cast& >(op)); + } + + template + INLINE ap_concat_ref<1, af_bit_ref, _AP_W2, + af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &op) { + return ap_concat_ref<1, af_bit_ref, _AP_W2, + af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, + _AP_N2> >(*this, const_cast& >(op)); + } + + template + INLINE ap_concat_ref<1, af_bit_ref, 1, + af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &op) { + return ap_concat_ref<1, af_bit_ref, 1, + af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, + const_cast& >(op)); + } + + template + INLINE bool operator == (const af_bit_ref<_AP_W2, _AP_I2, + _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) { + return get() == op.get(); + } + + template + INLINE bool operator != (const af_bit_ref<_AP_W2, _AP_I2, + _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) { + return get() != op.get(); + } + + INLINE bool operator ~ () const { + bool bit = (d_bv.V)[d_index]; + return bit ? false : true; + } + + INLINE int length() const { + return 1; + } + + INLINE bool get() { + return d_bv.V[d_index]; + } + + INLINE bool get() const { + return d_bv.V[d_index]; + } + + INLINE std::string to_string() const { + return d_bv.V[d_index] ? "1" : "0"; + } +}; + +///Range(slice) reference +//------------------------------------------------------------ +template +struct af_range_ref { +#ifdef _MSC_VER + #pragma warning(disable: 4521 4522) +#endif /* #ifdef _MSC_VER */ + ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &d_bv; + int l_index; + int h_index; + +public: + INLINE af_range_ref(const af_range_ref<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& ref): + d_bv(ref.d_bv), l_index(ref.l_index), h_index(ref.h_index) {} + + INLINE af_range_ref(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>* bv, int h, int l): + d_bv(*bv),l_index(l),h_index(h) { + //if (h < l) + // fprintf(stderr, + //"Warning! The bits selected will be returned in reverse order\n"); + } + + INLINE operator ap_private<_AP_W, false> () const { + if (h_index >= l_index) { + ap_private<_AP_W, false> val(d_bv.V); + ap_private<_AP_W,false> mask(-1); + mask>>=_AP_W-(h_index-l_index+1); + val>>=l_index; + return val&=mask; + } else { + ap_private<_AP_W, false> val = 0; + for (int i=0, j=l_index;j>=0&&j>=h_index;j--,i++) + if ((d_bv.V)[j]) val.set(i); + return val; + } + } + + INLINE operator unsigned long long() const { + return get().to_uint64(); + } + + template + INLINE af_range_ref& operator =(const ap_private<_AP_W2,_AP_S2>& val) { + ap_private<_AP_W, false> vval= ap_private<_AP_W, false>(val); + if (l_index > h_index) { + for (int i=0, j=l_index;j>=0&&j>=h_index;j--,i++) + vval[i]? d_bv.V.set(j):d_bv.V.clear(j); + } else { + ap_private<_AP_W,false> mask(-1); + if (l_index>0) { + mask<<=l_index; + vval<<=l_index; + } + if (h_index<_AP_W-1) { + ap_private<_AP_W,false> mask2(-1); + mask2>>=_AP_W-h_index-1; + mask&=mask2; + vval&=mask2; + } + mask.flip(); + d_bv.V &= mask; + d_bv.V |= vval; + } + return *this; + } + + INLINE af_range_ref& operator = (unsigned long long val) { + const ap_private<_AP_W, false> tmpVal(val); + return operator = (tmpVal); + } + + template + INLINE af_range_ref& operator = + (const ap_concat_ref <_AP_W3, _AP_T3, _AP_W4, _AP_T4>& val) { + const ap_private<_AP_W, false> tmpVal(val); + return operator = (tmpVal); + } + + template + INLINE af_range_ref& operator =(const ap_bit_ref<_AP_W3, _AP_S3>& val) { + const ap_private<_AP_W, false> tmpVal(val); + return operator = (tmpVal); + } + + template + INLINE af_range_ref& operator =(const ap_range_ref<_AP_W3,_AP_S3>& val) { + const ap_private<_AP_W, false> tmpVal(val); + return operator =(tmpVal); + } + + template + INLINE af_range_ref& operator= (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& val) { + const ap_private<_AP_W2, false> tmp= val.get(); + return operator = (tmp); + } + + INLINE af_range_ref& operator= (const af_range_ref<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& val) { + const ap_private<_AP_W, false> tmp= val.get(); + return operator = (tmp); + } + + template + INLINE af_range_ref& operator= (const ap_fixed_base<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& val) { + return operator=(val.to_ap_private()); + } + + template + INLINE bool operator == (const ap_range_ref<_AP_W2, _AP_S2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs==rhs; + } + + template + INLINE bool operator != (const ap_range_ref<_AP_W2, _AP_S2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs!=rhs; + } + + template + INLINE bool operator > (const ap_range_ref<_AP_W2, _AP_S2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs>rhs; + } + + template + INLINE bool operator >= (const ap_range_ref<_AP_W2, _AP_S2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs>=rhs; + } + + template + INLINE bool operator < (const ap_range_ref<_AP_W2, _AP_S2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs + INLINE bool operator <= (const ap_range_ref<_AP_W2, _AP_S2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs<=rhs; + } + + template + INLINE bool operator == (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs==rhs; + } + + template + INLINE bool operator != (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs!=rhs; + } + + template + INLINE bool operator > (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs>rhs; + } + + template + INLINE bool operator >= (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs>=rhs; + } + + template + INLINE bool operator < (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs + INLINE bool operator <= (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs<=rhs; + } + + template + INLINE void set(const ap_private<_AP_W2,false>& val) { + ap_private<_AP_W,_AP_S> vval=val; + if (l_index>h_index) { + for (int i=0, j=l_index;j>=0&&j>=h_index;j--,i++) + vval[i]? d_bv.V.set(j):d_bv.V.clear(j); + } else { + ap_private<_AP_W,_AP_S> mask(-1); + if (l_index>0) { + ap_private<_AP_W,false> mask1(-1); + mask1>>=_AP_W-l_index; + mask1.flip(); + mask=mask1; + //vval&=mask1; + vval<<=l_index; + } + if (h_index<_AP_W-1) { + ap_private<_AP_W,false> mask2(-1); + mask2<<=h_index+1; + mask2.flip(); + mask&=mask2; + vval&=mask2; + } + mask.flip(); + d_bv&=mask; + d_bv|=vval; + } + + } + + INLINE ap_private<_AP_W,false> get() const { + if (h_index val(0); + for (int i=0, j=l_index;j>=0&&j>=h_index;j--,i++) + if ((d_bv.V)[j]) val.set(i); + return val; + } else { + ap_private<_AP_W, false> val = ap_private<_AP_W,false>(d_bv.V); + val>>= l_index; + if (h_index<_AP_W-1) + { + ap_private<_AP_W,false> mask(-1); + mask>>=_AP_W-(h_index-l_index+1); + val&=mask; + } + return val; + } + } + + template + INLINE ap_concat_ref<_AP_W, af_range_ref, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (ap_private<_AP_W2, _AP_S2>& op) { + return ap_concat_ref<_AP_W, af_range_ref, _AP_W2, + ap_private<_AP_W2, _AP_S2> >(*this, op); + } + + template + INLINE ap_concat_ref<_AP_W, af_range_ref, 1, ap_bit_ref<_AP_W2, _AP_S2> > + operator, (const ap_bit_ref<_AP_W2, _AP_S2> &op) { + return ap_concat_ref<_AP_W, af_range_ref, 1, + ap_bit_ref<_AP_W2, _AP_S2> >(*this, + const_cast& >(op)); + } + + template + INLINE ap_concat_ref<_AP_W, af_range_ref, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > + operator, (const ap_range_ref<_AP_W2, _AP_S2> &op) { + return ap_concat_ref<_AP_W, af_range_ref, _AP_W2, + ap_range_ref<_AP_W2, _AP_S2> >(*this, + const_cast& >(op)); + } + + template + INLINE ap_concat_ref<_AP_W, af_range_ref, _AP_W2 + _AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > + operator, (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &op) { + return ap_concat_ref<_AP_W, af_range_ref, _AP_W2 + _AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(*this, + const_cast& >(op)); + } + + template + INLINE ap_concat_ref<_AP_W, af_range_ref, _AP_W2, + af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &op) { + return ap_concat_ref<_AP_W, af_range_ref, _AP_W2, + af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, + const_cast& > (op)); + } + + template + INLINE ap_concat_ref<_AP_W, af_range_ref, 1, + af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &op) { + return ap_concat_ref<_AP_W, af_range_ref, 1, + af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, + const_cast& >(op)); + } + + INLINE int length() const { + return h_index>=l_index?h_index-l_index+1:l_index-h_index+1; + } + + INLINE int to_int() const { + ap_private<_AP_W,false> val=get(); + return val.to_int(); + } + + INLINE unsigned int to_uint() const { + ap_private<_AP_W,false> val=get(); + return val.to_uint(); + } + + INLINE long to_long() const { + ap_private<_AP_W,false> val=get(); + return val.to_long(); + } + + INLINE unsigned long to_ulong() const { + ap_private<_AP_W,false> val=get(); + return val.to_ulong(); + } + + INLINE ap_slong to_int64() const { + ap_private<_AP_W,false> val=get(); + return val.to_int64(); + } + + INLINE ap_ulong to_uint64() const { + ap_private<_AP_W,false> val=get(); + return val.to_uint64(); + } + + INLINE std::string to_string(uint8_t radix) const { + return get().to_string(radix); + } + +}; + +//----------------------------------------------------------------------------- +///ap_fixed_base: AutoPilot fixed point +//----------------------------------------------------------------------------- +template +struct ap_fixed_base { +#ifdef _MSC_VER + #pragma warning(disable: 4521 4522) +#endif /* #ifdef _MSC_VER */ +public: + template friend struct +ap_fixed_base; + template friend struct +af_bit_ref; + + INLINE void overflow_adjust(bool underflow, bool overflow, + bool lD, bool sign) { + if (!overflow && !underflow) return; + switch (_AP_O) { + case AP_WRAP: + if (_AP_N == 0) + return; + if (_AP_S) { + //signed SC_WRAP + //n_bits == 1; + if (_AP_N > 1) { + ap_private<_AP_W, _AP_S> mask(-1); + if (_AP_N >= _AP_W) mask = 0; + else mask.lshr(_AP_N); + if (sign) + V &= mask; + else + V |= ~mask; + } + sign ? V.set(_AP_W - 1) : V.clear(_AP_W - 1); + } else { + //unsigned SC_WRAP + ap_private<_AP_W, _AP_S> mask(-1); + if (_AP_N >= _AP_W) mask = 0; + else mask.lshr(_AP_N); + mask.flip(); + V |= mask; + } + break; + case AP_SAT_ZERO: + V.clear(); + break; + case AP_WRAP_SM: + { + bool Ro = ap_private_ops::get<_AP_W, _AP_S, _AP_W -1>(V); // V[_AP_W -1]; + if (_AP_N == 0) { + if (lD != Ro) { + V.flip(); + lD ? ap_private_ops::set<_AP_W, _AP_S, _AP_W - 1>(V) : + ap_private_ops::clear<_AP_W, _AP_S, _AP_W - 1>(V); + } + } else { + if (_AP_N == 1 && sign != Ro) { + V.flip(); + } else if (_AP_N > 1) { + bool lNo = ap_private_ops::get<_AP_W, _AP_S, _AP_W - _AP_N> (V); // V[_AP_W - _AP_N]; + if (lNo == sign) + V.flip(); + ap_private<_AP_W, false> mask(-1); + if (_AP_N >= _AP_W) mask = 0; + else mask.lshr(_AP_N); + if (sign) + V &= mask; + else + V |= mask.flip(); + sign ? ap_private_ops::set<_AP_W, _AP_S, _AP_W - 1>(V) : ap_private_ops::clear<_AP_W, _AP_S, _AP_W - 1>(V); + } + } + } + break; + default: + if (_AP_S) { + if (overflow) { + V.set(); ap_private_ops::clear<_AP_W, _AP_S, _AP_W-1>(V); + } else if (underflow) { + V.clear(); + ap_private_ops::set<_AP_W, _AP_S, _AP_W-1>(V); + if (_AP_O == AP_SAT_SYM) + ap_private_ops::set<_AP_W, _AP_S, 0>(V); + } + } else { + if (overflow) + V.set(); + else if (underflow) + V.clear(); + } + } + } + + INLINE bool quantization_adjust(bool qb, bool r, bool s) { + bool carry=ap_private_ops::get<_AP_W, _AP_S, _AP_W-1>(V); + switch (_AP_Q) { + case AP_TRN: + return false; + case AP_RND_ZERO: + qb &= s || r; + break; + case AP_RND_MIN_INF: + qb &= r; + break; + case AP_RND_INF: + qb &= !s || r; + break; + case AP_RND_CONV: + qb &= ap_private_ops::get<_AP_W, _AP_S, 0>(V) || r; + break; + case AP_TRN_ZERO: + qb = s && ( qb || r ); + break; + default:; + + } + if (qb) ++V; + //only when old V[_AP_W-1]==1 && new V[_AP_W-1]==0 + return carry && !(ap_private_ops::get<_AP_W, _AP_S, _AP_W-1>(V)); //(!V[_AP_W-1]); + } + + template + struct RType { + enum { + _AP_F=_AP_W-_AP_I, + F2=_AP_W2-_AP_I2, + mult_w = _AP_W+_AP_W2, + mult_i = _AP_I+_AP_I2, + mult_s = _AP_S||_AP_S2, + plus_w = AP_MAX(_AP_I+(_AP_S2&&!_AP_S),_AP_I2+(_AP_S&&!_AP_S2))+1+AP_MAX(_AP_F,F2), + plus_i = AP_MAX(_AP_I+(_AP_S2&&!_AP_S),_AP_I2+(_AP_S&&!_AP_S2))+1, + plus_s = _AP_S||_AP_S2, + minus_w = AP_MAX(_AP_I+(_AP_S2&&!_AP_S),_AP_I2+(_AP_S&&!_AP_S2))+1+AP_MAX(_AP_F,F2), + minus_i = AP_MAX(_AP_I+(_AP_S2&&!_AP_S),_AP_I2+(_AP_S&&!_AP_S2))+1, + minus_s = true, +#ifndef __SC_COMPATIBLE__ + div_w = _AP_W + AP_MAX(_AP_W2 - _AP_I2, 0) + _AP_S2, +#else + div_w = _AP_W + AP_MAX(_AP_W2 - _AP_I2, 0) + _AP_S2 + AP_MAX(_AP_I2, 0), +#endif /* #ifndef __SC_COMPATIBLE__ */ + div_i = _AP_I + (_AP_W2-_AP_I2) + _AP_S2, + div_s = _AP_S||_AP_S2, + logic_w = AP_MAX(_AP_I+(_AP_S2&&!_AP_S),_AP_I2+(_AP_S&&!_AP_S2))+AP_MAX(_AP_F,F2), + logic_i = AP_MAX(_AP_I+(_AP_S2&&!_AP_S),_AP_I2+(_AP_S&&!_AP_S2)), + logic_s = _AP_S||_AP_S2 + }; + + typedef ap_fixed_base mult; + typedef ap_fixed_base plus; + typedef ap_fixed_base minus; + typedef ap_fixed_base logic; + typedef ap_fixed_base div; + typedef ap_fixed_base<_AP_W, _AP_I, _AP_S> arg1; + }; + INLINE void report() { +#if 0 + if (_AP_W > 1024 && _AP_W <= 4096) { + fprintf(stderr, "[W] W=%d is out of bound (1<=W<=1024):" + " for synthesis, please define macro AP_INT_TYPE_EXT(N) to" + " extend the valid range.\n", _AP_W); + } else +#endif /* #if 0 */ + if (_AP_W > MAX_MODE(AP_INT_MAX_W) * 1024) { + fprintf(stderr, "[E] ap_%sfixed<%d, ...>: Bitwidth exceeds the " + "default max value %d. Please use macro " + "AP_INT_MAX_W to set a larger max value.\n", + _AP_S?"":"u", _AP_W, + MAX_MODE(AP_INT_MAX_W) * 1024); + exit(1); + } + } + + /// Constructors. + // ------------------------------------------------------------------------- +#if 0 + #ifdef __SC_COMPATIBLE__ + INLINE ap_fixed_base():V(uint32_t(_AP_W), uint64_t(0)) {} + #else + INLINE ap_fixed_base():V(uint32_t(_AP_W)) {} + #endif /* #ifdef __SC_COMPATIBLE__ */ +#else + INLINE ap_fixed_base():V(0) {} +#endif /* #if 0 */ + // INLINE ap_fixed_base():V() {} + // INLINE explicit ap_fixed_base(const ap_private<_AP_W+_AP_I, _AP_S>& _V):V(_V) {} + INLINE ap_fixed_base(const ap_fixed_base& op):V(op.V) {} + template + INLINE ap_fixed_base(const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op):V(0) { + enum {N2=_AP_W2,_AP_F=_AP_W-_AP_I,F2=_AP_W2-_AP_I2,QUAN_INC=F2>_AP_F && !(_AP_Q==AP_TRN || + (_AP_Q==AP_TRN_ZERO && !_AP_S2))}; + if (!op) return; + bool carry=false; + //handle quantization + enum { sh_amt =(F2>_AP_F)?F2-_AP_F:_AP_F-F2}; + const ap_private<_AP_W2, _AP_S2>& val = op.V; + bool neg_src=val.isNegative(); + if (F2==_AP_F) + V=val; + + else if (F2>_AP_F) { + if (sh_amt >= _AP_W2) + V = neg_src ? -1 : 0; + else + V = _AP_S2?val.ashr(sh_amt):val.lshr(sh_amt); + if (_AP_Q!=AP_TRN && !(_AP_Q==AP_TRN_ZERO && !_AP_S2)) { + bool qb = false; + if (F2-_AP_F>_AP_W2) + qb = neg_src; + else + qb = ap_private_ops::get<_AP_W2, _AP_S2, F2-_AP_F-1>(val); + + bool r=false; + enum { pos3 = F2-_AP_F-2}; + if (pos3>=_AP_W2-1) + r=val!=0; + else if (pos3>=0) + r = (val<<(_AP_W2-1-pos3))!=0; + carry = quantization_adjust(qb,r,neg_src); + } + } else { //no quantization + if (sh_amt < _AP_W) { + V=val; + V <<= sh_amt; + } + } + //hanle overflow/underflow + if ((_AP_O!=AP_WRAP || _AP_N != 0) && + ((!_AP_S && _AP_S2) || _AP_I-_AP_S < + _AP_I2 - _AP_S2 + (QUAN_INC|| (_AP_S2 && + _AP_O==AP_SAT_SYM)))) {//saturation + bool deleted_zeros = _AP_S2?true:!carry, + deleted_ones = true; + bool lD=(_AP_I2>_AP_I && _AP_W2-_AP_I2+_AP_I>=0) && + ap_private_ops::get<_AP_W2, _AP_S2, _AP_W2-_AP_I2+_AP_I>(val); + enum { pos1=F2-_AP_F+_AP_W, pos2=F2-_AP_F+_AP_W+1}; + if (pos1 < _AP_W2) { + bool Range1_all_ones= true; + bool Range1_all_zeros= true; + if (pos1 >= 0) { + enum { __W = (_AP_W2-pos1) > 0 ? (_AP_W2-pos1) : 1 }; + const ap_private<__W, _AP_S2> Range1=ap_private<__W, _AP_S2>(val.lshr(pos1)); + Range1_all_ones=Range1.isAllOnesValue(); + Range1_all_zeros=Range1.isMinValue(); + } else { + Range1_all_ones=false; + Range1_all_zeros=val.isMinValue(); + } + bool Range2_all_ones=true; + if (pos2<_AP_W2 && pos2>=0) { + enum { __W = (_AP_W2-pos2)>0 ? (_AP_W2-pos2) : 1}; + ap_private<__W, true> Range2=ap_private<__W, true>(val.lshr(pos2)); + Range2_all_ones=Range2.isAllOnesValue(); + } else if (pos2<0) + Range2_all_ones=false; + + deleted_zeros=deleted_zeros && (carry?Range1_all_ones:Range1_all_zeros); + deleted_ones=carry?Range2_all_ones&&(F2-_AP_F+_AP_W<0||!lD) + :Range1_all_ones; + neg_src= neg_src&&!(carry && Range1_all_ones); + } else + neg_src = neg_src && V[_AP_W-1]; + + bool neg_trg= V.isNegative(); + bool overflow=(neg_trg||!deleted_zeros) && !val.isNegative(); + bool underflow=(!neg_trg||!deleted_ones)&&neg_src; + //printf("neg_src = %d, neg_trg = %d, deleted_zeros = %d, + // deleted_ones = %d, overflow = %d, underflow = %d\n", + // neg_src, neg_trg, deleted_zeros, deleted_ones, + // overflow, underflow); + if (_AP_O==AP_SAT_SYM && _AP_S2 && _AP_S) + underflow |= neg_src && (_AP_W>1?V.isMinSignedValue():true); + overflow_adjust(underflow, overflow, lD, neg_src); + } + report(); + } + + template + INLINE ap_fixed_base(const volatile ap_fixed_base<_AP_W2,_AP_I2, + _AP_S2,_AP_Q2,_AP_O2, _AP_N2> &op) : V(op.V) { + *this = const_cast&>(op); + } + + template + INLINE ap_fixed_base(const ap_private<_AP_W2,_AP_S2>& op) { + ap_fixed_base<_AP_W2,_AP_W2,_AP_S2> f_op; + f_op.V=op; + *this = f_op; + } + + INLINE ap_fixed_base(bool b) { + *this=(ap_private<1,false>)b; + report(); + } + + INLINE ap_fixed_base(char b) { + *this=(ap_private<8,false>)b; + report(); + } + + INLINE ap_fixed_base(signed char b) { + *this=(ap_private<8,true>)b; + report(); + } + + INLINE ap_fixed_base(unsigned char b) { + *this=(ap_private<8,false>)b; + report(); + } + + INLINE ap_fixed_base(signed short b) { + *this=(ap_private<16,true>)b; + report(); + } + + INLINE ap_fixed_base(unsigned short b) { + *this=(ap_private<16,false>)b; + report(); + } + + INLINE ap_fixed_base(signed int b) { + *this=(ap_private<32,true>)b; + report(); + } + + INLINE ap_fixed_base(unsigned int b) { + *this=(ap_private<32,false>)b; + report(); + } +# if defined __x86_64__ + INLINE ap_fixed_base(signed long b) { + *this=(ap_private<64,true>)b; + report(); + } + + INLINE ap_fixed_base(unsigned long b) { + *this=(ap_private<64,false>)b; + report(); + } +# else + INLINE ap_fixed_base(signed long b) { + *this=(ap_private<32,true>)b; + report(); + } + + INLINE ap_fixed_base(unsigned long b) { + *this=(ap_private<32,false>)b; + report(); + } +# endif + + INLINE ap_fixed_base(ap_slong b) { + *this=(ap_private<64,true>)b; + report(); + } + + INLINE ap_fixed_base(ap_ulong b) { + *this=(ap_private<64,false>)b; + report(); + } + +#if 1 + INLINE ap_fixed_base(const char* val):V(0) { + ap_private<_AP_W, _AP_S> Tmp(val); + V = Tmp; + } + + INLINE ap_fixed_base(const char* val, signed char rd): V(0) { + ap_private<_AP_W, _AP_S> Tmp(val, rd); + V = Tmp; + } + +#endif + + INLINE ap_fixed_base(const std::string& val) { + ap_private<_AP_W, _AP_S> Tmp(val, 2); + V = Tmp; + report(); + } + + template + INLINE ap_fixed_base(const ap_bit_ref<_AP_W2, _AP_S2>& op) { + *this = ((bool)op); + report(); + } + + template + INLINE ap_fixed_base(const ap_range_ref<_AP_W2, _AP_S2>& op) { + *this = ap_private<_AP_W2, _AP_S2>(op); + report(); + } + + template + INLINE ap_fixed_base(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& op) { + *this = ((const ap_private<_AP_W2 + _AP_W3, false>&)(op)); + report(); + } + + template + INLINE ap_fixed_base(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) { + *this = (bool(op)); + report(); + } + + template + INLINE ap_fixed_base(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) { + *this = (ap_private<_AP_W2, false>(op)); + report(); + } + + //helper function + INLINE unsigned long long doubleToRawBits(double pf)const { + union { + unsigned long long __L; + double __D; + }LD; + LD.__D=pf; + return LD.__L; + } + + + INLINE double rawBitsToDouble(unsigned long long pi) const { + union { + unsigned long long __L; + double __D; + }LD; + LD.__L=pi; + return LD.__D; + } + + INLINE float rawBitsToFloat(uint32_t pi) const { + union { + uint32_t __L; + float __D; + }LD; + LD.__L = pi; + return LD.__D; + } + + INLINE ap_fixed_base(double d):V(0) { + if (!d) return; + const bool isneg=d<0; + + const uint64_t ireg=doubleToRawBits(isneg?-d:d); + if ((ireg&0x7fffffffffffffffULL)!=0) { + const int32_t exp=(((ireg)>>DOUBLE_MAN)&0x07ff)-DOUBLE_BIAS; + ap_private man = ireg & DOUBLE_MAN_MASK; + man.clear(DOUBLE_MAN+1); + man.set(DOUBLE_MAN); + if (isneg) { + man.flip(); + man++; + } + + enum {_AP_S2=true, _AP_W2=DOUBLE_MAN+2,_AP_F=_AP_W -_AP_I }; + const int _AP_I2=exp+2; + const int F2=_AP_W2-_AP_I2; + const bool QUAN_INC=F2>_AP_F && !(_AP_Q==AP_TRN || (_AP_Q==AP_TRN_ZERO && + !_AP_S2)); + bool carry=false; + //handle quantization + const unsigned sh_amt=abs(F2-_AP_F); // sh_amt = F2>_AP_F ? F2 -_AP_F : _AP_F-F2; + if (F2==_AP_F ) + V=man; + else if (F2>_AP_F) { + if (sh_amt >= DOUBLE_MAN+2) + V=isneg?-1:0; + else + V=(man>>sh_amt) | ((man & 1ULL<<(DOUBLE_MAN+1)) ? (DOUBLE_MAN_MASK>>(DOUBLE_MAN+2-sh_amt) <<(DOUBLE_MAN+2-sh_amt)):0); + + if (_AP_Q!=AP_TRN && !(_AP_Q==AP_TRN_ZERO && !_AP_S2)) { + const bool qb=((F2-_AP_F > DOUBLE_MAN+2) ? isneg : (man & (1ULL<<(F2-_AP_F-1))) != 0); + const int pos3=F2-_AP_F-2; + const bool r = (pos3>= 0) ? (man << AP_MAX(0, _AP_W2-pos3-1)& DOUBLE_MAN_MASK)!=0 : false; + carry = quantization_adjust(qb,r,isneg); + } + } + else { //no quantization + // V=man; + if (sh_amt < _AP_W) { + V = man; + V <<= sh_amt; + } + } + //handle overflow/underflow + if ((_AP_O != AP_WRAP || _AP_N != 0) && + ((!_AP_S && _AP_S2) || _AP_I-_AP_S < + _AP_I2-_AP_S2+(QUAN_INC|| (_AP_S2 && + _AP_O==AP_SAT_SYM)) )) {// saturation + bool deleted_zeros = _AP_S2?true:!carry, + deleted_ones = true; + bool neg_src; + const bool lD=(_AP_I2>_AP_I) && (_AP_W2-_AP_I2+_AP_I>=0) && (man & (1ULL <<(DOUBLE_MAN+2-_AP_I2+_AP_I))); + int pos1=F2+_AP_W-_AP_F; + if (pos1 < _AP_W2) { + int pos2=pos1+1; + bool Range1_all_ones=true; + bool Range1_all_zeros=true; + if (pos1>=0) { + ap_private<_AP_W,_AP_S> Range1= + ap_private<_AP_W,_AP_S>((man >> pos1) | ((1ULL<<(DOUBLE_MAN+1)&man) ? (DOUBLE_MAN_MASK >> (DOUBLE_MAN+2-pos1) <<(DOUBLE_MAN+2-pos1)):0)); + Range1_all_ones = Range1.isAllOnesValue(); // Range1.isAllOnesValue(); + Range1_all_zeros = Range1.isMinValue(); // Range1.isMinValue(); + } else { + Range1_all_ones=false; + Range1_all_zeros = man==0; // man.isMinValue(); + } + bool Range2_all_ones=true; + if (pos2<_AP_W2 && pos2>=0) { + ap_private<_AP_W, _AP_S> Range2= + ap_private<_AP_W, _AP_S>((man >> pos2) | ((1ULL<<(DOUBLE_MAN+1)&man) ? (DOUBLE_MAN_MASK >> (DOUBLE_MAN+2-pos2) <<(DOUBLE_MAN+2-pos2)):0)); + Range2_all_ones=Range2.isAllOnesValue(); // Range2.isAllOnesValue(); + } else if (pos2<0) + Range2_all_ones=false; + deleted_zeros=deleted_zeros && (carry?Range1_all_ones:Range1_all_zeros); + deleted_ones=carry?Range2_all_ones&&(F2-_AP_F+_AP_W<0||!lD) : Range1_all_ones; + neg_src=isneg&&!(carry&Range1_all_ones); + } else + neg_src = isneg && V[_AP_W -1]; + + const bool neg_trg=V.isNegative(); + const bool overflow=(neg_trg||!deleted_zeros) && !isneg; + bool underflow=(!neg_trg||!deleted_ones)&&neg_src; + //printf("neg_src = %d, neg_trg = %d, deleted_zeros = %d, + // deleted_ones = %d, overflow = %d, underflow = %d\n", + // neg_src, neg_trg, deleted_zeros, deleted_ones, + // overflow, underflow); + if (_AP_O==AP_SAT_SYM && _AP_S2 && _AP_S) + underflow |= neg_src && (_AP_W>1?V.isMinSignedValue():true); + overflow_adjust(underflow,overflow,lD, neg_src); + } + } + report(); + } + + + ///assign operators + //------------------------------------------------------------------------- + + INLINE volatile ap_fixed_base& operator=(const ap_fixed_base<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& op) volatile { + V = op.V; + return *this; + } + + INLINE ap_fixed_base& operator=(const ap_fixed_base<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& op) { + V = op.V; + return *this; + } + + INLINE volatile ap_fixed_base& operator=(const volatile ap_fixed_base<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& op) volatile { + V = op.V; + return *this; + } + + INLINE ap_fixed_base& operator=(const volatile ap_fixed_base<_AP_W, _AP_I, _AP_S, + _AP_Q, _AP_O, _AP_N>& op) { + V = op.V; + return *this; + } + + // Set this ap_fixed_base with a bits string. That means the ssdm_int::V + // inside this ap_fixed_base is assigned by bv. + // Note the input parameter should be a fixed-point formatted bit string. + INLINE ap_fixed_base& setBits(unsigned long long bv) { + V=bv; + return *this; + } + + // Return a ap_fixed_base object whose ssdm_int::V is assigned by bv. + // Note the input parameter should be a fixed-point formatted bit string. + static INLINE ap_fixed_base bitsToFixed(unsigned long long bv) { + ap_fixed_base Tmp=bv; + return Tmp; + } + + // Explicit conversion functions to ap_private that captures + // all integer bits (bits are truncated) + INLINE ap_private + to_ap_private(bool Cnative = true) const { + ap_private ret = ap_private ((_AP_I >= 1) ? (_AP_S==true ? V.ashr(AP_MAX(0,_AP_W - _AP_I)) : V.lshr(AP_MAX(0,_AP_W - _AP_I))) : ap_private<_AP_W, _AP_S>(0)); + + if (Cnative) { + bool r = false; + if (_AP_I < _AP_W) { + if (_AP_I > 0) r = !(V.getLoBits(_AP_W - _AP_I).isMinValue()); + else r = !(V.isMinValue()); + } + if (r && V.isNegative()) { // if this is negative integer + ++ret;//ap_private(1,_AP_S); + } + } else { + //Follow OSCI library, conversion from sc_fixed to sc_int + } + return ret; + } + + template + INLINE operator ap_private<_AP_W2,_AP_S2> () const { + return (ap_private<_AP_W2,_AP_S2>)to_ap_private(); + } + + template + INLINE operator ap_private<_AP_W2,_AP_S2,_AP_N2> () const { + return (ap_private<_AP_W2,_AP_S2,_AP_N2>)to_ap_private(); + } + + //Explict conversion function to C built-in integral type + INLINE int to_int() const { + return to_ap_private().to_int(); + } + + INLINE int to_uint() const { + return to_ap_private().to_uint(); + } + + INLINE ap_slong to_int64() const { + return to_ap_private().to_int64(); + } + + INLINE ap_ulong to_uint64() const { + return to_ap_private().to_uint64(); + } + + INLINE double to_double() const { + if (!V) + return 0; + if (_AP_W>64 || (_AP_W - _AP_I) > 0) { + bool isneg = _AP_S && V[_AP_W-1]; + uint64_t res = isneg ? 0x8000000000000000ULL : 0; + ap_private<_AP_W, false> tmp = V; + if (isneg) tmp = -tmp; + int i = _AP_W -1 - tmp.countLeadingZeros(); + int exp = _AP_I-(_AP_W-i); + res|=((uint64_t)(exp+DOUBLE_BIAS))<DOUBLE_MAN)?tmp.lshr(i-DOUBLE_MAN):tmp).to_uint64() & DOUBLE_MAN_MASK; + res |= i 0) { + /* This specialization is disabled. It is giving wrong results in some cases. + bool isneg=V.isNegative(); + double dp = V.get(); + dp /= (1<< (_AP_W - _AP_I)); + return dp;*/ + } else + return double(to_int64()); + } + + INLINE float to_float() const { + uint32_t res=0; + if (V==0) + return 0; + bool isneg=V.isNegative(); + ap_private<_AP_W, _AP_S> tmp=V; + if (isneg) tmp = -tmp; + if (_AP_W-_AP_I>0||_AP_W>64) { + if (isneg) + res=0x80000000; + int i=_AP_W-1; + i-=tmp.countLeadingZeros(); + int exp=_AP_I-(_AP_W-i); + res|=(exp+FLOAT_BIAS)< man = 0; + if (i!=0) { + tmp.clear(i); + if (i>FLOAT_MAN) + man=tmp.lshr(i-FLOAT_MAN); + else + man=tmp; + res |= i < FLOAT_MAN?man.getZExtValue()<<(FLOAT_MAN-i):man.getZExtValue(); + } + } else { + return float(to_int64()); + } + float dp=rawBitsToFloat(res); + return dp; + } + + INLINE operator double () const { + return to_double(); + } +#ifndef __SC_COMPATIBLE__ + INLINE operator float () const { + return to_float(); + } + + INLINE operator char () const { + return (char) to_int(); + } + + INLINE operator unsigned char () const { + return (unsigned char) to_uint(); + } + + INLINE operator short () const { + return (short) to_int(); + } + + INLINE operator unsigned short () const { + return (unsigned short) to_uint(); + } + + INLINE operator int () const { + return to_int(); + } + + INLINE operator unsigned int () const { + return to_uint(); + } +#if 1 +#ifdef __x86_64__ + INLINE operator long () const { + return (long)to_int64(); + } + + INLINE operator unsigned long () const { + return (unsigned long) to_uint64(); + } +#else + INLINE operator long () const { + return to_int64(); + } + + INLINE operator unsigned long () const { + return to_uint64(); + } + +#endif +#endif + INLINE operator unsigned long long () const { + return to_uint64(); + } + + INLINE operator long long () const { + return to_int64(); + } +#endif + + INLINE std::string to_string(uint8_t radix=2, bool sign=false) const; + + INLINE ap_slong bits_to_int64() const { + ap_private res(V); + return (ap_slong) res; + } + + INLINE ap_ulong bits_to_uint64() const { + ap_private res(V); + return (ap_ulong) res; + } + + INLINE int length() const {return _AP_W;} + + // Count the number of zeros from the most significant bit + // to the first one bit. Note this is only for ap_fixed_base whose + // _AP_W <= 64, otherwise will incur assertion. + INLINE int countLeadingZeros() { + return V.countLeadingZeros(); + } + + ///Arithmetic:Binary + //------------------------------------------------------------------------- + template + INLINE typename RType<_AP_W2,_AP_I2,_AP_S2>::mult + operator * (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + typename RType<_AP_W2,_AP_I2,_AP_S2>::mult r; + r.V = V * op2.V; + return r; + } + + template + static INLINE ap_fixed_base multiply(const ap_fixed_base<_AP_W1,_AP_I1,_AP_S1>& op1, const + ap_fixed_base<_AP_W2,_AP_I2,_AP_S2>& op2) { + ap_private<_AP_W+_AP_W2, _AP_S> OP1=op1.V; + ap_private<_AP_W2,_AP_S2> OP2=op2.V; + return OP1*OP2; + } + + template + INLINE typename RType<_AP_W2,_AP_I2,_AP_S2>::div + operator / (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + enum {F2 = _AP_W2-_AP_I2, _W1=AP_MAX(_AP_W + AP_MAX(F2, 0), _AP_W2), + _W2=AP_MAX(_AP_W2,AP_MAX(_AP_W + AP_MAX(F2, 0), _AP_W2))}; + ap_private<_W1, _AP_S> dividend = (ap_private<_W1, _AP_S>(V)) << ((_W1>_AP_W)?F2:0); + ap_private<_W1, _AP_S2> divisior = ap_private<_W2, _AP_S2>(op2.V); + ap_private<_W1, _AP_S> ret = ap_private<_W1,_AP_S> ((_AP_S||_AP_S2) ? dividend.sdiv(divisior): dividend.udiv(divisior)); + typename RType<_AP_W2, _AP_I2, _AP_S2>::div r; + r.V = ret; + return r; + } +#define OP_BIN_AF(Sym, Rty, Width, Sign, Fun) \ + template \ + INLINE typename RType<_AP_W2,_AP_I2,_AP_S2>::Rty \ + operator Sym (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const \ + { \ + enum {_AP_F=_AP_W-_AP_I, F2=_AP_W2-_AP_I2}; \ + typename RType<_AP_W2,_AP_I2,_AP_S2>::Rty r, lhs(*this), rhs(op2); \ + r.V = lhs.V.Fun(rhs.V); \ + return r; \ + } \ + INLINE typename RType<_AP_W,_AP_I,_AP_S>::Rty \ + operator Sym (const ap_fixed_base& op2) const \ + { \ + typename RType<_AP_W,_AP_I,_AP_S>::Rty r; \ + r.V = V Sym op2.V; \ + return r; \ + } \ + + OP_BIN_AF(+, plus, plus_w, plus_s, Add) + OP_BIN_AF(-, minus, minus_w, minus_s, Sub) + +#define OP_LOGIC_BIN_AF(Sym, Rty, Width, Sign) \ + template \ + INLINE typename RType<_AP_W2,_AP_I2,_AP_S2>::Rty \ + operator Sym (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const \ + { \ + typename RType<_AP_W2,_AP_I2,_AP_S2>::Rty r, lhs(*this), rhs(op2); \ + r.V=lhs.V Sym rhs.V; \ + return r; \ + } \ + INLINE typename RType<_AP_W,_AP_I,_AP_S>::Rty \ + operator Sym (const ap_fixed_base& op2) const \ + { \ + typename RType<_AP_W,_AP_I,_AP_S>::Rty r; \ + r.V = V Sym op2.V; \ + return r; \ + } \ + INLINE typename RType<_AP_W,_AP_I,_AP_S>::Rty operator Sym(int op2) const \ + { \ + return V Sym (op2<<(_AP_W - _AP_I)); \ + } + OP_LOGIC_BIN_AF(&, logic, logic_w, logic_s) + OP_LOGIC_BIN_AF(|, logic, logic_w, logic_s) + OP_LOGIC_BIN_AF(^, logic, logic_w, logic_s) + + ///Arithmic : assign + //------------------------------------------------------------------------- +#define OP_ASSIGN_AF(Sym) \ + template \ + INLINE ap_fixed_base& operator Sym##= (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) \ + { \ + *this=operator Sym (op2) ; \ + return *this; \ + } + + OP_ASSIGN_AF(+) + OP_ASSIGN_AF(-) + OP_ASSIGN_AF(&) + OP_ASSIGN_AF(|) + OP_ASSIGN_AF(^) + OP_ASSIGN_AF(*) + OP_ASSIGN_AF(/) + + ///Prefix increment, decrement + //------------------------------------------------------------------------- + INLINE ap_fixed_base& operator ++() { + operator+=(ap_fixed_base<1,1,false>(1)); //SystemC's semantics + return *this; + } + + INLINE ap_fixed_base& operator --() { + operator-=(ap_fixed_base<1,1,false>(1)); //SystemC's semantics + return *this; + } + + //Postfix increment, decrement + //------------------------------------------------------------------------- + INLINE const ap_fixed_base operator ++(int) { + ap_fixed_base t(*this); + operator++(); + return t; + } + + INLINE const ap_fixed_base operator --(int) { + ap_fixed_base t = *this; + operator--(); + return t; + } + + ///Unary arithmetic + //------------------------------------------------------------------------- + INLINE ap_fixed_base operator +() {return *this;} + + INLINE ap_fixed_base<_AP_W + 1, _AP_I + 1, true> operator -() const { + ap_fixed_base<_AP_W + 1, _AP_I + 1, true> Tmp(*this); + Tmp.V = - Tmp.V; + return Tmp; + } + + INLINE ap_fixed_base<_AP_W,_AP_I,true,_AP_Q,_AP_O, _AP_N> getNeg() { + ap_fixed_base<_AP_W,_AP_I,true,_AP_Q,_AP_O, _AP_N> Tmp(*this); + Tmp.V=-Tmp.V; + return Tmp; + } + + ///Not (!) + //------------------------------------------------------------------------- + INLINE bool operator !() const { + return !V; + } + + ///Bitwise complement + //------------------------------------------------------------------------- + INLINE ap_fixed_base<_AP_W, _AP_I, _AP_S> + operator ~() const { + ap_fixed_base<_AP_W, _AP_I, _AP_S> res(*this); + res.V.flip(); + return res; + } + + ///Shift + ///template argument as shift value + template + INLINE ap_fixed_base<_AP_W, _AP_I + _AP_SHIFT, _AP_S> lshift () const { + ap_fixed_base<_AP_W, _AP_I + _AP_SHIFT, _AP_S> r; + r.V = V; + return r; + } + + template + INLINE ap_fixed_base<_AP_W, _AP_I - _AP_SHIFT, _AP_S> rshift () const { + ap_fixed_base<_AP_W, _AP_I - _AP_SHIFT, _AP_S> r; + r.V = V; + return r; + } + + //Because the return type is the type of the the first operand, shift assign + //operators do not carry out any quantization or overflow + //While systemc, shift assigns for sc_fixed/sc_ufixed will result in + //quantization or overflow (depending on the mode of the first operand) + //------------------------------------------------------------------------- + INLINE ap_fixed_base operator << (int sh) const { + ap_fixed_base r; + bool isNeg=(sh&0x80000000) != 0; + sh=isNeg?-sh:sh; + bool shiftoverflow = sh >= _AP_W; + bool NegSrc = V.isNegative(); + if (isNeg) { + if (shiftoverflow) + NegSrc?r.V.set():r.V.clear(); + else + r.V=_AP_S?V.ashr(sh):V.lshr(sh); + } else { + if (shiftoverflow) + r.V.clear(); + else + r.V=V< 1 && sh <= _AP_W) + rb = (V << (_AP_W - sh + 1 )) != 0; + else if (sh > _AP_W) + rb = V != 0; + r.quantization_adjust(qb, rb, NegSrc); + } else if (isNeg == false && _AP_O != AP_WRAP) { + bool allones, allzeros; + if (sh < _AP_W ) { + ap_private<_AP_W, _AP_S > range1 = V.lshr(_AP_W - sh - 1); + allones = range1.isAllOnesValue(); + allzeros = range1.isMinValue(); + } else { + allones = false; + allzeros = V.isMinValue(); + } + bool overflow = !allzeros && !NegSrc; + bool underflow = !allones && NegSrc; + if (_AP_O == AP_SAT_SYM && _AP_S) + underflow |= NegSrc && (_AP_W > 1 ? r.V.isMinSignedValue():true); + bool lD = false; + if ( sh < _AP_W ) lD = V[_AP_W - sh - 1]; + r.overflow_adjust(underflow, overflow, lD, NegSrc); + } +#endif + return r; + } + + template + INLINE ap_fixed_base operator<<(const ap_private<_AP_W2,true>& op2) const { + int sh = op2.to_int(); + return operator << (sh); + } + + INLINE ap_fixed_base operator << (unsigned int sh ) const { + ap_fixed_base r; + bool shiftoverflow = sh >= _AP_W; + r.V = shiftoverflow ? ap_private<_AP_W, _AP_S >(0) : V << sh; + if (sh == 0) return r; +#ifdef __SC_COMPATIBLE__ + bool NegSrc = V.isNegative(); + if (_AP_O != AP_WRAP) { + bool allones, allzeros; + if (sh < _AP_W ) { + ap_private<_AP_W, _AP_S > range1 = V.lshr(_AP_W - sh -1); + allones = range1.isAllOnesValue(); + allzeros = range1.isMinValue(); + } else { + allones = false; + allzeros = V.isMinValue(); + } + bool overflow = !allzeros && !NegSrc; + bool underflow = !allones && NegSrc; + if (_AP_O == AP_SAT_SYM && _AP_S) + underflow |= NegSrc && (_AP_W > 1 ? r.V.isMinSignedValue():true); + bool lD = false; + if ( sh < _AP_W ) lD = V[_AP_W - sh - 1]; + r.overflow_adjust(underflow, overflow, lD, NegSrc); + } +#endif + return r; + } + + template + INLINE ap_fixed_base operator << (const ap_private<_AP_W2,false>& op2) const { + unsigned int sh = op2.to_uint(); + return operator << (sh); + } + + INLINE ap_fixed_base operator >> (int sh) const { + ap_fixed_base r; + bool isNeg=(sh&0x80000000) != 0; + bool NegSrc = V.isNegative(); + sh=isNeg?-sh:sh; + bool shiftoverflow = sh >= _AP_W; + if (isNeg && !shiftoverflow) r.V=V< 1 && sh <= _AP_W) + rb = (V << (_AP_W - sh + 1 )) != 0; + else if (sh > _AP_W) + rb = V != 0; + r.quantization_adjust(qb, rb, NegSrc); + } else if (isNeg == true && _AP_O != AP_WRAP) { + bool allones, allzeros; + if (sh < _AP_W ) { + ap_private<_AP_W, _AP_S > range1 = V.lshr(_AP_W - sh - 1); + allones = range1.isAllOnesValue(); + allzeros = range1.isMinValue(); + } else { + allones = false; + allzeros = V.isMinValue(); + } + bool overflow = !allzeros && !NegSrc; + bool underflow = !allones && NegSrc; + if (_AP_O == AP_SAT_SYM && _AP_S) + underflow |= NegSrc && (_AP_W > 1 ? r.V.isMinSignedValue():true); + bool lD = false; + if ( sh < _AP_W ) lD = V[_AP_W - sh - 1]; + r.overflow_adjust(underflow, overflow, lD, NegSrc); + } +#endif + return r; + } + + template + INLINE ap_fixed_base operator >> (const ap_private<_AP_W2,true>& op2) const { + int sh = op2.to_int(); + return operator >> (sh); + } + + INLINE ap_fixed_base operator >> (unsigned int sh) const { + ap_fixed_base r; + bool NegSrc = V.isNegative(); + bool shiftoverflow = sh >= _AP_W; + if (shiftoverflow) + NegSrc?r.V.set():r.V.clear(); + else + r.V=_AP_S?V.ashr(sh):V.lshr(sh); +#ifdef __SC_COMPATIBLE__ + if (sh == 0) return r; + if (_AP_Q != AP_TRN) { + bool qb = false; + if (sh <= _AP_W) qb = V[sh - 1]; + bool rb = false; + if (sh > 1 && sh <= _AP_W) + rb = (V << (_AP_W - sh + 1 )) != 0; + else if (sh > _AP_W) + rb = V != 0; + r.quantization_adjust(qb, rb, NegSrc); + } +#endif + return r; + } + + template + INLINE ap_fixed_base operator >> (const ap_private<_AP_W2,false>& op2) const { + unsigned int sh = op2.to_uint(); + return operator >> (sh); + } + + ///shift assign + //------------------------------------------------------------------------- +#define OP_AP_SHIFT_AP_ASSIGN_AF(Sym) \ + template \ + INLINE ap_fixed_base& operator Sym##=(const ap_private<_AP_W2,_AP_S2>& op2) \ + { \ + *this=operator Sym (op2); \ + return *this; \ + } + + OP_AP_SHIFT_AP_ASSIGN_AF(<<) + OP_AP_SHIFT_AP_ASSIGN_AF(>>) + + ///Support shift(ap_fixed_base) +#define OP_AP_SHIFT_AF(Sym) \ + template \ + INLINE ap_fixed_base operator Sym (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const \ + { \ + return operator Sym (op2.to_ap_private()); \ + } \ + template \ + INLINE ap_fixed_base& operator Sym##= (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) \ + { \ + *this=operator Sym (op2); \ + return *this; \ + } + + OP_AP_SHIFT_AF(<<) + OP_AP_SHIFT_AF(>>) + + INLINE ap_fixed_base& operator >>= (unsigned int sh) { + *this = operator >> (sh); + return *this; + } + + INLINE ap_fixed_base& operator <<= (unsigned int sh) { + *this = operator << (sh); + return *this; + } + + INLINE ap_fixed_base& operator >>= (int sh) { + *this = operator >> (sh); + return *this; + } + + INLINE ap_fixed_base& operator <<= (int sh) { + *this = operator << (sh); + return *this; + } + + ///Comparisons + //------------------------------------------------------------------------- + template + INLINE bool operator == (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + enum {_AP_F=_AP_W-_AP_I,F2=_AP_W2-_AP_I2, shAmt1 = AP_MAX(F2-_AP_F, 0), shAmt2 = AP_MAX(_AP_F-F2,0), _AP_W3 = (_AP_F==F2) ? AP_MAX(_AP_W,_AP_W2) : AP_MAX(_AP_W+shAmt1, _AP_W2+shAmt2)}; + ap_private<_AP_W3, _AP_S > OP1= ap_private<_AP_W3, _AP_S >(V)< OP2=ap_private<_AP_W3,_AP_S2 >(op2.V)< + INLINE bool operator != (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + return !(*this==op2); + } + + template + INLINE bool operator > (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + enum {_AP_F=_AP_W-_AP_I,F2=_AP_W2-_AP_I2, shAmt1 = AP_MAX(F2-_AP_F, 0), shAmt2 = AP_MAX(_AP_F-F2,0), _AP_W3 = (_AP_F==F2) ? AP_MAX(_AP_W,_AP_W2) : AP_MAX(_AP_W+shAmt1, _AP_W2+shAmt2)}; + ap_private<_AP_W3, _AP_S > OP1= ap_private<_AP_W3, _AP_S >(V)< OP2=ap_private<_AP_W3,_AP_S2 >(op2.V)< + INLINE bool operator <= (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + return !(*this>op2); + } + + template + INLINE bool operator < (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + enum {_AP_F=_AP_W-_AP_I,F2=_AP_W2-_AP_I2, shAmt1 = AP_MAX(F2-_AP_F, 0), shAmt2 = AP_MAX(_AP_F-F2,0), _AP_W3 = (_AP_F==F2) ? AP_MAX(_AP_W,_AP_W2) : AP_MAX(_AP_W+shAmt1, _AP_W2+shAmt2)}; + ap_private<_AP_W3, _AP_S > OP1= ap_private<_AP_W3, _AP_S >(V)< OP2=ap_private<_AP_W3,_AP_S2 >(op2.V)< + INLINE bool operator >= (const ap_fixed_base<_AP_W2,_AP_I2,_AP_S2,_AP_Q2,_AP_O2, _AP_N2>& op2) const { + return !(*this) + DOUBLE_CMP_AF(>=) + DOUBLE_CMP_AF(<) + DOUBLE_CMP_AF(<=) + + // Bit and Slice Select + INLINE af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N> operator [] (unsigned int index) { + assert(index<_AP_W&&"Attemping to read bit beyond MSB"); + return af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>(this, index); + } + + INLINE af_bit_ref<_AP_W, _AP_I,_AP_S,_AP_Q,_AP_O, _AP_N> bit(unsigned int index) { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>(this, index); + } + + template + INLINE af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N> bit (const ap_private<_AP_W2,_AP_S2>& index) { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>(this, index.to_int()); + } + + INLINE bool bit (unsigned int index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return V[index]; + } + + INLINE bool operator [] (unsigned int index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return V[index]; + } + + template + INLINE bool bit (const ap_private<_AP_W2, _AP_S2>& index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return V[index.to_uint()]; + } + + template + INLINE bool operator [] (const ap_private<_AP_W2, _AP_S2>& index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return V[index.to_uint()]; + } + + INLINE af_bit_ref<_AP_W, _AP_I,_AP_S,_AP_Q,_AP_O, _AP_N> get_bit(int index) { + assert(index < _AP_I && "Attempting to read bit beyond MSB"); + assert(index >= _AP_I - _AP_W&& "Attempting to read bit beyond MSB"); + return af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>(this, index + _AP_W - _AP_I); + } + + template + INLINE af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N> get_bit (const ap_private<_AP_W2, true>& index) { + assert(index >= _AP_I - _AP_W && "Attempting to read bit with negative index"); + assert(index < _AP_I && "Attempting to read bit beyond MSB"); + return af_bit_ref<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>(this, index.to_int() + _AP_W - _AP_I); + } + + INLINE bool get_bit (int index) const { + assert(index >= _AP_I - _AP_W && "Attempting to read bit with negative index"); + assert(index < _AP_I && "Attempting to read bit beyond MSB"); + return V[index + _AP_W - _AP_I]; + } + + template + INLINE bool get_bit (const ap_private<_AP_W2, true>& index) const { + assert(index >= _AP_I - _AP_W && "Attempting to read bit with negative index"); + assert(index < _AP_I && "Attempting to read bit beyond MSB"); + return V[index.to_int() + _AP_W - _AP_I]; + } + + INLINE af_range_ref<_AP_W,_AP_I,_AP_S, _AP_Q, _AP_O, _AP_N> + range(int Hi, int Lo) { + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>(this, Hi, Lo); + } + + INLINE af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> + operator () (int Hi, int Lo) { + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>(this, Hi, Lo); + } + + INLINE af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> + range(int Hi, int Lo) const { + assert((Hi < _AP_W) && (Lo < _AP_W) &&"Out of bounds in range()"); + return af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>(const_cast(this), Hi, Lo); + } + + INLINE af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> + operator () (int Hi, int Lo) const { + return this->range(Hi, Lo); + } + + template + INLINE af_range_ref<_AP_W,_AP_I,_AP_S, _AP_Q, _AP_O, _AP_N> + range(const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>(this, Hi, Lo); + } + + template + INLINE af_range_ref<_AP_W,_AP_I,_AP_S, _AP_Q, _AP_O, _AP_N> + operator () (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>(this, Hi, Lo); + } + + template + INLINE af_range_ref<_AP_W,_AP_I,_AP_S, _AP_Q, _AP_O, _AP_N> + range(const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) const { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>(const_cast< + ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>*>(this), + Hi, Lo); + } + + template + INLINE af_range_ref<_AP_W,_AP_I,_AP_S, _AP_Q, _AP_O, _AP_N> + operator () (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) const { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + return this->range(Hi, Lo); + } + + INLINE af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> + range() { + return this->range(_AP_W - 1, 0); + } + + INLINE af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> + range() const { + return this->range(_AP_W - 1, 0); + } + + INLINE bool is_zero () const { + return V.isMinValue(); + } + + INLINE bool is_neg () const { + if (V.isNegative()) + return true; + return false; + } + + INLINE int wl () const { + return _AP_W; + } + + INLINE int iwl () const { + return _AP_I; + } + + INLINE ap_q_mode q_mode () const { + return _AP_Q; + } + + INLINE ap_o_mode o_mode () const { + return _AP_O; + } + + INLINE int n_bits () const { + return 0; + } + + //private: +public: + ap_private<_AP_W, _AP_S> V; +}; + +template +std::string ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>::to_string( + uint8_t radix, bool sign) const { + std::string str; + str.clear(); + char step; + std::string prefix; + switch (radix) { + case 2 : prefix = "0b"; step = 1; break; + case 8 : prefix = "0o"; step = 3; break; + case 16 : prefix = "0x"; step = 4; break; + default : break; + } + if (_AP_W <= _AP_I) + str = this->to_ap_private().to_string(radix, + radix == 10 ? _AP_S : sign); + else { + if (radix == 10) { + bool isNeg = _AP_S && V.isNegative(); + if (_AP_I > 0) { + ap_private int_part(0); + int_part = this->to_ap_private(); + str += int_part.to_string(radix, false); + } else { + if (isNeg) str += '-'; + } + ap_fixed_base<_AP_W, _AP_I, _AP_S> tmp(*this); + if (isNeg && _AP_I <= 0) tmp = -tmp; + ap_fixed_base<_AP_W - AP_MIN(_AP_I, 0), 0, false> frac_part = tmp; + if (frac_part == 0) return str; + str += "."; + while (frac_part != 0) { + char digit = (frac_part * radix).to_ap_private(); + str += static_cast(digit + '0'); + frac_part *= radix; + } + } else { + if (_AP_I > 0) { + for (signed i = _AP_W - _AP_I; i < _AP_W; i += step) { + + char digit = (char)(this->range(AP_MIN(i + step - 1, _AP_W - 1), i)); + str = (digit < 10 ? static_cast(digit + '0') : + static_cast(digit - 10 + 'a')) + str; + } + } + str += '.'; + ap_fixed_base tmp(*this); + for (signed i = _AP_W - _AP_I - 1; i >= 0; i -= step) { + char digit = (char)(tmp.range(i, AP_MAX(0, i - step + 1))); + str += digit < 10 ? static_cast(digit + '0') : + static_cast(digit - 10 + 'a'); + } + } + } + str = prefix + str; + return str; +} + +template +INLINE void b_not(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op) { + ret.V = op.V; + ret.V.flip(); +} + +template +INLINE void b_and(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op1, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op2) { + ret.V = op1.V & op2.V; +} + +template +INLINE void b_or(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op1, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op2) { + ret.V = op1.V | op2.V; +} + +template +INLINE void b_xor(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op1, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op2) { + ret.V = op1.V ^ op2.V; +} + +template +INLINE void neg(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) { + ap_fixed_base<_AP_W2+!_AP_S2, _AP_I2+!_AP_S2, true, _AP_Q2, _AP_O2, _AP_N2> Tmp; + Tmp.V = - op.V; + ret = Tmp; +} + +template +INLINE void neg(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op) { + ret.V = -op.V; +} + +template +INLINE void lshift(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op, + int i) { + ap_fixed_base<_AP_W2 - _AP_I2 + AP_MAX(_AP_I, _AP_I2), AP_MAX(_AP_I, _AP_I2), _AP_S2, _AP_Q2, _AP_O2, _AP_N2> Tmp; + Tmp = op; + Tmp.V <<= i; + ret = Tmp; +} + +template +INLINE void lshift(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op, + int i) { + ret.V = op.V << i; +} + +template +INLINE void rshift(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op, + int i) { + ap_fixed_base<_AP_I2 + AP_MAX(_AP_W - _AP_I, _AP_W2 - _AP_I2), _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> Tmp; + Tmp = op; + Tmp.V = _AP_S2 ? Tmp.V.ashr(i): Tmp.V.lshr(i); + ret = Tmp; +} + +template +INLINE void rshift(ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, + const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op, + int i) { + ret.V = _AP_S ? op.V.ashr(i): op.V.lshr(i); +} + +#define AF_CTOR_SPEC_BASE(_AP_W,_AP_S,C_TYPE) \ + template<> INLINE ap_fixed_base<_AP_W,_AP_W,_AP_S,AP_TRN,AP_WRAP>::ap_fixed_base(C_TYPE i_op):V(i_op) \ + { \ + } + +#define AF_CTOR_SPEC(__W,C_TYPE) \ + AF_CTOR_SPEC_BASE(__W,true,C_TYPE) \ + AF_CTOR_SPEC_BASE(__W,false,C_TYPE) + +AF_CTOR_SPEC(1,bool) +AF_CTOR_SPEC(8, signed char) +AF_CTOR_SPEC(8, unsigned char) +AF_CTOR_SPEC(16, signed short) +AF_CTOR_SPEC(16, unsigned short) +AF_CTOR_SPEC(32, signed int) +AF_CTOR_SPEC(32, unsigned int) +AF_CTOR_SPEC(64, ap_slong) +AF_CTOR_SPEC(64, ap_ulong) + +///Output streaming +//----------------------------------------------------------------------------- +template +INLINE std::ostream& +operator <<(std::ostream& os, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& x) { + os << x.to_double(); + return os; +} + +///Input streaming +//----------------------------------------------------------------------------- +template +INLINE std::istream& +operator >> (std::istream& os, ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& x) { + double d; + os >> d; + x = ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>(x); + return os; +} + +template +INLINE void print(const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& x) { + ap_private<_AP_W,_AP_S> data=x.V; + if (_AP_I>0) { + const ap_private<_AP_I,_AP_S> p1=data>>(_AP_W-_AP_I); + print(p1); + + } else + printf("0"); + printf("."); + if (_AP_I<_AP_W) { + const ap_private<_AP_W-_AP_I,false> p2=data; + print(p2,false); + } +} + +///Operators mixing Integers with ap_fixed_base +//----------------------------------------------------------------------------- +#if 1 +#define AF_BIN_OP_WITH_INT_SF(BIN_OP,C_TYPE,_AP_W2,_AP_S2,RTYPE) \ + template \ + INLINE typename ap_fixed_base<_AP_W,_AP_I,_AP_S>::template RType<_AP_W2,_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP (const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) \ + { \ + return op.operator BIN_OP(ap_private<_AP_W2,_AP_S2>(i_op)); \ + } +#define AF_BIN_OP_WITH_INT(BIN_OP, C_TYPE, _AP_W2,_AP_S2,RTYPE) \ + template \ + INLINE typename ap_fixed_base<_AP_W,_AP_I,_AP_S>::template RType<_AP_W2,_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP (const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) \ + { \ + return op.operator BIN_OP (ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op)); \ + } \ + \ + template \ + INLINE typename ap_fixed_base<_AP_W,_AP_I,_AP_S>::template RType<_AP_W2,_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP (C_TYPE i_op, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op) \ + { \ + return ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op).operator BIN_OP (op); \ + } + +#else +#define AF_BIN_OP_WITH_INT_SF(BIN_OP,C_TYPE,_AP_W2,_AP_S2,RTYPE) \ + template \ + INLINE typename ap_fixed_base<_AP_W,_AP_I,_AP_S>::template RType<_AP_W2,_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP (const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) \ + { \ + return op BIN_OP (i_op); \ + } +#define AF_BIN_OP_WITH_INT(BIN_OP, C_TYPE, _AP_W2,_AP_S2,RTYPE) \ + template \ + INLINE typename ap_fixed_base<_AP_W,_AP_I,_AP_S>::template RType<_AP_W2,_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP (const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) \ + { \ + return op.V BIN_OP (i_op<<(_AP_W-_AP_I)); \ + } \ + \ + \ + template \ + INLINE typename ap_fixed_base<_AP_W,_AP_I,_AP_S>::template RType<_AP_W2,_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP (C_TYPE i_op, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op) \ + { \ + return ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op).operator BIN_OP (op); \ + } + +#endif +#if 1 +#define AF_REL_OP_WITH_INT(REL_OP, C_TYPE, _AP_W2,_AP_S2) \ + template \ + INLINE bool operator REL_OP (const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) \ + { \ + return op.operator REL_OP (ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op)); \ + } \ + \ + \ + template \ + INLINE bool operator REL_OP (C_TYPE i_op, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op) \ + { \ + return ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op).operator REL_OP (op); \ + } +#else +#define AF_REL_OP_WITH_INT(REL_OP, C_TYPE, _AP_W2,_AP_S2) \ + template \ + INLINE bool operator REL_OP (const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) \ + { \ + return op.V.operator REL_OP (i_op<<(_AP_W-_AP_I)); \ + } \ + \ + \ + template \ + INLINE bool operator REL_OP (C_TYPE i_op, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op) \ + { \ + return (i_op<<(_AP_W-_AP_I)) REL_OP (op.V.VAL); \ + } +#endif +#if 1 +#define AF_ASSIGN_OP_WITH_INT(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& operator ASSIGN_OP ( ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) { \ + return op.operator ASSIGN_OP (ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op)); \ + } +#define AF_ASSIGN_OP_WITH_INT_SF(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& operator ASSIGN_OP ( ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) { \ + return op.operator ASSIGN_OP (ap_private<_AP_W2,_AP_S2>(i_op)); \ + } +#else +#define AF_ASSIGN_OP_WITH_INT(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& operator ASSIGN_OP ( ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) { \ + return op.V.operator ASSIGN_OP (i_op); \ + } +#define AF_ASSIGN_OP_WITH_INT_SF(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& operator ASSIGN_OP ( ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, C_TYPE i_op) { \ + return op.V.operator ASSIGN_OP (i_op); \ + } +#endif + +#define AF_OPS_WITH_INT(C_TYPE, WI, SI) \ + AF_BIN_OP_WITH_INT(+, C_TYPE, WI, SI, plus) \ + AF_BIN_OP_WITH_INT(-, C_TYPE, WI, SI, minus) \ + AF_BIN_OP_WITH_INT(*, C_TYPE, WI, SI, mult) \ + AF_BIN_OP_WITH_INT(/, C_TYPE, WI, SI, div) \ + AF_BIN_OP_WITH_INT_SF(>>, C_TYPE, WI, SI, arg1) \ + AF_BIN_OP_WITH_INT_SF(<<, C_TYPE, WI, SI, arg1) \ + AF_BIN_OP_WITH_INT(&, C_TYPE, WI, SI, logic) \ + AF_BIN_OP_WITH_INT(|, C_TYPE, WI, SI, logic) \ + AF_BIN_OP_WITH_INT(^, C_TYPE, WI, SI, logic) \ + \ + AF_REL_OP_WITH_INT(==, C_TYPE, WI, SI) \ + AF_REL_OP_WITH_INT(!=, C_TYPE, WI, SI) \ + AF_REL_OP_WITH_INT(>, C_TYPE, WI, SI) \ + AF_REL_OP_WITH_INT(>=, C_TYPE, WI, SI) \ + AF_REL_OP_WITH_INT(<, C_TYPE, WI, SI) \ + AF_REL_OP_WITH_INT(<=, C_TYPE, WI, SI) \ + \ + AF_ASSIGN_OP_WITH_INT(+=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT(-=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT(*=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT(/=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT_SF(>>=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT_SF(<<=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT(&=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT(|=, C_TYPE, WI, SI) \ + AF_ASSIGN_OP_WITH_INT(^=, C_TYPE, WI, SI) + +AF_OPS_WITH_INT(bool, 1, false) +AF_OPS_WITH_INT(char, 8, true) +AF_OPS_WITH_INT(signed char, 8, true) +AF_OPS_WITH_INT(unsigned char, 8, false) +AF_OPS_WITH_INT(short, 16, true) +AF_OPS_WITH_INT(unsigned short, 16, false) +AF_OPS_WITH_INT(int, 32, true) +AF_OPS_WITH_INT(unsigned int, 32, false) +# if defined __x86_64__ +AF_OPS_WITH_INT(long, 64, true) +AF_OPS_WITH_INT(unsigned long, 64, false) +# else +AF_OPS_WITH_INT(long, 32, true) +AF_OPS_WITH_INT(unsigned long, 32, false) +# endif +AF_OPS_WITH_INT(ap_slong, 64, true) +AF_OPS_WITH_INT(ap_ulong, 64, false) + +#define AF_BIN_OP_WITH_AP_INT(BIN_OP, RTYPE) \ + template \ + INLINE typename ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>::template RType<_AP_W,_AP_I,_AP_S>::RTYPE \ + operator BIN_OP ( const ap_private<_AP_W2,_AP_S2>& i_op, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op) { \ + return ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op).operator BIN_OP (op); \ + } \ + template \ + INLINE typename ap_fixed_base<_AP_W,_AP_I,_AP_S>::template RType<_AP_W2,_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP ( const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, const ap_private<_AP_W2,_AP_S2>& i_op) { \ + return op.operator BIN_OP (ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op)); \ + } + +#define AF_REL_OP_WITH_AP_INT(REL_OP) \ + template \ + INLINE bool operator REL_OP ( const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, const ap_private<_AP_W2,_AP_S2>& i_op) { \ + return op.operator REL_OP ( ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op)); \ + } \ + template \ + INLINE bool operator REL_OP ( const ap_private<_AP_W2,_AP_S2>& i_op, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op) { \ + return ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op).operator REL_OP (op); \ + } + +#define AF_ASSIGN_OP_WITH_AP_INT(ASSIGN_OP) \ + template \ + INLINE ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& operator ASSIGN_OP ( ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op, const ap_private<_AP_W2,_AP_S2>& i_op) { \ + return op.operator ASSIGN_OP (ap_fixed_base<_AP_W2,_AP_W2,_AP_S2>(i_op)); \ + } \ + template \ + INLINE ap_private<_AP_W2,_AP_S2>& operator ASSIGN_OP ( ap_private<_AP_W2,_AP_S2>& i_op, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op) { \ + return i_op.operator ASSIGN_OP (op.to_ap_private()); \ + } + +AF_BIN_OP_WITH_AP_INT(+, plus) +AF_BIN_OP_WITH_AP_INT(-, minus) +AF_BIN_OP_WITH_AP_INT(*, mult) +AF_BIN_OP_WITH_AP_INT(/, div) +AF_BIN_OP_WITH_AP_INT(&, logic) +AF_BIN_OP_WITH_AP_INT(|, logic) +AF_BIN_OP_WITH_AP_INT(^, logic) + +AF_REL_OP_WITH_AP_INT(==) +AF_REL_OP_WITH_AP_INT(!=) +AF_REL_OP_WITH_AP_INT(>) +AF_REL_OP_WITH_AP_INT(>=) +AF_REL_OP_WITH_AP_INT(<) +AF_REL_OP_WITH_AP_INT(<=) + +AF_ASSIGN_OP_WITH_AP_INT(+=) +AF_ASSIGN_OP_WITH_AP_INT(-=) +AF_ASSIGN_OP_WITH_AP_INT(*=) +AF_ASSIGN_OP_WITH_AP_INT(/=) +AF_ASSIGN_OP_WITH_AP_INT(&=) +AF_ASSIGN_OP_WITH_AP_INT(|=) +AF_ASSIGN_OP_WITH_AP_INT(^=) + +#define AF_REF_REL_OP_MIX_INT(REL_OP, C_TYPE, _AP_W2, _AP_S2) \ +template \ + INLINE bool operator REL_OP ( const af_range_ref<_AP_W,_AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op, C_TYPE op2) { \ + return (ap_private<_AP_W, false>(op)).operator REL_OP (ap_private<_AP_W2,_AP_S2>(op2)); \ + } \ +template \ + INLINE bool operator REL_OP ( C_TYPE op2, const af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op) { \ + return ap_private<_AP_W2,_AP_S2>(op2).operator REL_OP (ap_private<_AP_W, false>(op)); \ + } \ +template \ + INLINE bool operator REL_OP ( const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op, C_TYPE op2) { \ + return (bool(op)) REL_OP op2; \ + } \ +template \ + INLINE bool operator REL_OP ( C_TYPE op2, const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op) { \ + return op2 REL_OP (bool(op)); \ + } + +#define AF_REF_REL_MIX_INT(C_TYPE, _AP_WI, _AP_SI) \ +AF_REF_REL_OP_MIX_INT(>, C_TYPE, _AP_WI, _AP_SI) \ +AF_REF_REL_OP_MIX_INT(<, C_TYPE, _AP_WI, _AP_SI) \ +AF_REF_REL_OP_MIX_INT(>=, C_TYPE, _AP_WI, _AP_SI) \ +AF_REF_REL_OP_MIX_INT(<=, C_TYPE, _AP_WI, _AP_SI) \ +AF_REF_REL_OP_MIX_INT(==, C_TYPE, _AP_WI, _AP_SI) \ +AF_REF_REL_OP_MIX_INT(!=, C_TYPE, _AP_WI, _AP_SI) + +AF_REF_REL_MIX_INT(bool, 1, false) +AF_REF_REL_MIX_INT(char, 8, true) +AF_REF_REL_MIX_INT(signed char, 8, true) +AF_REF_REL_MIX_INT(unsigned char, 8, false) +AF_REF_REL_MIX_INT(short, 16, true) +AF_REF_REL_MIX_INT(unsigned short, 16, false) +AF_REF_REL_MIX_INT(int, 32, true) +AF_REF_REL_MIX_INT(unsigned int, 32, false) +# if defined __x86_64__ +AF_REF_REL_MIX_INT(long, 64, true) +AF_REF_REL_MIX_INT(unsigned long, 64, false) +# else +AF_REF_REL_MIX_INT(long, 32, true) +AF_REF_REL_MIX_INT(unsigned long, 32, false) +# endif +AF_REF_REL_MIX_INT(ap_slong, 64, true) +AF_REF_REL_MIX_INT(ap_ulong, 64, false) + +#define AF_REF_REL_OP_AP_INT(REL_OP) \ +template \ + INLINE bool operator REL_OP ( const af_range_ref<_AP_W,_AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op, const ap_private<_AP_W2, _AP_S> &op2) { \ + return (ap_private<_AP_W, false>(op)).operator REL_OP (op2); \ + } \ +template \ + INLINE bool operator REL_OP (const ap_private<_AP_W2, _AP_S2> &op2, const af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op) { \ + return op2.operator REL_OP (ap_private<_AP_W, false>(op)); \ + } \ +template \ + INLINE bool operator REL_OP ( const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op, const ap_private<_AP_W2, _AP_S2> &op2) { \ + return (ap_private<1, false>(op)).operator REL_OP (op2); \ + } \ +template \ + INLINE bool operator REL_OP ( const ap_private<_AP_W2, _AP_S2> &op2, const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op) { \ + return op2.operator REL_OP (ap_private<1,false>(op)); \ + } + +AF_REF_REL_OP_AP_INT(>) +AF_REF_REL_OP_AP_INT(<) +AF_REF_REL_OP_AP_INT(>=) +AF_REF_REL_OP_AP_INT(<=) +AF_REF_REL_OP_AP_INT(==) +AF_REF_REL_OP_AP_INT(!=) + +// Relational Operators with double +template +INLINE bool operator == ( double op1, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op2) { + return op2.operator == (op1); +} + +template +INLINE bool operator != ( double op1, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op2) { + return op2.operator != (op1); +} + +template +INLINE bool operator > ( double op1, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op2) { + return op2.operator < (op1); +} + +template +INLINE bool operator >= ( double op1, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op2) { + return op2.operator <= (op1); +} + +template +INLINE bool operator < ( double op1, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op2) { + return op2.operator > (op1); +} + +template +INLINE bool operator <= ( double op1, const ap_fixed_base<_AP_W,_AP_I,_AP_S,_AP_Q,_AP_O, _AP_N>& op2) { + return op2.operator >= (op1); +} + +#endif /* #ifndef __AESL_GCC_AP_FIXED_H__ */ \ No newline at end of file diff --git a/hls_2018/router_02_boardstr/etc/ap_int_sim.h b/hls_2018/router_02_boardstr/etc/ap_int_sim.h new file mode 100755 index 0000000..887ccd8 --- /dev/null +++ b/hls_2018/router_02_boardstr/etc/ap_int_sim.h @@ -0,0 +1,1629 @@ +/* + * Copyright 2012 Xilinx, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __AESL_GCC_AP_INT_H__ +#define __AESL_GCC_AP_INT_H__ + +#ifndef __cplusplus +#error C++ is required to include this header file +#endif /* #ifndef __cplusplus */ + +#undef _AP_DEBUG_ +#include +#include + +// for safety +#if (defined(_AP_N)|| defined(_AP_C)) +#error One or more of the following is defined: _AP_N, _AP_C. Definition conflicts with their usage as template parameters. +#endif /* #if (defined(_AP_N)|| defined(_AP_C)) */ + +// for safety +#if (defined(_AP_W) || defined(_AP_I) || defined(_AP_S) || defined(_AP_Q) || defined(_AP_O) || defined(_AP_W2) || defined(_AP_I2) || defined(_AP_S2) || defined(_AP_Q2) || defined(_AP_O2)) +#error One or more of the following is defined: _AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2. Definition conflicts with their usage as template parameters. +#endif /* #if (defined(_AP_W) || defined(_AP_I) || defined(_AP_S) || defined(_AP_Q) || defined(_AP_O) || defined(_AP_W2) || defined(_AP_I2) || defined(_AP_S2) || defined(_AP_Q2) || defined(_AP_O2)) */ + +//for safety +#if (defined(_AP_W3) || defined(_AP_S3) || defined(_AP_W4) || defined(_AP_S4)) +#error One or more of the following is defined: _AP_W3, _AP_S3, _AP_W4,_AP_S4. Definition conflicts with their usage as template parameters. +#endif /* #if (defined(_AP_W3) || defined(_AP_S3) || defined(_AP_W4) || defined(_AP_S4)) */ + +//for safety +#if (defined(_AP_W1) || defined(_AP_S1) || defined(_AP_I1) || defined(_AP_T) || defined(_AP_T1) || defined(_AP_T2) || defined(_AP_T3) || defined(_AP_T4)) +#error One or more of the following is defined: _AP_W1, _AP_S1, _AP_I1, _AP_T, _AP_T1, _AP_T2, _AP_T3, _AP_T4. Definition conflicts with their usage as template parameters. +#endif /* #if (defined(_AP_W1) || defined(_AP_S1) || defined(_AP_I1) || defined(_AP_T) || defined(_AP_T1) || defined(_AP_T2) || defined(_AP_T3) || defined(_AP_T4)) */ + +#define __AESL_APDT_IN_SCFLOW__ +#ifndef __AESL_APDT_IN_SCFLOW__ + #include "etc/ap_private.h" +#else + #include "../etc/ap_private.h" +#endif /* #ifndef __AESL_APDT_IN_SCFLOW__ */ + +#ifdef _AP_DEBUG_ + #define AP_DEBUG(s) s +#else + #define AP_DEBUG(s) +#endif /* #ifdef _AP_DEBUG_ */ + +#ifndef __SIMULATION__ + #define __SIMULATION__ +#endif /* #ifndef __SIMULATION__ */ + +#if !(defined SYSTEMC_H) && !(defined SYSTEMC_INCLUDED) + #ifndef SC_TRN + #define SC_TRN AP_TRN + #endif /* #ifndef SC_TRN */ + #ifndef SC_RND + #define SC_RND AP_RND + #endif /* #ifndef SC_RND */ + #ifndef SC_TRN_ZERO + #define SC_TRN_ZERO AP_TRN_ZERO + #endif /* #ifndef SC_TRN_ZERO */ + #ifndef SC_RND_ZERO + #define SC_RND_ZERO AP_RND_ZERO + #endif /* #ifndef SC_RND_ZERO */ + #ifndef SC_RND_INF + #define SC_RND_INF AP_RND_INF + #endif /* #ifndef SC_RND_INF */ + #ifndef SC_RND_MIN_INF + #define SC_RND_MIN_INF AP_RND_MIN_INF + #endif /* #ifndef SC_RND_MIN_INF */ + #ifndef SC_RND_CONV + #define SC_RND_CONV AP_RND_CONV + #endif /* #ifndef SC_RND_CONV */ + #ifndef SC_WRAP + #define SC_WRAP AP_WRAP + #endif /* #ifndef SC_WRAP */ + #ifndef SC_SAT + #define SC_SAT AP_SAT + #endif /* #ifndef SC_SAT */ + #ifndef SC_SAT_ZERO + #define SC_SAT_ZERO AP_SAT_ZERO + #endif /* #ifndef SC_SAT_ZERO */ + #ifndef SC_SAT_SYM + #define SC_SAT_SYM AP_SAT_SYM + #endif /* #ifndef SC_SAT_SYM */ + #ifndef SC_WRAP_SM + #define SC_WRAP_SM AP_WRAP_SM + #endif /* #ifndef SC_WRAP_SM */ + #ifndef SC_BIN + #define SC_BIN AP_BIN + #endif /* #ifndef SC_BIN */ + #ifndef SC_OCT + #define SC_OCT AP_OCT + #endif /* #ifndef SC_OCT */ + #ifndef SC_DEC + #define SC_DEC AP_DEC + #endif /* #ifndef SC_DEC */ + #ifndef SC_HEX + #define SC_HEX AP_HEX + #endif /* #ifndef SC_HEX */ +#endif /* #if !(defined SYSTEMC_H) && !(defined SYSTEMC_INCLUDED) */ +#ifndef AP_INT_MAX_W +#define AP_INT_MAX_W 1024 +#endif +#define BIT_WIDTH_UPPER_LIMIT (1 << 15) +#if AP_INT_MAX_W > BIT_WIDTH_UPPER_LIMIT +#error "Bitwidth exceeds 32768 (1 << 15), the maximum allowed value" +#endif +#define MAX_MODE(BITS) ((BITS + 1023) / 1024) + +///Forward declaration +template struct ap_range_ref; +template struct ap_bit_ref; + +template struct ap_fixed_base; +template struct af_range_ref; +template struct af_bit_ref; +template class ap_uint; + +enum { + AP_BIN = 2, + AP_OCT = 8, + AP_DEC = 10, + AP_HEX = 16 +}; + +///Why to use reference? +///Because we will operate the original object indirectly by operating the +///result object directly after concating or part selecting + +///Proxy class which allows concatination to be used as rvalue(for reading) and +//lvalue(for writing) + +/// Concatination reference. +// ---------------------------------------------------------------- +template +struct ap_concat_ref { +#ifdef _MSC_VER + #pragma warning(disable: 4521 4522) +#endif /* #ifdef _MSC_VER */ + enum {_AP_WR=_AP_W1+_AP_W2,}; + _AP_T1& mbv1; + _AP_T2& mbv2; + + INLINE ap_concat_ref(const ap_concat_ref<_AP_W1, _AP_T1, + _AP_W2, _AP_T2>& ref): + mbv1(ref.mbv1), mbv2(ref.mbv2) {} + + INLINE ap_concat_ref(_AP_T1& bv1, _AP_T2& bv2):mbv1(bv1),mbv2(bv2) {} + + template + INLINE ap_concat_ref& operator = (const ap_private<_AP_W3,_AP_S3>& val) { + ap_private<_AP_W1+_AP_W2, false> vval(val); + int W_ref1=mbv1.length(); + int W_ref2=mbv2.length(); + ap_private<_AP_W1,false> mask1(-1); + mask1>>=_AP_W1-W_ref1; + ap_private<_AP_W2,false> mask2(-1); + mask2>>=_AP_W2-W_ref2; + mbv1.set(ap_private<_AP_W1,false>((vval>>W_ref2)&mask1)); + mbv2.set(ap_private<_AP_W2,false>(vval&mask2)); + return *this; + } + + INLINE ap_concat_ref& operator = (unsigned long long val) { + ap_private<_AP_W1+_AP_W2, false> tmpVal(val); + return operator = (tmpVal); + } + + template + INLINE ap_concat_ref& operator = + (const ap_concat_ref <_AP_W3, _AP_T3, _AP_W4, _AP_T4>& val) { + ap_private<_AP_W1+_AP_W2, false> tmpVal(val); + return operator = (tmpVal); + } + + INLINE ap_concat_ref& operator = + (const ap_concat_ref <_AP_W1, _AP_T1, _AP_W2, _AP_T2>& val) { + ap_private<_AP_W1+_AP_W2, false> tmpVal(val); + return operator = (tmpVal); + } + + template + INLINE ap_concat_ref& operator =(const ap_bit_ref<_AP_W3, _AP_S3>& val) { + ap_private<_AP_W1+_AP_W2, false> tmpVal(val); + return operator = (tmpVal); + } + + template + INLINE ap_concat_ref& operator =(const ap_range_ref<_AP_W3,_AP_S3>& val) { + ap_private<_AP_W1+_AP_W2, false> tmpVal(val); + return operator =(tmpVal); + } + + template + INLINE ap_concat_ref& operator= (const af_range_ref<_AP_W3, _AP_I3, _AP_S3, + _AP_Q3, _AP_O3, _AP_N3>& val) { + return operator = ((const ap_private<_AP_W3, false>)(val)); + } + + template + INLINE ap_concat_ref& operator= (const ap_fixed_base<_AP_W3, _AP_I3, _AP_S3, + _AP_Q3, _AP_O3, _AP_N3>& val) { + return operator = (val.to_ap_private()); + } + + template + INLINE ap_concat_ref& operator= (const af_bit_ref<_AP_W3, _AP_I3, _AP_S3, + _AP_Q3, _AP_O3, _AP_N3>& val) { + return operator=((unsigned long long)(bool)(val)); + } + + + INLINE operator ap_private<_AP_WR, false> () const { + return get(); + } + + INLINE operator unsigned long long () const { + return get().to_uint64(); + } + + template + INLINE ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, ap_range_ref<_AP_W3, _AP_S3> > + operator, (const ap_range_ref<_AP_W3, _AP_S3> &a2) { + return ap_concat_ref<_AP_WR, ap_concat_ref, + _AP_W3, ap_range_ref<_AP_W3, _AP_S3> >(*this, + const_cast &>(a2)); + } + + template + INLINE ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, ap_private<_AP_W3, _AP_S3> > + operator, (ap_private<_AP_W3, _AP_S3> &a2) { + return ap_concat_ref<_AP_WR, ap_concat_ref, + _AP_W3, ap_private<_AP_W3, _AP_S3> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, ap_private<_AP_W3, _AP_S3> > + operator, (const ap_private<_AP_W3, _AP_S3> &a2) { + return ap_concat_ref<_AP_WR, ap_concat_ref, + _AP_W3, ap_private<_AP_W3, _AP_S3> >(*this, + const_cast&>(a2)); + } + + template + INLINE ap_concat_ref<_AP_WR, ap_concat_ref, 1, ap_bit_ref<_AP_W3, _AP_S3> > + operator, (const ap_bit_ref<_AP_W3, _AP_S3> &a2) { + return ap_concat_ref<_AP_WR, ap_concat_ref, + 1, ap_bit_ref<_AP_W3, _AP_S3> >(*this, + const_cast &>(a2)); + } + + template + INLINE ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3+_AP_W4, ap_concat_ref<_AP_W3,_AP_T3,_AP_W4,_AP_T4> > + operator, (const ap_concat_ref<_AP_W3,_AP_T3,_AP_W4,_AP_T4> &a2) + { + return ap_concat_ref<_AP_WR, ap_concat_ref, + _AP_W3+_AP_W4, ap_concat_ref<_AP_W3,_AP_T3,_AP_W4, + _AP_T4> >(*this, const_cast& >(a2)); + } + + template + INLINE + ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, af_range_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3> > + operator, (const af_range_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, + _AP_O3, _AP_N3> &a2) { + return ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, af_range_ref<_AP_W3, + _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3> >(*this, + const_cast& >(a2)); + } + + template + INLINE + ap_concat_ref<_AP_WR, ap_concat_ref, 1, af_bit_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3> > + operator, (const af_bit_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, + _AP_O3, _AP_N3> &a2) { + return ap_concat_ref<_AP_WR, ap_concat_ref, 1, af_bit_ref<_AP_W3, + _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3> >(*this, + const_cast& >(a2)); + } + + template + INLINE ap_private + operator & (const ap_private<_AP_W3,_AP_S3>& a2) { + return get() & a2; + } + + + template + INLINE ap_private + operator | (const ap_private<_AP_W3,_AP_S3>& a2) { + return get() | a2; + } + + + template + INLINE ap_private + operator ^ (const ap_private<_AP_W3,_AP_S3>& a2) { + return ap_private(get() ^ a2); + } + + INLINE const ap_private<_AP_WR, false> get() const + { + ap_private<_AP_W1+_AP_W2, false> tmpVal = ap_private<_AP_W1+_AP_W2, false> (mbv1.get()); + ap_private<_AP_W1+_AP_W2, false> tmpVal2 = ap_private<_AP_W1+_AP_W2, false> (mbv2.get()); + int W_ref2 = mbv2.length(); + tmpVal <<= W_ref2; + tmpVal |= tmpVal2; + return tmpVal; + } + + INLINE const ap_private<_AP_WR, false> get() { + ap_private<_AP_W1+_AP_W2, false> tmpVal = ap_private<_AP_W1+_AP_W2, false> ( mbv1.get()); + ap_private<_AP_W1+_AP_W2, false> tmpVal2 = ap_private<_AP_W1+_AP_W2, false> (mbv2.get()); + int W_ref2 = mbv2.length(); + tmpVal <<= W_ref2; + tmpVal |= tmpVal2; + return tmpVal; + } + + template + INLINE void set(const ap_private<_AP_W3,false> & val) { + ap_private<_AP_W1+_AP_W2, false> vval(val); + int W_ref1=mbv1.length(); + int W_ref2=mbv2.length(); + ap_private<_AP_W1,false> mask1(-1); + mask1>>=_AP_W1-W_ref1; + ap_private<_AP_W2,false> mask2(-1); + mask2>>=_AP_W2-W_ref2; + mbv1.set(ap_private<_AP_W1,false>((vval>>W_ref2)&mask1)); + mbv2.set(ap_private<_AP_W2,false>(vval&mask2)); + } + + INLINE int length() const { + return mbv1.length()+mbv2.length(); + } + + INLINE std::string to_string(uint8_t radix=2) const { + return get().to_string(radix); + } +}; + +///Proxy class, which allows part selection to be used as rvalue(for reading) and +//lvalue(for writing) + +///Range(slice) reference +//------------------------------------------------------------ +template +struct ap_range_ref { +#ifdef _MSC_VER + #pragma warning( disable : 4521 4522 ) +#endif /* #ifdef _MSC_VER */ + ap_private<_AP_W,_AP_S> &d_bv; + int l_index; + int h_index; + +public: + INLINE ap_range_ref(const ap_range_ref<_AP_W, _AP_S>& ref): + d_bv(ref.d_bv), l_index(ref.l_index), h_index(ref.h_index) {} + + INLINE ap_range_ref(ap_private<_AP_W,_AP_S>* bv, int h, int l): + d_bv(*bv),l_index(l),h_index(h) { + //if (h < l) + //fprintf(stderr, "Warning! The bits selected will be returned in reverse order\n"); + } + + INLINE operator ap_private<_AP_W, false> () const { + ap_private<_AP_W, false> val(0); + if(h_index>=l_index) { + if (_AP_W > 64) { + val=d_bv; + ap_private<_AP_W,false> mask(-1); + mask>>=_AP_W-(h_index-l_index+1); + val>>=l_index; + val&=mask; + } else { + const static uint64_t mask = (~0ULL>> (64>_AP_W ? (64-_AP_W):0)); + val = (d_bv >> l_index) & (mask >>(_AP_W-(h_index-l_index+1))); + } + } else { + for(int i=0, j=l_index;j>=0&&j>=h_index;j--,i++) + if((d_bv)[j]) val.set(i); + } + return val; + } + + INLINE operator unsigned long long () const { + return to_uint64(); + } + + template + INLINE ap_range_ref& operator =(const ap_private<_AP_W2,_AP_S2>& val) { + ap_private<_AP_W,false> vval=ap_private<_AP_W,false>(val); + if (l_index>h_index) { + for (int i=0, j=l_index;j>=0&&j>=h_index;j--,i++) + (vval)[i]? d_bv.set(j):d_bv.clear(j); + } else { + if (_AP_W > 64) { + ap_private<_AP_W,false> mask(-1); + if (l_index>0) { + mask<<=l_index; + vval<<=l_index; + } + if(h_index<_AP_W-1) + { + ap_private<_AP_W,false> mask2(-1); + mask2>>=_AP_W-h_index-1; + mask&=mask2; + vval&=mask2; + } + mask.flip(); + d_bv&=mask; + d_bv|=vval; + } else { + unsigned shift = 64-_AP_W; + uint64_t mask = ~0ULL>>(shift); + if(l_index>0) + { + vval = mask & vval << l_index; + mask = mask & mask << l_index; + } + if(h_index<_AP_W-1) + { + uint64_t mask2 = mask; + mask2 >>= (_AP_W-h_index-1); + mask&=mask2; + vval&=mask2; + } + mask = ~mask; + d_bv&=mask; + d_bv|=vval; + } + } + return *this; + } + + INLINE ap_range_ref& operator = (unsigned long long val) + { + const ap_private<_AP_W,_AP_S> vval=val; + return operator = (vval); + } + + + INLINE ap_range_ref& operator =(const ap_range_ref<_AP_W, _AP_S>& val) + { + const ap_private<_AP_W, false> tmpVal(val); + return operator =(tmpVal); + } + + + + template + INLINE ap_range_ref& operator = + (const ap_concat_ref <_AP_W3, _AP_T3, _AP_W4, _AP_T4>& val) + { + const ap_private<_AP_W, false> tmpVal(val); + return operator = (tmpVal); + } + + template + INLINE ap_range_ref& operator =(const ap_range_ref<_AP_W3,_AP_S3>& val) + { + const ap_private<_AP_W, false> tmpVal(val); + return operator =(tmpVal); + } + + template + INLINE ap_range_ref& operator= (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& val) { + return operator=((const ap_private<_AP_W2, _AP_S2>)(val)); + } + + template + INLINE ap_range_ref& operator= (const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& val) { + return operator=(val.to_ap_private()); + } + + template + INLINE ap_range_ref& operator= (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& val) { + return operator=((unsigned long long)(bool)(val)); + } + + template + INLINE ap_range_ref& operator= (const ap_bit_ref<_AP_W2, _AP_S2>& val) { + return operator=((unsigned long long)(bool)(val)); + } + + template + INLINE + ap_concat_ref<_AP_W,ap_range_ref,_AP_W2,ap_range_ref<_AP_W2,_AP_S2> > + operator, (const ap_range_ref<_AP_W2,_AP_S2> &a2) + { + return + ap_concat_ref<_AP_W, ap_range_ref, _AP_W2, + ap_range_ref<_AP_W2,_AP_S2> >(*this, + const_cast& >(a2)); + } + + + template + INLINE ap_concat_ref<_AP_W,ap_range_ref,_AP_W2,ap_private<_AP_W2,_AP_S2> > + operator , (ap_private<_AP_W2,_AP_S2>& a2) + { + return + ap_concat_ref<_AP_W, ap_range_ref, _AP_W2, ap_private<_AP_W2,_AP_S2> >(*this, a2); + } + + INLINE ap_concat_ref<_AP_W,ap_range_ref,_AP_W,ap_private<_AP_W,_AP_S> > + operator , (ap_private<_AP_W, _AP_S>& a2) + { + return + ap_concat_ref<_AP_W, ap_range_ref, _AP_W, + ap_private<_AP_W,_AP_S> >(*this, a2); + } + + + + template + INLINE + ap_concat_ref<_AP_W,ap_range_ref,1,ap_bit_ref<_AP_W2,_AP_S2> > + operator, (const ap_bit_ref<_AP_W2,_AP_S2> &a2) + { + return + ap_concat_ref<_AP_W, ap_range_ref, 1, + ap_bit_ref<_AP_W2,_AP_S2> >(*this, const_cast& >(a2)); + } + + + template + INLINE + ap_concat_ref<_AP_W, ap_range_ref, _AP_W2+_AP_W3, ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > + operator, (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) + { + return ap_concat_ref<_AP_W, ap_range_ref, _AP_W2+_AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(*this, + const_cast& >(a2)); + } + + template + INLINE + ap_concat_ref<_AP_W, ap_range_ref, _AP_W2, af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<_AP_W, ap_range_ref, _AP_W2, af_range_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, + const_cast& >(a2)); + } + + template + INLINE + ap_concat_ref<_AP_W, ap_range_ref, 1, af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<_AP_W, ap_range_ref, 1, af_bit_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, + const_cast& >(a2)); + } + + template + INLINE bool operator == (const ap_range_ref<_AP_W2, _AP_S2>& op2) + { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs==rhs; + } + + + template + INLINE bool operator != (const ap_range_ref<_AP_W2, _AP_S2>& op2) + { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs!=rhs; + } + + + template + INLINE bool operator > (const ap_range_ref<_AP_W2, _AP_S2>& op2) + { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs>rhs; + } + + + template + INLINE bool operator >= (const ap_range_ref<_AP_W2, _AP_S2>& op2) + { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs>=rhs; + } + + + template + INLINE bool operator < (const ap_range_ref<_AP_W2, _AP_S2>& op2) + { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs + INLINE bool operator <= (const ap_range_ref<_AP_W2, _AP_S2>& op2) + { + ap_private<_AP_W,false> lhs=get(); + ap_private<_AP_W2,false> rhs=op2.get(); + return lhs<=rhs; + } + + + template + INLINE void set(const ap_private<_AP_W2,false>& val) + { + ap_private<_AP_W,_AP_S> vval=val; + if(l_index>h_index) + { + for(int i=0, j=l_index;j>=0&&j>=h_index;j--,i++) + (vval)[i]? d_bv.set(j):d_bv.clear(j); + } else { + if (_AP_W>64 ) { + ap_private<_AP_W,_AP_S> mask(-1); + if(l_index>0) + { + ap_private<_AP_W,false> mask1(-1); + mask1>>=_AP_W-l_index; + mask1.flip(); + mask=mask1; + //vval&=mask1; + vval<<=l_index; + } + if(h_index<_AP_W-1) + { + ap_private<_AP_W,false> mask2(-1); + mask2<<=h_index+1; + mask2.flip(); + mask&=mask2; + vval&=mask2; + } + mask.flip(); + d_bv&=mask; + d_bv|=vval; + } else { + uint64_t mask = ~0ULL >> (64-_AP_W); + if(l_index>0) + { + uint64_t mask1 = mask; + mask1=mask & (mask1>>(_AP_W-l_index)); + vval =mask&( vval <> (64-_AP_W); + mask2 = mask &(mask2<<(h_index+1)); + mask&=~mask2; + vval&=~mask2; + } + d_bv&=(~mask&(~0ULL >> (64-_AP_W))); + d_bv|=vval; + } + } + } + + + INLINE ap_private<_AP_W,false> get() const + { + ap_private<_AP_W,false> val(0); + if(h_index=0&&j>=h_index;j--,i++) + if((d_bv)[j]) val.set(i); + } else { + val=d_bv; + val>>=l_index; + if(h_index<_AP_W-1) + { + if (_AP_W <= 64) { + const static uint64_t mask = (~0ULL>> (64>_AP_W ? (64-_AP_W):0)); + val &= (mask>> (_AP_W-(h_index-l_index+1))); + } else { + ap_private<_AP_W,false> mask(-1); + mask>>=_AP_W-(h_index-l_index+1); + val&=mask; + } + } + } + return val; + } + + + INLINE ap_private<_AP_W,false> get() + { + ap_private<_AP_W,false> val(0); + if(h_index=0&&j>=h_index;j--,i++) + if((d_bv)[j]) val.set(i); + } else { + val=d_bv; + val>>=l_index; + if(h_index<_AP_W-1) + { + if (_AP_W <= 64 ) { + static const uint64_t mask = ~0ULL>> (64>_AP_W ? (64-_AP_W):0); + return val &= ( (mask) >> (_AP_W - (h_index-l_index+1))); + } else { + ap_private<_AP_W,false> mask(-1); + mask>>=_AP_W-(h_index-l_index+1); + val&=mask; + } + } + } + return val; + } + + + INLINE int length() const + { + return h_index>=l_index?h_index-l_index+1:l_index-h_index+1; + } + + + INLINE int to_int() const + { + ap_private<_AP_W,false> val=get(); + return val.to_int(); + } + + + INLINE unsigned int to_uint() const + { + ap_private<_AP_W,false> val=get(); + return val.to_uint(); + } + + + INLINE long to_long() const + { + ap_private<_AP_W,false> val=get(); + return val.to_long(); + } + + + INLINE unsigned long to_ulong() const + { + ap_private<_AP_W,false> val=get(); + return val.to_ulong(); + } + + + INLINE ap_slong to_int64() const + { + ap_private<_AP_W,false> val=get(); + return val.to_int64(); + } + + + INLINE ap_ulong to_uint64() const + { + ap_private<_AP_W,false> val=get(); + return val.to_uint64(); + } + + INLINE std::string to_string(uint8_t radix=2) const { + return get().to_string(radix); + } + +}; + +///Proxy class, which allows bit selection to be used as rvalue(for reading) and +//lvalue(for writing) + +///Bit reference +//-------------------------------------------------------------- +template +struct ap_bit_ref { +#ifdef _MSC_VER +#pragma warning( disable : 4521 4522 ) +#endif + ap_private<_AP_W,_AP_S>& d_bv; + int d_index; + +public: + INLINE ap_bit_ref(const ap_bit_ref<_AP_W, _AP_S>& ref): + d_bv(ref.d_bv), d_index(ref.d_index) {} + + INLINE ap_bit_ref(ap_private<_AP_W,_AP_S>& bv, int index=0): + d_bv(bv),d_index(index) + { +#ifdef _AP_DEBUG_ + assert(d_index<_AP_W&&"index out of bound"); +#endif + } + + + INLINE operator bool () const + { + return d_bv.get_bit(d_index); + } + + + INLINE bool to_bool() const + { + return operator bool (); + } + + + INLINE ap_bit_ref& operator = (unsigned long long val) + { + if(val) + d_bv.set(d_index); + else + d_bv.clear(d_index); + return *this; + } + + +#if 0 + INLINE ap_bit_ref& operator = (bool val) + { + if(val) + d_bv.set(d_index); + else + d_bv.clear(d_index); + return *this; + } +#endif + template + INLINE ap_bit_ref& operator =(const ap_private<_AP_W2,_AP_S2>& val) + { + return operator =((unsigned long long)(val != 0)); + } + + + template + INLINE ap_bit_ref& operator =(const ap_bit_ref<_AP_W2,_AP_S2>& val) + { + return operator =((unsigned long long)(bool)val); + } + + INLINE ap_bit_ref& operator =(const ap_bit_ref<_AP_W,_AP_S>& val) + { + return operator =((unsigned long long)(bool)val); + } + + template + INLINE ap_bit_ref& operator =(const ap_range_ref<_AP_W2,_AP_S2>& val) + { + return operator =((unsigned long long)(bool) val); + } + + + template + INLINE ap_bit_ref& operator= (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& val) { + return operator=((const ap_private<_AP_W2, false>)(val)); + } + + template + INLINE ap_bit_ref& operator= (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2>& val) { + return operator=((unsigned long long)(bool)(val)); + } + + template + INLINE ap_bit_ref& operator= (const ap_concat_ref<_AP_W2, _AP_T3, _AP_W3, _AP_T3>& val) { + return operator=((const ap_private<_AP_W2 + _AP_W3, false>)(val)); + } + + + + template + INLINE ap_concat_ref<1, ap_bit_ref, _AP_W2, ap_private<_AP_W2,_AP_S2> > + operator , (ap_private<_AP_W2, _AP_S2>& a2) + { + return ap_concat_ref<1, ap_bit_ref, _AP_W2, ap_private<_AP_W2,_AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<1, ap_bit_ref, _AP_W2, ap_range_ref<_AP_W2,_AP_S2> > + operator, (const ap_range_ref<_AP_W2, _AP_S2> &a2) + { + return + ap_concat_ref<1, ap_bit_ref, _AP_W2, ap_range_ref<_AP_W2,_AP_S2> >(*this, + const_cast &>(a2)); + } + + + template + INLINE ap_concat_ref<1, ap_bit_ref, 1, ap_bit_ref<_AP_W2,_AP_S2> > + operator, (const ap_bit_ref<_AP_W2, _AP_S2> &a2) + { + return + ap_concat_ref<1, ap_bit_ref, 1, ap_bit_ref<_AP_W2,_AP_S2> >(*this, + const_cast &>(a2)); + } + + + INLINE ap_concat_ref<1, ap_bit_ref, 1, ap_bit_ref > + operator, (const ap_bit_ref &a2) + { + return + ap_concat_ref<1, ap_bit_ref, 1, ap_bit_ref >(*this, + const_cast(a2)); + } + + + template + INLINE ap_concat_ref<1, ap_bit_ref, _AP_W2+_AP_W3, ap_concat_ref<_AP_W2,_AP_T2,_AP_W3,_AP_T3> > + operator, (const ap_concat_ref<_AP_W2,_AP_T2,_AP_W3,_AP_T3> &a2) + { + return + ap_concat_ref<1,ap_bit_ref,_AP_W2+_AP_W3, + ap_concat_ref<_AP_W2,_AP_T2,_AP_W3,_AP_T3> >(*this, + const_cast& >(a2)); + } + + template + INLINE + ap_concat_ref<1, ap_bit_ref, _AP_W2, af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<1, ap_bit_ref, _AP_W2, af_range_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, + const_cast& >(a2)); + } + + template + INLINE + ap_concat_ref<1, ap_bit_ref, 1, af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<1, ap_bit_ref, 1, af_bit_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, + const_cast& >(a2)); + } + + template + INLINE bool operator == (const ap_bit_ref<_AP_W2, _AP_S2>& op) { + return get() == op.get(); + } + + template + INLINE bool operator != (const ap_bit_ref<_AP_W2, _AP_S2>& op) { + return get() != op.get(); + } + + + INLINE bool get() const + { + return operator bool (); + } + + + INLINE bool get() + { + return operator bool (); + } + + + template + INLINE void set(const ap_private<_AP_W3, false>& val) + { + operator = (val); + } + + INLINE bool operator ~ () const { + bool bit = (d_bv)[d_index]; + return bit ? false : true; + } + + INLINE int length() const { return 1; } + + INLINE std::string to_string() const { + bool val = get(); + return val ? "1" : "0"; + } +}; + +/// Operators mixing Integers with AP_Int +// ---------------------------------------------------------------- +#if 1 +#define OP_BIN_MIX_INT(BIN_OP, C_TYPE, _AP_WI, _AP_SI, RTYPE) \ + template \ + INLINE typename ap_private<_AP_WI,_AP_SI>::template RType<_AP_W,_AP_S>::RTYPE \ + operator BIN_OP ( C_TYPE i_op, const ap_private<_AP_W,_AP_S> &op) { \ + return ap_private<_AP_WI,_AP_SI>(i_op).operator BIN_OP (op); \ + } \ + template \ + INLINE typename ap_private<_AP_W,_AP_S>::template RType<_AP_WI,_AP_SI>::RTYPE \ + operator BIN_OP ( const ap_private<_AP_W,_AP_S> &op, C_TYPE i_op) { \ + return op.operator BIN_OP (ap_private<_AP_WI,_AP_SI>(i_op)); \ + } +#else +#define OP_BIN_MIX_INT(BIN_OP, C_TYPE, _AP_WI, _AP_SI, RTYPE) \ + template \ + INLINE typename ap_private<_AP_WI,_AP_SI>::template RType<_AP_W,_AP_S>::RTYPE \ + operator BIN_OP ( C_TYPE i_op, const ap_private<_AP_W,_AP_S> &op) { \ + return ap_private<_AP_WI,_AP_SI>(i_op).operator BIN_OP (op); \ + } \ + template \ + INLINE typename ap_private<_AP_W,_AP_S>::template RType<_AP_WI,_AP_SI>::RTYPE \ + operator BIN_OP ( const ap_private<_AP_W,_AP_S> &op, C_TYPE i_op) { \ + return op.operator BIN_OP (ap_private<_AP_WI,_AP_SI>(i_op)); \ + } +#endif +#define OP_REL_MIX_INT(REL_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE bool operator REL_OP ( const ap_private<_AP_W,_AP_S> &op, C_TYPE op2) { \ + return op.operator REL_OP (ap_private<_AP_W2, _AP_S2>(op2)); \ + } \ + template \ + INLINE bool operator REL_OP ( C_TYPE op2, const ap_private<_AP_W,_AP_S> &op) { \ + return ap_private<_AP_W2,_AP_S2>(op2).operator REL_OP (op); \ + } +#define OP_ASSIGN_MIX_INT(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE ap_private<_AP_W,_AP_S> &operator ASSIGN_OP ( ap_private<_AP_W,_AP_S> &op, C_TYPE op2) { \ + return op.operator ASSIGN_OP (ap_private<_AP_W2,_AP_S2>(op2)); \ + } + +#define OP_BIN_SHIFT_INT(BIN_OP, C_TYPE, _AP_WI, _AP_SI, RTYPE) \ + template \ + C_TYPE operator BIN_OP ( C_TYPE i_op, const ap_private<_AP_W,_AP_S> &op) { \ + return i_op BIN_OP (op.getVal()); \ + } \ + template \ + INLINE typename ap_private<_AP_W,_AP_S>::template RType<_AP_WI,_AP_SI>::RTYPE \ + operator BIN_OP ( const ap_private<_AP_W,_AP_S> &op, C_TYPE i_op) { \ + return op.operator BIN_OP (i_op); \ + } +#define OP_ASSIGN_RSHIFT_INT(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE ap_private<_AP_W,_AP_S> &operator ASSIGN_OP ( ap_private<_AP_W,_AP_S> &op, C_TYPE op2) { \ + op = op.operator >> (op2); \ + return op; \ + } +#define OP_ASSIGN_LSHIFT_INT(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE ap_private<_AP_W,_AP_S> &operator ASSIGN_OP ( ap_private<_AP_W,_AP_S> &op, C_TYPE op2) { \ + op = op.operator << (op2); \ + return op; \ + } + +#define OPS_MIX_INT(C_TYPE, WI, SI) \ + OP_BIN_MIX_INT(*, C_TYPE, WI, SI, mult) \ + OP_BIN_MIX_INT(+, C_TYPE, WI, SI, plus) \ + OP_BIN_MIX_INT(-, C_TYPE, WI, SI, minus) \ + OP_BIN_MIX_INT(/, C_TYPE, WI, SI, div) \ + OP_BIN_MIX_INT(%, C_TYPE, WI, SI, mod) \ + OP_BIN_MIX_INT(&, C_TYPE, WI, SI, logic) \ + OP_BIN_MIX_INT(|, C_TYPE, WI, SI, logic) \ + OP_BIN_MIX_INT(^, C_TYPE, WI, SI, logic) \ + OP_BIN_SHIFT_INT(>>, C_TYPE, WI, SI, arg1) \ + OP_BIN_SHIFT_INT(<<, C_TYPE, WI, SI, arg1) \ + \ + OP_REL_MIX_INT(==, C_TYPE, WI, SI) \ + OP_REL_MIX_INT(!=, C_TYPE, WI, SI) \ + OP_REL_MIX_INT(>, C_TYPE, WI, SI) \ + OP_REL_MIX_INT(>=, C_TYPE, WI, SI) \ + OP_REL_MIX_INT(<, C_TYPE, WI, SI) \ + OP_REL_MIX_INT(<=, C_TYPE, WI, SI) \ + \ + OP_ASSIGN_MIX_INT(+=, C_TYPE, WI, SI) \ + OP_ASSIGN_MIX_INT(-=, C_TYPE, WI, SI) \ + OP_ASSIGN_MIX_INT(*=, C_TYPE, WI, SI) \ + OP_ASSIGN_MIX_INT(/=, C_TYPE, WI, SI) \ + OP_ASSIGN_MIX_INT(%=, C_TYPE, WI, SI) \ + OP_ASSIGN_MIX_INT(&=, C_TYPE, WI, SI) \ + OP_ASSIGN_MIX_INT(|=, C_TYPE, WI, SI) \ + OP_ASSIGN_MIX_INT(^=, C_TYPE, WI, SI) \ + OP_ASSIGN_RSHIFT_INT(>>=, C_TYPE, WI, SI) \ + OP_ASSIGN_LSHIFT_INT(<<=, C_TYPE, WI, SI) + + +OPS_MIX_INT(bool, 1, false) +OPS_MIX_INT(char, 8, true) +OPS_MIX_INT(signed char, 8, true) +OPS_MIX_INT(unsigned char, 8, false) +OPS_MIX_INT(short, 16, true) +OPS_MIX_INT(unsigned short, 16, false) +OPS_MIX_INT(int, 32, true) +OPS_MIX_INT(unsigned int, 32, false) +# if defined __x86_64__ +OPS_MIX_INT(long, 64, true) +OPS_MIX_INT(unsigned long, 64, false) +# else +OPS_MIX_INT(long, 32, true) +OPS_MIX_INT(unsigned long, 32, false) +# endif +OPS_MIX_INT(ap_slong, 64, true) +OPS_MIX_INT(ap_ulong, 64, false) + +#define OP_BIN_MIX_RANGE(BIN_OP, RTYPE) \ + template \ + INLINE typename ap_private<_AP_W1,_AP_S1>::template RType<_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP ( const ap_range_ref<_AP_W1,_AP_S1>& op1, const ap_private<_AP_W2,_AP_S2>& op2) { \ + return ap_private<_AP_W1, false>(op1).operator BIN_OP (op2); \ + } \ + template \ + INLINE typename ap_private<_AP_W1,_AP_S1>::template RType<_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP ( const ap_private<_AP_W1,_AP_S1>& op1, const ap_range_ref<_AP_W2,_AP_S2>& op2) { \ + return op1.operator BIN_OP (ap_private<_AP_W2, false>(op2)); \ + } + +#define OP_REL_MIX_RANGE(REL_OP) \ + template \ + INLINE bool operator REL_OP ( const ap_range_ref<_AP_W1,_AP_S1>& op1, const ap_private<_AP_W2,_AP_S2>& op2) { \ + return ap_private<_AP_W1,false>(op1).operator REL_OP (op2); \ + } \ + template \ + INLINE bool operator REL_OP ( const ap_private<_AP_W1,_AP_S1>& op1, const ap_range_ref<_AP_W2,_AP_S2>& op2) { \ + return op1.operator REL_OP (op2.operator ap_private<_AP_W2, false>()); \ + } + +#define OP_ASSIGN_MIX_RANGE(ASSIGN_OP) \ + template \ + INLINE ap_private<_AP_W1,_AP_S1>& operator ASSIGN_OP ( ap_private<_AP_W1,_AP_S1>& op1, const ap_range_ref<_AP_W2,_AP_S2>& op2) { \ + return op1.operator ASSIGN_OP (ap_private<_AP_W2, false>(op2)); \ + } \ + template \ + INLINE ap_range_ref<_AP_W1,_AP_S1>& operator ASSIGN_OP (ap_range_ref<_AP_W1,_AP_S1>& op1, ap_private<_AP_W2,_AP_S2>& op2) { \ + ap_private<_AP_W1, false> tmp(op1); \ + tmp.operator ASSIGN_OP (op2); \ + op1 = tmp; \ + return op1; \ + } + + +OP_ASSIGN_MIX_RANGE(+=) +OP_ASSIGN_MIX_RANGE(-=) +OP_ASSIGN_MIX_RANGE(*=) +OP_ASSIGN_MIX_RANGE(/=) +OP_ASSIGN_MIX_RANGE(%=) +OP_ASSIGN_MIX_RANGE(>>=) +OP_ASSIGN_MIX_RANGE(<<=) +OP_ASSIGN_MIX_RANGE(&=) +OP_ASSIGN_MIX_RANGE(|=) +OP_ASSIGN_MIX_RANGE(^=) + +OP_REL_MIX_RANGE(==) +OP_REL_MIX_RANGE(!=) +OP_REL_MIX_RANGE(>) +OP_REL_MIX_RANGE(>=) +OP_REL_MIX_RANGE(<) +OP_REL_MIX_RANGE(<=) + +OP_BIN_MIX_RANGE(+, plus) +OP_BIN_MIX_RANGE(-, minus) +OP_BIN_MIX_RANGE(*, mult) +OP_BIN_MIX_RANGE(/, div) +OP_BIN_MIX_RANGE(%, mod) +OP_BIN_MIX_RANGE(>>, arg1) +OP_BIN_MIX_RANGE(<<, arg1) +OP_BIN_MIX_RANGE(&, logic) +OP_BIN_MIX_RANGE(|, logic) +OP_BIN_MIX_RANGE(^, logic) + +#define OP_BIN_MIX_BIT(BIN_OP, RTYPE) \ + template \ + INLINE typename ap_private<1, false>::template RType<_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP ( const ap_bit_ref<_AP_W1,_AP_S1>& op1, const ap_private<_AP_W2,_AP_S2>& op2) { \ + return ap_private<1, false>(op1).operator BIN_OP (op2); \ + } \ + template \ + INLINE typename ap_private<_AP_W1,_AP_S1>::template RType<1,false>::RTYPE \ + operator BIN_OP ( const ap_private<_AP_W1,_AP_S1>& op1, const ap_bit_ref<_AP_W2,_AP_S2>& op2) { \ + return op1.operator BIN_OP (ap_private<1, false>(op2)); \ + } + +#define OP_REL_MIX_BIT(REL_OP) \ + template \ + INLINE bool operator REL_OP ( const ap_bit_ref<_AP_W1,_AP_S1>& op1, const ap_private<_AP_W2,_AP_S2>& op2) { \ + return ap_private<_AP_W1,false>(op1).operator REL_OP (op2); \ + } \ + template \ + INLINE bool operator REL_OP ( const ap_private<_AP_W1,_AP_S1>& op1, const ap_bit_ref<_AP_W2,_AP_S2>& op2) { \ + return op1.operator REL_OP (ap_private<1, false>(op2)); \ + } + +#define OP_ASSIGN_MIX_BIT(ASSIGN_OP) \ + template \ + INLINE ap_private<_AP_W1,_AP_S1>& operator ASSIGN_OP ( ap_private<_AP_W1,_AP_S1>& op1, ap_bit_ref<_AP_W2,_AP_S2>& op2) { \ + return op1.operator ASSIGN_OP (ap_private<1, false>(op2)); \ + } \ + template \ + INLINE ap_bit_ref<_AP_W1,_AP_S1>& operator ASSIGN_OP ( ap_bit_ref<_AP_W1,_AP_S1>& op1, ap_private<_AP_W2,_AP_S2>& op2) { \ + ap_private<1, false> tmp(op1); \ + tmp.operator ASSIGN_OP (op2); \ + op1 = tmp; \ + return op1; \ + } + + +OP_ASSIGN_MIX_BIT(+=) +OP_ASSIGN_MIX_BIT(-=) +OP_ASSIGN_MIX_BIT(*=) +OP_ASSIGN_MIX_BIT(/=) +OP_ASSIGN_MIX_BIT(%=) +OP_ASSIGN_MIX_BIT(>>=) +OP_ASSIGN_MIX_BIT(<<=) +OP_ASSIGN_MIX_BIT(&=) +OP_ASSIGN_MIX_BIT(|=) +OP_ASSIGN_MIX_BIT(^=) + +OP_REL_MIX_BIT(==) +OP_REL_MIX_BIT(!=) +OP_REL_MIX_BIT(>) +OP_REL_MIX_BIT(>=) +OP_REL_MIX_BIT(<) +OP_REL_MIX_BIT(<=) + +OP_BIN_MIX_BIT(+, plus) +OP_BIN_MIX_BIT(-, minus) +OP_BIN_MIX_BIT(*, mult) +OP_BIN_MIX_BIT(/, div) +OP_BIN_MIX_BIT(%, mod) +OP_BIN_MIX_BIT(>>, arg1) +OP_BIN_MIX_BIT(<<, arg1) +OP_BIN_MIX_BIT(&, logic) +OP_BIN_MIX_BIT(|, logic) +OP_BIN_MIX_BIT(^, logic) + +#define REF_REL_OP_MIX_INT(REL_OP, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE bool operator REL_OP ( const ap_range_ref<_AP_W,_AP_S> &op, C_TYPE op2) { \ + return (ap_private<_AP_W, false>(op)).operator REL_OP (ap_private<_AP_W2,_AP_S2>(op2)); \ + } \ + template \ + INLINE bool operator REL_OP ( C_TYPE op2, const ap_range_ref<_AP_W,_AP_S> &op) { \ + return ap_private<_AP_W2,_AP_S2>(op2).operator REL_OP (ap_private<_AP_W, false>(op)); \ + } \ + template \ + INLINE bool operator REL_OP ( const ap_bit_ref<_AP_W,_AP_S> &op, C_TYPE op2) { \ + return (bool(op)) REL_OP op2; \ + } \ + template \ + INLINE bool operator REL_OP ( C_TYPE op2, const ap_bit_ref<_AP_W,_AP_S> &op) { \ + return op2 REL_OP (bool(op)); \ + } \ + template \ + INLINE bool operator REL_OP ( const ap_concat_ref<_AP_W,_AP_T, _AP_W1, _AP_T1> &op, C_TYPE op2) { \ + return (ap_private<_AP_W + _AP_W1, false>(op)).operator REL_OP (ap_private<_AP_W2,_AP_S2>(op2)); \ + } \ + template \ + INLINE bool operator REL_OP ( C_TYPE op2, const ap_concat_ref<_AP_W,_AP_T, _AP_W1, _AP_T1> &op) { \ + return ap_private<_AP_W2,_AP_S2>(op2).operator REL_OP (ap_private<_AP_W + _AP_W1, false>(op)); \ + } + +#define REF_REL_MIX_INT(C_TYPE, _AP_WI, _AP_SI) \ +REF_REL_OP_MIX_INT(>, C_TYPE, _AP_WI, _AP_SI) \ +REF_REL_OP_MIX_INT(<, C_TYPE, _AP_WI, _AP_SI) \ +REF_REL_OP_MIX_INT(>=, C_TYPE, _AP_WI, _AP_SI) \ +REF_REL_OP_MIX_INT(<=, C_TYPE, _AP_WI, _AP_SI) \ +REF_REL_OP_MIX_INT(==, C_TYPE, _AP_WI, _AP_SI) \ +REF_REL_OP_MIX_INT(!=, C_TYPE, _AP_WI, _AP_SI) + +REF_REL_MIX_INT(bool, 1, false) +REF_REL_MIX_INT(char, 8, true) +REF_REL_MIX_INT(signed char, 8, true) +REF_REL_MIX_INT(unsigned char, 8, false) +REF_REL_MIX_INT(short, 16, true) +REF_REL_MIX_INT(unsigned short, 16, false) +REF_REL_MIX_INT(int, 32, true) +REF_REL_MIX_INT(unsigned int, 32, false) +# if defined __x86_64__ +REF_REL_MIX_INT(long, 64, true) +REF_REL_MIX_INT(unsigned long, 64, false) +# else +REF_REL_MIX_INT(long, 32, true) +REF_REL_MIX_INT(unsigned long, 32, false) +# endif +REF_REL_MIX_INT(ap_slong, 64, true) +REF_REL_MIX_INT(ap_ulong, 64, false) + +#define REF_BIN_OP_MIX_INT(BIN_OP, RTYPE, C_TYPE, _AP_W2, _AP_S2) \ + template \ + INLINE typename ap_private<_AP_W, false>::template RType<_AP_W2,_AP_S2>::RTYPE \ + operator BIN_OP ( const ap_range_ref<_AP_W,_AP_S> &op, C_TYPE op2) { \ + return (ap_private<_AP_W, false>(op)).operator BIN_OP (ap_private<_AP_W2,_AP_S2>(op2)); \ + } \ + template \ + INLINE typename ap_private<_AP_W2, _AP_S2>::template RType<_AP_W,false>::RTYPE \ + operator BIN_OP ( C_TYPE op2, const ap_range_ref<_AP_W,_AP_S> &op) { \ + return ap_private<_AP_W2,_AP_S2>(op2).operator BIN_OP (ap_private<_AP_W, false>(op)); \ + } + +#define REF_BIN_MIX_INT(C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(+, plus, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(-, minus, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(*, mult, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(/, div, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(%, mod, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(>>, arg1, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(<<, arg1, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(&, logic, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(|, logic, C_TYPE, _AP_WI, _AP_SI) \ +REF_BIN_OP_MIX_INT(^, logic, C_TYPE, _AP_WI, _AP_SI) + +REF_BIN_MIX_INT(bool, 1, false) +REF_BIN_MIX_INT(char, 8, true) +REF_BIN_MIX_INT(signed char, 8, true) +REF_BIN_MIX_INT(unsigned char, 8, false) +REF_BIN_MIX_INT(short, 16, true) +REF_BIN_MIX_INT(unsigned short, 16, false) +REF_BIN_MIX_INT(int, 32, true) +REF_BIN_MIX_INT(unsigned int, 32, false) +# if defined __x86_64__ +REF_BIN_MIX_INT(long, 64, true) +REF_BIN_MIX_INT(unsigned long, 64, false) +#else +REF_BIN_MIX_INT(long, 32, true) +REF_BIN_MIX_INT(unsigned long, 32, false) +#endif +REF_BIN_MIX_INT(ap_slong, 64, true) +REF_BIN_MIX_INT(ap_ulong, 64, false) + +#define REF_BIN_OP(BIN_OP, RTYPE) \ +template \ +INLINE typename ap_private<_AP_W, false>::template RType<_AP_W2, false>::RTYPE \ +operator BIN_OP (const ap_range_ref<_AP_W,_AP_S> &lhs, const ap_range_ref<_AP_W2,_AP_S2> &rhs) { \ + return ap_private<_AP_W,false>(lhs).operator BIN_OP (ap_private<_AP_W2, false>(rhs)); \ +} + +REF_BIN_OP(+, plus) +REF_BIN_OP(-, minus) +REF_BIN_OP(*, mult) +REF_BIN_OP(/, div) +REF_BIN_OP(%, mod) +REF_BIN_OP(>>, arg1) +REF_BIN_OP(<<, arg1) +REF_BIN_OP(&, logic) +REF_BIN_OP(|, logic) +REF_BIN_OP(^, logic) + +#if 1 +#define CONCAT_OP_MIX_INT(C_TYPE, _AP_WI, _AP_SI) \ +template \ +INLINE \ +ap_private< _AP_W + _AP_WI, false > \ + operator, (const ap_private<_AP_W, _AP_S> &op1, C_TYPE op2) { \ + ap_private<_AP_WI + _AP_W, false> val(op2); \ + ap_private<_AP_WI + _AP_W, false> ret(op1); \ + ret <<= _AP_WI; \ + if (_AP_SI) { \ + val <<= _AP_W; val >>= _AP_W; \ + }\ + ret |= val; \ + return ret;\ +} \ +template \ +INLINE \ +ap_private< _AP_W + _AP_WI, false > \ + operator, (C_TYPE op1, const ap_private<_AP_W, _AP_S>& op2) { \ + ap_private<_AP_WI + _AP_W, false> val(op1); \ + ap_private<_AP_WI + _AP_W, false> ret(op2); \ + if (_AP_S) { \ + ret <<= _AP_WI; ret >>= _AP_WI; \ + } \ + ret |= val << _AP_W; \ + return ret; \ +} \ +template \ +INLINE \ +ap_private< _AP_W + _AP_WI, false > \ + operator, (const ap_range_ref<_AP_W, _AP_S> &op1, C_TYPE op2) { \ + ap_private<_AP_WI + _AP_W, false> val(op2); \ + ap_private<_AP_WI + _AP_W, false> ret(op1); \ + ret <<= _AP_WI; \ + if (_AP_SI) { \ + val <<= _AP_W; val >>= _AP_W; \ + } \ + ret |= val; \ + return ret; \ +} \ +template \ +INLINE \ +ap_private< _AP_W + _AP_WI, false > \ + operator, (C_TYPE op1, const ap_range_ref<_AP_W, _AP_S> &op2) { \ + ap_private<_AP_WI + _AP_W, false> val(op1); \ + ap_private<_AP_WI + _AP_W, false> ret(op2); \ + int len = op2.length(); \ + val <<= len; \ + ret |= val; \ + return ret; \ +} \ +template \ +INLINE \ +ap_private<_AP_WI + 1, false > \ + operator, (const ap_bit_ref<_AP_W, _AP_S> &op1, C_TYPE op2) { \ + ap_private<_AP_WI + 1, false> val(op2); \ + val[_AP_WI] = op1; \ + return val; \ +} \ +template \ +INLINE \ +ap_private<_AP_WI + 1, false > \ + operator, (C_TYPE op1, const ap_bit_ref<_AP_W, _AP_S> &op2) { \ + ap_private<_AP_WI + 1, false> val(op1); \ + val <<= 1; \ + val[0] = op2; \ + return val; \ +} \ +template \ +INLINE \ +ap_private<_AP_W + _AP_W2 + _AP_WI, false > \ + operator, (const ap_concat_ref<_AP_W, _AP_T, _AP_W2, _AP_T2> &op1, C_TYPE op2) {\ + ap_private<_AP_WI + _AP_W + _AP_W2, _AP_SI> val(op2);\ + ap_private<_AP_WI + _AP_W + _AP_W2, _AP_SI> ret(op1);\ + if (_AP_SI) { \ + val <<= _AP_W + _AP_W2; val >>= _AP_W + _AP_W2; \ + } \ + ret <<= _AP_WI; \ + ret |= val; \ + return ret; \ +}\ +template \ +INLINE \ +ap_private<_AP_W + _AP_W2 + _AP_WI, false > \ + operator, (C_TYPE op1, const ap_concat_ref<_AP_W, _AP_T, _AP_W2, _AP_T2> &op2) {\ + ap_private<_AP_WI + _AP_W + _AP_W2, _AP_SI> val(op1);\ + ap_private<_AP_WI + _AP_W + _AP_W2, _AP_SI> ret(op2);\ + int len = op2.length(); \ + val <<= len; \ + ret |= val;\ + return ret; \ +}\ +template \ +INLINE \ +ap_private< _AP_W + _AP_WI, false > \ + operator, (const af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op1, C_TYPE op2) { \ + ap_private<_AP_WI + _AP_W, false> val(op2); \ + ap_private<_AP_WI + _AP_W, false> ret(op1); \ + if (_AP_SI) { \ + val <<= _AP_W; val >>= _AP_W; \ + }\ + ret <<= _AP_WI; \ + ret |= val; \ + return ret; \ +} \ +template \ +INLINE \ +ap_private< _AP_W + _AP_WI, false > \ + operator, (C_TYPE op1, const af_range_ref<_AP_W, _AP_I, _AP_S, \ + _AP_Q, _AP_O, _AP_N> &op2) { \ + ap_private<_AP_WI + _AP_W, false> val(op1); \ + ap_private<_AP_WI + _AP_W, false> ret(op2); \ + int len = op2.length(); \ + val <<= len; \ + ret |= val; \ + return ret; \ +} \ +template \ +INLINE \ +ap_private< 1 + _AP_WI, false> \ + operator, (const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, \ + _AP_N> &op1, C_TYPE op2) { \ + ap_private<_AP_WI + 1, _AP_SI> val(op2); \ + val[_AP_WI] = op1; \ + return val; \ +} \ +template \ +INLINE \ +ap_private< 1 + _AP_WI, false> \ + operator, (C_TYPE op1, const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q,\ + _AP_O, _AP_N> &op2) { \ + ap_private<_AP_WI + 1, _AP_SI> val(op1); \ + val <<= 1; \ + val[0] = op2; \ + return val; \ +} + +CONCAT_OP_MIX_INT(bool, 1, false) +CONCAT_OP_MIX_INT(char, 8, true) +CONCAT_OP_MIX_INT(signed char, 8, true) +CONCAT_OP_MIX_INT(unsigned char, 8, false) +CONCAT_OP_MIX_INT(short, 16, true) +CONCAT_OP_MIX_INT(unsigned short, 16, false) +CONCAT_OP_MIX_INT(int, 32, true) +CONCAT_OP_MIX_INT(unsigned int, 32, false) +# if defined __x86_64__ +CONCAT_OP_MIX_INT(long, 64, true) +CONCAT_OP_MIX_INT(unsigned long, 64, false) +# else +CONCAT_OP_MIX_INT(long, 32, true) +CONCAT_OP_MIX_INT(unsigned long, 32, false) +# endif +CONCAT_OP_MIX_INT(ap_slong, 64, true) +CONCAT_OP_MIX_INT(ap_ulong, 64, false) +#endif + +#if 1 +#define CONCAT_SHIFT_MIX_INT(C_TYPE, op) \ +template \ +INLINE ap_uint<_AP_W+_AP_W1> operator op (const ap_concat_ref<_AP_W, _AP_T, _AP_W1, _AP_T1> lhs, C_TYPE rhs) { \ + return ((ap_uint<_AP_W+_AP_W1>)lhs.get()) op ((int)rhs); \ +} + +CONCAT_SHIFT_MIX_INT(long, <<) +CONCAT_SHIFT_MIX_INT(unsigned long, <<) +CONCAT_SHIFT_MIX_INT(unsigned int, <<) +CONCAT_SHIFT_MIX_INT(ap_ulong, <<) +CONCAT_SHIFT_MIX_INT(ap_slong, <<) +CONCAT_SHIFT_MIX_INT(long, >>) +CONCAT_SHIFT_MIX_INT(unsigned long, >>) +CONCAT_SHIFT_MIX_INT(unsigned int, >>) +CONCAT_SHIFT_MIX_INT(ap_ulong, >>) +CONCAT_SHIFT_MIX_INT(ap_slong, >>) +#endif + +#if defined(SYSTEMC_H) || defined(SYSTEMC_INCLUDED) +template +INLINE void sc_trace(sc_core::sc_trace_file *tf, const ap_private<_AP_W, _AP_S> &op, + const std::string &name) { + if (tf) + tf->trace(sc_dt::sc_lv<_AP_W>(op.to_string(2).c_str()), name); +} +#endif + +template +INLINE std::ostream& operator<<(std::ostream& out, const ap_private<_AP_W,_AP_S> &op) +{ + ap_private<_AP_W, _AP_S> v=op; + const std::ios_base::fmtflags basefield = out.flags() & std::ios_base::basefield; + unsigned radix = (basefield == std::ios_base::hex) ? 16 : + ((basefield == std::ios_base::oct) ? 8 : 10); + std::string str=v.toString(radix,_AP_S); + out< +INLINE std::istream& operator >> (std::istream& in, ap_private<_AP_W,_AP_S> &op) +{ + std::string str; + in >> str; + op = ap_private<_AP_W, _AP_S>(str.c_str()); + return in; + +} + +template +INLINE std::ostream& operator<<(std::ostream& out, const ap_range_ref<_AP_W,_AP_S> &op) +{ + return operator<<(out, ap_private<_AP_W, _AP_S>(op)); +} + +template +INLINE std::istream& operator >> (std::istream& in, ap_range_ref<_AP_W,_AP_S> &op) +{ + return operator>>(in, ap_private<_AP_W, _AP_S>(op));; +} + +template +INLINE void print(const ap_private<_AP_W,_AP_S> &op, bool fill=true ) +{ + ap_private<_AP_W, _AP_S> v=op; + uint32_t ws=v.getNumWords(); + const uint64_t *ptr=v.getRawData(); + int i=ws-1; +#if 0 + if(fill) + printf("%016llx",*(ptr+i)); + else + printf("%llx",*(ptr+i)); +#else +//match SystemC output + if(_AP_W%64 != 0) { + uint32_t offset=_AP_W%64; + uint32_t count=(offset+3)/4; + int64_t data=*(ptr+i); + if(_AP_S) + data=(data<<(64-offset))>>(64-offset); + else + count=(offset+4)/4; + while(count-->0) + printf("%llx",(data>>(count*4))&0xf); + } else { + if(_AP_S==false) + printf("0"); + printf("%016llx",*(ptr+i)); + } +#endif + for(--i;i>=0;i--) + printf("%016llx",*(ptr+i)); + printf("\n"); + +} +#endif /* #ifndef __AESL_GCC_AP_INT_H__ */ \ No newline at end of file diff --git a/hls_2018/router_02_boardstr/etc/ap_private.h b/hls_2018/router_02_boardstr/etc/ap_private.h new file mode 100755 index 0000000..1a68a9e --- /dev/null +++ b/hls_2018/router_02_boardstr/etc/ap_private.h @@ -0,0 +1,5858 @@ +/* + * Copyright 2012 Xilinx, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LLVM_SUPPORT_MATHEXTRAS_H +#define LLVM_SUPPORT_MATHEXTRAS_H + +#ifdef _MSC_VER +#if _MSC_VER <= 1500 +typedef __int8 int8_t; +typedef unsigned __int8 uint8_t; +typedef __int16 int16_t; +typedef unsigned __int16 uint16_t; +typedef __int32 int32_t; +typedef unsigned __int32 uint32_t; +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; +#else if +#include +#endif /* #if _MSC_VER <= 1500 */ +#else +#include +#endif /* #if _MSC_VER <= 1500 */ +#undef INLINE +#if 1 +#define INLINE inline +#else +//Enable to debug ap_int/ap_fixed +#define INLINE __attribute__((weak)) +#endif +#define AP_MAX(a,b) ((a) > (b) ? (a) : (b)) +#define AP_MIN(a,b) ((a) < (b) ? (a) : (b)) +#define AP_ABS(a) ((a)>=0 ? (a):-(a)) +#ifndef AP_INT_MAX_W +#define AP_INT_MAX_W 1024 +#endif +#define BIT_WIDTH_UPPER_LIMIT (1 << 15) +#if AP_INT_MAX_W > BIT_WIDTH_UPPER_LIMIT +#error "Bitwidth exceeds 32768 (1 << 15), the maximum allowed value" +#endif +#define MAX_MODE(BITS) ((BITS + 1023) / 1024) + +// NOTE: The following support functions use the _32/_64 extensions instead of +// type overloading so that signed and unsigned integers can be used without +// ambiguity. + +/// Hi_32 - This function returns the high 32 bits of a 64 bit value. +INLINE uint32_t Hi_32(uint64_t Value) { + return static_cast(Value >> 32); +} + +/// Lo_32 - This function returns the low 32 bits of a 64 bit value. +INLINE uint32_t Lo_32(uint64_t Value) { + return static_cast(Value); +} + +/// ByteSwap_16 - This function returns a byte-swapped representation of the +/// 16-bit argument, Value. +INLINE uint16_t ByteSwap_16(uint16_t Value) { +#if defined(_MSC_VER) && !defined(_DEBUG) + // The DLL version of the runtime lacks these functions (bug!?), but in a + // release build they're replaced with BSWAP instructions anyway. + return (uint16_t)(_byteswap_ushort(Value)); +#else + uint16_t Hi = (uint16_t)((Value) << 8); + uint16_t Lo = (uint16_t)((Value) >> 8); + return Hi | Lo; +#endif +} + +/// ByteSwap_32 - This function returns a byte-swapped representation of the +/// 32-bit argument, Value. +INLINE uint32_t ByteSwap_32(uint32_t Value) { + uint32_t Byte0 = Value & 0x000000FF; + uint32_t Byte1 = Value & 0x0000FF00; + uint32_t Byte2 = Value & 0x00FF0000; + uint32_t Byte3 = Value & 0xFF000000; + return ((Byte0) << 24) | ((Byte1) << 8) | ((Byte2) >> 8) | ((Byte3) >> 24); +} + +/// ByteSwap_64 - This function returns a byte-swapped representation of the +/// 64-bit argument, Value. +INLINE uint64_t ByteSwap_64(uint64_t Value) { + uint64_t Hi = ByteSwap_32(uint32_t(Value)); + uint32_t Lo = ByteSwap_32(uint32_t(Value >> 32)); + return ((Hi) << 32) | Lo; +} + +/// CountLeadingZeros_32 - this function performs the platform optimal form of +/// counting the number of zeros from the most significant bit to the first one +/// bit. Ex. CountLeadingZeros_32(0x00F000FF) == 8. +/// Returns 32 if the word is zero. +INLINE unsigned CountLeadingZeros_32(uint32_t Value) { + unsigned Count; // result +#if __GNUC__ >= 4 + // PowerPC is defined for __builtin_clz(0) +#if !defined(__ppc__) && !defined(__ppc64__) + if (Value == 0) return 32; +#endif + Count = __builtin_clz(Value); +#else + if (Value == 0) return 32; + Count = 0; + // bisecton method for count leading zeros + for (unsigned Shift = 32 >> 1; Shift; Shift >>= 1) { + uint32_t Tmp = (Value) >> (Shift); + if (Tmp) { + Value = Tmp; + } else { + Count |= Shift; + } + } +#endif + return Count; +} + +/// CountLeadingZeros_64 - This function performs the platform optimal form +/// of counting the number of zeros from the most significant bit to the first +/// one bit (64 bit edition.) +/// Returns 64 if the word is zero. +INLINE unsigned CountLeadingZeros_64(uint64_t Value) { + unsigned Count; // result +#if __GNUC__ >= 4 + // PowerPC is defined for __builtin_clzll(0) +#if !defined(__ppc__) && !defined(__ppc64__) + if (!Value) return 64; +#endif + Count = __builtin_clzll(Value); +#else + if (sizeof(long) == sizeof(int64_t)) { + if (!Value) return 64; + Count = 0; + // bisecton method for count leading zeros + for (unsigned Shift = 64 >> 1; Shift; Shift >>= 1) { + uint64_t Tmp = (Value) >> (Shift); + if (Tmp) { + Value = Tmp; + } else { + Count |= Shift; + } + } + } else { + // get hi portion + uint32_t Hi = Hi_32(Value); + + // if some bits in hi portion + if (Hi) { + // leading zeros in hi portion plus all bits in lo portion + Count = CountLeadingZeros_32(Hi); + } else { + // get lo portion + uint32_t Lo = Lo_32(Value); + // same as 32 bit value + Count = CountLeadingZeros_32(Lo)+32; + } + } +#endif + return Count; +} + +/// CountTrailingZeros_64 - This function performs the platform optimal form +/// of counting the number of zeros from the least significant bit to the first +/// one bit (64 bit edition.) +/// Returns 64 if the word is zero. +INLINE unsigned CountTrailingZeros_64(uint64_t Value) { +#if __GNUC__ >= 4 + return (Value != 0) ? __builtin_ctzll(Value) : 64; +#else + static const unsigned Mod67Position[] = { + 64, 0, 1, 39, 2, 15, 40, 23, 3, 12, 16, 59, 41, 19, 24, 54, + 4, 64, 13, 10, 17, 62, 60, 28, 42, 30, 20, 51, 25, 44, 55, + 47, 5, 32, 65, 38, 14, 22, 11, 58, 18, 53, 63, 9, 61, 27, + 29, 50, 43, 46, 31, 37, 21, 57, 52, 8, 26, 49, 45, 36, 56, + 7, 48, 35, 6, 34, 33, 0 + }; + return Mod67Position[(uint64_t)(-(int64_t)Value & (int64_t)Value) % 67]; +#endif +} + +/// CountPopulation_64 - this function counts the number of set bits in a value, +/// (64 bit edition.) +INLINE unsigned CountPopulation_64(uint64_t Value) { +#if __GNUC__ >= 4 + return __builtin_popcountll(Value); +#else + uint64_t v = Value - (((Value) >> 1) & 0x5555555555555555ULL); + v = (v & 0x3333333333333333ULL) + (((v) >> 2) & 0x3333333333333333ULL); + v = (v + ((v) >> 4)) & 0x0F0F0F0F0F0F0F0FULL; + return unsigned((uint64_t)(v * 0x0101010101010101ULL) >> 56); +#endif +} + +#endif // LLVM_SUPPORT_MATHEXTRAS_H + + +#ifndef AP_PRIVATE_H +#define AP_PRIVATE_H + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace AESL_std { + template + DataType INLINE min(DataType a, DataType b) { + // if (a >= b) return b; + // else return a; + return (a>=b) ? b : a; + } + + template + DataType INLINE max(DataType a, DataType b) { + // if (a >= b) return a; + // else return b; + return (a>=b) ? a : b; + } +} +enum ap_q_mode { + AP_RND, // rounding to plus infinity + AP_RND_ZERO,// rounding to zero + AP_RND_MIN_INF,// rounding to minus infinity + AP_RND_INF,// rounding to infinity + AP_RND_CONV, // convergent rounding + AP_TRN, // truncation + AP_TRN_ZERO // truncation to zero + +}; +enum ap_o_mode { + AP_SAT, // saturation + AP_SAT_ZERO, // saturation to zero + AP_SAT_SYM, // symmetrical saturation + AP_WRAP, // wrap-around (*) + AP_WRAP_SM // sign magnitude wrap-around (*) +}; + +template struct ap_fixed_base; +template struct af_range_ref; +template struct af_bit_ref; + +template struct ap_range_ref; +template struct ap_bit_ref; +template struct ap_concat_ref; +static bool InvalidDigit(const char* str, unsigned len, unsigned start, unsigned radix) { + unsigned i; + for (i = start; i < len; ++i) + if ((radix == 2 && (str[i] == '0' || str[i] == '1')) || + (radix == 8 && str[i] >= '0' && str[i] <= '7') || + (radix == 10 && str[i] >= '0' && str[i] <= '9') || + (radix == 16 && ((str[i] >= '0' && str[i] <= '9') || + (str[i] >= 'a' && str[i] <= 'f') || + (str[i] >= 'A' && str[i] <= 'F')))) + continue; + else + return true; + return false; +} + +static void ap_parse_sign(const char* str, uint32_t &base, bool &neg) { + if (str[0] == '+' || str[0] == '-') base = 1; + if (str[0] == '-') neg = true; + else neg = false; + return; +} + +static void ap_parse_prefix(const char* str, uint32_t &offset, uint32_t &radix) { + if (str[0] == '0') { + switch (str[1]) { + case 'b': + case 'B': offset = 2; radix = 2; break; + case 'x': + case 'X': offset = 2; radix = 16; break; + case 'd': + case 'D': offset = 2; radix = 10; break; + case 'o': + case 'O': offset = 2; radix = 8; break; + default: break; + } + } + if (offset == 0) + for (int i=0, len = strlen(str); i= 'a') || (str[i] <= 'F' && str[i] >= 'A')) { + radix = 16; + break; + } + return; +} + +/// sub_1 - This function subtracts a single "digit" (64-bit word), y, from +/// the multi-digit integer array, x[], propagating the borrowed 1 value until +/// no further borrowing is neeeded or it runs out of "digits" in x. The result +/// is 1 if "borrowing" exhausted the digits in x, or 0 if x was not exhausted. +/// In other words, if y > x then this function returns 1, otherwise 0. +/// @returns the borrow out of the subtraction +static bool sub_1(uint64_t x[], uint32_t len, uint64_t y) { + for (uint32_t i = 0; i < len; ++i) { + uint64_t __X = x[i]; + x[i] -= y; + if (y > __X) + y = 1; // We have to "borrow 1" from next "digit" + else { + y = 0; // No need to borrow + break; // Remaining digits are unchanged so exit early + } + } + return (y != 0); +} + + /// This enumeration just provides for internal constants used in this + /// translation unit. + enum { + MIN_INT_BITS = 1, ///< Minimum number of bits that can be specified + ///< Note that this must remain synchronized with IntegerType::MIN_INT_BITS + MAX_INT_BITS = (1<<23)-1 ///< Maximum number of bits that can be specified + ///< Note that this must remain synchronized with IntegerType::MAX_INT_BITS + }; + + /// A utility function for allocating memory and checking for allocation + /// failure. The content is not zeroed. + static uint64_t* getMemory(uint32_t numWords) { + return (uint64_t*) malloc(numWords*sizeof(uint64_t)); + } + + //===----------------------------------------------------------------------===// + // ap_private Class + //===----------------------------------------------------------------------===// + + /// ap_private - This class represents arbitrary precision constant integral values. + /// It is a functional replacement for common case unsigned integer type like + /// "unsigned", "unsigned long" or "uint64_t", but also allows non-byte-width + /// integer sizes and large integer value types such as 3-bits, 15-bits, or more + /// than 64-bits of precision. ap_private provides a variety of arithmetic operators + /// and methods to manipulate integer values of any bit-width. It supports both + /// the typical integer arithmetic and comparison operations as well as bitwise + /// manipulation. + /// + /// The class has several invariants worth noting: + /// * All bit, byte, and word positions are zero-based. + /// * Once the bit width is set, it doesn't change except by the Truncate, + /// SignExtend, or ZeroExtend operations. + /// * All binary operators must be on ap_private instances of the same bit width. + /// Attempting to use these operators on instances with different bit + /// widths will yield an assertion. + /// * The value is stored canonically as an unsigned value. For operations + /// where it makes a difference, there are both signed and unsigned variants + /// of the operation. For example, sdiv and udiv. However, because the bit + /// widths must be the same, operations such as Mul and Add produce the same + /// results regardless of whether the values are interpreted as signed or + /// not. + /// * In general, the class tries to follow the style of computation that LLVM + /// uses in its IR. This simplifies its use for LLVM. + /// + /// @brief Class for arbitrary precision integers. + template class ap_private; + namespace ap_private_ops{ + template + INLINE ap_private<_AP_W, _AP_S, _AP_N> lshr(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, uint32_t shiftAmt); + template + INLINE ap_private<_AP_W, _AP_S, _AP_N> shl(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, uint32_t shiftAmt); + } + +#if defined(_MSC_VER) +# if _MSC_VER < 1400 && !defined(for) +# define for if(0);else for +# endif + typedef unsigned __int64 ap_ulong; + typedef signed __int64 ap_slong; +#else + typedef unsigned long long ap_ulong; + typedef signed long long ap_slong; +#endif + template struct retval { + }; + template<> struct retval { + typedef ap_slong Type; + }; + template<> struct retval { + typedef ap_ulong Type; + }; + + template + class ap_private { +#ifdef _MSC_VER +#pragma warning( disable : 4521 4522 ) +#endif +public: + typedef typename retval<_AP_S>::Type ValType; + template friend struct ap_fixed_base; + ///return type of variety of operations + //---------------------------------------------------------- + template + struct RType { + enum { + mult_w = _AP_W+_AP_W2, + mult_s = _AP_S||_AP_S2, + plus_w = AP_MAX(_AP_W+(_AP_S2&&!_AP_S),_AP_W2+(_AP_S&&!_AP_S2))+1, + plus_s = _AP_S||_AP_S2, + minus_w = AP_MAX(_AP_W+(_AP_S2&&!_AP_S),_AP_W2+(_AP_S&&!_AP_S2))+1, + minus_s = true, + div_w = _AP_W+_AP_S2, + div_s = _AP_S||_AP_S2, + mod_w = AP_MIN(_AP_W,_AP_W2+(!_AP_S2&&_AP_S)), + mod_s = _AP_S, + logic_w = AP_MAX(_AP_W+(_AP_S2&&!_AP_S),_AP_W2+(_AP_S&&!_AP_S2)), + logic_s = _AP_S||_AP_S2 + }; + typedef ap_private mult; + typedef ap_private plus; + typedef ap_private minus; + typedef ap_private logic; + typedef ap_private div; + typedef ap_private mod; + typedef ap_private<_AP_W, _AP_S> arg1; + typedef bool reduce; + }; + + INLINE void report() { +#if 0 + if (_AP_W > 1024 && _AP_W <= 4096) { + fprintf(stderr, "[W] W=%d is out of bound (1<=W<=1024): for" + " synthesis: please define macro AP_INT_TYPE_EXT(N)" + " to extend the valid range.\n", _AP_W); + } else +#endif + if (_AP_W > MAX_MODE(AP_INT_MAX_W) * 1024) { + fprintf(stderr, "[E] ap_%sint<%d>: Bitwidth exceeds the " + "default max value %d. Please use macro " + "AP_INT_MAX_W to set a larger max value.\n", + _AP_S?"":"u", _AP_W, + MAX_MODE(AP_INT_MAX_W) * 1024); + exit(1); + } + } + + enum { BitWidth = _AP_W }; + /// This union is used to store the integer value. When the + /// integer bit-width <= 64, it uses VAL, otherwise it uses pVal. + + /// This enum is used to hold the constants we needed for ap_private. + uint64_t VAL; ///< Used to store the <= 64 bits integer value. + uint64_t pVal[_AP_N]; ///< Used to store the >64 bits integer value. + + /// This enum is used to hold the constants we needed for ap_private. + enum { + APINT_BITS_PER_WORD = sizeof(uint64_t) * 8, ///< Bits in a word + APINT_WORD_SIZE = sizeof(uint64_t) ///< Byte size of a word + }; + + enum { excess_bits = (_AP_W%APINT_BITS_PER_WORD) ? APINT_BITS_PER_WORD -(_AP_W%APINT_BITS_PER_WORD) : 0}; + static const uint64_t mask = ((uint64_t)~0ULL >> (excess_bits)); + + /// This constructor is used only internally for speed of construction of + /// temporaries. It is unsafe for general use so it is not public. + /* Constructors */ + + ap_private(const char* val) { + std::string str(val); + uint32_t strLen = str.length(); + const char *strp = str.c_str(); + uint32_t offset = 0; + uint32_t base = 0; + bool neg = false; + uint32_t radix = 16; + ap_parse_sign(strp, base, neg); + ap_parse_prefix(strp + base, offset, radix); + + if ((radix != 10 && neg) || + (strLen - base - offset <= 0) || + InvalidDigit(strp, strLen, base + offset, radix)) { + fprintf(stderr, "invalid character string %s !\n", val); + assert(0); + } + + ap_private ap_private_val(str.c_str(), strLen, radix, base, offset); + if (neg) + ap_private_val = -ap_private_val; + operator = (ap_private_val); + report(); + } + + ap_private(const char* val, int rd) { + std::string str(val); + uint32_t strLen = str.length(); + const char *strp = str.c_str(); + uint32_t offset = 0; + uint32_t base = 0; + uint32_t radix = rd; + bool neg = false; + ap_parse_sign(strp, base, neg); + ap_parse_prefix(strp + base, offset, radix); + + if ((radix != 10 && neg) || + (strLen - base - offset <= 0) || + InvalidDigit(strp, strLen, base + offset, radix)) { + fprintf(stderr, "invalid character string %s !\n", val); + assert(0); + } + + // uint32_t bitsNeeded = ap_private<_AP_W, _AP_S>::getBitsNeeded(strp, strLen, radix); + // ap_private<_AP_W, _AP_S> ap_private_val(bitsNeeded, strp , strLen, radix, base, offset); + ap_private ap_private_val(strp , strLen, radix, base, offset); + if (neg) + ap_private_val = -ap_private_val; + operator = (ap_private_val); + report(); + } + + /// Note that numWords can be smaller or larger than the corresponding bit + /// width but any extraneous bits will be dropped. + /// @param numBits the bit width of the constructed ap_private + /// @param numWords the number of words in bigVal + /// @param bigVal a sequence of words to form the initial value of the ap_private + /// @brief Construct an ap_private of numBits width, initialized as bigVal[]. + ap_private(uint32_t numWords, const uint64_t bigVal[]): VAL(0) { + assert(bigVal && "Null pointer detected!"); + { + // Get memory, cleared to 0 + memset(pVal, 0, _AP_N * sizeof(uint64_t)); + + // Calculate the number of words to copy + uint32_t words = AESL_std::min(numWords, _AP_N); + // Copy the words from bigVal to pVal + memcpy(pVal, bigVal, words * APINT_WORD_SIZE); + if (words >= _AP_W) + clearUnusedBits(); + // Make sure unused high bits are cleared + } + } + + /// This constructor interprets Val as a string in the given radix. The + /// interpretation stops when the first charater that is not suitable for the + /// radix is encountered. Acceptable radix values are 2, 8, 10 and 16. It is + /// an error for the value implied by the string to require more bits than + /// numBits. + /// @param numBits the bit width of the constructed ap_private + /// @param val the string to be interpreted + /// @param radix the radix of Val to use for the intepretation + /// @brief Construct an ap_private from a string representation. + ap_private(const std::string& val, uint8_t radix=2, int base=0, int offset=0): VAL(0) { + assert(!val.empty() && "The input string is empty."); + const char *c_str = val.c_str(); + fromString(c_str+base+offset, val.size()-base-offset, radix); + } + + /// This constructor interprets the slen characters starting at StrStart as + /// a string in the given radix. The interpretation stops when the first + /// character that is not suitable for the radix is encountered. Acceptable + /// radix values are 2, 8, 10 and 16. It is an error for the value implied by + /// the string to require more bits than numBits. + /// @param numBits the bit width of the constructed ap_private + /// @param strStart the start of the string to be interpreted + /// @param slen the maximum number of characters to interpret + /// @param radix the radix to use for the conversion + /// @brief Construct an ap_private from a string representation. + /// This method does not consider whether it is negative or not. + ap_private(const char strStart[], uint32_t slen, uint8_t radix, int base=0, int offset=0) : VAL(0) { + fromString(strStart+base+offset, slen-base-offset, radix); + } + + template + INLINE ap_private(const ap_range_ref<_AP_W2,_AP_S2>& ref) { + *this=ref.get(); + report(); + } + + template + INLINE ap_private(const ap_bit_ref<_AP_W2,_AP_S2>& ref) { + *this = ((uint64_t)(bool)ref); + report(); + } + + template + INLINE ap_private(const ap_concat_ref<_AP_W2, _AP_T2,_AP_W3, _AP_T3>& ref) { + *this=ref.get(); + report(); + } + + template + INLINE ap_private(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2> &val) { + *this = ((val.operator ap_private<_AP_W2, false> ())); + report(); + } + + template + INLINE ap_private(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2> &val) { + *this = (uint64_t)(bool)val; + report(); + } + + /// Simply makes *this a copy of that. + /// @brief Copy Constructor. + template + ap_private(const volatile ap_private<_AP_W1, _AP_S1, _AP_N1>& that): VAL(0) { + operator = (const_cast& >(that)); + } + + template + ap_private(const ap_private<_AP_W1, _AP_S1, _AP_N1>& that): VAL(0) { + operator = (that); + } + + template + explicit ap_private(const ap_private<_AP_W1, _AP_S1, 1>& that): VAL(0) { + static const uint64_t that_sign_ext_mask = (_AP_W1==APINT_BITS_PER_WORD)?0:~0ULL>>(_AP_W1%APINT_BITS_PER_WORD)<<(_AP_W1%APINT_BITS_PER_WORD); + if (that.isNegative()) { + pVal[0] = that.VAL|that_sign_ext_mask; + memset(pVal+1, ~0, sizeof(uint64_t)*(_AP_N-1)); + } else { + pVal[0] = that.VAL; + memset(pVal+1, 0, sizeof(uint64_t)*(_AP_N-1)); + } + clearUnusedBits(); + } + + ap_private(const ap_private& that): VAL(0) { + memcpy(pVal, that.pVal, _AP_N * APINT_WORD_SIZE); + clearUnusedBits(); + } + + /// @brief Destructor. + virtual ~ap_private() {} + + /// Default constructor that creates an uninitialized ap_private. This is useful + /// for object deserialization (pair this with the static method Read). + ap_private(){memset(pVal, 0, sizeof(uint64_t)*(_AP_N));} + + ap_private(uint64_t* val, uint32_t bits=_AP_W) {assert(0);} + ap_private(const uint64_t *const val, uint32_t bits) {assert(0);} + + /// @name Constructors + /// @{ + /// If isSigned is true then val is treated as if it were a signed value + /// (i.e. as an int64_t) and the appropriate sign extension to the bit width + /// will be done. Otherwise, no sign extension occurs (high order bits beyond + /// the range of val are zero filled). + /// @param numBits the bit width of the constructed ap_private + /// @param val the initial value of the ap_private + /// @param isSigned how to treat signedness of val + /// @brief Create a new ap_private of numBits width, initialized as val. +#define CTOR(TYPE, SIGNED) \ + ap_private(TYPE val, bool isSigned=SIGNED) { \ + pVal[0] = val; \ + if (isSigned && int64_t(pVal[0]) < 0) { \ + memset(pVal+1, ~0, sizeof(uint64_t)*(_AP_N-1)); \ + } else { \ + memset(pVal+1, 0, sizeof(uint64_t)*(_AP_N-1)); \ + } \ + clearUnusedBits(); \ + } +#if 1 + CTOR(int, true) + CTOR(bool, false) + CTOR(signed char, true) + CTOR(unsigned char, false) + CTOR(short, true) + CTOR(unsigned short, false) + CTOR(unsigned int, false) + CTOR(long, true) + CTOR(unsigned long, false) + CTOR(unsigned long long, false) + CTOR(long long, true) + CTOR(float, false) + CTOR(double, false) +#undef CTOR +#else + CTOR(uint64_t) +#undef CTOR +#endif + + + /// @returns true if the number of bits <= 64, false otherwise. + /// @brief Determine if this ap_private just has one word to store value. + INLINE bool isSingleWord() const { + return false; + } + + /// @returns the word position for the specified bit position. + /// @brief Determine which word a bit is in. + static uint32_t whichWord(uint32_t bitPosition) { + // return bitPosition / APINT_BITS_PER_WORD; + return (bitPosition) >> 6; + } + + /// @returns the bit position in a word for the specified bit position + /// in the ap_private. + /// @brief Determine which bit in a word a bit is in. + static uint32_t whichBit(uint32_t bitPosition) { + // return bitPosition % APINT_BITS_PER_WORD; + return bitPosition & 0x3f; + } + + /// bit at a specific bit position. This is used to mask the bit in the + /// corresponding word. + /// @returns a uint64_t with only bit at "whichBit(bitPosition)" set + /// @brief Get a single bit mask. + static uint64_t maskBit(uint32_t bitPosition) { + return 1ULL << (whichBit(bitPosition)); + } + + /// @returns the corresponding word for the specified bit position. + /// @brief Get the word corresponding to a bit position + INLINE uint64_t getWord(uint32_t bitPosition) const { + return isSingleWord() ? VAL : pVal[whichWord(bitPosition)]; + } + + /// This method is used internally to clear the to "N" bits in the high order + /// word that are not used by the ap_private. This is needed after the most + /// significant word is assigned a value to ensure that those bits are + /// zero'd out. + /// @brief Clear unused high order bits + INLINE void clearUnusedBits(void) { + pVal[_AP_N-1] = _AP_S ? ((((int64_t)pVal[_AP_N-1])<<(excess_bits))>> excess_bits) : (excess_bits ? ((pVal[_AP_N-1])<<(excess_bits))>>(excess_bits) : pVal[_AP_N-1]); + } + + INLINE void clearUnusedBitsToZero(void) { + pVal[_AP_N-1] &= mask; + } + + INLINE void clearUnusedBitsToOne(void) { + pVal[_AP_N-1] |= mask; + } + + /// This is used by the constructors that take string arguments. + /// @brief Convert a char array into an ap_private + INLINE void fromString(const char *strStart, uint32_t slen, + uint8_t radix) ; + + INLINE ap_private read() volatile { + return *this; + } + + INLINE void write(const ap_private& op2) volatile { + *this = (op2); + } + + //Explicit conversions to C interger types + //----------------------------------------------------------- + operator ValType() const { + return getVal(); + } + + INLINE ValType getVal() const{ + return *pVal; + } + + INLINE int to_int() const { + return int(*this); + } + + INLINE unsigned to_uint() const { + return (unsigned) getVal(); + } + + INLINE long to_long() const { + return (long) getVal(); + } + + INLINE unsigned long to_ulong() const { + return (unsigned long) getVal(); + } + + INLINE ap_slong to_int64() const { + return (ap_slong) getVal(); + } + + INLINE ap_ulong to_uint64() const { + return (ap_ulong) getVal(); + } + + INLINE double to_double() const { + if (isNegative()) + return roundToDouble(true); + else + return roundToDouble(false); + } + + INLINE unsigned length() const { return _AP_W; } + + /*Reverse the contents of ap_private instance. I.e. LSB becomes MSB and vise versa*/ + INLINE ap_private& reverse () { + for (int i = 0; i < _AP_W/2; ++i) { + bool tmp = operator[](i); + if (operator[](_AP_W - 1 - i)) + set(i); + else + clear(i); + if (tmp) + set(_AP_W - 1 - i); + else + clear(_AP_W - 1 - i); + } + clearUnusedBits(); + return *this; + } + + /*Return true if the value of ap_private instance is zero*/ + INLINE bool iszero () const { + return isMinValue(); + } + + /* x < 0 */ + INLINE bool sign () const { + if (isNegative()) + return true; + return false; + } + + /* x[i] = !x[i] */ + INLINE void invert (int i) { + assert( i >= 0 && "Attempting to read bit with negative index"); + assert( i < _AP_W && "Attempting to read bit beyond MSB"); + flip(i); + } + + /* x[i] */ + INLINE bool test (int i) const { + assert( i >= 0 && "Attempting to read bit with negative index"); + assert( i < _AP_W && "Attempting to read bit beyond MSB"); + return operator[](i); + } + + //Set the ith bit into v + INLINE void set (int i, bool v) { + assert( i >= 0 && "Attempting to write bit with negative index"); + assert( i < _AP_W && "Attempting to write bit beyond MSB"); + v ? set(i) : clear(i); + } + + //Set the ith bit into v + INLINE void set_bit (int i, bool v) { + assert( i >= 0 && "Attempting to write bit with negative index"); + assert( i < _AP_W && "Attempting to write bit beyond MSB"); + v ? set(i) : clear(i); + } + + INLINE ap_private& set(uint32_t bitPosition) { + pVal[whichWord(bitPosition)] |= maskBit(bitPosition); + clearUnusedBits(); + return *this; + } + + INLINE void set() { + for (uint32_t i = 0; i < _AP_N; ++i) + pVal[i] = ~0ULL; + clearUnusedBits(); + } + + //Get the value of ith bit + INLINE bool get (int i) const { + assert( i >= 0 && "Attempting to read bit with negative index"); + assert( i < _AP_W && "Attempting to read bit beyond MSB"); + return operator [](i); + } + + //Get the value of ith bit + INLINE bool get_bit (int i) const { + assert( i >= 0 && "Attempting to read bit with negative index"); + assert( i < _AP_W && "Attempting to read bit beyond MSB"); + return operator [](i); + } + + //This is used for sc_lv and sc_bv, which is implemented by sc_uint + //Rotate an ap_private object n places to the left + INLINE void lrotate(int n) { + assert( n >= 0 && "Attempting to shift negative index"); + assert( n < _AP_W && "Shift value larger than bit width"); + operator = (shl(n) | lshr(_AP_W - n)); + } + + //This is used for sc_lv and sc_bv, which is implemented by sc_uint + //Rotate an ap_private object n places to the right + INLINE void rrotate(int n) { + assert( n >= 0 && "Attempting to shift negative index"); + assert( n < _AP_W && "Shift value larger than bit width"); + operator = (lshr(n) | shl(_AP_W - n)); + } + + /// Set the given bit to 0 whose position is given as "bitPosition". + /// @brief Set a given bit to 0. + ap_private& clear(uint32_t bitPosition) { + pVal[whichWord(bitPosition)] &= ~maskBit(bitPosition); + clearUnusedBits(); + return *this; + } + + /// @brief Set every bit to 0. + void clear() { + memset(pVal, 0, _AP_N * APINT_WORD_SIZE); + } + + /// @brief Toggle every bit to its opposite value. + ap_private& flip() { + for (uint32_t i = 0; i < _AP_N; ++i) + pVal[i] ^= ~0ULL; + clearUnusedBits(); + return *this; + } + + /// Toggle a given bit to its opposite value whose position is given + /// as "bitPosition". + /// @brief Toggles a given bit to its opposite value. + ap_private& flip(uint32_t bitPosition) { + assert(bitPosition < BitWidth && "Out of the bit-width range!"); + if ((*this)[bitPosition]) clear(bitPosition); + else set(bitPosition); + return *this; + } + + //complements every bit + INLINE void b_not() { + flip(); + } + + ap_private getLoBits(uint32_t numBits) const { + return ap_private_ops::lshr(ap_private_ops::shl(*this, _AP_W - numBits), + _AP_W - numBits); + } + + ap_private getHiBits(uint32_t numBits) const { + return ap_private_ops::lshr(*this, _AP_W - numBits); + } + + //Binary Arithmetic + //----------------------------------------------------------- + + template + INLINE ap_private + operator & (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) { + return *this & a2.get(); + } + + template + INLINE ap_private + operator | (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) { + return *this | a2.get(); + } + + template + INLINE ap_private + operator ^ (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) { + return *this ^ a2.get(); + } + + + ///Arithmetic assign + //------------------------------------------------------------- + +#define OP_BIN_LOGIC_ASSIGN_AP(Sym) \ + template \ + INLINE ap_private& operator Sym(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { \ + uint32_t numWords = AESL_std::min(_AP_N, _AP_N1); \ + uint32_t i; \ + for (i = 0; i < numWords; ++i) \ + pVal[i] Sym RHS.pVal[i]; \ + if (_AP_N1 < _AP_N) { \ + uint64_t ext = RHS.isNegative()?~0ULL:0; \ + for (;i<_AP_N; i++) \ + pVal[i] Sym ext; \ + } \ + clearUnusedBits(); \ + return *this; \ + } + + OP_BIN_LOGIC_ASSIGN_AP(&=); + OP_BIN_LOGIC_ASSIGN_AP(|=); + OP_BIN_LOGIC_ASSIGN_AP(^=); +#undef OP_BIN_LOGIC_ASSIGN_AP + + /// Adds the RHS APint to this ap_private. + /// @returns this, after addition of RHS. + /// @brief Addition assignment operator. + template + INLINE ap_private& operator+=(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { + add(pVal, pVal, RHS.pVal, _AP_N, _AP_N, _AP_N1, _AP_S, _AP_S1); + clearUnusedBits(); + return *this; + } + + template + INLINE ap_private& operator-=(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { + sub(pVal, pVal, RHS.pVal, _AP_N, _AP_N, _AP_N1, _AP_S, _AP_S1); + clearUnusedBits(); + return *this; + } + + template + ap_private& operator*=(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { + // Get some bit facts about LHS and check for zero + uint32_t lhsBits = getActiveBits(); + uint32_t lhsWords = !lhsBits ? 0 : whichWord(lhsBits - 1) + 1; + if (!lhsWords) { + // 0 * X ===> 0 + return *this; + } + + ap_private dupRHS = RHS; + // Get some bit facts about RHS and check for zero + uint32_t rhsBits = dupRHS.getActiveBits(); + uint32_t rhsWords = !rhsBits ? 0 : whichWord(rhsBits - 1) + 1; + if (!rhsWords) { + // X * 0 ===> 0 + clear(); + return *this; + } + + // Allocate space for the result + uint32_t destWords = rhsWords + lhsWords; + uint64_t *dest = getMemory(destWords); + + // Perform the long multiply + mul(dest, pVal, lhsWords, dupRHS.pVal, rhsWords, destWords); + + // Copy result back into *this + clear(); + uint32_t wordsToCopy = destWords >= _AP_N ? _AP_N : destWords; + + memcpy(pVal, dest, wordsToCopy* APINT_WORD_SIZE); + + uint64_t ext = (isNegative() ^ RHS.isNegative()) ? ~0ULL : 0ULL; + for (int i=wordsToCopy; i<_AP_N; i++) + pVal[i]=ext; + clearUnusedBits(); + // delete dest array and return + free(dest); + return *this; + } + +#define OP_ASSIGN_AP(Sym) \ + template \ + INLINE ap_private& operator Sym##=(const ap_private<_AP_W2,_AP_S2>& op) \ + { \ + *this=operator Sym (op); \ + return *this; \ + } \ + + OP_ASSIGN_AP(/) + OP_ASSIGN_AP(%) +#undef OP_ASSIGN_AP + +#define OP_BIN_LOGIC_AP(Sym) \ + template \ + INLINE \ + typename RType<_AP_W1, _AP_S1>::logic \ + operator Sym (const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) const { \ + enum { numWords = (RType<_AP_W1, _AP_S1>::logic_w +APINT_BITS_PER_WORD-1)/APINT_BITS_PER_WORD}; \ + typename RType<_AP_W1, _AP_S1>::logic Result; \ + uint64_t *val = Result.pVal; \ + uint32_t i; \ + uint32_t min_N = std::min(_AP_N, _AP_N1); \ + uint32_t max_N = std::max(_AP_N, _AP_N1); \ + for (i = 0; i < min_N; ++i) \ + val[i] = pVal[i] Sym RHS.pVal[i]; \ + if (numWords > i) { \ + const uint64_t* tmpVal = (_AP_N>_AP_N1 ? pVal : RHS.pVal)+i; \ + uint64_t ext = ((_AP_N<_AP_N1 && isNegative() )||(_AP_N1 < _AP_N && RHS.isNegative())) ? ~0ULL : 0; \ + for (;i i) { \ + uint64_t ext2 = ((_AP_N>_AP_N1 && isNegative() )||(_AP_N1 > _AP_N && RHS.isNegative())) ? ~0ULL : 0; \ + val[i] = ext Sym ext2; \ + } \ + } \ + Result.clearUnusedBits(); \ + return Result; \ + } + + OP_BIN_LOGIC_AP(|); + OP_BIN_LOGIC_AP(&); + OP_BIN_LOGIC_AP(^); + +#undef OP_BIN_LOGIC_AP + + template + INLINE typename RType<_AP_W1,_AP_S1>::plus operator+(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) const { + // assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + typename RType<_AP_W1,_AP_S1>::plus Result; + bool carry = add(Result.pVal, this->pVal, RHS.pVal, (RType<_AP_W1,_AP_S1>::plus_w + 63) / 64, _AP_N, _AP_N1, _AP_S, _AP_S1); + if ((RType<_AP_W1,_AP_S1>::plus_w + 63) / 64> std::max(_AP_W, _AP_W1) ) + Result.pVal[(RType<_AP_W1,_AP_S1>::plus_w + 63)/64 - 1] = carry; + Result.clearUnusedBits(); + return Result; + } + + template + INLINE typename RType<_AP_W1,_AP_S1>::minus operator-(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) const { + typename RType<_AP_W1,_AP_S1>::minus Result; + bool borrow = sub(Result.pVal, this->pVal, RHS.pVal, (RType<_AP_W1,_AP_S1>::minus_w + 63) / 64, _AP_N, _AP_N1, _AP_S, _AP_S1); + if ((RType<_AP_W1,_AP_S1>::minus_w + 63) / 64 > AESL_std::max(_AP_W, _AP_W1) ) { + Result.pVal[(RType<_AP_W1,_AP_S1>::minus_w+63)/64 - 1] = borrow; + } + Result.clearUnusedBits(); + return Result; + } + + template + typename RType<_AP_W1, _AP_S1>::mult operator*(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) const { + + // Get some bit facts about LHS and check for zero + uint32_t lhsBits = getActiveBits(); + uint32_t lhsWords = !lhsBits ? 0 : whichWord(lhsBits - 1) + 1; + if (!lhsWords) + // 0 * X ===> 0 + return typename RType<_AP_W1, _AP_S1>::mult(); + + // Get some bit facts about RHS and check for zero + uint32_t rhsBits = RHS.getActiveBits(); + uint32_t rhsWords = !rhsBits ? 0 : whichWord(rhsBits - 1) + 1; + if (!rhsWords) { + // X * 0 ===> 0 + return typename RType<_AP_W1, _AP_S1>::mult(); + } + + //extend size to avoid result loss + typename RType<_AP_W1, _AP_S1>::mult dupLHS = *this; + typename RType<_AP_W1, _AP_S1>::mult dupRHS = RHS; + lhsBits = dupLHS.getActiveBits(); + lhsWords = !lhsBits ? 0 : whichWord(lhsBits - 1) + 1; + rhsBits = dupRHS.getActiveBits(); + rhsWords = !rhsBits ? 0 : whichWord(rhsBits - 1) + 1; + + // Allocate space for the result + enum { destWords =(RType<_AP_W1, _AP_S1>::mult_w+APINT_BITS_PER_WORD-1)/APINT_BITS_PER_WORD}; + int destw = destWords; + typename RType<_AP_W1, _AP_S1>::mult Result; + uint64_t *dest = Result.pVal; + uint64_t ext = (isNegative() ^ RHS.isNegative()) ? ~0ULL : 0; + + // Perform the long multiply + mul(dest, dupLHS.pVal, lhsWords, dupRHS.pVal, rhsWords, destWords); + + for (int i=lhsWords+rhsWords; i + INLINE typename RType<_AP_W2,_AP_S2>::div + operator / (const ap_private<_AP_W2,_AP_S2>& op) const { + ap_private lhs=ap_private(*this); + ap_private rhs=ap_private(op); + return typename RType<_AP_W2,_AP_S2>::div((_AP_S||_AP_S2)?lhs.sdiv(rhs):lhs.udiv(rhs)); + } + + template + INLINE typename RType<_AP_W2,_AP_S2>::mod + operator % (const ap_private<_AP_W2,_AP_S2>& op) const { + ap_private lhs=*this; + ap_private rhs= op; + typename RType<_AP_W2,_AP_S2>::mod res = typename RType<_AP_W2,_AP_S2>::mod(_AP_S?lhs.srem(rhs):lhs.urem(rhs)); + return res; + } + + template + INLINE ap_private + operator << (const ap_private<_AP_W2, _AP_S2>& op2) const { + uint32_t sh=op2.to_uint(); + return *this << sh; + } + + INLINE ap_private + operator << (uint32_t sh) const { + ap_private r(*this); + bool overflow=(sh>=length()); + if(overflow) + r.clear(); + else + r = ap_private(r.shl(sh)); + return r; + } + + template + INLINE ap_private + operator >> (const ap_private<_AP_W2, _AP_S2>& op2) const { + uint32_t sh = op2.to_uint(); + return *this >> sh; + } + + INLINE ap_private + operator >> (uint32_t sh) const { + ap_private r(*this); + bool overflow=(sh>=_AP_W); + bool neg_v=r.isNegative(); + if(_AP_S) { + if(overflow) + neg_v?r.set():r.clear(); + else + return r.ashr(sh); + } else { + if(overflow) + r.clear(); + else + return r.lshr(sh); + } + return r; + } + + ///Shift assign + //------------------------------------------------------------------ +#define OP_ASSIGN_AP(Sym) \ + template \ + INLINE ap_private& operator Sym##=(int op) \ + { \ + *this = operator Sym (op); \ + return *this; \ + } \ + INLINE ap_private& operator Sym##=(unsigned int op) \ + { \ + *this = operator Sym (op); \ + return *this; \ + } \ + template \ + INLINE ap_private& operator Sym##=(const ap_private<_AP_W2,_AP_S2>& op) \ + { \ + *this = operator Sym (op); \ + return *this; \ + } + OP_ASSIGN_AP(>>) + OP_ASSIGN_AP(<<) +#undef OP_ASSIGN_AP + ///Comparisons + //----------------------------------------------------------------- + bool operator==(const ap_private& RHS) const { + // Get some facts about the number of bits used in the two operands. + uint32_t n1 = getActiveBits(); + uint32_t n2 = RHS.getActiveBits(); + + // If the number of bits isn't the same, they aren't equal + if (n1 != n2) + return false; + + // If the number of bits fits in a word, we only need to compare the low word. + if (n1 <= APINT_BITS_PER_WORD) + return pVal[0] == RHS.pVal[0]; + + // Otherwise, compare everything + for (int i = whichWord(n1 - 1); i >= 0; --i) + if (pVal[i] != RHS.pVal[i]) + return false; + return true; + } + + template + INLINE bool operator == (const ap_private<_AP_W2, _AP_S2>& op) const { + enum { _AP_MAX_W = AP_MAX(_AP_W+(_AP_S||_AP_S2),_AP_W2+(_AP_S||_AP_S2))}; + ap_private<_AP_MAX_W, _AP_S|_AP_S2> lhs(*this); + ap_private<_AP_MAX_W, _AP_S|_AP_S2> rhs(op); + return lhs==rhs; + } + + bool operator==(uint64_t Val) const { + uint32_t n = getActiveBits(); + if (n <= APINT_BITS_PER_WORD) + return pVal[0] == Val; + else + return false; + } + + template + INLINE bool operator != (const ap_private<_AP_W2, _AP_S2>& op) const { + return !(*this==op); + } + + template + INLINE bool operator!=(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return !((*this) == RHS); + } + + INLINE bool operator!=(uint64_t Val) const { + return !((*this) == Val); + } + + + template + INLINE bool operator <= (const ap_private<_AP_W2,_AP_S2>& op) const { + return !(*this>op); + } + + INLINE bool operator <(const ap_private& op) const { + return _AP_S ? slt(op):ult(op); + } + + template + INLINE bool operator < (const ap_private<_AP_W2, _AP_S2>& op) const { + enum { _AP_MAX_W = AP_MAX(_AP_W+(_AP_S||_AP_S2),_AP_W2+(_AP_S||_AP_S2))}; + ap_private<_AP_MAX_W, _AP_S> lhs(*this); + ap_private<_AP_MAX_W, _AP_S2> rhs(op); + if (_AP_S == _AP_S2) + return _AP_S?lhs.slt(rhs):lhs.ult(rhs); + else + if (_AP_S) + if (_AP_W2 >= _AP_W) + return lhs.ult(rhs); + else + return lhs.slt(rhs); + else + if (_AP_W >= _AP_W2) + return lhs.ult(rhs); + else + return lhs.slt(rhs); + } + + template + INLINE bool operator >=(const ap_private<_AP_W2,_AP_S2>& op) const { + return !(*this + INLINE bool operator > (const ap_private<_AP_W2, _AP_S2>& op) const { + enum { _AP_MAX_W = AP_MAX(_AP_W+(_AP_S||_AP_S2),_AP_W2+(_AP_S||_AP_S2))}; + ap_private<_AP_MAX_W, _AP_S> lhs(*this); + ap_private<_AP_MAX_W, _AP_S2> rhs(op); + if (_AP_S == _AP_S2) + return _AP_S?lhs.sgt(rhs):lhs.ugt(rhs); + else + if (_AP_S) + if (_AP_W2 >= _AP_W) + return lhs.ugt(rhs); + else + return lhs.sgt(rhs); + else + if (_AP_W >= _AP_W2) + return lhs.ugt(rhs); + else + return lhs.sgt(rhs); + } + + ///Bit and Part Select + //-------------------------------------------------------------- + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (int Hi, int Lo) { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (int Hi, int Lo) const { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(const_cast*>(this), Hi, Lo); + } + + INLINE ap_range_ref<_AP_W,_AP_S> + range (int Hi, int Lo) const { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>((const_cast*> (this)), Hi, Lo); + } + + INLINE ap_range_ref<_AP_W,_AP_S> + range (int Hi, int Lo) { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + range (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + range (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) const { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(const_cast(this), Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) const { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + return this->range(Hi, Lo); + } + + INLINE ap_bit_ref<_AP_W,_AP_S> operator [] (uint32_t index) { + assert(index >= 0&&"Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S>( *this, index ); + } + + template + INLINE ap_bit_ref<_AP_W,_AP_S> operator [] (const ap_private<_AP_W2,_AP_S2> &index) { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S>( *this, index.to_int() ); + } + + template + INLINE bool operator [] (const ap_private<_AP_W2,_AP_S2>& index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + ap_bit_ref<_AP_W,_AP_S> br =operator [] (index); + return br.to_bool(); + } + + INLINE bool operator [](uint32_t bitPosition) const { + return (maskBit(bitPosition) & (pVal[whichWord(bitPosition)])) != 0; + } + + INLINE ap_bit_ref<_AP_W,_AP_S> bit (int index) { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S>( *this, index ); + } + + template + INLINE ap_bit_ref<_AP_W,_AP_S> bit (const ap_private<_AP_W2,_AP_S2> &index) { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W &&"Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S>( *this, index.to_int() ); + } + + INLINE bool bit (int index) const { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + ap_bit_ref<_AP_W,_AP_S> br(const_cast*>(this), index); + return br.to_bool(); + } + + template + INLINE bool bit (const ap_private<_AP_W2,_AP_S2>& index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + ap_bit_ref<_AP_W,_AP_S> br = bit(index); + return br.to_bool(); + } + + template + INLINE ap_concat_ref<_AP_W,ap_private<_AP_W, _AP_S>,_AP_W2,ap_private<_AP_W2,_AP_S2> > concat(ap_private<_AP_W2,_AP_S2>& a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_private<_AP_W2,_AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W,ap_private<_AP_W, _AP_S>,_AP_W2,ap_private<_AP_W2,_AP_S2> > concat(const ap_private<_AP_W2,_AP_S2>& a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_private<_AP_W2,_AP_S2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (ap_private<_AP_W2, _AP_S2>& a2) { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (ap_private<_AP_W2, _AP_S2>& a2) const { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(const_cast& >(*this), a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (const ap_private<_AP_W2, _AP_S2>& a2) { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(*this, const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (const ap_private<_AP_W2, _AP_S2>& a2) const { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(const_cast& >(*this), const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > + operator, (const ap_range_ref<_AP_W2, _AP_S2> &a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, + ap_range_ref<_AP_W2, _AP_S2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > + operator, (ap_range_ref<_AP_W2, _AP_S2> &a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, + ap_range_ref<_AP_W2, _AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, ap_bit_ref<_AP_W2, _AP_S2> > + operator, (const ap_bit_ref<_AP_W2, _AP_S2> &a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, + ap_bit_ref<_AP_W2, _AP_S2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, ap_bit_ref<_AP_W2, _AP_S2> > + operator, (ap_bit_ref<_AP_W2, _AP_S2> &a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, + ap_bit_ref<_AP_W2, _AP_S2> >(*this, a2); + } + + template + INLINE + ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > + operator, (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE + ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > + operator, (ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) const { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) const { + return ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, a2); + } + + INLINE ap_private<_AP_W,false> get() const { + ap_private<_AP_W,false> ret(*this); + return ret; + } + + template + INLINE void set(const ap_private<_AP_W3, false> & val) { + operator = (ap_private<_AP_W3, _AP_S>(val)); + } + + /// @} + /// @name Value Tests + /// @{ + /// This tests the high bit of this ap_private to determine if it is set. + /// @returns true if this ap_private is negative, false otherwise + /// @brief Determine sign of this ap_private. + INLINE bool isNegative() const { + //just for get rid of warnings + enum {shift = (_AP_W-APINT_BITS_PER_WORD*(_AP_N-1)-1)}; + static const uint64_t mask = 1ULL << (shift); + return _AP_S && (pVal[_AP_N-1]&mask); + } + + /// This tests the high bit of the ap_private to determine if it is unset. + /// @brief Determine if this ap_private Value is positive (not negative). + INLINE bool isPositive() const { + return !isNegative(); + } + + /// This tests if the value of this ap_private is strictly positive (> 0). + /// @returns true if this ap_private is Positive and not zero. + /// @brief Determine if this ap_private Value is strictly positive. + INLINE bool isStrictlyPositive() const { + return isPositive() && (*this) != 0; + } + + /// This checks to see if the value has all bits of the ap_private are set or not. + /// @brief Determine if all bits are set + INLINE bool isAllOnesValue() const { + return countPopulation() == _AP_W; + } + + /// This checks to see if the value of this ap_private is the maximum unsigned + /// value for the ap_private's bit width. + /// @brief Determine if this is the largest unsigned value. + INLINE bool isMaxValue() const { + return countPopulation() == _AP_W; + } + + /// This checks to see if the value of this ap_private is the maximum signed + /// value for the ap_private's bit width. + /// @brief Determine if this is the largest signed value. + INLINE bool isMaxSignedValue() const { + return BitWidth == 1 ? VAL == 0 : + !isNegative() && countPopulation() == _AP_W - 1; + } + + /// This checks to see if the value of this ap_private is the minimum unsigned + /// value for the ap_private's bit width. + /// @brief Determine if this is the smallest unsigned value. + INLINE bool isMinValue() const { + return countPopulation() == 0; + } + + /// This checks to see if the value of this ap_private is the minimum signed + /// value for the ap_private's bit width. + /// @brief Determine if this is the smallest signed value. + INLINE bool isMinSignedValue() const { + return BitWidth == 1 ? VAL == 1 : + isNegative() && countPopulation() == 1; + } + + /// This function returns a pointer to the internal storage of the ap_private. + /// This is useful for writing out the ap_private in binary form without any + /// conversions. + INLINE const uint64_t* getRawData() const { + if (isSingleWord()) + return &VAL; + return &pVal[0]; + } + + ap_private sqrt() const; + + /// @} + /// @Assignment Operators + /// @{ + /// @returns *this after assignment of RHS. + /// @brief Copy assignment operator. + INLINE ap_private& operator=(const ap_private& RHS) { + if (this != &RHS) + memcpy(pVal, RHS.pVal, _AP_N * APINT_WORD_SIZE); + return *this; + } + INLINE ap_private& operator=(const volatile ap_private& RHS) { + if (this != &RHS) + for (int i=0; i<_AP_N; ++i) + pVal[i] = RHS.pVal[i]; + return *this; + } + INLINE volatile ap_private& operator=(const ap_private& RHS) volatile { + if (this != &RHS) + for (int i=0; i<_AP_N; ++i) + pVal[i] = RHS.pVal[i]; + return *this; + } + INLINE volatile ap_private& operator=(const volatile ap_private& RHS) volatile { + if (this != &RHS) + for (int i=0; i<_AP_N; ++i) + pVal[i] = RHS.pVal[i]; + return *this; + } + + template + INLINE ap_private& operator=(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { + if (_AP_S1) + cpSextOrTrunc(RHS); + else + cpZextOrTrunc(RHS); + clearUnusedBits(); + return *this; + } + + template + INLINE ap_private& operator=(const volatile ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { + if (_AP_S1) + cpSextOrTrunc(RHS); + else + cpZextOrTrunc(RHS); + clearUnusedBits(); + return *this; + } + + template + INLINE ap_private& operator=(const ap_private<_AP_W1, _AP_S1, 1>& RHS) { + static const uint64_t that_sign_ext_mask = (_AP_W1==APINT_BITS_PER_WORD)?0:~0ULL>>(_AP_W1%APINT_BITS_PER_WORD)<<(_AP_W1%APINT_BITS_PER_WORD); + if (RHS.isNegative()) { + pVal[0] = RHS.VAL | that_sign_ext_mask; + memset(pVal+1,~0, APINT_WORD_SIZE*(_AP_N-1)); + } else { + pVal[0] = RHS.VAL; + memset(pVal+1, 0, APINT_WORD_SIZE*(_AP_N-1)); + } + clearUnusedBits(); + return *this; + } + + template + INLINE ap_private& operator=(const volatile ap_private<_AP_W1, _AP_S1, 1>& RHS) { + static const uint64_t that_sign_ext_mask = (_AP_W1==APINT_BITS_PER_WORD)?0:~0ULL>>(_AP_W1%APINT_BITS_PER_WORD)<<(_AP_W1%APINT_BITS_PER_WORD); + if (RHS.isNegative()) { + pVal[0] = RHS.VAL | that_sign_ext_mask; + memset(pVal+1,~0, APINT_WORD_SIZE*(_AP_N-1)); + } else { + pVal[0] = RHS.VAL; + memset(pVal+1, 0, APINT_WORD_SIZE*(_AP_N-1)); + } + clearUnusedBits(); + return *this; + } + + /// @} + /// @name Unary Operators + /// @{ + /// @returns a new ap_private value representing *this incremented by one + /// @brief Postfix increment operator. + INLINE const ap_private operator++(int) { + ap_private API(*this); + ++(*this); + return API; + } + + /// @returns *this incremented by one + /// @brief Prefix increment operator. + INLINE ap_private& operator++() { + add_1(pVal, pVal, _AP_N, 1); + clearUnusedBits(); + return *this; + } + + /// @returns a new ap_private representing *this decremented by one. + /// @brief Postfix decrement operator. + INLINE const ap_private operator--(int) { + ap_private API(*this); + --(*this); + return API; + } + + /// @returns *this decremented by one. + /// @brief Prefix decrement operator. + INLINE ap_private& operator--() { + sub_1(pVal, _AP_N, 1); + clearUnusedBits(); + return *this; + } + + /// Performs a bitwise complement operation on this ap_private. + /// @returns an ap_private that is the bitwise complement of *this + /// @brief Unary bitwise complement operator. + INLINE ap_private operator~() const { + ap_private Result(*this); + Result.flip(); + return Result; + } + + /// Negates *this using two's complement logic. + /// @returns An ap_private value representing the negation of *this. + /// @brief Unary negation operator + INLINE typename RType<1,false>::minus operator-() const { + return ap_private<1,false>(0) - (*this); + } + + /// Performs logical negation operation on this ap_private. + /// @returns true if *this is zero, false otherwise. + /// @brief Logical negation operator. + INLINE bool operator !() const { + for (uint32_t i = 0; i < _AP_N; ++i) + if (pVal[i]) + return false; + return true; + } + + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> And(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return this->operator&(RHS); + } + template + INLINE ap_private Or(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return this->operator|(RHS); + } + template + ap_private Xor(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return this->operator^(RHS); + } + + ap_private Mul(const ap_private& RHS) const { + ap_private Result(*this); + Result *= RHS; + return Result; + } + + ap_private Add(const ap_private& RHS) const { + ap_private Result(0); + bool carry = add(Result.pVal, this->pVal, RHS.pVal, _AP_N, _AP_N, _AP_N, _AP_S, _AP_S); + Result.clearUnusedBits(); + return Result; + } + + ap_private Sub(const ap_private& RHS) const { + ap_private Result(0); + sub(Result.pVal, this->pVal, RHS.pVal, _AP_N, _AP_N, _AP_N, _AP_S, _AP_S); + Result.clearUnusedBits(); + return Result; + } + + /// Arithmetic right-shift this ap_private by shiftAmt. + /// @brief Arithmetic right-shift function. + ap_private ashr(uint32_t shiftAmt) const { + assert(shiftAmt <= BitWidth && "Invalid shift amount, too big"); + // Handle a degenerate case + if (shiftAmt == 0) + return *this; + + // Handle single word shifts with built-in ashr + if (isSingleWord()) { + if (shiftAmt == BitWidth) + return ap_private(/*BitWidth, 0*/); // undefined + else { + uint32_t SignBit = APINT_BITS_PER_WORD - BitWidth; + return ap_private(/*BitWidth,*/ + (((int64_t(VAL) << (SignBit)) >> (SignBit)) >> (shiftAmt))); + } + } + + // If all the bits were shifted out, the result is, technically, undefined. + // We return -1 if it was negative, 0 otherwise. We check this early to avoid + // issues in the algorithm below. + if (shiftAmt == BitWidth) { + if (isNegative()) + return ap_private(-1); + else + return ap_private(0); + } + + // Create some space for the result. + ap_private Retval(0); + uint64_t * val = Retval.pVal; + + // Compute some values needed by the following shift algorithms + uint32_t wordShift = shiftAmt % APINT_BITS_PER_WORD; // bits to shift per word + uint32_t offset = shiftAmt / APINT_BITS_PER_WORD; // word offset for shift + uint32_t breakWord = _AP_N - 1 - offset; // last word affected + uint32_t bitsInWord = whichBit(BitWidth); // how many bits in last word? + if (bitsInWord == 0) + bitsInWord = APINT_BITS_PER_WORD; + + // If we are shifting whole words, just move whole words + if (wordShift == 0) { + // Move the words containing significant bits + for (uint32_t i = 0; i <= breakWord; ++i) + val[i] = pVal[i+offset]; // move whole word + + // Adjust the top significant word for sign bit fill, if negative + if (isNegative()) + if (bitsInWord < APINT_BITS_PER_WORD) + val[breakWord] |= ~0ULL << (bitsInWord); // set high bits + } else { + // Shift the low order words + for (uint32_t i = 0; i < breakWord; ++i) { + // This combines the shifted corresponding word with the low bits from + // the next word (shifted into this word's high bits). + val[i] = ((pVal[i+offset]) >> (wordShift)); + val[i] |= ((pVal[i+offset+1]) << (APINT_BITS_PER_WORD - wordShift)); + } + + // Shift the break word. In this case there are no bits from the next word + // to include in this word. + val[breakWord] = (pVal[breakWord+offset]) >> (wordShift); + + // Deal with sign extenstion in the break word, and possibly the word before + // it. + if (isNegative()) { + if (wordShift > bitsInWord) { + if (breakWord > 0) + val[breakWord-1] |= + ~0ULL << (APINT_BITS_PER_WORD - (wordShift - bitsInWord)); + val[breakWord] |= ~0ULL; + } else + val[breakWord] |= (~0ULL << (bitsInWord - wordShift)); + } + } + + // Remaining words are 0 or -1, just assign them. + uint64_t fillValue = (isNegative() ? ~0ULL : 0); + for (uint32_t i = breakWord+1; i < _AP_N; ++i) + val[i] = fillValue; + Retval.clearUnusedBits(); + return Retval; + } + + /// Logical right-shift this ap_private by shiftAmt. + /// @brief Logical right-shift function. + ap_private lshr(uint32_t shiftAmt) const { + if (isSingleWord()) { + if (shiftAmt == BitWidth) + return ap_private(0); + else + return ap_private((this->VAL) >> (shiftAmt)); + } + + // If all the bits were shifted out, the result is 0. This avoids issues + // with shifting by the size of the integer type, which produces undefined + // results. We define these "undefined results" to always be 0. + if (shiftAmt == BitWidth) + return ap_private(0); + + // If none of the bits are shifted out, the result is *this. This avoids + // issues with shifting byt he size of the integer type, which produces + // undefined results in the code below. This is also an optimization. + if (shiftAmt == 0) + return *this; + + // Create some space for the result. + ap_private Retval(0); + uint64_t * val = Retval.pVal; + + // If we are shifting less than a word, compute the shift with a simple carry + if (shiftAmt < APINT_BITS_PER_WORD) { + uint64_t carry = 0; + for (int i = _AP_N-1; i >= 0; --i) { + val[i] = ((pVal[i]) >> (shiftAmt)) | carry; + carry = (pVal[i]) << (APINT_BITS_PER_WORD - shiftAmt); + } + Retval.clearUnusedBits(); + return Retval; + } + + // Compute some values needed by the remaining shift algorithms + uint32_t wordShift = shiftAmt % APINT_BITS_PER_WORD; + uint32_t offset = shiftAmt / APINT_BITS_PER_WORD; + + // If we are shifting whole words, just move whole words + if (wordShift == 0) { + for (uint32_t i = 0; i < _AP_N - offset; ++i) + val[i] = pVal[i+offset]; + for (uint32_t i = _AP_N-offset; i < _AP_N; i++) + val[i] = 0; + Retval.clearUnusedBits(); + return Retval; + } + + // Shift the low order words + uint32_t breakWord = _AP_N - offset -1; + for (uint32_t i = 0; i < breakWord; ++i) + val[i] = ((pVal[i+offset]) >> (wordShift)) | + ((pVal[i+offset+1]) << (APINT_BITS_PER_WORD - wordShift)); + // Shift the break word. + val[breakWord] = (pVal[breakWord+offset]) >> (wordShift); + + // Remaining words are 0 + for (uint32_t i = breakWord+1; i < _AP_N; ++i) + val[i] = 0; + Retval.clearUnusedBits(); + return Retval; + } + + /// Left-shift this ap_private by shiftAmt. + /// @brief Left-shift function. + ap_private shl(uint32_t shiftAmt) const { + assert(shiftAmt <= BitWidth && "Invalid shift amount, too big"); + if (isSingleWord()) { + if (shiftAmt == BitWidth) + return ap_private(0); // avoid undefined shift results + return ap_private((VAL) << (shiftAmt)); + } + + // If all the bits were shifted out, the result is 0. This avoids issues + // with shifting by the size of the integer type, which produces undefined + // results. We define these "undefined results" to always be 0. + if (shiftAmt == BitWidth) + return ap_private(0); + + // If none of the bits are shifted out, the result is *this. This avoids a + // lshr by the words size in the loop below which can produce incorrect + // results. It also avoids the expensive computation below for a common case. + if (shiftAmt == 0) + return *this; + + // Create some space for the result. + ap_private Retval(0); + uint64_t* val = Retval.pVal; + // If we are shifting less than a word, do it the easy way + if (shiftAmt < APINT_BITS_PER_WORD) { + uint64_t carry = 0; + for (uint32_t i = 0; i < _AP_N; i++) { + val[i] = ((pVal[i]) << (shiftAmt)) | carry; + carry = (pVal[i]) >> (APINT_BITS_PER_WORD - shiftAmt); + } + Retval.clearUnusedBits(); + return Retval; + } + + // Compute some values needed by the remaining shift algorithms + uint32_t wordShift = shiftAmt % APINT_BITS_PER_WORD; + uint32_t offset = shiftAmt / APINT_BITS_PER_WORD; + + // If we are shifting whole words, just move whole words + if (wordShift == 0) { + for (uint32_t i = 0; i < offset; i++) + val[i] = 0; + for (uint32_t i = offset; i < _AP_N; i++) + val[i] = pVal[i-offset]; + Retval.clearUnusedBits(); + return Retval; + } + + // Copy whole words from this to Result. + uint32_t i = _AP_N - 1; + for (; i > offset; --i) + val[i] = (pVal[i-offset]) << (wordShift) | + (pVal[i-offset-1]) >> (APINT_BITS_PER_WORD - wordShift); + val[offset] = (pVal[0]) << (wordShift); + for (i = 0; i < offset; ++i) + val[i] = 0; + Retval.clearUnusedBits(); + return Retval; + } + + INLINE ap_private rotl(uint32_t rotateAmt) const { + if (rotateAmt == 0) + return *this; + // Don't get too fancy, just use existing shift/or facilities + ap_private hi(*this); + ap_private lo(*this); + hi.shl(rotateAmt); + lo.lshr(BitWidth - rotateAmt); + return hi | lo; + } + + INLINE ap_private rotr(uint32_t rotateAmt) const { + if (rotateAmt == 0) + return *this; + // Don't get too fancy, just use existing shift/or facilities + ap_private hi(*this); + ap_private lo(*this); + lo.lshr(rotateAmt); + hi.shl(BitWidth - rotateAmt); + return hi | lo; + } + + /// Perform an unsigned divide operation on this ap_private by RHS. Both this and + /// RHS are treated as unsigned quantities for purposes of this division. + /// @returns a new ap_private value containing the division result + /// @brief Unsigned division operation. + ap_private udiv(const ap_private& RHS) const { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + + // First, deal with the easy case + if (isSingleWord()) { + assert(RHS.VAL != 0 && "Divide by zero?"); + return ap_private(VAL / RHS.VAL); + } + + // Get some facts about the LHS and RHS number of bits and words + uint32_t rhsBits = RHS.getActiveBits(); + uint32_t rhsWords = !rhsBits ? 0 : (whichWord(rhsBits - 1) + 1); + assert(rhsWords && "Divided by zero???"); + uint32_t lhsBits = this->getActiveBits(); + uint32_t lhsWords = !lhsBits ? 0 : (whichWord(lhsBits - 1) + 1); + + // Deal with some degenerate cases + if (!lhsWords) + // 0 / X ===> 0 + return ap_private(0); + else if (lhsWords < rhsWords || this->ult(RHS)) { + // X / Y ===> 0, iff X < Y + return ap_private(0); + } else if (*this == RHS) { + // X / X ===> 1 + return ap_private(1); + } else if (lhsWords == 1 && rhsWords == 1) { + // All high words are zero, just use native divide + return ap_private(this->pVal[0] / RHS.pVal[0]); + } + + // We have to compute it the hard way. Invoke the Knuth divide algorithm. + ap_private Quotient(0); // to hold result. + divide(*this, lhsWords, RHS, rhsWords, &Quotient, (ap_private*)0); + return Quotient; + } + + /// Signed divide this ap_private by ap_private RHS. + /// @brief Signed division function for ap_private. + INLINE ap_private sdiv(const ap_private& RHS) const { + if (isNegative()) + if (RHS.isNegative()) + return (-(*this)).udiv(-RHS); + else + return -((-(*this)).udiv(RHS)); + else if (RHS.isNegative()) + return -(this->udiv(-RHS)); + return this->udiv(RHS); + } + + /// Perform an unsigned remainder operation on this ap_private with RHS being the + /// divisor. Both this and RHS are treated as unsigned quantities for purposes + /// of this operation. Note that this is a true remainder operation and not + /// a modulo operation because the sign follows the sign of the dividend + /// which is *this. + /// @returns a new ap_private value containing the remainder result + /// @brief Unsigned remainder operation. + ap_private urem(const ap_private& RHS) const { + if (isSingleWord()) { + assert(RHS.VAL != 0 && "Remainder by zero?"); + return ap_private(VAL % RHS.VAL); + } + + // Get some facts about the LHS + uint32_t lhsBits = getActiveBits(); + uint32_t lhsWords = !lhsBits ? 0 : (whichWord(lhsBits - 1) + 1); + + // Get some facts about the RHS + uint32_t rhsBits = RHS.getActiveBits(); + uint32_t rhsWords = !rhsBits ? 0 : (whichWord(rhsBits - 1) + 1); + assert(rhsWords && "Performing remainder operation by zero ???"); + + // Check the degenerate cases + if (lhsWords == 0) { + // 0 % Y ===> 0 + return ap_private(0); + } else if (lhsWords < rhsWords || this->ult(RHS)) { + // X % Y ===> X, iff X < Y + return *this; + } else if (*this == RHS) { + // X % X == 0; + return ap_private(0); + } else if (lhsWords == 1) { + // All high words are zero, just use native remainder + return ap_private(pVal[0] % RHS.pVal[0]); + } + + // We have to compute it the hard way. Invoke the Knuth divide algorithm. + ap_private Remainder(0); + divide(*this, lhsWords, RHS, rhsWords, (ap_private*)(0), &Remainder); + return Remainder; + } + + ap_private urem(uint64_t RHS) const { + // Get some facts about the LHS + uint32_t lhsBits = getActiveBits(); + uint32_t lhsWords = !lhsBits ? 0 : (whichWord(lhsBits - 1) + 1); + // Get some facts about the RHS + uint32_t rhsBits = 64 - CountLeadingZeros_64(RHS); // RHS.getActiveBits(); + uint32_t rhsWords = 1;//!rhsBits ? 0 : (ap_private<_AP_W, _AP_S, _AP_N>::whichWord(rhsBits - 1) + 1); + assert(rhsWords && "Performing remainder operation by zero ???"); + // Check the degenerate cases + if (lhsWords == 0) { + // 0 % Y ===> 0 + return ap_private(0); + } else if (lhsWords < rhsWords || this->ult(RHS)) { + // X % Y ===> X, iff X < Y + return *this; + } else if (*this == RHS) { + // X % X == 0; + return ap_private(0); + } else if (lhsWords == 1) { + // All high words are zero, just use native remainder + return ap_private(pVal[0] % RHS); + } + + // We have to compute it the hard way. Invoke the Knuth divide algorithm. + ap_private Remainder(0); + divide(*this, lhsWords, RHS, (ap_private*)(0), &Remainder); + return Remainder; + } + + /// Signed remainder operation on ap_private. + /// @brief Function for signed remainder operation. + INLINE ap_private srem(const ap_private& RHS) const { + if (isNegative()) { + ap_private lhs = -(*this); + if (RHS.isNegative()) { + ap_private rhs = -RHS; + return -(lhs.urem(rhs)); + } else + return -(lhs.urem(RHS)); + } else if (RHS.isNegative()) { + ap_private rhs = -RHS; + return this->urem(rhs); + } + return this->urem(RHS); + } + + /// Signed remainder operation on ap_private. + /// @brief Function for signed remainder operation. + INLINE ap_private srem(int64_t RHS) const { + if (isNegative()) + if (RHS<0) + return -((-(*this)).urem(-RHS)); + else + return -((-(*this)).urem(RHS)); + else if (RHS<0) + return this->urem(-RHS); + return this->urem(RHS); + } + + /// Sometimes it is convenient to divide two ap_private values and obtain both + /// the quotient and remainder. This function does both operations in the + /// same computation making it a little more efficient. + /// @brief Dual division/remainder interface. + static void udivrem(const ap_private& LHS, const ap_private& RHS, ap_private &Quotient, ap_private& Remainder) { + // Get some size facts about the dividend and divisor + uint32_t lhsBits = LHS.getActiveBits(); + uint32_t lhsWords = !lhsBits ? 0 : (ap_private::whichWord(lhsBits - 1) + 1); + uint32_t rhsBits = RHS.getActiveBits(); + uint32_t rhsWords = !rhsBits ? 0 : (ap_private::whichWord(rhsBits - 1) + 1); + + // Check the degenerate cases + if (lhsWords == 0) { + Quotient = 0; // 0 / Y ===> 0 + Remainder = 0; // 0 % Y ===> 0 + return; + } + + if (lhsWords < rhsWords || LHS.ult(RHS)) { + Quotient = 0; // X / Y ===> 0, iff X < Y + Remainder = LHS; // X % Y ===> X, iff X < Y + return; + } + + if (LHS == RHS) { + Quotient = 1; // X / X ===> 1 + Remainder = 0; // X % X ===> 0; + return; + } + + if (lhsWords == 1 && rhsWords == 1) { + // There is only one word to consider so use the native versions. + if (LHS.isSingleWord()) { + Quotient = ap_private(LHS.VAL / RHS.VAL); + Remainder = ap_private(LHS.VAL % RHS.VAL); + } else { + Quotient = ap_private(LHS.pVal[0] / RHS.pVal[0]); + Remainder = ap_private(LHS.pVal[0] % RHS.pVal[0]); + } + return; + } + + // Okay, lets do it the long way + divide(LHS, lhsWords, RHS, rhsWords, &Quotient, &Remainder); + } + + static void sdivrem(const ap_private &LHS, const ap_private &RHS, + ap_private &Quotient, ap_private &Remainder) { + if (LHS.isNegative()) { + if (RHS.isNegative()) + ap_private::udivrem(-LHS, -RHS, Quotient, Remainder); + else + ap_private::udivrem(-LHS, RHS, Quotient, Remainder); + Quotient = -Quotient; + Remainder = -Remainder; + } else if (RHS.isNegative()) { + ap_private::udivrem(LHS, -RHS, Quotient, Remainder); + Quotient = -Quotient; + } else { + ap_private::udivrem(LHS, RHS, Quotient, Remainder); + } + } + + /// Compares this ap_private with RHS for the validity of the equality + /// relationship. + /// @returns true if *this == Val + /// @brief Equality comparison. + template + INLINE bool eq(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return (*this) == RHS; + } + + /// Compares this ap_private with RHS for the validity of the inequality + /// relationship. + /// @returns true if *this != Val + /// @brief Inequality comparison + template + INLINE bool ne(const ap_private<_AP_W, _AP_S1, _AP_N> &RHS) const { + return !((*this) == RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// the validity of the less-than relationship. + /// @returns true if *this < RHS when both are considered unsigned. + /// @brief Unsigned less than comparison + template + INLINE bool ult(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + // Get active bit length of both operands + uint32_t n1 = getActiveBits(); + uint32_t n2 = RHS.getActiveBits(); + + // If magnitude of LHS is less than RHS, return true. + if (n1 < n2) + return true; + + // If magnitude of RHS is greather than LHS, return false. + if (n2 < n1) + return false; + + // If they bot fit in a word, just compare the low order word + if (n1 <= APINT_BITS_PER_WORD && n2 <= APINT_BITS_PER_WORD) + return pVal[0] < RHS.pVal[0]; + + // Otherwise, compare all words + uint32_t topWord = whichWord(AESL_std::max(n1,n2)-1); + for (int i = topWord; i >= 0; --i) { + if (pVal[i] > RHS.pVal[i]) + return false; + if (pVal[i] < RHS.pVal[i]) + return true; + } + return false; + } + + INLINE bool ult(uint64_t RHS) const { + // Get active bit length of both operands + uint32_t n1 = getActiveBits(); + uint32_t n2 = 64 - CountLeadingZeros_64(RHS); //RHS.getActiveBits(); + + // If magnitude of LHS is less than RHS, return true. + if (n1 < n2) + return true; + + // If magnitude of RHS is greather than LHS, return false. + if (n2 < n1) + return false; + + // If they bot fit in a word, just compare the low order word + if (n1 <= APINT_BITS_PER_WORD && n2 <= APINT_BITS_PER_WORD) + return pVal[0] < RHS; + assert(0); + } + + template + INLINE bool slt(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + ap_private lhs(*this); + ap_private<_AP_W, _AP_S1, _AP_N> rhs(RHS); + bool lhsNeg = isNegative(); + bool rhsNeg = rhs.isNegative(); + if (lhsNeg) { + // Sign bit is set so perform two's complement to make it positive + lhs.flip(); + lhs++; + } + if (rhsNeg) { + // Sign bit is set so perform two's complement to make it positive + rhs.flip(); + rhs++; + } + + // Now we have unsigned values to compare so do the comparison if necessary + // based on the negativeness of the values. + if (lhsNeg) + if (rhsNeg) + return lhs.ugt(rhs); + else + return true; + else if (rhsNeg) + return false; + else + return lhs.ult(rhs); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// validity of the less-or-equal relationship. + /// @returns true if *this <= RHS when both are considered unsigned. + /// @brief Unsigned less or equal comparison + template + INLINE bool ule(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return ult(RHS) || eq(RHS); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the less-or-equal relationship. + /// @returns true if *this <= RHS when both are considered signed. + /// @brief Signed less or equal comparison + template + INLINE bool sle(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return slt(RHS) || eq(RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// the validity of the greater-than relationship. + /// @returns true if *this > RHS when both are considered unsigned. + /// @brief Unsigned greather than comparison + template + INLINE bool ugt(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return !ult(RHS) && !eq(RHS); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// the validity of the greater-than relationship. + /// @returns true if *this > RHS when both are considered signed. + /// @brief Signed greather than comparison + template + INLINE bool sgt(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return !slt(RHS) && !eq(RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// validity of the greater-or-equal relationship. + /// @returns true if *this >= RHS when both are considered unsigned. + /// @brief Unsigned greater or equal comparison + template + INLINE bool uge(const ap_private<_AP_W, _AP_S, _AP_N>& RHS) const { + return !ult(RHS); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the greater-or-equal relationship. + /// @returns true if *this >= RHS when both are considered signed. + /// @brief Signed greather or equal comparison + template + INLINE bool sge(const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) const { + return !slt(RHS); + } + + template + void cpTrunc(const ap_private<_AP_W1, _AP_S1, _AP_N1>& that) { + assert(_AP_W1 > BitWidth && "Invalid ap_private Truncate request"); + assert(_AP_W1 >= MIN_INT_BITS && "Can't truncate to 0 bits"); + memcpy(pVal, that.pVal, _AP_N*APINT_WORD_SIZE); + } + + // Sign extend to a new width. + template + void cpSext(const ap_private<_AP_W1, _AP_S1, _AP_N1>& that) { + assert(_AP_W1 < BitWidth && "Invalid ap_private SignExtend request"); + assert(_AP_W1 <= MAX_INT_BITS && "Too many bits"); + // If the sign bit isn't set, this is the same as zext. + if (!that.isNegative()) { + cpZext(that); + return; + } + + // The sign bit is set. First, get some facts + enum { wordBits = _AP_W1 % APINT_BITS_PER_WORD}; + + // Mask the high order word appropriately + if (_AP_N1 == _AP_N) { + enum { newWordBits = _AP_W % APINT_BITS_PER_WORD}; + // The extension is contained to the wordsBefore-1th word. + static const uint64_t mask = wordBits?(~0ULL<<(wordBits)):0ULL; + if (_AP_N1 == 1) { + assert(0); + } else { + for (uint32_t i = 0; i < _AP_N1; ++i) + pVal[i] = that.pVal[i]; + pVal[_AP_N1-1] |= mask; + return; + } + } + + if (_AP_N1 == 1) { + assert(0);// newVal[0] = VAL | mask; + } else { + enum { newWordBits = _AP_W % APINT_BITS_PER_WORD}; + // The extension is contained to the wordsBefore-1th word. + static const uint64_t mask = wordBits?(~0ULL<<(wordBits)):0ULL; + for (uint32_t i = 0; i < _AP_N1; ++i) + pVal[i] = that.pVal[i]; + pVal[_AP_N1-1] |= mask; + } + for (uint32_t i=_AP_N1; i < _AP_N-1; i++) + pVal[i] = ~0ULL; + pVal[_AP_N-1] = ~0ULL; + clearUnusedBits(); + return; + } + + // Zero extend to a new width. + template + void cpZext(const ap_private<_AP_W1, _AP_S1, _AP_N1>& that) { + assert(_AP_W1 < BitWidth && "Invalid ap_private ZeroExtend request"); + assert(_AP_W1 <= MAX_INT_BITS && "Too many bits"); + uint32_t wordsAfter = _AP_N; + if (wordsAfter==1) { + assert(0); // return ap_private<_AP_W1, _AP_S, _AP_N1> (_AP_W1, VAL, _AP_S); + } else { + if (_AP_N1 == 1) { + assert(0); + // newVal[0] = VAL; + } else { + uint32_t i = 0; + for (; i < _AP_N1; ++i) + pVal[i] = that.pVal[i]; + for (; i < _AP_N; ++i) + pVal[i] = 0; + } + } + clearUnusedBits(); + } + + template + void cpZextOrTrunc(const ap_private<_AP_W1, _AP_S1, _AP_N1>& that) { + if (BitWidth > _AP_W1) + cpZext(that); + else if (BitWidth < _AP_W1) + cpTrunc(that); + else { + for (int i=0; i<_AP_N1; ++i) + pVal[i]=that.pVal[i]; + clearUnusedBits(); + } + } + + template + void cpSextOrTrunc(const ap_private<_AP_W1, _AP_S1, _AP_N1>& that) { + if (BitWidth > _AP_W1) + cpSext(that); + else if (BitWidth < _AP_W1) + cpTrunc(that); + else { + for (int i=0; i<_AP_N1; ++i) + pVal[i] = that.pVal[i]; + clearUnusedBits(); + } + } + + /// @name Value Characterization Functions + /// @{ + + /// @returns the total number of bits. + INLINE uint32_t getBitWidth() const { + return BitWidth; + } + + /// Here one word's bitwidth equals to that of uint64_t. + /// @returns the number of words to hold the integer value of this ap_private. + /// @brief Get the number of words. + INLINE uint32_t getNumWords() const { + return (BitWidth + APINT_BITS_PER_WORD - 1) / APINT_BITS_PER_WORD; + } + + /// This function returns the number of active bits which is defined as the + /// bit width minus the number of leading zeros. This is used in several + /// computations to see how "wide" the value is. + /// @brief Compute the number of active bits in the value + INLINE uint32_t getActiveBits() const { + uint32_t bits=BitWidth - countLeadingZeros(); + return bits?bits:1; + } + + + /// This method attempts to return the value of this ap_private as a zero extended + /// uint64_t. The bitwidth must be <= 64 or the value must fit within a + /// uint64_t. Otherwise an assertion will result. + /// @brief Get zero extended value + INLINE uint64_t getZExtValue() const { + assert(getActiveBits() <= 64 && "Too many bits for uint64_t"); + return *pVal; + } + + /// This method attempts to return the value of this ap_private as a sign extended + /// int64_t. The bit width must be <= 64 or the value must fit within an + /// int64_t. Otherwise an assertion will result. + /// @brief Get sign extended value + INLINE int64_t getSExtValue() const { + assert(getActiveBits() <= 64 && "Too many bits for int64_t"); + return int64_t(pVal[0]); + } + + /// This method determines how many bits are required to hold the ap_private + /// equivalent of the string given by \p str of length \p slen. + /// @brief Get bits required for string value. + static uint32_t getBitsNeeded(const char* str, uint32_t slen, uint8_t radix); + + /// countLeadingZeros - This function is an ap_private version of the + /// countLeadingZeros_{32,64} functions in MathExtras.h. It counts the number + /// of zeros from the most significant bit to the first one bit. + /// @returns BitWidth if the value is zero. + /// @returns the number of zeros from the most significant bit to the first + /// one bits. + INLINE uint32_t countLeadingZeros() const ; + + /// countLeadingOnes - This function counts the number of contiguous 1 bits + /// in the high order bits. The count stops when the first 0 bit is reached. + /// @returns 0 if the high order bit is not set + /// @returns the number of 1 bits from the most significant to the least + /// @brief Count the number of leading one bits. + INLINE uint32_t countLeadingOnes() const ; + + /// countTrailingZeros - This function is an ap_private version of the + /// countTrailingZoers_{32,64} functions in MathExtras.h. It counts + /// the number of zeros from the least significant bit to the first set bit. + /// @returns BitWidth if the value is zero. + /// @returns the number of zeros from the least significant bit to the first + /// one bit. + /// @brief Count the number of trailing zero bits. + INLINE uint32_t countTrailingZeros() const ; + + /// countPopulation - This function is an ap_private version of the + /// countPopulation_{32,64} functions in MathExtras.h. It counts the number + /// of 1 bits in the ap_private value. + /// @returns 0 if the value is zero. + /// @returns the number of set bits. + /// @brief Count the number of bits set. + INLINE uint32_t countPopulation() const { + uint32_t Count = 0; + for (uint32_t i = 0; i<_AP_N-1 ; ++i) + Count += CountPopulation_64(pVal[i]); + Count += CountPopulation_64(pVal[_AP_N-1]&mask); + return Count; + } + + /// @} + /// @name Conversion Functions + /// @{ + + /// This is used internally to convert an ap_private to a string. + /// @brief Converts an ap_private to a std::string + INLINE std::string toString(uint8_t radix, bool wantSigned) const + ; + + /// Considers the ap_private to be unsigned and converts it into a string in the + /// radix given. The radix can be 2, 8, 10 or 16. + /// @returns a character interpretation of the ap_private + /// @brief Convert unsigned ap_private to string representation. + INLINE std::string toStringUnsigned(uint8_t radix = 10) const { + return toString(radix, false); + } + + /// Considers the ap_private to be unsigned and converts it into a string in the + /// radix given. The radix can be 2, 8, 10 or 16. + /// @returns a character interpretation of the ap_private + /// @brief Convert unsigned ap_private to string representation. + INLINE std::string toStringSigned(uint8_t radix = 10) const { + return toString(radix, true); + } + + /// @returns a byte-swapped representation of this ap_private Value. + INLINE ap_private byteSwap() const ; + + /// @brief Converts this ap_private to a double value. + INLINE double roundToDouble(bool isSigned) const ; + + /// @brief Converts this unsigned ap_private to a double value. + INLINE double roundToDouble() const { + return roundToDouble(false); + } + + /// @brief Converts this signed ap_private to a double value. + INLINE double signedRoundToDouble() const { + return roundToDouble(true); + } + + /// The conversion does not do a translation from integer to double, it just + /// re-interprets the bits as a double. Note that it is valid to do this on + /// any bit width. Exactly 64 bits will be translated. + /// @brief Converts ap_private bits to a double + INLINE double bitsToDouble() const { + union { + uint64_t __I; + double __D; + } __T; + __T.__I = pVal[0]; + return __T.__D; + } + + /// The conversion does not do a translation from integer to float, it just + /// re-interprets the bits as a float. Note that it is valid to do this on + /// any bit width. Exactly 32 bits will be translated. + /// @brief Converts ap_private bits to a double + INLINE float bitsToFloat() const { + union { + uint32_t __I; + float __F; + } __T; + __T.__I = uint32_t(pVal[0]); + return __T.__F; + } + + /// The conversion does not do a translation from double to integer, it just + /// re-interprets the bits of the double. Note that it is valid to do this on + /// any bit width but bits from V may get truncated. + /// @brief Converts a double to ap_private bits. + INLINE ap_private& doubleToBits(double __V) { + union { + uint64_t __I; + double __D; + } __T; + __T.__D = __V; + pVal[0] = __T.__I; + return *this; + } + + /// The conversion does not do a translation from float to integer, it just + /// re-interprets the bits of the float. Note that it is valid to do this on + /// any bit width but bits from V may get truncated. + /// @brief Converts a float to ap_private bits. + INLINE ap_private& floatToBits(float __V) { + union { + uint32_t __I; + float __F; + } __T; + __T.__F = __V; + pVal[0] = __T.__I; + } + + //Reduce operation + //----------------------------------------------------------- + INLINE bool and_reduce() const { + return isMaxValue(); + } + + INLINE bool nand_reduce() const { + return isMinValue(); + } + + INLINE bool or_reduce() const { + return (bool)countPopulation(); + } + + INLINE bool nor_reduce() const { + return countPopulation()==0; + } + + INLINE bool xor_reduce() const { + unsigned int i=countPopulation(); + return (i%2)?true:false; + } + + INLINE bool xnor_reduce() const { + unsigned int i=countPopulation(); + return (i%2)?false:true; + } + INLINE std::string to_string(uint8_t radix=16, bool sign=false) const { + return toString(radix, radix==10?_AP_S:sign); + } +}; + +template +INLINE bool operator==(uint64_t V1, const ap_private<_AP_W, _AP_S, _AP_N>& V2) { + return V2 == V1; +} + +template +INLINE bool operator!=(uint64_t V1, const ap_private<_AP_W, _AP_S, _AP_N>& V2) { + return V2 != V1; +} + +namespace ap_private_ops { + enum {APINT_BITS_PER_WORD=64}; + /// @brief Determine the smaller of two ap_privates considered to be signed. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> smin(const ap_private<_AP_W, _AP_S, _AP_N> &LHS, const ap_private<_AP_W, _AP_S1, _AP_N> &RHS) { + return LHS.slt(RHS) ? LHS : RHS; + } + + /// @brief Determine the larger of two ap_privates considered to be signed. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> smax(const ap_private<_AP_W, _AP_S, _AP_N> &LHS, const ap_private<_AP_W, _AP_S1, _AP_N> &RHS) { + return LHS.sgt(RHS) ? LHS : RHS; + } + + /// @brief Determine the smaller of two ap_privates considered to be signed. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> umin(const ap_private<_AP_W, _AP_S, _AP_N> &LHS, const ap_private<_AP_W, _AP_S1, _AP_N> &RHS) { + return LHS.ult(RHS) ? LHS : RHS; + } + + /// @brief Determine the larger of two ap_privates considered to be unsigned. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> umax(const ap_private<_AP_W, _AP_S, _AP_N> &LHS, const ap_private<_AP_W, _AP_S1, _AP_N> &RHS) { + return LHS.ugt(RHS) ? LHS : RHS; + } + + /// @brief Check if the specified ap_private has a N-bits integer value. + template + INLINE bool isIntN(uint32_t __N, const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.isIntN(__N); + } + + /// @returns true if the argument ap_private value is a sequence of ones + /// starting at the least significant bit with the remainder zero. + template + INLINE bool isMask(uint32_t numBits, const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.getBoolValue() && ((APIVal + ap_private<_AP_W, _AP_S, _AP_N>(numBits,1)) & APIVal) == 0; + } + + /// @returns true if the argument ap_private value contains a sequence of ones + /// with the remainder zero. + template + INLINE bool isShiftedMask(uint32_t numBits, const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return isMask(numBits, (APIVal - ap_private<_AP_W, _AP_S, _AP_N>(numBits,1)) | APIVal); + } + + /// @returns a byte-swapped representation of the specified ap_private Value. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> byteSwap(const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.byteSwap(); + } + + /// @returns the floor log base 2 of the specified ap_private value. + template INLINE uint32_t logBase2(const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.logBase2(); + } + + /// GreatestCommonDivisor - This function returns the greatest common + /// divisor of the two ap_private values using Enclid's algorithm. + /// @returns the greatest common divisor of Val1 and Val2 + /// @brief Compute GCD of two ap_private values. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> GreatestCommonDivisor(const ap_private<_AP_W, _AP_S, _AP_N>& Val1, const ap_private<_AP_W, _AP_S, _AP_N>& Val2) + ; + + /// Treats the ap_private as an unsigned value for conversion purposes. + /// @brief Converts the given ap_private to a double value. + template INLINE double Roundap_privateToDouble(const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.roundToDouble(); + } + + /// Treats the ap_private as a signed value for conversion purposes. + /// @brief Converts the given ap_private to a double value. + template INLINE double RoundSignedap_privateToDouble(const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.signedRoundToDouble(); + } + + /// @brief Converts the given ap_private to a float vlalue. + template INLINE float Roundap_privateToFloat(const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return float(Roundap_privateToDouble(APIVal)); + } + + /// Treast the ap_private as a signed value for conversion purposes. + /// @brief Converts the given ap_private to a float value. + template INLINE float RoundSignedap_privateToFloat(const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return float(APIVal.signedRoundToDouble()); + } + + /// RoundDoubleToap_private - This function convert a double value to an ap_private value. + /// @brief Converts the given double value into a ap_private. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> RoundDoubleToap_private(double Double, uint32_t width) ; + + /// RoundFloatToap_private - Converts a float value into an ap_private value. + /// @brief Converts a float value into a ap_private. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> RoundFloatToap_private(float Float, uint32_t width) { + return RoundDoubleToap_private<_AP_W, _AP_S, _AP_N>(double(Float), width); + } + + /// Arithmetic right-shift the ap_private by shiftAmt. + /// @brief Arithmetic right-shift function. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> ashr(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, uint32_t shiftAmt) { + return LHS.ashr(shiftAmt); + } + + /// Logical right-shift the ap_private by shiftAmt. + /// @brief Logical right-shift function. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> lshr(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, uint32_t shiftAmt) { + return LHS.lshr(shiftAmt); + } + + /// Left-shift the ap_private by shiftAmt. + /// @brief Left-shift function. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> shl(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, uint32_t shiftAmt) { + return LHS.shl(shiftAmt); + } + + /// Signed divide ap_private LHS by ap_private RHS. + /// @brief Signed division function for ap_private. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> sdiv(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS.sdiv(RHS); + } + + /// Unsigned divide ap_private LHS by ap_private RHS. + /// @brief Unsigned division function for ap_private. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> udiv(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS.udiv(RHS); + } + + /// Signed remainder operation on ap_private. + /// @brief Function for signed remainder operation. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> srem(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS.srem(RHS); + } + + /// Unsigned remainder operation on ap_private. + /// @brief Function for unsigned remainder operation. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> urem(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS.urem(RHS); + } + + /// Performs multiplication on ap_private values. + /// @brief Function for multiplication operation. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> mul(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS * RHS; + } + + /// Performs addition on ap_private values. + /// @brief Function for addition operation. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> add(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS + RHS; + } + + /// Performs subtraction on ap_private values. + /// @brief Function for subtraction operation. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> sub(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS - RHS; + } + + /// Performs bitwise AND operation on ap_private LHS and + /// ap_private RHS. + /// @brief Bitwise AND function for ap_private. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> And(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS & RHS; + } + + /// Performs bitwise OR operation on ap_private LHS and ap_private RHS. + /// @brief Bitwise OR function for ap_private. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> Or(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS | RHS; + } + + /// Performs bitwise XOR operation on ap_private. + /// @brief Bitwise XOR function for ap_private. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1, _AP_N> Xor(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, const ap_private<_AP_W, _AP_S1, _AP_N>& RHS) { + return LHS ^ RHS; + } + + /// Performs a bitwise complement operation on ap_private. + /// @brief Bitwise complement function. + template INLINE ap_private<_AP_W, _AP_S, _AP_N> Not(const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return ~APIVal; + } + + template void clearUnusedBits(uint64_t& msw) { + // Compute how many bits are used in the final word + // uint32_t wordBits = APIVal.getBitWidth() & 0x3f; + if (wordBits == 0) + // If all bits are used, we want to leave the value alone. This also + // avoids the undefined behavior of >> when the shfit is the same size as + // the word size (64). + return; + + // Mask out the hight bits. + uint64_t mask = ~uint64_t(0ULL) >> (64 /*ap_private::APINT_BITS_PER_WORD */- wordBits); + msw &= mask; + } + template <> INLINE void clearUnusedBits<1>(uint64_t& msw) { + uint64_t mask = ~uint64_t(0ULL) >> (64 /*ap_private::APINT_BITS_PER_WORD */- 1); + msw &= mask; + } + template void clearUnusedBits(int64_t& msw) { + // Compute how many bits are used in the final word + // uint32_t wordBits = APIVal.getBitWidth() & 0x3f; + if (wordBits == 0) + // If all bits are used, we want to leave the value alone. This also + // avoids the undefined behavior of >> when the shfit is the same size as + // the word size (64). + return; + + // Mask out the hight bits. + uint64_t mask = ~uint64_t(0ULL) >> (64 /*ap_private::APINT_BITS_PER_WORD */- wordBits); + msw &= mask; + } + template <> INLINE void clearUnusedBits<1>(int64_t& msw) { + uint64_t mask = ~uint64_t(0ULL) >> (64 /*ap_private::APINT_BITS_PER_WORD */- 1); + msw &= mask; + } + // template + template + INLINE ap_private<_AP_W, _AP_S> ashr(const ap_private<_AP_W, _AP_S>& a) { + return ashr(a, shiftAmt); + } + + template + INLINE ap_private<_AP_W, _AP_S> lshr(const ap_private<_AP_W, _AP_S>& a) { + return lshr(a, shiftAmt); + } + + template + INLINE ap_private<_AP_W, true> ashr(const ap_private<_AP_W, true, 1>& a) { + enum {APINT_BITS_PER_WORD=64, excess_bits=APINT_BITS_PER_WORD-_AP_W}; + static const uint64_t sign_bit = (1ULL<<(_AP_W-1)); + static const uint64_t sign_ext_mask = (_AP_W-shiftAmt>0)?~0ULL<<(APINT_BITS_PER_WORD-_AP_W+shiftAmt):~0ULL; + return ap_private<_AP_W, true>((((int64_t)a.VAL) >> (shiftAmt)) | (a.VAL & sign_bit? sign_ext_mask : 0ULL)); + } + + template + INLINE ap_private<_AP_W, false> ashr(const ap_private<_AP_W, false, 1>& a) { + return ap_private<_AP_W, false>((a.VAL) >> (shiftAmt)); + } + + template + INLINE ap_private<_AP_W, _AP_S> lshr(const ap_private<_AP_W, _AP_S, 1>& a) { + static const uint64_t mask = ~0ULL<<_AP_W; + return ap_private<_AP_W, _AP_S>((a.VAL&mask) >> (shiftAmt)); + } + + template + INLINE ap_private<_AP_W-shiftAmt, _AP_S> shr(const ap_private<_AP_W, _AP_S>& a) { + return ap_private<_AP_W-shiftAmt, _AP_S>((a.VAL) >> (shiftAmt)); + } + + template + INLINE ap_private<_AP_W+shiftAmt, _AP_S> shl(const ap_private<_AP_W, _AP_S>& a) { + return ap_private<_AP_W+shiftAmt, _AP_S>((a.VAL) << (shiftAmt)); + } + + template + INLINE bool get(const ap_private<_AP_W, _AP_S, 1>& a) { + unsigned shift = (index%APINT_BITS_PER_WORD); + static const uint64_t mask=1ULL << (shift); + return ((mask & a.VAL) != 0); + } + + template + INLINE bool get(const ap_private<_AP_W, _AP_S>& a) { + static const uint64_t mask=1ULL << (index&0x3f); + return ((mask & a.pVal[(index)>>6]) != 0); + } + + template + INLINE void set(ap_private<_AP_W, _AP_S, 1>& a) { + const uint64_t mask = ~0ULL >> (lsb) << (APINT_BITS_PER_WORD-msb+lsb-1)>>(APINT_BITS_PER_WORD-msb-1); + a.VAL |= mask; + } + + template + INLINE void clear(ap_private<_AP_W, _AP_S, 1>& a) { + static const uint64_t mask = ~(~0ULL >> (lsb) <<(APINT_BITS_PER_WORD-msb+lsb-1) >> (APINT_BITS_PER_WORD-msb-1)); + a.VAL &= mask; + } + + template + INLINE void set(ap_private<_AP_W, _AP_S>& a) { + enum { APINT_BITS_PER_WORD=64, + lsb_word = lsb_index /APINT_BITS_PER_WORD, + msb_word = msb_index / APINT_BITS_PER_WORD, + msb = msb_index % APINT_BITS_PER_WORD, + lsb=lsb_index % APINT_BITS_PER_WORD}; + if (msb_word==lsb_word) { + const uint64_t mask = ~0ULL >> (lsb) << (APINT_BITS_PER_WORD-msb+lsb-1)>>(APINT_BITS_PER_WORD-msb-1); + a.pVal[msb_word] |= mask; + } else { + const uint64_t lsb_mask = ~0ULL >> (lsb) << (lsb); + const uint64_t msb_mask = ~0ULL << (APINT_BITS_PER_WORD-msb-1)>>(APINT_BITS_PER_WORD-msb-1); + a.pVal[lsb_word] |=lsb_mask; + for (int i=lsb_word+1; i + INLINE void clear(ap_private<_AP_W, _AP_S>& a) { + enum { APINT_BITS_PER_WORD=64, + lsb_word = lsb_index /APINT_BITS_PER_WORD, + msb_word = msb_index / APINT_BITS_PER_WORD, + msb = msb_index % APINT_BITS_PER_WORD, + lsb=lsb_index % APINT_BITS_PER_WORD}; + if (msb_word == lsb_word) { + const uint64_t mask = ~(~0ULL >> (lsb) << (APINT_BITS_PER_WORD-msb+lsb-1)>>(APINT_BITS_PER_WORD-msb-1)); + a.pVal[msb_word] &= mask; + } else { + const uint64_t lsb_mask = ~(~0ULL >> (lsb) << (lsb)); + const uint64_t msb_mask = ~(~0ULL << (APINT_BITS_PER_WORD-msb-1)>>(APINT_BITS_PER_WORD-msb-1)); + a.pVal[lsb_word] &=lsb_mask; + for (int i=lsb_word+1; i + INLINE void set(ap_private<_AP_W, _AP_S, 1>& a) { + static const uint64_t mask=1ULL << (index); + a.VAL |= mask; + a.clearUnusedBits(); + } + + template + INLINE void clear(ap_private<_AP_W, _AP_S, 1>& a) { + static const uint64_t mask=~(1ULL << (index)); + a.VAL &= mask; + a.clearUnusedBits(); + } + + template + INLINE void set(ap_private<_AP_W, _AP_S>& a) { + enum { APINT_BITS_PER_WORD=64, word = index/APINT_BITS_PER_WORD}; + static const uint64_t mask=1ULL << (index%APINT_BITS_PER_WORD); + a.pVal[word] |= mask; + a.clearUnusedBits(); + } + + template + INLINE void clear(ap_private<_AP_W, _AP_S>& a) { + enum { APINT_BITS_PER_WORD=64, word = index/APINT_BITS_PER_WORD}; + static const uint64_t mask=~(1ULL << (index%APINT_BITS_PER_WORD)); + a.pVal[word] &= mask; + a.clearUnusedBits(); + } + + template + INLINE bool isNegative(const ap_private<_AP_W, false>& a) { + return false; + } + + template + INLINE bool isNegative(const ap_private<_AP_W, true, 1>& a) { + static const uint64_t sign_mask = (1ULL << (_AP_W-1)); + return ((sign_mask & a.VAL) != 0); + } + + template + INLINE bool isNegative(const ap_private<_AP_W, true>& a) { + enum {APINT_BITS_PER_WORD=64,_AP_N=(_AP_W+APINT_BITS_PER_WORD-1)/APINT_BITS_PER_WORD}; + static const uint64_t sign_mask = (1ULL << (_AP_W%APINT_BITS_PER_WORD-1)); + return sign_mask & a.pVal[_AP_N-1]; + } +} // End of ap_private_ops namespace + +/// @brief Check if the specified ap_private has a N-bits integer value. +template +INLINE bool isIntN(uint32_t __N, const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.isIntN(__N); +} + +/// @returns true if the argument ap_private value is a sequence of ones +/// starting at the least significant bit with the remainder zero. +template +INLINE bool isMask(uint32_t numBits, const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return APIVal.getBoolValue() && ((APIVal + ap_private<_AP_W, _AP_S, _AP_N>(numBits,1)) & APIVal) == 0; +} + +/// @returns true if the argument ap_private value contains a sequence of ones +/// with the remainder zero. +template +INLINE bool isShiftedMask(uint32_t numBits, const ap_private<_AP_W, _AP_S, _AP_N>& APIVal) { + return isMask(numBits, (APIVal - ap_private<_AP_W, _AP_S, _AP_N>(numBits,1)) | APIVal); +} + +#if 0 +/// add_1 - This function adds a single "digit" integer, y, to the multiple +/// "digit" integer array, x[]. x[] is modified to reflect the addition and +/// 1 is returned if there is a carry out, otherwise 0 is returned. +/// @returns the carry of the addition. +static bool add_1(uint64_t dest[], uint64_t x[], uint32_t len, uint64_t y) { + for (uint32_t i = 0; i < len; ++i) { + dest[i] = y + x[i]; + if (dest[i] < y) + y = 1; // Carry one to next digit. + else { + y = 0; // No need to carry so exit early + break; + } + } + return (y != 0); +} +#endif + +#if 0 +/// add - This function adds the integer array x to the integer array Y and +/// places the result in dest. +/// @returns the carry out from the addition +/// @brief General addition of 64-bit integer arrays +static bool add(uint64_t *dest, const uint64_t *x, const uint64_t *y, + uint32_t destlen, uint32_t xlen, uint32_t ylen, bool xsigned, bool ysigned) { + bool carry = false; + uint32_t len = AESL_std::min(xlen, ylen); + uint32_t i; + for (i = 0; i< len && i < destlen; ++i) { + uint64_t limit = AESL_std::min(x[i],y[i]); // must come first in case dest == x + dest[i] = x[i] + y[i] + carry; + carry = dest[i] < limit || (carry && dest[i] == limit); + } + if (xlen > ylen) { + const uint64_t yext = xsigned && int64_t(y[ylen-1])<0 ? -1 : 0; + for (i=ylen; i< xlen && i < destlen; i++) { + uint64_t limit = AESL_std::min(x[i], yext); + dest[i] = x[i] + yext + carry; + carry = (dest[i] < limit)||(carry && dest[i] == x[i]); + } + } else if (ylen> xlen) { + const uint64_t xext = ysigned && int64_t(x[xlen-1])<0 ? -1 : 0; + for (i=xlen; i< ylen && i < destlen; i++) { + uint64_t limit = AESL_std::min(xext, y[i]); + dest[i] = xext + y[i] + carry; + carry = (dest[i] < limit)||(carry && dest[i] == y[i]); + } + } + return carry; +} +#endif + +#if 0 +/// @returns returns the borrow out. +/// @brief Generalized subtraction of 64-bit integer arrays. +static bool sub(uint64_t *dest, const uint64_t *x, const uint64_t *y, + uint32_t destlen, uint32_t xlen, uint32_t ylen, bool xsigned, bool ysigned) { + bool borrow = false; + uint32_t i; + uint32_t len = AESL_std::min(xlen, ylen); + for (i = 0; i < len && i < destlen; ++i) { + uint64_t x_tmp = borrow ? x[i] - 1 : x[i]; + borrow = y[i] > x_tmp || (borrow && x[i] == 0); + dest[i] = x_tmp - y[i]; + } + if (xlen > ylen) { + const uint64_t yext = ysigned && int64_t(y[ylen-1])<0 ? -1 : 0; + for (i=ylen; i< xlen && i < destlen; i++) { + uint64_t x_tmp = borrow ? x[i] - 1 : x[i]; + borrow = yext > x_tmp || (borrow && x[i] == 0); + dest[i] = x_tmp - yext; + } + } else if (ylen> xlen) { + const uint64_t xext = xsigned && int64_t(x[xlen-1])<0 ? -1 : 0; + for (i=xlen; i< ylen && i < destlen; i++) { + uint64_t x_tmp = borrow ? xext - 1 : xext; + borrow = y[i] > x_tmp || (borrow && xext==0); + dest[i] = x_tmp - y[i]; + } + } + return borrow; +} +#endif + +/// Subtracts the RHS ap_private from this ap_private +/// @returns this, after subtraction +/// @brief Subtraction assignment operator. + +#if 0 +/// Multiplies an integer array, x by a a uint64_t integer and places the result +/// into dest. +/// @returns the carry out of the multiplication. +/// @brief Multiply a multi-digit ap_private by a single digit (64-bit) integer. +static uint64_t mul_1(uint64_t dest[], const uint64_t x[], uint32_t len, uint64_t y) { + // Split y into high 32-bit part (hy) and low 32-bit part (ly) + uint64_t ly = y & 0xffffffffULL, hy = (y) >> 32; + uint64_t carry = 0; + static const uint64_t two_power_32 = 1ULL << 32; + // For each digit of x. + for (uint32_t i = 0; i < len; ++i) { + // Split x into high and low words + uint64_t lx = x[i] & 0xffffffffULL; + uint64_t hx = (x[i]) >> 32; + // hasCarry - A flag to indicate if there is a carry to the next digit. + // hasCarry == 0, no carry + // hasCarry == 1, has carry + // hasCarry == 2, no carry and the calculation result == 0. + uint8_t hasCarry = 0; + dest[i] = carry + lx * ly; + // Determine if the add above introduces carry. + hasCarry = (dest[i] < carry) ? 1 : 0; + carry = hx * ly + ((dest[i]) >> 32) + (hasCarry ? two_power_32 : 0); + // The upper limit of carry can be (2^32 - 1)(2^32 - 1) + + // (2^32 - 1) + 2^32 = 2^64. + hasCarry = (!carry && hasCarry) ? 1 : (!carry ? 2 : 0); + + carry += (lx * hy) & 0xffffffffULL; + dest[i] = ((carry) << 32) | (dest[i] & 0xffffffffULL); + carry = (((!carry && hasCarry != 2) || hasCarry == 1) ? two_power_32 : 0) + + ((carry) >> 32) + ((lx * hy) >> 32) + hx * hy; + } + return carry; +} +#endif + +#if 0 +/// Multiplies integer array x by integer array y and stores the result into +/// the integer array dest. Note that dest's size must be >= xlen + ylen. +/// @brief Generalized multiplicate of integer arrays. +static void mul(uint64_t dest[], const uint64_t x[], uint32_t xlen, const uint64_t y[], + uint32_t ylen, uint32_t destlen) { + dest[xlen] = mul_1(dest, x, xlen, y[0]); + for (uint32_t i = 1; i < ylen; ++i) { + uint64_t ly = y[i] & 0xffffffffULL, hy = (y[i]) >> 32; + uint64_t carry = 0, lx = 0, hx = 0; + for (uint32_t j = 0; j < xlen; ++j) { + lx = x[j] & 0xffffffffULL; + hx = (x[j]) >> 32; + // hasCarry - A flag to indicate if has carry. + // hasCarry == 0, no carry + // hasCarry == 1, has carry + // hasCarry == 2, no carry and the calculation result == 0. + uint8_t hasCarry = 0; + uint64_t resul = carry + lx * ly; + hasCarry = (resul < carry) ? 1 : 0; + carry = (hasCarry ? (1ULL << 32) : 0) + hx * ly + ((resul) >> 32); + hasCarry = (!carry && hasCarry) ? 1 : (!carry ? 2 : 0); + carry += (lx * hy) & 0xffffffffULL; + resul = ((carry) << 32) | (resul & 0xffffffffULL); + dest[i+j] += resul; + carry = (((!carry && hasCarry != 2) || hasCarry == 1) ? (1ULL << 32) : 0)+ + ((carry) >> 32) + (dest[i+j] < resul ? 1 : 0) + + ((lx * hy) >> 32) + hx * hy; + } + dest[i+xlen] = carry; + } +} +#endif + + + +template +uint32_t ap_private<_AP_W, _AP_S, _AP_N>::getBitsNeeded(const char* str, uint32_t slen, uint8_t radix) { + assert(str != 0 && "Invalid value string"); + assert(slen > 0 && "Invalid string length"); + + // Each computation below needs to know if its negative + uint32_t isNegative = str[0] == '-'; + if (isNegative) { + slen--; + str++; + } + // For radixes of power-of-two values, the bits required is accurately and + // easily computed + if (radix == 2) + return slen + isNegative; + if (radix == 8) + return slen * 3 + isNegative; + if (radix == 16) + return slen * 4 + isNegative; + + // Otherwise it must be radix == 10, the hard case + assert(radix == 10 && "Invalid radix"); + + // Convert to the actual binary value. + //ap_private<_AP_W, _AP_S, _AP_N> tmp(sufficient, str, slen, radix); + + // Compute how many bits are required. + //return isNegative + tmp.logBase2() + 1; + return isNegative + slen * 4; +} + +template +uint32_t ap_private<_AP_W, _AP_S, _AP_N>::countLeadingZeros() const { + enum { msw_bits = (BitWidth % APINT_BITS_PER_WORD)?(BitWidth % APINT_BITS_PER_WORD):APINT_BITS_PER_WORD, + excessBits = APINT_BITS_PER_WORD - msw_bits }; + uint32_t Count = CountLeadingZeros_64(pVal[_AP_N-1]); + if (Count>=excessBits) + Count -= excessBits; + if (!pVal[_AP_N-1]) { + for (uint32_t i = _AP_N-1 ; i ; --i) { + if (!pVal[i-1]) + Count += APINT_BITS_PER_WORD; + else { + Count += CountLeadingZeros_64(pVal[i-1]); + break; + } + } + } + return Count; +} + +static uint32_t countLeadingOnes_64(uint64_t __V, uint32_t skip) { + uint32_t Count = 0; + if (skip) + (__V) <<= (skip); + while (__V && (__V & (1ULL << 63))) { + Count++; + (__V) <<= 1; + } + return Count; +} + +template +uint32_t ap_private<_AP_W, _AP_S, _AP_N>::countLeadingOnes() const { + if (isSingleWord()) + return countLeadingOnes_64(VAL, APINT_BITS_PER_WORD - BitWidth); + + uint32_t highWordBits = BitWidth % APINT_BITS_PER_WORD; + uint32_t shift = (highWordBits == 0 ? 0 : APINT_BITS_PER_WORD - highWordBits); + int i = _AP_N - 1; + uint32_t Count = countLeadingOnes_64(pVal[i], shift); + if (Count == highWordBits) { + for (i--; i >= 0; --i) { + if (pVal[i] == ~0ULL) + Count += APINT_BITS_PER_WORD; + else { + Count += countLeadingOnes_64(pVal[i], 0); + break; + } + } + } + return Count; +} + +template +INLINE uint32_t ap_private<_AP_W, _AP_S, _AP_N>::countTrailingZeros() const { + if (isSingleWord()) + return AESL_std::min(uint32_t(CountTrailingZeros_64(VAL)), BitWidth); + uint32_t Count = 0; + uint32_t i = 0; + for (; i < _AP_N && pVal[i] == 0; ++i) + Count += APINT_BITS_PER_WORD; + if (i < _AP_N) + Count += CountTrailingZeros_64(pVal[i]); + return AESL_std::min(Count, BitWidth); +} + +template +ap_private<_AP_W, _AP_S, _AP_N> ap_private<_AP_W, _AP_S, _AP_N>::byteSwap() const { + assert(BitWidth >= 16 && BitWidth % 16 == 0 && "Cannot byteswap!"); + if (BitWidth == 16) + return ap_private<_AP_W, _AP_S, _AP_N>(/*BitWidth,*/ ByteSwap_16(uint16_t(VAL))); + else if (BitWidth == 32) + return ap_private<_AP_W, _AP_S, _AP_N>(/*BitWidth,*/ ByteSwap_32(uint32_t(VAL))); + else if (BitWidth == 48) { + uint32_t Tmp1 = uint32_t((VAL) >> 16); + Tmp1 = ByteSwap_32(Tmp1); + uint16_t Tmp2 = uint16_t(VAL); + Tmp2 = ByteSwap_16(Tmp2); + return ap_private<_AP_W, _AP_S, _AP_N>(/*BitWidth,*/ ((uint64_t(Tmp2)) << 32) | Tmp1); + } else if (BitWidth == 64) + return ap_private<_AP_W, _AP_S, _AP_N>(/*BitWidth,*/ ByteSwap_64(VAL)); + else { + ap_private<_AP_W, _AP_S, _AP_N> Result(0); + char *pByte = (char*)Result.pVal; + for (uint32_t i = 0; i < BitWidth / APINT_WORD_SIZE / 2; ++i) { + char Tmp = pByte[i]; + pByte[i] = pByte[BitWidth / APINT_WORD_SIZE - 1 - i]; + pByte[BitWidth / APINT_WORD_SIZE - i - 1] = Tmp; + } + return Result; + } +} + +template +ap_private<_AP_W, _AP_S, _AP_N> ap_private_ops::GreatestCommonDivisor(const ap_private<_AP_W, _AP_S, _AP_N>& API1, const ap_private<_AP_W, _AP_S, _AP_N>& API2) { + ap_private<_AP_W, _AP_S, _AP_N> __A = API1, __B = API2; + while (!!__B) { + ap_private<_AP_W, _AP_S, _AP_N> __T = __B; + __B = ap_private_ops::urem(__A, __B); + __A = __T; + } + return __A; +} + +template +ap_private<_AP_W, _AP_S, _AP_N> ap_private_ops::RoundDoubleToap_private(double Double, uint32_t width) { + union { + double __D; + uint64_t __I; + } __T; + __T.__D = Double; + + // Get the sign bit from the highest order bit + bool isNeg = (__T.__I) >> 63; + + // Get the 11-bit exponent and adjust for the 1023 bit bias + int64_t exp = (((__T.__I) >> 52) & 0x7ffULL) - 1023; + + // If the exponent is negative, the value is < 0 so just return 0. + if (exp < 0) + return ap_private<_AP_W, _AP_S, _AP_N>(width, 0u); + + // Extract the mantissa by clearing the top 12 bits (sign + exponent). + uint64_t mantissa = (__T.__I & (~0ULL >> 12)) | 1ULL << 52; + + // If the exponent doesn't shift all bits out of the mantissa + if (exp < 52) + return isNeg ? -ap_private<_AP_W, _AP_S, _AP_N>(width, (mantissa) >> (52 - exp)) : + ap_private<_AP_W, _AP_S, _AP_N>((mantissa) >> (52 - exp)); + + // If the client didn't provide enough bits for us to shift the mantissa into + // then the result is undefined, just return 0 + if (width <= exp - 52) + return ap_private<_AP_W, _AP_S, _AP_N>(width, 0); + + // Otherwise, we have to shift the mantissa bits up to the right location + ap_private<_AP_W, _AP_S, _AP_N> Tmp(width, mantissa); + Tmp = Tmp.shl(exp - 52); + return isNeg ? -Tmp : Tmp; +} + +/// RoundToDouble - This function convert this ap_private to a double. +/// The layout for double is as following (IEEE Standard 754): +/// -------------------------------------- +/// | Sign Exponent Fraction Bias | +/// |-------------------------------------- | +/// | 1[63] 11[62-52] 52[51-00] 1023 | +/// -------------------------------------- +template +double ap_private<_AP_W, _AP_S, _AP_N>::roundToDouble(bool isSigned) const { + + // Handle the simple case where the value is contained in one uint64_t. + if (isSingleWord() || getActiveBits() <= APINT_BITS_PER_WORD) { + uint64_t val; + if (isSingleWord()) val = VAL; + else val = pVal[0]; + if (isSigned) { + int64_t sext = ((int64_t(val)) << (64-BitWidth)) >> (64-BitWidth); + return double(sext); + } else + return double(val); + } + + // Determine if the value is negative. + bool isNeg = isSigned ? (*this)[BitWidth-1] : false; + + // Construct the absolute value if we're negative. + ap_private<_AP_W, _AP_S, _AP_N> Tmp(isNeg ? -(*this) : (*this)); + + // Figure out how many bits we're using. + uint32_t n = Tmp.getActiveBits(); + + // The exponent (without bias normalization) is just the number of bits + // we are using. Note that the sign bit is gone since we constructed the + // absolute value. + uint64_t exp = n; + + // Return infinity for exponent overflow + if (exp > 1023) { + if (!isSigned || !isNeg) + return std::numeric_limits::infinity(); + else + return -std::numeric_limits::infinity(); + } + exp += 1023; // Increment for 1023 bias + + // Number of bits in mantissa is 52. To obtain the mantissa value, we must + // extract the high 52 bits from the correct words in pVal. + uint64_t mantissa; + unsigned hiWord = whichWord(n-1); + if (hiWord == 0) { + mantissa = Tmp.pVal[0]; + if (n > 52) + (mantissa) >>= (n - 52); // shift down, we want the top 52 bits. + } else { + assert(hiWord > 0 && "High word is negative?"); + uint64_t hibits = (Tmp.pVal[hiWord]) << (52 - n % APINT_BITS_PER_WORD); + uint64_t lobits = (Tmp.pVal[hiWord-1]) >> (11 + n % APINT_BITS_PER_WORD); + mantissa = hibits | lobits; + } + + // The leading bit of mantissa is implicit, so get rid of it. + uint64_t sign = isNeg ? (1ULL << (APINT_BITS_PER_WORD - 1)) : 0; + union { + double __D; + uint64_t __I; + } __T; + __T.__I = sign | ((exp) << 52) | mantissa; + return __T.__D; +} + +// Square Root - this method computes and returns the square root of "this". +// Three mechanisms are used for computation. For small values (<= 5 bits), +// a table lookup is done. This gets some performance for common cases. For +// values using less than 52 bits, the value is converted to double and then +// the libc sqrt function is called. The result is rounded and then converted +// back to a uint64_t which is then used to construct the result. Finally, +// the Babylonian method for computing square roots is used. +template +ap_private<_AP_W, _AP_S, _AP_N> ap_private<_AP_W, _AP_S, _AP_N>::sqrt() const { + + // Determine the magnitude of the value. + uint32_t magnitude = getActiveBits(); + + // Use a fast table for some small values. This also gets rid of some + // rounding errors in libc sqrt for small values. + if (magnitude <= 5) { + static const uint8_t results[32] = { + /* 0 */ 0, + /* 1- 2 */ 1, 1, + /* 3- 6 */ 2, 2, 2, 2, + /* 7-12 */ 3, 3, 3, 3, 3, 3, + /* 13-20 */ 4, 4, 4, 4, 4, 4, 4, 4, + /* 21-30 */ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + /* 31 */ 6 + }; + return ap_private<_AP_W, _AP_S, _AP_N>(/*BitWidth,*/ results[ (isSingleWord() ? VAL : pVal[0]) ]); + } + + // If the magnitude of the value fits in less than 52 bits (the precision of + // an IEEE double precision floating point value), then we can use the + // libc sqrt function which will probably use a hardware sqrt computation. + // This should be faster than the algorithm below. + if (magnitude < 52) { +#ifdef _MSC_VER + // Amazingly, VC++ doesn't have round(). + return ap_private<_AP_W, _AP_S, _AP_N>(/*BitWidth,*/ + uint64_t(::sqrt(double(isSingleWord()?VAL:pVal[0]))) + 0.5); +#else + return ap_private<_AP_W, _AP_S, _AP_N>(/*BitWidth,*/ + uint64_t(::round(::sqrt(double(isSingleWord()?VAL:pVal[0]))))); +#endif + } + + // Okay, all the short cuts are exhausted. We must compute it. The following + // is a classical Babylonian method for computing the square root. This code + // was adapted to APINt from a wikipedia article on such computations. + // See http://www.wikipedia.org/ and go to the page named + // Calculate_an_integer_square_root. + uint32_t nbits = BitWidth, i = 4; + ap_private<_AP_W, _AP_S, _AP_N> testy(16); + ap_private<_AP_W, _AP_S, _AP_N> x_old(/*BitWidth,*/ 1); + ap_private<_AP_W, _AP_S, _AP_N> x_new(0); + ap_private<_AP_W, _AP_S, _AP_N> two(/*BitWidth,*/ 2); + + // Select a good starting value using binary logarithms. + for (;; i += 2, testy = testy.shl(2)) + if (i >= nbits || this->ule(testy)) { + x_old = x_old.shl(i / 2); + break; + } + + // Use the Babylonian method to arrive at the integer square root: + for (;;) { + x_new = (this->udiv(x_old) + x_old).udiv(two); + if (x_old.ule(x_new)) + break; + x_old = x_new; + } + + // Make sure we return the closest approximation + // NOTE: The rounding calculation below is correct. It will produce an + // off-by-one discrepancy with results from pari/gp. That discrepancy has been + // determined to be a rounding issue with pari/gp as it begins to use a + // floating point representation after 192 bits. There are no discrepancies + // between this algorithm and pari/gp for bit widths < 192 bits. + ap_private<_AP_W, _AP_S, _AP_N> square(x_old * x_old); + ap_private<_AP_W, _AP_S, _AP_N> nextSquare((x_old + 1) * (x_old +1)); + if (this->ult(square)) + return x_old; + else if (this->ule(nextSquare)) { + ap_private<_AP_W, _AP_S, _AP_N> midpoint((nextSquare - square).udiv(two)); + ap_private<_AP_W, _AP_S, _AP_N> offset(*this - square); + if (offset.ult(midpoint)) + return x_old; + else + return x_old + 1; + } else + assert(0 && "Error in ap_private<_AP_W, _AP_S, _AP_N>::sqrt computation"); + return x_old + 1; +} + +/// Implementation of Knuth's Algorithm D (Division of nonnegative integers) +/// from "Art of Computer Programming, Volume 2", section 4.3.1, p. 272. The +/// variables here have the same names as in the algorithm. Comments explain +/// the algorithm and any deviation from it. +static void KnuthDiv(uint32_t *u, uint32_t *v, uint32_t *q, uint32_t* r, + uint32_t m, uint32_t n) { + assert(u && "Must provide dividend"); + assert(v && "Must provide divisor"); + assert(q && "Must provide quotient"); + assert(u != v && u != q && v != q && "Must us different memory"); + assert(n>1 && "n must be > 1"); + + // Knuth uses the value b as the base of the number system. In our case b + // is 2^31 so we just set it to -1u. + uint64_t b = uint64_t(1) << 32; + + //DEBUG(cerr << "KnuthDiv: m=" << m << " n=" << n << '\n'); + //DEBUG(cerr << "KnuthDiv: original:"); + //DEBUG(for (int i = m+n; i >=0; i--) cerr << " " << std::setbase(16) << u[i]); + //DEBUG(cerr << " by"); + //DEBUG(for (int i = n; i >0; i--) cerr << " " << std::setbase(16) << v[i-1]); + //DEBUG(cerr << '\n'); + // D1. [Normalize.] Set d = b / (v[n-1] + 1) and multiply all the digits of + // u and v by d. Note that we have taken Knuth's advice here to use a power + // of 2 value for d such that d * v[n-1] >= b/2 (b is the base). A power of + // 2 allows us to shift instead of multiply and it is easy to determine the + // shift amount from the leading zeros. We are basically normalizing the u + // and v so that its high bits are shifted to the top of v's range without + // overflow. Note that this can require an extra word in u so that u must + // be of length m+n+1. + uint32_t shift = CountLeadingZeros_32(v[n-1]); + uint32_t v_carry = 0; + uint32_t u_carry = 0; + if (shift) { + for (uint32_t i = 0; i < m+n; ++i) { + uint32_t u_tmp = (u[i]) >> (32 - shift); + u[i] = ((u[i]) << (shift)) | u_carry; + u_carry = u_tmp; + } + for (uint32_t i = 0; i < n; ++i) { + uint32_t v_tmp = (v[i]) >> (32 - shift); + v[i] = ((v[i]) << (shift)) | v_carry; + v_carry = v_tmp; + } + } + u[m+n] = u_carry; + //DEBUG(cerr << "KnuthDiv: normal:"); + //DEBUG(for (int i = m+n; i >=0; i--) cerr << " " << std::setbase(16) << u[i]); + //DEBUG(cerr << " by"); + //DEBUG(for (int i = n; i >0; i--) cerr << " " << std::setbase(16) << v[i-1]); + //DEBUG(cerr << '\n'); + + // D2. [Initialize j.] Set j to m. This is the loop counter over the places. + int j = m; + do { + //DEBUG(cerr << "KnuthDiv: quotient digit #" << j << '\n'); + // D3. [Calculate q'.]. + // Set qp = (u[j+n]*b + u[j+n-1]) / v[n-1]. (qp=qprime=q') + // Set rp = (u[j+n]*b + u[j+n-1]) % v[n-1]. (rp=rprime=r') + // Now test if qp == b or qp*v[n-2] > b*rp + u[j+n-2]; if so, decrease + // qp by 1, inrease rp by v[n-1], and repeat this test if rp < b. The test + // on v[n-2] determines at high speed most of the cases in which the trial + // value qp is one too large, and it eliminates all cases where qp is two + // too large. + uint64_t dividend = ((uint64_t(u[j+n]) << 32) + u[j+n-1]); + //DEBUG(cerr << "KnuthDiv: dividend == " << dividend << '\n'); + uint64_t qp = dividend / v[n-1]; + uint64_t rp = dividend % v[n-1]; + if (qp == b || qp*v[n-2] > b*rp + u[j+n-2]) { + qp--; + rp += v[n-1]; + if (rp < b && (qp == b || qp*v[n-2] > b*rp + u[j+n-2])) + qp--; + } + //DEBUG(cerr << "KnuthDiv: qp == " << qp << ", rp == " << rp << '\n'); + + // D4. [Multiply and subtract.] Replace (u[j+n]u[j+n-1]...u[j]) with + // (u[j+n]u[j+n-1]..u[j]) - qp * (v[n-1]...v[1]v[0]). This computation + // consists of a simple multiplication by a one-place number, combined with + // a subtraction. + bool isNeg = false; + for (uint32_t i = 0; i < n; ++i) { + uint64_t u_tmp = uint64_t(u[j+i]) | ((uint64_t(u[j+i+1])) << 32); + uint64_t subtrahend = uint64_t(qp) * uint64_t(v[i]); + bool borrow = subtrahend > u_tmp; + /*DEBUG(cerr << "KnuthDiv: u_tmp == " << u_tmp + << ", subtrahend == " << subtrahend + << ", borrow = " << borrow << '\n');*/ + + uint64_t result = u_tmp - subtrahend; + uint32_t k = j + i; + u[k++] = (uint32_t)(result & (b-1)); // subtract low word + u[k++] = (uint32_t)((result) >> 32); // subtract high word + while (borrow && k <= m+n) { // deal with borrow to the left + borrow = u[k] == 0; + u[k]--; + k++; + } + isNeg |= borrow; + /*DEBUG(cerr << "KnuthDiv: u[j+i] == " << u[j+i] << ", u[j+i+1] == " << + u[j+i+1] << '\n');*/ + } + /*DEBUG(cerr << "KnuthDiv: after subtraction:"); + DEBUG(for (int i = m+n; i >=0; i--) cerr << " " << u[i]); + DEBUG(cerr << '\n');*/ + // The digits (u[j+n]...u[j]) should be kept positive; if the result of + // this step is actually negative, (u[j+n]...u[j]) should be left as the + // true value plus b**(n+1), namely as the b's complement of + // the true value, and a "borrow" to the left should be remembered. + // + if (isNeg) { + bool carry = true; // true because b's complement is "complement + 1" + for (uint32_t i = 0; i <= m+n; ++i) { + u[i] = ~u[i] + carry; // b's complement + carry = carry && u[i] == 0; + } + } + /*DEBUG(cerr << "KnuthDiv: after complement:"); + DEBUG(for (int i = m+n; i >=0; i--) cerr << " " << u[i]); + DEBUG(cerr << '\n');*/ + + // D5. [Test remainder.] Set q[j] = qp. If the result of step D4 was + // negative, go to step D6; otherwise go on to step D7. + q[j] = (uint32_t)qp; + if (isNeg) { + // D6. [Add back]. The probability that this step is necessary is very + // small, on the order of only 2/b. Make sure that test data accounts for + // this possibility. Decrease q[j] by 1 + q[j]--; + // and add (0v[n-1]...v[1]v[0]) to (u[j+n]u[j+n-1]...u[j+1]u[j]). + // A carry will occur to the left of u[j+n], and it should be ignored + // since it cancels with the borrow that occurred in D4. + bool carry = false; + for (uint32_t i = 0; i < n; i++) { + uint32_t limit = AESL_std::min(u[j+i],v[i]); + u[j+i] += v[i] + carry; + carry = u[j+i] < limit || (carry && u[j+i] == limit); + } + u[j+n] += carry; + } + /*DEBUG(cerr << "KnuthDiv: after correction:"); + DEBUG(for (int i = m+n; i >=0; i--) cerr <<" " << u[i]); + DEBUG(cerr << "\nKnuthDiv: digit result = " << q[j] << '\n');*/ + + // D7. [Loop on j.] Decrease j by one. Now if j >= 0, go back to D3. + } while (--j >= 0); + + /*DEBUG(cerr << "KnuthDiv: quotient:"); + DEBUG(for (int i = m; i >=0; i--) cerr <<" " << q[i]); + DEBUG(cerr << '\n');*/ + + // D8. [Unnormalize]. Now q[...] is the desired quotient, and the desired + // remainder may be obtained by dividing u[...] by d. If r is non-null we + // compute the remainder (urem uses this). + if (r) { + // The value d is expressed by the "shift" value above since we avoided + // multiplication by d by using a shift left. So, all we have to do is + // shift right here. In order to mak + if (shift) { + uint32_t carry = 0; + //DEBUG(cerr << "KnuthDiv: remainder:"); + for (int i = n-1; i >= 0; i--) { + r[i] = ((u[i]) >> (shift)) | carry; + carry = (u[i]) << (32 - shift); + //DEBUG(cerr << " " << r[i]); + } + } else { + for (int i = n-1; i >= 0; i--) { + r[i] = u[i]; + //DEBUG(cerr << " " << r[i]); + } + } + //DEBUG(cerr << '\n'); + } + //DEBUG(cerr << std::setbase(10) << '\n'); +} + +template +void divide(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, uint32_t lhsWords, + const ap_private<_AP_W, _AP_S, _AP_N>& RHS, uint32_t rhsWords, + ap_private<_AP_W, _AP_S, _AP_N> *Quotient, ap_private<_AP_W, _AP_S, _AP_N> *Remainder) { + assert(lhsWords >= rhsWords && "Fractional result"); + enum {APINT_BITS_PER_WORD=64}; + // First, compose the values into an array of 32-bit words instead of + // 64-bit words. This is a necessity of both the "short division" algorithm + // and the the Knuth "classical algorithm" which requires there to be native + // operations for +, -, and * on an m bit value with an m*2 bit result. We + // can't use 64-bit operands here because we don't have native results of + // 128-bits. Furthremore, casting the 64-bit values to 32-bit values won't + // work on large-endian machines. + uint64_t mask = ~0ull >> (sizeof(uint32_t)*8); + uint32_t n = rhsWords * 2; + uint32_t m = (lhsWords * 2) - n; + + // Allocate space for the temporary values we need either on the stack, if + // it will fit, or on the heap if it won't. + uint32_t SPACE[128]; + uint32_t *__U = 0; + uint32_t *__V = 0; + uint32_t *__Q = 0; + uint32_t *__R = 0; + if ((Remainder?4:3)*n+2*m+1 <= 128) { + __U = &SPACE[0]; + __V = &SPACE[m+n+1]; + __Q = &SPACE[(m+n+1) + n]; + if (Remainder) + __R = &SPACE[(m+n+1) + n + (m+n)]; + } else { + __U = new uint32_t[m + n + 1]; + __V = new uint32_t[n]; + __Q = new uint32_t[m+n]; + if (Remainder) + __R = new uint32_t[n]; + } + + // Initialize the dividend + memset(__U, 0, (m+n+1)*sizeof(uint32_t)); + for (unsigned i = 0; i < lhsWords; ++i) { + uint64_t tmp = (LHS.getNumWords() == 1 ? LHS.VAL : LHS.pVal[i]); + __U[i * 2] = (uint32_t)(tmp & mask); + __U[i * 2 + 1] = (tmp) >> (sizeof(uint32_t)*8); + } + __U[m+n] = 0; // this extra word is for "spill" in the Knuth algorithm. + + // Initialize the divisor + memset(__V, 0, (n)*sizeof(uint32_t)); + for (unsigned i = 0; i < rhsWords; ++i) { + uint64_t tmp = (RHS.getNumWords() == 1 ? RHS.VAL : RHS.pVal[i]); + __V[i * 2] = (uint32_t)(tmp & mask); + __V[i * 2 + 1] = (tmp) >> (sizeof(uint32_t)*8); + } + + // initialize the quotient and remainder + memset(__Q, 0, (m+n) * sizeof(uint32_t)); + if (Remainder) + memset(__R, 0, n * sizeof(uint32_t)); + + // Now, adjust m and n for the Knuth division. n is the number of words in + // the divisor. m is the number of words by which the dividend exceeds the + // divisor (i.e. m+n is the length of the dividend). These sizes must not + // contain any zero words or the Knuth algorithm fails. + for (unsigned i = n; i > 0 && __V[i-1] == 0; i--) { + n--; + m++; + } + for (unsigned i = m+n; i > 0 && __U[i-1] == 0; i--) + m--; + + // If we're left with only a single word for the divisor, Knuth doesn't work + // so we implement the short division algorithm here. This is much simpler + // and faster because we are certain that we can divide a 64-bit quantity + // by a 32-bit quantity at hardware speed and short division is simply a + // series of such operations. This is just like doing short division but we + // are using base 2^32 instead of base 10. + assert(n != 0 && "Divide by zero?"); + if (n == 1) { + uint32_t divisor = __V[0]; + uint32_t remainder = 0; + for (int i = m+n-1; i >= 0; i--) { + uint64_t partial_dividend = (uint64_t(remainder)) << 32 | __U[i]; + if (partial_dividend == 0) { + __Q[i] = 0; + remainder = 0; + } else if (partial_dividend < divisor) { + __Q[i] = 0; + remainder = (uint32_t)partial_dividend; + } else if (partial_dividend == divisor) { + __Q[i] = 1; + remainder = 0; + } else { + __Q[i] = (uint32_t)(partial_dividend / divisor); + remainder = (uint32_t)(partial_dividend - (__Q[i] * divisor)); + } + } + if (__R) + __R[0] = remainder; + } else { + // Now we're ready to invoke the Knuth classical divide algorithm. In this + // case n > 1. + KnuthDiv(__U, __V, __Q, __R, m, n); + } + + // If the caller wants the quotient + if (Quotient) { + // Set up the Quotient value's memory. + if (Quotient->BitWidth != LHS.BitWidth) { + if (Quotient->isSingleWord()) + Quotient->VAL = 0; + } else + Quotient->clear(); + + // The quotient is in Q. Reconstitute the quotient into Quotient's low + // order words. + if (lhsWords == 1) { + uint64_t tmp = + uint64_t(__Q[0]) | ((uint64_t(__Q[1])) << (APINT_BITS_PER_WORD / 2)); + if (Quotient->isSingleWord()) + Quotient->VAL = tmp; + else + Quotient->pVal[0] = tmp; + } else { + assert(!Quotient->isSingleWord() && "Quotient ap_private not large enough"); + for (unsigned i = 0; i < lhsWords; ++i) + Quotient->pVal[i] = + uint64_t(__Q[i*2]) | ((uint64_t(__Q[i*2+1])) << (APINT_BITS_PER_WORD / 2)); + } + Quotient->clearUnusedBits(); + } + + // If the caller wants the remainder + if (Remainder) { + // Set up the Remainder value's memory. + if (Remainder->BitWidth != RHS.BitWidth) { + if (Remainder->isSingleWord()) + Remainder->VAL = 0; + } else + Remainder->clear(); + + // The remainder is in R. Reconstitute the remainder into Remainder's low + // order words. + if (rhsWords == 1) { + uint64_t tmp = + uint64_t(__R[0]) | ((uint64_t(__R[1])) << (APINT_BITS_PER_WORD / 2)); + if (Remainder->isSingleWord()) + Remainder->VAL = tmp; + else + Remainder->pVal[0] = tmp; + } else { + assert(!Remainder->isSingleWord() && "Remainder ap_private not large enough"); + for (unsigned i = 0; i < rhsWords; ++i) + Remainder->pVal[i] = + uint64_t(__R[i*2]) | ((uint64_t(__R[i*2+1])) << (APINT_BITS_PER_WORD / 2)); + } + Remainder->clearUnusedBits(); + } + + // Clean up the memory we allocated. + if (__U != &SPACE[0]) { + delete [] __U; + delete [] __V; + delete [] __Q; + delete [] __R; + } +} + + +template +void ap_private<_AP_W, _AP_S, _AP_N>::fromString(const char *str, uint32_t slen, uint8_t radix) { + enum { numbits=_AP_W}; + // Check our assumptions here + assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) && + "Radix should be 2, 8, 10, or 16!"); + assert(str && "String is null?"); + bool isNeg = str[0] == '-'; + if (isNeg) + str++, slen--; + + //skip any leading zero + while(*str == '0' && *(str+1) != '\0') {str++; slen--;} + assert((slen <= numbits || radix != 2) && "Insufficient bit width"); + assert(((slen - 1)*3 <= numbits || radix != 8) && "Insufficient bit width"); + assert(((slen - 1)*4 <= numbits || radix != 16) && "Insufficient bit width"); + assert((((slen -1)*64)/22 <= numbits || radix != 10) && "Insufficient bit width"); + + memset(pVal, 0, _AP_N * sizeof(uint64_t)); + + // Figure out if we can shift instead of multiply + uint32_t shift = (radix == 16 ? 4 : radix == 8 ? 3 : radix == 2 ? 1 : 0); + + // Set up an ap_private for the digit to add outside the loop so we don't + // constantly construct/destruct it. + uint64_t bigVal[_AP_N]; + memset(bigVal, 0, _AP_N * sizeof(uint64_t)); + ap_private<_AP_W, _AP_S, _AP_N> apdigit(getBitWidth(), bigVal); + ap_private<_AP_W, _AP_S, _AP_N> apradix(radix); + + // Enter digit traversal loop + for (unsigned i = 0; i < slen; i++) { + // Get a digit + uint32_t digit = 0; + char cdigit = str[i]; + if (radix == 16) { +#define isxdigit(c) (((c) >= '0' && (c) <= '9') || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F')) +#define isdigit(c) ((c) >= '0' && (c) <= '9') + if (!isxdigit(cdigit)) + assert(0 && "Invalid hex digit in string"); + if (isdigit(cdigit)) + digit = cdigit - '0'; + else if (cdigit >= 'a') + digit = cdigit - 'a' + 10; + else if (cdigit >= 'A') + digit = cdigit - 'A' + 10; + else + assert(0 && "huh? we shouldn't get here"); + } else if (isdigit(cdigit)) { + digit = cdigit - '0'; + } else { + assert(0 && "Invalid character in digit string"); + } +#undef isxdigit +#undef isdigit + // Shift or multiply the value by the radix + if (shift) + *this <<= shift; + else + *this *= apradix; + + // Add in the digit we just interpreted + if (apdigit.isSingleWord()) + apdigit.VAL = digit; + else + apdigit.pVal[0] = digit; + *this += apdigit; + } + // If its negative, put it in two's complement form + if (isNeg) { + (*this)--; + this->flip(); + } + clearUnusedBits(); +} + +template +std::string ap_private<_AP_W, _AP_S, _AP_N>::toString(uint8_t radix, bool wantSigned) const { + assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) && + "Radix should be 2, 8, 10, or 16!"); + static const char *digits[] = { + "0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F" + }; + std::string result; + uint32_t bits_used = getActiveBits(); + + if (radix != 10) { + // For the 2, 8 and 16 bit cases, we can just shift instead of divide + // because the number of bits per digit (1,3 and 4 respectively) divides + // equaly. We just shift until there value is zero. + + // First, check for a zero value and just short circuit the logic below. + if (*this == (uint64_t)(0)) + result = "0"; + else { + ap_private<_AP_W, false, _AP_N> tmp(*this); + size_t insert_at = 0; + if (wantSigned && isNegative()) { + // They want to print the signed version and it is a negative value + // Flip the bits and add one to turn it into the equivalent positive + // value and put a '-' in the result. + tmp.flip(); + tmp++; + tmp.clearUnusedBitsToZero(); + result = "-"; + insert_at = 1; + } + // Just shift tmp right for each digit width until it becomes zero + uint32_t shift = (radix == 16 ? 4 : (radix == 8 ? 3 : 1)); + uint64_t mask = radix - 1; + ap_private<_AP_W, false, _AP_N> zero(0); + while (tmp.ne(zero)) { + unsigned digit = (tmp.isSingleWord() ? tmp.VAL : tmp.pVal[0]) & mask; + result.insert(insert_at, digits[digit]); + tmp = tmp.lshr(shift); + } + } + return result; + } + + ap_private<_AP_W, false, _AP_N> tmp(*this); + ap_private<_AP_W, false, _AP_N> divisor(radix); + ap_private<_AP_W, false, _AP_N> zero(0); + size_t insert_at = 0; + if (wantSigned && isNegative()) { + // They want to print the signed version and it is a negative value + // Flip the bits and add one to turn it into the equivalent positive + // value and put a '-' in the result. + tmp.flip(); + tmp++; + tmp.clearUnusedBitsToZero(); + result = "-"; + insert_at = 1; + } + if (tmp == ap_private<_AP_W, false, _AP_N>(0)) + result = "0"; + else while (tmp.ne(zero)) { + ap_private<_AP_W, false, _AP_N> APdigit(0); + ap_private<_AP_W, false, _AP_N> tmp2(0); + divide(tmp, tmp.getNumWords(), divisor, divisor.getNumWords(), &tmp2, + &APdigit); + uint32_t digit = APdigit.getZExtValue(); + assert(digit < radix && "divide failed"); + result.insert(insert_at,digits[digit]); + tmp = tmp2; + } + + return result; +} + +// This implements a variety of operations on a representation of +// arbitrary precision, two's-complement, bignum integer values. + +/* Assumed by lowHalf, highHalf, partMSB and partLSB. A fairly safe + and unrestricting assumption. */ + +/* Some handy functions local to this file. */ + +template +void divide(const ap_private<_AP_W, _AP_S, _AP_N>& LHS, uint32_t lhsWords, + uint64_t RHS, + ap_private<_AP_W, _AP_S, _AP_N> *Quotient, ap_private<_AP_W, _AP_S, _AP_N> *Remainder) { + uint32_t rhsWords=1; + assert(lhsWords >= rhsWords && "Fractional result"); + enum {APINT_BITS_PER_WORD=64}; + // First, compose the values into an array of 32-bit words instead of + // 64-bit words. This is a necessity of both the "short division" algorithm + // and the the Knuth "classical algorithm" which requires there to be native + // operations for +, -, and * on an m bit value with an m*2 bit result. We + // can't use 64-bit operands here because we don't have native results of + // 128-bits. Furthremore, casting the 64-bit values to 32-bit values won't + // work on large-endian machines. + uint64_t mask = ~0ull >> (sizeof(uint32_t)*8); + uint32_t n = 2; + uint32_t m = (lhsWords * 2) - n; + + // Allocate space for the temporary values we need either on the stack, if + // it will fit, or on the heap if it won't. + uint32_t SPACE[128]; + uint32_t *__U = 0; + uint32_t *__V = 0; + uint32_t *__Q = 0; + uint32_t *__R = 0; + if ((Remainder?4:3)*n+2*m+1 <= 128) { + __U = &SPACE[0]; + __V = &SPACE[m+n+1]; + __Q = &SPACE[(m+n+1) + n]; + if (Remainder) + __R = &SPACE[(m+n+1) + n + (m+n)]; + } else { + __U = new uint32_t[m + n + 1]; + __V = new uint32_t[n]; + __Q = new uint32_t[m+n]; + if (Remainder) + __R = new uint32_t[n]; + } + + // Initialize the dividend + memset(__U, 0, (m+n+1)*sizeof(uint32_t)); + for (unsigned i = 0; i < lhsWords; ++i) { + uint64_t tmp = (LHS.getNumWords() == 1 ? LHS.VAL : LHS.pVal[i]); + __U[i * 2] = tmp & mask; + __U[i * 2 + 1] = (tmp) >> (sizeof(uint32_t)*8); + } + __U[m+n] = 0; // this extra word is for "spill" in the Knuth algorithm. + + // Initialize the divisor + memset(__V, 0, (n)*sizeof(uint32_t)); + __V[0] = RHS & mask; + __V[1] = (RHS) >> (sizeof(uint32_t)*8); + + // initialize the quotient and remainder + memset(__Q, 0, (m+n) * sizeof(uint32_t)); + if (Remainder) + memset(__R, 0, n * sizeof(uint32_t)); + + // Now, adjust m and n for the Knuth division. n is the number of words in + // the divisor. m is the number of words by which the dividend exceeds the + // divisor (i.e. m+n is the length of the dividend). These sizes must not + // contain any zero words or the Knuth algorithm fails. + for (unsigned i = n; i > 0 && __V[i-1] == 0; i--) { + n--; + m++; + } + for (unsigned i = m+n; i > 0 && __U[i-1] == 0; i--) + m--; + + // If we're left with only a single word for the divisor, Knuth doesn't work + // so we implement the short division algorithm here. This is much simpler + // and faster because we are certain that we can divide a 64-bit quantity + // by a 32-bit quantity at hardware speed and short division is simply a + // series of such operations. This is just like doing short division but we + // are using base 2^32 instead of base 10. + assert(n != 0 && "Divide by zero?"); + if (n == 1) { + uint32_t divisor = __V[0]; + uint32_t remainder = 0; + for (int i = m+n-1; i >= 0; i--) { + uint64_t partial_dividend = (uint64_t(remainder)) << 32 | __U[i]; + if (partial_dividend == 0) { + __Q[i] = 0; + remainder = 0; + } else if (partial_dividend < divisor) { + __Q[i] = 0; + remainder = partial_dividend; + } else if (partial_dividend == divisor) { + __Q[i] = 1; + remainder = 0; + } else { + __Q[i] = partial_dividend / divisor; + remainder = partial_dividend - (__Q[i] * divisor); + } + } + if (__R) + __R[0] = remainder; + } else { + // Now we're ready to invoke the Knuth classical divide algorithm. In this + // case n > 1. + KnuthDiv(__U, __V, __Q, __R, m, n); + } + + // If the caller wants the quotient + if (Quotient) { + // Set up the Quotient value's memory. + if (Quotient->BitWidth != LHS.BitWidth) { + if (Quotient->isSingleWord()) + Quotient->VAL = 0; + else + delete [] Quotient->pVal; + } else + Quotient->clear(); + + // The quotient is in Q. Reconstitute the quotient into Quotient's low + // order words. + if (lhsWords == 1) { + uint64_t tmp = + uint64_t(__Q[0]) | ((uint64_t(__Q[1])) << (APINT_BITS_PER_WORD / 2)); + if (Quotient->isSingleWord()) + Quotient->VAL = tmp; + else + Quotient->pVal[0] = tmp; + } else { + assert(!Quotient->isSingleWord() && "Quotient ap_private not large enough"); + for (unsigned i = 0; i < lhsWords; ++i) + Quotient->pVal[i] = + uint64_t(__Q[i*2]) | ((uint64_t(__Q[i*2+1])) << (APINT_BITS_PER_WORD / 2)); + } + Quotient->clearUnusedBits(); + } + + // If the caller wants the remainder + if (Remainder) { + // Set up the Remainder value's memory. + if (Remainder->BitWidth != 64 /* RHS.BitWidth */) { + if (Remainder->isSingleWord()) + Remainder->VAL = 0; + } else + Remainder->clear(); + + // The remainder is in __R. Reconstitute the remainder into Remainder's low + // order words. + if (rhsWords == 1) { + uint64_t tmp = + uint64_t(__R[0]) | ((uint64_t(__R[1])) << (APINT_BITS_PER_WORD / 2)); + if (Remainder->isSingleWord()) + Remainder->VAL = tmp; + else + Remainder->pVal[0] = tmp; + } else { + assert(!Remainder->isSingleWord() && "Remainder ap_private not large enough"); + for (unsigned i = 0; i < rhsWords; ++i) + Remainder->pVal[i] = + uint64_t(__R[i*2]) | ((uint64_t(__R[i*2+1])) << (APINT_BITS_PER_WORD / 2)); + } + Remainder->clearUnusedBits(); + } + + // Clean up the memory we allocated. + if (__U != &SPACE[0]) { + delete [] __U; + delete [] __V; + delete [] __Q; + delete [] __R; + } +} + +//When bitwidth < 64 +template class ap_private <_AP_W, _AP_S, 1> { +#ifdef _MSC_VER +#pragma warning( disable : 4521 4522 ) +#endif +public: + typedef typename retval<_AP_S>::Type ValType; + template + struct RType { + enum { + _AP_N =1, + mult_w = _AP_W+_AP_W2, + mult_s = _AP_S||_AP_S2, //?? why + plus_w = AP_MAX(_AP_W+(_AP_S2&&!_AP_S),_AP_W2+(_AP_S&&!_AP_S2))+1, //shouldn't it be AP_MAX(_AP_W,_AP_W2)+!(_AP_S^_AP_S2)+1 ???? + plus_s = _AP_S||_AP_S2, + minus_w = AP_MAX(_AP_W+(_AP_S2&&!_AP_S),_AP_W2+(_AP_S&&!_AP_S2))+1, + minus_s = true, + div_w = _AP_W+_AP_S2, + div_s = _AP_S||_AP_S2, + mod_w = AP_MIN(_AP_W,_AP_W2+(!_AP_S2&&_AP_S)), + mod_s = _AP_S, + logic_w = AP_MAX(_AP_W+(_AP_S2&&!_AP_S),_AP_W2+(_AP_S&&!_AP_S2)), + logic_s = _AP_S||_AP_S2 + }; + typedef ap_private mult; + typedef ap_private plus; + typedef ap_private minus; + typedef ap_private logic; + typedef ap_private div; + typedef ap_private mod; + typedef ap_private<_AP_W, _AP_S> arg1; + typedef bool reduce; + }; + enum { APINT_BITS_PER_WORD = 64}; + enum { excess_bits = (_AP_W%APINT_BITS_PER_WORD) ? APINT_BITS_PER_WORD -(_AP_W%APINT_BITS_PER_WORD) : 0}; + static const uint64_t mask = ((uint64_t)~0ULL >> (excess_bits)); + static const uint64_t not_mask = ~mask; + static const uint64_t sign_bit_mask = 1ULL << (APINT_BITS_PER_WORD-1); + template struct sign_ext_mask { static const uint64_t mask=~0ULL<<_AP_W1;}; + + enum { BitWidth=_AP_W}; + uint64_t VAL; ///< Used to store the <= 64 bits integer value. + const uint64_t *const pVal; + + INLINE uint32_t getBitWidth() const { + return BitWidth; + } + + template + ap_private<_AP_W, _AP_S, 1>& operator=(const ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { + VAL = RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + + template + ap_private<_AP_W, _AP_S, 1>& operator=(const volatile ap_private<_AP_W1, _AP_S1, _AP_N1>& RHS) { + VAL = RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + + template + ap_private<_AP_W, _AP_S, 1>& operator=(const ap_private<_AP_W1, _AP_S1, 1>& RHS) { + VAL = RHS.VAL; + clearUnusedBits(); + return *this; + } + + template + ap_private<_AP_W, _AP_S, 1>& operator=(const volatile ap_private<_AP_W1, _AP_S1, 1>& RHS) { + VAL = RHS.VAL; + clearUnusedBits(); + return *this; + } + + volatile ap_private& operator=(const ap_private& RHS) volatile { + // Don't do anything for X = X + VAL = RHS.VAL; // No need to check because no harm done by copying. + return *this; + } + ap_private& operator=(const ap_private& RHS) { + // Don't do anything for X = X + VAL = RHS.VAL; // No need to check because no harm done by copying. + return *this; + } + + volatile ap_private& operator=(const volatile ap_private& RHS) volatile { + // Don't do anything for X = X + VAL = RHS.VAL; // No need to check because no harm done by copying. + return *this; + } + ap_private& operator=(const volatile ap_private& RHS) { + // Don't do anything for X = X + VAL = RHS.VAL; // No need to check because no harm done by copying. + return *this; + } + + template + INLINE ap_private& operator = (const ap_range_ref<_AP_W2, _AP_S2>& op2) { + *this = ap_private<_AP_W2, false>(op2); + return *this; + } + + explicit INLINE ap_private(uint64_t* val) : VAL(val[0]), pVal(&VAL){ + clearUnusedBits(); + } + + INLINE bool isSingleWord() const { return true; } + + INLINE void fromString(const char *strStart, uint32_t slen, + uint8_t radix, int offset=0) { + // Check our assumptions here + assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) && + "Radix should be 2, 8, 10, or 16!"); + assert(strStart && "String is null?"); + strStart+=offset; + switch(radix) { + case 2: + // sscanf(strStart,"%b",&VAL); + VAL = *strStart =='1' ? ~0ULL : 0; + for (;*strStart; ++strStart) { + assert((*strStart=='0'|| *strStart=='1')&&("Wrong binary number") ); + VAL <<=1; + VAL |= (*strStart-'0'); + } + break; + case 8: +#if __WIN32__ + sscanf(strStart,"%I64o",&VAL); +#else + +#if defined __x86_64__ + sscanf(strStart,"%lo",&VAL); +#else + sscanf(strStart,"%llo",&VAL); +#endif + +#endif + break; + case 10: +#if __WIN32__ + sscanf(strStart,"%I64u",&VAL); +#else + +#if defined __x86_64__ + sscanf(strStart,"%lu",&VAL); +#else + sscanf(strStart,"%llu",&VAL); +#endif + +#endif + break; + case 16: +#if __WIN32__ + sscanf(strStart,"%I64x",&VAL); +#else + +#if defined __x86_64__ + sscanf(strStart,"%lx",&VAL); +#else + sscanf(strStart,"%llx",&VAL); +#endif + +#endif + break; + default: + assert(true && "Unknown radix"); + // error + } + clearUnusedBits(); + } + + INLINE ap_private() : pVal(&VAL){VAL = 0ULL;} + +#define CTOR(TYPE) \ + INLINE ap_private(TYPE v) : VAL((uint64_t)v), pVal(&VAL) { \ + clearUnusedBits(); \ + } + CTOR(int) + CTOR(bool) + CTOR(signed char) + CTOR(unsigned char) + CTOR(short) + CTOR(unsigned short) + CTOR(unsigned int) + CTOR(long) + CTOR(unsigned long) + CTOR(unsigned long long) + CTOR(long long) + CTOR(float) + CTOR(double) +#undef CTOR + ap_private(uint32_t numWords, const uint64_t bigVal[]): VAL(bigVal[0]), pVal(&VAL) {clearUnusedBits();} + + ap_private(const std::string& val, uint8_t radix=2, int base=0, int offset=0): VAL(0), pVal(&VAL) { + assert(!val.empty() && "String empty?"); + fromString(val.c_str()+base, val.size()-base, radix); + } + + ap_private(const char strStart[], uint32_t slen, uint8_t radix, int base=0, int offset=0) : VAL(0), pVal(&VAL) { + fromString(strStart+base, slen-base, radix, offset); + } + + ap_private(const ap_private& that) : VAL(that.VAL), pVal(&VAL) { + clearUnusedBits(); + } + + template + ap_private(const ap_private<_AP_W1, _AP_S1, 1>& that) : VAL(that.VAL), pVal(&VAL) { + clearUnusedBits(); + } + + template + ap_private(const ap_private<_AP_W1, _AP_S1, _AP_N1>& that) : VAL(that.pVal[0]), pVal(&VAL) { + clearUnusedBits(); + } + + template + ap_private(const volatile ap_private<_AP_W1, _AP_S1, _AP_N1>& that) : VAL(that.pVal[0]), pVal(&VAL) { + clearUnusedBits(); + } + +#if 0 +template + explicit ap_private(const ap_private<_AP_W1, true, 1+_AP_W1/64>& that) + : VAL((_AP_W1>_AP_W) ? that.VAL & mask : ((1ULL<<(_AP_W1-1)&that.pVal[0]) ? sign_ext_mask<_AP_W1>::mask | that.VAL : that.pVal[0])), pVal(&VAL) {} + +template + explicit ap_private(const ap_private<_AP_W1, false, (_AP_W1+63)/64>& that) + : VAL(that.VAL & mask), pVal(&VAL) {} +#endif + + explicit ap_private(const char* val) : pVal(&VAL) { + std::string str(val); + uint32_t strLen = str.length(); + const char *strp = str.c_str(); + uint32_t offset = 0; + uint32_t base = 0; + bool neg = false; + uint32_t radix = 10; + ap_parse_sign(strp, base, neg); + ap_parse_prefix(strp + base, offset, radix); + + if ((radix != 10 && neg) || + (strLen - base - offset <= 0) || + InvalidDigit(strp, strLen, base + offset, radix)) { + fprintf(stderr, "invalid character string %s !\n", val); + assert(0); + } + + ap_private<_AP_W, _AP_S> ap_private_val(str.c_str(), strLen, radix, base, offset); + if (neg) + ap_private_val = -ap_private_val; + operator = (ap_private_val); + } + + ap_private(const char* val, signed char rd): pVal(&VAL) { + std::string str(val); + uint32_t strLen = str.length(); + const char *strp = str.c_str(); + uint32_t offset = 0; + uint32_t base = 0; + uint32_t radix = rd; + bool neg = false; + ap_parse_sign(strp, base, neg); + ap_parse_prefix(strp + base, offset, radix); + + if ((radix != 10 && neg) || + (strLen - base - offset <= 0) || + InvalidDigit(strp, strLen, base + offset, radix)) { + fprintf(stderr, "invalid character string %s !\n", val); + assert(0); + } + + uint32_t bitsNeeded = ap_private<_AP_W, _AP_S>::getBitsNeeded(strp, strLen, radix); + ap_private<_AP_W, _AP_S> ap_private_val(strp , strLen, radix, base, offset); + //ap_private<_AP_W, _AP_S> ap_private_val(bitsNeeded, strp , strLen, radix, base, offset); + if (strp[0] == '-') + ap_private_val = -ap_private_val; + operator = (ap_private_val); + } + + INLINE bool isNegative() const { + static const uint64_t sign_mask = 1ULL << (_AP_W-1); + return _AP_S && (sign_mask & VAL); + } + + INLINE bool isPositive() const { + return !isNegative(); + } + + INLINE bool isStrictlyPositive() const { + return !isNegative() && VAL!=0; + } + + INLINE bool isAllOnesValue() const { + return (mask & VAL) == mask; + } + + template + INLINE bool operator==(const ap_private<_AP_W1, _AP_S1, 1>& RHS) const { + return (VAL == RHS.VAL); + } + + INLINE bool operator==(const ap_private<_AP_W, _AP_S>& RHS) const { return VAL == RHS.VAL; } + INLINE bool operator==(const ap_private<_AP_W, !_AP_S>& RHS) const { return getVal() == RHS.getVal(); } + INLINE bool operator==(uint64_t Val) const { return (VAL == Val); } + INLINE bool operator!=(uint64_t Val) const { return (VAL != Val); } + INLINE bool operator!=(const ap_private<_AP_W, _AP_S>& RHS) const { return VAL != RHS.VAL; } + INLINE bool operator!=(const ap_private<_AP_W, !_AP_S>& RHS) const { return getVal() != RHS.getVal(); } + const ap_private operator++() { ++VAL; clearUnusedBits(); return *this; } + const ap_private operator--(int) { + ap_private orig(*this); + --VAL; clearUnusedBits(); + return orig; + } + const ap_private operator--() { --VAL; clearUnusedBits(); return *this;} + INLINE bool operator !() const { return !VAL;} + + const ap_private operator++(int) { + ap_private orig(*this); + VAL++; clearUnusedBits(); + return orig; + } + + const ap_private operator~() {return ap_private(~VAL);} + INLINE typename RType<1,false>::minus operator-() const { + return ap_private<1,false>(0) - (*this); + } + + INLINE std::string toString(uint8_t radix, bool wantSigned) const ; + INLINE std::string toStringUnsigned(uint8_t radix = 10) const { + return toString(radix, false); + } + INLINE std::string toStringSigned(uint8_t radix = 10) const { + return toString(radix, true); + } + INLINE void clear() { + VAL=0; + } + INLINE ap_private& clear(uint32_t bitPosition) { VAL &= ~(1ULL<<(bitPosition)); clearUnusedBits(); return *this;} + + INLINE ap_private ashr(uint32_t shiftAmt) const { + enum {excess_bits = APINT_BITS_PER_WORD - BitWidth}; + if (_AP_S) + return ap_private((shiftAmt == BitWidth) ? 0 : ((int64_t)VAL) >> (shiftAmt)); + else + return ap_private((shiftAmt == BitWidth) ? 0 : (VAL) >> (shiftAmt)); + } + + INLINE ap_private lshr(uint32_t shiftAmt) const { + return ap_private((shiftAmt == BitWidth) ? ap_private(0) : ap_private((VAL&mask) >> (shiftAmt))); + } + + INLINE ap_private shl(uint32_t shiftAmt) const { + if (shiftAmt > BitWidth) { + if (!isNegative()) + return ap_private(0); + else return ap_private(-1); + } + if (shiftAmt == BitWidth) return ap_private(0); + else return ap_private((VAL) << (shiftAmt)); + //return ap_private((shiftAmt == BitWidth) ? ap_private(0ULL) : ap_private(VAL << shiftAmt)); + } + + INLINE int64_t getSExtValue() const { + return VAL; + } + + INLINE uint64_t getZExtValue() const { + return VAL & mask; + } + + template + INLINE ap_private(const ap_range_ref<_AP_W2,_AP_S2>& ref) : pVal(&VAL) { + *this=ref.get(); + } + + template + INLINE ap_private(const ap_bit_ref<_AP_W2,_AP_S2>& ref) : pVal(&VAL) { + *this = ((uint64_t)(bool)ref); + } + + template + INLINE ap_private(const ap_concat_ref<_AP_W2, _AP_T2,_AP_W3, _AP_T3>& ref) : pVal(&VAL) { + *this=ref.get(); + } + + template + INLINE ap_private(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2> &val) : pVal(&VAL) { + *this = ((val.operator ap_private<_AP_W2, false> ())); + } + + template + INLINE ap_private(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, + _AP_Q2, _AP_O2, _AP_N2> &val) : pVal(&VAL) { + *this = (uint64_t)(bool)val; + } + + INLINE void write(const ap_private<_AP_W, _AP_S>& op2) volatile { + *this = (op2); + } + + //Explicit conversions to C interger types + //----------------------------------------------------------- + ValType getVal() const { + return VAL; + } + operator ValType () const { + return getVal(); + } + INLINE int to_int() const { + // ap_private<64 /* _AP_W */, _AP_S> res(V); + return (int) getVal(); + } + + INLINE unsigned to_uint() const { + return (unsigned) getVal(); + } + + INLINE long to_long() const { + return (long) getVal(); + } + + INLINE unsigned long to_ulong() const { + return (unsigned long) getVal(); + } + + INLINE ap_slong to_int64() const { + return (ap_slong) getVal(); + } + + INLINE ap_ulong to_uint64() const { + return (ap_ulong) getVal(); + } + + INLINE double to_double() const { + if (isNegative()) + return roundToDouble(true); + else + return roundToDouble(false); + } + + INLINE bool isMinValue() const { return VAL == 0;} + template INLINE ap_private& operator&=(const ap_private<_AP_W1, _AP_S1>& RHS) { + VAL = VAL&RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + + template INLINE ap_private& operator|=(const ap_private<_AP_W1, _AP_S1>& RHS) { + VAL = VAL|RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + + template INLINE ap_private& operator^=(const ap_private<_AP_W1, _AP_S1>& RHS){ + VAL = VAL^RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + + template INLINE ap_private& operator*=(const ap_private<_AP_W1, _AP_S1>& RHS){ + VAL = VAL*RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + + template INLINE ap_private& operator+=(const ap_private<_AP_W1, _AP_S1>& RHS){ + VAL = VAL+RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + + template INLINE ap_private& operator-=(const ap_private<_AP_W1, _AP_S1>& RHS){ + VAL = VAL-RHS.pVal[0]; + clearUnusedBits(); + return *this; + } + INLINE const ap_private& operator<<=(uint32_t shiftAmt) { VAL<<=shiftAmt; clearUnusedBits(); return *this; } + + template INLINE typename RType<_AP_W1, _AP_S1>::logic operator&(const ap_private<_AP_W1, _AP_S1>& RHS) const { + if (RType<_AP_W1, _AP_S1>::logic_w <= 64) { + typename RType<_AP_W1, _AP_S1>::logic Ret(VAL & RHS.VAL); + return Ret; + } else { + typename RType<_AP_W1, _AP_S1>::logic Ret = *this; + return Ret & RHS; + } + } + + template INLINE typename RType<_AP_W1, _AP_S1>::logic operator^(const ap_private<_AP_W1, _AP_S1>& RHS) const { + if (RType<_AP_W1, _AP_S1>::logic_w <= 64) { + typename RType<_AP_W1, _AP_S1>::logic Ret(VAL ^ RHS.VAL); + return Ret; + } else { + typename RType<_AP_W1, _AP_S1>::logic Ret = *this; + return Ret ^ RHS; + } + } + + template INLINE typename RType<_AP_W1, _AP_S1>::logic operator|(const ap_private<_AP_W1, _AP_S1>& RHS) const { + if (RType<_AP_W1, _AP_S1>::logic_w <= 64) { + typename RType<_AP_W1, _AP_S1>::logic Ret(VAL | RHS.VAL); + return Ret; + } else { + typename RType<_AP_W1, _AP_S1>::logic Ret = *this; + return Ret | RHS; + } + } + + INLINE ap_private<_AP_W, _AP_S> And(const ap_private<_AP_W, _AP_S>& RHS) const { + return ap_private<_AP_W, _AP_S>(VAL & RHS.VAL); + } + + INLINE ap_private<_AP_W, _AP_S> Or(const ap_private<_AP_W, _AP_S>& RHS) const { + return ap_private<_AP_W, _AP_S>(VAL | RHS.VAL); + } + + INLINE ap_private<_AP_W, _AP_S> Xor(const ap_private<_AP_W, _AP_S>& RHS) const { + return ap_private<_AP_W, _AP_S>(VAL ^ RHS.VAL); + } +#if 1 + template + INLINE typename RType<_AP_W1, _AP_S1>::mult operator*(const ap_private<_AP_W1, _AP_S1>& RHS) const { + if (RType<_AP_W1, _AP_S1>::mult_w <= 64) { + typename RType<_AP_W1, _AP_S1>::mult Result(VAL * RHS.VAL); + return Result; + } else { + typename RType<_AP_W1, _AP_S1>::mult Result = typename RType<_AP_W1, _AP_S1>::mult(*this); + Result *= RHS; + return Result; + } + } +#endif + INLINE ap_private<_AP_W, _AP_S> Mul(const ap_private<_AP_W, _AP_S>& RHS) const { + return ap_private<_AP_W, _AP_S>(VAL * RHS.VAL); + } + + INLINE ap_private<_AP_W, _AP_S> Add(const ap_private<_AP_W, _AP_S>& RHS) const { + return ap_private<_AP_W, _AP_S>(VAL + RHS.VAL); + } + + INLINE ap_private<_AP_W, _AP_S> Sub(const ap_private<_AP_W, _AP_S>& RHS) const { + return ap_private<_AP_W, _AP_S>(VAL - RHS.VAL); + } + +#if 1 + INLINE ap_private& operator&=(uint64_t RHS) { VAL &= RHS; clearUnusedBits(); return *this;} + INLINE ap_private& operator|=(uint64_t RHS) { VAL |= RHS; clearUnusedBits(); return *this;} + INLINE ap_private& operator^=(uint64_t RHS){ VAL ^= RHS; clearUnusedBits(); return *this;} + INLINE ap_private& operator*=(uint64_t RHS){ VAL *= RHS; clearUnusedBits(); return *this; } + INLINE ap_private& operator+=(uint64_t RHS){ VAL += RHS; clearUnusedBits(); return *this;} + INLINE ap_private& operator-=(uint64_t RHS){ VAL -= RHS; clearUnusedBits(); return *this; } + INLINE ap_private operator&(uint64_t RHS) const { return ap_private(VAL & RHS); } + INLINE ap_private operator|(uint64_t RHS) const { return ap_private(VAL | RHS); } + INLINE ap_private operator^(uint64_t RHS) const { return ap_private(VAL ^ RHS); } + INLINE ap_private operator*(uint64_t RHS) const { return ap_private(VAL * RHS); } + INLINE ap_private operator/(uint64_t RHS) const { return ap_private(VAL / RHS); } + INLINE ap_private operator+(uint64_t RHS) const { return ap_private(VAL + RHS); } + INLINE ap_private operator-(uint64_t RHS) const { return ap_private(VAL - RHS); } +#endif + INLINE bool isMinSignedValue() const { + static const uint64_t min_mask = ~(~0ULL << (_AP_W-1)); + return BitWidth == 1 ? VAL == 1 : + (ap_private_ops::isNegative<_AP_W>(*this) && ((min_mask & VAL)==0)); + } + +#if 1 + + template INLINE + typename RType<_AP_W1,_AP_S1>::plus operator+(const ap_private<_AP_W1, _AP_S1>& RHS) const { + if (RType<_AP_W1,_AP_S1>::plus_w <=64) + return typename RType<_AP_W1,_AP_S1>::plus(RType<_AP_W1,_AP_S1>::plus_s ? int64_t(VAL+RHS.VAL):uint64_t(VAL+RHS.VAL)); + typename RType<_AP_W1,_AP_S1>::plus Result=RHS; + Result += VAL; + return Result; + } + + template INLINE + typename RType<_AP_W1,_AP_S1>::minus operator-(const ap_private<_AP_W1, _AP_S1>& RHS) const { + if (RType<_AP_W1,_AP_S1>::minus_w <=64) + return typename RType<_AP_W1,_AP_S1>::minus(int64_t(VAL-RHS.VAL)); + typename RType<_AP_W1,_AP_S1>::minus Result=*this; + Result -= RHS; + return Result; + } +#endif // #if 1 + + INLINE ap_private& flip() { + VAL = (~0ULL^VAL)&mask; + clearUnusedBits(); + return *this; + } + + uint32_t countPopulation() const { return CountPopulation_64(VAL);} + uint32_t countLeadingZeros() const { + int remainder = BitWidth % APINT_BITS_PER_WORD; + int excessBits = (APINT_BITS_PER_WORD - remainder) % APINT_BITS_PER_WORD; + //enum { remainder = BitWidth % APINT_BITS_PER_WORD, excessBits = APINT_BITS_PER_WORD - remainder}; + uint32_t Count = CountLeadingZeros_64(VAL); + if (Count) + Count-=excessBits; + return AESL_std::min(Count, (uint32_t)_AP_W); + } + + /// HiBits - This function returns the high "numBits" bits of this ap_private. + ap_private<_AP_W, _AP_S, 1> getHiBits(uint32_t numBits) const { + ap_private<_AP_W, _AP_S, 1> ret(*this); + ret = (ret)>>(BitWidth - numBits); + return ret; + } + + /// LoBits - This function returns the low "numBits" bits of this ap_private. + ap_private<_AP_W, _AP_S, 1> getLoBits(uint32_t numBits) const { + ap_private<_AP_W, _AP_S, 1> ret((VAL) << (BitWidth - numBits)); + ret = (ret)>>(BitWidth - numBits); + return ret; + //return ap_private(numBits, (VAL << (BitWidth - numBits))>> (BitWidth - numBits)); + } + + ap_private<_AP_W, _AP_S,1>& set(uint32_t bitPosition) { + VAL |= (1ULL << (bitPosition)); + clearUnusedBits(); + return *this; // clearUnusedBits(); + } + + void set() { + VAL = ~0ULL; + clearUnusedBits(); + } + + template + INLINE void set(const ap_private<_AP_W3, false> & val) { + operator = (ap_private<_AP_W3, _AP_S>(val)); + } + + INLINE void set(const ap_private & val) { + operator = (val); + } + + bool operator[](uint32_t bitPosition) const { + return (((1ULL << (bitPosition)) & VAL) != 0); + } + + INLINE void clearUnusedBits(void) { + enum { excess_bits = (_AP_W%APINT_BITS_PER_WORD) ? APINT_BITS_PER_WORD -_AP_W%APINT_BITS_PER_WORD : 0}; + VAL = _AP_S ? ((((int64_t)VAL)<<(excess_bits))>> (excess_bits)) : (excess_bits ? ((VAL)<<(excess_bits))>>(excess_bits) : VAL); + } + + INLINE void clearUnusedBitsToZero(void) { + enum { excess_bits = (_AP_W%APINT_BITS_PER_WORD) ? APINT_BITS_PER_WORD -_AP_W%APINT_BITS_PER_WORD : 0}; + static uint64_t mask = ~0ULL >> (excess_bits); + VAL &= mask; + } + + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1> udiv(const ap_private<_AP_W, _AP_S1>& RHS) const { + return ap_private<_AP_W, _AP_S||_AP_S1>(VAL / RHS.VAL); + } + + INLINE ap_private udiv(uint64_t RHS) const { + return ap_private(VAL / RHS); + } + + /// Signed divide this ap_private by ap_private RHS. + /// @brief Signed division function for ap_private. + template + INLINE ap_private<_AP_W, _AP_S||_AP_S1> sdiv(const ap_private<_AP_W, _AP_S1> & RHS) const { + if (isNegative()) + if (RHS.isNegative()) + return (-(*this)).udiv(-RHS); + else + return -((-(*this)).udiv(RHS)); + else if (RHS.isNegative()) + return -(this->udiv(-RHS)); + return this->udiv(RHS); + } + + /// Signed divide this ap_private by ap_private RHS. + /// @brief Signed division function for ap_private. + INLINE ap_private sdiv(int64_t RHS) const { + if (isNegative()) + if (RHS<0) + return (-(*this)).udiv(-RHS); + else + return -((-(*this)).udiv(RHS)); + else if (RHS<0) + return -(this->udiv(-RHS)); + return this->udiv(RHS); + } + + template + INLINE ap_private urem(const ap_private<_AP_W, _AP_S2>& RHS) const { + assert(RHS.VAL != 0 && "Divide by 0"); + return ap_private(VAL%RHS.VAL); + } + + INLINE ap_private urem(uint64_t RHS) const { + assert(RHS != 0 && "Divide by 0"); + return ap_private(VAL%RHS); + } + + /// Signed remainder operation on ap_private. + /// @brief Function for signed remainder operation. + template + INLINE ap_private srem(const ap_private<_AP_W, _AP_S2>& RHS) const { + if (isNegative()) { + ap_private lhs = -(*this); + if (RHS.isNegative()) { + ap_private rhs = -RHS; + return -(lhs.urem(rhs)); + } else + return -(lhs.urem(RHS)); + } else if (RHS.isNegative()) { + ap_private rhs = -RHS; + return this->urem(rhs); + } + return this->urem(RHS); + } + + /// Signed remainder operation on ap_private. + /// @brief Function for signed remainder operation. + INLINE ap_private srem(int64_t RHS) const { + if (isNegative()) + if (RHS<0) + return -((-(*this)).urem(-RHS)); + else + return -((-(*this)).urem(RHS)); + else if (RHS<0) + return this->urem(-RHS); + return this->urem(RHS); + } + + INLINE static void udivrem(const ap_private &LHS, const ap_private &RHS, + ap_private &Quotient, ap_private &Remainder){ + assert(RHS!=0 && "Divide by 0"); + Quotient = LHS.VAl/RHS.VAl; + Remainder = LHS.VAL % RHS.VAL; + } + + INLINE static void udivrem(const ap_private &LHS, uint64_t RHS, + ap_private &Quotient, ap_private &Remainder){ + assert(RHS!=0 && "Divide by 0"); + Quotient = LHS.VAl/RHS; + Remainder = LHS.VAL % RHS; + } + + INLINE static void sdivrem(const ap_private &LHS, const ap_private &RHS, + ap_private &Quotient, ap_private &Remainder) { + if (LHS.isNegative()) { + if (RHS.isNegative()) + ap_private::udivrem(-LHS, -RHS, Quotient, Remainder); + else + ap_private::udivrem(-LHS, RHS, Quotient, Remainder); + Quotient = -Quotient; + Remainder = -Remainder; + } else if (RHS.isNegative()) { + ap_private::udivrem(LHS, -RHS, Quotient, Remainder); + Quotient = -Quotient; + } else { + ap_private::udivrem(LHS, RHS, Quotient, Remainder); + } + } + + INLINE static void sdivrem(const ap_private &LHS, int64_t RHS, + ap_private &Quotient, ap_private &Remainder) { + if (LHS.isNegative()) { + if (RHS<0) + ap_private::udivrem(-LHS, -RHS, Quotient, Remainder); + else + ap_private::udivrem(-LHS, RHS, Quotient, Remainder); + Quotient = -Quotient; + Remainder = -Remainder; + } else if (RHS<0) { + ap_private::udivrem(LHS, -RHS, Quotient, Remainder); + Quotient = -Quotient; + } else { + ap_private::udivrem(LHS, RHS, Quotient, Remainder); + } + } + + template INLINE bool eq(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return (*this) == RHS; + } + + template INLINE bool ne(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return !((*this) == RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// the validity of the less-than relationship. + /// @returns true if *this < RHS when both are considered unsigned. + /// @brief Unsigned less than comparison + template INLINE bool ult(const ap_private<_AP_W1, _AP_S1, 1>& RHS) const { + uint64_t lhsZext = ((uint64_t(VAL)) << (64-_AP_W)) >> (64-_AP_W); + uint64_t rhsZext = ((uint64_t(RHS.VAL)) << (64-_AP_W1)) >> (64-_AP_W1); + return lhsZext < rhsZext; + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the less-than relationship. + /// @returns true if *this < RHS when both are considered signed. + /// @brief Signed less than comparison + template INLINE bool slt(const ap_private<_AP_W1, _AP_S1, 1>& RHS) const { + int64_t lhsSext = ((int64_t(VAL)) << (64-_AP_W)) >> (64-_AP_W); + int64_t rhsSext = ((int64_t(RHS.VAL)) << (64-_AP_W1)) >> (64-_AP_W1); + return lhsSext < rhsSext; + } + + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// validity of the less-or-equal relationship. + /// @returns true if *this <= RHS when both are considered unsigned. + /// @brief Unsigned less or equal comparison + template INLINE bool ule(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return ult(RHS) || eq(RHS); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the less-or-equal relationship. + /// @returns true if *this <= RHS when both are considered signed. + /// @brief Signed less or equal comparison + template INLINE bool sle(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return slt(RHS) || eq(RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// the validity of the greater-than relationship. + /// @returns true if *this > RHS when both are considered unsigned. + /// @brief Unsigned greather than comparison + template INLINE bool ugt(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return !ult(RHS) && !eq(RHS); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// the validity of the greater-than relationship. + /// @returns true if *this > RHS when both are considered signed. + /// @brief Signed greather than comparison + template INLINE bool sgt(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return !slt(RHS) && !eq(RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// validity of the greater-or-equal relationship. + /// @returns true if *this >= RHS when both are considered unsigned. + /// @brief Unsigned greater or equal comparison + template INLINE bool uge(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return !ult(RHS); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the greater-or-equal relationship. + /// @returns true if *this >= RHS when both are considered signed. + /// @brief Signed greather or equal comparison + template INLINE bool sge(const ap_private<_AP_W1, _AP_S1>& RHS) const { + return !slt(RHS); + } + + INLINE ap_private abs() const { + if (isNegative()) + return -(*this); + return *this; + } + + ap_private<_AP_W, false> get() const { + ap_private<_AP_W,false> ret(*this); + return ret; + } + + INLINE static uint32_t getBitsNeeded(const char* str, uint32_t slen, uint8_t radix) { + return _AP_W; + } + + INLINE uint32_t getActiveBits() const { + uint32_t bits=_AP_W - countLeadingZeros(); + return bits?bits:1; + } + + INLINE double roundToDouble(bool isSigned=false) const { + const static uint64_t mask = ~0ULL << (APINT_BITS_PER_WORD - _AP_W); + return double(VAL); + } + + INLINE unsigned length() const { return _AP_W; } + + /*Reverse the contents of ap_private instance. I.e. LSB becomes MSB and vise versa*/ + INLINE ap_private& reverse () { + for (int i = 0; i < _AP_W/2; ++i) { + bool tmp = operator[](i); + if (operator[](_AP_W - 1 - i)) + set(i); + else + clear(i); + if (tmp) + set(_AP_W - 1 - i); + else + clear(_AP_W - 1 - i); + } + clearUnusedBits(); + return *this; + } + + /*Return true if the value of ap_private instance is zero*/ + INLINE bool iszero () const { + return isMinValue(); + } + + /* x < 0 */ + INLINE bool sign () const { + if (isNegative()) + return true; + return false; + } + + /* x[i] = !x[i] */ + INLINE void invert (int i) { + assert( i >= 0 && "Attempting to read bit with negative index"); + assert( i < _AP_W && "Attempting to read bit beyond MSB"); + flip(i); + } + + /* x[i] */ + INLINE bool test (int i) const { + assert( i >= 0 && "Attempting to read bit with negative index"); + assert( i < _AP_W && "Attempting to read bit beyond MSB"); + return operator[](i); + } + + //This is used for sc_lv and sc_bv, which is implemented by sc_uint + //Rotate an ap_private object n places to the left + INLINE void lrotate(int n) { + assert( n >= 0 && "Attempting to shift negative index"); + assert( n < _AP_W && "Shift value larger than bit width"); + operator = (shl(n) | lshr(_AP_W - n)); + } + + //This is used for sc_lv and sc_bv, which is implemented by sc_uint + //Rotate an ap_private object n places to the right + INLINE void rrotate(int n) { + assert( n >= 0 && "Attempting to shift negative index"); + assert( n < _AP_W && "Shift value larger than bit width"); + operator = (lshr(n) | shl(_AP_W - n)); + } + + //Set the ith bit into v + INLINE void set (int i, bool v) { + assert( i >= 0 && "Attempting to write bit with negative index"); + assert( i < _AP_W && "Attempting to write bit beyond MSB"); + v ? set(i) : clear(i); + } + + //Set the ith bit into v + INLINE void set_bit (int i, bool v) { + assert( i >= 0 && "Attempting to write bit with negative index"); + assert( i < _AP_W && "Attempting to write bit beyond MSB"); + v ? set(i) : clear(i); + } + + //Get the value of ith bit + INLINE bool get_bit (int i) const { + assert( i >= 0 && "Attempting to read bit with negative index"); + assert( i < _AP_W && "Attempting to read bit beyond MSB"); + return operator [](i); + } + + //complements every bit + INLINE void b_not() { + flip(); + } + + //Binary Arithmetic + //----------------------------------------------------------- +#define OP_BIN_AP(Sym,Rty, Fun) \ + template \ + INLINE \ + typename RType<_AP_W2,_AP_S2>::Rty \ + operator Sym (const ap_private<_AP_W2,_AP_S2>& op) const { \ + typename RType<_AP_W2,_AP_S2>::Rty lhs(*this); \ + typename RType<_AP_W2,_AP_S2>::Rty rhs(op); \ + return lhs.Fun(rhs); \ + } \ + + ///Bitwise and, or, xor + //OP_BIN_AP(&,logic, And) + //OP_BIN_AP(|,logic, Or) + //OP_BIN_AP(^,logic, Xor) + +#undef OP_BIN_AP + template + INLINE typename RType<_AP_W2,_AP_S2>::div + operator / (const ap_private<_AP_W2,_AP_S2>&op) const { + ap_private lhs=ap_private(*this); + ap_private rhs=ap_private(op); + return typename RType<_AP_W2,_AP_S2>::div((_AP_S||_AP_S2)?lhs.sdiv(rhs):lhs.udiv(rhs)); + } + + + template + INLINE typename RType<_AP_W2,_AP_S2>::mod + operator % (const ap_private<_AP_W2,_AP_S2>&op) const { + ap_private lhs=*this; + ap_private rhs=op; + typename RType<_AP_W2,_AP_S2>::mod res = typename RType<_AP_W2,_AP_S2>::mod (_AP_S?lhs.srem(rhs):lhs.urem(rhs)); + return res; + } + + +#define OP_ASSIGN_AP_2(Sym) \ + template \ + INLINE ap_private<_AP_W, _AP_S>& operator Sym##=(const ap_private<_AP_W2,_AP_S2>& op) \ + { \ + *this=operator Sym (op); \ + return *this; \ + } \ + + OP_ASSIGN_AP_2(/) + OP_ASSIGN_AP_2(%) +#undef OP_ASSIGN_AP_2 + + ///Bitwise assign: and, or, xor + //------------------------------------------------------------- + // OP_ASSIGN_AP(&) + // OP_ASSIGN_AP(^) + // OP_ASSIGN_AP(|) +#undef OP_ASSIGN_AP +#if 1 + + template + INLINE ap_private<_AP_W, _AP_S> + operator << (const ap_private<_AP_W2, _AP_S2>& op2) const { + uint32_t sh=op2.to_uint(); + return *this << sh; + } + + INLINE ap_private<_AP_W, _AP_S> + operator << (uint32_t sh) const { + return shl(sh); + } + +#endif + + template + INLINE ap_private<_AP_W, _AP_S> + operator >> (const ap_private<_AP_W2, _AP_S2>& op2) const { + uint32_t sh = op2.to_uint(); + return *this >> sh; + } + + INLINE ap_private<_AP_W, _AP_S> + operator >>(uint32_t sh) const { + ap_private<_AP_W, _AP_S> r(*this); + bool overflow=(sh>=_AP_W); + bool neg_v=r.isNegative(); + if(_AP_S) { + if(overflow) + neg_v?r.set():r.clear(); + else + return r.ashr(sh); + } else { + if(overflow) + r.clear(); + else + return r.lshr(sh); + } + return r; + } + + ///Shift assign + //------------------------------------------------------------------ +#define OP_ASSIGN_AP_3_SINGLE(Sym) \ + template \ + INLINE ap_private<_AP_W, _AP_S>& operator Sym##=(const ap_private<_AP_W2,_AP_S2>& op) \ + { \ + *this=operator Sym (op.getVal()); \ + return *this; \ + } + OP_ASSIGN_AP_3_SINGLE(>>) +#undef OP_ASSIGN_AP_3_SINGLE + + ///Comparisons + //----------------------------------------------------------------- + template + INLINE bool operator != (const ap_private<_AP_W2, _AP_S2, 1>& op) const { + return !(*this==op); + } + + template + INLINE bool operator > (const ap_private<_AP_W2, _AP_S2, 1>& op) const { + return op < *this; + } + + template + INLINE bool operator <= (const ap_private<_AP_W2, _AP_S2, 1>& op) const { + return !(*this>op); + } + + template + INLINE bool operator < (const ap_private<_AP_W2, _AP_S2, 1>& op) const { + enum { _AP_MAX_W = AP_MAX(_AP_W+(_AP_S||_AP_S2),_AP_W2+(_AP_S||_AP_S2))}; + ap_private<_AP_MAX_W, _AP_S> lhs(*this); + ap_private<_AP_MAX_W, _AP_S2> rhs(op); + if (_AP_S == _AP_S2) + return _AP_S?lhs.slt(rhs):lhs.ult(rhs); + else if (_AP_W < 32 && _AP_W2 < 32) + return lhs.slt(rhs); + else + if (_AP_S) + if (_AP_W2 >= _AP_W) + return lhs.ult(rhs); + else + return lhs.slt(rhs); + else + if (_AP_W >= _AP_W2) + return lhs.ult(rhs); + else + return lhs.slt(rhs); + } + + template + INLINE bool operator >=(const ap_private<_AP_W2, _AP_S2, 1>& op) const { + return !(*this + INLINE bool operator == (const ap_private<_AP_W2, _AP_S2, _AP_N2>& op) const { + return op == *this; + } + + template + INLINE bool operator != (const ap_private<_AP_W2, _AP_S2, _AP_N2>& op) const { + return !(op==*this); + } + + template + INLINE bool operator > (const ap_private<_AP_W2, _AP_S2, _AP_N2>& op) const { + return op < (*this); + } + + template + INLINE bool operator <= (const ap_private<_AP_W2, _AP_S2, _AP_N2>& op) const { + return op >= *this; + } + + template + INLINE bool operator <(const ap_private<_AP_W2, _AP_S2, _AP_N2>& op) const { + return op > *this; + } + + template + INLINE bool operator >=(const ap_private<_AP_W2,_AP_S2,_AP_N2>& op) const { + return op <= *this; + } + ///Bit and Part Select + //-------------------------------------------------------------- + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (int Hi, int Lo) { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (int Hi, int Lo) const { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(const_cast*>(this), Hi, Lo); + } + + INLINE ap_range_ref<_AP_W,_AP_S> + range (int Hi, int Lo) const { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>((const_cast*> (this)), Hi, Lo); + } + + INLINE ap_range_ref<_AP_W,_AP_S> + range (int Hi, int Lo) { + assert((Hi < _AP_W) && (Lo < _AP_W)&&"Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + range (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(this, Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + range (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) const { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + assert((Hi < _AP_W) && (Lo < _AP_W) && "Out of bounds in range()"); + return ap_range_ref<_AP_W,_AP_S>(const_cast(this), Hi, Lo); + } + + template + INLINE ap_range_ref<_AP_W,_AP_S> + operator () (const ap_private<_AP_W2, _AP_S2> &HiIdx, + const ap_private<_AP_W3, _AP_S3> &LoIdx) const { + int Hi = HiIdx.to_int(); + int Lo = LoIdx.to_int(); + return this->range(Hi, Lo); + } + + + INLINE ap_bit_ref<_AP_W,_AP_S> operator [] (uint32_t index) { + assert(index >= 0&&"Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S> (*this, (int)index); + } + + template + INLINE ap_bit_ref<_AP_W,_AP_S> operator [] (const ap_private<_AP_W2,_AP_S2> &index) { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S>( *this, index.to_int() ); + } + + template + INLINE bool operator [] (const ap_private<_AP_W2,_AP_S2>& index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + ap_bit_ref<_AP_W,_AP_S> br =operator [] (index); + return br.to_bool(); + } + + INLINE ap_bit_ref<_AP_W,_AP_S> bit (int index) { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S>( *this, index ); + } + + template + INLINE ap_bit_ref<_AP_W,_AP_S> bit (const ap_private<_AP_W2,_AP_S2> &index) { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W &&"Attempting to read bit beyond MSB"); + return ap_bit_ref<_AP_W,_AP_S>( *this, index.to_int() ); + } + + INLINE bool bit (int index) const { + assert(index >= 0 && "Attempting to read bit with negative index"); + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + ap_bit_ref<_AP_W,_AP_S> br(const_cast*>(this), index); + return br.to_bool(); + } + + template + INLINE bool bit (const ap_private<_AP_W2,_AP_S2>& index) const { + assert(index < _AP_W && "Attempting to read bit beyond MSB"); + ap_bit_ref<_AP_W,_AP_S> br = bit(index); + return br.to_bool(); + } + + template + INLINE ap_concat_ref<_AP_W,ap_private<_AP_W, _AP_S>,_AP_W2,ap_private<_AP_W2,_AP_S2> > concat(const ap_private<_AP_W2,_AP_S2>& a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_private<_AP_W2,_AP_S2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W,ap_private<_AP_W, _AP_S>,_AP_W2,ap_private<_AP_W2,_AP_S2> > concat(ap_private<_AP_W2,_AP_S2>& a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_private<_AP_W2,_AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (const ap_private<_AP_W2, _AP_S2>& a2) const { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(const_cast& >(*this), const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (const ap_private<_AP_W2, _AP_S2>& a2) { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(*this, const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (ap_private<_AP_W2, _AP_S2>& a2) const { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(const_cast& >(*this), a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > + operator, (ap_private<_AP_W2, _AP_S2>& a2) { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, + _AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > + operator, (const ap_range_ref<_AP_W2, _AP_S2> &a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, + ap_range_ref<_AP_W2, _AP_S2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > + operator, (ap_range_ref<_AP_W2, _AP_S2> &a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, + ap_range_ref<_AP_W2, _AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, ap_bit_ref<_AP_W2, _AP_S2> > + operator, (const ap_bit_ref<_AP_W2, _AP_S2> &a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, + ap_bit_ref<_AP_W2, _AP_S2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, ap_bit_ref<_AP_W2, _AP_S2> > + operator, (ap_bit_ref<_AP_W2, _AP_S2> &a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, + ap_bit_ref<_AP_W2, _AP_S2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > + operator, (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) const { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > + operator, (ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) { + return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2+_AP_W3, + ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) const { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<_AP_W, ap_private, _AP_W2, af_range_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, a2); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) const { + return ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(const_cast& >(*this), + const_cast& >(a2)); + } + + template + INLINE ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > + operator, (af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, + _AP_O2, _AP_N2> &a2) { + return ap_concat_ref<_AP_W, ap_private, 1, af_bit_ref<_AP_W2, + _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, a2); + } + + template + INLINE ap_private + operator & (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) { + return *this & a2.get(); + } + + template + INLINE ap_private + operator | (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) { + return *this | a2.get(); + } + + template + INLINE ap_private + operator ^ (const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) { + return *this ^ a2.get(); + } + + + //Reduce operation + //----------------------------------------------------------- + INLINE bool and_reduce() const { + return (VAL & mask) == mask; + } + + INLINE bool nand_reduce() const { + return (VAL & mask) != mask; + } + + INLINE bool or_reduce() const { + return (bool)VAL; + } + + INLINE bool nor_reduce() const { + return VAL==0; + } + + INLINE bool xor_reduce() const { + unsigned int i=countPopulation(); + return (i%2)?true:false; + } + + INLINE bool xnor_reduce() const { + unsigned int i=countPopulation(); + return (i%2)?false:true; + } + + INLINE std::string to_string(uint8_t radix=2, bool sign=false) const { + return toString(radix, radix==10?_AP_S:sign); + } +}; +template +std::string ap_private<_AP_W, _AP_S, 1>::toString(uint8_t radix, bool wantSigned) const { + assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) && + "Radix should be 2, 8, 10, or 16!"); + static const char *digits[] = { + "0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f" + }; + std::string result; + if (radix != 10) { + // For the 2, 8 and 16 bit cases, we can just shift instead of divide + // because the number of bits per digit (1,3 and 4 respectively) divides + // equaly. We just shift until there value is zero. + + // First, check for a zero value and just short circuit the logic below. + if (*this == (uint64_t)(0)) + result = "0"; + else { + ap_private<_AP_W, false, 1> tmp(*this); + size_t insert_at = 0; + if (wantSigned && isNegative()) { + // They want to print the signed version and it is a negative value + // Flip the bits and add one to turn it into the equivalent positive + // value and put a '-' in the result. + tmp.flip(); + tmp++; + result = "-"; + insert_at = 1; + } + // Just shift tmp right for each digit width until it becomes zero + uint32_t shift = (radix == 16 ? 4 : (radix == 8 ? 3 : 1)); + uint64_t mask = radix - 1; + ap_private<_AP_W, false, 1> zero(0); + while (tmp.ne(zero)) { + unsigned digit = (unsigned)(tmp.VAL & mask); + result.insert(insert_at, digits[digit]); + tmp = tmp.lshr(shift); + } + } + return result; + } + + ap_private<_AP_W, false, 1> tmp(*this); + ap_private<6, false, 1> divisor(radix); + ap_private<_AP_W, _AP_S, 1> zero(0); + size_t insert_at = 0; + if (wantSigned && isNegative()) { + // They want to print the signed version and it is a negative value + // Flip the bits and add one to turn it into the equivalent positive + // value and put a '-' in the result. + tmp.flip(); + tmp++; + result = "-"; + insert_at = 1; + } + if (tmp == ap_private<_AP_W, false, 1>(0ULL)) + result = "0"; + else while (tmp.ne(zero)) { + ap_private<_AP_W, false, 1> APdigit = tmp%divisor; + ap_private<_AP_W, false, 1> tmp2 = tmp/divisor; + uint32_t digit = (uint32_t)(APdigit.getZExtValue()); + assert(digit < radix && "divide failed"); + result.insert(insert_at,digits[digit]); + tmp = tmp2; + } + return result; + +} + +#endif /* #ifndef LLVM_SUPPORT_MATHEXTRAS_H */ \ No newline at end of file diff --git a/hls_2018/router_02_boardstr/main.cpp b/hls_2018/router_02_boardstr/main.cpp new file mode 100755 index 0000000..2de79fc --- /dev/null +++ b/hls_2018/router_02_boardstr/main.cpp @@ -0,0 +1,99 @@ +/** + * main.cpp + * + * for Vivado HLS + */ + +#ifdef SOFTWARE +#include "ap_int.h" +#else +#include +#endif + +#ifdef CALCTIME +#include +#include +#endif + +#include "router.hpp" + +#define PRINT_SOLUTION + + +int main(int argc, char *argv[]) { + using namespace std; + + // Test data // + // NL_Q00.txt + //char boardstr[BOARDSTR_SIZE] = "X10Y05Z3L0000107041L0004107002L0102102021L0900100003"; + // NL_Q06.txt + char boardstr[BOARDSTR_SIZE] = "X10Y18Z2L0900109002L0901105012L0902103052L0903103062L0904100102L0905106012L0906109022L0717109102L0808109112L0017209172L0401200072L0912208152L0009201092L0709209092L0901206052L0309204092L0701209072L0101201022L0011202152L0016202162"; + // NL_Q08.txt + //char boardstr[BOARDSTR_SIZE] = "X17Y20Z2L0000103022L1603115052L0916107032L0302108012L1104111042L1002100002L0919116162L1616113182L1001115012L0500201182L1603213152L0600210022"; + char boardstr_high[BOARDSTR_SIZE] = {}; + + // Read boardstr from command line + if (1 < argc) { + // From stdin + if(argv[1][0]!='X') + { + char* c_p=fgets(boardstr, BOARDSTR_SIZE, stdin); + int length=strlen(c_p); + boardstr[length-1]=0; + } + else + { + strcpy(boardstr, argv[1]); + } + } + + // Seed value + int seed = 12345; + if (2 < argc) { + seed = atoi(argv[2]); + } + +#ifdef PRINT_SOLUTION + int size_x = (boardstr[1] - '0') * 10 + (boardstr[2] - '0'); + int size_y = (boardstr[4] - '0') * 10 + (boardstr[5] - '0'); + int size_z = (boardstr[7] - '0'); +#endif + + // Solver + ap_int<32> status; + clock_t clock_start, clock_done; + clock_start = clock(); + bool result = pynqrouter(boardstr, boardstr_high, seed, &status); + clock_done = clock(); + if (result) { + cout << endl << "Test Passed!" << endl; + } else { + cout << endl << "Test Failed!" << endl; + } + cout << "status = " << (int)status << endl; + cout << "elapsed = " << ((double)(clock_done - clock_start) / CLOCKS_PER_SEC) << endl << endl; + +#ifdef PRINT_SOLUTION + cout << "SOLUTION" << endl; + cout << "========" << endl; + cout << "SIZE " << size_x << "X" << size_y << "X" << size_z << endl; + for (int z = 0; z < size_z; z++) { + cout << "LAYER " << (z + 1) << endl; + for (int y = 0; y < size_y; y++) { + for (int x = 0; x < size_x; x++) { + if (x != 0) { + cout << ","; + } + int i = ((x * MAX_WIDTH + y) << BITWIDTH_Z) | z; + unsigned int num = (unsigned char)(boardstr[i]) + ((unsigned char)(boardstr_high[i]) << 8); + cout << setfill('0') << setw(3) << right << num; + //cout << num; + } + cout << endl; + } + } +#endif + + return 0; +} + diff --git a/hls_2018/router_02_boardstr/router.cpp b/hls_2018/router_02_boardstr/router.cpp new file mode 100755 index 0000000..d40f356 --- /dev/null +++ b/hls_2018/router_02_boardstr/router.cpp @@ -0,0 +1,609 @@ +/** + * router.cpp + * + * for Vivado HLS + */ + +#ifdef SOFTWARE +#include "ap_int.h" +#else +#include +#endif + +#include "./router.hpp" + +// Set weight +ap_uint<8> new_weight(ap_uint<16> x) { +#pragma HLS INLINE + // K. Terada: y = 1~32 (8bit) + ap_uint<8> y; + y = ((x & 255) >> 3) + 1; + return y; +} + + +// Global values +static ap_uint<7> size_x; // X +static ap_uint<7> size_y; // Y +static ap_uint<4> size_z; // Z + +static ap_uint line_num = 0; // #Lines + +#ifdef DEBUG_PRINT +int max_queue_length; // Max length of priority queue +int max_search_count; // Max count of queue pop +int max_buffer_length; // Max length of line buffer +#endif + + +bool pynqrouter(char boardstr[BOARDSTR_SIZE], char boardstr_high[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *status) { +#pragma HLS INTERFACE s_axilite port=boardstr bundle=AXI4LS +#pragma HLS INTERFACE s_axilite port=boardstr_high bundle=AXI4LS +#pragma HLS INTERFACE s_axilite port=seed bundle=AXI4LS +#pragma HLS INTERFACE s_axilite port=status bundle=AXI4LS +#pragma HLS INTERFACE s_axilite port=return bundle=AXI4LS + + // status(0:Solved, 1:Not solved) + *status = -1; + + // For all lines + ap_uint paths[MAX_BUFFER]; // Line buffer + + // For each line + // Note: Should not partition completely + bool adjacents[MAX_LINES]; // Line has adjacent terminals? + ap_uint starts[MAX_LINES]; // Start list + ap_uint goals[MAX_LINES]; // Goal list + ap_uint s_idx[MAX_LINES]; // Start point on line buffer + + ap_uint<8> weights[MAX_CELLS]; // Weight of each cell + // Note: Should not partition weight array + // since each element will be accessed in "random" order + + + // ================================ + // (Step.0) Initialization (BEGIN) + // ================================ + + // Note: Loop counter -> need an extra bit (for condition determination) + + INIT_WEIGHTS: + for (ap_uint i = 0; i < (ap_uint)(MAX_CELLS); i++) { +#pragma HLS UNROLL factor=2 + weights[i] = 1; + } + + /// Parse /// + size_x = (boardstr[1] - '0') * 10 + (boardstr[2] - '0'); + size_y = (boardstr[4] - '0') * 10 + (boardstr[5] - '0'); + size_z = (boardstr[7] - '0'); + + INIT_BOARDS: + for (ap_uint idx = 8; idx < (ap_uint)(BOARDSTR_SIZE); idx+=11) { + + // NULL-terminated + if (boardstr[idx] == 0) break; + + // Start & Goal of each line + ap_uint<7> s_x = (boardstr[idx+1] - '0') * 10 + (boardstr[idx+2] - '0'); + ap_uint<7> s_y = (boardstr[idx+3] - '0') * 10 + (boardstr[idx+4] - '0'); + ap_uint<3> s_z = (boardstr[idx+5] - '0') - 1; + ap_uint<7> g_x = (boardstr[idx+6] - '0') * 10 + (boardstr[idx+7] - '0'); + ap_uint<7> g_y = (boardstr[idx+8] - '0') * 10 + (boardstr[idx+9] - '0'); + ap_uint<3> g_z = (boardstr[idx+10] - '0') - 1; + + ap_uint start_id = (((ap_uint)s_x * MAX_WIDTH + (ap_uint)s_y) << BITWIDTH_Z) | (ap_uint)s_z; + ap_uint goal_id = (((ap_uint)g_x * MAX_WIDTH + (ap_uint)g_y) << BITWIDTH_Z) | (ap_uint)g_z; + starts[line_num] = start_id; + goals[line_num] = goal_id; + weights[start_id] = MAX_WEIGHT; + weights[goal_id] = MAX_WEIGHT; + + // Line has adjacent terminals? + adjacents[line_num] = false; + ap_int<8> dx = (ap_int<8>)g_x - (ap_int<8>)s_x; // Min: -71, Max: 71 (Signed 8bit) + ap_int<8> dy = (ap_int<8>)g_y - (ap_int<8>)s_y; // Min: -71, Max: 71 (Signed 8bit) + ap_int<4> dz = (ap_int<4>)g_z - (ap_int<4>)s_z; // Min: -7, Max: 7 (Signed 4bit) + 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; + } + + line_num++; + } + + // ================================ + // (Step.0) Initialization (END) + // ================================ + +#ifdef DEBUG_PRINT + max_queue_length = 0; + max_search_count = 0; + max_buffer_length = 0; +#endif + + ap_uint pointer = 0; // Pointer for line buffer + + // ================================ + // (Step.1) Initial Routing (BEGIN) + // ================================ + +#ifdef DEBUG_PRINT + cout << "Initial Routing ..." << endl; +#endif + + FIRST_ROUTING: + for (ap_uint i = 0; i < (ap_uint)(line_num); i++) { +#pragma HLS LOOP_TRIPCOUNT min=2 max=999 + + s_idx[i] = pointer; + + if (adjacents[i] == true) continue; // Skip routing + +#ifdef DEBUG_PRINT + //cout << "LINE #" << (int)(i + 1) << endl; +#endif + // Routing + ap_uint dummy = MAX_BUFFER-1; + pointer = search(s_idx[i], &dummy, paths, starts[i], goals[i], weights); + } + + // ================================ + // (Step.1) Initial Routing (END) + // ================================ + + + // Memories for Overlap Check + ap_uint<1> overlap_checks[MAX_CELLS]; +#pragma HLS ARRAY_PARTITION variable=overlap_checks cyclic factor=16 dim=1 + bool has_overlap = false; + + // ================================ + // (Step.2) Rip-up Routing (BEGIN) + // ================================ + +#ifdef DEBUG_PRINT + cout << "Rip-up Routing ..." << endl; +#endif + + ap_uint target = line_num - 1, next_target; + + ROUTING: + for (ap_uint<16> round = 0; round < 32768 /* = (2048 * 16) */; round++) { +#pragma HLS LOOP_TRIPCOUNT min=1 max=32768 + + // Target line + target = round % line_num; + next_target = target + 1; + if (next_target == line_num) next_target = 0; + +#ifdef DEBUG_PRINT + //cout << "(round " << round << ") LINE #" << (int)(target + 1); + //cout << " -> " << pointer << endl; +#endif +#ifdef DEBUG_PRINT + int buffer_length = pointer - s_idx[target]; + if (max_buffer_length < buffer_length) { max_buffer_length = buffer_length; } +#endif + + // Skip routing + if (adjacents[target] == true) { + s_idx[target] = pointer; continue; + } + + + // (Step.2-1) Reset weights of target line + WEIGHT_RESET: + for (ap_uint j = s_idx[target]; j != s_idx[next_target]; j++) { +#pragma HLS UNROLL factor=2 +#pragma HLS LOOP_TRIPCOUNT min=1 max=256 + weights[paths[j]] = 1; + } + + // (Step.2-2) Set weights of non-target lines and terminals + ap_uint<8> current_round_weight = new_weight(round); + WEIGHT_PATH: + for (ap_uint j = s_idx[next_target]; j != pointer; j++) { +#pragma HLS UNROLL factor=2 +#pragma HLS LOOP_TRIPCOUNT min=1 max=8192 + weights[paths[j]] = current_round_weight; + } + WEIGHT_TERMINAL: + for (ap_uint i = 0; i < (ap_uint)(line_num); i++) { +#pragma HLS UNROLL factor=2 +#pragma HLS LOOP_TRIPCOUNT min=2 max=999 + weights[starts[i]] = MAX_WEIGHT; + weights[goals[i]] = MAX_WEIGHT; + } + // Reset weight of start terminal of target line (bug avoiding) + // Restore original settings in (*) + weights[starts[target]] = 1; + + // (Step.2-3) Routing + s_idx[target] = pointer; + ap_uint n_idx = s_idx[next_target]; // For overflow check + pointer = search(s_idx[target], &n_idx, paths, starts[target], goals[target], weights); + //pointer = search(s_idx[target], paths, starts[target], goals[target], weights); + //cout << n_idx << ", " << s_idx[next_target] << endl; + + // (*) + weights[starts[target]] = MAX_WEIGHT; + +#ifdef DEBUG_PRINT + bool ng = false; + for (ap_uint i = 0; i < (ap_uint)(line_num); i++) { + if (weights[starts[i]] != 255 || weights[goals[i]] != 255) { + cout << i << " "; ng = true; + } + } + if(ng) { cout << endl; } +#endif + + // (Step.2-4) Overlap check + has_overlap = false; + if (n_idx != s_idx[next_target]) break; // Overflow check + OVERLAP_RESET: + for (ap_uint i = 0; i < (ap_uint)(MAX_CELLS); i++) { +#pragma HLS UNROLL factor=32 + overlap_checks[i] = 0; + } + OVERLAP_CHECK_LINE: + for (ap_uint i = 0; i < (ap_uint)(line_num); i++) { +#pragma HLS UNROLL factor=2 +#pragma HLS LOOP_TRIPCOUNT min=2 max=999 + overlap_checks[starts[i]] = 1; + overlap_checks[goals[i]] = 1; + } + OVERLAP_CHECK_PATH: + for (ap_uint j = s_idx[next_target]; j != pointer; j++) { +#pragma HLS UNROLL factor=2 +#pragma HLS LOOP_TRIPCOUNT min=1 max=8192 + ap_uint cell_id = paths[j]; + if (overlap_checks[cell_id]) { + has_overlap = true; break; + } + overlap_checks[cell_id] = 1; + } +#ifdef DEBUG_PRINT + if(!has_overlap){ cout << "ROUND: " << round << endl; } +#endif + if (!has_overlap) break; // Finish routing? + } + +#ifdef DEBUG_PRINT + cout << "MAX PQ LENGTH: " << max_queue_length << endl; + cout << "MAX SEARCH COUNT: " << max_search_count << endl; + cout << "MAX BUFFER: " << max_buffer_length << endl; +#endif + + // Not solved + if (has_overlap) { + *status = 1; return false; + } + + // ================================ + // (Step.2) Rip-up Routing (END) + // ================================ + + + // ================================ + // (Step.3) Output (BEGIN) + // ================================ + +#ifdef DEBUG_PRINT + cout << "Output ..." << endl; +#endif + + // Init: Blank = 0 + OUTPUT_INIT: + for (ap_uint i = 0; i < (ap_uint)(MAX_CELLS); i++) { + boardstr[i] = 0; + boardstr_high[i] = 0; + } + // Line + OUTPUT_LINE: + for (ap_uint i = 0; i < (ap_uint)(line_num); i++) { +#pragma HLS LOOP_TRIPCOUNT min=2 max=999 + boardstr[starts[i]] = (i + 1); + boardstr[goals[i]] = (i + 1); + boardstr_high[starts[i]] = (i + 1) >> 8; + boardstr_high[goals[i]] = (i + 1) >> 8; + +/** + cout << "#" << i; + ap_uint<13> start_xy = (ap_uint<13>)(starts[i] >> BITWIDTH_Z); + ap_uint<7> start_x = (ap_uint<7>)(start_xy / MAX_WIDTH); + ap_uint<7> start_y = (ap_uint<7>)(start_xy - start_x * MAX_WIDTH); + ap_uint<3> start_z = (ap_uint<3>)(starts[i] & BITMASK_Z); + ap_uint<13> goal_xy = (ap_uint<13>)(goals[i] >> BITWIDTH_Z); + 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<3> goal_z = (ap_uint<3>)(goals[i] & BITMASK_Z); + cout << "(" << start_x << "," << start_y << "," << start_z << ")->"; + cout << "(" << goal_x << "," << goal_y << "," << goal_z << ")" << endl; +**/ + + ap_uint p1; // p1: s_idx of target + ap_uint p2; // p2: s_idx of next target + p1 = s_idx[i]; + if (i == (ap_uint)(line_num-1)) { + p2 = s_idx[0]; + } + else { + p2 = s_idx[i+1]; + } + if (i == target) { + p2 = pointer; + } + OUTPUT_LINE_PATH: + for (ap_uint j = p1; j != p2; j++) { +#pragma HLS LOOP_TRIPCOUNT min=1 max=256 + boardstr[paths[j]] = (i + 1); + boardstr_high[paths[j]] = (i + 1) >> 8; + +/** + ap_uint<13> trgt_xy = (ap_uint<13>)(paths[j] >> BITWIDTH_Z); + ap_uint<7> trgt_x = (ap_uint<7>)(trgt_xy / MAX_WIDTH); + ap_uint<7> trgt_y = (ap_uint<7>)(trgt_xy - trgt_x * MAX_WIDTH); + ap_uint<3> trgt_z = (ap_uint<3>)(paths[j] & BITMASK_Z); + cout << "(" << trgt_x << "," << trgt_y << "," << trgt_z << ")"; +**/ + + } +/** + cout << endl; +**/ + } + + // ================================ + // (Step.3) Output (END) + // ================================ + + *status = 0; return true; +} + + +// ================================ // +// For Routing +// ================================ // + +// Max: 71, Min: 0 (7bit) +ap_uint<7> abs_uint7(ap_uint<7> a, ap_uint<7> b) { +#pragma HLS INLINE + if (a < b) { return b - a; } + else { return a - b; } +} +// Max: 7, Min: 0 (3bit) +ap_uint<3> abs_uint3(ap_uint<3> a, ap_uint<3> b) { +#pragma HLS INLINE + if (a < b) { return b - a; } + else { return a - b; } +} + +// Reference codes: +// http://lethe2211.hatenablog.com/entry/2014/12/30/011030 +// http://www.redblobgames.com/pathfinding/a-star/implementation.html +// Need to modify "array partition factor" +ap_uint search(ap_uint idx, ap_uint *n_idx, ap_uint paths[MAX_BUFFER], ap_uint start, ap_uint goal, ap_uint<8> w[MAX_CELLS]) { + + ap_uint dist[MAX_CELLS]; +#pragma HLS ARRAY_PARTITION variable=dist cyclic factor=64 dim=1 + ap_uint prev[MAX_CELLS]; + + SEARCH_INIT_DIST: + for (ap_uint i = 0; i < (ap_uint)(MAX_CELLS); i++) { +#pragma HLS UNROLL factor=128 + dist[i] = 65535; // = (2^16 - 1) + } + + // Priority queue (Circular list) + ap_uint top = 1, bottom = 0; + bool is_empty = true; + ap_uint<32> pq_nodes[MAX_PQ]; +#pragma HLS ARRAY_PARTITION variable=pq_nodes cyclic factor=32 dim=1 +/** Set!: factor=PP **/ + +#ifdef DEBUG_PRINT + int queue_length = 0; + int search_count = 0; +#endif + + // Point of goal terminal + 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_y = (ap_uint<7>)(goal_xy - goal_x * MAX_WIDTH); + ap_uint<3> goal_z = (ap_uint<3>)(goal & BITMASK_Z); + + dist[start] = 0; + pq_push(pq_nodes, 0, start, &top, &bottom, &is_empty); // push start terminal + + SEARCH_PQ: + while (!is_empty) { +#pragma HLS LOOP_TRIPCOUNT min=1 max=1000 +#pragma HLS LOOP_FLATTEN off + + ap_uint<16> prev_cost; + ap_uint<16> src; // target cell + pq_pop(pq_nodes, &prev_cost, &src, &top, &bottom, &is_empty); +#ifdef DEBUG_PRINT + search_count++; +#endif + + + // End routing + if (src == goal) break; + + + // Target cell + ap_uint<16> dist_src = dist[src]; + ap_uint<8> cost = w[src]; + // Point of target cell + 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_y = (ap_uint<7>)(src_xy - src_x * MAX_WIDTH); + ap_uint<3> src_z = (ap_uint<3>)(src & BITMASK_Z); + + // Search adjacent cells + SEARCH_ADJACENTS: + for (ap_uint<3> a = 0; a < 6; a++) { + ap_int<8> dest_x = (ap_int<8>)src_x; // Min: -1, Max: 72 (Signed 8bit) + ap_int<8> dest_y = (ap_int<8>)src_y; // Min: -1, Max: 72 (Signed 8bit) + ap_int<5> dest_z = (ap_int<5>)src_z; // Min: -1, Max: 8 (Signed 5bit) + if (a == 0) { dest_x -= 1; } + if (a == 1) { dest_x += 1; } + if (a == 2) { dest_y -= 1; } + if (a == 3) { dest_y += 1; } + if (a == 4) { dest_z -= 1; } + if (a == 5) { dest_z += 1; } + + // Inside the board ? // + if (0 <= dest_x && dest_x < (ap_int<8>)size_x && 0 <= dest_y && dest_y < (ap_int<8>)size_y && 0 <= dest_z && dest_z < (ap_int<5>)size_z) { + // Adjacent cell + ap_uint<16> dest = (((ap_uint<16>)dest_x * MAX_WIDTH + (ap_uint<16>)dest_y) << BITWIDTH_Z) | (ap_uint<16>)dest_z; + ap_uint<16> dist_new = dist_src + cost; + + if (dist[dest] > dist_new) { + dist[dest] = dist_new; // Update dist + prev[dest] = src; // Recode previous cell + dist_new += abs_uint7(dest_x, goal_x) + abs_uint7(dest_y, goal_y) + abs_uint3(dest_z, goal_z); // A* heuristic + pq_push(pq_nodes, dist_new, dest, &top, &bottom, &is_empty); // push adjacent cell + } + } + } +#ifdef DEBUG_PRINT + if (queue_length < (bottom-top+1)) { queue_length = (bottom-top+1); } +#endif + } + + // Output target path + // Note: Do not include start & goal terminals + ap_uint<16> t = prev[goal]; + + // Backtracking + ap_uint p = idx; // buffer-idx + SEARCH_BACKTRACK: + while (t != start) { +#pragma HLS LOOP_TRIPCOUNT min=1 max=256 + // overflow check + if (p == (*n_idx)) { + (*n_idx)++; break; + } + paths[p] = t; + p++; + t = prev[t]; + } + +#ifdef DEBUG_PRINT + if (max_queue_length < queue_length) { max_queue_length = queue_length; } + if (max_search_count < search_count) { max_search_count = search_count; } +#endif + + return p; +} + +// Queue push (Enqueue) +// Need to modify "trip count" (5) +void pq_push(ap_uint<32> pq_nodes[MAX_PQ], ap_uint<16> priority, ap_uint<16> data, ap_uint *top, ap_uint *bottom, bool *is_empty) { +#pragma HLS INLINE + + (*bottom)++; + if ((*bottom) == (*top) && !(*is_empty)) { (*bottom)--; } // Queue is full -> Last element is automatically removed + + // Binary search for circular list + ap_uint t = (*top); + ap_uint b = (*bottom); + ap_uint h = ((ap_uint)(b - t) / 2) + t; + // Note: "h = (t + b) / 2" causes a bug! + PQ_PUSH_BINARY: + while (t != b) { +#pragma HLS LOOP_TRIPCOUNT min=0 max=13 +/** Set!: min=0 max=PQ_BIT **/ + if ((ap_uint<16>)(pq_nodes[h] & PQ_PRIORITY_MASK) >= priority) { + b = h; + } + else { + t = h + 1; + } + h = ((ap_uint)(b - t) / 2) + t; + } + + // Parallel shifting (PP parallel) + ap_uint shift_count = (*bottom) - t; // # of shifting + + ap_uint bottom_H = (*bottom) / PP; // High-order bits of (*bottom) + ap_uint bottom_L = (*bottom) % PP; // Low-order bits of (*bottom) + ap_uint p0 = (*bottom), p1; + if (shift_count > (ap_uint)(bottom_L)) { + // bottom_L bit shift + PQ_PUSH_SHIFT_H_1: + for (ap_uint k = 0; k < (ap_uint)(bottom_L); k++) { +#pragma HLS LOOP_TRIPCOUNT min=0 max=31 +/** Set!: min=0 max=PP-1 **/ + p0 = p0 - 1; // source + p1 = p0 + 1; // destination + pq_nodes[p1] = pq_nodes[p0]; + } + shift_count = shift_count - bottom_L; + } + else { + // shift_count bit shift + PQ_PUSH_SHIFT_H_2: + for (ap_uint k = 0; k < (ap_uint)(shift_count); k++) { +#pragma HLS LOOP_TRIPCOUNT min=0 max=31 +/** Set!: min=0 max=PP-1 **/ + p0 = p0 - 1; // source + p1 = p0 + 1; // destination + pq_nodes[p1] = pq_nodes[p0]; + } + pq_nodes[p0] = ((ap_uint<32>)data << PQ_PRIORITY_WIDTH) | (ap_uint<32>)priority; + *is_empty = false; return; + } + + ap_uint shift_count_i = shift_count >> LOG_PP; + ap_uint shift_count_j = shift_count - (shift_count_i << LOG_PP); + // Note: Bit adjustment is necessary + // when the values of PP & LOG_PP have been changed. + + ap_uint p[PP+1]; +#pragma HLS ARRAY_PARTITION variable=p complete dim=1 + p[0] = bottom_H * PP; + ap_uint<32> tmp[PP]; +#pragma HLS ARRAY_PARTITION variable=tmp complete dim=1 + PQ_PUSH_SHIFT_I: + for (ap_uint i = 0; i < (ap_uint)(shift_count_i); i++) { +#pragma HLS LOOP_TRIPCOUNT min=0 max=255 +/** Set!: min=0 max=(MAX_PQ)/(PP)-1 **/ + p[0] = p[0] - PP; + for (ap_uint k = 1; k <= (ap_uint)(PP); k++) { +#pragma HLS UNROLL + p[k] = p[0] + k; + } + for (ap_uint k = 1; k <= (ap_uint)(PP); k++) { +#pragma HLS UNROLL + tmp[k-1] = pq_nodes[p[k-1]]; + } + for (ap_uint k = 1; k <= (ap_uint)(PP); k++) { +#pragma HLS UNROLL + pq_nodes[p[k]] = tmp[k-1]; + } + } + PQ_PUSH_SHIFT_J: + for (ap_uint j = 0; j < (ap_uint)(shift_count_j); j++) { +#pragma HLS LOOP_TRIPCOUNT min=0 max=31 +/** Set!: min=0 max=PP-1 **/ + p[0] = p[0] - 1; + p[1] = p[0] + 1; + pq_nodes[p[1]] = pq_nodes[p[0]]; + } + pq_nodes[p[0]] = ((ap_uint<32>)data << PQ_PRIORITY_WIDTH) | (ap_uint<32>)priority; + *is_empty = false; +} + +// Queue pop (Dequeue) +void pq_pop(ap_uint<32> pq_nodes[MAX_PQ], ap_uint<16> *ret_priority, ap_uint<16> *ret_data, ap_uint *top, ap_uint *bottom, bool *is_empty) { +#pragma HLS INLINE + + *ret_priority = (ap_uint<16>)(pq_nodes[(*top)] & PQ_PRIORITY_MASK); + *ret_data = (ap_uint<16>)(pq_nodes[(*top)] >> PQ_PRIORITY_WIDTH); + (*top)++; + if (((*bottom)-(*top)+1) == 0) { *is_empty = true; } +} diff --git a/hls_2018/router_02_boardstr/router.hpp b/hls_2018/router_02_boardstr/router.hpp new file mode 100755 index 0000000..a029ae8 --- /dev/null +++ b/hls_2018/router_02_boardstr/router.hpp @@ -0,0 +1,59 @@ +/** + * router.hpp + * + * for Vivado HLS + */ + +#ifndef __ROUTER_HPP__ +#define __ROUTER_HPP__ + +#ifdef SOFTWARE +#include "ap_int.h" +#else +#include +#endif + +//#define DEBUG_PRINT // for debug + +#ifdef DEBUG_PRINT +using namespace std; +#endif + +// Parameters +#define MAX_WIDTH 72 // Max of X, Y +#define BITWIDTH_XY 13 +#define BITMASK_XY 65528 // 1111 1111 1111 1000 +#define MAX_LAYER 8 // Max of Z +#define BITWIDTH_Z 3 +#define BITMASK_Z 7 // 0000 0000 0000 0111 + +#define MAX_CELLS 41472 // Max #cells (16bit) +#define MAX_LINES 1024 // Max #lines (10bit) +#define MAX_PQ 8192 // Queue size (13bit) +#define MAX_BUFFER 16384 // Line buffer size (14bit) +#define CELL_BIT 16 +#define LINE_BIT 10 +#define PQ_BIT 13 +#define BUFF_BIT 14 + +#define PQ_PRIORITY_WIDTH 16 +#define PQ_PRIORITY_MASK 65535 // 0000 0000 0000 0000 1111 1111 1111 1111 +#define PQ_DATA_WIDTH 16 +#define PQ_DATA_MASK 4294901760 // 1111 1111 1111 1111 0000 0000 0000 0000 + +#define MAX_WEIGHT 255 // Max weight +#define BOARDSTR_SIZE 41472 // Size of I/O + +#define PP 32 // Parameter for Parallel shifting in queue push +#define LOG_PP 5 // LOG_PP is log2(PP) + +ap_uint<8> new_weight(ap_uint<16> x); +bool pynqrouter(char boardstr[BOARDSTR_SIZE], char boardstr_high[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *status); + +ap_uint<7> abs_uint7(ap_uint<7> a, ap_uint<7> b); +ap_uint<3> abs_uint3(ap_uint<3> a, ap_uint<3> b); +ap_uint search(ap_uint idx, ap_uint *n_idx, ap_uint paths[MAX_BUFFER], ap_uint start, ap_uint goal, ap_uint<8> w[MAX_WEIGHT]); +void pq_push(ap_uint<32> pq_nodes[MAX_PQ], ap_uint<16> priority, ap_uint<16> data, ap_uint *top, ap_uint *bottom, bool *is_empty); +void pq_pop(ap_uint<32> pq_nodes[MAX_PQ], ap_uint<16> *ret_priority, ap_uint<16> *ret_data, ap_uint *top, ap_uint *bottom, bool *is_empty); + +#endif /* __ROUTER_HPP__ */ diff --git a/hls_2018/router_04_boardstr/bitstream/router_design.bit b/hls_2018/router_04_boardstr/bitstream/router_design.bit new file mode 100755 index 0000000000000000000000000000000000000000..ff18863db2877ef2c92e741df2f47c44f41c3498 GIT binary patch literal 5568793 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

{oFI*Bl`}% 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 zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjY`NML^cohRzAGXVkw2oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfWU8!z$;aC@;Bf6+y9)$it_bJwK|E-2YdDBvhMZl7&PbT ztUgEcljr_9&)dJmc{@9KrTS*GtxkUW?Jxa9d)}HpFSPr%&(8UDE}RS3fNS9Wa1H!F DyUlTV literal 0 HcmV?d00001 diff --git a/hls_2018/router_03_boardstr/bitstream/router_design.tcl b/hls_2018/router_03_boardstr/bitstream/router_design.tcl new file mode 100755 index 0000000..e5347df --- /dev/null +++ b/hls_2018/router_03_boardstr/bitstream/router_design.tcl @@ -0,0 +1,1113 @@ + +################################################################ +# This is a generated script based on design: router_design +# +# Though there are limitations about the generated script, +# the main purpose of this utility is to make learning +# IP Integrator Tcl commands easier. +################################################################ + +namespace eval _tcl { +proc get_script_folder {} { + set script_path [file normalize [info script]] + set script_folder [file dirname $script_path] + return $script_folder +} +} +variable script_folder +set script_folder [_tcl::get_script_folder] + +################################################################ +# Check if script is running in correct Vivado version. +################################################################ +set scripts_vivado_version 2018.2 +set current_vivado_version [version -short] + +if { [string first $scripts_vivado_version $current_vivado_version] == -1 } { + puts "" + catch {common::send_msg_id "BD_TCL-109" "ERROR" "This script was generated using Vivado <$scripts_vivado_version> and is being run in <$current_vivado_version> of Vivado. Please run the script in Vivado <$scripts_vivado_version> then open the design in Vivado <$current_vivado_version>. Upgrade the design by running \"Tools => Report => Report IP Status...\", then run write_bd_tcl to create an updated script."} + + return 1 +} + +################################################################ +# START +################################################################ + +# To test this script, run the following commands from Vivado Tcl console: +# source router_design_script.tcl + +# If there is no project opened, this script will create a +# project, but make sure you do not have an existing project +# <./myproj/project_1.xpr> in the current working folder. + +set list_projs [get_projects -quiet] +if { $list_projs eq "" } { + create_project project_1 myproj -part xc7z020clg400-1 +} + + +# CHANGE DESIGN NAME HERE +variable design_name +set design_name router_design + +# If you do not already have an existing IP Integrator design open, +# you can create a design using the following command: +# create_bd_design $design_name + +# Creating design if needed +set errMsg "" +set nRet 0 + +set cur_design [current_bd_design -quiet] +set list_cells [get_bd_cells -quiet] + +if { ${design_name} eq "" } { + # USE CASES: + # 1) Design_name not set + + set errMsg "Please set the variable to a non-empty value." + set nRet 1 + +} elseif { ${cur_design} ne "" && ${list_cells} eq "" } { + # USE CASES: + # 2): Current design opened AND is empty AND names same. + # 3): Current design opened AND is empty AND names diff; design_name NOT in project. + # 4): Current design opened AND is empty AND names diff; design_name exists in project. + + if { $cur_design ne $design_name } { + common::send_msg_id "BD_TCL-001" "INFO" "Changing value of from <$design_name> to <$cur_design> since current design is empty." + set design_name [get_property NAME $cur_design] + } + common::send_msg_id "BD_TCL-002" "INFO" "Constructing design in IPI design <$cur_design>..." + +} elseif { ${cur_design} ne "" && $list_cells ne "" && $cur_design eq $design_name } { + # USE CASES: + # 5) Current design opened AND has components AND same names. + + set errMsg "Design <$design_name> already exists in your project, please set the variable to another value." + set nRet 1 +} elseif { [get_files -quiet ${design_name}.bd] ne "" } { + # USE CASES: + # 6) Current opened design, has components, but diff names, design_name exists in project. + # 7) No opened design, design_name exists in project. + + set errMsg "Design <$design_name> already exists in your project, please set the variable to another value." + set nRet 2 + +} else { + # USE CASES: + # 8) No opened design, design_name not in project. + # 9) Current opened design, has components, but diff names, design_name not in project. + + common::send_msg_id "BD_TCL-003" "INFO" "Currently there is no design <$design_name> in project, so creating one..." + + create_bd_design $design_name + + common::send_msg_id "BD_TCL-004" "INFO" "Making design <$design_name> as current_bd_design." + current_bd_design $design_name + +} + +common::send_msg_id "BD_TCL-005" "INFO" "Currently the variable is equal to \"$design_name\"." + +if { $nRet != 0 } { + catch {common::send_msg_id "BD_TCL-114" "ERROR" $errMsg} + return $nRet +} + +set bCheckIPsPassed 1 +################################################################## +# CHECK IPs +################################################################## +set bCheckIPs 1 +if { $bCheckIPs == 1 } { + set list_check_ips "\ +xilinx.com:ip:axi_gpio:2.0\ +xilinx.com:ip:processing_system7:5.5\ +xilinx.com:hls:pynqrouter:1.0\ +xilinx.com:ip:proc_sys_reset:5.0\ +" + + set list_ips_missing "" + common::send_msg_id "BD_TCL-006" "INFO" "Checking if the following IPs exist in the project's IP catalog: $list_check_ips ." + + foreach ip_vlnv $list_check_ips { + set ip_obj [get_ipdefs -all $ip_vlnv] + if { $ip_obj eq "" } { + lappend list_ips_missing $ip_vlnv + } + } + + if { $list_ips_missing ne "" } { + catch {common::send_msg_id "BD_TCL-115" "ERROR" "The following IPs are not found in the IP Catalog:\n $list_ips_missing\n\nResolution: Please add the repository containing the IP(s) to the project." } + set bCheckIPsPassed 0 + } + +} + +if { $bCheckIPsPassed != 1 } { + common::send_msg_id "BD_TCL-1003" "WARNING" "Will not continue with creation of design due to the error(s) above." + return 3 +} + +################################################################## +# DESIGN PROCs +################################################################## + + + +# Procedure to create entire design; Provide argument to make +# procedure reusable. If parentCell is "", will use root. +proc create_root_design { parentCell } { + + variable script_folder + variable design_name + + if { $parentCell eq "" } { + set parentCell [get_bd_cells /] + } + + # Get object for parentCell + set parentObj [get_bd_cells $parentCell] + if { $parentObj == "" } { + catch {common::send_msg_id "BD_TCL-100" "ERROR" "Unable to find parent cell <$parentCell>!"} + return + } + + # Make sure parentObj is hier blk + set parentType [get_property TYPE $parentObj] + if { $parentType ne "hier" } { + catch {common::send_msg_id "BD_TCL-101" "ERROR" "Parent <$parentObj> has TYPE = <$parentType>. Expected to be ."} + return + } + + # Save current instance; Restore later + set oldCurInst [current_bd_instance .] + + # Set parent object as current + current_bd_instance $parentObj + + + # Create interface ports + set DDR [ create_bd_intf_port -mode Master -vlnv xilinx.com:interface:ddrx_rtl:1.0 DDR ] + set FIXED_IO [ create_bd_intf_port -mode Master -vlnv xilinx.com:display_processing_system7:fixedio_rtl:1.0 FIXED_IO ] + + # Create ports + set LD [ create_bd_port -dir O -from 3 -to 0 LD ] + + # Create instance: axi_gpio_0, and set properties + set axi_gpio_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:axi_gpio:2.0 axi_gpio_0 ] + set_property -dict [ list \ + CONFIG.C_GPIO_WIDTH {4} \ + ] $axi_gpio_0 + + # Create instance: processing_system7_0, and set properties + set processing_system7_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:processing_system7:5.5 processing_system7_0 ] + set_property -dict [ list \ + CONFIG.PCW_ACT_APU_PERIPHERAL_FREQMHZ {650.000000} \ + CONFIG.PCW_ACT_CAN0_PERIPHERAL_FREQMHZ {23.8095} \ + CONFIG.PCW_ACT_CAN1_PERIPHERAL_FREQMHZ {23.8095} \ + CONFIG.PCW_ACT_CAN_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_DCI_PERIPHERAL_FREQMHZ {10.096154} \ + CONFIG.PCW_ACT_ENET0_PERIPHERAL_FREQMHZ {125.000000} \ + CONFIG.PCW_ACT_ENET1_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_FPGA0_PERIPHERAL_FREQMHZ {100.000000} \ + CONFIG.PCW_ACT_FPGA1_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_FPGA2_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_FPGA3_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_I2C_PERIPHERAL_FREQMHZ {50} \ + CONFIG.PCW_ACT_PCAP_PERIPHERAL_FREQMHZ {200.000000} \ + CONFIG.PCW_ACT_QSPI_PERIPHERAL_FREQMHZ {200.000000} \ + CONFIG.PCW_ACT_SDIO_PERIPHERAL_FREQMHZ {50.000000} \ + CONFIG.PCW_ACT_SMC_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_SPI_PERIPHERAL_FREQMHZ {10.000000} \ + CONFIG.PCW_ACT_TPIU_PERIPHERAL_FREQMHZ {200.000000} \ + CONFIG.PCW_ACT_TTC0_CLK0_PERIPHERAL_FREQMHZ {108.333336} \ + CONFIG.PCW_ACT_TTC0_CLK1_PERIPHERAL_FREQMHZ {108.333336} \ + CONFIG.PCW_ACT_TTC0_CLK2_PERIPHERAL_FREQMHZ {108.333336} \ + CONFIG.PCW_ACT_TTC1_CLK0_PERIPHERAL_FREQMHZ {108.333336} \ + CONFIG.PCW_ACT_TTC1_CLK1_PERIPHERAL_FREQMHZ {108.333336} \ + CONFIG.PCW_ACT_TTC1_CLK2_PERIPHERAL_FREQMHZ {108.333336} \ + CONFIG.PCW_ACT_TTC_PERIPHERAL_FREQMHZ {50} \ + CONFIG.PCW_ACT_UART_PERIPHERAL_FREQMHZ {100.000000} \ + CONFIG.PCW_ACT_USB0_PERIPHERAL_FREQMHZ {60} \ + CONFIG.PCW_ACT_USB1_PERIPHERAL_FREQMHZ {60} \ + CONFIG.PCW_ACT_WDT_PERIPHERAL_FREQMHZ {108.333336} \ + CONFIG.PCW_APU_CLK_RATIO_ENABLE {6:2:1} \ + CONFIG.PCW_APU_PERIPHERAL_FREQMHZ {650} \ + CONFIG.PCW_ARMPLL_CTRL_FBDIV {26} \ + CONFIG.PCW_CAN0_BASEADDR {0xE0008000} \ + CONFIG.PCW_CAN0_CAN0_IO {} \ + CONFIG.PCW_CAN0_HIGHADDR {0xE0008FFF} \ + CONFIG.PCW_CAN0_PERIPHERAL_CLKSRC {External} \ + CONFIG.PCW_CAN0_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_CAN0_PERIPHERAL_FREQMHZ {-1} \ + CONFIG.PCW_CAN1_BASEADDR {0xE0009000} \ + CONFIG.PCW_CAN1_CAN1_IO {} \ + CONFIG.PCW_CAN1_HIGHADDR {0xE0009FFF} \ + CONFIG.PCW_CAN1_PERIPHERAL_CLKSRC {External} \ + CONFIG.PCW_CAN1_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_CAN1_PERIPHERAL_FREQMHZ {-1} \ + CONFIG.PCW_CAN_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_CAN_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_CAN_PERIPHERAL_DIVISOR1 {1} \ + CONFIG.PCW_CAN_PERIPHERAL_FREQMHZ {100} \ + CONFIG.PCW_CAN_PERIPHERAL_VALID {0} \ + CONFIG.PCW_CLK0_FREQ {100000000} \ + CONFIG.PCW_CLK1_FREQ {10000000} \ + CONFIG.PCW_CLK2_FREQ {10000000} \ + CONFIG.PCW_CLK3_FREQ {10000000} \ + CONFIG.PCW_CORE0_FIQ_INTR {0} \ + CONFIG.PCW_CORE0_IRQ_INTR {0} \ + CONFIG.PCW_CORE1_FIQ_INTR {0} \ + CONFIG.PCW_CORE1_IRQ_INTR {0} \ + CONFIG.PCW_CPU_CPU_6X4X_MAX_RANGE {667} \ + CONFIG.PCW_CPU_CPU_PLL_FREQMHZ {1300.000} \ + CONFIG.PCW_CPU_PERIPHERAL_CLKSRC {ARM PLL} \ + CONFIG.PCW_CPU_PERIPHERAL_DIVISOR0 {2} \ + CONFIG.PCW_CRYSTAL_PERIPHERAL_FREQMHZ {50} \ + CONFIG.PCW_DCI_PERIPHERAL_CLKSRC {DDR PLL} \ + CONFIG.PCW_DCI_PERIPHERAL_DIVISOR0 {52} \ + CONFIG.PCW_DCI_PERIPHERAL_DIVISOR1 {2} \ + CONFIG.PCW_DCI_PERIPHERAL_FREQMHZ {10.159} \ + CONFIG.PCW_DDRPLL_CTRL_FBDIV {21} \ + CONFIG.PCW_DDR_DDR_PLL_FREQMHZ {1050.000} \ + CONFIG.PCW_DDR_HPRLPR_QUEUE_PARTITION {HPR(0)/LPR(32)} \ + CONFIG.PCW_DDR_HPR_TO_CRITICAL_PRIORITY_LEVEL {15} \ + CONFIG.PCW_DDR_LPR_TO_CRITICAL_PRIORITY_LEVEL {2} \ + CONFIG.PCW_DDR_PERIPHERAL_CLKSRC {DDR PLL} \ + CONFIG.PCW_DDR_PERIPHERAL_DIVISOR0 {2} \ + CONFIG.PCW_DDR_PORT0_HPR_ENABLE {0} \ + CONFIG.PCW_DDR_PORT1_HPR_ENABLE {0} \ + CONFIG.PCW_DDR_PORT2_HPR_ENABLE {0} \ + CONFIG.PCW_DDR_PORT3_HPR_ENABLE {0} \ + CONFIG.PCW_DDR_PRIORITY_READPORT_0 {} \ + CONFIG.PCW_DDR_PRIORITY_READPORT_2 {} \ + CONFIG.PCW_DDR_PRIORITY_WRITEPORT_0 {} \ + CONFIG.PCW_DDR_PRIORITY_WRITEPORT_2 {} \ + CONFIG.PCW_DDR_RAM_BASEADDR {0x00100000} \ + CONFIG.PCW_DDR_RAM_HIGHADDR {0x1FFFFFFF} \ + CONFIG.PCW_DDR_WRITE_TO_CRITICAL_PRIORITY_LEVEL {2} \ + CONFIG.PCW_DM_WIDTH {4} \ + CONFIG.PCW_DQS_WIDTH {4} \ + CONFIG.PCW_DQ_WIDTH {32} \ + CONFIG.PCW_ENET0_BASEADDR {0xE000B000} \ + CONFIG.PCW_ENET0_ENET0_IO {MIO 16 .. 27} \ + CONFIG.PCW_ENET0_GRP_MDIO_ENABLE {1} \ + CONFIG.PCW_ENET0_GRP_MDIO_IO {MIO 52 .. 53} \ + CONFIG.PCW_ENET0_HIGHADDR {0xE000BFFF} \ + CONFIG.PCW_ENET0_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_ENET0_PERIPHERAL_DIVISOR0 {8} \ + CONFIG.PCW_ENET0_PERIPHERAL_DIVISOR1 {1} \ + CONFIG.PCW_ENET0_PERIPHERAL_ENABLE {1} \ + CONFIG.PCW_ENET0_PERIPHERAL_FREQMHZ {1000 Mbps} \ + CONFIG.PCW_ENET0_RESET_ENABLE {1} \ + CONFIG.PCW_ENET0_RESET_IO {MIO 9} \ + CONFIG.PCW_ENET1_BASEADDR {0xE000C000} \ + CONFIG.PCW_ENET1_ENET1_IO {} \ + CONFIG.PCW_ENET1_HIGHADDR {0xE000CFFF} \ + CONFIG.PCW_ENET1_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_ENET1_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_ENET1_PERIPHERAL_DIVISOR1 {1} \ + CONFIG.PCW_ENET1_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_ENET1_PERIPHERAL_FREQMHZ {1000 Mbps} \ + CONFIG.PCW_ENET1_RESET_ENABLE {0} \ + CONFIG.PCW_ENET1_RESET_IO {} \ + CONFIG.PCW_FTM_CTI_IN1 {} \ + CONFIG.PCW_FTM_CTI_IN3 {} \ + CONFIG.PCW_FTM_CTI_OUT1 {} \ + CONFIG.PCW_FTM_CTI_OUT3 {} \ + CONFIG.PCW_GPIO_EMIO_GPIO_WIDTH {64} \ + CONFIG.PCW_GPIO_HIGHADDR {0xE000AFFF} \ + CONFIG.PCW_GPIO_MIO_GPIO_ENABLE {1} \ + CONFIG.PCW_GPIO_MIO_GPIO_IO {MIO} \ + CONFIG.PCW_GPIO_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_I2C0_BASEADDR {0xE0004000} \ + CONFIG.PCW_I2C0_GRP_INT_ENABLE {0} \ + CONFIG.PCW_I2C0_GRP_INT_IO {} \ + CONFIG.PCW_I2C0_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_I2C0_RESET_ENABLE {0} \ + CONFIG.PCW_I2C0_RESET_IO {} \ + CONFIG.PCW_I2C1_HIGHADDR {0xE0005FFF} \ + CONFIG.PCW_I2C1_I2C1_IO {} \ + CONFIG.PCW_I2C_PERIPHERAL_FREQMHZ {25} \ + CONFIG.PCW_I2C_RESET_ENABLE {1} \ + CONFIG.PCW_I2C_RESET_POLARITY {Active Low} \ + CONFIG.PCW_I2C_RESET_SELECT {} \ + CONFIG.PCW_NAND_NAND_IO {} \ + CONFIG.PCW_NOR_GRP_CS0_ENABLE {0} \ + CONFIG.PCW_NOR_GRP_CS0_IO {} \ + CONFIG.PCW_NOR_GRP_SRAM_CS0_ENABLE {0} \ + CONFIG.PCW_NOR_GRP_SRAM_CS0_IO {} \ + CONFIG.PCW_NOR_GRP_SRAM_INT_ENABLE {0} \ + CONFIG.PCW_NOR_GRP_SRAM_INT_IO {} \ + CONFIG.PCW_NOR_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_NOR_SRAM_CS0_T_CEOE {1} \ + CONFIG.PCW_NOR_SRAM_CS0_T_PC {1} \ + CONFIG.PCW_NOR_SRAM_CS0_T_RC {11} \ + CONFIG.PCW_NOR_SRAM_CS0_T_TR {1} \ + CONFIG.PCW_NOR_SRAM_CS0_T_WC {11} \ + CONFIG.PCW_NOR_SRAM_CS0_T_WP {1} \ + CONFIG.PCW_NOR_SRAM_CS0_WE_TIME {0} \ + CONFIG.PCW_NOR_SRAM_CS1_T_CEOE {1} \ + CONFIG.PCW_NOR_SRAM_CS1_T_PC {1} \ + CONFIG.PCW_NOR_SRAM_CS1_T_RC {11} \ + CONFIG.PCW_NOR_SRAM_CS1_T_TR {1} \ + CONFIG.PCW_NOR_SRAM_CS1_T_WC {11} \ + CONFIG.PCW_NOR_SRAM_CS1_T_WP {1} \ + CONFIG.PCW_NOR_SRAM_CS1_WE_TIME {0} \ + CONFIG.PCW_OVERRIDE_BASIC_CLOCK {0} \ + CONFIG.PCW_P2F_CAN0_INTR {0} \ + CONFIG.PCW_P2F_CAN1_INTR {0} \ + CONFIG.PCW_P2F_CTI_INTR {0} \ + CONFIG.PCW_P2F_DMAC0_INTR {0} \ + CONFIG.PCW_P2F_DMAC1_INTR {0} \ + CONFIG.PCW_P2F_DMAC2_INTR {0} \ + CONFIG.PCW_P2F_DMAC3_INTR {0} \ + CONFIG.PCW_P2F_DMAC4_INTR {0} \ + CONFIG.PCW_P2F_DMAC5_INTR {0} \ + CONFIG.PCW_P2F_DMAC6_INTR {0} \ + CONFIG.PCW_P2F_DMAC7_INTR {0} \ + CONFIG.PCW_P2F_DMAC_ABORT_INTR {0} \ + CONFIG.PCW_P2F_ENET0_INTR {0} \ + CONFIG.PCW_P2F_ENET1_INTR {0} \ + CONFIG.PCW_P2F_GPIO_INTR {0} \ + CONFIG.PCW_P2F_I2C0_INTR {0} \ + CONFIG.PCW_P2F_I2C1_INTR {0} \ + CONFIG.PCW_P2F_QSPI_INTR {0} \ + CONFIG.PCW_P2F_SDIO0_INTR {0} \ + CONFIG.PCW_P2F_SDIO1_INTR {0} \ + CONFIG.PCW_P2F_SMC_INTR {0} \ + CONFIG.PCW_P2F_SPI0_INTR {0} \ + CONFIG.PCW_P2F_SPI1_INTR {0} \ + CONFIG.PCW_P2F_UART0_INTR {0} \ + CONFIG.PCW_P2F_UART1_INTR {0} \ + CONFIG.PCW_P2F_USB0_INTR {0} \ + CONFIG.PCW_P2F_USB1_INTR {0} \ + CONFIG.PCW_PACKAGE_DDR_BOARD_DELAY0 {0.223} \ + CONFIG.PCW_PACKAGE_DDR_BOARD_DELAY1 {0.212} \ + CONFIG.PCW_PACKAGE_DDR_BOARD_DELAY2 {0.085} \ + CONFIG.PCW_PACKAGE_DDR_BOARD_DELAY3 {0.092} \ + CONFIG.PCW_PACKAGE_DDR_DQS_TO_CLK_DELAY_0 {0.040} \ + CONFIG.PCW_PACKAGE_DDR_DQS_TO_CLK_DELAY_1 {0.058} \ + CONFIG.PCW_PACKAGE_DDR_DQS_TO_CLK_DELAY_2 {-0.009} \ + CONFIG.PCW_PACKAGE_DDR_DQS_TO_CLK_DELAY_3 {-0.033} \ + CONFIG.PCW_PACKAGE_NAME {clg400} \ + CONFIG.PCW_PCAP_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_PCAP_PERIPHERAL_DIVISOR0 {5} \ + CONFIG.PCW_PCAP_PERIPHERAL_FREQMHZ {200} \ + CONFIG.PCW_PERIPHERAL_BOARD_PRESET {None} \ + CONFIG.PCW_PJTAG_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_PJTAG_PJTAG_IO {} \ + CONFIG.PCW_QSPI_GRP_SINGLE_SS_ENABLE {1} \ + CONFIG.PCW_QSPI_GRP_SINGLE_SS_IO {MIO 1 .. 6} \ + CONFIG.PCW_QSPI_GRP_SS1_ENABLE {0} \ + CONFIG.PCW_QSPI_GRP_SS1_IO {} \ + CONFIG.PCW_SD0_GRP_WP_ENABLE {0} \ + CONFIG.PCW_SD0_GRP_WP_IO {} \ + CONFIG.PCW_SD1_GRP_POW_ENABLE {0} \ + CONFIG.PCW_SD1_GRP_POW_IO {} \ + CONFIG.PCW_SD1_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_SD1_SD1_IO {} \ + CONFIG.PCW_SPI0_GRP_SS1_ENABLE {0} \ + CONFIG.PCW_SPI0_GRP_SS1_IO {} \ + CONFIG.PCW_SPI0_HIGHADDR {0xE0006FFF} \ + CONFIG.PCW_SPI0_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_SPI0_SPI0_IO {} \ + CONFIG.PCW_SPI1_GRP_SS1_ENABLE {0} \ + CONFIG.PCW_SPI1_GRP_SS1_IO {} \ + CONFIG.PCW_SPI1_HIGHADDR {0xE0007FFF} \ + CONFIG.PCW_SPI1_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_SPI1_SPI1_IO {} \ + CONFIG.PCW_TRACE_GRP_2BIT_ENABLE {0} \ + CONFIG.PCW_TRACE_GRP_2BIT_IO {} \ + CONFIG.PCW_TRACE_GRP_4BIT_ENABLE {0} \ + CONFIG.PCW_TRACE_GRP_4BIT_IO {} \ + CONFIG.PCW_TRACE_INTERNAL_WIDTH {2} \ + CONFIG.PCW_TRACE_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_TRACE_PIPELINE_WIDTH {8} \ + CONFIG.PCW_TRACE_TRACE_IO {} \ + CONFIG.PCW_TTC1_BASEADDR {0xE0105000} \ + CONFIG.PCW_TTC1_CLK0_PERIPHERAL_CLKSRC {CPU_1X} \ + CONFIG.PCW_TTC1_CLK0_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_TTC1_CLK0_PERIPHERAL_FREQMHZ {133.333333} \ + CONFIG.PCW_TTC1_CLK1_PERIPHERAL_CLKSRC {CPU_1X} \ + CONFIG.PCW_TTC1_CLK1_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_TTC1_CLK1_PERIPHERAL_FREQMHZ {133.333333} \ + CONFIG.PCW_TTC1_CLK2_PERIPHERAL_CLKSRC {CPU_1X} \ + CONFIG.PCW_TTC1_CLK2_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_TTC1_CLK2_PERIPHERAL_FREQMHZ {133.333333} \ + CONFIG.PCW_TTC1_HIGHADDR {0xE0105fff} \ + CONFIG.PCW_TTC1_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_TTC1_TTC1_IO {} \ + CONFIG.PCW_UART0_HIGHADDR {0xE0000FFF} \ + CONFIG.PCW_UART0_PERIPHERAL_ENABLE {1} \ + CONFIG.PCW_UART0_UART0_IO {MIO 14 .. 15} \ + CONFIG.PCW_UART1_BASEADDR {0xE0001000} \ + CONFIG.PCW_UART1_BAUD_RATE {115200} \ + CONFIG.PCW_UART1_GRP_FULL_ENABLE {0} \ + CONFIG.PCW_UART1_GRP_FULL_IO {} \ + CONFIG.PCW_UART_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_UART_PERIPHERAL_DIVISOR0 {10} \ + CONFIG.PCW_UART_PERIPHERAL_FREQMHZ {100} \ + CONFIG.PCW_UART_PERIPHERAL_VALID {1} \ + CONFIG.PCW_UIPARAM_ACT_DDR_FREQ_MHZ {525.000000} \ + CONFIG.PCW_UIPARAM_DDR_ADV_ENABLE {0} \ + CONFIG.PCW_UIPARAM_DDR_AL {0} \ + CONFIG.PCW_UIPARAM_DDR_BANK_ADDR_COUNT {3} \ + CONFIG.PCW_UIPARAM_DDR_BL {8} \ + CONFIG.PCW_UIPARAM_DDR_BOARD_DELAY0 {0.223} \ + CONFIG.PCW_UIPARAM_DDR_BOARD_DELAY1 {0.212} \ + CONFIG.PCW_UIPARAM_DDR_BOARD_DELAY2 {0.085} \ + CONFIG.PCW_UIPARAM_DDR_BOARD_DELAY3 {0.092} \ + CONFIG.PCW_UIPARAM_DDR_BUS_WIDTH {16 Bit} \ + CONFIG.PCW_UIPARAM_DDR_CL {7} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_0_LENGTH_MM {25.8} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_0_PACKAGE_LENGTH {80.4535} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_0_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_1_LENGTH_MM {25.8} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_1_PACKAGE_LENGTH {80.4535} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_1_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_2_LENGTH_MM {0} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_2_PACKAGE_LENGTH {80.4535} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_2_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_3_LENGTH_MM {0} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_3_PACKAGE_LENGTH {80.4535} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_3_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_CLOCK_STOP_EN {0} \ + CONFIG.PCW_UIPARAM_DDR_COL_ADDR_COUNT {10} \ + CONFIG.PCW_UIPARAM_DDR_CWL {6} \ + CONFIG.PCW_UIPARAM_DDR_DEVICE_CAPACITY {4096 MBits} \ + CONFIG.PCW_UIPARAM_DDR_DQS_0_LENGTH_MM {15.6} \ + CONFIG.PCW_UIPARAM_DDR_DQS_0_PACKAGE_LENGTH {105.056} \ + CONFIG.PCW_UIPARAM_DDR_DQS_0_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_DQS_1_LENGTH_MM {18.8} \ + CONFIG.PCW_UIPARAM_DDR_DQS_1_PACKAGE_LENGTH {66.904} \ + CONFIG.PCW_UIPARAM_DDR_DQS_1_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_DQS_2_LENGTH_MM {0} \ + CONFIG.PCW_UIPARAM_DDR_DQS_2_PACKAGE_LENGTH {89.1715} \ + CONFIG.PCW_UIPARAM_DDR_DQS_2_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_DQS_3_LENGTH_MM {0} \ + CONFIG.PCW_UIPARAM_DDR_DQS_3_PACKAGE_LENGTH {113.63} \ + CONFIG.PCW_UIPARAM_DDR_DQS_3_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_DQS_TO_CLK_DELAY_0 {0.040} \ + CONFIG.PCW_UIPARAM_DDR_DQS_TO_CLK_DELAY_1 {0.058} \ + CONFIG.PCW_UIPARAM_DDR_DQS_TO_CLK_DELAY_2 {-0.009} \ + CONFIG.PCW_UIPARAM_DDR_DQS_TO_CLK_DELAY_3 {-0.033} \ + CONFIG.PCW_UIPARAM_DDR_DQ_0_LENGTH_MM {16.5} \ + CONFIG.PCW_UIPARAM_DDR_DQ_0_PACKAGE_LENGTH {98.503} \ + CONFIG.PCW_UIPARAM_DDR_DQ_0_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_DQ_1_LENGTH_MM {18} \ + CONFIG.PCW_UIPARAM_DDR_DQ_1_PACKAGE_LENGTH {68.5855} \ + CONFIG.PCW_UIPARAM_DDR_DQ_1_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_DQ_2_LENGTH_MM {0} \ + CONFIG.PCW_UIPARAM_DDR_DQ_2_PACKAGE_LENGTH {90.295} \ + CONFIG.PCW_UIPARAM_DDR_DQ_2_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_DQ_3_LENGTH_MM {0} \ + CONFIG.PCW_UIPARAM_DDR_DQ_3_PACKAGE_LENGTH {103.977} \ + CONFIG.PCW_UIPARAM_DDR_DQ_3_PROPOGATION_DELAY {160} \ + CONFIG.PCW_UIPARAM_DDR_DRAM_WIDTH {16 Bits} \ + CONFIG.PCW_UIPARAM_DDR_ECC {Disabled} \ + CONFIG.PCW_UIPARAM_DDR_ENABLE {1} \ + CONFIG.PCW_UIPARAM_DDR_FREQ_MHZ {525} \ + CONFIG.PCW_UIPARAM_DDR_HIGH_TEMP {Normal (0-85)} \ + CONFIG.PCW_UIPARAM_DDR_MEMORY_TYPE {DDR 3} \ + CONFIG.PCW_UIPARAM_DDR_PARTNO {MT41J256M16 RE-125} \ + CONFIG.PCW_UIPARAM_DDR_ROW_ADDR_COUNT {15} \ + CONFIG.PCW_UIPARAM_DDR_SPEED_BIN {DDR3_1066F} \ + CONFIG.PCW_UIPARAM_DDR_TRAIN_DATA_EYE {1} \ + CONFIG.PCW_UIPARAM_DDR_TRAIN_READ_GATE {1} \ + CONFIG.PCW_UIPARAM_DDR_TRAIN_WRITE_LEVEL {1} \ + CONFIG.PCW_UIPARAM_DDR_T_FAW {40.0} \ + CONFIG.PCW_UIPARAM_DDR_T_RAS_MIN {35.0} \ + CONFIG.PCW_UIPARAM_DDR_T_RC {48.91} \ + CONFIG.PCW_UIPARAM_DDR_T_RCD {7} \ + CONFIG.PCW_UIPARAM_DDR_T_RP {7} \ + CONFIG.PCW_UIPARAM_DDR_USE_INTERNAL_VREF {0} \ + CONFIG.PCW_UIPARAM_GENERATE_SUMMARY {NA} \ + CONFIG.PCW_USB0_BASEADDR {0xE0102000} \ + CONFIG.PCW_USB0_HIGHADDR {0xE0102fff} \ + CONFIG.PCW_USB0_PERIPHERAL_ENABLE {1} \ + CONFIG.PCW_USB0_PERIPHERAL_FREQMHZ {60} \ + CONFIG.PCW_USB0_RESET_ENABLE {1} \ + CONFIG.PCW_USB0_RESET_IO {MIO 46} \ + CONFIG.PCW_USB0_USB0_IO {MIO 28 .. 39} \ + CONFIG.PCW_USB1_BASEADDR {0xE0103000} \ + CONFIG.PCW_USB1_HIGHADDR {0xE0103fff} \ + CONFIG.PCW_USB1_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_USB1_PERIPHERAL_FREQMHZ {60} \ + CONFIG.PCW_USB1_RESET_ENABLE {0} \ + CONFIG.PCW_USB1_RESET_IO {} \ + CONFIG.PCW_USB_RESET_ENABLE {1} \ + CONFIG.PCW_USB_RESET_POLARITY {Active Low} \ + CONFIG.PCW_USB_RESET_SELECT {Share reset pin} \ + CONFIG.PCW_USE_AXI_FABRIC_IDLE {0} \ + CONFIG.PCW_USE_AXI_NONSECURE {0} \ + CONFIG.PCW_USE_CORESIGHT {0} \ + CONFIG.PCW_USE_CROSS_TRIGGER {0} \ + CONFIG.PCW_USE_CR_FABRIC {1} \ + CONFIG.PCW_USE_DDR_BYPASS {0} \ + CONFIG.PCW_USE_DEBUG {0} \ + CONFIG.PCW_USE_DEFAULT_ACP_USER_VAL {0} \ + CONFIG.PCW_USE_DMA0 {0} \ + CONFIG.PCW_USE_DMA1 {0} \ + CONFIG.PCW_USE_DMA2 {0} \ + CONFIG.PCW_USE_DMA3 {0} \ + CONFIG.PCW_USE_EXPANDED_IOP {0} \ + CONFIG.PCW_USE_EXPANDED_PS_SLCR_REGISTERS {0} \ + CONFIG.PCW_USE_FABRIC_INTERRUPT {0} \ + CONFIG.PCW_USE_HIGH_OCM {0} \ + CONFIG.PCW_USE_M_AXI_GP0 {1} \ + CONFIG.PCW_USE_M_AXI_GP1 {0} \ + CONFIG.PCW_USE_PROC_EVENT_BUS {0} \ + CONFIG.PCW_USE_PS_SLCR_REGISTERS {0} \ + CONFIG.PCW_USE_S_AXI_ACP {0} \ + CONFIG.PCW_USE_S_AXI_GP0 {0} \ + CONFIG.PCW_USE_S_AXI_GP1 {0} \ + CONFIG.PCW_USE_S_AXI_HP0 {0} \ + CONFIG.PCW_USE_S_AXI_HP1 {0} \ + CONFIG.PCW_USE_S_AXI_HP2 {0} \ + CONFIG.PCW_USE_S_AXI_HP3 {0} \ + CONFIG.PCW_USE_TRACE {0} \ + CONFIG.PCW_USE_TRACE_DATA_EDGE_DETECTOR {0} \ + CONFIG.PCW_VALUE_SILVERSION {3} \ + CONFIG.PCW_WDT_PERIPHERAL_CLKSRC {CPU_1X} \ + CONFIG.PCW_WDT_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_WDT_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_WDT_PERIPHERAL_FREQMHZ {133.333333} \ + CONFIG.PCW_WDT_WDT_IO {} \ + CONFIG.PCW_CAN0_GRP_CLK_ENABLE {0} \ + CONFIG.PCW_CAN0_GRP_CLK_IO {} \ + CONFIG.PCW_CAN1_GRP_CLK_ENABLE {0} \ + CONFIG.PCW_CAN1_GRP_CLK_IO {} \ + CONFIG.PCW_DDR_PRIORITY_READPORT_1 {} \ + CONFIG.PCW_DDR_PRIORITY_READPORT_3 {} \ + CONFIG.PCW_DDR_PRIORITY_WRITEPORT_1 {} \ + CONFIG.PCW_DDR_PRIORITY_WRITEPORT_3 {} \ + CONFIG.PCW_ENET1_GRP_MDIO_ENABLE {0} \ + CONFIG.PCW_ENET1_GRP_MDIO_IO {} \ + CONFIG.PCW_ENET_RESET_ENABLE {1} \ + CONFIG.PCW_ENET_RESET_POLARITY {Active Low} \ + CONFIG.PCW_ENET_RESET_SELECT {Share reset pin} \ + CONFIG.PCW_EN_4K_TIMER {0} \ + CONFIG.PCW_EN_CAN0 {0} \ + CONFIG.PCW_EN_CAN1 {0} \ + CONFIG.PCW_EN_CLK0_PORT {1} \ + CONFIG.PCW_EN_CLK1_PORT {0} \ + CONFIG.PCW_EN_CLK2_PORT {0} \ + CONFIG.PCW_EN_CLK3_PORT {0} \ + CONFIG.PCW_EN_CLKTRIG0_PORT {0} \ + CONFIG.PCW_EN_CLKTRIG1_PORT {0} \ + CONFIG.PCW_EN_CLKTRIG2_PORT {0} \ + CONFIG.PCW_EN_CLKTRIG3_PORT {0} \ + CONFIG.PCW_EN_DDR {1} \ + CONFIG.PCW_EN_EMIO_CAN0 {0} \ + CONFIG.PCW_EN_EMIO_CAN1 {0} \ + CONFIG.PCW_EN_EMIO_CD_SDIO0 {0} \ + CONFIG.PCW_EN_EMIO_CD_SDIO1 {0} \ + CONFIG.PCW_EN_EMIO_ENET0 {0} \ + CONFIG.PCW_EN_EMIO_ENET1 {0} \ + CONFIG.PCW_EN_EMIO_GPIO {0} \ + CONFIG.PCW_EN_EMIO_I2C0 {0} \ + CONFIG.PCW_EN_EMIO_I2C1 {0} \ + CONFIG.PCW_EN_EMIO_MODEM_UART0 {0} \ + CONFIG.PCW_EN_EMIO_MODEM_UART1 {0} \ + CONFIG.PCW_EN_EMIO_PJTAG {0} \ + CONFIG.PCW_EN_EMIO_SDIO0 {0} \ + CONFIG.PCW_EN_EMIO_SDIO1 {0} \ + CONFIG.PCW_EN_EMIO_SPI0 {0} \ + CONFIG.PCW_EN_EMIO_SPI1 {0} \ + CONFIG.PCW_EN_EMIO_SRAM_INT {0} \ + CONFIG.PCW_EN_EMIO_TRACE {0} \ + CONFIG.PCW_EN_EMIO_TTC0 {0} \ + CONFIG.PCW_EN_EMIO_TTC1 {0} \ + CONFIG.PCW_EN_EMIO_UART0 {0} \ + CONFIG.PCW_EN_EMIO_UART1 {0} \ + CONFIG.PCW_EN_EMIO_WDT {0} \ + CONFIG.PCW_EN_EMIO_WP_SDIO0 {0} \ + CONFIG.PCW_EN_EMIO_WP_SDIO1 {0} \ + CONFIG.PCW_EN_ENET0 {1} \ + CONFIG.PCW_EN_ENET1 {0} \ + CONFIG.PCW_EN_GPIO {1} \ + CONFIG.PCW_EN_I2C0 {0} \ + CONFIG.PCW_EN_I2C1 {0} \ + CONFIG.PCW_EN_MODEM_UART0 {0} \ + CONFIG.PCW_EN_MODEM_UART1 {0} \ + CONFIG.PCW_EN_PJTAG {0} \ + CONFIG.PCW_EN_PTP_ENET0 {0} \ + CONFIG.PCW_EN_PTP_ENET1 {0} \ + CONFIG.PCW_EN_QSPI {1} \ + CONFIG.PCW_EN_RST0_PORT {1} \ + CONFIG.PCW_EN_RST1_PORT {0} \ + CONFIG.PCW_EN_RST2_PORT {0} \ + CONFIG.PCW_EN_RST3_PORT {0} \ + CONFIG.PCW_EN_SDIO0 {1} \ + CONFIG.PCW_EN_SDIO1 {0} \ + CONFIG.PCW_EN_SMC {0} \ + CONFIG.PCW_EN_SPI0 {0} \ + CONFIG.PCW_EN_SPI1 {0} \ + CONFIG.PCW_EN_TRACE {0} \ + CONFIG.PCW_EN_TTC0 {0} \ + CONFIG.PCW_EN_TTC1 {0} \ + CONFIG.PCW_EN_UART0 {1} \ + CONFIG.PCW_EN_UART1 {0} \ + CONFIG.PCW_EN_USB0 {1} \ + CONFIG.PCW_EN_USB1 {0} \ + CONFIG.PCW_EN_WDT {0} \ + CONFIG.PCW_FCLK0_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_FCLK0_PERIPHERAL_DIVISOR0 {5} \ + CONFIG.PCW_FCLK0_PERIPHERAL_DIVISOR1 {2} \ + CONFIG.PCW_FCLK1_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_FCLK1_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_FCLK1_PERIPHERAL_DIVISOR1 {1} \ + CONFIG.PCW_FCLK2_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_FCLK2_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_FCLK2_PERIPHERAL_DIVISOR1 {1} \ + CONFIG.PCW_FCLK3_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_FCLK3_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_FCLK3_PERIPHERAL_DIVISOR1 {1} \ + CONFIG.PCW_FCLK_CLK0_BUF {TRUE} \ + CONFIG.PCW_FCLK_CLK1_BUF {FALSE} \ + CONFIG.PCW_FCLK_CLK2_BUF {FALSE} \ + CONFIG.PCW_FCLK_CLK3_BUF {FALSE} \ + CONFIG.PCW_FPGA0_PERIPHERAL_FREQMHZ {100} \ + CONFIG.PCW_FPGA1_PERIPHERAL_FREQMHZ {50} \ + CONFIG.PCW_FPGA2_PERIPHERAL_FREQMHZ {50} \ + CONFIG.PCW_FPGA3_PERIPHERAL_FREQMHZ {50} \ + CONFIG.PCW_FPGA_FCLK0_ENABLE {1} \ + CONFIG.PCW_FPGA_FCLK1_ENABLE {0} \ + CONFIG.PCW_FPGA_FCLK2_ENABLE {0} \ + CONFIG.PCW_FPGA_FCLK3_ENABLE {0} \ + CONFIG.PCW_FTM_CTI_IN0 {} \ + CONFIG.PCW_FTM_CTI_IN2 {} \ + CONFIG.PCW_FTM_CTI_OUT0 {} \ + CONFIG.PCW_FTM_CTI_OUT2 {} \ + CONFIG.PCW_GPIO_BASEADDR {0xE000A000} \ + CONFIG.PCW_GPIO_EMIO_GPIO_ENABLE {0} \ + CONFIG.PCW_GPIO_EMIO_GPIO_IO {} \ + CONFIG.PCW_I2C0_HIGHADDR {0xE0004FFF} \ + CONFIG.PCW_I2C0_I2C0_IO {} \ + CONFIG.PCW_I2C1_BASEADDR {0xE0005000} \ + CONFIG.PCW_I2C1_GRP_INT_ENABLE {0} \ + CONFIG.PCW_I2C1_GRP_INT_IO {} \ + CONFIG.PCW_I2C1_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_I2C1_RESET_ENABLE {0} \ + CONFIG.PCW_I2C1_RESET_IO {} \ + CONFIG.PCW_IMPORT_BOARD_PRESET {None} \ + CONFIG.PCW_INCLUDE_ACP_TRANS_CHECK {0} \ + CONFIG.PCW_INCLUDE_TRACE_BUFFER {0} \ + CONFIG.PCW_IOPLL_CTRL_FBDIV {20} \ + CONFIG.PCW_IO_IO_PLL_FREQMHZ {1000.000} \ + CONFIG.PCW_IRQ_F2P_INTR {0} \ + CONFIG.PCW_IRQ_F2P_MODE {DIRECT} \ + CONFIG.PCW_MIO_0_DIRECTION {inout} \ + CONFIG.PCW_MIO_0_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_0_PULLUP {enabled} \ + CONFIG.PCW_MIO_0_SLEW {slow} \ + CONFIG.PCW_MIO_10_DIRECTION {inout} \ + CONFIG.PCW_MIO_10_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_10_PULLUP {enabled} \ + CONFIG.PCW_MIO_10_SLEW {slow} \ + CONFIG.PCW_MIO_11_DIRECTION {inout} \ + CONFIG.PCW_MIO_11_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_11_PULLUP {enabled} \ + CONFIG.PCW_MIO_11_SLEW {slow} \ + CONFIG.PCW_MIO_12_DIRECTION {inout} \ + CONFIG.PCW_MIO_12_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_12_PULLUP {enabled} \ + CONFIG.PCW_MIO_12_SLEW {slow} \ + CONFIG.PCW_MIO_13_DIRECTION {inout} \ + CONFIG.PCW_MIO_13_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_13_PULLUP {enabled} \ + CONFIG.PCW_MIO_13_SLEW {slow} \ + CONFIG.PCW_MIO_14_DIRECTION {in} \ + CONFIG.PCW_MIO_14_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_14_PULLUP {enabled} \ + CONFIG.PCW_MIO_14_SLEW {slow} \ + CONFIG.PCW_MIO_15_DIRECTION {out} \ + CONFIG.PCW_MIO_15_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_15_PULLUP {enabled} \ + CONFIG.PCW_MIO_15_SLEW {slow} \ + CONFIG.PCW_MIO_16_DIRECTION {out} \ + CONFIG.PCW_MIO_16_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_16_PULLUP {enabled} \ + CONFIG.PCW_MIO_16_SLEW {slow} \ + CONFIG.PCW_MIO_17_DIRECTION {out} \ + CONFIG.PCW_MIO_17_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_17_PULLUP {enabled} \ + CONFIG.PCW_MIO_17_SLEW {slow} \ + CONFIG.PCW_MIO_18_DIRECTION {out} \ + CONFIG.PCW_MIO_18_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_18_PULLUP {enabled} \ + CONFIG.PCW_MIO_18_SLEW {slow} \ + CONFIG.PCW_MIO_19_DIRECTION {out} \ + CONFIG.PCW_MIO_19_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_19_PULLUP {enabled} \ + CONFIG.PCW_MIO_19_SLEW {slow} \ + CONFIG.PCW_MIO_1_DIRECTION {out} \ + CONFIG.PCW_MIO_1_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_1_PULLUP {enabled} \ + CONFIG.PCW_MIO_1_SLEW {slow} \ + CONFIG.PCW_MIO_20_DIRECTION {out} \ + CONFIG.PCW_MIO_20_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_20_PULLUP {enabled} \ + CONFIG.PCW_MIO_20_SLEW {slow} \ + CONFIG.PCW_MIO_21_DIRECTION {out} \ + CONFIG.PCW_MIO_21_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_21_PULLUP {enabled} \ + CONFIG.PCW_MIO_21_SLEW {slow} \ + CONFIG.PCW_MIO_22_DIRECTION {in} \ + CONFIG.PCW_MIO_22_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_22_PULLUP {enabled} \ + CONFIG.PCW_MIO_22_SLEW {slow} \ + CONFIG.PCW_MIO_23_DIRECTION {in} \ + CONFIG.PCW_MIO_23_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_23_PULLUP {enabled} \ + CONFIG.PCW_MIO_23_SLEW {slow} \ + CONFIG.PCW_MIO_24_DIRECTION {in} \ + CONFIG.PCW_MIO_24_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_24_PULLUP {enabled} \ + CONFIG.PCW_MIO_24_SLEW {slow} \ + CONFIG.PCW_MIO_25_DIRECTION {in} \ + CONFIG.PCW_MIO_25_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_25_PULLUP {enabled} \ + CONFIG.PCW_MIO_25_SLEW {slow} \ + CONFIG.PCW_MIO_26_DIRECTION {in} \ + CONFIG.PCW_MIO_26_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_26_PULLUP {enabled} \ + CONFIG.PCW_MIO_26_SLEW {slow} \ + CONFIG.PCW_MIO_27_DIRECTION {in} \ + CONFIG.PCW_MIO_27_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_27_PULLUP {enabled} \ + CONFIG.PCW_MIO_27_SLEW {slow} \ + CONFIG.PCW_MIO_28_DIRECTION {inout} \ + CONFIG.PCW_MIO_28_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_28_PULLUP {enabled} \ + CONFIG.PCW_MIO_28_SLEW {slow} \ + CONFIG.PCW_MIO_29_DIRECTION {in} \ + CONFIG.PCW_MIO_29_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_29_PULLUP {enabled} \ + CONFIG.PCW_MIO_29_SLEW {slow} \ + CONFIG.PCW_MIO_2_DIRECTION {inout} \ + CONFIG.PCW_MIO_2_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_2_PULLUP {disabled} \ + CONFIG.PCW_MIO_2_SLEW {slow} \ + CONFIG.PCW_MIO_30_DIRECTION {out} \ + CONFIG.PCW_MIO_30_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_30_PULLUP {enabled} \ + CONFIG.PCW_MIO_30_SLEW {slow} \ + CONFIG.PCW_MIO_31_DIRECTION {in} \ + CONFIG.PCW_MIO_31_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_31_PULLUP {enabled} \ + CONFIG.PCW_MIO_31_SLEW {slow} \ + CONFIG.PCW_MIO_32_DIRECTION {inout} \ + CONFIG.PCW_MIO_32_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_32_PULLUP {enabled} \ + CONFIG.PCW_MIO_32_SLEW {slow} \ + CONFIG.PCW_MIO_33_DIRECTION {inout} \ + CONFIG.PCW_MIO_33_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_33_PULLUP {enabled} \ + CONFIG.PCW_MIO_33_SLEW {slow} \ + CONFIG.PCW_MIO_34_DIRECTION {inout} \ + CONFIG.PCW_MIO_34_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_34_PULLUP {enabled} \ + CONFIG.PCW_MIO_34_SLEW {slow} \ + CONFIG.PCW_MIO_35_DIRECTION {inout} \ + CONFIG.PCW_MIO_35_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_35_PULLUP {enabled} \ + CONFIG.PCW_MIO_35_SLEW {slow} \ + CONFIG.PCW_MIO_36_DIRECTION {in} \ + CONFIG.PCW_MIO_36_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_36_PULLUP {enabled} \ + CONFIG.PCW_MIO_36_SLEW {slow} \ + CONFIG.PCW_MIO_37_DIRECTION {inout} \ + CONFIG.PCW_MIO_37_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_37_PULLUP {enabled} \ + CONFIG.PCW_MIO_37_SLEW {slow} \ + CONFIG.PCW_MIO_38_DIRECTION {inout} \ + CONFIG.PCW_MIO_38_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_38_PULLUP {enabled} \ + CONFIG.PCW_MIO_38_SLEW {slow} \ + CONFIG.PCW_MIO_39_DIRECTION {inout} \ + CONFIG.PCW_MIO_39_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_39_PULLUP {enabled} \ + CONFIG.PCW_MIO_39_SLEW {slow} \ + CONFIG.PCW_MIO_3_DIRECTION {inout} \ + CONFIG.PCW_MIO_3_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_3_PULLUP {disabled} \ + CONFIG.PCW_MIO_3_SLEW {slow} \ + CONFIG.PCW_MIO_40_DIRECTION {inout} \ + CONFIG.PCW_MIO_40_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_40_PULLUP {enabled} \ + CONFIG.PCW_MIO_40_SLEW {slow} \ + CONFIG.PCW_MIO_41_DIRECTION {inout} \ + CONFIG.PCW_MIO_41_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_41_PULLUP {enabled} \ + CONFIG.PCW_MIO_41_SLEW {slow} \ + CONFIG.PCW_MIO_42_DIRECTION {inout} \ + CONFIG.PCW_MIO_42_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_42_PULLUP {enabled} \ + CONFIG.PCW_MIO_42_SLEW {slow} \ + CONFIG.PCW_MIO_43_DIRECTION {inout} \ + CONFIG.PCW_MIO_43_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_43_PULLUP {enabled} \ + CONFIG.PCW_MIO_43_SLEW {slow} \ + CONFIG.PCW_MIO_44_DIRECTION {inout} \ + CONFIG.PCW_MIO_44_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_44_PULLUP {enabled} \ + CONFIG.PCW_MIO_44_SLEW {slow} \ + CONFIG.PCW_MIO_45_DIRECTION {inout} \ + CONFIG.PCW_MIO_45_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_45_PULLUP {enabled} \ + CONFIG.PCW_MIO_45_SLEW {slow} \ + CONFIG.PCW_MIO_46_DIRECTION {out} \ + CONFIG.PCW_MIO_46_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_46_PULLUP {enabled} \ + CONFIG.PCW_MIO_46_SLEW {slow} \ + CONFIG.PCW_MIO_47_DIRECTION {in} \ + CONFIG.PCW_MIO_47_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_47_PULLUP {enabled} \ + CONFIG.PCW_MIO_47_SLEW {slow} \ + CONFIG.PCW_MIO_48_DIRECTION {inout} \ + CONFIG.PCW_MIO_48_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_48_PULLUP {enabled} \ + CONFIG.PCW_MIO_48_SLEW {slow} \ + CONFIG.PCW_MIO_49_DIRECTION {inout} \ + CONFIG.PCW_MIO_49_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_49_PULLUP {enabled} \ + CONFIG.PCW_MIO_49_SLEW {slow} \ + CONFIG.PCW_MIO_4_DIRECTION {inout} \ + CONFIG.PCW_MIO_4_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_4_PULLUP {disabled} \ + CONFIG.PCW_MIO_4_SLEW {slow} \ + CONFIG.PCW_MIO_50_DIRECTION {inout} \ + CONFIG.PCW_MIO_50_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_50_PULLUP {enabled} \ + CONFIG.PCW_MIO_50_SLEW {slow} \ + CONFIG.PCW_MIO_51_DIRECTION {inout} \ + CONFIG.PCW_MIO_51_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_51_PULLUP {enabled} \ + CONFIG.PCW_MIO_51_SLEW {slow} \ + CONFIG.PCW_MIO_52_DIRECTION {out} \ + CONFIG.PCW_MIO_52_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_52_PULLUP {enabled} \ + CONFIG.PCW_MIO_52_SLEW {slow} \ + CONFIG.PCW_MIO_53_DIRECTION {inout} \ + CONFIG.PCW_MIO_53_IOTYPE {LVCMOS 1.8V} \ + CONFIG.PCW_MIO_53_PULLUP {enabled} \ + CONFIG.PCW_MIO_53_SLEW {slow} \ + CONFIG.PCW_MIO_5_DIRECTION {inout} \ + CONFIG.PCW_MIO_5_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_5_PULLUP {disabled} \ + CONFIG.PCW_MIO_5_SLEW {slow} \ + CONFIG.PCW_MIO_6_DIRECTION {out} \ + CONFIG.PCW_MIO_6_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_6_PULLUP {disabled} \ + CONFIG.PCW_MIO_6_SLEW {slow} \ + CONFIG.PCW_MIO_7_DIRECTION {out} \ + CONFIG.PCW_MIO_7_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_7_PULLUP {disabled} \ + CONFIG.PCW_MIO_7_SLEW {slow} \ + CONFIG.PCW_MIO_8_DIRECTION {out} \ + CONFIG.PCW_MIO_8_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_8_PULLUP {disabled} \ + CONFIG.PCW_MIO_8_SLEW {slow} \ + CONFIG.PCW_MIO_9_DIRECTION {out} \ + CONFIG.PCW_MIO_9_IOTYPE {LVCMOS 3.3V} \ + CONFIG.PCW_MIO_9_PULLUP {enabled} \ + CONFIG.PCW_MIO_9_SLEW {slow} \ + CONFIG.PCW_MIO_PRIMITIVE {54} \ + CONFIG.PCW_MIO_TREE_PERIPHERALS {GPIO#Quad SPI Flash#Quad SPI Flash#Quad SPI Flash#Quad SPI Flash#Quad SPI Flash#Quad SPI Flash#GPIO#Quad SPI Flash#ENET Reset#GPIO#GPIO#GPIO#GPIO#UART 0#UART 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#Enet 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#SD 0#SD 0#SD 0#SD 0#SD 0#SD 0#USB Reset#SD 0#GPIO#GPIO#GPIO#GPIO#Enet 0#Enet 0} \ + CONFIG.PCW_MIO_TREE_SIGNALS {gpio[0]#qspi0_ss_b#qspi0_io[0]#qspi0_io[1]#qspi0_io[2]#qspi0_io[3]/HOLD_B#qspi0_sclk#gpio[7]#qspi_fbclk#reset#gpio[10]#gpio[11]#gpio[12]#gpio[13]#rx#tx#tx_clk#txd[0]#txd[1]#txd[2]#txd[3]#tx_ctl#rx_clk#rxd[0]#rxd[1]#rxd[2]#rxd[3]#rx_ctl#data[4]#dir#stp#nxt#data[0]#data[1]#data[2]#data[3]#clk#data[5]#data[6]#data[7]#clk#cmd#data[0]#data[1]#data[2]#data[3]#reset#cd#gpio[48]#gpio[49]#gpio[50]#gpio[51]#mdc#mdio} \ + CONFIG.PCW_M_AXI_GP0_ENABLE_STATIC_REMAP {0} \ + CONFIG.PCW_M_AXI_GP0_ID_WIDTH {12} \ + CONFIG.PCW_M_AXI_GP0_SUPPORT_NARROW_BURST {0} \ + CONFIG.PCW_M_AXI_GP0_THREAD_ID_WIDTH {12} \ + CONFIG.PCW_M_AXI_GP1_ENABLE_STATIC_REMAP {0} \ + CONFIG.PCW_M_AXI_GP1_ID_WIDTH {12} \ + CONFIG.PCW_M_AXI_GP1_SUPPORT_NARROW_BURST {0} \ + CONFIG.PCW_M_AXI_GP1_THREAD_ID_WIDTH {12} \ + CONFIG.PCW_NAND_CYCLES_T_AR {1} \ + CONFIG.PCW_NAND_CYCLES_T_CLR {1} \ + CONFIG.PCW_NAND_CYCLES_T_RC {11} \ + CONFIG.PCW_NAND_CYCLES_T_REA {1} \ + CONFIG.PCW_NAND_CYCLES_T_RR {1} \ + CONFIG.PCW_NAND_CYCLES_T_WC {11} \ + CONFIG.PCW_NAND_CYCLES_T_WP {1} \ + CONFIG.PCW_NAND_GRP_D8_ENABLE {0} \ + CONFIG.PCW_NAND_GRP_D8_IO {} \ + CONFIG.PCW_NAND_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_NOR_CS0_T_CEOE {1} \ + CONFIG.PCW_NOR_CS0_T_PC {1} \ + CONFIG.PCW_NOR_CS0_T_RC {11} \ + CONFIG.PCW_NOR_CS0_T_TR {1} \ + CONFIG.PCW_NOR_CS0_T_WC {11} \ + CONFIG.PCW_NOR_CS0_T_WP {1} \ + CONFIG.PCW_NOR_CS0_WE_TIME {0} \ + CONFIG.PCW_NOR_CS1_T_CEOE {1} \ + CONFIG.PCW_NOR_CS1_T_PC {1} \ + CONFIG.PCW_NOR_CS1_T_RC {11} \ + CONFIG.PCW_NOR_CS1_T_TR {1} \ + CONFIG.PCW_NOR_CS1_T_WC {11} \ + CONFIG.PCW_NOR_CS1_T_WP {1} \ + CONFIG.PCW_NOR_CS1_WE_TIME {0} \ + CONFIG.PCW_NOR_GRP_A25_ENABLE {0} \ + CONFIG.PCW_NOR_GRP_A25_IO {} \ + CONFIG.PCW_NOR_GRP_CS1_ENABLE {0} \ + CONFIG.PCW_NOR_GRP_CS1_IO {} \ + CONFIG.PCW_NOR_GRP_SRAM_CS1_ENABLE {0} \ + CONFIG.PCW_NOR_GRP_SRAM_CS1_IO {} \ + CONFIG.PCW_NOR_NOR_IO {} \ + CONFIG.PCW_PLL_BYPASSMODE_ENABLE {0} \ + CONFIG.PCW_PRESET_BANK0_VOLTAGE {LVCMOS 3.3V} \ + CONFIG.PCW_PRESET_BANK1_VOLTAGE {LVCMOS 1.8V} \ + CONFIG.PCW_PS7_SI_REV {PRODUCTION} \ + CONFIG.PCW_QSPI_GRP_FBCLK_ENABLE {1} \ + CONFIG.PCW_QSPI_GRP_FBCLK_IO {MIO 8} \ + CONFIG.PCW_QSPI_GRP_IO1_ENABLE {0} \ + CONFIG.PCW_QSPI_GRP_IO1_IO {} \ + CONFIG.PCW_QSPI_INTERNAL_HIGHADDRESS {0xFCFFFFFF} \ + CONFIG.PCW_QSPI_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_QSPI_PERIPHERAL_DIVISOR0 {5} \ + CONFIG.PCW_QSPI_PERIPHERAL_ENABLE {1} \ + CONFIG.PCW_QSPI_PERIPHERAL_FREQMHZ {200} \ + CONFIG.PCW_QSPI_QSPI_IO {MIO 1 .. 6} \ + CONFIG.PCW_SD0_GRP_CD_ENABLE {1} \ + CONFIG.PCW_SD0_GRP_CD_IO {MIO 47} \ + CONFIG.PCW_SD0_GRP_POW_ENABLE {0} \ + CONFIG.PCW_SD0_GRP_POW_IO {} \ + CONFIG.PCW_SD0_PERIPHERAL_ENABLE {1} \ + CONFIG.PCW_SD0_SD0_IO {MIO 40 .. 45} \ + CONFIG.PCW_SD1_GRP_CD_ENABLE {0} \ + CONFIG.PCW_SD1_GRP_CD_IO {} \ + CONFIG.PCW_SD1_GRP_WP_ENABLE {0} \ + CONFIG.PCW_SD1_GRP_WP_IO {} \ + CONFIG.PCW_SDIO0_BASEADDR {0xE0100000} \ + CONFIG.PCW_SDIO0_HIGHADDR {0xE0100FFF} \ + CONFIG.PCW_SDIO1_BASEADDR {0xE0101000} \ + CONFIG.PCW_SDIO1_HIGHADDR {0xE0101FFF} \ + CONFIG.PCW_SDIO_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_SDIO_PERIPHERAL_DIVISOR0 {20} \ + CONFIG.PCW_SDIO_PERIPHERAL_FREQMHZ {50} \ + CONFIG.PCW_SDIO_PERIPHERAL_VALID {1} \ + CONFIG.PCW_SINGLE_QSPI_DATA_MODE {x4} \ + CONFIG.PCW_SMC_CYCLE_T0 {NA} \ + CONFIG.PCW_SMC_CYCLE_T1 {NA} \ + CONFIG.PCW_SMC_CYCLE_T2 {NA} \ + CONFIG.PCW_SMC_CYCLE_T3 {NA} \ + CONFIG.PCW_SMC_CYCLE_T4 {NA} \ + CONFIG.PCW_SMC_CYCLE_T5 {NA} \ + CONFIG.PCW_SMC_CYCLE_T6 {NA} \ + CONFIG.PCW_SMC_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_SMC_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_SMC_PERIPHERAL_FREQMHZ {100} \ + CONFIG.PCW_SMC_PERIPHERAL_VALID {0} \ + CONFIG.PCW_SPI0_BASEADDR {0xE0006000} \ + CONFIG.PCW_SPI0_GRP_SS0_ENABLE {0} \ + CONFIG.PCW_SPI0_GRP_SS0_IO {} \ + CONFIG.PCW_SPI0_GRP_SS2_ENABLE {0} \ + CONFIG.PCW_SPI0_GRP_SS2_IO {} \ + CONFIG.PCW_SPI1_BASEADDR {0xE0007000} \ + CONFIG.PCW_SPI1_GRP_SS0_ENABLE {0} \ + CONFIG.PCW_SPI1_GRP_SS0_IO {} \ + CONFIG.PCW_SPI1_GRP_SS2_ENABLE {0} \ + CONFIG.PCW_SPI1_GRP_SS2_IO {} \ + CONFIG.PCW_SPI_PERIPHERAL_CLKSRC {IO PLL} \ + CONFIG.PCW_SPI_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_SPI_PERIPHERAL_FREQMHZ {166.666666} \ + CONFIG.PCW_SPI_PERIPHERAL_VALID {0} \ + CONFIG.PCW_S_AXI_ACP_ARUSER_VAL {31} \ + CONFIG.PCW_S_AXI_ACP_AWUSER_VAL {31} \ + CONFIG.PCW_S_AXI_ACP_ID_WIDTH {3} \ + CONFIG.PCW_S_AXI_GP0_ID_WIDTH {6} \ + CONFIG.PCW_S_AXI_GP1_ID_WIDTH {6} \ + CONFIG.PCW_S_AXI_HP0_DATA_WIDTH {64} \ + CONFIG.PCW_S_AXI_HP0_ID_WIDTH {6} \ + CONFIG.PCW_S_AXI_HP1_DATA_WIDTH {64} \ + CONFIG.PCW_S_AXI_HP1_ID_WIDTH {6} \ + CONFIG.PCW_S_AXI_HP2_DATA_WIDTH {64} \ + CONFIG.PCW_S_AXI_HP2_ID_WIDTH {6} \ + CONFIG.PCW_S_AXI_HP3_DATA_WIDTH {64} \ + CONFIG.PCW_S_AXI_HP3_ID_WIDTH {6} \ + CONFIG.PCW_TPIU_PERIPHERAL_CLKSRC {External} \ + CONFIG.PCW_TPIU_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_TPIU_PERIPHERAL_FREQMHZ {200} \ + CONFIG.PCW_TRACE_BUFFER_CLOCK_DELAY {12} \ + CONFIG.PCW_TRACE_BUFFER_FIFO_SIZE {128} \ + CONFIG.PCW_TRACE_GRP_16BIT_ENABLE {0} \ + CONFIG.PCW_TRACE_GRP_16BIT_IO {} \ + CONFIG.PCW_TRACE_GRP_32BIT_ENABLE {0} \ + CONFIG.PCW_TRACE_GRP_32BIT_IO {} \ + CONFIG.PCW_TRACE_GRP_8BIT_ENABLE {0} \ + CONFIG.PCW_TRACE_GRP_8BIT_IO {} \ + CONFIG.PCW_TTC0_BASEADDR {0xE0104000} \ + CONFIG.PCW_TTC0_CLK0_PERIPHERAL_CLKSRC {CPU_1X} \ + CONFIG.PCW_TTC0_CLK0_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_TTC0_CLK0_PERIPHERAL_FREQMHZ {133.333333} \ + CONFIG.PCW_TTC0_CLK1_PERIPHERAL_CLKSRC {CPU_1X} \ + CONFIG.PCW_TTC0_CLK1_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_TTC0_CLK1_PERIPHERAL_FREQMHZ {133.333333} \ + CONFIG.PCW_TTC0_CLK2_PERIPHERAL_CLKSRC {CPU_1X} \ + CONFIG.PCW_TTC0_CLK2_PERIPHERAL_DIVISOR0 {1} \ + CONFIG.PCW_TTC0_CLK2_PERIPHERAL_FREQMHZ {133.333333} \ + CONFIG.PCW_TTC0_HIGHADDR {0xE0104fff} \ + CONFIG.PCW_TTC0_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_TTC0_TTC0_IO {} \ + CONFIG.PCW_TTC_PERIPHERAL_FREQMHZ {50} \ + CONFIG.PCW_UART0_BASEADDR {0xE0000000} \ + CONFIG.PCW_UART0_BAUD_RATE {115200} \ + CONFIG.PCW_UART0_GRP_FULL_ENABLE {0} \ + CONFIG.PCW_UART0_GRP_FULL_IO {} \ + CONFIG.PCW_UART1_HIGHADDR {0xE0001FFF} \ + CONFIG.PCW_UART1_PERIPHERAL_ENABLE {0} \ + CONFIG.PCW_UART1_UART1_IO {} \ + CONFIG.PCW_USB1_USB1_IO {} \ + ] $processing_system7_0 + + # Create instance: ps7_0_axi_periph, and set properties + set ps7_0_axi_periph [ create_bd_cell -type ip -vlnv xilinx.com:ip:axi_interconnect:2.1 ps7_0_axi_periph ] + set_property -dict [ list \ + CONFIG.NUM_MI {2} \ + ] $ps7_0_axi_periph + + # Create instance: pynqrouter_0, and set properties + set pynqrouter_0 [ create_bd_cell -type ip -vlnv xilinx.com:hls:pynqrouter:1.0 pynqrouter_0 ] + + # Create instance: rst_ps7_0_100M, and set properties + set rst_ps7_0_100M [ create_bd_cell -type ip -vlnv xilinx.com:ip:proc_sys_reset:5.0 rst_ps7_0_100M ] + + # Create interface connections + connect_bd_intf_net -intf_net processing_system7_0_DDR [get_bd_intf_ports DDR] [get_bd_intf_pins processing_system7_0/DDR] + connect_bd_intf_net -intf_net processing_system7_0_FIXED_IO [get_bd_intf_ports FIXED_IO] [get_bd_intf_pins processing_system7_0/FIXED_IO] + connect_bd_intf_net -intf_net processing_system7_0_M_AXI_GP0 [get_bd_intf_pins processing_system7_0/M_AXI_GP0] [get_bd_intf_pins ps7_0_axi_periph/S00_AXI] + connect_bd_intf_net -intf_net ps7_0_axi_periph_M00_AXI [get_bd_intf_pins ps7_0_axi_periph/M00_AXI] [get_bd_intf_pins pynqrouter_0/s_axi_AXI4LS] + connect_bd_intf_net -intf_net ps7_0_axi_periph_M01_AXI [get_bd_intf_pins axi_gpio_0/S_AXI] [get_bd_intf_pins ps7_0_axi_periph/M01_AXI] + + # Create port connections + connect_bd_net -net axi_gpio_0_gpio_io_o [get_bd_ports LD] [get_bd_pins axi_gpio_0/gpio_io_o] + connect_bd_net -net processing_system7_0_FCLK_CLK0 [get_bd_pins axi_gpio_0/s_axi_aclk] [get_bd_pins processing_system7_0/FCLK_CLK0] [get_bd_pins processing_system7_0/M_AXI_GP0_ACLK] [get_bd_pins ps7_0_axi_periph/ACLK] [get_bd_pins ps7_0_axi_periph/M00_ACLK] [get_bd_pins ps7_0_axi_periph/M01_ACLK] [get_bd_pins ps7_0_axi_periph/S00_ACLK] [get_bd_pins pynqrouter_0/ap_clk] [get_bd_pins rst_ps7_0_100M/slowest_sync_clk] + connect_bd_net -net processing_system7_0_FCLK_RESET0_N [get_bd_pins processing_system7_0/FCLK_RESET0_N] [get_bd_pins rst_ps7_0_100M/ext_reset_in] + connect_bd_net -net rst_ps7_0_100M_interconnect_aresetn [get_bd_pins ps7_0_axi_periph/ARESETN] [get_bd_pins rst_ps7_0_100M/interconnect_aresetn] + connect_bd_net -net rst_ps7_0_100M_peripheral_aresetn [get_bd_pins axi_gpio_0/s_axi_aresetn] [get_bd_pins ps7_0_axi_periph/M00_ARESETN] [get_bd_pins ps7_0_axi_periph/M01_ARESETN] [get_bd_pins ps7_0_axi_periph/S00_ARESETN] [get_bd_pins pynqrouter_0/ap_rst_n] [get_bd_pins rst_ps7_0_100M/peripheral_aresetn] + + # Create address segments + create_bd_addr_seg -range 0x00010000 -offset 0x41200000 [get_bd_addr_spaces processing_system7_0/Data] [get_bd_addr_segs axi_gpio_0/S_AXI/Reg] SEG_axi_gpio_0_Reg + create_bd_addr_seg -range 0x00040000 -offset 0x43C00000 [get_bd_addr_spaces processing_system7_0/Data] [get_bd_addr_segs pynqrouter_0/s_axi_AXI4LS/Reg] SEG_pynqrouter_0_Reg + + + # Restore current instance + current_bd_instance $oldCurInst + + save_bd_design +} +# End of create_root_design() + + +################################################################## +# MAIN FLOW +################################################################## + +create_root_design "" + + diff --git a/hls_2018/router_03/router.cpp b/hls_2018/router_03/router.cpp index 772d420..9d01b73 100755 --- a/hls_2018/router_03/router.cpp +++ b/hls_2018/router_03/router.cpp @@ -51,7 +51,7 @@ bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *stat // For each line // Note: Should not partition completely bool adjacents[MAX_LINES]; // Line has adjacent terminals? - ap_uint starts[MAX_LINES]; // Start list + ap_uint starts[MAX_LINES]; // Start list ap_uint goals[MAX_LINES]; // Goal list ap_uint s_idx[MAX_LINES]; // Start point on line buffer @@ -151,6 +151,7 @@ bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *stat // Memories for Overlap Check ap_uint<1> overlap_checks[MAX_CELLS]; +#pragma HLS ARRAY_PARTITION variable=overlap_checks cyclic factor=32 dim=1 bool has_overlap = false; // ================================ @@ -188,6 +189,7 @@ bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *stat // (Step.2-1) Reset weights of target line WEIGHT_RESET: for (ap_uint j = s_idx[target]; j != s_idx[next_target]; j++) { +#pragma HLS UNROLL factor=2 #pragma HLS LOOP_TRIPCOUNT min=1 max=256 weights[paths[j]] = 1; } @@ -196,11 +198,13 @@ bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *stat ap_uint<8> current_round_weight = new_weight(round); WEIGHT_PATH: for (ap_uint j = s_idx[next_target]; j != pointer; j++) { +#pragma HLS UNROLL factor=2 #pragma HLS LOOP_TRIPCOUNT min=1 max=8192 weights[paths[j]] = current_round_weight; } WEIGHT_TERMINAL: for (ap_uint i = 0; i < (ap_uint)(line_num); i++) { +#pragma HLS UNROLL factor=2 #pragma HLS LOOP_TRIPCOUNT min=2 max=999 weights[starts[i]] = MAX_WEIGHT; weights[goals[i]] = MAX_WEIGHT; @@ -230,16 +234,19 @@ bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *stat has_overlap = false; OVERLAP_RESET: for (ap_uint i = 0; i < (ap_uint)(MAX_CELLS); i++) { +#pragma HLS UNROLL factor=32 overlap_checks[i] = 0; } OVERLAP_CHECK_LINE: for (ap_uint i = 0; i < (ap_uint)(line_num); i++) { +#pragma HLS UNROLL factor=2 #pragma HLS LOOP_TRIPCOUNT min=2 max=999 overlap_checks[starts[i]] = 1; overlap_checks[goals[i]] = 1; } OVERLAP_CHECK_PATH: for (ap_uint j = s_idx[next_target]; j != pointer; j++) { +#pragma HLS UNROLL factor=2 #pragma HLS LOOP_TRIPCOUNT min=1 max=8192 ap_uint cell_id = paths[j]; if (overlap_checks[cell_id]) { @@ -340,10 +347,12 @@ ap_uint<3> abs_uint3(ap_uint<3> a, ap_uint<3> b) { ap_uint search(ap_uint idx, ap_uint paths[MAX_BUFFER], ap_uint start, ap_uint goal, ap_uint<8> w[MAX_CELLS]) { ap_uint dist[MAX_CELLS]; +#pragma HLS ARRAY_PARTITION variable=dist cyclic factor=64 dim=1 ap_uint prev[MAX_CELLS]; SEARCH_INIT_DIST: for (ap_uint i = 0; i < (ap_uint)(MAX_CELLS); i++) { +#pragma HLS UNROLL factor=64 dist[i] = 65535; // = (2^16 - 1) } @@ -459,7 +468,7 @@ void pq_push(ap_uint<32> pq_nodes[MAX_PQ], ap_uint<16> priority, ap_uint<16> dat ap_uint p = (*pq_len) >> 1; // parent node PQ_PUSH_LOOP: while (i > 1 && (ap_uint<16>)(pq_nodes[p] & PQ_PRIORITY_MASK) >= priority) { -#pragma HLS LOOP_TRIPCOUNT min=0 max=15 +#pragma HLS LOOP_TRIPCOUNT min=0 max=14 /** Set!: min=0 max=PQ_BIT **/ pq_nodes[i] = pq_nodes[p]; i = p; @@ -482,7 +491,7 @@ void pq_pop(ap_uint<32> pq_nodes[MAX_PQ], ap_uint<16> *ret_priority, ap_uint<16> PQ_POP_LOOP: while (!(i >> (PQ_BIT-1))) { // (2018.08.24) Loop condition fixed -#pragma HLS LOOP_TRIPCOUNT min=1 max=15 +#pragma HLS LOOP_TRIPCOUNT min=1 max=14 /** Set!: min=0 max=PQ_BIT **/ ap_uint c1 = i << 1; // child node(left) ap_uint c2 = c1 + 1; // child node(right) diff --git a/hls_2018/router_03/router.hpp b/hls_2018/router_03/router.hpp index 0f523d4..18e1bcc 100755 --- a/hls_2018/router_03/router.hpp +++ b/hls_2018/router_03/router.hpp @@ -29,11 +29,11 @@ using namespace std; #define MAX_CELLS 41472 // Max #cells (16bit) #define MAX_LINES 1024 // Max #lines (10bit) -#define MAX_PQ 32768 // Queue size (15bit) +#define MAX_PQ 16384 // Queue size (14bit) #define MAX_BUFFER 16384 // Line buffer size (14bit) #define CELL_BIT 16 #define LINE_BIT 10 -#define PQ_BIT 15 +#define PQ_BIT 14 #define BUFF_BIT 14 #define PQ_PRIORITY_WIDTH 16 -- 2.22.0 From 05891b659c5e8962d937c1c1396df28a7e6b0ef0 Mon Sep 17 00:00:00 2001 From: KazushiKawamura Date: Sun, 26 Aug 2018 16:25:47 +0900 Subject: [PATCH 23/30] Fix a little --- hls_2018/router_03/router.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hls_2018/router_03/router.cpp b/hls_2018/router_03/router.cpp index 9d01b73..b6f255e 100755 --- a/hls_2018/router_03/router.cpp +++ b/hls_2018/router_03/router.cpp @@ -51,7 +51,7 @@ bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *stat // For each line // Note: Should not partition completely bool adjacents[MAX_LINES]; // Line has adjacent terminals? - ap_uint starts[MAX_LINES]; // Start list + ap_uint starts[MAX_LINES]; // Start list ap_uint goals[MAX_LINES]; // Goal list ap_uint s_idx[MAX_LINES]; // Start point on line buffer -- 2.22.0 From 5430e8a2a408e90f055a05b69cbbbd9ccf9c9094 Mon Sep 17 00:00:00 2001 From: KazushiKawamura Date: Sun, 26 Aug 2018 21:50:14 +0900 Subject: [PATCH 24/30] Add pragma for Vivado-HLS --- hls_2018/router_01/router.cpp | 10 ++++++++++ hls_2018/router_02/router.cpp | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/hls_2018/router_01/router.cpp b/hls_2018/router_01/router.cpp index de396f1..19e47cf 100755 --- a/hls_2018/router_01/router.cpp +++ b/hls_2018/router_01/router.cpp @@ -68,6 +68,7 @@ bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *stat INIT_WEIGHTS: for (ap_uint i = 0; i < (ap_uint)(MAX_CELLS); i++) { +#pragma HLS UNROLL factor=2 weights[i] = 1; } @@ -151,6 +152,7 @@ bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *stat // Memories for Overlap Check ap_uint<1> overlap_checks[MAX_CELLS]; +#pragma HLS ARRAY_PARTITION variable=overlap_checks cyclic factor=16 dim=1 bool has_overlap = false; // ================================ @@ -188,6 +190,7 @@ bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *stat // (Step.2-1) Reset weights of target line WEIGHT_RESET: for (ap_uint j = s_idx[target]; j != s_idx[next_target]; j++) { +#pragma HLS UNROLL factor=2 #pragma HLS LOOP_TRIPCOUNT min=1 max=256 weights[paths[j]] = 1; } @@ -196,11 +199,13 @@ bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *stat ap_uint<8> current_round_weight = new_weight(round); WEIGHT_PATH: for (ap_uint j = s_idx[next_target]; j != pointer; j++) { +#pragma HLS UNROLL factor=2 #pragma HLS LOOP_TRIPCOUNT min=1 max=8192 weights[paths[j]] = current_round_weight; } WEIGHT_TERMINAL: for (ap_uint i = 0; i < (ap_uint)(line_num); i++) { +#pragma HLS UNROLL factor=2 #pragma HLS LOOP_TRIPCOUNT min=2 max=999 weights[starts[i]] = MAX_WEIGHT; weights[goals[i]] = MAX_WEIGHT; @@ -230,16 +235,19 @@ bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *stat has_overlap = false; OVERLAP_RESET: for (ap_uint i = 0; i < (ap_uint)(MAX_CELLS); i++) { +#pragma HLS UNROLL factor=32 overlap_checks[i] = 0; } OVERLAP_CHECK_LINE: for (ap_uint i = 0; i < (ap_uint)(line_num); i++) { +#pragma HLS UNROLL factor=2 #pragma HLS LOOP_TRIPCOUNT min=2 max=999 overlap_checks[starts[i]] = 1; overlap_checks[goals[i]] = 1; } OVERLAP_CHECK_PATH: for (ap_uint j = s_idx[next_target]; j != pointer; j++) { +#pragma HLS UNROLL factor=2 #pragma HLS LOOP_TRIPCOUNT min=1 max=8192 ap_uint cell_id = paths[j]; if (overlap_checks[cell_id]) { @@ -340,10 +348,12 @@ ap_uint<3> abs_uint3(ap_uint<3> a, ap_uint<3> b) { ap_uint search(ap_uint idx, ap_uint paths[MAX_BUFFER], ap_uint start, ap_uint goal, ap_uint<8> w[MAX_CELLS]) { ap_uint dist[MAX_CELLS]; +#pragma HLS ARRAY_PARTITION variable=dist cyclic factor=64 dim=1 ap_uint prev[MAX_CELLS]; SEARCH_INIT_DIST: for (ap_uint i = 0; i < (ap_uint)(MAX_CELLS); i++) { +#pragma HLS UNROLL factor=128 dist[i] = 65535; // = (2^16 - 1) } diff --git a/hls_2018/router_02/router.cpp b/hls_2018/router_02/router.cpp index cf50624..d6e76f3 100755 --- a/hls_2018/router_02/router.cpp +++ b/hls_2018/router_02/router.cpp @@ -68,6 +68,7 @@ bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *stat INIT_WEIGHTS: for (ap_uint i = 0; i < (ap_uint)(MAX_CELLS); i++) { +#pragma HLS UNROLL factor=2 weights[i] = 1; } @@ -151,6 +152,7 @@ bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *stat // Memories for Overlap Check ap_uint<1> overlap_checks[MAX_CELLS]; +#pragma HLS ARRAY_PARTITION variable=overlap_checks cyclic factor=16 dim=1 bool has_overlap = false; // ================================ @@ -188,6 +190,7 @@ bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *stat // (Step.2-1) Reset weights of target line WEIGHT_RESET: for (ap_uint j = s_idx[target]; j != s_idx[next_target]; j++) { +#pragma HLS UNROLL factor=2 #pragma HLS LOOP_TRIPCOUNT min=1 max=256 weights[paths[j]] = 1; } @@ -196,11 +199,13 @@ bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *stat ap_uint<8> current_round_weight = new_weight(round); WEIGHT_PATH: for (ap_uint j = s_idx[next_target]; j != pointer; j++) { +#pragma HLS UNROLL factor=2 #pragma HLS LOOP_TRIPCOUNT min=1 max=8192 weights[paths[j]] = current_round_weight; } WEIGHT_TERMINAL: for (ap_uint i = 0; i < (ap_uint)(line_num); i++) { +#pragma HLS UNROLL factor=2 #pragma HLS LOOP_TRIPCOUNT min=2 max=999 weights[starts[i]] = MAX_WEIGHT; weights[goals[i]] = MAX_WEIGHT; @@ -230,16 +235,19 @@ bool pynqrouter(char boardstr[BOARDSTR_SIZE], ap_uint<32> seed, ap_int<32> *stat has_overlap = false; OVERLAP_RESET: for (ap_uint i = 0; i < (ap_uint)(MAX_CELLS); i++) { +#pragma HLS UNROLL factor=32 overlap_checks[i] = 0; } OVERLAP_CHECK_LINE: for (ap_uint i = 0; i < (ap_uint)(line_num); i++) { +#pragma HLS UNROLL factor=2 #pragma HLS LOOP_TRIPCOUNT min=2 max=999 overlap_checks[starts[i]] = 1; overlap_checks[goals[i]] = 1; } OVERLAP_CHECK_PATH: for (ap_uint j = s_idx[next_target]; j != pointer; j++) { +#pragma HLS UNROLL factor=2 #pragma HLS LOOP_TRIPCOUNT min=1 max=8192 ap_uint cell_id = paths[j]; if (overlap_checks[cell_id]) { @@ -340,10 +348,12 @@ ap_uint<3> abs_uint3(ap_uint<3> a, ap_uint<3> b) { ap_uint search(ap_uint idx, ap_uint paths[MAX_BUFFER], ap_uint start, ap_uint goal, ap_uint<8> w[MAX_CELLS]) { ap_uint dist[MAX_CELLS]; +#pragma HLS ARRAY_PARTITION variable=dist cyclic factor=64 dim=1 ap_uint prev[MAX_CELLS]; SEARCH_INIT_DIST: for (ap_uint i = 0; i < (ap_uint)(MAX_CELLS); i++) { +#pragma HLS UNROLL factor=128 dist[i] = 65535; // = (2^16 - 1) } -- 2.22.0 From 4517dd63083988dd0d968e7654d3d883ad41e5b0 Mon Sep 17 00:00:00 2001 From: KazushiKawamura Date: Sun, 26 Aug 2018 21:55:39 +0900 Subject: [PATCH 25/30] Add bitstream files --- .../router_02/bitstream/04/router_design.bit | Bin 0 -> 4045681 bytes .../router_02/bitstream/04/router_design.tcl | 1113 +++++++++++++++++ .../router_02/bitstream/16/router_design.bit | Bin 0 -> 4045681 bytes .../router_02/bitstream/16/router_design.tcl | 1113 +++++++++++++++++ 4 files changed, 2226 insertions(+) create mode 100755 hls_2018/router_02/bitstream/04/router_design.bit create mode 100755 hls_2018/router_02/bitstream/04/router_design.tcl create mode 100755 hls_2018/router_02/bitstream/16/router_design.bit create mode 100755 hls_2018/router_02/bitstream/16/router_design.tcl diff --git a/hls_2018/router_02/bitstream/04/router_design.bit b/hls_2018/router_02/bitstream/04/router_design.bit new file mode 100755 index 0000000000000000000000000000000000000000..e396b3e06fcf693a98398e4136bf1e4e1eace62d GIT binary patch literal 4045681 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 zB2XewB2XewB2XewB2XewB2XewB2XewB2XewB2XewB2XewB2XewB2XewB2XewB2Xew zB2XewB2XewB2XewB2XewB2XewB2XewB2XewB2XewB2XewB2XewB2XewB2XewB2Xew zB2XewB2XewB2XewB2XewB2XewB2XewB2XewB2XewB2XewB2XewB2XewB2XewB2Xew zB2XewB2XewB2XewB2XewB2XewB2XewB2XewB2XewB2XewB2XewB2XewB2XewB2Xew zB2XewB2XewB2XewB2XewB2XewB2XewB2XewB2XewB2XewB2XewB2XewB2XewB2Xew zB2XewB2XewB2XewB2XewB2XewB2XewB2XewB2XewB2XewB2XewB2XewB2XewB2Xew zB2XewB2XewB2XewB2XewB2XewB2XewB2XewB2XewB2XewB2XewB2XewB2XewB2Xew zB2XewB2XewB2XewB2XewB2XewB2XewB2XewB2XewB2XewB2XewB2XewB2XewB2Xew zB2XewB2XewB2XewB2XewB2XewB2XewB2XewB2XewB2XewB2XewB2XewB2XewB2Xew zB2XewB2XewB2XewB2XewB2XewB2XewB2XewB2Xf*a0Ko&EiW>o-fHqY>B>5`)SXHR zvr2G6XWG?w8WxUx=HGX+J<~MmrtY1LQ7MzrhnCQn7VO&f>2_wixFzk;zwc^GGhv94 z)QPAIHBG%4V^C^RcllX}*YuRrOiA~+&gE&7PJ*&l7Joh9v>-Ili%>;$L2RP_vjr{p zXqFCRkFJ9G5@VH$VTl-vj8~P~YdSkG^HpX!A?64l;d&e-aVkyqQnlnAX;G6JI!%b8 zh>6Zaf0Hmx#ndphEy-jU@Q|RYd0b*sd6(i@YS$YrY9S7R(SwZDP9_;=RFl|IEH{py z>pBYl#%hAU2sWb1*%Kq<_IFptCw1y8!_69{+(E>Iv+s56PacK6H59#)pOG4c_qV5qK+OL@khN!DZht#Y%w0PvV zhiT3p!!SRuiIzEtR$U&(YMdNub!ccW^JMKCf}4O0jK2v6{YcW^4y9=x=AI`>QwwdK z9sLv5w0?@tw0chaN8dNi*%6m%-+!sCrw_Cmcc0)(9|p9&_VfUyqEaGIB2XewB2Xew zB2XewB2XewB2XewB2XewB2XewBG4IuaF0c&bSU%gP{pD*AOa8nhXG16RrE}aqEI4G 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%0DCS&7}BU0k|@vS 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