-
Notifications
You must be signed in to change notification settings - Fork 68
/
dynclock.c
98 lines (84 loc) · 2.95 KB
/
dynclock.c
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
/*
* Copyright 2012 Luke Dashjr
* Copyright 2012 nelisky
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 3 of the License, or (at your option)
* any later version. See COPYING for more details.
*/
#include "config.h"
#include "dynclock.h"
#include "miner.h"
void dclk_prepare(struct dclk_data *data)
{
*data = (struct dclk_data){
.minGoodSamples = 150.,
.freqMinM = 1,
};
}
void dclk_msg_freqchange(const char *repr, int oldFreq, int newFreq, const char *tail)
{
applog(LOG_NOTICE, "%s: Frequency %s from %u to %u MHz%s",
repr,
(oldFreq > newFreq ? "dropped" : "raised "),
oldFreq, newFreq,
tail ?: ""
);
}
bool dclk_updateFreq(struct dclk_data *data, dclk_change_clock_func_t changeclock, struct thr_info *thr)
{
struct cgpu_info *cgpu = thr->cgpu;
uint8_t freqMDefault = data->freqMDefault;
int i, maxM, bestM;
double bestR, r;
bool rv = true;
if (freqMDefault > data->freqMaxM)
// This occurs when the device in question adjusts its MaxM down due to temperature or similar reasons
freqMDefault = data->freqMaxM;
for (i = 0; i < data->freqMaxM; i++)
if (data->maxErrorRate[i + 1] * i < data->maxErrorRate[i] * (i + 20))
data->maxErrorRate[i + 1] = data->maxErrorRate[i] * (1.0 + 20.0 / i);
maxM = 0;
while (maxM < freqMDefault && data->maxErrorRate[maxM + 1] < DCLK_MAXMAXERRORRATE)
maxM++;
while (maxM < data->freqMaxM && data->maxErrorRate[maxM + 1] < DCLK_MAXMAXERRORRATE && data->errorWeight[maxM] >= data->minGoodSamples)
maxM++;
bestM = data->freqMinM;
bestR = 0;
for (i = bestM; i <= maxM; i++) {
r = (i + 1 + (i == data->freqM? DCLK_ERRORHYSTERESIS: 0)) * (1 - data->maxErrorRate[i]);
if (r > bestR) {
bestM = i;
bestR = r;
}
}
if (bestM != data->freqM) {
rv = changeclock(thr, bestM);
}
maxM = freqMDefault;
while (maxM < data->freqMaxM && data->errorWeight[maxM + 1] > 100)
maxM++;
if ((bestM < (1.0 - DCLK_OVERHEATTHRESHOLD) * maxM) && bestM < maxM - 1) {
applog(LOG_ERR, "%s %u: frequency drop of %.1f%% detect. This may be caused by overheating. FPGA is shut down to prevent damage.",
cgpu->api->name, cgpu->device_id,
(1.0 - 1.0 * bestM / maxM) * 100);
return false;
}
return rv;
}
void dclk_gotNonces(struct dclk_data *data)
{
data->errorCount[data->freqM] *= 0.995;
data->errorWeight[data->freqM] = data->errorWeight[data->freqM] * 0.995 + 1.0;
}
void dclk_errorCount(struct dclk_data *data, double portion)
{
data->errorCount[data->freqM] += portion;
}
void dclk_preUpdate(struct dclk_data *data)
{
data->errorRate[data->freqM] = data->errorCount[data->freqM] / data->errorWeight[data->freqM] * (data->errorWeight[data->freqM] < 100 ? data->errorWeight[data->freqM] * 0.01 : 1.0);
if (data->errorRate[data->freqM] > data->maxErrorRate[data->freqM])
data->maxErrorRate[data->freqM] = data->errorRate[data->freqM];
}