dynclock.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. /*
  2. * Copyright 2012-2013 Luke Dashjr
  3. * Copyright 2012 nelisky
  4. *
  5. * This program is free software; you can redistribute it and/or modify it
  6. * under the terms of the GNU General Public License as published by the Free
  7. * Software Foundation; either version 3 of the License, or (at your option)
  8. * any later version. See COPYING for more details.
  9. */
  10. #include "config.h"
  11. #include <stdbool.h>
  12. #include <stdint.h>
  13. #include "dynclock.h"
  14. #include "miner.h"
  15. void dclk_prepare(struct dclk_data *data)
  16. {
  17. *data = (struct dclk_data){
  18. // after 275 sample periods
  19. .minGoodSamples = 150.,
  20. .freqMinM = 1,
  21. };
  22. }
  23. void dclk_msg_freqchange(const char *repr, int oldFreq, int newFreq, const char *tail)
  24. {
  25. applog(LOG_NOTICE, "%"PRIpreprv": Frequency %s from %u to %u MHz%s",
  26. repr,
  27. (oldFreq > newFreq ? "dropped" : "raised "),
  28. oldFreq, newFreq,
  29. tail ?: ""
  30. );
  31. }
  32. bool dclk_updateFreq(struct dclk_data *data, dclk_change_clock_func_t changeclock, struct thr_info *thr)
  33. {
  34. struct cgpu_info *cgpu = thr->cgpu;
  35. uint8_t freqMDefault = data->freqMDefault;
  36. int i, maxM, bestM;
  37. double bestR, r;
  38. bool rv = true;
  39. if (freqMDefault > data->freqMaxM)
  40. // This occurs when the device in question adjusts its MaxM down due to temperature or similar reasons
  41. freqMDefault = data->freqMaxM;
  42. for (i = 0; i < data->freqMaxM; i++)
  43. if (data->maxErrorRate[i + 1] * i < data->maxErrorRate[i] * (i + 20))
  44. data->maxErrorRate[i + 1] = data->maxErrorRate[i] * (1.0 + 20.0 / i);
  45. maxM = 0;
  46. // Use max mulitplier up to the default as far as possible without hitting the max error rate
  47. while (maxM < freqMDefault && data->maxErrorRate[maxM + 1] < DCLK_MAXMAXERRORRATE)
  48. maxM++;
  49. // Use max mulitplier beyond the default if it's never hit the max error rate, and our current max has collected sufficient samples
  50. while (maxM < data->freqMaxM && data->maxErrorRate[maxM + 1] < DCLK_MAXMAXERRORRATE && data->errorWeight[maxM] >= data->minGoodSamples)
  51. maxM++;
  52. // Find the multiplier that gives the best hashrate
  53. bestM = data->freqMinM;
  54. bestR = 0;
  55. for (i = bestM; i <= maxM; i++) {
  56. // Hashrate is weighed on a linear scale
  57. r = (i + 1);
  58. // The currently selected frequency gets a small "bonus" in comparison, as hysteresis
  59. if (i == data->freqM)
  60. r += DCLK_ERRORHYSTERESIS;
  61. // Adjust for measured error rate
  62. r *= (1 - data->maxErrorRate[i]);
  63. // If it beats the current best, update best*
  64. if (r > bestR) {
  65. bestM = i;
  66. bestR = r;
  67. }
  68. }
  69. // Actually change the clock if the best multiplier is not currently selected
  70. if (bestM != data->freqM) {
  71. rv = changeclock(thr, bestM);
  72. }
  73. // Find the highest multiplier that we've taken a reasonable sampling of
  74. maxM = freqMDefault;
  75. while (maxM < data->freqMaxM && data->errorWeight[maxM + 1] > 100)
  76. maxM++;
  77. // If the new multiplier is some fraction of the highest we've used long enough to get a good sample, assume there is something wrong and instruct the driver to shut it off
  78. if ((bestM < (1.0 - DCLK_OVERHEATTHRESHOLD) * maxM) && bestM < maxM - 1) {
  79. applog(LOG_ERR, "%"PRIpreprv": frequency drop of %.1f%% detect. This may be caused by overheating. FPGA is shut down to prevent damage.",
  80. cgpu->proc_repr,
  81. (1.0 - 1.0 * bestM / maxM) * 100);
  82. return false;
  83. }
  84. return rv;
  85. }
  86. void dclk_gotNonces(struct dclk_data *data)
  87. {
  88. data->errorCount[data->freqM] *= 0.995;
  89. data->errorWeight[data->freqM] = data->errorWeight[data->freqM] * 0.995 + 1.0;
  90. }
  91. void dclk_errorCount(struct dclk_data *data, double portion)
  92. {
  93. data->errorCount[data->freqM] += portion;
  94. }
  95. void dclk_preUpdate(struct dclk_data *data)
  96. {
  97. data->errorRate[data->freqM] = data->errorCount[data->freqM] / data->errorWeight[data->freqM];
  98. // errorWeight 100 begins after sample period 137; before then, we minimize the effect of measured errorRate
  99. if (data->errorWeight[data->freqM] < 100)
  100. data->errorRate[data->freqM] /= 100;
  101. if (data->errorRate[data->freqM] > data->maxErrorRate[data->freqM])
  102. data->maxErrorRate[data->freqM] = data->errorRate[data->freqM];
  103. }