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_SIGNAL_HH__ 31#define __SYSTEMC_EXT_CHANNEL_SC_SIGNAL_HH__ 32 33#include <iostream> 34#include <string> 35#include <vector> 36 37#include "../core/sc_event.hh" 38#include "../core/sc_module.hh" // for sc_gen_unique_name 39#include "../core/sc_prim.hh" 40#include "../dt/bit/sc_logic.hh" 41#include "sc_signal_inout_if.hh" 42 43namespace sc_core 44{ 45 46class sc_port_base; 47 48} // namespace sc_core 49 50namespace sc_gem5 51{ 52 53class Process; 54class Reset; 55 56class ScSignalBase : public sc_core::sc_prim_channel 57{ 58 public: 59 virtual const char *kind() const { return "sc_signal"; } 60 61 protected: 62 ScSignalBase(const char *_name); 63 virtual ~ScSignalBase(); 64 65 const sc_core::sc_event &defaultEvent() const; 66 const sc_core::sc_event &valueChangedEvent() const; 67 68 bool event() const; 69 70 void _signalChange(); 71 72 virtual sc_core::sc_writer_policy get_writer_policy() const = 0; 73 74 InternalScEvent _valueChangedEvent; 75 uint64_t _changeStamp; 76 sc_core::sc_port_base *_gem5WriterPort; 77}; 78 79class ScSignalBaseBinary : public ScSignalBase 80{ 81 protected: 82 ScSignalBaseBinary(const char *_name); 83 84 mutable std::vector<sc_gem5::Reset *> _resets; 85 void _signalReset(sc_gem5::Reset *reset); 86 void _signalReset(); 87 88 const sc_core::sc_event &posedgeEvent() const; 89 const sc_core::sc_event &negedgeEvent() const; 90 91 bool posedge() const; 92 bool negedge() const; 93 94 InternalScEvent _posedgeEvent; 95 InternalScEvent _negedgeEvent; 96 97 uint64_t _posStamp; 98 uint64_t _negStamp; 99 100 void _signalPosedge(); 101 void _signalNegedge(); 102}; 103 104template <class T> 105class ScSignalBasePicker : public ScSignalBase 106{ 107 protected: 108 ScSignalBasePicker(const char *_name) : ScSignalBase(_name) {} 109}; 110 111template <> 112class ScSignalBasePicker<bool> : public ScSignalBaseBinary 113{ 114 protected: 115 ScSignalBasePicker(const char *_name) : ScSignalBaseBinary(_name) {} 116}; 117 118template <> 119class ScSignalBasePicker<sc_dt::sc_logic> : public ScSignalBaseBinary 120{ 121 protected: 122 ScSignalBasePicker(const char *_name) : ScSignalBaseBinary(_name) {} 123}; 124 125template <sc_core::sc_writer_policy WRITER_POLICY> 126class WriteChecker; 127 128template <> 129class WriteChecker<sc_core::SC_ONE_WRITER> 130{ 131 public: 132 WriteChecker(ScSignalBase *_sig); 133 134 void checkPort(sc_core::sc_port_base &port, 135 std::string iface_type_name, std::string out_name); 136 void checkWriter(); 137 138 private: 139 ScSignalBase *sig; 140 sc_core::sc_port_base *firstPort; 141 Process *proc; 142 uint64_t writeStamp; 143}; 144 145template <> 146class WriteChecker<sc_core::SC_MANY_WRITERS> 147{ 148 public: 149 WriteChecker(ScSignalBase *_sig); 150 151 void checkPort(sc_core::sc_port_base &port, 152 std::string iface_type_name, std::string out_name); 153 void checkWriter(); 154 155 private: 156 ScSignalBase *sig; 157 Process *proc; 158 uint64_t writeStamp; 159}; 160 161template <class T, sc_core::sc_writer_policy WRITER_POLICY> 162class ScSignalBaseT : 163 public ScSignalBasePicker<T>, public sc_core::sc_signal_inout_if<T> 164{ 165 public: 166 ScSignalBaseT(const char *_name) : 167 ScSignalBasePicker<T>(_name), m_cur_val(T()), m_new_val(T()), 168 _checker(this) 169 {} 170 ScSignalBaseT(const char *_name, const T &initial_value) : 171 ScSignalBasePicker<T>(_name), m_cur_val(initial_value), 172 m_new_val(initial_value), _checker(this) 173 {} 174 virtual ~ScSignalBaseT() {} 175 176 virtual void 177 register_port(sc_core::sc_port_base &port, const char *iface_type_name) 178 { 179# if !defined(SC_NO_WRITE_CHECK) 180 { 181 _checker.checkPort(port, iface_type_name, 182 typeid(sc_core::sc_signal_inout_if<T>).name()); 183 } 184# endif 185 } 186 187 virtual const T &read() const { return m_cur_val; } 188 operator const T&() const { return read(); } 189 190 virtual void 191 write(const T &t) 192 { 193# if !defined(SC_NO_WRITE_CHECK) 194 { 195 _checker.checkWriter(); 196 } 197# endif 198 m_new_val = t; 199 bool changed = !(m_cur_val == m_new_val); 200 if (changed) 201 this->request_update(); 202 } 203 204 virtual const sc_core::sc_event & 205 default_event() const 206 { 207 return ScSignalBase::defaultEvent(); 208 } 209 210 virtual const sc_core::sc_event & 211 value_changed_event() const 212 { 213 return ScSignalBase::valueChangedEvent(); 214 } 215 216 virtual void print(std::ostream &os=std::cout) const { os << m_cur_val; } 217 virtual void 218 dump(std::ostream &os=std::cout) const 219 { 220 os << " name = " << this->name() << ::std::endl; 221 os << " value = " << m_cur_val << ::std::endl; 222 os << "new value = " << m_new_val << ::std::endl; 223 } 224 225 virtual bool event() const { return ScSignalBase::event(); } 226 227 virtual sc_core::sc_writer_policy 228 get_writer_policy() const 229 { 230 return WRITER_POLICY; 231 } 232 233 protected: 234 // These members which store the current and future value of the signal 235 // are not specified in the standard but are referred to directly by one 236 // of the tests. 237 T m_cur_val; 238 T m_new_val; 239 240 WriteChecker<WRITER_POLICY> _checker; 241}; 242 243template <typename T, sc_core::sc_writer_policy WRITER_POLICY> 244class ScSignalBinary : public ScSignalBaseT<T, WRITER_POLICY> 245{ 246 public: 247 ScSignalBinary(const char *_name) : ScSignalBaseT<T, WRITER_POLICY>(_name) 248 {} 249 ScSignalBinary(const char *_name, const T& initial_value) : 250 ScSignalBaseT<T, WRITER_POLICY>(_name, initial_value) 251 {} 252 253 const sc_core::sc_event & 254 posedge_event() const 255 { 256 return ScSignalBaseBinary::posedgeEvent(); 257 } 258 const sc_core::sc_event & 259 negedge_event() const 260 { 261 return ScSignalBaseBinary::negedgeEvent(); 262 } 263 264 bool posedge() const { return ScSignalBaseBinary::posedge(); } 265 bool negedge() const { return ScSignalBaseBinary::negedge(); } 266}; 267 268} // namespace sc_gem5 269 270namespace sc_core 271{ 272 273template <class T, sc_writer_policy WRITER_POLICY=SC_ONE_WRITER> 274class sc_signal : public sc_gem5::ScSignalBaseT<T, WRITER_POLICY> 275{ 276 public: 277 sc_signal() : sc_gem5::ScSignalBaseT<T, WRITER_POLICY>( 278 sc_gen_unique_name("signal")) 279 {} 280 explicit sc_signal(const char *name) : 281 sc_gem5::ScSignalBaseT<T, WRITER_POLICY>(name) 282 {} 283 explicit sc_signal(const char *name, const T &initial_value) : 284 sc_gem5::ScSignalBaseT<T, WRITER_POLICY>(name, initial_value) 285 {} 286 virtual ~sc_signal() {} 287 288 sc_signal<T, WRITER_POLICY> & 289 operator = (const T &t) 290 { 291 this->write(t); 292 return *this; 293 } 294 sc_signal<T, WRITER_POLICY> & 295 operator = (const sc_signal<T, WRITER_POLICY> &s) 296 { 297 this->write(s.read()); 298 return *this; 299 } 300 301 protected: 302 virtual void 303 update() 304 { 305 if (this->m_new_val == this->m_cur_val) 306 return; 307 308 this->m_cur_val = this->m_new_val; 309 this->_signalChange(); 310 } 311 312 private: 313 // Disabled 314 sc_signal(const sc_signal<T, WRITER_POLICY> &); 315}; 316 317template <class T, sc_writer_policy WRITER_POLICY> 318inline std::ostream & 319operator << (std::ostream &os, const sc_signal<T, WRITER_POLICY> &s) 320{ 321 os << s.read(); 322 return os; 323} 324 325template <sc_writer_policy WRITER_POLICY> 326class sc_signal<bool, WRITER_POLICY> : 327 public sc_gem5::ScSignalBinary<bool, WRITER_POLICY> 328{ 329 public: 330 sc_signal() : 331 sc_gem5::ScSignalBinary<bool, WRITER_POLICY>( 332 sc_gen_unique_name("signal")) 333 {} 334 explicit sc_signal(const char *name) : 335 sc_gem5::ScSignalBinary<bool, WRITER_POLICY>(name) 336 {} 337 explicit sc_signal(const char *name, const bool &initial_value) : 338 sc_gem5::ScSignalBinary<bool, WRITER_POLICY>(name, initial_value) 339 {} 340 virtual ~sc_signal() {} 341 342 sc_signal<bool, WRITER_POLICY> & 343 operator = (const bool &b) 344 { 345 this->write(b); 346 return *this; 347 } 348 sc_signal<bool, WRITER_POLICY> & 349 operator = (const sc_signal<bool, WRITER_POLICY> &s) 350 { 351 this->write(s.read()); 352 return *this; 353 } 354 355 protected: 356 virtual void 357 update() 358 { 359 if (this->m_new_val == this->m_cur_val) 360 return; 361 362 this->m_cur_val = this->m_new_val; 363 this->_signalChange(); 364 } 365 366 void 367 _signalChange() 368 { 369 sc_gem5::ScSignalBinary<bool, WRITER_POLICY>::_signalChange(); 370 this->_signalReset(); 371 if (this->m_cur_val) 372 this->_signalPosedge(); 373 else 374 this->_signalNegedge(); 375 } 376 377 private: 378 bool 379 _addReset(sc_gem5::Reset *reset) const 380 { 381 this->_resets.push_back(reset); 382 return true; 383 } 384 385 // Disabled 386 sc_signal(const sc_signal<bool, WRITER_POLICY> &); 387}; 388 389template <sc_writer_policy WRITER_POLICY> 390class sc_signal<sc_dt::sc_logic, WRITER_POLICY> : 391 public sc_gem5::ScSignalBinary<sc_dt::sc_logic, WRITER_POLICY> 392{ 393 public: 394 sc_signal() : 395 sc_gem5::ScSignalBinary<sc_dt::sc_logic, WRITER_POLICY>( 396 sc_gen_unique_name("signal")) 397 {} 398 explicit sc_signal(const char *name) : 399 sc_gem5::ScSignalBinary<sc_dt::sc_logic, WRITER_POLICY>(name) 400 {} 401 explicit sc_signal(const char *name, 402 const sc_dt::sc_logic &initial_value) : 403 sc_gem5::ScSignalBinary<sc_dt::sc_logic, WRITER_POLICY>( 404 name, initial_value) 405 {} 406 virtual ~sc_signal() {} 407 408 sc_signal<sc_dt::sc_logic, WRITER_POLICY> & 409 operator = (const sc_dt::sc_logic &l) 410 { 411 this->write(l); 412 return *this; 413 } 414 sc_signal<sc_dt::sc_logic, WRITER_POLICY> & 415 operator = (const sc_signal<sc_dt::sc_logic, WRITER_POLICY> &s) 416 { 417 this->write(s.read()); 418 return *this; 419 } 420 421 protected: 422 virtual void 423 update() 424 { 425 if (this->m_new_val == this->m_cur_val) 426 return; 427 428 this->m_cur_val = this->m_new_val; 429 this->_signalChange(); 430 } 431 432 void 433 _signalChange() 434 { 435 sc_gem5::ScSignalBinary<sc_dt::sc_logic, WRITER_POLICY>:: 436 _signalChange(); 437 if (this->m_cur_val == sc_dt::SC_LOGIC_1) 438 this->_signalPosedge(); 439 else if (this->m_cur_val == sc_dt::SC_LOGIC_0) 440 this->_signalNegedge(); 441 } 442 443 private: 444 // Disabled 445 sc_signal(const sc_signal<sc_dt::sc_logic, WRITER_POLICY> &); 446}; 447 448} // namespace sc_core 449 450#endif //__SYSTEMC_EXT_CHANNEL_SC_SIGNAL_HH__ 451