RubyPort.hh revision 8874
12SN/A/*
21762SN/A * Copyright (c) 2009 Advanced Micro Devices, Inc.
32SN/A * Copyright (c) 2011 Mark D. Hill and David A. Wood
42SN/A * All rights reserved.
52SN/A *
62SN/A * Redistribution and use in source and binary forms, with or without
72SN/A * modification, are permitted provided that the following conditions are
82SN/A * met: redistributions of source code must retain the above copyright
92SN/A * notice, this list of conditions and the following disclaimer;
102SN/A * redistributions in binary form must reproduce the above copyright
112SN/A * notice, this list of conditions and the following disclaimer in the
122SN/A * documentation and/or other materials provided with the distribution;
132SN/A * neither the name of the copyright holders nor the names of its
142SN/A * contributors may be used to endorse or promote products derived from
152SN/A * this software without specific prior written permission.
162SN/A *
172SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
182SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
192SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
202SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
212SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
222SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
232SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
242SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
252SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
262SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
272665SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
282665SN/A */
292665SN/A
302SN/A#ifndef __MEM_RUBY_SYSTEM_RUBYPORT_HH__
312SN/A#define __MEM_RUBY_SYSTEM_RUBYPORT_HH__
322SN/A
332SN/A#include <cassert>
341298SN/A#include <string>
351298SN/A
361259SN/A#include "mem/protocol/RequestStatus.hh"
372SN/A#include "mem/ruby/system/System.hh"
382SN/A#include "mem/mem_object.hh"
39146SN/A#include "mem/physical.hh"
40146SN/A#include "mem/tport.hh"
417632SBrad.Beckmann@amd.com#include "params/RubyPort.hh"
428232Snate@binkert.org
433348SN/Aclass MessageBuffer;
448229Snate@binkert.orgclass AbstractController;
453348SN/A
463348SN/Aclass RubyPort : public MemObject
4756SN/A{
48695SN/A  public:
492SN/A    class M5Port : public SimpleTimingPort
502SN/A    {
512SN/A      private:
521298SN/A        RubyPort *ruby_port;
531298SN/A        RubySystem* ruby_system;
543187SN/A        bool _onRetryList;
553349SN/A        bool access_phys_mem;
563187SN/A
574898SN/A      public:
584898SN/A        M5Port(const std::string &_name, RubyPort *_port,
594898SN/A               RubySystem*_system, bool _access_phys_mem);
604898SN/A        bool sendNextCycle(PacketPtr pkt);
614898SN/A        void hitCallback(PacketPtr pkt);
624898SN/A        void evictionCallback(const Address& address);
634898SN/A        unsigned deviceBlockSize() const;
643187SN/A
653187SN/A        bool onRetryList()
663187SN/A        { return _onRetryList; }
673187SN/A
683349SN/A        void onRetryList(bool newVal)
693187SN/A        { _onRetryList = newVal; }
704895SN/A
714895SN/A      protected:
724895SN/A        virtual bool recvTiming(PacketPtr pkt);
737823Ssteve.reinhardt@amd.com        virtual Tick recvAtomic(PacketPtr pkt);
743187SN/A        virtual void recvFunctional(PacketPtr pkt);
753187SN/A
763187SN/A      private:
773349SN/A        bool isPhysMemAddress(Addr addr);
783187SN/A        bool doFunctionalRead(PacketPtr pkt);
793204SN/A        bool doFunctionalWrite(PacketPtr pkt);
807823Ssteve.reinhardt@amd.com    };
813340SN/A
823262SN/A    friend class M5Port;
833204SN/A
843187SN/A    class PioPort : public SimpleTimingPort
853187SN/A    {
863187SN/A      private:
878711Sandreas.hansson@arm.com        RubyPort *ruby_port;
883187SN/A
893187SN/A      public:
903187SN/A        PioPort(const std::string &_name, RubyPort *_port);
913187SN/A        bool sendNextCycle(PacketPtr pkt);
923187SN/A
933187SN/A      protected:
943187SN/A        virtual bool recvTiming(PacketPtr pkt);
953187SN/A        virtual Tick recvAtomic(PacketPtr pkt);
963187SN/A    };
973262SN/A
983349SN/A    friend class PioPort;
993262SN/A
1003262SN/A    struct SenderState : public Packet::SenderState
1013262SN/A    {
1023262SN/A        M5Port* port;
1033262SN/A        Packet::SenderState *saved;
1047544SN/A
1057544SN/A        SenderState(M5Port* _port, Packet::SenderState *sender_state = NULL)
1067544SN/A            : port(_port), saved(sender_state)
1077544SN/A        {}
1087544SN/A    };
1097544SN/A
1107544SN/A    typedef RubyPortParams Params;
1117544SN/A    RubyPort(const Params *p);
1123262SN/A    virtual ~RubyPort() {}
1133262SN/A
1147544SN/A    void init();
1157544SN/A
1167544SN/A    Port *getPort(const std::string &if_name, int idx);
1177544SN/A
1183262SN/A    virtual RequestStatus makeRequest(PacketPtr pkt) = 0;
1193262SN/A    virtual int outstandingCount() const = 0;
1203262SN/A    virtual bool isDeadlockEventScheduled() const = 0;
1213262SN/A    virtual void descheduleDeadlockEvent() = 0;
1225034SN/A
1235034SN/A    //
1242SN/A    // Called by the controller to give the sequencer a pointer.
1253187SN/A    // A pointer to the controller is needed for atomic support.
1263187SN/A    //
1273187SN/A    void setController(AbstractController* _cntrl) { m_controller = _cntrl; }
1283187SN/A    int getId() { return m_version; }
1293187SN/A    unsigned int drain(Event *de);
1305034SN/A
1315034SN/A  protected:
1325034SN/A    const std::string m_name;
1335034SN/A    void ruby_hit_callback(PacketPtr pkt);
1347544SN/A    void testDrainComplete();
1355034SN/A    void ruby_eviction_callback(const Address& address);
1365034SN/A
1375034SN/A    int m_version;
1385034SN/A    AbstractController* m_controller;
1395034SN/A    MessageBuffer* m_mandatory_q_ptr;
1408436SBrad.Beckmann@amd.com    PioPort pio_port;
1418436SBrad.Beckmann@amd.com    bool m_usingRubyTester;
1422SN/A
1437544SN/A  private:
1447544SN/A    void addToRetryList(M5Port * port)
1453187SN/A    {
1465034SN/A        if (!port->onRetryList()) {
1472SN/A            port->onRetryList(true);
1482SN/A            retryList.push_back(port);
1492SN/A            waitingOnSequencer = true;
1502SN/A        }
1512SN/A    }
1522SN/A
1532SN/A    unsigned int getDrainCount(Event *de);
1548436SBrad.Beckmann@amd.com
1555606SN/A    uint16_t m_port_id;
1561298SN/A    uint64_t m_request_cnt;
1573187SN/A
1587544SN/A    PioPort physMemPort;
1593187SN/A
1603187SN/A    /*! Vector of CPU Port attached to this Ruby port. */
1613187SN/A    typedef std::vector<M5Port*>::iterator CpuPortIter;
1623187SN/A    std::vector<M5Port*> cpu_ports;
1633187SN/A
1643187SN/A    Event *drainEvent;
1653187SN/A
1663187SN/A    PhysicalMemory* physmem;
1673187SN/A    RubySystem* ruby_system;
1683187SN/A
1693187SN/A    //
1703187SN/A    // Based on similar code in the M5 bus.  Stores pointers to those ports
1713187SN/A    // that should be called when the Sequencer becomes available after a stall.
1723187SN/A    //
1733187SN/A    std::list<M5Port*> retryList;
1743187SN/A
1753187SN/A    bool waitingOnSequencer;
1763187SN/A    bool access_phys_mem;
1773187SN/A};
1783187SN/A
1793187SN/A#endif // __MEM_RUBY_SYSTEM_RUBYPORT_HH__
1804579SN/A