------------------------------------------------------------------------------
MC logo
replacement_h_TITLE
[^] CSc 422 Assignment 4
------------------------------------------------------------------------------
[CSc 422 Assignment 1] [CSc 422 Assignment 2] [CSc 422 Assignment 3] [CSc 422 Assignment 4]
[Replacement Main] [replacement_h] [replacement_cpp] [FIFO Class] [LRU Class] [LRU Implementation] [NRU Class] [NRU Implementation] [Reader Test Class]
replacement.h
#include <string>
#include <iostream>
#include <map>

using std::string;
using std::ostream;
using std::map;

#ifndef _replacement_h_
#define _replacement_h_

/*
 * Objects of class Ref represent a reference.  Each reference has a type,
 * an address, and a size in bytes.  It represents a block of memory of
 * the indicated size starting at the address.  Types are described shortly.
 */
class Ref {
public:
        // This gives the types.  Besides a null type, references are
        // classified as instruction fetch, data store, data fetch, and
        // data update, which is a fetch then a store in the same instruction.
        enum ref_type_t { null, instr_fetch, store, fetch, update };

        // Each reference has a type, an address, and a size (number of bytes
        // read or written).
        ref_type_t type;
        unsigned long addr;
        unsigned short size;

        // Construct an object giving the fields.
        Ref(): type(null), addr(0), size(0) { }
        Ref(ref_type_t _type, unsigned long _addr, unsigned short _size):
                type(_type), addr(_addr), size(_size) { }

        // Does this type modify memory?
        bool is_write() const { return type == store || type == update; }

        // Printing a reference.
        void print(ostream &strm) const;
};

// Use << to run Ref::print.
inline ostream &operator<<(ostream &strm, const Ref &r)
{
        r.print(strm);
        return strm;
}

/*
 * This represents a page table entry.  
 */
class PTE {
public:
        PTE(): m_valid(false), m_ref(false), m_mod(false), m_frameno(0)
        {
        }
        PTE(unsigned long frame): m_valid(true), m_ref(false), m_mod(false), 
                                  m_frameno(frame)
        {
        }
        bool is_valid() const { return m_valid; }
        bool get_ref() const { return m_ref; }
        bool get_mod() const { return m_mod; }
        unsigned long get_frame() const { return m_frameno; }

        void set_ref() { m_ref = true; }
        void set_mod() { m_ref = m_mod = true; }

        void clr_ref() { m_ref = false; }
        void clr_mod() { m_mod = false; }

        // The page for this entry has just be brought into
        // the indicated frame.  
        void validate(unsigned long frameno) {
                m_valid = true;
                m_ref = m_mod = false;
                m_frameno = frameno;
        }

        // Invalidate the entry.  Returns the old modified value.
        // Simulates removal of the page.
        bool invalidate() {
                bool ret = m_mod;
                m_valid = m_ref = m_mod = false;
                m_frameno = 0;
        }
private:
        bool m_valid;           // Entry is valid.
        bool m_ref;             // Reference bit.
        bool m_mod;             // Entry is modified.
        unsigned long m_frameno;// If valid, the frame for this page.
};

/*
 * Replacement algorithm simulation abstract base class.
 */
class ReplacementAlg
{
public:
        ReplacementAlg(unsigned long num_frame, int page_bits, 
                       int maint_freq = 0):
                m_num_frame(num_frame), m_page_bits(page_bits),
                m_maint_freq(maint_freq), m_maint_count(0), m_refcount(0),
                m_faultct(0), m_removect(0), m_rewrite(0) { init_memory(); }

        ~ReplacementAlg() { delete [] m_memory; }

        /* Simple extractors. */
        unsigned long get_num_frames() { return m_num_frame; }
        int get_page_bits() { return m_page_bits; }
        int get_maint_freq() { return m_maint_freq; }

        /* Utilities for reading and handling reference traces. */

        // Read the indicated file and process its references.  The file
        // format is the one generated by Valgrind with Lackey.  Lines
        // which don't look like references are silently ignored.  Throws a
        // std::runtime_error if the file cannot be opened.  Returns the
        // number of references successfully read and processed.
        int read(string filename);

        // Simulate the response to a reference.  Updates flags in the
        // page table as needed.  If there is a fault, calls fault() to 
        // choose a replacement, and handles the fault.  If you replace
        // it, your replacement should generally call this along the way.
        virtual void ref(const Ref &r);

        // Extract the page number from a reference.
        unsigned long pageno(const Ref &r) const 
        {
                return r.addr >> m_page_bits;
        }

        // Tell the number of pages touched by the reference.  Some references
        // cross page boundaries, so may effect two or (theoretically) more
        // pages.  Npage() usually returns one, but a reference where addr is
        // within size of the end of the page will return two.
        int npage(const Ref &r) const 
        {
                return (r.addr+r.size-1 >> m_page_bits) - pageno(r) + 1;
        }

        /* Page table utilities. */

        // Get the PTE for the indicated page number.  The caller is not
        // to change this PTE.  The result is not NULL, but the entry may
        // be invalid.
        const PTE *get_PTE_by_page(unsigned long page);  

        // Get the page table entry for a PTE which refers to this physical
        // page.  The caller is allowed to change this PTE.  If no PTE
        // is using this frame, return NULL.
        PTE *get_PTE_by_frame(unsigned long frame);

        /* NOTE: The base class is mainly responsible for maintaining the
         * page table.  The get_PTE_by_frame() method allows changes mainly
         * for implementing replacement algorithms (many of them) which need
         * to clear the referenced flag.  get_PTE_by_page does not allow
         * changes for reasons of its own efficiency.  The return value from
         * fault directs this class to update the table.  */

        /* Frame number utility. */

        // Modular rpno++ for real page numbers.  Assumes rpno is in range
        // initially, and increments it wrapping at the number of pages.
        // Returns the original rpno.
        unsigned long increal(unsigned long &rpno) {
                unsigned int ret = rpno++;
                if(rpno >= get_num_frames()) rpno = 0;
                return ret;
        }

        /* Performance stats. */
        void reset_stats()
        {
                m_refcount = 0;
                m_faultct = 0;
                m_removect = 0;
                m_rewrite = 0;
        }

        int get_refcount() { return m_refcount; }
        int get_faultcount() { return m_faultct; }
        double get_faultrate() { 
                return m_refcount ? (double)m_faultct/(double)m_refcount : 0.0;
        }

        int get_removect() { return m_removect; }
        int get_rewritecount() { return m_rewrite; }

        /* Abstract operations to be implemented by the derived class. */

        // The name of this algorithm.
        virtual string name() = 0;

        // Handle a page fault.  Receives a reference and must return the
        // chosen page frame number
        virtual unsigned long fault(const Ref &r) = 0;

        // If the replacement algorithm needs some periodic maintenance
        // operation, which occurs every n references, set the main_freq
        // constructor parameter, and replace this method.  If not
        // implemented, the do-nothing here will be run.
        virtual void maint() { }

        // Print a summary statistics report.
        virtual void print_stats(std::ostream &strm);
private:
        unsigned long m_num_frame; // Number of frames
        int m_page_bits;        // Page size bits (page size is 2^m_page_bits)
        int m_maint_freq;       // How often to run the main() function.
        int m_maint_count;      // Ref counter to implement m_maint_freq.

        // Performance stats.
        int m_refcount;         // Number of references (cross page count more).
        int m_faultct;          // Count of faults.
        int m_removect;         // Number of pages removed.
        int m_rewrite;          // Number of modified pages removed.

        // The page table.  Maps from virtual page number to PTE, if any.
        // Missing items are invalid.
        typedef map<unsigned long, PTE> page_table_t;
        page_table_t m_page_table;

        // This array is indexed by frame number (real page number) and
        // gives the location in the page table using it, if any.
        page_table_t::iterator *m_memory;

        // This method is called by the constructors to set up m_memory.
        void init_memory();
};

#endif