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>
313 lines
7.5 KiB
C++
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
|