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