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  sc_bv_base.cpp -- Arbitrary size bit vector class.
23
24  Original Author: Gene Bushuyev, Synopsys, Inc.
25
26 *****************************************************************************/
27
28/*****************************************************************************
29
30  MODIFICATION LOG - modifiers, enter your name, affiliation, date and
31  changes you are making here.
32
33      Name, Affiliation, Date:
34  Description of Modification:
35
36 *****************************************************************************/
37
38
39// $Log: sc_bv_base.cpp,v $
40// Revision 1.2  2011/08/24 22:05:40  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.4  2006/04/11 23:12:26  acg
47//   Andy Goodrich: Fixed bug in parsing of extended string constants like
48//   0bus1110011.
49//
50// Revision 1.3  2006/01/13 18:53:53  acg
51// Andy Goodrich: added $Log command so that CVS comments are reproduced in
52// the source.
53//
54
55#include <cstring>
56#include <sstream>
57
58#include "systemc/ext/dt/bit/messages.hh"
59#include "systemc/ext/dt/bit/sc_bv_base.hh"
60#include "systemc/ext/dt/fx/sc_fix.hh"
61#include "systemc/ext/dt/fx/sc_ufix.hh"
62#include "systemc/ext/utils/sc_report.hh"
63
64namespace sc_dt
65{
66
67// ----------------------------------------------------------------------------
68//  CLASS : sc_bv_base
69//
70//  Arbitrary size bit vector base class.
71// ----------------------------------------------------------------------------
72
73void
74sc_bv_base::init(int length_, bool init_value)
75{
76    // check the length
77    if (length_ <= 0) {
78        SC_REPORT_ERROR(sc_core::SC_ID_ZERO_LENGTH_, 0);
79        sc_core::sc_abort(); // can't recover from here
80    }
81    // allocate memory for the data and control words
82    m_len = length_;
83    m_size = (m_len - 1) / SC_DIGIT_SIZE + 1;
84    m_data = new sc_digit[m_size];
85    // initialize the bits to 'init_value'
86    sc_digit dw = init_value ? ~SC_DIGIT_ZERO : SC_DIGIT_ZERO;
87    int sz = m_size;
88    for (int i = 0; i < sz; ++i) {
89        m_data[i] = dw;
90    }
91    clean_tail();
92}
93
94void
95sc_bv_base::assign_from_string(const std::string &s)
96{
97    // s must have been converted to bin
98    int len = m_len;
99    int s_len = s.length() - 1;
100    int min_len = sc_min(len, s_len);
101    int i = 0;
102    for (; i < min_len; ++i) {
103        char c = s[s_len - i - 1];
104        if (c != '0' && c != '1') {
105            SC_REPORT_ERROR(sc_core::SC_ID_CANNOT_CONVERT_,
106                "string can contain only '0' and '1' characters");
107            // may continue, if suppressed
108            c = '0';
109        }
110        set_bit(i, sc_logic_value_t(c - '0'));
111    }
112    // if formatted, fill the rest with sign(s), otherwise fill with zeros
113    sc_logic_value_t fill = (s[s_len] == 'F' ? sc_logic_value_t(s[0] - '0')
114                                             : sc_logic_value_t(0));
115    for (; i < len; ++i) {
116        set_bit(i, fill);
117    }
118}
119
120// constructors
121sc_bv_base::sc_bv_base(const char *a) : m_len(0), m_size(0), m_data(0)
122{
123    std::string s = convert_to_bin(a);
124    init(s.length() - 1);
125    assign_from_string(s);
126}
127
128sc_bv_base::sc_bv_base(const char *a, int length_) :
129    m_len(0), m_size(0), m_data(0)
130{
131    init(length_);
132    assign_from_string(convert_to_bin(a));
133}
134
135sc_bv_base::sc_bv_base(const sc_bv_base &a) :
136    sc_proxy<sc_bv_base>(), m_len(a.m_len), m_size(a.m_size),
137    m_data(new sc_digit[m_size])
138{
139    // copy the bits
140    int sz = m_size;
141    for (int i = 0; i < sz; ++i) {
142        m_data[i] = a.m_data[i];
143    }
144}
145
146// assignment operators
147sc_bv_base &
148sc_bv_base::operator = (const char *a)
149{
150    assign_from_string(convert_to_bin(a));
151    return *this;
152}
153
154
155// ----------------------------------------------------------------------------
156// convert formatted string to binary string
157
158const std::string
159convert_to_bin(const char *s)
160{
161    // Beware: logic character strings cannot start with '0x' or '0X',
162    //         because this is seen as a hexadecimal encoding prefix!
163
164    if (s == 0) {
165        SC_REPORT_ERROR(sc_core::SC_ID_CANNOT_CONVERT_,
166                "character string is zero");
167        return std::string();
168    }
169    if (*s == 0) {
170        SC_REPORT_ERROR(sc_core::SC_ID_CANNOT_CONVERT_,
171            "character string is empty");
172        return std::string();
173    }
174
175    int n = strlen(s);
176    int i = 0;
177    if (s[0] == '-' || s[0] == '+') {
178        ++i;
179    }
180    if (n > (i + 2) && s[i] == '0') {
181        if (s[i + 1] == 'b' || s[i + 1] == 'B') {
182            if (s[i + 2] == '0' || s[i + 2] == '1') {
183                std::string str(&s[2]);
184                str += "F";
185                return str;
186            }
187        }
188        if (s[i + 1] == 'b' || s[i + 1] == 'B' ||
189            s[i + 1] == 'c' || s[i + 1] == 'C' ||
190            s[i + 1] == 'd' || s[i + 1] == 'D' ||
191            s[i + 1] == 'o' || s[i + 1] == 'O' ||
192            s[i + 1] == 'x' || s[i + 1] == 'X') {
193            try {
194                // worst case length = n * 4
195                sc_fix a(s, n * 4, n * 4, SC_TRN, SC_WRAP, 0, SC_ON);
196                std::string str = a.to_bin();
197                str += "F"; // mark the string as formatted
198                // get rid of prefix (0b) and redundant leading bits
199                const char *p = str.c_str() + 2;
200                while (p[1] && p[0] == p[1]) {
201                    ++p;
202                }
203                return std::string(p);
204            } catch (const sc_core::sc_report &) {
205                std::stringstream msg;
206                msg << "character string '" << s << "' is not valid";
207                SC_REPORT_ERROR(sc_core::SC_ID_CANNOT_CONVERT_,
208                        msg.str().c_str());
209                return std::string();
210            }
211        }
212    }
213
214    // bin by default
215    std::string str(s);
216    str += "U"; // mark the string as unformatted
217    return str;
218}
219
220// convert binary string to formatted string
221const std::string
222convert_to_fmt(const std::string &s, sc_numrep numrep, bool w_prefix)
223{
224    int n = s.length();
225    std::string str("0bus");
226    // str += "0bus";
227    str += s;
228    sc_ufix a(str.c_str(), n, n, SC_TRN, SC_WRAP, 0, SC_ON);
229    return a.to_string(numrep, w_prefix);
230}
231
232} // namespace sc_dt
233