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_concatref.h -- Concatenation support.
23
24  Original Author: Andy Goodrich, Forte Design, Inc.
25
26 *****************************************************************************/
27
28/*****************************************************************************
29
30  MODIFICATION LOG - modifiers, enter your name, affiliation, date and
31  changes you are making here.
32
33      Name, Affiliation, Date:
34  Description of Modification:
35
36  Andy Goodrich, Forte Design Systems, 17 Nov 2002
37  Creation of sc_concatref class by merging the capabilities of
38  sc_int_concref, sc_int_concref, sc_uint_concref, sc_uint_concref,
39  and implementing the capabilities of sc_signed_concref, sc_signed_concref,
40  sc_unsigned_concref, and sc_unsigned_concref. The resultant class allows
41  mixed mode concatenations on the left and right sides of an assignment.
42
43 *****************************************************************************/
44
45// $Log: sc_concatref.h,v $
46// Revision 1.6  2011/08/24 22:05:48  acg
47//  Torsten Maehne: initialization changes to remove warnings.
48//
49// Revision 1.5  2009/11/17 19:58:15  acg
50//  Andy Goodrich: fix of shift rhs possibilities to include "int".
51//
52// Revision 1.4  2009/02/28 00:26:29  acg
53//  Andy Goodrich: bug fixes.
54//
55// Revision 1.3  2008/04/29 20:23:55  acg
56//  Andy Goodrich: fixed the code that assigns the value of a string to
57//  an sc_concatref instance.
58//
59// Revision 1.2  2008/02/14 20:57:26  acg
60//  Andy Goodrich: added casts to ~0 instances to keep MSVC compiler happy.
61//
62// Revision 1.1.1.1  2006/12/15 20:20:05  acg
63// SystemC 2.3
64//
65// Revision 1.4  2006/10/23 19:36:59  acg
66//  Andy Goodrich: changed casts for operations on concatenation values to
67//  mirror those of sc_unsigned. For instance, an sc_unsigned minus a value
68//  returns an sc_signed result, whereas an sc_concatref minus a value was
69//  returning an sc_unsigned result. Now both sc_unsigned and sc_concatref
70//  minus a value return an sc_signed result.
71//
72// Revision 1.3  2006/01/13 18:54:01  acg
73// Andy Goodrich: added $Log command so that CVS comments are reproduced in
74// the source.
75//
76
77#ifndef __SYSTEMC_EXT_DT_MISC_SC_CONCATREF_HH__
78#define __SYSTEMC_EXT_DT_MISC_SC_CONCATREF_HH__
79
80#include <iostream>
81
82#include "../bit/sc_bv.hh"
83#include "../bit/sc_lv.hh"
84#include "../int/sc_int_base.hh"
85#include "../int/sc_signed.hh"
86#include "../int/sc_uint_base.hh"
87#include "../int/sc_unsigned.hh"
88#include "../sc_temporary.hh"
89#include "sc_value_base.hh"
90
91namespace sc_dt
92{
93
94// classes defined in this module
95class sc_concatref;
96class sc_concat_bool;
97
98} // namespace sc_dt
99
100namespace sc_core
101{
102
103extern sc_byte_heap sc_temp_heap; // Temporary storage.
104
105// explicit template instantiations
106extern template class sc_vpool<sc_dt::sc_concatref>;
107extern template class sc_vpool<sc_dt::sc_concat_bool>;
108
109} // namespace sc_core
110
111namespace sc_dt {
112
113// ----------------------------------------------------------------------------
114//  CLASS TEMPLATE : sc_concatref
115//
116//  Proxy class for sized bit concatenation.
117// ----------------------------------------------------------------------------
118
119class sc_concatref : public sc_generic_base<sc_concatref>, public sc_value_base
120{
121  public:
122    friend class sc_core::sc_vpool<sc_concatref>;
123
124    inline void
125    initialize(sc_value_base &left, sc_value_base &right)
126    {
127        bool left_xz; // True if x's and/or z's found in left.
128        bool right_xz; // True if x's and/or z's found in right.
129
130        m_left_p = (sc_value_base *)&left;
131        m_right_p = (sc_value_base *)&right;
132        m_len_r = right.concat_length(&right_xz);
133        m_len = left.concat_length(&left_xz) + m_len_r;
134        m_flags = (left_xz || right_xz) ? cf_xz_present : cf_none;
135    }
136
137
138    inline void
139    initialize(const sc_value_base &left, const sc_value_base &right)
140    {
141        bool left_xz;   // True if x's and/or z's found in left.
142        bool right_xz;  // True if x's and/or z's found in right.
143
144        m_left_p = (sc_value_base *)&left;
145        m_right_p = (sc_value_base *)&right;
146        m_len_r = right.concat_length(&right_xz);
147        m_len = left.concat_length(&left_xz) + m_len_r;
148        m_flags = (left_xz || right_xz) ? cf_xz_present : cf_none;
149    }
150
151    // destructor
152    virtual ~sc_concatref() {}
153
154    // capacity
155    unsigned int length() const { return m_len; }
156
157    // concatenation
158    virtual int
159    concat_length(bool *xz_present_p) const
160    {
161        if (xz_present_p)
162            *xz_present_p = m_flags & cf_xz_present ? true : false;
163        return m_len;
164    }
165
166    virtual void
167    concat_clear_data(bool to_ones)
168    {
169        m_left_p->concat_clear_data(to_ones);
170        m_right_p->concat_clear_data(to_ones);
171    }
172
173    virtual bool
174    concat_get_ctrl(sc_digit *dst_p, int low_i) const
175    {
176        bool rnz = m_right_p->concat_get_ctrl(dst_p, low_i);
177        bool lnz = m_left_p->concat_get_ctrl(dst_p, low_i + m_len_r);
178        return rnz || lnz;
179    }
180
181    virtual bool
182    concat_get_data(sc_digit *dst_p, int low_i) const
183    {
184        bool rnz = m_right_p->concat_get_data(dst_p, low_i);
185        bool lnz = m_left_p->concat_get_data(dst_p, low_i + m_len_r);
186        return rnz || lnz;
187    }
188
189    virtual uint64
190    concat_get_uint64() const
191    {
192        if (m_len_r >= 64) {
193            return m_right_p->concat_get_uint64();
194        } else {
195            return (m_left_p->concat_get_uint64() << m_len_r) |
196                m_right_p->concat_get_uint64();
197        }
198    }
199
200    virtual void
201    concat_set(int64 src, int low_i)
202    {
203        m_right_p->concat_set(src, low_i);
204        m_left_p->concat_set(src, low_i + m_len_r);
205    }
206
207    virtual void
208    concat_set(const sc_signed &src, int low_i)
209    {
210        m_right_p->concat_set(src, low_i);
211        m_left_p->concat_set(src, low_i + m_len_r);
212    }
213
214    virtual void
215    concat_set(const sc_unsigned &src, int low_i)
216    {
217        m_right_p->concat_set(src, low_i);
218        m_left_p->concat_set(src, low_i + m_len_r);
219    }
220
221    virtual void
222    concat_set(uint64 src, int low_i)
223    {
224        m_right_p->concat_set(src, low_i);
225        m_left_p->concat_set(src, low_i + m_len_r);
226    }
227
228    // explicit conversions
229    uint64
230    to_uint64() const
231    {
232        uint64 mask;
233        uint64 result;
234
235        result = m_right_p->concat_get_uint64();
236        if (m_len_r < 64) {
237            mask = (uint64)~0;
238            result = (m_left_p->concat_get_uint64() << m_len_r) |
239                        (result & ~(mask << m_len_r));
240        }
241        if (m_len < 64) {
242            mask = (uint64)~0;
243            result = result & ~(mask << m_len);
244        }
245        return result;
246    }
247
248    const sc_unsigned &
249    value() const
250    {
251        bool left_non_zero;
252        sc_unsigned *result_p = sc_unsigned::m_pool.allocate();
253        bool right_non_zero;
254
255        result_p->nbits = result_p->num_bits(m_len);
256        result_p->ndigits = DIV_CEIL(result_p->nbits);
257        result_p->digit = (sc_digit *)sc_core::sc_temp_heap.allocate(
258            sizeof(sc_digit) * result_p->ndigits);
259        result_p->digit[result_p->ndigits - 1] = 0;
260        right_non_zero = m_right_p->concat_get_data(result_p->digit, 0);
261        left_non_zero = m_left_p->concat_get_data(result_p->digit, m_len_r);
262        if (left_non_zero || right_non_zero)
263            result_p->sgn = SC_POS;
264        else
265            result_p->sgn = SC_ZERO;
266        return *result_p;
267    }
268
269    int64 to_int64() const { return (int64)to_uint64(); }
270    int to_int() const { return (int)to_int64(); }
271    unsigned int to_uint() const { return (unsigned int)to_uint64(); }
272    long to_long() const { return (long)to_int64(); }
273    unsigned long to_ulong() const { return (unsigned long)to_uint64(); }
274    double to_double() const { return value().to_double(); }
275
276    void to_sc_signed(sc_signed &target) const { target = value(); }
277
278    void to_sc_unsigned(sc_unsigned &target) const { target = value(); }
279
280    // implicit conversions:
281    operator uint64 () const { return to_uint64(); }
282
283    operator const sc_unsigned & () const { return value(); }
284
285    // unary operators:
286    sc_unsigned operator + () const { return value(); }
287
288    sc_signed operator - () const { return -value(); }
289
290    sc_unsigned operator ~ () const { return ~value(); }
291
292    // explicit conversion to character string
293    const std::string
294    to_string(sc_numrep numrep=SC_DEC) const
295    {
296        return value().to_string(numrep);
297    }
298
299    const std::string
300    to_string(sc_numrep numrep, bool w_prefix) const
301    {
302        return value().to_string(numrep,w_prefix);
303    }
304
305    // assignments
306    inline const sc_concatref &
307    operator = (int v)
308    {
309        m_right_p->concat_set((int64)v, 0);
310        m_left_p->concat_set((int64)v, m_len_r);
311        return *this;
312    }
313
314    inline const sc_concatref &
315    operator = (long v)
316    {
317        m_right_p->concat_set((int64)v, 0);
318        m_left_p->concat_set((int64)v, m_len_r);
319        return *this;
320    }
321
322    inline const sc_concatref &
323    operator = (int64 v)
324    {
325        m_right_p->concat_set(v, 0);
326        m_left_p->concat_set(v, m_len_r);
327        return *this;
328    }
329
330    inline const sc_concatref &
331    operator = (unsigned int v)
332    {
333        m_right_p->concat_set((uint64)v, 0);
334        m_left_p->concat_set((uint64)v, m_len_r);
335        return *this;
336    }
337
338    inline const sc_concatref &
339    operator = (unsigned long v)
340    {
341        m_right_p->concat_set((uint64)v, 0);
342        m_left_p->concat_set((uint64)v, m_len_r);
343        return *this;
344    }
345
346    inline const sc_concatref &
347    operator = (uint64 v)
348    {
349        m_right_p->concat_set(v, 0);
350        m_left_p->concat_set(v, m_len_r);
351        return *this;
352    }
353
354    const sc_concatref &
355    operator = (const sc_concatref &v)
356    {
357        sc_unsigned temp(v.length());
358        temp = v.value();
359        m_right_p->concat_set(temp, 0);
360        m_left_p->concat_set(temp, m_len_r);
361        return *this;
362    }
363
364    const sc_concatref &
365    operator = (const sc_signed &v)
366    {
367        m_right_p->concat_set(v, 0);
368        m_left_p->concat_set(v, m_len_r);
369        return *this;
370    }
371
372    const sc_concatref &
373    operator = (const sc_unsigned &v)
374    {
375        m_right_p->concat_set(v, 0);
376        m_left_p->concat_set(v, m_len_r);
377        return *this;
378    }
379
380    const sc_concatref &
381    operator = (const char *v_p)
382    {
383        sc_unsigned v(m_len);
384        v = v_p;
385        m_right_p->concat_set(v, 0);
386        m_left_p->concat_set(v, m_len_r);
387        return *this;
388    }
389
390    const sc_concatref &
391    operator = (const sc_bv_base &v)
392    {
393        sc_unsigned temp(v.length());
394        temp = v;
395        m_right_p->concat_set(temp, 0);
396        m_left_p->concat_set(temp, m_len_r);
397        return *this;
398    }
399
400    const sc_concatref &
401    operator = (const sc_lv_base &v)
402    {
403        sc_unsigned data(v.length());
404        data = v;
405        m_right_p->concat_set(data, 0);
406        m_left_p->concat_set(data, m_len_r);
407        return *this;
408    }
409
410    // reduce methods
411    bool and_reduce() const { return value().and_reduce(); }
412    bool nand_reduce() const { return value().nand_reduce(); }
413    bool or_reduce() const { return value().or_reduce(); }
414    bool nor_reduce() const { return value().nor_reduce(); }
415    bool xor_reduce() const { return value().xor_reduce(); }
416    bool xnor_reduce() const { return value().xnor_reduce(); }
417
418    // other methods
419    void print(::std::ostream &os=::std::cout) const { os << this->value(); }
420
421    void
422    scan(::std::istream &is)
423    {
424        std::string s;
425        is >> s;
426        *this = s.c_str();
427    }
428
429  public:
430    // Pool of temporary objects.
431    static sc_core::sc_vpool<sc_concatref> m_pool;
432
433  public:
434    enum concat_flags {
435        cf_none = 0,        // Normal value.
436        cf_xz_present = 1   // X and/or Z values present.
437    };
438
439  protected:
440    sc_value_base *m_left_p;  // Left hand operand of concatenation.
441    sc_value_base *m_right_p; // Right hand operand of concatenation.
442    int m_len;                // Length of concatenation.
443    int m_len_r;              // Length of m_rightt_p.
444    concat_flags m_flags;     // Value is read only.
445
446  private:
447    sc_concatref(const sc_concatref &);
448    sc_concatref() : m_left_p(0), m_right_p(0), m_len(0), m_len_r(0), m_flags()
449    {}
450};
451
452// functional notation for the reduce methods
453inline bool and_reduce(const sc_concatref &a) { return a.and_reduce(); }
454inline bool nand_reduce(const sc_concatref &a) { return a.nand_reduce(); }
455inline bool or_reduce(const sc_concatref &a) { return a.or_reduce(); }
456inline bool nor_reduce(const sc_concatref &a) { return a.nor_reduce(); }
457inline bool xor_reduce(const sc_concatref &a) { return a.xor_reduce(); }
458inline bool xnor_reduce(const sc_concatref &a) { return a.xnor_reduce(); }
459
460// SHIFT OPERATORS FOR sc_concatref OBJECT INSTANCES:
461//
462// Because sc_concatref has implicit casts to both uint64 and sc_unsigned
463// it is necessary to disambiguate the use of the shift operators. We do
464// this in favor of sc_unsigned so that precision is not lost. To get an
465// integer-based result use a cast to uint64 before performing the shift.
466
467inline const sc_unsigned
468operator << (const sc_concatref &target, uint64 shift)
469{
470    return target.value() << (int)shift;
471}
472
473inline const sc_unsigned
474operator << (const sc_concatref &target, int64 shift)
475{
476    return target.value() << (int)shift;
477}
478
479inline const sc_unsigned
480operator << (const sc_concatref &target, unsigned long shift)
481{
482    return target.value() << (int)shift;
483}
484
485inline const sc_unsigned
486operator << (const sc_concatref &target, int shift)
487{
488    return target.value() << shift;
489}
490
491inline const sc_unsigned
492operator << (const sc_concatref &target, unsigned int shift)
493{
494    return target.value() << (int)shift;
495}
496
497inline const sc_unsigned
498operator << (const sc_concatref &target, long shift)
499{
500    return target.value() << (int)shift;
501}
502
503inline const sc_unsigned
504operator >> (const sc_concatref &target, uint64 shift)
505{
506    return target.value() >> (int)shift;
507}
508
509inline const sc_unsigned
510operator >> (const sc_concatref &target, int64 shift)
511{
512    return target.value() >> (int)shift;
513}
514
515inline const sc_unsigned
516operator >> (const sc_concatref &target, unsigned long shift)
517{
518    return target.value() >> (int)shift;
519}
520
521inline const sc_unsigned
522operator >> (const sc_concatref &target, int shift)
523{
524    return target.value() >> shift;
525}
526
527inline const sc_unsigned
528operator >> (const sc_concatref &target, unsigned int shift)
529{
530    return target.value() >> (int)shift;
531}
532
533inline const sc_unsigned
534operator >> (const sc_concatref &target, long shift)
535{
536    return target.value() >> (int)shift;
537}
538
539// STREAM OPERATORS FOR sc_concatref OBJECT INSTANCES:
540inline ::std::ostream &
541operator << (::std::ostream &os, const sc_concatref &v)
542{
543    return os << v.value();
544}
545
546inline ::std::istream &
547operator >> (::std::istream &is, sc_concatref &a)
548{
549    sc_unsigned temp(a.concat_length(0));
550    temp.scan(is);
551    a = temp;
552    return is;
553}
554
555
556// ----------------------------------------------------------------------------
557//  CLASS TEMPLATE : sc_concat_bool
558//
559//  Proxy class for read-only boolean values in concatenations.
560// ----------------------------------------------------------------------------
561
562class sc_concat_bool : public sc_value_base
563{
564  protected:
565    static sc_core::sc_vpool<sc_concat_bool> m_pool; // Temporaries pool.
566    bool m_value;                                    // Value for this obj.
567
568  public:
569    // constructor:
570    sc_concat_bool() : sc_value_base(), m_value() {}
571
572    // destructor:
573    virtual ~sc_concat_bool() { }
574
575    // allocation of temporary object:
576    static inline sc_concat_bool *
577    allocate(bool v)
578    {
579        sc_concat_bool *result_p = m_pool.allocate();
580        result_p->m_value = v;
581        return result_p;
582    }
583
584    // concatenation:
585    virtual int
586    concat_length(bool *xz_present_p) const
587    {
588        if (xz_present_p)
589            *xz_present_p = false;
590        return 1;
591    }
592
593    virtual bool
594    concat_get_ctrl(sc_digit *dst_p, int low_i) const
595    {
596        int bit = 1 << (low_i % BITS_PER_DIGIT);
597        int word_i = low_i / BITS_PER_DIGIT;
598        dst_p[word_i] &= ~bit;
599        return false;
600    }
601
602    virtual bool
603    concat_get_data(sc_digit *dst_p, int low_i) const
604    {
605        int bit = 1 << (low_i % BITS_PER_DIGIT);
606        int word_i = low_i / BITS_PER_DIGIT;
607        if (m_value)
608            dst_p[word_i] |= bit;
609        else
610            dst_p[word_i] &= ~bit;
611        return m_value;
612    }
613
614    virtual uint64
615    concat_get_uint64() const
616    {
617        return m_value ? 1 : 0;
618    }
619};
620
621
622// ----------------------------------------------------------------------------
623// ARITHMETIC AND LOGIC OPERATORS FOR sc_concatref
624// ----------------------------------------------------------------------------
625
626#define SC_CONCAT_OP_TYPE(RESULT, OP, OTHER_TYPE) \
627    inline RESULT \
628    operator OP (const sc_concatref &a, OTHER_TYPE b) \
629    { \
630        return a.value() OP b; \
631    } \
632    inline RESULT \
633    operator OP (OTHER_TYPE a, const sc_concatref &b) \
634    { \
635        return a OP b.value(); \
636    }
637
638
639#define SC_CONCAT_OP(RESULT, OP) \
640    inline RESULT \
641    operator OP (const sc_concatref &a, const sc_concatref &b) \
642    { \
643        return a.value() OP b.value(); \
644    }  \
645    SC_CONCAT_OP_TYPE(const sc_signed, OP, int) \
646    SC_CONCAT_OP_TYPE(const sc_signed, OP, long) \
647    SC_CONCAT_OP_TYPE(const sc_signed, OP, int64) \
648    SC_CONCAT_OP_TYPE(RESULT, OP, unsigned int) \
649    SC_CONCAT_OP_TYPE(RESULT, OP, unsigned long) \
650    SC_CONCAT_OP_TYPE(RESULT, OP, uint64) \
651    SC_CONCAT_OP_TYPE(const sc_signed, OP, const sc_int_base &) \
652    SC_CONCAT_OP_TYPE(RESULT, OP, const sc_uint_base &) \
653    SC_CONCAT_OP_TYPE(const sc_signed, OP, const sc_signed &) \
654    SC_CONCAT_OP_TYPE(RESULT, OP, const sc_unsigned &) \
655    inline RESULT \
656    operator OP (const sc_concatref &a, bool b) \
657    { \
658        return a.value() OP (int)b; \
659    } \
660    inline RESULT \
661    operator OP (bool a, const sc_concatref &b) \
662    { \
663        return (int)a OP b.value(); \
664    }
665
666#define SC_CONCAT_BOOL_OP(OP) \
667    inline bool \
668    operator OP (const sc_concatref &a, const sc_concatref &b) \
669    { \
670        return a.value() OP b.value(); \
671    }  \
672    SC_CONCAT_OP_TYPE(bool, OP, int) \
673    SC_CONCAT_OP_TYPE(bool, OP, long) \
674    SC_CONCAT_OP_TYPE(bool, OP, int64) \
675    SC_CONCAT_OP_TYPE(bool, OP, unsigned int) \
676    SC_CONCAT_OP_TYPE(bool, OP, unsigned long) \
677    SC_CONCAT_OP_TYPE(bool, OP, uint64) \
678    SC_CONCAT_OP_TYPE(bool, OP, const sc_int_base &) \
679    SC_CONCAT_OP_TYPE(bool, OP, const sc_uint_base &) \
680    SC_CONCAT_OP_TYPE(bool, OP, const sc_signed &) \
681    SC_CONCAT_OP_TYPE(bool, OP, const sc_unsigned &) \
682    inline bool \
683    operator OP (const sc_concatref &a, bool b) \
684    { \
685        return a.value() OP (int)b; \
686    } \
687    inline bool \
688    operator OP (bool a, const sc_concatref &b) \
689    { \
690        return (int)a OP b.value(); \
691    }
692
693SC_CONCAT_OP(const sc_unsigned, +)
694SC_CONCAT_OP(const sc_signed, -)
695SC_CONCAT_OP(const sc_unsigned, *)
696SC_CONCAT_OP(const sc_unsigned, /)
697SC_CONCAT_OP(const sc_unsigned, %)
698SC_CONCAT_OP(const sc_unsigned, &)
699SC_CONCAT_OP(const sc_unsigned, |)
700SC_CONCAT_OP(const sc_unsigned, ^)
701SC_CONCAT_BOOL_OP(==)
702SC_CONCAT_BOOL_OP(<=)
703SC_CONCAT_BOOL_OP(>=)
704SC_CONCAT_BOOL_OP(!=)
705SC_CONCAT_BOOL_OP(>)
706SC_CONCAT_BOOL_OP(<)
707
708#undef SC_CONCAT_OP
709#undef SC_CONCAT_OP_TYPE
710
711
712// ----------------------------------------------------------------------------
713// CONCATENATION FUNCTION AND OPERATOR FOR STANDARD SYSTEM C DATA TYPES:
714// ----------------------------------------------------------------------------
715
716inline sc_dt::sc_concatref &
717concat(sc_dt::sc_value_base &a, sc_dt::sc_value_base &b)
718{
719    sc_dt::sc_concatref *result_p; // Proxy for the concatenation.
720
721    result_p = sc_dt::sc_concatref::m_pool.allocate();
722    result_p->initialize(a, b);
723    return *result_p;
724}
725
726inline const sc_dt::sc_concatref &
727concat(const sc_dt::sc_value_base &a, const sc_dt::sc_value_base &b)
728{
729    sc_dt::sc_concatref *result_p; // Proxy for the concatenation.
730
731    result_p = sc_dt::sc_concatref::m_pool.allocate();
732    result_p->initialize(a, b);
733    return *result_p;
734}
735
736inline const sc_dt::sc_concatref &
737concat(const sc_dt::sc_value_base &a, bool b)
738{
739    const sc_dt::sc_concat_bool *b_p; // Proxy for boolean value.
740    sc_dt::sc_concatref *result_p; // Proxy for the concatenation.
741
742    b_p = sc_dt::sc_concat_bool::allocate(b);
743    result_p = sc_dt::sc_concatref::m_pool.allocate();
744    result_p->initialize(a, *b_p);
745    return *result_p;
746}
747
748inline const sc_dt::sc_concatref &
749concat(bool a, const sc_dt::sc_value_base &b)
750{
751    const sc_dt::sc_concat_bool *a_p; // Proxy for boolean value.
752    sc_dt::sc_concatref *result_p; // Proxy for the concatenation.
753
754    a_p = sc_dt::sc_concat_bool::allocate(a);
755    result_p = sc_dt::sc_concatref::m_pool.allocate();
756    result_p->initialize(*a_p, b);
757    return *result_p;
758}
759
760inline sc_dt::sc_concatref &
761operator , (sc_dt::sc_value_base &a, sc_dt::sc_value_base &b)
762{
763    sc_dt::sc_concatref *result_p; // Proxy for the concatenation.
764
765    result_p = sc_dt::sc_concatref::m_pool.allocate();
766    result_p->initialize(a, b);
767    return *result_p;
768}
769
770inline const sc_dt::sc_concatref &
771operator , (const sc_dt::sc_value_base &a, const sc_dt::sc_value_base &b)
772{
773    sc_dt::sc_concatref *result_p; // Proxy for the concatenation.
774
775    result_p = sc_dt::sc_concatref::m_pool.allocate();
776    result_p->initialize(a, b);
777    return *result_p;
778}
779
780inline const sc_dt::sc_concatref &
781operator , (const sc_dt::sc_value_base &a, bool b)
782{
783    const sc_dt::sc_concat_bool *b_p; // Proxy for boolean value.
784    sc_dt::sc_concatref *result_p; // Proxy for the concatenation.
785
786    b_p = sc_dt::sc_concat_bool::allocate(b);
787    result_p = sc_dt::sc_concatref::m_pool.allocate();
788    result_p->initialize(a, *b_p);
789    return *result_p;
790}
791
792inline const sc_dt::sc_concatref &
793operator , (bool a, const sc_dt::sc_value_base &b)
794{
795    const sc_dt::sc_concat_bool *a_p; // Proxy for boolean value.
796    sc_dt::sc_concatref *result_p; // Proxy for the concatenation.
797
798    a_p = sc_dt::sc_concat_bool::allocate(a);
799    result_p = sc_dt::sc_concatref::m_pool.allocate();
800    result_p->initialize(*a_p, b);
801    return *result_p;
802}
803
804} // namespace sc_dt
805
806#endif //  __SYSTEMC_EXT_DT_MISC_SC_CONCATREF_HH__
807