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