/*
This file is part of JOP, the Java Optimized Processor
see <http://www.jopdesign.com/>
Copyright (C) 2010, Martin Schoeberl (martin@jopdesign.com)
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/>.
*/
package csp;
import util.Timer;
import joprt.RtThread;
import com.jopdesign.sys.Native;
import com.jopdesign.io.IOFactory;
import com.jopdesign.io.SysDevice;
/**
* @author flavius
*
*/
// Note: This program finishes on the main processor, when PRIMECNT primes were detected
// The rest of the processors may continue to wait for further input!
// Thus the time is for computing nrCpu*(PRIMECNT-1) + 1 primes.
public class EratosthenesCsp3 extends RtThread {
final static int PRIMECNT = 20;
final static int PRIORITY = 1;
final static int PERIOD = 1000;
static Object lock = new Object();
public static int endCalculation = 0;
volatile static boolean go = false;
int id;
int nid; // next processor id
public EratosthenesCsp3(int i, int ni) {
super(PRIORITY, PERIOD);
id = i;
nid = ni;
//crtlvl = 0;
//primes = new int[PRIMECNT];
}
public static int cpuIndex2NoCAddress(int i) {
// this is when I use two rings, with the other ring starting at Addr 4
// if(i==2) return 4;
// else return i;
// this is with a single ring!
return i;
}
/**
* @param args
*/
public static void main(String[] args) {
// Initialization for benchmarking
int start = 0;
int stop = 0;
int time = 0;
System.out.println("Eratosthenes Sieve, v3, SPM");
SysDevice sys = IOFactory.getFactory().getSysDevice();
int nrCpu = Runtime.getRuntime().availableProcessors();
// ni must be translated from proc index to NoC address!
for (int i=0; i<nrCpu; i++) {
int ni = i+1;
if(ni==nrCpu) ni = 0;
System.out.println(cpuIndex2NoCAddress(ni));
RtThread rtt = new EratosthenesCsp3(i, cpuIndex2NoCAddress(ni));
rtt.setProcessor(i);
}
System.out.println("starting cpus.");
// start threads and other cpus
RtThread.startMission();
// give threads time to setup their memory
// RtThread.sleepMs(100);
// using clock cycles instead
start = sys.cntInt; // (int) System.currentTimeMillis();
// let them run
go = true;
// wait for finish
while (true) {
synchronized (lock) {
if (endCalculation == 1) // nrCpu) // just the first needs to finish!
break;
}
}
// End of measurement
stop = sys.cntInt; // (int) System.currentTimeMillis();
System.out.println("StartTime: " + start);
System.out.println("StopTime: " + stop);
time = stop - start;
System.out.println("TimeSpent: " + time);
}
/*
public void run() {
computePrimes(id, nid);
}
*/
public void run() {
Runnable r = new Runnable() {
public void run() {
computePrimes(id, nid);
}
};
PrivateScope scope = new PrivateScope(1000);
while (!go) {
waitForNextPeriod();
}
scope.enter(r);
}
static void computePrimes(int id, int nid) {
int crtlvl = 0;
int[] primes = new int[PRIMECNT];
int[] mulprimes = new int[PRIMECNT];
// proc 0
int i = 2;
while(crtlvl < PRIMECNT) {
// receive a level and a candidate
// int lvl, candidate;
// proc 0
int lvl = 0;
int candidate = i;
if(id == 0) {
if(((Native.rd(NoC.NOC_REG_STATUS) & NoC.NOC_MASK_RCV) != 0)) { // if(NoC.isReceiving()) {
// System.out.println("<");
// something to process
/////////////////////// receive a two word message instead ////////////////
lvl = Native.rd(NoC.NOC_REG_RCVDATA);
// while(NoC.isReceiveBufferEmpty());
candidate = Native.rd(NoC.NOC_REG_RCVDATA);
Native.wr(0, NoC.NOC_REG_RCVRESET);
///////////////////////////////////////////////////////////////////////////
// level increases here
lvl++;
} else {
i++;
}
} else {
/////////////////////// receive a two word message instead ////////////////
while((Native.rd(NoC.NOC_REG_STATUS) & NoC.NOC_MASK_RCV) == 0); // while(!NoC.isReceiving());
lvl = Native.rd(NoC.NOC_REG_RCVDATA);
// while(NoC.isReceiveBufferEmpty());
candidate = Native.rd(NoC.NOC_REG_RCVDATA);
Native.wr(0, NoC.NOC_REG_RCVRESET);
///////////////////////////////////////////////////////////////////////////
}
// check it against the current prime
if(lvl==crtlvl) {
// this is a new prime, so store it
primes[crtlvl] = candidate;
// next number to check is..
mulprimes[crtlvl] = candidate; // + candidate;
crtlvl++;
// do not send it further
} else {
// check whether is divisible with the current prime
// % was way too slow
// if(candidate % primes[lvl] != 0) {
// must bring the current multiple up to the candidate size
while(mulprimes[lvl] < candidate)
mulprimes[lvl] = mulprimes[lvl] + primes[lvl];
if(candidate != mulprimes[lvl]) {
// may be prime, send it further!
////////////////// send a two word message instead ///////////////////////////
while((Native.rd(NoC.NOC_REG_STATUS) & NoC.NOC_MASK_SND) != 0); // while(NoC.isSending());
Native.wr(nid, NoC.NOC_REG_SNDDST);
Native.wr(2, NoC.NOC_REG_SNDCNT);
Native.wr(lvl, NoC.NOC_REG_SNDDATA);
// while(NoC.isSendBufferFull());
Native.wr(candidate, NoC.NOC_REG_SNDDATA);
//////////////////////////////////////////////////////////////////////////////
} else {
// this number should be discarded
// must update the multiples to check against
// may not need this with the adjustment
// mulprimes[lvl] = candidate + primes[lvl];
}
}
}
synchronized (lock) {
endCalculation++;
}
// all entries are full
if(id == 0) {
// print out the result for this processor
System.out.print("Primes on cpu0 ");
for(i=0;i<PRIMECNT;i++)
System.out.println(primes[i]);
}
}
}