------------------------------------------------------------------------------
MC logo
replacement_cpp_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.cpp
#include <errno.h>
#include <string.h>
#include <stdlib.h>

#include <string>
#include <iostream>
#include <fstream>
#include <iomanip>
#include <sstream>
#include <stdexcept>
#include <utility>
#include "replacement.h"

using std::string;

void Ref::print(ostream &strm) const
{
        // Print strings for the reference types.
        static const char *tmap[] = { "null", "ifet", "stor", "fetc", "upda" };

        strm << tmap[type] 
             << " @ 0x" << std::setw(8) << std::setfill('0') << std::hex 
             << addr << std::dec << "+" << size;
}

void ReplacementAlg::init_memory()
{
        m_memory = new page_table_t::iterator[m_num_frame];
        for(int i = 0; i < m_num_frame; ++i)
                m_memory[i] = m_page_table.end();
}

int ReplacementAlg::read(string filename)
{
        // Set up the reading stream, either an open file or cin.
        std::ifstream fin;              // Open if filename is not -
        std::istream *inpoint;          // Point to input stream in use.
        if(filename == "-") 
                inpoint = &std::cin;
        else {
                fin.open(filename.c_str());
                if(!fin) 
                        throw std::runtime_error
                                ("Open " + filename + " failed: " + 
                                 strerror(errno));
                inpoint = &fin;
        }

        // Read all the lines, and interpret any which will as references.
        int count = 0;
        string line;
        while(std::getline(*inpoint, line)) {
                Ref r; // Fill this in.

                // Read the fields from the line.  If the format doesn't
                // match, discard the line.
                if(sscanf(line.c_str()+2, "%x,%ld", &r.addr, &r.size) != 2)
                        continue;

                // Set the line type, and discard the line if the type
                // mark is not recognized.
                if(line[0] == 'I') {
                        r.type = Ref::instr_fetch;
                } else if(line[1] == 'S') {
                        r.type = Ref::store;
                } else if(line[1] == 'L') {
                        r.type = Ref::fetch;
                } else if(line[1] == 'M') {
                        r.type = Ref::update;
                } else 
                        continue;

                // Process the item.
                ++count;
                ref(r);
        }

        return count;
}

// Simulate the occurance of a memory reference.
void ReplacementAlg::ref(const Ref &r)
{
        // Handle the reference count and maintenance call.
        if(m_maint_freq && ++m_maint_count >= m_maint_freq) {
                maint();
                m_maint_count = 0;
        }

        // Analyze the reference.
        unsigned pno = pageno(r);
        int np = npage(r);
        for(; np--; ++pno) {
                ++m_refcount;

                // Check the frame.
                page_table_t::iterator i = m_page_table.find(pno);
                if(i == m_page_table.end() || !i->second.is_valid()) {
                        // Page fault.
                        ++m_faultct;

                        // Get the frame to use.
                        unsigned long target = fault(r);
                        if(target >= m_num_frame) {
                                std::ostringstream msg;
                                msg << "fault() returned out-of-bounds frame "
                                    << target << " for fault on " << r;
                                throw std::runtime_error(msg.str());
                        }

                        // Remove the existing page if present.
                        page_table_t::iterator oldPTE = m_memory[target];
                        if(oldPTE != m_page_table.end() && 
                           oldPTE->second.is_valid()) {
                                // Remove current occupant.
                                ++m_removect;
                                if(oldPTE->second.get_mod()) ++m_rewrite;
                                m_page_table.erase(oldPTE);
                        }

                        // Insert the the pte for the faulting page.
                        if(i == m_page_table.end())
                                i = m_page_table.insert
                                        (std::make_pair(pno, PTE(target))).first;
                        else
                                i->second.validate(target);

                        // Adjust the frame.
                        m_memory[target] = i;

                        // Retry the reference.
                } 

                // Update PTE flags.
                i->second.set_ref();
                if(r.is_write()) i->second.set_mod();
        }
}

// Look up a PTE by page number
const PTE *ReplacementAlg::get_PTE_by_page(unsigned long page)
{
        static PTE invalid;

        page_table_t::iterator loc = m_page_table.find(page);
        if(loc == m_page_table.end()) return &invalid;
        return &loc->second;
}

// Look up a PTE by frame number
PTE *ReplacementAlg::get_PTE_by_frame(unsigned long frame)
{
        if(frame >= m_num_frame) {
                std::ostringstream msg;
                msg << "get_PTE_by_frame() sent frame number "
                    << frame << " out of range";
                throw std::runtime_error(msg.str());
        }
        page_table_t::iterator loc = m_memory[frame];
        if(loc == m_page_table.end()) return NULL;
        return &loc->second;
}

void ReplacementAlg::print_stats(std::ostream &strm)
{
        strm << "Algorithm: " << name();
        if(m_maint_freq) strm << ", maint freq " << m_maint_freq;
        strm << std::endl;
        strm << "Memory: " << m_num_frame << " frames of " 
             << (1 << m_page_bits) << " bytes each for " 
             << (1 << m_page_bits)*m_num_frame << " total." << std::endl;
        strm << "Performance: " << get_refcount() << " references produced " 
             << get_faultcount() << " faults, rate: " << get_faultrate() 
             << std::endl;
}