Browse Source

Merge branch 'opt_sha256d' into bfgminer

Luke Dashjr 11 years ago
parent
commit
c46cd1a62f
24 changed files with 324 additions and 242 deletions
  1. 3 1
      Makefile.am
  2. 1 0
      api.c
  3. 48 3
      driver-cpu.c
  4. 27 72
      driver-opencl.c
  5. 18 4
      driver-opencl.h
  6. 5 4
      findnonce.c
  7. 1 1
      findnonce.h
  8. 50 0
      malgo/scrypt.c
  9. 6 0
      malgo/scrypt.h
  10. 112 0
      malgo/sha256d.c
  11. 4 84
      miner.c
  12. 9 2
      miner.h
  13. 31 13
      ocl.c
  14. 2 18
      ocl.h
  15. 1 1
      opencl/diablo.cl
  16. 1 1
      opencl/diakgcn.cl
  17. 1 1
      opencl/phatk.cl
  18. 1 1
      opencl/poclbm.cl
  19. 1 1
      opencl/psw.cl
  20. 1 1
      opencl/scrypt.cl
  21. 1 1
      opencl/zuikkis.cl
  22. 0 19
      scrypt.h
  23. 0 13
      util.c
  24. 0 1
      util.h

+ 3 - 1
Makefile.am

@@ -149,6 +149,8 @@ endif
 
 
 
 
 if USE_SHA256D
 if USE_SHA256D
+bfgminer_SOURCES += malgo/sha256d.c
+
 if USE_OPENCL
 if USE_OPENCL
 dist_kernels_DATA += \
 dist_kernels_DATA += \
 	$(top_srcdir)/opencl/diablo.cl  \
 	$(top_srcdir)/opencl/diablo.cl  \
@@ -195,7 +197,7 @@ endif # USE_CPUMINING
 endif # USE_SHA256D
 endif # USE_SHA256D
 
 
 if USE_SCRYPT
 if USE_SCRYPT
-bfgminer_SOURCES += scrypt.c scrypt.h
+bfgminer_SOURCES += malgo/scrypt.c malgo/scrypt.h
 dist_doc_DATA += README.scrypt
 dist_doc_DATA += README.scrypt
 
 
 if USE_OPENCL
 if USE_OPENCL

+ 1 - 0
api.c

@@ -3099,6 +3099,7 @@ static void minecoin(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __may
 				break;
 				break;
 #endif
 #endif
 			default:
 			default:
+				root = api_add_const(root, "Hash Method", goal->malgo->name, false);
 				break;
 				break;
 		}
 		}
 
 

+ 48 - 3
driver-cpu.c

@@ -761,6 +761,48 @@ static bool cpu_thread_init(struct thr_info *thr)
 	return true;
 	return true;
 }
 }
 
 
+static
+float cpu_min_nonce_diff(struct cgpu_info * const proc, const struct mining_algorithm * const malgo)
+{
+	return minimum_pdiff;
+}
+
+static
+bool scanhash_generic(struct thr_info * const thr, struct work * const work, const uint32_t max_nonce, uint32_t * const last_nonce, uint32_t n)
+{
+	struct mining_algorithm * const malgo = work_mining_algorithm(work);
+	void (* const hash_data_f)(void *, const void *) = malgo->hash_data_f;
+	uint8_t * const hash = work->hash;
+	uint8_t *data = work->data;
+	const uint8_t * const target = work->target;
+	uint32_t * const out_nonce = (uint32_t *)&data[0x4c];
+	bool ret = false;
+	
+	const uint32_t hash7_targ = le32toh(((const uint32_t *)target)[7]);
+	uint32_t * const hash7_tmp = &((uint32_t *)hash)[7];
+	
+	while (true)
+	{
+		*out_nonce = n;
+		
+		hash_data_f(hash, data);
+		
+		if (unlikely(le32toh(*hash7_tmp) <= hash7_targ))
+		{
+			ret = true;
+			break;
+		}
+
+		if ((n >= max_nonce) || thr->work_restart)
+			break;
+
+		n++;
+	}
+	
+	*last_nonce = n;
+	return ret;
+}
+
 static int64_t cpu_scanhash(struct thr_info *thr, struct work *work, int64_t max_nonce)
 static int64_t cpu_scanhash(struct thr_info *thr, struct work *work, int64_t max_nonce)
 {
 {
 	uint32_t first_nonce = work->blk.nonce;
 	uint32_t first_nonce = work->blk.nonce;
@@ -773,7 +815,7 @@ CPUSearch:
 
 
 	/* scan nonces for a proof-of-work hash */
 	/* scan nonces for a proof-of-work hash */
 	{
 	{
-		sha256_func func = NULL;
+		sha256_func func = scanhash_generic;
 		switch (work_mining_algorithm(work)->algo)
 		switch (work_mining_algorithm(work)->algo)
 		{
 		{
 #ifdef USE_SCRYPT
 #ifdef USE_SCRYPT
@@ -783,9 +825,12 @@ CPUSearch:
 #endif
 #endif
 #ifdef USE_SHA256D
 #ifdef USE_SHA256D
 			case POW_SHA256D:
 			case POW_SHA256D:
-				func = sha256_funcs[opt_algo];
+				if (work->nonce_diff >= 1.)
+					func = sha256_funcs[opt_algo];
 				break;
 				break;
 #endif
 #endif
+			default:
+				break;
 		}
 		}
 		if (unlikely(!func))
 		if (unlikely(!func))
 			applogr(0, LOG_ERR, "%"PRIpreprv": Unknown mining algorithm", thr->cgpu->proc_repr);
 			applogr(0, LOG_ERR, "%"PRIpreprv": Unknown mining algorithm", thr->cgpu->proc_repr);
@@ -817,7 +862,7 @@ struct device_drv cpu_drv = {
 	.dname = "cpu",
 	.dname = "cpu",
 	.name = "CPU",
 	.name = "CPU",
 	.probe_priority = 120,
 	.probe_priority = 120,
-	.drv_min_nonce_diff = common_sha256d_and_scrypt_min_nonce_diff,
+	.drv_min_nonce_diff = cpu_min_nonce_diff,
 	.drv_detect = cpu_detect,
 	.drv_detect = cpu_detect,
 	.thread_prepare = cpu_thread_prepare,
 	.thread_prepare = cpu_thread_prepare,
 	.can_limit_work = cpu_can_limit_work,
 	.can_limit_work = cpu_can_limit_work,

+ 27 - 72
driver-opencl.c

@@ -403,27 +403,17 @@ bool _set_kernel(struct cgpu_info * const cgpu, const char *_val)
 	
 	
 	int dummy_srclen;
 	int dummy_srclen;
 	enum cl_kernels interface;
 	enum cl_kernels interface;
-	char *src = opencl_kernel_source(filename, &dummy_srclen, &interface);
+	struct mining_algorithm *malgo;
+	char *src = opencl_kernel_source(filename, &dummy_srclen, &interface, &malgo);
 	if (!src)
 	if (!src)
 		return false;
 		return false;
 	free(src);
 	free(src);
-	
-	char **kfp =
-#ifdef USE_SHA256D
-		&data->kernel_file_sha256d;
-#else
-		NULL;
-#endif
-#ifdef USE_SCRYPT
-	if (interface == KL_SCRYPT)
-		kfp = &data->kernel_file_scrypt;
-#endif
-#ifndef USE_SHA256D
-	if (!kfp)
+	if (!malgo)
 		return false;
 		return false;
-#endif
-	free(*kfp);
-	*kfp = strdup(_val);
+	
+	struct opencl_kernel_info * const kernelinfo = &data->kernelinfo[malgo->algo];
+	free(kernelinfo->file);
+	kernelinfo->file = strdup(_val);
 	
 	
 	return true;
 	return true;
 }
 }
@@ -1665,6 +1655,12 @@ static bool opencl_thread_init(struct thr_info *thr)
 	return true;
 	return true;
 }
 }
 
 
+static
+float opencl_min_nonce_diff(struct cgpu_info * const proc, const struct mining_algorithm * const malgo)
+{
+	return malgo->opencl_min_nonce_diff ?: -1.;
+}
+
 #ifdef USE_SHA256D
 #ifdef USE_SHA256D
 static bool opencl_prepare_work(struct thr_info __maybe_unused *thr, struct work *work)
 static bool opencl_prepare_work(struct thr_info __maybe_unused *thr, struct work *work)
 {
 {
@@ -1684,61 +1680,16 @@ const struct opencl_kernel_info *opencl_scanhash_get_kernel(struct cgpu_info * c
 {
 {
 	struct opencl_device_data * const data = cgpu->device_data;
 	struct opencl_device_data * const data = cgpu->device_data;
 	struct opencl_kernel_info *kernelinfo = NULL;
 	struct opencl_kernel_info *kernelinfo = NULL;
-	char *kernel_file;
-	switch (malgo->algo)
+	kernelinfo = &data->kernelinfo[malgo->algo];
+	if (!kernelinfo->file)
 	{
 	{
-#ifdef USE_SHA256D
-		case POW_SHA256D:
-			kernelinfo = &clState->kernel_sha256d;
-			if (!data->kernel_file_sha256d)
-			{
-				const char * const vbuff = clState->platform_ver_str;
-				if (clState->is_mesa)
-				{
-					applog(LOG_INFO, "Selecting phatk kernel for Mesa");
-					data->kernel_file_sha256d = strdup("phatk");
-				}
-				else  /* Detect all 2.6 SDKs not with Tahiti and use diablo kernel */
-				if (!strstr(cgpu->name, "Tahiti") &&
-				   (strstr(vbuff, "844.4") ||  // Linux 64 bit ATI 2.6 SDK
-				    strstr(vbuff, "851.4") ||  // Windows 64 bit ""
-				    strstr(vbuff, "831.4") ||
-				    strstr(vbuff, "898.1") ||  // 12.2 driver SDK 
-				    strstr(vbuff, "923.1") ||  // 12.4
-				    strstr(vbuff, "938.2") ||  // SDK 2.7
-				    strstr(vbuff, "1113.2")))  // SDK 2.8
-				{
-					applog(LOG_INFO, "Selecting diablo kernel");
-					data->kernel_file_sha256d = strdup("diablo");
-				}
-				else  /* Detect all 7970s, older ATI and NVIDIA and use poclbm */
-				if (strstr(cgpu->name, "Tahiti") || !clState->hasBitAlign)
-				{
-					applog(LOG_INFO, "Selecting poclbm kernel");
-					data->kernel_file_sha256d = strdup("poclbm");
-				}
-				else  /* Use phatk for the rest R5xxx R6xxx */
-				{
-					applog(LOG_INFO, "Selecting phatk kernel");
-					data->kernel_file_sha256d = strdup("phatk");
-				}
-			}
-			kernel_file = data->kernel_file_sha256d;
-			break;
-#endif
-#ifdef USE_SCRYPT
-		case POW_SCRYPT:
-			kernelinfo = &clState->kernel_scrypt;
-			BFGINIT(data->kernel_file_scrypt, strdup("scrypt"));
-			kernel_file = data->kernel_file_scrypt;
-			break;
-#endif
+		kernelinfo->file = malgo->opencl_get_default_kernel_file(malgo, cgpu, clState);
+		if (!kernelinfo->file)
+			applogr(NULL, LOG_ERR, "%s: Unsupported mining algorithm", cgpu->dev_repr);
 	}
 	}
-	if (!kernelinfo)
-		applogr(NULL, LOG_ERR, "%s: Unsupported mining algorithm", cgpu->dev_repr);
 	if (!kernelinfo->loaded)
 	if (!kernelinfo->loaded)
 	{
 	{
-		if (!opencl_load_kernel(cgpu, clState, cgpu->name, kernelinfo, kernel_file, malgo))
+		if (!opencl_load_kernel(cgpu, clState, cgpu->name, kernelinfo, kernelinfo->file, malgo))
 			applogr(NULL, LOG_ERR, "%s: Failed to load kernel", cgpu->dev_repr);
 			applogr(NULL, LOG_ERR, "%s: Failed to load kernel", cgpu->dev_repr);
 		
 		
 		kernelinfo->queue_kernel_parameters = kernel_interfaces[kernelinfo->interface].queue_kernel_parameters_func;
 		kernelinfo->queue_kernel_parameters = kernel_interfaces[kernelinfo->interface].queue_kernel_parameters_func;
@@ -1856,7 +1807,7 @@ static int64_t opencl_scanhash(struct thr_info *thr, struct work *work,
 			return -1;
 			return -1;
 		}
 		}
 		applog(LOG_DEBUG, "GPU %d found something?", gpu->device_id);
 		applog(LOG_DEBUG, "GPU %d found something?", gpu->device_id);
-		postcalc_hash_async(thr, work, thrdata->res);
+		postcalc_hash_async(thr, work, thrdata->res, kinfo->interface);
 		memset(thrdata->res, 0, buffersize);
 		memset(thrdata->res, 0, buffersize);
 		/* This finish flushes the writebuffer set with CL_FALSE in clEnqueueWriteBuffer */
 		/* This finish flushes the writebuffer set with CL_FALSE in clEnqueueWriteBuffer */
 		clFinish(clState->commandQueue);
 		clFinish(clState->commandQueue);
@@ -1874,11 +1825,15 @@ void opencl_clean_kernel_info(struct opencl_kernel_info * const kinfo)
 
 
 static void opencl_thread_shutdown(struct thr_info *thr)
 static void opencl_thread_shutdown(struct thr_info *thr)
 {
 {
+	struct cgpu_info * const cgpu = thr->cgpu;
+	struct opencl_device_data * const data = cgpu->device_data;
 	const int thr_id = thr->id;
 	const int thr_id = thr->id;
 	_clState *clState = clStates[thr_id];
 	_clState *clState = clStates[thr_id];
 
 
-	opencl_clean_kernel_info(&clState->kernel_sha256d);
-	opencl_clean_kernel_info(&clState->kernel_scrypt);
+	for (unsigned i = 0; i < (unsigned)POW_ALGORITHM_COUNT; ++i)
+	{
+		opencl_clean_kernel_info(&data->kernelinfo[i]);
+	}
 	clReleaseCommandQueue(clState->commandQueue);
 	clReleaseCommandQueue(clState->commandQueue);
 	clReleaseContext(clState->context);
 	clReleaseContext(clState->context);
 }
 }
@@ -1943,7 +1898,7 @@ struct device_drv opencl_api = {
 	.dname = "opencl",
 	.dname = "opencl",
 	.name = "OCL",
 	.name = "OCL",
 	.probe_priority = 110,
 	.probe_priority = 110,
-	.drv_min_nonce_diff = common_sha256d_and_scrypt_min_nonce_diff,
+	.drv_min_nonce_diff = opencl_min_nonce_diff,
 	.drv_detect = opencl_detect,
 	.drv_detect = opencl_detect,
 	.reinit_device = reinit_opencl_device,
 	.reinit_device = reinit_opencl_device,
 	.watchdog = opencl_watchdog,
 	.watchdog = opencl_watchdog,

+ 18 - 4
driver-opencl.h

@@ -21,6 +21,22 @@ enum opencl_binary_usage {
 
 
 static const float intensity_not_set = FLT_MAX;
 static const float intensity_not_set = FLT_MAX;
 
 
+struct opencl_kernel_info;
+struct _clState;
+
+typedef cl_int (*queue_kernel_parameters_func_t)(const struct opencl_kernel_info *, struct _clState *, struct work *, cl_uint);
+
+struct opencl_kernel_info {
+	char *file;
+	bool loaded;
+	cl_program program;
+	cl_kernel kernel;
+	bool goffset;
+	enum cl_kernels interface;
+	size_t wsize;
+	queue_kernel_parameters_func_t queue_kernel_parameters;
+};
+
 struct opencl_device_data {
 struct opencl_device_data {
 	bool mapped;
 	bool mapped;
 	int virtual_gpu;
 	int virtual_gpu;
@@ -32,14 +48,12 @@ struct opencl_device_data {
 	
 	
 	cl_uint vwidth;
 	cl_uint vwidth;
 	size_t work_size;
 	size_t work_size;
-#ifdef USE_SHA256D
-	char *kernel_file_sha256d;
-#endif
 	cl_ulong max_alloc;
 	cl_ulong max_alloc;
 	
 	
+	struct opencl_kernel_info kernelinfo[POW_ALGORITHM_COUNT];
+	
 	enum opencl_binary_usage opt_opencl_binaries;
 	enum opencl_binary_usage opt_opencl_binaries;
 #ifdef USE_SCRYPT
 #ifdef USE_SCRYPT
-	char *kernel_file_scrypt;
 	int lookup_gap;
 	int lookup_gap;
 	size_t thread_concurrency;
 	size_t thread_concurrency;
 	size_t shaders;
 	size_t shaders;

+ 5 - 4
findnonce.c

@@ -19,7 +19,6 @@
 
 
 #include "findnonce.h"
 #include "findnonce.h"
 #include "miner.h"
 #include "miner.h"
-#include "scrypt.h"
 
 
 #ifdef USE_SHA256D
 #ifdef USE_SHA256D
 const uint32_t SHA256_K[64] = {
 const uint32_t SHA256_K[64] = {
@@ -141,6 +140,7 @@ struct pc_data {
 	uint32_t res[OPENCL_MAX_BUFFERSIZE];
 	uint32_t res[OPENCL_MAX_BUFFERSIZE];
 	pthread_t pth;
 	pthread_t pth;
 	int found;
 	int found;
+	enum cl_kernels kinterface;
 };
 };
 
 
 static void *postcalc_hash(void *userdata)
 static void *postcalc_hash(void *userdata)
@@ -150,7 +150,7 @@ static void *postcalc_hash(void *userdata)
 	unsigned int entry = 0;
 	unsigned int entry = 0;
 	int found = FOUND;
 	int found = FOUND;
 #ifdef USE_SCRYPT
 #ifdef USE_SCRYPT
-	if (work_mining_algorithm(&pcd->work)->algo == POW_SCRYPT)
+	if (pcd->kinterface == KL_SCRYPT)
 		found = SCRYPT_FOUND;
 		found = SCRYPT_FOUND;
 #endif
 #endif
 
 
@@ -179,7 +179,7 @@ static void *postcalc_hash(void *userdata)
 	return NULL;
 	return NULL;
 }
 }
 
 
-void postcalc_hash_async(struct thr_info *thr, struct work *work, uint32_t *res)
+void postcalc_hash_async(struct thr_info * const thr, struct work * const work, uint32_t * const res, const enum cl_kernels kinterface)
 {
 {
 	struct pc_data *pcd = malloc(sizeof(struct pc_data));
 	struct pc_data *pcd = malloc(sizeof(struct pc_data));
 	int buffersize;
 	int buffersize;
@@ -191,10 +191,11 @@ void postcalc_hash_async(struct thr_info *thr, struct work *work, uint32_t *res)
 
 
 	*pcd = (struct pc_data){
 	*pcd = (struct pc_data){
 		.thr = thr,
 		.thr = thr,
+		.kinterface = kinterface,
 	};
 	};
 	__copy_work(&pcd->work, work);
 	__copy_work(&pcd->work, work);
 #ifdef USE_SCRYPT
 #ifdef USE_SCRYPT
-	if (work_mining_algorithm(work)->algo == POW_SCRYPT)
+	if (kinterface == KL_SCRYPT)
 		buffersize = SCRYPT_BUFFERSIZE;
 		buffersize = SCRYPT_BUFFERSIZE;
 	else
 	else
 #endif
 #endif

+ 1 - 1
findnonce.h

@@ -25,6 +25,6 @@
 #ifdef USE_SHA256D
 #ifdef USE_SHA256D
 extern void precalc_hash(struct opencl_work_data *blk, uint32_t *state, uint32_t *data);
 extern void precalc_hash(struct opencl_work_data *blk, uint32_t *state, uint32_t *data);
 #endif
 #endif
-extern void postcalc_hash_async(struct thr_info *thr, struct work *work, uint32_t *res);
+extern void postcalc_hash_async(struct thr_info *thr, struct work *work, uint32_t *res, enum cl_kernels);
 
 
 #endif /*__FINDNONCE_H__*/
 #endif /*__FINDNONCE_H__*/

+ 50 - 0
scrypt.c → malgo/scrypt.c

@@ -32,11 +32,14 @@
 #include "config.h"
 #include "config.h"
 #include "miner.h"
 #include "miner.h"
 
 
+#include <math.h>
 #include <stdlib.h>
 #include <stdlib.h>
 #include <stdbool.h>
 #include <stdbool.h>
 #include <stdint.h>
 #include <stdint.h>
 #include <string.h>
 #include <string.h>
 
 
+#include <uthash.h>
+
 typedef struct SHA256Context {
 typedef struct SHA256Context {
 	uint32_t state[8];
 	uint32_t state[8];
 	uint32_t buf[16];
 	uint32_t buf[16];
@@ -546,3 +549,50 @@ bool scanhash_scrypt(struct thr_info * const thr, struct work * const work,
 	free(scratchbuf);
 	free(scratchbuf);
 	return ret;
 	return ret;
 }
 }
+
+#ifdef USE_OPENCL
+static
+float opencl_oclthreads_to_intensity_scrypt(const unsigned long oclthreads)
+{
+	return log2(oclthreads);
+}
+
+static
+unsigned long opencl_intensity_to_oclthreads_scrypt(float intensity)
+{
+	return pow(2, intensity);
+}
+
+static
+char *opencl_get_default_kernel_file_scrypt(const struct mining_algorithm * const malgo, struct cgpu_info * const cgpu, struct _clState * const clState)
+{
+	return strdup("scrypt");
+}
+#endif
+
+struct mining_algorithm malgo_scrypt = {
+	.name = "scrypt",
+	.aliases = "scrypt",
+	
+	.algo = POW_SCRYPT,
+	.ui_skip_hash_bytes = 2,
+	.reasonable_low_nonce_diff = 1./0x10000,
+	
+	.hash_data_f = scrypt_hash_data,
+	
+#ifdef USE_OPENCL
+	.opencl_oclthreads_to_intensity = opencl_oclthreads_to_intensity_scrypt,
+	.opencl_intensity_to_oclthreads = opencl_intensity_to_oclthreads_scrypt,
+	.opencl_min_oclthreads =      0x100,  // intensity   8
+	.opencl_max_oclthreads = 0x20000000,  // intensity  31
+	.opencl_min_nonce_diff = 1./0x10000,
+	.opencl_get_default_kernel_file = opencl_get_default_kernel_file_scrypt,
+#endif
+};
+
+static
+__attribute__((constructor))
+void init_scrypt(void)
+{
+	LL_APPEND(mining_algorithms, (&malgo_scrypt));
+}

+ 6 - 0
malgo/scrypt.h

@@ -0,0 +1,6 @@
+#ifndef SCRYPT_H
+#define SCRYPT_H
+
+extern void test_scrypt(void);
+
+#endif /* SCRYPT_H */

+ 112 - 0
malgo/sha256d.c

@@ -0,0 +1,112 @@
+/*
+ * Copyright 2012-2014 Luke Dashjr
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 3 of the License, or (at your option)
+ * any later version.  See COPYING for more details.
+ */
+
+#include "config.h"
+
+#include <math.h>
+#include <string.h>
+
+#include <uthash.h>
+
+#include "logging.h"
+#include "miner.h"
+#include "ocl.h"
+#include "util.h"
+
+static
+void hash_data(void *out_hash, const void *data)
+{
+	unsigned char blkheader[80];
+	
+	// data is past the first SHA256 step (padding and interpreting as big endian on a little endian platform), so we need to flip each 32-bit chunk around to get the original input block header
+	swap32yes(blkheader, data, 80 / 4);
+	
+	// double-SHA256 to get the block hash
+	gen_hash(blkheader, out_hash, 80);
+}
+
+#ifdef USE_OPENCL
+float opencl_oclthreads_to_intensity_sha256d(const unsigned long oclthreads)
+{
+	return log2f(oclthreads) - 15.;
+}
+
+unsigned long opencl_intensity_to_oclthreads_sha256d(float intensity)
+{
+	return powf(2, intensity + 15);
+}
+
+static
+char *opencl_get_default_kernel_file_sha256d(const struct mining_algorithm * const malgo, struct cgpu_info * const cgpu, struct _clState * const clState)
+{
+	const char * const vbuff = clState->platform_ver_str;
+	
+	if (clState->is_mesa)
+	{
+		applog(LOG_INFO, "Selecting phatk kernel for Mesa");
+		return strdup("phatk");
+	}
+	
+	/* Detect all 2.6 SDKs not with Tahiti and use diablo kernel */
+	if (!strstr(cgpu->name, "Tahiti") &&
+	   (strstr(vbuff, "844.4") ||  // Linux 64 bit ATI 2.6 SDK
+	    strstr(vbuff, "851.4") ||  // Windows 64 bit ""
+	    strstr(vbuff, "831.4") ||
+	    strstr(vbuff, "898.1") ||  // 12.2 driver SDK
+	    strstr(vbuff, "923.1") ||  // 12.4
+	    strstr(vbuff, "938.2") ||  // SDK 2.7
+	    strstr(vbuff, "1113.2")))  // SDK 2.8
+	{
+		applog(LOG_INFO, "Selecting diablo kernel");
+		return strdup("diablo");
+	}
+	
+	/* Detect all 7970s, older ATI and NVIDIA and use poclbm */
+	if (strstr(cgpu->name, "Tahiti") || !clState->hasBitAlign)
+	{
+		applog(LOG_INFO, "Selecting poclbm kernel");
+		return strdup("poclbm");
+	}
+	
+	/* Use phatk for the rest R5xxx R6xxx */
+	{
+		applog(LOG_INFO, "Selecting phatk kernel");
+		return strdup("phatk");
+	}
+}
+#endif  /* USE_OPENCL */
+
+struct mining_algorithm malgo_sha256d = {
+	.name = "SHA256d",
+	.aliases = "SHA256d|SHA256|SHA2",
+	
+	.algo = POW_SHA256D,
+	.ui_skip_hash_bytes = 4,
+	.worktime_skip_prevblk_u32 = 1,
+	.reasonable_low_nonce_diff = 1.,
+	
+	.hash_data_f = hash_data,
+	
+#ifdef USE_OPENCL
+	.opencl_nodefault = true,
+	.opencl_oclthreads_to_intensity = opencl_oclthreads_to_intensity_sha256d,
+	.opencl_intensity_to_oclthreads = opencl_intensity_to_oclthreads_sha256d,
+	.opencl_min_oclthreads =       0x20,  // intensity -10
+	.opencl_max_oclthreads = 0x20000000,  // intensity  14
+	.opencl_min_nonce_diff = 1.,
+	.opencl_get_default_kernel_file = opencl_get_default_kernel_file_sha256d,
+#endif
+};
+
+static
+__attribute__((constructor))
+void init_sha256d(void)
+{
+    LL_APPEND(mining_algorithms, (&malgo_sha256d));
+}

+ 4 - 84
miner.c

@@ -80,7 +80,6 @@
 #include "adl.h"
 #include "adl.h"
 #include "driver-cpu.h"
 #include "driver-cpu.h"
 #include "driver-opencl.h"
 #include "driver-opencl.h"
-#include "scrypt.h"
 #include "util.h"
 #include "util.h"
 
 
 #ifdef USE_AVALON
 #ifdef USE_AVALON
@@ -98,7 +97,7 @@
 #endif
 #endif
 
 
 #ifdef USE_SCRYPT
 #ifdef USE_SCRYPT
-#include "scrypt.h"
+#include "malgo/scrypt.h"
 #endif
 #endif
 
 
 #include "version.h"
 #include "version.h"
@@ -1033,76 +1032,8 @@ struct mining_algorithm *mining_algorithm_by_alias(const char * const alias)
 	return NULL;
 	return NULL;
 }
 }
 
 
-
-#if defined(USE_SHA256D) && defined(USE_OPENCL)
-static
-float opencl_oclthreads_to_intensity_sha256d(const unsigned long oclthreads)
-{
-	return log2f(oclthreads) - 15.;
-}
-
-static
-unsigned long opencl_intensity_to_oclthreads_sha256d(float intensity)
-{
-	return powf(2, intensity + 15);
-}
-#endif
-
-#ifdef USE_SHA256D
-static struct mining_algorithm malgo_sha256d = {
-	.name = "SHA256d",
-	.aliases = "SHA256d|SHA256|SHA2",
-	
-	.algo = POW_SHA256D,
-	.ui_skip_hash_bytes = 4,
-	.worktime_skip_prevblk_u32 = 1,
-	.reasonable_low_nonce_diff = 1.,
-	
-	.hash_data_f = hash_data,
-	
-#ifdef USE_OPENCL
-	.opencl_nodefault = true,
-	.opencl_oclthreads_to_intensity = opencl_oclthreads_to_intensity_sha256d,
-	.opencl_intensity_to_oclthreads = opencl_intensity_to_oclthreads_sha256d,
-	.opencl_min_oclthreads =       0x20,  // intensity -10
-	.opencl_max_oclthreads = 0x20000000,  // intensity  14
-#endif
-};
-#endif
-
-
 #ifdef USE_SCRYPT
 #ifdef USE_SCRYPT
-#ifdef USE_OPENCL
-static
-float opencl_oclthreads_to_intensity_scrypt(const unsigned long oclthreads)
-{
-	return log2(oclthreads);
-}
-
-static
-unsigned long opencl_intensity_to_oclthreads_scrypt(float intensity)
-{
-	return pow(2, intensity);
-}
-#endif
-
-static struct mining_algorithm malgo_scrypt = {
-	.name = "scrypt",
-	.aliases = "scrypt",
-	
-	.algo = POW_SCRYPT,
-	.ui_skip_hash_bytes = 2,
-	.reasonable_low_nonce_diff = 1./0x10000,
-	
-	.hash_data_f = scrypt_hash_data,
-	
-#ifdef USE_OPENCL
-	.opencl_oclthreads_to_intensity = opencl_oclthreads_to_intensity_scrypt,
-	.opencl_intensity_to_oclthreads = opencl_intensity_to_oclthreads_scrypt,
-	.opencl_min_oclthreads =      0x100,  // intensity   8
-	.opencl_max_oclthreads = 0x20000000,  // intensity  31
-#endif
-};
+extern struct mining_algorithm malgo_scrypt;
 
 
 static
 static
 const char *set_malgo_scrypt()
 const char *set_malgo_scrypt()
@@ -1110,21 +1041,8 @@ const char *set_malgo_scrypt()
 	goal_set_malgo(get_mining_goal("default"), &malgo_scrypt);
 	goal_set_malgo(get_mining_goal("default"), &malgo_scrypt);
 	return NULL;
 	return NULL;
 }
 }
-
 #endif
 #endif
 
 
-static
-__attribute__((constructor))
-void init_mining_goals(struct mining_goal_info * const goal, const struct mining_algorithm * const malgo)
-{
-#ifdef USE_SHA256D
-	LL_APPEND(mining_algorithms, (&malgo_sha256d));
-#endif
-#ifdef USE_SCRYPT
-	LL_APPEND(mining_algorithms, (&malgo_scrypt));
-#endif
-}
-
 static
 static
 int mining_goals_name_cmp(const struct mining_goal_info * const a, const struct mining_goal_info * const b)
 int mining_goals_name_cmp(const struct mining_goal_info * const a, const struct mining_goal_info * const b)
 {
 {
@@ -1145,6 +1063,8 @@ void blkchain_init_block(struct blockchain_info * const blkchain)
 	blkchain->currentblk = dummy_block;
 	blkchain->currentblk = dummy_block;
 }
 }
 
 
+extern struct mining_algorithm malgo_sha256d;
+
 struct mining_goal_info *get_mining_goal(const char * const name)
 struct mining_goal_info *get_mining_goal(const char * const name)
 {
 {
 	static unsigned next_goal_id;
 	static unsigned next_goal_id;

+ 9 - 2
miner.h

@@ -278,11 +278,12 @@ struct gpu_adl {
 
 
 enum pow_algorithm {
 enum pow_algorithm {
 #ifdef USE_SHA256D
 #ifdef USE_SHA256D
-	POW_SHA256D = 1,
+	POW_SHA256D,
 #endif
 #endif
 #ifdef USE_SCRYPT
 #ifdef USE_SCRYPT
-	POW_SCRYPT  = 2,
+	POW_SCRYPT,
 #endif
 #endif
+	POW_ALGORITHM_COUNT,
 };
 };
 
 
 struct api_data;
 struct api_data;
@@ -1123,6 +1124,10 @@ struct blockchain_info {
 	char currentblk_first_seen_time_str[0x20];  // was global blocktime
 	char currentblk_first_seen_time_str[0x20];  // was global blocktime
 };
 };
 
 
+struct _clState;
+struct cgpu_info;
+struct mining_algorithm;
+
 struct mining_algorithm {
 struct mining_algorithm {
 	const char *name;
 	const char *name;
 	const char *aliases;
 	const char *aliases;
@@ -1146,6 +1151,8 @@ struct mining_algorithm {
 	unsigned long (*opencl_intensity_to_oclthreads)(float intensity);
 	unsigned long (*opencl_intensity_to_oclthreads)(float intensity);
 	unsigned long opencl_min_oclthreads;
 	unsigned long opencl_min_oclthreads;
 	unsigned long opencl_max_oclthreads;
 	unsigned long opencl_max_oclthreads;
+	float opencl_min_nonce_diff;
+	char *(*opencl_get_default_kernel_file)(const struct mining_algorithm *, struct cgpu_info *, struct _clState *);
 #endif
 #endif
 };
 };
 
 

+ 31 - 13
ocl.c

@@ -258,24 +258,42 @@ char *file_contents(const char *filename, int *length)
 	return (char*)buffer;
 	return (char*)buffer;
 }
 }
 
 
-char *opencl_kernel_source(const char * const filename, int * const out_sourcelen, enum cl_kernels * const out_kinterface)
+static
+void extract_word(char * const buf, const size_t bufsz, const char ** const endptr, const char *s)
+{
+	const char *q;
+	for ( ; s[0] && isspace(s[0]); ++s)
+		if (s[0] == '\n' || s[0] == '\r')
+			break;
+	for (q = s; q[0] && !isspace(q[0]); ++q)
+	{}  // Find end of string
+	size_t len = q - s;
+	if (len >= bufsz)
+		len = bufsz - 1;
+	memcpy(buf, s, len);
+	buf[len] = '\0';
+	if (endptr)
+		*endptr = q;
+}
+
+char *opencl_kernel_source(const char * const filename, int * const out_sourcelen, enum cl_kernels * const out_kinterface, struct mining_algorithm ** const out_malgo)
 {
 {
 	char *source = file_contents(filename, out_sourcelen);
 	char *source = file_contents(filename, out_sourcelen);
 	if (!source)
 	if (!source)
 		return NULL;
 		return NULL;
-	char *s = strstr(source, "kernel-interface:"), *q;
+	char *s = strstr(source, "kernel-interface:");
 	if (s)
 	if (s)
 	{
 	{
-		for (s = &s[17]; s[0] && isspace(s[0]); ++s)
-			if (s[0] == '\n' || s[0] == '\r')
-				break;
-		for (q = s; q[0] && !isspace(q[0]); ++q)
-		{}  // Find end of string
-		const size_t kinamelen = q - s;
-		char kiname[kinamelen + 1];
-		memcpy(kiname, s, kinamelen);
-		kiname[kinamelen] = '\0';
-		*out_kinterface = select_kernel(kiname);
+		const char *q;
+		char buf[0x20];
+		extract_word(buf, sizeof(buf), &q, &s[17]);
+		*out_kinterface = select_kernel(buf);
+		
+		if (out_malgo && (q[0] == '\t' || q[0] == ' '))
+		{
+			extract_word(buf, sizeof(buf), &q, q);
+			*out_malgo = mining_algorithm_by_alias(buf);
+		}
 	}
 	}
 	else
 	else
 		*out_kinterface = KL_NONE;
 		*out_kinterface = KL_NONE;
@@ -718,7 +736,7 @@ bool opencl_load_kernel(struct cgpu_info * const cgpu, _clState * const clState,
 	snprintf(filename, sizeof(filename), "%s.cl", kernel_file);
 	snprintf(filename, sizeof(filename), "%s.cl", kernel_file);
 	snprintf(binaryfilename, sizeof(filename), "%s", kernel_file);
 	snprintf(binaryfilename, sizeof(filename), "%s", kernel_file);
 	int pl;
 	int pl;
-	char *source = opencl_kernel_source(filename, &pl, &kernelinfo->interface);
+	char *source = opencl_kernel_source(filename, &pl, &kernelinfo->interface, NULL);
 	if (!source)
 	if (!source)
 		return false;
 		return false;
 	{
 	{

+ 2 - 18
ocl.h

@@ -1,8 +1,6 @@
 #ifndef BFG_OCL_H
 #ifndef BFG_OCL_H
 #define BFG_OCL_H
 #define BFG_OCL_H
 
 
-#include "config.h"
-
 #include <stdbool.h>
 #include <stdbool.h>
 #include <stdio.h>
 #include <stdio.h>
 
 
@@ -10,21 +8,10 @@
 
 
 #include "miner.h"
 #include "miner.h"
 
 
+struct mining_algorithm;
 struct opencl_kernel_info;
 struct opencl_kernel_info;
 typedef struct _clState _clState;
 typedef struct _clState _clState;
 
 
-typedef cl_int (*queue_kernel_parameters_func_t)(const struct opencl_kernel_info *, _clState *, struct work *, cl_uint);
-
-struct opencl_kernel_info {
-	bool loaded;
-	cl_program program;
-	cl_kernel kernel;
-	bool goffset;
-	enum cl_kernels interface;
-	size_t wsize;
-	queue_kernel_parameters_func_t queue_kernel_parameters;
-};
-
 struct _clState {
 struct _clState {
 	cl_device_id devid;
 	cl_device_id devid;
 	char *platform_ver_str;
 	char *platform_ver_str;
@@ -33,9 +20,6 @@ struct _clState {
 	cl_context context;
 	cl_context context;
 	cl_command_queue commandQueue;
 	cl_command_queue commandQueue;
 	
 	
-	struct opencl_kernel_info kernel_sha256d;
-	struct opencl_kernel_info kernel_scrypt;
-	
 	cl_mem outputBuffer;
 	cl_mem outputBuffer;
 #ifdef USE_SCRYPT
 #ifdef USE_SCRYPT
 	cl_mem CLbuffer0;
 	cl_mem CLbuffer0;
@@ -53,7 +37,7 @@ struct _clState {
 
 
 extern FILE *opencl_open_kernel(const char *filename);
 extern FILE *opencl_open_kernel(const char *filename);
 extern char *file_contents(const char *filename, int *length);
 extern char *file_contents(const char *filename, int *length);
-extern char *opencl_kernel_source(const char *filename, int *out_sourcelen, enum cl_kernels *out_kinterface);
+extern char *opencl_kernel_source(const char *filename, int *out_sourcelen, enum cl_kernels *out_kinterface, struct mining_algorithm **);
 extern int clDevicesNum(void);
 extern int clDevicesNum(void);
 extern _clState *opencl_create_clState(unsigned int gpu, char *name, size_t nameSize);
 extern _clState *opencl_create_clState(unsigned int gpu, char *name, size_t nameSize);
 extern bool opencl_load_kernel(struct cgpu_info *, _clState *clState, const char *name, struct opencl_kernel_info *, const char *kernel_file, const struct mining_algorithm *);
 extern bool opencl_load_kernel(struct cgpu_info *, _clState *clState, const char *name, struct opencl_kernel_info *, const char *kernel_file, const struct mining_algorithm *);

+ 1 - 1
opencl/diablo.cl

@@ -17,7 +17,7 @@
  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
  */
 
 
-// kernel-interface: diablo
+// kernel-interface: diablo SHA256d
 
 
 #ifdef VECTORS4
 #ifdef VECTORS4
 	typedef uint4 z;
 	typedef uint4 z;

+ 1 - 1
opencl/diakgcn.cl

@@ -3,7 +3,7 @@
 // Parts and / or ideas for this kernel are based upon the public-domain poclbm project, the phatk kernel by Phateus and the DiabloMiner kernel by DiabloD3.
 // Parts and / or ideas for this kernel are based upon the public-domain poclbm project, the phatk kernel by Phateus and the DiabloMiner kernel by DiabloD3.
 // The kernel was rewritten by me (Diapolo) and is still public-domain!
 // The kernel was rewritten by me (Diapolo) and is still public-domain!
 
 
-// kernel-interface: diakgcn
+// kernel-interface: diakgcn SHA256d
 
 
 #ifdef VECTORS4
 #ifdef VECTORS4
 	typedef uint4 u;
 	typedef uint4 u;

+ 1 - 1
opencl/phatk.cl

@@ -2,7 +2,7 @@
 // I have therefore decided to keep it public-domain.
 // I have therefore decided to keep it public-domain.
 // Modified version copyright 2011-2012 Con Kolivas
 // Modified version copyright 2011-2012 Con Kolivas
 
 
-// kernel-interface: phatk
+// kernel-interface: phatk SHA256d
 
 
 #ifdef VECTORS4
 #ifdef VECTORS4
 	typedef uint4 u;
 	typedef uint4 u;

+ 1 - 1
opencl/poclbm.cl

@@ -5,7 +5,7 @@
 // This file is taken and modified from the public-domain poclbm project, and
 // This file is taken and modified from the public-domain poclbm project, and
 // we have therefore decided to keep it public-domain in Phoenix.
 // we have therefore decided to keep it public-domain in Phoenix.
 
 
-// kernel-interface: poclbm
+// kernel-interface: poclbm SHA256d
 
 
 #ifdef VECTORS4
 #ifdef VECTORS4
 	typedef uint4 u;
 	typedef uint4 u;

+ 1 - 1
opencl/psw.cl

@@ -29,7 +29,7 @@
  * online backup system.
  * online backup system.
  */
  */
 
 
-// kernel-interface: scrypt
+// kernel-interface: scrypt scrypt
 
 
 __constant uint ES[2] = { 0x00FF00FF, 0xFF00FF00 };
 __constant uint ES[2] = { 0x00FF00FF, 0xFF00FF00 };
 __constant uint K[] = {
 __constant uint K[] = {

+ 1 - 1
opencl/scrypt.cl

@@ -31,7 +31,7 @@
  * online backup system.
  * online backup system.
  */
  */
 
 
-// kernel-interface: scrypt
+// kernel-interface: scrypt scrypt
 
 
 __constant uint ES[2] = { 0x00FF00FF, 0xFF00FF00 };
 __constant uint ES[2] = { 0x00FF00FF, 0xFF00FF00 };
 __constant uint K[] = {
 __constant uint K[] = {

+ 1 - 1
opencl/zuikkis.cl

@@ -28,7 +28,7 @@
  * online backup system.
  * online backup system.
  */
  */
 
 
-// kernel-interface: scrypt
+// kernel-interface: scrypt scrypt
 
 
 __constant uint ES[2] = { 0x00FF00FF, 0xFF00FF00 };
 __constant uint ES[2] = { 0x00FF00FF, 0xFF00FF00 };
 __constant uint K[] = {
 __constant uint K[] = {

+ 0 - 19
scrypt.h

@@ -1,19 +0,0 @@
-#ifndef SCRYPT_H
-#define SCRYPT_H
-
-#include <stdint.h>
-
-#include "miner.h"
-
-#ifdef USE_SCRYPT
-extern void test_scrypt(void);
-extern void scrypt_hash_data(void *digest, const void *data);
-extern void scrypt_regenhash(struct work *work);
-
-#else /* USE_SCRYPT */
-static inline void scrypt_regenhash(__maybe_unused struct work *work)
-{
-}
-#endif /* USE_SCRYPT */
-
-#endif /* SCRYPT_H */

+ 0 - 13
util.c

@@ -790,19 +790,6 @@ char *ucs2_to_utf8_dup(uint16_t * const in, size_t sz)
 	return out;
 	return out;
 }
 }
 
 
-#ifdef USE_SHA256D
-void hash_data(void *out_hash, const void *data)
-{
-	unsigned char blkheader[80];
-	
-	// data is past the first SHA256 step (padding and interpreting as big endian on a little endian platform), so we need to flip each 32-bit chunk around to get the original input block header
-	swap32yes(blkheader, data, 80 / 4);
-	
-	// double-SHA256 to get the block hash
-	gen_hash(blkheader, out_hash, 80);
-}
-#endif
-
 // Example output: 0000000000000000000000000000000000000000000000000000ffff00000000 (bdiff 1)
 // Example output: 0000000000000000000000000000000000000000000000000000ffff00000000 (bdiff 1)
 void real_block_target(unsigned char *target, const unsigned char *data)
 void real_block_target(unsigned char *target, const unsigned char *data)
 {
 {

+ 0 - 1
util.h

@@ -194,7 +194,6 @@ extern char *ucs2_to_utf8_dup(uint16_t *in, size_t sz);
 }while(0)
 }while(0)
 
 
 extern void gen_hash(unsigned char *data, unsigned char *hash, int len);
 extern void gen_hash(unsigned char *data, unsigned char *hash, int len);
-extern void hash_data(void *digest, const void *data);
 extern void real_block_target(unsigned char *target, const unsigned char *data);
 extern void real_block_target(unsigned char *target, const unsigned char *data);
 extern bool hash_target_check(const unsigned char *hash, const unsigned char *target);
 extern bool hash_target_check(const unsigned char *hash, const unsigned char *target);
 extern bool hash_target_check_v(const unsigned char *hash, const unsigned char *target);
 extern bool hash_target_check_v(const unsigned char *hash, const unsigned char *target);