Discrete Event Simulation Algorithm debug - c++

I am working on a discrete event simulation program in C++. My output is completely incorrect but all the output values are pretty close to the correct output. I have tried debugging my algorithm but I couldn't find any errors. Below is my main algorithm for the simulation.
I implemented the event priority queue using a min heap and array. I am not allowed to use any STL libraries. The FIFO queue used in the code is a linked list. When I print the event time at the top of the priority queue, the events are not always getting passed in ascending order (which I think is how event priority queues are supposed to work) and I do not understand why. The ascending order is breached mostly around event completion times. Please help!
#include <iostream>
#include <fstream>
#include "PQueue.h"
#include "SPqueue.h"
#include "LinkedList.h"
using namespace std;
int serverCount; //number of servers
Spqueue spq; //priority queue for servers
Pqueue pq; //priority queue for events
LinkedList list; //FIFO queue to put arriving events in
double totalTime; //variables for statistics calculation
double timeNow;
double totalWait;
int ql;
int qlength = 0;
double totalQlength;
int time = 0;
bool available(); //checks availability of servers
int main() {
ifstream fin;
fin.open("Sample2.txt");
if (!fin.good())
cerr << "Couldn't find file/corrupted file" << endl;
fin >> serverCount; //reads number of servers and efficiency
//from file
for (int i = 0; i < serverCount; i++) {
server s;
fin >> s.effi;
s.status = true;
s.count = 0;
spq.insert(s);
}
//reads first event from file
event e;
fin >> e.eventTime;
fin >> e.serviceTime;
e.eventType = -1;
pq.insert(e);
int i = 1;
//while priority queue is not empty
while (!pq.isEmpty()) {
timeNow = pq.getArrivalTime(1);
while (time < pq.getArrivalTime(1)) {
totalQlength = totalQlength + list.getLength();
time++;
}
//get event from priority queue
if (pq.getServer(1) == -1) { //if arrival event, add to FIFO queue
list.AddTail(pq.getArrivalTime(1), pq.getServiceTime());
if (list.getLength() > qlength) {
qlength = list.getLength();
}
//read next arrival event from file
if (!fin.eof()) {
event e;
fin >> e.eventTime;
fin >> e.serviceTime;
e.eventType = -1;
pq.insert(e);
i++;
}
}
else //must be customer complete event
{
spq.setIdle(pq.getServer(1)); //set the server to idle
}
pq.deleteMin(); //remove the evnt from priority queue
//if FIFO queue is not empty and servers are available
//process event
if ((list.isEmpty() == false) && (available() == true)) {
list.getHead();
int s = spq.getMin();
spq.setBusy(s); //set server to busy
spq.incrementCustNumber(s); //increment number of customers
//served
double waitTime = timeNow - list.getHead().arrivalTime;
totalWait = totalWait + waitTime;
double serviceT = spq.getEffi(s) * list.getHead().serviceTime;
double eventT = list.getHead().arrivalTime +serviceT;
event e2;
e2.eventTime = eventT;
e2.serviceTime = list.getHead().serviceTime;
e2.eventType = s;
pq.insert(e2); //add customer complete event to the priority
//queue
list.RemoveHead(); //remove head from FIFO
}
totalTime = pq.getArrivalTime(1);
}
fin.close();
return 0;
}
bool available() {
bool ava = false;
for (int i = 1; i <= serverCount; i++) {
if (spq.getStatus(i) == true) {
ava = true;
break;
}
}
return ava;
}
Below is the priority queue implementation:
#include <iostream>
#include <fstream>
#include "PQueue.h"
using namespace std;
Pqueue::Pqueue() {
inde = 0; //length of heap
}
void Pqueue::insert(event i) { //inserts new element into the heap array and maintains min heap property
inde++;
pqueue[inde] = i;
siftup(inde);
}
int Pqueue::getServer(int i) {
return pqueue[i].eventType;
}
void Pqueue::siftup(int i) { //shifts element up to the correct position in the heap
if (i == 1)
return;
int p = i / 2;
if (pqueue[p].eventTime > pqueue[i].eventTime)
{
swap(pqueue[i], pqueue[p]);
siftup(p);
}
}
void Pqueue::deleteMin() { //removes element at the root of the heap
swap(pqueue[inde], pqueue[1]);
inde--;
siftdown(1);
}
void Pqueue::siftdown(int i) { //shifts element to its position in the min heap
int c = i * 2;
int c2 = (i * 2) + 1;
if (c > inde) return;
int in = i;
if (pqueue[i].eventTime > pqueue[c].eventTime)
{
in = c;
}
if ((c2 < inde) && (pqueue[i].eventTime > pqueue[c2].eventTime))
{
in = c2;
}
if (pqueue[c].eventTime < pqueue[c2].eventTime) {
in = c;
}
if (in != i) {
swap(pqueue[i], pqueue[in]);
siftdown(in);
}
}
void Pqueue::swap(event& i, event& j) {
event temp;
temp = i;
i = j;
j = temp;
}
bool Pqueue::isEmpty() { //checks if the priority queue is empty
if (inde == 0) return true;
else
return false;
}
double Pqueue::getArrivalTime(int i) {
return pqueue[i].eventTime;
}
double Pqueue::getServiceTime() {
return pqueue[1].serviceTime;
}
There are five servers with varying efficiency. The most efficient idle server is to be used. For this, I sorted the array of servers efficiency wise in the beginning.
#include <iostream>
#include <fstream>
#include "SPqueue.h"
using namespace std;
Spqueue::Spqueue() {
inde = 0;
}
void Spqueue::insert(server i) { //inserts new element into the array
inde++;
spqueue[inde] = i;
}
void Spqueue::heapify(int n, int i)
{
int largest = i; // Initialize largest as root
int l = 2 * i; // left = 2*i + 1
int r = 2 * i +1; // right = 2*i + 2
// If left child is larger than root
if (l < n && spqueue[l].effi > spqueue[largest].effi)
largest = l;
// If right child is larger than largest so far
if (r < n && spqueue[r].effi > spqueue[largest].effi)
largest = r;
// If largest is not root
if (largest != i)
{
swap(spqueue[i], spqueue[largest]);
// Recursively heapify the affected sub-tree
heapify(n, largest);
}
}
void Spqueue::heapSort()
{
// Build heap (rearrange array)
for (int i = inde / 2 - 1; i > 0; i--)
heapify(inde, i);
// One by one extract an element from heap
for (int i = inde - 1; i > 0; i--)
{
// Move current root to end
swap(spqueue[1], spqueue[i]);
// call max heapify on the reduced heap
heapify(i, 1);
}
}
void Spqueue::swap(server& i, server& j) {
server temp;
temp = i;
i = j;
j = temp;
}
int Spqueue::getMin() { //iterates to the next available server in the sorted list of servers
int i = 0;
while (i <=20){
if (spqueue[i].status == true)
{
return i;
}
else
{
i++;
}
}
}
bool Spqueue::getStatus(int i) {
return spqueue[i].status;
}
void Spqueue::setBusy(int i) {
spqueue[i].status = false;
}
void Spqueue::addServiceTime(int i,double s) {
spqueue[i].busyTime = spqueue[i].busyTime + s;
}
double Spqueue::getTotalServiceTime(int i) {
return spqueue[i].busyTime;
}
void Spqueue::setIdle(int i) {
spqueue[i].status = true;
}
double Spqueue::getEffi(int i) {
return spqueue[i].effi;
}
void Spqueue::incrementCustNumber(int i) {
spqueue[i].count++;
}
int Spqueue::getCount(int i) {
return spqueue[i].count;
}
And the following function is supposed to return the most efficient server.
int Spqueue::getMin() { //iterates to the next available server in
the already sorted array
int i = 0;
while (i <=20){
if (spqueue[i].status == true)
{
return i;
}
else
{
i++;
}
}
}

Your priority queue implementation of siftdown has some problems.
void Pqueue::siftdown(int i) { //shifts element to its position in the min heap
int c = i * 2;
int c2 = (i * 2) + 1;
// *** Possible bug
// *** I think that if c == inde, then c is indexing beyond the current queue
if (c > inde) return;
int in = i;
if (pqueue[i].eventTime > pqueue[c].eventTime)
{
in = c;
}
if ((c2 < inde) && (pqueue[i].eventTime > pqueue[c2].eventTime))
{
in = c2;
}
// ***************
// ** Bug here
if (pqueue[c].eventTime < pqueue[c2].eventTime) {
in = c;
}
if (in != i) {
swap(pqueue[i], pqueue[in]);
siftdown(in);
}
}
First, I think you want to test c1 >= inde. Also, when you're checking to see if pqueue[c].eventTime < pqueue[c2].eventTime, you do so without making sure that c2 is within bounds.
I find the following to be a more clear and succinct way to do things:
// find the smallest child
int in = c;
if (c2 < inde && pqueue[c2] < pqueue[c])
{
in = c2;
}
if (pqueue[in] < pqueue[i]) {
swap(pqueue[i], pqueue[in]);
siftdown(in);
}

Related

Priority Queue using heap, values with same key don't follow FIFO (first in first out)

So I'm trying to create this priority queue to handle my "Order" objects, I'm running into a problem where an object containing the same key/priority will be placed at an early earlier position than others initialized first. I have provided the expected and received output alongside the 83 lines of code of how I constructed my heap with notes
#include <iostream>
#include <vector>
struct Order {
int value = -1;
int priority = -1;
bool operator <(Order const& RHS) { return priority < RHS.priority; }
};
class heap {
private:
std::vector<Order> orders{ Order{} };
int size{}; //initalizes it at 0
int p(int index) { return index >> 1; }
int l(int index) { return index << 1; }
int r(int index) { return (index << 1) + 1; }
public:
bool isEmpty() const { return size == 0; }
void shiftUp(int position);
void shiftDown(int position);
void add(Order new_entry);
Order removeTop();
Order& getTop() { return orders[1]; }
};
template <typename T>
void mySwap(T& a, T& b) {
T temp = a;
a = b;
b = temp;
}
int main() {
heap h;
h.add(Order{1,3}); h.add(Order{2,2});
h.add(Order{3,3}); h.add(Order{5,1});
h.add(Order{6,2}); h.add(Order{7,2});
h.add(Order{8,3}); h.add(Order{9,1});
h.add(Order{23,3});
std::cout << "value" << " key(priority)" << "\n";
for (int i = 0; i < 8; i++) {
Order temp = h.removeTop();
std::cout << temp.value << "\t " << temp.priority << "\n";
}
}
void heap::shiftUp(int position) {
if (position > size) return;
if (position == 1) return;
if (orders[p(position)] < orders[position]) {
mySwap(orders[position], orders[p(position)]);
shiftUp(p(position));
}
}
void heap::shiftDown(int position) {
if (position > size) return;
int greaterPosition = position;
if (l(position) <= size && orders[position] < orders[l(position)])
greaterPosition = l(position);
if (r(position) <= size && orders[greaterPosition] < orders[r(position)])
greaterPosition = r(position);
if (greaterPosition != position) {
mySwap(orders[position], orders[greaterPosition]);
shiftDown(greaterPosition);
}
}
void heap::add(Order new_entry) {
if (size + 1 >= orders.size()) orders.push_back(Order{});
orders[++size] = new_entry;
shiftUp(size);
}
Order heap::removeTop() {
Order temp = orders[1];
mySwap(orders[1],orders[orders.size() - 1]); size--;
orders.pop_back();
shiftDown(1);
return temp;
}
/*
Expected Output
Value key(priority)
1 3
3 3
8 3
23 3
2 2
6 2
7 2
5 1
9 1
Recieved/wrong Output
value key(priority)
1 3
23 3
3 3
8 3
2 2
6 2
7 2
5 1
*/
Fixed code from answered information above
#include <iostream>
#include <vector>
struct Order {
int value = -1;
int priority = -1;
int FIFO;
bool operator <(Order const& RHS) {
if (priority == RHS.priority)
return FIFO > RHS.FIFO;
else
return priority < RHS.priority;
} //compares keys for larger presidence
};
class heap {
private:
std::vector<Order> orders{ Order{} };
int size{}; //initalizes it at 0
int p(int index) { return index >> 1; }
int l(int index) { return index << 1; }
int r(int index) { return (index << 1) + 1; }
public:
bool isEmpty() const { return size == 0; }
void shiftUp(int position);
void shiftDown(int position);
void add(Order new_entry);
Order removeTop();
Order& getTop() { return orders[1]; }
};
template <typename T>
void mySwap(T& a, T& b) {
T temp = a;
a = b;
b = temp;
}
int main() {
heap h;
h.add(Order{1,3}); h.add(Order{2,2});
h.add(Order{3,3}); h.add(Order{5,1});
h.add(Order{6,2}); h.add(Order{7,2});
h.add(Order{8,3}); h.add(Order{9,1});
h.add(Order{23,3});
std::cout << "value" << " key(priority)" << "\n";
for (int i = 0; i < 8; i++) {
Order temp = h.removeTop();
std::cout << temp.value << "\t " << temp.priority << "\n";
}
}
void heap::shiftUp(int position) {
if (position > size) return;
if (position == 1) return;
if (orders[p(position)] < orders[position]) {
mySwap(orders[position], orders[p(position)]);
shiftUp(p(position));
}
}
void heap::shiftDown(int position) {
if (position > size) return;
int greaterPosition = position;
if (l(position) <= size && orders[position] < orders[l(position)])
greaterPosition = l(position);
if (r(position) <= size && orders[greaterPosition] < orders[r(position)])
greaterPosition = r(position);
if (greaterPosition != position) {
mySwap(orders[position], orders[greaterPosition]);
shiftDown(greaterPosition);
}
}
void heap::add(Order new_entry) {
if (size + 1 >= orders.size()) orders.push_back(Order{});
new_entry.FIFO = size + 1;
orders[++size] = new_entry;
shiftUp(size);
}
Order heap::removeTop() {
Order temp = orders[1];
mySwap(orders[1],orders[orders.size() - 1]); size--;
orders.pop_back();
shiftDown(1);
return temp;
}
In general, heap does not have FIFO property until you implement something that helps doing so. In your order class, you are only comparing using the priority value. In your Order class, you are comparing two Orders by only their priority value. You need a additional variable that serves as the purpose for recording the timing when that value was inserted, and compare according to that.
If you are using the variable value for that purpose, you need to specify in your overloaded < method, what do you want to do when two Order's priority values are equal. Currently, you are only using the priority variable to compare. You are not specifying what do you want to do when the priority of two Orders are equal. You have to specify what do you want to do when the priority value of two variables are equal. Maybe compare a timing variable.

Pointer to array of pointers to structs in C++

I need some help, I'm learing data structers and I got a task to write a programm based on array of pointers to structres which can add elements and do other task with array.I have next model of levels:
first level --> net of shops
second level --> shop
third level --> goods
I've written types for this
typedef struct
{
QString date;
QString prod_code;
QString name;
}goods;
typedef struct
{
QString address;
QString number;
void **sublevel;
}shop;
typedef struct
{
QString website;
QString name;
QString owner;
QString address;
void **sublevel;
}net;
Then I've created global variable void **Start which points to array of pointers:
// init list
void ** init_list()
{
void** p = new void*[SIZE_AR];
p = p+2;
((int*)p)[COUNT_POS] = 0;
((int*)p)[SIZE_POS] = SIZE_AR;
return p;
}
void ** Start = init_list();
COUNT_POS - index of elements where I store count of currently used elemnets
SIZE_POS - size of array allocated in dynamic memory
SIZE_AR - default size for array
But I get segmentation fault when I try to add to element to the last level
(for previous two ones works fine):
// expand array if it overfilled
void ExpandArrPtr (void **&ar, int &SizeAr, int Cnt)
{
void **arW;
arW = new void*[SizeAr+DELTA+2];
for (int K = SizeAr-1; K >= 0; K--) {
arW[K+2] = ar[K];
}
SizeAr = SizeAr + DELTA;
ar=ar-2;
delete []ar;
ar=arW+2;
((int*)ar)[COUNT_POS] = Cnt;
((int*)ar)[SIZE_POS] = SizeAr;
}
// binary search
void bin_search(void **start, QString key, int &pos, bool &find, Cmpmethod func)
{
int mid;
int high, low;
find = false;
if((int*)start[COUNT_POS] == 0)
{
pos = 0;
qDebug()<<"zero elem\n";
return;
}
low = 0;
high = ((int*)start)[COUNT_POS] - 1;
do
{
mid = (high + low) / 2;
int result = func(start[mid], key);
if(result == 0)
{
pos = mid;
find = true;
return;
}
else if(result == 1)
{
high = mid - 1;
}
else
{
low = mid + 1;
}
}while(low <= high);
pos = low;
}
// function for adding in any level
void addtosort(void **&start, void *pnew, int pos)
{
int count = ((int*)start)[COUNT_POS];
int size = ((int*)start)[SIZE_POS];
if(count == size)
{
ExpandArrPtr(start, size, count);
}
if(pos == count)
{
start[pos] = pnew;
}
else
{
for(int i = count;i >= pos;i--)
{
start[i+1] = start[i];
}
start[pos] = pnew;
}
count++;
((int*)start)[COUNT_POS] = count;
}
void add_goods(void **&Start, goods * Pnew)
{
int pos;
bool find;
bin_search((((shop*)(Start))->sublevel), Pnew->name, pos, find, compare_goods);
addtosort((((shop*)(Start))->sublevel), Pnew, pos);
}
// finding the item in second level to add
void find_place(QString key)
{
int pos;
bool find;
int count = ((int*)Start)[COUNT_POS];
for(int i = 0;i < count;i++)
{
bin_search(((net*)(Start)[i])->sublevel, key, pos, find, compare_shop);
if(find)
{
goods * Pnew = new goods;
Pnew->date = "foo"
Pnew->name = "bar"
add_goods(((net*)(Start)[pos])->sublevel, Pnew);
break;
}
}
}
What can cause such problem?

Create a randomly connected set of nodes?

I'm trying to write a function, generate_labyrinth(), that creates a fixed number of randomly connected nodes. Each node is connected with three other nodes.
Here is what I have now:
labyrinth.h:
#ifndef LABYRINTH_H
#define LABYRINTH_H
// node
class Room {
public:
Room ()
: room_number(0), left_door(nullptr),
center_door(nullptr), right_door(nullptr) { }
// data member
int room_number;
// pointers to other nodes
Room* left_door;
Room* center_door;
Room* right_door;
};
//=================================================
class Labyrinth {
public:
Labyrinth (int s) : size(s) { generate_labyrinth (); }
private:
// number of nodes
int size;
// root node
Room* entrance;
// Helper functions
int random_number (int from, int to);
int random_number_without_i (int min, int max, int i);
// Initialiazation function
void generate_labyrinth ();
};
#include "labyrinth.cpp"
#endif
labyrinth.cpp:
// Class Labyrinth member implementations
int Labyrinth::random_number (int min, int max) {
static bool seed_initialized = false;
if (!seed_initialized) {
seed_initialized = true;
srand((unsigned int) time(NULL));
}
return rand() % (max - min + 1) + min;
}
int Labyrinth::random_number_without_i (int min, int max, int i) {
int res = random_number(min, max);
while (res == i){
res = random_number(min, max);
}
return res;
}
void Labyrinth::generate_labyrinth () {
// create "size" number of nodes
entrance = new Room[size];
// initialize Room (node) data members
for (auto i = 0; i < size; ++i) {
entrance[i].room_number = i;
}
// connect each room with three others
int first_room = 1;
int last_room = size - 1;
for (int i = 1; i < size; ++i) {
// avoid connecting a room with itself
int left_goes_to = random_number_without_i (first_room, last_room, i);
int center_goes_to = random_number_without_i (first_room, last_room, i);
int right_goes_to = random_number_without_i (first_room, last_room, i);
entrance[i].left_door = (&entrance[left_goes_to]);
entrance[i].center_door = (&entrance [center_goes_to]);
entrance[i].right_door = (&entrance [right_goes_to]);;
}
// TEST IF NODES POINT TO EACH OTHER
for (auto i = 0; i < size; ++i) {
if (entrance[i].left_door == nullptr || entrance[i].center_door == nullptr ||
entrance[i].right_door == nullptr) {
std::cout <<"Uninitialized pointer value\n";
}
}
getchar();
}
main:
#include <iostream>
#include <time.h>
#include "labyrinth.h"
//=================================================
int main()
{
int cave_size = 20;
Labyrinth cave(cave_size);
}
It appears that after the node initialization in generate_labyrinth () the three pointers, left_room, center_room, right_room remain uninitialized, i.e. the output I get is :
Uninitialized pointer value
Questions:
Why aren't the pointers in the nodes initialized?
Is there another way to generate a randomly connected set of nodes?
Note: I'm not using an insert() function as the number of nodes is fixed and determined during the construction of the data structure.
You generate connections for first_room to last_room, which are rooms 1 to size-1.
// connect each room with three others
int first_room = 1;
int last_room = size - 1;
for (int i = 1; i < size; ++i) {
But when you check the connections you start with room 0 (probably supposed to be the entrance itself).
// TEST IF NODES POINT TO EACH OTHER
for (auto i = 0; i < size; ++i) {

boost mutex in parallel quicksort

This is my first time using mutexes so I am not exactly sure about what I am doing but I think I am having an error with the thread safety of the push_back function using the vector container (I am having multiple threads write to it at the same time and getting this error):
* glibc detected * ./quicksort: double free or corruption (out): 0x00007f2638000980 *
To solve this I added a mutex but it didn't seem to do anything, the code is here:
void parallel_quicksort(vector<int>& input)
{
boost::mutex mutex;
queue<pr_pair> partitions, temp_partitions;
vector<pr_pair> jobs;
parallel_partition(input, partitions, 0, input.size());
pr_pair temp;
while(1)
{
boost::thread_group threadpool;
while(!partitions.empty())
{
temp = partitions.front();
partitions.pop();
jobs.push_back(temp);
if (jobs.size() == NUM_THREADS)
{
for (int i = 0; i < NUM_THREADS; i++)
{
temp = jobs.back();
jobs.pop_back();
threadpool.create_thread(boost::bind(&parallel_partition, boost::ref(input), boost::ref(temp_partitions), temp.p, temp.r));
}
threadpool.join_all();
}
}
while(!jobs.empty())
{
temp = jobs.back();
jobs.pop_back();
threadpool.create_thread(boost::bind(&parallel_partition, boost::ref(input), boost::ref(temp_partitions), temp.p, temp.r));
}
threadpool.join_all();
while(!temp_partitions.empty())
{
temp = temp_partitions.front();
partitions.push(temp);
temp_partitions.pop();
}
if(partitions.empty())
{
break;
}
}
return;
}
void parallel_partition(vector<int>& input, queue<pr_pair>& partitions, int p, int r)
{
int p_store = p;
int r_store = r;
int pivot = input[r];
while (p<r)
{
while (input[p] < pivot)
p++;
while (input[r] > pivot)
r--;
if (input[p] == input[r])
p++;
else if (p<r)
{
int tmp = input[p];
input[p] = input[r];
input[r] = tmp; }
}
pr_pair temp;
if (r-1 > p_store)
{
boost::mutex::scoped_lock scoped_lock(mutex);
temp.p = p_store;
temp.r = r-1;
partitions.push(temp);
}
if (r_store > r+1)
{
boost::mutex::scoped_lock scoped_lock(mutex);
temp.p = r+1;
temp.r = r_store;
partitions.push(temp);
}
return;
}
Quickly scanning the code it seems that you guarded access to the partitions data structure, but your input data structure is modified as well in the parallel_partition method. So that could cause problems.

C++ pointer "losing" its value

As an exercise (largely an exercise in trying to write something using pointers), I'm writing a cache simulation, specifically of the pseudo least recently used system from the old 486. I'm getting an "Access violation reading location" error on the line:
int min = treeArray[set]->root->findPLRU();
Initially the treeArray seems to be initialised properly (if I pause the program at the start and take a look, it's all as should be), but when the programme breaks and I delve in to examine things the root of the tree in question isn't defined.
I feel it's quite probable that I'm making some sort of very elementary pointer mistake, which is causing the pointer to the node to be "lost" somewhere, but I've no clue what it might be. Is there something in particular I need to do to "hold on" to a pointer value?
#include "stdafx.h"
#include "stdlib.h"
#include <conio.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <io.h>
#include "main.h"
//char fn[80]; // trace filename
int tf; // trace file
trace buf[BUFSZ / sizeof(trace)]; // buffer SIZE
int LRUHits = 0;
int pLRUHits = 0;
int randomHits = 0;
int height;
int cachelinenumber;
//log2 helper function
int log2(int n)
{
int i = 0;
while (n)
{
n = n >> 1;
i++;
}
return i - 1;
}
class CacheLine{
public:
int tag;
int access;
CacheLine();
};
class Cache;
class Node{
public:
bool goRight;
Node* left;
Node* right;
int leftCacheLine;
int rightCacheLine;
Node(int depth) // constructor
{
goRight = false;
if (depth < height - 1)
{
left = new Node(depth + 1);
right = new Node(depth + 1);
leftCacheLine = -1;
rightCacheLine = -1;
}
else
{
leftCacheLine = cachelinenumber;
cachelinenumber++;
rightCacheLine = cachelinenumber;
cachelinenumber++;
}
//printf("Depth: %d, Height: %d, Left: %d, Right: %d\n", depth, height, leftCacheLine, rightCacheLine);
}
~Node()
{
delete left;
delete right;
}
int findPLRU()
{
if (leftCacheLine < 0 || rightCacheLine < 0)
{
if (goRight)
{
goRight = false;
return right->findPLRU();
}
else
{
goRight = true;
return left->findPLRU();
}
}
else
{
if (goRight)
{
goRight = false;
return rightCacheLine;
}
else
{
goRight = true;
return leftCacheLine;
}
}
}
};
class Tree{
public:
Node* root;
Tree()
{
root = new Node(0);
}
~Tree()
{
delete root;
}
};
//cache class
class Cache
{
public:
CacheLine *cache;
int l, k, n, replacementPolicy;
int log2l, log2n;
int access;
Tree** treeArray;
//constructor
Cache(int ll, int kk, int nn, int _replacementPolicy)
{
l = ll;
k = kk;
n = nn;
replacementPolicy = _replacementPolicy;
log2l = log2(l);
log2n = log2(n);
cache = (CacheLine*)malloc(sizeof(CacheLine)*k*n);
for (int i = 0; i < k*n; i++)
{
cache[i].tag = 0x80000000;
cache[i].access = 0;
}
if (replacementPolicy == 1)
{
cachelinenumber = 0;
treeArray = new Tree*[n];
for (int i = 0; i < n; i++)
{
treeArray[i] = new Tree();
}
}
access = -1;
}
//destructor
~Cache()
{
free(cache);
}
//test for hit
void hit(int a)
{
access++;
int set = (a >> log2l) & (n - 1);
int tag = a >> (log2n + log2l);
CacheLine* c = &cache[set*k];
for (int i = 0; i < k; i++)
{
if (c[i].tag == tag)
{
c[i].access = access;
if (replacementPolicy == 0)
LRUHits++;
else if (replacementPolicy == 1)
pLRUHits++;
else if (replacementPolicy == 2)
randomHits++;
break;
}
}
if (replacementPolicy == 0) //LRU
{
int min = 0;
int minv = c[0].access;
for (int i = 1; i < k; i++)
{
if (c[i].access < minv)
{
minv = c[i].access;
min = i;
}
}
c[min].tag = tag;
c[min].access = access;
}
else if(replacementPolicy == 1) // pseudoLRU
{
int min = treeArray[set]->root->findPLRU();
c[min].tag = tag;
c[min].access = access;
}
else // random
{
srand(clock());
int randomNumber = rand()%k;
c[randomNumber].tag = tag;
c[randomNumber].access = access;
}
return;
}
};
void analyse (int l, int k, int n)
{
height = log2(k) + 1;
char fn[] = "ico0.trace";
if ((tf = open(fn, _O_RDONLY | _O_BINARY )) == -1) {
printf("unable to open file %s\n", fn);
exit(0);
}
LRUHits = 0;
pLRUHits = 0;
randomHits = 0;
Cache *cache0 = new Cache(l, k, n, 0); // LRU
Cache *cache1 = new Cache(l, k, n, 1); // pseudoLRU
Cache *cache2 = new Cache(l, k, n, 2); // random
int bytes, word0, a, type, burstcount;
int hits = 0;
int tcount = 0;
while (bytes = read(tf, buf, sizeof(buf)))
{
for (int i = 0; i < bytes / (int) sizeof(trace); i++, tcount++)
{
word0 = buf[i].word0;
a = (word0 & ADDRESSMASK) << 2;
type = (word0 >> TYPESHIFT) & TYPEMASK;
burstcount = ((word0 >> BURSTSHIFT) & BURSTMASK) + 1;
cache0->hit(a);
cache1->hit(a);
cache2->hit(a);
}
}
printf("Hits: %d Total: %d\n", LRUHits, tcount);
printf("Hits: %d Total: %d\n", pLRUHits, tcount);
printf("Hits: %d Total: %d\n\n\n", randomHits, tcount);
delete cache0;
delete cache1;
delete cache2;
}
int _tmain(int argc, _TCHAR* argv[])
{
//analyse(16, 1, 8);
analyse(16, 2, 512);
//analyse(16, 4, 256);
//analyse(16, 8, 128);
//analyse(16, 1024, 1);
_getch();
return 0;
}
Your question hasn't yet been pounced upon, probably because your code still doesn't compile since you've not provided main.h.
And even then it would annoy most folks trying to help you because you make no mention of the ico0.trace file that is required to prevent the code from immediately exiting.
You say int min = treeArray[set]->root->findPLRU(); access violates.
1) the value of set can never exceed the size n of your treeArray since you & n-1 the range of input values.
2) since your ~Tree() destructor is never called there will always be a treeArray[set]->root
3) since you *always create new left & right nodes whenever leftCacheLine = -1 or rightCacheLine = -1 it cannot be due to recursive findPLRUs
So, the pointer to the node is not being "lost" somewhere; it is being stomped on.
Try replacing:
int min = treeArray[set]->root->findPLRU();
c[min].tag = tag;
c[min].access = access;
with:
int min = treeArray[set]->root->findPLRU();
if (min >= k*n)
{
printf("ook\n");
}
else
{
c[min].tag = tag;
c[min].access = access;
}
and I think you will discover what's doing the stomping. ;)