Browse Source

Icarus: fix abort calculation/allow user specified abort

nfactor-troky
Kano 13 years ago
parent
commit
f15d2233fa
  1. 6
      FPGA-README
  2. 51
      driver-icarus.c

6
FPGA-README

@ -7,10 +7,10 @@ Icarus
There is a hidden option in cgminer when Icarus support is compiled in: There is a hidden option in cgminer when Icarus support is compiled in:
--icarus-timing <arg> Set how the Icarus timing is calculated - one setting/value for all or comma separated --icarus-timing <arg> Set how the Icarus timing is calculated - one setting/value for all or comma separated
default Use the default Icarus hash time (2.6316ns) default[=N] Use the default Icarus hash time (2.6316ns)
short Calculate the hash time and stop adjusting it at ~315 difficulty 1 shares (~1hr) short Calculate the hash time and stop adjusting it at ~315 difficulty 1 shares (~1hr)
long Re-calculate the hash time continuously long Re-calculate the hash time continuously
value Specify the hash time in nanoseconds (e.g. 2.6316) value[=N] Specify the hash time in nanoseconds (e.g. 2.6316) and abort time (e.g. 2.6316=80)
Icarus timing is required for devices that do not exactly match a default Icarus Rev3 in Icarus timing is required for devices that do not exactly match a default Icarus Rev3 in
processing speed processing speed
@ -35,6 +35,8 @@ There is a hidden option in cgminer when Icarus support is compiled in:
In 'default' or 'value' mode the 'constants' are calculated once at the start, based on the default In 'default' or 'value' mode the 'constants' are calculated once at the start, based on the default
value or the value specified value or the value specified
The optional additional =N specifies to set the default abort at N 1/10ths of a second, not the
calculated value, which is 112 for 2.6316ns
To determine the hash time value for a non Icarus Rev3 device or an Icarus Rev3 with a different To determine the hash time value for a non Icarus Rev3 device or an Icarus Rev3 with a different
bitstream to the default one, use 'long' mode and give it at least a few hundred shares, or use bitstream to the default one, use 'long' mode and give it at least a few hundred shares, or use

51
driver-icarus.c

@ -82,7 +82,7 @@ ASSERT1(sizeof(uint32_t) == 4);
// Since this rounds up a the last digit - it is a slight overestimate // Since this rounds up a the last digit - it is a slight overestimate
// Thus the hash rate will be a VERY slight underestimate // Thus the hash rate will be a VERY slight underestimate
// (by a lot less than the displayed accuracy) // (by a lot less than the displayed accuracy)
#define ICARUS_HASH_TIME 0.0000000026316 #define ICARUS_REV3_HASH_TIME 0.0000000026316
#define NANOSEC 1000000000.0 #define NANOSEC 1000000000.0
// Icarus Rev3 doesn't send a completion message when it finishes // Icarus Rev3 doesn't send a completion message when it finishes
@ -259,17 +259,22 @@ static int icarus_gets(unsigned char *buf, int fd, struct timeval *tv_finish, in
ssize_t ret = 0; ssize_t ret = 0;
int rc = 0; int rc = 0;
int read_amount = ICARUS_READ_SIZE; int read_amount = ICARUS_READ_SIZE;
bool first = true;
// Read reply 1 byte at a time to get earliest tv_finish
while (true) { while (true) {
ret = read(fd, buf, read_amount); ret = read(fd, buf, 1);
gettimeofday(tv_finish, NULL);
if (first)
gettimeofday(tv_finish, NULL);
if (ret >= read_amount) if (ret >= read_amount)
return 0; return 0;
// Allow a partial I/O
if (ret > 0) { if (ret > 0) {
buf += ret; buf += ret;
read_amount -= ret; read_amount -= ret;
first = false;
continue; continue;
} }
@ -328,7 +333,7 @@ static void set_timing_mode(struct cgpu_info *icarus)
struct ICARUS_INFO *info = icarus_info[icarus->device_id]; struct ICARUS_INFO *info = icarus_info[icarus->device_id];
double Hs; double Hs;
char buf[BUFSIZ+1]; char buf[BUFSIZ+1];
char *ptr, *comma; char *ptr, *comma, *eq;
size_t max; size_t max;
int i; int i;
@ -355,14 +360,17 @@ static void set_timing_mode(struct cgpu_info *icarus)
buf[max] = '\0'; buf[max] = '\0';
} }
info->Hs = 0;
info->read_count = 0;
if (strcasecmp(buf, MODE_SHORT_STR) == 0) { if (strcasecmp(buf, MODE_SHORT_STR) == 0) {
info->Hs = ICARUS_HASH_TIME; info->Hs = ICARUS_REV3_HASH_TIME;
info->read_count = ICARUS_READ_COUNT_TIMING; info->read_count = ICARUS_READ_COUNT_TIMING;
info->timing_mode = MODE_SHORT; info->timing_mode = MODE_SHORT;
info->do_icarus_timing = true; info->do_icarus_timing = true;
} else if (strcasecmp(buf, MODE_LONG_STR) == 0) { } else if (strcasecmp(buf, MODE_LONG_STR) == 0) {
info->Hs = ICARUS_HASH_TIME; info->Hs = ICARUS_REV3_HASH_TIME;
info->read_count = ICARUS_READ_COUNT_TIMING; info->read_count = ICARUS_READ_COUNT_TIMING;
info->timing_mode = MODE_LONG; info->timing_mode = MODE_LONG;
@ -370,16 +378,29 @@ static void set_timing_mode(struct cgpu_info *icarus)
} else if ((Hs = atof(buf)) != 0) { } else if ((Hs = atof(buf)) != 0) {
info->Hs = Hs / NANOSEC; info->Hs = Hs / NANOSEC;
info->fullnonce = info->Hs * (((double)0xffffffff) + 1); info->fullnonce = info->Hs * (((double)0xffffffff) + 1);
info->read_count = (int)(info->fullnonce * TIME_FACTOR) - 1;
if ((eq = strchr(buf, '=')) != NULL)
info->read_count = atoi(eq+1);
if (info->read_count < 1)
info->read_count = (int)(info->fullnonce * TIME_FACTOR) - 1;
if (unlikely(info->read_count < 1))
info->read_count = 1;
info->timing_mode = MODE_VALUE; info->timing_mode = MODE_VALUE;
info->do_icarus_timing = false; info->do_icarus_timing = false;
} else { } else {
// Anything else in buf just uses DEFAULT mode // Anything else in buf just uses DEFAULT mode
info->Hs = ICARUS_HASH_TIME; info->Hs = ICARUS_REV3_HASH_TIME;
info->fullnonce = info->Hs * (((double)0xffffffff) + 1); info->fullnonce = info->Hs * (((double)0xffffffff) + 1);
info->read_count = (int)(info->fullnonce * TIME_FACTOR) - 1;
if ((eq = strchr(buf, '=')) != NULL)
info->read_count = atoi(eq+1);
if (info->read_count < 1)
info->read_count = (int)(info->fullnonce * TIME_FACTOR) - 1;
info->timing_mode = MODE_DEFAULT; info->timing_mode = MODE_DEFAULT;
info->do_icarus_timing = false; info->do_icarus_timing = false;
@ -562,10 +583,7 @@ static uint64_t icarus_scanhash(struct thr_info *thr, struct work *work,
if (ret) if (ret)
return 0; /* This should never happen */ return 0; /* This should never happen */
info = icarus_info[icarus->device_id]; gettimeofday(&tv_start, NULL);
if (opt_debug || info->do_icarus_timing)
gettimeofday(&tv_start, NULL);
if (opt_debug) { if (opt_debug) {
ob_hex = bin2hex(ob_bin, sizeof(ob_bin)); ob_hex = bin2hex(ob_bin, sizeof(ob_bin));
@ -578,6 +596,7 @@ static uint64_t icarus_scanhash(struct thr_info *thr, struct work *work,
/* Icarus will return 4 bytes (ICARUS_READ_SIZE) nonces or nothing */ /* Icarus will return 4 bytes (ICARUS_READ_SIZE) nonces or nothing */
memset(nonce_bin, 0, sizeof(nonce_bin)); memset(nonce_bin, 0, sizeof(nonce_bin));
info = icarus_info[icarus->device_id];
ret = icarus_gets(nonce_bin, fd, &tv_finish, thr_id, info->read_count); ret = icarus_gets(nonce_bin, fd, &tv_finish, thr_id, info->read_count);
work->blk.nonce = 0xffffffff; work->blk.nonce = 0xffffffff;
@ -654,7 +673,9 @@ static uint64_t icarus_scanhash(struct thr_info *thr, struct work *work,
if (history0->values >= info->min_data_count if (history0->values >= info->min_data_count
&& timercmp(&tv_start, &(history0->finish), >)) { && timercmp(&tv_start, &(history0->finish), >)) {
for (i = INFO_HISTORY; i > 0; i--) for (i = INFO_HISTORY; i > 0; i--)
memcpy(&(info->history[i]), &(info->history[i-1]), sizeof(struct ICARUS_HISTORY)); memcpy(&(info->history[i]),
&(info->history[i-1]),
sizeof(struct ICARUS_HISTORY));
// Initialise history0 to zero for summary calculation // Initialise history0 to zero for summary calculation
memset(history0, 0, sizeof(struct ICARUS_HISTORY)); memset(history0, 0, sizeof(struct ICARUS_HISTORY));

Loading…
Cancel
Save