| /***************************************************************************** |
| |
| Licensed to Accellera Systems Initiative Inc. (Accellera) under one or |
| more contributor license agreements. See the NOTICE file distributed |
| with this work for additional information regarding copyright ownership. |
| Accellera licenses this file to you 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. |
| |
| *****************************************************************************/ |
| |
| /***************************************************************************** |
| |
| sc_proxy.h -- Proxy base class for vector data types. |
| |
| This class is created for several purposes: |
| 1) hiding operators from the global namespace that would be |
| otherwise found by Koenig lookup |
| 2) avoiding repeating the same operations in every class |
| including proxies that could also be achieved by common |
| base class, but this method allows |
| 3) improve performance by using non-virtual functions |
| |
| Original Author: Gene Bushuyev, Synopsys, Inc. |
| |
| *****************************************************************************/ |
| |
| /***************************************************************************** |
| |
| MODIFICATION LOG - modifiers, enter your name, affiliation, date and |
| changes you are making here. |
| |
| Name, Affiliation, Date: |
| Description of Modification: |
| |
| *****************************************************************************/ |
| |
| // $Log: sc_proxy.h,v $ |
| // Revision 1.3 2010/12/07 20:09:07 acg |
| // Andy Goodrich: Fix for returning enough data |
| // |
| // Revision 1.2 2009/02/28 00:26:14 acg |
| // Andy Goodrich: bug fixes. |
| // |
| // Revision 1.1.1.1 2006/12/15 20:31:36 acg |
| // SystemC 2.2 |
| // |
| // Revision 1.3 2006/01/13 18:53:53 acg |
| // Andy Goodrich: added $Log command so that CVS comments are reproduced in |
| // the source. |
| // |
| |
| #ifndef __SYSTEMC_EXT_DT_BIT_SC_PROXY_HH__ |
| #define __SYSTEMC_EXT_DT_BIT_SC_PROXY_HH__ |
| |
| #include <iostream> |
| |
| #include "../../utils/functions.hh" |
| #include "../int/sc_int_base.hh" |
| #include "../int/sc_signed.hh" |
| #include "../int/sc_uint_base.hh" |
| #include "../int/sc_unsigned.hh" |
| #include "messages.hh" |
| #include "sc_bit.hh" |
| #include "sc_logic.hh" |
| |
| namespace sc_dt |
| { |
| |
| // classes defined in this module |
| template <class X> |
| class sc_proxy; |
| |
| // forward class declarations |
| class sc_bv_base; |
| class sc_lv_base; |
| template <class X> |
| class sc_bitref_r; |
| template <class X> |
| class sc_bitref; |
| template <class X> |
| class sc_subref_r; |
| template <class X> |
| class sc_subref; |
| template <class X, class Y> |
| class sc_concref_r; |
| template <class X, class Y> |
| class sc_concref; |
| |
| const int SC_DIGIT_SIZE = BITS_PER_BYTE * sizeof(sc_digit); |
| |
| const sc_digit SC_DIGIT_ZERO = (sc_digit)0; |
| const sc_digit SC_DIGIT_ONE = (sc_digit)1; |
| const sc_digit SC_DIGIT_TWO = (sc_digit)2; |
| |
| void sc_proxy_out_of_bounds(const char *msg=NULL, int64 val=0); |
| |
| // assignment functions; forward declarations |
| |
| template <class X, class Y> |
| inline void assign_p_(sc_proxy<X> &px, const sc_proxy<Y> &py); |
| |
| // Vector types that are not derived from sc_proxy must have a length() |
| // function and an operator []. |
| |
| template <class X, class T> |
| inline void assign_v_(sc_proxy<X> &px, const T &a); |
| |
| // other functions; forward declarations |
| const std::string convert_to_bin(const char *s); |
| const std::string convert_to_fmt(const std::string &s, sc_numrep numrep, bool); |
| |
| // ---------------------------------------------------------------------------- |
| // CLASS TEMPLATE : sc_proxy_traits |
| // |
| // Template traits helper to select the correct bit/value/vector_types for |
| // sc_proxy-based vector classes. |
| // |
| // All types derived from/based on a bit-vector contain typedef to a plain |
| // bool, all others point to the sc_logic_value_t/sc_logic/sc_lv_base types. |
| // ---------------------------------------------------------------------------- |
| |
| template <typename X> |
| struct sc_proxy_traits; |
| |
| template <> |
| struct sc_proxy_traits<sc_bv_base> |
| { |
| typedef sc_proxy_traits<sc_bv_base> traits_type; |
| typedef bool value_type; |
| typedef sc_logic bit_type; // sc_logic needed for mixed expressions |
| typedef sc_bv_base vector_type; |
| }; |
| |
| template <> |
| struct sc_proxy_traits<sc_lv_base> |
| { |
| typedef sc_proxy_traits<sc_lv_base> traits_type; |
| typedef sc_logic_value_t value_type; |
| typedef sc_logic bit_type; |
| typedef sc_lv_base vector_type; |
| }; |
| |
| template <typename X> |
| struct sc_proxy_traits<sc_bitref_r<X> > : sc_proxy_traits<X> {}; |
| |
| template <typename X> |
| struct sc_proxy_traits<sc_bitref<X> > : sc_proxy_traits<X> {}; |
| |
| template <typename X> |
| struct sc_proxy_traits<sc_subref_r<X> > : sc_proxy_traits<X> {}; |
| |
| template <typename X> |
| struct sc_proxy_traits<sc_subref<X> > : sc_proxy_traits<X> {}; |
| |
| template <typename X> |
| struct sc_proxy_traits<sc_proxy<X> > : sc_proxy_traits<X> {}; |
| |
| |
| template <typename X, typename Y> |
| struct sc_mixed_proxy_traits_helper : sc_proxy_traits<sc_lv_base> |
| {}; // logic vector by default |
| |
| template <typename X> |
| struct sc_mixed_proxy_traits_helper<X, X> : X {}; |
| |
| template <typename X, typename Y> |
| struct sc_proxy_traits<sc_concref_r<X, Y> > : |
| sc_mixed_proxy_traits_helper< |
| typename X::traits_type, typename Y::traits_type> |
| {}; |
| |
| template <typename X, typename Y> |
| struct sc_proxy_traits<sc_concref<X, Y> > : |
| sc_mixed_proxy_traits_helper< |
| typename X::traits_type, typename Y::traits_type> |
| {}; |
| |
| |
| // ---------------------------------------------------------------------------- |
| // CLASS TEMPLATE : sc_proxy |
| // |
| // Base class template for bit/logic vector classes. |
| // (Barton/Nackmann implementation) |
| // ---------------------------------------------------------------------------- |
| |
| template <class X> |
| class sc_proxy // #### : public sc_value_base |
| { |
| public: |
| typedef typename sc_proxy_traits<X>::traits_type traits_type; |
| typedef typename traits_type::bit_type bit_type; |
| typedef typename traits_type::value_type value_type; |
| |
| // virtual destructor |
| virtual ~sc_proxy() {} |
| |
| // casts |
| X &back_cast() { return static_cast<X &>(*this); } |
| |
| const X &back_cast() const { return static_cast<const X &>(*this); } |
| |
| // assignment operators |
| template <class Y> |
| X & |
| assign_(const sc_proxy<Y> &a) |
| { |
| assign_p_(*this, a); |
| return back_cast(); |
| } |
| |
| X &assign_(const char *a); |
| X &assign_(const bool *a); |
| X &assign_(const sc_logic *a); |
| |
| X & |
| assign_(const sc_unsigned &a) |
| { |
| assign_v_(*this, a); |
| return back_cast(); |
| } |
| |
| X & |
| assign_(const sc_signed &a) |
| { |
| assign_v_(*this, a); |
| return back_cast(); |
| } |
| |
| X &assign_(const sc_uint_base &a) { return assign_((uint64)a); } |
| X &assign_(const sc_int_base &a) { return assign_((int64)a); } |
| X &assign_(unsigned int a); |
| X &assign_(int a); |
| X &assign_(unsigned long a); |
| X &assign_(long a); |
| X &assign_(uint64 a); |
| X &assign_(int64 a); |
| |
| // bitwise operators and functions |
| |
| // bitwise complement |
| X &b_not(); |
| |
| const sc_lv_base operator ~ () const; |
| |
| // bitwise and |
| X &operator &= (const char *b); |
| X &operator &= (const bool *b); |
| X &operator &= (const sc_logic *b); |
| X &operator &= (const sc_unsigned &b); |
| X &operator &= (const sc_signed &b); |
| X &operator &= (const sc_uint_base &b) { return operator &= ((uint64)b); } |
| X &operator &= (const sc_int_base &b) { return operator &= ((int64)b); } |
| X &operator &= (unsigned long b); |
| X &operator &= (long b); |
| X &operator &= (unsigned int b) { return operator &= ((unsigned long)b); } |
| X &operator &= (int b) { return operator &= ((long)b); } |
| X &operator &= (uint64 b); |
| X &operator &= (int64 b); |
| |
| const sc_lv_base operator & (const char *b) const; |
| const sc_lv_base operator & (const bool *b) const; |
| const sc_lv_base operator & (const sc_logic *b) const; |
| const sc_lv_base operator & (const sc_unsigned &b) const; |
| const sc_lv_base operator & (const sc_signed &b) const; |
| const sc_lv_base operator & (const sc_uint_base &b) const; |
| const sc_lv_base operator & (const sc_int_base &b) const; |
| const sc_lv_base operator & (unsigned long b) const; |
| const sc_lv_base operator & (long b) const; |
| const sc_lv_base operator & (unsigned int b) const; |
| const sc_lv_base operator & (int b) const; |
| const sc_lv_base operator & (uint64 b) const; |
| const sc_lv_base operator & (int64 b) const; |
| |
| // bitwise or |
| X &operator |= (const char *b); |
| X &operator |= (const bool *b); |
| X &operator |= (const sc_logic *b); |
| X &operator |= (const sc_unsigned &b); |
| X &operator |= (const sc_signed &b); |
| X &operator |= (const sc_uint_base &b) { return operator |= ((uint64)b); } |
| X &operator |= (const sc_int_base &b) { return operator |= ((int64)b); } |
| X &operator |= (unsigned long b); |
| X &operator |= (long b); |
| X &operator |= (unsigned int b) { return operator |= ((unsigned long)b); } |
| X &operator |= (int b) { return operator |= ((long)b); } |
| X &operator |= (uint64 b); |
| X &operator |= (int64 b); |
| |
| const sc_lv_base operator | (const char *b) const; |
| const sc_lv_base operator | (const bool *b) const; |
| const sc_lv_base operator | (const sc_logic *b) const; |
| const sc_lv_base operator | (const sc_unsigned &b) const; |
| const sc_lv_base operator | (const sc_signed &b) const; |
| const sc_lv_base operator | (const sc_uint_base &b) const; |
| const sc_lv_base operator | (const sc_int_base &b) const; |
| const sc_lv_base operator | (unsigned long b) const; |
| const sc_lv_base operator | (long b) const; |
| const sc_lv_base operator | (unsigned int b) const; |
| const sc_lv_base operator | (int b) const; |
| const sc_lv_base operator | (uint64 b) const; |
| const sc_lv_base operator | (int64 b) const; |
| |
| // bitwise xor |
| X &operator ^= (const char *b); |
| X &operator ^= (const bool *b); |
| X &operator ^= (const sc_logic *b); |
| X &operator ^= (const sc_unsigned &b); |
| X &operator ^= (const sc_signed &b); |
| X &operator ^= (const sc_uint_base &b) { return operator ^= ((uint64)b); } |
| X &operator ^= (const sc_int_base &b) { return operator ^= ((int64)b); } |
| X &operator ^= (unsigned long b); |
| X &operator ^= (long b); |
| X &operator ^= (unsigned int b) { return operator ^= ((unsigned long)b); } |
| X &operator ^= (int b) { return operator ^= ((long)b); } |
| X &operator ^= (uint64 b); |
| X &operator ^= (int64 b); |
| |
| const sc_lv_base operator ^ (const char *b) const; |
| const sc_lv_base operator ^ (const bool *b) const; |
| const sc_lv_base operator ^ (const sc_logic *b) const; |
| const sc_lv_base operator ^ (const sc_unsigned &b) const; |
| const sc_lv_base operator ^ (const sc_signed &b) const; |
| const sc_lv_base operator ^ (const sc_uint_base &b) const; |
| const sc_lv_base operator ^ (const sc_int_base &b) const; |
| const sc_lv_base operator ^ (unsigned long b) const; |
| const sc_lv_base operator ^ (long b) const; |
| const sc_lv_base operator ^ (unsigned int b) const; |
| const sc_lv_base operator ^ (int b) const; |
| const sc_lv_base operator ^ (uint64 b) const; |
| const sc_lv_base operator ^ (int64 b) const; |
| |
| // bitwise left shift |
| X &operator <<= (int n); |
| const sc_lv_base operator << (int n) const; |
| |
| // bitwise right shift |
| X &operator >>= (int n); |
| const sc_lv_base operator >> (int n) const; |
| |
| // bitwise left rotate |
| X &lrotate(int n); |
| |
| // bitwise right rotate |
| X &rrotate(int n); |
| |
| // bitwise reverse |
| X &reverse(); |
| |
| // bit selection |
| sc_bitref<X> operator [] (int i) { return sc_bitref<X>(back_cast(), i); } |
| sc_bitref_r<X> |
| operator [] (int i) const |
| { |
| return sc_bitref_r<X>(back_cast(), i); |
| } |
| sc_bitref<X> bit(int i) { return sc_bitref<X>(back_cast(), i); } |
| sc_bitref_r<X> bit(int i) const { return sc_bitref_r<X>(back_cast(), i); } |
| |
| // part selection |
| sc_subref<X> |
| operator () (int hi, int lo) |
| { |
| return sc_subref<X>(back_cast(), hi, lo); |
| } |
| sc_subref_r<X> |
| operator () (int hi, int lo) const |
| { |
| return sc_subref_r<X>(back_cast(), hi, lo); |
| } |
| sc_subref<X> |
| range(int hi, int lo) |
| { |
| return sc_subref<X>(back_cast(), hi, lo); |
| } |
| sc_subref_r<X> |
| range(int hi, int lo) const |
| { |
| return sc_subref_r<X>(back_cast(), hi, lo); |
| } |
| |
| // reduce functions |
| value_type and_reduce() const; |
| value_type |
| nand_reduce() const |
| { |
| return sc_logic::not_table[and_reduce()]; |
| } |
| value_type or_reduce() const; |
| value_type nor_reduce() const { return sc_logic::not_table[or_reduce()]; } |
| value_type xor_reduce() const; |
| value_type |
| xnor_reduce() const |
| { |
| return sc_logic::not_table[xor_reduce()]; |
| } |
| |
| // relational operators |
| bool operator == (const char *b) const; |
| bool operator == (const bool *b) const; |
| bool operator == (const sc_logic *b) const; |
| bool operator == (const sc_unsigned &b) const; |
| bool operator == (const sc_signed &b) const; |
| bool operator == (const sc_uint_base &b) const; |
| bool operator == (const sc_int_base &b) const; |
| bool operator == (unsigned long b) const; |
| bool operator == (long b) const; |
| bool operator == (unsigned int b) const; |
| bool operator == (int b) const; |
| bool operator == (uint64 b) const; |
| bool operator == (int64 b) const; |
| |
| // explicit conversions to character string |
| const std::string to_string() const; |
| const std::string to_string(sc_numrep) const; |
| const std::string to_string(sc_numrep, bool) const; |
| |
| // explicit conversions |
| inline int64 to_int64() const { return to_anything_signed(); } |
| inline uint64 to_uint64() const; |
| int to_int() const { return (int)to_anything_signed(); } |
| |
| unsigned int |
| to_uint() const |
| { |
| return (unsigned int)to_anything_unsigned(); |
| } |
| |
| long to_long() const { return (long)to_anything_signed(); } |
| |
| unsigned long |
| to_ulong() const |
| { |
| return (unsigned long)to_anything_unsigned(); |
| } |
| |
| // other methods |
| void |
| print(::std::ostream &os=::std::cout) const |
| { |
| // The test below will force printing in binary if decimal is |
| // specified. |
| if (sc_io_base(os, SC_DEC) == SC_DEC) |
| os << to_string(); |
| else |
| os << to_string(sc_io_base(os, SC_BIN), sc_io_show_base(os)); |
| } |
| |
| void scan(::std::istream &is=::std::cin); |
| |
| protected: |
| void check_bounds(int n) const; // check if bit n accessible |
| void check_wbounds(int n) const; // check if word n accessible |
| |
| sc_digit to_anything_unsigned() const; |
| int64 to_anything_signed() const; |
| }; |
| |
| |
| // ---------------------------------------------------------------------------- |
| |
| // bitwise operators and functions |
| |
| // bitwise and |
| |
| template <class X, class Y> |
| inline X &operator &= (sc_proxy<X> &px, const sc_proxy<Y> &py); |
| |
| |
| template <class X, class Y> |
| inline const sc_lv_base operator & ( |
| const sc_proxy<X> &px, const sc_proxy<Y> &py); |
| |
| |
| #define DECL_BITWISE_AND_OP_T(tp) \ |
| template <class X> \ |
| inline const sc_lv_base operator & (tp b, const sc_proxy<X> &px); |
| |
| DECL_BITWISE_AND_OP_T(const char *) |
| DECL_BITWISE_AND_OP_T(const bool *) |
| DECL_BITWISE_AND_OP_T(const sc_logic *) |
| DECL_BITWISE_AND_OP_T(const sc_unsigned &) |
| DECL_BITWISE_AND_OP_T(const sc_signed &) |
| DECL_BITWISE_AND_OP_T(const sc_uint_base &) |
| DECL_BITWISE_AND_OP_T(const sc_int_base &) |
| DECL_BITWISE_AND_OP_T(unsigned long) |
| DECL_BITWISE_AND_OP_T(long) |
| DECL_BITWISE_AND_OP_T(unsigned int) |
| DECL_BITWISE_AND_OP_T(int) |
| DECL_BITWISE_AND_OP_T(uint64) |
| DECL_BITWISE_AND_OP_T(int64) |
| |
| #undef DECL_BITWISE_AND_OP_T |
| |
| // bitwise or |
| template <class X, class Y> |
| inline X &operator |= (sc_proxy<X> &px, const sc_proxy<Y> &py); |
| |
| template <class X, class Y> |
| inline const sc_lv_base operator | ( |
| const sc_proxy<X> &px, const sc_proxy<Y> &py); |
| |
| |
| #define DECL_BITWISE_OR_OP_T(tp) \ |
| template <class X> \ |
| inline const sc_lv_base operator | (tp a, const sc_proxy<X> &px); |
| |
| DECL_BITWISE_OR_OP_T(const char *) |
| DECL_BITWISE_OR_OP_T(const bool *) |
| DECL_BITWISE_OR_OP_T(const sc_logic *) |
| DECL_BITWISE_OR_OP_T(const sc_unsigned &) |
| DECL_BITWISE_OR_OP_T(const sc_signed &) |
| DECL_BITWISE_OR_OP_T(const sc_uint_base &) |
| DECL_BITWISE_OR_OP_T(const sc_int_base &) |
| DECL_BITWISE_OR_OP_T(unsigned long) |
| DECL_BITWISE_OR_OP_T(long) |
| DECL_BITWISE_OR_OP_T(unsigned int) |
| DECL_BITWISE_OR_OP_T(int) |
| DECL_BITWISE_OR_OP_T(uint64) |
| DECL_BITWISE_OR_OP_T(int64) |
| |
| #undef DECL_BITWISE_OR_OP_T |
| |
| // bitwise xor |
| template <class X, class Y> |
| inline X &operator ^= (sc_proxy<X> &px, const sc_proxy<Y> &py); |
| |
| template <class X, class Y> |
| inline const sc_lv_base operator ^ ( |
| const sc_proxy<X> &px, const sc_proxy<Y> &py); |
| |
| #define DECL_BITWISE_XOR_OP_T(tp) \ |
| template <class X> \ |
| inline const sc_lv_base operator ^ (tp a, const sc_proxy<X> &px); |
| |
| DECL_BITWISE_XOR_OP_T(const char *) |
| DECL_BITWISE_XOR_OP_T(const bool *) |
| DECL_BITWISE_XOR_OP_T(const sc_logic *) |
| DECL_BITWISE_XOR_OP_T(const sc_unsigned &) |
| DECL_BITWISE_XOR_OP_T(const sc_signed &) |
| DECL_BITWISE_XOR_OP_T(const sc_uint_base &) |
| DECL_BITWISE_XOR_OP_T(const sc_int_base &) |
| DECL_BITWISE_XOR_OP_T(unsigned long) |
| DECL_BITWISE_XOR_OP_T(long) |
| DECL_BITWISE_XOR_OP_T(unsigned int) |
| DECL_BITWISE_XOR_OP_T(int) |
| DECL_BITWISE_XOR_OP_T(uint64) |
| DECL_BITWISE_XOR_OP_T(int64) |
| |
| #undef DECL_BITWISE_XOR_OP_T |
| |
| // relational operators |
| template <class X, class Y> |
| inline bool operator == (const sc_proxy<X> &px, const sc_proxy<Y> &py); |
| |
| template <class X, class Y> |
| inline bool operator != (const sc_proxy<X> &px, const sc_proxy<Y> &py); |
| |
| #define DECL_REL_OP_T(tp) \ |
| template <class X> \ |
| inline bool operator == (tp b, const sc_proxy<X> &px); \ |
| \ |
| template <class X> \ |
| inline bool operator != (const sc_proxy<X> &px, tp b); \ |
| \ |
| template <class X> \ |
| inline bool operator != (tp b, const sc_proxy<X> &px); |
| |
| DECL_REL_OP_T(const char *) |
| DECL_REL_OP_T(const bool *) |
| DECL_REL_OP_T(const sc_logic *) |
| DECL_REL_OP_T(const sc_unsigned &) |
| DECL_REL_OP_T(const sc_signed &) |
| DECL_REL_OP_T(const sc_uint_base &) |
| DECL_REL_OP_T(const sc_int_base &) |
| DECL_REL_OP_T(unsigned long) |
| DECL_REL_OP_T(long) |
| DECL_REL_OP_T(unsigned int) |
| DECL_REL_OP_T(int) |
| DECL_REL_OP_T(uint64) |
| DECL_REL_OP_T(int64) |
| |
| #undef DECL_REL_OP_T |
| |
| // l-value concatenation |
| |
| // Due to the fact that temporary objects cannot be passed to non-const |
| // references, we have to enumerate, use call by value, and use dynamic |
| // memory allocation (and deallocation). |
| |
| |
| // IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII |
| |
| template <class X> |
| inline void |
| get_words_(const X &x, int wi, sc_digit &x_dw, sc_digit &x_cw) |
| { |
| x_dw = x.get_word(wi); |
| x_cw = x.get_cword(wi); |
| } |
| |
| template <class X> |
| inline void |
| set_words_(X &x, int wi, sc_digit x_dw, sc_digit x_cw) |
| { |
| x.set_word(wi, x_dw); |
| x.set_cword(wi, x_cw); |
| } |
| |
| template <class X> |
| inline void |
| extend_sign_w_(X &x, int wi, bool sign) |
| { |
| int sz = x.size(); |
| unsigned int sgn = (sign ? ~SC_DIGIT_ZERO : SC_DIGIT_ZERO); |
| for (int i = wi; i < sz; ++i) { |
| set_words_(x, i, sgn, SC_DIGIT_ZERO); |
| } |
| } |
| |
| // assignment functions |
| template <class X, class Y> |
| inline void |
| assign_p_(sc_proxy<X> &px, const sc_proxy<Y> &py) |
| { |
| if ((void *)&px != (void *)&py) { |
| X &x = px.back_cast(); |
| const Y &y = py.back_cast(); |
| int sz = x.size(); |
| int min_sz = sc_min(sz, y.size()); |
| int i = 0; |
| for (; i < min_sz; ++i) { |
| set_words_(x, i, y.get_word(i), y.get_cword(i)); |
| } |
| // extend with zeros |
| extend_sign_w_(x, i, false); |
| x.clean_tail(); |
| } |
| } |
| |
| // Vector types that are not derived from sc_proxy, sc_int_base, |
| // sc_uint_base, sc_signed, or sc_unsigned, must have a length() |
| // function and an operator []. The vector argument type must support |
| // accessing bits that are beyond the msb. The vector argument type |
| // decides what to do there (e.g. sign extension or zero padding). |
| |
| template <class X, class T> |
| inline void |
| assign_v_(sc_proxy<X> &px, const T &a) |
| { |
| X &x = px.back_cast(); |
| int i; |
| int len_x = x.length(); |
| int len_a = a.length(); |
| if (len_a > len_x) |
| len_a = len_x; |
| for (i = 0; i < len_a; ++i) { |
| x.set_bit(i, sc_logic_value_t((bool)a[i])); |
| } |
| for (; i < len_x; ++i) { |
| x.set_bit(i, sc_logic_value_t(false)); |
| } |
| } |
| |
| template <class X> |
| inline void |
| assign_v_(sc_proxy<X> &px, const sc_int_base &a) |
| { |
| X &x = px.back_cast(); |
| int i; |
| bool sign = a < 0; |
| int len_x = x.length(); |
| int len_a = a.length(); |
| if ( len_a > len_x ) len_a = len_x; |
| for (i = 0; i < len_a; ++i) { |
| x.set_bit(i, sc_logic_value_t((bool)a[i])); |
| } |
| for (; i < len_x; ++i) { |
| x.set_bit(i, sc_logic_value_t(sign)); |
| } |
| } |
| |
| template <class X> |
| inline void |
| assign_v_(sc_proxy<X> &px, const sc_signed &a) |
| { |
| X &x = px.back_cast(); |
| int i; |
| bool sign = a < 0; |
| int len_x = x.length(); |
| int len_a = a.length(); |
| if (len_a > len_x) |
| len_a = len_x; |
| for (i = 0; i < len_a; ++i) { |
| x.set_bit(i, sc_logic_value_t((bool)a[i])); |
| } |
| for (; i < len_x; ++i) { |
| x.set_bit(i, sc_logic_value_t(sign)); |
| } |
| } |
| |
| template <class X> |
| inline void |
| assign_v_(sc_proxy<X> &px, const sc_uint_base &a) |
| { |
| X &x = px.back_cast(); |
| int i; |
| int len_x = x.length(); |
| int len_a = a.length(); |
| if (len_a > len_x) |
| len_a = len_x; |
| for (i = 0; i < len_a; ++i) { |
| x.set_bit(i, sc_logic_value_t((bool)a[i])); |
| } |
| for (; i < len_x; ++i) { |
| x.set_bit(i, sc_logic_value_t(false)); |
| } |
| } |
| |
| template <class X> |
| inline void |
| assign_v_(sc_proxy<X> &px, const sc_unsigned &a) |
| { |
| X &x = px.back_cast(); |
| int i; |
| int len_x = x.length(); |
| int len_a = a.length(); |
| if (len_a > len_x) |
| len_a = len_x; |
| for (i = 0; i < len_a; ++i) { |
| x.set_bit(i, sc_logic_value_t((bool)a[i])); |
| } |
| for (; i < len_x; ++i) { |
| x.set_bit(i, sc_logic_value_t(false)); |
| } |
| } |
| |
| // assignment operators |
| template <class X> |
| inline X & |
| sc_proxy<X>::assign_(const char *a) |
| { |
| X &x = back_cast(); |
| std::string s = convert_to_bin(a); |
| int len = x.length(); |
| int s_len = s.length() - 1; |
| int min_len = sc_min(len, s_len); |
| int i = 0; |
| for (; i < min_len; ++i) { |
| char c = s[s_len - i - 1]; |
| x.set_bit(i, sc_logic::char_to_logic[(int)c]); |
| } |
| // if formatted, fill the rest with sign(s), otherwise fill with zeros |
| sc_logic_value_t fill = (s[s_len] == 'F' ? sc_logic_value_t(s[0] - '0') |
| : sc_logic_value_t(0)); |
| for (; i < len; ++i) { |
| x.set_bit(i, fill); |
| } |
| return x; |
| } |
| |
| template <class X> |
| inline X & |
| sc_proxy<X>::assign_(const bool *a) |
| { |
| // the length of 'a' must be larger than or equal to the length of 'this' |
| X &x = back_cast(); |
| int len = x.length(); |
| for (int i = 0; i < len; ++i) { |
| x.set_bit(i, sc_logic_value_t(a[i])); |
| } |
| return x; |
| } |
| |
| template <class X> |
| inline X & |
| sc_proxy<X>::assign_(const sc_logic *a) |
| { |
| // the length of 'a' must be larger than or equal to the length of 'this' |
| X &x = back_cast(); |
| int len = x.length(); |
| for (int i = 0; i < len; ++i) { |
| x.set_bit(i, a[i].value()); |
| } |
| return x; |
| } |
| |
| template <class X> |
| inline X & |
| sc_proxy<X>::assign_(unsigned int a) |
| { |
| X &x = back_cast(); |
| set_words_(x, 0, (sc_digit)a, SC_DIGIT_ZERO); |
| // extend with zeros |
| extend_sign_w_(x, 1, false); |
| x.clean_tail(); |
| return x; |
| } |
| |
| template <class X> |
| inline X & |
| sc_proxy<X>::assign_(int a) |
| { |
| X &x = back_cast(); |
| set_words_(x, 0, (sc_digit)a, SC_DIGIT_ZERO); |
| // extend with sign(a) |
| extend_sign_w_(x, 1, (a < 0)); |
| x.clean_tail(); |
| return x; |
| } |
| |
| #if SC_LONG_64 |
| template <class X> |
| inline X & |
| sc_proxy<X>::assign_(unsigned long a) |
| { |
| X &x = back_cast(); |
| set_words_(x, 0, ((sc_digit)a & ~SC_DIGIT_ZERO), SC_DIGIT_ZERO); |
| if (x.size() > 1) { |
| set_words_(x, 1, ((sc_digit)(a >> SC_DIGIT_SIZE) & ~SC_DIGIT_ZERO), |
| SC_DIGIT_ZERO); |
| // extend with zeros |
| extend_sign_w_(x, 2, false); |
| } |
| x.clean_tail(); |
| return x; |
| } |
| |
| template <class X> |
| inline X & |
| sc_proxy<X>::assign_(long a) |
| { |
| X &x = back_cast(); |
| set_words_(x, 0, ((sc_digit)a & ~SC_DIGIT_ZERO), SC_DIGIT_ZERO); |
| if (x.size() > 1) { |
| set_words_(x, 1, |
| ((sc_digit)((uint64)a >> SC_DIGIT_SIZE) & ~SC_DIGIT_ZERO), |
| SC_DIGIT_ZERO); |
| // extend with sign(a) |
| extend_sign_w_(x, 2, (a < 0)); |
| } |
| x.clean_tail(); |
| return x; |
| } |
| |
| #else |
| |
| template <class X> |
| inline X & |
| sc_proxy<X>::assign_(unsigned long a) |
| { |
| X &x = back_cast(); |
| set_words_(x, 0, (sc_digit)a, SC_DIGIT_ZERO); |
| // extend with zeros |
| extend_sign_w_(x, 1, false); |
| x.clean_tail(); |
| return x; |
| } |
| |
| template <class X> |
| inline X & |
| sc_proxy<X>::assign_(long a) |
| { |
| X &x = back_cast(); |
| set_words_(x, 0, (sc_digit)a, SC_DIGIT_ZERO); |
| // extend with sign(a) |
| extend_sign_w_(x, 1, (a < 0)); |
| x.clean_tail(); |
| return x; |
| } |
| |
| #endif |
| |
| template <class X> |
| inline X & |
| sc_proxy<X>::assign_(uint64 a) |
| { |
| X &x = back_cast(); |
| set_words_(x, 0, ((sc_digit)a & ~SC_DIGIT_ZERO), SC_DIGIT_ZERO); |
| if (x.size() > 1) { |
| set_words_(x, 1, ((sc_digit) (a >> SC_DIGIT_SIZE) & ~SC_DIGIT_ZERO), |
| SC_DIGIT_ZERO ); |
| // extend with zeros |
| extend_sign_w_(x, 2, false); |
| } |
| x.clean_tail(); |
| return x; |
| } |
| |
| template <class X> |
| inline X & |
| sc_proxy<X>::assign_(int64 a) |
| { |
| X &x = back_cast(); |
| set_words_(x, 0, ((sc_digit)a & ~SC_DIGIT_ZERO), SC_DIGIT_ZERO); |
| if (x.size() > 1) { |
| set_words_(x, 1, |
| ((sc_digit)((uint64)a >> SC_DIGIT_SIZE) & ~SC_DIGIT_ZERO), |
| SC_DIGIT_ZERO ); |
| // extend with sign(a) |
| extend_sign_w_(x, 2, (a < 0)); |
| } |
| x.clean_tail(); |
| return x; |
| } |
| |
| // bitwise operators and functions |
| |
| // bitwise complement |
| template <class X> |
| inline X & |
| sc_proxy<X>::b_not() |
| { |
| X &x = back_cast(); |
| int sz = x.size(); |
| for (int i = 0; i < sz; ++i) { |
| sc_digit x_dw, x_cw; |
| get_words_(x, i, x_dw, x_cw); |
| x.set_word(i, x_cw | ~x_dw); |
| } |
| x.clean_tail(); |
| return x; |
| } |
| |
| // bitwise and |
| template <class X, class Y> |
| inline X & |
| b_and_assign_(sc_proxy<X> &px, const sc_proxy<Y> &py) |
| { |
| X &x = px.back_cast(); |
| const Y &y = py.back_cast(); |
| sc_assert(x.length() == y.length()); |
| int sz = x.size(); |
| for (int i = 0; i < sz; ++i) { |
| sc_digit x_dw, x_cw, y_dw, y_cw; |
| get_words_(x, i, x_dw, x_cw); |
| get_words_(y, i, y_dw, y_cw); |
| sc_digit cw = (x_dw & y_cw) | (x_cw & y_dw) | (x_cw & y_cw); |
| sc_digit dw = cw | (x_dw & y_dw); |
| set_words_(x, i, dw, cw); |
| } |
| // tail cleaning not needed |
| return x; |
| } |
| |
| // bitwise or |
| template <class X, class Y> |
| inline X & |
| b_or_assign_(sc_proxy<X> &px, const sc_proxy<Y> &py) |
| { |
| X &x = px.back_cast(); |
| const Y &y = py.back_cast(); |
| sc_assert(x.length() == y.length()); |
| int sz = x.size(); |
| for (int i = 0; i < sz; ++i) { |
| sc_digit x_dw, x_cw, y_dw, y_cw; |
| get_words_(x, i, x_dw, x_cw); |
| get_words_(y, i, y_dw, y_cw); |
| sc_digit cw = (x_cw & y_cw) | (x_cw & ~y_dw) | (~x_dw & y_cw); |
| sc_digit dw = cw | x_dw | y_dw; |
| set_words_(x, i, dw, cw); |
| } |
| // tail cleaning not needed |
| return x; |
| } |
| |
| // bitwise xor |
| template <class X, class Y> |
| inline X & |
| b_xor_assign_(sc_proxy<X> &a, const sc_proxy<Y> &b) |
| { |
| X &x = a.back_cast(); |
| const Y &y = b.back_cast(); |
| sc_assert(x.length() == y.length()); |
| int sz = x.size(); |
| for (int i = 0; i < sz; ++i) { |
| sc_digit x_dw, x_cw, y_dw, y_cw; |
| get_words_(x, i, x_dw, x_cw); |
| get_words_(y, i, y_dw, y_cw); |
| sc_digit cw = x_cw | y_cw; |
| sc_digit dw = cw | (x_dw ^ y_dw); |
| set_words_( x, i, dw, cw ); |
| } |
| // tail cleaning not needed |
| return x; |
| } |
| |
| // bitwise left shift |
| template <class X> |
| inline X & |
| sc_proxy<X>::operator <<= (int n) |
| { |
| X &x = back_cast(); |
| if (n < 0) { |
| sc_proxy_out_of_bounds("left shift operation is only allowed with " |
| "positive shift values, shift value = ", n); |
| return x; |
| } |
| if (n >= x.length()) { |
| extend_sign_w_(x, 0, false); |
| // no tail cleaning needed |
| return x; |
| } |
| int sz = x.size(); |
| int wn = n / SC_DIGIT_SIZE; |
| int bn = n % SC_DIGIT_SIZE; |
| if (wn != 0) { |
| // shift words |
| int i = sz - 1; |
| for (; i >= wn; --i) { |
| set_words_(x, i, x.get_word(i - wn), x.get_cword(i - wn)); |
| } |
| for (; i >= 0; --i) { |
| set_words_(x, i, SC_DIGIT_ZERO, SC_DIGIT_ZERO); |
| } |
| } |
| if (bn != 0) { |
| // shift bits |
| for (int i = sz - 1; i >= 1; --i) { |
| sc_digit x_dw, x_cw; |
| get_words_(x, i, x_dw, x_cw); |
| x_dw <<= bn; |
| x_dw |= x.get_word(i - 1) >> (SC_DIGIT_SIZE - bn); |
| x_cw <<= bn; |
| x_cw |= x.get_cword(i - 1) >> (SC_DIGIT_SIZE - bn); |
| set_words_(x, i, x_dw, x_cw); |
| } |
| sc_digit x_dw, x_cw; |
| get_words_(x, 0, x_dw, x_cw); |
| x_dw <<= bn; |
| x_cw <<= bn; |
| set_words_(x, 0, x_dw, x_cw); |
| } |
| x.clean_tail(); |
| return x; |
| } |
| |
| // bitwise right shift |
| template <class X> |
| inline X & |
| sc_proxy<X>::operator >>= (int n) |
| { |
| X &x = back_cast(); |
| if (n < 0) { |
| sc_proxy_out_of_bounds("right shift operation is only allowed with " |
| "positive shift values, shift value = ", n); |
| return x; |
| } |
| if (n >= x.length()) { |
| extend_sign_w_(x, 0, false); |
| // no tail cleaning needed |
| return x; |
| } |
| int sz = x.size(); |
| int wn = n / SC_DIGIT_SIZE; |
| int bn = n % SC_DIGIT_SIZE; |
| if (wn != 0) { |
| // shift words |
| int i = 0; |
| for (; i < (sz - wn); ++i) { |
| set_words_(x, i, x.get_word(i + wn), x.get_cword(i + wn)); |
| } |
| for (; i < sz; ++i) { |
| set_words_(x, i, SC_DIGIT_ZERO, SC_DIGIT_ZERO); |
| } |
| } |
| if (bn != 0) { |
| // shift bits |
| for (int i = 0; i < (sz - 1); ++i) { |
| sc_digit x_dw, x_cw; |
| get_words_(x, i, x_dw, x_cw); |
| x_dw >>= bn; |
| x_dw |= x.get_word(i + 1) << (SC_DIGIT_SIZE - bn); |
| x_cw >>= bn; |
| x_cw |= x.get_cword(i + 1) << (SC_DIGIT_SIZE - bn); |
| set_words_(x, i, x_dw, x_cw); |
| } |
| sc_digit x_dw, x_cw; |
| get_words_(x, sz - 1, x_dw, x_cw); |
| x_dw >>= bn; |
| x_cw >>= bn; |
| set_words_(x, sz - 1, x_dw, x_cw); |
| } |
| x.clean_tail(); |
| return x; |
| } |
| |
| // bitwise left rotate |
| template <class X> |
| inline const sc_lv_base lrotate(const sc_proxy<X> &x, int n); |
| |
| // bitwise right rotate |
| template <class X> |
| inline const sc_lv_base rrotate(const sc_proxy<X>& x, int n); |
| |
| // bitwise reverse |
| template <class X> |
| inline X & |
| sc_proxy<X>::reverse() |
| { |
| X &x = back_cast(); |
| int len = x.length(); |
| int half_len = len / 2; |
| for (int i = 0, j = len - 1; i < half_len; ++ i, --j) { |
| value_type t = x.get_bit(i); |
| x.set_bit(i, x.get_bit(j)); |
| x.set_bit(j, t); |
| } |
| return x; |
| } |
| |
| template <class X> |
| inline const sc_lv_base reverse(const sc_proxy<X> &a); |
| |
| // reduce functions |
| template <class X> |
| inline typename sc_proxy<X>::value_type |
| sc_proxy<X>::and_reduce() const |
| { |
| const X &x = back_cast(); |
| value_type result = value_type(1); |
| int len = x.length(); |
| for (int i = 0; i < len; ++i) { |
| result = sc_logic::and_table[result][x.get_bit(i)]; |
| } |
| return result; |
| } |
| |
| template <class X> |
| inline typename sc_proxy<X>::value_type |
| sc_proxy<X>::or_reduce() const |
| { |
| const X &x = back_cast(); |
| value_type result = value_type(0); |
| int len = x.length(); |
| for (int i = 0; i < len; ++i) { |
| result = sc_logic::or_table[result][x.get_bit(i)]; |
| } |
| return result; |
| } |
| |
| template <class X> |
| inline typename sc_proxy<X>::value_type |
| sc_proxy<X>::xor_reduce() const |
| { |
| const X &x = back_cast(); |
| value_type result = value_type(0); |
| int len = x.length(); |
| for (int i = 0; i < len; ++i) { |
| result = sc_logic::xor_table[result][x.get_bit(i)]; |
| } |
| return result; |
| } |
| |
| // relational operators |
| template <class X, class Y> |
| inline bool |
| operator != (const sc_proxy<X> &px, const sc_proxy<Y> &py) |
| { |
| return !(px == py); |
| } |
| |
| |
| #define DEFN_REL_OP_T(tp) \ |
| template <class X> \ |
| inline bool operator == (tp b, const sc_proxy<X> &px) { return (px == b); } \ |
| \ |
| template <class X> \ |
| inline bool operator != (const sc_proxy<X> &px, tp b) { return !(px == b); } \ |
| \ |
| template <class X> \ |
| inline bool operator != (tp b, const sc_proxy<X> &px) { return !(px == b); } |
| |
| DEFN_REL_OP_T(const char *) |
| DEFN_REL_OP_T(const bool *) |
| DEFN_REL_OP_T(const sc_logic *) |
| DEFN_REL_OP_T(const sc_unsigned &) |
| DEFN_REL_OP_T(const sc_signed &) |
| DEFN_REL_OP_T(const sc_uint_base &) |
| DEFN_REL_OP_T(const sc_int_base &) |
| DEFN_REL_OP_T(unsigned long) |
| DEFN_REL_OP_T(long) |
| DEFN_REL_OP_T(unsigned int) |
| DEFN_REL_OP_T(int) |
| DEFN_REL_OP_T(uint64) |
| DEFN_REL_OP_T(int64) |
| |
| #undef DEFN_REL_OP_T |
| |
| // explicit conversions to character string |
| template <class X> |
| inline const std::string |
| sc_proxy<X>::to_string() const |
| { |
| const X &x = back_cast(); |
| int len = x.length(); |
| std::string s; // (len + 1); |
| for (int i = 0; i < len; ++i) { |
| s += sc_logic::logic_to_char[x.get_bit(len - i - 1)]; |
| } |
| return s; |
| } |
| |
| template <class X> |
| inline const std::string |
| sc_proxy<X>::to_string(sc_numrep numrep) const |
| { |
| return convert_to_fmt(to_string(), numrep, true); |
| } |
| |
| template <class X> |
| inline const std::string |
| sc_proxy<X>::to_string(sc_numrep numrep, bool w_prefix) const |
| { |
| return convert_to_fmt(to_string(), numrep, w_prefix); |
| } |
| |
| // other methods |
| template <class X> |
| inline void |
| sc_proxy<X>::scan(::std::istream &is) |
| { |
| std::string s; |
| is >> s; |
| back_cast() = s.c_str(); |
| } |
| |
| template <class X> |
| inline void |
| sc_proxy<X>::check_bounds(int n) const // check if bit n accessible |
| { |
| if (n < 0 || n >= back_cast().length()) { |
| sc_proxy_out_of_bounds(NULL, n); |
| sc_core::sc_abort(); // can't recover from here |
| } |
| } |
| |
| template <class X> |
| inline void |
| sc_proxy<X>::check_wbounds(int n) const // check if word n accessible |
| { |
| if (n < 0 || n >= back_cast().size()) { |
| sc_proxy_out_of_bounds(NULL, n); |
| sc_core::sc_abort(); // can't recover from here |
| } |
| } |
| |
| template <class X> |
| inline sc_digit |
| sc_proxy<X>::to_anything_unsigned() const |
| { |
| // only 0 word is returned |
| // can't convert logic values other than 0 and 1 |
| const X &x = back_cast(); |
| int len = x.length(); |
| if (x.get_cword(0) != SC_DIGIT_ZERO) { |
| SC_REPORT_WARNING(sc_core::SC_ID_VECTOR_CONTAINS_LOGIC_VALUE_, 0); |
| } |
| sc_digit w = x.get_word(0); |
| if (len >= SC_DIGIT_SIZE) { |
| return w; |
| } |
| return (w & (~SC_DIGIT_ZERO >> (SC_DIGIT_SIZE - len))); |
| } |
| |
| template <class X> |
| inline uint64 |
| sc_proxy<X>::to_uint64() const |
| { |
| // words 1 and 0 returned. |
| // can't convert logic values other than 0 and 1 |
| const X &x = back_cast(); |
| int len = x.length(); |
| if (x.get_cword(0) != SC_DIGIT_ZERO) { |
| SC_REPORT_WARNING(sc_core::SC_ID_VECTOR_CONTAINS_LOGIC_VALUE_, 0); |
| } |
| uint64 w = x.get_word(0); |
| if (len > SC_DIGIT_SIZE) { |
| if (x.get_cword(1) != SC_DIGIT_ZERO) { |
| SC_REPORT_WARNING(sc_core::SC_ID_VECTOR_CONTAINS_LOGIC_VALUE_, 0); |
| } |
| uint64 w1 = x.get_word(1); |
| w = w | (w1 << SC_DIGIT_SIZE); |
| return w; |
| } else if (len == SC_DIGIT_SIZE) { |
| return w; |
| } else { |
| return (w & (~SC_DIGIT_ZERO >> (SC_DIGIT_SIZE - len))); |
| } |
| } |
| |
| template <class X> |
| inline int64 |
| sc_proxy<X>::to_anything_signed() const |
| { |
| const X &x = back_cast(); |
| int len = x.length(); |
| int64 w = 0; |
| |
| if (len > SC_DIGIT_SIZE) { |
| if (x.get_cword(1) != SC_DIGIT_ZERO) |
| SC_REPORT_WARNING(sc_core::SC_ID_VECTOR_CONTAINS_LOGIC_VALUE_, 0); |
| w = x.get_word(1); |
| } |
| if (x.get_cword(0) != SC_DIGIT_ZERO) |
| SC_REPORT_WARNING(sc_core::SC_ID_VECTOR_CONTAINS_LOGIC_VALUE_, 0); |
| w = (w << SC_DIGIT_SIZE) | x.get_word(0); |
| if (len >= 64) { |
| return w; |
| } |
| |
| uint64 zero = 0; |
| value_type sgn = x.get_bit(len - 1); |
| if (sgn == 0) { |
| return (int64)(w & (~zero >> (64 - len))); |
| } else { |
| return (int64)(w | (~zero << len)); |
| } |
| } |
| |
| |
| // ---------------------------------------------------------------------------- |
| |
| // functional notation for the reduce methods |
| template <class X> |
| inline typename sc_proxy<X>::value_type |
| and_reduce(const sc_proxy<X> &a) |
| { |
| return a.and_reduce(); |
| } |
| |
| template <class X> |
| inline typename sc_proxy<X>::value_type |
| nand_reduce(const sc_proxy<X> &a) |
| { |
| return a.nand_reduce(); |
| } |
| |
| template <class X> |
| inline typename sc_proxy<X>::value_type |
| or_reduce(const sc_proxy<X> &a) |
| { |
| return a.or_reduce(); |
| } |
| |
| template <class X> |
| inline typename sc_proxy<X>::value_type |
| nor_reduce(const sc_proxy<X> &a) |
| { |
| return a.nor_reduce(); |
| } |
| |
| template <class X> |
| inline typename sc_proxy<X>::value_type |
| xor_reduce(const sc_proxy<X> &a) |
| { |
| return a.xor_reduce(); |
| } |
| |
| template <class X> |
| inline typename sc_proxy<X>::value_type |
| xnor_reduce(const sc_proxy<X> &a) |
| { |
| return a.xnor_reduce(); |
| } |
| |
| // ---------------------------------------------------------------------------- |
| |
| template <class X> |
| inline ::std::ostream & |
| operator << (::std::ostream &os, const sc_proxy<X> &a) |
| { |
| a.print(os); |
| return os; |
| } |
| |
| template <class X> |
| inline ::std::istream & |
| operator >> (::std::istream &is, sc_proxy<X> &a) |
| { |
| a.scan(is); |
| return is; |
| } |
| |
| } // namespace sc_dt |
| |
| #endif // __SYSTEMC_EXT_DT_BIT_SC_PROXY_HH__ |