package csp;
import com.jopdesign.sys.Native;
import com.jopdesign.sys.Const;
// Network on Chip access primitives
// it should allow sending and receiving at the same time!!
public class NoC {
// hardcoded, could be put in Const
public static final int NOC_MASK_ADDR = 0x00FF; // LS byte
public static final int NOC_MASK_BUSY = 0x0100;
public static final int NOC_MASK_SND = 0x0200;
public static final int NOC_MASK_RCV = 0x0400;
public static final int NOC_MASK_EOD = 0x0800;
public static final int NOC_MASK_SNDEMPTY = 0x1000;
public static final int NOC_MASK_SNDFULL = 0x2000;
public static final int NOC_MASK_RCVEMPTY = 0x4000;
public static final int NOC_MASK_RCVFULL = 0x8000;
// registers read
public static final int NOC_REG_STATUS = Const.NOC_ADDR;
// deprecated
// static final int NOC_REG_RCVCNT = Const.NOC_ADDR | 0x01;
public static final int NOC_REG_RCVSLOTS = Const.NOC_ADDR | 0x01;
public static final int NOC_REG_RCVSRC = Const.NOC_ADDR | 0x02;
public static final int NOC_REG_RCVDATA = Const.NOC_ADDR | 0x03;
// registers write
public static final int NOC_REG_RCVRESET = Const.NOC_ADDR;
public static final int NOC_REG_SNDCNT = Const.NOC_ADDR | 0x01;
public static final int NOC_REG_SNDDST = Const.NOC_ADDR | 0x02;
public static final int NOC_REG_SNDDATA = Const.NOC_ADDR | 0x03;
// this node's address, must be initialized
// private static int myAddress = -1;
// just take the current node address for later use
/*
public static void initialize() {
myAddress = Native.rd(NOC_REG_STATUS) & NOC_MASK_ADDR;
}
*/
public static int thisAddress() {
// throw new Error("Static fields are shared for all cores!");
// bummer
// return myAddress;
return Native.rd(NOC_REG_STATUS) & NOC_MASK_ADDR;
}
// some flag accesses
public static boolean isBusy() {
return (Native.rd(NOC_REG_STATUS) & NOC_MASK_BUSY) != 0;
}
public static boolean isSending() {
return (Native.rd(NOC_REG_STATUS) & NOC_MASK_SND) != 0;
}
public static boolean isReceiving() {
return (Native.rd(NOC_REG_STATUS) & NOC_MASK_RCV) != 0;
}
public static boolean isEoD() {
return (Native.rd(NOC_REG_STATUS) & NOC_MASK_EOD) != 0;
}
public static boolean isSendBufferFull() {
return (Native.rd(NOC_REG_STATUS) & NOC_MASK_SNDFULL) != 0;
}
public static boolean isSendBufferEmpty() {
return (Native.rd(NOC_REG_STATUS) & NOC_MASK_SNDEMPTY) != 0;
}
public static boolean isReceiveBufferFull() {
return (Native.rd(NOC_REG_STATUS) & NOC_MASK_RCVFULL) != 0;
}
public static boolean isReceiveBufferEmpty() {
return (Native.rd(NOC_REG_STATUS) & NOC_MASK_RCVEMPTY) != 0;
}
// not that interesting really
public static int getSourceAddress() {
return Native.rd(NOC_REG_RCVSRC);
}
// shows the slots containing data as a bit map
// 1 means data present, 0 means not Data or EoD
// use to implement ALT or PRI ALT
public static int getDataSlots() {
return Native.rd(NOC_REG_RCVSLOTS);
}
public static boolean sendIfFree(
int dstAddr, int header, int cnt, int buf[]) {
if(isSending()) return false;
// can send data here
Native.wr(dstAddr, NOC_REG_SNDDST);
Native.wr(cnt+1, NOC_REG_SNDCNT); // account for the header
Native.wr(header, NOC_REG_SNDDATA);
int i=0;
while(i<cnt) {
while(!isSendBufferFull());
Native.wr(buf[i], NOC_REG_SNDDATA);
i++;
}
return true;
}
public static int readData() {
return Native.rd(NOC_REG_RCVDATA);
}
// call this to reset EoD flag and allow more receive!
public static void writeReset() {
Native.wr(0, NOC_REG_RCVRESET);
}
// same as writeReset, but with the possibility to ignore slots
// 1 on position K means ignore slots from node K
// 0 means receive, to be backward compatible
public static void writeResetMask(int bitmap) {
Native.wr(bitmap, NOC_REG_RCVRESET);
}
// Single word send and receive.
// Params:
// - dstAddr : the NoC node address. this is automatically
// assigned to each node in Hw at bootup.
// For each node can be detected with NoC.thisAddress();
// It will only have values from 0 to N-1
// - d : any data
public static void nb_send1(int dstAddr, int d) {
Native.wr(dstAddr, NOC_REG_SNDDST);
Native.wr(1, NOC_REG_SNDCNT);
Native.wr(d, NOC_REG_SNDDATA);
}
// receives from any source
// check NoC.getSourceAddress() for the NoC node address of the
// sender.
public static int b_receive1() {
while(!isReceiving());
int d = Native.rd(NOC_REG_RCVDATA);
// NoC.isEoD() should be true here for single word messages!
//
// does reset for more receive. after this,
// the source, count and everything else may be faulty
Native.wr(0, NOC_REG_RCVRESET); // aka writeReset();
return d;
}
}