Browse Source

Add an avalon-auto option which enables dynamic overclocking based on hardware error rate for maximum effective hashrate.

nfactor-troky
Con Kolivas 11 years ago
parent
commit
e811c4dc77
  1. 16
      ASIC-README
  2. 1
      README
  3. 3
      cgminer.c
  4. 88
      driver-avalon.c
  5. 11
      driver-avalon.h

16
ASIC-README

@ -84,15 +84,17 @@ degrees. @@ -84,15 +84,17 @@ degrees.
Avalon commands:
--avalon-auto Adjust avalon overclock frequency dynamically for best hashrate
--avalon-cutoff <arg> Set avalon overheat cut off temperature (default: 60)
--avalon-options <arg> Set avalon options baud:miners:asic:timeout:freq
--avalon-temp <arg> Set avalon target temperature (default: 50)
eg:
--avalon-cutoff 65
This will cut off the avalon should it get up to 65 degrees and will then
re-enable it when it gets to the target temperature as specified by avalon-temp.
Avalon auto will enable dynamic overclocking gradually increasing and
decreasing the frequency till the highest hashrate that keeps hardware errors
around 1% is achieved. This WILL run your avalon beyond its normal specification
so the usual warnings apply. When avalon-auto is enabled, the avalon-options
for frequency and timeout are used as the starting point only.
eg:
--avalon-temp 55
@ -103,6 +105,12 @@ very low such as 0 will achieve this. This option can be added to the "More @@ -103,6 +105,12 @@ very low such as 0 will achieve this. This option can be added to the "More
options" entry in the web interface if you do not have a direct way of setting
it.
eg:
--avalon-cutoff 65
This will cut off the avalon should it get up to 65 degrees and will then
re-enable it when it gets to the target temperature as specified by avalon-temp.
eg:
--avalon-options 115200:24:10:45:282

1
README

@ -233,6 +233,7 @@ See SCRYPT-README for more information regarding litecoin mining. @@ -233,6 +233,7 @@ See SCRYPT-README for more information regarding litecoin mining.
ASIC and FPGA mining boards (BFL ASIC, BitForce, Icarus, ModMiner, Ztex)
only options:
--avalon-auto Adjust avalon overclock frequency dynamically for best hashrate
--avalon-cutoff <arg> Set avalon overheat cut off temperature (default: 60)
--avalon-options <arg> Set avalon options baud:miners:asic:timeout:freq
--avalon-temp <arg> Set avalon target temperature (default: 50)

3
cgminer.c

@ -1057,6 +1057,9 @@ static struct opt_table opt_config_table[] = { @@ -1057,6 +1057,9 @@ static struct opt_table opt_config_table[] = {
opt_hidden),
#endif
#ifdef USE_AVALON
OPT_WITHOUT_ARG("--avalon-auto",
opt_set_bool, &opt_avalon_auto,
"Adjust avalon overclock frequency dynamically for best hashrate"),
OPT_WITH_ARG("--avalon-cutoff",
set_int_0_to_100, opt_show_intval, &opt_avalon_overheat,
"Set avalon overheat cut off temperature"),

88
driver-avalon.c

@ -42,6 +42,8 @@ @@ -42,6 +42,8 @@
int opt_avalon_temp = AVALON_TEMP_TARGET;
int opt_avalon_overheat = AVALON_TEMP_OVERHEAT;
bool opt_avalon_auto;
static int option_offset = -1;
struct device_drv avalon_drv;
@ -51,6 +53,7 @@ static int avalon_init_task(struct avalon_task *at, @@ -51,6 +53,7 @@ static int avalon_init_task(struct avalon_task *at,
uint8_t miner_num, uint8_t nonce_elf,
uint8_t gate_miner, int frequency)
{
uint16_t *lefreq16;
uint8_t *buf;
static bool first = true;
@ -98,37 +101,8 @@ static int avalon_init_task(struct avalon_task *at, @@ -98,37 +101,8 @@ static int avalon_init_task(struct avalon_task *at,
buf[9] = 0x01;
buf[10] = 0x00;
buf[11] = 0x00;
switch (frequency) {
case 256:
buf[6] = 0x03;
buf[7] = 0x08;
break;
default:
case 270:
buf[6] = 0x73;
buf[7] = 0x08;
break;
case 282:
buf[6] = 0xd3;
buf[7] = 0x08;
break;
case 300:
buf[6] = 0x63;
buf[7] = 0x09;
break;
case 325:
buf[6] = 0x28;
buf[7] = 0x0a;
break;
case 350:
buf[6] = 0xf0;
buf[7] = 0x0a;
break;
case 375:
buf[6] = 0xb8;
buf[7] = 0x0b;
break;
}
lefreq16 = (uint16_t *)&buf[6];
*lefreq16 = htole16(frequency * 8);
return 0;
}
@ -731,6 +705,11 @@ static void avalon_parse_results(struct cgpu_info *avalon, struct avalon_info *i @@ -731,6 +705,11 @@ static void avalon_parse_results(struct cgpu_info *avalon, struct avalon_info *i
mutex_lock(&info->lock);
if (!info->nonces++)
gettemp = true;
info->auto_nonces++;
mutex_unlock(&info->lock);
} else if (opt_avalon_auto) {
mutex_lock(&info->lock);
info->auto_hw++;
mutex_unlock(&info->lock);
}
@ -842,6 +821,31 @@ static void avalon_rotate_array(struct cgpu_info *avalon) @@ -842,6 +821,31 @@ static void avalon_rotate_array(struct cgpu_info *avalon)
avalon->work_array = 0;
}
static void avalon_set_timeout(struct avalon_info *info)
{
info->timeout = AVALON_TIMEOUT_FACTOR / info->frequency;
}
static void avalon_inc_freq(struct avalon_info *info)
{
info->frequency += 2;
if (info->frequency > AVALON_MAX_FREQUENCY)
info->frequency = AVALON_MAX_FREQUENCY;
avalon_set_timeout(info);
applog(LOG_NOTICE, "Avalon increasing frequency to %d, timeout %d",
info->frequency, info->timeout);
}
static void avalon_dec_freq(struct avalon_info *info)
{
info->frequency -= 1;
if (info->frequency < AVALON_MIN_FREQUENCY)
info->frequency = AVALON_MIN_FREQUENCY;
avalon_set_timeout(info);
applog(LOG_NOTICE, "Avalon decreasing frequency to %d, timeout %d",
info->frequency, info->timeout);
}
static void *avalon_send_tasks(void *userdata)
{
struct cgpu_info *avalon = (struct cgpu_info *)userdata;
@ -860,6 +864,24 @@ static void *avalon_send_tasks(void *userdata) @@ -860,6 +864,24 @@ static void *avalon_send_tasks(void *userdata)
while (avalon_buffer_full(avalon))
cgsem_wait(&info->write_sem);
if (opt_avalon_auto && info->auto_queued >= AVALON_AUTO_CYCLE) {
mutex_lock(&info->lock);
if (info->auto_nonces >= (AVALON_AUTO_CYCLE * 19 / 20) &&
info->auto_nonces <= (AVALON_AUTO_CYCLE * 21 / 20)) {
int total = info->auto_nonces + info->auto_hw;
/* Try to keep hw errors ~1-1.5% */
if (info->auto_hw * 100 < total)
avalon_inc_freq(info);
else if (info->auto_hw * 66 > total)
avalon_dec_freq(info);
}
info->auto_queued =
info->auto_nonces =
info->auto_hw = 0;
mutex_unlock(&info->lock);
}
mutex_lock(&info->qlock);
start_count = avalon->work_array * avalon_get_work_count;
end_count = start_count + avalon_get_work_count;
@ -877,11 +899,15 @@ static void *avalon_send_tasks(void *userdata) @@ -877,11 +899,15 @@ static void *avalon_send_tasks(void *userdata)
info->timeout, info->asic_count,
info->miner_count, 1, 0, info->frequency);
avalon_create_task(&at, avalon->works[i]);
info->auto_queued++;
} else {
idled++;
avalon_init_task(&at, 0, 0, info->fan_pwm,
info->timeout, info->asic_count,
info->miner_count, 1, 1, info->frequency);
/* Reset the auto_queued count if we end up
* idling any miners. */
info->auto_queued = 0;
}
ret = avalon_send_task(&at, avalon);

11
driver-avalon.h

@ -25,15 +25,21 @@ @@ -25,15 +25,21 @@
#define AVALON_FAN_FACTOR 120
#define AVALON_DEFAULT_FAN_MAX_PWM 0xA0 /* 100% */
#define AVALON_DEFAULT_FAN_MIN_PWM 0x20 /* 20% */
#define AVALON_TEMP_TARGET 50
#define AVALON_TEMP_HYSTERESIS 3
#define AVALON_TEMP_OVERHEAT 60
#define AVALON_DEFAULT_TIMEOUT 0x2D
#define AVALON_MIN_FREQUENCY 256
#define AVALON_MAX_FREQUENCY 450
#define AVALON_TIMEOUT_FACTOR 12000
#define AVALON_DEFAULT_FREQUENCY 282
#define AVALON_DEFAULT_MINER_NUM 0x20
#define AVALON_DEFAULT_ASIC_NUM 0xA
#define AVALON_AUTO_CYCLE 1024
#define AVALON_FTDI_READSIZE 510
#define AVALON_USB_PACKETSIZE 512
#define AVALON_READBUF_SIZE 8192
@ -118,6 +124,10 @@ struct avalon_info { @@ -118,6 +124,10 @@ struct avalon_info {
cgsem_t write_sem;
int nonces;
int auto_queued;
int auto_nonces;
int auto_hw;
bool idle;
bool reset;
bool overheat;
@ -142,6 +152,7 @@ ASSERT1(sizeof(uint32_t) == 4); @@ -142,6 +152,7 @@ ASSERT1(sizeof(uint32_t) == 4);
extern struct avalon_info **avalon_info;
extern int opt_avalon_temp;
extern int opt_avalon_overheat;
extern bool opt_avalon_auto;
#endif /* USE_AVALON */
#endif /* AVALON_H */

Loading…
Cancel
Save