-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsystem.cc
102 lines (90 loc) · 3.69 KB
/
system.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include "system.h"
void System::init(unsigned int _num_caches, protocol_t _protocol, Cache::config_t cache_config, unsigned int mem_size, unsigned int _bus_width){
this->protocol = _protocol;
this->num_caches = _num_caches;
this->bus_width = _bus_width;
invalidations = 0;
data_bus_transactions = 0;
pthread_mutex_init(&bus_mutex, NULL);
bus.message = NONE;
bus.data = new uint8_t[cache_config.line_size];
shared_mem = new Memory();
shared_mem->init(mem_size, cache_config.line_size, &bus);
caches = new Cache[num_caches];
for (unsigned int i = 0; i < num_caches; i++) {
caches[i].init(cache_config, protocol, &bus);
}
}
uint8_t System::access(unsigned int core, addr_t physical_addr, access_t access_type, uint8_t data){
pthread_mutex_lock(&bus_mutex);
bus.addr = physical_addr;
uint8_t result_data = caches[core].try_access(physical_addr, access_type, data);
message_t message = bus.message;
if (message == READ_MISS || message == WRITE_MISS) {
bool sent_data_from_cache = false; // true if dirty copy of data in another cache
bool valid_in_other_cache = false; // true if valid copy of data in another cache
// request data from other caches first.
for (unsigned int i = 0; i < num_caches; i++) {
if (i != core) {
sent_data_from_cache = caches[i].system_access(physical_addr, SEND);
if (!valid_in_other_cache) valid_in_other_cache = caches[i].check_valid(physical_addr);
if (sent_data_from_cache) {
// write back to mem while recent data is on bus
shared_mem->access(physical_addr, STORE);
break;
}
}
}
// If none of the caches has a dirty copy, request data from memory
if (!sent_data_from_cache) {
shared_mem->access(physical_addr, SEND);
}
// Update bus message
if (!valid_in_other_cache && protocol == MESI && message == READ_MISS) {
bus.message = SET_EXCLUSIVE;
} else {
bus.message = NONE;
}
// Tell original requesting processor to store data into its cache
data_bus_transactions++;
caches[core].system_access(physical_addr, STORE);
// If the new block evicts an old block, writeback.
if (bus.message == WRITEBACK) {
data_bus_transactions++;
shared_mem->access(bus.addr, STORE);
}
bus.message = NONE;
result_data = caches[core].processor_access(physical_addr, access_type, data);
}
if (message == INVALIDATE || message == WRITE_MISS) {
// invalidate others
invalidations++;
if (verbose) std::cout << " INVALIDATION\n";
for (unsigned int i = 0; i < num_caches; i++) {
if (i != core) caches[i].invalidate(physical_addr);
}
bus.message = NONE;
}
pthread_mutex_unlock(&bus_mutex);
return result_data;
}
void System::print_stats(){
for (unsigned int i = 0; i < num_caches; i++) {
std::cout << "\n======================== Core " << i << " Cache Stats=========================\n";
caches[i].print_stats();
}
std::cout << "========================== System Stats ===========================\n";
shared_mem->print_stats();
std::cout << "Invalidations: " << invalidations << "\n";
std::cout << "Total data transactions through bus: " << data_bus_transactions << "\n";
}
System::~System() {
delete [] caches;
delete shared_mem;
delete [] bus.data;
pthread_mutex_destroy(&bus_mutex);
}