-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathperceptron.cpp
65 lines (57 loc) · 1.91 KB
/
perceptron.cpp
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
//
// Created by toby on 26/02/19.
//
#include <cstdlib>
#include "perceptron.h"
perceptron::perceptron(int address_bits_, int history_bits_, int weight_bits_, int threshold_) {
address_bits = address_bits_;
history_bits = history_bits_;
weight_bits = weight_bits_;
weight_max = (1<<(weight_bits-1))-1;
weight_min = -(1<<(weight_bits-1));
threshold = threshold_;
weight_table_size = (1<<address_bits);
size = weight_bits*weight_table_size*(history_bits_+1);
weight_table = new short[(history_bits+1)*weight_table_size];
mask = mask = (1<<(history_bits-1))-1;
global_history = 0;
num_previous = 0;
}
int perceptron::predict(unsigned int addr, int taken) {
//make prediction
int entry = (addr/2)%weight_table_size;
entry *= (history_bits+1);
int y = weight_table[entry];
for(int i=0; i<num_previous; i++) {
int x = (global_history >> i) & 1;
if(x == 0 ) x = -1;
y += weight_table[entry+i+1]*x;
}
int predict_taken = 0;
if(y>= 0) predict_taken = 1;
//train perceptron
//threshold prevents overtraining
if(abs(y) <= threshold || predict_taken != taken) {
if (taken && weight_table[entry] < weight_max) {
weight_table[entry]++;
} else if (weight_table[entry] > weight_min) {
weight_table[entry]--;
}
for (int i = 0; i < num_previous; i++) {
int x = (global_history >> i) & 1;
if (taken == x && weight_table[entry + i + 1] < weight_max) {
weight_table[entry + i + 1]++;
} else if (taken != x && weight_table[entry + i + 1] > weight_min)
weight_table[entry + i + 1]--;
}
}
//update global history
global_history &= mask;
global_history = (global_history << 1) + taken;
if(num_previous < history_bits) {
num_previous++;
}
return predict_taken;
}
perceptron::~perceptron() {
}