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
/
- from Rev 36 to Rev 37
- ↔ Reverse comparison
Rev 36 → Rev 37
/async_sdm_noc/trunk/sdm/define.h
0,0 → 1,51
/* |
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 define file for the SystemC test modules |
|
History: |
28/05/2011 Clean up for opensource. <wsong83@gmail.com> |
|
*/ |
|
#ifndef NOC_DEF_H_ |
#define NOC_DEF_H_ |
|
#define SC_INCLUDE_DYNAMIC_PROCESSES |
#include "sim_ana.h" |
#include "pdu_def.h" |
|
// channel bandwidth |
const unsigned int ChBW = 1; // the data width of a single virtual circuit in unit of bytes |
const unsigned int SubChN = 1; // the number of virtual circuits or VCs per direction |
const unsigned int FSIZE_MAX = 512; // the longest frame has 512 bytes of data |
|
const unsigned int DIMX = 4; // the X size of the mesh network |
const unsigned int DIMY = 4; // the Y size of the mesh network |
const unsigned int FLEN = 64; // the payload size of a frame in unit of bytes |
|
const unsigned int BufDepth = 1; // the depth of the input buffer (only useful in VC routers to determine the inital tokens in output ports) |
|
const double FFreq = 0.1; // Node injection rate, in unit of MFlit/second, 0 means the maximal inject rate |
|
const double Record_Period = 1e3 * 1e3; // the interval of recording the average performance to log files, in unit of ps |
const double Warm_UP = 0e4 * 1e3; // the warm up time of performance analysis, in unit of ps |
const double SIM_TIME = 1e3 * 1e3; // the overall simulation time of the netowrk, in unit of ns |
|
extern sim_ana * ANA; // declaration of the global simulation analysis module |
|
typedef pdu_flit<ChBW> FLIT; // define the template of flit |
typedef pdu_frame<ChBW> FRAME; // define the template of frame |
|
// Channel Slicing will alter the port format |
// #define ENABLE_CHANNEL_CLISING |
|
#endif |
/async_sdm_noc/trunk/sdm/tb/netnode.v
0,0 → 1,70
/* |
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 module of network node including the processing element and the network interface. |
Currently the transmission FIFO is 500 frame deep. |
|
History: |
27/02/2011 Initial version. <wsong83@gmail.com> |
30/05/2011 Clean up for opensource. <wsong83@gmail.com> |
|
*/ |
|
`include "define.v" |
|
module NetNode ( |
dia, do4, doa, di4, |
do0, do1, do2, do3, |
di0, di1, di2, di3, |
rst_n) |
// |
// 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. |
// |
parameter DW = 32; |
parameter VCN = 1; |
parameter x = 2; |
parameter y = 2; |
parameter SCN = DW/2; |
|
`ifdef ENABLE_CHANNEL_SLICING |
input [VCN*SCN-1:0] dia; |
input [VCN*SCN-1:0] do4; |
output [VCN*SCN-1:0] doa; |
output [VCN*SCN-1:0] di4; |
`else |
input [VCN-1:0] dia; |
input [VCN-1:0] do4; |
output [VCN-1:0] doa; |
output [VCN-1:0] di4; |
`endif // !`ifdef ENABLE_CHANNEL_SLICING |
|
input [VCN*SCN-1:0] do0; |
input [VCN*SCN-1:0] do1; |
input [VCN*SCN-1:0] do2; |
input [VCN*SCN-1:0] do3; |
|
output [VCN*SCN-1:0] di0; |
output [VCN*SCN-1:0] di1; |
output [VCN*SCN-1:0] di2; |
output [VCN*SCN-1:0] di3; |
|
input rst_n; |
|
|
endmodule // NetNode |
|
|
/async_sdm_noc/trunk/sdm/tb/netnode.h
0,0 → 1,236
/* |
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 module of network node including the processing element and the network interface. |
Currently the transmission FIFO is 500 frame deep. |
|
History: |
26/02/2011 Initial version. <wsong83@gmail.com> |
30/05/2011 Clean up for opensource. <wsong83@gmail.com> |
|
*/ |
|
#ifndef NETNODE_H_ |
#define NETNODE_H_ |
|
#include "define.h" |
#include <systemc.h> |
#include "ni.h" |
#include "procelem.h" |
#include "rtdriver.h" |
|
class NetNode : public sc_module { |
public: |
RTDriver * LIOD [SubChN]; /* driving and convert I/O to/from router local port */ |
Network_Adapter * NI; /* network interface */ |
ProcElem * PE; /* processor element */ |
|
#ifdef ENABLE_CHANNEL_CLISING |
sc_signal<sc_lv<ChBW*4> > rtia [SubChN]; /* input ack to router */ |
sc_signal<sc_lv<ChBW*4> > rtod4 [SubChN]; /* output eof to router */ |
sc_signal<sc_lv<ChBW*4> > rtoa [SubChN]; /* output ack from router */ |
sc_signal<sc_lv<ChBW*4> > rtid4 [SubChN]; /* input data from router */ |
sc_in<sc_lv<SubChN*ChBW*4> > dia; /* input ack, undivided */ |
sc_in<sc_lv<SubChN*ChBW*4> > do4; /* output eof, undivided */ |
sc_out<sc_lv<SubChN*ChBW*4> > doa; /* output ack, undivided */ |
sc_out<sc_lv<SubChN*ChBW*4> > di4; /* input eof, undivided */ |
#else |
sc_signal<sc_logic > rtia [SubChN]; /* input ack to router */ |
sc_signal<sc_logic > rtod4 [SubChN]; /* output data to router */ |
sc_signal<sc_logic > rtoa [SubChN]; /* output ack from router */ |
sc_signal<sc_logic > rtid4 [SubChN]; /* input eof from router */ |
sc_in<sc_lv<SubChN> > dia; /* input ack, undivided */ |
sc_in<sc_lv<SubChN> > do4; /* output eof, undivided */ |
sc_out<sc_lv<SubChN> > doa; /* output ack, undivided */ |
sc_out<sc_lv<SubChN> > di4; /* input eof, undivided */ |
#endif |
|
sc_signal<sc_lv<ChBW*4 > > rtod [SubChN][4]; /* output data to router */ |
sc_signal<sc_lv<ChBW*4 > > rtid [SubChN][4]; /* input data from router */ |
sc_in<sc_lv<SubChN*ChBW*4 > > do0; /* output d0, undivided */ |
sc_in<sc_lv<SubChN*ChBW*4 > > do1; |
sc_in<sc_lv<SubChN*ChBW*4 > > do2; |
sc_in<sc_lv<SubChN*ChBW*4 > > do3; |
sc_out<sc_lv<SubChN*ChBW*4 > > di0; /* input data, undivided */ |
sc_out<sc_lv<SubChN*ChBW*4 > > di1; |
sc_out<sc_lv<SubChN*ChBW*4 > > di2; |
sc_out<sc_lv<SubChN*ChBW*4 > > di3; |
sc_in<sc_logic > rst_n; /* global reste, from the verilog top level */ |
|
// signals between IOD and NI |
sc_fifo<pdu_flit<ChBW> > * NI2P [SubChN]; /* flit fifo, from NI to IO driver */ |
sc_fifo<pdu_flit<ChBW> > * P2NI [SubChN]; /* flit fifo, from IO driver to NI */ |
|
// signals between NI and FG/FS |
sc_fifo<pdu_frame<ChBW> > * FIQ; /* the frame fifo, from PE to NI */ |
sc_fifo<pdu_frame<ChBW> > * FOQ; /* the frame fifo, from NI to PE */ |
sc_signal<bool> brst_n; /* the reset in the SystemC modules */ |
|
int x, y; /* private local address */ |
|
SC_CTOR(NetNode) |
: dia("dia"), do4("do4"), doa("doa"), di4("di4"), |
do0("do0"), do1("do1"), do2("do2"), do3("do3"), |
di0("di0"), di1("di1"), di2("di2"), di3("di3"), |
rst_n("rst_n") |
{ |
// dynamically get the parameters from Verilog test bench |
ncsc_get_param("x", x); |
ncsc_get_param("y", y); |
|
// initialization |
NI = new Network_Adapter("NI", x, y); |
PE = new ProcElem("PE", x, y); |
FIQ = new sc_fifo<pdu_frame<ChBW> >(500); /* currently the fifo from PE is 500 frame deep */ |
FOQ = new sc_fifo<pdu_frame<ChBW> >(1); |
for(unsigned int j=0; j<SubChN; j++) { |
LIOD[j] = new RTDriver("LIOD"); |
NI2P[j] = new sc_fifo<pdu_flit<ChBW> >(1); |
P2NI[j] = new sc_fifo<pdu_flit<ChBW> >(1); |
} |
|
// connections |
for(unsigned int j=0; j<SubChN; j++) { |
LIOD[j]->NI2P(*NI2P[j]); |
LIOD[j]->P2NI(*P2NI[j]); |
for(unsigned int k=0; k<4; k++) { |
LIOD[j]->rtid[k](rtid[j][k]); |
LIOD[j]->rtod[k](rtod[j][k]); |
} |
LIOD[j]->rtia(rtia[j]); |
LIOD[j]->rtid4(rtid4[j]); |
LIOD[j]->rtoa(rtoa[j]); |
LIOD[j]->rtod4(rtod4[j]); |
} |
|
NI->frame_in(*FIQ); |
NI->frame_out(*FOQ); |
for(unsigned int j=0; j<SubChN; j++) { |
NI->IP[j](*P2NI[j]); |
NI->OP[j](*NI2P[j]); |
} |
|
PE->rst_n(brst_n); |
PE->Fout(*FIQ); |
PE->Fin(*FOQ); |
|
brst_n.write(false); |
|
SC_METHOD(rst_proc); |
sensitive << rst_n; |
|
sc_spawn_options opt_inp; |
opt_inp.spawn_method(); |
for(unsigned int j=0; j<SubChN; j++) { |
opt_inp.set_sensitivity(&rtid[j][0]); |
opt_inp.set_sensitivity(&rtid[j][1]); |
opt_inp.set_sensitivity(&rtid[j][2]); |
opt_inp.set_sensitivity(&rtid[j][3]); |
opt_inp.set_sensitivity(&rtid4[j]); |
} |
opt_inp.set_sensitivity(&dia); |
sc_spawn(sc_bind(&NetNode::VC_inp, this), NULL, &opt_inp); |
|
|
sc_spawn_options opt_outp; |
opt_outp.spawn_method(); |
for(unsigned int j=0; j<SubChN; j++) { |
opt_outp.set_sensitivity(&rtoa[j]); |
} |
opt_outp.set_sensitivity(&do0); |
opt_outp.set_sensitivity(&do1); |
opt_outp.set_sensitivity(&do2); |
opt_outp.set_sensitivity(&do3); |
opt_outp.set_sensitivity(&do4); |
sc_spawn(sc_bind(&NetNode::VC_outp, this), NULL, &opt_outp); |
} |
|
|
// thread to divide the input buses according to virtual circuits |
void VC_inp() { |
|
sc_lv<SubChN*ChBW*4> md[4]; |
#ifdef ENABLE_CHANNEL_CLISING |
sc_lv<SubChN*ChBW*4> md4; |
sc_lv<SubChN*ChBW*4> mda; |
#else |
sc_lv<SubChN> md4; |
sc_lv<SubChN> mda; |
#endif |
|
mda = dia.read(); |
|
for(unsigned int i=0; i<SubChN; i++) { |
#ifdef ENABLE_CHANNEL_CLISING |
rtia[i].write(mda(ChBW*4*(i+1)-1, ChBW*4*i)); |
md4(ChBW*4*(i+1)-1, ChBW*4*i) = rtid4[i].read(); |
#else |
rtia[i].write(mda[i]); |
md4[i] = rtid4[i].read(); |
#endif |
md[0](ChBW*4*(i+1)-1, ChBW*4*i) = rtid[i][0].read(); |
md[1](ChBW*4*(i+1)-1, ChBW*4*i) = rtid[i][1].read(); |
md[2](ChBW*4*(i+1)-1, ChBW*4*i) = rtid[i][2].read(); |
md[3](ChBW*4*(i+1)-1, ChBW*4*i) = rtid[i][3].read(); |
} |
|
di0.write(md[0]); |
di1.write(md[1]); |
di2.write(md[2]); |
di3.write(md[3]); |
di4.write(md4); |
} |
|
// thread to combine the buses according to virtual circuits |
void VC_outp() { |
sc_lv<SubChN*ChBW*4> md[4]; |
#ifdef ENABLE_CHANNEL_CLISING |
sc_lv<SubChN*ChBW*4> md4; |
sc_lv<SubChN*ChBW*4> mda; |
#else |
sc_lv<SubChN> md4; |
sc_lv<SubChN> mda; |
#endif |
|
md[0] = do0.read(); |
md[1] = do1.read(); |
md[2] = do2.read(); |
md[3] = do3.read(); |
md4 = do4.read(); |
|
|
for(unsigned int i=0; i<SubChN; i++) { |
#ifdef ENABLE_CHANNEL_CLISING |
mda(ChBW*4*(i+1)-1, ChBW*4*i) = rtoa[i].read(); |
rtod4[i].write(md4(ChBW*4*(i+1)-1, ChBW*4*i)); |
#else |
mda[i] = rtoa[i].read(); |
rtod4[i].write(md4[i]); |
#endif |
rtod[i][0].write(md[0](ChBW*4*(i+1)-1, ChBW*4*i)); |
rtod[i][1].write(md[1](ChBW*4*(i+1)-1, ChBW*4*i)); |
rtod[i][2].write(md[2](ChBW*4*(i+1)-1, ChBW*4*i)); |
rtod[i][3].write(md[3](ChBW*4*(i+1)-1, ChBW*4*i)); |
} |
|
doa.write(mda); |
} |
|
// generate the reset for SystemC modules |
void rst_proc() { |
bool mrst_n; |
mrst_n = rst_n.read().is_01() ? rst_n.read().to_bool() : false; |
brst_n.write(mrst_n); |
} |
}; |
|
|
#endif |
/async_sdm_noc/trunk/sdm/tb/rtdriver.cpp
0,0 → 1,289
/* |
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 port driver between NI and router. |
|
History: |
27/04/2010 Initial version. <wsong83@gmail.com> |
16/10/2010 Support SDM. <wsong83@gmail.com> |
31/05/2011 Remove the sc_unit datatype to support data width larger than 64. <wsong83@gmail.com> |
|
*/ |
|
#include "rtdriver.h" |
|
RTDriver::RTDriver(sc_module_name mname) |
: sc_module(mname), |
NI2P("NI2P"), |
P2NI("P2NI") |
{ |
SC_METHOD(IPdetect); |
sensitive << rtia; |
|
SC_METHOD(OPdetect); |
sensitive << rtod[0] << rtod[1] << rtod[2] << rtod[3] << rtod4; |
|
SC_THREAD(send); |
SC_THREAD(recv); |
|
rtinp_sig = false; |
rtoutp_sig = false; |
} |
|
void RTDriver::IPdetect() { |
sc_logic ack_lv_high, ack_lv_low; // the sc_logic ack |
|
// read the ack |
#ifdef ENABLE_CHANNEL_CLISING |
ack_lv_high = rtia.read().and_reduce(); |
ack_lv_low = rtia.read().or_reduce(); |
#else |
ack_lv_high = rtia.read(); |
ack_lv_low = rtia.read(); |
#endif |
|
if(ack_lv_high.is_01() && ack_lv_high.to_bool()) |
rtinp_sig = true; |
|
if(ack_lv_low.is_01() && (!ack_lv_low.to_bool())) |
rtinp_sig = false; |
} |
|
void RTDriver::OPdetect() { |
sc_lv<ChBW*4> data_lv; // the ORed data |
sc_logic data_lv_high, data_lv_low; |
|
#ifdef ENABLE_CHANNEL_CLISING |
data_lv = rtod[0].read() | rtod[1].read() | rtod[2].read() | rtod[3].read() | rtod4.read(); |
data_lv_high = data_lv.and_reduce(); |
data_lv_low = data_lv.or_reduce(); |
#else |
data_lv = rtod[0].read() | rtod[1].read() | rtod[2].read() | rtod[3].read(); |
data_lv_high = data_lv.and_reduce() | rtod4.read(); |
data_lv_low = data_lv.or_reduce() | rtod4.read(); |
#endif |
|
if(data_lv_high.is_01() && data_lv_high.to_bool()) |
rtoutp_sig = true; |
|
if(data_lv_high.is_01() && (!data_lv_low.to_bool())) |
rtoutp_sig = false; |
} |
|
void RTDriver::send() { |
FLIT mflit; // the local flit buffer |
unsigned int i, j; // local loop index |
sc_lv<ChBW*4> mdata[4]; // local data copy |
#ifdef ENABLE_CHANNEL_CLISING |
sc_lv<ChBW*4> mdata4; // local copy of eof |
#else |
sc_logic mdata4; // local copy of eof |
#endif |
|
// initialize the output ports |
mdata[0] = 0; |
mdata[1] = 0; |
mdata[2] = 0; |
mdata[3] = 0; |
#ifdef ENABLE_CHANNEL_CLISING |
mdata4 = 0; |
#else |
mdata4 = false; |
#endif |
|
rtid[0].write(mdata[0]); |
rtid[1].write(mdata[1]); |
rtid[2].write(mdata[2]); |
rtid[3].write(mdata[3]); |
rtid4.write(mdata4); |
|
while(true) { |
mflit = NI2P->read(); // read in the flit |
|
// write the flit |
if(mflit.ftype == F_HD) { |
// the target address |
mdata[mflit.addrx&0x3][0] = SC_LOGIC_1; |
mdata[(mflit.addrx&0xc)>>2][1] = SC_LOGIC_1; |
mdata[mflit.addry&0x3][2] = SC_LOGIC_1; |
mdata[(mflit.addry&0xc)>>2][3] = SC_LOGIC_1; |
|
for(i=0,j=4; i<(ChBW-1)*4; i++, j++) { |
switch((mflit[i/4] >> ((i%4)*2)) & 0x3) { |
case 0: mdata[0][j] = SC_LOGIC_1; break; |
case 1: mdata[1][j] = SC_LOGIC_1; break; |
case 2: mdata[2][j] = SC_LOGIC_1; break; |
case 3: mdata[3][j] = SC_LOGIC_1; break; |
} |
} |
} else { |
for(i=0; i<ChBW*4; i++) { |
switch((mflit[i/4] >> ((i%4)*2)) & 0x3) { |
case 0: mdata[0][i] = SC_LOGIC_1; break; |
case 1: mdata[1][i] = SC_LOGIC_1; break; |
case 2: mdata[2][i] = SC_LOGIC_1; break; |
case 3: mdata[3][i] = SC_LOGIC_1; break; |
} |
} |
} |
|
// write to the port |
rtid[0].write(mdata[0]); |
rtid[1].write(mdata[1]); |
rtid[2].write(mdata[2]); |
rtid[3].write(mdata[3]); |
|
// wait for the router to capture the data |
wait(rtinp_sig.posedge_event()); |
wait(0.2, SC_NS); // a delay to avoid data override |
|
// clear the data |
mdata[0] = 0; |
mdata[1] = 0; |
mdata[2] = 0; |
mdata[3] = 0; |
|
rtid[0].write(mdata[0]); |
rtid[1].write(mdata[1]); |
rtid[2].write(mdata[2]); |
rtid[3].write(mdata[3]); |
|
// wait for the input port be ready again |
wait(rtinp_sig.negedge_event()); |
wait(0.2, SC_NS); // a delay to avoid data override |
|
// check whether a tailf flit is needed |
if(mflit.ftype == F_TL) { |
// write the eof |
rtid4.write(~mdata4); |
|
// wait for the router to capture the data |
wait(rtinp_sig.posedge_event()); |
wait(0.2, SC_NS); // a delay to avoid data override |
|
// clear the eof |
rtid4.write(mdata4); |
|
// wait for the input port be ready again |
wait(rtinp_sig.negedge_event()); |
wait(0.2, SC_NS); // a delay to avoid data override |
} |
} |
} |
|
void RTDriver::recv() { |
FLIT mflit; // the local flit buffer |
sc_lv<ChBW*4> mdata[4]; // local data copy |
#ifdef ENABLE_CHANNEL_CLISING |
sc_lv<ChBW*4> mdata4; // local copy of eof |
sc_lv<ChBW*4> mack = 0; // local copy of ack |
#else |
sc_logic mdata4; // local copy of eof |
sc_logic mack = SC_LOGIC_0; // local copy of ack |
#endif |
sc_lv<4> dd; // the current 1-of-4 data under process |
unsigned int i, j; // local loop index |
|
bool is_hd = true; // the current flit is a header flit |
|
// initialize the ack signal |
rtoa.write(mack); |
|
while(true) { |
// clear the flit |
mflit.clear(); |
|
// wait for an incoming flit |
wait(rtoutp_sig.posedge_event()); |
|
// analyse the flit |
mdata[0] = rtod[0].read(); |
mdata[1] = rtod[1].read(); |
mdata[2] = rtod[2].read(); |
mdata[3] = rtod[3].read(); |
mdata4 = rtod4.read(); |
|
if(is_hd) { |
mflit.ftype = F_HD; |
is_hd = false; |
} |
#ifdef ENABLE_CHANNEL_CLISING |
else if(mdata4[0].to_bool()) { |
mflit.ftype = F_TL; |
is_hd = true; |
} |
#else |
else if(mdata4.to_bool()) { |
mflit.ftype = F_TL; |
is_hd = true; |
} |
#endif |
else { |
mflit.ftype = F_DAT; |
} |
|
if(mflit.ftype == F_HD) { |
// fetch the address |
dd[0] = mdata[0][0]; dd[1] = mdata[1][0]; dd[2] = mdata[2][0]; dd[3] = mdata[3][0]; |
mflit.addrx |= (c1o42b(dd.to_uint()) << 0); |
dd[0] = mdata[0][1]; dd[1] = mdata[1][1]; dd[2] = mdata[2][1]; dd[3] = mdata[3][1]; |
mflit.addrx |= (c1o42b(dd.to_uint()) << 2); |
dd[0] = mdata[0][2]; dd[1] = mdata[1][2]; dd[2] = mdata[2][2]; dd[3] = mdata[3][2]; |
mflit.addry |= (c1o42b(dd.to_uint()) << 0); |
dd[0] = mdata[0][3]; dd[1] = mdata[1][3]; dd[2] = mdata[2][3]; dd[3] = mdata[3][3]; |
mflit.addry |= (c1o42b(dd.to_uint()) << 2); |
|
// fill in data |
for(i=1; i<ChBW; i++) { |
for(j=0; j<4; j++) { |
dd[0] = mdata[0][i*4+j]; |
dd[1] = mdata[1][i*4+j]; |
dd[2] = mdata[2][i*4+j]; |
dd[3] = mdata[3][i*4+j]; |
mflit[i-1] |= c1o42b(dd.to_uint()) << j*2; |
} |
} |
} else if (mflit.ftype != F_TL) { |
// fill in data |
for(i=0; i<ChBW; i++) { |
for(j=0; j<4; j++) { |
dd[0] = mdata[0][i*4+j]; |
dd[1] = mdata[1][i*4+j]; |
dd[2] = mdata[2][i*4+j]; |
dd[3] = mdata[3][i*4+j]; |
mflit[i] |= c1o42b(dd.to_uint()) << j*2; |
} |
} |
} |
|
// send the flit to the NI |
P2NI->write(mflit); |
|
wait(0.2, SC_NS); // a delay to avoid data override |
rtoa.write(~mack); // notify that data is captured |
|
// wait for the data withdrawal |
wait(rtoutp_sig.negedge_event()); |
wait(0.2, SC_NS); // a delay to avoid data override |
rtoa.write(mack); // notify that data is captured |
|
} |
} |
|
unsigned int RTDriver::c1o42b(unsigned int dd) { |
switch(dd) { |
case 1: return 0; |
case 2: return 1; |
case 4: return 2; |
case 8: return 3; |
default: return 0xff; |
} |
} |
/async_sdm_noc/trunk/sdm/tb/noc_top.v
0,0 → 1,136
/* |
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 mesh network for simulation. |
|
History: |
03/03/2011 Initial version. <wsong83@gmail.com> |
30/05/2011 Clean up for opensource. <wsong83@gmail.com> |
|
*/ |
|
// the router structure definitions |
`include "define.v" |
|
module noc_top(/*AUTOARG*/ |
// Inputs |
rst_n |
); |
input rst_n; |
|
|
parameter DW = 32; |
parameter VCN = 1; |
parameter DIMX = 8; |
parameter DIMY = 8; |
parameter SCN = DW/2; |
|
wire [DIMX-1:0][DIMY-1:0][3:0][VCN*SCN-1:0] di0, di1, di2, di3; |
wire [DIMX-1:0][DIMY-1:0][3:0][VCN*SCN-1:0] do0, do1, do2, do3; |
`ifdef ENABLE_CHANNEL_SLICING |
wire [DIMX-1:0][DIMY-1:0][3:0][VCN*SCN-1:0] di4, dia; |
wire [DIMX-1:0][DIMY-1:0][3:0][VCN*SCN-1:0] do4, doa; |
`else |
wire [DIMX-1:0][DIMY-1:0][3:0][VCN-1:0] di4, dia; |
wire [DIMX-1:0][DIMY-1:0][3:0][VCN-1:0] do4, doa; |
`endif |
|
genvar x, y; |
|
generate for(x=0; x<DIMX; x++) begin: DX |
for(y=0; y<DIMY; y++) begin: DY |
|
node_top #(.DW(DW), .VCN(VCN), .x(x), .y(y)) |
NN ( |
.si0 (di0[x][y][0]), .si1 (di1[x][y][0]), .si2 (di2[x][y][0]), .si3 (di3[x][y][0]), .si4 (di4[x][y][0]), .sia (dia[x][y][0]), |
.wi0 (di0[x][y][1]), .wi1 (di1[x][y][1]), .wi2 (di2[x][y][1]), .wi3 (di3[x][y][1]), .wi4 (di4[x][y][1]), .wia (dia[x][y][1]), |
.ni0 (di0[x][y][2]), .ni1 (di1[x][y][2]), .ni2 (di2[x][y][2]), .ni3 (di3[x][y][2]), .ni4 (di4[x][y][2]), .nia (dia[x][y][2]), |
.ei0 (di0[x][y][3]), .ei1 (di1[x][y][3]), .ei2 (di2[x][y][3]), .ei3 (di3[x][y][3]), .ei4 (di4[x][y][3]), .eia (dia[x][y][3]), |
.so0 (do0[x][y][0]), .so1 (do1[x][y][0]), .so2 (do2[x][y][0]), .so3 (do3[x][y][0]), .so4 (do4[x][y][0]), .soa (doa[x][y][0]), |
.wo0 (do0[x][y][1]), .wo1 (do1[x][y][1]), .wo2 (do2[x][y][1]), .wo3 (do3[x][y][1]), .wo4 (do4[x][y][1]), .woa (doa[x][y][1]), |
.no0 (do0[x][y][2]), .no1 (do1[x][y][2]), .no2 (do2[x][y][2]), .no3 (do3[x][y][2]), .no4 (do4[x][y][2]), .noa (doa[x][y][2]), |
.eo0 (do0[x][y][3]), .eo1 (do1[x][y][3]), .eo2 (do2[x][y][3]), .eo3 (do3[x][y][3]), .eo4 (do4[x][y][3]), .eoa (doa[x][y][3]), |
.rst_n(rst_n) |
); |
|
// north link |
if(x==0) begin |
assign di0[x][y][2] = do0[x][y][2]; |
assign di1[x][y][2] = do1[x][y][2]; |
assign di2[x][y][2] = do2[x][y][2]; |
assign di3[x][y][2] = do3[x][y][2]; |
assign di4[x][y][2] = do4[x][y][2]; |
assign doa[x][y][2] = dia[x][y][2]; |
end else begin |
assign di0[x][y][2] = do0[x-1][y][0]; |
assign di1[x][y][2] = do1[x-1][y][0]; |
assign di2[x][y][2] = do2[x-1][y][0]; |
assign di3[x][y][2] = do3[x-1][y][0]; |
assign di4[x][y][2] = do4[x-1][y][0]; |
assign doa[x-1][y][0] = dia[x][y][2]; |
end |
|
// south link |
if(x==DIMX-1) begin |
assign di0[x][y][0] = do0[x][y][0]; |
assign di1[x][y][0] = do1[x][y][0]; |
assign di2[x][y][0] = do2[x][y][0]; |
assign di3[x][y][0] = do3[x][y][0]; |
assign di4[x][y][0] = do4[x][y][0]; |
assign doa[x][y][0] = dia[x][y][0]; |
end else begin |
assign di0[x][y][0] = do0[x+1][y][2]; |
assign di1[x][y][0] = do1[x+1][y][2]; |
assign di2[x][y][0] = do2[x+1][y][2]; |
assign di3[x][y][0] = do3[x+1][y][2]; |
assign di4[x][y][0] = do4[x+1][y][2]; |
assign doa[x+1][y][2] = dia[x][y][0]; |
end |
|
// west link |
if(y==0) begin |
assign di0[x][y][1] = do0[x][y][1]; |
assign di1[x][y][1] = do1[x][y][1]; |
assign di2[x][y][1] = do2[x][y][1]; |
assign di3[x][y][1] = do3[x][y][1]; |
assign di4[x][y][1] = do4[x][y][1]; |
assign doa[x][y][1] = dia[x][y][1]; |
end else begin |
assign di0[x][y][1] = do0[x][y-1][3]; |
assign di1[x][y][1] = do1[x][y-1][3]; |
assign di2[x][y][1] = do2[x][y-1][3]; |
assign di3[x][y][1] = do3[x][y-1][3]; |
assign di4[x][y][1] = do4[x][y-1][3]; |
assign doa[x][y-1][3] = dia[x][y][1]; |
end // else: !if(y==0) |
|
// east link |
if(y==DIMY-1) begin |
assign di0[x][y][3] = do0[x][y][3]; |
assign di1[x][y][3] = do1[x][y][3]; |
assign di2[x][y][3] = do2[x][y][3]; |
assign di3[x][y][3] = do3[x][y][3]; |
assign di4[x][y][3] = do4[x][y][3]; |
assign doa[x][y][3] = dia[x][y][3]; |
end else begin |
assign di0[x][y][3] = do0[x][y+1][1]; |
assign di1[x][y][3] = do1[x][y+1][1]; |
assign di2[x][y][3] = do2[x][y+1][1]; |
assign di3[x][y][3] = do3[x][y+1][1]; |
assign di4[x][y][3] = do4[x][y+1][1]; |
assign doa[x][y+1][1] = dia[x][y][3]; |
end // else: !if(y==DIMY-1) |
|
end // block: DY |
end // block: DX |
endgenerate |
|
endmodule // noc_top |
/async_sdm_noc/trunk/sdm/tb/ni.cpp
0,0 → 1,94
/* |
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 SystemC network adapter/interface for NoC simulation. |
|
History: |
23/12/2008 Initial version. <wsong83@gmail.com> |
30/09/2010 Use template style packet definition. <wsong83@gmail.com> |
16/10/2010 Support SDM. <wsong83@gmail.com> |
29/05/2011 CLean up for opensource. <wsong83@gmail.com> |
|
*/ |
|
#include "ni.h" |
|
Network_Adapter::Network_Adapter( |
sc_module_name name // module name |
,unsigned int x // location x |
,unsigned int y // location y |
): |
sc_module(name), |
frame_in("FrmIn"), |
frame_out("FrmOut"), |
loc_x(x), |
loc_y(y) |
{ |
sc_spawn_options opt; |
|
for(unsigned int i=0; i<SubChN; i++) { |
sc_spawn(sc_bind(&Network_Adapter::ibuffer_thread, this, i), NULL, &opt); |
sc_spawn(sc_bind(&Network_Adapter::obuffer_thread, this, i), NULL, &opt); |
} |
} |
|
Network_Adapter::~Network_Adapter() |
{ |
} |
|
// read in the incoming frame |
void Network_Adapter::ibuffer_thread(unsigned int ii){ |
FRAME mframe; |
FLIT mflit; |
|
while(1){ |
mframe.clear(); |
|
while(1) { |
mflit = IP[ii]->read(); |
mframe << mflit; |
|
if(mflit.ftype == F_TL) break; |
} |
|
frame_out->write(mframe); |
} |
} |
|
// send out a frame |
void Network_Adapter::obuffer_thread(unsigned int ii){ |
|
FRAME mframe; |
FLIT mflit; |
|
while(1){ |
mframe = frame_in->read(); |
|
while(1) { |
mframe >> mflit; |
mflit.vcn = ii; |
|
OP[ii]->write(mflit); |
|
if(mflit.ftype == F_TL) break; |
} |
} |
} |
|
bool Network_Adapter::check_frame(const FRAME& frame) |
{ |
// TODO: check the integerity, dummy right noe |
return true; |
} |
|
|
|
|
/async_sdm_noc/trunk/sdm/tb/rtdriver.h
0,0 → 1,66
/* |
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 port driver between NI and router. |
|
History: |
27/04/2010 Initial version. <wsong83@gmail.com> |
16/10/2010 Support SDM. <wsong83@gmail.com> |
30/05/2011 Remove the sc_unit datatype to support data width larger than 64. <wsong83@gmail.com> |
|
*/ |
|
#ifndef RT_DRIVER_H_ |
#define RT_DRIVER_H_ |
|
#include "define.h" |
#include <systemc.h> |
#include "pdu_def.h" |
|
SC_MODULE(RTDriver) { |
|
public: |
// port with network interface |
sc_port<sc_fifo_in_if<FLIT> > NI2P; |
sc_port<sc_fifo_out_if<FLIT> > P2NI; |
|
// signals from interface to router |
sc_out<sc_lv<ChBW*4> > rtid [4]; |
sc_in<sc_lv<ChBW*4> > rtod [4]; |
|
#ifdef ENABLE_CHANNEL_CLISING |
sc_out<sc_lv<ChBW*4> > rtid4; |
sc_in<sc_lv<ChBW*4> > rtod4; |
sc_in<sc_lv<ChBW*4> > rtia; |
sc_out<sc_lv<ChBW*4> > rtoa; |
#else |
sc_out<sc_logic > rtid4; |
sc_in<sc_logic > rtod4; |
sc_in<sc_logic> rtia; |
sc_out<sc_logic> rtoa; |
#endif |
|
SC_HAS_PROCESS(RTDriver); |
RTDriver(sc_module_name name); |
|
void IPdetect(); // Method to detect the router input port |
void OPdetect(); // Method to detect the router output port |
void send(); // thread of sending a flit |
void recv(); // thread to recveive a flit |
|
sc_signal<bool> rtinp_sig; // fire when the router input port is ready for a new flit |
sc_signal<bool> rtoutp_sig; // fire when the router output port has a new flit |
|
unsigned int c1o42b(unsigned int); // convert 1-of-4 to binary |
}; |
|
|
#endif |
/async_sdm_noc/trunk/sdm/tb/noctb.v
0,0 → 1,48
/* |
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 |
|
Test bench. |
|
History: |
03/03/2011 Initial version. <wsong83@gmail.com> |
30/05/2011 Clean up for opensource. <wsong83@gmail.com> |
|
*/ |
|
`timescale 1ns/1ps |
|
module noctb; |
parameter DW = 8; // the data width of a single virtual circuit |
parameter VCN = 1; // the number of virtual circuits per direction |
parameter DIMX = 4; // the X dimension |
parameter DIMY = 4; // the Y dimension |
|
reg rst_n; |
|
noc_top #(.DW(DW), .VCN(VCN), .DIMX(DIMX), .DIMY(DIMY)) |
NoC (.rst_n(rst_n)); // the mesh network |
|
AnaProc ANAM(); // the global performance analyser |
|
initial begin |
rst_n = 0; |
|
# 133; |
|
rst_n = 1; |
|
end |
|
endmodule // noctb |
|
|
|
|
/async_sdm_noc/trunk/sdm/tb/rtwrapper.v
0,0 → 1,222
/* |
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 wrapper for the synthesized router. |
|
History: |
28/05/2009 Initial version. <wsong83@gmail.com> |
30/05/2011 Clean up for opensource. <wsong83@gmail.com> |
|
*/ |
|
// the router structure definitions |
`include "define.v" |
|
module router_hdl(/*AUTOARG*/ |
// Outputs |
so0, so1, so2, so3, wo0, wo1, wo2, wo3, no0, no1, no2, no3, eo0, |
eo1, eo2, eo3, lo0, lo1, lo2, lo3, so4, wo4, no4, eo4, lo4, sia, |
wia, nia, eia, lia, |
// Inputs |
si0, si1, si2, si3, wi0, wi1, wi2, wi3, ni0, ni1, ni2, ni3, ei0, |
ei1, ei2, ei3, li0, li1, li2, li3, si4, wi4, ni4, ei4, li4, soa, |
woa, noa, eoa, loa, addrx, addry, rst_n |
); |
|
parameter VCN = 1; // number of virtual circuits in each direction. When VCN == 1, it is a wormhole router |
parameter DW = 32; // the datawidth of a single virtual circuit, the total data width of the router is DW*VCN |
parameter SCN = DW/2; // the number of 1-of-4 sub-channel in each virtual circuit |
|
input [VCN*SCN-1:0] si0, si1, si2, si3; |
input [VCN*SCN-1:0] wi0, wi1, wi2, wi3; |
input [VCN*SCN-1:0] ni0, ni1, ni2, ni3; |
input [VCN*SCN-1:0] ei0, ei1, ei2, ei3; |
input [VCN*SCN-1:0] li0, li1, li2, li3; |
output [VCN*SCN-1:0] so0, so1, so2, so3; |
output [VCN*SCN-1:0] wo0, wo1, wo2, wo3; |
output [VCN*SCN-1:0] no0, no1, no2, no3; |
output [VCN*SCN-1:0] eo0, eo1, eo2, eo3; |
output [VCN*SCN-1:0] lo0, lo1, lo2, lo3; |
// eof bits and ack lines |
`ifdef ENABLE_CHANNEL_SLICING |
input [VCN*SCN-1:0] si4, wi4, ni4, ei4, li4; |
output [VCN*SCN-1:0] so4, wo4, no4, eo4, lo4; |
output [VCN*SCN-1:0] sia, wia, nia, eia, lia; |
input [VCN*SCN-1:0] soa, woa, noa, eoa, loa; |
`else |
input [VCN-1:0] si4, wi4, ni4, ei4, li4; |
output [VCN-1:0] so4, wo4, no4, eo4, lo4; |
output [VCN-1:0] sia, wia, nia, eia, lia; |
input [VCN-1:0] soa, woa, noa, eoa, loa; |
`endif // !`ifdef ENABLE_CHANNEL_SLICING |
|
input [7:0] addrx, addry; |
input rst_n; |
|
wire [VCN*SCN-1:0] psi0, psi1, psi2, psi3; |
wire [VCN*SCN-1:0] pwi0, pwi1, pwi2, pwi3; |
wire [VCN*SCN-1:0] pni0, pni1, pni2, pni3; |
wire [VCN*SCN-1:0] pei0, pei1, pei2, pei3; |
wire [VCN*SCN-1:0] pli0, pli1, pli2, pli3; |
wire [VCN*SCN-1:0] pso0, pso1, pso2, pso3; |
wire [VCN*SCN-1:0] pwo0, pwo1, pwo2, pwo3; |
wire [VCN*SCN-1:0] pno0, pno1, pno2, pno3; |
wire [VCN*SCN-1:0] peo0, peo1, peo2, peo3; |
wire [VCN*SCN-1:0] plo0, plo1, plo2, plo3; |
// eof bits and ack lines |
`ifdef ENABLE_CHANNEL_SLICING |
wire [VCN*SCN-1:0] psi4, pwi4, pni4, pei4, pli4; |
wire [VCN*SCN-1:0] pso4, pwo4, pno4, peo4, plo4; |
wire [VCN*SCN-1:0] psia, pwia, pnia, peia, plia; |
wire [VCN*SCN-1:0] psoa, pwoa, pnoa, peoa, ploa; |
`else |
wire [VCN-1:0] psi4, pwi4, pni4, pei4, pli4; |
wire [VCN-1:0] pso4, pwo4, pno4, peo4, plo4; |
wire [VCN-1:0] psia, pwia, pnia, peia, plia; |
wire [VCN-1:0] psoa, pwoa, pnoa, peoa, ploa; |
`endif // !`ifdef ENABLE_CHANNEL_SLICING |
|
wire [7:0] paddrx, paddry; |
wire prst_n; |
|
router RT ( |
.sia ( psia ), |
.wia ( pwia ), |
.nia ( pnia ), |
.eia ( peia ), |
.lia ( plia ), |
.so0 ( pso0 ), |
.so1 ( pso1 ), |
.so2 ( pso2 ), |
.so3 ( pso3 ), |
.wo0 ( pwo0 ), |
.wo1 ( pwo1 ), |
.wo2 ( pwo2 ), |
.wo3 ( pwo3 ), |
.no0 ( pno0 ), |
.no1 ( pno1 ), |
.no2 ( pno2 ), |
.no3 ( pno3 ), |
.eo0 ( peo0 ), |
.eo1 ( peo1 ), |
.eo2 ( peo2 ), |
.eo3 ( peo3 ), |
.lo0 ( plo0 ), |
.lo1 ( plo1 ), |
.lo2 ( plo2 ), |
.lo3 ( plo3 ), |
.so4 ( pso4 ), |
.wo4 ( pwo4 ), |
.no4 ( pno4 ), |
.eo4 ( peo4 ), |
.lo4 ( plo4 ), |
.si0 ( psi0 ), |
.si1 ( psi1 ), |
.si2 ( psi2 ), |
.si3 ( psi3 ), |
.wi0 ( pwi0 ), |
.wi1 ( pwi1 ), |
.wi2 ( pwi2 ), |
.wi3 ( pwi3 ), |
.ni0 ( pni0 ), |
.ni1 ( pni1 ), |
.ni2 ( pni2 ), |
.ni3 ( pni3 ), |
.ei0 ( pei0 ), |
.ei1 ( pei1 ), |
.ei2 ( pei2 ), |
.ei3 ( pei3 ), |
.li0 ( pli0 ), |
.li1 ( pli1 ), |
.li2 ( pli2 ), |
.li3 ( pli3 ), |
.si4 ( psi4 ), |
.wi4 ( pwi4 ), |
.ni4 ( pni4 ), |
.ei4 ( pei4 ), |
.li4 ( pli4 ), |
.soa ( psoa ), |
.woa ( pwoa ), |
.noa ( pnoa ), |
.eoa ( peoa ), |
.loa ( ploa ), |
.addrx ( paddrx ), |
.addry ( paddry ), |
.rst_n ( prst_n ) |
); |
|
assign sia = psia ; |
assign wia = pwia ; |
assign nia = pnia ; |
assign eia = peia ; |
assign lia = plia ; |
assign so0 = pso0 ; |
assign so1 = pso1 ; |
assign so2 = pso2 ; |
assign so3 = pso3 ; |
assign wo0 = pwo0 ; |
assign wo1 = pwo1 ; |
assign wo2 = pwo2 ; |
assign wo3 = pwo3 ; |
assign no0 = pno0 ; |
assign no1 = pno1 ; |
assign no2 = pno2 ; |
assign no3 = pno3 ; |
assign eo0 = peo0 ; |
assign eo1 = peo1 ; |
assign eo2 = peo2 ; |
assign eo3 = peo3 ; |
assign lo0 = plo0 ; |
assign lo1 = plo1 ; |
assign lo2 = plo2 ; |
assign lo3 = plo3 ; |
assign so4 = pso4 ; |
assign wo4 = pwo4 ; |
assign no4 = pno4 ; |
assign eo4 = peo4 ; |
assign lo4 = plo4 ; |
assign psi0 = si0 ; |
assign psi1 = si1 ; |
assign psi2 = si2 ; |
assign psi3 = si3 ; |
assign pwi0 = wi0 ; |
assign pwi1 = wi1 ; |
assign pwi2 = wi2 ; |
assign pwi3 = wi3 ; |
assign pni0 = ni0 ; |
assign pni1 = ni1 ; |
assign pni2 = ni2 ; |
assign pni3 = ni3 ; |
assign pei0 = ei0 ; |
assign pei1 = ei1 ; |
assign pei2 = ei2 ; |
assign pei3 = ei3 ; |
assign pli0 = li0 ; |
assign pli1 = li1 ; |
assign pli2 = li2 ; |
assign pli3 = li3 ; |
assign psi4 = si4 ; |
assign pwi4 = wi4 ; |
assign pni4 = ni4 ; |
assign pei4 = ei4 ; |
assign pli4 = li4 ; |
assign psoa = soa ; |
assign pwoa = woa ; |
assign pnoa = noa ; |
assign peoa = eoa ; |
assign ploa = loa ; |
assign paddrx = addrx ; |
assign paddry = addry ; |
assign prst_n = rst_n ; |
|
initial $sdf_annotate("../syn/file/router.sdf", RT); |
|
endmodule |
async_sdm_noc/trunk/sdm/tb/rtwrapper.v
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: async_sdm_noc/trunk/sdm/tb/node_top.v
===================================================================
--- async_sdm_noc/trunk/sdm/tb/node_top.v (nonexistent)
+++ async_sdm_noc/trunk/sdm/tb/node_top.v (revision 37)
@@ -0,0 +1,117 @@
+/*
+ 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 network node including a router, a NI and a processing element.
+
+ History:
+ 03/03/2011 Initial version.
+ 30/05/2011 Clean up for opensource.
+
+*/
+
+// the router structure definitions
+`include "define.v"
+
+module node_top(/*AUTOARG*/
+ // Outputs
+ so0, so1, so2, so3, wo0, wo1, wo2, wo3, no0, no1, no2, no3, eo0,
+ eo1, eo2, eo3, sia, wia, nia, eia, so4, wo4, no4, eo4,
+ // Inputs
+ si0, si1, si2, si3, wi0, wi1, wi2, wi3, ni0, ni1, ni2, ni3, ei0,
+ ei1, ei2, ei3, si4, wi4, ni4, ei4, soa, woa, noa, eoa, rst_n
+ );
+ parameter DW = 32;
+ parameter VCN = 1;
+ parameter x = 0;
+ parameter y = 0;
+ parameter SCN = DW/2;
+
+ input [VCN*SCN-1:0] si0, si1, si2, si3;
+ input [VCN*SCN-1:0] wi0, wi1, wi2, wi3;
+ input [VCN*SCN-1:0] ni0, ni1, ni2, ni3;
+ input [VCN*SCN-1:0] ei0, ei1, ei2, ei3;
+ output [VCN*SCN-1:0] so0, so1, so2, so3;
+ output [VCN*SCN-1:0] wo0, wo1, wo2, wo3;
+ output [VCN*SCN-1:0] no0, no1, no2, no3;
+ output [VCN*SCN-1:0] eo0, eo1, eo2, eo3;
+ wire [VCN*SCN-1:0] li0, li1, li2, li3;
+ wire [VCN*SCN-1:0] lo0, lo1, lo2, lo3;
+`ifdef ENABLE_CHANNEL_SLICING
+ input [VCN*SCN-1:0] si4, wi4, ni4, ei4;
+ output [VCN*SCN-1:0] sia, wia, nia, eia;
+ output [VCN*SCN-1:0] so4, wo4, no4, eo4;
+ input [VCN*SCN-1:0] soa, woa, noa, eoa;
+ wire [VCN*SCN-1:0] li4, lia, lo4, loa;
+`else
+ input [VCN-1:0] si4, wi4, ni4, ei4;
+ output [VCN-1:0] sia, wia, nia, eia;
+ output [VCN-1:0] so4, wo4, no4, eo4;
+ input [VCN-1:0] soa, woa, noa, eoa;
+ wire [VCN-1:0] li4, lia, lo4, loa;
+`endif // !`ifdef ENABLE_CHANNEL_SLICING
+
+ input rst_n;
+
+
+ // the network node
+ NetNode #(.DW(DW), .VCN(VCN), .x(x), .y(y))
+ Node (
+ .dia ( lia ),
+ .do4 ( lo4 ),
+ .doa ( loa ),
+ .di4 ( li4 ),
+ .do0 ( lo0 ),
+ .do1 ( lo1 ),
+ .do2 ( lo2 ),
+ .do3 ( lo3 ),
+ .di0 ( li0 ),
+ .di1 ( li1 ),
+ .di2 ( li2 ),
+ .di3 ( li3 ),
+ .rst_n ( rst_n )
+ );
+
+
+ // router wrapper
+ router_hdl #(.DW(DW), .VCN(VCN))
+ RTN (
+ .so0(so0), .so1(so1), .so2(so2), .so3(so3), .so4(so4), .soa(soa),
+ .wo0(wo0), .wo1(wo1), .wo2(wo2), .wo3(wo3), .wo4(wo4), .woa(woa),
+ .no0(no0), .no1(no1), .no2(no2), .no3(no3), .no4(no4), .noa(noa),
+ .eo0(eo0), .eo1(eo1), .eo2(eo2), .eo3(eo3), .eo4(eo4), .eoa(eoa),
+ .lo0(lo0), .lo1(lo1), .lo2(lo2), .lo3(lo3), .lo4(lo4), .loa(loa),
+ .si0(si0), .si1(si1), .si2(si2), .si3(si3), .si4(si4), .sia(sia),
+ .wi0(wi0), .wi1(wi1), .wi2(wi2), .wi3(wi3), .wi4(wi4), .wia(wia),
+ .ni0(ni0), .ni1(ni1), .ni2(ni2), .ni3(ni3), .ni4(ni4), .nia(nia),
+ .ei0(ei0), .ei1(ei1), .ei2(ei2), .ei3(ei3), .ei4(ei4), .eia(eia),
+ .li0(li0), .li1(li1), .li2(li2), .li3(li3), .li4(li4), .lia(lia),
+ .addrx (b2chain(x)),
+ .addry (b2chain(y)),
+ .rst_n (rst_n)
+ );
+
+
+ // binary to 1-of-4 (Chain) converter
+ function [7:0] b2chain;
+ input [3:0] data;
+ begin
+ b2chain[0] = (data[1:0] == 2'b00);
+ b2chain[1] = (data[1:0] == 2'b01);
+ b2chain[2] = (data[1:0] == 2'b10);
+ b2chain[3] = (data[1:0] == 2'b11);
+ b2chain[4] = (data[3:2] == 2'b00);
+ b2chain[5] = (data[3:2] == 2'b01);
+ b2chain[6] = (data[3:2] == 2'b10);
+ b2chain[7] = (data[3:2] == 2'b11);
+ end
+ endfunction
+
+endmodule // node_top
Index: async_sdm_noc/trunk/sdm/tb/ni.h
===================================================================
--- async_sdm_noc/trunk/sdm/tb/ni.h (nonexistent)
+++ async_sdm_noc/trunk/sdm/tb/ni.h (revision 37)
@@ -0,0 +1,59 @@
+/*
+ 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 SystemC network adapter/interface for NoC simulation.
+
+ History:
+ 20/08/2008 Initial version.
+ 30/09/2010 Use template style packet definition.
+ 16/10/2010 Support SDM.
+ 30/05/2011 CLean up for opensource.
+
+*/
+
+#ifndef NETWORK_ADAPTER_H_
+#define NETWORK_ADAPTER_H_
+
+#include "define.h"
+#include
+
+SC_MODULE(Network_Adapter)
+{
+
+public:
+ SC_HAS_PROCESS(Network_Adapter);
+ Network_Adapter(
+ sc_module_name name // module name
+ ,unsigned int x // location x
+ ,unsigned int y // location y
+ );
+ ~Network_Adapter();
+
+ // interface with processor
+ sc_port > frame_in; // frame for transmission
+ sc_port > frame_out; // frame for receiving
+
+ // interface with router
+ sc_port > IP [SubChN]; // input port from IO driver
+ sc_port > OP [SubChN]; // output port to IO driver
+
+private:
+ unsigned int loc_x,loc_y; // location information
+
+ // functional thread
+ void ibuffer_thread(unsigned int); // input buffer respond thread
+ void obuffer_thread(unsigned int); // output buffer respond thread
+
+ // other functions
+ bool check_frame(const FRAME& frame); // check the correctness of frame received
+};
+
+#endif /*NETWORK_ADAPTER_H_*/
Index: async_sdm_noc/trunk/sdm/tb/netnode.cpp
===================================================================
--- async_sdm_noc/trunk/sdm/tb/netnode.cpp (nonexistent)
+++ async_sdm_noc/trunk/sdm/tb/netnode.cpp (revision 37)
@@ -0,0 +1,23 @@
+/*
+ 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 module of network node including the processing element and the network interface.
+ Currently the transmission FIFO is 500 frame deep.
+
+ History:
+ 26/02/2011 Initial version.
+
+*/
+
+#include "netnode.h"
+
+NCSC_MODULE_EXPORT(NetNode)
+
Index: async_sdm_noc/trunk/sdm/src/im_alloc.v
===================================================================
--- async_sdm_noc/trunk/sdm/src/im_alloc.v (revision 36)
+++ async_sdm_noc/trunk/sdm/src/im_alloc.v (revision 37)
@@ -90,7 +90,7 @@
`else
assign IPr[i][j] = |IPrm[i][j];
for(k=0; k
+#
+
+# make sure the LDVHOME environment is ready for NC-Simulator, IUS/LDV, Cadence
+export NCSC_GCC=${LDVHOME}/tools/systemc/gcc/bin/g++
+
+CXXFLAG="-c -g -Wall -I../../common/tb -I../tb -I../"
+
+# remove the files from last run
+rm -fr INCA_libs
+rm *.o
+rm *.so
+
+# compile verilog files
+# cell library
+ncvlog -nowarn RECOMP ../../lib/NangateOpenCellLibrary_typical_conditional.v
+# synthesized design
+ncvlog ../syn/file/router_syn.v
+# other verilog test bench files
+ncvlog -incdir ../ ../../common/tb/anaproc.v
+ncvlog -sv -incdir ../ ../tb/rtwrapper.v
+ncvlog -incdir ../ ../tb/netnode.v
+ncvlog -sv -incdir ../ ../tb/noc_top.v
+ncvlog -sv -incdir ../ ../tb/node_top.v
+ncvlog ../tb/noctb.v
+
+#compile SystemC files
+ncsc -compiler $NCSC_GCC -cflags "${CXXFLAG}" ../../common/tb/sim_ana.cpp
+ncsc -compiler $NCSC_GCC -cflags "${CXXFLAG}" ../../common/tb/anaproc.cpp
+ncsc -compiler $NCSC_GCC -cflags "${CXXFLAG}" ../tb/netnode.cpp
+ncsc -compiler $NCSC_GCC -cflags "${CXXFLAG}" ../tb/ni.cpp
+ncsc -compiler $NCSC_GCC -cflags "${CXXFLAG}" ../tb/rtdriver.cpp
+
+# build the run time link library
+${NCSC_GCC} -Wl -shared -o sysc.so -L${CDS_LNX86_ROOT}/ldv_2009_sc/tools/lib \
+ sim_ana.o anaproc.o netnode.o ni.o rtdriver.o \
+ ${CDS_LNX86_ROOT}/ldv_2009_sc/tools/systemc/lib/gnu/libncscCoSim_sh.so \
+ ${CDS_LNX86_ROOT}/ldv_2009_sc/tools/systemc/lib/gnu/libncscCoroutines_sh.so \
+ ${CDS_LNX86_ROOT}/ldv_2009_sc/tools/systemc/lib/gnu/libsystemc_sh.so
+
+# elaborate the simulation
+ncelab -timescale 1ns/1ps -access +rwc -loadsc sysc.so worklib.noctb
+
async_sdm_noc/trunk/sdm/sim/compile.sh
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: async_sdm_noc/trunk/sdm/syn/script/constraint.tcl
===================================================================
--- async_sdm_noc/trunk/sdm/syn/script/constraint.tcl (revision 36)
+++ async_sdm_noc/trunk/sdm/syn/script/constraint.tcl (revision 37)
@@ -41,7 +41,7 @@
# the delay cell in the lookahead pipeline
# It is not a problem to get errors here if ENABLE_LOOKAHEAD is not defined.
foreach_in_collection celln [get_references -hierarchical outp_buf_*] {
- set_disable_timing [get_object_name $celln]/DLY/U -from A -to Z
+ set_disable_timing [get_object_name $celln]/*DLY/U -from A -to Z
}
# set some timing path ending points
@@ -61,8 +61,8 @@
# set the timing constraints for data paths and ack paths
# For better speed performance, please tune these delay and factors according different cell libraries
-set DATA_dly 5
-set ACK_dly 8
+set DATA_dly 1.0
+set ACK_dly 1.6
set_max_delay [expr ${DATA_dly} * 1.00] -from ${DPA} -to ${DPD} -group G_DATA
set_max_delay [expr ${ACK_dly} * 1.00] -from ${DPA} -to ${DPA} -group G_ACK
@@ -81,4 +81,4 @@
set_max_area 0
# timing path disabled by user constraints
-suppress_message TIM-175
\ No newline at end of file
+suppress_message TIM-175
/async_sdm_noc/trunk/sdm/syn/script/compile.tcl
12,7 → 12,7
# currently using the Nangate 45nm cell lib. |
# |
# History: |
# 26/05/2009 Initial version. <wsong83@gmail.com> |
# 31/05/2009 Initial version. <wsong83@gmail.com> |
|
set rm_top router |
set rm_para "VCN=>1, DW=>8, IPD=>1, OPD=>1" |
36,6 → 36,7
|
# elaborate the design |
elaborate ${rm_top} -parameters ${rm_para} |
rename_design ${current_design} router |
|
link |
|
58,7 → 59,6
|
write -format verilog -hierarchy -out file/${current_design}_syn.v $current_design |
write_sdf -significant_digits 5 file/${current_design}.sdf |
write_sdc file/${current_design}.sdc |
|
report_constraints -verbose |
|
/async_sdm_noc/trunk/TODO
0,0 → 1,9
01/06/2011 Urgent Clean up the VC router |
01/06/2011 Urgent Provide better documents |
01/06/2011 Support other routing algorithms |
01/06/2011 Long time Support QoS ?? (necessary?) who needs it pls contact me |
01/06/2011 Keep channel slicing inside routers |
01/06/2011 Provide network interface |
01/06/2011 Lookahead routing |
01/06/2011 Support variable number of ports |
01/06/2011 Unify local port by serialization/parallelization |
/async_sdm_noc/trunk/common/tb/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 |
/async_sdm_noc/trunk/common/tb/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); |
|
/async_sdm_noc/trunk/common/tb/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 |
|
/async_sdm_noc/trunk/common/tb/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; |
} |
|
/async_sdm_noc/trunk/common/tb/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 |
/async_sdm_noc/trunk/common/tb/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_ */ |
/async_sdm_noc/trunk/common/tb/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 |
|
/async_sdm_noc/trunk/common/tb/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 |
/async_sdm_noc/trunk/common/tb/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 |
/async_sdm_noc/trunk/common/src/cell_lib.v
16,7 → 16,7
05/05/2009 Initial version. <wsong83@gmail.com> |
20/05/2011 Change to general verilog description for opensource. |
The Nangate cell library is used. <wsong83@gmail.com> |
|
01/06/2011 The bugs in the C2 and C2P1 gates are fixed. <wsong83@gmail.com> |
*/ |
|
// General 2-input C-element |
30,7 → 30,7
nand U1 (m[0], a0, a1); |
nand U2 (m[1], a0, q); |
nand U3 (m[2], a1, q); |
assign q = &m; |
assign q = ~&m; |
|
endmodule |
|
46,7 → 46,7
nand U1 (m[0], a, d); |
nand U2 (m[1], d, q); |
nand U3 (m[2], a, q); |
assign q = &m; |
assign q = ~&m; |
|
endmodule |
|
105,7 → 105,7
nand U1 (m[0], a0, a1, b); |
nand U2 (m[1], a0, q); |
nand U3 (m[2], a1, q); |
assign q = &m; |
assign q = ~&m; |
|
endmodule |
|
/async_sdm_noc/trunk/README
0,0 → 1,103
|
Asynchronous Spatial Division Multiplexing Router for On-Chip Networks |
|
Version: 0.1 |
|
On-chip networks or networks-on-chip (NoCs) are the on-chip communication fabric for |
current and future multiprocessor SoCs (MPSoCs) and chip multiprocessors (CMPs). |
Compared with synchronous NoCs, asynchronous NoCs have following benefits: |
* Tolerance to all kinds of delay variations caused by process, power and temperature |
variations. |
* Low transmission latency. |
* Zero dynamic power when idle. |
* Unified sync/async interface and easy clock domain integration. |
|
Most NoCs use the wormhole flow control method. Many complex flow control methods are |
built upon the wormhole method, such as virtual channel (VC), TDMA, and SDM. VC is the |
most utilized flow control in both sync and async NoCs. However, it is found VC |
compromises the throughput performance of asynchronous NoCs. This project provides a new |
asynchronous router structure which use SDM rather than VC. It has been shown that SDM |
achieve better throughput than VC in the same router configuration. |
|
This project provide a reconfigurable asynchronous SDM router which can be configured |
into a basic wormhole router or an SDM router with multiple virtual circuits in every |
direction. |
|
Features: |
* 5-port router for mesh network (0 south, 1 west, 2 north, 3 east, 4 local) |
* The dimension order routing (XY routing) |
* Available flow control methods: wormhole, SDM |
* Reconfigurable number of virtual circuits, buffer size, data width |
* Fully synthesizable router implementation |
* SystemC testbench provided |
|
Languages: |
* Routers are written in synthesizable SystemVerilog |
* Test benches are provided by SystemC |
|
Software requirements: |
* The open source Nangate 45nm cell library |
* Synopsys Design Compiler (Synthesis) |
* Cadence IUS -- NC Simulator (for SystemC/Verilog co-simulation) |
|
File structure: |
* common files needed for both SDM and VC routers |
\- script synthesis scripts for all routers |
|- src HDL for all routers |
\- tb test bench files for all routers |
* doc documents |
* lib minimal Nangate 45nm cell lib |
* sdm SDM/wormhole router design |
\- define.v HDL configuration file |
|- define.h test bench configuration |
|- sim simulation run dir |
|- src HDL |
|- syn synthesis run dir |
\- script synthesis script |
\- tb test bench |
* vc VC router (ongoing) |
|
How to run: |
* to synthesize a router |
1. set up your design compiler enviornment and your cell library. |
2. modify the "define.v" configuration file for the strcture your want. |
currently including: |
ENABLE_CLOS use the 2-stage Clos switch instead of crossbar |
ENABLE_CRRD use the CRRD dispatching algorithm for the Clos |
ENABLE_MRMA use the multi-resource matching arbiter instead of MNMA |
ENABLE_CHANNEL_SLICING use channel slicing |
ENABLE_LOOKAHEAD use the lookahead pipelines |
ENABLE_EOF router use eof bit to indicate end-of-frame |
3. modify the "compile.tcl" scription for the design parameters. |
currently including: |
VCN number of virtual circuits |
DW the data width of a single virtual circuit |
IPD the depth of input buffers |
OPD the depth of putput buffers |
4. if another cell lib is used, change "cell_lib.v" in common\src and other related |
files. (very likely you need to email me for further instructions :-) ) |
5. modify the "tech.tcl" in common/script for your cell library. |
6. run the synthesis at [sdm/vc]/syn |
dc_shell -f script/compile.tcl |
7. the synthesized netlist is inside [sdm/vc]/syn/file/ |
|
* to run post-synthesis simulation |
1. check the netlists in [sdm/vc]/syn/file/ |
2. modify the testbench configuration "define.h" according to your requirements. |
3. make sure your NC-Simulator is installed alright (proper SystemC support). |
4. run the compilation at [sdm/vc]/sim |
compile.tcl |
5. run the simulation at [sdm/vc]/sim |
ncsim -tcl noctb |
6. the simulation output files are *.ana at [sdm/vc]/sim |
"throughput.ana": |
{simulation time in ps} TAB {throughput in bytes} |
"delay.ana": |
{simulation time in ps} TAB {avg. frame latency} TAB {avg. path setup delay} |
|
For any questions and bug reports, |
please email to Wei Song from wsong83@gmail.com |
|
Wei Song |
01/06/2011 |
|
async_sdm_noc/trunk
Property changes :
Modified: svn:mergeinfo
## -0,0 +0,1 ##
Merged /async_sdm_noc/branches/init:r28-36