From ccee686aee321a4104f496ee91753105dfa3c57f Mon Sep 17 00:00:00 2001 From: Denis Ahrens Date: Sat, 22 Dec 2012 01:12:00 +0100 Subject: [PATCH 1/4] ztex: precheck the secondary solutions to avoid hw errors the ztex bitstreams gives back the latest checked nonce and its hash7 value and two possible solutions. every 250ms the latest nonce is checked and compared with hash7 to count hw errors and adapt the MHz value. one change is to use the solutions even if the latest nonce is not correct. the original java ztex code also does it this way. since the second solution is often not correct we have alot of hw errors. now we always check the second solution before we submit it to the cgminer main code. the java code also ignores all hw errors 500ms after a sendHash. we now do the same. this can possibly yield in a higher MHz rate. but the chance is so low nobody will ever notice in practice. --- driver-ztex.c | 96 +++++++++++++++++++++++---------------------------- libztex.c | 7 +++- 2 files changed, 50 insertions(+), 53 deletions(-) diff --git a/driver-ztex.c b/driver-ztex.c index 23aa97e4..de7011f3 100644 --- a/driver-ztex.c +++ b/driver-ztex.c @@ -146,9 +146,7 @@ static bool ztex_updateFreq(struct libztex_device* ztex) } -static bool ztex_checkNonce(struct libztex_device *ztex, - struct work *work, - struct libztex_hash_data *hdata) +static uint32_t ztex_checkNonce(struct work *work, uint32_t nonce) { uint32_t *data32 = (uint32_t *)(work->data); unsigned char swap[80]; @@ -158,31 +156,15 @@ static bool ztex_checkNonce(struct libztex_device *ztex, uint32_t *hash2_32 = (uint32_t *)hash2; int i; -#if defined(__BIGENDIAN__) || defined(MIPSEB) - hdata->nonce = swab32(hdata->nonce); - hdata->hash7 = swab32(hdata->hash7); -#endif + swap32[76/4] = htonl(nonce); - work->data[64 + 12 + 0] = (hdata->nonce >> 0) & 0xff; - work->data[64 + 12 + 1] = (hdata->nonce >> 8) & 0xff; - work->data[64 + 12 + 2] = (hdata->nonce >> 16) & 0xff; - work->data[64 + 12 + 3] = (hdata->nonce >> 24) & 0xff; - - for (i = 0; i < 80 / 4; i++) + for (i = 0; i < 76 / 4; i++) swap32[i] = swab32(data32[i]); sha2(swap, 80, hash1); sha2(hash1, 32, hash2); -#if defined(__BIGENDIAN__) || defined(MIPSEB) - if (hash2_32[7] != ((hdata->hash7 + 0x5be0cd19) & 0xFFFFFFFF)) { -#else - if (swab32(hash2_32[7]) != ((hdata->hash7 + 0x5be0cd19) & 0xFFFFFFFF)) { -#endif - ztex->errorCount[ztex->freqM] += 1.0 / ztex->numNonces; - applog(LOG_DEBUG, "%s: checkNonce failed for %0.8X", ztex->repr, hdata->nonce); - return false; - } - return true; + + return htonl(hash2_32[7]); } static int64_t ztex_scanhash(struct thr_info *thr, struct work *work, @@ -240,9 +222,11 @@ static int64_t ztex_scanhash(struct thr_info *thr, struct work *work, } overflow = false; + int count = 0; applog(LOG_DEBUG, "%s: entering poll loop", ztex->repr); while (!(overflow || thr->work_restart)) { + count++; nmsleep(250); if (thr->work_restart) { applog(LOG_DEBUG, "%s: New work detected", ztex->repr); @@ -274,12 +258,9 @@ static int64_t ztex_scanhash(struct thr_info *thr, struct work *work, ztex->errorCount[ztex->freqM] *= 0.995; ztex->errorWeight[ztex->freqM] = ztex->errorWeight[ztex->freqM] * 0.995 + 1.0; - + for (i = 0; i < ztex->numNonces; i++) { nonce = hdata[i].nonce; -#if defined(__BIGENDIAN__) || defined(MIPSEB) - nonce = swab32(nonce); -#endif if (nonce > noncecnt) noncecnt = nonce; if (((0xffffffff - nonce) < (nonce - lastnonce[i])) || nonce < lastnonce[i]) { @@ -287,36 +268,47 @@ static int64_t ztex_scanhash(struct thr_info *thr, struct work *work, overflow = true; } else lastnonce[i] = nonce; -#if !(defined(__BIGENDIAN__) || defined(MIPSEB)) - nonce = swab32(nonce); -#endif - if (!ztex_checkNonce(ztex, work, &hdata[i])) { - thr->cgpu->hw_errors++; - continue; + + if (ztex_checkNonce(work, nonce) != (hdata->hash7 + 0x5be0cd19)) { + applog(LOG_DEBUG, "%s: checkNonce failed for %0.8X", ztex->repr, nonce); + + // do not count errors in the first 500ms after sendHashData (2x250 wait time) + if (count > 2) { + ztex->errorCount[ztex->freqM] += 1.0 / ztex->numNonces; + thr->cgpu->hw_errors++; + } } + for (j=0; j<=ztex->extraSolutions; j++) { nonce = hdata[i].goldenNonce[j]; - if (nonce > 0) { - found = false; - for (k = 0; k < backlog_max; k++) { - if (backlog[k] == nonce) { - found = true; - break; - } - } - if (!found) { - applog(LOG_DEBUG, "%s: Share found N%dE%d", ztex->repr, i, j); - backlog[backlog_p++] = nonce; - if (backlog_p >= backlog_max) - backlog_p = 0; -#if defined(__BIGENDIAN__) || defined(MIPSEB) - nonce = swab32(nonce); -#endif - work->blk.nonce = 0xffffffff; - submit_nonce(thr, work, nonce); - applog(LOG_DEBUG, "%s: submitted %0.8x", ztex->repr, nonce); + + if (nonce == ztex->offsNonces) { + continue; + } + + // precheck the extraSolutions since they often fail + if (j > 0 && ztex_checkNonce(work, nonce) != 0) { + continue; + } + + found = false; + for (k = 0; k < backlog_max; k++) { + if (backlog[k] == nonce) { + found = true; + break; } } + if (!found) { + applog(LOG_DEBUG, "%s: Share found N%dE%d", ztex->repr, i, j); + backlog[backlog_p++] = nonce; + + if (backlog_p >= backlog_max) + backlog_p = 0; + + work->blk.nonce = 0xffffffff; + submit_nonce(thr, work, nonce); + applog(LOG_DEBUG, "%s: submitted %0.8x", ztex->repr, nonce); + } } } } diff --git a/libztex.c b/libztex.c index 71d62003..d33c5c59 100644 --- a/libztex.c +++ b/libztex.c @@ -878,11 +878,16 @@ int libztex_readHashData(struct libztex_device *ztex, struct libztex_hash_data n //applog(LOG_DEBUG, "W %d:0 %0.8x", i, nonces[i].goldenNonce[0]); memcpy((char*)&nonces[i].nonce, &rbuf[(i*bufsize)+4], 4); - nonces[i].nonce -= ztex->offsNonces; memcpy((char*)&nonces[i].hash7, &rbuf[(i*bufsize)+8], 4); + nonces[i].nonce = htole32(nonces[i].nonce); + nonces[i].hash7 = htole32(nonces[i].hash7); + + nonces[i].nonce -= ztex->offsNonces; + for (j=0; jextraSolutions; j++) { memcpy((char*)&nonces[i].goldenNonce[j+1], &rbuf[(i*bufsize)+12+(j*4)], 4); + nonces[i].goldenNonce[j+1] = htole32(nonces[i].goldenNonce[j+1]); nonces[i].goldenNonce[j+1] -= ztex->offsNonces; //applog(LOG_DEBUG, "W %d:%d %0.8x", i, j+1, nonces[i].goldenNonce[j+1]); } From f553c50b7beb13a52adc0f6e5741bd10bca95014 Mon Sep 17 00:00:00 2001 From: Denis Ahrens Date: Sat, 22 Dec 2012 01:22:42 +0100 Subject: [PATCH 2/4] ztex: if we had only errors in one round we do not count the errors to detect a totally non working fpga we only do that if the last round had some valid nonces. if we would count the errors the automatic megahertz adaption would drop and never recover. --- driver-ztex.c | 19 ++++++++++++++++++- libztex.c | 3 +++ libztex.h | 2 ++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/driver-ztex.c b/driver-ztex.c index de7011f3..41ee3b0c 100644 --- a/driver-ztex.c +++ b/driver-ztex.c @@ -223,6 +223,8 @@ static int64_t ztex_scanhash(struct thr_info *thr, struct work *work, overflow = false; int count = 0; + int validNonces = 0; + double errorCount = 0; applog(LOG_DEBUG, "%s: entering poll loop", ztex->repr); while (!(overflow || thr->work_restart)) { @@ -274,10 +276,13 @@ static int64_t ztex_scanhash(struct thr_info *thr, struct work *work, // do not count errors in the first 500ms after sendHashData (2x250 wait time) if (count > 2) { - ztex->errorCount[ztex->freqM] += 1.0 / ztex->numNonces; thr->cgpu->hw_errors++; + errorCount += (1.0 / ztex->numNonces); } } + else + validNonces++; + for (j=0; j<=ztex->extraSolutions; j++) { nonce = hdata[i].goldenNonce[j]; @@ -313,6 +318,18 @@ static int64_t ztex_scanhash(struct thr_info *thr, struct work *work, } } + // only add the errorCount if we had at least some valid nonces or + // had no valid nonces in the last round + if (ztex->nonceCheckValid > 0 && validNonces == 0) { + applog(LOG_ERR, "%s: resetting %.1f errors", ztex->repr, errorCount); + } + else { + ztex->errorCount[ztex->freqM] += errorCount; + } + + // remember the number of valid nonces for the check in the next round + ztex->nonceCheckValid = validNonces; + ztex->errorRate[ztex->freqM] = ztex->errorCount[ztex->freqM] / ztex->errorWeight[ztex->freqM] * (ztex->errorWeight[ztex->freqM] < 100? ztex->errorWeight[ztex->freqM] * 0.01: 1.0); if (ztex->errorRate[ztex->freqM] > ztex->maxErrorRate[ztex->freqM]) ztex->maxErrorRate[ztex->freqM] = ztex->errorRate[ztex->freqM]; diff --git a/libztex.c b/libztex.c index d33c5c59..b3dfbebe 100644 --- a/libztex.c +++ b/libztex.c @@ -701,6 +701,9 @@ int libztex_prepare_device(struct libusb_device *dev, struct libztex_device** zt newdev->maxErrorRate[cnt] = 0; } + // fake that the last round found something valid + newdev->nonceCheckValid = 1; + newdev->usbbus = libusb_get_bus_number(dev); newdev->usbaddress = libusb_get_device_address(dev); sprintf(newdev->repr, "ZTEX %s-1", newdev->snString); diff --git a/libztex.h b/libztex.h index ffd056ea..c1d09b60 100644 --- a/libztex.h +++ b/libztex.h @@ -73,6 +73,8 @@ struct libztex_device { double errorRate[256]; double maxErrorRate[256]; + int16_t nonceCheckValid; + int16_t numberOfFpgas; int selectedFpga; bool parallelConfigSupport; From 8be5da3d694985b4f0076ffcec8dcb069095c5e2 Mon Sep 17 00:00:00 2001 From: Denis Ahrens Date: Sat, 22 Dec 2012 17:47:10 +0100 Subject: [PATCH 3/4] driver-ztex: react to new work in 10ms and not 250ms --- driver-ztex.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/driver-ztex.c b/driver-ztex.c index 41ee3b0c..8ef2910b 100644 --- a/driver-ztex.c +++ b/driver-ztex.c @@ -229,11 +229,18 @@ static int64_t ztex_scanhash(struct thr_info *thr, struct work *work, applog(LOG_DEBUG, "%s: entering poll loop", ztex->repr); while (!(overflow || thr->work_restart)) { count++; - nmsleep(250); + + int sleepcount = 0; + while (thr->work_restart == 0 && sleepcount < 25) { + nmsleep(10); + sleepcount += 1; + } + if (thr->work_restart) { applog(LOG_DEBUG, "%s: New work detected", ztex->repr); break; } + ztex_selectFpga(ztex); i = libztex_readHashData(ztex, &hdata[0]); if (i < 0) { From f5306156f724ed75515a5aee9f8520b4ef7a89ee Mon Sep 17 00:00:00 2001 From: Denis Ahrens Date: Sat, 22 Dec 2012 21:39:40 +0100 Subject: [PATCH 4/4] driver-ztex: only reset errors if there are some Only check the errors and print the log message if there actually were errros. --- driver-ztex.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/driver-ztex.c b/driver-ztex.c index 8ef2910b..19ec066b 100644 --- a/driver-ztex.c +++ b/driver-ztex.c @@ -327,11 +327,13 @@ static int64_t ztex_scanhash(struct thr_info *thr, struct work *work, // only add the errorCount if we had at least some valid nonces or // had no valid nonces in the last round - if (ztex->nonceCheckValid > 0 && validNonces == 0) { - applog(LOG_ERR, "%s: resetting %.1f errors", ztex->repr, errorCount); - } - else { - ztex->errorCount[ztex->freqM] += errorCount; + if (errorCount > 0.0) { + if (ztex->nonceCheckValid > 0 && validNonces == 0) { + applog(LOG_ERR, "%s: resetting %.1f errors", ztex->repr, errorCount); + } + else { + ztex->errorCount[ztex->freqM] += errorCount; + } } // remember the number of valid nonces for the check in the next round