From: hades Date: Fri, 10 Mar 2006 17:29:37 +0000 (+0000) Subject: bidirectional handshake working, Ingo X-Git-Tag: oldGBE~788 X-Git-Url: https://jspc29.x-matter.uni-frankfurt.de/git/?a=commitdiff_plain;h=11f758a6d428358d93b75dbcc1470093b921a5bf;p=trbnet.git bidirectional handshake working, Ingo --- diff --git a/Makefile b/Makefile index 85b3f03..8c15b61 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ .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 diff --git a/basic.h b/basic.h index d2c6de5..5f3f56b 100644 --- a/basic.h +++ b/basic.h @@ -46,10 +46,12 @@ using namespace std; #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 diff --git a/hubtest.cc b/hubtest.cc index bcc1c23..69a0fab 100644 --- a/hubtest.cc +++ b/hubtest.cc @@ -1,4 +1,5 @@ #include "iobufcx.h" +#include "iofifo.h" int acktest(void) { @@ -10,19 +11,17 @@ 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) @@ -52,11 +51,96 @@ int acktest(void) { } +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(); } diff --git a/ibufcx.cc b/ibufcx.cc index 25d1489..01e00f9 100644 --- a/ibufcx.cc +++ b/ibufcx.cc @@ -14,43 +14,55 @@ void IBUFCX::Logic(void){ } 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; // @@ -80,6 +92,7 @@ void IBUFCX::Logic(void){ else nextstate = mystate; } + }// END NOACK } // BUFFER is not EMPTY else { //BUFFER IS EMPTY if (mystate==FREEMODE) { diff --git a/ibufcx.h b/ibufcx.h index 4a51f9d..03c4f22 100644 --- a/ibufcx.h +++ b/ibufcx.h @@ -20,6 +20,7 @@ public: }; 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 diff --git a/iobufcx.cc b/iobufcx.cc index f5a316f..79537fe 100644 --- a/iobufcx.cc +++ b/iobufcx.cc @@ -15,14 +15,71 @@ void IOBUFCX::Logic(void){ 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(); @@ -30,6 +87,8 @@ void IOBUFCX::Logic(void){ }; void IOBUFCX::NextCLK(void){ + word_counter = next_word_counter; + block_counter = next_block_counter; myibuf.NextCLK(); myobuf.NextCLK(); } diff --git a/iobufcx.h b/iobufcx.h index 2ec451d..2523877 100644 --- a/iobufcx.h +++ b/iobufcx.h @@ -11,11 +11,16 @@ // 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); @@ -30,9 +35,10 @@ class IOBUFCX { 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 @@ -47,7 +53,8 @@ class IOBUFCX { private: - + unsigned int next_word_counter, word_counter; + unsigned int block_counter, next_block_counter; }; diff --git a/iofifo.cc b/iofifo.cc new file mode 100644 index 0000000..2bda75e --- /dev/null +++ b/iofifo.cc @@ -0,0 +1,79 @@ +#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 " <