.SUFFIXES: .cc
-OBJS = ibufcx.o obufcx.o iobufcx.o hubtest.o basic.o
+OBJS = ibufcx.o obufcx.o iobufcx.o iofifo.o hubtest.o basic.o
CXX = g++
CXXFLAGS = -g -O3 -Wall -fPIC
#define STATUSBITS 24,26
-#define HEADER_HEADER 0x0
-#define HEADER_TERM 0x1
-#define HEADER_BUF 0x2
-#define HEADER_DATA 0x3
+#define HEADER_HEADER 0x1
+#define HEADER_TERM 0x2
+#define HEADER_BUF 0x3
+#define HEADER_DATA 0x4
+#define HEADER_ACK 0x5
+
//
// logic array
#include "iobufcx.h"
+#include "iofifo.h"
int acktest(void) {
if (i==0) {
//write a word into buf
buf.WRITE=1;
- buf.SIGIN.set(0x00000000u); // empty header
+ buf.SIGIN.set(0x01000000u); // empty header
}
else if (i==1) {
buf.WRITE=1;
- buf.SIGIN.set(0x03000000u); // data word
+ buf.SIGIN.set(0x04000000u); // data word
}
else if (i==2) {
buf.WRITE=1;
- //buf.SIGIN.set(0x01000000u); // term word
- buf.SIGIN.set(0x02000000u); // EOB word
+ //buf.SIGIN.set(0x02000000u); // term word
+ buf.SIGIN.set(0x03000000u); // EOB word
}
-
-
else buf.WRITE=0;
if (i==2)
}
+void connect(IOBUFCX * a, IOBUFCX * b) {
+ //cross-connect 2 buffers
+ //this is what the OSI_LINK_LAYER should do
+
+ b->SIGIN = a->SIGOUT;
+ a->SIGIN = b->SIGOUT;
+
+ a->READ = a->DATAREADY;
+ b->READ = b->DATAREADY;
+
+ b->WRITE = a->DATAREADY;
+ a->WRITE = b->DATAREADY;
-void main(void) {
+}
- //acktest();
+int iofifotest(void) {
+
+ IOFIFO send,end;
+ for (int i=0; i<15; i++) {
+
+ //TESTBENCH
+ if (i==0) {
+ //write a word into send
+ send.WRITE=1;
+ send.SIGIN.set(0x00adfaceu);
+ }
+ else if (i==1) {
+ send.WRITE=1;
+ send.SIGIN.set(0x00345678u); // data word
+ }
+ else if (i==2) {
+ send.WRITE=1;
+ send.SIGIN.set(0x01212u); // data word
+ } else {
+ send.WRITE=0;
+ }
+
+ //HEADER activate
+ if (i==3) {
+ send.WRITE_SENDER_HEADER=1;
+ send.SENDER_HEADER.set(0x01000000u);
+ } else send.WRITE_SENDER_HEADER=0;
+
+ //ENDPOINT
+ end.WRITE=0;
+ //end.READ=0;
+ end.WRITE_SENDER_HEADER=0;
+
+ //LOGIC
+ for (int l=0;l<100;l++) {
+ //simulate READER
+ if (end.DATAREADY) end.READ=1;
+ else end.READ=0;
+ send.Logic();
+ end.Logic();
+ connect(&send.iobuffer, &end.iobuffer);
+ }
+
+ //
+ if (send.iobuffer.DATAREADY)
+ cout << "DOWN MEDIA SIGOUT " << std::hex << send.iobuffer.SIGOUT.get_value(0,27) << endl;
+ else cout << "NO DOWN MEDIA DATA" << endl;
+
+ if (end.iobuffer.DATAREADY)
+ cout << "UP MEDIA SIGOUT " << std::hex << end.iobuffer.SIGOUT.get_value(0,27) << endl;
+ else cout << "NO UP MEDIA DATA" << endl;
+
+ //cout << "OBUF: ";send.iobuffer.myobuf.Dump();
+ //cout << "IOFIFO: ";send.Dump();
+
+ //cout << "END:OBUF: ";end.iobuffer.myobuf.Dump();
+
+ //buf.myobuf.Dump();
+ //asign CLK
+ send.NextCLK();
+ end.NextCLK();
+ cout << "--------------------" << endl;
+ }
+
+
+}
+
+
+
+
+int main(void) {
+
+ //acktest();
+ iofifotest();
}
}
if ((!(buffer->EMPTY))) { //BUFFER has data
- if (mystate==FREEMODE) {
- if (buffer->SIGOUT.get_value(STATUSBITS) == HEADER_HEADER) { //word to be read is a header
- buffer->READ = READ; //yes, read header
- header.WRITE = 1;
- headerterm.WRITE = 0;
- DATAREADY = 1;
- if (READ)
- nextstate = TRANSFERMODE;
- else
- nextstate = FREEMODE;
- } else if (buffer->SIGOUT.get_value(STATUSBITS) == HEADER_TERM) { //TERM transfer
- buffer->READ = 1; //clean TERM
- header.WRITE = 0;
- headerterm.WRITE = 1; //
- DATAREADY = 0;
- if (READ)
- nextstate = TERMMODE;
- else
+
+ //ACK is something special, it must be killed after one CLK cycle
+ if (buffer->SIGOUT.get_value(STATUSBITS) == HEADER_ACK) {
+ GOT_ACK = 1;
+ buffer->READ = 1; //clean TERM
+ header.WRITE = 0;
+ headerterm.WRITE = 0; //
+ DATAREADY = 0;
+ nextstate = mystate;
+ }
+ else {
+ GOT_ACK = 0;
+ if (mystate==FREEMODE) {
+ if (buffer->SIGOUT.get_value(STATUSBITS) == HEADER_HEADER) { //word to be read is a header
+ buffer->READ = READ; //yes, read header
+ header.WRITE = 1;
+ headerterm.WRITE = 0;
+ DATAREADY = 1;
+ if (READ)
+ nextstate = TRANSFERMODE;
+ else
nextstate = FREEMODE;
- } else { //something is wrong...first word MUST be header or TERM
- buffer->READ = 1; //clean wrong word
- header.WRITE = 0;
- headerterm.WRITE = 0;
- DATAREADY = 0;
- nextstate = ERRORMODE;
- }
- } //FREEMODE
- else if (mystate==TRANSFERMODE) {
- if (buffer->SIGOUT.get_value(STATUSBITS) == HEADER_HEADER) { //word to be read is a header
- buffer->READ = READ; //yes, read header
- //cout << "a" << endl;
- header.WRITE = 1;
- headerterm.WRITE = 0;
- DATAREADY = 1;
- nextstate = TRANSFERMODE;
- } else if (buffer->SIGOUT.get_value(STATUSBITS) == HEADER_TERM) { //TERM transfer
- //cout << buffer->SIGOUT.get_value(STATUSBITS) << endl;
+ } else if (buffer->SIGOUT.get_value(STATUSBITS) == HEADER_TERM) { //TERM transfer
+ buffer->READ = 1; //clean TERM
+ header.WRITE = 0;
+ headerterm.WRITE = 1; //
+ DATAREADY = 0;
+ if (READ)
+ nextstate = TERMMODE;
+ else
+ nextstate = FREEMODE;
+ } else { //something is wrong...first word MUST be header or TERM
+ buffer->READ = 1; //clean wrong word
+ header.WRITE = 0;
+ headerterm.WRITE = 0;
+ DATAREADY = 0;
+ nextstate = ERRORMODE;
+ }
+ } //FREEMODE
+ else if (mystate==TRANSFERMODE) {
+ if (buffer->SIGOUT.get_value(STATUSBITS) == HEADER_HEADER) { //word to be read is a header
+ buffer->READ = READ; //yes, read header
+ //cout << "a" << endl;
+ header.WRITE = 1;
+ headerterm.WRITE = 0;
+ DATAREADY = 1;
+ nextstate = TRANSFERMODE;
+ } else if (buffer->SIGOUT.get_value(STATUSBITS) == HEADER_TERM) { //TERM transfer
+ //cout << buffer->SIGOUT.get_value(STATUSBITS) << endl;
buffer->READ = 1; //clean TERM
header.WRITE = 0;
headerterm.WRITE = 1; //
else
nextstate = mystate;
}
+ }// END NOACK
} // BUFFER is not EMPTY
else { //BUFFER IS EMPTY
if (mystate==FREEMODE) {
};
in WRITE,READ,RESENDHEADER,CLEAR;
out DATAREADY; //means that data can be transferred
+ out GOT_ACK;
// out TERM; //TERM header arrived
// out BUFFEREND; //ACK cycle has to be done
myibuf.RESENDHEADER = RESENDHEADER_IN_INT;
DATAREADY_OUT_INT = myibuf.DATAREADY;
-
//connect to media
- SIGOUT = myobuf.SIGOUT;
+
myibuf.SIGIN = SIGIN;
- myobuf.READ = READ;
- DATAREADY = myobuf.DATAREADY;
myibuf.WRITE = WRITE;
+ if (READ)
+ next_word_counter = word_counter +1;
+
+ if (word_counter == 0) {
+ if (block_counter < MAX_BLOCKS) {
+ //resend header
+ RESENDHEADER_OUT_INT = 1;
+ SIGOUT = myobuf.SIGOUT;
+ DATAREADY = myobuf.DATAREADY; //forward the DATAREADY from the input
+ myobuf.READ = READ;
+ next_block_counter = block_counter;
+ if (READ)
+ next_word_counter = word_counter +1;
+ else
+ next_word_counter = word_counter;
+ } else { //transfer continued
+ if (myibuf.GOT_ACK) {
+ RESENDHEADER_OUT_INT = 1;
+ SIGOUT = myobuf.SIGOUT;
+ DATAREADY = 0;
+ myobuf.READ = 0;
+ next_block_counter = block_counter - 1;
+ next_word_counter = 0;
+ } else { //transfer stalled
+ RESENDHEADER_OUT_INT = 1;
+ SIGOUT = myobuf.SIGOUT;
+ DATAREADY = 0;
+ myobuf.READ = 0;
+ next_block_counter = block_counter;
+ next_word_counter = word_counter;
+ }
+ }
+ } else if (word_counter == (MAX_WORD-1)) {
+ // send EOB
+ RESENDHEADER_OUT_INT = 0;
+ SIGOUT.set(HEADER_BUF << 24);
+ DATAREADY = 1; //so I have DATAREADY
+ myobuf.READ = 0;
+ if (READ) {
+ next_word_counter = 0;
+ if (!myibuf.GOT_ACK) //async ACK
+ next_block_counter = block_counter + 1;
+ else
+ next_block_counter = block_counter;
+ }
+ else {
+ next_word_counter = word_counter;
+ next_block_counter = block_counter;
+ }
+ } else {
+ RESENDHEADER_OUT_INT = 0;
+ SIGOUT = myobuf.SIGOUT;
+ DATAREADY = myobuf.DATAREADY;
+ myobuf.READ = READ;
+ next_block_counter = block_counter;
+ if (READ)
+ next_word_counter = word_counter + 1;
+ else
+ next_word_counter = word_counter;
+ }
myibuf.Logic();
myobuf.Logic();
};
void IOBUFCX::NextCLK(void){
+ word_counter = next_word_counter;
+ block_counter = next_block_counter;
myibuf.NextCLK();
myobuf.NextCLK();
}
// output buffer for ONE channel and ONE port
//
+//hardcoded, later to be made with LSYNC
+#define MAX_WORD 3
+#define MAX_BLOCKS 2
class IOBUFCX {
public:
IOBUFCX() {RESET();};
void RESET() {
+ word_counter =0;
+ block_counter=0;
};
void Logic(void);
out READ_OUT_INT; //IOBUF is activating internal logic
out DATAREADY_OUT_INT; //means that data can be transferred
in DATAREADY_IN_INT; //from other IBUF (stream partner)
- out READ_OUT; //read from other IBUF (stream partner)
-
+
in RESENDHEADER_IN_INT; //in-streaming have to resend header
+ out RESENDHEADER_OUT_INT; //internal logic has to resend header
+
in WRITE; //media is putting data into IBUF
out READ; //media is reading data
out DATAREADY; //media knows that I have somthing to offer
private:
-
+ unsigned int next_word_counter, word_counter;
+ unsigned int block_counter, next_block_counter;
};
--- /dev/null
+#include "iofifo.h"
+
+// WRITE data to network
+// way1.) write the header first, then the data
+// way2.) write first the data, data transfer is locked until you write the header
+// after transfer, write a TERM header to the header register
+// TODO: IDLE mode...
+
+
+
+void IOFIFO::Logic(void){
+
+ //header control
+ reg_sender_header.SIGIN = SENDER_HEADER;
+ reg_sender_header.WRITE = WRITE_SENDER_HEADER;
+
+ //input fifo -> decouples writing from network transfer
+ buffer->SIGIN = SIGIN;
+ buffer->WRITE = WRITE;
+
+ //output device
+ SIGOUT = iobuffer.SIGOUT_INT;
+ iobuffer.READ_IN_INT = READ;
+ DATAREADY = iobuffer.DATAREADY_OUT_INT;
+
+ if (mystate == IOFIFO_FREEMODE) { //nothing happened so far...
+ iobuffer.SIGIN_INT = SIGIN;
+ iobuffer.DATAREADY_IN_INT = 0;
+ buffer->READ = 0;
+ if (reg_sender_header.SIGOUT.get_value(STATUSBITS) == HEADER_HEADER) {
+ nextstate = IOFIFO_SENDHEADER;
+ } else
+ nextstate = IOFIFO_FREEMODE;
+ } // end FREEMODE
+ else if (mystate == IOFIFO_SENDHEADER) {
+ iobuffer.SIGIN_INT = reg_sender_header.SIGOUT;
+ iobuffer.DATAREADY_IN_INT = 1;
+ buffer->READ = 0;
+ if (iobuffer.READ_OUT_INT) //yes, buffer reads my header
+ nextstate = IOFIFO_SENDMODE;
+ else
+ nextstate = IOFIFO_SENDHEADER;
+ } // end SENDHEADER
+ else if (mystate == IOFIFO_SENDMODE) {
+ if (iobuffer.RESENDHEADER_OUT_INT) {
+ iobuffer.SIGIN_INT = reg_sender_header.SIGOUT;
+ iobuffer.DATAREADY_IN_INT = 1;
+ buffer->READ = 0;
+ } else {
+ iobuffer.SIGIN_INT = buffer->SIGOUT;
+ if (reg_sender_header.SIGOUT.get_value(STATUSBITS) == HEADER_HEADER) {
+ iobuffer.DATAREADY_IN_INT = (!buffer->EMPTY);
+ nextstate = IOFIFO_SENDMODE;
+ }
+ else {
+ iobuffer.DATAREADY_IN_INT = 0;
+ nextstate = IOFIFO_FREEMODE;
+ }
+ buffer->READ = iobuffer.READ_OUT_INT;
+ }
+ }
+
+ buffer->Logic();
+ iobuffer.Logic();
+ reg_sender_header.Logic();
+
+}
+
+
+void IOFIFO::NextCLK(void){
+ mystate = nextstate;
+ buffer->NextCLK();
+ iobuffer.NextCLK();
+ reg_sender_header.NextCLK();
+}
+
+void IOFIFO::Dump(void){
+ cout << "ST:" << mystate << " BUFREAD " << buffer->READ << " HH " << reg_sender_header.SIGOUT.get_value(STATUSBITS) << " HW " << reg_sender_header.WRITE << " IOB_DR " << iobuffer.DATAREADY_IN_INT << " IOB_RSH " <<iobuffer.RESENDHEADER_OUT_INT << endl;
+}
--- /dev/null
+#ifndef IOFIFO_H
+#define IOFIFO_H
+
+#define IOFIFO_FREEMODE 1
+#define IOFIFO_SENDHEADER 2
+#define IOFIFO_SENDMODE 3
+
+#include "iobufcx.h"
+
+class IOFIFO {
+ public:
+ IOFIFO() {
+ buffer = new FIFO28(16);
+ RESET();
+ };
+ void RESET() {
+ mystate = IOFIFO_FREEMODE;
+ reg_sender_header.WRITE = 1;
+ reg_sender_header.SIGIN.set(0xfffffff);
+ reg_sender_header.NextCLK();
+ reg_sender_header.WRITE = 0;
+
+ };
+
+ in_vector28 SENDER_HEADER;
+ in WRITE_SENDER_HEADER;
+ in_vector28 SIGIN; //write data from host
+ in WRITE; //write data from host
+ out FULL; //fifo full (not yet implemented)
+
+ out_vector28 SIGOUT; //data from network
+ in READ; //read data from host
+ out DATAREADY; //data can be read
+
+ //now some lines for the media
+
+
+ void Logic(void);
+
+ void NextCLK(void);
+
+ void Dump(void);
+
+ IOBUFCX iobuffer;
+ FIFO28 * buffer; //in principle 24 Bit would be enough....
+ REG28 reg_sender_header;;
+
+ private:
+ state mystate, nextstate;
+
+};
+
+
+#endif
if ((mystate==OBUF_FREEMODE) || (mystate==OBUF_WAITINGMODE)) {
if (IBUF_STATEIN == WAITINGMODE) {
//partner has got EOB and we should send an ACK
- SIGOUT.set(HEADER_TERM << 24); //prepare ACK
+ SIGOUT.set(HEADER_ACK << 24); //prepare ACK
if (READ)
nextstate = OBUF_CLEARMODE;
else
};
void OBUFCX::NextCLK(void){
- mystate = nextstate;
+ mystate = nextstate;
}