zorba.karlos
Newbie
Offline
Activity: 1
Merit: 0
|
|
February 14, 2015, 05:56:32 AM |
|
For BFL Monarch, I added experimental underclocking support to cgminer.
Example Usage: the following sets the clock frequency to max (1x), voltage at 580mV.
# cgminer --bflsc-volt=4 --bflsc-clock=16
Refer to BFL documentation for voltage levels, but please note I shifted the index by one; I needed '0' to mean 'do-nothing'. IE: the '16' above = 'F" in BFL docs.
As a safety precaution, cgminer will not initialize / use a Monarch unless the voltage and clock are set successfully. IE: a hotplug or power interruption will restore the voltage/clock settings to a Monarch before mining commences.
The patch below is against cgminer commit 8b425ed545d64f3007c6a7b2b70910efec65a7ea. htt p s://github.com/ckolivas/cgminer/commit/8b425ed545d64f3007c6a7b2b70910efec65a7ea
----------------
diff --git a/cgminer.c b/cgminer.c index 94e847e..48db62d 100644 --- a/cgminer.c +++ b/cgminer.c @@ -796,6 +796,16 @@ static char *set_int_1_to_10(const char *arg, int *i) return set_int_range(arg, i, 1, 10); } +static char *set_int_0_to_32(const char *arg, int *i) +{ + return set_int_range(arg, i, 0, 32); +} + +static char *set_int_0_to_16(const char *arg, int *i) +{ + return set_int_range(arg, i, 0, 16); +} + static char __maybe_unused *set_int_0_to_4(const char *arg, int *i) { return set_int_range(arg, i, 0, 4); @@ -1265,6 +1275,12 @@ static struct opt_table opt_config_table[] = { OPT_WITH_ARG("--bflsc-overheat", set_int_0_to_200, opt_show_intval, &opt_bflsc_overheat, "Set overheat temperature where BFLSC devices throttle, 0 to disable"), + OPT_WITH_ARG("--bflsc-volt", + set_int_0_to_16, opt_show_intval, &opt_bflsc_volt, + "Set monarch voltage level (1-16), 0 to disable. BFL claims values above 7 are disabled."), + OPT_WITH_ARG("--bflsc-clock", + set_int_0_to_32, opt_show_intval, &opt_bflsc_clock, + "Set monarch clock speed (1-32), 0 to disable, 17-32 enable clock doubler"), #endif #ifdef USE_AVALON OPT_WITH_ARG("--bitburner-voltage", diff --git a/driver-bflsc.c b/driver-bflsc.c index ac77d48..7dfd10c 100644 --- a/driver-bflsc.c +++ b/driver-bflsc.c @@ -31,6 +31,15 @@ #include "driver-bflsc.h" int opt_bflsc_overheat = BFLSC_TEMP_OVERHEAT; +int opt_bflsc_clock = 0; +int opt_bflsc_volt = 0; + +float bflsc_voltage_map[] = { + 0.540, 0.550, 0.560, 0.580, + 0.600, 0.620, 0.630, 0.643, + 0.650, 0.662, 0.670, 0.680, + 0.700, 0.720, 0.730, 0.750 +}; static const char *blank = ""; @@ -453,6 +462,7 @@ static bool bflsc_qres(struct cgpu_info *bflsc, char *buf, size_t bufsiz, int de static void __bflsc_initialise(struct cgpu_info *bflsc) { int err, interface; + struct bflsc_info *sc_info = (struct bflsc_info *)(bflsc->device_data); // TODO: does x-link bypass the other device FTDI? (I think it does) // So no initialisation required except for the master device? @@ -536,6 +546,7 @@ static void __bflsc_initialise(struct cgpu_info *bflsc) if (!bflsc->cutofftemp) bflsc->cutofftemp = opt_bflsc_overheat; + } static void bflsc_initialise(struct cgpu_info *bflsc) @@ -555,6 +566,82 @@ static void bflsc_initialise(struct cgpu_info *bflsc) } } +static bool __bflsc_set_volt(struct cgpu_info *bflsc) { + char msg[16]; + char recv[100]; + int err,amount; + bool sent; + int effective_volt; + + if (!opt_bflsc_volt) + return true; + + effective_volt=opt_bflsc_volt-1; + + applogsiz(LOG_WARNING, BFLSC_APPLOGSIZ, + "%s (%s) set volt to %0.3fV (V%XX) ", + bflsc->drv->dname, bflsc->device_path, + bflsc_voltage_map[effective_volt], effective_volt); + + snprintf(msg, sizeof(msg), "V%XX\n", effective_volt); + err = usb_write(bflsc, msg, strlen(msg), &amount, C_SETVOLT); + if (err < 0 || amount < 4) { + bflsc_applog(bflsc, 0, C_SETVOLT, amount, err); + return false; + } + err = usb_read_ok_timeout(bflsc, recv, sizeof(recv)-1, &amount, SET_VOLT_TIME_MAX_MS, C_REPLYSETVOLT); + if (err < 0 ) { + bflsc_applog(bflsc, 0, C_REPLYSETVOLT, amount, err); + return false; + } + return true; +} + +static bool __bflsc_set_clock(struct cgpu_info *bflsc) { + char msg[16]; + char recv[100]; + int err,amount; + bool sent; + char double_clock_flag; + int effective_clock; + + if (!opt_bflsc_clock) + return true; + + effective_clock=opt_bflsc_clock-1; + double_clock_flag='X'; + + if (effective_clock > 15) { + double_clock_flag='D'; + effective_clock &= 0x0F; + if (effective_clock > 2) { + applogsiz(LOG_WARNING, BFLSC_APPLOGSIZ, + "Frequency too high with clock doubling enabled; reducing frequency."); + effective_clock=2; + opt_bflsc_clock=19; + } + } + + applogsiz(LOG_WARNING, BFLSC_APPLOGSIZ, + "%s (%s) set clock to %i (F%X%c)", + bflsc->drv->dname, bflsc->device_path, + opt_bflsc_clock, effective_clock, double_clock_flag); + + snprintf(msg, sizeof(msg), "F%X%c\n", effective_clock, double_clock_flag); + err = usb_write(bflsc, msg, strlen(msg), &amount, C_SETCLOCK); + if (err < 0 || amount < 4) { + bflsc_applog(bflsc, 0, C_SETCLOCK, amount, err); + return false; + } + err = usb_read_ok_timeout(bflsc, recv, sizeof(recv)-1, &amount, SET_CLOCK_TIME_MAX_MS, C_REPLYSETCLOCK); + if (err < 0 ) { + bflsc_applog(bflsc, 0, C_REPLYSETCLOCK, amount, err); + return false; + } + return true; +} + + static bool getinfo(struct cgpu_info *bflsc, int dev) { struct bflsc_info *sc_info = (struct bflsc_info *)(bflsc->device_data); @@ -894,6 +981,15 @@ reinit: applog(LOG_DEBUG, "%s (%s) identified as: '%s'", bflsc->drv->dname, bflsc->device_path, bflsc->drv->name); + if (sc_info->ident == IDENT_BMA) { + if (!__bflsc_set_volt(bflsc)) + goto unshin; + cgsleep_ms(100); // let voltage stabilize + if (!__bflsc_set_clock(bflsc)) + goto unshin; + cgsleep_ms(100); // let clock stabilize + } + if (!add_cgpu(bflsc)) goto unshin; diff --git a/driver-bflsc.h b/driver-bflsc.h index 4778993..50789b0 100644 --- a/driver-bflsc.h +++ b/driver-bflsc.h @@ -386,7 +386,13 @@ struct SaveString { #define REINIT_TIME_MAX_MS 800 // Keep trying up to this many us #define REINIT_TIME_MAX 3000000 +// How long do we wait for the voltage-set operation? (ms) +#define SET_VOLT_TIME_MAX_MS 10000 +// How long do we wait for the clock-set operation? (ms) +#define SET_CLOCK_TIME_MAX_MS 15000 int opt_bflsc_overheat; +int opt_bflsc_clock; +int opt_bflsc_volt; #endif /* BFLSC_H */
|