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_nbutils.cpp -- External and friend functions for both sc_signed and 2312854Sgabeblack@google.com sc_unsigned classes. 2412854Sgabeblack@google.com 2512854Sgabeblack@google.com Original Author: Ali Dasdan, Synopsys, Inc. 2612854Sgabeblack@google.com 2712854Sgabeblack@google.com *****************************************************************************/ 2812854Sgabeblack@google.com 2912854Sgabeblack@google.com/***************************************************************************** 3012854Sgabeblack@google.com 3112854Sgabeblack@google.com MODIFICATION LOG - modifiers, enter your name, affiliation, date and 3212854Sgabeblack@google.com changes you are making here. 3312854Sgabeblack@google.com 3412854Sgabeblack@google.com Name, Affiliation, Date: 3512854Sgabeblack@google.com Description of Modification: 3612854Sgabeblack@google.com 3712854Sgabeblack@google.com *****************************************************************************/ 3812854Sgabeblack@google.com 3912854Sgabeblack@google.com 4012854Sgabeblack@google.com// $Log: sc_nbutils.cpp,v $ 4112854Sgabeblack@google.com// Revision 1.4 2011/08/24 22:05:46 acg 4212854Sgabeblack@google.com// Torsten Maehne: initialization changes to remove warnings. 4312854Sgabeblack@google.com// 4412854Sgabeblack@google.com// Revision 1.3 2011/02/18 20:19:15 acg 4512854Sgabeblack@google.com// Andy Goodrich: updating Copyright notice. 4612854Sgabeblack@google.com// 4712854Sgabeblack@google.com// Revision 1.2 2007/11/04 21:26:40 acg 4812854Sgabeblack@google.com// Andy Goodrich: added a buffer to the allocation of the q array to address 4912854Sgabeblack@google.com// an issue with references outside the array by 1 byte detected by valgrind. 5012854Sgabeblack@google.com// 5112854Sgabeblack@google.com// Revision 1.1.1.1 2006/12/15 20:20:05 acg 5212854Sgabeblack@google.com// SystemC 2.3 5312854Sgabeblack@google.com// 5412854Sgabeblack@google.com// Revision 1.3 2006/01/13 18:49:32 acg 5512854Sgabeblack@google.com// Added $Log command so that CVS check in comments are reproduced in the 5612854Sgabeblack@google.com// source. 5712854Sgabeblack@google.com// 5812854Sgabeblack@google.com 5912854Sgabeblack@google.com#include <cctype> 6012854Sgabeblack@google.com#include <cstdio> 6112854Sgabeblack@google.com#include <cstring> 6212854Sgabeblack@google.com#include <sstream> 6312854Sgabeblack@google.com 6413325Sgabeblack@google.com#include "systemc/ext/dt/bit/messages.hh" 6513325Sgabeblack@google.com#include "systemc/ext/dt/int/messages.hh" 6612854Sgabeblack@google.com#include "systemc/ext/dt/int/sc_nbutils.hh" 6712854Sgabeblack@google.com#include "systemc/ext/utils/functions.hh" 6812854Sgabeblack@google.com 6912854Sgabeblack@google.comnamespace sc_dt 7012854Sgabeblack@google.com{ 7112854Sgabeblack@google.com 7212854Sgabeblack@google.com// only used within vec_from_str (non-standard, deprecated) 7312854Sgabeblack@google.comstatic inline void 7412854Sgabeblack@google.comis_valid_base(sc_numrep base) 7512854Sgabeblack@google.com{ 7612854Sgabeblack@google.com switch (base) { 7712854Sgabeblack@google.com case SC_NOBASE: case SC_BIN: 7812854Sgabeblack@google.com case SC_OCT: case SC_DEC: 7912854Sgabeblack@google.com case SC_HEX: 8012854Sgabeblack@google.com break; 8112854Sgabeblack@google.com case SC_BIN_US: case SC_BIN_SM: 8212854Sgabeblack@google.com case SC_OCT_US: case SC_OCT_SM: 8312854Sgabeblack@google.com case SC_HEX_US: case SC_HEX_SM: 8412854Sgabeblack@google.com case SC_CSD: 8512854Sgabeblack@google.com SC_REPORT_ERROR("not implemented", 8612854Sgabeblack@google.com "is_valid_base( sc_numrep base ) : " 8712854Sgabeblack@google.com "bases SC_CSD, or ending in _US and _SM are " 8812854Sgabeblack@google.com "not supported"); 8912854Sgabeblack@google.com break; 9012854Sgabeblack@google.com default: 9112854Sgabeblack@google.com std::stringstream msg; 9212854Sgabeblack@google.com msg << "is_valid_base( sc_numrep base ) : base = " << base << 9312854Sgabeblack@google.com " is not valid"; 9413325Sgabeblack@google.com SC_REPORT_ERROR(sc_core::SC_ID_VALUE_NOT_VALID_, msg.str().c_str()); 9512854Sgabeblack@google.com } 9612854Sgabeblack@google.com} 9712854Sgabeblack@google.com 9812854Sgabeblack@google.com// ---------------------------------------------------------------------------- 9912854Sgabeblack@google.com// ENUM : sc_numrep 10012854Sgabeblack@google.com// 10112854Sgabeblack@google.com// Enumeration of number representations for character string conversion. 10212854Sgabeblack@google.com// ---------------------------------------------------------------------------- 10312854Sgabeblack@google.com 10412854Sgabeblack@google.comconst std::string 10512854Sgabeblack@google.comto_string(sc_numrep numrep) 10612854Sgabeblack@google.com{ 10712854Sgabeblack@google.com switch (numrep) { 10812854Sgabeblack@google.com#define CASE_ENUM2STR(Value) case Value: return #Value 10912854Sgabeblack@google.com 11012854Sgabeblack@google.com CASE_ENUM2STR(SC_DEC); 11112854Sgabeblack@google.com 11212854Sgabeblack@google.com CASE_ENUM2STR(SC_BIN); 11312854Sgabeblack@google.com CASE_ENUM2STR(SC_BIN_US); 11412854Sgabeblack@google.com CASE_ENUM2STR(SC_BIN_SM); 11512854Sgabeblack@google.com 11612854Sgabeblack@google.com CASE_ENUM2STR(SC_OCT); 11712854Sgabeblack@google.com CASE_ENUM2STR(SC_OCT_US); 11812854Sgabeblack@google.com CASE_ENUM2STR(SC_OCT_SM); 11912854Sgabeblack@google.com 12012854Sgabeblack@google.com CASE_ENUM2STR(SC_HEX); 12112854Sgabeblack@google.com CASE_ENUM2STR(SC_HEX_US); 12212854Sgabeblack@google.com CASE_ENUM2STR(SC_HEX_SM); 12312854Sgabeblack@google.com 12412854Sgabeblack@google.com CASE_ENUM2STR(SC_CSD); 12512854Sgabeblack@google.com 12612854Sgabeblack@google.com#undef CASE_ENUM2STR 12712854Sgabeblack@google.com 12812854Sgabeblack@google.com default: 12912854Sgabeblack@google.com return "unknown"; 13012854Sgabeblack@google.com } 13112854Sgabeblack@google.com} 13212854Sgabeblack@google.com 13312854Sgabeblack@google.com// ---------------------------------------------------------------------------- 13412854Sgabeblack@google.com// SECTION: General utility functions. 13512854Sgabeblack@google.com// ---------------------------------------------------------------------------- 13612854Sgabeblack@google.com 13712854Sgabeblack@google.com// Return the number of characters to advance the source of c. This 13812854Sgabeblack@google.com// function implements one move of the FSM to parse the following 13912854Sgabeblack@google.com// regular expressions. Error checking is done in the caller. 14012854Sgabeblack@google.com 14112854Sgabeblack@google.comsmall_type 14212854Sgabeblack@google.comfsm_move(char c, small_type &b, small_type &s, small_type &state) 14312854Sgabeblack@google.com{ 14412854Sgabeblack@google.com // Possible regular expressions (REs): 14512854Sgabeblack@google.com // Let N = any digit depending on the base. 14612854Sgabeblack@google.com // 1. [0|1|..|9]N* 14712854Sgabeblack@google.com // 2. [+|-][0|1|..|9]N* 14812854Sgabeblack@google.com // 3. 0[b|B|d|D|o|O|x|X][0|1|..|F]N* 14912854Sgabeblack@google.com // 4. [+|-]?0[b|B|d|D|o|O|x|X][0|1|..|F]N* 15012854Sgabeblack@google.com // 15112854Sgabeblack@google.com // The finite state machine (FMS) to parse these regular expressions 15212854Sgabeblack@google.com // has 4 states, 0 to 3. 0 is the initial state and 3 is the final 15312854Sgabeblack@google.com // state. 15412854Sgabeblack@google.com // 15512854Sgabeblack@google.com // Default sign = SC_POS, default base = NB_DEFAULT_BASE. 15612854Sgabeblack@google.com 15712854Sgabeblack@google.com switch (state) { 15812854Sgabeblack@google.com case 0: // The initial state. 15912854Sgabeblack@google.com switch (c) { 16012854Sgabeblack@google.com case '0': s = SC_POS; state = 1; return 0; // RE 1 or 3 16112854Sgabeblack@google.com case '+': s = SC_POS; state = 2; return 1; // RE 2 16212854Sgabeblack@google.com case '-': s = SC_NEG; state = 2; return 1; // RE 2 16312854Sgabeblack@google.com default: 16412854Sgabeblack@google.com s = SC_POS; b = NB_DEFAULT_BASE; state = 3; return 0; // RE 1 16512854Sgabeblack@google.com } 16612854Sgabeblack@google.com // break; //unreachable code 16712854Sgabeblack@google.com case 1: // 0... 16812854Sgabeblack@google.com switch (c) { 16912854Sgabeblack@google.com case 'x': case 'X': b = SC_HEX; state = 3; return 2; // RE 3 or 4 17012854Sgabeblack@google.com case 'd': case 'D': b = SC_DEC; state = 3; return 2; // RE 3 or 4 17112854Sgabeblack@google.com case 'o': case 'O': b = SC_OCT; state = 3; return 2; // RE 3 or 4 17212854Sgabeblack@google.com case 'b': case 'B': b = SC_BIN; state = 3; return 2; // RE 3 or 4 17312854Sgabeblack@google.com default: b = NB_DEFAULT_BASE; state = 3; return 0; // RE 1 17412854Sgabeblack@google.com } 17512854Sgabeblack@google.com // break; //unreachable code 17612854Sgabeblack@google.com case 2: // +... or -... 17712854Sgabeblack@google.com switch (c) { 17812854Sgabeblack@google.com case '0': state = 1; return 0; // RE 2 or 4 17912854Sgabeblack@google.com default: b = NB_DEFAULT_BASE; state = 3; return 0; // RE 2 18012854Sgabeblack@google.com } 18112854Sgabeblack@google.com // break; //unreachable code 18212854Sgabeblack@google.com case 3: // The final state. 18312854Sgabeblack@google.com break; 18412854Sgabeblack@google.com default: 18512854Sgabeblack@google.com // Any other state is not possible. 18612854Sgabeblack@google.com sc_assert((0 <= state) && (state <= 3)); 18712854Sgabeblack@google.com } // switch 18812854Sgabeblack@google.com return 0; 18912854Sgabeblack@google.com} 19012854Sgabeblack@google.com 19112854Sgabeblack@google.com 19212854Sgabeblack@google.com// Get base b and sign s of the number in the char string v. Return a 19312854Sgabeblack@google.com// pointer to the first char after the point where b and s are 19412854Sgabeblack@google.com// determined or where the end of v is reached. The input string v has 19512854Sgabeblack@google.com// to be null terminated. 19612854Sgabeblack@google.comconst char * 19712854Sgabeblack@google.comget_base_and_sign(const char *v, small_type &b, small_type &s) 19812854Sgabeblack@google.com{ 19912854Sgabeblack@google.com#ifdef DEBUG_SYSTEMC 20012854Sgabeblack@google.com sc_assert(v != NULL); 20112854Sgabeblack@google.com#endif 20212854Sgabeblack@google.com const small_type STATE_START = 0; 20312854Sgabeblack@google.com const small_type STATE_FINISH = 3; 20412854Sgabeblack@google.com 20512854Sgabeblack@google.com // Default sign = SC_POS, default base = 10. 20612854Sgabeblack@google.com s = SC_POS; 20712854Sgabeblack@google.com b = NB_DEFAULT_BASE; 20812854Sgabeblack@google.com 20912854Sgabeblack@google.com small_type state = STATE_START; 21012854Sgabeblack@google.com small_type nskip = 0; // Skip that many chars. 21112854Sgabeblack@google.com const char *u = v; 21212854Sgabeblack@google.com 21312854Sgabeblack@google.com while (*u) { 21412854Sgabeblack@google.com if (isspace(*u)) { // Skip white space. 21512854Sgabeblack@google.com ++u; 21612854Sgabeblack@google.com } else { 21712854Sgabeblack@google.com nskip += fsm_move(*u, b, s, state); 21812854Sgabeblack@google.com if (state == STATE_FINISH) 21912854Sgabeblack@google.com break; 22012854Sgabeblack@google.com else 22112854Sgabeblack@google.com ++u; 22212854Sgabeblack@google.com } 22312854Sgabeblack@google.com } 22412854Sgabeblack@google.com 22512854Sgabeblack@google.com // Test to see if the above loop executed more than it should 22612854Sgabeblack@google.com // have. The max number of skipped chars is equal to the length of 22712854Sgabeblack@google.com // the longest format specifier, e.g., "-0x". 22812854Sgabeblack@google.com sc_assert(nskip <= 3); 22912854Sgabeblack@google.com 23012854Sgabeblack@google.com v += nskip; 23112854Sgabeblack@google.com 23212854Sgabeblack@google.com // Handles empty strings or strings without any digits after the 23312854Sgabeblack@google.com // base or base and sign specifier. 23412854Sgabeblack@google.com if (*v == '\0') { 23512854Sgabeblack@google.com static const char msg[] = 23612854Sgabeblack@google.com "get_base_and_sign( const char* v, small_type&, small_type& ) : " 23712854Sgabeblack@google.com "v = \"\" is not valid"; 23813325Sgabeblack@google.com SC_REPORT_ERROR(sc_core::SC_ID_CONVERSION_FAILED_, msg); 23912854Sgabeblack@google.com } 24012854Sgabeblack@google.com return v; 24112854Sgabeblack@google.com} 24212854Sgabeblack@google.com 24312854Sgabeblack@google.com//----------------------------------------------------------------------------- 24412854Sgabeblack@google.com//"parse_binary_bits" 24512854Sgabeblack@google.com// 24612854Sgabeblack@google.com// This function parses the supplied string into the supplied vector as a 24712854Sgabeblack@google.com// right justified bit value. 24812854Sgabeblack@google.com// src_p -> character string representing the bits to be parsed. 24912854Sgabeblack@google.com// dst_n = number of words in data_p and ctrl_p. 25012854Sgabeblack@google.com// data_p -> words w/BITS_PER_DIGIT bits to receive the value's data bits. 25112854Sgabeblack@google.com// ctrl_p -> words w/BITS_PER_DIGIT bits to receive the value's control 25212854Sgabeblack@google.com// bits, or zero. 25312854Sgabeblack@google.com// Result is true if value was non-zero. 25412854Sgabeblack@google.com//----------------------------------------------------------------------------- 25512854Sgabeblack@google.comvoid 25612854Sgabeblack@google.comparse_binary_bits(const char *src_p, int dst_n, 25712854Sgabeblack@google.com sc_digit *data_p, sc_digit *ctrl_p) 25812854Sgabeblack@google.com{ 25912854Sgabeblack@google.com int bit_i; // Number of bit now processing. 26012854Sgabeblack@google.com sc_digit ctrl; // Control word now assembling. 26112854Sgabeblack@google.com sc_digit data; // Data word now assembling. 26212854Sgabeblack@google.com int delta_n; // src_n - dst_n*BITS_PER_DIGIT. 26312854Sgabeblack@google.com int src_i; // Index in src_p now accessing (left to right). 26412854Sgabeblack@google.com int src_n; // Length of source that is left in bits. 26512854Sgabeblack@google.com int word_i; // Bit within word now accessing (left to right). 26612854Sgabeblack@google.com 26712854Sgabeblack@google.com // MAKE SURE WE HAVE A STRING TO PARSE: 26812854Sgabeblack@google.com if (src_p == 0) { 26913325Sgabeblack@google.com SC_REPORT_ERROR(sc_core::SC_ID_CONVERSION_FAILED_, 27012854Sgabeblack@google.com "character string is zero"); 27112854Sgabeblack@google.com return; 27212854Sgabeblack@google.com } 27312854Sgabeblack@google.com if (*src_p == 0) { 27413325Sgabeblack@google.com SC_REPORT_ERROR(sc_core::SC_ID_CONVERSION_FAILED_, 27512854Sgabeblack@google.com "character string is empty"); 27612854Sgabeblack@google.com return; 27712854Sgabeblack@google.com } 27812854Sgabeblack@google.com 27912854Sgabeblack@google.com 28012854Sgabeblack@google.com // INDEX INTO THE SOURCE TO A DEPTH THAT WILL ACCOMODATE OUR SIZE: 28112854Sgabeblack@google.com // 28212854Sgabeblack@google.com // If the source is smaller than our value initialize our value to zero. 28312854Sgabeblack@google.com 28412854Sgabeblack@google.com src_n = strlen(src_p); 28512854Sgabeblack@google.com delta_n = src_n - (dst_n*BITS_PER_DIGIT); 28612854Sgabeblack@google.com if (delta_n > 0) { 28712854Sgabeblack@google.com src_p = &src_p[delta_n]; 28812854Sgabeblack@google.com src_n -= delta_n; 28912854Sgabeblack@google.com } else { 29012854Sgabeblack@google.com for (word_i = 0; word_i < dst_n; word_i++) 29112854Sgabeblack@google.com data_p[word_i] = 0; 29212854Sgabeblack@google.com if (ctrl_p) 29312854Sgabeblack@google.com for (word_i = 0; word_i < dst_n; word_i++) 29412854Sgabeblack@google.com ctrl_p[word_i] = 0; 29512854Sgabeblack@google.com } 29612854Sgabeblack@google.com 29712854Sgabeblack@google.com // LOOP OVER THE SOURCE ASSEMBLING WORDS AND PLACING THEM IN OUR VALUE: 29812854Sgabeblack@google.com // 29912854Sgabeblack@google.com // We stride right to left through the source in BITS_PER_DIGIT chunks. 30012854Sgabeblack@google.com // Each of those chunks is processed from left to right a bit at a time. 30112854Sgabeblack@google.com // We process the high order word specially, since there are less bits. 30212854Sgabeblack@google.com src_n = src_n - BITS_PER_DIGIT; 30312854Sgabeblack@google.com for (word_i=0; word_i < dst_n; word_i++) { 30412854Sgabeblack@google.com src_i = src_n; 30512854Sgabeblack@google.com 30612854Sgabeblack@google.com // PARTIAL LAST WORD TO ASSEMBLE: 30712854Sgabeblack@google.com if (src_i < 0) { 30812854Sgabeblack@google.com src_n += BITS_PER_DIGIT; 30912854Sgabeblack@google.com data = 0; 31012854Sgabeblack@google.com ctrl = 0; 31112854Sgabeblack@google.com for (src_i = 0; src_i < src_n; src_i++) { 31212854Sgabeblack@google.com ctrl = ctrl << 1; 31312854Sgabeblack@google.com data = data << 1; 31412854Sgabeblack@google.com switch (src_p[src_i]) { 31512854Sgabeblack@google.com case 'X': 31612854Sgabeblack@google.com case 'x': ctrl = ctrl | 1; data = data | 1; break; 31712854Sgabeblack@google.com case '1': data = data | 1; break; 31812854Sgabeblack@google.com case 'Z': 31912854Sgabeblack@google.com case 'z': ctrl = ctrl | 1; break; 32012854Sgabeblack@google.com case '0': break; 32112854Sgabeblack@google.com default: 32212854Sgabeblack@google.com { 32312854Sgabeblack@google.com std::stringstream msg; 32412854Sgabeblack@google.com msg << "character string '" << src_p << 32512854Sgabeblack@google.com "' is not valid"; 32613325Sgabeblack@google.com SC_REPORT_ERROR(sc_core::SC_ID_CONVERSION_FAILED_, 32712854Sgabeblack@google.com msg.str().c_str()); 32812854Sgabeblack@google.com return; 32912854Sgabeblack@google.com } 33012854Sgabeblack@google.com break; 33112854Sgabeblack@google.com } 33212854Sgabeblack@google.com } 33312854Sgabeblack@google.com if (ctrl_p) 33412854Sgabeblack@google.com ctrl_p[word_i] = ctrl; 33512854Sgabeblack@google.com data_p[word_i] = data; 33612854Sgabeblack@google.com break; 33712854Sgabeblack@google.com } 33812854Sgabeblack@google.com 33912854Sgabeblack@google.com // FULL WORD TO BE ASSEMBLED: 34012854Sgabeblack@google.com ctrl = 0; 34112854Sgabeblack@google.com data = 0; 34212854Sgabeblack@google.com for (bit_i = 0; bit_i < BITS_PER_DIGIT; bit_i++) { 34312854Sgabeblack@google.com ctrl = ctrl << 1; 34412854Sgabeblack@google.com data = data << 1; 34512854Sgabeblack@google.com switch (src_p[src_i++]) { 34612854Sgabeblack@google.com case 'X': 34712854Sgabeblack@google.com case 'x': ctrl = ctrl | 1; data = data | 1; break; 34812854Sgabeblack@google.com case '1': data = data | 1; break; 34912854Sgabeblack@google.com case 'Z': 35012854Sgabeblack@google.com case 'z': ctrl = ctrl | 1; break; 35112854Sgabeblack@google.com case '0': break; 35212854Sgabeblack@google.com default: 35312854Sgabeblack@google.com { 35412854Sgabeblack@google.com std::stringstream msg; 35512854Sgabeblack@google.com msg << "character string '" << src_p << 35612854Sgabeblack@google.com "' is not valid"; 35713325Sgabeblack@google.com SC_REPORT_ERROR(sc_core::SC_ID_CONVERSION_FAILED_, 35812854Sgabeblack@google.com msg.str().c_str()); 35912854Sgabeblack@google.com return; 36012854Sgabeblack@google.com } 36112854Sgabeblack@google.com break; 36212854Sgabeblack@google.com } 36312854Sgabeblack@google.com } 36412854Sgabeblack@google.com if (ctrl_p) 36512854Sgabeblack@google.com ctrl_p[word_i] = ctrl; 36612854Sgabeblack@google.com data_p[word_i] = data; 36712854Sgabeblack@google.com src_n = src_n - BITS_PER_DIGIT; 36812854Sgabeblack@google.com } 36912854Sgabeblack@google.com} 37012854Sgabeblack@google.com 37112854Sgabeblack@google.com 37212854Sgabeblack@google.com//----------------------------------------------------------------------------- 37312854Sgabeblack@google.com//"parse_hex_bits" 37412854Sgabeblack@google.com// 37512854Sgabeblack@google.com// This function parses the supplied string into the supplied vector as a 37612854Sgabeblack@google.com// right justified bit value. 37712854Sgabeblack@google.com// src_p -> character string representing the bits to be parsed. 37812854Sgabeblack@google.com// dst_n = number of words in data_p and ctrl_p. 37912854Sgabeblack@google.com// data_p -> words w/32 bits to receive the value's data bits. 38012854Sgabeblack@google.com// ctrl_p -> words w/32 bits to receive the value's control bits, 38112854Sgabeblack@google.com// or zero. 38212854Sgabeblack@google.com// Result is true if value was non-zero. 38312854Sgabeblack@google.com//----------------------------------------------------------------------------- 38412854Sgabeblack@google.comvoid 38512854Sgabeblack@google.comparse_hex_bits(const char *src_p, int dst_n, 38612854Sgabeblack@google.com sc_digit *data_p, sc_digit *ctrl_p) 38712854Sgabeblack@google.com{ 38812854Sgabeblack@google.com sc_digit ctrl; // Control word now assembling. 38912854Sgabeblack@google.com sc_digit data; // Data word now assembling. 39012854Sgabeblack@google.com int delta_n; // src_n - dst_n*BITS_PER_DIGIT. 39112854Sgabeblack@google.com int digit_i; // Number of digit now processing. 39212854Sgabeblack@google.com int src_i; // Index in src_p now accessing (left to right). 39312854Sgabeblack@google.com int src_n; // Length of source that is left in bits. 39412854Sgabeblack@google.com int word_i; // Bit within word now accessing (left to right). 39512854Sgabeblack@google.com 39612854Sgabeblack@google.com // MAKE SURE WE HAVE A STRING TO PARSE: 39712854Sgabeblack@google.com if (src_p == 0) { 39813325Sgabeblack@google.com SC_REPORT_ERROR(sc_core::SC_ID_CONVERSION_FAILED_, 39912854Sgabeblack@google.com "character string is zero"); 40012854Sgabeblack@google.com return; 40112854Sgabeblack@google.com } 40212854Sgabeblack@google.com if (*src_p == 0) { 40313325Sgabeblack@google.com SC_REPORT_ERROR(sc_core::SC_ID_CONVERSION_FAILED_, 40412854Sgabeblack@google.com "character string is empty"); 40512854Sgabeblack@google.com return; 40612854Sgabeblack@google.com } 40712854Sgabeblack@google.com 40812854Sgabeblack@google.com // INDEX INTO THE SOURCE TO A DEPTH THAT WILL ACCOMODATE OUR SIZE: 40912854Sgabeblack@google.com // 41012854Sgabeblack@google.com // If the source is smaller than our value initialize our value to zero. 41112854Sgabeblack@google.com src_n = strlen(src_p); 41212854Sgabeblack@google.com delta_n = src_n - (dst_n*8); 41312854Sgabeblack@google.com if (delta_n > 0) { 41412854Sgabeblack@google.com src_p = &src_p[delta_n]; 41512854Sgabeblack@google.com src_n -= delta_n; 41612854Sgabeblack@google.com } else { 41712854Sgabeblack@google.com for (word_i = 0; word_i < dst_n; word_i++) 41812854Sgabeblack@google.com data_p[word_i] = 0; 41912854Sgabeblack@google.com if (ctrl_p) 42012854Sgabeblack@google.com for (word_i = 0; word_i < dst_n; word_i++) 42112854Sgabeblack@google.com ctrl_p[word_i] = 0; 42212854Sgabeblack@google.com } 42312854Sgabeblack@google.com 42412854Sgabeblack@google.com // LOOP OVER THE SOURCE ASSEMBLING WORDS AND PLACING THEM IN OUR VALUE: 42512854Sgabeblack@google.com // 42612854Sgabeblack@google.com // We stride right to left through the source in BITS_PER_DIGIT chunks. 42712854Sgabeblack@google.com // Each of those chunks is processed from left to right a bit at a time. 42812854Sgabeblack@google.com // We process the high order word specially, since there are less bits. 42912854Sgabeblack@google.com src_n = src_n - 8; 43012854Sgabeblack@google.com for (word_i = 0; word_i < dst_n; word_i++) { 43112854Sgabeblack@google.com src_i = src_n; 43212854Sgabeblack@google.com 43312854Sgabeblack@google.com // PARTIAL LAST WORD TO ASSEMBLE: 43412854Sgabeblack@google.com if (src_i < 0) { 43512854Sgabeblack@google.com src_n += 8; 43612854Sgabeblack@google.com data = 0; 43712854Sgabeblack@google.com ctrl = 0; 43812854Sgabeblack@google.com for (src_i = 0; src_i < src_n; src_i++) { 43912854Sgabeblack@google.com ctrl = ctrl << 4; 44012854Sgabeblack@google.com data = data << 4; 44112854Sgabeblack@google.com switch (src_p[src_i]) { 44212854Sgabeblack@google.com case 'X': 44312854Sgabeblack@google.com case 'x': ctrl = ctrl | 15; data = data | 15; break; 44412854Sgabeblack@google.com case 'F': 44512854Sgabeblack@google.com case 'f': data = data | 15; break; 44612854Sgabeblack@google.com case 'E': 44712854Sgabeblack@google.com case 'e': data = data | 14; break; 44812854Sgabeblack@google.com case 'D': 44912854Sgabeblack@google.com case 'd': data = data | 13; break; 45012854Sgabeblack@google.com case 'C': 45112854Sgabeblack@google.com case 'c': data = data | 12; break; 45212854Sgabeblack@google.com case 'B': 45312854Sgabeblack@google.com case 'b': data = data | 11; break; 45412854Sgabeblack@google.com case 'A': 45512854Sgabeblack@google.com case 'a': data = data | 10; break; 45612854Sgabeblack@google.com case '9': data = data | 9; break; 45712854Sgabeblack@google.com case '8': data = data | 8; break; 45812854Sgabeblack@google.com case '7': data = data | 7; break; 45912854Sgabeblack@google.com case '6': data = data | 6; break; 46012854Sgabeblack@google.com case '5': data = data | 5; break; 46112854Sgabeblack@google.com case '4': data = data | 4; break; 46212854Sgabeblack@google.com case '3': data = data | 3; break; 46312854Sgabeblack@google.com case '2': data = data | 2; break; 46412854Sgabeblack@google.com case '1': data = data | 1; break; 46512854Sgabeblack@google.com case '0': break; 46612854Sgabeblack@google.com case 'Z': 46712854Sgabeblack@google.com case 'z': ctrl = ctrl | 15; break; 46812854Sgabeblack@google.com default: 46912854Sgabeblack@google.com { 47012854Sgabeblack@google.com std::stringstream msg; 47112854Sgabeblack@google.com msg << "character string '" << src_p << 47212854Sgabeblack@google.com "' is not valid"; 47313325Sgabeblack@google.com SC_REPORT_ERROR(sc_core::SC_ID_CONVERSION_FAILED_, 47412854Sgabeblack@google.com msg.str().c_str()); 47512854Sgabeblack@google.com return; 47612854Sgabeblack@google.com } 47712854Sgabeblack@google.com break; 47812854Sgabeblack@google.com } 47912854Sgabeblack@google.com } 48012854Sgabeblack@google.com if (ctrl_p) 48112854Sgabeblack@google.com ctrl_p[word_i] = ctrl; 48212854Sgabeblack@google.com data_p[word_i] = data; 48312854Sgabeblack@google.com break; 48412854Sgabeblack@google.com } 48512854Sgabeblack@google.com 48612854Sgabeblack@google.com // FULL WORD TO BE ASSEMBLED: 48712854Sgabeblack@google.com ctrl = 0; 48812854Sgabeblack@google.com data = 0; 48912854Sgabeblack@google.com for (digit_i = 0; digit_i < 8; digit_i++) { 49012854Sgabeblack@google.com ctrl = ctrl << 4; 49112854Sgabeblack@google.com data = data << 4; 49212854Sgabeblack@google.com switch (src_p[src_i++]) { 49312854Sgabeblack@google.com case 'X': 49412854Sgabeblack@google.com case 'x': ctrl = ctrl | 15; data = data | 15; break; 49512854Sgabeblack@google.com case 'F': 49612854Sgabeblack@google.com case 'f': data = data | 15; break; 49712854Sgabeblack@google.com case 'E': 49812854Sgabeblack@google.com case 'e': data = data | 14; break; 49912854Sgabeblack@google.com case 'D': 50012854Sgabeblack@google.com case 'd': data = data | 13; break; 50112854Sgabeblack@google.com case 'C': 50212854Sgabeblack@google.com case 'c': data = data | 12; break; 50312854Sgabeblack@google.com case 'B': 50412854Sgabeblack@google.com case 'b': data = data | 11; break; 50512854Sgabeblack@google.com case 'A': 50612854Sgabeblack@google.com case 'a': data = data | 10; break; 50712854Sgabeblack@google.com case '9': data = data | 9; break; 50812854Sgabeblack@google.com case '8': data = data | 8; break; 50912854Sgabeblack@google.com case '7': data = data | 7; break; 51012854Sgabeblack@google.com case '6': data = data | 6; break; 51112854Sgabeblack@google.com case '5': data = data | 5; break; 51212854Sgabeblack@google.com case '4': data = data | 4; break; 51312854Sgabeblack@google.com case '3': data = data | 3; break; 51412854Sgabeblack@google.com case '2': data = data | 2; break; 51512854Sgabeblack@google.com case '1': data = data | 1; break; 51612854Sgabeblack@google.com case '0': break; 51712854Sgabeblack@google.com case 'Z': 51812854Sgabeblack@google.com case 'z': ctrl = ctrl | 15; break; 51912854Sgabeblack@google.com default: 52012854Sgabeblack@google.com { 52112854Sgabeblack@google.com std::stringstream msg; 52212854Sgabeblack@google.com msg << "character string '" << src_p << "' is not valid"; 52313325Sgabeblack@google.com SC_REPORT_ERROR(sc_core::SC_ID_CONVERSION_FAILED_, 52412854Sgabeblack@google.com msg.str().c_str() ); 52512854Sgabeblack@google.com return; 52612854Sgabeblack@google.com } 52712854Sgabeblack@google.com break; 52812854Sgabeblack@google.com } 52912854Sgabeblack@google.com } 53012854Sgabeblack@google.com if (ctrl_p) 53112854Sgabeblack@google.com ctrl_p[word_i] = ctrl; 53212854Sgabeblack@google.com data_p[word_i] = data; 53312854Sgabeblack@google.com src_n = src_n - BITS_PER_DIGIT; 53412854Sgabeblack@google.com } 53512854Sgabeblack@google.com} 53612854Sgabeblack@google.com 53712854Sgabeblack@google.com 53812854Sgabeblack@google.com// ---------------------------------------------------------------------------- 53912854Sgabeblack@google.com// SECTION: Utility functions involving unsigned vectors. 54012854Sgabeblack@google.com// ---------------------------------------------------------------------------- 54112854Sgabeblack@google.com 54212854Sgabeblack@google.com// Read u from a null terminated char string v. Note that operator>> 54312854Sgabeblack@google.com// in sc_nbcommon.cpp is similar to this function. 54412854Sgabeblack@google.comsmall_type 54512854Sgabeblack@google.comvec_from_str(int unb, int und, sc_digit *u, const char *v, sc_numrep base) 54612854Sgabeblack@google.com{ 54712854Sgabeblack@google.com 54812854Sgabeblack@google.com#ifdef DEBUG_SYSTEMC 54912854Sgabeblack@google.com sc_assert((unb > 0) && (und > 0) && (u != NULL)); 55012854Sgabeblack@google.com sc_assert(v != NULL); 55112854Sgabeblack@google.com#endif 55212854Sgabeblack@google.com is_valid_base(base); 55312854Sgabeblack@google.com 55412854Sgabeblack@google.com small_type b, s; // base and sign. 55512854Sgabeblack@google.com 55612854Sgabeblack@google.com v = get_base_and_sign(v, b, s); 55712854Sgabeblack@google.com 55812854Sgabeblack@google.com if (base != SC_NOBASE) { 55912854Sgabeblack@google.com if (b == NB_DEFAULT_BASE) { 56012854Sgabeblack@google.com b = base; 56112854Sgabeblack@google.com } else { 56212854Sgabeblack@google.com std::stringstream msg; 56312854Sgabeblack@google.com msg << "vec_from_str( int, int, sc_digit*, const char*, " << 56412854Sgabeblack@google.com "sc_numrep base ) : base = " << base << 56512854Sgabeblack@google.com " does not match the default base"; 56613325Sgabeblack@google.com SC_REPORT_ERROR(sc_core::SC_ID_CONVERSION_FAILED_, 56712854Sgabeblack@google.com msg.str().c_str()); 56812854Sgabeblack@google.com return 0; 56912854Sgabeblack@google.com } 57012854Sgabeblack@google.com } 57112854Sgabeblack@google.com 57212854Sgabeblack@google.com vec_zero(und, u); 57312854Sgabeblack@google.com 57412854Sgabeblack@google.com char c; 57512854Sgabeblack@google.com for (; (c = *v); ++v) { 57612854Sgabeblack@google.com if (isalnum(c)) { 57712854Sgabeblack@google.com small_type val; // Numeric value of a char. 57812854Sgabeblack@google.com 57912854Sgabeblack@google.com if (isalpha(c)) // Hex digit. 58012854Sgabeblack@google.com val = toupper(c) - 'A' + 10; 58112854Sgabeblack@google.com else 58212854Sgabeblack@google.com val = c - '0'; 58312854Sgabeblack@google.com 58412854Sgabeblack@google.com if (val >= b) { 58512854Sgabeblack@google.com std::stringstream msg; 58612854Sgabeblack@google.com msg << "vec_from_str( int, int, sc_digit*, const char*, " << 58712854Sgabeblack@google.com "sc_numrep base ) : '" << *v << "' is not a valid " << 58812854Sgabeblack@google.com "digit in base " << b; 58913325Sgabeblack@google.com SC_REPORT_ERROR(sc_core::SC_ID_CONVERSION_FAILED_, 59012854Sgabeblack@google.com msg.str().c_str()); 59112854Sgabeblack@google.com return 0; 59212854Sgabeblack@google.com } 59312854Sgabeblack@google.com 59412854Sgabeblack@google.com // digit = digit * b + val; 59512854Sgabeblack@google.com vec_mul_small_on(und, u, b); 59612854Sgabeblack@google.com 59712854Sgabeblack@google.com if (val) 59812854Sgabeblack@google.com vec_add_small_on(und, u, val); 59912854Sgabeblack@google.com } else { 60012854Sgabeblack@google.com std::stringstream msg; 60112854Sgabeblack@google.com msg << "vec_from_str( int, int, sc_digit*, const char*, " << 60212854Sgabeblack@google.com "sc_numrep base ) : '" << *v << "' is not a valid " << 60312854Sgabeblack@google.com "digit in base " << b; 60413325Sgabeblack@google.com SC_REPORT_ERROR(sc_core::SC_ID_CONVERSION_FAILED_, 60512854Sgabeblack@google.com msg.str().c_str()); 60612854Sgabeblack@google.com return 0; 60712854Sgabeblack@google.com } 60812854Sgabeblack@google.com } 60912854Sgabeblack@google.com 61012854Sgabeblack@google.com return convert_signed_SM_to_2C_to_SM(s, unb, und, u); 61112854Sgabeblack@google.com} 61212854Sgabeblack@google.com 61312854Sgabeblack@google.com 61412854Sgabeblack@google.com// All vec_ functions assume that the vector to hold the result, 61512854Sgabeblack@google.com// called w, has sufficient length to hold the result. For efficiency 61612854Sgabeblack@google.com// reasons, we do not test whether or not we are out of bounds. 61712854Sgabeblack@google.com 61812854Sgabeblack@google.com// Compute w = u + v, where w, u, and v are vectors. 61912854Sgabeblack@google.com// - ulen >= vlen 62012854Sgabeblack@google.com// - wlen >= sc_max(ulen, vlen) + 1 62112854Sgabeblack@google.comvoid 62212854Sgabeblack@google.comvec_add(int ulen, const sc_digit *u, int vlen, const sc_digit *v, sc_digit *w) 62312854Sgabeblack@google.com{ 62412854Sgabeblack@google.com#ifdef DEBUG_SYSTEMC 62512854Sgabeblack@google.com sc_assert((ulen > 0) && (u != NULL)); 62612854Sgabeblack@google.com sc_assert((vlen > 0) && (v != NULL)); 62712854Sgabeblack@google.com sc_assert(w != NULL); 62812854Sgabeblack@google.com sc_assert(ulen >= vlen); 62912854Sgabeblack@google.com#endif 63012854Sgabeblack@google.com 63112854Sgabeblack@google.com const sc_digit *uend = (u + ulen); 63212854Sgabeblack@google.com const sc_digit *vend = (v + vlen); 63312854Sgabeblack@google.com 63412854Sgabeblack@google.com sc_digit carry = 0; // Also used as sum to save space. 63512854Sgabeblack@google.com 63612854Sgabeblack@google.com // Add along the shorter v. 63712854Sgabeblack@google.com while (v < vend) { 63812854Sgabeblack@google.com carry += (*u++) + (*v++); 63912854Sgabeblack@google.com (*w++) = carry & DIGIT_MASK; 64012854Sgabeblack@google.com carry >>= BITS_PER_DIGIT; 64112854Sgabeblack@google.com } 64212854Sgabeblack@google.com 64312854Sgabeblack@google.com // Propagate the carry. 64412854Sgabeblack@google.com while (carry && (u < uend)) { 64512854Sgabeblack@google.com carry = (*u++) + 1; 64612854Sgabeblack@google.com (*w++) = carry & DIGIT_MASK; 64712854Sgabeblack@google.com carry >>= BITS_PER_DIGIT; 64812854Sgabeblack@google.com } 64912854Sgabeblack@google.com 65012854Sgabeblack@google.com // Copy the rest of u to the result. 65112854Sgabeblack@google.com while (u < uend) 65212854Sgabeblack@google.com (*w++) = (*u++); 65312854Sgabeblack@google.com 65412854Sgabeblack@google.com // Propagate the carry if it is still 1. 65512854Sgabeblack@google.com if (carry) 65612854Sgabeblack@google.com (*w) = 1; 65712854Sgabeblack@google.com} 65812854Sgabeblack@google.com 65912854Sgabeblack@google.com 66012854Sgabeblack@google.com// Compute u += v, where u and v are vectors. 66112854Sgabeblack@google.com// - ulen >= vlen 66212854Sgabeblack@google.comvoid 66312854Sgabeblack@google.comvec_add_on(int ulen, sc_digit *ubegin, int vlen, const sc_digit *v) 66412854Sgabeblack@google.com{ 66512854Sgabeblack@google.com#ifdef DEBUG_SYSTEMC 66612854Sgabeblack@google.com sc_assert((ulen > 0) && (ubegin != NULL)); 66712854Sgabeblack@google.com sc_assert((vlen > 0) && (v != NULL)); 66812854Sgabeblack@google.com sc_assert(ulen >= vlen); 66912854Sgabeblack@google.com#endif 67012854Sgabeblack@google.com 67112854Sgabeblack@google.com sc_digit *u = ubegin; 67212854Sgabeblack@google.com const sc_digit *uend = (u + ulen); 67312854Sgabeblack@google.com const sc_digit *vend = (v + vlen); 67412854Sgabeblack@google.com 67512854Sgabeblack@google.com sc_digit carry = 0; // Also used as sum to save space. 67612854Sgabeblack@google.com 67712854Sgabeblack@google.com // Add along the shorter v. 67812854Sgabeblack@google.com while (v < vend) { 67912854Sgabeblack@google.com carry += (*u) + (*v++); 68012854Sgabeblack@google.com (*u++) = carry & DIGIT_MASK; 68112854Sgabeblack@google.com carry >>= BITS_PER_DIGIT; 68212854Sgabeblack@google.com } 68312854Sgabeblack@google.com 68412854Sgabeblack@google.com // Propagate the carry. 68512854Sgabeblack@google.com while (carry && (u < uend)) { 68612854Sgabeblack@google.com carry = (*u) + 1; 68712854Sgabeblack@google.com (*u++) = carry & DIGIT_MASK; 68812854Sgabeblack@google.com carry >>= BITS_PER_DIGIT; 68912854Sgabeblack@google.com } 69012854Sgabeblack@google.com 69112854Sgabeblack@google.com#ifdef DEBUG_SYSTEMC 69212854Sgabeblack@google.com if (carry != 0) { 69312854Sgabeblack@google.com SC_REPORT_WARNING(sc_core::SC_ID_WITHOUT_MESSAGE_, 69412854Sgabeblack@google.com "vec_add_on( int, sc_digit*, int, const " 69512854Sgabeblack@google.com "sc_digit* ) : " 69612854Sgabeblack@google.com "result of addition is wrapped around"); 69712854Sgabeblack@google.com } 69812854Sgabeblack@google.com#endif 69912854Sgabeblack@google.com} 70012854Sgabeblack@google.com 70112854Sgabeblack@google.com 70212854Sgabeblack@google.com// Compute u += v, where u and v are vectors. 70312854Sgabeblack@google.com// - ulen < vlen 70412854Sgabeblack@google.comvoid 70512854Sgabeblack@google.comvec_add_on2(int ulen, sc_digit *ubegin, int, 70612854Sgabeblack@google.com#ifdef DEBUG_SYSTEMC 70712854Sgabeblack@google.com vlen, 70812854Sgabeblack@google.com#endif 70912854Sgabeblack@google.com const sc_digit *v) 71012854Sgabeblack@google.com{ 71112854Sgabeblack@google.com#ifdef DEBUG_SYSTEMC 71212854Sgabeblack@google.com sc_assert((ulen > 0) && (ubegin != NULL)); 71312854Sgabeblack@google.com sc_assert((vlen > 0) && (v != NULL)); 71412854Sgabeblack@google.com sc_assert(ulen < vlen); 71512854Sgabeblack@google.com#endif 71612854Sgabeblack@google.com 71712854Sgabeblack@google.com sc_digit *u = ubegin; 71812854Sgabeblack@google.com const sc_digit *uend = (u + ulen); 71912854Sgabeblack@google.com 72012854Sgabeblack@google.com sc_digit carry = 0; // Also used as sum to save space. 72112854Sgabeblack@google.com 72212854Sgabeblack@google.com // Add along the shorter u. 72312854Sgabeblack@google.com while (u < uend) { 72412854Sgabeblack@google.com carry += (*u) + (*v++); 72512854Sgabeblack@google.com (*u++) = carry & DIGIT_MASK; 72612854Sgabeblack@google.com carry >>= BITS_PER_DIGIT; 72712854Sgabeblack@google.com } 72812854Sgabeblack@google.com 72912854Sgabeblack@google.com#ifdef DEBUG_SYSTEMC 73012854Sgabeblack@google.com if (carry != 0) { 73112854Sgabeblack@google.com SC_REPORT_WARNING(sc_core::SC_ID_WITHOUT_MESSAGE_, 73212854Sgabeblack@google.com "vec_add_on2( int, sc_digit*, int, const " 73312854Sgabeblack@google.com "sc_digit* ) : " 73412854Sgabeblack@google.com "result of addition is wrapped around"); 73512854Sgabeblack@google.com } 73612854Sgabeblack@google.com#endif 73712854Sgabeblack@google.com} 73812854Sgabeblack@google.com 73912854Sgabeblack@google.com 74012854Sgabeblack@google.com// Compute w = u + v, where w and u are vectors, and v is a scalar. 74112854Sgabeblack@google.comvoid 74212854Sgabeblack@google.comvec_add_small(int ulen, const sc_digit *u, sc_digit v, sc_digit *w) 74312854Sgabeblack@google.com{ 74412854Sgabeblack@google.com#ifdef DEBUG_SYSTEMC 74512854Sgabeblack@google.com sc_assert((ulen > 0) && (u != NULL)); 74612854Sgabeblack@google.com sc_assert(w != NULL); 74712854Sgabeblack@google.com#endif 74812854Sgabeblack@google.com 74912854Sgabeblack@google.com const sc_digit *uend = (u + ulen); 75012854Sgabeblack@google.com 75112854Sgabeblack@google.com // Add along the shorter v. 75212854Sgabeblack@google.com sc_digit carry = (*u++) + v; 75312854Sgabeblack@google.com (*w++) = carry & DIGIT_MASK; 75412854Sgabeblack@google.com carry >>= BITS_PER_DIGIT; 75512854Sgabeblack@google.com 75612854Sgabeblack@google.com // Propagate the carry. 75712854Sgabeblack@google.com while (carry && (u < uend)) { 75812854Sgabeblack@google.com carry = (*u++) + 1; 75912854Sgabeblack@google.com (*w++) = carry & DIGIT_MASK; 76012854Sgabeblack@google.com carry >>= BITS_PER_DIGIT; 76112854Sgabeblack@google.com } 76212854Sgabeblack@google.com 76312854Sgabeblack@google.com // Copy the rest of u to the result. 76412854Sgabeblack@google.com while (u < uend) 76512854Sgabeblack@google.com (*w++) = (*u++); 76612854Sgabeblack@google.com 76712854Sgabeblack@google.com // Propagate the carry if it is still 1. 76812854Sgabeblack@google.com if (carry) 76912854Sgabeblack@google.com (*w) = 1; 77012854Sgabeblack@google.com} 77112854Sgabeblack@google.com 77212854Sgabeblack@google.com// Compute u += v, where u is vectors, and v is a scalar. 77312854Sgabeblack@google.comvoid 77412854Sgabeblack@google.comvec_add_small_on(int ulen, sc_digit *u, sc_digit v) 77512854Sgabeblack@google.com{ 77612854Sgabeblack@google.com#ifdef DEBUG_SYSTEMC 77712854Sgabeblack@google.com sc_assert((ulen > 0) && (u != NULL)); 77812854Sgabeblack@google.com#endif 77912854Sgabeblack@google.com 78012854Sgabeblack@google.com int i = 0; 78112854Sgabeblack@google.com 78212854Sgabeblack@google.com while (v && (i < ulen)) { 78312854Sgabeblack@google.com v += u[i]; 78412854Sgabeblack@google.com u[i++] = v & DIGIT_MASK; 78512854Sgabeblack@google.com v >>= BITS_PER_DIGIT; 78612854Sgabeblack@google.com } 78712854Sgabeblack@google.com 78812854Sgabeblack@google.com#ifdef DEBUG_SYSTEMC 78912854Sgabeblack@google.com if (v != 0) { 79012854Sgabeblack@google.com SC_REPORT_WARNING(sc_core::SC_ID_WITHOUT_MESSAGE_, 79112854Sgabeblack@google.com "vec_add_small_on( int, sc_digit*, unsigned " 79212854Sgabeblack@google.com "long ) : " 79312854Sgabeblack@google.com "result of addition is wrapped around"); 79412854Sgabeblack@google.com } 79512854Sgabeblack@google.com#endif 79612854Sgabeblack@google.com} 79712854Sgabeblack@google.com 79812854Sgabeblack@google.com// Compute w = u - v, where w, u, and v are vectors. 79912854Sgabeblack@google.com// - ulen >= vlen 80012854Sgabeblack@google.com// - wlen >= sc_max(ulen, vlen) 80112854Sgabeblack@google.comvoid 80212854Sgabeblack@google.comvec_sub(int ulen, const sc_digit *u, int vlen, const sc_digit *v, sc_digit *w) 80312854Sgabeblack@google.com{ 80412854Sgabeblack@google.com#ifdef DEBUG_SYSTEMC 80512854Sgabeblack@google.com sc_assert((ulen > 0) && (u != NULL)); 80612854Sgabeblack@google.com sc_assert((vlen > 0) && (v != NULL)); 80712854Sgabeblack@google.com sc_assert(w != NULL); 80812854Sgabeblack@google.com sc_assert(ulen >= vlen); 80912854Sgabeblack@google.com#endif 81012854Sgabeblack@google.com 81112854Sgabeblack@google.com const sc_digit *uend = (u + ulen); 81212854Sgabeblack@google.com const sc_digit *vend = (v + vlen); 81312854Sgabeblack@google.com 81412854Sgabeblack@google.com sc_digit borrow = 0; // Also used as diff to save space. 81512854Sgabeblack@google.com 81612854Sgabeblack@google.com // Subtract along the shorter v. 81712854Sgabeblack@google.com while (v < vend) { 81812854Sgabeblack@google.com borrow = ((*u++) + DIGIT_RADIX) - (*v++) - borrow; 81912854Sgabeblack@google.com (*w++) = borrow & DIGIT_MASK; 82012854Sgabeblack@google.com borrow = 1 - (borrow >> BITS_PER_DIGIT); 82112854Sgabeblack@google.com } 82212854Sgabeblack@google.com 82312854Sgabeblack@google.com // Propagate the borrow. 82412854Sgabeblack@google.com while (borrow && (u < uend)) { 82512854Sgabeblack@google.com borrow = ((*u++) + DIGIT_RADIX) - 1; 82612854Sgabeblack@google.com (*w++) = borrow & DIGIT_MASK; 82712854Sgabeblack@google.com borrow = 1 - (borrow >> BITS_PER_DIGIT); 82812854Sgabeblack@google.com } 82912854Sgabeblack@google.com 83012854Sgabeblack@google.com#ifdef DEBUG_SYSTEMC 83112854Sgabeblack@google.com sc_assert(borrow == 0); 83212854Sgabeblack@google.com#endif 83312854Sgabeblack@google.com 83412854Sgabeblack@google.com // Copy the rest of u to the result. 83512854Sgabeblack@google.com while (u < uend) 83612854Sgabeblack@google.com (*w++) = (*u++); 83712854Sgabeblack@google.com} 83812854Sgabeblack@google.com 83912854Sgabeblack@google.com// Compute u = u - v, where u and v are vectors. 84012854Sgabeblack@google.com// - u > v 84112854Sgabeblack@google.com// - ulen >= vlen 84212854Sgabeblack@google.comvoid 84312854Sgabeblack@google.comvec_sub_on(int ulen, sc_digit *ubegin, int vlen, const sc_digit *v) 84412854Sgabeblack@google.com{ 84512854Sgabeblack@google.com#ifdef DEBUG_SYSTEMC 84612854Sgabeblack@google.com sc_assert((ulen > 0) && (ubegin != NULL)); 84712854Sgabeblack@google.com sc_assert((vlen > 0) && (v != NULL)); 84812854Sgabeblack@google.com sc_assert(ulen >= vlen); 84912854Sgabeblack@google.com#endif 85012854Sgabeblack@google.com 85112854Sgabeblack@google.com sc_digit *u = ubegin; 85212854Sgabeblack@google.com const sc_digit *uend = (u + ulen); 85312854Sgabeblack@google.com const sc_digit *vend = (v + vlen); 85412854Sgabeblack@google.com 85512854Sgabeblack@google.com sc_digit borrow = 0; // Also used as diff to save space. 85612854Sgabeblack@google.com 85712854Sgabeblack@google.com // Subtract along the shorter v. 85812854Sgabeblack@google.com while (v < vend) { 85912854Sgabeblack@google.com borrow = ((*u) + DIGIT_RADIX) - (*v++) - borrow; 86012854Sgabeblack@google.com (*u++) = borrow & DIGIT_MASK; 86112854Sgabeblack@google.com borrow = 1 - (borrow >> BITS_PER_DIGIT); 86212854Sgabeblack@google.com } 86312854Sgabeblack@google.com 86412854Sgabeblack@google.com // Propagate the borrow. 86512854Sgabeblack@google.com while (borrow && (u < uend)) { 86612854Sgabeblack@google.com borrow = ((*u) + DIGIT_RADIX) - 1; 86712854Sgabeblack@google.com (*u++) = borrow & DIGIT_MASK; 86812854Sgabeblack@google.com borrow = 1 - (borrow >> BITS_PER_DIGIT); 86912854Sgabeblack@google.com } 87012854Sgabeblack@google.com 87112854Sgabeblack@google.com#ifdef DEBUG_SYSTEMC 87212854Sgabeblack@google.com sc_assert(borrow == 0); 87312854Sgabeblack@google.com#endif 87412854Sgabeblack@google.com} 87512854Sgabeblack@google.com 87612854Sgabeblack@google.com// Compute u = v - u, where u and v are vectors. 87712854Sgabeblack@google.com// - v > u 87812854Sgabeblack@google.com// - ulen <= vlen or ulen > ulen 87912854Sgabeblack@google.comvoid 88012854Sgabeblack@google.comvec_sub_on2(int ulen, sc_digit *ubegin, int vlen, const sc_digit *v) 88112854Sgabeblack@google.com{ 88212854Sgabeblack@google.com#ifdef DEBUG_SYSTEMC 88312854Sgabeblack@google.com sc_assert((ulen > 0) && (ubegin != NULL)); 88412854Sgabeblack@google.com sc_assert((vlen > 0) && (v != NULL)); 88512854Sgabeblack@google.com#endif 88612854Sgabeblack@google.com 88712854Sgabeblack@google.com sc_digit *u = ubegin; 88812854Sgabeblack@google.com const sc_digit *uend = (u + sc_min(ulen, vlen)); 88912854Sgabeblack@google.com 89012854Sgabeblack@google.com sc_digit borrow = 0; // Also used as diff to save space. 89112854Sgabeblack@google.com 89212854Sgabeblack@google.com // Subtract along the shorter u. 89312854Sgabeblack@google.com while (u < uend) { 89412854Sgabeblack@google.com borrow = ((*v++) + DIGIT_RADIX) - (*u) - borrow; 89512854Sgabeblack@google.com (*u++) = borrow & DIGIT_MASK; 89612854Sgabeblack@google.com borrow = 1 - (borrow >> BITS_PER_DIGIT); 89712854Sgabeblack@google.com } 89812854Sgabeblack@google.com 89912854Sgabeblack@google.com#ifdef DEBUG_SYSTEMC 90012854Sgabeblack@google.com if (borrow != 0) { 90112854Sgabeblack@google.com SC_REPORT_WARNING(sc_core::SC_ID_WITHOUT_MESSAGE_, 90212854Sgabeblack@google.com "vec_sub_on2( int, sc_digit*, int, const " 90312854Sgabeblack@google.com "sc_digit* ) : " 90412854Sgabeblack@google.com "result of subtraction is wrapped around"); 90512854Sgabeblack@google.com } 90612854Sgabeblack@google.com#endif 90712854Sgabeblack@google.com} 90812854Sgabeblack@google.com 90912854Sgabeblack@google.com// Compute w = u - v, where w and u are vectors, and v is a scalar. 91012854Sgabeblack@google.comvoid 91112854Sgabeblack@google.comvec_sub_small(int ulen, const sc_digit *u, sc_digit v, sc_digit *w) 91212854Sgabeblack@google.com{ 91312854Sgabeblack@google.com#ifdef DEBUG_SYSTEMC 91412854Sgabeblack@google.com sc_assert(ulen > 0); 91512854Sgabeblack@google.com sc_assert(u != NULL); 91612854Sgabeblack@google.com#endif 91712854Sgabeblack@google.com 91812854Sgabeblack@google.com const sc_digit *uend = (u + ulen); 91912854Sgabeblack@google.com 92012854Sgabeblack@google.com // Add along the shorter v. 92112854Sgabeblack@google.com sc_digit borrow = ((*u++) + DIGIT_RADIX) - v; 92212854Sgabeblack@google.com (*w++) = borrow & DIGIT_MASK; 92312854Sgabeblack@google.com borrow = 1 - (borrow >> BITS_PER_DIGIT); 92412854Sgabeblack@google.com 92512854Sgabeblack@google.com // Propagate the borrow. 92612854Sgabeblack@google.com while (borrow && (u < uend)) { 92712854Sgabeblack@google.com borrow = ((*u++) + DIGIT_RADIX) - 1; 92812854Sgabeblack@google.com (*w++) = borrow & DIGIT_MASK; 92912854Sgabeblack@google.com borrow = 1 - (borrow >> BITS_PER_DIGIT); 93012854Sgabeblack@google.com } 93112854Sgabeblack@google.com 93212854Sgabeblack@google.com#ifdef DEBUG_SYSTEMC 93312854Sgabeblack@google.com sc_assert(borrow == 0); 93412854Sgabeblack@google.com#endif 93512854Sgabeblack@google.com 93612854Sgabeblack@google.com // Copy the rest of u to the result. 93712854Sgabeblack@google.com while (u < uend) 93812854Sgabeblack@google.com (*w++) = (*u++); 93912854Sgabeblack@google.com} 94012854Sgabeblack@google.com 94112854Sgabeblack@google.com 94212854Sgabeblack@google.com// Compute u -= v, where u is vectors, and v is a scalar. 94312854Sgabeblack@google.comvoid 94412854Sgabeblack@google.comvec_sub_small_on(int ulen, sc_digit *u, sc_digit v) 94512854Sgabeblack@google.com{ 94612854Sgabeblack@google.com#ifdef DEBUG_SYSTEMC 94712854Sgabeblack@google.com sc_assert((ulen > 0) && (u != NULL)); 94812854Sgabeblack@google.com#endif 94912854Sgabeblack@google.com 95012854Sgabeblack@google.com for (int i = 0; i < ulen; ++i) { 95112854Sgabeblack@google.com v = (u[i] + DIGIT_RADIX) - v; 95212854Sgabeblack@google.com u[i] = v & DIGIT_MASK; 95312854Sgabeblack@google.com v = 1 - (v >> BITS_PER_DIGIT); 95412854Sgabeblack@google.com } 95512854Sgabeblack@google.com 95612854Sgabeblack@google.com#ifdef DEBUG_SYSTEMC 95712854Sgabeblack@google.com sc_assert(v == 0); 95812854Sgabeblack@google.com#endif 95912854Sgabeblack@google.com} 96012854Sgabeblack@google.com 96112854Sgabeblack@google.com// Compute w = u * v, where w, u, and v are vectors. 96212854Sgabeblack@google.comvoid 96312854Sgabeblack@google.comvec_mul(int ulen, const sc_digit *u, int vlen, const sc_digit *vbegin, 96412854Sgabeblack@google.com sc_digit *wbegin) 96512854Sgabeblack@google.com{ 96612854Sgabeblack@google.com 96712854Sgabeblack@google.com /* Consider u = Ax + B and v = Cx + D where x is equal to 96812854Sgabeblack@google.com HALF_DIGIT_RADIX. In other words, A is the higher half of u and 96912854Sgabeblack@google.com B is the lower half of u. The interpretation for v is 97012854Sgabeblack@google.com similar. Then, we have the following picture: 97112854Sgabeblack@google.com 97212854Sgabeblack@google.com u_h u_l 97312854Sgabeblack@google.com u: -------- -------- 97412854Sgabeblack@google.com A B 97512854Sgabeblack@google.com 97612854Sgabeblack@google.com v_h v_l 97712854Sgabeblack@google.com v: -------- -------- 97812854Sgabeblack@google.com C D 97912854Sgabeblack@google.com 98012854Sgabeblack@google.com result (d): 98112854Sgabeblack@google.com carry_before: -------- -------- 98212854Sgabeblack@google.com carry_h carry_l 98312854Sgabeblack@google.com result_before: -------- -------- -------- -------- 98412854Sgabeblack@google.com R1_h R1_l R0_h R0_l 98512854Sgabeblack@google.com -------- -------- 98612854Sgabeblack@google.com BD_h BD_l 98712854Sgabeblack@google.com -------- -------- 98812854Sgabeblack@google.com AD_h AD_l 98912854Sgabeblack@google.com -------- -------- 99012854Sgabeblack@google.com BC_h BC_l 99112854Sgabeblack@google.com -------- -------- 99212854Sgabeblack@google.com AC_h AC_l 99312854Sgabeblack@google.com result_after: -------- -------- -------- -------- 99412854Sgabeblack@google.com R1_h' R1_l' R0_h' R0_l' 99512854Sgabeblack@google.com 99612854Sgabeblack@google.com prod_l = R0_h|R0_l + B * D + 0|carry_l 99712854Sgabeblack@google.com = R0_h|R0_l + BD_h|BD_l + 0|carry_l 99812854Sgabeblack@google.com 99912854Sgabeblack@google.com prod_h = A * D + B * C + high_half(prod_l) + carry_h 100012854Sgabeblack@google.com = AD_h|AD_l + BC_h|BC_l + high_half(prod_l) + 0|carry_h 100112854Sgabeblack@google.com 100212854Sgabeblack@google.com carry = A * C + high_half(prod_h) 100312854Sgabeblack@google.com = AC_h|AC_l + high_half(prod_h) 100412854Sgabeblack@google.com 100512854Sgabeblack@google.com R0_l' = low_half(prod_l) 100612854Sgabeblack@google.com 100712854Sgabeblack@google.com R0_h' = low_half(prod_h) 100812854Sgabeblack@google.com 100912854Sgabeblack@google.com R0 = high_half(prod_h)|low_half(prod_l) 101012854Sgabeblack@google.com 101112854Sgabeblack@google.com where '|' is the concatenation operation and the suffixes 0 and 1 101212854Sgabeblack@google.com show the iteration number, i.e., 0 is the current iteration and 1 101312854Sgabeblack@google.com is the next iteration. 101412854Sgabeblack@google.com 101512854Sgabeblack@google.com NOTE: sc_max(prod_l, prod_h, carry) <= 2 * x^2 - 1, so any 101612854Sgabeblack@google.com of these numbers can be stored in a digit. 101712854Sgabeblack@google.com 101812854Sgabeblack@google.com NOTE: low_half(u) returns the lower BITS_PER_HALF_DIGIT of u, 101912854Sgabeblack@google.com whereas high_half(u) returns the rest of the bits, which may 102012854Sgabeblack@google.com contain more bits than BITS_PER_HALF_DIGIT. 102112854Sgabeblack@google.com */ 102212854Sgabeblack@google.com 102312854Sgabeblack@google.com#ifdef DEBUG_SYSTEMC 102412854Sgabeblack@google.com sc_assert((ulen > 0) && (u != NULL)); 102512854Sgabeblack@google.com sc_assert((vlen > 0) && (vbegin != NULL)); 102612854Sgabeblack@google.com sc_assert(wbegin != NULL); 102712854Sgabeblack@google.com#endif 102812854Sgabeblack@google.com 102912854Sgabeblack@google.com#define prod_h carry 103012854Sgabeblack@google.com const sc_digit *uend = (u + ulen); 103112854Sgabeblack@google.com const sc_digit *vend = (vbegin + vlen); 103212854Sgabeblack@google.com 103312854Sgabeblack@google.com while (u < uend) { 103412854Sgabeblack@google.com sc_digit u_h = (*u++); // A|B 103512854Sgabeblack@google.com sc_digit u_l = low_half(u_h); // B 103612854Sgabeblack@google.com u_h = high_half(u_h); // A 103712854Sgabeblack@google.com 103812854Sgabeblack@google.com#ifdef DEBUG_SYSTEMC 103912854Sgabeblack@google.com // The overflow bits must be zero. 104012854Sgabeblack@google.com sc_assert(u_h == (u_h & HALF_DIGIT_MASK)); 104112854Sgabeblack@google.com#endif 104212854Sgabeblack@google.com sc_digit carry = 0; 104312854Sgabeblack@google.com sc_digit *w = (wbegin++); 104412854Sgabeblack@google.com const sc_digit *v = vbegin; 104512854Sgabeblack@google.com 104612854Sgabeblack@google.com while (v < vend) { 104712854Sgabeblack@google.com sc_digit v_h = (*v++); // C|D 104812854Sgabeblack@google.com sc_digit v_l = low_half(v_h); // D 104912854Sgabeblack@google.com 105012854Sgabeblack@google.com v_h = high_half(v_h); // C 105112854Sgabeblack@google.com 105212854Sgabeblack@google.com#ifdef DEBUG_SYSTEMC 105312854Sgabeblack@google.com // The overflow bits must be zero. 105412854Sgabeblack@google.com sc_assert(v_h == (v_h & HALF_DIGIT_MASK)); 105512854Sgabeblack@google.com#endif 105612854Sgabeblack@google.com 105712854Sgabeblack@google.com sc_digit prod_l = (*w) + u_l * v_l + low_half(carry); 105812854Sgabeblack@google.com prod_h = u_h * v_l + u_l * v_h + 105912854Sgabeblack@google.com high_half(prod_l) + high_half(carry); 106012854Sgabeblack@google.com (*w++) = concat(low_half(prod_h), low_half(prod_l)); 106112854Sgabeblack@google.com carry = u_h * v_h + high_half(prod_h); 106212854Sgabeblack@google.com } 106312854Sgabeblack@google.com (*w) = carry; 106412854Sgabeblack@google.com } 106512854Sgabeblack@google.com#undef prod_h 106612854Sgabeblack@google.com} 106712854Sgabeblack@google.com 106812854Sgabeblack@google.com// Compute w = u * v, where w and u are vectors, and v is a scalar. 106912854Sgabeblack@google.com// - 0 < v < HALF_DIGIT_RADIX. 107012854Sgabeblack@google.comvoid 107112854Sgabeblack@google.comvec_mul_small(int ulen, const sc_digit *u, sc_digit v, sc_digit *w) 107212854Sgabeblack@google.com{ 107312854Sgabeblack@google.com#ifdef DEBUG_SYSTEMC 107412854Sgabeblack@google.com sc_assert((ulen > 0) && (u != NULL)); 107512854Sgabeblack@google.com sc_assert(w != NULL); 107612854Sgabeblack@google.com sc_assert((0 < v) && (v < HALF_DIGIT_RADIX)); 107712854Sgabeblack@google.com#endif 107812854Sgabeblack@google.com 107912854Sgabeblack@google.com#define prod_h carry 108012854Sgabeblack@google.com 108112854Sgabeblack@google.com const sc_digit *uend = (u + ulen); 108212854Sgabeblack@google.com sc_digit carry = 0; 108312854Sgabeblack@google.com while (u < uend) { 108412854Sgabeblack@google.com sc_digit u_AB = (*u++); 108512854Sgabeblack@google.com#ifdef DEBUG_SYSTEMC 108612854Sgabeblack@google.com // The overflow bits must be zero. 108712854Sgabeblack@google.com sc_assert(high_half(u_AB) == high_half_masked(u_AB)); 108812854Sgabeblack@google.com#endif 108912854Sgabeblack@google.com sc_digit prod_l = v * low_half(u_AB) + low_half(carry); 109012854Sgabeblack@google.com prod_h = v * high_half(u_AB) + high_half(prod_l) + high_half(carry); 109112854Sgabeblack@google.com (*w++) = concat(low_half(prod_h), low_half(prod_l)); 109212854Sgabeblack@google.com carry = high_half(prod_h); 109312854Sgabeblack@google.com } 109412854Sgabeblack@google.com (*w) = carry; 109512854Sgabeblack@google.com#undef prod_h 109612854Sgabeblack@google.com} 109712854Sgabeblack@google.com 109812854Sgabeblack@google.com// Compute u = u * v, where u is a vector, and v is a scalar. 109912854Sgabeblack@google.com// - 0 < v < HALF_DIGIT_RADIX. 110012854Sgabeblack@google.comvoid 110112854Sgabeblack@google.comvec_mul_small_on(int ulen, sc_digit *u, sc_digit v) 110212854Sgabeblack@google.com{ 110312854Sgabeblack@google.com#ifdef DEBUG_SYSTEMC 110412854Sgabeblack@google.com sc_assert((ulen > 0) && (u != NULL)); 110512854Sgabeblack@google.com sc_assert((0 < v) && (v < HALF_DIGIT_RADIX)); 110612854Sgabeblack@google.com#endif 110712854Sgabeblack@google.com 110812854Sgabeblack@google.com#define prod_h carry 110912854Sgabeblack@google.com sc_digit carry = 0; 111012854Sgabeblack@google.com for (int i = 0; i < ulen; ++i) { 111112854Sgabeblack@google.com#ifdef DEBUG_SYSTEMC 111212854Sgabeblack@google.com // The overflow bits must be zero. 111312854Sgabeblack@google.com sc_assert(high_half(u[i]) == high_half_masked(u[i])); 111412854Sgabeblack@google.com#endif 111512854Sgabeblack@google.com sc_digit prod_l = v * low_half(u[i]) + low_half(carry); 111612854Sgabeblack@google.com prod_h = v * high_half(u[i]) + high_half(prod_l) + high_half(carry); 111712854Sgabeblack@google.com u[i] = concat(low_half(prod_h), low_half(prod_l)); 111812854Sgabeblack@google.com carry = high_half(prod_h); 111912854Sgabeblack@google.com } 112012854Sgabeblack@google.com#undef prod_h 112112854Sgabeblack@google.com 112212854Sgabeblack@google.com#ifdef DEBUG_SYSTEMC 112312854Sgabeblack@google.com if (carry != 0) { 112412854Sgabeblack@google.com SC_REPORT_WARNING(sc_core::SC_ID_WITHOUT_MESSAGE_, 112512854Sgabeblack@google.com "vec_mul_small_on( int, sc_digit*, unsigned " 112612854Sgabeblack@google.com "long ) : " 112712854Sgabeblack@google.com "result of multiplication is wrapped around"); 112812854Sgabeblack@google.com } 112912854Sgabeblack@google.com#endif 113012854Sgabeblack@google.com} 113112854Sgabeblack@google.com 113212854Sgabeblack@google.com// Compute w = u / v, where w, u, and v are vectors. 113312854Sgabeblack@google.com// - u and v are assumed to have at least two digits as uchars. 113412854Sgabeblack@google.comvoid 113512854Sgabeblack@google.comvec_div_large(int ulen, const sc_digit *u, int vlen, const sc_digit *v, 113612854Sgabeblack@google.com sc_digit *w) 113712854Sgabeblack@google.com{ 113812854Sgabeblack@google.com#ifdef DEBUG_SYSTEMC 113912854Sgabeblack@google.com sc_assert((ulen > 0) && (u != NULL)); 114012854Sgabeblack@google.com sc_assert((vlen > 0) && (v != NULL)); 114112854Sgabeblack@google.com sc_assert(w != NULL); 114212854Sgabeblack@google.com sc_assert(BITS_PER_DIGIT >= 3 * BITS_PER_BYTE); 114312854Sgabeblack@google.com#endif 114412854Sgabeblack@google.com 114512854Sgabeblack@google.com // We will compute q = x / y where x = u and y = v. The reason for 114612854Sgabeblack@google.com // using x and y is that x and y are BYTE_RADIX copies of u and v, 114712854Sgabeblack@google.com // respectively. The use of BYTE_RADIX radix greatly simplifies the 114812854Sgabeblack@google.com // complexity of the division operation. These copies are also 114912854Sgabeblack@google.com // needed even when we use DIGIT_RADIX representation. 115012854Sgabeblack@google.com 115112854Sgabeblack@google.com int xlen = BYTES_PER_DIGIT * ulen + 1; 115212854Sgabeblack@google.com int ylen = BYTES_PER_DIGIT * vlen; 115312854Sgabeblack@google.com 115412854Sgabeblack@google.com#ifdef SC_MAX_NBITS 115512854Sgabeblack@google.com uchar x[DIV_CEIL2(SC_MAX_NBITS, BITS_PER_BYTE)]; 115612854Sgabeblack@google.com uchar y[DIV_CEIL2(SC_MAX_NBITS, BITS_PER_BYTE)]; 115712854Sgabeblack@google.com uchar q[DIV_CEIL2(SC_MAX_NBITS, BITS_PER_BYTE)]; 115812854Sgabeblack@google.com#else 115912854Sgabeblack@google.com uchar *x = new uchar[xlen]; 116012854Sgabeblack@google.com uchar *y = new uchar[ylen]; 116112854Sgabeblack@google.com // valgrind complains about us accessing too far to so leave a buffer. 116212854Sgabeblack@google.com uchar *q = new uchar[(xlen - ylen) + 10]; 116312854Sgabeblack@google.com#endif 116412854Sgabeblack@google.com 116512854Sgabeblack@google.com // q corresponds to w. 116612854Sgabeblack@google.com 116712854Sgabeblack@google.com // Set (uchar) x = (sc_digit) u. 116812854Sgabeblack@google.com xlen = vec_to_char(ulen, u, xlen, x); 116912854Sgabeblack@google.com 117012854Sgabeblack@google.com // Skip all the leading zeros in x. 117112854Sgabeblack@google.com while ((--xlen >= 0) && (! x[xlen])) 117212854Sgabeblack@google.com continue; 117312854Sgabeblack@google.com xlen++; 117412854Sgabeblack@google.com 117512854Sgabeblack@google.com // Set (uchar) y = (sc_digit) v. 117612854Sgabeblack@google.com ylen = vec_to_char(vlen, v, ylen, y); 117712854Sgabeblack@google.com 117812854Sgabeblack@google.com // Skip all the leading zeros in y. 117912854Sgabeblack@google.com while ((--ylen >= 0) && (! y[ylen])) 118012854Sgabeblack@google.com continue; 118112854Sgabeblack@google.com ylen++; 118212854Sgabeblack@google.com 118312854Sgabeblack@google.com#ifdef DEBUG_SYSTEMC 118412854Sgabeblack@google.com sc_assert(xlen > 1); 118512854Sgabeblack@google.com sc_assert(ylen > 1); 118612854Sgabeblack@google.com#endif 118712854Sgabeblack@google.com 118812854Sgabeblack@google.com // At this point, all the leading zeros are eliminated from x and y. 118912854Sgabeblack@google.com 119012854Sgabeblack@google.com // Zero the last digit of x. 119112854Sgabeblack@google.com x[xlen] = 0; 119212854Sgabeblack@google.com 119312854Sgabeblack@google.com // The first two digits of y. 119412854Sgabeblack@google.com sc_digit y2 = (y[ylen - 1] << BITS_PER_BYTE) + y[ylen - 2]; 119512854Sgabeblack@google.com 119612854Sgabeblack@google.com const sc_digit DOUBLE_BITS_PER_BYTE = 2 * BITS_PER_BYTE; 119712854Sgabeblack@google.com 119812854Sgabeblack@google.com // Find each q[k]. 119912854Sgabeblack@google.com for (int k = (xlen - ylen); k >= 0; --k) { 120012854Sgabeblack@google.com // qk is a guess for q[k] such that q[k] = qk or qk - 1. 120112854Sgabeblack@google.com sc_digit qk; 120212854Sgabeblack@google.com 120312854Sgabeblack@google.com // Find qk by just using 2 digits of y and 3 digits of x. The 120412854Sgabeblack@google.com // following code assumes that sizeof(sc_digit) >= 3 BYTEs. 120512854Sgabeblack@google.com int k2 = k + ylen; 120612854Sgabeblack@google.com 120712854Sgabeblack@google.com qk = ((x[k2] << DOUBLE_BITS_PER_BYTE) + 120812854Sgabeblack@google.com (x[k2 - 1] << BITS_PER_BYTE) + x[k2 - 2]) / y2; 120912854Sgabeblack@google.com 121012854Sgabeblack@google.com if (qk >= BYTE_RADIX) // qk cannot be larger than the largest 121112854Sgabeblack@google.com qk = BYTE_RADIX - 1; // digit in BYTE_RADIX. 121212854Sgabeblack@google.com 121312854Sgabeblack@google.com // q[k] = qk or qk - 1. The following if-statement determines which: 121412854Sgabeblack@google.com if (qk) { 121512854Sgabeblack@google.com uchar *xk = (x + k); // A shortcut for x[k]. 121612854Sgabeblack@google.com 121712854Sgabeblack@google.com // x = x - y * qk : 121812854Sgabeblack@google.com sc_digit carry = 0; 121912854Sgabeblack@google.com 122012854Sgabeblack@google.com for (int i = 0; i < ylen; ++i) { 122112854Sgabeblack@google.com carry += y[i] * qk; 122212854Sgabeblack@google.com sc_digit diff = (xk[i] + BYTE_RADIX) - (carry & BYTE_MASK); 122312854Sgabeblack@google.com xk[i] = (uchar)(diff & BYTE_MASK); 122412854Sgabeblack@google.com carry = (carry >> BITS_PER_BYTE) + 122512854Sgabeblack@google.com (1 - (diff >> BITS_PER_BYTE)); 122612854Sgabeblack@google.com } 122712854Sgabeblack@google.com 122812854Sgabeblack@google.com // If carry, qk may be one too large. 122912854Sgabeblack@google.com if (carry) { 123012854Sgabeblack@google.com // 2's complement the last digit. 123112854Sgabeblack@google.com carry = (xk[ylen] + BYTE_RADIX) - carry; 123212854Sgabeblack@google.com xk[ylen] = (uchar)(carry & BYTE_MASK); 123312854Sgabeblack@google.com carry = 1 - (carry >> BITS_PER_BYTE); 123412854Sgabeblack@google.com 123512854Sgabeblack@google.com if (carry) { 123612854Sgabeblack@google.com 123712854Sgabeblack@google.com // qk was one too large, so decrement it. 123812854Sgabeblack@google.com --qk; 123912854Sgabeblack@google.com 124012854Sgabeblack@google.com // Since qk was decreased by one, y must be added to x: 124112854Sgabeblack@google.com // x = x - y * (qk - 1) = x - y * qk + y = x_above + y. 124212854Sgabeblack@google.com carry = 0; 124312854Sgabeblack@google.com 124412854Sgabeblack@google.com for (int i = 0; i < ylen; ++i) { 124512854Sgabeblack@google.com carry += xk[i] + y[i]; 124612854Sgabeblack@google.com xk[i] = (uchar)(carry & BYTE_MASK); 124712854Sgabeblack@google.com carry >>= BITS_PER_BYTE; 124812854Sgabeblack@google.com } 124912854Sgabeblack@google.com 125012854Sgabeblack@google.com if (carry) 125112854Sgabeblack@google.com xk[ylen] = (uchar)((xk[ylen] + 1) & BYTE_MASK); 125212854Sgabeblack@google.com 125312854Sgabeblack@google.com } // second if carry 125412854Sgabeblack@google.com } // first if carry 125512854Sgabeblack@google.com } // if qk 125612854Sgabeblack@google.com q[k] = (uchar)qk; 125712854Sgabeblack@google.com } // for k 125812854Sgabeblack@google.com 125912854Sgabeblack@google.com // Set (sc_digit) w = (uchar) q. 126012854Sgabeblack@google.com vec_from_char(xlen - ylen + 1, q, ulen, w); 126112854Sgabeblack@google.com 126212854Sgabeblack@google.com#ifndef SC_MAX_NBITS 126312854Sgabeblack@google.com delete [] x; 126412854Sgabeblack@google.com delete [] y; 126512854Sgabeblack@google.com delete [] q; 126612854Sgabeblack@google.com#endif 126712854Sgabeblack@google.com 126812854Sgabeblack@google.com} 126912854Sgabeblack@google.com 127012854Sgabeblack@google.com// Compute w = u / v, where u and w are vectors, and v is a scalar. 127112854Sgabeblack@google.com// - 0 < v < HALF_DIGIT_RADIX. Below, we rename w to q. 127212854Sgabeblack@google.comvoid 127312854Sgabeblack@google.comvec_div_small(int ulen, const sc_digit *u, sc_digit v, sc_digit *q) 127412854Sgabeblack@google.com{ 127512854Sgabeblack@google.com // Given (u = u_1u_2...u_n)_b = (q = q_1q_2...q_n) * v + r, where b 127612854Sgabeblack@google.com // is the base, and 0 <= r < v. Then, the algorithm is as follows: 127712854Sgabeblack@google.com // 127812854Sgabeblack@google.com // r = 0; 127912854Sgabeblack@google.com // for (j = 1; j <= n; j++) { 128012854Sgabeblack@google.com // q_j = (r * b + u_j) / v; 128112854Sgabeblack@google.com // r = (r * b + u_j) % v; 128212854Sgabeblack@google.com // } 128312854Sgabeblack@google.com // 128412854Sgabeblack@google.com // In our case, b = DIGIT_RADIX, and u = Ax + B and q = Cx + D where 128512854Sgabeblack@google.com // x = HALF_DIGIT_RADIX. Note that r < v < x and b = x^2. Then, a 128612854Sgabeblack@google.com // typical situation is as follows: 128712854Sgabeblack@google.com // 128812854Sgabeblack@google.com // ---- ---- 128912854Sgabeblack@google.com // 0 r 129012854Sgabeblack@google.com // ---- ---- 129112854Sgabeblack@google.com // A B 129212854Sgabeblack@google.com // ---- ---- ---- 129312854Sgabeblack@google.com // r A B = r * b + u 129412854Sgabeblack@google.com // 129512854Sgabeblack@google.com // Hence, C = (r|A) / v. 129612854Sgabeblack@google.com // D = (((r|A) % v)|B) / v 129712854Sgabeblack@google.com // r = (((r|A) % v)|B) % v 129812854Sgabeblack@google.com 129912854Sgabeblack@google.com#ifdef DEBUG_SYSTEMC 130012854Sgabeblack@google.com sc_assert((ulen > 0) && (u != NULL)); 130112854Sgabeblack@google.com sc_assert(q != NULL); 130212854Sgabeblack@google.com sc_assert((0 < v) && (v < HALF_DIGIT_RADIX)); 130312854Sgabeblack@google.com#endif 130412854Sgabeblack@google.com 130512854Sgabeblack@google.com#define q_h r 130612854Sgabeblack@google.com sc_digit r = 0; 130712854Sgabeblack@google.com const sc_digit *ubegin = u; 130812854Sgabeblack@google.com 130912854Sgabeblack@google.com u += ulen; 131012854Sgabeblack@google.com q += ulen; 131112854Sgabeblack@google.com 131212854Sgabeblack@google.com while (ubegin < u) { 131312854Sgabeblack@google.com sc_digit u_AB = (*--u); // A|B 131412854Sgabeblack@google.com 131512854Sgabeblack@google.com#ifdef DEBUG_SYSTEMC 131612854Sgabeblack@google.com // The overflow bits must be zero. 131712854Sgabeblack@google.com sc_assert(high_half(u_AB) == high_half_masked(u_AB)); 131812854Sgabeblack@google.com#endif 131912854Sgabeblack@google.com 132012854Sgabeblack@google.com sc_digit num = concat(r, high_half(u_AB)); // num = r|A 132112854Sgabeblack@google.com q_h = num / v; // C 132212854Sgabeblack@google.com num = concat((num % v), low_half(u_AB)); // num = (((r|A) % v)|B) 132312854Sgabeblack@google.com (*--q) = concat(q_h, num / v); // q = C|D 132412854Sgabeblack@google.com r = num % v; 132512854Sgabeblack@google.com } 132612854Sgabeblack@google.com#undef q_h 132712854Sgabeblack@google.com} 132812854Sgabeblack@google.com 132912854Sgabeblack@google.com// Compute w = u % v, where w, u, and v are vectors. 133012854Sgabeblack@google.com// - u and v are assumed to have at least two digits as uchars. 133112854Sgabeblack@google.comvoid 133212854Sgabeblack@google.comvec_rem_large(int ulen, const sc_digit *u, int vlen, const sc_digit *v, 133312854Sgabeblack@google.com sc_digit *w) 133412854Sgabeblack@google.com{ 133512854Sgabeblack@google.com#ifdef DEBUG_SYSTEMC 133612854Sgabeblack@google.com sc_assert((ulen > 0) && (u != NULL)); 133712854Sgabeblack@google.com sc_assert((vlen > 0) && (v != NULL)); 133812854Sgabeblack@google.com sc_assert(w != NULL); 133912854Sgabeblack@google.com sc_assert(BITS_PER_DIGIT >= 3 * BITS_PER_BYTE); 134012854Sgabeblack@google.com#endif 134112854Sgabeblack@google.com 134212854Sgabeblack@google.com // This function is adapted from vec_div_large. 134312854Sgabeblack@google.com int xlen = BYTES_PER_DIGIT * ulen + 1; 134412854Sgabeblack@google.com int ylen = BYTES_PER_DIGIT * vlen; 134512854Sgabeblack@google.com 134612854Sgabeblack@google.com#ifdef SC_MAX_NBITS 134712854Sgabeblack@google.com uchar x[DIV_CEIL2(SC_MAX_NBITS, BITS_PER_BYTE)]; 134812854Sgabeblack@google.com uchar y[DIV_CEIL2(SC_MAX_NBITS, BITS_PER_BYTE)]; 134912854Sgabeblack@google.com#else 135012854Sgabeblack@google.com uchar *x = new uchar[xlen]; 135112854Sgabeblack@google.com uchar *y = new uchar[ylen]; 135212854Sgabeblack@google.com#endif 135312854Sgabeblack@google.com 135412854Sgabeblack@google.com // r corresponds to w. 135512854Sgabeblack@google.com 135612854Sgabeblack@google.com // Set (uchar) x = (sc_digit) u. 135712854Sgabeblack@google.com xlen = vec_to_char(ulen, u, xlen, x); 135812854Sgabeblack@google.com 135912854Sgabeblack@google.com // Skip all the leading zeros in x. 136012854Sgabeblack@google.com while ((--xlen >= 0) && (!x[xlen])) 136112854Sgabeblack@google.com continue; 136212854Sgabeblack@google.com xlen++; 136312854Sgabeblack@google.com 136412854Sgabeblack@google.com // Set (uchar) y = (sc_digit) v. 136512854Sgabeblack@google.com ylen = vec_to_char(vlen, v, ylen, y); 136612854Sgabeblack@google.com 136712854Sgabeblack@google.com // Skip all the leading zeros in y. 136812854Sgabeblack@google.com while ((--ylen >= 0) && (!y[ylen])) 136912854Sgabeblack@google.com continue; 137012854Sgabeblack@google.com ylen++; 137112854Sgabeblack@google.com 137212854Sgabeblack@google.com#ifdef DEBUG_SYSTEMC 137312854Sgabeblack@google.com sc_assert(xlen > 1); 137412854Sgabeblack@google.com sc_assert(ylen > 1); 137512854Sgabeblack@google.com#endif 137612854Sgabeblack@google.com 137712854Sgabeblack@google.com // At this point, all the leading zeros are eliminated from x and y. 137812854Sgabeblack@google.com 137912854Sgabeblack@google.com // Zero the last digit of x. 138012854Sgabeblack@google.com x[xlen] = 0; 138112854Sgabeblack@google.com 138212854Sgabeblack@google.com // The first two digits of y. 138312854Sgabeblack@google.com sc_digit y2 = (y[ylen - 1] << BITS_PER_BYTE) + y[ylen - 2]; 138412854Sgabeblack@google.com 138512854Sgabeblack@google.com const sc_digit DOUBLE_BITS_PER_BYTE = 2 * BITS_PER_BYTE; 138612854Sgabeblack@google.com 138712854Sgabeblack@google.com // Find each q[k]. 138812854Sgabeblack@google.com for (int k = xlen - ylen; k >= 0; --k) { 138912854Sgabeblack@google.com // qk is a guess for q[k] such that q[k] = qk or qk - 1. 139012854Sgabeblack@google.com sc_digit qk; 139112854Sgabeblack@google.com 139212854Sgabeblack@google.com // Find qk by just using 2 digits of y and 3 digits of x. The 139312854Sgabeblack@google.com // following code assumes that sizeof(sc_digit) >= 3 BYTEs. 139412854Sgabeblack@google.com int k2 = k + ylen; 139512854Sgabeblack@google.com 139612854Sgabeblack@google.com qk = ((x[k2] << DOUBLE_BITS_PER_BYTE) + 139712854Sgabeblack@google.com (x[k2 - 1] << BITS_PER_BYTE) + x[k2 - 2]) / y2; 139812854Sgabeblack@google.com 139912854Sgabeblack@google.com if (qk >= BYTE_RADIX) // qk cannot be larger than the largest 140012854Sgabeblack@google.com qk = BYTE_RADIX - 1; // digit in BYTE_RADIX. 140112854Sgabeblack@google.com 140212854Sgabeblack@google.com // q[k] = qk or qk - 1. The following if-statement determines which. 140312854Sgabeblack@google.com if (qk) { 140412854Sgabeblack@google.com uchar *xk = (x + k); // A shortcut for x[k]. 140512854Sgabeblack@google.com 140612854Sgabeblack@google.com // x = x - y * qk; 140712854Sgabeblack@google.com sc_digit carry = 0; 140812854Sgabeblack@google.com 140912854Sgabeblack@google.com for (int i = 0; i < ylen; ++i) { 141012854Sgabeblack@google.com carry += y[i] * qk; 141112854Sgabeblack@google.com sc_digit diff = (xk[i] + BYTE_RADIX) - (carry & BYTE_MASK); 141212854Sgabeblack@google.com xk[i] = (uchar)(diff & BYTE_MASK); 141312854Sgabeblack@google.com carry = (carry >> BITS_PER_BYTE) + 141412854Sgabeblack@google.com (1 - (diff >> BITS_PER_BYTE)); 141512854Sgabeblack@google.com } 141612854Sgabeblack@google.com 141712854Sgabeblack@google.com if (carry) { 141812854Sgabeblack@google.com // 2's complement the last digit. 141912854Sgabeblack@google.com carry = (xk[ylen] + BYTE_RADIX) - carry; 142012854Sgabeblack@google.com xk[ylen] = (uchar)(carry & BYTE_MASK); 142112854Sgabeblack@google.com carry = 1 - (carry >> BITS_PER_BYTE); 142212854Sgabeblack@google.com 142312854Sgabeblack@google.com if (carry) { 142412854Sgabeblack@google.com // qk was one too large, so decrement it. 142512854Sgabeblack@google.com // --qk; 142612854Sgabeblack@google.com 142712854Sgabeblack@google.com // x = x - y * (qk - 1) = x - y * qk + y = x_above + y. 142812854Sgabeblack@google.com carry = 0; 142912854Sgabeblack@google.com 143012854Sgabeblack@google.com for (int i = 0; i < ylen; ++i) { 143112854Sgabeblack@google.com carry += xk[i] + y[i]; 143212854Sgabeblack@google.com xk[i] = (uchar)(carry & BYTE_MASK); 143312854Sgabeblack@google.com carry >>= BITS_PER_BYTE; 143412854Sgabeblack@google.com } 143512854Sgabeblack@google.com 143612854Sgabeblack@google.com if (carry) 143712854Sgabeblack@google.com xk[ylen] = (uchar)((xk[ylen] + 1) & BYTE_MASK); 143812854Sgabeblack@google.com } // second if carry 143912854Sgabeblack@google.com } // first if carry 144012854Sgabeblack@google.com } // if qk 144112854Sgabeblack@google.com } // for k 144212854Sgabeblack@google.com 144312854Sgabeblack@google.com // Set (sc_digit) w = (uchar) x for the remainder. 144412854Sgabeblack@google.com vec_from_char(ylen, x, ulen, w); 144512854Sgabeblack@google.com 144612854Sgabeblack@google.com#ifndef SC_MAX_NBITS 144712854Sgabeblack@google.com delete [] x; 144812854Sgabeblack@google.com delete [] y; 144912854Sgabeblack@google.com#endif 145012854Sgabeblack@google.com 145112854Sgabeblack@google.com} 145212854Sgabeblack@google.com 145312854Sgabeblack@google.com// Compute r = u % v, where u is a vector, and r and v are scalars. 145412854Sgabeblack@google.com// - 0 < v < HALF_DIGIT_RADIX. 145512854Sgabeblack@google.com// - The remainder r is returned. 145612854Sgabeblack@google.comsc_digit 145712854Sgabeblack@google.comvec_rem_small(int ulen, const sc_digit *u, sc_digit v) 145812854Sgabeblack@google.com{ 145912854Sgabeblack@google.com 146012854Sgabeblack@google.com#ifdef DEBUG_SYSTEMC 146112854Sgabeblack@google.com sc_assert((ulen > 0) && (u != NULL)); 146212854Sgabeblack@google.com sc_assert((0 < v) && (v < HALF_DIGIT_RADIX)); 146312854Sgabeblack@google.com#endif 146412854Sgabeblack@google.com 146512854Sgabeblack@google.com // This function is adapted from vec_div_small(). 146612854Sgabeblack@google.com 146712854Sgabeblack@google.com sc_digit r = 0; 146812854Sgabeblack@google.com const sc_digit *ubegin = u; 146912854Sgabeblack@google.com 147012854Sgabeblack@google.com u += ulen; 147112854Sgabeblack@google.com 147212854Sgabeblack@google.com while (ubegin < u) { 147312854Sgabeblack@google.com sc_digit u_AB = (*--u); // A|B 147412854Sgabeblack@google.com#ifdef DEBUG_SYSTEMC 147512854Sgabeblack@google.com // The overflow bits must be zero. 147612854Sgabeblack@google.com sc_assert(high_half(u_AB) == high_half_masked(u_AB)); 147712854Sgabeblack@google.com#endif 147812854Sgabeblack@google.com // r = (((r|A) % v)|B) % v 147912854Sgabeblack@google.com r = (concat(((concat(r, high_half(u_AB))) % v), low_half(u_AB))) % v; 148012854Sgabeblack@google.com } 148112854Sgabeblack@google.com 148212854Sgabeblack@google.com return r; 148312854Sgabeblack@google.com} 148412854Sgabeblack@google.com 148512854Sgabeblack@google.com// u = u / v, r = u % v. 148612854Sgabeblack@google.comsc_digit 148712854Sgabeblack@google.comvec_rem_on_small(int ulen, sc_digit *u, sc_digit v) 148812854Sgabeblack@google.com{ 148912854Sgabeblack@google.com#ifdef DEBUG_SYSTEMC 149012854Sgabeblack@google.com sc_assert((ulen > 0) && (u != NULL)); 149112854Sgabeblack@google.com sc_assert(v > 0); 149212854Sgabeblack@google.com#endif 149312854Sgabeblack@google.com 149412854Sgabeblack@google.com#define q_h r 149512854Sgabeblack@google.com sc_digit r = 0; 149612854Sgabeblack@google.com const sc_digit *ubegin = u; 149712854Sgabeblack@google.com 149812854Sgabeblack@google.com u += ulen; 149912854Sgabeblack@google.com while (ubegin < u) { 150012854Sgabeblack@google.com sc_digit u_AB = (*--u); // A|B 150112854Sgabeblack@google.com#ifdef DEBUG_SYSTEMC 150212854Sgabeblack@google.com // The overflow bits must be zero. 150312854Sgabeblack@google.com sc_assert(high_half(u_AB) == high_half_masked(u_AB)); 150412854Sgabeblack@google.com#endif 150512854Sgabeblack@google.com sc_digit num = concat(r, high_half(u_AB)); // num = r|A 150612854Sgabeblack@google.com q_h = num / v; // C 150712854Sgabeblack@google.com num = concat((num % v), low_half(u_AB)); // num = (((r|A) % v)|B) 150812854Sgabeblack@google.com (*u) = concat(q_h, num / v); // q = C|D 150912854Sgabeblack@google.com r = num % v; 151012854Sgabeblack@google.com } 151112854Sgabeblack@google.com#undef q_h 151212854Sgabeblack@google.com return r; 151312854Sgabeblack@google.com} 151412854Sgabeblack@google.com 151512854Sgabeblack@google.com// Set (uchar) v = (sc_digit) u. Return the new vlen. 151612854Sgabeblack@google.comint 151712854Sgabeblack@google.comvec_to_char(int ulen, const sc_digit *u, int vlen, uchar *v) 151812854Sgabeblack@google.com{ 151912854Sgabeblack@google.com#ifdef DEBUG_SYSTEMC 152012854Sgabeblack@google.com sc_assert((ulen > 0) && (u != NULL)); 152112854Sgabeblack@google.com sc_assert((vlen > 0) && (v != NULL)); 152212854Sgabeblack@google.com#endif 152312854Sgabeblack@google.com 152412854Sgabeblack@google.com int nbits = ulen * BITS_PER_DIGIT; 152512854Sgabeblack@google.com int right = 0; 152612854Sgabeblack@google.com int left = right + BITS_PER_BYTE - 1; 152712854Sgabeblack@google.com 152812854Sgabeblack@google.com vlen = 0; 152912854Sgabeblack@google.com while (nbits > 0) { 153012854Sgabeblack@google.com int left_digit = left / BITS_PER_DIGIT; 153112854Sgabeblack@google.com int right_digit = right / BITS_PER_DIGIT; 153212854Sgabeblack@google.com int nsr = ((vlen << LOG2_BITS_PER_BYTE) % BITS_PER_DIGIT); 153312854Sgabeblack@google.com int d = u[right_digit] >> nsr; 153412854Sgabeblack@google.com 153512854Sgabeblack@google.com if (left_digit != right_digit) { 153612854Sgabeblack@google.com if (left_digit < ulen) 153712854Sgabeblack@google.com d |= u[left_digit] << (BITS_PER_DIGIT - nsr); 153812854Sgabeblack@google.com } 153912854Sgabeblack@google.com 154012854Sgabeblack@google.com v[vlen++] = (uchar)(d & BYTE_MASK); 154112854Sgabeblack@google.com 154212854Sgabeblack@google.com left += BITS_PER_BYTE; 154312854Sgabeblack@google.com right += BITS_PER_BYTE; 154412854Sgabeblack@google.com nbits -= BITS_PER_BYTE; 154512854Sgabeblack@google.com } 154612854Sgabeblack@google.com return vlen; 154712854Sgabeblack@google.com} 154812854Sgabeblack@google.com 154912854Sgabeblack@google.com// Set (sc_digit) v = (uchar) u. 155012854Sgabeblack@google.com// - sizeof(uchar) <= sizeof(sc_digit), 155112854Sgabeblack@google.comvoid 155212854Sgabeblack@google.comvec_from_char(int ulen, const uchar *u, int vlen, sc_digit *v) 155312854Sgabeblack@google.com{ 155412854Sgabeblack@google.com#ifdef DEBUG_SYSTEMC 155512854Sgabeblack@google.com sc_assert((ulen > 0) && (u != NULL)); 155612854Sgabeblack@google.com sc_assert((vlen > 0) && (v != NULL)); 155712854Sgabeblack@google.com sc_assert(sizeof(uchar) <= sizeof(sc_digit)); 155812854Sgabeblack@google.com#endif 155912854Sgabeblack@google.com 156012854Sgabeblack@google.com sc_digit *vend = (v + vlen); 156112854Sgabeblack@google.com 156212854Sgabeblack@google.com const int nsr = BITS_PER_DIGIT - BITS_PER_BYTE; 156312854Sgabeblack@google.com const sc_digit mask = one_and_ones(nsr); 156412854Sgabeblack@google.com 156512854Sgabeblack@google.com (*v) = (sc_digit) u[ulen - 1]; 156612854Sgabeblack@google.com 156712854Sgabeblack@google.com for (int i = ulen - 2; i >= 0; --i) { 156812854Sgabeblack@google.com // Manual inlining of vec_shift_left(). 156912854Sgabeblack@google.com sc_digit *viter = v; 157012854Sgabeblack@google.com sc_digit carry = 0; 157112854Sgabeblack@google.com while (viter < vend) { 157212854Sgabeblack@google.com sc_digit vval = (*viter); 157312854Sgabeblack@google.com (*viter++) = (((vval & mask) << BITS_PER_BYTE) | carry); 157412854Sgabeblack@google.com carry = vval >> nsr; 157512854Sgabeblack@google.com } 157612854Sgabeblack@google.com 157712854Sgabeblack@google.com if (viter < vend) 157812854Sgabeblack@google.com (*viter) = carry; 157912854Sgabeblack@google.com 158012854Sgabeblack@google.com (*v) |= (sc_digit)u[i]; 158112854Sgabeblack@google.com } 158212854Sgabeblack@google.com} 158312854Sgabeblack@google.com 158412854Sgabeblack@google.com// Set u <<= nsl. 158512854Sgabeblack@google.com// If nsl is negative, it is ignored. 158612854Sgabeblack@google.comvoid 158712854Sgabeblack@google.comvec_shift_left(int ulen, sc_digit *u, int nsl) 158812854Sgabeblack@google.com{ 158912854Sgabeblack@google.com#ifdef DEBUG_SYSTEMC 159012854Sgabeblack@google.com sc_assert((ulen > 0) && (u != NULL)); 159112854Sgabeblack@google.com#endif 159212854Sgabeblack@google.com 159312854Sgabeblack@google.com if (nsl <= 0) 159412854Sgabeblack@google.com return; 159512854Sgabeblack@google.com 159612854Sgabeblack@google.com // Shift left whole digits if nsl is large enough. 159712854Sgabeblack@google.com if (nsl >= (int) BITS_PER_DIGIT) { 159812854Sgabeblack@google.com int nd; 159912854Sgabeblack@google.com if (nsl % BITS_PER_DIGIT == 0) { 160012854Sgabeblack@google.com nd = nsl / BITS_PER_DIGIT; // No need to use DIV_CEIL(nsl). 160112854Sgabeblack@google.com nsl = 0; 160212854Sgabeblack@google.com } else { 160312854Sgabeblack@google.com nd = DIV_CEIL(nsl) - 1; 160412854Sgabeblack@google.com nsl -= nd * BITS_PER_DIGIT; 160512854Sgabeblack@google.com } 160612854Sgabeblack@google.com 160712854Sgabeblack@google.com if (nd) { 160812854Sgabeblack@google.com // Shift left for nd digits. 160912854Sgabeblack@google.com for (int j = ulen - 1; j >= nd; --j) 161012854Sgabeblack@google.com u[j] = u[j - nd]; 161112854Sgabeblack@google.com 161212854Sgabeblack@google.com vec_zero(sc_min(nd, ulen), u); 161312854Sgabeblack@google.com } 161412854Sgabeblack@google.com if (nsl == 0) 161512854Sgabeblack@google.com return; 161612854Sgabeblack@google.com } 161712854Sgabeblack@google.com 161812854Sgabeblack@google.com // Shift left if nsl < BITS_PER_DIGIT. 161912854Sgabeblack@google.com sc_digit *uiter = u; 162012854Sgabeblack@google.com sc_digit *uend = uiter + ulen; 162112854Sgabeblack@google.com 162212854Sgabeblack@google.com int nsr = BITS_PER_DIGIT - nsl; 162312854Sgabeblack@google.com sc_digit mask = one_and_ones(nsr); 162412854Sgabeblack@google.com 162512854Sgabeblack@google.com sc_digit carry = 0; 162612854Sgabeblack@google.com 162712854Sgabeblack@google.com while (uiter < uend) { 162812854Sgabeblack@google.com sc_digit uval = (*uiter); 162912854Sgabeblack@google.com (*uiter++) = (((uval & mask) << nsl) | carry); 163012854Sgabeblack@google.com carry = uval >> nsr; 163112854Sgabeblack@google.com } 163212854Sgabeblack@google.com 163312854Sgabeblack@google.com if (uiter < uend) 163412854Sgabeblack@google.com (*uiter) = carry; 163512854Sgabeblack@google.com} 163612854Sgabeblack@google.com 163712854Sgabeblack@google.com// Set u >>= nsr. 163812854Sgabeblack@google.com// If nsr is negative, it is ignored. 163912854Sgabeblack@google.comvoid 164012854Sgabeblack@google.comvec_shift_right(int ulen, sc_digit *u, int nsr, sc_digit fill) 164112854Sgabeblack@google.com{ 164212854Sgabeblack@google.com#ifdef DEBUG_SYSTEMC 164312854Sgabeblack@google.com sc_assert((ulen > 0) && (u != NULL)); 164412854Sgabeblack@google.com#endif 164512854Sgabeblack@google.com 164612854Sgabeblack@google.com // fill is usually either 0 or DIGIT_MASK; it can be any value. 164712854Sgabeblack@google.com if (nsr <= 0) 164812854Sgabeblack@google.com return; 164912854Sgabeblack@google.com 165012854Sgabeblack@google.com // Shift right whole digits if nsr is large enough. 165112854Sgabeblack@google.com if (nsr >= (int) BITS_PER_DIGIT) { 165212854Sgabeblack@google.com int nd; 165312854Sgabeblack@google.com if (nsr % BITS_PER_DIGIT == 0) { 165412854Sgabeblack@google.com nd = nsr / BITS_PER_DIGIT; 165512854Sgabeblack@google.com nsr = 0; 165612854Sgabeblack@google.com } else { 165712854Sgabeblack@google.com nd = DIV_CEIL(nsr) - 1; 165812854Sgabeblack@google.com nsr -= nd * BITS_PER_DIGIT; 165912854Sgabeblack@google.com } 166012854Sgabeblack@google.com 166112854Sgabeblack@google.com if (nd) { 166212854Sgabeblack@google.com // Shift right for nd digits. 166312854Sgabeblack@google.com for (int j = 0; j < (ulen - nd); ++j) 166412854Sgabeblack@google.com u[j] = u[j + nd]; 166512854Sgabeblack@google.com 166612854Sgabeblack@google.com if (fill) { 166712854Sgabeblack@google.com for (int j = ulen - sc_min( nd, ulen ); j < ulen; ++j) 166812854Sgabeblack@google.com u[j] = fill; 166912854Sgabeblack@google.com } else { 167012854Sgabeblack@google.com vec_zero(ulen - sc_min( nd, ulen ), ulen, u); 167112854Sgabeblack@google.com } 167212854Sgabeblack@google.com } 167312854Sgabeblack@google.com if (nsr == 0) 167412854Sgabeblack@google.com return; 167512854Sgabeblack@google.com } 167612854Sgabeblack@google.com 167712854Sgabeblack@google.com // Shift right if nsr < BITS_PER_DIGIT. 167812854Sgabeblack@google.com sc_digit *ubegin = u; 167912854Sgabeblack@google.com sc_digit *uiter = (ubegin + ulen); 168012854Sgabeblack@google.com 168112854Sgabeblack@google.com int nsl = BITS_PER_DIGIT - nsr; 168212854Sgabeblack@google.com sc_digit mask = one_and_ones(nsr); 168312854Sgabeblack@google.com 168412854Sgabeblack@google.com sc_digit carry = (fill & mask) << nsl; 168512854Sgabeblack@google.com 168612854Sgabeblack@google.com while (ubegin < uiter) { 168712854Sgabeblack@google.com sc_digit uval = (*--uiter); 168812854Sgabeblack@google.com (*uiter) = (uval >> nsr) | carry; 168912854Sgabeblack@google.com carry = (uval & mask) << nsl; 169012854Sgabeblack@google.com } 169112854Sgabeblack@google.com} 169212854Sgabeblack@google.com 169312854Sgabeblack@google.com 169412854Sgabeblack@google.com// Let u[l..r], where l and r are left and right bit positions 169512854Sgabeblack@google.com// respectively, be equal to its mirror image. 169612854Sgabeblack@google.comvoid 169712854Sgabeblack@google.comvec_reverse(int unb, int und, sc_digit *ud, int l, int r) 169812854Sgabeblack@google.com{ 169912854Sgabeblack@google.com#ifdef DEBUG_SYSTEMC 170012854Sgabeblack@google.com sc_assert((unb > 0) && (und > 0) && (ud != NULL)); 170112854Sgabeblack@google.com sc_assert((0 <= r) && (r <= l) && (l < unb)); 170212854Sgabeblack@google.com#endif 170312854Sgabeblack@google.com 170412854Sgabeblack@google.com if (l < r) { 170512854Sgabeblack@google.com std::stringstream msg; 170612854Sgabeblack@google.com msg << "vec_reverse( int, int, sc_digit*, int l, int r ) : " << 170712854Sgabeblack@google.com "l = " << l << " < r = " << r << " is not valid", 170813325Sgabeblack@google.com SC_REPORT_ERROR(sc_core::SC_ID_CONVERSION_FAILED_, msg.str().c_str()); 170912854Sgabeblack@google.com return; 171012854Sgabeblack@google.com } 171112854Sgabeblack@google.com 171212854Sgabeblack@google.com // Make sure that l and r are within bounds. 171312854Sgabeblack@google.com r = sc_max(r, 0); 171412854Sgabeblack@google.com l = sc_min(l, unb - 1); 171512854Sgabeblack@google.com 171612854Sgabeblack@google.com // Allocate memory for processing. 171712854Sgabeblack@google.com#ifdef SC_MAX_NBITS 171812854Sgabeblack@google.com sc_digit d[MAX_NDIGITS]; 171912854Sgabeblack@google.com#else 172012854Sgabeblack@google.com sc_digit *d = new sc_digit[und]; 172112854Sgabeblack@google.com#endif 172212854Sgabeblack@google.com 172312854Sgabeblack@google.com // d is a copy of ud. 172412854Sgabeblack@google.com vec_copy(und, d, ud); 172512854Sgabeblack@google.com 172612854Sgabeblack@google.com // Based on the value of the ith in d, find the value of the jth bit 172712854Sgabeblack@google.com // in ud. 172812854Sgabeblack@google.com for (int i = l, j = r; i >= r; --i, ++j) { 172912854Sgabeblack@google.com if ((d[digit_ord(i)] & one_and_zeros(bit_ord(i))) != 0) // Test. 173012854Sgabeblack@google.com ud[digit_ord(j)] |= one_and_zeros(bit_ord(j)); // Set. 173112854Sgabeblack@google.com else 173212854Sgabeblack@google.com ud[digit_ord(j)] &= ~(one_and_zeros(bit_ord(j))); // Clear. 173312854Sgabeblack@google.com } 173412854Sgabeblack@google.com 173512854Sgabeblack@google.com#ifndef SC_MAX_NBITS 173612854Sgabeblack@google.com delete [] d; 173712854Sgabeblack@google.com#endif 173812854Sgabeblack@google.com} 173912854Sgabeblack@google.com 174012854Sgabeblack@google.com#ifdef SC_MAX_NBITS 174112854Sgabeblack@google.comvoid test_bound_failed(int nb) 174212854Sgabeblack@google.com{ 174312854Sgabeblack@google.com std::stringstream msg; 174412854Sgabeblack@google.com msg << "test_bound( int nb ) : " 174512854Sgabeblack@google.com "nb = " << nb << " > SC_MAX_NBITS = " << SC_MAX_NBITS << 174612854Sgabeblack@google.com " is not valid"; 174712854Sgabeblack@google.com SC_REPORT_ERROR(sc_core::SC_ID_OUT_OF_BOUNDS_, msg.str().c_str()); 174812854Sgabeblack@google.com} 174912854Sgabeblack@google.com#endif // SC_MAX_NBITS 175012854Sgabeblack@google.com 175112854Sgabeblack@google.com} // namespace sc_dt 1752