Browse Source

x6500: Try a more flexible approach to applying dynclock logic

Luke Dashjr 13 years ago
parent
commit
f482f59240
3 changed files with 15 additions and 8 deletions
  1. 9 6
      driver-x6500.c
  2. 4 2
      dynclock.c
  3. 2 0
      dynclock.h

+ 9 - 6
driver-x6500.c

@@ -375,6 +375,7 @@ static bool x6500_fpga_init(struct thr_info *thr)
 	thr->cgpu_data = fpga;
 
 	dclk_prepare(&fpga->dclk);
+	fpga->dclk.minGoodSamples = 3;
 	fpga->dclk.freqMaxM = X6500_MAXIMUM_CLOCK / 2;
 	x6500_change_clock(thr, X6500_DEFAULT_CLOCK / 2);
 	fpga->dclk.freqMDefault = fpga->dclk.freqM;
@@ -459,7 +460,6 @@ int64_t x6500_process_results(struct thr_info *thr, struct work *work)
 	int64_t hashes;
 	uint32_t nonce;
 	bool bad;
-	int imm_bad_nonces = 0, imm_nonces = 0;
 
 	while (1) {
 		mutex_lock(&x6500->device_mutex);
@@ -467,13 +467,14 @@ int64_t x6500_process_results(struct thr_info *thr, struct work *work)
 		nonce = x6500_get_register(jtag, 0xE);
 		mutex_unlock(&x6500->device_mutex);
 		if (nonce != 0xffffffff) {
-			++imm_nonces;
 			bad = !test_nonce(work, nonce, false);
 			if (!bad) {
 				submit_nonce(thr, work, nonce);
 				applog(LOG_DEBUG, "%s %u.%u: Nonce for current  work: %08lx",
 				       x6500->api->name, x6500->device_id, fpgaid,
 				       (unsigned long)nonce);
+
+				dclk_gotNonces(&fpga->dclk);
 			} else if (test_nonce(&fpga->prevwork, nonce, false)) {
 				submit_nonce(thr, &fpga->prevwork, nonce);
 				applog(LOG_DEBUG, "%s %u.%u: Nonce for PREVIOUS work: %08lx",
@@ -485,7 +486,9 @@ int64_t x6500_process_results(struct thr_info *thr, struct work *work)
 				       (unsigned long)nonce);
 				++hw_errors;
 				++x6500->hw_errors;
-				++imm_bad_nonces;
+
+				dclk_gotNonces(&fpga->dclk);
+				dclk_errorCount(&fpga->dclk, 1.);
 
 				// Purge buffers just in case of read/write desync
 				mutex_lock(&x6500->device_mutex);
@@ -493,6 +496,9 @@ int64_t x6500_process_results(struct thr_info *thr, struct work *work)
 				mutex_unlock(&x6500->device_mutex);
 				jtag->a->bufread = 0;
 			}
+			// Keep reading nonce buffer until it's empty
+			// This is necessary to avoid getting hw errors from Freq B after we've moved on to Freq A
+			continue;
 		}
 
 		hashes = calc_hashes(fpga, &tv_now);
@@ -504,9 +510,6 @@ int64_t x6500_process_results(struct thr_info *thr, struct work *work)
 			break;
 	}
 
-	dclk_gotNonces(&fpga->dclk);
-	if (imm_bad_nonces)
-		dclk_errorCount(&fpga->dclk, ((double)imm_bad_nonces) / (double)imm_nonces);
 	dclk_preUpdate(&fpga->dclk);
 	dclk_updateFreq(&fpga->dclk, x6500_dclk_change_clock, thr);
 

+ 4 - 2
dynclock.c

@@ -13,7 +13,9 @@
 
 void dclk_prepare(struct dclk_data *data)
 {
-	*data = (struct dclk_data){.freqM=0};
+	*data = (struct dclk_data){
+		.minGoodSamples = 150.,
+	};
 }
 
 void dclk_msg_freqchange(const char *repr, int oldFreq, int newFreq, const char *tail)
@@ -45,7 +47,7 @@ bool dclk_updateFreq(struct dclk_data *data, dclk_change_clock_func_t changecloc
 	maxM = 0;
 	while (maxM < freqMDefault && data->maxErrorRate[maxM + 1] < DCLK_MAXMAXERRORRATE)
 		maxM++;
-	while (maxM < data->freqMaxM && data->errorWeight[maxM] > 150 && data->maxErrorRate[maxM + 1] < DCLK_MAXMAXERRORRATE)
+	while (maxM < data->freqMaxM && data->maxErrorRate[maxM + 1] < DCLK_MAXMAXERRORRATE && data->errorWeight[maxM] >= data->minGoodSamples)
 		maxM++;
 
 	bestM = 0;

+ 2 - 0
dynclock.h

@@ -15,6 +15,8 @@ struct dclk_data {
 	uint8_t freqMaxM;
 	uint8_t freqMDefault;
 
+	uint8_t minGoodSamples;
+
 	double errorCount[256];
 	double errorWeight[256];
 	double errorRate[256];