URL
https://opencores.org/ocsvn/btcminer/btcminer/trunk
Subversion Repositories btcminer
Compare Revisions
- This comparison shows the changes necessary to convert path
/btcminer
- from Rev 1 to Rev 2
- ↔ Reverse comparison
Rev 1 → Rev 2
/trunk/ztex_ufm1_15d4.c
0,0 → 1,32
/*! |
btcminer -- BTCMiner for ZTEX USB-FPGA Modules: EZ-USB FX2 firmware for ZTEX USB FPGA Module 1.15d (one double hash pipe) |
Copyright (C) 2011-2012 ZTEX GmbH |
http://www.ztex.de |
|
This program is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License version 3 as |
published by the Free Software Foundation. |
|
This program is distributed in the hope that it will be useful, but |
WITHOUT ANY WARRANTY; without even the implied warranty of |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
General Public License for more details. |
|
You should have received a copy of the GNU General Public License |
along with this program; if not, see http://www.gnu.org/licenses/. |
!*/ |
|
#define[NUM_NONCES][1] |
#define[EXTRA_SOLUTIONS][1] |
#define[OFFS_NONCES][0] |
#define[F_MULT][50] |
//#define[F_MAX_MULT][54] |
#define[F_MAX_MULT][62] |
#define[HASHES_PER_CLOCK][128] |
#define[BITFILE_STRING]["ztex_ufm1_15d4"] |
|
#define[F_M1][400] |
#define[F_DIV][6] |
#define[F_MIN_MULT][25] |
|
#include[btcminer.h] |
/trunk/ztex_ufm1_15y.c
0,0 → 1,43
/*! |
default -- Default Firmware for ZTEX USB-FPGA Modules 1.15y |
Copyright (C) 2009-2012 ZTEX GmbH. |
http://www.ztex.de |
|
This program is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License version 3 as |
published by the Free Software Foundation. |
|
This program is distributed in the hope that it will be useful, but |
WITHOUT ANY WARRANTY; without even the implied warranty of |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
General Public License for more details. |
|
You should have received a copy of the GNU General Public License |
along with this program; if not, see http://www.gnu.org/licenses/. |
!*/ |
|
#include[ztex-conf.h] // Loads the configuration macros, see ztex-conf.h for the available macros |
#include[ztex-utils.h] // include basic functions and variables |
|
// Endpoint 2 is used to high speed FPGA configuration |
EP_CONFIG(2,0,BULK,OUT,512,4); |
|
// select ZTEX USB FPGA Module 1.15y as target (required for FPGA configuration) |
IDENTITY_UFM_1_15Y(10.15.0.0,0); |
|
// enables high speed FPGA configuration, use EP 2 |
ENABLE_HS_FPGA_CONF(2); |
|
// this product string can also used for identification by the host software |
#define[PRODUCT_STRING]["USB-FPGA Module 1.15y (default)"] |
|
#include[ztex.h] |
|
void main(void) |
{ |
init_USB(); // init everything |
|
while (1) { } // twiddle thumbs |
} |
|
|
/trunk/ztex_ufm1_15y1.c
0,0 → 1,35
/*! |
btcminer -- BTCMiner for ZTEX USB-FPGA Modules: EZ-USB FX2 firmware for ZTEX USB FPGA Module 1.15d (one double hash pipe) |
Copyright (C) 2011-2012 ZTEX GmbH |
http://www.ztex.de |
|
This program is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License version 3 as |
published by the Free Software Foundation. |
|
This program is distributed in the hope that it will be useful, but |
WITHOUT ANY WARRANTY; without even the implied warranty of |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
General Public License for more details. |
|
You should have received a copy of the GNU General Public License |
along with this program; if not, see http://www.gnu.org/licenses/. |
!*/ |
|
#define[TARGET_BOARD][1.15y] |
|
#define[NUM_NONCES][1] |
#define[EXTRA_SOLUTIONS][1] |
#define[OFFS_NONCES][0] |
#define[F_MULT][50] |
//#define[F_MULT][54] |
//#define[F_MAX_MULT][54] |
#define[F_MAX_MULT][62] |
#define[HASHES_PER_CLOCK][128] |
#define[BITFILE_STRING]["ztex_ufm1_15y1"] |
|
#define[F_M1][400] |
#define[F_DIV][6] |
#define[F_MIN_MULT][25] |
|
#include[btcminer.h] |
/trunk/BTCMiner.java
0,0 → 1,2436
/*! |
BTCMiner -- BTCMiner for ZTEX USB-FPGA Modules |
Copyright (C) 2011-2012 ZTEX GmbH |
http://www.ztex.de |
|
This program is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License version 3 as |
published by the Free Software Foundation. |
|
This program is distributed in the hope that it will be useful, but |
WITHOUT ANY WARRANTY; without even the implied warranty of |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
General Public License for more details. |
|
You should have received a copy of the GNU General Public License |
along with this program; if not, see http://www.gnu.org/licenses/. |
!*/ |
|
/* TODO: |
* HUP signal |
* rollntime / expire |
*/ |
|
|
import java.io.*; |
import java.util.*; |
import java.net.*; |
import java.security.*; |
import java.text.*; |
import java.util.zip.*; |
|
import ch.ntb.usb.*; |
|
import ztex.*; |
|
// ***************************************************************************** |
// ******* ParameterException ************************************************** |
// ***************************************************************************** |
// Exception the prints a help message |
class ParameterException extends Exception { |
public final static String helpMsg = new String ( |
"Parameters:\n"+ |
" -host <string> Host URL (default: http://127.0.0.1:8332)\n" + |
" -u <string> RPC User name\n" + |
" -p <string> RPC Password\n" + |
" -b <url> <user name> <password> \n" + |
" URL, user name and password of a backup server. Can be specified multiple times. \n"+ |
" -lp <url> <user name> <password> \n" + |
" URL, user name and password of a long polling server (determined automatically by default) \n"+ |
" -l <log file> Log file (default: BTCMiner.log) \n" + |
" -l2 <log file> Secondary log file, logs everything but statistics \n" + |
" -bl <log file> Log of submitted blocks file \n" + |
" -c <file name> Secondary command input file, can be a named pipe \n" + |
" -m s|t|p|c Set single mode, test mode, programming mode or cluster mode\n"+ |
" Single mode: runs BTCMiner on a single board (default mode)\n" + |
" Test mode: tests a board using some test data\n" + |
" Programming mode: programs device with the given firmware\n" + |
" Cluster mode: runs BTCMiner on all programmed boards\n" + |
" -ep0 Always use slow EP0 for Bitstream transfer\n" + |
" -oh <number> Overheat threshold: if the hash rate drops by that factor (but at least two frequency steps)\n"+ |
" the overheat shutdown is triggered (default: 0.04, recommended: 0 to 0.08)\n"+ |
|
" -ps <string> Select devices with the given serial number,\n" + |
" in cluster mode: select devices which serial number starts with the given string\n" + |
" -e <number> Maximum error rate\n"+ |
" -tc Enable target check (disabled by default)\n" + |
" -v Be verbose\n" + |
" -h This help\n" + |
"Parameters in single mode, test mode and programming mode\n"+ |
" -d <number> Device Number, see -i\n" + |
" -f <ihx file> Firmware file (required in programming mode)\n" + |
" -i Print bus info\n" + |
"Parameters in cluster mode\n"+ |
" -n <number> Maximum amount of devices per thread (default: 10)\n"+ |
"Parameters in programming mode\n"+ |
" -pt <string> Program devices of the given type\n" + |
" If neither -ps nor -ps is given, only unconfigured devices are programmed\n" + |
" -s Set serial number\n" + |
" -rf Erase firmware in EEPROM (overwrites -f, requires -pt or -ps)\n" |
); |
|
|
public ParameterException (String msg) { |
super( msg + "\n" + helpMsg ); |
} |
} |
|
/* ***************************************************************************** |
******* ParserException ***************************************************** |
***************************************************************************** */ |
class ParserException extends Exception { |
public ParserException(String msg ) { |
super( msg ); |
} |
} |
|
/* ***************************************************************************** |
******* FirmwareException *************************************************** |
***************************************************************************** */ |
class FirmwareException extends Exception { |
public FirmwareException(String msg ) { |
super( msg ); |
} |
} |
|
|
// ***************************************************************************** |
// ******* MsgObj ************************************************************* |
// ***************************************************************************** |
interface MsgObj { |
public void msg(String s); |
} |
|
|
// ***************************************************************************** |
// ******* NewBlockMonitor ***************************************************** |
// ***************************************************************************** |
class NewBlockMonitor extends Thread implements MsgObj { |
public int newCount = -1; |
|
public boolean running; |
|
private static final int minLongPollInterval = 250; // in ms |
|
private byte[] prevBlock = new byte[32]; |
private byte[] dataBuf = new byte[128]; |
|
private Vector<LogString> logBuf = new Vector<LogString>(); |
|
public static boolean submitOld; |
|
// ******* constructor ********************************************************* |
public NewBlockMonitor( ) { |
start(); |
} |
|
// ******* checkNew ************************************************************ |
synchronized public boolean checkNew ( byte[] data ) throws NumberFormatException { |
if ( data.length < 36 ) |
throw new NumberFormatException("Invalid length of data"); |
|
boolean n = false; |
|
for ( int i=0; i<32; i++ ) { |
n = n | ( data[i+4] != prevBlock[i] ); |
prevBlock[i] = data[i+4]; |
} |
if ( n ) { |
newCount += 1; |
submitOld = true; |
if ( newCount > 0 ) |
msg("New block detected by block monitor"); |
} |
|
return n; |
} |
|
// ******* run ***************************************************************** |
public void run () { |
running = true; |
|
boolean enableLP = true; |
boolean warnings = true; |
long enableLPTime = 0; |
|
submitOld = true; |
|
while ( running ) { |
long t = new Date().getTime(); |
|
if ( BTCMiner.longPollURL!=null && enableLP && t>enableLPTime) { |
try { |
// msg("info: LP"); |
String req = BTCMiner.bitcoinRequest(this, BTCMiner.longPollURL, BTCMiner.longPollUser, BTCMiner.longPollPassw, "getwork", ""); |
BTCMiner.hexStrToData(BTCMiner.jsonParse(req, "data"), dataBuf); |
submitOld = true; |
String so = null; |
try { |
so = BTCMiner.jsonParse(req, "submitold"); |
if ( so.equalsIgnoreCase("false") ) |
submitOld = false; |
} |
catch ( Exception e ) { |
} |
|
for ( int i=0; i<32; i++ ) { |
prevBlock[i] = dataBuf[i+4]; |
} |
newCount += 1; |
msg( "New block detected by long polling" + ( so == null ? "" : " (submitold = " + so + ")" ) ); |
} |
catch ( MalformedURLException e ) { |
msg("Warning: " + e.getLocalizedMessage() + ": disabling long polling"); |
enableLP = false; |
} |
catch ( IOException e ) { |
if ( new Date().getTime() < t+500 ) { |
msg("Warning: " + e.getLocalizedMessage() + ": disabling long polling fo 60s"); |
enableLPTime = new Date().getTime() + 60000; |
} |
} |
catch ( Exception e ) { |
if ( warnings ) |
msg("Warning: " + e.getLocalizedMessage()); |
warnings = false; |
} |
} |
|
if ( BTCMiner.longPollURL==null ) |
enableLPTime = new Date().getTime() + 2000; |
|
t += minLongPollInterval - new Date().getTime(); |
if ( t > 5 ) { |
try { |
Thread.sleep( t ); |
} |
catch ( InterruptedException e) { |
} |
} |
} |
|
// System.out.println("Stopping block monitor"); |
} |
|
// ******* msg ***************************************************************** |
public void msg(String s) { |
synchronized ( logBuf ) { |
logBuf.add( new LogString( s ) ); |
} |
} |
|
// ******* print *************************************************************** |
public void print () { |
synchronized ( logBuf ) { |
for ( int j=0; j<logBuf.size(); j++ ) { |
LogString ls = logBuf.elementAt(j); |
System.out.println( ls.msg ); |
if ( BTCMiner.logFile != null ) { |
BTCMiner.logFile.println( BTCMiner.dateFormat.format(ls.time) + ": " + ls.msg ); |
} |
if ( BTCMiner.logFile2 != null && !ls.msg.substring(0,18).equals("New block detected") ) { |
BTCMiner.logFile2.println( BTCMiner.dateFormat.format(ls.time) + ": " + ls.msg ); |
} |
} |
logBuf.clear(); |
} |
} |
} |
|
// ***************************************************************************** |
// ******* BTCMinerThread ****************************************************** |
// ***************************************************************************** |
class BTCMinerThread extends Thread { |
private Vector<BTCMiner> miners = new Vector<BTCMiner>(); |
private String busName; |
private PollLoop pollLoop = null; |
|
// ******* constructor ********************************************************* |
public BTCMinerThread( String bn ) { |
busName = bn; |
} |
|
// ******* add ***************************************************************** |
public void add ( BTCMiner m ) { |
synchronized ( miners ) { |
miners.add ( m ); |
m.name = busName + ": " + m.name; |
} |
|
if ( pollLoop==null ) { |
BTCMiner.printMsg2("Starting mining thread for bus " + busName); |
start(); |
} |
} |
|
// ******* size **************************************************************** |
public int size () { |
return miners.size(); |
} |
|
// ******* elementAt *********************************************************** |
public BTCMiner elementAt ( int i ) { |
return miners.elementAt(i); |
} |
|
// ******* find **************************************************************** |
public BTCMiner find ( int dn ) { |
for (int i=0; i<miners.size(); i++ ) { |
if ( (miners.elementAt(i).ztex().dev().dev().getDevnum() == dn) ) |
return miners.elementAt(i); |
} |
return null; |
} |
|
// ******* busName ************************************************************* |
public String busName () { |
return busName; |
} |
|
// ******* running ************************************************************* |
public boolean running () { |
return pollLoop != null; |
} |
|
// ******* run ***************************************************************** |
public void run () { |
pollLoop = new PollLoop(miners); |
pollLoop.run(); |
pollLoop = null; |
} |
|
// ******* printInfo ************************************************************ |
public void printInfo ( ) { |
if ( pollLoop != null ) |
pollLoop.printInfo( busName ); |
} |
|
// ******* disconnect *********************************************************** |
public int disconnect ( String ss, Vector<BTCMiner> allMiners ) { |
int i=0; |
synchronized ( miners ) { |
for (int j=miners.size()-1; j>=0; j-- ) { |
BTCMiner m = miners.elementAt(j); |
if ( ss.equals(m.ztex().dev().snString()) ) { |
BTCMiner.printMsg("Disconnecting "+m.name); |
if ( allMiners != null ) |
allMiners.removeElement(m); |
m.suspend(); |
miners.removeElementAt(j); |
i+=1; |
} |
} |
} |
return i; |
} |
|
} |
|
|
// ***************************************************************************** |
// ******* BTCMinerCluster ***************************************************** |
// ***************************************************************************** |
class BTCMinerCluster { |
public static int maxDevicesPerThread = 10; |
|
private Vector<BTCMinerThread> threads = new Vector<BTCMinerThread>(); |
private Vector<BTCMiner> allMiners = new Vector<BTCMiner>(); |
|
// ******* constructor ************************************************************** |
public BTCMinerCluster( boolean verbose ) { |
final long infoInterval = 300000; |
|
scan( verbose ); |
|
long nextInfoTime = new Date().getTime() + 60000; |
|
boolean quit = false; |
while ( threads.size()>0 && !quit) { |
|
try { |
Thread.sleep( 300 ); |
} |
catch ( InterruptedException e) { |
} |
|
BTCMiner.newBlockMonitor.print(); |
for (int i=0; i<allMiners.size(); i++) |
allMiners.elementAt(i).print(); |
|
if ( new Date().getTime() > nextInfoTime ) { |
double d = 0.0; |
double e = 0.0; |
for ( int i=0; i<allMiners.size(); i++ ) { |
BTCMiner m = allMiners.elementAt(i); |
m.printInfo( true ); |
d+=m.submittedHashRate(); |
e+=m.totalHashRate(); |
} |
for ( int i=0; i<threads.size(); i++ ) |
threads.elementAt(i).printInfo(); |
|
BTCMiner.printMsg2("Total hash rate: " + String.format("%.1f", e ) + " MH/s"); |
BTCMiner.printMsg2("Total submitted hash rate: " + String.format("%.1f", d ) + " MH/s"); |
BTCMiner.printMsg2(" -------- "); |
nextInfoTime = new Date().getTime() + infoInterval; |
} |
|
for (int i=threads.size()-1; i>=0; i--) { |
BTCMinerThread t = threads.elementAt(i); |
if ( !t.running() ) { |
BTCMiner.printMsg2( "Stopped thread for bus " + t.busName() ); |
threads.removeElementAt(i); |
} |
} |
|
try { |
StringBuffer sb = new StringBuffer(); |
while ( System.in.available() > 0 ) { |
int j = System.in.read(); |
if (j>32) |
sb.append((char) j); |
} |
|
if ( sb.length() == 0 && BTCMiner.in2 != null ) { |
while ( BTCMiner.in2.available() > 0 ) { |
int j = BTCMiner.in2.read(); |
if (j>32) |
sb.append((char) j); |
} |
} |
|
String cmd = sb.toString(); |
|
if (cmd.length()<1) {} |
else if (cmd.equalsIgnoreCase("q") || cmd.equalsIgnoreCase("quit") ) { |
for (int i=allMiners.size()-1; i>=0; i--) { |
allMiners.elementAt(i).suspend(); |
try { |
Thread.sleep( 10 ); |
} |
catch ( InterruptedException e) { |
} |
} |
quit=true; |
} |
else if (cmd.equalsIgnoreCase("r") || cmd.equalsIgnoreCase("rescan") ) { |
scan( verbose ); |
} |
else if (cmd.equalsIgnoreCase("s") || cmd.equalsIgnoreCase("suspend") ) { |
long t = new Date().getTime(); |
int j=0; |
for (int i=allMiners.size()-1; i>=0; i--) { |
if ( allMiners.elementAt(i).suspend() ) j++; |
allMiners.elementAt(i).startTimeAdjust = t; |
try { |
Thread.sleep( 10 ); |
} |
catch ( InterruptedException e) { |
} |
} |
BTCMiner.printMsg2("Suspended " + j + " of " + allMiners.size() + " miners. Enter `r' to resume."); |
} |
else if (cmd.equalsIgnoreCase("c") || cmd.equalsIgnoreCase("counter_reset") ) { |
for (int i=allMiners.size()-1; i>=0; i--) { |
allMiners.elementAt(i).resetCounters(); |
} |
BTCMiner.printMsg2("Reset all performance end error counters."); |
} |
else if (cmd.equalsIgnoreCase("i") || cmd.equalsIgnoreCase("info") ) { |
nextInfoTime = 0; |
} |
else if ( cmd.charAt(0) == 'd' || cmd.charAt(0) == 'D' ) { |
int i = ( cmd.length()>=10 && cmd.substring(0,10).equalsIgnoreCase("disconnect") ) ? 10 : 1; |
while ( i<cmd.length() && cmd.charAt(i)<=' ' ) i++; |
int j = cmd.length()-1; |
while ( j>=i && cmd.charAt(j)<=' ' ) j--; |
if ( i<=j ) { |
String ss=BTCMiner.checkSnString(cmd.substring(i,j+1)); |
j=0; |
for ( i = threads.size()-1; i>=0; i-- ) { |
j+=threads.elementAt(i).disconnect(ss, allMiners); |
} |
System.out.println("Disconnected "+j+" miners"); |
} |
else { |
System.out.println("No serial number specified"); |
} |
} |
else if (cmd.equalsIgnoreCase("h") || cmd.equalsIgnoreCase("help") ) { |
System.out.println("q(uit) Exit BTCMiner"); |
System.out.println("r(escan) Rescan bus"); |
System.out.println("c(ounter_reset) Reset performance and error counters"); |
System.out.println("s(uspend) Suspend cluster"); |
System.out.println("d(isconnect) <serial nunmber> Disconnect device"); |
System.out.println("i(nfo) Print cluster informations"); |
System.out.println("h(elp) Print this help"); |
} |
else System.out.println("Invalid command: `"+cmd+"', enter `h' for help"); |
|
} |
catch ( Exception e ) { |
} |
|
} |
|
// BTCMiner.newBlockMonitor.running = false; |
} |
|
// ******* add ***************************************************************** |
private void add ( BTCMiner m ) { |
int i=0, j=0; |
String bn = m.ztex().dev().dev().getBus().getDirname() + "-" + j; |
while ( i<threads.size() ) { |
BTCMinerThread t = threads.elementAt(i); |
if ( bn.equalsIgnoreCase(threads.elementAt(i).busName()) ) { |
if ( t.size() < maxDevicesPerThread ) |
break; |
j++; |
i=0; |
bn = m.ztex().dev().dev().getBus().getDirname() + "-" + j; |
} |
else { |
i++; |
} |
} |
|
if ( i >= threads.size() ) |
threads.add( new BTCMinerThread(bn) ); |
threads.elementAt(i).add(m); |
} |
|
// ******* find **************************************************************** |
private BTCMiner find ( ZtexDevice1 dev ) { |
int dn = dev.dev().getDevnum(); |
String bn = dev.dev().getBus().getDirname(); |
for ( int i=threads.size()-1; i>=0; i-- ) { |
BTCMiner m = threads.elementAt(i).find(dn); |
if ( m != null && bn.equals(m.ztex().dev().dev().getBus().getDirname()) ) |
return m; |
} |
return null; |
} |
|
// ******* insertIntoAllMiners ************************************************* |
private void insertIntoAllMiners ( BTCMiner m ) { |
int j = 0; |
while ( j<allMiners.size() && m.name.compareTo(allMiners.elementAt(j).name)>=0 ) |
j++; |
allMiners.insertElementAt(m, j); |
} |
|
// ******* scan **************************************************************** |
private void scan ( boolean verbose ) { |
long t = new Date().getTime(); |
|
allMiners.clear(); |
for ( int i = threads.size()-1; i>=0; i-- ) { |
BTCMinerThread mt = threads.elementAt(i); |
for (int j=mt.size()-1; j>=0; j-- ) { |
BTCMiner m = mt.elementAt(j); |
insertIntoAllMiners(m); |
if ( m.suspended ) { |
m.suspended = false; |
m.isRunning = false; |
try { |
Thread.sleep( 20 ); |
} |
catch ( InterruptedException e) { |
} |
BTCMiner.printMsg2(m.name + ": resuming"); |
} |
else { |
m.startTimeAdjust = t; |
BTCMiner.printMsg2(m.name + ": already running"); |
} |
} |
} |
|
BTCMiner.printMsg2("\n(Re)Scanning bus ... "); |
|
PollLoop.scanMode = true; |
|
ZtexScanBus1 bus = new ZtexScanBus1( ZtexDevice1.ztexVendorId, ZtexDevice1.ztexProductId, false, false, 1, null, 10, 0, 1, 0 ); |
int k = 0; |
int l = 0; |
for (int i=0; i<bus.numberOfDevices(); i++ ) { |
try { |
ZtexDevice1 dev = bus.device(i); |
if ( dev.productId(0)!=10 || dev.productId(2)>1 ) |
break; |
|
if ( BTCMiner.filterSN == null || dev.snString().substring(0,BTCMiner.filterSN.length()).equals(BTCMiner.filterSN) ) { |
k += 1; |
BTCMiner m = find( dev ); |
if ( m == null ) { |
l += 1; |
m = new BTCMiner ( dev, null, verbose ); |
m.clusterMode = true; |
add( m ); |
BTCMiner.printMsg(m.name + ": added"); |
insertIntoAllMiners(m); |
|
for ( int j=1; j<m.numberOfFpgas(); j++ ) { |
BTCMiner n = new BTCMiner( m.ztex(), m.fpgaNum(j), verbose ); |
n.clusterMode = true; |
add( n ); |
BTCMiner.printMsg(n.name + ": added"); |
insertIntoAllMiners(n); |
} |
} |
} |
} |
catch ( Exception e ) { |
BTCMiner.printMsg( "Error: "+e.getLocalizedMessage() ); |
} |
} |
|
if ( k == 0 ) { |
System.err.println("No devices found. At least one device has to be connected."); |
System.exit(0); |
} |
BTCMiner.printMsg2("" + l + " new devices found."); |
|
t = new Date().getTime(); |
for (int i=0; i<allMiners.size(); i++ ) |
allMiners.elementAt(i).startTime+= t-allMiners.elementAt(i).startTimeAdjust; |
|
PollLoop.scanMode = false; |
|
BTCMiner.printMsg2("\nSummary: "); |
for (int i=0; i<threads.size(); i++ ) |
BTCMiner.printMsg2(" Bus " + threads.elementAt(i).busName() + "\t: " + threads.elementAt(i).size() + " miners"); |
BTCMiner.printMsg2(" Total \t: " + allMiners.size() + " miners\n"); |
BTCMiner.printMsg2("\nDisconnect all devices or enter `q' for exit. Enter `h' for help.\n"); |
|
BTCMiner.connectionEffort = 1.0 + Math.exp( (1.0 - Math.sqrt(Math.min(allMiners.size(),maxDevicesPerThread)*allMiners.size())) / 13.0 ); |
// System.out.println( BTCMiner.connectionEffort ); |
|
} |
} |
|
|
// ***************************************************************************** |
// ******* LogString *********************************************************** |
// ***************************************************************************** |
class LogString { |
public Date time; |
public String msg; |
|
public LogString(String s) { |
time = new Date(); |
msg = s; |
} |
} |
|
|
// ***************************************************************************** |
// ******* PollLoop ************************************************************ |
// ***************************************************************************** |
class PollLoop { |
public static boolean scanMode = false; |
|
private double usbTime = 0.0; |
private double networkTime = 0.0; |
private double timeW = 1e-6; |
private Vector<BTCMiner> v; |
public static final long minQueryInterval = 250; |
|
// ******* constructor ********************************************************* |
public PollLoop ( Vector<BTCMiner> pv ) { |
v = pv; |
} |
|
// ******* run ***************************************************************** |
public void run ( ) { |
int maxIoErrorCount = (int) Math.round( (BTCMiner.rpcCount > 1 ? 2 : 4)*BTCMiner.connectionEffort ); |
int ioDisableTime = BTCMiner.rpcCount > 1 ? 60 : 30; |
|
while ( v.size()>0 ) { |
long t0 = new Date().getTime(); |
long tu = 0; |
|
if ( ! scanMode ) { |
synchronized ( v ) { |
for ( int i=v.size()-1; i>=0; i-- ) { |
BTCMiner m = v.elementAt(i); |
|
m.usbTime = 0; |
|
try { |
if ( ! m.suspended ) { |
if ( m.checkUpdate() && m.getWork() ) { // getwork calls getNonces |
m.dmsg("Got new work"); |
m.sendData(); |
} |
else { |
m.getNonces(); |
} |
m.updateFreq(); |
m.printInfo(false); |
} |
} |
catch ( IOException e ) { |
m.ioErrorCount[m.rpcNum]++; |
if ( m.ioErrorCount[m.rpcNum] >= maxIoErrorCount ) { |
m.msg("Error: "+e.getLocalizedMessage() +": Disabling URL " + m.rpcurl[m.rpcNum] + " for " + ioDisableTime + "s"); |
m.disableTime[m.rpcNum] = new Date().getTime() + ioDisableTime*1000; |
m.ioErrorCount[m.rpcNum] = 0; |
} |
} |
catch ( ParserException e ) { |
m.msg("Error: "+e.getLocalizedMessage() +": Disabling URL " + m.rpcurl[m.rpcNum] + " for 60s"); |
m.disableTime[m.rpcNum] = new Date().getTime() + 60000; |
} |
catch ( NumberFormatException e ) { |
m.msg("Error: "+e.getLocalizedMessage() +": Disabling URL " + m.rpcurl[m.rpcNum] + " for 60s"); |
m.disableTime[m.rpcNum] = new Date().getTime() + 60000; |
} |
catch ( IndexOutOfBoundsException e ) { |
m.msg("Error: "+e.getLocalizedMessage() +": Disabling URL " + m.rpcurl[m.rpcNum] + " for 60s"); |
m.disableTime[m.rpcNum] = new Date().getTime() + 60000; |
} |
catch ( Exception e ) { |
m.msg("Error: "+e.getLocalizedMessage()+": Disabling device"); |
m.fatalError = "Error: "+e.getLocalizedMessage()+": Device disabled since " + BTCMiner.dateFormat.format( new Date() ); |
v.removeElementAt(i); |
} |
|
tu += m.usbTime; |
|
if ( ! m.clusterMode ) { |
BTCMiner.newBlockMonitor.print(); |
} |
} |
} |
|
t0 = new Date().getTime() - t0; |
usbTime = usbTime * 0.9998 + tu; |
networkTime = networkTime * 0.9998 + t0 - tu; |
timeW = timeW * 0.9998 + 1; |
} |
else { |
t0 = 0; |
} |
|
t0 = minQueryInterval - t0; |
if ( t0 > 5 ) { |
try { |
Thread.sleep( t0 ); |
} |
catch ( InterruptedException e) { |
} |
} |
} |
} |
|
// ******* printInfo *********************************************************** |
public void printInfo( String name ) { |
int oc = 0; |
double gt=0.0, gtw=0.0, st=0.0, stw=0.0; |
for ( int i=v.size()-1; i>=0; i-- ) { |
BTCMiner m = v.elementAt(i); |
oc += m.overflowCount; |
m.overflowCount = 0; |
|
st += m.submitTime; |
stw += m.submitTimeW; |
|
gt += m.getTime; |
gtw += m.getTimeW; |
} |
|
BTCMiner.printMsg2(name + ": poll loop time: " + Math.round((usbTime+networkTime)/timeW) + "ms (USB: " + Math.round(usbTime/timeW) + "ms network: " + Math.round(networkTime/timeW) + "ms) getwork time: " |
+ Math.round(gt/gtw) + "ms submit time: " + Math.round(st/stw) + "ms" ); |
if ( oc > 0 ) |
BTCMiner.printMsg( name + ": Warning: " + oc + " overflows occured. This is usually caused by a slow network connection." ); |
} |
} |
|
|
// ***************************************************************************** |
// ***************************************************************************** |
// ******* BTCMiner ************************************************************ |
// ***************************************************************************** |
// ***************************************************************************** |
class BTCMiner implements MsgObj { |
|
// ***************************************************************************** |
// ******* static methods ****************************************************** |
// ***************************************************************************** |
static final int maxRpcCount = 32; |
static String[] rpcurl = new String[maxRpcCount]; |
static String[] rpcuser = new String[maxRpcCount]; |
static String[] rpcpassw = new String[maxRpcCount]; |
static int rpcCount = 1; |
|
static String longPollURL = null; |
static String longPollUser = ""; |
static String longPollPassw = ""; |
|
static int bcid = -1; |
|
static String firmwareFile = null; |
static boolean printBus = false; |
|
public final static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); |
|
static PrintStream logFile = null; |
static PrintStream logFile2 = null; |
static PrintStream blkLogFile = null; |
|
static InputStream in2 = null; |
static String in2FileName = null; |
|
static double connectionEffort = 2.0; |
|
static NewBlockMonitor newBlockMonitor = null; |
|
static boolean forceEP0Config = false; |
|
static double overheatThreshold = 0.04; |
|
static double maxMaxErrorRate = 0.05; |
|
|
|
static boolean targetCheck = false; |
|
static String filterSN = null; |
|
public static final String[] dummyFirmwareNames = { |
"USB-FPGA Module 1.15d (default)" , |
"USB-FPGA Module 1.15x (default)" , |
"USB-FPGA Module 1.15y (default)" |
}; |
|
public static final int[] defaultFirmwarePID1 = { |
13 , |
13 , |
15 |
}; |
|
public static final String[] firmwareFiles = { |
"ztex_ufm1_15d4.ihx" , |
"ztex_ufm1_15d4.ihx" , |
"ztex_ufm1_15y1.ihx" |
}; |
|
public static final byte[] sha256_init_state = hexStrToData("67e6096a85ae67bb72f36e3c3af54fa57f520e518c68059babd9831f19cde05b"); |
public static final byte[] sha256_pad1 = hexStrToData("000000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000"); |
|
// ******* printMsg ************************************************************* |
public static void printMsg ( String msg ) { |
System.out.println( msg ); |
if ( logFile != null ) |
logFile.println( dateFormat.format( new Date() ) + ": " + msg ); |
if ( logFile2 != null ) |
logFile2.println( dateFormat.format( new Date() ) + ": " + msg ); |
} |
|
// ******* printMsg2 ************************************************************ |
public static void printMsg2 ( String msg ) { |
System.out.println( msg ); |
if ( logFile != null ) |
logFile.println( dateFormat.format( new Date() ) + ": " + msg ); |
} |
|
// ******* encodeBase64 ********************************************************* |
public static String encodeBase64(String s) { |
return encodeBase64(s.getBytes()); |
} |
|
public static String encodeBase64(byte[] src) { |
return encodeBase64(src, 0, src.length); |
} |
|
public static String encodeBase64(byte[] src, int start, int length) { |
final String charSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; |
byte[] encodeData = new byte[64]; |
byte[] dst = new byte[(length+2)/3 * 4 + length/72]; |
int x = 0; |
int dstIndex = 0; |
int state = 0; |
int old = 0; |
int len = 0; |
int max = length + start; |
|
for (int i = 0; i<64; i++) { |
byte c = (byte) charSet.charAt(i); |
encodeData[i] = c; |
} |
|
for (int srcIndex = start; srcIndex<max; srcIndex++) { |
x = src[srcIndex]; |
switch (++state) { |
case 1: |
dst[dstIndex++] = encodeData[(x>>2) & 0x3f]; |
break; |
case 2: |
dst[dstIndex++] = encodeData[((old<<4)&0x30) |
| ((x>>4)&0xf)]; |
break; |
case 3: |
dst[dstIndex++] = encodeData[((old<<2)&0x3C) |
| ((x>>6)&0x3)]; |
dst[dstIndex++] = encodeData[x&0x3F]; |
state = 0; |
break; |
} |
old = x; |
if (++len >= 72) { |
dst[dstIndex++] = (byte) '\n'; |
len = 0; |
} |
} |
|
switch (state) { |
case 1: dst[dstIndex++] = encodeData[(old<<4) & 0x30]; |
dst[dstIndex++] = (byte) '='; |
dst[dstIndex++] = (byte) '='; |
break; |
case 2: dst[dstIndex++] = encodeData[(old<<2) & 0x3c]; |
dst[dstIndex++] = (byte) '='; |
break; |
} |
return new String(dst); |
} |
|
// ******* hexStrToData ******************************************************** |
public static byte[] hexStrToData( String str ) throws NumberFormatException { |
if ( str.length() % 2 != 0 ) |
throw new NumberFormatException("Invalid length of string"); |
byte[] buf = new byte[str.length() >> 1]; |
for ( int i=0; i<buf.length; i++) { |
buf[i] = (byte) Integer.parseInt( str.substring(i*2,i*2+2), 16); |
} |
return buf; |
} |
|
public static void hexStrToData( String str, byte[] buf ) throws NumberFormatException { |
if ( str.length()<buf.length*2 ) |
throw new NumberFormatException("Invalid length of string"); |
for ( int i=0; i<buf.length; i++) { |
buf[i] = (byte) Integer.parseInt( str.substring(i*2,i*2+2), 16); |
} |
} |
|
// ******* hexStrToData2 ******************************************************** |
public static void hexStrToData2( String str, byte[] buf ) throws NumberFormatException { |
if ( str.length()<buf.length*2 ) |
throw new NumberFormatException("Invalid length of string"); |
for ( int i=0; i<buf.length; i++) { |
buf[i] = (byte) (Integer.parseInt( str.substring(i*2,i*2+1), 16) + Integer.parseInt( str.substring(i*2+1,i*2+2), 16)*16); |
} |
} |
|
// ******* dataToHexStr ******************************************************** |
public static String dataToHexStr (byte[] data) { |
final char hexchars[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; |
char[] buf = new char[data.length*2]; |
for ( int i=0; i<data.length; i++) { |
buf[i*2+0] = hexchars[(data[i] & 255) >> 4]; |
buf[i*2+1] = hexchars[(data[i] & 15)]; |
} |
return new String(buf); |
} |
|
// ******* dataToInt ********************************************************** |
public static int dataToInt (byte[] buf, int offs) { |
if ( offs + 4 > buf.length ) |
throw new NumberFormatException("Invalid length of data"); |
return (buf[offs+0] & 255) | ((buf[offs+1] & 255)<<8) | ((buf[offs+2] & 255)<<16) | ((buf[offs+3] & 255)<<24); |
} |
|
// ******* intToData ********************************************************** |
public static byte[] intToData (int n) { |
byte[] buf = new byte[4]; |
buf[0] = (byte) (n & 255); |
buf[1] = (byte) ((n >> 8) & 255); |
buf[2] = (byte) ((n >> 16) & 255); |
buf[3] = (byte) ((n >> 24) & 255); |
return buf; |
} |
|
public static void intToData (int n, byte[] buf, int offs) { |
buf[offs+0] = (byte) (n & 255); |
buf[offs+1] = (byte) ((n >> 8) & 255); |
buf[offs+2] = (byte) ((n >> 16) & 255); |
buf[offs+3] = (byte) ((n >> 24) & 255); |
} |
|
// ******* intToHexStr ******************************************************** |
public static String intToHexStr (int n) { |
return dataToHexStr( reverse( intToData ( n ) ) ); |
} |
|
// ******* reverse ************************************************************ |
public static byte[] reverse (byte[] data) { |
byte[] buf = new byte[data.length]; |
for ( int i=0; i<data.length; i++) |
buf[data.length-i-1] = data[i]; |
return buf; |
} |
|
// ******* jsonParse *********************************************************** |
// does not work if parameter name is a part of a parameter value |
public static String jsonParse (String response, String parameter) throws ParserException { |
int lp = parameter.length(); |
int i = 0; |
while ( i+lp<response.length() && !parameter.equalsIgnoreCase(response.substring(i,i+lp)) ) |
i++; |
i+=lp; |
if ( i>=response.length() ) |
throw new ParserException( "jsonParse: Parameter `"+parameter+"' not found" ); |
while ( i<response.length() && response.charAt(i) != ':' ) |
i++; |
i+=1; |
while ( i<response.length() && (byte)response.charAt(i) <= 32 ) |
i++; |
if ( i>=response.length() ) |
throw new ParserException( "jsonParse: Value expected after `"+parameter+"'" ); |
int j=i; |
if ( i<response.length() && response.charAt(i)=='"' ) { |
i+=1; |
j=i; |
while ( j<response.length() && response.charAt(j) != '"' ) |
j++; |
if ( j>=response.length() ) |
throw new ParserException( "jsonParse: No closing `\"' found for value of paramter `"+parameter+"'" ); |
} |
else { |
while ( j<response.length() && response.charAt(j) != ',' && response.charAt(j) != /*{*/'}' ) |
j++; |
} |
return response.substring(i,j); |
} |
|
|
// ******* checkSnString ******************************************************* |
// make sure that snString is 10 chars long |
public static String checkSnString ( String snString ) { |
if ( snString.length()>10 ) { |
snString = snString.substring(0,10); |
System.err.println( "Serial number too long (max. 10 characters), truncated to `" + snString + "'" ); |
} |
while ( snString.length()<10 ) |
snString = '0' + snString; |
return snString; |
} |
|
|
// ******* getType ************************************************************* |
private static String getType ( ZtexDevice1 pDev ) { |
byte[] buf = new byte[64]; |
try { |
Ztex1v1 ztex = new Ztex1v1 ( pDev ); |
ztex.vendorRequest2( 0x82, "Read descriptor", 0, 0, buf, 64 ); |
if ( buf[0] < 1 || buf[0] > 5 ) |
throw new FirmwareException("Invalid BTCMiner descriptor version"); |
|
int i0 = buf[0] > 4 ? 11 : ( buf[0] > 2 ? 10 : 8 ); |
int i = i0; |
while ( i<64 && buf[i]!=0 ) |
i++; |
if ( i < i0+1 ) |
throw new FirmwareException("Invalid bitstream file name"); |
|
return new String(buf, i0, i-i0); |
} |
catch ( Exception e ) { |
System.out.println("Warning: "+e.getLocalizedMessage() ); |
} |
return null; |
} |
|
|
// ******* sha256_transform **************************************************** |
public static void sha256_transform(byte[] state, int state_offs, byte[] data, int data_offs, byte[] out, int out_offs) throws NumberFormatException { |
if ( state.length < state_offs+32 ) |
throw new NumberFormatException("Invalid length of state"); |
if ( data.length < data_offs+64 ) |
throw new NumberFormatException("Invalid length of data"); |
if ( out.length < out_offs+32 ) |
throw new NumberFormatException("Invalid length of out"); |
|
final int[] k = { |
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, |
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, |
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, |
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, |
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, |
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, |
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, |
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, |
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, |
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, |
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, |
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, |
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, |
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, |
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, |
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 |
}; |
|
int A = dataToInt(state,state_offs+0); |
int B = dataToInt(state,state_offs+4); |
int C = dataToInt(state,state_offs+8); |
int D = dataToInt(state,state_offs+12); |
int E = dataToInt(state,state_offs+16); |
int F = dataToInt(state,state_offs+20); |
int G = dataToInt(state,state_offs+24); |
int H = dataToInt(state,state_offs+28); |
int T, T2; |
int[] wBuf = new int[64]; |
|
for (int i = 0; i < 16; i++) |
wBuf[i] = dataToInt(data, data_offs+4*i); |
|
for (int i = 16; i < 64; i++) { |
T = wBuf[i - 2]; |
T2 = wBuf[i - 15]; |
wBuf[i] = (((T >>> 17) | (T << 15)) ^ ((T >>> 19) | (T << 13)) ^ (T >>> 10)) + wBuf[i - 7] + (((T2 >>> 7) | (T2 << 25)) ^ ((T2 >>> 18) | (T2 << 14)) ^ (T2 >>> 3)) + wBuf[i - 16]; |
} |
|
for (int i=0; i < 64; i++) { |
T = H + (((E >>> 6) | (E << 26)) ^ ((E >>> 11) | (E << 21)) ^ ((E >>> 25) | (E << 7))) + ((E & F) ^ (~E & G)) + k[i] + wBuf[i]; |
T2 = (((A >>> 2) | (A << 30)) ^ ((A >>> 13) | (A << 19)) ^ ((A >>> 22) | (A << 10))) + ((A & B) ^ (A & C) ^ (B & C)); |
H = G; |
G = F; |
F = E; |
E = D + T; |
D = C; |
C = B; |
B = A; |
A = T + T2; |
} |
|
intToData( A+dataToInt(state,state_offs+0), out, out_offs+0 ); |
intToData( B+dataToInt(state,state_offs+4), out, out_offs+4 ); |
intToData( C+dataToInt(state,state_offs+8), out, out_offs+8 ); |
intToData( D+dataToInt(state,state_offs+12), out, out_offs+12 ); |
intToData( E+dataToInt(state,state_offs+16), out, out_offs+16 ); |
intToData( F+dataToInt(state,state_offs+20), out, out_offs+20 ); |
intToData( G+dataToInt(state,state_offs+24), out, out_offs+24 ); |
intToData( H+dataToInt(state,state_offs+28), out, out_offs+28 ); |
} |
|
public static void printBus ( ZtexScanBus1 bus ) { |
for (int i=0; i<bus.numberOfDevices(); i++ ) { |
ZtexDevice1 dev = bus.device(i); |
System.out.println( i + ": " + dev.toString() ); |
try { |
byte buf[] = new byte[6]; |
new Ztex1v1(dev).macRead(buf); |
System.out.println(" MAC address: " + dataToHexStr(buf)); |
} |
catch (Exception e) { |
} |
} |
} |
|
// ***************************************************************************** |
// ******* non-static methods ************************************************** |
// ***************************************************************************** |
private Ztex1v1 ztex = null; |
private int fpgaNum = 0; |
|
public int numNonces, offsNonces, freqM, freqMDefault, freqMaxM, extraSolutions; |
public double freqM1; |
public double hashesPerClock; |
private String bitFileName = null; |
public String name; |
public String fatalError = null; |
private boolean suspendSupported = false; |
|
public int ioErrorCount[] = new int[maxRpcCount]; |
public long disableTime[] = new long[maxRpcCount]; |
|
public int rpcNum = 0; |
private int prevRpcNum = 0; |
|
public boolean verbose = false; |
public boolean clusterMode = false; |
|
public Vector<LogString> logBuf = new Vector<LogString>(); |
|
private byte[] dataBuf = new byte[128]; |
private byte[] dataBuf2 = new byte[128]; |
private byte[] midstateBuf = new byte[32]; |
private byte[] sendBuf = new byte[44]; |
private byte[] hashBuf = hexStrToData("00000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000010000"); |
private byte[] targetBuf = hexStrToData("ffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000"); |
private double difficulity = 1.0; |
|
private int newCount = 0; |
|
public boolean isRunning = false; |
public boolean suspended = false; |
|
MessageDigest digest = null; |
|
public int[] lastGoldenNonces = { 0, 0, 0, 0, 0, 0, 0, 0 }; |
public int[] goldenNonce, nonce, hash7; |
public int submittedCount = 0; |
public double totalSubmittedCount = 0.0; |
public long startTime, startTimeAdjust; |
|
public int overflowCount = 0; |
public long usbTime = 0; |
public double getTime = 0.0; |
public double getTimeW = 1e-6; |
public double submitTime = 0.0; |
public double submitTimeW = 1e-6; |
|
public long maxPollInterval = 20000; |
public long infoInterval = 15000; |
|
public long lastGetWorkTime = 0; |
public long ignoreErrorTime = 0; |
public long lastInfoTime = 0; |
|
public double[] errorCount = new double[256]; |
public double[] errorWeight = new double[256]; |
public double[] errorRate = new double[256]; |
public double[] maxErrorRate = new double[256]; |
public final double errorHysteresis = 0.1; // in frequency steps |
|
private double maxHashRate = 0; |
|
private int numberOfFpgas = 0; |
private int[] fpgaMap; |
|
// ******* BTCMiner ************************************************************ |
// constructor |
public BTCMiner ( Ztex1v1 pZtex, String firmwareFile, boolean v ) throws UsbException, FirmwareException, NoSuchAlgorithmException { |
|
digest = MessageDigest.getInstance("SHA-256"); |
verbose = v; |
|
ztex = pZtex; |
ztex.tempSensorUpdateInterval = 1000; |
ztex.enableExtraFpgaConfigurationChecks = true; |
|
String snString=null; |
if ( ( ztex.dev().productId(2)==0) && (firmwareFile==null) ) { |
for ( int j=0; j<defaultFirmwarePID1.length; j++ ) |
if ( defaultFirmwarePID1[j]==ztex.dev().productId(1) && ztex.dev().productString().equals(dummyFirmwareNames[j]) ) |
firmwareFile = firmwareFiles[j]; |
if ( firmwareFile != null ) { |
msg("Using firmware `" + firmwareFile + "'" + " for `" + ztex.dev().productString() +"'" ); |
snString = ztex.dev().snString(); |
} |
} |
|
if ( firmwareFile != null ) { |
try { |
ZtexIhxFile1 ihxFile = new ZtexIhxFile1( firmwareFile ); |
if ( snString != null ) |
ihxFile.setSnString( snString ); |
ztex.uploadFirmware( ihxFile, false ); |
} |
catch ( Exception e ) { |
throw new FirmwareException ( e.getLocalizedMessage() ); |
} |
} |
|
if ( ! ztex.valid() || ztex.dev().productId(0)!=10 || ztex.dev().productId(2)!=1 ) |
throw new FirmwareException("Wrong or no firmware"); |
|
getDescriptor(); |
|
goldenNonce = new int[numNonces*(1+extraSolutions)]; |
nonce = new int[numNonces]; |
hash7 = new int[numNonces]; |
|
name = bitFileName+"-"+ztex.dev().snString(); |
msg( "New device: "+ descriptorInfo() ); |
try { |
byte buf[] = new byte[6]; |
ztex.macRead(buf); |
msg("MAC address: " + dataToHexStr(buf)); |
} |
catch (Exception e) { |
msg("No mac address support"); |
} |
|
|
// long d = Math.round( 2500.0 / (freqM1 * (freqMaxM+1) * numNonces) * 1000.0 ); |
// if ( d < maxPollInterval ) maxPollInterval=d; |
|
numberOfFpgas = 0; |
try { |
fpgaMap = new int[ztex.numberOfFpgas()]; |
for (int i=0; i<ztex.numberOfFpgas(); i++ ) { |
try { |
ztex.selectFpga(i); |
msg("FPGA "+ (i+1) + ": configuration time: " + ( forceEP0Config ? ztex.configureFpgaLS( "fpga/"+bitFileName+".bit" , true, 2 ) : ztex.configureFpga( "fpga/"+bitFileName+".bit" , true, 2 ) ) + " ms"); |
try { |
Thread.sleep( 100 ); |
} |
catch ( InterruptedException e) { |
} |
fpgaMap[numberOfFpgas] = i; |
numberOfFpgas += 1; |
} |
catch ( Exception e ) { |
msg( "Error configuring FPGA " + i + ": " + e.getLocalizedMessage() ); |
} |
} |
} |
catch ( InvalidFirmwareException e ) { |
throw new FirmwareException( e.getLocalizedMessage() ); |
} |
|
if ( numberOfFpgas < 1 ) |
throw new FirmwareException("No FPGA's found"); |
|
fpgaNum = fpgaMap[0]; |
name += "-" + (fpgaNum+1); |
msg( "New FPGA" ); |
freqM = -1; |
updateFreq(); |
|
lastInfoTime = new Date().getTime(); |
|
for (int i=0; i<255; i++) { |
errorCount[i] = 0; |
errorWeight[i] = 0; |
errorRate[i] = 0; |
maxErrorRate[i] = 0; |
} |
maxHashRate = freqMDefault + 1.0; |
|
startTime = new Date().getTime(); |
startTimeAdjust = startTime; |
|
for (int i=0; i<rpcCount; i++) { |
disableTime[i] = 0; |
ioErrorCount[i] = 0; |
} |
|
if ( newBlockMonitor == null ) { |
newBlockMonitor = new NewBlockMonitor(); |
} |
|
} |
|
|
public BTCMiner ( ZtexDevice1 pDev, String firmwareFile, boolean v ) throws UsbException, FirmwareException, NoSuchAlgorithmException { |
this ( new Ztex1v1 ( pDev ), firmwareFile, v ); |
} |
|
|
public BTCMiner ( Ztex1v1 pZtex, int pFpgaNum, boolean v ) throws UsbException, FirmwareException, NoSuchAlgorithmException { |
digest = MessageDigest.getInstance("SHA-256"); |
verbose = v; |
|
ztex = pZtex; |
fpgaNum = pFpgaNum; |
|
if ( ! ztex.valid() || ztex.dev().productId(0)!=10 || ztex.dev().productId(2)!=1 || ( ztex.dev().productId(3)<1 && ztex.dev().productId(3)>2 ) ) |
throw new FirmwareException("Wrong or no firmware"); |
|
getDescriptor(); |
|
goldenNonce = new int[numNonces*(1+extraSolutions)]; |
nonce = new int[numNonces]; |
hash7 = new int[numNonces]; |
|
name = bitFileName+"-"+ztex.dev().snString()+"-"+(fpgaNum+1); |
|
try { |
msg( "New FPGA" ); |
freqM = -1; |
updateFreq(); |
|
lastInfoTime = new Date().getTime(); |
} |
catch ( Exception e ) { |
throw new FirmwareException ( e.getLocalizedMessage() ); |
} |
|
|
for (int i=0; i<255; i++) { |
errorCount[i] = 0; |
errorWeight[i] = 0; |
errorRate[i] = 0; |
maxErrorRate[i] = 0; |
} |
maxHashRate = freqMDefault + 1.0; |
|
startTime = new Date().getTime(); |
startTimeAdjust = startTime; |
|
for (int i=0; i<rpcCount; i++) { |
disableTime[i] = 0; |
ioErrorCount[i] = 0; |
} |
|
} |
|
// ******* ztex **************************************************************** |
public Ztex1v1 ztex() { |
return ztex; |
} |
|
// ******* numberofFpgas ******************************************************* |
public int numberOfFpgas() { |
return numberOfFpgas; |
} |
|
// ******* selectFpga ********************************************************** |
public void selectFpga() throws UsbException, InvalidFirmwareException, IndexOutOfBoundsException { |
ztex.selectFpga(fpgaNum); |
} |
|
// ******* fpgaNum ************************************************************* |
public int fpgaNum() { |
return fpgaNum; |
} |
|
public int fpgaNum(int n) throws IndexOutOfBoundsException { // only valid for root miner |
if ( n<0 || n>=numberOfFpgas ) |
throw new IndexOutOfBoundsException( "fpgaNum: Invalid FPGA number" ); |
return fpgaMap[n]; |
} |
|
// ******* msg ***************************************************************** |
public void msg(String s) { |
if ( clusterMode ) { |
synchronized ( logBuf ) { |
logBuf.add( new LogString( s ) ); |
} |
} |
else { |
printMsg( ( name!=null ? name + ": " : "" ) + s ); |
} |
} |
|
// ******* dmsg ***************************************************************** |
void dmsg(String s) { |
if ( verbose ) |
msg(s); |
} |
|
// ******* print *************************************************************** |
public void print () { |
synchronized ( logBuf ) { |
for ( int j=0; j<logBuf.size(); j++ ) { |
LogString ls = logBuf.elementAt(j); |
System.out.println( name + ": " + ls.msg ); |
if ( logFile != null ) { |
logFile.println( dateFormat.format(ls.time) + ": " + name + ": " + ls.msg ); |
} |
if ( logFile2 != null ) { |
logFile2.println( dateFormat.format(ls.time) + ": " + name + ": " + ls.msg ); |
} |
} |
logBuf.clear(); |
} |
} |
|
// ******* httpGet ************************************************************* |
public static String httpGet(MsgObj msgObj, String url, String user, String passw, String request) throws MalformedURLException, IOException { |
HttpURLConnection con = (HttpURLConnection) new URL(url).openConnection(); |
con.setRequestMethod("POST"); |
con.setConnectTimeout((int) Math.round(2000.0*BTCMiner.connectionEffort)); |
con.setReadTimeout(url == longPollURL ? 1000000 : (int) Math.round(2000.0*BTCMiner.connectionEffort)); |
con.setRequestProperty("Authorization", "Basic " + encodeBase64(user + ":" + passw)); |
con.setRequestProperty("Accept-Encoding", "gzip,deflate"); |
con.setRequestProperty("Content-Type", "application/json"); |
con.setRequestProperty("Cache-Control", "no-cache"); |
con.setRequestProperty("User-Agent", "ztexBTCMiner"); |
con.setRequestProperty("X-Mining-Extensions", "longpoll midstate submitold"); |
con.setRequestProperty("Content-Length", "" + request.length()); |
con.setUseCaches(false); |
con.setDoInput(true); |
con.setDoOutput(true); |
|
// Send request |
OutputStreamWriter wr = new OutputStreamWriter ( con.getOutputStream ()); |
wr.write(request); |
wr.flush(); |
wr.close(); |
|
// read response header |
String str = con.getHeaderField("X-Reject-Reason"); |
if( str != null && ! str.equals("") && ! str.equals("high-hash") && ! str.equals("stale-prevblk") && ! str.equals("duplicate") ) { |
msgObj.msg("Warning: Rejected block: " + str); |
} |
|
// read response header |
str = con.getHeaderField("X-Long-Polling"); |
if ( str != null && ! str.equals("") && longPollURL==null ) { |
synchronized ( BTCMiner.newBlockMonitor ) { |
if ( longPollURL==null ) { |
longPollURL = (str.length()>7 && str.substring(0,4).equalsIgnoreCase("http") ) ? str : url+str; |
msgObj.msg("Using LongPolling URL " + longPollURL); |
longPollUser = user; |
longPollPassw = passw; |
} |
} |
} |
|
// read response |
InputStream is; |
if ( con.getContentEncoding() == null ) |
is = con.getInputStream(); |
else if ( con.getContentEncoding().equalsIgnoreCase("gzip") ) |
is = new GZIPInputStream(con.getInputStream()); |
else if (con.getContentEncoding().equalsIgnoreCase("deflate") ) |
is = new InflaterInputStream(con.getInputStream()); |
else |
throw new IOException( "httpGet: Unknown encoding: " + con.getContentEncoding() ); |
|
byte[] buf = new byte[1024]; |
StringBuffer response = new StringBuffer(); |
int len; |
while ( (len = is.read(buf)) > 0 ) { |
response.append(new String(buf,0,len)); |
} |
is.close(); |
con.disconnect(); |
|
return response.toString(); |
} |
|
/* String httpGet(String request) throws MalformedURLException, IOException { |
return httpGet(rpcurl[rpcNum], rpcuser[rpcNum], rpcpassw[rpcNum], request ) |
} */ |
|
// ******* bitcoinRequest ****************************************************** |
public static String bitcoinRequest( MsgObj msgObj, String url, String user, String passw, String request, String params) throws MalformedURLException, IOException { |
bcid += 1; |
return httpGet( msgObj, url, user, passw, "{\"jsonrpc\":\"1.0\",\"id\":" + bcid + ",\"method\":\""+ request + "\",\"params\":["+ (params.equals("") ? "" : ("\""+params+"\"")) + "]}" ); |
} |
|
public String bitcoinRequest( String request, String params) throws MalformedURLException, IOException { |
String s = bitcoinRequest( this, rpcurl[rpcNum], rpcuser[rpcNum], rpcpassw[rpcNum], request, params ); |
ioErrorCount[rpcNum] = 0; |
return s; |
} |
|
|
// ******* getWork ************************************************************* |
public boolean getWork() throws UsbException, MalformedURLException, IOException, ParserException { |
|
long t = new Date().getTime(); |
|
int i = 0; |
while ( i<rpcCount && (disableTime[i]>t) ) |
i++; |
if ( i >= rpcCount ) |
return false; |
|
rpcNum = i; |
String response = bitcoinRequest("getwork","" ); |
t = new Date().getTime() - t; |
getTime = getTime * 0.99 + t; |
getTimeW = getTimeW * 0.99 + 1; |
|
try { |
hexStrToData(jsonParse(response,"data"), dataBuf2); |
newBlockMonitor.checkNew( dataBuf2 ); |
} |
catch ( NumberFormatException e ) { |
} |
|
if ( newCount >= newBlockMonitor.newCount || newBlockMonitor.submitOld ) { |
while ( getNonces() ) {} |
} |
|
newCount = newBlockMonitor.newCount; |
|
try { |
hexStrToData(jsonParse(response,"data"), dataBuf); |
} |
catch ( NumberFormatException e ) { |
throw new ParserException( e.getLocalizedMessage() ); |
} |
|
|
|
try { |
if ( targetCheck ) { |
hexStrToData(jsonParse(response,"target"), targetBuf); |
} |
else { |
hexStrToData("ffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000", targetBuf); |
} |
} |
catch ( Exception e ) { |
hexStrToData("ffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000", targetBuf); |
} |
|
double d = 1.0; |
difficulity = 0; |
for (int j=0; j<28; j++) { |
difficulity += (targetBuf[j] & 255) * d; |
d*=256; |
} |
difficulity = d / difficulity; |
|
boolean b = false; |
int k = dataBuf.length - sha256_pad1.length; |
for ( int j=0; j<sha256_pad1.length; j++ ) |
if ( sha256_pad1[j] != dataBuf[k+j] ) { |
b=true; |
dataBuf[k+j] = sha256_pad1[j]; |
} |
if ( b ) |
msg("Warning: Invalid data from " + rpcurl[rpcNum]); |
|
|
sha256_transform( sha256_init_state,0, dataBuf,0, midstateBuf,0); |
|
lastGetWorkTime = new Date().getTime(); |
prevRpcNum = i; |
return true; |
} |
|
// ******* submitWork ********************************************************** |
public void submitWork( int n ) throws MalformedURLException, IOException { |
long t = new Date().getTime(); |
|
intToData(n, dataBuf, 76); |
|
dmsg( "Submitting new nonce " + intToHexStr(n) ); |
if ( blkLogFile != null ) |
blkLogFile.println( dateFormat.format( new Date() ) + ": " + name + ": submitted " + dataToHexStr(dataBuf) + " to " + rpcurl[rpcNum]); |
String response = bitcoinRequest( "getwork", dataToHexStr(dataBuf) ); |
String err = null; |
try { |
err = jsonParse(response,"error"); |
} |
catch ( ParserException e ) { |
} |
if ( err!=null && !err.equals("null") && !err.equals("") ) |
msg( "Error attempting to submit new nonce: " + err ); |
|
for (int i=lastGoldenNonces.length-1; i>0; i-- ) |
lastGoldenNonces[i]=lastGoldenNonces[i-1]; |
lastGoldenNonces[0] = n; |
|
t = new Date().getTime() - t; |
submitTime = submitTime * 0.99 + t; |
submitTimeW = submitTimeW * 0.99 + 1; |
} |
|
// ******* initWork ********************************************************** |
public void initWork (byte[] data, byte[] midstate) { |
if ( data.length != 128 ) |
throw new NumberFormatException("Invalid length of data"); |
if ( midstate.length != 32 ) |
throw new NumberFormatException("Invalid length of midstate"); |
for (int i=0; i<128; i++) |
dataBuf[i] = data[i]; |
for (int i=0; i<32; i++) |
midstateBuf[i] = midstate[i]; |
} |
|
// ******* getHash *********************************************************** |
public int getHash(int n) throws NumberFormatException { |
intToData(n, dataBuf, 76); |
sha256_transform( midstateBuf,0, dataBuf,64, hashBuf,0 ); |
sha256_transform( sha256_init_state,0, hashBuf,0, hashBuf,0 ); |
return dataToInt( hashBuf,28 ); |
} |
|
// ******* compareWithTarget *************************************************** |
// returns true if smaller than or equal to target |
public boolean compareWithTarget(int n) throws NumberFormatException { |
intToData(n, dataBuf, 76); |
sha256_transform( midstateBuf,0, dataBuf,64, hashBuf,0 ); |
sha256_transform( sha256_init_state,0, hashBuf,0, hashBuf,0 ); |
for ( int i=0; i<32; i++ ) { |
int j=i+3-2*(i%4); |
if ( (hashBuf[31-j] & 255) < (targetBuf[31-i] & 255) ) |
return true; |
if ( (hashBuf[31-j] & 255) > (targetBuf[31-i] & 255) ) |
return false; |
} |
return true; |
} |
|
// ******* getMidstate ********************************************************* |
public byte[] getMidstate() { |
sha256_transform( sha256_init_state,0, dataBuf,0, hashBuf,0); |
return hashBuf; |
} |
|
// ******* sendData *********************************************************** |
public void sendData () throws UsbException { |
for ( int i=0; i<12; i++ ) |
sendBuf[i] = dataBuf[i+64]; |
for ( int i=0; i<32; i++ ) |
sendBuf[i+12] = midstateBuf[i]; |
|
long t = new Date().getTime(); |
synchronized (ztex) { |
try { |
selectFpga(); |
} |
catch ( InvalidFirmwareException e ) { |
// shouldn't occur |
} |
ztex.vendorCommand2( 0x80, "Send hash data", 0, 0, sendBuf, 44 ); |
} |
usbTime += new Date().getTime() - t; |
|
ignoreErrorTime = new Date().getTime() + 500; // ignore errors for next 1s |
for ( int i=0; i<numNonces; i++ ) |
nonce[i] = 0; |
isRunning = true; |
} |
|
// ******* setFreq ************************************************************* |
public void setFreq (int m) throws UsbException { |
if ( m > freqMaxM ) m = freqMaxM; |
|
long t = new Date().getTime(); |
synchronized (ztex) { |
try { |
selectFpga(); |
} |
catch ( InvalidFirmwareException e ) { |
// shouldn't occur |
} |
ztex.vendorCommand( 0x83, "Send hash data", m, 0 ); |
} |
usbTime += new Date().getTime() - t; |
|
ignoreErrorTime = new Date().getTime() + 2000; // ignore errors for next 2s |
} |
|
// ******* suspend ************************************************************* |
public boolean suspend ( ) { |
suspended = true; |
if ( suspendSupported ) { |
try { |
synchronized (ztex) { |
selectFpga(); |
ztex.vendorCommand( 0x84, "Suspend" ); |
} |
} |
catch ( Exception e ) { |
msg( "Suspend command failed: " + e.getLocalizedMessage() ); |
return false; |
} |
} |
else { |
msg( "Suspend command not supported. Update Firmware." ); |
return false; |
} |
return true; |
} |
|
// ******* updateFreq ********************************************************** |
public void updateFreq() throws UsbException { |
|
for ( int i=0; i<freqMaxM; i++ ) { |
if ( maxErrorRate[i+1]*i < maxErrorRate[i]*(i+20) ) |
maxErrorRate[i+1] = maxErrorRate[i]*(1.0+20.0/i); |
} |
|
int maxM = 0; |
while ( maxM<freqMDefault && maxErrorRate[maxM+1]<maxMaxErrorRate ) |
maxM++; |
while ( maxM<freqMaxM && errorWeight[maxM]>150 && maxErrorRate[maxM+1]<maxMaxErrorRate ) |
maxM++; |
|
int bestM=0; |
double bestR=0; |
for ( int i=0; i<=maxM; i++ ) { |
double r = (i + 1 + ( i == freqM ? errorHysteresis : 0))*(1-maxErrorRate[i]); |
if ( r > bestR ) { |
bestM = i; |
bestR = r; |
} |
} |
|
if ( bestM != freqM ) { |
msg ( "Set frequency " + ( freqM<0 ? "" : "from " + String.format("%.2f",(freqM+1)*(freqM1)) + "MHz ") + "to " + String.format("%.2f",(bestM+1)*(freqM1)) +"MHz" ); |
freqM = bestM; |
setFreq( freqM ); |
} |
|
maxM = freqMDefault; |
while ( maxM<freqMaxM && errorWeight[maxM+1]>100 ) |
maxM++; |
if ( ( bestM+1 < (1.0-overheatThreshold )*maxHashRate ) && bestM < maxM-1 ) { |
try { |
synchronized (ztex) { |
selectFpga(); |
ztex.resetFpga(); |
} |
} |
catch ( Exception e ) { |
} |
throw new UsbException("Hash rate drop of " + String.format("%.1f",(1.0-1.0*(bestM+1)/maxHashRate)*100) + "% detect. This may be caused by overheating. FPGA is shut down to prevent damage." ); |
} |
|
double temp; |
try { |
temp = ztex.tempSensorRead(fpgaNum); |
} |
catch ( Exception e ) { |
temp = tempLimit - 1e12; |
} |
if ( temp > tempLimit ) { |
try { |
synchronized (ztex) { |
selectFpga(); |
ztex.resetFpga(); |
} |
} |
catch ( Exception e ) { |
} |
|
} |
|
} |
|
// ******* getNonces *********************************************************** |
public boolean getNonces() throws UsbException, MalformedURLException, IOException { |
if ( !isRunning || disableTime[prevRpcNum] > new Date().getTime() ) return false; |
|
rpcNum = prevRpcNum; |
|
getNoncesInt(); |
|
if ( ignoreErrorTime < new Date().getTime() ) { |
errorCount[freqM] *= 0.995; |
errorWeight[freqM] = errorWeight[freqM]*0.995 + 1.0; |
for ( int i=0; i<numNonces; i++ ) { |
if ( ! checkNonce( nonce[i], hash7[i] ) ) |
errorCount[freqM] +=1.0/numNonces; |
} |
|
errorRate[freqM] = errorCount[freqM] / errorWeight[freqM] * Math.min(1.0, errorWeight[freqM]*0.01) ; |
if ( errorRate[freqM] > maxErrorRate[freqM] ) |
maxErrorRate[freqM] = errorRate[freqM]; |
if ( errorWeight[freqM] > 120 ) |
maxHashRate = Math.max(maxHashRate, (freqM+1.0)*(1-errorRate[freqM])); |
} |
|
boolean submitted = false; |
for ( int i=0; i<numNonces*(1+extraSolutions); i++ ) { |
int n = goldenNonce[i]; |
if ( n != -offsNonces ) { |
if ( compareWithTarget(n) ) { |
int j=0; |
while ( j<lastGoldenNonces.length && lastGoldenNonces[j]!=n ) |
j++; |
if (j>=lastGoldenNonces.length) { |
submitWork( n ); |
submittedCount+=1; |
totalSubmittedCount+=difficulity; |
submitted = true; |
} |
} |
} |
} |
return submitted; |
} |
|
// ******* getNoncesInt ******************************************************** |
public void getNoncesInt() throws UsbException { |
int bs = 12+extraSolutions*4; |
byte[] buf = new byte[numNonces*bs]; |
boolean overflow = false; |
|
long t = new Date().getTime(); |
synchronized (ztex) { |
try { |
selectFpga(); |
} |
catch ( InvalidFirmwareException e ) { |
// shouldn't occur |
} |
ztex.vendorRequest2( 0x81, "Read hash data", 0, 0, buf, numNonces*bs ); |
} |
usbTime += new Date().getTime() - t; |
|
// System.out.print(dataToHexStr(buf)+" "); |
for ( int i=0; i<numNonces; i++ ) { |
goldenNonce[i*(1+extraSolutions)] = dataToInt(buf,i*bs+0) - offsNonces; |
int j = dataToInt(buf,i*bs+4) - offsNonces; |
overflow |= ((j >> 4) & 0xfffffff) < ((nonce[i]>>4) & 0xfffffff); |
nonce[i] = j; |
hash7[i] = dataToInt(buf,i*bs+8); |
for ( j=0; j<extraSolutions; j++ ) |
goldenNonce[i*(1+extraSolutions)+1+j] = dataToInt(buf,i*bs+12+j*4) - offsNonces; |
} |
if ( overflow && ! PollLoop.scanMode ) |
overflowCount += 1; |
} |
|
// ******* checkNonce ******************************************************* |
public boolean checkNonce( int n, int h ) throws UsbException { |
int offs[] = { 0, 1, -1, 2, -2 }; |
// int offs[] = { 0 }; |
for (int i=0; i<offs.length; i++ ) { |
if ( getHash(n + offs[i]) == h + 0x5be0cd19 ) |
return true; |
} |
return false; |
} |
|
// ******* totalHashRate ******************************************************* |
public double totalHashRate () { |
return fatalError == null ? (freqM+1)*freqM1*(1-errorRate[freqM])*hashesPerClock : 0; |
} |
|
// ******* submittedHashRate *************************************************** |
public double submittedHashRate () { |
return fatalError == null ? 4.294967296e6 * totalSubmittedCount / (new Date().getTime()-startTime) : 0; |
} |
|
// ******* printInfo *********************************************************** |
public void printInfo( boolean force ) { |
long t = new Date().getTime(); |
if ( !force && (clusterMode || lastInfoTime+infoInterval > t || !isRunning) ) |
return; |
|
if ( fatalError != null ) { |
printMsg2(name + ": " + fatalError); |
return; |
} |
|
if ( suspended ) { |
printMsg2(name + ": Suspended"); |
return; |
} |
|
StringBuffer sb = new StringBuffer( "f=" + String.format("%.2f",(freqM+1)*freqM1)+"MHz" ); |
|
if ( errorWeight[freqM]>20 ) |
sb.append(", errorRate="+ String.format("%.2f",errorRate[freqM]*100)+"%"); |
|
if ( errorWeight[freqM]>100 ) |
sb.append(", maxErrorRate="+ String.format("%.2f",maxErrorRate[freqM]*100)+"%"); |
|
/* if ( freqM<255 && (errorWeight[freqM+1]>100.1 || maxErrorRate[freqM+1]>0.001 ) ) |
sb.append(", nextMaxErrorRate="+ String.format("%.2f",maxErrorRate[freqM+1]*100)+"%"); */ |
|
double hr = (freqM+1)*freqM1*(1-errorRate[freqM])*hashesPerClock; |
|
if ( errorWeight[freqM]>20 ) |
sb.append(", hashRate=" + String.format("%.1f", hr )+"MH/s" ); |
|
try { |
|
} |
catch ( Exception e ) { |
} |
|
sb.append(", submitted " +submittedCount+" new nonces, luckFactor=" + String.format("%.2f", submittedHashRate()/hr+0.0049 )); |
submittedCount = 0; |
|
printMsg2(name + ": " + sb.toString()); |
|
lastInfoTime = t; |
} |
|
// ******* getDescriptor ******************************************************* |
private void getDescriptor () throws UsbException, FirmwareException { |
byte[] buf = new byte[64]; |
|
ztex.vendorRequest2( 0x82, "Read descriptor", 0, 0, buf, 64 ); |
if ( buf[0] != 5 ) { |
if ( ( buf[0] != 2 ) && ( buf[0] != 4 ) ) { |
throw new FirmwareException("Invalid BTCMiner descriptor version. Firmware must be updated."); |
} |
msg("Warning: Firmware out of date"); |
} |
numNonces = (buf[1] & 255) + 1; |
offsNonces = ((buf[2] & 255) | ((buf[3] & 255) << 8)) - 10000; |
freqM1 = ( (buf[4] & 255) | ((buf[5] & 255) << 8) ) * 0.01; |
freqM = (buf[6] & 255); |
freqMaxM = (buf[7] & 255); |
if ( freqM > freqMaxM ) |
freqM = freqMaxM; |
freqMDefault = freqM; |
|
suspendSupported = buf[0] == 5; |
|
hashesPerClock = buf[0] > 2 ? ( ( (buf[8] & 255) | ((buf[9] & 255) << 8) ) +1 )/128.0 : 1.0; |
extraSolutions = buf[0] > 4 ? buf[10] : 0; |
|
int i0 = buf[0] > 4 ? 11 : ( buf[0] == 4 ? 10 : 8 ); |
int i = i0; |
while ( i<64 && buf[i]!=0 ) |
i++; |
if ( i < i0+1) |
throw new FirmwareException("Invalid bitstream file name"); |
bitFileName = new String(buf, i0, i-i0); |
|
if ( buf[0] < 4 ) { |
if ( bitFileName.substring(0,13).equals("ztex_ufm1_15b") ) |
hashesPerClock = 0.5; |
msg( "Warning: HASHES_PER_CLOCK not defined, assuming " + hashesPerClock ); |
} |
} |
|
// ******* checkUpdate ********************************************************** |
public boolean checkUpdate() { |
long t = new Date().getTime(); |
if ( !isRunning ) return true; |
if ( ignoreErrorTime > t ) return false; |
if ( newCount < newBlockMonitor.newCount) return true; |
if ( disableTime[prevRpcNum] > t ) return true; |
if ( lastGetWorkTime + maxPollInterval < t ) return true; |
for ( int i=0; i<numNonces ; i++ ) |
if ( ((nonce[i]>>1) & 0x7fffffff) > (0x38000000 + Math.round(Math.random()*0x10000000)) ) return true; |
return false; |
} |
|
// ******* descriptorInfo ****************************************************** |
public String descriptorInfo () { |
return "bitfile=" + bitFileName + " f_default=" + String.format("%.2f",freqM1 * (freqMDefault+1)) + "MHz f_max=" + String.format("%.2f",freqM1 * (freqMaxM+1))+ "MHz HpC="+hashesPerClock+"H"; |
} |
|
|
public void resetCounters () { |
while ( freqMDefault<freqM && errorWeight[freqMDefault+1]>100 ) |
freqMDefault++; |
|
for ( int i=0; i<255; i++ ) { |
errorCount[i] *= 0.05; |
errorWeight[i] *= 0.05; |
errorRate[i]=0; |
maxErrorRate[i]=0; |
} |
startTime = new Date().getTime(); |
totalSubmittedCount = 0; |
} |
|
// ***************************************************************************** |
// ******* main **************************************************************** |
// ***************************************************************************** |
public static void main (String args[]) { |
|
int devNum = -1; |
boolean workarounds = false; |
|
String firmwareFile = null, snString = null; |
boolean printBus = false; |
boolean verbose = false; |
boolean eraseFirmware = false; |
|
String filterType = null; |
String logFileName = "BTCMiner.log"; |
|
char mode = 's'; |
|
rpcCount = 1; |
rpcurl[0] = "http://127.0.0.1:8332"; |
rpcuser[0] = null; |
rpcpassw[0] = null; |
|
try { |
// init USB stuff |
LibusbJava.usb_init(); |
|
|
// scan the command line arguments |
for (int i=0; i<args.length; i++ ) { |
if ( args[i].equals("-d") ) { |
i++; |
try { |
if (i>=args.length) throw new Exception(); |
devNum = Integer.parseInt( args[i] ); |
} |
catch (Exception e) { |
throw new ParameterException("Device number expected after -d"); |
} |
} |
else if ( args[i].equals("-l") ) { |
i++; |
if (i>=args.length) { |
throw new ParameterException("Error: File name expected after `-l'"); |
} |
try { |
logFileName = args[i]; |
} |
catch (Exception e) { |
throw new ParameterException("Error: File name expected after `-l': "+e.getLocalizedMessage() ); |
} |
} |
else if ( args[i].equals("-l2") ) { |
i++; |
if (i>=args.length) { |
throw new ParameterException("Error: File name expected after `-l2'"); |
} |
try { |
logFile2 = new PrintStream ( new FileOutputStream ( args[i], true ), true ); |
} |
catch (Exception e) { |
throw new ParameterException("Error: File name expected after `-l2': "+e.getLocalizedMessage() ); |
} |
} |
else if ( args[i].equals("-bl") ) { |
i++; |
if (i>=args.length) { |
throw new ParameterException("Error: File name expected after `-dl'"); |
} |
try { |
blkLogFile = new PrintStream ( new FileOutputStream ( args[i], true ), true ); |
} |
catch (Exception e) { |
throw new ParameterException("Error: File name expected after `-bl': "+e.getLocalizedMessage() ); |
} |
} |
else if ( args[i].equals("-c") ) { |
i++; |
if (i>=args.length) { |
throw new ParameterException("Error: File name expected after `-c'"); |
} |
try { |
in2FileName = args[i]; |
new Thread() { |
public void run () { |
try { |
in2 = new FileInputStream ( in2FileName ); |
} |
catch (Exception e) { |
System.err.println("Error: File name expected after `-c': "+e.getLocalizedMessage() ); |
} |
} |
}.start(); |
} |
catch (Exception e) { |
throw new ParameterException("Error: File name expected after `-c': "+e.getLocalizedMessage() ); |
} |
} |
else if ( args[i].equals("-host") ) { |
i++; |
try { |
if (i>=args.length) throw new Exception(); |
rpcurl[0] = args[i]; |
} |
catch (Exception e) { |
throw new ParameterException("URL expected after -host"); |
} |
} |
else if ( args[i].equals("-u") ) { |
i++; |
try { |
if (i>=args.length) throw new Exception(); |
rpcuser[0] = args[i]; |
} |
catch (Exception e) { |
throw new ParameterException("User expected after -u"); |
} |
} |
else if ( args[i].equals("-p") ) { |
i++; |
try { |
if (i>=args.length) throw new Exception(); |
rpcpassw[0] = args[i]; |
} |
catch (Exception e) { |
throw new ParameterException("Password expected after -p"); |
} |
} |
else if ( args[i].equals("-b") ) { |
i+=3; |
try { |
if (i>=args.length) throw new Exception(); |
if ( rpcCount >= maxRpcCount ) |
throw new IndexOutOfBoundsException("Maximum amount of backup servers reached"); |
rpcurl[rpcCount] = args[i-2]; |
rpcuser[rpcCount] = args[i-1]; |
rpcpassw[rpcCount] = args[i]; |
rpcCount+=1; |
} |
catch (Exception e) { |
throw new ParameterException("<URL> <user name> <password> expected after -b"); |
} |
} |
else if ( args[i].equals("-lp") ) { |
i+=3; |
try { |
if (i>=args.length) throw new Exception(); |
longPollURL = args[i-2]; |
longPollUser = args[i-1]; |
longPollPassw = args[i]; |
} |
catch (Exception e) { |
throw new ParameterException("<URL> <user name> <password> expected after -lp"); |
} |
} |
else if ( args[i].equals("-f") ) { |
i++; |
try { |
if (i>=args.length) throw new Exception(); |
firmwareFile = args[i]; |
} |
catch (Exception e) { |
throw new ParameterException("ihx file name expected after -f"); |
} |
} |
else if ( args[i].equals("-pt") ) { |
i++; |
try { |
if (i>=args.length) throw new Exception(); |
filterType = args[i]; |
} |
catch (Exception e) { |
throw new ParameterException("<string> after -pt"); |
} |
} |
else if ( args[i].equals("-ps") ) { |
i++; |
try { |
if (i>=args.length) throw new Exception(); |
filterSN = args[i]; |
} |
catch (Exception e) { |
throw new ParameterException("<string> after -ps"); |
} |
} |
else if ( args[i].equals("-m") ) { |
i++; |
try { |
if (i>=args.length) throw new Exception(); |
if ( args[i].length() < 1 ) throw new Exception(); |
mode = Character.toLowerCase( args[i].charAt(0) ); |
if ( mode != 's' && mode != 't' && mode != 'p' && mode != 'c' ) throw new Exception(); |
} |
catch (Exception e) { |
throw new ParameterException("s|t|p|c expected after -m"); |
} |
} |
else if ( args[i].equals("-s") ) { |
i++; |
if ( i >= args.length ) { |
throw new ParameterException("Error: String expected after -s"); |
} |
snString = checkSnString(args[i]); |
} |
else if ( args[i].equals("-i") ) { |
printBus = true; |
} |
else if ( args[i].equals("-v") ) { |
verbose = true; |
} |
else if ( args[i].equals("-rf") ) { |
eraseFirmware = true; |
} |
else if ( args[i].equals("-ep0") ) { |
forceEP0Config = true; |
} |
else if ( args[i].equals("-tc") ) { |
targetCheck = true; |
} |
else if ( args[i].equals("-h") ) { |
System.err.println(ParameterException.helpMsg); |
System.exit(0); |
} |
else if ( args[i].equals("-n") ) { |
i++; |
try { |
if (i>=args.length) throw new Exception(); |
BTCMinerCluster.maxDevicesPerThread = Integer.parseInt( args[i] ); |
} |
catch (Exception e) { |
throw new ParameterException("Number expected after -n"); |
} |
} |
else if ( args[i].equals("-oh") ) { |
i++; |
try { |
if (i>=args.length) throw new Exception(); |
overheatThreshold = Double.parseDouble( args[i] ); |
} |
catch (Exception e) { |
throw new ParameterException("Number expected after -oh"); |
} |
} |
else if ( args[i].equals("-t") ) { |
i++; |
try { |
if (i>=args.length) throw new Exception(); |
tempLimit = Double.parseDouble( args[i] ); |
} |
catch (Exception e) { |
throw new ParameterException("Number expected after -t"); |
} |
} |
else if ( args[i].equals("-e") ) { |
i++; |
try { |
if (i>=args.length) throw new Exception(); |
double d = Double.parseDouble( args[i] ); |
if ( d < 0.0001 ) d = 0.0001; |
if ( d < maxMaxErrorRate ) maxMaxErrorRate = d; |
} |
catch (Exception e) { |
throw new ParameterException("Number expected after -e"); |
} |
} |
else throw new ParameterException("Invalid Parameter: "+args[i]); |
} |
|
logFile = new PrintStream ( new FileOutputStream ( logFileName, true ), true ); |
|
if ( overheatThreshold > 0.1001 ) System.err.println("Warning: overheat threshold set to " + overheatThreshold +": overheat shutdown may be triggered too late, recommended values: 0..0.1"); |
|
if ( BTCMinerCluster.maxDevicesPerThread < 1 ) |
BTCMinerCluster.maxDevicesPerThread = 127; |
|
if ( mode != 'c' && filterSN != null) |
filterSN = checkSnString(filterSN); |
|
if ( mode != 't' && mode != 'p' ) { |
if ( rpcuser[0] == null ) { |
System.out.print("Enter RPC user name: "); |
rpcuser[0] = new BufferedReader(new InputStreamReader( System.in) ).readLine(); |
} |
|
if ( rpcpassw[0] == null ) { |
System.out.print("Enter RPC password: "); |
rpcpassw[0] = new BufferedReader(new InputStreamReader(System.in) ).readLine(); |
} |
} |
|
/* Authenticator.setDefault(new Authenticator() { |
protected PasswordAuthentication getPasswordAuthentication() { |
return new PasswordAuthentication (BTCMiner.rpcuser, BTCMiner.rpcpassw.toCharArray()); |
} |
}); */ |
|
|
if ( mode == 's' || mode == 't' ) { |
if ( devNum < 0 ) |
devNum = 0; |
|
ZtexScanBus1 bus = new ZtexScanBus1( ZtexDevice1.ztexVendorId, ZtexDevice1.ztexProductId, filterSN==null, false, 1, filterSN, 10, 0, 1, 0 ); |
if ( bus.numberOfDevices() <= 0) { |
System.err.println("No devices found"); |
System.exit(0); |
} |
if ( printBus ) { |
printBus(bus); |
System.exit(0); |
} |
|
BTCMiner miner = new BTCMiner ( bus.device(devNum), firmwareFile, verbose ); |
if ( mode == 't' ) { // single mode |
miner.initWork( |
hexStrToData( "0000000122f3e795bb7a55b2b4a580e0dbba9f2a5aedbfc566632984000008de00000000e951667fbba0cfae7719ab2fb4ab8d291a20d387782f4610297f5899cc58b7d64e4056801a08e1e500000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000" ), |
hexStrToData( "28b81bd40a0e1b75d18362cb9a2faa61669d42913f26194f776c349e97559190" ) |
); |
|
miner.sendData ( ); |
for (int i=0; i<200; i++ ) { |
try { |
Thread.sleep( 250 ); |
} |
catch ( InterruptedException e) { |
} |
miner.getNoncesInt(); |
|
for ( int j=0; j<miner.numNonces; j++ ) { |
System.out.println( i +"-" + j + ": " + intToHexStr(miner.nonce[j]) + " " + miner.checkNonce(miner.nonce[j],miner.hash7[j]) + " " + miner.overflowCount + " " + intToHexStr(miner.goldenNonce[j*(1+miner.extraSolutions)]) + " " + intToHexStr( miner.getHash( miner.goldenNonce[j]) ) ); |
} |
} |
} |
else { // single mode |
Vector<BTCMiner> v = new Vector<BTCMiner>(); |
v.add ( miner ); |
for ( int i=1; i<miner.numberOfFpgas(); i++ ) |
v.add(new BTCMiner(miner.ztex(), miner.fpgaNum(i), verbose) ); |
System.out.println(""); |
if ( miner.ztex().numberOfFpgas()>1 ) |
System.out.println("A multi-FPGA board is detected. Use the cluster mode for additional statistics."); |
System.out.println("Disconnect device or press Ctrl-C for exit\n"); |
new PollLoop(v).run(); |
} |
} |
else if ( mode == 'p' ) { |
if ( eraseFirmware && filterType == null && filterSN == null ) |
throw new ParameterException("-rf requires -pt or -ps"); |
|
/* ZtexScanBus1 bus = ( filterType == null && filterSN == null ) |
? new ZtexScanBus1( ZtexDevice1.cypressVendorId, ZtexDevice1.cypressProductId, true, false, 1) |
: new ZtexScanBus1( ZtexDevice1.ztexVendorId, ZtexDevice1.ztexProductId, false, false, 1, null, 10, 0, 1, 0 ); */ |
ZtexScanBus1 bus = new ZtexScanBus1( ZtexDevice1.ztexVendorId, ZtexDevice1.ztexProductId, filterType==null && filterSN==null, false, 1, null, 10, 0, 0, 0 ); |
|
if ( bus.numberOfDevices() <= 0) { |
System.err.println("No devices found"); |
System.exit(0); |
} |
if ( printBus ) { |
printBus(bus); |
System.exit(0); |
} |
if ( firmwareFile == null && !eraseFirmware ) |
throw new Exception("Parameter -f or -rf required in programming mode"); |
|
int imin=0, imax=bus.numberOfDevices()-1; |
if ( devNum >= 0 ) { |
imin=devNum; |
imax=devNum; |
} |
|
ZtexIhxFile1 ihxFile = eraseFirmware ? null : new ZtexIhxFile1( firmwareFile ); |
|
int j = 0; |
for (int i=imin; i<=imax; i++ ) { |
ZtexDevice1 dev = bus.device(i); |
if ( ( filterSN == null || filterSN.equals(dev.snString()) ) && |
( filterType == null || ( (dev.productId(2) == 1) && filterType.equals(getType(dev))) ) && |
( filterType != null || filterSN != null || dev.productId(2) == 0) ) { |
Ztex1v1 ztex = new Ztex1v1 ( dev ); |
if ( snString != null && ihxFile != null ) |
ihxFile.setSnString( snString ); |
else if ( ztex.valid() && ihxFile != null ) |
ihxFile.setSnString( dev.snString() ); |
if ( eraseFirmware ) { |
ztex.eepromDisable(); |
System.out.println("EEPROM erased: " + ztex.toString()); |
} |
else { |
System.out.println("\nold: "+ztex.toString()); |
System.out.println("Firmware upload time: " + ztex.uploadFirmware( ihxFile, false ) + " ms"); |
System.out.println("EEPROM programming time: " + ztex.eepromUpload( ihxFile, false ) + " ms"); |
System.out.println("new: " + ztex.toString()); |
} |
j+=1; |
} |
} |
System.out.println("\ntotal amount of (re-)programmed devices: " + j); |
} |
else if ( mode == 'c' ) { |
new BTCMinerCluster( verbose ); |
} |
|
|
} |
catch (Exception e) { |
System.out.println("Error: "+e.getLocalizedMessage() ); |
} |
|
if ( BTCMiner.newBlockMonitor != null ) { |
BTCMiner.newBlockMonitor.running = false; |
BTCMiner.newBlockMonitor.interrupt(); |
} |
|
System.exit(0); |
|
} |
|
} |
/trunk/COPYING
0,0 → 1,674
GNU GENERAL PUBLIC LICENSE |
Version 3, 29 June 2007 |
|
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> |
Everyone is permitted to copy and distribute verbatim copies |
of this license document, but changing it is not allowed. |
|
Preamble |
|
The GNU General Public License is a free, copyleft license for |
software and other kinds of works. |
|
The licenses for most software and other practical works are designed |
to take away your freedom to share and change the works. By contrast, |
the GNU General Public License is intended to guarantee your freedom to |
share and change all versions of a program--to make sure it remains free |
software for all its users. We, the Free Software Foundation, use the |
GNU General Public License for most of our software; it applies also to |
any other work released this way by its authors. You can apply it to |
your programs, too. |
|
When we speak of free software, we are referring to freedom, not |
price. Our General Public Licenses are designed to make sure that you |
have the freedom to distribute copies of free software (and charge for |
them if you wish), that you receive source code or can get it if you |
want it, that you can change the software or use pieces of it in new |
free programs, and that you know you can do these things. |
|
To protect your rights, we need to prevent others from denying you |
these rights or asking you to surrender the rights. Therefore, you have |
certain responsibilities if you distribute copies of the software, or if |
you modify it: responsibilities to respect the freedom of others. |
|
For example, if you distribute copies of such a program, whether |
gratis or for a fee, you must pass on to the recipients the same |
freedoms that you received. You must make sure that they, too, receive |
or can get the source code. And you must show them these terms so they |
know their rights. |
|
Developers that use the GNU GPL protect your rights with two steps: |
(1) assert copyright on the software, and (2) offer you this License |
giving you legal permission to copy, distribute and/or modify it. |
|
For the developers' and authors' protection, the GPL clearly explains |
that there is no warranty for this free software. For both users' and |
authors' sake, the GPL requires that modified versions be marked as |
changed, so that their problems will not be attributed erroneously to |
authors of previous versions. |
|
Some devices are designed to deny users access to install or run |
modified versions of the software inside them, although the manufacturer |
can do so. This is fundamentally incompatible with the aim of |
protecting users' freedom to change the software. The systematic |
pattern of such abuse occurs in the area of products for individuals to |
use, which is precisely where it is most unacceptable. Therefore, we |
have designed this version of the GPL to prohibit the practice for those |
products. If such problems arise substantially in other domains, we |
stand ready to extend this provision to those domains in future versions |
of the GPL, as needed to protect the freedom of users. |
|
Finally, every program is threatened constantly by software patents. |
States should not allow patents to restrict development and use of |
software on general-purpose computers, but in those that do, we wish to |
avoid the special danger that patents applied to a free program could |
make it effectively proprietary. To prevent this, the GPL assures that |
patents cannot be used to render the program non-free. |
|
The precise terms and conditions for copying, distribution and |
modification follow. |
|
TERMS AND CONDITIONS |
|
0. Definitions. |
|
"This License" refers to version 3 of the GNU General Public License. |
|
"Copyright" also means copyright-like laws that apply to other kinds of |
works, such as semiconductor masks. |
|
"The Program" refers to any copyrightable work licensed under this |
License. Each licensee is addressed as "you". "Licensees" and |
"recipients" may be individuals or organizations. |
|
To "modify" a work means to copy from or adapt all or part of the work |
in a fashion requiring copyright permission, other than the making of an |
exact copy. The resulting work is called a "modified version" of the |
earlier work or a work "based on" the earlier work. |
|
A "covered work" means either the unmodified Program or a work based |
on the Program. |
|
To "propagate" a work means to do anything with it that, without |
permission, would make you directly or secondarily liable for |
infringement under applicable copyright law, except executing it on a |
computer or modifying a private copy. Propagation includes copying, |
distribution (with or without modification), making available to the |
public, and in some countries other activities as well. |
|
To "convey" a work means any kind of propagation that enables other |
parties to make or receive copies. Mere interaction with a user through |
a computer network, with no transfer of a copy, is not conveying. |
|
An interactive user interface displays "Appropriate Legal Notices" |
to the extent that it includes a convenient and prominently visible |
feature that (1) displays an appropriate copyright notice, and (2) |
tells the user that there is no warranty for the work (except to the |
extent that warranties are provided), that licensees may convey the |
work under this License, and how to view a copy of this License. If |
the interface presents a list of user commands or options, such as a |
menu, a prominent item in the list meets this criterion. |
|
1. Source Code. |
|
The "source code" for a work means the preferred form of the work |
for making modifications to it. "Object code" means any non-source |
form of a work. |
|
A "Standard Interface" means an interface that either is an official |
standard defined by a recognized standards body, or, in the case of |
interfaces specified for a particular programming language, one that |
is widely used among developers working in that language. |
|
The "System Libraries" of an executable work include anything, other |
than the work as a whole, that (a) is included in the normal form of |
packaging a Major Component, but which is not part of that Major |
Component, and (b) serves only to enable use of the work with that |
Major Component, or to implement a Standard Interface for which an |
implementation is available to the public in source code form. A |
"Major Component", in this context, means a major essential component |
(kernel, window system, and so on) of the specific operating system |
(if any) on which the executable work runs, or a compiler used to |
produce the work, or an object code interpreter used to run it. |
|
The "Corresponding Source" for a work in object code form means all |
the source code needed to generate, install, and (for an executable |
work) run the object code and to modify the work, including scripts to |
control those activities. However, it does not include the work's |
System Libraries, or general-purpose tools or generally available free |
programs which are used unmodified in performing those activities but |
which are not part of the work. For example, Corresponding Source |
includes interface definition files associated with source files for |
the work, and the source code for shared libraries and dynamically |
linked subprograms that the work is specifically designed to require, |
such as by intimate data communication or control flow between those |
subprograms and other parts of the work. |
|
The Corresponding Source need not include anything that users |
can regenerate automatically from other parts of the Corresponding |
Source. |
|
The Corresponding Source for a work in source code form is that |
same work. |
|
2. Basic Permissions. |
|
All rights granted under this License are granted for the term of |
copyright on the Program, and are irrevocable provided the stated |
conditions are met. This License explicitly affirms your unlimited |
permission to run the unmodified Program. The output from running a |
covered work is covered by this License only if the output, given its |
content, constitutes a covered work. This License acknowledges your |
rights of fair use or other equivalent, as provided by copyright law. |
|
You may make, run and propagate covered works that you do not |
convey, without conditions so long as your license otherwise remains |
in force. You may convey covered works to others for the sole purpose |
of having them make modifications exclusively for you, or provide you |
with facilities for running those works, provided that you comply with |
the terms of this License in conveying all material for which you do |
not control copyright. Those thus making or running the covered works |
for you must do so exclusively on your behalf, under your direction |
and control, on terms that prohibit them from making any copies of |
your copyrighted material outside their relationship with you. |
|
Conveying under any other circumstances is permitted solely under |
the conditions stated below. Sublicensing is not allowed; section 10 |
makes it unnecessary. |
|
3. Protecting Users' Legal Rights From Anti-Circumvention Law. |
|
No covered work shall be deemed part of an effective technological |
measure under any applicable law fulfilling obligations under article |
11 of the WIPO copyright treaty adopted on 20 December 1996, or |
similar laws prohibiting or restricting circumvention of such |
measures. |
|
When you convey a covered work, you waive any legal power to forbid |
circumvention of technological measures to the extent such circumvention |
is effected by exercising rights under this License with respect to |
the covered work, and you disclaim any intention to limit operation or |
modification of the work as a means of enforcing, against the work's |
users, your or third parties' legal rights to forbid circumvention of |
technological measures. |
|
4. Conveying Verbatim Copies. |
|
You may convey verbatim copies of the Program's source code as you |
receive it, in any medium, provided that you conspicuously and |
appropriately publish on each copy an appropriate copyright notice; |
keep intact all notices stating that this License and any |
non-permissive terms added in accord with section 7 apply to the code; |
keep intact all notices of the absence of any warranty; and give all |
recipients a copy of this License along with the Program. |
|
You may charge any price or no price for each copy that you convey, |
and you may offer support or warranty protection for a fee. |
|
5. Conveying Modified Source Versions. |
|
You may convey a work based on the Program, or the modifications to |
produce it from the Program, in the form of source code under the |
terms of section 4, provided that you also meet all of these conditions: |
|
a) The work must carry prominent notices stating that you modified |
it, and giving a relevant date. |
|
b) The work must carry prominent notices stating that it is |
released under this License and any conditions added under section |
7. This requirement modifies the requirement in section 4 to |
"keep intact all notices". |
|
c) You must license the entire work, as a whole, under this |
License to anyone who comes into possession of a copy. This |
License will therefore apply, along with any applicable section 7 |
additional terms, to the whole of the work, and all its parts, |
regardless of how they are packaged. This License gives no |
permission to license the work in any other way, but it does not |
invalidate such permission if you have separately received it. |
|
d) If the work has interactive user interfaces, each must display |
Appropriate Legal Notices; however, if the Program has interactive |
interfaces that do not display Appropriate Legal Notices, your |
work need not make them do so. |
|
A compilation of a covered work with other separate and independent |
works, which are not by their nature extensions of the covered work, |
and which are not combined with it such as to form a larger program, |
in or on a volume of a storage or distribution medium, is called an |
"aggregate" if the compilation and its resulting copyright are not |
used to limit the access or legal rights of the compilation's users |
beyond what the individual works permit. Inclusion of a covered work |
in an aggregate does not cause this License to apply to the other |
parts of the aggregate. |
|
6. Conveying Non-Source Forms. |
|
You may convey a covered work in object code form under the terms |
of sections 4 and 5, provided that you also convey the |
machine-readable Corresponding Source under the terms of this License, |
in one of these ways: |
|
a) Convey the object code in, or embodied in, a physical product |
(including a physical distribution medium), accompanied by the |
Corresponding Source fixed on a durable physical medium |
customarily used for software interchange. |
|
b) Convey the object code in, or embodied in, a physical product |
(including a physical distribution medium), accompanied by a |
written offer, valid for at least three years and valid for as |
long as you offer spare parts or customer support for that product |
model, to give anyone who possesses the object code either (1) a |
copy of the Corresponding Source for all the software in the |
product that is covered by this License, on a durable physical |
medium customarily used for software interchange, for a price no |
more than your reasonable cost of physically performing this |
conveying of source, or (2) access to copy the |
Corresponding Source from a network server at no charge. |
|
c) Convey individual copies of the object code with a copy of the |
written offer to provide the Corresponding Source. This |
alternative is allowed only occasionally and noncommercially, and |
only if you received the object code with such an offer, in accord |
with subsection 6b. |
|
d) Convey the object code by offering access from a designated |
place (gratis or for a charge), and offer equivalent access to the |
Corresponding Source in the same way through the same place at no |
further charge. You need not require recipients to copy the |
Corresponding Source along with the object code. If the place to |
copy the object code is a network server, the Corresponding Source |
may be on a different server (operated by you or a third party) |
that supports equivalent copying facilities, provided you maintain |
clear directions next to the object code saying where to find the |
Corresponding Source. Regardless of what server hosts the |
Corresponding Source, you remain obligated to ensure that it is |
available for as long as needed to satisfy these requirements. |
|
e) Convey the object code using peer-to-peer transmission, provided |
you inform other peers where the object code and Corresponding |
Source of the work are being offered to the general public at no |
charge under subsection 6d. |
|
A separable portion of the object code, whose source code is excluded |
from the Corresponding Source as a System Library, need not be |
included in conveying the object code work. |
|
A "User Product" is either (1) a "consumer product", which means any |
tangible personal property which is normally used for personal, family, |
or household purposes, or (2) anything designed or sold for incorporation |
into a dwelling. In determining whether a product is a consumer product, |
doubtful cases shall be resolved in favor of coverage. For a particular |
product received by a particular user, "normally used" refers to a |
typical or common use of that class of product, regardless of the status |
of the particular user or of the way in which the particular user |
actually uses, or expects or is expected to use, the product. A product |
is a consumer product regardless of whether the product has substantial |
commercial, industrial or non-consumer uses, unless such uses represent |
the only significant mode of use of the product. |
|
"Installation Information" for a User Product means any methods, |
procedures, authorization keys, or other information required to install |
and execute modified versions of a covered work in that User Product from |
a modified version of its Corresponding Source. The information must |
suffice to ensure that the continued functioning of the modified object |
code is in no case prevented or interfered with solely because |
modification has been made. |
|
If you convey an object code work under this section in, or with, or |
specifically for use in, a User Product, and the conveying occurs as |
part of a transaction in which the right of possession and use of the |
User Product is transferred to the recipient in perpetuity or for a |
fixed term (regardless of how the transaction is characterized), the |
Corresponding Source conveyed under this section must be accompanied |
by the Installation Information. But this requirement does not apply |
if neither you nor any third party retains the ability to install |
modified object code on the User Product (for example, the work has |
been installed in ROM). |
|
The requirement to provide Installation Information does not include a |
requirement to continue to provide support service, warranty, or updates |
for a work that has been modified or installed by the recipient, or for |
the User Product in which it has been modified or installed. Access to a |
network may be denied when the modification itself materially and |
adversely affects the operation of the network or violates the rules and |
protocols for communication across the network. |
|
Corresponding Source conveyed, and Installation Information provided, |
in accord with this section must be in a format that is publicly |
documented (and with an implementation available to the public in |
source code form), and must require no special password or key for |
unpacking, reading or copying. |
|
7. Additional Terms. |
|
"Additional permissions" are terms that supplement the terms of this |
License by making exceptions from one or more of its conditions. |
Additional permissions that are applicable to the entire Program shall |
be treated as though they were included in this License, to the extent |
that they are valid under applicable law. If additional permissions |
apply only to part of the Program, that part may be used separately |
under those permissions, but the entire Program remains governed by |
this License without regard to the additional permissions. |
|
When you convey a copy of a covered work, you may at your option |
remove any additional permissions from that copy, or from any part of |
it. (Additional permissions may be written to require their own |
removal in certain cases when you modify the work.) You may place |
additional permissions on material, added by you to a covered work, |
for which you have or can give appropriate copyright permission. |
|
Notwithstanding any other provision of this License, for material you |
add to a covered work, you may (if authorized by the copyright holders of |
that material) supplement the terms of this License with terms: |
|
a) Disclaiming warranty or limiting liability differently from the |
terms of sections 15 and 16 of this License; or |
|
b) Requiring preservation of specified reasonable legal notices or |
author attributions in that material or in the Appropriate Legal |
Notices displayed by works containing it; or |
|
c) Prohibiting misrepresentation of the origin of that material, or |
requiring that modified versions of such material be marked in |
reasonable ways as different from the original version; or |
|
d) Limiting the use for publicity purposes of names of licensors or |
authors of the material; or |
|
e) Declining to grant rights under trademark law for use of some |
trade names, trademarks, or service marks; or |
|
f) Requiring indemnification of licensors and authors of that |
material by anyone who conveys the material (or modified versions of |
it) with contractual assumptions of liability to the recipient, for |
any liability that these contractual assumptions directly impose on |
those licensors and authors. |
|
All other non-permissive additional terms are considered "further |
restrictions" within the meaning of section 10. If the Program as you |
received it, or any part of it, contains a notice stating that it is |
governed by this License along with a term that is a further |
restriction, you may remove that term. If a license document contains |
a further restriction but permits relicensing or conveying under this |
License, you may add to a covered work material governed by the terms |
of that license document, provided that the further restriction does |
not survive such relicensing or conveying. |
|
If you add terms to a covered work in accord with this section, you |
must place, in the relevant source files, a statement of the |
additional terms that apply to those files, or a notice indicating |
where to find the applicable terms. |
|
Additional terms, permissive or non-permissive, may be stated in the |
form of a separately written license, or stated as exceptions; |
the above requirements apply either way. |
|
8. Termination. |
|
You may not propagate or modify a covered work except as expressly |
provided under this License. Any attempt otherwise to propagate or |
modify it is void, and will automatically terminate your rights under |
this License (including any patent licenses granted under the third |
paragraph of section 11). |
|
However, if you cease all violation of this License, then your |
license from a particular copyright holder is reinstated (a) |
provisionally, unless and until the copyright holder explicitly and |
finally terminates your license, and (b) permanently, if the copyright |
holder fails to notify you of the violation by some reasonable means |
prior to 60 days after the cessation. |
|
Moreover, your license from a particular copyright holder is |
reinstated permanently if the copyright holder notifies you of the |
violation by some reasonable means, this is the first time you have |
received notice of violation of this License (for any work) from that |
copyright holder, and you cure the violation prior to 30 days after |
your receipt of the notice. |
|
Termination of your rights under this section does not terminate the |
licenses of parties who have received copies or rights from you under |
this License. If your rights have been terminated and not permanently |
reinstated, you do not qualify to receive new licenses for the same |
material under section 10. |
|
9. Acceptance Not Required for Having Copies. |
|
You are not required to accept this License in order to receive or |
run a copy of the Program. Ancillary propagation of a covered work |
occurring solely as a consequence of using peer-to-peer transmission |
to receive a copy likewise does not require acceptance. However, |
nothing other than this License grants you permission to propagate or |
modify any covered work. These actions infringe copyright if you do |
not accept this License. Therefore, by modifying or propagating a |
covered work, you indicate your acceptance of this License to do so. |
|
10. Automatic Licensing of Downstream Recipients. |
|
Each time you convey a covered work, the recipient automatically |
receives a license from the original licensors, to run, modify and |
propagate that work, subject to this License. You are not responsible |
for enforcing compliance by third parties with this License. |
|
An "entity transaction" is a transaction transferring control of an |
organization, or substantially all assets of one, or subdividing an |
organization, or merging organizations. If propagation of a covered |
work results from an entity transaction, each party to that |
transaction who receives a copy of the work also receives whatever |
licenses to the work the party's predecessor in interest had or could |
give under the previous paragraph, plus a right to possession of the |
Corresponding Source of the work from the predecessor in interest, if |
the predecessor has it or can get it with reasonable efforts. |
|
You may not impose any further restrictions on the exercise of the |
rights granted or affirmed under this License. For example, you may |
not impose a license fee, royalty, or other charge for exercise of |
rights granted under this License, and you may not initiate litigation |
(including a cross-claim or counterclaim in a lawsuit) alleging that |
any patent claim is infringed by making, using, selling, offering for |
sale, or importing the Program or any portion of it. |
|
11. Patents. |
|
A "contributor" is a copyright holder who authorizes use under this |
License of the Program or a work on which the Program is based. The |
work thus licensed is called the contributor's "contributor version". |
|
A contributor's "essential patent claims" are all patent claims |
owned or controlled by the contributor, whether already acquired or |
hereafter acquired, that would be infringed by some manner, permitted |
by this License, of making, using, or selling its contributor version, |
but do not include claims that would be infringed only as a |
consequence of further modification of the contributor version. For |
purposes of this definition, "control" includes the right to grant |
patent sublicenses in a manner consistent with the requirements of |
this License. |
|
Each contributor grants you a non-exclusive, worldwide, royalty-free |
patent license under the contributor's essential patent claims, to |
make, use, sell, offer for sale, import and otherwise run, modify and |
propagate the contents of its contributor version. |
|
In the following three paragraphs, a "patent license" is any express |
agreement or commitment, however denominated, not to enforce a patent |
(such as an express permission to practice a patent or covenant not to |
sue for patent infringement). To "grant" such a patent license to a |
party means to make such an agreement or commitment not to enforce a |
patent against the party. |
|
If you convey a covered work, knowingly relying on a patent license, |
and the Corresponding Source of the work is not available for anyone |
to copy, free of charge and under the terms of this License, through a |
publicly available network server or other readily accessible means, |
then you must either (1) cause the Corresponding Source to be so |
available, or (2) arrange to deprive yourself of the benefit of the |
patent license for this particular work, or (3) arrange, in a manner |
consistent with the requirements of this License, to extend the patent |
license to downstream recipients. "Knowingly relying" means you have |
actual knowledge that, but for the patent license, your conveying the |
covered work in a country, or your recipient's use of the covered work |
in a country, would infringe one or more identifiable patents in that |
country that you have reason to believe are valid. |
|
If, pursuant to or in connection with a single transaction or |
arrangement, you convey, or propagate by procuring conveyance of, a |
covered work, and grant a patent license to some of the parties |
receiving the covered work authorizing them to use, propagate, modify |
or convey a specific copy of the covered work, then the patent license |
you grant is automatically extended to all recipients of the covered |
work and works based on it. |
|
A patent license is "discriminatory" if it does not include within |
the scope of its coverage, prohibits the exercise of, or is |
conditioned on the non-exercise of one or more of the rights that are |
specifically granted under this License. You may not convey a covered |
work if you are a party to an arrangement with a third party that is |
in the business of distributing software, under which you make payment |
to the third party based on the extent of your activity of conveying |
the work, and under which the third party grants, to any of the |
parties who would receive the covered work from you, a discriminatory |
patent license (a) in connection with copies of the covered work |
conveyed by you (or copies made from those copies), or (b) primarily |
for and in connection with specific products or compilations that |
contain the covered work, unless you entered into that arrangement, |
or that patent license was granted, prior to 28 March 2007. |
|
Nothing in this License shall be construed as excluding or limiting |
any implied license or other defenses to infringement that may |
otherwise be available to you under applicable patent law. |
|
12. No Surrender of Others' Freedom. |
|
If conditions are imposed on you (whether by court order, agreement or |
otherwise) that contradict the conditions of this License, they do not |
excuse you from the conditions of this License. If you cannot convey a |
covered work so as to satisfy simultaneously your obligations under this |
License and any other pertinent obligations, then as a consequence you may |
not convey it at all. For example, if you agree to terms that obligate you |
to collect a royalty for further conveying from those to whom you convey |
the Program, the only way you could satisfy both those terms and this |
License would be to refrain entirely from conveying the Program. |
|
13. Use with the GNU Affero General Public License. |
|
Notwithstanding any other provision of this License, you have |
permission to link or combine any covered work with a work licensed |
under version 3 of the GNU Affero General Public License into a single |
combined work, and to convey the resulting work. The terms of this |
License will continue to apply to the part which is the covered work, |
but the special requirements of the GNU Affero General Public License, |
section 13, concerning interaction through a network will apply to the |
combination as such. |
|
14. Revised Versions of this License. |
|
The Free Software Foundation may publish revised and/or new versions of |
the GNU General Public License from time to time. Such new versions will |
be similar in spirit to the present version, but may differ in detail to |
address new problems or concerns. |
|
Each version is given a distinguishing version number. If the |
Program specifies that a certain numbered version of the GNU General |
Public License "or any later version" applies to it, you have the |
option of following the terms and conditions either of that numbered |
version or of any later version published by the Free Software |
Foundation. If the Program does not specify a version number of the |
GNU General Public License, you may choose any version ever published |
by the Free Software Foundation. |
|
If the Program specifies that a proxy can decide which future |
versions of the GNU General Public License can be used, that proxy's |
public statement of acceptance of a version permanently authorizes you |
to choose that version for the Program. |
|
Later license versions may give you additional or different |
permissions. However, no additional obligations are imposed on any |
author or copyright holder as a result of your choosing to follow a |
later version. |
|
15. Disclaimer of Warranty. |
|
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY |
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT |
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY |
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, |
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM |
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF |
ALL NECESSARY SERVICING, REPAIR OR CORRECTION. |
|
16. Limitation of Liability. |
|
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING |
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS |
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY |
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE |
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF |
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD |
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), |
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF |
SUCH DAMAGES. |
|
17. Interpretation of Sections 15 and 16. |
|
If the disclaimer of warranty and limitation of liability provided |
above cannot be given local legal effect according to their terms, |
reviewing courts shall apply local law that most closely approximates |
an absolute waiver of all civil liability in connection with the |
Program, unless a warranty or assumption of liability accompanies a |
copy of the Program in return for a fee. |
|
END OF TERMS AND CONDITIONS |
|
How to Apply These Terms to Your New Programs |
|
If you develop a new program, and you want it to be of the greatest |
possible use to the public, the best way to achieve this is to make it |
free software which everyone can redistribute and change under these terms. |
|
To do so, attach the following notices to the program. It is safest |
to attach them to the start of each source file to most effectively |
state the exclusion of warranty; and each file should have at least |
the "copyright" line and a pointer to where the full notice is found. |
|
<one line to give the program's name and a brief idea of what it does.> |
Copyright (C) <year> <name of author> |
|
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. |
|
This program is distributed in the hope that it will be useful, |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
GNU General Public License for more details. |
|
You should have received a copy of the GNU General Public License |
along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
Also add information on how to contact you by electronic and paper mail. |
|
If the program does terminal interaction, make it output a short |
notice like this when it starts in an interactive mode: |
|
<program> Copyright (C) <year> <name of author> |
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. |
This is free software, and you are welcome to redistribute it |
under certain conditions; type `show c' for details. |
|
The hypothetical commands `show w' and `show c' should show the appropriate |
parts of the General Public License. Of course, your program's commands |
might be different; for a GUI interface, you would use an "about box". |
|
You should also get your employer (if you work as a programmer) or school, |
if any, to sign a "copyright disclaimer" for the program, if necessary. |
For more information on this, and how to apply and follow the GNU GPL, see |
<http://www.gnu.org/licenses/>. |
|
The GNU General Public License does not permit incorporating your program |
into proprietary programs. If your program is a subroutine library, you |
may consider it more useful to permit linking proprietary applications with |
the library. If this is what you want to do, use the GNU Lesser General |
Public License instead of this License. But first, please read |
<http://www.gnu.org/philosophy/why-not-lgpl.html>. |
/trunk/btcminer.h
0,0 → 1,400
/*! |
btcminer -- BTCMiner for ZTEX USB-FPGA Modules: EZ-USB FX2 firmware |
Copyright (C) 2011-2012 ZTEX GmbH |
http://www.ztex.de |
|
This program is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License version 3 as |
published by the Free Software Foundation. |
|
This program is distributed in the hope that it will be useful, but |
WITHOUT ANY WARRANTY; without even the implied warranty of |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
General Public License for more details. |
|
You should have received a copy of the GNU General Public License |
along with this program; if not, see http://www.gnu.org/licenses/. |
!*/ |
|
#include[ztex-conf.h] // Loads the configuration macros, see ztex-conf.h for the available macros |
#include[ztex-utils.h] // include basic functions |
|
// configure endpoints 2 (used for high speed configuration) |
EP_CONFIG(2,0,BULK,OUT,512,2); |
|
// select target board |
#ifndef[TARGET_BOARD] |
#define[TARGET_BOARD][1.15] |
#endif |
|
#ifeq[TARGET_BOARD][1.15y] |
IDENTITY_UFM_1_15Y(10.15.1.2,0); |
#else |
IDENTITY_UFM_1_15(10.13.1.1,0); |
ENABLE_UFM_1_15X_DETECTION; |
#define[select_num][0] |
#endif |
|
// enables high speed FPGA configuration, use EP 2 |
ENABLE_HS_FPGA_CONF(2); |
|
|
// this product string is also used for identification by the host software |
#define[PRODUCT_STRING]["btcminer for ZTEX FPGA Modules"] |
|
#define[WATCHDOG_TIMEOUT][(300*100)] |
|
#ifndef[F_M1] |
#define[F_M1][800] |
#endif |
|
#ifndef[F_DIV] |
#define[F_DIV][6] |
#endif |
|
#ifndef[F_MIN_MULT] |
#define[F_MIN_MULT][13] |
#endif |
|
#ifeq[TARGET_BOARD][1.15y] |
#define[WR_CLK][IOA0] |
#define[RD_CLK][IOC6] |
#define[PLL_STOP][IOC5] |
#define[OEA_MASK][bmBIT0] |
#define[OEC_MASK][bmBIT6 | bmBIT5] |
#else |
#define[WR_CLK][IOA6] |
#define[RD_CLK][IOC1] |
#define[PLL_STOP][IOC2] |
#define[OEA_MASK][bmBIT6] |
#define[OEC_MASK][bmBIT1 | bmBIT2] |
#endif |
|
|
// !!!!! currently NUM_NONCES must not be larger than 2 !!!!! |
|
__xdata BYTE stopped[NUMBER_OF_FPGAS]; |
__xdata WORD watchdog_cnt; |
|
#define[PRE_FPGA_RESET][PRE_FPGA_RESET |
OEC |= bmBIT4; |
IOC4 = 1; // reset clocks |
#ifeq[TARGET_BOARD][1.15] |
CPUCS &= ~bmBIT1; // stop clock |
#endif |
] |
|
#define[POST_FPGA_CONFIG][POST_FPGA_CONFIG |
IOC4 = 1; |
PLL_STOP = 1; |
OEC = bmBIT0 | bmBIT2 | bmBIT4 | OEC_MASK; |
stopped[select_num] = 1; |
|
#ifeq[TARGET_BOARD][1.15] |
CPUCS |= bmBIT1; // start clock |
wait(20); |
#endif |
IOC4 = 0; |
|
OEA = bmBIT2 | bmBIT4 | bmBIT5 | bmBIT7 | OEA_MASK; |
IOA = 0; |
OEB = 0; |
OED = 255; |
|
#ifeq[TARGET_BOARD][1.15] |
if ( is_ufm_1_15x ) { |
OEA |= bmBIT0; |
IOA0 = 1; |
} |
#endif |
|
wait(50); |
|
set_freq(0); |
// set_freq(F_MULT); |
] |
|
|
#ifeq[TARGET_BOARD][1.15] |
__xdata BYTE prev_gn1, prev_gn2; |
#else |
__xdata BYTE OLD_IOC[NUMBER_OF_FPGAS]; |
#define[PRE_FPGA_SELECT][PRE_FPGA_SELECT |
OLD_IOC[prev_select_num] = IOC; |
IOC = OLD_IOC[select_num]; |
] |
#endif |
|
/* ********************************************************************* |
***** descriptor **************************************************** |
********************************************************************* */ |
__code BYTE BitminerDescriptor[] = |
{ |
5, // 0, version number |
NUM_NONCES-1, // 1, number of nonces - 1 |
(OFFS_NONCES+10000)&255, // 2, ( nonce offset + 10000 ) & 255 |
(OFFS_NONCES+10000)>>8, // 3, ( nonce offset + 10000 ) >> 8 |
F_M1 & 255, // 4, frequency @ F_MULT=1 / 10kHz (LSB) |
F_M1 >> 8, // 5, frequency @ F_MULT=1 / 10kHz (MSB) |
F_MULT-1, // 6, frequency multiplier - 1 (default) |
F_MAX_MULT-1, // 7, max frequency multiplier - 1 |
(HASHES_PER_CLOCK-1) & 255, // 8, (hashes_per_clck/128-1 ) & 266 |
(WORD)(HASHES_PER_CLOCK-1) >> 8, // 9, (hashes_per_clck/128-1 ) >> 8 |
EXTRA_SOLUTIONS, // 10, number of extra solutions |
|
}; |
__code char bitfileString[] = BITFILE_STRING; |
__code BYTE bitFileStringTerm = 0; |
|
|
/* ********************************************************************* |
***** set_freq ****************************************************** |
********************************************************************* */ |
#define[PROGEN][IOA5] |
#define[PROGCLK][IOA2] |
#define[PROGDATA][IOA4] |
|
void set_freq ( BYTE f ) { |
BYTE b,i; |
|
if ( f < F_MIN_MULT-1 ) |
f = F_MIN_MULT-1; |
|
if ( f > F_MAX_MULT-1 ) |
f = F_MAX_MULT-1; |
|
PROGEN = 1; |
|
PROGDATA = 1; |
PROGCLK = 1; |
PROGCLK = 0; |
|
PROGDATA = 0; |
PROGCLK = 1; |
PROGCLK = 0; |
|
b = F_DIV - 1; |
for ( i=0; i<8; i++ ) { |
PROGDATA = b & 1; |
PROGCLK = 1; |
PROGCLK = 0; |
b = b >> 1; |
} |
|
PROGEN = 0; |
|
PROGCLK = 1; |
PROGCLK = 0; |
PROGCLK = 1; |
PROGCLK = 0; |
PROGCLK = 1; |
PROGCLK = 0; |
|
// load D |
PROGEN = 1; |
|
PROGDATA = 1; |
PROGCLK = 1; |
PROGCLK = 0; |
|
PROGCLK = 1; |
PROGCLK = 0; |
|
b = f; |
for ( i=0; i<8; i++ ) { |
PROGDATA = b & 1; |
PROGCLK = 1; |
PROGCLK = 0; |
b = b >> 1; |
} |
|
PROGEN = 0; |
|
PROGCLK = 1; |
PROGCLK = 0; |
PROGCLK = 1; |
PROGCLK = 0; |
PROGCLK = 1; |
PROGCLK = 0; |
|
// GO |
PROGDATA = 0; |
|
PROGEN = 1; |
|
PROGCLK = 1; |
PROGCLK = 0; |
|
PROGEN = 0; |
|
_asm |
mov r1,#50 |
011000$: |
mov r2,#0 |
011001$: |
setb _PROGCLK |
clr _PROGCLK |
setb _PROGCLK |
clr _PROGCLK |
setb _PROGCLK |
clr _PROGCLK |
setb _PROGCLK |
clr _PROGCLK |
djnz r2, 011001$ |
djnz r1, 011000$ |
__endasm; |
} |
|
|
/* ********************************************************************* |
***** EP0 vendor command 0x80 *************************************** |
********************************************************************* */ |
// write data to FPGA |
void ep0_write_data () { |
BYTE b; |
|
IOC0 = 1; // reset on |
for ( b=0; b<EP0BCL; b++ ) { |
IOD = EP0BUF[b]; |
RD_CLK = !RD_CLK; |
} |
IOC0 = 0; // reset off |
#ifeq[TARGET_BOARD][1.15] |
prev_gn1 = 0; |
prev_gn2 = 0; |
#endif |
} |
|
ADD_EP0_VENDOR_COMMAND((0x80,, |
watchdog_cnt = 0; |
|
if ( stopped[select_num] ) { |
PLL_STOP = 0; |
wait(100); |
stopped[select_num]=0; |
} |
,, |
ep0_write_data(); |
));; |
|
|
/* ********************************************************************* |
***** EP0 vendor request 0x81 *************************************** |
********************************************************************* */ |
// read data from FPGA |
void ep0_read_data () { |
BYTE b; |
for ( b=0; b<ep0_payload_transfer; b++ ) { |
EP0BUF[b] = IOB; |
WR_CLK = !WR_CLK; |
} |
#ifeq[TARGET_BOARD][1.15] |
prev_gn1 = EP0BUF[0]; |
#endif |
EP0BCH = 0; |
EP0BCL = ep0_payload_transfer; |
} |
|
// read date from FPGA |
ADD_EP0_VENDOR_REQUEST((0x81,, |
IOA7 = 1; // write start signal |
IOA7 = 0; |
ep0_read_data (); |
,, |
ep0_read_data (); |
));; |
|
|
/* ********************************************************************* |
***** EP0 vendor request 0x82 *************************************** |
********************************************************************* */ |
// send descriptor |
ADD_EP0_VENDOR_REQUEST((0x82,, |
MEM_COPY1(BitminerDescriptor,EP0BUF,64); |
EP0BCH = 0; |
EP0BCL = SETUPDAT[6]; |
,, |
));; |
|
|
/* ********************************************************************* |
***** EP0 vendor command 0x83 *************************************** |
********************************************************************* */ |
// set frequency |
ADD_EP0_VENDOR_COMMAND((0x83,, |
PLL_STOP = 1; |
set_freq(SETUPDAT[2]); |
wait(20); |
PLL_STOP = 0; |
stopped[select_num] = 0; |
watchdog_cnt = 0; |
,, |
NOP; |
));; |
|
|
/* ********************************************************************* |
***** EP0 vendor command 0x84 *************************************** |
********************************************************************* */ |
// suspend |
ADD_EP0_VENDOR_COMMAND((0x84,, |
stopped[select_num] = 1; |
PLL_STOP = 1; |
,, |
NOP; |
));; |
|
|
// include the main part of the firmware kit, define the descriptors, ... |
#include[ztex.h] |
|
void main(void) |
{ |
BYTE b, c; |
// init everything |
init_USB(); |
|
watchdog_cnt = 1; |
for ( b = 0; b<NUMBER_OF_FPGAS; b++ ) { |
stopped[b] = 1; |
} |
|
#ifeq[TARGET_BOARD][1.15] |
c = 0; |
prev_gn1 = 0; |
prev_gn2 = 0; |
#endif |
|
while (1) { |
|
wait(10); |
|
#ifeq[TARGET_BOARD][1.15] |
if ( is_ufm_1_15x ) { |
if ( prev_gn1 != prev_gn2 ) { |
c = 25; |
prev_gn2 = prev_gn1; |
} |
IOA0 = ( stopped[0] || c>0 ) ? 1 : 0; |
if ( c > 0 ) c--; |
} |
|
#endif |
|
watchdog_cnt += 1; |
if ( watchdog_cnt == WATCHDOG_TIMEOUT ) { |
#ifeq[TARGET_BOARD][1.15] |
stopped[0] = 1; |
PLL_STOP = 1; |
#else |
c = select_num; |
for ( b = 0; b<NUMBER_OF_FPGAS; b++ ) { |
select_fpga(b); |
stopped[b] = 1; |
PLL_STOP = 1; |
} |
select_fpga(c); |
#endif |
} |
} |
} |
/trunk/ztex_ufm1_15b1.c
0,0 → 1,27
/*! |
btcminer -- BTCMiner for ZTEX USB-FPGA Modules: EZ-USB FX2 firmware for ZTEX USB FPGA Module 1.15b (one single hash pipe) |
Copyright (C) 2011-2012 ZTEX GmbH |
http://www.ztex.de |
|
This program is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License version 3 as |
published by the Free Software Foundation. |
|
This program is distributed in the hope that it will be useful, but |
WITHOUT ANY WARRANTY; without even the implied warranty of |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
General Public License for more details. |
|
You should have received a copy of the GNU General Public License |
along with this program; if not, see http://www.gnu.org/licenses/. |
!*/ |
|
#define[NUM_NONCES][1] |
#define[EXTRA_SOLUTIONS][0] |
#define[OFFS_NONCES][130] |
#define[F_MULT][23] |
#define[F_MAX_MULT][28] |
#define[HASHES_PER_CLOCK][64] |
#define[BITFILE_STRING]["ztex_ufm1_15b1"] |
|
#include[btcminer.h] |
/trunk/ztex_ufm1_15d4-nomac.c
0,0 → 1,21
/*! |
btcminer -- BTCMiner for ZTEX USB-FPGA Modules: EZ-USB FX2 firmware for ZTEX USB FPGA Module 1.15d (one double hash pipe) |
Copyright (C) 2011-2012 ZTEX GmbH |
http://www.ztex.de |
|
This program is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License version 3 as |
published by the Free Software Foundation. |
|
This program is distributed in the hope that it will be useful, but |
WITHOUT ANY WARRANTY; without even the implied warranty of |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
General Public License for more details. |
|
You should have received a copy of the GNU General Public License |
along with this program; if not, see http://www.gnu.org/licenses/. |
!*/ |
|
#define[EEPROM_MAC_DISABLED][1] |
|
#include[ztex_ufm1_15d4.c] |
/trunk/ztex_ufm1_15d.c
0,0 → 1,44
/*! |
default -- Default Firmware for ZTEX USB-FPGA Modules 1.15x |
Copyright (C) 2009-2012 ZTEX GmbH. |
http://www.ztex.de |
|
This program is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License version 3 as |
published by the Free Software Foundation. |
|
This program is distributed in the hope that it will be useful, but |
WITHOUT ANY WARRANTY; without even the implied warranty of |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
General Public License for more details. |
|
You should have received a copy of the GNU General Public License |
along with this program; if not, see http://www.gnu.org/licenses/. |
!*/ |
|
#include[ztex-conf.h] // Loads the configuration macros, see ztex-conf.h for the available macros |
#include[ztex-utils.h] // include basic functions and variables |
|
// Endpoint 2 is used to high speed FPGA configuration |
EP_CONFIG(2,0,BULK,OUT,512,4); |
|
// select ZTEX USB FPGA Module 1.15 as target (required for FPGA configuration) |
IDENTITY_UFM_1_15(10.13.0.0,0); |
ENABLE_UFM_1_15X_DETECTION; // avoids some warnings |
|
// enables high speed FPGA configuration, use EP 2 |
ENABLE_HS_FPGA_CONF(2); |
|
// this product string can also used for identification by the host software |
#define[PRODUCT_STRING]["USB-FPGA Module 1.15d (default)"] |
|
#include[ztex.h] |
|
void main(void) |
{ |
init_USB(); // init everything |
|
while (1) { } // twiddle thumbs |
} |
|
|
/trunk/fpga/ztex_ufm1_15d1.v
0,0 → 1,146
/*! |
btcminer -- BTCMiner for ZTEX USB-FPGA Modules: HDL code for ZTEX USB-FPGA Module 1.15b (one double hash pipe) |
Copyright (C) 2011 ZTEX GmbH |
http://www.ztex.de |
|
This program is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License version 3 as |
published by the Free Software Foundation. |
|
This program is distributed in the hope that it will be useful, but |
WITHOUT ANY WARRANTY; without even the implied warranty of |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
General Public License for more details. |
|
You should have received a copy of the GNU General Public License |
along with this program; if not, see http://www.gnu.org/licenses/. |
!*/ |
|
module ztex_ufm1_15d1 (fxclk_in, reset, pll_stop, dcm_progclk, dcm_progdata, dcm_progen, rd_clk, wr_clk, wr_start, read, write); |
|
input fxclk_in, reset, pll_stop, dcm_progclk, dcm_progdata, dcm_progen, rd_clk, wr_clk, wr_start; |
input [7:0] read; |
output [7:0] write; |
|
reg [3:0] rd_clk_b, wr_clk_b; |
reg wr_start_b1, wr_start_b2, reset_buf; |
reg dcm_progclk_buf, dcm_progdata_buf, dcm_progen_buf; |
reg [4:0] wr_delay; |
reg [351:0] inbuf, inbuf_tmp; |
reg [95:0] outbuf; |
reg [7:0] read_buf, write_buf; |
|
wire fxclk, clk, dcm_clk, pll_fb, pll_clk0, dcm_locked, pll_reset; |
wire [31:0] golden_nonce, nonce2, hash2; |
|
miner253 m ( |
.clk(clk), |
.reset(reset_buf), |
.midstate(inbuf[351:96]), |
.data(inbuf[95:0]), |
.golden_nonce(golden_nonce), |
.nonce2(nonce2), |
.hash2(hash2) |
); |
|
BUFG bufg_fxclk ( |
.I(fxclk_in), |
.O(fxclk) |
); |
|
BUFG bufg_clk ( |
.I(pll_clk0), |
.O(clk) |
); |
|
DCM_CLKGEN #( |
.CLKFX_DIVIDE(6.0), |
.CLKFX_MULTIPLY(24), |
.CLKFXDV_DIVIDE(2) |
) |
dcm0 ( |
.CLKIN(fxclk), |
.CLKFX(dcm_clk), |
.FREEZEDCM(1'b0), |
.PROGCLK(dcm_progclk_buf), |
.PROGDATA(dcm_progdata_buf), |
.PROGEN(dcm_progen_buf), |
.LOCKED(dcm_locked), |
.RST(1'b0) |
); |
|
PLL_BASE #( |
.BANDWIDTH("LOW"), |
.CLKFBOUT_MULT(4), |
.CLKOUT0_DIVIDE(4), |
.CLKOUT0_DUTY_CYCLE(0.5), |
.CLK_FEEDBACK("CLKFBOUT"), |
.COMPENSATION("DCM2PLL"), |
.DIVCLK_DIVIDE(1), |
.REF_JITTER(0.05), |
.RESET_ON_LOSS_OF_LOCK("FALSE") |
) |
pll0 ( |
.CLKFBOUT(pll_fb), |
.CLKOUT0(pll_clk0), |
.CLKFBIN(pll_fb), |
.CLKIN(dcm_clk), |
.RST(pll_reset) |
); |
|
assign write = write_buf; |
assign pll_reset = pll_stop | ~dcm_locked; |
|
always @ (posedge clk) |
begin |
if ( (rd_clk_b[3] == rd_clk_b[2]) && (rd_clk_b[2] == rd_clk_b[1]) && (rd_clk_b[1] != rd_clk_b[0]) ) |
begin |
inbuf_tmp[351:344] <= read_buf; |
inbuf_tmp[343:0] <= inbuf_tmp[351:8]; |
end; |
inbuf <= inbuf_tmp; // due to TIG's |
|
if ( wr_start_b1 && wr_start_b2 ) |
begin |
wr_delay <= 5'd0; |
end else |
begin |
wr_delay[0] <= 1'b1; |
wr_delay[4:1] <= wr_delay[3:0]; |
end |
|
if ( ! wr_delay[4] ) |
begin |
outbuf <= { hash2, nonce2, golden_nonce }; |
end else |
begin |
if ( (wr_clk_b[3] == wr_clk_b[2]) && (wr_clk_b[2] == wr_clk_b[1]) && (wr_clk_b[1] != wr_clk_b[0]) ) |
outbuf[87:0] <= outbuf[95:8]; |
end |
|
read_buf <= read; |
write_buf <= outbuf[7:0]; |
|
rd_clk_b[0] <= rd_clk; |
rd_clk_b[3:1] <= rd_clk_b[2:0]; |
|
wr_clk_b[0] <= wr_clk; |
wr_clk_b[3:1] <= wr_clk_b[2:0]; |
|
wr_start_b1 <= wr_start; |
wr_start_b2 <= wr_start_b1; |
|
|
reset_buf <= reset; |
end |
|
always @ (posedge fxclk) |
begin |
dcm_progclk_buf <= dcm_progclk; |
dcm_progdata_buf <= dcm_progdata; |
dcm_progen_buf <= dcm_progen; |
end |
|
|
endmodule |
|
/trunk/fpga/miner130.v
0,0 → 1,124
/*! |
btcminer -- BTCMiner for ZTEX USB-FPGA Modules: HDL code for ZTEX USB-FPGA Module 1.15b (one double hash pipe) |
Copyright (C) 2011 ZTEX GmbH |
http://www.ztex.de |
|
This program is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License version 3 as |
published by the Free Software Foundation. |
|
This program is distributed in the hope that it will be useful, but |
WITHOUT ANY WARRANTY; without even the implied warranty of |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
General Public License for more details. |
|
You should have received a copy of the GNU General Public License |
along with this program; if not, see http://www.gnu.org/licenses/. |
!*/ |
|
`define IDX(x) (((x)+1)*(32)-1):((x)*(32)) |
|
module miner130 (clk, reset, midstate, data, golden_nonce, nonce2, hash2); |
|
parameter NONCE_OFFS = 32'd0; |
parameter NONCE_INCR = 32'd1; |
|
input clk, reset; |
input [255:0] midstate; |
input [95:0] data; |
output reg [31:0] golden_nonce, nonce2, hash2; |
|
reg [31:0] nonce; |
wire [255:0] hash; |
|
reg [7:0] cnt = 8'd0; |
reg feedback = 1'b0; |
reg is_golden_nonce; |
reg feedback_b1, feedback_b2, feedback_b3, feedback_b4, feedback_b5, feedback_b6, reset_b1, reset_b2; |
|
reg [255:0] state_buf; |
reg [511:0] data_buf; |
|
sha256_pipe129 p ( |
.clk(clk), |
.state(state_buf), |
.data(data_buf), |
.hash(hash) |
); |
|
always @ (posedge clk) |
begin |
if ( cnt == 8'd129 ) |
begin |
feedback <= ~feedback; |
cnt <= 8'd0; |
end else begin |
cnt <= cnt + 8'd1; |
end |
|
if ( feedback_b1 ) |
begin |
data_buf <= { 256'h0000010000000000000000000000000000000000000000000000000080000000, |
hash[`IDX(7)] + midstate[`IDX(7)], |
hash[`IDX(6)] + midstate[`IDX(6)], |
hash[`IDX(5)] + midstate[`IDX(5)], |
hash[`IDX(4)] + midstate[`IDX(4)], |
hash[`IDX(3)] + midstate[`IDX(3)], |
hash[`IDX(2)] + midstate[`IDX(2)], |
hash[`IDX(1)] + midstate[`IDX(1)], |
hash[`IDX(0)] + midstate[`IDX(0)] |
}; |
end else begin |
data_buf <= {384'h000002800000000000000000000000000000000000000000000000000000000000000000000000000000000080000000, nonce, data}; |
end |
|
if ( feedback_b2 ) |
begin |
state_buf <= 256'h5be0cd191f83d9ab9b05688c510e527fa54ff53a3c6ef372bb67ae856a09e667; |
end else begin |
state_buf <= midstate; |
end |
|
if ( reset_b1 ) |
begin |
nonce <= NONCE_OFFS; |
end else if ( ! feedback_b3 ) |
begin |
nonce <= nonce + NONCE_INCR; |
end |
|
if ( reset_b2 ) |
begin |
golden_nonce <= 32'd0; |
end else if ( is_golden_nonce ) |
begin |
golden_nonce <= nonce2; |
end |
|
if ( ! feedback_b4 ) |
begin |
hash2 <= hash[255:224]; |
end |
|
if ( ! feedback_b5 ) |
begin |
nonce2 <= nonce; |
end |
|
if ( ! feedback_b6 ) |
begin |
is_golden_nonce <= hash[255:224] == 32'ha41f32e7; |
end |
|
feedback_b1 <= feedback; |
feedback_b2 <= feedback; |
feedback_b3 <= feedback; |
feedback_b4 <= feedback; |
feedback_b5 <= feedback; |
feedback_b6 <= feedback; |
|
reset_b1 <= reset; |
reset_b2 <= reset; |
end |
|
endmodule |
/trunk/fpga/ztex_ufm1_15d3.v
0,0 → 1,149
/*! |
btcminer -- BTCMiner for ZTEX USB-FPGA Modules: HDL code for ZTEX USB-FPGA Module 1.15b (one double hash pipe) |
Copyright (C) 2011-2012 ZTEX GmbH |
http://www.ztex.de |
|
This program is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License version 3 as |
published by the Free Software Foundation. |
|
This program is distributed in the hope that it will be useful, but |
WITHOUT ANY WARRANTY; without even the implied warranty of |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
General Public License for more details. |
|
You should have received a copy of the GNU General Public License |
along with this program; if not, see http://www.gnu.org/licenses/. |
!*/ |
|
module ztex_ufm1_15d3 (fxclk_in, reset, clk_reset, pll_stop, dcm_progclk, dcm_progdata, dcm_progen, rd_clk, wr_clk, wr_start, read, write); |
|
input fxclk_in, reset, clk_reset, pll_stop, dcm_progclk, dcm_progdata, dcm_progen, rd_clk, wr_clk, wr_start; |
input [7:0] read; |
output [7:0] write; |
|
reg [3:0] rd_clk_b, wr_clk_b; |
reg wr_start_b1, wr_start_b2, reset_buf; |
reg dcm_progclk_buf, dcm_progdata_buf, dcm_progen_buf; |
reg [4:0] wr_delay; |
reg [351:0] inbuf, inbuf_tmp; |
reg [95:0] outbuf; |
reg [7:0] read_buf, write_buf; |
|
wire fxclk, clk, dcm_clk, pll_fb, pll_clk0, dcm_locked, pll_reset; |
wire [2:1] dcm_status; |
wire [31:0] golden_nonce, nonce2, hash2; |
|
miner253 m ( |
.clk(clk), |
.reset(reset_buf), |
.midstate(inbuf[351:96]), |
.data(inbuf[95:0]), |
.golden_nonce(golden_nonce), |
.nonce2(nonce2), |
.hash2(hash2) |
); |
|
BUFG bufg_fxclk ( |
.I(fxclk_in), |
.O(fxclk) |
); |
|
BUFG bufg_clk ( |
.I(pll_clk0), |
.O(clk) |
); |
|
DCM_CLKGEN #( |
.CLKFX_DIVIDE(4.0), |
.CLKFX_MULTIPLY(32), |
.CLKFXDV_DIVIDE(2), |
.CLKIN_PERIOD(20.8333) |
) |
dcm0 ( |
.CLKIN(fxclk), |
.CLKFXDV(dcm_clk), |
.FREEZEDCM(1'b0), |
.PROGCLK(dcm_progclk_buf), |
.PROGDATA(dcm_progdata_buf), |
.PROGEN(dcm_progen_buf), |
.LOCKED(dcm_locked), |
.STATUS(dcm_status), |
.RST(clk_reset) |
); |
|
PLL_BASE #( |
.BANDWIDTH("LOW"), |
.CLKFBOUT_MULT(4), |
.CLKOUT0_DIVIDE(4), |
.CLKOUT0_DUTY_CYCLE(0.5), |
.CLK_FEEDBACK("CLKFBOUT"), |
.COMPENSATION("INTERNAL"), |
.DIVCLK_DIVIDE(1), |
.REF_JITTER(0.10), |
.RESET_ON_LOSS_OF_LOCK("FALSE") |
) |
pll0 ( |
.CLKFBOUT(pll_fb), |
.CLKOUT0(pll_clk0), |
.CLKFBIN(pll_fb), |
.CLKIN(dcm_clk), |
.RST(pll_reset) |
); |
|
assign write = write_buf; |
assign pll_reset = pll_stop | ~dcm_locked | clk_reset | dcm_status[2]; |
|
always @ (posedge clk) |
begin |
if ( (rd_clk_b[3] == rd_clk_b[2]) && (rd_clk_b[2] == rd_clk_b[1]) && (rd_clk_b[1] != rd_clk_b[0]) ) |
begin |
inbuf_tmp[351:344] <= read_buf; |
inbuf_tmp[343:0] <= inbuf_tmp[351:8]; |
end; |
inbuf <= inbuf_tmp; // due to TIG's |
|
if ( wr_start_b1 && wr_start_b2 ) |
begin |
wr_delay <= 5'd0; |
end else |
begin |
wr_delay[0] <= 1'b1; |
wr_delay[4:1] <= wr_delay[3:0]; |
end |
|
if ( ! wr_delay[4] ) |
begin |
outbuf <= { hash2, nonce2, golden_nonce }; |
end else |
begin |
if ( (wr_clk_b[3] == wr_clk_b[2]) && (wr_clk_b[2] == wr_clk_b[1]) && (wr_clk_b[1] != wr_clk_b[0]) ) |
outbuf[87:0] <= outbuf[95:8]; |
end |
|
read_buf <= read; |
write_buf <= outbuf[7:0]; |
|
rd_clk_b[0] <= rd_clk; |
rd_clk_b[3:1] <= rd_clk_b[2:0]; |
|
wr_clk_b[0] <= wr_clk; |
wr_clk_b[3:1] <= wr_clk_b[2:0]; |
|
wr_start_b1 <= wr_start; |
wr_start_b2 <= wr_start_b1; |
|
|
reset_buf <= reset; |
end |
|
always @ (posedge fxclk) |
begin |
dcm_progclk_buf <= dcm_progclk; |
dcm_progdata_buf <= dcm_progdata; |
dcm_progen_buf <= dcm_progen; |
end |
|
|
endmodule |
|
/trunk/fpga/ztex_ufm1_15.ucf
0,0 → 1,77
NET "fxclk_in" TNM_NET = "fxclk_in"; |
TIMESPEC "TS_fxclk_in" = PERIOD "fxclk_in" 20.3ns HIGH 50 %; |
NET "fxclk_in" LOC = "L22" | IOSTANDARD = LVCMOS33 ; |
|
# input |
NET "write<0>" LOC = "Y17" | IOSTANDARD = LVCMOS33 | DRIVE = 12; # PB0 |
NET "write<1>" LOC = "V13" | IOSTANDARD = LVCMOS33 | DRIVE = 12; # PB1 |
NET "write<2>" LOC = "W13" | IOSTANDARD = LVCMOS33 | DRIVE = 12; # PB2 |
NET "write<3>" LOC = "AA8" | IOSTANDARD = LVCMOS33 | DRIVE = 12; # PB3 |
NET "write<4>" LOC = "AB8" | IOSTANDARD = LVCMOS33 | DRIVE = 12; # PB4 |
NET "write<5>" LOC = "W6" | IOSTANDARD = LVCMOS33 | DRIVE = 12; # PB5 |
NET "write<6>" LOC = "Y6" | IOSTANDARD = LVCMOS33 | DRIVE = 12; # PB6 |
NET "write<7>" LOC = "Y9" | IOSTANDARD = LVCMOS33 | DRIVE = 12; # PB7 |
|
NET "wr_clk" LOC = "AB5" | IOSTANDARD = LVCMOS33; # PA6 |
NET "wr_start" LOC = "AB17" | IOSTANDARD = LVCMOS33 ; # PA7 |
|
# dcm |
NET "dcm_progclk" LOC = "U15" | IOSTANDARD = LVCMOS33 ; # PA2 |
NET "dcm_progdata" LOC = "W17" | IOSTANDARD = LVCMOS33 ; # PA4 |
NET "dcm_progen" LOC = "Y18" | IOSTANDARD = LVCMOS33 ; # PA5 |
|
#output |
NET "read<0>" LOC = "V21" | IOSTANDARD = LVCMOS33 ; # PD0 |
NET "read<1>" LOC = "V22" | IOSTANDARD = LVCMOS33 ; # PD1 |
NET "read<2>" LOC = "U20" | IOSTANDARD = LVCMOS33 ; # PD2 |
NET "read<3>" LOC = "U22" | IOSTANDARD = LVCMOS33 ; # PD3 |
NET "read<4>" LOC = "R20" | IOSTANDARD = LVCMOS33 ; # PD4 |
NET "read<5>" LOC = "R22" | IOSTANDARD = LVCMOS33 ; # PD5 |
NET "read<6>" LOC = "P18" | IOSTANDARD = LVCMOS33 ; # PD6 |
NET "read<7>" LOC = "P19" | IOSTANDARD = LVCMOS33 ; # PD7 |
|
NET "reset" LOC = "G20" | IOSTANDARD = LVCMOS33 ; # PC0 |
NET "rd_clk" LOC = "T20" | IOSTANDARD = LVCMOS33 ; # PC1 |
NET "pll_stop" LOC = "Y5" | IOSTANDARD = LVCMOS33 ; # PC2 |
NET "clk_reset" LOC = "G19" | IOSTANDARD = LVCMOS33 ; # PC4 |
|
# unused |
#NET "" LOC = "AB9" | IOSTANDARD = LVCMOS33 | DRIVE = 12 ; # PC3 |
#NET "" LOC = "G19" | IOSTANDARD = LVCMOS33 | DRIVE = 12 ; # PC4 |
#NET "" LOC = "H20" | IOSTANDARD = LVCMOS33 | DRIVE = 12 ; # PC5 |
#NET "" LOC = "H19" | IOSTANDARD = LVCMOS33 | DRIVE = 12 ; # PC6 |
#NET "" LOC = "H18" | IOSTANDARD = LVCMOS33 | DRIVE = 12 ; # PC7 |
|
# debug |
#NET "green16<0>" LOC = "V20" | IOSTANDARD = LVCMOS33 | DRIVE = 12; |
#NET "green16<1>" LOC = "Y22" | IOSTANDARD = LVCMOS33 | DRIVE = 12; |
#NET "green16<2>" LOC = "AA22" | IOSTANDARD = LVCMOS33 | DRIVE = 12; |
#NET "green16<3>" LOC = "Y21" | IOSTANDARD = LVCMOS33 | DRIVE = 12; |
#NET "green16<4>" LOC = "W20" | IOSTANDARD = LVCMOS33 | DRIVE = 12; |
#NET "green16<5>" LOC = "AA20" | IOSTANDARD = LVCMOS33 | DRIVE = 12; |
#NET "green16<6>" LOC = "V19" | IOSTANDARD = LVCMOS33 | DRIVE = 12; |
#NET "green16<7>" LOC = "Y19" | IOSTANDARD = LVCMOS33 | DRIVE = 12; |
#NET "green16<8>" LOC = "V18" | IOSTANDARD = LVCMOS33 | DRIVE = 12; |
#NET "green16<9>" LOC = "Y15" | IOSTANDARD = LVCMOS33 | DRIVE = 12; |
#NET "green16<10>" LOC = "W15" | IOSTANDARD = LVCMOS33 | DRIVE = 12; |
#NET "green16<11>" LOC = "AA14" | IOSTANDARD = LVCMOS33 | DRIVE = 12; |
#NET "green16<12>" LOC = "AB12" | IOSTANDARD = LVCMOS33 | DRIVE = 12; |
#NET "green16<13>" LOC = "AA10" | IOSTANDARD = LVCMOS33 | DRIVE = 12; |
#NET "green16<14>" LOC = "T14" | IOSTANDARD = LVCMOS33 | DRIVE = 12; |
#NET "green16<15>" LOC = "W12" | IOSTANDARD = LVCMOS33 | DRIVE = 12; |
|
# TIG's |
NET "inbuf[*]" TIG; |
NET "m/golden_nonce[*]" TIG; |
|
############################################################################ |
# LEDS |
############################################################################ |
#NET "LED<0>" LOC = "R1" | IOSTANDARD = LVCMOS33 | DRIVE = 12 ; |
#NET "LED<1>" LOC = "T1" | IOSTANDARD = LVCMOS33 | DRIVE = 12 ; |
#NET "LED<2>" LOC = "U1" | IOSTANDARD = LVCMOS33 | DRIVE = 12 ; |
#NET "LED<3>" LOC = "V1" | IOSTANDARD = LVCMOS33 | DRIVE = 12 ; |
#NET "LED<4>" LOC = "W1" | IOSTANDARD = LVCMOS33 | DRIVE = 12 ; |
#NET "LED<5>" LOC = "Y1" | IOSTANDARD = LVCMOS33 | DRIVE = 12 ; |
#NET "LED<6>" LOC = "AB2" | IOSTANDARD = LVCMOS33 | DRIVE = 12 ; |
#NET "LED<7>" LOC = "AA2" | IOSTANDARD = LVCMOS33 | DRIVE = 12 ; |
/trunk/fpga/ztex_ufm1_15d4.v
0,0 → 1,159
/*! |
btcminer -- BTCMiner for ZTEX USB-FPGA Modules: HDL code for ZTEX USB-FPGA Module 1.15b (one double hash pipe) |
Copyright (C) 2011-2012 ZTEX GmbH |
http://www.ztex.de |
|
This program is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License version 3 as |
published by the Free Software Foundation. |
|
This program is distributed in the hope that it will be useful, but |
WITHOUT ANY WARRANTY; without even the implied warranty of |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
General Public License for more details. |
|
You should have received a copy of the GNU General Public License |
along with this program; if not, see http://www.gnu.org/licenses/. |
!*/ |
|
module ztex_ufm1_15d4 (fxclk_in, reset, clk_reset, pll_stop, dcm_progclk, dcm_progdata, dcm_progen, rd_clk, wr_clk, wr_start, read, write); |
|
input fxclk_in, reset, clk_reset, pll_stop, dcm_progclk, dcm_progdata, dcm_progen, rd_clk, wr_clk, wr_start; |
input [7:0] read; |
output [7:0] write; |
|
reg [3:0] rd_clk_b, wr_clk_b; |
reg wr_start_b1, wr_start_b2, reset_buf; |
reg dcm_progclk_buf, dcm_progdata_buf, dcm_progen_buf; |
reg [4:0] wr_delay; |
reg [351:0] inbuf, inbuf_tmp; |
reg [127:0] outbuf; |
reg [7:0] read_buf, write_buf; |
reg [31:0] golden_nonce1, golden_nonce2; |
|
wire fxclk, clk, dcm_clk, pll_fb, pll_clk0, dcm_locked, pll_reset; |
wire [2:1] dcm_status; |
wire [31:0] golden_nonce, nonce2, hash2; |
|
miner253 m ( |
.clk(clk), |
.reset(reset_buf), |
.midstate(inbuf[351:96]), |
.data(inbuf[95:0]), |
.golden_nonce(golden_nonce), |
.nonce2(nonce2), |
.hash2(hash2) |
); |
|
BUFG bufg_fxclk ( |
.I(fxclk_in), |
.O(fxclk) |
); |
|
BUFG bufg_clk ( |
.I(pll_clk0), |
.O(clk) |
); |
|
DCM_CLKGEN #( |
.CLKFX_DIVIDE(4.0), |
.CLKFX_MULTIPLY(32), |
.CLKFXDV_DIVIDE(2), |
.CLKIN_PERIOD(20.8333) |
) |
dcm0 ( |
.CLKIN(fxclk), |
.CLKFXDV(dcm_clk), |
.FREEZEDCM(1'b0), |
.PROGCLK(dcm_progclk_buf), |
.PROGDATA(dcm_progdata_buf), |
.PROGEN(dcm_progen_buf), |
.LOCKED(dcm_locked), |
.STATUS(dcm_status), |
.RST(clk_reset) |
); |
|
PLL_BASE #( |
.BANDWIDTH("LOW"), |
.CLKFBOUT_MULT(4), |
.CLKOUT0_DIVIDE(4), |
.CLKOUT0_DUTY_CYCLE(0.5), |
.CLK_FEEDBACK("CLKFBOUT"), |
.COMPENSATION("INTERNAL"), |
.DIVCLK_DIVIDE(1), |
.REF_JITTER(0.10), |
.RESET_ON_LOSS_OF_LOCK("FALSE") |
) |
pll0 ( |
.CLKFBOUT(pll_fb), |
.CLKOUT0(pll_clk0), |
.CLKFBIN(pll_fb), |
.CLKIN(dcm_clk), |
.RST(pll_reset) |
); |
|
assign write = write_buf; |
assign pll_reset = pll_stop | ~dcm_locked | clk_reset | dcm_status[2]; |
|
always @ (posedge clk) |
begin |
if ( (rd_clk_b[3] == rd_clk_b[2]) && (rd_clk_b[2] == rd_clk_b[1]) && (rd_clk_b[1] != rd_clk_b[0]) ) |
begin |
inbuf_tmp[351:344] <= read_buf; |
inbuf_tmp[343:0] <= inbuf_tmp[351:8]; |
end; |
inbuf <= inbuf_tmp; |
|
if ( wr_start_b1 && wr_start_b2 ) |
begin |
wr_delay <= 5'd0; |
end else |
begin |
wr_delay[0] <= 1'b1; |
wr_delay[4:1] <= wr_delay[3:0]; |
end |
|
if ( ! wr_delay[4] ) |
begin |
outbuf <= { golden_nonce2, hash2, nonce2, golden_nonce1 }; |
end else |
begin |
if ( (wr_clk_b[3] == wr_clk_b[2]) && (wr_clk_b[2] == wr_clk_b[1]) && (wr_clk_b[1] != wr_clk_b[0]) ) |
outbuf[119:0] <= outbuf[127:8]; |
end |
|
if ( reset_buf ) |
begin |
golden_nonce2 <= 32'd0; |
golden_nonce1 <= 32'd0; |
end else if ( golden_nonce != golden_nonce1 ) |
begin |
golden_nonce2 <= golden_nonce1; |
golden_nonce1 <= golden_nonce; |
end |
|
read_buf <= read; |
write_buf <= outbuf[7:0]; |
|
rd_clk_b[0] <= rd_clk; |
rd_clk_b[3:1] <= rd_clk_b[2:0]; |
|
wr_clk_b[0] <= wr_clk; |
wr_clk_b[3:1] <= wr_clk_b[2:0]; |
|
wr_start_b1 <= wr_start; |
wr_start_b2 <= wr_start_b1; |
|
reset_buf <= reset; |
end |
|
always @ (posedge fxclk) |
begin |
dcm_progclk_buf <= dcm_progclk; |
dcm_progdata_buf <= dcm_progdata; |
dcm_progen_buf <= dcm_progen; |
end |
|
|
endmodule |
|
/trunk/fpga/ztex_ufm1_15y1.v
0,0 → 1,169
/*! |
btcminer -- BTCMiner for ZTEX USB-FPGA Modules: HDL code for ZTEX USB-FPGA Module 1.15b (one double hash pipe) |
Copyright (C) 2012 ZTEX GmbH |
http://www.ztex.de |
|
This program is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License version 3 as |
published by the Free Software Foundation. |
|
This program is distributed in the hope that it will be useful, but |
WITHOUT ANY WARRANTY; without even the implied warranty of |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
General Public License for more details. |
|
You should have received a copy of the GNU General Public License |
along with this program; if not, see http://www.gnu.org/licenses/. |
!*/ |
|
module ztex_ufm1_15y1 (fxclk_in, reset, select, clk_reset, pll_stop, dcm_progclk, dcm_progdata, dcm_progen, rd_clk, wr_clk, wr_start, read, write); |
|
input fxclk_in, select, reset, clk_reset, pll_stop, dcm_progclk, dcm_progdata, dcm_progen, rd_clk, wr_clk, wr_start; |
input [7:0] read; |
output [7:0] write; |
|
reg [3:0] rd_clk_b, wr_clk_b; |
reg wr_start_b1, wr_start_b2, reset_buf, clk_reset_buf = 1, pll_stop_buf = 1, select_buf; |
|
reg dcm_progclk_buf, dcm_progdata_buf, dcm_progen_buf; |
reg [4:0] wr_delay; |
reg [351:0] inbuf, inbuf_tmp; |
reg [127:0] outbuf; |
reg [7:0] read_buf, write_buf; |
reg [31:0] golden_nonce1, golden_nonce2; |
|
wire fxclk, clk, dcm_clk, pll_fb, pll_clk0, dcm_locked, pll_reset; |
wire [2:1] dcm_status; |
wire [31:0] golden_nonce, nonce2, hash2; |
|
miner253 m ( |
.clk(clk), |
.reset(reset_buf), |
.midstate(inbuf[351:96]), |
.data(inbuf[95:0]), |
.golden_nonce(golden_nonce), |
.nonce2(nonce2), |
.hash2(hash2) |
); |
|
BUFG bufg_fxclk ( |
.I(fxclk_in), |
.O(fxclk) |
); |
|
BUFG bufg_clk ( |
.I(pll_clk0), |
.O(clk) |
); |
|
DCM_CLKGEN #( |
.CLKFX_DIVIDE(4.0), |
.CLKFX_MULTIPLY(32), |
.CLKFXDV_DIVIDE(2), |
.CLKIN_PERIOD(20.8333) |
) |
dcm0 ( |
.CLKIN(fxclk), |
.CLKFXDV(dcm_clk), |
.FREEZEDCM(1'b0), |
.PROGCLK(dcm_progclk_buf), |
.PROGDATA(dcm_progdata_buf), |
.PROGEN(dcm_progen_buf), |
.LOCKED(dcm_locked), |
.STATUS(dcm_status), |
.RST(clk_reset_buf) |
); |
|
PLL_BASE #( |
.BANDWIDTH("LOW"), |
.CLKFBOUT_MULT(4), |
.CLKOUT0_DIVIDE(4), |
.CLKOUT0_DUTY_CYCLE(0.5), |
.CLK_FEEDBACK("CLKFBOUT"), |
.COMPENSATION("INTERNAL"), |
.DIVCLK_DIVIDE(1), |
.REF_JITTER(0.10), |
.RESET_ON_LOSS_OF_LOCK("FALSE") |
) |
pll0 ( |
.CLKFBOUT(pll_fb), |
.CLKOUT0(pll_clk0), |
.CLKFBIN(pll_fb), |
.CLKIN(dcm_clk), |
.RST(pll_reset) |
); |
|
assign write = select ? write_buf : 8'bz;; |
assign pll_reset = pll_stop_buf | ~dcm_locked | clk_reset_buf | dcm_status[2]; |
|
always @ (posedge clk) |
begin |
if ( (rd_clk_b[3] == rd_clk_b[2]) && (rd_clk_b[2] == rd_clk_b[1]) && (rd_clk_b[1] != rd_clk_b[0]) && select_buf ) |
begin |
inbuf_tmp[351:344] <= read_buf; |
inbuf_tmp[343:0] <= inbuf_tmp[351:8]; |
end; |
inbuf <= inbuf_tmp; // due to TIG's |
|
if ( wr_start_b1 && wr_start_b2 ) |
begin |
wr_delay <= 5'd0; |
end else |
begin |
wr_delay[0] <= 1'b1; |
wr_delay[4:1] <= wr_delay[3:0]; |
end |
|
if ( ! wr_delay[4] ) |
begin |
outbuf <= { golden_nonce2, hash2, nonce2, golden_nonce1 }; |
end else |
begin |
if ( (wr_clk_b[3] == wr_clk_b[2]) && (wr_clk_b[2] == wr_clk_b[1]) && (wr_clk_b[1] != wr_clk_b[0]) ) |
outbuf[119:0] <= outbuf[127:8]; |
end |
|
if ( reset_buf ) |
begin |
golden_nonce2 <= 32'd0; |
golden_nonce1 <= 32'd0; |
end else if ( golden_nonce != golden_nonce1 ) |
begin |
golden_nonce2 <= golden_nonce1; |
golden_nonce1 <= golden_nonce; |
end |
|
read_buf <= read; |
write_buf <= outbuf[7:0]; |
|
rd_clk_b[0] <= rd_clk; |
rd_clk_b[3:1] <= rd_clk_b[2:0]; |
|
wr_clk_b[0] <= wr_clk; |
wr_clk_b[3:1] <= wr_clk_b[2:0]; |
|
wr_start_b1 <= wr_start; |
wr_start_b2 <= wr_start_b1; |
|
select_buf <= select; |
if ( select ) |
begin |
reset_buf <= reset; |
end |
end |
|
always @ (posedge fxclk) |
begin |
dcm_progclk_buf <= dcm_progclk; |
dcm_progdata_buf <= dcm_progdata; |
dcm_progen_buf <= dcm_progen & select; |
if ( select ) |
begin |
clk_reset_buf <= clk_reset; |
pll_stop_buf <= pll_stop; |
end |
end |
|
|
endmodule |
|
/trunk/fpga/miner253.v
0,0 → 1,85
/*! |
btcminer -- BTCMiner for ZTEX USB-FPGA Modules: HDL code: double hash miner |
Copyright (C) 2011 ZTEX GmbH |
http://www.ztex.de |
|
This program is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License version 3 as |
published by the Free Software Foundation. |
|
This program is distributed in the hope that it will be useful, but |
WITHOUT ANY WARRANTY; without even the implied warranty of |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
General Public License for more details. |
|
You should have received a copy of the GNU General Public License |
along with this program; if not, see http://www.gnu.org/licenses/. |
!*/ |
|
module miner253 (clk, reset, midstate, data, golden_nonce, nonce2, hash2); |
|
parameter NONCE_OFFS = 32'd0; |
parameter NONCE_INCR = 32'd1; |
parameter NONCE2_OFFS = 32'd0; |
|
input clk, reset; |
input [255:0] midstate; |
input [95:0] data; |
output reg [31:0] golden_nonce, hash2, nonce2; |
|
|
reg [31:0] nonce; |
wire [255:0] hash; |
wire [31:0] hash2_w; |
reg reset_b1, reset_b2, reset_b3, is_golden_nonce; |
|
sha256_pipe130 p1 ( |
.clk(clk), |
.state(midstate), |
.state2(midstate), |
.data({384'h000002800000000000000000000000000000000000000000000000000000000000000000000000000000000080000000, nonce, data}), |
.hash(hash) |
); |
|
sha256_pipe123 p2 ( |
.clk(clk), |
.data({256'h0000010000000000000000000000000000000000000000000000000080000000, hash}), |
.hash(hash2_w) |
); |
|
always @ (posedge clk) |
begin |
if ( reset_b1 ) |
begin |
nonce <= 32'd254 + NONCE_OFFS; |
end else begin |
nonce <= nonce + NONCE_INCR; |
end |
|
if ( reset_b2 ) |
begin |
nonce2 <= NONCE_OFFS + NONCE2_OFFS; |
end else begin |
nonce2 <= nonce2 + NONCE_INCR; |
end |
|
if ( reset_b3 ) |
begin |
golden_nonce1 <= 32'd0; |
golden_nonce2 <= 32'd0; |
end |
else if ( is_golden_nonce ) |
begin |
golden_nonce1 <= nonce2; |
golgen_nonce2 <= golden_nonce1; |
end |
|
reset_b1 <= reset; |
reset_b2 <= reset; |
reset_b3 <= reset; |
|
hash2 <= hash2_w; |
is_golden_nonce <= hash2_w == 32'ha41f32e7; |
end |
|
endmodule |
/trunk/fpga/ztex_ufm1_15y.ucf
0,0 → 1,49
NET "fxclk_in" TNM_NET = "fxclk_in"; |
TIMESPEC "TS_fxclk_in" = PERIOD "fxclk_in" 20.3ns HIGH 50 %; |
NET "fxclk_in" LOC = "L22" | IOSTANDARD = LVCMOS33 ; |
|
NET "select" LOC = "AB11" | IOSTANDARD = LVCMOS33 ; |
|
# input |
NET "write<0>" LOC = "Y17" | IOSTANDARD = LVCMOS33 | DRIVE = 12; # PB0 |
NET "write<1>" LOC = "V13" | IOSTANDARD = LVCMOS33 | DRIVE = 12; # PB1 |
NET "write<2>" LOC = "W13" | IOSTANDARD = LVCMOS33 | DRIVE = 12; # PB2 |
NET "write<3>" LOC = "AA8" | IOSTANDARD = LVCMOS33 | DRIVE = 12; # PB3 |
NET "write<4>" LOC = "AB8" | IOSTANDARD = LVCMOS33 | DRIVE = 12; # PB4 |
NET "write<5>" LOC = "W6" | IOSTANDARD = LVCMOS33 | DRIVE = 12; # PB5 |
NET "write<6>" LOC = "Y6" | IOSTANDARD = LVCMOS33 | DRIVE = 12; # PB6 |
NET "write<7>" LOC = "Y9" | IOSTANDARD = LVCMOS33 | DRIVE = 12; # PB7 |
|
NET "wr_clk" LOC = "AA22" | IOSTANDARD = LVCMOS33; # PA0 |
NET "wr_start" LOC = "AB17" | IOSTANDARD = LVCMOS33 ; # PA7 |
|
# dcm |
NET "dcm_progclk" LOC = "U15" | IOSTANDARD = LVCMOS33 ; # PA2 |
NET "dcm_progdata" LOC = "AB21" | IOSTANDARD = LVCMOS33 ; # PA4 |
NET "dcm_progen" LOC = "Y18" | IOSTANDARD = LVCMOS33 ; # PA5 |
|
#output |
NET "read<0>" LOC = "V21" | IOSTANDARD = LVCMOS33 ; # PD0 |
NET "read<1>" LOC = "V22" | IOSTANDARD = LVCMOS33 ; # PD1 |
NET "read<2>" LOC = "U20" | IOSTANDARD = LVCMOS33 ; # PD2 |
NET "read<3>" LOC = "U22" | IOSTANDARD = LVCMOS33 ; # PD3 |
NET "read<4>" LOC = "R20" | IOSTANDARD = LVCMOS33 ; # PD4 |
NET "read<5>" LOC = "R22" | IOSTANDARD = LVCMOS33 ; # PD5 |
NET "read<6>" LOC = "P18" | IOSTANDARD = LVCMOS33 ; # PD6 |
NET "read<7>" LOC = "P19" | IOSTANDARD = LVCMOS33 ; # PD7 |
|
NET "reset" LOC = "G20" | IOSTANDARD = LVCMOS33 ; # PC0 |
NET "rd_clk" LOC = "H19" | IOSTANDARD = LVCMOS33 ; # PC6 |
NET "pll_stop" LOC = "H20" | IOSTANDARD = LVCMOS33 ; # PC5 |
NET "clk_reset" LOC = "G19" | IOSTANDARD = LVCMOS33 ; # PC4 |
|
# unused |
#NET "" LOC = "AB9" | IOSTANDARD = LVCMOS33 | DRIVE = 12 ; # PC3 |
#NET "" LOC = "H18" | IOSTANDARD = LVCMOS33 | DRIVE = 12 ; # PC7 |
|
# TIG's |
NET "inbuf[*]" TIG; |
NET "m/golden_nonce[*]" TIG; |
NET "select" TIG; |
PIN "select" TIG; |
|
/trunk/fpga/ztex_ufm1_15b1.v
0,0 → 1,146
/*! |
btcminer -- BTCMiner for ZTEX USB-FPGA Modules: HDL code for ZTEX USB-FPGA Module 1.15b (one double hash pipe) |
Copyright (C) 2011 ZTEX GmbH |
http://www.ztex.de |
|
This program is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License version 3 as |
published by the Free Software Foundation. |
|
This program is distributed in the hope that it will be useful, but |
WITHOUT ANY WARRANTY; without even the implied warranty of |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
General Public License for more details. |
|
You should have received a copy of the GNU General Public License |
along with this program; if not, see http://www.gnu.org/licenses/. |
!*/ |
|
module ztex_ufm1_15b1 (fxclk_in, reset, pll_stop, dcm_progclk, dcm_progdata, dcm_progen, rd_clk, wr_clk, wr_start, read, write); |
|
input fxclk_in, reset, pll_stop, dcm_progclk, dcm_progdata, dcm_progen, rd_clk, wr_clk, wr_start; |
input [7:0] read; |
output [7:0] write; |
|
reg [3:0] rd_clk_b, wr_clk_b; |
reg wr_start_b1, wr_start_b2, reset_buf; |
reg dcm_progclk_buf, dcm_progdata_buf, dcm_progen_buf; |
reg [4:0] wr_delay; |
reg [351:0] inbuf, inbuf_tmp; |
reg [95:0] outbuf; |
reg [7:0] read_buf, write_buf; |
|
wire fxclk, clk, dcm_clk, pll_fb, pll_clk0, dcm_locked, pll_reset; |
wire [31:0] golden_nonce, nonce2, hash2; |
|
miner130 m ( |
.clk(clk), |
.reset(reset_buf), |
.midstate(inbuf[351:96]), |
.data(inbuf[95:0]), |
.golden_nonce(golden_nonce), |
.nonce2(nonce2), |
.hash2(hash2) |
); |
|
BUFG bufg_fxclk ( |
.I(fxclk_in), |
.O(fxclk) |
); |
|
BUFG bufg_clk ( |
.I(pll_clk0), |
.O(clk) |
); |
|
DCM_CLKGEN #( |
.CLKFX_DIVIDE(6.0), |
.CLKFX_MULTIPLY(20), |
.CLKFXDV_DIVIDE(2) |
) |
dcm0 ( |
.CLKIN(fxclk), |
.CLKFX(dcm_clk), |
.FREEZEDCM(1'b0), |
.PROGCLK(dcm_progclk_buf), |
.PROGDATA(dcm_progdata_buf), |
.PROGEN(dcm_progen_buf), |
.LOCKED(dcm_locked), |
.RST(1'b0) |
); |
|
PLL_BASE #( |
.BANDWIDTH("LOW"), |
.CLKFBOUT_MULT(4), |
.CLKOUT0_DIVIDE(4), |
.CLKOUT0_DUTY_CYCLE(0.5), |
.CLK_FEEDBACK("CLKFBOUT"), |
.COMPENSATION("DCM2PLL"), |
.DIVCLK_DIVIDE(1), |
.REF_JITTER(0.05), |
.RESET_ON_LOSS_OF_LOCK("FALSE") |
) |
pll0 ( |
.CLKFBOUT(pll_fb), |
.CLKOUT0(pll_clk0), |
.CLKFBIN(pll_fb), |
.CLKIN(dcm_clk), |
.RST(pll_reset) |
); |
|
assign write = write_buf; |
assign pll_reset = pll_stop | ~dcm_locked; |
|
always @ (posedge clk) |
begin |
if ( (rd_clk_b[3] == rd_clk_b[2]) && (rd_clk_b[2] == rd_clk_b[1]) && (rd_clk_b[1] != rd_clk_b[0]) ) |
begin |
inbuf_tmp[351:344] <= read_buf; |
inbuf_tmp[343:0] <= inbuf_tmp[351:8]; |
end; |
inbuf <= inbuf_tmp; // due to TIG's |
|
if ( wr_start_b1 && wr_start_b2 ) |
begin |
wr_delay <= 5'd0; |
end else |
begin |
wr_delay[0] <= 1'b1; |
wr_delay[4:1] <= wr_delay[3:0]; |
end |
|
if ( ! wr_delay[4] ) |
begin |
outbuf <= { hash2, nonce2, golden_nonce }; |
end else |
begin |
if ( (wr_clk_b[3] == wr_clk_b[2]) && (wr_clk_b[2] == wr_clk_b[1]) && (wr_clk_b[1] != wr_clk_b[0]) ) |
outbuf[87:0] <= outbuf[95:8]; |
end |
|
read_buf <= read; |
write_buf <= outbuf[7:0]; |
|
rd_clk_b[0] <= rd_clk; |
rd_clk_b[3:1] <= rd_clk_b[2:0]; |
|
wr_clk_b[0] <= wr_clk; |
wr_clk_b[3:1] <= wr_clk_b[2:0]; |
|
wr_start_b1 <= wr_start; |
wr_start_b2 <= wr_start_b1; |
|
|
reset_buf <= reset; |
end |
|
always @ (posedge fxclk) |
begin |
dcm_progclk_buf <= dcm_progclk; |
dcm_progdata_buf <= dcm_progdata; |
dcm_progen_buf <= dcm_progen; |
end |
|
|
endmodule |
|
/trunk/fpga/sha256_pipes2.v
0,0 → 1,199
/*! |
btcminer -- BTCMiner for ZTEX USB-FPGA Modules: HDL code: hash pipelines |
Copyright (C) 2011 ZTEX GmbH |
http://www.ztex.de |
|
This program is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License version 3 as |
published by the Free Software Foundation. |
|
This program is distributed in the hope that it will be useful, but |
WITHOUT ANY WARRANTY; without even the implied warranty of |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
General Public License for more details. |
|
You should have received a copy of the GNU General Public License |
along with this program; if not, see http://www.gnu.org/licenses/. |
!*/ |
|
`define IDX(x) (((x)+1)*(32)-1):((x)*(32)) |
`define E0(x) ( {{x}[1:0],{x}[31:2]} ^ {{x}[12:0],{x}[31:13]} ^ {{x}[21:0],{x}[31:22]} ) |
`define E1(x) ( {{x}[5:0],{x}[31:6]} ^ {{x}[10:0],{x}[31:11]} ^ {{x}[24:0],{x}[31:25]} ) |
`define CH(x,y,z) ( (z) ^ ((x) & ((y) ^ (z))) ) |
`define MAJ(x,y,z) ( ((x) & (y)) | ((z) & ((x) | (y))) ) |
`define S0(x) ( { {x}[6:4] ^ {x}[17:15], {{x}[3:0], {x}[31:7]} ^ {{x}[14:0],{x}[31:18]} ^ {x}[31:3] } ) |
`define S1(x) ( { {x}[16:7] ^ {x}[18:9], {{x}[6:0], {x}[31:17]} ^ {{x}[8:0],{x}[31:19]} ^ {x}[31:10] } ) |
|
module sha256_pipe2_base ( clk, i_state, i_data, out ); |
|
parameter STAGES = 64; |
|
input clk; |
input [255:0] i_state; |
input [511:0] i_data; |
output [255:0] out; |
|
localparam Ks = { |
32'h428a2f98, 32'h71374491, 32'hb5c0fbcf, 32'he9b5dba5, |
32'h3956c25b, 32'h59f111f1, 32'h923f82a4, 32'hab1c5ed5, |
32'hd807aa98, 32'h12835b01, 32'h243185be, 32'h550c7dc3, |
32'h72be5d74, 32'h80deb1fe, 32'h9bdc06a7, 32'hc19bf174, |
32'he49b69c1, 32'hefbe4786, 32'h0fc19dc6, 32'h240ca1cc, |
32'h2de92c6f, 32'h4a7484aa, 32'h5cb0a9dc, 32'h76f988da, |
32'h983e5152, 32'ha831c66d, 32'hb00327c8, 32'hbf597fc7, |
32'hc6e00bf3, 32'hd5a79147, 32'h06ca6351, 32'h14292967, |
32'h27b70a85, 32'h2e1b2138, 32'h4d2c6dfc, 32'h53380d13, |
32'h650a7354, 32'h766a0abb, 32'h81c2c92e, 32'h92722c85, |
32'ha2bfe8a1, 32'ha81a664b, 32'hc24b8b70, 32'hc76c51a3, |
32'hd192e819, 32'hd6990624, 32'hf40e3585, 32'h106aa070, |
32'h19a4c116, 32'h1e376c08, 32'h2748774c, 32'h34b0bcb5, |
32'h391c0cb3, 32'h4ed8aa4a, 32'h5b9cca4f, 32'h682e6ff3, |
32'h748f82ee, 32'h78a5636f, 32'h84c87814, 32'h8cc70208, |
32'h90befffa, 32'ha4506ceb, 32'hbef9a3f7, 32'hc67178f2 |
}; |
|
genvar i; |
|
generate |
|
for (i = 0; i <= STAGES; i = i + 1) begin : S |
|
reg [511:0] data; |
reg [223:0] state; |
reg [31:0] t1_p1; |
|
if(i == 0) |
begin |
|
reg [223:0] o_state; |
|
always @ (posedge clk) |
begin |
data <= i_data; |
state <= i_state[223:0]; |
t1_p1 <= i_state[`IDX(7)] + i_data[`IDX(0)] + Ks[`IDX(63)]; |
end |
|
end else |
begin |
|
reg [511:0] data_buf; |
reg [223:0] state_buf; |
reg [31:0] data15_p1, data15_p2, data15_p3, t1; |
|
always @ (posedge clk) |
begin |
data_buf <= S[i-1].data; |
data[479:0] <= data_buf[511:32]; |
|
data15_p1 <= `S1( S[i-1].data[`IDX(15)] ); // 3 |
data15_p2 <= data15_p1; // 1 |
data15_p3 <= ( ( i == 1 ) ? `S1( S[i-1].data[`IDX(14)] ) : S[i-1].data15_p2 ) + S[i-1].data[`IDX(9)] + S[i-1].data[`IDX(0)]; // 3 |
data[`IDX(15)] <= `S0( data_buf[`IDX(1)] ) + data15_p3; // 4 |
|
state_buf <= S[i-1].state; // 2 |
|
t1 <= `CH( S[i-1].state[`IDX(4)], S[i-1].state[`IDX(5)], S[i-1].state[`IDX(6)] ) + `E1( S[i-1].state[`IDX(4)] ) + S[i-1].t1_p1; // 6 |
|
state[`IDX(0)] <= `MAJ( state_buf[`IDX(0)], state_buf[`IDX(1)], state_buf[`IDX(2)] ) + `E0( state_buf[`IDX(0)] ) + t1; // 7 |
state[`IDX(1)] <= state_buf[`IDX(0)]; // 1 |
state[`IDX(2)] <= state_buf[`IDX(1)]; // 1 |
state[`IDX(3)] <= state_buf[`IDX(2)]; // 1 |
state[`IDX(4)] <= state_buf[`IDX(3)] + t1; // 2 |
state[`IDX(5)] <= state_buf[`IDX(4)]; // 1 |
state[`IDX(6)] <= state_buf[`IDX(5)]; // 1 |
|
t1_p1 <= state_buf[`IDX(6)] + data_buf[`IDX(1)] + Ks[`IDX((127-i) & 63)]; // 2 |
end |
|
end |
end |
|
endgenerate |
|
reg [31:0] state7, state7_buf; |
|
always @ (posedge clk) |
begin |
state7_buf <= S[STAGES-1].state[`IDX(6)]; |
state7 <= state7_buf; |
end |
|
assign out[223:0] = S[STAGES].state; |
assign out[255:224] = state7; |
|
endmodule |
|
|
module sha256_pipe130 ( clk, state, state2, data, hash ); |
|
input clk; |
input [255:0] state, state2; |
input [511:0] data; |
output reg [255:0] hash; |
|
wire [255:0] out; |
|
sha256_pipe2_base #( .STAGES(64) ) P ( |
.clk(clk), |
.i_state(state), |
.i_data(data), |
.out(out) |
); |
|
always @ (posedge clk) |
begin |
hash[`IDX(0)] <= state2[`IDX(0)] + out[`IDX(0)]; |
hash[`IDX(1)] <= state2[`IDX(1)] + out[`IDX(1)]; |
hash[`IDX(2)] <= state2[`IDX(2)] + out[`IDX(2)]; |
hash[`IDX(3)] <= state2[`IDX(3)] + out[`IDX(3)]; |
hash[`IDX(4)] <= state2[`IDX(4)] + out[`IDX(4)]; |
hash[`IDX(5)] <= state2[`IDX(5)] + out[`IDX(5)]; |
hash[`IDX(6)] <= state2[`IDX(6)] + out[`IDX(6)]; |
hash[`IDX(7)] <= state2[`IDX(7)] + out[`IDX(7)]; |
end |
|
endmodule |
|
|
module sha256_pipe123 ( clk, data, hash ); |
|
parameter state = 256'h5be0cd191f83d9ab9b05688c510e527fa54ff53a3c6ef372bb67ae856a09e667; |
|
input clk; |
input [511:0] data; |
output [31:0] hash; |
|
wire [255:0] out; |
|
sha256_pipe2_base #( .STAGES(61) ) P ( |
.clk(clk), |
.i_state(state), |
.i_data(data), |
.out(out) |
); |
|
assign hash = out[`IDX(4)]; |
|
endmodule |
|
|
module sha256_pipe129 ( clk, state, data, hash ); |
|
input clk; |
input [255:0] state; |
input [511:0] data; |
output [255:0] hash; |
|
wire [255:0] out; |
|
sha256_pipe2_base #( .STAGES(64) ) P ( |
.clk(clk), |
.i_state(state), |
.i_data(data), |
.out(out) |
); |
|
assign hash = out; |
|
endmodule |
/trunk/Makefile
0,0 → 1,29
######################### |
# configuration section # |
######################### |
|
# Defines the location of the EZ-USB SDK |
ZTEXPREFIX=../../ztex |
|
# The name of the jar archive |
JARTARGET=ZtexBTCMiner.jar |
# Java Classes that have to be build |
CLASSTARGETS=BTCMiner.class |
# Extra dependencies for Java Classes |
CLASSEXTRADEPS= |
|
# ihx files (firmware ROM files) that have to be build |
IHXTARGETS=ztex_ufm1_15b1.ihx ztex_ufm1_15d4.ihx ztex_ufm1_15y1.ihx ztex_ufm1_15d.ihx ztex_ufm1_15y.ihx ztex_ufm1_15d4-nomac.ihx ztex_ufm1_15y1-nomac.ihx |
# Extra Dependencies for ihx files |
IHXEXTRADEPS=btcminer.h |
|
# Extra files that should be included into th jar archive |
EXTRAJARFLAGS= |
EXTRAJARFILES=$(IHXTARGETS) fpga/ztex_ufm1_15b1.bit fpga/ztex_ufm1_15d1.bit fpga/ztex_ufm1_15d3.bit fpga/ztex_ufm1_15d4.bit fpga/ztex_ufm1_15y1.bit |
# fpga/ztex_ufm1_15d.bit |
|
################################ |
# DO NOT CHANAGE THE FOLLOWING # |
################################ |
# includes the main Makefile |
include $(ZTEXPREFIX)/Makefile.mk |
/trunk/ztex_ufm1_15y1-nomac.c
0,0 → 1,21
/*! |
btcminer -- BTCMiner for ZTEX USB-FPGA Modules: EZ-USB FX2 firmware for ZTEX USB FPGA Module 1.15d (one double hash pipe) |
Copyright (C) 2011-2012 ZTEX GmbH |
http://www.ztex.de |
|
This program is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License version 3 as |
published by the Free Software Foundation. |
|
This program is distributed in the hope that it will be useful, but |
WITHOUT ANY WARRANTY; without even the implied warranty of |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
General Public License for more details. |
|
You should have received a copy of the GNU General Public License |
along with this program; if not, see http://www.gnu.org/licenses/. |
!*/ |
|
#define[EEPROM_MAC_DISABLED][1] |
|
#include[ztex_ufm1_15y1.c] |