systemc: Report an error if an sc_event_finder is used on an unbound port.

Rather than assuming the port is bound, check and report an error.

Change-Id: I4af89d104bc6de9932ff044740446833732d01d9
Reviewed-on: https://gem5-review.googlesource.com/c/13300
Reviewed-by: Gabe Black <gabeblack@google.com>
Maintainer: Gabe Black <gabeblack@google.com>
diff --git a/src/systemc/ext/core/sc_event.hh b/src/systemc/ext/core/sc_event.hh
index f70951d..90c1911 100644
--- a/src/systemc/ext/core/sc_event.hh
+++ b/src/systemc/ext/core/sc_event.hh
@@ -32,8 +32,10 @@
 
 #include <cassert>
 #include <set>
+#include <sstream>
 #include <vector>
 
+#include "../utils/sc_report_handler.hh"
 #include "sc_port.hh"
 #include "sc_time.hh"
 
@@ -56,46 +58,6 @@
 class sc_object;
 class sc_port_base;
 
-class sc_event_finder
-{
-  protected:
-    virtual ~sc_event_finder() {}
-
-  public:
-    // Should be "implementation defined" but used in the tests.
-    virtual const sc_event &find_event(sc_interface *if_p=NULL) const = 0;
-    virtual const sc_port_base *port() const = 0;
-};
-
-template <class IF>
-class sc_event_finder_t : public sc_event_finder
-{
-  public:
-    sc_event_finder_t(const sc_port_base &p,
-                      const sc_event & (IF::*_method)() const) :
-        _method(_method)
-    {
-        _port = dynamic_cast<const sc_port_b<IF> *>(&p);
-        assert(_port);
-    }
-
-    virtual ~sc_event_finder_t() {}
-
-    const sc_port_base *port() const { return _port; }
-
-    const sc_event &
-    find_event(sc_interface *if_p=NULL) const override
-    {
-        const IF *iface = if_p ? dynamic_cast<const IF *>(if_p) :
-            dynamic_cast<const IF *>(_port->get_interface());
-        return (const_cast<IF *>(iface)->*_method)();
-    }
-
-  private:
-    const sc_port_b<IF> *_port;
-    const sc_event &(IF::*_method)() const;
-};
-
 class sc_event_and_list
 {
   public:
@@ -243,6 +205,54 @@
     ::sc_gem5::Event *_gem5_event;
 };
 
+class sc_event_finder
+{
+  protected:
+    virtual ~sc_event_finder() {}
+
+  public:
+    // Should be "implementation defined" but used in the tests.
+    virtual const sc_event &find_event(sc_interface *if_p=NULL) const = 0;
+    virtual const sc_port_base *port() const = 0;
+};
+
+template <class IF>
+class sc_event_finder_t : public sc_event_finder
+{
+  public:
+    sc_event_finder_t(const sc_port_base &p,
+                      const sc_event & (IF::*_method)() const) :
+        _method(_method)
+    {
+        _port = dynamic_cast<const sc_port_b<IF> *>(&p);
+        assert(_port);
+    }
+
+    virtual ~sc_event_finder_t() {}
+
+    const sc_port_base *port() const { return _port; }
+
+    const sc_event &
+    find_event(sc_interface *if_p=NULL) const override
+    {
+        static const sc_event none;
+        const IF *iface = if_p ? dynamic_cast<const IF *>(if_p) :
+            dynamic_cast<const IF *>(_port->get_interface());
+        if (!iface) {
+            std::ostringstream ss;
+            ss << "port is not bound: port '" << _port->name() << "' (" <<
+                _port->kind() << ")";
+            SC_REPORT_ERROR("(E118) find event failed", ss.str().c_str());
+            return none;
+        }
+        return (const_cast<IF *>(iface)->*_method)();
+    }
+
+  private:
+    const sc_port_b<IF> *_port;
+    const sc_event &(IF::*_method)() const;
+};
+
 const std::vector<sc_event *> &sc_get_top_level_events();
 sc_event *sc_find_event(const char *);