system.hh revision 8922
1/*
2 * Copyright (c) 2012 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder.  You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Copyright (c) 2002-2005 The Regents of The University of Michigan
15 * Copyright (c) 2011 Regents of the University of California
16 * All rights reserved.
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions are
20 * met: redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer;
22 * redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution;
25 * neither the name of the copyright holders nor the names of its
26 * contributors may be used to endorse or promote products derived from
27 * this software without specific prior written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 *
41 * Authors: Steve Reinhardt
42 *          Lisa Hsu
43 *          Nathan Binkert
44 *          Rick Strong
45 */
46
47#ifndef __SYSTEM_HH__
48#define __SYSTEM_HH__
49
50#include <string>
51#include <vector>
52
53#include "base/loader/symtab.hh"
54#include "base/misc.hh"
55#include "base/statistics.hh"
56#include "cpu/pc_event.hh"
57#include "enums/MemoryMode.hh"
58#include "kern/system_events.hh"
59#include "mem/fs_translating_port_proxy.hh"
60#include "mem/mem_object.hh"
61#include "mem/port.hh"
62#include "params/System.hh"
63
64class BaseCPU;
65class BaseRemoteGDB;
66class GDBListener;
67class ObjectFile;
68class PhysicalMemory;
69class Platform;
70class ThreadContext;
71
72class System : public MemObject
73{
74  private:
75
76    /**
77     * Private class for the system port which is only used as a
78     * master for debug access and for non-structural entities that do
79     * not have a port of their own.
80     */
81    class SystemPort : public MasterPort
82    {
83      public:
84
85        /**
86         * Create a system port with a name and an owner.
87         */
88        SystemPort(const std::string &_name, MemObject *_owner)
89            : MasterPort(_name, _owner)
90        { }
91        bool recvTiming(PacketPtr pkt)
92        { panic("SystemPort does not receive timing!\n"); return false; }
93        void recvRetry()
94        { panic("SystemPort does not expect retry!\n"); }
95        Tick recvAtomic(PacketPtr pkt)
96        { panic("SystemPort does not receive atomic!\n"); return 0; }
97        void recvFunctional(PacketPtr pkt)
98        { panic("SystemPort does not receive functional!\n"); }
99    };
100
101    SystemPort _systemPort;
102
103  public:
104
105    /**
106     * After all objects have been created and all ports are
107     * connected, check that the system port is connected.
108     */
109    virtual void init();
110
111    /**
112     * Get a reference to the system port that can be used by
113     * non-structural simulation objects like processes or threads, or
114     * external entities like loaders and debuggers, etc, to access
115     * the memory system.
116     *
117     * @return a reference to the system port we own
118     */
119    MasterPort& getSystemPort() { return _systemPort; }
120
121    /**
122     * Additional function to return the Port of a memory object.
123     */
124    MasterPort& getMasterPort(const std::string &if_name, int idx = -1);
125
126    static const char *MemoryModeStrings[3];
127
128    Enums::MemoryMode
129    getMemoryMode()
130    {
131        assert(memoryMode);
132        return memoryMode;
133    }
134
135    /** Change the memory mode of the system. This should only be called by the
136     * python!!
137     * @param mode Mode to change to (atomic/timing)
138     */
139    void setMemoryMode(Enums::MemoryMode mode);
140
141    PhysicalMemory *physmem;
142    PCEventQueue pcEventQueue;
143
144    std::vector<ThreadContext *> threadContexts;
145    int _numContexts;
146
147    ThreadContext *getThreadContext(ThreadID tid)
148    {
149        return threadContexts[tid];
150    }
151
152    int numContexts()
153    {
154        assert(_numContexts == (int)threadContexts.size());
155        return _numContexts;
156    }
157
158    /** Return number of running (non-halted) thread contexts in
159     * system.  These threads could be Active or Suspended. */
160    int numRunningContexts();
161
162    /** List to store ranges of memories in this system */
163    AddrRangeList memRanges;
164
165    /** check if an address points to valid system memory
166     * and thus we can fetch instructions out of it
167     */
168    bool isMemory(const Addr addr) const;
169
170    Addr pagePtr;
171
172    uint64_t init_param;
173
174    /** Port to physical memory used for writing object files into ram at
175     * boot.*/
176    PortProxy physProxy;
177    FSTranslatingPortProxy virtProxy;
178
179    /** kernel symbol table */
180    SymbolTable *kernelSymtab;
181
182    /** Object pointer for the kernel code */
183    ObjectFile *kernel;
184
185    /** Begining of kernel code */
186    Addr kernelStart;
187
188    /** End of kernel code */
189    Addr kernelEnd;
190
191    /** Entry point in the kernel to start at */
192    Addr kernelEntry;
193
194    /** Mask that should be anded for binary/symbol loading.
195     * This allows one two different OS requirements for the same ISA to be
196     * handled.  Some OSes are compiled for a virtual address and need to be
197     * loaded into physical memory that starts at address 0, while other
198     * bare metal tools generate images that start at address 0.
199     */
200    Addr loadAddrMask;
201
202  protected:
203    uint64_t nextPID;
204
205  public:
206    uint64_t allocatePID()
207    {
208        return nextPID++;
209    }
210
211    /** Amount of physical memory that is still free */
212    Addr freeMemSize();
213
214    /** Amount of physical memory that exists */
215    Addr memSize();
216
217  protected:
218    Enums::MemoryMode memoryMode;
219    uint64_t workItemsBegin;
220    uint64_t workItemsEnd;
221    uint32_t numWorkIds;
222    std::vector<bool> activeCpus;
223
224    /** This array is a per-sytem list of all devices capable of issuing a
225     * memory system request and an associated string for each master id.
226     * It's used to uniquely id any master in the system by name for things
227     * like cache statistics.
228     */
229    std::vector<std::string> masterIds;
230
231  public:
232
233    /** Request an id used to create a request object in the system. All objects
234     * that intend to issues requests into the memory system must request an id
235     * in the init() phase of startup. All master ids must be fixed by the
236     * regStats() phase that immediately preceeds it. This allows objects in the
237     * memory system to understand how many masters may exist and
238     * appropriately name the bins of their per-master stats before the stats
239     * are finalized
240     */
241    MasterID getMasterId(std::string req_name);
242
243    /** Get the name of an object for a given request id.
244     */
245    std::string getMasterName(MasterID master_id);
246
247    /** Get the number of masters registered in the system */
248    MasterID maxMasters()
249    {
250        return masterIds.size();
251    }
252
253    virtual void regStats();
254    /**
255     * Called by pseudo_inst to track the number of work items started by this
256     * system.
257     */
258    uint64_t
259    incWorkItemsBegin()
260    {
261        return ++workItemsBegin;
262    }
263
264    /**
265     * Called by pseudo_inst to track the number of work items completed by
266     * this system.
267     */
268    uint64_t
269    incWorkItemsEnd()
270    {
271        return ++workItemsEnd;
272    }
273
274    /**
275     * Called by pseudo_inst to mark the cpus actively executing work items.
276     * Returns the total number of cpus that have executed work item begin or
277     * ends.
278     */
279    int
280    markWorkItem(int index)
281    {
282        int count = 0;
283        assert(index < activeCpus.size());
284        activeCpus[index] = true;
285        for (std::vector<bool>::iterator i = activeCpus.begin();
286             i < activeCpus.end(); i++) {
287            if (*i) count++;
288        }
289        return count;
290    }
291
292    inline void workItemBegin(uint32_t tid, uint32_t workid)
293    {
294        std::pair<uint32_t,uint32_t> p(tid, workid);
295        lastWorkItemStarted[p] = curTick();
296    }
297
298    void workItemEnd(uint32_t tid, uint32_t workid);
299
300    /**
301     * Fix up an address used to match PCs for hooking simulator
302     * events on to target function executions.  See comment in
303     * system.cc for details.
304     */
305    virtual Addr fixFuncEventAddr(Addr addr)
306    {
307        panic("Base fixFuncEventAddr not implemented.\n");
308    }
309
310    /**
311     * Add a function-based event to the given function, to be looked
312     * up in the specified symbol table.
313     */
314    template <class T>
315    T *addFuncEvent(SymbolTable *symtab, const char *lbl)
316    {
317        Addr addr = 0; // initialize only to avoid compiler warning
318
319        if (symtab->findAddress(lbl, addr)) {
320            T *ev = new T(&pcEventQueue, lbl, fixFuncEventAddr(addr));
321            return ev;
322        }
323
324        return NULL;
325    }
326
327    /** Add a function-based event to kernel code. */
328    template <class T>
329    T *addKernelFuncEvent(const char *lbl)
330    {
331        return addFuncEvent<T>(kernelSymtab, lbl);
332    }
333
334  public:
335    std::vector<BaseRemoteGDB *> remoteGDB;
336    std::vector<GDBListener *> gdbListen;
337    bool breakpoint();
338
339  public:
340    typedef SystemParams Params;
341
342  protected:
343    Params *_params;
344
345  public:
346    System(Params *p);
347    ~System();
348
349    void initState();
350
351    const Params *params() const { return (const Params *)_params; }
352
353  public:
354
355    /**
356     * Returns the addess the kernel starts at.
357     * @return address the kernel starts at
358     */
359    Addr getKernelStart() const { return kernelStart; }
360
361    /**
362     * Returns the addess the kernel ends at.
363     * @return address the kernel ends at
364     */
365    Addr getKernelEnd() const { return kernelEnd; }
366
367    /**
368     * Returns the addess the entry point to the kernel code.
369     * @return entry point of the kernel code
370     */
371    Addr getKernelEntry() const { return kernelEntry; }
372
373    /// Allocate npages contiguous unused physical pages
374    /// @return Starting address of first page
375    Addr allocPhysPages(int npages);
376
377    int registerThreadContext(ThreadContext *tc, int assigned=-1);
378    void replaceThreadContext(ThreadContext *tc, int context_id);
379
380    void serialize(std::ostream &os);
381    void unserialize(Checkpoint *cp, const std::string &section);
382    virtual void resume();
383
384  public:
385    Counter totalNumInsts;
386    EventQueue instEventQueue;
387    std::map<std::pair<uint32_t,uint32_t>, Tick>  lastWorkItemStarted;
388    std::map<uint32_t, Stats::Histogram*> workItemStats;
389
390    ////////////////////////////////////////////
391    //
392    // STATIC GLOBAL SYSTEM LIST
393    //
394    ////////////////////////////////////////////
395
396    static std::vector<System *> systemList;
397    static int numSystemsRunning;
398
399    static void printSystems();
400
401
402};
403
404#endif // __SYSTEM_HH__
405