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