00001 // Torc - Copyright 2011 University of Southern California. All Rights Reserved. 00002 // $HeadURL: https://torc-isi.svn.sourceforge.net/svnroot/torc-isi/branches/staging/0.9/src/torc/architecture/WireUsage.hpp $ 00003 // $Id: WireUsage.hpp 10 2011-10-12 18:40:16Z nsteiner $ 00004 00005 // This program is free software: you can redistribute it and/or modify it under the terms of the 00006 // GNU General Public License as published by the Free Software Foundation, either version 3 of the 00007 // License, or (at your option) any later version. 00008 // 00009 // This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 00010 // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 00011 // the GNU General Public License for more details. 00012 // 00013 // You should have received a copy of the GNU General Public License along with this program. If 00014 // not, see <http://www.gnu.org/licenses/>. 00015 00016 /// \file 00017 /// \brief Header for the WireUsage class. 00018 00019 #ifndef TORC_ARCHITECTURE_WIREUSAGE_HPP 00020 #define TORC_ARCHITECTURE_WIREUSAGE_HPP 00021 00022 #include "torc/architecture/Array.hpp" 00023 #include "torc/architecture/Tiles.hpp" 00024 #include "torc/architecture/Tilewire.hpp" 00025 #include <boost/dynamic_bitset.hpp> 00026 00027 namespace torc { 00028 namespace architecture { 00029 00030 /// \brief Encapsulation the design wire usage. 00031 /// \details This class uses a compact bitset representation to very efficiently track the wire 00032 /// usage of a design in an entire device. Internal bitset objects are maintained on a 00033 /// per-tile basis, and are not allocated until at least one wire in the tile has been 00034 /// marked used. 00035 class WireUsage { 00036 protected: 00037 // types 00038 typedef boost::dynamic_bitset<> dynamic_bitset; ///< \brief Imported type name. 00039 typedef xilinx::TileIndex TileIndex; ///< \brief Imported type name. 00040 typedef xilinx::TileCount TileCount; ///< \brief Imported type name. 00041 typedef xilinx::TileTypeIndex TileTypeIndex; ///< \brief Imported type name. 00042 typedef xilinx::WireIndex WireIndex; ///< \brief Imported type name. 00043 // members 00044 /// \brief Reference to the database Tiles object. 00045 const Tiles& mTiles; 00046 /// \brief The number of tiles for which bitsets are allocated. 00047 TileCount mTileUsageCount; 00048 /// \brief The wire usage bitset array. 00049 Array<dynamic_bitset*> mBitsets; 00050 /// \brief The number of bits allocated by the usage bitsets. 00051 uint32_t mBitCount; 00052 /// \brief The mask of tile bitsets that contain changes. 00053 dynamic_bitset mTileDirty; 00054 public: 00055 // constructors 00056 /// \brief Public constructor. 00057 WireUsage(const Tiles& inTiles) : mTiles(inTiles), mTileUsageCount(), mBitsets(0), 00058 mBitCount(0), mTileDirty(0) {} 00059 /// \brief Non-virtual destructor. 00060 ~WireUsage(void) { 00061 size_t tileCount = mBitsets.getSize(); 00062 for(TileIndex i; i < tileCount; i++) { 00063 if(mBitsets[i] != 0) { delete mBitsets[i]; mBitsets[i] = 0; } 00064 } 00065 } 00066 // functions 00067 /// \brief Size the wire usage according to the number of device tiles. 00068 void autosize(void) { 00069 // release any existing bitsets 00070 for(TileCount i; i < mBitsets.getSize(); i++) { 00071 if(mBitsets[i] != 0) { delete mBitsets[i]; mBitsets[i] = 0; } 00072 mTileDirty.reset(i); 00073 } 00074 // resize for the new dimensions 00075 TileCount tileCount = mTiles.getTileCount(); 00076 mBitsets.setSize(tileCount); 00077 for(TileCount i; i < tileCount; i++) mBitsets[i] = 0; 00078 mTileDirty.resize(tileCount); 00079 } 00080 /// \brief Marks the specified tilewire as being used. 00081 void use(const Tilewire& inTilewire) { 00082 // extract the tile and wire indexes 00083 TileIndex tileIndex = inTilewire.getTileIndex(); 00084 WireIndex wireIndex = inTilewire.getWireIndex(); 00085 00086 // look up the appropriate bitset, allocating it if necessary 00087 dynamic_bitset* bitset = mBitsets[tileIndex]; 00088 if(bitset == 0) { 00089 // determine how many wires are in this tile 00090 const TileInfo& tileInfo = mTiles.getTileInfo(tileIndex); 00091 TileTypeIndex tileTypeIndex = tileInfo.getTypeIndex(); 00092 size_t size = mTiles.getWireInfo(tileTypeIndex).getSize(); 00093 bitset = mBitsets[tileIndex] = new dynamic_bitset(size); 00094 // track the statistics 00095 mTileUsageCount++; 00096 mBitCount += size; 00097 } 00098 00099 // set the bit and mark the tile dirty 00100 bitset->set(wireIndex, true); 00101 mTileDirty.set(tileIndex, true); 00102 } 00103 /// \brief Marks the specified tilewire as being unused. 00104 void release(const Tilewire& inTilewire) { 00105 // extract the tile and wire indexes 00106 TileIndex tileIndex = inTilewire.getTileIndex(); 00107 WireIndex wireIndex = inTilewire.getWireIndex(); 00108 00109 // if there is no entry for the tile, the tilewire is already implicitly unused. 00110 dynamic_bitset* bitset = mBitsets[tileIndex]; 00111 if(bitset == 0) return; 00112 00113 // otherwise clear the bit and mark the tile dirty 00114 bitset->set(wireIndex, false); 00115 mTileDirty.set(tileIndex, true); 00116 } 00117 /// \brief Marks all wires as being unused, without releasing the bitset objects. 00118 /// \details This capability allows the tracer to track the wires that it has visited while 00119 /// processing a particular net, and then to start again from scratch without incurring 00120 /// allocation and construction overheads. 00121 void clear(void) { 00122 // iterate over all of the tiles 00123 size_t tileCount = mBitsets.getSize(); 00124 for(TileIndex i; i < tileCount; i++) { 00125 // skip this tile if it isn't dirty 00126 if(!mTileDirty[i]) continue; 00127 // mark the tile clean 00128 mTileDirty.reset(i); 00129 // look up the bitset for this tile 00130 dynamic_bitset* bitset = mBitsets[i]; 00131 // skip tiles without an associated bitset (should never happen for dirty tiles) 00132 if(bitset == 0) continue; 00133 // clear the entire bitset 00134 bitset->reset(); 00135 } 00136 } 00137 /// \brief Determines whether the specified tilewire is in use. 00138 bool isUsed(const Tilewire& inTilewire) { 00139 // extract the tile and wire indexes 00140 TileIndex tileIndex = inTilewire.getTileIndex(); 00141 WireIndex wireIndex = inTilewire.getWireIndex(); 00142 00143 // if there is no entry for the tile, the tilewire is already implicitly unused. 00144 dynamic_bitset* bitset = mBitsets[tileIndex]; 00145 if(bitset == 0) return false; 00146 00147 // otherwise, interrogate the bit 00148 return bitset->test(wireIndex); 00149 } 00150 /// \brief Returns the number of wires in use. 00151 uint32_t getWireUsageCount(void) const { 00152 uint32_t usageCount = 0; 00153 size_t tileCount = mBitsets.getSize(); 00154 for(TileIndex i; i < tileCount; i++) { 00155 /// \todo Question: can we get away with only checking dirty bitsets? 00156 //// skip this tile if it isn't dirty 00157 //if(!mTileDirty[i]) continue; 00158 // look up the bitset for this tile 00159 dynamic_bitset* bitset = mBitsets[i]; 00160 // skip tiles without an associated bitset 00161 if(bitset == 0) continue; 00162 // clear the entire bitset 00163 usageCount += bitset->count(); 00164 } 00165 return usageCount; 00166 } 00167 // accessors 00168 /// \brief Returns the number of tiles that have been touched. 00169 TileCount getTileUsageCount(void) const { return mTileUsageCount; } 00170 /// \brief Returns the number of bits allocated. 00171 uint32_t getBitCount(void) const { return mBitCount; } 00172 }; 00173 00174 } // namespace architecture 00175 } // namespace torc 00176 00177 #endif // TORC_ARCHITECTURE_WIREUSAGE_HPP