Files
gem5/src/systemc/core/sc_process_handle.cc
Gabe Black e58072108f systemc: Fix a "problem" with kill/reset exceptions.
Despite what it says in the spec, the proc_ctrl compliance test throws
a copy of the reset exception it catches, not the original. Because of
that, the code in the kernel which catches the exception gets the base
class, not the derived class with overridden virtual methods, etc.
This happens to work for the Accellera implementation because they
manipulate members of the base class itself which are preserved despite
this bug. To make the test work, we imitate their implementation, even
though it exposes more implementation details through the header files.

Change-Id: I7ed9818c0552869ec790cb7f7bfbe365ade5e49c
Reviewed-on: https://gem5-review.googlesource.com/12045
Reviewed-by: Gabe Black <gabeblack@google.com>
Maintainer: Gabe Black <gabeblack@google.com>
2018-09-11 21:46:22 +00:00

313 lines
7.5 KiB
C++

/*
* 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.
*
* Authors: Gabe Black
*/
#include "base/logging.hh"
#include "systemc/core/process.hh"
#include "systemc/core/scheduler.hh"
#include "systemc/ext/core/sc_main.hh"
#include "systemc/ext/core/sc_process_handle.hh"
namespace sc_core
{
const char *
sc_unwind_exception::what() const throw()
{
return _isReset ? "RESET" : "KILL";
}
bool
sc_unwind_exception::is_reset() const
{
return _isReset;
}
sc_unwind_exception::sc_unwind_exception() : _isReset(false) {}
sc_unwind_exception::sc_unwind_exception(const sc_unwind_exception &e) :
_isReset(e._isReset)
{}
sc_unwind_exception::~sc_unwind_exception() throw() {}
const char *
sc_process_b::name()
{
warn("%s not implemented.\n", __PRETTY_FUNCTION__);
return "";
}
const char *
sc_process_b::kind()
{
warn("%s not implemented.\n", __PRETTY_FUNCTION__);
return "";
}
sc_process_b *
sc_get_curr_process_handle()
{
warn("%s not implemented.\n", __PRETTY_FUNCTION__);
return nullptr;
}
sc_process_handle::sc_process_handle() : _gem5_process(nullptr) {}
sc_process_handle::sc_process_handle(const sc_process_handle &handle) :
_gem5_process(handle._gem5_process)
{
if (_gem5_process)
_gem5_process->incref();
}
sc_process_handle::sc_process_handle(sc_object *obj) :
_gem5_process(dynamic_cast<::sc_gem5::Process *>(obj))
{
if (_gem5_process)
_gem5_process->incref();
}
sc_process_handle::~sc_process_handle()
{
if (_gem5_process)
_gem5_process->decref();
}
bool
sc_process_handle::valid() const
{
return _gem5_process != nullptr;
}
sc_process_handle &
sc_process_handle::operator = (const sc_process_handle &handle)
{
if (_gem5_process)
_gem5_process->decref();
_gem5_process = handle._gem5_process;
if (_gem5_process)
_gem5_process->incref();
return *this;
}
bool
sc_process_handle::operator == (const sc_process_handle &handle) const
{
return _gem5_process && handle._gem5_process &&
(_gem5_process == handle._gem5_process);
}
bool
sc_process_handle::operator != (const sc_process_handle &handle) const
{
return !(handle == *this);
}
bool
sc_process_handle::operator < (const sc_process_handle &other) const
{
return _gem5_process < other._gem5_process;
}
void
sc_process_handle::swap(sc_process_handle &handle)
{
::sc_gem5::Process *temp = handle._gem5_process;
handle._gem5_process = _gem5_process;
_gem5_process = temp;
}
const char *
sc_process_handle::name() const
{
return _gem5_process ? _gem5_process->name() : "";
}
sc_curr_proc_kind
sc_process_handle::proc_kind() const
{
return _gem5_process ? _gem5_process->procKind() : SC_NO_PROC_;
}
const std::vector<sc_object *> &
sc_process_handle::get_child_objects() const
{
static const std::vector<sc_object *> empty;
return _gem5_process ? _gem5_process->get_child_objects() : empty;
}
const std::vector<sc_event *> &
sc_process_handle::get_child_events() const
{
static const std::vector<sc_event *> empty;
return _gem5_process ? _gem5_process->get_child_events() : empty;
}
sc_object *
sc_process_handle::get_parent_object() const
{
return _gem5_process ? _gem5_process->get_parent_object() : nullptr;
}
sc_object *
sc_process_handle::get_process_object() const
{
return _gem5_process;
}
bool
sc_process_handle::dynamic() const
{
return _gem5_process ? _gem5_process->dynamic() : false;
}
bool
sc_process_handle::terminated() const
{
return _gem5_process ? _gem5_process->terminated() : false;
}
const sc_event &
sc_process_handle::terminated_event() const
{
static sc_event non_event;
return _gem5_process ? _gem5_process->terminatedEvent() : non_event;
}
void
sc_process_handle::suspend(sc_descendent_inclusion_info include_descendants)
{
if (!_gem5_process)
return;
_gem5_process->suspend(include_descendants == SC_INCLUDE_DESCENDANTS);
}
void
sc_process_handle::resume(sc_descendent_inclusion_info include_descendants)
{
if (!_gem5_process)
return;
_gem5_process->resume(include_descendants == SC_INCLUDE_DESCENDANTS);
}
void
sc_process_handle::disable(sc_descendent_inclusion_info include_descendants)
{
if (!_gem5_process)
return;
_gem5_process->disable(include_descendants == SC_INCLUDE_DESCENDANTS);
}
void
sc_process_handle::enable(sc_descendent_inclusion_info include_descendants)
{
if (!_gem5_process)
return;
_gem5_process->enable(include_descendants == SC_INCLUDE_DESCENDANTS);
}
void
sc_process_handle::kill(sc_descendent_inclusion_info include_descendants)
{
if (!_gem5_process)
return;
_gem5_process->kill(include_descendants == SC_INCLUDE_DESCENDANTS);
}
void
sc_process_handle::reset(sc_descendent_inclusion_info include_descendants)
{
if (!_gem5_process)
return;
_gem5_process->reset(include_descendants == SC_INCLUDE_DESCENDANTS);
}
bool
sc_process_handle::is_unwinding()
{
if (!_gem5_process) {
//TODO This should generate a systemc style warning if the handle is
//invalid.
return false;
} else {
return _gem5_process->isUnwinding();
}
}
const sc_event &
sc_process_handle::reset_event() const
{
static sc_event non_event;
return _gem5_process ? _gem5_process->resetEvent() : non_event;
}
void
sc_process_handle::sync_reset_on(
sc_descendent_inclusion_info include_descendants)
{
if (!_gem5_process)
return;
_gem5_process->syncResetOn(include_descendants == SC_INCLUDE_DESCENDANTS);
}
void
sc_process_handle::sync_reset_off(
sc_descendent_inclusion_info include_descendants)
{
if (!_gem5_process)
return;
_gem5_process->syncResetOff(include_descendants == SC_INCLUDE_DESCENDANTS);
}
sc_process_handle
sc_get_current_process_handle()
{
if (sc_is_running())
return sc_process_handle(::sc_gem5::scheduler.current());
else
return sc_process_handle(::sc_gem5::Process::newest());
}
bool
sc_is_unwinding()
{
return sc_get_current_process_handle().is_unwinding();
}
bool sc_allow_process_control_corners;
} // namespace sc_core