-# Copyright (c) 2012 ARM Limited
+# Copyright (c) 2012-2013 ARM Limited
# All rights reserved.
#
# The license below extends only to copyright in the software and shall
from m5.proxy import *
from MemObject import MemObject
from Prefetcher import BasePrefetcher
-
+from Tags import *
class BaseCache(MemObject):
type = 'BaseCache'
mem_side = MasterPort("Port on side closer to MEM")
addr_ranges = VectorParam.AddrRange([AllMemory], "The address range for the CPU-side port")
system = Param.System(Parent.any, "System we belong to")
+ tags = Param.BaseTags(LRU(), "Tag Store for LRU caches")
BaseCache *
BaseCacheParams::create()
{
- int numSets = size / (assoc * block_size);
-
- if (numSets == 1) {
- FALRU *tags = new FALRU(block_size, size, hit_latency);
- return new Cache<FALRU>(this, tags);
+ unsigned numSets = size / (assoc * block_size);
+
+ assert(tags);
+
+ if (dynamic_cast<FALRU*>(tags)) {
+ if (numSets != 1)
+ fatal("Got FALRU tags with more than one set\n");
+ return new Cache<FALRU>(this);
+ } else if (dynamic_cast<LRU*>(tags)) {
+ if (numSets == 1)
+ warn("Consider using FALRU tags for a fully associative cache\n");
+ return new Cache<LRU>(this);
} else {
- LRU *tags = new LRU(numSets, block_size, assoc, hit_latency);
- return new Cache<LRU>(this, tags);
+ fatal("No suitable tags selected\n");
}
}
public:
/** Instantiates a basic cache object. */
- Cache(const Params *p, TagStore *tags);
+ Cache(const Params *p);
void regStats();
#include "sim/sim_exit.hh"
template<class TagStore>
-Cache<TagStore>::Cache(const Params *p, TagStore *tags)
+Cache<TagStore>::Cache(const Params *p)
: BaseCache(p),
- tags(tags),
+ tags(dynamic_cast<TagStore*>(p->tags)),
prefetcher(p->prefetcher),
doFastWrites(true),
prefetchOnAccess(p->prefetch_on_access)
Cache<TagStore>::regStats()
{
BaseCache::regStats();
- tags->regStats(name());
}
template<class TagStore>
incMissCount(pkt);
return false;
}
- int master_id = pkt->req->masterId();
- tags->insertBlock(pkt->getAddr(), blk, master_id);
+ tags->insertBlock(pkt, blk);
blk->status = BlkValid | BlkReadable;
}
std::memcpy(blk->data, pkt->getPtr<uint8_t>(), blkSize);
tempBlock->tag = tags->extractTag(addr);
DPRINTF(Cache, "using temp block for %x\n", addr);
} else {
- int id = pkt->req->masterId();
- tags->insertBlock(pkt->getAddr(), blk, id);
+ tags->insertBlock(pkt, blk);
}
// we should never be overwriting a valid block
if env['TARGET_ISA'] == 'no':
Return()
+SimObject('Tags.py')
+
Source('base.cc')
Source('fa_lru.cc')
Source('lru.cc')
-Source('cacheset.cc')
--- /dev/null
+# Copyright (c) 2012-2013 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: Prakash Ramrakhyani
+
+from m5.params import *
+from m5.proxy import *
+from ClockedObject import ClockedObject
+
+class BaseTags(ClockedObject):
+ type = 'BaseTags'
+ abstract = True
+ cxx_header = "mem/cache/tags/base.hh"
+ # Get the size from the parent (cache)
+ size = Param.MemorySize(Parent.size, "capacity in bytes")
+
+ # Get the block size from the parent (cache)
+ block_size = Param.Int(Parent.block_size, "block size in bytes")
+
+ # Get the hit latency from the parent (cache)
+ hit_latency = Param.Cycles(Parent.hit_latency,
+ "The hit latency for this cache")
+
+class LRU(BaseTags):
+ type = 'LRU'
+ cxx_class = 'LRU'
+ cxx_header = "mem/cache/tags/lru.hh"
+ assoc = Param.Int(Parent.assoc, "associativity")
+
+class FALRU(BaseTags):
+ type = 'FALRU'
+ cxx_class = 'FALRU'
+ cxx_header = "mem/cache/tags/fa_lru.hh"
/*
+ * Copyright (c) 2013 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.
+ *
* Copyright (c) 2003-2005 The Regents of The University of Michigan
* All rights reserved.
*
using namespace std;
+BaseTags::BaseTags(const Params *p)
+ : ClockedObject(p), blkSize(p->block_size), size(p->size),
+ hitLatency(p->hit_latency)
+{
+}
+
void
BaseTags::setCache(BaseCache *_cache)
{
cache = _cache;
- objName = cache->name();
}
void
-BaseTags::regStats(const string &name)
+BaseTags::regStats()
{
using namespace Stats;
replacements
.init(maxThreadsPerCPU)
- .name(name + ".replacements")
+ .name(name() + ".replacements")
.desc("number of replacements")
.flags(total)
;
tagsInUse
- .name(name + ".tagsinuse")
+ .name(name() + ".tagsinuse")
.desc("Cycle average of tags in use")
;
totalRefs
- .name(name + ".total_refs")
+ .name(name() + ".total_refs")
.desc("Total number of references to valid blocks.")
;
sampledRefs
- .name(name + ".sampled_refs")
+ .name(name() + ".sampled_refs")
.desc("Sample count of references to valid blocks.")
;
avgRefs
- .name(name + ".avg_refs")
+ .name(name() + ".avg_refs")
.desc("Average number of references to valid blocks.")
;
avgRefs = totalRefs/sampledRefs;
warmupCycle
- .name(name + ".warmup_cycle")
+ .name(name() + ".warmup_cycle")
.desc("Cycle when the warmup percentage was hit.")
;
occupancies
.init(cache->system->maxMasters())
- .name(name + ".occ_blocks")
+ .name(name() + ".occ_blocks")
.desc("Average occupied blocks per requestor")
.flags(nozero | nonan)
;
}
avgOccs
- .name(name + ".occ_percent")
+ .name(name() + ".occ_percent")
.desc("Average percentage of cache occupancy")
.flags(nozero | total)
;
/*
- * Copyright (c) 2012 ARM Limited
+ * Copyright (c) 2012-2013 ARM Limited
* All rights reserved.
*
* The license below extends only to copyright in the software and shall
#include "base/callback.hh"
#include "base/statistics.hh"
+#include "params/BaseTags.hh"
+#include "sim/clocked_object.hh"
class BaseCache;
/**
* A common base class of Cache tagstore objects.
*/
-class BaseTags
+class BaseTags : public ClockedObject
{
protected:
+ /** The block size of the cache. */
+ const unsigned blkSize;
+ /** The size of the cache. */
+ const unsigned size;
+ /** The hit latency of the cache. */
+ const Cycles hitLatency;
+
/** Pointer to the parent cache. */
BaseCache *cache;
- /** Local copy of the parent cache name. Used for DPRINTF. */
- std::string objName;
-
/**
* The number of tags that need to be touched to meet the warmup
* percentage.
*/
public:
+ typedef BaseTagsParams Params;
+ BaseTags(const Params *p);
/**
* Destructor.
virtual ~BaseTags() {}
/**
- * Set the parent cache back pointer. Also copies the cache name to
- * objName.
+ * Set the parent cache back pointer.
* @param _cache Pointer to parent cache.
*/
void setCache(BaseCache *_cache);
- /**
- * Return the parent cache name.
- * @return the parent cache name.
- */
- const std::string &name() const
- {
- return objName;
- }
-
/**
* Register local statistics.
- * @param name The name to preceed each statistic name.
*/
- void regStats(const std::string &name);
+ void regStats();
/**
* Average in the reference count for valid blocks when the simulation
+++ /dev/null
-/*
- * Copyright (c) 2009 The Regents of The University of Michigan
- * 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: Lisa Hsu
- */
-
-
-#include "mem/cache/tags/cacheset.hh"
-
-CacheBlk*
-CacheSet::findBlk(Addr tag) const
-{
- for (int i = 0; i < assoc; ++i) {
- if (blks[i]->tag == tag && blks[i]->isValid()) {
- return blks[i];
- }
- }
- return 0;
-}
-
-void
-CacheSet::moveToHead(CacheBlk *blk)
-{
- // nothing to do if blk is already head
- if (blks[0] == blk)
- return;
-
- // write 'next' block into blks[i], moving up from MRU toward LRU
- // until we overwrite the block we moved to head.
-
- // start by setting up to write 'blk' into blks[0]
- int i = 0;
- CacheBlk *next = blk;
-
- do {
- assert(i < assoc);
- // swap blks[i] and next
- CacheBlk *tmp = blks[i];
- blks[i] = next;
- next = tmp;
- ++i;
- } while (next != blk);
-}
-
-void
-CacheSet::moveToTail(CacheBlk *blk)
-{
- // nothing to do if blk is already tail
- if (blks[assoc-1] == blk)
- return;
-
- // write 'next' block into blks[i], moving from LRU to MRU
- // until we overwrite the block we moved to tail.
-
- // start by setting up to write 'blk' into tail
- int i = assoc - 1;
- CacheBlk *next = blk;
-
- do {
- assert(i >= 0);
- // swap blks[i] and next
- CacheBlk *tmp = blks[i];
- blks[i] = next;
- next = tmp;
- --i;
- } while (next != blk);
-}
-
/*
+ * Copyright (c) 2013 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.
+ *
* Copyright (c) 2009 The Regents of The University of Michigan
* All rights reserved.
*
/**
* An associative set of cache blocks.
*/
+template <class Blktype>
class CacheSet
{
public:
int assoc;
/** Cache blocks in this set, maintained in LRU order 0 = MRU. */
- CacheBlk **blks;
+ Blktype **blks;
/**
* Find a block matching the tag in this set.
- * @param asid The address space ID.
+ * @param way_id The id of the way that matches the tag.
* @param tag The Tag to find.
- * @return Pointer to the block if found.
+ * @return Pointer to the block if found. Set way_id to assoc if none found
*/
- CacheBlk* findBlk(Addr tag) const;
+ Blktype* findBlk(Addr tag, int& way_id) const ;
+ Blktype* findBlk(Addr tag) const ;
/**
* Move the given block to the head of the list.
* @param blk The block to move.
*/
- void moveToHead(CacheBlk *blk);
+ void moveToHead(Blktype *blk);
/**
* Move the given block to the tail of the list.
* @param blk The block to move
*/
- void moveToTail(CacheBlk *blk);
+ void moveToTail(Blktype *blk);
};
+template <class Blktype>
+Blktype*
+CacheSet<Blktype>::findBlk(Addr tag, int& way_id) const
+{
+ /**
+ * Way_id returns the id of the way that matches the block
+ * If no block is found way_id is set to assoc.
+ */
+ way_id = assoc;
+ for (int i = 0; i < assoc; ++i) {
+ if (blks[i]->tag == tag && blks[i]->isValid()) {
+ way_id = i;
+ return blks[i];
+ }
+ }
+ return NULL;
+}
+
+template <class Blktype>
+Blktype*
+CacheSet<Blktype>::findBlk(Addr tag) const
+{
+ int ignored_way_id;
+ return findBlk(tag, ignored_way_id);
+}
+
+template <class Blktype>
+void
+CacheSet<Blktype>::moveToHead(Blktype *blk)
+{
+ // nothing to do if blk is already head
+ if (blks[0] == blk)
+ return;
+
+ // write 'next' block into blks[i], moving up from MRU toward LRU
+ // until we overwrite the block we moved to head.
+
+ // start by setting up to write 'blk' into blks[0]
+ int i = 0;
+ Blktype *next = blk;
+
+ do {
+ assert(i < assoc);
+ // swap blks[i] and next
+ Blktype *tmp = blks[i];
+ blks[i] = next;
+ next = tmp;
+ ++i;
+ } while (next != blk);
+}
+
+template <class Blktype>
+void
+CacheSet<Blktype>::moveToTail(Blktype *blk)
+{
+ // nothing to do if blk is already tail
+ if (blks[assoc - 1] == blk)
+ return;
+
+ // write 'next' block into blks[i], moving from LRU to MRU
+ // until we overwrite the block we moved to tail.
+
+ // start by setting up to write 'blk' into tail
+ int i = assoc - 1;
+ Blktype *next = blk;
+
+ do {
+ assert(i >= 0);
+ // swap blks[i] and next
+ Blktype *tmp = blks[i];
+ blks[i] = next;
+ next = tmp;
+ --i;
+ } while (next != blk);
+}
+
#endif
/*
+ * Copyright (c) 2013 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.
+ *
* Copyright (c) 2003-2005 The Regents of The University of Michigan
* All rights reserved.
*
using namespace std;
-FALRU::FALRU(unsigned _blkSize, unsigned _size, Cycles hit_latency)
- : blkSize(_blkSize), size(_size), hitLatency(hit_latency)
+FALRU::FALRU(const Params *p)
+ : BaseTags(p)
{
if (!isPowerOf2(blkSize))
fatal("cache block size (in bytes) `%d' must be a power of two",
}
void
-FALRU::regStats(const string &name)
+FALRU::regStats()
{
using namespace Stats;
- BaseTags::regStats(name);
+ BaseTags::regStats();
hits
.init(numCaches+1)
- .name(name + ".falru_hits")
+ .name(name() + ".falru_hits")
.desc("The number of hits in each cache size.")
;
misses
.init(numCaches+1)
- .name(name + ".falru_misses")
+ .name(name() + ".falru_misses")
.desc("The number of misses in each cache size.")
;
accesses
- .name(name + ".falru_accesses")
+ .name(name() + ".falru_accesses")
.desc("The number of accesses to the FA LRU cache.")
;
}
void
-FALRU::insertBlock(Addr addr, FALRU::BlkType *blk, int context_src)
+FALRU::insertBlock(PacketPtr pkt, FALRU::BlkType *blk)
{
}
blks[i].clearLoadLocks();
}
}
+
+FALRU *
+FALRUParams::create()
+{
+ return new FALRU(this);
+}
+
/*
- * Copyright (c) 2012 ARM Limited
+ * Copyright (c) 2012-2013 ARM Limited
* All rights reserved.
*
* The license below extends only to copyright in the software and shall
#include "mem/cache/tags/base.hh"
#include "mem/cache/blk.hh"
#include "mem/packet.hh"
+#include "params/FALRU.hh"
/**
* A fully associative cache block.
typedef std::list<FALRUBlk*> BlkList;
protected:
- /** The block size of the cache. */
- const unsigned blkSize;
- /** The size of the cache. */
- const unsigned size;
- /** The hit latency of the cache. */
- const Cycles hitLatency;
-
/** Array of pointers to blocks at the cache size boundaries. */
FALRUBlk **cacheBoundaries;
/** A mask for the FALRUBlk::inCache bits. */
*/
public:
+
+ typedef FALRUParams Params;
+
/**
* Construct and initialize this cache tagstore.
- * @param blkSize The block size of the cache.
- * @param size The size of the cache.
- * @param hit_latency The hit latency of the cache.
*/
- FALRU(unsigned blkSize, unsigned size, Cycles hit_latency);
+ FALRU(const Params *p);
~FALRU();
/**
* Register the stats for this object.
* @param name The name to prepend to the stats name.
*/
- void regStats(const std::string &name);
+ void regStats();
/**
* Invalidate a cache block.
*/
FALRUBlk* findVictim(Addr addr, PacketList & writebacks);
- void insertBlock(Addr addr, BlkType *blk, int context_src);
+ void insertBlock(PacketPtr pkt, BlkType *blk);
/**
* Return the hit latency of this cache.
return;
}
}
+
};
#endif // __MEM_CACHE_TAGS_FA_LRU_HH__
/*
- * Copyright (c) 2012 ARM Limited
+ * Copyright (c) 2012-2013 ARM Limited
* All rights reserved.
*
* The license below extends only to copyright in the software and shall
#include "base/intmath.hh"
#include "debug/Cache.hh"
#include "debug/CacheRepl.hh"
-#include "mem/cache/tags/cacheset.hh"
#include "mem/cache/tags/lru.hh"
#include "mem/cache/base.hh"
#include "sim/core.hh"
using namespace std;
-// create and initialize a LRU/MRU cache structure
-LRU::LRU(unsigned _numSets, unsigned _blkSize, unsigned _assoc,
- unsigned _hit_latency)
- : numSets(_numSets), blkSize(_blkSize), assoc(_assoc),
- hitLatency(_hit_latency)
+LRU::LRU(const Params *p)
+ :BaseTags(p), assoc(p->assoc),
+ numSets(p->size / (p->block_size * p->assoc))
{
// Check parameters
if (blkSize < 4 || !isPowerOf2(blkSize)) {
/** @todo Make warmup percentage a parameter. */
warmupBound = numSets * assoc;
- sets = new CacheSet[numSets];
+ sets = new SetType[numSets];
blks = new BlkType[numSets * assoc];
// allocate data storage in one big chunk
numBlocks = numSets * assoc;
}
void
-LRU::insertBlock(Addr addr, BlkType *blk, int master_id)
+LRU::insertBlock(PacketPtr pkt, BlkType *blk)
{
+ Addr addr = pkt->getAddr();
+ MasterID master_id = pkt->req->masterId();
if (!blk->isTouched) {
tagsInUse++;
blk->isTouched = true;
}
}
+LRU *
+LRUParams::create()
+{
+ return new LRU(this);
+}
std::string
LRU::print() const {
std::string cache_state;
/*
- * Copyright (c) 2012 ARM Limited
+ * Copyright (c) 2012-2013 ARM Limited
* All rights reserved.
*
* The license below extends only to copyright in the software and shall
#include <list>
#include "mem/cache/tags/base.hh"
+#include "mem/cache/tags/cacheset.hh"
#include "mem/cache/blk.hh"
#include "mem/packet.hh"
+#include "params/LRU.hh"
class BaseCache;
-class CacheSet;
/**
typedef CacheBlk BlkType;
/** Typedef for a list of pointers to the local block class. */
typedef std::list<BlkType*> BlkList;
+ /** Typedef the set type used in this tag store. */
+ typedef CacheSet<CacheBlk> SetType;
+
protected:
- /** The number of sets in the cache. */
- const unsigned numSets;
- /** The number of bytes in a block. */
- const unsigned blkSize;
/** The associativity of the cache. */
const unsigned assoc;
- /** The hit latency. */
- const Cycles hitLatency;
+ /** The number of sets in the cache. */
+ const unsigned numSets;
/** The cache sets. */
- CacheSet *sets;
+ SetType *sets;
/** The cache blocks. */
BlkType *blks;
unsigned blkMask;
public:
+
+ /** Convenience typedef. */
+ typedef LRUParams Params;
+
/**
* Construct and initialize this tag store.
- * @param _numSets The number of sets in the cache.
- * @param _blkSize The number of bytes in a block.
- * @param _assoc The associativity of the cache.
- * @param _hit_latency The latency in cycles for a hit.
*/
- LRU(unsigned _numSets, unsigned _blkSize, unsigned _assoc,
- unsigned _hit_latency);
+ LRU(const Params *p);
/**
* Destructor
/**
* Insert the new block into the cache. For LRU this means inserting into
* the MRU position of the set.
- * @param addr The address to update.
+ * @param pkt Packet holding the address to update
* @param blk The block to update.
*/
- void insertBlock(Addr addr, BlkType *blk, int context_src);
+ void insertBlock(PacketPtr pkt, BlkType *blk);
/**
* Generate the tag from the given address.