chunk_generator.hh revision 2565
11897Sstever@eecs.umich.edu/*
23077Sstever@eecs.umich.edu * Copyright (c) 2001-2005 The Regents of The University of Michigan
31897Sstever@eecs.umich.edu * All rights reserved.
41897Sstever@eecs.umich.edu *
51897Sstever@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
61897Sstever@eecs.umich.edu * modification, are permitted provided that the following conditions are
71897Sstever@eecs.umich.edu * met: redistributions of source code must retain the above copyright
81897Sstever@eecs.umich.edu * notice, this list of conditions and the following disclaimer;
91897Sstever@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
101897Sstever@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the
111897Sstever@eecs.umich.edu * documentation and/or other materials provided with the distribution;
121897Sstever@eecs.umich.edu * neither the name of the copyright holders nor the names of its
131897Sstever@eecs.umich.edu * contributors may be used to endorse or promote products derived from
141897Sstever@eecs.umich.edu * this software without specific prior written permission.
151897Sstever@eecs.umich.edu *
161897Sstever@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
171897Sstever@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
181897Sstever@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
191897Sstever@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
201897Sstever@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
211897Sstever@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
221897Sstever@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
231897Sstever@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
241897Sstever@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
251897Sstever@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
261897Sstever@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
271897Sstever@eecs.umich.edu */
281897Sstever@eecs.umich.edu
291897Sstever@eecs.umich.edu#ifndef __BASE__CHUNK_GENERATOR_HH__
301897Sstever@eecs.umich.edu#define __BASE__CHUNK_GENERATOR_HH__
311897Sstever@eecs.umich.edu
321897Sstever@eecs.umich.edu/**
331897Sstever@eecs.umich.edu * @file
341897Sstever@eecs.umich.edu * Declaration and inline definition of ChunkGenerator object.
351897Sstever@eecs.umich.edu */
361897Sstever@eecs.umich.edu
371897Sstever@eecs.umich.edu#include <algorithm>
381897Sstever@eecs.umich.edu#include "base/intmath.hh"
391897Sstever@eecs.umich.edu#include "arch/isa_traits.hh" // for Addr
401897Sstever@eecs.umich.edu
411897Sstever@eecs.umich.edu/**
423077Sstever@eecs.umich.edu * This class takes an arbitrary memory region (address/length pair)
433099Sstever@eecs.umich.edu * and generates a series of appropriately (e.g. block- or page-)
443099Sstever@eecs.umich.edu * aligned chunks covering the same region.
451897Sstever@eecs.umich.edu *
463709Sstever@eecs.umich.edu * Example usage:
473099Sstever@eecs.umich.edu
483099Sstever@eecs.umich.edu\code
491897Sstever@eecs.umich.edu    for (ChunkGenerator gen(addr, size, chunkSize); !gen.done(); gen.next()) {
503099Sstever@eecs.umich.edu        doSomethingChunky(gen.addr(), gen.size());
511897Sstever@eecs.umich.edu    }
521897Sstever@eecs.umich.edu\endcode
531897Sstever@eecs.umich.edu */
541897Sstever@eecs.umich.educlass ChunkGenerator
551897Sstever@eecs.umich.edu{
561897Sstever@eecs.umich.edu  private:
571897Sstever@eecs.umich.edu    /** The starting address of the current chunk. */
581897Sstever@eecs.umich.edu    Addr curAddr;
591897Sstever@eecs.umich.edu    /** The starting address of the next chunk (after the current one). */
601897Sstever@eecs.umich.edu    Addr nextAddr;
611897Sstever@eecs.umich.edu    /** The size of the current chunk (in bytes). */
621897Sstever@eecs.umich.edu    int  curSize;
631897Sstever@eecs.umich.edu    /** The number of bytes remaining in the region after the current chunk. */
641897Sstever@eecs.umich.edu    int  sizeLeft;
651897Sstever@eecs.umich.edu    /** The start address so we can calculate offset in writing block. */
661897Sstever@eecs.umich.edu    const Addr startAddr;
671897Sstever@eecs.umich.edu    /** The maximum chunk size, e.g., the cache block size or page size. */
681897Sstever@eecs.umich.edu    const int chunkSize;
691897Sstever@eecs.umich.edu
701897Sstever@eecs.umich.edu  public:
711897Sstever@eecs.umich.edu    /**
721897Sstever@eecs.umich.edu     * Constructor.
731897Sstever@eecs.umich.edu     * @param startAddr The starting address of the region.
741897Sstever@eecs.umich.edu     * @param totalSize The total size of the region.
751897Sstever@eecs.umich.edu     * @param _chunkSize The size/alignment of chunks into which
761897Sstever@eecs.umich.edu     *    the region should be decomposed.
771897Sstever@eecs.umich.edu     */
781897Sstever@eecs.umich.edu    ChunkGenerator(Addr _startAddr, int totalSize, int _chunkSize)
791897Sstever@eecs.umich.edu        : startAddr(_startAddr), chunkSize(_chunkSize)
801897Sstever@eecs.umich.edu    {
813077Sstever@eecs.umich.edu        // chunkSize must be a power of two
823077Sstever@eecs.umich.edu        assert(chunkSize == 0 || isPowerOf2(chunkSize));
833077Sstever@eecs.umich.edu
843077Sstever@eecs.umich.edu        // set up initial chunk.
853077Sstever@eecs.umich.edu        curAddr = startAddr;
863077Sstever@eecs.umich.edu
873077Sstever@eecs.umich.edu        if (chunkSize == 0) //Special Case, if we see 0, assume no chuncking
883077Sstever@eecs.umich.edu        {
893077Sstever@eecs.umich.edu            nextAddr = startAddr + totalSize;
901897Sstever@eecs.umich.edu        }
911897Sstever@eecs.umich.edu        else
921897Sstever@eecs.umich.edu        {
931897Sstever@eecs.umich.edu            // nextAddr should be *next* chunk start
941897Sstever@eecs.umich.edu            nextAddr = roundUp(startAddr, chunkSize);
951897Sstever@eecs.umich.edu            if (curAddr == nextAddr) {
961897Sstever@eecs.umich.edu                // ... even if startAddr is already chunk-aligned
971897Sstever@eecs.umich.edu                nextAddr += chunkSize;
98            }
99        }
100
101        // how many bytes are left between curAddr and the end of this chunk?
102        int left_in_chunk = nextAddr - curAddr;
103        curSize = std::min(totalSize, left_in_chunk);
104        sizeLeft = totalSize - curSize;
105    }
106
107    /** Return starting address of current chunk. */
108    Addr addr() { return curAddr; }
109    /** Return size in bytes of current chunk. */
110    int  size() { return curSize; }
111
112    /** Number of bytes we have already chunked up. */
113    int complete() { return curAddr - startAddr; }
114    /**
115     * Are we done?  That is, did the last call to next() advance
116     * past the end of the region?
117     * @return True if yes, false if more to go.
118     */
119    bool done() { return (curSize == 0); }
120
121    /**
122     * Advance generator to next chunk.
123     * @return True if successful, false if unsuccessful
124     * (because we were at the last chunk).
125     */
126    bool next()
127    {
128        if (sizeLeft == 0) {
129            curSize = 0;
130            return false;
131        }
132
133        curAddr = nextAddr;
134        curSize = std::min(sizeLeft, chunkSize);
135        sizeLeft -= curSize;
136        nextAddr += curSize;
137        return true;
138    }
139};
140
141#endif // __BASE__CHUNK_GENERATOR_HH__
142