sc_proxy.hh revision 12853
1/***************************************************************************** 2 3 Licensed to Accellera Systems Initiative Inc. (Accellera) under one or 4 more contributor license agreements. See the NOTICE file distributed 5 with this work for additional information regarding copyright ownership. 6 Accellera licenses this file to you under the Apache License, Version 2.0 7 (the "License"); you may not use this file except in compliance with the 8 License. You may obtain a copy of the License at 9 10 http://www.apache.org/licenses/LICENSE-2.0 11 12 Unless required by applicable law or agreed to in writing, software 13 distributed under the License is distributed on an "AS IS" BASIS, 14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 15 implied. See the License for the specific language governing 16 permissions and limitations under the License. 17 18 *****************************************************************************/ 19 20/***************************************************************************** 21 22 sc_proxy.h -- Proxy base class for vector data types. 23 24 This class is created for several purposes: 25 1) hiding operators from the global namespace that would be 26 otherwise found by Koenig lookup 27 2) avoiding repeating the same operations in every class 28 including proxies that could also be achieved by common 29 base class, but this method allows 30 3) improve performance by using non-virtual functions 31 32 Original Author: Gene Bushuyev, Synopsys, Inc. 33 34 *****************************************************************************/ 35 36/***************************************************************************** 37 38 MODIFICATION LOG - modifiers, enter your name, affiliation, date and 39 changes you are making here. 40 41 Name, Affiliation, Date: 42 Description of Modification: 43 44 *****************************************************************************/ 45 46// $Log: sc_proxy.h,v $ 47// Revision 1.3 2010/12/07 20:09:07 acg 48// Andy Goodrich: Fix for returning enough data 49// 50// Revision 1.2 2009/02/28 00:26:14 acg 51// Andy Goodrich: bug fixes. 52// 53// Revision 1.1.1.1 2006/12/15 20:31:36 acg 54// SystemC 2.2 55// 56// Revision 1.3 2006/01/13 18:53:53 acg 57// Andy Goodrich: added $Log command so that CVS comments are reproduced in 58// the source. 59// 60 61#ifndef __SYSTEMC_EXT_DT_BIT_SC_PROXY_HH__ 62#define __SYSTEMC_EXT_DT_BIT_SC_PROXY_HH__ 63 64#include <iostream> 65 66#include "../../utils/functions.hh" 67#include "../int/sc_int_base.hh" 68#include "../int/sc_signed.hh" 69#include "../int/sc_uint_base.hh" 70#include "../int/sc_unsigned.hh" 71#include "sc_bit.hh" 72#include "sc_logic.hh" 73 74namespace sc_dt 75{ 76 77// classes defined in this module 78template <class X> 79class sc_proxy; 80 81// forward class declarations 82class sc_bv_base; 83class sc_lv_base; 84template <class X> 85class sc_bitref_r; 86template <class X> 87class sc_bitref; 88template <class X> 89class sc_subref_r; 90template <class X> 91class sc_subref; 92template <class X, class Y> 93class sc_concref_r; 94template <class X, class Y> 95class sc_concref; 96 97const int SC_DIGIT_SIZE = BITS_PER_BYTE * sizeof(sc_digit); 98 99const sc_digit SC_DIGIT_ZERO = (sc_digit)0; 100const sc_digit SC_DIGIT_ONE = (sc_digit)1; 101const sc_digit SC_DIGIT_TWO = (sc_digit)2; 102 103void sc_proxy_out_of_bounds(const char *msg=NULL, int64 val=0); 104 105// assignment functions; forward declarations 106 107template <class X, class Y> 108inline void assign_p_(sc_proxy<X> &px, const sc_proxy<Y> &py); 109 110// Vector types that are not derived from sc_proxy must have a length() 111// function and an operator []. 112 113template <class X, class T> 114inline void assign_v_(sc_proxy<X> &px, const T &a); 115 116// other functions; forward declarations 117const std::string convert_to_bin(const char *s); 118const std::string convert_to_fmt(const std::string &s, sc_numrep numrep, bool); 119 120// ---------------------------------------------------------------------------- 121// CLASS TEMPLATE : sc_proxy_traits 122// 123// Template traits helper to select the correct bit/value/vector_types for 124// sc_proxy-based vector classes. 125// 126// All types derived from/based on a bit-vector contain typedef to a plain 127// bool, all others point to the sc_logic_value_t/sc_logic/sc_lv_base types. 128// ---------------------------------------------------------------------------- 129 130template <typename X> 131struct sc_proxy_traits; 132 133template <> 134struct sc_proxy_traits<sc_bv_base> 135{ 136 typedef sc_proxy_traits<sc_bv_base> traits_type; 137 typedef bool value_type; 138 typedef sc_logic bit_type; // sc_logic needed for mixed expressions 139 typedef sc_bv_base vector_type; 140}; 141 142template <> 143struct sc_proxy_traits<sc_lv_base> 144{ 145 typedef sc_proxy_traits<sc_lv_base> traits_type; 146 typedef sc_logic_value_t value_type; 147 typedef sc_logic bit_type; 148 typedef sc_lv_base vector_type; 149}; 150 151template <typename X> 152struct sc_proxy_traits<sc_bitref_r<X> > : sc_proxy_traits<X> {}; 153 154template <typename X> 155struct sc_proxy_traits<sc_bitref<X> > : sc_proxy_traits<X> {}; 156 157template <typename X> 158struct sc_proxy_traits<sc_subref_r<X> > : sc_proxy_traits<X> {}; 159 160template <typename X> 161struct sc_proxy_traits<sc_subref<X> > : sc_proxy_traits<X> {}; 162 163template <typename X> 164struct sc_proxy_traits<sc_proxy<X> > : sc_proxy_traits<X> {}; 165 166 167template <typename X, typename Y> 168struct sc_mixed_proxy_traits_helper : sc_proxy_traits<sc_lv_base> 169{}; // logic vector by default 170 171template <typename X> 172struct sc_mixed_proxy_traits_helper<X, X> : X {}; 173 174template <typename X, typename Y> 175struct sc_proxy_traits<sc_concref_r<X, Y> > : 176 sc_mixed_proxy_traits_helper< 177 typename X::traits_type, typename Y::traits_type> 178{}; 179 180template <typename X, typename Y> 181struct sc_proxy_traits<sc_concref<X, Y> > : 182 sc_mixed_proxy_traits_helper< 183 typename X::traits_type, typename Y::traits_type> 184{}; 185 186 187// ---------------------------------------------------------------------------- 188// CLASS TEMPLATE : sc_proxy 189// 190// Base class template for bit/logic vector classes. 191// (Barton/Nackmann implementation) 192// ---------------------------------------------------------------------------- 193 194template <class X> 195class sc_proxy // #### : public sc_value_base 196{ 197 public: 198 typedef typename sc_proxy_traits<X>::traits_type traits_type; 199 typedef typename traits_type::bit_type bit_type; 200 typedef typename traits_type::value_type value_type; 201 202 // virtual destructor 203 virtual ~sc_proxy() {} 204 205 // casts 206 X &back_cast() { return static_cast<X &>(*this); } 207 208 const X &back_cast() const { return static_cast<const X &>(*this); } 209 210 // assignment operators 211 template <class Y> 212 X & 213 assign_(const sc_proxy<Y> &a) 214 { 215 assign_p_(*this, a); 216 return back_cast(); 217 } 218 219 X &assign_(const char *a); 220 X &assign_(const bool *a); 221 X &assign_(const sc_logic *a); 222 223 X & 224 assign_(const sc_unsigned &a) 225 { 226 assign_v_(*this, a); 227 return back_cast(); 228 } 229 230 X & 231 assign_(const sc_signed &a) 232 { 233 assign_v_(*this, a); 234 return back_cast(); 235 } 236 237 X &assign_(const sc_uint_base &a) { return assign_((uint64)a); } 238 X &assign_(const sc_int_base &a) { return assign_((int64)a); } 239 X &assign_(unsigned int a); 240 X &assign_(int a); 241 X &assign_(unsigned long a); 242 X &assign_(long a); 243 X &assign_(uint64 a); 244 X &assign_(int64 a); 245 246 // bitwise operators and functions 247 248 // bitwise complement 249 X &b_not(); 250 251 const sc_lv_base operator ~ () const; 252 253 // bitwise and 254 X &operator &= (const char *b); 255 X &operator &= (const bool *b); 256 X &operator &= (const sc_logic *b); 257 X &operator &= (const sc_unsigned &b); 258 X &operator &= (const sc_signed &b); 259 X &operator &= (const sc_uint_base &b) { return operator &= ((uint64)b); } 260 X &operator &= (const sc_int_base &b) { return operator &= ((int64)b); } 261 X &operator &= (unsigned long b); 262 X &operator &= (long b); 263 X &operator &= (unsigned int b) { return operator &= ((unsigned long)b); } 264 X &operator &= (int b) { return operator &= ((long)b); } 265 X &operator &= (uint64 b); 266 X &operator &= (int64 b); 267 268 const sc_lv_base operator & (const char *b) const; 269 const sc_lv_base operator & (const bool *b) const; 270 const sc_lv_base operator & (const sc_logic *b) const; 271 const sc_lv_base operator & (const sc_unsigned &b) const; 272 const sc_lv_base operator & (const sc_signed &b) const; 273 const sc_lv_base operator & (const sc_uint_base &b) const; 274 const sc_lv_base operator & (const sc_int_base &b) const; 275 const sc_lv_base operator & (unsigned long b) const; 276 const sc_lv_base operator & (long b) const; 277 const sc_lv_base operator & (unsigned int b) const; 278 const sc_lv_base operator & (int b) const; 279 const sc_lv_base operator & (uint64 b) const; 280 const sc_lv_base operator & (int64 b) const; 281 282 // bitwise or 283 X &operator |= (const char *b); 284 X &operator |= (const bool *b); 285 X &operator |= (const sc_logic *b); 286 X &operator |= (const sc_unsigned &b); 287 X &operator |= (const sc_signed &b); 288 X &operator |= (const sc_uint_base &b) { return operator |= ((uint64)b); } 289 X &operator |= (const sc_int_base &b) { return operator |= ((int64)b); } 290 X &operator |= (unsigned long b); 291 X &operator |= (long b); 292 X &operator |= (unsigned int b) { return operator |= ((unsigned long)b); } 293 X &operator |= (int b) { return operator |= ((long)b); } 294 X &operator |= (uint64 b); 295 X &operator |= (int64 b); 296 297 const sc_lv_base operator | (const char *b) const; 298 const sc_lv_base operator | (const bool *b) const; 299 const sc_lv_base operator | (const sc_logic *b) const; 300 const sc_lv_base operator | (const sc_unsigned &b) const; 301 const sc_lv_base operator | (const sc_signed &b) const; 302 const sc_lv_base operator | (const sc_uint_base &b) const; 303 const sc_lv_base operator | (const sc_int_base &b) const; 304 const sc_lv_base operator | (unsigned long b) const; 305 const sc_lv_base operator | (long b) const; 306 const sc_lv_base operator | (unsigned int b) const; 307 const sc_lv_base operator | (int b) const; 308 const sc_lv_base operator | (uint64 b) const; 309 const sc_lv_base operator | (int64 b) const; 310 311 // bitwise xor 312 X &operator ^= (const char *b); 313 X &operator ^= (const bool *b); 314 X &operator ^= (const sc_logic *b); 315 X &operator ^= (const sc_unsigned &b); 316 X &operator ^= (const sc_signed &b); 317 X &operator ^= (const sc_uint_base &b) { return operator ^= ((uint64)b); } 318 X &operator ^= (const sc_int_base &b) { return operator ^= ((int64)b); } 319 X &operator ^= (unsigned long b); 320 X &operator ^= (long b); 321 X &operator ^= (unsigned int b) { return operator ^= ((unsigned long)b); } 322 X &operator ^= (int b) { return operator ^= ((long)b); } 323 X &operator ^= (uint64 b); 324 X &operator ^= (int64 b); 325 326 const sc_lv_base operator ^ (const char *b) const; 327 const sc_lv_base operator ^ (const bool *b) const; 328 const sc_lv_base operator ^ (const sc_logic *b) const; 329 const sc_lv_base operator ^ (const sc_unsigned &b) const; 330 const sc_lv_base operator ^ (const sc_signed &b) const; 331 const sc_lv_base operator ^ (const sc_uint_base &b) const; 332 const sc_lv_base operator ^ (const sc_int_base &b) const; 333 const sc_lv_base operator ^ (unsigned long b) const; 334 const sc_lv_base operator ^ (long b) const; 335 const sc_lv_base operator ^ (unsigned int b) const; 336 const sc_lv_base operator ^ (int b) const; 337 const sc_lv_base operator ^ (uint64 b) const; 338 const sc_lv_base operator ^ (int64 b) const; 339 340 // bitwise left shift 341 X &operator <<= (int n); 342 const sc_lv_base operator << (int n) const; 343 344 // bitwise right shift 345 X &operator >>= (int n); 346 const sc_lv_base operator >> (int n) const; 347 348 // bitwise left rotate 349 X &lrotate(int n); 350 351 // bitwise right rotate 352 X &rrotate(int n); 353 354 // bitwise reverse 355 X &reverse(); 356 357 // bit selection 358 sc_bitref<X> operator [] (int i) { return sc_bitref<X>(back_cast(), i); } 359 sc_bitref_r<X> 360 operator [] (int i) const 361 { 362 return sc_bitref_r<X>(back_cast(), i); 363 } 364 sc_bitref<X> bit(int i) { return sc_bitref<X>(back_cast(), i); } 365 sc_bitref_r<X> bit(int i) const { return sc_bitref_r<X>(back_cast(), i); } 366 367 // part selection 368 sc_subref<X> 369 operator () (int hi, int lo) 370 { 371 return sc_subref<X>(back_cast(), hi, lo); 372 } 373 sc_subref_r<X> 374 operator () (int hi, int lo) const 375 { 376 return sc_subref_r<X>(back_cast(), hi, lo); 377 } 378 sc_subref<X> 379 range(int hi, int lo) 380 { 381 return sc_subref<X>(back_cast(), hi, lo); 382 } 383 sc_subref_r<X> 384 range(int hi, int lo) const 385 { 386 return sc_subref_r<X>(back_cast(), hi, lo); 387 } 388 389 // reduce functions 390 value_type and_reduce() const; 391 value_type 392 nand_reduce() const 393 { 394 return sc_logic::not_table[and_reduce()]; 395 } 396 value_type or_reduce() const; 397 value_type nor_reduce() const { return sc_logic::not_table[or_reduce()]; } 398 value_type xor_reduce() const; 399 value_type 400 xnor_reduce() const 401 { 402 return sc_logic::not_table[xor_reduce()]; 403 } 404 405 // relational operators 406 bool operator == (const char *b) const; 407 bool operator == (const bool *b) const; 408 bool operator == (const sc_logic *b) const; 409 bool operator == (const sc_unsigned &b) const; 410 bool operator == (const sc_signed &b) const; 411 bool operator == (const sc_uint_base &b) const; 412 bool operator == (const sc_int_base &b) const; 413 bool operator == (unsigned long b) const; 414 bool operator == (long b) const; 415 bool operator == (unsigned int b) const; 416 bool operator == (int b) const; 417 bool operator == (uint64 b) const; 418 bool operator == (int64 b) const; 419 420 // explicit conversions to character string 421 const std::string to_string() const; 422 const std::string to_string(sc_numrep) const; 423 const std::string to_string(sc_numrep, bool) const; 424 425 // explicit conversions 426 inline int64 to_int64() const { return to_anything_signed(); } 427 inline uint64 to_uint64() const; 428 int to_int() const { return (int)to_anything_signed(); } 429 430 unsigned int 431 to_uint() const 432 { 433 return (unsigned int)to_anything_unsigned(); 434 } 435 436 long to_long() const { return (long)to_anything_signed(); } 437 438 unsigned long 439 to_ulong() const 440 { 441 return (unsigned long)to_anything_unsigned(); 442 } 443 444 // other methods 445 void 446 print(::std::ostream &os=::std::cout) const 447 { 448 // The test below will force printing in binary if decimal is 449 // specified. 450 if (sc_io_base(os, SC_DEC) == SC_DEC) 451 os << to_string(); 452 else 453 os << to_string(sc_io_base(os, SC_BIN), sc_io_show_base(os)); 454 } 455 456 void scan(::std::istream &is=::std::cin); 457 458 protected: 459 void check_bounds(int n) const; // check if bit n accessible 460 void check_wbounds(int n) const; // check if word n accessible 461 462 sc_digit to_anything_unsigned() const; 463 int64 to_anything_signed() const; 464}; 465 466 467// ---------------------------------------------------------------------------- 468 469// bitwise operators and functions 470 471// bitwise and 472 473template <class X, class Y> 474inline X &operator &= (sc_proxy<X> &px, const sc_proxy<Y> &py); 475 476 477template <class X, class Y> 478inline const sc_lv_base operator & ( 479 const sc_proxy<X> &px, const sc_proxy<Y> &py); 480 481 482#define DECL_BITWISE_AND_OP_T(tp) \ 483template <class X> \ 484inline const sc_lv_base operator & (tp b, const sc_proxy<X> &px); 485 486DECL_BITWISE_AND_OP_T(const char *) 487DECL_BITWISE_AND_OP_T(const bool *) 488DECL_BITWISE_AND_OP_T(const sc_logic *) 489DECL_BITWISE_AND_OP_T(const sc_unsigned &) 490DECL_BITWISE_AND_OP_T(const sc_signed &) 491DECL_BITWISE_AND_OP_T(const sc_uint_base &) 492DECL_BITWISE_AND_OP_T(const sc_int_base &) 493DECL_BITWISE_AND_OP_T(unsigned long) 494DECL_BITWISE_AND_OP_T(long) 495DECL_BITWISE_AND_OP_T(unsigned int) 496DECL_BITWISE_AND_OP_T(int) 497DECL_BITWISE_AND_OP_T(uint64) 498DECL_BITWISE_AND_OP_T(int64) 499 500#undef DECL_BITWISE_AND_OP_T 501 502// bitwise or 503template <class X, class Y> 504inline X &operator |= (sc_proxy<X> &px, const sc_proxy<Y> &py); 505 506template <class X, class Y> 507inline const sc_lv_base operator | ( 508 const sc_proxy<X> &px, const sc_proxy<Y> &py); 509 510 511#define DECL_BITWISE_OR_OP_T(tp) \ 512template <class X> \ 513inline const sc_lv_base operator | (tp a, const sc_proxy<X> &px); 514 515DECL_BITWISE_OR_OP_T(const char *) 516DECL_BITWISE_OR_OP_T(const bool *) 517DECL_BITWISE_OR_OP_T(const sc_logic *) 518DECL_BITWISE_OR_OP_T(const sc_unsigned &) 519DECL_BITWISE_OR_OP_T(const sc_signed &) 520DECL_BITWISE_OR_OP_T(const sc_uint_base &) 521DECL_BITWISE_OR_OP_T(const sc_int_base &) 522DECL_BITWISE_OR_OP_T(unsigned long) 523DECL_BITWISE_OR_OP_T(long) 524DECL_BITWISE_OR_OP_T(unsigned int) 525DECL_BITWISE_OR_OP_T(int) 526DECL_BITWISE_OR_OP_T(uint64) 527DECL_BITWISE_OR_OP_T(int64) 528 529#undef DECL_BITWISE_OR_OP_T 530 531// bitwise xor 532template <class X, class Y> 533inline X &operator ^= (sc_proxy<X> &px, const sc_proxy<Y> &py); 534 535template <class X, class Y> 536inline const sc_lv_base operator ^ ( 537 const sc_proxy<X> &px, const sc_proxy<Y> &py); 538 539#define DECL_BITWISE_XOR_OP_T(tp) \ 540template <class X> \ 541inline const sc_lv_base operator ^ (tp a, const sc_proxy<X> &px); 542 543DECL_BITWISE_XOR_OP_T(const char *) 544DECL_BITWISE_XOR_OP_T(const bool *) 545DECL_BITWISE_XOR_OP_T(const sc_logic *) 546DECL_BITWISE_XOR_OP_T(const sc_unsigned &) 547DECL_BITWISE_XOR_OP_T(const sc_signed &) 548DECL_BITWISE_XOR_OP_T(const sc_uint_base &) 549DECL_BITWISE_XOR_OP_T(const sc_int_base &) 550DECL_BITWISE_XOR_OP_T(unsigned long) 551DECL_BITWISE_XOR_OP_T(long) 552DECL_BITWISE_XOR_OP_T(unsigned int) 553DECL_BITWISE_XOR_OP_T(int) 554DECL_BITWISE_XOR_OP_T(uint64) 555DECL_BITWISE_XOR_OP_T(int64) 556 557#undef DECL_BITWISE_XOR_OP_T 558 559// relational operators 560template <class X, class Y> 561inline bool operator == (const sc_proxy<X> &px, const sc_proxy<Y> &py); 562 563template <class X, class Y> 564inline bool operator != (const sc_proxy<X> &px, const sc_proxy<Y> &py); 565 566#define DECL_REL_OP_T(tp) \ 567template <class X> \ 568inline bool operator == (tp b, const sc_proxy<X> &px); \ 569 \ 570template <class X> \ 571inline bool operator != (const sc_proxy<X> &px, tp b); \ 572 \ 573template <class X> \ 574inline bool operator != (tp b, const sc_proxy<X> &px); 575 576DECL_REL_OP_T(const char *) 577DECL_REL_OP_T(const bool *) 578DECL_REL_OP_T(const sc_logic *) 579DECL_REL_OP_T(const sc_unsigned &) 580DECL_REL_OP_T(const sc_signed &) 581DECL_REL_OP_T(const sc_uint_base &) 582DECL_REL_OP_T(const sc_int_base &) 583DECL_REL_OP_T(unsigned long) 584DECL_REL_OP_T(long) 585DECL_REL_OP_T(unsigned int) 586DECL_REL_OP_T(int) 587DECL_REL_OP_T(uint64) 588DECL_REL_OP_T(int64) 589 590#undef DECL_REL_OP_T 591 592// l-value concatenation 593 594// Due to the fact that temporary objects cannot be passed to non-const 595// references, we have to enumerate, use call by value, and use dynamic 596// memory allocation (and deallocation). 597 598 599// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII 600 601template <class X> 602inline void 603get_words_(const X &x, int wi, sc_digit &x_dw, sc_digit &x_cw) 604{ 605 x_dw = x.get_word(wi); 606 x_cw = x.get_cword(wi); 607} 608 609template <class X> 610inline void 611set_words_(X &x, int wi, sc_digit x_dw, sc_digit x_cw) 612{ 613 x.set_word(wi, x_dw); 614 x.set_cword(wi, x_cw); 615} 616 617template <class X> 618inline void 619extend_sign_w_(X &x, int wi, bool sign) 620{ 621 int sz = x.size(); 622 unsigned int sgn = (sign ? ~SC_DIGIT_ZERO : SC_DIGIT_ZERO); 623 for (int i = wi; i < sz; ++i) { 624 set_words_(x, i, sgn, SC_DIGIT_ZERO); 625 } 626} 627 628// assignment functions 629template <class X, class Y> 630inline void 631assign_p_(sc_proxy<X> &px, const sc_proxy<Y> &py) 632{ 633 if ((void *)&px != (void *)&py) { 634 X &x = px.back_cast(); 635 const Y &y = py.back_cast(); 636 int sz = x.size(); 637 int min_sz = sc_min(sz, y.size()); 638 int i = 0; 639 for (; i < min_sz; ++i) { 640 set_words_(x, i, y.get_word(i), y.get_cword(i)); 641 } 642 // extend with zeros 643 extend_sign_w_(x, i, false); 644 x.clean_tail(); 645 } 646} 647 648// Vector types that are not derived from sc_proxy, sc_int_base, 649// sc_uint_base, sc_signed, or sc_unsigned, must have a length() 650// function and an operator []. The vector argument type must support 651// accessing bits that are beyond the msb. The vector argument type 652// decides what to do there (e.g. sign extension or zero padding). 653 654template <class X, class T> 655inline void 656assign_v_(sc_proxy<X> &px, const T &a) 657{ 658 X &x = px.back_cast(); 659 int i; 660 int len_x = x.length(); 661 int len_a = a.length(); 662 if (len_a > len_x) 663 len_a = len_x; 664 for (i = 0; i < len_a; ++i) { 665 x.set_bit(i, sc_logic_value_t((bool)a[i])); 666 } 667 for (; i < len_x; ++i) { 668 x.set_bit(i, sc_logic_value_t(false)); 669 } 670} 671 672template <class X> 673inline void 674assign_v_(sc_proxy<X> &px, const sc_int_base &a) 675{ 676 X &x = px.back_cast(); 677 int i; 678 bool sign = a < 0; 679 int len_x = x.length(); 680 int len_a = a.length(); 681 if ( len_a > len_x ) len_a = len_x; 682 for (i = 0; i < len_a; ++i) { 683 x.set_bit(i, sc_logic_value_t((bool)a[i])); 684 } 685 for (; i < len_x; ++i) { 686 x.set_bit(i, sc_logic_value_t(sign)); 687 } 688} 689 690template <class X> 691inline void 692assign_v_(sc_proxy<X> &px, const sc_signed &a) 693{ 694 X &x = px.back_cast(); 695 int i; 696 bool sign = a < 0; 697 int len_x = x.length(); 698 int len_a = a.length(); 699 if (len_a > len_x) 700 len_a = len_x; 701 for (i = 0; i < len_a; ++i) { 702 x.set_bit(i, sc_logic_value_t((bool)a[i])); 703 } 704 for (; i < len_x; ++i) { 705 x.set_bit(i, sc_logic_value_t(sign)); 706 } 707} 708 709template <class X> 710inline void 711assign_v_(sc_proxy<X> &px, const sc_uint_base &a) 712{ 713 X &x = px.back_cast(); 714 int i; 715 int len_x = x.length(); 716 int len_a = a.length(); 717 if (len_a > len_x) 718 len_a = len_x; 719 for (i = 0; i < len_a; ++i) { 720 x.set_bit(i, sc_logic_value_t((bool)a[i])); 721 } 722 for (; i < len_x; ++i) { 723 x.set_bit(i, sc_logic_value_t(false)); 724 } 725} 726 727template <class X> 728inline void 729assign_v_(sc_proxy<X> &px, const sc_unsigned &a) 730{ 731 X &x = px.back_cast(); 732 int i; 733 int len_x = x.length(); 734 int len_a = a.length(); 735 if (len_a > len_x) 736 len_a = len_x; 737 for (i = 0; i < len_a; ++i) { 738 x.set_bit(i, sc_logic_value_t((bool)a[i])); 739 } 740 for (; i < len_x; ++i) { 741 x.set_bit(i, sc_logic_value_t(false)); 742 } 743} 744 745// assignment operators 746template <class X> 747inline X & 748sc_proxy<X>::assign_(const char *a) 749{ 750 X &x = back_cast(); 751 std::string s = convert_to_bin(a); 752 int len = x.length(); 753 int s_len = s.length() - 1; 754 int min_len = sc_min(len, s_len); 755 int i = 0; 756 for (; i < min_len; ++i) { 757 char c = s[s_len - i - 1]; 758 x.set_bit(i, sc_logic::char_to_logic[(int)c]); 759 } 760 // if formatted, fill the rest with sign(s), otherwise fill with zeros 761 sc_logic_value_t fill = (s[s_len] == 'F' ? sc_logic_value_t(s[0] - '0') 762 : sc_logic_value_t(0)); 763 for (; i < len; ++i) { 764 x.set_bit(i, fill); 765 } 766 return x; 767} 768 769template <class X> 770inline X & 771sc_proxy<X>::assign_(const bool *a) 772{ 773 // the length of 'a' must be larger than or equal to the length of 'this' 774 X &x = back_cast(); 775 int len = x.length(); 776 for (int i = 0; i < len; ++i) { 777 x.set_bit(i, sc_logic_value_t(a[i])); 778 } 779 return x; 780} 781 782template <class X> 783inline X & 784sc_proxy<X>::assign_(const sc_logic *a) 785{ 786 // the length of 'a' must be larger than or equal to the length of 'this' 787 X &x = back_cast(); 788 int len = x.length(); 789 for (int i = 0; i < len; ++i) { 790 x.set_bit(i, a[i].value()); 791 } 792 return x; 793} 794 795template <class X> 796inline X & 797sc_proxy<X>::assign_(unsigned int a) 798{ 799 X &x = back_cast(); 800 set_words_(x, 0, (sc_digit)a, SC_DIGIT_ZERO); 801 // extend with zeros 802 extend_sign_w_(x, 1, false); 803 x.clean_tail(); 804 return x; 805} 806 807template <class X> 808inline X & 809sc_proxy<X>::assign_(int a) 810{ 811 X &x = back_cast(); 812 set_words_(x, 0, (sc_digit)a, SC_DIGIT_ZERO); 813 // extend with sign(a) 814 extend_sign_w_(x, 1, (a < 0)); 815 x.clean_tail(); 816 return x; 817} 818 819#if defined(SC_LONG_64) 820template <class X> 821inline X & 822sc_proxy<X>::assign_(unsigned long a) 823{ 824 X &x = back_cast(); 825 set_words_(x, 0, ((sc_digit)a & ~SC_DIGIT_ZERO), SC_DIGIT_ZERO); 826 if (x.size() > 1) { 827 set_words_(x, 1, ((sc_digit)(a >> SC_DIGIT_SIZE) & ~SC_DIGIT_ZERO), 828 SC_DIGIT_ZERO); 829 // extend with zeros 830 extend_sign_w_(x, 2, false); 831 } 832 x.clean_tail(); 833 return x; 834} 835 836template <class X> 837inline X & 838sc_proxy<X>::assign_(long a) 839{ 840 X &x = back_cast(); 841 set_words_(x, 0, ((sc_digit)a & ~SC_DIGIT_ZERO), SC_DIGIT_ZERO); 842 if (x.size() > 1) { 843 set_words_(x, 1, 844 ((sc_digit)((uint64)a >> SC_DIGIT_SIZE) & ~SC_DIGIT_ZERO), 845 SC_DIGIT_ZERO); 846 // extend with sign(a) 847 extend_sign_w_(x, 2, (a < 0)); 848 } 849 x.clean_tail(); 850 return x; 851} 852 853#else 854 855template <class X> 856inline X & 857sc_proxy<X>::assign_(unsigned long a) 858{ 859 X &x = back_cast(); 860 set_words_(x, 0, (sc_digit)a, SC_DIGIT_ZERO); 861 // extend with zeros 862 extend_sign_w_(x, 1, false); 863 x.clean_tail(); 864 return x; 865} 866 867template <class X> 868inline X & 869sc_proxy<X>::assign_(long a) 870{ 871 X &x = back_cast(); 872 set_words_(x, 0, (sc_digit)a, SC_DIGIT_ZERO); 873 // extend with sign(a) 874 extend_sign_w_(x, 1, (a < 0)); 875 x.clean_tail(); 876 return x; 877} 878 879#endif 880 881template <class X> 882inline X & 883sc_proxy<X>::assign_(uint64 a) 884{ 885 X &x = back_cast(); 886 set_words_(x, 0, ((sc_digit)a & ~SC_DIGIT_ZERO), SC_DIGIT_ZERO); 887 if (x.size() > 1) { 888 set_words_(x, 1, ((sc_digit) (a >> SC_DIGIT_SIZE) & ~SC_DIGIT_ZERO), 889 SC_DIGIT_ZERO ); 890 // extend with zeros 891 extend_sign_w_(x, 2, false); 892 } 893 x.clean_tail(); 894 return x; 895} 896 897template <class X> 898inline X & 899sc_proxy<X>::assign_(int64 a) 900{ 901 X &x = back_cast(); 902 set_words_(x, 0, ((sc_digit)a & ~SC_DIGIT_ZERO), SC_DIGIT_ZERO); 903 if (x.size() > 1) { 904 set_words_(x, 1, 905 ((sc_digit)((uint64)a >> SC_DIGIT_SIZE) & ~SC_DIGIT_ZERO), 906 SC_DIGIT_ZERO ); 907 // extend with sign(a) 908 extend_sign_w_(x, 2, (a < 0)); 909 } 910 x.clean_tail(); 911 return x; 912} 913 914// bitwise operators and functions 915 916// bitwise complement 917template <class X> 918inline X & 919sc_proxy<X>::b_not() 920{ 921 X &x = back_cast(); 922 int sz = x.size(); 923 for (int i = 0; i < sz; ++i) { 924 sc_digit x_dw, x_cw; 925 get_words_(x, i, x_dw, x_cw); 926 x.set_word(i, x_cw | ~x_dw); 927 } 928 x.clean_tail(); 929 return x; 930} 931 932// bitwise and 933template <class X, class Y> 934inline X & 935b_and_assign_(sc_proxy<X> &px, const sc_proxy<Y> &py) 936{ 937 X &x = px.back_cast(); 938 const Y &y = py.back_cast(); 939 sc_assert(x.length() == y.length()); 940 int sz = x.size(); 941 for (int i = 0; i < sz; ++i) { 942 sc_digit x_dw, x_cw, y_dw, y_cw; 943 get_words_(x, i, x_dw, x_cw); 944 get_words_(y, i, y_dw, y_cw); 945 sc_digit cw = (x_dw & y_cw) | (x_cw & y_dw) | (x_cw & y_cw); 946 sc_digit dw = cw | (x_dw & y_dw); 947 set_words_(x, i, dw, cw); 948 } 949 // tail cleaning not needed 950 return x; 951} 952 953// bitwise or 954template <class X, class Y> 955inline X & 956b_or_assign_(sc_proxy<X> &px, const sc_proxy<Y> &py) 957{ 958 X &x = px.back_cast(); 959 const Y &y = py.back_cast(); 960 sc_assert(x.length() == y.length()); 961 int sz = x.size(); 962 for (int i = 0; i < sz; ++i) { 963 sc_digit x_dw, x_cw, y_dw, y_cw; 964 get_words_(x, i, x_dw, x_cw); 965 get_words_(y, i, y_dw, y_cw); 966 sc_digit cw = (x_cw & y_cw) | (x_cw & ~y_dw) | (~x_dw & y_cw); 967 sc_digit dw = cw | x_dw | y_dw; 968 set_words_(x, i, dw, cw); 969 } 970 // tail cleaning not needed 971 return x; 972} 973 974// bitwise xor 975template <class X, class Y> 976inline X & 977b_xor_assign_(sc_proxy<X> &a, const sc_proxy<Y> &b) 978{ 979 X &x = a.back_cast(); 980 const Y &y = b.back_cast(); 981 sc_assert(x.length() == y.length()); 982 int sz = x.size(); 983 for (int i = 0; i < sz; ++i) { 984 sc_digit x_dw, x_cw, y_dw, y_cw; 985 get_words_(x, i, x_dw, x_cw); 986 get_words_(y, i, y_dw, y_cw); 987 sc_digit cw = x_cw | y_cw; 988 sc_digit dw = cw | (x_dw ^ y_dw); 989 set_words_( x, i, dw, cw ); 990 } 991 // tail cleaning not needed 992 return x; 993} 994 995// bitwise left shift 996template <class X> 997inline X & 998sc_proxy<X>::operator <<= (int n) 999{ 1000 X &x = back_cast(); 1001 if (n < 0) { 1002 sc_proxy_out_of_bounds("left shift operation is only allowed with " 1003 "positive shift values, shift value = ", n); 1004 return x; 1005 } 1006 if (n >= x.length()) { 1007 extend_sign_w_(x, 0, false); 1008 // no tail cleaning needed 1009 return x; 1010 } 1011 int sz = x.size(); 1012 int wn = n / SC_DIGIT_SIZE; 1013 int bn = n % SC_DIGIT_SIZE; 1014 if (wn != 0) { 1015 // shift words 1016 int i = sz - 1; 1017 for (; i >= wn; --i) { 1018 set_words_(x, i, x.get_word(i - wn), x.get_cword(i - wn)); 1019 } 1020 for (; i >= 0; --i) { 1021 set_words_(x, i, SC_DIGIT_ZERO, SC_DIGIT_ZERO); 1022 } 1023 } 1024 if (bn != 0) { 1025 // shift bits 1026 for (int i = sz - 1; i >= 1; --i) { 1027 sc_digit x_dw, x_cw; 1028 get_words_(x, i, x_dw, x_cw); 1029 x_dw <<= bn; 1030 x_dw |= x.get_word(i - 1) >> (SC_DIGIT_SIZE - bn); 1031 x_cw <<= bn; 1032 x_cw |= x.get_cword(i - 1) >> (SC_DIGIT_SIZE - bn); 1033 set_words_(x, i, x_dw, x_cw); 1034 } 1035 sc_digit x_dw, x_cw; 1036 get_words_(x, 0, x_dw, x_cw); 1037 x_dw <<= bn; 1038 x_cw <<= bn; 1039 set_words_(x, 0, x_dw, x_cw); 1040 } 1041 x.clean_tail(); 1042 return x; 1043} 1044 1045// bitwise right shift 1046template <class X> 1047inline X & 1048sc_proxy<X>::operator >>= (int n) 1049{ 1050 X &x = back_cast(); 1051 if (n < 0) { 1052 sc_proxy_out_of_bounds("right shift operation is only allowed with " 1053 "positive shift values, shift value = ", n); 1054 return x; 1055 } 1056 if (n >= x.length()) { 1057 extend_sign_w_(x, 0, false); 1058 // no tail cleaning needed 1059 return x; 1060 } 1061 int sz = x.size(); 1062 int wn = n / SC_DIGIT_SIZE; 1063 int bn = n % SC_DIGIT_SIZE; 1064 if (wn != 0) { 1065 // shift words 1066 int i = 0; 1067 for (; i < (sz - wn); ++i) { 1068 set_words_(x, i, x.get_word(i + wn), x.get_cword(i + wn)); 1069 } 1070 for (; i < sz; ++i) { 1071 set_words_(x, i, SC_DIGIT_ZERO, SC_DIGIT_ZERO); 1072 } 1073 } 1074 if (bn != 0) { 1075 // shift bits 1076 for (int i = 0; i < (sz - 1); ++i) { 1077 sc_digit x_dw, x_cw; 1078 get_words_(x, i, x_dw, x_cw); 1079 x_dw >>= bn; 1080 x_dw |= x.get_word(i + 1) << (SC_DIGIT_SIZE - bn); 1081 x_cw >>= bn; 1082 x_cw |= x.get_cword(i + 1) << (SC_DIGIT_SIZE - bn); 1083 set_words_(x, i, x_dw, x_cw); 1084 } 1085 sc_digit x_dw, x_cw; 1086 get_words_(x, sz - 1, x_dw, x_cw); 1087 x_dw >>= bn; 1088 x_cw >>= bn; 1089 set_words_(x, sz - 1, x_dw, x_cw); 1090 } 1091 x.clean_tail(); 1092 return x; 1093} 1094 1095// bitwise left rotate 1096template <class X> 1097inline const sc_lv_base lrotate(const sc_proxy<X> &x, int n); 1098 1099// bitwise right rotate 1100template <class X> 1101inline const sc_lv_base rrotate(const sc_proxy<X>& x, int n); 1102 1103// bitwise reverse 1104template <class X> 1105inline X & 1106sc_proxy<X>::reverse() 1107{ 1108 X &x = back_cast(); 1109 int len = x.length(); 1110 int half_len = len / 2; 1111 for (int i = 0, j = len - 1; i < half_len; ++ i, --j) { 1112 value_type t = x.get_bit(i); 1113 x.set_bit(i, x.get_bit(j)); 1114 x.set_bit(j, t); 1115 } 1116 return x; 1117} 1118 1119template <class X> 1120inline const sc_lv_base reverse(const sc_proxy<X> &a); 1121 1122// reduce functions 1123template <class X> 1124inline typename sc_proxy<X>::value_type 1125sc_proxy<X>::and_reduce() const 1126{ 1127 const X &x = back_cast(); 1128 value_type result = value_type(1); 1129 int len = x.length(); 1130 for (int i = 0; i < len; ++i) { 1131 result = sc_logic::and_table[result][x.get_bit(i)]; 1132 } 1133 return result; 1134} 1135 1136template <class X> 1137inline typename sc_proxy<X>::value_type 1138sc_proxy<X>::or_reduce() const 1139{ 1140 const X &x = back_cast(); 1141 value_type result = value_type(0); 1142 int len = x.length(); 1143 for (int i = 0; i < len; ++i) { 1144 result = sc_logic::or_table[result][x.get_bit(i)]; 1145 } 1146 return result; 1147} 1148 1149template <class X> 1150inline typename sc_proxy<X>::value_type 1151sc_proxy<X>::xor_reduce() const 1152{ 1153 const X &x = back_cast(); 1154 value_type result = value_type(0); 1155 int len = x.length(); 1156 for (int i = 0; i < len; ++i) { 1157 result = sc_logic::xor_table[result][x.get_bit(i)]; 1158 } 1159 return result; 1160} 1161 1162// relational operators 1163template <class X, class Y> 1164inline bool 1165operator != (const sc_proxy<X> &px, const sc_proxy<Y> &py) 1166{ 1167 return !(px == py); 1168} 1169 1170 1171#define DEFN_REL_OP_T(tp) \ 1172template <class X> \ 1173inline bool operator == (tp b, const sc_proxy<X> &px) { return (px == b); } \ 1174 \ 1175template <class X> \ 1176inline bool operator != (const sc_proxy<X> &px, tp b) { return !(px == b); } \ 1177 \ 1178template <class X> \ 1179inline bool operator != (tp b, const sc_proxy<X> &px) { return !(px == b); } 1180 1181DEFN_REL_OP_T(const char *) 1182DEFN_REL_OP_T(const bool *) 1183DEFN_REL_OP_T(const sc_logic *) 1184DEFN_REL_OP_T(const sc_unsigned &) 1185DEFN_REL_OP_T(const sc_signed &) 1186DEFN_REL_OP_T(const sc_uint_base &) 1187DEFN_REL_OP_T(const sc_int_base &) 1188DEFN_REL_OP_T(unsigned long) 1189DEFN_REL_OP_T(long) 1190DEFN_REL_OP_T(unsigned int) 1191DEFN_REL_OP_T(int) 1192DEFN_REL_OP_T(uint64) 1193DEFN_REL_OP_T(int64) 1194 1195#undef DEFN_REL_OP_T 1196 1197// explicit conversions to character string 1198template <class X> 1199inline const std::string 1200sc_proxy<X>::to_string() const 1201{ 1202 const X &x = back_cast(); 1203 int len = x.length(); 1204 std::string s; // (len + 1); 1205 for (int i = 0; i < len; ++i) { 1206 s += sc_logic::logic_to_char[x.get_bit(len - i - 1)]; 1207 } 1208 return s; 1209} 1210 1211template <class X> 1212inline const std::string 1213sc_proxy<X>::to_string(sc_numrep numrep) const 1214{ 1215 return convert_to_fmt(to_string(), numrep, true); 1216} 1217 1218template <class X> 1219inline const std::string 1220sc_proxy<X>::to_string(sc_numrep numrep, bool w_prefix) const 1221{ 1222 return convert_to_fmt(to_string(), numrep, w_prefix); 1223} 1224 1225// other methods 1226template <class X> 1227inline void 1228sc_proxy<X>::scan(::std::istream &is) 1229{ 1230 std::string s; 1231 is >> s; 1232 back_cast() = s.c_str(); 1233} 1234 1235template <class X> 1236inline void 1237sc_proxy<X>::check_bounds(int n) const // check if bit n accessible 1238{ 1239 if (n < 0 || n >= back_cast().length()) { 1240 sc_proxy_out_of_bounds(NULL, n); 1241 sc_core::sc_abort(); // can't recover from here 1242 } 1243} 1244 1245template <class X> 1246inline void 1247sc_proxy<X>::check_wbounds(int n) const // check if word n accessible 1248{ 1249 if (n < 0 || n >= back_cast().size()) { 1250 sc_proxy_out_of_bounds(NULL, n); 1251 sc_core::sc_abort(); // can't recover from here 1252 } 1253} 1254 1255template <class X> 1256inline sc_digit 1257sc_proxy<X>::to_anything_unsigned() const 1258{ 1259 // only 0 word is returned 1260 // can't convert logic values other than 0 and 1 1261 const X &x = back_cast(); 1262 int len = x.length(); 1263 if (x.get_cword(0) != SC_DIGIT_ZERO) { 1264 SC_REPORT_WARNING("vector contains 4-value logic", 0); 1265 } 1266 sc_digit w = x.get_word(0); 1267 if (len >= SC_DIGIT_SIZE) { 1268 return w; 1269 } 1270 return (w & (~SC_DIGIT_ZERO >> (SC_DIGIT_SIZE - len))); 1271} 1272 1273template <class X> 1274inline uint64 1275sc_proxy<X>::to_uint64() const 1276{ 1277 // words 1 and 0 returned. 1278 // can't convert logic values other than 0 and 1 1279 const X &x = back_cast(); 1280 int len = x.length(); 1281 if (x.get_cword(0) != SC_DIGIT_ZERO) { 1282 SC_REPORT_WARNING("vector contains 4-value logic", 0); 1283 } 1284 uint64 w = x.get_word(0); 1285 if (len > SC_DIGIT_SIZE) { 1286 if (x.get_cword(1) != SC_DIGIT_ZERO) { 1287 SC_REPORT_WARNING("vector contains 4-value logic", 0); 1288 } 1289 uint64 w1 = x.get_word(1); 1290 w = w | (w1 << SC_DIGIT_SIZE); 1291 return w; 1292 } else if (len == SC_DIGIT_SIZE) { 1293 return w; 1294 } else { 1295 return (w & (~SC_DIGIT_ZERO >> (SC_DIGIT_SIZE - len))); 1296 } 1297} 1298 1299template <class X> 1300inline int64 1301sc_proxy<X>::to_anything_signed() const 1302{ 1303 const X &x = back_cast(); 1304 int len = x.length(); 1305 int64 w = 0; 1306 1307 if (len > SC_DIGIT_SIZE) { 1308 if (x.get_cword(1) != SC_DIGIT_ZERO) 1309 SC_REPORT_WARNING("vector contains 4-value logic", 0); 1310 w = x.get_word(1); 1311 } 1312 if (x.get_cword(0) != SC_DIGIT_ZERO) 1313 SC_REPORT_WARNING("vector contains 4-value logic", 0); 1314 w = (w << SC_DIGIT_SIZE) | x.get_word(0); 1315 if (len >= 64) { 1316 return w; 1317 } 1318 1319 uint64 zero = 0; 1320 value_type sgn = x.get_bit(len - 1); 1321 if (sgn == 0) { 1322 return (int64)(w & (~zero >> (64 - len))); 1323 } else { 1324 return (int64)(w | (~zero << len)); 1325 } 1326} 1327 1328 1329// ---------------------------------------------------------------------------- 1330 1331// functional notation for the reduce methods 1332template <class X> 1333inline typename sc_proxy<X>::value_type 1334and_reduce(const sc_proxy<X> &a) 1335{ 1336 return a.and_reduce(); 1337} 1338 1339template <class X> 1340inline typename sc_proxy<X>::value_type 1341nand_reduce(const sc_proxy<X> &a) 1342{ 1343 return a.nand_reduce(); 1344} 1345 1346template <class X> 1347inline typename sc_proxy<X>::value_type 1348or_reduce(const sc_proxy<X> &a) 1349{ 1350 return a.or_reduce(); 1351} 1352 1353template <class X> 1354inline typename sc_proxy<X>::value_type 1355nor_reduce(const sc_proxy<X> &a) 1356{ 1357 return a.nor_reduce(); 1358} 1359 1360template <class X> 1361inline typename sc_proxy<X>::value_type 1362xor_reduce(const sc_proxy<X> &a) 1363{ 1364 return a.xor_reduce(); 1365} 1366 1367template <class X> 1368inline typename sc_proxy<X>::value_type 1369xnor_reduce(const sc_proxy<X> &a) 1370{ 1371 return a.xnor_reduce(); 1372} 1373 1374// ---------------------------------------------------------------------------- 1375 1376template <class X> 1377inline ::std::ostream & 1378operator << (::std::ostream &os, const sc_proxy<X> &a) 1379{ 1380 a.print(os); 1381 return os; 1382} 1383 1384template <class X> 1385inline ::std::istream & 1386operator >> (::std::istream &is, sc_proxy<X> &a) 1387{ 1388 a.scan(is); 1389 return is; 1390} 1391 1392} // namespace sc_dt 1393 1394#endif // __SYSTEMC_EXT_DT_BIT_SC_PROXY_HH__ 1395