| /* | |
| * Copyright 2018 Google, Inc. | |
| * | |
| * Redistribution and use in source and binary forms, with or without | |
| * modification, are permitted provided that the following conditions are | |
| * met: redistributions of source code must retain the above copyright | |
| * notice, this list of conditions and the following disclaimer; | |
| * redistributions in binary form must reproduce the above copyright | |
| * notice, this list of conditions and the following disclaimer in the | |
| * documentation and/or other materials provided with the distribution; | |
| * neither the name of the copyright holders nor the names of its | |
| * contributors may be used to endorse or promote products derived from | |
| * this software without specific prior written permission. | |
| * | |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
| * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| */ | |
| #include <sstream> | |
| #include "systemc/core/scheduler.hh" | |
| #include "systemc/ext/channel/messages.hh" | |
| #include "systemc/ext/channel/sc_signal.hh" | |
| #include "systemc/ext/core/sc_main.hh" | |
| namespace sc_gem5 | |
| { | |
| ScSignalBase::ScSignalBase(const char *name) : | |
| sc_core::sc_prim_channel(name), _changeStamp(~0ULL), | |
| _gem5WriterPort(nullptr) | |
| {} | |
| ScSignalBase::~ScSignalBase() {} | |
| const sc_core::sc_event & | |
| ScSignalBase::defaultEvent() const | |
| { | |
| return valueChangedEvent(); | |
| } | |
| const sc_core::sc_event & | |
| ScSignalBase::valueChangedEvent() const | |
| { | |
| return _valueChangedEvent; | |
| } | |
| bool | |
| ScSignalBase::event() const | |
| { | |
| return _changeStamp == getChangeStamp(); | |
| } | |
| void | |
| ScSignalBase::_signalChange() | |
| { | |
| _changeStamp = getChangeStamp(); | |
| _valueChangedEvent.notify(sc_core::SC_ZERO_TIME); | |
| } | |
| void | |
| ScSignalBaseBinary::_signalPosedge() | |
| { | |
| _posStamp = getChangeStamp(); | |
| _posedgeEvent.notify(sc_core::SC_ZERO_TIME); | |
| } | |
| void | |
| ScSignalBaseBinary::_signalNegedge() | |
| { | |
| _negStamp = getChangeStamp(); | |
| _negedgeEvent.notify(sc_core::SC_ZERO_TIME); | |
| } | |
| namespace | |
| { | |
| void | |
| reportSignalError(ScSignalBase *sig, sc_core::sc_object *first, | |
| sc_core::sc_object *second, bool delta_conflict=false) | |
| { | |
| std::ostringstream ss; | |
| ss << "\n signal " << "`" << sig->name() << "' (" << sig->kind() << ")"; | |
| ss << "\n first driver `" << first->name() << "' (" << | |
| first->kind() << ")"; | |
| ss << "\n second driver `" << second->name() << "' (" << | |
| second->kind() << ")"; | |
| if (delta_conflict) { | |
| ss << "\n conflicting write in delta cycle " << | |
| sc_core::sc_delta_count(); | |
| } | |
| SC_REPORT_ERROR(sc_core::SC_ID_MORE_THAN_ONE_SIGNAL_DRIVER_, | |
| ss.str().c_str()); | |
| } | |
| } // anonymous namespace | |
| WriteChecker<sc_core::SC_ONE_WRITER>::WriteChecker(ScSignalBase *_sig) : | |
| sig(_sig), firstPort(nullptr), proc(nullptr), writeStamp(~0ULL) | |
| {} | |
| void | |
| WriteChecker<sc_core::SC_ONE_WRITER>::checkPort(sc_core::sc_port_base &port, | |
| std::string iface_type_name, std::string out_name) | |
| { | |
| if (iface_type_name == out_name) { | |
| if (firstPort) | |
| reportSignalError(sig, firstPort, &port); | |
| firstPort = &port; | |
| } | |
| } | |
| void | |
| WriteChecker<sc_core::SC_ONE_WRITER>::checkWriter() | |
| { | |
| Process *p = scheduler.current(); | |
| if (!p) | |
| return; | |
| uint64_t stamp = getChangeStamp(); | |
| if (proc && proc != p) | |
| reportSignalError(sig, proc, p); | |
| proc = p; | |
| writeStamp = stamp; | |
| } | |
| WriteChecker<sc_core::SC_MANY_WRITERS>::WriteChecker(ScSignalBase *_sig) : | |
| sig(_sig), proc(nullptr), writeStamp(~0ULL) | |
| {} | |
| void | |
| WriteChecker<sc_core::SC_MANY_WRITERS>::checkPort(sc_core::sc_port_base &port, | |
| std::string iface_type_name, std::string out_name) | |
| { | |
| return; | |
| } | |
| void | |
| WriteChecker<sc_core::SC_MANY_WRITERS>::checkWriter() | |
| { | |
| Process *p = scheduler.current(); | |
| if (!p) | |
| return; | |
| uint64_t stamp = getChangeStamp(); | |
| if (writeStamp == stamp && proc && proc != p) | |
| reportSignalError(sig, proc, p, writeStamp == stamp); | |
| proc = p; | |
| writeStamp = stamp; | |
| } | |
| ScSignalBaseBinary::ScSignalBaseBinary(const char *_name) : | |
| ScSignalBase(_name), _posStamp(~0ULL), _negStamp(~0ULL) | |
| {} | |
| const sc_core::sc_event & | |
| ScSignalBaseBinary::posedgeEvent() const | |
| { | |
| return _posedgeEvent; | |
| } | |
| const sc_core::sc_event & | |
| ScSignalBaseBinary::negedgeEvent() const | |
| { | |
| return _negedgeEvent; | |
| } | |
| bool | |
| ScSignalBaseBinary::posedge() const | |
| { | |
| return _posStamp == getChangeStamp(); | |
| } | |
| bool | |
| ScSignalBaseBinary::negedge() const | |
| { | |
| return _negStamp == getChangeStamp(); | |
| } | |
| void | |
| ScSignalBaseBinary::_signalReset(sc_gem5::Reset *r) | |
| { | |
| r->update(); | |
| } | |
| void | |
| ScSignalBaseBinary::_signalReset() | |
| { | |
| for (auto r: _resets) | |
| _signalReset(r); | |
| } | |
| } // namespace sc_gem5 |