sc_signal.cc revision 13288:f1c04129f709
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#include <sstream> 31 32#include "systemc/core/scheduler.hh" 33#include "systemc/ext/channel/sc_signal.hh" 34#include "systemc/ext/core/sc_main.hh" 35 36namespace sc_gem5 37{ 38 39ScSignalBase::ScSignalBase(const char *name) : 40 sc_core::sc_prim_channel(name), _changeStamp(~0ULL), 41 _gem5WriterPort(nullptr) 42{} 43 44ScSignalBase::~ScSignalBase() {} 45 46const sc_core::sc_event & 47ScSignalBase::defaultEvent() const 48{ 49 return valueChangedEvent(); 50} 51 52const sc_core::sc_event & 53ScSignalBase::valueChangedEvent() const 54{ 55 return _valueChangedEvent; 56} 57 58bool 59ScSignalBase::event() const 60{ 61 return _changeStamp == getChangeStamp(); 62} 63 64void 65ScSignalBase::_signalChange() 66{ 67 _changeStamp = getChangeStamp(); 68 _valueChangedEvent.notify(sc_core::SC_ZERO_TIME); 69} 70 71namespace 72{ 73 74void 75reportSignalError(ScSignalBase *sig, sc_core::sc_object *first, 76 sc_core::sc_object *second, bool delta_conflict=false) 77{ 78 std::ostringstream ss; 79 ss << "\n signal " << "`" << sig->name() << "' (" << sig->kind() << ")"; 80 ss << "\n first driver `" << first->name() << "' (" << 81 first->kind() << ")"; 82 ss << "\n second driver `" << second->name() << "' (" << 83 second->kind() << ")"; 84 if (delta_conflict) { 85 ss << "\n conflicting write in delta cycle " << 86 sc_core::sc_delta_count(); 87 } 88 SC_REPORT_ERROR( 89 "(E115) sc_signal<T> cannot have more than one driver", 90 ss.str().c_str()); 91} 92 93} // anonymous namespace 94 95WriteChecker<sc_core::SC_ONE_WRITER>::WriteChecker(ScSignalBase *_sig) : 96 sig(_sig), firstPort(nullptr), proc(nullptr), writeStamp(~0ULL) 97{} 98 99void 100WriteChecker<sc_core::SC_ONE_WRITER>::checkPort(sc_core::sc_port_base &port, 101 std::string iface_type_name, std::string out_name) 102{ 103 if (iface_type_name == out_name) { 104 if (firstPort) 105 reportSignalError(sig, firstPort, &port); 106 firstPort = &port; 107 } 108} 109 110void 111WriteChecker<sc_core::SC_ONE_WRITER>::checkWriter() 112{ 113 Process *p = scheduler.current(); 114 if (!p) 115 return; 116 uint64_t stamp = getChangeStamp(); 117 if (proc && proc != p) 118 reportSignalError(sig, proc, p); 119 proc = p; 120 writeStamp = stamp; 121} 122 123WriteChecker<sc_core::SC_MANY_WRITERS>::WriteChecker(ScSignalBase *_sig) : 124 sig(_sig), proc(nullptr), writeStamp(~0ULL) 125{} 126 127void 128WriteChecker<sc_core::SC_MANY_WRITERS>::checkPort(sc_core::sc_port_base &port, 129 std::string iface_type_name, std::string out_name) 130{ 131 return; 132} 133 134void 135WriteChecker<sc_core::SC_MANY_WRITERS>::checkWriter() 136{ 137 Process *p = scheduler.current(); 138 if (!p) 139 return; 140 uint64_t stamp = getChangeStamp(); 141 if (writeStamp == stamp && proc && proc != p) 142 reportSignalError(sig, proc, p, writeStamp == stamp); 143 proc = p; 144 writeStamp = stamp; 145} 146 147ScSignalBaseBinary::ScSignalBaseBinary(const char *_name) : 148 ScSignalBase(_name), _posStamp(~0ULL), _negStamp(~0ULL) 149{} 150 151const sc_core::sc_event & 152ScSignalBaseBinary::posedgeEvent() const 153{ 154 return _posedgeEvent; 155} 156 157const sc_core::sc_event & 158ScSignalBaseBinary::negedgeEvent() const 159{ 160 return _negedgeEvent; 161} 162 163bool 164ScSignalBaseBinary::posedge() const 165{ 166 return _posStamp == getChangeStamp(); 167} 168 169bool 170ScSignalBaseBinary::negedge() const 171{ 172 return _negStamp == getChangeStamp(); 173} 174 175void 176ScSignalBaseBinary::_signalReset(sc_gem5::Reset *r) 177{ 178 r->update(); 179} 180 181void 182ScSignalBaseBinary::_signalReset() 183{ 184 for (auto r: _resets) 185 _signalReset(r); 186} 187 188} // namespace sc_gem5 189