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
            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)
 
 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
 'long' mode requires it to always be stable to ensure accuracy, however, over
 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
 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))
 
+// 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
 // 5 seconds allows for up to a ~840MH/s device
 #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_SHORT_STR = "short";
+static const char *MODE_SHORT_STREQ = "short=";
 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_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_limit = 0; // 0 = no limit
 
 	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->timing_mode = MODE_SHORT;
 		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) {
+		// long
 		info->read_count = ICARUS_READ_COUNT_TIMING;
 
 		info->timing_mode = MODE_LONG;
 		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) {
+		// ns[=read_count]
 		info->Hs = Hs / NANOSEC;
 		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;
 
-	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,
-		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)
@@ -917,6 +955,7 @@ static int64_t icarus_scanhash(struct thr_info *thr, struct work *work,
 	int count;
 	double Hs, W, fullnonce;
 	int read_count;
+	bool limited;
 	int64_t estimate_hashes;
 	uint32_t values;
 	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
 	&&  !was_hw_error
 	&&  ((nonce & info->nonce_mask) > END_CONDITION)
@@ -1197,6 +1238,11 @@ keepwaiting:
 
 			fullnonce = W + Hs * (((double)0xffffffff) + 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->read_count = read_count;
@@ -1212,10 +1258,11 @@ keepwaiting:
 			else if (info->timing_mode == MODE_SHORT)
 				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,
-					Hs, W, read_count, fullnonce);
+					Hs, W, read_count,
+					limited ? " (limited)" : "", fullnonce);
 		}
 		info->history_count++;
 		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'
 	// 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_limit", &(info->read_count_limit), false);
 	root = api_add_double(root, "fullnonce", &(info->fullnonce), false);
 	root = api_add_int(root, "count", &(info->count), 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
 	double Hs;
 	int read_count;
+	// ds limit for (short=/long=) read_count
+	int read_count_limit;
 
 	enum timing_mode timing_mode;
 	bool do_icarus_timing;