Browse Source

Merge commit '22ca87d' into cg_merges_20131023a

Conflicts:
	FPGA-README
	driver-icarus.c
Luke Dashjr 12 years ago
parent
commit
7cbd8a8328
3 changed files with 63 additions and 8 deletions
  1. 7 2
      README.FPGA
  2. 54 6
      driver-icarus.c
  3. 2 0
      icarus-common.h

+ 7 - 2
README.FPGA

@@ -162,8 +162,8 @@ an early CM1 Icarus copy bitstream)
 
 
 --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 separated values than Icarus devices, the last values
 If you define fewer comma separated values than Icarus devices, the last values
@@ -188,6 +188,11 @@ Any CPU delays while calculating the hash time will affect the result
 ~315 difficulty 1 shares
 ~315 difficulty 1 shares
 'long' mode requires it to always be stable to ensure accuracy, however, over
 'long' mode requires it to always be stable to ensure accuracy, however, over
 time it continually corrects itself
 time it continually corrects itself
+The optional additional =N for 'short' or 'long' specifies the limit to set the
+timeout to in deciseconds; thus if the timing code calculation is higher while
+running, it will instead use the limit
+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
 When in 'short' or 'long' mode, it will report the hash time value each time it
 is re-calculated
 is re-calculated

+ 54 - 6
driver-icarus.c

@@ -79,6 +79,13 @@ ASSERT1(sizeof(uint32_t) == 4);
 
 
 #define ICARUS_READ_TIME(baud) ((double)ICARUS_READ_SIZE * (double)8.0 / (double)(baud))
 #define ICARUS_READ_TIME(baud) ((double)ICARUS_READ_SIZE * (double)8.0 / (double)(baud))
 
 
+// Defined in deciseconds
+// 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_COUNT_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
 // 5 seconds allows for up to a ~840MH/s device
 // 5 seconds allows for up to a ~840MH/s device
 #define ICARUS_READ_COUNT_TIMING	(5 * TIME_FACTOR)
 #define ICARUS_READ_COUNT_TIMING	(5 * TIME_FACTOR)
@@ -134,7 +141,9 @@ static struct timeval history_sec = { HISTORY_SEC, 0 };
 
 
 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";
 
 
@@ -356,18 +365,46 @@ static void set_timing_mode(int this_option_offset, struct cgpu_info *icarus)
 	}
 	}
 
 
 	info->read_count = 0;
 	info->read_count = 0;
+	info->read_count_limit = 0; // 0 = no limit
 
 
 	if (strcasecmp(buf, MODE_SHORT_STR) == 0) {
 	if (strcasecmp(buf, MODE_SHORT_STR) == 0) {
+		// short
+		info->read_count = 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_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;
+
+		info->read_count_limit = atoi(&buf[strlen(MODE_SHORT_STREQ)]);
+		if (info->read_count_limit < 0)
+			info->read_count_limit = 0;
+		if (info->read_count_limit > ICARUS_READ_COUNT_LIMIT_MAX)
+			info->read_count_limit = ICARUS_READ_COUNT_LIMIT_MAX;
 	} else if (strcasecmp(buf, MODE_LONG_STR) == 0) {
 	} else if (strcasecmp(buf, MODE_LONG_STR) == 0) {
+		// long
 		info->read_count = ICARUS_READ_COUNT_TIMING;
 		info->read_count = 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_count = ICARUS_READ_COUNT_TIMING;
+
+		info->timing_mode = MODE_LONG;
+		info->do_icarus_timing = true;
+
+		info->read_count_limit = atoi(&buf[strlen(MODE_LONG_STREQ)]);
+		if (info->read_count_limit < 0)
+			info->read_count_limit = 0;
+		if (info->read_count_limit > ICARUS_READ_COUNT_LIMIT_MAX)
+			info->read_count_limit = ICARUS_READ_COUNT_LIMIT_MAX;
 	} else if ((Hs = atof(buf)) != 0) {
 	} else if ((Hs = atof(buf)) != 0) {
+		// ns[=read_count]
 		info->Hs = Hs / NANOSEC;
 		info->Hs = Hs / NANOSEC;
 		info->fullnonce = info->Hs * (((double)0xffffffff) + 1);
 		info->fullnonce = info->Hs * (((double)0xffffffff) + 1);
 
 
@@ -407,9 +444,10 @@ 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, "%"PRIpreprv": Init: mode=%s read_count=%d Hs=%e",
+	applog(LOG_DEBUG, "%"PRIpreprv": Init: mode=%s read_count=%d limit=%dms Hs=%e",
 		icarus->proc_repr,
 		icarus->proc_repr,
-		timing_mode_str(info->timing_mode), info->read_count, info->Hs);
+		timing_mode_str(info->timing_mode),
+		info->read_count, info->read_count_limit, info->Hs);
 }
 }
 
 
 static uint32_t mask(int work_division)
 static uint32_t mask(int work_division)
@@ -917,6 +955,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_count;
 	int read_count;
+	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;
@@ -1124,7 +1163,9 @@ keepwaiting:
 		}
 		}
 	}
 	}
 
 
-	// 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)
@@ -1197,6 +1238,11 @@ keepwaiting:
 
 
 			fullnonce = W + Hs * (((double)0xffffffff) + 1);
 			fullnonce = W + Hs * (((double)0xffffffff) + 1);
 			read_count = (int)(fullnonce * TIME_FACTOR) - 1;
 			read_count = (int)(fullnonce * TIME_FACTOR) - 1;
+			if (info->read_count_limit > 0 && read_count > info->read_count_limit) {
+				read_count = info->read_count_limit;
+				limited = true;
+			} else
+				limited = false;
 
 
 			info->Hs = Hs;
 			info->Hs = Hs;
 			info->read_count = read_count;
 			info->read_count = read_count;
@@ -1212,10 +1258,11 @@ keepwaiting:
 			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_DEBUG, "%"PRIpreprv" Re-estimate: read_count=%d fullnonce=%fs history count=%d Hs=%e W=%e values=%d hash range=0x%08lx min data count=%u", icarus->proc_repr, read_count, fullnonce, count, Hs, W, values, hash_count_range, info->min_data_count);
-			applog(LOG_DEBUG, "%"PRIpreprv" Re-estimate: Hs=%e W=%e read_count=%d fullnonce=%.3fs",
+//			applog(LOG_DEBUG, "%"PRIpreprv" Re-estimate: read_count=%d%s fullnonce=%fs history count=%d Hs=%e W=%e values=%d hash range=0x%08lx min data count=%u", icarus->proc_repr, read_count, limited ? " (limited)" : "", fullnonce, count, Hs, W, values, hash_count_range, info->min_data_count);
+			applog(LOG_DEBUG, "%"PRIpreprv" Re-estimate: Hs=%e W=%e read_count=%d%s fullnonce=%.3fs",
 					icarus->proc_repr,
 					icarus->proc_repr,
-					Hs, W, read_count, fullnonce);
+					Hs, W, read_count,
+					limited ? " (limited)" : "", fullnonce);
 		}
 		}
 		info->history_count++;
 		info->history_count++;
 		cgtime(&tv_history_finish);
 		cgtime(&tv_history_finish);
@@ -1241,6 +1288,7 @@ static struct api_data *icarus_drv_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_count", &(info->read_count), false);
 	root = api_add_int(root, "read_count", &(info->read_count), false);
+	root = api_add_int(root, "read_count_limit", &(info->read_count_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);

+ 2 - 0
icarus-common.h

@@ -60,6 +60,8 @@ struct ICARUS_INFO {
 	// seconds per Hash
 	// seconds per Hash
 	double Hs;
 	double Hs;
 	int read_count;
 	int read_count;
+	// ds limit for (short=/long=) read_count
+	int read_count_limit;
 
 
 	enum timing_mode timing_mode;
 	enum timing_mode timing_mode;
 	bool do_icarus_timing;
 	bool do_icarus_timing;