chunk_generator.hh revision 5731:453f320129a1
12686Sksewell@umich.edu/*
22100SN/A * Copyright (c) 2001-2005 The Regents of The University of Michigan
35254Sksewell@umich.edu * All rights reserved.
45254Sksewell@umich.edu *
55254Sksewell@umich.edu * Redistribution and use in source and binary forms, with or without
65254Sksewell@umich.edu * modification, are permitted provided that the following conditions are
75254Sksewell@umich.edu * met: redistributions of source code must retain the above copyright
85254Sksewell@umich.edu * notice, this list of conditions and the following disclaimer;
95254Sksewell@umich.edu * redistributions in binary form must reproduce the above copyright
105254Sksewell@umich.edu * notice, this list of conditions and the following disclaimer in the
115254Sksewell@umich.edu * documentation and/or other materials provided with the distribution;
125254Sksewell@umich.edu * neither the name of the copyright holders nor the names of its
135254Sksewell@umich.edu * contributors may be used to endorse or promote products derived from
145254Sksewell@umich.edu * this software without specific prior written permission.
155254Sksewell@umich.edu *
165254Sksewell@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
175254Sksewell@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
185254Sksewell@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
195254Sksewell@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
205254Sksewell@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
215254Sksewell@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
225254Sksewell@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
235254Sksewell@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
245254Sksewell@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
255254Sksewell@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
265254Sksewell@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
275254Sksewell@umich.edu *
285254Sksewell@umich.edu * Authors: Steve Reinhardt
295254Sksewell@umich.edu */
305254Sksewell@umich.edu
315254Sksewell@umich.edu#ifndef __BASE__CHUNK_GENERATOR_HH__
322706Sksewell@umich.edu#define __BASE__CHUNK_GENERATOR_HH__
332022SN/A
342022SN/A/**
352043SN/A * @file
362024SN/A * Declaration and inline definition of ChunkGenerator object.
372024SN/A */
382043SN/A
392686Sksewell@umich.edu#include <algorithm>
404661Sksewell@umich.edu#include "base/intmath.hh"
412022SN/A#include "arch/isa_traits.hh" // for Addr
422083SN/A
432686Sksewell@umich.edu/**
442101SN/A * This class takes an arbitrary memory region (address/length pair)
452043SN/A * and generates a series of appropriately (e.g. block- or page-)
462043SN/A * aligned chunks covering the same region.
472101SN/A *
482101SN/A * Example usage:
496384Sgblack@eecs.umich.edu
506384Sgblack@eecs.umich.edu\code
516384Sgblack@eecs.umich.edu    for (ChunkGenerator gen(addr, size, chunkSize); !gen.done(); gen.next()) {
526384Sgblack@eecs.umich.edu        doSomethingChunky(gen.addr(), gen.size());
536384Sgblack@eecs.umich.edu    }
546384Sgblack@eecs.umich.edu\endcode
552101SN/A */
562101SN/Aclass ChunkGenerator
572101SN/A{
582046SN/A  private:
592686Sksewell@umich.edu    /** The starting address of the current chunk. */
602686Sksewell@umich.edu    Addr curAddr;
612686Sksewell@umich.edu    /** The starting address of the next chunk (after the current one). */
622470SN/A    Addr nextAddr;
632686Sksewell@umich.edu    /** The size of the current chunk (in bytes). */
644661Sksewell@umich.edu    int  curSize;
655222Sksewell@umich.edu    /** The number of bytes remaining in the region after the current chunk. */
665222Sksewell@umich.edu    int  sizeLeft;
672686Sksewell@umich.edu    /** The start address so we can calculate offset in writing block. */
6813389Sgabeblack@google.com    const Addr startAddr;
692470SN/A    /** The maximum chunk size, e.g., the cache block size or page size. */
702241SN/A    const int chunkSize;
712101SN/A
722495SN/A  public:
732495SN/A    /**
7413389Sgabeblack@google.com     * Constructor.
752101SN/A     * @param _startAddr The starting address of the region.
766384Sgblack@eecs.umich.edu     * @param totalSize The total size of the region.
776384Sgblack@eecs.umich.edu     * @param _chunkSize The size/alignment of chunks into which
786384Sgblack@eecs.umich.edu     *    the region should be decomposed.
7913389Sgabeblack@google.com     */
806384Sgblack@eecs.umich.edu    ChunkGenerator(Addr _startAddr, int totalSize, int _chunkSize)
812495SN/A        : startAddr(_startAddr), chunkSize(_chunkSize)
822101SN/A    {
832101SN/A        // chunkSize must be a power of two
842495SN/A        assert(chunkSize == 0 || isPowerOf2(chunkSize));
852495SN/A        assert(totalSize >= 0);
862495SN/A
872495SN/A        // set up initial chunk.
882495SN/A        curAddr = startAddr;
892495SN/A
902495SN/A        if (chunkSize == 0) //Special Case, if we see 0, assume no chuncking
912495SN/A        {
922495SN/A            nextAddr = startAddr + totalSize;
932495SN/A        }
942495SN/A        else
952495SN/A        {
962495SN/A            // nextAddr should be *next* chunk start
972101SN/A            nextAddr = roundUp(startAddr, chunkSize);
9813389Sgabeblack@google.com            if (curAddr == nextAddr) {
992101SN/A                // ... even if startAddr is already chunk-aligned
1002101SN/A                nextAddr += chunkSize;
10113389Sgabeblack@google.com            }
1022101SN/A        }
1036384Sgblack@eecs.umich.edu
1046384Sgblack@eecs.umich.edu        // how many bytes are left between curAddr and the end of this chunk?
1056384Sgblack@eecs.umich.edu        int left_in_chunk = nextAddr - curAddr;
10613389Sgabeblack@google.com        curSize = std::min(totalSize, left_in_chunk);
1076384Sgblack@eecs.umich.edu        sizeLeft = totalSize - curSize;
1082101SN/A    }
1092101SN/A
1102495SN/A    /** Return starting address of current chunk. */
1112495SN/A    Addr addr() { return curAddr; }
1122495SN/A    /** Return size in bytes of current chunk. */
1132495SN/A    int  size() { return curSize; }
1142495SN/A
1156384Sgblack@eecs.umich.edu    /** Number of bytes we have already chunked up. */
1166384Sgblack@eecs.umich.edu    int complete() { return curAddr - startAddr; }
1176384Sgblack@eecs.umich.edu    /**
1186384Sgblack@eecs.umich.edu     * Are we done?  That is, did the last call to next() advance
1196384Sgblack@eecs.umich.edu     * past the end of the region?
1202495SN/A     * @return True if yes, false if more to go.
1216384Sgblack@eecs.umich.edu     */
1222495SN/A    bool done() { return (curSize == 0); }
1232495SN/A
1242043SN/A    /**
1252043SN/A     * Advance generator to next chunk.
1262025SN/A     * @return True if successful, false if unsuccessful
1272043SN/A     * (because we were at the last chunk).
1282686Sksewell@umich.edu     */
1292686Sksewell@umich.edu    bool next()
1302123SN/A    {
1312101SN/A        if (sizeLeft == 0) {
1326376Sgblack@eecs.umich.edu            curSize = 0;
1336376Sgblack@eecs.umich.edu            return false;
1346376Sgblack@eecs.umich.edu        }
1357792Sgblack@eecs.umich.edu
1366376Sgblack@eecs.umich.edu        curAddr = nextAddr;
1376376Sgblack@eecs.umich.edu        curSize = std::min(sizeLeft, chunkSize);
1386376Sgblack@eecs.umich.edu        sizeLeft -= curSize;
1396376Sgblack@eecs.umich.edu        nextAddr += curSize;
1406376Sgblack@eecs.umich.edu        return true;
1416376Sgblack@eecs.umich.edu    }
1426376Sgblack@eecs.umich.edu};
1437792Sgblack@eecs.umich.edu
1446376Sgblack@eecs.umich.edu#endif // __BASE__CHUNK_GENERATOR_HH__
1456376Sgblack@eecs.umich.edu