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  scfx_mant.h -
23
24  Original Author: Robert Graulich, Synopsys, Inc.
25                   Martin Janssen,  Synopsys, Inc.
26
27 *****************************************************************************/
28
29/*****************************************************************************
30
31  MODIFICATION LOG - modifiers, enter your name, affiliation, date and
32  changes you are making here.
33
34      Name, Affiliation, Date:
35  Description of Modification:
36
37 *****************************************************************************/
38
39// $Log: scfx_mant.h,v $
40// Revision 1.2  2011/08/24 22:05:43  acg
41//  Torsten Maehne: initialization changes to remove warnings.
42//
43// Revision 1.1.1.1  2006/12/15 20:20:04  acg
44// SystemC 2.3
45//
46// Revision 1.3  2006/01/13 18:53:58  acg
47// Andy Goodrich: added $Log command so that CVS comments are reproduced in
48// the source.
49//
50
51#ifndef SCFX_MANT_H
52#define SCFX_MANT_H
53
54
55#include "sysc/datatypes/fx/scfx_ieee.h"
56#include "sysc/datatypes/fx/scfx_utils.h"
57#include "sysc/kernel/sc_macros.h"
58
59
60namespace sc_dt
61{
62
63// classes defined in this module
64class scfx_mant;
65class scfx_mant_ref;
66
67
68typedef unsigned int  word;       // Using int because of 64-bit machines.
69typedef unsigned short half_word;
70
71
72// ----------------------------------------------------------------------------
73//  CLASS : scfx_mant
74//
75//  Mantissa class.
76// ----------------------------------------------------------------------------
77
78class scfx_mant
79{
80
81    word* m_array;
82    int   m_size;
83
84public:
85
86    explicit scfx_mant( std::size_t );
87             scfx_mant( const scfx_mant& );
88
89    scfx_mant& operator = ( const scfx_mant& );
90
91    ~scfx_mant();
92
93    void clear();
94
95    void resize_to( int, int = 0 );
96
97    int size() const;
98
99    word  operator [] ( int ) const;
100    word& operator [] ( int );
101
102    half_word  half_at( int ) const;
103    half_word& half_at( int );
104
105    half_word* half_addr( int = 0 ) const;
106
107private:
108
109    static word* alloc( std::size_t );
110    static void free( word*, std::size_t );
111
112    static word* alloc_word( std::size_t size );
113    static void free_word( word* array, std::size_t size );
114
115};
116
117
118// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
119
120inline
121int
122scfx_mant::size() const
123{
124    return m_size;
125}
126
127
128inline
129word*
130scfx_mant::alloc( std::size_t size )
131{
132#if defined( SC_BIG_ENDIAN )
133    return alloc_word( size ) + ( size - 1 );
134#elif defined( SC_LITTLE_ENDIAN )
135    return alloc_word( size );
136#endif
137}
138
139inline
140void
141scfx_mant::free( word* mant, std::size_t size )
142{
143#if defined( SC_BIG_ENDIAN )
144    free_word( mant - ( size - 1 ), size );
145#elif defined( SC_LITTLE_ENDIAN )
146    free_word( mant, size );
147#endif
148}
149
150inline
151word
152scfx_mant::operator[]( int i ) const
153{
154    SC_ASSERT_( i >= 0 && i < m_size, "mantissa index out of range" );
155#if defined( SC_BIG_ENDIAN )
156    return m_array[-i];
157#elif defined( SC_LITTLE_ENDIAN )
158    return m_array[i];
159#endif
160}
161
162inline
163word&
164scfx_mant::operator[]( int i )
165{
166    SC_ASSERT_( i >= 0 && i < m_size, "mantissa index out of range" );
167#if defined( SC_BIG_ENDIAN )
168    return m_array[-i];
169#elif defined( SC_LITTLE_ENDIAN )
170    return m_array[i];
171#endif
172}
173
174inline
175scfx_mant::scfx_mant( std::size_t size )
176: m_array(0), m_size(size)
177{
178    m_array = alloc( size );
179}
180
181inline
182scfx_mant::scfx_mant( const scfx_mant& rhs )
183: m_array(0), m_size(rhs.m_size)
184{
185    m_array = alloc( m_size );
186    for( int i = 0; i < m_size; i ++ )
187    {
188        (*this)[i] = rhs[i];
189    }
190}
191
192inline
193scfx_mant&
194scfx_mant::operator = ( const scfx_mant& rhs )
195{
196    if( &rhs != this )
197    {
198        if( m_size != rhs.m_size )
199	{
200	    free( m_array, m_size );
201	    m_array = alloc( m_size = rhs.m_size );
202	}
203
204	for( int i = 0; i < m_size; i ++ )
205	{
206	    (*this)[i] = rhs[i];
207	}
208    }
209    return *this;
210}
211
212inline
213scfx_mant::~scfx_mant()
214{
215    if( m_array != 0 )
216    {
217        free( m_array, m_size );
218    }
219}
220
221inline
222void
223scfx_mant::clear()
224{
225    for( int i = 0; i < m_size; i ++ )
226    {
227        (*this)[i] = 0;
228    }
229}
230
231inline
232void
233scfx_mant::resize_to( int size, int restore )
234{
235    if( size == m_size )
236    {
237        return;
238    }
239
240    if( ! m_array )
241    {
242        m_array = alloc( m_size = size );
243    }
244    else
245    {
246        word* p = alloc( size );
247
248	if( restore )
249	{
250	    int end = sc_min( size, m_size );
251	    if( restore == 1 )		// msb resized -> align at 0
252	    {
253	        for( int i = 0; i < size; i ++ )
254		{
255		    if( i < end )
256		    {
257#if defined( SC_BIG_ENDIAN )
258		        p[-i] = m_array[-i];
259#elif defined( SC_LITTLE_ENDIAN )
260			p[i] = m_array[i];
261#endif
262		    }
263		    else
264		    {
265#if defined( SC_BIG_ENDIAN )
266		        p[-i] = 0;
267#elif defined( SC_LITTLE_ENDIAN )
268			p[i] = 0;
269#endif
270		    }
271		}
272	    }
273	    else			// lsb resized -> align at size-1
274	    {
275	        for( int i = 0; i < size; i ++ )
276		{
277		    if( i < end )
278		    {
279#if defined( SC_BIG_ENDIAN )
280		        p[-size+1+i] = m_array[-m_size+1+i];
281#elif defined( SC_LITTLE_ENDIAN )
282			p[size-1-i] = m_array[m_size-1-i];
283#endif
284		    }
285		    else
286		    {
287#if defined( SC_BIG_ENDIAN )
288		        p[-size+1+i] = 0;
289#elif defined( SC_LITTLE_ENDIAN )
290			p[size-1-i] = 0;
291#endif
292		    }
293		}
294	    }
295	}
296
297	free( m_array, m_size );
298	m_array = p;
299	m_size = size;
300    }
301}
302
303inline
304half_word
305scfx_mant::half_at( int i ) const
306{
307    SC_ASSERT_( ( i >> 1 ) >= 0 && ( i >> 1 ) < m_size,
308		"mantissa index out of range" );
309#if defined( SC_BIG_ENDIAN )
310    return reinterpret_cast<half_word*>( m_array )[-i];
311#elif defined( SC_LITTLE_ENDIAN )
312    return reinterpret_cast<half_word*>( m_array )[i];
313#endif
314}
315
316inline
317half_word&
318scfx_mant::half_at( int i )
319{
320    SC_ASSERT_( ( i >> 1 ) >= 0 && ( i >> 1 ) < m_size,
321		"mantissa index out of range" );
322#if defined( SC_BIG_ENDIAN )
323    return reinterpret_cast<half_word*>( m_array )[-i];
324#elif defined( SC_LITTLE_ENDIAN )
325    return reinterpret_cast<half_word*>( m_array )[i];
326#endif
327}
328
329inline
330half_word*
331scfx_mant::half_addr( int i ) const
332{
333    SC_ASSERT_( i >= 0 && i < m_size, "mantissa index out of range" );
334#if defined( SC_BIG_ENDIAN )
335    return reinterpret_cast<half_word*>( m_array - i ) + 1;
336#elif defined( SC_LITTLE_ENDIAN )
337    return reinterpret_cast<half_word*>( m_array + i );
338#endif
339}
340
341
342// ----------------------------------------------------------------------------
343//  one's complement of a mantissa
344// ----------------------------------------------------------------------------
345
346inline
347void
348complement( scfx_mant& target, const scfx_mant& source, int size )
349{
350    for( int i = 0; i < size; i ++ )
351    {
352        target[i] = ~source[i];
353    }
354}
355
356
357// ----------------------------------------------------------------------------
358//  increment mantissa
359// ----------------------------------------------------------------------------
360
361inline
362void
363inc( scfx_mant& mant )
364{
365    for( int i = 0; i < mant.size(); i ++ )
366    {
367        if( ++ mant[i] )
368	{
369	    break;
370	}
371    }
372}
373
374
375// ----------------------------------------------------------------------------
376//  CLASS : scfx_mant_ref
377//
378//  Mantissa reference class.
379// ----------------------------------------------------------------------------
380
381class scfx_mant_ref
382{
383
384    scfx_mant* m_mant;
385    bool       m_not_const;
386
387public:
388
389    scfx_mant_ref();
390    scfx_mant_ref( const scfx_mant& );
391    scfx_mant_ref( scfx_mant* );
392
393    scfx_mant_ref& operator = ( const scfx_mant& );
394    scfx_mant_ref& operator = ( scfx_mant* );
395
396    ~scfx_mant_ref();
397
398    operator scfx_mant&();
399
400    word operator [] ( int );
401
402private:
403
404    void remove_it();
405
406    scfx_mant_ref( const scfx_mant_ref& );
407    scfx_mant_ref& operator = ( const scfx_mant_ref& );
408
409    void* operator new( std::size_t sz ) { return ::operator new( sz ); }
410
411};
412
413
414// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
415
416inline
417void
418scfx_mant_ref::remove_it()
419{
420    if( m_not_const )
421    {
422        delete m_mant;
423    }
424}
425
426inline
427scfx_mant_ref::scfx_mant_ref()
428: m_mant( 0 ), m_not_const( false )
429{}
430
431inline
432scfx_mant_ref::scfx_mant_ref( const scfx_mant& mant )
433: m_mant( const_cast<scfx_mant*>( &mant ) ), m_not_const( false )
434{}
435
436inline
437scfx_mant_ref::scfx_mant_ref( scfx_mant* mant )
438: m_mant( mant ), m_not_const( true )
439{}
440
441inline
442scfx_mant_ref&
443scfx_mant_ref::operator = ( const scfx_mant& mant )
444{
445    remove_it();
446
447    m_mant = const_cast<scfx_mant*>( &mant );
448    m_not_const = false;
449
450    return *this;
451}
452
453inline
454scfx_mant_ref&
455scfx_mant_ref::operator = ( scfx_mant* mant )
456{
457    remove_it();
458
459    m_mant = mant;
460    m_not_const = true;
461
462    return *this;
463}
464
465inline
466scfx_mant_ref::~scfx_mant_ref()
467{
468    remove_it();
469}
470
471inline
472scfx_mant_ref::operator scfx_mant&()
473{
474    // SC_ASSERT_( m_not_const, "not allowed to modify mant" );
475    return *m_mant;
476}
477
478inline
479word
480scfx_mant_ref::operator [] ( int i )
481{
482    return (*m_mant)[i];
483}
484
485} // namespace sc_dt
486
487
488#endif
489
490// Taf!
491