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