1/* 2 * Copyright 2018 Google, Inc. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: redistributions of source code must retain the above copyright 7 * notice, this list of conditions and the following disclaimer; 8 * redistributions in binary form must reproduce the above copyright 9 * notice, this list of conditions and the following disclaimer in the 10 * documentation and/or other materials provided with the distribution; 11 * neither the name of the copyright holders nor the names of its 12 * contributors may be used to endorse or promote products derived from 13 * this software without specific prior written permission. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 * 27 * Authors: Gabe Black 28 */ 29 30#ifndef __SYSTEMC_EXT_CHANNEL_SC_INOUT_HH__ 31#define __SYSTEMC_EXT_CHANNEL_SC_INOUT_HH__ 32 33#include <string> 34 35#include "../core/sc_event.hh" 36#include "../core/sc_main.hh" 37#include "../core/sc_port.hh" 38#include "../dt/bit/sc_logic.hh" 39#include "../utils/sc_trace_file.hh" 40#include "sc_signal_inout_if.hh" 41 42namespace sc_dt 43{ 44 45class sc_logic; 46 47} // namespace sc_dt 48 49namespace sc_core 50{ 51 52class sc_event; 53class sc_trace_file; 54 55template <class T> 56class sc_inout : public sc_port<sc_signal_inout_if<T>, 1> 57{ 58 public: 59 sc_inout() : sc_port<sc_signal_inout_if<T>, 1>(), initValue(nullptr), 60 _valueChangedFinder(*this, &sc_signal_inout_if<T>::value_changed_event) 61 {} 62 explicit sc_inout(const char *name) : 63 sc_port<sc_signal_inout_if<T>, 1>(name), initValue(nullptr), 64 _valueChangedFinder(*this, &sc_signal_inout_if<T>::value_changed_event) 65 {} 66 virtual ~sc_inout() { delete initValue; } 67 68 // Deprecated binding constructors. 69 explicit sc_inout(const sc_signal_inout_if<T> &interface) : 70 sc_port<sc_signal_inout_if<T>, 1>(interface), initValue(nullptr), 71 _valueChangedFinder(*this, &sc_signal_inout_if<T>::value_changed_event) 72 {} 73 sc_inout(const char *name, const sc_signal_inout_if<T> &interface) : 74 sc_port<sc_signal_inout_if<T>, 1>(name, interface), initValue(nullptr), 75 _valueChangedFinder(*this, &sc_signal_inout_if<T>::value_changed_event) 76 {} 77 explicit sc_inout(sc_port_b<sc_signal_inout_if<T> > &parent) : 78 sc_port<sc_signal_inout_if<T>, 1>(parent), initValue(nullptr), 79 _valueChangedFinder(*this, &sc_signal_inout_if<T>::value_changed_event) 80 {} 81 sc_inout(const char *name, sc_port_b<sc_signal_inout_if<T> > &parent) : 82 sc_port<sc_signal_inout_if<T>, 1>(name, parent), initValue(nullptr), 83 _valueChangedFinder(*this, &sc_signal_inout_if<T>::value_changed_event) 84 {} 85 explicit sc_inout(sc_port<sc_signal_inout_if<T>, 1> &parent) : 86 sc_port<sc_signal_inout_if<T>, 1>(parent), initValue(nullptr), 87 _valueChangedFinder(*this, &sc_signal_inout_if<T>::value_changed_event) 88 {} 89 sc_inout(const char *name, sc_port<sc_signal_inout_if<T>, 1> &parent) : 90 sc_port<sc_signal_inout_if<T>, 1>(name, parent), initValue(nullptr), 91 _valueChangedFinder(*this, &sc_signal_inout_if<T>::value_changed_event) 92 {} 93 94 void 95 initialize(const T &t) 96 { 97 if (this->size()) { 98 (*this)->write(t); 99 } else { 100 if (!initValue) 101 initValue = new T; 102 *initValue = t; 103 } 104 } 105 void initialize(const sc_signal_in_if<T> &i) { initialize(i.read()); } 106 107 virtual void 108 end_of_elaboration() 109 { 110 if (initValue) { 111 write(*initValue); 112 delete initValue; 113 initValue = nullptr; 114 } 115 116 for (auto params: traceParamsVec) 117 sc_trace(params->tf, (*this)->read(), params->name); 118 119 traceParamsVec.clear(); 120 } 121 122 const T &read() const { return (*this)->read(); } 123 operator const T& () const { return (*this)->read(); } 124 125 void write(const T &t) { (*this)->write(t); } 126 sc_inout<T> & 127 operator = (const T &t) 128 { 129 (*this)->write(t); 130 return *this; 131 } 132 sc_inout<T> & 133 operator = (const sc_signal_in_if<T> &i) 134 { 135 (*this)->write(i.read()); 136 return *this; 137 } 138 sc_inout<T> & 139 operator = (const sc_port<sc_signal_in_if<T>, 1> &p) 140 { 141 (*this)->write(p->read()); 142 return *this; 143 } 144 sc_inout<T> & 145 operator = (const sc_port<sc_signal_inout_if<T>, 1> &p) 146 { 147 (*this)->write(p->read()); 148 return *this; 149 } 150 sc_inout<T> & 151 operator = (const sc_inout<T> &p) 152 { 153 (*this)->write(p->read()); 154 return *this; 155 } 156 157 const sc_event &default_event() const { return (*this)->default_event(); } 158 const sc_event & 159 value_changed_event() const 160 { 161 return (*this)->value_changed_event(); 162 } 163 bool event() const { return (*this)->event(); } 164 sc_event_finder &value_changed() const { return _valueChangedFinder; } 165 166 virtual const char *kind() const { return "sc_inout"; } 167 168 void 169 add_trace(sc_trace_file *tf, const std::string &name) const 170 { 171 traceParamsVec.push_back(new sc_trace_params(tf, name)); 172 } 173 174 private: 175 T *initValue; 176 mutable sc_event_finder_t<sc_signal_inout_if<T> > _valueChangedFinder; 177 178 mutable sc_trace_params_vec traceParamsVec; 179 180 // Disabled 181 sc_inout(const sc_inout<T> &); 182}; 183 184template <class T> 185inline void 186sc_trace(sc_trace_file *tf, const sc_inout<T> &i, const std::string &name) 187{ 188 if (::sc_core::sc_get_status() < ::sc_core::SC_START_OF_SIMULATION) 189 i.add_trace(tf, name); 190 else 191 sc_trace(tf, i->read(), name); 192} 193 194template <> 195class sc_inout<bool> : public sc_port<sc_signal_inout_if<bool>, 1> 196{ 197 public: 198 sc_inout() : sc_port<sc_signal_inout_if<bool>, 1>(), initValue(nullptr), 199 _valueChangedFinder(*this, 200 &sc_signal_inout_if<bool>::value_changed_event), 201 _posFinder(*this, &sc_signal_inout_if<bool>::posedge_event), 202 _negFinder(*this, &sc_signal_inout_if<bool>::negedge_event) 203 {} 204 explicit sc_inout(const char *name) : 205 sc_port<sc_signal_inout_if<bool>, 1>(name), initValue(nullptr), 206 _valueChangedFinder(*this, 207 &sc_signal_inout_if<bool>::value_changed_event), 208 _posFinder(*this, &sc_signal_inout_if<bool>::posedge_event), 209 _negFinder(*this, &sc_signal_inout_if<bool>::negedge_event) 210 {} 211 virtual ~sc_inout() { delete initValue; } 212 213 // Deprecated binding constructors. 214 explicit sc_inout(const sc_signal_inout_if<bool> &interface) : 215 sc_port<sc_signal_inout_if<bool>, 1>(interface), initValue(nullptr), 216 _valueChangedFinder(*this, 217 &sc_signal_inout_if<bool>::value_changed_event), 218 _posFinder(*this, &sc_signal_inout_if<bool>::posedge_event), 219 _negFinder(*this, &sc_signal_inout_if<bool>::negedge_event) 220 {} 221 sc_inout(const char *name, const sc_signal_inout_if<bool> &interface) : 222 sc_port<sc_signal_inout_if<bool>, 1>(name, interface), 223 initValue(nullptr), 224 _valueChangedFinder(*this, 225 &sc_signal_inout_if<bool>::value_changed_event), 226 _posFinder(*this, &sc_signal_inout_if<bool>::posedge_event), 227 _negFinder(*this, &sc_signal_inout_if<bool>::negedge_event) 228 {} 229 explicit sc_inout(sc_port_b<sc_signal_inout_if<bool> > &parent) : 230 sc_port<sc_signal_inout_if<bool>, 1>(parent), initValue(nullptr), 231 _valueChangedFinder(*this, 232 &sc_signal_inout_if<bool>::value_changed_event), 233 _posFinder(*this, &sc_signal_inout_if<bool>::posedge_event), 234 _negFinder(*this, &sc_signal_inout_if<bool>::negedge_event) 235 {} 236 sc_inout(const char *name, sc_port_b<sc_signal_inout_if<bool> > &parent) : 237 sc_port<sc_signal_inout_if<bool>, 1>(name, parent), initValue(nullptr), 238 _valueChangedFinder(*this, 239 &sc_signal_inout_if<bool>::value_changed_event), 240 _posFinder(*this, &sc_signal_inout_if<bool>::posedge_event), 241 _negFinder(*this, &sc_signal_inout_if<bool>::negedge_event) 242 {} 243 explicit sc_inout(sc_port<sc_signal_inout_if<bool>, 1> &parent) : 244 sc_port<sc_signal_inout_if<bool>, 1>(parent), initValue(nullptr), 245 _valueChangedFinder(*this, 246 &sc_signal_inout_if<bool>::value_changed_event), 247 _posFinder(*this, &sc_signal_inout_if<bool>::posedge_event), 248 _negFinder(*this, &sc_signal_inout_if<bool>::negedge_event) 249 {} 250 sc_inout(const char *name, sc_port<sc_signal_inout_if<bool>, 1> &parent) : 251 sc_port<sc_signal_inout_if<bool>, 1>(name, parent), initValue(nullptr), 252 _valueChangedFinder(*this, 253 &sc_signal_inout_if<bool>::value_changed_event), 254 _posFinder(*this, &sc_signal_inout_if<bool>::posedge_event), 255 _negFinder(*this, &sc_signal_inout_if<bool>::negedge_event) 256 {} 257 258 void 259 initialize(const bool &b) 260 { 261 if (this->size()) { 262 (*this)->write(b); 263 } else { 264 if (!initValue) 265 initValue = new bool; 266 *initValue = b; 267 } 268 } 269 void initialize(const sc_signal_in_if<bool> &i) { initialize(i.read()); } 270 271 virtual void 272 end_of_elaboration() 273 { 274 if (initValue) { 275 write(*initValue); 276 delete initValue; 277 initValue = nullptr; 278 } 279 280 for (auto params: traceParamsVec) 281 sc_trace(params->tf, (*this)->read(), params->name); 282 283 traceParamsVec.clear(); 284 } 285 286 const bool &read() const { return (*this)->read(); } 287 operator const bool& () const { return (*this)->read(); } 288 289 void write(const bool &b) { (*this)->write(b); } 290 sc_inout<bool> & 291 operator = (const bool &b) 292 { 293 (*this)->write(b); 294 return *this; 295 } 296 sc_inout<bool> & 297 operator = (const sc_signal_in_if<bool> &i) 298 { 299 (*this)->write(i.read()); 300 return *this; 301 } 302 sc_inout<bool> & 303 operator = (const sc_port<sc_signal_in_if<bool>, 1> &p) 304 { 305 (*this)->write(p->read()); 306 return *this; 307 } 308 sc_inout<bool> & 309 operator = (const sc_port<sc_signal_inout_if<bool>, 1> &p) 310 { 311 (*this)->write(p->read()); 312 return *this; 313 } 314 sc_inout<bool> & 315 operator = (const sc_inout<bool> &p) 316 { 317 (*this)->write(p->read()); 318 return *this; 319 } 320 321 const sc_event &default_event() const { return (*this)->default_event(); } 322 const sc_event & 323 value_changed_event() const 324 { 325 return (*this)->value_changed_event(); 326 } 327 const sc_event &posedge_event() const { return (*this)->posedge_event(); } 328 const sc_event &negedge_event() const { return (*this)->negedge_event(); } 329 bool event() const { return (*this)->event(); } 330 bool posedge() const { return (*this)->posedge(); } 331 bool negedge() const { return (*this)->negedge(); } 332 333 sc_event_finder &value_changed() const { return _valueChangedFinder; } 334 sc_event_finder &pos() const { return _posFinder; } 335 sc_event_finder &neg() const { return _negFinder; } 336 337 virtual const char *kind() const { return "sc_inout"; } 338 339 void 340 add_trace(sc_trace_file *tf, const std::string &name) const 341 { 342 traceParamsVec.push_back(new sc_trace_params(tf, name)); 343 } 344 345 private: 346 bool *initValue; 347 mutable sc_event_finder_t<sc_signal_inout_if<bool> > _valueChangedFinder; 348 mutable sc_event_finder_t<sc_signal_inout_if<bool> > _posFinder; 349 mutable sc_event_finder_t<sc_signal_inout_if<bool> > _negFinder; 350 351 mutable sc_trace_params_vec traceParamsVec; 352 353 // Disabled 354 sc_inout(const sc_inout<bool> &); 355}; 356 357template <> 358inline void sc_trace<bool>( 359 sc_trace_file *tf, const sc_inout<bool> &i, const std::string &name) 360{ 361 if (::sc_core::sc_get_status() < ::sc_core::SC_START_OF_SIMULATION) 362 i.add_trace(tf, name); 363 else 364 sc_trace(tf, i->read(), name); 365} 366 367template <> 368class sc_inout<sc_dt::sc_logic> : 369 public sc_port<sc_signal_inout_if<sc_dt::sc_logic>, 1> 370{ 371 public: 372 sc_inout() : sc_port<sc_signal_inout_if<sc_dt::sc_logic>, 1>(), 373 initValue(nullptr), 374 _valueChangedFinder(*this, 375 &sc_signal_inout_if<sc_dt::sc_logic>::value_changed_event), 376 _posFinder(*this, &sc_signal_inout_if<sc_dt::sc_logic>::posedge_event), 377 _negFinder(*this, &sc_signal_inout_if<sc_dt::sc_logic>::negedge_event) 378 {} 379 explicit sc_inout(const char *name) : 380 sc_port<sc_signal_inout_if<sc_dt::sc_logic>, 1>(name), 381 initValue(nullptr), 382 _valueChangedFinder(*this, 383 &sc_signal_inout_if<sc_dt::sc_logic>::value_changed_event), 384 _posFinder(*this, &sc_signal_inout_if<sc_dt::sc_logic>::posedge_event), 385 _negFinder(*this, &sc_signal_inout_if<sc_dt::sc_logic>::negedge_event) 386 {} 387 virtual ~sc_inout() { delete initValue; } 388 389 // Deprecated binding constructors. 390 explicit sc_inout(const sc_signal_inout_if<sc_dt::sc_logic> &interface) : 391 sc_port<sc_signal_inout_if<sc_dt::sc_logic>, 1>(interface), 392 initValue(nullptr), 393 _valueChangedFinder(*this, 394 &sc_signal_inout_if<sc_dt::sc_logic>::value_changed_event), 395 _posFinder(*this, &sc_signal_inout_if<sc_dt::sc_logic>::posedge_event), 396 _negFinder(*this, &sc_signal_inout_if<sc_dt::sc_logic>::negedge_event) 397 {} 398 sc_inout(const char *name, 399 const sc_signal_inout_if<sc_dt::sc_logic> &interface) : 400 sc_port<sc_signal_inout_if<sc_dt::sc_logic>, 1>(name, interface), 401 initValue(nullptr), 402 _valueChangedFinder(*this, 403 &sc_signal_inout_if<sc_dt::sc_logic>::value_changed_event), 404 _posFinder(*this, &sc_signal_inout_if<sc_dt::sc_logic>::posedge_event), 405 _negFinder(*this, &sc_signal_inout_if<sc_dt::sc_logic>::negedge_event) 406 {} 407 explicit sc_inout( 408 sc_port_b<sc_signal_inout_if<sc_dt::sc_logic> > &parent) : 409 sc_port<sc_signal_inout_if<sc_dt::sc_logic>, 1>(parent), 410 initValue(nullptr), 411 _valueChangedFinder(*this, 412 &sc_signal_inout_if<sc_dt::sc_logic>::value_changed_event), 413 _posFinder(*this, &sc_signal_inout_if<sc_dt::sc_logic>::posedge_event), 414 _negFinder(*this, &sc_signal_inout_if<sc_dt::sc_logic>::negedge_event) 415 {} 416 sc_inout(const char *name, 417 sc_port_b<sc_signal_inout_if<sc_dt::sc_logic> > &parent) : 418 sc_port<sc_signal_inout_if<sc_dt::sc_logic>, 1>(name, parent), 419 initValue(nullptr), 420 _valueChangedFinder(*this, 421 &sc_signal_inout_if<sc_dt::sc_logic>::value_changed_event), 422 _posFinder(*this, &sc_signal_inout_if<sc_dt::sc_logic>::posedge_event), 423 _negFinder(*this, &sc_signal_inout_if<sc_dt::sc_logic>::negedge_event) 424 {} 425 explicit sc_inout( 426 sc_port<sc_signal_inout_if<sc_dt::sc_logic>, 1> &parent) : 427 sc_port<sc_signal_inout_if<sc_dt::sc_logic>, 1>(parent), 428 initValue(nullptr), 429 _valueChangedFinder(*this, 430 &sc_signal_inout_if<sc_dt::sc_logic>::value_changed_event), 431 _posFinder(*this, &sc_signal_inout_if<sc_dt::sc_logic>::posedge_event), 432 _negFinder(*this, &sc_signal_inout_if<sc_dt::sc_logic>::negedge_event) 433 {} 434 sc_inout(const char *name, 435 sc_port<sc_signal_inout_if<sc_dt::sc_logic>, 1> &parent) : 436 sc_port<sc_signal_inout_if<sc_dt::sc_logic>, 1>(name, parent), 437 initValue(nullptr), 438 _valueChangedFinder(*this, 439 &sc_signal_inout_if<sc_dt::sc_logic>::value_changed_event), 440 _posFinder(*this, &sc_signal_inout_if<sc_dt::sc_logic>::posedge_event), 441 _negFinder(*this, &sc_signal_inout_if<sc_dt::sc_logic>::negedge_event) 442 {} 443 444 void 445 initialize(const sc_dt::sc_logic &l) 446 { 447 if (this->size()) { 448 (*this)->write(l); 449 } else { 450 if (!initValue) 451 initValue = new sc_dt::sc_logic; 452 *initValue = l; 453 } 454 } 455 void 456 initialize(const sc_signal_in_if<sc_dt::sc_logic> &i) 457 { 458 initialize(i.read()); 459 } 460 461 virtual void 462 end_of_elaboration() 463 { 464 if (initValue) { 465 write(*initValue); 466 delete initValue; 467 initValue = nullptr; 468 } 469 470 for (auto params: traceParamsVec) 471 sc_trace(params->tf, (*this)->read(), params->name); 472 473 traceParamsVec.clear(); 474 } 475 476 const sc_dt::sc_logic &read() const { return (*this)->read(); } 477 operator const sc_dt::sc_logic& () const { return (*this)->read(); } 478 479 void write(const sc_dt::sc_logic &l) { (*this)->write(l); } 480 sc_inout<sc_dt::sc_logic> & 481 operator = (const sc_dt::sc_logic &l) 482 { 483 (*this)->write(l); 484 return *this; 485 } 486 sc_inout<sc_dt::sc_logic> & 487 operator = (const sc_signal_in_if<sc_dt::sc_logic> &i) 488 { 489 (*this)->write(i.read()); 490 return *this; 491 } 492 sc_inout<sc_dt::sc_logic> & 493 operator = (const sc_port<sc_signal_in_if<sc_dt::sc_logic>, 1> &p) 494 { 495 (*this)->write(p->read()); 496 return *this; 497 } 498 sc_inout<sc_dt::sc_logic> & 499 operator = (const sc_port<sc_signal_inout_if<sc_dt::sc_logic>, 1> &p) 500 { 501 (*this)->write(p->read()); 502 return *this; 503 } 504 sc_inout<sc_dt::sc_logic> & 505 operator = (const sc_inout<sc_dt::sc_logic> &p) 506 { 507 (*this)->write(p->read()); 508 return *this; 509 } 510 511 const sc_event &default_event() const { return (*this)->default_event(); } 512 const sc_event & 513 value_changed_event() const 514 { 515 return (*this)->value_changed_event(); 516 } 517 const sc_event &posedge_event() const { return (*this)->posedge_event(); } 518 const sc_event &negedge_event() const { return (*this)->negedge_event(); } 519 bool event() const { return (*this)->event(); } 520 bool posedge() const { return (*this)->posedge(); } 521 bool negedge() const { return (*this)->negedge(); } 522 523 sc_event_finder &value_changed() const { return _valueChangedFinder; } 524 sc_event_finder &pos() const { return _posFinder; } 525 sc_event_finder &neg() const { return _negFinder; } 526 527 virtual const char *kind() const { return "sc_inout"; } 528 529 void 530 add_trace(sc_trace_file *tf, const std::string &name) const 531 { 532 traceParamsVec.push_back(new sc_trace_params(tf, name)); 533 } 534 535 private: 536 sc_dt::sc_logic *initValue; 537 mutable sc_event_finder_t< 538 sc_signal_inout_if<sc_dt::sc_logic> > _valueChangedFinder; 539 mutable sc_event_finder_t<sc_signal_inout_if<sc_dt::sc_logic> > _posFinder; 540 mutable sc_event_finder_t<sc_signal_inout_if<sc_dt::sc_logic> > _negFinder; 541 542 mutable sc_trace_params_vec traceParamsVec; 543 544 // Disabled 545 sc_inout(const sc_inout<sc_dt::sc_logic> &); 546}; 547 548template <> 549inline void 550sc_trace<sc_dt::sc_logic>(sc_trace_file *tf, 551 const sc_inout<sc_dt::sc_logic> &i, const std::string &name) 552{ 553 if (::sc_core::sc_get_status() < ::sc_core::SC_START_OF_SIMULATION) 554 i.add_trace(tf, name); 555 else 556 sc_trace(tf, i->read(), name); 557} 558 559} // namespace sc_core 560 561#endif //__SYSTEMC_EXT_CHANNEL_SC_INOUT_HH__ 562