diff --git a/hls_2018/router_02_boardstr/Makefile b/hls_2018/router_02_boardstr/Makefile new file mode 100755 index 0000000000000000000000000000000000000000..8f79e7a62ede483ae7dcda810f306a02f915dfbb --- /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 0000000000000000000000000000000000000000..866fdcdf2ea6a5fb67d1461ce4a19e353d0c9216 --- /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 0000000000000000000000000000000000000000..22133932836bb8b98d3ed1def664d05b1732b8a6 --- /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 0000000000000000000000000000000000000000..b8d9fdc96ac3f7eb9c86cc55d0eac0a57bf670b5 --- /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 Binary files /dev/null and b/hls_2018/router_02_boardstr/bitstream/04/router_design.bit differ 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 0000000000000000000000000000000000000000..e5347dff159dc309b6768469faa92beeede33e8e --- /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 0000000000000000000000000000000000000000..5be571dd70e490d282d279a4eeed32db069703e9 --- /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 0000000000000000000000000000000000000000..887ccd88bfd52d1777db8661d72c57703ccf736a --- /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 0000000000000000000000000000000000000000..1a68a9e56e950d7108a3014149623c017023d809 --- /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 0000000000000000000000000000000000000000..2de79fc3624c71a11ed8c2513163805ae5c0a5ea --- /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 0000000000000000000000000000000000000000..d40f356490488b60c4334a9dad1db807abcf9262 --- /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 0000000000000000000000000000000000000000..a029ae8894e217aa5ff1c6b1013bbfffe573cede --- /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 Binary files /dev/null and b/hls_2018/router_04_boardstr/bitstream/router_design.bit differ diff --git a/hls_2018/router_04_boardstr/bitstream/router_design.tcl b/hls_2018/router_04_boardstr/bitstream/router_design.tcl new file mode 100755 index 0000000000000000000000000000000000000000..48425529f62524b8fe2400c7af4fa74fb981b349 --- /dev/null +++ b/hls_2018/router_04_boardstr/bitstream/router_design.tcl @@ -0,0 +1,844 @@ + +################################################################ +# 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 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 9c739e232e7de17abe1ace528c1c083acf7af851..367b122e70388f09c5462b971ade2d5a16aa0cae 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 3a3054236ffa14e39b05e4674f157d4540f28d86..0c0452b170773166ac40f2687fa39bc4817fc291 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 0000000000000000000000000000000000000000..8f79e7a62ede483ae7dcda810f306a02f915dfbb --- /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 0000000000000000000000000000000000000000..866fdcdf2ea6a5fb67d1461ce4a19e353d0c9216 --- /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 0000000000000000000000000000000000000000..b8d9fdc96ac3f7eb9c86cc55d0eac0a57bf670b5 --- /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 0000000000000000000000000000000000000000..5be571dd70e490d282d279a4eeed32db069703e9 --- /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 0000000000000000000000000000000000000000..887ccd88bfd52d1777db8661d72c57703ccf736a --- /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 0000000000000000000000000000000000000000..1a68a9e56e950d7108a3014149623c017023d809 --- /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 0000000000000000000000000000000000000000..60f08ea2e519a8ff39686c2aa7a561ab4249b229 --- /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 0000000000000000000000000000000000000000..d086860d0e1da2ff5a01a8c86936208398ce611e --- /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 0000000000000000000000000000000000000000..08d93637549ded9591f8a06d7b60b2f55b564778 --- /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 ba77daa34bb0df7b5f97419b431463dbfb1fd3ff..0000000000000000000000000000000000000000 --- 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