123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465 |
- /*
- * Copyright 2017-2021 vh
- * Copyright 2021-2023 kano
- *
- * 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 "math.h"
- #include "miner.h"
- #include "usbutils.h"
- #include "klist.h"
- #define JOB_MAX 0x7F
- #define BUFFER_MAX 0xFF
- #define SAMPLE_SIZE 0x78
- #define MS_SECOND_1 1000
- #define MS_SECOND_5 (MS_SECOND_1 * 5)
- #define MS_SECOND_10 (MS_SECOND_1 * 10)
- #define MS_SECOND_15 (MS_SECOND_1 * 15)
- #define MS_SECOND_30 (MS_SECOND_1 * 30)
- #define MS_MINUTE_1 (MS_SECOND_1 * 60)
- #define MS_MINUTE_2 (MS_MINUTE_1 * 2)
- #define MS_MINUTE_3 (MS_MINUTE_1 * 3)
- #define MS_MINUTE_4 (MS_MINUTE_1 * 4)
- #define MS_MINUTE_5 (MS_MINUTE_1 * 5)
- #define MS_MINUTE_10 (MS_MINUTE_1 * 10)
- #define MS_MINUTE_30 (MS_MINUTE_1 * 30)
- #define MS_HOUR_1 (MS_MINUTE_1 * 60)
- enum miner_state {
- MINER_INIT = 1,
- MINER_CHIP_COUNT, // 2
- MINER_CHIP_COUNT_XX, // 3
- MINER_CHIP_COUNT_OK, // 4
- MINER_OPEN_CORE, // 5
- MINER_OPEN_CORE_OK, // 6
- MINER_MINING, // 7
- MINER_MINING_DUPS, // 8
- MINER_SHUTDOWN, // 9
- MINER_SHUTDOWN_OK, // 10
- MINER_RESET // 11
- };
- enum miner_asic {
- BM1384 = 1,
- BM1387,
- BM1397
- };
- enum plateau_type {
- PT_NONONCE = 1,
- PT_FREQSET,
- PT_FREQNR,
- PT_DUPNONCE
- };
- enum micro_command {
- M1_GET_FAN = (0x00 << 3),
- M1_GET_RPM = (0x01 << 3),
- M1_GET_VIN = (0x02 << 3),
- M1_GET_IIN = (0x03 << 3),
- M1_GET_TEMP = (0x04 << 3),
- M1_GET_VNODE0 = (0x05 << 3),
- M1_CLR_BEN = (0x08 << 3),
- M1_SET_BEN = (0x09 << 3),
- M1_CLR_LED = (0x0A << 3),
- M1_SET_LED = (0x0B << 3),
- M1_CLR_RST = (0x0C << 3),
- M1_SET_RST = (0x0D << 3),
- M2_SET_FAN = (0x18 << 3),
- M2_SET_VCORE = (0x1C << 3)
- };
- enum asic_state {
- ASIC_HEALTHY = 0,
- ASIC_HALFDEAD,
- ASIC_ALMOST_DEAD,
- ASIC_DEAD
- };
- // N.B. at 2TH/s R909 ticket 64 = ~1.2 nonces per chip per second
- // thus 20mins is only ~1000 nonces - so variance isn't very low
- // time range of each value = 10 minutes
- #define CHTIME 600
- // number of ranges thus total 1hr
- #define CHNUM 6
- #define CHOFF(n) (((n) + CHNUM) % CHNUM)
- // N.B. uses CLOCK_MONOTONIC
- #define CHBASE(_t1) ((int)((_t1) / CHTIME))
- #define CHCMP(_t1, _t2) (CHBASE(_t1) == CHBASE(_t2))
- struct GEKKOCHIP
- {
- // seconds time of [offset]
- time_t zerosec;
- // the position of [0]
- int offset;
- // number of nonces in each range
- int noncenum[CHNUM];
- // number of nonces in 0..last-1
- int noncesum;
- // last used offset 0 based
- int last;
- };
- struct ASIC_INFO {
- struct timeval last_nonce; // Last time nonce was found
- float frequency; // Current frequency
- float frequency_set; // set_frequency
- bool frequency_updated; // Initiate check for new frequency
- uint32_t frequency_attempt; // attempts of set_frequency
- uint32_t dups; // Duplicate nonce counter
- uint32_t dupsall; // Total duplicate nonce counter
- enum asic_state state;
- enum asic_state last_state;
- struct timeval state_change_time; // Device startup time
- struct timeval last_frequency_adjust; // Last time of frequency adjust
- struct timeval last_frequency_ping; // Last time of frequency ping
- struct timeval last_frequency_reply; // Last time of frequency reply
- uint32_t prev_nonce; // Last nonce found
- float fullscan_ms; // Estimated time(ms) for full nonce range
- uint32_t fullscan_us; // Estimated time(us) for full nonce range
- uint64_t hashrate; // Estimated hashrate = cores x chips x frequency
- float frequency_reply;
-
- int nonces;
- struct GEKKOCHIP gc; // running nonce buffer
- };
- struct COMPAC_NONCE
- {
- int asic;
- unsigned char rx[BUFFER_MAX];
- size_t len;
- size_t prelen;
- struct timeval when;
- };
- #define DATA_NONCE(_item) ((struct COMPAC_NONCE *)(_item->data))
- #define ALLOC_NLIST_ITEMS 256
- #define LIMIT_NLIST_ITEMS 0
- // BM1397 info->job_id offsets to check (when job_id is wrong)
- static int cur_attempt[] = { 0, -4, -8, -12 };
- #define CUR_ATTEMPT (sizeof(cur_attempt)/sizeof(int))
- // macro to adjust frequency choices to be an integer multple of info->freq_base
- #define FREQ_BASE(_f) (ceil((float)(_f) / info->freq_base) * info->freq_base)
- // macro to add/subtract from the job_id but roll in the min...max range
- #define JOB_ID_ROLL(_jid, _add, _info) \
- ((_info)->min_job_id + (((_jid) + (_add) - (_info)->min_job_id) % \
- ((_info)->max_job_id + 1 - (_info)->min_job_id)))
- // convert chip to address for the 1397
- #define CHIPPY1397(_inf, _chi) (((double)(_inf->chips) == 0) ? \
- (unsigned char)0 : \
- ((unsigned char)(floor((double)0x100 / (double)(_inf->chips))) * (unsigned char)(_chi)))
- // convert address to chip for the 1397
- #define TOCHIPPY1397(_inf, _adr) (((double)(_inf->chips) == 0) ? \
- 0 : (int)floor((double)(_adr) \
- / floor((double)0x100 / (double)(_inf->chips))) )
- // BM1397 registers
- #define BM1397FREQ 0x08
- #define BM1397TICKET 0x14
- #define GHNUM (60*5)
- #define GHOFF(n) (((n) + GHNUM) % GHNUM)
- // a time jump without any nonces will reset the GEKKOHASH data
- // this would normally be a miner failure, so should reset anyway,
- // however under normal mining operation, using 10sec,
- // a 6GH/s asic will have this happen, on average, about once every 10 days
- // a 30GH/s asic is unlikely to have this happen in the life of the universe
- #define GHLIMsec 10
- // number of nonces that should give better than 80% accuracy
- // CDF[ERlang] 400 0.8 = 9.0991e-06
- #define GHNONCES 400
- // a loss of this much hash rate will reduce requested freq and reset
- #define GHREQUIRE 0.65
- // number of nonces needed before using as the rolling hash rate
- // N.B. 200Mhz ticket 16 GSF is around 2/sec
- // also, 8 has high variance ... but resets shouldn't be common
- // code adds 1 to this value since the first nonce isn't part of the H/s calc
- #define GHNONCENEEDED 8
- // running 5min nonce diff buffer (for GH/s)
- // offset = current second, GHOFF(offset-1) = previous second
- // GHOFF(offset-(GHNUM-1)) = GHOFF(offset+1) = oldest possible
- // GHOFF(offset-last) = oldest used
- // code is all linear except one loop that is almost always only
- // one interation or total max one interation per second elapsed real time
- struct GEKKOHASH
- {
- // seconds time of [offset]
- time_t zerosec;
- // the position of [0]
- int offset;
- // total diff in each second
- int64_t diff[GHNUM];
- // time of the first nonce in each second
- struct timeval firstt[GHNUM];
- // diff of first nonce in each second
- int64_t firstd[GHNUM];
- // time of the last nonce in each second
- struct timeval lastt[GHNUM];
- // number of nonces in each second
- int noncenum[GHNUM];
- // sum of diff[0..last-1]
- int64_t diffsum;
- // number of nonces in 0..last-1
- int noncesum;
- // last used offset 0 based
- int last;
- };
- #define JOBMIN 5
- #define JOBOFF(n) (((n) + JOBMIN) % JOBMIN)
- // a time jump without any work will reset the GEKKOJOB data
- // this would normally be all pool failure or power down due to heat
- // 3 = 3 minutes so should never happen
- #define JOBLIMn 3
- // the arrays are minutes of data
- // N.B. uses CLOCK_MONOTONIC
- #define JOBTIME(_sec) ((int)((int)(_sec)/(int)60))
- struct GEKKOJOB
- {
- // JOBTIME of [offset]
- time_t zeromin;
- // time of last job added
- struct timeval lastjob;
- // the position of [0]
- int offset;
- // time of the first job in each
- struct timeval firstj[JOBMIN];
- // time of the last job in each
- struct timeval lastj[JOBMIN];
- // number of job items in each
- int jobnum[JOBMIN];
- // average ms between jobs
- double avgms[JOBMIN];
- // min ms
- double minms[JOBMIN];
- // max ms
- double maxms[JOBMIN];
- // number of jobs in 0..last-1
- int jobsnum;
- // last used offset 0 based
- int last;
- };
- struct COMPAC_INFO {
- enum sub_ident ident; // Miner identity
- enum miner_state mining_state; // Miner state
- enum miner_asic asic_type; // ASIC Type
- struct thr_info *thr; // Running Thread
- struct thr_info rthr; // Listening Thread
- struct thr_info wthr; // Miner Work Thread
- pthread_mutex_t lock; // Mutex
- pthread_mutex_t wlock; // Mutex Serialize Writes
- pthread_mutex_t rlock; // Mutex Serialize Reads
- struct thr_info nthr; // GSF Nonce Thread
- K_LIST *nlist; // GSF Nonce list
- K_LIST *nstore; // GSF Nonce store
- pthread_mutex_t nlock; // GSF lock
- pthread_cond_t ncond; // GSF wait
- uint64_t ntimeout; // GSF number of cond timeouts
- uint64_t ntrigger; // GSF number of cond tiggered
- float freq_mult; // frequency multiplier
- float freq_base; // frequency mod value
- float step_freq; // frequency step value
- float min_freq; // Lowest frequency mine2 will tune down to
- int ramp_time; // time to allow for initial frequency ramp
- float frequency; // Chip Average Frequency
- float frequency_asic; // Highest of current asics.
- float frequency_default; // ASIC Frequency on RESET
- float frequency_requested; // Requested Frequency
- float frequency_selected; // Initial Requested Frequency
- float frequency_start; // Starting Frequency
- float frequency_fail_high; // Highest Frequency of Chip Failure
- float frequency_fail_low; // Lowest Frequency of Chip Failure
- float frequency_computed; // Highest hashrate seen as a frequency value
- float eff_gs; // hash : expected hash
- float eff_tm; // hash : expected hash
- float eff_li; // hash : expected hash
- float eff_1m; // hash : expected hash
- float eff_5m; // hash : expected hash
- float eff_15; // hash : expected hash
- float eff_wu; // wu : expected wu
- float tune_up; // Increase frequency when eff_gs is above value
- float tune_down; // Decrease frequency when eff_gs is below value
- float freq_fail; // last freq set failure on BM1397
- float hr_scale; // scale adjustment for hashrate
- float micro_temp; // Micro Reported Temp
- float wait_factor0; // Base setting from opt value
- float wait_factor; // Used to compute max_task_wait
- bool lock_freq; // When true disable all but safety,reset,shutdown and API freq changes
- int usb_prop; // Number of usec to wait after certain usb commands
- float fullscan_ms; // Estimated time(ms) for full nonce range
- float task_ms; // Avg time(ms) between task sent to device
- uint32_t fullscan_us; // Estimated time(us) for full nonce range
- uint64_t hashrate; // Estimated hashrate = cores x chips x frequency x hr_scale
- uint64_t busy_work;
- uint64_t task_hcn; // Hash Count Number - max nonce iter.
- uint32_t prev_nonce; // Last nonce found
- int failing; // Flag failing sticks
- int fail_count; // Track failures = resets
- int frequency_fo; // Frequency check token
- int frequency_of; // Frequency check token
- int accepted; // Nonces accepted
- int dups; // Duplicates found (for plateau code)
- int dupsall; // Duplicate nonce counter (total)
- int dupsreset; // Duplicates since reset
- int tracker; // Track code execution path
- int interface; // USB interface
- int init_count; // USB interface initialization counter
- int low_eff_resets; // Count of low_eff resets
- int midstates; // Number of midstates
- int nonceless; // Tasks sent. Resets when nonce is found.
- int nonces; // Nonces found
- int plateau_reset; // Count plateau based resets
- int zero_check; // Received nonces from zero work
- int vcore; // Core voltage
- int micro_found; // Found a micro to communicate with
- bool can_boost; // true if boost is possible
- bool vmask; // Current pool's vmask
- bool boosted; // Good nonce found for midstate2/3/4
- bool report;
- bool frequency_syncd; // All asics share same frequency
- double wu;
- double wu_max; // Max WU since last frequency change
- double rolling;
- uint32_t bauddiv; // Baudrate divider
- uint32_t chips; // Stores number of chips found
- uint32_t cores; // Stores number of core per chp
- uint32_t difficulty; // For computing hashrate
- float nonce_expect; // For PT_NONONCE
- float nonce_limit; // For PT_NONONCE
- uint32_t expected_chips; // Number of chips for device
- uint64_t hashes; // Hashes completed
- uint64_t xhashes; // Hashes completed / 0xffffffffull
- uint32_t job_id; // JobId incrementer
- int32_t log_wide; // Extra output in widescreen mode
- uint32_t low_hash; // Tracks of low hashrate
- uint32_t min_job_id; // JobId start/rollover
- uint32_t add_job_id; // JobId increment
- uint32_t max_job_id; // JobId cap
- uint64_t max_task_wait; // Micro seconds to wait before next task is sent
- uint32_t ramping; // Ramping incrementer
- uint32_t rx_len; // rx length
- uint32_t task_len; // task length
- uint32_t ticket_mask; // Used to reduce flashes per second
- uint32_t update_work; // Notification of work update
- struct timeval start_time; // Device startup time
- struct timeval monitor_time; // Health check reference point
- struct timeval last_computed_increase; // Last frequency computed change
- struct timeval last_scanhash; // Last time inside scanhash loop
- struct timeval last_dup_time; // Last time nonce dup detected was attempted
- struct timeval last_reset; // Last time reset was triggered
- struct timeval last_task; // Last time work was sent
- struct timeval last_nonce; // Last time nonce was found
- struct timeval last_hwerror; // Last time hw error was detected
- struct timeval last_fast_forward; // Last time of ramp jump to peak
- struct timeval last_frequency_adjust; // Last time of frequency adjust
- struct timeval last_frequency_ping; // Last time of frequency poll
- struct timeval last_frequency_report; // Last change of frequency report
- struct timeval last_frequency_invalid; // Last change of frequency report anomaly
- struct timeval last_chain_inactive; // Last sent chain inactive
- struct timeval last_low_eff_reset; // Last time responded to low_eff condition
- struct timeval last_micro_ping; // Last time of micro controller poll
- struct timeval last_write_error; // Last usb write error message
- struct timeval last_wu_increase; // Last wu_max change
- struct timeval last_pool_lost; // Last time we lost pool
- struct timeval last_update_rates; // Last time we called compac_update_rates()
- struct timeval first_task;
- uint64_t tasks;
- uint64_t cur_off[CUR_ATTEMPT];
- double work_usec_avg;
- uint64_t work_usec_num;
- double last_work_diff; // Diff of last work sent
- struct timeval last_ticket_attempt; // List attempt to set ticket
- int ticket_number; // offset in ticket array
- int ticket_work; // work sent since ticket set
- int64_t ticket_nonces; // nonces since ticket set
- int64_t below_nonces; // nonces too low since ticket set
- bool ticket_ok; // ticket working ok
- bool ticket_got_low; // nonce found close to but >= diff
- int ticket_failures; // Must not exceed MAX_TICKET_CHECK
- struct ASIC_INFO asics[255];
- int64_t noncebyte[256]; // Count of nonces with the given byte[3] value
- bool nb2c_setup; // BM1397 true = nb2chip is setup (false = all 0)
- uint16_t nb2chip[256]; // BM1397 map nonce byte to: chip that produced it
- bool active_work[JOB_MAX+1]; // Tag good and stale work
- struct work *work[JOB_MAX+1]; // Work ring buffer
- pthread_mutex_t ghlock; // Mutex for all access to gh
- struct GEKKOHASH gh; // running hash rate buffer
- float ghrequire; // Ratio of expected HR required (GHREQUIRE) 0.0-0.8
- pthread_mutex_t joblock; // Mutex for all access to jb
- struct GEKKOJOB job; // running job rate buffer
- pthread_mutex_t slock; // usleep() stats
- uint64_t num0;
- uint64_t num;
- double req;
- double fac;
- uint64_t num1_1;
- double req1_1;
- double fac1_1;
- uint64_t num1_5;
- double req1_5;
- double fac1_5;
- uint64_t inv;
- double workgen; // work timing overrun stats
- int64_t over1num;
- double over1amt;
- int64_t over2num;
- double over2amt;
- struct timeval tune_limit; // time between tune checks
- struct timeval last_tune_up; // time of last tune up attempt
- unsigned char task[BUFFER_MAX]; // Task transmit buffer
- unsigned char cmd[BUFFER_MAX]; // Command transmit buffer
- unsigned char rx[BUFFER_MAX]; // Receive buffer
- unsigned char tx[BUFFER_MAX]; // Transmit buffer
- unsigned char end[1024]; // buffer overrun test
- };
- void stuff_lsb(unsigned char *dst, uint32_t x);
- void stuff_msb(unsigned char *dst, uint32_t x);
- void stuff_reverse(unsigned char *dst, unsigned char *src, uint32_t len);
- uint64_t bound(uint64_t value, uint64_t lower_bound, uint64_t upper_bound);
|