| /* | |
| * 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 "systemc/core/object.hh" | |
| #include <algorithm> | |
| #include <stack> | |
| #include "systemc/core/event.hh" | |
| #include "systemc/core/module.hh" | |
| #include "systemc/core/scheduler.hh" | |
| #include "systemc/ext/core/messages.hh" | |
| #include "systemc/ext/core/sc_module.hh" | |
| #include "systemc/ext/core/sc_simcontext.hh" | |
| namespace sc_gem5 | |
| { | |
| namespace | |
| { | |
| ObjectsIt | |
| findObjectIn(Objects &objects, const std::string &name) | |
| { | |
| ObjectsIt it; | |
| for (it = objects.begin(); it != objects.end(); it++) | |
| if (!strcmp((*it)->name(), name.c_str())) | |
| break; | |
| return it; | |
| } | |
| void | |
| addObject(Objects *objects, sc_core::sc_object *object) | |
| { | |
| objects->emplace(objects->end(), object); | |
| } | |
| void | |
| popObject(Objects *objects, const std::string &name) | |
| { | |
| ObjectsIt it = findObjectIn(*objects, name); | |
| assert(it != objects->end()); | |
| std::swap(objects->back(), *it); | |
| objects->pop_back(); | |
| } | |
| bool | |
| nameIsUnique(Objects *objects, Events *events, const std::string &name) | |
| { | |
| for (auto obj: *objects) | |
| if (!strcmp(obj->basename(), name.c_str())) | |
| return false; | |
| for (auto event: *events) | |
| if (!strcmp(event->basename(), name.c_str())) | |
| return false; | |
| return true; | |
| } | |
| } // anonymous namespace | |
| Object::Object(sc_core::sc_object *_sc_obj) : Object(_sc_obj, nullptr) {} | |
| Object::Object(sc_core::sc_object *_sc_obj, const char *obj_name) : | |
| _sc_obj(_sc_obj), _basename(obj_name ? obj_name : ""), parent(nullptr) | |
| { | |
| if (_basename == "") | |
| _basename = ::sc_core::sc_gen_unique_name("object"); | |
| parent = pickParentObj(); | |
| Module *n = newModule(); | |
| if (n) { | |
| // We are a module in the process of being constructed. | |
| n->finish(this); | |
| } | |
| std::string original_name = _basename; | |
| _basename = sc_gem5::pickUniqueName(parent, original_name); | |
| if (parent) | |
| addObject(&parent->_gem5_object->children, _sc_obj); | |
| else | |
| addObject(&topLevelObjects, _sc_obj); | |
| addObject(&allObjects, _sc_obj); | |
| sc_core::sc_object *sc_p = parent; | |
| std::string path = ""; | |
| while (sc_p) { | |
| path = std::string(sc_p->basename()) + std::string(".") + path; | |
| sc_p = sc_p->get_parent_object(); | |
| } | |
| if (_basename != original_name) { | |
| std::string message = path + original_name + | |
| ". Latter declaration will be renamed to " + | |
| path + _basename; | |
| SC_REPORT_WARNING(sc_core::SC_ID_INSTANCE_EXISTS_, message.c_str()); | |
| } | |
| _name = path + _basename; | |
| } | |
| Object::Object(sc_core::sc_object *_sc_obj, const Object &arg) : | |
| Object(_sc_obj, arg._basename.c_str()) | |
| {} | |
| Object & | |
| Object::operator = (const Object &) | |
| { | |
| return *this; | |
| } | |
| Object::~Object() | |
| { | |
| // Promote all children to be top level objects. | |
| for (auto child: children) { | |
| addObject(&topLevelObjects, child); | |
| child->_gem5_object->parent = nullptr; | |
| } | |
| children.clear(); | |
| for (auto event: events) | |
| Event::getFromScEvent(event)->clearParent(); | |
| if (parent) | |
| popObject(&parent->_gem5_object->children, _name); | |
| else | |
| popObject(&topLevelObjects, _name); | |
| popObject(&allObjects, _name); | |
| } | |
| const char * | |
| Object::name() const | |
| { | |
| return _name.c_str(); | |
| } | |
| const char * | |
| Object::basename() const | |
| { | |
| return _basename.c_str(); | |
| } | |
| void | |
| Object::print(std::ostream &out) const | |
| { | |
| out << name(); | |
| } | |
| void | |
| Object::dump(std::ostream &out) const | |
| { | |
| out << "name = " << name() << "\n"; | |
| out << "kind = " << _sc_obj->kind() << "\n"; | |
| } | |
| const std::vector<sc_core::sc_object *> & | |
| Object::get_child_objects() const | |
| { | |
| return children; | |
| } | |
| const std::vector<sc_core::sc_event *> & | |
| Object::get_child_events() const | |
| { | |
| return events; | |
| } | |
| sc_core::sc_object *Object::get_parent_object() const | |
| { | |
| return parent; | |
| } | |
| bool | |
| Object::add_attribute(sc_core::sc_attr_base &attr) | |
| { | |
| return cltn.push_back(&attr); | |
| } | |
| sc_core::sc_attr_base * | |
| Object::get_attribute(const std::string &attr) | |
| { | |
| return cltn[attr]; | |
| } | |
| sc_core::sc_attr_base * | |
| Object::remove_attribute(const std::string &attr) | |
| { | |
| return cltn.remove(attr); | |
| } | |
| void | |
| Object::remove_all_attributes() | |
| { | |
| cltn.remove_all(); | |
| } | |
| int | |
| Object::num_attributes() const | |
| { | |
| return cltn.size(); | |
| } | |
| sc_core::sc_attr_cltn & | |
| Object::attr_cltn() | |
| { | |
| return cltn; | |
| } | |
| const sc_core::sc_attr_cltn & | |
| Object::attr_cltn() const | |
| { | |
| return cltn; | |
| } | |
| sc_core::sc_simcontext * | |
| Object::simcontext() const | |
| { | |
| return sc_core::sc_get_curr_simcontext(); | |
| } | |
| EventsIt | |
| Object::addChildEvent(sc_core::sc_event *e) | |
| { | |
| return events.emplace(events.end(), e); | |
| } | |
| void | |
| Object::delChildEvent(sc_core::sc_event *e) | |
| { | |
| EventsIt it = std::find(events.begin(), events.end(), e); | |
| assert(it != events.end()); | |
| std::swap(*it, events.back()); | |
| events.pop_back(); | |
| } | |
| std::string | |
| Object::pickUniqueName(std::string base) | |
| { | |
| std::string seed = base; | |
| while (!nameIsUnique(&children, &events, base)) | |
| base = ::sc_core::sc_gen_unique_name(seed.c_str()); | |
| return base; | |
| } | |
| std::string | |
| pickUniqueName(::sc_core::sc_object *parent, std::string base) | |
| { | |
| if (parent) | |
| return Object::getFromScObject(parent)->pickUniqueName(base); | |
| std::string seed = base; | |
| while (!nameIsUnique(&topLevelObjects, &topLevelEvents, base)) | |
| base = ::sc_core::sc_gen_unique_name(seed.c_str()); | |
| return base; | |
| } | |
| Objects topLevelObjects; | |
| Objects allObjects; | |
| const std::vector<sc_core::sc_object *> & | |
| getTopLevelScObjects() | |
| { | |
| return topLevelObjects; | |
| } | |
| sc_core::sc_object * | |
| findObject(const char *name, const Objects &objects) | |
| { | |
| ObjectsIt it = findObjectIn(allObjects, name); | |
| return it == allObjects.end() ? nullptr : *it; | |
| } | |
| namespace | |
| { | |
| std::stack<sc_core::sc_object *> objParentStack; | |
| } // anonymous namespace | |
| sc_core::sc_object * | |
| pickParentObj() | |
| { | |
| if (!objParentStack.empty()) | |
| return objParentStack.top(); | |
| Process *p = scheduler.current(); | |
| if (p) | |
| return p; | |
| return nullptr; | |
| } | |
| void pushParentObj(sc_core::sc_object *obj) { objParentStack.push(obj); } | |
| void popParentObj() { objParentStack.pop(); } | |
| } // namespace sc_gem5 |