event.cc revision 11988
17860SN/A/*
27860SN/A * Copyright (c) 2017 ARM Limited
37860SN/A * All rights reserved
48835SAli.Saidi@ARM.com *
57935SN/A * The license below extends only to copyright in the software and shall
67935SN/A * not be construed as granting a license to any other intellectual
77935SN/A * property including but not limited to intellectual property relating
87860SN/A * to a hardware implementation of the functionality of the software
97860SN/A * licensed hereunder.  You may use the software subject to the license
107860SN/A * terms below provided that you ensure that this notice is replicated
117860SN/A * unmodified and in its entirety in all distributions of the software,
128835SAli.Saidi@ARM.com * modified or unmodified, in source code or in binary form.
139265SAli.Saidi@ARM.com *
148835SAli.Saidi@ARM.com * Copyright (c) 2006 The Regents of The University of Michigan
158835SAli.Saidi@ARM.com * Copyright (c) 2013 Advanced Micro Devices, Inc.
168835SAli.Saidi@ARM.com * Copyright (c) 2013 Mark D. Hill and David A. Wood
177860SN/A * All rights reserved.
188721SN/A *
198721SN/A * Redistribution and use in source and binary forms, with or without
208835SAli.Saidi@ARM.com * modification, are permitted provided that the following conditions are
218835SAli.Saidi@ARM.com * met: redistributions of source code must retain the above copyright
227935SN/A * notice, this list of conditions and the following disclaimer;
237935SN/A * redistributions in binary form must reproduce the above copyright
247935SN/A * notice, this list of conditions and the following disclaimer in the
257935SN/A * documentation and/or other materials provided with the distribution;
267935SN/A * neither the name of the copyright holders nor the names of its
277935SN/A * contributors may be used to endorse or promote products derived from
287935SN/A * this software without specific prior written permission.
298893Ssaidi@eecs.umich.edu *
307860SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
317860SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
327860SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
338835SAli.Saidi@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
347860SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
357860SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
367860SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
377860SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
387860SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
398835SAli.Saidi@ARM.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
407860SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
417860SN/A *
427860SN/A * Authors: Nathan Binkert
437860SN/A *          Andreas Sandberg
448835SAli.Saidi@ARM.com */
457860SN/A
467860SN/A#include "pybind11/pybind11.h"
477860SN/A#include "pybind11/stl.h"
487860SN/A
497860SN/A#include "sim/eventq.hh"
507860SN/A#include "sim/sim_events.hh"
518835SAli.Saidi@ARM.com#include "sim/sim_exit.hh"
527860SN/A#include "sim/simulate.hh"
537860SN/A
547860SN/Anamespace py = pybind11;
557860SN/A
567860SN/A/**
577860SN/A * PyBind wrapper for Events
587860SN/A *
597860SN/A * We need to wrap the Event class with some Python glue code to
607860SN/A * enable method overrides in Python and memory management. Unlike its
618893Ssaidi@eecs.umich.edu * C++ cousin, PyEvents need to override __call__ instead of
627860SN/A * Event::process().
637860SN/A *
649265SAli.Saidi@ARM.com * Memory management is mostly done using reference counting in
657860SN/A * Python. However, PyBind can't keep track of the reference the event
667860SN/A * queue holds to a scheduled event. We therefore need to inhibit
679265SAli.Saidi@ARM.com * deletion and hand over ownership to the event queue in case a
688150SN/A * scheduled event loses all of its Python references.
697860SN/A */
707860SN/Aclass PyEvent : public Event
717860SN/A{
728835SAli.Saidi@ARM.com  public:
737860SN/A    struct Deleter {
747860SN/A        void operator()(PyEvent *ev) {
759265SAli.Saidi@ARM.com            assert(!ev->isAutoDelete());
767860SN/A            if (ev->scheduled()) {
777860SN/A                // The event is scheduled, give ownership to the event
788835SAli.Saidi@ARM.com                // queue.
797860SN/A                ev->setFlags(Event::AutoDelete);
807860SN/A            } else {
817860SN/A                // The event isn't scheduled, hence Python owns it and
827860SN/A                // we need to free it here.
837860SN/A                delete ev;
848893Ssaidi@eecs.umich.edu            }
857860SN/A        }
867860SN/A    };
877860SN/A
888835SAli.Saidi@ARM.com    PyEvent(Event::Priority priority)
897860SN/A        : Event(priority)
908835SAli.Saidi@ARM.com    { }
918835SAli.Saidi@ARM.com
928835SAli.Saidi@ARM.com    void process() override {
938835SAli.Saidi@ARM.com        if (isAutoDelete()) {
949265SAli.Saidi@ARM.com            // Ownership of the event was handed over to the event queue
959265SAli.Saidi@ARM.com            // because the last revference in Python land was GCed. We
968835SAli.Saidi@ARM.com            // need to claim the object again since we're creating a new
978893Ssaidi@eecs.umich.edu            // Python reference.
987860SN/A            clearFlags(AutoDelete);
997860SN/A        }
1007860SN/A
1018893Ssaidi@eecs.umich.edu        // Call the Python implementation as __call__. This provides a
1027860SN/A        // slightly more Python-friendly interface.
1037860SN/A        PYBIND11_OVERLOAD_PURE_NAME(void, PyEvent, "__call__", process);
1049265SAli.Saidi@ARM.com    }
1057860SN/A};
1067860SN/A
1079265SAli.Saidi@ARM.comvoid
1088150SN/Apybind_init_event(py::module &m_native)
1097860SN/A{
1107860SN/A    py::module m = m_native.def_submodule("event");
1117860SN/A
1128835SAli.Saidi@ARM.com    m.def("simulate", &simulate,
1137860SN/A          py::arg("ticks") = MaxTick);
1147860SN/A    m.def("exitSimLoop", &exitSimLoop);
1159265SAli.Saidi@ARM.com    m.def("getEventQueue", []() { return curEventQueue(); },
1167860SN/A          py::return_value_policy::reference);
1177860SN/A    m.def("setEventQueue", [](EventQueue *q) { return curEventQueue(q); });
1188835SAli.Saidi@ARM.com    m.def("getEventQueue", &getEventQueue,
1197860SN/A          py::return_value_policy::reference);
1207860SN/A
1217860SN/A    py::class_<EventQueue>(m, "EventQueue")
1227860SN/A        .def("name",  [](EventQueue *eq) { return eq->name(); })
1237860SN/A        .def("dump", &EventQueue::dump)
1248893Ssaidi@eecs.umich.edu        .def("schedule", [](EventQueue *eq, PyEvent *e, Tick t) {
1257860SN/A                eq->schedule(e, t);
1268835SAli.Saidi@ARM.com            }, py::arg("event"), py::arg("when"))
1278835SAli.Saidi@ARM.com        .def("deschedule", [](EventQueue *eq, PyEvent *e) {
1288835SAli.Saidi@ARM.com                eq->deschedule(e);
1297860SN/A            }, py::arg("event"))
1307860SN/A        .def("reschedule", [](EventQueue *eq, PyEvent *e, Tick t, bool alw) {
1318835SAli.Saidi@ARM.com                eq->reschedule(e, t, alw);
1327860SN/A            }, py::arg("event"), py::arg("tick"), py::arg("always") = false)
1338835SAli.Saidi@ARM.com        ;
1348835SAli.Saidi@ARM.com
1358835SAli.Saidi@ARM.com    // TODO: Ownership of global exit events has always been a bit
1368835SAli.Saidi@ARM.com    // questionable. We currently assume they are owned by the C++
1379265SAli.Saidi@ARM.com    // word. This is what the old SWIG code did, but that will result
1389265SAli.Saidi@ARM.com    // in memory leaks.
1398835SAli.Saidi@ARM.com    py::class_<GlobalSimLoopExitEvent,
1408893Ssaidi@eecs.umich.edu               std::unique_ptr<GlobalSimLoopExitEvent, py::nodelete>>(
1417860SN/A               m, "GlobalSimLoopExitEvent")
1427860SN/A        .def("getCause", &GlobalSimLoopExitEvent::getCause)
1437860SN/A        .def("getCode", &GlobalSimLoopExitEvent::getCode)
1448893Ssaidi@eecs.umich.edu        ;
1457860SN/A
1467860SN/A    // TODO: We currently export a wrapper class and not the Event
1479265SAli.Saidi@ARM.com    // base class. This wil be problematic if we ever return an event
1487860SN/A    // from C++.
1497860SN/A    py::class_<PyEvent, std::unique_ptr<PyEvent, PyEvent::Deleter>>
1509265SAli.Saidi@ARM.com        c_event(m, "Event");
1518150SN/A    c_event
1527860SN/A        .def(py::init<Event::Priority>(),
1537860SN/A             py::arg("priority") = (int)Event::Default_Pri)
1547860SN/A        .def("name", &Event::name)
1558835SAli.Saidi@ARM.com        .def("dump", &Event::dump)
1567860SN/A        .def("scheduled", &Event::scheduled)
1577860SN/A        .def("squash", &Event::squash)
1589265SAli.Saidi@ARM.com        .def("squashed", &Event::squashed)
1597860SN/A        .def("isExitEvent", &Event::isExitEvent)
1607860SN/A        .def("isAutoDelete", &Event::isAutoDelete)
1618835SAli.Saidi@ARM.com        .def("when", &Event::when)
1627860SN/A        .def("priority", &Event::priority)
1637860SN/A        ;
1647860SN/A
1657860SN/A#define PRIO(n) c_event.attr(# n) = py::cast((int)Event::n)
1668893Ssaidi@eecs.umich.edu    PRIO(Minimum_Pri);
1678893Ssaidi@eecs.umich.edu    PRIO(Minimum_Pri);
1687860SN/A    PRIO(Debug_Enable_Pri);
1697860SN/A    PRIO(Debug_Break_Pri);
1709055Ssaidi@eecs.umich.edu    PRIO(CPU_Switch_Pri);
1717860SN/A    PRIO(Delayed_Writeback_Pri);
1727860SN/A    PRIO(Default_Pri);
1737860SN/A    PRIO(DVFS_Update_Pri);
1747860SN/A    PRIO(Serialize_Pri);
1759096Sandreas.hansson@arm.com    PRIO(CPU_Tick_Pri);
1768893Ssaidi@eecs.umich.edu    PRIO(Stat_Event_Pri);
1778893Ssaidi@eecs.umich.edu    PRIO(Progress_Event_Pri);
1787860SN/A    PRIO(Sim_Exit_Pri);
1797860SN/A    PRIO(Maximum_Pri);
1807860SN/A}
1817860SN/A