sc_bv_base.cpp revision 12027:1eb7dc7aa10b
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 <string.h>
56
57#include "sysc/datatypes/bit/sc_bit_ids.h"
58#include "sysc/datatypes/bit/sc_bv_base.h"
59#include "sysc/datatypes/fx/sc_fix.h"
60#include "sysc/datatypes/fx/sc_ufix.h"
61
62
63namespace sc_dt
64{
65
66// ----------------------------------------------------------------------------
67//  CLASS : sc_bv_base
68//
69//  Arbitrary size bit vector base class.
70// ----------------------------------------------------------------------------
71
72void
73sc_bv_base::init( int length_, bool init_value )
74{
75    // check the length
76    if( length_ <= 0 ) {
77	SC_REPORT_ERROR( sc_core::SC_ID_ZERO_LENGTH_, 0 );
78    }
79    // allocate memory for the data and control words
80    m_len = length_;
81    m_size = (m_len - 1) / SC_DIGIT_SIZE + 1;
82    m_data = new sc_digit[m_size];
83    // initialize the bits to 'init_value'
84    sc_digit dw = init_value ? ~SC_DIGIT_ZERO : SC_DIGIT_ZERO;
85    int sz = m_size;
86    for( int i = 0; i < sz; ++ i ) {
87	m_data[i] = dw;
88    }
89    clean_tail();
90}
91
92
93void
94sc_bv_base::assign_from_string( const std::string& s )
95{
96    // s must have been converted to bin
97    int len = m_len;
98    int s_len = s.length() - 1;
99    int min_len = sc_min( len, s_len );
100    int i = 0;
101    for( ; i < min_len; ++ i ) {
102	char c = s[s_len - i - 1];
103	if( c != '0' && c != '1' ) {
104	    SC_REPORT_ERROR( sc_core::SC_ID_CANNOT_CONVERT_,
105	        "string can contain only '0' and '1' characters" );
106	}
107	set_bit( i, sc_logic_value_t( c - '0' ) );
108    }
109    // if formatted, fill the rest with sign(s), otherwise fill with zeros
110    sc_logic_value_t fill = (s[s_len] == 'F' ? sc_logic_value_t( s[0] - '0' )
111		                             : sc_logic_value_t( 0 ));
112    for( ; i < len; ++ i ) {
113	set_bit( i, fill );
114    }
115}
116
117
118// constructors
119
120sc_bv_base::sc_bv_base( const char* a )
121    : 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>(),
137      m_len( a.m_len ),
138      m_size( a.m_size ),
139      m_data( new sc_digit[m_size] )
140{
141    // copy the bits
142    int sz = m_size;
143    for( int i = 0; i < sz; ++ i ) {
144	m_data[i] = a.m_data[i];
145    }
146}
147
148
149// assignment operators
150
151sc_bv_base&
152sc_bv_base::operator = ( const char* a )
153{
154    assign_from_string( convert_to_bin( a ) );
155    return *this;
156}
157
158
159#if 0
160
161// bitwise complement
162
163sc_bv_base&
164sc_bv_base::b_not()
165{
166    int sz = m_size;
167    for( int i = 0; i < sz; ++ i ) {
168	m_data[i] = ~m_data[i];
169    }
170    clean_tail();
171    return *this;
172}
173
174
175// bitwise left shift
176
177sc_bv_base&
178sc_bv_base::operator <<= ( int n )
179{
180    if( n < 0 ) {
181	char msg[BUFSIZ];
182	std::sprintf( msg,
183		 "left shift operation is only allowed with positive "
184		 "shift values, shift value = %d", n );
185	SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, msg );
186    }
187    int sz = m_size;
188    if( n >= m_len ) {
189	for( int i = 0; i < sz; ++ i ) {
190	    m_data[i] = SC_DIGIT_ZERO;
191	}
192	// clean_tail();
193	return *this;
194    }
195    int wn = n / SC_DIGIT_SIZE;
196    int bn = n % SC_DIGIT_SIZE;
197    if( wn != 0 ) {
198	// shift words
199	int i = sz - 1;
200	for( ; i >= wn; -- i ) {
201	    m_data[i] = m_data[i - wn];
202	}
203	for( ; i >= 0; -- i ) {
204	    m_data[i] = SC_DIGIT_ZERO;
205	}
206    }
207    if( bn != 0 ) {
208	// shift bits
209	for( int i = sz - 1; i >= 1; -- i ) {
210	    m_data[i] <<= bn;
211	    m_data[i] |= m_data[i - 1] >> (SC_DIGIT_SIZE - bn);
212	}
213	m_data[0] <<= bn;
214    }
215    clean_tail();
216    return *this;
217}
218
219
220// bitwise right shift
221
222sc_bv_base&
223sc_bv_base::operator >>= ( int n )
224{
225    if( n < 0 ) {
226	char msg[BUFSIZ];
227	std::sprintf( msg,
228		 "right shift operation is only allowed with positive "
229		 "shift values, shift value = %d", n );
230	SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, msg );
231    }
232    int sz = m_size;
233    if( n >= m_len ) {
234	for( int i = 0; i < sz; ++ i ) {
235	    m_data[i] = SC_DIGIT_ZERO;
236	}
237	// clean_tail();
238	return *this;
239    }
240    int wn = n / SC_DIGIT_SIZE;
241    int bn = n % SC_DIGIT_SIZE;
242    if( wn != 0 ) {
243	// shift words
244	int i = 0;
245	for( ; i < (sz - wn); ++ i ) {
246	    m_data[i] = m_data[i + wn];
247	}
248	for( ; i < sz; ++ i ) {
249	    m_data[i] = SC_DIGIT_ZERO;
250	}
251    }
252    if( bn != 0 ) {
253	// shift bits
254	for( int i = 0; i < (sz - 1); ++ i ) {
255	    m_data[i] >>= bn;
256	    m_data[i] |= m_data[i + 1] << (SC_DIGIT_SIZE - bn);
257	}
258	m_data[sz - 1] >>= bn;
259    }
260    clean_tail();
261    return *this;
262}
263
264
265// bitwise left rotate
266
267sc_bv_base&
268sc_bv_base::lrotate( int n )
269{
270    if( n < 0 ) {
271	char msg[BUFSIZ];
272	std::sprintf( msg,
273		 "left rotate operation is only allowed with positive "
274		 "rotate values, rotate value = %d", n );
275	SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, msg );
276    }
277    int len = m_len;
278    n %= len;
279    *this = (*this << n) | (*this >> (len - n));
280    return *this;
281}
282
283
284// bitwise right rotate
285
286sc_bv_base&
287sc_bv_base::rrotate( int n )
288{
289    if( n < 0 ) {
290	char msg[BUFSIZ];
291	std::sprintf( msg,
292		 "right rotate operation is only allowed with positive "
293		 "rotate values, rotate value = %d", n );
294	SC_REPORT_ERROR( sc_core::SC_ID_OUT_OF_BOUNDS_, msg );
295    }
296    int len = m_len;
297    n %= len;
298    *this = (*this >> n) | (*this << (len - n));
299    return *this;
300}
301
302#endif
303
304
305// ----------------------------------------------------------------------------
306
307// convert formatted string to binary string
308
309const std::string
310convert_to_bin( const char* s )
311{
312    // Beware: logic character strings cannot start with '0x' or '0X',
313    //         because this is seen as a hexadecimal encoding prefix!
314
315    if( s == 0 ) {
316	SC_REPORT_ERROR(sc_core::SC_ID_CANNOT_CONVERT_,
317	    "character string is zero" );
318    }
319    if( *s == 0 ) {
320	SC_REPORT_ERROR(sc_core::SC_ID_CANNOT_CONVERT_,
321	    "character string is empty");
322    }
323
324    int n = strlen( s );
325    int i = 0;
326    if( s[0] == '-' || s[0] == '+' ) {
327	++ i;
328    }
329    if( n > (i + 2) && s[i] == '0' )
330    {
331        if (s[i+1] == 'b' || s[i+1] == 'B' )
332	{
333	    if ( s[i+2] == '0' || s[i+2] == '1' )
334	    {
335		std::string str( &s[2] );
336	        str += "F";
337	        return str;
338	    }
339	}
340        if ( s[i+1] == 'b' || s[i+1] == 'B' ||
341	     s[i+1] == 'c' || s[i+1] == 'C' ||
342	     s[i+1] == 'd' || s[i+1] == 'D' ||
343	     s[i+1] == 'o' || s[i+1] == 'O' ||
344	     s[i+1] == 'x' || s[i+1] == 'X')
345        {
346	    try {
347		// worst case length = n * 4
348		sc_fix a( s, n * 4, n * 4, SC_TRN, SC_WRAP, 0, SC_ON );
349		std::string str = a.to_bin();
350		str += "F"; // mark the string as formatted
351		// get rid of prefix (0b) and redundant leading bits
352		const char* p = str.c_str() + 2;
353		while( p[1] && p[0] == p[1] ) {
354		    ++ p;
355		}
356		return std::string( p );
357	    } catch( sc_core::sc_report ) {
358		char msg[BUFSIZ];
359		std::sprintf( msg, "character string '%s' is not valid", s );
360		SC_REPORT_ERROR( sc_core::SC_ID_CANNOT_CONVERT_, msg );
361		// never reached
362		return std::string();
363	    }
364	}
365
366    }
367
368    // bin by default
369
370    std::string str( s );
371    str += "U"; // mark the string as unformatted
372    return str;
373}
374
375// convert binary string to formatted string
376
377const std::string
378convert_to_fmt( const std::string& s, sc_numrep numrep, bool w_prefix )
379{
380    int n = s.length();
381    std::string str("0bus");
382    // str += "0bus";
383    str += s;
384    sc_ufix a( str.c_str(), n, n, SC_TRN, SC_WRAP, 0, SC_ON );
385    return a.to_string( numrep, w_prefix );
386}
387
388} // namespace sc_dt
389