Browse Source

Merge branch 'master' of github.com:ckolivas/cgminer

Con Kolivas 12 years ago
parent
commit
22ca87dbf2
2 changed files with 65 additions and 9 deletions
  1. 6 2
      FPGA-README
  2. 59 7
      driver-icarus.c

+ 6 - 2
FPGA-README

@@ -213,8 +213,8 @@ only 1 FPGA actually runs on the board (e.g. like an early CM1 Icarus copy bitst
 
 
 --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[=N]   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)
-           long          Re-calculate the hash time continuously
+           short=[N]     Calculate the hash time and stop adjusting it at ~315 difficulty 1 shares (~1hr)
+           long=[N]      Re-calculate the hash time continuously
            value[=N]     Specify the hash time in nanoseconds (e.g. 2.6316) and abort time (e.g. 2.6316=80)
            value[=N]     Specify the hash time in nanoseconds (e.g. 2.6316) and abort time (e.g. 2.6316=80)
 
 
 If you define fewer comma seperated values than Icarus devices, the last values will be used
 If you define fewer comma seperated values than Icarus devices, the last values will be used
@@ -236,6 +236,10 @@ Any CPU delays while calculating the hash time will affect the result
 'short' mode only requires the computer to be stable until it has completed ~315 difficulty 1 shares
 'short' mode only requires the computer to be stable until it has completed ~315 difficulty 1 shares
 'long' mode requires it to always be stable to ensure accuracy, however, over time it continually
 'long' mode requires it to always be stable to ensure accuracy, however, over time it continually
 corrects itself
 corrects itself
+The optional additional =N for 'short' or 'long' specifies the limit to set the timeout to in N * 100ms
+thus if the timing code calculation is higher while running, it will instead use N * 100ms
+This can be set to the appropriate value to ensure the device never goes idle even if the
+calculation is negatively affected by system performance
 
 
 When in 'short' or 'long' mode, it will report the hash time value each time it is re-calculated
 When in 'short' or 'long' mode, it will report the hash time value each time it is re-calculated
 In 'short' or 'long' mode, the scan abort time starts at 5 seconds and uses the default 2.6316ns
 In 'short' or 'long' mode, the scan abort time starts at 5 seconds and uses the default 2.6316ns

+ 59 - 7
driver-icarus.c

@@ -72,9 +72,17 @@ ASSERT1(sizeof(uint32_t) == 4);
 // maybe 1ms?
 // maybe 1ms?
 #define ICARUS_READ_TIME(baud) (0.001)
 #define ICARUS_READ_TIME(baud) (0.001)
 
 
-// USB ms timeout to wait
+// USB ms timeout to wait - user specified timeouts are multiples of this
 #define ICARUS_WAIT_TIMEOUT 100
 #define ICARUS_WAIT_TIMEOUT 100
 
 
+// Defined in multiples of ICARUS_WAIT_TIMEOUT
+// Must of course be greater than ICARUS_READ_COUNT_TIMING/ICARUS_WAIT_TIMEOUT
+// There's no need to have this bigger, since the overhead/latency of extra work
+// is pretty small once you get beyond a 10s nonce range time and 10s also
+// means that nothing slower than 429MH/s can go idle so most icarus devices
+// will always mine without idling
+#define ICARUS_READ_TIME_LIMIT_MAX 100
+
 // In timing mode: Default starting value until an estimate can be obtained
 // In timing mode: Default starting value until an estimate can be obtained
 // 5000 ms allows for up to a ~840MH/s device
 // 5000 ms allows for up to a ~840MH/s device
 #define ICARUS_READ_COUNT_TIMING	5000
 #define ICARUS_READ_COUNT_TIMING	5000
@@ -160,7 +168,9 @@ enum timing_mode { MODE_DEFAULT, MODE_SHORT, MODE_LONG, MODE_VALUE };
 
 
 static const char *MODE_DEFAULT_STR = "default";
 static const char *MODE_DEFAULT_STR = "default";
 static const char *MODE_SHORT_STR = "short";
 static const char *MODE_SHORT_STR = "short";
+static const char *MODE_SHORT_STREQ = "short=";
 static const char *MODE_LONG_STR = "long";
 static const char *MODE_LONG_STR = "long";
+static const char *MODE_LONG_STREQ = "long=";
 static const char *MODE_VALUE_STR = "value";
 static const char *MODE_VALUE_STR = "value";
 static const char *MODE_UNKNOWN_STR = "unknown";
 static const char *MODE_UNKNOWN_STR = "unknown";
 
 
@@ -176,6 +186,8 @@ struct ICARUS_INFO {
 	double Hs;
 	double Hs;
 	// ms til we abort
 	// ms til we abort
 	int read_time;
 	int read_time;
+	// ms limit for (short=/long=) read_time
+	int read_time_limit;
 
 
 	enum timing_mode timing_mode;
 	enum timing_mode timing_mode;
 	bool do_icarus_timing;
 	bool do_icarus_timing;
@@ -536,19 +548,46 @@ static void set_timing_mode(int this_option_offset, struct cgpu_info *icarus)
 	}
 	}
 
 
 	info->read_time = 0;
 	info->read_time = 0;
+	info->read_time_limit = 0; // 0 = no limit
 
 
-	// TODO: allow short=N and long=N
 	if (strcasecmp(buf, MODE_SHORT_STR) == 0) {
 	if (strcasecmp(buf, MODE_SHORT_STR) == 0) {
+		// short
+		info->read_time = ICARUS_READ_COUNT_TIMING;
+
+		info->timing_mode = MODE_SHORT;
+		info->do_icarus_timing = true;
+	} else if (strncasecmp(buf, MODE_SHORT_STREQ, strlen(MODE_SHORT_STREQ)) == 0) {
+		// short=limit
 		info->read_time = ICARUS_READ_COUNT_TIMING;
 		info->read_time = ICARUS_READ_COUNT_TIMING;
 
 
 		info->timing_mode = MODE_SHORT;
 		info->timing_mode = MODE_SHORT;
 		info->do_icarus_timing = true;
 		info->do_icarus_timing = true;
+
+		info->read_time_limit = atoi(&buf[strlen(MODE_SHORT_STREQ)]);
+		if (info->read_time_limit < 0)
+			info->read_time_limit = 0;
+		if (info->read_time_limit > ICARUS_READ_TIME_LIMIT_MAX)
+			info->read_time_limit = ICARUS_READ_TIME_LIMIT_MAX;
 	} else if (strcasecmp(buf, MODE_LONG_STR) == 0) {
 	} else if (strcasecmp(buf, MODE_LONG_STR) == 0) {
+		// long
 		info->read_time = ICARUS_READ_COUNT_TIMING;
 		info->read_time = ICARUS_READ_COUNT_TIMING;
 
 
 		info->timing_mode = MODE_LONG;
 		info->timing_mode = MODE_LONG;
 		info->do_icarus_timing = true;
 		info->do_icarus_timing = true;
+	} else if (strncasecmp(buf, MODE_LONG_STREQ, strlen(MODE_LONG_STREQ)) == 0) {
+		// long=limit
+		info->read_time = ICARUS_READ_COUNT_TIMING;
+
+		info->timing_mode = MODE_LONG;
+		info->do_icarus_timing = true;
+
+		info->read_time_limit = atoi(&buf[strlen(MODE_LONG_STREQ)]);
+		if (info->read_time_limit < 0)
+			info->read_time_limit = 0;
+		if (info->read_time_limit > ICARUS_READ_TIME_LIMIT_MAX)
+			info->read_time_limit = ICARUS_READ_TIME_LIMIT_MAX;
 	} else if ((Hs = atof(buf)) != 0) {
 	} else if ((Hs = atof(buf)) != 0) {
+		// ns[=read_time]
 		info->Hs = Hs / NANOSEC;
 		info->Hs = Hs / NANOSEC;
 		info->fullnonce = info->Hs * (((double)0xffffffff) + 1);
 		info->fullnonce = info->Hs * (((double)0xffffffff) + 1);
 
 
@@ -583,10 +622,13 @@ static void set_timing_mode(int this_option_offset, struct cgpu_info *icarus)
 
 
 	info->min_data_count = MIN_DATA_COUNT;
 	info->min_data_count = MIN_DATA_COUNT;
 
 
-	applog(LOG_DEBUG, "%s: cgid %d Init: mode=%s read_time=%dms Hs=%e",
+	// All values are in multiples of ICARUS_WAIT_TIMEOUT
+	info->read_time_limit *= ICARUS_WAIT_TIMEOUT;
+
+	applog(LOG_DEBUG, "%s: cgid %d Init: mode=%s read_time=%dms limit=%dms Hs=%e",
 			icarus->drv->name, icarus->cgminer_id,
 			icarus->drv->name, icarus->cgminer_id,
 			timing_mode_str(info->timing_mode),
 			timing_mode_str(info->timing_mode),
-			info->read_time, info->Hs);
+			info->read_time, info->read_time_limit, info->Hs);
 }
 }
 
 
 static uint32_t mask(int work_division)
 static uint32_t mask(int work_division)
@@ -866,6 +908,7 @@ static int64_t icarus_scanhash(struct thr_info *thr, struct work *work,
 	int count;
 	int count;
 	double Hs, W, fullnonce;
 	double Hs, W, fullnonce;
 	int read_time;
 	int read_time;
+	bool limited;
 	int64_t estimate_hashes;
 	int64_t estimate_hashes;
 	uint32_t values;
 	uint32_t values;
 	int64_t hash_count_range;
 	int64_t hash_count_range;
@@ -967,7 +1010,9 @@ static int64_t icarus_scanhash(struct thr_info *thr, struct work *work,
 				elapsed.tv_sec, elapsed.tv_usec);
 				elapsed.tv_sec, elapsed.tv_usec);
 	}
 	}
 
 
-	// ignore possible end condition values ... and hw errors
+	// Ignore possible end condition values ... and hw errors
+	// TODO: set limitations on calculated values depending on the device
+	// to avoid crap values caused by CPU/Task Switching/Swapping/etc
 	if (info->do_icarus_timing
 	if (info->do_icarus_timing
 	&&  !was_hw_error
 	&&  !was_hw_error
 	&&  ((nonce & info->nonce_mask) > END_CONDITION)
 	&&  ((nonce & info->nonce_mask) > END_CONDITION)
@@ -1040,6 +1085,11 @@ static int64_t icarus_scanhash(struct thr_info *thr, struct work *work,
 
 
 			fullnonce = W + Hs * (((double)0xffffffff) + 1);
 			fullnonce = W + Hs * (((double)0xffffffff) + 1);
 			read_time = SECTOMS(fullnonce) - ICARUS_READ_REDUCE;
 			read_time = SECTOMS(fullnonce) - ICARUS_READ_REDUCE;
+			if (info->read_time_limit > 0 && read_time > info->read_time_limit) {
+				read_time = info->read_time_limit;
+				limited = true;
+			} else
+				limited = false;
 
 
 			info->Hs = Hs;
 			info->Hs = Hs;
 			info->read_time = read_time;
 			info->read_time = read_time;
@@ -1055,8 +1105,9 @@ static int64_t icarus_scanhash(struct thr_info *thr, struct work *work,
 			else if (info->timing_mode == MODE_SHORT)
 			else if (info->timing_mode == MODE_SHORT)
 				info->do_icarus_timing = false;
 				info->do_icarus_timing = false;
 
 
-			applog(LOG_WARNING, "%s%d Re-estimate: Hs=%e W=%e read_time=%dms fullnonce=%.3fs",
-					icarus->drv->name, icarus->device_id, Hs, W, read_time, fullnonce);
+			applog(LOG_WARNING, "%s%d Re-estimate: Hs=%e W=%e read_time=%dms%s fullnonce=%.3fs",
+					icarus->drv->name, icarus->device_id, Hs, W, read_time,
+					limited ? " (limited)" : "", fullnonce);
 		}
 		}
 		info->history_count++;
 		info->history_count++;
 		cgtime(&tv_history_finish);
 		cgtime(&tv_history_finish);
@@ -1078,6 +1129,7 @@ static struct api_data *icarus_api_stats(struct cgpu_info *cgpu)
 	// locking access to displaying API debug 'stats'
 	// locking access to displaying API debug 'stats'
 	// If locking becomes an issue for any of them, use copy_data=true also
 	// If locking becomes an issue for any of them, use copy_data=true also
 	root = api_add_int(root, "read_time", &(info->read_time), false);
 	root = api_add_int(root, "read_time", &(info->read_time), false);
+	root = api_add_int(root, "read_time_limit", &(info->read_time_limit), false);
 	root = api_add_double(root, "fullnonce", &(info->fullnonce), false);
 	root = api_add_double(root, "fullnonce", &(info->fullnonce), false);
 	root = api_add_int(root, "count", &(info->count), false);
 	root = api_add_int(root, "count", &(info->count), false);
 	root = api_add_hs(root, "Hs", &(info->Hs), false);
 	root = api_add_hs(root, "Hs", &(info->Hs), false);