summaryrefslogtreecommitdiff
path: root/src/mem/stack_dist_calc.hh
diff options
context:
space:
mode:
Diffstat (limited to 'src/mem/stack_dist_calc.hh')
-rw-r--r--src/mem/stack_dist_calc.hh454
1 files changed, 454 insertions, 0 deletions
diff --git a/src/mem/stack_dist_calc.hh b/src/mem/stack_dist_calc.hh
new file mode 100644
index 000000000..881b71179
--- /dev/null
+++ b/src/mem/stack_dist_calc.hh
@@ -0,0 +1,454 @@
+/*
+ * Copyright (c) 2014 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Kanishk Sugand
+ * Andreas Hansson
+ */
+
+#ifndef __MEM_STACK_DIST_CALC_HH__
+#define __MEM_STACK_DIST_CALC_HH__
+
+#include <map>
+#include <vector>
+
+#include "base/types.hh"
+#include "mem/packet.hh"
+#include "params/StackDistCalc.hh"
+#include "sim/sim_object.hh"
+#include "sim/stats.hh"
+
+/**
+ * The stack distance calculator is a passive object that merely
+ * observes the addresses pass to it. It calculates stack distances
+ * of incoming addresses based on the partial sum hierarchy tree
+ * algorithm described by Alamasi et al.
+ * http://doi.acm.org/10.1145/773039.773043.
+ *
+ * A tree structure is maintained and updated at each transaction
+ * (unique or non-unique). The tree is implemented as an STL vector
+ * with layers of the form <map> Each layer in this tree is an
+ * ordered map <uint64_t, Node*>. Nodes are structs which take form
+ * of leaf, intermediate and root nodes. For example, in a tree with 3
+ * layers, tree[0][5] gives a leaf node pointer for key=5 tree[1][1]
+ * gives an intermediate node pointer for key=1 tree[2][0] gives the
+ * root node in the tree.
+ *
+ * At every transaction a hash-map (aiMap) is looked up to check if
+ * the address was already encountered before. Based on this lookup a
+ * transaction can be termed as unique or non-unique.
+ *
+ * In addition to the normal stack distance calculation, a feature to
+ * mark an old node in the tree is added. This is useful if it is
+ * required to see the reuse pattern. For example, BackInvalidates
+ * from a lower level (e.g. membus to L2), can be marked (isMarked
+ * flag of Node set to True). Then later if this same address is
+ * accessed (by L1), the value of the isMarked flag would be
+ * True. This would give some insight on how the BackInvalidates
+ * policy of the lower level affect the read/write accesses in an
+ * application.
+ *
+ * There are two functions provided to interface with the calculator:
+ * 1. pair<uint64_t, bool> calcStackDistAndUpdate(Addr r_address,
+ * bool addNewNode)
+ * At every unique transaction a new leaf node is added at tree[0](leaf layer)
+ * and linked to the layer above (if addNewNode is True). The sums of all
+ * the intermediate nodes is updated till the root. The stack-distance is
+ * returned as a Constant representing INFINITY.
+ *
+ * At every non-unique transaction the tree is traversed from the
+ * leaf at the returned index to the root, the old node is deleted
+ * from the tree, and the sums (to the right are collected) and
+ * decremented. The collected sum represets the stack distance of the
+ * found node. If this node was marked then a bool flag set to True
+ * is returned with the stack_distance. During this operation a node
+ * is discarded at the leaf layer always. Moreover during the
+ * traversal upwards using the updateSum() method, if an intermediate
+ * node is found with no children connected to it, then that is
+ * discarded too.
+ *
+ * The return value of this function is a pair representing the
+ * stack_distance and the value of the marked flag.
+ *
+ * 2. pair<uint64_t , bool> calcStackDist(Addr r_address, bool mark)
+ * This is a stripped down version of the above function which is used to
+ * just inspect the tree, and mark a leaf node (if mark flag is set). The
+ * functionality to add a new node is removed.
+ *
+ * At every unique transaction the stack-distance is returned as a constant
+ * representing INFINITY.
+ *
+ * At every non-unique transaction the tree is traversed from the
+ * leaf at the returned index to the root, and the sums (to the right)
+ * are collected. The collected sum represets the stack distance of
+ * the found node.
+ *
+ * This function does NOT Modify the stack. (No node is added or
+ * deleted). It is just used to mark a node already created and get
+ * its stack distance.
+ *
+ * The return value of this function is a pair representing the stack
+ * distance and the value of the marked flag.
+ *
+ * The table below depicts the usage of the Algorithm using the functions:
+ * pair<uint64_t Stack_dist, bool isMarked> calcStackDistAndUpdate
+ * (Addr r_address, bool addNewNode)
+ * pair<uint64_t Stack_dist, bool isMarked> calcStackDist
+ * (Addr r_address, bool mark)
+ *
+ * | Function | Arguments |Return Val |Use For|
+ * |calcStackDistAndUpdate|r_address, True|I/SD,False |A,GD,GM|
+ * |calcStackDistAndUpdate|r_address,False|SD,prevMark|D,GD,GM|
+ * |calcStackDist |r_address,False|SD,prevMark| GD,GM|
+ * |calcStackDist |r_address, True|SD,prevMark| GD,GM|
+ *
+ * (*A: Allocate an address in stack, if old entry present then it is deleted,
+ * *U: Delete old-address from stack, no new entry is added
+ * *GD: Get-Stack distance of an address,
+ * *GM: Get value of Mark flag, indicates if that address has been touched
+ * before,
+ * *I: stack-distance = infinity,
+ * *SD: Stack Distance
+ * *r_address: address to be added, *prevMark: value of isMarked flag
+ * of the Node)
+ *
+ * Invalidates refer to a type of packet that removes something from
+ * a cache, either autonoumously (due-to cache's own replacement
+ * policy), or snoops from other caches which invalidate something
+ * inside our cache.
+ *
+ * Usage | Function to use |Typical Use |
+ * Add new entry |calcStackDistAndUpdate|Read/Write Allocate |
+ * Delete Old Entry |calcStackDistAndUpdate|Writebacks/Cleanevicts|
+ * Dist.of Old entry|calcStackDist |Cleanevicts/Invalidate|
+ *
+ * Node Balancing: The tree structure is maintained by an
+ * updateTree() operation called when an intermediate node is
+ * required. The update operation is roughly categorized as a root
+ * update or intermediate layer update. When number of leaf nodes
+ * grow over a power of 2 then a new layer is added at the top of the
+ * tree and a new root node is initialized. The old node at the lower
+ * layer is connected to this. In an intermediate node update
+ * operation a new intermediate node is added to the required layer.
+ *
+ * Debugging: Debugging can be enabled by setting the verifyStack flag
+ * true. Debugging is implemented using a dummy stack that behaves in
+ * a naive way, using STL vectors (i.e each unique address is pushed
+ * on the top of an STL vector stack, and SD is returned as
+ * Infinity. If a non unique address is encountered then the previous
+ * entry in the STL vector is removed, all the entities above it are
+ * pushed down, and the address is pushed at the top of the stack).
+ *
+ * A printStack(int numOfEntitiesToPrint) is provided to print top n entities
+ * in both (tree and STL based dummy stack).
+ */
+class StackDistCalc : public SimObject
+{
+
+ private:
+
+ struct Node;
+
+ typedef std::map<uint64_t, Node*> IndexNodeMap;
+ typedef std::map<Addr, uint64_t> AddressIndexMap;
+ typedef std::vector<IndexNodeMap> TreeType;
+
+ /**
+ * Gets sum from the node upwards recursively till the root. This
+ * function is called first by getSumsLeavesToRoot, and then
+ * recursively calls itself.
+ *
+ * @param node pointer to the node which is updated
+ * @param from_left variable which says that the request arrived
+ * from the left
+ * @param sum_from_below Sum of left and right children below
+ * @param level level in the tree the calling node is located
+ * @param stack_dist stack distance of the node below
+ * @return The stack distance of the current address.
+ *
+ */
+ uint64_t getSum(Node* node, bool from_left, uint64_t sum_from_below,
+ uint64_t stack_dist, uint64_t level) const;
+
+ /**
+ * Gets the sum from the leaf node specified. This function
+ * is called by calcStackDist.
+ *
+ * @param node pointer to the node which is updated
+ * @return The stack distance of the current address.
+ *
+ */
+ uint64_t getSumsLeavesToRoot(Node* node) const;
+
+ /**
+ * Updates the nodes upwards recursively till the root.
+ * This function is first called by updateSumsLeavesToRoot,
+ * and then it recursively calls itself.
+ *
+ * @param node pointer to the node which is updated
+ * @param from_left variable which says that the request arrived
+ * from the left
+ * @param sum_from_below Sum of left and right children below
+ * @param level level in the tree the calling node is located
+ * @param stack_dist stack distance of the node below
+ * @param discard_node whether the calling node was discarded or not
+ * @return The stack distance of the current address.
+ *
+ */
+ uint64_t updateSum(Node* node,
+ bool from_left, uint64_t sum_from_below, uint64_t level,
+ uint64_t stack_dist, bool discard_node);
+
+ /**
+ * Updates the leaf nodes and nodes above. This function is
+ * called by the calcStackDistAndUpdate.
+ *
+ * @param node pointer to the node which is updated
+ * @param is_new_leaf is true if this is a newly added node
+ * @return The stack distance of the current address.
+ *
+ */
+ uint64_t updateSumsLeavesToRoot(Node* node, bool is_new_leaf);
+
+ /**
+ * updateTree is a tree balancing operation, which maintains the
+ * binary tree structure.
+ * This method is called whenever index%2 == 0 (i.e. every
+ * alternate cycle) The two main operation are :
+ * OP1. Moving the root node one layer up if index counter
+ * crosses power of 2
+ * OP2. Addition of intermediate nodes as and when required
+ * and linking them to their parents in the layer above.
+ */
+ void updateTree();
+
+ /**
+ * This method is used for verification purposes
+ * It recursively traverses upwards from the given node till
+ * the root to check if the ultimate parent node (root-node) points
+ * to null.
+ *
+ * @param node pointer to the node whose sanity is being checked
+ * @param level the level at which this node is located in the tree
+ *
+ */
+ void sanityCheckTree(const Node* node, uint64_t level = 0) const;
+
+ /**
+ * A convenient way of refering to infinity.
+ */
+ static constexpr uint64_t Infinity = std::numeric_limits<uint64_t>::max();
+
+ /**
+ * Process the given address. If Mark is true then set the
+ * mark flag of the leaf node.
+ * This function returns the stack distance of the incoming
+ * address and the previous status of the mark flag.
+ *
+ * @param r_address The current address to process
+ * @param mark set the mark flag for the address.
+ * @return The stack distance of the current address and the mark flag.
+ */
+ std::pair<uint64_t , bool> calcStackDist(const Addr r_address,
+ bool mark = false);
+
+ /**
+ * Process the given address:
+ * - Lookup the tree for the given address
+ * - delete old node if found in tree
+ * - add a new node (if addNewNode flag is set)
+ * This function returns the stack distance of the incoming
+ * address and the status of the mark flag.
+ *
+ * @param r_address The current address to process
+ * @param addNewNode If true, a new node is added to the tree
+ * @return The stack distance of the current address and the mark flag.
+ */
+ std::pair<uint64_t, bool> calcStackDistAndUpdate(const Addr r_address,
+ bool addNewNode = true);
+
+ /**
+ * Return the counter for address accesses (unique and
+ * non-unique). This is further used to dump stats at
+ * regular intervals.
+ *
+ * @return The stack distance of the current address.
+ */
+ uint64_t getIndex() const { return index; }
+
+ /**
+ * Query depth of the tree (tree[0] represents leaf layer while
+ * tree[treeDepth] represents the root layer, all layers in
+ * between contain intermediate nodes)
+ *
+ * @return Tree depth
+ */
+ uint64_t getTreeDepth() const { return tree.size() - 1; }
+
+ /**
+ * Print the last n items on the stack.
+ * This method prints top n entries in the tree based implementation as
+ * well as dummy stack.
+ * @param n Number of entries to print
+ */
+ void printStack(int n = 5) const;
+
+ /**
+ * This is an alternative implementation of the stack-distance
+ * in a naive way. It uses simple STL vector to represent the stack.
+ * It can be used in parallel for debugging purposes.
+ * It is 10x slower than the tree based implemenation.
+ *
+ * @param r_address The current address to process
+ * @param update_stack Flag to indicate if stack should be updated
+ * @return Stack distance which is calculated by this alternative
+ * implementation
+ *
+ */
+ uint64_t verifyStackDist(const Addr r_address,
+ bool update_stack = false);
+
+ public:
+
+ /**
+ * Convenience method to get the params when registering stats.
+ */
+ const StackDistCalcParams* params() const
+ { return reinterpret_cast<const StackDistCalcParams*>(_params); }
+
+ StackDistCalc(const StackDistCalcParams* p);
+
+ ~StackDistCalc();
+
+ void regStats();
+
+ /**
+ * Update the tree and the statistics.
+ *
+ * @param cmd Command from the packet
+ * @param addr Address to put on the stack
+ */
+ void update(const MemCmd& cmd, Addr addr);
+
+ private:
+
+ /**
+ * Node which takes form of Leaf, INode or Root
+ */
+ struct Node{
+ // Sum of the left children
+ uint64_t sumLeft;
+
+ // Sum of the right children
+ uint64_t sumRight;
+
+ // Flag to indicate that sumLeft has gone from non-zero value to 0
+ bool discardLeft;
+
+ // Flag to indicate that sumRight has gone from non-zero value to 0
+ bool discardRight;
+
+ // Index of the current element in the Map
+ uint64_t nodeIndex;
+
+ // Pointer to the parent
+ Node* parent;
+
+ // Flag to mark the node as the right/left child
+ bool isLeftNode;
+
+ /**
+ * Flag to indicate if this address is marked. Used in case
+ * where stack distance of a touched address is required.
+ */
+ bool isMarked;
+
+ /**
+ * The discard flags are false by default they become true if
+ * the node is reached again in a future lookup.
+ */
+ Node() : sumLeft(0), sumRight(0), discardLeft(false),
+ discardRight(false), nodeIndex(0),
+ parent(nullptr), isLeftNode(true), isMarked(false)
+ { }
+ };
+
+ /**
+ * Internal counter for address accesses (unique and non-unique)
+ * This counter increments everytime the calcStackDist() method is
+ * called. This counter is used as a key for the hash- map at the
+ * leaf layer. Practically at every call to the calculator this
+ * counter is incremented and a new leaf node is added in the tree
+ * at the leaf layer using this counter value as the key.
+ */
+ uint64_t index;
+
+ // Binary tree of partial sums
+ TreeType tree;
+
+ // Hash map which returns last seen index of each address
+ AddressIndexMap aiMap;
+
+ // Keeps count of number of the next unique index for each
+ // level in the tree
+ std::vector<uint64_t> nextIndex;
+
+ // Dummy Stack for verification
+ std::vector<uint64_t> stack;
+
+ // Flag to enable verification of stack. (Slows down the simulation)
+ const bool verifyStack;
+
+ // Disable the linear histograms
+ const bool disableLinearHists;
+
+ // Disable the logarithmic histograms
+ const bool disableLogHists;
+
+ // Reads linear histogram
+ Stats::Histogram readLinearHist;
+
+ // Reads logarithmic histogram
+ Stats::SparseHistogram readLogHist;
+
+ // Writes linear histogram
+ Stats::Histogram writeLinearHist;
+
+ // Writes logarithmic histogram
+ Stats::SparseHistogram writeLogHist;
+
+};
+
+#endif //__STACK_DIST_CALC_HH__