sc_bv_base.cc revision 13325
16899SN/A/*****************************************************************************
26899SN/A
36899SN/A  Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
46899SN/A  more contributor license agreements.  See the NOTICE file distributed
56899SN/A  with this work for additional information regarding copyright ownership.
66899SN/A  Accellera licenses this file to you under the Apache License, Version 2.0
76899SN/A  (the "License"); you may not use this file except in compliance with the
86899SN/A  License.  You may obtain a copy of the License at
96899SN/A
106899SN/A    http://www.apache.org/licenses/LICENSE-2.0
116899SN/A
126899SN/A  Unless required by applicable law or agreed to in writing, software
136899SN/A  distributed under the License is distributed on an "AS IS" BASIS,
146899SN/A  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
156899SN/A  implied.  See the License for the specific language governing
166899SN/A  permissions and limitations under the License.
176899SN/A
186899SN/A *****************************************************************************/
196899SN/A
206899SN/A/*****************************************************************************
216899SN/A
226899SN/A  sc_bv_base.cpp -- Arbitrary size bit vector class.
236899SN/A
246899SN/A  Original Author: Gene Bushuyev, Synopsys, Inc.
256899SN/A
266899SN/A *****************************************************************************/
276899SN/A
286899SN/A/*****************************************************************************
296899SN/A
307632SBrad.Beckmann@amd.com  MODIFICATION LOG - modifiers, enter your name, affiliation, date and
318232Snate@binkert.org  changes you are making here.
327053SN/A
336899SN/A      Name, Affiliation, Date:
346899SN/A  Description of Modification:
356899SN/A
367053SN/A *****************************************************************************/
377053SN/A
387053SN/A
397053SN/A// $Log: sc_bv_base.cpp,v $
407053SN/A// Revision 1.2  2011/08/24 22:05:40  acg
416899SN/A//  Torsten Maehne: initialization changes to remove warnings.
427053SN/A//
436899SN/A// Revision 1.1.1.1  2006/12/15 20:20:04  acg
447053SN/A// SystemC 2.3
457053SN/A//
467053SN/A// Revision 1.4  2006/04/11 23:12:26  acg
477053SN/A//   Andy Goodrich: Fixed bug in parsing of extended string constants like
488164Snilay@cs.wisc.edu//   0bus1110011.
497053SN/A//
506899SN/A// Revision 1.3  2006/01/13 18:53:53  acg
516899SN/A// Andy Goodrich: added $Log command so that CVS comments are reproduced in
527053SN/A// the source.
537053SN/A//
546899SN/A
557053SN/A#include <cstring>
567053SN/A#include <sstream>
576899SN/A
587053SN/A#include "systemc/ext/dt/bit/messages.hh"
597053SN/A#include "systemc/ext/dt/bit/sc_bv_base.hh"
607053SN/A#include "systemc/ext/dt/fx/sc_fix.hh"
617053SN/A#include "systemc/ext/dt/fx/sc_ufix.hh"
626899SN/A#include "systemc/ext/utils/sc_report.hh"
638184Ssomayeh@cs.wisc.edu
648184Ssomayeh@cs.wisc.edunamespace sc_dt
658184Ssomayeh@cs.wisc.edu{
668184Ssomayeh@cs.wisc.edu
677053SN/A// ----------------------------------------------------------------------------
687053SN/A//  CLASS : sc_bv_base
697053SN/A//
707053SN/A//  Arbitrary size bit vector base class.
717053SN/A// ----------------------------------------------------------------------------
727053SN/A
737053SN/Avoid
747053SN/Asc_bv_base::init(int length_, bool init_value)
757053SN/A{
766899SN/A    // check the length
776899SN/A    if (length_ <= 0) {
787053SN/A        SC_REPORT_ERROR(sc_core::SC_ID_ZERO_LENGTH_, 0);
797053SN/A        sc_core::sc_abort(); // can't recover from here
806899SN/A    }
817053SN/A    // allocate memory for the data and control words
826899SN/A    m_len = length_;
837053SN/A    m_size = (m_len - 1) / SC_DIGIT_SIZE + 1;
847053SN/A    m_data = new sc_digit[m_size];
857053SN/A    // initialize the bits to 'init_value'
866899SN/A    sc_digit dw = init_value ? ~SC_DIGIT_ZERO : SC_DIGIT_ZERO;
877053SN/A    int sz = m_size;
887053SN/A    for (int i = 0; i < sz; ++i) {
896899SN/A        m_data[i] = dw;
907053SN/A    }
916899SN/A    clean_tail();
927053SN/A}
937053SN/A
947053SN/Avoid
957053SN/Asc_bv_base::assign_from_string(const std::string &s)
967053SN/A{
977053SN/A    // s must have been converted to bin
987053SN/A    int len = m_len;
997053SN/A    int s_len = s.length() - 1;
1007053SN/A    int min_len = sc_min(len, s_len);
1017053SN/A    int i = 0;
1027053SN/A    for (; i < min_len; ++i) {
1036899SN/A        char c = s[s_len - i - 1];
1046899SN/A        if (c != '0' && c != '1') {
1057568SN/A            SC_REPORT_ERROR(sc_core::SC_ID_CANNOT_CONVERT_,
1067823Ssteve.reinhardt@amd.com                "string can contain only '0' and '1' characters");
1077568SN/A            // may continue, if suppressed
1088190SLisa.Hsu@amd.com            c = '0';
1097568SN/A        }
1107053SN/A        set_bit(i, sc_logic_value_t(c - '0'));
1116899SN/A    }
1127053SN/A    // if formatted, fill the rest with sign(s), otherwise fill with zeros
1137053SN/A    sc_logic_value_t fill = (s[s_len] == 'F' ? sc_logic_value_t(s[0] - '0')
1147053SN/A                                             : sc_logic_value_t(0));
1157053SN/A    for (; i < len; ++i) {
1166899SN/A        set_bit(i, fill);
1177053SN/A    }
1187053SN/A}
1197053SN/A
1207053SN/A// constructors
1217053SN/Asc_bv_base::sc_bv_base(const char *a) : m_len(0), m_size(0), m_data(0)
1227053SN/A{
1237053SN/A    std::string s = convert_to_bin(a);
1247053SN/A    init(s.length() - 1);
1257053SN/A    assign_from_string(s);
1266899SN/A}
1277053SN/A
1287053SN/Asc_bv_base::sc_bv_base(const char *a, int length_) :
1297053SN/A    m_len(0), m_size(0), m_data(0)
1306899SN/A{
1316899SN/A    init(length_);
1327053SN/A    assign_from_string(convert_to_bin(a));
1338184Ssomayeh@cs.wisc.edu}
1348184Ssomayeh@cs.wisc.edu
1358184Ssomayeh@cs.wisc.edusc_bv_base::sc_bv_base(const sc_bv_base &a) :
1368184Ssomayeh@cs.wisc.edu    sc_proxy<sc_bv_base>(), m_len(a.m_len), m_size(a.m_size),
1378184Ssomayeh@cs.wisc.edu    m_data(new sc_digit[m_size])
1388184Ssomayeh@cs.wisc.edu{
1398184Ssomayeh@cs.wisc.edu    // copy the bits
1408184Ssomayeh@cs.wisc.edu    int sz = m_size;
1418184Ssomayeh@cs.wisc.edu    for (int i = 0; i < sz; ++i) {
1428184Ssomayeh@cs.wisc.edu        m_data[i] = a.m_data[i];
1438184Ssomayeh@cs.wisc.edu    }
1448184Ssomayeh@cs.wisc.edu}
1458184Ssomayeh@cs.wisc.edu
1468184Ssomayeh@cs.wisc.edu// assignment operators
1478184Ssomayeh@cs.wisc.edusc_bv_base &
1488184Ssomayeh@cs.wisc.edusc_bv_base::operator = (const char *a)
1498184Ssomayeh@cs.wisc.edu{
1508184Ssomayeh@cs.wisc.edu    assign_from_string(convert_to_bin(a));
1518184Ssomayeh@cs.wisc.edu    return *this;
1528184Ssomayeh@cs.wisc.edu}
1538184Ssomayeh@cs.wisc.edu
1548184Ssomayeh@cs.wisc.edu
1558184Ssomayeh@cs.wisc.edu// ----------------------------------------------------------------------------
1568184Ssomayeh@cs.wisc.edu// convert formatted string to binary string
1578184Ssomayeh@cs.wisc.edu
1588184Ssomayeh@cs.wisc.educonst std::string
1598184Ssomayeh@cs.wisc.educonvert_to_bin(const char *s)
1608184Ssomayeh@cs.wisc.edu{
1618184Ssomayeh@cs.wisc.edu    // Beware: logic character strings cannot start with '0x' or '0X',
1628184Ssomayeh@cs.wisc.edu    //         because this is seen as a hexadecimal encoding prefix!
1638184Ssomayeh@cs.wisc.edu
1647053SN/A    if (s == 0) {
1656899SN/A        SC_REPORT_ERROR(sc_core::SC_ID_CANNOT_CONVERT_,
1667053SN/A                "character string is zero");
1677053SN/A        return std::string();
1686899SN/A    }
1697053SN/A    if (*s == 0) {
1707053SN/A        SC_REPORT_ERROR(sc_core::SC_ID_CANNOT_CONVERT_,
1717053SN/A            "character string is empty");
1726899SN/A        return std::string();
1737053SN/A    }
1746899SN/A
1757053SN/A    int n = strlen(s);
1767053SN/A    int i = 0;
1776899SN/A    if (s[0] == '-' || s[0] == '+') {
1787053SN/A        ++i;
1797823Ssteve.reinhardt@amd.com    }
1807053SN/A    if (n > (i + 2) && s[i] == '0') {
1816899SN/A        if (s[i + 1] == 'b' || s[i + 1] == 'B') {
1828190SLisa.Hsu@amd.com            if (s[i + 2] == '0' || s[i + 2] == '1') {
1837053SN/A                std::string str(&s[2]);
1847053SN/A                str += "F";
1857053SN/A                return str;
1867053SN/A            }
1877053SN/A        }
1887053SN/A        if (s[i + 1] == 'b' || s[i + 1] == 'B' ||
1896899SN/A            s[i + 1] == 'c' || s[i + 1] == 'C' ||
1907053SN/A            s[i + 1] == 'd' || s[i + 1] == 'D' ||
1916899SN/A            s[i + 1] == 'o' || s[i + 1] == 'O' ||
1927053SN/A            s[i + 1] == 'x' || s[i + 1] == 'X') {
1937053SN/A            try {
1947053SN/A                // worst case length = n * 4
1957053SN/A                sc_fix a(s, n * 4, n * 4, SC_TRN, SC_WRAP, 0, SC_ON);
1966899SN/A                std::string str = a.to_bin();
1977053SN/A                str += "F"; // mark the string as formatted
1987053SN/A                // get rid of prefix (0b) and redundant leading bits
1996899SN/A                const char *p = str.c_str() + 2;
2007053SN/A                while (p[1] && p[0] == p[1]) {
2017053SN/A                    ++p;
2027053SN/A                }
2037053SN/A                return std::string(p);
2046899SN/A            } catch (const sc_core::sc_report &) {
2057053SN/A                std::stringstream msg;
2067053SN/A                msg << "character string '" << s << "' is not valid";
2077053SN/A                SC_REPORT_ERROR(sc_core::SC_ID_CANNOT_CONVERT_,
2087053SN/A                        msg.str().c_str());
2097053SN/A                return std::string();
2107053SN/A            }
2117053SN/A        }
2127053SN/A    }
2137053SN/A
2147053SN/A    // bin by default
2157053SN/A    std::string str(s);
2167053SN/A    str += "U"; // mark the string as unformatted
2177053SN/A    return str;
2187053SN/A}
2197053SN/A
2207053SN/A// convert binary string to formatted string
2217053SN/Aconst std::string
2227053SN/Aconvert_to_fmt(const std::string &s, sc_numrep numrep, bool w_prefix)
2237053SN/A{
2246899SN/A    int n = s.length();
2256899SN/A    std::string str("0bus");
2266899SN/A    // str += "0bus";
2277053SN/A    str += s;
2287053SN/A    sc_ufix a(str.c_str(), n, n, SC_TRN, SC_WRAP, 0, SC_ON);
2296899SN/A    return a.to_string(numrep, w_prefix);
2307053SN/A}
2317053SN/A
2326899SN/A} // namespace sc_dt
2337053SN/A