replacement_h_TITLE
#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