URL
https://opencores.org/ocsvn/async_sdm_noc/async_sdm_noc/trunk
Subversion Repositories async_sdm_noc
Compare Revisions
- This comparison shows the changes necessary to convert path
/async_sdm_noc/trunk/common/tb
- from Rev 22 to Rev 37
- ↔ Reverse comparison
Rev 22 → Rev 37
/hash_table.h
0,0 → 1,145
/* |
Asynchronous SDM NoC |
(C)2011 Wei Song |
Advanced Processor Technologies Group |
Computer Science, the Univ. of Manchester, UK |
|
Authors: |
Wei Song wsong83@gmail.com |
|
License: LGPL 3.0 or later |
|
A hash table container to store the frames under transmission. |
?? Using STL may be better? |
|
Sorry, I have no intention to explain the codes below as it is unlikely to modify it. |
If there are bugs here, please email me. |
|
History: |
29/06/2010 Initial version. <wsong83@gmail.com> |
27/05/2011 Clean up for opensource. <wsong83@gmail.com> |
|
*/ |
|
#ifndef HASH_TABLE_H_ |
#define HASH_TABLE_H_ |
|
#include <ostream> |
|
using namespace std; |
|
template<typename T, unsigned int HSIZE> |
class hash_table; |
|
|
template<typename T, unsigned int HSIZE> |
ostream& operator<< (ostream& os, const hash_table<T,HSIZE>& HB) { |
T * item; |
os << "Records in hash table:" << endl; |
for(unsigned int i=0; i<HSIZE; i++) { |
os << "vector " << i << ": "; |
item = HB.dat[i][0]; |
while(item != NULL) { |
os << *item << "| "; |
item = item->next; |
} |
os << endl; |
} |
return os; |
} |
|
template<typename T, unsigned int HSIZE> |
class hash_table { |
|
public: |
T * dat [HSIZE][2]; |
|
hash_table() { |
for(unsigned int i=0; i<HSIZE; i++) { |
dat[i][0] = NULL; |
dat[i][1] = NULL; |
} |
} |
|
void insert ( T& ); /* insert an item into the hash table */ |
T * find ( long ); /* find an item */ |
T * find ( const T& ); /* find an item by reading an existing item */ |
void clear ( T * ); /* delete an item in the hash table */ |
|
~hash_table() { |
for(unsigned int i=0; i<HSIZE; i++) { |
if(dat[i][0] != NULL) { |
delete dat[i][0]; |
dat[i][0] = NULL; |
dat[i][1] = NULL; |
} |
} |
} |
|
friend ostream& operator<< <T,HSIZE> (ostream&, const hash_table<T,HSIZE>&); |
|
private: |
T* search (T*, long); |
}; |
|
template<typename T, unsigned int HSIZE> |
void hash_table<T,HSIZE>::insert ( T& RD) { |
long key = RD.key; |
unsigned int vcn = key%HSIZE; |
T * entry = dat[vcn][1]; |
|
if(entry == NULL) { /* the whole vector is empty right now */ |
dat[vcn][0] = &RD; |
dat[vcn][1] = &RD; |
} else { /* non-empty vector */ |
entry->next = &RD; |
RD.pre = entry; |
dat[vcn][1] = &RD; |
} |
} |
|
template<typename T, unsigned int HSIZE> |
T * hash_table<T,HSIZE>::find ( long mkey) { |
unsigned int vcn = mkey%HSIZE; |
return search(dat[vcn][0], mkey); |
} |
|
template<typename T, unsigned int HSIZE> |
T * hash_table<T,HSIZE>::find ( const T& RD) { |
return find((long)(RD)); |
} |
|
template<typename T, unsigned int HSIZE> |
void hash_table<T,HSIZE>::clear ( T * RD) { |
unsigned int vcn = ((long)(*RD)) % HSIZE; |
|
if(RD->pre == NULL) /* head of a vector */ |
dat[vcn][0] = RD->next; |
|
if(RD->next == NULL) /* tail of a vector */ |
dat[vcn][1] = RD->pre; |
|
if(RD->pre != NULL) |
(RD->pre)->next = RD->next; |
|
if(RD->next != NULL) |
(RD->next)->pre = RD->pre; |
|
RD->pre = NULL; |
RD->next = NULL; |
|
delete RD; |
} |
|
template<typename T, unsigned int HSIZE> |
T* hash_table<T,HSIZE>::search (T* entry, long mkey) { |
while(entry != NULL) { |
if((long)(*entry) == mkey) |
return entry; |
else |
entry = entry->next; |
} |
return NULL; |
} |
|
#endif |
/anaproc.cpp
0,0 → 1,26
/* |
Asynchronous SDM NoC |
(C)2011 Wei Song |
Advanced Processor Technologies Group |
Computer Science, the Univ. of Manchester, UK |
|
Authors: |
Wei Song wsong83@gmail.com |
|
License: LGPL 3.0 or later |
|
The SystemC class to keep a module of the simulation analysis object. |
|
History: |
27/02/2011 Initial version. <wsong83@gmail.com> |
28/05/2011 Clean up for opensource. <wsong83@gmail.com> |
|
*/ |
|
#include "anaproc.h" |
|
NCSC_MODULE_EXPORT(AnaProc) |
|
// the simulation analysis object, global object |
sim_ana * ANA = new sim_ana(Warm_UP, Record_Period); |
|
/anaproc.v
0,0 → 1,32
/* |
Asynchronous SDM NoC |
(C)2011 Wei Song |
Advanced Processor Technologies Group |
Computer Science, the Univ. of Manchester, UK |
|
Authors: |
Wei Song wsong83@gmail.com |
|
License: LGPL 3.0 or later |
|
The SystemC to keep a module of the simulation analysis object. |
|
History: |
27/02/2011 Initial version. <wsong83@gmail.com> |
30/05/2011 Clean up for opensource. <wsong83@gmail.com> |
|
*/ |
|
module AnaProc () |
// |
// The foreign attribute string value must be a SystemC value. |
// |
(* integer foreign = "SystemC"; |
*); |
// |
// Verilog port names must match port names exactly as they appear in the |
// sc_module class in SystemC; they must also match in order, mode, and type. |
// |
|
endmodule |
|
/sim_ana.cpp
0,0 → 1,186
/* |
Asynchronous SDM NoC |
(C)2011 Wei Song |
Advanced Processor Technologies Group |
Computer Science, the Univ. of Manchester, UK |
|
Authors: |
Wei Song wsong83@gmail.com |
|
License: LGPL 3.0 or later |
|
Simulation analyzer, gethering info. for performance analyses. |
|
Possible bugs: |
* the histograph function has not been tested yet. |
|
|
History: |
29/06/2010 Initial version. <wsong83@gmail.com> |
27/05/2011 Clean up for opensource. <wsong83@gmail.com> |
|
*/ |
|
#include "sim_ana.h" |
|
bool sim_ana::set_ana_parameters(double mwt, double mrp) { |
if((mwt < 0) || (mrp < 0)) |
return false; |
|
warm_time = mwt; |
record_period = mrp; |
return true; |
} |
|
bool sim_ana::analyze_delay(string mfname) { |
ofstream file_handle; |
|
delay_ana = true; |
delay_file = mfname; |
|
file_handle.open(delay_file.data(), fstream::trunc); |
file_handle.close(); |
|
return true; |
} |
|
bool sim_ana::analyze_throughput(string mfname) { |
ofstream file_handle; |
|
throughput_ana = true; |
throughput_file = mfname; |
|
file_handle.open(throughput_file.data(), fstream::trunc); |
file_handle.close(); |
|
return true; |
} |
|
bool sim_ana::analyze_delay_histo(string mframe, double tstart, double tend, unsigned int binnum) { |
ofstream file_handle; |
|
if((tstart < 0) || (tend <= tstart) || (binnum < 3)) |
return false; |
|
delay_histo_ana = true; |
delay_histo_file = mframe; |
|
file_handle.open(delay_histo_file.data(), fstream::trunc); |
file_handle.close(); |
|
delay_histo_start = tstart; |
delay_histo_end = tend; |
delay_histo_gap = (tstart - tend) / (binnum - 2); |
delay_histo_binnum = binnum; |
|
histo_data = new unsigned long [binnum]; |
|
for(unsigned int i=0; i<binnum; i++) |
histo_data[i] = 0; |
|
return true; |
} |
|
bool sim_ana::start(long mkey, double mtime) { |
sim_record<2> * mrd; |
|
mrd = new sim_record<2> (mtime, mkey); |
|
ANA.insert(*mrd); |
|
return true; |
} |
|
bool sim_ana::stop(long mkey, double mtime, unsigned int payload) { |
ofstream file_handle; |
sim_record<2> * mrd; |
|
mrd = ANA.find(mkey); |
|
if(mrd == NULL) |
return false; |
|
// cout << mtime << " " << mtime - mrd->stamp[0] << endl; |
|
if(mtime < warm_time) { |
ANA.clear(mrd); |
return true; |
} |
|
if(delay_ana) { |
fm_dly += (mtime - mrd->stamp[0]); |
pth_dly += (mrd->stamp[1] - mrd->stamp[0]); |
} |
|
if(throughput_ana) { |
th_value += payload; |
} |
|
if(delay_histo_ana) { |
double delay = mtime - mrd->stamp[0]; |
|
if(delay >= delay_histo_end) |
histo_data[delay_histo_binnum-1]++; |
else { |
delay -= delay_histo_start; |
if(delay < 0) |
histo_data[0]++; |
else { |
histo_data[(unsigned long)(1 + delay/delay_histo_gap)]++; |
} |
} |
} |
|
ANA.clear(mrd); |
|
// check whether need to write out |
if(floor(mtime/record_period) > floor(last_time/record_period)) { |
if(delay_ana) { |
file_handle.open(delay_file.data(), fstream::app); |
file_handle << mtime << "\t" << fm_dly.avalue() << "\t" << pth_dly.avalue() << endl; |
file_handle.close(); |
} |
|
if(throughput_ana) { |
file_handle.open(throughput_file.data(), fstream::app); |
file_handle << mtime << "\t" << th_value.value() << endl; |
file_handle.close(); |
} |
|
last_time = mtime; |
} |
|
|
return true; |
} |
|
bool sim_ana::record(long mkey, double mtime) { |
sim_record<2> * mrd; |
|
mrd = ANA.find(mkey); |
|
if(mrd == NULL) |
return false; |
|
mrd->stamp[mrd->index] = mtime; |
|
return true; |
} |
|
|
sim_ana::~sim_ana() { |
ofstream file_handle; |
|
if(delay_histo_ana) { |
file_handle.open(delay_histo_file.data(), fstream::app); |
|
for(unsigned int i=0; i<delay_histo_binnum; i++) |
file_handle << (double)(delay_histo_start + i*delay_histo_gap) << "\t" << histo_data[i] << endl; |
|
file_handle.close(); |
} |
|
if(histo_data != NULL) |
delete[] histo_data; |
} |
|
/anaproc.h
0,0 → 1,46
/* |
Asynchronous SDM NoC |
(C)2011 Wei Song |
Advanced Processor Technologies Group |
Computer Science, the Univ. of Manchester, UK |
|
Authors: |
Wei Song wsong83@gmail.com |
|
License: LGPL 3.0 or later |
|
The SystemC to keep a module of the simulation analysis object. |
|
History: |
27/02/2011 Initial version. <wsong83@gmail.com> |
28/05/2011 Clean up for opensource. <wsong83@gmail.com> |
|
*/ |
|
#ifndef ANA_PROC_H_ |
#define ANA_PROC_H_ |
|
#include "define.h" |
#include <systemc.h> |
|
class AnaProc : public sc_module { |
|
public: |
SC_CTOR(AnaProc) |
{ |
ANA->analyze_delay("delay.ana"); |
ANA->analyze_throughput("throughput.ana"); |
SC_THREAD(run_proc); |
} |
|
void run_proc() { |
while(1){ |
wait(SIM_TIME, SC_NS); |
} |
} |
|
}; |
|
|
|
#endif |
/pdu_def.h
0,0 → 1,307
/* |
Asynchronous SDM NoC |
(C)2011 Wei Song |
Advanced Processor Technologies Group |
Computer Science, the Univ. of Manchester, UK |
|
Authors: |
Wei Song wsong83@gmail.com |
|
License: LGPL 3.0 or later |
|
Package definition. |
|
History: |
19/08/2008 Initial version. <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> |
21/09/2010 Support VC and use templates. <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> |
30/05/2011 Clear the addresses field when clear a flit. <wsong83@gmail.com> |
|
*/ |
|
#ifndef PDU_DEF_H_ |
#define PDU_DEF_H_ |
|
#include <ostream> |
#include <iomanip> |
|
using namespace std; |
|
// flit types: data, idle, head and tail |
enum ftype_t {F_DAT, F_IDLE, F_HD, F_TL}; |
|
template<unsigned int BW> |
class pdu_flit; |
|
// override the method to stream out flits |
template<unsigned int BW> |
ostream& operator<< (ostream& os, const pdu_flit<BW>& dd) { |
switch(dd.ftype) { |
case F_DAT: |
os << hex << "<DATA:" << (unsigned int)(dd.vcn) << ":" << (unsigned int)(dd.prio) << ":"; |
for(unsigned int i=0; i<BW; i++) |
os << setw(2) << setfill('0') << (unsigned int)(dd[i]); |
os << setw(0) << dec << ">"; |
break; |
case F_HD: |
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++) |
os << setw(2) << setfill('0') << (unsigned int)(dd[i]); |
os << setw(0) << dec << ">"; |
break; |
case F_TL: |
os << hex << "<TAIL:" << (unsigned int)(dd.vcn) << ":" << (unsigned int)(dd.prio) << ":"; |
for(unsigned int i=0; i<BW; i++) |
os << setw(2) << setfill('0') << (unsigned int)(dd[i]); |
os << setw(0) << dec << ">"; |
break; |
case F_IDLE: |
os << "<IDLE>" ; |
break; |
default: |
os << "<ERR!>" ; |
break; |
} |
|
return os; |
} |
|
// flit used in NoC communication |
template<unsigned int BW> |
class pdu_flit { |
public: |
unsigned char vcn; |
unsigned char prio; |
ftype_t ftype; |
unsigned int addrx, addry; |
private: |
unsigned char data [BW]; |
|
void copy(const pdu_flit<BW>& dd) { |
vcn = dd.vcn; |
prio = dd.prio; |
ftype = dd.ftype; |
addrx = dd.addrx; |
addry = dd.addry; |
for(unsigned int i=0; i<BW; i++) data[i] = dd.data[i]; |
} |
|
public: |
pdu_flit() |
: vcn(0), prio(0), ftype(F_IDLE) |
{ |
for(unsigned int i=0; i<BW; i++) data[i] = 0; |
} |
|
void clear(){ // clear the flit |
vcn = 0; |
prio = 0; |
ftype = F_IDLE; |
addrx = 0; |
addry = 0; |
for(unsigned int i=0; i<BW; i++) data[i] = 0; |
} |
|
unsigned char& operator[] (unsigned int index){ // read as a vector |
return data[index]; |
} |
|
const unsigned char& operator[] (unsigned int index) const { // read as a vector |
return data[index]; |
} |
|
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 |
copy(dd); |
} |
|
pdu_flit& operator=(const pdu_flit<BW>& dd){ // override the default eque with operation |
copy(dd); |
return(*this); |
} |
}; |
|
//=============================================================================== |
// method to stream out frames |
template<unsigned int BW> |
class pdu_frame; |
|
template<unsigned int BW> |
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 << setw(2) << setfill('0'); |
for(unsigned int i=0; i<dd.fsize; i++) |
os << setw(2) << setfill('0') << (unsigned int)(dd[i]); |
os << setw(0) << dec << ">"; |
return os; |
} |
|
// frame definition |
template<unsigned int BW> |
class pdu_frame{ |
|
public: |
unsigned int addrx, addry; |
unsigned char prio; |
unsigned int fsize; |
int rptr, wptr; |
|
private: |
unsigned char * data; // data field |
|
public: |
pdu_frame() |
: addrx(0), addry(0), prio(0), fsize(0), rptr(-1), wptr(0), data(NULL) |
{} |
|
pdu_frame(unsigned int fs) |
: addrx(0), addry(0), prio(0), fsize(fs), rptr(-1), wptr(0) |
{ |
data = new unsigned char [fs]; |
} |
|
~pdu_frame() { |
if(data != NULL) { |
delete[] data; |
data = NULL; |
} |
} |
|
void clear() { |
rptr = -1; |
wptr = 0; |
} |
|
unsigned char& operator[] (unsigned int index) { |
if(index > fsize) // need to enlarge the buf |
resize(index); |
|
return data[index]; |
} |
|
const unsigned char& operator[] (unsigned int index) const { |
return data[index]; |
} |
|
bool empty() { |
return ((rptr == wptr) || (wptr == 0)); |
} |
|
void push(unsigned char dd) { |
if(wptr==fsize) |
resize(fsize+1); |
|
data[wptr++] = dd; |
} |
|
unsigned char pop() { |
if(empty()) |
return 0; |
|
return data[rptr++]; |
} |
|
pdu_frame& operator<< (const pdu_flit<BW>& dd) { |
switch(dd.ftype) { |
case F_DAT: |
for(unsigned int i=0; i<BW; i++) |
push(dd[i]); |
break; |
case F_HD: |
addrx = dd.addrx; |
addry = dd.addry; |
prio = dd.prio; |
for(unsigned int i=0; i<BW-1; i++) |
push(dd[i]); |
break; |
case F_TL: |
for(unsigned int i=0; i<BW; i++) |
push(dd[i]); |
resize(wptr); |
break; |
default: |
break; |
} |
return *this; |
} |
|
pdu_frame& operator>> (pdu_flit<BW>& dd) { |
if(rptr==-1) { |
dd.ftype = F_HD; |
rptr++; |
for(unsigned int i=0; i<BW-1; i++) { |
dd[i] = pop(); |
} |
dd.addrx = addrx; |
dd.addry = addry; |
} else { |
dd.ftype = F_DAT; |
for(unsigned int i=0; i<BW; i++) { |
dd[i] = pop(); |
} |
} |
if(empty()) |
dd.ftype = F_TL; |
|
return *this; |
} |
|
// friend ostream& operator<< <BW> (ostream& os, const pdu_frame<BW>& dd); |
|
pdu_frame(const pdu_frame<BW>& dd) { |
copy(dd); |
} |
|
pdu_frame<BW>& operator=(const pdu_frame<BW>& dd) { |
copy(dd); |
return (*this); |
} |
|
unsigned int psize() { |
unsigned int prac_size = fsize; |
while(1) { |
if(data[prac_size-1] == 0) |
prac_size--; |
else |
break; |
} |
return prac_size; |
} |
|
private: |
void resize(unsigned int fs) { |
// boundry check |
if(fs == fsize) |
return; |
|
// resize the buffer |
unsigned char * buf = new unsigned char [fs]; |
for(unsigned int i=0; (i<fsize && i<fs); i++) { |
buf[i] = data[i]; |
} |
fsize = fs; |
delete[] data; |
data = buf; |
} |
|
void copy(const pdu_frame<BW>& dd) { |
addrx = dd.addrx; |
addry = dd.addry; |
prio = dd.prio; |
resize(dd.fsize); |
rptr = dd.rptr; |
wptr = dd.wptr; |
|
for(unsigned int i=0; i<fsize; i++) { |
data[i] = dd.data[i]; |
} |
} |
|
}; |
|
|
#endif /* PDU_DEF_H_ */ |
/procelem.h
0,0 → 1,130
/* |
Asynchronous SDM NoC |
(C)2011 Wei Song |
Advanced Processor Technologies Group |
Computer Science, the Univ. of Manchester, UK |
|
Authors: |
Wei Song wsong83@gmail.com |
|
License: LGPL 3.0 or later |
|
The SystemC processing element. |
|
History: |
26/02/2011 Initial version. <wsong83@gmail.com> |
31/05/2011 Clean up for opensource. <wsong83@gmail.com> |
|
*/ |
|
#ifndef PROCELEM_H_ |
#define PROCELEM_H_ |
|
#include "define.h" |
#include <systemc.h> |
|
|
// a function to generate random numbers comply with an exponential distribution with expection exp |
double rand_exponential(double exp) { |
unsigned int rint = rand() % (unsigned int)(1e6); |
double rdat = rint * 1.0 / 1e6; |
return (-1.0 * exp * log(rdat)); |
} |
|
class ProcElem : public sc_module { |
|
public: |
sc_in<bool> rst_n; // active low reset |
sc_port<sc_fifo_out_if<FRAME> > Fout; // frame output port |
sc_port<sc_fifo_in_if<FRAME> > Fin; // frame input port |
|
SC_HAS_PROCESS(ProcElem); |
|
unsigned int addrx, addry; // the local address |
|
ProcElem(sc_module_name nm, unsigned int addrx, unsigned int addry) |
: sc_module(nm), addrx(addrx), addry(addry) |
{ |
SC_THREAD(tproc); // frame transmission thread |
SC_THREAD(rproc); // frame receiving thread |
} |
|
// the transmission thread |
void tproc() { |
// waiting for reset |
wait(rst_n.posedge_event()); |
|
while(1) { |
// wait for a random interval |
if(FFreq != 0) { |
double rnum = rand_exponential(1e6/FFreq); |
wait(rnum, SC_PS); |
} |
|
// generate a frame |
// specify the target address according to random uniform traffic |
unsigned int rint, tarx, tary; |
rint = rand()%(DIMX*DIMY-1); |
if(rint == addrx*DIMY + addry) |
rint = DIMX*DIMY-1; |
|
tarx = rint/DIMY; |
tary = rint%DIMY; |
|
// initialize the frame object |
FRAME tframe(FLEN); |
|
// fill in the fields |
tframe.addrx = tarx; |
tframe.addry = tary; |
for(unsigned int i=0; i<FLEN; i++) |
tframe.push(rand()&0xff); |
|
// specify the unique key of each frame |
// a key is 32 bits log |
// in this test bench, it is the first 4 bytes of the frame payload |
unsigned long key = 0; |
for(unsigned int i=0; (i<FLEN && i<4); i++) { |
key <<= 8; |
key |= tframe[i]; |
} |
|
// record the new frame |
ANA->start(key, sc_time_stamp().to_double()); |
|
// sen the frame to the router |
Fout->write(tframe); |
} |
} |
|
// the receiving thread |
void rproc() { |
while(1) { |
// initialize a space for the frame |
FRAME rframe; |
|
// read in the frame |
rframe = Fin->read(); |
unsigned long key = 0; |
|
// regenerate the unique key |
for(unsigned int i=0; (i<FLEN && i<4); i++) { |
key <<= 8; |
key |= rframe[i]; |
} |
|
// check the key in the simulation analysis database and update info. |
if(!ANA->stop(key, sc_time_stamp().to_double(), rframe.psize())) { |
// report error when no match is found |
cout << sc_time_stamp() << " " << name() ; |
cout << "packet did not find!" << endl; |
cout << rframe << endl; |
sc_stop(); |
} |
} |
} |
|
}; |
|
#endif |
|
/sim_record.h
0,0 → 1,90
/* |
Asynchronous SDM NoC |
(C)2011 Wei Song |
Advanced Processor Technologies Group |
Computer Science, the Univ. of Manchester, UK |
|
Authors: |
Wei Song wsong83@gmail.com |
|
License: LGPL 3.0 or later |
|
Simulation record element. |
|
History: |
28/06/2010 Initial version. <wsong83@gmail.com> |
27/05/2011 Clean up for opensource. <wsong83@gmail.com> |
|
*/ |
|
#ifndef SIM_RECORD_H_ |
#define SIM_RECORD_H_ |
|
#include <ostream> |
|
using namespace std; |
|
template<unsigned int TSIZE> |
class sim_record; |
|
template<unsigned int TSIZE> |
ostream& operator<< (ostream& os, const sim_record<TSIZE>& mrd) { |
os << hex << mrd.key << " " << dec; |
for(unsigned int i=0; i<TSIZE; i++) |
os << mrd.stamp[i] << " "; |
return os; |
} |
|
template<unsigned int TSIZE> |
class sim_record { |
|
public: |
double stamp [TSIZE]; /* vector to record time information */ |
long key; /* the hash key for searching */ |
unsigned int index; /* the current stamp index */ |
sim_record<TSIZE> * next; /* pointer to the next record */ |
sim_record<TSIZE> * pre; /* pointer to the previous record */ |
|
sim_record() |
: key(0), index(0), next(NULL), pre(NULL) |
{} |
|
sim_record(double mt, long mkey, sim_record<TSIZE> * mnp = NULL, sim_record<TSIZE> * mpp = NULL) |
: key(mkey), index(1), next(mnp), pre(mpp) { |
for(unsigned int i=0; i<TSIZE; i++) |
stamp[i] = mt; |
} |
|
sim_record( const sim_record<TSIZE>& mrd ) |
: key(mrd.key), index(mrd.index), next(NULL), pre(NULL) { |
for(unsigned int i=0; i<TSIZE; i++) |
stamp[i] = mrd.stamp[i]; |
} |
|
sim_record<TSIZE>& operator= ( const sim_record<TSIZE>& mrd ) { |
key = mrd.key; |
index = mrd.index; |
next = NULL; |
pre = NULL; |
for(unsigned int i=0; i<TSIZE; i++) |
stamp[i] = mrd.stamp[i]; |
} |
|
~sim_record() { |
if(next != NULL) { |
delete next; |
next = NULL; |
} |
pre = NULL; |
} |
|
operator long() const { |
return key; |
} |
|
friend ostream& operator<< <TSIZE> (ostream&, const sim_record<TSIZE>&); |
|
}; |
|
|
#endif |
/sim_ana.h
0,0 → 1,141
/* |
Asynchronous SDM NoC |
(C)2011 Wei Song |
Advanced Processor Technologies Group |
Computer Science, the Univ. of Manchester, UK |
|
Authors: |
Wei Song wsong83@gmail.com |
|
License: LGPL 3.0 or later |
|
Simulation analyzer, gethering info. for performance analyses. |
|
Possible bugs: |
* the histograph function has not been tested yet. |
|
|
History: |
29/06/2010 Initial version. <wsong83@gmail.com> |
28/05/2011 Clean up for opensource. <wsong83@gmail.com> |
|
*/ |
|
#ifndef SIM_ANA_H_ |
#define SIM_ANA_H_ |
|
#include <cstdlib> |
#include <cmath> |
#include <iostream> |
#include <fstream> |
#include <string> |
#include "sim_record.h" |
#include "hash_table.h" |
|
using namespace std; |
|
// a data type for accumulative performance, such as throughput analysis |
class accu_record{ |
private: |
double V1, V2; /* two values to avoid loss of accuracy, V1 save the accumulated V2 of at least 512 records */ |
unsigned int N1, N2; |
public: |
accu_record() |
:V1(0), V2(0), N1(0), N2(0) |
{} |
|
accu_record& operator+= (const double m) { |
N2++; |
V2 += m; |
if(N2 >= N1/512) { |
N1 += N2; |
V1 += V2; |
N2 = 0; |
V2 = 0; |
} |
return(*this); |
} |
|
double avalue() { /* return averged value */ |
double rt; |
|
if(0 == N1+N2) |
rt = 0; |
else |
rt = (V1 + V2) / (N1 + N2); |
|
V1 = 0; |
V2 = 0; |
N1 = 0; |
N2 = 0; |
return rt; |
} |
|
double value() { /* return the accumulative value */ |
double rt; |
|
if(0 == N1+N2) |
rt = 0; |
else |
rt = (V1 + V2); |
|
V1 = 0; |
V2 = 0; |
N1 = 0; |
N2 = 0; |
return rt; |
} |
}; |
|
/* the major simulation record class, only one such object in one simulation */ |
class sim_ana { |
public: |
|
sim_ana() |
: warm_time(0), record_period(0),last_time(0), |
delay_ana(false), throughput_ana(false), delay_histo_ana(false), |
histo_data(NULL) {} |
|
sim_ana(double mwt, double mrp) |
: warm_time(mwt), record_period(mrp), last_time(0), |
delay_ana(false), throughput_ana(false), delay_histo_ana(false), |
histo_data(NULL) {} |
|
~sim_ana(); |
|
/* currently 16 table entries is enough and good for memory efficiency */ |
hash_table<sim_record<2>,16> ANA; |
|
bool start(long, double); /* start to record a new record */ |
bool record(long, double); /* record a time stamp */ |
bool stop(long, double, unsigned int); /* stop an old record */ |
|
bool set_ana_parameters(double, double); /* set analysis time parameters */ |
bool analyze_delay(string); /* enable delay analysis */ |
bool analyze_throughput(string); /* enable throughput analysis */ |
bool analyze_delay_histo(string, double, double, unsigned int); /* enable delay histo analysis */ |
|
private: |
double warm_time; |
double record_period; |
double last_time; |
|
bool delay_ana; /* whether analyze frame delay */ |
bool throughput_ana; /* whether analyze throughput */ |
bool delay_histo_ana; /* whether analyze frame delay histo */ |
unsigned int delay_histo_binnum; /* bin number of the histo graph */ |
double delay_histo_start; /* histo begin level */ |
double delay_histo_end; /* histo end level */ |
double delay_histo_gap; /* gap bewteen two levels (gap = (start-end)/(binnum-2)) */ |
unsigned long * histo_data; |
|
string delay_file; /* the name for delay analyses result file */ |
string throughput_file; /* the name for throughput analyses result file */ |
string delay_histo_file; /* the name for histograph analyses file */ |
|
accu_record fm_dly; /* records of frame delay */ |
accu_record pth_dly; /* records of path delay */ |
accu_record th_value; /* records of throughput */ |
}; |
|
#endif |