sc_nbutils.cpp

来自「基于4个mips核的noc设计」· C++ 代码 · 共 1,521 行 · 第 1/3 页

CPP
1,521
字号
/*****************************************************************************  The following code is derived, directly or indirectly, from the SystemC  source code Copyright (c) 1996-2002 by all Contributors.  All Rights reserved.  The contents of this file are subject to the restrictions and limitations  set forth in the SystemC Open Source License Version 2.3 (the "License");  You may not use this file except in compliance with such restrictions and  limitations. You may obtain instructions on how to receive a copy of the  License at http://www.systemc.org/. Software distributed by Contributors  under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF  ANY KIND, either express or implied. See the License for the specific  language governing rights and limitations under the License. *****************************************************************************//*****************************************************************************  sc_nbutils.cpp -- External and friend functions for both sc_signed and                    sc_unsigned classes.   Original Author: Ali Dasdan, Synopsys, Inc. *****************************************************************************//*****************************************************************************  MODIFICATION LOG - modifiers, enter your name, affiliation, date and  changes you are making here.      Name, Affiliation, Date:  Description of Modification: *****************************************************************************/#include <ctype.h>#include "systemc/datatypes/int/sc_int_ids.h"#include "systemc/datatypes/int/sc_nbutils.h"#include "systemc/kernel/sc_macros.h"namespace sc_dt{// ----------------------------------------------------------------------------//  SECTION: General utility functions.// ----------------------------------------------------------------------------// Return the number of characters to advance the source of c.  This// function implements one move of the FSM to parse the following// regular expressions. Error checking is done in the caller.small_typefsm_move(char c, small_type &b, small_type &s, small_type &state){  // Possible regular expressions (REs):  // Let N = any digit depending on the base.  //    1. [0|1|..|9]N*  //    2. [+|-][0|1|..|9]N*  //    3. 0[b|B|d|D|o|O|x|X][0|1|..|F]N*  //    4. [+|-]?0[b|B|d|D|o|O|x|X][0|1|..|F]N*  //  // The finite state machine (FMS) to parse these regular expressions  // has 4 states, 0 to 3. 0 is the initial state and 3 is the final  // state.  //  // Default sign = SC_POS, default base = NB_DEFAULT_BASE.  switch (state) {  case 0: // The initial state.    switch (c) {     case '0': s = SC_POS; state = 1; return 0; // RE 1 or 3    case '+': s = SC_POS; state = 2; return 1; // RE 2    case '-': s = SC_NEG; state = 2; return 1; // RE 2    default:  s = SC_POS; b = NB_DEFAULT_BASE; state = 3; return 0; // RE 1    }    // break; //unreachable code  case 1: // 0...    switch (c) {    case 'x': case 'X': b = SC_HEX; state = 3; return 2; // RE 3 or 4    case 'd': case 'D': b = SC_DEC; state = 3; return 2; // RE 3 or 4    case 'o': case 'O': b = SC_OCT; state = 3; return 2; // RE 3 or 4    case 'b': case 'B': b = SC_BIN; state = 3; return 2; // RE 3 or 4    default:  b = NB_DEFAULT_BASE; state = 3; return 0; // RE 1    }    // break; //unreachable code  case 2: // +... or -...    switch (c) {    case '0': state = 1; return 0; // RE 2 or 4    default:  b = NB_DEFAULT_BASE; state = 3; return 0; // RE 2    }    // break; //unreachable code  case 3: // The final state.    break;  default:    // Any other state is not possible.    assert((0 <= state) && (state <= 3));  } // switch  return 0;}  // Get base b and sign s of the number in the char string v. Return a// pointer to the first char after the point where b and s are// determined or where the end of v is reached. The input string v has// to be null terminated.const char *get_base_and_sign(const char *v, small_type &b, small_type &s){#ifdef DEBUG_SYSTEMC  assert(v != NULL);#endif  const small_type STATE_START = 0;  const small_type STATE_FINISH = 3;  // Default sign = SC_POS, default base = 10.  s = SC_POS;  b = NB_DEFAULT_BASE;  small_type state = STATE_START;  small_type nskip = 0; // Skip that many chars.  const char *u = v;  while (*u) {    if (isspace(*u))  // Skip white space.      ++u;    else {      nskip += fsm_move(*u, b, s, state);      if (state == STATE_FINISH)        break;      else        ++u;    }  }#ifdef DEBUG_SYSTEMC  // Test to see if the above loop executed more than it should  // have. The max number of skipped chars is equal to the length of  // the longest format specifier, e.g., "-0x".  assert(nskip <= 3);#endif  v += nskip;  // Handles empty strings or strings without any digits after the  // base or base and sign specifier.  if (*v == '\0') {       char msg[BUFSIZ];      sprintf( msg,	       "get_base_and_sign( const char* v, small_type&, small_type& ) : "	       "v = \"\" is not valid" );      SC_REPORT_ERROR( SC_ID_CONVERSION_FAILED_, msg );  }  return v;}// ----------------------------------------------------------------------------//  SECTION: Utility functions involving unsigned vectors.// ----------------------------------------------------------------------------// Read u from a null terminated char string v. Note that operator>>// in sc_nbcommon.cpp is similar to this function.small_typevec_from_str(int unb, int und, unsigned long *u,              const char *v, sc_numrep base) {#ifdef DEBUG_SYSTEMC  assert((unb > 0) && (und > 0) && (u != NULL));  assert(v != NULL);#endif  is_valid_base(base);  small_type b, s;  // base and sign.  v = get_base_and_sign(v, b, s);  if (base != SC_NOBASE) {    if (b == NB_DEFAULT_BASE)      b = base;    else {	char msg[BUFSIZ];	sprintf( msg,		 "vec_from_str( int, int, unsigned long*, const char*, sc_numrep base ) : "		 "base = %s does not match the default base",		 to_string( base ).c_str() );	SC_REPORT_ERROR( SC_ID_CONVERSION_FAILED_, msg );    }  }  vec_zero(und, u);  char c;    for ( ; (c = *v); ++v) {    if (isalnum(c)) {            small_type val;  // Numeric value of a char.          if (isalpha(c)) // Hex digit.        val = toupper(c) - 'A' + 10;      else        val = c - '0';            if (val >= b) {	  char msg[BUFSIZ];	  sprintf( msg,		   "vec_from_str( int, int, unsigned long*, const char*, sc_numrep base ) : "		   "'%c' is not a valid digit in base %d",		   *v, b );	  SC_REPORT_ERROR( SC_ID_CONVERSION_FAILED_, msg );      }            // digit = digit * b + val;      vec_mul_small_on(und, u, b);            if (val)        vec_add_small_on(und, u, val);    }    else {	char msg[BUFSIZ];	sprintf( msg,		 "vec_from_str( int, int, unsigned long*, const char*, sc_numrep base ) : "		 "'%c' is not a valid digit in base %d",		 *v, b );	SC_REPORT_ERROR( SC_ID_CONVERSION_FAILED_, msg );    }  }  return convert_signed_SM_to_2C_to_SM(s, unb, und, u);}// All vec_ functions assume that the vector to hold the result,// called w, has sufficient length to hold the result. For efficiency// reasons, we do not test whether or not we are out of bounds.// Compute w = u + v, where w, u, and v are vectors. // - ulen >= vlen// - wlen >= sc_max(ulen, vlen) + 1voidvec_add(int ulen, const unsigned long *u,        int vlen, const unsigned long *v,        unsigned long *w){#ifdef DEBUG_SYSTEMC  assert((ulen > 0) && (u != NULL));  assert((vlen > 0) && (v != NULL));  assert(w != NULL);  assert(ulen >= vlen);#endif  const unsigned long *uend = (u + ulen);  const unsigned long *vend = (v + vlen);  register unsigned long carry = 0;   // Also used as sum to save space.  // Add along the shorter v.  while (v < vend) {    carry += (*u++) + (*v++);    (*w++) = carry & DIGIT_MASK;    carry >>= BITS_PER_DIGIT;  }  // Propagate the carry.  while (carry && (u < uend)) {    carry = (*u++) + 1;    (*w++) = carry & DIGIT_MASK;    carry >>= BITS_PER_DIGIT;  }  // Copy the rest of u to the result.  while (u < uend)    (*w++) = (*u++);  // Propagate the carry if it is still 1.  if (carry)    (*w) = 1;}// Compute u += v, where u and v are vectors.// - ulen >= vlenvoidvec_add_on(int ulen, unsigned long *ubegin,            int vlen, const unsigned long *v){#ifdef DEBUG_SYSTEMC  assert((ulen > 0) && (ubegin != NULL));  assert((vlen > 0) && (v != NULL));  assert(ulen >= vlen);#endif  register unsigned long *u = ubegin;  const unsigned long *uend = (u + ulen);  const unsigned long *vend = (v + vlen);  register unsigned long carry = 0;   // Also used as sum to save space.  // Add along the shorter v.  while (v < vend) {    carry += (*u) + (*v++);    (*u++) = carry & DIGIT_MASK;    carry >>= BITS_PER_DIGIT;  }  // Propagate the carry.  while (carry && (u < uend)) {    carry = (*u) + 1;    (*u++) = carry & DIGIT_MASK;    carry >>= BITS_PER_DIGIT;  }#ifdef DEBUG_SYSTEMC  if( carry != 0 ) {      SC_REPORT_WARNING( SC_ID_WITHOUT_MESSAGE_,			 "vec_add_on( int, unsigned long*, int, const "			 "unsigned long* ) : "			 "result of addition is wrapped around" );  }#endif}// Compute u += v, where u and v are vectors.// - ulen < vlenvoidvec_add_on2(int ulen, unsigned long *ubegin,             int#ifdef DEBUG_SYSTEMC            vlen#endif            , const unsigned long *v){#ifdef DEBUG_SYSTEMC  assert((ulen > 0) && (ubegin != NULL));  assert((vlen > 0) && (v != NULL));  assert(ulen < vlen);#endif  register unsigned long *u = ubegin;  const unsigned long *uend = (u + ulen);  register unsigned long carry = 0;   // Also used as sum to save space.  // Add along the shorter u.  while (u < uend) {    carry += (*u) + (*v++);    (*u++) = carry & DIGIT_MASK;    carry >>= BITS_PER_DIGIT;  }#ifdef DEBUG_SYSTEMC  if( carry != 0 ) {      SC_REPORT_WARNING( SC_ID_WITHOUT_MESSAGE_,                         "vec_add_on2( int, unsigned long*, int, const "			 "unsigned long* ) : "			 "result of addition is wrapped around" );  }#endif}// Compute w = u + v, where w and u are vectors, and v is a scalar.voidvec_add_small(int ulen, const unsigned long *u,              unsigned long v,               unsigned long *w){#ifdef DEBUG_SYSTEMC  assert((ulen > 0) && (u != NULL));  assert(w != NULL);#endif  const unsigned long *uend = (u + ulen);  // Add along the shorter v.  register unsigned long carry = (*u++) + v;  (*w++) = carry & DIGIT_MASK;  carry >>= BITS_PER_DIGIT;  // Propagate the carry.  while (carry && (u < uend)) {    carry = (*u++) + 1;    (*w++) = carry & DIGIT_MASK;    carry >>= BITS_PER_DIGIT;  }  // Copy the rest of u to the result.  while (u < uend)    (*w++) = (*u++);  // Propagate the carry if it is still 1.  if (carry)    (*w) = 1;}// Compute u += v, where u is vectors, and v is a scalar.void vec_add_small_on(int ulen, unsigned long *u, unsigned long v){#ifdef DEBUG_SYSTEMC  assert((ulen > 0) && (u != NULL));#endif  register int i = 0;  while (v && (i < ulen)) {    v += u[i];    u[i++] = v & DIGIT_MASK;    v >>= BITS_PER_DIGIT;  }#ifdef DEBUG_SYSTEMC  if( v != 0 ) {      SC_REPORT_WARNING( SC_ID_WITHOUT_MESSAGE_,                         "vec_add_small_on( int, unsigned long*, unsigned "			 "long ) : "			 "result of addition is wrapped around" );  }#endif}// Compute w = u - v, where w, u, and v are vectors.// - ulen >= vlen// - wlen >= sc_max(ulen, vlen)voidvec_sub(int ulen, const unsigned long *u,        int vlen, const unsigned long *v,        unsigned long *w){#ifdef DEBUG_SYSTEMC  assert((ulen > 0) && (u != NULL));  assert((vlen > 0) && (v != NULL));  assert(w != NULL);  assert(ulen >= vlen);#endif  const unsigned long *uend = (u + ulen);  const unsigned long *vend = (v + vlen);  register unsigned long borrow = 0;   // Also used as diff to save space.  // Subtract along the shorter v.  while (v < vend) {    borrow = ((*u++) + DIGIT_RADIX) - (*v++) - borrow;    (*w++) = borrow & DIGIT_MASK;    borrow = 1 - (borrow >> BITS_PER_DIGIT);  }  // Propagate the borrow.  while (borrow && (u < uend)) {    borrow = ((*u++) + DIGIT_RADIX) - 1;    (*w++) = borrow & DIGIT_MASK;    borrow = 1 - (borrow >> BITS_PER_DIGIT);  }#ifdef DEBUG_SYSTEMC  assert(borrow == 0);#endif  // Copy the rest of u to the result.  while (u < uend)    (*w++) = (*u++);}// Compute u = u - v, where u and v are vectors.// - u > v// - ulen >= vlenvoidvec_sub_on(int ulen, unsigned long *ubegin,           int vlen, const unsigned long *v){#ifdef DEBUG_SYSTEMC  assert((ulen > 0) && (ubegin != NULL));  assert((vlen > 0) && (v != NULL));  assert(ulen >= vlen);#endif

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?