114126Schunchenhsu@google.com/*
214126Schunchenhsu@google.com * Copyright 2019 Google LLC.
314126Schunchenhsu@google.com *
414126Schunchenhsu@google.com * Redistribution and use in source and binary forms, with or without
514126Schunchenhsu@google.com * modification, are permitted provided that the following conditions are
614126Schunchenhsu@google.com * met: redistributions of source code must retain the above copyright
714126Schunchenhsu@google.com * notice, this list of conditions and the following disclaimer;
814126Schunchenhsu@google.com * redistributions in binary form must reproduce the above copyright
914126Schunchenhsu@google.com * notice, this list of conditions and the following disclaimer in the
1014126Schunchenhsu@google.com * documentation and/or other materials provided with the distribution;
1114126Schunchenhsu@google.com * neither the name of the copyright holders nor the names of its
1214126Schunchenhsu@google.com * contributors may be used to endorse or promote products derived from
1314126Schunchenhsu@google.com * this software without specific prior written permission.
1414126Schunchenhsu@google.com *
1514126Schunchenhsu@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1614126Schunchenhsu@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1714126Schunchenhsu@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1814126Schunchenhsu@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
1914126Schunchenhsu@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2014126Schunchenhsu@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2114126Schunchenhsu@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2214126Schunchenhsu@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2314126Schunchenhsu@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2414126Schunchenhsu@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2514126Schunchenhsu@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2614126Schunchenhsu@google.com *
2714126Schunchenhsu@google.com * Authors: Chun-Chen TK Hsu
2814126Schunchenhsu@google.com */
2914126Schunchenhsu@google.com
3014126Schunchenhsu@google.com#ifndef __SYSTEMC_SC_PORT_WRAPPER_HH__
3114126Schunchenhsu@google.com#define __SYSTEMC_SC_PORT_WRAPPER_HH__
3214126Schunchenhsu@google.com
3314126Schunchenhsu@google.com#include <string>
3414126Schunchenhsu@google.com#include <type_traits>
3514126Schunchenhsu@google.com
3614126Schunchenhsu@google.com#include "base/logging.hh"
3714126Schunchenhsu@google.com#include "sim/port.hh"
3814126Schunchenhsu@google.com#include "systemc/ext/core/sc_export.hh"
3914126Schunchenhsu@google.com#include "systemc/ext/core/sc_interface.hh"
4014126Schunchenhsu@google.com#include "systemc/ext/core/sc_port.hh"
4114126Schunchenhsu@google.com
4214126Schunchenhsu@google.comnamespace sc_gem5
4314126Schunchenhsu@google.com{
4414126Schunchenhsu@google.com
4514126Schunchenhsu@google.com// Forward declaration
4614126Schunchenhsu@google.comtemplate <typename IF>
4714126Schunchenhsu@google.comclass ScPortWrapper;
4814126Schunchenhsu@google.comtemplate <typename IF>
4914126Schunchenhsu@google.comclass ScInterfaceWrapper;
5014126Schunchenhsu@google.comtemplate <typename IF>
5114126Schunchenhsu@google.comclass ScExportWrapper;
5214126Schunchenhsu@google.com
5314126Schunchenhsu@google.comtemplate <typename IF>
5414126Schunchenhsu@google.comclass ScPortWrapper : public ::Port
5514126Schunchenhsu@google.com{
5614126Schunchenhsu@google.com  public:
5714126Schunchenhsu@google.com    using ScPort = sc_core::sc_port_b<IF>;
5814126Schunchenhsu@google.com
5914126Schunchenhsu@google.com    ScPortWrapper(ScPort& p, const std::string& name, PortID id)
6014126Schunchenhsu@google.com        : Port(name, id), port_(p)
6114126Schunchenhsu@google.com    {}
6214126Schunchenhsu@google.com
6314126Schunchenhsu@google.com    ScPort&
6414126Schunchenhsu@google.com    port()
6514126Schunchenhsu@google.com    {
6614126Schunchenhsu@google.com        return port_;
6714126Schunchenhsu@google.com    }
6814126Schunchenhsu@google.com
6914126Schunchenhsu@google.com    void
7014126Schunchenhsu@google.com    unbind() override
7114126Schunchenhsu@google.com    {
7214126Schunchenhsu@google.com        panic("sc_port can't be unbound.");
7314126Schunchenhsu@google.com    }
7414126Schunchenhsu@google.com
7514126Schunchenhsu@google.com    void
7614126Schunchenhsu@google.com    bind(::Port& peer) override
7714126Schunchenhsu@google.com    {
7814126Schunchenhsu@google.com        // Try ScPortWrapper or ScInterfaceWrapper
7914126Schunchenhsu@google.com        if (auto* beer = dynamic_cast<ScPortWrapper<IF>*>(&peer)) {
8014126Schunchenhsu@google.com            port_.bind(beer->port());
8114126Schunchenhsu@google.com        } else if (auto* iface =
8214126Schunchenhsu@google.com                       dynamic_cast<ScInterfaceWrapper<IF>*>(&peer)) {
8314126Schunchenhsu@google.com            port_.bind(iface->interface());
8414126Schunchenhsu@google.com        } else {
8514126Schunchenhsu@google.com            fatal("Attempt to bind sc_port %s to incompatible port %s.",
8614126Schunchenhsu@google.com                  name(), peer.name());
8714126Schunchenhsu@google.com        }
8814189Sgabeblack@google.com        Port::bind(peer);
8914126Schunchenhsu@google.com    }
9014126Schunchenhsu@google.com
9114126Schunchenhsu@google.com  private:
9214126Schunchenhsu@google.com    ScPort& port_;
9314126Schunchenhsu@google.com};
9414126Schunchenhsu@google.com
9514126Schunchenhsu@google.comtemplate <typename IF>
9614126Schunchenhsu@google.comclass ScInterfaceWrapper : public ::Port
9714126Schunchenhsu@google.com{
9814126Schunchenhsu@google.com  public:
9914126Schunchenhsu@google.com    ScInterfaceWrapper(IF& i, const std::string name, PortID id)
10014126Schunchenhsu@google.com        : Port(name, id), iface_(i)
10114126Schunchenhsu@google.com    {}
10214126Schunchenhsu@google.com
10314126Schunchenhsu@google.com    IF&
10414126Schunchenhsu@google.com    interface()
10514126Schunchenhsu@google.com    {
10614126Schunchenhsu@google.com        return iface_;
10714126Schunchenhsu@google.com    }
10814126Schunchenhsu@google.com
10914126Schunchenhsu@google.com    void
11014126Schunchenhsu@google.com    unbind() override
11114126Schunchenhsu@google.com    {
11214126Schunchenhsu@google.com        panic("sc_interface can't be unbound.");
11314126Schunchenhsu@google.com    }
11414126Schunchenhsu@google.com
11514126Schunchenhsu@google.com    void
11614126Schunchenhsu@google.com    bind(::Port& peer) override
11714126Schunchenhsu@google.com    {
11814126Schunchenhsu@google.com        // fatal error if peer is neither ScPortWrapper nor ScExportWrapper
11914126Schunchenhsu@google.com        fatal_if(!dynamic_cast<ScPortWrapper<IF>*>(&peer) &&
12014126Schunchenhsu@google.com                     !dynamic_cast<ScExportWrapper<IF>*>(&peer),
12114126Schunchenhsu@google.com                 "Attempt to bind sc_interface %s to incompatible port %s.",
12214126Schunchenhsu@google.com                 name(), peer.name());
12314126Schunchenhsu@google.com
12414126Schunchenhsu@google.com        // Don't bind to peer otherwise we may have error messages saying that
12514126Schunchenhsu@google.com        // this interface has already be bound since the peer may already did
12614126Schunchenhsu@google.com        // that. Just let sc_port or sc_export do the binding
12714189Sgabeblack@google.com        Port::bind(peer);
12814126Schunchenhsu@google.com    }
12914126Schunchenhsu@google.com
13014126Schunchenhsu@google.com  private:
13114126Schunchenhsu@google.com    IF& iface_;
13214126Schunchenhsu@google.com};
13314126Schunchenhsu@google.com
13414126Schunchenhsu@google.comtemplate <typename IF>
13514126Schunchenhsu@google.comclass ScExportWrapper : public ::Port
13614126Schunchenhsu@google.com{
13714126Schunchenhsu@google.com  public:
13814126Schunchenhsu@google.com    using ScExport = sc_core::sc_export<IF>;
13914126Schunchenhsu@google.com
14014126Schunchenhsu@google.com    ScExportWrapper(ScExport& p, const std::string& name, PortID id)
14114126Schunchenhsu@google.com        : Port(name, id), port_(p)
14214126Schunchenhsu@google.com    {}
14314126Schunchenhsu@google.com
14414126Schunchenhsu@google.com    ScExport&
14514126Schunchenhsu@google.com    port()
14614126Schunchenhsu@google.com    {
14714126Schunchenhsu@google.com        return port_;
14814126Schunchenhsu@google.com    }
14914126Schunchenhsu@google.com
15014126Schunchenhsu@google.com    void
15114126Schunchenhsu@google.com    unbind() override
15214126Schunchenhsu@google.com    {
15314126Schunchenhsu@google.com        panic("sc_export cannot be unbound.");
15414126Schunchenhsu@google.com    }
15514126Schunchenhsu@google.com
15614126Schunchenhsu@google.com    void
15714126Schunchenhsu@google.com    bind(::Port& peer) override
15814126Schunchenhsu@google.com    {
15914126Schunchenhsu@google.com        auto* iface = dynamic_cast<ScInterfaceWrapper<IF>*>(&peer);
16014126Schunchenhsu@google.com        fatal_if(!iface,
16114126Schunchenhsu@google.com                 "Attempt to bind sc_export %s to incompatible port %s.",
16214126Schunchenhsu@google.com                 name(), peer.name());
16314126Schunchenhsu@google.com
16414126Schunchenhsu@google.com        port_.bind(iface->interface());
16514189Sgabeblack@google.com        Port::bind(peer);
16614126Schunchenhsu@google.com    }
16714126Schunchenhsu@google.com
16814126Schunchenhsu@google.com  private:
16914126Schunchenhsu@google.com    ScExport& port_;
17014126Schunchenhsu@google.com};
17114126Schunchenhsu@google.com
17214126Schunchenhsu@google.com}  // namespace sc_gem5
17314126Schunchenhsu@google.com
17414126Schunchenhsu@google.com#endif  // __SYSTEMC_SC_PORT_WRAPPER_HH__
175