1/*****************************************************************************
2
3  Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
4  more contributor license agreements.  See the NOTICE file distributed
5  with this work for additional information regarding copyright ownership.
6  Accellera licenses this file to you under the Apache License, Version 2.0
7  (the "License"); you may not use this file except in compliance with the
8  License.  You may obtain a copy of the License at
9
10    http://www.apache.org/licenses/LICENSE-2.0
11
12  Unless required by applicable law or agreed to in writing, software
13  distributed under the License is distributed on an "AS IS" BASIS,
14  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15  implied.  See the License for the specific language governing
16  permissions and limitations under the License.
17
18 *****************************************************************************/
19
20/*****************************************************************************
21
22  sc_proxy.h -- Proxy base class for vector data types.
23
24                This class is created for several purposes:
25                1) hiding operators from the global namespace that would be
26                   otherwise found by Koenig lookup
27                2) avoiding repeating the same operations in every class
28                   including proxies that could also be achieved by common
29                   base class, but this method allows
30                3) improve performance by using non-virtual functions
31
32  Original Author: Gene Bushuyev, Synopsys, Inc.
33
34 *****************************************************************************/
35
36/*****************************************************************************
37
38  MODIFICATION LOG - modifiers, enter your name, affiliation, date and
39  changes you are making here.
40
41      Name, Affiliation, Date:
42  Description of Modification:
43
44 *****************************************************************************/
45
46// $Log: sc_proxy.h,v $
47// Revision 1.3  2010/12/07 20:09:07  acg
48// Andy Goodrich: Fix for returning enough data
49//
50// Revision 1.2  2009/02/28 00:26:14  acg
51//  Andy Goodrich: bug fixes.
52//
53// Revision 1.1.1.1  2006/12/15 20:31:36  acg
54// SystemC 2.2
55//
56// Revision 1.3  2006/01/13 18:53:53  acg
57// Andy Goodrich: added $Log command so that CVS comments are reproduced in
58// the source.
59//
60
61#ifndef __SYSTEMC_EXT_DT_BIT_SC_PROXY_HH__
62#define __SYSTEMC_EXT_DT_BIT_SC_PROXY_HH__
63
64#include <iostream>
65
66#include "../../utils/functions.hh"
67#include "../int/sc_int_base.hh"
68#include "../int/sc_signed.hh"
69#include "../int/sc_uint_base.hh"
70#include "../int/sc_unsigned.hh"
71#include "messages.hh"
72#include "sc_bit.hh"
73#include "sc_logic.hh"
74
75namespace sc_dt
76{
77
78// classes defined in this module
79template <class X>
80class sc_proxy;
81
82// forward class declarations
83class sc_bv_base;
84class sc_lv_base;
85template <class X>
86class sc_bitref_r;
87template <class X>
88class sc_bitref;
89template <class X>
90class sc_subref_r;
91template <class X>
92class sc_subref;
93template <class X, class Y>
94class sc_concref_r;
95template <class X, class Y>
96class sc_concref;
97
98const int SC_DIGIT_SIZE = BITS_PER_BYTE * sizeof(sc_digit);
99
100const sc_digit SC_DIGIT_ZERO = (sc_digit)0;
101const sc_digit SC_DIGIT_ONE = (sc_digit)1;
102const sc_digit SC_DIGIT_TWO = (sc_digit)2;
103
104void sc_proxy_out_of_bounds(const char *msg=NULL, int64 val=0);
105
106// assignment functions; forward declarations
107
108template <class X, class Y>
109inline void assign_p_(sc_proxy<X> &px, const sc_proxy<Y> &py);
110
111// Vector types that are not derived from sc_proxy must have a length()
112// function and an operator [].
113
114template <class X, class T>
115inline void assign_v_(sc_proxy<X> &px, const T &a);
116
117// other functions; forward declarations
118const std::string convert_to_bin(const char *s);
119const std::string convert_to_fmt(const std::string &s, sc_numrep numrep, bool);
120
121// ----------------------------------------------------------------------------
122//  CLASS TEMPLATE : sc_proxy_traits
123//
124// Template traits helper to select the correct bit/value/vector_types for
125// sc_proxy-based vector classes.
126//
127// All types derived from/based on a bit-vector contain typedef to a plain
128// bool, all others point to the sc_logic_value_t/sc_logic/sc_lv_base types.
129// ----------------------------------------------------------------------------
130
131template <typename X>
132struct sc_proxy_traits;
133
134template <>
135struct sc_proxy_traits<sc_bv_base>
136{
137    typedef sc_proxy_traits<sc_bv_base> traits_type;
138    typedef bool value_type;
139    typedef sc_logic bit_type; // sc_logic needed for mixed expressions
140    typedef sc_bv_base vector_type;
141};
142
143template <>
144struct sc_proxy_traits<sc_lv_base>
145{
146    typedef sc_proxy_traits<sc_lv_base> traits_type;
147    typedef sc_logic_value_t value_type;
148    typedef sc_logic bit_type;
149    typedef sc_lv_base vector_type;
150};
151
152template <typename X>
153struct sc_proxy_traits<sc_bitref_r<X> > : sc_proxy_traits<X> {};
154
155template <typename X>
156struct sc_proxy_traits<sc_bitref<X> > : sc_proxy_traits<X> {};
157
158template <typename X>
159struct sc_proxy_traits<sc_subref_r<X> > : sc_proxy_traits<X> {};
160
161template <typename X>
162struct sc_proxy_traits<sc_subref<X> > : sc_proxy_traits<X> {};
163
164template <typename X>
165struct sc_proxy_traits<sc_proxy<X> > : sc_proxy_traits<X> {};
166
167
168template <typename X, typename Y>
169struct sc_mixed_proxy_traits_helper : sc_proxy_traits<sc_lv_base>
170{}; // logic vector by default
171
172template <typename X>
173struct sc_mixed_proxy_traits_helper<X, X> : X {};
174
175template <typename X, typename Y>
176struct sc_proxy_traits<sc_concref_r<X, Y> > :
177        sc_mixed_proxy_traits_helper<
178            typename X::traits_type, typename Y::traits_type>
179{};
180
181template <typename X, typename Y>
182struct sc_proxy_traits<sc_concref<X, Y> > :
183        sc_mixed_proxy_traits_helper<
184            typename X::traits_type, typename Y::traits_type>
185{};
186
187
188// ----------------------------------------------------------------------------
189//  CLASS TEMPLATE : sc_proxy
190//
191//  Base class template for bit/logic vector classes.
192//  (Barton/Nackmann implementation)
193// ----------------------------------------------------------------------------
194
195template <class X>
196class sc_proxy // #### : public sc_value_base
197{
198  public:
199    typedef typename sc_proxy_traits<X>::traits_type traits_type;
200    typedef typename traits_type::bit_type bit_type;
201    typedef typename traits_type::value_type value_type;
202
203    // virtual destructor
204    virtual ~sc_proxy() {}
205
206    // casts
207    X &back_cast() { return static_cast<X &>(*this); }
208
209    const X &back_cast() const { return static_cast<const X &>(*this); }
210
211    // assignment operators
212    template <class Y>
213    X &
214    assign_(const sc_proxy<Y> &a)
215    {
216        assign_p_(*this, a);
217        return back_cast();
218    }
219
220    X &assign_(const char *a);
221    X &assign_(const bool *a);
222    X &assign_(const sc_logic *a);
223
224    X &
225    assign_(const sc_unsigned &a)
226    {
227        assign_v_(*this, a);
228        return back_cast();
229    }
230
231    X &
232    assign_(const sc_signed &a)
233    {
234        assign_v_(*this, a);
235        return back_cast();
236    }
237
238    X &assign_(const sc_uint_base &a) { return assign_((uint64)a); }
239    X &assign_(const sc_int_base &a) { return assign_((int64)a); }
240    X &assign_(unsigned int a);
241    X &assign_(int a);
242    X &assign_(unsigned long a);
243    X &assign_(long a);
244    X &assign_(uint64 a);
245    X &assign_(int64 a);
246
247    // bitwise operators and functions
248
249    // bitwise complement
250    X &b_not();
251
252    const sc_lv_base operator ~ () const;
253
254    // bitwise and
255    X &operator &= (const char *b);
256    X &operator &= (const bool *b);
257    X &operator &= (const sc_logic *b);
258    X &operator &= (const sc_unsigned &b);
259    X &operator &= (const sc_signed &b);
260    X &operator &= (const sc_uint_base &b) { return operator &= ((uint64)b); }
261    X &operator &= (const sc_int_base &b) { return operator &= ((int64)b); }
262    X &operator &= (unsigned long b);
263    X &operator &= (long b);
264    X &operator &= (unsigned int b) { return operator &= ((unsigned long)b); }
265    X &operator &= (int b) { return operator &= ((long)b); }
266    X &operator &= (uint64 b);
267    X &operator &= (int64 b);
268
269    const sc_lv_base operator & (const char *b) const;
270    const sc_lv_base operator & (const bool *b) const;
271    const sc_lv_base operator & (const sc_logic *b) const;
272    const sc_lv_base operator & (const sc_unsigned &b) const;
273    const sc_lv_base operator & (const sc_signed &b) const;
274    const sc_lv_base operator & (const sc_uint_base &b) const;
275    const sc_lv_base operator & (const sc_int_base &b) const;
276    const sc_lv_base operator & (unsigned long b) const;
277    const sc_lv_base operator & (long b) const;
278    const sc_lv_base operator & (unsigned int b) const;
279    const sc_lv_base operator & (int b) const;
280    const sc_lv_base operator & (uint64 b) const;
281    const sc_lv_base operator & (int64 b) const;
282
283    // bitwise or
284    X &operator |= (const char *b);
285    X &operator |= (const bool *b);
286    X &operator |= (const sc_logic *b);
287    X &operator |= (const sc_unsigned &b);
288    X &operator |= (const sc_signed &b);
289    X &operator |= (const sc_uint_base &b) { return operator |= ((uint64)b); }
290    X &operator |= (const sc_int_base &b) { return operator |= ((int64)b); }
291    X &operator |= (unsigned long b);
292    X &operator |= (long b);
293    X &operator |= (unsigned int b) { return operator |= ((unsigned long)b); }
294    X &operator |= (int b) { return operator |= ((long)b); }
295    X &operator |= (uint64 b);
296    X &operator |= (int64 b);
297
298    const sc_lv_base operator | (const char *b) const;
299    const sc_lv_base operator | (const bool *b) const;
300    const sc_lv_base operator | (const sc_logic *b) const;
301    const sc_lv_base operator | (const sc_unsigned &b) const;
302    const sc_lv_base operator | (const sc_signed &b) const;
303    const sc_lv_base operator | (const sc_uint_base &b) const;
304    const sc_lv_base operator | (const sc_int_base &b) const;
305    const sc_lv_base operator | (unsigned long b) const;
306    const sc_lv_base operator | (long b) const;
307    const sc_lv_base operator | (unsigned int b) const;
308    const sc_lv_base operator | (int b) const;
309    const sc_lv_base operator | (uint64 b) const;
310    const sc_lv_base operator | (int64 b) const;
311
312    // bitwise xor
313    X &operator ^= (const char *b);
314    X &operator ^= (const bool *b);
315    X &operator ^= (const sc_logic *b);
316    X &operator ^= (const sc_unsigned &b);
317    X &operator ^= (const sc_signed &b);
318    X &operator ^= (const sc_uint_base &b) { return operator ^= ((uint64)b); }
319    X &operator ^= (const sc_int_base &b) { return operator ^= ((int64)b); }
320    X &operator ^= (unsigned long b);
321    X &operator ^= (long b);
322    X &operator ^= (unsigned int b) { return operator ^= ((unsigned long)b); }
323    X &operator ^= (int b) { return operator ^= ((long)b); }
324    X &operator ^= (uint64 b);
325    X &operator ^= (int64 b);
326
327    const sc_lv_base operator ^ (const char *b) const;
328    const sc_lv_base operator ^ (const bool *b) const;
329    const sc_lv_base operator ^ (const sc_logic *b) const;
330    const sc_lv_base operator ^ (const sc_unsigned &b) const;
331    const sc_lv_base operator ^ (const sc_signed &b) const;
332    const sc_lv_base operator ^ (const sc_uint_base &b) const;
333    const sc_lv_base operator ^ (const sc_int_base &b) const;
334    const sc_lv_base operator ^ (unsigned long b) const;
335    const sc_lv_base operator ^ (long b) const;
336    const sc_lv_base operator ^ (unsigned int b) const;
337    const sc_lv_base operator ^ (int b) const;
338    const sc_lv_base operator ^ (uint64 b) const;
339    const sc_lv_base operator ^ (int64 b) const;
340
341    // bitwise left shift
342    X &operator <<= (int n);
343    const sc_lv_base operator << (int n) const;
344
345    // bitwise right shift
346    X &operator >>= (int n);
347    const sc_lv_base operator >> (int n) const;
348
349    // bitwise left rotate
350    X &lrotate(int n);
351
352    // bitwise right rotate
353    X &rrotate(int n);
354
355    // bitwise reverse
356    X &reverse();
357
358    // bit selection
359    sc_bitref<X> operator [] (int i) { return sc_bitref<X>(back_cast(), i); }
360    sc_bitref_r<X>
361    operator [] (int i) const
362    {
363        return sc_bitref_r<X>(back_cast(), i);
364    }
365    sc_bitref<X> bit(int i) { return sc_bitref<X>(back_cast(), i); }
366    sc_bitref_r<X> bit(int i) const { return sc_bitref_r<X>(back_cast(), i); }
367
368    // part selection
369    sc_subref<X>
370    operator () (int hi, int lo)
371    {
372        return sc_subref<X>(back_cast(), hi, lo);
373    }
374    sc_subref_r<X>
375    operator () (int hi, int lo) const
376    {
377        return sc_subref_r<X>(back_cast(), hi, lo);
378    }
379    sc_subref<X>
380    range(int hi, int lo)
381    {
382        return sc_subref<X>(back_cast(), hi, lo);
383    }
384    sc_subref_r<X>
385    range(int hi, int lo) const
386    {
387        return sc_subref_r<X>(back_cast(), hi, lo);
388    }
389
390    // reduce functions
391    value_type and_reduce() const;
392    value_type
393    nand_reduce() const
394    {
395        return sc_logic::not_table[and_reduce()];
396    }
397    value_type or_reduce() const;
398    value_type nor_reduce() const { return sc_logic::not_table[or_reduce()]; }
399    value_type xor_reduce() const;
400    value_type
401    xnor_reduce() const
402    {
403        return sc_logic::not_table[xor_reduce()];
404    }
405
406    // relational operators
407    bool operator == (const char *b) const;
408    bool operator == (const bool *b) const;
409    bool operator == (const sc_logic *b) const;
410    bool operator == (const sc_unsigned &b) const;
411    bool operator == (const sc_signed &b) const;
412    bool operator == (const sc_uint_base &b) const;
413    bool operator == (const sc_int_base &b) const;
414    bool operator == (unsigned long b) const;
415    bool operator == (long b) const;
416    bool operator == (unsigned int b) const;
417    bool operator == (int b) const;
418    bool operator == (uint64 b) const;
419    bool operator == (int64 b) const;
420
421    // explicit conversions to character string
422    const std::string to_string() const;
423    const std::string to_string(sc_numrep) const;
424    const std::string to_string(sc_numrep, bool) const;
425
426    // explicit conversions
427    inline int64 to_int64() const { return to_anything_signed(); }
428    inline uint64 to_uint64() const;
429    int to_int() const { return (int)to_anything_signed(); }
430
431    unsigned int
432    to_uint() const
433    {
434        return (unsigned int)to_anything_unsigned();
435    }
436
437    long to_long() const { return (long)to_anything_signed(); }
438
439    unsigned long
440    to_ulong() const
441    {
442        return (unsigned long)to_anything_unsigned();
443    }
444
445    // other methods
446    void
447    print(::std::ostream &os=::std::cout) const
448    {
449        // The test below will force printing in binary if decimal is
450        // specified.
451        if (sc_io_base(os, SC_DEC) == SC_DEC)
452            os << to_string();
453        else
454            os << to_string(sc_io_base(os, SC_BIN), sc_io_show_base(os));
455    }
456
457    void scan(::std::istream &is=::std::cin);
458
459  protected:
460    void check_bounds(int n) const; // check if bit n accessible
461    void check_wbounds(int n) const; // check if word n accessible
462
463    sc_digit to_anything_unsigned() const;
464    int64 to_anything_signed() const;
465};
466
467
468// ----------------------------------------------------------------------------
469
470// bitwise operators and functions
471
472// bitwise and
473
474template <class X, class Y>
475inline X &operator &= (sc_proxy<X> &px, const sc_proxy<Y> &py);
476
477
478template <class X, class Y>
479inline const sc_lv_base operator & (
480        const sc_proxy<X> &px, const sc_proxy<Y> &py);
481
482
483#define DECL_BITWISE_AND_OP_T(tp) \
484template <class X> \
485inline const sc_lv_base operator & (tp b, const sc_proxy<X> &px);
486
487DECL_BITWISE_AND_OP_T(const char *)
488DECL_BITWISE_AND_OP_T(const bool *)
489DECL_BITWISE_AND_OP_T(const sc_logic *)
490DECL_BITWISE_AND_OP_T(const sc_unsigned &)
491DECL_BITWISE_AND_OP_T(const sc_signed &)
492DECL_BITWISE_AND_OP_T(const sc_uint_base &)
493DECL_BITWISE_AND_OP_T(const sc_int_base &)
494DECL_BITWISE_AND_OP_T(unsigned long)
495DECL_BITWISE_AND_OP_T(long)
496DECL_BITWISE_AND_OP_T(unsigned int)
497DECL_BITWISE_AND_OP_T(int)
498DECL_BITWISE_AND_OP_T(uint64)
499DECL_BITWISE_AND_OP_T(int64)
500
501#undef DECL_BITWISE_AND_OP_T
502
503// bitwise or
504template <class X, class Y>
505inline X &operator |= (sc_proxy<X> &px, const sc_proxy<Y> &py);
506
507template <class X, class Y>
508inline const sc_lv_base operator | (
509        const sc_proxy<X> &px, const sc_proxy<Y> &py);
510
511
512#define DECL_BITWISE_OR_OP_T(tp) \
513template <class X> \
514inline const sc_lv_base operator | (tp a, const sc_proxy<X> &px);
515
516DECL_BITWISE_OR_OP_T(const char *)
517DECL_BITWISE_OR_OP_T(const bool *)
518DECL_BITWISE_OR_OP_T(const sc_logic *)
519DECL_BITWISE_OR_OP_T(const sc_unsigned &)
520DECL_BITWISE_OR_OP_T(const sc_signed &)
521DECL_BITWISE_OR_OP_T(const sc_uint_base &)
522DECL_BITWISE_OR_OP_T(const sc_int_base &)
523DECL_BITWISE_OR_OP_T(unsigned long)
524DECL_BITWISE_OR_OP_T(long)
525DECL_BITWISE_OR_OP_T(unsigned int)
526DECL_BITWISE_OR_OP_T(int)
527DECL_BITWISE_OR_OP_T(uint64)
528DECL_BITWISE_OR_OP_T(int64)
529
530#undef DECL_BITWISE_OR_OP_T
531
532// bitwise xor
533template <class X, class Y>
534inline X &operator ^= (sc_proxy<X> &px, const sc_proxy<Y> &py);
535
536template <class X, class Y>
537inline const sc_lv_base operator ^ (
538        const sc_proxy<X> &px, const sc_proxy<Y> &py);
539
540#define DECL_BITWISE_XOR_OP_T(tp) \
541template <class X> \
542inline const sc_lv_base operator ^ (tp a, const sc_proxy<X> &px);
543
544DECL_BITWISE_XOR_OP_T(const char *)
545DECL_BITWISE_XOR_OP_T(const bool *)
546DECL_BITWISE_XOR_OP_T(const sc_logic *)
547DECL_BITWISE_XOR_OP_T(const sc_unsigned &)
548DECL_BITWISE_XOR_OP_T(const sc_signed &)
549DECL_BITWISE_XOR_OP_T(const sc_uint_base &)
550DECL_BITWISE_XOR_OP_T(const sc_int_base &)
551DECL_BITWISE_XOR_OP_T(unsigned long)
552DECL_BITWISE_XOR_OP_T(long)
553DECL_BITWISE_XOR_OP_T(unsigned int)
554DECL_BITWISE_XOR_OP_T(int)
555DECL_BITWISE_XOR_OP_T(uint64)
556DECL_BITWISE_XOR_OP_T(int64)
557
558#undef DECL_BITWISE_XOR_OP_T
559
560// relational operators
561template <class X, class Y>
562inline bool operator == (const sc_proxy<X> &px, const sc_proxy<Y> &py);
563
564template <class X, class Y>
565inline bool operator != (const sc_proxy<X> &px, const sc_proxy<Y> &py);
566
567#define DECL_REL_OP_T(tp) \
568template <class X> \
569inline bool operator == (tp b, const sc_proxy<X> &px); \
570 \
571template <class X> \
572inline bool operator != (const sc_proxy<X> &px, tp b); \
573 \
574template <class X> \
575inline bool operator != (tp b, const sc_proxy<X> &px);
576
577DECL_REL_OP_T(const char *)
578DECL_REL_OP_T(const bool *)
579DECL_REL_OP_T(const sc_logic *)
580DECL_REL_OP_T(const sc_unsigned &)
581DECL_REL_OP_T(const sc_signed &)
582DECL_REL_OP_T(const sc_uint_base &)
583DECL_REL_OP_T(const sc_int_base &)
584DECL_REL_OP_T(unsigned long)
585DECL_REL_OP_T(long)
586DECL_REL_OP_T(unsigned int)
587DECL_REL_OP_T(int)
588DECL_REL_OP_T(uint64)
589DECL_REL_OP_T(int64)
590
591#undef DECL_REL_OP_T
592
593// l-value concatenation
594
595// Due to the fact that temporary objects cannot be passed to non-const
596// references, we have to enumerate, use call by value, and use dynamic
597// memory allocation (and deallocation).
598
599
600// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
601
602template <class X>
603inline void
604get_words_(const X &x, int wi, sc_digit &x_dw, sc_digit &x_cw)
605{
606    x_dw = x.get_word(wi);
607    x_cw = x.get_cword(wi);
608}
609
610template <class X>
611inline void
612set_words_(X &x, int wi, sc_digit x_dw, sc_digit x_cw)
613{
614    x.set_word(wi, x_dw);
615    x.set_cword(wi, x_cw);
616}
617
618template <class X>
619inline void
620extend_sign_w_(X &x, int wi, bool sign)
621{
622    int sz = x.size();
623    unsigned int sgn = (sign ? ~SC_DIGIT_ZERO : SC_DIGIT_ZERO);
624    for (int i = wi; i < sz; ++i) {
625        set_words_(x, i, sgn, SC_DIGIT_ZERO);
626    }
627}
628
629// assignment functions
630template <class X, class Y>
631inline void
632assign_p_(sc_proxy<X> &px, const sc_proxy<Y> &py)
633{
634    if ((void *)&px != (void *)&py) {
635        X &x = px.back_cast();
636        const Y &y = py.back_cast();
637        int sz = x.size();
638        int min_sz = sc_min(sz, y.size());
639        int i = 0;
640        for (; i < min_sz; ++i) {
641            set_words_(x, i, y.get_word(i), y.get_cword(i));
642        }
643        // extend with zeros
644        extend_sign_w_(x, i, false);
645        x.clean_tail();
646    }
647}
648
649// Vector types that are not derived from sc_proxy, sc_int_base,
650// sc_uint_base, sc_signed, or sc_unsigned, must have a length()
651// function and an operator []. The vector argument type must support
652// accessing bits that are beyond the msb. The vector argument type
653// decides what to do there (e.g. sign extension or zero padding).
654
655template <class X, class T>
656inline void
657assign_v_(sc_proxy<X> &px, const T &a)
658{
659    X &x = px.back_cast();
660    int i;
661    int len_x = x.length();
662    int len_a = a.length();
663    if (len_a > len_x)
664        len_a = len_x;
665    for (i = 0; i < len_a; ++i) {
666        x.set_bit(i, sc_logic_value_t((bool)a[i]));
667    }
668    for (; i < len_x; ++i) {
669        x.set_bit(i, sc_logic_value_t(false));
670    }
671}
672
673template <class X>
674inline void
675assign_v_(sc_proxy<X> &px, const sc_int_base &a)
676{
677    X &x = px.back_cast();
678    int i;
679    bool sign = a < 0;
680    int len_x = x.length();
681    int len_a = a.length();
682    if ( len_a > len_x ) len_a = len_x;
683    for (i = 0; i < len_a; ++i) {
684        x.set_bit(i, sc_logic_value_t((bool)a[i]));
685    }
686    for (; i < len_x; ++i) {
687        x.set_bit(i, sc_logic_value_t(sign));
688    }
689}
690
691template <class X>
692inline void
693assign_v_(sc_proxy<X> &px, const sc_signed &a)
694{
695    X &x = px.back_cast();
696    int i;
697    bool sign = a < 0;
698    int len_x = x.length();
699    int len_a = a.length();
700    if (len_a > len_x)
701        len_a = len_x;
702    for (i = 0; i < len_a; ++i) {
703        x.set_bit(i, sc_logic_value_t((bool)a[i]));
704    }
705    for (; i < len_x; ++i) {
706        x.set_bit(i, sc_logic_value_t(sign));
707    }
708}
709
710template <class X>
711inline void
712assign_v_(sc_proxy<X> &px, const sc_uint_base &a)
713{
714    X &x = px.back_cast();
715    int i;
716    int len_x = x.length();
717    int len_a = a.length();
718    if (len_a > len_x)
719        len_a = len_x;
720    for (i = 0; i < len_a; ++i) {
721        x.set_bit(i, sc_logic_value_t((bool)a[i]));
722    }
723    for (; i < len_x; ++i) {
724        x.set_bit(i, sc_logic_value_t(false));
725    }
726}
727
728template <class X>
729inline void
730assign_v_(sc_proxy<X> &px, const sc_unsigned &a)
731{
732    X &x = px.back_cast();
733    int i;
734    int len_x = x.length();
735    int len_a = a.length();
736    if (len_a > len_x)
737        len_a = len_x;
738    for (i = 0; i < len_a; ++i) {
739        x.set_bit(i, sc_logic_value_t((bool)a[i]));
740    }
741    for (; i < len_x; ++i) {
742        x.set_bit(i, sc_logic_value_t(false));
743    }
744}
745
746// assignment operators
747template <class X>
748inline X &
749sc_proxy<X>::assign_(const char *a)
750{
751    X &x = back_cast();
752    std::string s = convert_to_bin(a);
753    int len = x.length();
754    int s_len = s.length() - 1;
755    int min_len = sc_min(len, s_len);
756    int i = 0;
757    for (; i < min_len; ++i) {
758        char c = s[s_len - i - 1];
759        x.set_bit(i, sc_logic::char_to_logic[(int)c]);
760    }
761    // if formatted, fill the rest with sign(s), otherwise fill with zeros
762    sc_logic_value_t fill = (s[s_len] == 'F' ? sc_logic_value_t(s[0] - '0')
763                                             : sc_logic_value_t(0));
764    for (; i < len; ++i) {
765        x.set_bit(i, fill);
766    }
767    return x;
768}
769
770template <class X>
771inline X &
772sc_proxy<X>::assign_(const bool *a)
773{
774    // the length of 'a' must be larger than or equal to the length of 'this'
775    X &x = back_cast();
776    int len = x.length();
777    for (int i = 0; i < len; ++i) {
778        x.set_bit(i, sc_logic_value_t(a[i]));
779    }
780    return x;
781}
782
783template <class X>
784inline X &
785sc_proxy<X>::assign_(const sc_logic *a)
786{
787    // the length of 'a' must be larger than or equal to the length of 'this'
788    X &x = back_cast();
789    int len = x.length();
790    for (int i = 0; i < len; ++i) {
791        x.set_bit(i, a[i].value());
792    }
793    return x;
794}
795
796template <class X>
797inline X &
798sc_proxy<X>::assign_(unsigned int a)
799{
800    X &x = back_cast();
801    set_words_(x, 0, (sc_digit)a, SC_DIGIT_ZERO);
802    // extend with zeros
803    extend_sign_w_(x, 1, false);
804    x.clean_tail();
805    return x;
806}
807
808template <class X>
809inline X &
810sc_proxy<X>::assign_(int a)
811{
812    X &x = back_cast();
813    set_words_(x, 0, (sc_digit)a, SC_DIGIT_ZERO);
814    // extend with sign(a)
815    extend_sign_w_(x, 1, (a < 0));
816    x.clean_tail();
817    return x;
818}
819
820#if SC_LONG_64
821template <class X>
822inline X &
823sc_proxy<X>::assign_(unsigned long a)
824{
825    X &x = back_cast();
826    set_words_(x, 0, ((sc_digit)a & ~SC_DIGIT_ZERO), SC_DIGIT_ZERO);
827    if (x.size() > 1) {
828        set_words_(x, 1, ((sc_digit)(a >> SC_DIGIT_SIZE) & ~SC_DIGIT_ZERO),
829                   SC_DIGIT_ZERO);
830        // extend with zeros
831        extend_sign_w_(x, 2, false);
832    }
833    x.clean_tail();
834    return x;
835}
836
837template <class X>
838inline X &
839sc_proxy<X>::assign_(long a)
840{
841    X &x = back_cast();
842    set_words_(x, 0, ((sc_digit)a & ~SC_DIGIT_ZERO), SC_DIGIT_ZERO);
843    if (x.size() > 1) {
844        set_words_(x, 1,
845                   ((sc_digit)((uint64)a >> SC_DIGIT_SIZE) & ~SC_DIGIT_ZERO),
846                   SC_DIGIT_ZERO);
847        // extend with sign(a)
848        extend_sign_w_(x, 2, (a < 0));
849    }
850    x.clean_tail();
851    return x;
852}
853
854#else
855
856template <class X>
857inline X &
858sc_proxy<X>::assign_(unsigned long a)
859{
860    X &x = back_cast();
861    set_words_(x, 0, (sc_digit)a, SC_DIGIT_ZERO);
862    // extend with zeros
863    extend_sign_w_(x, 1, false);
864    x.clean_tail();
865    return x;
866}
867
868template <class X>
869inline X &
870sc_proxy<X>::assign_(long a)
871{
872    X &x = back_cast();
873    set_words_(x, 0, (sc_digit)a, SC_DIGIT_ZERO);
874    // extend with sign(a)
875    extend_sign_w_(x, 1, (a < 0));
876    x.clean_tail();
877    return x;
878}
879
880#endif
881
882template <class X>
883inline X &
884sc_proxy<X>::assign_(uint64 a)
885{
886    X &x = back_cast();
887    set_words_(x, 0, ((sc_digit)a & ~SC_DIGIT_ZERO), SC_DIGIT_ZERO);
888    if (x.size() > 1) {
889        set_words_(x, 1, ((sc_digit) (a >> SC_DIGIT_SIZE) & ~SC_DIGIT_ZERO),
890                   SC_DIGIT_ZERO );
891        // extend with zeros
892        extend_sign_w_(x, 2, false);
893    }
894    x.clean_tail();
895    return x;
896}
897
898template <class X>
899inline X &
900sc_proxy<X>::assign_(int64 a)
901{
902    X &x = back_cast();
903    set_words_(x, 0, ((sc_digit)a & ~SC_DIGIT_ZERO), SC_DIGIT_ZERO);
904    if (x.size() > 1) {
905        set_words_(x, 1,
906                   ((sc_digit)((uint64)a >> SC_DIGIT_SIZE) & ~SC_DIGIT_ZERO),
907                   SC_DIGIT_ZERO );
908        // extend with sign(a)
909        extend_sign_w_(x, 2, (a < 0));
910    }
911    x.clean_tail();
912    return x;
913}
914
915// bitwise operators and functions
916
917// bitwise complement
918template <class X>
919inline X &
920sc_proxy<X>::b_not()
921{
922    X &x = back_cast();
923    int sz = x.size();
924    for (int i = 0; i < sz; ++i) {
925        sc_digit x_dw, x_cw;
926        get_words_(x, i, x_dw, x_cw);
927        x.set_word(i, x_cw | ~x_dw);
928    }
929    x.clean_tail();
930    return x;
931}
932
933// bitwise and
934template <class X, class Y>
935inline X &
936b_and_assign_(sc_proxy<X> &px, const sc_proxy<Y> &py)
937{
938    X &x = px.back_cast();
939    const Y &y = py.back_cast();
940    sc_assert(x.length() == y.length());
941    int sz = x.size();
942    for (int i = 0; i < sz; ++i) {
943        sc_digit x_dw, x_cw, y_dw, y_cw;
944        get_words_(x, i, x_dw, x_cw);
945        get_words_(y, i, y_dw, y_cw);
946        sc_digit cw = (x_dw & y_cw) | (x_cw & y_dw) | (x_cw & y_cw);
947        sc_digit dw = cw | (x_dw & y_dw);
948        set_words_(x, i, dw, cw);
949    }
950    // tail cleaning not needed
951    return x;
952}
953
954// bitwise or
955template <class X, class Y>
956inline X &
957b_or_assign_(sc_proxy<X> &px, const sc_proxy<Y> &py)
958{
959    X &x = px.back_cast();
960    const Y &y = py.back_cast();
961    sc_assert(x.length() == y.length());
962    int sz = x.size();
963    for (int i = 0; i < sz; ++i) {
964        sc_digit x_dw, x_cw, y_dw, y_cw;
965        get_words_(x, i, x_dw, x_cw);
966        get_words_(y, i, y_dw, y_cw);
967        sc_digit cw = (x_cw & y_cw) | (x_cw & ~y_dw) | (~x_dw & y_cw);
968        sc_digit dw = cw | x_dw | y_dw;
969        set_words_(x, i, dw, cw);
970    }
971    // tail cleaning not needed
972    return x;
973}
974
975// bitwise xor
976template <class X, class Y>
977inline X &
978b_xor_assign_(sc_proxy<X> &a, const sc_proxy<Y> &b)
979{
980    X &x = a.back_cast();
981    const Y &y = b.back_cast();
982    sc_assert(x.length() == y.length());
983    int sz = x.size();
984    for (int i = 0; i < sz; ++i) {
985        sc_digit x_dw, x_cw, y_dw, y_cw;
986        get_words_(x, i, x_dw, x_cw);
987        get_words_(y, i, y_dw, y_cw);
988        sc_digit cw = x_cw | y_cw;
989        sc_digit dw = cw | (x_dw ^ y_dw);
990        set_words_( x, i, dw, cw );
991    }
992    // tail cleaning not needed
993    return x;
994}
995
996// bitwise left shift
997template <class X>
998inline X &
999sc_proxy<X>::operator <<= (int n)
1000{
1001    X &x = back_cast();
1002    if (n < 0) {
1003        sc_proxy_out_of_bounds("left shift operation is only allowed with "
1004                               "positive shift values, shift value = ", n);
1005        return x;
1006    }
1007    if (n >= x.length()) {
1008        extend_sign_w_(x, 0, false);
1009        // no tail cleaning needed
1010        return x;
1011    }
1012    int sz = x.size();
1013    int wn = n / SC_DIGIT_SIZE;
1014    int bn = n % SC_DIGIT_SIZE;
1015    if (wn != 0) {
1016        // shift words
1017        int i = sz - 1;
1018        for (; i >= wn; --i) {
1019            set_words_(x, i, x.get_word(i - wn), x.get_cword(i - wn));
1020        }
1021        for (; i >= 0; --i) {
1022            set_words_(x, i, SC_DIGIT_ZERO, SC_DIGIT_ZERO);
1023        }
1024    }
1025    if (bn != 0) {
1026        // shift bits
1027        for (int i = sz - 1; i >= 1; --i) {
1028            sc_digit x_dw, x_cw;
1029            get_words_(x, i, x_dw, x_cw);
1030            x_dw <<= bn;
1031            x_dw |= x.get_word(i - 1) >> (SC_DIGIT_SIZE - bn);
1032            x_cw <<= bn;
1033            x_cw |= x.get_cword(i - 1) >> (SC_DIGIT_SIZE - bn);
1034            set_words_(x, i, x_dw, x_cw);
1035        }
1036        sc_digit x_dw, x_cw;
1037        get_words_(x, 0, x_dw, x_cw);
1038        x_dw <<= bn;
1039        x_cw <<= bn;
1040        set_words_(x, 0, x_dw, x_cw);
1041    }
1042    x.clean_tail();
1043    return x;
1044}
1045
1046// bitwise right shift
1047template <class X>
1048inline X &
1049sc_proxy<X>::operator >>= (int n)
1050{
1051    X &x = back_cast();
1052    if (n < 0) {
1053        sc_proxy_out_of_bounds("right shift operation is only allowed with "
1054                               "positive shift values, shift value = ", n);
1055        return x;
1056    }
1057    if (n >= x.length()) {
1058        extend_sign_w_(x, 0, false);
1059        // no tail cleaning needed
1060        return x;
1061    }
1062    int sz = x.size();
1063    int wn = n / SC_DIGIT_SIZE;
1064    int bn = n % SC_DIGIT_SIZE;
1065    if (wn != 0) {
1066        // shift words
1067        int i = 0;
1068        for (; i < (sz - wn); ++i) {
1069            set_words_(x, i, x.get_word(i + wn), x.get_cword(i + wn));
1070        }
1071        for (; i < sz; ++i) {
1072            set_words_(x, i, SC_DIGIT_ZERO, SC_DIGIT_ZERO);
1073        }
1074    }
1075    if (bn != 0) {
1076        // shift bits
1077        for (int i = 0; i < (sz - 1); ++i) {
1078            sc_digit x_dw, x_cw;
1079            get_words_(x, i, x_dw, x_cw);
1080            x_dw >>= bn;
1081            x_dw |= x.get_word(i + 1) << (SC_DIGIT_SIZE - bn);
1082            x_cw >>= bn;
1083            x_cw |= x.get_cword(i + 1) << (SC_DIGIT_SIZE - bn);
1084            set_words_(x, i, x_dw, x_cw);
1085        }
1086        sc_digit x_dw, x_cw;
1087        get_words_(x, sz - 1, x_dw, x_cw);
1088        x_dw >>= bn;
1089        x_cw >>= bn;
1090        set_words_(x, sz - 1, x_dw, x_cw);
1091    }
1092    x.clean_tail();
1093    return x;
1094}
1095
1096// bitwise left rotate
1097template <class X>
1098inline const sc_lv_base lrotate(const sc_proxy<X> &x, int n);
1099
1100// bitwise right rotate
1101template <class X>
1102inline const sc_lv_base rrotate(const sc_proxy<X>& x, int n);
1103
1104// bitwise reverse
1105template <class X>
1106inline X &
1107sc_proxy<X>::reverse()
1108{
1109    X &x = back_cast();
1110    int len = x.length();
1111    int half_len = len / 2;
1112    for (int i = 0, j = len - 1; i < half_len; ++ i, --j) {
1113        value_type t = x.get_bit(i);
1114        x.set_bit(i, x.get_bit(j));
1115        x.set_bit(j, t);
1116    }
1117    return x;
1118}
1119
1120template <class X>
1121inline const sc_lv_base reverse(const sc_proxy<X> &a);
1122
1123// reduce functions
1124template <class X>
1125inline typename sc_proxy<X>::value_type
1126sc_proxy<X>::and_reduce() const
1127{
1128    const X &x = back_cast();
1129    value_type result = value_type(1);
1130    int len = x.length();
1131    for (int i = 0; i < len; ++i) {
1132        result = sc_logic::and_table[result][x.get_bit(i)];
1133    }
1134    return result;
1135}
1136
1137template <class X>
1138inline typename sc_proxy<X>::value_type
1139sc_proxy<X>::or_reduce() const
1140{
1141    const X &x = back_cast();
1142    value_type result = value_type(0);
1143    int len = x.length();
1144    for (int i = 0; i < len; ++i) {
1145        result = sc_logic::or_table[result][x.get_bit(i)];
1146    }
1147    return result;
1148}
1149
1150template <class X>
1151inline typename sc_proxy<X>::value_type
1152sc_proxy<X>::xor_reduce() const
1153{
1154    const X &x = back_cast();
1155    value_type result = value_type(0);
1156    int len = x.length();
1157    for (int i = 0; i < len; ++i) {
1158        result = sc_logic::xor_table[result][x.get_bit(i)];
1159    }
1160    return result;
1161}
1162
1163// relational operators
1164template <class X, class Y>
1165inline bool
1166operator != (const sc_proxy<X> &px, const sc_proxy<Y> &py)
1167{
1168    return !(px == py);
1169}
1170
1171
1172#define DEFN_REL_OP_T(tp) \
1173template <class X> \
1174inline bool operator == (tp b, const sc_proxy<X> &px) { return (px == b); } \
1175 \
1176template <class X> \
1177inline bool operator != (const sc_proxy<X> &px, tp b) { return !(px == b); } \
1178 \
1179template <class X> \
1180inline bool operator != (tp b, const sc_proxy<X> &px) { return !(px == b); }
1181
1182DEFN_REL_OP_T(const char *)
1183DEFN_REL_OP_T(const bool *)
1184DEFN_REL_OP_T(const sc_logic *)
1185DEFN_REL_OP_T(const sc_unsigned &)
1186DEFN_REL_OP_T(const sc_signed &)
1187DEFN_REL_OP_T(const sc_uint_base &)
1188DEFN_REL_OP_T(const sc_int_base &)
1189DEFN_REL_OP_T(unsigned long)
1190DEFN_REL_OP_T(long)
1191DEFN_REL_OP_T(unsigned int)
1192DEFN_REL_OP_T(int)
1193DEFN_REL_OP_T(uint64)
1194DEFN_REL_OP_T(int64)
1195
1196#undef DEFN_REL_OP_T
1197
1198// explicit conversions to character string
1199template <class X>
1200inline const std::string
1201sc_proxy<X>::to_string() const
1202{
1203    const X &x = back_cast();
1204    int len = x.length();
1205    std::string s; // (len + 1);
1206    for (int i = 0; i < len; ++i) {
1207        s += sc_logic::logic_to_char[x.get_bit(len - i - 1)];
1208    }
1209    return s;
1210}
1211
1212template <class X>
1213inline const std::string
1214sc_proxy<X>::to_string(sc_numrep numrep) const
1215{
1216    return convert_to_fmt(to_string(), numrep, true);
1217}
1218
1219template <class X>
1220inline const std::string
1221sc_proxy<X>::to_string(sc_numrep numrep, bool w_prefix) const
1222{
1223    return convert_to_fmt(to_string(), numrep, w_prefix);
1224}
1225
1226// other methods
1227template <class X>
1228inline void
1229sc_proxy<X>::scan(::std::istream &is)
1230{
1231    std::string s;
1232    is >> s;
1233    back_cast() = s.c_str();
1234}
1235
1236template <class X>
1237inline void
1238sc_proxy<X>::check_bounds(int n) const // check if bit n accessible
1239{
1240    if (n < 0 || n >= back_cast().length()) {
1241        sc_proxy_out_of_bounds(NULL, n);
1242        sc_core::sc_abort(); // can't recover from here
1243    }
1244}
1245
1246template <class X>
1247inline void
1248sc_proxy<X>::check_wbounds(int n) const // check if word n accessible
1249{
1250    if (n < 0 || n >= back_cast().size()) {
1251        sc_proxy_out_of_bounds(NULL, n);
1252        sc_core::sc_abort(); // can't recover from here
1253    }
1254}
1255
1256template <class X>
1257inline sc_digit
1258sc_proxy<X>::to_anything_unsigned() const
1259{
1260    // only 0 word is returned
1261    // can't convert logic values other than 0 and 1
1262    const X &x = back_cast();
1263    int len = x.length();
1264    if (x.get_cword(0) != SC_DIGIT_ZERO) {
1265        SC_REPORT_WARNING(sc_core::SC_ID_VECTOR_CONTAINS_LOGIC_VALUE_, 0);
1266    }
1267    sc_digit w = x.get_word(0);
1268    if (len >= SC_DIGIT_SIZE) {
1269        return w;
1270    }
1271    return (w & (~SC_DIGIT_ZERO >> (SC_DIGIT_SIZE - len)));
1272}
1273
1274template <class X>
1275inline uint64
1276sc_proxy<X>::to_uint64() const
1277{
1278    // words 1 and 0 returned.
1279    // can't convert logic values other than 0 and 1
1280    const X &x = back_cast();
1281    int len = x.length();
1282    if (x.get_cword(0) != SC_DIGIT_ZERO) {
1283        SC_REPORT_WARNING(sc_core::SC_ID_VECTOR_CONTAINS_LOGIC_VALUE_, 0);
1284    }
1285    uint64 w = x.get_word(0);
1286    if (len > SC_DIGIT_SIZE) {
1287        if (x.get_cword(1) != SC_DIGIT_ZERO) {
1288            SC_REPORT_WARNING(sc_core::SC_ID_VECTOR_CONTAINS_LOGIC_VALUE_, 0);
1289        }
1290        uint64 w1 = x.get_word(1);
1291        w = w | (w1 << SC_DIGIT_SIZE);
1292        return w;
1293    } else if (len == SC_DIGIT_SIZE) {
1294        return w;
1295    } else {
1296        return (w & (~SC_DIGIT_ZERO >> (SC_DIGIT_SIZE - len)));
1297    }
1298}
1299
1300template <class X>
1301inline int64
1302sc_proxy<X>::to_anything_signed() const
1303{
1304    const X &x = back_cast();
1305    int len = x.length();
1306    int64 w = 0;
1307
1308    if (len > SC_DIGIT_SIZE) {
1309        if (x.get_cword(1) != SC_DIGIT_ZERO)
1310            SC_REPORT_WARNING(sc_core::SC_ID_VECTOR_CONTAINS_LOGIC_VALUE_, 0);
1311        w = x.get_word(1);
1312    }
1313    if (x.get_cword(0) != SC_DIGIT_ZERO)
1314        SC_REPORT_WARNING(sc_core::SC_ID_VECTOR_CONTAINS_LOGIC_VALUE_, 0);
1315    w = (w << SC_DIGIT_SIZE) | x.get_word(0);
1316    if (len >= 64) {
1317        return w;
1318    }
1319
1320    uint64 zero = 0;
1321    value_type sgn = x.get_bit(len - 1);
1322    if (sgn == 0) {
1323        return (int64)(w & (~zero >> (64 - len)));
1324    } else {
1325        return (int64)(w | (~zero << len));
1326    }
1327}
1328
1329
1330// ----------------------------------------------------------------------------
1331
1332// functional notation for the reduce methods
1333template <class X>
1334inline typename sc_proxy<X>::value_type
1335and_reduce(const sc_proxy<X> &a)
1336{
1337    return a.and_reduce();
1338}
1339
1340template <class X>
1341inline typename sc_proxy<X>::value_type
1342nand_reduce(const sc_proxy<X> &a)
1343{
1344    return a.nand_reduce();
1345}
1346
1347template <class X>
1348inline typename sc_proxy<X>::value_type
1349or_reduce(const sc_proxy<X> &a)
1350{
1351    return a.or_reduce();
1352}
1353
1354template <class X>
1355inline typename sc_proxy<X>::value_type
1356nor_reduce(const sc_proxy<X> &a)
1357{
1358    return a.nor_reduce();
1359}
1360
1361template <class X>
1362inline typename sc_proxy<X>::value_type
1363xor_reduce(const sc_proxy<X> &a)
1364{
1365    return a.xor_reduce();
1366}
1367
1368template <class X>
1369inline typename sc_proxy<X>::value_type
1370xnor_reduce(const sc_proxy<X> &a)
1371{
1372    return a.xnor_reduce();
1373}
1374
1375// ----------------------------------------------------------------------------
1376
1377template <class X>
1378inline ::std::ostream &
1379operator << (::std::ostream &os, const sc_proxy<X> &a)
1380{
1381    a.print(os);
1382    return os;
1383}
1384
1385template <class X>
1386inline ::std::istream &
1387operator >> (::std::istream &is, sc_proxy<X> &a)
1388{
1389    a.scan(is);
1390    return is;
1391}
1392
1393} // namespace sc_dt
1394
1395#endif // __SYSTEMC_EXT_DT_BIT_SC_PROXY_HH__
1396