scfx_mant.hh revision 12853
16145SN/A/*****************************************************************************
26145SN/A
36145SN/A  Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
46145SN/A  more contributor license agreements.  See the NOTICE file distributed
56145SN/A  with this work for additional information regarding copyright ownership.
66145SN/A  Accellera licenses this file to you under the Apache License, Version 2.0
76145SN/A  (the "License"); you may not use this file except in compliance with the
86145SN/A  License.  You may obtain a copy of the License at
96145SN/A
106145SN/A    http://www.apache.org/licenses/LICENSE-2.0
116145SN/A
126145SN/A  Unless required by applicable law or agreed to in writing, software
136145SN/A  distributed under the License is distributed on an "AS IS" BASIS,
146145SN/A  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
156145SN/A  implied.  See the License for the specific language governing
166145SN/A  permissions and limitations under the License.
176145SN/A
186145SN/A *****************************************************************************/
196145SN/A
206145SN/A/*****************************************************************************
216145SN/A
226145SN/A  scfx_mant.h -
236145SN/A
246145SN/A  Original Author: Robert Graulich, Synopsys, Inc.
256145SN/A                   Martin Janssen,  Synopsys, Inc.
266145SN/A
276145SN/A *****************************************************************************/
286145SN/A
2910441Snilay@cs.wisc.edu/*****************************************************************************
3010441Snilay@cs.wisc.edu
316145SN/A  MODIFICATION LOG - modifiers, enter your name, affiliation, date and
327055SN/A  changes you are making here.
337055SN/A
347455SN/A      Name, Affiliation, Date:
356154SN/A  Description of Modification:
366145SN/A
376145SN/A *****************************************************************************/
387039SN/A
397039SN/A// $Log: scfx_mant.h,v $
407039SN/A// Revision 1.2  2011/08/24 22:05:43  acg
417039SN/A//  Torsten Maehne: initialization changes to remove warnings.
427039SN/A//
437039SN/A// Revision 1.1.1.1  2006/12/15 20:20:04  acg
447039SN/A// SystemC 2.3
456145SN/A//
467039SN/A// Revision 1.3  2006/01/13 18:53:58  acg
477039SN/A// Andy Goodrich: added $Log command so that CVS comments are reproduced in
487039SN/A// the source.
497039SN/A//
507039SN/A
517039SN/A#ifndef __SYSTEMC_EXT_DT_FX_SCFX_MANT_HH__
527039SN/A#define __SYSTEMC_EXT_DT_FX_SCFX_MANT_HH__
537039SN/A
546145SN/A#include "../../utils/endian.hh"
557839SN/A#include "../../utils/functions.hh"
566145SN/A#include "scfx_ieee.hh"
577039SN/A#include "scfx_utils.hh"
587055SN/A
596145SN/Anamespace sc_dt
607039SN/A{
617039SN/A
627039SN/A// classes defined in this module
637039SN/Aclass scfx_mant;
646145SN/Aclass scfx_mant_ref;
657039SN/A
667455SN/Atypedef unsigned int word;       // Using int because of 64-bit machines.
676145SN/Atypedef unsigned short half_word;
687039SN/A
697039SN/A// ----------------------------------------------------------------------------
706145SN/A//  CLASS : scfx_mant
716145SN/A//
726145SN/A//  Mantissa class.
737055SN/A// ----------------------------------------------------------------------------
747055SN/A
756145SN/Aclass scfx_mant
767039SN/A{
777055SN/A    word *m_array;
787039SN/A    int m_size;
796145SN/A
806145SN/A  public:
816145SN/A    explicit scfx_mant(std::size_t);
827039SN/A    scfx_mant(const scfx_mant &);
837039SN/A
846145SN/A    scfx_mant &operator = (const scfx_mant &);
857039SN/A
867039SN/A    ~scfx_mant();
877455SN/A
886145SN/A    void clear();
896145SN/A
906145SN/A    void resize_to(int, int=0);
917039SN/A
927039SN/A    int size() const;
936145SN/A
947455SN/A    word operator [] (int) const;
957039SN/A    word &operator [] (int);
967455SN/A
977039SN/A    half_word half_at(int) const;
987039SN/A    half_word &half_at(int);
997039SN/A
1007039SN/A    half_word *half_addr(int=0) const;
1017039SN/A
1027039SN/A  private:
1037455SN/A    static word *alloc(std::size_t);
1047039SN/A    static void free(word *, std::size_t);
1057039SN/A
1066145SN/A    static word *alloc_word(std::size_t size);
1076145SN/A    static void free_word(word *array, std::size_t size);
1086145SN/A};
1096145SN/A
1107839SN/A
1117039SN/A// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
1126145SN/A
1137839SN/Ainline int scfx_mant::size() const { return m_size; }
1147839SN/A
1156145SN/Ainline word *
1166145SN/Ascfx_mant::alloc(std::size_t size)
1176145SN/A{
1186145SN/A#if defined(SC_BOOST_BIG_ENDIAN )
1197039SN/A    return alloc_word(size) + (size - 1);
1207055SN/A#elif defined(SC_BOOST_LITTLE_ENDIAN)
1216145SN/A    return alloc_word(size);
1226145SN/A#endif
1236145SN/A}
12410441Snilay@cs.wisc.edu
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