text: /*
   * Copyright (c) 20014-15 Arizona State University
   * All rights reserved.
   *
   * 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: Reiley Jeyapaul,
   *	    Srinivas Tanikella,
   *	    Jongeun Lee
   *
   *	    Compiler and Microarchitecture Lab, ASU
   * 	    http://aviral.lab.asu.edu
   */
  
  #include "base/vulnerability/vul_cache.hh"
  #include "debug/VulTracker.hh" //YOHAN
  
  CacheVulCalc::CacheVulCalc(int cacheline, int protMode)
      : cacheLineSize(cacheline),
        protectionMode(protMode)
  {
      numWords = cacheline / WORD_SIZE;
  }
  
  void
  CacheVulCalc::vulOnInsert(CacheBlk *blk)
  {
  	DPRINTF(VulTracker, "vulOnInsert %s\n", blk->print());
      if(protectionMode == PARITY_BLOCK) {
          for(unsigned i = 0; i < numWords; ++i) {
              blk->dataVulHist[i].op = INCOMING;
              blk->dataVulHist[i].t = curTick();
              blk->dataVulHist[i].incomingTick = curTick();
          }
      } else if(protectionMode == PARITY_WORD) {
          for(unsigned i = 0; i < numWords; ++i) {
              blk->dataVulHist[i].op = INCOMING;
              blk->dataVulHist[i].t = curTick();
          }
      } else if (protectionMode == ECC_BLOCK) {
  
      } else if (protectionMode == ECC_WORD) {
  
      } else {
          for(unsigned i = 0; i < numWords; ++i) {
              blk->dataVulHist[i].op = INCOMING;
              blk->dataVulHist[i].t = curTick();
          }
      }
  
  }
  
  long
  CacheVulCalc::vulOnRead(CacheBlk *blk, PacketPtr pkt)
  {
  	DPRINTF(VulTracker, "vulOnRead %s\n", blk->print());
      long vulTime = 0;
  
      if(protectionMode == PARITY_BLOCK) {
          for(unsigned i = 0; i < numWords; ++i) {
              if(blk->isDirty()) {
                  if(isTarget(pkt, i)) {
                      vulTime += curTick() - getRecent(blk);
                      blk->dataVulHist[i].op = READ;
                      blk->dataVulHist[i].t = curTick();
                  }
              } else {
                  blk->dataVulHist[i].op = READ;
                  blk->dataVulHist[i].t = curTick();
              }
          }
      } else if(protectionMode == PARITY_WORD) {
          for(unsigned i = 0; i < numWords; ++i) {
              if(blk->isDirty()) {
                  if(isTarget(pkt, i)) {
                      vulTime += curTick() - blk->dataVulHist[i].t;
                      blk->dataVulHist[i].op = READ;
                      blk->dataVulHist[i].t = curTick();
                  }
              } else {
                  if(isTarget(pkt, i)) {
                      blk->dataVulHist[i].op = READ;
                      blk->dataVulHist[i].t = curTick();
                  }
              }
          }
      } else if(protectionMode == ECC_BLOCK) {
  
      } else if(protectionMode == ECC_WORD) {
  
      } else {
          for(unsigned i = 0; i < numWords; ++i) {
              if(isTarget(pkt, i)) {
                  vulTime += curTick() - blk->dataVulHist[i].t;
                  blk->dataVulHist[i].op = READ;
                  blk->dataVulHist[i].t = curTick();
                  break;
              }
          }
      }
  
      return (vulTime/TICKS_PER_CYCLE)*WORD_SIZE;
  }
  
  void 
  CacheVulCalc::vulOnWrite(CacheBlk *blk, PacketPtr pkt)
  {
  	DPRINTF(VulTracker, "vulOnWrite %s\n", blk->print());
      if(protectionMode == PARITY_BLOCK) {
          for(unsigned i = 0; i < numWords; ++i) {
              if(isTarget(pkt, i)) {
                  blk->dataVulHist[i].op = WRITE;
                  blk->dataVulHist[i].t = curTick();
                  break;
              }
          }
      } else if(protectionMode == PARITY_WORD) {
          for(unsigned i = 0; i < numWords; ++i) {
              if(isTarget(pkt, i)) {
                  blk->dataVulHist[i].op = WRITE;
                  blk->dataVulHist[i].t = curTick();
                  break;
              }
          }           
      } else if(protectionMode == ECC_BLOCK) {
  
      } else if(protectionMode == ECC_WORD) {
  
      } else {
          for(unsigned i = 0; i < numWords; ++i) {
              if(isTarget(pkt, i)) {
                  blk->dataVulHist[i].op = WRITE;
                  blk->dataVulHist[i].t = curTick();
              }
          }
      }
  
  }
  
  long
  CacheVulCalc::vulOnEvict(CacheBlk *blk)
  {
  	DPRINTF(VulTracker, "vulOnEvict %s\n", blk->print());
      long vulTime = 0;
  
      if(protectionMode == PARITY_BLOCK) {
          for(unsigned i = 0; i < numWords; ++i) {
              if(blk->isDirty())
                  vulTime += curTick() - getRecent(blk);
              blk->dataVulHist[i].op = INVALID;
              blk->dataVulHist[i].t = curTick();
  
          }
      } else if(protectionMode == PARITY_WORD) {
          for(unsigned i =0; i < numWords; ++i) {
              if(blk->isDirty())
                  vulTime += curTick() - blk->dataVulHist[i].t;
              blk->dataVulHist[i].op = INVALID;
              blk->dataVulHist[i].t = curTick();
          }
      } else if(protectionMode == ECC_BLOCK) {
  
      } else if(protectionMode == ECC_WORD) {
  
      } else {
          for(unsigned i = 0; i < numWords; ++i) {
              if(blk->isDirty())
                  vulTime += curTick() - blk->dataVulHist[i].t;
              blk->dataVulHist[i].op = INVALID;
              blk->dataVulHist[i].t = curTick();
          }
      }
  
      return (vulTime/TICKS_PER_CYCLE)*WORD_SIZE;
  
  }
  
  Tick
  CacheVulCalc::getRecent(CacheBlk *blk)
  {
      Tick t=0;
      int size = cacheLineSize/WORD_SIZE;
      for(unsigned int i=0; i < size; i++) {
          if(blk->dataVulHist[i].t > t)
              t = blk->dataVulHist[i].t;
      }
      return t;
  }
  
  bool
  CacheVulCalc::isTarget(PacketPtr pkt, unsigned wordIdx)
  {
      Addr start = pkt->getOffset(cacheLineSize)/WORD_SIZE;
      assert(pkt->getSize() > 0);
      Addr end = start + (pkt->getSize() - 1)/WORD_SIZE;
      if(wordIdx >= start && wordIdx <= end)
          return true;
      else
          return false;
  }
      
  