112854Sgabeblack@google.com/*****************************************************************************
212854Sgabeblack@google.com
312854Sgabeblack@google.com  Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
412854Sgabeblack@google.com  more contributor license agreements.  See the NOTICE file distributed
512854Sgabeblack@google.com  with this work for additional information regarding copyright ownership.
612854Sgabeblack@google.com  Accellera licenses this file to you under the Apache License, Version 2.0
712854Sgabeblack@google.com  (the "License"); you may not use this file except in compliance with the
812854Sgabeblack@google.com  License.  You may obtain a copy of the License at
912854Sgabeblack@google.com
1012854Sgabeblack@google.com    http://www.apache.org/licenses/LICENSE-2.0
1112854Sgabeblack@google.com
1212854Sgabeblack@google.com  Unless required by applicable law or agreed to in writing, software
1312854Sgabeblack@google.com  distributed under the License is distributed on an "AS IS" BASIS,
1412854Sgabeblack@google.com  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
1512854Sgabeblack@google.com  implied.  See the License for the specific language governing
1612854Sgabeblack@google.com  permissions and limitations under the License.
1712854Sgabeblack@google.com
1812854Sgabeblack@google.com *****************************************************************************/
1912854Sgabeblack@google.com
2012854Sgabeblack@google.com/*****************************************************************************
2112854Sgabeblack@google.com
2212854Sgabeblack@google.com  sc_bv_base.cpp -- Arbitrary size bit vector class.
2312854Sgabeblack@google.com
2412854Sgabeblack@google.com  Original Author: Gene Bushuyev, Synopsys, Inc.
2512854Sgabeblack@google.com
2612854Sgabeblack@google.com *****************************************************************************/
2712854Sgabeblack@google.com
2812854Sgabeblack@google.com/*****************************************************************************
2912854Sgabeblack@google.com
3012854Sgabeblack@google.com  MODIFICATION LOG - modifiers, enter your name, affiliation, date and
3112854Sgabeblack@google.com  changes you are making here.
3212854Sgabeblack@google.com
3312854Sgabeblack@google.com      Name, Affiliation, Date:
3412854Sgabeblack@google.com  Description of Modification:
3512854Sgabeblack@google.com
3612854Sgabeblack@google.com *****************************************************************************/
3712854Sgabeblack@google.com
3812854Sgabeblack@google.com
3912854Sgabeblack@google.com// $Log: sc_bv_base.cpp,v $
4012854Sgabeblack@google.com// Revision 1.2  2011/08/24 22:05:40  acg
4112854Sgabeblack@google.com//  Torsten Maehne: initialization changes to remove warnings.
4212854Sgabeblack@google.com//
4312854Sgabeblack@google.com// Revision 1.1.1.1  2006/12/15 20:20:04  acg
4412854Sgabeblack@google.com// SystemC 2.3
4512854Sgabeblack@google.com//
4612854Sgabeblack@google.com// Revision 1.4  2006/04/11 23:12:26  acg
4712854Sgabeblack@google.com//   Andy Goodrich: Fixed bug in parsing of extended string constants like
4812854Sgabeblack@google.com//   0bus1110011.
4912854Sgabeblack@google.com//
5012854Sgabeblack@google.com// Revision 1.3  2006/01/13 18:53:53  acg
5112854Sgabeblack@google.com// Andy Goodrich: added $Log command so that CVS comments are reproduced in
5212854Sgabeblack@google.com// the source.
5312854Sgabeblack@google.com//
5412854Sgabeblack@google.com
5512854Sgabeblack@google.com#include <cstring>
5612854Sgabeblack@google.com#include <sstream>
5712854Sgabeblack@google.com
5813325Sgabeblack@google.com#include "systemc/ext/dt/bit/messages.hh"
5912854Sgabeblack@google.com#include "systemc/ext/dt/bit/sc_bv_base.hh"
6012854Sgabeblack@google.com#include "systemc/ext/dt/fx/sc_fix.hh"
6112854Sgabeblack@google.com#include "systemc/ext/dt/fx/sc_ufix.hh"
6212854Sgabeblack@google.com#include "systemc/ext/utils/sc_report.hh"
6312854Sgabeblack@google.com
6412854Sgabeblack@google.comnamespace sc_dt
6512854Sgabeblack@google.com{
6612854Sgabeblack@google.com
6712854Sgabeblack@google.com// ----------------------------------------------------------------------------
6812854Sgabeblack@google.com//  CLASS : sc_bv_base
6912854Sgabeblack@google.com//
7012854Sgabeblack@google.com//  Arbitrary size bit vector base class.
7112854Sgabeblack@google.com// ----------------------------------------------------------------------------
7212854Sgabeblack@google.com
7312854Sgabeblack@google.comvoid
7412854Sgabeblack@google.comsc_bv_base::init(int length_, bool init_value)
7512854Sgabeblack@google.com{
7612854Sgabeblack@google.com    // check the length
7712854Sgabeblack@google.com    if (length_ <= 0) {
7813325Sgabeblack@google.com        SC_REPORT_ERROR(sc_core::SC_ID_ZERO_LENGTH_, 0);
7912854Sgabeblack@google.com        sc_core::sc_abort(); // can't recover from here
8012854Sgabeblack@google.com    }
8112854Sgabeblack@google.com    // allocate memory for the data and control words
8212854Sgabeblack@google.com    m_len = length_;
8312854Sgabeblack@google.com    m_size = (m_len - 1) / SC_DIGIT_SIZE + 1;
8412854Sgabeblack@google.com    m_data = new sc_digit[m_size];
8512854Sgabeblack@google.com    // initialize the bits to 'init_value'
8612854Sgabeblack@google.com    sc_digit dw = init_value ? ~SC_DIGIT_ZERO : SC_DIGIT_ZERO;
8712854Sgabeblack@google.com    int sz = m_size;
8812854Sgabeblack@google.com    for (int i = 0; i < sz; ++i) {
8912854Sgabeblack@google.com        m_data[i] = dw;
9012854Sgabeblack@google.com    }
9112854Sgabeblack@google.com    clean_tail();
9212854Sgabeblack@google.com}
9312854Sgabeblack@google.com
9412854Sgabeblack@google.comvoid
9512854Sgabeblack@google.comsc_bv_base::assign_from_string(const std::string &s)
9612854Sgabeblack@google.com{
9712854Sgabeblack@google.com    // s must have been converted to bin
9812854Sgabeblack@google.com    int len = m_len;
9912854Sgabeblack@google.com    int s_len = s.length() - 1;
10012854Sgabeblack@google.com    int min_len = sc_min(len, s_len);
10112854Sgabeblack@google.com    int i = 0;
10212854Sgabeblack@google.com    for (; i < min_len; ++i) {
10312854Sgabeblack@google.com        char c = s[s_len - i - 1];
10412854Sgabeblack@google.com        if (c != '0' && c != '1') {
10513325Sgabeblack@google.com            SC_REPORT_ERROR(sc_core::SC_ID_CANNOT_CONVERT_,
10612854Sgabeblack@google.com                "string can contain only '0' and '1' characters");
10712854Sgabeblack@google.com            // may continue, if suppressed
10812854Sgabeblack@google.com            c = '0';
10912854Sgabeblack@google.com        }
11012854Sgabeblack@google.com        set_bit(i, sc_logic_value_t(c - '0'));
11112854Sgabeblack@google.com    }
11212854Sgabeblack@google.com    // if formatted, fill the rest with sign(s), otherwise fill with zeros
11312854Sgabeblack@google.com    sc_logic_value_t fill = (s[s_len] == 'F' ? sc_logic_value_t(s[0] - '0')
11412854Sgabeblack@google.com                                             : sc_logic_value_t(0));
11512854Sgabeblack@google.com    for (; i < len; ++i) {
11612854Sgabeblack@google.com        set_bit(i, fill);
11712854Sgabeblack@google.com    }
11812854Sgabeblack@google.com}
11912854Sgabeblack@google.com
12012854Sgabeblack@google.com// constructors
12112854Sgabeblack@google.comsc_bv_base::sc_bv_base(const char *a) : m_len(0), m_size(0), m_data(0)
12212854Sgabeblack@google.com{
12312854Sgabeblack@google.com    std::string s = convert_to_bin(a);
12412854Sgabeblack@google.com    init(s.length() - 1);
12512854Sgabeblack@google.com    assign_from_string(s);
12612854Sgabeblack@google.com}
12712854Sgabeblack@google.com
12812854Sgabeblack@google.comsc_bv_base::sc_bv_base(const char *a, int length_) :
12912854Sgabeblack@google.com    m_len(0), m_size(0), m_data(0)
13012854Sgabeblack@google.com{
13112854Sgabeblack@google.com    init(length_);
13212854Sgabeblack@google.com    assign_from_string(convert_to_bin(a));
13312854Sgabeblack@google.com}
13412854Sgabeblack@google.com
13512854Sgabeblack@google.comsc_bv_base::sc_bv_base(const sc_bv_base &a) :
13612854Sgabeblack@google.com    sc_proxy<sc_bv_base>(), m_len(a.m_len), m_size(a.m_size),
13712854Sgabeblack@google.com    m_data(new sc_digit[m_size])
13812854Sgabeblack@google.com{
13912854Sgabeblack@google.com    // copy the bits
14012854Sgabeblack@google.com    int sz = m_size;
14112854Sgabeblack@google.com    for (int i = 0; i < sz; ++i) {
14212854Sgabeblack@google.com        m_data[i] = a.m_data[i];
14312854Sgabeblack@google.com    }
14412854Sgabeblack@google.com}
14512854Sgabeblack@google.com
14612854Sgabeblack@google.com// assignment operators
14712854Sgabeblack@google.comsc_bv_base &
14812854Sgabeblack@google.comsc_bv_base::operator = (const char *a)
14912854Sgabeblack@google.com{
15012854Sgabeblack@google.com    assign_from_string(convert_to_bin(a));
15112854Sgabeblack@google.com    return *this;
15212854Sgabeblack@google.com}
15312854Sgabeblack@google.com
15412854Sgabeblack@google.com
15512854Sgabeblack@google.com// ----------------------------------------------------------------------------
15612854Sgabeblack@google.com// convert formatted string to binary string
15712854Sgabeblack@google.com
15812854Sgabeblack@google.comconst std::string
15912854Sgabeblack@google.comconvert_to_bin(const char *s)
16012854Sgabeblack@google.com{
16112854Sgabeblack@google.com    // Beware: logic character strings cannot start with '0x' or '0X',
16212854Sgabeblack@google.com    //         because this is seen as a hexadecimal encoding prefix!
16312854Sgabeblack@google.com
16412854Sgabeblack@google.com    if (s == 0) {
16513325Sgabeblack@google.com        SC_REPORT_ERROR(sc_core::SC_ID_CANNOT_CONVERT_,
16613325Sgabeblack@google.com                "character string is zero");
16712854Sgabeblack@google.com        return std::string();
16812854Sgabeblack@google.com    }
16912854Sgabeblack@google.com    if (*s == 0) {
17013325Sgabeblack@google.com        SC_REPORT_ERROR(sc_core::SC_ID_CANNOT_CONVERT_,
17112854Sgabeblack@google.com            "character string is empty");
17212854Sgabeblack@google.com        return std::string();
17312854Sgabeblack@google.com    }
17412854Sgabeblack@google.com
17512854Sgabeblack@google.com    int n = strlen(s);
17612854Sgabeblack@google.com    int i = 0;
17712854Sgabeblack@google.com    if (s[0] == '-' || s[0] == '+') {
17812854Sgabeblack@google.com        ++i;
17912854Sgabeblack@google.com    }
18012854Sgabeblack@google.com    if (n > (i + 2) && s[i] == '0') {
18112854Sgabeblack@google.com        if (s[i + 1] == 'b' || s[i + 1] == 'B') {
18212854Sgabeblack@google.com            if (s[i + 2] == '0' || s[i + 2] == '1') {
18312854Sgabeblack@google.com                std::string str(&s[2]);
18412854Sgabeblack@google.com                str += "F";
18512854Sgabeblack@google.com                return str;
18612854Sgabeblack@google.com            }
18712854Sgabeblack@google.com        }
18812854Sgabeblack@google.com        if (s[i + 1] == 'b' || s[i + 1] == 'B' ||
18912854Sgabeblack@google.com            s[i + 1] == 'c' || s[i + 1] == 'C' ||
19012854Sgabeblack@google.com            s[i + 1] == 'd' || s[i + 1] == 'D' ||
19112854Sgabeblack@google.com            s[i + 1] == 'o' || s[i + 1] == 'O' ||
19212854Sgabeblack@google.com            s[i + 1] == 'x' || s[i + 1] == 'X') {
19312854Sgabeblack@google.com            try {
19412854Sgabeblack@google.com                // worst case length = n * 4
19512854Sgabeblack@google.com                sc_fix a(s, n * 4, n * 4, SC_TRN, SC_WRAP, 0, SC_ON);
19612854Sgabeblack@google.com                std::string str = a.to_bin();
19712854Sgabeblack@google.com                str += "F"; // mark the string as formatted
19812854Sgabeblack@google.com                // get rid of prefix (0b) and redundant leading bits
19912854Sgabeblack@google.com                const char *p = str.c_str() + 2;
20012854Sgabeblack@google.com                while (p[1] && p[0] == p[1]) {
20112854Sgabeblack@google.com                    ++p;
20212854Sgabeblack@google.com                }
20312854Sgabeblack@google.com                return std::string(p);
20412854Sgabeblack@google.com            } catch (const sc_core::sc_report &) {
20512854Sgabeblack@google.com                std::stringstream msg;
20612854Sgabeblack@google.com                msg << "character string '" << s << "' is not valid";
20713325Sgabeblack@google.com                SC_REPORT_ERROR(sc_core::SC_ID_CANNOT_CONVERT_,
20812854Sgabeblack@google.com                        msg.str().c_str());
20912854Sgabeblack@google.com                return std::string();
21012854Sgabeblack@google.com            }
21112854Sgabeblack@google.com        }
21212854Sgabeblack@google.com    }
21312854Sgabeblack@google.com
21412854Sgabeblack@google.com    // bin by default
21512854Sgabeblack@google.com    std::string str(s);
21612854Sgabeblack@google.com    str += "U"; // mark the string as unformatted
21712854Sgabeblack@google.com    return str;
21812854Sgabeblack@google.com}
21912854Sgabeblack@google.com
22012854Sgabeblack@google.com// convert binary string to formatted string
22112854Sgabeblack@google.comconst std::string
22212854Sgabeblack@google.comconvert_to_fmt(const std::string &s, sc_numrep numrep, bool w_prefix)
22312854Sgabeblack@google.com{
22412854Sgabeblack@google.com    int n = s.length();
22512854Sgabeblack@google.com    std::string str("0bus");
22612854Sgabeblack@google.com    // str += "0bus";
22712854Sgabeblack@google.com    str += s;
22812854Sgabeblack@google.com    sc_ufix a(str.c_str(), n, n, SC_TRN, SC_WRAP, 0, SC_ON);
22912854Sgabeblack@google.com    return a.to_string(numrep, w_prefix);
23012854Sgabeblack@google.com}
23112854Sgabeblack@google.com
23212854Sgabeblack@google.com} // namespace sc_dt
233