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 __SYSTEMC_EXT_DT_FX_SCFX_MANT_HH__
52#define __SYSTEMC_EXT_DT_FX_SCFX_MANT_HH__
53
54#include "../../utils/endian.hh"
55#include "../../utils/functions.hh"
56#include "scfx_ieee.hh"
57#include "scfx_utils.hh"
58
59namespace sc_dt
60{
61
62// classes defined in this module
63class scfx_mant;
64class scfx_mant_ref;
65
66typedef unsigned int word;       // Using int because of 64-bit machines.
67typedef unsigned short half_word;
68
69// ----------------------------------------------------------------------------
70//  CLASS : scfx_mant
71//
72//  Mantissa class.
73// ----------------------------------------------------------------------------
74
75class scfx_mant
76{
77    word *m_array;
78    int m_size;
79
80  public:
81    explicit scfx_mant(std::size_t);
82    scfx_mant(const scfx_mant &);
83
84    scfx_mant &operator = (const scfx_mant &);
85
86    ~scfx_mant();
87
88    void clear();
89
90    void resize_to(int, int=0);
91
92    int size() const;
93
94    word operator [] (int) const;
95    word &operator [] (int);
96
97    half_word half_at(int) const;
98    half_word &half_at(int);
99
100    half_word *half_addr(int=0) const;
101
102  private:
103    static word *alloc(std::size_t);
104    static void free(word *, std::size_t);
105
106    static word *alloc_word(std::size_t size);
107    static void free_word(word *array, std::size_t size);
108};
109
110
111// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
112
113inline int scfx_mant::size() const { return m_size; }
114
115inline word *
116scfx_mant::alloc(std::size_t size)
117{
118#if defined(SC_BOOST_BIG_ENDIAN )
119    return alloc_word(size) + (size - 1);
120#elif defined(SC_BOOST_LITTLE_ENDIAN)
121    return alloc_word(size);
122#endif
123}
124
125inline void
126scfx_mant::free(word *mant, std::size_t size)
127{
128#if defined(SC_BOOST_BIG_ENDIAN)
129    free_word(mant - (size - 1), size);
130#elif defined(SC_BOOST_LITTLE_ENDIAN)
131    free_word(mant, size);
132#endif
133}
134
135inline word
136scfx_mant::operator [] (int i) const
137{
138    SC_ASSERT_(i >= 0 && i < m_size, "mantissa index out of range");
139#if defined(SC_BOOST_BIG_ENDIAN)
140    return m_array[-i];
141#elif defined(SC_BOOST_LITTLE_ENDIAN)
142    return m_array[i];
143#endif
144}
145
146inline word &
147scfx_mant::operator [] (int i)
148{
149    SC_ASSERT_(i >= 0 && i < m_size, "mantissa index out of range");
150#if defined(SC_BOOST_BIG_ENDIAN)
151    return m_array[-i];
152#elif defined(SC_BOOST_LITTLE_ENDIAN)
153    return m_array[i];
154#endif
155}
156
157inline scfx_mant::scfx_mant(std::size_t size_) : m_array(0), m_size(size_)
158{
159    m_array = alloc(size_);
160}
161
162inline scfx_mant::scfx_mant(const scfx_mant &rhs) :
163        m_array(0), m_size(rhs.m_size)
164{
165    m_array = alloc(m_size);
166    for (int i = 0; i < m_size; i++) {
167        (*this)[i] = rhs[i];
168    }
169}
170
171inline scfx_mant &
172scfx_mant::operator = (const scfx_mant &rhs)
173{
174    if (&rhs != this) {
175        if (m_size != rhs.m_size) {
176            free(m_array, m_size);
177            m_array = alloc(m_size = rhs.m_size);
178        }
179
180        for (int i = 0; i < m_size; i++) {
181            (*this)[i] = rhs[i];
182        }
183    }
184    return *this;
185}
186
187inline scfx_mant::~scfx_mant()
188{
189    if (m_array != 0) {
190        free(m_array, m_size);
191    }
192}
193
194inline void
195scfx_mant::clear()
196{
197    for (int i = 0; i < m_size; i++) {
198        (*this)[i] = 0;
199    }
200}
201
202inline void
203scfx_mant::resize_to(int size, int restore)
204{
205    if (size == m_size) {
206        return;
207    }
208
209    if (!m_array) {
210        m_array = alloc(m_size = size);
211    } else {
212        word* p = alloc(size);
213
214        if (restore) {
215            int end = sc_min(size, m_size);
216            if (restore == 1) { // msb resized -> align at 0
217                for (int i = 0; i < size; i++) {
218                    if (i < end) {
219#if defined(SC_BOOST_BIG_ENDIAN)
220                        p[-i] = m_array[-i];
221#elif defined(SC_BOOST_LITTLE_ENDIAN)
222                        p[i] = m_array[i];
223#endif
224                    } else {
225#if defined(SC_BOOST_BIG_ENDIAN)
226                        p[-i] = 0;
227#elif defined(SC_BOOST_LITTLE_ENDIAN)
228                        p[i] = 0;
229#endif
230                    }
231                }
232            } else { // lsb resized -> align at size - 1
233                for (int i = 0; i < size; i++) {
234                    if (i < end) {
235#if defined(SC_BOOST_BIG_ENDIAN)
236                        p[-size + 1 + i] = m_array[-m_size + 1 + i];
237#elif defined(SC_BOOST_LITTLE_ENDIAN)
238                        p[size - 1 - i] = m_array[m_size - 1 - i];
239#endif
240                    } else {
241#if defined(SC_BOOST_BIG_ENDIAN)
242                        p[-size + 1 + i] = 0;
243#elif defined(SC_BOOST_LITTLE_ENDIAN)
244                        p[size - 1 - i] = 0;
245#endif
246                    }
247                }
248            }
249        }
250
251        free(m_array, m_size);
252        m_array = p;
253        m_size = size;
254    }
255}
256
257inline half_word
258scfx_mant::half_at(int i) const
259{
260    SC_ASSERT_((i >> 1) >= 0 && (i >> 1) < m_size,
261               "mantissa index out of range");
262#if defined(SC_BOOST_BIG_ENDIAN)
263    return reinterpret_cast<half_word *>(m_array)[-i];
264#elif defined(SC_BOOST_LITTLE_ENDIAN )
265    return reinterpret_cast<half_word *>(m_array)[i];
266#endif
267}
268
269inline half_word &
270scfx_mant::half_at(int i)
271{
272    SC_ASSERT_((i >> 1) >= 0 && (i >> 1) < m_size,
273               "mantissa index out of range" );
274#if defined(SC_BOOST_BIG_ENDIAN)
275    return reinterpret_cast<half_word *>(m_array)[-i];
276#elif defined(SC_BOOST_LITTLE_ENDIAN)
277    return reinterpret_cast<half_word *>(m_array)[i];
278#endif
279}
280
281inline half_word *
282scfx_mant::half_addr(int i) const
283{
284    SC_ASSERT_(i >= 0 && i < m_size, "mantissa index out of range");
285#if defined(SC_BOOST_BIG_ENDIAN)
286    return reinterpret_cast<half_word *>(m_array - i) + 1;
287#elif defined(SC_BOOST_LITTLE_ENDIAN)
288    return reinterpret_cast<half_word *>(m_array + i);
289#endif
290}
291
292// ----------------------------------------------------------------------------
293//  one's complement of a mantissa
294// ----------------------------------------------------------------------------
295
296inline void
297complement(scfx_mant &target, const scfx_mant &source, int size)
298{
299    for (int i = 0; i < size; i++) {
300        target[i] = ~source[i];
301    }
302}
303
304// ----------------------------------------------------------------------------
305//  increment mantissa
306// ----------------------------------------------------------------------------
307
308inline void
309inc(scfx_mant &mant)
310{
311    for (int i = 0; i < mant.size(); i++) {
312        if (++mant[i]) {
313            break;
314        }
315    }
316}
317
318// ----------------------------------------------------------------------------
319//  CLASS : scfx_mant_ref
320//
321//  Mantissa reference class.
322// ----------------------------------------------------------------------------
323
324class scfx_mant_ref
325{
326    scfx_mant *m_mant;
327    bool m_not_const;
328
329  public:
330    scfx_mant_ref();
331    scfx_mant_ref(const scfx_mant &);
332    scfx_mant_ref(scfx_mant *);
333
334    scfx_mant_ref &operator = (const scfx_mant &);
335    scfx_mant_ref &operator = (scfx_mant *);
336
337    ~scfx_mant_ref();
338
339    operator scfx_mant & ();
340
341    word operator [] (int);
342
343  private:
344    void remove_it();
345
346    scfx_mant_ref(const scfx_mant_ref &);
347    scfx_mant_ref &operator = (const scfx_mant_ref &);
348
349    void *operator new(std::size_t sz) { return ::operator new (sz); }
350
351};
352
353// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
354
355inline void
356scfx_mant_ref::remove_it()
357{
358    if (m_not_const) {
359        delete m_mant;
360    }
361}
362
363inline scfx_mant_ref::scfx_mant_ref() : m_mant(0), m_not_const(false) {}
364
365inline scfx_mant_ref::scfx_mant_ref(const scfx_mant &mant) :
366        m_mant(const_cast<scfx_mant *>(& mant)), m_not_const(false)
367{}
368
369inline scfx_mant_ref::scfx_mant_ref(scfx_mant *mant) :
370        m_mant(mant), m_not_const(true)
371{}
372
373inline scfx_mant_ref &
374scfx_mant_ref::operator = (const scfx_mant &mant)
375{
376    remove_it();
377
378    m_mant = const_cast<scfx_mant *>(&mant);
379    m_not_const = false;
380
381    return *this;
382}
383
384inline scfx_mant_ref &
385scfx_mant_ref::operator = (scfx_mant *mant)
386{
387    remove_it();
388
389    m_mant = mant;
390    m_not_const = true;
391
392    return *this;
393}
394
395inline scfx_mant_ref::~scfx_mant_ref()
396{
397    remove_it();
398}
399
400inline scfx_mant_ref::operator scfx_mant & ()
401{
402    // SC_ASSERT_(m_not_const, "not allowed to modify mant");
403    return *m_mant;
404}
405
406inline word
407scfx_mant_ref::operator [] (int i)
408{
409    return (*m_mant)[i];
410}
411
412} // namespace sc_dt
413
414
415#endif // __SYSTEMC_EXT_DT_FX_SCFX_MANT_HH__
416