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 SC_CONCATREF_H
78#define SC_CONCATREF_H
79
80#include "sysc/kernel/sc_object.h"
81#include "sysc/datatypes/misc/sc_value_base.h"
82#include "sysc/utils/sc_temporary.h"
83#include "sysc/datatypes/bit/sc_bv.h"
84#include "sysc/datatypes/bit/sc_lv.h"
85#include "sysc/datatypes/int/sc_int_base.h"
86#include "sysc/datatypes/int/sc_uint_base.h"
87#include "sysc/datatypes/int/sc_signed.h"
88#include "sysc/datatypes/int/sc_unsigned.h"
89
90namespace sc_core {
91    extern sc_byte_heap sc_temp_heap; // Temporary storage.
92} // namespace sc_core
93
94namespace sc_dt
95{
96
97// ----------------------------------------------------------------------------
98//  CLASS TEMPLATE : sc_concatref
99//
100//  Proxy class for sized bit concatenation.
101// ----------------------------------------------------------------------------
102
103class sc_concatref : public sc_generic_base<sc_concatref>, public sc_value_base
104{
105public:
106    friend class sc_core::sc_vpool<sc_concatref>;
107
108    inline void initialize(
109        sc_value_base& left, sc_value_base& right )
110        {
111            bool left_xz;   // True if x's and/or z's found in left.
112            bool right_xz;  // True if x's and/or z's found in right.
113
114            m_left_p = (sc_value_base*)&left;
115            m_right_p = (sc_value_base*)&right;
116            m_len_r = right.concat_length(&right_xz);
117            m_len = left.concat_length(&left_xz) + m_len_r;
118            m_flags = ( left_xz || right_xz ) ? cf_xz_present : cf_none;
119        }
120
121
122    inline void initialize(
123        const sc_value_base& left, const sc_value_base& right )
124        {
125            bool left_xz;   // True if x's and/or z's found in left.
126            bool right_xz;  // True if x's and/or z's found in right.
127
128            m_left_p = (sc_value_base*)&left;
129            m_right_p = (sc_value_base*)&right;
130            m_len_r = right.concat_length(&right_xz);
131            m_len = left.concat_length(&left_xz) + m_len_r;
132            m_flags = ( left_xz || right_xz ) ? cf_xz_present : cf_none;
133        }
134
135    // destructor
136
137    virtual ~sc_concatref()
138    {}
139
140
141    // capacity
142
143    unsigned int length() const
144        { return m_len; }
145
146#ifdef SC_DT_DEPRECATED
147    int bitwidth() const
148        { return length(); }
149#endif
150
151    // concatenation
152
153    virtual int concat_length( bool* xz_present_p ) const
154    {
155        if ( xz_present_p )
156            *xz_present_p = m_flags & cf_xz_present ? true : false;
157        return m_len;
158    }
159
160    virtual void concat_clear_data( bool to_ones )
161    {
162        m_left_p->concat_clear_data(to_ones);
163        m_right_p->concat_clear_data(to_ones);
164    }
165
166    virtual bool concat_get_ctrl( sc_digit* dst_p, int low_i ) const
167    {
168        bool rnz = m_right_p->concat_get_ctrl( dst_p, low_i );
169        bool lnz = m_left_p->concat_get_ctrl( dst_p, low_i+m_len_r );
170        return rnz || lnz;
171    }
172
173    virtual bool concat_get_data( sc_digit* dst_p, int low_i ) const
174    {
175        bool rnz = m_right_p->concat_get_data( dst_p, low_i );
176        bool lnz = m_left_p->concat_get_data( dst_p, low_i+m_len_r );
177        return rnz || lnz;
178    }
179
180    virtual uint64 concat_get_uint64() const
181    {
182        if ( m_len_r >= 64 )
183            return m_right_p->concat_get_uint64();
184        else
185        {
186            return (m_left_p->concat_get_uint64() << m_len_r) |
187                m_right_p->concat_get_uint64();
188        }
189    }
190
191    virtual void concat_set( int64 src, int low_i )
192    {
193        m_right_p->concat_set( src, low_i );
194        m_left_p->concat_set( src, low_i+m_len_r);
195    }
196
197    virtual void concat_set( const sc_signed& src, int low_i )
198    {
199        m_right_p->concat_set( src, low_i );
200        m_left_p->concat_set( src, low_i+m_len_r);
201    }
202
203    virtual void concat_set( const sc_unsigned& src, int low_i )
204    {
205        m_right_p->concat_set( src, low_i );
206        m_left_p->concat_set( src, low_i+m_len_r);
207    }
208
209    virtual void concat_set( uint64 src, int low_i )
210    {
211        m_right_p->concat_set( src, low_i );
212        m_left_p->concat_set( src, low_i+m_len_r);
213    }
214
215
216    // explicit conversions
217
218    uint64 to_uint64() const
219        {
220            uint64 mask;
221            uint64 result;
222
223            result = m_right_p->concat_get_uint64();
224            if ( m_len_r < 64 )
225            {
226                mask = (uint64)~0;
227                result = (m_left_p->concat_get_uint64() << m_len_r) |
228                            (result & ~(mask << m_len_r));
229            }
230            if ( m_len < 64 )
231            {
232                mask = (uint64)~0;
233                result = result & ~(mask << m_len);
234            }
235            return result;
236        }
237
238    const sc_unsigned& value() const
239        {
240            bool           left_non_zero;
241            sc_unsigned*   result_p = sc_unsigned::m_pool.allocate();
242            bool           right_non_zero;
243
244            result_p->nbits = result_p->num_bits(m_len);
245	    result_p->ndigits = DIV_CEIL(result_p->nbits);
246            result_p->digit = (sc_digit*)sc_core::sc_temp_heap.allocate(
247                sizeof(sc_digit)*result_p->ndigits );
248#if defined(_MSC_VER)
249            // workaround spurious initialisation issue on MS Visual C++
250            memset( result_p->digit, 0, sizeof(sc_digit)*result_p->ndigits );
251#else
252            result_p->digit[result_p->ndigits-1] = 0;
253#endif
254            right_non_zero = m_right_p->concat_get_data( result_p->digit, 0 );
255            left_non_zero = m_left_p->concat_get_data(result_p->digit, m_len_r);
256            if ( left_non_zero || right_non_zero )
257                result_p->sgn = SC_POS;
258            else
259                result_p->sgn = SC_ZERO;
260            return *result_p;
261        }
262
263    int64 to_int64() const
264        {
265            return (int64)to_uint64();
266        }
267    int to_int() const
268        { return (int)to_int64(); }
269    unsigned int  to_uint() const
270        { return (unsigned int)to_uint64(); }
271    long to_long() const
272        { return (long)to_int64(); }
273    unsigned long to_ulong() const
274        { return (unsigned long)to_uint64(); }
275    double to_double() const
276        { return value().to_double(); }
277
278    void to_sc_signed( sc_signed& target ) const
279        { target = value(); }
280
281    void to_sc_unsigned( sc_unsigned& target ) const
282        { target = value(); }
283
284    // implicit conversions:
285
286    operator  uint64 () const
287        { return to_uint64(); }
288
289    operator const sc_unsigned& () const
290        { return value(); }
291
292    // unary operators:
293
294    sc_unsigned operator + () const
295        { return value(); }
296
297    sc_signed operator - () const
298        { return -value(); }
299
300    sc_unsigned operator ~ () const
301        { return ~value(); }
302
303    // explicit conversion to character string
304
305    const std::string to_string( sc_numrep numrep = SC_DEC ) const
306        { return value().to_string(numrep); }
307
308    const std::string to_string( sc_numrep numrep, bool w_prefix ) const
309        { return value().to_string(numrep,w_prefix); }
310
311
312
313    // assignments
314
315    inline const sc_concatref& operator = ( int 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& operator = ( long v )
323    {
324        m_right_p->concat_set((int64)v, 0);
325        m_left_p->concat_set((int64)v, m_len_r);
326        return *this;
327    }
328
329    inline const sc_concatref& operator = ( int64 v )
330    {
331        m_right_p->concat_set(v, 0);
332        m_left_p->concat_set(v, m_len_r);
333        return *this;
334    }
335
336    inline const sc_concatref& operator = ( unsigned int v )
337    {
338        m_right_p->concat_set((uint64)v, 0);
339        m_left_p->concat_set((uint64)v, m_len_r);
340        return *this;
341    }
342
343    inline const sc_concatref& operator = ( unsigned long v )
344    {
345        m_right_p->concat_set((uint64)v, 0);
346        m_left_p->concat_set((uint64)v, m_len_r);
347        return *this;
348    }
349
350    inline const sc_concatref& operator = ( uint64 v )
351    {
352        m_right_p->concat_set(v, 0);
353        m_left_p->concat_set(v, m_len_r);
354        return *this;
355    }
356
357    const sc_concatref& operator = ( const sc_concatref& v )
358    {
359        sc_unsigned temp(v.length());
360        temp = v.value();
361        m_right_p->concat_set(temp, 0);
362        m_left_p->concat_set(temp, m_len_r);
363        return *this;
364    }
365
366    const sc_concatref& operator = ( const sc_signed& v )
367    {
368        m_right_p->concat_set(v, 0);
369        m_left_p->concat_set(v, m_len_r);
370        return *this;
371    }
372
373    const sc_concatref& 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& operator = ( const char* v_p )
381    {
382        sc_unsigned v(m_len);
383        v = v_p;
384        m_right_p->concat_set(v, 0);
385        m_left_p->concat_set(v, m_len_r);
386        return *this;
387    }
388
389    const sc_concatref& operator = ( const sc_bv_base& v )
390    {
391        sc_unsigned temp(v.length());
392        temp = v;
393        m_right_p->concat_set(temp, 0);
394        m_left_p->concat_set(temp, m_len_r);
395        return *this;
396    }
397
398    const sc_concatref& operator = ( const sc_lv_base& v )
399    {
400        sc_unsigned data(v.length());
401        data = v;
402        m_right_p->concat_set(data, 0);
403        m_left_p->concat_set(data, m_len_r);
404        return *this;
405    }
406
407
408    // reduce methods
409
410    bool and_reduce() const
411        { return value().and_reduce(); }
412
413    bool nand_reduce() const
414        { return value().nand_reduce(); }
415
416    bool or_reduce() const
417        { return value().or_reduce(); }
418
419    bool nor_reduce() const
420        { return value().nor_reduce(); }
421
422    bool xor_reduce() const
423        { return value().xor_reduce(); }
424
425    bool xnor_reduce() const
426        { return value().xnor_reduce(); }
427
428    // other methods
429
430    void print( ::std::ostream& os = ::std::cout ) const
431        { os << this->value(); }
432
433    void scan( ::std::istream& is )
434    {
435        std::string s;
436        is >> s;
437        *this = s.c_str();
438    }
439
440public:
441    static sc_core::sc_vpool<sc_concatref> m_pool; // Pool of temporary objects.
442
443public:
444    enum concat_flags {
445        cf_none = 0,        // Normal value.
446        cf_xz_present = 1   // X and/or Z values present.
447    };
448
449protected:
450    sc_value_base*  m_left_p;    // Left hand operand of concatenation.
451    sc_value_base*  m_right_p;   // Right hand operand of concatenation.
452    int             m_len;       // Length of concatenation.
453    int             m_len_r;     // Length of m_rightt_p.
454    concat_flags    m_flags;     // Value is read only.
455
456private:
457    sc_concatref(const sc_concatref&);
458    sc_concatref() : m_left_p(0), m_right_p(0), m_len(0), m_len_r(0), m_flags()
459      {}
460};
461
462
463// functional notation for the reduce methods
464
465inline
466bool
467and_reduce( const sc_concatref& a )
468{
469    return a.and_reduce();
470}
471
472inline
473bool
474nand_reduce( const sc_concatref& a )
475{
476    return a.nand_reduce();
477}
478
479inline
480bool
481or_reduce( const sc_concatref& a )
482{
483    return a.or_reduce();
484}
485
486inline
487bool
488nor_reduce( const sc_concatref& a )
489{
490    return a.nor_reduce();
491}
492
493inline
494bool
495xor_reduce( const sc_concatref& a )
496{
497    return a.xor_reduce();
498}
499
500inline
501bool
502xnor_reduce( const sc_concatref& a )
503{
504    return a.xnor_reduce();
505}
506
507
508// SHIFT OPERATORS FOR sc_concatref OBJECT INSTANCES:
509//
510// Because sc_concatref has implicit casts to both uint64 and sc_unsigned
511// it is necessary to disambiguate the use of the shift operators. We do
512// this in favor of sc_unsigned so that precision is not lost. To get an
513// integer-based result use a cast to uint64 before performing the shift.
514
515inline const sc_unsigned operator << (const sc_concatref& target, uint64 shift)
516{
517    return target.value() << (int)shift;
518}
519
520inline const sc_unsigned operator << (const sc_concatref& target, int64 shift)
521{
522    return target.value() << (int)shift;
523}
524
525inline const sc_unsigned operator << (
526    const sc_concatref& target, unsigned long shift )
527{
528    return target.value() << (int)shift;
529}
530
531inline const sc_unsigned operator << (
532    const sc_concatref& target, int shift )
533{
534    return target.value() << shift;
535}
536
537inline const sc_unsigned operator << (
538    const sc_concatref& target, unsigned int shift )
539{
540    return target.value() << (int)shift;
541}
542
543inline const sc_unsigned operator << ( const sc_concatref& target, long shift )
544{
545    return target.value() << (int)shift;
546}
547
548inline const sc_unsigned operator >> (const sc_concatref& target, uint64 shift)
549{
550    return target.value() >> (int)shift;
551}
552
553inline const sc_unsigned operator >> (const sc_concatref& target, int64 shift)
554{
555    return target.value() >> (int)shift;
556}
557
558inline const sc_unsigned operator >> (
559    const sc_concatref& target, unsigned long shift )
560{
561    return target.value() >> (int)shift;
562}
563
564inline const sc_unsigned operator >> (
565    const sc_concatref& target, int shift )
566{
567    return target.value() >> shift;
568}
569
570inline const sc_unsigned operator >> (
571    const sc_concatref& target, unsigned int shift )
572{
573    return target.value() >> (int)shift;
574}
575
576inline const sc_unsigned operator >> ( const sc_concatref& target, long shift )
577{
578    return target.value() >> (int)shift;
579}
580
581
582// STREAM OPERATORS FOR sc_concatref OBJECT INSTANCES:
583
584inline
585::std::ostream&
586operator << ( ::std::ostream& os, const sc_concatref& v )
587{
588    return os << v.value();
589}
590
591inline
592::std::istream&
593operator >> ( ::std::istream& is, sc_concatref& a )
594{
595    sc_unsigned temp(a.concat_length(0));
596    temp.scan( is );
597    a = temp;
598    return is;
599}
600
601
602// ----------------------------------------------------------------------------
603//  CLASS TEMPLATE : sc_concat_bool
604//
605//  Proxy class for read-only boolean values in concatenations.
606// ----------------------------------------------------------------------------
607
608class sc_concat_bool : public sc_value_base
609{
610  protected:
611    static sc_core::sc_vpool<sc_concat_bool> m_pool;  // Temporaries pool.
612    bool                                     m_value; // Value for this obj.
613
614  public:
615
616    // constructor:
617
618    sc_concat_bool()
619    : sc_value_base(), m_value()
620    {}
621
622    // destructor:
623
624    virtual ~sc_concat_bool()
625        { }
626
627    // allocation of temporary object:
628
629    static inline sc_concat_bool* allocate( bool v )
630    {
631        sc_concat_bool* result_p = m_pool.allocate();
632        result_p->m_value = v;
633        return result_p;
634    }
635
636    // concatenation:
637
638    virtual int concat_length( bool* xz_present_p ) const
639    {
640        if ( xz_present_p ) *xz_present_p = false;
641        return 1;
642    }
643
644    virtual bool concat_get_ctrl( sc_digit* dst_p, int low_i ) const
645    {
646        int bit = 1 << (low_i % BITS_PER_DIGIT);
647        int word_i = low_i / BITS_PER_DIGIT;
648        dst_p[word_i] &= ~bit;
649        return false;
650    }
651
652    virtual bool concat_get_data( sc_digit* dst_p, int low_i ) const
653    {
654        int bit = 1 << (low_i % BITS_PER_DIGIT);
655        int word_i = low_i / BITS_PER_DIGIT;
656        if ( m_value )
657            dst_p[word_i] |= bit;
658        else
659            dst_p[word_i] &= ~bit;
660        return m_value;
661    }
662
663    virtual uint64 concat_get_uint64() const
664    {
665        return m_value ? 1 : 0;
666    }
667};
668
669
670// ----------------------------------------------------------------------------
671// ARITHMETIC AND LOGIC OPERATORS FOR sc_concatref
672// ----------------------------------------------------------------------------
673
674#define SC_CONCAT_OP_TYPE(RESULT,OP,OTHER_TYPE) \
675    inline RESULT operator OP ( const sc_concatref& a, OTHER_TYPE b ) \
676    { \
677        return a.value() OP b; \
678    } \
679    inline RESULT operator OP ( OTHER_TYPE a, const sc_concatref& b ) \
680    { \
681        return a OP b.value(); \
682    }
683
684
685#define SC_CONCAT_OP(RESULT,OP) \
686    inline RESULT operator OP ( const sc_concatref& a, const sc_concatref& b ) \
687    { \
688        return a.value() OP b.value(); \
689    }  \
690    SC_CONCAT_OP_TYPE(const sc_signed,OP,int) \
691    SC_CONCAT_OP_TYPE(const sc_signed,OP,long) \
692    SC_CONCAT_OP_TYPE(const sc_signed,OP,int64) \
693    SC_CONCAT_OP_TYPE(RESULT,OP,unsigned int) \
694    SC_CONCAT_OP_TYPE(RESULT,OP,unsigned long) \
695    SC_CONCAT_OP_TYPE(RESULT,OP,uint64) \
696    SC_CONCAT_OP_TYPE(const sc_signed,OP,const sc_int_base&) \
697    SC_CONCAT_OP_TYPE(RESULT,OP,const sc_uint_base&) \
698    SC_CONCAT_OP_TYPE(const sc_signed,OP,const sc_signed&) \
699    SC_CONCAT_OP_TYPE(RESULT,OP,const sc_unsigned&) \
700    inline RESULT operator OP ( const sc_concatref& a, bool b ) \
701    { \
702        return a.value() OP (int)b; \
703    } \
704    inline RESULT operator OP ( bool a, const sc_concatref& b ) \
705    { \
706        return (int)a OP b.value(); \
707    }
708
709#define SC_CONCAT_BOOL_OP(OP) \
710    inline bool operator OP ( const sc_concatref& a, const sc_concatref& b ) \
711    { \
712        return a.value() OP b.value(); \
713    }  \
714    SC_CONCAT_OP_TYPE(bool,OP,int) \
715    SC_CONCAT_OP_TYPE(bool,OP,long) \
716    SC_CONCAT_OP_TYPE(bool,OP,int64) \
717    SC_CONCAT_OP_TYPE(bool,OP,unsigned int) \
718    SC_CONCAT_OP_TYPE(bool,OP,unsigned long) \
719    SC_CONCAT_OP_TYPE(bool,OP,uint64) \
720    SC_CONCAT_OP_TYPE(bool,OP,const sc_int_base&) \
721    SC_CONCAT_OP_TYPE(bool,OP,const sc_uint_base&) \
722    SC_CONCAT_OP_TYPE(bool,OP,const sc_signed&) \
723    SC_CONCAT_OP_TYPE(bool,OP,const sc_unsigned&) \
724    inline bool operator OP ( const sc_concatref& a, bool b ) \
725    { \
726        return a.value() OP (int)b; \
727    } \
728    inline bool operator OP ( bool a, const sc_concatref& b ) \
729    { \
730        return (int)a OP b.value(); \
731    }
732
733SC_CONCAT_OP(const sc_unsigned,+)
734SC_CONCAT_OP(const sc_signed,-)
735SC_CONCAT_OP(const sc_unsigned,*)
736SC_CONCAT_OP(const sc_unsigned,/)
737SC_CONCAT_OP(const sc_unsigned,%)
738SC_CONCAT_OP(const sc_unsigned,&)
739SC_CONCAT_OP(const sc_unsigned,|)
740SC_CONCAT_OP(const sc_unsigned,^)
741SC_CONCAT_BOOL_OP(==)
742SC_CONCAT_BOOL_OP(<=)
743SC_CONCAT_BOOL_OP(>=)
744SC_CONCAT_BOOL_OP(!=)
745SC_CONCAT_BOOL_OP(>)
746SC_CONCAT_BOOL_OP(<)
747
748#undef SC_CONCAT_OP
749#undef SC_CONCAT_OP_TYPE
750
751
752// ----------------------------------------------------------------------------
753// CONCATENATION FUNCTION AND OPERATOR FOR STANDARD SYSTEM C DATA TYPES:
754// ----------------------------------------------------------------------------
755
756inline sc_dt::sc_concatref& concat(
757    sc_dt::sc_value_base& a, sc_dt::sc_value_base& b)
758{
759    sc_dt::sc_concatref* result_p;     // Proxy for the concatenation.
760
761    result_p = sc_dt::sc_concatref::m_pool.allocate();
762    result_p->initialize( a, b );
763    return *result_p;
764}
765
766inline
767const
768sc_dt::sc_concatref& concat(
769    const sc_dt::sc_value_base& a, const sc_dt::sc_value_base& b)
770{
771    sc_dt::sc_concatref* result_p;     // Proxy for the concatenation.
772
773    result_p = sc_dt::sc_concatref::m_pool.allocate();
774    result_p->initialize( a, b );
775    return *result_p;
776}
777
778inline
779const
780sc_dt::sc_concatref& concat(const sc_dt::sc_value_base& a, bool b)
781{
782    const sc_dt::sc_concat_bool* b_p;        // Proxy for boolean value.
783    sc_dt::sc_concatref*         result_p;   // Proxy for the concatenation.
784
785    b_p = sc_dt::sc_concat_bool::allocate(b);
786    result_p = sc_dt::sc_concatref::m_pool.allocate();
787    result_p->initialize( a, *b_p );
788    return *result_p;
789}
790
791inline
792const
793sc_dt::sc_concatref& concat(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
804inline sc_dt::sc_concatref& operator , (
805    sc_dt::sc_value_base& a, sc_dt::sc_value_base& b)
806{
807    sc_dt::sc_concatref* result_p;     // Proxy for the concatenation.
808
809    result_p = sc_dt::sc_concatref::m_pool.allocate();
810    result_p->initialize( a, b );
811    return *result_p;
812}
813
814inline
815const
816sc_dt::sc_concatref& operator , (
817    const sc_dt::sc_value_base& a, const sc_dt::sc_value_base& b)
818{
819    sc_dt::sc_concatref* result_p;     // Proxy for the concatenation.
820
821    result_p = sc_dt::sc_concatref::m_pool.allocate();
822    result_p->initialize( a, b );
823    return *result_p;
824}
825
826inline
827const
828sc_dt::sc_concatref& operator , (const sc_dt::sc_value_base& a, bool b)
829{
830    const sc_dt::sc_concat_bool* b_p;      // Proxy for boolean value.
831    sc_dt::sc_concatref*         result_p; // Proxy for the concatenation.
832
833    b_p = sc_dt::sc_concat_bool::allocate(b);
834    result_p = sc_dt::sc_concatref::m_pool.allocate();
835    result_p->initialize( a, *b_p );
836    return *result_p;
837}
838
839inline
840const
841sc_dt::sc_concatref& operator , (bool a, const sc_dt::sc_value_base& b)
842{
843    const sc_dt::sc_concat_bool* a_p;      // Proxy for boolean value.
844    sc_dt::sc_concatref*         result_p; // Proxy for the concatenation.
845
846    a_p = sc_dt::sc_concat_bool::allocate(a);
847    result_p = sc_dt::sc_concatref::m_pool.allocate();
848    result_p->initialize( *a_p, b );
849    return *result_p;
850}
851
852} // namespace sc_dt
853
854#endif //  SC_CONCATREF_H
855
856