/*
|
/*
|
Asynchronous SDM NoC
|
Asynchronous SDM NoC
|
(C)2011 Wei Song
|
(C)2011 Wei Song
|
Advanced Processor Technologies Group
|
Advanced Processor Technologies Group
|
Computer Science, the Univ. of Manchester, UK
|
Computer Science, the Univ. of Manchester, UK
|
|
|
Authors:
|
Authors:
|
Wei Song wsong83@gmail.com
|
Wei Song wsong83@gmail.com
|
|
|
License: LGPL 3.0 or later
|
License: LGPL 3.0 or later
|
|
|
Package definition.
|
Package definition.
|
|
|
History:
|
History:
|
19/08/2008 Initial version. <wsong83@gmail.com>
|
19/08/2008 Initial version. <wsong83@gmail.com>
|
04/08/2008 Add the check empty function. <wsong83@gmail.com>
|
04/08/2008 Add the check empty function. <wsong83@gmail.com>
|
22/09/2008 Override the copy and = operations. <wsong83@gmail.com>
|
22/09/2008 Override the copy and = operations. <wsong83@gmail.com>
|
21/09/2010 Support VC and use templates. <wsong83@gmail.com>
|
21/09/2010 Support VC and use templates. <wsong83@gmail.com>
|
19/11/2010 Fixed to support the minimal 8bit VC. <wsong83@gmail.com>
|
19/11/2010 Fixed to support the minimal 8bit VC. <wsong83@gmail.com>
|
27/05/2011 Clean up for opensource. <wsong83@gmail.com>
|
27/05/2011 Clean up for opensource. <wsong83@gmail.com>
|
|
30/05/2011 Clear the addresses field when clear a flit. <wsong83@gmail.com>
|
|
|
*/
|
*/
|
|
|
#ifndef PDU_DEF_H_
|
#ifndef PDU_DEF_H_
|
#define PDU_DEF_H_
|
#define PDU_DEF_H_
|
|
|
#include <ostream>
|
#include <ostream>
|
#include <iomanip>
|
#include <iomanip>
|
|
|
using namespace std;
|
using namespace std;
|
|
|
// flit types: data, idle, head and tail
|
// flit types: data, idle, head and tail
|
enum ftype_t {F_DAT, F_IDLE, F_HD, F_TL};
|
enum ftype_t {F_DAT, F_IDLE, F_HD, F_TL};
|
|
|
template<unsigned int BW>
|
template<unsigned int BW>
|
class pdu_flit;
|
class pdu_flit;
|
|
|
// override the method to stream out flits
|
// override the method to stream out flits
|
template<unsigned int BW>
|
template<unsigned int BW>
|
ostream& operator<< (ostream& os, const pdu_flit<BW>& dd) {
|
ostream& operator<< (ostream& os, const pdu_flit<BW>& dd) {
|
switch(dd.ftype) {
|
switch(dd.ftype) {
|
case F_DAT:
|
case F_DAT:
|
os << hex << "<DATA:" << (unsigned int)(dd.vcn) << ":" << (unsigned int)(dd.prio) << ":";
|
os << hex << "<DATA:" << (unsigned int)(dd.vcn) << ":" << (unsigned int)(dd.prio) << ":";
|
for(unsigned int i=0; i<BW; i++)
|
for(unsigned int i=0; i<BW; i++)
|
os << setw(2) << setfill('0') << (unsigned int)(dd[i]);
|
os << setw(2) << setfill('0') << (unsigned int)(dd[i]);
|
os << setw(0) << dec << ">";
|
os << setw(0) << dec << ">";
|
break;
|
break;
|
case F_HD:
|
case F_HD:
|
os << hex << "<HEAD:" << (unsigned int)(dd.vcn) << ":" << (unsigned int)(dd.prio) << ":" << (unsigned int)(dd.addrx) << "," << (unsigned int)(dd.addry) << ":";
|
os << hex << "<HEAD:" << (unsigned int)(dd.vcn) << ":" << (unsigned int)(dd.prio) << ":" << (unsigned int)(dd.addrx) << "," << (unsigned int)(dd.addry) << ":";
|
for(unsigned int i=0; i<BW-1; i++)
|
for(unsigned int i=0; i<BW-1; i++)
|
os << setw(2) << setfill('0') << (unsigned int)(dd[i]);
|
os << setw(2) << setfill('0') << (unsigned int)(dd[i]);
|
os << setw(0) << dec << ">";
|
os << setw(0) << dec << ">";
|
break;
|
break;
|
case F_TL:
|
case F_TL:
|
os << hex << "<TAIL:" << (unsigned int)(dd.vcn) << ":" << (unsigned int)(dd.prio) << ":";
|
os << hex << "<TAIL:" << (unsigned int)(dd.vcn) << ":" << (unsigned int)(dd.prio) << ":";
|
for(unsigned int i=0; i<BW; i++)
|
for(unsigned int i=0; i<BW; i++)
|
os << setw(2) << setfill('0') << (unsigned int)(dd[i]);
|
os << setw(2) << setfill('0') << (unsigned int)(dd[i]);
|
os << setw(0) << dec << ">";
|
os << setw(0) << dec << ">";
|
break;
|
break;
|
case F_IDLE:
|
case F_IDLE:
|
os << "<IDLE>" ;
|
os << "<IDLE>" ;
|
break;
|
break;
|
default:
|
default:
|
os << "<ERR!>" ;
|
os << "<ERR!>" ;
|
break;
|
break;
|
}
|
}
|
|
|
return os;
|
return os;
|
}
|
}
|
|
|
// flit used in NoC communication
|
// flit used in NoC communication
|
template<unsigned int BW>
|
template<unsigned int BW>
|
class pdu_flit {
|
class pdu_flit {
|
public:
|
public:
|
unsigned char vcn;
|
unsigned char vcn;
|
unsigned char prio;
|
unsigned char prio;
|
ftype_t ftype;
|
ftype_t ftype;
|
unsigned int addrx, addry;
|
unsigned int addrx, addry;
|
private:
|
private:
|
unsigned char data [BW];
|
unsigned char data [BW];
|
|
|
void copy(const pdu_flit<BW>& dd) {
|
void copy(const pdu_flit<BW>& dd) {
|
vcn = dd.vcn;
|
vcn = dd.vcn;
|
prio = dd.prio;
|
prio = dd.prio;
|
ftype = dd.ftype;
|
ftype = dd.ftype;
|
addrx = dd.addrx;
|
addrx = dd.addrx;
|
addry = dd.addry;
|
addry = dd.addry;
|
for(unsigned int i=0; i<BW; i++) data[i] = dd.data[i];
|
for(unsigned int i=0; i<BW; i++) data[i] = dd.data[i];
|
}
|
}
|
|
|
public:
|
public:
|
pdu_flit()
|
pdu_flit()
|
: vcn(0), prio(0), ftype(F_IDLE)
|
: vcn(0), prio(0), ftype(F_IDLE)
|
{
|
{
|
for(unsigned int i=0; i<BW; i++) data[i] = 0;
|
for(unsigned int i=0; i<BW; i++) data[i] = 0;
|
}
|
}
|
|
|
void clear(){ // clear the flit
|
void clear(){ // clear the flit
|
vcn = 0;
|
vcn = 0;
|
prio = 0;
|
prio = 0;
|
ftype = F_IDLE;
|
ftype = F_IDLE;
|
|
addrx = 0;
|
|
addry = 0;
|
for(unsigned int i=0; i<BW; i++) data[i] = 0;
|
for(unsigned int i=0; i<BW; i++) data[i] = 0;
|
}
|
}
|
|
|
unsigned char& operator[] (unsigned int index){ // read as a vector
|
unsigned char& operator[] (unsigned int index){ // read as a vector
|
return data[index];
|
return data[index];
|
}
|
}
|
|
|
const unsigned char& operator[] (unsigned int index) const { // read as a vector
|
const unsigned char& operator[] (unsigned int index) const { // read as a vector
|
return data[index];
|
return data[index];
|
}
|
}
|
|
|
friend ostream& operator<< <BW> (ostream& os, const pdu_flit<BW>& dd); // output to standard output stream
|
friend ostream& operator<< <BW> (ostream& os, const pdu_flit<BW>& dd); // output to standard output stream
|
|
|
pdu_flit(const pdu_flit<BW>& dd){ // override the default copy operation
|
pdu_flit(const pdu_flit<BW>& dd){ // override the default copy operation
|
copy(dd);
|
copy(dd);
|
}
|
}
|
|
|
pdu_flit& operator=(const pdu_flit<BW>& dd){ // override the default eque with operation
|
pdu_flit& operator=(const pdu_flit<BW>& dd){ // override the default eque with operation
|
copy(dd);
|
copy(dd);
|
return(*this);
|
return(*this);
|
}
|
}
|
};
|
};
|
|
|
//===============================================================================
|
//===============================================================================
|
// method to stream out frames
|
// method to stream out frames
|
template<unsigned int BW>
|
template<unsigned int BW>
|
class pdu_frame;
|
class pdu_frame;
|
|
|
template<unsigned int BW>
|
template<unsigned int BW>
|
ostream& operator<< (ostream& os, const pdu_frame<BW>& dd) {
|
ostream& operator<< (ostream& os, const pdu_frame<BW>& dd) {
|
os << hex << "<FRAME:p" << (unsigned int)(dd.prio) << ":a" << (unsigned int)(dd.addrx) << "," << (unsigned int)(dd.addry) << ":s" << dd.fsize << ":";
|
os << hex << "<FRAME:p" << (unsigned int)(dd.prio) << ":a" << (unsigned int)(dd.addrx) << "," << (unsigned int)(dd.addry) << ":s" << dd.fsize << ":";
|
// os << setw(2) << setfill('0');
|
// os << setw(2) << setfill('0');
|
for(unsigned int i=0; i<dd.fsize; i++)
|
for(unsigned int i=0; i<dd.fsize; i++)
|
os << setw(2) << setfill('0') << (unsigned int)(dd[i]);
|
os << setw(2) << setfill('0') << (unsigned int)(dd[i]);
|
os << setw(0) << dec << ">";
|
os << setw(0) << dec << ">";
|
return os;
|
return os;
|
}
|
}
|
|
|
// frame definition
|
// frame definition
|
template<unsigned int BW>
|
template<unsigned int BW>
|
class pdu_frame{
|
class pdu_frame{
|
|
|
public:
|
public:
|
unsigned int addrx, addry;
|
unsigned int addrx, addry;
|
unsigned char prio;
|
unsigned char prio;
|
unsigned int fsize;
|
unsigned int fsize;
|
int rptr, wptr;
|
int rptr, wptr;
|
|
|
private:
|
private:
|
unsigned char * data; // data field
|
unsigned char * data; // data field
|
|
|
public:
|
public:
|
pdu_frame()
|
pdu_frame()
|
: addrx(0), addry(0), prio(0), fsize(0), rptr(-1), wptr(0), data(NULL)
|
: addrx(0), addry(0), prio(0), fsize(0), rptr(-1), wptr(0), data(NULL)
|
{}
|
{}
|
|
|
pdu_frame(unsigned int fs)
|
pdu_frame(unsigned int fs)
|
: addrx(0), addry(0), prio(0), fsize(fs), rptr(-1), wptr(0)
|
: addrx(0), addry(0), prio(0), fsize(fs), rptr(-1), wptr(0)
|
{
|
{
|
data = new unsigned char [fs];
|
data = new unsigned char [fs];
|
}
|
}
|
|
|
~pdu_frame() {
|
~pdu_frame() {
|
if(data != NULL) {
|
if(data != NULL) {
|
delete[] data;
|
delete[] data;
|
data = NULL;
|
data = NULL;
|
}
|
}
|
}
|
}
|
|
|
void clear() {
|
void clear() {
|
rptr = -1;
|
rptr = -1;
|
wptr = 0;
|
wptr = 0;
|
}
|
}
|
|
|
unsigned char& operator[] (unsigned int index) {
|
unsigned char& operator[] (unsigned int index) {
|
if(index > fsize) // need to enlarge the buf
|
if(index > fsize) // need to enlarge the buf
|
resize(index);
|
resize(index);
|
|
|
return data[index];
|
return data[index];
|
}
|
}
|
|
|
const unsigned char& operator[] (unsigned int index) const {
|
const unsigned char& operator[] (unsigned int index) const {
|
return data[index];
|
return data[index];
|
}
|
}
|
|
|
bool empty() {
|
bool empty() {
|
return ((rptr == wptr) || (wptr == 0));
|
return ((rptr == wptr) || (wptr == 0));
|
}
|
}
|
|
|
void push(unsigned char dd) {
|
void push(unsigned char dd) {
|
if(wptr==fsize)
|
if(wptr==fsize)
|
resize(fsize+1);
|
resize(fsize+1);
|
|
|
data[wptr++] = dd;
|
data[wptr++] = dd;
|
}
|
}
|
|
|
unsigned char pop() {
|
unsigned char pop() {
|
if(empty())
|
if(empty())
|
return 0;
|
return 0;
|
|
|
return data[rptr++];
|
return data[rptr++];
|
}
|
}
|
|
|
pdu_frame& operator<< (const pdu_flit<BW>& dd) {
|
pdu_frame& operator<< (const pdu_flit<BW>& dd) {
|
switch(dd.ftype) {
|
switch(dd.ftype) {
|
case F_DAT:
|
case F_DAT:
|
for(unsigned int i=0; i<BW; i++)
|
for(unsigned int i=0; i<BW; i++)
|
push(dd[i]);
|
push(dd[i]);
|
break;
|
break;
|
case F_HD:
|
case F_HD:
|
addrx = dd.addrx;
|
addrx = dd.addrx;
|
addry = dd.addry;
|
addry = dd.addry;
|
prio = dd.prio;
|
prio = dd.prio;
|
for(unsigned int i=0; i<BW-1; i++)
|
for(unsigned int i=0; i<BW-1; i++)
|
push(dd[i]);
|
push(dd[i]);
|
break;
|
break;
|
case F_TL:
|
case F_TL:
|
for(unsigned int i=0; i<BW; i++)
|
for(unsigned int i=0; i<BW; i++)
|
push(dd[i]);
|
push(dd[i]);
|
resize(wptr);
|
resize(wptr);
|
break;
|
break;
|
default:
|
default:
|
break;
|
break;
|
}
|
}
|
return *this;
|
return *this;
|
}
|
}
|
|
|
pdu_frame& operator>> (pdu_flit<BW>& dd) {
|
pdu_frame& operator>> (pdu_flit<BW>& dd) {
|
if(rptr==-1) {
|
if(rptr==-1) {
|
dd.ftype = F_HD;
|
dd.ftype = F_HD;
|
rptr++;
|
rptr++;
|
for(unsigned int i=0; i<BW-1; i++) {
|
for(unsigned int i=0; i<BW-1; i++) {
|
dd[i] = pop();
|
dd[i] = pop();
|
}
|
}
|
dd.addrx = addrx;
|
dd.addrx = addrx;
|
dd.addry = addry;
|
dd.addry = addry;
|
} else {
|
} else {
|
dd.ftype = F_DAT;
|
dd.ftype = F_DAT;
|
for(unsigned int i=0; i<BW; i++) {
|
for(unsigned int i=0; i<BW; i++) {
|
dd[i] = pop();
|
dd[i] = pop();
|
}
|
}
|
}
|
}
|
if(empty())
|
if(empty())
|
dd.ftype = F_TL;
|
dd.ftype = F_TL;
|
|
|
return *this;
|
return *this;
|
}
|
}
|
|
|
// friend ostream& operator<< <BW> (ostream& os, const pdu_frame<BW>& dd);
|
// friend ostream& operator<< <BW> (ostream& os, const pdu_frame<BW>& dd);
|
|
|
pdu_frame(const pdu_frame<BW>& dd) {
|
pdu_frame(const pdu_frame<BW>& dd) {
|
copy(dd);
|
copy(dd);
|
}
|
}
|
|
|
pdu_frame<BW>& operator=(const pdu_frame<BW>& dd) {
|
pdu_frame<BW>& operator=(const pdu_frame<BW>& dd) {
|
copy(dd);
|
copy(dd);
|
return (*this);
|
return (*this);
|
}
|
}
|
|
|
unsigned int psize() {
|
unsigned int psize() {
|
unsigned int prac_size = fsize;
|
unsigned int prac_size = fsize;
|
while(1) {
|
while(1) {
|
if(data[prac_size-1] == 0)
|
if(data[prac_size-1] == 0)
|
prac_size--;
|
prac_size--;
|
else
|
else
|
break;
|
break;
|
}
|
}
|
return prac_size;
|
return prac_size;
|
}
|
}
|
|
|
private:
|
private:
|
void resize(unsigned int fs) {
|
void resize(unsigned int fs) {
|
// boundry check
|
// boundry check
|
if(fs == fsize)
|
if(fs == fsize)
|
return;
|
return;
|
|
|
// resize the buffer
|
// resize the buffer
|
unsigned char * buf = new unsigned char [fs];
|
unsigned char * buf = new unsigned char [fs];
|
for(unsigned int i=0; (i<fsize && i<fs); i++) {
|
for(unsigned int i=0; (i<fsize && i<fs); i++) {
|
buf[i] = data[i];
|
buf[i] = data[i];
|
}
|
}
|
fsize = fs;
|
fsize = fs;
|
delete[] data;
|
delete[] data;
|
data = buf;
|
data = buf;
|
}
|
}
|
|
|
void copy(const pdu_frame<BW>& dd) {
|
void copy(const pdu_frame<BW>& dd) {
|
addrx = dd.addrx;
|
addrx = dd.addrx;
|
addry = dd.addry;
|
addry = dd.addry;
|
prio = dd.prio;
|
prio = dd.prio;
|
resize(dd.fsize);
|
resize(dd.fsize);
|
rptr = dd.rptr;
|
rptr = dd.rptr;
|
wptr = dd.wptr;
|
wptr = dd.wptr;
|
|
|
for(unsigned int i=0; i<fsize; i++) {
|
for(unsigned int i=0; i<fsize; i++) {
|
data[i] = dd.data[i];
|
data[i] = dd.data[i];
|
}
|
}
|
}
|
}
|
|
|
};
|
};
|
|
|
|
|
#endif /* PDU_DEF_H_ */
|
#endif /* PDU_DEF_H_ */
|
|
|